diff --git a/docs/操作日志_配送合同草稿编辑修复_20260812.md b/docs/操作日志_配送合同草稿编辑修复_20260812.md
new file mode 100644
index 0000000..4a95e5d
--- /dev/null
+++ b/docs/操作日志_配送合同草稿编辑修复_20260812.md
@@ -0,0 +1,45 @@
+# 配送合同草稿编辑修复操作日志
+
+操作时间:2026-08-12
+操作类型:修改
+影响模块:平台总后台、气站后台、配送点后台的配送合同编辑入口
+
+## 操作前状态
+
+- 平台总后台错把 `contract_status=10(待处理)` 判定为可编辑草稿,导致 `contract_status=0` 的真实草稿无法编辑。
+- 气站和配送点后台没有在编辑入口校验合同业务状态和通用记录状态。
+
+## 具体操作
+
+- 将合同草稿判断修正为 `contract_status=0`。
+- 只允许通用记录状态 `status` 为 `0(草稿)` 或 `1(启用)` 的合同草稿进入编辑。
+- 列表保留编辑按钮,不可编辑时禁用并显示具体原因。
+- 平台总后台直达编辑页复用同一规则拦截。
+- 增加静态回归断言,固定合同状态值、通用状态范围和禁用原因提示。
+
+## 操作后状态
+
+- `contract_status=0` 且 `status∈{0,1}` 的合同可编辑。
+- `contract_status∈{10,11,12,13}` 的合同不可通过通用编辑修改。
+- `status∈{2,3,4}` 的合同不可编辑。
+
+## 代码变更
+
+- `frontend/platform_admin/src/api/resource-page-rules.ts`:修正平台端合同编辑规则。
+- `frontend/platform_admin/scripts/check-resource-pages.mjs`:增加合同编辑规则回归断言。
+- `frontend/gas_admin/src/views/shared/CrudListPage.vue`:增加气站端合同编辑限制和提示。
+- `frontend/delivery_admin/src/views/shared/CrudListPage.vue`:增加配送点端合同编辑限制和提示。
+- `docs/项目文档_标准资源全页管理_v1.0.md`:补充合同双状态编辑规则。
+
+## 验证结果
+
+- 平台总后台 `npm.cmd run resource-pages:check`:通过,共46类详情页、25类新建页和23类编辑页。
+- 平台总后台、气站后台、配送点后台 `npm.cmd run type:check`:全部通过。
+- 平台总后台、气站后台、配送点后台 `npm.cmd run build`:全部通过。
+- 本次变更文件定向 Biome lint:无新增错误;气站和配送点的通用页仍有既有告警。
+- 全量 `npm.cmd run lint`:未通过,被仓库既有的167个告警和2个错误阻断,问题主要位于未修改的模板组件与 Vite 配置,本次不扩大修复范围。
+
+## 风险评估
+
+- 仅收紧前端编辑入口,不修改合同状态数据、后端接口和生命周期动作。
+- 后端仍是权限和合同业务状态的最终校验边界,前端限制不作为安全控制替代。
diff --git a/docs/项目文档_标准资源全页管理_v1.0.md b/docs/项目文档_标准资源全页管理_v1.0.md
index 310aea0..d51527a 100644
--- a/docs/项目文档_标准资源全页管理_v1.0.md
+++ b/docs/项目文档_标准资源全页管理_v1.0.md
@@ -66,7 +66,8 @@ platforms/
- 账户用户名、密码和业务创建编码按服务端 DTO 设为仅创建或只读。
- 工作人员资质所属人员、用户地址所属用户、服务关系所属用户、检修产品等归属字段在编辑时锁定;后端协议必传时只原样回传。
- 智能气阀归属变更使用专属业务动作并提交动作、原因和备注,不混入普通编辑。
-- 配送合同仅草稿可编辑;已完成检修只允许维护备注;系统角色和平台角色权限按当前操作者锁定。
+- 配送合同仅在 `contract_status=0(草稿)` 且通用记录状态为草稿或启用时可编辑;待处理、生效中、已过期、已终止及停用、归档、冻结记录不可通过通用编辑修改。
+- 已完成检修只允许维护备注;系统角色和平台角色权限按当前操作者锁定。
- 保存时只从允许更新字段构造请求,保存后重新读取详情校验服务端结果。
### 4.2 详情内容
diff --git a/frontend/delivery_admin/src/views/shared/CrudListPage.vue b/frontend/delivery_admin/src/views/shared/CrudListPage.vue
index 97d268d..edb450c 100644
--- a/frontend/delivery_admin/src/views/shared/CrudListPage.vue
+++ b/frontend/delivery_admin/src/views/shared/CrudListPage.vue
@@ -76,7 +76,9 @@
账户管理
查看资质
详情
- 编辑
+
+ 编辑
+
审核
删除
@@ -766,6 +768,11 @@ function openCreate() {
}
function openEdit(row: Row) {
+ const reason = recordEditReason(row);
+ if (reason) {
+ Message.warning(reason);
+ return;
+ }
editingIdentity.value = String(row.identity ?? '');
resetForm(row);
formVisible.value = true;
@@ -775,6 +782,17 @@ function isProtectedRecord(row: Row) {
return props.definition.name === 'platform_role' && row.is_system === true;
}
+/** 统一返回合同和系统记录的编辑阻止原因。 */
+function recordEditReason(row: Row) {
+ if (isProtectedRecord(row)) return '系统内置记录不允许编辑';
+ if (props.definition.name !== 'gasorder_contract') return '';
+ if (Number(row.contract_status) !== 0)
+ return '只有草稿状态的合同可以编辑';
+ if (![0, 1].includes(Number(row.status)))
+ return '停用、已归档或已冻结的合同不可编辑';
+ return '';
+}
+
async function openDetail(row: Row) {
try {
detail.value = await resourceApi.detail(
diff --git a/frontend/gas_admin/src/views/shared/CrudListPage.vue b/frontend/gas_admin/src/views/shared/CrudListPage.vue
index 97d268d..edb450c 100644
--- a/frontend/gas_admin/src/views/shared/CrudListPage.vue
+++ b/frontend/gas_admin/src/views/shared/CrudListPage.vue
@@ -76,7 +76,9 @@
账户管理
查看资质
详情
- 编辑
+
+ 编辑
+
审核
删除
@@ -766,6 +768,11 @@ function openCreate() {
}
function openEdit(row: Row) {
+ const reason = recordEditReason(row);
+ if (reason) {
+ Message.warning(reason);
+ return;
+ }
editingIdentity.value = String(row.identity ?? '');
resetForm(row);
formVisible.value = true;
@@ -775,6 +782,17 @@ function isProtectedRecord(row: Row) {
return props.definition.name === 'platform_role' && row.is_system === true;
}
+/** 统一返回合同和系统记录的编辑阻止原因。 */
+function recordEditReason(row: Row) {
+ if (isProtectedRecord(row)) return '系统内置记录不允许编辑';
+ if (props.definition.name !== 'gasorder_contract') return '';
+ if (Number(row.contract_status) !== 0)
+ return '只有草稿状态的合同可以编辑';
+ if (![0, 1].includes(Number(row.status)))
+ return '停用、已归档或已冻结的合同不可编辑';
+ return '';
+}
+
async function openDetail(row: Row) {
try {
detail.value = await resourceApi.detail(
diff --git a/frontend/platform_admin/scripts/check-resource-pages.mjs b/frontend/platform_admin/scripts/check-resource-pages.mjs
index edf026b..4cc7d35 100644
--- a/frontend/platform_admin/scripts/check-resource-pages.mjs
+++ b/frontend/platform_admin/scripts/check-resource-pages.mjs
@@ -62,6 +62,17 @@ for (const marker of [
]) {
if (!displaySource.includes(marker)) fail(`合同详情中文展示缺少 ${marker}`);
}
+for (const marker of [
+ "Number(row.contract_status) !== 0",
+ "![0, 1].includes(Number(row.status))",
+ "只有草稿状态的合同可以编辑",
+ "停用、已归档或已冻结的合同不可编辑",
+]) {
+ if (!ruleSource.includes(marker)) fail(`合同编辑状态规则缺少 ${marker}`);
+}
+if (!listSource.includes('recordEditReason(record)')) {
+ fail('合同列表缺少编辑禁用原因提示');
+}
const createCount = listResources.filter((item) => createModes.has(item.mode)).length;
console.log(
diff --git a/frontend/platform_admin/src/api/resource-page-rules.ts b/frontend/platform_admin/src/api/resource-page-rules.ts
index 0b14232..1e61284 100644
--- a/frontend/platform_admin/src/api/resource-page-rules.ts
+++ b/frontend/platform_admin/src/api/resource-page-rules.ts
@@ -291,11 +291,11 @@ export function editBlockedReason(
context: ResourcePageContext,
) {
if (!definition.canEdit) return '当前资源不支持编辑';
- if (
- definition.name === 'gasorder_contract' &&
- Number(row.contract_status) !== 10
- ) {
- return '只有草稿状态的合同可以编辑';
+ if (definition.name === 'gasorder_contract') {
+ if (Number(row.contract_status) !== 0)
+ return '只有草稿状态的合同可以编辑';
+ if (![0, 1].includes(Number(row.status)))
+ return '停用、已归档或已冻结的合同不可编辑';
}
if (definition.name === 'platform_role') {
if (context.role !== 'root') return '只有 root 可以编辑平台角色';