import { ElTag } from "element-plus";
import { OfficeBuilding, Close, Aim, DocumentCopy, MoreFilled, Upload, Plus, Edit, Download, Link, View } from "@element-plus/icons-vue";
import UiButton from "../../ui/UiButton.vue";
+import UiInput from "../../ui/UiInput.vue";
import UiSelect from "../../ui/UiSelect.vue";
import UiTable from "../../ui/UiTable.vue";
import UiActions from "../../ui/UiActions.vue";
draft.value = {
domain_id: d.domain_id,
name: d.name || "",
+ abbr: d.abbr || "",
version: d.version || "1.0",
status: d.status || "available",
description: d.description || "",
onMounted(load);
async function saveMeta() {
+ if (!draft.value.name.trim()) { props.notify("请填写方案名称"); return; }
+ if (!/^[A-Z]+$/.test((draft.value.abbr || "").trim())) { props.notify("缩写必须为英文大写字母"); return; }
try {
await fetchDb(`/domain-templates/${props.id}`, {
method: "PUT",
headers: { "Content-Type": "application/json" },
- body: JSON.stringify(draft.value),
+ body: JSON.stringify({ ...draft.value, name: draft.value.name.trim(), abbr: (draft.value.abbr || "").trim() }),
});
props.notify("方案信息已保存");
editing.value = false;
<section :class="['domain-capability-head', scene.tone]">
<div class="domain-capability-code">{{ scene.code }}</div>
<div class="domain-capability-copy">
- <div><ElTag class="tag-new" :class="'tag-' + domainTagColor(domainName)">{{ domainName }}</ElTag><Status>{{ detail.status === "available" ? "可用" : "不可用" }}</Status><span>版本 {{ detail.version || "1.0" }}</span></div>
+ <div><ElTag class="tag-new" :class="'tag-' + domainTagColor(domainName)">{{ domainName }}</ElTag><Status>{{ detail.status === "available" ? "可用" : detail.status === "editing" ? "编辑中" : "不可用" }}</Status><span>版本 {{ detail.version || "1.0" }}</span></div>
<h2>{{ detail.name || "未命名领域方案" }}</h2>
<p>{{ detail.description || scene.desc }}</p>
</div>
</div>
</UiOverlay>
- <UiOverlay v-if="editing && draft" class="modal-backdrop" @mousedown="() => (editing = false)">
- <div class="modal domain-maintain-modal" @mousedown.stop>
- <header><h2>维护领域方案</h2><UiButton @click="() => (editing = false)">×</UiButton></header>
- <div class="modal-body">
- <div class="form-grid">
- <Field label="方案名称" required><UiInput :value="draft.name" @change="(e) => (draft = { ...draft, name: e.target.value })" /></Field>
- <Field label="所属领域" required>
- <UiSelect :value="draft.domain_id" @change="(e) => (draft = { ...draft, domain_id: Number(e.target.value) })">
- <option v-for="d in doms" :key="d.id" :value="d.id">{{ friendlyDomainName(d.name) }}</option>
- </UiSelect>
- </Field>
- <Field label="版本"><UiInput :value="draft.version" @change="(e) => (draft = { ...draft, version: e.target.value })" /></Field>
- <Field label="状态">
- <UiSelect :value="draft.status" @change="(e) => (draft = { ...draft, status: e.target.value })">
- <option value="available">可用</option>
- <option value="unavailable">不可用</option>
- </UiSelect>
- </Field>
- <Field label="方案说明"><UiInput textarea :rows="4" :value="draft.description" @change="(e) => (draft = { ...draft, description: e.target.value })" /></Field>
- </div>
- <div class="domain-maintain-note">资产、页面、知识与菜单均可分别进入预览后维护;本页不再采用分步确认流程。</div>
- </div>
- <footer>
+ <UiOverlay v-if="editing && draft" className="dlg-backdrop" @mousedown="() => (editing = false)">
+ <div class="dlg-box domain-maintain-dialog" style="width:480px" @mousedown.stop>
+ <h2>维护领域方案</h2>
+ <label class="field">
+ <span class="field-label"><i class="req">*</i>方案名称</span>
+ <UiInput :value="draft.name" maxLength="20" placeholder="请输入方案名称" @change="(e) => (draft = { ...draft, name: e.target.value })" />
+ </label>
+ <label class="field">
+ <span class="field-label"><i class="req">*</i>缩写(英文大写)</span>
+ <UiInput :value="draft.abbr" maxLength="10" placeholder="如 WTP" @change="(e) => (draft = { ...draft, abbr: e.target.value.toUpperCase() })" />
+ </label>
+ <label class="field">
+ <span class="field-label"><i class="req">*</i>所属领域</span>
+ <UiSelect :value="draft.domain_id" @change="(e) => (draft = { ...draft, domain_id: Number(e.target.value) })">
+ <option v-for="d in doms" :key="d.id" :value="d.id">{{ friendlyDomainName(d.name) }}</option>
+ </UiSelect>
+ </label>
+ <label class="field">
+ <span class="field-label">版本号</span>
+ <UiInput :value="draft.version" placeholder="如 V1.0" @change="(e) => (draft = { ...draft, version: e.target.value })" />
+ </label>
+ <label class="field">
+ <span class="field-label">状态</span>
+ <UiSelect :value="draft.status" @change="(e) => (draft = { ...draft, status: e.target.value })">
+ <option value="available">可用</option>
+ <option value="editing">编辑中</option>
+ </UiSelect>
+ </label>
+ <label class="field">
+ <span class="field-label">方案说明</span>
+ <UiInput textarea :rows="4" :value="draft.description" placeholder="请输入方案说明" @change="(e) => (draft = { ...draft, description: e.target.value })" />
+ </label>
+ <UiActions className="dlg-actions">
<ElButton secondary @click="() => (editing = false)">取消</ElButton>
- <ElButton @click="saveMeta">保存</ElButton>
- </footer>
+ <ElButton :disabled="!draft.name.trim() || !/^[A-Z]+$/.test((draft.abbr || '').trim())" @click="saveMeta">保存</ElButton>
+ </UiActions>
</div>
</UiOverlay>
/* 领域配置:默认颜色配置(swatch / dot),复用 antd 预设色板(web-ui-builder 设计体系) */
.domain-color-dot{display:inline-block;width:10px;height:10px;border-radius:50%;margin-right:8px;vertical-align:middle;border:1px solid color-mix(in srgb,var(--ant-color-text-base) 10%,transparent)}
.domain-color-dot.tag-blue{background:#1677ff}.domain-color-dot.tag-cyan{background:#13c2c2}.domain-color-dot.tag-orange{background:#fa8c16}.domain-color-dot.tag-green{background:#52c41a}.domain-color-dot.tag-purple{background:#722ed1}.domain-color-dot.tag-red{background:#f5222d}.domain-color-dot.tag-default{background:#8c8c8c}
-.domain-edit-dialog .field,.domain-create-dialog .field{display:block;margin-bottom:16px}
-.domain-edit-dialog .field-label,.domain-create-dialog .field-label{display:block;font-size:var(--ant-font-size-sm);color:var(--ant-color-text-secondary);margin-bottom:6px}
+.domain-edit-dialog .field,.domain-create-dialog .field,.domain-maintain-dialog .field{display:block;margin-bottom:16px}
+.domain-edit-dialog .field-label,.domain-create-dialog .field-label,.domain-maintain-dialog .field-label{display:block;font-size:var(--ant-font-size-sm);color:var(--ant-color-text-secondary);margin-bottom:6px}
+.field-label .req{color:var(--ant-color-error);font-style:normal;margin-right:4px}
+.domain-edit-dialog .button,.domain-create-dialog .button,.domain-maintain-dialog .button{min-width:96px;margin:0}
.domain-color-picker{display:flex;gap:10px;flex-wrap:wrap}
.domain-color-swatch{width:28px;height:28px;border-radius:var(--ant-border-radius);border:1px solid var(--ant-color-border);cursor:pointer;padding:0;transition:box-shadow .15s}
.domain-color-swatch.tag-blue{background:#1677ff}.domain-color-swatch.tag-cyan{background:#13c2c2}.domain-color-swatch.tag-orange{background:#fa8c16}.domain-color-swatch.tag-green{background:#52c41a}.domain-color-swatch.tag-purple{background:#722ed1}.domain-color-swatch.tag-red{background:#f5222d}.domain-color-swatch.tag-default{background:#8c8c8c}