160 lines
6.6 KiB
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>
|