优化列表刷新加载
This commit is contained in:
+26
-22
@@ -20,29 +20,33 @@ App({
|
||||
//通过分享链接/小程序码冷启动时缓存推广人,随登录请求一起绑定
|
||||
savePendingPromoter(options && options.query);
|
||||
this.loggingIn = true;
|
||||
// 登录
|
||||
wx.login({
|
||||
success: (res) => {
|
||||
util.request(api.AuthLoginByWeixin, {
|
||||
code: res.code,
|
||||
[PROMOTER_KEY]: getPendingPromoter(),
|
||||
}, 'POST').then((res) => {
|
||||
this.loggingIn = false;
|
||||
if (res.code === 1) {
|
||||
let userInfo = res.data.userinfo;
|
||||
wx.setStorageSync('token', res.data.token);
|
||||
wx.setStorageSync('userInfo', userInfo);
|
||||
//推广关系为永久绑定,登录成功后无论是否绑定都无需再次提交
|
||||
clearPendingPromoter();
|
||||
}
|
||||
}).catch((err) => {
|
||||
this.loggingIn = false;
|
||||
console.error('wxLogin failed:', err);
|
||||
});
|
||||
},
|
||||
fail: () => {
|
||||
// 登录。loginReady 给需要鉴权的请求等待,避免首屏带着空 token 发出去
|
||||
this.loginReady = new Promise((resolve) => {
|
||||
const finish = () => {
|
||||
this.loggingIn = false;
|
||||
},
|
||||
resolve();
|
||||
};
|
||||
wx.login({
|
||||
success: (loginRes) => {
|
||||
util.request(api.AuthLoginByWeixin, {
|
||||
code: loginRes.code,
|
||||
[PROMOTER_KEY]: getPendingPromoter(),
|
||||
}, 'POST', { auth: false }).then((res) => {
|
||||
if (res.code === 1) {
|
||||
let userInfo = res.data.userinfo;
|
||||
util.setToken(res.data.token);
|
||||
wx.setStorageSync('userInfo', userInfo);
|
||||
//推广关系为永久绑定,登录成功后无论是否绑定都无需再次提交
|
||||
clearPendingPromoter();
|
||||
}
|
||||
}).catch((err) => {
|
||||
console.error('wxLogin failed:', err);
|
||||
}).then(finish);
|
||||
},
|
||||
fail: () => {
|
||||
finish();
|
||||
},
|
||||
});
|
||||
});
|
||||
},
|
||||
onShow: function (options) {
|
||||
|
||||
@@ -70,15 +70,10 @@ Page({
|
||||
//图片预览
|
||||
onImageView(e) {
|
||||
const { images, index } = e.currentTarget.dataset;
|
||||
console.log('images', images);
|
||||
console.log('index', index);
|
||||
wx.previewImage({
|
||||
current: images[index], // 当前显示图片的http链接
|
||||
urls: images, // 需要预览的图片http链接列表
|
||||
success: (res) => {
|
||||
console.log('预览成功');
|
||||
},
|
||||
complete: (res) => {
|
||||
current: images[index],
|
||||
urls: images,
|
||||
complete: () => {
|
||||
this.setData({ fromPreview: true });
|
||||
}
|
||||
});
|
||||
@@ -87,65 +82,69 @@ Page({
|
||||
// 加载需求列表数据
|
||||
async loadDemandList(fresh = false, options = {}) {
|
||||
const { silent = false } = options;
|
||||
if (fresh) {
|
||||
this.setData({
|
||||
page: 1,
|
||||
hasMore: true, // 刷新时重置
|
||||
});
|
||||
wx.pageScrollTo({
|
||||
scrollTop: 0,
|
||||
});
|
||||
// 上拉加载:请求未结束或没有下一页时直接返回,避免并发把同一页打两次
|
||||
if (!fresh && (this._loading || !this.data.hasMore)) {
|
||||
return;
|
||||
}
|
||||
const seq = (this._listSeq || 0) + 1;
|
||||
this._listSeq = seq;
|
||||
this._loading = true;
|
||||
const page = fresh ? 1 : this.data.page;
|
||||
const { status, keywords, opType } = this.data;
|
||||
if (fresh) {
|
||||
wx.pageScrollTo({ scrollTop: 0 });
|
||||
}
|
||||
if (!silent) {
|
||||
wx.showLoading({ title: '加载中', mask: true });
|
||||
}
|
||||
wx.nextTick(() => {
|
||||
console.log(this.data.hasMore, fresh);
|
||||
if (!this.data.hasMore && !fresh) return;
|
||||
});
|
||||
|
||||
try {
|
||||
const { page, status, keywords, opType } = this.data;
|
||||
let params = { page, status, keywords, opType };
|
||||
// 下拉刷新自带 loading 指示,不再叠加 showLoading
|
||||
if (!silent) {
|
||||
wx.showLoading({
|
||||
title: '加载中',
|
||||
});
|
||||
const res = await fetchDemandList({ page, status, keywords, opType });
|
||||
if (seq !== this._listSeq) {
|
||||
return;
|
||||
}
|
||||
const res = await fetchDemandList(params);
|
||||
const nextList = res.data.data;
|
||||
console.log(res)
|
||||
console.log(nextList)
|
||||
if (!silent) {
|
||||
wx.hideLoading();
|
||||
if (!res || res.code !== 1 || !res.data) {
|
||||
wx.showToast({ title: (res && res.msg) || '加载失败', icon: 'none' });
|
||||
return;
|
||||
}
|
||||
|
||||
// 判断是否还有更多数据
|
||||
const { current_page, last_page } = res.data;
|
||||
let newDemandList = fresh ? nextList : this.data.demandList.concat(nextList);
|
||||
const hasMore = current_page < last_page;
|
||||
|
||||
// 只有在还有更多页时才自增page
|
||||
const nextList = Array.isArray(res.data.data) ? res.data.data : [];
|
||||
const hasMore = res.data.current_page < res.data.last_page;
|
||||
const start = fresh ? 0 : this.data.demandList.length;
|
||||
const patch = {
|
||||
hasMore,
|
||||
isEmpty: start + nextList.length === 0,
|
||||
};
|
||||
if (hasMore) {
|
||||
this.setData({
|
||||
demandList: newDemandList,
|
||||
page: page + 1,
|
||||
hasMore
|
||||
});
|
||||
patch.page = page + 1;
|
||||
} else if (fresh) {
|
||||
patch.page = 1;
|
||||
}
|
||||
if (fresh) {
|
||||
patch.demandList = nextList;
|
||||
} else {
|
||||
this.setData({
|
||||
demandList: newDemandList,
|
||||
hasMore: false
|
||||
nextList.forEach((item, i) => {
|
||||
patch[`demandList[${start + i}]`] = item;
|
||||
});
|
||||
}
|
||||
|
||||
this.setData({
|
||||
isEmpty: newDemandList.length > 0 ? false : true
|
||||
});
|
||||
// 检查内容是否超出最大高度,放到 nextTick 里
|
||||
wx.nextTick(() => {
|
||||
this.checkDescOverflow();
|
||||
this.setData(patch, () => {
|
||||
if (seq !== this._listSeq) {
|
||||
return;
|
||||
}
|
||||
const indices = [];
|
||||
for (let i = start; i < this.data.demandList.length; i++) {
|
||||
indices.push(i);
|
||||
}
|
||||
this.checkDescOverflow(indices);
|
||||
});
|
||||
} catch (err) {
|
||||
console.error('Failed to load demand list:', err);
|
||||
if (seq === this._listSeq) {
|
||||
console.error('Failed to load demand list:', err);
|
||||
wx.showToast({ title: '网络异常,请重试', icon: 'none' });
|
||||
}
|
||||
} finally {
|
||||
if (seq === this._listSeq) {
|
||||
this._loading = false;
|
||||
wx.hideLoading();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -161,6 +160,13 @@ Page({
|
||||
await this.loadDemandList(true);
|
||||
return;
|
||||
}
|
||||
const prev = {};
|
||||
demandList.forEach((item) => {
|
||||
prev[item.id] = { expanded: !!item.expanded, showToggle: !!item.showToggle };
|
||||
});
|
||||
const seq = (this._listSeq || 0) + 1;
|
||||
this._listSeq = seq;
|
||||
this._loading = true;
|
||||
try {
|
||||
const res = await fetchDemandList({
|
||||
page: 1,
|
||||
@@ -169,39 +175,83 @@ Page({
|
||||
keywords,
|
||||
opType
|
||||
});
|
||||
const nextList = res.data.data || [];
|
||||
//不动 page,保持原有的分页进度;条目流转出当前标签后总数会变,需同步 hasMore
|
||||
if (seq !== this._listSeq) {
|
||||
return;
|
||||
}
|
||||
if (!res || res.code !== 1 || !res.data) {
|
||||
return;
|
||||
}
|
||||
const raw = Array.isArray(res.data.data) ? res.data.data : [];
|
||||
// 保留已展开状态,避免返回列表时把「查看全文」收回去
|
||||
const nextList = raw.map((item) => {
|
||||
const old = prev[item.id];
|
||||
return {
|
||||
...item,
|
||||
expanded: old ? old.expanded : false,
|
||||
showToggle: old ? old.showToggle : false,
|
||||
};
|
||||
});
|
||||
this.setData({
|
||||
demandList: nextList,
|
||||
hasMore: res.data.current_page < res.data.last_page,
|
||||
isEmpty: nextList.length === 0
|
||||
});
|
||||
wx.nextTick(() => {
|
||||
this.checkDescOverflow();
|
||||
}, () => {
|
||||
if (seq !== this._listSeq) {
|
||||
return;
|
||||
}
|
||||
const indices = [];
|
||||
nextList.forEach((item, index) => {
|
||||
if (!prev[item.id]) {
|
||||
indices.push(index);
|
||||
}
|
||||
});
|
||||
this.checkDescOverflow(indices);
|
||||
});
|
||||
} catch (err) {
|
||||
console.error('Failed to refresh demand list:', err);
|
||||
if (seq === this._listSeq) {
|
||||
console.error('Failed to refresh demand list:', err);
|
||||
}
|
||||
} finally {
|
||||
if (seq === this._listSeq) {
|
||||
this._loading = false;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// 检查每条内容是否超出最大高度,决定是否显示“查看全文”
|
||||
checkDescOverflow() {
|
||||
/**
|
||||
* 只测量指定下标的描述高度,按路径更新 showToggle
|
||||
* 不改 expanded,加载下一页时已展开的条目保持展开
|
||||
* @param {number[]} indices
|
||||
*/
|
||||
checkDescOverflow(indices) {
|
||||
if (!indices || !indices.length) {
|
||||
return;
|
||||
}
|
||||
const seq = this._listSeq;
|
||||
const query = this.createSelectorQuery();
|
||||
const maxHeight = 60; // 120rpx ≈ 60px,实际可根据机型调整
|
||||
this.data.demandList.forEach((item, index) => {
|
||||
const maxHeight = 60; // 120rpx ≈ 60px
|
||||
indices.forEach((index) => {
|
||||
query.select(`#desc-${index}`).boundingClientRect();
|
||||
});
|
||||
query.exec((rects) => {
|
||||
const newList = this.data.demandList.map((item, idx) => {
|
||||
// 只有内容高度大于 maxHeight+1 时才显示“查看全文”
|
||||
const showToggle = rects[idx] && rects[idx].height > (maxHeight + 1);
|
||||
return {
|
||||
...item,
|
||||
expanded: false,
|
||||
showToggle
|
||||
};
|
||||
if (seq !== this._listSeq || !rects) {
|
||||
return;
|
||||
}
|
||||
const patch = {};
|
||||
rects.forEach((rect, i) => {
|
||||
const index = indices[i];
|
||||
const item = this.data.demandList[index];
|
||||
if (!item) {
|
||||
return;
|
||||
}
|
||||
const showToggle = !!(rect && rect.height > maxHeight + 1);
|
||||
if (!!item.showToggle !== showToggle) {
|
||||
patch[`demandList[${index}].showToggle`] = showToggle;
|
||||
}
|
||||
});
|
||||
this.setData({ demandList: newList });
|
||||
if (Object.keys(patch).length) {
|
||||
this.setData(patch);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
@@ -312,9 +362,10 @@ Page({
|
||||
* 页面上拉触底事件的处理函数
|
||||
*/
|
||||
onReachBottom() {
|
||||
if (this.data.hasMore) {
|
||||
this.loadDemandList();
|
||||
if (this._loading || !this.data.hasMore) {
|
||||
return;
|
||||
}
|
||||
this.loadDemandList();
|
||||
},
|
||||
|
||||
/**
|
||||
|
||||
@@ -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="index" 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" data-index="{{imgIndex}}" data-images="{{item.images}}" src="{{img}}" bind:tap="onImageView"></image>
|
||||
</view>
|
||||
</view>
|
||||
<view class="bottom-row">
|
||||
|
||||
@@ -28,7 +28,7 @@ Page({
|
||||
* 获取基础配置
|
||||
*/
|
||||
getConfig() {
|
||||
wx.$util.request(wx.$api.CommonGetMiniConfig, {}, 'GET').then(res => {
|
||||
wx.$util.request(wx.$api.CommonGetMiniConfig, {}, 'GET', { auth: false }).then(res => {
|
||||
if (res.code === 1) {
|
||||
this.setData({
|
||||
languageLabels: res.data.languageLabels || [],
|
||||
|
||||
@@ -89,62 +89,87 @@ Page({
|
||||
|
||||
// 产品列表
|
||||
async loadGoodsList(reset = false) {
|
||||
if (!reset && (this._loading || this.data.loadMoreStatus !== 0)) {
|
||||
return;
|
||||
}
|
||||
const seq = (this._listSeq || 0) + 1;
|
||||
this._listSeq = seq;
|
||||
this._loading = true;
|
||||
const page = reset ? 1 : this.data.page;
|
||||
const { pageSize, keywords, tabValue } = this.data;
|
||||
this.setData({
|
||||
loadMoreStatus: 1,
|
||||
loading: true,
|
||||
});
|
||||
try {
|
||||
const { loadMoreStatus, goodsList = [], page, pageSize, keywords, tabValue } = this.data;
|
||||
const params = {
|
||||
page: reset ? 1 : page,
|
||||
const result = await fetchGoodsList({
|
||||
page,
|
||||
categoryId: tabValue,
|
||||
pageSize,
|
||||
keywords,
|
||||
};
|
||||
if (loadMoreStatus !== 0 && !reset) return;
|
||||
this.setData({
|
||||
loadMoreStatus: 1,
|
||||
loading: true,
|
||||
});
|
||||
const result = await fetchGoodsList(params);
|
||||
console.log('fetchGoodsList', result)
|
||||
const data = result.data;
|
||||
if (result.code == 1) {
|
||||
const { spuList, totalCount = 0 } = data;
|
||||
if (totalCount === 0 && reset) {
|
||||
this.setData({
|
||||
emptyInfo: {
|
||||
tip: '抱歉,未找到相关商品',
|
||||
},
|
||||
total: totalCount,
|
||||
hasLoaded: true,
|
||||
loadMoreStatus: 0,
|
||||
loading: false,
|
||||
goodsList: [],
|
||||
});
|
||||
return;
|
||||
}
|
||||
const _goodsList = reset ? spuList : goodsList.concat(spuList);
|
||||
const _loadMoreStatus = _goodsList.length === totalCount ? 2 : 0;
|
||||
this.setData({
|
||||
total: totalCount,
|
||||
page: params.page + 1,
|
||||
goodsList: _goodsList,
|
||||
loadMoreStatus: _loadMoreStatus,
|
||||
});
|
||||
} else {
|
||||
if (seq !== this._listSeq) {
|
||||
return;
|
||||
}
|
||||
if (!result || result.code !== 1 || !result.data) {
|
||||
this.setData({
|
||||
loading: false,
|
||||
hasLoaded: true,
|
||||
loadMoreStatus: 0,
|
||||
});
|
||||
wx.showToast({
|
||||
title: '查询失败,请稍候重试',
|
||||
title: (result && result.msg) || '查询失败,请稍候重试',
|
||||
icon: 'none',
|
||||
});
|
||||
return;
|
||||
}
|
||||
const { spuList = [], totalCount = 0 } = result.data;
|
||||
if (totalCount === 0 && reset) {
|
||||
this.setData({
|
||||
emptyInfo: {
|
||||
tip: '抱歉,未找到相关商品',
|
||||
},
|
||||
total: totalCount,
|
||||
hasLoaded: true,
|
||||
loadMoreStatus: 2,
|
||||
loading: false,
|
||||
goodsList: [],
|
||||
page: 1,
|
||||
});
|
||||
return;
|
||||
}
|
||||
const start = reset ? 0 : this.data.goodsList.length;
|
||||
const loaded = start + spuList.length;
|
||||
const patch = {
|
||||
total: totalCount,
|
||||
page: page + 1,
|
||||
loadMoreStatus: loaded >= totalCount ? 2 : 0,
|
||||
hasLoaded: true,
|
||||
loading: false,
|
||||
};
|
||||
if (reset) {
|
||||
patch.goodsList = spuList;
|
||||
} else {
|
||||
spuList.forEach((item, i) => {
|
||||
patch[`goodsList[${start + i}]`] = item;
|
||||
});
|
||||
}
|
||||
this.setData(patch);
|
||||
} catch (error) {
|
||||
if (seq !== this._listSeq) {
|
||||
return;
|
||||
}
|
||||
console.error('loadGoodsList failed:', error);
|
||||
this.setData({
|
||||
loading: false,
|
||||
hasLoaded: true,
|
||||
loadMoreStatus: 0,
|
||||
});
|
||||
} finally {
|
||||
if (seq === this._listSeq) {
|
||||
this._loading = false;
|
||||
}
|
||||
}
|
||||
this.setData({
|
||||
hasLoaded: true,
|
||||
loading: false,
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
@@ -164,8 +189,11 @@ Page({
|
||||
},
|
||||
|
||||
onReachBottom() {
|
||||
if (this._loading || this.data.loadMoreStatus !== 0) {
|
||||
return;
|
||||
}
|
||||
const { goodsList, total } = this.data;
|
||||
if (goodsList.length === total) {
|
||||
if (goodsList.length >= total) {
|
||||
this.setData({
|
||||
loadMoreStatus: 2,
|
||||
});
|
||||
|
||||
@@ -24,17 +24,18 @@ Page({
|
||||
loading: false
|
||||
},
|
||||
|
||||
onLoad() {
|
||||
this.loadList(true);
|
||||
},
|
||||
|
||||
loadList(refresh = false) {
|
||||
let { pageSize, list, currentType } = this.data;
|
||||
if (!refresh && (this._loading || !this.data.hasMore)) {
|
||||
return;
|
||||
}
|
||||
const seq = (this._listSeq || 0) + 1;
|
||||
this._listSeq = seq;
|
||||
this._loading = true;
|
||||
const { pageSize, currentType } = this.data;
|
||||
const page = refresh ? 1 : this.data.page;
|
||||
|
||||
let params = {
|
||||
page: page,
|
||||
pageSize: pageSize,
|
||||
const params = {
|
||||
page,
|
||||
pageSize,
|
||||
};
|
||||
//全部时不传 message_type,由后端返回全类型
|
||||
if (currentType !== '') {
|
||||
@@ -42,25 +43,52 @@ Page({
|
||||
}
|
||||
|
||||
fetchMessageList(params).then((res) => {
|
||||
let newList = res.data.data;
|
||||
let hasMore = res.data.current_page < res.data.last_page;
|
||||
let unreadMap = res.data.unread_map || { '0': 0, '1': 0, '2': 0 };
|
||||
if (seq !== this._listSeq) {
|
||||
return;
|
||||
}
|
||||
if (!res || res.code !== 1 || !res.data) {
|
||||
wx.showToast({ title: (res && res.msg) || '加载失败', icon: 'none' });
|
||||
return;
|
||||
}
|
||||
const nextList = Array.isArray(res.data.data) ? res.data.data : [];
|
||||
const hasMore = res.data.current_page < res.data.last_page;
|
||||
const unreadMap = res.data.unread_map || { '0': 0, '1': 0, '2': 0 };
|
||||
//直接用后端统计的全量未读总数(含所有类型),
|
||||
//不再由前端累加 0/1/2,避免 message_type 超出这三个值时漏算
|
||||
let totalUnread = res.data.unread_total !== undefined && res.data.unread_total !== null
|
||||
const totalUnread = res.data.unread_total !== undefined && res.data.unread_total !== null
|
||||
? Number(res.data.unread_total) || 0
|
||||
: Number(unreadMap['0'] || 0) + Number(unreadMap['1'] || 0) + Number(unreadMap['2'] || 0);
|
||||
this.setData({
|
||||
list: refresh ? newList : list.concat(newList),
|
||||
page: page + 1,
|
||||
const patch = {
|
||||
page: hasMore ? page + 1 : page,
|
||||
unreadCount: res.data.unread_count,
|
||||
unreadMap: unreadMap,
|
||||
totalUnread: totalUnread,
|
||||
hasMore: hasMore,
|
||||
loading: false
|
||||
});
|
||||
//同步底部tabbar红点
|
||||
unreadMap,
|
||||
totalUnread,
|
||||
hasMore,
|
||||
loading: false,
|
||||
};
|
||||
if (refresh) {
|
||||
patch.list = nextList;
|
||||
} else {
|
||||
const start = this.data.list.length;
|
||||
nextList.forEach((item, i) => {
|
||||
patch[`list[${start + i}]`] = item;
|
||||
});
|
||||
}
|
||||
this.setData(patch);
|
||||
this.syncTabBarUnread(totalUnread);
|
||||
}).catch((err) => {
|
||||
if (seq !== this._listSeq) {
|
||||
return;
|
||||
}
|
||||
console.error('loadList failed:', err);
|
||||
wx.showToast({ title: '网络异常,请重试', icon: 'none' });
|
||||
}).then(() => {
|
||||
if (seq !== this._listSeq) {
|
||||
return;
|
||||
}
|
||||
this._loading = false;
|
||||
this.setData({ loading: false });
|
||||
wx.stopPullDownRefresh();
|
||||
});
|
||||
},
|
||||
|
||||
@@ -99,15 +127,29 @@ Page({
|
||||
},
|
||||
|
||||
onReachBottom() {
|
||||
if (this.data.hasMore) {
|
||||
this.loadList();
|
||||
if (this._loading || !this.data.hasMore) {
|
||||
return;
|
||||
}
|
||||
this.loadList();
|
||||
},
|
||||
|
||||
onClearUnreadTap() {
|
||||
messageSetRead({ isAll: 1 }).then(() => {
|
||||
if (this._clearing) {
|
||||
return;
|
||||
}
|
||||
this._clearing = true;
|
||||
messageSetRead({ isAll: 1 }).then((res) => {
|
||||
if (!res || res.code !== 1) {
|
||||
wx.showToast({ title: (res && res.msg) || '操作失败', icon: 'none' });
|
||||
return;
|
||||
}
|
||||
wx.showToast({ title: '全部已读', icon: 'success' });
|
||||
this.loadList(true);
|
||||
}).catch((err) => {
|
||||
console.error('messageSetRead failed:', err);
|
||||
wx.showToast({ title: '网络异常,请重试', icon: 'none' });
|
||||
}).then(() => {
|
||||
this._clearing = false;
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { config } from '../../config/index';
|
||||
import { CatalogList } from '../../config/api';
|
||||
|
||||
/** 获取商品列表 */
|
||||
function mockFetchGoodCategory() {
|
||||
@@ -13,20 +12,10 @@ export function getCategoryList() {
|
||||
if (config.useMock) {
|
||||
return mockFetchGoodCategory();
|
||||
}
|
||||
return new Promise((resolve, reject) => {
|
||||
wx.request({
|
||||
url: CatalogList,
|
||||
method: 'GET',
|
||||
success: (res) => {
|
||||
if (res.statusCode === 200) {
|
||||
resolve(res.data.data);
|
||||
} else {
|
||||
reject(new Error('获取分类列表失败'));
|
||||
}
|
||||
},
|
||||
fail: (err) => {
|
||||
reject(err);
|
||||
}
|
||||
});
|
||||
return wx.$util.request(wx.$api.CatalogList, {}, 'GET', { auth: false }).then((res) => {
|
||||
if (!res || res.code !== 1) {
|
||||
return Promise.reject(new Error((res && res.msg) || '获取分类列表失败'));
|
||||
}
|
||||
return res.data;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -12,5 +12,5 @@ export function fetchGood(ID = 0) {
|
||||
if (config.useMock) {
|
||||
return mockFetchGood(ID);
|
||||
}
|
||||
return wx.$util.request(wx.$api.GoodsDetail, { id: ID }, 'GET');
|
||||
return wx.$util.request(wx.$api.GoodsDetail, { id: ID }, 'GET', { auth: false });
|
||||
}
|
||||
|
||||
@@ -54,12 +54,12 @@ export function fetchHome() {
|
||||
|
||||
/** 获取配置数据 */
|
||||
export function fetchConfig() {
|
||||
return wx.$util.request(wx.$api.CommonGetMiniConfig, {}, 'GET');
|
||||
return wx.$util.request(wx.$api.CommonGetMiniConfig, {}, 'GET', { auth: false });
|
||||
}
|
||||
|
||||
/** 获取首页轮播(分类类型 banner) */
|
||||
export function fetchHomeBanners() {
|
||||
return wx.$util.request(wx.$api.CatalogList, { type: 'banner' }, 'GET');
|
||||
return wx.$util.request(wx.$api.CatalogList, { type: 'banner' }, 'GET', { auth: false });
|
||||
}
|
||||
|
||||
// 与后端 site.platform_commission_ratio 默认值一致,接口失败时兜底
|
||||
|
||||
+137
-87
@@ -1,6 +1,5 @@
|
||||
import dayjs from 'dayjs';
|
||||
var api = require('../config/api.js');
|
||||
var util = require('../utils/util.js');
|
||||
|
||||
const formatTime = (date, template) => dayjs(date).format(template);
|
||||
|
||||
@@ -55,63 +54,147 @@ function testMobile(num) {
|
||||
}
|
||||
}
|
||||
|
||||
const REQUEST_TIMEOUT = 15000;
|
||||
let tokenCache = '';
|
||||
let tokenLoaded = false;
|
||||
let reloginTask = null;
|
||||
|
||||
function getAppSafe() {
|
||||
try {
|
||||
return getApp();
|
||||
} catch (err) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/** 内存缓存 token,避免每次请求都读 Storage */
|
||||
function getToken() {
|
||||
if (!tokenLoaded) {
|
||||
tokenCache = wx.getStorageSync('token') || '';
|
||||
tokenLoaded = true;
|
||||
}
|
||||
return tokenCache;
|
||||
}
|
||||
|
||||
function setToken(token) {
|
||||
tokenCache = token || '';
|
||||
tokenLoaded = true;
|
||||
if (tokenCache) {
|
||||
wx.setStorageSync('token', tokenCache);
|
||||
} else {
|
||||
wx.removeStorageSync('token');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 封封微信的的request
|
||||
* 本地还没有 token 时,等冷启动登录结束再发需要鉴权的请求
|
||||
* 已有 token 则直接发,过期由 401 重登处理
|
||||
*/
|
||||
function request(url, data = {}, method = "GET") {
|
||||
return new Promise(function (resolve, reject) {
|
||||
wx.request({
|
||||
url: url,
|
||||
data: data,
|
||||
method: method,
|
||||
header: {
|
||||
'Content-Type': 'application/json',
|
||||
// 'XDEBUG_TRIGGER': 'true',
|
||||
'token': wx.getStorageSync('token')
|
||||
},
|
||||
success: function (res) {
|
||||
if (res.statusCode == 200) {
|
||||
function ensureLogin() {
|
||||
if (getToken()) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
const app = getAppSafe();
|
||||
if (app && app.loginReady) {
|
||||
return app.loginReady;
|
||||
}
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
if (res.data.errno == 401) {
|
||||
//需要登录后才可以操作
|
||||
function isUnauthorized(statusCode, body) {
|
||||
return statusCode === 401 || !!(body && body.code === 401);
|
||||
}
|
||||
|
||||
// let code = null;
|
||||
// return login().then((res) => {
|
||||
// code = res.code;
|
||||
// return getUserInfo();
|
||||
// }).then((userInfo) => {
|
||||
// //登录远程服务器
|
||||
// request(api.AuthLoginByWeixin, {
|
||||
// code: code,
|
||||
// userInfo: userInfo
|
||||
// }, 'POST').then(res => {
|
||||
// if (res.errno === 0) {
|
||||
// //存储用户信息
|
||||
// wx.setStorageSync('userInfo', res.data.userInfo);
|
||||
// wx.setStorageSync('token', res.data.token);
|
||||
// resolve(res);
|
||||
// } else {
|
||||
// reject(res);
|
||||
// }
|
||||
// }).catch((err) => {
|
||||
// reject(err);
|
||||
// });
|
||||
// }).catch((err) => {
|
||||
// reject(err);
|
||||
// })
|
||||
} else {
|
||||
resolve(res.data);
|
||||
}
|
||||
} else {
|
||||
reject(res.errMsg);
|
||||
/** 登录失效后重新换 token,进行中的重登合并成一次 */
|
||||
function relogin() {
|
||||
const app = getAppSafe();
|
||||
if (app && app.loggingIn && app.loginReady) {
|
||||
return app.loginReady.then(() => !!getToken());
|
||||
}
|
||||
if (reloginTask) {
|
||||
return reloginTask;
|
||||
}
|
||||
reloginTask = login()
|
||||
.then((wxRes) => request(api.AuthLoginByWeixin, { code: wxRes.code }, 'POST', { auth: false }))
|
||||
.then((res) => {
|
||||
if (res && res.code === 1 && res.data && res.data.token) {
|
||||
setToken(res.data.token);
|
||||
if (res.data.userinfo) {
|
||||
wx.setStorageSync('userInfo', res.data.userinfo);
|
||||
}
|
||||
|
||||
},
|
||||
fail: function (err) {
|
||||
reject(err)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error('relogin failed:', err);
|
||||
return false;
|
||||
})
|
||||
.then((ok) => {
|
||||
reloginTask = null;
|
||||
return ok;
|
||||
});
|
||||
return reloginTask;
|
||||
}
|
||||
|
||||
/**
|
||||
* 统一请求
|
||||
* @param {string} url
|
||||
* @param {object} data
|
||||
* @param {string} method
|
||||
* @param {{auth?: boolean, timeout?: number, retried?: boolean}} options
|
||||
* auth 默认 true:没有 token 时等待登录,401 时重登并重试一次
|
||||
* auth 为 false:免登录接口(分类、首页配置等)立即发送,不等待登录
|
||||
*/
|
||||
function request(url, data = {}, method = 'GET', options = {}) {
|
||||
const auth = options.auth !== false;
|
||||
const timeout = options.timeout || REQUEST_TIMEOUT;
|
||||
const retried = !!options.retried;
|
||||
|
||||
const send = () => new Promise((resolve, reject) => {
|
||||
const header = { 'Content-Type': 'application/json' };
|
||||
const token = getToken();
|
||||
if (token) {
|
||||
header.token = token;
|
||||
}
|
||||
wx.request({
|
||||
url,
|
||||
data,
|
||||
method,
|
||||
timeout,
|
||||
header,
|
||||
success(res) {
|
||||
const body = res.data && typeof res.data === 'object'
|
||||
? res.data
|
||||
: { code: 0, msg: '网络异常', data: null };
|
||||
if (res.statusCode === 200 || isUnauthorized(res.statusCode, body)) {
|
||||
resolve({ unauthorized: isUnauthorized(res.statusCode, body), body });
|
||||
return;
|
||||
}
|
||||
reject((body && body.msg) || res.errMsg || '网络异常');
|
||||
},
|
||||
fail(err) {
|
||||
reject(err);
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
const dispatch = () => send().then((result) => {
|
||||
if (result.unauthorized && auth && !retried) {
|
||||
return relogin().then((ok) => {
|
||||
if (!ok) {
|
||||
return result.body;
|
||||
}
|
||||
return request(url, data, method, { auth: true, timeout, retried: true });
|
||||
});
|
||||
}
|
||||
return result.body;
|
||||
});
|
||||
|
||||
if (!auth) {
|
||||
return dispatch();
|
||||
}
|
||||
return ensureLogin().then(dispatch);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -194,40 +277,6 @@ function showSuccessToast(msg) {
|
||||
})
|
||||
}
|
||||
|
||||
function sentRes(url, data, method, fn) {
|
||||
data = data || null;
|
||||
if (data == null) {
|
||||
var content = require('querystring').stringify(data);
|
||||
} else {
|
||||
var content = JSON.stringify(data); //json format
|
||||
}
|
||||
|
||||
var parse_u = require('url').parse(url, true);
|
||||
var isHttp = parse_u.protocol == 'http:';
|
||||
var options = {
|
||||
host: parse_u.hostname,
|
||||
port: parse_u.port || (isHttp ? 80 : 443),
|
||||
path: parse_u.path,
|
||||
method: method,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Content-Length': Buffer.byteLength(content, "utf8"),
|
||||
'Trackingmore-Api-Key': '1b70c67e-d191-4301-9c05-a50436a2526d'
|
||||
}
|
||||
};
|
||||
var req = require(isHttp ? 'http' : 'https').request(options, function (res) {
|
||||
var _data = '';
|
||||
res.on('data', function (chunk) {
|
||||
_data += chunk;
|
||||
});
|
||||
res.on('end', function () {
|
||||
fn != undefined && fn(_data);
|
||||
});
|
||||
});
|
||||
req.write(content);
|
||||
req.end();
|
||||
}
|
||||
|
||||
function loginNow() {
|
||||
let userInfo = wx.getStorageSync('userInfo');
|
||||
if (userInfo == '') {
|
||||
@@ -235,10 +284,10 @@ function loginNow() {
|
||||
success: (res) => {
|
||||
request(api.AuthLoginByWeixin, {
|
||||
code: res.code
|
||||
}, 'POST').then(function (res) {
|
||||
}, 'POST', { auth: false }).then(function (res) {
|
||||
if (res.code === 1) {
|
||||
let userInfo = res.data.userInfo;
|
||||
wx.setStorageSync('token', res.data.token);
|
||||
setToken(res.data.token);
|
||||
wx.setStorageSync('userInfo', userInfo);
|
||||
}
|
||||
});
|
||||
@@ -563,6 +612,8 @@ module.exports = {
|
||||
phoneRegCheck,
|
||||
formatTimeNum: formatTimeNum,
|
||||
request,
|
||||
getToken,
|
||||
setToken,
|
||||
redirect,
|
||||
showErrorToast,
|
||||
showSuccessToast,
|
||||
@@ -570,7 +621,6 @@ module.exports = {
|
||||
login,
|
||||
getUserInfo,
|
||||
testMobile,
|
||||
sentRes,
|
||||
loginNow,
|
||||
getTextLength,
|
||||
transferBorder,
|
||||
|
||||
Reference in New Issue
Block a user