diff --git a/_patch_ee_gate_migrate.py b/_patch_ee_gate_migrate.py deleted file mode 100644 index 3ddcfb6..0000000 --- a/_patch_ee_gate_migrate.py +++ /dev/null @@ -1,275 +0,0 @@ -#!/usr/bin/env python3 -"""Feature-gate v-if → "greyed out + upgrade prompt" migration. - -High-priority patches (grid/card rows that leave blank gaps): - - 1. home/index.vue L572 wf-stats-section: v-if="hasFeature('WORKFLOW_DAG_ENGINE')" - → always render; grey out with filter + ::after capture click → trigger upgrade dialog. - - 2. WorkflowList.vue L47 stat-card row 3rd card (pending_approve): v-if WORKFLOW_APPROVAL_FLOW - → always render (greyed-out 0 value + click interceptor to upgrade). - - 3. WorkflowList.vue L23 top button "审批中心": v-if WORKFLOW_APPROVAL_FLOW - → convert to v-feature.disable pattern (greyed button + upgrade prompt on click). - -Pattern reuse: just like charts-row 4th card solution already present in home/index.vue. - -Adds two helper composables per file so logic isn't duplicated: - eeGateT(key, fallback) — wraps i18n edition.* lookup with fallback - triggerEeUpgrade(code) — shows ElMessageBox.confirm + dispatches taurus:edition-upgrade -""" - -import pathlib - -def apply(p: pathlib.Path, patches: list[tuple[str, str, str]]): - content = p.read_text(encoding='utf-8') - for old, new, label in patches: - assert old in content, f"[{p.name}] Pattern for '{label}' NOT FOUND:\n{old[:200]}\n" - content = content.replace(old, new) - print(f" ✓ [{p.name}] {label}") - p.write_text(content, encoding='utf-8') - return content - -HOME = pathlib.Path("/media/jwj/TOSHIBA EXT/dev/taurus-stack-c/taurus-web/src/views/system/home/index.vue") -WFL = pathlib.Path("/media/jwj/TOSHIBA EXT/dev/taurus-stack-c/taurus-web/src/views/taurus/workflow/WorkflowList.vue") - -print("=== home/index.vue patches (wf-stats-section) ===") - -# ---------------- Patch HOME-1: template — remove v-if on wf-stats-section, gate the row ---------------- -HOME_P1_OLD = """
-
{{ T('workflow.sectionTitle') }}
-
""" -HOME_P1_NEW = """
-
{{ T('workflow.sectionTitle') }}
-
""" - -# ---------------- Patch HOME-2: script — add handleWfSectionClick + ee helpers near handleWfCardClick ---------------- -HOME_P2_OLD = """// 第 4 张卡片:EE 跳转工作流列表 / CE 弹升级提醒 -const handleWfCardClick = () => { - if (hasFeature('WORKFLOW_DAG_ENGINE')) { - goWfList(); - return; - } - // CE: 与 v-feature.disable 一致的 ElMessageBox 弹窗 - const tKey = (key: string, fallback: string) => { - try { - const v = t(`message.pages.edition.${key}`); - if (typeof v === 'string' && v && v !== `message.pages.edition.${key}`) return v; - } catch (_e) { /* noop */ } - return fallback; - }; - ElMessageBox.confirm( - tKey('enterpriseOnlyDesc', '该功能仅在 Taurus Ops 企业版中提供。升级到企业版即可解锁工作流引擎、DAG 编排、审批流、工单系统等全部高级能力。'), - tKey('enterpriseOnlyTitle', '企业版专属功能'), - { - confirmButtonText: tKey('upgradeAction', '立即升级'), - cancelButtonText: tKey('dismiss', '稍后再说'), - type: 'info', - showCancelButton: true, - closeOnClickModal: true, - } - ).then(() => { - window.dispatchEvent( - new CustomEvent('taurus:edition-upgrade', { detail: { code: 'WORKFLOW_DAG_ENGINE' } }) - ); - }).catch(() => { /* 用户取消 */ }); -};""" -HOME_P2_NEW = """// ---------- EE 升级拦截通用 helpers ---------- -const eeT = (key: string, fallback: string) => { - try { - const v = t(`message.pages.edition.${key}`); - if (typeof v === 'string' && v && v !== `message.pages.edition.${key}`) return v; - } catch (_e) { /* noop */ } - return fallback; -}; -const triggerEeUpgrade = (code: string, customDesc?: string) => { - ElMessageBox.confirm( - customDesc || eeT('enterpriseOnlyDesc', '该功能仅在 Taurus Ops 企业版中提供。升级到企业版即可解锁全部高级能力。'), - eeT('enterpriseOnlyTitle', '企业版专属功能'), - { - confirmButtonText: eeT('upgradeAction', '立即升级'), - cancelButtonText: eeT('dismiss', '稍后再说'), - type: 'info', - showCancelButton: true, - closeOnClickModal: true, - } - ).then(() => { - window.dispatchEvent(new CustomEvent('taurus:edition-upgrade', { detail: { code } })); - }).catch(() => { /* 用户取消 */ }); -}; - -// 第 4 张卡片:EE 跳转工作流列表 / CE 弹升级提醒 -const handleWfCardClick = () => { - if (hasFeature('WORKFLOW_DAG_ENGINE')) { - goWfList(); - return; - } - triggerEeUpgrade('WORKFLOW_DAG_ENGINE'); -}; - -// 工作流统计 6 卡片区块:EE 跳转工作流列表 / CE 弹升级提醒 -const handleWfSectionClick = (e: MouseEvent) => { - if (hasFeature('WORKFLOW_DAG_ENGINE')) return; - // 由 ee-gate-section::after 捕获点击,e.target 始终是父 div - e.stopPropagation(); - triggerEeUpgrade('WORKFLOW_DAG_ENGINE'); -};""" - -# ---------------- Patch HOME-3: style — add ee-gate-section grey mask ---------------- -HOME_P3_OLD = """.chart-container { - height: 220px; - width: 100%; - } - } -}""" -HOME_P3_NEW = """.chart-container { - height: 220px; - width: 100%; - } - } -} - -// ======== 统一 EE 功能区块置灰样式(原元素保留,::before 灰化 + ::after 捕获点击)======== -.ee-gate-section { - cursor: not-allowed; - position: relative; - - &::before { - content: ''; - position: absolute; - inset: 0; - border-radius: 8px; - backdrop-filter: grayscale(90%); - background: rgba(255, 255, 255, 0.4); - pointer-events: none; - z-index: 1; - } - - &::after { - content: ''; - position: absolute; - inset: 0; - cursor: not-allowed; - z-index: 2; - } - - &:hover { - // 阻止内部 card :hover transform 闪烁 - > * .wf-stat-card, > * .stat-card, > * .chart-card { - transform: none !important; - } - } -}""" - -apply(HOME, [ - (HOME_P1_OLD, HOME_P1_NEW, "wf-stats-section gate: always render"), - (HOME_P2_OLD, HOME_P2_NEW, "add eeT()/triggerEeUpgrade() helpers + handleWfSectionClick"), - (HOME_P3_OLD, HOME_P3_NEW, "add .ee-gate-section unified grey-mask CSS"), -]) - -print("\n=== WorkflowList.vue patches (stat card + top button) ===") - -# ---------------- Patch WFL-1: top 审批中心按钮 v-if → v-feature.disable ---------------- -WFL_P1_OLD = """ - {{ t('message.pages.workflowList.wlApprovalCenter') }} - - """ -WFL_P1_NEW = """ - {{ t('message.pages.workflowList.wlApprovalCenter') }} - - """ - -# ---------------- Patch WFL-2: stat card row 3rd (pending approval) v-if → always render, greyed ---------------- -WFL_P2_OLD = """
-
{{ stats.pending_approve }}
-
{{ t('message.pages.workflowList.wlStatPendingApprove') }}
-
""" -WFL_P2_NEW = """
-
{{ hasFeature('WORKFLOW_APPROVAL_FLOW') ? stats.pending_approve : 0 }}
-
- {{ t('message.pages.workflowList.wlStatPendingApprove') }} - EE -
-
""" - -# ---------------- Patch WFL-3: add import ElMessageBox if needed (should already exist per grep) ---------------- -# Per grep, already have: import { ElMessage, ElMessageBox, ElNotification, ElButton } from 'element-plus'; -# ---------------- Patch WFL-4: add onApprovalCenterBtnClick + onApprovalStatCardClick + ee helpers ---------------- -# Find end of imports (setup script region) — insert handlers near existing goApproveCenter -WFL_P4_OLD = """const goApproveCenter = () => router.push({ path: '/workflow/approve' });""" -WFL_P4_NEW = """// ---------- EE 升级拦截通用 helpers ---------- -const eeT = (key: string, fallback: string) => { - const { t: tl } = useI18n(); - try { - const v = tl(`message.pages.edition.${key}`); - if (typeof v === 'string' && v && v !== `message.pages.edition.${key}`) return v; - } catch (_e) { /* noop */ } - return fallback; -}; -const triggerEeUpgrade = (code: string, customDesc?: string) => { - ElMessageBox.confirm( - customDesc || eeT('enterpriseOnlyDesc', '该功能仅在 Taurus Ops 企业版中提供。升级到企业版即可解锁审批流、工作流、知识工单等全部高级能力。'), - eeT('enterpriseOnlyTitle', '企业版专属功能'), - { - confirmButtonText: eeT('upgradeAction', '立即升级'), - cancelButtonText: eeT('dismiss', '稍后再说'), - type: 'info', - showCancelButton: true, - closeOnClickModal: true, - } - ).then(() => { - window.dispatchEvent(new CustomEvent('taurus:edition-upgrade', { detail: { code } })); - }).catch(() => { /* 用户取消 */ }); -}; - -const goApproveCenter = () => router.push({ path: '/workflow/approve' }); -// 顶部「审批中心」按钮:EE 正常跳转 / CE 弹升级提醒 -const onApprovalCenterBtnClick = () => { - if (hasFeature('WORKFLOW_APPROVAL_FLOW')) { - goApproveCenter(); - return; - } - triggerEeUpgrade('WORKFLOW_APPROVAL_FLOW'); -}; -// 统计卡「待审批」:EE 正常跳转审批中心 / CE 弹升级提醒 -const onApprovalStatCardClick = () => { - if (hasFeature('WORKFLOW_APPROVAL_FLOW')) { - goApproveCenter(); - return; - } - triggerEeUpgrade('WORKFLOW_APPROVAL_FLOW'); -};""" - -# ---------------- Patch WFL-5: add .ee-gate-card CSS (at bottom of -WFL_P5_OLD = """/* ====== Scrollbar polish for category tree ====== */""" # common pattern -WFL_P5_NEW = """.ee-gate-card.is-ee-gate { - cursor: not-allowed; - position: relative; - filter: grayscale(90%) opacity(0.65); - background: repeating-linear-gradient(45deg, #fafafa, #fafafa 8px, #f4f4f5 8px, #f4f4f5 16px) !important; - box-shadow: none !important; - - &:hover { transform: none !important; } - .stat-num { user-select: none; } -} - -/* ====== Scrollbar polish for category tree ====== */""" - -apply(WFL, [ - (WFL_P1_OLD, WFL_P1_NEW, "top 审批中心 button: v-if → disabled + click gate"), - (WFL_P2_OLD, WFL_P2_NEW, "stat card 待审批 card: v-if → always render greyed + EE tag"), - (WFL_P4_OLD, WFL_P4_NEW, "add ee helpers + onApprovalCenterBtnClick + onApprovalStatCardClick"), - (WFL_P5_OLD, WFL_P5_NEW, "append .ee-gate-card.is-ee-gate greyscale stripe style"), -]) - -print("\n✓ All high-priority grid/card-row gate migrations applied.") \ No newline at end of file diff --git a/_patch_home_final.py b/_patch_home_final.py deleted file mode 100644 index 00968c9..0000000 --- a/_patch_home_final.py +++ /dev/null @@ -1,161 +0,0 @@ -#!/usr/bin/env python3 -"""Home approval-section & right-col migration — last 2 grid gate items.""" - -import pathlib - -HOME = pathlib.Path("/media/jwj/TOSHIBA EXT/dev/taurus-stack-c/taurus-web/src/views/system/home/index.vue") -content = HOME.read_text(encoding='utf-8') - -# ============= PATCH 1: approval-section outer v-if → always render greyed wrapper ============= -P1_OLD = """
-
{{ T('approval.sectionTitle') }}
-
""" -P1_NEW = """
-
{{ T('approval.sectionTitle') }}
-
""" -assert P1_OLD in content, "approval-section outer v-if not found" -content = content.replace(P1_OLD, P1_NEW) -print("✓ approval-section outer gate applied") - -# ============= PATCH 2: 5 inner approval cards — v-if → always render greyed (click per-card code) ============= -def replace_card(old_code: str, feature_code: str, click_fn: str, go_fn: str, num_var: str): - global content - # The exact template pattern to replace - P_OLD = f"""
""" - if P_OLD not in content: - print(f" · SKIPPED card {feature_code} — pattern not found (maybe already patched?)") - return - P_NEW = f"""
""" - content = content.replace(P_OLD, P_NEW) - # Update the number var inside the card — show 0 in CE - content = content.replace( - f"
{{ {num_var} }}
", - f"
{{ hasFeature('{feature_code}') ? {num_var} : 0 }}
", - 1 # only the first match in the block just replaced — safe - ) - print(f" ✓ card '{feature_code}' gated") - -# Cards defined in page order (file lines 544-572): -replace_card("SCRIPT_APPROVAL_FLOW", "SCRIPT_APPROVAL_FLOW", "onApprovalScriptCardClick", "goApprovalScript", "scriptApprovalPending") -replace_card("WORKFLOW_APPROVAL_FLOW", "WORKFLOW_APPROVAL_FLOW", "onApprovalWfCardClick", "goApprovalWf", "wfApprovalPending") -replace_card("OPS_EXECUTION_APPROVAL", "OPS_EXECUTION_APPROVAL", "onApprovalScriptExecCardClick", "goApprovalScriptExec", "scriptExecApprovalPending") -replace_card("OPS_EXECUTION_APPROVAL (2)", "OPS_EXECUTION_APPROVAL", "onApprovalCommandExecCardClick", "goApprovalCommandExec", "commandExecApprovalPending") -# Need exact click fn name match for 4th card (command exec): -P_CMD_OLD = """
""" -if P_CMD_OLD in content: - P_CMD_NEW = """
""" - content = content.replace(P_CMD_OLD, P_CMD_NEW) - # Replace the num var line for THIS card — commandExecApprovalPending - content = content.replace( - "
{{ commandExecApprovalPending }}
", - "
{{ hasFeature('OPS_EXECUTION_APPROVAL') ? commandExecApprovalPending : 0 }}
", - ) - print(" ✓ card 'OPS_EXECUTION_APPROVAL cmd' gated") - -# 5th card (wf exec approval) -P_WFEXEC_OLD = """
""" -if P_WFEXEC_OLD in content: - P_WFEXEC_NEW = """
""" - content = content.replace(P_WFEXEC_OLD, P_WFEXEC_NEW) - content = content.replace( - "
{{ wfExecApprovalPending }}
", - "
{{ hasFeature('OPS_EXECUTION_APPROVAL') ? wfExecApprovalPending : 0 }}
", - ) - print(" ✓ card 'OPS_EXECUTION_APPROVAL wf' gated") - -# ============= PATCH 3: right-col (定时任务) v-if → gate ============= -P3_OLD = """
""" -P3_NEW = """
""" -assert P3_OLD in content, "right-col v-if not found" -content = content.replace(P3_OLD, P3_NEW) -print("✓ right-col (schedule) gate applied") - -# ============= PATCH 4: Add per-card click handlers + 2 section click handlers after triggerEeUpgrade ============= -P4_OLD = """// 工作流统计 6 卡片区块:EE 跳转工作流列表 / CE 弹升级提醒 -const handleWfSectionClick = (e: MouseEvent) => { - if (hasFeature('WORKFLOW_DAG_ENGINE')) return; - // 由 ee-gate-section::after 捕获点击,e.target 始终是父 div - e.stopPropagation(); - triggerEeUpgrade('WORKFLOW_DAG_ENGINE'); -};""" -P4_NEW = P4_OLD + """ - -// ---------- Home Approval Section 5 cards - individual gates ---------- -function _guardFeature(code: string, goFn: () => void, evt?: MouseEvent): void { - if (hasFeature(code)) { - goFn(); - return; - } - if (evt) evt.stopPropagation(); - triggerEeUpgrade(code); -} -const onApprovalScriptCardClick = (e?: MouseEvent) => _guardFeature('SCRIPT_APPROVAL_FLOW', goApprovalScript, e); -const onApprovalWfCardClick = (e?: MouseEvent) => _guardFeature('WORKFLOW_APPROVAL_FLOW', goApprovalWf, e); -const onApprovalScriptExecCardClick = (e?: MouseEvent) => _guardFeature('OPS_EXECUTION_APPROVAL', goApprovalScriptExec, e); -const onApprovalCommandExecCardClick = (e?: MouseEvent) => _guardFeature('OPS_EXECUTION_APPROVAL', goApprovalCommandExec, e); -const onApprovalWfExecCardClick = (e?: MouseEvent) => _guardFeature('OPS_EXECUTION_APPROVAL', goApprovalWfExec, e); -// Outer approval section background click — only triggers if user clicks the gap -const handleApprovalSectionClick = (e: MouseEvent) => { - if (hasFeature('SCRIPT_APPROVAL_FLOW') || hasFeature('WORKFLOW_APPROVAL_FLOW') || hasFeature('OPS_EXECUTION_APPROVAL')) return; - // CE: 所有审批都没有 → 弹工作流审批 code 做兜底升级提示 - e.stopPropagation(); - triggerEeUpgrade('WORKFLOW_APPROVAL_FLOW'); -}; - -// ---------- Home 我的定时任务 right-col gate ---------- -const goSchedule = () => router.push('/ops/schedule'); -const handleScheduleColClick = (e: MouseEvent) => { - if (hasFeature('SCRIPT_TASK_UNIFIED')) return; - e.stopPropagation(); - triggerEeUpgrade('SCRIPT_TASK_UNIFIED'); -};""" - -assert P4_OLD in content, "handleWfSectionClick anchor for new handlers not found" -content = content.replace(P4_OLD, P4_NEW) -print("✓ added 5 per-card approval handlers + schedule col handler") - -# ============= PATCH 5: CSS — extend existing .ee-gate-section rule to cover .approval-card inside ============= -# Already have `.ee-gate-section` in file; also make per-card .ee-gate-card.is-ee-gate for -# standalone cards (single approval card inside a section with mixed CE/EE). -# Append just BEFORE the closing tag of style block (find last .chart-container line as anchor) -P5_OLD = """} -} - -// ======== 统一 EE 功能区块置灰样式""" -P5_NEW = """} -} - -// ======== EE Gate 单个卡片置灰(用于 grid-row 内部的独立卡片被 v-if 移除场景,不依赖父 section)======== -.ee-gate-card.is-ee-gate { - cursor: not-allowed; - position: relative; - filter: grayscale(90%) opacity(0.65); - background: repeating-linear-gradient(45deg, #fafafa, #fafafa 8px, #f4f4f5 8px, #f4f4f5 16px) !important; - box-shadow: none !important; - - &:hover { transform: none !important; box-shadow: 0 2px 8px rgba(0,0,0,0.04) !important; } - * { user-select: none; } -} - -// ======== 统一 EE 功能区块置灰""" -assert P5_OLD in content, "CSS anchor for ee-gate-card rule insertion not found" -content = content.replace(P5_OLD, P5_NEW) -print("✓ appended .ee-gate-card.is-ee-gate CSS rule") - -HOME.write_text(content, encoding='utf-8') -print(f"\n✓ Home file written, size={len(content)} bytes") \ No newline at end of file diff --git a/_patch_home_i18n_2.py b/_patch_home_i18n_2.py deleted file mode 100644 index a2dd192..0000000 --- a/_patch_home_i18n_2.py +++ /dev/null @@ -1,70 +0,0 @@ -#!/usr/bin/env python3 -"""Verify i18n paths for the new workflow EE placeholder card. - -The home/index.vue uses T = t('message.pages.home.' + key). -But: - - charts.workflowStatus / charts.workflowEETip are under - { message: { pages: { home: { charts: {...} } } } } → ✓ works with T() - - edition.enterpriseOnlyTag is under { message: { pages: { edition: {...} } } } - → using T('edition.enterpriseOnlyTag') resolves to - t('message.pages.home.edition.enterpriseOnlyTag') which does NOT exist. - -Fix in template: replace T('edition.enterpriseOnlyTag') with the direct -t('message.pages.edition.enterpriseOnlyTag') call. - -Also fix handleWfCardClick: uses require('element-plus') which breaks in Vite ESM. -Replace with direct import usage. -""" - -import pathlib - -FILE = pathlib.Path("/media/jwj/TOSHIBA EXT/dev/taurus-stack-c/taurus-web/src/views/system/home/index.vue") -content = FILE.read_text(encoding="utf-8") - -# Patch 1: template - T('edition.enterpriseOnlyTag') → t('message.pages.edition.enterpriseOnlyTag') -OLD_TAG = """{{ T('edition.enterpriseOnlyTag') }}""" -NEW_TAG = """{{ t('message.pages.edition.enterpriseOnlyTag') }}""" -assert OLD_TAG in content, "edition tag in template not found" -content = content.replace(OLD_TAG, NEW_TAG) -print("✓ Patch 1: template tag uses correct t() path") - -# Patch 2: handleWfCardClick - remove require('element-plus') — it was already imported implicitly via -# the installed app; but safer to import at top. Actually ElMessageBox IS globally available in Element Plus -# apps, so use (window as any).ElMessageBox fallback, OR reference via direct symbol. -# Simpler: because the template already uses ElMessageBox elsewhere, let's just reference a -# getGlobalProperties-style call. But the most robust ESM-compatible way in a setup script -# is to import at top. Let's verify it's not already imported, and inline the dialog using -# the same pattern as featureDirective.ts (direct `from 'element-plus'` at top of file). -# -# First check if ElMessageBox is already imported in the file top. -if "import { ElMessageBox } from 'element-plus'" not in content: - # add import near top - content = content.replace( - "import { Box, Select, Loading, Warning, Timer, Close, Remove, Document, Setting, Operation, Share, Connection, CircleCheck } from '@element-plus/icons-vue';", - "import { Box, Select, Loading, Warning, Timer, Close, Remove, Document, Setting, Operation, Share, Connection, CircleCheck } from '@element-plus/icons-vue';\nimport { ElMessageBox } from 'element-plus';" - ) - print("✓ Patch 2a: added ElMessageBox top-level import") - -OLD_BLOCK = """ const tKey = (key: string, fallback: string) => { - try { - const v = t(`message.pages.edition.${key}`); - if (typeof v === 'string' && v && v !== `message.pages.edition.${key}`) return v; - } catch (_e) { /* noop */ } - return fallback; - }; - const { ElMessageBox } = require('element-plus'); - ElMessageBox.confirm(""" -NEW_BLOCK = """ const tKey = (key: string, fallback: string) => { - try { - const v = t(`message.pages.edition.${key}`); - if (typeof v === 'string' && v && v !== `message.pages.edition.${key}`) return v; - } catch (_e) { /* noop */ } - return fallback; - }; - ElMessageBox.confirm(""" -assert OLD_BLOCK in content, "handleWfCardClick ElMessageBox require block not found" -content = content.replace(OLD_BLOCK, NEW_BLOCK) -print("✓ Patch 2b: removed require('element-plus') in favor of top-level import") - -FILE.write_text(content, encoding="utf-8") -print(f"\n✓ File written: {FILE} size={len(content)} bytes") \ No newline at end of file diff --git a/_patch_pilot_canary_final.py b/_patch_pilot_canary_final.py deleted file mode 100644 index e8bfcff..0000000 --- a/_patch_pilot_canary_final.py +++ /dev/null @@ -1,216 +0,0 @@ -#!/usr/bin/env python3 -"""Fix OPS_PILOT_CANARY (灰度执行) gate — 3 files.""" - -import pathlib - -ROOT = pathlib.Path("/media/jwj/TOSHIBA EXT/dev/taurus-stack-c/taurus-web/src/views/taurus/ops") - -# ============ File 1: ops/script/index.vue — 用户截图的快速执行弹窗 ============ -SCRIPT_INDEX = ROOT / "script" / "index.vue" -content = SCRIPT_INDEX.read_text(encoding='utf-8') - -P1_OLD = """ -
{{ t('message.pages.opsScript.strategyPilotTitle') }}
-
{{ t('message.pages.opsScript.strategyPilotDesc') }}
-
""" -assert P1_OLD in content -P1_NEW = """
- -
- {{ t('message.pages.opsScript.strategyPilotTitle') }} - EE -
-
{{ t('message.pages.opsScript.strategyPilotDesc') }}
-
-
""" -content = content.replace(P1_OLD, P1_NEW) -print("✓ script/index.vue: v-if pilot radio → ee-gate wrapper") - -# Add helpers + handler after `const hasFeature = (code: string) => editionStore.hasFeature(code);` -P1b_OLD = "const hasFeature = (code: string) => editionStore.hasFeature(code);\nimport CustomDialog" -assert P1b_OLD in content -P1b_NEW = """const hasFeature = (code: string) => editionStore.hasFeature(code); - -// ---------- EE 升级拦截通用 helpers ---------- -const eeT = (key: string, fallback: string) => { -\ttry { -\t\tconst v = t(`message.pages.edition.${key}`); -\t\tif (typeof v === 'string' && v && v !== `message.pages.edition.${key}`) return v; -\t} catch (_e) { /* noop */ } -\treturn fallback; -}; -const triggerEeUpgrade = (code: string, customDesc?: string) => { -\tElMessageBox.confirm( -\t\tcustomDesc || eeT('enterpriseOnlyDesc', '该功能仅在 Taurus Ops 企业版中提供。升级到企业版即可解锁灰度执行、审批流、通知等全部高级能力。'), -\t\teeT('enterpriseOnlyTitle', '企业版专属功能'), -\t\t{ confirmButtonText: eeT('upgradeAction', '立即升级'), cancelButtonText: eeT('dismiss', '稍后再说'), type: 'info', showCancelButton: true, closeOnClickModal: true } -\t).then(() => window.dispatchEvent(new CustomEvent('taurus:edition-upgrade', { detail: { code } }))).catch(() => {}); -}; -const onPilotRadioClick = (e?: MouseEvent) => { -\tif (hasFeature('OPS_PILOT_CANARY')) return; -\tif (e) e.stopPropagation(); -\ttriggerEeUpgrade('OPS_PILOT_CANARY'); -}; - -import CustomDialog""" -content = content.replace(P1b_OLD, P1b_NEW) -print("✓ script/index.vue: added eeT() + triggerEeUpgrade() + onPilotRadioClick handler") - -# Also wrap pilot-params template block with the gate guard — -# only when the form actually has exec_mode === 'pilot' AND feature OK, show the params form. -# (No change to this — current v-if already OK as secondary conditional, because in CE -# the pilot radio wrapper never sets the value, so pilot params template never activated. -# Extra safety: keep as-is because ExecutorPanel.vue watch already resets pilot→parallel.) - -SCRIPT_INDEX.write_text(content, encoding='utf-8') -print(f" → script/index.vue size={SCRIPT_INDEX.stat().st_size}") - -# ============ File 2: components/AdvancedOptionsPanel.vue ============ -AOP = ROOT / "components" / "AdvancedOptionsPanel.vue" -content = AOP.read_text(encoding='utf-8') - -P2a_OLD = """ {{ t('message.pages.opsExecution.advanced.pilot') }}""" -assert P2a_OLD in content -P2a_NEW = """ - - {{ t('message.pages.opsExecution.advanced.pilot') }} - EE - - """ -content = content.replace(P2a_OLD, P2a_NEW) -print("✓ AdvancedOptionsPanel.vue: pilot radio → ee-gate wrapper") - -# pilot-params section — just keep it's already conditional on hasFeature. It won't ever show in CE since radio can't be selected. No change. - -# Find the script setup block of AdvancedOptionsPanel -P2b_OLD = """ @@ -176,4 +181,4 @@ const goUpgrade = () => { justify-content: center; gap: 12px; } - + \ No newline at end of file diff --git a/src/i18n/pages/edition/en.ts b/src/i18n/pages/edition/en.ts index 79fb1da..acefb33 100644 --- a/src/i18n/pages/edition/en.ts +++ b/src/i18n/pages/edition/en.ts @@ -13,6 +13,34 @@ export default { workflowQuotaBadge: 'Workflows {current}/{limit}', workflowQuotaUpgradeHint: 'Quota full. Click to view upgrade options.', + // === EditionLockedPage (full-page lock overlay) === + lockedSubtitle: 'This feature is available only in Taurus Stack Enterprise Edition', + lockedBackBtn: 'Go Back', + lockedUpgradeBtn: '🚀 Upgrade to Enterprise', + lockedDefaultLabel: 'This page', + lockedHighlight1: 'Unlock enterprise-grade core capabilities', + lockedHighlight2: 'Enjoy professional technical support', + lockedHighlight3: 'Ensure large-scale operations compliance', + lockedUpgradeToast: 'Upgrade guide dialog will appear shortly…', + + // === EditionLockedPage page titles (for label prop) === + lockedPageLabels: { + ticketCenter: 'Ticket Center', + inspectionCenter: 'Inspection Center', + knowledgeBase: 'Knowledge Base', + taskCenter: 'Task Management Center', + toolsCenter: 'Ops Toolbox', + workflowApproveList: 'Workflow Approval Center', + workflowApprovalInstance: 'Workflow Approval Center', + workflowApprovalRule: 'Workflow Approval Rules', + programInstallTemplate: 'Enterprise Program Install Template', + programInstallConfig: 'Enterprise Program Install Config', + programInstallPolicy: 'Enterprise Program Install Policy', + scriptCheckRule: 'Script Security Scan Rules', + scriptApproval: 'Script Approval Center', + executionApproval: 'Execution Approval Center', + }, + // === Upgrade banner === ceBannerTitle: 'Using Community Edition?', ceBannerSubtitle: 'Unlock all Enterprise capabilities', diff --git a/src/i18n/pages/edition/zh-cn.ts b/src/i18n/pages/edition/zh-cn.ts index 3fb3a77..57ab986 100644 --- a/src/i18n/pages/edition/zh-cn.ts +++ b/src/i18n/pages/edition/zh-cn.ts @@ -13,6 +13,34 @@ export default { workflowQuotaBadge: '工作流 {current}/{limit}', workflowQuotaUpgradeHint: '配额已满,点击查看升级方案', + // === EditionLockedPage(整页锁遮罩)=== + lockedSubtitle: '此功能仅 Taurus Stack 企业版(Enterprise Edition)提供', + lockedBackBtn: '返回上一页', + lockedUpgradeBtn: '🚀 升级到企业版', + lockedDefaultLabel: '该页面', + lockedHighlight1: '解锁企业级核心能力', + lockedHighlight2: '享受专业技术支持', + lockedHighlight3: '保障大规模运维合规', + lockedUpgradeToast: '升级引导弹窗即将显示…', + + // === EditionLockedPage 各页面标题(label prop 用)=== + lockedPageLabels: { + ticketCenter: '工单中心', + inspectionCenter: '巡检中心', + knowledgeBase: '知识库', + taskCenter: '任务管理中心', + toolsCenter: '运维工具箱', + workflowApproveList: '作业审批中心', + workflowApprovalInstance: '工作流审批中心', + workflowApprovalRule: '作业审批规则', + programInstallTemplate: '企业程序安装模板', + programInstallConfig: '企业程序安装配置', + programInstallPolicy: '企业程序安装策略', + scriptCheckRule: '脚本安全扫描规则', + scriptApproval: '脚本审批中心', + executionApproval: '执行审批中心', + }, + // === Upgrade banner === ceBannerTitle: '正在使用社区版?', ceBannerSubtitle: '解锁企业版全部高级能力', diff --git a/src/i18n/pages/edition/zh-tw.ts b/src/i18n/pages/edition/zh-tw.ts index bee0450..fb2a6c0 100644 --- a/src/i18n/pages/edition/zh-tw.ts +++ b/src/i18n/pages/edition/zh-tw.ts @@ -13,6 +13,34 @@ export default { workflowQuotaBadge: '工作流 {current}/{limit}', workflowQuotaUpgradeHint: '配額已滿,點擊查看升級方案', + // === EditionLockedPage(整頁鎖遮罩)=== + lockedSubtitle: '此功能僅 Taurus Stack 企業版(Enterprise Edition)提供', + lockedBackBtn: '返回上一頁', + lockedUpgradeBtn: '🚀 升級到企業版', + lockedDefaultLabel: '該頁面', + lockedHighlight1: '解鎖企業級核心能力', + lockedHighlight2: '享受專業技術支援', + lockedHighlight3: '保障大規模維運合規', + lockedUpgradeToast: '升級引導彈窗即將顯示…', + + // === EditionLockedPage 各頁面標題(label prop 用)=== + lockedPageLabels: { + ticketCenter: '工單中心', + inspectionCenter: '巡檢中心', + knowledgeBase: '知識庫', + taskCenter: '任務管理中心', + toolsCenter: '維運工具箱', + workflowApproveList: '作業審批中心', + workflowApprovalInstance: '工作流審批中心', + workflowApprovalRule: '作業審批規則', + programInstallTemplate: '企業程式安裝範本', + programInstallConfig: '企業程式安裝設定', + programInstallPolicy: '企業程式安裝策略', + scriptCheckRule: '指令碼安全掃描規則', + scriptApproval: '指令碼審批中心', + executionApproval: '執行審批中心', + }, + // === Upgrade banner === ceBannerTitle: '正在使用社群版?', ceBannerSubtitle: '解鎖企業版全部高級能力', diff --git a/src/views/taurus/inspection/InspectionCenter.vue b/src/views/taurus/inspection/InspectionCenter.vue index 872238b..98a2d9f 100644 --- a/src/views/taurus/inspection/InspectionCenter.vue +++ b/src/views/taurus/inspection/InspectionCenter.vue @@ -1,5 +1,6 @@ + + @@ -501,4 +503,4 @@ onMounted(() => { } } } - + \ No newline at end of file diff --git a/src/views/taurus/supervisor/program-install-config/index.vue b/src/views/taurus/supervisor/program-install-config/index.vue index cbcfe90..66c12d2 100644 --- a/src/views/taurus/supervisor/program-install-config/index.vue +++ b/src/views/taurus/supervisor/program-install-config/index.vue @@ -1,5 +1,5 @@