Jelajahi Sumber

chore(s0): remove demo and AI seed markers from customer-facing data

演示数据在名称、说明、备注、编码、创建人等字段里留下了种子标记,
客户演示时会直接出现在列表列与编辑表单中,等于自曝「这是演示/测试数据」。
本次统一改成正常业务表述。

【第一部分 · S0 文案】租户 UATTEST_CHL 与 AIDOP
  [DEMO] 纵割                     -> 纵割
  [DEMO] S0 演示技能字典            -> 工序技能主数据
  [DEMO]数控组                    -> 数控组
  DEMO-ELEM-01                  -> ELEM-01
  DEMO-SOP-WI                   -> SOP-WI(ImageType 与 QualitySegmentImage 同步改,二者以此列关联)
  demo://s0/sop/DEMO-SOP-WI/... -> /sop/SOP-WI/...
  S0DEMO_UAT_A                  -> A 区货架(按货架号首字母生成)
  S0DEMO_BATCH1_20260825 电压转换工序生产要素 -> 电压转换工序生产要素
  S0 演示数据,按单生产订单物料计划周期  -> 按单生产订单物料计划周期
  S0 演示数据,口径取自 AIDOP 真实字典  -> 检验类型基础字典
  UAT_DEMO_SEED / S0-DEMO-SEED  -> admin(本库真实主流取值,789 行在用)

【第二部分 · 质量域 AI 标记】不限租户
  [AI测试]游标卡尺 -> 游标卡尺 ;[AI测试]OP10 -> OP10 ;[AI测试]每批 -> 每批 …
  少数去前缀后仍留「演示」的按同表真实取值改写:
    [AI测试]演示物料   -> 1AB6753 / 1AB6755 / A2C1149
    [AI测试]演示型号A  -> EEUE6000 主机全系列 等
    [AI测试]示范厂商   -> —(同表真实取值)
  fj2 整串即标记,去掉后为空 -> NULL
  含被列长截断成 `测试]演示型号I` 的残留

范围与取舍:
- 绝大多数只做「去前缀」——底层名称本身已是真实工艺用语,不编造新内容
- 主子表关联键为内部 glid,wlbm / syxh 不参与关联,改动不影响主子关系
- 事前做过引用完整性检查:待改编码中仅 DEMO-SOP-EQ/QC/WI 三个跨表,已同批同步
- **不含** UATDEMO 租户的 DEMO- 单据号体系(跨十余表引用的业务主键,风险过高)
- **不含** UATD- 前缀与账号名(AIDOPDemo / Demo01,改它等于伪造审计记录)
- **不含** 默认租户与 AIDOP-Demo 的 AI_SEED / AI-S0-* 业务键(这两个租户不用于演示)

实测:影响 539 行,事务内校验 34/34 通过后提交,新连接复验 34/34,幂等复跑 0 行。
演示租户 UATTEST_CHL 残留由 31 组降为 0 组。

chore: bump version server 1.0.420
YY968XX 1 hari lalu
induk
melakukan
7748325523

+ 9 - 3
server/Admin.NET.Web.Entry/Admin.NET.Web.Entry.csproj

@@ -11,9 +11,9 @@
     <GenerateSatelliteAssembliesForCore>true</GenerateSatelliteAssembliesForCore>
     <Copyright>Admin.NET</Copyright>
     <Description>Admin.NET 通用权限开发平台</Description>
-    <AssemblyVersion>1.0.419</AssemblyVersion>
-    <FileVersion>1.0.419</FileVersion>
-    <Version>1.0.419</Version>
+    <AssemblyVersion>1.0.420</AssemblyVersion>
+    <FileVersion>1.0.420</FileVersion>
+    <Version>1.0.420</Version>
   </PropertyGroup>
 
   <ItemGroup>
@@ -577,6 +577,12 @@
     <None Update="UpdateScripts\1.0.412.verify.sql">
       <CopyToOutputDirectory>Always</CopyToOutputDirectory>
     </None>
+    <None Update="UpdateScripts\1.0.420.sql">
+      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+    </None>
+    <None Update="UpdateScripts\1.0.420.verify.sql">
+      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+    </None>
   </ItemGroup>
 
   <ItemGroup>

+ 307 - 0
server/Admin.NET.Web.Entry/UpdateScripts/1.0.420.sql

@@ -0,0 +1,307 @@
+-- ===========================================================================
+-- S0 演示/种子文案清理
+--
+-- 背景:S0 的演示数据在名称、说明、备注、编码、创建人等字段里留下了
+--       `[DEMO]` / `DEMO-` / `S0DEMO_` / `S0 演示数据,…` / `*_DEMO_SEED`
+--       这类种子标记。客户演示时这些内容会直接出现在列表列与编辑表单里,
+--       等于自曝「这是演示/测试数据」。本脚本把它们改成正常的业务表述。
+--
+-- 范围:分两部分。
+--   第一部分(01-12):S0 运营建模相关表,租户 = UATTEST_CHL 与 AIDOP。
+--   第二部分(20-23):质量域的 `[AI测试]` 标记,不限租户
+--                     (实际分布在系统默认租户与 AIDOP 租户;UATTEST_CHL 无命中)。
+--
+--   **不含**:UATDEMO 租户(838257237606469)的 DEMO- 单据号体系。
+--   那批是跨十余张表引用的业务单据主键(DEMO-PO / DEMO-WO / DEMO-SO …),
+--   改动风险远高于文案,且该租户本身即名为 UATDEMO,本次按决定不动。
+--   **不含**:账号名(AIDOPDemo / Demo01 等),改它等于伪造审计记录。
+--
+-- 手法:绝大多数只做「去前缀」——底层名称本身已是真实工艺用语
+--       (纵割 / 工中核心 / 工作压力 / 前处理-涂覆 / 作业指导书 …),
+--       去掉标记即为正常业务数据,不需要编造新内容。
+--       整句自曝的备注则改写为中性业务描述。
+--
+-- 幂等:每条 UPDATE 都带 LIKE 条件,重跑影响行数为 0。
+-- 关联:ImageType.image_type_id 与 QualitySegmentImage.image_type_id 是关联键,
+--       两处必须同批同步改,否则断关联。
+-- ===========================================================================
+
+SET @t_uat := (SELECT t.Id FROM SysTenant t JOIN SysOrg o ON o.Id = t.OrgId WHERE o.Code = 'UATTEST_CHL' AND t.Status = 1 LIMIT 1);
+SET @t_aid := (SELECT t.Id FROM SysTenant t JOIN SysOrg o ON o.Id = t.OrgId WHERE o.Code = 'AIDOP'       AND t.Status = 1 LIMIT 1);
+
+
+-- ---------------------------------------------------------------------------
+-- 01 · 人员技能:名称与备注
+--      `[DEMO] 纵割` → `纵割`;备注整句改写
+-- ---------------------------------------------------------------------------
+UPDATE PersonSkill SET Name = TRIM(REPLACE(REPLACE(Name, '[DEMO] ', ''), '[DEMO]', ''))
+WHERE tenant_id IN (@t_uat, @t_aid) AND Name LIKE '%[DEMO]%';
+
+UPDATE PersonSkill SET Remark = '工序技能主数据'
+WHERE tenant_id IN (@t_uat, @t_aid) AND (Remark LIKE '%[DEMO]%' OR Remark LIKE '%演示%');
+
+
+-- ---------------------------------------------------------------------------
+-- 02 · 员工技能:技能描述与工作组
+-- ---------------------------------------------------------------------------
+UPDATE EmpSkills SET SkillDescription = TRIM(REPLACE(REPLACE(SkillDescription, '[DEMO] ', ''), '[DEMO]', ''))
+WHERE tenant_id IN (@t_uat, @t_aid) AND SkillDescription LIKE '%[DEMO]%';
+
+UPDATE EmpSkills SET Site = TRIM(REPLACE(REPLACE(Site, '[DEMO] ', ''), '[DEMO]', ''))
+WHERE tenant_id IN (@t_uat, @t_aid) AND Site LIKE '%[DEMO]%';
+
+
+-- ---------------------------------------------------------------------------
+-- 03 · 生产要素监控(DevMonitor):描述去前缀、编码去 DEMO-
+--      DEMO-ELEM-01 → ELEM-01 ;DEMO-TEMP → TEMP
+-- ---------------------------------------------------------------------------
+UPDATE DevMonitor SET CodeDescr = TRIM(REPLACE(REPLACE(CodeDescr, '[DEMO] ', ''), '[DEMO]', ''))
+WHERE tenant_id IN (@t_uat, @t_aid) AND CodeDescr LIKE '%[DEMO]%';
+
+UPDATE DevMonitor SET DeviceDescr = TRIM(REPLACE(REPLACE(DeviceDescr, '[DEMO] ', ''), '[DEMO]', ''))
+WHERE tenant_id IN (@t_uat, @t_aid) AND DeviceDescr LIKE '%[DEMO]%';
+
+UPDATE DevMonitor SET DeviceNumber = REPLACE(DeviceNumber, 'DEMO-', '')
+WHERE tenant_id IN (@t_uat, @t_aid) AND DeviceNumber LIKE 'DEMO-%';
+
+UPDATE DevMonitor SET MessageCode = REPLACE(MessageCode, 'DEMO-', '')
+WHERE tenant_id IN (@t_uat, @t_aid) AND MessageCode LIKE 'DEMO-%';
+
+
+-- ---------------------------------------------------------------------------
+-- 04 · 前处理要素与参数
+--      DEMO-PRE-01 → PRE-01 ;DEMO-CLEAN → CLEAN ;DEMO-PRE-ELEM-01 → PRE-ELEM-01
+-- ---------------------------------------------------------------------------
+UPDATE PreprocessElement SET descr = TRIM(REPLACE(REPLACE(descr, '[DEMO] ', ''), '[DEMO]', ''))
+WHERE tenant_id IN (@t_uat, @t_aid) AND descr LIKE '%[DEMO]%';
+
+UPDATE PreprocessElement SET item_code = REPLACE(item_code, 'DEMO-', '')
+WHERE tenant_id IN (@t_uat, @t_aid) AND item_code LIKE 'DEMO-%';
+
+UPDATE PreprocessElement SET typed = REPLACE(typed, 'DEMO-', '')
+WHERE tenant_id IN (@t_uat, @t_aid) AND typed LIKE 'DEMO-%';
+
+UPDATE PreprocessElementParam SET code_descr = TRIM(REPLACE(REPLACE(code_descr, '[DEMO] ', ''), '[DEMO]', ''))
+WHERE tenant_id IN (@t_uat, @t_aid) AND code_descr LIKE '%[DEMO]%';
+
+UPDATE PreprocessElementParam SET device_descr = TRIM(REPLACE(REPLACE(device_descr, '[DEMO] ', ''), '[DEMO]', ''))
+WHERE tenant_id IN (@t_uat, @t_aid) AND device_descr LIKE '%[DEMO]%';
+
+UPDATE PreprocessElementParam SET device_number = REPLACE(device_number, 'DEMO-', '')
+WHERE tenant_id IN (@t_uat, @t_aid) AND device_number LIKE 'DEMO-%';
+
+UPDATE PreprocessElementParam SET message_code = REPLACE(message_code, 'DEMO-', '')
+WHERE tenant_id IN (@t_uat, @t_aid) AND message_code LIKE 'DEMO-%';
+
+
+-- ---------------------------------------------------------------------------
+-- 05 · SOP 文件类型 ↔ 工序图纸(★ image_type_id 是关联键,两表同步改)
+--      DEMO-SOP-WI → SOP-WI ;demo://s0/sop/... → /sop/...
+-- ---------------------------------------------------------------------------
+UPDATE ImageType SET descr = TRIM(REPLACE(REPLACE(descr, '[DEMO] ', ''), '[DEMO]', ''))
+WHERE tenant_id IN (@t_uat, @t_aid) AND descr LIKE '%[DEMO]%';
+
+UPDATE ImageType SET image_type_id = REPLACE(image_type_id, 'DEMO-', '')
+WHERE tenant_id IN (@t_uat, @t_aid) AND image_type_id LIKE 'DEMO-%';
+
+UPDATE QualitySegmentImage SET descr = TRIM(REPLACE(REPLACE(REPLACE(descr, '[DEMO] ', ''), '[DEMO]', ''), '占位', ''))
+WHERE tenant_id IN (@t_uat, @t_aid) AND (descr LIKE '%[DEMO]%' OR descr LIKE '%占位%');
+
+UPDATE QualitySegmentImage SET image_type_id = REPLACE(image_type_id, 'DEMO-', '')
+WHERE tenant_id IN (@t_uat, @t_aid) AND image_type_id LIKE 'DEMO-%';
+
+UPDATE QualitySegmentImage SET path = REPLACE(REPLACE(path, 'demo://s0', ''), 'DEMO-', '')
+WHERE tenant_id IN (@t_uat, @t_aid) AND (path LIKE 'demo://%' OR path LIKE '%DEMO-%');
+
+UPDATE QualitySegmentImage SET rev = REPLACE(rev, 'DEMO-', '')
+WHERE tenant_id IN (@t_uat, @t_aid) AND rev LIKE 'DEMO-%';
+
+
+-- ---------------------------------------------------------------------------
+-- 06 · 条码规则的三段说明
+-- ---------------------------------------------------------------------------
+UPDATE BarCodeNbr SET FirmString1Note = TRIM(REPLACE(REPLACE(FirmString1Note, '[DEMO] ', ''), '[DEMO]', ''))
+WHERE tenant_id IN (@t_uat, @t_aid) AND FirmString1Note LIKE '%[DEMO]%';
+
+UPDATE BarCodeNbr SET FirmString2Note = TRIM(REPLACE(REPLACE(FirmString2Note, '[DEMO] ', ''), '[DEMO]', ''))
+WHERE tenant_id IN (@t_uat, @t_aid) AND FirmString2Note LIKE '%[DEMO]%';
+
+UPDATE BarCodeNbr SET FirmString3Note = TRIM(REPLACE(REPLACE(FirmString3Note, '[DEMO] ', ''), '[DEMO]', ''))
+WHERE tenant_id IN (@t_uat, @t_aid) AND FirmString3Note LIKE '%[DEMO]%';
+
+
+-- ---------------------------------------------------------------------------
+-- 07 · 工序生产要素:去掉批次种子前缀
+--      `S0DEMO_BATCH1_20260825 器械全检工序生产要素` → `器械全检工序生产要素`
+-- ---------------------------------------------------------------------------
+UPDATE ItemOpCondition SET Descr = TRIM(REPLACE(Descr, 'S0DEMO_BATCH1_20260825 ', ''))
+WHERE tenant_id IN (@t_uat, @t_aid) AND Descr LIKE 'S0DEMO%';
+
+
+-- ---------------------------------------------------------------------------
+-- 08 · 库位货架说明
+--      原值整串是种子标记(S0DEMO_UAT_A / S0DEMO_BATCH1_20260825),无可保留内容,
+--      按货架号首字母生成正常说明:A01/A02 → `A 区货架`
+-- ---------------------------------------------------------------------------
+UPDATE LocationShelfMaster SET descr = CONCAT(LEFT(inv_shelf, 1), ' 区货架')
+WHERE tenant_id IN (@t_uat, @t_aid) AND descr LIKE 'S0DEMO%';
+
+
+-- ---------------------------------------------------------------------------
+-- 09 · 仓储任务指派(wms_rwzp)
+-- ---------------------------------------------------------------------------
+UPDATE wms_rwzp SET bz = NULL
+WHERE tenant_id IN (@t_uat, @t_aid) AND (bz LIKE '%[DEMO]%' OR bz LIKE '%演示%');
+
+UPDATE wms_rwzp SET rwlx = TRIM(REPLACE(REPLACE(rwlx, '[DEMO] ', ''), '[DEMO]', ''))
+WHERE tenant_id IN (@t_uat, @t_aid) AND rwlx LIKE '%[DEMO]%';
+
+UPDATE wms_rwzp SET zt = TRIM(REPLACE(REPLACE(zt, '[DEMO] ', ''), '[DEMO]', ''))
+WHERE tenant_id IN (@t_uat, @t_aid) AND zt LIKE '%[DEMO]%';
+
+UPDATE wms_rwzp SET rqpc = REPLACE(rqpc, 'DEMO-', 'RQ-')
+WHERE tenant_id IN (@t_uat, @t_aid) AND rqpc LIKE 'DEMO-%';
+
+
+-- ---------------------------------------------------------------------------
+-- 10 · S0 周期类主数据备注:去掉「S0 演示数据,」自曝前缀
+--      `S0 演示数据,按单生产订单物料计划周期` → `按单生产订单物料计划周期`
+-- ---------------------------------------------------------------------------
+UPDATE S0MaterialPlanCycle SET remarks = TRIM(REPLACE(remarks, 'S0 演示数据,', ''))
+WHERE tenant_id IN (@t_uat, @t_aid) AND remarks LIKE 'S0 演示数据%';
+
+UPDATE S0OrderReviewCycle SET remarks = TRIM(REPLACE(remarks, 'S0 演示数据,', ''))
+WHERE tenant_id IN (@t_uat, @t_aid) AND remarks LIKE 'S0 演示数据%';
+
+UPDATE S0OrderScheduleCycle SET remarks = TRIM(REPLACE(remarks, 'S0 演示数据,', ''))
+WHERE tenant_id IN (@t_uat, @t_aid) AND remarks LIKE 'S0 演示数据%';
+
+-- 品类提前期:整句提到「取自字典」,改写为业务表述
+UPDATE S0CategoryLeadTime SET remarks = '物料属性按品类字典维护'
+WHERE tenant_id IN (@t_uat, @t_aid) AND remarks LIKE '%演示%';
+
+
+-- ---------------------------------------------------------------------------
+-- 11 · 质量基础数据备注:整句自曝(含「取自 AIDOP 真实字典」),逐类改写
+-- ---------------------------------------------------------------------------
+UPDATE qms_quality_base_type SET remark = CONCAT(type_category, '基础字典')
+WHERE tenant_id IN (@t_uat, @t_aid) AND remark LIKE '%演示%';
+
+UPDATE qms_inspectioncrit SET FCOMMENT = '依据类型按检验规范维护;具体文件编号待业务归档后补录'
+WHERE tenant_id IN (@t_uat, @t_aid) AND FCOMMENT LIKE '%演示%';
+
+UPDATE qms_inspectionfreq SET FREMARK = '频率口径按过程检验规范维护'
+WHERE tenant_id IN (@t_uat, @t_aid) AND FREMARK LIKE '%演示%';
+
+UPDATE qms_inspectionstd SET FCOMMENT = '判定表述按检验规范维护'
+WHERE tenant_id IN (@t_uat, @t_aid) AND FCOMMENT LIKE '%演示%';
+
+
+-- ---------------------------------------------------------------------------
+-- 12 · 创建人/修改人的种子标记 → `admin`
+--      `admin` 是本库真实数据里的主流取值(ProductStructureOp 789 行、LineMaster 72 行),
+--      不引入新面孔,也不冒用某个真实工号。
+-- ---------------------------------------------------------------------------
+UPDATE CostCtrMaster        SET CreateUser  = 'admin' WHERE tenant_id IN (@t_uat, @t_aid) AND CreateUser  LIKE '%DEMO_SEED%';
+UPDATE EmpWorkDutyMaster    SET CreateUser  = 'admin' WHERE tenant_id IN (@t_uat, @t_aid) AND CreateUser  LIKE '%DEMO_SEED%';
+UPDATE EmployeeMaster       SET CreateUser  = 'admin' WHERE tenant_id IN (@t_uat, @t_aid) AND CreateUser  LIKE '%DEMO_SEED%';
+UPDATE EmployeeMaster       SET UpdateUser  = 'admin' WHERE tenant_id IN (@t_uat, @t_aid) AND UpdateUser  LIKE '%DEMO_SEED%';
+UPDATE NbrTypeMaster        SET CreateUser  = 'admin' WHERE tenant_id IN (@t_uat, @t_aid) AND CreateUser  LIKE '%DEMO_SEED%';
+UPDATE WorkCtrMaster        SET UpdateUser  = 'admin' WHERE tenant_id IN (@t_uat, @t_aid) AND UpdateUser  LIKE '%DEMO_SEED%';
+UPDATE LocationShelfMaster  SET create_user = 'admin' WHERE tenant_id IN (@t_uat, @t_aid) AND create_user LIKE '%DEMO_SEED%';
+UPDATE S0CategoryLeadTime   SET create_user = 'admin' WHERE tenant_id IN (@t_uat, @t_aid) AND create_user LIKE '%DEMO_SEED%';
+UPDATE S0MaterialPlanCycle  SET create_user = 'admin' WHERE tenant_id IN (@t_uat, @t_aid) AND create_user LIKE '%DEMO_SEED%';
+UPDATE S0OrderReviewCycle   SET create_user = 'admin' WHERE tenant_id IN (@t_uat, @t_aid) AND create_user LIKE '%DEMO_SEED%';
+UPDATE S0OrderScheduleCycle SET create_user = 'admin' WHERE tenant_id IN (@t_uat, @t_aid) AND create_user LIKE '%DEMO_SEED%';
+UPDATE S0ProductDesignCycle SET create_user = 'admin' WHERE tenant_id IN (@t_uat, @t_aid) AND create_user LIKE '%DEMO_SEED%';
+UPDATE ItemSubstituteDetail SET CreateUser  = 'admin' WHERE tenant_id IN (@t_uat, @t_aid) AND CreateUser  LIKE '%DEMO-SEED%';
+
+
+-- ===========================================================================
+-- 第二部分:清除质量域的 `[AI测试]` 标记
+--
+-- 这是本次排查里唯一真正暴露「AI」的字样,分布在:
+--   系统默认租户 1300000000001 —— 质量基础数据 + FQC / OQC 检验规范
+--   AIDOP 租户   797403760988229 —— S6 IPQC 过程检验规范
+-- (UATTEST_CHL 租户 0 命中。)
+--
+-- 绝大多数去掉前缀后就是正常质量术语(游标卡尺 / 每批 / 按图纸依据 / OP10 …);
+-- 少数去前缀后仍留「演示」字样的,按同表真实取值改写。
+-- 主子表以内部 glid 关联,wlbm / syxh 不是关联键,改动不影响主子关系。
+-- ===========================================================================
+
+-- ---------------------------------------------------------------------------
+-- 20 · 质量基础数据(检验方法 / 项目 / 器具 / 频次 / 依据)—— 纯去前缀
+-- ---------------------------------------------------------------------------
+UPDATE qms_inspection_method SET FNAME = REPLACE(FNAME, '[AI测试]', '') WHERE FNAME LIKE '%[AI测试]%';
+UPDATE qms_inspection_method SET FCTRLSTRATEGY = REPLACE(FCTRLSTRATEGY, '[AI测试]', '') WHERE FCTRLSTRATEGY LIKE '%[AI测试]%';
+
+UPDATE qms_inspectionitems SET FNAME = REPLACE(FNAME, '[AI测试]', '') WHERE FNAME LIKE '%[AI测试]%';
+
+UPDATE qms_inspectioninstru SET FNAME  = REPLACE(FNAME,  '[AI测试]', '') WHERE FNAME  LIKE '%[AI测试]%';
+UPDATE qms_inspectioninstru SET FMODEL = REPLACE(FMODEL, '[AI测试]', '') WHERE FMODEL LIKE '%[AI测试]%';
+-- 「示范厂商」也不是真实厂商名,同表真实取值是「—」
+UPDATE qms_inspectioninstru SET FMANUFACTURER = '—' WHERE FMANUFACTURER LIKE '%[AI测试]%';
+
+UPDATE qms_inspectionfreq SET FNAME = REPLACE(FNAME, '[AI测试]', '') WHERE FNAME LIKE '%[AI测试]%';
+
+UPDATE qms_inspectioncrit SET FNAME = REPLACE(FNAME, '[AI测试]', '') WHERE FNAME LIKE '%[AI测试]%';
+UPDATE qms_inspectioncrit SET FCTRLSTRATEGY = REPLACE(FCTRLSTRATEGY, '[AI测试]', '') WHERE FCTRLSTRATEGY LIKE '%[AI测试]%';
+
+UPDATE qms_inspeccrit_entry SET FWORDNAME = REPLACE(FWORDNAME, '[AI测试]', '') WHERE FWORDNAME LIKE '%[AI测试]%';
+UPDATE qms_inspeccrit_entry SET FJ = REPLACE(FJ, '[AI测试]', '') WHERE FJ LIKE '%[AI测试]%';
+
+
+-- ---------------------------------------------------------------------------
+-- 21 · FQC 检验规范(S7)
+--      fj2 整串就是标记,去掉后为空 → 置 NULL(同表真实行本就为空)
+--      wlbm / syxh 去前缀后仍留「演示」→ 按同表真实取值改写
+-- ---------------------------------------------------------------------------
+UPDATE qms_fqcjygf SET fj = REPLACE(fj, '[AI测试]', '') WHERE fj LIKE '%[AI测试]%';
+UPDATE qms_fqcjygf SET fj2 = NULL WHERE fj2 LIKE '%[AI测试]%';
+UPDATE qms_fqcjygf SET wlbm = '1AB6753' WHERE wlbm LIKE '%AI测试%' OR wlbm LIKE '%演示物料%';
+UPDATE qms_fqcjygf SET syxh = 'EEUE6000 主机全系列'          WHERE syxh LIKE '%演示型号A%';
+UPDATE qms_fqcjygf SET syxh = 'EEUE6000 主机全系列(英文欧盟)' WHERE syxh LIKE '%演示型号B%';
+UPDATE qms_fqcjygf SET syxh = '集控备机'                     WHERE syxh LIKE '%演示型号C%';
+
+UPDATE qms_fqcjygfzb SET gxdh = REPLACE(gxdh, '[AI测试]', '') WHERE gxdh LIKE '%[AI测试]%';
+UPDATE qms_fqcjygfzb SET gxmc = REPLACE(gxmc, '[AI测试]', '') WHERE gxmc LIKE '%[AI测试]%';
+UPDATE qms_fqcjygfzb SET jyxm = REPLACE(jyxm, '[AI测试]', '') WHERE jyxm LIKE '%[AI测试]%';
+UPDATE qms_fqcjygfzb SET jyff = REPLACE(jyff, '[AI测试]', '') WHERE jyff LIKE '%[AI测试]%';
+UPDATE qms_fqcjygfzb SET jygg = REPLACE(jygg, '[AI测试]', '') WHERE jygg LIKE '%[AI测试]%';
+UPDATE qms_fqcjygfzb SET jypc = REPLACE(jypc, '[AI测试]', '') WHERE jypc LIKE '%[AI测试]%';
+UPDATE qms_fqcjygfzb SET jsbz = REPLACE(jsbz, '[AI测试]', '') WHERE jsbz LIKE '%[AI测试]%';
+
+
+-- ---------------------------------------------------------------------------
+-- 22 · OQC 出货检验规范
+-- ---------------------------------------------------------------------------
+UPDATE qms_oqcjygf SET fj = REPLACE(fj, '[AI测试]', '') WHERE fj LIKE '%[AI测试]%';
+UPDATE qms_oqcjygf SET fj2 = NULL WHERE fj2 LIKE '%[AI测试]%';
+UPDATE qms_oqcjygf SET wlbm = '1AB6755' WHERE wlbm LIKE '%AI测试%' OR wlbm LIKE '%演示物料%';
+UPDATE qms_oqcjygf SET syxh = 'EEUE6000 主机全系列'          WHERE syxh LIKE '%演示型号A%';
+UPDATE qms_oqcjygf SET syxh = 'EEUE6000 主机全系列(俄罗斯)' WHERE syxh LIKE '%演示型号B%';
+UPDATE qms_oqcjygf SET syxh = 'IFT45PULB'                    WHERE syxh LIKE '%演示型号C%';
+
+UPDATE qms_oqcjygfzb SET gxdh = REPLACE(gxdh, '[AI测试]', '') WHERE gxdh LIKE '%[AI测试]%';
+UPDATE qms_oqcjygfzb SET gxmc = REPLACE(gxmc, '[AI测试]', '') WHERE gxmc LIKE '%[AI测试]%';
+UPDATE qms_oqcjygfzb SET jyxm = REPLACE(jyxm, '[AI测试]', '') WHERE jyxm LIKE '%[AI测试]%';
+UPDATE qms_oqcjygfzb SET jyff = REPLACE(jyff, '[AI测试]', '') WHERE jyff LIKE '%[AI测试]%';
+UPDATE qms_oqcjygfzb SET jygg = REPLACE(jygg, '[AI测试]', '') WHERE jygg LIKE '%[AI测试]%';
+UPDATE qms_oqcjygfzb SET jypc = REPLACE(jypc, '[AI测试]', '') WHERE jypc LIKE '%[AI测试]%';
+UPDATE qms_oqcjygfzb SET jsbz = REPLACE(jsbz, '[AI测试]', '') WHERE jsbz LIKE '%[AI测试]%';
+
+
+-- ---------------------------------------------------------------------------
+-- 23 · IPQC 过程检验规范(S6,AIDOP 租户)
+--      syxh 的历史值被列长截断成 `测试]演示型号I`,需按残留形态匹配
+-- ---------------------------------------------------------------------------
+UPDATE qms_gcjygf SET fj = REPLACE(fj, '[AI测试]', '') WHERE fj LIKE '%[AI测试]%';
+UPDATE qms_gcjygf SET fj2 = NULL WHERE fj2 LIKE '%[AI测试]%';
+UPDATE qms_gcjygf SET wlbm = 'A2C1149' WHERE wlbm LIKE '%AI测试%' OR wlbm LIKE '%演示物料%';
+UPDATE qms_gcjygf SET syxh = 'XXS系列产品'      WHERE syxh LIKE '%演示型号B%';
+UPDATE qms_gcjygf SET syxh = 'S全系列'          WHERE syxh LIKE '%演示型号I%';
+UPDATE qms_gcjygf SET syxh = 'FNDA BMS全系列'   WHERE syxh LIKE '%演示型号S%';
+
+UPDATE qms_gcjygfzb SET gxdh = REPLACE(gxdh, '[AI测试]', '') WHERE gxdh LIKE '%[AI测试]%';
+UPDATE qms_gcjygfzb SET jypc = REPLACE(jypc, '[AI测试]', '') WHERE jypc LIKE '%[AI测试]%';

+ 103 - 0
server/Admin.NET.Web.Entry/UpdateScripts/1.0.420.verify.sql

@@ -0,0 +1,103 @@
+-- ===========================================================================
+-- 演示 / AI 文案清理 VERIFY —— 全部 SELECT 真值标量断言
+-- 核心断言:UATTEST_CHL(客户演示唯一使用的租户)零残留
+-- ===========================================================================
+
+-- ---------- UATTEST_CHL 零残留 ----------
+SELECT COUNT(*) = 0 FROM PersonSkill
+  WHERE tenant_id = (SELECT t.Id FROM SysTenant t JOIN SysOrg o ON o.Id=t.OrgId WHERE o.Code='UATTEST_CHL' AND t.Status=1 LIMIT 1)
+    AND (Name LIKE '%[DEMO]%' OR Remark LIKE '%[DEMO]%' OR Remark LIKE '%演示%');
+
+SELECT COUNT(*) = 0 FROM LocationShelfMaster
+  WHERE tenant_id = (SELECT t.Id FROM SysTenant t JOIN SysOrg o ON o.Id=t.OrgId WHERE o.Code='UATTEST_CHL' AND t.Status=1 LIMIT 1)
+    AND (descr LIKE '%DEMO%' OR create_user LIKE '%DEMO%');
+
+SELECT COUNT(*) = 0 FROM S0MaterialPlanCycle
+  WHERE tenant_id = (SELECT t.Id FROM SysTenant t JOIN SysOrg o ON o.Id=t.OrgId WHERE o.Code='UATTEST_CHL' AND t.Status=1 LIMIT 1)
+    AND (remarks LIKE '%演示%' OR create_user LIKE '%DEMO%');
+
+SELECT COUNT(*) = 0 FROM S0OrderReviewCycle
+  WHERE tenant_id = (SELECT t.Id FROM SysTenant t JOIN SysOrg o ON o.Id=t.OrgId WHERE o.Code='UATTEST_CHL' AND t.Status=1 LIMIT 1)
+    AND (remarks LIKE '%演示%' OR create_user LIKE '%DEMO%');
+
+SELECT COUNT(*) = 0 FROM S0OrderScheduleCycle
+  WHERE tenant_id = (SELECT t.Id FROM SysTenant t JOIN SysOrg o ON o.Id=t.OrgId WHERE o.Code='UATTEST_CHL' AND t.Status=1 LIMIT 1)
+    AND (remarks LIKE '%演示%' OR create_user LIKE '%DEMO%');
+
+SELECT COUNT(*) = 0 FROM S0CategoryLeadTime
+  WHERE tenant_id = (SELECT t.Id FROM SysTenant t JOIN SysOrg o ON o.Id=t.OrgId WHERE o.Code='UATTEST_CHL' AND t.Status=1 LIMIT 1)
+    AND (remarks LIKE '%演示%' OR create_user LIKE '%DEMO%');
+
+SELECT COUNT(*) = 0 FROM S0ProductDesignCycle
+  WHERE tenant_id = (SELECT t.Id FROM SysTenant t JOIN SysOrg o ON o.Id=t.OrgId WHERE o.Code='UATTEST_CHL' AND t.Status=1 LIMIT 1)
+    AND create_user LIKE '%DEMO%';
+
+SELECT COUNT(*) = 0 FROM NbrTypeMaster
+  WHERE tenant_id = (SELECT t.Id FROM SysTenant t JOIN SysOrg o ON o.Id=t.OrgId WHERE o.Code='UATTEST_CHL' AND t.Status=1 LIMIT 1)
+    AND CreateUser LIKE '%DEMO%';
+
+SELECT COUNT(*) = 0 FROM CostCtrMaster
+  WHERE tenant_id = (SELECT t.Id FROM SysTenant t JOIN SysOrg o ON o.Id=t.OrgId WHERE o.Code='UATTEST_CHL' AND t.Status=1 LIMIT 1)
+    AND CreateUser LIKE '%DEMO%';
+
+SELECT COUNT(*) = 0 FROM EmpWorkDutyMaster
+  WHERE tenant_id = (SELECT t.Id FROM SysTenant t JOIN SysOrg o ON o.Id=t.OrgId WHERE o.Code='UATTEST_CHL' AND t.Status=1 LIMIT 1)
+    AND CreateUser LIKE '%DEMO%';
+
+SELECT COUNT(*) = 0 FROM EmployeeMaster
+  WHERE tenant_id = (SELECT t.Id FROM SysTenant t JOIN SysOrg o ON o.Id=t.OrgId WHERE o.Code='UATTEST_CHL' AND t.Status=1 LIMIT 1)
+    AND (CreateUser LIKE '%DEMO%' OR UpdateUser LIKE '%DEMO%');
+
+SELECT COUNT(*) = 0 FROM WorkCtrMaster
+  WHERE tenant_id = (SELECT t.Id FROM SysTenant t JOIN SysOrg o ON o.Id=t.OrgId WHERE o.Code='UATTEST_CHL' AND t.Status=1 LIMIT 1)
+    AND UpdateUser LIKE '%DEMO%';
+
+SELECT COUNT(*) = 0 FROM qms_quality_base_type
+  WHERE tenant_id = (SELECT t.Id FROM SysTenant t JOIN SysOrg o ON o.Id=t.OrgId WHERE o.Code='UATTEST_CHL' AND t.Status=1 LIMIT 1)
+    AND remark LIKE '%演示%';
+
+SELECT COUNT(*) = 0 FROM qms_inspectioncrit
+  WHERE tenant_id = (SELECT t.Id FROM SysTenant t JOIN SysOrg o ON o.Id=t.OrgId WHERE o.Code='UATTEST_CHL' AND t.Status=1 LIMIT 1)
+    AND FCOMMENT LIKE '%演示%';
+
+SELECT COUNT(*) = 0 FROM qms_inspectionfreq
+  WHERE tenant_id = (SELECT t.Id FROM SysTenant t JOIN SysOrg o ON o.Id=t.OrgId WHERE o.Code='UATTEST_CHL' AND t.Status=1 LIMIT 1)
+    AND FREMARK LIKE '%演示%';
+
+SELECT COUNT(*) = 0 FROM qms_inspectionstd
+  WHERE tenant_id = (SELECT t.Id FROM SysTenant t JOIN SysOrg o ON o.Id=t.OrgId WHERE o.Code='UATTEST_CHL' AND t.Status=1 LIMIT 1)
+    AND FCOMMENT LIKE '%演示%';
+
+-- ---------- AIDOP 租户的 S0 文案同样清空 ----------
+SELECT COUNT(*) = 0 FROM PersonSkill
+  WHERE tenant_id = (SELECT t.Id FROM SysTenant t JOIN SysOrg o ON o.Id=t.OrgId WHERE o.Code='AIDOP' AND t.Status=1 LIMIT 1)
+    AND (Name LIKE '%[DEMO]%' OR Remark LIKE '%演示%');
+
+SELECT COUNT(*) = 0 FROM wms_rwzp
+  WHERE tenant_id = (SELECT t.Id FROM SysTenant t JOIN SysOrg o ON o.Id=t.OrgId WHERE o.Code='AIDOP' AND t.Status=1 LIMIT 1)
+    AND (bz LIKE '%[DEMO]%' OR rwlx LIKE '%[DEMO]%' OR zt LIKE '%[DEMO]%' OR rqpc LIKE 'DEMO-%');
+
+SELECT COUNT(*) = 0 FROM DevMonitor
+  WHERE tenant_id = (SELECT t.Id FROM SysTenant t JOIN SysOrg o ON o.Id=t.OrgId WHERE o.Code='AIDOP' AND t.Status=1 LIMIT 1)
+    AND (CodeDescr LIKE '%[DEMO]%' OR DeviceDescr LIKE '%[DEMO]%' OR DeviceNumber LIKE 'DEMO-%' OR MessageCode LIKE 'DEMO-%');
+
+-- ---------- 质量域 [AI测试] 全清(不限租户)----------
+SELECT COUNT(*) = 0 FROM qms_inspection_method WHERE FNAME LIKE '%[AI测试]%' OR FCTRLSTRATEGY LIKE '%[AI测试]%';
+SELECT COUNT(*) = 0 FROM qms_inspectionitems   WHERE FNAME LIKE '%[AI测试]%';
+SELECT COUNT(*) = 0 FROM qms_inspectioninstru  WHERE FNAME LIKE '%[AI测试]%' OR FMODEL LIKE '%[AI测试]%' OR FMANUFACTURER LIKE '%[AI测试]%';
+SELECT COUNT(*) = 0 FROM qms_inspectionfreq    WHERE FNAME LIKE '%[AI测试]%';
+SELECT COUNT(*) = 0 FROM qms_inspectioncrit    WHERE FNAME LIKE '%[AI测试]%' OR FCTRLSTRATEGY LIKE '%[AI测试]%';
+SELECT COUNT(*) = 0 FROM qms_inspeccrit_entry  WHERE FWORDNAME LIKE '%[AI测试]%' OR FJ LIKE '%[AI测试]%';
+SELECT COUNT(*) = 0 FROM qms_fqcjygf   WHERE fj LIKE '%[AI测试]%' OR fj2 LIKE '%[AI测试]%' OR wlbm LIKE '%演示%' OR syxh LIKE '%演示%';
+SELECT COUNT(*) = 0 FROM qms_fqcjygfzb WHERE gxdh LIKE '%[AI测试]%' OR gxmc LIKE '%[AI测试]%' OR jyxm LIKE '%[AI测试]%' OR jyff LIKE '%[AI测试]%' OR jygg LIKE '%[AI测试]%' OR jypc LIKE '%[AI测试]%' OR jsbz LIKE '%[AI测试]%';
+SELECT COUNT(*) = 0 FROM qms_oqcjygf   WHERE fj LIKE '%[AI测试]%' OR fj2 LIKE '%[AI测试]%' OR wlbm LIKE '%演示%' OR syxh LIKE '%演示%';
+SELECT COUNT(*) = 0 FROM qms_oqcjygfzb WHERE gxdh LIKE '%[AI测试]%' OR gxmc LIKE '%[AI测试]%' OR jyxm LIKE '%[AI测试]%' OR jyff LIKE '%[AI测试]%' OR jygg LIKE '%[AI测试]%' OR jypc LIKE '%[AI测试]%' OR jsbz LIKE '%[AI测试]%';
+SELECT COUNT(*) = 0 FROM qms_gcjygf    WHERE fj LIKE '%[AI测试]%' OR fj2 LIKE '%[AI测试]%' OR wlbm LIKE '%演示%' OR syxh LIKE '%演示%';
+SELECT COUNT(*) = 0 FROM qms_gcjygfzb  WHERE gxdh LIKE '%[AI测试]%' OR jypc LIKE '%[AI测试]%';
+
+-- ---------- 只改文案,不增删数据 ----------
+SELECT COUNT(*) = 5  FROM PersonSkill
+  WHERE tenant_id = (SELECT t.Id FROM SysTenant t JOIN SysOrg o ON o.Id=t.OrgId WHERE o.Code='UATTEST_CHL' AND t.Status=1 LIMIT 1);
+SELECT COUNT(*) = 20 FROM LocationShelfMaster
+  WHERE tenant_id = (SELECT t.Id FROM SysTenant t JOIN SysOrg o ON o.Id=t.OrgId WHERE o.Code='UATTEST_CHL' AND t.Status=1 LIMIT 1);
+SELECT COUNT(*) = 808 FROM ProductStructureOp;