feat: 网元分组调整和支持修改申请

This commit is contained in:
caiyuchao
2025-07-26 17:53:27 +08:00
parent a89409e640
commit 562e4a4630
4 changed files with 133 additions and 134 deletions

View File

@@ -1,91 +1,40 @@
<script lang="ts" setup> <script lang="ts" setup>
import type { FormInstance, SelectProps } from 'ant-design-vue'; import type { FormInstance } from 'ant-design-vue';
import type { LicenseApi } from '#/api/license/license'; import type { LicenseApi } from '#/api/license/license';
import { reactive, ref } from 'vue'; import { ref } from 'vue';
import { MinusCircleOutlined, PlusOutlined } from '@vben/icons'; import { MinusCircleOutlined, PlusOutlined } from '@vben/icons';
import { Textarea } from 'ant-design-vue'; import { Textarea } from 'ant-design-vue';
import { $t } from '#/locales'; import { $t } from '#/locales';
import { DICT_TYPE, getDictOptions } from '#/utils';
const emit = defineEmits(['neCodeList']); const props = withDefaults(
defineProps<{
availableOptions: Function;
neCodeList?: LicenseApi.NeCode[];
}>(),
{
neCodeList: () => [{ neList: [], activationCode: '', id: 1 }],
},
);
const neAllOptions = getDictOptions(DICT_TYPE.LIC_NE_ALL, 'number'); const emit = defineEmits(['addNeCode', 'removeNeCode']);
const ne5GOptions = getDictOptions(DICT_TYPE.LIC_NE_5G, 'number');
const ne4GOptions = getDictOptions(DICT_TYPE.LIC_NE_4G, 'number');
const ne23GOptions = getDictOptions(DICT_TYPE.LIC_NE_23G, 'number');
const neAddOptions = getDictOptions(DICT_TYPE.LIC_NE_ADD, 'number');
const options = ref<SelectProps['options']>([
{
label: '一体化',
options: neAllOptions,
},
{
label: '5G',
options: ne5GOptions,
},
{
label: '4G',
options: ne4GOptions,
},
{
label: '2/3G',
options: ne23GOptions,
},
{
label: '增值业务',
options: neAddOptions,
},
]);
let nextId = 2;
const formRef = ref<FormInstance>(); const formRef = ref<FormInstance>();
const dynamicValidateForm = reactive<{ neCodeList: LicenseApi.NeCode[] }>({
neCodeList: [{ neList: [], activationCode: '', id: 1 }],
});
const removeNeCode = (item: LicenseApi.NeCode) => { const removeNeCode = (item: LicenseApi.NeCode) => {
const index = dynamicValidateForm.neCodeList.indexOf(item); emit('removeNeCode', item);
if (index !== -1) {
dynamicValidateForm.neCodeList.splice(index, 1);
}
}; };
const addNeCode = () => { const addNeCode = () => {
dynamicValidateForm.neCodeList.push({ emit('addNeCode');
neList: [],
activationCode: '',
id: nextId++,
});
}; };
const filterOption = (input: string, option: any) => { const filterOption = (input: string, option: any) => {
return option.label.toLowerCase().includes(input.toLowerCase()); return option.label.toLowerCase().includes(input.toLowerCase());
}; };
const handleChange = () => {
emit('neCodeList', dynamicValidateForm.neCodeList);
};
const availableOptions = (groupIdx: number) => {
// 其他分组已选标签
const otherSelected = new Set(
dynamicValidateForm.neCodeList
.filter((_, idx) => idx !== groupIdx)
.flatMap((g) => g.neList),
);
// return ne5GOptions.filter((tag) => !otherSelected.has(tag.value));
return options.value?.map((item) => ({
...item,
options: item.options.filter(
(option: any) => !otherSelected.has(option.value),
),
}));
};
const validate = () => formRef.value?.validate(); const validate = () => formRef.value?.validate();
defineExpose({ defineExpose({
@@ -93,13 +42,9 @@ defineExpose({
}); });
</script> </script>
<template> <template>
<a-form <a-form ref="formRef" name="dynamic_form_nest_item" :model="props">
ref="formRef"
name="dynamic_form_nest_item"
:model="dynamicValidateForm"
>
<div <div
v-for="(neCode, index) in dynamicValidateForm.neCodeList" v-for="(neCode, index) in props.neCodeList"
:key="neCode.id" :key="neCode.id"
class="flex w-full gap-1" class="flex w-full gap-1"
> >
@@ -116,10 +61,9 @@ defineExpose({
allow-clear allow-clear
show-search show-search
style="width: 220px" style="width: 220px"
:options="availableOptions(index)" :options="props.availableOptions(index)"
:filter-option="filterOption" :filter-option="filterOption"
:placeholder="$t('license.selectNe')" :placeholder="$t('license.selectNe')"
@change="handleChange"
/> />
</a-form-item> </a-form-item>
<a-form-item <a-form-item
@@ -135,10 +79,9 @@ defineExpose({
allow-clear allow-clear
v-model:value="neCode.activationCode" v-model:value="neCode.activationCode"
:rows="1" :rows="1"
@change="handleChange"
/> />
</a-form-item> </a-form-item>
<a-form-item v-if="dynamicValidateForm.neCodeList.length > 1"> <a-form-item v-if="props.neCodeList.length > 1">
<MinusCircleOutlined <MinusCircleOutlined
@click="removeNeCode(neCode)" @click="removeNeCode(neCode)"
class="mt-1 cursor-pointer" class="mt-1 cursor-pointer"

View File

@@ -145,7 +145,7 @@ export function useFormSchema(): VbenFormSchema[] {
component: '', component: '',
formItemClass: 'col-span-2', formItemClass: 'col-span-2',
modelPropName: 'modelValue', modelPropName: 'modelValue',
rules: z.string(), rules: z.array(z.object({})),
}, },
// { // {
// fieldName: 'licenseContent', // fieldName: 'licenseContent',
@@ -308,19 +308,19 @@ export function useGridFormSchema(): VbenFormSchema[] {
allowClear: true, allowClear: true,
}, },
}, },
{ // {
fieldName: 'neList', // fieldName: 'neList',
label: $t('license.neList'), // label: $t('license.neList'),
component: 'Select', // component: 'Select',
componentProps: { // componentProps: {
allowClear: true, // allowClear: true,
mode: 'multiple', // mode: 'multiple',
options: getDictOptions(DICT_TYPE.LIC_NE_LIST, 'number'), // options: getDictOptions(DICT_TYPE.LIC_NE_LIST, 'number'),
showSearch: true, // showSearch: true,
filterOption: (input: string, option: any) => // filterOption: (input: string, option: any) =>
option.label.toLowerCase().includes(input.toLowerCase()), // option.label.toLowerCase().includes(input.toLowerCase()),
}, // },
}, // },
// { // {
// fieldName: 'userNumber', // fieldName: 'userNumber',
// label: $t('license.userNumber'), // label: $t('license.userNumber'),
@@ -353,15 +353,15 @@ export function useGridFormSchema(): VbenFormSchema[] {
// allowClear: true, // allowClear: true,
// }, // },
// }, // },
{ // {
fieldName: 'applicationTime', // fieldName: 'applicationTime',
label: $t('license.applicationTime'), // label: $t('license.applicationTime'),
component: 'RangePicker', // component: 'RangePicker',
componentProps: { // componentProps: {
...getRangePickerDefaultProps(), // ...getRangePickerDefaultProps(),
allowClear: true, // allowClear: true,
}, // },
}, // },
// { // {
// fieldName: 'remark', // fieldName: 'remark',
// label: $t('license.remark'), // label: $t('license.remark'),
@@ -408,23 +408,23 @@ export function useGridColumns(
minWidth: 120, minWidth: 120,
formatter: 'formatDateTime', formatter: 'formatDateTime',
}, },
{ // {
field: 'neList', // field: 'neList',
title: $t('license.neList'), // title: $t('license.neList'),
minWidth: 120, // minWidth: 120,
cellRender: { // cellRender: {
name: 'CellDictGroup', // name: 'CellDictGroup',
props: { // props: {
type: [ // type: [
DICT_TYPE.LIC_NE_ALL, // DICT_TYPE.LIC_NE_ALL,
DICT_TYPE.LIC_NE_5G, // DICT_TYPE.LIC_NE_5G,
DICT_TYPE.LIC_NE_4G, // DICT_TYPE.LIC_NE_4G,
DICT_TYPE.LIC_NE_23G, // DICT_TYPE.LIC_NE_23G,
DICT_TYPE.LIC_NE_ADD, // DICT_TYPE.LIC_NE_ADD,
], // ],
}, // },
}, // },
}, // },
{ {
field: 'userNumber', field: 'userNumber',
title: $t('license.userNumber'), title: $t('license.userNumber'),
@@ -435,12 +435,12 @@ export function useGridColumns(
title: $t('license.ranNumber'), title: $t('license.ranNumber'),
minWidth: 120, minWidth: 120,
}, },
{ // {
field: 'activationCode', // field: 'activationCode',
title: $t('license.activationCode'), // title: $t('license.activationCode'),
visible: false, // visible: false,
minWidth: 120, // minWidth: 120,
}, // },
// { // {
// field: 'licenseContent', // field: 'licenseContent',
// visible: false, // visible: false,
@@ -505,10 +505,10 @@ export function useGridColumns(
code: 'detail', code: 'detail',
text: $t('license.detail'), text: $t('license.detail'),
}, },
{ // {
code: 'edit', // code: 'edit',
show: hasAccessByCodes(['license:license:update']), // show: hasAccessByCodes(['license:license:update']),
}, // },
{ {
code: 'apply', code: 'apply',
text: $t('license.apply'), text: $t('license.apply'),

View File

@@ -183,7 +183,7 @@ const [Grid, gridApi] = useVbenVxeGrid({
<TableAction <TableAction
:actions="[ :actions="[
{ {
label: $t('ui.actionTitle.create', ['License']), label: $t('license.applyAction', ['License']),
type: 'primary', type: 'primary',
icon: ACTION_ICON.ADD, icon: ACTION_ICON.ADD,
auth: ['license:license:create'], auth: ['license:license:create'],

View File

@@ -1,4 +1,6 @@
<script lang="ts" setup> <script lang="ts" setup>
import type { SelectProps } from 'ant-design-vue';
import type { LicenseApi } from '#/api/license/license'; import type { LicenseApi } from '#/api/license/license';
import { computed, reactive, ref, watch } from 'vue'; import { computed, reactive, ref, watch } from 'vue';
@@ -21,7 +23,7 @@ import NeCode from '../components/ne-code.vue';
import { formData, useFormSchema } from '../data'; import { formData, useFormSchema } from '../data';
const emit = defineEmits(['success']); const emit = defineEmits(['success']);
const neListOptions = getDictOptions(DICT_TYPE.LIC_NE_LIST, 'number'); const neListOptions = getDictOptions(DICT_TYPE.LIC_NE_ALL, 'number');
const state = reactive({ const state = reactive({
indeterminate: false, indeterminate: false,
@@ -29,6 +31,7 @@ const state = reactive({
checkedList: [] as number[], checkedList: [] as number[],
neCodeList: [] as LicenseApi.NeCode[], neCodeList: [] as LicenseApi.NeCode[],
}); });
const neCodeRef = ref(); const neCodeRef = ref();
const getTitle = computed(() => { const getTitle = computed(() => {
@@ -38,7 +41,7 @@ const getTitle = computed(() => {
} }
return $t('ui.actionTitle.edit', ['License']); return $t('ui.actionTitle.edit', ['License']);
} else { } else {
return $t('ui.actionTitle.create', ['License']); return $t('license.applyAction', ['License']);
} }
}); });
@@ -136,20 +139,70 @@ const [Modal, modalApi] = useVbenModal({
modalApi.unlock(); modalApi.unlock();
} }
} }
// const neCodeList = data.neCodeList || [{ neList: [], activationCode: '' }];
// data = { ...data, neCodeList };
// 处理数据 // 处理数据
data.expiryDate = data.expiryDate ? data.expiryDate.toString() : ''; data.expiryDate = data.expiryDate ? data.expiryDate.toString() : '';
// 设置到 values // 设置到 values
formData.value = data; formData.value = data;
state.checkedList = data.neList || []; state.checkedList = data.neList || [];
state.neCodeList = data.neCodeList || []; state.neCodeList = data.neCodeList || [
{ neList: [], activationCode: '', id: 1 },
];
await formApi.setValues(formData.value); await formApi.setValues(formData.value);
}, },
}); });
const getNeCodeList = (neCodeList: LicenseApi.NeCode[]) => { const options = ref<SelectProps['options']>([
state.neCodeList = neCodeList; {
label: '一体化',
options: getDictOptions(DICT_TYPE.LIC_NE_ALL, 'number'),
},
{
label: '5G',
options: getDictOptions(DICT_TYPE.LIC_NE_5G, 'number'),
},
{
label: '4G',
options: getDictOptions(DICT_TYPE.LIC_NE_4G, 'number'),
},
{
label: '2/3G',
options: getDictOptions(DICT_TYPE.LIC_NE_23G, 'number'),
},
{
label: '增值业务',
options: getDictOptions(DICT_TYPE.LIC_NE_ADD, 'number'),
},
]);
let nextId = 2;
const removeNeCode = (item: LicenseApi.NeCode) => {
const index = state.neCodeList.indexOf(item);
if (index !== -1) {
state.neCodeList.splice(index, 1);
}
};
const addNeCode = () => {
state.neCodeList.push({
neList: [],
activationCode: '',
id: nextId++,
});
};
const availableOptions = (groupIdx: number) => {
// 其他分组已选标签
const otherSelected = new Set(
state.neCodeList
.filter((_, idx) => idx !== groupIdx)
.flatMap((g) => g.neList),
);
const aaaa = options.value?.map((item) => ({
...item,
options: item.options.filter(
(option: any) => !otherSelected.has(option.value),
),
}));
return aaaa;
}; };
</script> </script>
@@ -178,7 +231,10 @@ const getNeCodeList = (neCodeList: LicenseApi.NeCode[]) => {
<template #neCodeList="slotProps"> <template #neCodeList="slotProps">
<NeCode <NeCode
v-bind="slotProps" v-bind="slotProps"
@ne-code-list="getNeCodeList" @add-ne-code="addNeCode"
@remove-ne-code="removeNeCode"
:ne-code-list="state.neCodeList"
:available-options="availableOptions"
ref="neCodeRef" ref="neCodeRef"
v-model:value="state.neCodeList" v-model:value="state.neCodeList"
/> />