|
|
@@ -22,15 +22,27 @@ const requiredTokens = [
|
|
|
'--radius-md: 8px'
|
|
|
]
|
|
|
|
|
|
-const bannedEmoji = /[📋📌⚡⏳✅❌🎯🚀💡🔥]/u
|
|
|
+const bannedEmoji = /[📋📌⚡⏳✅❌🎯🚀💡🔥💬]/u
|
|
|
const bannedDecor = /(radial-gradient|gradient orb|bokeh|blur\(60px\)|border-radius:\s*(1[2-9]|[2-9]\d)px)/
|
|
|
+const bannedTextIcon = /[←→↑↓]/
|
|
|
+const rawHexColor = /#[0-9a-fA-F]{3,8}\b/
|
|
|
+const bannedLegacyPatterns = [
|
|
|
+ { re: /page-hero/, msg: '禁止 page-hero(改用 data-toolbar)' },
|
|
|
+ { re: /section-badge/, msg: '禁止 section-badge 胶囊徽章' },
|
|
|
+ { re: /grade-ring/, msg: '禁止 grade-ring 圆环' },
|
|
|
+ { re: /score-hero/, msg: '禁止 score-hero 渐变区' },
|
|
|
+ { re: /hint-card/, msg: '禁止 hint-card 大引导卡' },
|
|
|
+ { re: /conic-gradient/, msg: '禁止 conic-gradient' }
|
|
|
+]
|
|
|
const migratedMarkers = [
|
|
|
'clinical-shell',
|
|
|
'internal-login',
|
|
|
'period-workbench',
|
|
|
'period-status-strip',
|
|
|
'okr-workbench',
|
|
|
+ 'alignment-workbench',
|
|
|
'team-okr-workbench',
|
|
|
+ 'notification-workbench',
|
|
|
'review-workbench',
|
|
|
'scoring-worklist',
|
|
|
'result-workbench',
|
|
|
@@ -83,6 +95,7 @@ const myOkr = readFileSync(join(root, 'src/views/okr/MyOkrView.vue'), 'utf8')
|
|
|
const teamOkr = readFileSync(join(root, 'src/views/okr/TeamOkrView.vue'), 'utf8')
|
|
|
const scoringEdit = readFileSync(join(root, 'src/views/scoring/ScoringEditView.vue'), 'utf8')
|
|
|
const scoringList = readFileSync(join(root, 'src/views/scoring/ScoringListView.vue'), 'utf8')
|
|
|
+const myResult = readFileSync(join(root, 'src/views/scoring/MyResultView.vue'), 'utf8')
|
|
|
|
|
|
if (!layout.includes('clinical-shell')) failures.push('MainLayout must use clinical-shell')
|
|
|
if (!layout.includes('clinical-sidebar')) failures.push('MainLayout must use clinical-sidebar')
|
|
|
@@ -92,13 +105,43 @@ if (!periodList.includes('period-workbench')) failures.push('PeriodListView must
|
|
|
if (!periodList.includes('period-metrics')) failures.push('PeriodListView must show period-metrics')
|
|
|
if (!periodBanner.includes('period-status-strip')) failures.push('PeriodBanner must use period-status-strip')
|
|
|
if (!myOkr.includes('okr-workbench')) failures.push('MyOkrView must use okr-workbench')
|
|
|
-if (!myOkr.includes('okr-standard-panel')) failures.push('MyOkrView must use okr-standard-panel')
|
|
|
if (!teamOkr.includes('team-okr-workbench')) failures.push('TeamOkrView must use team-okr-workbench')
|
|
|
+if (!teamOkr.includes('@update:model-value="selectPeriod"')) failures.push('TeamOkrView period switch must reload subordinate OKRs')
|
|
|
if (!scoringEdit.includes('review-workbench')) failures.push('ScoringEditView must use review-workbench')
|
|
|
-if (!scoringEdit.includes('evidence-panel')) failures.push('ScoringEditView must use evidence-panel')
|
|
|
-if (!scoringEdit.includes('decision-panel')) failures.push('ScoringEditView must use decision-panel')
|
|
|
if (!scoringList.includes('scoring-worklist')) failures.push('ScoringListView must use scoring-worklist')
|
|
|
|
|
|
+// v2 信息架构断言
|
|
|
+if (!myOkr.includes('data-toolbar')) failures.push('MyOkrView must use data-toolbar (replaced page-hero)')
|
|
|
+if (!myOkr.includes('data-table')) failures.push('MyOkrView must use data-table (table-based O/KR)')
|
|
|
+if (!myOkr.includes('side-drawer__content') && !myOkr.includes('el-drawer')) {
|
|
|
+ failures.push('MyOkrView must use side drawer for KR detail/progress')
|
|
|
+}
|
|
|
+
|
|
|
+if (!scoringEdit.includes('compare-grid-3')) failures.push('ScoringEditView must use compare-grid-3 (3-column comparison)')
|
|
|
+if (!scoringEdit.includes('section-band')) failures.push('ScoringEditView must use section-band')
|
|
|
+if (!scoringEdit.includes('review-summary-bar')) failures.push('ScoringEditView must use review-summary-bar')
|
|
|
+
|
|
|
+if (!myResult.includes('metric-bar')) failures.push('MyResultView must use metric-bar (replaced grade-ring)')
|
|
|
+if (!myResult.includes('history-trend')) failures.push('MyResultView must use history-trend')
|
|
|
+if (myResult.includes('conic-gradient')) failures.push('MyResultView must not use conic-gradient (grade-ring removed)')
|
|
|
+
|
|
|
+if (!login.includes('underline-input')) failures.push('LoginView must use underline-input')
|
|
|
+if (!login.includes('login-brand')) failures.push('LoginView must use login-brand (full-screen split)')
|
|
|
+
|
|
|
+const v2LegacyCheckFiles = new Map([
|
|
|
+ ['src/components/MainLayout.vue', layout],
|
|
|
+ ['src/views/auth/LoginView.vue', login],
|
|
|
+ ['src/views/okr/MyOkrView.vue', myOkr],
|
|
|
+ ['src/views/scoring/ScoringEditView.vue', scoringEdit],
|
|
|
+ ['src/views/scoring/MyResultView.vue', myResult]
|
|
|
+])
|
|
|
+
|
|
|
+for (const [file, text] of v2LegacyCheckFiles) {
|
|
|
+ for (const { re, msg } of bannedLegacyPatterns) {
|
|
|
+ if (re.test(text)) failures.push(`${file}: ${msg}`)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
const requiredClasses = new Map([
|
|
|
['src/views/scoring/MyResultView.vue', 'result-workbench'],
|
|
|
['src/views/scoring/HistoryView.vue', 'history-workbench'],
|
|
|
@@ -106,7 +149,9 @@ const requiredClasses = new Map([
|
|
|
['src/views/org/OrgView.vue', 'org-workbench'],
|
|
|
['src/views/system/LogView.vue', 'log-workbench'],
|
|
|
['src/views/system/DimensionConfigView.vue', 'dimension-workbench'],
|
|
|
- ['src/views/period/KpiTemplateView.vue', 'template-workbench']
|
|
|
+ ['src/views/period/KpiTemplateView.vue', 'template-workbench'],
|
|
|
+ ['src/views/okr/AlignmentView.vue', 'alignment-workbench'],
|
|
|
+ ['src/views/notification/NotificationView.vue', 'notification-workbench']
|
|
|
])
|
|
|
|
|
|
for (const [file, className] of requiredClasses) {
|
|
|
@@ -121,6 +166,8 @@ for (const file of vueAndCssFiles) {
|
|
|
const mustFollowMedtechRules = rel.startsWith('src/styles/') || migratedMarkers.some((marker) => text.includes(marker))
|
|
|
if (mustFollowMedtechRules && bannedEmoji.test(text)) failures.push(`banned emoji in ${rel}`)
|
|
|
if (mustFollowMedtechRules && bannedDecor.test(text)) failures.push(`banned decorative style in ${rel}`)
|
|
|
+ if (mustFollowMedtechRules && rel !== 'src/styles/theme.css' && rawHexColor.test(text)) failures.push(`raw hex color in migrated file: ${rel}`)
|
|
|
+ if (mustFollowMedtechRules && bannedTextIcon.test(text)) failures.push(`text arrow used as icon in ${rel}`)
|
|
|
}
|
|
|
|
|
|
if (failures.length) {
|