Compare commits
No commits in common. "96f2ee15eb109a86c9d6446a2c989bcd9c5e4f9b" and "f354db835f0936ac2d0b20dddfefd173c62b5c0d" have entirely different histories.
96f2ee15eb
...
f354db835f
@ -1,26 +0,0 @@
|
||||
export const apiArr = {
|
||||
// 到家服务
|
||||
categoryList: "/api/v2/wechat/service/category/list", // 服务分类列表
|
||||
serviceList: "/api/v2/wechat/service/list", // 服务商品列表
|
||||
serviceInfo: "/api/v2/wechat/service/info", // 服务详情(含SKU+师傅)
|
||||
orderCreate: "/api/v2/wechat/service/order/create", // 下单(定金单)
|
||||
orderList: "/api/v2/wechat/service/order/list", // 我的服务订单列表
|
||||
orderInfo: "/api/v2/wechat/service/order/info", // 服务订单详情
|
||||
orderCancel: "/api/v2/wechat/service/order/cancel", // 取消服务订单
|
||||
preorder: "/api/v2/wechat/service/order/preorder", // 预下单(拉卡拉)
|
||||
tradeQuery: "/api/v2/wechat/service/order/trade-query", // 查单
|
||||
// 师傅端
|
||||
workerOrderList: "/api/v2/wechat/service/worker/order-list", // 师傅服务单列表
|
||||
workerOrderStatus: "/api/v2/wechat/service/worker/order-status", // 师傅更新状态
|
||||
workerExtraOrder: "/api/v2/wechat/service/worker/extra-order", // 师傅代客补差单
|
||||
workerMyInfo: "/api/v2/wechat/service/worker/my-info", // 解析当前用户的师傅信息
|
||||
// 家政合同(客户端)
|
||||
contractList: "/api/v2/wechat/service/contract/list", // 我的家政合同列表
|
||||
contractInfo: "/api/v2/wechat/service/contract/info", // 家政合同详情
|
||||
// 月账单
|
||||
workerMonthlyBillList: "/api/v2/wechat/service/worker/monthly-bill-list", // 师傅月账单列表
|
||||
workerPushBill: "/api/v2/wechat/service/worker/push-bill", // 师傅推送/拒绝月账单
|
||||
userMonthlyBillList: "/api/v2/wechat/service/user/monthly-bill-list", // 用户月账单列表
|
||||
userMonthlyBillPreOrder: "/api/v2/wechat/service/user/monthly-bill/preorder", // 用户月账单预下单
|
||||
userMonthlyBillTradeQuery: "/api/v2/wechat/service/user/monthly-bill/trade-query", // 用户月账单查单
|
||||
}
|
||||
@ -2,7 +2,6 @@ export const apiArr = {
|
||||
getCateList: "/api/v2/wechat/merchant-cate-crud/list", //商家分类列表
|
||||
getMerchantList: "/api/v2/wechat/merchant-info-crud/page", //商家列表
|
||||
getHomeBanner: "/api/v2/wechat/home-banner-region-crud/page", //获取首页banner及其广告
|
||||
getHomeBannerMulti: "/api/v2/wechat/home-banner-region-crud/multi", //按广告位批量获取首页广告(一次返回多个 ad_position)
|
||||
getButtonNum:"/api/v2/wechat/nav-display-crud/info",//获取首页button的行数 数量
|
||||
getHomeButton:"/api/v2/wechat/home-button-region-crud/page", //获取首页button
|
||||
|
||||
|
||||
@ -3,7 +3,6 @@ export const apiArr = {
|
||||
getMerchantList:"/api/v2/wechat/merchant-info-crud/page",//商家列表
|
||||
createComment:"/api/v2/wechat/merchant-evaluation-crud/creat",//创建用户评价
|
||||
getMerchantInfo:"/api/v2/wechat/merchant-info-crud/info",//获取商家信息详情
|
||||
getShopActivityList:"/api/v2/wechat/commodity/shop-activity/list",//好店详情页-店铺活动商品列表
|
||||
getMerchantComment:"/api/v2/wechat/merchant-evaluation-crud/page",//获取商家评价
|
||||
merChantCommentLike:"/api/v2/wechat/merchant-evaluation-like-crud/creat",//点赞
|
||||
merChantCommentUnlike:"/api/v2/wechat/merchant-evaluation-like-crud/del",//取消点赞
|
||||
@ -27,5 +26,4 @@ export const apiArr = {
|
||||
|
||||
|
||||
createStore:"/api/v2/wechat/store-info-crud/creat",//门店信息创建
|
||||
ocrRecognize:"/api/v1/wechat/oss/ocr-recognize",//证件 OCR 自动识别
|
||||
};
|
||||
|
||||
@ -1,107 +0,0 @@
|
||||
<template>
|
||||
<view class="private-image">
|
||||
<image v-if="signedUrl" :src="signedUrl" :mode="mode" :style="{ width: width, height: height }"
|
||||
@click="onClick" @error="onError" />
|
||||
<view v-else-if="loading" class="ph">加载中…</view>
|
||||
<view v-else-if="error" class="ph err">{{ error }}</view>
|
||||
<view v-else-if="!path" class="ph">未上传</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// PrivateImage —— 私密文件查看(小程序,商家本人)
|
||||
//
|
||||
// 用法:
|
||||
// <PrivateImage :path="form.id_card_front" width="200rpx" height="120rpx" />
|
||||
//
|
||||
// 不传 targetUserId —— 服务端会校验 object key 必须属于当前登录用户
|
||||
import {
|
||||
signPrivateView
|
||||
} from '@/utils/uploadOSS.js'
|
||||
|
||||
export default {
|
||||
name: 'PrivateImage',
|
||||
props: {
|
||||
path: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
width: {
|
||||
type: String,
|
||||
default: '200rpx'
|
||||
},
|
||||
height: {
|
||||
type: String,
|
||||
default: '120rpx'
|
||||
},
|
||||
mode: {
|
||||
type: String,
|
||||
default: 'aspectFill'
|
||||
},
|
||||
// mount 立即签发;click 点击才签
|
||||
trigger: {
|
||||
type: String,
|
||||
default: 'mount'
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
signedUrl: '',
|
||||
loading: false,
|
||||
error: ''
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
path: {
|
||||
immediate: true,
|
||||
handler(v) {
|
||||
if (v && this.trigger === 'mount') this.fetch()
|
||||
else this.signedUrl = ''
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async fetch() {
|
||||
if (!this.path) return
|
||||
this.loading = true
|
||||
this.error = ''
|
||||
try {
|
||||
const res = await signPrivateView(this.path)
|
||||
this.signedUrl = res.url
|
||||
} catch (e) {
|
||||
this.error = e.message || '加载失败'
|
||||
} finally {
|
||||
this.loading = false
|
||||
}
|
||||
},
|
||||
onClick() {
|
||||
if (this.signedUrl) {
|
||||
uni.previewImage({
|
||||
urls: [this.signedUrl]
|
||||
})
|
||||
} else if (this.trigger === 'click') {
|
||||
this.fetch()
|
||||
}
|
||||
},
|
||||
onError() {
|
||||
this.error = '图片加载失败'
|
||||
this.signedUrl = ''
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.private-image .ph {
|
||||
display: inline-block;
|
||||
text-align: center;
|
||||
color: #999;
|
||||
font-size: 22rpx;
|
||||
padding: 16rpx;
|
||||
border: 2rpx dashed #ccc;
|
||||
}
|
||||
|
||||
.private-image .ph.err {
|
||||
color: #f56c6c;
|
||||
}
|
||||
</style>
|
||||
@ -167,12 +167,10 @@ export default {
|
||||
// 解析path字段,提取scene参数的值
|
||||
const pathParts = res.path.split('?');
|
||||
if (pathParts.length > 1) {
|
||||
if (pathParts[1].startsWith('scene=')){
|
||||
const pathPart = decodeURIComponent(pathParts[1].substring(6))
|
||||
const queryParams = pathPart.split('&');
|
||||
const queryParams = pathParts[1].split('&');
|
||||
for (const param of queryParams) {
|
||||
const [key, value] = param.split('=');
|
||||
if (key === 'id') {
|
||||
if (key === 'scene') {
|
||||
const params = {
|
||||
id: value
|
||||
}
|
||||
@ -183,7 +181,6 @@ export default {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
fail: (err) => {
|
||||
console.log('扫码失败:', err);
|
||||
|
||||
@ -1,84 +0,0 @@
|
||||
# 首页 Banner / 广告位 跳转现状梳理
|
||||
|
||||
> 状态:现状分析(仅梳理,代码未改)。日期:2026-06-03
|
||||
> 范围:小程序 `pages/index/index.vue` 首页各广告位的点击跳转逻辑,对照后端配置。
|
||||
|
||||
---
|
||||
|
||||
## 一、后端是怎么配置跳转的
|
||||
|
||||
每条 banner/广告(表 `home_banner_region`)、金刚位(表 `home_button_region`)都有统一的跳转配置字段,核心是 **`promotion_type`(推广类型)**:
|
||||
|
||||
| promotion_type | 含义 | 配套字段 |
|
||||
|---|---|---|
|
||||
| 1 | 无跳转 | — |
|
||||
| 2 | 选择活动 | 关联 `advertisement_goods`(按 banner id) |
|
||||
| 3 | 跳转本程序页面 | `link_url` |
|
||||
| 4 | 跳转其他小程序 | `appid` + `link_url` |
|
||||
| 5 | 选择商品 | `advertisement_goods[].goods_id` |
|
||||
|
||||
- 后台创建/编辑接口(`api/admin/v2/crud_home_banner_region.go`)用 `promotion_type` + `required-if` 校验对应字段,例如 type=4 必填 appid、type=3/4 必填 link_url。
|
||||
- `home_button_region`(金刚位)字段相同,也有 `promotion_type` / `link_url` / `appid`。
|
||||
- type=2/5 的落地:`/packages/advertising/index/index?id=<banner.id>` 是“广告聚合落地页”,传 banner 自身 id 进去,页面内部拉该 banner 关联的 `advertisement_goods` 商品列表展示,并可进入 `goodsDetail`。
|
||||
|
||||
---
|
||||
|
||||
## 二、前端实际怎么跳的(问题所在)
|
||||
|
||||
首页有 4 个不同的点击处理函数各管一片,**几乎都没读 `promotion_type`**:
|
||||
|
||||
### 1. `headerServerClick`(金刚位 tabList、homeLeftList 用)
|
||||
- 文件:`pages/index/index.vue`(搜 `headerServerClick(e)`)
|
||||
- 只看 `link_url` 和 `appid`,**完全忽略 `promotion_type`**。
|
||||
- 逻辑:无 `link_url` → 弹“此功能暂未开通”;有 `appid` → 跳小程序;否则当本程序路径 `NavgateTo`。
|
||||
- **后果**:type=2(活动)、type=5(商品)的配置它不认 → 落到“没 link_url”分支 → 弹“暂未开通”。
|
||||
|
||||
### 2. `toAdvertisingView`(广告横幅 serverLeft、serverRight[0] 用)
|
||||
- 文件:`pages/index/index.vue:357` 附近
|
||||
- **写死**跳 `/packages/advertising/index/index?id=xxx`,不看 `promotion_type`,一律进广告落地页。
|
||||
|
||||
### 3. `goToPurify`(serverRight 非首个用,模板 `index.vue:101`)
|
||||
- 文件:`pages/index/index.vue:363` 附近
|
||||
- **彻底写死**:固定跳净水小程序 `appId=wx77b22c0a0018e580`,path/appId 全硬编码,传入的 `item` 没用到,与后台配置零关系。
|
||||
- 模板:`@tap="index === 0 ? toAdvertisingView(serverRightList) : goToPurify(item)"` —— serverRight 第一个跳广告页,其余全跳净水小程序。
|
||||
|
||||
### 4. `headerServerClick2`(中部 serverItem / homeRightList1,2 用)
|
||||
- 文件:`pages/index/index.vue`(搜 `headerServerClick2(e)`)
|
||||
- 不跳外链,只按 `title` 匹配商家分类做筛选,或固定跳本地生活页。**注意:这一处可能是“按分类筛选”的有意设计,不一定算 bug。**
|
||||
|
||||
### 5. 顶部轮播 Banner(位置 1,模板 `index.vue:68`)
|
||||
- 点击事件被**注释掉了**(`<!-- <swiper-item ... @click="headerServerClick(item)"> -->`),顶部 banner 现在点击无反应。
|
||||
|
||||
---
|
||||
|
||||
## 三、根因
|
||||
|
||||
后台用统一的 `promotion_type` 模型配跳转,前端却是早期“按位置分别写死”的处理函数拼起来的:既没统一读 `promotion_type`,部分位置还硬编码了目标(广告页、净水小程序)。所以出现“很多跳转和后台配置不符”——不是数据错,是前端没按配置解析。
|
||||
|
||||
---
|
||||
|
||||
## 四、建议修法(未实施,待决策)
|
||||
|
||||
做一个统一跳转函数 `handleAdJump(item)`,严格按 `promotion_type` 分发:
|
||||
|
||||
```
|
||||
switch promotion_type:
|
||||
1: 不跳
|
||||
2: NavgateTo('/packages/advertising/index/index?id=' + item.id) // 活动
|
||||
3: link_url 跳本程序页面(兼容 shopEnter 特例 / H5 / APP webview)
|
||||
4: navigateToMiniProgram(appid, link_url) // 其他小程序
|
||||
5: NavgateTo('/packages/advertising/index/index?id=' + item.id) // 商品(同活动,落地页内展示)
|
||||
其他: 弹“暂未开通”
|
||||
```
|
||||
|
||||
然后把首页所有广告位的 `@click`/`@tap` 都换成 `handleAdJump(item)`:
|
||||
- 顶部轮播 banner:取消注释,改 `handleAdJump`
|
||||
- 金刚位 tabList、homeLeftList:`headerServerClick` → `handleAdJump`
|
||||
- serverLeft、serverRight:`toAdvertisingView` / `goToPurify` → `handleAdJump`
|
||||
|
||||
### 实施前需确认的点
|
||||
1. `headerServerClick2`(中部 serverItem 按 title 筛分类)是否要保留分类筛选语义?还是也改成按 `promotion_type` 跳?
|
||||
2. 净水小程序跳转:是想**保留写死**,还是改由后台某条 banner 配 `type=4 + 该 appid` 来控制(更灵活,去掉硬编码)?
|
||||
3. type=2/5 是否都统一进广告落地页 `/packages/advertising/index/index?id=banner.id`(当前分析结论是“是”)。
|
||||
|
||||
> 相关:`promotion_type` 字段定义见 `huichang-server/internal/model/entity/home_banner_region.go`、`home_button_region.go`;广告落地页 `uniapp-ZHSQ/packages/advertising/index/index.vue`。
|
||||
32
main.js
32
main.js
@ -10,22 +10,6 @@ Vue.config.productionTip = false
|
||||
import uView from 'uni_modules/uview-ui';
|
||||
Vue.use(uView);
|
||||
|
||||
// 全局分享 mixin - 所有页面默认开启分享到微信好友和朋友圈
|
||||
Vue.mixin({
|
||||
onShareAppMessage() {
|
||||
return {
|
||||
title: '汇商生活家',
|
||||
path: '/pages/index/index'
|
||||
}
|
||||
},
|
||||
onShareTimeline() {
|
||||
return {
|
||||
title: '汇商生活家',
|
||||
query: ''
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
// 导入工具函数
|
||||
import { processImageUrl } from './utils/index.js'
|
||||
|
||||
@ -55,22 +39,6 @@ const app = createApp(App)
|
||||
// 安装 uView
|
||||
app.use(uView)
|
||||
|
||||
// 全局分享 mixin - 所有页面默认开启分享到微信好友和朋友圈
|
||||
app.mixin({
|
||||
onShareAppMessage() {
|
||||
return {
|
||||
title: '汇商生活家',
|
||||
path: '/pages/index/index'
|
||||
}
|
||||
},
|
||||
onShareTimeline() {
|
||||
return {
|
||||
title: '汇商生活家',
|
||||
query: ''
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
// 导入工具函数
|
||||
import { processImageUrl } from './utils/index.js'
|
||||
|
||||
|
||||
839
package-lock.json
generated
839
package-lock.json
generated
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "支付键盘、数字键盘、付款键盘、密码键盘",
|
||||
"version": "1.0.1",
|
||||
"lockfileVersion": 2,
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
@ -1168,842 +1168,5 @@
|
||||
"node": ">=0.4"
|
||||
}
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/helper-string-parser": {
|
||||
"version": "7.27.1",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz",
|
||||
"integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="
|
||||
},
|
||||
"@babel/helper-validator-identifier": {
|
||||
"version": "7.27.1",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz",
|
||||
"integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow=="
|
||||
},
|
||||
"@babel/parser": {
|
||||
"version": "7.28.4",
|
||||
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.4.tgz",
|
||||
"integrity": "sha512-yZbBqeM6TkpP9du/I2pUZnJsRMGGvOuIrhjzC1AwHwW+6he4mni6Bp/m8ijn0iOuZuPI2BfkCoSRunpyjnrQKg==",
|
||||
"requires": {
|
||||
"@babel/types": "^7.28.4"
|
||||
}
|
||||
},
|
||||
"@babel/types": {
|
||||
"version": "7.28.4",
|
||||
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.4.tgz",
|
||||
"integrity": "sha512-bkFqkLhh3pMBUQQkpVgWDWq/lqzc2678eUyDlTBhRqhCHFguYYGM0Efga7tYk4TogG/3x0EEl66/OQ+WGbWB/Q==",
|
||||
"requires": {
|
||||
"@babel/helper-string-parser": "^7.27.1",
|
||||
"@babel/helper-validator-identifier": "^7.27.1"
|
||||
}
|
||||
},
|
||||
"@jridgewell/sourcemap-codec": {
|
||||
"version": "1.5.5",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
|
||||
"integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og=="
|
||||
},
|
||||
"@vue/compiler-core": {
|
||||
"version": "3.5.21",
|
||||
"resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.21.tgz",
|
||||
"integrity": "sha512-8i+LZ0vf6ZgII5Z9XmUvrCyEzocvWT+TeR2VBUVlzIH6Tyv57E20mPZ1bCS+tbejgUgmjrEh7q/0F0bibskAmw==",
|
||||
"requires": {
|
||||
"@babel/parser": "^7.28.3",
|
||||
"@vue/shared": "3.5.21",
|
||||
"entities": "^4.5.0",
|
||||
"estree-walker": "^2.0.2",
|
||||
"source-map-js": "^1.2.1"
|
||||
}
|
||||
},
|
||||
"@vue/compiler-dom": {
|
||||
"version": "3.5.21",
|
||||
"resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.21.tgz",
|
||||
"integrity": "sha512-jNtbu/u97wiyEBJlJ9kmdw7tAr5Vy0Aj5CgQmo+6pxWNQhXZDPsRr1UWPN4v3Zf82s2H3kF51IbzZ4jMWAgPlQ==",
|
||||
"requires": {
|
||||
"@vue/compiler-core": "3.5.21",
|
||||
"@vue/shared": "3.5.21"
|
||||
}
|
||||
},
|
||||
"@vue/compiler-sfc": {
|
||||
"version": "3.5.21",
|
||||
"resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.21.tgz",
|
||||
"integrity": "sha512-SXlyk6I5eUGBd2v8Ie7tF6ADHE9kCR6mBEuPyH1nUZ0h6Xx6nZI29i12sJKQmzbDyr2tUHMhhTt51Z6blbkTTQ==",
|
||||
"requires": {
|
||||
"@babel/parser": "^7.28.3",
|
||||
"@vue/compiler-core": "3.5.21",
|
||||
"@vue/compiler-dom": "3.5.21",
|
||||
"@vue/compiler-ssr": "3.5.21",
|
||||
"@vue/shared": "3.5.21",
|
||||
"estree-walker": "^2.0.2",
|
||||
"magic-string": "^0.30.18",
|
||||
"postcss": "^8.5.6",
|
||||
"source-map-js": "^1.2.1"
|
||||
}
|
||||
},
|
||||
"@vue/compiler-ssr": {
|
||||
"version": "3.5.21",
|
||||
"resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.21.tgz",
|
||||
"integrity": "sha512-vKQ5olH5edFZdf5ZrlEgSO1j1DMA4u23TVK5XR1uMhvwnYvVdDF0nHXJUblL/GvzlShQbjhZZ2uvYmDlAbgo9w==",
|
||||
"requires": {
|
||||
"@vue/compiler-dom": "3.5.21",
|
||||
"@vue/shared": "3.5.21"
|
||||
}
|
||||
},
|
||||
"@vue/reactivity": {
|
||||
"version": "3.5.21",
|
||||
"resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.21.tgz",
|
||||
"integrity": "sha512-3ah7sa+Cwr9iiYEERt9JfZKPw4A2UlbY8RbbnH2mGCE8NwHkhmlZt2VsH0oDA3P08X3jJd29ohBDtX+TbD9AsA==",
|
||||
"requires": {
|
||||
"@vue/shared": "3.5.21"
|
||||
}
|
||||
},
|
||||
"@vue/runtime-core": {
|
||||
"version": "3.5.21",
|
||||
"resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.21.tgz",
|
||||
"integrity": "sha512-+DplQlRS4MXfIf9gfD1BOJpk5RSyGgGXD/R+cumhe8jdjUcq/qlxDawQlSI8hCKupBlvM+3eS1se5xW+SuNAwA==",
|
||||
"requires": {
|
||||
"@vue/reactivity": "3.5.21",
|
||||
"@vue/shared": "3.5.21"
|
||||
}
|
||||
},
|
||||
"@vue/runtime-dom": {
|
||||
"version": "3.5.21",
|
||||
"resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.21.tgz",
|
||||
"integrity": "sha512-3M2DZsOFwM5qI15wrMmNF5RJe1+ARijt2HM3TbzBbPSuBHOQpoidE+Pa+XEaVN+czbHf81ETRoG1ltztP2em8w==",
|
||||
"requires": {
|
||||
"@vue/reactivity": "3.5.21",
|
||||
"@vue/runtime-core": "3.5.21",
|
||||
"@vue/shared": "3.5.21",
|
||||
"csstype": "^3.1.3"
|
||||
}
|
||||
},
|
||||
"@vue/server-renderer": {
|
||||
"version": "3.5.21",
|
||||
"resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.21.tgz",
|
||||
"integrity": "sha512-qr8AqgD3DJPJcGvLcJKQo2tAc8OnXRcfxhOJCPF+fcfn5bBGz7VCcO7t+qETOPxpWK1mgysXvVT/j+xWaHeMWA==",
|
||||
"requires": {
|
||||
"@vue/compiler-ssr": "3.5.21",
|
||||
"@vue/shared": "3.5.21"
|
||||
}
|
||||
},
|
||||
"@vue/shared": {
|
||||
"version": "3.5.21",
|
||||
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.21.tgz",
|
||||
"integrity": "sha512-+2k1EQpnYuVuu3N7atWyG3/xoFWIVJZq4Mz8XNOdScFI0etES75fbny/oU4lKWk/577P1zmg0ioYvpGEDZ3DLw=="
|
||||
},
|
||||
"abort-controller": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz",
|
||||
"integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==",
|
||||
"requires": {
|
||||
"event-target-shim": "^5.0.0"
|
||||
}
|
||||
},
|
||||
"async-limiter": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz",
|
||||
"integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ=="
|
||||
},
|
||||
"balanced-match": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
|
||||
},
|
||||
"base64-js": {
|
||||
"version": "1.5.1",
|
||||
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
|
||||
"integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="
|
||||
},
|
||||
"bl": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
|
||||
"integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==",
|
||||
"requires": {
|
||||
"buffer": "^5.5.0",
|
||||
"inherits": "^2.0.4",
|
||||
"readable-stream": "^3.4.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"buffer": {
|
||||
"version": "5.7.1",
|
||||
"resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
|
||||
"integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
|
||||
"requires": {
|
||||
"base64-js": "^1.3.1",
|
||||
"ieee754": "^1.1.13"
|
||||
}
|
||||
},
|
||||
"readable-stream": {
|
||||
"version": "3.6.2",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
|
||||
"integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
|
||||
"requires": {
|
||||
"inherits": "^2.0.3",
|
||||
"string_decoder": "^1.1.1",
|
||||
"util-deprecate": "^1.0.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"brace-expansion": {
|
||||
"version": "1.1.12",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
|
||||
"integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
|
||||
"requires": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
}
|
||||
},
|
||||
"buffer": {
|
||||
"version": "6.0.3",
|
||||
"resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz",
|
||||
"integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==",
|
||||
"requires": {
|
||||
"base64-js": "^1.3.1",
|
||||
"ieee754": "^1.2.1"
|
||||
}
|
||||
},
|
||||
"buffer-from": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
|
||||
"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="
|
||||
},
|
||||
"callback-stream": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/callback-stream/-/callback-stream-1.1.0.tgz",
|
||||
"integrity": "sha512-sAZ9kODla+mGACBZ1IpTCAisKoGnv6PykW7fPk1LrM+mMepE18Yz0515yoVcrZy7dQsTUp3uZLQ/9Sx1RnLoHw==",
|
||||
"requires": {
|
||||
"inherits": "^2.0.1",
|
||||
"readable-stream": "> 1.0.0 < 3.0.0"
|
||||
}
|
||||
},
|
||||
"commist": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/commist/-/commist-1.1.0.tgz",
|
||||
"integrity": "sha512-rraC8NXWOEjhADbZe9QBNzLAN5Q3fsTPQtBV+fEVj6xKIgDgNiEVE6ZNfHpZOqfQ21YUzfVNUXLOEZquYvQPPg==",
|
||||
"requires": {
|
||||
"leven": "^2.1.0",
|
||||
"minimist": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"concat-map": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
|
||||
},
|
||||
"concat-stream": {
|
||||
"version": "1.6.2",
|
||||
"resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz",
|
||||
"integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==",
|
||||
"requires": {
|
||||
"buffer-from": "^1.0.0",
|
||||
"inherits": "^2.0.3",
|
||||
"readable-stream": "^2.2.2",
|
||||
"typedarray": "^0.0.6"
|
||||
}
|
||||
},
|
||||
"core-util-is": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
|
||||
"integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ=="
|
||||
},
|
||||
"csstype": {
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
|
||||
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="
|
||||
},
|
||||
"d": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/d/-/d-1.0.2.tgz",
|
||||
"integrity": "sha512-MOqHvMWF9/9MX6nza0KgvFH4HpMU0EF5uUDXqX/BtxtU8NfB0QzRtJ8Oe/6SuS4kbhyzVJwjd97EA4PKrzJ8bw==",
|
||||
"requires": {
|
||||
"es5-ext": "^0.10.64",
|
||||
"type": "^2.7.2"
|
||||
}
|
||||
},
|
||||
"debug": {
|
||||
"version": "4.4.3",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
|
||||
"integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
|
||||
"requires": {
|
||||
"ms": "^2.1.3"
|
||||
}
|
||||
},
|
||||
"duplexify": {
|
||||
"version": "3.7.1",
|
||||
"resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz",
|
||||
"integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==",
|
||||
"requires": {
|
||||
"end-of-stream": "^1.0.0",
|
||||
"inherits": "^2.0.1",
|
||||
"readable-stream": "^2.0.0",
|
||||
"stream-shift": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"end-of-stream": {
|
||||
"version": "1.4.5",
|
||||
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz",
|
||||
"integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==",
|
||||
"requires": {
|
||||
"once": "^1.4.0"
|
||||
}
|
||||
},
|
||||
"entities": {
|
||||
"version": "4.5.0",
|
||||
"resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
|
||||
"integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="
|
||||
},
|
||||
"es5-ext": {
|
||||
"version": "0.10.64",
|
||||
"resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.64.tgz",
|
||||
"integrity": "sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg==",
|
||||
"requires": {
|
||||
"es6-iterator": "^2.0.3",
|
||||
"es6-symbol": "^3.1.3",
|
||||
"esniff": "^2.0.1",
|
||||
"next-tick": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"es6-iterator": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz",
|
||||
"integrity": "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==",
|
||||
"requires": {
|
||||
"d": "1",
|
||||
"es5-ext": "^0.10.35",
|
||||
"es6-symbol": "^3.1.1"
|
||||
}
|
||||
},
|
||||
"es6-map": {
|
||||
"version": "0.1.5",
|
||||
"resolved": "https://registry.npmjs.org/es6-map/-/es6-map-0.1.5.tgz",
|
||||
"integrity": "sha512-mz3UqCh0uPCIqsw1SSAkB/p0rOzF/M0V++vyN7JqlPtSW/VsYgQBvVvqMLmfBuyMzTpLnNqi6JmcSizs4jy19A==",
|
||||
"requires": {
|
||||
"d": "1",
|
||||
"es5-ext": "~0.10.14",
|
||||
"es6-iterator": "~2.0.1",
|
||||
"es6-set": "~0.1.5",
|
||||
"es6-symbol": "~3.1.1",
|
||||
"event-emitter": "~0.3.5"
|
||||
}
|
||||
},
|
||||
"es6-set": {
|
||||
"version": "0.1.6",
|
||||
"resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.6.tgz",
|
||||
"integrity": "sha512-TE3LgGLDIBX332jq3ypv6bcOpkLO0AslAQo7p2VqX/1N46YNsvIWgvjojjSEnWEGWMhr1qUbYeTSir5J6mFHOw==",
|
||||
"requires": {
|
||||
"d": "^1.0.1",
|
||||
"es5-ext": "^0.10.62",
|
||||
"es6-iterator": "~2.0.3",
|
||||
"es6-symbol": "^3.1.3",
|
||||
"event-emitter": "^0.3.5",
|
||||
"type": "^2.7.2"
|
||||
}
|
||||
},
|
||||
"es6-symbol": {
|
||||
"version": "3.1.4",
|
||||
"resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.4.tgz",
|
||||
"integrity": "sha512-U9bFFjX8tFiATgtkJ1zg25+KviIXpgRvRHS8sau3GfhVzThRQrOeksPeT0BWW2MNZs1OEWJ1DPXOQMn0KKRkvg==",
|
||||
"requires": {
|
||||
"d": "^1.0.2",
|
||||
"ext": "^1.7.0"
|
||||
}
|
||||
},
|
||||
"esniff": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/esniff/-/esniff-2.0.1.tgz",
|
||||
"integrity": "sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg==",
|
||||
"requires": {
|
||||
"d": "^1.0.1",
|
||||
"es5-ext": "^0.10.62",
|
||||
"event-emitter": "^0.3.5",
|
||||
"type": "^2.7.2"
|
||||
}
|
||||
},
|
||||
"estree-walker": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
|
||||
"integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="
|
||||
},
|
||||
"event-emitter": {
|
||||
"version": "0.3.5",
|
||||
"resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz",
|
||||
"integrity": "sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==",
|
||||
"requires": {
|
||||
"d": "1",
|
||||
"es5-ext": "~0.10.14"
|
||||
}
|
||||
},
|
||||
"event-target-shim": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz",
|
||||
"integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ=="
|
||||
},
|
||||
"ext": {
|
||||
"version": "1.7.0",
|
||||
"resolved": "https://registry.npmjs.org/ext/-/ext-1.7.0.tgz",
|
||||
"integrity": "sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==",
|
||||
"requires": {
|
||||
"type": "^2.7.2"
|
||||
}
|
||||
},
|
||||
"extend": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
|
||||
"integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="
|
||||
},
|
||||
"fs.realpath": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
||||
"integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="
|
||||
},
|
||||
"glob": {
|
||||
"version": "7.2.3",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
|
||||
"integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
|
||||
"requires": {
|
||||
"fs.realpath": "^1.0.0",
|
||||
"inflight": "^1.0.4",
|
||||
"inherits": "2",
|
||||
"minimatch": "^3.1.1",
|
||||
"once": "^1.3.0",
|
||||
"path-is-absolute": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"glob-parent": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz",
|
||||
"integrity": "sha512-E8Ak/2+dZY6fnzlR7+ueWvhsH1SjHr4jjss4YS/h4py44jY9MhK/VFdaZJAWDz6BbL21KeteKxFSFpq8OS5gVA==",
|
||||
"requires": {
|
||||
"is-glob": "^3.1.0",
|
||||
"path-dirname": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"glob-stream": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-6.1.0.tgz",
|
||||
"integrity": "sha512-uMbLGAP3S2aDOHUDfdoYcdIePUCfysbAd0IAoWVZbeGU/oNQ8asHVSshLDJUPWxfzj8zsCG7/XeHPHTtow0nsw==",
|
||||
"requires": {
|
||||
"extend": "^3.0.0",
|
||||
"glob": "^7.1.1",
|
||||
"glob-parent": "^3.1.0",
|
||||
"is-negated-glob": "^1.0.0",
|
||||
"ordered-read-streams": "^1.0.0",
|
||||
"pumpify": "^1.3.5",
|
||||
"readable-stream": "^2.1.5",
|
||||
"remove-trailing-separator": "^1.0.1",
|
||||
"to-absolute-glob": "^2.0.0",
|
||||
"unique-stream": "^2.0.2"
|
||||
}
|
||||
},
|
||||
"help-me": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/help-me/-/help-me-1.1.0.tgz",
|
||||
"integrity": "sha512-P/IZ8yOMne3SCTHbVY429NZ67B/2bVQlcYGZh2iPPbdLrEQ/qY5aGChn0YTDmt7Sb4IKRI51fypItav+lNl76w==",
|
||||
"requires": {
|
||||
"callback-stream": "^1.0.2",
|
||||
"glob-stream": "^6.1.0",
|
||||
"through2": "^2.0.1",
|
||||
"xtend": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"ieee754": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
|
||||
"integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="
|
||||
},
|
||||
"inflight": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
|
||||
"integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
|
||||
"requires": {
|
||||
"once": "^1.3.0",
|
||||
"wrappy": "1"
|
||||
}
|
||||
},
|
||||
"inherits": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
|
||||
},
|
||||
"is-absolute": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz",
|
||||
"integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==",
|
||||
"requires": {
|
||||
"is-relative": "^1.0.0",
|
||||
"is-windows": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"is-extglob": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
|
||||
"integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="
|
||||
},
|
||||
"is-glob": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz",
|
||||
"integrity": "sha512-UFpDDrPgM6qpnFNI+rh/p3bUaq9hKLZN8bMUWzxmcnZVS3omf4IPK+BrewlnWjO1WmUsMYuSjKh4UJuV4+Lqmw==",
|
||||
"requires": {
|
||||
"is-extglob": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"is-negated-glob": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-negated-glob/-/is-negated-glob-1.0.0.tgz",
|
||||
"integrity": "sha512-czXVVn/QEmgvej1f50BZ648vUI+em0xqMq2Sn+QncCLN4zj1UAxlT+kw/6ggQTOaZPd1HqKQGEqbpQVtJucWug=="
|
||||
},
|
||||
"is-relative": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz",
|
||||
"integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==",
|
||||
"requires": {
|
||||
"is-unc-path": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"is-unc-path": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz",
|
||||
"integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==",
|
||||
"requires": {
|
||||
"unc-path-regex": "^0.1.2"
|
||||
}
|
||||
},
|
||||
"is-windows": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz",
|
||||
"integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA=="
|
||||
},
|
||||
"isarray": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
|
||||
"integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ=="
|
||||
},
|
||||
"json-stable-stringify-without-jsonify": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
|
||||
"integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw=="
|
||||
},
|
||||
"leven": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz",
|
||||
"integrity": "sha512-nvVPLpIHUxCUoRLrFqTgSxXJ614d8AgQoWl7zPe/2VadE8+1dpU3LBhowRuBAcuwruWtOdD8oYC9jDNJjXDPyA=="
|
||||
},
|
||||
"magic-string": {
|
||||
"version": "0.30.19",
|
||||
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.19.tgz",
|
||||
"integrity": "sha512-2N21sPY9Ws53PZvsEpVtNuSW+ScYbQdp4b9qUaL+9QkHUrGFKo56Lg9Emg5s9V/qrtNBmiR01sYhUOwu3H+VOw==",
|
||||
"requires": {
|
||||
"@jridgewell/sourcemap-codec": "^1.5.5"
|
||||
}
|
||||
},
|
||||
"minimatch": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
||||
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
|
||||
"requires": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
}
|
||||
},
|
||||
"minimist": {
|
||||
"version": "1.2.8",
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
|
||||
"integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="
|
||||
},
|
||||
"mqtt": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/mqtt/-/mqtt-3.0.0.tgz",
|
||||
"integrity": "sha512-0nKV6MAc1ibKZwaZQUTb3iIdT4NVpj541BsYrqrGBcQdQ7Jd0MnZD1/6/nj1UFdGTboK9ZEUXvkCu2nPCugHFA==",
|
||||
"requires": {
|
||||
"base64-js": "^1.3.0",
|
||||
"commist": "^1.0.0",
|
||||
"concat-stream": "^1.6.2",
|
||||
"end-of-stream": "^1.4.1",
|
||||
"es6-map": "^0.1.5",
|
||||
"help-me": "^1.0.1",
|
||||
"inherits": "^2.0.3",
|
||||
"minimist": "^1.2.0",
|
||||
"mqtt-packet": "^6.0.0",
|
||||
"pump": "^3.0.0",
|
||||
"readable-stream": "^2.3.6",
|
||||
"reinterval": "^1.1.0",
|
||||
"split2": "^3.1.0",
|
||||
"websocket-stream": "^5.1.2",
|
||||
"xtend": "^4.0.1"
|
||||
}
|
||||
},
|
||||
"mqtt-packet": {
|
||||
"version": "6.10.0",
|
||||
"resolved": "https://registry.npmjs.org/mqtt-packet/-/mqtt-packet-6.10.0.tgz",
|
||||
"integrity": "sha512-ja8+mFKIHdB1Tpl6vac+sktqy3gA8t9Mduom1BA75cI+R9AHnZOiaBQwpGiWnaVJLDGRdNhQmFaAqd7tkKSMGA==",
|
||||
"requires": {
|
||||
"bl": "^4.0.2",
|
||||
"debug": "^4.1.1",
|
||||
"process-nextick-args": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"ms": {
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
|
||||
},
|
||||
"nanoid": {
|
||||
"version": "3.3.11",
|
||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
|
||||
"integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="
|
||||
},
|
||||
"next-tick": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz",
|
||||
"integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ=="
|
||||
},
|
||||
"once": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
|
||||
"requires": {
|
||||
"wrappy": "1"
|
||||
}
|
||||
},
|
||||
"ordered-read-streams": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz",
|
||||
"integrity": "sha512-Z87aSjx3r5c0ZB7bcJqIgIRX5bxR7A4aSzvIbaxd0oTkWBCOoKfuGHiKj60CHVUgg1Phm5yMZzBdt8XqRs73Mw==",
|
||||
"requires": {
|
||||
"readable-stream": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"path-dirname": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz",
|
||||
"integrity": "sha512-ALzNPpyNq9AqXMBjeymIjFDAkAFH06mHJH/cSBHAgU0s4vfpBn6b2nf8tiRLvagKD8RbTpq2FKTBg7cl9l3c7Q=="
|
||||
},
|
||||
"path-is-absolute": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
|
||||
"integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg=="
|
||||
},
|
||||
"picocolors": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
|
||||
"integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="
|
||||
},
|
||||
"postcss": {
|
||||
"version": "8.5.6",
|
||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz",
|
||||
"integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==",
|
||||
"requires": {
|
||||
"nanoid": "^3.3.11",
|
||||
"picocolors": "^1.1.1",
|
||||
"source-map-js": "^1.2.1"
|
||||
}
|
||||
},
|
||||
"process-nextick-args": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
|
||||
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
|
||||
},
|
||||
"pump": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz",
|
||||
"integrity": "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==",
|
||||
"requires": {
|
||||
"end-of-stream": "^1.1.0",
|
||||
"once": "^1.3.1"
|
||||
}
|
||||
},
|
||||
"pumpify": {
|
||||
"version": "1.5.1",
|
||||
"resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz",
|
||||
"integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==",
|
||||
"requires": {
|
||||
"duplexify": "^3.6.0",
|
||||
"inherits": "^2.0.3",
|
||||
"pump": "^2.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"pump": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz",
|
||||
"integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==",
|
||||
"requires": {
|
||||
"end-of-stream": "^1.1.0",
|
||||
"once": "^1.3.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"readable-stream": {
|
||||
"version": "2.3.8",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz",
|
||||
"integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==",
|
||||
"requires": {
|
||||
"core-util-is": "~1.0.0",
|
||||
"inherits": "~2.0.3",
|
||||
"isarray": "~1.0.0",
|
||||
"process-nextick-args": "~2.0.0",
|
||||
"safe-buffer": "~5.1.1",
|
||||
"string_decoder": "~1.1.1",
|
||||
"util-deprecate": "~1.0.1"
|
||||
}
|
||||
},
|
||||
"reinterval": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/reinterval/-/reinterval-1.1.0.tgz",
|
||||
"integrity": "sha512-QIRet3SYrGp0HUHO88jVskiG6seqUGC5iAG7AwI/BV4ypGcuqk9Du6YQBUOUqm9c8pw1eyLoIaONifRua1lsEQ=="
|
||||
},
|
||||
"remove-trailing-separator": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz",
|
||||
"integrity": "sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw=="
|
||||
},
|
||||
"safe-buffer": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
||||
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
|
||||
},
|
||||
"source-map-js": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
|
||||
"integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="
|
||||
},
|
||||
"split2": {
|
||||
"version": "3.2.2",
|
||||
"resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz",
|
||||
"integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==",
|
||||
"requires": {
|
||||
"readable-stream": "^3.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"readable-stream": {
|
||||
"version": "3.6.2",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
|
||||
"integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
|
||||
"requires": {
|
||||
"inherits": "^2.0.3",
|
||||
"string_decoder": "^1.1.1",
|
||||
"util-deprecate": "^1.0.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"stream-shift": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.3.tgz",
|
||||
"integrity": "sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ=="
|
||||
},
|
||||
"string_decoder": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
|
||||
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
|
||||
"requires": {
|
||||
"safe-buffer": "~5.1.0"
|
||||
}
|
||||
},
|
||||
"through2": {
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz",
|
||||
"integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==",
|
||||
"requires": {
|
||||
"readable-stream": "~2.3.6",
|
||||
"xtend": "~4.0.1"
|
||||
}
|
||||
},
|
||||
"through2-filter": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-3.0.0.tgz",
|
||||
"integrity": "sha512-jaRjI2WxN3W1V8/FMZ9HKIBXixtiqs3SQSX4/YGIiP3gL6djW48VoZq9tDqeCWs3MT8YY5wb/zli8VW8snY1CA==",
|
||||
"requires": {
|
||||
"through2": "~2.0.0",
|
||||
"xtend": "~4.0.0"
|
||||
}
|
||||
},
|
||||
"to-absolute-glob": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz",
|
||||
"integrity": "sha512-rtwLUQEwT8ZeKQbyFJyomBRYXyE16U5VKuy0ftxLMK/PZb2fkOsg5r9kHdauuVDbsNdIBoC/HCthpidamQFXYA==",
|
||||
"requires": {
|
||||
"is-absolute": "^1.0.0",
|
||||
"is-negated-glob": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"type": {
|
||||
"version": "2.7.3",
|
||||
"resolved": "https://registry.npmjs.org/type/-/type-2.7.3.tgz",
|
||||
"integrity": "sha512-8j+1QmAbPvLZow5Qpi6NCaN8FB60p/6x8/vfNqOk/hC+HuvFZhL4+WfekuhQLiqFZXOgQdrs3B+XxEmCc6b3FQ=="
|
||||
},
|
||||
"typedarray": {
|
||||
"version": "0.0.6",
|
||||
"resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
|
||||
"integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA=="
|
||||
},
|
||||
"ultron": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz",
|
||||
"integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og=="
|
||||
},
|
||||
"unc-path-regex": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz",
|
||||
"integrity": "sha512-eXL4nmJT7oCpkZsHZUOJo8hcX3GbsiDOa0Qu9F646fi8dT3XuSVopVqAcEiVzSKKH7UoDti23wNX3qGFxcW5Qg=="
|
||||
},
|
||||
"unique-stream": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.3.1.tgz",
|
||||
"integrity": "sha512-2nY4TnBE70yoxHkDli7DMazpWiP7xMdCYqU2nBRO0UB+ZpEkGsSija7MvmvnZFUeC+mrgiUfcHSr3LmRFIg4+A==",
|
||||
"requires": {
|
||||
"json-stable-stringify-without-jsonify": "^1.0.1",
|
||||
"through2-filter": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"util-deprecate": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
|
||||
},
|
||||
"vue": {
|
||||
"version": "3.5.21",
|
||||
"resolved": "https://registry.npmjs.org/vue/-/vue-3.5.21.tgz",
|
||||
"integrity": "sha512-xxf9rum9KtOdwdRkiApWL+9hZEMWE90FHh8yS1+KJAiWYh+iGWV1FquPjoO9VUHQ+VIhsCXNNyZ5Sf4++RVZBA==",
|
||||
"requires": {
|
||||
"@vue/compiler-dom": "3.5.21",
|
||||
"@vue/compiler-sfc": "3.5.21",
|
||||
"@vue/runtime-dom": "3.5.21",
|
||||
"@vue/server-renderer": "3.5.21",
|
||||
"@vue/shared": "3.5.21"
|
||||
}
|
||||
},
|
||||
"websocket-stream": {
|
||||
"version": "5.5.2",
|
||||
"resolved": "https://registry.npmjs.org/websocket-stream/-/websocket-stream-5.5.2.tgz",
|
||||
"integrity": "sha512-8z49MKIHbGk3C4HtuHWDtYX8mYej1wWabjthC/RupM9ngeukU4IWoM46dgth1UOS/T4/IqgEdCDJuMe2039OQQ==",
|
||||
"requires": {
|
||||
"duplexify": "^3.5.1",
|
||||
"inherits": "^2.0.1",
|
||||
"readable-stream": "^2.3.3",
|
||||
"safe-buffer": "^5.1.2",
|
||||
"ws": "^3.2.0",
|
||||
"xtend": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"wrappy": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
|
||||
},
|
||||
"ws": {
|
||||
"version": "3.3.3",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz",
|
||||
"integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==",
|
||||
"requires": {
|
||||
"async-limiter": "~1.0.0",
|
||||
"safe-buffer": "~5.1.0",
|
||||
"ultron": "~1.1.0"
|
||||
}
|
||||
},
|
||||
"xtend": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
|
||||
"integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ=="
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -582,10 +582,8 @@ export default {
|
||||
|
||||
// 使用完整的商品数据对象,而不是itemObj
|
||||
this.currentGG = this.info.commodity_goods_info_list[this.currentGGIndex];
|
||||
// 将promotional_price赋值给sales_price(无活动价时保留商品自身价格,如客服分享场景)
|
||||
if (this.promotional_price !== "" && this.promotional_price != null) {
|
||||
// 将promotional_price赋值给sales_price
|
||||
this.currentGG.sales_price = this.promotional_price;
|
||||
}
|
||||
|
||||
// 设置相关属性
|
||||
this.changeImg = this.currentGG.commodity_pic[0];
|
||||
@ -618,10 +616,8 @@ export default {
|
||||
// 切换规格
|
||||
changeGG(item, index) {
|
||||
this.currentGG = item;
|
||||
// 将promotional_price赋值给sales_price(无活动价时保留商品自身价格)
|
||||
if (this.promotional_price !== "" && this.promotional_price != null) {
|
||||
// 将promotional_price赋值给sales_price
|
||||
this.currentGG.sales_price = this.promotional_price;
|
||||
}
|
||||
this.currentGGIndex = index;
|
||||
if (this.currentGG.cart_count) {
|
||||
this.currentNum = this.currentGG.cart_count.count;
|
||||
@ -782,15 +778,7 @@ export default {
|
||||
}
|
||||
},
|
||||
onLoad(options) {
|
||||
// 来自客服聊天卡片:优先从本地存储读完整数据(避免 URL 过长)
|
||||
if (options && options.fromChat) {
|
||||
let stashed
|
||||
try { stashed = uni.getStorageSync('chatCardItem') } catch (e) { stashed = null }
|
||||
uni.removeStorageSync('chatCardItem')
|
||||
this.itemObj = stashed || JSON.parse(decodeURIComponent(options.item))
|
||||
} else {
|
||||
this.itemObj = JSON.parse(decodeURIComponent(options.item));
|
||||
}
|
||||
const meun = menuButtonInfo();
|
||||
this.top = meun.top;
|
||||
this.localHeight = meun.height;
|
||||
|
||||
@ -91,9 +91,6 @@ export default {
|
||||
this.currentCommunity = e
|
||||
uni.setStorageSync('changeCommData', { id: e.community_id, name: e.name });
|
||||
uni.setStorageSync('currentCommunityAddr', e.addr);
|
||||
// 缓存该小区已绑定房产的门牌号(room_name,如「1栋1单元1层103」),供到家服务等下单页缺省填写
|
||||
const owner = (e.room_owner_list && e.room_owner_list.length) ? e.room_owner_list[0] : null
|
||||
uni.setStorageSync('currentRoomNo', owner && owner.room_name ? owner.room_name : '');
|
||||
NavgateTo("1")
|
||||
},
|
||||
},
|
||||
|
||||
@ -68,9 +68,9 @@ export default {
|
||||
},
|
||||
getAvatarUrl(record){
|
||||
if(record.client_id_one == uni.getStorageSync('openId')){
|
||||
return record.two && record.two.avatar ? picUrl + record.two.avatar : 'https://static.hshuishang.com/defaultTx.png'
|
||||
return record.two.avatar ? picUrl + record.two.avatar : 'https://static.hshuishang.com/defaultTx.png'
|
||||
}else{
|
||||
return record.one && record.one.avatar ? picUrl + record.one.avatar : 'https://static.hshuishang.com/defaultTx.png'
|
||||
return record.one.avatar ? picUrl + record.one.avatar : 'https://static.hshuishang.com/defaultTx.png'
|
||||
}
|
||||
},
|
||||
// 格式化时间
|
||||
|
||||
@ -33,44 +33,9 @@
|
||||
}" class="message-item">
|
||||
<image :src="message.isSelf ? userAvatar : getAvatarUrl(message)" class="message-avatar" mode="aspectFill">
|
||||
</image>
|
||||
<!-- 文字 -->
|
||||
<view v-if="!message.type || message.type === 1" class="message-content">
|
||||
<view class="message-content">
|
||||
{{ message.content }}
|
||||
</view>
|
||||
<!-- 图片 -->
|
||||
<view v-else-if="message.type === 2" class="message-media">
|
||||
<image v-if="message.mediaUrl" :src="message.mediaUrl" class="chat-img" mode="aspectFit"
|
||||
@tap="previewImage(message.mediaUrl)" />
|
||||
<view v-else class="media-loading">图片加载中…</view>
|
||||
</view>
|
||||
<!-- 视频 -->
|
||||
<view v-else-if="message.type === 3" class="message-media">
|
||||
<video v-if="message.mediaUrl" :src="message.mediaUrl" class="chat-video" controls></video>
|
||||
<view v-else class="media-loading">视频加载中…</view>
|
||||
</view>
|
||||
<!-- 商品/购物车卡片 -->
|
||||
<view v-else-if="message.type === 4" class="message-card" @tap="openCardLink(message.card)">
|
||||
<image v-if="message.card.pic && !message.card._picErr" :src="message.card.pic" class="card-pic"
|
||||
mode="aspectFill" @error="onCardPicError(message)" />
|
||||
<view v-else class="card-pic card-pic--ph">商品</view>
|
||||
<view class="card-info">
|
||||
<view class="card-name">{{ message.card.name }}</view>
|
||||
<view class="card-price">¥{{ message.card.price }}</view>
|
||||
<view class="card-tag">商品</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 订单卡片 -->
|
||||
<view v-else-if="message.type === 5" class="message-card" @tap="openCardLink(message.card)">
|
||||
<image v-if="message.card.pic && !message.card._picErr" :src="message.card.pic" class="card-pic"
|
||||
mode="aspectFill" @error="onCardPicError(message)" />
|
||||
<view v-else class="card-pic card-pic--ph">订单</view>
|
||||
<view class="card-info">
|
||||
<view class="card-name">订单 {{ message.card.order_no }}</view>
|
||||
<view class="card-price">¥{{ message.card.amount }}</view>
|
||||
<view class="card-tag">订单 · 共{{ message.card.count }}件</view>
|
||||
</view>
|
||||
</view>
|
||||
<view v-else class="message-content">{{ message.content }}</view>
|
||||
</view>
|
||||
</block>
|
||||
</scroll-view>
|
||||
@ -81,45 +46,18 @@
|
||||
<textarea v-model="inputMessage" :adjust-position="true" auto-height class="message-input" cursor-spacing="10"
|
||||
enable-keyboard-accessory-view="true" hold-keyboard="true" maxlength="500" placeholder="请输入消息..."
|
||||
@blur="onInputBlur" @confirm="sendMessage" @focus="onInputFocus" @input="handleInput"></textarea>
|
||||
<view class="plus-btn" @tap="togglePanel">
|
||||
<uni-icons color="#666" size="30" type="plusempty"></uni-icons>
|
||||
</view>
|
||||
<button :disabled="inputMessage.trim() === ''" class="send-btn" @tap="sendMessage">
|
||||
发送
|
||||
</button>
|
||||
</view>
|
||||
<!-- 更多功能面板 -->
|
||||
<view v-if="showPanel" class="more-panel">
|
||||
<view class="panel-item" @tap="chooseMedia('image')">
|
||||
<view class="panel-icon">🖼️</view>
|
||||
<text>相册图片</text>
|
||||
</view>
|
||||
<view class="panel-item" @tap="chooseMedia('camera')">
|
||||
<view class="panel-icon">📷</view>
|
||||
<text>拍摄</text>
|
||||
</view>
|
||||
<view class="panel-item" @tap="chooseMedia('video')">
|
||||
<view class="panel-icon">🎬</view>
|
||||
<text>视频</text>
|
||||
</view>
|
||||
<view class="panel-item" @tap="openGoodsPicker">
|
||||
<view class="panel-icon">🛒</view>
|
||||
<text>商品/购物车</text>
|
||||
</view>
|
||||
<view class="panel-item" @tap="openOrderPicker">
|
||||
<view class="panel-icon">📦</view>
|
||||
<text>订单</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { menuButtonInfo, picUrl, request, NavgateTo } from '@/utils'
|
||||
import { menuButtonInfo, picUrl, request } from '@/utils'
|
||||
import mqttTool from '@/utils/mqtt'
|
||||
import { apiArr } from '../../../api/customerService'
|
||||
import { uploadOSS, signPrivateView } from '@/utils/uploadOSS'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
@ -141,8 +79,6 @@ export default {
|
||||
|
||||
// 输入的消息
|
||||
inputMessage: '',
|
||||
// 更多功能面板
|
||||
showPanel: false,
|
||||
// 是否可以发送消息
|
||||
canSend: false,
|
||||
// 连接状态
|
||||
@ -214,13 +150,6 @@ export default {
|
||||
console.log('用户头像:', this.userAvatar)
|
||||
},
|
||||
onShow() {
|
||||
// 监听 picker 页回传的商品/订单卡片(只注册一次)
|
||||
if (!this._onPickCard) {
|
||||
this._onPickCard = ({ type, card }) => {
|
||||
this.publishMsg(type, JSON.stringify(card))
|
||||
}
|
||||
uni.$on('chat:pickCard', this._onPickCard)
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getAvatarUrl(record) {
|
||||
@ -231,7 +160,6 @@ export default {
|
||||
const options = {
|
||||
clientId: this.selfClientId
|
||||
}
|
||||
console.log('clientId:', options.clientId)
|
||||
|
||||
// 添加连接状态回调
|
||||
const callbacks = {
|
||||
@ -264,46 +192,26 @@ export default {
|
||||
let jsMsg = msg // 直接使用已解析的对象,无需再次解析
|
||||
console.log('收到消息', topic, msg)
|
||||
if (jsMsg.send_client === this.selfClientId || jsMsg.receive_client === this.selfClientId) {
|
||||
console.log('接收或发送人是我')
|
||||
if (jsMsg.send_client === this.chatTarget.openId || jsMsg.receive_client === this.chatTarget.openId) {
|
||||
this.appendMessage(jsMsg, jsMsg.send_client === this.selfClientId)
|
||||
console.log('接收或发送人是我的聊天对象')
|
||||
this.messages.push({
|
||||
content: jsMsg.content,
|
||||
time: Date.now(),
|
||||
isSelf: jsMsg.send_client === this.selfClientId,
|
||||
isLoading: false
|
||||
})
|
||||
console.log('收到我的消息', this.messages)
|
||||
this.scrollToView = 'msg-' + (this.messages.length - 1)
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
// 把一条原始消息(含 type/content)转成可渲染的消息对象并追加;图片/视频异步签名 URL
|
||||
async appendMessage(raw, isSelf) {
|
||||
const type = Number(raw.type) || 1
|
||||
const item = {
|
||||
type,
|
||||
content: raw.content,
|
||||
time: Date.now(),
|
||||
isSelf,
|
||||
isLoading: false,
|
||||
mediaUrl: '',
|
||||
card: null
|
||||
}
|
||||
if (type === 4 || type === 5) {
|
||||
try { item.card = typeof raw.content === 'string' ? JSON.parse(raw.content) : raw.content } catch (e) { item.card = {} }
|
||||
}
|
||||
const idx = this.messages.push(item) - 1
|
||||
this.scrollToView = 'msg-' + idx
|
||||
// 图片/视频:content 是私密 object_key,需签名后显示
|
||||
if (type === 2 || type === 3) {
|
||||
try {
|
||||
const r = await signPrivateView(raw.content)
|
||||
this.$set(this.messages[idx], 'mediaUrl', r.url)
|
||||
} catch (e) {
|
||||
console.error('签发聊天媒体URL失败', e)
|
||||
}
|
||||
}
|
||||
},
|
||||
async subscribe() {
|
||||
if (this.isConnected && this.client) {
|
||||
const topic = 'contact/message/send_msg/' + this.chatTarget.bindId // 按会话精确订阅,天然隔离(沿用 contact/message 授权前缀)
|
||||
this.client.subscribe(topic, { qos: 0 }, (err) => {
|
||||
this.client.subscribe('contact/message/receive_msg', { qos: 0 }, (err) => {
|
||||
if (!err) {
|
||||
console.log('订阅成功', topic, { qos: 0 })
|
||||
console.log('订阅成功', 'contact/message/receive_msg', { qos: 0 })
|
||||
this.connectingStatus = ''
|
||||
} else {
|
||||
console.log('订阅失败:', err)
|
||||
@ -439,32 +347,13 @@ export default {
|
||||
}
|
||||
|
||||
// 处理历史消息,转换为需要的格式
|
||||
const formattedMessages = historyMessages.map(msg => {
|
||||
const type = Number(msg.type) || 1
|
||||
const item = {
|
||||
type,
|
||||
const formattedMessages = historyMessages.map(msg => ({
|
||||
content: msg.content,
|
||||
time: new Date(msg.create_time).getTime(),
|
||||
times: msg.update_time,
|
||||
isSelf: msg.send_client === this.selfClientId,
|
||||
isLoading: false,
|
||||
mediaUrl: '',
|
||||
card: null
|
||||
}
|
||||
if (type === 4 || type === 5) {
|
||||
try { item.card = typeof msg.content === 'string' ? JSON.parse(msg.content) : msg.content } catch (e) { item.card = {} }
|
||||
}
|
||||
return item
|
||||
}).reverse(); // 反转消息顺序,确保最早的消息在最前面
|
||||
|
||||
// 图片/视频历史消息:异步签发私密 URL
|
||||
formattedMessages.forEach(item => {
|
||||
if (item.type === 2 || item.type === 3) {
|
||||
signPrivateView(item.content).then(r => {
|
||||
this.$set(item, 'mediaUrl', r.url)
|
||||
}).catch(e => console.error('历史媒体签名失败', e))
|
||||
}
|
||||
})
|
||||
isSelf: msg.send_client === this.selfClientId, // 修正判断条件
|
||||
isLoading: false
|
||||
})).reverse(); // 反转消息顺序,确保最早的消息在最前面
|
||||
|
||||
console.log('格式化后的历史消息:', formattedMessages)
|
||||
// 将格式化后的历史消息添加到消息列表开头
|
||||
@ -551,7 +440,7 @@ export default {
|
||||
}
|
||||
console.log('发送消息', msgData)
|
||||
this.client.publish(
|
||||
'contact/message/send_msg/' + this.chatTarget.bindId, // 按会话精确主题,双方订阅同一主题
|
||||
'contact/message/send_msg', // 使用指定的发送消息主题
|
||||
JSON.stringify(msgData),
|
||||
{ Qos: 0 },
|
||||
(err) => {
|
||||
@ -568,107 +457,6 @@ export default {
|
||||
this.inputMessage = ''
|
||||
},
|
||||
|
||||
// 切换"+"功能面板
|
||||
togglePanel() {
|
||||
this.showPanel = !this.showPanel
|
||||
},
|
||||
|
||||
// 统一发布消息(type: 1文字 2图片 3视频 4商品 5订单;content 为文本/object_key/JSON字符串)
|
||||
publishMsg(type, content) {
|
||||
if (!this.client || !this.isConnected) {
|
||||
uni.showToast({ title: '连接断开,请重试', icon: 'none' })
|
||||
return
|
||||
}
|
||||
const msgData = {
|
||||
bind_id: this.chatTarget.bindId,
|
||||
send_client: this.selfClientId,
|
||||
receive_client: this.chatTarget.openId,
|
||||
type,
|
||||
content,
|
||||
receive_read_status: 2
|
||||
}
|
||||
this.client.publish('contact/message/send_msg/' + this.chatTarget.bindId, JSON.stringify(msgData), { Qos: 0 }, (err) => {
|
||||
if (err) console.error('发送消息失败', err)
|
||||
})
|
||||
},
|
||||
|
||||
// 选择图片/拍摄/视频并上传(私密,按会话授权)
|
||||
chooseMedia(source) {
|
||||
this.showPanel = false
|
||||
if (source === 'video') {
|
||||
uni.chooseVideo({
|
||||
sourceType: ['album', 'camera'],
|
||||
maxDuration: 60,
|
||||
success: (res) => this.uploadAndSend(res.tempFilePath, 'chat_video', 3)
|
||||
})
|
||||
} else {
|
||||
uni.chooseImage({
|
||||
count: 1,
|
||||
sizeType: ['compressed'],
|
||||
sourceType: source === 'camera' ? ['camera'] : ['album'],
|
||||
success: (res) => {
|
||||
const fp = res.tempFilePaths && res.tempFilePaths[0]
|
||||
if (fp) this.uploadAndSend(fp, 'chat_image', 2)
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
// 上传到私密 bucket 后,把 object_key 作为消息内容发布
|
||||
async uploadAndSend(filePath, scene, type) {
|
||||
try {
|
||||
const { objectKey } = await uploadOSS({ filePath, scene, bindId: this.chatTarget.bindId })
|
||||
this.publishMsg(type, objectKey)
|
||||
} catch (e) {
|
||||
console.error('上传失败', e)
|
||||
uni.showToast({ title: '上传失败,请重试', icon: 'none' })
|
||||
}
|
||||
},
|
||||
|
||||
// 预览图片
|
||||
previewImage(url) {
|
||||
if (url) uni.previewImage({ urls: [url], current: url })
|
||||
},
|
||||
|
||||
// 点击商品/订单卡片跳转
|
||||
openCardLink(card) {
|
||||
if (!card) return
|
||||
// 兼容老消息:仍带 path 的直接跳
|
||||
if (!card.page && card.path) {
|
||||
NavgateTo(card.path, { isLogin: false })
|
||||
return
|
||||
}
|
||||
if (!card.page) return
|
||||
// 完整 item 经本地存储中转,避免 URL 过长被截断(详情页优先读 storage)
|
||||
const item = card.item || {}
|
||||
try {
|
||||
uni.setStorageSync('chatCardItem', item)
|
||||
} catch (e) {
|
||||
console.error('暂存卡片数据失败', e)
|
||||
}
|
||||
NavgateTo(card.page + '?item=' + encodeURIComponent(JSON.stringify(item)) + '&fromChat=1', { isLogin: false })
|
||||
},
|
||||
|
||||
// 卡片图片加载失败 -> 显示占位(用 $set 保证响应式)
|
||||
onCardPicError(message) {
|
||||
if (message && message.card) {
|
||||
this.$set(message.card, '_picErr', true)
|
||||
}
|
||||
},
|
||||
|
||||
// 选择商品/购物车发送
|
||||
openGoodsPicker() {
|
||||
this.showPanel = false
|
||||
// 跳转到选择页(复用购物车/商品列表),选完回传后 publishMsg(4, JSON)
|
||||
NavgateTo('/packages/customerService/picker/index?type=goods&bindId=' + this.chatTarget.bindId, { isLogin: false })
|
||||
},
|
||||
|
||||
// 选择订单发送
|
||||
openOrderPicker() {
|
||||
this.showPanel = false
|
||||
NavgateTo('/packages/customerService/picker/index?type=order&bindId=' + this.chatTarget.bindId, { isLogin: false })
|
||||
},
|
||||
|
||||
// 处理输入事件
|
||||
handleInput() {
|
||||
this.canSend = this.inputMessage.trim().length > 0
|
||||
@ -791,12 +579,6 @@ export default {
|
||||
clearTimeout(this.reconnectFailedTimer)
|
||||
this.reconnectFailedTimer = null
|
||||
}
|
||||
|
||||
// 移除卡片选择监听
|
||||
if (this._onPickCard) {
|
||||
uni.$off('chat:pickCard', this._onPickCard)
|
||||
this._onPickCard = null
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@ -809,115 +591,4 @@ export default {
|
||||
--header-height: 80px; /* 头部高度 */
|
||||
--input-height: 80px; /* 输入区域高度 */
|
||||
}
|
||||
|
||||
/* 图片/视频消息 */
|
||||
.message-media {
|
||||
max-width: 60%;
|
||||
}
|
||||
.chat-img {
|
||||
width: 320rpx;
|
||||
height: 320rpx;
|
||||
border-radius: 12rpx;
|
||||
background: #f0f0f0;
|
||||
}
|
||||
.chat-video {
|
||||
width: 400rpx;
|
||||
height: 300rpx;
|
||||
border-radius: 12rpx;
|
||||
}
|
||||
.media-loading {
|
||||
padding: 30rpx 40rpx;
|
||||
background: #fff;
|
||||
border-radius: 12rpx;
|
||||
color: #999;
|
||||
font-size: 24rpx;
|
||||
}
|
||||
|
||||
/* 商品/订单卡片 */
|
||||
.message-card {
|
||||
display: flex;
|
||||
width: 520rpx;
|
||||
background: #fff;
|
||||
border-radius: 14rpx;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 2rpx 8rpx rgba(0,0,0,0.06);
|
||||
}
|
||||
.card-pic {
|
||||
width: 180rpx;
|
||||
height: 180rpx;
|
||||
flex-shrink: 0;
|
||||
background: #f5f5f5;
|
||||
}
|
||||
.card-pic--ph {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #bbb;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
.card-info {
|
||||
flex: 1;
|
||||
padding: 18rpx 20rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
min-width: 0;
|
||||
}
|
||||
.card-name {
|
||||
font-size: 28rpx;
|
||||
color: #222;
|
||||
line-height: 38rpx;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
overflow: hidden;
|
||||
}
|
||||
.card-price {
|
||||
font-size: 32rpx;
|
||||
color: #FF370B;
|
||||
font-weight: 600;
|
||||
}
|
||||
.card-tag {
|
||||
align-self: flex-start;
|
||||
font-size: 20rpx;
|
||||
color: #999;
|
||||
border: 1rpx solid #eee;
|
||||
border-radius: 6rpx;
|
||||
padding: 0 10rpx;
|
||||
}
|
||||
|
||||
/* "+" 按钮与更多面板 */
|
||||
.plus-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 60rpx;
|
||||
height: 60rpx;
|
||||
}
|
||||
.more-panel {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
padding: 24rpx 12rpx;
|
||||
background: #f7f7f7;
|
||||
}
|
||||
.panel-item {
|
||||
width: 20%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 8rpx;
|
||||
font-size: 22rpx;
|
||||
color: #666;
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
.panel-icon {
|
||||
width: 96rpx;
|
||||
height: 96rpx;
|
||||
background: #fff;
|
||||
border-radius: 16rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 44rpx;
|
||||
}
|
||||
</style>
|
||||
@ -1,165 +0,0 @@
|
||||
<template>
|
||||
<view class="picker-page">
|
||||
<!-- 订单:普通/团购 两个 tab -->
|
||||
<view v-if="mode === 'order'" class="tabs">
|
||||
<view class="tab" :class="{ active: orderTab === 'normal' }" @tap="switchTab('normal')">普通订单</view>
|
||||
<view class="tab" :class="{ active: orderTab === 'group' }" @tap="switchTab('group')">团购订单</view>
|
||||
</view>
|
||||
|
||||
<scroll-view class="list" scroll-y>
|
||||
<!-- 订单列表 -->
|
||||
<block v-if="mode === 'order'">
|
||||
<view v-for="(item, idx) in orderList" :key="idx" class="order-card" @tap="pickOrder(item)">
|
||||
<view class="order-head">
|
||||
<text class="order-no">订单号:{{ item.order_no }}</text>
|
||||
</view>
|
||||
<view class="order-goods">
|
||||
<image v-for="(g, gi) in (item.commodity_order_item_list || []).slice(0, 4)" :key="gi"
|
||||
:src="g.commodity_pic" class="goods-thumb" mode="aspectFill" />
|
||||
</view>
|
||||
<view class="order-foot">
|
||||
<text>共{{ item.total_count }}件</text>
|
||||
<text class="amount">¥{{ item.total_amount }}</text>
|
||||
<view class="send-btn">发送</view>
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="orderList.length === 0" class="empty">暂无订单</view>
|
||||
</block>
|
||||
|
||||
<!-- 购物车列表 -->
|
||||
<block v-else>
|
||||
<view v-for="(g, idx) in cartGoods" :key="idx" class="goods-row" @tap="pickGoods(g)">
|
||||
<image :src="g.pic" class="goods-thumb-lg" mode="aspectFill" />
|
||||
<view class="goods-info">
|
||||
<view class="goods-name">{{ g.name }}</view>
|
||||
<view class="goods-price">¥{{ g.price }}</view>
|
||||
</view>
|
||||
<view class="send-btn">发送</view>
|
||||
</view>
|
||||
<view v-if="cartGoods.length === 0" class="empty">购物车为空</view>
|
||||
</block>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { request, picUrl } from '@/utils'
|
||||
import { apiArr as shopApi } from '@/api/shop'
|
||||
import { apiArr as afterSaleApi } from '@/api/afterSale'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
mode: 'order', // order | goods
|
||||
bindId: 0,
|
||||
orderTab: 'normal', // normal | group
|
||||
orderList: [],
|
||||
cartGoods: []
|
||||
}
|
||||
},
|
||||
onLoad(options) {
|
||||
this.mode = options.type === 'goods' ? 'goods' : 'order'
|
||||
this.bindId = Number(options.bindId) || 0
|
||||
uni.setNavigationBarTitle({ title: this.mode === 'goods' ? '选择购物车商品' : '选择订单' })
|
||||
if (this.mode === 'goods') {
|
||||
this.loadCart()
|
||||
} else {
|
||||
this.loadOrders()
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
switchTab(t) {
|
||||
this.orderTab = t
|
||||
this.loadOrders()
|
||||
},
|
||||
// 订单列表:order_cate 1普通 2团购(按 tab 过滤)
|
||||
loadOrders() {
|
||||
request(afterSaleApi.orderList, 'POST', {
|
||||
user_id: uni.getStorageSync('userId')
|
||||
}).then(res => {
|
||||
const list = res.order_list || []
|
||||
list.forEach(item => {
|
||||
(item.commodity_order_item_list || []).forEach(g => {
|
||||
g.commodity_pic = (g.commodity_pic && g.commodity_pic.startsWith('http')) ? g.commodity_pic : picUrl + g.commodity_pic
|
||||
})
|
||||
})
|
||||
if (this.orderTab === 'group') {
|
||||
this.orderList = list.filter(i => i.order_cate == 2)
|
||||
} else {
|
||||
this.orderList = list.filter(i => i.order_cate == 1 || i.order_cate == 4)
|
||||
}
|
||||
})
|
||||
},
|
||||
// 购物车(非团购)
|
||||
loadCart() {
|
||||
request(shopApi.getCar, 'POST', { is_group_buy: '' }).then(res => {
|
||||
const groups = [].concat(res.same_day_cart_list || [], res.normal_cart_list || [])
|
||||
const goods = []
|
||||
groups.forEach(sup => {
|
||||
(sup.commodity_cart_and_goods_model || []).forEach(c => {
|
||||
const gi = c.commodity_goods_info || {}
|
||||
goods.push({
|
||||
goods_id: c.goods_id,
|
||||
commodity_id: c.commodity_id,
|
||||
name: gi.commodity_name || gi.goods_name || '商品',
|
||||
pic: (gi.commodity_pic && gi.commodity_pic.startsWith('http')) ? gi.commodity_pic : picUrl + (gi.commodity_pic || ''),
|
||||
price: gi.sales_price || c.price || 0
|
||||
})
|
||||
})
|
||||
})
|
||||
this.cartGoods = goods
|
||||
})
|
||||
},
|
||||
// 选中订单 -> 回传订单卡片(type=5)
|
||||
pickOrder(item) {
|
||||
const firstPic = (item.commodity_order_item_list && item.commodity_order_item_list[0] && item.commodity_order_item_list[0].commodity_pic) || ''
|
||||
const card = {
|
||||
order_id: item.id,
|
||||
order_no: item.order_no,
|
||||
amount: item.total_amount,
|
||||
count: item.total_count,
|
||||
pic: firstPic,
|
||||
page: '/packages/myOrders/orderDetails/index', // 点击跳转目标页(完整 item 经 storage 中转,避免 URL 超长)
|
||||
item // 完整订单对象,详情页直接用
|
||||
}
|
||||
uni.$emit('chat:pickCard', { type: 5, card })
|
||||
uni.navigateBack()
|
||||
},
|
||||
// 选中购物车商品 -> 回传商品卡片(type=4)
|
||||
pickGoods(g) {
|
||||
const card = {
|
||||
goods_id: g.goods_id,
|
||||
commodity_id: g.commodity_id,
|
||||
name: g.name,
|
||||
price: g.price,
|
||||
pic: g.pic,
|
||||
page: '/packages/advertising/goodsDetail/index',
|
||||
item: { commodity_id: g.commodity_id, id: g.goods_id, promotional_price: g.price } // goodsDetail 需 commodity_id 查详情、id 定位规格、promotional_price 作展示价
|
||||
}
|
||||
uni.$emit('chat:pickCard', { type: 4, card })
|
||||
uni.navigateBack()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.picker-page { display: flex; flex-direction: column; height: 100vh; background: #f5f5f5; }
|
||||
.tabs { display: flex; background: #fff; }
|
||||
.tab { flex: 1; text-align: center; padding: 28rpx 0; font-size: 28rpx; color: #666; }
|
||||
.tab.active { color: #FF370B; font-weight: 600; border-bottom: 4rpx solid #FF370B; }
|
||||
.list { flex: 1; padding: 20rpx; box-sizing: border-box; }
|
||||
.order-card { background: #fff; border-radius: 12rpx; padding: 20rpx; margin-bottom: 20rpx; }
|
||||
.order-head { font-size: 24rpx; color: #999; margin-bottom: 14rpx; }
|
||||
.order-goods { display: flex; gap: 12rpx; }
|
||||
.goods-thumb { width: 120rpx; height: 120rpx; border-radius: 8rpx; background: #f0f0f0; }
|
||||
.order-foot { display: flex; align-items: center; justify-content: flex-end; gap: 20rpx; margin-top: 16rpx; }
|
||||
.order-foot .amount { color: #FF370B; font-weight: 600; }
|
||||
.goods-row { display: flex; align-items: center; background: #fff; border-radius: 12rpx; padding: 16rpx; margin-bottom: 16rpx; }
|
||||
.goods-thumb-lg { width: 140rpx; height: 140rpx; border-radius: 8rpx; background: #f0f0f0; flex-shrink: 0; }
|
||||
.goods-info { flex: 1; margin-left: 20rpx; min-width: 0; }
|
||||
.goods-name { font-size: 28rpx; color: #222; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
|
||||
.goods-price { font-size: 30rpx; color: #FF370B; font-weight: 600; margin-top: 12rpx; }
|
||||
.send-btn { background: linear-gradient(91deg, #FF7658, #FF370B); color: #fff; font-size: 24rpx; padding: 10rpx 28rpx; border-radius: 30rpx; flex-shrink: 0; }
|
||||
.empty { text-align: center; color: #999; font-size: 26rpx; padding: 80rpx 0; }
|
||||
</style>
|
||||
@ -1,79 +0,0 @@
|
||||
<template>
|
||||
<view class="hcd-page" v-if="info.id">
|
||||
<view class="hcd-card">
|
||||
<view class="hcd-status" :class="'st' + info.status">{{ statusText(info.status) }}</view>
|
||||
<view class="hcd-name">{{ info.contract_name }}</view>
|
||||
<view class="hcd-no">合同编号:{{ info.contract_no }}</view>
|
||||
</view>
|
||||
<view class="hcd-block">
|
||||
<view class="hcd-item"><text class="hcd-label">月薪</text><text class="hcd-val amount">¥{{ info.month_amount }}</text></view>
|
||||
<view class="hcd-item"><text class="hcd-label">账单日</text><text class="hcd-val">每月 {{ info.pay_day }} 号</text></view>
|
||||
<view class="hcd-item"><text class="hcd-label">结算方式</text><text class="hcd-val">{{ info.settle_mode === 1 ? '平台月账单' : '线下自付' }}</text></view>
|
||||
<view class="hcd-item"><text class="hcd-label">合同开始</text><text class="hcd-val">{{ fmtDate(info.start_date) }}</text></view>
|
||||
<view class="hcd-item"><text class="hcd-label">合同结束</text><text class="hcd-val">{{ fmtDate(info.end_date) }}</text></view>
|
||||
<view class="hcd-item"><text class="hcd-label">联系人</text><text class="hcd-val">{{ info.contact_name || '-' }}</text></view>
|
||||
<view class="hcd-item"><text class="hcd-label">联系电话</text><text class="hcd-val">{{ info.contact_phone || '-' }}</text></view>
|
||||
<view class="hcd-item"><text class="hcd-label">服务地址</text><text class="hcd-val">{{ info.service_address || '-' }}</text></view>
|
||||
<view class="hcd-item" v-if="info.remark"><text class="hcd-label">备注</text><text class="hcd-val">{{ info.remark }}</text></view>
|
||||
</view>
|
||||
<view class="hcd-block" v-if="info.file_url">
|
||||
<view class="hcd-file" @tap="openFile">查看已签合同</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { request, picUrl } from '@/utils'
|
||||
import { apiArr } from '@/api/homeService'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return { picUrl, id: 0, info: {} }
|
||||
},
|
||||
onLoad(options) {
|
||||
this.id = Number(options.id)
|
||||
this.loadInfo()
|
||||
},
|
||||
methods: {
|
||||
loadInfo() {
|
||||
const userId = uni.getStorageSync('userId')
|
||||
request(apiArr.contractInfo, 'POST', { id: this.id, user_id: userId }, {}, false).then(res => {
|
||||
this.info = res || {}
|
||||
})
|
||||
},
|
||||
statusText(s) {
|
||||
const map = { 1: '待签署', 2: '生效中', 3: '已到期', 4: '已解除', 5: '线下结算' }
|
||||
return map[s] || ''
|
||||
},
|
||||
fmtDate(v) {
|
||||
return v ? String(v).slice(0, 10) : '-'
|
||||
},
|
||||
openFile() {
|
||||
const url = this.info.file_url.startsWith('http') ? this.info.file_url : this.picUrl + this.info.file_url
|
||||
uni.downloadFile({
|
||||
url,
|
||||
success: (d) => {
|
||||
uni.openDocument({ filePath: d.tempFilePath, showMenu: true })
|
||||
},
|
||||
fail: () => uni.showToast({ title: '打开失败', icon: 'none' })
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.hcd-page { background: #f5f5f5; min-height: 100vh; padding: 20rpx; }
|
||||
.hcd-card { background: #fff; border-radius: 16rpx; padding: 28rpx; margin-bottom: 20rpx; }
|
||||
.hcd-status { font-size: 26rpx; color: #FF370B; margin-bottom: 12rpx; }
|
||||
.hcd-status.st2 { color: #07c160; }
|
||||
.hcd-status.st3, .hcd-status.st4 { color: #999; }
|
||||
.hcd-name { font-size: 34rpx; color: #222; font-weight: 600; }
|
||||
.hcd-no { font-size: 26rpx; color: #888; margin-top: 10rpx; }
|
||||
.hcd-block { background: #fff; border-radius: 16rpx; padding: 8rpx 28rpx; margin-bottom: 20rpx; }
|
||||
.hcd-item { display: flex; justify-content: space-between; padding: 22rpx 0; border-bottom: 1rpx solid #f2f2f2; }
|
||||
.hcd-label { font-size: 28rpx; color: #888; }
|
||||
.hcd-val { font-size: 28rpx; color: #222; max-width: 460rpx; text-align: right; }
|
||||
.hcd-val.amount { color: #FF370B; font-weight: 600; }
|
||||
.hcd-file { text-align: center; color: #2b6cff; font-size: 28rpx; padding: 24rpx 0; }
|
||||
</style>
|
||||
@ -1,152 +0,0 @@
|
||||
<template>
|
||||
<view class="hsd-page">
|
||||
<swiper class="hsd-swiper" autoplay circular v-if="carousel.length">
|
||||
<swiper-item v-for="(p, i) in carousel" :key="i">
|
||||
<image :src="p" mode="aspectFill" class="hsd-swiper-img" />
|
||||
</swiper-item>
|
||||
</swiper>
|
||||
<image v-else :src="picUrl + (info.cover_pic || '')" class="hsd-swiper-img" mode="aspectFill" />
|
||||
|
||||
<view class="hsd-main">
|
||||
<view class="hsd-name">{{ info.service_name }}</view>
|
||||
<view class="hsd-pricedesc">{{ info.price_desc }}</view>
|
||||
</view>
|
||||
|
||||
<!-- SKU 选择 -->
|
||||
<view class="hsd-block" v-if="skuList.length">
|
||||
<view class="hsd-block-tit">选择规格</view>
|
||||
<view class="hsd-sku-list">
|
||||
<view class="hsd-sku" :class="{ active: currentSku && currentSku.id === sku.id }"
|
||||
v-for="sku in skuList" :key="sku.id" @tap="selectSku(sku)">
|
||||
<view class="hsd-sku-name">{{ sku.sku_name }}</view>
|
||||
<view class="hsd-sku-price" v-if="isHousekeeping">月薪 ¥{{ sku.month_salary }}</view>
|
||||
<view class="hsd-sku-price" v-else>定金 ¥{{ sku.deposit }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 师傅选择 -->
|
||||
<view class="hsd-block" v-if="workerList.length">
|
||||
<view class="hsd-block-tit">选择师傅</view>
|
||||
<view class="hsd-worker-list">
|
||||
<view class="hsd-worker" :class="{ active: currentWorker && currentWorker.employee_id === w.employee_id }"
|
||||
v-for="w in workerList" :key="w.employee_id" @tap="selectWorker(w)">
|
||||
<image class="hsd-worker-img" :src="w.employee_image || defaultAvatar" mode="aspectFill" />
|
||||
<view class="hsd-worker-name">{{ w.employee_name }}</view>
|
||||
<view class="hsd-worker-exp">{{ w.expertise }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 详情图 -->
|
||||
<view class="hsd-block" v-if="detailPics.length">
|
||||
<view class="hsd-block-tit">服务详情</view>
|
||||
<image v-for="(p, i) in detailPics" :key="i" :src="p" mode="widthFix" class="hsd-detail-img" />
|
||||
</view>
|
||||
|
||||
<view class="hsd-bottom">
|
||||
<template v-if="isHousekeeping">
|
||||
<view class="hsd-bottom-price">月薪 <text>¥{{ currentSku ? currentSku.month_salary : '--' }}</text></view>
|
||||
<view class="hsd-bottom-btn" @tap="goConsult">咨询预约</view>
|
||||
</template>
|
||||
<template v-else>
|
||||
<view class="hsd-bottom-price">定金 <text>¥{{ currentSku ? currentSku.deposit : '--' }}</text></view>
|
||||
<view class="hsd-bottom-btn" @tap="goOrder">立即预约</view>
|
||||
</template>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { request, picUrl, NavgateTo } from '@/utils'
|
||||
import { apiArr } from '@/api/homeService'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
picUrl,
|
||||
defaultAvatar: 'https://static.hshuishang.com/defaultTx.png',
|
||||
id: 0,
|
||||
info: {},
|
||||
carousel: [],
|
||||
detailPics: [],
|
||||
skuList: [],
|
||||
workerList: [],
|
||||
currentSku: null,
|
||||
currentWorker: null
|
||||
}
|
||||
},
|
||||
onLoad(options) {
|
||||
this.id = Number(options.id)
|
||||
this.loadInfo()
|
||||
},
|
||||
computed: {
|
||||
// 家政服务(原长期服务 service_type=2):走咨询签约,不付定金
|
||||
isHousekeeping() {
|
||||
return Number(this.info.service_type) === 2
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
loadInfo() {
|
||||
request(apiArr.serviceInfo, 'POST', { id: this.id }, {}, false).then(res => {
|
||||
this.info = res || {}
|
||||
this.carousel = (res.carousel ? res.carousel.split(',') : []).filter(Boolean).map(p => p.startsWith('http') ? p : this.picUrl + p)
|
||||
this.detailPics = (res.detail_pic ? res.detail_pic.split(',') : []).filter(Boolean).map(p => p.startsWith('http') ? p : this.picUrl + p)
|
||||
this.skuList = res.sku_list || []
|
||||
this.workerList = res.worker_list || []
|
||||
if (this.skuList.length) this.currentSku = this.skuList[0]
|
||||
if (this.workerList.length) this.currentWorker = this.workerList[0]
|
||||
})
|
||||
},
|
||||
selectSku(sku) { this.currentSku = sku },
|
||||
selectWorker(w) { this.currentWorker = w },
|
||||
goOrder() {
|
||||
if (!this.currentSku) { uni.showToast({ title: '请选择规格', icon: 'none' }); return }
|
||||
if (!this.currentWorker) { uni.showToast({ title: '请选择师傅', icon: 'none' }); return }
|
||||
const params = {
|
||||
service_info_id: this.id,
|
||||
sku_id: this.currentSku.id,
|
||||
employee_id: this.currentWorker.employee_id,
|
||||
service_name: this.info.service_name,
|
||||
deposit: this.currentSku.deposit
|
||||
}
|
||||
NavgateTo('/packages/homeService/order/index?params=' + encodeURIComponent(JSON.stringify(params)))
|
||||
},
|
||||
// 家政服务:先与商家客服沟通签约,不走定金下单
|
||||
goConsult() {
|
||||
const supplierId = this.info.supplier_id
|
||||
if (!supplierId) { uni.showToast({ title: '商家信息缺失', icon: 'none' }); return }
|
||||
// 客服列表依赖 merchantInfo.id,写入当前服务所属商家
|
||||
const mi = uni.getStorageSync('merchantInfo') || {}
|
||||
mi.id = supplierId
|
||||
uni.setStorageSync('merchantInfo', mi)
|
||||
NavgateTo('/packages/customerService/changeService/index')
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.hsd-page { background: #f5f5f5; min-height: 100vh; padding-bottom: 130rpx; }
|
||||
.hsd-swiper, .hsd-swiper-img { width: 100%; height: 520rpx; }
|
||||
.hsd-main { background: #fff; padding: 24rpx; }
|
||||
.hsd-name { font-size: 36rpx; font-weight: 600; color: #222; }
|
||||
.hsd-pricedesc { font-size: 26rpx; color: #FF370B; margin-top: 14rpx; }
|
||||
.hsd-block { background: #fff; margin-top: 16rpx; padding: 24rpx; }
|
||||
.hsd-block-tit { font-size: 30rpx; font-weight: 600; color: #222; margin-bottom: 18rpx; }
|
||||
.hsd-sku-list, .hsd-worker-list { display: flex; flex-wrap: wrap; gap: 18rpx; }
|
||||
.hsd-sku { border: 1rpx solid #eee; border-radius: 10rpx; padding: 16rpx 24rpx; }
|
||||
.hsd-sku.active { border-color: #FF370B; background: #FFF1ED; }
|
||||
.hsd-sku-name { font-size: 28rpx; color: #222; }
|
||||
.hsd-sku-price { font-size: 24rpx; color: #FF370B; margin-top: 8rpx; }
|
||||
.hsd-worker { width: 160rpx; display: flex; flex-direction: column; align-items: center; border: 1rpx solid #eee; border-radius: 10rpx; padding: 16rpx 8rpx; }
|
||||
.hsd-worker.active { border-color: #FF370B; background: #FFF1ED; }
|
||||
.hsd-worker-img { width: 100rpx; height: 100rpx; border-radius: 50%; background: #f0f0f0; }
|
||||
.hsd-worker-name { font-size: 26rpx; color: #222; margin-top: 10rpx; }
|
||||
.hsd-worker-exp { font-size: 20rpx; color: #999; margin-top: 4rpx; }
|
||||
.hsd-detail-img { width: 100%; display: block; }
|
||||
.hsd-bottom { position: fixed; left: 0; right: 0; bottom: 0; background: #fff; display: flex; align-items: center; padding: 16rpx 24rpx calc(16rpx + env(safe-area-inset-bottom)); box-shadow: 0 -4rpx 20rpx rgba(0,0,0,0.04); }
|
||||
.hsd-bottom-price { flex: 1; font-size: 26rpx; color: #333; }
|
||||
.hsd-bottom-price text { color: #FF370B; font-size: 36rpx; font-weight: 600; }
|
||||
.hsd-bottom-btn { background: linear-gradient(91deg, #FF7658, #FF370B); color: #fff; font-size: 30rpx; padding: 20rpx 60rpx; border-radius: 44rpx; }
|
||||
</style>
|
||||
@ -1,124 +0,0 @@
|
||||
<template>
|
||||
<view class="hs-page">
|
||||
<!-- 到家/家政 Tab -->
|
||||
<view class="hs-tabs">
|
||||
<view class="hs-tab" :class="{ active: serviceType === 1 }" @tap="switchType(1)">到家服务</view>
|
||||
<view class="hs-tab" :class="{ active: serviceType === 2 }" @tap="switchType(2)">家政服务</view>
|
||||
</view>
|
||||
|
||||
<view class="hs-body">
|
||||
<!-- 左侧分类 -->
|
||||
<scroll-view class="hs-cate" scroll-y>
|
||||
<view class="hs-cate-item" :class="{ active: currentCate === 0 }" @tap="selectCate(0)">全部</view>
|
||||
<view class="hs-cate-item" :class="{ active: currentCate === item.id }"
|
||||
v-for="item in categoryList" :key="item.id" @tap="selectCate(item.id)">
|
||||
{{ item.category_name }}
|
||||
</view>
|
||||
</scroll-view>
|
||||
|
||||
<!-- 右侧服务列表 -->
|
||||
<scroll-view class="hs-list" scroll-y @scrolltolower="loadMore">
|
||||
<view class="hs-card" v-for="item in serviceList" :key="item.id" @tap="toDetail(item)">
|
||||
<image class="hs-card-pic" :src="picUrl + item.cover_pic" mode="aspectFill" />
|
||||
<view class="hs-card-info">
|
||||
<view class="hs-card-name">{{ item.service_name }}</view>
|
||||
<view class="hs-card-desc">{{ item.price_desc }}</view>
|
||||
<view class="hs-card-foot">
|
||||
<text class="hs-card-tag">{{ serviceType === 1 ? '到家' : '家政' }}</text>
|
||||
<text class="hs-card-btn">查看</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="serviceList.length === 0" class="hs-empty">暂无服务</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { request, picUrl, NavgateTo } from '@/utils'
|
||||
import { apiArr } from '@/api/homeService'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
picUrl,
|
||||
serviceType: 1,
|
||||
categoryList: [],
|
||||
currentCate: 0,
|
||||
serviceList: [],
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
hasMore: true
|
||||
}
|
||||
},
|
||||
onLoad() {
|
||||
this.loadCategory()
|
||||
this.loadList(true)
|
||||
},
|
||||
methods: {
|
||||
switchType(t) {
|
||||
if (this.serviceType === t) return
|
||||
this.serviceType = t
|
||||
this.currentCate = 0
|
||||
this.loadCategory()
|
||||
this.loadList(true)
|
||||
},
|
||||
selectCate(id) {
|
||||
this.currentCate = id
|
||||
this.loadList(true)
|
||||
},
|
||||
loadCategory() {
|
||||
request(apiArr.categoryList, 'POST', { service_type: this.serviceType }, {}, false).then(res => {
|
||||
this.categoryList = res.rows || []
|
||||
})
|
||||
},
|
||||
loadList(reset) {
|
||||
if (reset) {
|
||||
this.pageNum = 1
|
||||
this.hasMore = true
|
||||
this.serviceList = []
|
||||
}
|
||||
if (!this.hasMore) return
|
||||
request(apiArr.serviceList, 'POST', {
|
||||
service_type: this.serviceType,
|
||||
category_id: this.currentCate,
|
||||
page_num: this.pageNum,
|
||||
page_size: this.pageSize
|
||||
}, {}, false).then(res => {
|
||||
const rows = res.rows || []
|
||||
this.serviceList = this.serviceList.concat(rows)
|
||||
this.hasMore = rows.length === this.pageSize
|
||||
this.pageNum++
|
||||
})
|
||||
},
|
||||
loadMore() {
|
||||
this.loadList(false)
|
||||
},
|
||||
toDetail(item) {
|
||||
NavgateTo('/packages/homeService/detail/index?id=' + item.id)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.hs-page { display: flex; flex-direction: column; height: 100vh; background: #f5f5f5; }
|
||||
.hs-tabs { display: flex; background: #fff; }
|
||||
.hs-tab { flex: 1; text-align: center; padding: 26rpx 0; font-size: 28rpx; color: #666; }
|
||||
.hs-tab.active { color: #FF370B; font-weight: 600; border-bottom: 4rpx solid #FF370B; }
|
||||
.hs-body { flex: 1; display: flex; overflow: hidden; }
|
||||
.hs-cate { width: 180rpx; background: #fafafa; height: 100%; }
|
||||
.hs-cate-item { padding: 28rpx 16rpx; font-size: 26rpx; color: #555; text-align: center; }
|
||||
.hs-cate-item.active { background: #fff; color: #FF370B; font-weight: 600; }
|
||||
.hs-list { flex: 1; padding: 20rpx; box-sizing: border-box; }
|
||||
.hs-card { display: flex; background: #fff; border-radius: 12rpx; padding: 16rpx; margin-bottom: 16rpx; }
|
||||
.hs-card-pic { width: 200rpx; height: 200rpx; border-radius: 8rpx; flex-shrink: 0; background: #f0f0f0; }
|
||||
.hs-card-info { flex: 1; margin-left: 18rpx; display: flex; flex-direction: column; min-width: 0; }
|
||||
.hs-card-name { font-size: 30rpx; color: #222; font-weight: 600; }
|
||||
.hs-card-desc { font-size: 24rpx; color: #999; margin-top: 12rpx; flex: 1; }
|
||||
.hs-card-foot { display: flex; align-items: center; justify-content: space-between; }
|
||||
.hs-card-tag { font-size: 20rpx; color: #FF370B; border: 1rpx solid #FFD9CD; border-radius: 6rpx; padding: 2rpx 10rpx; }
|
||||
.hs-card-btn { background: linear-gradient(91deg, #FF7658, #FF370B); color: #fff; font-size: 24rpx; padding: 8rpx 28rpx; border-radius: 30rpx; }
|
||||
.hs-empty { text-align: center; color: #999; font-size: 26rpx; padding: 80rpx 0; }
|
||||
</style>
|
||||
@ -1,66 +0,0 @@
|
||||
<template>
|
||||
<view class="hsc-page">
|
||||
<view class="hsc-list">
|
||||
<view class="hsc-card" v-for="c in contracts" :key="c.id" @tap="toDetail(c)">
|
||||
<view class="hsc-head">
|
||||
<text class="hsc-no">{{ c.contract_no }}</text>
|
||||
<text class="hsc-status" :class="'st' + c.status">{{ statusText(c.status) }}</text>
|
||||
</view>
|
||||
<view class="hsc-body">
|
||||
<view class="hsc-name">{{ c.contract_name }}</view>
|
||||
<view class="hsc-row">月薪:<text class="hsc-amount">¥{{ c.month_amount }}</text></view>
|
||||
<view class="hsc-row">结算:{{ c.settle_mode === 1 ? '平台月账单' : '线下自付' }}</view>
|
||||
<view class="hsc-row">合同期:{{ fmtDate(c.start_date) }} ~ {{ fmtDate(c.end_date) }}</view>
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="contracts.length === 0" class="hsc-empty">暂无家政合同</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { request, NavgateTo } from '@/utils'
|
||||
import { apiArr } from '@/api/homeService'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return { contracts: [] }
|
||||
},
|
||||
onShow() {
|
||||
this.loadContracts()
|
||||
},
|
||||
methods: {
|
||||
loadContracts() {
|
||||
const userId = uni.getStorageSync('userId')
|
||||
request(apiArr.contractList, 'POST', { user_id: userId, page_num: 1, page_size: 50 }, {}, false).then(res => {
|
||||
this.contracts = res.rows || []
|
||||
})
|
||||
},
|
||||
statusText(s) {
|
||||
const map = { 1: '待签署', 2: '生效中', 3: '已到期', 4: '已解除', 5: '线下结算' }
|
||||
return map[s] || ''
|
||||
},
|
||||
fmtDate(v) {
|
||||
return v ? String(v).slice(0, 10) : ''
|
||||
},
|
||||
toDetail(c) {
|
||||
NavgateTo('/packages/homeService/contractDetail/index?id=' + c.id)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.hsc-page { background: #f5f5f5; min-height: 100vh; padding: 20rpx; }
|
||||
.hsc-card { background: #fff; border-radius: 16rpx; padding: 24rpx; margin-bottom: 20rpx; }
|
||||
.hsc-head { display: flex; justify-content: space-between; align-items: center; border-bottom: 1rpx solid #f2f2f2; padding-bottom: 16rpx; }
|
||||
.hsc-no { font-size: 26rpx; color: #888; }
|
||||
.hsc-status { font-size: 26rpx; color: #FF370B; }
|
||||
.hsc-status.st2 { color: #07c160; }
|
||||
.hsc-status.st3, .hsc-status.st4 { color: #999; }
|
||||
.hsc-body { padding-top: 16rpx; }
|
||||
.hsc-name { font-size: 30rpx; color: #222; font-weight: 600; margin-bottom: 12rpx; }
|
||||
.hsc-row { font-size: 26rpx; color: #555; margin-top: 8rpx; }
|
||||
.hsc-amount { color: #FF370B; font-weight: 600; }
|
||||
.hsc-empty { text-align: center; color: #999; font-size: 28rpx; padding-top: 120rpx; }
|
||||
</style>
|
||||
@ -1,95 +0,0 @@
|
||||
<template>
|
||||
<view class="hmb-page">
|
||||
<view class="hmb-list">
|
||||
<view class="hmb-card" v-for="b in bills" :key="b.id">
|
||||
<view class="hmb-head">
|
||||
<text class="hmb-no">{{ b.bill_no }}</text>
|
||||
<text class="hmb-status" :class="b.pay_status === 1 ? 'status-warn' : b.pay_status === 2 ? 'status-ok' : ''">{{ statusText(b.pay_status) }}</text>
|
||||
</view>
|
||||
<view class="hmb-body" @tap="toContract(b)">
|
||||
<image class="hmb-pic" :src="picUrl + (b.service_pic || '')" mode="aspectFill" />
|
||||
<view class="hmb-info">
|
||||
<view class="hmb-name">{{ b.service_name }}</view>
|
||||
<view class="hmb-month">{{ b.bill_month }} 月度账单</view>
|
||||
<view class="hmb-amount">¥{{ b.amount }}</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="hmb-foot">
|
||||
<view class="hmb-link" @tap.stop="toContract(b)">查看合同 ›</view>
|
||||
<view class="hmb-pay" v-if="b.pay_status === 1" @tap.stop="payBill(b)">去支付</view>
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="bills.length === 0" class="hmb-empty">暂无待支付月账单</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { request, picUrl, NavgateTo } from '@/utils'
|
||||
import { apiArr } from '@/api/homeService'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return { picUrl, bills: [] }
|
||||
},
|
||||
onShow() {
|
||||
this.loadBills()
|
||||
},
|
||||
methods: {
|
||||
loadBills() {
|
||||
const userId = uni.getStorageSync('userId')
|
||||
request(apiArr.userMonthlyBillList, 'POST', { user_id: userId, page_num: 1, page_size: 50 }, {}, false).then(res => {
|
||||
this.bills = res.rows || []
|
||||
})
|
||||
},
|
||||
statusText(payStatus) {
|
||||
return payStatus === 1 ? '待支付' : payStatus === 2 ? '已支付' : payStatus === 3 ? '已退款' : ''
|
||||
},
|
||||
toContract(b) {
|
||||
NavgateTo('/packages/homeService/contractDetail/index?id=' + b.contract_id)
|
||||
},
|
||||
payBill(b) {
|
||||
const userId = uni.getStorageSync('userId')
|
||||
request(apiArr.userMonthlyBillPreOrder, 'POST', { bill_id: b.id, user_id: userId, trans_type: '71' }).then(pay => {
|
||||
uni.requestPayment({
|
||||
provider: 'wxpay',
|
||||
timeStamp: pay.timeStamp,
|
||||
nonceStr: pay.nonceStr,
|
||||
package: pay.package,
|
||||
signType: pay.signType || 'RSA',
|
||||
paySign: pay.paySign,
|
||||
success: () => {
|
||||
request(apiArr.userMonthlyBillTradeQuery, 'POST', { bill_id: b.id }, {}, false).finally(() => {
|
||||
uni.showToast({ title: '支付成功', icon: 'none' })
|
||||
this.loadBills()
|
||||
})
|
||||
},
|
||||
fail: () => { uni.showToast({ title: '支付已取消', icon: 'none' }) }
|
||||
})
|
||||
}).catch(err => {
|
||||
uni.showToast({ title: err.errMsg || '发起支付失败', icon: 'none' })
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.hmb-page { background: #f5f5f5; min-height: 100vh; padding: 20rpx; box-sizing: border-box; }
|
||||
.hmb-list {}
|
||||
.hmb-card { background: #fff; border-radius: 12rpx; padding: 20rpx; margin-bottom: 18rpx; border-left: 6rpx solid #FF370B; }
|
||||
.hmb-head { display: flex; justify-content: space-between; align-items: center; font-size: 24rpx; color: #999; margin-bottom: 16rpx; }
|
||||
.hmb-status { font-size: 26rpx; }
|
||||
.status-warn { color: #FF9800; }
|
||||
.status-ok { color: #4CAF50; }
|
||||
.hmb-body { display: flex; }
|
||||
.hmb-pic { width: 150rpx; height: 150rpx; border-radius: 8rpx; background: #f0f0f0; flex-shrink: 0; }
|
||||
.hmb-info { flex: 1; margin-left: 18rpx; display: flex; flex-direction: column; }
|
||||
.hmb-name { font-size: 30rpx; color: #222; font-weight: 600; }
|
||||
.hmb-month { font-size: 24rpx; color: #666; margin-top: 8rpx; }
|
||||
.hmb-amount { font-size: 32rpx; color: #FF370B; font-weight: 600; margin-top: auto; }
|
||||
.hmb-foot { display: flex; justify-content: space-between; align-items: center; margin-top: 16rpx; }
|
||||
.hmb-link { font-size: 24rpx; color: #666; }
|
||||
.hmb-pay { background: linear-gradient(91deg, #FF7658, #FF370B); color: #fff; font-size: 26rpx; padding: 12rpx 40rpx; border-radius: 40rpx; margin-left: auto; }
|
||||
.hmb-empty { text-align: center; color: #999; font-size: 26rpx; padding: 80rpx 0; }
|
||||
</style>
|
||||
@ -1,108 +0,0 @@
|
||||
<template>
|
||||
<view class="hsm-page">
|
||||
<view class="hsm-list">
|
||||
<view class="hsm-card" v-for="o in orders" :key="o.id">
|
||||
<view class="hsm-head">
|
||||
<text class="hsm-no">{{ o.order_no }}</text>
|
||||
<text class="hsm-status">{{ statusText(o) }}</text>
|
||||
</view>
|
||||
<view class="hsm-body" @tap="toDetail(o)">
|
||||
<image class="hsm-pic" :src="picUrl + (o.service_pic || '')" mode="aspectFill" />
|
||||
<view class="hsm-info">
|
||||
<view class="hsm-name">{{ o.service_name }}</view>
|
||||
<view class="hsm-kind">{{ kindText(o.order_kind) }}</view>
|
||||
<view class="hsm-amount">¥{{ o.amount }}</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="hsm-foot" v-if="o.pay_status === 1 && o.status !== 5 && o.status !== 4">
|
||||
<view class="hsm-cancel" @tap="cancelOrder(o)">取消订单</view>
|
||||
<view class="hsm-pay" @tap="payOrder(o)">去支付</view>
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="orders.length === 0" class="hsm-empty">暂无服务订单</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { request, picUrl, NavgateTo } from '@/utils'
|
||||
import { apiArr } from '@/api/homeService'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return { picUrl, orders: [] }
|
||||
},
|
||||
onShow() {
|
||||
this.loadOrders()
|
||||
},
|
||||
methods: {
|
||||
loadOrders() {
|
||||
const userId = uni.getStorageSync('userId')
|
||||
request(apiArr.orderList, 'POST', { user_id: userId, page_num: 1, page_size: 50 }, {}, false).then(res => {
|
||||
this.orders = res.rows || []
|
||||
})
|
||||
},
|
||||
kindText(k) {
|
||||
return k === 1 ? '定金/上门费' : k === 2 ? '补差/尾款' : k === 3 ? '月账单' : ''
|
||||
},
|
||||
statusText(o) {
|
||||
if (o.status === 5) return '已取消'
|
||||
if (o.status === 4) return '已完成'
|
||||
if (o.pay_status === 1) return '待支付'
|
||||
const map = { 1: '待上门', 2: '服务中', 3: '待补款' }
|
||||
return map[o.status] || ''
|
||||
},
|
||||
toDetail(o) {
|
||||
NavgateTo('/packages/homeService/orderDetail/index?id=' + o.id)
|
||||
},
|
||||
cancelOrder(o) {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '确定取消该订单吗?',
|
||||
success: (r) => {
|
||||
if (!r.confirm) return
|
||||
const userId = uni.getStorageSync('userId')
|
||||
request(apiArr.orderCancel, 'POST', { id: o.id, user_id: Number(userId) || 0 }).then(() => {
|
||||
uni.showToast({ title: '已取消', icon: 'none' })
|
||||
this.loadOrders()
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
payOrder(o) {
|
||||
const userId = uni.getStorageSync('userId')
|
||||
request(apiArr.preorder, 'POST', { order_id: o.id, user_id: userId, trans_type: '71' }).then(pay => {
|
||||
uni.requestPayment({
|
||||
provider: 'wxpay',
|
||||
timeStamp: pay.timeStamp,
|
||||
nonceStr: pay.nonceStr,
|
||||
package: pay.package,
|
||||
signType: pay.signType || 'RSA',
|
||||
paySign: pay.paySign,
|
||||
success: () => {
|
||||
request(apiArr.tradeQuery, 'POST', { order_id: o.id }, {}, false).finally(() => this.loadOrders())
|
||||
},
|
||||
fail: () => { uni.showToast({ title: '支付已取消', icon: 'none' }) }
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.hsm-page { background: #f5f5f5; min-height: 100vh; padding: 20rpx; box-sizing: border-box; }
|
||||
.hsm-card { background: #fff; border-radius: 12rpx; padding: 20rpx; margin-bottom: 18rpx; }
|
||||
.hsm-head { display: flex; justify-content: space-between; align-items: center; font-size: 24rpx; color: #999; margin-bottom: 16rpx; }
|
||||
.hsm-status { color: #FF370B; }
|
||||
.hsm-body { display: flex; }
|
||||
.hsm-pic { width: 150rpx; height: 150rpx; border-radius: 8rpx; background: #f0f0f0; flex-shrink: 0; }
|
||||
.hsm-info { flex: 1; margin-left: 18rpx; display: flex; flex-direction: column; }
|
||||
.hsm-name { font-size: 30rpx; color: #222; font-weight: 600; }
|
||||
.hsm-kind { font-size: 24rpx; color: #999; margin-top: 10rpx; flex: 1; }
|
||||
.hsm-amount { font-size: 32rpx; color: #FF370B; font-weight: 600; }
|
||||
.hsm-foot { display: flex; justify-content: flex-end; align-items: center; margin-top: 16rpx; }
|
||||
.hsm-cancel { border: 1rpx solid #ccc; color: #666; font-size: 26rpx; padding: 11rpx 36rpx; border-radius: 40rpx; margin-right: 20rpx; }
|
||||
.hsm-pay { background: linear-gradient(91deg, #FF7658, #FF370B); color: #fff; font-size: 26rpx; padding: 12rpx 40rpx; border-radius: 40rpx; }
|
||||
.hsm-empty { text-align: center; color: #999; font-size: 26rpx; padding: 80rpx 0; }
|
||||
</style>
|
||||
@ -1,221 +0,0 @@
|
||||
<template>
|
||||
<view class="hso-page">
|
||||
<view class="hso-card">
|
||||
<view class="hso-svc">{{ params.service_name }}</view>
|
||||
<view class="hso-deposit">定金 ¥{{ params.deposit }}</view>
|
||||
</view>
|
||||
<view class="hso-form">
|
||||
<view class="hso-row">
|
||||
<text class="hso-label">联系人</text>
|
||||
<input class="hso-input" v-model="contactName" placeholder="请输入联系人" />
|
||||
</view>
|
||||
<view class="hso-row">
|
||||
<text class="hso-label">联系电话</text>
|
||||
<input class="hso-input" type="number" v-model="contactPhone" placeholder="请输入联系电话" maxlength="11" />
|
||||
</view>
|
||||
<view class="hso-row">
|
||||
<text class="hso-label">小区地址</text>
|
||||
<input class="hso-input" v-model="serviceAddress" placeholder="请选择或输入小区地址" />
|
||||
<text class="hso-map-btn" @tap="chooseLocation">地图选点</text>
|
||||
</view>
|
||||
<view class="hso-row">
|
||||
<text class="hso-label">门牌号</text>
|
||||
<input class="hso-input" v-model="houseNumber" placeholder="如:1栋1单元103室" />
|
||||
</view>
|
||||
<view class="hso-row" @tap="showDate = true">
|
||||
<text class="hso-label">上门时间</text>
|
||||
<text class="hso-input" :class="{ ph: !serviceTime }">{{ serviceTime || '请选择上门时间' }}</text>
|
||||
</view>
|
||||
<view class="hso-row hso-row--col">
|
||||
<text class="hso-label">备注</text>
|
||||
<textarea class="hso-textarea" v-model="remark" placeholder="选填" />
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="hso-bottom">
|
||||
<view class="hso-bottom-price">定金 <text>¥{{ params.deposit }}</text></view>
|
||||
<view class="hso-bottom-btn" @tap="submit">提交并支付</view>
|
||||
</view>
|
||||
|
||||
<u-datetime-picker :show="showDate" :value="dateValue" mode="datetime" @confirm="onDate" @cancel="showDate = false" @close="showDate = false" />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { request, NavgateTo, isPhone } from '@/utils'
|
||||
import { apiArr } from '@/api/homeService'
|
||||
import { apiArr as commApi } from '@/api/community'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
params: {},
|
||||
contactName: '',
|
||||
contactPhone: '',
|
||||
serviceAddress: '',
|
||||
houseNumber: '',
|
||||
serviceTime: '',
|
||||
dateValue: Date.now(),
|
||||
remark: '',
|
||||
showDate: false,
|
||||
submitting: false
|
||||
}
|
||||
},
|
||||
onLoad(options) {
|
||||
if (options.params) {
|
||||
try { this.params = JSON.parse(decodeURIComponent(options.params)) } catch (e) { this.params = {} }
|
||||
}
|
||||
// 先用本地缓存兜底(秒显),再异步拉后台房产数据覆盖为准确值
|
||||
this.fillFromStorage()
|
||||
this.loadBoundHouse()
|
||||
// 默认上门时间:当前时间 3 小时之后的整点
|
||||
this.initDefaultTime()
|
||||
},
|
||||
methods: {
|
||||
// 本地缓存兜底:小区地址(详细地址在前 + 小区名)、门牌号
|
||||
fillFromStorage() {
|
||||
const addr = uni.getStorageSync('currentCommunityAddr')
|
||||
const comm = uni.getStorageSync('changeCommData')
|
||||
const commName = (comm && comm.name) ? comm.name : ''
|
||||
if (addr) {
|
||||
this.serviceAddress = (addr + ' ' + commName).trim()
|
||||
} else if (commName) {
|
||||
this.serviceAddress = commName
|
||||
}
|
||||
const roomNo = uni.getStorageSync('currentRoomNo')
|
||||
if (roomNo) this.houseNumber = roomNo
|
||||
},
|
||||
// 拉取后台已绑定房产:用真实小区地址 + room_name 填充地址与门牌
|
||||
loadBoundHouse() {
|
||||
const loc = uni.getStorageSync('location') || {}
|
||||
const comm = uni.getStorageSync('changeCommData')
|
||||
request(commApi.commInfo, 'POST', {
|
||||
user_id: uni.getStorageSync('userId'),
|
||||
longitude: loc.lng,
|
||||
latitude: loc.lat,
|
||||
page_num: 1,
|
||||
page_size: 20
|
||||
}, { silent: false }).then(res => {
|
||||
const rows = (res && res.rows) ? res.rows : []
|
||||
if (!rows.length) return
|
||||
// 优先匹配当前选中的小区,否则取第一个
|
||||
let target = null
|
||||
if (comm && comm.id) target = rows.find(r => r.community_id === comm.id)
|
||||
if (!target) target = rows[0]
|
||||
const commName = target.name || ''
|
||||
if (target.addr) {
|
||||
this.serviceAddress = (target.addr + ' ' + commName).trim()
|
||||
} else if (commName) {
|
||||
this.serviceAddress = commName
|
||||
}
|
||||
const owner = (target.room_owner_list && target.room_owner_list.length) ? target.room_owner_list[0] : null
|
||||
if (owner && owner.room_name) this.houseNumber = owner.room_name
|
||||
}).catch(() => {})
|
||||
},
|
||||
// 默认上门时间 = 当前时间 + 3 小时,并向上取整到整点
|
||||
initDefaultTime() {
|
||||
const d = new Date()
|
||||
d.setHours(d.getHours() + 3)
|
||||
// 有分/秒/毫秒则进位到下一个整点
|
||||
if (d.getMinutes() > 0 || d.getSeconds() > 0 || d.getMilliseconds() > 0) {
|
||||
d.setHours(d.getHours() + 1)
|
||||
}
|
||||
d.setMinutes(0, 0, 0)
|
||||
this.dateValue = d.getTime()
|
||||
this.serviceTime = this.formatTime(d)
|
||||
},
|
||||
formatTime(d) {
|
||||
const p = n => String(n).padStart(2, '0')
|
||||
return `${d.getFullYear()}-${p(d.getMonth() + 1)}-${p(d.getDate())} ${p(d.getHours())}:${p(d.getMinutes())}`
|
||||
},
|
||||
// 地图选点:选择后回填地址(详细地址在前,小区/点位名称在后)
|
||||
chooseLocation() {
|
||||
const loc = uni.getStorageSync('location') || {}
|
||||
uni.chooseLocation({
|
||||
latitude: loc.lat,
|
||||
longitude: loc.lng,
|
||||
success: (res) => {
|
||||
const detail = res.name ? (res.address + ' ' + res.name) : res.address
|
||||
this.serviceAddress = (detail || '').trim()
|
||||
},
|
||||
fail: (err) => {
|
||||
if (err && err.errMsg && err.errMsg.indexOf('cancel') === -1) {
|
||||
uni.showToast({ title: '地图选点失败,请检查定位权限', icon: 'none' })
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
onDate(e) {
|
||||
const d = new Date(e.value)
|
||||
this.dateValue = d.getTime()
|
||||
this.serviceTime = this.formatTime(d)
|
||||
this.showDate = false
|
||||
},
|
||||
submit() {
|
||||
if (!this.contactName) { uni.showToast({ title: '请输入联系人', icon: 'none' }); return }
|
||||
if (!isPhone(this.contactPhone)) { uni.showToast({ title: '联系电话格式不正确', icon: 'none' }); return }
|
||||
if (!this.serviceAddress) { uni.showToast({ title: '请选择或输入小区地址', icon: 'none' }); return }
|
||||
if (!this.houseNumber) { uni.showToast({ title: '请输入门牌号', icon: 'none' }); return }
|
||||
if (this.submitting) return
|
||||
this.submitting = true
|
||||
const userId = uni.getStorageSync('userId')
|
||||
const fullAddress = (this.serviceAddress + ' ' + this.houseNumber).trim()
|
||||
request(apiArr.orderCreate, 'POST', {
|
||||
user_id: userId,
|
||||
service_info_id: this.params.service_info_id,
|
||||
sku_id: this.params.sku_id,
|
||||
employee_id: this.params.employee_id,
|
||||
service_address: fullAddress,
|
||||
contact_name: this.contactName,
|
||||
contact_phone: this.contactPhone,
|
||||
service_time: this.serviceTime,
|
||||
remark: this.remark
|
||||
}).then(res => {
|
||||
this.payOrder(res.id, userId)
|
||||
}).catch(() => { this.submitting = false })
|
||||
},
|
||||
payOrder(orderId, userId) {
|
||||
request(apiArr.preorder, 'POST', { order_id: orderId, user_id: userId, trans_type: '71' }).then(pay => {
|
||||
uni.requestPayment({
|
||||
provider: 'wxpay',
|
||||
timeStamp: pay.timeStamp,
|
||||
nonceStr: pay.nonceStr,
|
||||
package: pay.package,
|
||||
signType: pay.signType || 'RSA',
|
||||
paySign: pay.paySign,
|
||||
success: () => {
|
||||
// 支付成功后查单回写
|
||||
request(apiArr.tradeQuery, 'POST', { order_id: orderId }, {}, false).finally(() => {
|
||||
uni.redirectTo({ url: '/packages/homeService/myOrders/index' })
|
||||
})
|
||||
},
|
||||
fail: () => {
|
||||
this.submitting = false
|
||||
uni.showToast({ title: '支付已取消', icon: 'none' })
|
||||
uni.redirectTo({ url: '/packages/homeService/myOrders/index' })
|
||||
}
|
||||
})
|
||||
}).catch(() => { this.submitting = false })
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.hso-page { background: #f5f5f5; min-height: 100vh; padding-bottom: 130rpx; }
|
||||
.hso-card { background: #fff; padding: 28rpx 24rpx; display: flex; align-items: center; justify-content: space-between; }
|
||||
.hso-svc { font-size: 30rpx; color: #222; font-weight: 600; }
|
||||
.hso-deposit { font-size: 30rpx; color: #FF370B; font-weight: 600; }
|
||||
.hso-form { background: #fff; margin-top: 16rpx; padding: 0 24rpx; }
|
||||
.hso-row { display: flex; align-items: center; padding: 26rpx 0; border-bottom: 1rpx solid #f2f2f2; }
|
||||
.hso-row--col { flex-direction: column; align-items: flex-start; }
|
||||
.hso-label { width: 160rpx; font-size: 28rpx; color: #333; flex-shrink: 0; }
|
||||
.hso-input { flex: 1; font-size: 28rpx; color: #222; }
|
||||
.hso-input.ph { color: #b7b7b7; }
|
||||
.hso-map-btn { flex-shrink: 0; margin-left: 16rpx; font-size: 26rpx; color: #FF370B; padding: 6rpx 16rpx; border: 1rpx solid #FF370B; border-radius: 28rpx; }
|
||||
.hso-textarea { width: 100%; height: 120rpx; font-size: 28rpx; margin-top: 12rpx; }
|
||||
.hso-bottom { position: fixed; left: 0; right: 0; bottom: 0; background: #fff; display: flex; align-items: center; padding: 16rpx 24rpx calc(16rpx + env(safe-area-inset-bottom)); box-shadow: 0 -4rpx 20rpx rgba(0,0,0,0.04); }
|
||||
.hso-bottom-price { flex: 1; font-size: 26rpx; color: #333; }
|
||||
.hso-bottom-price text { color: #FF370B; font-size: 36rpx; font-weight: 600; }
|
||||
.hso-bottom-btn { background: linear-gradient(91deg, #FF7658, #FF370B); color: #fff; font-size: 30rpx; padding: 20rpx 60rpx; border-radius: 44rpx; }
|
||||
</style>
|
||||
@ -1,66 +0,0 @@
|
||||
<template>
|
||||
<view class="hsod-page" v-if="order.id">
|
||||
<view class="hsod-status">{{ statusText }}</view>
|
||||
<view class="hsod-card">
|
||||
<image class="hsod-pic" :src="picUrl + (order.service_pic || '')" mode="aspectFill" />
|
||||
<view class="hsod-info">
|
||||
<view class="hsod-name">{{ order.service_name }}</view>
|
||||
<view class="hsod-kind">{{ kindText(order.order_kind) }}</view>
|
||||
<view class="hsod-amount">¥{{ order.amount }}</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="hsod-block">
|
||||
<view class="hsod-row"><text>订单号</text><text>{{ order.order_no }}</text></view>
|
||||
<view class="hsod-row"><text>联系人</text><text>{{ order.contact_name }}</text></view>
|
||||
<view class="hsod-row"><text>联系电话</text><text>{{ order.contact_phone }}</text></view>
|
||||
<view class="hsod-row"><text>服务地址</text><text>{{ order.service_address }}</text></view>
|
||||
<view class="hsod-row" v-if="order.service_time"><text>上门时间</text><text>{{ order.service_time }}</text></view>
|
||||
<view class="hsod-row" v-if="order.remark"><text>备注</text><text>{{ order.remark }}</text></view>
|
||||
<view class="hsod-row"><text>支付状态</text><text>{{ order.pay_status === 2 ? '已支付' : '待支付' }}</text></view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { request, picUrl } from '@/utils'
|
||||
import { apiArr } from '@/api/homeService'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return { picUrl, order: {} }
|
||||
},
|
||||
onLoad(options) {
|
||||
request(apiArr.orderInfo, 'POST', { id: Number(options.id) }, {}, false).then(res => {
|
||||
this.order = res || {}
|
||||
})
|
||||
},
|
||||
computed: {
|
||||
statusText() {
|
||||
const o = this.order
|
||||
if (o.pay_status === 1) return '待支付'
|
||||
const map = { 1: '待上门', 2: '服务中', 3: '待补款', 4: '已完成', 5: '已取消' }
|
||||
return map[o.status] || ''
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
kindText(k) {
|
||||
return k === 1 ? '定金/上门费' : k === 2 ? '补差/尾款' : k === 3 ? '月账单' : ''
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.hsod-page { background: #f5f5f5; min-height: 100vh; }
|
||||
.hsod-status { background: linear-gradient(91deg, #FF7658, #FF370B); color: #fff; font-size: 34rpx; font-weight: 600; padding: 40rpx 24rpx; }
|
||||
.hsod-card { background: #fff; display: flex; padding: 24rpx; margin-top: 16rpx; }
|
||||
.hsod-pic { width: 150rpx; height: 150rpx; border-radius: 8rpx; background: #f0f0f0; flex-shrink: 0; }
|
||||
.hsod-info { flex: 1; margin-left: 18rpx; display: flex; flex-direction: column; }
|
||||
.hsod-name { font-size: 30rpx; color: #222; font-weight: 600; }
|
||||
.hsod-kind { font-size: 24rpx; color: #999; margin-top: 10rpx; flex: 1; }
|
||||
.hsod-amount { font-size: 32rpx; color: #FF370B; font-weight: 600; }
|
||||
.hsod-block { background: #fff; margin-top: 16rpx; padding: 8rpx 24rpx; }
|
||||
.hsod-row { display: flex; justify-content: space-between; font-size: 26rpx; color: #333; padding: 22rpx 0; border-bottom: 1rpx solid #f5f5f5; }
|
||||
.hsod-row text:first-child { color: #999; }
|
||||
.hsod-row:last-child { border-bottom: none; }
|
||||
</style>
|
||||
@ -1,307 +0,0 @@
|
||||
<template>
|
||||
<view class="hsw-page">
|
||||
<!-- 顶部Tab:全部/待上门/服务中/已完成/月账单 -->
|
||||
<view class="hsw-tabs">
|
||||
<view
|
||||
class="hsw-tab"
|
||||
:class="{ active: statusTab === item.v }"
|
||||
v-for="item in orderTabs"
|
||||
:key="item.v"
|
||||
@tap="switchStatus(item.v)"
|
||||
>{{ item.t }}</view>
|
||||
</view>
|
||||
<!-- 月账单子Tab -->
|
||||
<view class="hsw-tabs hsw-tabs-bill" v-if="showMonthlyBill">
|
||||
<view
|
||||
class="hsw-tab"
|
||||
:class="{ active: billTab === item.v }"
|
||||
v-for="item in billTabs"
|
||||
:key="item.v"
|
||||
@tap="switchBillTab(item.v)"
|
||||
>{{ item.t }}</view>
|
||||
</view>
|
||||
|
||||
<!-- 列表区域 -->
|
||||
<scroll-view class="hsw-list" scroll-y>
|
||||
<!-- 普通服务单(非月账单模式) -->
|
||||
<block v-if="!showMonthlyBill">
|
||||
<view class="hsw-card" v-for="o in orders" :key="o.id">
|
||||
<view class="hsw-head">
|
||||
<text class="hsw-no">{{ o.order_no }}</text>
|
||||
<text class="hsw-kind">{{ kindText(o.order_kind) }}</text>
|
||||
</view>
|
||||
<view class="hsw-row"><text>服务</text><text>{{ o.service_name }}</text></view>
|
||||
<view class="hsw-row"><text>客户</text><text>{{ o.contact_name }} {{ o.contact_phone }}</text></view>
|
||||
<view class="hsw-row"><text>地址</text><text>{{ o.service_address }}</text></view>
|
||||
<view class="hsw-row"><text>金额</text><text class="hsw-amount">¥{{ o.amount }}</text></view>
|
||||
<view class="hsw-foot">
|
||||
<view class="hsw-btn ghost" v-if="o.status === 1" @tap="updateStatus(o, 2)">开始服务</view>
|
||||
<view class="hsw-btn" v-if="o.status === 2 && o.order_kind === 1" @tap="openExtra(o)">代客补差</view>
|
||||
<view class="hsw-btn ghost" v-if="o.status === 2" @tap="updateStatus(o, 4)">完成服务</view>
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="orders.length === 0" class="hsw-empty">暂无服务单</view>
|
||||
</block>
|
||||
<!-- 月账单列表(师傅可见所有状态) -->
|
||||
<block v-else>
|
||||
<view class="hsw-card hsw-bill-card" v-for="b in bills" :key="b.id">
|
||||
<view class="hsw-head">
|
||||
<text class="hsw-no">{{ b.bill_no }}</text>
|
||||
<text class="hsw-kind" :class="b.push_status === 0 ? 'status-warn' : b.push_status === 1 ? 'status-info' : b.push_status === 2 ? 'status-ok' : 'status-cancel'">{{ pushStatusText(b.push_status) }}</text>
|
||||
</view>
|
||||
<view class="hsw-row"><text>服务</text><text>{{ b.service_name }}</text></view>
|
||||
<view class="hsw-row"><text>客户</text><text>{{ b.contact_name }} {{ b.contact_phone }}</text></view>
|
||||
<view class="hsw-row"><text>地址</text><text>{{ b.service_address }}</text></view>
|
||||
<view class="hsw-row"><text>账单月份</text><text>{{ b.bill_month }}</text></view>
|
||||
<view class="hsw-row"><text>金额</text><text class="hsw-amount">¥{{ b.amount }}</text></view>
|
||||
<view class="hsw-foot">
|
||||
<view class="hsw-btn" v-if="b.push_status === 0" @tap="openPush(b)">推送至用户支付</view>
|
||||
<view class="hsw-btn ghost" v-if="b.push_status === 0" @tap="openReject(b)">拒绝</view>
|
||||
<view class="hsw-btn ghost" v-if="b.push_status === 1">已推送,待用户支付</view>
|
||||
<view class="hsw-btn ghost" v-if="b.push_status === 2">用户已支付</view>
|
||||
<view class="hsw-btn ghost" v-if="b.push_status === 3">已拒绝{{ b.remark ? ':' + b.remark : '' }}</view>
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="bills.length === 0" class="hsw-empty">暂无月账单</view>
|
||||
</block>
|
||||
</scroll-view>
|
||||
|
||||
<!-- 代客补差弹层 -->
|
||||
<view class="hsw-mask" v-if="showExtra" @tap.self="showExtra = false">
|
||||
<view class="hsw-dialog">
|
||||
<view class="hsw-dialog-tit">代客生成补差单</view>
|
||||
<input class="hsw-dialog-input" type="digit" v-model="extraAmount" placeholder="请输入补差金额" />
|
||||
<input class="hsw-dialog-input" v-model="extraRemark" placeholder="备注(选填)" />
|
||||
<view class="hsw-dialog-btns">
|
||||
<view class="hsw-dialog-btn cancel" @tap="showExtra = false">取消</view>
|
||||
<view class="hsw-dialog-btn ok" @tap="submitExtra">确定</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 推送月账单弹层 -->
|
||||
<view class="hsw-mask" v-if="showPush" @tap.self="showPush = false">
|
||||
<view class="hsw-dialog">
|
||||
<view class="hsw-dialog-tit">推送月账单</view>
|
||||
<view class="hsw-dialog-info">确认推送至用户端?用户支付后该账单生效。</view>
|
||||
<view class="hsw-dialog-btns">
|
||||
<view class="hsw-dialog-btn cancel" @tap="showPush = false">取消</view>
|
||||
<view class="hsw-dialog-btn ok" @tap="submitPush">确认推送</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 拒绝月账单弹层 -->
|
||||
<view class="hsw-mask" v-if="showReject" @tap.self="showReject = false">
|
||||
<view class="hsw-dialog">
|
||||
<view class="hsw-dialog-tit">拒绝月账单</view>
|
||||
<input class="hsw-dialog-input" v-model="rejectRemark" placeholder="请输入拒绝原因(选填)" />
|
||||
<view class="hsw-dialog-btns">
|
||||
<view class="hsw-dialog-btn cancel" @tap="showReject = false">取消</view>
|
||||
<view class="hsw-dialog-btn ok" @tap="submitReject">确认拒绝</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { request } from '@/utils'
|
||||
import { apiArr } from '@/api/homeService'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
employeeId: 0,
|
||||
statusTab: 0,
|
||||
orderTabs: [
|
||||
{ v: 0, t: '全部' },
|
||||
{ v: 1, t: '待上门' },
|
||||
{ v: 2, t: '服务中' },
|
||||
{ v: 4, t: '已完成' },
|
||||
{ v: -1, t: '月账单' }
|
||||
],
|
||||
showMonthlyBill: false,
|
||||
billTab: 0,
|
||||
billTabs: [
|
||||
{ v: 0, t: '全部' },
|
||||
{ v: 1, t: '待推送' },
|
||||
{ v: 2, t: '已推送' }
|
||||
],
|
||||
orders: [],
|
||||
bills: [],
|
||||
showExtra: false,
|
||||
extraOrder: null,
|
||||
extraAmount: '',
|
||||
extraRemark: '',
|
||||
showPush: false,
|
||||
showReject: false,
|
||||
pushBill: null,
|
||||
rejectBill: null,
|
||||
rejectRemark: ''
|
||||
}
|
||||
},
|
||||
onLoad(options) {
|
||||
this.employeeId = Number(options.employeeId || uni.getStorageSync('serviceEmployeeId') || 0)
|
||||
if (!this.employeeId) {
|
||||
const userId = uni.getStorageSync('userId')
|
||||
request(apiArr.workerMyInfo, 'POST', { user_id: userId }, {}, false).then(res => {
|
||||
if (res && res.is_worker && res.employee_id) {
|
||||
this.employeeId = res.employee_id
|
||||
uni.setStorageSync('serviceEmployeeId', res.employee_id)
|
||||
this.loadOrders()
|
||||
} else {
|
||||
uni.showModal({ title: '提示', content: '您还不是服务师傅,请联系商家添加', showCancel: false })
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
onShow() {
|
||||
if (this.employeeId) {
|
||||
if (this.showMonthlyBill) {
|
||||
this.loadBills()
|
||||
} else {
|
||||
this.loadOrders()
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
switchStatus(v) {
|
||||
if (v === -1) {
|
||||
this.showMonthlyBill = true
|
||||
this.billTab = 0
|
||||
this.loadBills()
|
||||
} else {
|
||||
this.showMonthlyBill = false
|
||||
this.statusTab = v
|
||||
this.loadOrders()
|
||||
}
|
||||
},
|
||||
switchBillTab(v) {
|
||||
this.billTab = v
|
||||
this.loadBills()
|
||||
},
|
||||
loadOrders() {
|
||||
request(apiArr.workerOrderList, 'POST', {
|
||||
employee_id: this.employeeId,
|
||||
status: this.statusTab,
|
||||
page_num: 1,
|
||||
page_size: 50
|
||||
}, {}, false).then(res => {
|
||||
this.orders = res.rows || []
|
||||
})
|
||||
},
|
||||
loadBills() {
|
||||
request(apiArr.workerMonthlyBillList, 'POST', {
|
||||
employee_id: this.employeeId,
|
||||
user_id: Number(uni.getStorageSync('userId')) || 0,
|
||||
page_num: 1,
|
||||
page_size: 50
|
||||
}, {}, false).then(res => {
|
||||
let rows = res.rows || []
|
||||
if (this.billTab === 1) rows = rows.filter(b => b.push_status === 0)
|
||||
if (this.billTab === 2) rows = rows.filter(b => b.push_status === 1 || b.push_status === 2)
|
||||
this.bills = rows
|
||||
})
|
||||
},
|
||||
kindText(k) {
|
||||
return k === 1 ? '定金/上门费' : k === 2 ? '补差/尾款' : k === 3 ? '月账单' : ''
|
||||
},
|
||||
pushStatusText(s) {
|
||||
return s === 0 ? '待推送' : s === 1 ? '已推送待支付' : s === 2 ? '已支付' : s === 3 ? '已拒绝' : ''
|
||||
},
|
||||
updateStatus(o, status) {
|
||||
request(apiArr.workerOrderStatus, 'POST', { order_id: o.id, status }).then(() => {
|
||||
uni.showToast({ title: '操作成功', icon: 'none' })
|
||||
this.loadOrders()
|
||||
})
|
||||
},
|
||||
openExtra(o) {
|
||||
this.extraOrder = o
|
||||
this.extraAmount = ''
|
||||
this.extraRemark = ''
|
||||
this.showExtra = true
|
||||
},
|
||||
submitExtra() {
|
||||
const amt = Number(this.extraAmount)
|
||||
if (!amt || amt <= 0) { uni.showToast({ title: '请输入补差金额', icon: 'none' }); return }
|
||||
request(apiArr.workerExtraOrder, 'POST', {
|
||||
order_id: this.extraOrder.id,
|
||||
amount: amt,
|
||||
remark: this.extraRemark
|
||||
}).then(() => {
|
||||
this.showExtra = false
|
||||
uni.showToast({ title: '已生成补差单,待客户支付', icon: 'none' })
|
||||
this.loadOrders()
|
||||
})
|
||||
},
|
||||
openPush(b) {
|
||||
this.pushBill = b
|
||||
this.showPush = true
|
||||
},
|
||||
submitPush() {
|
||||
request(apiArr.workerPushBill, 'POST', {
|
||||
bill_id: this.pushBill.id,
|
||||
action: 1
|
||||
}).then(() => {
|
||||
this.showPush = false
|
||||
uni.showToast({ title: '已推送,用户可支付', icon: 'none' })
|
||||
this.loadBills()
|
||||
}).catch(err => {
|
||||
uni.showToast({ title: err.errMsg || '操作失败', icon: 'none' })
|
||||
})
|
||||
},
|
||||
openReject(b) {
|
||||
this.rejectBill = b
|
||||
this.rejectRemark = ''
|
||||
this.showReject = true
|
||||
},
|
||||
submitReject() {
|
||||
request(apiArr.workerPushBill, 'POST', {
|
||||
bill_id: this.rejectBill.id,
|
||||
action: 3,
|
||||
remark: this.rejectRemark
|
||||
}).then(() => {
|
||||
this.showReject = false
|
||||
uni.showToast({ title: '已拒绝', icon: 'none' })
|
||||
this.loadBills()
|
||||
}).catch(err => {
|
||||
uni.showToast({ title: err.errMsg || '操作失败', icon: 'none' })
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.hsw-page { display: flex; flex-direction: column; height: 100vh; background: #f5f5f5; }
|
||||
.hsw-tabs { display: flex; background: #fff; }
|
||||
.hsw-tab { flex: 1; text-align: center; padding: 24rpx 0; font-size: 26rpx; color: #666; }
|
||||
.hsw-tab.active { color: #FF370B; font-weight: 600; border-bottom: 4rpx solid #FF370B; }
|
||||
.hsw-tabs-bill { border-top: 1rpx solid #f0f0f0; }
|
||||
.hsw-list { flex: 1; padding: 20rpx; box-sizing: border-box; }
|
||||
.hsw-card { background: #fff; border-radius: 12rpx; padding: 20rpx; margin-bottom: 18rpx; }
|
||||
.hsw-bill-card { border-left: 6rpx solid #FF370B; }
|
||||
.hsw-head { display: flex; justify-content: space-between; font-size: 24rpx; color: #999; margin-bottom: 14rpx; }
|
||||
.hsw-kind { color: #FF370B; }
|
||||
.status-warn { color: #FF9800; }
|
||||
.status-info { color: #2196F3; }
|
||||
.status-ok { color: #4CAF50; }
|
||||
.status-cancel { color: #999; }
|
||||
.hsw-row { display: flex; justify-content: space-between; font-size: 26rpx; color: #333; padding: 8rpx 0; }
|
||||
.hsw-row text:first-child { color: #999; }
|
||||
.hsw-amount { color: #FF370B; font-weight: 600; }
|
||||
.hsw-foot { display: flex; justify-content: flex-end; gap: 16rpx; margin-top: 16rpx; }
|
||||
.hsw-btn { background: linear-gradient(91deg, #FF7658, #FF370B); color: #fff; font-size: 26rpx; padding: 12rpx 36rpx; border-radius: 40rpx; }
|
||||
.hsw-btn.ghost { background: #fff; color: #FF370B; border: 1rpx solid #FF370B; }
|
||||
.hsw-empty { text-align: center; color: #999; font-size: 26rpx; padding: 80rpx 0; }
|
||||
.hsw-mask { position: fixed; inset: 0; background: rgba(0,0,0,0.5); display: flex; align-items: center; justify-content: center; z-index: 999; }
|
||||
.hsw-dialog { width: 600rpx; background: #fff; border-radius: 16rpx; padding: 32rpx; }
|
||||
.hsw-dialog-tit { font-size: 30rpx; font-weight: 600; text-align: center; margin-bottom: 24rpx; }
|
||||
.hsw-dialog-info { font-size: 26rpx; color: #666; text-align: center; margin-bottom: 24rpx; }
|
||||
.hsw-dialog-input { border: 1rpx solid #eee; border-radius: 8rpx; height: 80rpx; padding: 0 20rpx; font-size: 28rpx; margin-bottom: 18rpx; }
|
||||
.hsw-dialog-btns { display: flex; gap: 20rpx; margin-top: 10rpx; }
|
||||
.hsw-dialog-btn { flex: 1; text-align: center; padding: 18rpx 0; border-radius: 44rpx; font-size: 28rpx; }
|
||||
.hsw-dialog-btn.cancel { background: #f2f2f2; color: #666; }
|
||||
.hsw-dialog-btn.ok { background: linear-gradient(91deg, #FF7658, #FF370B); color: #fff; }
|
||||
</style>
|
||||
@ -426,83 +426,3 @@ page {
|
||||
.coupon_item_button::after {
|
||||
border: none;
|
||||
}
|
||||
|
||||
/* ============ 店铺活动商品 ============ */
|
||||
.shop-activity {
|
||||
padding: 24rpx;
|
||||
}
|
||||
|
||||
.shop-activity-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: 600;
|
||||
color: #222;
|
||||
padding-left: 16rpx;
|
||||
border-left: 6rpx solid #FF370B;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.shop-activity-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 20rpx;
|
||||
}
|
||||
|
||||
.sa-goods {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background: #fff;
|
||||
border: 1rpx solid #f2f2f2;
|
||||
border-radius: 12rpx;
|
||||
padding: 16rpx;
|
||||
}
|
||||
|
||||
.sa-pic {
|
||||
width: 160rpx;
|
||||
height: 160rpx;
|
||||
border-radius: 8rpx;
|
||||
flex-shrink: 0;
|
||||
background: #f5f5f5;
|
||||
}
|
||||
|
||||
.sa-info {
|
||||
flex: 1;
|
||||
margin-left: 20rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.sa-name {
|
||||
font-size: 28rpx;
|
||||
color: #222;
|
||||
line-height: 38rpx;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.sa-price-row {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
margin-top: 16rpx;
|
||||
gap: 16rpx;
|
||||
}
|
||||
|
||||
.sa-price {
|
||||
font-size: 34rpx;
|
||||
font-weight: 600;
|
||||
color: #FF370B;
|
||||
}
|
||||
|
||||
.sa-unit {
|
||||
font-size: 22rpx;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.sa-origin {
|
||||
font-size: 22rpx;
|
||||
color: #999;
|
||||
text-decoration: line-through;
|
||||
}
|
||||
@ -59,27 +59,6 @@
|
||||
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 店铺活动商品 -->
|
||||
<view class="white_container shop-activity" v-if="shopActivityList.length > 0">
|
||||
<view class="shop-activity-title">店铺活动</view>
|
||||
<view class="shop-activity-list">
|
||||
<block v-for="(item, index) in shopActivityList" :key="index">
|
||||
<view class="sa-goods" v-for="(sku, sIdx) in item.group_buy_goods_list" :key="sIdx"
|
||||
@click="toShopActivityDetail(sku)">
|
||||
<image class="sa-pic" :src="sku.commodity_pic || item.commodity_pic" mode="aspectFill" />
|
||||
<view class="sa-info">
|
||||
<view class="sa-name">{{ sku.goods_name || item.commodity_name }}</view>
|
||||
<view class="sa-price-row">
|
||||
<view class="sa-price">¥{{ sku.group_buy_price }}<text class="sa-unit" v-if="sku.goods_unit">/{{ sku.goods_unit }}</text></view>
|
||||
<view class="sa-origin" v-if="sku.sales_price">单买价 ¥{{ sku.sales_price }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</block>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="white_container detail" v-for="(item, index) in commentList" :key="index">
|
||||
<view class="Msg">
|
||||
<view class="Msg_Tit">
|
||||
@ -137,7 +116,7 @@
|
||||
<image src="https://static.hshuishang.com/property-img-file/localLife_detail_Frame.png" mode="" />
|
||||
<view>电话</view>
|
||||
</view>
|
||||
<view v-if="isShow" class="left_label" @click="handleDiscussClick">
|
||||
<view class="left_label" @click="handleDiscussClick">
|
||||
<image src="https://static.hshuishang.com/property-img-file/localLife_shopList_Group_1334.png" mode="" />
|
||||
<view>点评</view>
|
||||
</view>
|
||||
@ -202,29 +181,12 @@ export default {
|
||||
isDisabled: false,
|
||||
coupons: [],
|
||||
couponDetails: [],
|
||||
showCouponPopup: false,
|
||||
shopActivityList: [] // 店铺活动商品(团购 activity_type=2)
|
||||
showCouponPopup: false
|
||||
};
|
||||
},
|
||||
onLoad(options) {
|
||||
let id;
|
||||
if (options.scene) {
|
||||
const scene = decodeURIComponent(options.scene);
|
||||
function getQueryParam(str, name) {
|
||||
const reg = new RegExp(`(^|&)${name}=([^&]*)(&|$)`);
|
||||
const match = str.match(reg);
|
||||
return match ? decodeURIComponent(match[2]) : null;
|
||||
}
|
||||
const idStr = getQueryParam(scene, 'id'); // 得到 "22"
|
||||
if (idStr) {
|
||||
id = Number(idStr); // 得到 22
|
||||
}
|
||||
}else{
|
||||
id = Number(uni.getStorageSync("merchantInfo").id)
|
||||
}
|
||||
console.log('scene:',options.scene,id)
|
||||
const params = {
|
||||
id: id
|
||||
id: Number(uni.getStorageSync("merchantInfo").id)
|
||||
}
|
||||
request(apiArr.getMerchantInfo, "POST", params).then(res => {
|
||||
this.info = res
|
||||
@ -235,8 +197,7 @@ export default {
|
||||
this.flag = false
|
||||
this.commentList = []
|
||||
this.getCommentList()
|
||||
this.getShopActivity()
|
||||
});
|
||||
})
|
||||
},
|
||||
onShow() {
|
||||
if (this.info.id) {
|
||||
@ -252,46 +213,6 @@ export default {
|
||||
},
|
||||
|
||||
methods: {
|
||||
// 店铺活动商品(团购 activity_type=2),小区来源与团购一致(绑定房产小区)
|
||||
getShopActivity() {
|
||||
const userId = uni.getStorageSync('userId')
|
||||
if (!userId) return
|
||||
const params = {
|
||||
user_id: userId,
|
||||
merchant_id: this.info.id,
|
||||
community_id: uni.getStorageSync('changeCommData') ? uni.getStorageSync('changeCommData').id : ''
|
||||
}
|
||||
request(apiArr.getShopActivityList, "POST", params, {}, false).then(res => {
|
||||
const list = (res.list || []).map(item => {
|
||||
const group_buy_goods_list = (item.group_buy_goods_list || []).map(sku => ({
|
||||
...sku,
|
||||
commodity_pic: picUrl + sku.commodity_pic,
|
||||
quantity: 0
|
||||
}))
|
||||
return {
|
||||
...item,
|
||||
commodity_pic: picUrl + item.commodity_pic,
|
||||
group_buy_goods_list
|
||||
}
|
||||
})
|
||||
this.shopActivityList = list
|
||||
}).catch(() => {
|
||||
this.shopActivityList = []
|
||||
})
|
||||
},
|
||||
// 点击店铺活动商品 -> 复用团购详情页
|
||||
toShopActivityDetail(itemObj) {
|
||||
let targetItem = itemObj
|
||||
if (!targetItem.group_buy_activity_info && targetItem.group_buy_goods_list && targetItem.group_buy_goods_list.length > 0) {
|
||||
targetItem = targetItem.group_buy_goods_list[0]
|
||||
}
|
||||
if (!targetItem.group_buy_activity_info) return
|
||||
const item = {
|
||||
...targetItem,
|
||||
groupById: targetItem.group_buy_activity_info.id
|
||||
}
|
||||
NavgateTo(`/packages/shop/groupPurchaseDetail/index?item=${JSON.stringify(item)}`)
|
||||
},
|
||||
getCouponList() {
|
||||
const params = {
|
||||
mch_id: uni.getStorageSync("merchantInfo").id,
|
||||
|
||||
@ -83,7 +83,7 @@
|
||||
买单返积分
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="item.quick_purchase_enabled==1" class="merchantItem_right_con_right" @click.stop="toJump(item)">
|
||||
<view class="merchantItem_right_con_right" @click="toJump(item)">
|
||||
<image src="https://static.hshuishang.com/property-img-file/local_review.png"
|
||||
mode="aspectFill"></image>
|
||||
点评
|
||||
@ -119,7 +119,6 @@
|
||||
import {
|
||||
request,
|
||||
picUrl,
|
||||
RequestUrl,
|
||||
uniqueByField,
|
||||
menuButtonInfo,
|
||||
calculateDistance,
|
||||
@ -156,20 +155,8 @@ export default {
|
||||
console.log(this.address);
|
||||
},
|
||||
|
||||
onPullDownRefresh() {
|
||||
this.page_num = 1;
|
||||
this.merchatList = [];
|
||||
this.flag = false;
|
||||
this.searchText = '';
|
||||
this.getCateList();
|
||||
this.getMechantList().then(() => {
|
||||
uni.stopPullDownRefresh();
|
||||
});
|
||||
},
|
||||
|
||||
onReachBottom() {
|
||||
if (this.flag) {
|
||||
this.page_num += 1;
|
||||
this.getMechantList();
|
||||
}
|
||||
},
|
||||
|
||||
@ -170,15 +170,7 @@ export default {
|
||||
};
|
||||
},
|
||||
onLoad(options) {
|
||||
let item
|
||||
// 来自客服聊天卡片:完整订单数据经本地存储中转(避免 URL 过长被截断)
|
||||
if (options && options.fromChat) {
|
||||
try { item = uni.getStorageSync('chatCardItem') } catch (e) { item = null }
|
||||
uni.removeStorageSync('chatCardItem')
|
||||
}
|
||||
if (!item) {
|
||||
item = JSON.parse(options?.item);
|
||||
}
|
||||
const item = JSON.parse(options?.item);
|
||||
this.orderInfo = item;
|
||||
// 启动倒计时
|
||||
item.order_status == "1" ? this.startCountdown() : "";
|
||||
|
||||
@ -1,16 +0,0 @@
|
||||
<template>
|
||||
<view class="container">
|
||||
<view>提交订单</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {};
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
</style>
|
||||
@ -1,148 +1,67 @@
|
||||
/* ============================================================
|
||||
* 商家入驻 - 资料审核状态页
|
||||
* 审核中 #FF9F0A 通过 #34C759 失败 #FF3B30 主色 #FF370B
|
||||
* ============================================================ */
|
||||
page {
|
||||
background-color: #F6F7F9;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.container {
|
||||
padding: 24rpx;
|
||||
box-sizing: border-box;
|
||||
padding-bottom: 200rpx;
|
||||
}
|
||||
|
||||
.audit-card {
|
||||
background: #FFFFFF;
|
||||
border-radius: 16rpx;
|
||||
padding: 60rpx 40rpx 48rpx;
|
||||
margin-top: 100rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.audit-icon {
|
||||
width: 120rpx;
|
||||
height: 120rpx;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-bottom: 28rpx;
|
||||
}
|
||||
|
||||
.audit-icon--ing {
|
||||
background: #FFF4E0;
|
||||
.auditStatus {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.audit-icon--ok {
|
||||
background: #E6F8EA;
|
||||
}
|
||||
|
||||
.audit-icon--fail {
|
||||
background: #FDECEA;
|
||||
}
|
||||
|
||||
.audit-title {
|
||||
font-size: 36rpx;
|
||||
font-weight: 600;
|
||||
color: #222;
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
|
||||
.audit-desc {
|
||||
font-size: 26rpx;
|
||||
color: #999;
|
||||
.title {
|
||||
font-size: 40rpx;
|
||||
font-weight: bold;
|
||||
margin: 10rpx 0;
|
||||
text-align: center;
|
||||
line-height: 40rpx;
|
||||
padding: 0 20rpx;
|
||||
margin-bottom: 32rpx;
|
||||
}
|
||||
|
||||
.audit-times {
|
||||
width: 100%;
|
||||
border-top: 1rpx solid #F2F2F2;
|
||||
padding-top: 24rpx;
|
||||
}
|
||||
|
||||
.audit-time-row {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
.content{
|
||||
font-size: 26rpx;
|
||||
color: #666;
|
||||
line-height: 44rpx;
|
||||
margin-top: 40rpx;
|
||||
text-align: center;
|
||||
color: #a9a9a9;
|
||||
}
|
||||
|
||||
/* 驳回原因框 */
|
||||
.reject-box {
|
||||
width: 100%;
|
||||
background: #FFF7F4;
|
||||
border: 1rpx solid #FFD9CD;
|
||||
border-radius: 12rpx;
|
||||
padding: 24rpx;
|
||||
margin-bottom: 24rpx;
|
||||
.info{
|
||||
margin-top: 70rpx;
|
||||
width: 500rpx;
|
||||
background-color: #f6f6fa;
|
||||
padding: 20rpx 30rpx;
|
||||
border-radius: 20rpx;
|
||||
}
|
||||
|
||||
.reject-title {
|
||||
.info view{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10rpx;
|
||||
font-size: 28rpx;
|
||||
font-weight: 600;
|
||||
color: #FF370B;
|
||||
margin-bottom: 14rpx;
|
||||
justify-content: space-between;
|
||||
margin: 15rpx 0;
|
||||
}
|
||||
|
||||
.reject-text {
|
||||
font-size: 26rpx;
|
||||
color: #FF370B;
|
||||
line-height: 42rpx;
|
||||
white-space: pre-wrap;
|
||||
.info_text{
|
||||
color: #999999;
|
||||
}
|
||||
|
||||
.reject-imgs {
|
||||
margin-top: 18rpx;
|
||||
.info_text2{
|
||||
color: #faba5a;
|
||||
}
|
||||
|
||||
.reject-imgs-label {
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
margin-bottom: 12rpx;
|
||||
.btn{
|
||||
margin-top: 50rpx;
|
||||
border: none;
|
||||
background-color: #ff4218;
|
||||
color: #ffffff;
|
||||
border-radius: 50rpx;
|
||||
}
|
||||
|
||||
.reject-thumbs {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 12rpx;
|
||||
.warning{
|
||||
color: #ff4218;
|
||||
font-size: 27rpx;
|
||||
margin: 50rpx 0;
|
||||
}
|
||||
|
||||
.reject-thumb {
|
||||
width: 120rpx;
|
||||
height: 120rpx;
|
||||
border-radius: 8rpx;
|
||||
border: 1rpx solid #EEE;
|
||||
}
|
||||
|
||||
/* 底部按钮 */
|
||||
.audit-footer {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: #FFFFFF;
|
||||
padding: 16rpx 24rpx calc(16rpx + env(safe-area-inset-bottom));
|
||||
box-shadow: 0 -4rpx 20rpx rgba(0, 0, 0, 0.04);
|
||||
z-index: 99;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
height: 88rpx;
|
||||
background: linear-gradient(91deg, #FF7658 0%, #FF370B 100%);
|
||||
border-radius: 44rpx;
|
||||
color: #FFFFFF;
|
||||
.warning_title{
|
||||
font-size: 30rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-weight: bold;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
@ -1,141 +1,117 @@
|
||||
<template>
|
||||
<view class="container">
|
||||
<!-- 审核中 -->
|
||||
<view class="audit-card" v-if="status === 1">
|
||||
<view class="audit-icon audit-icon--ing">
|
||||
<u-icon name="clock" color="#FF9F0A" size="56"></u-icon>
|
||||
<view class="auditStatusContainer" v-if="itemObj.status == 1">
|
||||
<view class="header">
|
||||
<view class="statusIcon">
|
||||
<image src="https://static.hshuishang.com/enter_audit1.png" mode="aspectFill" class="auditStatus" />
|
||||
</view>
|
||||
<view class="audit-title">正在审核中</view>
|
||||
<view class="audit-desc">您的店铺资料已提交,工作人员将在 1-3 个工作日内完成审核,请耐心等待。</view>
|
||||
<view class="audit-times">
|
||||
<view class="audit-time-row"><text>申请时间:</text><text>{{ itemObj.create_time || '—' }}</text></view>
|
||||
<view class="title">
|
||||
审核中
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 审核通过 -->
|
||||
<view class="audit-card" v-else-if="status === 2">
|
||||
<view class="audit-icon audit-icon--ok">
|
||||
<u-icon name="checkmark" color="#34C759" size="56"></u-icon>
|
||||
<view class="content">
|
||||
<view>您的入驻申请正在审核中</view>
|
||||
<view>请耐心等待工作人员处理</view>
|
||||
</view>
|
||||
<view class="audit-title">审核通过</view>
|
||||
<view class="audit-desc">恭喜您,您的店铺资料已同意审核</view>
|
||||
<view class="audit-times">
|
||||
<view class="audit-time-row"><text>申请时间:</text><text>{{ itemObj.create_time || '—' }}</text></view>
|
||||
<view class="audit-time-row"><text>审核时间:</text><text>{{ itemObj.handle_time || '—' }}</text></view>
|
||||
<view class="info">
|
||||
<view>
|
||||
<view class="info_text">申请提交时间</view>
|
||||
<view>{{ itemObj.create_time }}</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 审核失败 -->
|
||||
<view class="audit-card" v-else-if="status === 3">
|
||||
<view class="audit-icon audit-icon--fail">
|
||||
<u-icon name="close" color="#FF3B30" size="56"></u-icon>
|
||||
</view>
|
||||
<view class="audit-title">审核失败</view>
|
||||
<view class="audit-desc">很抱歉,您的资料未通过审核,请修改后重新提交。</view>
|
||||
|
||||
<view class="reject-box" v-if="itemObj.remark || rejectImages.length">
|
||||
<view class="reject-title">
|
||||
<u-icon name="error-circle" color="#FF370B" size="28"></u-icon>
|
||||
<text>驳回原因</text>
|
||||
</view>
|
||||
<view class="reject-text">{{ itemObj.remark || '—' }}</view>
|
||||
<view class="reject-imgs" v-if="rejectImages.length">
|
||||
<view class="reject-imgs-label">问题截图</view>
|
||||
<view class="reject-thumbs">
|
||||
<image v-for="(u, i) in rejectImages" :key="i" :src="u" class="reject-thumb"
|
||||
mode="aspectFill" @click="preview(rejectImages, i)" />
|
||||
<view>
|
||||
<view class="info_text">当前审核环节</view>
|
||||
<view class="info_text2">资质验证中</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="audit-times">
|
||||
<view class="audit-time-row"><text>申请时间:</text><text>{{ itemObj.create_time || '—' }}</text></view>
|
||||
<view class="audit-time-row"><text>审核时间:</text><text>{{ itemObj.handle_time || '—' }}</text></view>
|
||||
<view class="auditStatusContainer" v-if="itemObj.status == 2">
|
||||
<view class="header">
|
||||
<view class="statusIcon">
|
||||
<image src="https://static.hshuishang.com/af_√.png" mode="aspectFill"
|
||||
class="auditStatus" />
|
||||
</view>
|
||||
<view class="title">
|
||||
入驻成功
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="audit-footer" v-if="status === 3">
|
||||
<view class="btn-primary" @click="resubmit">修改资料并重新提交</view>
|
||||
<view class="content">
|
||||
<view>恭喜您!您的店铺已成功入驻我们平台</view>
|
||||
</view>
|
||||
<view class="info">
|
||||
<view>
|
||||
<view class="info_text">店铺名称</view>
|
||||
<view>{{ itemObj.merchant_name }}</view>
|
||||
</view>
|
||||
<view>
|
||||
<view class="info_text">入住时间</view>
|
||||
<view>{{ itemObj.handle_time || '' }}</view>
|
||||
</view>
|
||||
<view>
|
||||
<view class="info_text">店铺ID</view>
|
||||
<view>{{ itemObj.merchant_code }}</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- <view>
|
||||
<button class="btn" @click="goShopManage">进入店铺管理</button>
|
||||
</view> -->
|
||||
</view>
|
||||
<view class="auditStatusContainer" v-if="itemObj.status == 3">
|
||||
<view class="header">
|
||||
<view class="statusIcon">
|
||||
<image src="https://static.hshuishang.com/enter_audit2.png" mode="aspectFill" class="auditStatus" />
|
||||
</view>
|
||||
<view class="title">
|
||||
审核失败
|
||||
</view>
|
||||
</view>
|
||||
<view class="content">
|
||||
<view>很抱歉,您的入驻申请未通过审核</view>
|
||||
<view>请修改后重新提交</view>
|
||||
</view>
|
||||
<view class="info">
|
||||
<view>
|
||||
<view class="info_text">申请提交时间</view>
|
||||
<view>{{ itemObj.create_time }}</view>
|
||||
</view>
|
||||
<view>
|
||||
<view class="info_text">审核完成时间</view>
|
||||
<view>{{ itemObj.handle_time || '' }}</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="warning" v-if="itemObj.remark">
|
||||
<view class="warning_title">审核未通过原因</view>
|
||||
<view>
|
||||
{{ itemObj.remark || '' }}
|
||||
</view>
|
||||
</view>
|
||||
<view>
|
||||
<button class="btn" @click="resubmit">修改并重新提交</button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { NavgateTo } from '../../../utils/index';
|
||||
import { signPrivateView } from '../../../utils/uploadOSS.js';
|
||||
import { request, NavgateTo } from '../../../utils/index';
|
||||
import { apiArr } from '../../../api/v2Home.js'
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
itemObj: {},
|
||||
rejectImages: [],
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
status() {
|
||||
return Number(this.itemObj.status) || 0
|
||||
itemObj: {}
|
||||
}
|
||||
},
|
||||
onLoad(options) {
|
||||
if (options && options.itemObj) {
|
||||
try {
|
||||
this.itemObj = JSON.parse(decodeURIComponent(options.itemObj))
|
||||
} catch (e) {
|
||||
console.error('解析审核状态参数失败:', e)
|
||||
this.itemObj = {}
|
||||
}
|
||||
} else if (options && options.status) {
|
||||
// 兼容老版本:仅带 status,没有完整对象
|
||||
this.itemObj = { status: Number(options.status) }
|
||||
}
|
||||
// 驳回问题截图:后端 reject_images 字段(逗号分隔的私密 key),有则签名展示
|
||||
if (this.itemObj.reject_images) {
|
||||
this.signRejectImages(this.itemObj.reject_images)
|
||||
}
|
||||
this.itemObj = JSON.parse(options.itemObj);
|
||||
},
|
||||
methods: {
|
||||
async signRejectImages(paths) {
|
||||
const list = (paths || '').split(',').filter(Boolean)
|
||||
const result = []
|
||||
for (const p of list) {
|
||||
try {
|
||||
const r = await signPrivateView(p)
|
||||
result.push(r.url)
|
||||
} catch (e) {
|
||||
console.error('签发驳回截图 URL 失败:', p, e)
|
||||
}
|
||||
}
|
||||
this.rejectImages = result
|
||||
},
|
||||
preview(urls, current) {
|
||||
if (!urls || !urls.length) return
|
||||
uni.previewImage({ urls, current: urls[current] })
|
||||
goShopManage() {
|
||||
NavgateTo('/packages/storeManagement/index/index');
|
||||
},
|
||||
resubmit() {
|
||||
// 编辑数据较大(含多组图片路径),用本地存储中转,避免 URL 过长被截断
|
||||
try {
|
||||
uni.setStorageSync('shopEnterEditData', this.itemObj)
|
||||
} catch (e) {
|
||||
console.error('暂存编辑数据失败:', e)
|
||||
NavgateTo('/packages/shopEnter/index/index?itemObj=' + JSON.stringify(this.itemObj));
|
||||
}
|
||||
NavgateTo('/packages/shopEnter/index/index?edit=1');
|
||||
},
|
||||
// 返回首页(审核态为终态,避免回退到表单/确认页造成二次提交)
|
||||
goHome() {
|
||||
uni.reLaunch({ url: '/pages/index/index' })
|
||||
}
|
||||
},
|
||||
// 拦截物理返回 / 左上角返回:统一回首页,而非弹出上一页
|
||||
onBackPress(e) {
|
||||
// 编辑页发起的二次提交流程(status 3 驳回后点重新提交跳走)不拦截
|
||||
if (e && e.from === 'backbutton') {
|
||||
uni.reLaunch({ url: '/pages/index/index' })
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
@import url("./index.css");
|
||||
</style>
|
||||
@ -1,235 +0,0 @@
|
||||
/* ============================================================
|
||||
* 商家入驻 - 自定义相机(取景框拍证件)
|
||||
* ============================================================ */
|
||||
page {
|
||||
background: #000;
|
||||
}
|
||||
|
||||
.cam-page {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
background: #000;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* 顶部导航 */
|
||||
.cam-nav {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 20;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 12rpx 24rpx;
|
||||
height: 88rpx;
|
||||
}
|
||||
|
||||
.cam-nav-back {
|
||||
width: 60rpx;
|
||||
height: 60rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.cam-nav-title {
|
||||
color: #fff;
|
||||
font-size: 32rpx;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.cam-nav-right {
|
||||
width: 60rpx;
|
||||
}
|
||||
|
||||
/* 相机取景 */
|
||||
.cam-view {
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
/* 取景框遮罩 */
|
||||
.cam-overlay {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
z-index: 10;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.cam-frame {
|
||||
position: relative;
|
||||
border: 2rpx dashed rgba(255, 255, 255, 0.7);
|
||||
border-radius: 16rpx;
|
||||
}
|
||||
|
||||
.frame-landscape {
|
||||
width: 86vw;
|
||||
height: 54vw;
|
||||
}
|
||||
|
||||
.frame-portrait {
|
||||
width: 64vw;
|
||||
height: 86vw;
|
||||
}
|
||||
|
||||
.cam-corner {
|
||||
position: absolute;
|
||||
width: 44rpx;
|
||||
height: 44rpx;
|
||||
border-color: #FF370B;
|
||||
border-style: solid;
|
||||
border-width: 0;
|
||||
}
|
||||
|
||||
.cam-corner.tl {
|
||||
top: -2rpx;
|
||||
left: -2rpx;
|
||||
border-top-width: 6rpx;
|
||||
border-left-width: 6rpx;
|
||||
border-top-left-radius: 16rpx;
|
||||
}
|
||||
|
||||
.cam-corner.tr {
|
||||
top: -2rpx;
|
||||
right: -2rpx;
|
||||
border-top-width: 6rpx;
|
||||
border-right-width: 6rpx;
|
||||
border-top-right-radius: 16rpx;
|
||||
}
|
||||
|
||||
.cam-corner.bl {
|
||||
bottom: -2rpx;
|
||||
left: -2rpx;
|
||||
border-bottom-width: 6rpx;
|
||||
border-left-width: 6rpx;
|
||||
border-bottom-left-radius: 16rpx;
|
||||
}
|
||||
|
||||
.cam-corner.br {
|
||||
bottom: -2rpx;
|
||||
right: -2rpx;
|
||||
border-bottom-width: 6rpx;
|
||||
border-right-width: 6rpx;
|
||||
border-bottom-right-radius: 16rpx;
|
||||
}
|
||||
|
||||
.cam-tip {
|
||||
margin-top: 36rpx;
|
||||
color: #fff;
|
||||
font-size: 28rpx;
|
||||
text-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.6);
|
||||
}
|
||||
|
||||
/* 横版/竖版切换 */
|
||||
.cam-orient {
|
||||
position: absolute;
|
||||
bottom: 280rpx;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 20;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 24rpx;
|
||||
}
|
||||
|
||||
.orient-item {
|
||||
padding: 12rpx 40rpx;
|
||||
border-radius: 40rpx;
|
||||
background: rgba(255, 255, 255, 0.18);
|
||||
color: rgba(255, 255, 255, 0.8);
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.orient-item.active {
|
||||
background: #FF370B;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/* 底部操作 */
|
||||
.cam-actions {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 20;
|
||||
height: 240rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-around;
|
||||
padding-bottom: env(safe-area-inset-bottom);
|
||||
background: rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
.cam-action-side {
|
||||
width: 110rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 8rpx;
|
||||
color: #fff;
|
||||
font-size: 24rpx;
|
||||
}
|
||||
|
||||
.cam-action-placeholder {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.cam-shutter {
|
||||
width: 130rpx;
|
||||
height: 130rpx;
|
||||
border-radius: 50%;
|
||||
background: #fff;
|
||||
border: 8rpx solid rgba(255, 255, 255, 0.4);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.cam-shutter:active {
|
||||
transform: scale(0.94);
|
||||
}
|
||||
|
||||
/* 预览态 */
|
||||
.cam-preview {
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
background: #000;
|
||||
}
|
||||
|
||||
.cam-preview-actions {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 20;
|
||||
height: 200rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 40rpx;
|
||||
padding-bottom: env(safe-area-inset-bottom);
|
||||
background: rgba(0, 0, 0, 0.4);
|
||||
}
|
||||
|
||||
.prev-btn {
|
||||
width: 240rpx;
|
||||
height: 88rpx;
|
||||
border-radius: 44rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 30rpx;
|
||||
}
|
||||
|
||||
.prev-retake {
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.prev-submit {
|
||||
background: linear-gradient(91deg, #FF7658 0%, #FF370B 100%);
|
||||
color: #fff;
|
||||
}
|
||||
@ -1,165 +0,0 @@
|
||||
<template>
|
||||
<view class="cam-page">
|
||||
<!-- 顶部自定义导航 -->
|
||||
<view class="cam-nav" :style="{ paddingTop: statusBarHeight + 'px' }">
|
||||
<view class="cam-nav-back" @click="goBack">
|
||||
<u-icon name="arrow-left" color="#fff" size="40"></u-icon>
|
||||
</view>
|
||||
<view class="cam-nav-title">{{ title }}</view>
|
||||
<view class="cam-nav-right"></view>
|
||||
</view>
|
||||
|
||||
<!-- 拍摄态:相机取景 -->
|
||||
<block v-if="!captured">
|
||||
<camera class="cam-view" :device-position="'back'" :flash="'auto'" @error="onCamError"></camera>
|
||||
<!-- 取景框遮罩 -->
|
||||
<view class="cam-overlay">
|
||||
<view class="cam-frame" :class="orientation === 'landscape' ? 'frame-landscape' : 'frame-portrait'">
|
||||
<view class="cam-corner tl"></view>
|
||||
<view class="cam-corner tr"></view>
|
||||
<view class="cam-corner bl"></view>
|
||||
<view class="cam-corner br"></view>
|
||||
</view>
|
||||
<view class="cam-tip">{{ frameTip }}</view>
|
||||
</view>
|
||||
<!-- 横版/竖版切换 -->
|
||||
<view class="cam-orient">
|
||||
<view class="orient-item" :class="{ active: orientation === 'landscape' }" @click="orientation = 'landscape'">横版</view>
|
||||
<view class="orient-item" :class="{ active: orientation === 'portrait' }" @click="orientation = 'portrait'">竖版</view>
|
||||
</view>
|
||||
<!-- 底部操作:相册 / 拍照 -->
|
||||
<view class="cam-actions">
|
||||
<view class="cam-action-side" @click="pickFromAlbum">
|
||||
<u-icon name="photo" color="#fff" size="44"></u-icon>
|
||||
<text>相册</text>
|
||||
</view>
|
||||
<view class="cam-shutter" @click="takePhoto"></view>
|
||||
<view class="cam-action-side cam-action-placeholder"></view>
|
||||
</view>
|
||||
</block>
|
||||
|
||||
<!-- 预览态:重拍 / 提交 -->
|
||||
<block v-else>
|
||||
<image class="cam-preview" :src="tempPath" mode="aspectFit"></image>
|
||||
<view class="cam-preview-actions">
|
||||
<view class="prev-btn prev-retake" @click="retake">重拍</view>
|
||||
<view class="prev-btn prev-submit" @click="confirmUse">提交</view>
|
||||
</view>
|
||||
</block>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
statusBarHeight: 20,
|
||||
target: 'license', // license / idFront / idBack / industry
|
||||
orientation: 'landscape',
|
||||
captured: false,
|
||||
tempPath: '',
|
||||
cameraCtx: null,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
title() {
|
||||
const map = {
|
||||
license: '拍摄营业执照',
|
||||
idFront: '拍摄身份证人像面',
|
||||
idBack: '拍摄身份证国徽面',
|
||||
industry: '拍摄行业资质',
|
||||
}
|
||||
return map[this.target] || '拍摄证件'
|
||||
},
|
||||
frameTip() {
|
||||
const map = {
|
||||
license: '请将营业执照完整置于取景框内',
|
||||
idFront: '请将身份证人像面置于取景框内',
|
||||
idBack: '请将身份证国徽面置于取景框内',
|
||||
industry: '请将资质证件完整置于取景框内',
|
||||
}
|
||||
return map[this.target] || '请将证件完整置于取景框内'
|
||||
}
|
||||
},
|
||||
onLoad(options) {
|
||||
if (options && options.target) this.target = options.target
|
||||
// 身份证默认横版,营业执照/资质默认竖版
|
||||
this.orientation = (this.target === 'idFront' || this.target === 'idBack') ? 'landscape' : 'portrait'
|
||||
try {
|
||||
const sys = uni.getSystemInfoSync()
|
||||
this.statusBarHeight = sys.statusBarHeight || 20
|
||||
} catch (e) {}
|
||||
},
|
||||
onReady() {
|
||||
// #ifndef H5
|
||||
this.cameraCtx = uni.createCameraContext()
|
||||
// #endif
|
||||
},
|
||||
methods: {
|
||||
goBack() {
|
||||
uni.navigateBack()
|
||||
},
|
||||
onCamError(e) {
|
||||
console.error('相机错误:', e)
|
||||
uni.showModal({
|
||||
title: '无法使用相机',
|
||||
content: '请检查是否已授予相机权限,或改用相册上传。',
|
||||
showCancel: false
|
||||
})
|
||||
},
|
||||
takePhoto() {
|
||||
if (!this.cameraCtx) {
|
||||
// H5 等不支持 camera 组件的环境,回退到系统拍照
|
||||
this.pickFromCamera()
|
||||
return
|
||||
}
|
||||
this.cameraCtx.takePhoto({
|
||||
quality: 'high',
|
||||
success: (res) => {
|
||||
this.tempPath = res.tempImagePath
|
||||
this.captured = true
|
||||
},
|
||||
fail: () => {
|
||||
uni.showToast({ title: '拍照失败,请重试', icon: 'none' })
|
||||
}
|
||||
})
|
||||
},
|
||||
pickFromCamera() {
|
||||
uni.chooseImage({
|
||||
count: 1, sizeType: ['compressed'], sourceType: ['camera'],
|
||||
success: (res) => {
|
||||
const fp = res.tempFilePaths && res.tempFilePaths[0]
|
||||
if (!fp) return
|
||||
this.tempPath = fp
|
||||
this.captured = true
|
||||
}
|
||||
})
|
||||
},
|
||||
pickFromAlbum() {
|
||||
uni.chooseImage({
|
||||
count: 1, sizeType: ['compressed'], sourceType: ['album'],
|
||||
success: (res) => {
|
||||
const fp = res.tempFilePaths && res.tempFilePaths[0]
|
||||
if (!fp) return
|
||||
this.tempPath = fp
|
||||
this.captured = true
|
||||
}
|
||||
})
|
||||
},
|
||||
retake() {
|
||||
this.captured = false
|
||||
this.tempPath = ''
|
||||
},
|
||||
confirmUse() {
|
||||
if (!this.tempPath) return
|
||||
// 把拍摄结果通过事件总线回传给入驻表单页,由其负责上传 + OCR
|
||||
uni.$emit('shopEnter:capture', { target: this.target, filePath: this.tempPath })
|
||||
uni.navigateBack()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
@import url("./index.css");
|
||||
</style>
|
||||
@ -1,95 +0,0 @@
|
||||
page {
|
||||
background-color: #f6f7fb;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.container {
|
||||
padding: 30rpx;
|
||||
}
|
||||
|
||||
.header {
|
||||
padding: 40rpx 0 60rpx;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.header-title {
|
||||
font-size: 40rpx;
|
||||
font-weight: bold;
|
||||
color: #222222;
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
|
||||
.header-desc {
|
||||
font-size: 28rpx;
|
||||
color: #999999;
|
||||
}
|
||||
|
||||
.type-list {
|
||||
margin-bottom: 40rpx;
|
||||
}
|
||||
|
||||
.type-card {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background: #FFFFFF;
|
||||
border-radius: 20rpx;
|
||||
padding: 40rpx 30rpx;
|
||||
margin-bottom: 24rpx;
|
||||
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.type-card:active {
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.type-icon {
|
||||
width: 100rpx;
|
||||
height: 100rpx;
|
||||
margin-right: 24rpx;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.type-icon image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.type-info {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.type-name {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
color: #222222;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
|
||||
.type-desc {
|
||||
font-size: 24rpx;
|
||||
color: #999999;
|
||||
}
|
||||
|
||||
.type-arrow {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.tips {
|
||||
background: #FFFFFF;
|
||||
border-radius: 20rpx;
|
||||
padding: 30rpx;
|
||||
}
|
||||
|
||||
.tips-title {
|
||||
font-size: 28rpx;
|
||||
font-weight: bold;
|
||||
color: #222222;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.tips-item {
|
||||
font-size: 24rpx;
|
||||
color: #666666;
|
||||
line-height: 1.8;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
@ -1,63 +0,0 @@
|
||||
<template>
|
||||
<view class="container">
|
||||
<view class="header">
|
||||
<view class="header-title">选择入驻类型</view>
|
||||
<view class="header-desc">请选择您的商家入驻身份</view>
|
||||
</view>
|
||||
|
||||
<view class="type-list">
|
||||
<!-- 个人入驻 -->
|
||||
<view class="type-card" @click="chooseType('personal')">
|
||||
<view class="type-icon">
|
||||
<image src="https://static.hshuishang.com/property-img-file/icon_personal.png" mode="aspectFit"></image>
|
||||
</view>
|
||||
<view class="type-info">
|
||||
<view class="type-name">个人入驻</view>
|
||||
<view class="type-desc">适用于个体工商户、自然人经营者</view>
|
||||
</view>
|
||||
<view class="type-arrow">
|
||||
<u-icon name="arrow-right" color="#999" size="28"></u-icon>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 企业入驻 -->
|
||||
<view class="type-card" @click="chooseType('enterprise')">
|
||||
<view class="type-icon">
|
||||
<image src="https://static.hshuishang.com/property-img-file/icon_enterprise.png" mode="aspectFit"></image>
|
||||
</view>
|
||||
<view class="type-info">
|
||||
<view class="type-name">企业入驻</view>
|
||||
<view class="type-desc">适用于企业、公司法人</view>
|
||||
</view>
|
||||
<view class="type-arrow">
|
||||
<u-icon name="arrow-right" color="#999" size="28"></u-icon>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="tips">
|
||||
<view class="tips-title">入驻须知</view>
|
||||
<view class="tips-item">1. 个人入驻需提供身份证、银行卡等个人资质信息</view>
|
||||
<view class="tips-item">2. 企业入驻需提供营业执照、法人身份证、对公账户等企业资质信息</view>
|
||||
<view class="tips-item">3. 提交后将由平台工作人员进行审核,预计1-3个工作日</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { NavgateTo } from '../../../utils';
|
||||
export default {
|
||||
data() {
|
||||
return {}
|
||||
},
|
||||
methods: {
|
||||
chooseType(type) {
|
||||
NavgateTo('/packages/shopEnter/index/index?enterType=' + type);
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
@import url("./index.css");
|
||||
</style>
|
||||
@ -1,182 +0,0 @@
|
||||
/* ============================================================
|
||||
* 商家入驻 - 确认信息页(预览信息)
|
||||
* 主色 #FF370B 背景 #F6F7F9
|
||||
* ============================================================ */
|
||||
page {
|
||||
background-color: #F6F7F9;
|
||||
min-height: 100vh;
|
||||
padding-bottom: 200rpx;
|
||||
}
|
||||
|
||||
.container {
|
||||
padding-bottom: 40rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* 顶部进度条(复用主页样式) */
|
||||
.step-bar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 24rpx 30rpx 28rpx;
|
||||
background: linear-gradient(91deg, #FF7658 0%, #FF370B 100%);
|
||||
}
|
||||
|
||||
.step-pill {
|
||||
flex: 1;
|
||||
height: 60rpx;
|
||||
margin: 0 8rpx;
|
||||
border-radius: 30rpx;
|
||||
background: rgba(255, 255, 255, 0.18);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: rgba(255, 255, 255, 0.65);
|
||||
font-size: 26rpx;
|
||||
}
|
||||
|
||||
.step-pill.active {
|
||||
background: #FFFFFF;
|
||||
color: #FF370B;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.confirm-head {
|
||||
font-size: 32rpx;
|
||||
font-weight: 600;
|
||||
color: #222;
|
||||
padding: 28rpx 24rpx 8rpx;
|
||||
}
|
||||
|
||||
/* 分组卡片 */
|
||||
.cf-group {
|
||||
background: #FFFFFF;
|
||||
margin: 16rpx 24rpx 0;
|
||||
border-radius: 16rpx;
|
||||
padding: 8rpx 24rpx;
|
||||
}
|
||||
|
||||
.cf-group-title {
|
||||
font-size: 28rpx;
|
||||
font-weight: 600;
|
||||
color: #222;
|
||||
padding: 20rpx 0 12rpx;
|
||||
border-bottom: 1rpx solid #F2F2F2;
|
||||
}
|
||||
|
||||
.cf-row {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
padding: 22rpx 0;
|
||||
border-bottom: 1rpx solid #F7F7F7;
|
||||
}
|
||||
|
||||
.cf-row:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.cf-k {
|
||||
font-size: 26rpx;
|
||||
color: #999;
|
||||
flex-shrink: 0;
|
||||
margin-right: 24rpx;
|
||||
}
|
||||
|
||||
.cf-v {
|
||||
font-size: 26rpx;
|
||||
color: #222;
|
||||
text-align: right;
|
||||
flex: 1;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
/* 文件资料行 */
|
||||
.cf-file-row {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
padding: 22rpx 0;
|
||||
border-bottom: 1rpx solid #F7F7F7;
|
||||
}
|
||||
|
||||
.cf-file-row:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.cf-thumbs {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 12rpx;
|
||||
justify-content: flex-end;
|
||||
flex: 1;
|
||||
margin-left: 24rpx;
|
||||
}
|
||||
|
||||
.cf-thumb {
|
||||
width: 120rpx;
|
||||
height: 120rpx;
|
||||
border-radius: 8rpx;
|
||||
border: 1rpx solid #EEE;
|
||||
}
|
||||
|
||||
.cf-empty {
|
||||
font-size: 24rpx;
|
||||
color: #B7B7B7;
|
||||
}
|
||||
|
||||
/* 协议勾选 */
|
||||
.agreement {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 24rpx 24rpx 0;
|
||||
}
|
||||
|
||||
.agreement-text {
|
||||
font-size: 24rpx;
|
||||
color: #666;
|
||||
margin-left: 8rpx;
|
||||
}
|
||||
|
||||
.agreement-link {
|
||||
color: #FF370B;
|
||||
}
|
||||
|
||||
/* 底部按钮(吸底) */
|
||||
.bottom-bar {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: #FFFFFF;
|
||||
padding: 16rpx 24rpx calc(16rpx + env(safe-area-inset-bottom));
|
||||
display: flex;
|
||||
gap: 16rpx;
|
||||
box-shadow: 0 -4rpx 20rpx rgba(0, 0, 0, 0.04);
|
||||
z-index: 99;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
flex: 1;
|
||||
height: 88rpx;
|
||||
background: linear-gradient(91deg, #FF7658 0%, #FF370B 100%);
|
||||
border-radius: 44rpx;
|
||||
color: #FFFFFF;
|
||||
font-size: 30rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.btn-secondary {
|
||||
flex: 1;
|
||||
height: 88rpx;
|
||||
background: #FFFFFF;
|
||||
border: 1rpx solid #FF370B;
|
||||
border-radius: 44rpx;
|
||||
color: #FF370B;
|
||||
font-size: 30rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
@ -1,209 +0,0 @@
|
||||
<template>
|
||||
<view class="container">
|
||||
<!-- 顶部进度条 -->
|
||||
<view class="step-bar">
|
||||
<view class="step-pill active">填写信息</view>
|
||||
<view class="step-pill">提交审核</view>
|
||||
<view class="step-pill">入驻成功</view>
|
||||
</view>
|
||||
|
||||
<view class="confirm-head">请确认以下信息</view>
|
||||
|
||||
<!-- 基本信息 -->
|
||||
<view class="cf-group">
|
||||
<view class="cf-group-title">基本信息</view>
|
||||
<view class="cf-row"><text class="cf-k">门店名称</text><text class="cf-v">{{ d.merchant_name || '—' }}</text></view>
|
||||
<view class="cf-row"><text class="cf-k">所在地区</text><text class="cf-v">{{ d._region_label || '—' }}</text></view>
|
||||
<view class="cf-row"><text class="cf-k">详细地址</text><text class="cf-v">{{ d.address || '—' }}</text></view>
|
||||
<view class="cf-row"><text class="cf-k">商家类目</text><text class="cf-v">{{ d._cate_name || '—' }}</text></view>
|
||||
<view class="cf-row" v-if="d._biz_status_label"><text class="cf-k">营业状态</text><text class="cf-v">{{ d._biz_status_label }}</text></view>
|
||||
<view class="cf-row"><text class="cf-k">负责人姓名</text><text class="cf-v">{{ d.contact_name || '—' }}</text></view>
|
||||
<view class="cf-row"><text class="cf-k">负责人手机</text><text class="cf-v">{{ d.phone || '—' }}</text></view>
|
||||
</view>
|
||||
|
||||
<!-- 资质信息 -->
|
||||
<view class="cf-group">
|
||||
<view class="cf-group-title">资质信息</view>
|
||||
<view class="cf-row"><text class="cf-k">执照名称</text><text class="cf-v">{{ d.license_name || '—' }}</text></view>
|
||||
<view class="cf-row"><text class="cf-k">信用代码</text><text class="cf-v">{{ d.credit_code || '—' }}</text></view>
|
||||
<view class="cf-row"><text class="cf-k">营业执照</text><text class="cf-v">{{ d.license_is_forever === 1 ? '永久有效' : (d.license_valid_until || '—') }}</text></view>
|
||||
<view class="cf-row" v-if="d.industry_name"><text class="cf-k">证书名称</text><text class="cf-v">{{ d.industry_name }}</text></view>
|
||||
<view class="cf-row" v-if="d.industry_cert_no"><text class="cf-k">证书编号</text><text class="cf-v">{{ d.industry_cert_no }}</text></view>
|
||||
<view class="cf-row" v-if="d.industry_name"><text class="cf-k">资质有效期</text><text class="cf-v">{{ d.industry_is_forever === 1 ? '永久有效' : (d.industry_valid_until || '—') }}</text></view>
|
||||
<view class="cf-row"><text class="cf-k">法人姓名</text><text class="cf-v">{{ d.legal_person || '—' }}</text></view>
|
||||
<view class="cf-row"><text class="cf-k">身份证号</text><text class="cf-v">{{ d.id_card_no || '—' }}</text></view>
|
||||
<view class="cf-row"><text class="cf-k">证件有效期</text><text class="cf-v">{{ d.id_is_forever === 1 ? '永久有效' : (d.id_valid_until || '—') }}</text></view>
|
||||
</view>
|
||||
|
||||
<!-- 结算信息 -->
|
||||
<view class="cf-group">
|
||||
<view class="cf-group-title">结算信息</view>
|
||||
<view class="cf-row"><text class="cf-k">银行开户名</text><text class="cf-v">{{ d.account_name || '—' }}</text></view>
|
||||
<view class="cf-row"><text class="cf-k">{{ d.account_type === 2 ? '对公账号' : '银行卡号' }}</text><text class="cf-v">{{ d.bank_card || '—' }}</text></view>
|
||||
<view class="cf-row"><text class="cf-k">开户银行</text><text class="cf-v">{{ d.bank_name || '—' }}</text></view>
|
||||
<view class="cf-row"><text class="cf-k">开户支行</text><text class="cf-v">{{ d.bank_branch || '—' }}</text></view>
|
||||
<view class="cf-row" v-if="d._bank_region_label"><text class="cf-k">银行所在地</text><text class="cf-v">{{ d._bank_region_label }}</text></view>
|
||||
<view class="cf-row" v-if="d.bank_union_no"><text class="cf-k">联行号</text><text class="cf-v">{{ d.bank_union_no }}</text></view>
|
||||
</view>
|
||||
|
||||
<!-- 文件资料 -->
|
||||
<view class="cf-group">
|
||||
<view class="cf-group-title">文件资料</view>
|
||||
<view class="cf-file-row">
|
||||
<text class="cf-k">营业执照</text>
|
||||
<view class="cf-thumbs">
|
||||
<image v-for="(u, i) in licenseUrls" :key="i" :src="u" class="cf-thumb" mode="aspectFill" @click="preview(licenseUrls, i)" />
|
||||
<text v-if="!licenseUrls.length" class="cf-empty">未上传</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="cf-file-row">
|
||||
<text class="cf-k">行业资质</text>
|
||||
<view class="cf-thumbs">
|
||||
<image v-for="(u, i) in industryUrls" :key="i" :src="u" class="cf-thumb" mode="aspectFill" @click="preview(industryUrls, i)" />
|
||||
<text v-if="!industryUrls.length" class="cf-empty">未上传</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="cf-file-row">
|
||||
<text class="cf-k">法人证件</text>
|
||||
<view class="cf-thumbs">
|
||||
<image v-for="(u, i) in idUrls" :key="i" :src="u" class="cf-thumb" mode="aspectFill" @click="preview(idUrls, i)" />
|
||||
<text v-if="!idUrls.length" class="cf-empty">未上传</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="cf-file-row">
|
||||
<text class="cf-k">门头环境</text>
|
||||
<view class="cf-thumbs">
|
||||
<image v-for="(u, i) in facadeUrls" :key="i" :src="u" class="cf-thumb" mode="aspectFill" @click="preview(facadeUrls, i)" />
|
||||
<text v-if="!facadeUrls.length" class="cf-empty">未上传</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="cf-file-row">
|
||||
<text class="cf-k">店内环境</text>
|
||||
<view class="cf-thumbs">
|
||||
<image v-for="(u, i) in interiorUrls" :key="i" :src="u" class="cf-thumb" mode="aspectFill" @click="preview(interiorUrls, i)" />
|
||||
<text v-if="!interiorUrls.length" class="cf-empty">未上传</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 协议勾选 -->
|
||||
<view class="agreement">
|
||||
<view class="agreement-check" @click="agreeProtocol = !agreeProtocol">
|
||||
<u-icon :name="agreeProtocol ? 'checkmark-circle-fill' : 'checkmark-circle'" :color="agreeProtocol ? '#FF370B' : '#ccc'" size="36"></u-icon>
|
||||
</view>
|
||||
<view class="agreement-text">
|
||||
我已阅读并同意<text class="agreement-link" @click.stop="viewProtocol">《商家入驻协议》</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="bottom-bar">
|
||||
<view class="btn-secondary" @click="goBack">返回修改</view>
|
||||
<view class="btn-primary" @click="submit">提交审核</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { apiArr } from '../../../api/v2local';
|
||||
import { request, picUrl, NavgateTo } from '../../../utils';
|
||||
import { signPrivateView } from '../../../utils/uploadOSS.js';
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
picUrl,
|
||||
d: {},
|
||||
agreeProtocol: false,
|
||||
licenseUrls: [],
|
||||
industryUrls: [],
|
||||
idUrls: [],
|
||||
facadeUrls: [],
|
||||
interiorUrls: [],
|
||||
submitting: false,
|
||||
}
|
||||
},
|
||||
onLoad(options) {
|
||||
if (options && options.itemObj) {
|
||||
try {
|
||||
this.d = JSON.parse(decodeURIComponent(options.itemObj))
|
||||
} catch (e) {
|
||||
console.error('解析确认页参数失败:', e)
|
||||
this.d = {}
|
||||
}
|
||||
}
|
||||
// 门头环境 / 店内环境:公开 bucket,直接拼 URL
|
||||
this.facadeUrls = (this.d.facade_photo || '').split(',').filter(Boolean).map(p => this.picUrl + p)
|
||||
this.interiorUrls = (this.d.interior_photo || '').split(',').filter(Boolean).map(p => this.picUrl + p)
|
||||
// 营业执照 / 行业资质 / 身份证:私密 bucket,需要签名
|
||||
this.signList(this.d.license_photo, 'licenseUrls')
|
||||
this.signList(this.d.industry_photo, 'industryUrls')
|
||||
this.signList([this.d.id_card_front, this.d.id_card_back].filter(Boolean).join(','), 'idUrls')
|
||||
},
|
||||
methods: {
|
||||
async signList(paths, key) {
|
||||
const list = (paths || '').split(',').filter(Boolean)
|
||||
const result = []
|
||||
for (const p of list) {
|
||||
try {
|
||||
const r = await signPrivateView(p)
|
||||
result.push(r.url)
|
||||
} catch (e) {
|
||||
console.error('签发私密 URL 失败:', p, e)
|
||||
}
|
||||
}
|
||||
this[key] = result
|
||||
},
|
||||
preview(urls, current) {
|
||||
if (!urls || !urls.length) return
|
||||
uni.previewImage({ urls, current: urls[current] })
|
||||
},
|
||||
viewProtocol() {
|
||||
uni.showModal({
|
||||
title: '商家入驻协议',
|
||||
content: '本协议是您与平台之间关于商家入驻服务的法律协议。入驻后您需遵守平台规则,按时提供商品或服务,保证信息真实有效。平台有权对违规商家进行处罚。',
|
||||
showCancel: false,
|
||||
confirmText: '我知道了'
|
||||
})
|
||||
},
|
||||
goBack() {
|
||||
uni.navigateBack()
|
||||
},
|
||||
submit() {
|
||||
if (!this.agreeProtocol) {
|
||||
uni.showToast({ title: '请先阅读并同意商家入驻协议', icon: 'none' })
|
||||
return
|
||||
}
|
||||
if (this.submitting) return
|
||||
this.submitting = true
|
||||
// 剥离仅用于展示的下划线字段,避免传给后端
|
||||
const params = {}
|
||||
Object.keys(this.d).forEach(k => {
|
||||
if (!k.startsWith('_')) params[k] = this.d[k]
|
||||
})
|
||||
request(apiArr.createStore, "POST", params).then(res => {
|
||||
// 审核页仅需少量字段;用 reLaunch 清空页面栈,避免返回到表单/确认页造成二次提交
|
||||
const auditItem = {
|
||||
status: 1,
|
||||
create_time: new Date().toLocaleString('sv-SE').replace('T', ' '),
|
||||
handle_time: '',
|
||||
remark: ''
|
||||
}
|
||||
uni.reLaunch({
|
||||
url: "/packages/shopEnter/auditStatus/index?itemObj=" + encodeURIComponent(JSON.stringify(auditItem))
|
||||
})
|
||||
}).catch(res => {
|
||||
this.submitting = false
|
||||
const msg = res && res.message ? res.message : '提交失败,请稍后重试'
|
||||
if (msg.includes("agent_nil")) {
|
||||
uni.showModal({ title: '提交失败', content: '未找到对应的代理商信息,请联系平台', showCancel: false })
|
||||
return
|
||||
}
|
||||
uni.showModal({ title: '提交失败', content: msg, showCancel: false })
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
@import url("./index.css");
|
||||
</style>
|
||||
@ -1,66 +0,0 @@
|
||||
page {
|
||||
background-color: #f6f7fb;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.container {
|
||||
padding: 30rpx;
|
||||
}
|
||||
|
||||
.example-section {
|
||||
background: #FFFFFF;
|
||||
border-radius: 20rpx;
|
||||
padding: 30rpx;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 34rpx;
|
||||
font-weight: bold;
|
||||
color: #222222;
|
||||
margin-bottom: 30rpx;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.sub-section {
|
||||
margin-bottom: 40rpx;
|
||||
}
|
||||
|
||||
.sub-title {
|
||||
font-size: 28rpx;
|
||||
color: #333333;
|
||||
margin-bottom: 20rpx;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.example-img {
|
||||
width: 100%;
|
||||
margin-bottom: 20rpx;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.example-img image {
|
||||
width: 500rpx;
|
||||
border-radius: 10rpx;
|
||||
border: 2rpx dashed #ddd;
|
||||
}
|
||||
|
||||
.tips {
|
||||
background: #FFF8F6;
|
||||
border-radius: 10rpx;
|
||||
padding: 24rpx;
|
||||
margin-top: 20rpx;
|
||||
}
|
||||
|
||||
.tips-title {
|
||||
font-size: 26rpx;
|
||||
font-weight: bold;
|
||||
color: #FF370B;
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
|
||||
.tips-item {
|
||||
font-size: 24rpx;
|
||||
color: #666666;
|
||||
line-height: 1.8;
|
||||
}
|
||||
@ -1,83 +0,0 @@
|
||||
<template>
|
||||
<view class="container">
|
||||
<view class="example-section" v-if="type === 'license'">
|
||||
<view class="title">营业执照拍摄示例</view>
|
||||
<view class="example-img">
|
||||
<image :src="picUrl + '/static/example/license.jpg'" mode="widthFix"></image>
|
||||
</view>
|
||||
<view class="tips">
|
||||
<view class="tips-title">拍摄要求:</view>
|
||||
<view class="tips-item">1. 请确保营业执照在有效期内</view>
|
||||
<view class="tips-item">2. 照片需清晰完整,四角完整可见</view>
|
||||
<view class="tips-item">3. 不得有遮挡、涂改、反光</view>
|
||||
<view class="tips-item">4. 支持原件拍照或彩色扫描件</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="example-section" v-if="type === 'idcard'">
|
||||
<view class="title">身份证拍摄示例</view>
|
||||
<view class="sub-section">
|
||||
<view class="sub-title">身份证正面(人像面)</view>
|
||||
<view class="example-img">
|
||||
<image :src="picUrl + '/static/example/front.jpg'" mode="widthFix"></image>
|
||||
</view>
|
||||
</view>
|
||||
<view class="sub-section">
|
||||
<view class="sub-title">身份证反面(国徽面)</view>
|
||||
<view class="example-img">
|
||||
<image :src="picUrl + '/static/example/back.jpg'" mode="widthFix"></image>
|
||||
</view>
|
||||
</view>
|
||||
<view class="tips">
|
||||
<view class="tips-title">拍摄要求:</view>
|
||||
<view class="tips-item">1. 请确保身份证在有效期内</view>
|
||||
<view class="tips-item">2. 照片需清晰完整,四角完整可见</view>
|
||||
<view class="tips-item">3. 不得有遮挡、涂改、反光</view>
|
||||
<view class="tips-item">4. 仅支持二代身份证</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="example-section" v-if="type === 'industry'">
|
||||
<view class="title">行业资质示例</view>
|
||||
<view class="example-img">
|
||||
<image src="/static/example/license.jpg" mode="widthFix"></image>
|
||||
</view>
|
||||
<view class="tips">
|
||||
<view class="tips-title">拍摄要求:</view>
|
||||
<view class="tips-item">1. 请上传与经营品类对应的资质(如食品经营许可证)</view>
|
||||
<view class="tips-item">2. 照片需清晰完整,四角完整可见</view>
|
||||
<view class="tips-item">3. 不得有遮挡、涂改、反光</view>
|
||||
<view class="tips-item">4. 资质需在有效期内</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { picUrl } from '../../../utils/index';
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
picUrl,
|
||||
type: 'license'
|
||||
}
|
||||
},
|
||||
onLoad(options) {
|
||||
if (options.type) {
|
||||
this.type = options.type;
|
||||
}
|
||||
// 设置导航栏标题
|
||||
const titleMap = {
|
||||
license: '营业执照示例',
|
||||
idcard: '身份证示例',
|
||||
industry: '行业资质示例'
|
||||
}
|
||||
uni.setNavigationBarTitle({
|
||||
title: titleMap[this.type] || '资质示例'
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
@import url("./index.css");
|
||||
</style>
|
||||
@ -1,674 +1,116 @@
|
||||
/* ============================================================
|
||||
* 商家入驻 - 基本信息 tab 全新样式(按设计稿 PDF 1)
|
||||
* 主色 #FF370B 辅色 #FFF1ED 灰边 #EEE 灰字 #999 深字 #222
|
||||
* ============================================================ */
|
||||
|
||||
page {
|
||||
background-color: #F6F7F9;
|
||||
background-color: #f6f7fb;
|
||||
min-height: 100vh;
|
||||
padding-bottom: 200rpx;
|
||||
padding-bottom: 60rpx;
|
||||
}
|
||||
|
||||
.container {
|
||||
padding-bottom: 40rpx;
|
||||
background: url(https://static.hshuishang.com/property-img-file/shopEn_apply.png) no-repeat;
|
||||
background-size: 750rpx 497rpx;
|
||||
box-sizing: border-box;
|
||||
padding-top: 290rpx;
|
||||
}
|
||||
|
||||
.Msg {
|
||||
width: 710rpx;
|
||||
background: #FFFFFF;
|
||||
border-radius: 20rpx 20rpx 20rpx 20rpx;
|
||||
margin: 0 auto;
|
||||
padding: 0 20rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* ================= 顶部进度条(红底胶囊) ================= */
|
||||
.step-bar {
|
||||
.row {
|
||||
padding-top: 30rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 24rpx 30rpx 28rpx;
|
||||
background: linear-gradient(91deg, #FF7658 0%, #FF370B 100%);
|
||||
}
|
||||
|
||||
.step-pill {
|
||||
flex: 1;
|
||||
height: 60rpx;
|
||||
margin: 0 8rpx;
|
||||
border-radius: 30rpx;
|
||||
background: rgba(255, 255, 255, 0.18);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: rgba(255, 255, 255, 0.65);
|
||||
font-size: 26rpx;
|
||||
}
|
||||
|
||||
.step-pill.active {
|
||||
background: #FFFFFF;
|
||||
color: #FF370B;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* ================= Tab 切换 ================= */
|
||||
.tab-bar {
|
||||
display: flex;
|
||||
background: #FFFFFF;
|
||||
padding: 0 60rpx;
|
||||
}
|
||||
|
||||
.tab-item {
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
padding: 28rpx 0 22rpx;
|
||||
font-size: 30rpx;
|
||||
color: #222;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.tab-item.active {
|
||||
color: #FF370B;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.tab-item.active::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
bottom: 8rpx;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
width: 56rpx;
|
||||
height: 6rpx;
|
||||
background: #FF370B;
|
||||
border-radius: 3rpx;
|
||||
}
|
||||
|
||||
/* ================= 表单卡片 ================= */
|
||||
.form-card {
|
||||
background: #FFFFFF;
|
||||
margin: 20rpx 24rpx 0;
|
||||
padding: 24rpx;
|
||||
border-radius: 16rpx;
|
||||
}
|
||||
|
||||
.field {
|
||||
margin-top: 20rpx;
|
||||
}
|
||||
|
||||
.field:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.field-label {
|
||||
font-size: 26rpx;
|
||||
color: #222;
|
||||
margin-bottom: 14rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.field-label .star {
|
||||
color: #FF370B;
|
||||
margin-right: 4rpx;
|
||||
font-size: 26rpx;
|
||||
}
|
||||
|
||||
.field-input {
|
||||
height: 80rpx;
|
||||
border: 1rpx solid #EBEBEB;
|
||||
border-radius: 8rpx;
|
||||
padding: 0 20rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background: #FFFFFF;
|
||||
}
|
||||
|
||||
.field-input input {
|
||||
flex: 1;
|
||||
.row_label {
|
||||
font-size: 28rpx;
|
||||
color: #222;
|
||||
height: 80rpx;
|
||||
line-height: 80rpx;
|
||||
color: #999999;
|
||||
width: 180rpx;
|
||||
}
|
||||
|
||||
.field-input input::placeholder,
|
||||
.field-input .placeholder {
|
||||
color: #B7B7B7;
|
||||
.red {
|
||||
color: #FF370B;
|
||||
margin-left: 5rpx;
|
||||
}
|
||||
|
||||
.field-input.disabled {
|
||||
background: #FAFAFA;
|
||||
}
|
||||
|
||||
.field-value {
|
||||
.row_con {
|
||||
flex: 1;
|
||||
font-size: 28rpx;
|
||||
color: #222;
|
||||
padding-bottom: 30rpx;
|
||||
border-bottom: 1rpx solid #EBEBEB;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.field-value.placeholder {
|
||||
color: #B7B7B7;
|
||||
.row_con input {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.field-arrow {
|
||||
color: #C8C8C8;
|
||||
font-size: 24rpx;
|
||||
margin-left: 12rpx;
|
||||
.nonebor {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
/* ================= 上传图片块 ================= */
|
||||
.upload-section {
|
||||
margin-top: 20rpx;
|
||||
}
|
||||
|
||||
.upload-title {
|
||||
font-size: 26rpx;
|
||||
color: #222;
|
||||
margin-bottom: 16rpx;
|
||||
.row2 {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.upload-title .star {
|
||||
color: #FF370B;
|
||||
margin-right: 4rpx;
|
||||
.mt {
|
||||
margin-top: 26rpx;
|
||||
padding-top: 36rpx;
|
||||
padding-bottom: 36rpx;
|
||||
}
|
||||
|
||||
.upload-title .count {
|
||||
color: #999;
|
||||
font-size: 24rpx;
|
||||
margin-left: 8rpx;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.upload-grid {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 16rpx;
|
||||
}
|
||||
|
||||
/* uview u-upload 内部样式微调(让占位框跟设计稿一致) */
|
||||
.upload-section /deep/ .u-upload__wrap__preview {
|
||||
width: 168rpx !important;
|
||||
height: 168rpx !important;
|
||||
border-radius: 12rpx !important;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.upload-section /deep/ .u-upload__button {
|
||||
width: 168rpx !important;
|
||||
height: 168rpx !important;
|
||||
border-radius: 12rpx !important;
|
||||
background: #FAFAFA !important;
|
||||
border: 1rpx dashed #D1D1D1 !important;
|
||||
}
|
||||
|
||||
.upload-add {
|
||||
width: 168rpx;
|
||||
height: 168rpx;
|
||||
background: #FAFAFA;
|
||||
border: 1rpx dashed #D1D1D1;
|
||||
border-radius: 12rpx;
|
||||
.imgCon {
|
||||
font-size: 18rpx;
|
||||
color: #222222;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #999;
|
||||
font-size: 22rpx;
|
||||
width: 120rpx;
|
||||
height: 120rpx;
|
||||
background: #F6F7FB;
|
||||
border: 1rpx solid #D1D1D1;
|
||||
border-radius: 10rpx 10rpx 10rpx 10rpx;
|
||||
}
|
||||
|
||||
.upload-add-icon {
|
||||
font-size: 48rpx;
|
||||
color: #C8C8C8;
|
||||
line-height: 1;
|
||||
margin-bottom: 6rpx;
|
||||
}
|
||||
|
||||
/* ================= 底部红色提示框(门店信息要求) ================= */
|
||||
.tip-box {
|
||||
margin: 20rpx 24rpx 0;
|
||||
background: #FFF7F4;
|
||||
border: 1rpx solid #FFD9CD;
|
||||
border-radius: 12rpx;
|
||||
padding: 20rpx 24rpx 24rpx;
|
||||
display: flex;
|
||||
gap: 12rpx;
|
||||
}
|
||||
|
||||
.tip-box .tip-icon {
|
||||
color: #FF370B;
|
||||
font-size: 28rpx;
|
||||
font-weight: bold;
|
||||
flex-shrink: 0;
|
||||
line-height: 40rpx;
|
||||
}
|
||||
|
||||
.tip-box .tip-content {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.tip-box .tip-title {
|
||||
font-size: 26rpx;
|
||||
color: #FF370B;
|
||||
font-weight: 600;
|
||||
.imgCon image {
|
||||
width: 34rpx;
|
||||
height: 34rpx;
|
||||
margin-bottom: 8rpx;
|
||||
}
|
||||
|
||||
.tip-box .tip-item {
|
||||
font-size: 24rpx;
|
||||
color: #FF370B;
|
||||
line-height: 40rpx;
|
||||
.mt2 {
|
||||
margin-top: 30rpx;
|
||||
}
|
||||
|
||||
/* ================= 底部按钮(吸底) ================= */
|
||||
.bottom-bar {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: #FFFFFF;
|
||||
padding: 16rpx 24rpx calc(16rpx + env(safe-area-inset-bottom));
|
||||
display: flex;
|
||||
gap: 16rpx;
|
||||
box-shadow: 0 -4rpx 20rpx rgba(0, 0, 0, 0.04);
|
||||
z-index: 99;
|
||||
.u-upload__wrap__preview {
|
||||
width: 120rpx;
|
||||
height: 120rpx;
|
||||
border-radius: 10rpx 0rpx 10rpx 10rpx !important;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
flex: 1;
|
||||
height: 88rpx;
|
||||
background: linear-gradient(91deg, #FF7658 0%, #FF370B 100%);
|
||||
border-radius: 44rpx;
|
||||
.u-upload__wrap__preview__image {
|
||||
width: 100% !important;
|
||||
height: 100% !important;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.addBtn {
|
||||
font-size: 36rpx;
|
||||
color: #FFFFFF;
|
||||
font-size: 30rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.btn-secondary {
|
||||
flex: 1;
|
||||
height: 88rpx;
|
||||
background: #FFFFFF;
|
||||
border: 1rpx solid #FF370B;
|
||||
border-radius: 44rpx;
|
||||
color: #FF370B;
|
||||
font-size: 30rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
/* ================= 协议勾选 ================= */
|
||||
.agreement {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 24rpx 24rpx 0;
|
||||
}
|
||||
|
||||
.agreement-text {
|
||||
font-size: 24rpx;
|
||||
color: #666;
|
||||
margin-left: 8rpx;
|
||||
}
|
||||
|
||||
.agreement-link {
|
||||
color: #FF370B;
|
||||
}
|
||||
|
||||
/* ================= 资质示例链接 ================= */
|
||||
.example-link {
|
||||
font-size: 24rpx;
|
||||
color: #FF370B;
|
||||
margin-top: 10rpx;
|
||||
}
|
||||
|
||||
/* ================= 弹层选择器(所在地区/类目/营业状态) ================= */
|
||||
.popup-mask {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
z-index: 999;
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
}
|
||||
|
||||
.popup-sheet {
|
||||
width: 100%;
|
||||
background: #FFFFFF;
|
||||
border-radius: 24rpx 24rpx 0 0;
|
||||
max-height: 80vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.popup-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 28rpx 32rpx;
|
||||
border-bottom: 1rpx solid #F0F0F0;
|
||||
}
|
||||
|
||||
.popup-header .pop-cancel {
|
||||
color: #999;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.popup-header .pop-title {
|
||||
color: #222;
|
||||
font-size: 30rpx;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.popup-header .pop-confirm {
|
||||
color: #FF370B;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.popup-body {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.popup-col {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
padding: 12rpx 0;
|
||||
}
|
||||
|
||||
.popup-col-item {
|
||||
padding: 24rpx 32rpx;
|
||||
font-size: 28rpx;
|
||||
color: #222;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.popup-col-item.selected {
|
||||
color: #FF370B;
|
||||
}
|
||||
|
||||
.popup-col-item .check {
|
||||
color: #FF370B;
|
||||
font-size: 24rpx;
|
||||
}
|
||||
|
||||
/* 单列选择列表(营业状态) */
|
||||
.popup-list {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.popup-list-item {
|
||||
padding: 30rpx 32rpx;
|
||||
font-size: 30rpx;
|
||||
color: #222;
|
||||
text-align: center;
|
||||
border-bottom: 1rpx solid #F5F5F5;
|
||||
}
|
||||
|
||||
.popup-list-item.selected {
|
||||
color: #FF370B;
|
||||
}
|
||||
|
||||
/* ================= 类目选择搜索框 ================= */
|
||||
.popup-search {
|
||||
margin: 16rpx 32rpx;
|
||||
background: #F5F5F5;
|
||||
border-radius: 8rpx;
|
||||
padding: 14rpx 20rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12rpx;
|
||||
font-size: 26rpx;
|
||||
color: #B7B7B7;
|
||||
}
|
||||
|
||||
/* ============ Tab2 资质相关 ============ */
|
||||
.qual-thumb {
|
||||
width: 100%;
|
||||
height: 360rpx;
|
||||
border-radius: 12rpx;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
border: 1rpx solid #EBEBEB;
|
||||
}
|
||||
|
||||
.qual-thumb-img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.qual-thumb-del {
|
||||
position: absolute;
|
||||
top: 8rpx;
|
||||
right: 8rpx;
|
||||
width: 44rpx;
|
||||
height: 44rpx;
|
||||
border-radius: 50%;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
color: #fff;
|
||||
font-size: 32rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.id-card-row {
|
||||
display: flex;
|
||||
gap: 20rpx;
|
||||
margin-top: 12rpx;
|
||||
}
|
||||
|
||||
.id-card-cell {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 12rpx;
|
||||
}
|
||||
|
||||
.id-card-cell .upload-add {
|
||||
width: 100%;
|
||||
height: 200rpx;
|
||||
}
|
||||
|
||||
.id-card-cell .qual-thumb {
|
||||
width: 100%;
|
||||
height: 200rpx;
|
||||
}
|
||||
|
||||
.id-card-cell-label {
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.forever-toggle {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10rpx;
|
||||
margin-top: 12rpx;
|
||||
padding-left: 4rpx;
|
||||
}
|
||||
|
||||
.forever-toggle-text {
|
||||
font-size: 24rpx;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
/* ============ 有效期分段控件(永久有效 / 截止日期) ============ */
|
||||
.validity-seg {
|
||||
display: flex;
|
||||
gap: 16rpx;
|
||||
}
|
||||
|
||||
.validity-seg .seg-item {
|
||||
flex: 1;
|
||||
height: 72rpx;
|
||||
border: 1rpx solid #EBEBEB;
|
||||
border-radius: 8rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 26rpx;
|
||||
color: #666;
|
||||
background: #FFFFFF;
|
||||
}
|
||||
|
||||
.validity-seg .seg-item.active {
|
||||
color: #FF370B;
|
||||
border-color: #FF370B;
|
||||
background: #FFF1ED;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* ============ 结算页:银行账户信息分组标题 ============ */
|
||||
.section-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 30rpx;
|
||||
color: #222;
|
||||
font-weight: 600;
|
||||
padding: 28rpx 24rpx 4rpx;
|
||||
}
|
||||
|
||||
.section-title::before {
|
||||
content: '';
|
||||
width: 6rpx;
|
||||
height: 30rpx;
|
||||
background: #FF370B;
|
||||
border-radius: 3rpx;
|
||||
margin-right: 12rpx;
|
||||
}
|
||||
|
||||
/* 结算页行内底部提示 */
|
||||
.row-tip {
|
||||
font-size: 22rpx;
|
||||
color: #86909C;
|
||||
padding: 12rpx 24rpx 0;
|
||||
line-height: 34rpx;
|
||||
}
|
||||
|
||||
/* 结算页可点击选择行右侧布局 */
|
||||
.row_con--select {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.row_con .row_value {
|
||||
flex: 1;
|
||||
font-size: 28rpx;
|
||||
color: #222;
|
||||
}
|
||||
|
||||
.row_con .row_value.placeholder {
|
||||
color: #B7B7B7;
|
||||
}
|
||||
|
||||
/* ============ 结算页 银行账户信息表单 ============ */
|
||||
.Msg {
|
||||
background: #FFFFFF;
|
||||
margin: 12rpx 24rpx 0;
|
||||
border-radius: 16rpx;
|
||||
padding: 0 24rpx;
|
||||
}
|
||||
|
||||
.Msg .row {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 24rpx 0;
|
||||
border-bottom: 1rpx solid #F2F2F2;
|
||||
}
|
||||
|
||||
.Msg .row:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.Msg .row_label {
|
||||
font-size: 26rpx;
|
||||
color: #222;
|
||||
margin-bottom: 14rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.Msg .row_label .star {
|
||||
color: #FF370B;
|
||||
margin-right: 4rpx;
|
||||
}
|
||||
|
||||
.Msg .row_con {
|
||||
height: 80rpx;
|
||||
border: 1rpx solid #EBEBEB;
|
||||
border-radius: 8rpx;
|
||||
padding: 0 20rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background: #FFFFFF;
|
||||
}
|
||||
|
||||
.Msg .row_con input {
|
||||
flex: 1;
|
||||
font-size: 28rpx;
|
||||
color: #222;
|
||||
height: 80rpx;
|
||||
line-height: 80rpx;
|
||||
}
|
||||
|
||||
.Msg .row_con input::placeholder {
|
||||
color: #B7B7B7;
|
||||
}
|
||||
|
||||
/* 结算页底部按钮组 */
|
||||
.btn-group {
|
||||
display: flex;
|
||||
gap: 16rpx;
|
||||
padding: 40rpx 24rpx;
|
||||
}
|
||||
|
||||
.btn-group .prevBtn {
|
||||
flex: 1;
|
||||
height: 88rpx;
|
||||
background: #FFFFFF;
|
||||
border: 1rpx solid #FF370B;
|
||||
border-radius: 44rpx;
|
||||
color: #FF370B;
|
||||
font-size: 30rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.btn-group .nextBtn {
|
||||
flex: 1;
|
||||
height: 88rpx;
|
||||
width: 600rpx;
|
||||
height: 90rpx;
|
||||
background: linear-gradient(91deg, #FF7658 0%, #FF370B 100%);
|
||||
border-radius: 44rpx;
|
||||
color: #FFFFFF;
|
||||
font-size: 30rpx;
|
||||
border-radius: 100rpx 100rpx 100rpx 100rpx;
|
||||
margin: 0 auto;
|
||||
margin-top: 58rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.action-sheet {
|
||||
width: 100%;
|
||||
background: #F2F2F4;
|
||||
padding-bottom: env(safe-area-inset-bottom);
|
||||
}
|
||||
|
||||
.action-item {
|
||||
background: #FFFFFF;
|
||||
padding: 32rpx 0;
|
||||
text-align: center;
|
||||
font-size: 32rpx;
|
||||
color: #222;
|
||||
border-bottom: 1rpx solid #F0F0F0;
|
||||
}
|
||||
|
||||
.action-item:active {
|
||||
background: #F8F8F8;
|
||||
}
|
||||
|
||||
.action-cancel {
|
||||
margin-top: 12rpx;
|
||||
color: #999;
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -25,7 +25,7 @@ page {
|
||||
.button {
|
||||
width: 400rpx;
|
||||
height: 90rpx;
|
||||
background: #FF0101;
|
||||
background: #ff7252;
|
||||
color: white;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
|
||||
@ -53,12 +53,6 @@ page {
|
||||
font-size: 36rpx;
|
||||
color: #ffffff;
|
||||
}
|
||||
.logout-btn {
|
||||
margin-top: 40rpx;
|
||||
background: #ffffff;
|
||||
border: 1rpx solid #ff370b;
|
||||
color: #ff370b;
|
||||
}
|
||||
.tabel1 {
|
||||
margin: 0 20rpx;
|
||||
border-bottom: 1rpx solid #ebebeb;
|
||||
|
||||
@ -73,7 +73,6 @@
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="btn logout-btn" @click="headerLogoutClick">退出登录</view>
|
||||
<nav-footer :current="4"/>
|
||||
</view>
|
||||
</template>
|
||||
@ -192,36 +191,6 @@ export default {
|
||||
});
|
||||
},
|
||||
|
||||
// 退出登录
|
||||
headerLogoutClick() {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '确定要退出登录吗?',
|
||||
success: (res) => {
|
||||
if (!res.confirm) return;
|
||||
// 清除全部登录态缓存
|
||||
const keys = [
|
||||
'ctoken', 'userId', 'openId', 'phone', 'is_deal', 'is_dev',
|
||||
'is_shop', 'is_merchant', 'is_worker', 'shopId',
|
||||
'order_dispatch_permission', 'work_order_permission',
|
||||
'nickName', 'headPhoto', 'changeCommData', 'currentRoomNo'
|
||||
];
|
||||
keys.forEach(k => uni.removeStorageSync(k));
|
||||
uni.showToast({
|
||||
title: '已退出登录',
|
||||
icon: 'success',
|
||||
mask: true,
|
||||
duration: 1500,
|
||||
success: () => {
|
||||
setTimeout(() => {
|
||||
uni.reLaunch({ url: '/pages/login/login' });
|
||||
}, 1500);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
headerRadioClick(item) {
|
||||
this.sex = item;
|
||||
},
|
||||
|
||||
82
pages.json
82
pages.json
@ -5,7 +5,6 @@
|
||||
"style": {
|
||||
"navigationStyle": "custom",
|
||||
"navigationBarBackgroundColor": "#FFF",
|
||||
"enablePullDownRefresh": true,
|
||||
"usingComponents": {
|
||||
"nav-footer": "/components/nav/nav"
|
||||
}
|
||||
@ -134,47 +133,6 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"root": "packages/homeService",
|
||||
"pages": [
|
||||
{
|
||||
"path": "index/index",
|
||||
"style": { "navigationBarTitleText": "到家服务", "navigationBarBackgroundColor": "#fff" }
|
||||
},
|
||||
{
|
||||
"path": "detail/index",
|
||||
"style": { "navigationBarTitleText": "服务详情", "navigationBarBackgroundColor": "#fff" }
|
||||
},
|
||||
{
|
||||
"path": "order/index",
|
||||
"style": { "navigationBarTitleText": "确认预约", "navigationBarBackgroundColor": "#fff" }
|
||||
},
|
||||
{
|
||||
"path": "myOrders/index",
|
||||
"style": { "navigationBarTitleText": "我的服务订单", "navigationBarBackgroundColor": "#fff" }
|
||||
},
|
||||
{
|
||||
"path": "orderDetail/index",
|
||||
"style": { "navigationBarTitleText": "订单详情", "navigationBarBackgroundColor": "#fff" }
|
||||
},
|
||||
{
|
||||
"path": "worker/index",
|
||||
"style": { "navigationBarTitleText": "我的接单", "navigationBarBackgroundColor": "#fff" }
|
||||
},
|
||||
{
|
||||
"path": "myContracts/index",
|
||||
"style": { "navigationBarTitleText": "我的家政合同", "navigationBarBackgroundColor": "#fff" }
|
||||
},
|
||||
{
|
||||
"path": "contractDetail/index",
|
||||
"style": { "navigationBarTitleText": "合同详情", "navigationBarBackgroundColor": "#fff" }
|
||||
},
|
||||
{
|
||||
"path": "myMonthlyBills/index",
|
||||
"style": { "navigationBarTitleText": "我的月账单", "navigationBarBackgroundColor": "#fff" }
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"root": "packages/customerService",
|
||||
"pages": [
|
||||
@ -186,13 +144,6 @@
|
||||
"navigationBarBackgroundColor": "#F9F9F9"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "picker/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "选择",
|
||||
"navigationBarBackgroundColor": "#fff"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "chattingRecords/index",
|
||||
"style": {
|
||||
@ -620,13 +571,6 @@
|
||||
{
|
||||
"root": "packages/shopEnter",
|
||||
"pages": [
|
||||
{
|
||||
"path": "choose/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "商家入驻",
|
||||
"navigationBarBackgroundColor": "#fff"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "index/index",
|
||||
"style": {
|
||||
@ -634,20 +578,6 @@
|
||||
"navigationBarBackgroundColor": "#fff"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "confirm/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "商家入驻",
|
||||
"navigationBarBackgroundColor": "#fff"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "camera/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "拍摄证件",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "sucess/index",
|
||||
"style": {
|
||||
@ -659,14 +589,7 @@
|
||||
{
|
||||
"path": "auditStatus/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "资料审核",
|
||||
"navigationBarBackgroundColor": "#fff"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "example/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "资质示例",
|
||||
"navigationBarTitleText": "审核状态",
|
||||
"navigationBarBackgroundColor": "#fff"
|
||||
}
|
||||
}
|
||||
@ -679,8 +602,7 @@
|
||||
"path": "index/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "湖畔好店",
|
||||
"navigationBarBackgroundColor": "#fff",
|
||||
"enablePullDownRefresh": true
|
||||
"navigationBarBackgroundColor": "#fff"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@ -203,7 +203,7 @@
|
||||
买单返积分
|
||||
</view>
|
||||
</view>
|
||||
<view class="merchantItem_right_con_right" @click.stop="toJump(item)">
|
||||
<view class="merchantItem_right_con_right" @click="toJump(item)">
|
||||
<image src="https://static.hshuishang.com/property-img-file/local_review.png" mode="aspectFill">
|
||||
</image>
|
||||
点评
|
||||
@ -489,9 +489,6 @@ export default {
|
||||
uni.setStorageSync('location', preciseLocation);
|
||||
uni.setStorageSync('ad_code', ad_info.adcode);
|
||||
// TODO: 这里需要强依赖 ad_code 去查询,必须保障代码先后执行顺序正确
|
||||
// 先一次性批量拉取首页各广告位(1-11),后续各 getHomeXxx 直接读缓存,
|
||||
// 把原来十几次 banner-region 请求压成一次
|
||||
await this.prefetchBannerGroups();
|
||||
const [bannerList, serverLeft, serverRightList, homeLeftList, homeRightList, bottomList, buttonList, categoryList] = await Promise.all([
|
||||
|
||||
this.getHomeBanner(),// 轮播图查询
|
||||
@ -668,57 +665,30 @@ export default {
|
||||
|
||||
async headershopEnterClick() {
|
||||
if (!uni.getStorageSync('userId')) {
|
||||
NavgateTo('/packages/shopEnter/choose/index', { isLogin: false });
|
||||
NavgateTo('/packages/shopEnter/index/index', { isLogin: false });
|
||||
return
|
||||
}
|
||||
const res = await request(apiArr2.statusQuery, "POST", {}, { silent: false });
|
||||
if (res.status) {
|
||||
NavgateTo('/packages/shopEnter/auditStatus/index?itemObj=' + JSON.stringify(res));
|
||||
} else {
|
||||
NavgateTo('/packages/shopEnter/choose/index');
|
||||
NavgateTo('/packages/shopEnter/index/index');
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
// 一次性拉取多个广告位,结果缓存到 this._bannerGroups,供各 getHomeXxx 读取,
|
||||
// 把原来十几次 banner-region 请求压成一次。
|
||||
async prefetchBannerGroups(positions = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]) {
|
||||
try {
|
||||
const res = await request(apiArr2.getHomeBannerMulti, "POST", {
|
||||
ad_code: Number(uni.getStorageSync('ad_code')),
|
||||
ad_positions: positions,
|
||||
longitude: uni.getStorageSync('location').lng,
|
||||
latitude: uni.getStorageSync('location').lat,
|
||||
page_size: 50
|
||||
}, { silent: false });
|
||||
this._bannerGroups = (res && res.groups) ? res.groups : {};
|
||||
} catch (e) {
|
||||
console.warn('批量拉取首页广告失败,回退逐个请求:', e);
|
||||
this._bannerGroups = null; // 标记不可用,各方法回退单查
|
||||
}
|
||||
},
|
||||
|
||||
// 读取某广告位的数据:优先用批量缓存,缓存缺失则回退单个 page 请求(保证方法可独立工作)
|
||||
async getBannerRows(position) {
|
||||
if (this._bannerGroups) {
|
||||
const rows = this._bannerGroups[String(position)] || [];
|
||||
return rows;
|
||||
}
|
||||
async getHomeBanner() {
|
||||
const res = await request(apiArr2.getHomeBanner, "POST", {
|
||||
ad_code: uni.getStorageSync('ad_code'),
|
||||
ad_position: position,
|
||||
ad_position: 1,
|
||||
longitude: uni.getStorageSync('location').lng,
|
||||
latitude: uni.getStorageSync('location').lat,
|
||||
page_num: 1,
|
||||
page_size: 50
|
||||
page_size: 10
|
||||
}, { silent: false });
|
||||
return (res && res.rows) ? res.rows : [];
|
||||
},
|
||||
|
||||
async getHomeBanner() {
|
||||
const rows = await this.getBannerRows(1);
|
||||
if (rows && rows.length) {
|
||||
let filterRes = this.filterShowList(rows, 1);
|
||||
if (res.rows && res.rows.length) {
|
||||
let filterRes = this.filterShowList(res.rows, 1);
|
||||
filterRes.forEach(item => {
|
||||
item.pic_src = picUrl + item.pic_src
|
||||
})
|
||||
@ -729,14 +699,21 @@ export default {
|
||||
},
|
||||
|
||||
async getServerLeft() {
|
||||
const rows = await this.getBannerRows(2);
|
||||
if (!rows || !rows.length) {
|
||||
const res = await request(apiArr2.getHomeBanner, "POST", {
|
||||
ad_code: uni.getStorageSync('ad_code'),
|
||||
ad_position: 2,
|
||||
longitude: uni.getStorageSync('location').lng,
|
||||
latitude: uni.getStorageSync('location').lat,
|
||||
page_num: 1,
|
||||
page_size: 10
|
||||
}, { silent: false });
|
||||
if (!res.rows || !res.rows.length) {
|
||||
this.serverLeftList = []
|
||||
}
|
||||
|
||||
if (rows && rows.length) {
|
||||
this.serverLeftList = rows
|
||||
let filterRes = this.filterShowList(rows, 1);
|
||||
if (res.rows && res.rows.length) {
|
||||
this.serverLeftList = res.rows
|
||||
let filterRes = this.filterShowList(res?.rows, 1);
|
||||
filterRes.forEach(item => {
|
||||
item.pic_src = picUrl + item.pic_src
|
||||
})
|
||||
@ -750,12 +727,19 @@ export default {
|
||||
async getServerRight() {
|
||||
const rightList = []
|
||||
for (let i = 3; i < 5; i++) {
|
||||
const rows = await this.getBannerRows(i);
|
||||
if (!rows || !rows.length) {
|
||||
const res = await request(apiArr2.getHomeBanner, "POST", {
|
||||
ad_code: uni.getStorageSync('ad_code'),
|
||||
ad_position: i,
|
||||
longitude: uni.getStorageSync('location').lng,
|
||||
latitude: uni.getStorageSync('location').lat,
|
||||
page_num: 1,
|
||||
page_size: 10
|
||||
}, { silent: false });
|
||||
if (!res.rows || !res.rows.length) {
|
||||
this.serverRightList = []
|
||||
}
|
||||
if (rows && rows.length) {
|
||||
let filterRes = this.filterShowList(rows, 1);
|
||||
if (res.rows && res.rows.length) {
|
||||
let filterRes = this.filterShowList(res?.rows, 1);
|
||||
filterRes.forEach(item => {
|
||||
item.pic_src = picUrl + item.pic_src
|
||||
})
|
||||
@ -766,9 +750,16 @@ export default {
|
||||
},
|
||||
|
||||
async getHomeMidLeft() {
|
||||
const rows = await this.getBannerRows(5);
|
||||
if (rows && rows.length) {
|
||||
let filterRes = this.filterShowList(rows, 1);
|
||||
const res = await request(apiArr2.getHomeBanner, "POST", {
|
||||
ad_code: uni.getStorageSync('ad_code'),
|
||||
ad_position: 5,
|
||||
longitude: uni.getStorageSync('location').lng,
|
||||
latitude: uni.getStorageSync('location').lat,
|
||||
page_num: 1,
|
||||
page_size: 10
|
||||
}, { silent: false });
|
||||
if (res.rows && res.rows.length) {
|
||||
let filterRes = this.filterShowList(res?.rows, 1);
|
||||
filterRes.forEach(item => {
|
||||
item.pic_src = picUrl + item.pic_src
|
||||
})
|
||||
@ -781,9 +772,19 @@ export default {
|
||||
async getHomeMidRight() {
|
||||
const rightList = []
|
||||
for (let i = 6; i < 12; i++) {
|
||||
const rows = await this.getBannerRows(i);
|
||||
if (rows && rows.length) {
|
||||
let filterRes = this.filterShowList(rows, 1);
|
||||
const res = await request(apiArr2.getHomeBanner, "POST", {
|
||||
ad_code: uni.getStorageSync('ad_code'),
|
||||
ad_position: i,
|
||||
longitude: uni.getStorageSync('location').lng,
|
||||
latitude: uni.getStorageSync('location').lat,
|
||||
page_num: 1,
|
||||
page_size: 10
|
||||
}, { silent: false });
|
||||
if (res.rows && res.rows.length) {
|
||||
// let firstItem = res.rows[0];
|
||||
// firstItem.pic_src = picUrl + firstItem.pic_src;
|
||||
// rightList.push(firstItem);
|
||||
let filterRes = this.filterShowList(res?.rows, 1);
|
||||
filterRes.forEach(item => {
|
||||
item.pic_src = picUrl + item.pic_src
|
||||
})
|
||||
@ -1196,14 +1197,6 @@ export default {
|
||||
}
|
||||
},
|
||||
|
||||
onPullDownRefresh() {
|
||||
this.bottomList = [];
|
||||
this.bottomPageNum = 1;
|
||||
this.flag = false;
|
||||
this.init();
|
||||
uni.stopPullDownRefresh();
|
||||
},
|
||||
|
||||
async onReachBottom() {
|
||||
if (this.flag) {
|
||||
const res = await this.getHomeBottom();
|
||||
|
||||
@ -17,16 +17,6 @@
|
||||
<view class="login-tip" style="font-size: 28rpx; color: #555555; margin-top: 30rpx;">为了更好的体验,申请获取您的公开信息
|
||||
</view>
|
||||
<view class="login-tip" style="font-size: 28rpx; color: #555555; margin-top: 14rpx;">(头像、昵称等)</view>
|
||||
|
||||
<view class="profile-fill">
|
||||
<button class="avatar-btn" open-type="chooseAvatar" @chooseavatar="onChooseAvatar">
|
||||
<image class="avatar-img" :src="avatarUrl || defaultAvatar" mode="aspectFill"></image>
|
||||
<text class="avatar-tip">点击选择头像</text>
|
||||
</button>
|
||||
<input type="nickname" class="nickname-input" :value="nickName" placeholder="点击填写昵称"
|
||||
@blur="onNickInput" @input="onNickInput" />
|
||||
</view>
|
||||
|
||||
<view class="login-button">
|
||||
<button class="login-btn" open-type="getPhoneNumber" @click="headerLoginClick"
|
||||
@getphonenumber="getPhoneNumber">
|
||||
@ -47,7 +37,6 @@
|
||||
import { apiArr } from '../../api/login';
|
||||
import { apiArr as apiArr2 } from '../../api/v2User';
|
||||
import { request } from '../../utils';
|
||||
import { uploadOSS } from '@/utils/uploadOSS';
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
@ -55,26 +44,10 @@ export default {
|
||||
loginChannel: '', // 登录渠道
|
||||
userId: '',
|
||||
passWord: '',
|
||||
nickName: '', // 微信昵称(头像昵称填写能力)
|
||||
avatarUrl: '', // 头像预览地址(临时或OSS)
|
||||
avatarTemp: '', // 微信头像临时路径,登录后再传OSS
|
||||
defaultAvatar: 'https://static.hshuishang.com/loginMainImg.png',
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
||||
// 选择头像回调:此时尚未登录(无 token),仅暂存临时路径,
|
||||
// 待 get-phone 成功拿到 token 后再上传 OSS
|
||||
onChooseAvatar(e) {
|
||||
this.avatarTemp = e.detail.avatarUrl || '';
|
||||
this.avatarUrl = this.avatarTemp; // 仅用于界面预览
|
||||
},
|
||||
|
||||
// 昵称输入回调
|
||||
onNickInput(e) {
|
||||
this.nickName = e.detail.value || '';
|
||||
},
|
||||
|
||||
headerInputClick(e) {
|
||||
const { name } = e.currentTarget.dataset;
|
||||
const { value } = e.detail;
|
||||
@ -141,30 +114,12 @@ export default {
|
||||
// return
|
||||
if (event.detail.errMsg === "getPhoneNumber:ok") {
|
||||
request(apiArr.loginGetUserPhone, 'POST', {
|
||||
code: event.detail.code,
|
||||
user_id: uni.getStorageSync('userId'),
|
||||
nick_name: this.nickName || ''
|
||||
}, { silent: false }).then(async (res) => {
|
||||
code: event.detail.code
|
||||
}, { silent: false }).then((res) => {
|
||||
console.log(res);
|
||||
uni.hideLoading();
|
||||
if (isLogin) {
|
||||
uni.setStorageSync('phone', res.phone);
|
||||
if (this.nickName) uni.setStorageSync('nickName', this.nickName);
|
||||
// 此时已登录(有 token),把头像临时路径上传到 OSS 并落库
|
||||
if (this.avatarTemp) {
|
||||
try {
|
||||
const { objectKey } = await uploadOSS({ filePath: this.avatarTemp, scene: 'avatar', showLoading: false });
|
||||
// 数据库统一存相对 object key(带前导/),显示时再拼 CDN 域名
|
||||
const avatarPath = '/' + objectKey;
|
||||
await request(apiArr2.userInfoUpdate, 'POST', {
|
||||
user_id: uni.getStorageSync('userId'),
|
||||
avatar: avatarPath
|
||||
}, { silent: true });
|
||||
uni.setStorageSync('headPhoto', avatarPath);
|
||||
} catch (err) {
|
||||
console.error('头像上传/保存失败:', err);
|
||||
}
|
||||
}
|
||||
uni.hideLoading();
|
||||
uni.showToast({
|
||||
title: '登录成功',
|
||||
icon: 'success',
|
||||
@ -177,7 +132,6 @@ export default {
|
||||
}
|
||||
});
|
||||
} else {
|
||||
uni.hideLoading();
|
||||
uni.showToast({
|
||||
title: '登录失败',
|
||||
icon: 'error',
|
||||
@ -227,10 +181,8 @@ export default {
|
||||
page_num: 1,
|
||||
page_size: 10,
|
||||
}, { silent: false }).then((res3) => {
|
||||
const rows = (res3 && res3.rows) || [];
|
||||
if (rows.length > 0) {
|
||||
uni.setStorageSync("changeCommData", { name: rows[0].name, id: rows[0].community_id });
|
||||
}
|
||||
const { rows: [{}] } = res3;
|
||||
uni.setStorageSync("changeCommData",{ name: rows[0].name, id: rows[0].community_id })
|
||||
})
|
||||
},
|
||||
|
||||
@ -308,49 +260,4 @@ export default {
|
||||
|
||||
<style>
|
||||
@import url("./login.css");
|
||||
|
||||
.profile-fill {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
margin-top: 30rpx;
|
||||
}
|
||||
|
||||
.avatar-btn {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
background: transparent;
|
||||
border: none;
|
||||
padding: 0;
|
||||
line-height: normal;
|
||||
}
|
||||
|
||||
.avatar-btn::after {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.avatar-img {
|
||||
width: 120rpx;
|
||||
height: 120rpx;
|
||||
border-radius: 50%;
|
||||
background-color: #f2f2f2;
|
||||
}
|
||||
|
||||
.avatar-tip {
|
||||
font-size: 24rpx;
|
||||
color: #999999;
|
||||
margin-top: 10rpx;
|
||||
}
|
||||
|
||||
.nickname-input {
|
||||
width: 420rpx;
|
||||
height: 80rpx;
|
||||
margin-top: 24rpx;
|
||||
padding: 0 24rpx;
|
||||
border: 1rpx solid #e0e0e0;
|
||||
border-radius: 12rpx;
|
||||
font-size: 28rpx;
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
@ -71,11 +71,11 @@
|
||||
src="https://static.hshuishang.com/property-img-file/page_user_Group_1557.png" />
|
||||
<text class="device-title title-item">我的工单</text>
|
||||
</view>
|
||||
<!--view class="item_device" @click="handleMeApplyClick">
|
||||
<view class="item_device" @click="handleMeApplyClick">
|
||||
<image class="icon-img"
|
||||
src="https://static.hshuishang.com/property-img-file/page_user_Group_1558.png" />
|
||||
<text class="device-title title-item">我的管家</text>
|
||||
</view-->
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@ -169,16 +169,16 @@ export default {
|
||||
name: "团购订单",
|
||||
url: "/packages/myOrders/groupOrders/index",
|
||||
},
|
||||
// {
|
||||
// image: "https://static.hshuishang.com/property-img-file/page_user_Group_1565.png",
|
||||
// name: "我的收藏",
|
||||
// url: "",
|
||||
// },
|
||||
// {
|
||||
// image: "https://static.hshuishang.com/property-img-file/page_user_Group_1566.png",
|
||||
// name: "售后服务",
|
||||
// url: "",
|
||||
// },
|
||||
{
|
||||
image: "https://static.hshuishang.com/property-img-file/page_user_Group_1565.png",
|
||||
name: "我的收藏",
|
||||
url: "",
|
||||
},
|
||||
{
|
||||
image: "https://static.hshuishang.com/property-img-file/page_user_Group_1566.png",
|
||||
name: "售后服务",
|
||||
url: "",
|
||||
},
|
||||
{
|
||||
image: "https://static.hshuishang.com/property-img-file/page_user_Group_1563.png",
|
||||
name: "收货地址",
|
||||
@ -192,34 +192,34 @@ export default {
|
||||
],
|
||||
visitList: [{
|
||||
image: "https://static.hshuishang.com/property-img-file/page_user_Group_1572.png",
|
||||
name: "到家服务订单",
|
||||
url: "/packages/homeService/myOrders/index",
|
||||
name: "服务工单",
|
||||
url: "",
|
||||
},
|
||||
{
|
||||
image: "https://static.hshuishang.com/property-img-file/page_user_Group_1573.png",
|
||||
name: "我的月账单",
|
||||
url: "/packages/homeService/myMonthlyBills/index",
|
||||
name: "服务地址",
|
||||
url: "",
|
||||
},
|
||||
{
|
||||
image: "https://static.hshuishang.com/property-img-file/page_user_Group_1574.png",
|
||||
name: "我的家政合同",
|
||||
url: "/packages/homeService/myContracts/index",
|
||||
name: "服务卡",
|
||||
url: "",
|
||||
}
|
||||
],
|
||||
shopList: [{
|
||||
image: "https://static.hshuishang.com/property-img-file/page_user_Group_1580.png",
|
||||
name: "附近门店",
|
||||
url: "/packages/localLife/index/index",
|
||||
url: "",
|
||||
},
|
||||
{
|
||||
image: "https://static.hshuishang.com/property-img-file/page_user_Group_1581.png",
|
||||
name: "服务券",
|
||||
url: "",
|
||||
},
|
||||
// {
|
||||
// image: "https://static.hshuishang.com/property-img-file/page_user_Group_1581.png",
|
||||
// name: "服务券",
|
||||
// url: "",
|
||||
// },
|
||||
{
|
||||
image: "https://static.hshuishang.com/property-img-file/page_user_Group_1582.png",
|
||||
name: "支付记录",
|
||||
url: "/packages/localLife/payInfo/index",
|
||||
url: "",
|
||||
}
|
||||
],
|
||||
shopManagementList: [
|
||||
@ -240,12 +240,6 @@ export default {
|
||||
name: "物业端",
|
||||
url: "/packages/workOrderDashboard/guide/index",
|
||||
isShow: uni.getStorageSync("is_worker"),
|
||||
},
|
||||
{
|
||||
image: "https://static.hshuishang.com/property-img-file/userPageWuye.png",
|
||||
name: "师傅端",
|
||||
url: "/packages/homeService/worker/index",
|
||||
isShow: uni.getStorageSync("is_merchant"),
|
||||
}
|
||||
],
|
||||
parkList: [
|
||||
@ -353,12 +347,6 @@ export default {
|
||||
name: "物业端",
|
||||
url: "/packages/workOrderDashboard/guide/index",
|
||||
isShow: loginRes.is_worker,
|
||||
},
|
||||
{
|
||||
image: "https://static.hshuishang.com/property-img-file/userPageWuye.png",
|
||||
name: "师傅端",
|
||||
url: "/packages/homeService/worker/index",
|
||||
isShow: loginRes.is_merchant,
|
||||
}
|
||||
];
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
{
|
||||
"appid": "wx1addb25675dd8e70",
|
||||
"compileType": "miniprogram",
|
||||
"libVersion": "3.16.0",
|
||||
"libVersion": "3.8.3",
|
||||
"packOptions": {
|
||||
"ignore": [],
|
||||
"include": []
|
||||
@ -19,18 +19,7 @@
|
||||
"disablePlugins": [],
|
||||
"outputPath": ""
|
||||
},
|
||||
"condition": true,
|
||||
"compileWorklet": false,
|
||||
"uglifyFileName": false,
|
||||
"uploadWithSourceMap": true,
|
||||
"packNpmManually": false,
|
||||
"minifyWXSS": true,
|
||||
"minifyWXML": true,
|
||||
"localPlugins": false,
|
||||
"disableUseStrict": false,
|
||||
"useCompilerPlugins": false,
|
||||
"swc": false,
|
||||
"disableSWC": true
|
||||
"condition": true
|
||||
},
|
||||
"condition": {},
|
||||
"editorSetting": {
|
||||
|
||||
@ -2,22 +2,7 @@
|
||||
"description": "项目私有配置文件。此文件中的内容将覆盖 project.config.json 中的相同字段。项目的改动优先同步到此文件中。详见文档:https://developers.weixin.qq.com/miniprogram/dev/devtools/projectconfig.html",
|
||||
"projectname": "uniapp-ZHSQ",
|
||||
"setting": {
|
||||
"compileHotReLoad": true,
|
||||
"urlCheck": true,
|
||||
"coverView": true,
|
||||
"lazyloadPlaceholderEnable": false,
|
||||
"skylineRenderEnable": false,
|
||||
"preloadBackgroundData": false,
|
||||
"autoAudits": false,
|
||||
"useApiHook": true,
|
||||
"showShadowRootInWxmlPanel": true,
|
||||
"useStaticServer": false,
|
||||
"useLanDebug": false,
|
||||
"showES6CompileOption": false,
|
||||
"checkInvalidKey": true,
|
||||
"ignoreDevUnusedFiles": true,
|
||||
"bigPackageSizeSupport": false
|
||||
"compileHotReLoad": true
|
||||
},
|
||||
"libVersion": "3.16.0",
|
||||
"condition": {}
|
||||
"libVersion": "3.9.1"
|
||||
}
|
||||
@ -3,8 +3,8 @@ const environments = {
|
||||
development: {
|
||||
apiUrl: "https://test.hshuishang.com",
|
||||
picUrl: "https://test.hshuishang.com",
|
||||
aliyunOssUrl: "https://wechat-img-file-dev.oss-cn-beijing.aliyuncs.com",
|
||||
staticUrl: "https://static-dev.hshuishang.com",
|
||||
aliyunOssUrl: "https://wechat-img-file.oss-cn-beijing.aliyuncs.com",
|
||||
staticUrl: "https://static.hshuishang.com",
|
||||
},
|
||||
production: {
|
||||
apiUrl: "https://api.hshuishang.com",
|
||||
@ -16,6 +16,11 @@ const environments = {
|
||||
|
||||
// 判断当前环境
|
||||
const getCurrentEnvironment = () => {
|
||||
// 1. 优先通过NODE_ENV判断
|
||||
if (process && process.env && process.env.NODE_ENV) {
|
||||
return process.env.NODE_ENV;
|
||||
}
|
||||
|
||||
// 2. 微信小程序环境判断
|
||||
if (typeof wx !== "undefined" && wx.getAccountInfoSync) {
|
||||
try {
|
||||
@ -34,11 +39,6 @@ const getCurrentEnvironment = () => {
|
||||
}
|
||||
}
|
||||
|
||||
// 1. 优先通过NODE_ENV判断
|
||||
if (process && process.env && process.env.NODE_ENV) {
|
||||
return process.env.NODE_ENV;
|
||||
}
|
||||
|
||||
// 3. 通过全局配置判断(例如Vercel等平台的环境变量)
|
||||
if (typeof global !== "undefined" && global.env) {
|
||||
return global.env;
|
||||
@ -58,10 +58,9 @@ const currentEnv = getCurrentEnvironment();
|
||||
const envConfig = environments[currentEnv] || environments.production;
|
||||
|
||||
export const RequsetUrl = envConfig.apiUrl; // 请求地址前缀
|
||||
// 公开图片域名:统一走 CDN(dev: static-dev.hshuishang.com / prod: static.hshuishang.com)
|
||||
export const picUrl = envConfig.staticUrl;
|
||||
export const aliyunOssUrl = envConfig.aliyunOssUrl; // 阿里云OSS直链地址(私密文件签名 URL 已自带 host,一般不需要直接拼)
|
||||
export const staticUrl = envConfig.staticUrl; // CDN 加速域名
|
||||
export const picUrl = envConfig.picUrl; // 图片地址前缀
|
||||
export const aliyunOssUrl = envConfig.aliyunOssUrl; // 阿里云OSS地址
|
||||
export const staticUrl = envConfig.staticUrl; // 静态资源地址
|
||||
|
||||
/**
|
||||
* 处理图片URL,根据环境自动替换
|
||||
@ -227,7 +226,7 @@ export const request = (
|
||||
}
|
||||
resolve(res.data.data); // 请求成功
|
||||
} else {
|
||||
console.log("走到这列",RequsetUrl, url,res.header,res.data,res.profile);
|
||||
console.log("走到这列");
|
||||
uni.hideLoading();
|
||||
// uni.showToast({
|
||||
// title: res.data.msg || "请求失败",
|
||||
@ -326,26 +325,70 @@ export const floatCalculate = (num1, num2, operator) => {
|
||||
};
|
||||
|
||||
/**
|
||||
* 图片上传 —— 走 OSS 直传,回调形状对齐旧后端 { code, data: { path } },path 以 / 开头
|
||||
* @param {string} filename - 本地文件路径
|
||||
* @param {Function} fn - 回调函数
|
||||
* @param {string} [scene] - 场景,默认 common
|
||||
* 图片上传
|
||||
* @param {string} filename - 图片上传地址
|
||||
* @param {Function} fn - 接口回调函数
|
||||
*/
|
||||
export const upload = (filename, fn, scene = "common") => {
|
||||
// 引入此处避免顶层循环依赖
|
||||
const { uploadOSSCompat } = require("./uploadOSS.js");
|
||||
uploadOSSCompat(filename, fn, scene);
|
||||
export const upload = (filename, fn) => {
|
||||
uni.showLoading({
|
||||
title: "上传中",
|
||||
mask: true,
|
||||
});
|
||||
|
||||
uni.uploadFile({
|
||||
url: RequsetUrl + "/api/v1/public/upload-image",
|
||||
filePath: filename,
|
||||
name: "image",
|
||||
formData: {
|
||||
uid: uni.getStorageSync("uid"),
|
||||
},
|
||||
success: (f) => {
|
||||
uni.hideLoading();
|
||||
fn(JSON.parse(f.data));
|
||||
},
|
||||
fail: (res) => {
|
||||
uni.hideLoading();
|
||||
console.log(res);
|
||||
uni.showToast({
|
||||
title: "上传文件失败",
|
||||
icon: "none",
|
||||
});
|
||||
},
|
||||
complete: () => {},
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 视频上传 —— 走 OSS 直传
|
||||
* @param {string} filename - 本地文件路径
|
||||
* @param {Function} fn - 回调函数
|
||||
* @param {string} [scene] - 场景,默认 video
|
||||
* 视频上传
|
||||
* @param {string} filename - 图片上传地址
|
||||
* @param {Function} fn - 接口回调函数
|
||||
*/
|
||||
export const uploadVideo = (filename, fn, scene = "video") => {
|
||||
const { uploadOSSCompat } = require("./uploadOSS.js");
|
||||
uploadOSSCompat(filename, fn, scene);
|
||||
export const uploadVideo = (filename, fn) => {
|
||||
uni.showLoading({
|
||||
title: "上传中",
|
||||
mask: true,
|
||||
});
|
||||
uni.uploadFile({
|
||||
url: RequsetUrl + "/api/v1/public/upload-video",
|
||||
filePath: filename,
|
||||
name: "file",
|
||||
formData: {
|
||||
uid: uni.getStorageSync("uid"),
|
||||
},
|
||||
success: (f) => {
|
||||
uni.hideLoading();
|
||||
fn(JSON.parse(f.data));
|
||||
},
|
||||
fail: (res) => {
|
||||
uni.hideLoading();
|
||||
console.log(res);
|
||||
uni.showToast({
|
||||
title: "上传文件失败",
|
||||
icon: "none",
|
||||
});
|
||||
},
|
||||
complete: () => {},
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@ -1,152 +0,0 @@
|
||||
// uniapp-ZHSQ —— OSS 直传客户端
|
||||
//
|
||||
// 用法:
|
||||
// import { uploadOSS } from '@/utils/uploadOSS'
|
||||
// const { objectKey, url } = await uploadOSS({ filePath: tempFilePath, scene: 'avatar' })
|
||||
// // objectKey: OSS 上的相对 key,存数据库
|
||||
// // url: 公开访问 URL(如果走签名 URL 显示,前端再单独处理)
|
||||
//
|
||||
// 支持的 scene 由服务端 wechatOssSceneCfg 控制,目前:
|
||||
// - avatar 用户头像 (jpg/jpeg/png/webp,<=5MB)
|
||||
// - merchant 商家入驻资料 (jpg/jpeg/png/webp/pdf,<=10MB)
|
||||
|
||||
import { RequsetUrl, aliyunOssUrl } from "@/utils/index.js";
|
||||
|
||||
const inferExt = (filePath) => {
|
||||
if (!filePath) return "";
|
||||
const idx = filePath.lastIndexOf(".");
|
||||
if (idx < 0) return "";
|
||||
return filePath.substring(idx + 1).toLowerCase();
|
||||
};
|
||||
|
||||
const fetchCredential = (scene, ext, bindId) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const data = { scene, ext };
|
||||
if (bindId) data.bind_id = bindId; // 客服聊天场景:按会话分目录
|
||||
uni.request({
|
||||
url: RequsetUrl + "/api/v1/wechat/oss/credential",
|
||||
method: "POST",
|
||||
header: {
|
||||
Authorization: uni.getStorageSync("ctoken") || "",
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
data,
|
||||
success: (res) => {
|
||||
if (res.statusCode !== 200) return reject(new Error("获取上传凭证失败:" + res.statusCode));
|
||||
const body = res.data || {};
|
||||
// 兼容服务端通用响应包装
|
||||
const data = body.data || body;
|
||||
if (!data || !data.host) return reject(new Error("上传凭证字段缺失"));
|
||||
resolve(data);
|
||||
},
|
||||
fail: (err) => reject(err),
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
const postToOSS = (filePath, cred) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
uni.uploadFile({
|
||||
url: cred.host,
|
||||
filePath,
|
||||
name: "file", // 必须是 file,OSS PostObject 协议约定
|
||||
formData: {
|
||||
key: cred.object_key,
|
||||
OSSAccessKeyId: cred.access_key_id,
|
||||
"x-oss-security-token": cred.security_token,
|
||||
policy: cred.policy,
|
||||
signature: cred.signature,
|
||||
success_action_status: "200",
|
||||
},
|
||||
success: (res) => {
|
||||
// OSS 200 -> 空 body 视为成功
|
||||
if (res.statusCode === 200 || res.statusCode === 204) {
|
||||
resolve();
|
||||
} else {
|
||||
reject(new Error("OSS 上传失败:" + res.statusCode + " " + (res.data || "")));
|
||||
}
|
||||
},
|
||||
fail: (err) => reject(err),
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 直传 OSS。
|
||||
* @param {Object} opts
|
||||
* @param {string} opts.filePath 本地文件临时路径(uni.chooseImage 拿到的 path)
|
||||
* @param {string} opts.scene 上传场景:avatar / merchant
|
||||
* @param {string} [opts.ext] 扩展名(不含点);不传则从 filePath 推断
|
||||
* @param {boolean} [opts.showLoading=true]
|
||||
* @returns {Promise<{ objectKey: string, url: string }>}
|
||||
*/
|
||||
export const uploadOSS = async ({ filePath, scene, ext, bindId, showLoading = true }) => {
|
||||
if (!filePath) throw new Error("filePath 不能为空");
|
||||
if (!scene) throw new Error("scene 不能为空");
|
||||
|
||||
const finalExt = (ext || inferExt(filePath)).toLowerCase();
|
||||
if (!finalExt) throw new Error("无法识别文件扩展名");
|
||||
|
||||
if (showLoading) uni.showLoading({ title: "上传中", mask: true });
|
||||
try {
|
||||
const cred = await fetchCredential(scene, finalExt, bindId);
|
||||
await postToOSS(filePath, cred);
|
||||
return {
|
||||
objectKey: cred.object_key,
|
||||
url: aliyunOssUrl + "/" + cred.object_key,
|
||||
};
|
||||
} finally {
|
||||
if (showLoading) uni.hideLoading();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 兼容旧版 utils/index.js 中 upload(filename, fn) 的回调式 API。
|
||||
* 内部走 OSS 直传,回调 res 形状对齐旧版(res.data.path 为以 / 开头的 object key,
|
||||
* 调用方 picUrl + res.data.path 可以直接拼成完整 URL)。
|
||||
*
|
||||
* @param {string} filePath
|
||||
* @param {Function} fn 接收 { code, msg, data: { path } }
|
||||
* @param {string} [scene='merchant']
|
||||
*/
|
||||
export const uploadOSSCompat = (filePath, fn, scene = "merchant") => {
|
||||
uploadOSS({ filePath, scene })
|
||||
.then(({ objectKey }) => {
|
||||
fn && fn({ code: 1, msg: "ok", data: { path: "/" + objectKey } });
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error("uploadOSSCompat 失败:", err);
|
||||
uni.showToast({ title: err.message || "上传文件失败", icon: "none" });
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 取私密文件查看 URL(小程序商家本人查看自己上传的证件 / 合同)。
|
||||
* 服务端会校验 path 必须以 wechat/merchant_private/{当前 user_id}/ 开头。
|
||||
*
|
||||
* @param {string} objectKey 存数据库的 path(带或不带前导 /)
|
||||
* @returns {Promise<{ url: string, expireSeconds: number }>}
|
||||
*/
|
||||
export const signPrivateView = (objectKey) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!objectKey) return reject(new Error("object_key 不能为空"));
|
||||
const cleanKey = objectKey.replace(/^\/+/, "");
|
||||
uni.request({
|
||||
url: RequsetUrl + "/api/v1/wechat/oss/sign-private-view",
|
||||
method: "POST",
|
||||
header: {
|
||||
Authorization: uni.getStorageSync("ctoken") || "",
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
data: { object_key: cleanKey },
|
||||
success: (res) => {
|
||||
if (res.statusCode !== 200) return reject(new Error("签发失败:" + res.statusCode));
|
||||
const body = res.data || {};
|
||||
const data = body.data || body;
|
||||
if (!data || !data.url) return reject(new Error("签发结果字段缺失"));
|
||||
resolve({ url: data.url, expireSeconds: data.expire_seconds });
|
||||
},
|
||||
fail: (err) => reject(err),
|
||||
});
|
||||
});
|
||||
};
|
||||
Loading…
x
Reference in New Issue
Block a user