diff --git a/src/pages/TicketsPage.vue b/src/pages/TicketsPage.vue index 48e8723..afbb108 100644 --- a/src/pages/TicketsPage.vue +++ b/src/pages/TicketsPage.vue @@ -75,7 +75,17 @@ - + + + + + + {{ item.name }} + {{ item.description }} + + + + 取消 @@ -193,7 +203,6 @@ const perPage = ref(20) const filters = reactive({ status: '', category_id: null, mine: false }) const categories = ref([]) const categoryTree = ref([]) -const activeCategories = computed(() => categories.value.filter((item) => item.is_active)) const categoryCascaderProps = { value: 'id', label: 'name', checkStrictly: true, emitPath: false } const categoryOptions = computed(() => buildCategoryOptions(categoryTree.value)) const activeCategoryOptions = computed(() => buildCategoryOptions(categoryTree.value, true)) @@ -262,14 +271,22 @@ function handleSizeChange(nextSize: number): void { } function openCreateTicket(): void { - Object.assign(ticketForm, { ticket_category_id: activeCategories.value[0]?.id || null, title: '', content: '' }) + Object.assign(ticketForm, { ticket_category_id: null, title: '', content: '' }) ticketDialogVisible.value = true } async function submitTicket(): Promise { const ticketCategoryId = selectedCategoryId(ticketForm.ticket_category_id) - if (!ticketCategoryId || !ticketForm.title?.trim() || !ticketForm.content?.trim()) { - ElMessage.warning('请完整填写工单信息') + if (!ticketCategoryId) { + ElMessage.warning('请选择工单分类') + return + } + if (!ticketForm.title?.trim()) { + ElMessage.warning('请输入工单标题') + return + } + if (!ticketForm.content?.trim()) { + ElMessage.warning('请输入工单内容') return } savingTicket.value = true @@ -415,6 +432,21 @@ function categoryLabel(categoryId: number | string | null | undefined): string { return path.length > 0 ? path.join(' / ') : '-' } +const selectedCategoryDescriptions = computed(() => { + const categoryId = selectedCategoryId(ticketForm.ticket_category_id) + if (!categoryId) { + return [] + } + + return findCategoryNodes(categoryTree.value, categoryId) + .filter((item) => String(item.description || '').trim() !== '') + .map((item) => ({ + id: item.id, + name: item.name, + description: String(item.description || '').trim(), + })) +}) + function findCategoryPath(items: any[], categoryId: number, parents: string[] = []): string[] { for (const item of items) { const nextPath = [...parents, item.name] @@ -430,6 +462,21 @@ function findCategoryPath(items: any[], categoryId: number, parents: string[] = return [] } +function findCategoryNodes(items: any[], categoryId: number, parents: any[] = []): any[] { + for (const item of items) { + const nextPath = [...parents, item] + if (Number(item.id) === categoryId) { + return nextPath + } + const childPath = findCategoryNodes(item.children || [], categoryId, nextPath) + if (childPath.length > 0) { + return childPath + } + } + + return [] +} + async function removeCategory(row: any): Promise { await ElMessageBox.confirm(`确认删除分类「${row.name}」吗?历史工单会保留但分类置空。`, '提示', { type: 'warning' }) await ticketsApi.removeCategory(row.id) @@ -474,4 +521,8 @@ onMounted(async () => { .message-box { border: 1px solid #e2e8f0; border-radius: 8px; padding: 10px; background: #f8fafc; } .message-sender { font-size: 12px; color: #64748b; margin-bottom: 6px; } .message-content { white-space: pre-wrap; color: #0f172a; } +.ticket-content-field { width: 100%; display: flex; flex-direction: column; gap: 10px; } +.category-descriptions { border: 1px solid #e5e7eb; border-radius: 6px; background: #f8fafc; padding: 10px 12px; display: flex; flex-direction: column; gap: 6px; } +.category-description-line { color: #334155; line-height: 1.5; word-break: break-word; } +.category-description-name { color: #111827; font-weight: 600; margin-right: 8px; }