Commit 29e3131bbaf9b7db4057dddda911c1d00defc5c5
1 parent
c6c9460d
feat: implement package manage batch delete
Showing
6 changed files
with
113 additions
and
21 deletions
@@ -45,7 +45,7 @@ export const getOtaPackagesList = (params: GetOtaPackagesParams) => { | @@ -45,7 +45,7 @@ export const getOtaPackagesList = (params: GetOtaPackagesParams) => { | ||
45 | * @param params | 45 | * @param params |
46 | * @returns | 46 | * @returns |
47 | */ | 47 | */ |
48 | -export const createOtaPackages = (params: CreateOtaPackageParams) => { | 48 | +export const createOtaPackage = (params: CreateOtaPackageParams) => { |
49 | return defHttp.post<OtaRecordDatum>( | 49 | return defHttp.post<OtaRecordDatum>( |
50 | { | 50 | { |
51 | url: Api.CREATE_OTA_PACKAGES, | 51 | url: Api.CREATE_OTA_PACKAGES, |
@@ -76,7 +76,7 @@ export const uploadOtaPackages = (params: UploadOtaPackagesParams) => { | @@ -76,7 +76,7 @@ export const uploadOtaPackages = (params: UploadOtaPackagesParams) => { | ||
76 | * @description 获取设备默认信息 | 76 | * @description 获取设备默认信息 |
77 | * @returns | 77 | * @returns |
78 | */ | 78 | */ |
79 | -export const getDevicePRofileInfo = () => { | 79 | +export const getDefaultDeviceProfile = () => { |
80 | return defHttp.get<DefaultDeviceProfileInfo>( | 80 | return defHttp.get<DefaultDeviceProfileInfo>( |
81 | { | 81 | { |
82 | url: Api.GET_DEVICE_PROFILE_INFO_DEFAULT, | 82 | url: Api.GET_DEVICE_PROFILE_INFO_DEFAULT, |
src/hooks/component/useSyncConfirm.ts
0 → 100644
1 | +import { ModalOptionsEx, useMessage } from '../web/useMessage'; | ||
2 | + | ||
3 | +export function useSyncConfirm() { | ||
4 | + const { createConfirm } = useMessage(); | ||
5 | + | ||
6 | + const createSyncConfirm = (options: ModalOptionsEx): Promise<boolean> => { | ||
7 | + return new Promise((resolve, reject) => { | ||
8 | + createConfirm({ | ||
9 | + ...options, | ||
10 | + onOk: () => { | ||
11 | + resolve(true); | ||
12 | + }, | ||
13 | + onCancel: () => { | ||
14 | + reject(false); | ||
15 | + }, | ||
16 | + }); | ||
17 | + }); | ||
18 | + }; | ||
19 | + | ||
20 | + return { createSyncConfirm }; | ||
21 | +} |
@@ -3,7 +3,7 @@ | @@ -3,7 +3,7 @@ | ||
3 | import { BasicForm, useForm } from '/@/components/Form'; | 3 | import { BasicForm, useForm } from '/@/components/Form'; |
4 | import { ALG, formSchema, PackageField } from '../config/packageDetail.config'; | 4 | import { ALG, formSchema, PackageField } from '../config/packageDetail.config'; |
5 | import { ref } from 'vue'; | 5 | import { ref } from 'vue'; |
6 | - import { createOtaPackages, uploadOtaPackages, deleteOtaPackage } from '/@/api/ota'; | 6 | + import { createOtaPackage, uploadOtaPackages, deleteOtaPackage } from '/@/api/ota'; |
7 | import { CreateOtaPackageParams } from '/@/api/ota/model'; | 7 | import { CreateOtaPackageParams } from '/@/api/ota/model'; |
8 | 8 | ||
9 | interface FieldsValue extends CreateOtaPackageParams { | 9 | interface FieldsValue extends CreateOtaPackageParams { |
@@ -54,7 +54,7 @@ | @@ -54,7 +54,7 @@ | ||
54 | const handleCreatePackages = async (value: FieldsValue) => { | 54 | const handleCreatePackages = async (value: FieldsValue) => { |
55 | try { | 55 | try { |
56 | setLoading(true); | 56 | setLoading(true); |
57 | - const { id } = await createOtaPackages(value); | 57 | + const { id } = await createOtaPackage(value); |
58 | const { isURL } = value; | 58 | const { isURL } = value; |
59 | if (!isURL) { | 59 | if (!isURL) { |
60 | await handleUploadFile(value, id.id); | 60 | await handleUploadFile(value, id.id); |
@@ -82,6 +82,14 @@ | @@ -82,6 +82,14 @@ | ||
82 | 82 | ||
83 | <template> | 83 | <template> |
84 | <BasicModal title="包管理" destroy-on-close @register="registerModal" @ok="handleSubmit"> | 84 | <BasicModal title="包管理" destroy-on-close @register="registerModal" @ok="handleSubmit"> |
85 | - <BasicForm @register="registerForm" /> | 85 | + <BasicForm @register="registerForm" class="package-manage-form" /> |
86 | </BasicModal> | 86 | </BasicModal> |
87 | </template> | 87 | </template> |
88 | + | ||
89 | +<style scoped lang="less"> | ||
90 | + .package-manage-form { | ||
91 | + :deep(.ant-form-item-control-input-content > div > div) { | ||
92 | + width: 100% !important; | ||
93 | + } | ||
94 | + } | ||
95 | +</style> |
1 | <script lang="ts" setup> | 1 | <script lang="ts" setup> |
2 | - import { OtaRecordDatum } from '/@/api/ota/model'; | 2 | + import { DeviceProfileRecord, OtaRecordDatum } from '/@/api/ota/model'; |
3 | import { BasicDrawer, useDrawerInner } from '/@/components/Drawer'; | 3 | import { BasicDrawer, useDrawerInner } from '/@/components/Drawer'; |
4 | import { Tabs, Space, Button } from 'ant-design-vue'; | 4 | import { Tabs, Space, Button } from 'ant-design-vue'; |
5 | import { useForm, BasicForm } from '/@/components/Form'; | 5 | import { useForm, BasicForm } from '/@/components/Form'; |
@@ -7,14 +7,23 @@ | @@ -7,14 +7,23 @@ | ||
7 | import { ref, unref } from 'vue'; | 7 | import { ref, unref } from 'vue'; |
8 | import { PackageField } from '../config/packageDetail.config'; | 8 | import { PackageField } from '../config/packageDetail.config'; |
9 | import { useMessage } from '/@/hooks/web/useMessage'; | 9 | import { useMessage } from '/@/hooks/web/useMessage'; |
10 | - import { deleteOtaPackage, getDeviceProfileInfoById, getOtaPackageInfo } from '/@/api/ota'; | 10 | + import { |
11 | + createOtaPackage, | ||
12 | + deleteOtaPackage, | ||
13 | + getDeviceProfileInfoById, | ||
14 | + getOtaPackageInfo, | ||
15 | + } from '/@/api/ota'; | ||
11 | import { useCopyToClipboard } from '/@/hooks/web/useCopyToClipboard'; | 16 | import { useCopyToClipboard } from '/@/hooks/web/useCopyToClipboard'; |
12 | import { useDownload } from '../hook/useDownload'; | 17 | import { useDownload } from '../hook/useDownload'; |
13 | 18 | ||
14 | const emit = defineEmits(['register', 'update:list']); | 19 | const emit = defineEmits(['register', 'update:list']); |
15 | 20 | ||
21 | + const loading = ref(false); | ||
22 | + | ||
16 | const otaRecord = ref<OtaRecordDatum>({} as unknown as OtaRecordDatum); | 23 | const otaRecord = ref<OtaRecordDatum>({} as unknown as OtaRecordDatum); |
17 | 24 | ||
25 | + const deviceProfileInfo = ref<DeviceProfileRecord>({} as unknown as DeviceProfileRecord); | ||
26 | + | ||
18 | const { createConfirm, createMessage } = useMessage(); | 27 | const { createConfirm, createMessage } = useMessage(); |
19 | 28 | ||
20 | const [registerForm, { setFieldsValue, getFieldsValue }] = useForm({ | 29 | const [registerForm, { setFieldsValue, getFieldsValue }] = useForm({ |
@@ -23,7 +32,7 @@ | @@ -23,7 +32,7 @@ | ||
23 | disabled: true, | 32 | disabled: true, |
24 | }); | 33 | }); |
25 | 34 | ||
26 | - const [register, { closeDrawer }] = useDrawerInner(async (id: string) => { | 35 | + const [register, { closeDrawer, changeLoading }] = useDrawerInner(async (id: string) => { |
27 | try { | 36 | try { |
28 | const record = await getOtaPackageInfo(id); | 37 | const record = await getOtaPackageInfo(id); |
29 | const deviceInfo = await getDeviceProfileInfoById(record.deviceProfileId.id); | 38 | const deviceInfo = await getDeviceProfileInfoById(record.deviceProfileId.id); |
@@ -32,11 +41,12 @@ | @@ -32,11 +41,12 @@ | ||
32 | [PackageField.DESCRIPTION]: record.additionalInfo.description, | 41 | [PackageField.DESCRIPTION]: record.additionalInfo.description, |
33 | [PackageField.DEVICE_PROFILE_INFO]: deviceInfo.name, | 42 | [PackageField.DEVICE_PROFILE_INFO]: deviceInfo.name, |
34 | }); | 43 | }); |
44 | + deviceProfileInfo.value = deviceInfo; | ||
35 | otaRecord.value = record; | 45 | otaRecord.value = record; |
36 | } catch (error) {} | 46 | } catch (error) {} |
37 | }); | 47 | }); |
38 | 48 | ||
39 | - const openDetailPage = () => {}; | 49 | + // const openDetailPage = () => {}; |
40 | 50 | ||
41 | const downloadPackage = async () => { | 51 | const downloadPackage = async () => { |
42 | await useDownload(unref(otaRecord)); | 52 | await useDownload(unref(otaRecord)); |
@@ -72,17 +82,40 @@ | @@ -72,17 +82,40 @@ | ||
72 | if (unref(isSuccessRef)) createMessage.success('复制成功'); | 82 | if (unref(isSuccessRef)) createMessage.success('复制成功'); |
73 | }; | 83 | }; |
74 | 84 | ||
85 | + const setLoading = (status: boolean) => { | ||
86 | + changeLoading(status); | ||
87 | + loading.value = status; | ||
88 | + }; | ||
89 | + | ||
75 | const handleSubmit = async () => { | 90 | const handleSubmit = async () => { |
76 | - getFieldsValue(); | 91 | + const value = getFieldsValue(); |
92 | + try { | ||
93 | + setLoading(true); | ||
94 | + await createOtaPackage({ | ||
95 | + ...unref(otaRecord), | ||
96 | + additionalInfo: { description: value[PackageField.DESCRIPTION] }, | ||
97 | + } as any); | ||
98 | + createMessage.success('修改成功'); | ||
99 | + } catch (error) { | ||
100 | + } finally { | ||
101 | + setLoading(false); | ||
102 | + closeDrawer(); | ||
103 | + } | ||
77 | }; | 104 | }; |
78 | </script> | 105 | </script> |
79 | 106 | ||
80 | <template> | 107 | <template> |
81 | - <BasicDrawer width="40%" class="relative" @register="register" @ok="handleSubmit"> | 108 | + <BasicDrawer |
109 | + :title="otaRecord.title" | ||
110 | + width="40%" | ||
111 | + class="relative" | ||
112 | + @register="register" | ||
113 | + @ok="handleSubmit" | ||
114 | + > | ||
82 | <Tabs> | 115 | <Tabs> |
83 | <Tabs.TabPane tab="详情" key="detail"> | 116 | <Tabs.TabPane tab="详情" key="detail"> |
84 | <Space> | 117 | <Space> |
85 | - <Button type="primary" @click="openDetailPage">打开详情页</Button> | 118 | + <!-- <Button type="primary" @click="openDetailPage">打开详情页</Button> --> |
86 | <Button type="primary" @click="downloadPackage" :disabled="!!otaRecord.url"> | 119 | <Button type="primary" @click="downloadPackage" :disabled="!!otaRecord.url"> |
87 | 下载包 | 120 | 下载包 |
88 | </Button> | 121 | </Button> |
@@ -97,11 +130,13 @@ | @@ -97,11 +130,13 @@ | ||
97 | <BasicForm @register="registerForm" /> | 130 | <BasicForm @register="registerForm" /> |
98 | </Tabs.TabPane> | 131 | </Tabs.TabPane> |
99 | </Tabs> | 132 | </Tabs> |
100 | - <div | ||
101 | - class="absolute right-0 bottom-0 w-full border-t bg-light-50 border-t-gray-100 py-2 px-4 text-right" | ||
102 | - > | ||
103 | - <Button class="mr-2">取消</Button> | ||
104 | - <Button type="primary">保存</Button> | ||
105 | - </div> | 133 | + <template #footer> |
134 | + <div | ||
135 | + class="absolute right-0 bottom-0 w-full border-t bg-light-50 border-t-gray-100 py-2 px-4 text-right" | ||
136 | + > | ||
137 | + <Button class="mr-2" @click="closeDrawer">取消</Button> | ||
138 | + <Button type="primary" :loading="loading" @click="handleSubmit">保存</Button> | ||
139 | + </div> | ||
140 | + </template> | ||
106 | </BasicDrawer> | 141 | </BasicDrawer> |
107 | </template> | 142 | </template> |
1 | -import { getDevicePRofileInfo, getDeviceProfileInfos } from '/@/api/ota'; | 1 | +import { getDefaultDeviceProfile, getDeviceProfileInfos } from '/@/api/ota'; |
2 | import { Id } from '/@/api/ota/model'; | 2 | import { Id } from '/@/api/ota/model'; |
3 | import { FormSchema } from '/@/components/Form'; | 3 | import { FormSchema } from '/@/components/Form'; |
4 | import { FileItem } from '/@/components/Form/src/components/ApiUpload.vue'; | 4 | import { FileItem } from '/@/components/Form/src/components/ApiUpload.vue'; |
@@ -97,7 +97,7 @@ export const formSchema: FormSchema[] = [ | @@ -97,7 +97,7 @@ export const formSchema: FormSchema[] = [ | ||
97 | labelField: 'name', | 97 | labelField: 'name', |
98 | valueField: 'id', | 98 | valueField: 'id', |
99 | api: async () => { | 99 | api: async () => { |
100 | - const data = await getDevicePRofileInfo(); | 100 | + const data = await getDefaultDeviceProfile(); |
101 | data.id = JSON.stringify(data.id) as unknown as Id; | 101 | data.id = JSON.stringify(data.id) as unknown as Id; |
102 | setFieldsValue({ [PackageField.DEVICE_PROFILE_INFO]: data.id }); | 102 | setFieldsValue({ [PackageField.DEVICE_PROFILE_INFO]: data.id }); |
103 | return { data: [data] }; | 103 | return { data: [data] }; |
@@ -11,8 +11,10 @@ | @@ -11,8 +11,10 @@ | ||
11 | import { useDrawer } from '/@/components/Drawer'; | 11 | import { useDrawer } from '/@/components/Drawer'; |
12 | import { useMessage } from '/@/hooks/web/useMessage'; | 12 | import { useMessage } from '/@/hooks/web/useMessage'; |
13 | import { useDownload } from './hook/useDownload'; | 13 | import { useDownload } from './hook/useDownload'; |
14 | + import { computed } from 'vue'; | ||
15 | + import { useSyncConfirm } from '/@/hooks/component/useSyncConfirm'; | ||
14 | 16 | ||
15 | - const [register, { reload }] = useTable({ | 17 | + const [register, { reload, getSelectRowKeys, getRowSelection, setSelectedRowKeys }] = useTable({ |
16 | columns, | 18 | columns, |
17 | title: '包仓库', | 19 | title: '包仓库', |
18 | api: async (params: GetOtaPackagesParams) => { | 20 | api: async (params: GetOtaPackagesParams) => { |
@@ -35,9 +37,13 @@ | @@ -35,9 +37,13 @@ | ||
35 | labelWidth: 120, | 37 | labelWidth: 120, |
36 | schemas: searchFormSchema, | 38 | schemas: searchFormSchema, |
37 | }, | 39 | }, |
40 | + rowKey: (record: OtaRecordDatum) => record.id.id, | ||
38 | showIndexColumn: false, | 41 | showIndexColumn: false, |
39 | useSearchForm: true, | 42 | useSearchForm: true, |
40 | showTableSetting: true, | 43 | showTableSetting: true, |
44 | + rowSelection: { | ||
45 | + type: 'checkbox', | ||
46 | + }, | ||
41 | }); | 47 | }); |
42 | 48 | ||
43 | const { createConfirm, createMessage } = useMessage(); | 49 | const { createConfirm, createMessage } = useMessage(); |
@@ -71,6 +77,25 @@ | @@ -71,6 +77,25 @@ | ||
71 | }, | 77 | }, |
72 | }); | 78 | }); |
73 | }; | 79 | }; |
80 | + | ||
81 | + const canDelete = computed(() => { | ||
82 | + const rowSelection = getRowSelection(); | ||
83 | + return !rowSelection.selectedRowKeys?.length; | ||
84 | + }); | ||
85 | + | ||
86 | + const { createSyncConfirm } = useSyncConfirm(); | ||
87 | + const handleBatchDelete = async () => { | ||
88 | + const rowKeys = getSelectRowKeys(); | ||
89 | + try { | ||
90 | + await createSyncConfirm({ iconType: 'warning', content: '确认后所有选中的OTA升级将被删除' }); | ||
91 | + for (const key of rowKeys) { | ||
92 | + await deleteOtaPackage(key); | ||
93 | + } | ||
94 | + createMessage.success('批量删除成功'); | ||
95 | + setSelectedRowKeys([]); | ||
96 | + reload(); | ||
97 | + } catch (error) {} | ||
98 | + }; | ||
74 | </script> | 99 | </script> |
75 | 100 | ||
76 | <template> | 101 | <template> |
@@ -78,6 +103,9 @@ | @@ -78,6 +103,9 @@ | ||
78 | <BasicTable @register="register" @row-click="handleOpenDetailDrawer" class="ota-list"> | 103 | <BasicTable @register="register" @row-click="handleOpenDetailDrawer" class="ota-list"> |
79 | <template #toolbar> | 104 | <template #toolbar> |
80 | <Button @click="handleCreatePackage" type="primary">新增包</Button> | 105 | <Button @click="handleCreatePackage" type="primary">新增包</Button> |
106 | + <Button @click="handleBatchDelete" :disabled="canDelete" type="primary" danger> | ||
107 | + 批量删除 | ||
108 | + </Button> | ||
81 | </template> | 109 | </template> |
82 | <template #action="{ record }"> | 110 | <template #action="{ record }"> |
83 | <TableAction | 111 | <TableAction |