页面优化
This commit is contained in:
+4
-16
@@ -56,26 +56,14 @@ App({
|
||||
bindPendingPromoter();
|
||||
}
|
||||
updateManager();
|
||||
//从后台切回前台时刷新一次未读红点(不使用定时轮询,避免请求堆积导致页面卡死)
|
||||
this.refreshUnread();
|
||||
// 切回前台的时间。Tab 页用它区分「从后台回来」和「切换 Tab」,避免每次 onShow 都打接口
|
||||
this.globalData.appShowAt = Date.now();
|
||||
},
|
||||
onHide: function () {},
|
||||
globalData: {
|
||||
unread: 0, //未读消息数(tabbar红点共享缓存)
|
||||
unreadFetchedAt: 0, //上次拉取未读数的时间,各 tabBar 实例共用,避免切 Tab 重复请求
|
||||
appShowAt: 0, //最近一次 App.onShow 的时间
|
||||
refreshDemandId: 0, //操作后需要刷新状态的需求ID(跨页面通知列表页)
|
||||
},
|
||||
|
||||
/**
|
||||
* 刷新当前 tab 页 tabbar 实例的红点(非tab页无tabbar实例,自动跳过)
|
||||
*/
|
||||
refreshUnread: function () {
|
||||
if (!wx.getStorageSync('token')) {
|
||||
return;
|
||||
}
|
||||
const page = getCurrentPages().pop();
|
||||
const tabBar = page && typeof page.getTabBar === 'function' ? page.getTabBar() : null;
|
||||
if (tabBar && typeof tabBar.refreshUnread === 'function') {
|
||||
tabBar.refreshUnread();
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
@@ -6,7 +6,25 @@
|
||||
* @Description: webp-image组件对t-image包裹了一层,主要实现图片裁剪、webp压缩功能
|
||||
* @FilePath: /tdesign-miniprogram-starter/components/webp-image/index.js
|
||||
*/
|
||||
const systemInfo = wx.getSystemInfoSync();
|
||||
let screenWidth = 375;
|
||||
let pixelRatio = 2;
|
||||
let screenReady = false;
|
||||
|
||||
function ensureScreen() {
|
||||
if (screenReady) {
|
||||
return;
|
||||
}
|
||||
screenReady = true;
|
||||
try {
|
||||
const info = wx.getWindowInfo();
|
||||
screenWidth = info.screenWidth || info.windowWidth || 375;
|
||||
pixelRatio = info.pixelRatio || 2;
|
||||
} catch (err) {
|
||||
screenWidth = 375;
|
||||
pixelRatio = 2;
|
||||
}
|
||||
}
|
||||
|
||||
Component({
|
||||
externalClasses: ['t-class', 't-class-load'],
|
||||
properties: {
|
||||
@@ -42,9 +60,14 @@ Component({
|
||||
data: {
|
||||
thumbHeight: 375,
|
||||
thumbWidth: 375,
|
||||
systemInfo,
|
||||
screenWidth: 375,
|
||||
pixelRatio: 2,
|
||||
},
|
||||
lifetimes: {
|
||||
attached() {
|
||||
ensureScreen();
|
||||
this.setData({ screenWidth, pixelRatio });
|
||||
},
|
||||
ready() {
|
||||
const { mode } = this.properties;
|
||||
// 获取容器的真实宽高,设置图片的裁剪宽度
|
||||
@@ -66,7 +89,8 @@ Component({
|
||||
},
|
||||
methods: {
|
||||
px2rpx(px) {
|
||||
return (750 / (systemInfo.screenWidth || 375)) * px;
|
||||
ensureScreen();
|
||||
return (750 / (screenWidth || 375)) * px;
|
||||
},
|
||||
getRect(selector) {
|
||||
return new Promise((resolve) => {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<wxs src="./utils.wxs" module="Utils" />
|
||||
<t-image
|
||||
t-class="J-image"
|
||||
src="{{Utils.getSrc({src, thumbWidth: thumbWidth || 0, thumbHeight: thumbHeight || 0, systemInfo, webp, mode})}}"
|
||||
class="J-image"
|
||||
src="{{Utils.getSrc({src, thumbWidth: thumbWidth || 0, thumbHeight: thumbHeight || 0, screenWidth, pixelRatio, webp, mode})}}"
|
||||
t-class="t-class"
|
||||
t-class-load="t-class-load"
|
||||
mode="{{ mode }}"
|
||||
|
||||
@@ -119,13 +119,11 @@ function getSrc(options) {
|
||||
return imageMogr(options.src, {
|
||||
width:
|
||||
options.mode !== 'heightFix'
|
||||
? rpx2px(options.thumbWidth, options.systemInfo.screenWidth) *
|
||||
options.systemInfo.pixelRatio
|
||||
? rpx2px(options.thumbWidth, options.screenWidth) * (options.pixelRatio || 2)
|
||||
: null,
|
||||
height:
|
||||
options.mode !== 'widthFix'
|
||||
? rpx2px(options.thumbHeight, options.systemInfo.screenWidth) *
|
||||
options.systemInfo.pixelRatio
|
||||
? rpx2px(options.thumbHeight, options.screenWidth) * (options.pixelRatio || 2)
|
||||
: null,
|
||||
format: options.webp ? 'webp' : null,
|
||||
});
|
||||
|
||||
@@ -9,16 +9,16 @@ Component({
|
||||
|
||||
lifetimes: {
|
||||
attached() {
|
||||
//先用 globalData 缓存渲染,避免切换 tab 时红点闪没,再拉取最新
|
||||
// 先用全局缓存渲染,避免切换 tab 时红点闪没。网络请求交给 show,并与其他实例共用节流
|
||||
const app = getApp();
|
||||
if (app && Number(app.globalData?.unread) > 0) {
|
||||
this.setData({ unread: Number(app.globalData.unread) });
|
||||
const unread = app && app.globalData ? Number(app.globalData.unread) || 0 : 0;
|
||||
if (unread > 0) {
|
||||
this.setData({ unread });
|
||||
}
|
||||
this.refreshUnread();
|
||||
},
|
||||
},
|
||||
|
||||
//所在 tab 页面显示时刷新(切换 tab、从其他页面返回均会触发)
|
||||
// 当前 tab 显示时刷新。30s 内各实例只发一次请求
|
||||
pageLifetimes: {
|
||||
show() {
|
||||
this.refreshUnread();
|
||||
@@ -48,35 +48,46 @@ Component({
|
||||
|
||||
/**
|
||||
* 从服务端拉取未读消息数
|
||||
* 未登录/请求失败时保持 0(不显示红点),不影响 tabbar 正常使用
|
||||
* 5s 内重复触发只发一次请求(app轮询/页面onShow/tabbar show 多处触发)
|
||||
* 未登录时不显示红点。节流记在 globalData,切换 Tab 新建的 tabBar 实例也会共用
|
||||
* 30s 内只发一次;消息页改未读数走 setUnread,不走这里
|
||||
*/
|
||||
refreshUnread(force = false) {
|
||||
if (!wx.getStorageSync('token')) {
|
||||
const app = getApp();
|
||||
const token = (wx.$util && wx.$util.getToken && wx.$util.getToken()) || '';
|
||||
if (!token) {
|
||||
this.setData({ unread: 0 });
|
||||
const app = getApp();
|
||||
if (app) app.globalData.unread = 0;
|
||||
if (app && app.globalData) {
|
||||
app.globalData.unread = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
const now = Date.now();
|
||||
if (!force && now - (this._lastFetchAt || 0) < 5000) {
|
||||
const last = app && app.globalData ? Number(app.globalData.unreadFetchedAt) || 0 : 0;
|
||||
if (!force && now - last < 30000) {
|
||||
if (app && app.globalData) {
|
||||
this.setData({ unread: Number(app.globalData.unread) || 0 });
|
||||
}
|
||||
return;
|
||||
}
|
||||
//上一次请求尚未结束时不再发起,避免请求堆积占满并发导致页面假死
|
||||
if (this._fetching) {
|
||||
if (app && app.globalData && app.globalData.unreadFetching) {
|
||||
return;
|
||||
}
|
||||
this._lastFetchAt = now;
|
||||
this._fetching = true;
|
||||
if (app && app.globalData) {
|
||||
app.globalData.unreadFetching = true;
|
||||
app.globalData.unreadFetchedAt = now;
|
||||
}
|
||||
const done = () => {
|
||||
this._fetching = false;
|
||||
if (app && app.globalData) {
|
||||
app.globalData.unreadFetching = false;
|
||||
}
|
||||
};
|
||||
fetchMessageUnreadCount().then((res) => {
|
||||
if (res.code == 1) {
|
||||
const unread = Number(res.data?.unread_count) || 0;
|
||||
this.setData({ unread });
|
||||
const app = getApp();
|
||||
if (app) app.globalData.unread = unread;
|
||||
if (app && app.globalData) {
|
||||
app.globalData.unread = unread;
|
||||
}
|
||||
}
|
||||
}).catch(() => {}).then(done, done);
|
||||
},
|
||||
@@ -88,7 +99,10 @@ Component({
|
||||
const unread = Number(count) || 0;
|
||||
this.setData({ unread });
|
||||
const app = getApp();
|
||||
if (app) app.globalData.unread = unread;
|
||||
if (app && app.globalData) {
|
||||
app.globalData.unread = unread;
|
||||
app.globalData.unreadFetchedAt = Date.now();
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
<t-cell title="工期" note="{{_calc.withUnit(demandInfo.limit_time, '天')}}" bordered hover />
|
||||
<t-cell title="联系方式" note="{{demandInfo.contactText}}" bordered hover />
|
||||
<view class="qrcode-row">
|
||||
<image class="qrcode-img" wx:if="{{demandInfo.demand_group_chat.qr_code && (demandInfo.isMy || demandInfo.isMyWin )}}" src="{{demandInfo.demand_group_chat.qr_code}}" data-index="{{0}}" data-images="{{[demandInfo.demand_group_chat.qr_code]}}" mode="widthFix" bind:tap="onImageView" show-menu-by-longpress="{{true}}" />
|
||||
<image class="qrcode-img" wx:if="{{demandInfo.demand_group_chat.qr_code && (demandInfo.isMy || demandInfo.isMyWin )}}" src="{{demandInfo.demand_group_chat.qr_code}}" data-index="{{0}}" data-images="{{[demandInfo.demand_group_chat.qr_code]}}" mode="widthFix" bind:tap="onImageView" show-menu-by-longpress="{{true}}"></image>
|
||||
</view>
|
||||
<!-- 任务内容 -->
|
||||
<t-collapse value="{{activeValues}}" bind:change="handleChange">
|
||||
@@ -59,7 +59,7 @@
|
||||
<view class="delivery-section">
|
||||
<view class="delivery-title">开发完成凭证截图</view>
|
||||
<view class="delivery-images">
|
||||
<image wx:for="{{_calc.getDelivery(demandInfo).images}}" wx:key="index" class="delivery-image" src="{{item.url}}" mode="aspectFill" data-index="{{index}}" data-images="{{_calc.getDelivery(demandInfo).images}}" bindtap="onDeliveryImagePreview" />
|
||||
<image wx:for="{{_calc.getDelivery(demandInfo).images}}" wx:key="index" class="delivery-image" src="{{item.url}}" mode="aspectFill" data-index="{{index}}" data-images="{{_calc.getDelivery(demandInfo).images}}" bindtap="onDeliveryImagePreview"></image>
|
||||
</view>
|
||||
<view class="delivery-title">交付附件</view>
|
||||
<view class="file-list">
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
{{item.expanded ? '收起' : '查看全文'}}
|
||||
</view>
|
||||
<view class="content-img-list">
|
||||
<image wx:for="{{item.images}}" wx:for-item="img" wx:for-index="imgIndex" wx:key="*this" class="content-img" mode="aspectFill" data-index="{{imgIndex}}" data-images="{{item.images}}" src="{{img}}" bind:tap="onImageView"></image>
|
||||
<image wx:for="{{item.images}}" wx:for-item="img" wx:for-index="imgIndex" wx:key="*this" class="content-img" mode="aspectFill" src="{{img}}" data-index="{{imgIndex}}" data-images="{{item.images}}" bind:tap="onImageView"></image>
|
||||
</view>
|
||||
</view>
|
||||
<view class="bottom-row">
|
||||
|
||||
@@ -48,7 +48,13 @@ Page({
|
||||
|
||||
onShow() {
|
||||
this.getTabBar().init();
|
||||
this.refreshRole();
|
||||
const app = getApp();
|
||||
const appShowAt = app && app.globalData ? app.globalData.appShowAt : 0;
|
||||
// 冷启动和从后台回到前台才拉角色;切换 Tab 不重复请求
|
||||
if (!this._roleLoadedAt || appShowAt !== this._seenAppShowAt) {
|
||||
this._seenAppShowAt = appShowAt;
|
||||
this.refreshRole();
|
||||
}
|
||||
},
|
||||
|
||||
onLoad() {
|
||||
@@ -64,12 +70,12 @@ Page({
|
||||
},
|
||||
|
||||
onPullDownRefresh() {
|
||||
this.init();
|
||||
this.loadHomePage(true);
|
||||
this.refreshRole();
|
||||
},
|
||||
|
||||
init() {
|
||||
this.loadHomePage();
|
||||
this.loadHomePage(false);
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -77,6 +83,10 @@ Page({
|
||||
* 入驻审核通过后,用户回到小程序触发 onShow 即可看到「进入接单大厅」入口
|
||||
*/
|
||||
refreshRole() {
|
||||
if (this._roleLoading) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
this._roleLoading = true;
|
||||
return fetchPerson().then((res) => {
|
||||
if (res.code === 1 && res.data) {
|
||||
const role = res.data.role || '';
|
||||
@@ -87,15 +97,20 @@ Page({
|
||||
wx.setStorageSync('userInfo', userInfo);
|
||||
}
|
||||
}
|
||||
}).catch((err) => {
|
||||
console.error('refreshRole failed:', err);
|
||||
}).then(() => {
|
||||
this._roleLoading = false;
|
||||
this._roleLoadedAt = Date.now();
|
||||
});
|
||||
},
|
||||
|
||||
async loadHomePage() {
|
||||
async loadHomePage(force = false) {
|
||||
this.setData({
|
||||
pageLoading: true,
|
||||
});
|
||||
try {
|
||||
const [configRes, bannerRes] = await Promise.all([fetchConfig(), fetchHomeBanners()]);
|
||||
const [configRes, bannerRes] = await Promise.all([fetchConfig({ force }), fetchHomeBanners()]);
|
||||
const next = { pageLoading: false };
|
||||
if (configRes.code === 1) {
|
||||
next.tabList = configRes.data.developTypes || [];
|
||||
|
||||
@@ -5,7 +5,7 @@ function tagTheme(type) {
|
||||
'1': 'warning',
|
||||
'2': 'success'
|
||||
};
|
||||
return map[String(type)] || 'default';
|
||||
return map['' + type] || 'default';
|
||||
}
|
||||
module.exports = {
|
||||
tagTheme: tagTheme
|
||||
|
||||
@@ -9,7 +9,7 @@ function tagTheme(type) {
|
||||
'1': 'warning',
|
||||
'2': 'success'
|
||||
};
|
||||
return map[String(type)] || 'default';
|
||||
return map['' + type] || 'default';
|
||||
}
|
||||
module.exports = {
|
||||
ellipsis: ellipsis,
|
||||
|
||||
@@ -298,7 +298,7 @@ Page({
|
||||
|
||||
onAmountTap() {
|
||||
this.setData({
|
||||
'serviceFrom.amount.temp': priceFormat(this.data.serviceFrom.amount.current),
|
||||
'serviceFrom.amount.temp': priceFormat(this.data.serviceFrom.amount.current, 2),
|
||||
'serviceFrom.amount.focus': true,
|
||||
inputDialogVisible: true,
|
||||
});
|
||||
@@ -307,8 +307,13 @@ Page({
|
||||
confirmBtn: '确定',
|
||||
});
|
||||
this.inputDialog._onConfirm = () => {
|
||||
const max = Number(this.data.serviceFrom.amount.max) || 0;
|
||||
let amount = parseFloat(this.data.serviceFrom.amount.temp) || 0;
|
||||
if (amount > max) {
|
||||
amount = max;
|
||||
}
|
||||
this.setData({
|
||||
'serviceFrom.amount.current': this.data.serviceFrom.amount.temp * 100,
|
||||
'serviceFrom.amount.current': amount,
|
||||
});
|
||||
};
|
||||
this.inputDialog._onCancel = () => {};
|
||||
@@ -327,12 +332,13 @@ Page({
|
||||
let { value } = e.detail;
|
||||
const regRes = value.match(/\d+(\.?\d+)?/); // 失去焦点时,不允许末尾为小数点
|
||||
value = regRes ? regRes[0] : '0';
|
||||
value = parseFloat(value) * 100;
|
||||
if (value > this.data.serviceFrom.amount.max) {
|
||||
value = this.data.serviceFrom.amount.max;
|
||||
let amount = parseFloat(value) || 0;
|
||||
const max = Number(this.data.serviceFrom.amount.max) || 0;
|
||||
if (amount > max) {
|
||||
amount = max;
|
||||
}
|
||||
this.setData({
|
||||
'serviceFrom.amount.temp': priceFormat(value),
|
||||
'serviceFrom.amount.temp': priceFormat(amount, 2),
|
||||
'serviceFrom.amount.focus': false,
|
||||
});
|
||||
},
|
||||
|
||||
@@ -3,6 +3,8 @@ import {
|
||||
} from '../../services/usercenter/fetchUsercenter';
|
||||
import Toast from 'tdesign-miniprogram/toast/index';
|
||||
|
||||
const USER_CENTER_TTL = 30000;
|
||||
|
||||
const menuData = [
|
||||
[{
|
||||
title: '我发布的需求',
|
||||
@@ -94,6 +96,31 @@ const orderTagInfos = [{
|
||||
},
|
||||
];
|
||||
|
||||
function cloneMenu(list) {
|
||||
return list.map((row) => row.map((item) => ({ ...item })));
|
||||
}
|
||||
|
||||
/** 按角色组装菜单,每次返回新数组,避免改到模块上的模板 */
|
||||
function buildMenu(userInfo = {}, countsData = []) {
|
||||
const menu = cloneMenu(menuData);
|
||||
menu[0] = menu[0].filter((item) => item.type !== 'quote' && item.type !== 'promoter');
|
||||
if (userInfo.role === 'dev') {
|
||||
menu[0].splice(1, 0, { title: '我投标的需求', tit: '', url: '', icon: '', type: 'quote' });
|
||||
}
|
||||
if (userInfo.group_name === PROMOTER_GROUP) {
|
||||
const balanceIndex = menu[0].findIndex((item) => item.type === 'balance');
|
||||
menu[0].splice(balanceIndex === -1 ? menu[0].length : balanceIndex + 1, 0, { ...promoterMenu });
|
||||
}
|
||||
const counts = Array.isArray(countsData) ? countsData : [];
|
||||
menu[0].forEach((item) => {
|
||||
const matched = counts.find((count) => count.type === item.type);
|
||||
if (matched) {
|
||||
item.tit = matched.num;
|
||||
}
|
||||
});
|
||||
return menu;
|
||||
}
|
||||
|
||||
const getDefaultData = () => ({
|
||||
showMakePhone: false,
|
||||
userInfo: {
|
||||
@@ -101,8 +128,8 @@ const getDefaultData = () => ({
|
||||
nickName: '正在登录...',
|
||||
phoneNumber: '',
|
||||
},
|
||||
menuData,
|
||||
orderTagInfos,
|
||||
menuData: cloneMenu(menuData),
|
||||
orderTagInfos: orderTagInfos.map((item) => ({ ...item })),
|
||||
customerServiceInfo: {},
|
||||
currAuthStep: 1,
|
||||
showKefu: true,
|
||||
@@ -118,10 +145,22 @@ Page({
|
||||
|
||||
onShow() {
|
||||
this.getTabBar().init();
|
||||
this.init();
|
||||
const app = getApp();
|
||||
const appShowAt = app && app.globalData ? app.globalData.appShowAt : 0;
|
||||
const fromBackground = appShowAt !== this._seenAppShowAt;
|
||||
this._seenAppShowAt = appShowAt;
|
||||
const stale = !this._loadedAt || Date.now() - this._loadedAt > USER_CENTER_TTL;
|
||||
// 从后台回来,或距离上次成功超过 30 秒,才重新拉用户中心
|
||||
if (fromBackground || stale) {
|
||||
this.init();
|
||||
}
|
||||
},
|
||||
onPullDownRefresh() {
|
||||
this.init();
|
||||
if (this._loading) {
|
||||
wx.stopPullDownRefresh();
|
||||
return;
|
||||
}
|
||||
this.fetUseriInfoHandle();
|
||||
},
|
||||
|
||||
init() {
|
||||
@@ -129,44 +168,40 @@ Page({
|
||||
},
|
||||
|
||||
fetUseriInfoHandle() {
|
||||
fetchUserCenter().then(
|
||||
(res) => {
|
||||
const {
|
||||
userInfo,
|
||||
countsData,
|
||||
orderTagInfos: orderTags,
|
||||
customerServiceInfo,
|
||||
} = res.data;
|
||||
// eslint-disable-next-line no-unused-expressions
|
||||
menuData[0] = menuData[0].filter((item) => item.type !== 'quote' && item.type !== 'promoter');
|
||||
if (userInfo.role === 'dev') {
|
||||
menuData[0].splice(1, 0, { title: '我投标的需求', tit: '', url: '', icon: '', type: 'quote' });
|
||||
}
|
||||
if (userInfo.group_name === PROMOTER_GROUP) {
|
||||
const balanceIndex = menuData[0].findIndex((item) => item.type === 'balance');
|
||||
menuData[0].splice(balanceIndex === -1 ? menuData[0].length : balanceIndex + 1, 0, { ...promoterMenu });
|
||||
}
|
||||
menuData[0].forEach((v) => {
|
||||
countsData.forEach((counts) => {
|
||||
if (counts.type === v.type) {
|
||||
v.tit = counts.num;
|
||||
}
|
||||
});
|
||||
});
|
||||
const info = orderTagInfos.map((v, index) => ({
|
||||
...v,
|
||||
...orderTags[index],
|
||||
}));
|
||||
this.setData({
|
||||
userInfo,
|
||||
menuData,
|
||||
orderTagInfos: info,
|
||||
customerServiceInfo,
|
||||
currAuthStep: 2,
|
||||
});
|
||||
wx.stopPullDownRefresh();
|
||||
},
|
||||
);
|
||||
if (this._loading) {
|
||||
return;
|
||||
}
|
||||
this._loading = true;
|
||||
fetchUserCenter().then((res) => {
|
||||
if (!res || res.code !== 1 || !res.data) {
|
||||
wx.showToast({ title: (res && res.msg) || '加载失败', icon: 'none' });
|
||||
return;
|
||||
}
|
||||
const {
|
||||
userInfo,
|
||||
countsData,
|
||||
orderTagInfos: orderTags,
|
||||
customerServiceInfo,
|
||||
} = res.data;
|
||||
const info = orderTagInfos.map((item, index) => ({
|
||||
...item,
|
||||
...(orderTags && orderTags[index] ? orderTags[index] : {}),
|
||||
}));
|
||||
this._loadedAt = Date.now();
|
||||
this.setData({
|
||||
userInfo,
|
||||
menuData: buildMenu(userInfo, countsData),
|
||||
orderTagInfos: info,
|
||||
customerServiceInfo,
|
||||
currAuthStep: 2,
|
||||
});
|
||||
}).catch((err) => {
|
||||
console.error('fetchUserCenter failed:', err);
|
||||
wx.showToast({ title: '网络异常,请重试', icon: 'none' });
|
||||
}).then(() => {
|
||||
this._loading = false;
|
||||
wx.stopPullDownRefresh();
|
||||
});
|
||||
},
|
||||
|
||||
onClickCell({
|
||||
|
||||
@@ -52,9 +52,46 @@ export function fetchHome() {
|
||||
});
|
||||
}
|
||||
|
||||
/** 获取配置数据 */
|
||||
export function fetchConfig() {
|
||||
return wx.$util.request(wx.$api.CommonGetMiniConfig, {}, 'GET', { auth: false });
|
||||
const CONFIG_TTL = 60000;
|
||||
let configCache = null;
|
||||
let configTask = null;
|
||||
// 与后端 site.platform_commission_ratio 默认值一致,接口失败时兜底
|
||||
const DEFAULT_COMMISSION_RATIO = 0.1;
|
||||
let commissionRatioCache = null;
|
||||
const CASE_VIEW_STORAGE_KEY = 'goodsCaseView';
|
||||
let caseViewCache = null;
|
||||
|
||||
/**
|
||||
* 获取小程序配置。成功结果缓存 60 秒,同时进行中的请求合并成一次
|
||||
* @param {{force?: boolean}} options force 为 true 时忽略缓存(下拉刷新)
|
||||
*/
|
||||
export function fetchConfig(options = {}) {
|
||||
const force = options === true || options.force === true;
|
||||
if (configTask) {
|
||||
return configTask;
|
||||
}
|
||||
if (!force && configCache && Date.now() - configCache.at < CONFIG_TTL) {
|
||||
return Promise.resolve(configCache.res);
|
||||
}
|
||||
configTask = wx.$util.request(wx.$api.CommonGetMiniConfig, {}, 'GET', { auth: false }).then((res) => {
|
||||
if (res && res.code === 1) {
|
||||
configCache = { at: Date.now(), res };
|
||||
const ratio = Number(res.data?.platform_commission_ratio);
|
||||
if (ratio >= 0 && ratio <= 1) {
|
||||
commissionRatioCache = ratio;
|
||||
}
|
||||
caseViewCache = res.data?.goods_case_view === true || res.data?.goods_case_view === 1;
|
||||
wx.setStorageSync(CASE_VIEW_STORAGE_KEY, caseViewCache);
|
||||
}
|
||||
return res;
|
||||
}).then((res) => {
|
||||
configTask = null;
|
||||
return res;
|
||||
}, (err) => {
|
||||
configTask = null;
|
||||
throw err;
|
||||
});
|
||||
return configTask;
|
||||
}
|
||||
|
||||
/** 获取首页轮播(分类类型 banner) */
|
||||
@@ -62,10 +99,6 @@ export function fetchHomeBanners() {
|
||||
return wx.$util.request(wx.$api.CatalogList, { type: 'banner' }, 'GET', { auth: false });
|
||||
}
|
||||
|
||||
// 与后端 site.platform_commission_ratio 默认值一致,接口失败时兜底
|
||||
const DEFAULT_COMMISSION_RATIO = 0.1;
|
||||
let commissionRatioCache = null;
|
||||
|
||||
/**
|
||||
* 获取平台服务费比例(0~1),成功后缓存,失败返回默认值且不缓存,下次重新请求
|
||||
* @returns {Promise<number>}
|
||||
@@ -87,9 +120,6 @@ export async function fetchPlatformCommissionRatio() {
|
||||
return DEFAULT_COMMISSION_RATIO;
|
||||
}
|
||||
|
||||
const CASE_VIEW_STORAGE_KEY = 'goodsCaseView';
|
||||
let caseViewCache = null;
|
||||
|
||||
/**
|
||||
* 商品是否按案例展示(不显示价格和购买入口)
|
||||
* 成功后缓存;失败时用上次成功的本地记录
|
||||
|
||||
@@ -406,24 +406,23 @@ function getUid(prefix) {
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化价格数额为字符串
|
||||
* 可对小数部分进行填充,默认不填充
|
||||
* @param price 价格数额,以分为单位!
|
||||
* @param fill 是否填充小数部分 0-不填充 1-填充第一位小数 2-填充两位小数
|
||||
* 格式化金额为字符串,单位为元
|
||||
* @param price 金额,单位元
|
||||
* @param fill 小数位数 0-不填充 1-一位 2-两位
|
||||
*/
|
||||
function priceFormat(price, fill = 0) {
|
||||
if (isNaN(price) || price === null || price === Infinity) {
|
||||
return price;
|
||||
}
|
||||
|
||||
let priceFormatValue = Math.round(parseFloat(`${price}`) * 10 ** 8) / 10 ** 8; // 恢复精度丢失
|
||||
priceFormatValue = `${Math.ceil(priceFormatValue) / 100}`; // 向上取整,单位转换为元,转换为字符串
|
||||
const rounded = Math.round(parseFloat(`${price}`) * 100) / 100;
|
||||
let priceFormatValue = `${rounded}`;
|
||||
if (fill > 0) {
|
||||
// 补充小数位数
|
||||
if (priceFormatValue.indexOf('.') === -1) {
|
||||
priceFormatValue = `${priceFormatValue}.`;
|
||||
}
|
||||
const n = fill - priceFormatValue.split('.')[1]?.length;
|
||||
const decimal = priceFormatValue.split('.')[1] || '';
|
||||
const n = fill - decimal.length;
|
||||
for (let i = 0; i < n; i++) {
|
||||
priceFormatValue = `${priceFormatValue}0`;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user