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参数的值
|
||||
const pathParts = res.path.split('?');
|
||||
if (pathParts.length > 1) {
|
||||
const queryParams = pathParts[1].split('&');
|
||||
for (const param of queryParams) {
|
||||
const [key, value] = param.split('=');
|
||||
if (key === 'scene') {
|
||||
const params = {
|
||||
id: value
|
||||
}
|
||||
uni.setStorageSync('merchantInfo', params);
|
||||
NavgateTo('/packages/localLife/detail/index')
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (pathParts[1].startsWith('scene=')){
|
||||
const pathPart = decodeURIComponent(pathParts[1].substring(6))
|
||||
const queryParams = pathPart.split('&');
|
||||
for (const param of queryParams) {
|
||||
const [key, value] = param.split('=');
|
||||
if (key === 'id') {
|
||||
const params = {
|
||||
id: value
|
||||
}
|
||||
uni.setStorageSync('merchantInfo', params);
|
||||
NavgateTo('/packages/localLife/detail/index')
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@ -68,9 +68,9 @@ export default {
|
||||
},
|
||||
getAvatarUrl(record){
|
||||
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{
|
||||
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 = {
|
||||
clientId: this.selfClientId
|
||||
}
|
||||
console.log('clientId:', options.clientId)
|
||||
|
||||
// 添加连接状态回调
|
||||
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) {
|
||||
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: {
|
||||
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 {
|
||||
background-color: #f6f7fb;
|
||||
min-height: 100vh;
|
||||
padding-bottom: 60rpx;
|
||||
background-color: #F6F7F9;
|
||||
min-height: 100vh;
|
||||
padding-bottom: 200rpx;
|
||||
}
|
||||
|
||||
.container {
|
||||
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;
|
||||
padding-bottom: 40rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.Msg {
|
||||
width: 710rpx;
|
||||
background: #FFFFFF;
|
||||
border-radius: 20rpx 20rpx 20rpx 20rpx;
|
||||
margin: 0 auto;
|
||||
padding: 0 20rpx;
|
||||
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%);
|
||||
}
|
||||
|
||||
.row {
|
||||
padding-top: 30rpx;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
.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;
|
||||
}
|
||||
|
||||
.row_label {
|
||||
font-size: 28rpx;
|
||||
color: #999999;
|
||||
width: 180rpx;
|
||||
.step-pill.active {
|
||||
background: #FFFFFF;
|
||||
color: #FF370B;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.red {
|
||||
color: #FF370B;
|
||||
margin-left: 5rpx;
|
||||
/* ================= Tab 切换 ================= */
|
||||
.tab-bar {
|
||||
display: flex;
|
||||
background: #FFFFFF;
|
||||
padding: 0 60rpx;
|
||||
}
|
||||
|
||||
.row_con {
|
||||
flex: 1;
|
||||
padding-bottom: 30rpx;
|
||||
border-bottom: 1rpx solid #EBEBEB;
|
||||
display: flex;
|
||||
.tab-item {
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
padding: 28rpx 0 22rpx;
|
||||
font-size: 30rpx;
|
||||
color: #222;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.row_con input {
|
||||
flex: 1;
|
||||
.tab-item.active {
|
||||
color: #FF370B;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.nonebor {
|
||||
border-bottom: none;
|
||||
.tab-item.active::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
bottom: 8rpx;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
width: 56rpx;
|
||||
height: 6rpx;
|
||||
background: #FF370B;
|
||||
border-radius: 3rpx;
|
||||
}
|
||||
|
||||
.row2 {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
/* ================= 表单卡片 ================= */
|
||||
.form-card {
|
||||
background: #FFFFFF;
|
||||
margin: 20rpx 24rpx 0;
|
||||
padding: 24rpx;
|
||||
border-radius: 16rpx;
|
||||
}
|
||||
|
||||
.mt {
|
||||
margin-top: 26rpx;
|
||||
padding-top: 36rpx;
|
||||
padding-bottom: 36rpx;
|
||||
.field {
|
||||
margin-top: 20rpx;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.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;
|
||||
.field:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.imgCon image {
|
||||
width: 34rpx;
|
||||
height: 34rpx;
|
||||
margin-bottom: 8rpx;
|
||||
.field-label {
|
||||
font-size: 26rpx;
|
||||
color: #222;
|
||||
margin-bottom: 14rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.mt2 {
|
||||
margin-top: 30rpx;
|
||||
.field-label .star {
|
||||
color: #FF370B;
|
||||
margin-right: 4rpx;
|
||||
font-size: 26rpx;
|
||||
}
|
||||
|
||||
.u-upload__wrap__preview {
|
||||
width: 120rpx;
|
||||
height: 120rpx;
|
||||
border-radius: 10rpx 0rpx 10rpx 10rpx !important;
|
||||
.field-input {
|
||||
height: 80rpx;
|
||||
border: 1rpx solid #EBEBEB;
|
||||
border-radius: 8rpx;
|
||||
padding: 0 20rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background: #FFFFFF;
|
||||
}
|
||||
|
||||
.u-upload__wrap__preview__image {
|
||||
width: 100% !important;
|
||||
height: 100% !important;
|
||||
object-fit: cover;
|
||||
.field-input input {
|
||||
flex: 1;
|
||||
font-size: 28rpx;
|
||||
color: #222;
|
||||
height: 80rpx;
|
||||
line-height: 80rpx;
|
||||
}
|
||||
|
||||
.addBtn {
|
||||
font-size: 36rpx;
|
||||
color: #FFFFFF;
|
||||
width: 600rpx;
|
||||
height: 90rpx;
|
||||
background: linear-gradient(91deg, #FF7658 0%, #FF370B 100%);
|
||||
border-radius: 100rpx 100rpx 100rpx 100rpx;
|
||||
margin: 0 auto;
|
||||
margin-top: 58rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.field-input input::placeholder,
|
||||
.field-input .placeholder {
|
||||
color: #B7B7B7;
|
||||
}
|
||||
|
||||
.field-input.disabled {
|
||||
background: #FAFAFA;
|
||||
}
|
||||
|
||||
.field-value {
|
||||
flex: 1;
|
||||
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>
|
||||
<view class="container">
|
||||
<view class="Msg">
|
||||
<view class="row">
|
||||
<view class="row_label">门店名称<text class="red">*</text></view>
|
||||
<view class="row_con">
|
||||
<input type="text" v-model="store_name" placeholder="需与门牌照名称一致">
|
||||
<!-- 顶部进度条(红底胶囊三段) -->
|
||||
<view class="step-bar">
|
||||
<view class="step-pill" :class="{ active: currentTab >= 1 }">填写信息</view>
|
||||
<view class="step-pill" :class="{ active: currentTab >= 4 }">提交审核</view>
|
||||
<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 class="row">
|
||||
<view class="row_label">所在省<text class="red">*</text></view>
|
||||
<view class="row_con" @click="chooseCity">
|
||||
<input type="text" disabled v-model="confirmProv.ad_name" placeholder="请选择所在省">
|
||||
<u-icon name="arrow-right" color="#999999" size="28"></u-icon>
|
||||
|
||||
<!-- 店内环境 -->
|
||||
<view class="form-card">
|
||||
<view class="upload-section">
|
||||
<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 class="row">
|
||||
<view class="row_label">所在市<text class="red">*</text></view>
|
||||
<view class="row_con" @click="chooseCity2">
|
||||
<input type="text" disabled v-model="confirmCity.short_name" placeholder="请选择所在市">
|
||||
<u-icon name="arrow-right" color="#999999" size="28"></u-icon>
|
||||
|
||||
<!-- 门头环境 -->
|
||||
<view class="form-card">
|
||||
<view class="upload-section">
|
||||
<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 class="row">
|
||||
<view class="row_label">所在区<text class="red">*</text></view>
|
||||
<view class="row_con" @click="chooseCity3">
|
||||
<input type="text" disabled v-model="confirmBusiness.short_name" placeholder="请选择所在区">
|
||||
<u-icon name="arrow-right" color="#999999" size="28"></u-icon>
|
||||
</view>
|
||||
</view>
|
||||
<view class="row">
|
||||
<view class="row_label">详细地址<text class="red">*</text></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 class="tip-box">
|
||||
<view class="tip-icon">!</view>
|
||||
<view class="tip-content">
|
||||
<view class="tip-title">门店信息要求</view>
|
||||
<view class="tip-item">· 门店名称需与门店招牌上的名称一致</view>
|
||||
<view class="tip-item">· 门店品类需与门店主要经营范围的分类一致</view>
|
||||
<view class="tip-item">· 门店地址需与门店实际经营地址一致</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="Msg mt">
|
||||
<view class="row2">
|
||||
<view class="row_label">门脸照</view>
|
||||
<view class="row_con2">
|
||||
<u-upload :fileList="imgList" @afterRead="afterReadImg" @delete="deletePic" name="1" multiple
|
||||
:maxCount="10">
|
||||
<view class="imgCon">
|
||||
<image src="https://static.hshuishang.com/property-img-file/com_imageImg.png"
|
||||
mode="widthFix"></image>
|
||||
上传图片
|
||||
</view>
|
||||
</u-upload>
|
||||
<!-- Tab 2: 资质信息 -->
|
||||
<view v-show="currentTab === 2">
|
||||
<view class="Msg">
|
||||
<view class="row" v-if="enterType === 'enterprise'">
|
||||
<view class="row_label">统一社会信用代码<text class="red">*</text></view>
|
||||
<view class="row_con">
|
||||
<input type="text" v-model="credit_code" placeholder="请输入统一社会信用代码">
|
||||
</view>
|
||||
</view>
|
||||
<view class="row" v-if="enterType === 'enterprise'">
|
||||
<view class="row_label">法人姓名<text class="red">*</text></view>
|
||||
<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 class="row2 mt2">
|
||||
<view class="row_label">店内环境</view>
|
||||
<view class="row_con2">
|
||||
<u-upload :fileList="imgList3" @afterRead="afterReadImg2" @delete="deletePic2" name="1" multiple
|
||||
:maxCount="10">
|
||||
<view class="imgCon">
|
||||
<image src="https://static.hshuishang.com/property-img-file/com_imageImg.png"
|
||||
mode="widthFix"></image>
|
||||
上传图片
|
||||
</view>
|
||||
</u-upload>
|
||||
<view class="Msg mt">
|
||||
<view class="row2">
|
||||
<view class="row_label">营业执照<text class="red">*</text></view>
|
||||
<view class="row_con2">
|
||||
<u-upload :fileList="imgList5" @afterRead="afterReadImg3" @delete="deletePic3" 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('license')">查看示例</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="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 class="btn-group">
|
||||
<view class="prevBtn" @click="currentTab = 1">上一步</view>
|
||||
<view class="nextBtn" @click="nextTab(3)">下一步</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="row2 mt2">
|
||||
<view class="row_label">营业执照<text class="red">*</text></view>
|
||||
<view class="row_con2">
|
||||
<u-upload :fileList="imgList5" @afterRead="afterReadImg3" @delete="deletePic3" name="1" multiple
|
||||
:maxCount="1">
|
||||
<view class="imgCon">
|
||||
<image src="https://static.hshuishang.com/property-img-file/com_imageImg.png"
|
||||
mode="widthFix"></image>
|
||||
上传图片
|
||||
<!-- Tab 3: 结算信息 -->
|
||||
<view v-show="currentTab === 3">
|
||||
<view class="Msg">
|
||||
<template v-if="enterType === 'personal'">
|
||||
<view class="row">
|
||||
<view class="row_label">开户人姓名</view>
|
||||
<view class="row_con">
|
||||
<input type="text" v-model="account_name" placeholder="请输入开户人姓名">
|
||||
</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 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>
|
||||
</template>
|
||||
|
||||
@ -130,10 +353,13 @@ import {
|
||||
upload,
|
||||
NavgateTo
|
||||
} from '../../../utils';
|
||||
import { signPrivateView } from '../../../utils/uploadOSS.js';
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
picUrl,
|
||||
currentTab: 1,
|
||||
enterType: 'personal',
|
||||
area: "",
|
||||
confirmCity: "",
|
||||
confirmArea: "",
|
||||
@ -146,12 +372,26 @@ export default {
|
||||
imgList5: [],
|
||||
imgList6: [],
|
||||
|
||||
// 身份证照片
|
||||
idCardFrontList: [],
|
||||
idCardFrontPath: [],
|
||||
idCardBackList: [],
|
||||
idCardBackPath: [],
|
||||
|
||||
contact_name: "",
|
||||
contact_phone: "",
|
||||
bank_card: "",
|
||||
bank_name: "",
|
||||
bank_branch: "",
|
||||
account_name: "",
|
||||
store_name: "",
|
||||
address: "",
|
||||
|
||||
// 企业入驻额外字段
|
||||
credit_code: "",
|
||||
legal_person: "",
|
||||
legal_id_card: "",
|
||||
|
||||
confirmProv: "",
|
||||
confirmCity: "",
|
||||
confirmBusiness: "",
|
||||
@ -166,9 +406,208 @@ export default {
|
||||
show4: false,
|
||||
|
||||
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: {
|
||||
// ===== 新版弹层交互 =====
|
||||
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解析省市区信息
|
||||
parseAdCode(adCode) {
|
||||
if (!adCode) return;
|
||||
@ -207,7 +646,6 @@ export default {
|
||||
this.show3 = false;
|
||||
},
|
||||
clickBuss(e) {
|
||||
console.log(e);
|
||||
this.show3 = false;
|
||||
this.confirmBusiness = e.value[0]
|
||||
},
|
||||
@ -270,11 +708,13 @@ export default {
|
||||
})
|
||||
},
|
||||
afterReadImg3(e) {
|
||||
e.file.forEach(item => {
|
||||
// 营业执照(私密 bucket)
|
||||
const files = Array.isArray(e.file) ? e.file : [e.file]
|
||||
files.forEach(item => {
|
||||
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)
|
||||
})
|
||||
}, 'merchant_private')
|
||||
})
|
||||
},
|
||||
deletePic2(e) {
|
||||
@ -285,101 +725,102 @@ export default {
|
||||
this.imgList5.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() {
|
||||
let that = this
|
||||
if (!that.store_name) {
|
||||
return uni.showToast({
|
||||
title: '请输入门店名称',
|
||||
duration: 2000
|
||||
});
|
||||
if (!that.validateTab3()) return;
|
||||
if (!that.agreeProtocol) {
|
||||
uni.showToast({ title: '请先阅读并同意商家入驻协议', icon: 'none' });
|
||||
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 facade_photo = that.imgList2.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,
|
||||
phone: that.contact_phone,
|
||||
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,
|
||||
address: that.address,
|
||||
ad_code: that.confirmBusiness.ad_code,
|
||||
facade_photo,
|
||||
interior_photo,
|
||||
license_photo,
|
||||
id_card_front,
|
||||
id_card_back,
|
||||
merchant_cate_id: that.confirmClassify.id,
|
||||
}).then(res => {
|
||||
that.contact_name = ''
|
||||
that.contact_phone = ''
|
||||
that.bank_card = ''
|
||||
that.store_name = ''
|
||||
that.address = ''
|
||||
that.confirmProv = ''
|
||||
that.confirmCity = ''
|
||||
that.confirmBusiness = ''
|
||||
that.imgList = []
|
||||
that.imgList2 = []
|
||||
that.imgList3 = []
|
||||
that.imgList4 = []
|
||||
that.imgList5 = []
|
||||
that.imgList6 = []
|
||||
that.confirmClassify = ''
|
||||
NavgateTo("../sucess/index")
|
||||
}).catch(res => {
|
||||
if (res.message.includes("agent_nil")) {
|
||||
uni.showToast({
|
||||
title: '未找到对应的代理商信息',
|
||||
icon: 'none',
|
||||
});
|
||||
}
|
||||
|
||||
if (that.enterType === 'enterprise') {
|
||||
params.credit_code = that.credit_code;
|
||||
params.legal_person = that.legal_person;
|
||||
params.legal_id_card = that.legal_id_card;
|
||||
params.account_type = 2;
|
||||
} else {
|
||||
params.account_type = 1;
|
||||
}
|
||||
|
||||
request(apiArr.createStore, "POST", params).then(res => {
|
||||
// 提交成功后用最新表单 + 服务端返回拼一个 itemObj 给 auditStatus 页用
|
||||
const newItem = {
|
||||
...params,
|
||||
id: res && res.id,
|
||||
status: 1,
|
||||
create_time: new Date().toLocaleString('sv-SE').replace('T', ' '),
|
||||
handle_time: '',
|
||||
merchant_code: '',
|
||||
remark: ''
|
||||
}
|
||||
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) {
|
||||
// 获取入驻类型
|
||||
if (options.enterType) {
|
||||
this.enterType = options.enterType;
|
||||
}
|
||||
|
||||
// 先执行数据获取方法
|
||||
Promise.all([this.getPro(), this.getClassify()]).then(() => {
|
||||
// 数据获取完成后再进行赋值操作
|
||||
// 数据获取完成后再进行赋值操作(编辑回显)
|
||||
if (options.itemObj) {
|
||||
this.itemObj = JSON.parse(options.itemObj)
|
||||
this.store_name = this.itemObj.merchant_name
|
||||
@ -425,6 +871,18 @@ export default {
|
||||
this.contact_phone = this.itemObj.phone
|
||||
this.confirmClassify = this.classify.find(item => item.id == this.itemObj.merchant_cate_id)
|
||||
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回显省市区
|
||||
if (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.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.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')
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -443,4 +907,4 @@ export default {
|
||||
|
||||
<style>
|
||||
@import url("./index.css");
|
||||
</style>
|
||||
</style>
|
||||
|
||||
14
pages.json
14
pages.json
@ -572,6 +572,13 @@
|
||||
{
|
||||
"root": "packages/shopEnter",
|
||||
"pages": [
|
||||
{
|
||||
"path": "choose/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "商家入驻",
|
||||
"navigationBarBackgroundColor": "#fff"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "index/index",
|
||||
"style": {
|
||||
@ -593,6 +600,13 @@
|
||||
"navigationBarTitleText": "审核状态",
|
||||
"navigationBarBackgroundColor": "#fff"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "example/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "资质示例",
|
||||
"navigationBarBackgroundColor": "#fff"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
@ -203,7 +203,7 @@
|
||||
买单返积分
|
||||
</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>
|
||||
点评
|
||||
@ -665,14 +665,14 @@ export default {
|
||||
|
||||
async headershopEnterClick() {
|
||||
if (!uni.getStorageSync('userId')) {
|
||||
NavgateTo('/packages/shopEnter/index/index', { isLogin: false });
|
||||
NavgateTo('/packages/shopEnter/choose/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/index/index');
|
||||
NavgateTo('/packages/shopEnter/choose/index');
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@ -3,8 +3,8 @@ const environments = {
|
||||
development: {
|
||||
apiUrl: "https://test.hshuishang.com",
|
||||
picUrl: "https://test.hshuishang.com",
|
||||
aliyunOssUrl: "https://wechat-img-file.oss-cn-beijing.aliyuncs.com",
|
||||
staticUrl: "https://static.hshuishang.com",
|
||||
aliyunOssUrl: "https://wechat-img-file-dev.oss-cn-beijing.aliyuncs.com",
|
||||
staticUrl: "https://static-dev.hshuishang.com",
|
||||
},
|
||||
production: {
|
||||
apiUrl: "https://api.hshuishang.com",
|
||||
@ -25,7 +25,7 @@ const getCurrentEnvironment = () => {
|
||||
if (envVersion === "release") {
|
||||
return "production"; // 正式版
|
||||
} else if (envVersion === "trial") {
|
||||
return "production"; // 体验版
|
||||
return "development"; // 体验版
|
||||
} else if (envVersion === "develop") {
|
||||
return "development"; // 开发版
|
||||
}
|
||||
@ -54,14 +54,14 @@ const getCurrentEnvironment = () => {
|
||||
};
|
||||
|
||||
// 获取当前环境配置
|
||||
const currentEnv = "production";//getCurrentEnvironment();
|
||||
const currentEnv = getCurrentEnvironment();
|
||||
const envConfig = environments[currentEnv] || environments.production;
|
||||
|
||||
export const RequsetUrl = envConfig.apiUrl; // 请求地址前缀
|
||||
// export const picUrl = envConfig.picUrl; // 图片地址前缀
|
||||
export const picUrl = currentEnv==='production'?envConfig.aliyunOssUrl:envConfig.picUrl; // 图片地址前缀
|
||||
export const aliyunOssUrl = envConfig.aliyunOssUrl; // 阿里云OSS地址
|
||||
export const staticUrl = envConfig.staticUrl; // 静态资源地址
|
||||
// 公开图片域名:统一走 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 加速域名
|
||||
|
||||
/**
|
||||
* 处理图片URL,根据环境自动替换
|
||||
@ -326,70 +326,26 @@ export const floatCalculate = (num1, num2, operator) => {
|
||||
};
|
||||
|
||||
/**
|
||||
* 图片上传
|
||||
* @param {string} filename - 图片上传地址
|
||||
* @param {Function} fn - 接口回调函数
|
||||
* 图片上传 —— 走 OSS 直传,回调形状对齐旧后端 { code, data: { path } },path 以 / 开头
|
||||
* @param {string} filename - 本地文件路径
|
||||
* @param {Function} fn - 回调函数
|
||||
* @param {string} [scene] - 场景,默认 common
|
||||
*/
|
||||
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: () => {},
|
||||
});
|
||||
export const upload = (filename, fn, scene = "common") => {
|
||||
// 引入此处避免顶层循环依赖
|
||||
const { uploadOSSCompat } = require("./uploadOSS.js");
|
||||
uploadOSSCompat(filename, fn, scene);
|
||||
};
|
||||
|
||||
/**
|
||||
* 视频上传
|
||||
* @param {string} filename - 图片上传地址
|
||||
* @param {Function} fn - 接口回调函数
|
||||
* 视频上传 —— 走 OSS 直传
|
||||
* @param {string} filename - 本地文件路径
|
||||
* @param {Function} fn - 回调函数
|
||||
* @param {string} [scene] - 场景,默认 video
|
||||
*/
|
||||
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: () => {},
|
||||
});
|
||||
export const uploadVideo = (filename, fn, scene = "video") => {
|
||||
const { uploadOSSCompat } = require("./uploadOSS.js");
|
||||
uploadOSSCompat(filename, fn, scene);
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
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