Commit 29e3131bbaf9b7db4057dddda911c1d00defc5c5

Authored by ww
1 parent c6c9460d

feat: implement package manage batch delete

... ... @@ -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,
... ...
  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
... ...