| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311 |
- <template>
- <div class="service-contents admin-page">
- <el-card>
- <div slot="header" class="admin-page-header">
- <span class="admin-page-title">服务内容管理</span>
- <div class="admin-page-actions">
- <el-input v-model="keyword" placeholder="搜索内容..." prefix-icon="el-icon-search" clearable @keyup.enter.native="handleSearch" @clear="handleSearch" />
- <el-button type="primary" size="small" @click="handleCreate">+ 添加内容</el-button>
- </div>
- </div>
- <el-form :inline="true">
- <el-form-item label="服务类型">
- <el-select v-model="query.typeId" placeholder="全部" clearable @change="handleQuery">
- <el-option v-for="t in serviceTypes" :key="t.id" :label="t.name" :value="t.id"></el-option>
- </el-select>
- </el-form-item>
- <el-form-item label="状态">
- <el-select v-model="query.status" placeholder="全部" clearable @change="handleQuery">
- <el-option label="启用" value="ACTIVE"></el-option>
- <el-option label="停用" value="DISABLED"></el-option>
- </el-select>
- </el-form-item>
- <el-form-item>
- <el-button @click="handleQuery">查询</el-button>
- </el-form-item>
- </el-form>
- <div class="table-scroll-wrap-sm">
- <el-table :data="filteredData" stripe>
- <el-table-column prop="id" label="ID" width="80"></el-table-column>
- <el-table-column prop="title" label="标题"></el-table-column>
- <el-table-column prop="typeId" label="类型" width="120">
- <template slot-scope="scope">
- {{ getTypeName(scope.row.typeId) }}
- </template>
- </el-table-column>
- <el-table-column prop="duration" label="时长(分钟)" width="100"></el-table-column>
- <el-table-column prop="ageRange" label="适用年龄" width="100"></el-table-column>
- <el-table-column prop="price" label="参考价格" width="100">
- <template slot-scope="scope">{{ formatPriceWithSymbol(scope.row.price) }}</template>
- </el-table-column>
- <el-table-column prop="status" label="状态" width="100">
- <template slot-scope="scope">
- <el-tag :type="scope.row.status === 'ACTIVE' ? 'success' : 'danger'">
- {{ scope.row.status === 'ACTIVE' ? '启用' : '停用' }}
- </el-tag>
- </template>
- </el-table-column>
- <el-table-column label="操作" width="200" fixed="right">
- <template slot-scope="{ row }">
- <el-button size="mini" type="primary" @click="handleEdit(row)">编辑</el-button>
- <el-dropdown trigger="hover" @command="(cmd) => handleActionCmd(row, cmd)">
- <el-button size="mini">
- 更多<i class="el-icon-arrow-down el-icon--right"></i>
- </el-button>
- <el-dropdown-menu slot="dropdown">
- <el-dropdown-item command="preview" icon="el-icon-view">预览</el-dropdown-item>
- <el-dropdown-item :command="row.status === 'ACTIVE' ? 'disable' : 'enable'" icon="el-icon-switch-button">{{ row.status === 'ACTIVE' ? '停用' : '启用' }}</el-dropdown-item>
- </el-dropdown-menu>
- </el-dropdown>
- </template>
- </el-table-column>
- </el-table>
- </div>
- </el-card>
- <el-dialog :visible.sync="dialogVisible" :title="isEdit ? '编辑服务内容' : '添加服务内容'" width="800px">
- <el-form :model="form" label-width="100px">
- <el-form-item label="服务类型">
- <el-select v-model="form.typeId" placeholder="请选择服务类型">
- <el-option v-for="t in serviceTypes" :key="t.id" :label="t.name" :value="t.id"></el-option>
- </el-select>
- </el-form-item>
- <el-form-item label="标题">
- <el-input v-model="form.title"></el-input>
- </el-form-item>
- <el-form-item label="服务详情">
- <div class="rich-editor">
- <div class="editor-toolbar">
- <el-button size="small" @click="insertTag('b')">B</el-button>
- <el-button size="small" @click="insertTag('i')">I</el-button>
- <el-button size="small" @click="insertTag('u')">U</el-button>
- <el-button size="small" @click="insertTag('h3')">标题</el-button>
- <el-button size="small" @click="insertTag('ul')">列表</el-button>
- <el-button size="small" @click="insertTag('img')">图片</el-button>
- </div>
- <el-input
- type="textarea"
- v-model="form.content"
- :rows="10"
- placeholder="请输入服务详情,支持HTML标签"
- ></el-input>
- </div>
- </el-form-item>
- <el-form-item label="建议时长(分钟)">
- <el-input-number v-model="form.duration" :min="0"></el-input-number>
- </el-form-item>
- <el-form-item label="适用年龄">
- <el-input v-model="form.ageRange" placeholder="如: 3-12岁"></el-input>
- </el-form-item>
- <el-form-item label="参考价格(元)">
- <el-input-number v-model="form.price" :min="0" :precision="2"></el-input-number>
- </el-form-item>
- </el-form>
- <div slot="footer">
- <el-button @click="dialogVisible = false">取消</el-button>
- <el-button type="primary" @click="handleSubmit">保存</el-button>
- </div>
- </el-dialog>
- <el-dialog :visible.sync="previewVisible" title="服务内容预览" width="600px">
- <div class="preview-content" v-html="previewContent"></div>
- </el-dialog>
- </div>
- </template>
- <script>
- import { getServiceContents, createServiceContent, updateServiceContent } from '@/api/adminService'
- import { getServiceTypes } from '@/api/adminService'
- export default {
- name: 'ServiceContents',
- data() {
- return {
- contents: [],
- keyword: '',
- serviceTypes: [],
- query: {
- typeId: null,
- status: null
- },
- dialogVisible: false,
- previewVisible: false,
- previewContent: '',
- isEdit: false,
- form: {
- id: null,
- typeId: null,
- title: '',
- content: '',
- duration: 0,
- ageRange: '',
- price: 0,
- status: 'ACTIVE'
- }
- }
- },
- created() {
- this.loadTypes()
- this.loadData()
- },
- computed: {
- filteredData() {
- if (!this.keyword) return this.contents
- var kw = this.keyword.toLowerCase()
- return this.contents.filter(function(item) {
- return item.title && item.title.toLowerCase().indexOf(kw) !== -1
- })
- }
- },
- methods: {
- async loadTypes() {
- try {
- const res = await getServiceTypes()
- if (res.data) {
- this.serviceTypes = res.data
- }
- } catch (e) {
- this.serviceTypes = [
- { id: 1, name: 'DAN测评' },
- { id: 2, name: '专属咨询' },
- { id: 3, name: '成长报告' },
- { id: 4, name: '家庭培训' }
- ]
- }
- },
- async loadData() {
- try {
- const res = await getServiceContents(this.query)
- if (res.data) {
- this.contents = res.data
- }
- } catch (e) {
- this.contents = [
- { id: 1, typeId: 1, title: '1对1 DAN测评', content: '<p>DAN测评是...</p>', duration: 60, ageRange: '3-12岁', price: 800, status: 'ACTIVE' },
- { id: 2, typeId: 1, title: 'DAN综合评估', content: '<p>综合评估...</p>', duration: 90, ageRange: '3-12岁', price: 1200, status: 'ACTIVE' },
- { id: 3, typeId: 2, title: '专属咨询', content: '<p>咨询服务...</p>', duration: 30, ageRange: '3-18岁', price: 580, status: 'ACTIVE' }
- ]
- }
- },
- getTypeName(typeId) {
- const type = this.serviceTypes.find(t => t.id === typeId)
- return type ? type.name : '-'
- },
- handleSearch() {},
- handleQuery() {
- this.loadData()
- },
- handleCreate() {
- this.isEdit = false
- this.form = {
- id: null,
- typeId: null,
- title: '',
- content: '',
- duration: 0,
- ageRange: '',
- price: 0,
- status: 'ACTIVE'
- }
- this.dialogVisible = true
- },
- handleEdit(row) {
- this.isEdit = true
- this.form = { ...row }
- this.dialogVisible = true
- },
- handlePreview(row) {
- this.previewContent = row.content
- this.previewVisible = true
- },
- async toggleStatus(row) {
- row.status = row.status === 'ACTIVE' ? 'DISABLED' : 'ACTIVE'
- try {
- await updateServiceContent(row.id, row)
- this.$message.success('状态已更新')
- } catch (e) {
- row.status = row.status === 'ACTIVE' ? 'DISABLED' : 'ACTIVE'
- this.$message.error('更新失败')
- }
- },
- async handleSubmit() {
- if (!this.form.typeId || !this.form.title) {
- this.$message.warning('请填写完整信息')
- return
- }
- try {
- if (this.isEdit) {
- await updateServiceContent(this.form.id, this.form)
- } else {
- await createServiceContent(this.form)
- }
- this.$message.success('保存成功')
- this.dialogVisible = false
- this.loadData()
- } catch (e) {
- this.$message.error('保存失败')
- }
- },
- insertTag(tag) {
- const tags = {
- b: '<strong></strong>',
- i: '<em></em>',
- u: '<u></u>',
- h3: '<h3></h3>',
- ul: '<ul><li></li></ul>',
- img: '<img src="" alt=""/>'
- }
- this.form.content += tags[tag]
- },
- handleActionCmd(row, cmd) {
- switch (cmd) {
- case 'preview':
- this.handlePreview(row)
- break
- case 'disable':
- row.status = 'DISABLED'
- this.toggleStatus(row)
- break
- case 'enable':
- row.status = 'ACTIVE'
- this.toggleStatus(row)
- break
- }
- }
- }
- }
- </script>
- <style scoped>
- .service-contents {
- padding: 20px;
- }
- .rich-editor {
- border: 1px solid #dcdfe6;
- border-radius: 4px;
- }
- .editor-toolbar {
- padding: 10px;
- border-bottom: 1px solid #dcdfe6;
- background: #f5f7fa;
- }
- .preview-content {
- padding: 20px;
- line-height: 1.8;
- }
- .preview-content h3 {
- margin: 16px 0 8px;
- }
- .preview-content ul {
- padding-left: 20px;
- }
- .preview-content img {
- max-width: 100%;
- }
- </style>
|