安评报告修改

dev-tmp1
huwei 2026-08-11 18:02:35 +08:00
parent 9342ab42d3
commit 3ec4e15e6b
32 changed files with 794 additions and 287 deletions

BIN
build_log.txt Normal file

Binary file not shown.

87
docs/db-diff/README.md Normal file
View File

@ -0,0 +1,87 @@
# 本地库 vs 线上库 结构差异分析报告
| 项目 | 信息 |
| --- | --- |
| 本地库 | `192.168.20.100:33080` / `safety-eval-service` |
| 线上库 | `nlb-kd2xz70qhllfet2koj.cn-beijing.nlb.aliyuncsslb.com:33068` / `safety-eval-service` |
| 分析时间 | 2026-08-11 |
| 执行动作 | 仅 `SELECT information_schema` 只读查询,**未对线上做任何变更** |
## 一、总体结论
| 检查项 | 结果 |
| --- | --- |
| 本地表数 / 线上表数 | 60 / 60 |
| 线上缺表 | **0** |
| 线上多表 | 0 |
| 线上缺字段 | **8**(全部集中在 `org_info` |
| 线上多字段 | 0 |
| 字段定义不一致 | **3** |
| 线上缺索引 | 0 |
整体差异很小,核心问题是 `org_info` 表缺少一批「原型 V1.6」新增字段。
## 二、线上缺失字段(`org_info`8 个)
均为可空、无默认值,补齐对存量数据无影响。
| 字段 | 类型 | 可空 | 说明 |
| --- | --- | --- | --- |
| `qualification_cert_no` | varchar(100) | 是 | 资质证书编号 |
| `fax` | varchar(20) | 是 | 传真 |
| `contact_name` | varchar(50) | 是 | 联系人(由 `contact_name_phone` 拆分) |
| `contact_phone` | varchar(20) | 是 | 联系电话(由 `contact_name_phone` 拆分) |
| `contact_name_phone` | varchar(100) | 是 | 联系人及电话 |
| `fixed_assets_total` | decimal(16,4) | 是 | 固定资产总值(万元) |
| `apply_business_scope` | varchar(500) | 是 | 拟申请的法定安全评价业务范围 |
| `org_intro` | text | 是 | 单位基本情况介绍 |
> 注:本地同时存在拆分后的 `contact_name` / `contact_phone` 与合并的 `contact_name_phone`,属于过渡期并存。是否三者全部上线,建议结合业务代码确认后再定。
## 三、字段定义不一致3 处)
### 1. `eval_process_control.reviewer_signature_task_status` — 可安全对齐
仅注释文案不同,类型 `varchar(64)`、`NOT NULL`、默认值 `non_dispatched` 均一致。
- 线上:`审核签字任务状态 ...`
- 本地:`过程控制审核签字任务状态 ...`
### 2 & 3. `org_info` 两个行业类别字段 — 存在数据截断风险,不建议改线上
| 字段 | 线上 | 本地 |
| --- | --- | --- |
| `safety_industry_category_code` | varchar(512) | varchar(32) |
| `safety_industry_category_name` | varchar(1024) | varchar(50) |
**线上字段比本地更宽**,而非缺失或落后。实测线上存量数据:
| 字段 | 最大长度 | 超出本地长度的行数 |
| --- | --- | --- |
| `safety_industry_category_code` | 110 | 2 行 > 32 |
| `safety_industry_category_name` | 57 | 1 行 > 50 |
本地对应数据最大长度仅 25 / 14说明本地只是从未触发过加宽需求。
**结论:若按本地定义收窄线上,会直接截断线上真实数据,造成不可逆丢失。**
正确做法是反向对齐——把本地改宽到与线上一致,相关语句已在 SQL 文件第五节给出。
## 四、索引
线上不存在缺失索引,无需处理。
## 五、交付物
| 文件 | 用途 |
| --- | --- |
| `online_schema_upgrade.sql` | 升级 SQL含备份、执行、校验风险项已注释隔离 |
| `schema_diff.json` | 结构化差异明细 |
| `compare_schema.py` | 只读对比脚本,可重复执行复核 |
## 六、执行建议
1. 先备份 `org_info`SQL 第一节)。
2. 执行第二节补字段、第三节对齐注释——这两项无数据风险。
3. 第四节保持注释状态,**不要在线上执行**。
4. 第五节在本地库执行,消除最后的长度差异。
5. 用第六节语句校验结果。

View File

@ -0,0 +1,159 @@
# -*- coding: utf-8 -*-
"""
只读对比本地库 vs 线上库 结构差异并生成升级 SQL
本脚本仅对 information_schema 执行 SELECT 查询绝不修改线上数据库
"""
import json
import pymysql
SCHEMA = "safety-eval-service"
LOCAL = dict(host="192.168.20.100", port=33080,
user="root", password="Mysql@zcloud33080")
ONLINE = dict(host="nlb-kd2xz70qhllfet2koj.cn-beijing.nlb.aliyuncsslb.com",
port=33068, user="root", password="5tS3owZ7w8Uk1egv")
COL_SQL = """
SELECT TABLE_NAME, COLUMN_NAME, ORDINAL_POSITION, COLUMN_TYPE, IS_NULLABLE,
COLUMN_DEFAULT, EXTRA, COLUMN_COMMENT, CHARACTER_SET_NAME, COLLATION_NAME
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA=%s
ORDER BY TABLE_NAME, ORDINAL_POSITION
"""
TBL_SQL = """
SELECT TABLE_NAME, ENGINE, TABLE_COLLATION, TABLE_COMMENT
FROM information_schema.TABLES
WHERE TABLE_SCHEMA=%s AND TABLE_TYPE='BASE TABLE'
ORDER BY TABLE_NAME
"""
IDX_SQL = """
SELECT TABLE_NAME, INDEX_NAME, NON_UNIQUE, SEQ_IN_INDEX, COLUMN_NAME, INDEX_TYPE
FROM information_schema.STATISTICS
WHERE TABLE_SCHEMA=%s
ORDER BY TABLE_NAME, INDEX_NAME, SEQ_IN_INDEX
"""
def fetch(conn_args):
conn = pymysql.connect(charset="utf8mb4", **conn_args)
try:
with conn.cursor(pymysql.cursors.DictCursor) as cur:
cur.execute(TBL_SQL, (SCHEMA,))
tables = {r["TABLE_NAME"]: r for r in cur.fetchall()}
cur.execute(COL_SQL, (SCHEMA,))
cols = {}
for r in cur.fetchall():
cols.setdefault(r["TABLE_NAME"], {})[r["COLUMN_NAME"]] = r
cur.execute(IDX_SQL, (SCHEMA,))
idx = {}
for r in cur.fetchall():
idx.setdefault(r["TABLE_NAME"], {}).setdefault(
r["INDEX_NAME"], []).append(r)
finally:
conn.close()
return tables, cols, idx
def q(name):
return "`%s`" % name
def col_def(c):
"""根据本地列定义拼出 DDL 片段。"""
parts = [q(c["COLUMN_NAME"]), c["COLUMN_TYPE"]]
if c["CHARACTER_SET_NAME"] and c["COLLATION_NAME"]:
# 保持与表默认字符集一致,通常无需显式声明,这里省略以免冲突
pass
parts.append("NOT NULL" if c["IS_NULLABLE"] == "NO" else "NULL")
default = c["COLUMN_DEFAULT"]
extra = (c["EXTRA"] or "")
if default is not None:
up = str(default).upper()
if up in ("CURRENT_TIMESTAMP", "CURRENT_TIMESTAMP()") or \
up.startswith("CURRENT_TIMESTAMP(") or extra.upper().startswith("DEFAULT_GENERATED"):
parts.append("DEFAULT %s" % default)
else:
parts.append("DEFAULT '%s'" % str(default).replace("'", "''"))
elif c["IS_NULLABLE"] == "YES":
parts.append("DEFAULT NULL")
extra_clean = extra.replace("DEFAULT_GENERATED", "").strip()
if extra_clean:
parts.append(extra_clean.upper())
if c["COLUMN_COMMENT"]:
parts.append("COMMENT '%s'" % c["COLUMN_COMMENT"].replace("'", "''"))
return " ".join(parts)
def main():
l_tbl, l_col, l_idx = fetch(LOCAL)
o_tbl, o_col, o_idx = fetch(ONLINE)
report = {
"local_table_count": len(l_tbl),
"online_table_count": len(o_tbl),
"missing_tables": sorted(set(l_tbl) - set(o_tbl)),
"extra_tables": sorted(set(o_tbl) - set(l_tbl)),
"missing_columns": [],
"extra_columns": [],
"diff_columns": [],
"missing_indexes": [],
}
for t in sorted(set(l_tbl) & set(o_tbl)):
lc, oc = l_col.get(t, {}), o_col.get(t, {})
for name in lc:
if name not in oc:
report["missing_columns"].append(
{"table": t, "column": name, "def": col_def(lc[name]),
"pos": lc[name]["ORDINAL_POSITION"]})
for name in oc:
if name not in lc:
report["extra_columns"].append({"table": t, "column": name,
"type": oc[name]["COLUMN_TYPE"]})
for name in lc:
if name not in oc:
continue
a, b = lc[name], oc[name]
diffs = {}
if a["COLUMN_TYPE"] != b["COLUMN_TYPE"]:
diffs["type"] = [b["COLUMN_TYPE"], a["COLUMN_TYPE"]]
if a["IS_NULLABLE"] != b["IS_NULLABLE"]:
diffs["nullable"] = [b["IS_NULLABLE"], a["IS_NULLABLE"]]
if (a["COLUMN_DEFAULT"] or "") != (b["COLUMN_DEFAULT"] or ""):
diffs["default"] = [b["COLUMN_DEFAULT"], a["COLUMN_DEFAULT"]]
if (a["EXTRA"] or "") != (b["EXTRA"] or ""):
diffs["extra"] = [b["EXTRA"], a["EXTRA"]]
if (a["COLUMN_COMMENT"] or "") != (b["COLUMN_COMMENT"] or ""):
diffs["comment"] = [b["COLUMN_COMMENT"], a["COLUMN_COMMENT"]]
if diffs:
report["diff_columns"].append(
{"table": t, "column": name, "diffs": diffs,
"def": col_def(a)})
li, oi = l_idx.get(t, {}), o_idx.get(t, {})
for iname, rows in li.items():
if iname == "PRIMARY":
continue
if iname not in oi:
report["missing_indexes"].append({
"table": t, "index": iname,
"unique": rows[0]["NON_UNIQUE"] == 0,
"columns": [r["COLUMN_NAME"] for r in rows]})
with open("schema_diff.json", "w", encoding="utf-8") as f:
json.dump(report, f, ensure_ascii=False, indent=2, default=str)
print("本地表数:", report["local_table_count"],
" 线上表数:", report["online_table_count"])
print("线上缺表:", len(report["missing_tables"]), report["missing_tables"])
print("线上多表:", len(report["extra_tables"]), report["extra_tables"])
print("线上缺字段:", len(report["missing_columns"]))
print("线上多字段:", len(report["extra_columns"]))
print("字段定义不一致:", len(report["diff_columns"]))
print("线上缺索引:", len(report["missing_indexes"]))
if __name__ == "__main__":
main()

View File

@ -0,0 +1,80 @@
-- =============================================================================
-- 线上数据库结构升级 SQLsafety-eval-service
--
-- 对比基准:本地库 192.168.20.100:33080 / safety-eval-service
-- 目标库 nlb-kd2xz70qhllfet2koj.cn-beijing.nlb.aliyuncsslb.com:33068 / safety-eval-service
-- 生成时间2026-08-11
--
-- 【重要】本文件仅供人工评审,尚未在任何环境执行。
-- 执行前请务必先备份 org_info 表。
-- =============================================================================
USE `safety-eval-service`;
-- -----------------------------------------------------------------------------
-- 一、备份(强烈建议,执行 DDL 前先跑)
-- -----------------------------------------------------------------------------
-- CREATE TABLE `org_info_bak_20260811` LIKE `org_info`;
-- INSERT INTO `org_info_bak_20260811` SELECT * FROM `org_info`;
-- -----------------------------------------------------------------------------
-- 二、补齐线上缺失字段org_info共 8 个,均为原型 V1.6 新增)
-- 全部为可空且无默认值,对存量数据无影响,可安全执行。
-- -----------------------------------------------------------------------------
ALTER TABLE `org_info`
ADD COLUMN `qualification_cert_no` varchar(100) NULL DEFAULT NULL COMMENT '资质证书编号2026-08-08 原型V1.6新增,非必填)' AFTER `env`,
ADD COLUMN `fax` varchar(20) NULL DEFAULT NULL COMMENT '传真2026-08-08 原型V1.6新增)' AFTER `qualification_cert_no`,
ADD COLUMN `contact_name` varchar(50) NULL DEFAULT NULL COMMENT '联系人2026-08-08 由 contact_name_phone 拆分)' AFTER `fax`,
ADD COLUMN `contact_phone` varchar(20) NULL DEFAULT NULL COMMENT '联系电话2026-08-08 由 contact_name_phone 拆分)' AFTER `contact_name`,
ADD COLUMN `contact_name_phone` varchar(100) NULL DEFAULT NULL COMMENT '联系人及电话2026-08-08 原型V1.6新增)' AFTER `contact_phone`,
ADD COLUMN `fixed_assets_total` decimal(16,4) NULL DEFAULT NULL COMMENT '固定资产总值万元非负2026-08-08 原型V1.6新增)' AFTER `contact_name_phone`,
ADD COLUMN `apply_business_scope` varchar(500) NULL DEFAULT NULL COMMENT '拟申请的法定安全评价业务范围多选逗号分隔2026-08-08 原型V1.6新增)' AFTER `fixed_assets_total`,
ADD COLUMN `org_intro` text NULL COMMENT '单位基本情况介绍长文本2026-08-08 原型V1.6新增)' AFTER `apply_business_scope`;
-- -----------------------------------------------------------------------------
-- 三、字段注释对齐eval_process_control
-- 仅注释文案不同,类型/长度/可空性均一致,无数据风险。
-- -----------------------------------------------------------------------------
ALTER TABLE `eval_process_control`
MODIFY COLUMN `reviewer_signature_task_status` varchar(64) NOT NULL DEFAULT 'non_dispatched'
COMMENT '过程控制审核签字任务状态 dispatched 下发non_dispatched 未下发 , completed 已完成';
-- =============================================================================
-- 四、【不建议执行】org_info 两个字段的长度差异
--
-- safety_industry_category_code线上 varchar(512) 本地 varchar(32)
-- safety_industry_category_name线上 varchar(1024) 本地 varchar(50)
--
-- 线上字段比本地更宽。实测线上存量数据:
-- - code 最大长度 110其中 2 条 > 32
-- - name 最大长度 57 其中 1 条 > 50
-- 若按本地定义收窄,将直接截断线上真实数据,造成不可逆的数据丢失。
--
-- 结论:应反向以线上为准,把【本地】改宽以与线上保持一致,
-- 而不是把线上改窄。以下语句仅作留档,禁止在线上执行。
--
-- ALTER TABLE `org_info`
-- MODIFY COLUMN `safety_industry_category_code` varchar(32) NULL DEFAULT NULL COMMENT '安全生产监管行业类别编码',
-- MODIFY COLUMN `safety_industry_category_name` varchar(50) NULL DEFAULT NULL COMMENT '安全生产监管行业类别名称';
-- =============================================================================
-- =============================================================================
-- 五、建议在【本地库】执行(使本地向线上看齐,消除该项差异)
--
-- ALTER TABLE `org_info`
-- MODIFY COLUMN `safety_industry_category_code` varchar(512) NULL DEFAULT NULL COMMENT '安全生产监管行业类别编码',
-- MODIFY COLUMN `safety_industry_category_name` varchar(1024) NULL DEFAULT NULL COMMENT '安全生产监管行业类别名称';
-- =============================================================================
-- -----------------------------------------------------------------------------
-- 六、执行后校验
-- -----------------------------------------------------------------------------
-- SELECT COLUMN_NAME, COLUMN_TYPE, IS_NULLABLE, COLUMN_COMMENT
-- FROM information_schema.COLUMNS
-- WHERE TABLE_SCHEMA='safety-eval-service' AND TABLE_NAME='org_info'
-- ORDER BY ORDINAL_POSITION;

View File

@ -0,0 +1,93 @@
{
"local_table_count": 60,
"online_table_count": 60,
"missing_tables": [],
"extra_tables": [],
"missing_columns": [
{
"table": "org_info",
"column": "qualification_cert_no",
"def": "`qualification_cert_no` varchar(100) NULL DEFAULT NULL COMMENT '资质证书编号2026-08-08 原型V1.6新增,非必填)'",
"pos": 57
},
{
"table": "org_info",
"column": "fax",
"def": "`fax` varchar(20) NULL DEFAULT NULL COMMENT '传真2026-08-08 原型V1.6新增)'",
"pos": 58
},
{
"table": "org_info",
"column": "contact_name",
"def": "`contact_name` varchar(50) NULL DEFAULT NULL COMMENT '联系人2026-08-08 由 contact_name_phone 拆分)'",
"pos": 59
},
{
"table": "org_info",
"column": "contact_phone",
"def": "`contact_phone` varchar(20) NULL DEFAULT NULL COMMENT '联系电话2026-08-08 由 contact_name_phone 拆分)'",
"pos": 60
},
{
"table": "org_info",
"column": "contact_name_phone",
"def": "`contact_name_phone` varchar(100) NULL DEFAULT NULL COMMENT '联系人及电话2026-08-08 原型V1.6新增)'",
"pos": 61
},
{
"table": "org_info",
"column": "fixed_assets_total",
"def": "`fixed_assets_total` decimal(16,4) NULL DEFAULT NULL COMMENT '固定资产总值万元非负2026-08-08 原型V1.6新增)'",
"pos": 62
},
{
"table": "org_info",
"column": "apply_business_scope",
"def": "`apply_business_scope` varchar(500) NULL DEFAULT NULL COMMENT '拟申请的法定安全评价业务范围多选逗号分隔2026-08-08 原型V1.6新增)'",
"pos": 63
},
{
"table": "org_info",
"column": "org_intro",
"def": "`org_intro` text NULL DEFAULT NULL COMMENT '单位基本情况介绍长文本2026-08-08 原型V1.6新增)'",
"pos": 64
}
],
"extra_columns": [],
"diff_columns": [
{
"table": "eval_process_control",
"column": "reviewer_signature_task_status",
"diffs": {
"comment": [
"审核签字任务状态 dispatched 下发non_dispatched 未下发 , completed 已完成",
"过程控制审核签字任务状态 dispatched 下发non_dispatched 未下发 , completed 已完成"
]
},
"def": "`reviewer_signature_task_status` varchar(64) NOT NULL DEFAULT 'non_dispatched' COMMENT '过程控制审核签字任务状态 dispatched 下发non_dispatched 未下发 , completed 已完成'"
},
{
"table": "org_info",
"column": "safety_industry_category_code",
"diffs": {
"type": [
"varchar(512)",
"varchar(32)"
]
},
"def": "`safety_industry_category_code` varchar(32) NULL DEFAULT NULL COMMENT '安全生产监管行业类别编码'"
},
{
"table": "org_info",
"column": "safety_industry_category_name",
"diffs": {
"type": [
"varchar(1024)",
"varchar(50)"
]
},
"def": "`safety_industry_category_name` varchar(50) NULL DEFAULT NULL COMMENT '安全生产监管行业类别名称'"
}
],
"missing_indexes": []
}

View File

@ -5,10 +5,12 @@ import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.qinan.safetyeval.client.api.institution.InstitutionEvalReportApi;
import org.qinan.safetyeval.client.co.report.EvalReportLibraryCO;
import org.qinan.safetyeval.client.co.report.InstitutionEvalReportBatchSubmitResultCO;
import org.qinan.safetyeval.client.co.report.InstitutionEvalReportSummaryCO;
import org.qinan.safetyeval.client.dto.PageResponse;
import org.qinan.safetyeval.client.dto.SingleResponse;
import org.qinan.safetyeval.client.dto.institution.InstitutionEvalReportAddCmd;
import org.qinan.safetyeval.client.dto.institution.InstitutionEvalReportBatchSubmitCmd;
import org.qinan.safetyeval.client.dto.institution.InstitutionEvalReportPageQuery;
import org.qinan.safetyeval.client.dto.institution.InstitutionEvalReportSubmitCmd;
import org.springframework.validation.annotation.Validated;
@ -53,4 +55,11 @@ public class InstitutionEvalReportController {
public SingleResponse<EvalReportLibraryCO> submit(@Validated @RequestBody InstitutionEvalReportSubmitCmd cmd) {
return institutionEvalReportApi.submit(cmd);
}
@ApiOperation("批量报送监管(未报送 → 已报送,支持部分成功)")
@PostMapping("/submit/batch")
public SingleResponse<InstitutionEvalReportBatchSubmitResultCO> batchSubmit(
@Validated @RequestBody InstitutionEvalReportBatchSubmitCmd cmd) {
return institutionEvalReportApi.batchSubmit(cmd);
}
}

View File

@ -8,8 +8,11 @@ import org.qinan.safetyeval.client.dto.PageResponse;
import org.qinan.safetyeval.client.dto.SingleResponse;
import org.qinan.safetyeval.client.dto.institution.InstitutionEvalReportAddCmd;
import org.qinan.safetyeval.client.dto.institution.InstitutionEvalReportPageQuery;
import org.qinan.safetyeval.client.co.report.InstitutionEvalReportBatchSubmitResultCO;
import org.qinan.safetyeval.client.dto.institution.InstitutionEvalReportSubmitCmd;
import org.qinan.safetyeval.client.dto.institution.InstitutionEvalReportBatchSubmitCmd;
import org.qinan.safetyeval.domain.entity.EvalReportEntity;
import org.qinan.safetyeval.domain.exception.BizException;
import org.qinan.safetyeval.domain.exception.ErrorCode;
import org.qinan.safetyeval.domain.query.EvalReportQuery;
import org.qinan.safetyeval.domain.query.PageResult;
@ -21,6 +24,8 @@ import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import java.time.LocalDate;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.stream.Collectors;
@Service
@ -108,6 +113,46 @@ public class InstitutionEvalReportExecutor implements InstitutionEvalReportApi {
return SingleResponse.success(ReportProfileCoConverter.toReportCO(result));
}
/**
* 2026-08-11
* submit
*
* 1) id submitToRegulator EVAL_REPORT_ALREADY_SUBMITTED
* 2) /// failList
* 3) 便
*/
@Override
public SingleResponse<InstitutionEvalReportBatchSubmitResultCO> batchSubmit(InstitutionEvalReportBatchSubmitCmd cmd) {
InstitutionEvalReportBatchSubmitResultCO result = new InstitutionEvalReportBatchSubmitResultCO();
if (cmd == null || cmd.getIds() == null || cmd.getIds().isEmpty()) {
throw new BizException(ErrorCode.EVAL_REPORT_BATCH_EMPTY);
}
// 变更时间2026-08-11 入参去重,避免同一报告被提交两次
Set<Long> distinctIds = new LinkedHashSet<>(cmd.getIds());
for (Long id : distinctIds) {
try {
EvalReportEntity existing = evalReportDomainService.get(id);
institutionOrgSupport.assertOrgAccess(existing.getOrgId(), ErrorCode.EVAL_REPORT_ORG_MISMATCH);
EvalReportEntity submitted = evalReportDomainService.submitToRegulator(id);
result.getSuccessList().add(ReportProfileCoConverter.toReportCO(submitted));
} catch (BizException be) {
addFail(result, id, be.getMessage());
} catch (Exception e) {
addFail(result, id, "报送失败:" + e.getMessage());
}
}
result.setSuccessCount(result.getSuccessList().size());
result.setFailCount(result.getFailList().size());
return SingleResponse.success(result);
}
private void addFail(InstitutionEvalReportBatchSubmitResultCO result, Long id, String reason) {
InstitutionEvalReportBatchSubmitResultCO.FailItem item = new InstitutionEvalReportBatchSubmitResultCO.FailItem();
item.setId(id);
item.setReason(reason);
result.getFailList().add(item);
}
private void applyDisplayStatus(EvalReportQuery query, String displayStatus, Integer reportStatusCode) {
if (StringUtils.hasText(displayStatus)) {
String status = displayStatus.trim().toUpperCase();

View File

@ -1,10 +1,12 @@
package org.qinan.safetyeval.client.api.institution;
import org.qinan.safetyeval.client.co.report.EvalReportLibraryCO;
import org.qinan.safetyeval.client.co.report.InstitutionEvalReportBatchSubmitResultCO;
import org.qinan.safetyeval.client.co.report.InstitutionEvalReportSummaryCO;
import org.qinan.safetyeval.client.dto.PageResponse;
import org.qinan.safetyeval.client.dto.SingleResponse;
import org.qinan.safetyeval.client.dto.institution.InstitutionEvalReportAddCmd;
import org.qinan.safetyeval.client.dto.institution.InstitutionEvalReportBatchSubmitCmd;
import org.qinan.safetyeval.client.dto.institution.InstitutionEvalReportPageQuery;
import org.qinan.safetyeval.client.dto.institution.InstitutionEvalReportSubmitCmd;
@ -19,4 +21,10 @@ public interface InstitutionEvalReportApi {
SingleResponse<EvalReportLibraryCO> add(InstitutionEvalReportAddCmd cmd);
SingleResponse<EvalReportLibraryCO> submit(InstitutionEvalReportSubmitCmd cmd);
/**
* 2026-08-11
* submit
*/
SingleResponse<InstitutionEvalReportBatchSubmitResultCO> batchSubmit(InstitutionEvalReportBatchSubmitCmd cmd);
}

View File

@ -0,0 +1,38 @@
package org.qinan.safetyeval.client.co.report;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
/**
*
*
* <p>2026-08-11</p>
* <p>/便
* //</p>
*/
@Data
public class InstitutionEvalReportBatchSubmitResultCO {
@ApiModelProperty(value = "成功报送条数")
private int successCount;
@ApiModelProperty(value = "失败条数")
private int failCount;
@ApiModelProperty(value = "成功报送的报告视图列表")
private List<EvalReportLibraryCO> successList = new ArrayList<>();
@ApiModelProperty(value = "失败明细报告ID -> 失败原因")
private List<FailItem> failList = new ArrayList<>();
@Data
public static class FailItem {
@ApiModelProperty(value = "失败的报告ID")
private Long id;
@ApiModelProperty(value = "失败原因")
private String reason;
}
}

View File

@ -0,0 +1,25 @@
package org.qinan.safetyeval.client.dto.institution;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.List;
/**
*
*
* <p>2026-08-11</p>
* <p> submit
* </p>
* <p> EvalReportDomainService.submitToRegulator
* EVAL_REPORT_ALREADY_SUBMITTED</p>
*/
@Data
public class InstitutionEvalReportBatchSubmitCmd {
@NotEmpty(message = "报告ID集合不能为空")
@ApiModelProperty(value = "待报送报告主键集合(仅支持「未报送」报告)", required = true)
private List<@NotNull(message = "报告ID不能为空") Long> ids;
}

View File

@ -1,4 +1,4 @@
<!doctype html><html lang="zh"><head data-built-info="@cqsjjb/scripts@2.0.0-rspack.2 Frontend_Env[production] Build_Date[2026/8/5 14:13:14] App_Identifier[safetyEval-h5]"><meta charset="UTF-8"/><meta name="renderer" content="webkit"/><meta http-equiv="X-UA-Compatible" content="IE=edge,Chrome=1"/><meta name="viewport" content="width=device-width,minimum-scale=1,maximum-scale=1,user-scalable=no,viewport-fit=cover"><meta charset="UTF-8" name="referrer" content="strict-origin-when-cross-origin"/><title>注册</title><script>(function () {
<!doctype html><html lang="zh"><head data-built-info="@cqsjjb/scripts@2.0.0-rspack.2 Frontend_Env[production] Build_Date[2026/8/11 14:10:31] App_Identifier[safetyEval-h5]"><meta charset="UTF-8"/><meta name="renderer" content="webkit"/><meta http-equiv="X-UA-Compatible" content="IE=edge,Chrome=1"/><meta name="viewport" content="width=device-width,minimum-scale=1,maximum-scale=1,user-scalable=no,viewport-fit=cover"><meta charset="UTF-8" name="referrer" content="strict-origin-when-cross-origin"/><title>注册</title><script>(function () {
const APP_ENV = {
antd: {
'ant-prefix': 'micro-temp',
@ -126,4 +126,4 @@
}
mergeParams();
})();
})();</script><script defer="defer" src="/safetyEval-h5/static/js/325.73c909fb4b7ba287.js"></script><script defer="defer" src="/safetyEval-h5/static/js/930.c071827086472787.js"></script><script defer="defer" src="/safetyEval-h5/static/js/997.9a421c4109ce8ab7.js"></script><script defer="defer" src="/safetyEval-h5/static/js/main.83bb2462d6099cf3.js"></script><link href="/safetyEval-h5/static/css/main.485b414ca5d6de25.css" rel="stylesheet"></head><body><noscript>此网页需要开启JavaScript功能。</noscript><div id="root" style="width: 100%; height: 100%; position: relative;overflow-y: auto;"></div><script type="text/javascript">/* @cqsjjb/script 输出当前应用基本信息 */console.log("%c@cqsjjb/scripts@2.0.0-rspack.2 Frontend_Env[production] Build_Date[2026/8/5 14:13:14] App_Identifier[safetyEval-h5] Frontend_Branch[dev] Backend_Branch[<branch-name>]", "color: #1890ff; border-radius: 2px; padding: 0 4px; border: 1px solid #1890ff; background: #f9fcff")</script></body><script src="https://cesium.com/downloads/cesiumjs/releases/1.91/Build/Cesium/Cesium.js"></script><link href="https://cesium.com/downloads/cesiumjs/releases/1.91/Build/Cesium/Widgets/widgets.css" rel="stylesheet"></html>
})();</script><script defer="defer" src="/safetyEval-h5/static/js/33.826ba7bce17f692b.js"></script><script defer="defer" src="/safetyEval-h5/static/js/509.37fefdea880bd79c.js"></script><script defer="defer" src="/safetyEval-h5/static/js/554.dce5d48939bcb600.js"></script><script defer="defer" src="/safetyEval-h5/static/js/main.cac46dc57d12de0f.js"></script><link href="/safetyEval-h5/static/css/main.aeb5d93e210e3449.css" rel="stylesheet"></head><body><noscript>此网页需要开启JavaScript功能。</noscript><div id="root" style="width: 100%; height: 100%; position: relative;overflow-y: auto;"></div><script type="text/javascript">/* @cqsjjb/script 输出当前应用基本信息 */console.log("%c@cqsjjb/scripts@2.0.0-rspack.2 Frontend_Env[production] Build_Date[2026/8/11 14:10:31] App_Identifier[safetyEval-h5] Frontend_Branch[dev-tmp1] Backend_Branch[<branch-name>]", "color: #1890ff; border-radius: 2px; padding: 0 4px; border: 1px solid #1890ff; background: #f9fcff")</script></body><script src="https://cesium.com/downloads/cesiumjs/releases/1.91/Build/Cesium/Cesium.js"></script><link href="https://cesium.com/downloads/cesiumjs/releases/1.91/Build/Cesium/Widgets/widgets.css" rel="stylesheet"></html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,4 +1,4 @@
<!doctype html><html lang="zh"><head data-built-info="@cqsjjb/scripts@2.0.0-rspack.3 Frontend_Env[production] Build_Date[2026/8/7 10:54:09] App_Identifier[safetyEval]"><meta charset="UTF-8"/><meta name="renderer" content="webkit"/><meta http-equiv="X-UA-Compatible" content="IE=edge,Chrome=1"/><meta name="viewport" content="width=device-width,minimum-scale=1,maximum-scale=1,user-scalable=no,viewport-fit=cover"><title>--</title><script>(function () {
<!doctype html><html lang="zh"><head data-built-info="@cqsjjb/scripts@2.0.0-rspack.3 Frontend_Env[production] Build_Date[2026/8/11 14:09:28] App_Identifier[safetyEval]"><meta charset="UTF-8"/><meta name="renderer" content="webkit"/><meta http-equiv="X-UA-Compatible" content="IE=edge,Chrome=1"/><meta name="viewport" content="width=device-width,minimum-scale=1,maximum-scale=1,user-scalable=no,viewport-fit=cover"><title>--</title><script>(function () {
const APP_ENV = {
antd: {
'ant-prefix': 'micro-temp',
@ -89,4 +89,4 @@
},
}
}</script><script defer="defer" src="/safetyEval/static/js/839.7be94e9f9e3a7d36.js"></script><script defer="defer" src="/safetyEval/static/js/101.3b5adf63ead4365d.js"></script><script defer="defer" src="/safetyEval/static/js/479.74f05548bf67e219.js"></script><script defer="defer" src="/safetyEval/static/js/main.3f3dd26de476266b.js"></script><link href="/safetyEval/static/css/main.5ca34e4215ba28a7.css" rel="stylesheet"></head><body><noscript>此网页需要开启JavaScript功能。</noscript><div id="root" style="width: 100%; height: 100%; position: relative;overflow-y: auto"></div><script type="text/javascript">/* @cqsjjb/script 输出当前应用基本信息 */console.log("%c@cqsjjb/scripts@2.0.0-rspack.3 Frontend_Env[production] Build_Date[2026/8/7 10:54:09] App_Identifier[safetyEval] Frontend_Branch[dev] Backend_Branch[dev]", "color: #1890ff; border-radius: 2px; padding: 0 4px; border: 1px solid #1890ff; background: #f9fcff")</script></body></html>
}</script><script defer="defer" src="/safetyEval/static/js/839.bcb7133530b5a949.js"></script><script defer="defer" src="/safetyEval/static/js/376.edf49837adea7bf5.js"></script><script defer="defer" src="/safetyEval/static/js/419.9f92da006b7be853.js"></script><script defer="defer" src="/safetyEval/static/js/479.ada5b7b837d8d37e.js"></script><script defer="defer" src="/safetyEval/static/js/main.ad05d9b885be96e9.js"></script><link href="/safetyEval/static/css/main.a70edbd2a3f67acc.css" rel="stylesheet"></head><body><noscript>此网页需要开启JavaScript功能。</noscript><div id="root" style="width: 100%; height: 100%; position: relative;overflow-y: auto"></div><script type="text/javascript">/* @cqsjjb/script 输出当前应用基本信息 */console.log("%c@cqsjjb/scripts@2.0.0-rspack.3 Frontend_Env[production] Build_Date[2026/8/11 14:09:28] App_Identifier[safetyEval] Frontend_Branch[dev-tmp1] Backend_Branch[dev]", "color: #1890ff; border-radius: 2px; padding: 0 4px; border: 1px solid #1890ff; background: #f9fcff")</script></body></html>

View File

@ -1 +1 @@
module.exports={javaGit:"http://47.92.113.182:3000/cq_anquan/safety-eval-service.git",javaGitName:"safety-eval-service",environment:{development:{javaGitBranch:"dev",API_HOST:"http://192.168.0.103"},production:{javaGitBranch:"dev",API_HOST:""}},appIdentifier:"safetyEval",contextInject:{appKey:"",fileUrl:"https://skqhdg.porthebei.com:9004/file/uploadFiles2/"},windowInject:{title:"微应用模板",links:[],element:{root:{id:"root"}},scripts:[]},server:{port:"8081",host:"192.168.0.187",open:!1},framework:{antd:{"ant-prefix":"micro-temp",fontFamily:"PingFangSC-Regular",colorPrimary:"#1677ff",borderRadius:2}},webpackConfig:{htmlWebpackPluginOption:{inject:!0},resolve:{fallback:{stream:!1}}}};
module.exports={javaGit:"http://47.92.113.182:3000/cq_anquan/safety-eval-service.git",javaGitName:"safety-eval-service",environment:{development:{javaGitBranch:"dev",API_HOST:"https://gbs-gateway.qhdsafety.com"},production:{javaGitBranch:"dev",API_HOST:""}},appIdentifier:"safetyEval",contextInject:{appKey:"",fileUrl:"https://skqhdg.porthebei.com:9004/file/uploadFiles2/"},windowInject:{title:"微应用模板",links:[],element:{root:{id:"root"}},scripts:[]},server:{port:"8081",host:"192.168.0.187",open:!1},framework:{antd:{"ant-prefix":"micro-temp",fontFamily:"PingFangSC-Regular",colorPrimary:"#1677ff",borderRadius:2}},webpackConfig:{htmlWebpackPluginOption:{inject:!0},resolve:{fallback:{stream:!1}}}};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -33,6 +33,8 @@
"dayjs": "^1.11.7",
"echarts": "^6.1.0",
"history": "^4.10.1",
"html2canvas": "^1.4.1",
"jspdf": "^2.5.2",
"lodash-es": "^4.17.21",
"react": "^18.2.0",
"react-dom": "^18.2.0",