diff --git a/code/container-ocr/ocr-springboot/src/main/java/cn/g3soft/controller/FileController.java b/code/container-ocr/ocr-springboot/src/main/java/cn/g3soft/controller/FileController.java index 96409e02..94fd2d21 100644 --- a/code/container-ocr/ocr-springboot/src/main/java/cn/g3soft/controller/FileController.java +++ b/code/container-ocr/ocr-springboot/src/main/java/cn/g3soft/controller/FileController.java @@ -304,4 +304,81 @@ public class FileController { } } + @PostMapping("/deletes") + @Transactional(rollbackFor = Exception.class) + public Result deleteFiles(@RequestBody List subids) { + try { + + if (subids == null || subids.isEmpty()) { + return Result.ok(); + } + + for (Object subidObj : subids) { + + if (subidObj == null) { + continue; + } + + Long subid = Long.valueOf(subidObj.toString()); + + // 1. 查询文件记录 + List> maps = dbUtils.loadData( + "SELECT * FROM bf_file WHERE subid = ?", + subid + ); + + if (maps.isEmpty()) { + continue; + } + + Map objectMap = maps.get(0); + + // 2. 获取文件路径 + String mxMapfilename = objectMap.get("mx_mapfilename") == null + ? "" + : objectMap.get("mx_mapfilename").toString(); + + // 3. 删除本地文件 + if (StringUtils.isNotBlank(mxMapfilename)) { + + String filePath = PathUtils.joinFilePath( + fileConfig.getBaseDir(), + mxMapfilename + ); + + boolean deleted = FileUtils.deleteFileByPath(filePath); + + if (!deleted) { + System.out.println("文件删除失败或不存在: " + filePath); + } + } + + // 4. 删除数据库记录 + dbUtils.deleteById("bf_file", "subid", subid); + + // 5. 记录日志 + Map mapData = new HashMap<>(); + + ObjectMapper objectMapper = new ObjectMapper(); + String dataStr = objectMapper.writeValueAsString(objectMap); + + String currentDateTime = TimeUtils.getDateTime(); + + mapData.put("b_table", "bf_file"); + mapData.put("b_option", "DELETE"); + mapData.put("b_datas", dataStr); + mapData.put("b_inputdatetime", currentDateTime); + mapData.put("b_inputuser_id", UserContext.get().getUserId()); + + dbUtils.insert("log_datas", "b_id", mapData); + } + + return Result.ok(); + + } catch (Exception e) { + e.printStackTrace(); + return Result.fail("批量删除失败: " + e.getMessage()); + } + } + } diff --git a/code/container-ocr/ocr-springboot/src/main/resources/application.yml b/code/container-ocr/ocr-springboot/src/main/resources/application.yml index 0e5ca111..38dff4da 100644 --- a/code/container-ocr/ocr-springboot/src/main/resources/application.yml +++ b/code/container-ocr/ocr-springboot/src/main/resources/application.yml @@ -16,7 +16,7 @@ spring: time-zone: "Asia/Shanghai" date-format: yyyy-MM-dd HH:mm:ss profiles: - active: build + active: dev file: base-dir: D:/data/file diff --git a/code/container-ocr/ocr-springboot/src/main/resources/dbconfigs/g3hd.properties b/code/container-ocr/ocr-springboot/src/main/resources/dbconfigs/g3hd.properties index 05bead7b..8d6733ef 100644 --- a/code/container-ocr/ocr-springboot/src/main/resources/dbconfigs/g3hd.properties +++ b/code/container-ocr/ocr-springboot/src/main/resources/dbconfigs/g3hd.properties @@ -1,10 +1,10 @@ -#url=jdbc:sqlserver://118.89.70.199:1433;databaseName=G3BoxOCR -#username=sa -#password=zhang520.. -#driver=com.microsoft.sqlserver.jdbc.SQLServerDriver - -url=jdbc:sqlserver://127.0.0.1:1433;databaseName=G3ContainerOCR +url=jdbc:sqlserver://118.89.70.199:1433;databaseName=G3BoxOCR username=sa -password=123456@aaa +password=zhang520.. driver=com.microsoft.sqlserver.jdbc.SQLServerDriver +#url=jdbc:sqlserver://127.0.0.1:1433;databaseName=G3ContainerOCR +#username=sa +#password=123456@aaa +#driver=com.microsoft.sqlserver.jdbc.SQLServerDriver + diff --git a/code/container-ocr/ocr-uniapp/src/pages-sub/upload/edit.vue b/code/container-ocr/ocr-uniapp/src/pages-sub/upload/edit.vue index 13ccad83..417e12e3 100644 --- a/code/container-ocr/ocr-uniapp/src/pages-sub/upload/edit.vue +++ b/code/container-ocr/ocr-uniapp/src/pages-sub/upload/edit.vue @@ -2,7 +2,7 @@ import type { UploadFile, UploadFileItem } from 'sard-uniapp' import { dialog, isImageUrl, isVideoUrl, toast } from 'sard-uniapp' import { getOrgBaseUrl } from '@/request' -import { deleteFileApi, loadDataApi, saveObjectApi, uploadContainerFileApi } from '@/request/api' +import { deleteFileApi, deleteFilesApi, loadDataApi, saveObjectApi, uploadContainerFileApi } from '@/request/api' import { useUserStore } from '@/store' import { buildPubicUrl, downloadFile, getFileExtension, imageCompress, isImage } from '@/utils/file' @@ -14,6 +14,12 @@ const form = ref({ b_container_img: '', }) +const subFileListRef = ref() +const subFileListRef2 = ref() + +const oldSubFileList = ref([]) +const oldSubFileList2 = ref([]) + const subFileList = ref([]) // 装货照片 const subFileList2 = ref([]) // 发货单、签收单、过磅单 @@ -101,6 +107,9 @@ async function loadMainData() { subFileList2.value = allFiles .filter(f => f.mx_cate_id === '2') .map(formatFile) + + oldSubFileList.value = JSON.parse(JSON.stringify(subFileList.value)) + oldSubFileList2.value = JSON.parse(JSON.stringify(subFileList2.value)) } } catch (err) { @@ -111,51 +120,19 @@ async function loadMainData() { } } -function onItemClick(fileItem: UploadFileItem) { - console.log(fileItem) - if (!isImageUrl(fileItem.mx_mapfilename) && !isVideoUrl(fileItem.mx_mapfilename)) { - downloadFile(fileItem.mx_mapfilename, fileItem.name) - } -} - -function beforeRead(file: UploadFile): boolean | Promise { - // 非图片直接允许上传 - if (!isImage(file.name)) - return true - - // 图片异步压缩,返回修改后的 UploadFile 对象 - return imageCompress(file.path).then((res) => { - file.path = res.path - file.size = res.size - return file - }).catch((err) => { - console.error('图片压缩失败:', err) - return file +function handleBeforeRemove({ file, fileList, resolve }) { + dialog.confirm({ + title: '提示', + message: '确定删除该文件吗?', + onConfirm: () => { + resolve(true) + }, + onCancel: () => { + resolve(false) + }, }) } -function beforeRemove(_index: number, _fileItem: UploadFileItem): boolean | Promise { - return new Promise((resolve, reject) => { - dialog.confirm({ - title: '提示', - message: `确定删除该张图片吗?`, - onConfirm: () => resolve(), - onCancel: () => reject(), - onClose: () => reject(), - }) - }) -} - -function onRemove(index: number, item: UploadFileItem) { - if (item.subid) { - deleteFileApi(item.subid).then((res) => { - if (res.success) { - toast.success('删除成功') - } - }) - } -} - async function handleConfirm() { if (form.value.b_container_img === '') { toast.fail('集装箱号图片不能为空') @@ -177,91 +154,209 @@ async function handleConfirm() { transparent: false, }) - const fileInserts = [] - const fileUpdates = [] + try { + const fileInserts = [] + const fileUpdates = [] + const fileDeletes = [] - const allFiles = [ - ...subFileList.value.map(item => ({ ...item, cate: '1' })), - ...subFileList2.value.map(item => ({ ...item, cate: '2' })), - ] + // ========================= + // 当前上传组件文件 + // ========================= + const subFiles + = subFileListRef.value?.$.setupState.uploadFiles || [] - const grouped = allFiles.reduce((acc, item) => { - if (!acc[item.cate]) - acc[item.cate] = [] - acc[item.cate].push(item) - return acc - }, {}) + const subFiles2 + = subFileListRef2.value?.$.setupState.uploadFiles || [] - for (const cate in grouped) { - let index = 1 + // 当前所有文件 + const allFiles = [ + ...subFiles.map(item => ({ + ...item, + cate: '1', + })), + ...subFiles2.map(item => ({ + ...item, + cate: '2', + })), + ] - for (const fileItem of grouped[cate]) { - const mx_xh = index++ + // 原始文件 + const oldFiles = [ + ...(oldSubFileList.value || []).map(item => ({ + ...item, + cate: '1', + })), + ...(oldSubFileList2.value || []).map(item => ({ + ...item, + cate: '2', + })), + ] - // 已存在 → update - if (fileItem.subid) { - fileUpdates.push({ - subid: fileItem.subid, - mx_xh, - mx_cate_id: cate, - }) - continue + // ========================= + // 删除文件 + // ========================= + const currentSubIds = new Set( + allFiles + .map(item => item.subid) + .filter(Boolean), + ) + + fileDeletes.push( + ...oldFiles + .filter(item => + item.subid + && !currentSubIds.has(item.subid), + ) + .map(item => ({ + subid: item.subid, + })), + ) + + // ========================= + // 分类排序 + // ========================= + const grouped = allFiles.reduce((acc, item) => { + if (!acc[item.cate]) { + acc[item.cate] = [] } - // 新增 → upload - const res = await uploadContainerFileApi(fileItem.file.path, { - jobId: form.value.b_id, - containerNo: form.value.b_container_no, - fileName: fileItem.name, - }) + acc[item.cate].push(item) - if (!res.success) - continue + return acc + }, {}) - fileInserts.push({ - subid: res.data.uid, - father: form.value.b_id, - mx_xh, - mx_filename: res.data.fileName, - mx_filesize: fileItem.file.size, - mx_fileext: getFileExtension(fileItem.file.name), - mx_mapfilename: res.data.path, - mx_moduleid: 'b_container', - mx_cate_id: cate, - }) + // ========================= + // 处理新增/更新 + // ========================= + for (const cate in grouped) { + let index = 1 - fileItem.subid = res.data.uid + for (const fileItem of grouped[cate]) { + const mx_xh = index++ + + // 已存在 → update + if (fileItem.subid) { + fileUpdates.push({ + subid: fileItem.subid, + mx_xh, + mx_cate_id: cate, + }) + + continue + } + + try { + // 上传路径 + let uploadPath + = fileItem.path + || fileItem.url + || fileItem.tempFilePath + + // 图片压缩 + if (isImage(fileItem.name)) { + const compressRes = await imageCompress(uploadPath) + + uploadPath = compressRes.path + } + + // 上传文件 + const res = await uploadContainerFileApi( + uploadPath, + { + jobId: form.value.b_id, + containerNo: form.value.b_container_no, + fileName: fileItem.name, + }, + ) + + if (!res.success) { + continue + } + + // 新增记录 + fileInserts.push({ + subid: res.data.uid, + father: form.value.b_id, + mx_xh, + mx_filename: res.data.fileName, + mx_filesize: fileItem.size, + mx_fileext: getFileExtension(fileItem.name), + mx_mapfilename: res.data.path, + mx_moduleid: 'b_container', + mx_cate_id: cate, + }) + + // 回填 subid + fileItem.subid = res.data.uid + } + catch (err) { + console.error('附件上传失败:', fileItem, err) + } + } } - } - if (fileInserts.length === 0 && fileUpdates.length === 0) { - toast.success('保存成功') + // ========================= + // 先删除物理文件 + // ========================= + if (fileDeletes.length > 0) { + const deleteRes = await deleteFilesApi( + fileDeletes.map(item => item.subid), + ) - setTimeout(() => { - loadMainData() - }, 1000) - return - } + if (!deleteRes.success) { + toast.fail('删除文件失败') - const reqData = [ - { - tableName: 'bf_file', - keyField: 'subid', - inserts: fileInserts, - updates: fileUpdates, - deletes: [], - }, - ] + return + } + } - saveObjectApi(reqData).then((res) => { - if (res.success) { + // ========================= + // 无新增/更新 + // 删除已经单独处理了 + // ========================= + if ( + fileInserts.length === 0 + && fileUpdates.length === 0 + ) { toast.success('保存成功') - setTimeout(() => { - loadMainData() - }, 1000) + return } - }) + + // ========================= + // 保存数据 + // ========================= + const reqData = [ + { + tableName: 'bf_file', + keyField: 'subid', + inserts: fileInserts, + updates: fileUpdates, + deletes: [], + }, + ] + + const res = await saveObjectApi(reqData) + + if (res.success) { + toast.success('保存成功') + } + else { + toast.fail('保存失败') + } + } + catch (err) { + console.error(err) + + toast.fail('保存失败') + } + finally { + setTimeout(() => { + toast.hide() + + loadMainData() + }, 1000) + } } // 集装箱号校验 @@ -385,13 +480,14 @@ const templateCollapse = ref(['template1']) - @@ -406,13 +502,14 @@ const templateCollapse = ref(['template1']) - diff --git a/code/container-ocr/ocr-uniapp/src/pages-sub/upload/index.vue b/code/container-ocr/ocr-uniapp/src/pages-sub/upload/index.vue index 5b99a2d0..b79fcf9e 100644 --- a/code/container-ocr/ocr-uniapp/src/pages-sub/upload/index.vue +++ b/code/container-ocr/ocr-uniapp/src/pages-sub/upload/index.vue @@ -19,6 +19,9 @@ const form = ref({ ocrNo: '', }) +const subFileListRef = ref() +const subFileListRef2 = ref() + const subFileList = ref([]) // 装货照片 const subFileList2 = ref([]) // 发货单、签收单、过磅单 @@ -114,38 +117,16 @@ function handleDeleteBoxImage() { resetForm() } -function onItemClick(fileItem: UploadFileItem) { - console.log(fileItem) - if (!isImageUrl(fileItem.mx_mapfilename) && !isVideoUrl(fileItem.mx_mapfilename)) { - downloadFile(fileItem.mx_mapfilename, fileItem.name) - } -} - -function beforeRead(file: UploadFile): boolean | Promise { - // 非图片直接允许上传 - if (!isImage(file.name)) - return true - - // 图片异步压缩,返回修改后的 UploadFile 对象 - return imageCompress(file.path).then((res) => { - file.path = res.path - file.size = res.size - return file - }).catch((err) => { - console.error('图片压缩失败:', err) - return file - }) -} - -function beforeRemove(_index: number, _fileItem: UploadFileItem): boolean | Promise { - return new Promise((resolve, reject) => { - dialog.confirm({ - title: '提示', - message: `确定删除该张图片吗?`, - onConfirm: () => resolve(), - onCancel: () => reject(), - onClose: () => reject(), - }) +function handleBeforeRemove({ file, fileList, resolve }) { + dialog.confirm({ + title: '提示', + message: '确定删除该文件吗?', + onConfirm: () => { + resolve(true) + }, + onCancel: () => { + resolve(false) + }, }) } @@ -155,7 +136,7 @@ async function handleConfirm() { return } - if (form.value.b_container_no === '') { + if (!form.value.b_container_no) { toast.fail('集装箱号不能为空') return } @@ -170,112 +151,154 @@ async function handleConfirm() { transparent: false, }) - const mainTable = { - b_id: form.value.b_id, - b_container_no: form.value.b_container_no, - b_container_img: form.value.b_container_img, - b_ocr_no: form.value.ocrNo, - b_ocr_score: form.value.ocrScore || 0.00, - } - const fileInserts = [] + try { + const mainTable = { + b_id: form.value.b_id, + b_container_no: form.value.b_container_no, + b_container_img: form.value.b_container_img, + b_ocr_no: form.value.ocrNo, + b_ocr_score: form.value.ocrScore || 0.00, + } - // 主表 - await uploadContainerFileApi(boxImage.value.path, { - jobId: form.value.b_id, - containerNo: form.value.b_container_no, - fileName: boxImage.value.name, - }).then((res) => { - if (res.success) { - mainTable.b_container_img = res.data.path + const fileInserts = [] + + // ========================= + // 上传主图 + // ========================= + const mainRes = await uploadContainerFileApi( + boxImage.value.path, + { + jobId: form.value.b_id, + containerNo: form.value.b_container_no, + fileName: boxImage.value.name, + }, + ) + + if (mainRes.success) { + mainTable.b_container_img = mainRes.data.path fileInserts.push({ - subid: res.data.uid, + subid: mainRes.data.uid, father: form.value.b_id, mx_xh: 0, - mx_filename: res.data.fileName, + mx_filename: mainRes.data.fileName, mx_filesize: boxImage.value.size, mx_fileext: getFileExtension(boxImage.value.name), - mx_mapfilename: res.data.path, + mx_mapfilename: mainRes.data.path, mx_moduleid: 'b_container', mx_cate_id: '0', }) } - }) - const indexMap = {} + // ========================= + // 附件排序 + // ========================= + const indexMap = {} - const getNextIndex = (cate) => { - if (!indexMap[cate]) { - indexMap[cate] = 1 + const getNextIndex = (cate) => { + if (!indexMap[cate]) { + indexMap[cate] = 1 + } + + return indexMap[cate]++ } - return indexMap[cate]++ - } - const allFiles = [ - ...subFileList.value.map(item => ({ - ...item, - cate: '1', - })), - ...subFileList2.value.map(item => ({ - ...item, - cate: '2', - })), - ] + // ========================= + // 获取附件 + // ========================= + const subFiles = subFileListRef.value?.$.setupState.uploadFiles || [] + const subFiles2 = subFileListRef2.value?.$.setupState.uploadFiles || [] - for (const fileItem of allFiles) { - const res = await uploadContainerFileApi(fileItem.file.path, { - jobId: form.value.b_id, - containerNo: form.value.b_container_no, - fileName: fileItem.name, - }) + const allFiles = [ + ...subFiles.map(item => ({ + ...item, + cate: '1', + })), + ...subFiles2.map(item => ({ + ...item, + cate: '2', + })), + ] - if (!res.success) - continue + // ========================= + // 上传附件 + // ========================= + for (const fileItem of allFiles) { + try { + let uploadPath = fileItem.url - fileInserts.push({ - subid: res.data.uid, - father: form.value.b_id, - mx_xh: getNextIndex(fileItem.cate), - mx_filename: res.data.fileName, - mx_filesize: fileItem.file.size, - mx_fileext: getFileExtension(fileItem.file.name), - mx_mapfilename: res.data.path, - mx_moduleid: 'b_container', - mx_cate_id: fileItem.cate, - }) - } + // 图片压缩 + if (isImage(fileItem.name)) { + const compressRes = await imageCompress(fileItem.url) + uploadPath = compressRes.path + } - const reqData = [ - { - tableName: 'b_container', - keyField: 'b_id', - inserts: [mainTable], - updates: [], - deletes: [], - }, - { - tableName: 'bf_file', - keyField: 'subid', - inserts: fileInserts, - updates: [], - deletes: [], - }, - ] + const res = await uploadContainerFileApi(uploadPath, { + jobId: form.value.b_id, + containerNo: form.value.b_container_no, + fileName: fileItem.name, + }) - saveObjectApi(reqData).then((res) => { - if (res.success) { + if (!res.success) { + continue + } + + fileInserts.push({ + subid: res.data.uid, + father: form.value.b_id, + mx_xh: getNextIndex(fileItem.cate), + mx_filename: res.data.fileName, + mx_filesize: fileItem.size, + mx_fileext: getFileExtension(fileItem.name), + mx_mapfilename: res.data.path, + mx_moduleid: 'b_container', + mx_cate_id: fileItem.cate, + }) + } + catch (err) { + console.error('附件上传失败:', fileItem, err) + } + } + + // ========================= + // 保存数据 + // ========================= + const reqData = [ + { + tableName: 'b_container', + keyField: 'b_id', + inserts: [mainTable], + updates: [], + deletes: [], + }, + { + tableName: 'bf_file', + keyField: 'subid', + inserts: fileInserts, + updates: [], + deletes: [], + }, + ] + + const saveRes = await saveObjectApi(reqData) + + if (saveRes.success) { toast.success('保存成功') + tipContainerNo.value = form.value.b_container_no showResult.value = true } else { toast.fail('保存失败') } - }).catch(() => { + } + catch (err) { + console.error(err) toast.fail('保存失败') - }).finally(() => { + } + finally { toast.hide() - }) + } } // 集装箱号校验 @@ -446,12 +469,14 @@ const templateCollapse = ref(['template1']) - @@ -465,12 +490,14 @@ const templateCollapse = ref(['template1']) - diff --git a/code/container-ocr/ocr-uniapp/src/request/api.ts b/code/container-ocr/ocr-uniapp/src/request/api.ts index 1b0aac73..345398eb 100644 --- a/code/container-ocr/ocr-uniapp/src/request/api.ts +++ b/code/container-ocr/ocr-uniapp/src/request/api.ts @@ -48,6 +48,10 @@ export function deleteFileApi(subid) { }) } +export function deleteFilesApi(subids: any[]) { + return httpPost(`file/deletes`, subids) +} + export function deleteAliyunFileApi(fileUrl) { return httpPost(`/file/deleteAliyunFile`, { bucketName: aliyunBucket, diff --git a/code/container-ocr/ocr-uniapp/src/utils/file.ts b/code/container-ocr/ocr-uniapp/src/utils/file.ts index e74ec005..e2eec576 100644 --- a/code/container-ocr/ocr-uniapp/src/utils/file.ts +++ b/code/container-ocr/ocr-uniapp/src/utils/file.ts @@ -126,35 +126,63 @@ export function formatFileSize(size: number): string { /** 获取文件名:从 URL 提取最后一段 */ function getFileName(fileUrl: string) { - return decodeURIComponent(fileUrl.split('/').pop() || '未命名文件') + return decodeURIComponent( + fileUrl.split('/').pop() || '未命名文件', + ) } -/** 获取文件后缀 */ -export function getFileExtension(fileUrl: string) { - const clean = fileUrl.split('?')[0].split('#')[0].trim() +/** 获取文件后缀(根据文件名) */ +export function getFileExtension(fileName: string) { + const clean = fileName + .split('?')[0] + .split('#')[0] + .trim() + const lastDot = clean.lastIndexOf('.') - return lastDot === -1 ? '' : clean.substring(lastDot + 1).toLowerCase() + + return lastDot === -1 + ? '' + : clean.substring(lastDot + 1).toLowerCase() } -/** 文件类型判断 */ -export function isImage(fileUrl: string) { - return ['jpg', 'jpeg', 'png', 'gif', 'webp', 'bmp'].includes(getFileExtension(fileUrl)) +/** 文件类型判断(根据文件名) */ +export function isImage(fileName: string) { + return [ + 'jpg', + 'jpeg', + 'png', + 'gif', + 'webp', + 'bmp', + ].includes(getFileExtension(fileName)) } -export function isVideo(fileUrl: string) { - return ['mp4', 'avi', 'mov', 'mkv', 'flv', 'wmv', '3gp'].includes(getFileExtension(fileUrl)) +export function isVideo(fileName: string) { + return [ + 'mp4', + 'avi', + 'mov', + 'mkv', + 'flv', + 'wmv', + '3gp', + ].includes(getFileExtension(fileName)) } /** =================== 下载入口 =================== */ -export function downloadFile(fileUrl: string, fileName?: string) { - const type: 'image' | 'video' | 'file' = isImage(fileUrl) - ? 'image' - : isVideo(fileUrl) - ? 'video' - : 'file' - +export function downloadFile( + fileUrl: string, + fileName?: string, +) { const finalName = fileName ?? getFileName(fileUrl) + const type: 'image' | 'video' | 'file' + = isImage(finalName) + ? 'image' + : isVideo(finalName) + ? 'video' + : 'file' + if (isH5) { downloadH5(fileUrl, finalName) } @@ -165,7 +193,6 @@ export function downloadFile(fileUrl: string, fileName?: string) { downloadApp(fileUrl, type, finalName) } } - /** =================== H5 下载 =================== */ async function downloadH5(fileUrl: string, fileName: string) { try { diff --git a/code/container-ocr/ocr-vue/components.d.ts b/code/container-ocr/ocr-vue/components.d.ts index 52fa9721..39ff9c4a 100644 --- a/code/container-ocr/ocr-vue/components.d.ts +++ b/code/container-ocr/ocr-vue/components.d.ts @@ -18,7 +18,6 @@ declare module 'vue' { ElDatePicker: typeof import('element-plus/es')['ElDatePicker'] ElDialog: typeof import('element-plus/es')['ElDialog'] ElDivider: typeof import('element-plus/es')['ElDivider'] - ElDrawer: typeof import('element-plus/es')['ElDrawer'] ElDropdown: typeof import('element-plus/es')['ElDropdown'] ElDropdownItem: typeof import('element-plus/es')['ElDropdownItem'] ElDropdownMenu: typeof import('element-plus/es')['ElDropdownMenu'] @@ -28,23 +27,16 @@ declare module 'vue' { ElInput: typeof import('element-plus/es')['ElInput'] ElMenu: typeof import('element-plus/es')['ElMenu'] ElMenuItem: typeof import('element-plus/es')['ElMenuItem'] - ElOption: typeof import('element-plus/es')['ElOption'] ElPagination: typeof import('element-plus/es')['ElPagination'] ElPopover: typeof import('element-plus/es')['ElPopover'] ElRadio: typeof import('element-plus/es')['ElRadio'] ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup'] ElResult: typeof import('element-plus/es')['ElResult'] ElScrollbar: typeof import('element-plus/es')['ElScrollbar'] - ElSelect: typeof import('element-plus/es')['ElSelect'] ElSplitter: typeof import('element-plus/es')['ElSplitter'] ElSplitterPanel: typeof import('element-plus/es')['ElSplitterPanel'] ElSubMenu: typeof import('element-plus/es')['ElSubMenu'] ElSwitch: typeof import('element-plus/es')['ElSwitch'] - ElTable: typeof import('element-plus/es')['ElTable'] - ElTableColumn: typeof import('element-plus/es')['ElTableColumn'] - ElTabPane: typeof import('element-plus/es')['ElTabPane'] - ElTabs: typeof import('element-plus/es')['ElTabs'] - ElText: typeof import('element-plus/es')['ElText'] ElTooltip: typeof import('element-plus/es')['ElTooltip'] ElTree: typeof import('element-plus/es')['ElTree'] G3Column: typeof import('./src/components/g3-table/g3-column.vue')['default']