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 | 45 | * @param params |
46 | 46 | * @returns |
47 | 47 | */ |
48 | -export const createOtaPackages = (params: CreateOtaPackageParams) => { | |
48 | +export const createOtaPackage = (params: CreateOtaPackageParams) => { | |
49 | 49 | return defHttp.post<OtaRecordDatum>( |
50 | 50 | { |
51 | 51 | url: Api.CREATE_OTA_PACKAGES, |
... | ... | @@ -76,7 +76,7 @@ export const uploadOtaPackages = (params: UploadOtaPackagesParams) => { |
76 | 76 | * @description 获取设备默认信息 |
77 | 77 | * @returns |
78 | 78 | */ |
79 | -export const getDevicePRofileInfo = () => { | |
79 | +export const getDefaultDeviceProfile = () => { | |
80 | 80 | return defHttp.get<DefaultDeviceProfileInfo>( |
81 | 81 | { |
82 | 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 | 3 | import { BasicForm, useForm } from '/@/components/Form'; |
4 | 4 | import { ALG, formSchema, PackageField } from '../config/packageDetail.config'; |
5 | 5 | import { ref } from 'vue'; |
6 | - import { createOtaPackages, uploadOtaPackages, deleteOtaPackage } from '/@/api/ota'; | |
6 | + import { createOtaPackage, uploadOtaPackages, deleteOtaPackage } from '/@/api/ota'; | |
7 | 7 | import { CreateOtaPackageParams } from '/@/api/ota/model'; |
8 | 8 | |
9 | 9 | interface FieldsValue extends CreateOtaPackageParams { |
... | ... | @@ -54,7 +54,7 @@ |
54 | 54 | const handleCreatePackages = async (value: FieldsValue) => { |
55 | 55 | try { |
56 | 56 | setLoading(true); |
57 | - const { id } = await createOtaPackages(value); | |
57 | + const { id } = await createOtaPackage(value); | |
58 | 58 | const { isURL } = value; |
59 | 59 | if (!isURL) { |
60 | 60 | await handleUploadFile(value, id.id); |
... | ... | @@ -82,6 +82,14 @@ |
82 | 82 | |
83 | 83 | <template> |
84 | 84 | <BasicModal title="包管理" destroy-on-close @register="registerModal" @ok="handleSubmit"> |
85 | - <BasicForm @register="registerForm" /> | |
85 | + <BasicForm @register="registerForm" class="package-manage-form" /> | |
86 | 86 | </BasicModal> |
87 | 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 | 1 | <script lang="ts" setup> |
2 | - import { OtaRecordDatum } from '/@/api/ota/model'; | |
2 | + import { DeviceProfileRecord, OtaRecordDatum } from '/@/api/ota/model'; | |
3 | 3 | import { BasicDrawer, useDrawerInner } from '/@/components/Drawer'; |
4 | 4 | import { Tabs, Space, Button } from 'ant-design-vue'; |
5 | 5 | import { useForm, BasicForm } from '/@/components/Form'; |
... | ... | @@ -7,14 +7,23 @@ |
7 | 7 | import { ref, unref } from 'vue'; |
8 | 8 | import { PackageField } from '../config/packageDetail.config'; |
9 | 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 | 16 | import { useCopyToClipboard } from '/@/hooks/web/useCopyToClipboard'; |
12 | 17 | import { useDownload } from '../hook/useDownload'; |
13 | 18 | |
14 | 19 | const emit = defineEmits(['register', 'update:list']); |
15 | 20 | |
21 | + const loading = ref(false); | |
22 | + | |
16 | 23 | const otaRecord = ref<OtaRecordDatum>({} as unknown as OtaRecordDatum); |
17 | 24 | |
25 | + const deviceProfileInfo = ref<DeviceProfileRecord>({} as unknown as DeviceProfileRecord); | |
26 | + | |
18 | 27 | const { createConfirm, createMessage } = useMessage(); |
19 | 28 | |
20 | 29 | const [registerForm, { setFieldsValue, getFieldsValue }] = useForm({ |
... | ... | @@ -23,7 +32,7 @@ |
23 | 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 | 36 | try { |
28 | 37 | const record = await getOtaPackageInfo(id); |
29 | 38 | const deviceInfo = await getDeviceProfileInfoById(record.deviceProfileId.id); |
... | ... | @@ -32,11 +41,12 @@ |
32 | 41 | [PackageField.DESCRIPTION]: record.additionalInfo.description, |
33 | 42 | [PackageField.DEVICE_PROFILE_INFO]: deviceInfo.name, |
34 | 43 | }); |
44 | + deviceProfileInfo.value = deviceInfo; | |
35 | 45 | otaRecord.value = record; |
36 | 46 | } catch (error) {} |
37 | 47 | }); |
38 | 48 | |
39 | - const openDetailPage = () => {}; | |
49 | + // const openDetailPage = () => {}; | |
40 | 50 | |
41 | 51 | const downloadPackage = async () => { |
42 | 52 | await useDownload(unref(otaRecord)); |
... | ... | @@ -72,17 +82,40 @@ |
72 | 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 | 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 | 105 | </script> |
79 | 106 | |
80 | 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 | 115 | <Tabs> |
83 | 116 | <Tabs.TabPane tab="详情" key="detail"> |
84 | 117 | <Space> |
85 | - <Button type="primary" @click="openDetailPage">打开详情页</Button> | |
118 | + <!-- <Button type="primary" @click="openDetailPage">打开详情页</Button> --> | |
86 | 119 | <Button type="primary" @click="downloadPackage" :disabled="!!otaRecord.url"> |
87 | 120 | 下载包 |
88 | 121 | </Button> |
... | ... | @@ -97,11 +130,13 @@ |
97 | 130 | <BasicForm @register="registerForm" /> |
98 | 131 | </Tabs.TabPane> |
99 | 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 | 141 | </BasicDrawer> |
107 | 142 | </template> | ... | ... |
1 | -import { getDevicePRofileInfo, getDeviceProfileInfos } from '/@/api/ota'; | |
1 | +import { getDefaultDeviceProfile, getDeviceProfileInfos } from '/@/api/ota'; | |
2 | 2 | import { Id } from '/@/api/ota/model'; |
3 | 3 | import { FormSchema } from '/@/components/Form'; |
4 | 4 | import { FileItem } from '/@/components/Form/src/components/ApiUpload.vue'; |
... | ... | @@ -97,7 +97,7 @@ export const formSchema: FormSchema[] = [ |
97 | 97 | labelField: 'name', |
98 | 98 | valueField: 'id', |
99 | 99 | api: async () => { |
100 | - const data = await getDevicePRofileInfo(); | |
100 | + const data = await getDefaultDeviceProfile(); | |
101 | 101 | data.id = JSON.stringify(data.id) as unknown as Id; |
102 | 102 | setFieldsValue({ [PackageField.DEVICE_PROFILE_INFO]: data.id }); |
103 | 103 | return { data: [data] }; | ... | ... |
... | ... | @@ -11,8 +11,10 @@ |
11 | 11 | import { useDrawer } from '/@/components/Drawer'; |
12 | 12 | import { useMessage } from '/@/hooks/web/useMessage'; |
13 | 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 | 18 | columns, |
17 | 19 | title: '包仓库', |
18 | 20 | api: async (params: GetOtaPackagesParams) => { |
... | ... | @@ -35,9 +37,13 @@ |
35 | 37 | labelWidth: 120, |
36 | 38 | schemas: searchFormSchema, |
37 | 39 | }, |
40 | + rowKey: (record: OtaRecordDatum) => record.id.id, | |
38 | 41 | showIndexColumn: false, |
39 | 42 | useSearchForm: true, |
40 | 43 | showTableSetting: true, |
44 | + rowSelection: { | |
45 | + type: 'checkbox', | |
46 | + }, | |
41 | 47 | }); |
42 | 48 | |
43 | 49 | const { createConfirm, createMessage } = useMessage(); |
... | ... | @@ -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 | 99 | </script> |
75 | 100 | |
76 | 101 | <template> |
... | ... | @@ -78,6 +103,9 @@ |
78 | 103 | <BasicTable @register="register" @row-click="handleOpenDetailDrawer" class="ota-list"> |
79 | 104 | <template #toolbar> |
80 | 105 | <Button @click="handleCreatePackage" type="primary">新增包</Button> |
106 | + <Button @click="handleBatchDelete" :disabled="canDelete" type="primary" danger> | |
107 | + 批量删除 | |
108 | + </Button> | |
81 | 109 | </template> |
82 | 110 | <template #action="{ record }"> |
83 | 111 | <TableAction | ... | ... |