修复气站合同用户权限与服务关系边界

This commit is contained in:
czl231
2026-08-18 22:49:14 +08:00
parent 61a61f916b
commit 9a31cadf5f
27 changed files with 635 additions and 59 deletions

View File

@@ -1,6 +1,6 @@
/**
* 功能:统一资源列表与详情页面的字段名称、关系、金额、状态和时间展示。
* 版本v1.7.0
* 版本v1.8.0
*/
import dayjs from 'dayjs';
import type { RecordPageMode, ResourceRow } from './resource-page-rules';
@@ -36,6 +36,7 @@ const aliases: Record<string, string> = {
delivery_basic_display_name: '配送点',
staff_account_display_name: '工作人员',
user_account_display_name: '用户',
user_service_active: '签约用户仍属合同气站',
creator_display_name: '创建方',
contract_display_name: '配送合同',
assigner_name: '分配人',

View File

@@ -1,6 +1,6 @@
/**
* 功能:定义标准资源在新建、详情和编辑页面中的字段能力与动态编辑限制。
* 版本v1.0.0
* 版本v1.1.0
*/
import type { ResourceField, ResourceUiDefinition } from './resources';
@@ -326,6 +326,8 @@ export function editBlockedReason(
) {
if (!definition.canEdit) return '当前资源不支持编辑';
if (definition.name === 'gasorder_contract') {
if (row.user_service_active === false)
return '签约用户已不属于合同气站,只允许查看或终止合同';
if (Number(row.contract_status) !== 0)
return '只有草稿状态的合同可以编辑';
if (![0, 1].includes(Number(row.status)))

View File

@@ -1,6 +1,6 @@
<!--
功能承载平台总后台全部标准资源的新建详情和编辑独立页面
版本v1.3.0
版本v1.4.0
-->
<template>
<div class="record-page">
@@ -400,9 +400,16 @@ const canEditRecord = computed(
const visibleActions = computed(() =>
(definition.value.detailActions ?? []).filter(
(action) =>
!action.visibleFor ||
action.visibleFor.values.includes(
record.value[action.visibleFor.field] as string | number,
!(
definition.value.name === 'gasorder_contract' &&
record.value.user_service_active === false &&
action.name !== '终止合同'
) &&
(
!action.visibleFor ||
action.visibleFor.values.includes(
record.value[action.visibleFor.field] as string | number,
)
),
),
);

View File

@@ -1,6 +1,6 @@
/**
* 功能:为资源表单和详情页加载、缓存并搜索关联资源选项。
* 版本v1.0.0
* 版本v1.1.0
*/
import { Message } from '@arco-design/web-vue';
import { onBeforeUnmount, reactive } from 'vue';
@@ -12,6 +12,7 @@ import {
import type { ResourceField } from '@/api/resources';
import type { ResourceRow } from '@/api/resource-page-rules';
import { fieldRelationResource } from '@/api/resource-display';
import { relationDisplayName } from '../shared/resource-list-field-display';
import { createRelationRequestVersionGuard } from './resource-relation-linkage-policy';
export type ResourceRelationLoadOptions = {
@@ -134,6 +135,8 @@ export function useResourceRelations(
/** 补载表单或详情中已经保存的关系值,避免分页和筛选导致回显裸标识。 */
async function ensureValues(fields: ResourceField[], values: ResourceRow) {
const requests = fields.flatMap((field) => {
// 服务端已在当前业务记录范围内返回名称时,不再重复补载关联用户。
if (relationDisplayName(field, values)) return [];
const resource = fieldRelationResource(field, values);
if (!resource) return [];
const value = values[field.key];

View File

@@ -1,6 +1,6 @@
<!--
功能展示标准资源列表并将新建详情和编辑入口导航到独立页面
版本v2.3.0
版本v2.4.0
-->
<template>
<a-card :title="listTitle" :bordered="false">
@@ -121,7 +121,7 @@
<a-button v-if="definition.name === 'staff_account'" size="mini" @click="viewCredentials(record)">查看资质</a-button>
<a-button size="mini" @click="openRecord('detail', record)">详情</a-button>
<a-button
v-if="definition.name === 'gasorder_contract' && Number(record.contract_status) === 0"
v-if="definition.name === 'gasorder_contract' && Number(record.contract_status) === 0 && record.user_service_active !== false"
size="mini"
type="primary"
@click="bindContractProduct(record)"

View File

@@ -1,6 +1,6 @@
/**
* 功能描述:集中处理标准资源列表字段的关系名称、唯一标识和列宽展示。
* 版本v1.1.0
* 版本v1.2.0
*/
import { fieldRelationResource, optionLabel } from '@/api/resource-display';
import type { ResourceRow } from '@/api/resource-page-rules';
@@ -106,6 +106,8 @@ export function relationListName(
row: ResourceRow,
relationOptions: Record<string, ResourceRow[]>,
) {
const serverName = relationDisplayName(field, row);
if (serverName) return serverName;
const identity = identityFieldValue(field, row);
const resource = fieldRelationResource(field, row);
const match = (relationOptions[resource] ?? []).find(
@@ -114,6 +116,14 @@ export function relationListName(
return match ? optionLabel(match) : '名称加载失败';
}
/** 读取服务端在当前业务记录权限范围内直接返回的关联名称。 */
export function relationDisplayName(field: ResourceField, row: ResourceRow) {
const key = field.key.endsWith('_identity')
? `${field.key.slice(0, -9)}_display_name`
: '';
return key ? String(row[key] ?? '').trim() : '';
}
/** 按字段类型返回标准列表列宽。 */
export function resourceListColumnWidth(
definitionName: string,