Merge branch 'master' into mrr_sj_develop_丁杰_20260609_自定义服务发布

This commit is contained in:
丁杰 2026-06-22 14:43:11 +08:00
commit 3e39ff1140
246 changed files with 32811 additions and 20573 deletions

41
App.vue
View File

@ -16,6 +16,9 @@
import { import {
setVersion setVersion
} from './utils/version.js' } from './utils/version.js'
import {
APP_BACK_BASE_URL
} from './utils/appBackBase.js'
// //
const aLiSDKModule = uni.requireNativePlugin('AliCloud-NirvanaPns'); const aLiSDKModule = uni.requireNativePlugin('AliCloud-NirvanaPns');
export default { export default {
@ -66,38 +69,13 @@
// await setVersion() // await setVersion()
//访 //访
// GET
let version = uni.getStorageSync('setVersion')
let baseUrl
await uni.request({
url: 'https://api.mrrwlkj.top/api/openPuc/getSjApiUrl', //
method: 'GET', // GET
header: {
'Content-Type': 'application/json', //
'VersionCode': version.VersionCode,
'DeviceBrand': version.DeviceBrand,
'DeviceType': version.DeviceType
},
success: (res) => {
if (res.data.code == 200) {
// #ifndef MP-WEIXIN // #ifndef MP-WEIXIN
uni.setStorageSync('baseUrl', res.data.data.url) uni.setStorageSync('baseUrl', APP_BACK_BASE_URL)
// #endif // #endif
// #ifdef MP-WEIXIN // #ifdef MP-WEIXIN
wx.setStorageSync('baseUrl', res.data.data.url) wx.setStorageSync('baseUrl', APP_BACK_BASE_URL)
// #endif // #endif
this.$store.commit("setLocation", true) this.$store.commit("setLocation", true)
}
console.log('请求成功', res.data);
},
fail: (err) => {
console.log('请求失败', err);
},
complete: () => {
console.log('请求完成(无论成功失败都会执行)');
}
});
// #ifdef APP-PLUS // #ifdef APP-PLUS
// //
@ -183,6 +161,7 @@
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')
@ -273,4 +252,12 @@
<style> <style>
/*每个页面公共css */ /*每个页面公共css */
@import '@/static/css/common.css'; @import '@/static/css/common.css';
/* App.vue全局style */
page,
html,
body {
-webkit-text-size-adjust: 100% !important;
text-size-adjust: 100% !important;
}
</style> </style>

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

@ -95,7 +95,7 @@ export default {
color: #999; color: #999;
} }
.tab-text.active { .tab-text.active {
color: #E8101E; /* 选中颜色 */ color: #FF4767; /* 选中颜色 */
} }
.tab-badge { .tab-badge {
position: absolute; position: absolute;

View File

@ -43,7 +43,7 @@ export default {
// //
color: { color: {
type: String, type: String,
default: '#E8101E' default: '#FF4767'
}, },
// //
backgroundColor: { backgroundColor: {

View File

@ -402,7 +402,7 @@ export default {
} }
.time-option.active .time-text { .time-option.active .time-text {
color: #E8101E; color: #FF4767;
font-weight: 500; font-weight: 500;
} }
@ -413,7 +413,7 @@ export default {
.time-discount { .time-discount {
font-size: 24rpx; font-size: 24rpx;
color: #E8101E; color: #FF4767;
padding: 4rpx 12rpx; padding: 4rpx 12rpx;
background-color: #fff5f6; background-color: #fff5f6;
border-radius: 20rpx; border-radius: 20rpx;
@ -444,7 +444,7 @@ export default {
color: #666; color: #666;
} }
.active { .active {
color: #E8101E; /* 选中态主题色 */ color: #FF4767; /* 选中态主题色 */
} }
/* 服务时间按钮专属:控制下拉图标尺寸 */ /* 服务时间按钮专属:控制下拉图标尺寸 */

View File

@ -52,7 +52,7 @@ export default {
// props // props
activeColor: { activeColor: {
type: String, type: String,
default: "#E8101E", default: "#FF4767",
}, },
// props // props
inactiveColor: { inactiveColor: {

View File

@ -59,7 +59,7 @@ export default {
// //
activeColor: { activeColor: {
type: String, type: String,
default: "#E8101E", default: "#FF4767",
}, },
// //
inactiveColor: { inactiveColor: {
@ -129,7 +129,7 @@ export default {
left: 0; left: 0;
right: 0; right: 0;
bottom: 0; bottom: 0;
border: 2rpx solid #E8101E; border: 2rpx solid #FF4767;
border-radius: 48rpx; border-radius: 48rpx;
} }
@ -143,6 +143,6 @@ export default {
} }
.icon-item.active .icon-text { .icon-item.active .icon-text {
color: #E8101E; color: #FF4767;
} }
</style> </style>

View File

@ -208,7 +208,7 @@ export default {
padding-left: 30rpx; padding-left: 30rpx;
position: relative; position: relative;
&__point { &__point {
background-color: #E8101E; background-color: #FF4767;
height: 6rpx; height: 6rpx;
width: 6rpx; width: 6rpx;
border-radius: 50%; border-radius: 50%;
@ -221,7 +221,7 @@ export default {
} }
.active { .active {
background: #ffffff; background: #ffffff;
color: #E8101E; color: #FF4767;
} }
} }
&__right { &__right {
@ -295,17 +295,17 @@ export default {
height: 82rpx; height: 82rpx;
font-weight: 400; font-weight: 400;
font-size: 30rpx; font-size: 30rpx;
color: #E8101E; color: #FF4767;
line-height: 42rpx; line-height: 42rpx;
text-align: left; text-align: left;
font-style: normal; font-style: normal;
} }
&__sure { &__sure {
border-radius: 41rpx; border-radius: 41rpx;
border: 2rpx solid #E8101E; border: 2rpx solid #FF4767;
} }
&__reset { &__reset {
background: #E8101E; background: #FF4767;
border-radius: 41rpx; border-radius: 41rpx;
color: #ffffff; color: #ffffff;
} }

View File

@ -114,8 +114,8 @@ export default {
} }
.active { .active {
background: rgba(252, 67, 124, 0.1); background: rgba(252, 67, 124, 0.1);
color: #E8101E; color: #FF4767;
border: 1rpx solid #E8101E; border: 1rpx solid #FF4767;
} }
} }
</style> </style>

View File

@ -548,7 +548,7 @@
width: 690rpx; width: 690rpx;
height: 68rpx; height: 68rpx;
background: #FFFFFF; background: #FFFFFF;
border: 2rpx solid #E8101E; border: 2rpx solid #FF4767;
background-color: #fafafa; background-color: #fafafa;
display: flex; display: flex;
align-items: center; align-items: center;

View File

@ -121,7 +121,7 @@ export default {
border: 1rpx solid #fba9bb; border: 1rpx solid #fba9bb;
font-weight: 500; font-weight: 500;
font-size: 24rpx; font-size: 24rpx;
color: #E8101E; color: #FF4767;
text-align: left; text-align: left;
font-style: normal; font-style: normal;
} }
@ -197,7 +197,7 @@ export default {
margin-top: 10rpx; margin-top: 10rpx;
font-weight: 500; font-weight: 500;
font-size: 24rpx; font-size: 24rpx;
color: #E8101E; color: #FF4767;
line-height: 33rpx; line-height: 33rpx;
text-align: left; text-align: left;
font-style: normal; font-style: normal;

View File

@ -59,7 +59,7 @@ export default {
.loginBtn { .loginBtn {
width: 262rpx; width: 262rpx;
height: 86rpx; height: 86rpx;
background: #e8101e; background: #FF4767;
border-radius: 43rpx; border-radius: 43rpx;
text-align: center; text-align: center;
line-height: 86rpx; line-height: 86rpx;

View File

@ -408,11 +408,11 @@ export default {
.isActive { .isActive {
background: rgba(252, 67, 124, 0.08); background: rgba(252, 67, 124, 0.08);
color: #e8101e !important; color: #FF4767 !important;
} }
.isActive .time-picker-content__time__list__item__text { .isActive .time-picker-content__time__list__item__text {
color: #e8101e !important; color: #FF4767 !important;
} }
/* 选中样式前后弧度 */ /* 选中样式前后弧度 */
@ -433,7 +433,7 @@ border-radius: 0rpx 51rpx 51rpx 0rpx}
.time-picker-content__time__sure__box { .time-picker-content__time__sure__box {
width: 648rpx; width: 648rpx;
height: 94rpx; height: 94rpx;
background: #E8101E; background: #FF4767;
border-radius: 48rpx; border-radius: 48rpx;
display: flex; display: flex;
align-items: center; align-items: center;

View File

@ -467,8 +467,8 @@
.isActive { .isActive {
background: rgba(252, 67, 124, 0.08); background: rgba(252, 67, 124, 0.08);
border-radius: 10rpx; border-radius: 10rpx;
border: 1rpx solid #E8101E; border: 1rpx solid #FF4767;
color: #E8101E; color: #FF4767;
/* 选中状态 */ /* 选中状态 */
} }
@ -493,7 +493,7 @@
&__box { &__box {
width: 648rpx; width: 648rpx;
height: 94rpx; height: 94rpx;
background: linear-gradient(140deg, #fa4e9a 0%, #E8101E 100%); background: linear-gradient(140deg, #fa4e9a 0%, #FF4767 100%);
border-radius: 48rpx; border-radius: 48rpx;
display: flex; display: flex;
align-items: center; align-items: center;

View File

@ -5,26 +5,15 @@
<view class="modal-title">开始服务</view> <view class="modal-title">开始服务</view>
<view class="modal-subtitle">请输入服务码</view> <view class="modal-subtitle">请输入服务码</view>
<view class="code-box"> <view class="code-box">
<view <view v-for="(item, idx) in codeLength" :key="idx"
v-for="(item, idx) in codeLength"
:key="idx"
:class="['code-cell', idx === currentIndex ? 'active' : '', code[idx] ? 'filled' : '']"> :class="['code-cell', idx === currentIndex ? 'active' : '', code[idx] ? 'filled' : '']">
<text v-if="code[idx]">{{ code[idx] }}</text> <text v-if="code[idx]">{{ code[idx] }}</text>
</view> </view>
<!-- 隐藏真实输入框 --> <!-- 隐藏真实输入框 -->
<input <input :adjust-position="false" class="real-input" type="number" :maxlength="codeLength"
:adjust-position="false" v-model="inputValue" :focus="true" @input="onInput" @focus="onFocus"
class="real-input" @keyboardheightchange="onkeyboardheightchange" @blur="onBlur" cursor-spacing="100"
type="number" cursor-color="transparent" ref="realInput" />
:maxlength="codeLength"
v-model="inputValue"
:focus="true"
@input="onInput"
@focus="onFocus"
@keyboardheightchange="onkeyboardheightchange"
@blur="onBlur"
cursor-spacing="100"
ref="realInput" />
</view> </view>
<button class="confirm-btn" :disabled="code.length < codeLength" @click="onConfirm">确定</button> <button class="confirm-btn" :disabled="code.length < codeLength" @click="onConfirm">确定</button>
<view class="close-btn" @click="close">×</view> <view class="close-btn" @click="close">×</view>
@ -117,12 +106,13 @@
z-index: 999999; z-index: 999999;
.modal-mask { .modal-mask {
position: absolute; position: fixed;
left: 0; left: 0;
top: 0; top: 0;
right: 0; right: 0;
bottom: 0; bottom: 0;
background: rgba(0, 0, 0, 0.15); background: rgba(0, 0, 0, 0.5);
z-index: -1;
} }
.modal-content { .modal-content {
@ -197,6 +187,7 @@
height: 100%; height: 100%;
opacity: 0; opacity: 0;
z-index: 2; z-index: 2;
caret-color: transparent;
} }
} }

View File

@ -181,7 +181,7 @@
position: absolute; position: absolute;
top: 0rpx; top: 0rpx;
left: 0rpx; left: 0rpx;
background-color: #E8101E; background-color: #FF4767;
color: #FFFFFF; color: #FFFFFF;
font-size: 24rpx; font-size: 24rpx;
padding: 6rpx 14rpx; padding: 6rpx 14rpx;
@ -247,7 +247,7 @@
.price-symbol { .price-symbol {
font-weight: 500; font-weight: 500;
font-size: 24rpx; font-size: 24rpx;
color: #E8101E; color: #FF4767;
line-height: 33rpx; line-height: 33rpx;
text-align: left; text-align: left;
font-style: normal; font-style: normal;
@ -256,7 +256,7 @@
.price-value { .price-value {
font-weight: 500; font-weight: 500;
font-size: 36rpx; font-size: 36rpx;
color: #E8101E; color: #FF4767;
line-height: 33rpx; line-height: 33rpx;
text-align: left; text-align: left;
font-style: normal; font-style: normal;
@ -332,12 +332,12 @@
.price-symbol { .price-symbol {
font-size: 24rpx; font-size: 24rpx;
color: #E8101E; color: #FF4767;
} }
.price-value { .price-value {
font-size: 32rpx; font-size: 32rpx;
color: #E8101E; color: #FF4767;
font-weight: 500; font-weight: 500;
margin-right: 12rpx; margin-right: 12rpx;
} }

View File

@ -336,7 +336,7 @@
.price-text{ .price-text{
font-weight: 500; font-weight: 500;
font-size: 24rpx; font-size: 24rpx;
color: #E8101E; color: #FF4767;
line-height: 33rpx; line-height: 33rpx;
text-align: left; text-align: left;
font-style: normal; font-style: normal;
@ -345,7 +345,7 @@
.price-symbol { .price-symbol {
font-weight: 500; font-weight: 500;
font-size: 20rpx; font-size: 20rpx;
color: #E8101E; color: #FF4767;
line-height: 33rpx; line-height: 33rpx;
text-align: left; text-align: left;
font-style: normal; font-style: normal;
@ -354,7 +354,7 @@
.price-value { .price-value {
font-weight: 500; font-weight: 500;
font-size: 30rpx; font-size: 30rpx;
color: #E8101E; color: #FF4767;
line-height: 33rpx; line-height: 33rpx;
text-align: left; text-align: left;
font-style: normal; font-style: normal;

View File

@ -1,63 +1,54 @@
<template> <template>
<view class="step-tab"> <view class="step-tab">
<view class="step-container"> <view class="step-container">
<!-- 步骤1: 入驻协议 -->
<view class="step-item" :class="getStepClass(0)"> <view class="step-item" :class="getStepClass(0)">
<view class="step-icon"> <view class="step-icon">
<image <image
v-if="currentStep === 0" v-if="mappedStep === 0"
src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/55a51333-318f-4ae4-8402-aca265bd499d" src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/d62a1d01-52cb-418e-ba5b-afef513061b9.png"
class="step-img active-circle" class="step-img active-circle"
mode="aspectFit" mode="aspectFit"
/> />
<view v-else-if="currentStep > 0" class="step-done">1</view> <view v-else-if="mappedStep > 0" class="step-done">1</view>
<view v-else class="step-number">1</view> <view v-else class="step-number">1</view>
</view> </view>
<text class="step-text" :class="{ active: currentStep === 0 }">入驻协议</text> <text class="step-text" :class="{ active: mappedStep === 0 }">入驻协议</text>
</view> </view>
<!-- 第一个连接线 -->
<view class="line-segment line-1"> <view class="line-segment line-1">
<view class="line-progress" :class="{ active: line1Active, deactivating: line1Deactivating }"></view> <view class="line-progress" :class="{ active: line1Active, deactivating: line1Deactivating }"></view>
</view> </view>
<!-- 步骤2: 根据身份显示不同信息 -->
<view class="step-item" :class="getStepClass(1)"> <view class="step-item" :class="getStepClass(1)">
<view class="step-icon"> <view class="step-icon">
<image <image
v-if="currentStep === 1" v-if="mappedStep === 1"
src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/55a51333-318f-4ae4-8402-aca265bd499d" src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/d62a1d01-52cb-418e-ba5b-afef513061b9.png"
class="step-img active-circle" class="step-img active-circle"
mode="aspectFit" mode="aspectFit"
/> />
<view v-else-if="currentStep > 1" class="step-done">2</view> <view v-else-if="mappedStep > 1" class="step-done">2</view>
<view v-else class="step-number">2</view> <view v-else class="step-number">2</view>
</view> </view>
<text class="step-text" :class="{ active: currentStep === 1 }"> <text class="step-text" :class="{ active: mappedStep === 1 }">基本信息</text>
{{ identity === 1 ? '个人信息' : '资质信息' }}
</text>
</view> </view>
<!-- 第二个连接线 -->
<view class="line-segment line-2"> <view class="line-segment line-2">
<view class="line-progress" :class="{ active: line2Active, deactivating: line2Deactivating }"></view> <view class="line-progress" :class="{ active: line2Active, deactivating: line2Deactivating }"></view>
</view> </view>
<!-- 步骤3: 根据身份显示不同信息 -->
<view class="step-item" :class="getStepClass(2)"> <view class="step-item" :class="getStepClass(2)">
<view class="step-icon"> <view class="step-icon">
<image <image
v-if="currentStep === 2" v-if="mappedStep === 2"
src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/55a51333-318f-4ae4-8402-aca265bd499d" src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/d62a1d01-52cb-418e-ba5b-afef513061b9.png"
class="step-img active-circle" class="step-img active-circle"
mode="aspectFit" mode="aspectFit"
/> />
<view v-else-if="currentStep > 2" class="step-done">3</view> <view v-else-if="mappedStep > 2" class="step-done">3</view>
<view v-else class="step-number">3</view> <view v-else class="step-number">3</view>
</view> </view>
<text class="step-text" :class="{ active: currentStep === 2 }"> <text class="step-text" :class="{ active: mappedStep === 2 }">资质认证</text>
{{ identity === 1 ? '资质信息' : '门店信息' }}
</text>
</view> </view>
</view> </view>
</view> </view>
@ -67,32 +58,23 @@
export default { export default {
name: "StepTab", name: "StepTab",
props: { props: {
// (0, 1, 2) mappedStep: {
currentStep: {
type: Number, type: Number,
default: 0 default: 0
},
// 1-2-
identity: {
type: Number,
default: 2
} }
}, },
data() { data() {
return { return {
prevStep: 0, // prevStep: 0,
line1Active: false, // 线 line1Active: false,
line2Active: false, // 线 line2Active: false,
line1Deactivating: false, // 线 line1Deactivating: false,
line2Deactivating: false // 线 line2Deactivating: false
}; };
}, },
watch: { watch: {
// currentStep线 mappedStep(newVal, oldVal) {
currentStep(newVal, oldVal) {
this.prevStep = oldVal; this.prevStep = oldVal;
//
if (newVal > oldVal) { if (newVal > oldVal) {
if (newVal >= 1) { if (newVal >= 1) {
this.line1Active = true; this.line1Active = true;
@ -102,38 +84,34 @@ export default {
this.line2Active = true; this.line2Active = true;
this.line2Deactivating = false; this.line2Deactivating = false;
} }
} } else if (newVal < oldVal) {
//
else if (newVal < oldVal) {
if (newVal < 2) { if (newVal < 2) {
this.line2Deactivating = true; this.line2Deactivating = true;
setTimeout(() => { setTimeout(() => {
this.line2Active = false; this.line2Active = false;
this.line2Deactivating = false; this.line2Deactivating = false;
}, 300); // }, 300);
} }
if (newVal < 1) { if (newVal < 1) {
this.line1Deactivating = true; this.line1Deactivating = true;
setTimeout(() => { setTimeout(() => {
this.line1Active = false; this.line1Active = false;
this.line1Deactivating = false; this.line1Deactivating = false;
}, 300); // }, 300);
} }
} }
} }
}, },
mounted() { mounted() {
// 线 this.line1Active = this.mappedStep >= 1;
this.line1Active = this.currentStep >= 1; this.line2Active = this.mappedStep >= 2;
this.line2Active = this.currentStep >= 2;
}, },
methods: { methods: {
// CSS
getStepClass(stepIndex) { getStepClass(stepIndex) {
if (stepIndex === this.currentStep) { if (stepIndex === this.mappedStep) {
return 'active'; return 'active';
} }
else if (stepIndex < this.currentStep) { else if (stepIndex < this.mappedStep) {
return 'completed'; return 'completed';
} }
return ''; return '';
@ -206,7 +184,7 @@ export default {
justify-content: center; justify-content: center;
align-items: center; align-items: center;
font-size: 28rpx; font-size: 28rpx;
color: #E8101E; color: #FF4767;
font-weight: 500; font-weight: 500;
transition: all 0.3s ease; transition: all 0.3s ease;
box-shadow: inset 0 0 4rpx rgba(232, 16, 30, 0.2); box-shadow: inset 0 0 4rpx rgba(232, 16, 30, 0.2);
@ -259,35 +237,16 @@ export default {
transform-origin: left center; transform-origin: left center;
} }
/* 激活状态的线条 - 前进动画 */
.line-progress.active { .line-progress.active {
width: 100%; width: 100%;
background-color: #E8101E; background-color: #FF4767;
transition: width 0.3s ease; transition: width 0.3s ease;
} }
/* 取消激活状态的线条 - 返回动画 */
.line-progress.deactivating { .line-progress.deactivating {
width: 0%; width: 0%;
background-color: #E8101E; background-color: #FF4767;
transition: width 0.3s ease; transition: width 0.3s ease;
transform-origin: right center; transform-origin: right center;
} }
/* 响应式调整 */
@media (max-width: 750rpx) {
.step-container {
/* padding: 5rpx 40rpx; */
}
.line-segment {
/* width: 100rpx; */
}
/* .line-1,
.line-2 {
margin-left: 15rpx;
margin-right: 15rpx;
} */
}
</style> </style>

View File

@ -1,8 +1,24 @@
<template> <template>
<uv-tabbar fixed :value="selected" @change="change1" activeColor="#ee0a24" :placeholder="false" <uv-tabbar
:safeAreaInsetBottom="false" :customStyle="{height:`110rpx`}"> v-if="tabbarReady"
<uv-tabbar-item v-for="(item,index) in $store.state.tabbarList" :key="index" :badge="getNum(index)" :key="refreshKey"
:customStyle="{height:`110rpx`}"> fixed
:value="currentTabIndex"
@change="onTabChange"
activeColor="#FF4767"
:placeholder="false"
:safeAreaInsetBottom="false"
:customStyle="{height:'110rpx'}"
>
<uv-tabbar-item
v-for="(item, idx) in tabbarList"
:key="idx"
:name="idx"
:text="item.text"
:badge="getNum(idx)"
:customStyle="{height:'110rpx'}"
@click="onItemClick(idx)"
>
<template v-slot:active-icon> <template v-slot:active-icon>
<image class="icon" :src="item.selectedIconPath"></image> <image class="icon" :src="item.selectedIconPath"></image>
</template> </template>
@ -14,108 +30,178 @@
</template> </template>
<script> <script>
import { mapState, mapMutations } from 'vuex';
import request from "@/utils/request"; import request from "@/utils/request";
export default { export default {
name: "tab-bar", name: "tab-bar",
props: { // props.selected Vuex
selected: {
type: [Number, String]
}
},
data() { data() {
return { return {
tabbarList: [{ refreshKey: 0, //
"iconPath": "/static/images/tabbar/new_home_gray.png", tabbarReady: false, //
"text": "首页", tabbarList: [ // tab
"selectedIconPath": "/static/images/tabbar/new_home.png", {
"pagePath": "/pages/home/home" iconPath: "/static/images/tabbar/new_home_gray.png",
text: "首页",
selectedIconPath: "/static/images/tabbar/new_home.png",
pagePath: "/pages/home/home"
}, },
{ {
"iconPath": "/static/images/tabbar/new_message_gray.png", iconPath: "/static/images/tabbar/new_order_gray.png",
"text": "消息", text: "订单",
"selectedIconPath": "/static/images/tabbar/new_message.png", selectedIconPath: "/static/images/tabbar/new_order.png",
"pagePath": "/pages/message/message" pagePath: "/pages/order/userorder-list"
}, },
{ {
"iconPath": "/static/images/tabbar/new_my_gray.png", iconPath: "/static/images/tabbar/new_message_gray.png",
"text": "我的", text: "消息",
"selectedIconPath": "/static/images/tabbar/new_my.png", selectedIconPath: "/static/images/tabbar/new_message.png",
"pagePath": "/pages/my/my" pagePath: "/pages/message/message"
},
{
iconPath: "/static/images/tabbar/new_my_gray.png",
text: "我的",
selectedIconPath: "/static/images/tabbar/new_my.png",
pagePath: "/pages/my/my"
} }
] ]
}; };
}, },
computed: { computed: {
messageNum() { //
return this.$store.state.messageNum || 0 ...mapState(['messageNum']),
}
},
async created() {
if (!this.$store.state.tabbarList.length) {
let isnNetwork = uni.getStorageSync("isnNetwork");
if (isnNetwork) {
await this.getButtonImg()
} else {
uni.getNetworkType({
success: (res) => {
console.log(res.networkType);
if (res.networkType == "none") {
this.$store.commit("setTabbarList", this.tabbarList) // ========= =========
} else { // Vuex
// currentTabIndex() {
uni.setStorageSync("isnNetwork", 1); try {
this.getButtonImg() //
const pages = getCurrentPages();
if (pages && pages.length > 0) {
//
const currentPage = pages[pages.length - 1];
//
const currentPath = '/' + (currentPage.route || currentPage.__route__);
// tabbarList
const index = this.tabbarList.findIndex(item => item.pagePath === currentPath);
if (index !== -1) {
return index;
}
}
// Vuex
return this.$store.state.currentTabIndex || 0;
} catch (e) {
return this.$store.state.currentTabIndex || 0;
}
}
// =================================================
},
watch: {
// tabbarList
tabbarList: {
deep: true,
handler() {
this.rebuildTabbar();
}
} }
}, },
created() {
//
this.tabbarReady = false;
this.$nextTick(() => {
this.tabbarReady = true;
//
// this.getButtonImg();
}); });
}
}
}, },
methods: { methods: {
...mapMutations(['SET_CURRENT_TAB_INDEX']),
//
setCurrentTabIndex(index) {
this.SET_CURRENT_TAB_INDEX(index);
},
// uv-tabbar
rebuildTabbar() {
this.tabbarReady = false;
this.$nextTick(() => {
this.refreshKey++;
this.tabbarReady = true;
});
},
// tab > 0
getNum(index) { getNum(index) {
if (index == 1) { if (index === 2 && this.messageNum > 0) {
return this.messageNum return this.messageNum;
} else {
return 0
} }
return null;
}, },
//
//
async getButtonImg() { async getButtonImg() {
try {
let res = await request.post("/sj/poster/getButtonImg", {}); let res = await request.post("/sj/poster/getButtonImg", {});
if (res.code == 200) { if (res.code === 200) {
// if (res.data?.photo) {
// this.topBgImage = res.data?.photo + '?time=666'
// }
this.tabbarList.forEach((item, index) => { this.tabbarList.forEach((item, index) => {
if (res.data[index].iconPath) { if (res.data[index]?.iconPath) {
item.iconPath = res.data[index].iconPath item.iconPath = res.data[index].iconPath;
} }
if (res.data[index].selectedIconPath) { if (res.data[index]?.selectedIconPath) {
item.selectedIconPath = res.data[index].selectedIconPath item.selectedIconPath = res.data[index].selectedIconPath;
} }
}) });
this.$store.commit("setTabbarList", this.tabbarList);
//
this.rebuildTabbar();
}
} catch (err) {
console.error('getButtonImg 请求失败', err);
} }
this.$store.commit("setTabbarList", this.tabbarList)
}, },
change1(val) {
// pages tabbar // uv-tabbar change
// 使navigateTo 使 onTabChange(val) {
const idx = parseInt(val, 10);
this.doJump(idx);
},
// item
onItemClick(idx) {
this.doJump(idx);
},
// +
doJump(index) {
const idx = parseInt(index, 10);
if (isNaN(idx) || !this.tabbarList[idx]) return;
// Vuex
this.setCurrentTabIndex(idx);
//
const targetPage = this.tabbarList[idx].pagePath;
uni.switchTab({ uni.switchTab({
url: this.tabbarList[val].pagePath url: targetPage,
}) fail: (err) => console.error('switchTab 失败', err)
this.messageUpudateNum() });
//
if (typeof this.messageUpudateNum === 'function') {
this.messageUpudateNum();
} }
} }
} }
};
</script> </script>
<style lang="scss"> <style lang="scss">
.icon { .icon {
height: 98rpx; height: 54rpx;
width: 98rpx; width: 54rpx;
} }
::v-deep .uv-tabbar__content { ::v-deep .uv-tabbar__content {
z-index: 999 !important; z-index: 999 !important;

View File

@ -383,7 +383,7 @@
justify-content: center; justify-content: center;
width: 690rpx; width: 690rpx;
height: 80rpx; height: 80rpx;
background: #E8101E; background: #FF4767;
border-radius: 38rpx; border-radius: 38rpx;
font-weight: 400; font-weight: 400;
font-size: 30rpx; font-size: 30rpx;

View File

@ -169,7 +169,7 @@ export default {
justify-content: center; justify-content: center;
width: 690rpx; width: 690rpx;
height: 80rpx; height: 80rpx;
background: #E8101E; background: #FF4767;
border-radius: 38rpx; border-radius: 38rpx;
font-weight: 400; font-weight: 400;
font-size: 30rpx; font-size: 30rpx;

View File

@ -307,7 +307,7 @@ export default {
&__text { &__text {
font-weight: 400; font-weight: 400;
font-size: 18rpx; font-size: 18rpx;
color: #E8101E; color: #FF4767;
line-height: 25rpx; line-height: 25rpx;
text-align: left; text-align: left;
font-style: normal; font-style: normal;
@ -371,7 +371,7 @@ export default {
&__immediately { &__immediately {
width: 236rpx; width: 236rpx;
height: 78rpx; height: 78rpx;
background: #E8101E; background: #FF4767;
border-radius: 39rpx; border-radius: 39rpx;
display: flex; display: flex;
align-items: center; align-items: center;
@ -405,7 +405,7 @@ export default {
&__active { &__active {
height: 28rpx; height: 28rpx;
background: linear-gradient(270deg, #fe78b3 0%, #E8101E 100%); background: linear-gradient(270deg, #fe78b3 0%, #FF4767 100%);
border-radius: 39rpx; border-radius: 39rpx;
} }

View File

@ -2,14 +2,21 @@
"name" : "美融融商家", "name" : "美融融商家",
"appid" : "__UNI__BBE6285", "appid" : "__UNI__BBE6285",
"description" : "同城便捷到家美业“技术外卖”服务、同城预约到店服务平台美融融为同城爱美人群提供更优质的更全面的服务。", "description" : "同城便捷到家美业“技术外卖”服务、同城预约到店服务平台美融融为同城爱美人群提供更优质的更全面的服务。",
"versionName" : "1.0.09", "versionName" : "1.0.22",
"versionCode" : 1009, "versionCode" : 1022,
"transformPx" : false, "transformPx" : false,
/* 5+App */ /* 5+App */
"app-plus" : { "app-plus" : {
"usingComponents" : true, "usingComponents" : true,
"nvueStyleCompiler" : "uni-app", "nvueStyleCompiler" : "uni-app",
"compilerVersion" : 3, "compilerVersion" : 3,
"screenOrientation" : [
//
"portrait-primary", //
"portrait-secondary", //
"landscape-primary", //
"landscape-secondary" //
],
"compatible" : { "compatible" : {
"ignoreVersion" : true //trueHBuilderX1.9.0 "ignoreVersion" : true //trueHBuilderX1.9.0
}, },
@ -34,7 +41,8 @@
"Payment" : {}, "Payment" : {},
"VideoPlayer" : {}, "VideoPlayer" : {},
"OAuth" : {}, "OAuth" : {},
"Camera" : {} "Camera" : {},
"Barcode" : {}
}, },
/* */ /* */
"distribute" : { "distribute" : {
@ -69,6 +77,7 @@
}, },
/* ios */ /* ios */
"ios" : { "ios" : {
"UIRequiresFullScreen" : false, //
"urlschemewhitelist" : [ "iosmap" ], "urlschemewhitelist" : [ "iosmap" ],
"dSYMs" : false, "dSYMs" : false,
"plistcmds" : [ "plistcmds" : [

View File

@ -31,6 +31,20 @@
"enablePullDownRefresh": true "enablePullDownRefresh": true
} }
}, },
{
"path": "pages/home/growth-package",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom"
}
},
{
"path": "pages/home/growth-package-result",
"style": {
"navigationBarTitleText": "支付结果",
"navigationStyle": "custom"
}
},
{ {
"path": "pages/message/message", "path": "pages/message/message",
"style": { "style": {
@ -89,8 +103,12 @@
"path": "pages/order/userorder-list", "path": "pages/order/userorder-list",
"style": { "style": {
"navigationBarTitleText": "订单", "navigationBarTitleText": "订单",
"navigationBarBackgroundColor": "#FFFFFF" "navigationBarBackgroundColor": "#FFFFFF",
"app-plus": {
"softinputNavBar": "none"
} }
}
}, },
{ {
"path": "pages/order/userorder-detail", "path": "pages/order/userorder-detail",
@ -150,7 +168,13 @@
} }
}, },
{ {
"path": "pages/add/add", "path": "pages/notice/notice_list",
"style": {
"navigationStyle": "custom"
}
},
{
"path": "pages/notice/detail",
"style": { "style": {
"navigationStyle": "custom" "navigationStyle": "custom"
} }
@ -221,6 +245,12 @@
"navigationStyle": "custom" "navigationStyle": "custom"
} }
}, },
{
"path": "pages/search_common/search",
"style": {
"navigationStyle": "custom"
}
},
{ {
"path": "pages/settings/index", "path": "pages/settings/index",
"style": { "style": {
@ -584,6 +614,30 @@
"navigationStyle": "custom" "navigationStyle": "custom"
} }
}, },
{
"path": "pages/shop/verify/verify-order",
"style": {
"navigationStyle": "custom"
}
},
{
"path": "pages/shop/verify/manual-verify",
"style": {
"navigationStyle": "custom"
}
},
{
"path": "pages/shop/verify/verify-fail",
"style": {
"navigationStyle": "custom"
}
},
{
"path": "pages/shop/verify/verify-order-detail",
"style": {
"navigationStyle": "custom"
}
},
{ {
"path": "pages/shop/photoAlbum/photoManage", "path": "pages/shop/photoAlbum/photoManage",
"style": { "style": {
@ -596,6 +650,14 @@
"navigationStyle": "custom" "navigationStyle": "custom"
} }
}, },
{
"path": "pages/shop/photoAlbum/videoplayer",
"style": {
"navigationBarTitleText": "全屏视频播放",
"pageOrientation": "auto",
"navigationStyle": "custom"
}
},
{ {
"path": "pages/shop/photoAlbum/videoList", "path": "pages/shop/photoAlbum/videoList",
"style": { "style": {
@ -943,6 +1005,43 @@
"style": { "style": {
"navigationBarTitleText": "拍摄技巧" "navigationBarTitleText": "拍摄技巧"
} }
},
{
"path": "pages/my/myFavorite",
"style": {
"navigationBarTitleText": "我的收藏",
"navigationStyle": "custom"
}
},
{
"path": "pages/jingxuan/selected-skills",
"style": {
"navigationStyle": "custom"
}
},
{
"path": "pages/jingxuan/selected-brands",
"style": {
"navigationStyle": "custom"
}
},
{
"path": "pages/jingxuan/brand-detail",
"style": {
"navigationStyle": "custom"
}
},
{
"path": "pages/jingxuan/skill-detail",
"style": {
"navigationStyle": "custom"
}
},
{
"path": "pages/ruzhu/successruzhu",
"style": {
"navigationBarTitleText": "入驻成功"
}
} }
@ -955,7 +1054,7 @@
}, },
"tabBar": { "tabBar": {
"color": "#999", "color": "#999",
"selectedColor": "#E8101E", "selectedColor": "#FF4767",
"backgroundColor": "#fff", "backgroundColor": "#fff",
"list": [{ "list": [{
"iconPath": "/static/images/tabbar/home_icon_dis.png", "iconPath": "/static/images/tabbar/home_icon_dis.png",
@ -963,7 +1062,14 @@
"selectedIconPath": "/static/images/tabbar/home_icon_active.png", "selectedIconPath": "/static/images/tabbar/home_icon_active.png",
"pagePath": "pages/home/home" "pagePath": "pages/home/home"
}, },
{ "iconPath": "/static/images/tabbar/new_message_gray.png", {
"iconPath": "/static/images/tabbar/new_order_gray.png",
"text": "订单",
"selectedIconPath": "/static/images/tabbar/new_order.png",
"pagePath": "pages/order/userorder-list"
},
{
"iconPath": "/static/images/tabbar/new_message_gray.png",
"text": "消息", "text": "消息",
"selectedIconPath": "/static/images/tabbar/new_message.png", "selectedIconPath": "/static/images/tabbar/new_message.png",
"pagePath": "pages/message/message" "pagePath": "pages/message/message"

View File

@ -55,7 +55,7 @@
<!-- 设为默认地址 --> <!-- 设为默认地址 -->
<view class="form-item switch-item"> <view class="form-item switch-item">
<text class="label">设为默认地址</text> <text class="label">设为默认地址</text>
<switch :checked="addressInfo.is_default == 1" @change="onSwitchChange" color="#E8101E" /> <switch :checked="addressInfo.is_default == 1" @change="onSwitchChange" color="#FF4767" />
</view> </view>
<!-- 顶部图标 --> <!-- 顶部图标 -->
<view class="biao"></view> <view class="biao"></view>
@ -622,7 +622,7 @@
.save-btn { .save-btn {
width: 630rpx; width: 630rpx;
height: 96rpx; height: 96rpx;
background-color: #E8101E; background-color: #FF4767;
border-radius: 44rpx; border-radius: 44rpx;
display: flex; display: flex;
justify-content: center; justify-content: center;

View File

@ -261,7 +261,7 @@
/* .tag { /* .tag {
font-size: 24rpx; font-size: 24rpx;
color: #E8101E; color: #FF4767;
background-color: rgba(252, 67, 124, 0.08); background-color: rgba(252, 67, 124, 0.08);
padding: 6rpx 16rpx; padding: 6rpx 16rpx;
border-radius: 6rpx; border-radius: 6rpx;
@ -370,7 +370,7 @@
width: 690rpx; width: 690rpx;
height: 78rpx; height: 78rpx;
border-radius: 39rpx; border-radius: 39rpx;
border: 1rpx solid #E8101E; border: 1rpx solid #FF4767;
text-align: center; text-align: center;
line-height: 64rpx; line-height: 64rpx;
display: flex; display: flex;
@ -383,7 +383,7 @@
font-family: PingFangSC, PingFang SC; font-family: PingFangSC, PingFang SC;
font-weight: 400; font-weight: 400;
font-size: 30rpx; font-size: 30rpx;
color: #E8101E; color: #FF4767;
line-height: 42rpx; line-height: 42rpx;
text-align: left; text-align: left;
font-style: normal; font-style: normal;

View File

@ -7,7 +7,7 @@
<!-- <view class="search-container"> <!-- <view class="search-container">
<text class="search-container-text" @click="goSelectCity">{{ city.name }}</text> <text class="search-container-text" @click="goSelectCity">{{ city.name }}</text>
<search-box v-model="searchKeyword" placeholder="请输入地址" width="571rpx" height="68rpx" <search-box v-model="searchKeyword" placeholder="请输入地址" width="571rpx" height="68rpx"
border="1px solid #E8101E" style="padding: 0;" @confirm="onSearch" :showBack="false"></search-box> border="1px solid #FF4767" style="padding: 0;" @confirm="onSearch" :showBack="false"></search-box>
</view> --> </view> -->
<view class="search-container"> <view class="search-container">
<text class="search-container-text" @click="goSelectCity"> <text class="search-container-text" @click="goSelectCity">
@ -858,7 +858,7 @@
flex: 1; flex: 1;
height: 68rpx; height: 68rpx;
background: #FFFFFF; background: #FFFFFF;
border: 2rpx solid #E8101E; border: 2rpx solid #FF4767;
border-radius: 60rpx; border-radius: 60rpx;
position: relative; position: relative;
@ -936,7 +936,7 @@
font-family: PingFangSC, PingFang SC; font-family: PingFangSC, PingFang SC;
font-weight: 400; font-weight: 400;
font-size: 26rpx; font-size: 26rpx;
color: #E8101E; color: #FF4767;
line-height: 34rpx; line-height: 34rpx;
text-align: center; text-align: center;
font-style: normal; font-style: normal;
@ -1124,7 +1124,7 @@
width: 48rpx; width: 48rpx;
height: 26rpx; height: 26rpx;
border-radius: 6rpx; border-radius: 6rpx;
background: #E8101E; background: #FF4767;
margin-right: 10rpx; margin-right: 10rpx;
&__text { &__text {

View File

@ -55,7 +55,7 @@
<!-- 设为默认地址 --> <!-- 设为默认地址 -->
<view class="form-item switch-item"> <view class="form-item switch-item">
<text class="label">设为默认地址</text> <text class="label">设为默认地址</text>
<switch :checked="addressInfo.is_default == 1" @change="onSwitchChange" color="#E8101E" /> <switch :checked="addressInfo.is_default == 1" @change="onSwitchChange" color="#FF4767" />
</view> </view>
<!-- 顶部图标 --> <!-- 顶部图标 -->
<view class="biao"></view> <view class="biao"></view>
@ -614,7 +614,7 @@
.save-btn { .save-btn {
width: 630rpx; width: 630rpx;
height: 96rpx; height: 96rpx;
background-color: #E8101E; background-color: #FF4767;
border-radius: 44rpx; border-radius: 44rpx;
display: flex; display: flex;
justify-content: center; justify-content: center;

View File

@ -666,7 +666,7 @@
flex: 1; flex: 1;
height: 68rpx; height: 68rpx;
background: #FFFFFF; background: #FFFFFF;
border: 2rpx solid #E8101E; border: 2rpx solid #FF4767;
border-radius: 60rpx; border-radius: 60rpx;
position: relative; position: relative;

View File

@ -6,37 +6,22 @@
<!-- 城市选择--> <!-- 城市选择-->
<view class="search-container" v-if="isSelectCity"> <view class="search-container" v-if="isSelectCity">
<text class="search-container-text" @click="goSelectCity">{{ city.name }}</text> <text class="search-container-text" @click="goSelectCity">{{ city.name }}</text>
<image src="https://mrrplus.oss-cn-beijing.aliyuncs.com/wxstaic/images/Fill.jpg" mode="aspectFit" class="text-img"></image> <image src="https://mrrplus.oss-cn-beijing.aliyuncs.com/wxstaic/images/Fill.jpg" mode="aspectFit"
class="text-img"></image>
</view> </view>
<!-- 地图容器 --> <!-- 地图容器 -->
<view class="map-container" :style="{ height: mapHeight + 'rpx' }"> <view class="map-container" :style="{ height: mapHeight + 'rpx' }">
<map <map v-if="mapVisible" :key="mapRenderKey" id="map" class="map" :latitude="latitude" :longitude="longitude"
v-if="mapVisible" scale="19" @tap="onMapTap" @regionchange="changeMap"></map>
:key="mapRenderKey"
id="map"
class="map"
:latitude="latitude"
:longitude="longitude"
scale="19"
@tap="onMapTap"
@regionchange="changeMap"
></map>
<image <image v-if="showMapSnapshot" class="map-snapshot" :src="mapSnapshotUrl" mode="aspectFill"
v-if="showMapSnapshot" @load="onSnapshotLoad" @error="onSnapshotError"></image>
class="map-snapshot"
:src="mapSnapshotUrl"
mode="aspectFill"
@load="onSnapshotLoad"
@error="onSnapshotError"
></image>
<cover-view v-if="mapVisible" class="center-marker"> <cover-view v-if="mapVisible" class="center-marker">
<cover-image <cover-image
src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/04007cab-3047-42b0-baab-44df344a92d2" src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/04007cab-3047-42b0-baab-44df344a92d2"
class="center-marker-img" class="center-marker-img"></cover-image>
></cover-image>
</cover-view> </cover-view>
</view> </view>
@ -44,13 +29,16 @@
<view class="bottom-edit-section"> <view class="bottom-edit-section">
<!-- 地址识别输入行 --> <!-- 地址识别输入行 -->
<view class="address-input-row"> <view class="address-input-row">
<textarea class="raw-address-input" v-model="rawAddress" placeholder="粘贴文本到此处,将自动识别地址信息。" placeholder-style="color: #C6C9CC; font-size: 14px;" :maxlength="200" :adjust-position="true" /> <textarea class="raw-address-input" v-model="rawAddress" placeholder="粘贴文本到此处,将自动识别地址信息。"
placeholder-style="color: #C6C9CC; font-size: 14px;" :maxlength="200" :adjust-position="true" />
<view class="action-buttons"> <view class="action-buttons">
<view class="action-btn paste-btn" @click="hasRawContent ? clearRawAddress() : onPaste()"> <view class="action-btn paste-btn" @click="hasRawContent ? clearRawAddress() : onPaste()">
<text class="btn-text" :style="{ color: '#333333' }">{{ hasRawContent ? '一键清空' : '粘贴' }}</text> <text class="btn-text" :style="{ color: '#333333' }">{{ hasRawContent ? '一键清空' : '粘贴' }}</text>
</view> </view>
<view class="action-btn smart-btn" :class="{ 'smart-btn-active': hasRawContent }" @click="onSmartRecognize"> <view class="action-btn smart-btn" :class="{ 'smart-btn-active': hasRawContent }"
<text class="btn-text" :style="{ color: hasRawContent ? '#E8101E' : '#999999' }">{{ smartBtnText }}</text> @click="onSmartRecognize">
<text class="btn-text"
:style="{ color: hasRawContent ? '#FF4767' : '#999999' }">{{ smartBtnText }}</text>
</view> </view>
</view> </view>
</view> </view>
@ -61,13 +49,17 @@
<text class="row-label">所在地区</text> <text class="row-label">所在地区</text>
<view class="row-content"> <view class="row-content">
<text :class="currentRegion ? 'content-text' : 'placeholder'">{{ currentRegion || "请选择"}}</text> <text :class="currentRegion ? 'content-text' : 'placeholder'">{{ currentRegion || "请选择"}}</text>
<image src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/71c63001-a104-49ad-a90d-30d2ade73f4d.png" mode="aspectFit" class="arrow-icon"></image> <image
src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/71c63001-a104-49ad-a90d-30d2ade73f4d.png"
mode="aspectFit" class="arrow-icon"></image>
</view> </view>
</view> </view>
<view class="line"></view> <view class="line"></view>
<view class="info-row"> <view class="info-row">
<text class="row-label">详细地址</text> <text class="row-label">详细地址</text>
<input type="text" class="detail-input" v-model="detailAddress" @input="onDetailInput" placeholder="请填写详细地址" placeholder-style="color: #999999; font-size: 14px;" :adjust-position="true" /> <input type="text" class="detail-input" v-model="detailAddress" @input="onDetailInput"
placeholder="请填写详细地址" placeholder-style="color: #999999; font-size: 14px;"
:adjust-position="true" />
</view> </view>
<view class="line"></view> <view class="line"></view>
</view> </view>
@ -89,32 +81,19 @@
<text class="popup-close" @click="closeRegionPicker">×</text> <text class="popup-close" @click="closeRegionPicker">×</text>
</view> </view>
<view class="region-body"> <view class="region-body">
<picker-view <picker-view @change="onRegionChange" class="picker-scroll" :indicator-style="indicatorStyle"
@change="onRegionChange" :value="regionPickerValue">
class="picker-scroll"
:indicator-style="indicatorStyle"
:value="regionPickerValue"
>
<picker-view-column> <picker-view-column>
<view <view class="picker-item" v-for="(item, index) in regionProvinceList" :key="index">
class="picker-item" {{ item.province }}</view>
v-for="(item, index) in regionProvinceList"
:key="index"
>{{ item.province }}</view>
</picker-view-column> </picker-view-column>
<picker-view-column> <picker-view-column>
<view <view class="picker-item" v-for="(item, index) in regionCityList" :key="index">
class="picker-item" {{ item.city }}</view>
v-for="(item, index) in regionCityList"
:key="index"
>{{ item.city }}</view>
</picker-view-column> </picker-view-column>
<picker-view-column> <picker-view-column>
<view <view class="picker-item" v-for="(item, index) in regionDistrictList" :key="index">
class="picker-item" {{ item.area }}</view>
v-for="(item, index) in regionDistrictList"
:key="index"
>{{ item.area }}</view>
</picker-view-column> </picker-view-column>
</picker-view> </picker-view>
</view> </view>
@ -135,7 +114,9 @@
import request from '@/utils/request' import request from '@/utils/request'
import ChinaCitys from './data/ChinaCitys.json' import ChinaCitys from './data/ChinaCitys.json'
import store from '@/store' import store from '@/store'
import { setVersion } from '@/utils/version.js' import {
setVersion
} from '@/utils/version.js'
export default { export default {
data() { data() {
@ -263,15 +244,16 @@
} }
this.startDependencyInitLock() this.startDependencyInitLock()
if (hasLocation) { if (hasLocation) {
this.applyMapLocation(options.longitude, options.latitude, true)
this.applyMapLocation(options.longitude, options.latitude, false)
return return
} }
const dependencyCode = options.dependency_code const dependencyCode = options.dependency_code
;(async () => { ;
(async () => {
let center = null let center = null
if (dependencyCode && regions[2]) { if (dependencyCode && regions[2]) {
@ -294,7 +276,7 @@
this.updateMapCenter( this.updateMapCenter(
parseFloat(locationRes[0]), parseFloat(locationRes[0]),
parseFloat(locationRes[1]), parseFloat(locationRes[1]),
true false
) )
} }
} else if (!skipAutoLocate) { } else if (!skipAutoLocate) {
@ -326,6 +308,7 @@
this.suppressInitDetailFill = true this.suppressInitDetailFill = true
} }
this.reverseGeocode(parseFloat(options.longitude), parseFloat(options.latitude)) this.reverseGeocode(parseFloat(options.longitude), parseFloat(options.latitude))
return return
} }
@ -504,6 +487,7 @@
this.mapReverseTimer = null this.mapReverseTimer = null
} }
if (!noReverse) { if (!noReverse) {
this.mapReverseTimer = setTimeout(() => { this.mapReverseTimer = setTimeout(() => {
this.reverseGeocode(lng, lat) this.reverseGeocode(lng, lat)
@ -556,7 +540,11 @@
}, },
findRegionIndexByCode(baseData, provinceCode, cityCode, areaCode) { findRegionIndexByCode(baseData, provinceCode, cityCode, areaCode) {
const result = { provinceIndex: -1, cityIndex: -1, areaIndex: -1 } const result = {
provinceIndex: -1,
cityIndex: -1,
areaIndex: -1
}
const targetProvinceCode = (provinceCode || '').slice(0, 6) const targetProvinceCode = (provinceCode || '').slice(0, 6)
const targetCityCode = (cityCode || '').slice(0, 6) const targetCityCode = (cityCode || '').slice(0, 6)
const targetAreaCode = (areaCode || '').slice(0, 6) const targetAreaCode = (areaCode || '').slice(0, 6)
@ -613,7 +601,10 @@
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const handleFail = (err) => { const handleFail = (err) => {
if (!silent) { if (!silent) {
uni.showToast({ title: '获取位置失败', icon: 'none' }) uni.showToast({
title: '获取位置失败',
icon: 'none'
})
} }
reject(err) reject(err)
} }
@ -966,7 +957,10 @@
clearRawAddress() { clearRawAddress() {
this.rawAddress = '' this.rawAddress = ''
uni.showToast({ title: '已清空', icon: 'none' }) uni.showToast({
title: '已清空',
icon: 'none'
})
}, },
onDetailInput(e) { onDetailInput(e) {
@ -982,7 +976,10 @@
success: (res) => { success: (res) => {
if (res.data) { if (res.data) {
this.rawAddress = res.data this.rawAddress = res.data
uni.showToast({ title: '已粘贴', icon: 'none' }) uni.showToast({
title: '已粘贴',
icon: 'none'
})
} }
} }
}) })
@ -1125,15 +1122,27 @@
validateRecognizedDetail(detailText, geo, hit = {}) { validateRecognizedDetail(detailText, geo, hit = {}) {
const cleaned = String(detailText || '').trim() const cleaned = String(detailText || '').trim()
if (!cleaned) { if (!cleaned) {
return { valid: false, cleaned: '', reason: 'empty' } return {
valid: false,
cleaned: '',
reason: 'empty'
}
} }
if (this.isLikelyInvalidRecognizedDetail(cleaned)) { if (this.isLikelyInvalidRecognizedDetail(cleaned)) {
return { valid: false, cleaned: '', reason: 'invalid_detail' } return {
valid: false,
cleaned: '',
reason: 'invalid_detail'
}
} }
if (!geo) { if (!geo) {
return { valid: false, cleaned: '', reason: 'geocode_failed' } return {
valid: false,
cleaned: '',
reason: 'geocode_failed'
}
} }
const geoLevel = String(geo?.level || '').trim() const geoLevel = String(geo?.level || '').trim()
@ -1156,14 +1165,26 @@
!/[A-Za-z]{6,}/.test(cleaned) !/[A-Za-z]{6,}/.test(cleaned)
if (hasAddressFeature || preciseLevel) { if (hasAddressFeature || preciseLevel) {
return { valid: true, cleaned, reason: '' } return {
valid: true,
cleaned,
reason: ''
}
} }
if (sameDistrict && purePoiLike) { if (sameDistrict && purePoiLike) {
return { valid: true, cleaned, reason: 'district_geo_verified' } return {
valid: true,
cleaned,
reason: 'district_geo_verified'
}
} }
return { valid: false, cleaned: '', reason: 'detail_not_precise' } return {
valid: false,
cleaned: '',
reason: 'detail_not_precise'
}
}, },
cleanRecognizedDetail(detail, province, city, district) { cleanRecognizedDetail(detail, province, city, district) {
@ -1425,10 +1446,14 @@
const lonlatParsed = this.parseLonlatInfo(res?.data?.lonlat || {}) const lonlatParsed = this.parseLonlatInfo(res?.data?.lonlat || {})
return { return {
province_name: (street.province_name || street.province || stdParsed.province_name || divisionParsed.province_name || '').trim(), province_name: (street.province_name || street.province || stdParsed.province_name ||
city_name: (street.city_name || street.city || stdParsed.city_name || divisionParsed.city_name || '').trim(), divisionParsed.province_name || '').trim(),
county_name: (street.county_name || street.district || street.county || stdParsed.county_name || divisionParsed.county_name || '').trim(), city_name: (street.city_name || street.city || stdParsed.city_name || divisionParsed.city_name ||
town_name: (street.town_name || street.town || street.street_name || stdParsed.town_name || divisionParsed.town_name || '').trim(), '').trim(),
county_name: (street.county_name || street.district || street.county || stdParsed.county_name ||
divisionParsed.county_name || '').trim(),
town_name: (street.town_name || street.town || street.street_name || stdParsed.town_name ||
divisionParsed.town_name || '').trim(),
road_name: (street.road_name || street.road || stdParsed.road_name || '').trim(), road_name: (street.road_name || street.road || stdParsed.road_name || '').trim(),
road_no: (street.road_no || street.roadno || stdParsed.road_no || '').trim(), road_no: (street.road_no || street.roadno || stdParsed.road_no || '').trim(),
poi_name: (street.poi_name || street.poi || stdParsed.poi_name || '').trim(), poi_name: (street.poi_name || street.poi || stdParsed.poi_name || '').trim(),
@ -1440,9 +1465,11 @@
block_no: (street.block_no || street.block || stdParsed.block_no || '').trim(), block_no: (street.block_no || street.block || stdParsed.block_no || '').trim(),
detail: (street.detail || street.address || stdParsed.detail || stdParsed.address || '').trim(), detail: (street.detail || street.address || stdParsed.detail || stdParsed.address || '').trim(),
address: (street.address || street.detail || stdParsed.address || stdParsed.detail || '').trim(), address: (street.address || street.detail || stdParsed.address || stdParsed.detail || '').trim(),
province_code: (street.province_code || stdParsed.province_code || divisionParsed.province_code || '').trim(), province_code: (street.province_code || stdParsed.province_code || divisionParsed.province_code ||
'').trim(),
city_code: (street.city_code || stdParsed.city_code || divisionParsed.city_code || '').trim(), city_code: (street.city_code || stdParsed.city_code || divisionParsed.city_code || '').trim(),
county_code: (street.county_code || street.district_code || stdParsed.county_code || divisionParsed.county_code || '').trim(), county_code: (street.county_code || street.district_code || stdParsed.county_code || divisionParsed
.county_code || '').trim(),
backend_gcj02: lonlatParsed.gcj02, backend_gcj02: lonlatParsed.gcj02,
backend_wgs84: lonlatParsed.wgs84, backend_wgs84: lonlatParsed.wgs84,
backend_level: lonlatParsed.level, backend_level: lonlatParsed.level,
@ -1680,13 +1707,19 @@
this.suppressInitDetailFill = false this.suppressInitDetailFill = false
if (!this.hasRawContent) { if (!this.hasRawContent) {
uni.showToast({ title: '请先粘贴或输入地址', icon: 'none' }) uni.showToast({
title: '请先粘贴或输入地址',
icon: 'none'
})
return return
} }
const originalRawText = (this.rawAddress || '').trim() const originalRawText = (this.rawAddress || '').trim()
if (!originalRawText) { if (!originalRawText) {
uni.showToast({ title: '请先粘贴或输入地址', icon: 'none' }) uni.showToast({
title: '请先粘贴或输入地址',
icon: 'none'
})
return return
} }
@ -1697,11 +1730,16 @@
const removedNoise = sanitizedText !== originalRawText const removedNoise = sanitizedText !== originalRawText
if (!sanitizedText) { if (!sanitizedText) {
uni.showToast({ title: '未提取到有效地址', icon: 'none' }) uni.showToast({
title: '未提取到有效地址',
icon: 'none'
})
return return
} }
uni.showLoading({ title: '识别中...' }) uni.showLoading({
title: '识别中...'
})
try { try {
const res = await this.requestRecognizeAddress(sanitizedText) const res = await this.requestRecognizeAddress(sanitizedText)
@ -1851,7 +1889,8 @@
showCancel: false showCancel: false
}) })
} else { } else {
const tip = this.getRecognizeToast(level, removedNoise, geocodeOk, hit, detailText, detailRejected) const tip = this.getRecognizeToast(level, removedNoise, geocodeOk, hit, detailText,
detailRejected)
if (tip.type === 'modal') { if (tip.type === 'modal') {
uni.showModal({ uni.showModal({
title: tip.title, title: tip.title,
@ -1868,7 +1907,8 @@
return return
} }
this.commitRecognizedResult(province, city, district, regionText, detailText, geo, level, removedNoise, geocodeOk, hit, detailRejected) this.commitRecognizedResult(province, city, district, regionText, detailText, geo, level,
removedNoise, geocodeOk, hit, detailRejected)
} catch (error) { } catch (error) {
console.error('智能识别失败:', error) console.error('智能识别失败:', error)
uni.hideLoading() uni.hideLoading()
@ -2015,7 +2055,8 @@
} }
}, },
commitRecognizedResult(province, city, district, regionText, detailText, geo, level, removedNoise, geocodeOk, hit, detailRejected) { commitRecognizedResult(province, city, district, regionText, detailText, geo, level, removedNoise, geocodeOk,
hit, detailRejected) {
this.currentProvince = province this.currentProvince = province
this.currentCity = city this.currentCity = city
this.currentDistrict = district this.currentDistrict = district
@ -2165,7 +2206,10 @@
const districtItem = this.regionDistrictList[districtIdx] const districtItem = this.regionDistrictList[districtIdx]
if (!provinceItem || !cityItem || !districtItem) { if (!provinceItem || !cityItem || !districtItem) {
uni.showToast({ title: '选择无效', icon: 'none' }) uni.showToast({
title: '选择无效',
icon: 'none'
})
return return
} }
@ -2195,7 +2239,10 @@
const [lng, lat] = center.split(',') const [lng, lat] = center.split(',')
this.updateMapCenter(parseFloat(lng), parseFloat(lat), true) this.updateMapCenter(parseFloat(lng), parseFloat(lat), true)
} else { } else {
uni.showToast({ title: '无法定位该地区,请手动拖动地图', icon: 'none' }) uni.showToast({
title: '无法定位该地区,请手动拖动地图',
icon: 'none'
})
} }
this.closeRegionPicker() this.closeRegionPicker()
@ -2221,7 +2268,8 @@
keywords: adcode.slice(0, 6) keywords: adcode.slice(0, 6)
}, },
success: (res) => { success: (res) => {
if (res.data.status === '1' && res.data.districts && res.data.districts.length > 0) { if (res.data.status === '1' && res.data.districts &&
res.data.districts.length > 0) {
const district = res.data.districts[0] const district = res.data.districts[0]
if (district.center) { if (district.center) {
resolveInner(district.center) resolveInner(district.center)
@ -2245,7 +2293,8 @@
keywords: keyword keywords: keyword
}, },
success: (res) => { success: (res) => {
if (res.data.status === '1' && res.data.districts && res.data.districts.length > 0) { if (res.data.status === '1' && res.data.districts &&
res.data.districts.length > 0) {
const district = res.data.districts[0] const district = res.data.districts[0]
if (district.center) { if (district.center) {
resolveInner(district.center) resolveInner(district.center)
@ -2301,6 +2350,7 @@
addressItem.cityname = "重庆郊县" addressItem.cityname = "重庆郊县"
} }
if (source === 'syr_info') { if (source === 'syr_info') {
uni.$emit('address-selected-for-syr', addressItem) uni.$emit('address-selected-for-syr', addressItem)
uni.setStorageSync('syr_selected_address', addressItem) uni.setStorageSync('syr_selected_address', addressItem)
@ -2417,7 +2467,8 @@
left: 0; left: 0;
right: 0; right: 0;
background-color: #FFFFFF; background-color: #FFFFFF;
padding: 20rpx 20rpx env(safe-area-inset-bottom) 20rpx; /* 适配刘海屏 */ padding: 20rpx 20rpx env(safe-area-inset-bottom) 20rpx;
/* 适配刘海屏 */
box-shadow: 0 -2rpx 10rpx rgba(0, 0, 0, 0.05); box-shadow: 0 -2rpx 10rpx rgba(0, 0, 0, 0.05);
z-index: 10; z-index: 10;
} }
@ -2483,8 +2534,8 @@
} }
.smart-btn.smart-btn-active { .smart-btn.smart-btn-active {
border-color: #E8101E; border-color: #FF4767;
color: #E8101E; color: #FF4767;
} }
.address-info-panel { .address-info-panel {
@ -2555,7 +2606,7 @@
} }
.confirm-btn { .confirm-btn {
background-color: #E8101E; background-color: #FF4767;
border-radius: 49rpx; border-radius: 49rpx;
height: 98rpx; height: 98rpx;
display: flex; display: flex;
@ -2582,10 +2633,12 @@
opacity: 0; opacity: 0;
transition: all 0.3s ease; transition: all 0.3s ease;
} }
.popup.show { .popup.show {
visibility: visible !important; visibility: visible !important;
opacity: 1 !important; opacity: 1 !important;
} }
.popup-mask { .popup-mask {
position: fixed; position: fixed;
top: 0; top: 0;
@ -2594,6 +2647,7 @@
bottom: 0; bottom: 0;
background-color: rgba(0, 0, 0, 0.5); background-color: rgba(0, 0, 0, 0.5);
} }
.popup-content { .popup-content {
position: relative; position: relative;
background-color: #ffffff; background-color: #ffffff;
@ -2603,9 +2657,11 @@
transition: transform 0.3s ease; transition: transform 0.3s ease;
max-height: 70vh; max-height: 70vh;
} }
.popup.show .popup-content { .popup.show .popup-content {
transform: translateY(0); transform: translateY(0);
} }
.popup-header { .popup-header {
display: flex; display: flex;
align-items: center; align-items: center;
@ -2614,23 +2670,28 @@
padding: 0 0 20rpx 0; padding: 0 0 20rpx 0;
border-bottom: 1rpx solid #F0F0F0; border-bottom: 1rpx solid #F0F0F0;
} }
.popup-title { .popup-title {
font-size: 32rpx; font-size: 32rpx;
font-weight: 500; font-weight: 500;
color: #333; color: #333;
} }
.popup-close { .popup-close {
font-size: 40rpx; font-size: 40rpx;
color: #999; color: #999;
padding: 10rpx; padding: 10rpx;
} }
.region-body { .region-body {
height: 400rpx; height: 400rpx;
overflow: hidden; overflow: hidden;
} }
.picker-scroll { .picker-scroll {
height: 400rpx; height: 400rpx;
} }
.picker-item { .picker-item {
height: 68rpx; height: 68rpx;
line-height: 68rpx; line-height: 68rpx;
@ -2638,12 +2699,14 @@
font-size: 28rpx; font-size: 28rpx;
color: #333; color: #333;
} }
.popup-footer { .popup-footer {
display: flex; display: flex;
margin-top: 30rpx; margin-top: 30rpx;
padding-top: 20rpx; padding-top: 20rpx;
border-top: 1rpx solid #F0F0F0; border-top: 1rpx solid #F0F0F0;
} }
.popup-btn { .popup-btn {
flex: 1; flex: 1;
height: 88rpx; height: 88rpx;
@ -2653,22 +2716,28 @@
justify-content: center; justify-content: center;
margin: 0 16rpx; margin: 0 16rpx;
} }
.popup-btn.cancel { .popup-btn.cancel {
background-color: #f5f5f5; background-color: #f5f5f5;
} }
.popup-btn.confirm { .popup-btn.confirm {
background: #e8101e; background: #FF4767;
} }
.popup-btn .btn-text { .popup-btn .btn-text {
font-size: 32rpx; font-size: 32rpx;
font-weight: 500; font-weight: 500;
} }
.popup-btn.cancel .btn-text { .popup-btn.cancel .btn-text {
color: #666666; color: #666666;
} }
.popup-btn.confirm .btn-text { .popup-btn.confirm .btn-text {
color: #ffffff; color: #ffffff;
} }
/* 指示器样式(沿用原有) */ /* 指示器样式(沿用原有) */
.indicatorStyle { .indicatorStyle {
height: 68rpx; height: 68rpx;

View File

@ -274,7 +274,7 @@
flex: 1; flex: 1;
height: 68rpx; height: 68rpx;
background: #FFFFFF; background: #FFFFFF;
border: 2rpx solid #E8101E; border: 2rpx solid #FF4767;
background-color: #fafafa; background-color: #fafafa;
display: flex; display: flex;
align-items: center; align-items: center;

View File

@ -8,7 +8,7 @@
></custom-navbar> ></custom-navbar>
<!-- <view class="search-container"> <!-- <view class="search-container">
<search-box v-model="searchKeyword" placeholder="请输入你的服务地址" width="690rpx" height="68rpx" <search-box v-model="searchKeyword" placeholder="请输入你的服务地址" width="690rpx" height="68rpx"
border="1px solid #E8101E" style="padding: 0;" @confirm="onSearch" :showBack="false"></search-box> border="1px solid #FF4767" style="padding: 0;" @confirm="onSearch" :showBack="false"></search-box>
</view> </view>
<scroll-view scroll-y class="hao-scroll"> <scroll-view scroll-y class="hao-scroll">
<view class="hot-citys"> <view class="hot-citys">

View File

@ -1,822 +1,88 @@
<template> <template>
<view style="z-index: 100;"> <view class="video-page">
<!-- 视频滑动主容器 --> <!-- 原生视频组件:全端兼容 -->
<view class="view-box" :style="viewTopLength"> <video id="fullVideo" class="video-box" :src="videoUrl" controls show-fullscreen-btn enable-progress-gesture
<!-- 复用的5个视频容器 - 核心复用节点,不可删减 --> :autoplay="false" :loop="false" :muted="false" @play="onPlay" @pause="onPause"
<view class="video-box" :style="itemViewTopLength0"> @fullscreenchange="handleFullScreenChange" @ended="onVideoEnd"></video>
<video :src="videoInfo_0.src" :style="fillScreen" :autoplay="videoInfo_0.autoplay"
:loop="videoInfo_0.loop" :controls="videoInfo_0.controls"
:enable-play-gesture="videoInfo_0.enablePlayGesture" :objectFit="videoInfo_0.objectFit || objectFit"
:show-fullscreen-btn="videoInfo_0.showFullscreenBtn"
:enable-progress-gesture="videoInfo_0.enableProgressGesture" @timeupdate="timeupdate(0,$event)"
@ended='ended' :show-play-btn="videoInfo_0.showPlayBtn" :show-progress="videoInfo_0.showProgress"
initial-time="0" id='video_id_0' @play="playing(0)" :muted="videoInfo_0.isMuted"
webkit-playsinline="true" playsinline="true">
</video>
<cover-view v-if="!videoInfo_0.flag" :style="stopIcon" class="cover-view-stop" />
<cover-view v-if="cover && videoInfo_0.coverStatus" :style="fillScreen2" class="video-image">
<image :mode="videoInfo_0.mode || mode" :src="videoInfo_0.coverUrl" :style="fillScreen"></image>
</cover-view>
<view class="video-action" @touchstart.stop='videotouchstart' @touchmove.stop="videotochmove"
@touchend.stop='videotouchend' @click.stop="videoClick"></view>
<!-- 视频文本区域 - 每个视频都有 -->
<view class="video-texts">
<view class="flex-row-center" style="flex: 1;">
<text class="video-title">{{ videoInfo_0.src }}</text>
<text class="video-score">评分 4.8</text>
</view>
<view class="flex-row-center-between" style="flex: 1;">
<text class="video-text">{{videoInfo_0.name}}</text>
<!-- 声音图标 - 绑定0号视频的状态点击切换静音 -->
<image class="video-sound"
:src="videoInfo_0.isMuted ? '/static/images/icons/sound_no.png' : '/static/images/icons/sound_yes.png'"
@click.stop="toggleMute(0)"></image>
</view>
</view>
</view>
<view class="video-box" :style="itemViewTopLength1">
<video :src="videoInfo_1.src" :style="fillScreen" :autoplay="videoInfo_1.autoplay"
:loop="videoInfo_1.loop" :controls="videoInfo_1.controls"
:enable-play-gesture="videoInfo_1.enablePlayGesture" :objectFit="videoInfo_1.objectFit || objectFit"
:show-fullscreen-btn="videoInfo_1.showFullscreenBtn"
:enable-progress-gesture="videoInfo_1.enableProgressGesture" @timeupdate="timeupdate(1,$event)"
@ended='ended' :show-play-btn="videoInfo_1.showPlayBtn" :show-progress="videoInfo_1.showProgress"
initial-time="0" id='video_id_1' @play="playing(1)" :muted="videoInfo_1.isMuted"
webkit-playsinline="true" playsinline="true">
</video>
<cover-view v-if="!videoInfo_1.flag" :style="stopIcon" class="cover-view-stop" />
<cover-view v-if="cover && videoInfo_1.coverStatus" :style="fillScreen2" class="video-image">
<image :mode="videoInfo_1.mode || mode" :src="videoInfo_1.coverUrl" :style="fillScreen"></image>
</cover-view>
<view class="video-action" @touchstart='videotouchstart' @touchmove="videotochmove"
@touchend='videotouchend' @click="videoClick"></view>
<!-- 视频文本区域 - 1号视频 -->
<view class="video-texts">
<view class="flex-row-center" style="flex: 1;">
<text class="video-title">珍草品汇理疗馆珍馆服务流程11订单</text>
<text class="video-score">评分 4.8</text>
</view>
<view class="flex-row-center-between" style="flex: 1;">
<text class="video-text">{{videoInfo_1.name}}</text>
<!-- 声音图标 - 绑定1号视频的状态 -->
<image class="video-sound"
:src="videoInfo_1.isMuted ? '/static/images/icons/sound_no.png' : '/static/images/icons/sound_yes.png'"
@click.stop="toggleMute(1)"></image>
</view>
</view>
</view>
<view class="video-box" :style="itemViewTopLength2">
<video :src="videoInfo_2.src" :style="fillScreen" :autoplay="videoInfo_2.autoplay"
:loop="videoInfo_2.loop" :controls="videoInfo_2.controls"
:enable-play-gesture="videoInfo_2.enablePlayGesture" :objectFit="videoInfo_2.objectFit || objectFit"
:show-fullscreen-btn="videoInfo_2.showFullscreenBtn"
:enable-progress-gesture="videoInfo_2.enableProgressGesture" @timeupdate="timeupdate(2,$event)"
@ended='ended' :show-play-btn="videoInfo_2.showPlayBtn" :show-progress="videoInfo_2.showProgress"
initial-time="0" id='video_id_2' @play="playing(2)" :muted="videoInfo_2.isMuted"
webkit-playsinline="true" playsinline="true">
</video>
<cover-view v-if="!videoInfo_2.flag" :style="stopIcon" class="cover-view-stop" />
<cover-view v-if="cover && videoInfo_2.coverStatus" :style="fillScreen2" class="video-image">
<image :mode="videoInfo_2.mode || mode" :src="videoInfo_2.coverUrl" :style="fillScreen"></image>
</cover-view>
<view class="video-action" @touchstart='videotouchstart' @touchmove="videotochmove"
@touchend='videotouchend' @click="videoClick"></view>
<!-- 视频文本区域 - 2号视频 -->
<view class="video-texts">
<view class="flex-row-center" style="flex: 1;">
<text class="video-title">珍草品汇理疗馆珍馆服务流程11订单</text>
<text class="video-score">评分 4.8</text>
</view>
<view class="flex-row-center-between" style="flex: 1;">
<text class="video-text">{{videoInfo_2.name}}</text>
<!-- 声音图标 - 绑定2号视频的状态 -->
<image class="video-sound"
:src="videoInfo_2.isMuted ? '/static/images/icons/sound_no.png' : '/static/images/icons/sound_yes.png'"
@click.stop="toggleMute(2)"></image>
</view>
</view>
</view>
<view class="video-box" :style="itemViewTopLength3">
<video :src="videoInfo_3.src" :style="fillScreen" :autoplay="videoInfo_3.autoplay"
:loop="videoInfo_3.loop" :controls="videoInfo_3.controls"
:enable-play-gesture="videoInfo_3.enablePlayGesture" :objectFit="videoInfo_3.objectFit || objectFit"
:show-fullscreen-btn="videoInfo_3.showFullscreenBtn"
:enable-progress-gesture="videoInfo_3.enableProgressGesture" @timeupdate="timeupdate(3,$event)"
@ended='ended' :show-play-btn="videoInfo_3.showPlayBtn" :show-progress="videoInfo_3.showProgress"
initial-time="0" id='video_id_3' @play="playing(3)" :muted="videoInfo_3.isMuted"
webkit-playsinline="true" playsinline="true">
</video>
<cover-view v-if="!videoInfo_3.flag" :style="stopIcon" class="cover-view-stop" />
<cover-view v-if="cover && videoInfo_3.coverStatus" :style="fillScreen2" class="video-image">
<image :mode="videoInfo_3.mode || mode" :src="videoInfo_3.coverUrl" :style="fillScreen"></image>
</cover-view>
<view class="video-action" @touchstart='videotouchstart' @touchmove="videotochmove"
@touchend='videotouchend' @click="videoClick"></view>
<!-- 视频文本区域 - 3号视频 -->
<view class="video-texts">
<view class="flex-row-center" style="flex: 1;">
<text class="video-title">珍草品汇理疗馆珍馆服务流程11订单</text>
<text class="video-score">评分 4.8</text>
</view>
<view class="flex-row-center-between" style="flex: 1;">
<text class="video-text">{{videoInfo_3.name}}</text>
<!-- 声音图标 - 绑定3号视频的状态 -->
<image class="video-sound"
:src="videoInfo_3.isMuted ? '/static/images/icons/sound_no.png' : '/static/images/icons/sound_yes.png'"
@click.stop="toggleMute(3)"></image>
</view>
</view>
</view>
<view class="video-box" :style="itemViewTopLength4">
<video :src="videoInfo_4.src" :style="fillScreen" :autoplay="videoInfo_4.autoplay"
:loop="videoInfo_4.loop" :controls="videoInfo_4.controls"
:enable-play-gesture="videoInfo_4.enablePlayGesture" :objectFit="videoInfo_4.objectFit || objectFit"
:show-fullscreen-btn="videoInfo_4.showFullscreenBtn"
:enable-progress-gesture="videoInfo_4.enableProgressGesture" @timeupdate="timeupdate(4,$event)"
@ended='ended' :show-play-btn="videoInfo_4.showPlayBtn" :show-progress="videoInfo_4.showProgress"
initial-time="0" id='video_id_4' @play="playing(4)" :muted="videoInfo_4.isMuted"
webkit-playsinline="true" playsinline="true">
</video>
<cover-view v-if="!videoInfo_4.flag" :style="stopIcon" class="cover-view-stop" />
<cover-view v-if="cover && videoInfo_4.coverStatus" :style="fillScreen2" class="video-image">
<image :mode="videoInfo_4.mode || mode" :src="videoInfo_4.coverUrl" :style="fillScreen"></image>
</cover-view>
<view class="video-action" @touchstart='videotouchstart' @touchmove="videotochmove"
@touchend='videotouchend' @click="videoClick"></view>
<!-- 视频文本区域 - 4号视频 -->
<view class="video-texts">
<view class="flex-row-center" style="flex: 1;">
<text class="video-title">珍草品汇理疗馆珍馆服务流程11订单</text>
<text class="video-score">评分 4.8</text>
</view>
<view class="flex-row-center-between" style="flex: 1;">
<text class="video-text">{{videoInfo_4.name}}</text>
<!-- 声音图标 - 绑定4号视频的状态 -->
<image class="video-sound"
:src="videoInfo_4.isMuted ? '/static/images/icons/sound_no.png' : '/static/images/icons/sound_yes.png'"
@click.stop="toggleMute(4)"></image>
</view>
</view>
</view>
<view @touchend='progressTouchend' class="progress-view">
<uv-slider v-if="showSlider" v-model="progressValue" activeColor="#D8D8D8" block-size="6"
backgroundColor="#494949;" class="progress-slider"></uv-slider>
</view>
<!-- 修改Dot指示器 - 最多显示5个 -->
<view class="dots" :style="{top:`${0.5*winHeight}px`}" v-if="videoListLength > 1">
<view class="dots-container">
<view class="dot-item" v-for="(dotIndex, idx) in visibleDots" :key="idx"
:class="{ active: dotIndex === videoIndex }" @click="jumpToVideo(dotIndex)"></view>
</view>
<text class="pageNumber">
{{ videoIndex+1 }}/{{ videoListLength }}
</text>
</view>
<!-- 自定义操作按钮 -->
<view class="btn-wrap">
<button type="primary" size="default" @click="openFullScreen">
手动横屏全屏播放
</button>
<button type="warn" size="default" @click="closeFullScreen">
退出全屏
</button>
</view> </view>
</view> </view>
</template> </template>
<script> <script>
let VIDEO_LIST = []
let initVideoInfo = {
src: "",
coverStatus: true,
coverUrl: "",
flag: false,
objectFit: "",
mode: "",
isMuted: false, // 默认不静音
autoplay: false,
loop: true,
controls: false,
enablePlayGesture: true,
showFullscreenBtn: false,
enableProgressGesture: false,
showPlayBtn: false,
showProgress: false
}
export default { export default {
props: {
popVideoList: {
type: Array,
default: [] // 默认值设为空数组JSON避免parse报错
},
marginTop: {
type: String,
default: "88" // 默认值设为空数组JSON避免parse报错
}
},
data() { data() {
return { return {
playSetTime:null, // 测试视频地址,替换自己的
showSlider: true, videoUrl: "https://www.w3school.com.cn/i/movie.mp4",
progressTime: 0, videoContext: null
progressValue: 0,
boxHeight: 0,
objectFit: "fill",
mode: "scaleToFill",
winWidth: 1,
winHeight: 1,
videoIndex: 0,
viewTop: 0,
viewTopPostion: 0,
videoList: [],
videoListLength: 0,
itemViewTop0: 0,
itemViewTop1: 0,
itemViewTop2: 0,
itemViewTop3: 0,
itemViewTop4: 0,
videoInfo_0: initVideoInfo,
videoInfo_1: initVideoInfo,
videoInfo_2: initVideoInfo,
videoInfo_3: initVideoInfo,
videoInfo_4: initVideoInfo,
stopIcon: '',
videotouchstartTimestamp: 0,
videotouchendTimestamp: 0,
moveView: true,
cover: true,
slidingStatus: false,
videoPlayingStatus: false,
preloadedIndex: [],
startPageY: 0,
endPageY: 0,
// 新增控制可视dot的数组
visibleDots: [],
}; };
}, },
watch: { onReady() {
// videoList: { // 初始化视频实例
// handler(newVal, oldVal) { this.videoContext = uni.createVideoContext("fullVideo", this);
// },
// immediate: true, // 可选:组件初始化时立即执行一次(即使值未变化)
// deep: false // 普通类型无需深度监听默认false
// }
},
created(options) {
//#ifdef APP-PLUS
plus.screen.lockOrientation("portrait-primary")
//#endif
if (this.popVideoList.length) {
try {
VIDEO_LIST = []
this.popVideoList.forEach((item, index) => {
let obj = {
"src": "",
"coverStatus": true,
"coverUrl": "",
"flag": false,
"objectFit": "contain",
"mode": "aspectFit",
"isMuted": false, // 默认不静音
"autoplay": false,
"loop": true,
"controls": false,
"enablePlayGesture": true,
"showFullscreenBtn": false,
"enableProgressGesture": false,
"showPlayBtn": false,
"showProgress": false,
"name": ""
}
obj.name = item.name
obj.src = item.url
obj.coverUrl = item.url +
`?x-oss-process=video/snapshot,t_1000,m_fast,f_jpg,w_600,ar_auto`
VIDEO_LIST.push(obj)
if (index == 0) {
initVideoInfo = obj
}
})
} catch (e) {}
this.getSystemInfo();
this.videoList = VIDEO_LIST;
this.videoListLength = this.videoList.length;
this.boxHeight = this.videoListLength * this.winHeight;
for (let i = 0; i < 5; i++) {
if (this.videoList[i]) {
this['videoInfo_' + i] = this.videoList[i]
}
}
// 初始化可视dot范围
this.updateVisibleDots();
// setTimeout(() => {
// this.playVideo(0)
// }, 500)
}
},
onUnload() {
for (let i = 0; i < 5; i++) {
this.unloadVideo(i)
}
},
computed: {
getVideoTop() {
return uni.upx2px(this.marginTop)
},
viewTopLength() {
return `height:${this.boxHeight}px;top:${this.viewTop}px;`
},
fillScreen() {
let style = `height:${this.winHeight}px;width:${this.winWidth}px;`
return style
},
fillScreen2() {
let style = `height:auto;width:${this.winWidth}px;`
return style
},
itemViewTopLength0() {
return `height:${this.winHeight}px;top:${this.itemViewTop0}px;`
},
itemViewTopLength1() {
return `height:${this.winHeight}px;top:${this.itemViewTop1}px;`
},
itemViewTopLength2() {
return `height:${this.winHeight}px;top:${this.itemViewTop2}px;`
},
itemViewTopLength3() {
return `height:${this.winHeight}px;top:${this.itemViewTop3}px;`
},
itemViewTopLength4() {
return `height:${this.winHeight}px;top:${this.itemViewTop4}px;`
}
}, },
methods: { methods: {
// 新增:切换视频静音状态 // 进入横屏全屏
toggleMute(videoNum) { openFullScreen() {
// 1. 切换数据层状态 // direction 90横屏-90反向横屏0自适应
this['videoInfo_' + videoNum].isMuted = !this['videoInfo_' + videoNum].isMuted; this.videoContext.requestFullScreen({
// 2. 同步视频实例静音状态(恢复并完善原有注释代码,加容错) direction: 90
const videoCtx = uni.createVideoContext("video_id_" + videoNum, this); });
if (videoCtx) {
videoCtx.mute(this['videoInfo_' + videoNum].isMuted);
}
}, },
// 修改点击dot跳转 - 传真实的视频索引 // 退出全屏
jumpToVideo(targetIndex) { closeFullScreen() {
if (targetIndex === this.videoIndex || this.slidingStatus) return; this.videoContext.exitFullScreen();
this.stopVideo(this.videoIndex % 5, true);
const diff = targetIndex - this.videoIndex;
this.videoIndex = targetIndex;
this.viewTopPostion = -this.videoIndex * this.winHeight;
this.viewTop = this.viewTopPostion;
if (this.videoListLength > 5) {
this.sortItemView(diff > 0 ? -1 : 1);
}
// 更新可视dot范围
this.updateVisibleDots();
setTimeout(() => {
this.playVideo(this.videoIndex % 5);
}, 400);
}, },
// 核心更新可视dot范围 - 最多显示5个 // 播放监听
updateVisibleDots() { onPlay() {
const maxShow = 5; console.log("视频开始播放");
const total = this.videoListLength;
// 视频总数 ≤ 5显示全部
if (total <= maxShow) {
this.visibleDots = Array.from({
length: total
}, (_, i) => i);
return;
}
// 视频总数 > 5显示包含当前索引的5个dot
// 计算起始索引,避免越界
let start = Math.max(0, Math.min(this.videoIndex - 2, total - maxShow));
// 生成5个连续的索引
this.visibleDots = Array.from({
length: maxShow
}, (_, i) => start + i);
}, },
progressTouchend() { // 暂停监听
let s = Math.round(this.progressValue / 100 * this.time) onPause() {
let i = this.videoIndex % 5 console.log("视频暂停");
uni.createVideoContext("video_id_" + i, this).seek(s)
uni.createVideoContext("video_id_" + i, this).play()
}, },
sliderchanging(e) { // 全屏状态切换监听
console.log(3333, e) handleFullScreenChange(e) {
}, if (e.detail.fullScreen) {
getSystemInfo() { uni.setNavigationBarHidden(true); // 全屏隐藏顶部导航
var _this = this;
uni.getSystemInfo({
success: function(res) {
_this.winWidth = res.windowWidth;
_this.winHeight = res.windowHeight;
let p = uni.upx2px(150)
_this.stopIcon = `left:${(res.windowWidth - p)/2}px;top:${(res.windowHeight - p)/2}px;`
_this.itemViewTop1 = res.windowHeight
_this.itemViewTop2 = res.windowHeight * 2
_this.itemViewTop3 = res.windowHeight * 3
_this.itemViewTop4 = res.windowHeight * 4
},
})
},
unloadVideo(index) {
if (index < 0 || index >= this.videoListLength) return;
const nodeNum = index % 5;
const videoCtx = uni.createVideoContext("video_id_" + nodeNum, this);
videoCtx.stop();
this.preloadedIndex = this.preloadedIndex.filter(item => item !== index);
},
playVideo(num) {
clearTimeout(this.playSetTime)
uni.$uv.debounce(() => {
this.videoPlayingStatus = true
this["videoInfo_" + num].flag = true
let VideoContext = uni.createVideoContext("video_id_" + num, this)
this.playSetTime = setTimeout(() => {
VideoContext.play()
}, 400)
}, 30)
},
stopVideo(num, control = false) {
const videoCtx = uni.createVideoContext("video_id_" + num, this);
if (!control) {
this['videoInfo_' + num].coverStatus = true;
videoCtx.stop()
} else { } else {
videoCtx.pause() uni.setNavigationBarHidden(false); // 退出恢复导航
} }
this["videoInfo_" + num].flag = false console.log("当前全屏状态:", e.detail.fullScreen);
}, },
nowPlayVideo() { // 视频播放结束
clearTimeout(this.playSetTime) onVideoEnd() {
uni.$uv.debounce(() => { // 播放完毕自动退出全屏
this.videoPlayingStatus = true this.videoContext.exitFullScreen();
this["videoInfo_" + this.videoIndex].flag = true
let VideoContext = uni.createVideoContext("video_id_" + this.videoIndex, this)
this.playSetTime = setTimeout(() => {
VideoContext.play()
}, 400)
}, 30)
},
nowStopVideo() {
const videoCtx = uni.createVideoContext("video_id_" + this.videoIndex, this);
videoCtx.pause()
this["videoInfo_" + this.videoIndex].flag = false
},
videoClick() {
let num = this.videoIndex % 5
if (this["videoInfo_" + num].flag) {
this.stopVideo(num, true)
} else {
this.playVideo(num, true)
}
},
videotouchstart(e) {
this.videotouchendTimestamp = this.videotouchstartTimestamp
this.videotouchstartTimestamp = e.timestamp
if ((this.videotouchstartTimestamp - this.videotouchendTimestamp) < 500) return
if (this.slidingStatus) return
this.startPageY = e.changedTouches[0].screenY;
},
videotochmove(e) {
if ((this.videotouchstartTimestamp - this.videotouchendTimestamp) < 500) return
if (this.slidingStatus) return
this.endPageY = e.changedTouches[0].screenY;
let sliding = this.endPageY - this.startPageY
if (sliding > 20 || sliding < -20) {
this.moveView = false
} else {
this.moveView = true
}
if (this.videoIndex == 0 && sliding > 50) {
this.viewTop = 50
} else if (this.videoIndex == this.videoListLength - 1 && sliding < 0) {
this.viewTop = this.viewTopPostion
} else {
this.viewTop = this.viewTopPostion + sliding
}
},
videotouchend(e) {
if ((this.videotouchstartTimestamp - this.videotouchendTimestamp) < 500) return
if (this.slidingStatus) return
this.moveView = true
this.endPageY = e.changedTouches[0].screenY;
let sliding = this.endPageY - this.startPageY
if ((sliding >= -40 && sliding < 0) || (sliding <= 40 && sliding > 0)) {
this.slidingStatus = true
this.videoSlidingReset(sliding)
return
}
if (sliding < -30) {
this.slidingStatus = true
if (this.videoIndex == this.videoListLength - 1) {
this.videoSlidingReset(sliding)
uni.showToast({
title: "已经到底了",
icon: "none"
})
return
}
this.moveView = false
this.videoSlidingToTop(sliding)
return
}
if (sliding > 30) {
this.slidingStatus = true
if (this.videoIndex == 0) {
this.videoSlidingReset(sliding)
return
}
this.moveView = false
this.videoSlidingToBottom(sliding)
}
},
videoSlidingReset(sliding) {
this.viewTop = this.viewTopPostion
this.slidingStatus = false
},
videoSlidingToTop(sliding) {
this.stopVideo(this.videoIndex % 5, true)
this.videoIndex++
if (this.videoListLength > 5) {
this.sortItemView(sliding)
}
this.viewTopPostion = this.viewTopPostion - this.winHeight
setTimeout(() => {
this.playVideo(this.videoIndex % 5)
}, 5)
let timer = setInterval(() => {
this.viewTop = this.viewTop - 35
if (this.viewTop < (this.viewTopPostion + 10)) {
this.viewTop = this.viewTopPostion
clearInterval(timer)
this.slidingStatus = false
this.slidingCallback()
}
}, 3)
},
videoSlidingToBottom(sliding) {
this.stopVideo(this.videoIndex % 5, true)
this.videoIndex--
if (this.videoListLength > 5) {
this.sortItemView(sliding)
}
this.viewTopPostion = this.viewTopPostion + this.winHeight
setTimeout(() => {
this.playVideo(this.videoIndex % 5)
}, 5)
let timer = setInterval(() => {
this.viewTop = this.viewTop + 35
if (this.viewTop > (this.viewTopPostion - 10)) {
this.viewTop = this.viewTopPostion
clearInterval(timer)
this.slidingStatus = false
this.slidingCallback()
}
}, 3)
},
// 修改滑动结束后更新可视dot
slidingCallback() {
this.progressValue = 0
this.updateVisibleDots();
},
//滑动组件排序
sortItemView(silding) {
// 向上滑动
if (silding < 0) {
if (this.videoIndex > 2 && this.videoIndex < this.videoListLength - 2) {
let i = (this.videoIndex - 3) % 5
this["itemViewTop" + i] = this["itemViewTop" + i] + this.winHeight * 5
this['videoInfo_' + i] = this.videoList[this.videoIndex + 2]
}
return
}
// 向下滑动
if (silding > 0) {
if (this.videoIndex > 1 && this.videoIndex < this.videoListLength - 3) {
let i = (this.videoIndex + 3) % 5
this["itemViewTop" + i] = this["itemViewTop" + i] - this.winHeight * 5
this['videoInfo_' + i] = this.videoList[this.videoIndex - 2]
}
}
},
playing(i) {
setTimeout(() => {
this['videoInfo_' + i].coverStatus = false
this.moveView = true
this.slidingStatus = false
}, 600)
},
timeupdate(i, e) {
if (this.videoPlayingStatus) {
this.slidingStatus = false
this.videoPlayingStatus = false
setTimeout(() => {
this['videoInfo_' + i].coverStatus = false
this.moveView = true
}, 200)
}
this["videoInfo_" + i].flag = true
if (e.detail.duration >= this.progressTime) {
if (this.videoIndex%5 == i) {
this.time = e.detail.duration
this.progress = e.detail.currentTime
this.progressValue = (e.detail.currentTime / e.detail.duration) * 100
}
this.showProgress = true
} else {
this.showProgress = false
}
},
ended() {
let num = this.videoIndex % 5
this["videoInfo_" + num].flag = false
this.progressValue = 0
}
} }
} }
};
</script> </script>
<style scoped lang="less"> <style scoped>
.view-box { .video-page {
// position: fixed; padding: 15rpx;
// left: 0;
// right: 0;
background-color: #000;
// z-index: 900;
} }
.video-box { .video-box {
position: absolute; width: 100%;
left: 0; height: 420rpx;
right: 0; border-radius: 12rpx;
z-index: 2000;
}
.video-image {
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
z-index: 2001;
}
.video-action {
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
z-index: 2008;
}
.video-texts {
position: absolute;
left: 30rpx;
right: 30rpx;
bottom: 120rpx;
z-index: 2009; // 确保在视频上方显示
.video-title {
font-weight: 500;
font-size: 24rpx;
color: #FFFFFF;
text-align: left;
font-style: normal;
lines: 1;
max-width: 240rpx;
}
.video-score {
font-weight: 500;
font-size: 24rpx;
color: #FFFFFF;
text-align: left;
font-style: normal;
margin-left: 20rpx;
}
.video-text {
font-weight: 400;
font-size: 28rpx;
color: #FFFFFF;
text-align: left;
font-style: normal;
}
.video-sound {
width: 44rpx;
height: 42rpx;
cursor: pointer; // 点击指针,提示可点击
}
}
.cover-view-stop {
position: absolute;
z-index: 9999;
width: 150rpx;
height: 200rpx;
background-color: rgba(0, 0, 0, 0.3);
border-radius: 50%;
}
.progress-view {
z-index: 9999;
position: fixed;
left: 30rpx;
right: 30rpx;
bottom: 80rpx;
.progress-slider {}
}
// 修改Dot指示器样式 - 最多显示5个 + 过渡动画
.dots {
position: fixed;
left: 20rpx;
top: 0;
transform: translateY(-50%);
z-index: 9999;
flex-direction: row;
.dots-container {
// 限制最多显示5个超出隐藏
width: fit-content;
overflow: hidden; overflow: hidden;
margin: auto 0;
.dot-item {
width: 10rpx;
height: 10rpx;
background: #FFFFFF;
border-radius: 50%;
// 核心:过渡动画,切换更丝滑
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
cursor: pointer;
margin-bottom: 10rpx;
&.active {
width: 10rpx;
height: 30rpx;
background: #FFFFFF;
border-radius: 5rpx;
}
}
} }
.pageNumber { .btn-wrap {
font-weight: bold; margin-top: 30rpx;
font-size: 28rpx;
color: #FFFFFF;
line-height: 36rpx;
text-align: left;
font-style: normal;
margin-left: 6rpx;
}
}
.flex-row-center-between {
display: flex; display: flex;
flex-direction: row; gap: 20rpx;
align-items: center;
justify-content: space-between;
}
.flex-row-start-between {
display: flex;
flex-direction: row;
align-items: flex-start;
justify-content: space-between;
}
.flex-row-center-center {
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
}
.flex-row-center {
display: flex;
flex-direction: row;
align-items: center;
}
.flex-row-start {
display: flex;
flex-direction: row;
align-items: flex-start;
}
.flex-row-end-between {
display: flex;
flex-direction: row;
align-items: flex-end;
justify-content: space-between;
} }
</style> </style>

View File

@ -0,0 +1,106 @@
<template>
<view class="video-page">
<!-- 原生视频组件全端兼容 -->
<video id="fullVideo" class="video-box" :src="videoUrl" controls show-fullscreen-btn enable-progress-gesture
:autoplay="true" :loop="false" :muted="false" @play="onPlay" @pause="onPause" object-fit="cover" :direction="90"
@fullscreenchange="handleFullScreenChange" @ended="onVideoEnd" @fullscreenclick="tapback"></video>
</view>
</template>
<script>
export default {
data() {
return {
videoUrl: "",
videoContext: null
};
},
onLoad(options) {
console.log(options, '页面参数');
//
if (options.url) {
this.videoUrl = options.url;
}
},
onReady() {
// #ifdef APP-PLUS
//plus.screen.unlockOrientation(); //
// #endif
//
this.videoContext = uni.createVideoContext("fullVideo", this);
//
//this.autoFullScreen();
},
methods: {
tapback(e) {
console.log('点击全屏按钮');
// if (e.target.fullScreen) {
// plus.screen.lockOrientation('landscape'); //
// }else{
// plus.screen.lockOrientation('portrait'); //
// }
},
// iOS
autoFullScreen() {
if (!this.videoContext) return;
// iOS090
const direction = uni.getSystemInfoSync().platform === 'ios' ? 0 : 90;
//
setTimeout(() => {
this.videoContext.requestFullScreen({
direction: direction
});
}, 300)
},
//
openFullScreen() {
if (!this.videoContext) return;
const direction = uni.getSystemInfoSync().platform === 'ios' ? 0 : 90;
this.videoContext.requestFullScreen({
direction
});
},
// 退
closeFullScreen() {
if (!this.videoContext) return;
this.videoContext.exitFullScreen();
},
//
onPlay() {
console.log("视频开始播放");
},
//
onPause() {
console.log("视频暂停");
},
//
handleFullScreenChange(e) {
// 退
// uni.setNavigationBarHidden(!!e.detail.fullScreen);
console.log("全屏状态:", e.detail.fullScreen);
},
//
onVideoEnd() {
this.closeFullScreen();
}
}
};
</script>
<style scoped>
.video-page {
width: 100%;
height: 100vh;
box-sizing: border-box;
}
.video-box {
width: 100%;
/* 自适应高度,避免拉伸 */
height: 100%;
object-fit: cover;
}
</style>

View File

@ -1,52 +1,59 @@
<template> <template>
<view class="container"> <view class="container">
<view class="positonFixed"> <view class="positonFixed">
<view class="header-top flex-row-center" :class="{videoTop:current==0}" <view class="header-top flex-row-center" :style="{ height: `${100 + statusBarHeight}rpx`,paddingTop:`${statusBarHeight}rpx`}">
:style="{ height: `${88+statusBarHeight}rpx`,paddingTop: `${statusBarHeight}rpx`}">
<view class="left-area" @click="goBack"> <view class="left-area" @click="goBack">
<image src="/static/images/whiteBack.png" mode="aspectFit" class="back-icon"></image> <image src="/static/images/back.png" mode="aspectFit" class="back-icon"></image>
</view> </view>
<view class="flex-row-center-center" style="flex: 1;margin-right: 18rpx;height:66rpx;"> <view class="flex-row-center-center" style="flex: 1;margin-right: 18rpx;height:66rpx;">
<uv-tabs :list="list" @click="tabsClick" itemStyle="height:66rpx;" :activeStyle="activeStyle" <uv-tabs :list="list" @click="tabsClick" itemStyle="height:66rpx;" :activeStyle="activeStyle"
:inactiveStyle="inactiveStyle" :current="current" :lineColor="`rgba(232, 16, 30, 1)`"></uv-tabs> :inactiveStyle="inactiveStyle" :current="current" :lineColor="`rgba(232, 16, 30, 1)`"></uv-tabs>
</view> </view>
</view> </view>
<scroll-view scroll-x style="height: 100rpx;" v-if="current==1"> <scroll-view scroll-x style="height: 100rpx;background-color: #fff;" v-if="current==1">
<view class="container-tabs flex-row-center"> <view class="container-tabs flex-row-center">
<view class="container-tab flex-row-center-center" @click="clickTab(item)" <view class="container-tab flex-row-center-center" @click="clickTab(item)"
:class="{active:cardListIndex==item.id}" v-for="(item,index) in cardList[1]" :key="index"> :class="{active:cardListIndex==item.id}" v-for="(item,index) in cardList[user_type]"
:key="index">
<text class="container-tab-text">{{ item.title }}</text> <text class="container-tab-text">{{ item.title }}</text>
</view> </view>
</view> </view>
</scroll-view> </scroll-view>
</view> </view>
<view :style="swiperStyle3"></view>
<view class="container-content" :style="swiperStyle2"> <view class="container-content" :style="swiperStyle2">
<swiper class="swiper" circular :style="swiperStyle" :current="current" @change="swiperChange" :disable-touch="current==0"> <swiper class="swiper" circular :style="swiperStyle" :current="current" @change="swiperChange"
:disable-touch="current==0">
<swiper-item> <swiper-item>
<videoSlide ref="ideoSlideRrf" :popVideoList="videoList" :marginTop="`${88 + this.statusBarHeight}`" v-show="current==0" v-if="videoList.length"></videoSlide> <scroll-view scroll-y :style="{height:`${viewportHeight - 100 - statusBarHeight}rpx`}">
<view class="swiper-items3">
<view class="swiper-item3" :class="{item2Left:index%2 == 0}"
v-for="(item,index) in videoList" :key="index" @click="tovideo(item)">
<image class="swiper-item3-video" mode="aspectFill" :src="item.img"></image>
<image
src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/c6c039fc-99fd-492e-ae9a-ed43260c94ef.png"
mode="widthFix"
style="width: 80rpx;position: absolute;top: 50%;left: 50%;transform: translate3d(-50%, -50%, 0);">
</image>
</view>
</view>
</scroll-view>
</swiper-item> </swiper-item>
<swiper-item> <swiper-item>
<scroll-view scroll-y :style="{height:`${viewportHeight-88-this.statusBarHeight-100}rpx`}"> <scroll-view scroll-y :style="{height:`${viewportHeight - 100 - statusBarHeight - 100}rpx`}">
<view class="swiper-items2"> <view class="swiper-items2">
<view class="swiper-item2" :class="{item2Left:index%2 == 0}" <view class="swiper-item2" :class="{item2Left:index%2 == 0}"
v-for="(item,index) in imagObj[cardListIndex]" :key="index"> v-for="(item,index) in imagObj[cardListIndex]" :key="index" @click="toimg(item)">
<image class="swiper-item2-img" mode="aspectFill" :src="item.url"></image> <image class="swiper-item2-img" mode="aspectFill" :src="item.url"></image>
<view class="swiper-item2-title"> <view class="swiper-item2-title">
<text class="swiper-item2-title-text">{{ item.name }}</text> <text class="swiper-item2-title-text">{{ item.name }}</text>
</view> </view>
</view> </view>
</view> </view>
</scroll-view> </scroll-view>
</swiper-item> </swiper-item>
</swiper> </swiper>
</view> </view>
</view> </view>
</template> </template>
@ -68,6 +75,23 @@
title: "主图", title: "主图",
id: 1 id: 1
}, },
{
title: "作品",
id: 3
},
{
title: "其他",
id: 4
}
],
2: [{
title: "全部",
id: 0
},
{
title: "主图",
id: 1
},
{ {
title: "环境", title: "环境",
id: 2 id: 2
@ -94,7 +118,7 @@
inactiveStyle: { inactiveStyle: {
fontWeight: 500, fontWeight: 500,
fontSize: "32rpx", fontSize: "32rpx",
color: "#666666", color: "#333333",
}, },
current: 1, current: 1,
statusBarHeight: 0, statusBarHeight: 0,
@ -108,6 +132,7 @@
}; };
}, },
async onLoad(options) { async onLoad(options) {
// 获取状态栏高度 // 获取状态栏高度
const systemInfo = await uni.getSystemInfoSync() const systemInfo = await uni.getSystemInfoSync()
this.systemInfo = systemInfo this.systemInfo = systemInfo
@ -120,6 +145,12 @@
this.getVideoList() this.getVideoList()
} }
}, },
onShow() {
// // #ifdef APP-PLUS
// plus.screen.unlockOrientation(); //解除屏幕方向的锁定,但是不一定是竖屏;
// plus.screen.lockOrientation('portrait'); //锁死屏幕方向为竖屏
// // #endif
},
computed: { computed: {
// 计算swiper的样式 // 计算swiper的样式
swiperStyle() { swiperStyle() {
@ -129,24 +160,35 @@
let viewportHeight = this.pxToRpx(this.systemInfo.windowHeight || window?.innerHeight || document let viewportHeight = this.pxToRpx(this.systemInfo.windowHeight || window?.innerHeight || document
?.documentElement?.clientHeight || 0, screenWidth); ?.documentElement?.clientHeight || 0, screenWidth);
let height = viewportHeight - 88 - this.statusBarHeight; let height = viewportHeight - 100 - this.statusBarHeight;
return { return {
height: `${height}rpx` height: `${height}rpx`
}; };
} }
return { return {
height: `${this.viewportHeight}rpx` height: `${this.viewportHeight - 100 - this.statusBarHeight}rpx`
}; };
}, },
swiperStyle2() { swiperStyle2() {
if (this.current == 1) { if (this.current == 1) {
return { return {
marginTop: `${88 + this.statusBarHeight + 100}rpx`, height: `${this.viewportHeight-100-this.statusBarHeight-100}rpx`
height: `${this.viewportHeight-88-this.statusBarHeight-100}rpx`
}; };
} }
return { return {
height: `${this.viewportHeight}rpx` height: `${this.viewportHeight - 100 - this.statusBarHeight}rpx`
};
},
swiperStyle3() {
if (this.current == 1) {
return {
width: `750rpx`,
height: `${200 + this.statusBarHeight}rpx`,
};
}
return {
width: `750rpx`,
height: `${100 + this.statusBarHeight}rpx`,
}; };
}, },
viewportHeight() { viewportHeight() {
@ -158,25 +200,30 @@
}, },
}, },
methods: { methods: {
goBack() {
uni.navigateBack(-1)
},
toimg(item) {
console.log(item, 'item');
uni.previewImage({
urls: [item.url], // 外面加 [] 变成数组
current: 0 // 可选,默认第一张
})
},
tovideo(item) {
uni.navigateTo({
url: '/pages/album/components/videoplayer?url=' + item.url
})
},
clickTab(item) { clickTab(item) {
this.cardListIndex = item.id this.cardListIndex = item.id
}, },
tabsClick(e) { tabsClick(e) {
this.$nextTick(() => { console.log('12312312312');
this.current = e.index this.current = e.index
if(this.current==1){
this.activeStyle.color = "#333333" this.activeStyle.color = "#333333"
this.inactiveStyle.color = "#666666" this.inactiveStyle.color = "#666666"
this.$refs.ideoSlideRrf.nowStopVideo()
}
if(this.current==0){
this.activeStyle.color = "#fff"
this.inactiveStyle.color = "#ccc"
this.$refs.ideoSlideRrf.nowPlayVideo()
}
})
}, },
swiperChange(e) { swiperChange(e) {
this.$nextTick(() => { this.$nextTick(() => {
@ -184,12 +231,10 @@
if (this.current == 1) { if (this.current == 1) {
this.activeStyle.color = "#333333" this.activeStyle.color = "#333333"
this.inactiveStyle.color = "#666666" this.inactiveStyle.color = "#666666"
this.$refs.ideoSlideRrf.nowStopVideo()
} }
if (this.current == 0) { if (this.current == 0) {
this.activeStyle.color = "#fff" this.activeStyle.color = "#333333"
this.inactiveStyle.color = "#ccc" this.inactiveStyle.color = "#666666"
this.$refs.ideoSlideRrf.nowPlayVideo()
} }
}) })
@ -208,12 +253,17 @@
type: 1 type: 1
}).then(res => { }).then(res => {
if (res.code == 200) { if (res.code == 200) {
if (res.data.list.length != 0) {
this.imagObj = res.data.list[1] this.imagObj = res.data.list[1]
let all = [] let all = []
for (let key in res.data.list[1]) { for (let key in res.data.list[1]) {
all = [...all, ...res.data.list[1][key]] all = [...all, ...res.data.list[1][key]]
} }
this.imagObj[0] = all this.imagObj[0] = all
} else {
this.imagObj[0] = []
}
} }
}) })
}, },
@ -224,8 +274,17 @@
type: 2 type: 2
}).then(res => { }).then(res => {
if (res.code == 200) { if (res.code == 200) {
if (res.data.list.length != 0) {
console.log(res.data, 'res.data');
for (let key in res.data.list[2]) { for (let key in res.data.list[2]) {
this.videoList = [...this.videoList, ...res.data.list[2][key]] this.videoList = [...this.videoList, ...res.data.list[2][key]]
this.videoList.forEach((item) => {
item.img = item.url +
'?x-oss-process=video/snapshot,t_1000,m_fast,f_jpg,w_600,ar_auto'
})
}
} else {
this.videoList = []
} }
} }
}) })
@ -266,8 +325,10 @@
} }
} }
} }
.videoTop { .videoTop {
background: transparent; background: transparent;
::v-deep .uv-tabs__wrapper__nav__line { ::v-deep .uv-tabs__wrapper__nav__line {
background: #fff !important; background: #fff !important;
} }
@ -296,7 +357,7 @@
.container-tab-text { .container-tab-text {
font-weight: 400; font-weight: 400;
font-size: 28rpx; font-size: 28rpx;
color: #E8101E; color: #FF4767;
line-height: 40rpx; line-height: 40rpx;
text-align: left; text-align: left;
font-style: normal; font-style: normal;
@ -306,6 +367,7 @@
.container-content { .container-content {
z-index: 1000; z-index: 1000;
.swiper { .swiper {
background: #fff; background: #fff;
@ -349,6 +411,47 @@
} }
} }
.swiper-items3 {
flex-wrap: wrap;
flex-direction: row;
display: flex;
padding-bottom: 20rpx;
.swiper-item3 {
width: 370rpx;
height: 370rpx;
margin-top: 10rpx;
overflow: hidden;
position: relative;
box-sizing: border-box;
border-radius: 20rpx;
.swiper-item3-video {
width: 370rpx;
height: 370rpx;
}
.swiper-item3-title {
position: absolute;
left: 0;
top: 0;
height: 33rpx;
padding: 0 8rpx;
background: rgba(0, 0, 0, 0.5);
border-radius: 0rpx 0rpx 10rpx 0rpx;
width: fit-content;
.swiper-item3-title-text {
font-weight: 400;
font-size: 18rpx;
color: #FFFFFF;
line-height: 33rpx;
}
}
}
}
.item2Left { .item2Left {
margin-right: 9rpx; margin-right: 9rpx;
} }
@ -398,6 +501,4 @@
align-items: flex-end; align-items: flex-end;
justify-content: space-between; justify-content: space-between;
} }
</style> </style>

View File

@ -86,7 +86,7 @@
? "门店下单购买后,您需到上门至门店进行服务,门店端展示价格为" ? "门店下单购买后,您需到上门至门店进行服务,门店端展示价格为"
: "" : ""
}} }}
<text style="color: #e8101e" v-if="showShopPrice">{{ <text style="color: #FF4767" v-if="showShopPrice">{{
shopPrice shopPrice
}}</text> }}</text>
{{ showShopPrice ? "元。" : "" }} {{ showShopPrice ? "元。" : "" }}
@ -364,19 +364,6 @@
> >
</view> </view>
<!-- 新增上门提醒弹窗-->
<transition name="fade">
<view class="popup-mask2" v-if="showReminderPopup" @click="closeReminderPopup(false)">
<view class="popup-content2" @click.stop>
<view class="popup-title">提示</view>
<view class="popup-message">此服务是需要上门服务的哦</view>
<view class="popup-buttons">
<view class="popup-btn popup-btn-notshow" @click="closeReminderPopup(true)">不再提示</view>
<view class="popup-btn popup-btn-know" @click="closeReminderPopup(false)">我已知晓</view>
</view>
</view>
</view>
</transition>
</view> </view>
</template> </template>
@ -402,7 +389,6 @@ export default {
}, },
data() { data() {
return { return {
showReminderPopup: false,
artisanType: getApp().globalData.artisanType, artisanType: getApp().globalData.artisanType,
nowQer: "xc", nowQer: "xc",
progress: 0, progress: 0,
@ -474,11 +460,6 @@ export default {
this.serviceTypes = this.serviceTypes.concat(res.data); this.serviceTypes = this.serviceTypes.concat(res.data);
}); });
} }
//
const notShow = uni.getStorageSync('addServiceReminderNotShow');
if (!notShow) {
this.showReminderPopup = true;
}
this.getUserInfo(); this.getUserInfo();
}, },
computed: { computed: {
@ -575,14 +556,6 @@ export default {
return true; return true;
}, },
closeReminderPopup(notShowAgain) {
console.log('关闭弹窗,不再提示:', notShowAgain);
if (notShowAgain) {
uni.setStorageSync('addServiceReminderNotShow', true);
}
this.showReminderPopup = false;
},
goImgAndText() { goImgAndText() {
uni.navigateTo({ uni.navigateTo({
url: `/pages/shop/add-img-text?list=${this.formData.graphic_details}`, url: `/pages/shop/add-img-text?list=${this.formData.graphic_details}`,
@ -1234,13 +1207,13 @@ export default {
.btn-draft { .btn-draft {
background-color: #ffffff; background-color: #ffffff;
color: #e8101e; color: #FF4767;
border: 2rpx solid #e8101e; border: 2rpx solid #FF4767;
box-sizing: border-box; box-sizing: border-box;
} }
.btn-submit { .btn-submit {
background-color: #e8101e; background-color: #FF4767;
color: #ffffff; color: #ffffff;
} }
@ -1512,13 +1485,13 @@ export default {
} }
.popup-btn-know { .popup-btn-know {
background-color: #e8101e; background-color: #FF4767;
color: #ffffff; color: #ffffff;
} }
.popup-btn-notshow { .popup-btn-notshow {
background-color: #ffffff; background-color: #ffffff;
color: #e8101e; color: #FF4767;
border: 1rpx #e8101e solid; border: 1rpx #FF4767 solid;
} }
</style> </style>

View File

@ -1204,7 +1204,7 @@ export default {
} }
.change-info-btn, .view-change-btn, .resubmit-btn { .change-info-btn, .view-change-btn, .resubmit-btn {
background: linear-gradient(180deg, #f52540 0%, #e8101e 100%); background: linear-gradient(180deg, #ff8e9d 0%, #FF4767 100%);
} }
/* 双按钮行样式 */ /* 双按钮行样式 */
@ -1225,7 +1225,7 @@ export default {
} }
.submit-btn { .submit-btn {
background: linear-gradient(180deg, #F52540 0%, #E8101E 100%, #E8101E 100%); background: linear-gradient(180deg, #ff8e9d 0%, #FF4767 100%);
border-radius: 43rpx; border-radius: 43rpx;
padding: 0 15rpx; padding: 0 15rpx;
} }
@ -1257,7 +1257,7 @@ export default {
.title-bar { .title-bar {
width: 6rpx; width: 6rpx;
height: 30rpx; height: 30rpx;
background-color: #E8101E; background-color: #FF4767;
margin-right: 7rpx; margin-right: 7rpx;
border-radius: 5rpx; border-radius: 5rpx;
} }
@ -1405,7 +1405,7 @@ export default {
width: 60rpx; width: 60rpx;
height: 60rpx; height: 60rpx;
border: 4rpx solid #fff; border: 4rpx solid #fff;
border-top: 4rpx solid #E8101E; border-top: 4rpx solid #FF4767;
border-radius: 50%; border-radius: 50%;
animation: spin 1s linear infinite; animation: spin 1s linear infinite;
margin-bottom: 16rpx; margin-bottom: 16rpx;
@ -1470,8 +1470,8 @@ export default {
} }
.radio.checked { .radio.checked {
background-color: #E8101E; background-color: #FF4767;
border-color: #E8101E; border-color: #FF4767;
} }
.radio-icon-image { .radio-icon-image {
@ -1640,7 +1640,7 @@ export default {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
background: linear-gradient(180deg, #f52540 0%, #e8101e 100%); background: linear-gradient(180deg, #ff8e9d 0%, #FF4767 100%);
} }
.popup-btn .btn-text { .popup-btn .btn-text {
@ -1659,7 +1659,7 @@ export default {
} }
.confirm-text { .confirm-text {
color: #E8101E; color: #FF4767;
font-weight: 500; font-weight: 500;
} }
@ -1771,13 +1771,13 @@ export default {
} }
.tip-btn.cancel { .tip-btn.cancel {
border: #E8101E 2rpx solid; border: #FF4767 2rpx solid;
background-color: transparent; background-color: transparent;
color: #e8101e; color: #FF4767;
} }
.tip-btn.confirm { .tip-btn.confirm {
background: linear-gradient(180deg, #f52540 0%, #e8101e 100%); background: linear-gradient(180deg, #ff8e9d 0%, #FF4767 100%);
color: #FFFFFF; color: #FFFFFF;
} }

View File

@ -165,7 +165,7 @@ export default {
timeRange: '7days', timeRange: '7days',
count: 0, count: 0,
chartOpts: { chartOpts: {
color: ["#E8101E"], color: ["#FF4767"],
padding: [15, 15, 0, 15], padding: [15, 15, 0, 15],
enableScroll: false, enableScroll: false,
legend: false, legend: false,
@ -657,7 +657,7 @@ page {
} }
.time-filter .active { .time-filter .active {
color: #E8101E; color: #FF4767;
} }
.chart-container { .chart-container {
@ -676,7 +676,7 @@ page {
width: 214rpx; width: 214rpx;
height: 56rpx; height: 56rpx;
background-color: #FFFFFF; background-color: #FFFFFF;
border: 1rpx solid #E8101E; border: 1rpx solid #FF4767;
border-radius: 8rpx; border-radius: 8rpx;
display: flex; display: flex;
justify-content: center; justify-content: center;
@ -687,7 +687,7 @@ page {
.type-name { .type-name {
font-size: 24rpx; font-size: 24rpx;
color: #E8101E; color: #FF4767;
} }
.type-count { .type-count {
@ -708,7 +708,7 @@ page {
background-color: #F53F3F; background-color: #F53F3F;
} }
.order-type-item.active { .order-type-item.active {
background-color: #E8101E; background-color: #FF4767;
} }
.order-type-item.active .type-name { .order-type-item.active .type-name {
color: #FFFFFF; color: #FFFFFF;
@ -800,7 +800,7 @@ page {
} }
.action-btn.verify .action-text { .action-btn.verify .action-text {
font-size: 28rpx; font-size: 28rpx;
color: #E8101E; color: #FF4767;
} }
.nothings-box { .nothings-box {

View File

@ -249,7 +249,7 @@ page {
flex-flow: row nowrap; flex-flow: row nowrap;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
border: 1rpx solid #E8101E; border: 1rpx solid #FF4767;
background-color: #FFF1F1; background-color: #FFF1F1;
border-radius: 22rpx; border-radius: 22rpx;
box-sizing: border-box; box-sizing: border-box;
@ -267,7 +267,7 @@ page {
} }
.verified-text { .verified-text {
font-size: 24rpx; font-size: 24rpx;
color: #E8101E; color: #FF4767;
} }
.verified-text.no { .verified-text.no {
color: #666666; color: #666666;

View File

@ -4,7 +4,9 @@
<view class="custom-navbar"> <view class="custom-navbar">
<!-- 左侧返回按钮和标题 --> <!-- 左侧返回按钮和标题 -->
<view class="navbar-left"> <view class="navbar-left">
<image class="back-icon" src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/456f4e6c-e86a-42c9-a272-484db9af6c7c" mode="aspectFit" @click="handleBack"></image> <image class="back-icon"
src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/456f4e6c-e86a-42c9-a272-484db9af6c7c"
mode="aspectFit" @click="handleBack"></image>
<text class="navbar-title">我的资料</text> <text class="navbar-title">我的资料</text>
</view> </view>
@ -36,24 +38,55 @@
<!-- 营业时间商家 / 服务时间手艺人 --> <!-- 营业时间商家 / 服务时间手艺人 -->
<view class="info-item" @click="navigateToTimeSetting"> <view class="info-item" @click="navigateToTimeSetting">
<view class="info-left"> <view class="info-left">
<image class="item-icon" src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/21f1efaf-0c17-49b0-a2b2-e0fd573b92b3" mode="aspectFit"></image> <image class="item-icon"
src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/21f1efaf-0c17-49b0-a2b2-e0fd573b92b3"
mode="aspectFit"></image>
<text class="item-label">{{ identity == '2' ? '营业时间' : '服务时间' }}</text> <text class="item-label">{{ identity == '2' ? '营业时间' : '服务时间' }}</text>
</view> </view>
<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.business_time">
</image>
<text style="margin-right: 16rpx;"
:style="{ color: userInfo.business_time ? '#c9c9c9' : '#ec5d57' }">
{{ userInfo.business_time ? '已设置' : '待完善' }}
</text>
<image class="arrow-right" src="/static/images/arrow_right.png" mode="aspectFit">
</image>
</view>
</view> </view>
<!-- 服务技能 -->
<view class="info-item" @click="navigateToServiceSkill"> <view class="info-item" @click="navigateToServiceSkill">
<view class="info-left"> <view class="info-left">
<image class="item-icon" src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/b90e2322-a261-4c17-a581-85010c3bc112" mode="aspectFit"></image> <image class="item-icon"
src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/b90e2322-a261-4c17-a581-85010c3bc112"
mode="aspectFit"></image>
<text class="item-label">服务技能</text> <text class="item-label">服务技能</text>
</view> </view>
<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="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>
</view> </view>
<!-- 门店信息 --> <!-- 门店信息 -->
<view class="info-item" v-if="identity == '2'" @click="navigateToShopInfo"> <view class="info-item" v-if="identity == '2'" @click="navigateToShopInfo">
<view class="info-left"> <view class="info-left">
<image class="item-icon" src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/e9618006-db69-446e-92e1-ba9dd81e79f9" mode="aspectFit"></image> <image class="item-icon"
src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/e9618006-db69-446e-92e1-ba9dd81e79f9"
mode="aspectFit"></image>
<text class="item-label">门店信息</text> <text class="item-label">门店信息</text>
</view> </view>
<image class="arrow-right" src="/static/images/arrow_right.png" mode="aspectFit"></image> <image class="arrow-right" src="/static/images/arrow_right.png" mode="aspectFit"></image>
@ -62,7 +95,9 @@
<!-- 服务区域手艺人显示 --> <!-- 服务区域手艺人显示 -->
<view class="info-item" v-if="identity == '1'" @click="navigateToServiceArea"> <view class="info-item" v-if="identity == '1'" @click="navigateToServiceArea">
<view class="info-left"> <view class="info-left">
<image class="item-icon" src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/a35603b1-50fb-4248-9f2e-2dd4d5e249c0" mode="aspectFit"></image> <image class="item-icon"
src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/a35603b1-50fb-4248-9f2e-2dd4d5e249c0"
mode="aspectFit"></image>
<text class="item-label">服务区域</text> <text class="item-label">服务区域</text>
</view> </view>
<image class="arrow-right" src="/static/images/arrow_right.png" mode="aspectFit"></image> <image class="arrow-right" src="/static/images/arrow_right.png" mode="aspectFit"></image>
@ -71,7 +106,9 @@
<!-- 个人信息手艺人显示 --> <!-- 个人信息手艺人显示 -->
<view class="info-item" v-if="identity == '1'" @click="navigateToPersonalInfo"> <view class="info-item" v-if="identity == '1'" @click="navigateToPersonalInfo">
<view class="info-left"> <view class="info-left">
<image class="item-icon" src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/77dc7a16-3b86-44e5-8acc-5f3b85ffc137" mode="aspectFit"></image> <image class="item-icon"
src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/77dc7a16-3b86-44e5-8acc-5f3b85ffc137"
mode="aspectFit"></image>
<text class="item-label">个人信息</text> <text class="item-label">个人信息</text>
</view> </view>
<image class="arrow-right" src="/static/images/arrow_right.png" mode="aspectFit"></image> <image class="arrow-right" src="/static/images/arrow_right.png" mode="aspectFit"></image>
@ -80,7 +117,9 @@
<!-- 个人信息手艺人显示 --> <!-- 个人信息手艺人显示 -->
<view class="info-item" @click="navigateToimg"> <view class="info-item" @click="navigateToimg">
<view class="info-left"> <view class="info-left">
<image class="item-icon" src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/53a9d1e1-e2d2-4001-b599-82e0c0747f1a.png" mode="aspectFit"></image> <image class="item-icon"
src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/53a9d1e1-e2d2-4001-b599-82e0c0747f1a.png"
mode="aspectFit"></image>
<text class="item-label">相册管理</text> <text class="item-label">相册管理</text>
</view> </view>
<image class="arrow-right" src="/static/images/arrow_right.png" mode="aspectFit"></image> <image class="arrow-right" src="/static/images/arrow_right.png" mode="aspectFit"></image>
@ -89,7 +128,9 @@
<!-- 个人信息手艺人显示 --> <!-- 个人信息手艺人显示 -->
<view class="info-item" @click="navigateTovideo"> <view class="info-item" @click="navigateTovideo">
<view class="info-left"> <view class="info-left">
<image class="item-icon" src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/6fc821cd-8dd1-41f1-8854-889fb5f76b78.png" mode="aspectFit"></image> <image class="item-icon"
src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/6fc821cd-8dd1-41f1-8854-889fb5f76b78.png"
mode="aspectFit"></image>
<text class="item-label">视频管理</text> <text class="item-label">视频管理</text>
</view> </view>
<image class="arrow-right" src="/static/images/arrow_right.png" mode="aspectFit"></image> <image class="arrow-right" src="/static/images/arrow_right.png" mode="aspectFit"></image>
@ -110,16 +151,33 @@
<!-- 资质信息 --> <!-- 资质信息 -->
<view class="info-item" @click="navigateToQualification"> <view class="info-item" @click="navigateToQualification">
<view class="info-left"> <view class="info-left">
<image class="item-icon" src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/2677692c-5931-4ac7-846e-b6d321184789" mode="aspectFit"></image> <image class="item-icon"
src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/2677692c-5931-4ac7-846e-b6d321184789"
mode="aspectFit"></image>
<text class="item-label">资质信息</text> <text class="item-label">资质信息</text>
</view> </view>
<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="shouldShowQualificationWarningIcon()">
</image>
<text style="margin-right: 16rpx;"
:style="{ color: qualificationStatusColor() }">
{{ qualificationStatusText() }}
</text>
<image class="arrow-right" src="/static/images/arrow_right.png" mode="aspectFit">
</image>
</view>
</view> </view>
<!-- 所属门店手艺人显示 --> <!-- 所属门店手艺人显示 -->
<view class="info-item" v-if="identity == '1'" @click="navigateToBelongShop"> <view class="info-item" v-if="identity == '1'" @click="navigateToBelongShop">
<view class="info-left"> <view class="info-left">
<image class="item-icon" src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/b5541cb5-58c1-4e72-b88f-5cf6450338a8" mode="aspectFit"></image> <image class="item-icon"
src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/b5541cb5-58c1-4e72-b88f-5cf6450338a8"
mode="aspectFit"></image>
<text class="item-label">所属门店</text> <text class="item-label">所属门店</text>
</view> </view>
<image class="arrow-right" src="/static/images/arrow_right.png" mode="aspectFit"></image> <image class="arrow-right" src="/static/images/arrow_right.png" mode="aspectFit"></image>
@ -131,7 +189,9 @@
</template> </template>
<script> <script>
import { handleImgSizeUni } from '@/utils/service.js' import {
handleImgSizeUni
} from '@/utils/service.js'
import request from "../../utils/request"; import request from "../../utils/request";
export default { export default {
@ -140,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 //
} }
}, },
@ -252,9 +317,9 @@ export default {
// //
handleMpAutoShare() { handleMpAutoShare() {
// //
const url = this.identity == '2' const url = this.identity == '2' ?
? `/pages/user/store-detail?id=${this.currentUserId}` `/pages/user/store-detail?id=${this.currentUserId}` :
: `/pages/user/syr-detail?id=${this.currentUserId}`; `/pages/user/syr-detail?id=${this.currentUserId}`;
uni.navigateTo({ uni.navigateTo({
url: url, url: url,
@ -286,9 +351,9 @@ export default {
}); });
// //
const url = this.identity == '2' const url = this.identity == '2' ?
? `/pages/user/store-detail?id=${this.currentUserId}&autoShare=1` `/pages/user/store-detail?id=${this.currentUserId}&autoShare=1` :
: `/pages/user/syr-detail?id=${this.currentUserId}&autoShare=1`; `/pages/user/syr-detail?id=${this.currentUserId}&autoShare=1`;
uni.navigateTo({ uni.navigateTo({
url: url, url: url,
@ -312,12 +377,13 @@ export default {
// APP // APP
executeAppShare(imageUrl) { executeAppShare(imageUrl) {
// //
const backupImageUrl = "https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/yh/1756713709528-717.png?x-oss-process=image/resize,p_40" const backupImageUrl =
"https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/yh/1756713709528-717.png?x-oss-process=image/resize,p_40"
// //
const shareTitle = this.identity == '2' const shareTitle = this.identity == '2' ?
? "好友刚推了个超赞商家点开认识TA ~" "好友刚推了个超赞商家点开认识TA ~" :
: "好友刚推了个超赞手艺人点开认识TA ~" "好友刚推了个超赞手艺人点开认识TA ~"
// //
const shareConfig = { const shareConfig = {
@ -425,11 +491,20 @@ export default {
console.log('调用接口获取用户信息type:', type) console.log('调用接口获取用户信息type:', type)
// //
const result = await request.post('/user/getuser', { type }) const result = await request.post('/sj/user/getUser', {
type
})
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)
@ -442,6 +517,7 @@ export default {
// ID // ID
this.tryAlternativeUserInfo() this.tryAlternativeUserInfo()
uni.hideLoading();
} }
}, },
@ -481,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()
@ -564,24 +732,77 @@ export default {
}) })
}, },
navigateToQualification() { // async navigateToQualification() {
if (this.identity == '2') { if (this.identity != '2' || this.isCertified()) {
//
uni.navigateTo({ uni.navigateTo({
url: '/pages/shop/qualification_sj_change' url: '/pages/shop/qualification_sj_change'
}) });
} else { return;
// }
await this.ensureAuthDetails();
if (!this.isSettled()) {
uni.navigateTo({ uni.navigateTo({
url: '/pages/artisan/qualification_syr_change' 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() { // 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 === '待完善';
} }
} }
} }
@ -599,7 +820,8 @@ export default {
top: 0; top: 0;
left: 0; left: 0;
right: 0; right: 0;
height: 108rpx; /* 使用标准导航栏高度 */ height: 108rpx;
/* 使用标准导航栏高度 */
background: white; background: white;
display: flex; display: flex;
align-items: center; align-items: center;
@ -697,7 +919,7 @@ export default {
.title-bar { .title-bar {
width: 6rpx; width: 6rpx;
height: 30rpx; height: 30rpx;
background-color: #E8101E; background-color: #FF4767;
margin-right: 10rpx; margin-right: 10rpx;
border-radius: 5rpx; border-radius: 5rpx;
} }

View File

@ -1544,7 +1544,7 @@ export default {
.tag { .tag {
font-size: 24rpx; font-size: 24rpx;
color: #E8101E; color: #FF4767;
margin-left: 14rpx; margin-left: 14rpx;
} }
.textarea { .textarea {
@ -1655,7 +1655,7 @@ export default {
.save-btn { .save-btn {
width: 702rpx; width: 702rpx;
height: 64rpx; height: 64rpx;
background: #E8101E; background: #FF4767;
border-radius: 32rpx; border-radius: 32rpx;
display: flex; display: flex;
align-items: center; align-items: center;
@ -1762,8 +1762,8 @@ export default {
} }
.checkbox.checked { .checkbox.checked {
background-color: #E8101E; background-color: #FF4767;
border-color: #E8101E; border-color: #FF4767;
} }
.check-icon { .check-icon {
@ -1796,7 +1796,7 @@ export default {
} }
.popup-btn.confirm { .popup-btn.confirm {
background: linear-gradient(90deg, #E8101E 0%, #FF618F 100%); background: linear-gradient(90deg, #FF4767 0%, #FF618F 100%);
} }
.popup-btn .btn-text { .popup-btn .btn-text {
@ -1834,7 +1834,7 @@ export default {
} }
.region-tab.active { .region-tab.active {
color: #E8101E; color: #FF4767;
font-weight: 500; font-weight: 500;
} }
@ -1846,7 +1846,7 @@ export default {
transform: translateX(-50%); transform: translateX(-50%);
width: 40rpx; width: 40rpx;
height: 4rpx; height: 4rpx;
background-color: #E8101E; background-color: #FF4767;
border-radius: 2rpx; border-radius: 2rpx;
} }
@ -1907,7 +1907,7 @@ export default {
.confirm-text { .confirm-text {
font-size: 32rpx; font-size: 32rpx;
color: #E8101E; color: #FF4767;
font-weight: 500; font-weight: 500;
} }
@ -1949,7 +1949,7 @@ export default {
} }
.time-block.active .time-value { .time-block.active .time-value {
color: #E8101E; color: #FF4767;
} }
.time-separator { .time-separator {

View File

@ -43,7 +43,7 @@
<view class="radio-item" @click="editable && setHealthCardValidType('permanent')"> <view class="radio-item" @click="editable && setHealthCardValidType('permanent')">
<view class="radio" :class="{ checked: displayData.health_card_expiry_type === 1 }"> <view class="radio" :class="{ checked: displayData.health_card_expiry_type === 1 }">
<image v-if="displayData.health_card_expiry_type === 1" <image v-if="displayData.health_card_expiry_type === 1"
src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/cb185ec8-9d30-4e53-b5dc-14b546013a60" src="/static/images/agree_y.png"
class="radio-icon-image" class="radio-icon-image"
mode="aspectFit"></image> mode="aspectFit"></image>
</view> </view>
@ -52,7 +52,7 @@
<view class="radio-item" @click="editable && setHealthCardValidType('date')"> <view class="radio-item" @click="editable && setHealthCardValidType('date')">
<view class="radio" :class="{ checked: displayData.health_card_expiry_type === 2 }"> <view class="radio" :class="{ checked: displayData.health_card_expiry_type === 2 }">
<image v-if="displayData.health_card_expiry_type === 2" <image v-if="displayData.health_card_expiry_type === 2"
src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/cb185ec8-9d30-4e53-b5dc-14b546013a60" src="/static/images/agree_y.png"
class="radio-icon-image" class="radio-icon-image"
mode="aspectFit"></image> mode="aspectFit"></image>
</view> </view>
@ -1292,7 +1292,7 @@ export default {
} }
.change-info-btn, .view-change-btn, .resubmit-btn { .change-info-btn, .view-change-btn, .resubmit-btn {
background: linear-gradient(180deg, #f52540 0%, #e8101e 100%); background: linear-gradient(180deg, #ff8e9d 0%, #FF4767 100%);
} }
/* 双按钮行样式 */ /* 双按钮行样式 */
@ -1313,7 +1313,7 @@ export default {
} }
.submit-btn { .submit-btn {
background: linear-gradient(180deg, #F52540 0%, #E8101E 100%, #E8101E 100%); background: linear-gradient(180deg, #ff8e9d 0%, #FF4767 100%);
border-radius: 43rpx; border-radius: 43rpx;
padding: 0 15rpx; padding: 0 15rpx;
} }
@ -1345,7 +1345,7 @@ export default {
.title-bar { .title-bar {
width: 6rpx; width: 6rpx;
height: 30rpx; height: 30rpx;
background-color: #E8101E; background-color: #FF4767;
margin-right: 7rpx; margin-right: 7rpx;
border-radius: 5rpx; border-radius: 5rpx;
} }
@ -1472,8 +1472,8 @@ export default {
} }
.radio.checked { .radio.checked {
background-color: #E8101E; background-color: #FF4767;
border-color: #E8101E; border-color: #FF4767;
} }
.radio-icon-image { .radio-icon-image {

View File

@ -104,7 +104,7 @@
@click="toggleDistrictSelect(index)" @click="toggleDistrictSelect(index)"
> >
<view class="checkbox" :class="{ checked: district.checked }"> <view class="checkbox" :class="{ checked: district.checked }">
<image v-if="district.checked" class="check-icon" src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/66325904-4603-48fd-b03b-90c684af96e9" mode="aspectFit"></image> <image v-if="district.checked" class="check-icon" src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/6948baf3-aad9-4d87-9483-9db0e462a3f7.png" mode="aspectFit"></image>
</view> </view>
<text class="checkbox-label">{{district.area}}</text> <text class="checkbox-label">{{district.area}}</text>
</view> </view>
@ -752,7 +752,7 @@ export default {
.title-bar { .title-bar {
width: 6rpx; width: 6rpx;
height: 30rpx; height: 30rpx;
background-color: #E8101E; background-color: #FF4767;
margin-right: 10rpx; margin-right: 10rpx;
border-radius: 5rpx; border-radius: 5rpx;
} }
@ -854,7 +854,7 @@ export default {
.limit-text { .limit-text {
font-size: 24rpx; font-size: 24rpx;
color: #E8101E; color: #FF4767;
} }
/* 区域选择器样式 */ /* 区域选择器样式 */
@ -942,7 +942,7 @@ export default {
} }
.region-tab.active { .region-tab.active {
color: #E8101E; color: #FF4767;
font-weight: 500; font-weight: 500;
} }
@ -954,7 +954,7 @@ export default {
transform: translateX(-50%); transform: translateX(-50%);
width: 40rpx; width: 40rpx;
height: 4rpx; height: 4rpx;
background-color: #E8101E; background-color: #FF4767;
border-radius: 2rpx; border-radius: 2rpx;
} }
@ -994,8 +994,8 @@ export default {
} }
.checkbox.checked { .checkbox.checked {
background-color: #E8101E; background-color: #FF4767;
border-color: #E8101E; border-color: #FF4767;
} }
.check-icon { .check-icon {
@ -1035,7 +1035,7 @@ export default {
} }
.popup-btn.confirm { .popup-btn.confirm {
background: linear-gradient(180deg, #f52540 0%, #e8101e 100%); background: linear-gradient(180deg, #ff8e9d 0%, #FF4767 100%);
} }
.popup-btn .btn-text { .popup-btn .btn-text {
@ -1075,11 +1075,11 @@ export default {
} }
.change-info-btn { .change-info-btn {
background: linear-gradient(180deg, #f52540 0%, #e8101e 100%); background: linear-gradient(180deg, #ff8e9d 0%, #FF4767 100%);
} }
.view-change-btn { .view-change-btn {
background: linear-gradient(180deg, #f52540 0%, #e8101e 100%); background: linear-gradient(180deg, #ff8e9d 0%, #FF4767 100%);
} }
/* 双按钮行样式 */ /* 双按钮行样式 */
@ -1100,7 +1100,7 @@ export default {
} }
.submit-btn { .submit-btn {
background: linear-gradient(180deg, #F52540 0%, #E8101E 100%, #E8101E 100%); background: linear-gradient(180deg, #ff8e9d 0%, #FF4767 100%);
border-radius: 43rpx; border-radius: 43rpx;
padding: 0 15rpx; padding: 0 15rpx;
} }

View File

@ -25,7 +25,7 @@
<view class="checkbox" :class="{ checked: isCurrentSkillSelected(skill.id) }"> <view class="checkbox" :class="{ checked: isCurrentSkillSelected(skill.id) }">
<image v-if="isCurrentSkillSelected(skill.id)" <image v-if="isCurrentSkillSelected(skill.id)"
class="check-icon" class="check-icon"
src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/66325904-4603-48fd-b03b-90c684af96e9" src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/6948baf3-aad9-4d87-9483-9db0e462a3f7.png"
mode="aspectFit"> mode="aspectFit">
</image> </image>
</view> </view>
@ -45,7 +45,7 @@
<view class="checkbox" :class="{ checked: skill.checked }"> <view class="checkbox" :class="{ checked: skill.checked }">
<image v-if="skill.checked" <image v-if="skill.checked"
class="check-icon" class="check-icon"
src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/66325904-4603-48fd-b03b-90c684af96e9" src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/6948baf3-aad9-4d87-9483-9db0e462a3f7.png"
mode="aspectFit"> mode="aspectFit">
</image> </image>
</view> </view>
@ -721,7 +721,7 @@ export default {
.title-bar { .title-bar {
width: 6rpx; width: 6rpx;
height: 30rpx; height: 30rpx;
background-color: #E8101E; background-color: #FF4767;
margin-right: 10rpx; margin-right: 10rpx;
border-radius: 5rpx; border-radius: 5rpx;
} }
@ -790,8 +790,8 @@ export default {
} }
.checkbox.checked { .checkbox.checked {
background-color: #E8101E; background-color: #FF4767;
border-color: #E8101E; border-color: #FF4767;
} }
.check-icon { .check-icon {
@ -827,12 +827,12 @@ export default {
.change-info-btn { .change-info-btn {
margin-top: 20rpx; margin-top: 20rpx;
background: linear-gradient(180deg, #f52540 0%, #e8101e 100%); background: linear-gradient(180deg, #ff8e9d 0%, #FF4767 100%);
} }
.view-change-btn { .view-change-btn {
margin-top: 20rpx; margin-top: 20rpx;
background: linear-gradient(180deg, #f52540 0%, #e8101e 100%); background: linear-gradient(180deg, #ff8e9d 0%, #FF4767 100%);
} }
/* 双按钮行样式 */ /* 双按钮行样式 */
@ -853,7 +853,7 @@ export default {
} }
.submit-btn { .submit-btn {
background: linear-gradient(180deg, #F52540 0%, #E8101E 100%, #E8101E 100%); background: linear-gradient(180deg, #ff8e9d 0%, #FF4767 100%);
border-radius: 43rpx; border-radius: 43rpx;
padding: 0 15rpx; padding: 0 15rpx;
} }

View File

@ -371,7 +371,7 @@ export default {
.title-bar { .title-bar {
width: 6rpx; width: 6rpx;
height: 30rpx; height: 30rpx;
background-color: #E8101E; background-color: #FF4767;
margin-right: 10rpx; margin-right: 10rpx;
border-radius: 5rpx; border-radius: 5rpx;
} }
@ -410,7 +410,7 @@ export default {
font-family: PingFangSC, PingFang SC; font-family: PingFangSC, PingFang SC;
font-weight: 400; font-weight: 400;
font-size: 28rpx; font-size: 28rpx;
color: #E8101E; color: #FF4767;
line-height: 40rpx; line-height: 40rpx;
text-align: left; text-align: left;
font-style: normal; font-style: normal;
@ -476,7 +476,7 @@ export default {
.confirm-text { .confirm-text {
font-size: 32rpx; font-size: 32rpx;
color: #E8101E; color: #FF4767;
font-weight: 500; font-weight: 500;
} }
@ -526,7 +526,7 @@ export default {
} }
.time-block.active .time-value-picker { .time-block.active .time-value-picker {
color: #E8101E; color: #FF4767;
} }
.time-separator { .time-separator {
@ -572,7 +572,7 @@ export default {
border: none; border: none;
width: 290rpx; width: 290rpx;
height: 86rpx; height: 86rpx;
background: linear-gradient( 180deg, #F52540 0%, #E8101E 100%, #E8101E 100%); background: linear-gradient( 180deg, #F52540 0%, #FF4767 100%, #FF4767 100%);
border-radius: 43rpx; border-radius: 43rpx;
} }
@ -592,7 +592,7 @@ export default {
} }
.btn-confirm-large { .btn-confirm-large {
background: #E8101E; background: #FF4767;
color: white; color: white;
} }
</style> </style>

View File

@ -100,13 +100,13 @@
<view class="radio-group"> <view class="radio-group">
<view class="radio-item" @click="editable && setIdCardValidType(1)"> <view class="radio-item" @click="editable && setIdCardValidType(1)">
<view class="radio" :class="{ checked: displayData.idcard_expiry_type === 1 }"> <view class="radio" :class="{ checked: displayData.idcard_expiry_type === 1 }">
<image v-if="displayData.idcard_expiry_type === 1" src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/cb185ec8-9d30-4e53-b5dc-14b546013a60" class="radio-icon-image" mode="aspectFit"></image> <image v-if="displayData.idcard_expiry_type === 1" src="/static/images/agree_y.png" class="radio-icon-image" mode="aspectFit"></image>
</view> </view>
<text class="radio-label">长久有效</text> <text class="radio-label">长久有效</text>
</view> </view>
<view class="radio-item" @click="editable && setIdCardValidType(2)"> <view class="radio-item" @click="editable && setIdCardValidType(2)">
<view class="radio" :class="{ checked: displayData.idcard_expiry_type === 2 }"> <view class="radio" :class="{ checked: displayData.idcard_expiry_type === 2 }">
<image v-if="displayData.idcard_expiry_type === 2" src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/cb185ec8-9d30-4e53-b5dc-14b546013a60" class="radio-icon-image" mode="aspectFit"></image> <image v-if="displayData.idcard_expiry_type === 2" src="/static/images/agree_y.png" class="radio-icon-image" mode="aspectFit"></image>
</view> </view>
<text class="radio-label">指定日期有效</text> <text class="radio-label">指定日期有效</text>
</view> </view>
@ -1813,7 +1813,7 @@ export default {
} }
.change-info-btn, .view-change-btn, .resubmit-btn { .change-info-btn, .view-change-btn, .resubmit-btn {
background: linear-gradient(180deg, #f52540 0%, #e8101e 100%); background: linear-gradient(180deg, #ff8e9d 0%, #FF4767 100%);
} }
/* 双按钮行样式 */ /* 双按钮行样式 */
@ -1834,7 +1834,7 @@ export default {
} }
.submit-btn { .submit-btn {
background: linear-gradient(180deg, #F52540 0%, #E8101E 100%, #E8101E 100%); background: linear-gradient(180deg, #ff8e9d 0%, #FF4767 100%);
border-radius: 43rpx; border-radius: 43rpx;
padding: 0 15rpx; padding: 0 15rpx;
} }
@ -1866,7 +1866,7 @@ export default {
.title-bar { .title-bar {
width: 6rpx; width: 6rpx;
height: 30rpx; height: 30rpx;
background-color: #E8101E; background-color: #FF4767;
margin-right: 7rpx; margin-right: 7rpx;
border-radius: 5rpx; border-radius: 5rpx;
} }
@ -2029,7 +2029,7 @@ export default {
width: 60rpx; width: 60rpx;
height: 60rpx; height: 60rpx;
border: 4rpx solid #fff; border: 4rpx solid #fff;
border-top: 4rpx solid #E8101E; border-top: 4rpx solid #FF4767;
border-radius: 50%; border-radius: 50%;
animation: spin 1s linear infinite; animation: spin 1s linear infinite;
margin-bottom: 16rpx; margin-bottom: 16rpx;
@ -2115,8 +2115,8 @@ export default {
} }
.radio.checked { .radio.checked {
background-color: #E8101E; background-color: #FF4767;
border-color: #E8101E; border-color: #FF4767;
} }
.radio-icon-image { .radio-icon-image {
@ -2291,7 +2291,7 @@ export default {
.confirm-text { .confirm-text {
font-size: 32rpx; font-size: 32rpx;
color: #E8101E; color: #FF4767;
font-weight: 500; font-weight: 500;
} }
@ -2321,7 +2321,7 @@ export default {
} }
.popup-btn.confirm { .popup-btn.confirm {
background: linear-gradient(180deg, #f52540 0%, #e8101e 100%); background: linear-gradient(180deg, #ff8e9d 0%, #FF4767 100%);
} }
.popup-btn .btn-text { .popup-btn .btn-text {
@ -2431,13 +2431,13 @@ export default {
} }
.tip-btn.cancel { .tip-btn.cancel {
border: #E8101E 2rpx solid; border: #FF4767 2rpx solid;
background-color: transparent; background-color: transparent;
color: #e8101e; color: #FF4767;
} }
.tip-btn.confirm { .tip-btn.confirm {
background: linear-gradient(180deg, #f52540 0%, #e8101e 100%); background: linear-gradient(180deg, #ff8e9d 0%, #FF4767 100%);
color: #FFFFFF; color: #FFFFFF;
} }

View File

@ -326,7 +326,7 @@ export default {
.add-icon { .add-icon {
font-size: 32rpx; font-size: 32rpx;
color: #E8101E; color: #FF4767;
margin-right: 8rpx; margin-right: 8rpx;
} }
@ -367,7 +367,7 @@ export default {
} }
.confirm-btn { .confirm-btn {
color: #E8101E; color: #FF4767;
} }
.title { .title {

View File

@ -934,7 +934,7 @@
.get-code-btn { .get-code-btn {
font-weight: 400; font-weight: 400;
font-size: 30rpx; font-size: 30rpx;
color: #E8101E; color: #FF4767;
line-height: 42rpx; line-height: 42rpx;
text-align: center; text-align: center;
font-style: normal; font-style: normal;
@ -959,7 +959,7 @@
.input-error { .input-error {
display: block; display: block;
font-size: 24rpx; font-size: 24rpx;
color: #e8101e; color: #FF4767;
margin-left: 30rpx; margin-left: 30rpx;
margin-top: -20rpx; margin-top: -20rpx;
margin-bottom: 20rpx; margin-bottom: 20rpx;

View File

@ -132,7 +132,7 @@ import request from '../../utils/request';
.state { .state {
height: 60rpx; height: 60rpx;
line-height: 60rpx; line-height: 60rpx;
background-color: #E8101E; background-color: #FF4767;
padding: 0 24rpx; padding: 0 24rpx;
} }
.state-text { .state-text {

View File

@ -132,7 +132,7 @@ export default {
color: #91908F; color: #91908F;
} }
.btn-box { .btn-box {
background: linear-gradient( 180deg, #F52540 0%, #E8101E 100%); background: linear-gradient( 180deg, #F52540 0%, #FF4767 100%);
height: 88rpx; height: 88rpx;
border-radius: 43rpx; border-radius: 43rpx;
font-weight: 500; font-weight: 500;

View File

@ -226,7 +226,7 @@
.score { .score {
font-weight: 400; font-weight: 400;
font-size: 26rpx; font-size: 26rpx;
color: #E8101E; color: #FF4767;
line-height: 37rpx; line-height: 37rpx;
} }

View File

@ -251,7 +251,7 @@
.score { .score {
font-weight: 400; font-weight: 400;
font-size: 26rpx; font-size: 26rpx;
color: #E8101E; color: #FF4767;
line-height: 37rpx; line-height: 37rpx;
text-align: left; text-align: left;
font-style: normal; font-style: normal;

View File

@ -279,7 +279,7 @@
.score { .score {
font-weight: 400; font-weight: 400;
font-size: 26rpx; font-size: 26rpx;
color: #E8101E; color: #FF4767;
line-height: 37rpx; line-height: 37rpx;
text-align: left; text-align: left;
font-style: normal; font-style: normal;

View File

@ -177,7 +177,7 @@
} }
.active { .active {
color: #E8101E; color: #FF4767;
} }
} }

View File

@ -0,0 +1,239 @@
<template>
<view class="brand-card-comp" @click="onClick">
<image class="brand-bg" :src="item.bgSrc" mode="aspectFill"></image>
<image class="mask-bg"
src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/9bca353c-fa74-407e-a69e-6f5e9aa43955.png"
mode="widthFix"></image>
<view class="card-content">
<view class="avatar-wrapper" style="border-color: #F7E5D7;">
<image class="avatar-img" :src="item.avatar || 'https://dummyimage.com/100x100/ccc/fff.png&text=logo'">
</image>
</view>
<text class="brand-name">{{ item.name }}</text>
<view class="tags-container">
<view class="tag-item" v-for="(tag, idx) in displayTags" :key="idx" :style="getTagStyle(tag)">
<!-- <image class="tag-icon" v-if="tag.icon" :src="tag.icon"></image> -->
<text class="tag-text">{{ tag.text }} </text>
<text class="tag-text1"></text>
</view>
</view>
</view>
</view>
</template>
<script>
//
const TAG_LIBRARY = {
franchise: { //
text: '品牌加盟',
color: '#8D4C1B ',
borderColor: '#D6CAC0 ',
icon: 'https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/60816ae2-92ee-4473-9eca-562e1200dbca.png'
},
recruit: { //
text: '学员招募',
color: '#E5505F',
borderColor: '#EFCFD2 ',
icon: 'https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/fd0699b9-9f3c-4b1e-8693-d0c9ec7eabc3.png'
},
more: { //
text: '更多详情',
color: '#333333',
borderColor: '#ECECEC',
icon: 'https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/cec453ce-f3fc-4881-8f2c-9ec5c61e759c.png'
}
}
export default {
name: 'brand-card',
props: {
//
item: {
type: Object,
default: () => ({})
},
// key ['franchise', 'recruit']
tagKeys: {
type: Array,
default: null
}
},
computed: {
// 使 tagKeys item.tags
displayTags() {
if (this.tagKeys && this.tagKeys.length) {
return this.tagKeys.map(key => TAG_LIBRARY[key]).filter(v => v)
}
// item.tags 使
if (this.item.tags && Array.isArray(this.item.tags)) {
return this.item.tags
}
return []
},
tagsLength() {
return this.displayTags.length
}
},
methods: {
//
onClick() {
// 1. emit便
this.$emit('click', this.item);
// 2.
if (!uni.getStorageSync("accessToken")) {
uni.navigateTo({
url: '/pages/blogPopup/blogPopup'
});
return;
}
// 3.
if (this.item && this.item.id) {
uni.navigateTo({
url: `/pages/jingxuan/brand-detail?id=${this.item.id}`
});
}
},
getTagStyle(tag) {
const len = this.tagsLength
let sizeStyle = {}
if (len === 1) {
sizeStyle = {
width: '288rpx',
height: '42rpx',
padding: '0 12rpx',
boxSizing: 'border-box'
}
} else if (len === 2) {
sizeStyle = {
width: '142rpx',
height: '42rpx',
padding: '0 12rpx',
boxSizing: 'border-box'
}
}
return {
...sizeStyle,
color: tag.color,
borderColor: tag.borderColor
}
}
}
}
</script>
<style lang="scss">
.brand-card-comp {
width: 328rpx;
height: 339rpx;
position: relative;
border-radius: 21rpx;
overflow: hidden;
background-color: #fff;
}
.brand-bg {
width: 100%;
height: 184rpx;
position: absolute;
top: 0;
left: 0;
z-index: 1;
}
.mask-bg {
width: 100%;
height: 251rpx;
position: absolute;
bottom: 0;
left: 0;
z-index: 2;
display: block;
}
.card-content {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
z-index: 3;
display: flex;
flex-direction: column;
align-items: center;
padding-bottom: 24rpx;
}
.avatar-wrapper {
width: 80rpx;
height: 80rpx;
border-radius: 50%;
border: 2rpx solid;
background-color: #fff;
display: flex;
justify-content: center;
align-items: center;
overflow: hidden;
margin-top: -38rpx;
margin-bottom: 12rpx;
}
.avatar-img {
width: 100%;
height: 100%;
}
.brand-name {
font-size: 28rpx;
font-weight: 500;
color: #333333;
line-height: 34rpx;
margin-bottom: 12rpx;
}
.tags-container {
display: flex;
justify-content: center;
align-items: center;
gap: 20rpx;
flex-wrap: wrap;
}
.tag-item {
display: flex;
align-items: center;
justify-content: center;
border-radius: 21rpx;
border: 1rpx solid;
background-color: transparent;
padding: 7rpx 12rpx;
}
.tag-icon {
width: 26rpx;
height: 24rpx;
margin-right: 6rpx;
flex-shrink: 0;
}
.tag-text {
font-size: 24rpx;
line-height: 28rpx;
white-space: nowrap;
margin-top: 4rpx;
padding-right: 2rpx;
}
.tag-text1 {
font-size: 40rpx;
line-height: 28rpx;
white-space: nowrap;
margin-top: 4rpx;
padding-right: 2rpx;
margin-bottom: 6rpx;
font-weight: 200;
}
</style>

View File

@ -156,6 +156,7 @@
weChatRefund: "/sj/workSeatOrder/weChatRefund", weChatRefund: "/sj/workSeatOrder/weChatRefund",
aliRefund: "/sj/workSeatOrder/aliRefund", aliRefund: "/sj/workSeatOrder/aliRefund",
startOrder: "/sj/workSeatOrder/start", startOrder: "/sj/workSeatOrder/start",
sureOrder:"/sj/workSeatOrder/sure",
endOrder: "/sj/workSeatOrder/end", endOrder: "/sj/workSeatOrder/end",
ordernum: "/sj/workSeatOrder/orderNum", ordernum: "/sj/workSeatOrder/orderNum",
list: "/sj/workSeatOrder/list", list: "/sj/workSeatOrder/list",
@ -209,7 +210,7 @@
secondTabs() { secondTabs() {
if (this.activeFirstId == 1 || this.activeFirstId == 2) { if (this.activeFirstId == 1 || this.activeFirstId == 2) {
return [{ return [{
title: `服务(${this.numInfo.noservernum})`, title: `开始(${this.numInfo.noservernum})`,
id: 3 id: 3
}, },
{ {
@ -405,6 +406,7 @@
return; return;
} }
this.clickType = true; this.clickType = true;
console.log(111,this.activeFirstId,this.urls)
request request
.post(this.urls[this.activeFirstId].sureOrder, { .post(this.urls[this.activeFirstId].sureOrder, {
id: order.id, id: order.id,
@ -414,7 +416,7 @@
.then((res) => { .then((res) => {
if (res.state != 1 || res.code != 200) { if (res.state != 1 || res.code != 200) {
uni.showToast({ uni.showToast({
title: res.msg, title: "开始服务",
icon: "none", icon: "none",
}); });
} else { } else {
@ -459,7 +461,7 @@
console.log(res); console.log(res);
if (res.state == 1 || res.code == 200) { if (res.state == 1 || res.code == 200) {
uni.showToast({ uni.showToast({
title: res.msg, title: "开始服务",
icon: "none", icon: "none",
}); });
this.searchList(); this.searchList();
@ -513,27 +515,27 @@
if (this.idType == 1) { if (this.idType == 1) {
if (this.activeFirstId == 1) { if (this.activeFirstId == 1) {
uni.navigateTo({ uni.navigateTo({
url: `/pages/shop/userorder-detail?order_id=${order.id}&order_kind=${order.order_kind}`, url: `/pages/shop/userorder-detail?order_id=${order.id}&order_kind=${order.order_kind}&haveButton=${this.haveButton}`,
}); });
} }
if (this.activeFirstId == 2) { if (this.activeFirstId == 2) {
uni.navigateTo({ uni.navigateTo({
url: `/pages/shop/userorder-detail?order_id=${order.id}&serviceType=2`, url: `/pages/shop/userorder-detail?order_id=${order.id}&serviceType=2&haveButton=${this.haveButton}`,
}); });
} }
if (this.activeFirstId == 3) { if (this.activeFirstId == 3) {
uni.navigateTo({ uni.navigateTo({
url: `/pages/shop/SellerDetail?order_id=${order.id}`, url: `/pages/shop/SellerDetail?order_id=${order.id}&haveButton=${this.haveButton}`,
}); });
} }
if (this.activeFirstId == 4) { if (this.activeFirstId == 4) {
uni.navigateTo({ uni.navigateTo({
url: `/pages/shop/userorder-detail?order_id=${order.id}&order_kind=${order.order_kind}`, url: `/pages/shop/userorder-detail?order_id=${order.id}&order_kind=${order.order_kind}&haveButton=${this.haveButton}`,
}); });
} }
if (this.activeFirstId == 5) { if (this.activeFirstId == 5) {
uni.navigateTo({ uni.navigateTo({
url: `/pages/shop/userorder-detail?order_id=${order.id}&order_kind=${order.order_kind}&serviceType=2`, url: `/pages/shop/userorder-detail?order_id=${order.id}&order_kind=${order.order_kind}&serviceType=2&haveButton=${this.haveButton}`,
}); });
} }
} }
@ -576,7 +578,7 @@
// //
&.active { &.active {
color: #e8101e; // color: #FF4767; //
font-weight: 600; // font-weight: 600; //
// //
@ -590,8 +592,8 @@
bottom: -6rpx; // bottom: -6rpx; //
height: 6rpx; // height: 6rpx; //
background: linear-gradient(306deg, background: linear-gradient(306deg,
#e8101e 0%, #FF4767 0%,
#e8101e 100%); // #FF4767 100%); //
border-radius: 3rpx; // border-radius: 3rpx; //
} }
} }
@ -626,7 +628,7 @@
// //
&.active { &.active {
color: #e8101e; // color: #FF4767; //
background: rgba(252, 67, 124, 0.1); // background: rgba(252, 67, 124, 0.1); //
font-weight: 600; // font-weight: 600; //
} }

View File

@ -0,0 +1,101 @@
<template>
<view class="notice-item" @tap="handleClick">
<view class="item-main">
<text class="item-title line-2">{{ item.title }}</text>
<view class="item-time">
<text class="time-text">发布时间{{ formattedTime }}</text>
</view>
</view>
</view>
</template>
<script>
export default {
name: "NoticeCard",
props: {
//
item: {
type: Object,
default: () => ({})
}
},
computed: {
//
formattedTime() {
const timeStr = this.item.create_time;
if (!timeStr) return '--:--:--';
let formatted = timeStr;
if (timeStr.includes('.') && !timeStr.includes('-')) {
formatted = timeStr.replace(/\./g, '-');
if (formatted.match(/\d{4}-\d{2}-\d{2}\d{2}:\d{2}:\d{2}/)) {
formatted = formatted.replace(/(\d{4}-\d{2}-\d{2})(\d{2}:\d{2}:\d{2})/, '$1 $2');
}
}
if (formatted.includes('-') && formatted.includes(':')) {
return formatted;
}
return timeStr;
}
},
methods: {
handleClick() {
// click
this.$emit('click', this.item);
}
}
};
</script>
<style lang="scss" scoped>
.notice-item {
display: flex;
align-items: center;
justify-content: space-between;
background: #ffffff;
border-radius: 20rpx;
padding: 30rpx;
margin-bottom: 20rpx;
transition: all 0.2s ease;
.item-main {
flex: 1;
min-width: 0; //
.item-title {
font-size: 30rpx;
font-weight: 500;
color: #101010;
line-height: 42rpx;
margin-bottom: 16rpx;
}
.item-time {
display: flex;
align-items: center;
.time-icon {
width: 24rpx;
height: 24rpx;
margin-right: 8rpx;
opacity: 0.6;
}
.time-text {
font-size: 22rpx;
color: #999;
line-height: 30rpx;
}
}
}
}
//
.line-2 {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
word-break: break-all;
}
</style>

View File

@ -171,6 +171,7 @@
}, },
emitStart() { emitStart() {
this.$emit("start"); this.$emit("start");
}, },
emitDone() { emitDone() {
this.$emit("done"); this.$emit("done");
@ -181,8 +182,8 @@
<style scoped lang="less"> <style scoped lang="less">
.order-card { .order-card {
padding: 20rpx 30rpx 20rpx 30rpx; padding: 24rpx 20rpx 24rpx 20rpx;
margin: 0rpx 30rpx 20rpx 30rpx; margin: 0;
background-color: #fff; background-color: #fff;
border-radius: 12px; border-radius: 12px;
/* box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); */ /* box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); */
@ -205,7 +206,7 @@
.stateText { .stateText {
font-weight: 400; font-weight: 400;
font-size: 26rpx; font-size: 26rpx;
color: #E8101E; color: #FF4767;
text-align: left; text-align: left;
font-style: normal; font-style: normal;
position: absolute; position: absolute;
@ -255,7 +256,7 @@
.service-price { .service-price {
font-weight: 500; font-weight: 500;
font-size: 24rpx; font-size: 24rpx;
color: #E8101E; color: #FF4767;
line-height: 34rpx; line-height: 34rpx;
text-align: left; text-align: left;
font-style: normal; font-style: normal;
@ -292,7 +293,7 @@
letter-spacing: 2px; letter-spacing: 2px;
text-align: left; text-align: left;
font-style: normal; font-style: normal;
background: linear-gradient(166deg, #FC5E72 0%, #E8101E 100%); background: linear-gradient(166deg, #FC5E72 0%, #FF4767 100%);
border-radius: 6rpx; border-radius: 6rpx;
padding: 4rpx 4rpx 4rpx 8rpx; padding: 4rpx 4rpx 4rpx 8rpx;
margin-right: 13rpx; margin-right: 13rpx;
@ -388,8 +389,8 @@
/* 接单按钮 */ /* 接单按钮 */
.accept-btn { .accept-btn {
border: 2rpx solid #E8101E; border: 2rpx solid #FF4767;
color: #E8101E; color: #FF4767;
} }
.order-address { .order-address {

View File

@ -129,7 +129,7 @@
.tab-text { .tab-text {
font-weight: 500; font-weight: 500;
color: #E8101E; color: #FF4767;
&::after{ &::after{
content: ''; content: '';
// //
@ -139,7 +139,7 @@
transform: translateX(-50%); transform: translateX(-50%);
bottom: -6rpx; // bottom: -6rpx; //
height: 6rpx; // height: 6rpx; //
background: linear-gradient( 306deg, #E8101E 0%, #F25988 100%); // background: linear-gradient( 306deg, #FF4767 0%, #F25988 100%); //
border-radius: 3rpx; // border-radius: 3rpx; //
} }
} }

View File

@ -0,0 +1,196 @@
<template>
<view class="skill-item" @click="handleClick">
<view class="cover-box">
<image class="cover" :src="item.coverSrc" mode="aspectFill"></image>
<image v-if="item.video" class="play-icon"
src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/5c1ddfef-a200-424a-a9dc-03d9395568f6.png"></image>
</view>
<view class="skill-info">
<view class="skill-title line-2">{{ item.title }}</view>
<view class="skill-type" :class="typeClass">
<image class="type-icon" :src="item.typeIcon || defaultTypeIcon"></image>
<text class="type-text">{{ item.type || '平台课程' }}</text>
</view>
<view class="skill-stats">
<image class="view-icon"
src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/2409b64a-56bb-4d9e-a4cc-5b3444fcf097.png">
</image>
{{ formatViews(item.views) }}观看 · {{ item.time }}
</view>
</view>
</view>
</template>
<script>
export default {
name: 'SkillItem',
props: {
item: {
type: Object,
required: true,
default: () => ({
id: null,
title: '',
coverSrc: '',
type: '平台课程',
views: 0,
time: '',
typeIcon: ''
})
}
},
data() {
return {
defaultTypeIcon: 'https://dummyimage.com/30x30/ccc/fff.png&text=I' //
}
},
computed: {
typeClass() {
const typeMap = {
'平台课程': 'platform-course',
'脸缘品牌': 'brand-course',
'品牌课程': 'brand-course'
}
return typeMap[this.item.type] || 'platform-course'
}
},
methods: {
formatViews(views) {
if (!views) return '0'
if (views >= 10000) {
return (views / 10000).toFixed(1) + 'w'
}
return views.toString()
},
handleClick() {
// 1. emit便
this.$emit('click', this.item);
// 2.
if (!uni.getStorageSync("accessToken")) {
uni.navigateTo({
url: '/pages/blogPopup/blogPopup'
});
return;
}
// 3.
if (this.item && this.item.id) {
uni.navigateTo({
url: `/pages/jingxuan/skill-detail?id=${this.item.id}`
});
}
}
}
}
</script>
<style lang="scss" scoped>
.skill-item {
display: flex;
margin-bottom: 30rpx;
&:last-child {
margin-bottom: 0;
}
.cover-box {
position: relative;
width: 224rpx;
height: 126rpx;
border-radius: 16rpx;
overflow: hidden;
margin-right: 24rpx;
flex-shrink: 0;
.cover {
width: 100%;
height: 100%;
}
.play-icon {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 39rpx;
height: 39rpx;
}
}
.skill-info {
flex: 1;
display: flex;
min-width: 0;
flex-direction: column;
justify-content: space-between;
.skill-title {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 1;
text-overflow: ellipsis;
overflow: hidden;
font-size: 28rpx;
color: #333;
font-weight: 500;
line-height: 40rpx;
}
.skill-type {
display: flex;
align-items: center;
font-size: 22rpx;
margin-top: 10rpx;
.type-icon {
border: 1rpx solid #D6CAC0;
width: 26rpx;
height: 26rpx;
margin-right: 8rpx;
border-radius: 50%;
}
.type-text {
border-radius: 7rpx;
font-weight: 400;
font-size: 24rpx;
line-height: 33rpx;
padding: 2rpx 10rpx;
}
&.platform-course .type-text {
background: #f9d3d760;
color: #E55463;
}
&.brand-course .type-text {
background: #f9d3d760;
color: #E55463;
}
}
.skill-stats {
font-size: 22rpx;
color: #999;
margin-top: 10rpx;
display: flex;
align-items: center;
.view-icon {
width: 26rpx;
height: 22rpx;
margin-right: 8rpx;
margin-top: -2rpx;
}
}
}
}
.line-2 {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
}
</style>

View File

@ -65,53 +65,14 @@
}, },
useTime() { useTime() {
const start = this.dataItem.reserve_start_time; const start = this.dataItem.reserve_start_time;
const endTime = this.dataItem.reserve_end_time; const end = this.dataItem.reserve_end_time;
if (!start || !end) return "未设置";
function formatTimeRange(startTimeStr, endTimeStr) { const startDate = new Date(start.replace(/-/g, '/'));
if (!startTimeStr || !endTimeStr) return "未设置"; const endDate = new Date(end.replace(/-/g, '/'));
if (isNaN(startDate.getTime()) || isNaN(endDate.getTime())) return "时间格式错误";
// Date const pad = (n) => String(n).padStart(2, "0");
const startTime = new Date(startTimeStr.replace(/-/g, '/')); const fmt = (d) => `${pad(d.getMonth() + 1)}.${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}`;
const endTime = new Date(endTimeStr.replace(/-/g, '/')); return `${fmt(startDate)}-${fmt(endDate)}`;
if (isNaN(startTime.getTime()) || isNaN(endTime.getTime())) {
console.error("无效的时间格式");
return "时间格式错误";
}
// YYYY
const formatYear = (date) => {
return date.getFullYear() + '年';
};
// MMDD
const formatMonthDay = (date) => {
const month = String(date.getMonth() + 1).padStart(2, "0");
const day = String(date.getDate()).padStart(2, "0");
return `${month}${day}`;
};
// HH:MM
const formatTimePart = (date) => {
const hours = String(date.getHours()).padStart(2, "0");
const minutes = String(date.getMinutes()).padStart(2, "0");
return `${hours}:${minutes}`;
};
//
const isSameDay = startTime.getFullYear() === endTime.getFullYear() &&
startTime.getMonth() === endTime.getMonth() &&
startTime.getDate() === endTime.getDate();
if (isSameDay) {
// 20250529 12:30-13:30
return `${formatYear(startTime)}${formatMonthDay(startTime)} ${formatTimePart(startTime)}-${formatTimePart(endTime)}`;
} else {
// 20250529 12:30-20250530 13:30
return `${formatYear(startTime)}${formatMonthDay(startTime)} ${formatTimePart(startTime)}-${formatYear(endTime)}${formatMonthDay(endTime)} ${formatTimePart(endTime)}`;
}
}
return formatTimeRange(start, endTime);
}, },
stateText() { stateText() {
const textList = [ const textList = [
@ -174,7 +135,7 @@
.stateText { .stateText {
font-weight: 400; font-weight: 400;
font-size: 26rpx; font-size: 26rpx;
color: #E8101E; color: #FF4767;
text-align: left; text-align: left;
font-style: normal; font-style: normal;
position: absolute; position: absolute;
@ -262,7 +223,7 @@
font-family: DINPro, DINPro; font-family: DINPro, DINPro;
font-weight: 500; font-weight: 500;
font-size: 36rpx; font-size: 36rpx;
color: #E8101E; color: #FF4767;
line-height: 34rpx; line-height: 34rpx;
text-align: left; text-align: left;
font-style: normal; font-style: normal;
@ -337,7 +298,7 @@
/* 接单按钮 */ /* 接单按钮 */
.accept-btn { .accept-btn {
border: 2rpx solid #E8101E; border: 2rpx solid #FF4767;
color: #E8101E; color: #FF4767;
} }
</style> </style>

View File

@ -0,0 +1,167 @@
<template>
<view class="growth-package-result-page">
<custom-navbar
title="支付结果"
:showBack="true"
backgroundColor="#F7F7F7"
borderBottom="none"
></custom-navbar>
<view class="result-main">
<view class="result-icon" :class="isFail ? 'is-fail' : 'is-success'">
<block v-if="isFail">
<view class="fail-line"></view>
<view class="fail-dot"></view>
</block>
<view v-else class="success-check"></view>
</view>
<view class="result-title">{{ resultInfo.title }}</view>
<view class="result-desc">{{ resultInfo.desc }}</view>
<view class="primary-btn" @tap="handlePrimaryTap">{{ isFail ? "重新支付" : "返回首页" }}</view>
</view>
</view>
</template>
<script>
import CustomNavbar from "@/components/custom-navbar/custom-navbar.vue";
export default {
components: {
CustomNavbar,
},
data() {
return {
status: "success",
};
},
computed: {
isFail() {
return this.status === "fail";
},
resultInfo() {
if (this.isFail) {
return {
title: "报名失败",
desc: "最后一步出了点问题 请重新支付",
};
}
return {
title: "报名成功",
desc: "您已完成支付 感谢你对美融融的支持",
};
},
},
onLoad(options) {
this.status = options.status === "fail" ? "fail" : "success";
},
methods: {
handlePrimaryTap() {
if (this.isFail) {
uni.redirectTo({
url: "/pages/home/growth-package",
});
return;
}
uni.switchTab({
url: "/pages/home/home",
});
},
},
};
</script>
<style lang="scss" scoped>
page {
background: #ffffff;
}
.growth-package-result-page {
min-height: 100vh;
background: #ffffff;
padding-bottom: env(safe-area-inset-bottom);
}
.result-main {
display: flex;
flex-direction: column;
align-items: center;
padding: 246rpx 40rpx 0;
}
.result-icon {
width: 104rpx;
height: 104rpx;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
}
.result-icon.is-success {
background: #12c76b;
}
.result-icon.is-fail {
background: #ff4652;
}
.success-check {
width: 44rpx;
height: 24rpx;
border-left: 8rpx solid #ffffff;
border-bottom: 8rpx solid #ffffff;
transform: rotate(-45deg);
margin-top: -8rpx;
}
.fail-line {
width: 8rpx;
height: 46rpx;
border-radius: 8rpx;
background: #ffffff;
}
.fail-dot {
width: 8rpx;
height: 8rpx;
margin-left: -8rpx;
margin-top: 58rpx;
border-radius: 50%;
background: #ffffff;
}
.result-title {
margin-top: 34rpx;
font-weight: 600;
font-size: 40rpx;
color: #333333;
line-height: 56rpx;
text-align: center;
}
.result-desc {
margin-top: 8rpx;
font-weight: 400;
font-size: 26rpx;
color: #b9b9b9;
line-height: 38rpx;
text-align: center;
}
.primary-btn {
width: 350rpx;
height: 80rpx;
margin-top: 144rpx;
border: 1rpx solid #ff4b67;
border-radius: 40rpx;
box-sizing: border-box;
background: #ffffff;
display: flex;
align-items: center;
justify-content: center;
font-weight: 400;
font-size: 30rpx;
color: #ff4767;
line-height: 42rpx;
}
</style>

View File

@ -0,0 +1,348 @@
<template>
<view class="growth-package-page">
<image class="content-image" src="@/static/images/home/growth-package/intro.png" mode="widthFix"></image>
<view class="deal-carousel">
<swiper class="deal-swiper" autoplay circular :interval="3000" previous-margin="40rpx"
next-margin="40rpx" :current="dealCurrentIndex" @change="handleDealChange">
<swiper-item v-for="(item, index) in dealSlides" :key="item">
<view class="deal-slide" :class="getDealSlideClass(index)">
<image class="deal-slide-image" :src="item" mode="aspectFit"></image>
</view>
</swiper-item>
</swiper>
<view class="deal-indicator">
<view class="indicator-track" v-for="(item, index) in dealSlides" :key="item"
:class="{ active: index === dealCurrentIndex }"></view>
</view>
</view>
<image class="content-image" src="@/static/images/home/growth-package/plan.png" mode="widthFix"></image>
<view class="fixed-action" @tap="handlePayTap">
<image class="action-image" :src="actionImage" mode="widthFix"></image>
</view>
</view>
</template>
<script>
import request from "@/utils/request";
export default {
name: "GrowthPackage",
data() {
return {
dealCurrentIndex: 0,
isPaying: false,
isJoined: false,
dealSlides: [
"/static/images/home/growth-package/deal-1.png",
"/static/images/home/growth-package/deal-2.png",
"/static/images/home/growth-package/deal-3.png",
],
};
},
computed: {
actionImage() {
return this.isJoined
? "/static/images/home/growth-package/action-success.png"
: "/static/images/home/growth-package/action.png";
},
},
onShow() {
this.getGrowthPackageStatus();
},
methods: {
async getGrowthPackageStatus() {
if (!uni.getStorageSync("accessToken")) {
this.isJoined = false;
return;
}
if (this.isPaying) return;
uni.showLoading({
title: "查询报名状态...",
mask: true,
});
try {
const res = await request.post(
"/sj/growthPackage/status",
{},
{
hideLoading: true,
}
);
this.isJoined = !!(res && res.code === 200 && res.data && Number(res.data.is_joined) === 1);
} catch (error) {
console.log("growthPackageStatus error", error);
} finally {
uni.hideLoading();
}
},
handleDealChange(event) {
this.dealCurrentIndex = event.detail.current;
},
getDealSlideClass(index) {
const length = this.dealSlides.length;
const prevIndex = (this.dealCurrentIndex + length - 1) % length;
const nextIndex = (this.dealCurrentIndex + 1) % length;
if (index === this.dealCurrentIndex) {
return "is-active";
}
if (index === prevIndex) {
return "is-prev";
}
if (index === nextIndex) {
return "is-next";
}
return "";
},
handlePayTap() {
if (this.isPaying) return;
if (this.isJoined) return;
if (!uni.getStorageSync("accessToken")) {
uni.navigateTo({
url: "/pages/blogPopup/blogPopup",
});
return;
}
uni.showActionSheet({
itemList: ["微信支付", "支付宝支付"],
success: (res) => {
const payKind = res.tapIndex === 0 ? 2 : 3;
this.createGrowthPackagePay(payKind);
},
});
},
async createGrowthPackagePay(payKind) {
this.isPaying = true;
uni.showLoading({
title: "支付中...",
mask: true,
});
try {
const payRes = await request.post(
"/sj/growthPackage/pay",
{
pay_kind: payKind,
},
{
hideLoading: true,
}
);
if (!payRes || payRes.code !== 200) {
uni.hideLoading();
this.isPaying = false;
if (payRes && payRes.data && (payRes.data.id || payRes.data.number)) {
this.goToPayResult("fail", payRes.data);
return;
}
uni.showToast({
title: (payRes && payRes.msg) || "支付请求失败",
icon: "none",
});
return;
}
const orderInfo = payRes.data || {};
if (Number(orderInfo.is_joined) === 1) {
uni.hideLoading();
this.isPaying = false;
this.isJoined = true;
this.goToPayResult("success", orderInfo.order || {});
return;
}
const paymentParams = orderInfo.pay_params || orderInfo.orderInfo;
if (!paymentParams) {
uni.hideLoading();
this.isPaying = false;
if (orderInfo.id || orderInfo.number) {
this.goToPayResult("fail", orderInfo);
return;
}
uni.showToast({
title: "支付参数缺失",
icon: "none",
});
return;
}
uni.hideLoading();
this.requestGrowthPackagePayment(payKind, paymentParams, orderInfo);
} catch (error) {
uni.hideLoading();
uni.showToast({
title: "支付请求失败",
icon: "none",
});
this.isPaying = false;
console.log("growthPackagePay error", error);
}
},
requestGrowthPackagePayment(payKind, paymentParams, orderInfo) {
const provider = payKind === 2 ? "wxpay" : "alipay";
let payOrderInfo = paymentParams;
if (payKind === 2 && paymentParams && typeof paymentParams === "object") {
payOrderInfo = {
...paymentParams,
};
const systemInfo = uni.getSystemInfoSync();
if (systemInfo.platform === "ios" && payOrderInfo.appid) {
payOrderInfo.appId = payOrderInfo.appid;
delete payOrderInfo.appid;
}
}
uni.requestPayment({
provider,
orderInfo: payOrderInfo,
success: () => {
this.queryGrowthPackagePay(orderInfo);
},
fail: (err) => {
this.isPaying = false;
console.log("growthPackage requestPayment fail", err);
this.goToPayResult("fail", orderInfo);
},
});
},
async queryGrowthPackagePay(orderInfo) {
try {
const queryRes = await request.post(
"/sj/growthPackage/queryPay",
{
id: orderInfo.id,
number: orderInfo.number,
},
{
hideLoading: true,
}
);
const order = queryRes && queryRes.data && queryRes.data.order;
if (queryRes && queryRes.code === 200 && order && Number(order.state) === 2) {
this.isJoined = true;
this.goToPayResult("success", order);
return;
}
this.goToPayResult("fail", orderInfo);
} catch (error) {
console.log("growthPackageQueryPay error", error);
this.goToPayResult("fail", orderInfo);
} finally {
this.isPaying = false;
}
},
goToPayResult(status, orderInfo = {}) {
const params = [`status=${status}`];
if (orderInfo.number) {
params.push(`number=${encodeURIComponent(orderInfo.number)}`);
}
if (orderInfo.pay_money || orderInfo.order_money) {
params.push(`money=${encodeURIComponent(orderInfo.pay_money || orderInfo.order_money)}`);
}
uni.redirectTo({
url: `/pages/home/growth-package-result?${params.join("&")}`,
});
},
},
}
</script>
<style lang="scss">
page {
background: #150903;
}
.growth-package-page {
min-height: 100vh;
padding-bottom: 259rpx;
background: #150903;
.content-image {
display: block;
width: 750rpx;
}
.deal-carousel {
position: relative;
width: 750rpx;
height: 1342rpx;
background: #000000;
overflow: hidden;
}
.deal-swiper {
width: 750rpx;
height: 1280rpx;
background: #000000;
}
.deal-slide {
position: relative;
width: 670rpx;
height: 1280rpx;
background: #000000;
overflow: hidden;
}
.deal-slide-image {
display: block;
width: 670rpx;
height: 1280rpx;
}
.deal-slide.is-prev,
.deal-slide.is-next {
height: 1169rpx;
margin-top: 56rpx;
}
.deal-slide.is-prev .deal-slide-image,
.deal-slide.is-next .deal-slide-image {
position: absolute;
top: -56rpx;
}
.deal-slide.is-prev .deal-slide-image {
right: 10rpx;
border-top-right-radius: 20rpx;
border-bottom-right-radius: 20rpx;
}
.deal-slide.is-next .deal-slide-image {
left: 10rpx;
border-top-left-radius: 20rpx;
border-bottom-left-radius: 20rpx;
}
.deal-indicator {
display: flex;
align-items: center;
justify-content: center;
height: 62rpx;
column-gap: 8rpx;
background: #000000;
}
.indicator-track {
width: 146rpx;
height: 8rpx;
border-radius: 999rpx;
background: rgba(255, 255, 255, 0.42);
}
.indicator-track.active {
background: #ffffff;
}
.fixed-action {
position: fixed;
left: 0;
right: 0;
bottom: 0;
z-index: 20;
width: 750rpx;
height: 259rpx;
background: #150903;
}
.action-image {
display: block;
width: 750rpx;
}
}
</style>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,544 @@
<template>
<view>
<custom-navbar title="精选品牌"
:leftImg="'https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/60ae3383-6ff6-4f42-818b-d9b09a9bd0e0.png'"
:showUser="true"
backgroundColor="url('https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/ce2e62e1-c26a-45c8-a49d-7ed00b2ce02c.png') center 20%/cover no-repeat"
titleColor="#333" borderBottom="none" :show-headle="true"
headleSrc="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/51ebca5d-95c5-4fb8-8aa3-560a79100d25.png"
@onHeadleClick="goToSearch" class="nav-img-size">
</custom-navbar>
<serviecFirstTab :tabs="tabs" :activeId="activeId" activeColor="#FF4767" @tab-click="tabClick" bgColor="#fff">
</serviecFirstTab>
<CommonList ref="brandListRef" :apiUrl="'/sj/brand/list'" :initialQuery="{}"
:listScrollHeight="`calc(100vh - ${statusBarHeight * 2 + 250}rpx)`" @data-loaded="handleDataLoaded">
<template #headerScroll>
<view class="icon-tabs">
<view v-for="item in iconTabs" :key="item.id" class="icon-tab"
:class="{ active: currentSecondClass == item.id }" @click="selectSecondClass(item.id)">
<image :src="item.photo" class="icon-img" mode="aspectFill"></image>
<text class="icon-text">{{ item.title }}</text>
</view>
</view>
<view class="sort-bar">
<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>
</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>
</view>
</view>
</view>
</template>
<template #listData="{ list }">
<view class="zhanwei">
<view class="brand-grid">
<brand-card class="brand-card-wrap" v-for="(brand, idx) in enrichedBrandList(list)" :key="brand.id || idx"
:item="brand" :tagKeys="brand._tagKeys" @click="handleBrandClick(brand)" />
</view>
</view>
</template>
<template #empty>
<noData></noData>
</template>
</CommonList>
</view>
</template>
<script>
import request from "../../utils/request";
import serviecFirstTab from "@/components/common/service-first-tab.vue";
import CommonList from "@/components/common/CommonList.vue";
import brandCard from "@/pages/home/components/brand-card.vue";
import noData from "@/components/noData/noData.vue";
export default {
components: {
serviecFirstTab,
CommonList,
brandCard,
noData
},
data() {
return {
statusBarHeight: 0,
navHeight: 0,
// /ID
activeId: "",
currentSecondClass: "",
tabs: [],
iconTabs: [],
selectedSecondIds: [], // ID
//
orderType: 0,
//
iconGreyUp: 'https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/e00ab2ac-bccf-42d8-820c-65727327e279.png',
iconGreyDown: 'https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/dfffb601-6877-4608-a3eb-88695b05c6c2.png',
iconPinkUp: 'https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/5bc84dff-e120-4d4b-a33e-25d68e065654.png',
iconPinkDown: 'https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/ff2c2c9d-694a-4adf-b737-66b07f4a63ae.png',
};
},
onLoad(options) {
const systemInfo = uni.getSystemInfoSync();
this.statusBarHeight = systemInfo.statusBarHeight;
this.navHeight = this.statusBarHeight + 44;
if (options.id) {
this.activeId = options.id;
}
this.getFirstClass();
//
this.loadFilterCategories();
},
methods: {
//
goToSearch() {
uni.navigateTo({
url: '/pages/search_common/search?type=brand' //
});
},
// state === 1
async loadFilterCategories() {
try {
const syrId = uni.getStorageSync('syrId') || 1;
const res = await request.post('/sj/firstclass', { id: syrId })
if ((res.code === 200 || res.state === 1) && res.data) {
const firstClasses = res.data;
//
const promises = firstClasses.map(async (first) => {
try {
const subRes = await request.post('/sj/secondclass', { id: first.id })
return {
id: first.id,
title: first.title,
children: ((subRes.code === 200 || subRes.state === 1) && subRes.data) ? subRes.data : []
}
} catch (e) {
return { id: first.id, title: first.title, children: [] }
}
});
const filterData = await Promise.all(promises);
//
this.brandFilterData = filterData.filter(group => group.children.length > 0);
} else {
this.brandFilterData = []
}
} catch (error) {
console.error('获取分类字典失败', error)
}
},
// ============ ============
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.refreshBrandList();
},
// ============ ============
getFirstClass() {
request.post("/sj/firstclass").then((res) => {
this.tabs = res.data || [];
if (this.tabs.length && !this.activeId) {
this.activeId = this.tabs[0].id;
}
this.getSecondClassList();
this.refreshBrandList();
});
},
getSecondClassList() {
if (!this.activeId) return;
request.post('/sj/secondclass', { id: this.activeId }).then((res) => {
this.iconTabs = res.data || [];
});
},
selectSecondClass(id) {
if (this.currentSecondClass === id) {
this.currentSecondClass = "";
} else {
this.currentSecondClass = id;
}
//
this.selectedSecondIds = [];
this.refreshBrandList();
},
tabClick(id) {
if (this.activeId === id) return;
this.activeId = id;
this.currentSecondClass = "";
this.selectedSecondIds = [];
this.getSecondClassList();
this.refreshBrandList();
},
// ============ ============
refreshBrandList() {
//
const targetSecondClass = this.selectedSecondIds.length > 0
? this.selectedSecondIds.join(',')
: this.currentSecondClass;
const params = {
first_class: this.activeId || undefined,
second_class: targetSecondClass || undefined,
// orderType 0 undefined使
order_type: this.orderType === 0 ? undefined : this.orderType
};
Object.keys(params).forEach(key => {
if (params[key] === undefined) delete params[key];
});
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);
}
},
enrichedBrandList(list) {
if (!list || !list.length) return [];
return list.map(brand => {
const tagKeys = [];
if (brand.franchise_state === 1) tagKeys.push('franchise');
if (brand.student_state === 1) tagKeys.push('recruit');
if (tagKeys.length === 0) tagKeys.push('more');
return {
...brand,
name: brand.name,
bgSrc: brand.cover_img || 'https://dummyimage.com/300x200/ccc/fff.png',
avatar: brand.logo_img || 'https://dummyimage.com/100x100/ccc/fff.png',
_tagKeys: tagKeys
};
});
},
handleBrandClick(brand) {
uni.navigateTo({
url: `/pages/brand/detail?id=${brand.id}`
});
},
handleDataLoaded(data) {
console.log("品牌列表加载完成", data);
}
}
};
</script>
<style lang="less" scoped>
//
::v-deep .icon-headle {
width: 32rpx !important;
height: 32rpx !important;
}
// Tab
.service-first-tab {
border-bottom: none;
padding-bottom: 27rpx;
position: relative;
z-index: 101;
}
::v-deep .service-first-tab {
box-shadow: none !important;
}
/* ================= 抽屉下拉样式 ================= */
.filter-panel {
position: fixed;
left: 0;
right: 0;
bottom: 0;
z-index: 100;
pointer-events: none;
overflow: hidden;
&.show {
pointer-events: auto;
.filter-mask {
opacity: 1;
}
.filter-container {
transform: translateY(0);
}
}
.filter-mask {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.4);
opacity: 0;
transition: opacity 0.3s ease-in-out;
}
.filter-container {
position: absolute;
top: 0;
left: 0;
right: 0;
background: #fff;
border-radius: 0 0 30rpx 30rpx;
padding: 140rpx 30rpx 40rpx;
display: flex;
flex-direction: column;
box-shadow: 0 10rpx 20rpx rgba(0, 0, 0, 0.05);
transform: translateY(-100%);
transition: transform 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
}
}
.filter-scroll {
max-height: 50vh;
}
.filter-group {
margin-bottom: 30rpx;
.group-title {
font-weight: 500;
font-size: 28rpx;
color: #333333;
line-height: 40rpx;
margin-bottom: 20rpx;
}
.pill-list {
display: flex;
flex-wrap: wrap;
gap: 20rpx 10rpx;
/* 控制行间距和列间距 */
}
}
/* 通用胶囊按钮 (一行四个) */
.pill-item {
width: calc(25% - 8rpx);
/* 精确计算一行四个 */
height: 58rpx;
background: #F5F5F5;
font-weight: 400;
font-size: 24rpx;
/* 字号略小以防溢出 */
color: #333333;
line-height: 37rpx;
/* flex 居中文字 */
display: flex;
align-items: center;
justify-content: center;
border-radius: 12rpx;
transition: all 0.3s;
box-sizing: border-box;
white-space: nowrap;
&.active {
background: #FFF0F2;
color: #FF4767;
border: 1rpx solid #FFB0BD;
}
}
.filter-footer {
display: flex;
justify-content: space-between;
margin-top: 40rpx;
.reset-btn,
.confirm-btn {
width: 47%;
text-align: center;
padding: 22rpx 0;
border-radius: 40rpx;
font-size: 28rpx;
}
.reset-btn {
background: #F5F5F5;
color: #666;
}
.confirm-btn {
background: #FF4767;
color: #fff;
}
}
/* ================= 其他页面样式 ================= */
//
.icon-tabs {
display: flex;
flex-flow: row wrap;
justify-content: flex-start;
align-items: center;
column-gap: 36rpx;
row-gap: 30rpx;
background: transparent;
padding: 0 0 0 30rpx;
margin-bottom: 30rpx;
}
.icon-tab {
display: flex;
flex-direction: column;
align-items: center;
}
.icon-img {
width: 100rpx;
height: 100rpx;
border-radius: 50%;
border: 2rpx solid transparent;
}
.icon-text {
margin-top: 10rpx;
font-weight: 400;
font-size: 24rpx;
color: #333333;
line-height: 33rpx;
text-align: left;
}
.icon-tab.active .icon-text {
color: #FF4767;
line-height: 33rpx;
}
.icon-tab.active .icon-img {
border: 2rpx solid #FF4767;
}
//
.sort-bar {
display: flex;
align-items: center;
padding: 0 30rpx;
margin-bottom: 24rpx;
gap: 100rpx;
.sort-item {
display: flex;
align-items: center;
.sort-text {
font-weight: 400;
font-size: 26rpx;
color: #666666;
line-height: 37rpx;
margin-right: 6rpx;
&.active {
color: #FF4767;
font-weight: 500;
}
}
.arrows {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
.arrow-icon {
width: 13rpx;
height: 8rpx;
margin: 2rpx 0;
}
}
}
}
//
.zhanwei {
background-color: #f5f5f5;
padding: 20rpx 0 0 0;
border-radius: 20rpx 20rpx 0rpx 0rpx;
}
.brand-grid {
background-color: #ffffff;
display: flex;
flex-wrap: wrap;
justify-content: space-between;
padding: 20rpx 24rpx;
row-gap: 24rpx;
border-radius: 20rpx 20rpx 0rpx 0rpx;
.brand-card-wrap {
width: 48.5%;
}
}
.common-list {
::v-deep .list-container {
padding: 0;
}
::v-deep .list-scroll {
margin-top: 0rpx;
}
}
.service-list {
background-color: #f5f5f5;
border-radius: 20rpx 20rpx 0 0;
}
.nav-img-size::v-deep .icon-headle {
width: 36rpx !important;
height: 36rpx !important;
}
</style>

View File

@ -0,0 +1,579 @@
<template>
<view class="skill-market-page">
<custom-navbar title="技能集市" :showBack="true" backgroundColor="#FFFFFF" :show-headle="true" borderBottom="none"
headleSrc="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/51ebca5d-95c5-4fb8-8aa3-560a79100d25.png"
@onHeadleClick="goToSearch" class="nav-img-size">
</custom-navbar>
<view class="sticky-header-container" :style="{ top: navHeight + 'px' }">
<view class="official-author-block" v-if="authorInfo.show">
<view class="author-left">
<image class="author-avatar" :src="authorInfo.avatar" mode="aspectFill"></image>
<view class="author-info">
<text class="author-name">{{ authorInfo.name }}</text>
<text class="author-desc">发布了{{ authorInfo.videoCount }}条技能</text>
</view>
</view>
<view class="view-more-btn" v-if="!authorInfo.isOfficial" @click="goToBrandDetail">
<text>查看更多</text>
<view class="arrow-right"></view>
</view>
</view>
<view class="sort-bar-wrap">
<view class="sort-bar">
<view class="left-sorts">
<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>
</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>
</view>
</view>
</view>
<view class="right-filter" @tap="toggleFilterPanel" v-if="!authorInfo.show">
<text class="filter-text">筛选</text>
<image class="filter-icon" :src="filterIcon" :class="{ 'rotate': filterVisible }"></image>
</view>
</view>
<view class="filter-panel" :class="{ 'show': filterVisible }" catchtouchmove="true">
<view class="filter-mask" @tap="closeFilterPanel"></view>
<view class="filter-container">
<text class="group-title">课程类型</text>
<view class="course-filter">
<view class="course-type-item" :class="{ active: linkType === '' }" @tap="selectAndApply('')">全部</view>
<view class="course-type-item" :class="{ active: linkType === 1 }" @tap="selectAndApply(1)">平台课程</view>
<view class="course-type-item" :class="{ active: linkType === 2 }" @tap="selectAndApply(2)">品牌课程</view>
</view>
</view>
</view>
</view>
</view>
<view class="list-container">
<view v-if="skillList.length > 0">
<skill-card v-for="(item, index) in skillList" :key="item.id || index" :item="item"
@click="goToDetail(item)"></skill-card>
</view>
<view v-else>
<noData></noData>
</view>
</view>
<view style="height: 60rpx;"></view>
</view>
</template>
<script>
import request from "@/utils/request"
import SkillCard from "@/pages/home/components/skill-card.vue"
import noData from "@/components/noData/noData.vue";
const USE_REAL_API = true
export default {
components: { SkillCard, noData },
data() {
return {
navHeight: 0,
orderType: 0,
linkType: '',
// //
authorInfo: {
show: false, //
isOfficial: false, //
brandId: null, // ID
name: '', // /
avatar: '', //
videoCount: 0 //
},
filterVisible: false,
skillList: [],
page: 1,
limit: 10,
isFinished: false,
iconGreyUp: 'https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/e00ab2ac-bccf-42d8-820c-65727327e279.png',
iconGreyDown: 'https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/dfffb601-6877-4608-a3eb-88695b05c6c2.png',
iconPinkUp: 'https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/5bc84dff-e120-4d4b-a33e-25d68e065654.png',
iconPinkDown: 'https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/ff2c2c9d-694a-4adf-b737-66b07f4a63ae.png',
mockDatabase: []
}
},
computed: {
filterIcon() {
return this.filterVisible
? 'https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/e00ab2ac-bccf-42d8-820c-65727327e279.png'
: 'https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/bfe7a104-bef8-4432-9487-42f05e3e9035.png'
}
},
//
onLoad(options) {
if (options && options.showAuthor === '1') {
this.authorInfo.show = true;
this.authorInfo.isOfficial = options.isOfficial === '1';
this.authorInfo.brandId = options.linkId || null;
// decodeURIComponent
this.authorInfo.name = options.authorName ? decodeURIComponent(options.authorName) : '未知作者';
this.authorInfo.avatar = options.authorAvatar ? decodeURIComponent(options.authorAvatar) : 'https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/bbe832bf-aae6-4579-b3cc-246d252488c3';
this.authorInfo.videoCount = options.videoCount || 0;
//
this.linkType = this.authorInfo.isOfficial ? 1 : 2;
} else if (options && options.linkType !== undefined) {
this.linkType = Number(options.linkType);
}
const sysInfo = uni.getSystemInfoSync()
const sbh = sysInfo.statusBarHeight || 0
this.navHeight = sbh
this.initMockData()
this.fetchData(true)
},
onReachBottom() {
if (!this.isFinished) {
this.fetchData(false)
}
},
methods: {
goToSearch() {
uni.navigateTo({
url: '/pages/search_common/search?type=skill'
});
},
//
goToBrandDetail() {
if (this.authorInfo.brandId) {
uni.navigateTo({
url: `/pages/jingxuan/brand-detail?id=${this.authorInfo.brandId}`
});
} else {
uni.showToast({ title: '缺少品牌信息', icon: 'none' });
}
},
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)
},
toggleFilterPanel() {
this.filterVisible = !this.filterVisible
},
closeFilterPanel() {
this.filterVisible = false
},
selectAndApply(typeVal) {
this.linkType = typeVal;
//
this.authorInfo.show = false;
this.closeFilterPanel();
this.fetchData(true);
},
async fetchData(isReset = false) {
if (isReset) {
this.page = 1
this.isFinished = false
this.skillList = []
}
if (USE_REAL_API) {
uni.showLoading({ title: '加载中...' })
try {
const params = {
page: this.page,
limit: this.limit
}
if (this.orderType !== 0) params.order_type = this.orderType;
if (this.linkType !== '') params.link_type = this.linkType;
// link_id
if (this.authorInfo.show && !this.authorInfo.isOfficial && this.authorInfo.brandId) {
params.link_id = this.authorInfo.brandId;
}
const res = await request.post('/sj/skill/list', params)
if ((res.code === 200 || res.state === 1) && res.data && res.data.list) {
const list = res.data.list.map(item => this.formatApiData(item))
if (list.length < this.limit) this.isFinished = true
this.skillList = isReset ? list : this.skillList.concat(list)
this.page++
} else {
this.isFinished = true
}
} catch (e) {
uni.showToast({ title: '加载失败', icon: 'none' })
} finally {
uni.hideLoading()
}
} else {
uni.showLoading({ title: '模拟加载中...' })
setTimeout(() => {
let list = [...this.mockDatabase]
if (this.linkType !== '') {
list = list.filter(item => item.link_type === this.linkType)
}
//
if (this.authorInfo.show && !this.authorInfo.isOfficial && this.authorInfo.brandId) {
list = list.filter(item => item.brand_id == this.authorInfo.brandId)
}
if (this.orderType !== 0) {
list.sort((a, b) => {
if (this.orderType === 1) return b.timestamp - a.timestamp
if (this.orderType === 2) return a.timestamp - b.timestamp
if (this.orderType === 3) return b.views - a.views
if (this.orderType === 4) return a.views - b.views
return 0
})
}
const start = (this.page - 1) * this.limit
const end = start + this.limit
const pageData = list.slice(start, end)
if (pageData.length < this.limit) this.isFinished = true
this.skillList = isReset ? pageData : this.skillList.concat(pageData)
this.page++
uni.hideLoading()
}, 500)
}
},
formatApiData(item) {
return {
id: item.id,
title: item.name,
coverSrc: item.cover_img || 'https://dummyimage.com/300x200/ccc/fff.png',
type: item.link_name || (item.link_type === 1 ? '平台课程' : '品牌课程'),
link_type: item.link_type,
views: item.browse_num || 0,
time: item.create_time ? this.formatTimeAgo(item.create_time) : '',
typeIcon: item.link_logo || ''
}
},
formatTimeAgo(timeStr) {
const now = new Date()
const time = new Date(timeStr.replace(/-/g, '/'))
const diff = Math.floor((now - time) / 1000)
if (diff < 3600) return Math.floor(diff / 60) + '分钟前'
if (diff < 86400) return Math.floor(diff / 3600) + '小时前'
if (diff < 604800) return Math.floor(diff / 86400) + '天前'
return timeStr.split(' ')[0]
},
goToDetail(item) {
if (item.id) {
uni.navigateTo({ url: `/pages/skill/detail?id=${item.id}` })
} else {
uni.showToast({ title: '详情页开发中', icon: 'none' })
}
},
initMockData() {
this.mockDatabase = [
{ id: 1, title: '穿戴甲的操作视频扫码验券操作教程', coverSrc: 'https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/e2220528-fdf6-4cad-a25d-ec6cbee1501e.jpg', type: '平台课程', link_type: 1, views: 836000, time: '7小时前', timestamp: Date.now() - 7 * 3600000 },
{ id: 2, title: '脸部按摩操作步骤详情', coverSrc: 'https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/e2220528-fdf6-4cad-a25d-ec6cbee1501e.jpg', type: '品牌课程', link_type: 2, brand_id: 101, views: 8334, time: '1天前', timestamp: Date.now() - 24 * 3600000 },
{ id: 3, title: '全身SPA的操作视频操作教程', coverSrc: 'https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/e2220528-fdf6-4cad-a25d-ec6cbee1501e.jpg', type: '平台课程', link_type: 1, views: 2344, time: '3天前', timestamp: Date.now() - 3 * 24 * 3600000 },
{ id: 4, title: '高级面部护理手法详解最新版', coverSrc: 'https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/e2220528-fdf6-4cad-a25d-ec6cbee1501e.jpg', type: '平台课程', link_type: 1, views: 836, time: '4月26日', timestamp: Date.now() - 30 * 24 * 3600000 },
{ id: 5, title: '光疗美甲进阶全方位解析', coverSrc: 'https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/e2220528-fdf6-4cad-a25d-ec6cbee1501e.jpg', type: '品牌课程', link_type: 2, brand_id: 101, views: 12000, time: '2小时前', timestamp: Date.now() - 2 * 3600000 }
]
}
}
}
</script>
<style lang="scss" scoped>
.skill-market-page {
min-height: 100vh;
background: #fff;
}
/* 统一吸顶容器 */
.sticky-header-container {
position: sticky;
background: #fff;
z-index: 101;
/* 确保整体吸顶时下方有稍微一点阴影或边框分割更好看,可根据 UI 需求开启 */
// border-bottom: 1rpx solid #F5F5F5;
}
/* 官方/品牌 作者展示块样式 */
.official-author-block {
display: flex;
align-items: center;
justify-content: space-between;
padding: 24rpx 30rpx;
background: #fff;
border-bottom: 10rpx solid #F5F5F5;
.author-left {
display: flex;
align-items: center;
.author-avatar {
width: 70rpx;
height: 70rpx;
border-radius: 50%;
margin-right: 20rpx;
}
.author-info {
display: flex;
flex-direction: column;
.author-name {
font-weight: 500;
font-size: 28rpx;
color: #333333;
line-height: 40rpx;
margin-bottom: 4rpx;
}
.author-desc {
font-weight: 400;
font-size: 20rpx;
color: #999999;
line-height: 28rpx;
}
}
}
.view-more-btn {
display: flex;
align-items: center;
font-size: 24rpx;
color: #FF4767;
border: 2rpx solid #FF4767;
padding: 8rpx 20rpx;
border-radius: 45rpx;
.arrow-right {
width: 10rpx;
height: 10rpx;
border-top: 2rpx solid #FF4767;
border-right: 2rpx solid #FF4767;
transform: rotate(45deg);
margin-left: 6rpx;
}
}
}
.sort-bar-wrap {
/* 移除单独的 sticky由外层 container 统一控制 */
background: #fff;
position: relative;
}
.sort-bar {
display: flex;
align-items: center;
justify-content: space-between;
padding: 24rpx 30rpx;
.left-sorts {
display: flex;
align-items: center;
gap: 100rpx;
.sort-item {
display: flex;
align-items: center;
.sort-text {
font-size: 28rpx;
color: #333333;
margin-right: 6rpx;
font-weight: 400;
&.active {
color: #FF4767;
font-weight: 500;
}
}
.arrows {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
.arrow-icon {
width: 14rpx;
height: 8rpx;
margin: 2rpx 0;
}
}
}
}
.right-filter {
display: flex;
align-items: center;
.filter-text {
font-size: 26rpx;
color: #666666;
margin-right: 8rpx;
}
.filter-icon {
width: 24rpx;
height: 24rpx;
transition: transform 0.3s ease;
&.rotate {
transform: rotate(180deg);
width: 18rpx;
height: 12rpx;
}
}
}
}
.list-container {
padding: 0 24rpx 30rpx;
}
.filter-panel {
position: absolute;
top: 100%;
left: 0;
right: 0;
height: 100vh;
z-index: 100;
pointer-events: none;
overflow: hidden;
&.show {
pointer-events: auto;
.filter-mask {
opacity: 1;
}
.filter-container {
transform: translateY(0);
}
}
.filter-mask {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.4);
opacity: 0;
transition: opacity 0.3s ease-in-out;
}
.filter-container {
position: absolute;
top: 0;
left: 0;
right: 0;
background: #fff;
border-radius: 0 0 24rpx 24rpx;
padding: 30rpx 30rpx 40rpx;
display: flex;
flex-direction: column;
transform: translateY(-100%);
transition: transform 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
}
}
.group-title {
font-weight: 500;
font-size: 28rpx;
color: #333333;
margin-bottom: 24rpx;
display: block;
}
.course-filter {
display: flex;
gap: 20rpx;
.course-type-item {
background: #F5F5F5;
color: #333333;
font-size: 26rpx;
padding: 12rpx 36rpx;
border-radius: 12rpx;
border: 1rpx solid transparent;
transition: all 0.2s;
display: flex;
align-items: center;
justify-content: center;
&.active {
background: #FFF0F2;
color: #FF4767;
border-color: #FFB0BD;
}
}
}
.empty-state {
display: flex;
flex-direction: column;
align-items: center;
padding: 120rpx 0;
.empty-icon {
width: 346rpx;
height: 373rpx;
}
}
::v-deep .icon-headle {
width: 32rpx !important;
height: 32rpx !important;
}
::v-deep .back-icon {
width: 28rpx !important;
height: 36rpx !important;
}
.nav-img-size::v-deep .icon-headle {
width: 36rpx !important;
height: 36rpx !important;
}
</style>

View File

@ -0,0 +1,768 @@
<template>
<view class="skill-detail-page">
<custom-navbar title="技能集市" backgroundColor="#ffffff" titleColor="#333" borderBottom="none">
</custom-navbar>
<!-- <view class="mock-switch" @click="toggleMockData">
<text>{{ useMockData ? '关闭模拟数据' : '开启模拟数据' }}</text>
</view> -->
<view class="video-section" v-if="article.videoSrc">
<view class="video-wrapper">
<video v-if="!tipShow" id="customVideo" class="main-video" :src="article.videoSrc" :poster="article.poster"
:controls="showNativeControls" :show-center-play-btn="false" :muted="isMuted" object-fit="cover"
@timeupdate="onTimeUpdate" @loadedmetadata="onLoadedMetaData" @ended="onEnded" @play="onPlay" @pause="onPause"
@fullscreenchange="onFullScreenChange">
<cover-image v-if="!isPlaying && !showNativeControls" class="center-play-icon"
src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/bb720bb0-4ada-49f6-9ce5-38abfd613d5d.png"
@click.stop="togglePlay"></cover-image>
<cover-view class="custom-control-bar" v-if="!showNativeControls">
<cover-image class="bar-bg"
src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/ce7f28f8-470d-4f5b-9c7e-ff2bf8635226.png"></cover-image>
<cover-view class="bar-content">
<cover-image v-if="isPlaying" class="ctrl-icon" :src="iconPause" @click.stop="togglePlay"></cover-image>
<cover-image v-if="!isPlaying" class="ctrl-icon" :src="iconPlay" @click.stop="togglePlay"></cover-image>
<cover-view class="time-text">{{ formatTime(currentTime) }}</cover-view>
<cover-view class="slider-track">
<cover-view class="slider-bg"></cover-view>
<cover-view class="slider-active" :style="activeStyle"></cover-view>
<cover-view class="slider-thumb" v-if="currentTime > 0" :style="thumbStyle"></cover-view>
</cover-view>
<cover-view class="time-text">{{ formatTime(duration) }}</cover-view>
<cover-image v-if="!isMuted" class="ctrl-icon mute-icon" :src="iconSoundOn"
@click.stop="toggleMute"></cover-image>
<cover-image v-if="isMuted" class="ctrl-icon mute-icon" :src="iconMute"
@click.stop="toggleMute"></cover-image>
<cover-image class="ctrl-icon fullscreen-icon" :src="iconFullscreen"
@click.stop="toggleFullScreen"></cover-image>
</cover-view>
</cover-view>
</video>
<image v-else class="main-video fallback-poster" :src="article.poster || article.videoSrc" mode="aspectFill">
</image>
</view>
</view>
<view class="article-header" v-if="article.title">
<view class="title">{{ article.title }}</view>
<view class="meta-row">
<view class="author-info" @click="goToAuthorMarket">
<image class="avatar" :src="article.authorAvatar" mode="aspectFill"></image>
<text class="author-name">{{ article.authorName }}</text>
<text class="date">{{ article.date }}</text>
</view>
<view class="favorite-btn" @click="toggleFavorite">
<image class="star-icon" :src="isFavorite ? filledStarUrl : emptyStarUrl" />
<text :class="{ 'active-fav': isFavorite }">{{ isFavorite ? '已收藏' : '收藏' }}</text>
</view>
</view>
</view>
<view class="article-content-wrapper">
<view class="article-content">
<rich-text :nodes="formattedHtmlContent"></rich-text>
</view>
</view>
<view class="recommend-section" v-if="recommendList.length > 0">
<view class="section-header">
<text class="section-title">相关推荐</text>
<view class="refresh-btn" @click="refreshList">
<image class="refresh-icon" :class="{ 'is-rotating': isRefreshing }"
src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/f2152145-df2a-49ab-87f5-f66b3207d0b0.png">
</image>
<text>换一批</text>
</view>
</view>
<view class="list-container">
<skill-card v-for="(item, index) in recommendList" :key="index" :item="item"></skill-card>
</view>
</view>
<tipsPopup2 :show="tipShow" @closePopup="closePopup" sureText="确认" @okBtn="okBtn">
{{ tipsText }}
</tipsPopup2>
</view>
</template>
<script>
import request from "@/utils/request";
import SkillCard from "@/pages/home/components/skill-card.vue";
import tipsPopup2 from "@/components/tips-popup/tips-popup2";
export default {
components: {
SkillCard,
tipsPopup2
},
data() {
return {
useMockData: false,
articleId: null,
isFavorite: false,
emptyStarUrl: 'https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/53378402-5456-4a80-b2ec-7c18d43d970e.png',
filledStarUrl: 'https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/10461305-6bf8-4016-ae76-3415e055ec63.png',
isRefreshing: false,
isLogin: false,
tipShow: false,
tipsText: "",
tipType: "",
videoContext: null,
isPlaying: false,
isMuted: false,
showNativeControls: false,
currentTime: 0,
duration: 0,
sliderValue: 0,
iconPlay: 'https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/88ca4fe3-645c-48a9-abda-1f9b45714970.png',
iconPause: 'https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/cf9d6dd6-e9df-4c46-bafa-e1a72f7ddbcd.png',
iconSoundOn: 'https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/9f13a630-7efd-4c61-b6fe-b6b282e28e42.png',
iconMute: 'https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/80f856c1-3d66-4b11-b21a-8eb6a3272a3c.png',
iconFullscreen: 'https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/4286ef33-6849-4851-8866-4230d2523a33.png',
article: {},
recommendList: [],
recommendPage: 1
}
},
computed: {
formattedHtmlContent() {
if (!this.article.htmlContent) return '';
let html = this.article.htmlContent;
html = html.replace(/<img/gi, '<img style="max-width:100%; height:auto; display:block; border-radius:10px; margin: 20rpx 0;"');
html = html.replace(/<p/gi, '<p style="margin-bottom: 24rpx; line-height: 40rpx;"');
return html;
},
activeStyle() {
return `width: ${this.sliderValue}%;`;
},
thumbStyle() {
return `left: ${this.sliderValue}%;`;
}
},
onLoad(options) {
if (options && options.id) {
this.articleId = parseInt(options.id, 10);
} else {
this.articleId = 1;
}
this.getPageData();
},
onShow() {
this.isLogin = uni.getStorageSync("accessToken") ? true : false;
},
methods: {
//
goToAuthorMarket() {
const isOfficial = this.article.linkType === 1 ? '1' : '0';
const linkId = this.article.linkId || '';
const name = encodeURIComponent(this.article.authorName || '');
const avatar = encodeURIComponent(this.article.authorAvatar || '');
const count = this.article.authorVideoCount || 0;
uni.navigateTo({
url: `/pages/jingxuan/selected-skills?showAuthor=1&isOfficial=${isOfficial}&linkId=${linkId}&authorName=${name}&authorAvatar=${avatar}&videoCount=${count}`
});
},
getVideoContext() {
if (!this.videoContext) {
this.videoContext = uni.createVideoContext('customVideo', this);
}
return this.videoContext;
},
closePopup() {
this.tipShow = false;
},
okBtn() {
if (this.tipType == "login") {
uni.navigateTo({
url: "/pages/blogPopup/blogPopup",
});
}
this.tipShow = false;
},
formatTime(sec) {
if (!sec) return '00:00';
sec = Math.round(sec);
let m = Math.floor(sec / 60);
let s = sec % 60;
return (m < 10 ? '0' + m : m) + ':' + (s < 10 ? '0' + s : s);
},
onLoadedMetaData(e) {
this.duration = e.detail.duration;
},
onTimeUpdate(e) {
if (e.detail.duration && this.duration === 0) {
this.duration = e.detail.duration;
}
this.currentTime = e.detail.currentTime;
if (this.duration > 0) {
this.sliderValue = Number(((this.currentTime / this.duration) * 100).toFixed(2));
}
},
onEnded() {
this.isPlaying = false;
this.currentTime = 0;
this.sliderValue = 0;
if (this.showNativeControls) {
const ctx = this.getVideoContext();
if (ctx) ctx.exitFullScreen();
}
},
onPlay() { this.isPlaying = true; },
onPause() { this.isPlaying = false; },
onFullScreenChange(e) {
const isFull = e.detail.fullScreen;
if (!isFull) {
this.showNativeControls = false;
} else {
this.showNativeControls = true;
}
},
togglePlay() {
const ctx = this.getVideoContext();
if (!ctx) return;
if (this.isPlaying) {
ctx.pause();
} else {
ctx.play();
}
},
toggleMute() {
this.isMuted = !this.isMuted;
},
toggleFullScreen() {
const ctx = this.getVideoContext();
if (!ctx) return;
this.showNativeControls = true;
this.$nextTick(() => {
ctx.requestFullScreen({ direction: 90 });
});
},
toggleMockData() {
this.useMockData = !this.useMockData;
uni.showToast({ title: this.useMockData ? 'Mock已开启' : 'Mock已关闭', icon: 'none' });
this.getPageData();
},
getPageData() {
if (this.useMockData) {
this.injectMockData();
return;
}
uni.showLoading({ title: '加载中...' });
request.post("/sj/skill/details", {
id: this.articleId
}).then((res) => {
if (res.code == 200 && res.data) {
const data = res.data;
this.article = {
title: data.name || '暂无标题',
// 使
linkType: data.link_type || 1, // 1= 2=
linkId: data.link_id || 0,
authorName: data.link_name || '美融融平台',
authorAvatar: data.link_logo || 'https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/bbe832bf-aae6-4579-b3cc-246d252488c3',
authorVideoCount: data.link_publish_num || 0, //
date: data.create_time ? data.create_time.substring(0, 10).replace(/-/g, '.') : '',
videoSrc: data.video || '',
poster: data.cover_img || '',
htmlContent: data.detail || ''
};
this.isFavorite = data.collect_state === 1;
request.post("/sj/skill/list", {
page: 1,
limit: 3,
skill_id: data.id
}).then((listRes) => {
if (listRes.code == 200 && listRes.data && listRes.data.list) {
// 使 map
this.recommendList = listRes.data.list.map(item => {
return {
id: item.id,
title: item.name || '暂无标题', //
coverSrc: item.cover_img || '', //
type: item.link_name || '平台课程', // /
typeIcon: item.link_logo || '', //
// /
views: item.total_browse_num || item.real_browse_num || item.browse_num || 0,
//
time: item.create_time ? item.create_time.substring(0, 10).replace(/-/g, '-') : ''
};
});
}
}).catch((err) => {
console.error('获取推荐列表异常', err);
});
} else {
uni.showToast({ title: res.msg || '获取数据失败', icon: 'none' });
}
}).catch((err) => {
console.error('获取技能集市详情异常', err);
}).finally(() => {
uni.hideLoading();
});
},
toggleFavorite() {
if (!this.isLogin) {
if (this.isPlaying) {
this.getVideoContext().pause();
}
this.tipsText = "您现在还未登录,是否确定前往登录?";
this.tipShow = true;
this.tipType = "login";
return;
}
if (this.useMockData) {
this.isFavorite = !this.isFavorite;
uni.showToast({ title: this.isFavorite ? '收藏成功' : '已取消收藏', icon: 'none' });
return;
}
uni.showLoading({ title: '处理中' });
const targetState = this.isFavorite ? 2 : 1;
request.post("/sj/skill/collect", {
id: this.articleId,
state: targetState
}).then(res => {
if (res.code == 200) {
this.isFavorite = !this.isFavorite;
uni.showToast({ title: this.isFavorite ? '收藏成功' : '已取消收藏', icon: 'none' });
} else {
uni.showToast({ title: res.msg || '操作失败', icon: 'none' });
}
}).catch(err => {
uni.showToast({ title: '网络异常', icon: 'none' });
}).finally(() => {
uni.hideLoading();
});
},
refreshList() {
if (this.isRefreshing) return;
this.isRefreshing = true;
uni.showLoading({ title: '加载中' });
// 101+1
if (this.recommendPage >= 10) {
this.recommendPage = 1;
} else {
this.recommendPage++;
}
request.post("/sj/skill/list", {
page: this.recommendPage,
limit: 3,
skill_id: this.article.id
}).then((res) => {
if (res.code == 200 && res.data && res.data.list && res.data.list.length > 0) {
this.recommendList = res.data.list.map(item => ({
id: item.id,
title: item.name || '暂无标题',
coverSrc: item.cover_img || '',
type: item.link_name || '平台课程',
views: item.browse_num || 0,
time: item.create_time ? item.create_time.split(' ')[0] : '',
typeIcon: item.link_logo || '',
video: item.video || ''
}));
} else {
// 1
this.recommendPage = 1;
request.post("/sj/skill/list", {
page: 1,
limit: 3,
skill_id: this.article.id
}).then((res2) => {
if (res2.code == 200 && res2.data && res2.data.list) {
this.recommendList = res2.data.list.map(item => ({
id: item.id,
title: item.name || '暂无标题',
coverSrc: item.cover_img || '',
type: item.link_name || '平台课程',
views: item.browse_num || 0,
time: item.create_time ? item.create_time.split(' ')[0] : '',
typeIcon: item.link_logo || '',
video: item.video || ''
}));
}
});
}
this.isRefreshing = false;
uni.hideLoading();
}).catch(() => {
this.isRefreshing = false;
uni.hideLoading();
});
},
injectMockData() {
this.isFavorite = false;
this.article = {
title: '穿戴甲的操作视频扫码验券操作',
// Mock(linkType2)
linkType: 2,
linkId: 101,
authorName: '蜜丝卡伦官方品牌',
authorAvatar: 'https://images.unsplash.com/photo-1512290923902-8a9f81dc236c?ixlib=rb-4.0.3&auto=format&fit=crop&w=100&q=80',
authorVideoCount: 658,
date: '2026.03.03',
videoSrc: 'https://vjs.zencdn.net/v/oceans.mp4',
poster: 'https://images.unsplash.com/photo-1610992015732-2449b76344bc?ixlib=rb-4.0.3&auto=format&fit=crop&w=800&q=80',
htmlContent: `
<p>最近一向以平价良心宠粉著称的胖东来突然因为一条毛巾被推上风口浪尖</p>
<p>4月下旬抖音博主惊梦人-连续发布多条探店视频称自己跑遍许昌5家胖东来门店发现一边是几块钱的玻璃水洗衣液等亲民好物另一边却摆着标价249元的高端毛巾价格形成反差</p>
<img src="https://dummyimage.com/800x400/ff6b81/ffffff.png&text=占位图" alt="会员权益"/>
`
};
this.loadMockRecommend();
},
loadMockRecommend() {
this.recommendList = [
{
id: 1,
title: '穿戴甲的操作视频扫码验券操作教程...',
coverSrc: 'https://images.unsplash.com/photo-1604654894610-df63bc536371?ixlib=rb-4.0.3&auto=format&fit=crop&w=400&q=80',
type: '平台课程',
typeIcon: 'https://dummyimage.com/100x100/e6505f/fff.png&text=融',
views: 836000,
time: '7小时前'
},
{
id: 2,
title: '脸部按摩操作步骤详情',
coverSrc: 'https://images.unsplash.com/photo-1512290923902-8a9f81dc236c?ixlib=rb-4.0.3&auto=format&fit=crop&w=400&q=80',
type: '脸缘品牌',
typeIcon: 'https://dummyimage.com/100x100/e6505f/fff.png&text=缘',
views: 8334,
time: '1天前'
}
];
}
}
}
</script>
<style lang="scss" scoped>
.skill-detail-page {
background-color: #ffffff;
min-height: 100vh;
padding-bottom: 60rpx;
position: relative;
}
.mock-switch {
position: fixed;
right: 20rpx;
top: 200rpx;
background: #E5505F;
color: #fff;
font-size: 24rpx;
padding: 10rpx 20rpx;
border-radius: 30rpx;
z-index: 999;
box-shadow: 0 4rpx 10rpx rgba(229, 80, 95, 0.4);
}
.video-section {
width: 100%;
height: 420rpx;
.video-wrapper {
position: relative;
width: 100%;
height: 100%;
.main-video {
width: 100%;
height: 100%;
position: relative;
}
.fallback-poster {
z-index: 1;
}
.center-play-icon {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 80rpx;
height: 80rpx;
z-index: 99;
}
.custom-control-bar {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
height: 70rpx;
z-index: 99;
.bar-bg {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 70rpx;
z-index: 100;
}
.bar-content {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 70rpx;
z-index: 101;
display: flex;
flex-direction: row;
align-items: center;
padding: 0 10rpx;
box-sizing: border-box;
.ctrl-icon {
width: 25rpx;
height: 30rpx;
margin: 0 10rpx;
flex-shrink: 0;
}
.mute-icon {
width: 38rpx;
height: 30rpx;
flex-shrink: 0;
}
.fullscreen-icon {
width: 30rpx;
height: 30rpx;
flex-shrink: 0;
}
.time-text {
font-size: 22rpx;
color: #ffffff;
line-height: 70rpx;
}
.slider-track {
flex: 1;
height: 70rpx;
margin: 0 20rpx;
position: relative;
display: flex;
flex-direction: column;
justify-content: center;
.slider-bg {
position: absolute;
top: 33rpx;
left: 0;
width: 100%;
height: 4rpx;
background-color: rgba(255, 255, 255, 0.4);
}
.slider-active {
position: absolute;
top: 33rpx;
left: 0;
height: 4rpx;
background-color: #FF4767;
}
.slider-thumb {
position: absolute;
top: 25rpx;
margin-left: -10rpx;
width: 20rpx;
height: 20rpx;
border-radius: 50%;
background-color: #FF4767;
}
}
}
}
}
}
.article-header {
padding: 30rpx 30rpx 20rpx;
.title {
font-weight: 500;
font-size: 32rpx;
color: #333333;
line-height: 45rpx;
margin-bottom: 24rpx;
}
.meta-row {
display: flex;
justify-content: space-between;
align-items: center;
.author-info {
display: flex;
align-items: center;
.avatar {
width: 28rpx;
height: 28rpx;
border-radius: 50%;
margin-right: 12rpx;
}
.author-name {
font-weight: 400;
font-size: 24rpx;
color: #666666;
line-height: 33rpx;
margin-right: 16rpx;
}
.date {
font-weight: 400;
font-size: 24rpx;
color: #999999;
line-height: 33rpx;
}
}
.favorite-btn {
display: flex;
align-items: center;
font-weight: 400;
font-size: 24rpx;
color: #999999;
line-height: 33rpx;
.star-icon {
width: 26rpx;
height: 26rpx;
margin-right: 6rpx;
margin-top: -2rpx;
}
.active-fav {
color: #FD5A8C;
}
}
}
}
.article-content-wrapper {
.article-content {
padding: 0 30rpx 40rpx;
font-weight: 400;
font-size: 28rpx;
color: #2A2A2A;
line-height: 40rpx;
::v-deep p {
margin-bottom: 24rpx;
line-height: 40rpx;
}
::v-deep img {
max-width: 100%;
height: auto;
display: block;
border-radius: 10rpx;
margin: 20rpx 0;
}
}
.empty-content {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 50rpx 0 80rpx;
.empty-icon {
width: 140rpx;
height: 140rpx;
margin-bottom: 24rpx;
opacity: 0.8;
}
.empty-text {
font-size: 26rpx;
color: #A9A9A9;
}
}
}
.recommend-section {
padding: 0 30rpx;
.section-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 30rpx;
.section-title {
font-weight: 500;
font-size: 30rpx;
color: #333333;
line-height: 42rpx;
}
.refresh-btn {
display: flex;
align-items: center;
font-size: 26rpx;
color: #999999;
.refresh-icon {
width: 24rpx;
height: 28rpx;
margin-right: 8rpx;
transition: transform 0.5s ease;
&.is-rotating {
transform: rotate(360deg);
}
}
}
}
}
</style>

View File

@ -405,7 +405,7 @@
.login { .login {
width: 630rpx; width: 630rpx;
height: 96rpx; height: 96rpx;
background-color: #E8101E; background-color: #FF4767;
color: #fff; color: #fff;
font-size: 40rpx; font-size: 40rpx;
line-height: 96rpx; line-height: 96rpx;

View File

@ -18,7 +18,7 @@
</view> </view>
</view> </view>
</view> </view>
<uv-switch v-model="mainSwitch.switch" activeColor="#E8101E" @change="handleSwitchChange('total',mainSwitch, $event)"></uv-switch> <uv-switch v-model="mainSwitch.switch" activeColor="#FF4767" @change="handleSwitchChange('total',mainSwitch, $event)"></uv-switch>
</view> </view>
</view> </view>
<view class="settings-title" v-if="kindList.length"> <view class="settings-title" v-if="kindList.length">
@ -34,7 +34,7 @@
</view> </view>
<view class="card-tip">{{ item.text }}</view> <view class="card-tip">{{ item.text }}</view>
</view> </view>
<uv-switch v-model="item.switch" activeColor="#E8101E" @change="handleSwitchChange('branch',item, $event)"></uv-switch> <uv-switch v-model="item.switch" activeColor="#FF4767" @change="handleSwitchChange('branch',item, $event)"></uv-switch>
</view> </view>
</view> </view>
@ -267,7 +267,7 @@
} }
.color-red { .color-red {
color: #E8101E !important; color: #FF4767 !important;
} }
/* 弹窗样式 */ /* 弹窗样式 */
@ -324,7 +324,7 @@
.dialog-btn { .dialog-btn {
width: 476rpx; width: 476rpx;
height: 86rpx; height: 86rpx;
background: #E8101E; background: #FF4767;
border-radius: 44rpx; border-radius: 44rpx;
display: flex; display: flex;
align-items: center; align-items: center;

View File

@ -332,7 +332,7 @@
width: 16rpx; width: 16rpx;
height: 16rpx; height: 16rpx;
border-radius: 50%; border-radius: 50%;
background-color: #E8101E; background-color: #FF4767;
margin-left: 8rpx; margin-left: 8rpx;
} }

View File

@ -18,7 +18,7 @@
</view> </view>
</view> </view>
</view> </view>
<uv-switch v-model="mainSwitch.switch" activeColor="#E8101E" <uv-switch v-model="mainSwitch.switch" activeColor="#FF4767"
@change="handleSwitchChange('total',mainSwitch, $event)"></uv-switch> @change="handleSwitchChange('total',mainSwitch, $event)"></uv-switch>
</view> </view>
</view> </view>
@ -35,7 +35,7 @@
</view> </view>
<view class="card-tip">{{ item.text }}</view> <view class="card-tip">{{ item.text }}</view>
</view> </view>
<uv-switch v-model="item.switch" activeColor="#E8101E" <uv-switch v-model="item.switch" activeColor="#FF4767"
@change="handleSwitchChange('branch',item, $event)"></uv-switch> @change="handleSwitchChange('branch',item, $event)"></uv-switch>
</view> </view>
</view> </view>
@ -289,7 +289,7 @@
} }
.color-red { .color-red {
color: #E8101E !important; color: #FF4767 !important;
} }
/* 弹窗样式 */ /* 弹窗样式 */
@ -346,7 +346,7 @@
.dialog-btn { .dialog-btn {
width: 476rpx; width: 476rpx;
height: 86rpx; height: 86rpx;
background: #E8101E; background: #FF4767;
border-radius: 44rpx; border-radius: 44rpx;
display: flex; display: flex;
align-items: center; align-items: center;
@ -437,7 +437,7 @@
width: 300rpx; width: 300rpx;
height: 80rpx; height: 80rpx;
line-height: 80rpx; line-height: 80rpx;
background: #E8101E; background: #FF4767;
border-radius: 40rpx; border-radius: 40rpx;
margin: 0 auto; margin: 0 auto;
} }

View File

@ -29,7 +29,7 @@
</view> </view>
<view class="card-tip"> 开启语音提示避免落单</view> <view class="card-tip"> 开启语音提示避免落单</view>
</view> </view>
<uv-switch v-model="value" @change="changeVoice" activeColor="#E8101E"></uv-switch> <uv-switch v-model="value" @change="changeVoice" activeColor="#FF4767"></uv-switch>
</view> </view>
</view> </view>
@ -292,7 +292,7 @@
} }
.color-red { .color-red {
color: #E8101E !important; color: #FF4767 !important;
} }
// //
@ -348,7 +348,7 @@
.dialog-btn { .dialog-btn {
width: 400rpx; width: 400rpx;
height: 88rpx; height: 88rpx;
background: #E8101E; background: #FF4767;
border-radius: 44rpx; border-radius: 44rpx;
display: flex; display: flex;
align-items: center; align-items: center;

View File

@ -20,19 +20,25 @@
<!-- @chooseavatar="getAvatar" --> <!-- @chooseavatar="getAvatar" -->
</view> </view>
<view class="user-detail" @click="goToProfile"> <view class="user-detail">
<view class="nickname"> <view class="nickname">
<text class="nickname-text">{{ <text class="nickname-text">{{
userInfo.name || userInfo.nick_name || "" userInfo.name || userInfo.nick_name || ""
}}</text> }}</text>
</view> </view>
<view class="user_detail_tip"> <view class="user_detail_tip" @click="toruzhu">
<view class="user_detail_tip_phone" v-if="id_type !== 0"> <image
资料编辑 :src="(userInfo.credentials_state === 2 || (userInfo.id_type > 0 && userInfo.credentials_state === 0)) ? 'https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/13cd25db-5b52-4d36-bad2-ee8680eed65f.png' : 'https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/711e35a8-a7a1-4eb2-8a76-52ac9795fa7e.png'"
<image mode="aspectFill" mode="" style="width:30rpx;height:30rpx ;"></image>
src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/6a4b7bc9-174a-471a-9bf5-6ba167005960" /> <view class="user_detail_tip_phone" style="margin-left: -10rpx;">
{{ (userInfo.credentials_state === 2 || (userInfo.id_type > 0 &&
userInfo.credentials_state === 0)) ? '认证通过' : userInfo.credentials_state === 1 ?
'资质审核中' : '资质待认证' }}
</view> </view>
<view v-else class="user_detail_tip_phone" style="color: #999999">美融融小程序欢迎您</view> <image mode="widthFix"
src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/89f929a5-1486-481f-a696-af520a6bb0f2.png"
style="width:8rpx ;margin-left: -6rpx;" />
</view> </view>
</view> </view>
</view> </view>
@ -41,7 +47,7 @@
<image <image
src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/931c0992-5243-4c70-ab2b-b99b430661c8.png" src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/931c0992-5243-4c70-ab2b-b99b430661c8.png"
mode="aspectFill" class="wallet_content_img"></image> mode="aspectFill" class="wallet_content_img"></image>
<view class="wallet_content_text">钱包余额<text style="color: #e8101e">{{ userInfo.money }}</text> <view class="wallet_content_text">钱包余额<text style="color: #FF4767">{{ userInfo.money }}</text>
</view> </view>
</view> </view>
</view> </view>
@ -56,11 +62,11 @@
<view class="inviteMessage" v-if="inviteList.length > 0"> <view class="inviteMessage" v-if="inviteList.length > 0">
<view class="inviteMessage_content"> <view class="inviteMessage_content">
<image mode="widthFix" class="inviteMessage_img" <image mode="widthFix" class="inviteMessage_img"
src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/7f577210-2d63-4146-af09-bcaf3db85a49.png" /> src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/bb9d15ac-ece5-4481-ae30-62f76ace032f.png" />
<view class="inviteMessage_text">您有{{ inviteList.length }}条商家邀请</view> <view class="inviteMessage_text">您有{{ inviteList.length }}条商家邀请</view>
</view> </view>
<image @click="goToInviteList" mode="aspectFill" class="btn_img" <image @click="goToInviteList" mode="aspectFill" class="btn_img"
src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/f2483bec-bbe7-4f2c-a6fd-e40a0accae82.png" /> src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/defe90dd-3e35-4582-ad45-b36f68681bcc.png" />
</view> </view>
</view> </view>
<!-- 用户相关信息 --> <!-- 用户相关信息 -->
@ -80,7 +86,7 @@
<view class="order-card"> <view class="order-card">
<template v-for="card in currentCardList"> <template v-for="card in currentCardList">
<view class="function-list" v-if="card.type == 'line'"> <view class="function-list" v-if="card.type == 'line'" :key="card.title">
<view class="function-title">{{ card.title }}</view> <view class="function-title">{{ card.title }}</view>
<view class="function-grid"> <view class="function-grid">
<view class="grid-item" v-for="(item, index) in card.list" :key="index" <view class="grid-item" v-for="(item, index) in card.list" :key="index"
@ -92,33 +98,109 @@
</view> </view>
</view> </view>
</view> </view>
<view class="function-list" style="padding: 24rpx; padding-bottom: 28rpx" <view class="function-list" style="padding: 24rpx; padding-bottom: 28rpx" v-if="card.type == 'lineCard'"
v-if="card.type == 'lineCard'"> :key="card.title">
<view class="lineCard-title">{{ card.title }}</view> <view class="lineCard-title">{{ card.title }}</view>
<view class="lineCard-grid"> <view class="lineCard-grid">
<image v-for="(item, index) in card.list" :src="item.url" mode="widthFix" <image v-for="(item, index) in card.list" :src="item.url" mode="widthFix"
@click="handleFunction(item)"></image> @click="handleFunction(item)" :key="index"></image>
</view> </view>
</view> </view>
<view class="imagePure" v-if="card.type == 'imagePure'"> <view class="imagePure" v-if="card.type == 'imagePure'" :key="card.title">
<image @click="handleFunction(card)" :src="card.url" mode="widthFix"></image> <image @click="handleFunction(card)" :src="card.url" mode="widthFix"></image>
</view> </view>
<view class="image-list" v-if="card.type == 'image'"> <view class="image-list" v-if="card.type == 'image'" :key="card.title">
<view class="image-title">{{ card.title }}</view> <view class="image-title">{{ card.title }}</view>
<image @click="handleFunction(card)" :src="card.url" mode="widthFix"></image> <image @click="handleFunction(card)" :src="card.url" mode="widthFix"></image>
</view> </view>
<view class="imageText-list" v-if="card.type == 'imageText'"> <view class="listcard-list" v-if="card.type == 'listcard'" :key="card.title">
<view class="imageText-title">{{ card.title }}</view> <view class="function-title">{{ card.title }}</view>
<view class="listcard-item" v-for="(item, index) in card.list" :key="index">
<image @click="handleFunction(item)" :src="item.url" mode="widthFix"></image>
<view class="listcard-title">{{ item.title }}</view>
<view class="listcard-text">{{ item.text }}</view>
</view>
</view>
<view class="imageText-list" v-if="card.type == 'imageText'" :key="card.title">
<view class="lineCard-title">{{ card.title }}</view>
<view class="imageText-content"> <view class="imageText-content">
<image :src="card.url" mode="widthFix"></image> <image :src="card.url" mode="widthFix"></image>
<view class="text-status">入驻成功啦</view> <view class="text-status">入驻成功啦</view>
<view class="text-next">下一步:等待<text style="color: #e8101e">专属门店商家邀约绑定</text>解锁订单资源与服</view> <view class="text-next">下一步:等待<text style="color: #FF4767">专属门店商家邀约绑定</text>解锁订单资源与服</view>
<view class="text-next">务通道开启高效变现共创共赢的新旅程</view> <view class="text-next">务通道开启高效变现共创共赢的新旅程</view>
</view> </view>
</view> </view>
</template> </template>
</view> </view>
<view class="setup-modal-mask" v-if="showSetupModal" catchtouchmove="true">
<view class="setup-modal-content">
<image class="modal-bg"
src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/ac2cb4aa-a7c5-4776-98f4-b77e9c0cfa85.png">
</image>
<view class="modal-header">
<text>温馨提示</text>
</view>
<view class="modal-body">
<text class="modal-subtitle">发布服务请完善以下资料</text>
<view class="missing-list">
<view class="missing-item" v-if="!hasBusinessTime">
<view class="item-left">
<image class="item-icon"
src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/21b26b44-5e36-4291-8900-705a3d5bfa90.png">
</image>
<view class="item-texts">
<text class="item-title">营业时间未配置</text>
<text class="item-desc">请完善店铺的营业时间</text>
</view>
</view>
<view class="item-right orange" @tap="goToBusinessTime">去配置</view>
</view>
<view class="divider-line"></view>
<view class="missing-item" v-if="!hasServiceSkill">
<view class="item-left">
<image class="item-icon"
src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/21b26b44-5e36-4291-8900-705a3d5bfa90.png">
</image>
<view class="item-texts">
<text class="item-title">服务技能未配置</text>
<text class="item-desc">请完善服务技能</text>
</view>
</view>
<view class="item-right orange" @tap="goToServiceSkill">去配置</view>
</view>
<view class="divider-line"></view>
<view class="missing-item" v-if="!isCertified">
<view class="item-left">
<image class="item-icon"
:src="isUnderReview ? 'https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/25c444be-a66e-45d6-b50d-922149ff059f.png' : 'https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/21b26b44-5e36-4291-8900-705a3d5bfa90.png'">
</image>
<view class="item-texts">
<text class="item-title" :class="{ 'blue-text': isUnderReview }">{{ isUnderReview ?
'资质认证中' : '资质未认证' }}</text>
<text class="item-desc">请完成资质认证</text>
</view>
</view>
<view class="item-right" :class="isUnderReview ? 'grey' : 'light-green'" @tap="goToAuth">
{{ isUnderReview ? '查看进度' : '去认证' }}
</view>
</view>
</view>
</view>
<view class="modal-footer">
<view class="btn-know" @tap="closeSetupModal">知道了</view>
</view>
</view>
</view>
<tipsPopup2 :show="tipShow" @closePopup="closePopup" sureText="确认" @okBtn="okBtn"> <tipsPopup2 :show="tipShow" @closePopup="closePopup" sureText="确认" @okBtn="okBtn">
{{ tipsText }} {{ tipsText }}
</tipsPopup2> </tipsPopup2>
@ -155,16 +237,30 @@
list: [{ list: [{
title: "员工管理", title: "员工管理",
url: "https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/a9c13cce-f3e1-4ac1-9881-d39dc2b813ff.png", url: "https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/9d847e84-e4ca-44c0-b9fb-e33803a67457.png",
path: "/pages/shop/staff/manage", path: "/pages/shop/staff/manage",
go_id_type: 1, go_id_type: 1,
}, },
{ {
title: "服务分配", title: "服务分配",
url: "https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/673f9885-3be1-4769-b417-b675b8ac5099.png", url: "https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/0d27ea76-2a81-4374-8033-5eef76598f9c.png",
path: "/pages/shop/staff/distribution-service", path: "/pages/shop/staff/distribution-service",
go_id_type: 1, go_id_type: 1,
}, },
{
title: "店铺装修",
url: "https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/4b558456-2e38-4185-8713-d1f0e6645820.png",
path: "/pages/artisan/profile",
go_id_type: 1,
directAccess: true,
},
{
title: "财务管理",
url: "https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/edafae37-8258-4e1c-9dcc-019484117047.png",
path: "/pages/wallet/wallet",
go_id_type: 1,
directAccess: true,
},
], ],
}, },
{ {
@ -175,25 +271,25 @@
title: "服务管理", title: "服务管理",
path: "/pages/artisan/service-list", path: "/pages/artisan/service-list",
go_id_type: 1, go_id_type: 1,
url: "https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/c4a8df11-b4c0-46e3-a72e-7bbb20bbbd6a.png", url: "https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/0076bdee-f1c6-412d-9f05-187189a855a6.png",
}, },
{ {
title: "工位管理", title: "工位管理",
path: "/pages/shop/workSpace/list", path: "/pages/shop/workSpace/list",
go_id_type: 1, go_id_type: 1,
url: "https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/d4c59f74-34a5-4e0f-b3be-766342e4d6e9.png", url: "https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/6568df0b-e646-4593-804b-a21ed0b35ede.png",
}, },
{ {
title: "购买服务", title: "购买服务",
path: "/pages/shop/buy-service", path: "/pages/shop/buy-service",
go_id_type: 1, go_id_type: 1,
url: "https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/285172ae-9757-472f-b466-73d5cc78d82a.png", url: "https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/6c9aa5ea-63aa-4a86-8858-cb58d303114f.png",
}, },
{ {
title: "购买工时", title: "购买工时",
path: "/pages/shop/manHour/buyManHour", path: "/pages/shop/manHour/buyManHour",
go_id_type: 1, go_id_type: 1,
url: "https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/9a13b1d0-3099-4e52-8d43-549f2520c1ca.png", url: "https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/c40cddcb-6a43-4355-b25d-ab3e53e17982.png",
}, },
], ],
}, },
@ -205,25 +301,25 @@
title: "用户订单", title: "用户订单",
path: "/pages/shop/userorders", path: "/pages/shop/userorders",
go_id_type: 1, go_id_type: 1,
url: "https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/1ca76fe3-21fc-408d-a453-4b253e377e46.png", url: "https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/b94e033c-836b-404c-85e9-9a7ba7680919.png",
}, },
{ {
title: "工位订单", title: "工位订单",
path: "/pages/shop/workSpace/saleList", path: "/pages/shop/workSpace/saleList",
go_id_type: 1, go_id_type: 1,
url: "https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/6ebd42c1-09a4-4ed1-8b82-de6db52f6cda.png", url: "https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/b5ede46f-71f9-4718-87a8-3aa4ba99c490.png",
}, },
{ {
title: "服务订单", title: "服务订单",
path: "/pages/shop/buy-order", path: "/pages/shop/buy-order",
go_id_type: 1, go_id_type: 1,
url: "https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/65c5d29b-9aa6-4dd0-b766-baa484d1e5fe.png", url: "https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/673f1dac-1693-4f0a-aec4-c196aa72382b.png",
}, },
{ {
title: "工时订单", title: "购买工时",
path: "/pages/shop/manHour/saleList", path: "/pages/shop/manHour/saleList",
go_id_type: 1, go_id_type: 1,
url: "https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/f4b1628d-9d2e-4de0-90a8-bd2c83dad2af.png", url: "https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/742bd9c9-0f38-4c10-b0fb-9b1ecebfc18c.png",
}, },
], ],
}, },
@ -235,13 +331,13 @@
title: "拼团管理", title: "拼团管理",
path: "/pages/shop/groupBuying/list", path: "/pages/shop/groupBuying/list",
go_id_type: 1, go_id_type: 1,
url: "https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/9a93bf6a-4387-460e-afb5-80441e4e7310.png", url: "https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/569c2ba5-2f39-4a3f-b36d-026c480d8203.png",
}, },
{ {
title: "日常推广", title: "日常推广",
path: "/pages/promotion/promotion", path: "/pages/promotion/promotion",
go_id_type: 1, go_id_type: 1,
url: "https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/b7419b23-2241-4b32-98f2-603bb479bcc1.png", url: "https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/90d92ff7-4110-4ebd-8207-e6370699a1b6.png",
}, },
], ],
}, },
@ -252,12 +348,12 @@
self_state: true, self_state: true,
list: [{ list: [{
text: "自营服务", text: "自营服务",
url: "https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/b0faf058-e824-4d8b-a4fa-17d3e90b04ec.png", url: "https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/fa0c9545-91f4-4a73-b5fe-fa1217aa768e.png",
path: "/pages/selfOperated/list", path: "/pages/selfOperated/list",
}, },
{ {
text: "自营订单", text: "自营订单",
url: "https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/b1dc0fc5-13be-4e21-8942-929edd42195b.png", url: "https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/dfeff761-7448-4f31-a4e9-ee12b088d6a8.png",
path: "/pages/shop/userorders?serviceType=2", path: "/pages/shop/userorders?serviceType=2",
}, },
], ],
@ -267,23 +363,26 @@
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",
}, },
{ {
type: "line", type: "listcard",
title: "我的服务", title: "我的服务",
list: [{ list: [{
text: "联系平台", text: "我的收藏",
icon: "https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/930a458a-9d2a-4543-a39c-399bb5bb5290.png", url: "https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/83fa7f51-dda3-494b-a50e-f15f8fdcdb9c.png",
path: "/pages/contact/contact", path: "/pages/my/myFavorite",
}, },
{ {
text: "设置", text: "设置",
icon: "https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/0e0676c1-aa2b-4b3f-b9d5-c020c566cc85.png", url: "https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/d1173680-386b-4db3-a74c-64108da6cec9.png",
path: "", path: "/pages/settings/index",
type: "setting", },
isNeedLogin: true, {
text: "联系客服",
url: "https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/5bbac7f8-940a-414a-be0b-e6faf5215f63.png",
path: "/pages/contact/contact",
}, },
], ],
}, },
@ -296,6 +395,8 @@
inviteList: [], inviteList: [],
// //
stopUseModal: false, stopUseModal: false,
showSetupModal: false,
authDetails: null,
}; };
}, },
onPageScroll(e) { onPageScroll(e) {
@ -314,6 +415,37 @@
return this.userInfo?.is_ok === 2; return this.userInfo?.is_ok === 2;
}, },
// (> 0 )
isCertified() {
if (!this.isLogin || typeof this.userInfo.id_type === 'undefined') return false;
return this.userInfo.id_type > 0;
},
//
isSettled() {
if (!this.isLogin || typeof this.userInfo.id_type === 'undefined') return false;
return this.userInfo.id_type !== 0;
},
//
isUnderReview() {
if (!this.isLogin) return false;
if (this.authDetails && Object.keys(this.authDetails).length > 0) {
return true;
}
return false;
},
//
hasServiceSkill() {
const fromUser = this.userInfo && Array.isArray(this.userInfo.servers_kill) && this.userInfo.servers_kill.length > 0;
const fromAuth = this.authDetails && Array.isArray(this.authDetails.servers_kill) && this.authDetails.servers_kill.length > 0;
return this.isLogin && (fromUser || fromAuth);
},
//
hasBusinessTime() {
const timeFromUser = this.userInfo && this.userInfo.business_time;
const timeFromAuth = this.authDetails && this.authDetails.business_time;
return this.isLogin && !!(timeFromUser || timeFromAuth);
},
currentCardList() { currentCardList() {
return this.cardList return this.cardList
.filter((card) => this.checkShow(card)) .filter((card) => this.checkShow(card))
@ -629,9 +761,78 @@
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 &&
result.data.servers_kill_arr &&
result.data.servers_kill_arr.length > 0 &&
isCertified;
const mgmtCard = this.cardList.find(c => c.title === "管理中心");
if (mgmtCard) {
const shopItem = mgmtCard.list.find(i => i.title === "店铺装修");
if (shopItem) {
shopItem.url = allReady ?
"https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/e6e72039-eec4-414c-8a86-aad404602962.png" :
"https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/4b558456-2e38-4185-8713-d1f0e6645820.png";
}
}
//
if (this.isSettled) {
this.fetchAuthDetails();
}
}); });
this.getInviteList(); this.getInviteList();
}, },
//
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;
});
},
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) {
@ -676,27 +877,27 @@
}); });
}, },
async handleFunction(item) { async handleFunction(item) {
// 退 // 1.
if (this.isLogin && item.type === "setting") {
uni.navigateTo({
url: `/pages/settings/index`,
});
return;
}
// 访
if (!this.checkAccess(item)) { if (!this.checkAccess(item)) {
return; return;
} }
// if (!this.isLogin) { // 2.
// uni.showToast({ if (!this.isLogin) {
// title: "使", if (item.path == "/pages/ruzhu/ruzhu") {
// icon: "none", uni.navigateTo({
// }); url: "/pages/blogPopup/blogPopup",
// return; });
// } return;
}
uni.showToast({
title: `您暂未登录,无法使用${item.title || item.text || ''}`,
icon: "none",
});
return;
}
// 3.
if (item.path == "/pages/ruzhu/ruzhu") { if (item.path == "/pages/ruzhu/ruzhu") {
request.post("/sj/userSjAuth/details", { request.post("/sj/userSjAuth/details", {
type: 1 type: 1
@ -711,32 +912,47 @@
}); });
} }
}); });
return; return;
} }
// 4. (go_id_type == 1)
if (item.go_id_type == 1) {
// 4a.
if (!this.isSettled) {
uni.showToast({
title: `您暂未入驻,无法使用${item.title || item.text || ''}`,
icon: "none",
});
return;
}
// 4b.
if (item.directAccess) {
uni.navigateTo({ url: item.path });
return;
}
// 4c.
if (!this.isCertified || !this.hasBusinessTime || !this.hasServiceSkill) {
this.showSetupModal = true;
return;
}
// 4d.
uni.navigateTo({ url: item.path });
return;
}
// 5. type
if (item.type) { if (item.type) {
uni.navigateTo({ uni.navigateTo({
url: `${item.path}?type=${item.type}`, url: `${item.path}?type=${item.type}`,
}); });
} else {
if (item.go_id_type == 1 && this.userInfo?.id_type == 0) {
uni.showToast({
title: `您暂未入驻,无法使用${ item.title }`,
icon: "none",
});
return; return;
} }
if(!this.isLogin && item.go_id_type){
uni.showToast({ // 6.
title: `您暂未登录,无法使用${ item.title }`, uni.navigateTo({ url: item.path });
icon: "none",
});
return;
}
uni.navigateTo({
url: `${item.path}`,
});
}
}, },
goToProfile() { goToProfile() {
// 访 // 访
@ -751,6 +967,28 @@
url: "/pages/artisan/profile", url: "/pages/artisan/profile",
}); });
}, },
toruzhu() {
this.navigateToCertificationProcess();
},
closeSetupModal() {
this.showSetupModal = false;
},
goToBusinessTime() {
this.showSetupModal = false;
uni.navigateTo({
url: '/pages/shop/business-time'
});
},
goToServiceSkill() {
this.showSetupModal = false;
uni.navigateTo({
url: '/pages/shop/service-skills'
});
},
goToAuth() {
this.showSetupModal = false;
this.navigateToCertificationProcess();
},
goToInviteList() { goToInviteList() {
// 访 // 访
if (this.isAccountDisabled) { if (this.isAccountDisabled) {
@ -811,7 +1049,7 @@
position: relative; position: relative;
padding-bottom: 50rpx; padding-bottom: 50rpx;
padding-top: var(--status-bar-height); padding-top: var(--status-bar-height);
background-image: url("https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/825812de-54b3-486a-a3a0-2c4a1fb9fd28.png"); background-image: url("https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/8c7c4d24-9a21-4d21-b1ed-1aa985d188e6.png");
background-position: 0 0; background-position: 0 0;
background-size: 100%; background-size: 100%;
background-repeat: no-repeat; background-repeat: no-repeat;
@ -885,9 +1123,9 @@
align-items: center; align-items: center;
.avatar { .avatar {
width: 124rpx; width: 110rpx;
height: 124rpx; height: 110rpx;
border: 4rpx solid #fff; border: 2rpx solid #fff;
box-sizing: border-box; box-sizing: border-box;
border-radius: 64rpx; border-radius: 64rpx;
margin-right: 20rpx; margin-right: 20rpx;
@ -895,8 +1133,8 @@
position: relative; position: relative;
.avatar-img { .avatar-img {
width: 116rpx; width: 110rpx;
height: 116rpx; height: 110rpx;
border-radius: 64rpx; border-radius: 64rpx;
margin-right: 20rpx; margin-right: 20rpx;
} }
@ -916,7 +1154,7 @@
.nickname { .nickname {
font-weight: 500; font-weight: 500;
font-size: 32rpx; font-size: 34rpx;
color: #333333; color: #333333;
line-height: 45rpx; line-height: 45rpx;
text-align: left; text-align: left;
@ -958,7 +1196,7 @@
.user-identity { .user-identity {
margin-top: 10rpx; margin-top: 10rpx;
border: 1rpx solid #e8101e; border: 1rpx solid #FF4767;
border-radius: 22rpx; border-radius: 22rpx;
width: 112rpx; width: 112rpx;
height: 44rpx; height: 44rpx;
@ -968,7 +1206,7 @@
.identity-text { .identity-text {
font-size: 20rpx; font-size: 20rpx;
color: #e8101e; color: #FF4767;
font-weight: 400; font-weight: 400;
} }
} }
@ -1240,6 +1478,58 @@
} }
/* 功能列表 */ /* 功能列表 */
.listcard-list {
position: relative;
z-index: 99;
margin: 0 30rpx;
background: #ffffff;
border-radius: 24rpx;
padding: 30rpx 20rpx;
display: flex;
flex-wrap: wrap;
justify-content: space-between;
.function-title {
width: 100%;
font-weight: 500;
font-size: 32rpx;
color: #252525;
line-height: 36rpx;
text-align: left;
font-style: normal;
margin-bottom: 20rpx;
}
.listcard-item {
width: 33.33%;
padding: 20rpx;
box-sizing: border-box;
image {
width: 50rpx;
height: 50rpx;
margin: 0 auto 10rpx;
display: block;
}
.listcard-title {
font-weight: 500;
font-size: 28rpx;
color: #252525;
line-height: 32rpx;
text-align: center;
margin-bottom: 8rpx;
}
.listcard-text {
font-size: 24rpx;
color: #999999;
line-height: 28rpx;
text-align: center;
}
}
}
.image-list { .image-list {
background: #ffffff; background: #ffffff;
border-radius: 24rpx; border-radius: 24rpx;
@ -1415,23 +1705,23 @@
align-items: center; align-items: center;
gap: 12rpx; gap: 12rpx;
margin-top: 10rpx; margin-top: 10rpx;
width: auto;
height: 46rpx;
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%;
background-repeat: no-repeat;
margin-left: -6rpx;
.user_detail_tip_phone { .user_detail_tip_phone {
max-width: 230rpx; // width: 100rpx;
height: 36rpx; height: 28rpx;
line-height: 36rpx; font-family: PingFangSC, PingFang SC;
border-radius: 6rpx; font-weight: 400;
font-size: 24rpx; font-size: 24rpx;
color: #666666; color: #6A574E;
box-sizing: border-box; line-height: 30rpx;
display: flex; font-style: normal;
align-items: center;
gap: 7rpx;
image {
width: 8rpx;
height: 14rpx;
}
} }
.user_detail_tip_invite_name { .user_detail_tip_invite_name {
@ -1448,4 +1738,158 @@
width: 100%; width: 100%;
} }
} }
/* ============ 提示弹窗样式 ============ */
.setup-modal-mask {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.5);
z-index: 9999;
display: flex;
align-items: center;
justify-content: center;
.setup-modal-content {
width: 630rpx;
height: 775rpx;
background: #FFFFFF;
border-radius: 32rpx;
position: relative;
display: flex;
flex-direction: column;
.modal-bg {
position: absolute;
top: 0;
left: 0;
width: 630rpx;
height: 265rpx;
z-index: 0;
}
.modal-header {
position: relative;
z-index: 1;
height: 100rpx;
display: flex;
align-items: flex-end;
justify-content: center;
padding-bottom: 20rpx;
text {
font-size: 36rpx;
font-weight: bold;
color: #333333;
letter-spacing: 2rpx;
}
}
.modal-body {
position: relative;
z-index: 1;
flex: 1;
padding: 24rpx 40rpx;
.modal-subtitle {
font-size: 28rpx;
color: #333333;
margin-bottom: 40rpx;
display: block;
}
.missing-list {
display: flex;
flex-direction: column;
gap: 46rpx;
.missing-item {
display: flex;
justify-content: space-between;
align-items: center;
.item-left {
display: flex;
align-items: flex-start;
.item-icon {
width: 32rpx;
height: 32rpx;
margin-right: 16rpx;
flex-shrink: 0;
margin-top: 6rpx;
}
.item-texts {
display: flex;
flex-direction: column;
.item-title {
font-size: 30rpx;
color: #333333;
font-weight: 500;
margin-bottom: 8rpx;
&.blue-text {
color: #2b85e4;
}
}
.item-desc {
font-size: 24rpx;
color: #999999;
}
}
}
.item-right {
font-size: 26rpx;
font-weight: 400;
margin-top: -45rpx;
&.orange {
color: #FF7B00;
}
&.grey {
color: #999999;
}
&.light-green {
color: #5CAC81;
}
}
}
.divider-line {
width: 100%;
height: 1rpx;
background-color: #f2f2f2;
margin: -26rpx 0;
}
}
}
.modal-footer {
position: relative;
z-index: 1;
padding: 0 50rpx 50rpx;
.btn-know {
width: 100%;
height: 88rpx;
background: #FF4767;
border-radius: 44rpx;
color: #FFFFFF;
font-size: 32rpx;
font-weight: 500;
display: flex;
align-items: center;
justify-content: center;
}
}
}
}
</style> </style>

670
pages/my/myFavorite.vue Normal file
View File

@ -0,0 +1,670 @@
<template>
<view class="collection-page">
<custom-navbar title="我的收藏" :showBack="true" backgroundColor="#FFFFFF" :show-headle="true" borderBottom="none"
headleSrc="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/b18bac2f-3e4c-4586-9d45-0f088629c9d1.png"
@onHeadleClick="goToSearch" class="serch-tap">
</custom-navbar>
<view class="tab-bar-wrap" :style="{ top: navHeight + 'px' }">
<view class="tab-bar">
<view class="tab-items">
<view class="tab-item" :class="{ active: currentTab === 'brand' }" @tap="switchTab('brand')">
收藏的品牌
</view>
<view class="tab-item" :class="{ active: currentTab === 'course' }" @tap="switchTab('course')">
收藏的课程
</view>
</view>
</view>
</view>
<view class="filter-panel" :class="{ 'show': filterVisible }" :style="{ top: filterTop + 'px' }"
catchtouchmove="true">
<view class="filter-mask" @tap="closeFilterPanel"></view>
<view class="filter-container">
<scroll-view scroll-y class="filter-scroll" v-if="currentTab === 'brand'">
<view class="filter-group" v-for="group in brandFilterData" :key="group.id">
<view class="group-title">{{ group.title }}</view>
<view class="pill-list">
<view class="pill-item" v-for="sub in group.children" :key="sub.id"
:class="{ active: selectedSecondIds.includes(sub.id) }" @tap="toggleSecondSelect(sub.id)">
{{ sub.title }}
</view>
</view>
</view>
</scroll-view>
<view v-else class="course-filter">
<view class="course-type-item" :class="{ active: selectedCourseType === 'platform' }"
@tap="selectCourseType('platform')">
平台课程
</view>
<view class="course-type-item" :class="{ active: selectedCourseType === 'brand' }"
@tap="selectCourseType('brand')">
品牌课程
</view>
</view>
<view class="filter-footer">
<view class="reset-btn" @tap="resetFilter">重置</view>
<view class="confirm-btn" @tap="applyFilterAndClose">确定</view>
</view>
</view>
</view>
<view class="collection-content" v-if="currentTab === 'brand'">
<view class="brand-grid" v-if="filteredBrandList.length > 0">
<brand-card class="brand-card-wrap" v-for="(item, index) in filteredBrandList" :key="index" :item="item"
:tagKeys="item.tagKeys" @click="goToBrandDetail(item)"></brand-card>
</view>
<view class="empty-state" v-else>
<image class="empty-icon"
src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/da814ede-1adc-4f90-8cdf-5357a12fab27.png">
</image>
</view>
</view>
<view class="collection-content" v-else>
<view class="course-list" v-if="filteredCourseList.length > 0">
<skill-card v-for="(item, index) in filteredCourseList" :key="index" :item="item"></skill-card>
</view>
<view class="empty-state" v-else>
<image class="empty-icon"
src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/da814ede-1adc-4f90-8cdf-5357a12fab27.png">
</image>
</view>
</view>
<view style="height: 120rpx;"></view>
</view>
</template>
<script>
import BrandCard from "@/pages/home/components/brand-card.vue"
import SkillCard from "@/pages/home/components/skill-card.vue"
import request from "@/utils/request"
// true=false=使
const USE_REAL_API = true
export default {
components: {
BrandCard,
SkillCard
},
data() {
return {
navHeight: 0, //
filterTop: 0, //
currentTab: 'brand',
//
filterVisible: false,
// ()
brandFilterData: [],
selectedSecondIds: [], // ID
//
selectedCourseType: '', // 'platform' 'brand'
//
rawBrandList: [],
rawCourseList: [],
//
filteredBrandList: [],
filteredCourseList: []
}
},
computed: {
filterIcon() {
return this.filterVisible
? 'https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/e00ab2ac-bccf-42d8-820c-65727327e279.png'
: 'https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/bfe7a104-bef8-4432-9487-42f05e3e9035.png'
}
},
onLoad() {
// Tab
const sysInfo = uni.getSystemInfoSync()
const sbh = sysInfo.statusBarHeight || 0
this.navHeight = sbh
// Tab 106rpx px
this.filterTop = this.navHeight + uni.upx2px(106)
this.loadFilterCategories()
this.loadData()
},
methods: {
//
goToSearch() {
// this.currentTab 'brand' 'course'
uni.navigateTo({
url: `/pages/search_common/search?type=collection_${this.currentTab}`
});
},
goBack() {
uni.navigateBack()
},
addAddress() {
//
},
switchTab(tab) {
if (this.currentTab === tab) return
this.currentTab = tab
// tab
if (tab === 'brand') {
this.resetBrandFilter()
} else {
this.resetCourseFilter()
}
this.loadData()
this.closeFilterPanel()
},
//
toggleFilterPanel() {
this.filterVisible = !this.filterVisible
},
closeFilterPanel() {
this.filterVisible = false
},
// state === 1
async loadFilterCategories() {
try {
const res = await request.post('/sj/firstclass', {})
if ((res.code === 200 || res.state === 1) && res.data) {
const firstClasses = res.data;
//
const promises = firstClasses.map(async (first) => {
try {
const subRes = await request.post('/sj/secondclass', { id: first.id })
return {
id: first.id,
title: first.title,
children: ((subRes.code === 200 || subRes.state === 1) && subRes.data) ? subRes.data : []
}
} catch (e) {
return { id: first.id, title: first.title, children: [] }
}
});
const filterData = await Promise.all(promises);
//
this.brandFilterData = filterData.filter(group => group.children.length > 0);
} else {
this.brandFilterData = []
}
} catch (error) {
console.error('获取分类字典失败', error)
}
},
toggleSecondSelect(secId) {
const index = this.selectedSecondIds.indexOf(secId)
if (index === -1) {
this.selectedSecondIds.push(secId)
} else {
this.selectedSecondIds.splice(index, 1)
}
},
//
selectCourseType(type) {
//
if (this.selectedCourseType === type) {
this.selectedCourseType = ''
} else {
this.selectedCourseType = type
}
},
//
resetBrandFilter() {
this.selectedSecondIds = []
this.applyBrandFilter()
},
resetCourseFilter() {
this.selectedCourseType = ''
this.applyCourseFilter()
},
resetFilter() {
if (this.currentTab === 'brand') {
this.resetBrandFilter()
} else {
this.resetCourseFilter()
}
},
applyFilterAndClose() {
if (this.currentTab === 'brand') {
this.applyBrandFilter()
} else {
this.applyCourseFilter()
}
this.closeFilterPanel()
},
// ID
applyBrandFilter() {
if (!this.rawBrandList.length) {
this.filteredBrandList = []
return
}
if (this.selectedSecondIds.length === 0) {
this.filteredBrandList = [...this.rawBrandList]
} else {
this.filteredBrandList = this.rawBrandList.filter(brand => {
return brand.secondClassIds && brand.secondClassIds.some(id => this.selectedSecondIds.includes(id))
})
}
},
//
applyCourseFilter() {
if (!this.rawCourseList.length) {
this.filteredCourseList = []
return
}
if (!this.selectedCourseType) {
this.filteredCourseList = [...this.rawCourseList]
} else {
this.filteredCourseList = this.rawCourseList.filter(course => {
if (this.selectedCourseType === 'platform') return course.type === '平台课程'
if (this.selectedCourseType === 'brand') return course.type === '品牌课程'
return true
})
}
},
// Tab
loadData() {
if (this.currentTab === 'brand') {
this.loadBrandList()
} else {
this.loadCourseList()
}
},
async loadBrandList() {
if (USE_REAL_API) {
await this.fetchRealBrandList()
} else {
this.mockBrandList()
}
this.applyBrandFilter()
},
async loadCourseList() {
if (USE_REAL_API) {
await this.fetchRealCourseList()
} else {
this.mockCourseList()
}
this.applyCourseFilter()
},
// ============ ============
async fetchRealBrandList() {
try {
// 1.
const res = await request.post('/sj/brand/collectList', { page: 1, limit: 100 })
if ((res.code === 200 || res.state === 1) && res.data && res.data.list) {
// 2. filter(item => item.collect_state === 1)
this.rawBrandList = res.data.list.map(item => {
let tags = []
if (item.franchise_state == 1) tags.push('franchise')
if (item.student_state == 1) tags.push('recruit')
if (tags.length === 0) tags.push('more')
return {
id: item.id,
name: item.name,
bgSrc: item.cover_img || 'https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/default.jpg',
avatar: item.logo_img || 'https://dummyimage.com/100x100/ccc/fff.png&text=Avatar',
tagKeys: tags,
// 3. split
secondClassIds: item.second_class_ids ? String(item.second_class_ids).split(',').map(Number) : []
}
})
console.log('成功获取品牌收藏列表:', this.rawBrandList)
} else {
this.rawBrandList = []
}
} catch (error) {
console.error('获取品牌收藏失败详情:', error)
}
},
async fetchRealCourseList() {
try {
// 1.
const res = await request.post('/sj/skill/collectList', { page: 1, limit: 100 })
if ((res.code === 200 || res.state === 1) && res.data && res.data.list) {
// 2. filter map
this.rawCourseList = res.data.list.map(item => {
return {
id: item.id,
title: item.name,
coverSrc: item.cover_img,
type: item.link_name || (item.link_type == 1 ? '平台课程' : '品牌课程'),
link_type: item.link_type,
views: item.browse_num || 0,
// 3. 使
time: item.create_time ? this.formatTimeAgo(item.create_time) : '',
typeIcon: item.link_logo || ''
}
})
console.log('成功获取课程收藏列表:', this.rawCourseList)
} else {
this.rawCourseList = []
}
} catch (error) {
console.error('获取课程收藏失败', error)
}
},
formatTimeAgo(timeStr) {
if (!timeStr) return '';
const timeStrSafe = String(timeStr);
const now = new Date()
const time = new Date(timeStrSafe.replace(/-/g, '/'))
const diff = Math.floor((now - time) / 1000)
if (diff < 3600) return Math.floor(diff / 60) + '分钟前'
if (diff < 86400) return Math.floor(diff / 3600) + '小时前'
if (diff < 604800) return Math.floor(diff / 86400) + '天前'
return timeStrSafe.split(' ')[0]
},
goToBrandDetail(item) {
if (item.id) {
uni.navigateTo({ url: `/pages/brand/detail?id=${item.id}` })
}
},
// ============ ============
mockBrandList() {
this.rawBrandList = [
{
id: 1, name: '脸缘品牌', bgSrc: 'https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/e2220528-fdf6-4cad-a25d-ec6cbee1501e.jpg',
avatar: 'https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/e2220528-fdf6-4cad-a25d-ec6cbee1501e.jpg',
tagKeys: ['franchise', 'recruit'], secondClassIds: [76, 77]
},
{
id: 2, name: '美肌工坊', bgSrc: 'https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/e2220528-fdf6-4cad-a25d-ec6cbee1501e.jpg',
avatar: 'https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/e2220528-fdf6-4cad-a25d-ec6cbee1501e.jpg',
tagKeys: ['franchise'], secondClassIds: [78]
},
{
id: 3, name: '悦容堂', bgSrc: 'https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/e2220528-fdf6-4cad-a25d-ec6cbee1501e.jpg',
avatar: 'https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/e2220528-fdf6-4cad-a25d-ec6cbee1501e.jpg',
tagKeys: ['recruit'], secondClassIds: [201, 202]
}
]
},
mockCourseList() {
this.rawCourseList = [
{ id: 1, title: '穿戴甲的操作视频扫码验券操作教程', coverSrc: 'https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/e2220528-fdf6-4cad-a25d-ec6cbee1501e.jpg', type: '平台课程', views: 836000, time: '7小时前' },
{ id: 2, title: '全身SPA的操作视频操作教程', coverSrc: 'https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/e2220528-fdf6-4cad-a25d-ec6cbee1501e.jpg', type: '平台课程', views: 2344, time: '3天前' },
{ id: 3, title: '高级面部护理手法详解', coverSrc: 'https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/e2220528-fdf6-4cad-a25d-ec6cbee1501e.jpg', type: '品牌课程', views: 56700, time: '1周前' }
]
}
}
}
</script>
<style lang="scss" scoped>
.collection-page {
min-height: 100vh;
background: #fff;
}
/* 将页面左右 padding 转移到内容区,保证 Tab 背景贯穿全屏 */
.tab-bar-wrap {
position: sticky;
/* 吸顶,保证滑动页面时一直显示在最前面 */
background: #fff;
padding: 10rpx 24rpx;
z-index: 101;
}
.tab-bar {
display: flex;
align-items: center;
justify-content: space-between;
background: transparent;
padding: 10rpx 0;
.tab-items {
display: flex;
align-items: center;
.tab-item {
font-weight: 400;
font-size: 26rpx;
color: #777777;
background: #f5f5f5;
border-radius: 27rpx;
margin-right: 40rpx;
padding: 9rpx 24rpx;
&.active {
color: #FF4767;
background: #FFECEF;
border: 2rpx solid #FFB0BD;
border-radius: 29rpx;
}
}
}
.filter-area {
display: flex;
align-items: center;
padding: 10rpx 0;
.filter-text {
font-size: 24rpx;
color: #666666;
margin-right: 6rpx;
}
.filter-icon {
width: 24rpx;
height: 24rpx;
/* 展开时切换为上下箭头图标,调整大小 */
&.rotate {
width: 18rpx;
height: 12rpx;
}
}
}
}
/* 核心抽屉动画布局 */
.filter-panel {
position: fixed;
left: 0;
right: 0;
bottom: 0;
z-index: 100;
/* 低于 Tab区的101保证隐藏时躲在其后 */
pointer-events: none;
/* 面板关闭时,穿透点击到底部列表 */
overflow: hidden;
/* 防止抽屉向上滑出时外溢 */
&.show {
pointer-events: auto;
/* 打开时恢复点击拦截 */
.filter-mask {
opacity: 1;
}
.filter-container {
transform: translateY(50rpx);
/* 滑出 */
}
}
.filter-mask {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.4);
opacity: 0;
transition: opacity 0.3s ease-in-out;
}
.filter-container {
position: absolute;
top: 0;
left: 0;
right: 0;
background: #fff;
border-radius: 0 0 30rpx 30rpx;
padding: 40rpx 30rpx;
max-height: 80vh;
display: flex;
flex-direction: column;
box-shadow: 0 10rpx 20rpx rgba(0, 0, 0, 0.05);
transform: translateY(-100%);
/* 默认隐藏在上方即Tab背后 */
transition: transform 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
}
}
/* 垂直分组设计的样式图3 */
.filter-scroll {
max-height: 50vh;
}
.filter-group {
margin-bottom: 30rpx;
.group-title {
font-weight: 500;
font-size: 28rpx;
color: #333333;
line-height: 40rpx;
margin-bottom: 20rpx;
}
.pill-list {
display: flex;
flex-wrap: wrap;
gap: 20rpx;
}
}
/* 通用胶囊按钮 */
.pill-item {
width: calc(25% - 16rpx);
/* 25%是一行四个,减去间距 */
height: 58rpx;
background: #F5F5F5;
font-weight: 400;
font-size: 26rpx;
color: #333333;
line-height: 37rpx;
/* 使用 flex 居中 */
display: flex;
align-items: center;
justify-content: center;
border-radius: 12rpx;
box-sizing: border-box;
/* 防止 padding 会撑大盒子 */
&.active {
background: #FFF0F2;
color: #FF4767;
border: 1rpx solid #FFB0BD;
}
}
.course-filter {
display: flex;
gap: 20rpx;
/* padding: 20rpx 0 40rpx; */
.course-type-item {
background: #F5F5F5;
color: #666666;
font-size: 26rpx;
padding: 12rpx 40rpx;
border-radius: 12rpx;
&.active {
background: #FFF0F2;
color: #FF4767;
}
}
}
.filter-footer {
display: flex;
justify-content: space-between;
margin-top: 20rpx;
padding-top: 20rpx;
/* border-top: 1rpx solid #F5F5F5; */
.reset-btn,
.confirm-btn {
width: 47%;
text-align: center;
padding: 20rpx 0;
border-radius: 40rpx;
font-size: 28rpx;
}
.reset-btn {
background: #F5F5F5;
color: #666;
}
.confirm-btn {
background: #FF4767;
color: #fff;
}
}
/* 内容区缩进补充 */
.collection-content {
padding: 0 24rpx 24rpx;
margin-top: 20rpx;
overflow: hidden;
}
.brand-grid {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
.brand-card-wrap {
width: 49.2%;
margin-bottom: 20rpx;
}
}
.course-list {
display: flex;
flex-direction: column;
}
.empty-state {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 120rpx 0;
.empty-icon {
width: 346rpx;
height: 373rpx;
}
}
::v-deep .icon-headle {
width: 36rpx !important;
height: 36rpx !important;
}
</style>

View File

@ -400,7 +400,7 @@ export default {
left: 60rpx; left: 60rpx;
width: 630rpx; width: 630rpx;
height: 96rpx; height: 96rpx;
background: #E8101E; background: #FF4767;
border-radius: 58rpx; border-radius: 58rpx;
display: flex; display: flex;
align-items: center; align-items: center;
@ -499,7 +499,7 @@ export default {
} }
.region-tab.active { .region-tab.active {
color: #E8101E; color: #FF4767;
font-weight: 500; font-weight: 500;
} }
@ -511,7 +511,7 @@ export default {
transform: translateX(-50%); transform: translateX(-50%);
width: 40rpx; width: 40rpx;
height: 4rpx; height: 4rpx;
background-color: #E8101E; background-color: #FF4767;
border-radius: 2rpx; border-radius: 2rpx;
} }
@ -552,7 +552,7 @@ export default {
} }
.popup-btn.confirm { .popup-btn.confirm {
background: linear-gradient(90deg, #E8101E 0%, #FF618F 100%); background: linear-gradient(90deg, #FF4767 0%, #FF618F 100%);
} }
.popup-btn .btn-text { .popup-btn .btn-text {

356
pages/notice/detail.vue Normal file
View File

@ -0,0 +1,356 @@
<template>
<view class="notice-detail-page">
<!-- 自定义顶部导航组件 -->
<custom-navbar
title="公告通知详情"
:showBack="true"
backgroundColor="linear-gradient(180deg, #E6ECFB 0%, #FFFFFF 100%)"
:showHeadle="true"
borderBottom="none"
/>
<!-- 页面主要内容 -->
<view class="page-content">
<!-- 加载状态 -->
<view v-if="loading" class="loading-container">
<view class="loading-icon"></view>
<text class="loading-text">加载中...</text>
</view>
<!-- 详情内容 -->
<view v-else-if="detailData.id" class="detail-card">
<!-- 标题 -->
<text class="detail-title">{{ detailData.title }}</text>
<!-- 发布时间 -->
<view class="detail-time">
<text class="time-text">时间{{ formatTime(detailData.create_time) }}</text>
<text class="browse-text"> <image class="browse-icon" src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/6133cbef-5861-40f8-80f5-d8a86477c94f.png" mode="aspectFit"></image> {{ detailData.browse_num }}</text>
</view>
<!-- 富文本内容 -->
<view class="detail-content">
<rich-text :nodes="detailData.content"></rich-text>
</view>
</view>
<!-- 空状态或错误 -->
<view v-else-if="!loading && !detailData.id" class="empty-container">
<image class="empty-img" src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/8c5e7b2a-3d4f-4b1e-9a7c-6e8f2d1b4a5c.png" mode="aspectFit"></image>
<text class="empty-text">公告不存在或已删除</text>
</view>
</view>
</view>
</template>
<script>
import CustomNavbar from '@/components/custom-navbar/custom-navbar.vue';
import request from '@/utils/request';
export default {
components: {
CustomNavbar
},
data() {
return {
loading: false, //
detailData: { //
id: null,
title: '',
create_time: '',
content: ''
}
};
},
onLoad(options) {
const id = options.id;
if (id) {
this.fetchNoticeDetail(id);
} else {
uni.showToast({
title: '参数错误',
icon: 'none'
});
setTimeout(() => {
uni.navigateBack();
}, 1500);
}
},
methods: {
//
fetchNoticeDetail(id) {
this.loading = true;
request.post('/sj/notice/details', { id: id })
.then(res => {
if (res.code === 200 && res.data) {
this.detailData = res.data;
//
uni.setNavigationBarTitle({
title: this.detailData.title || '公告详情'
});
} else {
uni.showToast({
title: res.msg || '获取详情失败',
icon: 'none'
});
}
})
.catch(err => {
console.error('获取公告详情失败:', err);
uni.showToast({
title: '网络异常,请稍后重试',
icon: 'none'
});
})
.finally(() => {
this.loading = false;
});
},
formatTime(timeStr) {
if (!timeStr) return '--:--:--';
let formatted = timeStr;
if (timeStr.includes('.') && !timeStr.includes('-')) {
const match = timeStr.match(/(\d{4})\.(\d{2})\.(\d{2})(\d{2}:\d{2}:\d{2})/);
if (match) {
formatted = `${match[1]}-${match[2]}-${match[3]} ${match[4]}`;
} else {
formatted = timeStr.replace(/\./g, '-');
}
}
//
if (formatted.includes('-') && formatted.includes(':')) {
// : 2026.05.08 15:00:00
const datePart = formatted.split(' ')[0];
const timePart = formatted.split(' ')[1] || '';
if (datePart && datePart.includes('-')) {
const dotDate = datePart.replace(/-/g, '.');
return `${dotDate} ${timePart}`.trim();
}
return formatted;
}
return timeStr;
},
}
};
</script>
<style lang="scss" scoped>
.notice-detail-page {
min-height: 100vh;
background-color: #fff;
}
.page-content {
// padding: 20rpx 24rpx 60rpx;
}
//
.loading-container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 120rpx 0;
.loading-icon {
width: 60rpx;
height: 60rpx;
border: 4rpx solid #e0e0e0;
border-top-color: #FF4767;
border-radius: 50%;
animation: spin 0.8s linear infinite;
margin-bottom: 20rpx;
}
.loading-text {
font-size: 26rpx;
color: #999;
}
}
@keyframes spin {
to { transform: rotate(360deg); }
}
//
.detail-card {
background: #ffffff;
border-radius: 24rpx;
padding: 20rpx 30rpx;
margin-bottom: 30rpx;
.detail-title {
display: block;
margin-bottom: 14rpx;
font-weight: 500;
font-size: 40rpx;
color: #333333;
line-height: 56rpx;
}
.detail-time {
display: flex;
align-items: center;
margin-bottom: 30rpx;
justify-content: space-between; //
// border-bottom: 1rpx solid #f0f0f0;
.time-icon {
width: 28rpx;
height: 28rpx;
margin-right: 10rpx;
opacity: 0.6;
}
.time-text {
font-weight: 400;
font-size: 28rpx;
color: #B6B6B6;
line-height: 40rpx;
}
.browse-icon {
width: 38rpx;
height: 22rpx;
// margin-right: 10rpx;
}
.browse-text {
margin-right: 10rpx;
font-weight: 400;
font-size: 28rpx;
color: #B08463;
line-height: 40rpx;
}
}
.detail-content {
font-weight: 400;
font-size: 28rpx;
color: #2A2A2A;
line-height: 40rpx;
overflow-x: hidden;
// rich-text
::v-deep img {
max-width: 100%;
height: auto;
display: block;
margin: 30rpx 0;
}
::v-deep p {
margin-bottom: 20rpx; //
padding: 0;
}
//
::v-deep br {
display: block; // <br>
margin-bottom: 30rpx; //
}
}
}
//
.empty-container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 150rpx 0;
.empty-img {
width: 200rpx;
height: 200rpx;
margin-bottom: 30rpx;
opacity: 0.6;
}
.empty-text {
font-size: 28rpx;
color: #999;
}
}
//
.member-card {
background: linear-gradient(135deg, #FFE6E8 0%, #FFF0E6 100%);
border-radius: 24rpx;
padding: 30rpx;
display: flex;
align-items: center;
justify-content: space-between;
margin-top: 20rpx;
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.04);
.member-info {
flex: 1;
.member-price {
display: block;
font-size: 32rpx;
font-weight: bold;
color: #FF4767;
line-height: 44rpx;
margin-bottom: 8rpx;
}
.member-desc {
display: block;
font-size: 24rpx;
color: #333;
line-height: 34rpx;
margin-bottom: 12rpx;
}
.member-tag {
display: flex;
align-items: center;
.tag-text, .tag-gift {
font-size: 20rpx;
background: rgba(255, 71, 103, 0.15);
padding: 4rpx 12rpx;
border-radius: 20rpx;
color: #FF4767;
margin-right: 12rpx;
}
.tag-gift {
background: rgba(255, 193, 7, 0.2);
color: #E6A100;
}
}
}
.member-btn {
background: linear-gradient(135deg, #FF4767, #FF6B8A);
border-radius: 48rpx;
padding: 14rpx 28rpx;
text-align: center;
min-width: 160rpx;
box-shadow: 0 4rpx 12rpx rgba(255, 71, 103, 0.3);
.btn-text {
display: block;
font-size: 26rpx;
font-weight: 600;
color: #FFFFFF;
line-height: 36rpx;
}
.btn-sub {
display: block;
font-size: 20rpx;
color: rgba(255, 255, 255, 0.9);
line-height: 28rpx;
}
}
}
::v-deep .icon-headle {
width: 32rpx !important;
height: 32rpx !important;
}
</style>

View File

@ -0,0 +1,213 @@
<template>
<view class="notice-page">
<!-- 自定义顶部导航组件 -->
<custom-navbar title="公告通知" :showBack="true" backgroundColor="#FFFFFF" :show-headle="true"
headleSrc="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/51ebca5d-95c5-4fb8-8aa3-560a79100d25.png"
@onHeadleClick="goToSearch" class="nav-img-size" />
<view class="page-content">
<!-- 加载状态 -->
<view v-if="loading" class="loading-container">
<view class="loading-icon"></view>
<text class="loading-text">加载中...</text>
</view>
<!-- 公告列表 -->
<view v-else-if="noticeList.length > 0" class="notice-list">
<NoticeCard v-for="item in noticeList" :key="item.id" :item="item" @click="goToDetail" />
<!-- 加载更多状态 -->
<view v-if="loadingMore" class="load-more">
<text>加载更多...</text>
</view>
<view v-else-if="!hasMore && noticeList.length > 0" class="no-more">
<text>没有更多了</text>
</view>
</view>
<!-- 空状态 -->
<view v-else class="empty-container">
<image class="empty-img"
src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/8c5e7b2a-3d4f-4b1e-9a7c-6e8f2d1b4a5c.png"
mode="aspectFit"></image>
<text class="empty-text">暂无公告通知</text>
</view>
</view>
</view>
</template>
<script>
import CustomNavbar from '@/components/custom-navbar/custom-navbar.vue';
import NoticeCard from '@/pages/home/components/notice-card.vue';
import request from '@/utils/request';
export default {
components: {
CustomNavbar,
NoticeCard //
},
data() {
return {
loading: false,
loadingMore: false,
noticeList: [],
page: 1,
limit: 10,
total: 0,
hasMore: true
};
},
onLoad() {
this.fetchNoticeList(true);
},
onPullDownRefresh() {
this.fetchNoticeList(true);
},
onReachBottom() {
if (!this.loadingMore && this.hasMore && !this.loading) {
this.fetchNoticeList(false);
}
},
methods: {
//
goToSearch() {
uni.navigateTo({
url: '/pages/search_common/search?type=notice'
});
},
//
fetchNoticeList(reset = true) {
if (reset) {
this.page = 1;
this.hasMore = true;
this.loading = true;
} else {
if (!this.hasMore) return;
this.loadingMore = true;
// +1
this.page++;
}
request.post('/sj/notice/list', {
page: this.page,
limit: this.limit
}).then(res => {
if (res.code === 200 && res.data) {
const list = res.data.list || [];
const total = res.data.total || 0;
this.total = total;
if (reset) {
this.noticeList = list;
} else {
this.noticeList = [...this.noticeList, ...list];
}
//
this.hasMore = this.noticeList.length < total;
} else {
if (reset) this.noticeList = [];
this.hasMore = false;
//
if (!reset && this.page > 1) this.page--;
}
}).catch(err => {
console.error('获取公告列表失败:', err);
if (!reset && this.page > 1) this.page--; //
uni.showToast({
title: '加载失败,请稍后重试',
icon: 'none'
});
}).finally(() => {
this.loading = false;
this.loadingMore = false;
if (reset) {
uni.stopPullDownRefresh();
}
});
},
// NoticeCard $emit item
goToDetail(item) {
if (item.id) {
uni.navigateTo({
url: `/pages/notice/detail?id=${item.id}`
});
}
}
}
};
</script>
<style lang="scss" scoped>
.notice-page {
min-height: 100vh;
background-color: #f5f6f8;
}
.page-content {
padding: 20rpx 20rpx 40rpx;
}
.loading-container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 120rpx 0;
.loading-icon {
width: 60rpx;
height: 60rpx;
border: 4rpx solid #e0e0e0;
border-top-color: #FF4767;
border-radius: 50%;
animation: spin 0.8s linear infinite;
margin-bottom: 20rpx;
}
.loading-text {
font-size: 26rpx;
color: #999;
}
}
@keyframes spin {
to {
transform: rotate(360deg);
}
}
.load-more,
.no-more {
text-align: center;
padding: 30rpx 0;
font-size: 24rpx;
color: #999;
}
.empty-container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 150rpx 0;
.empty-img {
width: 200rpx;
height: 200rpx;
margin-bottom: 30rpx;
opacity: 0.6;
}
.empty-text {
font-size: 28rpx;
color: #999;
}
}
.nav-img-size::v-deep .icon-headle {
width: 36rpx !important;
height: 36rpx !important;
}
</style>

View File

@ -275,18 +275,18 @@ export default {
.rating-score { .rating-score {
font-size: 16rpx; font-size: 16rpx;
color: #E8101E; color: #FF4767;
margin-left: 68rpx; margin-left: 68rpx;
} }
.currency { .currency {
font-size: 24rpx; font-size: 24rpx;
color: #E8101E; color: #FF4767;
} }
.amount { .amount {
font-size: 32rpx; font-size: 32rpx;
color: #E8101E; color: #FF4767;
font-weight: 500; font-weight: 500;
} }
@ -328,7 +328,7 @@ export default {
} }
.load-date { .load-date {
font-size: 24rpx; font-size: 24rpx;
color: #E8101E; color: #FF4767;
} }
.load-text { .load-text {

View File

@ -716,7 +716,7 @@ page {
.real-price { .real-price {
font-size: 32rpx; font-size: 32rpx;
font-weight: 500; font-weight: 500;
color: #E8101E; color: #FF4767;
} }
/* 订单信息卡片 */ /* 订单信息卡片 */
.order-card { .order-card {
@ -788,13 +788,13 @@ page {
margin-left: 20rpx; margin-left: 20rpx;
} }
.btn-border { .btn-border {
border: 1rpx solid #E8101E; border: 1rpx solid #FF4767;
background-color: #fff; background-color: #fff;
box-sizing: border-box; box-sizing: border-box;
margin-left: 20rpx; margin-left: 20rpx;
} }
.btn-bg { .btn-bg {
background-color: #E8101E; background-color: #FF4767;
} }
.button-text { .button-text {
font-size: 28rpx; font-size: 28rpx;
@ -804,7 +804,7 @@ page {
.btn-border .button-text { .btn-border .button-text {
font-size: 28rpx; font-size: 28rpx;
font-weight: 400; font-weight: 400;
color: #E8101E; color: #FF4767;
} }
/* APP适配 */ /* APP适配 */
/* #ifdef APP-PLUS */ /* #ifdef APP-PLUS */

View File

@ -24,7 +24,7 @@
<image :src="item.icon" mode="aspectFit" class="method-icon"></image> <image :src="item.icon" mode="aspectFit" class="method-icon"></image>
<text class="method-name">{{ item.name }}</text> <text class="method-name">{{ item.name }}</text>
</view> </view>
<agree-radio :isAgree="item.selected" :yesImg="`/static/images/icons/yes_icon.png`" :radioSize="`40rpx`" :noImg="`/static/images/icons/no_icon.png`"></agree-radio> <agree-radio :isAgree="item.selected" :yesImg="`/static/images/agree_y.png`" :radioSize="`40rpx`" :noImg="`/static/images/icons/no_icon.png`"></agree-radio>
</view> </view>
</view> </view>
</view> </view>
@ -494,7 +494,7 @@
::v-deep .uv-count-down__text { ::v-deep .uv-count-down__text {
font-weight: 400; font-weight: 400;
font-size: 26rpx; font-size: 26rpx;
color: #E8101E;; color: #FF4767;;
line-height: 37rpx; line-height: 37rpx;
text-align: center; text-align: center;
font-style: normal; font-style: normal;
@ -559,13 +559,13 @@
.total-amount .symbol { .total-amount .symbol {
font-size: 24rpx; font-size: 24rpx;
font-weight: 500; font-weight: 500;
color: #E8101E; color: #FF4767;
} }
.total-amount .amount { .total-amount .amount {
font-size: 28rpx; font-size: 28rpx;
font-weight: 500; font-weight: 500;
color: #E8101E; color: #FF4767;
} }
.amount-lable { .amount-lable {
@ -576,7 +576,7 @@
.pay-btn { .pay-btn {
width: 680rpx; width: 680rpx;
height: 88rpx; height: 88rpx;
background: linear-gradient( 180deg, #F52540 0%, #E8101E 100%); background: linear-gradient( 180deg, #F52540 0%, #FF4767 100%);
border-radius: 43rpx; border-radius: 43rpx;
font-weight: 500; font-weight: 500;
font-size: 30rpx; font-size: 30rpx;

View File

@ -623,7 +623,7 @@ export default {
height: 28rpx; height: 28rpx;
border: 3rpx; border: 3rpx;
margin-right: 16rpx; margin-right: 16rpx;
background-color: #E8101E; background-color: #FF4767;
} }
.service-item { .service-item {
@ -766,7 +766,7 @@ export default {
.price-total .price { .price-total .price {
font-size: 28rpx; font-size: 28rpx;
font-weight: 500; font-weight: 500;
color: #E8101E; color: #FF4767;
} }
.amount-lable { .amount-lable {
@ -777,7 +777,7 @@ export default {
.submit-btn { .submit-btn {
width: 492rpx; width: 492rpx;
height: 64rpx; height: 64rpx;
background: #E8101E; background: #FF4767;
border-radius: 32rpx; border-radius: 32rpx;
color: #ffffff; color: #ffffff;
font-size: 28rpx; font-size: 28rpx;
@ -984,8 +984,8 @@ export default {
.isActive { .isActive {
background: rgba(252, 67, 124, 0.08); background: rgba(252, 67, 124, 0.08);
border-radius: 10rpx; border-radius: 10rpx;
border: 1rpx solid #E8101E; border: 1rpx solid #FF4767;
color: #E8101E; color: #FF4767;
/* 选中状态 */ /* 选中状态 */
} }
@ -1010,7 +1010,7 @@ export default {
&__box { &__box {
width: 648rpx; width: 648rpx;
height: 94rpx; height: 94rpx;
background: linear-gradient(140deg, #fa4e9a 0%, #E8101E 100%); background: linear-gradient(140deg, #fa4e9a 0%, #FF4767 100%);
border-radius: 48rpx; border-radius: 48rpx;
display: flex; display: flex;
align-items: center; align-items: center;

View File

@ -18,7 +18,7 @@
<view class="group-invite" <view class="group-invite"
v-if="orderInfo.state !=1 && orderInfo.team_buy_id && (orderInfo.team_buy_order_state==1||orderInfo.team_buy_order_state==2)"> v-if="orderInfo.state !=1 && orderInfo.team_buy_id && (orderInfo.team_buy_order_state==1||orderInfo.team_buy_order_state==2)">
<view class="invite-text" v-if="orderInfo.team_buy_order_state == 1">参团成功需邀请<text <view class="invite-text" v-if="orderInfo.team_buy_order_state == 1">参团成功需邀请<text
style="color: #E8101E">{{orderInfo.team_buy.person_num - orderInfo.team_buy.pay_person_num}}</text>人才可完成拼团 style="color: #FF4767">{{orderInfo.team_buy.person_num - orderInfo.team_buy.pay_person_num}}</text>人才可完成拼团
</view> </view>
<view class="invite-text" v-if="orderInfo.team_buy_order_state == 2">参团成功已拼团成功</view> <view class="invite-text" v-if="orderInfo.team_buy_order_state == 2">参团成功已拼团成功</view>
@ -266,16 +266,16 @@
formatPriceNumber(this.orderInfo.cost_money-this.orderInfo.order_money), formatPriceNumber(this.orderInfo.cost_money-this.orderInfo.order_money),
18, 18,
2 2
)}rpx;color: #E8101E;line-height: 25rpx;text-align: left;font-style: normal;`" /> )}rpx;color: #FF4767;line-height: 25rpx;text-align: left;font-style: normal;`" />
</l-painter-view> </l-painter-view>
<l-painter-view css="margin-top:44rpx;"> <l-painter-view css="margin-top:44rpx;">
<l-painter-text text="¥" <l-painter-text text="¥"
css="font-weight: 500;font-size: 26rpx;color: #E8101E;line-height: 48rpx;text-align: left;font-style: normal;" /> css="font-weight: 500;font-size: 26rpx;color: #FF4767;line-height: 48rpx;text-align: left;font-style: normal;" />
<l-painter-text :text=" formatPriceNumber(this.orderInfo.order_money)" :css="`font-weight: 500;font-size:${formatPriceSize( <l-painter-text :text=" formatPriceNumber(this.orderInfo.order_money)" :css="`font-weight: 500;font-size:${formatPriceSize(
formatPriceNumber(this.orderInfo.order_money), formatPriceNumber(this.orderInfo.order_money),
56, 56,
3 3
)}rpx;color: #E8101E;line-height: 34rpx;text-align: left;font-style: normal;`" /> )}rpx;color: #FF4767;line-height: 34rpx;text-align: left;font-style: normal;`" />
</l-painter-view> </l-painter-view>
<l-painter-view css="margin-top:0rpx;"> <l-painter-view css="margin-top:0rpx;">
<l-painter-text :text="`原价¥${formatPriceNumber(this.orderInfo.cost_money)}`" :css="`text-decoration: line-through;font-weight: 400;font-size:${formatPriceSize( <l-painter-text :text="`原价¥${formatPriceNumber(this.orderInfo.cost_money)}`" :css="`text-decoration: line-through;font-weight: 400;font-size:${formatPriceSize(
@ -1005,7 +1005,7 @@
.phone-btn { .phone-btn {
width: 64rpx; width: 64rpx;
height: 64rpx; height: 64rpx;
background-color: #E8101E; background-color: #FF4767;
border-radius: 32rpx; border-radius: 32rpx;
} }
@ -1249,7 +1249,7 @@
.service-price2 { .service-price2 {
font-weight: 500; font-weight: 500;
font-size: 24rpx; font-size: 24rpx;
color: #E8101E; color: #FF4767;
line-height: 34rpx; line-height: 34rpx;
text-align: left; text-align: left;
font-style: normal; font-style: normal;
@ -1282,7 +1282,7 @@
font-family: DINPro, DINPro; font-family: DINPro, DINPro;
font-weight: 500; font-weight: 500;
font-size: 36rpx; font-size: 36rpx;
color: #E8101E; color: #FF4767;
line-height: 34rpx; line-height: 34rpx;
text-align: left; text-align: left;
font-style: normal; font-style: normal;
@ -1352,7 +1352,7 @@
} }
.btn-bg { .btn-bg {
background-color: #E8101E; background-color: #FF4767;
} }
.button-text { .button-text {
@ -1444,7 +1444,7 @@
align-items: center; align-items: center;
font-weight: 500; font-weight: 500;
font-size: 24rpx; font-size: 24rpx;
color: #E8101E; color: #FF4767;
line-height: 33rpx; line-height: 33rpx;
text-align: left; text-align: left;
font-style: normal; font-style: normal;

File diff suppressed because it is too large Load Diff

View File

@ -15,7 +15,7 @@
<view> <view>
<view class="serve-card-right__content__title">{{item.title}}</view> <view class="serve-card-right__content__title">{{item.title}}</view>
<view class="serve-card-right__content__price"><text <view class="serve-card-right__content__price"><text
style="color: #E8101E;font-weight: 500;">¥{{item.server_price}} </text> {{' '}}| style="color: #FF4767;font-weight: 500;">¥{{item.server_price}} </text> {{' '}}|
{{item.server_time}}分钟 {{item.server_time}}分钟
</view> </view>
</view> </view>

View File

@ -25,7 +25,7 @@
<text class="service-name">{{ item.server_title }}</text> <text class="service-name">{{ item.server_title }}</text>
<text class="order-time">下单时间{{ item.pay_time }}</text> <text class="order-time">下单时间{{ item.pay_time }}</text>
<text class="order-status"> <text class="order-status">
订单状态<text style="color: #E8101E;">{{ getDescriptionByNumber(item.state) }}</text> 订单状态<text style="color: #FF4767;">{{ getDescriptionByNumber(item.state) }}</text>
</text> </text>
</view> </view>
</view> </view>

View File

@ -1,7 +1,7 @@
<template> <template>
<view class="promotion"> <view class="promotion">
<custom-navbar title="推广服务" :leftImg="'/static/images/whiteBack.png'" :showUser="true" <custom-navbar title="推广服务" :leftImg="'/static/images/whiteBack.png'" :showUser="true"
backgroundColor="linear-gradient( 134deg, #F52540 0%, #E8101E 100%)" titleColor="#fff" backgroundColor="linear-gradient( 134deg, #F52540 0%, #FF4767 100%)" titleColor="#fff"
borderBottom="none"></custom-navbar> borderBottom="none"></custom-navbar>
<view class="promotion-search"> <view class="promotion-search">
<view class="promotion-add"> <view class="promotion-add">
@ -224,7 +224,7 @@
<style lang="less"> <style lang="less">
.promotion { .promotion {
.promotion-search { .promotion-search {
background: linear-gradient(134deg, #f52540 0%, #e8101e 100%); background: linear-gradient(134deg, #f52540 0%, #FF4767 100%);
box-sizing: border-box; box-sizing: border-box;
padding: 31rpx 20rpx 60rpx 20rpx; padding: 31rpx 20rpx 60rpx 20rpx;
@ -292,7 +292,7 @@
position: relative; position: relative;
&.active { &.active {
color: #E8101E; color: #FF4767;
&::after { &::after {
content: ''; content: '';
@ -325,7 +325,7 @@
width: 100%; width: 100%;
font-weight: 400; font-weight: 400;
font-size: 22rpx; font-size: 22rpx;
color: #E8101E; color: #FF4767;
line-height: 30rpx; line-height: 30rpx;
text-align: left; text-align: left;
font-style: normal; font-style: normal;
@ -374,7 +374,7 @@
border: 1rpx solid rgba(232, 16, 30, 0.2); border: 1rpx solid rgba(232, 16, 30, 0.2);
font-weight: 400; font-weight: 400;
font-size: 24rpx; font-size: 24rpx;
color: #E8101E; color: #FF4767;
line-height: 33rpx; line-height: 33rpx;
text-align: left; text-align: left;
font-style: normal; font-style: normal;
@ -398,7 +398,7 @@
font-family: DINPro, DINPro; font-family: DINPro, DINPro;
font-weight: 500; font-weight: 500;
font-size: 36rpx; font-size: 36rpx;
color: #E8101E; color: #FF4767;
line-height: 46rpx; line-height: 46rpx;
text-align: left; text-align: left;
font-style: normal; font-style: normal;
@ -468,12 +468,12 @@
} }
.closeModal { .closeModal {
border: 2rpx solid #E8101E; border: 2rpx solid #FF4767;
color: #E8101E; color: #FF4767;
} }
.sureModal { .sureModal {
background: #E8101E; background: #FF4767;
border-radius: 40rpx; border-radius: 40rpx;
color: #FFFFFF; color: #FFFFFF;
} }

View File

@ -2,7 +2,7 @@
<view class="select-serve"> <view class="select-serve">
<custom-navbar title="选择服务" backgroundColor="#FFFFFF"></custom-navbar> <custom-navbar title="选择服务" backgroundColor="#FFFFFF"></custom-navbar>
<view class="select-tip"> <view class="select-tip">
<text style="color: #E8101E;">温馨提示</text>您可自主勾选需推广的服务灵活设置比例形式的推广佣金 <text style="color: #FF4767;">温馨提示</text>您可自主勾选需推广的服务灵活设置比例形式的推广佣金
配置完成后服务将自动进入推广平台曝光触达更多潜在客户后续通过推广渠道如达人链接分享码成功成交的订单 配置完成后服务将自动进入推广平台曝光触达更多潜在客户后续通过推广渠道如达人链接分享码成功成交的订单
系统会从该笔订单中自动扣除您预设的佣金全程无需手动操作 系统会从该笔订单中自动扣除您预设的佣金全程无需手动操作
</view> </view>
@ -85,7 +85,7 @@
&__btn { &__btn {
width: 690rpx; width: 690rpx;
height: 78rpx; height: 78rpx;
background: #E8101E; background: #FF4767;
border-radius: 798rpx; border-radius: 798rpx;
display: flex; display: flex;
align-items: center; align-items: center;

View File

@ -2,7 +2,7 @@
<view class="select-serve"> <view class="select-serve">
<custom-navbar title="设置佣金" backgroundColor="#FFFFFF"></custom-navbar> <custom-navbar title="设置佣金" backgroundColor="#FFFFFF"></custom-navbar>
<view class="select-tip"> <view class="select-tip">
<text style="color: #E8101E;">温馨提示</text>支持 快速设置百分比如每单返 2%佣金成功成交的订单系统会按照实付金额*佣金比例进行扣减 <text style="color: #FF4767;">温馨提示</text>支持 按1%~30%区间设置佣金比例订单成功成交后系统将按实付金额 × 佣金比例自动扣减
</view> </view>
<view v-for="(item,index) in selectedItems" :key="index" class="serve-card"> <view v-for="(item,index) in selectedItems" :key="index" class="serve-card">
<image :src="item.photo[0]" mode="aspectFill" class="serve-card__img"></image> <image :src="item.photo[0]" mode="aspectFill" class="serve-card__img"></image>
@ -34,7 +34,7 @@
<uv-modal ref="modal" title="提示" width="620rpx"> <uv-modal ref="modal" title="提示" width="620rpx">
<view class="slot-content"> <view class="slot-content">
预估佣金按<text style="color: #E8101E;">订单实付金额 × 佣金比例</text>计算因服务实付金额受活动参与程度影响存在波动最终佣金以订单实际结算结果为准 预估佣金按<text style="color: #FF4767;">订单实付金额 × 佣金比例</text>计算因服务实付金额受活动参与程度影响存在波动最终佣金以订单实际结算结果为准
</view> </view>
<template v-slot:confirmButton> <template v-slot:confirmButton>
<view type="default" @click="closeModal" class="closeModal">确定</view> <view type="default" @click="closeModal" class="closeModal">确定</view>
@ -271,7 +271,7 @@
font-family: DINPro, DINPro; font-family: DINPro, DINPro;
font-weight: 500; font-weight: 500;
font-size: 22rpx; font-size: 22rpx;
color: #E8101E; color: #FF4767;
line-height: 34rpx; line-height: 34rpx;
text-align: left; text-align: left;
font-style: normal; font-style: normal;
@ -328,7 +328,7 @@
&__btn { &__btn {
width: 690rpx; width: 690rpx;
height: 78rpx; height: 78rpx;
background: #E8101E; background: #FF4767;
border-radius: 798rpx; border-radius: 798rpx;
display: flex; display: flex;
align-items: center; align-items: center;
@ -347,7 +347,7 @@
.closeModal { .closeModal {
width: 556rpx; width: 556rpx;
height: 80rpx; height: 80rpx;
background: #E8101E; background: #FF4767;
border-radius: 40rpx; border-radius: 40rpx;
font-weight: 500; font-weight: 500;
font-size: 28rpx; font-size: 28rpx;

View File

@ -1386,7 +1386,7 @@
.title-bar { .title-bar {
width: 6rpx; width: 6rpx;
height: 48rpx; height: 48rpx;
background-color: #E8101E; background-color: #FF4767;
margin-right: 16rpx; margin-right: 16rpx;
border-radius: 3rpx; border-radius: 3rpx;
} }
@ -1585,7 +1585,7 @@
.promise-title { .promise-title {
font-size: 28rpx; font-size: 28rpx;
color: #E8101E; color: #FF4767;
font-weight: 400; font-weight: 400;
margin-bottom: 24rpx; margin-bottom: 24rpx;
text-align: center; text-align: center;
@ -1603,7 +1603,7 @@
width: 12rpx; width: 12rpx;
height: 12rpx; height: 12rpx;
border-radius: 6rpx; border-radius: 6rpx;
background-color: #E8101E; background-color: #FF4767;
margin-right: 24rpx; margin-right: 24rpx;
} }
@ -1711,8 +1711,8 @@
} }
.checkbox.checked { .checkbox.checked {
background-color: #E8101E; background-color: #FF4767;
border-color: #E8101E; border-color: #FF4767;
} }
.check-icon { .check-icon {
@ -1745,7 +1745,7 @@
} }
.popup-btn.confirm { .popup-btn.confirm {
background: linear-gradient(90deg, #E8101E 0%, #FF618F 100%); background: linear-gradient(90deg, #FF4767 0%, #FF618F 100%);
} }
.popup-btn .btn-text { .popup-btn .btn-text {
@ -1783,7 +1783,7 @@
} }
.region-tab.active { .region-tab.active {
color: #E8101E; color: #FF4767;
font-weight: 500; font-weight: 500;
} }
@ -1795,7 +1795,7 @@
transform: translateX(-50%); transform: translateX(-50%);
width: 40rpx; width: 40rpx;
height: 4rpx; height: 4rpx;
background-color: #E8101E; background-color: #FF4767;
border-radius: 2rpx; border-radius: 2rpx;
} }
@ -1858,7 +1858,7 @@
.confirm-text { .confirm-text {
font-size: 32rpx; font-size: 32rpx;
color: #E8101E; color: #FF4767;
font-weight: 500; font-weight: 500;
} }
@ -1900,7 +1900,7 @@
} }
.time-block.active .time-value { .time-block.active .time-value {
color: #E8101E; color: #FF4767;
} }
.time-separator { .time-separator {

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -4,31 +4,35 @@
<custom-navbar :title="navTitle" :showBack="true"></custom-navbar> <custom-navbar :title="navTitle" :showBack="true"></custom-navbar>
<!-- 步骤切换 --> <!-- 步骤切换 -->
<step-tab :currentStep="currentStep" :identity="identity"></step-tab> <step-tab v-if="currentStep !== 2 && currentStep !== 4" :mappedStep="mappedStep"></step-tab>
<!-- 内容区域根据身份和步骤显示不同内容 --> <!-- 内容区域根据身份和步骤显示不同内容 -->
<view class="content"> <view class="content">
<!-- 入驻协议内容 -->
<view class="xieyi_content" v-if="currentStep === 0"> <view class="xieyi_content" v-if="currentStep === 0">
<rich-text :nodes="textData.text"></rich-text> <rich-text :nodes="textData.text"></rich-text>
</view> </view>
<!-- 步骤1: 根据身份显示不同内容 -->
<view v-else-if="currentStep === 1"> <view v-else-if="currentStep === 1">
<!-- 手艺人显示个人信息商家显示资质信息 -->
<qualification-info ref="qualificationInfo"></qualification-info> <qualification-info ref="qualificationInfo"></qualification-info>
</view> </view>
<!-- 步骤2: 根据身份显示不同内容 -->
<view v-else-if="currentStep === 2"> <view v-else-if="currentStep === 2">
<!-- 手艺人显示资质信息商家显示门店信息 --> <successruzhu :data="successData" @stateChange="onStateChange"></successruzhu>
</view>
<view v-else-if="currentStep === 3">
<store-info ref="storeInfo"></store-info> <store-info ref="storeInfo"></store-info>
</view> </view>
<view v-else-if="currentStep === 4">
<successruzhu :data="successData" @stateChange="onStateChange"></successruzhu>
</view>
</view> </view>
<view class="kong"></view> <view class="kong"></view>
<!-- 底部按钮区域 --> <!-- 底部按钮区域 -->
<view class="bottom-fixed"> <view class="bottom-fixed">
<!-- 步骤0: 入驻协议 - 只显示下一步 --> <!-- 步骤0: 入驻协议 -->
<view v-if="currentStep === 0" class="step-0-buttons"> <view v-if="currentStep === 0" class="step-0-buttons">
<view class="agree"> <view class="agree">
<image v-if="!isAgree" src="/static/images/agree_n.png" class="agree-btn" mode="aspectFit" <image v-if="!isAgree" src="/static/images/agree_n.png" class="agree-btn" mode="aspectFit"
@ -38,26 +42,38 @@
<text class="agree-tip">我已阅读并同意以上协议</text> <text class="agree-tip">我已阅读并同意以上协议</text>
</view> </view>
<view class="next-btn" @click="goNext"> <view class="next-btn" @click="goNext">
<text class="next-text">下一步填写资质信息</text> <text class="next-text">下一步填写基本信息</text>
</view> </view>
</view> </view>
<!-- 步骤1: 资质信息 - 显示上一步和下一步 --> <!-- 步骤1: 资质信息 -->
<view v-else-if="currentStep === 1" class="step-1-buttons"> <view v-else-if="currentStep === 1" class="step-1-buttons">
<view class="button-row"> <view class="button-row">
<view class="prev-btn" @click="goPrev"> <view class="prev-btn" @click="goPrev">
<text class="prev-text">上一步</text> <text class="prev-text">上一步</text>
</view> </view>
<view class="next-btn" @click="goNext"> <view class="next-btn" @click="goNext">
<text class="next-text">下一步填写门店信息</text> <text class="next-text">提交入驻</text>
</view> </view>
</view> </view>
</view> </view>
<!-- 步骤2: 门店信息 - 显示上一步和提交申请 --> <!-- 步骤2: 提交成功 -->
<view v-else-if="currentStep === 2" class="step-2-buttons"> <view v-else-if="currentStep === 2" class="step-2-buttons">
<view class="button-row"> <view class="button-row">
<view class="prev-btn" @click="goPrev"> <view class="prev-btn" @click="topt">
<text class="prev-text">进入平台</text>
</view>
<view class="submit-btn" @click="goNext">
<text class="submit-text">去完成资质认证</text>
</view>
</view>
</view>
<!-- 步骤3: 门店信息 -->
<view v-else-if="currentStep === 3" class="step-2-buttons">
<view class="button-row">
<view v-if="!isRejected" class="prev-btn" @click="goPrev">
<text class="prev-text">上一步</text> <text class="prev-text">上一步</text>
</view> </view>
<view class="submit-btn" @click="submitApplication"> <view class="submit-btn" @click="submitApplication">
@ -65,6 +81,23 @@
</view> </view>
</view> </view>
</view> </view>
<!-- 步骤4: 资质认证成功 -->
<view v-else-if="currentStep === 4" class="step-2-buttons">
<view v-if="isRejected" class="button-row">
<view class="prev-btn" @click="resubmit">
<text class="prev-text">重新提交</text>
</view>
<view class="showziliao1" @click="topt">
<text class="showziliaotext1">进入平台</text>
</view>
</view>
<view v-else class="button-row">
<view class="showziliao" @click="topt">
<text class="showziliaotext">进入平台</text>
</view>
</view>
</view>
</view> </view>
</view> </view>
</template> </template>
@ -74,12 +107,14 @@
import StepTab from '@/components/step-tab/step-tab.vue'; import StepTab from '@/components/step-tab/step-tab.vue';
import QualificationInfo from './qualification_sj.vue'; import QualificationInfo from './qualification_sj.vue';
import StoreInfo from './sj-info.vue'; import StoreInfo from './sj-info.vue';
import successruzhu from './successruzhu.vue';
export default { export default {
components: { components: {
StepTab, StepTab,
QualificationInfo, QualificationInfo,
StoreInfo, StoreInfo,
successruzhu
}, },
data() { data() {
return { return {
@ -89,9 +124,10 @@
textData: {}, textData: {},
loading: false, loading: false,
error: null, error: null,
navTitle: '商家入驻', //
qualificationData: null, // qualificationData: null, //
storeInfoData: null, // storeInfoData: null, //
successData: {}, //
isRejected: false, //
// //
artisanDataCache: { artisanDataCache: {
personalInfo: null, personalInfo: null,
@ -99,7 +135,36 @@
} }
} }
}, },
computed: {
mappedStep() {
if (this.currentStep === 0) return 0;
if (this.currentStep === 1) return 1;
if (this.currentStep === 3) return 2;
if (this.currentStep === 4) return 2;
return 0;
},
navTitle() {
return this.currentStep === 3 ? '资质认证' : '商家入驻';
}
},
async onLoad(options) { async onLoad(options) {
console.log(options, 'options---');
if (options.type == 0 && options.step == 3) {
this.currentStep = 3
this.isRejected = true
}
if (options.type == 1) {
this.currentStep = 4
}
if (options.type == 2) {
this.currentStep = 2
}
// step
if (options.step) {
this.currentStep = Number(options.step);
}
this.identity = 2; this.identity = 2;
await this.getUserInfoSync() await this.getUserInfoSync()
// 访 identity // 访 identity
@ -113,6 +178,21 @@
}, },
methods: { methods: {
topt() {
uni.switchTab({
url: '/pages/home/home'
})
},
onStateChange(state) {
if (state === 3) {
this.isRejected = true;
}
},
resubmit() {
uni.navigateTo({
url: '/pages/ruzhu/ruzhu?type=0&step=3'
});
},
// //
async getUserInfoSync() { async getUserInfoSync() {
await request.post('/sj/userSjAuth/details', { await request.post('/sj/userSjAuth/details', {
@ -122,56 +202,32 @@
let data = result.data let data = result.data
if (getApp().globalData.artisanType == 2) { if (getApp().globalData.artisanType == 2) {
//
let qualification_form_data = { let qualification_form_data = {
"uscc_num": data.uscc_num, "uscc_type": data.uscc_type || '',
"uscc_name": data.uscc_name, // "contact_identity": 'legal',
"legal_name": data.legal_name, // "contact_name": data.legal_name || data.contact_name || '',
"legal_phone": data.legal_phone, "contact_phone": data.legal_phone || data.contact_phone || '',
"legal_idcard_num": data.legal_idcard_num, "backup_phone": data.backup_phone || '',
"uscc_photo": data.uscc_photo, "invite_code": data.invite_code_other || '',
"legal_idcard_positive": data.legal_idcard_positive, "dependency": data.dependency || '',
"legal_idcard_negative": data.legal_idcard_negative, "address": data.address || '',
"uscc_type": data.uscc_type, "dependency_code": data.dependency_code || '',
"license_valid_type": data.uscc_expiry_type, "dependency_province": data.dependency_province || '',
} "dependency_city": data.dependency_city || '',
if (data.uscc_expiry) { "longitude": data.longitude || '',
let expirys = data.uscc_expiry.split(' —— ') "latitude": data.latitude || '',
qualification_form_data.license_start_date = expirys[0] "name": data.name || '',
qualification_form_data.license_end_date = expirys[1] "contact_type": data.contact_type || ''
}
if (data.legal_idcard_expiry) {
let expirys = data.legal_idcard_expiry.split(' —— ')
qualification_form_data.idcard_start_date = expirys[0]
if (expirys[1]) {
qualification_form_data.legal_idcard_expiry_type = "date"
qualification_form_data.idcard_end_date = expirys[1]
} else {
qualification_form_data.legal_idcard_expiry_type = "permanent"
qualification_form_data.idcard_end_date = ""
}
} }
uni.setStorageSync('qualification_form_data', qualification_form_data); uni.setStorageSync('qualification_form_data', qualification_form_data);
let store_invite_state = {
"currentValidatingCode": data.invite_code_other
}
uni.setStorageSync('store_invite_state', store_invite_state);
let store_info_form_data = { let store_info_form_data = {
"head_photo": data.head_photo, "head_photo": data.head_photo,
"name": data.name, "name": data.name,
"business_time": data.business_time, "business_time": data.business_time,
"servers_kill": data.servers_kill, // "servers_kill": data.servers_kill,
"dependency": data.dependency,
"address": data.address,
"apply_state": data.apply_state, "apply_state": data.apply_state,
"invite_code_other": data.invite_code_other, "invite_code_other": data.invite_code_other,
"major": data.major, "major": data.major
"dependency_code": data.dependency_code,
"dependency_province": data.dependency_province,
"dependency_city": data.dependency_city,
"longitude": data.longitude,
"latitude": data.latitude
} }
console.log(111111111, store_info_form_data) console.log(111111111, store_info_form_data)
uni.setStorageSync('store_info_form_data', store_info_form_data); uni.setStorageSync('store_info_form_data', store_info_form_data);
@ -182,65 +238,6 @@
console.error('获取用户信息接口错误:', error); console.error('获取用户信息接口错误:', error);
}); });
}, },
/**
* 解析身份证有效期字符串转换为中文日期格式兼容低版本iOS支持结束日期为空/长期
* @param {string} expiryStr 原有效期字符串格式如"2016-01-29 —— 2026-01-29" | "2016-01-29 —— " | "2016-01-29 —— 长期"
* @returns {Object} 包含开始和结束日期的对象
*/
parseIdCardExpiry(expiryStr) {
//
let id_card_start_date = '';
let id_card_end_date = '';
try {
// 1. ---
const dateParts = expiryStr.split(/\s*[-—]{1,2}\s*/).map(str => str.trim());
//
const startStr = dateParts[0] || '';
const endStr = dateParts[1] || '';
// 2. iOS
const formatDateToChinese = (dateStr) => {
//
if (!dateStr) return '';
//
if (dateStr === '长期') return '长期';
// iOSyyyy-mm-ddyyyy/mm/dd
const compatibleStr = dateStr.replace(/-/g, '/');
const date = new Date(compatibleStr);
//
if (isNaN(date.getTime())) {
return ''; //
}
//
const year = date.getFullYear();
const month = date.getMonth() + 1;
const day = date.getDate();
return `${year}${month}${day}`;
};
// 3.
if (startStr) {
id_card_start_date = formatDateToChinese(startStr);
}
// 4.
id_card_end_date = formatDateToChinese(endStr);
} catch (err) {
console.error('解析身份证有效期失败:', err);
}
// 5.
return {
id_card_start_date,
id_card_end_date
};
},
// //
checkAndPassAddressToSj() { checkAndPassAddressToSj() {
try { try {
@ -248,37 +245,14 @@
if (sjAddress) { if (sjAddress) {
console.log('找到商家地址数据,准备传递:', sjAddress); console.log('找到商家地址数据,准备传递:', sjAddress);
//
setTimeout(() => { setTimeout(() => {
if (this.identity === 2 && this.$refs.storeInfo) { if (this.identity === 2 && this.$refs.qualificationInfo) {
console.log('传递地址给商家组件'); console.log('传递地址给资质组件');
if (typeof this.$refs.qualificationInfo.handleAddressSelected === 'function') {
// this.$refs.qualificationInfo.handleAddressSelected(sjAddress);
if (typeof this.$refs.storeInfo.handleAddressSelected === 'function') {
this.$refs.storeInfo.handleAddressSelected(sjAddress);
} else if (this.$refs.storeInfo.formData) {
//
this.$refs.storeInfo.formData.address = sjAddress.address || sjAddress
.name;
this.$refs.storeInfo.formData.longitude = sjAddress.longitude;
this.$refs.storeInfo.formData.latitude = sjAddress.latitude;
//
if (sjAddress.pname || sjAddress.cityname || sjAddress.adname) {
const locationParts = [];
if (sjAddress.pname) locationParts.push(sjAddress.pname);
if (sjAddress.cityname) locationParts.push(sjAddress.cityname);
if (sjAddress.adname) locationParts.push(sjAddress.adname);
this.$refs.storeInfo.formData.dependency = locationParts.join('-');
} }
this.$refs.storeInfo.saveFormDataToLocal();
this.$refs.storeInfo.$forceUpdate();
} }
//
uni.removeStorageSync('sj_selected_address'); uni.removeStorageSync('sj_selected_address');
}
}, 300); }, 300);
} }
} catch (e) { } catch (e) {
@ -400,7 +374,6 @@
// //
async submitForReview() { async submitForReview() {
//
const userInfo = await this.checkAndGetUserInfo(); const userInfo = await this.checkAndGetUserInfo();
if (!userInfo) { if (!userInfo) {
return; return;
@ -411,71 +384,30 @@
}); });
try { try {
console.log('=== 提交审核调试信息 ==='); let formData = this.buildBusinessData(this.qualificationData, {});
console.log('身份类型:', this.identity); formData.type = 1;
console.log('门店信息数据:', this.storeInfoData); formData.id_type = 1;
console.log('资质信息数据:', this.qualificationData); if (Array.isArray(formData.qualifications_sector)) {
console.log('个人信息数据:', this.personalInfoData); formData.qualifications_sector = JSON.stringify(formData.qualifications_sector);
let apiUrl = '';
let formData = {};
if (this.identity === 2) {
//
apiUrl = '/sj/userSjAuth/apply';
//
if (this.$refs.storeInfo) {
if (!this.$refs.storeInfo.saveFormData()) {
uni.hideLoading();
return;
} }
this.storeInfoData = this.$refs.storeInfo.getFormData(); if (Array.isArray(formData.qualifications_other)) {
console.log('重新获取的门店信息:', this.storeInfoData); formData.qualifications_other = JSON.stringify(formData.qualifications_other);
} }
const res = await request.post('/sj/userSjAuth/applyOne', formData);
//
if (!this.storeInfoData || !this.storeInfoData.servers_kill || this.storeInfoData
.servers_kill.length === 0) {
uni.hideLoading();
uni.showToast({
title: '请选择服务技能',
icon: 'none'
});
return;
}
formData = this.buildBusinessData(this.qualificationData, this.storeInfoData);
}
console.log('提交的数据:', formData);
console.log('API URL:', apiUrl);
formData.type = 1
formData.id_type = 1
const res = await request.post(apiUrl, formData);
uni.hideLoading(); uni.hideLoading();
if (res.state == 1 || res.code == 200) { if (res.state == 1 || res.code == 200) {
// this.successData = res.data.customer_service
console.log(this.successData,
'this.successDatathis.successDatathis.successDatathis.successData=======');
uni.showToast({ uni.showToast({
title: '提交成功', title: '提交成功',
icon: 'none', icon: 'none',
duration: 1500, duration: 1500
success: () => { });
setTimeout(() => { setTimeout(() => {
uni.redirectTo({ this.currentStep = 2;
url: `./submitres?identity=${this.identity}&applyState=1`
});
}, 1500); }, 1500);
}
});
} else { } else {
uni.showToast({ uni.showToast({
title: res.msg || '提交失败', title: res.msg || '提交失败',
@ -484,7 +416,6 @@
} }
} catch (error) { } catch (error) {
uni.hideLoading(); uni.hideLoading();
console.error('提交审核失败:', error);
uni.showToast({ uni.showToast({
title: '提交失败,请重试', title: '提交失败,请重试',
icon: 'none' icon: 'none'
@ -492,106 +423,66 @@
} }
}, },
//
formatDateForBackend(dateStr) {
if (!dateStr) return '';
if (dateStr === '长久有效' || dateStr === '长久有效') return '';
// YYYY-MM-DD
const match = dateStr.match(/(\d+)年(\d+)月(\d+)日/);
if (match) {
const year = match[1];
const month = match[2].padStart(2, '0');
const day = match[3].padStart(2, '0');
return `${year}-${month}-${day}`;
}
// YYYY-MM-DD
return dateStr;
},
// //
buildBusinessData(qualificationData, storeData) { buildBusinessData(qualificationData, storeData) {
// qualificationData = qualificationData || {};
storeData = storeData || {};
console.log(qualificationData, 'storeDatastoreDatastoreData');
const formData = {}; const formData = {};
Object.assign(formData, storeData);
// -
if (storeData && storeData.servers_kill && storeData.servers_kill.length > 0) {
// servers_kill
formData.servers_kill = Array.isArray(storeData.servers_kill) ?
storeData.servers_kill : [storeData.servers_kill];
console.log('服务技能数组:', formData.servers_kill);
} else {
console.warn('警告:没有服务技能数据');
formData.servers_kill = [];
}
//
if (qualificationData.uscc_type) { if (qualificationData.uscc_type) {
formData.uscc_type = qualificationData.uscc_type === 'individual' ? 1 : 2; formData.uscc_type = qualificationData.uscc_type;
} }
if (qualificationData.uscc_photo) { // if (qualificationData.contact_identity) {
formData.uscc_photo = qualificationData.uscc_photo; // formData.contact_identity = qualificationData.contact_identity;
// }
// if (qualificationData.contact_name) {
// formData.contact_name = qualificationData.contact_name;
// }
if (qualificationData.contact_phone) {
formData.contact_phone = qualificationData.contact_phone;
} }
if (qualificationData.uscc_num) { if (qualificationData.backup_phone) {
formData.uscc_num = qualificationData.uscc_num; formData.backup_phone = qualificationData.backup_phone;
} }
if (qualificationData.uscc_name) { if (qualificationData.contact_type) {
formData.uscc_name = qualificationData.uscc_name; formData.contact_type = qualificationData.contact_type;
} }
if (qualificationData.license_valid_type) { if (qualificationData.invite_code_other) {
formData.uscc_expiry_type = qualificationData.license_valid_type === 'permanent' ? 1 : 2; formData.invite_code_other = qualificationData.invite_code_other;
}
if (qualificationData.contact_name) {
formData.contact_name = qualificationData.contact_name;
} }
// if (qualificationData.dependency) {
if (qualificationData.license_start_date) { formData.dependency = qualificationData.dependency;
const startDate = this.formatDateForBackend(qualificationData.license_start_date); }
if (qualificationData.dependency_code) {
formData.dependency_code = qualificationData.dependency_code;
}
if (qualificationData.dependency_province) {
formData.dependency_province = qualificationData.dependency_province;
}
if (qualificationData.dependency_city) {
formData.dependency_city = qualificationData.dependency_city;
}
if (qualificationData.name) {
formData.name = qualificationData.name;
}
if (qualificationData.address) {
formData.address = qualificationData.address;
}
if (qualificationData.longitude) formData.longitude = qualificationData.longitude;
if (qualificationData.latitude) formData.latitude = qualificationData.latitude;
if (qualificationData.license_valid_type === 'permanent') { // if (storeData && storeData.servers_kill && storeData.servers_kill.length > 0) {
// + " " // // formData.servers_kill = Array.isArray(storeData.servers_kill) ?
formData.uscc_expiry = `${startDate} —— `; // // storeData.servers_kill : [storeData.servers_kill];
} else if (qualificationData.license_end_date) { // } else {
// + " " + // formData.servers_kill = [];
const endDate = this.formatDateForBackend(qualificationData.license_end_date); // }
formData.uscc_expiry = `${startDate} —— ${endDate}`;
}
}
//
if (qualificationData.legal_name) {
formData.legal_name = qualificationData.legal_name;
}
if (qualificationData.legal_phone) {
formData.legal_phone = qualificationData.legal_phone;
}
if (qualificationData.legal_idcard_num) {
formData.legal_idcard_num = qualificationData.legal_idcard_num;
}
if (qualificationData.legal_idcard_expiry_type) {
formData.legal_idcard_expiry_type = qualificationData.legal_idcard_expiry_type === 'permanent' ? 1 : 2;
}
//
if (qualificationData.idcard_start_date) {
const idcardStartDate = this.formatDateForBackend(qualificationData.idcard_start_date);
if (qualificationData.legal_idcard_expiry_type === 'permanent') {
formData.legal_idcard_expiry = `${idcardStartDate} —— `;
} else if (qualificationData.idcard_end_date) {
const idcardEndDate = this.formatDateForBackend(qualificationData.idcard_end_date);
formData.legal_idcard_expiry = `${idcardStartDate} —— ${idcardEndDate}`;
}
}
if (qualificationData.legal_idcard_positive) {
formData.legal_idcard_positive = qualificationData.legal_idcard_positive;
}
if (qualificationData.legal_idcard_negative) {
formData.legal_idcard_negative = qualificationData.legal_idcard_negative;
}
//
if (storeData.head_photo) { if (storeData.head_photo) {
formData.head_photo = storeData.head_photo; formData.head_photo = storeData.head_photo;
} }
@ -601,65 +492,23 @@
if (storeData.business_time) { if (storeData.business_time) {
formData.business_time = storeData.business_time; formData.business_time = storeData.business_time;
} }
if (storeData.servers_kill && storeData.servers_kill.length > 0) {
//
formData.servers_kill = storeData.servers_kill;
console.log('服务技能数组:', formData.servers_kill);
} else {
formData.servers_kill = [];
console.warn('警告:没有服务技能数据');
}
console.log('最终 formData 中的 servers_kill:', formData.servers_kill);
console.log('=== 调试结束 ===');
if (storeData.dependency) {
formData.dependency = storeData.dependency;
//
if (storeData.dependency_code) {
formData.dependency_code = storeData.dependency_code;
}
if (storeData.dependency_province) {
formData.dependency_province = storeData.dependency_province;
}
if (storeData.dependency_city) {
formData.dependency_city = storeData.dependency_city;
}
}
if (storeData.address) {
formData.address = storeData.address;
}
//
if (storeData.longitude) formData.longitude = storeData.longitude;
if (storeData.latitude) formData.latitude = storeData.latitude;
//
if (storeData.apply_state) { if (storeData.apply_state) {
formData.get_msg_method = storeData.apply_state; formData.get_msg_method = storeData.apply_state;
} }
if (storeData.invite_code_other) {
formData.invite_code_other = storeData.invite_code_other;
}
if (storeData.major) { if (storeData.major) {
formData.major = storeData.major; formData.major = storeData.major;
} }
// -
// 使 qualificationData storeData
const userInfo = uni.getStorageSync('userInfo');
const userInfo = uni.getStorageSync('userInfo');
if (userInfo && userInfo.account) { if (userInfo && userInfo.account) {
formData.account = userInfo.account; formData.account = userInfo.account;
} else { } else {
//
const loginAccount = uni.getStorageSync('loginAccount'); const loginAccount = uni.getStorageSync('loginAccount');
if (loginAccount) { if (loginAccount) {
formData.account = loginAccount; formData.account = loginAccount;
} else { } else if (qualificationData.contact_phone) {
// formData.contact_name = qualificationData.contact_name;
if (qualificationData.legal_phone) {
formData.account = qualificationData.legal_phone;
} else { } else {
console.error('无法获取账号信息'); console.error('无法获取账号信息');
uni.showToast({ uni.showToast({
@ -669,18 +518,12 @@
return null; return null;
} }
} }
}
console.log('使用的账号:', formData.account);
return formData; return formData;
}, },
async goNext() { async goNext() {
console.log('当前步骤:', this.currentStep);
console.log('身份类型:', this.identity);
// 0
if (this.currentStep === 0 && !this.isAgree) { if (this.currentStep === 0 && !this.isAgree) {
uni.showToast({ uni.showToast({
title: '请阅读并同意以上协议', title: '请阅读并同意以上协议',
@ -689,61 +532,92 @@
return; return;
} }
// 1
if (this.currentStep === 1) { if (this.currentStep === 1) {
console.log('商家验证资质信息');
//
if (this.$refs.qualificationInfo) { if (this.$refs.qualificationInfo) {
const isValid = await this.$refs.qualificationInfo.saveFormData(); const isValid = await this.$refs.qualificationInfo.saveFormData();
if (!isValid) { if (!isValid) {
console.log('商家资质信息验证失败');
return; return;
} }
this.qualificationData = this.$refs.qualificationInfo.getFormData(); this.qualificationData = this.$refs.qualificationInfo.getFormData();
console.log(' 商家资质信息验证通过 ');
} }
} await this.submitForReview();
// 2
if (this.currentStep === 2) {
//
if (this.$refs.storeInfo) {
const isValid = await this.$refs.storeInfo.saveFormData();
if (!isValid) {
console.log('商家门店信息验证失败');
return; return;
} }
this.storeInfoData = this.$refs.storeInfo.getFormData();
console.log('商家门店信息验证通过');
}
}
if (this.currentStep < 2) { if (this.currentStep < 3) {
this.currentStep++; this.currentStep++;
console.log('切换到步骤:', this.currentStep);
//
setTimeout(() => { setTimeout(() => {
this.scrollToTop(); this.scrollToTop();
}, 100); }, 100);
} else {
this.completeRegistration();
} }
}, },
submitApplication() { async submitApplication() {
//
if (this.$refs.storeInfo) { if (this.$refs.storeInfo) {
if (!this.$refs.storeInfo.saveFormData()) { // await
const isValid = await this.$refs.storeInfo.saveFormData();
if (!isValid) {
return; return;
} }
this.storeInfoData = this.$refs.storeInfo.getFormData(); this.storeInfoData = this.$refs.storeInfo.getFormData();
console.log('商家门店信息数据:', this.storeInfoData);
} }
// uni.showLoading({
this.completeRegistration(); title: '提交中...'
});
try {
const formData = this.buildBusinessData(this.qualificationData, this.storeInfoData);
if (!formData) {
uni.hideLoading();
return;
}
formData.type = 1;
formData.id_type = 1;
console.log(formData, '-----------');
if (formData.legal_idcard_expiry_start && formData.legal_idcard_expiry_end) {
formData.legal_idcard_expiry =
formData.legal_idcard_expiry_end === '长久有效' ?
`${formData.legal_idcard_expiry_start} —— 长久` :
`${formData.legal_idcard_expiry_start} —— ${formData.legal_idcard_expiry_end}`;
}
delete formData.legal_idcard_expiry_start
delete formData.legal_idcard_expiry_end
delete formData.contact_phone
delete formData.contact_type
delete formData.contact_name
delete formData.invite_code_other
if (Array.isArray(formData.qualifications_sector)) {
formData.qualifications_sector = JSON.stringify(formData.qualifications_sector);
}
if (Array.isArray(formData.qualifications_other)) {
formData.qualifications_other = JSON.stringify(formData.qualifications_other);
}
console.log(formData, 'formData请求参数');
const res = await request.post('/sj/userSjAuth/apply', formData);
uni.hideLoading();
if (res.state == 1 || res.code == 200) {
this.successData = res.data ? (res.data.customer_service || {}) : {};
uni.showToast({
title: '提交成功',
icon: 'none'
});
setTimeout(() => {
this.currentStep = 4;
}, 1500);
} else {
uni.showToast({
title: res.msg || '提交失败了',
icon: 'none'
});
}
} catch (error) {
console.error('提交失败:', error);
uni.hideLoading();
uni.showToast({
title: '提交失败,请重试',
icon: 'none'
});
}
}, },
goPrev() { goPrev() {
@ -751,11 +625,6 @@
this.currentStep--; this.currentStep--;
} }
}, },
completeRegistration() {
//
this.submitForReview();
},
//
scrollToTop() { scrollToTop() {
uni.pageScrollTo({ uni.pageScrollTo({
scrollTop: 0, scrollTop: 0,
@ -786,6 +655,7 @@
</script> </script>
<style> <style>
/* ...与原来一致的代码... */
.ruzhu-page { .ruzhu-page {
background: #f5f5f5; background: #f5f5f5;
} }
@ -842,7 +712,7 @@
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
background: linear-gradient(180deg, #f52540 0%, #e8101e 100%); background: #FF4767;
border-radius: 49rpx; border-radius: 49rpx;
} }
@ -867,7 +737,7 @@
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
background: linear-gradient(180deg, #f52540 0%, #e8101e 100%); background: #FF4767;
border-radius: 49rpx; border-radius: 49rpx;
} }
@ -884,7 +754,7 @@
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
background: linear-gradient(180deg, #f52540 0%, #e8101e 100%); background: linear-gradient(180deg, #ff8e9d 0%, #FF4767 100%);
border-radius: 49rpx; border-radius: 49rpx;
} }
@ -906,7 +776,7 @@
} }
.prev-text { .prev-text {
color: #E8101E; color: #FF4767;
font-size: 36rpx; font-size: 36rpx;
font-weight: 500; font-weight: 500;
} }
@ -957,4 +827,42 @@
font-size: 32rpx; font-size: 32rpx;
font-weight: 500; font-weight: 500;
} }
.showziliao {
width: 690rpx;
height: 98rpx;
background: #FF4767;
border-radius: 49rpx;
}
.showziliao1 {
width: 400rpx;
height: 98rpx;
background: #FF4767;
border-radius: 49rpx;
}
.showziliaotext {
height: 40rpx;
font-family: PingFangSC, PingFang SC;
font-weight: 500;
font-size: 32rpx;
color: #FFFFFF;
line-height: 96rpx;
font-style: normal;
margin: 0 0 0 281rpx;
align-items: center;
}
.showziliaotext1 {
height: 40rpx;
font-family: PingFangSC, PingFang SC;
font-weight: 500;
font-size: 32rpx;
color: #FFFFFF;
line-height: 96rpx;
font-style: normal;
margin: 0 0 0 140rpx;
align-items: center;
}
</style> </style>

File diff suppressed because it is too large Load Diff

View File

@ -73,7 +73,7 @@
} }
.btn-wallet { .btn-wallet {
font-size: 24rpx; font-size: 24rpx;
color: #E8101E; color: #FF4767;
margin-top: 40rpx; margin-top: 40rpx;
} }
.btn-contact { .btn-contact {

View File

@ -135,31 +135,30 @@ export default {
return; return;
} }
// type request.post('/sj/userSjAuth/details', {
let type; type: this.identity // 1=2=
if (this.identity == 1) { }).then(result => {
type = 2; // console.log('申请详情接口返回数据:', result);
} else if (this.identity == 2) { if (result.code === 200) {
type = 3; // if (result.data) {
} else { if (result.data.back_text) {
console.error('未知的用户类型identity:', this.identity);
this.backMag = '用户类型错误,请联系客服';
return;
}
console.log('请求参数 type:', type);
request.post('/user/getuser', {type}).then(result => {
console.log('接口返回数据:', result);
if (result.data && result.data.back_text) {
this.backMag = result.data.back_text; this.backMag = result.data.back_text;
console.log('设置backMag为:', this.backMag); console.log('设置backMag为:', this.backMag);
} else { } else {
this.backMag = '未知原因,请联系客服'; this.backMag = '未知原因,请联系客服';
console.log('接口返回无back_text字段'); console.log('接口返回无back_text字段');
} }
} else {
//
console.log('接口返回成功但data为空');
this.backMag = '暂无驳回原因信息';
}
} else {
this.backMag = '获取驳回原因失败,请联系客服';
console.log('接口返回错误:', result?.msg || '未知错误');
}
}).catch(err => { }).catch(err => {
console.error('获取用户信息失败:', err); console.error('获取申请详情失败:', err);
this.backMag = '获取驳回原因失败,请联系客服'; this.backMag = '获取驳回原因失败,请联系客服';
}).finally(() => { }).finally(() => {
console.log('getUserInfo执行完成'); console.log('getUserInfo执行完成');
@ -248,7 +247,7 @@ export default {
.btn-back { .btn-back {
width: 630rpx; width: 630rpx;
height: 96rpx; height: 96rpx;
background: #E8101E; background: #FF4767;
border-radius: 48rpx; border-radius: 48rpx;
display: flex; display: flex;
align-items: center; align-items: center;
@ -268,11 +267,11 @@ export default {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
border: 1rpx solid #E8101E; border: 1rpx solid #FF4767;
margin-top: 32rpx; margin-top: 32rpx;
} }
.fail-back-btn .btn-text { .fail-back-btn .btn-text {
color: #E8101E; color: #FF4767;
} }
.submitres-page /deep/ .back-btn { .submitres-page /deep/ .back-btn {

View File

@ -0,0 +1,131 @@
<template>
<view class="pages">
<custom-navbar :title="infoData.top" :showBack="true"></custom-navbar>
<view class="title-icon">{{ infoData.title }}</view>
<view class="title-content">{{ infoData.notice }}</view>
<view class="erweimabox">
<view class="erweimab">
<image :src="infoData.photo" mode="widthFix"
style="width: 404rpx;border-radius:25rpx ;margin: 37rpx 0 0 36rpx;"></image>
</view>
<view class="kefubtn">扫码联系专属客服</view>
</view>
</view>
</template>
<script>
import request from '../../utils/request';
export default {
props: {
data: {
type: Object,
default: () => ({})
}
},
data() {
return {
infoData: {}
}
},
mounted() {
this.getCustomerService();
},
methods: {
async getCustomerService() {
try {
const res = await request.post('/sj/userSjAuth/getCustomerService');
console.log('客服接口返回:', res);
if (res && (res.state == 1 || res.code == 200)) {
if (res.data.state != 3) {
this.infoData = res.data || {};
} else {
this.infoData = {
top: '审核结果',
title: '审核未通过',
photo: res.data.photo
};
this.$emit('stateChange', 3);
request.post('/sj/userSjAuth/details', {
type: 1
}).then(res => {
if (res && (res.state == 1 || res.code == 200)) {
console.log(res.data.back_text, '驳回res')
this.infoData = {
...this.infoData,
notice: res.data.back_text || '您的入驻申请未通过,请重新提交申请'
};
}
})
}
}
} catch (e) {
console.error('获取客服信息失败:', e);
}
}
}
}
</script>
<style>
.kefubtn {
height: 42rpx;
font-family: PingFangSC, PingFang SC;
font-weight: 400;
font-size: 30rpx;
color: #5A5A5A;
line-height: 42rpx;
text-align: center;
font-style: normal;
margin-top: 23rpx;
}
.pages {
background-image: url('https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/467f6b5f-32dc-4ba3-847a-22be4569c45e.png');
background-size: 100%;
background-repeat: no-repeat;
}
.erweimab {
margin: 70rpx 0 0 103rpx;
width: 477rpx;
height: 477rpx;
background-image: url('https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/e5461570-10e3-4e11-a6ca-8543f106639a.png');
background-size: 100%;
background-repeat: no-repeat;
}
.erweimabox {
margin: 71rpx 0 0 6rpx;
width: 690rpx;
height: 690rpx;
background: #FFFFFF;
border-radius: 62rpx;
border: 1rpx solid #F2F4F6;
}
.title-icon {
/* margin-left: 283rpx; */
height: 67rpx;
font-family: PingFangSC, PingFang SC;
font-weight: 500;
font-size: 48rpx;
color: #333333;
line-height: 67rpx;
text-align: center;
font-style: normal;
margin-top: -40rpx;
}
.title-content {
margin: 14rpx 0 0 0rpx;
height: 42rpx;
font-family: PingFangSC, PingFang SC;
font-weight: 400;
font-size: 30rpx;
color: #666666;
line-height: 42rpx;
text-align: center;
font-style: normal;
}
</style>

View File

@ -116,6 +116,6 @@ export default {
} }
.delete { .delete {
color: #e8101e; color: #FF4767;
} }
</style> </style>

View File

@ -279,10 +279,10 @@
getIconColor(index) { getIconColor(index) {
if (this.activeIndex === index) { if (this.activeIndex === index) {
return '#E8101E'; return '#FF4767';
} }
if (this.hasValue(this.filterTabs[index].key)) { if (this.hasValue(this.filterTabs[index].key)) {
return '#E8101E'; return '#FF4767';
} }
return '#666'; return '#666';
}, },
@ -527,7 +527,7 @@
} }
&.active { &.active {
color: #E8101E; color: #FF4767;
} }
.check-icon { .check-icon {
@ -567,7 +567,7 @@
} }
&.active { &.active {
background: #FFECF0; background: #FFECF0;
color: #E8101E; color: #FF4767;
} }
} }
@ -620,7 +620,7 @@
height: 100%; height: 100%;
.custom-price-container.active & { .custom-price-container.active & {
color: #E8101E; color: #FF4767;
} }
} }

View File

@ -192,7 +192,7 @@ export default {
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
background: linear-gradient(306deg, #e8101e 0%, #fc563b 100%); background: linear-gradient(306deg, #FF4767 0%, #fc563b 100%);
background-size: cover; background-size: cover;
color: #fff; color: #fff;
font-size: 26rpx; font-size: 26rpx;

Some files were not shown because too many files have changed in this diff Show More