@agile-team/wl-skills-kit 2.3.3 → 2.3.5

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.
Files changed (91) hide show
  1. package/CHANGELOG.md +24 -23
  2. package/README.md +15 -146
  3. package/files/.cursor/mcp.json +8 -0
  4. package/files/.github/guides/README.md +13 -13
  5. package/files/.github/guides/architecture.md +555 -555
  6. package/files/.github/guides/mcp-setup.md +109 -0
  7. package/files/.github/guides/usage.md +184 -176
  8. package/files/.github/reports/README.md +65 -65
  9. package/files/.github/reports/SYS_DICT_INFO.md +50 -50
  10. package/files/.github/reports/SYS_MENU_INFO.md +247 -247
  11. package/files/.github/reports/SYS_PERMISSION_INFO.md +20 -20
  12. package/files/.github/reports//347/273/204/344/273/266/346/217/220/345/217/226/345/273/272/350/256/256.md +33 -33
  13. package/files/.github/reports//350/247/204/350/214/203/345/256/241/346/237/245/346/212/245/345/221/212.md +44 -44
  14. package/files/.github/skills/_compat/README.md +108 -108
  15. package/files/.github/skills/_compat/editors.json +7 -0
  16. package/files/.github/skills/_compat/headers/agents.txt +8 -8
  17. package/files/.github/skills/_compat/headers/claude-code.txt +7 -7
  18. package/files/.github/skills/_compat/headers/cline.txt +7 -7
  19. package/files/.github/skills/_compat/headers/cursor-mdc.txt +16 -16
  20. package/files/.github/skills/_compat/headers/cursor-rules.txt +7 -7
  21. package/files/.github/skills/_compat/headers/github-copilot.txt +1 -1
  22. package/files/.github/skills/_compat/headers/kiro.txt +10 -10
  23. package/files/.github/skills/_compat/headers/qoder.txt +8 -0
  24. package/files/.github/skills/_compat/headers/trae.txt +11 -11
  25. package/files/.github/skills/_compat/headers/windsurf.txt +7 -7
  26. package/files/.github/skills/_registry.md +81 -81
  27. package/files/.github/skills/core/api-contract/SKILL.md +344 -344
  28. package/files/.github/skills/core/api-contract/USAGE.md +110 -110
  29. package/files/.github/skills/core/convention-audit/SKILL.md +189 -189
  30. package/files/.github/skills/core/convention-audit/USAGE.md +99 -99
  31. package/files/.github/skills/core/page-codegen/SKILL.md +973 -973
  32. package/files/.github/skills/core/page-codegen/USAGE.md +102 -102
  33. package/files/.github/skills/core/page-codegen/templates/_index.md +46 -46
  34. package/files/.github/skills/core/page-codegen/templates/domains/_CONTRIBUTING.md +107 -107
  35. package/files/.github/skills/core/page-codegen/templates/domains/produce/TPL-OPERATION-STATION.md +442 -442
  36. package/files/.github/skills/core/page-codegen/templates/domains/sale/README.md +26 -26
  37. package/files/.github/skills/core/page-codegen/templates/universal/TPL-CHANGE-HISTORY.md +276 -276
  38. package/files/.github/skills/core/page-codegen/templates/universal/TPL-DETAIL-TABS.md +1145 -1145
  39. package/files/.github/skills/core/page-codegen/templates/universal/TPL-DRIVEN.md +309 -309
  40. package/files/.github/skills/core/page-codegen/templates/universal/TPL-FORM-ROUTE.md +436 -436
  41. package/files/.github/skills/core/page-codegen/templates/universal/TPL-LIST.md +191 -191
  42. package/files/.github/skills/core/page-codegen/templates/universal/TPL-MASTER-DETAIL.md +148 -148
  43. package/files/.github/skills/core/page-codegen/templates/universal/TPL-RECORD-FORM.md +376 -376
  44. package/files/.github/skills/core/page-codegen/templates/universal/TPL-TREE-LIST.md +186 -186
  45. package/files/.github/skills/core/prototype-scan/SKILL.md +498 -498
  46. package/files/.github/skills/core/prototype-scan/USAGE.md +95 -95
  47. package/files/.github/skills/core/template-extract/SKILL.md +139 -139
  48. package/files/.github/skills/core/template-extract/USAGE.md +93 -93
  49. package/files/.github/skills/domain/README.md +51 -51
  50. package/files/.github/skills/sync/menu-sync/SKILL.md +263 -263
  51. package/files/.github/skills/sync/menu-sync/USAGE.md +104 -104
  52. package/files/.github/skills/sync/menu-sync/env/env.local.json +7 -7
  53. package/files/.github/skills/sync/menu-sync/env/guide.md +99 -99
  54. package/files/.github/skills/sync/permission-sync/SKILL.draft.md +91 -91
  55. package/files/.github/standards/01-toolchain.md +57 -57
  56. package/files/.github/standards/02-code-structure.md +111 -111
  57. package/files/.github/standards/03-comments.md +53 -53
  58. package/files/.github/standards/04-coding-basics.md +33 -33
  59. package/files/.github/standards/05-logging.md +38 -38
  60. package/files/.github/standards/06-security.md +44 -44
  61. package/files/.github/standards/07-config.md +52 -52
  62. package/files/.github/standards/08-git.md +60 -60
  63. package/files/.github/standards/09-typescript.md +71 -71
  64. package/files/.github/standards/10-pinia.md +57 -57
  65. package/files/.github/standards/11-form-validation.md +81 -81
  66. package/files/.github/standards/12-base-table.md +153 -153
  67. package/files/.github/standards/13-platform-components.md +123 -123
  68. package/files/.github/standards/index.md +89 -89
  69. package/files/.kiro/settings/mcp.json +8 -0
  70. package/files/.mcp.json +8 -0
  71. package/files/.vscode/mcp.json +9 -0
  72. package/files/demo/produce/aiflow/mmwr-customer-apply-change-history/data.ts +196 -196
  73. package/files/demo/produce/aiflow/mmwr-customer-apply-change-history/index.scss +150 -150
  74. package/files/demo/produce/aiflow/mmwr-customer-apply-change-history/index.vue +79 -79
  75. package/files/docs/jh-date-range.md +257 -257
  76. package/files/docs/jh-date.md +222 -222
  77. package/files/docs/jh-dept-picker.md +190 -190
  78. package/files/docs/jh-drag-row.md +590 -590
  79. package/files/docs/jh-file-upload.md +216 -216
  80. package/files/docs/jh-picker.md +218 -218
  81. package/files/docs/jh-select.md +148 -148
  82. package/files/docs/jh-text.md +248 -248
  83. package/files/docs/jh-user-picker.md +197 -197
  84. package/files/src/components/global/C_RightToolbar/data.ts +228 -228
  85. package/files/src/components/global/C_RightToolbar/index.scss +44 -44
  86. package/files/src/components/global/C_Splitter/index.scss +61 -61
  87. package/files/src/components/global/C_SvgIcon/index.scss +15 -15
  88. package/files/src/components/global/C_TagStatus/index.scss +20 -20
  89. package/files/src/components/global/C_Tree/data.ts +61 -61
  90. package/files/src/components/local/c_listModal/index.scss +4 -4
  91. package/package.json +1 -1
@@ -1,196 +1,196 @@
1
- import { getAction } from "@jhlc/common-core/src/api/action";
2
- import { useRouter } from "vue-router";
3
- import { createChangeMockData } from "@/components/local/c_customerTabs/data";
4
- import type {
5
- BasicInfoForm,
6
- BusinessInfoRow
7
- } from "@/components/local/c_customerTabs/data";
8
-
9
- export const API_CONFIG = {
10
- changeHistoryList: "/sale/customerApply/changeHistory/list",
11
- getById: "/sale/customerApply/changeHistory/getById",
12
- getDiffById: "/sale/customerApply/changeHistory/getDiffById"
13
- } as const;
14
-
15
- export interface HistoryRecord {
16
- id: string;
17
- changeType: string;
18
- changeTime: string;
19
- changePerson: string;
20
- }
21
-
22
- /** 变更历史记录 mock 数据(对齐原型截图,首条为"数据变更"以便立即展示比对效果) */
23
- function createHistoryListMock(): HistoryRecord[] {
24
- return [
25
- {
26
- id: "h001",
27
- changeType: "数据变更",
28
- changeTime: "2025/12/15 13:48:07",
29
- changePerson: "变更人姓名"
30
- },
31
- {
32
- id: "h002",
33
- changeType: "数据新增",
34
- changeTime: "2025/12/15 13:48:07",
35
- changePerson: "新增人姓名"
36
- },
37
- {
38
- id: "h003",
39
- changeType: "数据新增",
40
- changeTime: "2025/12/15 13:48:07",
41
- changePerson: "新增人姓名"
42
- },
43
- {
44
- id: "h004",
45
- changeType: "数据变更",
46
- changeTime: "2025/12/15 13:48:07",
47
- changePerson: "变更人姓名"
48
- },
49
- {
50
- id: "h005",
51
- changeType: "数据变更",
52
- changeTime: "2025/12/15 13:48:07",
53
- changePerson: "变更人姓名"
54
- },
55
- {
56
- id: "h006",
57
- changeType: "数据新增",
58
- changeTime: "2025/12/15 13:48:07",
59
- changePerson: "新增人姓名"
60
- },
61
- {
62
- id: "h007",
63
- changeType: "数据新增",
64
- changeTime: "2025/12/15 13:48:07",
65
- changePerson: "新增人姓名"
66
- }
67
- ];
68
- }
69
-
70
- /** 变更比对 mock:旧版数据(对齐原型截图中的上下比对效果)
71
- * 使用显示标签(非值码),以便 diff-old-value 直接展示中文。
72
- * - basicInfo.taxCategory: "小规模纳税人"(旧)vs "一级纳税人"(新)
73
- * - basicInfo.relationType: "02-合并关系人"(旧)vs "03-非关系人"(新)
74
- * - businessInfoList[0]: salesType "外销"(旧)vs "内销"(新),customerLevel "B3" vs "B1"
75
- */
76
- function createDiffMockData(): {
77
- basicInfo: BasicInfoForm;
78
- businessInfoList: BusinessInfoRow[];
79
- } {
80
- const current = createChangeMockData();
81
- return {
82
- basicInfo: {
83
- ...current.basicInfo,
84
- taxCategory: "小规模纳税人",
85
- relationType: "02-合并关系人"
86
- },
87
- businessInfoList: current.businessInfoList.map((row, idx) => {
88
- if (idx === 0) {
89
- return { ...row, salesType: "外销", customerLevel: "B3" };
90
- }
91
- return { ...row };
92
- })
93
- };
94
- }
95
-
96
- export function useChangeHistory(tabsRef: any) {
97
- const router = useRouter();
98
- const loading = ref(false);
99
- const historyLoading = ref(false);
100
- const historyList = ref<HistoryRecord[]>([]);
101
- const selectedId = ref<string>("");
102
- const isMockMode = ref(false);
103
-
104
- // ─── 真实接口模式(有 id 时调用) ───
105
-
106
- async function loadHistoryList(applyId: string) {
107
- isMockMode.value = false;
108
- historyLoading.value = true;
109
- try {
110
- const res = await getAction(API_CONFIG.changeHistoryList, { applyId });
111
- if (res?.data?.length) {
112
- historyList.value = res.data;
113
- }
114
- } finally {
115
- historyLoading.value = false;
116
- if (historyList.value.length > 0) {
117
- await loadHistoryDetail(historyList.value[0].id);
118
- }
119
- }
120
- }
121
-
122
- async function loadHistoryDetail(id: string) {
123
- selectedId.value = id;
124
- loading.value = true;
125
- const currentRecord = historyList.value.find((r) => r.id === id);
126
- const isChangeType = currentRecord?.changeType.includes("变更");
127
- try {
128
- const res = await getAction(API_CONFIG.getById, { id });
129
- if (res?.data) {
130
- tabsRef.value?.loadData(res.data);
131
- if (isChangeType) {
132
- const diffRes = await getAction(API_CONFIG.getDiffById, { id }).catch(
133
- () => null
134
- );
135
- if (diffRes?.data) {
136
- tabsRef.value?.loadDiffData(diffRes.data);
137
- } else {
138
- tabsRef.value?.clearDiffData?.();
139
- }
140
- } else {
141
- tabsRef.value?.clearDiffData?.();
142
- }
143
- }
144
- } finally {
145
- loading.value = false;
146
- }
147
- }
148
-
149
- // ─── Mock 模式(无 id 时调用,纯本地数据,零接口请求) ───
150
-
151
- function loadMockData() {
152
- isMockMode.value = true;
153
- historyList.value = createHistoryListMock();
154
- if (historyList.value.length > 0) {
155
- nextTick(() => selectMockDetail(historyList.value[0].id));
156
- }
157
- }
158
-
159
- function selectMockDetail(id: string) {
160
- selectedId.value = id;
161
- const currentRecord = historyList.value.find((r) => r.id === id);
162
- const isChangeType = currentRecord?.changeType.includes("变更");
163
- tabsRef.value?.loadData(createChangeMockData());
164
- if (isChangeType) {
165
- tabsRef.value?.loadDiffData(createDiffMockData());
166
- } else {
167
- tabsRef.value?.clearDiffData?.();
168
- }
169
- }
170
-
171
- // ─── 公共 ───
172
-
173
- function handleSelectHistory(item: HistoryRecord) {
174
- if (item.id === selectedId.value) return;
175
- if (isMockMode.value) {
176
- selectMockDetail(item.id);
177
- } else {
178
- loadHistoryDetail(item.id);
179
- }
180
- }
181
-
182
- function handleCancel() {
183
- router.back();
184
- }
185
-
186
- return {
187
- loading,
188
- historyLoading,
189
- historyList,
190
- selectedId,
191
- loadHistoryList,
192
- loadMockData,
193
- handleSelectHistory,
194
- handleCancel
195
- };
196
- }
1
+ import { getAction } from "@jhlc/common-core/src/api/action";
2
+ import { useRouter } from "vue-router";
3
+ import { createChangeMockData } from "@/components/local/c_customerTabs/data";
4
+ import type {
5
+ BasicInfoForm,
6
+ BusinessInfoRow
7
+ } from "@/components/local/c_customerTabs/data";
8
+
9
+ export const API_CONFIG = {
10
+ changeHistoryList: "/sale/customerApply/changeHistory/list",
11
+ getById: "/sale/customerApply/changeHistory/getById",
12
+ getDiffById: "/sale/customerApply/changeHistory/getDiffById"
13
+ } as const;
14
+
15
+ export interface HistoryRecord {
16
+ id: string;
17
+ changeType: string;
18
+ changeTime: string;
19
+ changePerson: string;
20
+ }
21
+
22
+ /** 变更历史记录 mock 数据(对齐原型截图,首条为"数据变更"以便立即展示比对效果) */
23
+ function createHistoryListMock(): HistoryRecord[] {
24
+ return [
25
+ {
26
+ id: "h001",
27
+ changeType: "数据变更",
28
+ changeTime: "2025/12/15 13:48:07",
29
+ changePerson: "变更人姓名"
30
+ },
31
+ {
32
+ id: "h002",
33
+ changeType: "数据新增",
34
+ changeTime: "2025/12/15 13:48:07",
35
+ changePerson: "新增人姓名"
36
+ },
37
+ {
38
+ id: "h003",
39
+ changeType: "数据新增",
40
+ changeTime: "2025/12/15 13:48:07",
41
+ changePerson: "新增人姓名"
42
+ },
43
+ {
44
+ id: "h004",
45
+ changeType: "数据变更",
46
+ changeTime: "2025/12/15 13:48:07",
47
+ changePerson: "变更人姓名"
48
+ },
49
+ {
50
+ id: "h005",
51
+ changeType: "数据变更",
52
+ changeTime: "2025/12/15 13:48:07",
53
+ changePerson: "变更人姓名"
54
+ },
55
+ {
56
+ id: "h006",
57
+ changeType: "数据新增",
58
+ changeTime: "2025/12/15 13:48:07",
59
+ changePerson: "新增人姓名"
60
+ },
61
+ {
62
+ id: "h007",
63
+ changeType: "数据新增",
64
+ changeTime: "2025/12/15 13:48:07",
65
+ changePerson: "新增人姓名"
66
+ }
67
+ ];
68
+ }
69
+
70
+ /** 变更比对 mock:旧版数据(对齐原型截图中的上下比对效果)
71
+ * 使用显示标签(非值码),以便 diff-old-value 直接展示中文。
72
+ * - basicInfo.taxCategory: "小规模纳税人"(旧)vs "一级纳税人"(新)
73
+ * - basicInfo.relationType: "02-合并关系人"(旧)vs "03-非关系人"(新)
74
+ * - businessInfoList[0]: salesType "外销"(旧)vs "内销"(新),customerLevel "B3" vs "B1"
75
+ */
76
+ function createDiffMockData(): {
77
+ basicInfo: BasicInfoForm;
78
+ businessInfoList: BusinessInfoRow[];
79
+ } {
80
+ const current = createChangeMockData();
81
+ return {
82
+ basicInfo: {
83
+ ...current.basicInfo,
84
+ taxCategory: "小规模纳税人",
85
+ relationType: "02-合并关系人"
86
+ },
87
+ businessInfoList: current.businessInfoList.map((row, idx) => {
88
+ if (idx === 0) {
89
+ return { ...row, salesType: "外销", customerLevel: "B3" };
90
+ }
91
+ return { ...row };
92
+ })
93
+ };
94
+ }
95
+
96
+ export function useChangeHistory(tabsRef: any) {
97
+ const router = useRouter();
98
+ const loading = ref(false);
99
+ const historyLoading = ref(false);
100
+ const historyList = ref<HistoryRecord[]>([]);
101
+ const selectedId = ref<string>("");
102
+ const isMockMode = ref(false);
103
+
104
+ // ─── 真实接口模式(有 id 时调用) ───
105
+
106
+ async function loadHistoryList(applyId: string) {
107
+ isMockMode.value = false;
108
+ historyLoading.value = true;
109
+ try {
110
+ const res = await getAction(API_CONFIG.changeHistoryList, { applyId });
111
+ if (res?.data?.length) {
112
+ historyList.value = res.data;
113
+ }
114
+ } finally {
115
+ historyLoading.value = false;
116
+ if (historyList.value.length > 0) {
117
+ await loadHistoryDetail(historyList.value[0].id);
118
+ }
119
+ }
120
+ }
121
+
122
+ async function loadHistoryDetail(id: string) {
123
+ selectedId.value = id;
124
+ loading.value = true;
125
+ const currentRecord = historyList.value.find((r) => r.id === id);
126
+ const isChangeType = currentRecord?.changeType.includes("变更");
127
+ try {
128
+ const res = await getAction(API_CONFIG.getById, { id });
129
+ if (res?.data) {
130
+ tabsRef.value?.loadData(res.data);
131
+ if (isChangeType) {
132
+ const diffRes = await getAction(API_CONFIG.getDiffById, { id }).catch(
133
+ () => null
134
+ );
135
+ if (diffRes?.data) {
136
+ tabsRef.value?.loadDiffData(diffRes.data);
137
+ } else {
138
+ tabsRef.value?.clearDiffData?.();
139
+ }
140
+ } else {
141
+ tabsRef.value?.clearDiffData?.();
142
+ }
143
+ }
144
+ } finally {
145
+ loading.value = false;
146
+ }
147
+ }
148
+
149
+ // ─── Mock 模式(无 id 时调用,纯本地数据,零接口请求) ───
150
+
151
+ function loadMockData() {
152
+ isMockMode.value = true;
153
+ historyList.value = createHistoryListMock();
154
+ if (historyList.value.length > 0) {
155
+ nextTick(() => selectMockDetail(historyList.value[0].id));
156
+ }
157
+ }
158
+
159
+ function selectMockDetail(id: string) {
160
+ selectedId.value = id;
161
+ const currentRecord = historyList.value.find((r) => r.id === id);
162
+ const isChangeType = currentRecord?.changeType.includes("变更");
163
+ tabsRef.value?.loadData(createChangeMockData());
164
+ if (isChangeType) {
165
+ tabsRef.value?.loadDiffData(createDiffMockData());
166
+ } else {
167
+ tabsRef.value?.clearDiffData?.();
168
+ }
169
+ }
170
+
171
+ // ─── 公共 ───
172
+
173
+ function handleSelectHistory(item: HistoryRecord) {
174
+ if (item.id === selectedId.value) return;
175
+ if (isMockMode.value) {
176
+ selectMockDetail(item.id);
177
+ } else {
178
+ loadHistoryDetail(item.id);
179
+ }
180
+ }
181
+
182
+ function handleCancel() {
183
+ router.back();
184
+ }
185
+
186
+ return {
187
+ loading,
188
+ historyLoading,
189
+ historyList,
190
+ selectedId,
191
+ loadHistoryList,
192
+ loadMockData,
193
+ handleSelectHistory,
194
+ handleCancel
195
+ };
196
+ }
@@ -1,150 +1,150 @@
1
- .change-history-page {
2
- display: flex !important;
3
- padding: 0 !important;
4
- height: 100%;
5
- overflow: hidden;
6
-
7
- /* ─── 左侧:变更记录面板 ─── */
8
- .history-panel {
9
- width: 200px;
10
- flex-shrink: 0;
11
- border-right: 1px solid #e4e7ed;
12
- display: flex;
13
- flex-direction: column;
14
- overflow: hidden;
15
- background: #fff;
16
-
17
- &__header {
18
- padding: 12px 16px;
19
- font-size: 14px;
20
- font-weight: 600;
21
- color: #303133;
22
- border-bottom: 1px solid #e4e7ed;
23
- flex-shrink: 0;
24
- }
25
-
26
- &__list {
27
- flex: 1;
28
- overflow-y: auto;
29
- padding: 4px 0;
30
- }
31
- }
32
-
33
- .history-card {
34
- display: flex;
35
- align-items: flex-start;
36
- padding: 10px 16px;
37
- cursor: pointer;
38
- border-left: 3px solid transparent;
39
- transition: background 0.15s;
40
- gap: 8px;
41
-
42
- &:hover {
43
- background: #f5f7fa;
44
- }
45
-
46
- &.is-active {
47
- background: #ecf5ff;
48
- border-left-color: #409eff;
49
- }
50
-
51
- &__dot {
52
- width: 8px;
53
- height: 8px;
54
- border-radius: 50%;
55
- margin-top: 5px;
56
- flex-shrink: 0;
57
-
58
- &.is-add {
59
- background: #409eff;
60
- }
61
- &.is-change {
62
- background: #e6a23c;
63
- }
64
- }
65
-
66
- &__content {
67
- flex: 1;
68
- min-width: 0;
69
- }
70
-
71
- &__type {
72
- font-size: 13px;
73
- font-weight: 500;
74
- color: #303133;
75
- line-height: 18px;
76
- }
77
-
78
- &__date {
79
- font-size: 12px;
80
- color: #909399;
81
- line-height: 18px;
82
- }
83
-
84
- &__person {
85
- font-size: 12px;
86
- color: #606266;
87
- line-height: 18px;
88
- }
89
- }
90
-
91
- .history-empty {
92
- padding: 32px 16px;
93
- text-align: center;
94
- color: #909399;
95
- font-size: 13px;
96
- }
97
-
98
- /* ─── 右侧:变更详情面板 ─── */
99
- .detail-panel {
100
- flex: 1;
101
- overflow: hidden;
102
- display: flex;
103
- flex-direction: column;
104
- background: #fff;
105
-
106
- &__body {
107
- flex: 1;
108
- overflow-y: auto;
109
- padding: 0 16px 16px;
110
- }
111
- }
112
-
113
- .page-header {
114
- display: flex;
115
- align-items: center;
116
- padding: 10px 16px;
117
- flex-shrink: 0;
118
-
119
- .page-title {
120
- font-size: 16px;
121
- font-weight: 600;
122
- margin-right: 10px;
123
- }
124
-
125
- .page-tag {
126
- display: inline-block;
127
- padding: 1px 8px;
128
- font-size: 12px;
129
- border-radius: 4px;
130
- margin-right: 8px;
131
-
132
- &--change {
133
- background-color: var(--el-color-primary-light-9);
134
- color: var(--el-color-primary);
135
- border: 1px solid var(--el-color-primary-light-7);
136
- }
137
-
138
- &--status {
139
- background-color: var(--el-color-warning-light-9);
140
- color: var(--el-color-warning);
141
- border: 1px solid var(--el-color-warning-light-7);
142
- }
143
- }
144
- }
145
-
146
- .page-toolbar {
147
- padding: 0 16px 8px;
148
- flex-shrink: 0;
149
- }
150
- }
1
+ .change-history-page {
2
+ display: flex !important;
3
+ padding: 0 !important;
4
+ height: 100%;
5
+ overflow: hidden;
6
+
7
+ /* ─── 左侧:变更记录面板 ─── */
8
+ .history-panel {
9
+ width: 200px;
10
+ flex-shrink: 0;
11
+ border-right: 1px solid #e4e7ed;
12
+ display: flex;
13
+ flex-direction: column;
14
+ overflow: hidden;
15
+ background: #fff;
16
+
17
+ &__header {
18
+ padding: 12px 16px;
19
+ font-size: 14px;
20
+ font-weight: 600;
21
+ color: #303133;
22
+ border-bottom: 1px solid #e4e7ed;
23
+ flex-shrink: 0;
24
+ }
25
+
26
+ &__list {
27
+ flex: 1;
28
+ overflow-y: auto;
29
+ padding: 4px 0;
30
+ }
31
+ }
32
+
33
+ .history-card {
34
+ display: flex;
35
+ align-items: flex-start;
36
+ padding: 10px 16px;
37
+ cursor: pointer;
38
+ border-left: 3px solid transparent;
39
+ transition: background 0.15s;
40
+ gap: 8px;
41
+
42
+ &:hover {
43
+ background: #f5f7fa;
44
+ }
45
+
46
+ &.is-active {
47
+ background: #ecf5ff;
48
+ border-left-color: #409eff;
49
+ }
50
+
51
+ &__dot {
52
+ width: 8px;
53
+ height: 8px;
54
+ border-radius: 50%;
55
+ margin-top: 5px;
56
+ flex-shrink: 0;
57
+
58
+ &.is-add {
59
+ background: #409eff;
60
+ }
61
+ &.is-change {
62
+ background: #e6a23c;
63
+ }
64
+ }
65
+
66
+ &__content {
67
+ flex: 1;
68
+ min-width: 0;
69
+ }
70
+
71
+ &__type {
72
+ font-size: 13px;
73
+ font-weight: 500;
74
+ color: #303133;
75
+ line-height: 18px;
76
+ }
77
+
78
+ &__date {
79
+ font-size: 12px;
80
+ color: #909399;
81
+ line-height: 18px;
82
+ }
83
+
84
+ &__person {
85
+ font-size: 12px;
86
+ color: #606266;
87
+ line-height: 18px;
88
+ }
89
+ }
90
+
91
+ .history-empty {
92
+ padding: 32px 16px;
93
+ text-align: center;
94
+ color: #909399;
95
+ font-size: 13px;
96
+ }
97
+
98
+ /* ─── 右侧:变更详情面板 ─── */
99
+ .detail-panel {
100
+ flex: 1;
101
+ overflow: hidden;
102
+ display: flex;
103
+ flex-direction: column;
104
+ background: #fff;
105
+
106
+ &__body {
107
+ flex: 1;
108
+ overflow-y: auto;
109
+ padding: 0 16px 16px;
110
+ }
111
+ }
112
+
113
+ .page-header {
114
+ display: flex;
115
+ align-items: center;
116
+ padding: 10px 16px;
117
+ flex-shrink: 0;
118
+
119
+ .page-title {
120
+ font-size: 16px;
121
+ font-weight: 600;
122
+ margin-right: 10px;
123
+ }
124
+
125
+ .page-tag {
126
+ display: inline-block;
127
+ padding: 1px 8px;
128
+ font-size: 12px;
129
+ border-radius: 4px;
130
+ margin-right: 8px;
131
+
132
+ &--change {
133
+ background-color: var(--el-color-primary-light-9);
134
+ color: var(--el-color-primary);
135
+ border: 1px solid var(--el-color-primary-light-7);
136
+ }
137
+
138
+ &--status {
139
+ background-color: var(--el-color-warning-light-9);
140
+ color: var(--el-color-warning);
141
+ border: 1px solid var(--el-color-warning-light-7);
142
+ }
143
+ }
144
+ }
145
+
146
+ .page-toolbar {
147
+ padding: 0 16px 8px;
148
+ flex-shrink: 0;
149
+ }
150
+ }