All checks were successful
构建并部署前端到测试环境 / build-and-deploy (push) Successful in 23m46s
- 套餐历史展示沉默期状态、截止日期、累计延期与调整审批中,可延期时显示延期入口 - 新增延期页:资格、档位与自定义天数试算、支付方式、下单(request_id 幂等) - 支付宝走现有支付页;微信为链接时在微信外直接跳转,否则展示二维码与复制链接 - 新增我的延期订单列表与详情、沉默期记录,沉默期错误码转客户提示
139 lines
4.8 KiB
JavaScript
139 lines
4.8 KiB
JavaScript
import request from '@/utils/request.js';
|
|
import { useAssetStore } from '@/store/asset.js';
|
|
import { useUserStore } from '@/store/user.js';
|
|
import { getSessionContext, isCurrentSession } from '@/utils/session-context.js';
|
|
|
|
let assetInfoRequestId = 0;
|
|
|
|
export const normalizeAssetInfo = (data = {}) => {
|
|
// 保护期已下线:不向展示和业务判断透传废弃字段,兼容 none 或字段缺失。
|
|
const { device_protect_status, ...info } = data;
|
|
return {
|
|
...info,
|
|
allowed_payment_methods: Array.isArray(data.allowed_payment_methods)
|
|
? data.allowed_payment_methods
|
|
: [],
|
|
real_name_status: data.real_name_status === undefined || data.real_name_status === null
|
|
? data.real_name_status
|
|
: Number(data.real_name_status),
|
|
realname_required: data.realname_required === undefined || data.realname_required === null
|
|
? data.realname_required
|
|
: data.realname_required === true || data.realname_required === 1,
|
|
days_until_final_expiry: data.days_until_final_expiry === null || data.days_until_final_expiry === undefined
|
|
? data.days_until_final_expiry
|
|
: Number(data.days_until_final_expiry),
|
|
is_expiring: data.is_expiring === undefined || data.is_expiring === null
|
|
? data.is_expiring
|
|
: data.is_expiring === true || data.is_expiring === 1
|
|
};
|
|
};
|
|
|
|
const toBool = (value) => value === true || value === 1 || value === 'true';
|
|
|
|
// 沉默期对象:总开关关闭或不适用时后端不返回,保持为 null。
|
|
export const normalizePackageSilence = (silence) => {
|
|
if (!silence || typeof silence !== 'object') return null;
|
|
return {
|
|
...silence,
|
|
extendable: toBool(silence.extendable),
|
|
silence_adjust_pending: toBool(silence.silence_adjust_pending),
|
|
silence_extended_days: Number(silence.silence_extended_days) || 0
|
|
};
|
|
};
|
|
|
|
const normalizePackageHistoryNode = (node = {}) => ({
|
|
...node,
|
|
silence: normalizePackageSilence(node.silence),
|
|
children: Array.isArray(node.children)
|
|
? node.children.filter(child => Number(child?.status) !== 4).map(normalizePackageHistoryNode)
|
|
: [],
|
|
expand_by_default: node.expand_by_default === true || node.expand_by_default === 1
|
|
});
|
|
|
|
export const normalizeAssetPackageHistory = (data = {}) => ({
|
|
...data,
|
|
items: Array.isArray(data.items)
|
|
? data.items.filter(node => Number(node?.status) !== 4).map(normalizePackageHistoryNode)
|
|
: [],
|
|
page: Number(data.page),
|
|
size: Number(data.size),
|
|
total: Number(data.total)
|
|
});
|
|
|
|
export const isAssetRealNameCompleted = (assetInfo = {}) => {
|
|
if (assetInfo.asset_type === 'device') {
|
|
return (assetInfo.cards || []).some((card) => Number(card?.real_name_status) === 1);
|
|
}
|
|
|
|
return Number(assetInfo.real_name_status) === 1;
|
|
};
|
|
|
|
export const hasActiveOrPendingPackage = async (identifier) => {
|
|
const [pendingData, activeData] = await Promise.all([
|
|
assetApi.getPackageHistory(identifier, 1, 1, { status: 0 }),
|
|
assetApi.getPackageHistory(identifier, 1, 1, { status: 1 })
|
|
]);
|
|
|
|
return [pendingData, activeData].some(data => Array.isArray(data?.items) && data.items.length > 0);
|
|
};
|
|
|
|
export const assetApi = {
|
|
getInfo(identifier) {
|
|
identifier = typeof identifier === 'string' ? identifier.trim() : '';
|
|
if (!identifier) {
|
|
return Promise.reject({ msg: '缺少资产标识,请重新输入或扫码登录' });
|
|
}
|
|
const context = getSessionContext();
|
|
const userStore = useUserStore();
|
|
if (userStore.state.loginPending || !context.token) {
|
|
return Promise.reject({ msg: '登录和微信配置尚未完成,请稍后重试' });
|
|
}
|
|
const phoneRevision = userStore.state.phoneRevision;
|
|
const requestId = identifier === context.identifier ? ++assetInfoRequestId : null;
|
|
return request({
|
|
url: '/api/c/v1/asset/info',
|
|
method: 'GET',
|
|
data: { identifier }
|
|
}).then((response) => {
|
|
const data = normalizeAssetInfo(response);
|
|
if (identifier === context.identifier && isCurrentSession(context)) {
|
|
const assetStore = useAssetStore();
|
|
// 替换整个快照,不合并旧轮询开关;迟到的旧请求不得覆盖新状态。
|
|
if (requestId === assetInfoRequestId) assetStore.setAssetInfo(data);
|
|
assetStore.receiveExpiryReminder(context, data.expiry_reminder);
|
|
if (phoneRevision === userStore.state.phoneRevision && typeof data.bound_phone === 'string') {
|
|
userStore.setCustomerPhone(data.bound_phone);
|
|
}
|
|
}
|
|
return data;
|
|
});
|
|
},
|
|
|
|
getPackageHistory(identifier, page, page_size, params = {}) {
|
|
return request({
|
|
url: '/api/c/v1/asset/package-history',
|
|
method: 'GET',
|
|
data: { identifier, page, page_size, ...params }
|
|
}).then(normalizeAssetPackageHistory);
|
|
},
|
|
|
|
getPackages(identifier, packageType = '') {
|
|
return request({
|
|
url: '/api/c/v1/asset/packages',
|
|
method: 'GET',
|
|
data: {
|
|
identifier,
|
|
...(packageType ? { package_type: packageType } : {})
|
|
}
|
|
});
|
|
},
|
|
|
|
refresh(identifier) {
|
|
return request({
|
|
url: '/api/c/v1/asset/refresh',
|
|
method: 'POST',
|
|
data: { identifier }
|
|
});
|
|
}
|
|
};
|