feat(route/mi): refactor crowdfunding with ofetch and art-template (#16974)
* feat(route/mi): refactor crowdfunding with ofetch and art-template * fix: remove unnecessary diff * refactor: use flatMap ---------
This commit is contained in:
parent
5747505a12
commit
5a653b6ef4
|
|
@ -1,37 +1,58 @@
|
|||
import { Route } from '@/types';
|
||||
import got from '@/utils/got';
|
||||
import { Data, DataItem, Route, ViewType } from '@/types';
|
||||
import { CrowdfundingDetailInfo, CrowdfundingList } from './types';
|
||||
import utils from './utils';
|
||||
|
||||
export const route: Route = {
|
||||
path: '/crowdfunding',
|
||||
categories: ['shopping'],
|
||||
example: '/mi/crowdfunding',
|
||||
name: '小米众筹',
|
||||
maintainers: ['DIYgod'],
|
||||
maintainers: ['DIYgod', 'nuomi1'],
|
||||
handler,
|
||||
features: {
|
||||
requireConfig: false,
|
||||
requirePuppeteer: false,
|
||||
antiCrawler: false,
|
||||
supportRadar: true,
|
||||
supportBT: false,
|
||||
supportPodcast: false,
|
||||
supportScihub: false,
|
||||
},
|
||||
radar: [
|
||||
{
|
||||
source: ['m.mi.com/crowdfunding/home'],
|
||||
target: '/crowdfunding',
|
||||
},
|
||||
],
|
||||
view: ViewType.Notifications,
|
||||
};
|
||||
|
||||
const getDetails = async (list: CrowdfundingList[]) => {
|
||||
const result: Promise<CrowdfundingDetailInfo>[] = list.flatMap((section) => section.items.map((item) => utils.getCrowdfundingItem(item)));
|
||||
return await Promise.all(result);
|
||||
};
|
||||
|
||||
const getDataItem = (item: CrowdfundingDetailInfo) =>
|
||||
({
|
||||
title: item.project_name,
|
||||
description: utils.renderCrowdfunding(item),
|
||||
link: `https://m.mi.com/crowdfunding/proddetail/${item.project_id}`,
|
||||
image: item.big_image,
|
||||
language: 'zh-cn',
|
||||
}) as DataItem;
|
||||
|
||||
async function handler() {
|
||||
const response = await got({
|
||||
method: 'post',
|
||||
url: 'http://api.m.mi.com/v1/microwd/home',
|
||||
headers: {
|
||||
'Mishop-Client-Id': '180100031055',
|
||||
'User-Agent': 'MiShop/4.3.68 (iPhone; iOS 12.0.1; Scale/3.00)',
|
||||
'IOS-App-Version': '4.3.68',
|
||||
'IOS-Version': 'system=12.0.1&device=iPhone10,3',
|
||||
},
|
||||
});
|
||||
const list = response.data.data.list.flatMap((a) => a.items || []);
|
||||
const list = await utils.getCrowdfundingList();
|
||||
const details = await getDetails(list);
|
||||
|
||||
const items: DataItem[] = details.map((item) => getDataItem(item));
|
||||
|
||||
return {
|
||||
title: '小米众筹',
|
||||
link: '',
|
||||
link: 'https://m.mi.com/crowdfunding/home',
|
||||
item: items,
|
||||
allowEmpty: true,
|
||||
item:
|
||||
list &&
|
||||
list.map((item) => ({
|
||||
title: item.product_name,
|
||||
description: `<img src="${item.img_url}"><br>价格:${item.product_price}元`,
|
||||
})),
|
||||
};
|
||||
image: 'https://m.mi.com/static/img/icons/apple-touch-icon-152x152.png',
|
||||
language: 'zh-cn',
|
||||
} as Data;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,28 @@
|
|||
<img src="{{ big_image }}">
|
||||
<br>
|
||||
{{ project_name }}
|
||||
<br>
|
||||
{{ project_desc }}
|
||||
<br>
|
||||
众筹价:{{ price }} 元,建议零售价:{{ product_market_price }} 元
|
||||
<br>
|
||||
众筹开始:{{ start_time_desc }},众筹结束:{{ end_time_desc }}
|
||||
<br>
|
||||
物流:{{ send_info }}
|
||||
<br>
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>档位</th>
|
||||
<th>价格</th>
|
||||
<th>描述</th>
|
||||
</tr>
|
||||
{{ each support_list }}
|
||||
<tr>
|
||||
<td>{{ $value.name }}</td>
|
||||
<td>{{ $value.price }} 元</td>
|
||||
<td>{{ $value.support_desc }}</td>
|
||||
</tr>
|
||||
{{ /each }}
|
||||
</tbody>
|
||||
</table>
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
export interface DataResponse<Data> {
|
||||
data: Data;
|
||||
}
|
||||
|
||||
export interface CrowdfundingData {
|
||||
list: CrowdfundingList[];
|
||||
}
|
||||
|
||||
export interface CrowdfundingList {
|
||||
items: CrowdfundingItem[];
|
||||
}
|
||||
|
||||
export interface CrowdfundingItem {
|
||||
project_id: number;
|
||||
product_market_price: string;
|
||||
}
|
||||
|
||||
export interface CrowdfundingDetailData {
|
||||
crowd_funding_info: CrowdfundingDetailInfo;
|
||||
}
|
||||
|
||||
export interface CrowdfundingDetailInfo {
|
||||
big_image: string;
|
||||
end_time: number;
|
||||
end_time_desc: string; // injected
|
||||
price: string;
|
||||
product_market_price: string; // injected
|
||||
project_desc: string;
|
||||
project_id: number;
|
||||
project_name: string;
|
||||
start_time: number;
|
||||
start_time_desc: string; // injected
|
||||
support_list: CrowdfundingDetailSupportList[];
|
||||
}
|
||||
|
||||
export interface CrowdfundingDetailSupportList {
|
||||
name: string;
|
||||
price: string;
|
||||
support_desc: string;
|
||||
}
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
import { getCurrentPath } from '@/utils/helpers';
|
||||
const __dirname = getCurrentPath(import.meta.url);
|
||||
|
||||
import cache from '@/utils/cache';
|
||||
import ofetch from '@/utils/ofetch';
|
||||
import { art } from '@/utils/render';
|
||||
import dayjs from 'dayjs';
|
||||
import 'dayjs/locale/zh-cn';
|
||||
import localizedFormat from 'dayjs/plugin/localizedFormat';
|
||||
import timezone from 'dayjs/plugin/timezone';
|
||||
import utc from 'dayjs/plugin/utc';
|
||||
import path from 'path';
|
||||
import { CrowdfundingData, CrowdfundingDetailData, CrowdfundingDetailInfo, CrowdfundingItem, CrowdfundingList, DataResponse } from './types';
|
||||
|
||||
dayjs.extend(localizedFormat);
|
||||
dayjs.extend(timezone);
|
||||
dayjs.extend(utc);
|
||||
|
||||
/**
|
||||
* 获取众筹项目列表
|
||||
*
|
||||
* @returns {Promise<CrowdfundingList[]>} 众筹项目列表。
|
||||
*/
|
||||
export const getCrowdfundingList = async (): Promise<CrowdfundingList[]> => {
|
||||
const response = await ofetch<DataResponse<CrowdfundingData>>('https://m.mi.com/v1/crowd/crowd_home', {
|
||||
headers: {
|
||||
referrer: 'https://m.mi.com/',
|
||||
},
|
||||
method: 'POST',
|
||||
});
|
||||
return response.data.list;
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取众筹项目详情并缓存
|
||||
*
|
||||
* @param {CrowdfundingItem} item - 众筹项目。
|
||||
* @returns {Promise<CrowdfundingDetailInfo>} 众筹项目详情。
|
||||
*/
|
||||
export const getCrowdfundingItem = (item: CrowdfundingItem): Promise<CrowdfundingDetailInfo> =>
|
||||
cache.tryGet(`mi:crowdfunding:${item.project_id}`, async () => {
|
||||
const response = await ofetch<DataResponse<CrowdfundingDetailData>>('https://m.mi.com/v1/crowd/crowd_detail', {
|
||||
headers: {
|
||||
referrer: 'https://m.mi.com/crowdfunding/home',
|
||||
},
|
||||
method: 'POST',
|
||||
query: {
|
||||
project_id: item.project_id,
|
||||
},
|
||||
});
|
||||
// 建议零售价
|
||||
if (response.data.crowd_funding_info.product_market_price === undefined) {
|
||||
response.data.crowd_funding_info.product_market_price = item.product_market_price;
|
||||
}
|
||||
// 众筹开始
|
||||
if (response.data.crowd_funding_info.start_time_desc === undefined) {
|
||||
response.data.crowd_funding_info.start_time_desc = formatDate(response.data.crowd_funding_info.start_time);
|
||||
}
|
||||
// 众筹结束
|
||||
if (response.data.crowd_funding_info.end_time_desc === undefined) {
|
||||
response.data.crowd_funding_info.end_time_desc = formatDate(response.data.crowd_funding_info.end_time);
|
||||
}
|
||||
return response.data.crowd_funding_info;
|
||||
}) as Promise<CrowdfundingDetailInfo>;
|
||||
|
||||
/**
|
||||
* 渲染众筹项目模板
|
||||
*
|
||||
* @param {CrowdfundingDetailInfo} item - 众筹项目详情。
|
||||
* @returns {string} 渲染后的众筹项目模板字符串。
|
||||
*/
|
||||
export const renderCrowdfunding = (item: CrowdfundingDetailInfo): string => art(path.join(__dirname, 'templates/crowdfunding.art'), item);
|
||||
|
||||
const formatDate = (timestamp: number): string => dayjs.unix(timestamp).tz('Asia/Shanghai').locale('zh-cn').format('lll');
|
||||
|
||||
export default {
|
||||
getCrowdfundingList,
|
||||
getCrowdfundingItem,
|
||||
renderCrowdfunding,
|
||||
};
|
||||
Loading…
Reference in New Issue