Compare commits

...

10 Commits

Author SHA1 Message Date
BAKEYi c8c82fb93a 1 2026-06-17 16:30:51 +08:00
丁杰 cc5f824858 个人中心校验 2026-06-15 21:33:34 +08:00
丁杰 177fbb35f9 bug修复,版本号升级。正式域名更换 2026-06-15 20:48:58 +08:00
丁杰 7a071227e7 精选品牌分类,技能审核中修复 2026-06-15 16:01:57 +08:00
丁杰 d01b04bce0 审核状态等一系列bug修复 2026-06-15 14:01:12 +08:00
丁杰 7fe55a5c6f 头像压缩 2026-06-12 11:33:33 +08:00
丁杰 bb183e89fc 修复首页登录监测 2026-06-12 10:45:45 +08:00
丁杰 0eb6237e41 核销流程优化 2026-06-10 11:21:43 +08:00
丁杰 b38847ada8 自营订单核销后跳转详情 2026-06-10 10:38:39 +08:00
丁杰 5578a25653 入驻流程优化 2026-06-09 13:54:44 +08:00
22 changed files with 944 additions and 531 deletions

View File

@ -183,6 +183,7 @@ export default {
onShow: function () { onShow: function () {
uni.hideTabBar(); uni.hideTabBar();
console.log('App Show') console.log('App Show')
uni.$emit('appShowRefresh')
}, },
onHide: function () { onHide: function () {
console.log('App Hide') console.log('App Hide')

92
CHANGE_RECORD.md Normal file
View File

@ -0,0 +1,92 @@
# 改动记录
## 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" : "美融融商家", "name" : "美融融商家",
"appid" : "__UNI__BBE6285", "appid" : "__UNI__BBE6285",
"description" : "同城便捷到家美业“技术外卖”服务、同城预约到店服务平台美融融为同城爱美人群提供更优质的更全面的服务。", "description" : "同城便捷到家美业“技术外卖”服务、同城预约到店服务平台美融融为同城爱美人群提供更优质的更全面的服务。",
"versionName" : "1.0.16", "versionName" : "1.0.21",
"versionCode" : 1016, "versionCode" : 1021,
"transformPx" : false, "transformPx" : false,
/* 5+App */ /* 5+App */
"app-plus" : { "app-plus" : {

View File

@ -70,12 +70,11 @@
src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/338d957b-cbb6-409b-9e7a-ef5faa0f9b70.png" src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/338d957b-cbb6-409b-9e7a-ef5faa0f9b70.png"
mode="widthFix" mode="widthFix"
style="width:26rpx;margin-top: 26rpx;position: relative;top: 4rpx;left: -10rpx;" style="width:26rpx;margin-top: 26rpx;position: relative;top: 4rpx;left: -10rpx;"
v-if="!userInfo.servers_kill_arr || userInfo.servers_kill_arr.length === 0"> v-if="shouldShowServiceSkillWarningIcon()">
</image> </image>
<text style="margin-right: 16rpx;" <text style="margin-right: 16rpx;"
:style="{ color: (userInfo.servers_kill_arr && userInfo.servers_kill_arr.length > 0) ? '#c9c9c9' : '#ec5d57' }"> :style="{ color: serviceSkillStatusColor() }">
{{ (userInfo.servers_kill_arr && userInfo.servers_kill_arr.length > 0) ? '已设置' : {{ serviceSkillStatusText() }}
'待完善' }}
</text> </text>
<image class="arrow-right" src="/static/images/arrow_right.png" mode="aspectFit"> <image class="arrow-right" src="/static/images/arrow_right.png" mode="aspectFit">
</image> </image>
@ -162,12 +161,11 @@
src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/338d957b-cbb6-409b-9e7a-ef5faa0f9b70.png" src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/338d957b-cbb6-409b-9e7a-ef5faa0f9b70.png"
mode="widthFix" mode="widthFix"
style="width:26rpx;margin-top: 26rpx;position: relative;top: 4rpx;left: -10rpx;" style="width:26rpx;margin-top: 26rpx;position: relative;top: 4rpx;left: -10rpx;"
v-if="userInfo.credentials_state === 0"> v-if="shouldShowQualificationWarningIcon()">
</image> </image>
<text style="margin-right: 16rpx;" <text style="margin-right: 16rpx;"
:style="{ color: userInfo.credentials_state === 0 ? '#ec5d57' : userInfo.credentials_state === 1 ? '#e59e45' : '#389930' }"> :style="{ color: qualificationStatusColor() }">
{{ userInfo.credentials_state === 0 ? '待完善' : userInfo.credentials_state === 1 ? '审核中' : {{ qualificationStatusText() }}
'已认证' }}
</text> </text>
<image class="arrow-right" src="/static/images/arrow_right.png" mode="aspectFit"> <image class="arrow-right" src="/static/images/arrow_right.png" mode="aspectFit">
</image> </image>
@ -202,6 +200,11 @@ export default {
identity: '', identity: '',
currentUserId: '', // ID currentUserId: '', // ID
userInfo: {}, // userInfo: {}, //
authDetails: null,
serviceSkillAuditStatus: null,
isServiceSkillAuditLoaded: false,
qualificationAuditStatus: null,
isQualificationAuditLoaded: false,
sharing: false // sharing: false //
} }
}, },
@ -495,6 +498,13 @@ export default {
if (result.data && result.data.id) { if (result.data && result.data.id) {
this.userInfo = result.data this.userInfo = result.data
this.currentUserId = result.data.id this.currentUserId = result.data.id
this.fetchServiceSkillApplyDetails()
this.fetchQualificationApplyDetails()
if (this.isSettled()) {
this.fetchAuthDetails()
} else {
this.authDetails = null
}
// //
uni.setStorageSync('userInfo', result.data) uni.setStorageSync('userInfo', result.data)
@ -547,6 +557,98 @@ export default {
} }
}, },
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 app = getApp()
@ -630,42 +732,77 @@ export default {
}) })
}, },
navigateToQualification() { async navigateToQualification() {
const idType = this.userInfo.id_type; if (this.identity != '2' || this.isCertified()) {
const credentialsState = this.userInfo.credentials_state; uni.navigateTo({
url: '/pages/shop/qualification_sj_change'
});
return;
}
if (idType === 0 && credentialsState === 0) { await this.ensureAuthDetails();
// if (!this.isSettled()) {
uni.navigateTo({ uni.navigateTo({
url: '/pages/ruzhu/ruzhu' url: '/pages/ruzhu/ruzhu'
}); });
} else if (idType > 0 && credentialsState === 0) { } else if (this.isUnderReview()) {
// +
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({ uni.navigateTo({
url: '/pages/ruzhu/ruzhu?type=1' url: '/pages/ruzhu/ruzhu?type=1'
}); });
} else {
uni.navigateTo({
url: '/pages/ruzhu/ruzhu?step=3'
});
} }
}, },
navigateToBelongShop() { // navigateToBelongShop() { //
uni.navigateTo({ uni.navigateTo({
url: '/pages/artisan/belong_shop' 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 === '待完善';
} }
} }
} }

View File

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

View File

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

View File

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

View File

@ -3,8 +3,12 @@
<custom-navbar :title="info.name || '品牌详情'" <custom-navbar :title="info.name || '品牌详情'"
:leftImg="'https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/60ae3383-6ff6-4f42-818b-d9b09a9bd0e0.png'" :leftImg="'https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/60ae3383-6ff6-4f42-818b-d9b09a9bd0e0.png'"
:showUser="true" backgroundColor="#ffffff" titleColor="#333" borderBottom="none" :show-headle="true" :showUser="true" backgroundColor="#ffffff" titleColor="#333" borderBottom="none">
:headleSrc="isCollected ? iconCollectOn : iconCollectOff" @onHeadleClick="toggleCollectStatus"> <template #right>
<view class="collect-btn" @click="toggleCollectStatus">
<text class="collect-icon" :class="{ active: isCollected }"></text>
</view>
</template>
</custom-navbar> </custom-navbar>
<!-- 顶部导航栏扩展动态计算位置的拨号图标 --> <!-- 顶部导航栏扩展动态计算位置的拨号图标 -->
@ -721,6 +725,31 @@ export default {
position: relative; 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 { .nav-phone-wrap {
position: fixed; position: fixed;
@ -917,7 +946,7 @@ export default {
line-height: 37rpx; line-height: 37rpx;
display: -webkit-box; display: -webkit-box;
-webkit-box-orient: vertical; -webkit-box-orient: vertical;
-webkit-line-clamp: 19; -webkit-line-clamp: 10;
overflow: hidden; overflow: hidden;
white-space: pre-line; white-space: pre-line;

View File

@ -28,16 +28,16 @@
<view class="sort-item" @tap="toggleSort('time')"> <view class="sort-item" @tap="toggleSort('time')">
<text class="sort-text" :class="{ active: orderType === 1 || orderType === 2 }">发布时间</text> <text class="sort-text" :class="{ active: orderType === 1 || orderType === 2 }">发布时间</text>
<view class="arrows"> <view class="arrows">
<image class="arrow-icon" :src="orderType === 1 ? iconPinkUp : iconGreyUp"></image> <image class="arrow-icon" :src="orderType === 2 ? iconPinkUp : iconGreyUp"></image>
<image class="arrow-icon" :src="orderType === 2 ? iconPinkDown : iconGreyDown"></image> <image class="arrow-icon" :src="orderType === 1 ? iconPinkDown : iconGreyDown"></image>
</view> </view>
</view> </view>
<view class="sort-item" @tap="toggleSort('view')"> <view class="sort-item" @tap="toggleSort('view')">
<text class="sort-text" :class="{ active: orderType === 3 || orderType === 4 }">浏览量</text> <text class="sort-text" :class="{ active: orderType === 3 || orderType === 4 }">浏览量</text>
<view class="arrows"> <view class="arrows">
<image class="arrow-icon" :src="orderType === 3 ? iconPinkUp : iconGreyUp"></image> <image class="arrow-icon" :src="orderType === 4 ? iconPinkUp : iconGreyUp"></image>
<image class="arrow-icon" :src="orderType === 4 ? iconPinkDown : iconGreyDown"></image> <image class="arrow-icon" :src="orderType === 3 ? iconPinkDown : iconGreyDown"></image>
</view> </view>
</view> </view>
</view> </view>
@ -153,9 +153,21 @@ export default {
// ============ ============ // ============ ============
toggleSort(type) { toggleSort(type) {
if (type === 'time') { if (type === 'time') {
this.orderType = this.orderType === 1 ? 2 : 1; if (this.orderType === 1) {
this.orderType = 2;
} else if (this.orderType === 2) {
this.orderType = 0;
} else {
this.orderType = 1;
}
} else if (type === 'view') { } else if (type === 'view') {
this.orderType = this.orderType === 3 ? 4 : 3; if (this.orderType === 3) {
this.orderType = 4;
} else if (this.orderType === 4) {
this.orderType = 0;
} else {
this.orderType = 3;
}
} }
this.refreshBrandList(); this.refreshBrandList();
}, },
@ -194,6 +206,7 @@ export default {
if (this.activeId === id) return; if (this.activeId === id) return;
this.activeId = id; this.activeId = id;
this.currentSecondClass = ""; this.currentSecondClass = "";
this.selectedSecondIds = [];
this.getSecondClassList(); this.getSecondClassList();
this.refreshBrandList(); this.refreshBrandList();
}, },
@ -217,6 +230,12 @@ export default {
}); });
if (this.$refs.brandListRef) { 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); this.$refs.brandListRef.manualRefresh(params);
} }
}, },

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -59,8 +59,9 @@
</scroll-view> </scroll-view>
<view class="bottom-btn-wrapper"> <view class="bottom-btn-wrapper">
<view class="confirm-btn" @tap="confirmVerify" :class="{ 'btn-disabled': isVerifying }"> <view class="confirm-btn" @tap="isVerified ? goHomePage() : confirmVerify()"
<text class="btn-text">{{ isVerifying ? '核销中...' : '确认核销' }}</text> :class="{ 'btn-disabled': isVerifying }">
<text class="btn-text">{{ isVerified ? '核销成功,返回首页' : (isVerifying ? '核销中...' : '确认核销') }}</text>
</view> </view>
</view> </view>
</view> </view>
@ -101,7 +102,9 @@ export default {
payPrice: 0, payPrice: 0,
settlePrice: 0 settlePrice: 0
}, },
isVerifying: false isVerifying: false,
isVerified: false, //
userInfo: {} // sjid
}; };
}, },
onLoad(options) { onLoad(options) {
@ -124,6 +127,23 @@ export default {
console.log('未获取到订单信息'); 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: { methods: {
// /sj/poster/getOrderByCode data // /sj/poster/getOrderByCode data
mapOrderData(data) { mapOrderData(data) {
@ -152,6 +172,63 @@ export default {
goBack() { goBack() {
uni.navigateBack(); 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() { confirmVerify() {
if (this.isVerifying) return; if (this.isVerifying) return;
if (!this.orderData.orderId) { if (!this.orderData.orderId) {
@ -182,16 +259,10 @@ export default {
uni.hideLoading(); uni.hideLoading();
if (res.code === 200) { if (res.code === 200) {
uni.showToast({ title: '核销成功', icon: 'success' }); uni.showToast({ title: '核销成功', icon: 'success' });
const orderId = this.orderData.orderId; this.isVerified = true;
const orderType = this.orderData.orderType; this.isVerifying = false;
let url = ''; //
if (orderType == 3) { const url = this.getOrderDetailUrl();
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(() => { setTimeout(() => {
uni.navigateTo({ url }); uni.navigateTo({ url });
}, 1500); }, 1500);

View File

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