diff --git a/admin/src/router/index.ts b/admin/src/router/index.ts index 9725610..19f9fa4 100644 --- a/admin/src/router/index.ts +++ b/admin/src/router/index.ts @@ -2,6 +2,7 @@ import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router' import Shell from '../views/Shell.vue' const routes: RouteRecordRaw[] = [ + { path: '/admin/login', component: () => import('../views/admin/Login.vue') }, { path: '/', component: Shell, @@ -15,8 +16,9 @@ const routes: RouteRecordRaw[] = [ { path: 'parts/templates', component: () => import('../views/parts/Templates.vue') }, { path: 'consult', component: () => import('../views/consult/ConsultList.vue') } ,{ path: 'notice/list', component: () => import('../views/notice/NoticeList.vue') } - ,{ path: 'dict/units', component: () => import('../views/dict/Units.vue') } + ,{ path: 'dict/categories', component: () => import('../views/dict/Categories.vue') } + ,{ path: 'normal-admin/applications', component: () => import('../views/normal-admin/Applications.vue') } ] } ] diff --git a/admin/src/views/Shell.vue b/admin/src/views/Shell.vue index c2c7212..5c843aa 100644 --- a/admin/src/views/Shell.vue +++ b/admin/src/views/Shell.vue @@ -14,8 +14,8 @@ 模板管理 咨询回复 公告管理 - 主单位 主类别 + 普通管理员审批
diff --git a/admin/src/views/admin/Login.vue b/admin/src/views/admin/Login.vue new file mode 100644 index 0000000..dd70994 --- /dev/null +++ b/admin/src/views/admin/Login.vue @@ -0,0 +1,59 @@ + + + + + + + diff --git a/admin/src/views/normal-admin/Applications.vue b/admin/src/views/normal-admin/Applications.vue new file mode 100644 index 0000000..30d0b1b --- /dev/null +++ b/admin/src/views/normal-admin/Applications.vue @@ -0,0 +1,96 @@ + + + + + + + diff --git a/admin/src/views/parts/Templates.vue b/admin/src/views/parts/Templates.vue index 2f9c1ea..c62768e 100644 --- a/admin/src/views/parts/Templates.vue +++ b/admin/src/views/parts/Templates.vue @@ -23,31 +23,37 @@ {{ row.status===1?'启用':'停用' }} - + - + - + - + - + - + 参数字段 -
+
新增字段
@@ -55,14 +61,14 @@ - + - + - + - + - + - + - + - +
@@ -122,11 +131,7 @@ function loadCategories() { }) } -function openCreate() { - dlg.visible = true; dlg.id = 0 - Object.assign(form, { id:0, categoryId: undefined, name:'', modelRule:'', status:1, params:[] }) -} -function openEdit(row:any) { +function openView(row:any) { dlg.visible = true; dlg.id = row.id http.get(`/api/admin/part-templates/${row.id}`).then(res => { const d = res.data @@ -135,14 +140,19 @@ function openEdit(row:any) { }) } +function openCreate() { + dlg.visible = true; dlg.id = 0 + Object.assign(form, { id: 0, categoryId: undefined, name: '', modelRule: '', status: 1, params: [] }) +} + function addParam() { form.params.push({ fieldKey:'', fieldLabel:'', type:'string', required:false, unit:'', enumOptionsText:'', searchable:false, dedupeParticipate:false, sortOrder:0 }) } -function removeParam(i:number) { - form.params.splice(i,1) -} + +function removeParam(i:number) { form.params.splice(i,1) } + function save() { - // 前端校验:fieldKey/fieldLabel/类型/重复 + // 校验 const seen = new Set() for (const p of form.params) { const key = String(p.fieldKey||'').trim() @@ -157,9 +167,19 @@ function save() { const payload:any = { categoryId: form.categoryId, name: form.name, modelRule: form.modelRule, status: form.status, params: form.params.map((p:any)=>({ fieldKey:p.fieldKey, fieldLabel:p.fieldLabel, type:p.type, required:p.required, unit:p.unit, enumOptions: (p.enumOptionsText||'').split(',').map((s:string)=>s.trim()).filter((s:string)=>s), searchable:p.searchable, dedupeParticipate:p.dedupeParticipate, sortOrder:p.sortOrder })) } - const req = dlg.id ? http.put(`/api/admin/part-templates/${dlg.id}`, { ...payload, deleteAllRelatedProductsAndSubmissions: true }) - : http.post('/api/admin/part-templates', payload) - req.then(()=>{ ElMessage.success('保存成功'); dlg.visible=false; load() }) + http.post('/api/admin/part-templates', payload).then(()=>{ + ElMessage.success('创建成功'); dlg.visible=false; load() + }) +} + +function doDelete(row:any) { + // 默认非强制删除;如需强制,可加 { params: { force: true } } + http.delete(`/api/admin/part-templates/${row.id}`).then(()=>{ + ElMessage.success('已隐藏(可通过后台强制删除彻底清理)') + load() + }).catch((err:any)=>{ + ElMessage.error(err?.message || '删除失败') + }) } onMounted(()=>{ loadCategories(); load() }) diff --git a/backend/data/attachments/2025/09/27/4ba1a56e751cbeaa8f650c6e537402996cb65e0fea2fd0a64a1333d39fc434d9.png b/backend/data/attachments/2025/09/27/4ba1a56e751cbeaa8f650c6e537402996cb65e0fea2fd0a64a1333d39fc434d9.png new file mode 100644 index 0000000..290fe75 Binary files /dev/null and b/backend/data/attachments/2025/09/27/4ba1a56e751cbeaa8f650c6e537402996cb65e0fea2fd0a64a1333d39fc434d9.png differ diff --git a/backend/data/attachments/2025/09/28/26f61f0b79f7f77c80ffb57b486b6816b553f54346fe822236700a3f78045e2d.jpg b/backend/data/attachments/2025/09/28/26f61f0b79f7f77c80ffb57b486b6816b553f54346fe822236700a3f78045e2d.jpg new file mode 100644 index 0000000..efa4026 Binary files /dev/null and b/backend/data/attachments/2025/09/28/26f61f0b79f7f77c80ffb57b486b6816b553f54346fe822236700a3f78045e2d.jpg differ diff --git a/backend/data/attachments/2025/09/28/6b56ceef792d34e297ba7d54b91e831096b508a27134ef10cc40e6efc52e3d23.png b/backend/data/attachments/2025/09/28/6b56ceef792d34e297ba7d54b91e831096b508a27134ef10cc40e6efc52e3d23.png new file mode 100644 index 0000000..d2ae2bb Binary files /dev/null and b/backend/data/attachments/2025/09/28/6b56ceef792d34e297ba7d54b91e831096b508a27134ef10cc40e6efc52e3d23.png differ diff --git a/backend/data/attachments/2025/09/29/4c6e1c35d3fb58f0e8b43e4268997f30d60e48e1b52a73652558ec7c148a6efc.jpg b/backend/data/attachments/2025/09/29/4c6e1c35d3fb58f0e8b43e4268997f30d60e48e1b52a73652558ec7c148a6efc.jpg new file mode 100644 index 0000000..bda6184 Binary files /dev/null and b/backend/data/attachments/2025/09/29/4c6e1c35d3fb58f0e8b43e4268997f30d60e48e1b52a73652558ec7c148a6efc.jpg differ diff --git a/backend/data/attachments/2025/09/29/ca1448006d639132cefeb485eecd7a72bac36c95b065892d1190b5d572d867f3.jpg b/backend/data/attachments/2025/09/29/ca1448006d639132cefeb485eecd7a72bac36c95b065892d1190b5d572d867f3.jpg new file mode 100644 index 0000000..2d80fb6 Binary files /dev/null and b/backend/data/attachments/2025/09/29/ca1448006d639132cefeb485eecd7a72bac36c95b065892d1190b5d572d867f3.jpg differ diff --git a/backend/db/db.sql b/backend/db/db.sql index 99bd796..333ecff 100644 --- a/backend/db/db.sql +++ b/backend/db/db.sql @@ -156,7 +156,7 @@ CREATE TABLE IF NOT EXISTS products ( user_id BIGINT UNSIGNED NOT NULL, name VARCHAR(120) NOT NULL, category_id BIGINT UNSIGNED NULL, - unit_id BIGINT UNSIGNED NOT NULL, + -- unit_id 已移除 brand VARCHAR(64) NULL, model VARCHAR(64) NULL, spec VARCHAR(128) NULL, @@ -175,12 +175,12 @@ CREATE TABLE IF NOT EXISTS products ( UNIQUE KEY ux_products_shop_barcode (shop_id, barcode), KEY idx_products_shop (shop_id), KEY idx_products_category (category_id), - KEY idx_products_unit (unit_id), + -- KEY idx_products_unit (unit_id), FULLTEXT KEY ft_products_search (name, brand, model, spec, search_text), CONSTRAINT fk_products_shop FOREIGN KEY (shop_id) REFERENCES shops(id), CONSTRAINT fk_products_user FOREIGN KEY (user_id) REFERENCES users(id), CONSTRAINT fk_products_category FOREIGN KEY (category_id) REFERENCES product_categories(id), - CONSTRAINT fk_products_unit FOREIGN KEY (unit_id) REFERENCES product_units(id), + -- CONSTRAINT fk_products_unit FOREIGN KEY (unit_id) REFERENCES product_units(id), CONSTRAINT fk_products_globalsku FOREIGN KEY (global_sku_id) REFERENCES global_skus(id), CONSTRAINT ck_products_safe_range CHECK (safe_min IS NULL OR safe_max IS NULL OR safe_min <= safe_max) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='商品'; diff --git a/backend/src/main/java/com/example/demo/admin/AdminDictController.java b/backend/src/main/java/com/example/demo/admin/AdminDictController.java index 42f5b71..ae0a5c0 100644 --- a/backend/src/main/java/com/example/demo/admin/AdminDictController.java +++ b/backend/src/main/java/com/example/demo/admin/AdminDictController.java @@ -71,11 +71,7 @@ public class AdminDictController { public ResponseEntity deleteUnit(@PathVariable("id") Long id) { ProductUnit u = unitRepository.findById(id).orElse(null); if (u == null || !u.getShopId().equals(defaults.getDictShopId())) return ResponseEntity.status(404).body(Map.of("message","not found")); - // 引用保护:若有商品使用该单位,阻止删除 - Long cnt = jdbcTemplate.queryForObject("SELECT COUNT(*) FROM products WHERE unit_id=?", Long.class, id); - if (cnt != null && cnt > 0) { - return ResponseEntity.status(409).body(Map.of("message","存在引用,无法删除")); - } + // 按新方案:移除对 products.unit_id 的引用校验(该字段已移除) unitRepository.deleteById(id); return ResponseEntity.ok().build(); } @@ -121,12 +117,15 @@ public class AdminDictController { public ResponseEntity deleteCategory(@PathVariable("id") Long id) { ProductCategory c = categoryRepository.findById(id).orElse(null); if (c == null || !c.getShopId().equals(defaults.getDictShopId())) return ResponseEntity.status(404).body(Map.of("message","not found")); - // 子类与引用保护 - Long child = jdbcTemplate.queryForObject("SELECT COUNT(*) FROM product_categories WHERE parent_id=?", Long.class, id); - if (child != null && child > 0) return ResponseEntity.status(409).body(Map.of("message","存在子类,无法删除")); - Long cnt = jdbcTemplate.queryForObject("SELECT COUNT(*) FROM products WHERE category_id=?", Long.class, id); - if (cnt != null && cnt > 0) return ResponseEntity.status(409).body(Map.of("message","存在引用,无法删除")); - categoryRepository.deleteById(id); + // 平台管理员二次确认可在拦截器或前端完成;此处执行软删级联 + // 1) 软删分类 + jdbcTemplate.update("UPDATE product_categories SET deleted_at=NOW(), updated_at=NOW() WHERE id=? AND deleted_at IS NULL", id); + // 2) 软删分类下模板(使用 deleted_at 统一标记) + jdbcTemplate.update("UPDATE part_templates SET deleted_at=NOW(), updated_at=NOW() WHERE category_id=? AND (deleted_at IS NULL)", id); + // 3) 软删该分类下的所有商品:包括通过模板创建的与直接挂分类的 + jdbcTemplate.update("UPDATE products SET deleted_at=NOW(), updated_at=NOW() WHERE (category_id=? OR template_id IN (SELECT id FROM part_templates WHERE category_id=?)) AND deleted_at IS NULL", id, id); + // 4) 软删该分类下的所有配件提交:包含直接指向分类的与指向该分类下模板的 + jdbcTemplate.update("UPDATE part_submissions SET deleted_at=NOW(), updated_at=NOW() WHERE (category_id=? OR template_id IN (SELECT id FROM part_templates WHERE category_id=?)) AND deleted_at IS NULL", id, id); return ResponseEntity.ok().build(); } } diff --git a/backend/src/main/java/com/example/demo/auth/EmailAuthService.java b/backend/src/main/java/com/example/demo/auth/EmailAuthService.java index 957ef07..35c8ab3 100644 --- a/backend/src/main/java/com/example/demo/auth/EmailAuthService.java +++ b/backend/src/main/java/com/example/demo/auth/EmailAuthService.java @@ -21,16 +21,20 @@ public class EmailAuthService { private final com.example.demo.common.ShopDefaultsProperties shopDefaults; private final EmailSenderService emailSender; + private final com.example.demo.common.DefaultSeedService defaultSeedService; + public EmailAuthService(JdbcTemplate jdbcTemplate, JwtService jwtService, JwtProperties jwtProps, com.example.demo.common.ShopDefaultsProperties shopDefaults, - EmailSenderService emailSender) { + EmailSenderService emailSender, + com.example.demo.common.DefaultSeedService defaultSeedService) { this.jdbcTemplate = jdbcTemplate; this.jwtService = jwtService; this.jwtProps = jwtProps; this.shopDefaults = shopDefaults; this.emailSender = emailSender; + this.defaultSeedService = defaultSeedService; } public static class SendCodeRequest { public String email; public String scene; } @@ -205,6 +209,9 @@ public class EmailAuthService { Number userGenId = userKey.getKey(); if (userGenId == null) throw new IllegalStateException("创建用户失败"); userId = userGenId.longValue(); + + // 初始化默认客户/供应商(幂等) + defaultSeedService.initializeForShop(shopId, userId); } String token = jwtService.signToken(userId, shopId, null, "email_otp", email); diff --git a/backend/src/main/java/com/example/demo/auth/NormalAdminApplyController.java b/backend/src/main/java/com/example/demo/auth/NormalAdminApplyController.java index e86d64e..2999ca5 100644 --- a/backend/src/main/java/com/example/demo/auth/NormalAdminApplyController.java +++ b/backend/src/main/java/com/example/demo/auth/NormalAdminApplyController.java @@ -6,6 +6,7 @@ import org.springframework.web.bind.annotation.*; import java.util.Map; import java.util.Objects; +import java.util.LinkedHashMap; @RestController @RequestMapping("/api/normal-admin") @@ -27,6 +28,11 @@ public class NormalAdminApplyController { } else { sidFinal = shopId; } // 校验 VIP(根据配置可选) boolean requireVip = true; // 默认要求VIP有效 + try { + String v = jdbc.query("SELECT value FROM system_parameters WHERE `key`='normalAdmin.requiredVipActive' ORDER BY id DESC LIMIT 1", + rs -> rs.next() ? rs.getString(1) : null); + if (v != null) { v = v.trim(); if (v.startsWith("\"") && v.endsWith("\"")) v = v.substring(1, v.length()-1); requireVip = ("true".equalsIgnoreCase(v) || "1".equals(v)); } + } catch (Exception ignored) {} Integer vipOk = jdbc.query( "SELECT CASE WHEN (is_vip=1 AND status=1 AND (expire_at IS NULL OR expire_at>NOW())) THEN 1 ELSE 0 END FROM vip_users WHERE user_id=? AND shop_id=? ORDER BY id DESC LIMIT 1", ps -> { ps.setLong(1, userId); ps.setLong(2, sidFinal); }, @@ -41,7 +47,12 @@ public class NormalAdminApplyController { ps -> { ps.setLong(1, sidFinal); ps.setLong(2, userId); ps.setString(3, "apply"); ps.setString(4, remark); }); // 是否自动通过 - boolean autoApprove = false; // 默认false,后续接入 system_parameters + boolean autoApprove = false; + try { + String v = jdbc.query("SELECT value FROM system_parameters WHERE `key`='normalAdmin.autoApprove' ORDER BY id DESC LIMIT 1", + rs -> rs.next() ? rs.getString(1) : null); + if (v != null) { v = v.trim(); if (v.startsWith("\"") && v.endsWith("\"")) v = v.substring(1, v.length()-1); autoApprove = ("true".equalsIgnoreCase(v) || "1".equals(v)); } + } catch (Exception ignored) {} if (autoApprove) { // 将角色变更为 normal_admin 并写入 approve 审计 String prev = jdbc.query("SELECT role FROM users WHERE id=?", ps -> ps.setLong(1, userId), rs -> rs.next()? rs.getString(1): null); @@ -52,6 +63,62 @@ public class NormalAdminApplyController { return ResponseEntity.ok(Map.of("ok", true)); } + + @GetMapping("/application/status") + public ResponseEntity myApplicationStatus(@RequestHeader(name = "X-User-Id") long userId) { + try { + Map out = new LinkedHashMap<>(); + // 当前角色 + String role = null; + try { + role = jdbc.query("SELECT role FROM users WHERE id=? LIMIT 1", + ps -> ps.setLong(1, userId), rs -> rs.next() ? rs.getString(1) : null); + } catch (Exception ignored) {} + boolean isNormalAdmin = role != null && "normal_admin".equalsIgnoreCase(role.trim()); + + // 最近一次审计动作 + Map last = null; + try { + last = jdbc.query( + "SELECT action, created_at AS createdAt, remark FROM normal_admin_audits WHERE user_id=? ORDER BY created_at DESC LIMIT 1", + ps -> ps.setLong(1, userId), + rs -> { + if (!rs.next()) return null; + Map m = new LinkedHashMap<>(); + m.put("action", rs.getString("action")); + m.put("createdAt", rs.getTimestamp("createdAt")); + m.put("remark", rs.getString("remark")); + return m; + } + ); + } catch (Exception ignored) {} + + String applicationStatus = "none"; + if (isNormalAdmin) { + applicationStatus = "approved"; + } else if (last != null) { + String action = (String) last.get("action"); + if ("apply".equalsIgnoreCase(action)) applicationStatus = "pending"; + else if ("approve".equalsIgnoreCase(action)) applicationStatus = "approved"; + else if ("reject".equalsIgnoreCase(action)) applicationStatus = "rejected"; + else if ("revoke".equalsIgnoreCase(action)) applicationStatus = "revoked"; + } + + out.put("isNormalAdmin", isNormalAdmin); + out.put("applicationStatus", applicationStatus); + if (last != null) { + out.put("lastAction", last.get("action")); + out.put("lastActionAt", last.get("createdAt")); + out.put("lastRemark", last.get("remark")); + } + return ResponseEntity.ok(out); + } catch (Exception e) { + Map fallback = new LinkedHashMap<>(); + fallback.put("isNormalAdmin", false); + fallback.put("applicationStatus", "none"); + return ResponseEntity.ok(fallback); + } + } } diff --git a/backend/src/main/java/com/example/demo/auth/RegisterService.java b/backend/src/main/java/com/example/demo/auth/RegisterService.java index 16b8221..b1cf715 100644 --- a/backend/src/main/java/com/example/demo/auth/RegisterService.java +++ b/backend/src/main/java/com/example/demo/auth/RegisterService.java @@ -20,6 +20,7 @@ public class RegisterService { private final JwtProperties jwtProps; private final ShopDefaultsProperties shopDefaults; private AppDefaultsProperties appDefaults; + private com.example.demo.common.DefaultSeedService defaultSeedService; public RegisterService(JdbcTemplate jdbcTemplate, JwtService jwtService, @@ -36,6 +37,11 @@ public class RegisterService { this.appDefaults = appDefaults; } + @Autowired + public void setDefaultSeedService(com.example.demo.common.DefaultSeedService defaultSeedService) { + this.defaultSeedService = defaultSeedService; + } + private String hashPassword(String raw) { try { return org.springframework.security.crypto.bcrypt.BCrypt.hashpw(raw, org.springframework.security.crypto.bcrypt.BCrypt.gensalt(10)); @@ -108,6 +114,11 @@ public class RegisterService { // 3) 创建默认账户(现金/银行存款/微信) createDefaultAccounts(shopId, userId); + + // 4) 初始化默认客户/供应商(幂等) + if (defaultSeedService != null) { + defaultSeedService.initializeForShop(shopId, userId); + } } String token = jwtService.signToken(userId, shopId, phone, "register"); diff --git a/backend/src/main/java/com/example/demo/common/AppDefaultsProperties.java b/backend/src/main/java/com/example/demo/common/AppDefaultsProperties.java index 2c3a52f..402c50e 100644 --- a/backend/src/main/java/com/example/demo/common/AppDefaultsProperties.java +++ b/backend/src/main/java/com/example/demo/common/AppDefaultsProperties.java @@ -18,6 +18,10 @@ public class AppDefaultsProperties { private String accountWechatName = "微信"; private String accountAlipayName = "支付宝"; + // 默认往来单位名称(配置化,避免硬编码) + private String customerName = "散客"; + private String supplierName = "默认供应商"; + public Long getShopId() { return shopId; } public void setShopId(Long shopId) { this.shopId = shopId; } public Long getUserId() { return userId; } @@ -34,6 +38,12 @@ public class AppDefaultsProperties { public void setAccountWechatName(String accountWechatName) { this.accountWechatName = accountWechatName; } public String getAccountAlipayName() { return accountAlipayName; } public void setAccountAlipayName(String accountAlipayName) { this.accountAlipayName = accountAlipayName; } + + public String getCustomerName() { return customerName; } + public void setCustomerName(String customerName) { this.customerName = customerName; } + + public String getSupplierName() { return supplierName; } + public void setSupplierName(String supplierName) { this.supplierName = supplierName; } } diff --git a/backend/src/main/java/com/example/demo/common/DefaultSeedService.java b/backend/src/main/java/com/example/demo/common/DefaultSeedService.java new file mode 100644 index 0000000..f25264c --- /dev/null +++ b/backend/src/main/java/com/example/demo/common/DefaultSeedService.java @@ -0,0 +1,41 @@ +package com.example.demo.common; + +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class DefaultSeedService { + + private final JdbcTemplate jdbcTemplate; + private final AppDefaultsProperties appDefaults; + + public DefaultSeedService(JdbcTemplate jdbcTemplate, AppDefaultsProperties appDefaults) { + this.jdbcTemplate = jdbcTemplate; + this.appDefaults = appDefaults; + } + + /** + * 幂等初始化:为新店铺创建默认客户/供应商(若不存在)。 + */ + @Transactional + public void initializeForShop(Long shopId, Long userId) { + if (shopId == null || userId == null) return; + // 默认客户 + jdbcTemplate.update( + "INSERT INTO customers (shop_id,user_id,name,price_level,status,created_at,updated_at) " + + "SELECT ?, ?, ?, 'retail', 1, NOW(), NOW() FROM DUAL " + + "WHERE NOT EXISTS (SELECT 1 FROM customers WHERE shop_id=? AND name=?)", + shopId, userId, appDefaults.getCustomerName(), shopId, appDefaults.getCustomerName() + ); + // 默认供应商 + jdbcTemplate.update( + "INSERT INTO suppliers (shop_id,user_id,name,status,created_at,updated_at) " + + "SELECT ?, ?, ?, 1, NOW(), NOW() FROM DUAL " + + "WHERE NOT EXISTS (SELECT 1 FROM suppliers WHERE shop_id=? AND name=?)", + shopId, userId, appDefaults.getSupplierName(), shopId, appDefaults.getSupplierName() + ); + } +} + + diff --git a/backend/src/main/java/com/example/demo/common/NormalAdminAuthInterceptor.java b/backend/src/main/java/com/example/demo/common/NormalAdminAuthInterceptor.java index 3b080f5..de33398 100644 --- a/backend/src/main/java/com/example/demo/common/NormalAdminAuthInterceptor.java +++ b/backend/src/main/java/com/example/demo/common/NormalAdminAuthInterceptor.java @@ -59,7 +59,16 @@ public class NormalAdminAuthInterceptor implements HandlerInterceptor { } // 可选校验:VIP 有效 - boolean requireVip = Boolean.parseBoolean(String.valueOf(System.getenv().getOrDefault("NORMAL_ADMIN_REQUIRE_VIP_ACTIVE", "true"))); + boolean requireVip; + try { + String v = jdbcTemplate.query("SELECT value FROM system_parameters WHERE `key`='normalAdmin.requiredVipActive' ORDER BY id DESC LIMIT 1", + rs -> rs.next() ? rs.getString(1) : null); + if (v == null) requireVip = true; else { + v = v.trim(); + if (v.startsWith("\"") && v.endsWith("\"")) v = v.substring(1, v.length()-1); + requireVip = "true".equalsIgnoreCase(v) || "1".equals(v); + } + } catch (Exception e) { requireVip = true; } if (requireVip) { Integer vipOk = jdbcTemplate.query( "SELECT CASE WHEN (is_vip=1 AND status=1 AND (expire_at IS NULL OR expire_at>NOW())) THEN 1 ELSE 0 END FROM vip_users WHERE user_id=? AND shop_id=? ORDER BY id DESC LIMIT 1", diff --git a/backend/src/main/java/com/example/demo/common/WebConfig.java b/backend/src/main/java/com/example/demo/common/WebConfig.java index e6611ef..1ac2ad5 100644 --- a/backend/src/main/java/com/example/demo/common/WebConfig.java +++ b/backend/src/main/java/com/example/demo/common/WebConfig.java @@ -4,6 +4,7 @@ import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistration; import org.springframework.lang.NonNull; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration @@ -29,6 +30,19 @@ public class WebConfig implements WebMvcConfigurer { InterceptorRegistration nr = registry.addInterceptor(normalAdminAuthInterceptor); nr.addPathPatterns("/api/normal-admin/parts/**"); } + + @Override + public void addResourceHandlers(@NonNull ResourceHandlerRegistry registry) { + // 将 /static/** 映射到前端静态资源目录(开发时)与 classpath 静态目录(部署时) + String userDir = System.getProperty("user.dir"); + String frontendStatic = userDir + java.io.File.separator + "frontend" + java.io.File.separator + "static" + java.io.File.separator; + registry.addResourceHandler("/static/**") + .addResourceLocations( + "file:" + frontendStatic, + "classpath:/static/", + "classpath:/public/" + ); + } } diff --git a/backend/src/main/java/com/example/demo/order/OrderService.java b/backend/src/main/java/com/example/demo/order/OrderService.java index a3ad751..1bec6ff 100644 --- a/backend/src/main/java/com/example/demo/order/OrderService.java +++ b/backend/src/main/java/com/example/demo/order/OrderService.java @@ -27,14 +27,18 @@ public class OrderService { private final JdbcTemplate jdbcTemplate; private final ProductPriceRepository productPriceRepository; + private final com.example.demo.common.AppDefaultsProperties appDefaults; + public OrderService(InventoryRepository inventoryRepository, JdbcTemplate jdbcTemplate, AccountDefaultsProperties accountDefaults, - ProductPriceRepository productPriceRepository) { + ProductPriceRepository productPriceRepository, + com.example.demo.common.AppDefaultsProperties appDefaults) { this.inventoryRepository = inventoryRepository; this.jdbcTemplate = jdbcTemplate; this.accountDefaults = accountDefaults; this.productPriceRepository = productPriceRepository; + this.appDefaults = appDefaults; } @Transactional @@ -134,8 +138,12 @@ public class OrderService { "VALUES (?,?,?,?,'approved', ?, 0, ?, NOW(), NOW())"; } - Long customerId = req.customerId; - Long supplierId = req.supplierId; + final Long customerId = (isSalesHead && req.customerId == null) + ? resolveOrCreateDefaultCustomer(shopId, userId) + : req.customerId; + final Long supplierId = (isPurchaseHead && req.supplierId == null) + ? resolveOrCreateDefaultSupplier(shopId, userId) + : req.supplierId; jdbcTemplate.update(con -> { java.sql.PreparedStatement ps = con.prepareStatement(headSql, new String[]{"id"}); int idx = 1; @@ -188,6 +196,28 @@ public class OrderService { return new OrderDtos.CreateOrderResponse(orderId, orderNo); } + private Long resolveOrCreateDefaultCustomer(Long shopId, Long userId) { + String name = appDefaults.getCustomerName(); + java.util.List ids = jdbcTemplate.query("SELECT id FROM customers WHERE shop_id=? AND name=? LIMIT 1", (rs,rn)->rs.getLong(1), shopId, name); + if (!ids.isEmpty()) return ids.get(0); + jdbcTemplate.update("INSERT INTO customers (shop_id,user_id,name,price_level,status,created_at,updated_at) VALUES (?,?,?,'retail',1,NOW(),NOW())", + shopId, userId, name); + ids = jdbcTemplate.query("SELECT id FROM customers WHERE shop_id=? AND name=? LIMIT 1", (rs,rn)->rs.getLong(1), shopId, name); + if (!ids.isEmpty()) return ids.get(0); + throw new IllegalStateException("默认客户创建失败"); + } + + private Long resolveOrCreateDefaultSupplier(Long shopId, Long userId) { + String name = appDefaults.getSupplierName(); + java.util.List ids = jdbcTemplate.query("SELECT id FROM suppliers WHERE shop_id=? AND name=? LIMIT 1", (rs,rn)->rs.getLong(1), shopId, name); + if (!ids.isEmpty()) return ids.get(0); + jdbcTemplate.update("INSERT INTO suppliers (shop_id,user_id,name,status,created_at,updated_at) VALUES (?,?,?,1,NOW(),NOW())", + shopId, userId, name); + ids = jdbcTemplate.query("SELECT id FROM suppliers WHERE shop_id=? AND name=? LIMIT 1", (rs,rn)->rs.getLong(1), shopId, name); + if (!ids.isEmpty()) return ids.get(0); + throw new IllegalStateException("默认供应商创建失败"); + } + private BigDecimal resolveProductCostPrice(Long productId, Long shopId) { return productPriceRepository.findById(productId) .filter(price -> price.getShopId().equals(shopId)) diff --git a/backend/src/main/java/com/example/demo/product/controller/MetadataController.java b/backend/src/main/java/com/example/demo/product/controller/MetadataController.java index 3934c70..f877ea2 100644 --- a/backend/src/main/java/com/example/demo/product/controller/MetadataController.java +++ b/backend/src/main/java/com/example/demo/product/controller/MetadataController.java @@ -49,11 +49,14 @@ public class MetadataController { @GetMapping("/api/product-templates") public ResponseEntity listTemplates(@RequestParam(name = "categoryId", required = false) Long categoryId) { Map body = new HashMap<>(); + // 排除已软删模板;仍要求 status=1 才可见 java.util.List list = - categoryId == null ? templateRepository.findByStatusOrderByIdDesc(1) - : templateRepository.findByStatusAndCategoryIdOrderByIdDesc(1, categoryId); + (categoryId == null) + ? templateRepository.findByStatusOrderByIdDesc(1) + : templateRepository.findByStatusAndCategoryIdOrderByIdDesc(1, categoryId); java.util.List> out = new java.util.ArrayList<>(); for (com.example.demo.product.entity.PartTemplate t : list) { + try { if (t.getDeletedAt() != null) continue; } catch (Exception ignore) {} java.util.Map m = new java.util.HashMap<>(); m.put("id", t.getId()); m.put("categoryId", t.getCategoryId()); diff --git a/backend/src/main/java/com/example/demo/product/controller/NormalAdminSubmissionController.java b/backend/src/main/java/com/example/demo/product/controller/NormalAdminSubmissionController.java index 74c95b1..fc396c4 100644 --- a/backend/src/main/java/com/example/demo/product/controller/NormalAdminSubmissionController.java +++ b/backend/src/main/java/com/example/demo/product/controller/NormalAdminSubmissionController.java @@ -1,7 +1,9 @@ package com.example.demo.product.controller; import com.example.demo.product.service.ProductSubmissionService; +import jakarta.servlet.http.HttpServletResponse; import org.springframework.http.ResponseEntity; +import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.web.bind.annotation.*; @RestController @@ -9,19 +11,28 @@ import org.springframework.web.bind.annotation.*; public class NormalAdminSubmissionController { private final ProductSubmissionService submissionService; + private final JdbcTemplate jdbc; - public NormalAdminSubmissionController(ProductSubmissionService submissionService) { + public NormalAdminSubmissionController(ProductSubmissionService submissionService, + JdbcTemplate jdbc) { this.submissionService = submissionService; + this.jdbc = jdbc; } - // 代理现有管理端接口,但不暴露跨店查询参数,实际范围由拦截器限定 + private Long findShopIdByUser(Long userId) { + if (userId == null) return null; + return jdbc.query("SELECT shop_id FROM users WHERE id=?", ps -> ps.setLong(1, userId), rs -> rs.next()? rs.getLong(1): null); + } + + // 代理现有管理端接口,但范围限定为当前用户所属店铺 @GetMapping("/submissions") - public ResponseEntity list(@RequestParam(name = "status", required = false) String status, + public ResponseEntity list(@RequestHeader(name = "X-User-Id", required = false) Long userId, + @RequestParam(name = "status", required = false) String status, @RequestParam(name = "kw", required = false) String kw, @RequestParam(name = "page", defaultValue = "1") int page, @RequestParam(name = "size", defaultValue = "20") int size) { - // 普通管理端不允许跨店过滤,reviewer/shopId 均不提供 - return ResponseEntity.ok(submissionService.listAdmin(status, kw, null, null, null, null, page, size)); + Long shopId = findShopIdByUser(userId); + return ResponseEntity.ok(submissionService.listAdmin(status, kw, shopId, null, null, null, page, size)); } @GetMapping("/submissions/{id}") @@ -42,7 +53,6 @@ public class NormalAdminSubmissionController { public ResponseEntity approve(@PathVariable("id") Long id, @RequestHeader(name = "X-User-Id", required = false) Long userId, @RequestBody(required = false) com.example.demo.product.dto.ProductSubmissionDtos.ApproveRequest req) { - // 这里将 X-User-Id 作为审批人记录(普通管理员为用户表) var resp = submissionService.approve(id, userId, req); return ResponseEntity.ok(resp); } @@ -54,6 +64,15 @@ public class NormalAdminSubmissionController { submissionService.reject(id, userId, req); return ResponseEntity.ok(java.util.Map.of("ok", true)); } + + @GetMapping("/submissions/export") + public void export(@RequestHeader(name = "X-User-Id", required = false) Long userId, + @RequestParam(name = "status", required = false) String status, + @RequestParam(name = "kw", required = false) String kw, + HttpServletResponse response) { + Long shopId = findShopIdByUser(userId); + submissionService.export(status, kw, shopId, null, null, null, response); + } } diff --git a/backend/src/main/java/com/example/demo/product/controller/PartTemplateController.java b/backend/src/main/java/com/example/demo/product/controller/PartTemplateController.java index 360c728..ef1bf47 100644 --- a/backend/src/main/java/com/example/demo/product/controller/PartTemplateController.java +++ b/backend/src/main/java/com/example/demo/product/controller/PartTemplateController.java @@ -38,6 +38,15 @@ public class PartTemplateController { public ResponseEntity list() { return ResponseEntity.ok(templateService.list()); } + + @DeleteMapping("/{id}") + public ResponseEntity delete(@PathVariable("id") Long id, + @RequestParam(value = "force", required = false) Boolean force) { + templateService.delete(id, Boolean.TRUE.equals(force)); + return ResponseEntity.ok(java.util.Map.of("ok", true)); + } + + // 分类级联软删将在 AdminDictController 中触发;此处保持模板单体删除逻辑 } diff --git a/backend/src/main/java/com/example/demo/product/controller/ProductController.java b/backend/src/main/java/com/example/demo/product/controller/ProductController.java index c03952b..698759b 100644 --- a/backend/src/main/java/com/example/demo/product/controller/ProductController.java +++ b/backend/src/main/java/com/example/demo/product/controller/ProductController.java @@ -23,18 +23,29 @@ public class ProductController { public ResponseEntity search(@RequestHeader(name = "X-Shop-Id", required = false) Long shopId, @RequestParam(name = "kw", required = false) String kw, @RequestParam(name = "categoryId", required = false) Long categoryId, + @RequestParam(name = "templateId", required = false) Long templateId, + @RequestParam java.util.Map requestParams, @RequestParam(name = "page", defaultValue = "1") int page, @RequestParam(name = "size", defaultValue = "50") int size) { Long sid = (shopId == null ? defaults.getShopId() : shopId); - Page result = productService.search(sid, kw, categoryId, Math.max(page - 1, 0), size); + java.util.Map paramFilters = new java.util.HashMap<>(); + for (java.util.Map.Entry e : requestParams.entrySet()) { + String k = e.getKey(); + if (k != null && k.startsWith("param_") && e.getValue() != null && !e.getValue().isBlank()) { + String key = k.substring(6); + if (!key.isBlank()) paramFilters.put(key, e.getValue()); + } + } + Page result = productService.search(sid, kw, categoryId, templateId, paramFilters, Math.max(page - 1, 0), size); java.util.Map body = new java.util.HashMap<>(); body.put("list", result.getContent()); return ResponseEntity.ok(body); } @GetMapping("/{id}") - public ResponseEntity detail(@PathVariable("id") Long id) { - return productService.findDetail(id) + public ResponseEntity detail(@PathVariable("id") Long id, + @RequestParam(name = "includeDeleted", required = false, defaultValue = "false") boolean includeDeleted) { + return productService.findDetail(id, includeDeleted) .>map(ResponseEntity::ok) .orElseGet(() -> ResponseEntity.notFound().build()); } @@ -61,6 +72,15 @@ public class ProductController { productService.update(id, sid, uid, req); return ResponseEntity.ok().build(); } + + @DeleteMapping("/{id}") + public ResponseEntity delete(@PathVariable("id") Long id, + @RequestHeader(name = "X-Shop-Id", required = false) Long shopId, + @RequestHeader(name = "X-User-Id", required = false) Long userId) { + Long sid = (shopId == null ? defaults.getShopId() : shopId); + productService.delete(id, sid); + return ResponseEntity.ok().build(); + } } diff --git a/backend/src/main/java/com/example/demo/product/dto/ProductDtos.java b/backend/src/main/java/com/example/demo/product/dto/ProductDtos.java index 1e2d4cb..13943b6 100644 --- a/backend/src/main/java/com/example/demo/product/dto/ProductDtos.java +++ b/backend/src/main/java/com/example/demo/product/dto/ProductDtos.java @@ -15,6 +15,7 @@ public class ProductDtos { public BigDecimal stock; // from inventories.quantity public BigDecimal retailPrice; // from product_prices public String cover; // first image url + public Boolean deleted; // derived from deleted_at } public static class ProductDetail { @@ -26,7 +27,8 @@ public class ProductDtos { public String spec; public String origin; public Long categoryId; - public Long unitId; + // 单位字段已移除 + public Long templateId; public BigDecimal safeMin; public BigDecimal safeMax; public BigDecimal stock; @@ -35,6 +37,10 @@ public class ProductDtos { public BigDecimal wholesalePrice; public BigDecimal bigClientPrice; public List images; + public Map parameters; + public Long sourceSubmissionId; + public String externalCode; + public Boolean deleted; } public static class Image { diff --git a/backend/src/main/java/com/example/demo/product/dto/ProductSubmissionDtos.java b/backend/src/main/java/com/example/demo/product/dto/ProductSubmissionDtos.java index 2776496..7a923bc 100644 --- a/backend/src/main/java/com/example/demo/product/dto/ProductSubmissionDtos.java +++ b/backend/src/main/java/com/example/demo/product/dto/ProductSubmissionDtos.java @@ -8,12 +8,13 @@ public class ProductSubmissionDtos { public static class CreateRequest { public Long templateId; + public String externalCode; // 外部编号 public String name; public String model; public String brand; public String spec; public String origin; - public Long unitId; + // 单位字段已移除 public Long categoryId; public Map parameters; public List images; @@ -25,11 +26,12 @@ public class ProductSubmissionDtos { public static class UpdateRequest { public Long templateId; + public String externalCode; // 外部编号 public String name; public String brand; public String spec; public String origin; - public Long unitId; + // 单位字段已移除 public Long categoryId; public Map parameters; public List images; @@ -72,12 +74,13 @@ public class ProductSubmissionDtos { public Long shopId; public Long userId; public Long templateId; + public String externalCode; public String name; public String model; public String brand; public String spec; public String origin; - public Long unitId; + // 单位字段已移除 public Long categoryId; public Map parameters; public List images; diff --git a/backend/src/main/java/com/example/demo/product/entity/PartTemplate.java b/backend/src/main/java/com/example/demo/product/entity/PartTemplate.java index 568743b..399cba0 100644 --- a/backend/src/main/java/com/example/demo/product/entity/PartTemplate.java +++ b/backend/src/main/java/com/example/demo/product/entity/PartTemplate.java @@ -32,6 +32,9 @@ public class PartTemplate { @Column(name = "updated_at") private LocalDateTime updatedAt; + @Column(name = "deleted_at") + private LocalDateTime deletedAt; + public Long getId() { return id; } public Long getCategoryId() { return categoryId; } public void setCategoryId(Long categoryId) { this.categoryId = categoryId; } @@ -47,6 +50,8 @@ public class PartTemplate { public void setCreatedAt(LocalDateTime createdAt) { this.createdAt = createdAt; } public LocalDateTime getUpdatedAt() { return updatedAt; } public void setUpdatedAt(LocalDateTime updatedAt) { this.updatedAt = updatedAt; } + public LocalDateTime getDeletedAt() { return deletedAt; } + public void setDeletedAt(LocalDateTime deletedAt) { this.deletedAt = deletedAt; } } diff --git a/backend/src/main/java/com/example/demo/product/entity/Product.java b/backend/src/main/java/com/example/demo/product/entity/Product.java index 881ece1..343fc69 100644 --- a/backend/src/main/java/com/example/demo/product/entity/Product.java +++ b/backend/src/main/java/com/example/demo/product/entity/Product.java @@ -24,9 +24,6 @@ public class Product { @Column(name = "category_id") private Long categoryId; - @Column(name = "unit_id", nullable = false) - private Long unitId; - @Column(name = "template_id") private Long templateId; @@ -84,8 +81,6 @@ public class Product { public void setName(String name) { this.name = name; } public Long getCategoryId() { return categoryId; } public void setCategoryId(Long categoryId) { this.categoryId = categoryId; } - public Long getUnitId() { return unitId; } - public void setUnitId(Long unitId) { this.unitId = unitId; } public Long getTemplateId() { return templateId; } public void setTemplateId(Long templateId) { this.templateId = templateId; } public String getBrand() { return brand; } diff --git a/backend/src/main/java/com/example/demo/product/repo/PartTemplateRepository.java b/backend/src/main/java/com/example/demo/product/repo/PartTemplateRepository.java index 3514e96..3fe6ef8 100644 --- a/backend/src/main/java/com/example/demo/product/repo/PartTemplateRepository.java +++ b/backend/src/main/java/com/example/demo/product/repo/PartTemplateRepository.java @@ -6,6 +6,7 @@ import org.springframework.data.jpa.repository.JpaRepository; public interface PartTemplateRepository extends JpaRepository { java.util.List findByStatusOrderByIdDesc(Integer status); java.util.List findByStatusAndCategoryIdOrderByIdDesc(Integer status, Long categoryId); + java.util.List findByDeletedAtIsNullOrderByIdDesc(); } diff --git a/backend/src/main/java/com/example/demo/product/repo/ProductRepository.java b/backend/src/main/java/com/example/demo/product/repo/ProductRepository.java index f978098..8909908 100644 --- a/backend/src/main/java/com/example/demo/product/repo/ProductRepository.java +++ b/backend/src/main/java/com/example/demo/product/repo/ProductRepository.java @@ -11,10 +11,11 @@ public interface ProductRepository extends JpaRepository { @Query("SELECT p FROM Product p WHERE p.shopId = :shopId AND (p.deletedAt IS NULL) AND " + "(:kw IS NULL OR :kw = '' OR p.name LIKE CONCAT('%', :kw, '%') OR p.brand LIKE CONCAT('%', :kw, '%') OR p.model LIKE CONCAT('%', :kw, '%') OR p.spec LIKE CONCAT('%', :kw, '%') OR p.barcode LIKE CONCAT('%', :kw, '%')) AND " + - "(:categoryId IS NULL OR p.categoryId = :categoryId) ORDER BY p.id DESC") + "(:categoryId IS NULL OR p.categoryId = :categoryId) AND (:templateId IS NULL OR p.templateId = :templateId) ORDER BY p.id DESC") Page search(@Param("shopId") Long shopId, @Param("kw") String kw, @Param("categoryId") Long categoryId, + @Param("templateId") Long templateId, Pageable pageable); boolean existsByShopIdAndBarcode(Long shopId, String barcode); diff --git a/backend/src/main/java/com/example/demo/product/repo/ProductSubmissionRepository.java b/backend/src/main/java/com/example/demo/product/repo/ProductSubmissionRepository.java index 70f10e4..e48c861 100644 --- a/backend/src/main/java/com/example/demo/product/repo/ProductSubmissionRepository.java +++ b/backend/src/main/java/com/example/demo/product/repo/ProductSubmissionRepository.java @@ -14,7 +14,9 @@ public interface ProductSubmissionRepository extends JpaRepository findByShopIdAndUserIdAndStatusIn(Long shopId, Long userId, List statuses, Pageable pageable); - @Query("SELECT ps FROM ProductSubmission ps WHERE (:statusList IS NULL OR ps.status IN :statusList) " + + Page findByShopIdAndUserIdAndStatusInAndDeletedAtIsNull(Long shopId, Long userId, List statuses, Pageable pageable); + + @Query("SELECT ps FROM ProductSubmission ps WHERE ps.deletedAt IS NULL AND (:statusList IS NULL OR ps.status IN :statusList) " + "AND (:kw IS NULL OR ps.modelUnique LIKE :kw OR ps.name LIKE :kw OR ps.brand LIKE :kw) " + "AND (:shopId IS NULL OR ps.shopId = :shopId) " + "AND (:reviewerId IS NULL OR ps.reviewerId = :reviewerId) " + diff --git a/backend/src/main/java/com/example/demo/product/service/PartTemplateService.java b/backend/src/main/java/com/example/demo/product/service/PartTemplateService.java index 76d68cc..e824e9c 100644 --- a/backend/src/main/java/com/example/demo/product/service/PartTemplateService.java +++ b/backend/src/main/java/com/example/demo/product/service/PartTemplateService.java @@ -64,6 +64,15 @@ public class PartTemplateService { if (req.modelRule != null) t.setModelRule(req.modelRule); if (req.status != null) t.setStatus(req.status); t.setUpdatedAt(LocalDateTime.now()); + try { + // 若模板已被软删,不允许通过 update 将其“启用”,需运维恢复 + java.lang.reflect.Field f = t.getClass().getDeclaredField("deletedAt"); + f.setAccessible(true); + Object v = f.get(t); + if (v != null && (req.status != null && req.status == 1)) { + throw new IllegalStateException("模板已删除,无法启用。请联系平台管理员"); + } + } catch (NoSuchFieldException ignore) { } catch (IllegalAccessException ignore) { } templateRepository.save(t); if (req.params != null) { @@ -117,6 +126,32 @@ public class PartTemplateService { return out; } + @Transactional + public void delete(Long id, boolean force) { + if (!force) { + // 软删除:隐藏模板并级联软删该模板下商品 + PartTemplate t = templateRepository.findById(id).orElseThrow(); + t.setStatus(0); + t.setUpdatedAt(LocalDateTime.now()); + // 统一软删标记:写入 deleted_at + try { jdbcTemplate.update("UPDATE part_templates SET deleted_at=NOW() WHERE id=? AND deleted_at IS NULL", id); } catch (Exception ignore) {} + templateRepository.save(t); + // 级联软删商品与配件提交 + jdbcTemplate.update("UPDATE products SET deleted_at=NOW() WHERE template_id=? AND deleted_at IS NULL", id); + jdbcTemplate.update("UPDATE part_submissions SET deleted_at=NOW() WHERE template_id=? AND deleted_at IS NULL", id); + return; + } + + // 永久删除:删除参数与模板,并清理关联数据 + paramRepository.findByTemplateIdOrderBySortOrderAscIdAsc(id).forEach(p -> paramRepository.deleteById(p.getId())); + jdbcTemplate.update("UPDATE products SET deleted_at=NOW() WHERE template_id=? AND deleted_at IS NULL", id); + jdbcTemplate.update("DELETE FROM product_images WHERE product_id IN (SELECT id FROM products WHERE template_id=? )", id); + jdbcTemplate.update("DELETE FROM product_prices WHERE product_id IN (SELECT id FROM products WHERE template_id=? )", id); + jdbcTemplate.update("DELETE FROM inventories WHERE product_id IN (SELECT id FROM products WHERE template_id=? )", id); + jdbcTemplate.update("UPDATE part_submissions SET deleted_at=NOW() WHERE template_id=? AND deleted_at IS NULL", id); + templateRepository.deleteById(id); + } + private void upsertParams(Long templateId, List params, LocalDateTime now) { if (params == null) return; int idx = 0; diff --git a/backend/src/main/java/com/example/demo/product/service/ProductService.java b/backend/src/main/java/com/example/demo/product/service/ProductService.java index bf5625f..1948fdb 100644 --- a/backend/src/main/java/com/example/demo/product/service/ProductService.java +++ b/backend/src/main/java/com/example/demo/product/service/ProductService.java @@ -96,10 +96,7 @@ public class ProductService { product.setCategoryId(submission.getCategoryId()); changed = true; } - if (submission.getUnitId() != null && !submission.getUnitId().equals(product.getUnitId())) { - product.setUnitId(submission.getUnitId()); - changed = true; - } + // 单位字段已移除 if (submission.getRemarkText() != null && !submission.getRemarkText().isBlank()) { product.setDescription(submission.getRemarkText()); changed = true; @@ -137,58 +134,55 @@ public class ProductService { syncImages(submission.getUserId(), productId, product.getShopId(), images); } - public Page search(Long shopId, String kw, Long categoryId, int page, int size) { - try { - Page p = productRepository.search(shopId, kw, categoryId, PageRequest.of(page, size)); - return p.map(prod -> { - ProductDtos.ProductListItem it = new ProductDtos.ProductListItem(); - it.id = prod.getId(); - it.name = prod.getName(); - it.brand = prod.getBrand(); - it.model = prod.getModel(); - it.spec = prod.getSpec(); - inventoryRepository.findById(prod.getId()).ifPresent(inv -> it.stock = inv.getQuantity()); - priceRepository.findById(prod.getId()).ifPresent(pr -> it.retailPrice = pr.getRetailPrice()); - List imgs = imageRepository.findByProductIdOrderBySortOrderAscIdAsc(prod.getId()); - it.cover = imgs.isEmpty() ? null : imgs.get(0).getUrl(); - return it; - }); - } catch (Exception e) { - // 安全回退为 JDBC 查询,保障功能可用 - StringBuilder sql = new StringBuilder("SELECT p.id,p.name,p.brand,p.model,p.spec,\n" + - "(SELECT i.quantity FROM inventories i WHERE i.product_id=p.id) AS stock,\n" + - "(SELECT pr.retail_price FROM product_prices pr WHERE pr.product_id=p.id) AS retail_price,\n" + - "(SELECT img.url FROM product_images img WHERE img.product_id=p.id ORDER BY img.sort_order, img.id LIMIT 1) AS cover\n" + - "FROM products p WHERE p.shop_id=? AND p.deleted_at IS NULL"); - List ps = new ArrayList<>(); - ps.add(shopId); - if (kw != null && !kw.isBlank()) { sql.append(" AND (p.name LIKE ? OR p.brand LIKE ? OR p.model LIKE ? OR p.spec LIKE ? OR p.barcode LIKE ?)"); - String like = "%" + kw + "%"; ps.add(like); ps.add(like); ps.add(like); ps.add(like); ps.add(like); } - if (categoryId != null) { sql.append(" AND p.category_id=?"); ps.add(categoryId); } - sql.append(" ORDER BY p.id DESC LIMIT ? OFFSET ?"); - ps.add(size); ps.add(page * size); - List list = jdbcTemplate.query(sql.toString(), (rs,rn) -> { - ProductDtos.ProductListItem it = new ProductDtos.ProductListItem(); - it.id = rs.getLong("id"); - it.name = rs.getString("name"); - it.brand = rs.getString("brand"); - it.model = rs.getString("model"); - it.spec = rs.getString("spec"); - java.math.BigDecimal st = (java.math.BigDecimal) rs.getObject("stock"); - it.stock = st; - java.math.BigDecimal rp = (java.math.BigDecimal) rs.getObject("retail_price"); - it.retailPrice = rp; - it.cover = rs.getString("cover"); - return it; - }, ps.toArray()); - return new PageImpl<>(list, PageRequest.of(page, size), list.size()); + public Page search(Long shopId, String kw, Long categoryId, Long templateId, java.util.Map paramFilters, int page, int size) { + // 直接使用 JDBC 支持 JSON_EXTRACT 过滤(MySQL) + StringBuilder sql = new StringBuilder("SELECT p.id,p.name,p.brand,p.model,p.spec,\n" + + "(SELECT i.quantity FROM inventories i WHERE i.product_id=p.id) AS stock,\n" + + "(SELECT pr.retail_price FROM product_prices pr WHERE pr.product_id=p.id) AS retail_price,\n" + + "(SELECT img.url FROM product_images img WHERE img.product_id=p.id ORDER BY img.sort_order, img.id LIMIT 1) AS cover,\n" + + "(p.deleted_at IS NOT NULL) AS deleted\n" + + "FROM products p WHERE p.shop_id=? AND p.deleted_at IS NULL"); + List ps = new ArrayList<>(); + ps.add(shopId); + if (kw != null && !kw.isBlank()) { sql.append(" AND (p.name LIKE ? OR p.brand LIKE ? OR p.model LIKE ? OR p.spec LIKE ? OR p.barcode LIKE ?)"); + String like = "%" + kw + "%"; ps.add(like); ps.add(like); ps.add(like); ps.add(like); ps.add(like); } + if (categoryId != null) { sql.append(" AND p.category_id=?"); ps.add(categoryId); } + if (templateId != null) { sql.append(" AND p.template_id=?"); ps.add(templateId); } + if (paramFilters != null && !paramFilters.isEmpty()) { + for (java.util.Map.Entry ent : paramFilters.entrySet()) { + String key = ent.getKey(); String val = ent.getValue(); + if (key == null || key.isBlank() || val == null || val.isBlank()) continue; + // 精确匹配参数值:将 JSON 值解包后与入参做等值比较,避免 LIKE 导致的误匹配 + sql.append(" AND JSON_UNQUOTE(JSON_EXTRACT(p.attributes_json, ?)) = ?"); + ps.add("$." + key); + ps.add(val.trim()); + } } + sql.append(" ORDER BY p.id DESC LIMIT ? OFFSET ?"); + ps.add(size); ps.add(page * size); + List list = jdbcTemplate.query(sql.toString(), (rs,rn) -> { + ProductDtos.ProductListItem it = new ProductDtos.ProductListItem(); + it.id = rs.getLong("id"); + it.name = rs.getString("name"); + it.brand = rs.getString("brand"); + it.model = rs.getString("model"); + it.spec = rs.getString("spec"); + java.math.BigDecimal st = (java.math.BigDecimal) rs.getObject("stock"); + it.stock = st; + java.math.BigDecimal rp = (java.math.BigDecimal) rs.getObject("retail_price"); + it.retailPrice = rp; + it.cover = rs.getString("cover"); + it.deleted = rs.getBoolean("deleted"); + return it; + }, ps.toArray()); + return new PageImpl<>(list, PageRequest.of(page, size), list.size()); } - public Optional findDetail(Long id) { + public Optional findDetail(Long id, boolean includeDeleted) { Optional op = productRepository.findById(id); if (op.isEmpty()) return Optional.empty(); Product p = op.get(); + if (p.getDeletedAt() != null && !includeDeleted) return Optional.empty(); ProductDtos.ProductDetail d = new ProductDtos.ProductDetail(); d.id = p.getId(); d.name = p.getName(); @@ -198,7 +192,7 @@ public class ProductService { d.spec = p.getSpec(); d.origin = p.getOrigin(); d.categoryId = p.getCategoryId(); - d.unitId = p.getUnitId(); + d.templateId = p.getTemplateId(); d.safeMin = p.getSafeMin(); d.safeMax = p.getSafeMax(); inventoryRepository.findById(p.getId()).ifPresent(inv -> d.stock = inv.getQuantity()); @@ -216,6 +210,11 @@ public class ProductService { list.add(i); } d.images = list; + d.parameters = JsonUtils.fromJson(p.getAttributesJson(), new com.fasterxml.jackson.core.type.TypeReference>() {}); + d.sourceSubmissionId = p.getSourceSubmissionId(); + // deleted 标志供前端展示 + d.deleted = (p.getDeletedAt() != null); + // externalCode 来自 submission,若来源存在可透传(此处留空,由前端兼容) return Optional.of(d); } @@ -235,7 +234,7 @@ public class ProductService { p.setSpec(emptyToNull(req.spec)); p.setOrigin(emptyToNull(req.origin)); p.setCategoryId(req.categoryId); - p.setUnitId(req.unitId); + // 单位字段已移除 p.setDedupeKey(emptyToNull(req.dedupeKey)); p.setSafeMin(req.safeMin); p.setSafeMax(req.safeMax); @@ -290,7 +289,7 @@ public class ProductService { p.setSpec(emptyToNull(req.spec)); p.setOrigin(emptyToNull(req.origin)); p.setCategoryId(req.categoryId); - p.setUnitId(req.unitId); + // 单位字段已移除 p.setDedupeKey(emptyToNull(req.dedupeKey)); p.setSafeMin(req.safeMin); p.setSafeMax(req.safeMax); @@ -306,7 +305,7 @@ public class ProductService { private void validate(Long shopId, ProductDtos.CreateOrUpdateProductRequest req) { if (req.name == null || req.name.isBlank()) throw new IllegalArgumentException("name必填"); - if (req.unitId == null) throw new IllegalArgumentException("unitId必填"); + // 不再要求 unitId if (req.safeMin != null && req.safeMax != null) { if (req.safeMin.compareTo(req.safeMax) > 0) throw new IllegalArgumentException("安全库存区间不合法"); } @@ -360,6 +359,16 @@ public class ProductService { private static T nvl(T v, T def) { return v != null ? v : def; } private static String emptyToNull(String s) { return (s == null || s.isBlank()) ? null : s; } + + @Transactional + public void delete(Long id, Long shopId) { + Product p = productRepository.findById(id).orElse(null); + if (p == null) return; + if (!p.getShopId().equals(shopId)) throw new IllegalArgumentException("跨店铺数据"); + p.setDeletedAt(LocalDateTime.now()); + productRepository.save(p); + // 关联数据:价格/库存采用 ON DELETE CASCADE 不触发;软删仅标记主表 + } } diff --git a/backend/src/main/java/com/example/demo/product/service/ProductSubmissionService.java b/backend/src/main/java/com/example/demo/product/service/ProductSubmissionService.java index 47b2349..67ca6b5 100644 --- a/backend/src/main/java/com/example/demo/product/service/ProductSubmissionService.java +++ b/backend/src/main/java/com/example/demo/product/service/ProductSubmissionService.java @@ -14,6 +14,7 @@ import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Sort; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; +import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -43,15 +44,18 @@ public class ProductSubmissionService { private final ProductService productService; private final PartTemplateParamRepository templateParamRepository; private final AppDefaultsProperties defaults; + private final JdbcTemplate jdbcTemplate; public ProductSubmissionService(ProductSubmissionRepository submissionRepository, ProductService productService, AppDefaultsProperties defaults, - PartTemplateParamRepository templateParamRepository) { + PartTemplateParamRepository templateParamRepository, + JdbcTemplate jdbcTemplate) { this.submissionRepository = submissionRepository; this.productService = productService; this.defaults = defaults; this.templateParamRepository = templateParamRepository; + this.jdbcTemplate = jdbcTemplate; } @Transactional @@ -61,12 +65,13 @@ public class ProductSubmissionService { submission.setShopId(shopId); submission.setUserId(userId); submission.setTemplateId(req.templateId); + if (req.externalCode != null && !req.externalCode.isBlank()) submission.setExternalCode(req.externalCode.trim()); submission.setName(req.name); submission.setModelUnique(normalizeModel(req.model)); submission.setBrand(req.brand); submission.setSpec(req.spec); submission.setOrigin(req.origin); - submission.setUnitId(req.unitId); + // 单位字段已移除 submission.setCategoryId(req.categoryId); submission.setAttributesJson(JsonUtils.toJson(req.parameters)); submission.setImagesJson(JsonUtils.toJson(req.images)); @@ -84,7 +89,7 @@ public class ProductSubmissionService { public ProductSubmissionDtos.PageResult listMine(Long shopId, Long userId, String status, int page, int size) { String normalizedStatus = (status == null || status.isBlank() || "undefined".equalsIgnoreCase(status)) ? null : status; - Page result = submissionRepository.findByShopIdAndUserIdAndStatusIn( + Page result = submissionRepository.findByShopIdAndUserIdAndStatusInAndDeletedAtIsNull( shopId, userId, resolveStatuses(normalizedStatus), PageRequest.of(Math.max(page - 1, 0), size, Sort.by(Sort.Direction.DESC, "createdAt"))); return toPageResult(result); } @@ -109,6 +114,26 @@ public class ProductSubmissionService { LocalDateTime endTime = parseDate(endAt); List records = submissionRepository.searchAdmin(statuses.isEmpty() ? null : statuses, kwLike, shopId, reviewerId, start, endTime, PageRequest.of(0, 2000, Sort.by(Sort.Direction.DESC, "createdAt"))).getContent(); + // 收集所有模板的必填参数标题 + java.util.LinkedHashSet requiredParamLabels = new java.util.LinkedHashSet<>(); + java.util.Map> labelToKeyByTemplate = new java.util.HashMap<>(); + for (ProductSubmission s : records) { + Long tid = s.getTemplateId(); + if (tid == null || tid <= 0) continue; + if (!labelToKeyByTemplate.containsKey(tid)) { + java.util.Map map = new java.util.LinkedHashMap<>(); + var defs = templateParamRepository.findByTemplateIdOrderBySortOrderAscIdAsc(tid); + for (var d : defs) { + if (Boolean.TRUE.equals(d.getRequired())) { + map.put(d.getFieldLabel(), d.getFieldKey()); + requiredParamLabels.add(d.getFieldLabel()); + } + } + labelToKeyByTemplate.put(tid, map); + } else { + for (var e : labelToKeyByTemplate.get(tid).keySet()) requiredParamLabels.add(e); + } + } try (Workbook workbook = new XSSFWorkbook()) { Sheet sheet = workbook.createSheet("Submissions"); CreationHelper creationHelper = workbook.getCreationHelper(); @@ -117,27 +142,36 @@ public class ProductSubmissionService { int rowIdx = 0; Row header = sheet.createRow(rowIdx++); - String[] headers = {"ID", "型号", "名称", "品牌", "状态", "提交人", "店铺", "提交时间", "审核时间", "审核备注"}; - for (int i = 0; i < headers.length; i++) { - header.createCell(i).setCellValue(headers[i]); - } + java.util.List headers = new java.util.ArrayList<>(); + headers.add("编号"); + headers.add("分类"); + headers.add("品牌"); + headers.add("型号"); + headers.addAll(requiredParamLabels); + headers.add("备注"); + for (int i = 0; i < headers.size(); i++) header.createCell(i).setCellValue(headers.get(i)); for (ProductSubmission submission : records) { Row row = sheet.createRow(rowIdx++); int col = 0; - row.createCell(col++).setCellValue(submission.getId()); - row.createCell(col++).setCellValue(nvl(submission.getModelUnique())); - row.createCell(col++).setCellValue(nvl(submission.getName())); + // 编号、分类、品牌、型号 + row.createCell(col++).setCellValue(nvl(submission.getExternalCode())); + row.createCell(col++).setCellValue(nvl(resolveCategoryName(submission.getCategoryId()))); row.createCell(col++).setCellValue(nvl(submission.getBrand())); - row.createCell(col++).setCellValue(submission.getStatus().name()); - row.createCell(col++).setCellValue(submission.getUserId() != null ? submission.getUserId() : 0); - row.createCell(col++).setCellValue(submission.getShopId() != null ? submission.getShopId() : 0); - setDateCell(row.createCell(col++), submission.getCreatedAt(), dateStyle); - setDateCell(row.createCell(col++), submission.getReviewedAt(), dateStyle); - row.createCell(col).setCellValue(nvl(submission.getReviewRemark())); + row.createCell(col++).setCellValue(nvl(submission.getModelUnique())); + // 模板必填参数值 + java.util.Map params = JsonUtils.fromJson(submission.getAttributesJson(), new com.fasterxml.jackson.core.type.TypeReference>() {}); + java.util.Map l2k = labelToKeyByTemplate.getOrDefault(submission.getTemplateId(), java.util.Collections.emptyMap()); + for (String label : requiredParamLabels) { + String key = l2k.get(label); + Object v = (key == null || params == null) ? null : params.get(key); + row.createCell(col++).setCellValue(v == null ? "" : String.valueOf(v)); + } + // 备注 + row.createCell(col).setCellValue(nvl(submission.getRemarkText())); } - for (int i = 0; i < headers.length; i++) { + for (int i = 0; i < headers.size(); i++) { sheet.autoSizeColumn(i); int width = sheet.getColumnWidth(i); sheet.setColumnWidth(i, Math.min(width + 512, 10000)); @@ -153,6 +187,15 @@ public class ProductSubmissionService { } } + private final java.util.Map categoryNameCache = new java.util.HashMap<>(); + private String resolveCategoryName(Long categoryId) { + if (categoryId == null) return ""; + if (categoryNameCache.containsKey(categoryId)) return categoryNameCache.get(categoryId); + String name = jdbcTemplate.query("SELECT name FROM product_categories WHERE id=?", ps -> ps.setLong(1, categoryId), rs -> rs.next()? rs.getString(1): ""); + categoryNameCache.put(categoryId, name == null ? "" : name); + return name == null ? "" : name; + } + public Optional findDetail(Long id) { return submissionRepository.findById(id).map(this::toDetail); } @@ -168,10 +211,11 @@ public class ProductSubmissionService { throw new IllegalArgumentException("仅待审核记录可编辑"); } submission.setName(req.name != null ? req.name : submission.getName()); + if (req.externalCode != null) submission.setExternalCode(req.externalCode); submission.setBrand(req.brand != null ? req.brand : submission.getBrand()); submission.setSpec(req.spec != null ? req.spec : submission.getSpec()); submission.setOrigin(req.origin != null ? req.origin : submission.getOrigin()); - submission.setUnitId(req.unitId != null ? req.unitId : submission.getUnitId()); + // 单位字段已移除 submission.setCategoryId(req.categoryId != null ? req.categoryId : submission.getCategoryId()); if (req.parameters != null) submission.setAttributesJson(JsonUtils.toJson(req.parameters)); if (req.images != null) submission.setImagesJson(JsonUtils.toJson(req.images)); @@ -372,11 +416,12 @@ public class ProductSubmissionService { detail.shopId = submission.getShopId(); detail.userId = submission.getUserId(); detail.name = submission.getName(); + detail.externalCode = submission.getExternalCode(); detail.model = submission.getModelUnique(); detail.brand = submission.getBrand(); detail.spec = submission.getSpec(); detail.origin = submission.getOrigin(); - detail.unitId = submission.getUnitId(); + // 单位字段已移除 detail.categoryId = submission.getCategoryId(); detail.templateId = submission.getTemplateId(); detail.parameters = JsonUtils.fromJson(submission.getAttributesJson(), new com.fasterxml.jackson.core.type.TypeReference>() {}); @@ -426,7 +471,7 @@ public class ProductSubmissionService { payload.spec = submission.getSpec(); payload.origin = submission.getOrigin(); payload.categoryId = submission.getCategoryId(); - payload.unitId = submission.getUnitId(); + // 单位字段已移除 payload.dedupeKey = submission.getDedupeKey(); payload.safeMin = submission.getSafeMin(); payload.safeMax = submission.getSafeMax(); diff --git a/backend/txm/debug_out/txm.log b/backend/txm/debug_out/txm.log index a872eb2..71b4d1d 100644 --- a/backend/txm/debug_out/txm.log +++ b/backend/txm/debug_out/txm.log @@ -94,3 +94,135 @@ 2025-09-27 22:56:27.814 | INFO | __main__ | 启动 FastAPI 服务器: 127.0.0.1:8000 2025-09-27 22:56:27.815 | DEBUG | asyncio | Using proactor: IocpProactor 2025-09-27 22:56:27.839 | DEBUG | EAN13Recognizer | 配置加载完成: preprocess={'resize_width': 1280, 'gaussian_blur_ksize': 3, 'morphology_kernel': 17, 'sobel_ksize': 3, 'binarize': 'otsu', 'close_kernel': 21}, roi={'min_area_ratio': 0.01, 'min_wh_ratio': 2.0, 'warp_target_height': 120, 'crop_bottom_ratio': 0.25}, decoder={'sample_rows': [0.35, 0.5, 0.65], 'total_modules': 95, 'guard_tolerance': 0.35, 'peak_valley_rel_threshold': 0.2, 'engine_order': ['pyzbar', 'ean13'], 'try_invert': True, 'rotations': [0, 90, 180, 270]} +2025-09-27 23:05:41.132 | DEBUG | EAN13Recognizer | 配置加载完成: preprocess={'resize_width': 1280, 'gaussian_blur_ksize': 3, 'morphology_kernel': 17, 'sobel_ksize': 3, 'binarize': 'otsu', 'close_kernel': 21}, roi={'min_area_ratio': 0.01, 'min_wh_ratio': 2.0, 'warp_target_height': 120, 'crop_bottom_ratio': 0.25}, decoder={'sample_rows': [0.35, 0.5, 0.65], 'total_modules': 95, 'guard_tolerance': 0.35, 'peak_valley_rel_threshold': 0.2, 'engine_order': ['pyzbar', 'ean13'], 'try_invert': True, 'rotations': [0, 90, 180, 270]} +2025-09-27 23:05:41.133 | INFO | __main__ | 启动 FastAPI 服务器: 127.0.0.1:8000 +2025-09-27 23:05:41.135 | DEBUG | asyncio | Using proactor: IocpProactor +2025-09-27 23:05:41.171 | DEBUG | EAN13Recognizer | 配置加载完成: preprocess={'resize_width': 1280, 'gaussian_blur_ksize': 3, 'morphology_kernel': 17, 'sobel_ksize': 3, 'binarize': 'otsu', 'close_kernel': 21}, roi={'min_area_ratio': 0.01, 'min_wh_ratio': 2.0, 'warp_target_height': 120, 'crop_bottom_ratio': 0.25}, decoder={'sample_rows': [0.35, 0.5, 0.65], 'total_modules': 95, 'guard_tolerance': 0.35, 'peak_valley_rel_threshold': 0.2, 'engine_order': ['pyzbar', 'ean13'], 'try_invert': True, 'rotations': [0, 90, 180, 270]} +2025-09-27 23:47:53.925 | DEBUG | EAN13Recognizer | 配置加载完成: preprocess={'resize_width': 1280, 'gaussian_blur_ksize': 3, 'morphology_kernel': 17, 'sobel_ksize': 3, 'binarize': 'otsu', 'close_kernel': 21}, roi={'min_area_ratio': 0.01, 'min_wh_ratio': 2.0, 'warp_target_height': 120, 'crop_bottom_ratio': 0.25}, decoder={'sample_rows': [0.35, 0.5, 0.65], 'total_modules': 95, 'guard_tolerance': 0.35, 'peak_valley_rel_threshold': 0.2, 'engine_order': ['pyzbar', 'ean13'], 'try_invert': True, 'rotations': [0, 90, 180, 270]} +2025-09-27 23:47:53.926 | INFO | __main__ | 启动 FastAPI 服务器: 127.0.0.1:8000 +2025-09-27 23:47:53.928 | DEBUG | asyncio | Using proactor: IocpProactor +2025-09-27 23:47:53.957 | DEBUG | EAN13Recognizer | 配置加载完成: preprocess={'resize_width': 1280, 'gaussian_blur_ksize': 3, 'morphology_kernel': 17, 'sobel_ksize': 3, 'binarize': 'otsu', 'close_kernel': 21}, roi={'min_area_ratio': 0.01, 'min_wh_ratio': 2.0, 'warp_target_height': 120, 'crop_bottom_ratio': 0.25}, decoder={'sample_rows': [0.35, 0.5, 0.65], 'total_modules': 95, 'guard_tolerance': 0.35, 'peak_valley_rel_threshold': 0.2, 'engine_order': ['pyzbar', 'ean13'], 'try_invert': True, 'rotations': [0, 90, 180, 270]} +2025-09-28 01:24:20.344 | DEBUG | EAN13Recognizer | 配置加载完成: preprocess={'resize_width': 1280, 'gaussian_blur_ksize': 3, 'morphology_kernel': 17, 'sobel_ksize': 3, 'binarize': 'otsu', 'close_kernel': 21}, roi={'min_area_ratio': 0.01, 'min_wh_ratio': 2.0, 'warp_target_height': 120, 'crop_bottom_ratio': 0.25}, decoder={'sample_rows': [0.35, 0.5, 0.65], 'total_modules': 95, 'guard_tolerance': 0.35, 'peak_valley_rel_threshold': 0.2, 'engine_order': ['pyzbar', 'ean13'], 'try_invert': True, 'rotations': [0, 90, 180, 270]} +2025-09-28 01:24:20.346 | INFO | __main__ | 启动 FastAPI 服务器: 127.0.0.1:8000 +2025-09-28 01:24:20.363 | DEBUG | asyncio | Using proactor: IocpProactor +2025-09-28 01:24:20.585 | DEBUG | EAN13Recognizer | 配置加载完成: preprocess={'resize_width': 1280, 'gaussian_blur_ksize': 3, 'morphology_kernel': 17, 'sobel_ksize': 3, 'binarize': 'otsu', 'close_kernel': 21}, roi={'min_area_ratio': 0.01, 'min_wh_ratio': 2.0, 'warp_target_height': 120, 'crop_bottom_ratio': 0.25}, decoder={'sample_rows': [0.35, 0.5, 0.65], 'total_modules': 95, 'guard_tolerance': 0.35, 'peak_valley_rel_threshold': 0.2, 'engine_order': ['pyzbar', 'ean13'], 'try_invert': True, 'rotations': [0, 90, 180, 270]} +2025-09-28 22:00:52.538 | DEBUG | EAN13Recognizer | 配置加载完成: preprocess={'resize_width': 1280, 'gaussian_blur_ksize': 3, 'morphology_kernel': 17, 'sobel_ksize': 3, 'binarize': 'otsu', 'close_kernel': 21}, roi={'min_area_ratio': 0.01, 'min_wh_ratio': 2.0, 'warp_target_height': 120, 'crop_bottom_ratio': 0.25}, decoder={'sample_rows': [0.35, 0.5, 0.65], 'total_modules': 95, 'guard_tolerance': 0.35, 'peak_valley_rel_threshold': 0.2, 'engine_order': ['pyzbar', 'ean13'], 'try_invert': True, 'rotations': [0, 90, 180, 270]} +2025-09-28 22:00:52.542 | INFO | __main__ | 启动 FastAPI 服务器: 127.0.0.1:8000 +2025-09-28 22:00:52.560 | DEBUG | asyncio | Using proactor: IocpProactor +2025-09-28 22:00:52.876 | DEBUG | EAN13Recognizer | 配置加载完成: preprocess={'resize_width': 1280, 'gaussian_blur_ksize': 3, 'morphology_kernel': 17, 'sobel_ksize': 3, 'binarize': 'otsu', 'close_kernel': 21}, roi={'min_area_ratio': 0.01, 'min_wh_ratio': 2.0, 'warp_target_height': 120, 'crop_bottom_ratio': 0.25}, decoder={'sample_rows': [0.35, 0.5, 0.65], 'total_modules': 95, 'guard_tolerance': 0.35, 'peak_valley_rel_threshold': 0.2, 'engine_order': ['pyzbar', 'ean13'], 'try_invert': True, 'rotations': [0, 90, 180, 270]} +2025-09-28 22:02:38.951 | DEBUG | EAN13Recognizer | 配置加载完成: preprocess={'resize_width': 1280, 'gaussian_blur_ksize': 3, 'morphology_kernel': 17, 'sobel_ksize': 3, 'binarize': 'otsu', 'close_kernel': 21}, roi={'min_area_ratio': 0.01, 'min_wh_ratio': 2.0, 'warp_target_height': 120, 'crop_bottom_ratio': 0.25}, decoder={'sample_rows': [0.35, 0.5, 0.65], 'total_modules': 95, 'guard_tolerance': 0.35, 'peak_valley_rel_threshold': 0.2, 'engine_order': ['pyzbar', 'ean13'], 'try_invert': True, 'rotations': [0, 90, 180, 270]} +2025-09-28 22:02:38.954 | INFO | __main__ | 启动 FastAPI 服务器: 127.0.0.1:8000 +2025-09-28 22:02:38.956 | DEBUG | asyncio | Using proactor: IocpProactor +2025-09-28 22:02:38.980 | DEBUG | EAN13Recognizer | 配置加载完成: preprocess={'resize_width': 1280, 'gaussian_blur_ksize': 3, 'morphology_kernel': 17, 'sobel_ksize': 3, 'binarize': 'otsu', 'close_kernel': 21}, roi={'min_area_ratio': 0.01, 'min_wh_ratio': 2.0, 'warp_target_height': 120, 'crop_bottom_ratio': 0.25}, decoder={'sample_rows': [0.35, 0.5, 0.65], 'total_modules': 95, 'guard_tolerance': 0.35, 'peak_valley_rel_threshold': 0.2, 'engine_order': ['pyzbar', 'ean13'], 'try_invert': True, 'rotations': [0, 90, 180, 270]} +2025-09-28 22:29:34.466 | DEBUG | EAN13Recognizer | 配置加载完成: preprocess={'resize_width': 1280, 'gaussian_blur_ksize': 3, 'morphology_kernel': 17, 'sobel_ksize': 3, 'binarize': 'otsu', 'close_kernel': 21}, roi={'min_area_ratio': 0.01, 'min_wh_ratio': 2.0, 'warp_target_height': 120, 'crop_bottom_ratio': 0.25}, decoder={'sample_rows': [0.35, 0.5, 0.65], 'total_modules': 95, 'guard_tolerance': 0.35, 'peak_valley_rel_threshold': 0.2, 'engine_order': ['pyzbar', 'ean13'], 'try_invert': True, 'rotations': [0, 90, 180, 270]} +2025-09-28 22:29:34.468 | INFO | __main__ | 启动 FastAPI 服务器: 127.0.0.1:8000 +2025-09-28 22:29:34.476 | DEBUG | asyncio | Using proactor: IocpProactor +2025-09-28 22:29:34.670 | DEBUG | EAN13Recognizer | 配置加载完成: preprocess={'resize_width': 1280, 'gaussian_blur_ksize': 3, 'morphology_kernel': 17, 'sobel_ksize': 3, 'binarize': 'otsu', 'close_kernel': 21}, roi={'min_area_ratio': 0.01, 'min_wh_ratio': 2.0, 'warp_target_height': 120, 'crop_bottom_ratio': 0.25}, decoder={'sample_rows': [0.35, 0.5, 0.65], 'total_modules': 95, 'guard_tolerance': 0.35, 'peak_valley_rel_threshold': 0.2, 'engine_order': ['pyzbar', 'ean13'], 'try_invert': True, 'rotations': [0, 90, 180, 270]} +2025-09-28 22:35:16.776 | DEBUG | EAN13Recognizer | 配置加载完成: preprocess={'resize_width': 1280, 'gaussian_blur_ksize': 3, 'morphology_kernel': 17, 'sobel_ksize': 3, 'binarize': 'otsu', 'close_kernel': 21}, roi={'min_area_ratio': 0.01, 'min_wh_ratio': 2.0, 'warp_target_height': 120, 'crop_bottom_ratio': 0.25}, decoder={'sample_rows': [0.35, 0.5, 0.65], 'total_modules': 95, 'guard_tolerance': 0.35, 'peak_valley_rel_threshold': 0.2, 'engine_order': ['pyzbar', 'ean13'], 'try_invert': True, 'rotations': [0, 90, 180, 270]} +2025-09-28 22:35:16.779 | INFO | __main__ | 启动 FastAPI 服务器: 127.0.0.1:8000 +2025-09-28 22:35:16.780 | DEBUG | asyncio | Using proactor: IocpProactor +2025-09-28 22:35:16.811 | DEBUG | EAN13Recognizer | 配置加载完成: preprocess={'resize_width': 1280, 'gaussian_blur_ksize': 3, 'morphology_kernel': 17, 'sobel_ksize': 3, 'binarize': 'otsu', 'close_kernel': 21}, roi={'min_area_ratio': 0.01, 'min_wh_ratio': 2.0, 'warp_target_height': 120, 'crop_bottom_ratio': 0.25}, decoder={'sample_rows': [0.35, 0.5, 0.65], 'total_modules': 95, 'guard_tolerance': 0.35, 'peak_valley_rel_threshold': 0.2, 'engine_order': ['pyzbar', 'ean13'], 'try_invert': True, 'rotations': [0, 90, 180, 270]} +2025-09-28 22:38:31.014 | DEBUG | EAN13Recognizer | 配置加载完成: preprocess={'resize_width': 1280, 'gaussian_blur_ksize': 3, 'morphology_kernel': 17, 'sobel_ksize': 3, 'binarize': 'otsu', 'close_kernel': 21}, roi={'min_area_ratio': 0.01, 'min_wh_ratio': 2.0, 'warp_target_height': 120, 'crop_bottom_ratio': 0.25}, decoder={'sample_rows': [0.35, 0.5, 0.65], 'total_modules': 95, 'guard_tolerance': 0.35, 'peak_valley_rel_threshold': 0.2, 'engine_order': ['pyzbar', 'ean13'], 'try_invert': True, 'rotations': [0, 90, 180, 270]} +2025-09-28 22:38:31.017 | INFO | __main__ | 启动 FastAPI 服务器: 127.0.0.1:8000 +2025-09-28 22:38:31.020 | DEBUG | asyncio | Using proactor: IocpProactor +2025-09-28 22:38:31.048 | DEBUG | EAN13Recognizer | 配置加载完成: preprocess={'resize_width': 1280, 'gaussian_blur_ksize': 3, 'morphology_kernel': 17, 'sobel_ksize': 3, 'binarize': 'otsu', 'close_kernel': 21}, roi={'min_area_ratio': 0.01, 'min_wh_ratio': 2.0, 'warp_target_height': 120, 'crop_bottom_ratio': 0.25}, decoder={'sample_rows': [0.35, 0.5, 0.65], 'total_modules': 95, 'guard_tolerance': 0.35, 'peak_valley_rel_threshold': 0.2, 'engine_order': ['pyzbar', 'ean13'], 'try_invert': True, 'rotations': [0, 90, 180, 270]} +2025-09-28 23:06:13.053 | DEBUG | EAN13Recognizer | 配置加载完成: preprocess={'resize_width': 1280, 'gaussian_blur_ksize': 3, 'morphology_kernel': 17, 'sobel_ksize': 3, 'binarize': 'otsu', 'close_kernel': 21}, roi={'min_area_ratio': 0.01, 'min_wh_ratio': 2.0, 'warp_target_height': 120, 'crop_bottom_ratio': 0.25}, decoder={'sample_rows': [0.35, 0.5, 0.65], 'total_modules': 95, 'guard_tolerance': 0.35, 'peak_valley_rel_threshold': 0.2, 'engine_order': ['pyzbar', 'ean13'], 'try_invert': True, 'rotations': [0, 90, 180, 270]} +2025-09-28 23:06:13.055 | INFO | __main__ | 启动 FastAPI 服务器: 127.0.0.1:8000 +2025-09-28 23:06:13.057 | DEBUG | asyncio | Using proactor: IocpProactor +2025-09-28 23:06:13.108 | DEBUG | EAN13Recognizer | 配置加载完成: preprocess={'resize_width': 1280, 'gaussian_blur_ksize': 3, 'morphology_kernel': 17, 'sobel_ksize': 3, 'binarize': 'otsu', 'close_kernel': 21}, roi={'min_area_ratio': 0.01, 'min_wh_ratio': 2.0, 'warp_target_height': 120, 'crop_bottom_ratio': 0.25}, decoder={'sample_rows': [0.35, 0.5, 0.65], 'total_modules': 95, 'guard_tolerance': 0.35, 'peak_valley_rel_threshold': 0.2, 'engine_order': ['pyzbar', 'ean13'], 'try_invert': True, 'rotations': [0, 90, 180, 270]} +2025-09-28 23:15:20.745 | DEBUG | EAN13Recognizer | 配置加载完成: preprocess={'resize_width': 1280, 'gaussian_blur_ksize': 3, 'morphology_kernel': 17, 'sobel_ksize': 3, 'binarize': 'otsu', 'close_kernel': 21}, roi={'min_area_ratio': 0.01, 'min_wh_ratio': 2.0, 'warp_target_height': 120, 'crop_bottom_ratio': 0.25}, decoder={'sample_rows': [0.35, 0.5, 0.65], 'total_modules': 95, 'guard_tolerance': 0.35, 'peak_valley_rel_threshold': 0.2, 'engine_order': ['pyzbar', 'ean13'], 'try_invert': True, 'rotations': [0, 90, 180, 270]} +2025-09-28 23:15:20.749 | INFO | __main__ | 启动 FastAPI 服务器: 127.0.0.1:8000 +2025-09-28 23:15:20.753 | DEBUG | asyncio | Using proactor: IocpProactor +2025-09-28 23:15:20.798 | DEBUG | EAN13Recognizer | 配置加载完成: preprocess={'resize_width': 1280, 'gaussian_blur_ksize': 3, 'morphology_kernel': 17, 'sobel_ksize': 3, 'binarize': 'otsu', 'close_kernel': 21}, roi={'min_area_ratio': 0.01, 'min_wh_ratio': 2.0, 'warp_target_height': 120, 'crop_bottom_ratio': 0.25}, decoder={'sample_rows': [0.35, 0.5, 0.65], 'total_modules': 95, 'guard_tolerance': 0.35, 'peak_valley_rel_threshold': 0.2, 'engine_order': ['pyzbar', 'ean13'], 'try_invert': True, 'rotations': [0, 90, 180, 270]} +2025-09-28 23:22:54.219 | DEBUG | EAN13Recognizer | 配置加载完成: preprocess={'resize_width': 1280, 'gaussian_blur_ksize': 3, 'morphology_kernel': 17, 'sobel_ksize': 3, 'binarize': 'otsu', 'close_kernel': 21}, roi={'min_area_ratio': 0.01, 'min_wh_ratio': 2.0, 'warp_target_height': 120, 'crop_bottom_ratio': 0.25}, decoder={'sample_rows': [0.35, 0.5, 0.65], 'total_modules': 95, 'guard_tolerance': 0.35, 'peak_valley_rel_threshold': 0.2, 'engine_order': ['pyzbar', 'ean13'], 'try_invert': True, 'rotations': [0, 90, 180, 270]} +2025-09-28 23:22:54.223 | INFO | __main__ | 启动 FastAPI 服务器: 127.0.0.1:8000 +2025-09-28 23:22:54.226 | DEBUG | asyncio | Using proactor: IocpProactor +2025-09-28 23:22:54.264 | DEBUG | EAN13Recognizer | 配置加载完成: preprocess={'resize_width': 1280, 'gaussian_blur_ksize': 3, 'morphology_kernel': 17, 'sobel_ksize': 3, 'binarize': 'otsu', 'close_kernel': 21}, roi={'min_area_ratio': 0.01, 'min_wh_ratio': 2.0, 'warp_target_height': 120, 'crop_bottom_ratio': 0.25}, decoder={'sample_rows': [0.35, 0.5, 0.65], 'total_modules': 95, 'guard_tolerance': 0.35, 'peak_valley_rel_threshold': 0.2, 'engine_order': ['pyzbar', 'ean13'], 'try_invert': True, 'rotations': [0, 90, 180, 270]} +2025-09-28 23:23:45.474 | DEBUG | EAN13Recognizer | 配置加载完成: preprocess={'resize_width': 1280, 'gaussian_blur_ksize': 3, 'morphology_kernel': 17, 'sobel_ksize': 3, 'binarize': 'otsu', 'close_kernel': 21}, roi={'min_area_ratio': 0.01, 'min_wh_ratio': 2.0, 'warp_target_height': 120, 'crop_bottom_ratio': 0.25}, decoder={'sample_rows': [0.35, 0.5, 0.65], 'total_modules': 95, 'guard_tolerance': 0.35, 'peak_valley_rel_threshold': 0.2, 'engine_order': ['pyzbar', 'ean13'], 'try_invert': True, 'rotations': [0, 90, 180, 270]} +2025-09-28 23:23:45.482 | INFO | __main__ | 启动 FastAPI 服务器: 127.0.0.1:8000 +2025-09-28 23:23:45.490 | DEBUG | asyncio | Using proactor: IocpProactor +2025-09-28 23:23:45.530 | DEBUG | EAN13Recognizer | 配置加载完成: preprocess={'resize_width': 1280, 'gaussian_blur_ksize': 3, 'morphology_kernel': 17, 'sobel_ksize': 3, 'binarize': 'otsu', 'close_kernel': 21}, roi={'min_area_ratio': 0.01, 'min_wh_ratio': 2.0, 'warp_target_height': 120, 'crop_bottom_ratio': 0.25}, decoder={'sample_rows': [0.35, 0.5, 0.65], 'total_modules': 95, 'guard_tolerance': 0.35, 'peak_valley_rel_threshold': 0.2, 'engine_order': ['pyzbar', 'ean13'], 'try_invert': True, 'rotations': [0, 90, 180, 270]} +2025-09-28 23:41:40.864 | DEBUG | EAN13Recognizer | 配置加载完成: preprocess={'resize_width': 1280, 'gaussian_blur_ksize': 3, 'morphology_kernel': 17, 'sobel_ksize': 3, 'binarize': 'otsu', 'close_kernel': 21}, roi={'min_area_ratio': 0.01, 'min_wh_ratio': 2.0, 'warp_target_height': 120, 'crop_bottom_ratio': 0.25}, decoder={'sample_rows': [0.35, 0.5, 0.65], 'total_modules': 95, 'guard_tolerance': 0.35, 'peak_valley_rel_threshold': 0.2, 'engine_order': ['pyzbar', 'ean13'], 'try_invert': True, 'rotations': [0, 90, 180, 270]} +2025-09-28 23:41:40.869 | INFO | __main__ | 启动 FastAPI 服务器: 127.0.0.1:8000 +2025-09-28 23:41:40.873 | DEBUG | asyncio | Using proactor: IocpProactor +2025-09-28 23:41:40.910 | DEBUG | EAN13Recognizer | 配置加载完成: preprocess={'resize_width': 1280, 'gaussian_blur_ksize': 3, 'morphology_kernel': 17, 'sobel_ksize': 3, 'binarize': 'otsu', 'close_kernel': 21}, roi={'min_area_ratio': 0.01, 'min_wh_ratio': 2.0, 'warp_target_height': 120, 'crop_bottom_ratio': 0.25}, decoder={'sample_rows': [0.35, 0.5, 0.65], 'total_modules': 95, 'guard_tolerance': 0.35, 'peak_valley_rel_threshold': 0.2, 'engine_order': ['pyzbar', 'ean13'], 'try_invert': True, 'rotations': [0, 90, 180, 270]} +2025-09-28 23:50:01.655 | DEBUG | EAN13Recognizer | 配置加载完成: preprocess={'resize_width': 1280, 'gaussian_blur_ksize': 3, 'morphology_kernel': 17, 'sobel_ksize': 3, 'binarize': 'otsu', 'close_kernel': 21}, roi={'min_area_ratio': 0.01, 'min_wh_ratio': 2.0, 'warp_target_height': 120, 'crop_bottom_ratio': 0.25}, decoder={'sample_rows': [0.35, 0.5, 0.65], 'total_modules': 95, 'guard_tolerance': 0.35, 'peak_valley_rel_threshold': 0.2, 'engine_order': ['pyzbar', 'ean13'], 'try_invert': True, 'rotations': [0, 90, 180, 270]} +2025-09-28 23:50:01.658 | INFO | __main__ | 启动 FastAPI 服务器: 127.0.0.1:8000 +2025-09-28 23:50:01.661 | DEBUG | asyncio | Using proactor: IocpProactor +2025-09-28 23:50:01.696 | DEBUG | EAN13Recognizer | 配置加载完成: preprocess={'resize_width': 1280, 'gaussian_blur_ksize': 3, 'morphology_kernel': 17, 'sobel_ksize': 3, 'binarize': 'otsu', 'close_kernel': 21}, roi={'min_area_ratio': 0.01, 'min_wh_ratio': 2.0, 'warp_target_height': 120, 'crop_bottom_ratio': 0.25}, decoder={'sample_rows': [0.35, 0.5, 0.65], 'total_modules': 95, 'guard_tolerance': 0.35, 'peak_valley_rel_threshold': 0.2, 'engine_order': ['pyzbar', 'ean13'], 'try_invert': True, 'rotations': [0, 90, 180, 270]} +2025-09-29 00:03:06.082 | DEBUG | EAN13Recognizer | 配置加载完成: preprocess={'resize_width': 1280, 'gaussian_blur_ksize': 3, 'morphology_kernel': 17, 'sobel_ksize': 3, 'binarize': 'otsu', 'close_kernel': 21}, roi={'min_area_ratio': 0.01, 'min_wh_ratio': 2.0, 'warp_target_height': 120, 'crop_bottom_ratio': 0.25}, decoder={'sample_rows': [0.35, 0.5, 0.65], 'total_modules': 95, 'guard_tolerance': 0.35, 'peak_valley_rel_threshold': 0.2, 'engine_order': ['pyzbar', 'ean13'], 'try_invert': True, 'rotations': [0, 90, 180, 270]} +2025-09-29 00:03:06.095 | INFO | __main__ | 启动 FastAPI 服务器: 127.0.0.1:8000 +2025-09-29 00:03:06.106 | DEBUG | asyncio | Using proactor: IocpProactor +2025-09-29 00:03:06.388 | DEBUG | EAN13Recognizer | 配置加载完成: preprocess={'resize_width': 1280, 'gaussian_blur_ksize': 3, 'morphology_kernel': 17, 'sobel_ksize': 3, 'binarize': 'otsu', 'close_kernel': 21}, roi={'min_area_ratio': 0.01, 'min_wh_ratio': 2.0, 'warp_target_height': 120, 'crop_bottom_ratio': 0.25}, decoder={'sample_rows': [0.35, 0.5, 0.65], 'total_modules': 95, 'guard_tolerance': 0.35, 'peak_valley_rel_threshold': 0.2, 'engine_order': ['pyzbar', 'ean13'], 'try_invert': True, 'rotations': [0, 90, 180, 270]} +2025-09-29 11:43:33.011 | DEBUG | EAN13Recognizer | 配置加载完成: preprocess={'resize_width': 1280, 'gaussian_blur_ksize': 3, 'morphology_kernel': 17, 'sobel_ksize': 3, 'binarize': 'otsu', 'close_kernel': 21}, roi={'min_area_ratio': 0.01, 'min_wh_ratio': 2.0, 'warp_target_height': 120, 'crop_bottom_ratio': 0.25}, decoder={'sample_rows': [0.35, 0.5, 0.65], 'total_modules': 95, 'guard_tolerance': 0.35, 'peak_valley_rel_threshold': 0.2, 'engine_order': ['pyzbar', 'ean13'], 'try_invert': True, 'rotations': [0, 90, 180, 270]} +2025-09-29 11:43:33.016 | INFO | __main__ | 启动 FastAPI 服务器: 127.0.0.1:8000 +2025-09-29 11:43:33.032 | DEBUG | asyncio | Using proactor: IocpProactor +2025-09-29 11:43:33.358 | DEBUG | EAN13Recognizer | 配置加载完成: preprocess={'resize_width': 1280, 'gaussian_blur_ksize': 3, 'morphology_kernel': 17, 'sobel_ksize': 3, 'binarize': 'otsu', 'close_kernel': 21}, roi={'min_area_ratio': 0.01, 'min_wh_ratio': 2.0, 'warp_target_height': 120, 'crop_bottom_ratio': 0.25}, decoder={'sample_rows': [0.35, 0.5, 0.65], 'total_modules': 95, 'guard_tolerance': 0.35, 'peak_valley_rel_threshold': 0.2, 'engine_order': ['pyzbar', 'ean13'], 'try_invert': True, 'rotations': [0, 90, 180, 270]} +2025-09-29 11:59:27.297 | DEBUG | EAN13Recognizer | 配置加载完成: preprocess={'resize_width': 1280, 'gaussian_blur_ksize': 3, 'morphology_kernel': 17, 'sobel_ksize': 3, 'binarize': 'otsu', 'close_kernel': 21}, roi={'min_area_ratio': 0.01, 'min_wh_ratio': 2.0, 'warp_target_height': 120, 'crop_bottom_ratio': 0.25}, decoder={'sample_rows': [0.35, 0.5, 0.65], 'total_modules': 95, 'guard_tolerance': 0.35, 'peak_valley_rel_threshold': 0.2, 'engine_order': ['pyzbar', 'ean13'], 'try_invert': True, 'rotations': [0, 90, 180, 270]} +2025-09-29 11:59:27.298 | INFO | __main__ | 启动 FastAPI 服务器: 127.0.0.1:8000 +2025-09-29 11:59:27.306 | DEBUG | asyncio | Using proactor: IocpProactor +2025-09-29 11:59:27.418 | DEBUG | EAN13Recognizer | 配置加载完成: preprocess={'resize_width': 1280, 'gaussian_blur_ksize': 3, 'morphology_kernel': 17, 'sobel_ksize': 3, 'binarize': 'otsu', 'close_kernel': 21}, roi={'min_area_ratio': 0.01, 'min_wh_ratio': 2.0, 'warp_target_height': 120, 'crop_bottom_ratio': 0.25}, decoder={'sample_rows': [0.35, 0.5, 0.65], 'total_modules': 95, 'guard_tolerance': 0.35, 'peak_valley_rel_threshold': 0.2, 'engine_order': ['pyzbar', 'ean13'], 'try_invert': True, 'rotations': [0, 90, 180, 270]} +2025-09-29 12:21:49.423 | DEBUG | EAN13Recognizer | 配置加载完成: preprocess={'resize_width': 1280, 'gaussian_blur_ksize': 3, 'morphology_kernel': 17, 'sobel_ksize': 3, 'binarize': 'otsu', 'close_kernel': 21}, roi={'min_area_ratio': 0.01, 'min_wh_ratio': 2.0, 'warp_target_height': 120, 'crop_bottom_ratio': 0.25}, decoder={'sample_rows': [0.35, 0.5, 0.65], 'total_modules': 95, 'guard_tolerance': 0.35, 'peak_valley_rel_threshold': 0.2, 'engine_order': ['pyzbar', 'ean13'], 'try_invert': True, 'rotations': [0, 90, 180, 270]} +2025-09-29 12:21:49.425 | INFO | __main__ | 启动 FastAPI 服务器: 127.0.0.1:8000 +2025-09-29 12:21:49.427 | DEBUG | asyncio | Using proactor: IocpProactor +2025-09-29 12:21:49.456 | DEBUG | EAN13Recognizer | 配置加载完成: preprocess={'resize_width': 1280, 'gaussian_blur_ksize': 3, 'morphology_kernel': 17, 'sobel_ksize': 3, 'binarize': 'otsu', 'close_kernel': 21}, roi={'min_area_ratio': 0.01, 'min_wh_ratio': 2.0, 'warp_target_height': 120, 'crop_bottom_ratio': 0.25}, decoder={'sample_rows': [0.35, 0.5, 0.65], 'total_modules': 95, 'guard_tolerance': 0.35, 'peak_valley_rel_threshold': 0.2, 'engine_order': ['pyzbar', 'ean13'], 'try_invert': True, 'rotations': [0, 90, 180, 270]} +2025-09-29 12:24:55.373 | DEBUG | EAN13Recognizer | 配置加载完成: preprocess={'resize_width': 1280, 'gaussian_blur_ksize': 3, 'morphology_kernel': 17, 'sobel_ksize': 3, 'binarize': 'otsu', 'close_kernel': 21}, roi={'min_area_ratio': 0.01, 'min_wh_ratio': 2.0, 'warp_target_height': 120, 'crop_bottom_ratio': 0.25}, decoder={'sample_rows': [0.35, 0.5, 0.65], 'total_modules': 95, 'guard_tolerance': 0.35, 'peak_valley_rel_threshold': 0.2, 'engine_order': ['pyzbar', 'ean13'], 'try_invert': True, 'rotations': [0, 90, 180, 270]} +2025-09-29 12:24:55.375 | INFO | __main__ | 启动 FastAPI 服务器: 127.0.0.1:8000 +2025-09-29 12:24:55.389 | DEBUG | asyncio | Using proactor: IocpProactor +2025-09-29 12:24:55.608 | DEBUG | EAN13Recognizer | 配置加载完成: preprocess={'resize_width': 1280, 'gaussian_blur_ksize': 3, 'morphology_kernel': 17, 'sobel_ksize': 3, 'binarize': 'otsu', 'close_kernel': 21}, roi={'min_area_ratio': 0.01, 'min_wh_ratio': 2.0, 'warp_target_height': 120, 'crop_bottom_ratio': 0.25}, decoder={'sample_rows': [0.35, 0.5, 0.65], 'total_modules': 95, 'guard_tolerance': 0.35, 'peak_valley_rel_threshold': 0.2, 'engine_order': ['pyzbar', 'ean13'], 'try_invert': True, 'rotations': [0, 90, 180, 270]} +2025-09-29 12:54:19.142 | DEBUG | EAN13Recognizer | 配置加载完成: preprocess={'resize_width': 1280, 'gaussian_blur_ksize': 3, 'morphology_kernel': 17, 'sobel_ksize': 3, 'binarize': 'otsu', 'close_kernel': 21}, roi={'min_area_ratio': 0.01, 'min_wh_ratio': 2.0, 'warp_target_height': 120, 'crop_bottom_ratio': 0.25}, decoder={'sample_rows': [0.35, 0.5, 0.65], 'total_modules': 95, 'guard_tolerance': 0.35, 'peak_valley_rel_threshold': 0.2, 'engine_order': ['pyzbar', 'ean13'], 'try_invert': True, 'rotations': [0, 90, 180, 270]} +2025-09-29 12:54:19.144 | INFO | __main__ | 启动 FastAPI 服务器: 127.0.0.1:8000 +2025-09-29 12:54:19.146 | DEBUG | asyncio | Using proactor: IocpProactor +2025-09-29 12:54:19.168 | DEBUG | EAN13Recognizer | 配置加载完成: preprocess={'resize_width': 1280, 'gaussian_blur_ksize': 3, 'morphology_kernel': 17, 'sobel_ksize': 3, 'binarize': 'otsu', 'close_kernel': 21}, roi={'min_area_ratio': 0.01, 'min_wh_ratio': 2.0, 'warp_target_height': 120, 'crop_bottom_ratio': 0.25}, decoder={'sample_rows': [0.35, 0.5, 0.65], 'total_modules': 95, 'guard_tolerance': 0.35, 'peak_valley_rel_threshold': 0.2, 'engine_order': ['pyzbar', 'ean13'], 'try_invert': True, 'rotations': [0, 90, 180, 270]} +2025-09-29 13:00:11.536 | DEBUG | python_multipart.multipart | Calling on_part_begin with no data +2025-09-29 13:00:11.536 | DEBUG | python_multipart.multipart | Calling on_header_field with data[38:57] +2025-09-29 13:00:11.536 | DEBUG | python_multipart.multipart | Calling on_header_value with data[59:125] +2025-09-29 13:00:11.536 | DEBUG | python_multipart.multipart | Calling on_header_end with no data +2025-09-29 13:00:11.536 | DEBUG | python_multipart.multipart | Calling on_header_field with data[127:139] +2025-09-29 13:00:11.538 | DEBUG | python_multipart.multipart | Calling on_header_value with data[141:151] +2025-09-29 13:00:11.538 | DEBUG | python_multipart.multipart | Calling on_header_end with no data +2025-09-29 13:00:11.538 | DEBUG | python_multipart.multipart | Calling on_header_field with data[153:167] +2025-09-29 13:00:11.538 | DEBUG | python_multipart.multipart | Calling on_header_value with data[169:174] +2025-09-29 13:00:11.538 | DEBUG | python_multipart.multipart | Calling on_header_end with no data +2025-09-29 13:00:11.538 | DEBUG | python_multipart.multipart | Calling on_headers_finished with no data +2025-09-29 13:00:11.538 | DEBUG | python_multipart.multipart | Calling on_part_data with data[178:69513] +2025-09-29 13:00:11.539 | DEBUG | python_multipart.multipart | Calling on_part_data with data[0:14631] +2025-09-29 13:00:11.539 | DEBUG | python_multipart.multipart | Calling on_part_end with no data +2025-09-29 13:00:11.539 | DEBUG | python_multipart.multipart | Calling on_end with no data +2025-09-29 13:00:11.550 | DEBUG | app.server.main | /api/barcode/scan 收到图像: shape=(1440, 1080, 3), dtype=uint8 +2025-09-29 13:00:11.559 | DEBUG | pyzbar_engine | 调用 pyzbar: symbols=8, rotations=[0, 90, 180, 270], try_invert=True +2025-09-29 13:00:11.802 | DEBUG | pyzbar_engine | pyzbar 返回结果数: 1 +2025-09-29 13:00:11.803 | DEBUG | EAN13Recognizer | pyzbar 返回 1 条结果 +2025-09-29 13:00:11.803 | DEBUG | EAN13Recognizer | 输入尺寸=(1707, 1280, 3), 预处理后尺寸=(1707, 1280, 3) +2025-09-29 13:00:11.804 | DEBUG | pyzbar_engine | 调用 pyzbar: symbols=8, rotations=[0, 90, 180, 270], try_invert=True +2025-09-29 13:00:12.040 | DEBUG | pyzbar_engine | pyzbar 返回结果数: 1 +2025-09-29 13:00:12.040 | DEBUG | EAN13Recognizer | pyzbar 识别到 1 条结果 +2025-09-29 13:00:12.056 | DEBUG | EAN13Recognizer | ROI bbox=(372, 627, 654, 190) +2025-09-29 13:00:12.060 | DEBUG | EAN13Recognizer | 透视矫正后尺寸=(120, 413) +2025-09-29 13:00:12.098 | DEBUG | EAN13Recognizer | 自研 EAN13 解码失败 +2025-09-29 13:00:12.099 | DEBUG | EAN13Recognizer | recognize_any 未命中 EAN13, others=1 +2025-09-29 13:00:12.100 | INFO | app.server.main | /api/barcode/scan 命中非 EAN: type=CODE128, code=84455470401081732071, cost_ms=561.2 +2025-09-29 13:11:28.027 | DEBUG | EAN13Recognizer | 配置加载完成: preprocess={'resize_width': 1280, 'gaussian_blur_ksize': 3, 'morphology_kernel': 17, 'sobel_ksize': 3, 'binarize': 'otsu', 'close_kernel': 21}, roi={'min_area_ratio': 0.01, 'min_wh_ratio': 2.0, 'warp_target_height': 120, 'crop_bottom_ratio': 0.25}, decoder={'sample_rows': [0.35, 0.5, 0.65], 'total_modules': 95, 'guard_tolerance': 0.35, 'peak_valley_rel_threshold': 0.2, 'engine_order': ['pyzbar', 'ean13'], 'try_invert': True, 'rotations': [0, 90, 180, 270]} +2025-09-29 13:11:28.029 | INFO | __main__ | 启动 FastAPI 服务器: 127.0.0.1:8000 +2025-09-29 13:11:28.030 | DEBUG | asyncio | Using proactor: IocpProactor +2025-09-29 13:11:28.059 | DEBUG | EAN13Recognizer | 配置加载完成: preprocess={'resize_width': 1280, 'gaussian_blur_ksize': 3, 'morphology_kernel': 17, 'sobel_ksize': 3, 'binarize': 'otsu', 'close_kernel': 21}, roi={'min_area_ratio': 0.01, 'min_wh_ratio': 2.0, 'warp_target_height': 120, 'crop_bottom_ratio': 0.25}, decoder={'sample_rows': [0.35, 0.5, 0.65], 'total_modules': 95, 'guard_tolerance': 0.35, 'peak_valley_rel_threshold': 0.2, 'engine_order': ['pyzbar', 'ean13'], 'try_invert': True, 'rotations': [0, 90, 180, 270]} +2025-09-29 19:35:33.086 | DEBUG | EAN13Recognizer | 配置加载完成: preprocess={'resize_width': 1280, 'gaussian_blur_ksize': 3, 'morphology_kernel': 17, 'sobel_ksize': 3, 'binarize': 'otsu', 'close_kernel': 21}, roi={'min_area_ratio': 0.01, 'min_wh_ratio': 2.0, 'warp_target_height': 120, 'crop_bottom_ratio': 0.25}, decoder={'sample_rows': [0.35, 0.5, 0.65], 'total_modules': 95, 'guard_tolerance': 0.35, 'peak_valley_rel_threshold': 0.2, 'engine_order': ['pyzbar', 'ean13'], 'try_invert': True, 'rotations': [0, 90, 180, 270]} +2025-09-29 19:35:33.087 | INFO | __main__ | 启动 FastAPI 服务器: 127.0.0.1:8000 +2025-09-29 19:35:33.105 | DEBUG | asyncio | Using proactor: IocpProactor +2025-09-29 19:35:33.458 | DEBUG | EAN13Recognizer | 配置加载完成: preprocess={'resize_width': 1280, 'gaussian_blur_ksize': 3, 'morphology_kernel': 17, 'sobel_ksize': 3, 'binarize': 'otsu', 'close_kernel': 21}, roi={'min_area_ratio': 0.01, 'min_wh_ratio': 2.0, 'warp_target_height': 120, 'crop_bottom_ratio': 0.25}, decoder={'sample_rows': [0.35, 0.5, 0.65], 'total_modules': 95, 'guard_tolerance': 0.35, 'peak_valley_rel_threshold': 0.2, 'engine_order': ['pyzbar', 'ean13'], 'try_invert': True, 'rotations': [0, 90, 180, 270]} +2025-09-29 21:02:28.561 | DEBUG | EAN13Recognizer | 配置加载完成: preprocess={'resize_width': 1280, 'gaussian_blur_ksize': 3, 'morphology_kernel': 17, 'sobel_ksize': 3, 'binarize': 'otsu', 'close_kernel': 21}, roi={'min_area_ratio': 0.01, 'min_wh_ratio': 2.0, 'warp_target_height': 120, 'crop_bottom_ratio': 0.25}, decoder={'sample_rows': [0.35, 0.5, 0.65], 'total_modules': 95, 'guard_tolerance': 0.35, 'peak_valley_rel_threshold': 0.2, 'engine_order': ['pyzbar', 'ean13'], 'try_invert': True, 'rotations': [0, 90, 180, 270]} +2025-09-29 21:02:28.563 | INFO | __main__ | 启动 FastAPI 服务器: 127.0.0.1:8000 +2025-09-29 21:02:28.579 | DEBUG | asyncio | Using proactor: IocpProactor +2025-09-29 21:02:28.828 | DEBUG | EAN13Recognizer | 配置加载完成: preprocess={'resize_width': 1280, 'gaussian_blur_ksize': 3, 'morphology_kernel': 17, 'sobel_ksize': 3, 'binarize': 'otsu', 'close_kernel': 21}, roi={'min_area_ratio': 0.01, 'min_wh_ratio': 2.0, 'warp_target_height': 120, 'crop_bottom_ratio': 0.25}, decoder={'sample_rows': [0.35, 0.5, 0.65], 'total_modules': 95, 'guard_tolerance': 0.35, 'peak_valley_rel_threshold': 0.2, 'engine_order': ['pyzbar', 'ean13'], 'try_invert': True, 'rotations': [0, 90, 180, 270]} +2025-09-29 21:13:29.629 | DEBUG | EAN13Recognizer | 配置加载完成: preprocess={'resize_width': 1280, 'gaussian_blur_ksize': 3, 'morphology_kernel': 17, 'sobel_ksize': 3, 'binarize': 'otsu', 'close_kernel': 21}, roi={'min_area_ratio': 0.01, 'min_wh_ratio': 2.0, 'warp_target_height': 120, 'crop_bottom_ratio': 0.25}, decoder={'sample_rows': [0.35, 0.5, 0.65], 'total_modules': 95, 'guard_tolerance': 0.35, 'peak_valley_rel_threshold': 0.2, 'engine_order': ['pyzbar', 'ean13'], 'try_invert': True, 'rotations': [0, 90, 180, 270]} +2025-09-29 21:13:29.631 | INFO | __main__ | 启动 FastAPI 服务器: 127.0.0.1:8000 +2025-09-29 21:13:29.632 | DEBUG | asyncio | Using proactor: IocpProactor +2025-09-29 21:13:29.653 | DEBUG | EAN13Recognizer | 配置加载完成: preprocess={'resize_width': 1280, 'gaussian_blur_ksize': 3, 'morphology_kernel': 17, 'sobel_ksize': 3, 'binarize': 'otsu', 'close_kernel': 21}, roi={'min_area_ratio': 0.01, 'min_wh_ratio': 2.0, 'warp_target_height': 120, 'crop_bottom_ratio': 0.25}, decoder={'sample_rows': [0.35, 0.5, 0.65], 'total_modules': 95, 'guard_tolerance': 0.35, 'peak_valley_rel_threshold': 0.2, 'engine_order': ['pyzbar', 'ean13'], 'try_invert': True, 'rotations': [0, 90, 180, 270]} +2025-09-29 21:26:27.378 | DEBUG | EAN13Recognizer | 配置加载完成: preprocess={'resize_width': 1280, 'gaussian_blur_ksize': 3, 'morphology_kernel': 17, 'sobel_ksize': 3, 'binarize': 'otsu', 'close_kernel': 21}, roi={'min_area_ratio': 0.01, 'min_wh_ratio': 2.0, 'warp_target_height': 120, 'crop_bottom_ratio': 0.25}, decoder={'sample_rows': [0.35, 0.5, 0.65], 'total_modules': 95, 'guard_tolerance': 0.35, 'peak_valley_rel_threshold': 0.2, 'engine_order': ['pyzbar', 'ean13'], 'try_invert': True, 'rotations': [0, 90, 180, 270]} +2025-09-29 21:26:27.379 | INFO | __main__ | 启动 FastAPI 服务器: 127.0.0.1:8000 +2025-09-29 21:26:27.382 | DEBUG | asyncio | Using proactor: IocpProactor +2025-09-29 21:26:27.404 | DEBUG | EAN13Recognizer | 配置加载完成: preprocess={'resize_width': 1280, 'gaussian_blur_ksize': 3, 'morphology_kernel': 17, 'sobel_ksize': 3, 'binarize': 'otsu', 'close_kernel': 21}, roi={'min_area_ratio': 0.01, 'min_wh_ratio': 2.0, 'warp_target_height': 120, 'crop_bottom_ratio': 0.25}, decoder={'sample_rows': [0.35, 0.5, 0.65], 'total_modules': 95, 'guard_tolerance': 0.35, 'peak_valley_rel_threshold': 0.2, 'engine_order': ['pyzbar', 'ean13'], 'try_invert': True, 'rotations': [0, 90, 180, 270]} +2025-09-29 21:30:25.753 | DEBUG | EAN13Recognizer | 配置加载完成: preprocess={'resize_width': 1280, 'gaussian_blur_ksize': 3, 'morphology_kernel': 17, 'sobel_ksize': 3, 'binarize': 'otsu', 'close_kernel': 21}, roi={'min_area_ratio': 0.01, 'min_wh_ratio': 2.0, 'warp_target_height': 120, 'crop_bottom_ratio': 0.25}, decoder={'sample_rows': [0.35, 0.5, 0.65], 'total_modules': 95, 'guard_tolerance': 0.35, 'peak_valley_rel_threshold': 0.2, 'engine_order': ['pyzbar', 'ean13'], 'try_invert': True, 'rotations': [0, 90, 180, 270]} +2025-09-29 21:30:25.754 | INFO | __main__ | 启动 FastAPI 服务器: 127.0.0.1:8000 +2025-09-29 21:30:25.756 | DEBUG | asyncio | Using proactor: IocpProactor +2025-09-29 21:30:25.775 | DEBUG | EAN13Recognizer | 配置加载完成: preprocess={'resize_width': 1280, 'gaussian_blur_ksize': 3, 'morphology_kernel': 17, 'sobel_ksize': 3, 'binarize': 'otsu', 'close_kernel': 21}, roi={'min_area_ratio': 0.01, 'min_wh_ratio': 2.0, 'warp_target_height': 120, 'crop_bottom_ratio': 0.25}, decoder={'sample_rows': [0.35, 0.5, 0.65], 'total_modules': 95, 'guard_tolerance': 0.35, 'peak_valley_rel_threshold': 0.2, 'engine_order': ['pyzbar', 'ean13'], 'try_invert': True, 'rotations': [0, 90, 180, 270]} diff --git a/doc/database_documentation.md b/doc/database_documentation.md index cd3a030..65c00e5 100644 --- a/doc/database_documentation.md +++ b/doc/database_documentation.md @@ -267,7 +267,7 @@ | user_id | BIGINT UNSIGNED | NOT NULL | | | | name | VARCHAR(120) | NOT NULL | | 供全文检索 | | category_id | BIGINT UNSIGNED | YES | | | -| unit_id | BIGINT UNSIGNED | NOT NULL | | | +| unit_id | (已移除) | | | | | template_id | BIGINT UNSIGNED | YES | | 关联的模板 | | brand | VARCHAR(64) | YES | | | | model | VARCHAR(64) | YES | | | @@ -291,8 +291,8 @@ - safe_min/safe_max: 安全库存上下限 - search_text: 聚合检索字段(触发器维护) -**Indexes**: - PRIMARY KEY: `id` - KEY: `idx_products_shop` (`shop_id`) - KEY: `idx_products_category` (`category_id`) - KEY: `idx_products_unit` (`unit_id`) - KEY: `idx_products_template` (`template_id`) - KEY: `idx_products_dedupe` (`dedupe_key`) - KEY: `idx_products_shop_blacklist` (`shop_id`,`is_blacklisted`) - FULLTEXT: `ft_products_search` (`name`,`brand`,`model`,`spec`,`search_text`) - UNIQUE: `ux_products_shop_barcode` (`shop_id`,`barcode`) - UNIQUE: `ux_products_template_name_model` (`template_id`,`name`,`model`) -**Foreign Keys**: - `fk_products_shop`: `shop_id` → `shops(id)` - `fk_products_user`: `user_id` → `users(id)` - `fk_products_category`: `category_id` → `product_categories(id)` - `fk_products_unit`: `unit_id` → `product_units(id)` - `fk_products_template`: `template_id` → `part_templates(id)` - `fk_products_globalsku`: `global_skus(id)` +**Indexes**: - PRIMARY KEY: `id` - KEY: `idx_products_shop` (`shop_id`) - KEY: `idx_products_category` (`category_id`) - KEY: `idx_products_template` (`template_id`) - KEY: `idx_products_dedupe` (`dedupe_key`) - KEY: `idx_products_shop_blacklist` (`shop_id`,`is_blacklisted`) - FULLTEXT: `ft_products_search` (`name`,`brand`,`model`,`spec`,`search_text`) - UNIQUE: `ux_products_shop_barcode` (`shop_id`,`barcode`) - UNIQUE: `ux_products_template_name_model` (`template_id`,`name`,`model`) +**Foreign Keys**: - `fk_products_shop`: `shop_id` → `shops(id)` - `fk_products_user`: `user_id` → `users(id)` - `fk_products_category`: `category_id` → `product_categories(id)` - `fk_products_template`: `template_id` → `part_templates(id)` - `fk_products_globalsku`: `global_skus(id)` ### part_submissions(配件提交与审核) | Column Name | Data Type | Nullable | Default | Comment | @@ -377,8 +377,9 @@ | created_by_admin_id | BIGINT UNSIGNED | YES | | 创建管理员 | | created_at | TIMESTAMP | NOT NULL | CURRENT_TIMESTAMP | | | updated_at | TIMESTAMP | NOT NULL | CURRENT_TIMESTAMP | | +| deleted_at | DATETIME | YES | | 软删标记 | -**Indexes**: - PRIMARY KEY: `id` - KEY: `idx_pt_category` (`category_id`) - KEY: `idx_pt_status` (`status`) - KEY: `idx_pt_admin` (`created_by_admin_id`) +**Indexes**: - PRIMARY KEY: `id` - KEY: `idx_pt_category` (`category_id`) - KEY: `idx_pt_status` (`status`) - KEY: `idx_pt_admin` (`created_by_admin_id`) - KEY: `idx_part_templates_deleted_at` (`deleted_at`) **Foreign Keys**: - `fk_pt_category`: `category_id` → `product_categories(id)` - `fk_pt_admin`: `created_by_admin_id` → `admins(id)` ### part_template_params(模板参数字段) diff --git a/doc/openapi.yaml b/doc/openapi.yaml index a4375e9..382325d 100644 --- a/doc/openapi.yaml +++ b/doc/openapi.yaml @@ -728,6 +728,30 @@ paths: responses: '200': { description: 成功 } + /api/normal-admin/application/status: + get: + summary: 普通管理员-本人申请状态查询(✅ Fully Implemented) + description: 返回当前用户最近一次申请状态与是否已具备普通管理员权限。 + parameters: + - in: header + name: X-User-Id + required: true + schema: { type: integer, format: int64 } + description: 当前登录用户ID + responses: + '200': + description: 成功 + content: + application/json: + schema: + type: object + properties: + isNormalAdmin: { type: boolean } + applicationStatus: { type: string, enum: [none, pending, approved, rejected, revoked] } + lastAction: { type: string, nullable: true } + lastActionAt: { type: string, format: date-time, nullable: true } + lastRemark: { type: string, nullable: true } + /api/admin/normal-admin/applications: get: summary: 平台-普通管理员申请列表(❌ Partially Implemented) @@ -1149,12 +1173,18 @@ paths: /api/products: get: summary: 商品搜索(✅ Fully Implemented) - description: 支持 kw/page/size/categoryId;返回 {list:[]} 以兼容前端。 + description: 支持 kw/page/size/categoryId/templateId 以及模板参数过滤。模板参数以 param_ 前缀传入,如 param_颜色=黑、param_内径=10;后端对 JSON attributes 进行 LIKE 匹配(字符串化),多个参数为 AND 关系。返回 {list:[]} 以兼容前端。 parameters: - in: query name: kw schema: type: string + - in: query + name: categoryId + schema: { type: integer, format: int64 } + - in: query + name: templateId + schema: { type: integer, format: int64 } - in: query name: page schema: @@ -1165,6 +1195,11 @@ paths: schema: type: integer default: 50 + - in: query + name: param_* + schema: + type: string + description: 模板参数过滤,星号代表任意模板参数键;示例 param_颜色=黑 responses: '200': description: 成功 @@ -1204,11 +1239,16 @@ paths: /api/products/{id}: get: summary: 商品详情(✅ Fully Implemented) + description: 默认对软删记录返回 404;仅当 includeDeleted=true 时返回已软删详情(仅管理端使用)。 parameters: - in: path name: id required: true schema: { type: integer } + - in: query + name: includeDeleted + required: false + schema: { type: boolean, default: false } responses: '200': description: 成功 @@ -2232,7 +2272,6 @@ paths: spec: { type: string, nullable: true } origin: { type: string, nullable: true } barcode: { type: string, nullable: true } - unitId: { type: integer, format: int64, nullable: true } categoryId: { type: integer, format: int64, nullable: true } parameters: { type: object, additionalProperties: true, nullable: true } images: @@ -2311,7 +2350,6 @@ paths: spec: { type: string, nullable: true } origin: { type: string, nullable: true } barcode: { type: string, nullable: true } - unitId: { type: integer, format: int64, nullable: true } categoryId: { type: integer, format: int64, nullable: true } parameters: { type: object, additionalProperties: true, nullable: true } images: @@ -2401,7 +2439,6 @@ paths: name: { type: string, nullable: true } brand: { type: string, nullable: true } spec: { type: string, nullable: true } - unitId: { type: integer, format: int64, nullable: true } categoryId: { type: integer, format: int64, nullable: true } parameters: { type: object, additionalProperties: true, nullable: true } images: @@ -2482,7 +2519,7 @@ paths: /api/admin/part-templates: get: - summary: 管理端-模板列表(❌ Partially Implemented) + summary: 管理端-模板列表(✅ Fully Implemented) responses: { '200': { description: 成功 } } post: summary: 管理端-创建模板(❌ Partially Implemented) @@ -2514,11 +2551,27 @@ paths: responses: { '200': { description: 成功 } } /api/admin/part-templates/{id}: get: - summary: 管理端-模板详情(❌ Partially Implemented) + summary: 管理端-模板详情(✅ Fully Implemented) parameters: [ { in: path, name: id, required: true, schema: { type: integer, format: int64 } } ] responses: { '200': { description: 成功 } } put: summary: 管理端-更新模板(❌ Partially Implemented) + delete: + summary: 管理端-删除模板(软删除,✅ Fully Implemented) + description: |- + 默认行为:软删除(隐藏)——仅将 `part_templates.status` 置为 0,前台列表默认不再显示。 + 强制模式:`force=true` 时,执行永久删除:删除参数定义并清理关联商品(软删)与提交(软删),最后删除模板记录。 + parameters: + - in: path + name: id + required: true + schema: { type: integer, format: int64 } + - in: query + name: force + required: false + schema: { type: boolean } + responses: + '200': { description: 成功 } parameters: [ { in: path, name: id, required: true, schema: { type: integer, format: int64 } } ] requestBody: required: true diff --git a/doc/模板参数可模糊查询_功能需求文档.md b/doc/模板参数可模糊查询_功能需求文档.md new file mode 100644 index 0000000..a587db0 --- /dev/null +++ b/doc/模板参数可模糊查询_功能需求文档.md @@ -0,0 +1,127 @@ +## 模板参数可模糊查询(±容差)功能需求文档 + +### 1. 背景与目标 +当前用户端「按模板参数查询」要求参数值与数据库完全相同才能命中,实际使用中数值类参数(如内径、外径、长度等)存在测量/录入微小误差,严格等值导致命中率偏低。新增能力:在管理端创建模板时,为每个参数提供「可模糊查询」选项;开启后,用户搜索该参数时按数值区间匹配(±容差);未开启的参数继续精确等值。 + +### 2. 业务范围 +- 场景:用户端/管理端的商品列表查询(含「按模板参数查询」模式)。 +- 对象:模板参数定义(仅限数值型参数生效)。 +- 不影响:名称/品牌/型号/规格关键字搜索逻辑;非数值类型参数的等值匹配逻辑。 + +### 3. 术语与约束 +- 模板参数类型:string/number/boolean/enum/date。 +- 模糊查询仅对 type=number 生效;其他类型不展示该选项或忽略配置。 +- 容差(tolerance):对搜索入参 v,匹配区间为 \[v - tolerance, v + tolerance](闭区间)。默认容差为 1(见配置项),可在参数层级单独覆盖。 +- 组合关系:多参数为 AND 关系;每个参数根据其「可模糊查询」与容差独立计算。 + +### 4. 交互与流程 +- 管理端-模板配置: + - 新建/编辑模板参数时,新增选项: + - 可模糊查询(开关,仅当类型为 number 显示) + - 容差值(number,>0,显示单位提示,同 `unit` 字段;当开关开启时必填,否则置空) + - 校验: + - type≠number 时禁止开启; + - 容差必须为正数,支持小数; + - 可保存为“使用平台默认容差”,当字段留空时后端落默认(见配置)。 +- 用户端/管理端-按模板参数查询: + - 入参与现状一致:仍以 `templateId` + 多个 `param_*` 传参; + - 行为变化: + - 对应参数若开启可模糊查询:按区间 \[v - tol, v + tol] 比较; + - 否则:仍为精确等值比较。 + +### 5. 数据模型变更(待实施) +- 表:`part_template_params` + - 新增列: + - `fuzzy_searchable` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否允许模糊查询(仅数值型)' + - `fuzzy_tolerance` DECIMAL(18,6) NULL COMMENT '容差;NULL 表示使用平台默认容差' + - 说明: + - 仅当 `type='number' AND fuzzy_searchable=1` 时才使用容差; + - 初始迁移将全部历史记录置为 `fuzzy_searchable=0, fuzzy_tolerance=NULL`,保持现有行为不变。 + +### 6. 配置项(后端) +- `search.fuzzy.enabled`(bool,默认 true):是否启用模糊查询全局开关; +- `search.fuzzy.defaultTolerance`(decimal,默认 1.0):当参数未设置 `fuzzy_tolerance` 时使用; +- 读取途径:Spring 配置(application.properties/yaml)或环境变量。禁止在代码中硬编码数字 1。 +- 仅全局配置,不支持租户级(`system_parameters`)覆盖;无需设置小数精度上限/最大容差限制。 + +### 7. 接口协议与兼容性 +- 查询接口:`GET /api/products`(已存在) + - 入参保持不变:`templateId`、`param_*`。 + - 语义扩展(无须 `templateId` 也启用模糊):后端将基于商品行的 `template_id` 与参数定义逐行判定某个 `param_*` 是否启用 ±容差;若该参数在对应模板中未开启模糊或非数值型,则对该条件执行等值匹配。 +- 模板接口:`POST /api/admin/part-templates`、`PUT /api/admin/part-templates/{id}`(已存在) + - 参数定义对象新增字段: + - `fuzzySearchable`(boolean) + - `fuzzyTolerance`(number,nullable) + - 若前端暂未改造,后端默认按 `fuzzySearchable=false` 处理,兼容旧请求体。 + +(根据「接口规范生效条件」,待功能开发完成后更新 `doc/openapi.yaml` 中对应 schema 与描述,并在 summary/description 标注实现状态) + +### 8. 后端实现要点(建议方案) +当前实现(精确匹配),示意: +```sql +-- 现状(等值): +AND JSON_UNQUOTE(JSON_EXTRACT(p.attributes_json, '$.内径')) = '10' +``` + +推荐实现: +- 行级判定方案(支持无 `templateId` 也启用模糊): + - 对每个传入的 `param_=v`: + - 以 `EXISTS` 子查询或 `JOIN part_template_params ptp ON ptp.template_id=p.template_id AND ptp.field_key=''` 获取参数定义; + - 若 `ptp.type='number' AND ptp.fuzzy_searchable=1`:对 `v` 解析为数值,计算 `tol = COALESCE(ptp.fuzzy_tolerance, :defaultTolerance)`; + - 下限截断:`lower = GREATEST(0, v - tol)`; + - 条件: + ```sql + CAST(JSON_UNQUOTE(JSON_EXTRACT(p.attributes_json, '$.')) AS DECIMAL(18,6)) BETWEEN :lower AND :upper + ``` + - 否则:执行等值匹配: + ```sql + JSON_UNQUOTE(JSON_EXTRACT(p.attributes_json, '$.')) = :val + ``` +- 快路径(可选):当请求携带 `templateId` 时,可先一次性加载该模板参数定义映射到内存,按映射决定每个条件构造,以减少 `JOIN/EXISTS` 次数。 +- 容差取值:优先 `ptp.fuzzy_tolerance`,否则全局 `search.fuzzy.defaultTolerance`。 + +性能建议: +- 初期:允许全表扫描 + JSON_EXTRACT;观察真实 QPS 与延迟; +- 进阶(可选):对热点参数引入“生成列 + 索引”(Generated Column),例如: + - 在 `products` 增加 `attr_ DECIMAL(18,6) GENERATED ALWAYS AS (CAST(JSON_UNQUOTE(JSON_EXTRACT(attributes_json, '$.')) AS DECIMAL(18,6))) STORED` 并建索引,以支持范围查询; + - 仅对访问量高的少数参数启用,避免列爆炸。 + +### 9. 管理端实现要点(UI/校验) +- `admin/src/views/parts/Templates.vue`: + - 参数编辑行新增: + - 开关:可模糊查询(仅 type=number 显示) + - 数值输入:容差(显示单位,>0,支持小数;留空表示使用平台默认) + - 保存/加载兼容:与后端新增字段映射,历史数据默认显示为关闭态。 + - 校验:当参数开启模糊时,对应值在 UI 侧仅允许数字输入;单位提示与 `unit` 一致。 + +### 10. 验收标准(Test Cases) +- 单参数-模糊:模板字段 `内径`(number,fuzzy=true,tolerance=1);商品 A/B/C 分别取值 9/10/11;搜索 `param_内径=10` 命中 A/B/C。 +- 单参数-精确:同上但 fuzzy=false;搜索 `param_内径=10` 仅命中 B。 +- 多参数组合:`内径`(fuzzy=true, tol=0.5)、`长度`(fuzzy=false);搜索 `param_内径=10`、`param_长度=20` 仅命中满足区间与等值的交集。 +- 无 templateId:也启用模糊;后端逐行按 `p.template_id` 与参数定义判定是否应用容差。 +- 容差来源:当 `fuzzy_tolerance=NULL` 时,生效平台默认容差;覆盖值生效优先级高于默认。 +- 非数值参数:即使请求携带 `param_颜色=黑`,也严格等值。 + - 下限截断:当 `v - tol < 0` 时,以 `0` 作为下限;不支持负数参数匹配。 + - 非法输入:当参数在模板中开启模糊但请求值非数字时,返回 400(Bad Request)。 + +### 11. 兼容与回退 +- 不改动现有请求入参与返回体,历史客户端无需升级亦可按原精确逻辑使用; +- 新能力由模板参数配置显式开启,可随时在模板中关闭; +- 如需全局关闭,可通过 `search.fuzzy.enabled=false` 临时禁用(后端配置)。 + +### 12. 风险与注意事项 +- 数据质量:历史 `attributes_json` 中数值可能以字符串存储;需统一以 `CAST(JSON_UNQUOTE(...))` 解析。 +- 单位与容差:UI 需提示单位;容差与单位一一对应,避免“毫米 vs 厘米”误解。 +- 性能:范围查询较等值更难走索引;必要时引入“生成列+索引”优化热点字段。 + - 负数与边界:不支持负数参数;区间采用闭区间,且下限截断为 `0`。 + +### 13. 实施清单(参考) +1) 数据库:为 `part_template_params` 增列 `fuzzy_searchable`、`fuzzy_tolerance`;(变更需通过 MysqlMCP,成功后同步更新 `doc/database_documentation.md` 与 `backend/db/db.sql`) +2) 配置:新增 `search.fuzzy.*` 配置项并给出默认值(全局生效,无租户级覆盖); +3) 管理端:模板参数编辑 UI 新增开关与容差输入; +4) 后端:按 8 节改造查询 SQL 构建逻辑(无 `templateId` 也启用模糊,行级按模板判定); +5) 文档:在功能开发完成后更新 `doc/openapi.yaml` 中模板参数 schema 与 `GET /api/products` 的查询规则说明,并标注实现状态; +6) 发布:前后端同步上线;无需灰度与回滚开关; +7) 验收:按 10 节用例覆盖单测/集成测试与手工回归。 + + diff --git a/doc/货品删除功能开发文档.md b/doc/货品删除功能开发文档.md new file mode 100644 index 0000000..1f03324 --- /dev/null +++ b/doc/货品删除功能开发文档.md @@ -0,0 +1,175 @@ +## 货品删除功能开发文档(软删方案) + +### 1. 背景与目标 +- 将“与货品相关”的删除行为统一为软删除,避免历史引用断裂,支持后续恢复与审计。 +- 用户仅保留“拉黑/恢复”,订单维持“作废 void”,不做删除。 + +### 2. 范围 +- 货品主表:`products` +- 关联信息:`product_images`、`product_prices`、`inventories`、`product_aliases` +- 相关查询接口:商品搜索、详情、导出(如有) + +### 2.1 父子级联关系(必须遵守) +- 分类(`product_categories`) → 模板(`part_templates`) → 商品(`products`) +- 规则: + - 删除分类 ⇒ 级联软删该分类下所有模板;再级联软删由这些模板创建的所有商品;并同时软删所有 `category_id=该分类` 的商品(包括未通过模板创建的商品)。 + - 删除模板 ⇒ 仅软删该模板下的商品,不影响同分类其它模板的商品。 + - 订单不可删除,仅允许作废(void),因此采用“软删”是必要前提,避免历史订单断裂。 + - 恢复:当前不提供任何恢复入口;如未来开放,恢复不做级联,需逐层独立恢复以避免误恢复。 + +### 3. 设计要点 +- 软删标记:使用 `products.deleted_at DATETIME NULL`(已存在)。被软删即视为“不对外可见”。 +- 恢复:当前不提供恢复入口。若未来开放,语义为将 `deleted_at=NULL`。 +- 查询默认过滤:所有列表/搜索默认附加 `deleted_at IS NULL`(当前搜索已实现)。 +- 详情访问:若记录被软删,返回 404(或通过 `includeDeleted=true` 显式读取)。 +- 关联表处理:软删商品时不物理删除图片/价格/库存/别名(均按商品引用读取,详情被 404 屏蔽即可)。 + +- 模板软删标记统一:为 `part_templates` 引入 `deleted_at DATETIME NULL` 以统一软删标记;`status` 字段保留为启停用,不代表软删。所有查询需同时过滤 `deleted_at IS NULL AND status=1`(按需)。 + +- 字典与作用域:分类与单位属于 `shop_id=0` 的全局字典。删除分类会影响所有店铺下此分类的模板与商品;此操作需平台管理员权限并要求二次确认。 + +- 报表与搜索:默认排除软删记录;不提供“含回收站”开关。 + +- 数据保留与清理:支持配置项 `SOFT_DELETE_RETENTION_DAYS`(默认永久保留,仅清理无引用对象)。 + +- 单位删除校验:移除对已废弃 `products.unit_id` 的校验逻辑。 + +### 4. 数据库与索引 +现状:`products` 存在唯一约束 `UNIQUE(shop_id, barcode)`。软删后可能需要“同店铺、同条码”重新建商品。 + +- 目标:唯一约束仅作用于“活动记录”(未软删)。 +- 做法:增加生成列 `is_active` 并重建唯一索引(MySQL 8)。 + +DDL(上线脚本草案) +```sql +-- 仅对生产环境执行一次;如已存在请跳过对应步骤 +ALTER TABLE products + ADD COLUMN is_active TINYINT AS (CASE WHEN deleted_at IS NULL THEN 1 ELSE 0 END) STORED, + ADD INDEX idx_products_deleted_at (deleted_at); + +-- 重建唯一索引,使其仅约束未软删记录 +DROP INDEX ux_products_shop_barcode ON products; -- 若不存在请忽略 +CREATE UNIQUE INDEX ux_products_shop_barcode_live ON products(shop_id, barcode, is_active); +``` + +风险与说明 +- “条码为空”不会受唯一约束影响(MySQL 对 NULL 不唯一);符合预期。 +- 老数据不受影响;后续删除改为软删即可。 +- 若未来需要“永久删除”,可新增仅限平台运维的强删脚本,先清理关联,再物理删除目标商品。 +- 如未来开放“恢复”,当恢复商品与现存“活动记录”在 `(shop_id, barcode)` 上冲突时,恢复应返回 `409 Conflict` 并附带冲突商品信息。 + +模板表 DDL(新增软删标记) +```sql +ALTER TABLE part_templates + ADD COLUMN deleted_at DATETIME NULL, + ADD INDEX idx_part_templates_deleted_at (deleted_at); +``` + +### 5. 接口设计(OpenAPI 约定) +说明:按规范,等后端开始开发即补充到 `/doc/openapi.yaml` 并标注实现状态;本方案不新增任何“恢复”接口。 + +1) 软删商品(行为不变,明确语义) +- Method/Path: `DELETE /api/products/{id}` +- 语义:软删,将 `deleted_at=NOW()`。 +- 返回:`200 {}` +- 鉴权:需要 `X-Shop-Id`/`X-User-Id` 或 Token,且仅允许同店铺数据。 + +2) 商品详情(行为调整) +- Method/Path: `GET /api/products/{id}` +- 默认:若 `deleted_at IS NOT NULL` 返回 `404`。 +- 可选:`includeDeleted=true` 时允许读取已软删详情(仅管理端使用)。 + +3) 恢复接口 +- 不同意新增以下恢复接口:`PUT /api/admin/dicts/categories/{id}/restore`、`PUT /api/admin/part-templates/{id}/restore`、`PUT /api/products/{id}/restore`。 + +### 6. 后端实现说明 +- Controller 改动(示意) + - `ProductController.delete(id, shopId)`:保持现有调用,内部执行软删。 + - `GET /api/products/{id}`:调用 `productService.findDetail(id)` 前,先判断 `deleted_at`,若非空且未显式 `includeDeleted` → `404`。 + +- Service 改动(核心) + - 移除/不提供任何恢复相关方法。 + - `findDetail(id)`:若被软删且无 `includeDeleted` 参数 → 返回空 Optional。 + - 模板表采用 `deleted_at` 表示软删,`status` 表示启停用;查询需同时过滤 `deleted_at IS NULL` 与必要的 `status` 条件。 + +#### 6.1 级联软删伪代码 +```java +// 分类软删 +void deleteCategorySoft(Long categoryId) { + // 1) 标记分类 deleted_at + UPDATE product_categories SET deleted_at=NOW() WHERE id=? AND deleted_at IS NULL; + // 2) 级联模板软删(统一使用 deleted_at) + UPDATE part_templates SET deleted_at=NOW() WHERE category_id=? AND deleted_at IS NULL; + // 3) 级联商品软删:模板创建的商品 + 直接挂在分类下的商品 + UPDATE products SET deleted_at=NOW() WHERE ( + template_id IN (SELECT id FROM part_templates WHERE category_id=?) + OR category_id=? + ) AND deleted_at IS NULL; +} + +// 模板软删(不波及其它模板) +void deleteTemplateSoft(Long templateId) { + // 1) 模板标记为软删 + UPDATE part_templates SET deleted_at=NOW() WHERE id=? AND deleted_at IS NULL; + // 2) 级联商品软删(仅该模板下) + UPDATE products SET deleted_at=NOW() WHERE template_id=? AND deleted_at IS NULL; +} +``` + +### 7. 前端改动 +- 列表页:保持不显示软删项(现已过滤)。 +- 详情页:若接口返回 404,提示“已被删除或无权限”。 +- 管理端:不提供“回收站/恢复”入口;删除按钮提示:该操作为软删除,对前台不可见,当前无恢复入口。 + +### 8. 权限与审计 +- 鉴权:沿用现有用户/店铺头部识别;仅同店铺商品可操作。 +- 权限边界: + - 普通用户:仅可删除本用户的货品;无权删除模板与分类;无恢复权限。 + - 店铺管理员:仅有审核功能;无删除模板/分类与恢复权限。 + - 平台管理员:可删除货品、模板、分类;删除全局分类需二次确认;无恢复权限。 +- 审计:不记录操作日志(操作者、时间、来源 IP、对象 ID 与名称),以简化开发。 + +### 9. 测试用例 +- 删除后搜索不可见;`GET /api/products/{id}` 返回 404。 +- 条码唯一:软删后允许同店铺同条码新建。 +- (如未来开放恢复)恢复时如与现有活动记录冲突,返回 409 并附带冲突商品信息。 + +### 10. 发布与回滚 +- 发布顺序: + 1) 执行数据库 DDL(生成列与索引)。 + 2) 上线后端(调整 detail 行为,移除/不提供恢复逻辑)。 + 3) 上线前端(不提供回收站/恢复入口)。 +- 回滚: + - 后端回滚到旧版本;DDL 不需要回退(生成列与新索引向前兼容)。 + +### 11. FAQ / 风险 +- 问:软删后图片与价格是否清理? + - 答:不清理,保持数据可恢复;若永久删除再统一清理关联。 +- 问:库存与统计是否包含软删商品? + - 答:常规统计应排除软删;如需包含,增加显式参数。 +- 问:条码冲突如何处理? + - 答:按“活动记录”唯一;如未来开放恢复,发现冲突则返回 409,并指明冲突商品。 +- 问:字典(分类/单位)是否为全局维度?删除是否影响所有店铺? + - 答:是,`shop_id=0` 全局字典;删除全局分类会影响所有店铺下该分类的模板与商品,需平台管理员二次确认。 +- 问:是否保留“强删”入口? + - 答:保留仅限平台运维的强删入口(默认关闭)。分类/模板强删前需校验无订单关联商品后再执行。 +- 问:为何不做物理删除? + - 答:订单/流水等历史记录必须可追溯;物理删除会破坏外键与统计。软删能满足“前台不可见、后台可恢复”的业务诉求。 + + +### 12. 任务拆解(实施) +- 后端: + - [ ] `GET /api/products/{id}` 软删返回 404 / 支持 `includeDeleted` + - [ ] 分类删除级联扩展:同时软删 `category_id=该分类` 的商品(含未走模板创建) + - [ ] 模板表引入 `deleted_at`;查询同时过滤 `deleted_at IS NULL` 与必要的 `status` + - [ ] 移除“单位删除校验检查 products.unit_id”的逻辑 +- 数据库: + - [ ] 为 `products` 增加 `is_active` 与唯一索引(见 DDL) + - [ ] 为 `part_templates` 增加 `deleted_at` 与索引 +- 前端管理端: + - [ ] 删除按钮文案更新(软删除,对前台不可见,当前无恢复入口) + - [ ] 不提供“回收站/恢复”入口 + +(本文件为技术方案与实施指引,变更上线后请同步 `/doc/openapi.yaml` 与 `/doc/database_documentation.md`) + + diff --git a/frontend/.env.local b/frontend/.env.local new file mode 100644 index 0000000..99d2361 --- /dev/null +++ b/frontend/.env.local @@ -0,0 +1 @@ +VITE_APP_API_BASE_URL=http://192.168.31.192:8080 diff --git a/frontend/common/config.js b/frontend/common/config.js index 15f91cb..999c3fa 100644 --- a/frontend/common/config.js +++ b/frontend/common/config.js @@ -49,3 +49,8 @@ export const KPI_ICONS = { stockCount: '/static/icons/product.png' } +// 登录页顶部图片,避免在页面硬编码,允许通过环境变量或本地存储覆盖 +const envAuthLoginImg = (typeof process !== 'undefined' && process.env && (process.env.VITE_APP_AUTH_LOGIN_TOP_IMAGE || process.env.AUTH_LOGIN_TOP_IMAGE)) || ''; +const storageAuthLoginImg = typeof uni !== 'undefined' ? (uni.getStorageSync('AUTH_LOGIN_TOP_IMAGE') || '') : ''; +export const AUTH_LOGIN_TOP_IMAGE = String(envAuthLoginImg || storageAuthLoginImg || '/static/icons/undraw_visual-data_1eya.png'); + diff --git a/frontend/common/constants.js b/frontend/common/constants.js index 99b1b1a..0c96323 100644 --- a/frontend/common/constants.js +++ b/frontend/common/constants.js @@ -42,3 +42,11 @@ export const STORAGE_KEYS = { } +// KPI 标签常量,避免页面硬编码 +export const KPI_LABELS = { + todaySales: '今日销售额', + monthSales: '本月销售额', + monthProfit: '本月利润', + stockCount: '库存量' +} + diff --git a/frontend/pages.json b/frontend/pages.json index bc39330..aa5a551 100644 --- a/frontend/pages.json +++ b/frontend/pages.json @@ -38,11 +38,23 @@ } }, { - "path": "pages/product/form", + "path": "pages/product/submission-detail", "style": { - "navigationBarTitleText": "编辑货品" + "navigationBarTitleText": "提交详情" } }, + { + "path": "pages/product/form", + "style": { + "navigationBarTitleText": "编辑货品" + } + }, + { + "path": "pages/product/product-detail", + "style": { + "navigationBarTitleText": "货品详情" + } + }, { "path": "pages/product/categories", "style": { diff --git a/frontend/pages/auth/login.vue b/frontend/pages/auth/login.vue index dbef1ca..06908b7 100644 --- a/frontend/pages/auth/login.vue +++ b/frontend/pages/auth/login.vue @@ -1,18 +1,21 @@ diff --git a/frontend/pages/index/index.vue b/frontend/pages/index/index.vue index 04ea5b3..95ce2b6 100644 --- a/frontend/pages/index/index.vue +++ b/frontend/pages/index/index.vue @@ -12,28 +12,28 @@ - 今日销售额 + {{ KPI_LABELS.todaySales }} {{ kpi.todaySales }} - 本月销售额 + {{ KPI_LABELS.monthSales }} {{ kpi.monthSales }} - 本月利润 + {{ KPI_LABELS.monthProfit }} {{ kpi.monthProfit }} - 库存商品数量 + {{ KPI_LABELS.stockCount }} {{ kpi.stockCount }} @@ -93,12 +93,13 @@ @@ -186,6 +259,9 @@ page { border-color: #4c8dff; } +/* 指定 hero 内激活态徽标文本为黑色 */ +.vip-hero .status-pill.active text { color: #000 !important; } + .vip-summary { display: grid; grid-template-columns: repeat(2, minmax(0,1fr)); @@ -337,6 +413,45 @@ page { opacity: 0.88; } +.apply-card { + margin-top: 0; + background: linear-gradient(135deg, rgba(30,173,145,0.14) 0%, rgba(30,173,145,0.06) 100%); + border-radius: 28rpx; + padding: 30rpx 28rpx; + display: flex; + align-items: center; + gap: 24rpx; + border: 2rpx solid rgba(30,173,145,0.18); + box-shadow: 0 10rpx 24rpx rgba(30,173,145,0.15); +} + +.apply-text { flex: 1; display:flex; flex-direction: column; gap: 10rpx; } +.apply-title { font-size: 32rpx; font-weight: 800; color: #1ead91; } +.apply-desc { font-size: 24rpx; color: #247a66; line-height: 34rpx; } +.apply-btn { + flex: 0 0 auto; + padding: 20rpx 36rpx; + border-radius: 999rpx; + border: none; + background-color: transparent; + background: linear-gradient(135deg, #1ead91 0%, #159b7e 100%); + color: #fff; + font-size: 28rpx; + font-weight: 700; + box-shadow: 0 10rpx 22rpx rgba(21,155,126,0.20); +} + +.apply-btn::after { border: none; } +.apply-btn:active { opacity: .9; } + +.apply-btn.disabled { + opacity: .5; + background: #c7e8df; + color: #fff; + box-shadow: none; + pointer-events: none; +} + @media (max-width: 375px) { .vip-summary { grid-template-columns: 1fr; diff --git a/frontend/pages/product/form.vue b/frontend/pages/product/form.vue index 65d8c64..b1a62b8 100644 --- a/frontend/pages/product/form.vue +++ b/frontend/pages/product/form.vue @@ -31,41 +31,18 @@ + + - - - - - 主单位:{{ unitLabel }} - 类别:{{ categoryLabel }} - - - 库存与安全库存 - - - - - - - + - - - 价格(进价/零售/批发/大单) - - - - - - - - + 图片 @@ -94,14 +71,11 @@ export default { return { id: '', form: { - name: '', barcode: '', brand: '', model: '', spec: '', origin: '', - categoryId: '', unitId: '', - stock: null, safeMin: null, safeMax: null, - purchasePrice: null, retailPrice: null, wholesalePrice: null, bigClientPrice: null, + name: '', barcode: '', brand: '', model: '', spec: '', + categoryId: '', images: [], remark: '', platformStatus: '', sourceSubmissionId: '' }, - units: [], categories: [], keyboardHeight: 0 } @@ -115,12 +89,7 @@ export default { this.disposeKeyboardListener() }, computed: { - unitNames() { return this.units.map(u => u.name) }, categoryNames() { return this.categories.map(c => c.name) }, - unitLabel() { - const u = this.units.find(x => String(x.id) === String(this.form.unitId)) - return u ? u.name : '选择单位' - }, categoryLabel() { const c = this.categories.find(x => String(x.id) === String(this.form.categoryId)) return c ? c.name : '选择类别' @@ -128,7 +97,7 @@ export default { }, methods: { async bootstrap() { - await Promise.all([this.fetchUnits(), this.fetchCategories()]) + await Promise.all([this.fetchCategories()]) if (this.id) this.loadDetail() }, initKeyboardListener() { @@ -147,22 +116,12 @@ export default { } } catch (_) {} }, - async fetchUnits() { - try { - const res = await get('/api/product-units') - this.units = Array.isArray(res?.list) ? res.list : (Array.isArray(res) ? res : []) - } catch (_) {} - }, async fetchCategories() { try { const res = await get('/api/product-categories') this.categories = Array.isArray(res?.list) ? res.list : (Array.isArray(res) ? res : []) } catch (_) {} }, - onPickUnit(e) { - const idx = Number(e.detail.value); const u = this.units[idx] - this.form.unitId = u ? u.id : '' - }, onPickCategory(e) { const idx = Number(e.detail.value); const c = this.categories[idx] this.form.categoryId = c ? c.id : '' @@ -193,12 +152,8 @@ export default { const data = await get('/api/products/' + this.id) Object.assign(this.form, { name: data.name, - barcode: data.barcode, brand: data.brand, model: data.model, spec: data.spec, origin: data.origin, - categoryId: data.categoryId, unitId: data.unitId, - stock: data.stock, - safeMin: data.safeMin, safeMax: data.safeMax, - purchasePrice: data.purchasePrice, retailPrice: data.retailPrice, - wholesalePrice: data.wholesalePrice, bigClientPrice: data.bigClientPrice, + barcode: data.barcode, brand: data.brand, model: data.model, spec: data.spec, + categoryId: data.categoryId, images: (data.images || []).map(i => i.url || i), remark: data.remark || '', platformStatus: data.platformStatus || '', @@ -208,21 +163,13 @@ export default { }, validate() { if (!this.form.name) { uni.showToast({ title: '请填写名称', icon: 'none' }); return false } - if (this.form.safeMin != null && this.form.safeMax != null && Number(this.form.safeMin) > Number(this.form.safeMax)) { - uni.showToast({ title: '安全库存区间不合法', icon: 'none' }); return false - } return true }, buildPayload() { const f = this.form return { - name: f.name, barcode: f.barcode, brand: f.brand, model: f.model, spec: f.spec, origin: f.origin, - categoryId: f.categoryId || null, unitId: f.unitId, - safeMin: f.safeMin, safeMax: f.safeMax, - prices: { - purchasePrice: f.purchasePrice, retailPrice: f.retailPrice, wholesalePrice: f.wholesalePrice, bigClientPrice: f.bigClientPrice - }, - stock: f.stock, + name: f.name, barcode: f.barcode, brand: f.brand, model: f.model, spec: f.spec, + categoryId: f.categoryId || null, images: f.images, remark: f.remark } @@ -236,7 +183,7 @@ export default { else await post('/api/products', payload) uni.showToast({ title: '保存成功', icon: 'success', mask: false }) if (goOn && !this.id) { - this.form = { name: '', barcode: '', brand: '', model: '', spec: '', origin: '', categoryId: '', unitId: '', stock: null, safeMin: null, safeMax: null, purchasePrice: null, retailPrice: null, wholesalePrice: null, bigClientPrice: null, images: [], remark: '', platformStatus: '', sourceSubmissionId: '' } + this.form = { name: '', barcode: '', brand: '', model: '', spec: '', categoryId: '', images: [], remark: '', platformStatus: '', sourceSubmissionId: '' } } else { setTimeout(() => uni.navigateBack(), 400) } diff --git a/frontend/pages/product/list.vue b/frontend/pages/product/list.vue index f4c8018..490c5b7 100644 --- a/frontend/pages/product/list.vue +++ b/frontend/pages/product/list.vue @@ -2,32 +2,59 @@ 全部 - 按类别 + 查询 我的提交 - - - - {{ categoryLabel }} - + + + + {{ modeLabel }} + + + + + + + + + {{ categoryLabel }} + + + {{ templateLabel }} + + + + + + + + + {{ displayParamEnum(p) }} + + + {{ paramValues[p.fieldKey] || ('选择' + p.fieldLabel) }} + + + + + - + - - {{ it.name }} + + {{ it.name }} + 已删除 平台推荐 我的提交 {{ it.brand || '-' }} {{ it.model || '' }} {{ it.spec || '' }} - 库存:{{ it.stock ?? 0 }} - 零售价:¥{{ (it.retailPrice ?? it.price ?? 0).toFixed(2) }} - + @@ -47,11 +74,13 @@ export default { data() { return { items: [], - query: { kw: '', page: 1, size: 20, categoryId: '' }, + query: { kw: '', page: 1, size: 20, categoryId: '', mode: 'direct', templateId: '', params: {} }, finished: false, loading: false, tab: 'all', - categories: [] + categories: [], + templates: [], + paramValues: {} } }, onLoad() { @@ -76,26 +105,59 @@ export default { categoryLabel() { const c = this.categories.find(x => String(x.id) === String(this.query.categoryId)) return c ? '类别:' + c.name : '选择类别' - } + }, + modeLabel() { + const map = { direct: '直接查询', nameLike: '名称模糊查询', template: '按模板参数查询' } + return map[this.query.mode] || '直接查询' + }, + templateNames() { return this.templates.map(t => t.name) }, + templateLabel() { + const t = this.templates.find(x => String(x.id) === String(this.query.templateId)) + return t ? '模板:' + t.name : '选择模板' + }, + selectedTemplate() { return this.templates.find(t => String(t.id) === String(this.query.templateId)) || null }, + selectedTemplateParams() { return (this.selectedTemplate && Array.isArray(this.selectedTemplate.params)) ? this.selectedTemplate.params : [] } }, methods: { switchTab(t) { this.tab = t this.query.categoryId = '' + this.query.templateId = '' + this.paramValues = {} this.reload() }, onPickCategory(e) { const idx = Number(e.detail.value) const c = this.categories[idx] this.query.categoryId = c ? c.id : '' - this.reload() + this.fetchTemplates() }, + onPickTemplate(e) { + const idx = Number(e.detail.value) + const t = this.templates[idx] + this.query.templateId = t ? t.id : '' + this.paramValues = {} + }, + onPickParamEnumWrapper(p, e) { + const idx = Number(e.detail.value) + const arr = p.enumOptions || [] + this.paramValues[p.fieldKey] = arr[idx] + }, + onParamBoolChange(p, e) { this.paramValues[p.fieldKey] = e?.detail?.value ? true : false }, + onParamDateChange(p, e) { this.paramValues[p.fieldKey] = e?.detail?.value || '' }, async fetchCategories() { try { const res = await get('/api/product-categories', {}) this.categories = Array.isArray(res?.list) ? res.list : (Array.isArray(res) ? res : []) } catch (_) {} }, + async fetchTemplates() { + try { + const res = await get('/api/product-templates', this.query.categoryId ? { categoryId: this.query.categoryId } : {}) + const list = Array.isArray(res?.list) ? res.list : (Array.isArray(res) ? res : []) + this.templates = list + } catch (_) { this.templates = [] } + }, reload() { this.items = [] this.query.page = 1 @@ -107,7 +169,16 @@ export default { this.loading = true try { const params = { kw: this.query.kw, page: this.query.page, size: this.query.size } - if (this.tab === 'category' && this.query.categoryId) params.categoryId = this.query.categoryId + if (this.tab === 'search') { + if (this.query.categoryId) params.categoryId = this.query.categoryId + if (this.query.templateId) params.templateId = this.query.templateId + if (this.paramValues && Object.keys(this.paramValues).length) { + for (const k of Object.keys(this.paramValues)) { + const v = this.paramValues[k] + if (v !== undefined && v !== null && v !== '') params['param_' + k] = v + } + } + } const res = await get('/api/products', params) const list = Array.isArray(res?.list) ? res.list : (Array.isArray(res) ? res : []) this.items = this.items.concat(list) @@ -119,13 +190,26 @@ export default { this.loading = false } }, - openForm(id) { - const url = '/pages/product/form' + (id ? ('?id=' + id) : '') - uni.navigateTo({ url }) - }, - goMySubmissions() { + openDetail(id) { + uni.navigateTo({ url: '/pages/product/product-detail?id=' + id }) + }, + goMySubmissions() { uni.navigateTo({ url: '/pages/product/submissions' }) - } + }, + async remove(it) { + try { + const r = await new Promise(resolve => { + uni.showModal({ content: '确认删除该货品?删除后可在后台恢复', success: resolve }) + }) + if (!r || !r.confirm) return + const { del } = require('../../common/http.js') + await del('/api/products/' + it.id) + uni.showToast({ title: '已删除', icon: 'success' }) + this.reload() + } catch (e) { + uni.showToast({ title: '删除失败', icon: 'none' }) + } + } } } @@ -139,6 +223,9 @@ export default { .search { display:flex; gap: 12rpx; padding: 16rpx; background:$uni-bg-color-grey; align-items: center; } .search input { flex:1; background:$uni-bg-color-hover; border-radius: 12rpx; padding: 12rpx; color: $uni-text-color; } .picker { padding: 8rpx 12rpx; background:$uni-bg-color-hover; border-radius: 10rpx; color:$uni-text-color-grey; } +.template-mode { flex-direction: column; align-items: stretch; gap: 8rpx; } +.picker-row { display:flex; gap: 12rpx; } +.params-wrap { margin-top: 6rpx; background:$uni-bg-color-grey; border-radius: 12rpx; padding: 8rpx 8rpx; } .list { flex:1; } .item { display:flex; padding: 20rpx; background:$uni-bg-color-grey; border-bottom: 1rpx solid $uni-border-color; } .thumb { width: 120rpx; height: 120rpx; border-radius: 12rpx; margin-right: 16rpx; background:$uni-bg-color-hover; } @@ -146,6 +233,7 @@ export default { .name { color:$uni-text-color; margin-bottom: 6rpx; font-weight: 600; display:flex; align-items:center; gap: 12rpx; } .tag-platform { font-size: 22rpx; color:#fff; background:#2d8cf0; padding: 4rpx 10rpx; border-radius: 8rpx; } .tag-custom { font-size: 22rpx; color:#fff; background:#67c23a; padding: 4rpx 10rpx; border-radius: 8rpx; } +.tag-deleted { font-size: 22rpx; color:#fff; background:#909399; padding: 4rpx 10rpx; border-radius: 8rpx; } .meta { color:$uni-text-color-grey; font-size: 24rpx; } .price { margin-left: 20rpx; color:$uni-color-primary; } .empty { height: 60vh; display:flex; align-items:center; justify-content:center; color:$uni-text-color-grey; } diff --git a/frontend/pages/product/product-detail.vue b/frontend/pages/product/product-detail.vue new file mode 100644 index 0000000..01cbcd6 --- /dev/null +++ b/frontend/pages/product/product-detail.vue @@ -0,0 +1,142 @@ + + + + + + diff --git a/frontend/pages/product/submission-detail.vue b/frontend/pages/product/submission-detail.vue index ab33307..72bc82d 100644 --- a/frontend/pages/product/submission-detail.vue +++ b/frontend/pages/product/submission-detail.vue @@ -9,18 +9,17 @@ 名称{{ detail.name || '-' }} 品牌{{ detail.brand || '-' }} 规格{{ detail.spec || '-' }} - 产地{{ detail.origin || '-' }} 条码{{ detail.barcode || '-' }} - 单位{{ unitName }} 类别{{ categoryName }} - 安全库存{{ stockRange }} + 模板{{ templateName }} + 参数 - - - {{ item.key }} + + + {{ item.label }} {{ item.value }} @@ -63,7 +62,8 @@ export default { id: '', detail: null, unitName: '-', - categoryName: '-' + categoryName: '-', + templateName: '-' } }, async onLoad(query) { @@ -79,8 +79,9 @@ export default { try { const data = await get(`/api/products/submissions/${this.id}`) this.detail = data - this.unitName = this.unitLookup(data.unitId) + // 单位已移除 this.categoryName = this.categoryLookup(data.categoryId) + this.templateName = this.templateLookup(data.templateId) } catch (e) { const msg = e?.message || '加载失败' uni.showToast({ title: msg, icon: 'none' }) @@ -96,11 +97,7 @@ export default { if (s === 'rejected') return 'rejected' return 'pending' }, - parameterPairs() { - const params = this.detail?.parameters - if (!params || typeof params !== 'object') return [] - return Object.keys(params).map(k => ({ key: k, value: params[k] })) - }, + preview(idx) { if (!this.detail?.images || !this.detail.images.length) return uni.previewImage({ urls: this.detail.images, current: idx }) @@ -120,7 +117,7 @@ export default { }, unitLookup(id) { try { - const list = uni.getStorageSync('CACHE_UNITS') || [] + const list = [] const found = list.find(x => String(x.id) === String(id)) return found ? found.name : '-' } catch (_) { return '-' } @@ -132,6 +129,13 @@ export default { return found ? found.name : '-' } catch (_) { return '-' } }, + templateLookup(id) { + try { + const list = uni.getStorageSync('CACHE_TEMPLATES') || [] + const found = list.find(x => String(x.id) === String(id)) + return found ? found.name : '-' + } catch (_) { return '-' } + }, back() { uni.navigateBack({ delta: 1 }) }, @@ -160,6 +164,20 @@ export default { if (min != null && max != null) return `${min} ~ ${max}` if (min != null) return `≥ ${min}` return `≤ ${max}` + }, + labeledPairs() { + const params = this.detail?.parameters + if (!params || typeof params !== 'object') return [] + // 从缓存模板中读取 label + let labelMap = {} + try { + const templates = uni.getStorageSync('CACHE_TEMPLATES') || [] + const tpl = templates.find(t => String(t.id) === String(this.detail?.templateId)) + if (tpl && Array.isArray(tpl.params)) { + for (const p of tpl.params) labelMap[p.fieldKey] = p.fieldLabel + } + } catch (_) {} + return Object.keys(params).map(k => ({ key: k, label: labelMap[k] || k, value: params[k] })) } } } diff --git a/frontend/pages/product/submissions.vue b/frontend/pages/product/submissions.vue index 96601ce..e6ed4b0 100644 --- a/frontend/pages/product/submissions.vue +++ b/frontend/pages/product/submissions.vue @@ -68,9 +68,10 @@ export default { methods: { async preloadDictionaries() { try { - const [units, categories] = await Promise.all([ + const [units, categories, templates] = await Promise.all([ this.cacheUnitsLoaded ? Promise.resolve(null) : get('/api/product-units'), - this.cacheCategoriesLoaded ? Promise.resolve(null) : get('/api/product-categories') + this.cacheCategoriesLoaded ? Promise.resolve(null) : get('/api/product-categories'), + get('/api/product-templates') ]) if (units) { const list = Array.isArray(units?.list) ? units.list : (Array.isArray(units) ? units : []) @@ -82,6 +83,10 @@ export default { uni.setStorageSync('CACHE_CATEGORIES', list) this.cacheCategoriesLoaded = true } + if (templates) { + const list = Array.isArray(templates?.list) ? templates.list : (Array.isArray(templates) ? templates : []) + uni.setStorageSync('CACHE_TEMPLATES', list) + } } catch (_) { // 忽略缓存失败 } diff --git a/frontend/pages/product/submit.vue b/frontend/pages/product/submit.vue index 1838e91..d67abbd 100644 --- a/frontend/pages/product/submit.vue +++ b/frontend/pages/product/submit.vue @@ -32,6 +32,13 @@ + + + 编号 + + + + 模板 @@ -43,6 +50,42 @@ + + + + 参数 + + + + + {{ p.fieldLabel }}({{ p.unit }})* + + + + + + + + + + + + + {{ displayEnum(p) }} + + + + + {{ paramValues[p.fieldKey] || ('选择' + p.fieldLabel) }} + + + + + + + + + 图片 @@ -91,6 +134,7 @@ export default { categoryId: '', templateId: '', + externalCode: '', parameters: {}, images: [], remark: '', @@ -172,11 +216,18 @@ export default { this.form.templateId = t ? t.id : '' this.paramValues = {} }, + onPickDate(p, e) { + this.paramValues[p.fieldKey] = e?.detail?.value || '' + }, onPickEnum(p, e) { const idx = Number(e.detail.value) const arr = p.enumOptions || [] this.paramValues[p.fieldKey] = arr[idx] }, + displayEnum(p) { + const v = this.paramValues[p.fieldKey] + return (v === undefined || v === null || v === '') ? ('选择' + p.fieldLabel) : String(v) + }, async scanBarcode() { try { const chooseRes = await uni.chooseImage({ count: 1, sourceType: ['camera','album'], sizeType: ['compressed'] }) @@ -253,6 +304,7 @@ export default { model: this.form.model, brand: this.form.brand, barcode: this.form.barcode, + externalCode: this.form.externalCode || null, categoryId: this.form.categoryId || null, templateId: this.form.templateId || null, parameters: paramsForSubmit, diff --git a/frontend/static/icons/undraw_visual-data_1eya.png b/frontend/static/icons/undraw_visual-data_1eya.png new file mode 100644 index 0000000..eecc141 Binary files /dev/null and b/frontend/static/icons/undraw_visual-data_1eya.png differ diff --git a/frontend/static/icons/配件审核_1758986693151.xlsx b/frontend/static/icons/配件审核_1758986693151.xlsx new file mode 100644 index 0000000..91d534b Binary files /dev/null and b/frontend/static/icons/配件审核_1758986693151.xlsx differ diff --git a/frontend/static/icons/配件审核_1758987353730.xlsx b/frontend/static/icons/配件审核_1758987353730.xlsx new file mode 100644 index 0000000..b421396 Binary files /dev/null and b/frontend/static/icons/配件审核_1758987353730.xlsx differ diff --git a/frontend/uni.scss b/frontend/uni.scss index 08eecc1..87d3ea9 100644 --- a/frontend/uni.scss +++ b/frontend/uni.scss @@ -74,3 +74,9 @@ $uni-color-subtitle: #555555; // 二级标题颜色 $uni-font-size-subtitle:26px; $uni-color-paragraph: #3F536E; // 文章段落颜色 $uni-font-size-paragraph:15px; + +/* 表单控件尺寸(统一配置,避免页面内硬编码) */ +$app-form-control-height: 76rpx; // 控件总高度(含边框) +$app-form-control-padding-x: 20rpx; // 水平方向内边距 +$app-form-control-border-width: 2rpx; // 边框宽度 +$app-form-control-border-radius: 12rpx; // 圆角半径 diff --git a/frontend/unpackage/dist/dev/.sourcemap/mp-weixin/app.js.map b/frontend/unpackage/dist/dev/.sourcemap/mp-weixin/app.js.map index ed31365..8658281 100644 --- a/frontend/unpackage/dist/dev/.sourcemap/mp-weixin/app.js.map +++ b/frontend/unpackage/dist/dev/.sourcemap/mp-weixin/app.js.map @@ -1 +1 @@ -{"version":3,"file":"app.js","sources":["App.vue","main.js"],"sourcesContent":["\"D:\\wx\\PartsInquiry\\frontend\\static\\icons\\icons8-account-male-100.png\"\r\n\r\n\r\n","import App from './App'\r\n\r\n// #ifndef VUE3\r\nimport Vue from 'vue'\r\nimport './uni.promisify.adaptor'\r\nVue.config.productionTip = false\r\nApp.mpType = 'app'\r\nconst app = new Vue({\r\n ...App\r\n})\r\napp.$mount()\r\n// #endif\r\n\r\n// #ifdef VUE3\r\nimport { createSSRApp } from 'vue'\r\nexport function createApp() {\r\n const app = createSSRApp(App)\r\n return {\r\n app\r\n }\r\n}\r\n// #endif\r\n\r\n// 规范化 WebSocket 关闭码(仅微信小程序)\r\n// #ifdef MP-WEIXIN\r\nif (typeof uni !== 'undefined' && typeof uni.connectSocket === 'function') {\r\n const _connectSocket = uni.connectSocket\r\n uni.connectSocket = function(options) {\r\n const task = _connectSocket.call(this, options)\r\n if (task && typeof task.close === 'function') {\r\n const _close = task.close\r\n task.close = function(params = {}) {\r\n if (params && typeof params === 'object') {\r\n const codeNum = Number(params.code)\r\n const isValid = codeNum === 1000 || (codeNum >= 3000 && codeNum <= 4999)\r\n if (!isValid) {\r\n params.code = 1000\r\n if (!params.reason) params.reason = 'normalized from invalid close code'\r\n }\r\n }\r\n return _close.call(this, params)\r\n }\r\n }\r\n return task\r\n }\r\n}\r\n// #endif\r\n\r\n// 全局安全返回:首屏无法后退时自动回到首页 tab(微信小程序)\r\n// #ifdef MP-WEIXIN\r\nif (typeof uni !== 'undefined' && typeof uni.navigateBack === 'function') {\r\n const _navigateBack = uni.navigateBack\r\n uni.navigateBack = function(params = {}) {\r\n try {\r\n const pages = typeof getCurrentPages === 'function' ? getCurrentPages() : []\r\n const maxDelta = pages.length > 0 ? (pages.length - 1) : 0\r\n const d = Number(params.delta || 1)\r\n if (maxDelta >= 1 && d <= maxDelta) {\r\n return _navigateBack.call(this, params)\r\n }\r\n return uni.switchTab({ url: '/pages/index/index' })\r\n } catch (e) {\r\n return uni.switchTab({ url: '/pages/index/index' })\r\n }\r\n }\r\n}\r\n// #endif"],"names":["uni","createSSRApp","App"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACC,MAAK,YAAU;AAAA,EACd,UAAU,WAAW;AACpBA,kBAAAA,MAAA,MAAA,OAAA,gBAAY,YAAY;AAAA,EACxB;AAAA,EACD,QAAQ,WAAW;AAClBA,kBAAAA,MAAY,MAAA,OAAA,gBAAA,UAAU;AAAA,EACtB;AAAA,EACD,QAAQ,WAAW;AAClBA,kBAAAA,MAAY,MAAA,OAAA,iBAAA,UAAU;AAAA,EACvB;AACD;ACIM,SAAS,YAAY;AAC1B,QAAM,MAAMC,cAAY,aAACC,SAAG;AAC5B,SAAO;AAAA,IACL;AAAA,EACD;AACH;AAKA,IAAI,OAAOF,cAAG,UAAK,eAAe,OAAOA,cAAAA,MAAI,kBAAkB,YAAY;AACzE,QAAM,iBAAiBA,cAAAA,MAAI;AAC3BA,sBAAI,gBAAgB,SAAS,SAAS;AACpC,UAAM,OAAO,eAAe,KAAK,MAAM,OAAO;AAC9C,QAAI,QAAQ,OAAO,KAAK,UAAU,YAAY;AAC5C,YAAM,SAAS,KAAK;AACpB,WAAK,QAAQ,SAAS,SAAS,IAAI;AACjC,YAAI,UAAU,OAAO,WAAW,UAAU;AACxC,gBAAM,UAAU,OAAO,OAAO,IAAI;AAClC,gBAAM,UAAU,YAAY,OAAS,WAAW,OAAQ,WAAW;AACnE,cAAI,CAAC,SAAS;AACZ,mBAAO,OAAO;AACd,gBAAI,CAAC,OAAO;AAAQ,qBAAO,SAAS;AAAA,UACrC;AAAA,QACF;AACD,eAAO,OAAO,KAAK,MAAM,MAAM;AAAA,MAChC;AAAA,IACF;AACD,WAAO;AAAA,EACR;AACH;AAKA,IAAI,OAAOA,cAAG,UAAK,eAAe,OAAOA,cAAAA,MAAI,iBAAiB,YAAY;AACxE,QAAM,gBAAgBA,cAAAA,MAAI;AAC1BA,gBAAAA,MAAI,eAAe,SAAS,SAAS,IAAI;AACvC,QAAI;AACF,YAAM,QAAQ,OAAO,oBAAoB,aAAa,gBAAiB,IAAG,CAAE;AAC5E,YAAM,WAAW,MAAM,SAAS,IAAK,MAAM,SAAS,IAAK;AACzD,YAAM,IAAI,OAAO,OAAO,SAAS,CAAC;AAClC,UAAI,YAAY,KAAK,KAAK,UAAU;AAClC,eAAO,cAAc,KAAK,MAAM,MAAM;AAAA,MACvC;AACD,aAAOA,cAAG,MAAC,UAAU,EAAE,KAAK,qBAAoB,CAAE;AAAA,IACnD,SAAQ,GAAG;AACV,aAAOA,cAAG,MAAC,UAAU,EAAE,KAAK,qBAAoB,CAAE;AAAA,IACnD;AAAA,EACF;AACH;;;"} \ No newline at end of file +{"version":3,"file":"app.js","sources":["App.vue","main.js"],"sourcesContent":["\"D:\\wx\\PartsInquiry\\frontend\\static\\icons\\icons8-account-male-100.png\"\r\n\r\n\r\n","import App from './App'\r\n\r\n// #ifndef VUE3\r\nimport Vue from 'vue'\r\nimport './uni.promisify.adaptor'\r\nVue.config.productionTip = false\r\nApp.mpType = 'app'\r\nconst app = new Vue({\r\n ...App\r\n})\r\napp.$mount()\r\n// #endif\r\n\r\n// #ifdef VUE3\r\nimport { createSSRApp } from 'vue'\r\nexport function createApp() {\r\n const app = createSSRApp(App)\r\n return {\r\n app\r\n }\r\n}\r\n// #endif\r\n\r\n// 规范化 WebSocket 关闭码(仅微信小程序)\r\n// #ifdef MP-WEIXIN\r\nif (typeof uni !== 'undefined' && typeof uni.connectSocket === 'function') {\r\n const _connectSocket = uni.connectSocket\r\n uni.connectSocket = function(options) {\r\n const task = _connectSocket.call(this, options)\r\n if (task && typeof task.close === 'function') {\r\n const _close = task.close\r\n task.close = function(params = {}) {\r\n if (params && typeof params === 'object') {\r\n const codeNum = Number(params.code)\r\n const isValid = codeNum === 1000 || (codeNum >= 3000 && codeNum <= 4999)\r\n if (!isValid) {\r\n params.code = 1000\r\n if (!params.reason) params.reason = 'normalized from invalid close code'\r\n }\r\n }\r\n return _close.call(this, params)\r\n }\r\n }\r\n return task\r\n }\r\n}\r\n// #endif\r\n\r\n// 全局安全返回:首屏无法后退时自动回到首页 tab(微信小程序)\r\n// #ifdef MP-WEIXIN\r\nif (typeof uni !== 'undefined' && typeof uni.navigateBack === 'function') {\r\n const _navigateBack = uni.navigateBack\r\n uni.navigateBack = function(params = {}) {\r\n try {\r\n const pages = typeof getCurrentPages === 'function' ? getCurrentPages() : []\r\n const maxDelta = pages.length > 0 ? (pages.length - 1) : 0\r\n const d = Number(params.delta || 1)\r\n if (maxDelta >= 1 && d <= maxDelta) {\r\n return _navigateBack.call(this, params)\r\n }\r\n return uni.switchTab({ url: '/pages/index/index' })\r\n } catch (e) {\r\n return uni.switchTab({ url: '/pages/index/index' })\r\n }\r\n }\r\n}\r\n// #endif"],"names":["uni","createSSRApp","App"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACC,MAAK,YAAU;AAAA,EACd,UAAU,WAAW;AACpBA,kBAAAA,MAAA,MAAA,OAAA,gBAAY,YAAY;AAAA,EACxB;AAAA,EACD,QAAQ,WAAW;AAClBA,kBAAAA,MAAY,MAAA,OAAA,gBAAA,UAAU;AAAA,EACtB;AAAA,EACD,QAAQ,WAAW;AAClBA,kBAAAA,MAAY,MAAA,OAAA,iBAAA,UAAU;AAAA,EACvB;AACD;ACIM,SAAS,YAAY;AAC1B,QAAM,MAAMC,cAAY,aAACC,SAAG;AAC5B,SAAO;AAAA,IACL;AAAA,EACD;AACH;AAKA,IAAI,OAAOF,cAAG,UAAK,eAAe,OAAOA,cAAAA,MAAI,kBAAkB,YAAY;AACzE,QAAM,iBAAiBA,cAAAA,MAAI;AAC3BA,sBAAI,gBAAgB,SAAS,SAAS;AACpC,UAAM,OAAO,eAAe,KAAK,MAAM,OAAO;AAC9C,QAAI,QAAQ,OAAO,KAAK,UAAU,YAAY;AAC5C,YAAM,SAAS,KAAK;AACpB,WAAK,QAAQ,SAAS,SAAS,IAAI;AACjC,YAAI,UAAU,OAAO,WAAW,UAAU;AACxC,gBAAM,UAAU,OAAO,OAAO,IAAI;AAClC,gBAAM,UAAU,YAAY,OAAS,WAAW,OAAQ,WAAW;AACnE,cAAI,CAAC,SAAS;AACZ,mBAAO,OAAO;AACd,gBAAI,CAAC,OAAO;AAAQ,qBAAO,SAAS;AAAA,UACrC;AAAA,QACF;AACD,eAAO,OAAO,KAAK,MAAM,MAAM;AAAA,MAChC;AAAA,IACF;AACD,WAAO;AAAA,EACR;AACH;AAKA,IAAI,OAAOA,cAAG,UAAK,eAAe,OAAOA,cAAAA,MAAI,iBAAiB,YAAY;AACxE,QAAM,gBAAgBA,cAAAA,MAAI;AAC1BA,gBAAAA,MAAI,eAAe,SAAS,SAAS,IAAI;AACvC,QAAI;AACF,YAAM,QAAQ,OAAO,oBAAoB,aAAa,gBAAiB,IAAG,CAAE;AAC5E,YAAM,WAAW,MAAM,SAAS,IAAK,MAAM,SAAS,IAAK;AACzD,YAAM,IAAI,OAAO,OAAO,SAAS,CAAC;AAClC,UAAI,YAAY,KAAK,KAAK,UAAU;AAClC,eAAO,cAAc,KAAK,MAAM,MAAM;AAAA,MACvC;AACD,aAAOA,cAAG,MAAC,UAAU,EAAE,KAAK,qBAAoB,CAAE;AAAA,IACnD,SAAQ,GAAG;AACV,aAAOA,cAAG,MAAC,UAAU,EAAE,KAAK,qBAAoB,CAAE;AAAA,IACnD;AAAA,EACF;AACH;;;"} \ No newline at end of file diff --git a/frontend/unpackage/dist/dev/.sourcemap/mp-weixin/common/config.js.map b/frontend/unpackage/dist/dev/.sourcemap/mp-weixin/common/config.js.map index 49ccd15..f175bd9 100644 --- a/frontend/unpackage/dist/dev/.sourcemap/mp-weixin/common/config.js.map +++ b/frontend/unpackage/dist/dev/.sourcemap/mp-weixin/common/config.js.map @@ -1 +1 @@ -{"version":3,"file":"config.js","sources":["common/config.js"],"sourcesContent":["// 统一配置:禁止在业务代码中硬编码\n// 优先级:环境变量(Vite/HBuilderX 构建注入) > 本地存储 > 默认值\n\nconst envBaseUrl = (typeof process !== 'undefined' && process.env && (process.env.VITE_APP_API_BASE_URL || process.env.API_BASE_URL)) || '';\nconst storageBaseUrl = typeof uni !== 'undefined' ? (uni.getStorageSync('API_BASE_URL') || '') : '';\nconst fallbackBaseUrl = 'http://127.0.0.1:8080';\n\nexport const API_BASE_URL = (envBaseUrl || storageBaseUrl || fallbackBaseUrl).replace(/\\/$/, '');\n\n// 多地址候选(按优先级顺序,自动去重与去尾斜杠)\nconst candidateBases = [envBaseUrl, storageBaseUrl, fallbackBaseUrl, 'http://127.0.0.1:8080', 'http://localhost:8080'];\nexport const API_BASE_URL_CANDIDATES = Array.from(new Set(candidateBases.filter(Boolean))).map(u => String(u).replace(/\\/$/, ''));\n\nconst envShopId = (typeof process !== 'undefined' && process.env && (process.env.VITE_APP_SHOP_ID || process.env.SHOP_ID)) || '';\nconst storageShopId = typeof uni !== 'undefined' ? (uni.getStorageSync('SHOP_ID') || '') : '';\nexport const SHOP_ID = Number(envShopId || storageShopId || 1);\n\n\n// 默认用户(可移除):\n// - 用途:开发/演示环境,自动将用户固定为“张老板”(id=2)\n// - 开关优先级:环境变量 > 本地存储 > 默认值\n// - 生产默认关闭(false);开发可通过本地存储或环境变量开启\nconst envEnableDefaultUser = (typeof process !== 'undefined' && process.env && (process.env.VITE_APP_ENABLE_DEFAULT_USER || process.env.ENABLE_DEFAULT_USER)) || '';\nconst storageEnableDefaultUser = typeof uni !== 'undefined' ? (uni.getStorageSync('ENABLE_DEFAULT_USER') || '') : '';\nexport const ENABLE_DEFAULT_USER = String(envEnableDefaultUser || storageEnableDefaultUser || 'false').toLowerCase() === 'true';\n\nconst envDefaultUserId = (typeof process !== 'undefined' && process.env && (process.env.VITE_APP_DEFAULT_USER_ID || process.env.DEFAULT_USER_ID)) || '';\nconst storageDefaultUserId = typeof uni !== 'undefined' ? (uni.getStorageSync('DEFAULT_USER_ID') || '') : '';\nexport const DEFAULT_USER_ID = Number(envDefaultUserId || storageDefaultUserId || 0);\n\n\n// 会员价格(单位:元/月):环境 > 本地存储 > 默认值\nconst envVipPrice = (typeof process !== 'undefined' && process.env && (process.env.VITE_APP_VIP_PRICE || process.env.VIP_PRICE)) || '';\nconst storageVipPrice = typeof uni !== 'undefined' ? (uni.getStorageSync('VIP_PRICE') || '') : '';\nexport const VIP_PRICE_PER_MONTH = Number(envVipPrice || storageVipPrice || 15);\n\n\n// 首页横幅图片(公告上方),避免硬编码\n// 优先级:环境变量 > 本地存储 > 默认值(放置于 /static/icons/ 下)\nconst envHomeBanner = (typeof process !== 'undefined' && process.env && (process.env.VITE_APP_HOME_BANNER_IMG || process.env.HOME_BANNER_IMG)) || '';\nconst storageHomeBanner = typeof uni !== 'undefined' ? (uni.getStorageSync('HOME_BANNER_IMG') || '') : '';\nexport const HOME_BANNER_IMG = String(envHomeBanner || storageHomeBanner || '/static/icons/home-banner.png');\n\n// KPI 图标(可按需覆盖),避免在页面里硬编码\nexport const KPI_ICONS = {\n todaySales: '/static/icons/webwxgetmsgimg.jpg',\n monthSales: '/static/icons/webwxgetmsgimg.jpg',\n monthProfit: '/static/icons/icons8-profit-50.png',\n stockCount: '/static/icons/product.png'\n}\n\n"],"names":["uni"],"mappings":";;AAGA,MAAM,aAAc,OAAO,YAAY,eAAe,QAAQ,QAAQ,QAAQ,IAAI,yBAAyB,QAAQ,IAAI,iBAAkB;AACzI,MAAM,iBAAiB,OAAOA,cAAG,UAAK,cAAeA,cAAAA,MAAI,eAAe,cAAc,KAAK,KAAM;AACjG,MAAM,kBAAkB;AAEZ,MAAC,gBAAgB,cAAc,kBAAkB,iBAAiB,QAAQ,OAAO,EAAE;AAG/F,MAAM,iBAAiB,CAAC,YAAY,gBAAgB,iBAAiB,yBAAyB,uBAAuB;AACzG,MAAC,0BAA0B,MAAM,KAAK,IAAI,IAAI,eAAe,OAAO,OAAO,CAAC,CAAC,EAAE,IAAI,OAAK,OAAO,CAAC,EAAE,QAAQ,OAAO,EAAE,CAAC;AAEhI,MAAM,YAAa,OAAO,YAAY,eAAe,QAAQ,QAAQ,QAAQ,IAAI,oBAAoB,QAAQ,IAAI,YAAa;AAC9H,MAAM,gBAAgB,OAAOA,cAAG,UAAK,cAAeA,cAAAA,MAAI,eAAe,SAAS,KAAK,KAAM;AAC/E,MAAC,UAAU,OAAO,aAAa,iBAAiB,CAAC;AAO7D,MAAM,uBAAwB,OAAO,YAAY,eAAe,QAAQ,QAAQ,QAAQ,IAAI,gCAAgC,QAAQ,IAAI,wBAAyB;AACjK,MAAM,2BAA2B,OAAOA,cAAG,UAAK,cAAeA,cAAAA,MAAI,eAAe,qBAAqB,KAAK,KAAM;AACtG,MAAC,sBAAsB,OAAO,wBAAwB,4BAA4B,OAAO,EAAE,YAAW,MAAO;AAEzH,MAAM,mBAAoB,OAAO,YAAY,eAAe,QAAQ,QAAQ,QAAQ,IAAI,4BAA4B,QAAQ,IAAI,oBAAqB;AACrJ,MAAM,uBAAuB,OAAOA,cAAG,UAAK,cAAeA,cAAAA,MAAI,eAAe,iBAAiB,KAAK,KAAM;AAC9F,MAAC,kBAAkB,OAAO,oBAAoB,wBAAwB,CAAC;AAI9D,OAAO,YAAY,eAAe,QAAQ,QAAQ,QAAQ,IAAI,sBAAsB,QAAQ,IAAI,cAAe;AAC5G,OAAOA,cAAG,UAAK,cAAeA,cAAG,MAAC,eAAe,WAAW,KAAK,KAAM;AAMxE,OAAO,YAAY,eAAe,QAAQ,QAAQ,QAAQ,IAAI,4BAA4B,QAAQ,IAAI,oBAAqB;AACxH,OAAOA,cAAG,UAAK,cAAeA,cAAG,MAAC,eAAe,iBAAiB,KAAK,KAAM;AAI3F,MAAC,YAAY;AAAA,EACrB,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,aAAa;AAAA,EACb,YAAY;AAChB;;;;;;;"} \ No newline at end of file +{"version":3,"file":"config.js","sources":["common/config.js"],"sourcesContent":["// 统一配置:禁止在业务代码中硬编码\n// 优先级:环境变量(Vite/HBuilderX 构建注入) > 本地存储 > 默认值\n\nconst envBaseUrl = (typeof process !== 'undefined' && process.env && (process.env.VITE_APP_API_BASE_URL || process.env.API_BASE_URL)) || '';\nconst storageBaseUrl = typeof uni !== 'undefined' ? (uni.getStorageSync('API_BASE_URL') || '') : '';\nconst fallbackBaseUrl = 'http://127.0.0.1:8080';\n\nexport const API_BASE_URL = (envBaseUrl || storageBaseUrl || fallbackBaseUrl).replace(/\\/$/, '');\n\n// 多地址候选(按优先级顺序,自动去重与去尾斜杠)\nconst candidateBases = [envBaseUrl, storageBaseUrl, fallbackBaseUrl, 'http://127.0.0.1:8080', 'http://localhost:8080'];\nexport const API_BASE_URL_CANDIDATES = Array.from(new Set(candidateBases.filter(Boolean))).map(u => String(u).replace(/\\/$/, ''));\n\nconst envShopId = (typeof process !== 'undefined' && process.env && (process.env.VITE_APP_SHOP_ID || process.env.SHOP_ID)) || '';\nconst storageShopId = typeof uni !== 'undefined' ? (uni.getStorageSync('SHOP_ID') || '') : '';\nexport const SHOP_ID = Number(envShopId || storageShopId || 1);\n\n\n// 默认用户(可移除):\n// - 用途:开发/演示环境,自动将用户固定为“张老板”(id=2)\n// - 开关优先级:环境变量 > 本地存储 > 默认值\n// - 生产默认关闭(false);开发可通过本地存储或环境变量开启\nconst envEnableDefaultUser = (typeof process !== 'undefined' && process.env && (process.env.VITE_APP_ENABLE_DEFAULT_USER || process.env.ENABLE_DEFAULT_USER)) || '';\nconst storageEnableDefaultUser = typeof uni !== 'undefined' ? (uni.getStorageSync('ENABLE_DEFAULT_USER') || '') : '';\nexport const ENABLE_DEFAULT_USER = String(envEnableDefaultUser || storageEnableDefaultUser || 'false').toLowerCase() === 'true';\n\nconst envDefaultUserId = (typeof process !== 'undefined' && process.env && (process.env.VITE_APP_DEFAULT_USER_ID || process.env.DEFAULT_USER_ID)) || '';\nconst storageDefaultUserId = typeof uni !== 'undefined' ? (uni.getStorageSync('DEFAULT_USER_ID') || '') : '';\nexport const DEFAULT_USER_ID = Number(envDefaultUserId || storageDefaultUserId || 0);\n\n\n// 会员价格(单位:元/月):环境 > 本地存储 > 默认值\nconst envVipPrice = (typeof process !== 'undefined' && process.env && (process.env.VITE_APP_VIP_PRICE || process.env.VIP_PRICE)) || '';\nconst storageVipPrice = typeof uni !== 'undefined' ? (uni.getStorageSync('VIP_PRICE') || '') : '';\nexport const VIP_PRICE_PER_MONTH = Number(envVipPrice || storageVipPrice || 15);\n\n\n// 首页横幅图片(公告上方),避免硬编码\n// 优先级:环境变量 > 本地存储 > 默认值(放置于 /static/icons/ 下)\nconst envHomeBanner = (typeof process !== 'undefined' && process.env && (process.env.VITE_APP_HOME_BANNER_IMG || process.env.HOME_BANNER_IMG)) || '';\nconst storageHomeBanner = typeof uni !== 'undefined' ? (uni.getStorageSync('HOME_BANNER_IMG') || '') : '';\nexport const HOME_BANNER_IMG = String(envHomeBanner || storageHomeBanner || '/static/icons/home-banner.png');\n\n// KPI 图标(可按需覆盖),避免在页面里硬编码\nexport const KPI_ICONS = {\n todaySales: '/static/icons/webwxgetmsgimg.jpg',\n monthSales: '/static/icons/webwxgetmsgimg.jpg',\n monthProfit: '/static/icons/icons8-profit-50.png',\n stockCount: '/static/icons/product.png'\n}\n\n// 登录页顶部图片,避免在页面硬编码,允许通过环境变量或本地存储覆盖\nconst envAuthLoginImg = (typeof process !== 'undefined' && process.env && (process.env.VITE_APP_AUTH_LOGIN_TOP_IMAGE || process.env.AUTH_LOGIN_TOP_IMAGE)) || '';\nconst storageAuthLoginImg = typeof uni !== 'undefined' ? (uni.getStorageSync('AUTH_LOGIN_TOP_IMAGE') || '') : '';\nexport const AUTH_LOGIN_TOP_IMAGE = String(envAuthLoginImg || storageAuthLoginImg || '/static/icons/undraw_visual-data_1eya.png');\n\n"],"names":["uni"],"mappings":";;AAGA,MAAM,aAAc,OAAO,YAAY,eAAe,QAAQ,QAAQ,QAAQ,IAAI,yBAAyB,QAAQ,IAAI,iBAAkB;AACzI,MAAM,iBAAiB,OAAOA,cAAG,UAAK,cAAeA,cAAAA,MAAI,eAAe,cAAc,KAAK,KAAM;AACjG,MAAM,kBAAkB;AAEZ,MAAC,gBAAgB,cAAc,kBAAkB,iBAAiB,QAAQ,OAAO,EAAE;AAG/F,MAAM,iBAAiB,CAAC,YAAY,gBAAgB,iBAAiB,yBAAyB,uBAAuB;AACzG,MAAC,0BAA0B,MAAM,KAAK,IAAI,IAAI,eAAe,OAAO,OAAO,CAAC,CAAC,EAAE,IAAI,OAAK,OAAO,CAAC,EAAE,QAAQ,OAAO,EAAE,CAAC;AAEhI,MAAM,YAAa,OAAO,YAAY,eAAe,QAAQ,QAAQ,QAAQ,IAAI,oBAAoB,QAAQ,IAAI,YAAa;AAC9H,MAAM,gBAAgB,OAAOA,cAAG,UAAK,cAAeA,cAAAA,MAAI,eAAe,SAAS,KAAK,KAAM;AAC/E,MAAC,UAAU,OAAO,aAAa,iBAAiB,CAAC;AAO7D,MAAM,uBAAwB,OAAO,YAAY,eAAe,QAAQ,QAAQ,QAAQ,IAAI,gCAAgC,QAAQ,IAAI,wBAAyB;AACjK,MAAM,2BAA2B,OAAOA,cAAG,UAAK,cAAeA,cAAAA,MAAI,eAAe,qBAAqB,KAAK,KAAM;AACtG,MAAC,sBAAsB,OAAO,wBAAwB,4BAA4B,OAAO,EAAE,YAAW,MAAO;AAEzH,MAAM,mBAAoB,OAAO,YAAY,eAAe,QAAQ,QAAQ,QAAQ,IAAI,4BAA4B,QAAQ,IAAI,oBAAqB;AACrJ,MAAM,uBAAuB,OAAOA,cAAG,UAAK,cAAeA,cAAAA,MAAI,eAAe,iBAAiB,KAAK,KAAM;AAC9F,MAAC,kBAAkB,OAAO,oBAAoB,wBAAwB,CAAC;AAI9D,OAAO,YAAY,eAAe,QAAQ,QAAQ,QAAQ,IAAI,sBAAsB,QAAQ,IAAI,cAAe;AAC5G,OAAOA,cAAG,UAAK,cAAeA,cAAG,MAAC,eAAe,WAAW,KAAK,KAAM;AAMxE,OAAO,YAAY,eAAe,QAAQ,QAAQ,QAAQ,IAAI,4BAA4B,QAAQ,IAAI,oBAAqB;AACxH,OAAOA,cAAG,UAAK,cAAeA,cAAG,MAAC,eAAe,iBAAiB,KAAK,KAAM;AAI3F,MAAC,YAAY;AAAA,EACrB,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,aAAa;AAAA,EACb,YAAY;AAChB;AAGA,MAAM,kBAAmB,OAAO,YAAY,eAAe,QAAQ,QAAQ,QAAQ,IAAI,iCAAiC,QAAQ,IAAI,yBAA0B;AAC9J,MAAM,sBAAsB,OAAOA,cAAG,UAAK,cAAeA,cAAAA,MAAI,eAAe,sBAAsB,KAAK,KAAM;AAClG,MAAC,uBAAuB,OAAO,mBAAmB,uBAAuB,2CAA2C;;;;;;;;"} \ No newline at end of file diff --git a/frontend/unpackage/dist/dev/.sourcemap/mp-weixin/common/constants.js.map b/frontend/unpackage/dist/dev/.sourcemap/mp-weixin/common/constants.js.map index 2232667..87e94d3 100644 --- a/frontend/unpackage/dist/dev/.sourcemap/mp-weixin/common/constants.js.map +++ b/frontend/unpackage/dist/dev/.sourcemap/mp-weixin/common/constants.js.map @@ -1 +1 @@ -{"version":3,"file":"constants.js","sources":["common/constants.js"],"sourcesContent":["// 统一常量配置:其他收入/支出分类,禁止在业务中硬编码\r\nexport const INCOME_CATEGORIES = [\r\n\t{ key: 'sale_income', label: '销售收入' },\r\n\t{ key: 'operation_income', label: '经营所得' },\r\n\t{ key: 'interest_income', label: '利息收入' },\r\n\t{ key: 'investment_income', label: '投资收入' },\r\n\t{ key: 'other_income', label: '其它收入' }\r\n]\r\n\r\nexport const EXPENSE_CATEGORIES = [\r\n\t{ key: 'operation_expense', label: '经营支出' },\r\n\t{ key: 'office_supplies', label: '办公用品' },\r\n\t{ key: 'rent', label: '房租' },\r\n\t{ key: 'interest_expense', label: '利息支出' },\r\n\t{ key: 'other_expense', label: '其它支出' }\r\n]\r\n\r\n// 路由常量(集中管理页面路径,避免在业务中硬编码)\r\nexport const ROUTES = {\r\n\thome: '/pages/index/index',\r\n\tproductList: '/pages/product/list',\r\n\tproductForm: '/pages/product/form',\r\n\tproductSelect: '/pages/product/select',\r\n\tproductSettings: '/pages/product/settings',\r\n\torderCreate: '/pages/order/create',\r\n\tdetail: '/pages/detail/index',\r\n\tmy: '/pages/my/index',\r\n\tmyAbout: '/pages/my/about',\r\n\tmyVip: '/pages/my/vip',\r\n\treport: '/pages/report/index',\r\n\tcustomerSelect: '/pages/customer/select',\r\n\tsupplierSelect: '/pages/supplier/select',\r\n\taccountSelect: '/pages/account/select'\r\n}\r\n\r\n\r\n// 本地存储键:统一管理,避免在业务中散落硬编码\r\nexport const STORAGE_KEYS = {\r\n\tVIP_IS_VIP: 'USER_VIP_IS_VIP',\r\n\tVIP_START: 'USER_VIP_START',\r\n\tVIP_END: 'USER_VIP_END'\r\n}\r\n\r\n\r\n"],"names":[],"mappings":";AACY,MAAC,oBAAoB;AAAA,EAChC,EAAE,KAAK,eAAe,OAAO,OAAQ;AAAA,EACrC,EAAE,KAAK,oBAAoB,OAAO,OAAQ;AAAA,EAC1C,EAAE,KAAK,mBAAmB,OAAO,OAAQ;AAAA,EACzC,EAAE,KAAK,qBAAqB,OAAO,OAAQ;AAAA,EAC3C,EAAE,KAAK,gBAAgB,OAAO,OAAQ;AACvC;AAEY,MAAC,qBAAqB;AAAA,EACjC,EAAE,KAAK,qBAAqB,OAAO,OAAQ;AAAA,EAC3C,EAAE,KAAK,mBAAmB,OAAO,OAAQ;AAAA,EACzC,EAAE,KAAK,QAAQ,OAAO,KAAM;AAAA,EAC5B,EAAE,KAAK,oBAAoB,OAAO,OAAQ;AAAA,EAC1C,EAAE,KAAK,iBAAiB,OAAO,OAAQ;AACxC;AAGY,MAAC,SAAS;AAAA,EACrB,MAAM;AAAA,EACN,aAAa;AAAA,EACb,aAAa;AAAA,EACb,eAAe;AAAA,EACf,iBAAiB;AAAA,EACjB,aAAa;AAAA,EACb,QAAQ;AAAA,EACR,IAAI;AAAA,EACJ,SAAS;AAAA,EACT,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,gBAAgB;AAAA,EAChB,gBAAgB;AAAA,EAChB,eAAe;AAChB;;;;"} \ No newline at end of file +{"version":3,"file":"constants.js","sources":["common/constants.js"],"sourcesContent":["// 统一常量配置:其他收入/支出分类,禁止在业务中硬编码\nexport const INCOME_CATEGORIES = [\n\t{ key: 'sale_income', label: '销售收入' },\n\t{ key: 'operation_income', label: '经营所得' },\n\t{ key: 'interest_income', label: '利息收入' },\n\t{ key: 'investment_income', label: '投资收入' },\n\t{ key: 'other_income', label: '其它收入' }\n]\n\nexport const EXPENSE_CATEGORIES = [\n\t{ key: 'operation_expense', label: '经营支出' },\n\t{ key: 'office_supplies', label: '办公用品' },\n\t{ key: 'rent', label: '房租' },\n\t{ key: 'interest_expense', label: '利息支出' },\n\t{ key: 'other_expense', label: '其它支出' }\n]\n\n// 路由常量(集中管理页面路径,避免在业务中硬编码)\nexport const ROUTES = {\n\thome: '/pages/index/index',\n\tproductList: '/pages/product/list',\n\tproductForm: '/pages/product/form',\n\tproductSelect: '/pages/product/select',\n\tproductSettings: '/pages/product/settings',\n\torderCreate: '/pages/order/create',\n\tdetail: '/pages/detail/index',\n\tmy: '/pages/my/index',\n\tmyAbout: '/pages/my/about',\n\tmyVip: '/pages/my/vip',\n\treport: '/pages/report/index',\n\tcustomerSelect: '/pages/customer/select',\n\tsupplierSelect: '/pages/supplier/select',\n\taccountSelect: '/pages/account/select'\n}\n\n\n// 本地存储键:统一管理,避免在业务中散落硬编码\nexport const STORAGE_KEYS = {\n\tVIP_IS_VIP: 'USER_VIP_IS_VIP',\n\tVIP_START: 'USER_VIP_START',\n\tVIP_END: 'USER_VIP_END'\n}\n\n\n// KPI 标签常量,避免页面硬编码\nexport const KPI_LABELS = {\n todaySales: '今日销售额',\n monthSales: '本月销售额',\n monthProfit: '本月利润',\n stockCount: '库存量'\n}\n\n"],"names":[],"mappings":";AACY,MAAC,oBAAoB;AAAA,EAChC,EAAE,KAAK,eAAe,OAAO,OAAQ;AAAA,EACrC,EAAE,KAAK,oBAAoB,OAAO,OAAQ;AAAA,EAC1C,EAAE,KAAK,mBAAmB,OAAO,OAAQ;AAAA,EACzC,EAAE,KAAK,qBAAqB,OAAO,OAAQ;AAAA,EAC3C,EAAE,KAAK,gBAAgB,OAAO,OAAQ;AACvC;AAEY,MAAC,qBAAqB;AAAA,EACjC,EAAE,KAAK,qBAAqB,OAAO,OAAQ;AAAA,EAC3C,EAAE,KAAK,mBAAmB,OAAO,OAAQ;AAAA,EACzC,EAAE,KAAK,QAAQ,OAAO,KAAM;AAAA,EAC5B,EAAE,KAAK,oBAAoB,OAAO,OAAQ;AAAA,EAC1C,EAAE,KAAK,iBAAiB,OAAO,OAAQ;AACxC;AAGY,MAAC,SAAS;AAAA,EACrB,MAAM;AAAA,EACN,aAAa;AAAA,EACb,aAAa;AAAA,EACb,eAAe;AAAA,EACf,iBAAiB;AAAA,EACjB,aAAa;AAAA,EACb,QAAQ;AAAA,EACR,IAAI;AAAA,EACJ,SAAS;AAAA,EACT,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,gBAAgB;AAAA,EAChB,gBAAgB;AAAA,EAChB,eAAe;AAChB;AAYY,MAAC,aAAa;AAAA,EACtB,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,aAAa;AAAA,EACb,YAAY;AAChB;;;;;"} \ No newline at end of file diff --git a/frontend/unpackage/dist/dev/.sourcemap/mp-weixin/pages/auth/login.js.map b/frontend/unpackage/dist/dev/.sourcemap/mp-weixin/pages/auth/login.js.map index 549cee8..83a6d4e 100644 --- a/frontend/unpackage/dist/dev/.sourcemap/mp-weixin/pages/auth/login.js.map +++ b/frontend/unpackage/dist/dev/.sourcemap/mp-weixin/pages/auth/login.js.map @@ -1 +1 @@ -{"version":3,"file":"login.js","sources":["pages/auth/login.vue","../../../../Downloads/HBuilderX.4.76.2025082103/HBuilderX/plugins/uniapp-cli-vite/uniPage:/cGFnZXMvYXV0aC9sb2dpbi52dWU"],"sourcesContent":["\n\n\n\n\n","import MiniProgramPage from 'C:/Users/21826/Desktop/Wj/PartsInquiry/frontend/pages/auth/login.vue'\nwx.createPage(MiniProgramPage)"],"names":["uni","post"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"login.js","sources":["pages/auth/login.vue","../../../../Downloads/HBuilderX.4.76.2025082103/HBuilderX/plugins/uniapp-cli-vite/uniPage:/cGFnZXMvYXV0aC9sb2dpbi52dWU"],"sourcesContent":["\n\n\n\n\n","import MiniProgramPage from 'C:/Users/21826/Desktop/Wj/PartsInquiry/frontend/pages/auth/login.vue'\nwx.createPage(MiniProgramPage)"],"names":["AUTH_LOGIN_TOP_IMAGE","uni","post"],"mappings":"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"} \ No newline at end of file diff --git a/frontend/unpackage/dist/dev/.sourcemap/mp-weixin/pages/index/index.js.map b/frontend/unpackage/dist/dev/.sourcemap/mp-weixin/pages/index/index.js.map index 6221fa8..afdbb01 100644 --- a/frontend/unpackage/dist/dev/.sourcemap/mp-weixin/pages/index/index.js.map +++ b/frontend/unpackage/dist/dev/.sourcemap/mp-weixin/pages/index/index.js.map @@ -1 +1 @@ -{"version":3,"file":"index.js","sources":["pages/index/index.vue","../../../../Downloads/HBuilderX.4.76.2025082103/HBuilderX/plugins/uniapp-cli-vite/uniPage:/cGFnZXMvaW5kZXgvaW5kZXgudnVl"],"sourcesContent":["\n\n\n\n\n","import MiniProgramPage from 'C:/Users/21826/Desktop/Wj/PartsInquiry/frontend/pages/index/index.vue'\nwx.createPage(MiniProgramPage)"],"names":["KPI_ICON_MAP","uni","get","put","post","ROUTES"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"index.js","sources":["pages/index/index.vue","../../../../Downloads/HBuilderX.4.76.2025082103/HBuilderX/plugins/uniapp-cli-vite/uniPage:/cGFnZXMvaW5kZXgvaW5kZXgudnVl"],"sourcesContent":["\n\n\n\n\n","import MiniProgramPage from 'C:/Users/21826/Desktop/Wj/PartsInquiry/frontend/pages/index/index.vue'\nwx.createPage(MiniProgramPage)"],"names":["KPI_ICON_MAP","KPI_LABELS","uni","get","put","post","ROUTES"],"mappings":"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"} \ No newline at end of file diff --git a/frontend/unpackage/dist/dev/.sourcemap/mp-weixin/pages/my/index.js.map b/frontend/unpackage/dist/dev/.sourcemap/mp-weixin/pages/my/index.js.map index 915e6d2..45b6a30 100644 --- a/frontend/unpackage/dist/dev/.sourcemap/mp-weixin/pages/my/index.js.map +++ b/frontend/unpackage/dist/dev/.sourcemap/mp-weixin/pages/my/index.js.map @@ -1 +1 @@ -{"version":3,"file":"index.js","sources":["pages/my/index.vue","../../../../Downloads/HBuilderX.4.76.2025082103/HBuilderX/plugins/uniapp-cli-vite/uniPage:/cGFnZXMvbXkvaW5kZXgudnVl"],"sourcesContent":["\n\n\n\n\n\n\n","import MiniProgramPage from 'C:/Users/21826/Desktop/Wj/PartsInquiry/frontend/pages/my/index.vue'\nwx.createPage(MiniProgramPage)"],"names":["API_BASE_URL","uni","get"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"index.js","sources":["pages/my/index.vue","../../../../Downloads/HBuilderX.4.76.2025082103/HBuilderX/plugins/uniapp-cli-vite/uniPage:/cGFnZXMvbXkvaW5kZXgudnVl"],"sourcesContent":["\n\n\n\n\n\n\n","import MiniProgramPage from 'C:/Users/21826/Desktop/Wj/PartsInquiry/frontend/pages/my/index.vue'\nwx.createPage(MiniProgramPage)"],"names":["API_BASE_URL","uni","get"],"mappings":"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"} \ No newline at end of file diff --git a/frontend/unpackage/dist/dev/.sourcemap/mp-weixin/pages/my/vip.js.map b/frontend/unpackage/dist/dev/.sourcemap/mp-weixin/pages/my/vip.js.map index 9851fe9..c00d6dd 100644 --- a/frontend/unpackage/dist/dev/.sourcemap/mp-weixin/pages/my/vip.js.map +++ b/frontend/unpackage/dist/dev/.sourcemap/mp-weixin/pages/my/vip.js.map @@ -1 +1 @@ -{"version":3,"file":"vip.js","sources":["pages/my/vip.vue","../../../../Downloads/HBuilderX.4.76.2025082103/HBuilderX/plugins/uniapp-cli-vite/uniPage:/cGFnZXMvbXkvdmlwLnZ1ZQ"],"sourcesContent":["\n\n\n\n\n\n\n","import MiniProgramPage from 'C:/Users/21826/Desktop/Wj/PartsInquiry/frontend/pages/my/vip.vue'\nwx.createPage(MiniProgramPage)"],"names":["get","post","uni"],"mappings":";;;;AA+DA,MAAK,YAAU;AAAA,EACd,OAAM;AACL,WAAO;AAAA,MACG,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,OAAO;AAAA,MAChB,UAAU,CAAC;AAAA,IACZ;AAAA,EACA;AAAA,EACD,SAAQ;AACP,SAAK,QAAQ;AACb,SAAK,gBAAgB;AAAA,EACrB;AAAA,EACD,UAAU;AAAA,IACT,gBAAe;AACd,YAAM,IAAI,OAAO,KAAK,UAAU,EAAE;AAClC,aAAO,KAAK;AAAA,IACZ;AAAA,IACD,eAAc;AACb,YAAM,IAAI,OAAO,KAAK,KAAK;AAC3B,aAAO,OAAO,SAAS,CAAC,KAAK,IAAI,IAAI,EAAE,QAAQ,CAAC,IAAI;AAAA,IACrD;AAAA,EACA;AAAA,EACD,SAAS;AAAA,IACR,kBAAiB;AAChB,WAAK,WAAW;AAAA,QACf,EAAE,KAAK,WAAW,OAAO,UAAU,MAAM,mBAAmB,MAAM,2CAA4C;AAAA,QAC9G,EAAE,KAAK,YAAY,OAAO,UAAU,MAAM,mBAAmB,MAAM,qCAAsC;AAAA,QACzG,EAAE,KAAK,YAAY,OAAO,UAAU,MAAM,kBAAkB,MAAM,4CAA4C;AAAA,MAC/G;AAAA,IACA;AAAA,IACK,MAAM,UAAS;AACX,UAAI;AACA,cAAM,OAAO,MAAMA,YAAG,IAAC,iBAAiB;AACxC,aAAK,QAAQ,CAAC,EAAC,6BAAM;AACrB,aAAK,UAAS,6BAAM,aAAY;AAChC,YAAI,QAAO,6BAAM,WAAU;AAAU,eAAK,QAAQ,KAAK;AAAA,MAC3D,SAAQ,GAAG;AAEP,aAAK,QAAQ;AAAA,MACjB;AAAA,IACT;AAAA,IACK,MAAM,QAAO;AACT,UAAI;AACA,cAAMC,YAAI,KAAC,gBAAgB,EAAE;AAC7BC,sBAAG,MAAC,UAAU,EAAE,OAAO,UAAU,MAAM,WAAW;AAClD,cAAM,KAAK,QAAQ;AAAA,MACvB,SAAQ,GAAG;AACPA,sBAAAA,MAAI,UAAU,EAAE,OAAO,OAAO,EAAE,WAAW,MAAM,GAAG,MAAM,QAAQ;AAAA,MACtE;AAAA,IACV;AAAA,EACD;AACD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AClHA,GAAG,WAAW,eAAe;"} \ No newline at end of file +{"version":3,"file":"vip.js","sources":["pages/my/vip.vue","../../../../Downloads/HBuilderX.4.76.2025082103/HBuilderX/plugins/uniapp-cli-vite/uniPage:/cGFnZXMvbXkvdmlwLnZ1ZQ"],"sourcesContent":["\n\n\n\n\n\n\n","import MiniProgramPage from 'C:/Users/21826/Desktop/Wj/PartsInquiry/frontend/pages/my/vip.vue'\nwx.createPage(MiniProgramPage)"],"names":["m","get","post","uni"],"mappings":"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"} \ No newline at end of file diff --git a/frontend/unpackage/dist/dev/.sourcemap/mp-weixin/pages/product/detail.js.map b/frontend/unpackage/dist/dev/.sourcemap/mp-weixin/pages/product/detail.js.map new file mode 100644 index 0000000..67e8a2a --- /dev/null +++ b/frontend/unpackage/dist/dev/.sourcemap/mp-weixin/pages/product/detail.js.map @@ -0,0 +1 @@ +{"version":3,"file":"detail.js","sources":["pages/product/detail.vue","../../../../Downloads/HBuilderX.4.76.2025082103/HBuilderX/plugins/uniapp-cli-vite/uniPage:/cGFnZXMvcHJvZHVjdC9kZXRhaWwudnVl"],"sourcesContent":["\r\n\r\n\r\n\r\n\r\n\r\n\r\n","import MiniProgramPage from 'C:/Users/21826/Desktop/Wj/PartsInquiry/frontend/pages/product/detail.vue'\nwx.createPage(MiniProgramPage)"],"names":["uni","get","post"],"mappings":"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"} \ No newline at end of file diff --git a/frontend/unpackage/dist/dev/.sourcemap/mp-weixin/pages/product/form.js.map b/frontend/unpackage/dist/dev/.sourcemap/mp-weixin/pages/product/form.js.map index 20f5cc3..b3e72ab 100644 --- a/frontend/unpackage/dist/dev/.sourcemap/mp-weixin/pages/product/form.js.map +++ b/frontend/unpackage/dist/dev/.sourcemap/mp-weixin/pages/product/form.js.map @@ -1 +1 @@ -{"version":3,"file":"form.js","sources":["pages/product/form.vue","../../../../Downloads/HBuilderX.4.76.2025082103/HBuilderX/plugins/uniapp-cli-vite/uniPage:/cGFnZXMvcHJvZHVjdC9mb3JtLnZ1ZQ"],"sourcesContent":["