Compare commits

..

No commits in common. "c8c82fb93a407b0e0c8ea822a1c5034ad6aed09e" and "b542e8562441c0f0d1b84c25420c8d46910ece0f" have entirely different histories.

22 changed files with 531 additions and 944 deletions

View File

@ -183,7 +183,6 @@ export default {
onShow: function () {
uni.hideTabBar();
console.log('App Show')
uni.$emit('appShowRefresh')
},
onHide: function () {
console.log('App Hide')
@ -282,4 +281,4 @@ body {
-webkit-text-size-adjust: 100% !important;
text-size-adjust: 100% !important;
}
</style>
</style>

View File

@ -1,92 +0,0 @@
# 改动记录
## 2026-06-12
### 后台长时间运行后首页登录态不同步
问题现象:
- APP 后台运行较长时间后再次进入。
- 商家首页显示未登录或无法及时获取商家信息。
- “我的”页面仍显示已登录。
- 从“我的”页面切回首页后,首页才能正常获取商家信息。
涉及文件:
- `App.vue`
- `pages/home/home.vue`
- `utils/request.js`
改动内容:
- `App.vue`
- 在全局 `onShow` 中新增 `uni.$emit('appShowRefresh')`
- APP 从后台恢复前台时主动通知页面刷新状态,避免只依赖页面级 `onShow`
- `pages/home/home.vue`
- 新增 `refreshPageState` 方法,统一处理首页登录态刷新。
- `onShow`、下拉刷新、APP 前台恢复事件都调用同一套刷新逻辑。
- `onLoad` 注册 `appShowRefresh` 事件。
- `onUnload` 解除 `appShowRefresh` 事件,避免重复监听。
- 有 token 时主动重新请求 `/sj/user/getUser`
- 无 token 时清空 `userInfo`、`authDetails`、`sjId`,并重置 `isUserInfoLoaded`
- `getUserInfo` 请求成功后显式设置 `isLogin = true``isUserInfoLoaded = true`
- `getUserInfo` 请求失败时,如果本地 token 已被清理,则同步首页为未登录状态。
- `utils/request.js`
- `refreshToken` 兼容后端返回结构:
- 支持 token 在 `res.access_token`
- 支持 token 在 `res.data.access_token`
- 刷新 token 成功后同步更新:
- `accessToken`
- `refreshToken`
- `refresh_token_expries`
- 如果刷新接口成功但没有返回 `access_token`,主动抛错,避免写入 `undefined` token。
验证情况:
- 已检查相关 diff未做全文件重构。
- `pages/home/home.vue` 原文件为 CRLF 行尾;为避免整文件行尾改造造成大面积 diff本次保留原行尾。
- 项目 `package.json` 未配置 build/lint 脚本,未执行完整构建校验。
### 订单详情顾客头像被挤压
问题现象:
- `pages/shop/SellerDetail` 页面“顾客信息”一栏中,客户头像在部分图片比例下显示被拉伸或挤压。
涉及文件:
- `pages/shop/SellerDetail.vue`
改动内容:
- 给顾客头像 `<image>` 增加 `mode="aspectFill"`,按头像容器比例裁剪填充,避免原图比例不一致时被拉伸。
- 为 `.shop_photo` 增加 `min-width``min-height`,在 flex 布局中进一步锁定头像为固定正方形尺寸。
验证情况:
- 已执行 `pages/shop/SellerDetail.vue``CHANGE_RECORD.md` 的空白格式检查。
### 核销成功后工时/工位订单详情跳转错误
问题现象:
- 商家扫码核销或输入核销码核销成功后,工时订单和工位订单跳转到详情页时参数或页面类型不正确。
- 工时订单会进入工位详情链路,工位订单会落到普通订单详情链路。
涉及文件:
- `pages/shop/verify/verify-order-detail.vue`
改动内容:
- 新增 `getOrderDetailUrl`,统一按 `order_type` 生成核销成功后的详情页地址。
- `order_type=3` 工时订单跳转到 `/pages/shop/SellerDetail?order_id=...&identity=1`,使用手艺人工时订单详情链路。
- `order_type=4` 工位订单跳转到 `/pages/shop/SellerDetail?order_id=...`,使用商家工位订单详情链路。
- `order_type=6` 自营订单跳转普通订单详情并携带 `serviceType=2`
- 其他普通订单跳转普通订单详情,不再误携带自营参数。
验证情况:
- 已执行 `pages/shop/verify/verify-order-detail.vue``CHANGE_RECORD.md` 的空白格式检查。

View File

@ -2,8 +2,8 @@
"name" : "美融融商家",
"appid" : "__UNI__BBE6285",
"description" : "同城便捷到家美业“技术外卖”服务、同城预约到店服务平台美融融为同城爱美人群提供更优质的更全面的服务。",
"versionName" : "1.0.21",
"versionCode" : 1021,
"versionName" : "1.0.16",
"versionCode" : 1016,
"transformPx" : false,
/* 5+App */
"app-plus" : {

View File

@ -66,19 +66,20 @@
<text class="item-label">服务技能</text>
</view>
<view>
<image
src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/338d957b-cbb6-409b-9e7a-ef5faa0f9b70.png"
mode="widthFix"
style="width:26rpx;margin-top: 26rpx;position: relative;top: 4rpx;left: -10rpx;"
v-if="shouldShowServiceSkillWarningIcon()">
</image>
<text style="margin-right: 16rpx;"
:style="{ color: serviceSkillStatusColor() }">
{{ serviceSkillStatusText() }}
</text>
<image class="arrow-right" src="/static/images/arrow_right.png" mode="aspectFit">
</image>
</view>
<image
src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/338d957b-cbb6-409b-9e7a-ef5faa0f9b70.png"
mode="widthFix"
style="width:26rpx;margin-top: 26rpx;position: relative;top: 4rpx;left: -10rpx;"
v-if="!userInfo.servers_kill_arr || userInfo.servers_kill_arr.length === 0">
</image>
<text style="margin-right: 16rpx;"
:style="{ color: (userInfo.servers_kill_arr && userInfo.servers_kill_arr.length > 0) ? '#c9c9c9' : '#ec5d57' }">
{{ (userInfo.servers_kill_arr && userInfo.servers_kill_arr.length > 0) ? '已设置' :
'待完善' }}
</text>
<image class="arrow-right" src="/static/images/arrow_right.png" mode="aspectFit">
</image>
</view>
</view>
<!-- 门店信息 -->
@ -157,16 +158,17 @@
<text class="item-label">资质信息</text>
</view>
<view>
<image
src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/338d957b-cbb6-409b-9e7a-ef5faa0f9b70.png"
mode="widthFix"
style="width:26rpx;margin-top: 26rpx;position: relative;top: 4rpx;left: -10rpx;"
v-if="shouldShowQualificationWarningIcon()">
</image>
<text style="margin-right: 16rpx;"
:style="{ color: qualificationStatusColor() }">
{{ qualificationStatusText() }}
</text>
<image
src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/338d957b-cbb6-409b-9e7a-ef5faa0f9b70.png"
mode="widthFix"
style="width:26rpx;margin-top: 26rpx;position: relative;top: 4rpx;left: -10rpx;"
v-if="userInfo.credentials_state === 0">
</image>
<text style="margin-right: 16rpx;"
:style="{ color: userInfo.credentials_state === 0 ? '#ec5d57' : userInfo.credentials_state === 1 ? '#e59e45' : '#389930' }">
{{ userInfo.credentials_state === 0 ? '待完善' : userInfo.credentials_state === 1 ? '审核中' :
'已认证' }}
</text>
<image class="arrow-right" src="/static/images/arrow_right.png" mode="aspectFit">
</image>
</view>
@ -197,17 +199,12 @@ import request from "../../utils/request";
export default {
data() {
return {
identity: '',
currentUserId: '', // ID
userInfo: {}, //
authDetails: null,
serviceSkillAuditStatus: null,
isServiceSkillAuditLoaded: false,
qualificationAuditStatus: null,
isQualificationAuditLoaded: false,
sharing: false //
}
},
identity: '',
currentUserId: '', // ID
userInfo: {}, //
sharing: false //
}
},
onLoad() {
//
this.loadIdentity()
@ -495,19 +492,12 @@ export default {
type
})
if (result.data && result.data.id) {
this.userInfo = result.data
this.currentUserId = result.data.id
this.fetchServiceSkillApplyDetails()
this.fetchQualificationApplyDetails()
if (this.isSettled()) {
this.fetchAuthDetails()
} else {
this.authDetails = null
}
//
uni.setStorageSync('userInfo', result.data)
if (result.data && result.data.id) {
this.userInfo = result.data
this.currentUserId = result.data.id
//
uni.setStorageSync('userInfo', result.data)
console.log('从接口获取用户信息成功:', this.userInfo)
} else {
console.log('接口返回数据异常:', result)
@ -522,8 +512,8 @@ export default {
},
//
tryAlternativeUserInfo() {
try {
tryAlternativeUserInfo() {
try {
const app = getApp()
// 1: ID
@ -554,102 +544,10 @@ export default {
console.log('所有获取用户信息的方法都失败了')
} catch (e) {
console.log('备用方案获取用户信息失败:', e)
}
},
fetchAuthDetails() {
return request.post("/sj/userSjAuth/details", {
type: 1,
id_type: '1'
}).then(res => {
if (res.code == 200 && res.data) {
this.authDetails = res.data;
}
return res;
});
},
fetchServiceSkillApplyDetails() {
this.isServiceSkillAuditLoaded = false;
return request.post('/sj/userSjAuth/details', {
apply_type: 2
}).then(res => {
if ((res.code == 200 || res.state == 1) && res.data) {
const status = Number(res.data.apply_state);
this.serviceSkillAuditStatus = Number.isNaN(status) ? null : status;
} else {
this.serviceSkillAuditStatus = null;
}
this.isServiceSkillAuditLoaded = true;
return res;
}).catch(error => {
console.log('获取服务技能申请详情失败:', error);
this.serviceSkillAuditStatus = null;
this.isServiceSkillAuditLoaded = true;
});
},
fetchQualificationApplyDetails() {
this.isQualificationAuditLoaded = false;
return request.post('/sj/userSjAuth/details', {
apply_type: 4
}).then(res => {
if ((res.code == 200 || res.state == 1) && res.data) {
const statusCheck = this.getQualificationApplyStatus(res.data);
this.qualificationAuditStatus = statusCheck.isValid ? statusCheck.status : null;
} else {
this.qualificationAuditStatus = null;
}
this.isQualificationAuditLoaded = true;
return res;
}).catch(error => {
console.log('获取资质信息申请详情失败:', error);
this.qualificationAuditStatus = null;
this.isQualificationAuditLoaded = true;
});
},
isSettled() {
return typeof this.userInfo.id_type !== 'undefined' && this.userInfo.id_type !== 0;
},
isCertified() {
return typeof this.userInfo.id_type !== 'undefined' && this.userInfo.id_type > 0;
},
isUnderReview() {
return this.authDetails && Object.keys(this.authDetails).length > 0;
},
async ensureAuthDetails() {
if (this.identity != '2' || !this.isSettled() || this.isUnderReview()) {
return;
}
await this.fetchAuthDetails();
},
getQualificationApplyStatus(detail) {
const status = Number(detail.apply_state);
if (Number.isNaN(status)) {
return {
isValid: false,
status: null
};
}
if (status === 2) {
return {
isValid: true,
status
};
}
return {
isValid: true,
status
};
},
loadIdentity() {
}
},
loadIdentity() {
//
const app = getApp()
const globalIdentity = app.globalData.artisanType
@ -732,80 +630,45 @@ export default {
})
},
async navigateToQualification() {
if (this.identity != '2' || this.isCertified()) {
uni.navigateTo({
url: '/pages/shop/qualification_sj_change'
});
return;
}
await this.ensureAuthDetails();
if (!this.isSettled()) {
uni.navigateTo({
url: '/pages/ruzhu/ruzhu'
});
} else if (this.isUnderReview()) {
uni.navigateTo({
url: '/pages/ruzhu/ruzhu?type=1'
});
} else {
uni.navigateTo({
url: '/pages/ruzhu/ruzhu?step=3'
});
}
},
navigateToBelongShop() { //
uni.navigateTo({
url: '/pages/artisan/belong_shop'
})
},
hasServiceSkills() {
return this.userInfo.servers_kill_arr && this.userInfo.servers_kill_arr.length > 0;
},
serviceSkillStatusText() {
if (this.serviceSkillAuditStatus === 1) return '审核中';
if (this.serviceSkillAuditStatus === 3) return '审核未通过';
return this.hasServiceSkills() ? '已设置' : '待完善';
},
serviceSkillStatusColor() {
const statusText = this.serviceSkillStatusText();
if (statusText === '审核未通过' || statusText === '待完善') return '#ec5d57';
if (statusText === '审核中') return '#e59e45';
return '#c9c9c9';
},
shouldShowServiceSkillWarningIcon() {
const statusText = this.serviceSkillStatusText();
return statusText === '审核未通过' || statusText === '待完善';
},
getCredentialsState() {
const state = Number(this.userInfo.credentials_state);
return Number.isNaN(state) ? null : state;
},
qualificationStatusText() {
if (!this.isQualificationAuditLoaded) return '';
if (this.qualificationAuditStatus === 1) return '审核中';
if (this.qualificationAuditStatus === 2) return '已认证';
if (this.qualificationAuditStatus === 3) return '审核未通过';
const credentialsState = this.getCredentialsState();
if (credentialsState === 0) return '待完善';
if (credentialsState === 1) return '审核中';
if (this.userInfo.id_type < 0) return '审核未通过';
return '已认证';
},
qualificationStatusColor() {
const statusText = this.qualificationStatusText();
if (statusText === '审核未通过' || statusText === '待完善') return '#ec5d57';
if (statusText === '审核中') return '#e59e45';
return '#389930';
},
shouldShowQualificationWarningIcon() {
const statusText = this.qualificationStatusText();
return statusText === '审核未通过' || statusText === '待完善';
}
}
}
navigateToQualification() {
const idType = this.userInfo.id_type;
const credentialsState = this.userInfo.credentials_state;
if (idType === 0 && credentialsState === 0) {
//
uni.navigateTo({
url: '/pages/ruzhu/ruzhu'
});
} else if (idType > 0 && credentialsState === 0) {
// +
uni.navigateTo({
url: '/pages/shop/qualification_sj_change'
});
} else if (idType > 0 && credentialsState === 1) {
// +
uni.navigateTo({
url: '/pages/shop/qualification_sj_change'
});
} else if (idType > 0 && credentialsState === 2) {
// +
uni.navigateTo({
url: '/pages/shop/qualification_sj_change'
});
} else if (idType < 0 && credentialsState === 1) {
// +
uni.navigateTo({
url: '/pages/ruzhu/ruzhu?type=1'
});
}
},
navigateToBelongShop() { //
uni.navigateTo({
url: '/pages/artisan/belong_shop'
})
}
}
}
</script>
<style>
@ -987,4 +850,4 @@ export default {
width: 11rpx;
height: 22rpx;
}
</style>
</style>

View File

@ -187,7 +187,7 @@ export default {
}
.brand-name {
font-size: 28rpx;
font-size: 26rpx;
font-weight: 500;
color: #333333;
line-height: 34rpx;

View File

@ -88,7 +88,7 @@ export default {
<style lang="scss" scoped>
.skill-item {
display: flex;
margin-bottom: 30rpx;
margin-bottom: 20rpx;
&:last-child {
margin-bottom: 0;
@ -133,7 +133,7 @@ export default {
overflow: hidden;
font-size: 28rpx;
color: #333;
font-weight: 500;
font-weight: 400;
line-height: 40rpx;
}
@ -193,4 +193,4 @@ export default {
-webkit-line-clamp: 2;
overflow: hidden;
}
</style>
</style>

View File

@ -128,7 +128,7 @@
</view>
<view class="stat-item">
<text class="num">{{ orderBasic.finished }}</text>
<text class="label">取消</text>
<text class="label">完成</text>
</view>
</view>
</view>
@ -196,7 +196,7 @@
<view class="brands-section card-box">
<view class="card-header">
<view class="header-left"><text class="title" style="margin-left: 10rpx;">精选品牌</text></view>
<view class="header-right brand-more" @tap="goToBrandList">更多品牌 <image class="more-right-icon"
<view class="header-right" @tap="goToBrandList">更多品牌 <image class="more-right-icon"
src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/ee119e24-1cb2-43df-86e6-61af8e9fd0ad.png">
</image>
</view>
@ -401,11 +401,24 @@ export default {
}
},
onShow() {
this.refreshPageState();
//
this.isLogin = uni.getStorageSync("accessToken") ? true : false;
if (this.isLogin) {
this.getUserInfo();
}
//
this.fetchNoticeList();
this.fetchBrandList();
this.fetchSkillList();
},
onPullDownRefresh() {
// 1.
this.refreshPageState();
if (this.isLogin) {
this.getUserInfo();
}
this.fetchNoticeList();
this.fetchBrandList();
this.fetchSkillList();
// 2.
setTimeout(() => {
@ -414,10 +427,6 @@ export default {
},
onLoad() {
uni.hideTabBar();
uni.$on('appShowRefresh', this.refreshPageState);
},
onUnload() {
uni.$off('appShowRefresh', this.refreshPageState);
},
watch: {
'orderDetail.score'() {
@ -425,22 +434,6 @@ export default {
}
},
methods: {
refreshPageState() {
const hasToken = !!uni.getStorageSync("accessToken");
this.isLogin = hasToken;
if (hasToken) {
this.getUserInfo();
} else {
this.userInfo = {};
this.authDetails = null;
this.isUserInfoLoaded = false;
this.sjId = null;
}
//
this.fetchNoticeList();
this.fetchBrandList();
this.fetchSkillList();
},
//
formatMoney(amount) {
let num = parseFloat(amount);
@ -596,11 +589,9 @@ export default {
},
getUserInfo() {
this.isUserInfoLoaded = false;
return request.post("/sj/user/getUser").then((result) => {
request.post("/sj/user/getUser").then((result) => {
if (result.code == 200 && result.data) {
this.userInfo = result.data;
this.isLogin = true;
this.isUserInfoLoaded = true; // UI
uni.setStorageSync("sjId", result.data.id);
this.sjId = result.data.id;
@ -616,15 +607,6 @@ export default {
this.fetchAuthDetails();
}
}
}).catch((err) => {
if (!uni.getStorageSync("accessToken")) {
this.isLogin = false;
this.userInfo = {};
this.authDetails = null;
this.sjId = null;
}
this.isUserInfoLoaded = false;
console.error("首页获取商家信息失败:", err);
});
},
@ -783,7 +765,8 @@ export default {
// /
toggleStatus() {
const isCurrentlyResting = !this.isOpenStore; //
const currentStatus = this.userInfo.order_taking;
const isCurrentlyResting = currentStatus != 1; //
//
if (isCurrentlyResting && !this.canOpenStore) {
@ -792,7 +775,7 @@ export default {
}
//
let newStatus = this.isOpenStore ? 2 : 1;
let newStatus = currentStatus == 1 ? 2 : 1;
// Loading
uni.showLoading({
@ -1084,14 +1067,10 @@ page {
.header-right {
font-weight: 400;
font-size: 24rpx;
font-size: 22rpx;
color: #666666;
line-height: 28rpx;
}
.brand-more {
font-size: 24rpx;
}
}
.header-section {
@ -1462,7 +1441,7 @@ page {
.notice-btn {
// font-weight: 400;
font-size: 22rpx;
font-size: 20rpx;
color: #8D4C1B;
padding: 6rpx 18rpx;
border-radius: 30rpx;
@ -1600,4 +1579,4 @@ page {
overflow: hidden;
}
}
</style>
</style>

View File

@ -3,12 +3,8 @@
<custom-navbar :title="info.name || '品牌详情'"
:leftImg="'https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/60ae3383-6ff6-4f42-818b-d9b09a9bd0e0.png'"
:showUser="true" backgroundColor="#ffffff" titleColor="#333" borderBottom="none">
<template #right>
<view class="collect-btn" @click="toggleCollectStatus">
<text class="collect-icon" :class="{ active: isCollected }"></text>
</view>
</template>
:showUser="true" backgroundColor="#ffffff" titleColor="#333" borderBottom="none" :show-headle="true"
:headleSrc="isCollected ? iconCollectOn : iconCollectOff" @onHeadleClick="toggleCollectStatus">
</custom-navbar>
<!-- 顶部导航栏扩展动态计算位置的拨号图标 -->
@ -725,31 +721,6 @@ export default {
position: relative;
}
.brand-detail-page ::v-deep .right-area {
border: none;
border-radius: 0;
background: transparent;
}
.collect-btn {
width: 46rpx;
height: 46rpx;
display: flex;
align-items: center;
justify-content: center;
background: transparent;
}
.collect-icon {
font-size: 42rpx;
line-height: 46rpx;
color: #C9CDD4;
&.active {
color: #FF4767;
}
}
/* 导航栏左侧新增动态拨号图标 */
.nav-phone-wrap {
position: fixed;
@ -946,7 +917,7 @@ export default {
line-height: 37rpx;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 10;
-webkit-line-clamp: 19;
overflow: hidden;
white-space: pre-line;
@ -1366,4 +1337,4 @@ export default {
font-size: 32rpx;
color: #333333;
}
</style>
</style>

View File

@ -28,16 +28,16 @@
<view class="sort-item" @tap="toggleSort('time')">
<text class="sort-text" :class="{ active: orderType === 1 || orderType === 2 }">发布时间</text>
<view class="arrows">
<image class="arrow-icon" :src="orderType === 2 ? iconPinkUp : iconGreyUp"></image>
<image class="arrow-icon" :src="orderType === 1 ? iconPinkDown : iconGreyDown"></image>
<image class="arrow-icon" :src="orderType === 1 ? iconPinkUp : iconGreyUp"></image>
<image class="arrow-icon" :src="orderType === 2 ? iconPinkDown : iconGreyDown"></image>
</view>
</view>
<view class="sort-item" @tap="toggleSort('view')">
<text class="sort-text" :class="{ active: orderType === 3 || orderType === 4 }">浏览量</text>
<view class="arrows">
<image class="arrow-icon" :src="orderType === 4 ? iconPinkUp : iconGreyUp"></image>
<image class="arrow-icon" :src="orderType === 3 ? iconPinkDown : iconGreyDown"></image>
<image class="arrow-icon" :src="orderType === 3 ? iconPinkUp : iconGreyUp"></image>
<image class="arrow-icon" :src="orderType === 4 ? iconPinkDown : iconGreyDown"></image>
</view>
</view>
</view>
@ -153,21 +153,9 @@ export default {
// ============ ============
toggleSort(type) {
if (type === 'time') {
if (this.orderType === 1) {
this.orderType = 2;
} else if (this.orderType === 2) {
this.orderType = 0;
} else {
this.orderType = 1;
}
this.orderType = this.orderType === 1 ? 2 : 1;
} else if (type === 'view') {
if (this.orderType === 3) {
this.orderType = 4;
} else if (this.orderType === 4) {
this.orderType = 0;
} else {
this.orderType = 3;
}
this.orderType = this.orderType === 3 ? 4 : 3;
}
this.refreshBrandList();
},
@ -206,7 +194,6 @@ export default {
if (this.activeId === id) return;
this.activeId = id;
this.currentSecondClass = "";
this.selectedSecondIds = [];
this.getSecondClassList();
this.refreshBrandList();
},
@ -230,12 +217,6 @@ export default {
});
if (this.$refs.brandListRef) {
// CommonList queryData
['first_class', 'second_class', 'order_type'].forEach(key => {
if (!Object.prototype.hasOwnProperty.call(params, key) && this.$refs.brandListRef.queryData) {
this.$delete(this.$refs.brandListRef.queryData, key);
}
});
this.$refs.brandListRef.manualRefresh(params);
}
},
@ -541,4 +522,4 @@ export default {
width: 36rpx !important;
height: 36rpx !important;
}
</style>
</style>

View File

@ -28,16 +28,16 @@
<view class="sort-item" @tap="toggleSort('time')">
<text class="sort-text" :class="{ active: orderType === 1 || orderType === 2 }">发布时间</text>
<view class="arrows">
<image class="arrow-icon" :src="orderType === 2 ? iconPinkUp : iconGreyUp"></image>
<image class="arrow-icon" :src="orderType === 1 ? iconPinkDown : iconGreyDown"></image>
<image class="arrow-icon" :src="orderType === 1 ? iconPinkUp : iconGreyUp"></image>
<image class="arrow-icon" :src="orderType === 2 ? iconPinkDown : iconGreyDown"></image>
</view>
</view>
<view class="sort-item" @tap="toggleSort('view')">
<text class="sort-text" :class="{ active: orderType === 3 || orderType === 4 }">浏览量</text>
<view class="arrows">
<image class="arrow-icon" :src="orderType === 4 ? iconPinkUp : iconGreyUp"></image>
<image class="arrow-icon" :src="orderType === 3 ? iconPinkDown : iconGreyDown"></image>
<image class="arrow-icon" :src="orderType === 3 ? iconPinkUp : iconGreyUp"></image>
<image class="arrow-icon" :src="orderType === 4 ? iconPinkDown : iconGreyDown"></image>
</view>
</view>
</view>
@ -176,11 +176,9 @@ export default {
toggleSort(type) {
if (type === 'time') {
if (this.orderType === 1) this.orderType = 2
else if (this.orderType === 2) this.orderType = 0
else this.orderType = 1
} else if (type === 'view') {
if (this.orderType === 3) this.orderType = 4
else if (this.orderType === 4) this.orderType = 0
else this.orderType = 3
}
this.fetchData(true)
@ -466,7 +464,7 @@ export default {
}
.list-container {
padding: 0 24rpx 30rpx;
padding: 30rpx 24rpx;
}
.filter-panel {
@ -576,4 +574,4 @@ export default {
width: 36rpx !important;
height: 36rpx !important;
}
</style>
</style>

View File

@ -70,9 +70,12 @@
</view>
<view class="article-content-wrapper">
<view class="article-content">
<view class="article-content" v-if="article.htmlContent">
<rich-text :nodes="formattedHtmlContent"></rich-text>
</view>
<view class="empty-content" v-else>
<text class="empty-text">暂无图文介绍</text>
</view>
</view>
<view class="recommend-section" v-if="recommendList.length > 0">

View File

@ -363,7 +363,7 @@ export default {
title: "",
id_type: 1,
self_state: false,
url: "https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/545f2db0-d66a-41ca-b1f5-6a28469e65ba.png",
url: "https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/30b42fe6-21f9-443f-a091-5439d57e3593.png",
path: "/pages/selfOperated/agreement?title=平台自营项目介绍&type=18",
},
{
@ -761,13 +761,10 @@ export default {
request.post("/sj/user/getUser").then((result) => {
this.userInfo = result.data;
uni.setStorageSync("syrId", result.data.id);
//
const isCertified = result.data.credentials_state === 2 ||
(result.data.id_type > 0 && result.data.credentials_state === 0);
const allReady = result.data.business_time &&
result.data.servers_kill_arr &&
result.data.servers_kill_arr.length > 0 &&
isCertified;
result.data.credentials_state === 2;
const mgmtCard = this.cardList.find(c => c.title === "管理中心");
if (mgmtCard) {
const shopItem = mgmtCard.list.find(i => i.title === "店铺装修");
@ -786,53 +783,15 @@ export default {
},
//
fetchAuthDetails() {
return request.post("/sj/userSjAuth/details", {
request.post("/sj/userSjAuth/details", {
type: 1,
id_type: '1'
}).then(res => {
if (res.code == 200 && res.data) {
this.authDetails = res.data;
}
return res;
});
},
async ensureAuthDetails() {
if (!this.isSettled || (this.authDetails && Object.keys(this.authDetails).length > 0)) {
return;
}
await this.fetchAuthDetails();
},
navigateToCertificationForm() {
if (this.isSettled) {
uni.navigateTo({
url: '/pages/ruzhu/ruzhu?step=3'
});
} else {
uni.navigateTo({
url: '/pages/ruzhu/ruzhu'
});
}
},
async navigateToCertificationProcess() {
if (this.isCertified) {
uni.navigateTo({
url: '/pages/shop/qualification_sj_change'
});
return;
}
await this.ensureAuthDetails();
if (!this.isSettled) {
uni.navigateTo({
url: '/pages/ruzhu/ruzhu'
});
} else if (this.isUnderReview) {
uni.navigateTo({
url: '/pages/ruzhu/ruzhu?type=1'
});
} else {
this.navigateToCertificationForm();
}
},
async goLogin() {
// 访
if (this.isAccountDisabled) {
@ -884,12 +843,6 @@ export default {
// 2.
if (!this.isLogin) {
if (item.path == "/pages/ruzhu/ruzhu") {
uni.navigateTo({
url: "/pages/blogPopup/blogPopup",
});
return;
}
uni.showToast({
title: `您暂未登录,无法使用${item.title || item.text || ''}`,
icon: "none",
@ -968,7 +921,39 @@ export default {
});
},
toruzhu() {
this.navigateToCertificationProcess();
const idType = this.userInfo.id_type;
const credentialsState = this.userInfo.credentials_state;
if (idType < 0 && credentialsState <= 1) {
//
uni.navigateTo({
url: '/pages/ruzhu/ruzhu?type=1'
});
} else if (idType <= 0 && credentialsState === 0) {
//
uni.navigateTo({
url: '/pages/ruzhu/ruzhu'
});
} else if (idType > 0 && credentialsState === 0) {
// +
uni.navigateTo({
url: '/pages/shop/qualification_sj_change'
});
} else if (idType > 0 && credentialsState === 1) {
// +
uni.navigateTo({
url: '/pages/shop/qualification_sj_change'
});
} else if (idType > 0 && credentialsState === 2) {
// +
uni.navigateTo({
url: '/pages/shop/qualification_sj_change'
});
} else if (idType < 0 && credentialsState === 1) {
// +
uni.navigateTo({
url: '/pages/ruzhu/ruzhu?type=1'
});
}
},
closeSetupModal() {
this.showSetupModal = false;
@ -987,7 +972,21 @@ export default {
},
goToAuth() {
this.showSetupModal = false;
this.navigateToCertificationProcess();
if (this.isUnderReview) {
uni.navigateTo({
url: '/pages/ruzhu/ruzhu?type=1'
});
} else {
if (this.isSettled) {
uni.navigateTo({
url: '/pages/ruzhu/ruzhu?step=3'
});
} else {
uni.navigateTo({
url: '/pages/ruzhu/ruzhu'
});
}
}
},
goToInviteList() {
// 访
@ -1706,7 +1705,7 @@ button::after {
gap: 12rpx;
margin-top: 10rpx;
width: auto;
height: 46rpx;
height: 36rpx;
padding: 0 8rpx 0 8rpx;
background-image: url('https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/378a6936-a543-4ff5-9aa0-cfcb4d4e14b3.png');
background-size: 100% 100%;
@ -1892,4 +1891,4 @@ button::after {
}
}
}
</style>
</style>

View File

@ -1,5 +1,5 @@
<template>
<view class="order-list-page">
<view class="order-list-page" style="background-color: #fafafa">
<view class="status" v-if="isLogin">
<scroll-view scroll-x class="status-tabs" :show-scrollbar="false">
@ -21,7 +21,7 @@
</view>
</scroll-view>
</view>
<view class="status-gap"></view>
<view style="background-color: #f5f5f5; height: 20rpx"></view>
<CommonList nList ref="groupRef" :isLogin="isLogin" :apiUrl="apiUrl"
:listScrollHeight="`calc(100vh - 280rpx - 20rpx)`" @load-success="loadSuccess" class="nodatamit">
<template #listData="{ list }" class="commit">
@ -41,12 +41,10 @@
<view class="noDataBox">
<noData tipText="暂无服务订单哟~" v-if="isLogin"></noData>
<view class="nologin_part" v-else>
<image
src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/15e33bab-8868-40bf-935b-a9ee9ca3c0d2.png"
class="nologin_icon"
mode="aspectFit"
@click="goLogin"
></image>
<image src="/static/images/no_login.png" class="nologin_icon" mode="aspectFit"></image>
<view class="btn-login" @click="goLogin">
<text class="login-text">前去登录</text>
</view>
</view>
</view>
</template>
@ -572,7 +570,6 @@ export default {
min-height: 100vh;
display: flex;
flex-direction: column;
background-color: #FAFAFA;
}
/* 状态标签栏 (移植自用户端示例) */
@ -657,7 +654,7 @@ export default {
/* 数据列表及卡片外框样式 */
.order-item-wrap {
background-color: #FAFAFA;
background-color: #f5f5f5;
overflow: hidden;
}
@ -672,15 +669,33 @@ export default {
/* 未登录状态的样式 */
.nologin_part {
display: flex;
flex-flow: column nowrap;
justify-content: center;
align-items: center;
width: 100%;
height: 100%;
}
.nologin_icon {
width: 422rpx;
height: 378rpx;
width: 360rpx;
height: 360rpx;
margin-top: 100rpx;
margin-bottom: 40rpx;
}
.btn-login {
width: 200rpx;
height: 68rpx;
background-color: #ff4767;
border-radius: 34rpx;
display: flex;
flex-flow: row nowrap;
justify-content: center;
align-items: center;
box-shadow: 0 4rpx 10rpx rgba(255, 71, 103, 0.3);
}
.login-text {
font-size: 30rpx;
color: #fff;
}
::v-deep .list-scroll {
@ -690,11 +705,6 @@ export default {
}
.nodatamit {
background-color: #FAFAFA;
background-color: #f5f5f5;
}
.status-gap {
background-color: #FAFAFA;
height: 20rpx;
}
</style>
</style>

View File

@ -124,6 +124,7 @@ export default {
textData: {},
loading: false,
error: null,
navTitle: '商家入驻', //
qualificationData: null, //
storeInfoData: null, //
successData: {}, //
@ -142,9 +143,6 @@ export default {
if (this.currentStep === 3) return 2;
if (this.currentStep === 4) return 2;
return 0;
},
navTitle() {
return this.currentStep === 3 ? '资质认证' : '商家入驻';
}
},
async onLoad(options) {
@ -156,9 +154,6 @@ export default {
if (options.type == 1) {
this.currentStep = 4
}
if (options.type == 2) {
this.currentStep = 2
}
// step
if (options.step) {

View File

@ -42,7 +42,7 @@ export default {
} else {
this.infoData = {
top: '审核结果',
title: '审核未通过',
title: '审核失败',
photo: res.data.photo
};
this.$emit('stateChange', 3);
@ -114,7 +114,6 @@ export default {
line-height: 67rpx;
text-align: center;
font-style: normal;
margin-top: -40rpx;
}
.title-content {

View File

@ -21,16 +21,16 @@
<view class="sort-item" @tap="toggleSort('time')">
<text class="sort-text" :class="{ active: orderType === 1 || orderType === 2 }">发布时间</text>
<view class="arrows">
<image class="arrow-icon" :src="orderType === 2 ? iconPinkUp : iconGreyUp"></image>
<image class="arrow-icon" :src="orderType === 1 ? iconPinkDown : iconGreyDown"></image>
<image class="arrow-icon" :src="orderType === 1 ? iconPinkUp : iconGreyUp"></image>
<image class="arrow-icon" :src="orderType === 2 ? iconPinkDown : iconGreyDown"></image>
</view>
</view>
<view class="sort-item" @tap="toggleSort('view')">
<text class="sort-text" :class="{ active: orderType === 3 || orderType === 4 }">浏览量</text>
<view class="arrows">
<image class="arrow-icon" :src="orderType === 4 ? iconPinkUp : iconGreyUp"></image>
<image class="arrow-icon" :src="orderType === 3 ? iconPinkDown : iconGreyDown"></image>
<image class="arrow-icon" :src="orderType === 3 ? iconPinkUp : iconGreyUp"></image>
<image class="arrow-icon" :src="orderType === 4 ? iconPinkDown : iconGreyDown"></image>
</view>
</view>
</view>
@ -150,21 +150,9 @@ export default {
//
toggleSort(type) {
if (type === 'time') {
if (this.orderType === 1) {
this.orderType = 2;
} else if (this.orderType === 2) {
this.orderType = 0;
} else {
this.orderType = 1;
}
this.orderType = this.orderType === 1 ? 2 : 1;
} else if (type === 'view') {
if (this.orderType === 3) {
this.orderType = 4;
} else if (this.orderType === 4) {
this.orderType = 0;
} else {
this.orderType = 3;
}
this.orderType = this.orderType === 3 ? 4 : 3;
}
//
@ -451,4 +439,4 @@ export default {
font-size: 24rpx;
color: #999;
}
</style>
</style>

View File

@ -74,7 +74,7 @@
<view class="card_title" v-if="identity==0">顾客信息</view>
<view class="card_title" v-if="identity==1">店铺信息</view>
<view class="shop_title_box">
<image class="shop_photo" :src="orderInfo.head_photo" mode="aspectFill" />
<image class="shop_photo" :src="orderInfo.head_photo" />
<view class="left-section">
<view class="shop_title">{{ orderInfo.name }}</view>
<text class="shop_phone" @click="contactService(orderInfo.phone)">
@ -906,8 +906,6 @@
.shop_photo {
width: 70rpx;
height: 70rpx;
min-width: 70rpx;
min-height: 70rpx;
border-radius: 50%;
flex-shrink: 0;
}
@ -1075,4 +1073,4 @@
.mt_10 {
margin-top: 10rpx;
}
</style>
</style>

View File

@ -240,12 +240,6 @@ export default {
},
isCertified() {
if (!this.isLogin || typeof this.userInfo.id_type === 'undefined') return false;
if (typeof this.userInfo.credentials_state !== 'undefined' && this.userInfo.credentials_state !== null) {
const credentialsState = Number(this.userInfo.credentials_state);
if (!Number.isNaN(credentialsState)) {
return credentialsState === 2 || (this.userInfo.id_type > 0 && credentialsState === 0);
}
}
return this.userInfo.id_type > 0;
},
hasBusinessTime() {
@ -314,11 +308,6 @@ export default {
}).then(res => {
if (res.code == 200 && res.data) {
this.authDetails = res.data;
if (!this.userInfo.business_time && res.data.business_time) {
this.currentTime = res.data.business_time;
this.originalTime = res.data.business_time;
this.parseTimeString(res.data.business_time);
}
}
});
},
@ -357,22 +346,15 @@ export default {
// /
toggleStatus() {
if (!this.isCertified) {
uni.showToast({ title: '请完成资质认证', icon: 'none' });
return;
}
const currentStatus = this.userInfo.order_taking;
const isCurrentlyResting = currentStatus != 1; //
//
if (!this.isSettled) {
uni.showToast({ title: '请先完成入驻', icon: 'none' });
return;
}
//
let newStatus = currentStatus == 1 ? 2 : 1;
//
let newStatus = this.isOpenStore ? 2 : 1;
if (newStatus === 1 && !this.canOpenStore) {
uni.showToast({ title: '当前资料不完善,无法开启接单', icon: 'none' });
//
if (newStatus === 1 && !this.hasBusinessTime) {
uni.showToast({ title: '请配置营业时间', icon: 'none' });
return;
}
@ -521,21 +503,9 @@ export default {
// 使 code
if (res.code === 200) {
const savedTime = this.currentTime;
this.showBottomActions = false
this.tempTime = ''
this.originalTime = savedTime //
this.userInfo = {
...(this.userInfo || {}),
business_time: savedTime
}
if (this.authDetails) {
this.authDetails = {
...this.authDetails,
business_time: savedTime
}
}
this.parseTimeString(savedTime)
this.originalTime = this.currentTime //
uni.showToast({
title: '营业时间更新成功',
@ -1081,4 +1051,4 @@ export default {
background: linear-gradient(135deg, #FF4767, #FF6B8A);
color: white;
}
</style>
</style>

View File

@ -149,30 +149,26 @@ export default {
},
//
shouldShowRejectReason() {
//
return Number(this.auditStatus) === 3 &&
//
return this.auditStatus === 3 &&
!this.showPendingSkills &&
!this.hasChanges &&
this.backText;
//
!this.hasPendingApply();
},
//
hasPendingApply() {
if (!this.lastApplyTime) return false;
//
return true;
},
// /
isChangeUnderReview() {
return Number(this.auditStatus) === 1 ||
Number(this.auditStatus) === 3 ||
this.showAuditTip ||
this.buttonType === 'view';
}
},
async onLoad() {
this.sjInformation = await request.post('/sj/user/getUser');
await this.initPage();
//
if (this.currentSkills.length === 0 && !this.originalMajor && !this.isChangeUnderReview) {
if (this.currentSkills.length === 0 && !this.originalMajor) {
this.startChange();
}
},
@ -311,8 +307,7 @@ export default {
if (res.code === 200 && res.data) {
const detail = res.data;
this.applyId = detail.id;
const auditStatus = Number(detail.apply_state);
this.auditStatus = Number.isNaN(auditStatus) ? null : auditStatus;
this.auditStatus = detail.apply_state;
this.backText = detail.back_text || ''; //
console.log('审核状态:', this.auditStatus);
@ -965,4 +960,4 @@ export default {
width: 33.333%;
}
} */
</style>
</style>

View File

@ -19,7 +19,7 @@
<image class="avatar" :src="sryDetail.head_photo" mode="aspectFill"></image>
<view class="user-detail">
<view class="flex-row-center-between">
<text class="user-name">{{ sryDisplayName }}</text>
<text class="user-name">{{ sryDetail.name }}</text>
<view class="enter-btn flex-row-center" @click="goDetail">进入详情</view>
</view>
<view class="tags">
@ -117,9 +117,6 @@ export default {
}
},
computed: {
sryDisplayName() {
return this.sryDetail.nick_name || this.sryDetail.name || "";
},
mergeServiceList() {
// 1.
let allSubArrays = Object.values(this.$store.state.sjServiceList);
@ -490,4 +487,4 @@ export default {
::v-deep .navbar-content .title {
margin-left: 20rpx !important;
}
</style>
</style>

View File

@ -59,9 +59,8 @@
</scroll-view>
<view class="bottom-btn-wrapper">
<view class="confirm-btn" @tap="isVerified ? goHomePage() : confirmVerify()"
:class="{ 'btn-disabled': isVerifying }">
<text class="btn-text">{{ isVerified ? '核销成功,返回首页' : (isVerifying ? '核销中...' : '确认核销') }}</text>
<view class="confirm-btn" @tap="confirmVerify" :class="{ 'btn-disabled': isVerifying }">
<text class="btn-text">{{ isVerifying ? '核销中...' : '确认核销' }}</text>
</view>
</view>
</view>
@ -102,9 +101,7 @@ export default {
payPrice: 0,
settlePrice: 0
},
isVerifying: false,
isVerified: false, //
userInfo: {} // sjid
isVerifying: false
};
},
onLoad(options) {
@ -127,23 +124,6 @@ export default {
console.log('未获取到订单信息');
}
},
async onShow() {
//
if (this.orderData.orderId) {
// sjid
if (!this.userInfo.id) {
try {
const res = await request.post('/user/getuser', { type: 3 });
if (res.data) {
this.userInfo = res.data;
}
} catch (e) {
console.error('获取用户信息失败', e);
}
}
this.checkVerifyStatus();
}
},
methods: {
// /sj/poster/getOrderByCode data
mapOrderData(data) {
@ -172,63 +152,6 @@ export default {
goBack() {
uni.navigateBack();
},
//
checkVerifyStatus() {
if (!this.orderData.orderId) return;
//
const orderType = this.orderData.orderType;
let detailUrl = '';
let params = { id: this.orderData.orderId };
if (orderType == 3) {
//
detailUrl = '/syr/workHourOrder/details';
} else if (orderType == 4) {
//
detailUrl = '/sj/workSeatOrder/details';
} else if (orderType == 6) {
//
detailUrl = '/sj/orderSelf/details';
params.sjid = this.userInfo.id || ''; // sjid
} else {
// (orderType 1, 2, 5)
detailUrl = '/sj/yhorderdetail';
params.sjid = this.userInfo.id || '';
}
request.post(detailUrl, params).then(res => {
if (res.code === 200 && res.data) {
const orderState = res.data.state;
// 1/2/3 4/5/6/7
if (orderState >= 4) {
this.isVerified = true;
}
}
}).catch(err => {
console.error('检查核销状态失败', err);
});
},
//
goHomePage() {
uni.switchTab({
url: '/pages/home/home'
});
},
getOrderDetailUrl() {
const orderId = this.orderData.orderId;
const orderType = this.orderData.orderType;
if (orderType == 3) {
return `/pages/shop/SellerDetail?order_id=${orderId}&identity=1`;
}
if (orderType == 4) {
return `/pages/shop/SellerDetail?order_id=${orderId}`;
}
if (orderType == 6) {
return `/pages/shop/userorder-detail?order_id=${orderId}&serviceType=2`;
}
return `/pages/shop/userorder-detail?order_id=${orderId}`;
},
confirmVerify() {
if (this.isVerifying) return;
if (!this.orderData.orderId) {
@ -259,10 +182,16 @@ export default {
uni.hideLoading();
if (res.code === 200) {
uni.showToast({ title: '核销成功', icon: 'success' });
this.isVerified = true;
this.isVerifying = false;
//
const url = this.getOrderDetailUrl();
const orderId = this.orderData.orderId;
const orderType = this.orderData.orderType;
let url = '';
if (orderType == 3) {
url = `/pages/shop/SellerDetail?order_id=${orderId}`;
} else if (orderType == 2 || orderType == 5) {
url = `/pages/shop/userorder-detail?order_id=${orderId}&serviceType=2`;
} else {
url = `/pages/shop/userorder-detail?order_id=${orderId}`;
}
setTimeout(() => {
uni.navigateTo({ url });
}, 1500);
@ -570,4 +499,4 @@ export default {
.btn-disabled {
opacity: 0.6;
}
</style>
</style>

View File

@ -1,66 +1,78 @@
import { getToken, setToken, removeToken } from "./auth";
import { setVersion } from "../utils/version.js";
import { getBaseUrl } from "../utils/version.js";
import {
getToken,
setToken,
removeToken
} from './auth'
import {
setVersion
} from '../utils/version.js'
import {
getBaseUrl
} from '../utils/version.js'
let baseURL;
setVersion();
setVersion()
let isRefreshing = false;
let subscribers = [];
let isRefreshing = false
let subscribers = []
// 订阅 Token 刷新
function subscribeTokenRefresh(cb) {
subscribers.push(cb);
subscribers.push(cb)
}
// 发布 Token 刷新完成
function onRrefreshed(token) {
subscribers.forEach((cb) => cb(token));
subscribers = [];
subscribers.forEach(cb => cb(token))
subscribers = []
}
// 请求拦截器
const requestInterceptor = (options) => {
// 获取token
const token = uni.getStorageSync("accessToken");
if (token) {
options.header = {
...options.header,
Authorization: `Bearer ${token}`,
};
}
// 获取token
const token = uni.getStorageSync('accessToken')
if (token) {
options.header = {
...options.header,
'Authorization': `Bearer ${token}`
}
}
// #ifdef H5
// H5端跨域处理
options.header = {
...options.header,
"Access-Control-Allow-Origin": "*",
};
// #endif
// #ifdef H5
// H5端跨域处理
options.header = {
...options.header,
'Access-Control-Allow-Origin': '*'
}
// #endif
return options;
};
return options
}
// 响应拦截器
// 响应拦截器
const responseInterceptor = async (options, response, resolve, reject) => {
const { statusCode, data } = response;
// 请求成功
if (statusCode >= 200 && statusCode < 300) {
return data;
}
const {
statusCode,
data
} = response
// 请求成功
if (statusCode >= 200 && statusCode < 300) {
return data
}
// 处理错误
if (statusCode === 401) {
return await handleUnauthorized(options, resolve, reject);
}
// 处理错误
if (statusCode === 401) {
// 其他错误
uni.showToast({
title: data.message || "请求失败",
icon: "none",
});
return Promise.reject(data);
};
return await handleUnauthorized(options, resolve, reject)
}
// 其他错误
uni.showToast({
title: data.message || '请求失败',
icon: 'none'
})
return Promise.reject(data)
}
// 创建 uni.request 的封装
// const request = (options) => {
// return new Promise((resolve, reject) => {
@ -83,256 +95,249 @@ const responseInterceptor = async (options, response, resolve, reject) => {
// 请求方法
const request = async (options, isUpdate) => {
// 合并配置
let url = uni.getStorageSync("baseUrl");
if (uni.getStorageSync("setVersion").VersionCode == "") {
setVersion();
}
// 合并配置
let url = uni.getStorageSync('baseUrl')
if (uni.getStorageSync('setVersion').VersionCode == '') {
setVersion()
}
if (!url) {
await new Promise((resolve, reject) => {
uni.request({
url: "https://api.mrrwlkj.top/api/openPuc/getSjApiUrl", // 接口地址
method: "GET", // 请求方法(默认 GET
header: {
"Content-Type": "application/json", // 请求头
VersionCode: uni.getStorageSync("setVersion").VersionCode,
DeviceBrand: uni.getStorageSync("setVersion").DeviceBrand,
DeviceType: uni.getStorageSync("setVersion").DeviceType,
},
success: (res) => {
if (res.data.code == 200) {
uni.setStorageSync("baseUrl", res.data.data.url);
url = res.data.data.url;
resolve(url);
}
console.log("请求成功", res.data);
},
fail: (err) => {
console.log("请求失败", err);
},
complete: () => {
console.log("请求完成(无论成功失败都会执行)");
},
});
});
}
if (!url) {
await new Promise((resolve, reject) => {
uni.request({
url: 'https://api.mrrwlkj.top/api/openPuc/getSjApiUrl', // 接口地址
method: 'GET', // 请求方法(默认 GET
header: {
'Content-Type': 'application/json', // 请求头
'VersionCode': uni.getStorageSync('setVersion').VersionCode,
'DeviceBrand': uni.getStorageSync('setVersion').DeviceBrand,
'DeviceType': uni.getStorageSync('setVersion').DeviceType
},
success: (res) => {
if (res.data.code == 200) {
uni.setStorageSync('baseUrl', res.data.data.url)
url = res.data.data.url
resolve(url)
}
console.log('请求成功', res.data);
},
fail: (err) => {
console.log('请求失败', err);
},
complete: () => {
console.log('请求完成(无论成功失败都会执行)');
}
});
})
if (process.env.NODE_ENV === "development") {
baseURL = url; // 发布到生产环境时,此处代码会被摇树移除掉。
baseURL = "http://test.mrrwlkj.top"; // 发布到生产环境时,此处代码会被摇树移除掉。
//baseURL = 'http://dev.mrrwlkj.top'; // 发布到生产环境时,此处代码会被摇树移除掉。
// baseURL = "https://app.mrrweb.com.cn";
} else {
baseURL = url; // 发布到生产环境时,此处代码会被摇树移除掉。
baseURL = "http://test.mrrwlkj.top"; // 发布到生产环境时,此处代码会被摇树移除掉。
//baseURL = 'http://dev.mrrwlkj.top'; // 发布到生产环境时,此处代码会被摇树移除掉。
// baseURL = "https://app.mrrweb.com.cn";
}
console.log("生产环境");
}
// 基础配置
const config = {
baseURL: baseURL, // APP和H5的开发URL
baseURL: baseURL, // APP和H5的开发URL
// baseURL: 'https://app.mrrweb.com.cn', // APP和H5的生产URL
header: {
"content-type": "application/json",
VersionCode: uni.getStorageSync("setVersion").VersionCode,
DeviceBrand: uni.getStorageSync("setVersion").DeviceBrand,
DeviceType: uni.getStorageSync("setVersion").DeviceType,
},
timeout: 60000, // 超时时间
};
if (process.env.NODE_ENV === 'development') {
baseURL = url; // 发布到生产环境时,此处代码会被摇树移除掉。
baseURL = 'http://test.mrrwlkj.top'; // 发布到生产环境时,此处代码会被摇树移除掉。
//baseURL = 'http://dev.mrrwlkj.top'; // 发布到生产环境时,此处代码会被摇树移除掉。
//baseURL = 'https://app.mrrweb.com.cn';
} else {
baseURL = url; // 发布到生产环境时,此处代码会被摇树移除掉。
baseURL = 'http://test.mrrwlkj.top'; // 发布到生产环境时,此处代码会被摇树移除掉。
//baseURL = 'http://dev.mrrwlkj.top'; // 发布到生产环境时,此处代码会被摇树移除掉。
//baseURL = 'https://app.mrrweb.com.cn';
options = {
...config,
...options,
url: !isUpdate ? `${config.baseURL}${options.url}` : options.url,
};
console.log('生产环境');
}
// 请求拦截
options = requestInterceptor(options);
// 基础配置
const config = {
baseURL: baseURL, // APP和H5的开发URL
baseURL: baseURL, // APP和H5的开发URL
// baseURL: 'https://app.mrrweb.com.cn', // APP和H5的生产URL
// 发起请求
return new Promise((resolve, reject) => {
// #ifdef H5
// H5端添加loading
if (!options.hideLoading) {
uni.showLoading({
title: "加载中...",
});
}
// #endif
header: {
'content-type': 'application/json',
'VersionCode': uni.getStorageSync('setVersion').VersionCode,
'DeviceBrand': uni.getStorageSync('setVersion').DeviceBrand,
'DeviceType': uni.getStorageSync('setVersion').DeviceType
},
timeout: 60000 // 超时时间
}
uni.request({
...options,
success: (res) => {
// #ifdef H5
if (!options.hideLoading) {
uni.hideLoading();
}
// #endif
try {
const result = responseInterceptor(options, res, resolve, reject);
if (result && typeof result.then === "function") {
result.then((data) => resolve(data)).catch((err) => reject(err));
} else {
resolve(result);
}
} catch (err) {
reject(err);
}
},
fail: (err) => {
// #ifdef H5
if (!options.hideLoading) {
uni.hideLoading();
}
// #endif
// 网络错误处理
let errorMsg = "网络错误,请稍后重试";
// #ifdef H5
if (err.errMsg.includes("timeout")) {
errorMsg = "请求超时,请检查网络";
}
// #endif
options = {
...config,
...options,
url: !isUpdate ? `${config.baseURL}${options.url}` : options.url
}
uni.showToast({
title: errorMsg,
icon: "none",
});
reject(err);
},
});
});
};
// 请求拦截
options = requestInterceptor(options)
// 发起请求
return new Promise((resolve, reject) => {
// #ifdef H5
// H5端添加loading
if (!options.hideLoading) {
uni.showLoading({
title: '加载中...'
})
}
// #endif
uni.request({
...options,
success: (res) => {
// #ifdef H5
if (!options.hideLoading) {
uni.hideLoading()
}
// #endif
try {
const result = responseInterceptor(options, res, resolve, reject)
if (result && typeof result.then === 'function') {
result.then(data => resolve(data)).catch(err => reject(err))
} else {
resolve(result)
}
} catch (err) {
reject(err)
}
},
fail: (err) => {
// #ifdef H5
if (!options.hideLoading) {
uni.hideLoading()
}
// #endif
// 网络错误处理
let errorMsg = '网络错误,请稍后重试'
// #ifdef H5
if (err.errMsg.includes('timeout')) {
errorMsg = '请求超时,请检查网络'
}
// #endif
uni.showToast({
title: errorMsg,
icon: 'none'
})
reject(err)
}
})
})
}
// 处理 401 未授权
async function handleUnauthorized(originalRequest, resolve, reject) {
if (!getToken()) {
reject(new Error("未登录"));
return redirectToLogin();
}
// 如果正在刷新 Token将请求加入队列
if (isRefreshing) {
return subscribeTokenRefresh((token) => {
originalRequest.header["Authorization"] = `Bearer ${token}`;
request(originalRequest, true).then(resolve).catch(reject);
});
}
if (!getToken()) {
reject(new Error('未登录'))
return redirectToLogin()
}
// 如果正在刷新 Token将请求加入队列
if (isRefreshing) {
return subscribeTokenRefresh(token => {
originalRequest.header['Authorization'] = `Bearer ${token}`
request(originalRequest, true).then(resolve).catch(reject)
})
}
isRefreshing = true;
isRefreshing = true
try {
const newToken = await refreshToken();
setToken(newToken);
onRrefreshed(newToken);
try {
const newToken = await refreshToken()
setToken(newToken)
onRrefreshed(newToken)
// 用新 Token 重试原始请求
originalRequest.header["Authorization"] = `Bearer ${newToken}`;
const response = await request(originalRequest, true);
// resolve(response)
return response;
} catch (error) {
removeToken();
redirectToLogin();
reject(error);
return error;
} finally {
isRefreshing = false;
}
// 用新 Token 重试原始请求
originalRequest.header['Authorization'] = `Bearer ${newToken}`
const response = await request(originalRequest, true)
// resolve(response)
return response
} catch (error) {
removeToken()
redirectToLogin()
reject(error)
return error
} finally {
isRefreshing = false
}
}
// 刷新 Token
async function refreshToken() {
const refreshToken = uni.getStorageSync("refreshToken");
if (!refreshToken) {
throw new Error("No refresh token");
}
const res = await request({
url: "/sj/refreshtoken",
data: {
refresh_token: uni.getStorageSync("refreshToken"),
deviceid: getApp().globalData.deviceid,
},
method: "POST",
});
const refreshToken = uni.getStorageSync('refreshToken')
if (!refreshToken) {
throw new Error('No refresh token')
}
const res = await request({
url: '/sj/refreshtoken',
data: {
refresh_token: uni.getStorageSync('refreshToken'),
deviceid: getApp().globalData.deviceid
},
method: 'POST'
})
if (res.state == 1 || res.code == 200) {
const tokenData = res.data || res;
if (!tokenData.access_token) {
throw new Error("Refresh token response missing access_token");
}
uni.setStorageSync("accessToken", tokenData.access_token);
if (tokenData.refresh_token) {
uni.setStorageSync("refreshToken", tokenData.refresh_token);
}
if (tokenData.refresh_token_expries) {
uni.setStorageSync(
"refresh_token_expries",
tokenData.refresh_token_expries,
);
}
return tokenData.access_token;
}
if (res.state == 1 || res.code == 200) {
uni.setStorageSync('accessToken', res.access_token)
uni.setStorageSync('refreshToken', res.refresh_token)
return res.access_token
}
throw new Error("Refresh token failed");
throw new Error('Refresh token failed')
}
// 跳转到登录页
function redirectToLogin() {
// uni.reLaunch({
// url: '/pages/login/login'
// })
//一键登录测试
// uni.oprPresentLogin()
uni.navigateTo({
url: "/pages/blogPopup/blogPopup",
});
// uni.reLaunch({
// url: '/pages/login/login'
// })
//一键登录测试
// uni.oprPresentLogin()
uni.navigateTo({
url: '/pages/blogPopup/blogPopup'
});
}
// 导出请求方法
export default {
// GET请求
get(url, data = {}, options = {}) {
return request({
url,
data,
method: "GET",
...options,
});
},
// GET请求
get(url, data = {}, options = {}) {
return request({
url,
data,
method: 'GET',
...options
})
},
// POST请求
post(url, data = {}, options = {}) {
return request({
url,
data,
method: "POST",
...options,
});
},
// POST请求
post(url, data = {}, options = {}) {
return request({
url,
data,
method: 'POST',
...options
})
},
// PUT请求
put(url, data = {}, options = {}) {
return request({
url,
data,
method: "PUT",
...options,
});
},
// PUT请求
put(url, data = {}, options = {}) {
return request({
url,
data,
method: 'PUT',
...options
})
},
// DELETE请求
delete(url, data = {}, options = {}) {
return request({
url,
data,
method: "DELETE",
...options,
});
},
};
// DELETE请求
delete(url, data = {}, options = {}) {
return request({
url,
data,
method: 'DELETE',
...options
})
}
}