@agile-team/wl-skills-kit 2.4.2 → 2.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,7 +2,6 @@
2
2
 
3
3
  > 见 SKILL.md 主文件(约束 + 按钮规则 + Mock 规范等共用规则)。
4
4
 
5
-
6
5
  #### data.ts
7
6
 
8
7
  ```typescript
@@ -14,7 +13,10 @@ import {
14
13
  TableColumnDesc,
15
14
  BusLogicDataType
16
15
  } from "@/types/page";
17
- import { getAction, postAction } from "@jhlc/common-core/src/api/action";
16
+ import { ElMessage } from "element-plus";
17
+ import { defineColumns, renderOps } from "@agile-team/wk-skills-ui/runtime";
18
+
19
+ export const TABLE_CID = "[pageAbbr]-[base36Timestamp]";
18
20
 
19
21
  export const API_CONFIG = {
20
22
  list: "/[服务缩写]/[资源名]/list",
@@ -88,18 +90,24 @@ export function createPage(editModalRef?: any) {
88
90
  label: "新增",
89
91
  plain: true,
90
92
  onClick: () => editModalRef?.value?.open()
93
+ },
94
+ {
95
+ label: "导出",
96
+ plain: true,
97
+ onClick: () => ElMessage.info("导出逻辑待业务确认")
91
98
  }
92
99
  ];
93
100
  }
94
101
 
95
102
  columnsDef(): TableColumnDesc<any>[] {
96
- return [
97
- { type: "selection" },
98
- { type: "index" },
103
+ return defineColumns([
104
+ { type: "selection", width: 55, fixed: "left", align: "center", headerAlign: "center" },
105
+ { type: "index", label: "序号", width: 60, align: "center" },
99
106
  // 普通列
100
107
  {
101
108
  label: "[列名]",
102
109
  name: "[fieldName]",
110
+ cid: `${TABLE_CID}-[fieldName]`,
103
111
  minWidth: 120,
104
112
  sortable: true,
105
113
  filterable: true
@@ -108,6 +116,7 @@ export function createPage(editModalRef?: any) {
108
116
  {
109
117
  label: "[状态名]",
110
118
  name: "[statusField]",
119
+ cid: `${TABLE_CID}-[statusField]`,
111
120
  minWidth: 120,
112
121
  logicType: BusLogicDataType.dict,
113
122
  logicValue: "[dictCode]",
@@ -117,22 +126,18 @@ export function createPage(editModalRef?: any) {
117
126
  // 操作列(如需要行内编辑/删除按钮)
118
127
  {
119
128
  label: "操作",
129
+ name: "_action",
130
+ cid: `${TABLE_CID}-action`,
120
131
  width: 150,
121
132
  fixed: "right",
122
- operations: [
123
- {
124
- name: "edit",
125
- label: "编辑",
126
- onClick: (row: any) => editModalRef?.value?.open(row.id)
127
- },
128
- {
129
- name: "remove",
130
- label: "删除",
131
- onClick: (row: any) => this.remove(row.id)
132
- }
133
- ]
133
+ align: "center",
134
+ defaultSlot: ({ row }: any) =>
135
+ renderOps([
136
+ { type: "edit", onClick: () => editModalRef?.value?.open(row.id) },
137
+ { type: "del", onClick: () => this.remove(row.id) }
138
+ ])
134
139
  }
135
- ];
140
+ ] as any) as TableColumnDesc<any>[];
136
141
  }
137
142
  })();
138
143
 
@@ -152,7 +157,14 @@ export function createPage(editModalRef?: any) {
152
157
  @reset="select"
153
158
  />
154
159
  <BaseToolbar :items="toolbars" />
155
- <BaseTable ref="tableRef" :data="list" :columns="columns" showToolbar />
160
+ <BaseTable
161
+ ref="tableRef"
162
+ render-type="agGrid"
163
+ :cid="TABLE_CID"
164
+ :data="list"
165
+ :columns="columns"
166
+ showToolbar
167
+ />
156
168
  <jh-pagination
157
169
  v-show="page.total && page.total > 0"
158
170
  :total="page.total || 0"
@@ -165,7 +177,7 @@ export function createPage(editModalRef?: any) {
165
177
  </template>
166
178
 
167
179
  <script setup lang="ts">
168
- import { createPage } from "./data";
180
+ import { createPage, TABLE_CID } from "./data";
169
181
 
170
182
  const Page = createPage();
171
183
  const {
@@ -176,7 +188,7 @@ const {
176
188
  queryItems,
177
189
  columns,
178
190
  toolbars,
179
- select
191
+ select,
180
192
  } = Page;
181
193
 
182
194
  onMounted(() => select());
@@ -193,4 +205,81 @@ onMounted(() => select());
193
205
  // 页面特有样式(无特殊需求可留空)
194
206
  ```
195
207
 
208
+ #### mock/[页面kebab-name].ts
209
+
210
+ ```typescript
211
+ import type { MockMethod } from "vite-plugin-mock";
212
+
213
+ const dataPool = Array.from({ length: 23 }).map((_, index) => ({
214
+ id: String(index + 1),
215
+ name: `模拟数据${index + 1}`,
216
+ status: index % 2 === 0 ? "1" : "0",
217
+ remark: "由 vite-plugin-mock 提供,关闭 ENV_MOCK 后直接走真实接口",
218
+ }));
219
+
220
+ function pageList(query: any) {
221
+ const current = Number(query?.current || query?.pageNum || 1);
222
+ const size = Number(query?.size || query?.pageSize || 10);
223
+ const start = (current - 1) * size;
224
+ return {
225
+ code: 2000,
226
+ message: "success",
227
+ data: {
228
+ records: dataPool.slice(start, start + size),
229
+ total: dataPool.length,
230
+ current,
231
+ size,
232
+ },
233
+ };
234
+ }
235
+
236
+ export default [
237
+ {
238
+ url: "/dev-api/[服务缩写]/[资源名]/list",
239
+ method: "get",
240
+ response: ({ query }: any) => pageList(query),
241
+ },
242
+ {
243
+ url: "/dev-api/[服务缩写]/[资源名]/remove",
244
+ method: "post",
245
+ response: ({ body, query }: any) => {
246
+ const id = body?.id || query?.id;
247
+ const ids = body?.ids || (id ? [id] : []);
248
+ ids.forEach((itemId: string) => {
249
+ const index = dataPool.findIndex((item) => item.id === String(itemId));
250
+ if (index >= 0) dataPool.splice(index, 1);
251
+ });
252
+ return { code: 2000, message: "删除成功", data: null };
253
+ },
254
+ },
255
+ {
256
+ url: "/dev-api/[服务缩写]/[资源名]/save",
257
+ method: "post",
258
+ response: ({ body }: any) => {
259
+ const row = { id: String(Date.now()), ...body };
260
+ dataPool.unshift(row);
261
+ return { code: 2000, message: "新增成功", data: row };
262
+ },
263
+ },
264
+ {
265
+ url: "/dev-api/[服务缩写]/[资源名]/update",
266
+ method: "post",
267
+ response: ({ body }: any) => {
268
+ const index = dataPool.findIndex((item) => item.id === String(body?.id));
269
+ if (index >= 0) Object.assign(dataPool[index], body);
270
+ return { code: 2000, message: "更新成功", data: dataPool[index] || body };
271
+ },
272
+ },
273
+ {
274
+ url: "/dev-api/[服务缩写]/[资源名]/getById",
275
+ method: "get",
276
+ response: ({ query }: any) => ({
277
+ code: 2000,
278
+ message: "success",
279
+ data: dataPool.find((item) => item.id === String(query?.id)) || null,
280
+ }),
281
+ },
282
+ ] as MockMethod[];
283
+ ```
284
+
196
285
  ---
@@ -2,18 +2,22 @@
2
2
 
3
3
  > 见 SKILL.md 主文件(约束 + 按钮规则 + Mock 规范等共用规则)。
4
4
 
5
-
6
5
  #### data.ts(额外部分)
7
6
 
8
7
  在标准 createPage 基础上,增加 createBottomPage:
9
8
 
10
9
  ```typescript
11
10
  // ... 同模板 A 的 imports 和 API_CONFIG(增加从表相关 URL)
11
+ import { defineColumns, renderOps } from "@agile-team/wk-skills-ui/runtime";
12
+
13
+ export const TABLE_CID = "[pageAbbr]-[base36Timestamp]";
14
+ export const BOTTOM_TABLE_CID = `${TABLE_CID}-sub1`;
15
+
12
16
  export const API_CONFIG = {
13
17
  list: "/[服务缩写]/[主资源]/list",
14
18
  remove: "/[服务缩写]/[主资源]/remove",
15
19
  // ...标准 CRUD
16
- bottomList: "/[服务缩写]/[从资源]/list" // 从表查询
20
+ bottomList: "/[服务缩写]/[从资源]/list", // 从表查询
17
21
  } as const;
18
22
 
19
23
  export function createPage(/* refs */) {
@@ -24,7 +28,7 @@ export function createPage(/* refs */) {
24
28
  export function handleRowDblclick(
25
29
  row: any,
26
30
  bottomSelect: Function,
27
- BottomPage: any
31
+ BottomPage: any,
28
32
  ) {
29
33
  BottomPage.queryParam.value.mainId = row.id;
30
34
  BottomPage.tableRef.value.loading();
@@ -51,10 +55,16 @@ export function createBottomPage() {
51
55
  return [];
52
56
  }
53
57
  columnsDef(): TableColumnDesc<any>[] {
54
- return [
55
- { type: "index" }
58
+ return defineColumns([
59
+ { type: "index", label: "序号", width: 60, align: "center" },
60
+ {
61
+ label: "[从表字段]",
62
+ name: "[fieldName]",
63
+ cid: `${BOTTOM_TABLE_CID}-[fieldName]`,
64
+ minWidth: 120,
65
+ },
56
66
  // 从表字段
57
- ];
67
+ ] as any) as TableColumnDesc<any>[];
58
68
  }
59
69
  })();
60
70
  return (Page as any).create() as any;
@@ -77,6 +87,8 @@ export function createBottomPage() {
77
87
  <BaseToolbar :items="toolbars" />
78
88
  <BaseTable
79
89
  ref="tableRef"
90
+ render-type="agGrid"
91
+ :cid="TABLE_CID"
80
92
  :data="list"
81
93
  :columns="columns"
82
94
  showToolbar
@@ -97,6 +109,8 @@ export function createBottomPage() {
97
109
  <BaseToolbar :items="bottomToolbars" />
98
110
  <BaseTable
99
111
  ref="bottomTableRef"
112
+ render-type="agGrid"
113
+ :cid="BOTTOM_TABLE_CID"
100
114
  :data="bottomList"
101
115
  :columns="bottomColumns"
102
116
  showToolbar
@@ -107,7 +121,13 @@ export function createBottomPage() {
107
121
  </template>
108
122
 
109
123
  <script setup lang="ts">
110
- import { createPage, createBottomPage, handleRowDblclick } from "./data";
124
+ import {
125
+ createPage,
126
+ createBottomPage,
127
+ handleRowDblclick,
128
+ TABLE_CID,
129
+ BOTTOM_TABLE_CID,
130
+ } from "./data";
111
131
 
112
132
  const Page = createPage();
113
133
  const {
@@ -118,7 +138,7 @@ const {
118
138
  queryItems,
119
139
  columns,
120
140
  toolbars,
121
- select
141
+ select,
122
142
  } = Page;
123
143
 
124
144
  const BottomPage = createBottomPage();
@@ -127,7 +147,7 @@ const {
127
147
  list: bottomList,
128
148
  columns: bottomColumns,
129
149
  select: bottomSelect,
130
- toolbars: bottomToolbars
150
+ toolbars: bottomToolbars,
131
151
  } = BottomPage;
132
152
 
133
153
  onMounted(() => select());
@@ -2,7 +2,6 @@
2
2
 
3
3
  > 见 SKILL.md 主文件(约束 + 按钮规则 + Mock 规范等共用规则)。
4
4
 
5
-
6
5
  > 适用场景:通过 BaseQuery 选定主记录(如炉号、生产计划号),展示可编辑的 BaseForm 字段区 + BaseTable 明细行,**无分页**。
7
6
  > 典型于生产域实绩录入(转炉实绩、精炼实绩、连铸实绩等)。
8
7
  > 参考实现:`src/views/produce/production-omom/lgsj/mmsm-convert-progress/`
@@ -23,16 +22,19 @@ import {
23
22
  BaseQueryItemDesc,
24
23
  ActionButtonDesc,
25
24
  TableColumnDesc,
26
- BusLogicDataType
25
+ BusLogicDataType,
27
26
  } from "@/types/page";
28
27
  import type { BaseFormItemDesc } from "@jhlc/common-core/src/components/form/common/type";
29
28
  import c_spliterTitle from "@/components/local/c_spliterTitle/index.vue";
30
29
  import { getAction, postAction } from "@jhlc/common-core/src/api/action";
31
30
  import { debounce } from "lodash-es";
31
+ import { defineColumns } from "@agile-team/wk-skills-ui/runtime";
32
+
33
+ export const BOTTOM_TABLE_CID = "[pageAbbr]-[base36Timestamp]";
32
34
 
33
35
  export const API_CONFIG = {
34
- getByKey: "/[服务缩写]/[资源名]/getBy[Key]", // 按主键查询(炉号/计划号/熔炼号)
35
- saveOrUpdate: "/[服务缩写]/[资源名]/saveOrUpdate" // 保存实绩
36
+ getByKey: "/[服务缩写]/[资源名]/getBy[Key]", // 按主键查询(炉号/计划号/熔炼号)
37
+ saveOrUpdate: "/[服务缩写]/[资源名]/saveOrUpdate", // 保存实绩
36
38
  } as const;
37
39
 
38
40
  // ─────────────── 查询区 ───────────────
@@ -44,8 +46,8 @@ export const queryItems: BaseQueryItemDesc<any>[] = [
44
46
  {
45
47
  name: "[keyField]",
46
48
  label: "[主键名]",
47
- placeholder: "请输入[主键名]"
48
- }
49
+ placeholder: "请输入[主键名]",
50
+ },
49
51
  // 如需关联 Picker,使用 componentVNode 渲染(参考 mmsm-convert-progress PlanMainPicker)
50
52
  ];
51
53
 
@@ -54,7 +56,7 @@ export const select = async () => {
54
56
  const res = await getAction(API_CONFIG.getByKey, queryParam.value);
55
57
  form.value = {
56
58
  ...queryParam.value,
57
- ...(res.data?.[主数据字段] || {})
59
+ ...(res.data?.[主数据字段] || {}),
58
60
  };
59
61
  bottomTableData.value = res.data?.[明细字段] || [];
60
62
  };
@@ -85,7 +87,7 @@ export const formItems: BaseFormItemDesc<any>[] = [
85
87
  label: "",
86
88
  labelWidth: "0px",
87
89
  span: 4,
88
- componentVNode: () => h(c_spliterTitle, { title: "[分区名称]" })
90
+ componentVNode: () => h(c_spliterTitle, { title: "[分区名称]" }),
89
91
  },
90
92
  // 普通文本
91
93
  { label: "[字段名]", name: "[fieldName]", placeholder: "请输入[字段名]" },
@@ -96,22 +98,22 @@ export const formItems: BaseFormItemDesc<any>[] = [
96
98
  placeholder: "请选择[字典字段]",
97
99
  logicType: BusLogicDataType.dict,
98
100
  logicValue: "[dictCode]",
99
- required: true
101
+ required: true,
100
102
  },
101
103
  // 时间
102
104
  {
103
105
  label: "[时间字段]",
104
106
  name: "[timeField]",
105
107
  placeholder: "请选择[时间字段]",
106
- logicType: BusLogicDataType.datetime
108
+ logicType: BusLogicDataType.datetime,
107
109
  },
108
110
  // 数值
109
111
  {
110
112
  label: "[数值字段]",
111
113
  name: "[numField]",
112
114
  placeholder: "请输入[数值字段]",
113
- logicType: BusLogicDataType.number
114
- }
115
+ logicType: BusLogicDataType.number,
116
+ },
115
117
  ];
116
118
 
117
119
  /** 工具栏(需传入 formRef 以触发校验) */
@@ -126,13 +128,15 @@ export const toolbars = (formRef: any): ActionButtonDesc[] => [
126
128
  ElMessageBox.confirm("确定保存吗?", "提示", {
127
129
  confirmButtonText: "确定",
128
130
  cancelButtonText: "取消",
129
- type: "warning"
131
+ type: "warning",
130
132
  }).then(async () => {
131
- const res = await postAction(API_CONFIG.saveOrUpdate, { ...form.value });
133
+ const res = await postAction(API_CONFIG.saveOrUpdate, {
134
+ ...form.value,
135
+ });
132
136
  ElMessage.success(res?.message || "保存成功");
133
137
  });
134
138
  });
135
- }, 600)
139
+ }, 600),
136
140
  },
137
141
  {
138
142
  label: "重置",
@@ -141,8 +145,8 @@ export const toolbars = (formRef: any): ActionButtonDesc[] => [
141
145
  onClick: () => {
142
146
  resetForm();
143
147
  formRef?.resetFields();
144
- }
145
- }
148
+ },
149
+ },
146
150
  ];
147
151
 
148
152
  // ─────────────── 明细表格区 ───────────────
@@ -150,17 +154,18 @@ export const toolbars = (formRef: any): ActionButtonDesc[] => [
150
154
  export const bottomTableData = ref<any[]>([]);
151
155
 
152
156
  /** 明细表格列配置 */
153
- export const bottomTableColumns: TableColumnDesc<any>[] = [
154
- { type: "index", width: 55 },
157
+ export const bottomTableColumns: TableColumnDesc<any>[] = defineColumns([
158
+ { type: "index", label: "序号", width: 60, align: "center" },
155
159
  {
156
160
  label: "[列名]",
157
161
  name: "[fieldName]",
162
+ cid: `${BOTTOM_TABLE_CID}-[fieldName]`,
158
163
  minWidth: 100,
159
164
  sortable: true,
160
- filterable: true
161
- }
165
+ filterable: true,
166
+ },
162
167
  // 按原型顺序添加明细列,通常为只读(无操作列)
163
- ];
168
+ ] as any) as TableColumnDesc<any>[];
164
169
  ```
165
170
 
166
171
  #### index.vue
@@ -190,6 +195,8 @@ export const bottomTableColumns: TableColumnDesc<any>[] = [
190
195
  />
191
196
  <!-- 明细表格(无分页) -->
192
197
  <BaseTable
198
+ render-type="agGrid"
199
+ :cid="BOTTOM_TABLE_CID"
193
200
  :data="bottomTableData"
194
201
  :columns="bottomTableColumns"
195
202
  :height="300"
@@ -209,7 +216,8 @@ import {
209
216
  reset,
210
217
  bottomTableData,
211
218
  bottomTableColumns,
212
- resetForm
219
+ BOTTOM_TABLE_CID,
220
+ resetForm,
213
221
  } from "./data";
214
222
 
215
223
  const formRef = ref<any>(null);
@@ -248,14 +256,14 @@ onMounted(() => {
248
256
 
249
257
  #### 关键约束
250
258
 
251
- | 约束 | 说明 |
252
- |------|------|
253
- | **不用 AbstractPageQueryHook** | 直接导出 `ref` + 函数,无 `createPage()` 包装 |
254
- | **无分页** | `bottomTableData` 绑定全量数据,不加 `jh-pagination` |
255
- | **auto-select: false** | BaseQuery 查询是"选择主记录",不自动触发,用户主动点击 |
256
- | **toolbars(formRef)** | template 中调用函数传入 `formRef`,不是直接绑定数组 |
257
- | **debounce 保存** | 防止连点,来自 `lodash-es`,600ms |
258
- | **c_spliterTitle 分区** | 表单字段按业务分组,每组前插分隔标题 |
259
+ | 约束 | 说明 |
260
+ | ------------------------------ | ------------------------------------------------------ |
261
+ | **不用 AbstractPageQueryHook** | 直接导出 `ref` + 函数,无 `createPage()` 包装 |
262
+ | **无分页** | `bottomTableData` 绑定全量数据,不加 `jh-pagination` |
263
+ | **auto-select: false** | BaseQuery 查询是"选择主记录",不自动触发,用户主动点击 |
264
+ | **toolbars(formRef)** | template 中调用函数传入 `formRef`,不是直接绑定数组 |
265
+ | **debounce 保存** | 防止连点,来自 `lodash-es`,600ms |
266
+ | **c_spliterTitle 分区** | 表单字段按业务分组,每组前插分隔标题 |
259
267
 
260
268
  #### Mock 文件要点
261
269
 
@@ -312,20 +320,29 @@ export default mockApi;
312
320
  defineExpose({ loadData, collectFormData, validate, loadDiffData, clearDiffData })
313
321
  ```
314
322
 
315
- | 方法 | 说明 |
316
- |------|------|
323
+ | 方法 | 说明 |
324
+ | ------------------------ | ---------------------------------------- |
317
325
  | `loadDiffData(prevData)` | 接收旧版数据,组件内部对比并渲染差异指示 |
318
- | `clearDiffData()` | 清除比对状态 |
326
+ | `clearDiffData()` | 清除比对状态 |
319
327
 
320
328
  **组件内部实现要点**:
321
329
 
322
330
  1. **表单字段 diff**:用 `div.diff-field-col` 包裹 `jh-select` + `<span class="diff-old-value">`,旧值出现在字段**下方**(不破坏原布局):
331
+
323
332
  ```html
324
333
  <el-form-item label="纳税类型" prop="taxCategory">
325
334
  <div class="diff-field-col">
326
- <jh-select v-model="basicInfo.taxCategory" dict="tax_category" label="" placeholder="请选择" />
327
- <span v-if="diffBasicInfo && diffBasicInfo.taxCategory !== basicInfo.taxCategory"
328
- class="diff-old-value">{{ diffBasicInfo.taxCategory }}</span>
335
+ <jh-select
336
+ v-model="basicInfo.taxCategory"
337
+ dict="tax_category"
338
+ label=""
339
+ placeholder="请选择"
340
+ />
341
+ <span
342
+ v-if="diffBasicInfo && diffBasicInfo.taxCategory !== basicInfo.taxCategory"
343
+ class="diff-old-value"
344
+ >{{ diffBasicInfo.taxCategory }}</span
345
+ >
329
346
  </div>
330
347
  </el-form-item>
331
348
  ```
@@ -333,6 +350,7 @@ defineExpose({ loadData, collectFormData, validate, loadDiffData, clearDiffData
333
350
  > **数据约定**:`diffBasicInfo` 中存储显示标签(如 `"小规模纳税人"`),不存储 dict code,与 `basicInfo` 保持一致格式,才能正确比对和展示。
334
351
 
335
352
  2. **表格行 diff**:使用 `computed` 在每条主数据行后插入带 `_isDiffRow: true` 标记的旧版行:
353
+
336
354
  ```typescript
337
355
  const displayList = computed(() => {
338
356
  if (!diffList.value) return mainList.value;
@@ -341,8 +359,11 @@ const displayList = computed(() => {
341
359
  result.push({ ...row, _seq: i + 1 });
342
360
  const old = diffList.value![i];
343
361
  if (old) {
344
- const changed = Object.keys(old).filter(k => !k.startsWith('_') && String(old[k]) !== String(row[k]));
345
- if (changed.length) result.push({ ...old, _isDiffRow: true, _changedFields: changed });
362
+ const changed = Object.keys(old).filter(
363
+ (k) => !k.startsWith("_") && String(old[k]) !== String(row[k]),
364
+ );
365
+ if (changed.length)
366
+ result.push({ ...old, _isDiffRow: true, _changedFields: changed });
346
367
  }
347
368
  });
348
369
  return result;
@@ -352,25 +373,49 @@ const displayList = computed(() => {
352
373
  3. **单元格级高亮**:每个 view 模式列的 `<span>` 加上 `diffCellClass(row, 'fieldName')`。
353
374
 
354
375
  4. **CSS 样式**(在组件 scoped style 中):
376
+
355
377
  ```scss
356
378
  /* 表单字段 diff 包装器:列方向 flex,使旧值出现在 jh-select 下方 */
357
379
  .diff-field-col {
358
- display: flex; flex-direction: column; width: 100%;
359
- :deep(.el-select) { width: 100% !important; }
380
+ display: flex;
381
+ flex-direction: column;
382
+ width: 100%;
383
+ :deep(.el-select) {
384
+ width: 100% !important;
385
+ }
360
386
  }
361
387
  /* 表单字段旧值:在字段下方,● 前缀不加删除线,文字橙色 + 删除线 */
362
388
  .diff-old-value {
363
- display: block; font-size: 12px; color: #e6a23c;
364
- text-decoration: line-through; margin-top: 2px; line-height: 1.4;
365
- &::before { content: "● "; text-decoration: none; display: inline-block; }
389
+ display: block;
390
+ font-size: 12px;
391
+ color: #e6a23c;
392
+ text-decoration: line-through;
393
+ margin-top: 2px;
394
+ line-height: 1.4;
395
+ &::before {
396
+ content: "● ";
397
+ text-decoration: none;
398
+ display: inline-block;
399
+ }
366
400
  }
367
401
  /* 表格对比行:已变更字段 —— 橙色 + 删除线 */
368
- .diff-changed { color: #e6a23c !important; text-decoration: line-through; }
369
- .diff-row-marker { color: #e6a23c; font-size: 12px; }
402
+ .diff-changed {
403
+ color: #e6a23c !important;
404
+ text-decoration: line-through;
405
+ }
406
+ .diff-row-marker {
407
+ color: #e6a23c;
408
+ font-size: 12px;
409
+ }
370
410
  /* 表格对比行:整行浅红背景 + 未变字段灰色,已变字段橙色覆盖 */
371
411
  :deep(.el-table .is-diff-row) {
372
412
  background-color: #fef0f0 !important;
373
- td { background-color: #fef0f0 !important; color: #c0c4cc; }
374
- .diff-changed { color: #e6a23c !important; }
413
+ td {
414
+ background-color: #fef0f0 !important;
415
+ color: #c0c4cc;
416
+ }
417
+ .diff-changed {
418
+ color: #e6a23c !important;
419
+ }
375
420
  }
376
421
  ```