fix: bug
All checks were successful
构建并部署前端到测试环境 / build-and-deploy (push) Successful in 7m11s

This commit is contained in:
sexygoat
2026-04-24 18:39:39 +08:00
parent 2d6b5d7903
commit 17c299e4ce
27 changed files with 500 additions and 481 deletions

View File

@@ -105,7 +105,7 @@
})
const validateRefundAmount = (rule: any, value: number, callback: any) => {
if (value === undefined || value === null || value === 0) {
if (value === undefined || value === null) {
callback(new Error('请输入申请退款金额'))
} else if (value > formData.actual_received_amount) {
callback(new Error('申请退款金额不能大于实收金额'))

View File

@@ -1,5 +1,5 @@
<template>
<ElDialog v-model="visible" title="设置实名认证策略" width="500px">
<ElDialog v-model="visible" title="设置实名认证策略" width="35%">
<ElForm ref="formRef" :model="form" :rules="rules" label-width="120px">
<ElFormItem label="资产标识">
<span style="font-weight: bold; color: #409eff">{{ assetIdentifier }}</span>
@@ -21,7 +21,9 @@
<p>说明</p>
<p> <strong>无需实名</strong>用户使用设备无需进行实名认证</p>
<p> <strong>先实名后充值/购买</strong>用户必须先完成实名认证才能进行充值或购买套餐</p>
<p> <strong>先充值/购买后实名</strong>用户可以先充值或购买套餐之后需要完成实名认证</p>
<p
> <strong>先充值/购买后实名</strong>用户可以先充值或购买套餐之后需要完成实名认证</p
>
</div>
</ElFormItem>
</ElForm>

View File

@@ -1,136 +0,0 @@
<template>
<ElDialog v-model="visible" title="设置WiFi" width="500px" @close="handleClose">
<ElForm ref="formRef" :model="formData" :rules="rules" label-width="120px">
<ElFormItem label="设备信息">
<span style="font-weight: bold; color: #409eff">{{ deviceInfo }}</span>
</ElFormItem>
<ElFormItem label="WiFi状态" prop="enabled">
<ElRadioGroup v-model="formData.enabled">
<ElRadio :value="1">启用</ElRadio>
<ElRadio :value="0">禁用</ElRadio>
</ElRadioGroup>
</ElFormItem>
<ElFormItem label="WiFi名称" prop="ssid">
<ElInput
v-model="formData.ssid"
placeholder="请输入WiFi名称1-32个字符"
maxlength="32"
show-word-limit
clearable
autocomplete="off"
/>
</ElFormItem>
<ElFormItem label="WiFi密码" prop="password">
<ElInput
v-model="formData.password"
type="password"
placeholder="请输入WiFi密码8-63个字符"
maxlength="63"
show-word-limit
show-password
clearable
autocomplete="off"
/>
</ElFormItem>
</ElForm>
<template #footer>
<ElButton @click="visible = false">取消</ElButton>
<ElButton type="primary" @click="handleConfirm" :loading="confirmLoading">
确认设置
</ElButton>
</template>
</ElDialog>
</template>
<script setup lang="ts">
import { ref, reactive, watch } from 'vue'
import {
ElDialog,
ElForm,
ElFormItem,
ElInput,
ElButton,
ElRadioGroup,
ElRadio
} from 'element-plus'
import type { FormInstance, FormRules } from 'element-plus'
interface Props {
modelValue: boolean
deviceInfo: string
loading?: boolean
}
interface Emits {
(e: 'update:modelValue', value: boolean): void
(e: 'confirm', data: { enabled: number; ssid: string; password: string }): void
}
const props = withDefaults(defineProps<Props>(), {
loading: false
})
const emit = defineEmits<Emits>()
const visible = ref(props.modelValue)
const confirmLoading = ref(props.loading)
const formRef = ref<FormInstance>()
const formData = reactive({
enabled: 1,
ssid: '',
password: ''
})
const rules = reactive<FormRules>({
ssid: [
{ required: true, message: '请输入WiFi名称', trigger: 'blur' },
{ min: 1, max: 32, message: 'WiFi名称长度为1-32个字符', trigger: 'blur' }
],
password: [
{ required: true, message: '请输入WiFi密码', trigger: 'blur' },
{ min: 8, max: 63, message: 'WiFi密码长度为8-63个字符', trigger: 'blur' }
]
})
watch(
() => props.modelValue,
(val) => {
visible.value = val
if (val) {
formData.enabled = 1
formData.ssid = ''
formData.password = ''
}
}
)
watch(visible, (val) => {
emit('update:modelValue', val)
})
watch(
() => props.loading,
(val) => {
confirmLoading.value = val
}
)
const handleClose = () => {
formRef.value?.resetFields()
}
const handleConfirm = async () => {
if (!formRef.value) return
await formRef.value.validate((valid) => {
if (valid) {
emit('confirm', {
enabled: formData.enabled,
ssid: formData.ssid,
password: formData.password
})
}
})
}
</script>

View File

@@ -216,7 +216,8 @@ export interface AssetPackageUsageRecord {
master_usage_id?: number | null // 主套餐 ID加油包时有值
priority?: number // 优先级
created_at?: string // 创建时间
order_no?: string // 订单
order_id?: number // 订单ID
refund_id?: number // 退款ID有退款时才有值
}
/**

View File

@@ -587,8 +587,6 @@
}
getAccountList()
loadShopList()
loadEnterpriseList()
})
// 加载所有角色列表
@@ -597,7 +595,7 @@
const params: any = {
page: 1,
page_size: keyword ? 100 : 20, // 搜索时加载更多默认20条
role_type: 1
role_type: currentAccountType.value === 2 ? 1 : 2
}
if (keyword) {
params.role_name = keyword
@@ -646,6 +644,10 @@
// 显示分配角色对话框
const showRoleDialog = async (row: any) => {
if (row.user_type === 1) {
ElMessage.warning('超级管理员无法分配角色')
return
}
currentAccountId.value = row.id
currentAccountName.value = row.username
currentAccountType.value = row.user_type
@@ -1019,7 +1021,7 @@
.role-info {
display: flex;
flex: 1;
gap: 8px;
justify-content: space-between;
align-items: center;
}

View File

@@ -199,7 +199,7 @@
{{ getRealnamePolicyName(scope.row.realname_policy) }}
</template>
</ElTableColumn>
<ElTableColumn label="实名时间" width="180">
<ElTableColumn label="实名时间" width="170">
<template #default="scope">
{{ scope.row.real_name_at ? formatDateTime(scope.row.real_name_at) : '-' }}
</template>

View File

@@ -36,10 +36,17 @@
<div class="flow-stat-item">
<span class="flow-stat-label">总量</span>
<span class="flow-stat-value">
{{ formatDataSize(currentPackage.data_limit_mb || currentPackage.package_total_data || 0) }}
{{
formatDataSize(
currentPackage.data_limit_mb || currentPackage.package_total_data || 0
)
}}
</span>
</div>
<div v-if="isAdminOrPlatform && currentPackage.enable_virtual_data" class="flow-stat-item">
<div
v-if="isAdminOrPlatform && currentPackage.enable_virtual_data"
class="flow-stat-item"
>
<span class="flow-stat-label">实际可用</span>
<span class="flow-stat-value">
{{ formatDataSize(currentPackage.virtual_limit_mb || 0) }}
@@ -52,7 +59,8 @@
formatDataSize(
currentPackage.enable_virtual_data
? currentPackage.virtual_remain_mb || 0
: (currentPackage.data_limit_mb || currentPackage.package_total_data || 0) - (currentPackage.data_usage_mb || 0)
: (currentPackage.data_limit_mb || currentPackage.package_total_data || 0) -
(currentPackage.data_usage_mb || 0)
)
}}
</span>
@@ -62,13 +70,29 @@
<ElProgress
:percentage="
currentPackage.enable_virtual_data
? getUsageProgress(currentPackage.virtual_data_used || 0, currentPackage.virtual_data_total || 0)
: getUsageProgress(currentPackage.real_data_used || 0, currentPackage.real_data_total || 0)
? getUsageProgress(
currentPackage.virtual_data_used || 0,
currentPackage.virtual_data_total || 0
)
: getUsageProgress(
currentPackage.real_data_used || 0,
currentPackage.real_data_total || 0
)
"
:color="
currentPackage.enable_virtual_data
? getProgressColorByPercentage(getUsageProgress(currentPackage.virtual_data_used || 0, currentPackage.virtual_data_total || 0))
: getProgressColorByPercentage(getUsageProgress(currentPackage.real_data_used || 0, currentPackage.real_data_total || 0))
? getProgressColorByPercentage(
getUsageProgress(
currentPackage.virtual_data_used || 0,
currentPackage.virtual_data_total || 0
)
)
: getProgressColorByPercentage(
getUsageProgress(
currentPackage.real_data_used || 0,
currentPackage.real_data_total || 0
)
)
"
:stroke-width="14"
/>
@@ -89,7 +113,10 @@
<ElDescriptionsItem label="套餐类型">
{{ getPackageTypeName(currentPackage.package_type) }}
</ElDescriptionsItem>
<ElDescriptionsItem v-if="isAdminOrPlatform && currentPackage.enable_virtual_data" label="虚流量比例">
<ElDescriptionsItem
v-if="isAdminOrPlatform && currentPackage.enable_virtual_data"
label="虚流量比例"
>
{{ currentPackage.virtual_ratio || '-' }}
</ElDescriptionsItem>
<ElDescriptionsItem label="开始时间">
@@ -98,7 +125,7 @@
<ElDescriptionsItem label="到期时间">
{{ formatDateTime(currentPackage.expire_time) || '-' }}
</ElDescriptionsItem>
<ElDescriptionsItem label="购买时间">
<ElDescriptionsItem label="下单时间">
{{ formatDateTime(currentPackage.created_at) || '-' }}
</ElDescriptionsItem>
<ElDescriptionsItem v-if="currentPackage.duration_days" label="套餐时长">
@@ -128,12 +155,8 @@
import { formatDateTime } from '@/utils/business/format'
import type { PackageInfo } from '../types'
const {
formatAmount,
formatDataSize,
getUsageProgress,
getProgressColorByPercentage
} = useAssetFormatters()
const { formatAmount, formatDataSize, getUsageProgress, getProgressColorByPercentage } =
useAssetFormatters()
const userStore = useUserStore()
const { info: userInfo } = storeToRefs(userStore)

View File

@@ -25,7 +25,19 @@
</ElEmpty>
<div v-else-if="packageList && packageList.length > 0" class="table-scroll-container">
<ElTable :data="packageList" class="package-table" border>
<ElTableColumn prop="order_no" label="订单号" width="180" show-overflow-tooltip />
<ElTableColumn label="订单号" width="240">
<template #default="scope">
<ElButton
type="primary"
link
@click="handleOrderNoClick(scope.row)"
v-if="hasAuth('order:detail')"
>
{{ scope.row.order_no }}
</ElButton>
<span v-else>{{ scope.row.order_no }}</span>
</template>
</ElTableColumn>
<ElTableColumn label="套餐名称" width="150">
<template #default="scope">
<ElButton
@@ -50,11 +62,6 @@
</ElTag>
</template>
</ElTableColumn>
<ElTableColumn prop="data_limit_mb" label="总流量" width="120">
<template #default="scope">
{{ formatDataSize(scope.row.data_limit_mb) }}
</template>
</ElTableColumn>
<ElTableColumn label="流量" min-width="320">
<template #default="scope">
<div class="traffic-progress">
@@ -108,12 +115,12 @@
{{ formatDateTime(scope.row.expires_at) }}
</template>
</ElTableColumn>
<ElTableColumn prop="created_at" label="购买时间" width="170" show-overflow-tooltip>
<ElTableColumn prop="created_at" label="下单时间" width="170" show-overflow-tooltip>
<template #default="scope">
{{ formatDateTime(scope.row.created_at) }}
</template>
</ElTableColumn>
<ElTableColumn label="操作" width="100" fixed="right">
<ElTableColumn label="操作" width="120" fixed="right">
<template #default="scope">
<ElButton
v-if="scope.row.status !== 4 && hasAuth('package:create_refund')"
@@ -123,6 +130,18 @@
>
退款申请
</ElButton>
<ElButton
v-if="
scope.row.status === 4 &&
scope.row.refund_id &&
hasAuth('refund:package_list_detail')
"
type="primary"
link
@click="handleViewRefundDetail(scope.row)"
>
退款详情
</ElButton>
</template>
</ElTableColumn>
</ElTable>
@@ -217,6 +236,8 @@
(e: 'page-change', page: number): void
(e: 'size-change', size: number): void
(e: 'navigateToDevice', deviceNo: string): void
(e: 'navigateToOrder', orderId: number): void
(e: 'navigateToRefund', refundId: number): void
(e: 'refresh'): void
}
@@ -262,6 +283,24 @@
emit('showDailyRecords', { packageRow })
}
// 点击订单号
const handleOrderNoClick = (packageRow: PackageInfo) => {
if (!hasAuth('order:package_list_detail')) {
ElMessage.warning('您没有查看订单详情的权限')
return
}
emit('navigateToOrder', packageRow.order_id!)
}
// 查看退款详情
const handleViewRefundDetail = (packageRow: PackageInfo) => {
if (!hasAuth('refund:detail')) {
ElMessage.warning('您没有查看退款详情的权限')
return
}
emit('navigateToRefund', packageRow.refund_id!)
}
const handleShowRecharge = () => {
emit('showRecharge')
}

View File

@@ -1,6 +1,6 @@
<template>
<ElDialog v-model="visible" title="设置切卡模式" width="500px">
<ElForm ref="formRef" :model="form" :rules="rules" label-width="120px">
<ElForm ref="formRef" :model="form" :rules="rules" label-width="80px">
<ElFormItem label="设备标识">
<span style="font-weight: bold; color: #409eff">{{ deviceIdentifier }}</span>
</ElFormItem>

View File

@@ -1,6 +1,6 @@
<template>
<ElDialog v-model="visible" title="设置WiFi" width="500px" :append-to-body="true">
<ElForm ref="formRef" :model="form" :rules="rules" label-width="120px">
<ElDialog v-model="visible" title="设置WiFi" width="30%" :append-to-body="true">
<ElForm ref="formRef" :model="form" :rules="rules" label-width="80px" autocomplete="off">
<ElFormItem label="WiFi状态" prop="enabled">
<ElRadioGroup v-model="form.enabled">
<ElRadio :value="1">启用</ElRadio>
@@ -15,6 +15,7 @@
show-word-limit
clearable
autocomplete="off"
name="wifi_ssid"
/>
</ElFormItem>
<ElFormItem label="WiFi密码" prop="password">
@@ -27,6 +28,7 @@
show-password
clearable
autocomplete="off"
name="wifi_password"
/>
</ElFormItem>
</ElForm>
@@ -53,14 +55,33 @@
interface Props {
modelValue: boolean
cardNo?: string // 流量卡号ICCID
deviceIdentifier?: string // 设备标识IMEI
wifiEnabled?: number // WiFi启用状态
wifiSsid?: string // WiFi名称
wifiPassword?: string // WiFi密码
}
interface Emits {
(e: 'update:modelValue', value: boolean): void
(e: 'confirm', data: { card_no: string; enabled: number; ssid: string; password: string }): void
(
e: 'confirm',
data: {
deviceIdentifier?: string
card_no: string
enabled: number
ssid: string
password: string
}
): void
}
const props = defineProps<Props>()
const props = withDefaults(defineProps<Props>(), {
cardNo: '',
deviceIdentifier: '',
wifiEnabled: 1,
wifiSsid: '',
wifiPassword: ''
})
const emit = defineEmits<Emits>()
const formRef = ref<FormInstance>()
@@ -91,9 +112,9 @@
// 监听对话框打开,重置表单
watch(visible, (newVal) => {
if (newVal) {
form.enabled = 1
form.ssid = ''
form.password = ''
form.enabled = props.wifiEnabled ?? 1
form.ssid = props.wifiSsid ?? ''
form.password = props.wifiPassword ?? ''
}
})
@@ -107,6 +128,7 @@
try {
await formRef.value.validate()
emit('confirm', {
deviceIdentifier: props.deviceIdentifier,
card_no: props.cardNo || '',
enabled: form.enabled,
ssid: form.ssid,

View File

@@ -65,6 +65,8 @@
@page-change="handlePackagePageChange"
@size-change="handlePackageSizeChange"
@navigate-to-device="handleNavigateToDevice"
@navigate-to-order="handleNavigateToOrder"
@navigate-to-refund="handleNavigateToRefund"
@refresh="handlePackageRefresh"
/>
</div>
@@ -106,6 +108,9 @@
<WiFiConfigDialog
v-model="setWiFiDialogVisible"
:card-no="deviceRealtime?.current_iccid"
:wifi-enabled="deviceRealtime?.wifi_enabled ? 1 : 0"
:wifi-ssid="deviceRealtime?.ssid || ''"
:wifi-password="deviceRealtime?.wifi_password || ''"
@confirm="handleConfirmSetWiFi"
/>
<PackageRechargeDialog
@@ -147,8 +152,9 @@
<script setup lang="ts">
import { ref, watch, onMounted, nextTick } from 'vue'
import { useRoute } from 'vue-router'
import { useRoute, useRouter } from 'vue-router'
import { ElMessage, ElCard, ElEmpty } from 'element-plus'
import { RoutesAlias } from '@/router/routesAlias'
// 引入子组件
import AssetSearchCard from './components/AssetSearchCard.vue'
@@ -179,6 +185,7 @@
defineOptions({ name: 'SingleCard' })
const route = useRoute()
const router = useRouter()
// ========== 组件引用 ==========
const assetSearchCardRef = ref<InstanceType<typeof AssetSearchCard>>()
@@ -560,6 +567,20 @@
await handleSearch({ identifier: deviceNo })
}
/**
* 跳转到订单详情
*/
const handleNavigateToOrder = (orderId: number) => {
router.push(`${RoutesAlias.OrderDetail}/${orderId}`)
}
/**
* 跳转到退款详情
*/
const handleNavigateToRefund = (refundId: number) => {
router.push(`${RoutesAlias.RefundDetail}/${refundId}`)
}
/**
* URL参数自动加载
*/

View File

@@ -351,7 +351,7 @@
</ElSelect>
</ElFormItem>
</ElCol>
<ElCol :span="8">
<ElCol :span="9">
<ElFormItem label="ICCID" prop="iot_card_id">
<ElSelect
v-model="bindCardForm.iot_card_id"
@@ -401,6 +401,7 @@
</ElCol>
<ElCol :span="3">
<ElButton
v-permission="'device:bind_card'"
type="primary"
@click="handleConfirmBindCard"
:loading="bindCardLoading"
@@ -419,11 +420,9 @@
</div>
<div v-else>
<ElTable :data="deviceCards" border style="width: 100%">
<ElTableColumn prop="slot_position" label="插槽位置" width="120" align="center">
<ElTableColumn prop="slot_position" label="插槽位置" width="120">
<template #default="{ row }">
<div
style="display: flex; gap: 10px; align-items: center; justify-content: center"
>
<div style="display: flex; gap: 10px; align-items: center">
<span>SIM-{{ row.slot_position }}</span>
<ElTag v-if="row.is_current" type="success" size="small">当前</ElTag>
</div>
@@ -431,7 +430,7 @@
</ElTableColumn>
<ElTableColumn prop="iccid" label="ICCID" min-width="120" />
<ElTableColumn prop="msisdn" label="接入号" width="160" />
<ElTableColumn prop="network_status" label="网络状态" width="100" align="center">
<ElTableColumn prop="network_status" label="网络状态" width="100">
<template #default="{ row }">
<ElTag :type="getNetworkStatusTagType(row.network_status)">
{{ getNetworkStatusText(row.network_status) }}
@@ -445,7 +444,13 @@
</ElTableColumn>
<ElTableColumn label="操作" width="100" fixed="right" align="center">
<template #default="{ row }">
<ElButton type="danger" size="small" link @click="handleUnbindCard(row)">
<ElButton
v-permission="'device:unbind_card'"
type="danger"
size="small"
link
@click="handleUnbindCard(row)"
>
解绑
</ElButton>
</template>
@@ -470,93 +475,13 @@
@confirm="handleConfirmSwitchCard"
/>
<!-- 设置WiFi对话框 -->
<ElDialog v-model="setWiFiDialogVisible" title="设置WiFi" width="500px">
<ElForm
ref="setWiFiFormRef"
:model="setWiFiForm"
:rules="setWiFiRules"
label-width="120px"
>
<ElFormItem label="设备号">
<span style="font-weight: bold; color: #409eff">{{ currentOperatingImei }}</span>
</ElFormItem>
<ElFormItem label="WiFi状态" prop="enabled">
<ElRadioGroup v-model="setWiFiForm.enabled">
<ElRadio :value="1">启用</ElRadio>
<ElRadio :value="0">禁用</ElRadio>
</ElRadioGroup>
</ElFormItem>
<ElFormItem label="WiFi名称" prop="ssid">
<ElInput
v-model="setWiFiForm.ssid"
placeholder="请输入WiFi名称1-32个字符"
maxlength="32"
show-word-limit
clearable
autocomplete="off"
/>
</ElFormItem>
<ElFormItem label="WiFi密码" prop="password">
<ElInput
v-model="setWiFiForm.password"
type="password"
placeholder="请输入WiFi密码8-63个字符"
maxlength="63"
show-word-limit
show-password
clearable
autocomplete="off"
/>
</ElFormItem>
</ElForm>
<template #footer>
<ElButton @click="setWiFiDialogVisible = false">取消</ElButton>
<ElButton type="primary" @click="handleConfirmSetWiFi" :loading="setWiFiLoading">
确认设置
</ElButton>
</template>
</ElDialog>
<!-- 设置切卡模式对话框 -->
<ElDialog v-model="switchModeDialogVisible" title="设置切卡模式" width="500px">
<ElForm
ref="switchModeFormRef"
:model="switchModeForm"
:rules="switchModeRules"
label-width="120px"
>
<ElFormItem label="设备标识">
<span style="font-weight: bold; color: #409eff">{{
currentOperatingDeviceIdentifier
}}</span>
</ElFormItem>
<ElFormItem label="当前模式">
<ElTag :type="currentDeviceSwitchMode === 0 ? 'success' : 'warning'">
{{ currentDeviceSwitchMode === 0 ? '自动切卡' : '手动切卡' }}
</ElTag>
</ElFormItem>
<ElFormItem label="切卡模式" prop="switch_mode">
<ElRadioGroup v-model="switchModeForm.switch_mode">
<ElRadio :value="0">自动切卡</ElRadio>
<ElRadio :value="1">手动切卡</ElRadio>
</ElRadioGroup>
</ElFormItem>
<ElFormItem>
<div style="font-size: 12px; color: #909399; line-height: 1.6">
<p>说明</p>
<p> <strong>自动切卡</strong>设备根据信号强度自动切换到最优的SIM卡</p>
<p> <strong>手动切卡</strong>需要手动触发切换SIM卡操作</p>
</div>
</ElFormItem>
</ElForm>
<template #footer>
<ElButton @click="switchModeDialogVisible = false">取消</ElButton>
<ElButton type="primary" @click="handleConfirmSwitchMode" :loading="switchModeLoading">
确认设置
</ElButton>
</template>
</ElDialog>
<SwitchModeDialog
v-model="switchModeDialogVisible"
:device-identifier="currentOperatingDeviceIdentifier"
:current-mode="currentDeviceSwitchMode"
@confirm="handleConfirmSwitchMode"
/>
<!-- 实名认证策略对话框 -->
<RealnamePolicyDialog
@@ -586,6 +511,7 @@
import { Loading } from '@element-plus/icons-vue'
import type { FormInstance, FormRules } from 'element-plus'
import SwitchCardDialog from '@/components/device/SwitchCardDialog.vue'
import SwitchModeDialog from '@/views/asset-management/asset-information/components/dialogs/SwitchModeDialog.vue'
import type {
Device,
DeviceStatus,
@@ -663,6 +589,7 @@
// 搜索表单店铺/系列选项
const shopOptions = ref<any[]>([])
const searchSeriesOptions = ref<any[]>([])
const searchBatchNoOptions = ref<any[]>([])
// 设备详情弹窗相关
const deviceDetailDialogVisible = ref(false)
@@ -699,37 +626,11 @@
const deviceBindingCards = ref<any[]>([]) // 设备绑定的卡列表
const loadingDeviceCards = ref(false) // 加载设备绑定卡列表的状态
const setWiFiDialogVisible = ref(false)
const setWiFiLoading = ref(false)
const setWiFiFormRef = ref<FormInstance>()
const setWiFiForm = reactive({
enabled: 1,
ssid: '',
password: ''
})
const setWiFiRules = reactive<FormRules>({
ssid: [
{ required: true, message: '请输入WiFi名称', trigger: 'blur' },
{ min: 1, max: 32, message: 'WiFi名称长度为1-32个字符', trigger: 'blur' }
],
password: [
{ required: true, message: '请输入WiFi密码', trigger: 'blur' },
{ min: 8, max: 63, message: 'WiFi密码长度为8-63个字符', trigger: 'blur' }
]
})
// 切换模式相关
const switchModeDialogVisible = ref(false)
const switchModeLoading = ref(false)
const switchModeFormRef = ref<FormInstance>()
const currentOperatingDeviceIdentifier = ref<string>('')
const currentDeviceSwitchMode = ref<number>(0)
const switchModeForm = reactive({
switch_mode: 0
})
const switchModeRules = reactive<FormRules>({
switch_mode: [{ required: true, message: '请选择切卡模式', trigger: 'change' }]
})
// 实名认证策略相关
const realnamePolicyDialogVisible = ref(false)
@@ -754,6 +655,34 @@
// 搜索表单
const searchForm = reactive({ ...initialSearchState })
// 搜索批次号(用于搜索表单)
const loadSearchBatchNoOptions = async (batchNo?: string) => {
try {
const params: any = {
page: 1,
page_size: 20
}
if (batchNo) {
params.batch_no = batchNo
}
const res = await CardService.getIotCardImportTasks(params)
if (res.code === 0) {
searchBatchNoOptions.value = res.data.items || []
}
} catch (error) {
console.error('加载批次号选项失败:', error)
}
}
// 搜索批次号
const handleSearchBatchNo = (query: string) => {
if (query) {
loadSearchBatchNoOptions(query)
} else {
loadSearchBatchNoOptions()
}
}
// 搜索表单配置
const searchFormItems: SearchFormItem[] = [
{
@@ -792,11 +721,20 @@
{
label: '批次号',
prop: 'batch_no',
type: 'input',
type: 'select',
config: {
clearable: true,
placeholder: '请输入批次号'
}
filterable: true,
remote: true,
remoteMethod: handleSearchBatchNo,
loading: false,
placeholder: '请选择或搜索批次号'
},
options: () =>
searchBatchNoOptions.value.map((b) => ({
label: b.batch_no,
value: b.batch_no
}))
},
{
label: '设备类型',
@@ -941,6 +879,7 @@
bindCardForm.search_type = 'iccid'
bindCardForm.iot_card_id = undefined
bindCardForm.slot_position = 1
bindCardFormRef.value?.resetFields()
// 加载未绑定设备的卡列表
await Promise.all([loadDeviceCards(device.virtual_no), loadDefaultIotCards()])
}
@@ -1338,8 +1277,6 @@
let isFirstActivation = true
onMounted(() => {
getTableData()
searchShops('')
searchSeries('')
})
// 当页面被 keep-alive 激活时自动刷新数据
@@ -1492,6 +1429,7 @@
allocateForm.target_shop_id = undefined
allocateForm.remark = ''
allocateResult.value = null
shopCascadeOptions.value = []
allocateDialogVisible.value = true
}
@@ -1505,7 +1443,7 @@
try {
const data = {
device_ids: selectedDevices.value.map((d) => d.id),
target_shop_id: allocateForm.target_shop_id![0],
target_shop_id: allocateForm.target_shop_id![allocateForm.target_shop_id.length - 1],
remark: allocateForm.remark
}
const res = await DeviceService.allocateDevices(data)
@@ -1720,15 +1658,6 @@
await showSwitchCardDialog(imei)
break
}
case 'set-wifi': {
const imei = device?.imei || (await getDeviceImei(deviceNo))
if (!imei) {
ElMessage.error('无法获取设备IMEI,无法执行WiFi设置操作')
return
}
showSetWiFiDialog(imei)
break
}
case 'manual-deactivate':
handleManualDeactivateDevice()
break
@@ -1926,77 +1855,33 @@
}
}
// 显示设置WiFi对话框
const showSetWiFiDialog = (imei: string) => {
currentOperatingImei.value = imei
setWiFiForm.enabled = 1
setWiFiForm.ssid = ''
setWiFiForm.password = ''
setWiFiDialogVisible.value = true
}
// 确认设置WiFi
const handleConfirmSetWiFi = async () => {
if (!setWiFiFormRef.value) return
await setWiFiFormRef.value.validate(async (valid) => {
if (valid) {
setWiFiLoading.value = true
try {
const res = await DeviceService.setWiFi(currentOperatingImei.value, {
enabled: setWiFiForm.enabled,
ssid: setWiFiForm.ssid,
password: setWiFiForm.password
})
if (res.code === 0) {
ElMessage.success('WiFi设置成功')
setWiFiDialogVisible.value = false
} else {
ElMessage.error(res.msg || '设置失败')
}
} catch (error: any) {
console.error('设置WiFi失败:', error)
} finally {
setWiFiLoading.value = false
}
}
})
}
// 显示切换模式对话框
const showSwitchModeDialog = (deviceIdentifier: string, currentMode?: number) => {
currentOperatingDeviceIdentifier.value = deviceIdentifier
currentDeviceSwitchMode.value = currentMode ?? 0
switchModeForm.switch_mode = currentMode ?? 0
switchModeDialogVisible.value = true
}
// 确认切换模式
const handleConfirmSwitchMode = async () => {
if (!switchModeFormRef.value) return
await switchModeFormRef.value.validate(async (valid) => {
if (valid) {
switchModeLoading.value = true
try {
const res = await DeviceService.setSwitchMode(
currentOperatingDeviceIdentifier.value,
switchModeForm.switch_mode
)
if (res.code === 0) {
ElMessage.success('设置切卡模式成功')
switchModeDialogVisible.value = false
await getTableData()
} else {
ElMessage.error(res.msg || '设置切卡模式失败')
}
} catch (error: any) {
console.error('设置切卡模式失败:', error)
} finally {
switchModeLoading.value = false
}
const handleConfirmSwitchMode = async (data: { switch_mode: number }) => {
switchModeLoading.value = true
try {
const res = await DeviceService.setSwitchMode(
currentOperatingDeviceIdentifier.value,
data.switch_mode
)
if (res.code === 0) {
ElMessage.success('设置切卡模式成功')
switchModeDialogVisible.value = false
await getTableData()
} else {
ElMessage.error(res.msg || '设置切卡模式失败')
}
})
} catch (error: any) {
console.error('设置切卡模式失败:', error)
} finally {
switchModeLoading.value = false
}
}
// 设备操作菜单项配置
@@ -2048,14 +1933,6 @@
})
}
if (hasAuth('device:set_wifi')) {
moreActions.push({
label: '设置WiFi',
handler: () => handleDeviceOperation('set-wifi', row.virtual_no, row),
type: 'primary'
})
}
if (hasAuth('device:clear_series')) {
moreActions.push({
label: '清除关联',

View File

@@ -140,13 +140,20 @@
>
<ElSelect
v-model="allocateForm.carrier_id"
placeholder="请选择运营商"
placeholder="请选择或搜索运营商"
clearable
filterable
remote
:remote-method="handleSearchAllocateCarrier"
:loading="allocateCarrierLoading"
style="width: 100%"
>
<ElOption label="中国移动" :value="1" />
<ElOption label="中国联通" :value="2" />
<ElOption label="中国电信" :value="3" />
<ElOption
v-for="item in allocateCarrierOptions"
:key="item.id"
:label="item.carrier_name"
:value="item.id"
/>
</ElSelect>
</ElFormItem>
<ElFormItem
@@ -166,10 +173,25 @@
</ElSelect>
</ElFormItem>
<ElFormItem
v-if="allocateForm.selection_type === CardSelectionType.FILTER"
v-if="allocateForm.selection_type === CardSelectionType.FILTER && userInfo.user_type !== 3"
label="批次号"
>
<ElInput v-model="allocateForm.batch_no" placeholder="请输入批次号" />
<ElSelect
v-model="allocateForm.batch_no"
placeholder="请选择或搜索批次号"
clearable
filterable
remote
:remote-method="handleSearchAllocateBatchNo"
style="width: 100%"
>
<ElOption
v-for="item in allocateBatchNoOptions"
:key="item.id"
:label="item.batch_no"
:value="item.batch_no"
/>
</ElSelect>
</ElFormItem>
<ElFormItem label="备注">
@@ -235,20 +257,42 @@
>
<ElSelect
v-model="recallForm.carrier_id"
placeholder="请选择运营商"
placeholder="请选择或搜索运营商"
clearable
filterable
remote
:remote-method="handleSearchAllocateCarrier"
:loading="allocateCarrierLoading"
style="width: 100%"
>
<ElOption label="中国移动" :value="1" />
<ElOption label="中国联通" :value="2" />
<ElOption label="中国电信" :value="3" />
<ElOption
v-for="item in allocateCarrierOptions"
:key="item.id"
:label="item.carrier_name"
:value="item.id"
/>
</ElSelect>
</ElFormItem>
<ElFormItem
v-if="recallForm.selection_type === CardSelectionType.FILTER"
v-if="recallForm.selection_type === CardSelectionType.FILTER && userInfo.user_type !== 3"
label="批次号"
>
<ElInput v-model="recallForm.batch_no" placeholder="请输入批次号" />
<ElSelect
v-model="recallForm.batch_no"
placeholder="请选择或搜索批次号"
clearable
filterable
remote
:remote-method="handleSearchAllocateBatchNo"
style="width: 100%"
>
<ElOption
v-for="item in allocateBatchNoOptions"
:key="item.id"
:label="item.batch_no"
:value="item.batch_no"
/>
</ElSelect>
</ElFormItem>
<ElFormItem label="备注">
@@ -585,6 +629,8 @@
import type { SearchFormItem } from '@/types'
import { useCheckedColumns } from '@/composables/useCheckedColumns'
import { useAuth } from '@/composables/useAuth'
import { useUserStore } from '@/store/modules/user'
import { storeToRefs } from 'pinia'
import { formatDateTime } from '@/utils/business/format'
import ArtMenuRight from '@/components/core/others/ArtMenuRight.vue'
import type { MenuItemType } from '@/components/core/others/ArtMenuRight.vue'
@@ -602,6 +648,8 @@
defineOptions({ name: 'StandaloneCardList' })
const { hasAuth } = useAuth()
const userStore = useUserStore()
const { info: userInfo } = storeToRefs(userStore)
const router = useRouter()
const loading = ref(false)
@@ -646,6 +694,10 @@
const carrierLoading = ref(false)
const searchCarrierOptions = ref<any[]>([])
// 批量分配对话框运营商选项
const allocateCarrierOptions = ref<any[]>([])
const allocateCarrierLoading = ref(false)
// 加载搜索栏运营商选项默认加载10条
const loadSearchCarrierOptions = async (carrierName?: string) => {
try {
@@ -665,6 +717,37 @@
}
}
// 加载批量分配对话框运营商选项
const loadAllocateCarrierOptions = async (carrierName?: string) => {
try {
allocateCarrierLoading.value = true
const params: any = {
page: 1,
page_size: 20
}
if (carrierName) {
params.carrier_name = carrierName
}
const res = await CarrierService.getCarriers(params)
if (res.code === 0) {
allocateCarrierOptions.value = res.data.items || []
}
} catch (error) {
console.error('加载运营商选项失败:', error)
} finally {
allocateCarrierLoading.value = false
}
}
// 搜索批量分配对话框运营商
const handleSearchAllocateCarrier = (query: string) => {
if (query) {
loadAllocateCarrierOptions(query)
} else {
loadAllocateCarrierOptions()
}
}
// 搜索运营商(用于搜索栏)
const handleSearchCarrier = (query: string) => {
if (query) {
@@ -674,6 +757,37 @@
}
}
// 批量分配对话框批次号选项
const allocateBatchNoOptions = ref<any[]>([])
// 加载批量分配对话框批次号选项
const loadAllocateBatchNoOptions = async (batchNo?: string) => {
try {
const params: any = {
page: 1,
page_size: 20
}
if (batchNo) {
params.batch_no = batchNo
}
const res = await CardService.getIotCardImportTasks(params)
if (res.code === 0) {
allocateBatchNoOptions.value = res.data.items || []
}
} catch (error) {
console.error('加载批次号选项失败:', error)
}
}
// 搜索批量分配对话框批次号
const handleSearchAllocateBatchNo = (query: string) => {
if (query) {
loadAllocateBatchNoOptions(query)
} else {
loadAllocateBatchNoOptions()
}
}
// 套餐系列搜索相关
const searchSeriesOptions = ref<any[]>([])
@@ -939,22 +1053,7 @@
})
// 搜索表单配置
const formItems: SearchFormItem[] = [
{
label: '状态',
prop: 'status',
type: 'select',
config: {
clearable: true,
placeholder: '全部'
},
options: () => [
{ label: '在库', value: 1 },
{ label: '已分销', value: 2 },
{ label: '已激活', value: 3 },
{ label: '已停用', value: 4 }
]
},
const baseFormItems: SearchFormItem[] = [
{
label: 'ICCID',
prop: 'iccid',
@@ -983,13 +1082,19 @@
}))
},
{
label: 'MSISDN',
prop: 'msisdn',
type: 'input',
label: '状态',
prop: 'status',
type: 'select',
config: {
clearable: true,
placeholder: '请输入MSISDN'
}
placeholder: '全部'
},
options: () => [
{ label: '在库', value: 1 },
{ label: '已分销', value: 2 },
{ label: '已激活', value: 3 },
{ label: '已停用', value: 4 }
]
},
{
label: '卡虚拟号',
@@ -1000,6 +1105,15 @@
placeholder: '请输入卡虚拟号'
}
},
{
label: 'MSISDN',
prop: 'msisdn',
type: 'input',
config: {
clearable: true,
placeholder: '请输入MSISDN'
}
},
{
label: '绑定设备虚拟号',
prop: 'device_virtual_no',
@@ -1085,6 +1199,9 @@
}
]
// 搜索表单配置
const formItems: SearchFormItem[] = baseFormItems
// 列配置
const columnOptions = [
{ label: 'ICCID', prop: 'iccid' },
@@ -1521,6 +1638,8 @@
batch_no: '',
remark: ''
})
loadAllocateCarrierOptions()
loadAllocateBatchNoOptions()
if (allocateFormRef.value) {
allocateFormRef.value.resetFields()
}
@@ -1545,6 +1664,8 @@
if (recallFormRef.value) {
recallFormRef.value.resetFields()
}
loadAllocateCarrierOptions()
loadAllocateBatchNoOptions()
}
// 关闭批量分配对话框

View File

@@ -233,7 +233,6 @@
const columnOptions = [
{ label: '任务编号', prop: 'task_no' },
{ label: '任务状态', prop: 'status' },
{ label: '文件名', prop: 'file_name' },
{ label: '总数', prop: 'total_count' },
{ label: '成功数', prop: 'success_count' },
{ label: '失败数', prop: 'fail_count' },
@@ -241,6 +240,8 @@
{ label: '开始时间', prop: 'started_at' },
{ label: '完成时间', prop: 'completed_at' },
{ label: '错误信息', prop: 'error_message' },
{ label: '批次号', prop: 'batch_no' },
{ label: '文件名', prop: 'file_name' },
{ label: '创建时间', prop: 'created_at' }
]
@@ -311,12 +312,6 @@
return h(ElTag, { type: getStatusType(row.status) }, () => row.status_text)
}
},
{
prop: 'file_name',
label: '文件名',
minWidth: 180,
showOverflowTooltip: true
},
{
prop: 'total_count',
label: '总数',
@@ -343,6 +338,12 @@
label: '跳过数',
width: 80
},
{
prop: 'batch_no',
label: '批次号',
width: 180,
showOverflowTooltip: true
},
{
prop: 'started_at',
label: '开始时间',
@@ -363,6 +364,12 @@
showOverflowTooltip: true,
formatter: (row: DeviceImportTask) => row.error_message || '-'
},
{
prop: 'file_name',
label: '文件名',
minWidth: 180,
showOverflowTooltip: true
},
{
prop: 'created_at',
label: '创建时间',

View File

@@ -344,7 +344,6 @@
{ label: '任务状态', prop: 'status' },
{ label: '运营商', prop: 'carrier_name' },
{ label: '卡业务类型', prop: 'card_category' },
{ label: '文件名', prop: 'file_name' },
{ label: '总数', prop: 'total_count' },
{ label: '成功数', prop: 'success_count' },
{ label: '失败数', prop: 'fail_count' },
@@ -352,6 +351,8 @@
{ label: '开始时间', prop: 'started_at' },
{ label: '完成时间', prop: 'completed_at' },
{ label: '错误信息', prop: 'error_message' },
{ label: '批次号', prop: 'batch_no' },
{ label: '文件名', prop: 'file_name' },
{ label: '创建时间', prop: 'created_at' }
]
@@ -440,12 +441,6 @@
: row.card_category
}
},
{
prop: 'file_name',
label: '文件名',
minWidth: 250,
showOverflowTooltip: true
},
{
prop: 'total_count',
label: '总数',
@@ -472,6 +467,12 @@
label: '跳过数',
width: 80
},
{
prop: 'batch_no',
label: '批次号',
width: 180,
showOverflowTooltip: true
},
{
prop: 'started_at',
label: '开始时间',
@@ -492,6 +493,12 @@
showOverflowTooltip: true,
formatter: (row: IotCardImportTask) => row.error_message || '-'
},
{
prop: 'file_name',
label: '文件名',
minWidth: 250,
showOverflowTooltip: true
},
{
prop: 'created_at',
label: '创建时间',

View File

@@ -803,7 +803,7 @@
.role-info {
display: flex;
flex: 1;
gap: 8px;
justify-content: space-between;
align-items: center;
}

View File

@@ -172,9 +172,9 @@
}
}
// 返回列表
// 返回上一页
const handleBack = () => {
router.push(RoutesAlias.AgentRecharge)
router.back()
}
onMounted(() => {

View File

@@ -492,6 +492,14 @@
loadShops()
})
let isFirstActivation = true
onActivated(() => {
if (!isFirstActivation) {
getTableData()
}
isFirstActivation = false
})
// 构建树形数据
const buildTreeData = (items: ShopResponse[]) => {
const map = new Map<number, ShopResponse & { children?: ShopResponse[] }>()

View File

@@ -393,8 +393,9 @@
}
}
// 返回上一页
const handleBack = () => {
router.push(RoutesAlias.RefundManagement)
router.back()
}
onMounted(() => {

View File

@@ -560,6 +560,14 @@
searchOrdersForFilter('')
})
let isFirstActivation = true
onActivated(() => {
if (!isFirstActivation) {
getTableData()
}
isFirstActivation = false
})
// 搜索店铺(用于搜索表单)
const searchShops = async (query: string) => {
try {

View File

@@ -7,7 +7,7 @@
:items="searchFormItems"
show-expand
@reset="handleReset"
label-width="100"
label-width="90"
@search="handleSearch"
></ArtSearchBar>
@@ -421,8 +421,7 @@
config: {
maxlength: 50,
clearable: true
},
labelWidth: '100'
}
},
{
label: '资产标识符',
@@ -431,9 +430,8 @@
config: {
maxlength: 30,
clearable: true,
placeholder: 'ICCID/VirtualNo/IMEI/SN/MSISDN'
},
labelWidth: '100'
placeholder: 'ICCID/VirtualNo/IMEI/MSISDN/SN'
}
},
{
label: '买家手机号',
@@ -443,8 +441,24 @@
config: {
maxlength: 20,
clearable: true
},
labelWidth: '100'
}
},
{
label: '所属代理商',
prop: 'seller_shop_id',
type: 'select',
placeholder: '请选择所属代理商',
options: () =>
shopOptions.value.map((shop) => ({
label: shop.shop_name,
value: shop.id
})),
config: {
clearable: true,
filterable: true,
remote: true,
remoteMethod: (query: string) => searchShops(query)
}
},
{
label: '支付方式',
@@ -454,7 +468,7 @@
options: [
{ label: '钱包支付', value: 'wallet' },
{ label: '微信支付', value: 'wechat' },
{ label: '支付宝支付', value: 'alipay' },
// { label: '支付宝支付', value: 'alipay' },
{ label: '线下支付', value: 'offline' }
],
config: {
@@ -502,23 +516,6 @@
clearable: true
}
},
{
label: '所属代理商',
prop: 'seller_shop_id',
type: 'select',
placeholder: '请选择所属代理商',
options: () =>
shopOptions.value.map((shop) => ({
label: shop.shop_name,
value: shop.id
})),
config: {
clearable: true,
filterable: true,
remote: true,
remoteMethod: (query: string) => searchShops(query)
}
},
{
label: '订单渠道',
prop: 'purchase_role',
@@ -526,9 +523,9 @@
placeholder: '请选择订单渠道',
options: [
{ label: '自己购买', value: 'self_purchase' },
{ label: '上级代理购买', value: 'purchased_by_parent' },
{ label: '平台代购', value: 'purchased_by_platform' },
{ label: '给下级购买', value: 'purchase_for_subordinate' }
// { label: '上级代理购买', value: 'purchased_by_parent' },
{ label: '平台代购', value: 'purchased_by_platform' }
// { label: '给下级购买', value: 'purchase_for_subordinate' }
],
config: {
clearable: true
@@ -565,6 +562,7 @@
{ label: '资产标识符', prop: 'asset_identifier' },
{ label: '订单渠道', prop: 'purchase_role' },
{ label: '购买备注', prop: 'purchase_remark' },
{ label: '下单时间', prop: 'created_at' },
{ label: '操作者', prop: 'operator_name' },
{ label: '支付状态', prop: 'payment_status' },
{ label: '佣金状态', prop: 'commission_status_name' },
@@ -914,6 +912,7 @@
prop: 'asset_identifier',
label: '资产标识符',
width: 180,
showOverflowTooltip: true,
formatter: (row: Order) => row.asset_identifier || '-'
},
{
@@ -942,6 +941,12 @@
showOverflowTooltip: true,
formatter: (row: Order) => row.purchase_remark || '-'
},
{
prop: 'created_at',
label: '下单时间',
width: 180,
formatter: (row: Order) => formatDateTime(row.created_at)
},
{
prop: 'operator_name',
label: '操作者',

View File

@@ -363,7 +363,7 @@
</template>
<script setup lang="ts">
import { h } from 'vue'
import { h, watch } from 'vue'
import { useRouter } from 'vue-router'
import { PackageManageService, PackageSeriesService } from '@/api/modules'
import { ElMessage, ElMessageBox, ElTag, ElSwitch, ElInputNumber } from 'element-plus'
@@ -922,6 +922,13 @@
getTableData()
})
// 监听对话框打开,加载系列选项
watch(dialogVisible, (visible) => {
if (visible) {
loadSeriesOptions()
}
})
// 加载系列选项(用于新增/编辑对话框,默认加载10条)
const loadSeriesOptions = async (seriesName?: string) => {
seriesLoading.value = true

View File

@@ -48,7 +48,7 @@
<ElDialog
v-model="dialogVisible"
:title="dialogType === 'add' ? '新增套餐系列' : '编辑套餐系列'"
width="30%"
width="40%"
:close-on-click-modal="false"
>
<ElForm ref="formRef" :model="form" :rules="rules" label-width="120px">
@@ -291,7 +291,13 @@
<span class="title-text">强充配置</span>
</div>
<ElFormItem label="强充金额">
<ElFormItem label="启用强充">
<ElSwitch
v-model="form.one_time_commission_config.enable_force_recharge"
/>
</ElFormItem>
<ElFormItem label="强充金额" v-if="form.one_time_commission_config.enable_force_recharge">
<ElInputNumber
v-model="form.one_time_commission_config.force_amount"
:min="0"
@@ -305,7 +311,7 @@
>
</ElFormItem>
<ElFormItem label="强充计算类型">
<ElFormItem label="强充计算类型" v-if="form.one_time_commission_config.enable_force_recharge">
<ElRadioGroup v-model="form.one_time_commission_config.force_calc_type">
<ElRadio value="fixed">固定</ElRadio>
<ElRadio value="dynamic">动态</ElRadio>
@@ -483,7 +489,8 @@
{
label: '强充状态',
prop: 'enable_force_recharge',
formatter: (row: any) => (row.one_time_commission_config?.enable_force_recharge ? '启用' : '未启用')
formatter: (row: any) =>
row.one_time_commission_config?.enable_force_recharge ? '启用' : '未启用'
},
{
label: '强充金额',

View File

@@ -209,7 +209,7 @@
<ElDialog
v-model="dialogVisible"
:title="dialogType === 'add' ? '新增代理系列授权' : '编辑代理系列授权'"
width="40%"
width="50%"
:close-on-click-modal="false"
@closed="handleDialogClosed"
>
@@ -973,13 +973,11 @@
loading: shopLoading.value,
placeholder: '请选择或搜索分配者店铺'
},
options: () => [
{ label: '平台', value: 0 },
...searchAllocatorShopOptions.value.map((s) => ({
options: () =>
searchAllocatorShopOptions.value.map((s) => ({
label: s.shop_name,
value: s.id
}))
]
},
{
@@ -1337,10 +1335,6 @@
}
onMounted(() => {
loadSeriesOptions()
loadSearchSeriesOptions()
loadSearchShopOptions()
loadSearchAllocatorShopOptions()
getTableData()
})
@@ -1647,7 +1641,7 @@
// 搜索系列(用于搜索栏)
const handleSearchSeries = async (query: string) => {
if (!query) {
loadSearchSeriesOptions()
await loadSearchSeriesOptions()
return
}
try {
@@ -1668,7 +1662,7 @@
// 搜索店铺(用于搜索栏-被分配的店铺)
const handleSearchShop = async (query: string) => {
if (!query) {
loadSearchShopOptions()
await loadSearchShopOptions()
return
}
try {
@@ -1688,7 +1682,7 @@
// 搜索分配者店铺(用于搜索栏)
const handleSearchAllocatorShop = async (query: string) => {
if (!query) {
loadSearchAllocatorShopOptions()
await loadSearchAllocatorShopOptions()
return
}
try {
@@ -1767,6 +1761,8 @@
// 每次打开对话框时重新加载店铺列表,确保获取最新的店铺数据
await loadShopListForDialog()
// 加载系列选项
await loadSeriesOptions()
if (type === 'edit' && row) {
// 编辑模式:先调用详情接口获取完整数据

View File

@@ -245,6 +245,7 @@
return actions
}
// 返回上一页
const handleBack = () => {
router.back()
}

View File

@@ -247,9 +247,9 @@
return sections
})
// 返回列表
// 返回上一页
const handleBack = () => {
router.push(RoutesAlias.WechatConfig)
router.back()
}
// 获取详情数据

View File

@@ -1104,7 +1104,7 @@
.role-info {
display: flex;
gap: 8px;
justify-content: space-between;
align-items: center;
.role-name {