fix oss public/private logic, fixed merchant-info submit logic
This commit is contained in:
parent
d3ac0573bf
commit
5fc340a47a
107
components/PrivateImage.vue
Normal file
107
components/PrivateImage.vue
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
<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,18 +167,21 @@ export default {
|
|||||||
// 解析path字段,提取scene参数的值
|
// 解析path字段,提取scene参数的值
|
||||||
const pathParts = res.path.split('?');
|
const pathParts = res.path.split('?');
|
||||||
if (pathParts.length > 1) {
|
if (pathParts.length > 1) {
|
||||||
const queryParams = pathParts[1].split('&');
|
if (pathParts[1].startsWith('scene=')){
|
||||||
for (const param of queryParams) {
|
const pathPart = decodeURIComponent(pathParts[1].substring(6))
|
||||||
const [key, value] = param.split('=');
|
const queryParams = pathPart.split('&');
|
||||||
if (key === 'scene') {
|
for (const param of queryParams) {
|
||||||
const params = {
|
const [key, value] = param.split('=');
|
||||||
id: value
|
if (key === 'id') {
|
||||||
}
|
const params = {
|
||||||
uni.setStorageSync('merchantInfo', params);
|
id: value
|
||||||
NavgateTo('/packages/localLife/detail/index')
|
}
|
||||||
break;
|
uni.setStorageSync('merchantInfo', params);
|
||||||
}
|
NavgateTo('/packages/localLife/detail/index')
|
||||||
}
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@ -68,9 +68,9 @@ export default {
|
|||||||
},
|
},
|
||||||
getAvatarUrl(record){
|
getAvatarUrl(record){
|
||||||
if(record.client_id_one == uni.getStorageSync('openId')){
|
if(record.client_id_one == uni.getStorageSync('openId')){
|
||||||
return record.two.avatar ? picUrl + record.two.avatar : 'https://static.hshuishang.com/defaultTx.png'
|
return record.two && record.two.avatar ? picUrl + record.two.avatar : 'https://static.hshuishang.com/defaultTx.png'
|
||||||
}else{
|
}else{
|
||||||
return record.one.avatar ? picUrl + record.one.avatar : 'https://static.hshuishang.com/defaultTx.png'
|
return record.one && record.one.avatar ? picUrl + record.one.avatar : 'https://static.hshuishang.com/defaultTx.png'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// 格式化时间
|
// 格式化时间
|
||||||
|
|||||||
@ -160,6 +160,7 @@ export default {
|
|||||||
const options = {
|
const options = {
|
||||||
clientId: this.selfClientId
|
clientId: this.selfClientId
|
||||||
}
|
}
|
||||||
|
console.log('clientId:', options.clientId)
|
||||||
|
|
||||||
// 添加连接状态回调
|
// 添加连接状态回调
|
||||||
const callbacks = {
|
const callbacks = {
|
||||||
|
|||||||
@ -0,0 +1,16 @@
|
|||||||
|
<template>
|
||||||
|
<view class="container">
|
||||||
|
<view>提交订单</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {};
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
</style>
|
||||||
@ -100,7 +100,18 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
onLoad(options) {
|
onLoad(options) {
|
||||||
this.itemObj = JSON.parse(options.itemObj);
|
if (options && options.itemObj) {
|
||||||
|
try {
|
||||||
|
const raw = decodeURIComponent(options.itemObj)
|
||||||
|
this.itemObj = JSON.parse(raw)
|
||||||
|
} catch (e) {
|
||||||
|
console.error('解析审核状态参数失败:', e)
|
||||||
|
this.itemObj = {}
|
||||||
|
}
|
||||||
|
} else if (options && options.status) {
|
||||||
|
// 兼容老版本:仅带 status,没有完整对象
|
||||||
|
this.itemObj = { status: Number(options.status) }
|
||||||
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
goShopManage() {
|
goShopManage() {
|
||||||
|
|||||||
95
packages/shopEnter/choose/index.css
Normal file
95
packages/shopEnter/choose/index.css
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
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;
|
||||||
|
}
|
||||||
63
packages/shopEnter/choose/index.vue
Normal file
63
packages/shopEnter/choose/index.vue
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
<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>
|
||||||
66
packages/shopEnter/example/index.css
Normal file
66
packages/shopEnter/example/index.css
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
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;
|
||||||
|
}
|
||||||
69
packages/shopEnter/example/index.vue
Normal file
69
packages/shopEnter/example/index.vue
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
<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>
|
||||||
|
</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: '身份证示例'
|
||||||
|
}
|
||||||
|
uni.setNavigationBarTitle({
|
||||||
|
title: titleMap[this.type] || '资质示例'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
@import url("./index.css");
|
||||||
|
</style>
|
||||||
@ -1,116 +1,420 @@
|
|||||||
|
/* ============================================================
|
||||||
|
* 商家入驻 - 基本信息 tab 全新样式(按设计稿 PDF 1)
|
||||||
|
* 主色 #FF370B 辅色 #FFF1ED 灰边 #EEE 灰字 #999 深字 #222
|
||||||
|
* ============================================================ */
|
||||||
|
|
||||||
page {
|
page {
|
||||||
background-color: #f6f7fb;
|
background-color: #F6F7F9;
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
padding-bottom: 60rpx;
|
padding-bottom: 200rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
.container {
|
.container {
|
||||||
background: url(https://static.hshuishang.com/property-img-file/shopEn_apply.png) no-repeat;
|
padding-bottom: 40rpx;
|
||||||
background-size: 750rpx 497rpx;
|
box-sizing: border-box;
|
||||||
box-sizing: border-box;
|
|
||||||
padding-top: 290rpx;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.Msg {
|
/* ================= 顶部进度条(红底胶囊) ================= */
|
||||||
width: 710rpx;
|
.step-bar {
|
||||||
background: #FFFFFF;
|
display: flex;
|
||||||
border-radius: 20rpx 20rpx 20rpx 20rpx;
|
align-items: center;
|
||||||
margin: 0 auto;
|
justify-content: space-between;
|
||||||
padding: 0 20rpx;
|
padding: 24rpx 30rpx 28rpx;
|
||||||
box-sizing: border-box;
|
background: linear-gradient(91deg, #FF7658 0%, #FF370B 100%);
|
||||||
}
|
}
|
||||||
|
|
||||||
.row {
|
.step-pill {
|
||||||
padding-top: 30rpx;
|
flex: 1;
|
||||||
display: flex;
|
height: 60rpx;
|
||||||
justify-content: space-between;
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
.row_label {
|
.step-pill.active {
|
||||||
font-size: 28rpx;
|
background: #FFFFFF;
|
||||||
color: #999999;
|
color: #FF370B;
|
||||||
width: 180rpx;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
|
|
||||||
.red {
|
/* ================= Tab 切换 ================= */
|
||||||
color: #FF370B;
|
.tab-bar {
|
||||||
margin-left: 5rpx;
|
display: flex;
|
||||||
|
background: #FFFFFF;
|
||||||
|
padding: 0 60rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
.row_con {
|
.tab-item {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
padding-bottom: 30rpx;
|
text-align: center;
|
||||||
border-bottom: 1rpx solid #EBEBEB;
|
padding: 28rpx 0 22rpx;
|
||||||
display: flex;
|
font-size: 30rpx;
|
||||||
|
color: #222;
|
||||||
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
.row_con input {
|
.tab-item.active {
|
||||||
flex: 1;
|
color: #FF370B;
|
||||||
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nonebor {
|
.tab-item.active::after {
|
||||||
border-bottom: none;
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
bottom: 8rpx;
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
width: 56rpx;
|
||||||
|
height: 6rpx;
|
||||||
|
background: #FF370B;
|
||||||
|
border-radius: 3rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
.row2 {
|
/* ================= 表单卡片 ================= */
|
||||||
display: flex;
|
.form-card {
|
||||||
align-items: center;
|
background: #FFFFFF;
|
||||||
|
margin: 20rpx 24rpx 0;
|
||||||
|
padding: 24rpx;
|
||||||
|
border-radius: 16rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mt {
|
.field {
|
||||||
margin-top: 26rpx;
|
margin-top: 20rpx;
|
||||||
padding-top: 36rpx;
|
|
||||||
padding-bottom: 36rpx;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.field:first-child {
|
||||||
|
margin-top: 0;
|
||||||
.imgCon {
|
|
||||||
font-size: 18rpx;
|
|
||||||
color: #222222;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
width: 120rpx;
|
|
||||||
height: 120rpx;
|
|
||||||
background: #F6F7FB;
|
|
||||||
border: 1rpx solid #D1D1D1;
|
|
||||||
border-radius: 10rpx 10rpx 10rpx 10rpx;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.imgCon image {
|
.field-label {
|
||||||
width: 34rpx;
|
font-size: 26rpx;
|
||||||
height: 34rpx;
|
color: #222;
|
||||||
margin-bottom: 8rpx;
|
margin-bottom: 14rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mt2 {
|
.field-label .star {
|
||||||
margin-top: 30rpx;
|
color: #FF370B;
|
||||||
|
margin-right: 4rpx;
|
||||||
|
font-size: 26rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
.u-upload__wrap__preview {
|
.field-input {
|
||||||
width: 120rpx;
|
height: 80rpx;
|
||||||
height: 120rpx;
|
border: 1rpx solid #EBEBEB;
|
||||||
border-radius: 10rpx 0rpx 10rpx 10rpx !important;
|
border-radius: 8rpx;
|
||||||
|
padding: 0 20rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
background: #FFFFFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
.u-upload__wrap__preview__image {
|
.field-input input {
|
||||||
width: 100% !important;
|
flex: 1;
|
||||||
height: 100% !important;
|
font-size: 28rpx;
|
||||||
object-fit: cover;
|
color: #222;
|
||||||
|
height: 80rpx;
|
||||||
|
line-height: 80rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
.addBtn {
|
.field-input input::placeholder,
|
||||||
font-size: 36rpx;
|
.field-input .placeholder {
|
||||||
color: #FFFFFF;
|
color: #B7B7B7;
|
||||||
width: 600rpx;
|
}
|
||||||
height: 90rpx;
|
|
||||||
background: linear-gradient(91deg, #FF7658 0%, #FF370B 100%);
|
.field-input.disabled {
|
||||||
border-radius: 100rpx 100rpx 100rpx 100rpx;
|
background: #FAFAFA;
|
||||||
margin: 0 auto;
|
}
|
||||||
margin-top: 58rpx;
|
|
||||||
display: flex;
|
.field-value {
|
||||||
align-items: center;
|
flex: 1;
|
||||||
justify-content: center;
|
font-size: 28rpx;
|
||||||
|
color: #222;
|
||||||
|
}
|
||||||
|
|
||||||
|
.field-value.placeholder {
|
||||||
|
color: #B7B7B7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.field-arrow {
|
||||||
|
color: #C8C8C8;
|
||||||
|
font-size: 24rpx;
|
||||||
|
margin-left: 12rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ================= 上传图片块 ================= */
|
||||||
|
.upload-section {
|
||||||
|
margin-top: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.upload-title {
|
||||||
|
font-size: 26rpx;
|
||||||
|
color: #222;
|
||||||
|
margin-bottom: 16rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.upload-title .star {
|
||||||
|
color: #FF370B;
|
||||||
|
margin-right: 4rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.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;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
color: #999;
|
||||||
|
font-size: 22rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.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;
|
||||||
|
margin-bottom: 8rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tip-box .tip-item {
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #FF370B;
|
||||||
|
line-height: 40rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ================= 底部按钮(吸底) ================= */
|
||||||
|
.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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ================= 协议勾选 ================= */
|
||||||
|
.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;
|
||||||
}
|
}
|
||||||
@ -1,119 +1,342 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="container">
|
<view class="container">
|
||||||
<view class="Msg">
|
<!-- 顶部进度条(红底胶囊三段) -->
|
||||||
<view class="row">
|
<view class="step-bar">
|
||||||
<view class="row_label">门店名称<text class="red">*</text></view>
|
<view class="step-pill" :class="{ active: currentTab >= 1 }">填写信息</view>
|
||||||
<view class="row_con">
|
<view class="step-pill" :class="{ active: currentTab >= 4 }">提交审核</view>
|
||||||
<input type="text" v-model="store_name" placeholder="需与门牌照名称一致">
|
<view class="step-pill" :class="{ active: currentTab >= 5 }">入驻成功</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- Tab 切换 -->
|
||||||
|
<view class="tab-bar">
|
||||||
|
<view class="tab-item" :class="{ active: currentTab === 1 }" @click="switchTab(1)">基本信息</view>
|
||||||
|
<view class="tab-item" :class="{ active: currentTab === 2 }" @click="switchTab(2)">资质信息</view>
|
||||||
|
<view class="tab-item" :class="{ active: currentTab === 3 }" @click="switchTab(3)">结算信息</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- ============ Tab 1: 基本信息 ============ -->
|
||||||
|
<view v-show="currentTab === 1">
|
||||||
|
<!-- 文本字段 -->
|
||||||
|
<view class="form-card">
|
||||||
|
<view class="field">
|
||||||
|
<view class="field-label"><text class="star">*</text>门店名称</view>
|
||||||
|
<view class="field-input">
|
||||||
|
<input type="text" v-model="store_name" placeholder="需与门牌照名称一致" />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="field">
|
||||||
|
<view class="field-label"><text class="star">*</text>所在地区</view>
|
||||||
|
<view class="field-input" @click="openRegion">
|
||||||
|
<view class="field-value" :class="{ placeholder: !regionLabel }">
|
||||||
|
{{ regionLabel || '请选择省/市/区' }}
|
||||||
|
</view>
|
||||||
|
<u-icon name="arrow-right" color="#C8C8C8" size="24"></u-icon>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="field">
|
||||||
|
<view class="field-label"><text class="star">*</text>详细地址</view>
|
||||||
|
<view class="field-input">
|
||||||
|
<input type="text" v-model="address" placeholder="请输入详细地址" />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="field">
|
||||||
|
<view class="field-label"><text class="star">*</text>商家类目</view>
|
||||||
|
<view class="field-input" @click="openClassify">
|
||||||
|
<view class="field-value" :class="{ placeholder: !confirmClassify.cate_name }">
|
||||||
|
{{ confirmClassify.cate_name || '选择经营品类' }}
|
||||||
|
</view>
|
||||||
|
<u-icon name="arrow-right" color="#C8C8C8" size="24"></u-icon>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="field">
|
||||||
|
<view class="field-label"><text class="star">*</text>营业状态</view>
|
||||||
|
<view class="field-input" @click="showBizStatus = true">
|
||||||
|
<view class="field-value" :class="{ placeholder: !bizStatusLabel }">
|
||||||
|
{{ bizStatusLabel || '选择营业状态' }}
|
||||||
|
</view>
|
||||||
|
<u-icon name="arrow-right" color="#C8C8C8" size="24"></u-icon>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="field">
|
||||||
|
<view class="field-label"><text class="star">*</text>联系人</view>
|
||||||
|
<view class="field-input">
|
||||||
|
<input type="text" v-model="contact_name" placeholder="请输入联系人姓名" />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="field">
|
||||||
|
<view class="field-label"><text class="star">*</text>手机号</view>
|
||||||
|
<view class="field-input">
|
||||||
|
<input type="number" v-model="contact_phone" placeholder="请输入联系方式" maxlength="11" />
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="row">
|
|
||||||
<view class="row_label">所在省<text class="red">*</text></view>
|
<!-- 店内环境 -->
|
||||||
<view class="row_con" @click="chooseCity">
|
<view class="form-card">
|
||||||
<input type="text" disabled v-model="confirmProv.ad_name" placeholder="请选择所在省">
|
<view class="upload-section">
|
||||||
<u-icon name="arrow-right" color="#999999" size="28"></u-icon>
|
<view class="upload-title">
|
||||||
|
<text class="star">*</text>店内环境<text class="count">({{ imgList3.length }}/3张)</text>
|
||||||
|
</view>
|
||||||
|
<u-upload :fileList="imgList3" @afterRead="afterReadImg2" @delete="deletePic2" name="2" :maxCount="3" multiple>
|
||||||
|
<view class="upload-add">
|
||||||
|
<view class="upload-add-icon">+</view>
|
||||||
|
<text>{{ imgList3.length }}/3</text>
|
||||||
|
</view>
|
||||||
|
</u-upload>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="row">
|
|
||||||
<view class="row_label">所在市<text class="red">*</text></view>
|
<!-- 门头环境 -->
|
||||||
<view class="row_con" @click="chooseCity2">
|
<view class="form-card">
|
||||||
<input type="text" disabled v-model="confirmCity.short_name" placeholder="请选择所在市">
|
<view class="upload-section">
|
||||||
<u-icon name="arrow-right" color="#999999" size="28"></u-icon>
|
<view class="upload-title">
|
||||||
|
<text class="star">*</text>门头环境<text class="count">({{ imgList.length }}/3张)</text>
|
||||||
|
</view>
|
||||||
|
<u-upload :fileList="imgList" @afterRead="afterReadImg" @delete="deletePic" name="1" :maxCount="3" multiple>
|
||||||
|
<view class="upload-add">
|
||||||
|
<view class="upload-add-icon">+</view>
|
||||||
|
<text>{{ imgList.length }}/3</text>
|
||||||
|
</view>
|
||||||
|
</u-upload>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="row">
|
|
||||||
<view class="row_label">所在区<text class="red">*</text></view>
|
<!-- 红色提示框 -->
|
||||||
<view class="row_con" @click="chooseCity3">
|
<view class="tip-box">
|
||||||
<input type="text" disabled v-model="confirmBusiness.short_name" placeholder="请选择所在区">
|
<view class="tip-icon">!</view>
|
||||||
<u-icon name="arrow-right" color="#999999" size="28"></u-icon>
|
<view class="tip-content">
|
||||||
</view>
|
<view class="tip-title">门店信息要求</view>
|
||||||
</view>
|
<view class="tip-item">· 门店名称需与门店招牌上的名称一致</view>
|
||||||
<view class="row">
|
<view class="tip-item">· 门店品类需与门店主要经营范围的分类一致</view>
|
||||||
<view class="row_label">详细地址<text class="red">*</text></view>
|
<view class="tip-item">· 门店地址需与门店实际经营地址一致</view>
|
||||||
<view class="row_con">
|
|
||||||
<input type="text" v-model="address" placeholder="请输入详细地址">
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="row">
|
|
||||||
<view class="row_label">联系人<text class="red">*</text></view>
|
|
||||||
<view class="row_con">
|
|
||||||
<input type="text" v-model="contact_name" placeholder="请输入联系人">
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="row">
|
|
||||||
<view class="row_label">手机号<text class="red">*</text></view>
|
|
||||||
<view class="row_con">
|
|
||||||
<input type="text" v-model="contact_phone" placeholder="请输入联系方式">
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="row">
|
|
||||||
<view class="row_label">商家分类<text class="red">*</text></view>
|
|
||||||
<view class="row_con" @click="chooseClassify">
|
|
||||||
<input type="text" disabled v-model="confirmClassify.cate_name" placeholder="请选择商家分类">
|
|
||||||
<u-icon name="arrow-right" color="#999999" size="28"></u-icon>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="row">
|
|
||||||
<view class="row_label">银行卡号</view>
|
|
||||||
<view class="row_con nonebor">
|
|
||||||
<input type="text" v-model="bank_card" placeholder="请输入银行卡号">
|
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<view class="Msg mt">
|
<!-- Tab 2: 资质信息 -->
|
||||||
<view class="row2">
|
<view v-show="currentTab === 2">
|
||||||
<view class="row_label">门脸照</view>
|
<view class="Msg">
|
||||||
<view class="row_con2">
|
<view class="row" v-if="enterType === 'enterprise'">
|
||||||
<u-upload :fileList="imgList" @afterRead="afterReadImg" @delete="deletePic" name="1" multiple
|
<view class="row_label">统一社会信用代码<text class="red">*</text></view>
|
||||||
:maxCount="10">
|
<view class="row_con">
|
||||||
<view class="imgCon">
|
<input type="text" v-model="credit_code" placeholder="请输入统一社会信用代码">
|
||||||
<image src="https://static.hshuishang.com/property-img-file/com_imageImg.png"
|
</view>
|
||||||
mode="widthFix"></image>
|
</view>
|
||||||
上传图片
|
<view class="row" v-if="enterType === 'enterprise'">
|
||||||
</view>
|
<view class="row_label">法人姓名<text class="red">*</text></view>
|
||||||
</u-upload>
|
<view class="row_con">
|
||||||
|
<input type="text" v-model="legal_person" placeholder="请输入法人姓名">
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="row" v-if="enterType === 'enterprise'">
|
||||||
|
<view class="row_label">法人身份证号<text class="red">*</text></view>
|
||||||
|
<view class="row_con nonebor">
|
||||||
|
<input type="text" v-model="legal_id_card" placeholder="请输入法人身份证号">
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
<view class="Msg mt">
|
||||||
<view class="row2 mt2">
|
<view class="row2">
|
||||||
<view class="row_label">店内环境</view>
|
<view class="row_label">营业执照<text class="red">*</text></view>
|
||||||
<view class="row_con2">
|
<view class="row_con2">
|
||||||
<u-upload :fileList="imgList3" @afterRead="afterReadImg2" @delete="deletePic2" name="1" multiple
|
<u-upload :fileList="imgList5" @afterRead="afterReadImg3" @delete="deletePic3" name="1" :maxCount="1">
|
||||||
:maxCount="10">
|
<view class="imgCon">
|
||||||
<view class="imgCon">
|
<image src="https://static.hshuishang.com/property-img-file/com_imageImg.png" mode="widthFix"></image>
|
||||||
<image src="https://static.hshuishang.com/property-img-file/com_imageImg.png"
|
上传图片
|
||||||
mode="widthFix"></image>
|
</view>
|
||||||
上传图片
|
</u-upload>
|
||||||
</view>
|
<view class="example-link" @click="showExample('license')">查看示例</view>
|
||||||
</u-upload>
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="row2 mt2">
|
||||||
|
<view class="row_label">{{ enterType === 'enterprise' ? '法人身份证正面' : '身份证正面' }}<text class="red">*</text></view>
|
||||||
|
<view class="row_con2">
|
||||||
|
<u-upload :fileList="idCardFrontList" @afterRead="afterReadIdFront" @delete="deleteIdFront" name="1" :maxCount="1">
|
||||||
|
<view class="imgCon">
|
||||||
|
<image src="https://static.hshuishang.com/property-img-file/com_imageImg.png" mode="widthFix"></image>
|
||||||
|
上传图片
|
||||||
|
</view>
|
||||||
|
</u-upload>
|
||||||
|
<view class="example-link" @click="showExample('idcard')">查看示例</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="row2 mt2">
|
||||||
|
<view class="row_label">{{ enterType === 'enterprise' ? '法人身份证反面' : '身份证反面' }}<text class="red">*</text></view>
|
||||||
|
<view class="row_con2">
|
||||||
|
<u-upload :fileList="idCardBackList" @afterRead="afterReadIdBack" @delete="deleteIdBack" name="1" :maxCount="1">
|
||||||
|
<view class="imgCon">
|
||||||
|
<image src="https://static.hshuishang.com/property-img-file/com_imageImg.png" mode="widthFix"></image>
|
||||||
|
上传图片
|
||||||
|
</view>
|
||||||
|
</u-upload>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
<view class="btn-group">
|
||||||
|
<view class="prevBtn" @click="currentTab = 1">上一步</view>
|
||||||
|
<view class="nextBtn" @click="nextTab(3)">下一步</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
<view class="row2 mt2">
|
<!-- Tab 3: 结算信息 -->
|
||||||
<view class="row_label">营业执照<text class="red">*</text></view>
|
<view v-show="currentTab === 3">
|
||||||
<view class="row_con2">
|
<view class="Msg">
|
||||||
<u-upload :fileList="imgList5" @afterRead="afterReadImg3" @delete="deletePic3" name="1" multiple
|
<template v-if="enterType === 'personal'">
|
||||||
:maxCount="1">
|
<view class="row">
|
||||||
<view class="imgCon">
|
<view class="row_label">开户人姓名</view>
|
||||||
<image src="https://static.hshuishang.com/property-img-file/com_imageImg.png"
|
<view class="row_con">
|
||||||
mode="widthFix"></image>
|
<input type="text" v-model="account_name" placeholder="请输入开户人姓名">
|
||||||
上传图片
|
|
||||||
</view>
|
</view>
|
||||||
</u-upload>
|
</view>
|
||||||
|
<view class="row">
|
||||||
|
<view class="row_label">银行卡号</view>
|
||||||
|
<view class="row_con">
|
||||||
|
<input type="text" v-model="bank_card" placeholder="请输入银行卡号">
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="row">
|
||||||
|
<view class="row_label">开户银行</view>
|
||||||
|
<view class="row_con">
|
||||||
|
<input type="text" v-model="bank_name" placeholder="请输入开户银行">
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="row">
|
||||||
|
<view class="row_label">开户支行</view>
|
||||||
|
<view class="row_con nonebor">
|
||||||
|
<input type="text" v-model="bank_branch" placeholder="请输入开户支行">
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<view class="row">
|
||||||
|
<view class="row_label">企业开户名称</view>
|
||||||
|
<view class="row_con">
|
||||||
|
<input type="text" v-model="account_name" placeholder="请输入企业开户名称">
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="row">
|
||||||
|
<view class="row_label">对公银行账号</view>
|
||||||
|
<view class="row_con">
|
||||||
|
<input type="text" v-model="bank_card" placeholder="请输入对公银行账号">
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="row">
|
||||||
|
<view class="row_label">开户银行</view>
|
||||||
|
<view class="row_con">
|
||||||
|
<input type="text" v-model="bank_name" placeholder="请输入开户银行">
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="row">
|
||||||
|
<view class="row_label">开户支行</view>
|
||||||
|
<view class="row_con nonebor">
|
||||||
|
<input type="text" v-model="bank_branch" placeholder="请输入开户支行">
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
</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="btn-group">
|
||||||
|
<view class="prevBtn" @click="currentTab = 2">上一步</view>
|
||||||
|
<view class="nextBtn" @click="submit">提交入驻</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 所在地区弹层(多列联动) -->
|
||||||
|
<view class="popup-mask" v-if="showRegion" @click.self="showRegion = false">
|
||||||
|
<view class="popup-sheet">
|
||||||
|
<view class="popup-header">
|
||||||
|
<text class="pop-cancel" @click="showRegion = false">取消</text>
|
||||||
|
<text class="pop-title">所在地区</text>
|
||||||
|
<text class="pop-confirm" @click="confirmRegion">确定</text>
|
||||||
|
</view>
|
||||||
|
<view class="popup-body" style="height: 50vh;">
|
||||||
|
<scroll-view class="popup-col" scroll-y>
|
||||||
|
<view v-for="item in pro" :key="item.ad_code"
|
||||||
|
class="popup-col-item" :class="{ selected: tempProv.ad_code === item.ad_code }"
|
||||||
|
@click="tapProv(item)">
|
||||||
|
<text>{{ item.ad_name }}</text>
|
||||||
|
<text class="check" v-if="tempProv.ad_code === item.ad_code">✓</text>
|
||||||
|
</view>
|
||||||
|
</scroll-view>
|
||||||
|
<scroll-view class="popup-col" scroll-y>
|
||||||
|
<view v-for="item in city" :key="item.ad_code"
|
||||||
|
class="popup-col-item" :class="{ selected: tempCity.ad_code === item.ad_code }"
|
||||||
|
@click="tapCity(item)">
|
||||||
|
<text>{{ item.short_name }}</text>
|
||||||
|
<text class="check" v-if="tempCity.ad_code === item.ad_code">✓</text>
|
||||||
|
</view>
|
||||||
|
</scroll-view>
|
||||||
|
<scroll-view class="popup-col" scroll-y>
|
||||||
|
<view v-for="item in buss" :key="item.ad_code"
|
||||||
|
class="popup-col-item" :class="{ selected: tempBuss.ad_code === item.ad_code }"
|
||||||
|
@click="tapBuss(item)">
|
||||||
|
<text>{{ item.short_name }}</text>
|
||||||
|
<text class="check" v-if="tempBuss.ad_code === item.ad_code">✓</text>
|
||||||
|
</view>
|
||||||
|
</scroll-view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<view class="addBtn" @click="submit">立即入驻</view>
|
<!-- 类目选择弹层(多选示意 + 搜索框) -->
|
||||||
|
<view class="popup-mask" v-if="showClassifyPop" @click.self="showClassifyPop = false">
|
||||||
|
<view class="popup-sheet">
|
||||||
|
<view class="popup-header">
|
||||||
|
<text class="pop-cancel" @click="showClassifyPop = false">取消</text>
|
||||||
|
<text class="pop-title">选择类目</text>
|
||||||
|
<text class="pop-confirm" @click="confirmClassifyPop">确定</text>
|
||||||
|
</view>
|
||||||
|
<view class="popup-search">
|
||||||
|
<u-icon name="search" color="#B7B7B7" size="28"></u-icon>
|
||||||
|
<text>搜索类目</text>
|
||||||
|
</view>
|
||||||
|
<scroll-view class="popup-list" scroll-y style="max-height: 50vh;">
|
||||||
|
<view v-for="item in classify" :key="item.id"
|
||||||
|
class="popup-list-item" :class="{ selected: tempClassify.id === item.id }"
|
||||||
|
@click="tempClassify = item">
|
||||||
|
{{ item.cate_name }}
|
||||||
|
</view>
|
||||||
|
</scroll-view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 营业状态弹层 -->
|
||||||
|
<view class="popup-mask" v-if="showBizStatus" @click.self="showBizStatus = false">
|
||||||
|
<view class="popup-sheet">
|
||||||
|
<view class="popup-header">
|
||||||
|
<text class="pop-cancel" @click="showBizStatus = false">取消</text>
|
||||||
|
<text class="pop-title">营业状态</text>
|
||||||
|
<text class="pop-confirm" @click="showBizStatus = false">确定</text>
|
||||||
|
</view>
|
||||||
|
<view class="popup-list">
|
||||||
|
<view v-for="opt in bizStatusList" :key="opt.value"
|
||||||
|
class="popup-list-item" :class="{ selected: bizStatus === opt.value }"
|
||||||
|
@click="selectBizStatus(opt)">
|
||||||
|
{{ opt.label }}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 底部固定按钮:仅 Tab1 显示,其余 tab 沿用各自原按钮(暂未改造) -->
|
||||||
|
<view class="bottom-bar" v-if="currentTab === 1">
|
||||||
|
<view class="btn-primary" @click="nextTab(2)">下一步</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
<u-picker :show="show" :columns="[pro]" keyName="ad_name" @confirm="clickPro" @cancel="cancelPro"></u-picker>
|
|
||||||
<u-picker :show="show2" :columns="[city]" keyName="short_name" @confirm="clickCity"
|
|
||||||
@cancel="cancelCity"></u-picker>
|
|
||||||
<u-picker :show="show3" :columns="[buss]" keyName="short_name" @confirm="clickBuss"
|
|
||||||
@cancel="cancelBuss"></u-picker>
|
|
||||||
<u-picker :show="show4" :columns="[classify]" keyName="cate_name" @confirm="clickClassify"
|
|
||||||
@cancel="cancelClassify"></u-picker>
|
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -130,10 +353,13 @@ import {
|
|||||||
upload,
|
upload,
|
||||||
NavgateTo
|
NavgateTo
|
||||||
} from '../../../utils';
|
} from '../../../utils';
|
||||||
|
import { signPrivateView } from '../../../utils/uploadOSS.js';
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
picUrl,
|
picUrl,
|
||||||
|
currentTab: 1,
|
||||||
|
enterType: 'personal',
|
||||||
area: "",
|
area: "",
|
||||||
confirmCity: "",
|
confirmCity: "",
|
||||||
confirmArea: "",
|
confirmArea: "",
|
||||||
@ -146,12 +372,26 @@ export default {
|
|||||||
imgList5: [],
|
imgList5: [],
|
||||||
imgList6: [],
|
imgList6: [],
|
||||||
|
|
||||||
|
// 身份证照片
|
||||||
|
idCardFrontList: [],
|
||||||
|
idCardFrontPath: [],
|
||||||
|
idCardBackList: [],
|
||||||
|
idCardBackPath: [],
|
||||||
|
|
||||||
contact_name: "",
|
contact_name: "",
|
||||||
contact_phone: "",
|
contact_phone: "",
|
||||||
bank_card: "",
|
bank_card: "",
|
||||||
|
bank_name: "",
|
||||||
|
bank_branch: "",
|
||||||
|
account_name: "",
|
||||||
store_name: "",
|
store_name: "",
|
||||||
address: "",
|
address: "",
|
||||||
|
|
||||||
|
// 企业入驻额外字段
|
||||||
|
credit_code: "",
|
||||||
|
legal_person: "",
|
||||||
|
legal_id_card: "",
|
||||||
|
|
||||||
confirmProv: "",
|
confirmProv: "",
|
||||||
confirmCity: "",
|
confirmCity: "",
|
||||||
confirmBusiness: "",
|
confirmBusiness: "",
|
||||||
@ -166,9 +406,208 @@ export default {
|
|||||||
show4: false,
|
show4: false,
|
||||||
|
|
||||||
itemObj: {},
|
itemObj: {},
|
||||||
|
agreeProtocol: false,
|
||||||
|
|
||||||
|
// 新版弹层相关
|
||||||
|
showRegion: false,
|
||||||
|
showClassifyPop: false,
|
||||||
|
showBizStatus: false,
|
||||||
|
tempProv: {},
|
||||||
|
tempCity: {},
|
||||||
|
tempBuss: {},
|
||||||
|
tempClassify: {},
|
||||||
|
bizStatus: 0, // 1 营业中 2 即将开业 3 休息中
|
||||||
|
bizStatusList: [
|
||||||
|
{ value: 1, label: '营业中' },
|
||||||
|
{ value: 2, label: '即将开业' },
|
||||||
|
{ value: 3, label: '休息中' },
|
||||||
|
],
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
computed: {
|
||||||
|
regionLabel() {
|
||||||
|
const a = this.confirmProv && this.confirmProv.ad_name
|
||||||
|
const b = this.confirmCity && this.confirmCity.short_name
|
||||||
|
const c = this.confirmBusiness && this.confirmBusiness.short_name
|
||||||
|
if (!a) return ''
|
||||||
|
return [a, b, c].filter(Boolean).join('/')
|
||||||
|
},
|
||||||
|
bizStatusLabel() {
|
||||||
|
const opt = this.bizStatusList.find(o => o.value === this.bizStatus)
|
||||||
|
return opt ? opt.label : ''
|
||||||
|
},
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
// ===== 新版弹层交互 =====
|
||||||
|
async openRegion() {
|
||||||
|
if (!this.pro || !this.pro.length) await this.getPro()
|
||||||
|
this.tempProv = this.confirmProv && this.confirmProv.ad_code ? this.confirmProv : {}
|
||||||
|
this.tempCity = this.confirmCity && this.confirmCity.ad_code ? this.confirmCity : {}
|
||||||
|
this.tempBuss = this.confirmBusiness && this.confirmBusiness.ad_code ? this.confirmBusiness : {}
|
||||||
|
if (this.tempProv.ad_code) await this.getCity(this.tempProv.ad_code)
|
||||||
|
if (this.tempCity.ad_code) await this.getBuss(this.tempCity.ad_code)
|
||||||
|
this.showRegion = true
|
||||||
|
},
|
||||||
|
async tapProv(item) {
|
||||||
|
this.tempProv = item
|
||||||
|
this.tempCity = {}
|
||||||
|
this.tempBuss = {}
|
||||||
|
this.city = []
|
||||||
|
this.buss = []
|
||||||
|
await this.getCity(item.ad_code)
|
||||||
|
},
|
||||||
|
async tapCity(item) {
|
||||||
|
this.tempCity = item
|
||||||
|
this.tempBuss = {}
|
||||||
|
this.buss = []
|
||||||
|
await this.getBuss(item.ad_code)
|
||||||
|
},
|
||||||
|
tapBuss(item) {
|
||||||
|
this.tempBuss = item
|
||||||
|
},
|
||||||
|
confirmRegion() {
|
||||||
|
if (!this.tempProv.ad_code) {
|
||||||
|
uni.showToast({ title: '请选择省', icon: 'none' }); return
|
||||||
|
}
|
||||||
|
if (!this.tempCity.ad_code) {
|
||||||
|
uni.showToast({ title: '请选择市', icon: 'none' }); return
|
||||||
|
}
|
||||||
|
if (!this.tempBuss.ad_code) {
|
||||||
|
uni.showToast({ title: '请选择区', icon: 'none' }); return
|
||||||
|
}
|
||||||
|
this.confirmProv = this.tempProv
|
||||||
|
this.confirmCity = this.tempCity
|
||||||
|
this.confirmBusiness = this.tempBuss
|
||||||
|
this.showRegion = false
|
||||||
|
},
|
||||||
|
async openClassify() {
|
||||||
|
if (!this.classify || !this.classify.length) await this.getClassify()
|
||||||
|
this.tempClassify = this.confirmClassify && this.confirmClassify.id ? this.confirmClassify : {}
|
||||||
|
this.showClassifyPop = true
|
||||||
|
},
|
||||||
|
confirmClassifyPop() {
|
||||||
|
if (!this.tempClassify.id) {
|
||||||
|
uni.showToast({ title: '请选择类目', icon: 'none' }); return
|
||||||
|
}
|
||||||
|
this.confirmClassify = this.tempClassify
|
||||||
|
this.showClassifyPop = false
|
||||||
|
},
|
||||||
|
selectBizStatus(opt) {
|
||||||
|
this.bizStatus = opt.value
|
||||||
|
this.showBizStatus = false
|
||||||
|
},
|
||||||
|
|
||||||
|
switchTab(tab) {
|
||||||
|
// 点击 Tab 切换时需要校验前面的 Tab
|
||||||
|
if (tab > this.currentTab) {
|
||||||
|
if (this.currentTab === 1 && !this.validateTab1()) return;
|
||||||
|
if (tab === 3 && !this.validateTab2()) return;
|
||||||
|
}
|
||||||
|
this.currentTab = tab;
|
||||||
|
uni.pageScrollTo({ scrollTop: 0, duration: 200 });
|
||||||
|
},
|
||||||
|
nextTab(tab) {
|
||||||
|
if (tab === 2) {
|
||||||
|
if (!this.validateTab1()) return;
|
||||||
|
}
|
||||||
|
if (tab === 3) {
|
||||||
|
if (!this.validateTab2()) return;
|
||||||
|
}
|
||||||
|
this.currentTab = tab;
|
||||||
|
uni.pageScrollTo({ scrollTop: 0, duration: 200 });
|
||||||
|
},
|
||||||
|
validateTab1() {
|
||||||
|
// 基本信息校验
|
||||||
|
if (!this.store_name) { uni.showToast({ title: '请输入门店名称', icon: 'none' }); return false; }
|
||||||
|
if (!this.confirmProv.ad_code) { uni.showToast({ title: '请选择所在省', icon: 'none' }); return false; }
|
||||||
|
if (!this.confirmCity.ad_code) { uni.showToast({ title: '请选择所在市', icon: 'none' }); return false; }
|
||||||
|
if (!this.confirmBusiness.ad_code) { uni.showToast({ title: '请选择所在区', icon: 'none' }); return false; }
|
||||||
|
if (!this.address) { uni.showToast({ title: '请输入详细地址', icon: 'none' }); return false; }
|
||||||
|
if (!this.contact_name) { uni.showToast({ title: '请输入联系人姓名', icon: 'none' }); return false; }
|
||||||
|
if (!this.contact_phone) { uni.showToast({ title: '请输入联系人手机号', icon: 'none' }); return false; }
|
||||||
|
if (!isPhone(this.contact_phone)) { uni.showToast({ title: '联系人手机号格式不正确', icon: 'none' }); return false; }
|
||||||
|
if (!this.confirmClassify.id) { uni.showToast({ title: '请选择商家分类', icon: 'none' }); return false; }
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
validateTab2() {
|
||||||
|
// 资质信息校验
|
||||||
|
if (this.enterType === 'enterprise') {
|
||||||
|
if (!this.credit_code) { uni.showToast({ title: '请输入统一社会信用代码', icon: 'none' }); return false; }
|
||||||
|
if (!/^[0-9A-HJ-NPQRTUWXY]{18}$/.test(this.credit_code.toUpperCase())) {
|
||||||
|
uni.showToast({ title: '统一社会信用代码格式不正确(18位)', icon: 'none' });
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!this.legal_person) { uni.showToast({ title: '请输入法人姓名', icon: 'none' }); return false; }
|
||||||
|
if (!this.legal_id_card) { uni.showToast({ title: '请输入法人身份证号', icon: 'none' }); return false; }
|
||||||
|
if (!/(^\d{15}$)|(^\d{17}([0-9X])$)/.test(this.legal_id_card.toUpperCase())) {
|
||||||
|
uni.showToast({ title: '法人身份证号格式不正确', icon: 'none' });
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!this.imgList6.length) { uni.showToast({ title: '请上传营业执照', icon: 'none' }); return false; }
|
||||||
|
if (!this.idCardFrontPath.length) { uni.showToast({ title: '请上传身份证正面照片', icon: 'none' }); return false; }
|
||||||
|
if (!this.idCardBackPath.length) { uni.showToast({ title: '请上传身份证反面照片', icon: 'none' }); return false; }
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
validateTab3() {
|
||||||
|
// 结算信息校验(个人 / 企业都需要银行四要素)
|
||||||
|
if (!this.account_name) {
|
||||||
|
uni.showToast({
|
||||||
|
title: this.enterType === 'enterprise' ? '请输入企业开户名称' : '请输入开户人姓名',
|
||||||
|
icon: 'none'
|
||||||
|
});
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!this.bank_card) {
|
||||||
|
uni.showToast({
|
||||||
|
title: this.enterType === 'enterprise' ? '请输入对公银行账号' : '请输入银行卡号',
|
||||||
|
icon: 'none'
|
||||||
|
});
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!/^\d{15,20}$/.test(this.bank_card)) {
|
||||||
|
uni.showToast({ title: '银行账号格式不正确(15-20位数字)', icon: 'none' });
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!this.bank_name) { uni.showToast({ title: '请输入开户银行', icon: 'none' }); return false; }
|
||||||
|
if (!this.bank_branch) { uni.showToast({ title: '请输入开户支行', icon: 'none' }); return false; }
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
showExample(type) {
|
||||||
|
// 跳转到资质示例页
|
||||||
|
NavgateTo('/packages/shopEnter/example/index?type=' + type);
|
||||||
|
},
|
||||||
|
|
||||||
|
// 身份证正面上传(私密 bucket,不能直链回显)
|
||||||
|
afterReadIdFront(e) {
|
||||||
|
const files = Array.isArray(e.file) ? e.file : [e.file]
|
||||||
|
files.forEach(item => {
|
||||||
|
upload(item.url, res => {
|
||||||
|
// 私密文件:上传 UI 用本地预览,path 单独保存供提交
|
||||||
|
this.idCardFrontList.push({ url: item.url })
|
||||||
|
this.idCardFrontPath.push(res.data.path)
|
||||||
|
}, 'merchant_private')
|
||||||
|
})
|
||||||
|
},
|
||||||
|
deleteIdFront(e) {
|
||||||
|
this.idCardFrontList.splice(e.index, 1);
|
||||||
|
this.idCardFrontPath.splice(e.index, 1);
|
||||||
|
},
|
||||||
|
// 身份证反面上传(私密 bucket)
|
||||||
|
afterReadIdBack(e) {
|
||||||
|
const files = Array.isArray(e.file) ? e.file : [e.file]
|
||||||
|
files.forEach(item => {
|
||||||
|
upload(item.url, res => {
|
||||||
|
this.idCardBackList.push({ url: item.url })
|
||||||
|
this.idCardBackPath.push(res.data.path)
|
||||||
|
}, 'merchant_private')
|
||||||
|
})
|
||||||
|
},
|
||||||
|
deleteIdBack(e) {
|
||||||
|
this.idCardBackList.splice(e.index, 1);
|
||||||
|
this.idCardBackPath.splice(e.index, 1);
|
||||||
|
},
|
||||||
|
|
||||||
// 根据ad_code解析省市区信息
|
// 根据ad_code解析省市区信息
|
||||||
parseAdCode(adCode) {
|
parseAdCode(adCode) {
|
||||||
if (!adCode) return;
|
if (!adCode) return;
|
||||||
@ -207,7 +646,6 @@ export default {
|
|||||||
this.show3 = false;
|
this.show3 = false;
|
||||||
},
|
},
|
||||||
clickBuss(e) {
|
clickBuss(e) {
|
||||||
console.log(e);
|
|
||||||
this.show3 = false;
|
this.show3 = false;
|
||||||
this.confirmBusiness = e.value[0]
|
this.confirmBusiness = e.value[0]
|
||||||
},
|
},
|
||||||
@ -270,11 +708,13 @@ export default {
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
afterReadImg3(e) {
|
afterReadImg3(e) {
|
||||||
e.file.forEach(item => {
|
// 营业执照(私密 bucket)
|
||||||
|
const files = Array.isArray(e.file) ? e.file : [e.file]
|
||||||
|
files.forEach(item => {
|
||||||
upload(item.url, res => {
|
upload(item.url, res => {
|
||||||
this.imgList5.push({ url: this.picUrl + res.data.path })
|
this.imgList5.push({ url: item.url })
|
||||||
this.imgList6.push(res.data.path)
|
this.imgList6.push(res.data.path)
|
||||||
})
|
}, 'merchant_private')
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
deletePic2(e) {
|
deletePic2(e) {
|
||||||
@ -285,101 +725,102 @@ export default {
|
|||||||
this.imgList5.splice(e.index, 1);
|
this.imgList5.splice(e.index, 1);
|
||||||
this.imgList6.splice(e.index, 1);
|
this.imgList6.splice(e.index, 1);
|
||||||
},
|
},
|
||||||
|
viewProtocol() {
|
||||||
|
// 查看商家入驻协议
|
||||||
|
uni.showModal({
|
||||||
|
title: '商家入驻协议',
|
||||||
|
content: '本协议是您与平台之间关于商家入驻服务的法律协议。入驻后您需遵守平台规则,按时提供商品或服务,保证信息真实有效。平台有权对违规商家进行处罚。',
|
||||||
|
showCancel: false,
|
||||||
|
confirmText: '我知道了'
|
||||||
|
});
|
||||||
|
},
|
||||||
|
// 给私密 bucket 中的多张图批量签名 URL,写到目标 fileList
|
||||||
|
async signPrivatePaths(paths, listKey) {
|
||||||
|
if (!paths || !paths.length) {
|
||||||
|
this[listKey] = []
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const result = []
|
||||||
|
for (const p of paths) {
|
||||||
|
try {
|
||||||
|
const r = await signPrivateView(p)
|
||||||
|
result.push({ url: r.url })
|
||||||
|
} catch (e) {
|
||||||
|
console.error('签发私密 URL 失败:', p, e)
|
||||||
|
result.push({ url: '' })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this[listKey] = result
|
||||||
|
},
|
||||||
submit() {
|
submit() {
|
||||||
let that = this
|
let that = this
|
||||||
if (!that.store_name) {
|
if (!that.validateTab3()) return;
|
||||||
return uni.showToast({
|
if (!that.agreeProtocol) {
|
||||||
title: '请输入门店名称',
|
uni.showToast({ title: '请先阅读并同意商家入驻协议', icon: 'none' });
|
||||||
duration: 2000
|
return;
|
||||||
});
|
|
||||||
}
|
}
|
||||||
if (!that.confirmProv.ad_code) {
|
|
||||||
return uni.showToast({
|
|
||||||
title: '请选择所在省',
|
|
||||||
duration: 2000
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (!that.confirmCity.ad_code) {
|
|
||||||
return uni.showToast({
|
|
||||||
title: '请选择所在市',
|
|
||||||
duration: 2000
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (!that.confirmBusiness.ad_code) {
|
|
||||||
return uni.showToast({
|
|
||||||
title: '请选择所在区',
|
|
||||||
duration: 2000
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (!that.address) {
|
|
||||||
return uni.showToast({
|
|
||||||
title: '请输入详细地址',
|
|
||||||
duration: 2000
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (!that.contact_name) {
|
|
||||||
return uni.showToast({
|
|
||||||
title: '请输入联系人姓名',
|
|
||||||
duration: 2000
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (!that.contact_phone) {
|
|
||||||
return uni.showToast({
|
|
||||||
title: '请输入联系人手机号',
|
|
||||||
duration: 2000
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (!that.confirmClassify.id) {
|
|
||||||
return uni.showToast({
|
|
||||||
title: '请选择商家分类',
|
|
||||||
duration: 2000
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (!that.imgList6.length) {
|
|
||||||
return uni.showToast({
|
|
||||||
title: '请上传营业执照',
|
|
||||||
duration: 2000
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
let interior_photo = that.imgList4.join(",")
|
let interior_photo = that.imgList4.join(",")
|
||||||
let facade_photo = that.imgList2.join(",")
|
let facade_photo = that.imgList2.join(",")
|
||||||
let license_photo = that.imgList6.join(",")
|
let license_photo = that.imgList6.join(",")
|
||||||
request(apiArr.createStore, "POST", {
|
let id_card_front = that.idCardFrontPath.join(",")
|
||||||
|
let id_card_back = that.idCardBackPath.join(",")
|
||||||
|
|
||||||
|
let params = {
|
||||||
|
enter_type: that.enterType === 'enterprise' ? 2 : 1,
|
||||||
contact_name: that.contact_name,
|
contact_name: that.contact_name,
|
||||||
phone: that.contact_phone,
|
phone: that.contact_phone,
|
||||||
bank_card: that.bank_card,
|
bank_card: that.bank_card,
|
||||||
|
bank_name: that.bank_name,
|
||||||
|
bank_branch: that.bank_branch,
|
||||||
|
account_name: that.account_name,
|
||||||
merchant_name: that.store_name,
|
merchant_name: that.store_name,
|
||||||
address: that.address,
|
address: that.address,
|
||||||
ad_code: that.confirmBusiness.ad_code,
|
ad_code: that.confirmBusiness.ad_code,
|
||||||
facade_photo,
|
facade_photo,
|
||||||
interior_photo,
|
interior_photo,
|
||||||
license_photo,
|
license_photo,
|
||||||
|
id_card_front,
|
||||||
|
id_card_back,
|
||||||
merchant_cate_id: that.confirmClassify.id,
|
merchant_cate_id: that.confirmClassify.id,
|
||||||
}).then(res => {
|
}
|
||||||
that.contact_name = ''
|
|
||||||
that.contact_phone = ''
|
if (that.enterType === 'enterprise') {
|
||||||
that.bank_card = ''
|
params.credit_code = that.credit_code;
|
||||||
that.store_name = ''
|
params.legal_person = that.legal_person;
|
||||||
that.address = ''
|
params.legal_id_card = that.legal_id_card;
|
||||||
that.confirmProv = ''
|
params.account_type = 2;
|
||||||
that.confirmCity = ''
|
} else {
|
||||||
that.confirmBusiness = ''
|
params.account_type = 1;
|
||||||
that.imgList = []
|
}
|
||||||
that.imgList2 = []
|
|
||||||
that.imgList3 = []
|
request(apiArr.createStore, "POST", params).then(res => {
|
||||||
that.imgList4 = []
|
// 提交成功后用最新表单 + 服务端返回拼一个 itemObj 给 auditStatus 页用
|
||||||
that.imgList5 = []
|
const newItem = {
|
||||||
that.imgList6 = []
|
...params,
|
||||||
that.confirmClassify = ''
|
id: res && res.id,
|
||||||
NavgateTo("../sucess/index")
|
status: 1,
|
||||||
}).catch(res => {
|
create_time: new Date().toLocaleString('sv-SE').replace('T', ' '),
|
||||||
if (res.message.includes("agent_nil")) {
|
handle_time: '',
|
||||||
uni.showToast({
|
merchant_code: '',
|
||||||
title: '未找到对应的代理商信息',
|
remark: ''
|
||||||
icon: 'none',
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
NavgateTo("../auditStatus/index?itemObj=" + encodeURIComponent(JSON.stringify(newItem)))
|
||||||
|
}).catch(res => {
|
||||||
|
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
|
||||||
|
})
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -414,9 +855,14 @@ export default {
|
|||||||
|
|
||||||
},
|
},
|
||||||
onLoad(options) {
|
onLoad(options) {
|
||||||
|
// 获取入驻类型
|
||||||
|
if (options.enterType) {
|
||||||
|
this.enterType = options.enterType;
|
||||||
|
}
|
||||||
|
|
||||||
// 先执行数据获取方法
|
// 先执行数据获取方法
|
||||||
Promise.all([this.getPro(), this.getClassify()]).then(() => {
|
Promise.all([this.getPro(), this.getClassify()]).then(() => {
|
||||||
// 数据获取完成后再进行赋值操作
|
// 数据获取完成后再进行赋值操作(编辑回显)
|
||||||
if (options.itemObj) {
|
if (options.itemObj) {
|
||||||
this.itemObj = JSON.parse(options.itemObj)
|
this.itemObj = JSON.parse(options.itemObj)
|
||||||
this.store_name = this.itemObj.merchant_name
|
this.store_name = this.itemObj.merchant_name
|
||||||
@ -425,6 +871,18 @@ export default {
|
|||||||
this.contact_phone = this.itemObj.phone
|
this.contact_phone = this.itemObj.phone
|
||||||
this.confirmClassify = this.classify.find(item => item.id == this.itemObj.merchant_cate_id)
|
this.confirmClassify = this.classify.find(item => item.id == this.itemObj.merchant_cate_id)
|
||||||
this.bank_card = this.itemObj.bank_card
|
this.bank_card = this.itemObj.bank_card
|
||||||
|
this.bank_name = this.itemObj.bank_name || ''
|
||||||
|
this.bank_branch = this.itemObj.bank_branch || ''
|
||||||
|
this.account_name = this.itemObj.account_name || ''
|
||||||
|
this.credit_code = this.itemObj.credit_code || ''
|
||||||
|
this.legal_person = this.itemObj.legal_person || ''
|
||||||
|
this.legal_id_card = this.itemObj.legal_id_card || ''
|
||||||
|
|
||||||
|
// 入驻类型回显
|
||||||
|
if (this.itemObj.enter_type === 2) {
|
||||||
|
this.enterType = 'enterprise';
|
||||||
|
}
|
||||||
|
|
||||||
// 解析ad_code回显省市区
|
// 解析ad_code回显省市区
|
||||||
if (this.itemObj.ad_code) {
|
if (this.itemObj.ad_code) {
|
||||||
this.parseAdCode(this.itemObj.ad_code);
|
this.parseAdCode(this.itemObj.ad_code);
|
||||||
@ -433,8 +891,14 @@ export default {
|
|||||||
this.imgList2 = this.itemObj.facade_photo ? this.itemObj.facade_photo.split(",") : []
|
this.imgList2 = this.itemObj.facade_photo ? this.itemObj.facade_photo.split(",") : []
|
||||||
this.imgList3 = this.itemObj.interior_photo ? this.itemObj.interior_photo.split(",").map(item => ({ url: this.picUrl + item })) : []
|
this.imgList3 = this.itemObj.interior_photo ? this.itemObj.interior_photo.split(",").map(item => ({ url: this.picUrl + item })) : []
|
||||||
this.imgList4 = this.itemObj.interior_photo ? this.itemObj.interior_photo.split(",") : []
|
this.imgList4 = this.itemObj.interior_photo ? this.itemObj.interior_photo.split(",") : []
|
||||||
this.imgList5 = this.itemObj.license_photo?.split(",").map(item => ({ url: this.picUrl + item }))
|
|
||||||
this.imgList6 = this.itemObj.license_photo?.split(",")
|
// 营业执照、身份证 —— 私密 bucket,需要签名 URL 才能回显
|
||||||
|
this.imgList6 = this.itemObj.license_photo?.split(",").filter(Boolean) || []
|
||||||
|
this.idCardFrontPath = this.itemObj.id_card_front ? this.itemObj.id_card_front.split(",").filter(Boolean) : []
|
||||||
|
this.idCardBackPath = this.itemObj.id_card_back ? this.itemObj.id_card_back.split(",").filter(Boolean) : []
|
||||||
|
this.signPrivatePaths(this.imgList6, 'imgList5')
|
||||||
|
this.signPrivatePaths(this.idCardFrontPath, 'idCardFrontList')
|
||||||
|
this.signPrivatePaths(this.idCardBackPath, 'idCardBackList')
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
14
pages.json
14
pages.json
@ -572,6 +572,13 @@
|
|||||||
{
|
{
|
||||||
"root": "packages/shopEnter",
|
"root": "packages/shopEnter",
|
||||||
"pages": [
|
"pages": [
|
||||||
|
{
|
||||||
|
"path": "choose/index",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "商家入驻",
|
||||||
|
"navigationBarBackgroundColor": "#fff"
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"path": "index/index",
|
"path": "index/index",
|
||||||
"style": {
|
"style": {
|
||||||
@ -593,6 +600,13 @@
|
|||||||
"navigationBarTitleText": "审核状态",
|
"navigationBarTitleText": "审核状态",
|
||||||
"navigationBarBackgroundColor": "#fff"
|
"navigationBarBackgroundColor": "#fff"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "example/index",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "资质示例",
|
||||||
|
"navigationBarBackgroundColor": "#fff"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|||||||
@ -203,7 +203,7 @@
|
|||||||
买单返积分
|
买单返积分
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="merchantItem_right_con_right" @click="toJump(item)">
|
<view class="merchantItem_right_con_right" @click.stop="toJump(item)">
|
||||||
<image src="https://static.hshuishang.com/property-img-file/local_review.png" mode="aspectFill">
|
<image src="https://static.hshuishang.com/property-img-file/local_review.png" mode="aspectFill">
|
||||||
</image>
|
</image>
|
||||||
点评
|
点评
|
||||||
@ -665,14 +665,14 @@ export default {
|
|||||||
|
|
||||||
async headershopEnterClick() {
|
async headershopEnterClick() {
|
||||||
if (!uni.getStorageSync('userId')) {
|
if (!uni.getStorageSync('userId')) {
|
||||||
NavgateTo('/packages/shopEnter/index/index', { isLogin: false });
|
NavgateTo('/packages/shopEnter/choose/index', { isLogin: false });
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const res = await request(apiArr2.statusQuery, "POST", {}, { silent: false });
|
const res = await request(apiArr2.statusQuery, "POST", {}, { silent: false });
|
||||||
if (res.status) {
|
if (res.status) {
|
||||||
NavgateTo('/packages/shopEnter/auditStatus/index?itemObj=' + JSON.stringify(res));
|
NavgateTo('/packages/shopEnter/auditStatus/index?itemObj=' + JSON.stringify(res));
|
||||||
} else {
|
} else {
|
||||||
NavgateTo('/packages/shopEnter/index/index');
|
NavgateTo('/packages/shopEnter/choose/index');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@ -3,8 +3,8 @@ const environments = {
|
|||||||
development: {
|
development: {
|
||||||
apiUrl: "https://test.hshuishang.com",
|
apiUrl: "https://test.hshuishang.com",
|
||||||
picUrl: "https://test.hshuishang.com",
|
picUrl: "https://test.hshuishang.com",
|
||||||
aliyunOssUrl: "https://wechat-img-file.oss-cn-beijing.aliyuncs.com",
|
aliyunOssUrl: "https://wechat-img-file-dev.oss-cn-beijing.aliyuncs.com",
|
||||||
staticUrl: "https://static.hshuishang.com",
|
staticUrl: "https://static-dev.hshuishang.com",
|
||||||
},
|
},
|
||||||
production: {
|
production: {
|
||||||
apiUrl: "https://api.hshuishang.com",
|
apiUrl: "https://api.hshuishang.com",
|
||||||
@ -25,7 +25,7 @@ const getCurrentEnvironment = () => {
|
|||||||
if (envVersion === "release") {
|
if (envVersion === "release") {
|
||||||
return "production"; // 正式版
|
return "production"; // 正式版
|
||||||
} else if (envVersion === "trial") {
|
} else if (envVersion === "trial") {
|
||||||
return "production"; // 体验版
|
return "development"; // 体验版
|
||||||
} else if (envVersion === "develop") {
|
} else if (envVersion === "develop") {
|
||||||
return "development"; // 开发版
|
return "development"; // 开发版
|
||||||
}
|
}
|
||||||
@ -54,14 +54,14 @@ const getCurrentEnvironment = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// 获取当前环境配置
|
// 获取当前环境配置
|
||||||
const currentEnv = "production";//getCurrentEnvironment();
|
const currentEnv = getCurrentEnvironment();
|
||||||
const envConfig = environments[currentEnv] || environments.production;
|
const envConfig = environments[currentEnv] || environments.production;
|
||||||
|
|
||||||
export const RequsetUrl = envConfig.apiUrl; // 请求地址前缀
|
export const RequsetUrl = envConfig.apiUrl; // 请求地址前缀
|
||||||
// export const picUrl = envConfig.picUrl; // 图片地址前缀
|
// 公开图片域名:统一走 CDN(dev: static-dev.hshuishang.com / prod: static.hshuishang.com)
|
||||||
export const picUrl = currentEnv==='production'?envConfig.aliyunOssUrl:envConfig.picUrl; // 图片地址前缀
|
export const picUrl = envConfig.staticUrl;
|
||||||
export const aliyunOssUrl = envConfig.aliyunOssUrl; // 阿里云OSS地址
|
export const aliyunOssUrl = envConfig.aliyunOssUrl; // 阿里云OSS直链地址(私密文件签名 URL 已自带 host,一般不需要直接拼)
|
||||||
export const staticUrl = envConfig.staticUrl; // 静态资源地址
|
export const staticUrl = envConfig.staticUrl; // CDN 加速域名
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 处理图片URL,根据环境自动替换
|
* 处理图片URL,根据环境自动替换
|
||||||
@ -326,70 +326,26 @@ export const floatCalculate = (num1, num2, operator) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 图片上传
|
* 图片上传 —— 走 OSS 直传,回调形状对齐旧后端 { code, data: { path } },path 以 / 开头
|
||||||
* @param {string} filename - 图片上传地址
|
* @param {string} filename - 本地文件路径
|
||||||
* @param {Function} fn - 接口回调函数
|
* @param {Function} fn - 回调函数
|
||||||
|
* @param {string} [scene] - 场景,默认 common
|
||||||
*/
|
*/
|
||||||
export const upload = (filename, fn) => {
|
export const upload = (filename, fn, scene = "common") => {
|
||||||
uni.showLoading({
|
// 引入此处避免顶层循环依赖
|
||||||
title: "上传中",
|
const { uploadOSSCompat } = require("./uploadOSS.js");
|
||||||
mask: true,
|
uploadOSSCompat(filename, fn, scene);
|
||||||
});
|
|
||||||
|
|
||||||
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 {string} filename - 本地文件路径
|
||||||
* @param {Function} fn - 接口回调函数
|
* @param {Function} fn - 回调函数
|
||||||
|
* @param {string} [scene] - 场景,默认 video
|
||||||
*/
|
*/
|
||||||
export const uploadVideo = (filename, fn) => {
|
export const uploadVideo = (filename, fn, scene = "video") => {
|
||||||
uni.showLoading({
|
const { uploadOSSCompat } = require("./uploadOSS.js");
|
||||||
title: "上传中",
|
uploadOSSCompat(filename, fn, scene);
|
||||||
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: () => {},
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
150
utils/uploadOSS.js
Normal file
150
utils/uploadOSS.js
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
// 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) => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
uni.request({
|
||||||
|
url: RequsetUrl + "/api/v1/wechat/oss/credential",
|
||||||
|
method: "POST",
|
||||||
|
header: {
|
||||||
|
Authorization: uni.getStorageSync("ctoken") || "",
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
data: { scene, ext },
|
||||||
|
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, 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);
|
||||||
|
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