源文件

This commit is contained in:
gyq
2024-05-23 14:39:33 +08:00
commit a1128dd791
2997 changed files with 500069 additions and 0 deletions

View File

@@ -0,0 +1,195 @@
<!--
复制自 运营平台
差异 1. 删除商户搜索框 2. show函数删除mchNo参数 3.rules删除 mchNo参数
-->
<template>
<a-drawer
v-model:visible="vdata.isShow"
:title=" vdata.isAdd ? '新增门店' : '修改门店' "
width="60%"
:mask-closable="false"
@close="vdata.isShow = false"
>
<a-form ref="infoFormModel" :model="vdata.saveObject" :label-col="{span: 6}" :wrapper-col="{span: 15}" :rules="rules">
<a-row justify="space-between" type="flex">
<a-col :span="12">
<!-- <a-form-item label="商户号:" name="mchNo">-->
<!-- <JeepaySearchInfoInput v-model:value="vdata.saveObject.mchNo" placeholder="商户号" :textUpStyle="false" showType="MCH" :onlyMchName="true" />-->
<!-- </a-form-item>-->
<a-form-item label="选择商户" name="mchApplyId" >
<a-select :disabled="vdata.isAdd?false : true" v-model:value="vdata.saveObject.mchApplyId" placeholder="请选择商户号" show-search @search="handleBankChange" :filter-option="false">
<a-select-option v-for="(d, index) in vdata.filteredAppInfoList" :key="index" v-model:value="d.applyId"> {{ d.mchShortName }} - {{ d.applyId }} - {{ d.ifName }} </a-select-option>
</a-select>
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="门店名称:" name="storeName">
<a-input v-model:value="vdata.saveObject.storeName" />
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="联系人电话" name="contactPhone">
<a-input v-model:value="vdata.saveObject.contactPhone" />
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="门店LOGO" name="storeLogo">
<JeepayUpload v-model:src="vdata.saveObject.storeLogo" bizType="applyment" />
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="门头照" name="storeOuterImg">
<JeepayUpload v-model:src="vdata.saveObject.storeOuterImg" bizType="applyment" />
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="门店内景照" name="storeInnerImg">
<JeepayUpload v-model:src="vdata.saveObject.storeInnerImg" bizType="applyment" />
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="备注:" name="remark">
<a-input v-model:value="vdata.saveObject.remark" />
</a-form-item>
</a-col>
</a-row>
<a-divider />
<!-- 引入地图组件 -->
<JeepayAmap v-if="vdata.isShow" ref="jeepayAmapRef" />
</a-form>
<div class="drawer-btn-center">
<a-button :style="{ marginRight: '8px' }" @click="vdata.isShow = false"><close-outlined /> 取消</a-button>
<a-button type="primary" :loading="vdata.confirmLoading" @click="handleOkFunc"><check-outlined /> 保存</a-button>
</div>
</a-drawer>
</template>
<script lang="ts" setup>
import {req, API_URL_MCH_STORE_LIST, API_URL_MCH_APPLYMENT_LIST} from '@/api/manage'
import { reactive, ref, getCurrentInstance, nextTick } from 'vue'
const { $infoBox, $access } = getCurrentInstance()!.appContext.config.globalProperties
const jeepayAmapRef = ref()
const infoFormModel = ref()
const props = defineProps({
callbackFunc: {type: Function, default: () => {} }
})
const vdata = reactive({
filteredAppInfoList:[] as any,
appList: [] as any, // 应用列表
confirmLoading: false, // 显示确定按钮loading图标
isAdd: true, // 新增 or 修改页面标识
isShow: false, // 是否显示弹层/抽屉
saveObject: {} as any, // 数据对象
recordId: null, // 更新对象ID
})
const rules = {
areaCode: [{ required: true, message: '请选择省市区', trigger: 'blur' }],
storeName: [{ required: true, message: '请输入门店名称', trigger: 'blur' }],
mchApplyId: [{ required: true, message: '请输入商户号', trigger: 'blur' }]
}
function show (recordId) { // 弹层打开事件
if (infoFormModel.value !== undefined) {
infoFormModel.value.resetFields()
}
businessList();
vdata.isAdd = !recordId
// 数据恢复为默认数据
vdata.saveObject = { lng: '', lat: ''}
vdata.confirmLoading = false // 关闭loading
let initMapData : any = {}
if (!vdata.isAdd) { // 修改信息 延迟展示弹层
vdata.recordId = recordId
req.getById(API_URL_MCH_STORE_LIST, recordId).then(res => {
vdata.saveObject = res
vdata.isShow = true
// 门店包含了区域编码
if(res.areaCode && res.areaCode.length){
initMapData.areacode = res.areaCode
initMapData.lnglat = res.lng + ',' + res.lat
initMapData.address = res.address
}
// 显示地图信息
nextTick(() => jeepayAmapRef.value.init(initMapData))
})
} else {
vdata.isShow = true // 立马展示弹层信息
// 显示地图信息
nextTick(() => jeepayAmapRef.value.init(initMapData))
}
}
async function businessList(){
let res = await req.list(API_URL_MCH_APPLYMENT_LIST, {pageNumber:1,pageSize:-1,state:99});
console.log(res.records,'vdata.AppList')
vdata.filteredAppInfoList = res.records
vdata.appList = res.records
}
// 设置地图标点
function handleOkFunc () { // 点击【确认】按钮事件
let mapData = jeepayAmapRef.value.getMapData()
if(!mapData || mapData.areacode.length == 0 || !mapData.address || !mapData.lnglat){
return $infoBox.message.error('请选择地理位置')
}
if(mapData.lnglat.indexOf(',') < 0){
return $infoBox.message.error('请输入正确的经纬度')
}
infoFormModel.value.validate().then(valid =>{
vdata.confirmLoading = true // 显示loading
vdata.saveObject.lng = mapData.lnglat.split(',')[0]
vdata.saveObject.lat = mapData.lnglat.split(',')[1]
vdata.saveObject.address = mapData.address
vdata.saveObject.areaCode = JSON.stringify(mapData.areacode)
// 请求HTTP
req.addOrUpdate(vdata.isAdd ? null: vdata.recordId, API_URL_MCH_STORE_LIST, vdata.saveObject).then(res => {
vdata.isShow = false
vdata.confirmLoading = false
props.callbackFunc() // 刷新列表
}).catch(valid =>{
vdata.confirmLoading = false
})
})
}
const handleBankChange = (value) => {
console.log(value,'value')
vdata.filteredAppInfoList = [];
vdata.appList.forEach((item,index) => {
if (item.mchShortName.includes(value) || item.applyId.includes(value)) {
vdata.filteredAppInfoList.push(vdata.appList[index]);
}
});
};
defineExpose({show})
</script>

View File

@@ -0,0 +1,220 @@
<template>
<a-drawer
v-model:visible="vdata.isShow"
:title="vdata.isAdd ? '创建蚂蚁店铺' : '修改蚂蚁店铺'"
width="60%"
:mask-closable="false"
@close="vdata.isShow = false"
>
<a-form v-if="!vdata.isAdd" :model="vdata.saveObject" :label-col="{span: 6}" :wrapper-col="{span: 15}">
<a-row justify="space-between" type="flex">
<a-col :span="12">
<a-form-item label="蚂蚁店铺ID:">
<a-span>{{ vdata.saveObject.alipayShopId }}</a-span>
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="蚂蚁店铺状态">
<a-tag v-if="vdata.saveObject.alipayShopStatus=='0'">未创建</a-tag>
<a-tag v-else-if="vdata.saveObject.alipayShopStatus=='99'" color="green">审核通过</a-tag>
<a-tag v-else-if="vdata.saveObject.alipayShopStatus=='-1'" color="red">审核拒绝</a-tag>
<div v-else>
<a-tag color="orange">审核中</a-tag>
<a-button
v-if="$access('ENT_MCH_ALIPAY_SHOP_STATUS')"
type="primary"
:size="'small'"
:loading="vdata.updateLoading"
@click="updateShopStatusFunc(vdata.saveObject.storeId)"
>
<sync-outlined /> 更新状态
</a-button>
</div>
</a-form-item>
</a-col>
</a-row>
</a-form>
<a-divider v-if="!vdata.isAdd" />
<a-form ref="infoFormModel" :model="vdata.saveObject" :label-col="{span: 6}" :wrapper-col="{span: 15}" :rules="rules">
<a-row justify="space-between" type="flex">
<a-col :span="12">
<a-form-item label="门店名称:" name="storeName">
<a-input v-model:value="vdata.saveObject.storeName" />
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="联系人电话" name="contactPhone">
<a-input v-model:value="vdata.saveObject.contactPhone" />
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="门店类目" name="shopCategory">
<JeepayAliMccSelect v-model:value="vdata.saveObject.shopCategory" />
</a-form-item>
</a-col>
<a-col v-if="vdata.isAdd" :span="12">
<a-form-item label="店铺经营类型" name="shopType">
<a-radio-group v-model:value="vdata.saveObject.shopType">
<a-radio value="01">直营</a-radio>
<a-radio value="02">加盟</a-radio>
</a-radio-group>
</a-form-item>
</a-col>
</a-row>
<!-- 引入地图组件 -->
<JeepayAmap v-if="vdata.isShow" ref="jeepayAmapRef" />
</a-form>
<div class="drawer-btn-center">
<a-button :style="{ marginRight: '8px' }" @click="vdata.isShow = false"><close-outlined /> 取消</a-button>
<a-button :style="{ marginRight: '8px' }" type="primary" :loading="vdata.confirmLoading" @click="okFunc"><check-outlined /> 确定</a-button>
<a-button v-if="$access('ENT_MCH_ALIPAY_SHOP_DELETE') && vdata.saveObject.alipayShopStatus != '0'" type="danger" @click="alipayShopCloseFunc"><close-outlined /> 关闭蚂蚁店铺</a-button>
</div>
</a-drawer>
</template>
<script lang="ts" setup>
import { req, reqLoad, API_URL_MCH_STORE_LIST, API_ALIPAY_SHOP }from '@/api/manage'
import { reactive, ref, getCurrentInstance, nextTick } from 'vue'
const { $infoBox, $access } = getCurrentInstance()!.appContext.config.globalProperties
const jeepayAmapRef = ref()
const infoFormModel = ref()
const props = defineProps({
callbackFunc: {type: Function, default: () => {} }
})
const vdata: any = reactive({
isAdd: false, // 是否新增
confirmLoading: false, // 显示确定按钮loading图标
isShow: false, // 是否显示弹层/抽屉
saveObject: {} as any, // 数据对象
recordId: null, // 更新对象ID
})
const rules = {
areaCode: [{ required: true, message: '请选择省市区', trigger: 'blur' }],
storeName: [{ required: true, message: '请输入门店名称', trigger: 'blur' }],
contactPhone: [{ required: true, message: '请输入联系人电话', trigger: 'blur' }],
shopCategory: [{ required: true, message: '请输入门店类目', trigger: 'blur' }],
shopType: [{ required: true, message: '请输入店铺经营类型', trigger: 'blur' }]
}
function show (recordId, isAdd) { // 弹层打开事件
vdata.isAdd = isAdd
if (infoFormModel.value !== undefined) {
infoFormModel.value.resetFields()
}
// 数据恢复为默认数据
vdata.saveObject = { lng: '', lat: ''}
vdata.confirmLoading = false // 关闭loading
vdata.updateLoading = false // 关闭loading
vdata.isShow = true
let initMapData : any = {}
if (!isAdd) {
vdata.recordId = recordId
req.getById(API_ALIPAY_SHOP, recordId).then(res => {
vdata.saveObject = res
console.log(vdata.saveObject)
// 门店包含了区域编码
if(res.areaCode && res.areaCode.length){
initMapData.areacode = res.areaCode
initMapData.lnglat = res.lng + ',' + res.lat
initMapData.address = res.address
}
// 显示地图信息
nextTick(() => jeepayAmapRef.value.init(initMapData))
})
}else {
// 创建蚂蚁店铺,拉取商户门店信息
vdata.recordId = recordId
req.getById(API_URL_MCH_STORE_LIST, recordId).then(res => {
vdata.saveObject = res
// 门店包含了区域编码
if(res.areaCode && res.areaCode.length){
initMapData.areacode = res.areaCode
initMapData.lnglat = res.lng + ',' + res.lat
initMapData.address = res.address
}
// 显示地图信息
nextTick(() => jeepayAmapRef.value.init(initMapData))
})
}
}
// 创建/修改蚂蚁店铺
function okFunc () {
let mapData = jeepayAmapRef.value.getMapData()
if(!mapData || mapData.areacode.length == 0 || !mapData.address || !mapData.lnglat){
return $infoBox.message.error('请选择地理位置')
}
if(mapData.lnglat.indexOf(',') < 0){
return $infoBox.message.error('请输入正确的经纬度')
}
infoFormModel.value.validate().then(valid =>{
vdata.saveObject.lng = mapData.lnglat.split(',')[0]
vdata.saveObject.lat = mapData.lnglat.split(',')[1]
vdata.saveObject.address = mapData.address
vdata.saveObject.areaCode = JSON.stringify(mapData.areacode)
vdata.confirmLoading = true // 显示loading
if (vdata.isAdd) {
reqLoad.add(API_ALIPAY_SHOP + '/' + vdata.recordId, vdata.saveObject).then(res => {
vdata.isShow = false
vdata.confirmLoading = false
props.callbackFunc() // 刷新列表
}).catch(valid =>{
vdata.confirmLoading = false
})
}else {
reqLoad.updateById(API_ALIPAY_SHOP, vdata.recordId, vdata.saveObject).then(res => {
vdata.isShow = false
vdata.confirmLoading = false
props.callbackFunc() // 刷新列表
}).catch(valid =>{
vdata.confirmLoading = false
})
}
})
}
function alipayShopCloseFunc () { // 关闭蚂蚁店铺
$infoBox.confirmDanger('关闭蚂蚁店铺', '确定关闭蚂蚁店铺吗?', () => {
return reqLoad.delById(API_ALIPAY_SHOP, vdata.recordId).then(res => {
$infoBox.message.success('关闭成功')
props.callbackFunc() // 刷新列表
}).catch(err => console.log(err))
},() => {
console.log(1111)
})
}
function updateShopStatusFunc (recordId) { // 【更新蚂蚁店铺状态】
vdata.updateLoading = true
reqLoad.getById(API_ALIPAY_SHOP + '/createResult', recordId, undefined).then(res => {
vdata.updateLoading = false
vdata.saveObject.alipayShopStatus = res.alipayShopStatus
}).catch(err =>{
console.log(err)
})
}
defineExpose({show})
</script>

View File

@@ -0,0 +1,189 @@
<template>
<a-drawer
v-model:visible="vdata.visible"
:title=" true ? '门店详情' : '' "
:body-style="{ paddingBottom: '80px' }"
width="40%"
@close="onClose"
>
<a-divider class="jeepay-m-divider" orientation="left" style="color: #1A66FF;">商户信息</a-divider>
<a-row justify="space-between" type="flex">
<a-col :sm="12">
<a-descriptions>
<a-descriptions-item label="商户全称">
{{ vdata.mchDetail.mchFullName }}
</a-descriptions-item>
</a-descriptions>
</a-col>
<a-col :sm="12">
<a-descriptions>
<a-descriptions-item label="商户简称">
{{ vdata.mchDetail.mchShortName }}
</a-descriptions-item>
</a-descriptions>
</a-col>
<a-col :sm="12">
<a-descriptions>
<a-descriptions-item label="商户类型">
{{ vdata.mchDetail.merchantType == 1?'小微':vdata.mchDetail.merchantType == 2?'个体':vdata.mchDetail.merchantType == 1?'企业':'其他' }}
</a-descriptions-item>
</a-descriptions>
</a-col>
<a-col :sm="12">
<a-descriptions>
<a-descriptions-item label="结算状态">
{{vdata.mchDetail.settlementType??"无"}}
</a-descriptions-item>
</a-descriptions>
</a-col>
<a-col :sm="12">
<a-descriptions>
<a-descriptions-item label="联系人姓名">
{{ vdata.mchDetail.contactName }}
</a-descriptions-item>
</a-descriptions>
</a-col>
<a-col :sm="12">
<a-descriptions>
<a-descriptions-item label="联系人手机号">
{{ vdata.mchDetail.contactPhone }}
</a-descriptions-item>
</a-descriptions>
</a-col>
</a-row>
<a-divider class="jeepay-m-divider" orientation="left" style="color: #1A66FF;">门店信息</a-divider>
<a-row justify="space-between" type="flex">
<a-col :sm="12">
<a-descriptions>
<a-descriptions-item label="门店编号">
{{ vdata.detailData['storeId'] }}
</a-descriptions-item>
</a-descriptions>
</a-col>
<a-col :sm="12">
<a-descriptions>
<a-descriptions-item label="门店名称">
{{ vdata.detailData['storeName'] }}
</a-descriptions-item>
</a-descriptions>
</a-col>
<a-col :sm="12">
<a-descriptions>
<a-descriptions-item label="门店logo">
<a-image v-if="vdata.detailData['storeLogo']" class="img" :src="vdata.detailData['storeLogo']" />
</a-descriptions-item>
</a-descriptions>
</a-col>
<a-col :sm="12">
<a-descriptions>
<a-descriptions-item label="门店内景照">
<a-image v-if="vdata.detailData['storeInnerImg']" class="img" :src="vdata.detailData['storeInnerImg']" />
</a-descriptions-item>
</a-descriptions>
</a-col>
<a-col :sm="12">
<a-descriptions>
<a-descriptions-item label="门头照">
<a-image v-if="vdata.detailData['storeOuterImg']" class="img" :src="vdata.detailData['storeOuterImg']" />
</a-descriptions-item>
</a-descriptions>
</a-col>
<a-col :sm="12">
<a-descriptions>
<a-descriptions-item label="门店地址">
{{ vdata.detailData['address'] }}
</a-descriptions-item>
</a-descriptions>
</a-col>
<!-- <a-col :sm="12">-->
<!-- <a-descriptions>-->
<!-- <a-descriptions-item label="代理商号">-->
<!-- {{ vdata.detailData['agentNo'] }}-->
<!-- </a-descriptions-item>-->
<!-- </a-descriptions>-->
<!-- </a-col>-->
<!-- <a-col :sm="12">-->
<!-- <a-descriptions>-->
<!-- <a-descriptions-item label="用户号">-->
<!-- {{ vdata.detailData['mchNo'] }}-->
<!-- </a-descriptions-item>-->
<!-- </a-descriptions>-->
<!-- </a-col>-->
<a-col :sm="12">
<a-descriptions>
<a-descriptions-item label="联系人手机号">
{{ vdata.detailData['contactPhone'] }}
</a-descriptions-item>
</a-descriptions>
</a-col>
</a-row>
<a-row justify="start" type="flex">
<a-col :sm="24">
<a-form-item label="备注">
<a-input
v-model:value="vdata.detailData['remark']"
type="textarea"
disabled="disabled"
style="height: 50px"
/>
</a-form-item>
</a-col>
</a-row>
</a-drawer>
</template>
<script lang="ts" setup>
import {API_URL_MCH_APPLYMENT_LIST, API_URL_MCH_STORE_LIST, req} from '@/api/manage'
import { reactive } from 'vue'
const vdata:any = reactive({
btnLoading: false,
detailData: {}, // 数据对象
mchDetail:{},// 数据对象
recordId: null, // 更新对象ID
visible: false, // 是否显示弹层/抽屉
isvList: [], // 服务商下拉列表
isvName: '' // 服务商名称
})
function show (recordId) { // 弹层打开事件
vdata.detailData = {} // 数据清空
vdata.recordId = recordId
req.getById(API_URL_MCH_STORE_LIST, recordId).then(res => {
vdata.detailData = res
mchDetail()
})
vdata.visible = true
}
function onClose () {
vdata.visible = false
}
function mchDetail(){
req.getById(API_URL_MCH_APPLYMENT_LIST, vdata.detailData.mchApplyId).then(res => {
if(res.succResParameter){
const succResParameter = JSON.parse(res.succResParameter)
vdata.termNo = succResParameter.termNo
}else{
vdata.termNo = "无"
}
vdata.mchDetail = res
})
}
defineExpose({
show //抛出show函数给父组件
})
</script>
<style>
.img {
width: 50px;
height: 50px;
}
</style>

View File

@@ -0,0 +1,442 @@
<template>
<page-header-wrapper>
<a-card>
<JeepaySearchForm :searchFunc="searchFunc" :resetFunc="resetFunc">
<a-form-item label="" class="table-search-item">
<JeepayDateRangePicker
ref="dateRangePicker"
v-model:value="vdata.searchData['queryDateRange']"
customDateRangeType="date"
/>
</a-form-item>
<jeepay-text-up v-model:value="vdata.searchData['mchApplyName']" :placeholder="'商户名称/商户号'" />
<jeepay-text-up v-model:value="vdata.searchData['storeId']" :placeholder="'门店名称/门店编号'" />
<jeepay-text-up v-model:value="vdata.searchData['ifName']" :placeholder="'支付通道'" />
<jeepay-text-up v-model:value="vdata.searchData['isvNo']" :placeholder="'渠道名称/渠道号'" />
<jeepay-text-up v-model:value="vdata.searchData['bindAppIdName']" :placeholder="'应用名称/应用Id'" />
<jeepay-text-up v-model:value="vdata.searchData['contactPhone']" :placeholder="'联系人电话'" />
</JeepaySearchForm>
<!-- 列表渲染 -->
<JeepayTable
ref="infoTable"
:initData="true"
:reqTableDataFunc="reqTableDataFunc"
:tableColumns="tableColumns"
:searchData="vdata.searchData"
rowKey="storeId"
@btnLoadClose="vdata.btnLoading = false"
>
<template #topBtnSlot>
<div>
<a-button
v-if="$access('ENT_MCH_STORE_ADD')"
type="primary"
class="mg-b-30"
@click="addFunc"
><plus-outlined />新建</a-button
>
</div>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'defaultFlag'">
<a-tag v-if="record.defaultFlag === 1" color="green"></a-tag>
<a-switch
v-else
:checked="record.defaultFlag === 1 ? true : false"
@change="
(defaultFlag) => {
return updateState(record.storeId, defaultFlag);
}
"
/>
</template>
<template v-if="column.key === 'bindAppIdName'">
<a-tooltip class="my-tooltip" overlayClassName="tooltip-box-name">
<template #title>
<span>应用名称{{record.bindAppIdName}}</span><br>
<span>应用ID{{record.bindAppId}}</span>
</template>
<div class="my-tooltip-title-box"> {{record.bindAppIdName}}</div>
</a-tooltip>
</template>
<template v-if="column.key === 'isvNo'">
<a-tooltip overlayClassName="tooltip-box-name">
<template #title>
<span>渠道名称{{record.isvName}}</span><br>
<span>渠道号{{record.isvNo}}</span>
</template>
<div class="my-tooltip-title-box"> {{record.isvName}}</div>
</a-tooltip>
</template>
<template v-if="column.key === 'mchShortName'">
<a-tooltip class="my-tooltip" overlayClassName="tooltip-box-name">
<template #title>
<span>商户名称{{record.mchApplyName}}</span><br>
<span>商户号{{record.mchApplyId}}</span>
</template>
<div class="my-tooltip-title-box">
{{record.mchApplyName}}
</div>
</a-tooltip>
</template>
<template v-if="column.key === 'storeName'">
<a-tooltip class="my-tooltip" overlayClassName="tooltip-box-name">
<template #title>
<span>门店名称{{record.storeName}}</span><br>
</template>
<div class="my-tooltip-title-box">
<a @click="detailFunc(record.storeId)" v-if="$access('ENT_MCH_STORE_VIEW')"><b>{{ record.storeName }}</b></a >
<a v-if="!$access('ENT_MCH_STORE_VIEW')"><b>{{ record.storeName }}</b></a ></div>
</a-tooltip>
</template>
<template v-if="column.key === 'deviceNumber'">
<a href="javascript:void(0)" @click="deviceFunc(record.storeId)">{{ record.deviceNumber ? record.deviceNumber : 0 }}</a>
</template>
<template v-if="column.key === 'remark'">
<span @click="editFunc(record.storeId)" class="two-lines"
><b>{{ record.remark != "" ? record.remark : "--" }}</b>
<EditOutlined @click="editFunc(record.storeId)" />
</span>
</template>
<template v-if="column.key === 'op'">
<!-- 操作列插槽 -->
<JeepayTableColumns>
<a-button v-if="$access('ENT_MCH_STORE_EDIT')" type="link" style="padding-right: 10px; padding-left: 10px" @click="deviceFunc(record.storeId)" >设备管理</a-button >
<a-button v-if="$access('ENT_MCH_STORE_EDIT')" type="link" style="padding-right: 10px; padding-left: 10px;text-align: center" @click="editFunc(record.storeId)" >修改</a-button >
<!-- <a-button
v-if="$access('ENT_MCH_STORE_APP_DIS')"
type="link"
@click="open(record)"
>应用分配</a-button
> -->
<a-button type="link" v-if="$access('ENT_MCH_STORE_HANDOVER_LOG')" @click="workRecordFunc(record)"
>交接班记录</a-button
>
<a-button type="link" v-if="$access('ENT_MCH_STORE_STAFF')" @click="getOperator()">员工管理</a-button>
<a-button
v-if="
$access('ENT_MCH_ALIPAY_SHOP_ADD') &&
record.alipayShopStatus == '0'
"
type="link"
@click="alipayShopCreateFunc(record.storeId)"
>创建蚂蚁店铺</a-button
>
<a-button
v-if="
$access('ENT_MCH_ALIPAY_SHOP_EDIT') &&
record.alipayShopStatus != '0' &&
record.alipayShopId
"
type="link"
@click="alipayShopUpdateFunc(record.storeId)"
>修改蚂蚁店铺</a-button
>
<a-button
v-if="$access('ENT_MCH_STORE_DELETE')"
type="link"
style="color: red"
@click="delFunc(record.storeId)"
>删除</a-button
>
</JeepayTableColumns>
</template>
</template>
</JeepayTable>
</a-card>
<!-- 新增 / 修改 页面组件 -->
<InfoAddOrEdit ref="infoAddOrEdit" :callbackFunc="searchFunc" />
<!-- 蚂蚁店铺 页面组件 -->
<AlipayShop ref="alipayShopRef" :callbackFunc="searchFunc" />
<!-- 详情页面组件 -->
<InfoDetail ref="infoDetail" :callback-func="searchFunc" />
<!-- 应用分配页面-->
<AppBind ref="appBind" :callbackFunc="searchFunc" />
<!-- 交接班记录页面 -->
<WorkRecord ref="workRecord" :callbackFunc="searchFunc" />
</page-header-wrapper>
<a-modal
v-model:visible="vdata.visibleNotes"
title="编辑备注"
:footer="null"
width="50%"
@cancel="handleCancel"
>
<div style="height: 20vh; overflow: auto">
<div
class="code code-layout-item"
style="display: flex; justify-content: center"
>
<a-form-item label="备注" required style="width: 80%">
<a-textarea
v-model:value="vdata.notes.value"
placeholder="请输入备注"
:auto-size="{ minRows: 3, maxRows: 5 }"
/>
</a-form-item>
</div>
<div style="text-align: center; margin-top: 34px">
<a-button
type="primary"
:disabled="vdata.isDisabled"
@click="sendNotes()"
>
确定
</a-button>
</div>
</div>
</a-modal>
</template>
<script lang="ts" setup>
import {
API_URL_MCH_STORE_LIST,
req,
reqLoad,
API_ALIPAY_SHOP,
} from "@/api/manage";
import { useUserStore } from "@/store/modules/user";
import {
onMounted,
ref,
reactive,
getCurrentInstance,
nextTick,
provide,
computed,
} from "vue";
import InfoAddOrEdit from "./AddOrEdit.vue";
import AlipayShop from "./AlipayShop.vue";
import InfoDetail from "./Detail.vue";
import WorkRecord from "./WorkRecord.vue";
import AppBind from "./components/AppBind.vue";
import { useRouter, useRoute } from "vue-router";
// 获取全局函数
const { $infoBox, $access } =
getCurrentInstance()!.appContext.config.globalProperties;
const userStore = useUserStore();
const router = useRouter(); //这是全部路由
// tableColumns 顺序不可随意修改 (关联下方列显示)
const tableColumns = reactive([
{ title: "商户名称", key: "mchShortName", dataIndex: "mchShortName" },
{ title: "门店名称", key: "storeName", dataIndex: "storeName"},
{ title: "门店编号", dataIndex: "storeId"},
{ key: "ifName", title: "支付通道", dataIndex: "ifName" },
{ key: "isvNo", title: "所属渠道", dataIndex: "isvNo" },
// { title: "是否默认", key: "defaultFlag", align: "center" },
{ title: "所属应用",key: "bindAppIdName", dataIndex: "bindAppIdName" },
{ title: "联系电话", dataIndex: "contactPhone" },
{ title: "备注", key: "remark", dataIndex: "remark"},
{ title: "设备总数", key: "deviceNumber", dataIndex: "deviceNumber", align: "center" },
// { title: '蚂蚁店铺状态', key: 'alipayShopStatus', dataIndex: 'alipayShopStatus' },
{ title: "创建时间", dataIndex: "createdAt" },
{ key: "op", title: "操作", fixed: "right", align: "center" },
]);
// 如果用户类型为店长、店员时
if (
userStore.userInfo["userType"] == 11 ||
userStore.userInfo["userType"] == 12
) {
// 删除是否默认的列展示
tableColumns.splice(2, 1);
}
console.log(router, "urltyle");
const infoDetail = ref();
const infoAddOrEdit = ref();
const alipayShopRef = ref();
const infoTable = ref();
const appBind = ref();
const workRecord = ref();
const vdata: any = reactive({
visibleNotes: false,
tableColumns: tableColumns,
searchData: {
mchApplyName: "",
},
btnLoading: false,
notes: {
appid: "",
value: "",
},
});
var mchApplyId = GetQueryString("applyId"); //北京市
if (mchApplyId) {
vdata.searchData.mchApplyName = mchApplyId;
}
// 请求table接口数据
function reqTableDataFunc(params) {
return req.list(API_URL_MCH_STORE_LIST, params);
}
function searchFunc() {
// 点击【查询】按钮点击事件
vdata.btnLoading = true; // 打开查询按钮的loading
infoTable.value.refTable(true);
}
function addFunc() {
// 业务通用【新增】 函数
infoAddOrEdit.value.show();
}
function getOperator() {
router.push({
path: "/users",
});
}
function deviceFunc(storeId){
router.push({
path: "/qrCodes",
query:{storeId:storeId}
});
}
function delFunc(recordId) {
// 业务通用【删除】 函数
$infoBox.confirmDanger(
"确认删除?",
"",
() => {
return req
.delById(API_URL_MCH_STORE_LIST, recordId)
.then((res) => {
$infoBox.message.success("删除成功!");
infoTable.value.refTable(false);
})
.catch((err) => {});
},
() => {
console.log(1111);
}
);
}
function editFunc(recordId) {
// 业务通用【修改】 函数
infoAddOrEdit.value.show(recordId);
}
function alipayShopCreateFunc(recordId) {
// 创建蚂蚁店铺
alipayShopRef.value.show(recordId, true);
}
function alipayShopUpdateFunc(recordId) {
// 更新蚂蚁店铺
alipayShopRef.value.show(recordId, false);
}
function detailFunc(recordId: any) {
// 门店详情页
infoDetail.value.show(recordId);
}
function open(record: any) {
// 门店详情页
appBind.value.open(record);
}
function workRecordFunc(record: any) {
// 相应门店交接班记录
workRecord.value.show(record);
}
function updateState(recordId, state) {
// 【更新状态】
const title = state === 1 ? "确认[默认]该门店?" : "确认[取消默认]该门店?";
const content = "开启默认后则默认使用该门店配置,有且只能有一个默认门店。";
return new Promise<void>((resolve, reject) => {
$infoBox.confirmDanger(
title,
content,
() => {
return reqLoad
.updateById(API_URL_MCH_STORE_LIST, recordId, { defaultFlag: state })
.then((res) => {
searchFunc();
resolve();
})
.catch((err) => reject(err));
},
() => {
reject(new Error());
}
);
});
}
function updateAlipayShopStatusFunc(recordId) {
// 【更新蚂蚁店铺状态】
return new Promise<void>((resolve, reject) => {
reqLoad
.getById(API_ALIPAY_SHOP + "/createResult", recordId, undefined)
.then((res) => {
vdata.btnLoading = false;
searchFunc();
})
.catch((valid) => {
vdata.btnLoading = false;
});
});
}
function GetQueryString(name) {
var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");
var r = window.location.search.substr(1).match(reg);
if (r != null) return decodeURIComponent(r[2]);
return null;
}
const resetFunc = () => {
vdata.searchData = {};
};
function sendNotes() {
req
.add("", {
remark: vdata.notes.value,
applyId: vdata.notes.appid,
})
.then((msg) => {
console.log(msg, "resresres");
$infoBox.message.success("编辑成功");
searchFunc(); // 更新列表
vdata.visibleNotes = false;
});
}
function remarkFunc(data) {
vdata.notes.appid = data.applyId;
vdata.notes.value = data.remark ?? "";
vdata.visibleNotes = true;
}
// 弹层取消
function handleCancel(e) {
vdata.visibleNotes = false;
}
</script>
<style>
.two-lines {
color: #1965ff;
max-width: 150px;
display: block;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
}
.my-tooltip .ant-btn {
width: 600px !important;
background-color: #f0f0f0;
color: #333;
border: 1px solid #ddd;
padding: 5px;
border-radius: 4px;
}
.ant-dropdown-menu-item-only-child{
text-align: center;
}
</style>

View File

@@ -0,0 +1,176 @@
<template>
<a-drawer
v-model:visible="vdata.isShow"
width="75%"
placement="right"
:closable="true"
title="交接班记录"
@close="vdata.isShow = false"
>
<a-form
ref="infoFormModel"
style="padding-bottom:50px"
layout="vertical"
>
<a-divider class="jeepay-m-divider" orientation="left" style="color: #1A66FF;">门店信息</a-divider>
<a-row justify="space-between" type="flex">
<a-col :sm="12">
<a-descriptions>
<a-descriptions-item label="商户编号">
{{ vdata.storeInfo.mchApplyId }}
</a-descriptions-item>
</a-descriptions>
</a-col>
<!-- <a-col :sm="12">-->
<!-- <a-descriptions>-->
<!-- <a-descriptions-item label="服务商编号">-->
<!-- {{ vdata.storeInfo.isvNo }}-->
<!-- </a-descriptions-item>-->
<!-- </a-descriptions>-->
<!-- </a-col>-->
<a-col :sm="12">
<a-descriptions>
<a-descriptions-item label="商户简称">
{{ vdata.storeInfo.mchShortName }}
</a-descriptions-item>
</a-descriptions>
</a-col>
<a-col :sm="12">
<a-descriptions>
<a-descriptions-item label="门店编号">
{{ vdata.storeInfo.storeId }}
</a-descriptions-item>
</a-descriptions>
</a-col>
<a-col :sm="12">
<a-descriptions>
<a-descriptions-item label="门店名称">
{{ vdata.storeInfo.storeName }}
</a-descriptions-item>
</a-descriptions>
</a-col>
</a-row>
<!-- 员工交接班列表 -->
<a-divider class="jeepay-m-divider" orientation="left" style="color: #1A66FF;">员工交接班信息</a-divider>
<div>
<JeepaySearchForm :searchFunc="searchFunc" :resetFunc="resetFunc">
<a-form-item label="" class="table-search-item">
<JeepayDateRangePicker ref="dateRangePicker" v-model:value="vdata.searchData['queryDateRange']" customDateRangeType="date" />
</a-form-item>
<jeepay-text-up v-model:value="vdata.searchData['userNo']" :placeholder="'员工编号'" />
<jeepay-text-up v-model:value="vdata.searchData['realname']" :placeholder="'员工姓名'" />
<a-button @click="getOperator()" type="primary" style="margin-right: 10px;"><search-outlined />员工管理</a-button>
</JeepaySearchForm>
<!-- <div @click="getOperator()" class="getOperator"><a >员工管理</a></div> -->
<div class="list-table">
<JeepayTable
ref="infoTable"
:initData="false"
:reqTableDataFunc="reqTableDataFunc"
:tableColumns="tableColumns"
:searchData="vdata.searchData"
rowKey="id"
scrollX="100%"
>
<template #headerCell="{ column }">
<span v-if="column.tooltipTitle">
{{ column.title }}
<a-tooltip :title="column.tooltipTitle"><info-circle-outlined /></a-tooltip>
</span>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'successAmount'">
<b style="color: #15B86C;">{{ record.successAmount / 100 }}</b>
</template>
<template v-if="column.key === 'successCount'">
<b style="color: #15B86C;">{{ record.successCount }}</b>
</template>
<template v-if="column.key === 'refundAmount'">
<b style="color: #FF6848;">{{ record.refundAmount / 100 }}</b>
</template>
<template v-if="column.key === 'refundCount'">
<b style="color: #FF6848;">{{ record.refundCount }}</b>
</template>
<template v-if="column.key === 'payAmount'">
<b style="color: #15B86C;">{{ (record.successAmount - record.refundAmount) / 100 }}</b>
</template>
</template>
</JeepayTable>
</div>
</div>
</a-form>
</a-drawer>
</template>
<script lang="ts" setup>
import { req, API_URL_MCH_WORK_RECORD_LIST } from '@/api/manage'
import { reactive, ref, nextTick } from 'vue'
import { useRouter, useRoute } from 'vue-router'
const router = useRouter() //这是全部路由
const infoFormModel = ref()
const tableColumns = reactive([
{ key: 'sysUserId', title: '用户ID', dataIndex: 'sysUserId'},
{ key: 'realname', title: '员工姓名', dataIndex: 'realname'},
{ key: 'userNo', title: '员工编号', dataIndex: 'userNo'},
{ key: 'successAmount', title: '成交金额', tooltipTitle: '支付成功的订单金额,包含部分退款及全额退款的订单', dataIndex: 'successAmount'},
{ key: 'successCount', title: '成交笔数', dataIndex: 'successCount'},
{ key: 'refundAmount', title: '退款金额', dataIndex: 'refundAmount'},
{ key: 'refundCount', title: '退款总笔数', tooltipTitle: '实际退款订单笔数,若一笔已成交订单退款多次,则计多次', dataIndex: 'refundCount'},
{ key: 'payAmount', title: '实收金额', tooltipTitle: '实际收款金额(成交金额-退款金额)', dataIndex: 'payAmount'},
{ key: 'workStartTime', title: '上班打卡时间', dataIndex: 'workStartTime'},
{ key: 'loginPageType', title: '登录方式', dataIndex: 'loginPageType'},
{ key: 'workEndTime', title: '下班打卡时间', dataIndex: 'workEndTime'},
{ key: 'logoutPageType', title: '登出方式', dataIndex: 'logoutPageType'}
])
// 当前 table 组件
const infoTable = ref()
const dateRangePicker = ref()
const vdata :any = reactive({
value: 1, // 单选框默认的值
isShow: false, // 是否显示弹层/抽屉
storeInfo: null,
searchData: {queryDateRange: 'today'},
})
defineExpose({ show })
function show(storeInfo) { // 弹层打开事件
vdata.storeInfo = storeInfo
vdata.isShow = true // 立马展示弹层信息
searchFunc()
}
// 表格搜索
function searchFunc () {
nextTick(() => {
infoTable.value.refTable(true)
})
}
function resetFunc(){
dateRangePicker.value.returnSelectModel()
vdata.searchData = {queryDateRange: 'today'}
}
// 请求table接口数据
function reqTableDataFunc (params){
return req.list(API_URL_MCH_WORK_RECORD_LIST, Object.assign({ storeId: vdata.storeInfo.storeId }, params))
}
function getOperator(){
router.push({
path:'/users'
})
}
</script>
<style>
.getOperator{
color: #1965FF !important;
padding-left: 8px !important;
padding-top: 8px !important;
}
</style>

View File

@@ -0,0 +1,104 @@
<template>
<a-drawer
v-model:visible="visible"
title="应用分配"
:body-style="{ paddingBottom: '80px' }"
width="40%"
@close="onClose"
>
<div class="app-title">请选择要绑定的应用</div>
<a-select
v-model:value="appid"
placeholder="请选择要绑定的应用"
size="middle"
style="width: 60%"
:field-names="{ label: 'appName', value: 'appId' }"
:options="list"
/>
<div class="drawer-btn-center">
<a-button :style="{ marginRight: '8px' }" @click="visible = false">
<close-outlined /> 取消
</a-button>
<a-button
type="primary"
:loading="confirmLoading"
@click="confirm('绑定应用成功')"
>
<check-outlined /> 保存
</a-button>
</div>
</a-drawer>
</template>
<script lang="ts" setup>
import { ref, getCurrentInstance } from 'vue'
import { API_URL_MCH_APP, API_URL_MCH_STORE_LIST, req } from '@/api/manage'
const { $infoBox, $access } = getCurrentInstance()!.appContext.config.globalProperties
const props = defineProps({
callbackFunc: { type: Function, default: () => {} },
})
const visible: any = ref(false)
const list: any = ref([])
const appid: any = ref(null)
const confirmLoading: any = ref(false)
const getList = () => {
req.list(API_URL_MCH_APP, {}).then(({ records }: any) => {
records.forEach((v) => {
v.appName = v.appName + ` [${v.appId}]`
})
records.unshift({
appName: '(空)',
appId: '',
})
list.value = records
})
}
const onClose = () => {
visible.value = false
}
const storeInfo: any = ref({})
const open = (store: any) => {
getList()
storeInfo.value = store
appid.value = store.bindAppId
visible.value = true
}
const confirm = (tips) => {
$infoBox.confirmDanger('确认保存应用吗?', '', () => {
confirmLoading.value = true
req
.updateById(API_URL_MCH_STORE_LIST, storeInfo.value.storeId, {
bindAppId: appid.value,
})
.then((res) => {
confirmLoading.value = false
$infoBox.message.success(tips)
props.callbackFunc()
onClose()
})
},() => {
console.log(1111)
})
}
defineExpose({ open })
</script>
<style lang="less" scoped>
.app-title {
margin-bottom: 15px;
}
.reset-app {
padding: 5px 8px;
margin-left: 20px;
border-radius: 5px;
font-size: 12px;
color: #fff;
background-color: tomato;
cursor: pointer;
}
</style>
>