This commit is contained in:
@@ -57,28 +57,28 @@
|
||||
width="600px"
|
||||
>
|
||||
<ElForm ref="formRef" :model="form" :rules="rules" label-width="100px">
|
||||
<ElFormItem label="企业编号" prop="enterprise_code">
|
||||
<div style="display: flex; gap: 8px">
|
||||
<ElInput
|
||||
v-model="form.enterprise_code"
|
||||
placeholder="请输入企业编号或点击生成"
|
||||
:disabled="dialogType === 'edit'"
|
||||
clearable
|
||||
style="flex: 1"
|
||||
/>
|
||||
<CodeGeneratorButton
|
||||
v-if="dialogType === 'add'"
|
||||
code-type="enterprise"
|
||||
@generated="handleCodeGenerated"
|
||||
/>
|
||||
</div>
|
||||
</ElFormItem>
|
||||
<ElRow :gutter="20">
|
||||
<ElCol :span="12">
|
||||
<ElFormItem label="企业编号" prop="enterprise_code">
|
||||
<ElInput
|
||||
v-model="form.enterprise_code"
|
||||
placeholder="请输入企业编号"
|
||||
:disabled="dialogType === 'edit'"
|
||||
/>
|
||||
</ElFormItem>
|
||||
</ElCol>
|
||||
<ElCol :span="12">
|
||||
<ElFormItem label="企业名称" prop="enterprise_name">
|
||||
<ElInput v-model="form.enterprise_name" placeholder="请输入企业名称" />
|
||||
</ElFormItem>
|
||||
</ElCol>
|
||||
</ElRow>
|
||||
<ElRow :gutter="20">
|
||||
<ElCol :span="12">
|
||||
<ElFormItem label="营业执照号" prop="business_license">
|
||||
<ElInput v-model="form.business_license" placeholder="请输入营业执照号" />
|
||||
</ElFormItem>
|
||||
</ElCol>
|
||||
<ElCol :span="12">
|
||||
<ElFormItem label="法人代表" prop="legal_person">
|
||||
<ElInput v-model="form.legal_person" placeholder="请输入法人代表" />
|
||||
@@ -86,6 +86,11 @@
|
||||
</ElCol>
|
||||
</ElRow>
|
||||
<ElRow :gutter="20">
|
||||
<ElCol :span="12">
|
||||
<ElFormItem label="营业执照号" prop="business_license">
|
||||
<ElInput v-model="form.business_license" placeholder="请输入营业执照号" />
|
||||
</ElFormItem>
|
||||
</ElCol>
|
||||
<ElCol :span="12">
|
||||
<ElFormItem label="所在地区" prop="region">
|
||||
<ElCascader
|
||||
@@ -99,6 +104,8 @@
|
||||
/>
|
||||
</ElFormItem>
|
||||
</ElCol>
|
||||
</ElRow>
|
||||
<ElRow :gutter="20">
|
||||
<!-- 只有非代理账号才显示归属店铺选择 -->
|
||||
<ElCol :span="12" v-if="!isAgentAccount">
|
||||
<ElFormItem label="归属店铺" prop="owner_shop_id">
|
||||
@@ -225,6 +232,7 @@
|
||||
import ArtButtonTable from '@/components/core/forms/ArtButtonTable.vue'
|
||||
import ArtMenuRight from '@/components/core/others/ArtMenuRight.vue'
|
||||
import TableContextMenuHint from '@/components/core/others/TableContextMenuHint.vue'
|
||||
import CodeGeneratorButton from '@/components/business/CodeGeneratorButton.vue'
|
||||
import type { MenuItemType } from '@/components/core/others/ArtMenuRight.vue'
|
||||
import { formatDateTime } from '@/utils/business/format'
|
||||
import { regionData } from '@/utils/constants/regionData'
|
||||
@@ -478,7 +486,7 @@
|
||||
{
|
||||
prop: 'operation',
|
||||
label: '操作',
|
||||
width: 190,
|
||||
width: 280,
|
||||
fixed: 'right',
|
||||
formatter: (row: EnterpriseItem) => {
|
||||
const buttons = []
|
||||
@@ -501,6 +509,15 @@
|
||||
)
|
||||
}
|
||||
|
||||
if (hasAuth('enterprise_customer:device_authorization')) {
|
||||
buttons.push(
|
||||
h(ArtButtonTable, {
|
||||
text: '设备授权',
|
||||
onClick: () => manageDevices(row)
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
return h('div', { style: 'display: flex; gap: 8px;' }, buttons)
|
||||
}
|
||||
}
|
||||
@@ -712,6 +729,11 @@
|
||||
})
|
||||
}
|
||||
|
||||
// 处理企业编码生成
|
||||
const handleCodeGenerated = (code: string) => {
|
||||
form.enterprise_code = code
|
||||
}
|
||||
|
||||
// 提交表单
|
||||
const handleSubmit = async (formEl: FormInstance | undefined) => {
|
||||
if (!formEl) return
|
||||
@@ -810,6 +832,13 @@
|
||||
})
|
||||
}
|
||||
|
||||
const manageDevices = (row: EnterpriseItem) => {
|
||||
router.push({
|
||||
path: '/asset-management/enterprise-devices',
|
||||
query: { id: row.id }
|
||||
})
|
||||
}
|
||||
|
||||
// 企业客户操作菜单项配置
|
||||
const enterpriseOperationMenuItems = computed((): MenuItemType[] => {
|
||||
const items: MenuItemType[] = []
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
<ArtSearchBar
|
||||
v-model:filter="searchForm"
|
||||
:items="searchFormItems"
|
||||
:show-expand="false"
|
||||
@reset="handleReset"
|
||||
@search="handleSearch"
|
||||
></ArtSearchBar>
|
||||
@@ -73,45 +74,55 @@
|
||||
<ElDialog
|
||||
v-model="allocateDialogVisible"
|
||||
:title="$t('enterpriseDevices.dialog.allocateTitle')"
|
||||
width="700px"
|
||||
width="75%"
|
||||
@close="handleAllocateDialogClose"
|
||||
>
|
||||
<ElForm
|
||||
ref="allocateFormRef"
|
||||
:model="allocateForm"
|
||||
:rules="allocateRules"
|
||||
label-width="120px"
|
||||
<!-- 搜索过滤条件 -->
|
||||
<ArtSearchBar
|
||||
v-model:filter="deviceSearchForm"
|
||||
:items="deviceSearchFormItems"
|
||||
label-width="85"
|
||||
:show-expand="false"
|
||||
@reset="handleDeviceSearchReset"
|
||||
@search="handleDeviceSearch"
|
||||
></ArtSearchBar>
|
||||
|
||||
<!-- 设备列表 -->
|
||||
<div class="device-selection-info">
|
||||
已选择 {{ selectedAvailableDevices.length }} 台设备
|
||||
</div>
|
||||
<ArtTable
|
||||
ref="availableDevicesTableRef"
|
||||
row-key="id"
|
||||
:loading="availableDevicesLoading"
|
||||
:data="availableDevicesList"
|
||||
:currentPage="devicePagination.page"
|
||||
:pageSize="devicePagination.pageSize"
|
||||
:total="devicePagination.total"
|
||||
:marginTop="10"
|
||||
@size-change="handleDevicePageSizeChange"
|
||||
@current-change="handleDevicePageChange"
|
||||
@selection-change="handleAvailableDevicesSelectionChange"
|
||||
>
|
||||
<ElFormItem :label="$t('enterpriseDevices.form.deviceNos')" prop="virtual_nos">
|
||||
<ElInput
|
||||
v-model="deviceNosText"
|
||||
type="textarea"
|
||||
:rows="6"
|
||||
:placeholder="$t('enterpriseDevices.form.deviceNosPlaceholder')"
|
||||
@input="handleDeviceNosChange"
|
||||
<template #default>
|
||||
<ElTableColumn type="selection" width="55" :selectable="checkDeviceSelectable" />
|
||||
<ElTableColumn
|
||||
v-for="col in availableDeviceColumns"
|
||||
:key="col.prop || col.type"
|
||||
v-bind="col"
|
||||
/>
|
||||
<div style="margin-top: 4px; font-size: 12px; color: var(--el-color-info)">
|
||||
{{
|
||||
$t('enterpriseDevices.form.selectedCount', {
|
||||
count: allocateForm.virtual_nos?.length || 0
|
||||
})
|
||||
}}
|
||||
</div>
|
||||
</ElFormItem>
|
||||
<ElFormItem :label="$t('enterpriseDevices.form.remark')">
|
||||
<ElInput
|
||||
v-model="allocateForm.remark"
|
||||
type="textarea"
|
||||
:rows="3"
|
||||
:placeholder="$t('enterpriseDevices.form.remarkPlaceholder')"
|
||||
/>
|
||||
</ElFormItem>
|
||||
</ElForm>
|
||||
</template>
|
||||
</ArtTable>
|
||||
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<ElButton @click="allocateDialogVisible = false">{{ $t('common.cancel') }}</ElButton>
|
||||
<ElButton type="primary" @click="handleAllocate" :loading="allocateLoading">
|
||||
<ElButton
|
||||
type="primary"
|
||||
@click="handleAllocate"
|
||||
:loading="allocateLoading"
|
||||
:disabled="selectedAvailableDevices.length === 0"
|
||||
>
|
||||
{{ $t('common.confirm') }}
|
||||
</ElButton>
|
||||
</div>
|
||||
@@ -225,7 +236,7 @@
|
||||
import { h } from 'vue'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { EnterpriseService } from '@/api/modules'
|
||||
import { EnterpriseService, DeviceService } from '@/api/modules'
|
||||
import { ElMessage, ElMessageBox, ElTag } from 'element-plus'
|
||||
import type { FormInstance, FormRules } from 'element-plus'
|
||||
import type { SearchFormItem } from '@/types'
|
||||
@@ -239,6 +250,7 @@
|
||||
FailedDeviceItem
|
||||
} from '@/types/api/enterpriseDevice'
|
||||
import type { EnterpriseItem } from '@/types/api'
|
||||
import type { Device, DeviceStatus } from '@/types/api/device'
|
||||
|
||||
defineOptions({ name: 'EnterpriseDevices' })
|
||||
|
||||
@@ -252,12 +264,10 @@
|
||||
const recallLoading = ref(false)
|
||||
const resultDialogVisible = ref(false)
|
||||
const tableRef = ref()
|
||||
const allocateFormRef = ref<FormInstance>()
|
||||
const recallFormRef = ref<FormInstance>()
|
||||
const selectedDevices = ref<EnterpriseDeviceItem[]>([])
|
||||
const enterpriseId = ref<number>(0)
|
||||
const enterpriseInfo = ref<EnterpriseItem | null>(null)
|
||||
const deviceNosText = ref('')
|
||||
const operationResult = ref<AllocateDevicesResponse | RecallDevicesResponse>({
|
||||
success_count: 0,
|
||||
fail_count: 0,
|
||||
@@ -265,6 +275,28 @@
|
||||
authorized_devices: null
|
||||
})
|
||||
|
||||
// 可用设备列表相关
|
||||
const availableDevicesTableRef = ref()
|
||||
const availableDevicesLoading = ref(false)
|
||||
const availableDevicesList = ref<Device[]>([])
|
||||
const selectedAvailableDevices = ref<Device[]>([])
|
||||
const allocatedDeviceVirtualNos = ref<Set<string>>(new Set())
|
||||
|
||||
// 设备搜索表单初始值
|
||||
const initialDeviceSearchState = {
|
||||
status: undefined,
|
||||
virtual_no: '',
|
||||
device_name: '',
|
||||
shop_id: undefined
|
||||
}
|
||||
|
||||
const deviceSearchForm = reactive({ ...initialDeviceSearchState })
|
||||
const devicePagination = reactive({
|
||||
page: 1,
|
||||
pageSize: 20,
|
||||
total: 0
|
||||
})
|
||||
|
||||
// 搜索表单初始值
|
||||
const initialSearchState = {
|
||||
virtual_no: ''
|
||||
@@ -273,31 +305,6 @@
|
||||
// 搜索表单
|
||||
const searchForm = reactive({ ...initialSearchState })
|
||||
|
||||
// 授权表单
|
||||
const allocateForm = reactive({
|
||||
virtual_nos: [] as string[],
|
||||
remark: ''
|
||||
})
|
||||
|
||||
// 授权表单验证规则
|
||||
const allocateRules = reactive<FormRules>({
|
||||
virtual_nos: [
|
||||
{
|
||||
required: true,
|
||||
validator: (rule, value, callback) => {
|
||||
if (!value || value.length === 0) {
|
||||
callback(new Error(t('enterpriseDevices.validation.deviceNosRequired')))
|
||||
} else if (value.length > 100) {
|
||||
callback(new Error(t('enterpriseDevices.validation.deviceNosMaxLength')))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
},
|
||||
trigger: 'change'
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
// 撤销表单
|
||||
const recallForm = reactive({})
|
||||
|
||||
@@ -324,6 +331,43 @@
|
||||
}
|
||||
]
|
||||
|
||||
// 设备列表搜索表单配置
|
||||
const deviceSearchFormItems: SearchFormItem[] = [
|
||||
{
|
||||
label: '设备状态',
|
||||
prop: 'status',
|
||||
type: 'select',
|
||||
config: {
|
||||
clearable: true,
|
||||
placeholder: '全部'
|
||||
},
|
||||
options: () => [
|
||||
{ label: '在库', value: 1 },
|
||||
{ label: '已分销', value: 2 },
|
||||
{ label: '已激活', value: 3 },
|
||||
{ label: '已停用', value: 4 }
|
||||
]
|
||||
},
|
||||
{
|
||||
label: '设备号',
|
||||
prop: 'virtual_no',
|
||||
type: 'input',
|
||||
config: {
|
||||
clearable: true,
|
||||
placeholder: '请输入设备号'
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '设备名称',
|
||||
prop: 'device_name',
|
||||
type: 'input',
|
||||
config: {
|
||||
clearable: true,
|
||||
placeholder: '请输入设备名称'
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
// 列配置
|
||||
const columnOptions = [
|
||||
{ label: t('enterpriseDevices.table.deviceId'), prop: 'device_id' },
|
||||
@@ -336,6 +380,38 @@
|
||||
|
||||
const deviceList = ref<EnterpriseDeviceItem[]>([])
|
||||
|
||||
// 获取设备状态标签类型
|
||||
const getDeviceStatusTag = (status: DeviceStatus) => {
|
||||
switch (status) {
|
||||
case 1:
|
||||
return 'info'
|
||||
case 2:
|
||||
return 'warning'
|
||||
case 3:
|
||||
return 'success'
|
||||
case 4:
|
||||
return 'danger'
|
||||
default:
|
||||
return 'info'
|
||||
}
|
||||
}
|
||||
|
||||
// 获取设备状态文本
|
||||
const getDeviceStatusText = (status: DeviceStatus) => {
|
||||
switch (status) {
|
||||
case 1:
|
||||
return '在库'
|
||||
case 2:
|
||||
return '已分销'
|
||||
case 3:
|
||||
return '已激活'
|
||||
case 4:
|
||||
return '已停用'
|
||||
default:
|
||||
return '未知'
|
||||
}
|
||||
}
|
||||
|
||||
// 动态列配置
|
||||
const { columnChecks, columns } = useCheckedColumns(() => [
|
||||
{
|
||||
@@ -372,6 +448,45 @@
|
||||
}
|
||||
])
|
||||
|
||||
// 可用设备列表列配置
|
||||
const availableDeviceColumns = computed(() => [
|
||||
{
|
||||
prop: 'virtual_no',
|
||||
label: '设备号',
|
||||
minWidth: 150
|
||||
},
|
||||
{
|
||||
prop: 'device_name',
|
||||
label: '设备名称',
|
||||
minWidth: 150
|
||||
},
|
||||
{
|
||||
prop: 'device_model',
|
||||
label: '设备型号',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
prop: 'status',
|
||||
label: '状态',
|
||||
width: 100,
|
||||
formatter: (row: Device) => {
|
||||
return h(ElTag, { type: getDeviceStatusTag(row.status) }, () =>
|
||||
getDeviceStatusText(row.status)
|
||||
)
|
||||
}
|
||||
},
|
||||
{
|
||||
prop: 'shop_name',
|
||||
label: '所属店铺',
|
||||
width: 150
|
||||
},
|
||||
{
|
||||
prop: 'bound_card_count',
|
||||
label: '绑定卡数',
|
||||
width: 100
|
||||
}
|
||||
])
|
||||
|
||||
onMounted(() => {
|
||||
const id = route.query.id
|
||||
if (id) {
|
||||
@@ -469,86 +584,130 @@
|
||||
router.back()
|
||||
}
|
||||
|
||||
// 显示授权对话框
|
||||
const showAllocateDialog = () => {
|
||||
allocateDialogVisible.value = true
|
||||
deviceNosText.value = ''
|
||||
allocateForm.virtual_nos = []
|
||||
allocateForm.remark = ''
|
||||
if (allocateFormRef.value) {
|
||||
allocateFormRef.value.resetFields()
|
||||
// 获取可用设备列表
|
||||
const getAvailableDevicesList = async () => {
|
||||
availableDevicesLoading.value = true
|
||||
try {
|
||||
const params: any = {
|
||||
page: devicePagination.page,
|
||||
page_size: devicePagination.pageSize,
|
||||
...deviceSearchForm
|
||||
}
|
||||
// 清理空值
|
||||
Object.keys(params).forEach((key) => {
|
||||
if (params[key] === '' || params[key] === undefined) {
|
||||
delete params[key]
|
||||
}
|
||||
})
|
||||
|
||||
const res = await DeviceService.getDevices(params)
|
||||
if (res.code === 0) {
|
||||
availableDevicesList.value = res.data.items || []
|
||||
devicePagination.total = res.data.total || 0
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
ElMessage.error('获取设备列表失败')
|
||||
} finally {
|
||||
availableDevicesLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 处理设备号输入变化
|
||||
const handleDeviceNosChange = () => {
|
||||
// 解析输入的设备号,支持逗号、空格、换行分隔
|
||||
const deviceNos = deviceNosText.value
|
||||
.split(/[,\s\n]+/)
|
||||
.map((no) => no.trim())
|
||||
.filter((no) => no.length > 0)
|
||||
allocateForm.virtual_nos = deviceNos
|
||||
// 处理设备列表选择变化
|
||||
const handleAvailableDevicesSelectionChange = (selection: Device[]) => {
|
||||
selectedAvailableDevices.value = selection
|
||||
}
|
||||
|
||||
// 设备列表搜索
|
||||
const handleDeviceSearch = () => {
|
||||
devicePagination.page = 1
|
||||
getAvailableDevicesList()
|
||||
}
|
||||
|
||||
// 设备列表重置
|
||||
const handleDeviceSearchReset = () => {
|
||||
Object.assign(deviceSearchForm, { ...initialDeviceSearchState })
|
||||
devicePagination.page = 1
|
||||
getAvailableDevicesList()
|
||||
}
|
||||
|
||||
// 设备列表分页大小变化
|
||||
const handleDevicePageSizeChange = (newPageSize: number) => {
|
||||
devicePagination.pageSize = newPageSize
|
||||
getAvailableDevicesList()
|
||||
}
|
||||
|
||||
// 设备列表页码变化
|
||||
const handleDevicePageChange = (newPage: number) => {
|
||||
devicePagination.page = newPage
|
||||
getAvailableDevicesList()
|
||||
}
|
||||
|
||||
// 检查设备是否可选(已授权的设备不可选)
|
||||
const checkDeviceSelectable = (row: Device) => {
|
||||
return !allocatedDeviceVirtualNos.value.has(row.virtual_no)
|
||||
}
|
||||
|
||||
// 显示授权对话框
|
||||
const showAllocateDialog = () => {
|
||||
allocateDialogVisible.value = true
|
||||
selectedAvailableDevices.value = []
|
||||
// 收集已授权的设备的 virtual_no
|
||||
allocatedDeviceVirtualNos.value = new Set(deviceList.value.map((device) => device.virtual_no))
|
||||
// 重置搜索条件
|
||||
Object.assign(deviceSearchForm, { ...initialDeviceSearchState })
|
||||
devicePagination.page = 1
|
||||
devicePagination.pageSize = 20
|
||||
// 加载可用设备列表
|
||||
getAvailableDevicesList()
|
||||
}
|
||||
|
||||
// 执行授权
|
||||
const handleAllocate = async () => {
|
||||
if (!allocateFormRef.value) return
|
||||
if (selectedAvailableDevices.value.length === 0) {
|
||||
ElMessage.warning('请选择要授权的设备')
|
||||
return
|
||||
}
|
||||
|
||||
await allocateFormRef.value.validate(async (valid) => {
|
||||
if (valid) {
|
||||
if (allocateForm.virtual_nos.length === 0) {
|
||||
ElMessage.warning(t('enterpriseDevices.messages.deviceNosEmpty'))
|
||||
return
|
||||
}
|
||||
allocateLoading.value = true
|
||||
try {
|
||||
const device_nos = selectedAvailableDevices.value.map((device) => device.virtual_no)
|
||||
const res = await EnterpriseService.allocateDevices(enterpriseId.value, {
|
||||
device_nos
|
||||
})
|
||||
|
||||
if (allocateForm.virtual_nos.length > 100) {
|
||||
ElMessage.warning(t('enterpriseDevices.messages.deviceNosMaxLimit'))
|
||||
return
|
||||
}
|
||||
if (res.code === 0) {
|
||||
operationResult.value = res.data
|
||||
allocateDialogVisible.value = false
|
||||
resultDialogVisible.value = true
|
||||
|
||||
allocateLoading.value = true
|
||||
try {
|
||||
const res = await EnterpriseService.allocateDevices(enterpriseId.value, {
|
||||
virtual_nos: allocateForm.virtual_nos,
|
||||
remark: allocateForm.remark || undefined
|
||||
})
|
||||
|
||||
if (res.code === 0) {
|
||||
operationResult.value = res.data
|
||||
allocateDialogVisible.value = false
|
||||
resultDialogVisible.value = true
|
||||
|
||||
// 显示成功消息
|
||||
if (res.data.success_count > 0 && res.data.fail_count === 0) {
|
||||
ElMessage.success(t('enterpriseDevices.messages.allocateSuccess'))
|
||||
} else if (res.data.success_count > 0 && res.data.fail_count > 0) {
|
||||
ElMessage.warning(
|
||||
t('enterpriseDevices.messages.allocatePartialSuccess', {
|
||||
success: res.data.success_count,
|
||||
fail: res.data.fail_count
|
||||
})
|
||||
)
|
||||
} else {
|
||||
ElMessage.error(t('enterpriseDevices.messages.allocateFailed'))
|
||||
}
|
||||
|
||||
getTableData()
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
// 显示成功消息
|
||||
if (res.data.success_count > 0 && res.data.fail_count === 0) {
|
||||
ElMessage.success(t('enterpriseDevices.messages.allocateSuccess'))
|
||||
} else if (res.data.success_count > 0 && res.data.fail_count > 0) {
|
||||
ElMessage.warning(
|
||||
t('enterpriseDevices.messages.allocatePartialSuccess', {
|
||||
success: res.data.success_count,
|
||||
fail: res.data.fail_count
|
||||
})
|
||||
)
|
||||
} else {
|
||||
ElMessage.error(t('enterpriseDevices.messages.allocateFailed'))
|
||||
} finally {
|
||||
allocateLoading.value = false
|
||||
}
|
||||
|
||||
getTableData()
|
||||
}
|
||||
})
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
ElMessage.error(t('enterpriseDevices.messages.allocateFailed'))
|
||||
} finally {
|
||||
allocateLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 关闭授权对话框
|
||||
const handleAllocateDialogClose = () => {
|
||||
if (allocateFormRef.value) {
|
||||
allocateFormRef.value.resetFields()
|
||||
}
|
||||
selectedAvailableDevices.value = []
|
||||
}
|
||||
|
||||
// 显示撤销授权对话框
|
||||
@@ -582,7 +741,7 @@
|
||||
recallLoading.value = true
|
||||
try {
|
||||
const res = await EnterpriseService.recallDevices(enterpriseId.value, {
|
||||
virtual_nos: selectedDevices.value.map((device) => device.virtual_no)
|
||||
device_nos: selectedDevices.value.map((device) => device.virtual_no)
|
||||
})
|
||||
|
||||
if (res.code === 0) {
|
||||
@@ -636,5 +795,12 @@
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.device-selection-info {
|
||||
margin-top: 10px;
|
||||
margin-bottom: 12px;
|
||||
color: var(--el-color-info);
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -83,7 +83,7 @@
|
||||
placeholder="请选择支付方式"
|
||||
style="width: 100%"
|
||||
>
|
||||
<ElOption label="微信在线支付" value="wechat" />
|
||||
<!--<ElOption label="微信在线支付" value="wechat" />-->
|
||||
<!-- 只有平台用户才显示线下转账选项 -->
|
||||
<ElOption
|
||||
v-if="userStore.info.user_type === 1 || userStore.info.user_type === 2"
|
||||
@@ -298,7 +298,7 @@
|
||||
|
||||
const createForm = reactive<{ amount: number; payment_method: string; shop_id: number | null }>({
|
||||
amount: 100,
|
||||
payment_method: 'wechat',
|
||||
payment_method: '线下转账',
|
||||
shop_id: null
|
||||
})
|
||||
|
||||
@@ -537,7 +537,7 @@
|
||||
const handleCreateDialogClosed = () => {
|
||||
createFormRef.value?.resetFields()
|
||||
createForm.amount = 100
|
||||
createForm.payment_method = 'wechat'
|
||||
createForm.payment_method = '线下转账'
|
||||
createForm.shop_id = null
|
||||
}
|
||||
|
||||
|
||||
@@ -77,10 +77,10 @@
|
||||
v-model="form.provider_type"
|
||||
placeholder="请选择支付渠道类型"
|
||||
style="width: 100%"
|
||||
:disabled="dialogType === 'edit'"
|
||||
@change="handleProviderTypeChange"
|
||||
>
|
||||
<ElOption label="微信直连" value="wechat" />
|
||||
<ElOption label="微信直连V2" value="wechat_v2" />
|
||||
<ElOption label="富友支付" value="fuiou" />
|
||||
</ElSelect>
|
||||
</ElFormItem>
|
||||
@@ -96,7 +96,7 @@
|
||||
</ElFormItem>
|
||||
|
||||
<!-- 微信相关配置 -->
|
||||
<template v-if="form.provider_type === 'wechat'">
|
||||
<template v-if="form.provider_type === 'wechat' || form.provider_type === 'wechat_v2'">
|
||||
<ElDivider content-position="left">
|
||||
<span class="divider-title">小程序配置</span>
|
||||
</ElDivider>
|
||||
@@ -106,7 +106,6 @@
|
||||
<ElInput
|
||||
v-model="form.miniapp_app_id"
|
||||
placeholder="请输入小程序AppID"
|
||||
:disabled="dialogType === 'edit'"
|
||||
/>
|
||||
</ElFormItem>
|
||||
</ElCol>
|
||||
@@ -131,7 +130,6 @@
|
||||
<ElInput
|
||||
v-model="form.oa_app_id"
|
||||
placeholder="请输入公众号AppID"
|
||||
:disabled="dialogType === 'edit'"
|
||||
/>
|
||||
</ElFormItem>
|
||||
</ElCol>
|
||||
@@ -172,7 +170,6 @@
|
||||
<ElInput
|
||||
v-model="form.oa_oauth_redirect_url"
|
||||
placeholder="请输入OAuth回调地址"
|
||||
:disabled="dialogType === 'edit'"
|
||||
/>
|
||||
</ElFormItem>
|
||||
|
||||
@@ -185,7 +182,6 @@
|
||||
<ElInput
|
||||
v-model="form.wx_mch_id"
|
||||
placeholder="请输入微信商户号"
|
||||
:disabled="dialogType === 'edit'"
|
||||
/>
|
||||
</ElFormItem>
|
||||
</ElCol>
|
||||
@@ -194,7 +190,6 @@
|
||||
<ElInput
|
||||
v-model="form.wx_serial_no"
|
||||
placeholder="请输入微信证书序列号"
|
||||
:disabled="dialogType === 'edit'"
|
||||
/>
|
||||
</ElFormItem>
|
||||
</ElCol>
|
||||
@@ -225,7 +220,6 @@
|
||||
<ElInput
|
||||
v-model="form.wx_notify_url"
|
||||
placeholder="请输入微信支付回调地址"
|
||||
:disabled="dialogType === 'edit'"
|
||||
/>
|
||||
</ElFormItem>
|
||||
<ElRow :gutter="20">
|
||||
@@ -261,7 +255,6 @@
|
||||
<ElInput
|
||||
v-model="form.miniapp_app_id"
|
||||
placeholder="请输入小程序AppID"
|
||||
:disabled="dialogType === 'edit'"
|
||||
/>
|
||||
</ElFormItem>
|
||||
</ElCol>
|
||||
@@ -286,7 +279,6 @@
|
||||
<ElInput
|
||||
v-model="form.oa_app_id"
|
||||
placeholder="请输入公众号AppID"
|
||||
:disabled="dialogType === 'edit'"
|
||||
/>
|
||||
</ElFormItem>
|
||||
</ElCol>
|
||||
@@ -327,7 +319,6 @@
|
||||
<ElInput
|
||||
v-model="form.oa_oauth_redirect_url"
|
||||
placeholder="请输入OAuth回调地址"
|
||||
:disabled="dialogType === 'edit'"
|
||||
/>
|
||||
</ElFormItem>
|
||||
|
||||
@@ -340,7 +331,6 @@
|
||||
<ElInput
|
||||
v-model="form.wx_mch_id"
|
||||
placeholder="请输入微信商户号"
|
||||
:disabled="dialogType === 'edit'"
|
||||
/>
|
||||
</ElFormItem>
|
||||
</ElCol>
|
||||
@@ -349,7 +339,6 @@
|
||||
<ElInput
|
||||
v-model="form.wx_serial_no"
|
||||
placeholder="请输入微信证书序列号"
|
||||
:disabled="dialogType === 'edit'"
|
||||
/>
|
||||
</ElFormItem>
|
||||
</ElCol>
|
||||
@@ -380,7 +369,6 @@
|
||||
<ElInput
|
||||
v-model="form.wx_notify_url"
|
||||
placeholder="请输入微信支付回调地址"
|
||||
:disabled="dialogType === 'edit'"
|
||||
/>
|
||||
</ElFormItem>
|
||||
<ElRow :gutter="20">
|
||||
@@ -415,7 +403,6 @@
|
||||
<ElInput
|
||||
v-model="form.fy_api_url"
|
||||
placeholder="请输入富友API地址"
|
||||
:disabled="dialogType === 'edit'"
|
||||
/>
|
||||
</ElFormItem>
|
||||
</ElCol>
|
||||
@@ -424,7 +411,6 @@
|
||||
<ElInput
|
||||
v-model="form.fy_ins_cd"
|
||||
placeholder="请输入富友机构号"
|
||||
:disabled="dialogType === 'edit'"
|
||||
/>
|
||||
</ElFormItem>
|
||||
</ElCol>
|
||||
@@ -435,7 +421,6 @@
|
||||
<ElInput
|
||||
v-model="form.fy_mchnt_cd"
|
||||
placeholder="请输入富友商户号"
|
||||
:disabled="dialogType === 'edit'"
|
||||
/>
|
||||
</ElFormItem>
|
||||
</ElCol>
|
||||
@@ -444,7 +429,6 @@
|
||||
<ElInput
|
||||
v-model="form.fy_term_id"
|
||||
placeholder="请输入富友终端号"
|
||||
:disabled="dialogType === 'edit'"
|
||||
/>
|
||||
</ElFormItem>
|
||||
</ElCol>
|
||||
@@ -453,7 +437,6 @@
|
||||
<ElInput
|
||||
v-model="form.fy_notify_url"
|
||||
placeholder="请输入富友支付回调地址"
|
||||
:disabled="dialogType === 'edit'"
|
||||
/>
|
||||
</ElFormItem>
|
||||
<ElRow :gutter="20">
|
||||
@@ -551,6 +534,7 @@
|
||||
placeholder: '请选择支付渠道类型',
|
||||
options: [
|
||||
{ label: '微信直连', value: 'wechat' },
|
||||
{ label: '微信直连V2', value: 'wechat_v2' },
|
||||
{ label: '富友支付', value: 'fuiou' }
|
||||
],
|
||||
config: {
|
||||
@@ -607,55 +591,15 @@
|
||||
}
|
||||
}
|
||||
|
||||
// 自定义验证器 - 编辑模式下允许为空,新增模式下必填
|
||||
const createRequiredValidator = (fieldName: string) => {
|
||||
return (rule: any, value: any, callback: any) => {
|
||||
if (dialogType.value === 'add' && !value) {
|
||||
callback(new Error(`请输入${fieldName}`))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 静态验证规则 - 一次性定义所有规则
|
||||
// 静态验证规则 - 只有配置名称和支付渠道类型是必填的
|
||||
const rules = reactive<FormRules>({
|
||||
name: [{ required: true, message: '请输入配置名称', trigger: 'blur' }],
|
||||
provider_type: [{ required: true, message: '请选择支付渠道类型', trigger: 'change' }],
|
||||
// 所有字段的验证规则都定义好
|
||||
miniapp_app_id: [{ required: true, validator: createRequiredValidator('小程序AppID'), trigger: 'blur' }],
|
||||
miniapp_app_secret: [{ required: true, validator: createRequiredValidator('小程序AppSecret'), trigger: 'blur' }],
|
||||
oa_app_id: [{ required: true, validator: createRequiredValidator('公众号AppID'), trigger: 'blur' }],
|
||||
oa_app_secret: [{ required: true, validator: createRequiredValidator('公众号AppSecret'), trigger: 'blur' }],
|
||||
oa_token: [{ required: true, validator: createRequiredValidator('公众号Token'), trigger: 'blur' }],
|
||||
oa_aes_key: [{ required: true, validator: createRequiredValidator('公众号AES Key'), trigger: 'blur' }],
|
||||
oa_oauth_redirect_url: [
|
||||
{ required: true, validator: createRequiredValidator('OAuth回调地址'), trigger: 'blur' },
|
||||
{ validator: urlValidator, trigger: 'blur' }
|
||||
],
|
||||
wx_mch_id: [{ required: true, validator: createRequiredValidator('微信商户号'), trigger: 'blur' }],
|
||||
wx_api_v2_key: [{ required: true, validator: createRequiredValidator('微信APIv2密钥'), trigger: 'blur' }],
|
||||
wx_api_v3_key: [{ required: true, validator: createRequiredValidator('微信APIv3密钥'), trigger: 'blur' }],
|
||||
wx_serial_no: [{ required: true, validator: createRequiredValidator('微信证书序列号'), trigger: 'blur' }],
|
||||
wx_cert_content: [{ required: true, validator: createRequiredValidator('微信支付证书内容'), trigger: 'blur' }],
|
||||
wx_key_content: [{ required: true, validator: createRequiredValidator('微信支付密钥内容'), trigger: 'blur' }],
|
||||
wx_notify_url: [
|
||||
{ required: true, validator: createRequiredValidator('微信支付回调地址'), trigger: 'blur' },
|
||||
{ validator: urlValidator, trigger: 'blur' }
|
||||
],
|
||||
fy_api_url: [
|
||||
{ required: true, validator: createRequiredValidator('富友API地址'), trigger: 'blur' },
|
||||
{ validator: urlValidator, trigger: 'blur' }
|
||||
],
|
||||
fy_ins_cd: [{ required: true, validator: createRequiredValidator('富友机构号'), trigger: 'blur' }],
|
||||
fy_mchnt_cd: [{ required: true, validator: createRequiredValidator('富友商户号'), trigger: 'blur' }],
|
||||
fy_term_id: [{ required: true, validator: createRequiredValidator('富友终端号'), trigger: 'blur' }],
|
||||
fy_private_key: [{ required: true, validator: createRequiredValidator('富友私钥'), trigger: 'blur' }],
|
||||
fy_public_key: [{ required: true, validator: createRequiredValidator('富友公钥'), trigger: 'blur' }],
|
||||
fy_notify_url: [
|
||||
{ required: true, validator: createRequiredValidator('富友支付回调地址'), trigger: 'blur' },
|
||||
{ validator: urlValidator, trigger: 'blur' }
|
||||
]
|
||||
// 其他字段都是可选的,只验证URL格式
|
||||
oa_oauth_redirect_url: [{ validator: urlValidator, trigger: 'blur' }],
|
||||
wx_notify_url: [{ validator: urlValidator, trigger: 'blur' }],
|
||||
fy_api_url: [{ validator: urlValidator, trigger: 'blur' }],
|
||||
fy_notify_url: [{ validator: urlValidator, trigger: 'blur' }]
|
||||
})
|
||||
|
||||
const form = reactive({
|
||||
@@ -721,6 +665,7 @@
|
||||
const getProviderTypeText = (type: PaymentProviderType): string => {
|
||||
const typeMap: Record<PaymentProviderType, string> = {
|
||||
wechat: '微信直连',
|
||||
wechat_v2: '微信直连V2',
|
||||
fuiou: '富友支付'
|
||||
}
|
||||
return typeMap[type] || type
|
||||
@@ -728,7 +673,7 @@
|
||||
|
||||
// 获取商户号
|
||||
const getMerchantId = (row: WechatConfig): string => {
|
||||
if (row.provider_type === 'wechat') {
|
||||
if (row.provider_type === 'wechat' || row.provider_type === 'wechat_v2') {
|
||||
return row.wx_mch_id || '-'
|
||||
}
|
||||
if (row.provider_type === 'fuiou') {
|
||||
@@ -739,7 +684,7 @@
|
||||
|
||||
// 获取支付回调地址
|
||||
const getNotifyUrl = (row: WechatConfig): string => {
|
||||
if (row.provider_type === 'wechat') {
|
||||
if (row.provider_type === 'wechat' || row.provider_type === 'wechat_v2') {
|
||||
return row.wx_notify_url || '-'
|
||||
}
|
||||
if (row.provider_type === 'fuiou') {
|
||||
|
||||
Reference in New Issue
Block a user