【招生用户端】 新增# 总结模板:对接新增、编辑、删除模板接口
parent
b4a860c1c5
commit
15679b26ee
|
@ -0,0 +1,22 @@
|
||||||
|
import request from '@/utils/request'
|
||||||
|
// 总结模板列表
|
||||||
|
export function templateAdd(params?: any) {
|
||||||
|
return request.post({ url: '/template/add', params })
|
||||||
|
}
|
||||||
|
|
||||||
|
// 新增总结模板
|
||||||
|
export function templateLists(params: any) {
|
||||||
|
return request.get({ url: '/template/list', params })
|
||||||
|
}
|
||||||
|
// 编辑总结模板
|
||||||
|
export function templateEdit(params: any) {
|
||||||
|
return request.post({ url: '/template/edit', params })
|
||||||
|
}
|
||||||
|
// 总结模板详情
|
||||||
|
export function templateDetail(params: any) {
|
||||||
|
return request.get({ url: '/template/detail', params })
|
||||||
|
}
|
||||||
|
// 删除总结模板
|
||||||
|
export function templateDelete(params: any) {
|
||||||
|
return request.post({ url: '/template/del', params })
|
||||||
|
}
|
|
@ -62,11 +62,29 @@ export const sexMap: Record<SexEnum, string> = {
|
||||||
[SexEnum.MALE]: '男',
|
[SexEnum.MALE]: '男',
|
||||||
[SexEnum.FEMALE]: '女'
|
[SexEnum.FEMALE]: '女'
|
||||||
}
|
}
|
||||||
|
export enum formTypeEum {
|
||||||
|
INPUT = 1,
|
||||||
|
TEXTAREA = 2
|
||||||
|
}
|
||||||
|
export const formTypeMap: Record<formTypeEum, string> = {
|
||||||
|
[formTypeEum.INPUT]: '单行文本',
|
||||||
|
[formTypeEum.TEXTAREA]: '多行文本'
|
||||||
|
}
|
||||||
|
export enum templateTypeEum {
|
||||||
|
TELE = 5,
|
||||||
|
RECEULT = 6
|
||||||
|
}
|
||||||
|
export const templateTypeMap: Record<templateTypeEum, string> = {
|
||||||
|
[templateTypeEum.TELE]: '电销',
|
||||||
|
[templateTypeEum.RECEULT]: '招生'
|
||||||
|
}
|
||||||
|
|
||||||
const keys: Record<string, any> = {
|
const keys: Record<string, any> = {
|
||||||
conversionMap: conversionMap,
|
conversionMap: conversionMap,
|
||||||
ClueSourceMap: ClueSourceMap,
|
ClueSourceMap: ClueSourceMap,
|
||||||
sexMap: sexMap
|
sexMap: sexMap,
|
||||||
|
formTypeMap: formTypeMap,
|
||||||
|
templateTypeMap: templateTypeMap
|
||||||
}
|
}
|
||||||
const generateConverOptions = (key: string) => {
|
const generateConverOptions = (key: string) => {
|
||||||
const mapKey = keys[key]
|
const mapKey = keys[key]
|
||||||
|
@ -80,3 +98,5 @@ const generateConverOptions = (key: string) => {
|
||||||
export const conversionOptions = generateConverOptions('conversionMap')
|
export const conversionOptions = generateConverOptions('conversionMap')
|
||||||
export const clueSourceOptions = generateConverOptions('ClueSourceMap')
|
export const clueSourceOptions = generateConverOptions('ClueSourceMap')
|
||||||
export const sexOptions = generateConverOptions('sexMap')
|
export const sexOptions = generateConverOptions('sexMap')
|
||||||
|
export const formTypeOptions = generateConverOptions('formTypeMap')
|
||||||
|
export const templateTypeOptions = generateConverOptions('templateTypeMap')
|
||||||
|
|
|
@ -2,16 +2,16 @@
|
||||||
<div class="flex items-center gap-[6px] mb-[10px]">
|
<div class="flex items-center gap-[6px] mb-[10px]">
|
||||||
<span>{{ index + 1 }}.</span>
|
<span>{{ index + 1 }}.</span>
|
||||||
<div class="bg-primary-light-10 p-[16px] rounded-[6px] flex-1">
|
<div class="bg-primary-light-10 p-[16px] rounded-[6px] flex-1">
|
||||||
<el-form-item label="表单类型">
|
<el-form-item label="表单类型" prop="formType">
|
||||||
<el-radio-group v-model="item.formType">
|
<el-radio-group v-model="item.formType">
|
||||||
<el-radio v-for="type in formTypes" :key="type.value" :label="type.value">{{ type.label }}</el-radio>
|
<el-radio v-for="type in templateTypeOptions" :key="type.value" :label="type.value">{{ type.label }}</el-radio>
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="表单标题">
|
<el-form-item label="表单标题" prop="formTitle">
|
||||||
<template v-if="item.formType === 1">
|
<template v-if="item.formType === formTypeEum.INPUT">
|
||||||
<el-input v-model="item.formTitle" placeholder="请输入表单标题" maxlength="50" show-word-limit />
|
<el-input v-model="item.formTitle" placeholder="请输入表单标题" maxlength="50" show-word-limit />
|
||||||
</template>
|
</template>
|
||||||
<template v-if="item.formType === 2">
|
<template v-if="item.formType === formTypeEum.TEXTAREA">
|
||||||
<el-input v-model="item.formTitle" type="textarea" placeholder="请输入表单标题" maxlength="250" show-word-limit />
|
<el-input v-model="item.formTitle" type="textarea" placeholder="请输入表单标题" maxlength="250" show-word-limit />
|
||||||
</template>
|
</template>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
@ -26,6 +26,7 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { PropType } from 'vue'
|
import type { PropType } from 'vue'
|
||||||
import type { Item } from './template-drawer.vue'
|
import type { Item } from './template-drawer.vue'
|
||||||
|
import { formTypeEum, templateTypeOptions } from '@/enums'
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
item: {
|
item: {
|
||||||
|
@ -41,10 +42,6 @@ const props = defineProps({
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
const emit = defineEmits(['handleCopyItem', 'handleDeleteItem'])
|
const emit = defineEmits(['handleCopyItem', 'handleDeleteItem'])
|
||||||
const formTypes = ref([
|
|
||||||
{ label: '单行文本', value: 1 },
|
|
||||||
{ label: '多行文本', value: 2 }
|
|
||||||
])
|
|
||||||
const handleCopyItem = () => {
|
const handleCopyItem = () => {
|
||||||
emit('handleCopyItem', props.index)
|
emit('handleCopyItem', props.index)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,22 +1,22 @@
|
||||||
<template>
|
<template>
|
||||||
<ProDrawer ref="proDrawerRef" @handle-cancel="handleCancel" @handle-confirm="handleConfirm">
|
<ProDrawer ref="proDrawerRef" @handle-cancel="handleCancel" @handle-confirm="handleConfirm">
|
||||||
<el-form v-model="form">
|
<el-form ref="formRef" :rules="rules" :model="form">
|
||||||
<el-form-item label="设置为默认模板">
|
<el-form-item label="设置为默认模板">
|
||||||
<el-switch v-model="form.isDefault" :active-value="1" :inactive-value="0" />
|
<el-switch v-model="form.isDefault" :active-value="1" :inactive-value="0" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="模板名称">
|
<el-form-item label="模板名称" prop="name">
|
||||||
<el-input v-model="form.templateName" placeholder="请输入" maxlength="20" show-word-limit />
|
<el-input v-model="form.name" placeholder="请输入" maxlength="20" show-word-limit />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="模板类型">
|
<el-form-item label="模板类型" prop="postId">
|
||||||
<el-radio-group v-model="form.templateType">
|
<el-radio-group v-model="form.postId">
|
||||||
<el-radio v-for="type in types" :key="type.value" :label="type.value">{{ type.label }}</el-radio>
|
<el-radio v-for="type in types" :key="type.value" :label="type.value">{{ type.label }}</el-radio>
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="模板内容">
|
<el-form-item label="模板内容" prop="templateFormList">
|
||||||
<el-button type="primary" plain @click="handleAddItem">新增模板项</el-button>
|
<el-button type="primary" plain @click="handleAddItem">新增模板项</el-button>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<add-item
|
<add-item
|
||||||
v-for="(item, index) in form.templateItems"
|
v-for="(item, index) in form.templateFormList"
|
||||||
:key="index"
|
:key="index"
|
||||||
:item="item"
|
:item="item"
|
||||||
:index="index"
|
:index="index"
|
||||||
|
@ -30,54 +30,126 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import ProDrawer, { type IParams } from '@/components/ProDrawer/index.vue'
|
import ProDrawer, { type IParams } from '@/components/ProDrawer/index.vue'
|
||||||
import addItem from './add-item.vue'
|
import addItem from './add-item.vue'
|
||||||
|
import { postLists } from '@/api/account_center/postion'
|
||||||
|
import type { FormInstance } from 'element-plus'
|
||||||
|
import { templateAdd, templateDetail, templateEdit, templateLists } from '@/api/summary'
|
||||||
|
import { toast } from '@/utils/util'
|
||||||
|
import feedback from '@/utils/feedback'
|
||||||
|
|
||||||
export interface Item {
|
export interface Item {
|
||||||
formType: number
|
formType: number
|
||||||
formTitle: string
|
formTitle: string
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IForm {
|
interface IForm {
|
||||||
templateName: string
|
id: string
|
||||||
templateType: number
|
name: string
|
||||||
|
postId: number | null
|
||||||
isDefault: number
|
isDefault: number
|
||||||
templateItems: Item[]
|
templateFormList: Item[]
|
||||||
}
|
}
|
||||||
const emit = defineEmits(['refreshList'])
|
const emit = defineEmits(['refreshList'])
|
||||||
const proDrawerRef = ref<InstanceType<typeof ProDrawer>>()
|
|
||||||
|
|
||||||
const types = ref([
|
const proDrawerRef = ref<InstanceType<typeof ProDrawer>>()
|
||||||
{ label: '电销', value: 1 },
|
const types = ref<any[]>([])
|
||||||
{ label: '招生', value: 2 }
|
const fetchPosition = async () => {
|
||||||
])
|
try {
|
||||||
|
const result = await postLists()
|
||||||
|
types.value = result.lists.map(item => ({
|
||||||
|
label: item.name,
|
||||||
|
value: item.id
|
||||||
|
}))
|
||||||
|
} catch (error) {}
|
||||||
|
}
|
||||||
|
fetchPosition()
|
||||||
|
const validateTemplateFormList = (rule: any, value: any, callback: any) => {
|
||||||
|
if (!value) {
|
||||||
|
return callback(new Error('请新增模板内容'))
|
||||||
|
} else {
|
||||||
|
if (value.length > 0) {
|
||||||
|
const findItem = value.find(item => item.formTitle === '')
|
||||||
|
if (findItem) {
|
||||||
|
return callback(new Error('表单标题不能为空'))
|
||||||
|
} else {
|
||||||
|
callback()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const formRef = ref<FormInstance>()
|
||||||
|
const rules = reactive({
|
||||||
|
name: { required: true, message: '请输入模板名称', trigger: 'blur' },
|
||||||
|
postId: { required: true, message: '请选择模板类型', trigger: 'change' },
|
||||||
|
templateFormList: [{ required: true, message: '请新增模板内容', trigger: 'blur' }, { validator: validateTemplateFormList }]
|
||||||
|
})
|
||||||
const form = ref<IForm>({
|
const form = ref<IForm>({
|
||||||
templateName: '',
|
id: '',
|
||||||
templateType: 1,
|
name: '',
|
||||||
|
postId: null,
|
||||||
isDefault: 1,
|
isDefault: 1,
|
||||||
templateItems: []
|
templateFormList: []
|
||||||
})
|
})
|
||||||
const handleAddItem = () => {
|
const handleAddItem = () => {
|
||||||
form.value.templateItems.push({
|
form.value.templateFormList.push({
|
||||||
formType: 1,
|
formType: 1,
|
||||||
formTitle: ''
|
formTitle: ''
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
const handleCopyItem = (index: number) => {
|
const handleCopyItem = (index: number) => {
|
||||||
form.value.templateItems.splice(index, 0, {
|
form.value.templateFormList.splice(index + 1, 0, {
|
||||||
formType: 1,
|
formType: 1,
|
||||||
formTitle: ''
|
formTitle: ''
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
const handleDeleteItem = (index: number) => {
|
const handleDeleteItem = (index: number) => {
|
||||||
form.value.templateItems.splice(index, 1)
|
form.value.templateFormList.splice(index, 1)
|
||||||
}
|
}
|
||||||
const openDrawer = (params: IParams) => {
|
const openDrawer = (params: IParams) => {
|
||||||
|
clearForm()
|
||||||
|
const { data } = params
|
||||||
|
if (data.id) fetchDetail(data.id)
|
||||||
proDrawerRef.value?.openDrawer(params)
|
proDrawerRef.value?.openDrawer(params)
|
||||||
}
|
}
|
||||||
const handleCancel = (callback: () => void) => {
|
const handleCancel = (callback: () => void) => {
|
||||||
callback()
|
callback()
|
||||||
}
|
}
|
||||||
const handleConfirm = (callback: () => void) => {
|
const handleConfirm = (callback: () => void) => {
|
||||||
callback()
|
const { id } = form.value
|
||||||
emit('refreshList')
|
formRef.value?.validate(async valid => {
|
||||||
|
if (!valid) return
|
||||||
|
try {
|
||||||
|
const api = id ? templateEdit : templateAdd
|
||||||
|
await api(form.value)
|
||||||
|
const msg = id ? '编辑' : '新增'
|
||||||
|
feedback.msgSuccess(`${msg}成功`)
|
||||||
|
callback()
|
||||||
|
emit('refreshList')
|
||||||
|
} catch (error) {}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const fetchDetail = async (id: number) => {
|
||||||
|
try {
|
||||||
|
const result = await templateDetail({ id })
|
||||||
|
setFormData(result)
|
||||||
|
} catch (error) {}
|
||||||
|
}
|
||||||
|
const setFormData = result => {
|
||||||
|
for (const key in result) {
|
||||||
|
if (Object.prototype.hasOwnProperty.call(form.value, key) && (result[key] != null || result[key] !== undefined)) {
|
||||||
|
form.value[key] = result[key]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const clearForm = () => {
|
||||||
|
form.value = {
|
||||||
|
id: '',
|
||||||
|
name: '',
|
||||||
|
postId: null,
|
||||||
|
isDefault: 1,
|
||||||
|
templateFormList: []
|
||||||
|
}
|
||||||
|
formRef.value?.resetFields()
|
||||||
}
|
}
|
||||||
defineExpose({
|
defineExpose({
|
||||||
openDrawer
|
openDrawer
|
||||||
|
|
|
@ -21,8 +21,7 @@ import summaryRecord from './modules/summary-record.vue'
|
||||||
const queryParams = ref<Record<string, any>>({
|
const queryParams = ref<Record<string, any>>({
|
||||||
template: {
|
template: {
|
||||||
name: '',
|
name: '',
|
||||||
type: '',
|
postId: ''
|
||||||
status: null
|
|
||||||
},
|
},
|
||||||
record: {
|
record: {
|
||||||
submitName: '',
|
submitName: '',
|
||||||
|
|
|
@ -8,9 +8,14 @@
|
||||||
<template #name="{ row }">
|
<template #name="{ row }">
|
||||||
<el-space>
|
<el-space>
|
||||||
<span>{{ row.name }}</span>
|
<span>{{ row.name }}</span>
|
||||||
<span>{{ tagName(row) }}</span>
|
<span v-if="row.isDefault" class="px-[6px] border border-solid border-[#12BB37] rounded-[4px] text-[#12BB37]">
|
||||||
|
{{ tagName(row) }}
|
||||||
|
</span>
|
||||||
</el-space>
|
</el-space>
|
||||||
</template>
|
</template>
|
||||||
|
<template #postId="{ row }">
|
||||||
|
<span>{{ typeName(row) }}</span>
|
||||||
|
</template>
|
||||||
<template #status="{ row }">
|
<template #status="{ row }">
|
||||||
<el-switch v-model="row.status" :active-value="1" :inactive-value="0" :before-change="() => handleBeforeChange(row)" />
|
<el-switch v-model="row.status" :active-value="1" :inactive-value="0" :before-change="() => handleBeforeChange(row)" />
|
||||||
</template>
|
</template>
|
||||||
|
@ -27,8 +32,8 @@
|
||||||
import useHandleData from '@/hooks/useHandleData'
|
import useHandleData from '@/hooks/useHandleData'
|
||||||
import templateDrawer from '../components/template-drawer.vue'
|
import templateDrawer from '../components/template-drawer.vue'
|
||||||
import { usePaging } from '@/hooks/usePaging'
|
import { usePaging } from '@/hooks/usePaging'
|
||||||
import { postLists } from '@/api/org/post'
|
|
||||||
import feedback from '@/utils/feedback'
|
import feedback from '@/utils/feedback'
|
||||||
|
import { templateDelete, templateLists } from '@/api/summary'
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
queryParams: {
|
queryParams: {
|
||||||
|
@ -43,7 +48,7 @@ const props = defineProps({
|
||||||
const emit = defineEmits(['handleEdit', 'handleDelete'])
|
const emit = defineEmits(['handleEdit', 'handleDelete'])
|
||||||
|
|
||||||
const { pager, getLists, resetPage, resetParams } = usePaging({
|
const { pager, getLists, resetPage, resetParams } = usePaging({
|
||||||
fetchFun: postLists,
|
fetchFun: templateLists,
|
||||||
params: props.queryParams
|
params: props.queryParams
|
||||||
})
|
})
|
||||||
getLists()
|
getLists()
|
||||||
|
@ -51,31 +56,29 @@ const proTableRef = ref()
|
||||||
const columns = reactive([
|
const columns = reactive([
|
||||||
{ type: 'selection', width: 70 },
|
{ type: 'selection', width: 70 },
|
||||||
{ prop: 'name', label: '模板名称', width: 180 },
|
{ prop: 'name', label: '模板名称', width: 180 },
|
||||||
{ prop: 'type', label: '模板类型', width: 180 },
|
{ prop: 'postId', label: '模板类型', width: 180 },
|
||||||
{ prop: 'status', label: '模板状态', width: 180 },
|
|
||||||
{ prop: 'createTime', label: '创建时间', width: 180 },
|
{ prop: 'createTime', label: '创建时间', width: 180 },
|
||||||
{ prop: 'updateTime', label: '更新时间', width: 180 },
|
{ prop: 'updateTime', label: '更新时间', width: 180 },
|
||||||
{ prop: 'operation', label: '操作', fixed: 'right', width: 250 }
|
{ prop: 'operation', label: '操作', fixed: 'right', width: 250 }
|
||||||
])
|
])
|
||||||
const enumType: Record<number, string> = {
|
const typeName = computed(() => row => row.postId == 5 ? '电销' : '招生')
|
||||||
1: '电销',
|
|
||||||
2: '招生'
|
|
||||||
}
|
|
||||||
const typeName = computed(() => row => enumType[row.type])
|
|
||||||
const tagName = computed(() => row => row.isDefault == 1 ? `默认${typeName.value(row)}模板` : '')
|
const tagName = computed(() => row => row.isDefault == 1 ? `默认${typeName.value(row)}模板` : '')
|
||||||
const templateDrawerRef = ref<InstanceType<typeof templateDrawer>>()
|
const templateDrawerRef = ref<InstanceType<typeof templateDrawer>>()
|
||||||
const handleAdd = () => {
|
const handleAdd = () => {
|
||||||
templateDrawerRef.value?.openDrawer({
|
openDrawer()
|
||||||
title: '新增模板',
|
|
||||||
width: 500,
|
|
||||||
data: {}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
const handleEdit = row => {
|
const handleEdit = row => {
|
||||||
|
const { id } = row
|
||||||
|
openDrawer(id)
|
||||||
|
}
|
||||||
|
const openDrawer = (id?: number) => {
|
||||||
templateDrawerRef.value?.openDrawer({
|
templateDrawerRef.value?.openDrawer({
|
||||||
title: '新增模板',
|
title: !id ? '新增模板' : '编辑模板',
|
||||||
width: 500,
|
width: 500,
|
||||||
data: { ...row }
|
data: {
|
||||||
|
id,
|
||||||
|
showFooter: true
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
const isDisabled = computed(() => proTableRef?.value?.selectedListIds?.length == 0)
|
const isDisabled = computed(() => proTableRef?.value?.selectedListIds?.length == 0)
|
||||||
|
@ -88,10 +91,14 @@ const handleBatchDelete = () => {
|
||||||
const deleteCommon = async (row?: any) => {
|
const deleteCommon = async (row?: any) => {
|
||||||
if (row) proTableRef.value.tableRef.toggleRowSelection(row, true)
|
if (row) proTableRef.value.tableRef.toggleRowSelection(row, true)
|
||||||
const ids = proTableRef.value.selectedListIds
|
const ids = proTableRef.value.selectedListIds
|
||||||
const message = '是否要删除选中的?'
|
const message = '是否要删除选中的模板?'
|
||||||
const flag = await useHandleData(message)
|
const flag = await useHandleData(message)
|
||||||
if (flag) {
|
if (flag) {
|
||||||
console.log(ids)
|
try {
|
||||||
|
await templateDelete({ ids })
|
||||||
|
feedback.msgSuccess('删除成功')
|
||||||
|
getLists()
|
||||||
|
} catch (error) {}
|
||||||
}
|
}
|
||||||
proTableRef.value.tableRef.clearSelection()
|
proTableRef.value.tableRef.clearSelection()
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,13 +5,8 @@
|
||||||
<el-input class="w-[280px]" placeholder="请输入" v-model="modelValue.name" clearable @keyup.enter="$emit('resetPage')" />
|
<el-input class="w-[280px]" placeholder="请输入" v-model="modelValue.name" clearable @keyup.enter="$emit('resetPage')" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="模板类型">
|
<el-form-item label="模板类型">
|
||||||
<el-select class="w-[280px]" v-model="modelValue.type">
|
<el-select class="w-[280px]" v-model="modelValue.postId">
|
||||||
<el-option v-for="option in typeOptions" :key="option.value" :label="option.label" :value="option.value" />
|
<el-option v-for="option in templateTypeOptions" :key="option.value" :label="option.label" :value="option.value" />
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="模板状态">
|
|
||||||
<el-select class="w-[280px]" v-model="modelValue.status">
|
|
||||||
<el-option v-for="option in statusOptions" :key="option.value" :label="option.label" :value="option.value" />
|
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
|
@ -23,25 +18,17 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import { templateTypeOptions } from '@/enums'
|
||||||
defineProps({
|
defineProps({
|
||||||
modelValue: {
|
modelValue: {
|
||||||
type: Object,
|
type: Object,
|
||||||
default: () => ({
|
default: () => ({
|
||||||
name: '',
|
name: '',
|
||||||
type: '',
|
postId: ''
|
||||||
status: null
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
defineEmits(['resetPage', 'resetParams'])
|
defineEmits(['resetPage', 'resetParams'])
|
||||||
const typeOptions = ref([
|
|
||||||
{ label: '电销', value: 1 },
|
|
||||||
{ label: '招生', value: 2 }
|
|
||||||
])
|
|
||||||
const statusOptions = ref([
|
|
||||||
{ label: '启用', value: 1 },
|
|
||||||
{ label: '停用', value: 2 }
|
|
||||||
])
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss"></style>
|
<style scoped lang="scss"></style>
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
<template>
|
||||||
|
<div class="flex flex-col gap-[16px] bg-white p-[20px]">
|
||||||
|
<div class="flex-row-between-center">
|
||||||
|
<span>{{ title }}</span>
|
||||||
|
<slot name="right" />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<slot />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
defineProps({
|
||||||
|
title: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
<style scoped></style>
|
|
@ -0,0 +1,10 @@
|
||||||
|
<template>
|
||||||
|
<card title="数据简报">
|
||||||
|
<div>333</div>
|
||||||
|
</card>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import card from './card.vue'
|
||||||
|
</script>
|
||||||
|
<style scoped></style>
|
|
@ -0,0 +1,259 @@
|
||||||
|
<template>
|
||||||
|
<div class="workbench">
|
||||||
|
<div class="lg:flex">
|
||||||
|
<el-card
|
||||||
|
class="!border-none mb-4 md:mr-4"
|
||||||
|
shadow="never"
|
||||||
|
:body-style="{
|
||||||
|
width: '400px'
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<template #header>
|
||||||
|
<span class="card-title">平台信息</span>
|
||||||
|
</template>
|
||||||
|
<div>
|
||||||
|
<div class="flex leading-9">
|
||||||
|
<div class="mr-3">平台名称</div>
|
||||||
|
<span>{{ workbenchData.version.name }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="flex leading-9">
|
||||||
|
<div class="mr-3">当前版本</div>
|
||||||
|
|
||||||
|
<div class="flex">
|
||||||
|
<div>{{ workbenchData.version.version }}</div>
|
||||||
|
<!-- <div class="flex">
|
||||||
|
<el-icon class="text-[#4073fa] mt-[10px] ml-2"><Top /></el-icon>
|
||||||
|
<div class="text-[#4073fa] cursor-pointer">有新版本</div>
|
||||||
|
</div> -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-card>
|
||||||
|
|
||||||
|
<el-card class="!border-none mb-4 flex-1" shadow="never">
|
||||||
|
<template #header>
|
||||||
|
<div>
|
||||||
|
<span class="card-title">数据统计</span>
|
||||||
|
<span class="ml-4 text-xs text-tx-secondary">
|
||||||
|
更新时间:{{ workbenchData.today.time }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<div class="flex flex-wrap">
|
||||||
|
<div class="w-1/2 md:w-1/4">
|
||||||
|
<div class="leading-10">今日销量(笔)</div>
|
||||||
|
<div class="text-6xl">{{ workbenchData.today.todaySalesCount }}</div>
|
||||||
|
<div class="text-xs text-tx-secondary">
|
||||||
|
总销量:{{ workbenchData.today.totalSalesCount }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="w-1/2 md:w-1/4">
|
||||||
|
<div class="leading-10">今日销售金额(元)</div>
|
||||||
|
<div class="text-6xl">{{ workbenchData.today.todaySalesAmount }}</div>
|
||||||
|
<div class="text-xs text-tx-secondary">
|
||||||
|
总销售金额:{{ `¥${workbenchData.today.totalSalesAmount}` }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="w-1/2 md:w-1/4">
|
||||||
|
<div class="leading-10">新增会员(人)</div>
|
||||||
|
<div class="text-6xl">{{ workbenchData.today.todayNewUser }}</div>
|
||||||
|
<div class="text-xs text-tx-secondary">
|
||||||
|
总会员量:{{ workbenchData.today.totalNewUser }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="w-1/2 md:w-1/4">
|
||||||
|
<div class="leading-10">用户访问量(人)</div>
|
||||||
|
<div class="text-6xl">{{ workbenchData.today.todayVisitor }}</div>
|
||||||
|
<div class="text-xs text-tx-secondary">
|
||||||
|
总访问量:{{ workbenchData.today.totalVisitor }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-card>
|
||||||
|
</div>
|
||||||
|
<div class="mb-4 function">
|
||||||
|
<el-card class="flex-1 !border-none" shadow="never">
|
||||||
|
<template #header>
|
||||||
|
<span>常用功能</span>
|
||||||
|
</template>
|
||||||
|
<div class="flex flex-wrap">
|
||||||
|
<div
|
||||||
|
v-for="item in workbenchData.menu"
|
||||||
|
class="md:w-[12.5%] w-1/4 flex flex-col items-center"
|
||||||
|
:key="item"
|
||||||
|
>
|
||||||
|
<router-link :to="item.url" class="flex flex-col items-center mb-3">
|
||||||
|
<img width="40" height="40" :src="item.image" />
|
||||||
|
<div class="mt-2">{{ item.name }}</div>
|
||||||
|
</router-link>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-card>
|
||||||
|
</div>
|
||||||
|
<div class="lg:flex">
|
||||||
|
<el-card class="flex-1 !border-none md:mr-4 mb-4" shadow="never">
|
||||||
|
<template #header>
|
||||||
|
<span>销售额趋势图(近15天)</span>
|
||||||
|
</template>
|
||||||
|
<div>
|
||||||
|
<v-charts
|
||||||
|
style="height: 350px"
|
||||||
|
:option="workbenchData.businessOption"
|
||||||
|
:autoresize="true"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</el-card>
|
||||||
|
|
||||||
|
<el-card class="flex-1 !border-none md:mr-4 mb-4" shadow="never">
|
||||||
|
<template #header>
|
||||||
|
<span>用户访问量(近15天)</span>
|
||||||
|
</template>
|
||||||
|
<div>
|
||||||
|
<v-charts
|
||||||
|
style="height: 350px"
|
||||||
|
:option="workbenchData.visitorOption"
|
||||||
|
:autoresize="true"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</el-card>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import goods_lists from './images/goods_lists.png'
|
||||||
|
import goods_category from './images/goods_category.png'
|
||||||
|
import order from './images/order.png'
|
||||||
|
import staff from './images/staff.png'
|
||||||
|
import index_decorate from './images/index_decorate.png'
|
||||||
|
import set_payment from './images/set_payment.png'
|
||||||
|
import distributor from './images/distributor.png'
|
||||||
|
import coupon from './images/coupon.png'
|
||||||
|
import { getWorkbench } from '@/api/app'
|
||||||
|
import vCharts from 'vue-echarts'
|
||||||
|
// 表单数据
|
||||||
|
const workbenchData: any = reactive({
|
||||||
|
version: {
|
||||||
|
version: '', // 系统版本
|
||||||
|
website: '' // 平台名称
|
||||||
|
},
|
||||||
|
today: {}, // 今日数据
|
||||||
|
menu: [
|
||||||
|
{
|
||||||
|
name: '服务列表',
|
||||||
|
image: goods_lists,
|
||||||
|
url: '/service/lists'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '服务分类',
|
||||||
|
image: goods_category,
|
||||||
|
url: '/service/category'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '订单列表',
|
||||||
|
image: order,
|
||||||
|
url: '/order/lists'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '师傅列表',
|
||||||
|
image: staff,
|
||||||
|
url: '/master_worker/index'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '分销商列表',
|
||||||
|
image: distributor,
|
||||||
|
url: '/distributor/index'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '首页装修',
|
||||||
|
image: index_decorate,
|
||||||
|
url: '/decorate/index'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '优惠券管理',
|
||||||
|
image: coupon,
|
||||||
|
url: '/marketing/coupon/lists'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '支付配置',
|
||||||
|
image: set_payment,
|
||||||
|
url: '/setting/payment/payment_config'
|
||||||
|
}
|
||||||
|
], // 常用功能
|
||||||
|
visitor: [], // 访问量
|
||||||
|
business: [], // 销售额
|
||||||
|
|
||||||
|
businessOption: {
|
||||||
|
xAxis: {
|
||||||
|
type: 'category',
|
||||||
|
data: []
|
||||||
|
},
|
||||||
|
yAxis: {
|
||||||
|
type: 'value'
|
||||||
|
},
|
||||||
|
itemStyle: {
|
||||||
|
// 点的颜色。
|
||||||
|
color: 'red'
|
||||||
|
},
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'axis'
|
||||||
|
},
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
name: '销售量',
|
||||||
|
data: [],
|
||||||
|
type: 'line',
|
||||||
|
smooth: true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
|
||||||
|
visitorOption: {
|
||||||
|
xAxis: {
|
||||||
|
type: 'category',
|
||||||
|
data: []
|
||||||
|
},
|
||||||
|
yAxis: {
|
||||||
|
type: 'value'
|
||||||
|
},
|
||||||
|
itemStyle: {
|
||||||
|
// 点的颜色。
|
||||||
|
color: 'red'
|
||||||
|
},
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'axis'
|
||||||
|
},
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
name: '访问量',
|
||||||
|
data: [],
|
||||||
|
type: 'line',
|
||||||
|
smooth: true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// 获取工作台主页数据
|
||||||
|
const getData = async () => {
|
||||||
|
const res = await getWorkbench()
|
||||||
|
workbenchData.version = res.version
|
||||||
|
workbenchData.today = res.today
|
||||||
|
workbenchData.visitor = res.visitor
|
||||||
|
workbenchData.business = res.business
|
||||||
|
|
||||||
|
// 写入数据
|
||||||
|
workbenchData.visitorOption.xAxis.data = workbenchData.visitor.date
|
||||||
|
workbenchData.visitorOption.series[0].data = workbenchData.visitor.list.data
|
||||||
|
|
||||||
|
workbenchData.businessOption.xAxis.data = workbenchData.business.date
|
||||||
|
workbenchData.businessOption.series[0].data = workbenchData.business.list.data
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
getData()
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped></style>
|
Loading…
Reference in New Issue