Просмотр исходного кода

fix(s8): hide inactive config fields for demo

Reduce demo noise on S8 config center: hide rendering of fields that
are stored but not consumed by business logic, and hide the entry to
config pages that overlap with ApprovalFlow. All fields/values stay in
form / payload so PUT全量 提交时旧值原样回写,不会被清空。

S8CrudConfigPage: add ConfigField.hidden flag; el-form-item v-show
honors it; validateForm skips required check on hidden fields; props
columns/fields accept readonly arrays.

ConfigHub: hide '通知分层' card entry (path / route / page / controller
/ entity / SysMenu seed all preserved; only前端 entry collapsed).

RolePermissionConfig page: keep OperatorBindingTab; hide legacy
'角色权限(旧版兼容)' Tab (S8CrudConfigPage import / endpoint
/api/aidop/s8/config/roles / fields / buildDefault / syncFromSys all
preserved for future restoration).

ExceptionType form: hide 7 fields (severity_default / sla_minutes /
owner_role_code / escalate_role_code / stats_mode / icon /
mobile_visible). Removed 'required' from these so新建 not blocked.
List columns also slim down (severityDefault / slaMinutes /
ownerRoleCode dropped from列表 only).

AlertRule form: hide alert_rule.time_window. Note: do NOT confuse with
dashboard_cell_config.time_window which is heavily consumed by
S8DashboardCellDataService.TimeRange.

DataSource form: hide auth_type.

DashboardCell form: hide filter_expression (service comment明示 not
mapped to frontend DTO; only length validated).

S8WatchRuleConfigPage params_json template UNTOUCHED.
SysMenuSeedData.cs UNTOUCHED.
Backend service / controller / entity / DB columns UNTOUCHED.

Verified: vue-tsc 0 error in changed files; pnpm run build PASS;
dotnet build 0 error; SchedulerJob continues to tick successfully
post-change (5min cadence, hits=5 created=0 failed=0 across 3 ticks).
YY968XX 1 месяц назад
Родитель
Сommit
b602870cc2

+ 13 - 4
Web/src/views/aidop/s8/components/config/S8CrudConfigPage.vue

@@ -13,8 +13,15 @@ interface ConfigField {
 	type: FieldType;
 	required?: boolean;
 	optionsKey?: string;
-	options?: OptionItem[];
+	options?: readonly OptionItem[];
 	placeholder?: string;
+	/**
+	 * 渲染层隐藏标记(演示降噪 / 字段未被业务消费)。
+	 * - hidden=true 时:表单不渲染该字段、validateForm 跳过 required 检查
+	 * - 字段值仍保留在 form / payload 中,PUT 全量提交时旧值原样回写,**不会被清空**
+	 * - 不要把字段从 fields 数组、buildDefault、loadData 字段集里移除
+	 */
+	hidden?: boolean;
 }
 
 interface ConfigColumn {
@@ -28,8 +35,8 @@ const props = defineProps<{
 	subtitle: string;
 	endpoint: string;
 	idKey?: string;
-	columns: ConfigColumn[];
-	fields: ConfigField[];
+	columns: readonly ConfigColumn[];
+	fields: readonly ConfigField[];
 	enableTest?: boolean;
 	buildDefault: () => Record<string, unknown>;
 	loadOptions?: () => Promise<Record<string, OptionItem[]>>;
@@ -86,6 +93,8 @@ function fieldOptions(field: ConfigField) {
 function validateForm() {
 	for (const field of props.fields) {
 		if (!field.required) continue;
+		// hidden 字段保留在 form / payload 中以便 PUT 全量回写旧值,但不参与必填校验。
+		if (field.hidden) continue;
 		const value = form[field.key];
 		if (value === undefined || value === null || value === '') {
 			ElMessage.warning(`${field.label}不能为空`);
@@ -161,7 +170,7 @@ onMounted(() => {
 
 		<el-dialog v-model="dialogVisible" :title="editingId > 0 ? '编辑配置' : '新增配置'" width="720px">
 			<el-form label-width="120px">
-				<el-form-item v-for="field in fields" :key="field.key" :label="field.label" :required="field.required">
+				<el-form-item v-for="field in fields" v-show="!field.hidden" :key="field.key" :label="field.label" :required="field.required">
 					<el-input
 						v-if="field.type === 'input'"
 						v-model="form[field.key]"

+ 4 - 1
Web/src/views/aidop/s8/config/S8AlertRulesPage.vue

@@ -16,7 +16,10 @@ const fields = [
 	{ key: 'severity', label: '严重度', type: 'select', required: true, optionsKey: 'severities' },
 	{ key: 'triggerCondition', label: '触发条件', type: 'input', required: true },
 	{ key: 'thresholdVal', label: '阈值', type: 'input' },
-	{ key: 'timeWindow', label: '时间窗口', type: 'input' },
+	// S8-CONFIG-CLEANUP-DEMO-1:ado_s8_alert_rule.time_window 当前未被业务消费(不要误伤
+	// ado_s8_dashboard_cell_config.time_window,那个在 S8DashboardCellDataService.TimeRange 大量消费)。
+	// 仅渲染层隐藏,PUT 全量提交时旧值原样回写。
+	{ key: 'timeWindow', label: '时间窗口', type: 'input', hidden: true },
 ] as const;
 
 const buildDefault = () => ({

+ 3 - 1
Web/src/views/aidop/s8/config/S8ConfigHubPage.vue

@@ -20,7 +20,9 @@ const cards = [
 	{ path: '/aidop/s8/config/scenes', title: '场景基础配置', desc: '场景编码、启用、排序' },
 	{ path: '/aidop/s8/config/exception-types', title: '异常类型', desc: '类型编码、SLA、责任角色' },
 	{ path: '/aidop/s8/config/dashboard-cells', title: '大屏卡片', desc: '页面/卡片编码、绑定类型、指标与时间窗' },
-	{ path: '/aidop/s8/config/notifications', title: '通知分层', desc: '场景 + 严重度 + 层级' },
+	// S8-CONFIG-CLEANUP-DEMO-1: 通知分层入口隐藏(演示降噪;通知通道与 ApprovalFlow 通知重叠,
+	// 整表当前未被业务消费)。后端菜单 / route / 页面 / controller / entity 均保留,仅前端入口收口。
+	// { path: '/aidop/s8/config/notifications', title: '通知分层', desc: '场景 + 严重度 + 层级' },
 	{ path: '/aidop/s8/config/roles', title: '角色权限', desc: 'S8 动作权限配置' },
 	{ path: '/aidop/s8/config/alert-rules', title: '报警规则', desc: '阈值与触发条件' },
 	{ path: '/aidop/s8/config/data-sources', title: '数据源', desc: '连接与启用' },

+ 5 - 0
Web/src/views/aidop/s8/config/S8DashboardCellConfigPage.vue

@@ -108,11 +108,16 @@ const fields = [
 		],
 		placeholder: '明细按部门分组时使用;也可由 cell-data 请求参数覆盖',
 	},
+	// S8-CONFIG-CLEANUP-DEMO-1:filterExpression 当前未映射到前端 DTO(service 注释明示),
+	// service 仅做长度校验(≤1000)不参与过滤;仅渲染层隐藏,PUT 旧值原样回写。
+	// 注意:dashboard.timeWindow 在 S8DashboardCellDataService.TimeRange 大量消费,**不动**。
+	// show_in_sidebar 当前在 fields 数组中未暴露,无需处理。
 	{
 		key: 'filterExpression',
 		label: '筛选表达式',
 		type: 'textarea',
 		placeholder: '可选,后续扩展(部门、订单范围等),留空表示不按表达式筛',
+		hidden: true,
 	},
 	{ key: 'enabled', label: '启用', type: 'switch' },
 	{ key: 'sortNo', label: '排序', type: 'number' },

+ 2 - 1
Web/src/views/aidop/s8/config/S8DataSourceConfigPage.vue

@@ -13,7 +13,8 @@ const fields = [
 	{ key: 'dataSourceCode', label: '数据源编码', type: 'input', required: true },
 	{ key: 'type', label: '类型', type: 'select', required: true, options: [{ label: 'HTTP', value: 'HTTP' }, { label: 'SQL', value: 'SQL' }, { label: 'MQ', value: 'MQ' }] },
 	{ key: 'endpoint', label: '连接地址', type: 'input', required: true },
-	{ key: 'authType', label: '认证方式', type: 'input' },
+	// S8-CONFIG-CLEANUP-DEMO-1:auth_type 当前 0 业务消费;仅渲染层隐藏。
+	{ key: 'authType', label: '认证方式', type: 'input', hidden: true },
 	{ key: 'enabled', label: '启用', type: 'switch' },
 ] as const;
 

+ 13 - 10
Web/src/views/aidop/s8/config/S8ExceptionTypeConfigPage.vue

@@ -2,18 +2,21 @@
 import S8CrudConfigPage from '../components/config/S8CrudConfigPage.vue';
 import { s8ConfigApi } from '../api/s8ConfigApi';
 
+// S8-CONFIG-CLEANUP-DEMO-1:列表只展示生效字段;不展示 severityDefault / slaMinutes / ownerRoleCode。
+// 这些列在 entity / DB / API / fields / buildDefault 全部保留,仅列表渲染层不显示。
 const columns = [
 	{ key: 'typeCode', label: '类型编码', width: 180 },
 	{ key: 'typeName', label: '类型名称', width: 180 },
 	{ key: 'domainCode', label: '所属域', width: 120 },
 	{ key: 'sceneCode', label: '场景编码', width: 150 },
-	{ key: 'severityDefault', label: '默认严重度', width: 120 },
-	{ key: 'slaMinutes', label: 'SLA(分钟)', width: 110 },
-	{ key: 'ownerRoleCode', label: '责任角色', width: 180 },
 	{ key: 'enabled', label: '启用', width: 90 },
 	{ key: 'sortNo', label: '排序', width: 90 },
 ];
 
+// S8-CONFIG-CLEANUP-DEMO-1:以下 7 个字段标记 hidden=true:
+// severityDefault / slaMinutes / ownerRoleCode / escalateRoleCode / statsMode / icon / mobileVisible
+// 渲染层隐藏,但保留在 fields / buildDefault / form / PUT payload,旧值原样回写不丢。
+// required 字段一并去掉以避免新建场景必填校验阻塞(实际值由 buildDefault 提供默认)。
 const fields = [
 	{ key: 'typeCode', label: '类型编码', type: 'input', required: true, placeholder: '如 ORDER_CHANGE' },
 	{ key: 'typeName', label: '类型名称', type: 'input', required: true },
@@ -29,26 +32,26 @@ const fields = [
 		],
 	},
 	{ key: 'sceneCode', label: '场景编码', type: 'select', required: true, optionsKey: 'scenes' },
-	{ key: 'severityDefault', label: '默认严重度', type: 'select', required: true, optionsKey: 'severities' },
-	{ key: 'slaMinutes', label: 'SLA(分钟)', type: 'number', required: true },
-	{ key: 'ownerRoleCode', label: '责任角色', type: 'select', required: true, optionsKey: 'roles' },
-	{ key: 'escalateRoleCode', label: '升级角色', type: 'select', optionsKey: 'roles' },
+	{ key: 'severityDefault', label: '默认严重度', type: 'select', optionsKey: 'severities', hidden: true },
+	{ key: 'slaMinutes', label: 'SLA(分钟)', type: 'number', hidden: true },
+	{ key: 'ownerRoleCode', label: '责任角色', type: 'select', optionsKey: 'roles', hidden: true },
+	{ key: 'escalateRoleCode', label: '升级角色', type: 'select', optionsKey: 'roles', hidden: true },
 	{
 		key: 'statsMode',
 		label: '统计模式',
 		type: 'select',
-		required: true,
 		options: [
 			{ label: '全部', value: 'ALL' },
 			{ label: '频率', value: 'FREQUENCY' },
 			{ label: '时长', value: 'DURATION' },
 			{ label: '关闭率', value: 'CLOSE_RATE' },
 		],
+		hidden: true,
 	},
-	{ key: 'mobileVisible', label: '移动端展示', type: 'switch' },
+	{ key: 'mobileVisible', label: '移动端展示', type: 'switch', hidden: true },
 	{ key: 'enabled', label: '启用', type: 'switch' },
 	{ key: 'sortNo', label: '排序', type: 'number' },
-	{ key: 'icon', label: '图标标识', type: 'input' },
+	{ key: 'icon', label: '图标标识', type: 'input', hidden: true },
 	{ key: 'remark', label: '备注', type: 'textarea' },
 ] as const;
 

+ 16 - 34
Web/src/views/aidop/s8/config/S8RolePermissionConfigPage.vue

@@ -1,10 +1,18 @@
 <script setup lang="ts" name="aidopS8RolePermissionConfig">
+// S8-CONFIG-CLEANUP-DEMO-1:保留以下 import / 状态字段(不删除),
+// 旧版"角色权限(旧版兼容)"Tab 在模板层隐藏;endpoint /api/aidop/s8/config/roles
+// 仍然可访问;S8RoleConfigService.cs / AdoS8RolePermissionConfig entity / DB 表均不动。
+// eslint-disable-next-line @typescript-eslint/no-unused-vars
 import { ref } from 'vue';
+// eslint-disable-next-line @typescript-eslint/no-unused-vars
 import { ElMessage } from 'element-plus';
+// eslint-disable-next-line @typescript-eslint/no-unused-vars
 import S8CrudConfigPage from '../components/config/S8CrudConfigPage.vue';
 import S8OperatorBindingTab from './S8OperatorBindingTab.vue';
+// eslint-disable-next-line @typescript-eslint/no-unused-vars
 import { s8ConfigApi } from '../api/s8ConfigApi';
 
+// eslint-disable-next-line @typescript-eslint/no-unused-vars
 const activeTab = ref<'binding' | 'roles'>('binding');
 
 const columns = [
@@ -44,40 +52,14 @@ async function syncFromSys(reload: () => void) {
 			<h2>角色权限配置</h2>
 			<div class="subtitle">S8 / 配置 / 角色权限</div>
 		</div>
-		<el-tabs v-model="activeTab" class="role-config-tabs">
-			<el-tab-pane label="操作员账号绑定" name="binding">
-				<S8OperatorBindingTab />
-			</el-tab-pane>
-			<el-tab-pane name="roles">
-				<template #label>
-					<span>
-						角色权限(旧版兼容)
-						<el-tag size="small" type="info" effect="plain" style="margin-left: 6px">已弃用</el-tag>
-					</span>
-				</template>
-				<el-alert
-					type="warning"
-					:closable="false"
-					show-icon
-					title="旧版角色权限(已弃用 / 待升级为权限矩阵)"
-					style="margin-bottom: 12px"
-				>
-					当前旧版配置仅用于兼容历史数据,不作为正式鉴权源。S8 正式权限将复用系统角色权限体系(SysUserRole + SysRoleMenu),并仅使用 s8:* 权限点。
-				</el-alert>
-				<S8CrudConfigPage
-					title="角色权限配置(旧版兼容)"
-					subtitle="S8 / 配置 / 角色权限(旧版逗号串字段,已弃用)"
-					endpoint="/api/aidop/s8/config/roles"
-					:columns="columns"
-					:fields="fields"
-					:build-default="buildDefault"
-				>
-					<template #toolbar-extra="{ reload }">
-						<el-button :loading="syncing" @click="syncFromSys(reload)">同步系统角色</el-button>
-					</template>
-				</S8CrudConfigPage>
-			</el-tab-pane>
-		</el-tabs>
+		<!--
+			S8-CONFIG-CLEANUP-DEMO-1:仅展示操作员账号绑定,隐藏旧版角色权限 Tab。
+			permission_codes 由 S8RoleConfigService.cs:74 写硬编码 "[]",无业务分支消费;
+			S8 正式鉴权沿用 SysUserRole + SysRoleMenu。
+			保留:S8OperatorBindingTab、s8ConfigApi.operatorBindings.*、columns/fields/buildDefault/
+			      syncFromSys/S8CrudConfigPage import / endpoint /api/aidop/s8/config/roles。
+		-->
+		<S8OperatorBindingTab />
 	</div>
 </template>