refactor(ticket): move the config tab into the SPA ticket center

users.php → 工单管理 的「配置」Tab 只管理部门 / 状态 / 预设回复三块
DB 字典,与 SPA「工单中心」已有的 8 个标量配置分裂成两处;且同一套
CRUD 在 admin_post 与 TicketConfigRest 里各写了一遍,REST 侧此前
没有任何调用方。

- 删除原生 config tab:UsersMenusTicketsConfig.php 整份移除,
  UsersMenusTicketsCenter 由 512 行降到 251 行(六个写处理方法、
  分发分支、十条提示码与 ticket_delete_button 一并清理)
- SPA /users/ticket 改为 customPage:内嵌 SchemaPage 承载原有 8 字段,
  三块字典改为 n-data-table + n-modal + n-dialog,取色器/管理员多选/
  拖拽排序替代原生手填表单
- TicketConfigRest 成为三块字典的唯一实现,新增 api/modules/tickets.js
  封装 aksrt/v1/admin/tickets*
- 双向深链:原生页跳 SPA 配置页,SPA 页跳回原生工单列表

契约测试同步更新,并新增 ticket-spa-config-contract 守护接线。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
kate522andClaude Fable 5 committed 2026-10-26 19:48:58 +08:00
1 parent d32bdc0581
commit e7ca0ee5df
19 files changed
+1074 -509

No files matched your search

@@ -0,0 +1,69 @@
<template>
<div class="aksrt-page-container">
<PageHeader
title="工单中心"
desc="工单功能开关、提交公告与提交表单配置,以及部门、状态、预设回复三块字典维护。工单的日常处理在 WordPress 用户菜单的「工单管理」中完成。"
>
<template #actions>
<n-space>
<n-button quaternary @click="openNativeList">工单处理</n-button>
</n-space>
</template>
</PageHeader>
<n-tabs v-model:value="activeTab" type="segment" animated class="aksrt-ticket-tabs">
<n-tab-pane name="settings" tab="基础配置">
<SchemaPage domain="users" section="ticket" />
</n-tab-pane>
<n-tab-pane name="types" tab="工单部门">
<TicketTypePanel ref="typePanel" />
</n-tab-pane>
<n-tab-pane name="statuses" tab="工单状态">
<TicketStatusPanel ref="statusPanel" />
</n-tab-pane>
<n-tab-pane name="prereplies" tab="预设回复">
<TicketPrereplyPanel ref="prereplyPanel" />
</n-tab-pane>
</n-tabs>
</div>
</template>
<script setup>
import { ref, watch } from 'vue'
import { NTabPane, NTabs } from 'naive-ui'
import PageHeader from '@/components/PageHeader.vue'
import SchemaPage from '@/pages/SchemaPage.vue'
import TicketTypePanel from './partials/ticket/TicketTypePanel.vue'
import TicketStatusPanel from './partials/ticket/TicketStatusPanel.vue'
import TicketPrereplyPanel from './partials/ticket/TicketPrereplyPanel.vue'
const activeTab = ref('settings')
const typePanel = ref(null)
const statusPanel = ref(null)
const prereplyPanel = ref(null)
/**
* 切回字典 Tab 时按需重拉:部门/状态在别处(如工单列表)不会变,
* 但多开两个后台标签时能拿到最新数据,代价只是各发一次 GET。
*/
const RELOAD_ON_ENTER = {
types: () => typePanel.value?.reload(),
statuses: () => statusPanel.value?.reload(),
prereplies: () => prereplyPanel.value?.reload(),
}
watch(activeTab, (name) => {
RELOAD_ON_ENTER[name]?.()
})
function openNativeList() {
const base = (window.aksrtAdminData?.adminUrl || '/wp-admin/').replace(/\/?$/, '/')
window.location.href = base + 'users.php?page=aksrt_tickets'
}
</script>
<style scoped>
.aksrt-ticket-tabs {
margin-bottom: 4px;
}
</style>