diff --git a/docs/new-media.md b/docs/new-media.md
index 1f9c154730..23d50eb13c 100644
--- a/docs/new-media.md
+++ b/docs/new-media.md
@@ -872,6 +872,28 @@ area 分区选项
+## 丁香园
+
+### 新冠疫苗实时动态
+
+
+
+查看北京市的新冠疫苗接种点,路由为 `/dxy/vaccine/北京`;
+
+查看北京市朝阳区的新冠疫苗接种点,路由为 `/dxy/vaccine/北京/北京/朝阳区`;
+
+查看湖北省武汉市的新冠疫苗接种点,路由为 `/dxy/vaccine/湖北/武汉`;
+
+查看湖北省武汉市武昌区的新冠疫苗接种点,路由为 `/dxy/vaccine/湖北/武汉/武昌区`。
+
+::: tip 提示
+
+若参数为空,则返回全国所有新冠疫苗接种点。
+
+:::
+
+
+
## 懂球帝
::: tip 提示
diff --git a/lib/router.js b/lib/router.js
index f8cbea1305..2f5546092e 100644
--- a/lib/router.js
+++ b/lib/router.js
@@ -3901,4 +3901,7 @@ router.get('/growincity/news/:id?', require('./routes/growincity/news'));
// Thrillist
router.get('/thrillist/:tag?', require('./routes/thrillist/index'));
+// 丁香园
+router.get('/dxy/vaccine/:province?/:city?/:location?', require('./routes/dxy/vaccine'));
+
module.exports = router;
diff --git a/lib/routes/dxy/vaccine.js b/lib/routes/dxy/vaccine.js
new file mode 100644
index 0000000000..d0751a8d4e
--- /dev/null
+++ b/lib/routes/dxy/vaccine.js
@@ -0,0 +1,101 @@
+const got = require('@/utils/got');
+
+module.exports = async (ctx) => {
+ const province = ctx.params.province || '';
+ const city = ctx.params.city || '';
+ const location = ctx.params.location || '';
+ const fullLocation = `${province ? `${province}${city ? `/${city}${location ? `/${location}` : ''}` : ''}` : ''}`;
+
+ const rootUrl = 'https://mama.dxy.com';
+ const currentUrl = `${rootUrl}/client/vaccine/new-crown-vaccine`;
+ const apiUrl = `${rootUrl}/api/vaccine/client/vaccination-point/all`;
+
+ const apiResponse = await got({
+ method: 'get',
+ url: apiUrl,
+ });
+
+ const response = await got({
+ method: 'get',
+ url: apiResponse.data.results.fileUrl,
+ });
+
+ const allPoints = [],
+ allLocations = {},
+ allLocationIds = {},
+ pointDataArray = response.data.results.pointData;
+
+ for (const data of pointDataArray) {
+ allLocations[data.locationName] = data.locationId;
+ allLocationIds[data.locationId] = data.locationName;
+ if (data.points) {
+ allPoints.push(...data.points);
+ } else {
+ pointDataArray.push(...data.pointData);
+ }
+ }
+
+ const list = allPoints.map((item) => {
+ const locationId = item.locationId;
+ const province = locationId - (locationId % 10000);
+ const city = locationId - (locationId % 100);
+
+ return {
+ title: `${allLocationIds[province]}/${allLocationIds.hasOwnProperty(city) ? `${allLocationIds[city]}/` : `${allLocationIds[province]}/`}${allLocationIds[locationId]}`,
+ link: item.contentUrl,
+ pubDate: new Date(item.modifyDate).toUTCString(),
+ };
+ });
+
+ const items = await Promise.all(
+ list
+ .filter((item) => {
+ if (fullLocation !== '') {
+ const locationSplit = item.title.split('/');
+ const fullLocationSplit = fullLocation.split('/');
+
+ for (let index = 0; index < fullLocationSplit.length; index++) {
+ if (locationSplit[index] !== fullLocationSplit[index]) {
+ return false;
+ }
+ }
+ }
+ return true;
+ })
+ .map(
+ async (item) =>
+ await ctx.cache.tryGet(item.link, async () => {
+ const detailResponse = await got({
+ method: 'get',
+ url: item.link,
+ });
+ const result = detailResponse.data.results;
+
+ const description =
+ `
${result.point.pointName}
` +
+ '' +
+ `- 户籍限制:${result.point.registerLimit}
` +
+ `- 服务限制:${result.point.serviceTag}
` +
+ `- 服务时间:${result.detail.serviceTime}
` +
+ `- 地址:${result.point.address}
` +
+ `- 电话:${result.point.phoneNo}
` +
+ `- 接种人群:${result.detail.targetPeople}
` +
+ `- 接种所需材料:${result.detail.materials}
` +
+ `- 预约步骤:${result.detail.reserveSteps}
` +
+ '
';
+
+ item.description = description;
+ item.title = `${result.point.pointName}(${item.title})`;
+ item.link = `${rootUrl}/client/vaccine/vaccination-point?pointId=${result.point.id}`;
+
+ return item;
+ })
+ )
+ );
+
+ ctx.state.data = {
+ title: `新冠疫苗接种点查询${fullLocation ? `(${fullLocation})` : ''} - 丁香园`,
+ link: currentUrl,
+ item: items,
+ };
+};