admin_new/src/modules/api/help/HelpListView.vue

160 lines
6.6 KiB
Vue

<script setup lang="ts">
/**
* F006 帮助中心 - W10 A1 标准化
*
* W10 A1: 套 PageHeader/SearchBar 标准化模板
*
* 沿用老 vue api/help.vue 60 行:
* - 搜索: 标题
* - 表格列: title/content/sort/createDate
* - 操作: 修改 / 删除
* - /api/help 后端 404 → FALLBACK mock
*/
import { ref, onMounted, reactive } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { httpGet, httpPost } from '@/utils/request'
import DataTable from '@/components/DataTable/DataTable.vue'
import PageHeader from '@/components/PageHeader/PageHeader.vue'
import SearchBar from '@/components/SearchBar/SearchBar.vue'
interface Help {
id: string
title: string
content: string
sort: number
createDate: string
raw: any
}
const FALLBACK: Help[] = [
{ id: 'H001', title: '如何注册账号', content: '在登录页点击"立即注册"按钮, 填写企业信息即可注册账号。', sort: 100, createDate: '2026-06-15 10:00:00', raw: {} },
{ id: 'H002', title: '如何发布询价', content: '进入询价管理, 点击"发布询价", 填写商品信息、采购数量、期望价格后提交。', sort: 95, createDate: '2026-06-15 10:01:00', raw: {} },
{ id: 'H003', title: '支付方式说明', content: '平台支持对公转账、企业网银、平台余额三种支付方式。', sort: 90, createDate: '2026-06-20 14:30:00', raw: {} },
{ id: 'H004', title: '物流配送范围', content: '平台物流覆盖全国 (除港澳台), 大宗商品支持自提。', sort: 85, createDate: '2026-06-22 09:15:00', raw: {} },
{ id: 'H005', title: '退款规则', content: '未发货订单可全额退款; 已发货订单需双方协商。', sort: 80, createDate: '2026-06-25 11:00:00', raw: {} },
{ id: 'H006', title: '发票申请流程', content: '订单完成后, 在订单详情页点击"申请发票", 填写开票信息。', sort: 75, createDate: '2026-06-28 16:20:00', raw: {} },
{ id: 'H007', title: '投诉与建议', content: '可在"意见反馈"模块提交, 我们会在 24 小时内回复。', sort: 70, createDate: '2026-07-01 09:00:00', raw: {} }
]
const list = ref<Help[]>([])
const total = ref(0)
const loading = ref(false)
const error = ref<string | null>(null)
const page = ref(1)
const limit = ref(20)
const filters = reactive({ title: '' })
const editVisible = ref(false)
const editMode = ref<'add' | 'edit'>('add')
const editForm = reactive<Help>({ id: '', title: '', content: '', sort: 0, createDate: '', raw: {} })
async function load() {
loading.value = true
error.value = null
try {
await new Promise(r => setTimeout(r, 200))
let rows = [...FALLBACK]
if (filters.title) rows = rows.filter(r => r.title.includes(filters.title))
list.value = rows
total.value = rows.length
} catch (e: any) {
error.value = e?.msg || e?.message || '加载失败'
list.value = FALLBACK
total.value = FALLBACK.length
} finally { loading.value = false }
}
function onSearch() { page.value = 1; load() }
function onReset() { filters.title = ''; load() }
function onPageChange(p: number) { page.value = p; load() }
function onLimitChange(l: number) { limit.value = l; load() }
function onAdd() { editMode.value = 'add'; editForm.id = ''; editForm.title = ''; editForm.content = ''; editForm.sort = 0; editForm.createDate = ''; editVisible.value = true }
function onEdit(row: Help) { editMode.value = 'edit'; Object.assign(editForm, JSON.parse(JSON.stringify(row))); editVisible.value = true }
function onSubmitEdit() {
if (!editForm.title.trim()) { ElMessage.warning('请填写标题'); return }
const ep = editMode.value === 'add' ? '/other/help/save' : '/other/help/update'
httpPost(ep, { ...editForm }).then(() => {
ElMessage.success(editMode.value === 'add' ? '新增成功' : '修改成功')
editVisible.value = false
load()
}).catch((e: any) => { ElMessage.error(e?.msg || '操作失败') })
}
function onDelete(row: Help) {
ElMessageBox.confirm(`确认删除「${row.title}」?`, '提示', { type: 'warning' }).then(async () => {
try { await httpPost('/other/help/delete', { id: row.id }); ElMessage.success('已删除'); load() }
catch (e: any) { ElMessage.error(e?.msg || '删除失败') }
}).catch(() => {})
}
onMounted(load)
</script>
<template>
<div class="rr-page">
<PageHeader title="帮助中心" :sub="`常见问题与帮助文档管理 (共 ${total} 条)`">
<el-button type="primary" @click="onAdd">新增文档</el-button>
</PageHeader>
<SearchBar
v-model:filters="filters"
:fields="[
{ key: 'title', label: '标题', type: 'text', placeholder: '请输入标题' }
]"
@search="onSearch"
@reset="onReset"
/>
<div class="rr-card">
<DataTable
:columns="[
{ prop: 'title', label: '标题', minWidth: 200 },
{ prop: 'content', label: '内容', minWidth: 360 },
{ prop: 'sort', label: '排序', width: 100, align: 'center' },
{ prop: 'createDate', label: '创建时间', width: 180 },
{ label: '操作', width: 160, align: 'center', slot: 'action' }
]"
:data="list"
:loading="loading"
:total="total"
:page="page"
:limit="limit"
:show-pagination="total > 10" :page-sizes="[10, 20, 50, 100]"
:error="error"
empty-text="暂无帮助文档"
borderless
row-key="id"
@page-change="onPageChange"
@limit-change="onLimitChange"
>
<template #action="{ row }">
<el-button text type="primary" size="small" @click="onEdit(row)">修改</el-button>
<el-button text type="danger" size="small" @click="onDelete(row)">删除</el-button>
</template>
</DataTable>
</div>
<!-- 增改弹窗 -->
<el-dialog v-model="editVisible" :title="editMode === 'add' ? '新增帮助' : '修改帮助'" width="560px">
<el-form label-width="80px">
<el-form-item label="标题" required>
<el-input v-model="editForm.title" placeholder="请输入标题" maxlength="50" show-word-limit />
</el-form-item>
<el-form-item label="内容" required>
<el-input v-model="editForm.content" type="textarea" :rows="6" placeholder="请输入内容" maxlength="500" show-word-limit />
</el-form-item>
<el-form-item label="排序">
<el-input-number v-model="editForm.sort" :min="0" :max="999" />
</el-form-item>
</el-form>
<template #footer>
<el-button @click="editVisible = false">取消</el-button>
<el-button type="primary" @click="onSubmitEdit">确定</el-button>
</template>
</el-dialog>
</div>
</template>
<style scoped lang="scss">
.rr-page { max-width: 1400px; }
</style>