20260511173242

This commit is contained in:
oneao committed 2026-05-11 17:32:43 +08:00
1 parent 56f5ba4e6b
commit 364d29dbaa
20 files changed
+2992 -88

No files matched your search

@@ -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);
}
}
@@ -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<String,Object> 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());
}
}
}
@@ -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<String, Object> reqPayload = new HashMap<>();
reqPayload.put("file", fileUrl);
@@ -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<String, Object> 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;
}
}
@@ -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
@@ -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
@@ -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
@@ -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 = ''
}
}
@@ -6,26 +6,45 @@ import { joinUrl } from '@/utils/common'
import { isH5 } from '@/utils/platform'
let dbJsonCache: Record<string, string> | null = null
let dbJsonPromise: Promise<Record<string, string>> | null = null
/**
* ======================
* 读取机构配置
* 读取机构配置(带缓存)
* ======================
*/
function readDbJson(): Promise<Record<string, string>> {
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<string, string>),
fail: err => reject(err),
success: (r) => {
dbJsonCache = r.data as Record<string, string>
resolve(dbJsonCache)
},
fail: (err) => {
dbJsonPromise = null
reject(err)
},
})
}
else {
resolve(dbJson as Record<string, string>)
dbJsonCache = dbJson as Record<string, string>
resolve(dbJsonCache)
}
})
return dbJsonPromise
}
/**
@@ -38,23 +57,7 @@ export async function getOrgBaseUrl(orgid: string): Promise<string> {
return ''
}
let dbRes: Record<string, string> = {}
// 读取配置(和你原逻辑保持一致)
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<string, string>),
fail: err => reject(err),
})
})
}
else {
dbRes = dbJson as Record<string, string>
}
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<string> {
throw new Error('机构码无效')
}
// 👉 关键:只返回原始 JSON 里的值
return baseUrl
}
+1 -6
View File
@@ -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
@@ -0,0 +1 @@
PUBLIC_API_BASE_URL=http://192.168.1.137:80/api
@@ -0,0 +1 @@
PUBLIC_API_BASE_URL=http://ser369.g3soft.cn:80/api
+8
View File
@@ -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']
@@ -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") {
@@ -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);
}
@@ -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;
@@ -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) {
</el-button>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item @click="handleUpdateShow(row)">
<el-dropdown-item
@click="handleUpdateShow(row)"
:disabled="!permissionStore.hasActionPermission(2)"
>
<el-icon class="el-icon--left">
<G3Icon icon="lucide:refresh-ccw" />
</el-icon>
@@ -76,15 +76,15 @@ async function loadTableDatas() {
}
if (searchForm.value.datas) {
searchCondition += `b_datas LIKE '${searchForm.value.datas}' AND `;
searchCondition += `b_datas LIKE '%${searchForm.value.datas}%' AND `;
}
if (searchForm.value.option) {
searchCondition += `b_option LIKE '${searchForm.value.option}' AND `;
searchCondition += `b_option LIKE '%${searchForm.value.option}%' AND `;
}
if (searchForm.value.table) {
searchCondition += `b_table LIKE '${searchForm.value.table}' AND `;
searchCondition += `b_table LIKE '%${searchForm.value.table}%' AND `;
}
if (searchCondition.endsWith(" AND ")) {
@@ -250,8 +250,11 @@ function handleSearchReset() {
showIcon: false,
trigger: 'cell',
}"
:cell-config="{
height: 'auto',
}"
height="100%"
show-overflow
:show-overflow="false"
show-header-overflow
>
<vxe-column field="seq" type="seq" width="50" align="center" title=" " fixed="left" />