Browse Source

特约商户

devlop
mo-bai 4 years ago
parent
commit
f8913d2623
15 changed files with 820 additions and 27 deletions
  1. 24
      apis/merchantApi.js
  2. 107
      components/qn-select/qn-select.vue
  3. 29
      enums/index.js
  4. 4
      env/index.js
  5. 10
      manifest.json
  6. 16
      pages.json
  7. 300
      pages/merchant-list/index.vue
  8. 298
      pages/merchant-setting/index.vue
  9. 21
      pages/mine/index.vue
  10. BIN
      static/imgs/merchant/apply-auditing-icon.png
  11. BIN
      static/imgs/merchant/apply-finished-icon.png
  12. BIN
      static/imgs/merchant/apply-reject-icon.png
  13. BIN
      static/imgs/merchant/error-icon.png
  14. BIN
      static/imgs/mine/merchant-icon.png
  15. 38
      utils/index.js

24
apis/merchantApi.js

@ -0,0 +1,24 @@
import http from '@/utils/http/index.js'
/**
* 获取特约商户列表
* @param {any} data
* @returns
*/
export function getMerchantList(data) {
return http.get({
url: '/uec/get/supplier/apply/commercial/tenant/list',
data
})
}
/**
* 申请特约商户
* @param {any} data
* @returns
*/
export function applyMerchant(data) {
return http.post({
url: '/uec/submit/supplier/commercial/tenant/apply',
data
})
}

107
components/qn-select/qn-select.vue

@ -1,14 +1,14 @@
<template> <template>
<view>
<view style="width: 100%; height: 100%">
<view class="select-mask" v-show="visible" @click="hideOption"></view> <view class="select-mask" v-show="visible" @click="hideOption"></view>
<view class="select-section" @click="showOption">
<text :class="text ? '' : 'placeholder'">{{ text || placeholder }}</text>
<view class="select-section" :style="contentStyle" @click="showOption">
<text class="text" :class="label ? '' : 'placeholder'" :style="label ? '' : placeholderStyle">{{ label || placeholder }}</text>
<view class="icon"></view> <view class="icon"></view>
<view class="options-area" v-show="visible"> <view class="options-area" v-show="visible">
<slot> <slot>
<view class="option" v-for="item in options" :key="item.value" @click.stop="handleSelect(item)"> <view class="option" v-for="item in options" :key="item.value" @click.stop="handleSelect(item)">
<text>{{ item.label }}</text> <text>{{ item.label }}</text>
<view v-if="value == item.value" class="icon"></view>
<view v-show="isSelected(item.value)" class="icon"></view>
</view> </view>
</slot> </slot>
</view> </view>
@ -26,35 +26,105 @@ export default {
type: String, type: String,
default: '请选择' default: '请选择'
}, },
/**
* 下拉框选项
* @param {Object} item
* @property {String} label - 选项名称
* @property {String} value - 选项值
*/
options: { options: {
type: Array, type: Array,
default: () => [] default: () => []
},
placeholderStyle: {
type: String,
default: ''
},
/**
* 指向select-section的样式
*/
contentStyle: {
type: String,
default: ''
},
/**
* 是否多选
*/
multiple: {
type: Boolean,
default: false
} }
}, },
data() { data() {
return { return {
visible: false, visible: false,
text: ''
label: ''
} }
}, },
created() {
this.handleChange(this.value, this.options)
},
methods: { methods: {
handleSelect(item) { handleSelect(item) {
this.text = item.label
this.$emit('input', item.value)
this.hideOption()
if (this.multiple) {
let value = []
if (!this.value) {
value = []
} else {
value = [...this.value]
}
const index = value.indexOf(item.value)
if (index > -1) {
value.splice(index, 1)
} else {
value.push(item.value)
}
this.$emit('input', value)
} else {
this.hideOption()
this.$emit('input', item.value)
}
}, },
showOption() { showOption() {
this.visible = true this.visible = true
}, },
hideOption() { hideOption() {
console.log('hideOption')
this.visible = false this.visible = false
},
isSelected(value) {
if (this.multiple) {
return this.value.indexOf(value) > -1
} else {
return this.value === value
}
},
/**
* 处理外层val或options改变的情况
*/
handleChange(val, options) {
if (this.multiple) {
let labelList = []
for (let value of val) {
const item = options.find((item) => item.value === value)
if (item) {
labelList.push(item.label)
} else {
labelList.push(' ')
}
}
this.label = labelList.join(' , ')
} else {
let target = options.find((o) => o.value === val)
this.label = target?.label || ''
}
} }
}, },
watch: { watch: {
value(val) { value(val) {
let target = this.options.find((o) => o.value === val)
this.text = target?.label || ''
this.handleChange(val, this.options)
},
options(val) {
this.handleChange(this.value, val)
} }
} }
} }
@ -64,10 +134,12 @@ export default {
.select-section { .select-section {
width: 100%; width: 100%;
height: 100%; height: 100%;
min-height: 64rpx;
// min-height: 64rpx;
position: relative; position: relative;
// fixed
transform: translateX(0); transform: translateX(0);
z-index: 300;
// z-index: 300;
z-index: 90;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
@ -78,11 +150,18 @@ export default {
padding: 12rpx 24rpx; padding: 12rpx 24rpx;
background-color: rgb(245, 245, 245); background-color: rgb(245, 245, 245);
border-radius: 8rpx; border-radius: 8rpx;
.text {
flex: 1 1 auto;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.icon { .icon {
background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADgAAAAgCAYAAABHA7voAAACtklEQVRYhdXYOW8TQRgG4CcxBHIQTA5uCCDRICSoKChB3MefBYmjpYCCDjokEnIQEDRIiPsqPltJjGe8a++G8EpWJPvLeB7P7OzsDGEIZ3AK27GEx/js/8oUzmMWH/EU80M4i3MdxR9wB582s4cDZB+uiwFan7sNXMBIxwc7cRQv8aP27g2WWYHrNEBj2N/qdpq4IbBbNTOij91wMNLAtJi/3TKKQ2Ikf1bevcEyJXA7MjXPG3iD45nCMVsP2cQt+dm1iCcNcY3N45g0chwHBPJXdf3sK7sFbjRTs4yH+NVovfEdC5iTRk5gv3+LnBS48UzNMh5ozbbGug++CWRuJHdhrxjxzUZOCNxEpmYDjo1AiiEnxeo1j999drZsxnFb/MCptKflhnWiE0gx5G6x+m4GckyM3GSmpo37657dDUgxZLP1WlAfclTgmpmaJI40kEC+EreQ1I10j/hlF3r1tI/sxM3Wd6SSxZEHsjaSOeSUuDZe9WirTHYI3HSmZkUPHL2BFENOi4VgsUB7vTIicDOZmhWxWvbcJxcBUgw5I6bVUsE2u2VEbJxnMzWFcRQHsnZNHpNG7hWb9+US7bazHdfEo08qpXCUA8JXvReefa12V0q0uw1XxXYwldI4ygMphtzf+rtasA9XxIY+ldf6wLUb7ydFkAfFruJNj++/jCOZmte4r88H736BFEMeEhv5t10+G8YlcXKQykA4BgMSyEWckD4ZOIwveLfuvWFcFAtWKgPjGBzI2kjmkEfFAdZ7cYp3oVWfSiU4qgFSDDknjvNO42SmrcpwxK9ZZZpiFzLW5/9XiqO6EWzni7gmj0uPZCqrKsZRPZA1ZG66dmYV99RwBlsHkHLI2nDUB6QYspZpuT51Agnkku4b9Pbe8nudHagbSCBfiOfFMfFU8gyPbJ2D5P83fwA+SqvvLFrSmAAAAABJRU5ErkJggg==') background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADgAAAAgCAYAAABHA7voAAACtklEQVRYhdXYOW8TQRgG4CcxBHIQTA5uCCDRICSoKChB3MefBYmjpYCCDjokEnIQEDRIiPsqPltJjGe8a++G8EpWJPvLeB7P7OzsDGEIZ3AK27GEx/js/8oUzmMWH/EU80M4i3MdxR9wB582s4cDZB+uiwFan7sNXMBIxwc7cRQv8aP27g2WWYHrNEBj2N/qdpq4IbBbNTOij91wMNLAtJi/3TKKQ2Ikf1bevcEyJXA7MjXPG3iD45nCMVsP2cQt+dm1iCcNcY3N45g0chwHBPJXdf3sK7sFbjRTs4yH+NVovfEdC5iTRk5gv3+LnBS48UzNMh5ozbbGug++CWRuJHdhrxjxzUZOCNxEpmYDjo1AiiEnxeo1j999drZsxnFb/MCptKflhnWiE0gx5G6x+m4GckyM3GSmpo37657dDUgxZLP1WlAfclTgmpmaJI40kEC+EreQ1I10j/hlF3r1tI/sxM3Wd6SSxZEHsjaSOeSUuDZe9WirTHYI3HSmZkUPHL2BFENOi4VgsUB7vTIicDOZmhWxWvbcJxcBUgw5I6bVUsE2u2VEbJxnMzWFcRQHsnZNHpNG7hWb9+US7bazHdfEo08qpXCUA8JXvReefa12V0q0uw1XxXYwldI4ygMphtzf+rtasA9XxIY+ldf6wLUb7ydFkAfFruJNj++/jCOZmte4r88H736BFEMeEhv5t10+G8YlcXKQykA4BgMSyEWckD4ZOIwveLfuvWFcFAtWKgPjGBzI2kjmkEfFAdZ7cYp3oVWfSiU4qgFSDDknjvNO42SmrcpwxK9ZZZpiFzLW5/9XiqO6EWzni7gmj0uPZCqrKsZRPZA1ZG66dmYV99RwBlsHkHLI2nDUB6QYspZpuT51Agnkku4b9Pbe8nudHagbSCBfiOfFMfFU8gyPbJ2D5P83fwA+SqvvLFrSmAAAAABJRU5ErkJggg==')
no-repeat center center/cover; no-repeat center center/cover;
width: 28rpx; width: 28rpx;
height: 16rpx; height: 16rpx;
margin-left: 16rpx;
} }
} }
.select-mask { .select-mask {
@ -90,7 +169,7 @@ export default {
height: 100vh; height: 100vh;
background-color: transparent; background-color: transparent;
position: fixed; position: fixed;
z-index: 200;
z-index: 80;
top: 0; top: 0;
left: 0; left: 0;
right: 0; right: 0;

29
enums/index.js

@ -211,3 +211,32 @@ export const invoiceStatusMap = {
[invoiceStatusEnum.INVOICE]: '开票', [invoiceStatusEnum.INVOICE]: '开票',
[invoiceStatusEnum.NO_INVOICE]: '不开票' [invoiceStatusEnum.NO_INVOICE]: '不开票'
} }
/**
* 商户类型 0:个人 1:企业
*/
export const mallSupplierTypeEnum = {
PERSONAL: 0,
ENTERPRISE: 1
}
export const mallSupplierTypeMap = {
[mallSupplierTypeEnum.PERSONAL]: '个体工商户',
[mallSupplierTypeEnum.ENTERPRISE]: '企业'
}
/**
* 申请单状态 0 待申请 1 已提交 2 重新提交 3 审核中 4 已驳回 5 待账户验证 6 待签约 7 开通权限中 8 已完成 9 申请单已被撤销
*/
export const applyStatusEnum = {
WAIT_APPLY: '0',
SUBMITTED: '1',
RE_SUBMIT: '2',
AUDITING: '3',
REJECTED: '4',
WAIT_VERIFY: '5',
WAIT_SIGN: '6',
WAIT_OPEN: '7',
FINISHED: '8',
CANCELED: '9'
}

4
env/index.js

@ -1,8 +1,8 @@
/** /**
* @description 唯一环境变量 * @description 唯一环境变量
*/ */
// const env = 'test'
const env = 'test'
// const env = 'dev' // const env = 'dev'
const env = 'production'
// const env = 'production'
export default env export default env

10
manifest.json

@ -3,7 +3,7 @@
"appid" : "__UNI__8C1E198", "appid" : "__UNI__8C1E198",
"description" : "", "description" : "",
"versionName" : "1.0.5", "versionName" : "1.0.5",
"versionCode" : 100,
"versionCode" : 101,
"transformPx" : false, "transformPx" : false,
"networkTimeout" : { "networkTimeout" : {
"request" : 6000 "request" : 6000
@ -26,8 +26,6 @@
"modules" : { "modules" : {
"Maps" : {}, "Maps" : {},
"Geolocation" : {}, "Geolocation" : {},
"FaceID" : {},
"iBeacon" : {},
"Push" : {}, "Push" : {},
"Share" : {}, "Share" : {},
"Payment" : {} "Payment" : {}
@ -41,8 +39,6 @@
"<uses-permission android:name=\"android.permission.ACCESS_FINE_LOCATION\"/>", "<uses-permission android:name=\"android.permission.ACCESS_FINE_LOCATION\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>", "<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>", "<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
"<uses-permission android:name=\"android.permission.BLUETOOTH\"/>",
"<uses-permission android:name=\"android.permission.BLUETOOTH_ADMIN\"/>",
"<uses-permission android:name=\"android.permission.CAMERA\"/>", "<uses-permission android:name=\"android.permission.CAMERA\"/>",
"<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>", "<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
"<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>", "<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
@ -54,9 +50,7 @@
"<uses-permission android:name=\"android.permission.VIBRATE\"/>", "<uses-permission android:name=\"android.permission.VIBRATE\"/>",
"<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>", "<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
"<uses-permission android:name=\"android.permission.WRITE_EXTERNAL_STORAGE\"/>", "<uses-permission android:name=\"android.permission.WRITE_EXTERNAL_STORAGE\"/>",
"<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>",
"<uses-permission android:name=\"android.permission.BLUETOOTH\"/>",
"<uses-permission android:name=\"android.permission.BLUETOOTH_ADMIN\"/>"
"<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
], ],
"abiFilters" : [ "armeabi-v7a", "x86" ] "abiFilters" : [ "armeabi-v7a", "x86" ]
}, },

16
pages.json

@ -372,6 +372,22 @@
"navigationStyle": "custom", "navigationStyle": "custom",
"enablePullDownRefresh": false "enablePullDownRefresh": false
} }
},
{
"path": "pages/merchant-list/index",
"style": {
"navigationBarTitleText": "特约商户列表",
"navigationStyle": "custom",
"enablePullDownRefresh": false
}
},
{
"path": "pages/merchant-setting/index",
"style": {
"navigationBarTitleText": "特约商户设置",
"navigationStyle": "custom",
"enablePullDownRefresh": false
}
} }
], ],
"globalStyle": { "globalStyle": {

300
pages/merchant-list/index.vue

@ -0,0 +1,300 @@
<template>
<view class="content">
<uni-nav-bar left-icon="back" @clickLeft="back" statusBar fixed title="特约商户列表"></uni-nav-bar>
<view class="flex-col group_3" v-for="merchant in merchantList" :key="merchant.enterpriseId">
<view class="flex-col section_1">
<view class="flex-row group_4 justify-between">
<view class="flex-row">
<text class="text_4">广西印刷有限公司</text>
<image v-if="showIcon(merchant.applymentState).img" :src="showIcon(merchant.applymentState).img" class="image_4" />
</view>
<view v-if="showIcon(merchant.applymentState).text" class="button" @click="checkInfo(merchant)">{{ showIcon(merchant.applymentState).text }}</view>
</view>
<view class="flex-col group_5" v-if="infoShowStatus.indexOf(merchant.applymentState) < -1">
<view class="top-section flex-col view_1">
<view class="top-group flex-row">
<view class="left-section"></view>
<text class="text_6">商户信息</text>
</view>
<view class="center-group flex-col view_4">
<view class="flex-row">
<text class="label">商户类型</text>
<text class="value">{{ mallSupplierTypeMap[merchant.mallSupplierType] }}</text>
</view>
<view class="flex-row">
<text class="label">客服电话</text>
<text class="value">{{ merchant.servicePhone }}</text>
</view>
<text class="text_12">商户资料</text>
</view>
<view class="flex-row equal-division">
<image @click="preview(merchant.businessLicenseImg)" :src="merchant.businessLicenseImg" class="equal-division-item image_5" />
<image @click="preview(merchant.legalPersonIdCardFrontImg)" :src="merchant.legalPersonIdCardFrontImg" class="equal-division-item" />
<image @click="preview(merchant.legalPersonIdCardBackImg)" :src="merchant.legalPersonIdCardBackImg" class="equal-division-item" />
</view>
</view>
<view class="top-section flex-col">
<view class="top-group flex-row">
<view class="left-section"></view>
<text class="text_6">结算账户</text>
</view>
<view class="center-group flex-col" v-if="merchant.mallSupplierType == mallSupplierTypeEnum.PERSONAL">
<view class="flex-row">
<text class="label">账户类型</text>
<text class="value">私账</text>
</view>
<view class="flex-row top_16">
<text class="label">账户名</text>
<text class="value">{{ merchant.privateAccounts.accountName }}</text>
</view>
<view class="flex-row top_16">
<text class="label">对私账户</text>
<text class="value">{{ merchant.privateAccounts.accountNumber }}</text>
</view>
<view class="flex-row top_16">
<text class="label">开户行</text>
<text class="value">{{ merchant.privateAccounts.accountBank }}</text>
</view>
</view>
<view class="center-group flex-col" v-if="merchant.mallSupplierType == mallSupplierTypeEnum.ENTERPRISE">
<view class="flex-row">
<text class="label">账户类型</text>
<text class="value">公账</text>
</view>
<view class="flex-row top_16">
<text class="label">账户名</text>
<text class="value">{{ merchant.corporateAccount.accountName }}</text>
</view>
<view class="flex-row top_16">
<text class="label">对私账户</text>
<text class="value">{{ merchant.corporateAccount.accountNumber }}</text>
</view>
<view class="flex-row top_16">
<text class="label">开户行</text>
<text class="value">{{ merchant.corporateAccount.accountBank }}</text>
</view>
</view>
</view>
<view class="top-section flex-col">
<view class="top-group flex-row">
<view class="left-section"></view>
<text class="text_6">法人信息</text>
</view>
<view class="center-group flex-col">
<view class="flex-row">
<text class="label">法人姓名</text>
<text class="value">{{ merchant.legalPersonName }}</text>
</view>
<view class="flex-row top_16">
<text class="label">身份证号码</text>
<text class="value">{{ merchant.legalPersonIdCardNo }}</text>
</view>
<view class="flex-row top_16">
<text class="label">手机号码</text>
<text class="value">{{ merchant.legalPersonMobile }}</text>
</view>
<view class="flex-row top_16">
<text class="label">邮箱</text>
<text class="value">{{ merchant.contactEmail }}</text>
</view>
</view>
</view>
</view>
</view>
</view>
</view>
</template>
<script>
import { go2, back } from '@/utils/hook.js'
import { getMerchantList } from '@/apis/merchantApi.js'
import { applyStatusEnum, mallSupplierTypeMap, mallSupplierTypeEnum } from '@/enums/index.js'
//
const infoShowStatus = [
applyStatusEnum.SUBMITTED,
applyStatusEnum.AUDITING,
applyStatusEnum.WAIT_VERIFY,
applyStatusEnum.WAIT_SIGN,
applyStatusEnum.WAIT_OPEN,
applyStatusEnum.FINISHED
]
export default {
data() {
return {
infoShowStatus: Object.freeze(infoShowStatus),
mallSupplierTypeMap: Object.freeze(mallSupplierTypeMap),
mallSupplierTypeEnum: Object.freeze(mallSupplierTypeEnum),
merchantList: [],
cache: {}
}
},
onShow() {
getMerchantList({ type: 5 }).then((res) => {
if (res) {
this.merchantList = res
}
})
},
methods: {
go2,
back,
preview(url) {
uni.previewImage({
current: url,
urls: [url]
})
},
showIcon(status) {
if (this.cache[status]) {
return this.cache[status]
}
/**
* @property {string} img - 图标 空就不展示
* @property {string} text - 按钮文字 空就不展示
*/
let result = {
img: '',
text: ''
}
let infoMap = [applyStatusEnum.RE_SUBMIT, applyStatusEnum.REJECTED, applyStatusEnum.CANCELED]
if (status === applyStatusEnum.FINISHED) {
result.img = '/static/imgs/merchant/apply-finished-icon.png'
} else if (status === applyStatusEnum.WAIT_APPLY) {
result.text = '去申请'
} else if (infoMap.includes(status)) {
result.img = '/static/imgs/merchant/apply-reject-icon.png'
result.text = '查看'
} else {
result.img = '/static/imgs/merchant/apply-auditing-icon.png'
}
this.cache[status] = result
return result
},
checkInfo(merchant) {
go2('merchant-setting', { info: JSON.stringify(merchant) })
}
}
}
</script>
<style lang="scss" scoped>
.content {
width: 750rpx;
}
.group_3 {
padding-bottom: 32rpx;
flex: 1 1 auto;
overflow-y: auto;
.section_1 {
background-color: rgb(255, 255, 255);
.group_4 {
padding: 23rpx 32rpx 22rpx;
border-bottom: solid 2rpx rgb(221, 221, 221);
.text_4 {
max-width: 370rpx;
color: rgb(0, 0, 0);
font-size: 30rpx;
font-weight: 600;
line-height: 42rpx;
white-space: wrap;
}
.image_4 {
margin-left: 16rpx;
width: 116rpx;
height: 32rpx;
}
.button {
width: 140rpx;
height: 56rpx;
background: #ffffff;
border: 1.2rpx solid rgba(0, 122, 255, 1);
border-radius: 40rpx;
display: flex;
justify-content: center;
align-items: center;
font-size: 28rpx;
color: #007aff;
}
}
.group_5 {
padding: 19rpx 32rpx 36rpx;
.top-section {
margin-top: 20rpx;
padding: 24rpx 24rpx 30rpx;
background-color: rgb(247, 248, 250);
border-radius: 8rpx;
.top-group {
color: rgb(51, 51, 51);
font-size: 28rpx;
font-weight: 500;
line-height: 40rpx;
white-space: nowrap;
.left-section {
align-self: center;
background-color: rgb(173, 186, 201);
border-radius: 50%;
width: 10rpx;
height: 10rpx;
}
.text_6 {
margin-left: 6rpx;
}
}
.center-group {
margin-top: 20rpx;
padding: 0 18rpx;
.text_12 {
margin-top: 16rpx;
color: rgb(136, 136, 136);
font-size: 28rpx;
line-height: 40rpx;
white-space: nowrap;
}
}
.view_4 {
margin-top: 21rpx;
}
.equal-division {
margin-left: 18rpx;
margin-top: 15rpx;
align-self: flex-start;
.equal-division-item {
margin-left: 12rpx;
flex: 1 1 120rpx;
border-radius: 10rpx;
width: 120rpx;
height: 120rpx;
}
.image_5 {
margin-left: 0;
}
}
}
.view_1 {
margin-top: 0;
}
}
}
.top_16 {
margin-top: 16rpx;
}
.label {
color: rgb(136, 136, 136);
font-size: 28rpx;
line-height: 40rpx;
white-space: nowrap;
width: 168rpx;
}
.value {
width: 430rpx;
color: rgb(51, 51, 51);
font-size: 28rpx;
font-weight: 500;
line-height: 40rpx;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
}
</style>

298
pages/merchant-setting/index.vue

@ -0,0 +1,298 @@
<template>
<view class="content">
<uni-nav-bar left-icon="back" @clickLeft="back" statusBar fixed title="特约商户设置"></uni-nav-bar>
<view class="justify-center section_1" v-show="auditDetail">
<image src="/static/imgs/merchant/error-icon.png" class="image_4" />
<text class="text_4">申请被驳回{{ auditDetail }}</text>
</view>
<qn-form-item label="商户信息" type="title"></qn-form-item>
<qn-form-item label="商户名称">
<text>{{ form.name }}</text>
</qn-form-item>
<qn-form-item label="商户类型" required>
<qn-select
contentStyle="background: none; padding: 0;text-align: right;"
:options="types"
v-model="form.mallSupplierType"
placeholder="请选择商户类型"
></qn-select>
</qn-form-item>
<qn-form-item label="客服电话" required>
<qn-easyinput :maxlength="11" v-model="form.servicePhone" :inputBorder="false" text="right" placeholder="请输入客服电话"></qn-easyinput>
</qn-form-item>
<qn-form-item label="联系邮箱" required>
<qn-easyinput :maxlength="25" v-model="form.contactEmail" :inputBorder="false" text="right" placeholder="请输入联系邮箱"></qn-easyinput>
</qn-form-item>
<qn-form-item label="商户资料" size="large">
<view class="flex-row img-area">
<image v-for="(url, index) in imgs" :key="index" class="img" :src="url" @click="preview(url)"></image>
</view>
</qn-form-item>
<qn-form-item label="结算账户" type="title"></qn-form-item>
<qn-form-item label="账户类型">
<text>{{ accountTypeName }}</text>
</qn-form-item>
<qn-form-item label="账户名">
<text>{{ form.accountName }}</text>
</qn-form-item>
<qn-form-item label="账户号码">
<text>{{ form.accountNumber }}</text>
</qn-form-item>
<qn-form-item label="开户行">
<text>{{ form.accountBank }}</text>
</qn-form-item>
<qn-form-item label="法人信息" type="title"></qn-form-item>
<qn-form-item label="法人姓名">
<text>{{ form.contactName }}</text>
</qn-form-item>
<qn-form-item label="法人身份证号">
<text>{{ form.contactIdNumber }}</text>
</qn-form-item>
<qn-form-item label="法人手机号">
<text>{{ form.mobilePhone }}</text>
</qn-form-item>
<qn-footer fixed height="120rpx">
<view class="button-area">
<view class="button button__cancel" @click="back">
<text class="text">取消</text>
</view>
<view class="button button__submit" @click="apply">
<text class="text" style="color: white">提交申请</text>
</view>
</view>
</qn-footer>
</view>
</template>
<script>
import { go2, back } from '@/utils/hook.js'
import { applyMerchant } from '@/apis/merchantApi.js'
import { mallSupplierTypeEnum, applyStatusEnum } from '@/enums/index.js'
import { validateField } from '@/utils/index.js'
const types = [
{
label: '个体工商户',
value: mallSupplierTypeEnum.PERSONAL
},
{
label: '企业',
value: mallSupplierTypeEnum.ENTERPRISE
}
]
const accountFields = [
{
label: '开户银行',
key: 'accountBank'
},
{
label: '开户名称',
key: 'accountName'
},
{
label: '银行账号',
key: 'accountNumber'
},
{
label: '开户银行省市编码',
key: 'bankAddressCode'
},
{
label: '开户银行联行号',
key: 'bankBranchId'
}
]
const validateFields = [
{
name: 'contactEmail',
rules: [{ required: true, message: '请输入联系邮箱' }]
},
{
name: 'servicePhone',
rules: [
{ required: true, message: '请输入客服电话' },
{ type: 'phone', message: '请输入正确的手机号' }
]
}
]
export default {
data() {
return {
types: Object.freeze(types),
accountTypeName: '私账',
privateAccounts: {}, //
corporateAccount: {}, //
imgs: [],
auditDetail: '',
form: {
businessType: 0, // 0 1
enterpriseId: null,
name: 'xxx',
mallSupplierType: null,
accountName: '',
accountNumber: '',
accountBank: '',
bankAddressCode: '',
bankBranchId: '',
servicePhone: '',
contactName: '',
contactIdNumber: '',
mobilePhone: '',
contactEmail: ''
}
}
},
onLoad(option) {
if (!option.info) {
uni.showToast({
title: '参数错误',
icon: 'none',
success: () => {
setTimeout(() => {
back()
}, 1500)
}
})
} else {
let info = JSON.parse(option.info)
this.privateAccounts = info.privateAccounts
this.corporateAccount = info.corporateAccount
this.imgs.push(info.businessLicenseImg, info.legalPersonIdCardFrontImg, info.legalPersonIdCardBackImg)
let keys = Object.keys(this.form)
keys.forEach((key) => {
if (info[key] != undefined) {
this.form[key] = info[key]
}
})
if (info.applymentState === applyStatusEnum.REJECTED) {
if (info.auditDetail) {
let reasons = info.auditDetail.map((item) => item.rejectReason)
this.auditDetail = reasons.join(',')
}
}
}
},
watch: {
'form.mallSupplierType': function (val) {
if (val === mallSupplierTypeEnum.PERSONAL) {
this.accountTypeName = '私账'
this.updateAccount(this.privateAccounts)
} else {
this.accountTypeName = '公账'
this.updateAccount(this.corporateAccount)
}
}
},
methods: {
go2,
back,
preview(url) {
uni.previewImage({
urls: this.imgs,
current: url
})
},
//
updateAccount(account) {
accountFields.forEach((item) => {
this.form[item.key] = account[item.key]
})
},
apply() {
for (let field of validateFields) {
const { name, rules } = field
const value = this.form[name]
const { isValid, msg } = validateField(value, rules)
if (!isValid) {
uni.showToast({
title: msg,
icon: 'none'
})
return false
}
}
applyMerchant(this.form).then((res) => {
if (res) {
uni.showToast({
title: '申请成功',
icon: 'none',
success: () => {
setTimeout(() => {
back()
}, 1500)
}
})
}
})
}
}
}
</script>
<style lang="scss" scoped>
.content {
width: 750rpx;
.img-area {
width: 686rpx;
padding-bottom: 32rpx;
}
.img {
margin-left: 12rpx;
border-radius: 10rpx;
width: 120rpx;
height: 120rpx;
border: 1px solid #f7f8fa;
}
}
.section_1 {
width: 750rpx;
padding: 28rpx 32rpx;
color: rgb(0, 0, 0);
font-size: 32rpx;
font-weight: 500;
line-height: 45rpx;
white-space: pre-wrap;
background-color: rgb(255, 192, 195);
.image_4 {
margin: 4rpx 0;
width: 36rpx;
height: 36rpx;
}
.text_4 {
width: 100%;
margin-left: 12rpx;
}
}
.button-area {
width: 750rpx;
padding: 0 32rpx;
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
.button {
flex-grow: 0;
flex-shrink: 0;
display: flex;
align-items: center;
justify-content: center;
border-radius: 10rpx;
.text {
font-size: 30rpx;
font-weight: 500;
text-align: center;
}
}
.button__cancel {
width: 270rpx;
height: 88rpx;
border: 2rpx solid #979797;
}
.button__submit {
width: 400rpx;
height: 88rpx;
background: #007aff;
}
}
</style>

21
pages/mine/index.vue

@ -133,6 +133,10 @@
<image class="icon" src="/static/imgs/mine/my-receipt-code.png"></image> <image class="icon" src="/static/imgs/mine/my-receipt-code.png"></image>
<text class="label">收款码</text> <text class="label">收款码</text>
</view> </view>
<view class="icon-item" @click="setMerchant">
<image class="icon" src="/static/imgs/mine/merchant-icon.png"></image>
<text class="label">特约商户</text>
</view>
<!-- <view <!-- <view
class="icon-item" class="icon-item"
@click=" @click="
@ -153,7 +157,6 @@
import { go2, loginGo2 } from '@/utils/hook.js' import { go2, loginGo2 } from '@/utils/hook.js'
import { fddEnterpriseStatus } from '@/enums/index.js' import { fddEnterpriseStatus } from '@/enums/index.js'
import { getBaseInfo, getVerifyUrl } from '@/apis/commonApi.js' import { getBaseInfo, getVerifyUrl } from '@/apis/commonApi.js'
import qnDataPicker from '@/components/qn-data-picker/qn-data-picker.vue'
import { dateTimeFormat } from '@/utils/index.js' import { dateTimeFormat } from '@/utils/index.js'
import { getOrderStatistics } from '@/apis/mineApi.js' import { getOrderStatistics } from '@/apis/mineApi.js'
// //
@ -171,7 +174,6 @@ const lastMonth = (() => {
return [dateTimeFormat(beginDate, 'yyyy-mm-dd'), dateTimeFormat(endDate, 'yyyy-mm-dd')] return [dateTimeFormat(beginDate, 'yyyy-mm-dd'), dateTimeFormat(endDate, 'yyyy-mm-dd')]
})() })()
export default { export default {
components: { qnDataPicker },
data() { data() {
return { return {
customerServicer: '17606507108', customerServicer: '17606507108',
@ -284,6 +286,21 @@ export default {
this.tradeData = res this.tradeData = res
} }
}) })
},
setMerchant() {
if (!this.hasCompany) {
uni.showModal({
title: '提示',
content: '您还没有企业信息,请先完善企业信息',
success: (res) => {
if (res.confirm) {
loginGo2('enterprise-info')
}
}
})
return
}
loginGo2('merchant-list')
} }
}, },
watch: { watch: {

BIN
static/imgs/merchant/apply-auditing-icon.png

Before After
Width: 100  |  Height: 32  |  Size: 4.7 KiB

BIN
static/imgs/merchant/apply-finished-icon.png

Before After
Width: 116  |  Height: 32  |  Size: 4.0 KiB

BIN
static/imgs/merchant/apply-reject-icon.png

Before After
Width: 100  |  Height: 32  |  Size: 4.4 KiB

BIN
static/imgs/merchant/error-icon.png

Before After
Width: 72  |  Height: 72  |  Size: 2.5 KiB

BIN
static/imgs/mine/merchant-icon.png

Before After
Width: 68  |  Height: 68  |  Size: 7.8 KiB

38
utils/index.js

@ -1,6 +1,6 @@
import env from '@/env/index.js' import env from '@/env/index.js'
import store from '@/store/index.js' import store from '@/store/index.js'
import { isDate, isString } from './is.js'
import { isDate, isString, isArray } from './is.js'
/** /**
* 日期格式化样例 yyyy-mm-dd hh:MM:ss * 日期格式化样例 yyyy-mm-dd hh:MM:ss
* @param date Date 需要转换的日期 * @param date Date 需要转换的日期
@ -299,3 +299,39 @@ export const round = (num, ratio) => {
} }
return result return result
} }
/**
* 根据规则校验字段
* @param {*} value 输入值
* @param {array} rules 规则集 {type,required,message}
* @value {boolean} required 是否必填
* @value {string} type 字段类型校验目前支持 phone
* @returns {object} {isValid,msg}
*/
export const validateField = (value, rules) => {
let isValid = true
let msg = ''
for (let rule of rules) {
if (rule.required) {
if (value === '' || value === undefined || value === null) {
isValid = false
msg = rule.message
break
}
if (isArray(value) && value.length === 0) {
isValid = false
msg = rule.message
break
}
}
if (rule.type === 'phone' && value !== '' && !/^1[3456789]\d{9}$/.test(value)) {
isValid = false
msg = rule.message
break
}
}
return {
isValid,
msg
}
}
Loading…
Cancel
Save