feat(cashier): 新增码牌配置功能

- 添加 CashierCodeConfig 相关 API 接口
- 实现码牌配置列表、编辑、删除等功能
- 新增码牌类型配置相关功能
- 重构原 ChannelCashierConfig 相关组件,改为 CashierCodeConfig
This commit is contained in:
DaxPay
2024-11-21 13:44:31 +08:00
parent c5701a6747
commit 52f9baba8c
12 changed files with 600 additions and 277 deletions

View File

@@ -0,0 +1,11 @@
<script setup lang="ts">
</script>
<template>
</template>
<style scoped lang="less">
</style>

View File

@@ -0,0 +1,134 @@
import { defHttp } from '@/utils/http/axios'
import { Result } from '#/axios'
import { MchEntity } from '#/web'
/**
* 根据AppId查询码牌列表
*/
export const findAllByAppId = (appId) =>
defHttp.get<Result<CashierCodeConfig[]>>({
url: '/cashier/code/config/findAllByAppId',
params: { appId },
})
/**
* 根据id查询码牌信息
*/
export const findById = (id) =>
defHttp.get<Result<CashierCodeConfig>>({ url: '/cashier/code/config/findById', params: { id } })
/**
* 码牌配置保存
*/
export const save = (param: CashierCodeConfig) =>
defHttp.post({ url: '/cashier/code/config/save', data: param })
/**
* 码牌配置更新
*/
export const update = (param: CashierCodeConfig) =>
defHttp.post({ url: '/cashier/code/config/update', data: param })
/**
* 码牌配置删除
*/
export const remove = (id) => defHttp.post({ url: '/cashier/code/config/delete', params: { id } })
/**
* 获取码牌地址
*/
export const getCashierCodeUrl = (id) =>
defHttp.get<Result<string>>({ url: '/cashier/code/config/getCashierCodeUrl', params: { id } })
/**
* 获取码牌各类型配置列表
*/
export const findTypeByCodeId = (cashierCodeId) =>
defHttp.get<Result<CashierCodeTypeConfig[]>>({
url: '/cashier/code/config/type/findAll',
params: { cashierCodeId },
})
/**
* 获取码牌类型配置详情
*/
export const findTypeById = (id) =>
defHttp.get<Result<CashierCodeTypeConfig>>({ url: '/cashier/code/config/type/findById', params: { id } })
/**
* 码牌类型配置保存
*/
export const saveType = (param: CashierCodeTypeConfig) =>
defHttp.post({ url: '/cashier/code/config/type/save', data: param })
/**
* 码牌类型配置更新
*/
export const updateType = (param: CashierCodeTypeConfig) =>
defHttp.post({ url: '/cashier/code/config/type/update', data: param })
/**
* 码牌类型配置删除
*/
export const deleteType = (id) => defHttp.post({ url: '/cashier/code/config/type/delete', params: { id } })
/**
* 码牌类型是否存在
*/
export const existsByType = (type, cashierCodeId) =>
defHttp.get<Result<boolean>>({
url: '/cashier/code/config/type/exists',
params: { type, cashierCodeId },
})
/**
* 码牌类型是否存在(不包括自身)
*/
export const existsByTypeNotId = (type, cashierCodeId, id) =>
defHttp.get<Result<boolean>>({
url: '/cashier/code/config/type/existsNotId',
params: { type, cashierCodeId, id },
})
/**
* 收银台码牌配置
*/
export interface CashierCodeConfig extends MchEntity {
/** 码牌名称 */
name?: string
/** 码牌code */
code?: string
/** 模板编号 */
templateCode?: string
/** 是否启用 */
enable?: boolean
/** 备注 */
remark?: string
}
/**
* 特定类型码牌配置
*/
export interface CashierCodeTypeConfig extends MchEntity {
/** 码牌ID */
cashierCodeId?: string
/**
* 码牌类型
*/
type?: string
/**
* 支付通道
*/
channel?: string
/**
* 支付方式
*/
payMethod?: string
/** 是否开启分账 */
allocation?: boolean
/** 自动分账 */
autoAllocation?: boolean
/** 备注 */
remark?: string
}

View File

@@ -0,0 +1,165 @@
<template>
<basic-modal
v-bind="$attrs"
:loading="confirmLoading"
:width="modalWidth"
:title="title"
:open="visible"
:mask-closable="showable"
@cancel="handleCancel"
>
<a-form
class="small-from-item"
ref="formRef"
:model="form"
:rules="rules"
:validate-trigger="['blur', 'change']"
:label-col="labelCol"
:wrapper-col="wrapperCol"
>
<a-form-item label="主键" name="id" :hidden="true">
<a-input v-model:value="form.id" :disabled="showable" />
</a-form-item>
<a-form-item label="码牌编码" name="code" v-show="form.code">
<a-input v-model:value="form.code" disabled />
</a-form-item>
<a-form-item label="码牌名称" name="name">
<a-input v-model:value="form.name" :disabled="showable" placeholder="请输入码牌名称" />
</a-form-item>
<a-form-item label="是否启用" name="enable">
<a-switch
checked-children="启用"
un-checked-children="停用"
v-model:checked="form.enable"
:disabled="showable"
/>
</a-form-item>
<a-form-item label="备注" name="remark">
<a-textarea v-model:value="form.remark" :disabled="showable" placeholder="请输入备注" />
</a-form-item>
</a-form>
<template #footer>
<a-space>
<a-button key="cancel" @click="handleCancel">取消</a-button>
<a-button
v-if="!showable"
key="forward"
:loading="confirmLoading"
type="primary"
@click="handleOk"
>保存</a-button
>
</a-space>
</template>
</basic-modal>
</template>
<script lang="ts" setup>
import { nextTick, onMounted, reactive, ref, unref } from 'vue'
import useFormEdit from '@/hooks/bootx/useFormEdit'
import { FormInstance, Rule } from 'ant-design-vue/lib/form'
import { FormEditType } from '@/enums/formTypeEnum'
import { BasicModal } from '@/components/Modal'
import { LabeledValue } from 'ant-design-vue/lib/select'
import { findById, save, update, CashierCodeConfig } from './CashierCodeConfig.api'
import { useDict } from '@/hooks/bootx/useDict'
const {
initFormEditType,
handleCancel,
labelCol,
wrapperCol,
modalWidth,
title,
confirmLoading,
visible,
showable,
formEditType,
} = useFormEdit()
const { dictDropDown } = useDict()
// 表单
const formRef = ref<FormInstance>()
const cashierTypeList = ref<LabeledValue[]>([])
const channelList = ref<LabeledValue[]>([])
const methodList = ref<LabeledValue[]>([])
let form = ref<CashierCodeConfig>({
enable: true,
})
// 校验
const rules = reactive({
code: [{ required: true, message: '' }],
name: [{ required: true, message: '请输入码牌名称' }],
enable: [{ required: true, message: '是否启用' }],
} as Record<string, Rule[]>)
// 事件
const emits = defineEmits(['ok'])
onMounted(() => {
initData()
})
/**
* 初始化数据
*/
async function initData() {
cashierTypeList.value = await dictDropDown('cashier_type')
channelList.value = await dictDropDown('channel')
methodList.value = await dictDropDown('pay_method')
}
/**
* 入口
*/
function init(id, editType: FormEditType, appId: string) {
initFormEditType(editType)
resetForm()
form.value.appId = unref(appId)
getInfo(id, editType)
}
/**
* 获取信息
*/
function getInfo(id, editType: FormEditType) {
if ([FormEditType.Edit, FormEditType.Show].includes(editType)) {
confirmLoading.value = true
findById(id).then(({ data }) => {
form.value = data
confirmLoading.value = false
})
} else {
confirmLoading.value = false
}
}
/**
* 保存
*/
function handleOk() {
formRef.value?.validate().then(async () => {
confirmLoading.value = true
if (formEditType.value === FormEditType.Add) {
await save(form.value).finally(() => (confirmLoading.value = false))
} else if (formEditType.value === FormEditType.Edit) {
await update(form.value).finally(() => (confirmLoading.value = false))
}
handleCancel()
emits('ok')
})
}
// 重置表单的校验
function resetForm() {
nextTick(() => {
formRef.value?.resetFields()
})
}
defineExpose({
init,
})
</script>
<style lang="less" scoped></style>

View File

@@ -0,0 +1,218 @@
<template>
<basic-drawer
showFooter
v-bind="$attrs"
width="70%"
title="码牌配置"
:mask-closable="true"
:open="visible"
@close="handleCancel"
>
<vxe-toolbar ref="xToolbar" custom :refresh="{ queryMethod: queryPage }">
<template #buttons>
<a-space>
<a-button type="primary" pre-icon="ant-design:plus-outlined" @click="add">新建</a-button>
</a-space>
</template>
</vxe-toolbar>
<vxe-table ey-field="id" ref="xTable" :data="records" :loading="loading">
<vxe-column type="seq" width="60" />
<vxe-column field="name" title="码牌名称" :min-width="150">
<template #default="{ row }">
<a href="javascript:" @click="show(row)">{{ row.name }}</a>
</template>
</vxe-column>
<vxe-column field="code" title="码牌编号" :min-width="220" />
<vxe-column field="enable" title="是否启用" :min-width="150">
<template #default="{ row }">
<a-tag v-if="row.enable" color="green">开启</a-tag>
<a-tag v-else color="red">关闭</a-tag>
</template>
</vxe-column>
<vxe-column field="remark" title="备注" :min-width="170" />
<vxe-column field="createTime" title="创建时间" :min-width="170" />
<vxe-column fixed="right" :width="240" :showOverflow="false" title="操作">
<template #default="{ row }">
<a href="javascript:" @click="edit(row)">编辑</a>
<a-divider type="vertical" />
<a href="javascript:" @click="typeList(row)">类型配置</a>
<a-divider type="vertical" />
<a href="javascript:" @click="getUrl(row)">获取码牌</a>
<a-divider type="vertical" />
<a href="javascript:" style="color: red" @click="del(row)">删除</a>
</template>
</vxe-column>
</vxe-table>
<a-modal
title="商户收款码牌"
:loading="modelLoading"
:width="500"
:open="modelVisible"
:mask-closable="false"
:footer="null"
@cancel="() => (modelVisible = false)"
>
<div class="flex justify-center" style="padding: 30px 0">
<a-qrcode
ref="qrcodeCanvasRef"
:status="modelLoading ? 'loading' : 'active'"
:size="350"
:value="qrUrl"
:error-level="'Q'"
color="black"
bg-color="white"
/>
</div>
<div class="flex justify-center" style="margin-bottom: 20px">
<a-button type="primary" @click="download">保存码牌</a-button>
<a-button style="margin-left: 25px" @click="copy">复制地址</a-button>
</div>
</a-modal>
<CashierCodeConfigEdit ref="cashierCodeConfigEdit" @ok="queryPage" />
<CashierCodeTypeConfigList ref="cashierCodeTypeConfigList" />
</basic-drawer>
</template>
<script setup lang="ts">
import { BasicDrawer } from '@/components/Drawer'
import { ref } from 'vue'
import {
findAllByAppId,
remove,
CashierCodeConfig,
getCashierCodeUrl,
} from './CashierCodeConfig.api'
import CashierCodeTypeConfigList from './CashierCodeTypeConfigList.vue'
import CashierCodeConfigEdit from './CashierCodeConfigEdit.vue'
import { FormEditType } from '@/enums/formTypeEnum'
import { useMessage } from '@/hooks/web/useMessage'
import { copyText } from '@/utils/copyTextToClipboard'
const { createConfirm, createMessage } = useMessage()
const currentAppId = ref<string>()
const loading = ref(false)
const visible = ref(false)
const records = ref<CashierCodeConfig[]>([])
const modelLoading = ref(false)
const modelVisible = ref(false)
const qrUrl = ref<string>('')
const cashierCodeTypeConfigList = ref<any>()
const cashierCodeConfigEdit = ref<any>()
const qrcodeCanvasRef = ref<any>()
/**
* 初始化并展示
*/
async function init(appId: string) {
visible.value = true
loading.value = false
currentAppId.value = appId
queryPage()
}
/**
* 查询
*/
function queryPage() {
// 列表信息
loading.value = true
findAllByAppId(currentAppId.value).then(({ data }) => {
records.value = data
loading.value = false
})
}
/**
* 关闭页面
*/
function handleCancel() {
visible.value = false
}
/**
* 新增
*/
function add() {
cashierCodeConfigEdit.value.init(null, FormEditType.Add, currentAppId.value)
}
/**
* 编辑
*/
function edit(record) {
cashierCodeConfigEdit.value.init(record.id, FormEditType.Edit, currentAppId.value)
}
/**
* 查看
*/
function show(record) {
cashierCodeConfigEdit.value.init(record.id, FormEditType.Show, currentAppId.value)
}
/**
* 类型配置列表
*/
function typeList(record) {
cashierCodeTypeConfigList.value.init(record)
}
/**
* 获取码牌地址
*/
function getUrl(record) {
modelVisible.value = true
modelLoading.value = true
getCashierCodeUrl(record.id)
.then(({ data }) => {
qrUrl.value = data
modelLoading.value = false
})
.catch(() => {
createMessage.error('获取码牌地址失败')
})
}
/**
* 复制
*/
function copy() {
copyText(qrUrl.value)
}
/**
* 下载
*/
async function download() {
const url = qrcodeCanvasRef.value.toDataURL()
const a = document.createElement('a')
a.download = 'QRCode.png'
a.href = url
document.body.appendChild(a)
a.click()
document.body.removeChild(a)
}
/**
* 删除
*/
function del(record) {
createConfirm({
iconType: 'warning',
title: '删除',
content: '是否删除该数据',
onOk: () => {
loading.value = true
remove(record.id).then(() => {
createMessage.success('删除成功')
queryPage()
})
},
})
}
defineExpose({
init,
})
</script>
<style scoped lang="less"></style>

View File

@@ -20,23 +20,16 @@
<a-form-item label="主键" name="id" :hidden="true">
<a-input v-model:value="form.id" :disabled="showable" />
</a-form-item>
<a-form-item label="收银台类型" validate-first name="cashierType">
<a-form-item label="码牌类型" validate-first name="type">
<a-select
style="width: 300px"
v-model:value="form.cashierType"
v-model:value="form.type"
:disabled="showable"
:options="cashierTypeList"
allow-clear
placeholder="请选择收银台类型"
/>
</a-form-item>
<a-form-item label="收银台名称" name="cashierName">
<a-input
v-model:value="form.cashierName"
:disabled="showable"
placeholder="请输入收银台名称"
/>
</a-form-item>
<a-form-item label="支付通道" name="channel">
<a-select
style="width: 300px"
@@ -65,14 +58,6 @@
:disabled="showable"
/>
</a-form-item>
<a-form-item label="自动分账" name="autoAllocation">
<a-switch
checked-children="启用"
un-checked-children="停用"
v-model:checked="form.autoAllocation"
:disabled="showable"
/>
</a-form-item>
<a-form-item label="备注" name="remark">
<a-textarea v-model:value="form.remark" :disabled="showable" placeholder="请输入备注" />
</a-form-item>
@@ -101,15 +86,14 @@
import { BasicModal } from '@/components/Modal'
import { LabeledValue } from 'ant-design-vue/lib/select'
import {
get,
add,
update,
findTypeById,
saveType,
updateType,
existsByType,
existsByTypeNotId,
ChannelCashierConfig,
} from './ChannelCashierConfig.api'
CashierCodeTypeConfig,
} from './CashierCodeConfig.api'
import { useDict } from '@/hooks/bootx/useDict'
import { MchApp } from '@/views/daxpay/common/merchant/app/MchApp.api'
const {
initFormEditType,
@@ -133,18 +117,19 @@
const channelList = ref<LabeledValue[]>([])
const methodList = ref<LabeledValue[]>([])
let form = ref<ChannelCashierConfig>({
let form = ref<CashierCodeTypeConfig>({
allocation: false,
autoAllocation: false,
})
//
const rules = reactive({
cashierType: [
type: [
{ required: true, message: '请选择收银台类型' },
{ validator: validateCode, trigger: 'blur' },
],
cashierName: [{ required: true, message: '请输入收银台名称' }],
name: [{ required: true, message: '请输入字典项名称' }],
channel: [{ required: true, message: '请选择支付通道' }],
payMethod: [{ required: true, message: '请选择支付方式' }],
allocation: [{ required: true, message: '' }],
} as Record<string, Rule[]>)
//
@@ -158,7 +143,7 @@
* 初始化数据
*/
async function initData() {
cashierTypeList.value = await dictDropDown('cashier_type')
cashierTypeList.value = await dictDropDown('cashier_code_type')
channelList.value = await dictDropDown('channel')
methodList.value = await dictDropDown('pay_method')
}
@@ -166,10 +151,10 @@
/**
* 入口
*/
function init(id, editType: FormEditType, mchApp: MchApp) {
function init(id, editType: FormEditType, configId: string) {
initFormEditType(editType)
resetForm()
form.value.appId = unref(mchApp.appId)
form.value.cashierCodeId = unref(configId)
getInfo(id, editType)
}
/**
@@ -178,7 +163,7 @@
function getInfo(id, editType: FormEditType) {
if ([FormEditType.Edit, FormEditType.Show].includes(editType)) {
confirmLoading.value = true
get(id).then(({ data }) => {
findTypeById(id).then(({ data }) => {
form.value = data
confirmLoading.value = false
})
@@ -193,9 +178,9 @@
formRef.value?.validate().then(async () => {
confirmLoading.value = true
if (formEditType.value === FormEditType.Add) {
await add(form.value).finally(() => (confirmLoading.value = false))
await saveType(form.value).finally(() => (confirmLoading.value = false))
} else if (formEditType.value === FormEditType.Edit) {
await update(form.value).finally(() => (confirmLoading.value = false))
await updateType(form.value).finally(() => (confirmLoading.value = false))
}
handleCancel()
emits('ok')
@@ -206,13 +191,13 @@
* 校验编码重复
*/
async function validateCode() {
const { cashierType, appId, id } = form.value
const { type, cashierCodeId, id } = form.value
if (id) {
const res = await existsByTypeNotId(appId, cashierType, id)
return res.data ? Promise.reject('该收银台类型已存在') : Promise.resolve()
const res = await existsByTypeNotId(type, cashierCodeId, id)
return res.data ? Promise.reject('该码牌类型已存在') : Promise.resolve()
} else {
const res = await existsByType(appId, cashierType)
return res.data ? Promise.reject('该收银台类型已存在') : Promise.resolve()
const res = await existsByType(type, cashierCodeId)
return res.data ? Promise.reject('该码牌类型已存在') : Promise.resolve()
}
}

View File

@@ -3,7 +3,7 @@
showFooter
v-bind="$attrs"
width="70%"
title="收银配置"
title="码牌类型配置"
:mask-closable="true"
:open="visible"
@close="handleCancel"
@@ -17,32 +17,25 @@
</vxe-toolbar>
<vxe-table ey-field="id" ref="xTable" :data="records" :loading="loading">
<vxe-column type="seq" width="60" />
<vxe-column field="cashierType" title="收银台类型" :min-width="150">
<vxe-column field="type" title="码牌类型" :min-width="150">
<template #default="{ row }">
<a-tag color="green">{{ dictConvert('cashier_type', row.cashierType) }}</a-tag>
{{ dictConvert('cashier_code_type', row.type) }}
</template>
</vxe-column>
<vxe-column field="cashierName" title="收银台名称" :min-width="150" />
<vxe-column field="channel" title="关联通道" :min-width="150">
<vxe-column field="channel" title="支付通道" :min-width="150">
<template #default="{ row }">
<a-tag color="green">{{ dictConvert('channel', row.channel) }}</a-tag>
{{ dictConvert('channel', row.channel) }}
</template>
</vxe-column>
<vxe-column field="channel" title="关联支付方式" :min-width="150">
<vxe-column field="payMethod" title="支付方式" :min-width="150">
<template #default="{ row }">
<a-tag color="green">{{ dictConvert('pay_method', row.payMethod) }}</a-tag>
{{ dictConvert('pay_method', row.payMethod) }}
</template>
</vxe-column>
<vxe-column field="allocation" title="开启分账" :min-width="150">
<template #default="{ row }">
<a-tag v-if="row.allocation" color="green">开启</a-tag>
<a-tag v-else color="red">关闭</a-tag>
</template>
</vxe-column>
<vxe-column field="autoAllocation" title="自动分账" :min-width="150">
<template #default="{ row }">
<a-tag v-if="row.autoAllocation" color="green">开启</a-tag>
<a-tag v-else color="red">关闭</a-tag>
<a-tag color="green" v-if="row.allocation">开启</a-tag>
<a-tag v-else>关闭</a-tag>
</template>
</vxe-column>
<vxe-column field="remark" title="备注" :min-width="170" />
@@ -57,36 +50,39 @@
</template>
</vxe-column>
</vxe-table>
<ChannelCashierConfigEdit ref="channelCashierConfigEdit" @ok="queryPage" />
<CashierCodeTypeConfigEdit ref="cashierCodeTypeConfigEdit" @ok="queryPage" />
</basic-drawer>
</template>
<script setup lang="ts">
import { BasicDrawer } from '@/components/Drawer'
import { ref } from 'vue'
import { findAll, remove, ChannelCashierConfig } from './ChannelCashierConfig.api'
import ChannelCashierConfigEdit from './ChannelCashierConfigEdit.vue'
import {
deleteType,
findTypeByCodeId,
CashierCodeConfig,
CashierCodeTypeConfig,
} from './CashierCodeConfig.api'
import CashierCodeTypeConfigEdit from './CashierCodeTypeConfigEdit.vue'
import { FormEditType } from '@/enums/formTypeEnum'
import { useMessage } from '@/hooks/web/useMessage'
import { useDict } from '@/hooks/bootx/useDict'
import { MchApp } from '@/views/daxpay/common/merchant/app/MchApp.api'
const { createConfirm, createMessage } = useMessage()
const { dictConvert } = useDict()
const currentApp = ref<MchApp>({})
const loading = ref(false)
const visible = ref(false)
const records = ref<ChannelCashierConfig[]>([])
const records = ref<CashierCodeTypeConfig[]>([])
const codeConfig = ref<CashierCodeConfig>({})
const channelCashierConfigEdit = ref<any>()
const cashierCodeTypeConfigEdit = ref<any>()
/**
* 初始化并展示
*/
async function init(mchApp: MchApp) {
async function init(config: CashierCodeConfig) {
visible.value = true
loading.value = false
currentApp.value = mchApp
codeConfig.value = config
queryPage()
}
@@ -96,7 +92,7 @@
function queryPage() {
//
loading.value = true
findAll(currentApp.value.appId).then(({ data }) => {
findTypeByCodeId(codeConfig.value.id).then(({ data }) => {
records.value = data
loading.value = false
})
@@ -113,19 +109,19 @@
* 新增
*/
function add() {
channelCashierConfigEdit.value.init(null, FormEditType.Add, currentApp.value)
cashierCodeTypeConfigEdit.value.init(null, FormEditType.Add, codeConfig.value.id)
}
/**
* 编辑
*/
function edit(record) {
channelCashierConfigEdit.value.init(record.id, FormEditType.Edit, currentApp.value)
cashierCodeTypeConfigEdit.value.init(record.id, FormEditType.Edit, codeConfig.value.id)
}
/**
* 查看
*/
function show(record) {
channelCashierConfigEdit.value.init(record.id, FormEditType.Show, currentApp.value)
cashierCodeTypeConfigEdit.value.init(record.id, FormEditType.Show, codeConfig.value.id)
}
/**
@@ -138,7 +134,7 @@
content: '是否删除该数据',
onOk: () => {
loading.value = true
remove(record.id).then(() => {
deleteType(record.id).then(() => {
createMessage.success('删除成功')
queryPage()
})

View File

@@ -68,17 +68,17 @@ export interface MchApp extends BaseEntity {
// 应用名称
appName?: string
// 签名方式
signType: string
signType?: string
// 签名秘钥
signSecret?: string
// 是否对请求进行验签
reqSign: boolean
reqSign?: boolean
// 支付限额
limitAmount: number
limitAmount?: number
// 订单默认超时时间(分钟)
orderTimeout: number
orderTimeout?: number
// 异步消息通知类型
notifyType: string
notifyType?: string
// 通知地址, http/WebSocket 需要配置
notifyUrl?: string
// 状态

View File

@@ -53,17 +53,19 @@
<a-link @click="showChannelSetup(row)">通道配置</a-link>
<a-divider type="vertical" />
<a-dropdown>
<a style="color:red"> 其他配置 <Icon icon="ant-design:down-outlined" :size="12" /> </a>
<a style="color: red">
其他配置 <Icon icon="ant-design:down-outlined" :size="12" />
</a>
<template #overlay>
<a-menu>
<a-menu-item>
<a-link @click="showNotifyConfig(row)">订阅配置</a-link>
</a-menu-item>
<a-menu-item>
<a-link @click="showCashierConfig(row)">收银配置</a-link>
<a-link @click="showCheckoutConfig(row)">收银配置</a-link>
</a-menu-item>
<a-menu-item>
<a-link @click="showCashierQrCOde(row)">收银码牌</a-link>
<a-link @click="showCashierCode(row)">码牌配置</a-link>
</a-menu-item>
<a-menu-item>
<a-link @click="showAllocConfig(row)">分账配置</a-link>
@@ -94,9 +96,8 @@
/>
<mch-app-edit ref="mchApp" @ok="queryPage" />
<channel-config-list ref="channelSetup" />
<ChannelCashierConfigList ref="channelCashierConfigList" />
<ChannelCashierQrCode ref="channelCashierQrCode" />
<MerchantNotifyConfigList ref="merchantNotifyConfigList" />
<CashierCodeConfigList ref="cashierCodeConfigList" />
<AllocationReceiverList ref="allocationReceiverList" />
<AllocationGroupList ref="allocationGroupList" />
</div>
@@ -118,10 +119,9 @@
import ChannelConfigList from '@/views/daxpay/common/merchant/channel/ChannelConfigList.vue'
import MerchantNotifyConfigList from '@/views/daxpay/common/merchant/notify/MerchantNotifyConfigList.vue'
import Icon from '@/components/Icon/Icon.vue'
import ChannelCashierConfigList from '@/views/daxpay/common/merchant/cashier/ChannelCashierConfigList.vue'
import ChannelCashierQrCode from '@/views/daxpay/common/merchant/cashier/ChannelCashierQrCode.vue'
import AllocationReceiverList from '@/views/daxpay/common/allocation/receiver/AllocationReceiverList.vue'
import AllocationGroupList from '@/views/daxpay/common/allocation/group/AllocationGroupList.vue'
import CashierCodeConfigList from '@/views/daxpay/common/config/cashier/code/CashierCodeConfigList.vue'
// 使用hooks
const {
@@ -148,8 +148,7 @@
const mchApp = ref<any>()
const channelSetup = ref<any>()
const merchantNotifyConfigList = ref<any>()
const channelCashierConfigList = ref<any>()
const channelCashierQrCode = ref<any>()
const cashierCodeConfigList = ref<any>()
const allocationReceiverList = ref<any>()
const allocationGroupList = ref<any>()
@@ -205,16 +204,16 @@
merchantNotifyConfigList.value.init(record.appId)
}
/**
* 收银配置
* 收银配置
*/
function showCashierConfig(record) {
channelCashierConfigList.value.init(record)
function showCheckoutConfig(record) {
}
/**
* 收银码牌
* 收银码牌配置
*/
function showCashierQrCOde(record) {
channelCashierQrCode.value.init(record.appId)
function showCashierCode(record) {
cashierCodeConfigList.value.init(record.appId)
}
/**
* 分账配置

View File

@@ -1,103 +0,0 @@
import { defHttp } from '@/utils/http/axios'
import { Result } from '#/axios'
import { MchEntity } from '#/web'
/**
* 配置列表
*/
export function findAll(appId) {
return defHttp.get<Result<ChannelCashierConfig[]>>({
url: '/channel/cashier/config/findByAppId',
params: { appId },
})
}
/**
* 配置详情
*/
export function get(id) {
return defHttp.get<Result<ChannelCashierConfig>>({
url: '/channel/cashier/config/findById',
params: { id },
})
}
/**
* 配置是否存在
*/
export function existsByType(appId, type) {
return defHttp.get<Result<boolean>>({
url: '/channel/cashier/config/existsByType',
params: { appId, type },
})
}
/**
* 配置是否存在
*/
export function existsByTypeNotId(appId, type, id) {
return defHttp.get<Result<boolean>>({
url: '/channel/cashier/config/existsByTypeNotId',
params: { appId, type, id },
})
}
/**
* 配置保存
*/
export function add(data: ChannelCashierConfig) {
return defHttp.post<Result<ChannelCashierConfig>>({
url: '/channel/cashier/config/save',
data,
})
}
/**
* 配置更新
*/
export function update(data: ChannelCashierConfig) {
return defHttp.post<Result<ChannelCashierConfig>>({
url: '/channel/cashier/config/update',
data,
})
}
/**
* 配置删除
*/
export function remove(id) {
return defHttp.post<Result<ChannelCashierConfig>>({
url: '/channel/cashier/config/delete',
params: { id },
})
}
/**
* 获取码牌地址
*/
export function getQrCodeUrl(appId) {
return defHttp.get<Result<string>>({
url: '/channel/cashier/config/qrCodeUrl',
params: { appId },
})
}
/**
* 通道收银台配置
*/
export interface ChannelCashierConfig extends MchEntity {
// 收银台类型
cashierType?: string
// 收银台名称
cashierName?: string
// 支付通道
channel?: string
// 支付方式
payMethod?: string
// 是否开启分账
allocation?: boolean
// 自动分账
autoAllocation?: boolean
// 备注
remark?: string
}

View File

@@ -1,82 +0,0 @@
<template>
<a-modal
title="商户收款码牌"
:loading="confirmLoading"
:width="500"
:open="visible"
:mask-closable="false"
:footer="null"
@cancel="handleCancel"
>
<div class="flex justify-center" style="padding: 30px 0">
<a-qrcode
ref="qrcodeCanvasRef"
:status="confirmLoading ? 'loading' : 'active'"
:size="350"
:value="url"
:error-level="'Q'"
color="black"
bg-color="white"
/>
</div>
<div class="flex justify-center" style="margin-bottom: 20px">
<a-button type="primary" @click="download">保存码牌</a-button>
<a-button style="margin-left: 25px" @click="copy">复制地址</a-button>
</div>
</a-modal>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { copyText } from '@/utils/copyTextToClipboard'
import { getQrCodeUrl } from './ChannelCashierConfig.api'
const confirmLoading = ref(false)
const visible = ref(false)
const url = ref('')
const qrcodeCanvasRef = ref()
/**
* 初始化
*/
function init(appId: string) {
visible.value = true
confirmLoading.value = true
getQrCodeUrl(appId).then((res) => {
url.value = res.data
confirmLoading.value = false
})
}
/**
* 复制
*/
function copy() {
copyText(url.value)
}
/**
* 关闭
*/
function handleCancel() {
visible.value = false
}
/**
* 下嘴
*/
async function download() {
const url = qrcodeCanvasRef.value.toDataURL()
const a = document.createElement('a')
a.download = 'QRCode.png'
a.href = url
document.body.appendChild(a)
a.click()
document.body.removeChild(a)
}
defineExpose({
init,
})
</script>
<style scoped lang="less"></style>

View File

@@ -70,7 +70,7 @@ export function cancel(id) {
/**
* 触发分账
*/
export function allocationByOrderNo(orderNo) {
export function allocByOrderNo(orderNo) {
return defHttp.post<Result<void>>({
url: '/order/pay/allocation',
params: { orderNo },

View File

@@ -137,7 +137,7 @@
<script lang="ts" setup>
import { computed, onMounted, ref, watch } from 'vue'
import {
allocationByOrderNo,
allocByOrderNo,
close,
getTotalAmount,
page,
@@ -356,7 +356,7 @@
title: '警告',
content: '是否触发该订单的分账操作',
onOk: () => {
allocationByOrderNo(record.orderNo).then(() => {
allocByOrderNo(record.orderNo).then(() => {
createMessage.success('分账请求已发送')
queryPage()
})