From 364d29dbaa80967d0269b9d02fdf1c58832e3cfe Mon Sep 17 00:00:00 2001 From: ZhangAo Date: Mon, 11 May 2026 17:32:43 +0800 Subject: [PATCH] 20260511173242 --- .../g3soft/controller/DataSaveController.java | 3 + .../cn/g3soft/controller/FileController.java | 19 +- .../cn/g3soft/controller/OcrController.java | 1 - .../main/java/cn/g3soft/utils/HttpUtils.java | 18 +- .../src/main/resources/application-dev.yml | 2 +- .../src/main/resources/application.yml | 5 +- .../main/resources/dbconfigs/g3hd.properties | 14 +- .../ocr-uniapp/src/pages-sub/upload/index.vue | 32 +- .../ocr-uniapp/src/request/index.ts | 52 +- code/container-ocr/ocr-vue/.env | 7 +- code/container-ocr/ocr-vue/.env.development | 1 + code/container-ocr/ocr-vue/.env.production | 1 + code/container-ocr/ocr-vue/components.d.ts | 8 + .../components/g3-container-file/index.vue | 12 +- .../container-ocr/ocr-vue/src/plugins/icon.js | 12 +- .../ocr-vue/src/store/permission.js | 20 +- .../ocr-vue/src/views/container/index.vue | 20 +- .../ocr-vue/src/views/system/log/data.vue | 11 +- code/jsp/editorder_s_cw.jsp | 2403 +++++++++++++++++ code/jsp/js/draft-page-manager.js | 439 +++ 20 files changed, 2992 insertions(+), 88 deletions(-) create mode 100644 code/container-ocr/ocr-vue/.env.development create mode 100644 code/container-ocr/ocr-vue/.env.production create mode 100644 code/jsp/editorder_s_cw.jsp create mode 100644 code/jsp/js/draft-page-manager.js diff --git a/code/container-ocr/ocr-springboot/src/main/java/cn/g3soft/controller/DataSaveController.java b/code/container-ocr/ocr-springboot/src/main/java/cn/g3soft/controller/DataSaveController.java index 2e9cc8a6..63d593ad 100644 --- a/code/container-ocr/ocr-springboot/src/main/java/cn/g3soft/controller/DataSaveController.java +++ b/code/container-ocr/ocr-springboot/src/main/java/cn/g3soft/controller/DataSaveController.java @@ -276,6 +276,9 @@ public class DataSaveController { mapData.put("b_option",operation); mapData.put("b_datas",dataStr); + mapData.put("b_inputdatetime",dateTime); + mapData.put("b_inputuser_id",userId); + logList.add(mapData); } } 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 b24ed5d8..3964a783 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 @@ -4,6 +4,7 @@ import cn.g3soft.config.FileConfig; import cn.g3soft.context.UserContext; import cn.g3soft.utils.*; import cn.g3soft.utils.uniqueId.idgen.UniqueId; +import com.fasterxml.jackson.databind.ObjectMapper; import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; import org.apache.poi.ss.usermodel.DateUtil; @@ -286,11 +287,27 @@ public class FileController { // 6. 删除数据库 dbUtils.deleteById("bf_file", "subid", subid); - return Result.ok(); + // 7. 记录日志 + 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/java/cn/g3soft/controller/OcrController.java b/code/container-ocr/ocr-springboot/src/main/java/cn/g3soft/controller/OcrController.java index 7b352769..c30644e5 100644 --- a/code/container-ocr/ocr-springboot/src/main/java/cn/g3soft/controller/OcrController.java +++ b/code/container-ocr/ocr-springboot/src/main/java/cn/g3soft/controller/OcrController.java @@ -26,7 +26,6 @@ public class OcrController { String fileUrl = (String) params.get("fileUrl"); String requestUrl = "http://127.0.0.1:8867/ocr"; -// String requestUrl = "http://127.0.0.1:8867/paddlex/ocr"; Map reqPayload = new HashMap<>(); reqPayload.put("file", fileUrl); diff --git a/code/container-ocr/ocr-springboot/src/main/java/cn/g3soft/utils/HttpUtils.java b/code/container-ocr/ocr-springboot/src/main/java/cn/g3soft/utils/HttpUtils.java index f0188159..14a1bf69 100644 --- a/code/container-ocr/ocr-springboot/src/main/java/cn/g3soft/utils/HttpUtils.java +++ b/code/container-ocr/ocr-springboot/src/main/java/cn/g3soft/utils/HttpUtils.java @@ -8,11 +8,6 @@ import java.util.concurrent.TimeUnit; import com.fasterxml.jackson.databind.ObjectMapper; import okhttp3.*; -/** - * 通用http发送方法 - * - * @author ruoyi - */ public class HttpUtils { private static final ObjectMapper MAPPER = new ObjectMapper(); @@ -87,19 +82,20 @@ public class HttpUtils // ==================== POST JSON(Map版本)==================== public static String postJson(String url, Map params) throws Exception { - // 1. Map 转 JSON 字符串 - String json = MAPPER.writeValueAsString(params); + RequestBody body = RequestBody.create( + MAPPER.writeValueAsString(params), + JSON + ); - // 2. 构建请求体 - RequestBody body = RequestBody.create(json, JSON); + OkHttpClient tempClient = client.newBuilder() + .build(); Request request = new Request.Builder() .url(url) .post(body) .build(); - // 3. 执行请求 - try (Response response = client.newCall(request).execute()) { + try (Response response = tempClient.newCall(request).execute()) { return response.body() != null ? response.body().string() : null; } } diff --git a/code/container-ocr/ocr-springboot/src/main/resources/application-dev.yml b/code/container-ocr/ocr-springboot/src/main/resources/application-dev.yml index 3a86beb4..462f2eef 100644 --- a/code/container-ocr/ocr-springboot/src/main/resources/application-dev.yml +++ b/code/container-ocr/ocr-springboot/src/main/resources/application-dev.yml @@ -4,4 +4,4 @@ server: port: 80 file: - server-url: http://192.168.5.6:80/api + server-url: http://192.168.1.137:80/api 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 9ebdc113..0e5ca111 100644 --- a/code/container-ocr/ocr-springboot/src/main/resources/application.yml +++ b/code/container-ocr/ocr-springboot/src/main/resources/application.yml @@ -1,7 +1,4 @@ server: - servlet: -# context-path: / # 应用的访问路径 -# context-path: /api/ # 应用的访问路径 tomcat: uri-encoding: UTF-8 # URI编码 accept-count: 1000 # 连接数满后的排队数 @@ -19,7 +16,7 @@ spring: time-zone: "Asia/Shanghai" date-format: yyyy-MM-dd HH:mm:ss profiles: - active: dev + active: build 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 b3f87b91..ebae3d85 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;encrypt=false -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;encrypt=false #username=sa -#password=123456@aaa +#password=zhang520.. #driver=com.microsoft.sqlserver.jdbc.SQLServerDriver +url=jdbc:sqlserver://127.0.0.1:1433;databaseName=G3ContainerOCR;encrypt=false +username=sa +password=123456@aaa +driver=com.microsoft.sqlserver.jdbc.SQLServerDriver + 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 78e31249..5b99a2d0 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 @@ -54,9 +54,16 @@ function handleChooseBox() { imageCompress(tempFile.path).then((compressRes) => { form.value.b_container_img = compressRes.path + const fileName = tempFile.name || `image_${Date.now()}.jpg` + boxImage.value = { + ...tempFile, + name: fileName, + path: compressRes.path, + size: compressRes.size, + } uploadTempFileApi(compressRes.path, { - fileName: tempFile.name, + fileName, }).then((res) => { if (res.success) { recognizeOcrBoxApi({ @@ -92,12 +99,15 @@ const computedOcrScore = computed(() => { function resetForm() { boxImage.value = null form.value.b_container_no = '' + form.value.b_container_img = '' form.value.ocrNo = '' form.value.ocrScore = 0.00 showResult.value = false isError.value = false ocrFinish.value = false + subFileList.value = [] + subFileList2.value = [] } function handleDeleteBoxImage() { @@ -140,7 +150,7 @@ function beforeRemove(_index: number, _fileItem: UploadFileItem): boolean | Prom } async function handleConfirm() { - if (form.value.b_container_img === '') { + if (!boxImage.value) { toast.fail('集装箱号图片不能为空') return } @@ -258,6 +268,13 @@ async function handleConfirm() { tipContainerNo.value = form.value.b_container_no showResult.value = true } + else { + toast.fail('保存失败') + } + }).catch(() => { + toast.fail('保存失败') + }).finally(() => { + toast.hide() }) } @@ -279,19 +296,8 @@ async function continueAdd() { const idRes = await getUniqueIdApi() if (idRes.success) { - boxImage.value = null - - ocrFinish.value = false - isError.value = false - resetForm() form.value.b_id = idRes.data - - subFileList.value = [] - subFileList2.value = [] - - showResult.value = false - tipContainerNo.value = '' } } diff --git a/code/container-ocr/ocr-uniapp/src/request/index.ts b/code/container-ocr/ocr-uniapp/src/request/index.ts index fea8ae83..4269d967 100644 --- a/code/container-ocr/ocr-uniapp/src/request/index.ts +++ b/code/container-ocr/ocr-uniapp/src/request/index.ts @@ -6,26 +6,45 @@ import { joinUrl } from '@/utils/common' import { isH5 } from '@/utils/platform' +let dbJsonCache: Record | null = null +let dbJsonPromise: Promise> | null = null + /** * ====================== - * 读取机构配置 + * 读取机构配置(带缓存) * ====================== */ function readDbJson(): Promise> { - return new Promise((resolve, reject) => { + if (dbJsonCache) { + return Promise.resolve(dbJsonCache) + } + + if (dbJsonPromise) { + return dbJsonPromise + } + + dbJsonPromise = new Promise((resolve, reject) => { if (isH5) { - const timestamp = Date.now() uni.request({ - url: `/g3ocr-app/static/db.json?t=${timestamp}`, + url: '/g3ocr-app/static/db.json', method: 'GET', - success: r => resolve(r.data as Record), - fail: err => reject(err), + success: (r) => { + dbJsonCache = r.data as Record + resolve(dbJsonCache) + }, + fail: (err) => { + dbJsonPromise = null + reject(err) + }, }) } else { - resolve(dbJson as Record) + dbJsonCache = dbJson as Record + resolve(dbJsonCache) } }) + + return dbJsonPromise } /** @@ -38,23 +57,7 @@ export async function getOrgBaseUrl(orgid: string): Promise { return '' } - let dbRes: Record = {} - - // 读取配置(和你原逻辑保持一致) - if (isH5) { - const timestamp = Date.now() - dbRes = await new Promise((resolve, reject) => { - uni.request({ - url: `/g3ocr-app/static/db.json?t=${timestamp}`, - method: 'GET', - success: res => resolve(res.data as Record), - fail: err => reject(err), - }) - }) - } - else { - dbRes = dbJson as Record - } + const dbRes = await readDbJson() if (!dbRes || Object.keys(dbRes).length === 0) { throw new Error('机构配置获取失败') @@ -66,7 +69,6 @@ export async function getOrgBaseUrl(orgid: string): Promise { throw new Error('机构码无效') } - // 👉 关键:只返回原始 JSON 里的值 return baseUrl } diff --git a/code/container-ocr/ocr-vue/.env b/code/container-ocr/ocr-vue/.env index 4da995fd..d34737e5 100644 --- a/code/container-ocr/ocr-vue/.env +++ b/code/container-ocr/ocr-vue/.env @@ -1,6 +1,6 @@ # Application # 应用名称(用于标题、日志等) -PUBLIC_APP_NAME=g3ocr +PUBLIC_APP_NAME=集装箱装货影像采集 # Server # 应用部署基础路径(路由和静态资源 base) @@ -8,9 +8,4 @@ PUBLIC_SERVER_PATH=/g3ocr/ # 本地开发服务器端口 PUBLIC_SERVER_PORT=8080 -# API -# 后端 API 基础地址 -# PUBLIC_API_BASE_URL=http://ser369.g3soft.cn:80/api -PUBLIC_API_BASE_URL=http://192.168.5.6:80/api - PUBLIC_ALIYUN_BUCKET = g3hd diff --git a/code/container-ocr/ocr-vue/.env.development b/code/container-ocr/ocr-vue/.env.development new file mode 100644 index 00000000..2988bd40 --- /dev/null +++ b/code/container-ocr/ocr-vue/.env.development @@ -0,0 +1 @@ +PUBLIC_API_BASE_URL=http://192.168.1.137:80/api diff --git a/code/container-ocr/ocr-vue/.env.production b/code/container-ocr/ocr-vue/.env.production new file mode 100644 index 00000000..9335023a --- /dev/null +++ b/code/container-ocr/ocr-vue/.env.production @@ -0,0 +1 @@ +PUBLIC_API_BASE_URL=http://ser369.g3soft.cn:80/api \ No newline at end of file diff --git a/code/container-ocr/ocr-vue/components.d.ts b/code/container-ocr/ocr-vue/components.d.ts index 39ff9c4a..52fa9721 100644 --- a/code/container-ocr/ocr-vue/components.d.ts +++ b/code/container-ocr/ocr-vue/components.d.ts @@ -18,6 +18,7 @@ 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'] @@ -27,16 +28,23 @@ 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'] diff --git a/code/container-ocr/ocr-vue/src/components/g3-container-file/index.vue b/code/container-ocr/ocr-vue/src/components/g3-container-file/index.vue index 89b2a1f8..9f72c365 100644 --- a/code/container-ocr/ocr-vue/src/components/g3-container-file/index.vue +++ b/code/container-ocr/ocr-vue/src/components/g3-container-file/index.vue @@ -630,6 +630,16 @@ function handleBatchDelete() { } async function deleteFiles(files) { + // ===== 新增:校验 mx_cate_id ===== + const protectedFiles = files.filter((item) => Number(item.mx_cate_id) === 0); + + if (protectedFiles.length > 0) { + const names = protectedFiles.map((item) => item.mx_filename).join(","); + + ElMessage.warning(`文件【${names}】属于箱门照,不允许删除`); + return; + } + // 收集文件的 mx_filename const filenames = files.map((file) => file.mx_filename).join(", "); @@ -673,7 +683,7 @@ async function deleteFiles(files) { } }); } -// 保存 + // 保存 async function handleSave() { if (cateId.value !== "1" && cateId.value !== "2") { diff --git a/code/container-ocr/ocr-vue/src/plugins/icon.js b/code/container-ocr/ocr-vue/src/plugins/icon.js index 7940cee0..ae0aed25 100644 --- a/code/container-ocr/ocr-vue/src/plugins/icon.js +++ b/code/container-ocr/ocr-vue/src/plugins/icon.js @@ -3,12 +3,12 @@ */ import { addCollection } from "@iconify/vue"; -import Lucide from "@iconify/json/json/lucide.json"; -import ElementPlus from "@iconify/json/json/ep.json"; -import Mingcute from "@iconify/json/json/mingcute.json"; +// import Lucide from "@iconify/json/json/lucide.json"; +// import ElementPlus from "@iconify/json/json/ep.json"; +// import Mingcute from "@iconify/json/json/mingcute.json"; export function SetupIcons() { - addCollection(Lucide); - addCollection(ElementPlus); - addCollection(Mingcute); + // addCollection(Lucide); + // addCollection(ElementPlus); + // addCollection(Mingcute); } diff --git a/code/container-ocr/ocr-vue/src/store/permission.js b/code/container-ocr/ocr-vue/src/store/permission.js index 3fd454d8..bd471563 100644 --- a/code/container-ocr/ocr-vue/src/store/permission.js +++ b/code/container-ocr/ocr-vue/src/store/permission.js @@ -76,16 +76,28 @@ export const usePermissionStore = defineStore("permission", () => { } const moduleid = route.meta.moduleId; - if (!moduleid) return false; - if (!hasModulePermission(moduleid)) return false; + if (!moduleid) { + return false; + } + + const hasModule = hasModulePermission(moduleid); + + if (!hasModule) { + return false; + } const actions = actionPermissions.value.filter((item) => item.ModuleID === moduleid); const action = actions.find((item) => Number(item.b_ivalue) === Number(id)); - if (!action) return false; - if (action.b_canuse === "0") return false; + if (!action) { + return false; + } + + if (action.b_canuse === "0") { + return false; + } // 其他情况允许 return true; diff --git a/code/container-ocr/ocr-vue/src/views/container/index.vue b/code/container-ocr/ocr-vue/src/views/container/index.vue index e06bc10f..ea0ae934 100644 --- a/code/container-ocr/ocr-vue/src/views/container/index.vue +++ b/code/container-ocr/ocr-vue/src/views/container/index.vue @@ -89,6 +89,7 @@ const handleSizeChange = (val) => { loadTableDatas(); }; + const handleCurrentChange = (val) => { pagination.page = val; @@ -229,7 +230,7 @@ async function deleteRows(rows = []) { keyField: "b_id", inserts: [], updates: [], - deletes: deleteIds.map((id) => ({ b_id: id })), + deletes: rows, }, ]; @@ -295,7 +296,11 @@ async function handleDownloadOne(data) { }); try { - const fileRes = await loadDataApi("bf_file", `father = ${data.b_id}`, "mx_cate_id asc,mx_xh asc"); + const fileRes = await loadDataApi( + "bf_file", + `father = ${data.b_id}`, + "mx_cate_id asc,mx_xh asc", + ); if (!fileRes.success) { ElMessage.error("获取附件失败"); @@ -369,7 +374,11 @@ async function handleDownloadBatch() { const containerCountMap = new Map(); for (const item of records) { - const fileRes = await loadDataApi("bf_file", `father='${item.b_id}'`, "mx_cate_id asc,mx_xh asc"); + const fileRes = await loadDataApi( + "bf_file", + `father='${item.b_id}'`, + "mx_cate_id asc,mx_xh asc", + ); const files = (fileRes.success && fileRes.data) || []; totalFiles += files.length; @@ -657,7 +666,10 @@ function buildFileName(containerNo, index, fileName) {