【招生用户端】 新增# 对接客户管理列表、详情接口
parent
662f221890
commit
fed8c9e1a5
|
@ -0,0 +1,14 @@
|
||||||
|
import request from '@/utils/request'
|
||||||
|
|
||||||
|
// 成交客户列表
|
||||||
|
export function customerLists(params?: any) {
|
||||||
|
return request.get({ url: '/client/list', params })
|
||||||
|
}
|
||||||
|
// 成交客户详情
|
||||||
|
export function customerDetail(params?: any) {
|
||||||
|
return request.get({ url: '/client/detail', params })
|
||||||
|
}
|
||||||
|
// 编辑成交客户
|
||||||
|
export function customerEdit(params?: any) {
|
||||||
|
return request.post({ url: '/client/edit', params })
|
||||||
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
<template>
|
<template>
|
||||||
<el-drawer v-model="drawerVisible" :title="parameter.title" :size="parameter.width">
|
<el-drawer v-model="drawerVisible" :title="parameter.title" :size="parameter.width">
|
||||||
<slot />
|
<slot />
|
||||||
<template #footer>
|
<template #footer v-if="parameter.data.showFooter">
|
||||||
<el-button @click="handleCancel">取消</el-button>
|
<el-button @click="handleCancel">取消</el-button>
|
||||||
<el-button type="primary" @click="handleConfirm">确认</el-button>
|
<el-button type="primary" @click="handleConfirm">确认</el-button>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -28,22 +28,14 @@ export const conversionMap: Record<converStatusEnum, string> = {
|
||||||
[converStatusEnum.CONVERTED]: '已成交',
|
[converStatusEnum.CONVERTED]: '已成交',
|
||||||
[converStatusEnum.FAILED]: '已战败'
|
[converStatusEnum.FAILED]: '已战败'
|
||||||
}
|
}
|
||||||
const generateConverOptions = () => {
|
|
||||||
return Object.keys(conversionMap).map(item => {
|
|
||||||
return {
|
|
||||||
label: conversionMap[item],
|
|
||||||
value: item
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
export const conversionOptions = generateConverOptions()
|
|
||||||
|
|
||||||
export enum CluseSourceEnum {
|
export enum CluseSourceEnum {
|
||||||
OFFLINE_LIST = 0
|
OFFLINE_LIST = 0
|
||||||
}
|
}
|
||||||
export const ClueSourceMap = {
|
export const ClueSourceMap: Record<CluseSourceEnum, string> = {
|
||||||
[CluseSourceEnum.OFFLINE_LIST]: '线下列表'
|
[CluseSourceEnum.OFFLINE_LIST]: '线下列表'
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum stateEnum {
|
export enum stateEnum {
|
||||||
ADD_RELATION = 0, //账号已添加
|
ADD_RELATION = 0, //账号已添加
|
||||||
NO_EXIST = 1, //账号不存在
|
NO_EXIST = 1, //账号不存在
|
||||||
|
@ -62,3 +54,19 @@ export const conversitionMap: Record<ConverSuccessEnum, string> = {
|
||||||
[ConverSuccessEnum.YES]: '是',
|
[ConverSuccessEnum.YES]: '是',
|
||||||
[ConverSuccessEnum.NO]: '否'
|
[ConverSuccessEnum.NO]: '否'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const keys: Record<string, any> = {
|
||||||
|
conversionMap: conversionMap,
|
||||||
|
ClueSourceMap: ClueSourceMap
|
||||||
|
}
|
||||||
|
const generateConverOptions = (key: string) => {
|
||||||
|
const mapKey = keys[key]
|
||||||
|
return Object.keys(mapKey).map(item => {
|
||||||
|
return {
|
||||||
|
label: mapKey[item],
|
||||||
|
value: Number(item)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
export const conversionOptions = generateConverOptions('conversionMap')
|
||||||
|
export const clueSourceOptions = generateConverOptions('ClueSourceMap')
|
||||||
|
|
|
@ -51,5 +51,5 @@
|
||||||
--el-box-shadow-light: 0px 0px 12px rgba(0, 0, 0, 0.12);
|
--el-box-shadow-light: 0px 0px 12px rgba(0, 0, 0, 0.12);
|
||||||
--el-box-shadow-lighter: 0px 0px 6px rgba(0, 0, 0, 0.12);
|
--el-box-shadow-lighter: 0px 0px 6px rgba(0, 0, 0, 0.12);
|
||||||
--el-box-shadow-dark: 0px 16px 48px 16px rgba(0, 0, 0, 0.08), 0px 12px 32px rgba(0, 0, 0, 0.12), 0px 8px 16px -8px rgba(0, 0, 0, 0.16);
|
--el-box-shadow-dark: 0px 16px 48px 16px rgba(0, 0, 0, 0.08), 0px 12px 32px rgba(0, 0, 0, 0.12), 0px 8px 16px -8px rgba(0, 0, 0, 0.16);
|
||||||
--color-purple: '#800080';
|
--color-purple: #800080;
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,12 +11,13 @@
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { clueDetail } from '@/api/clue'
|
import { clueDetail } from '@/api/clue'
|
||||||
import { ClueSourceMap, conversitionMap, stateMap } from '@/enums'
|
import { ClueSourceMap, conversionMap, conversitionMap, stateMap } from '@/enums'
|
||||||
|
|
||||||
const optionsMap: Record<string, any> = {
|
const optionsMap: Record<string, any> = {
|
||||||
listSource: ClueSourceMap,
|
listSource: ClueSourceMap,
|
||||||
state: stateMap,
|
situation: conversionMap,
|
||||||
isConversion: conversitionMap
|
isConversion: conversitionMap,
|
||||||
|
state: stateMap
|
||||||
}
|
}
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
|
@ -30,7 +31,7 @@ const props = defineProps({
|
||||||
})
|
})
|
||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
const baseInfo = ref<any[]>([])
|
const baseInfo = ref<any[]>([])
|
||||||
const formatValue = computed(() => (field: string, value: number) => optionsMap[field][value])
|
const formatValue = computed(() => (field: string, value: number) => optionsMap[field][value] ?? '--')
|
||||||
|
|
||||||
const fetchClueDetail = async () => {
|
const fetchClueDetail = async () => {
|
||||||
const { id } = props
|
const { id } = props
|
||||||
|
@ -47,15 +48,15 @@ const assemData = (result: any) => {
|
||||||
|
|
||||||
const clueBaseInfo = {
|
const clueBaseInfo = {
|
||||||
线索基本信息: { listSource: '线索来源', studentName: '学生名字', phone: '联系电话', basicInformation: '基本情况' },
|
线索基本信息: { listSource: '线索来源', studentName: '学生名字', phone: '联系电话', basicInformation: '基本情况' },
|
||||||
电销信息: { telemarketingTeacherName: '负责人', telemarketingOrganization: '所属组织', state: '线索状态', followUpTime: '跟进时间' },
|
电销信息: { telemarketingTeacherName: '负责人', telemarketingOrganization: '所属组织', situation: '线索状态', followUpTime: '跟进时间' },
|
||||||
招生信息: {
|
招生信息: {
|
||||||
recruitTeacherName: '负责人',
|
recruitTeacherName: '负责人',
|
||||||
recruitOrganization: '所属组织',
|
recruitOrganization: '所属组织',
|
||||||
state: '线索状态',
|
state: '状态',
|
||||||
getTime: '领取时间',
|
getTime: '领取时间',
|
||||||
isConversion: '是否转化成功',
|
isConversion: '是否转化成功',
|
||||||
remark: '备注',
|
remark: '备注',
|
||||||
updateTime: '成交时间'
|
accomplishTime: '成交时间'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Object.keys(clueBaseInfo).forEach((key: ClueBaseInfoKeys) => {
|
Object.keys(clueBaseInfo).forEach((key: ClueBaseInfoKeys) => {
|
||||||
|
@ -64,8 +65,8 @@ const assemData = (result: any) => {
|
||||||
const value = result[item]
|
const value = result[item]
|
||||||
return {
|
return {
|
||||||
label: data[item],
|
label: data[item],
|
||||||
value,
|
value: value ?? '--',
|
||||||
custom: ['listSource', 'state', 'isConversion'].includes(item),
|
custom: ['listSource', 'situation', 'isConversion', 'state'].includes(item),
|
||||||
field: item
|
field: item
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -74,6 +75,7 @@ const assemData = (result: any) => {
|
||||||
data: list
|
data: list
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
console.log(baseInfo.value)
|
||||||
}
|
}
|
||||||
watch(
|
watch(
|
||||||
() => props.modelValue,
|
() => props.modelValue,
|
||||||
|
@ -82,5 +84,14 @@ watch(
|
||||||
},
|
},
|
||||||
{ immediate: true }
|
{ immediate: true }
|
||||||
)
|
)
|
||||||
|
watch(
|
||||||
|
() => props.id,
|
||||||
|
(newVal, oldVal) => {
|
||||||
|
if (newVal !== oldVal) {
|
||||||
|
baseInfo.value = []
|
||||||
|
fetchClueDetail()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
</script>
|
</script>
|
||||||
<style scoped></style>
|
<style scoped></style>
|
||||||
|
|
|
@ -43,7 +43,7 @@ const columns = reactive([
|
||||||
{ prop: 'studentName', label: '学生名字', width: 180 },
|
{ prop: 'studentName', label: '学生名字', width: 180 },
|
||||||
{ prop: 'phone', label: '联系电话', width: 180 },
|
{ prop: 'phone', label: '联系电话', width: 180 },
|
||||||
{ prop: 'telemarketingTeacherName', label: '电销老师', width: 180 },
|
{ prop: 'telemarketingTeacherName', label: '电销老师', width: 180 },
|
||||||
{ prop: 'recruitTeacherName', label: '转化老师', width: 180 },
|
{ prop: 'recruitTeacherName', label: '招生老师', width: 180 },
|
||||||
{ prop: 'listSource', label: '名单来源', width: 180 },
|
{ prop: 'listSource', label: '名单来源', width: 180 },
|
||||||
{ prop: 'situation', label: '转化情况', width: 180 },
|
{ prop: 'situation', label: '转化情况', width: 180 },
|
||||||
{ prop: 'operation', label: '操作', fixed: 'right', width: 250 }
|
{ prop: 'operation', label: '操作', fixed: 'right', width: 250 }
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
<el-row :gutter="24">
|
<el-row :gutter="24">
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-form-item label="身份证号码">
|
<el-form-item label="身份证号码">
|
||||||
<el-input v-model="form.codeNumber" placeholder="请输入" maxlength="18" show-word-limit />
|
<el-input v-model="form.idCard" placeholder="请输入" maxlength="18" show-word-limit />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
|
@ -30,44 +30,44 @@
|
||||||
<el-row :gutter="24">
|
<el-row :gutter="24">
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-form-item label="毕业院校">
|
<el-form-item label="毕业院校">
|
||||||
<el-input v-model="form.school" placeholder="请输入" maxlength="50" show-word-limit />
|
<el-input v-model="form.graduationSchool" placeholder="请输入" maxlength="50" show-word-limit />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-form-item label="家庭地址">
|
<el-form-item label="家庭地址">
|
||||||
<el-input v-model="form.address" placeholder="请输入" maxlength="100" show-word-limit />
|
<el-input v-model="form.homeAddress" placeholder="请输入" maxlength="100" show-word-limit />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
<el-row :gutter="24">
|
<el-row :gutter="24">
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-form-item label="家长姓名">
|
<el-form-item label="家长姓名">
|
||||||
<el-input v-model="form.name" placeholder="请输入" maxlength="20" show-word-limit />
|
<el-input v-model="form.parentName" placeholder="请输入" maxlength="20" show-word-limit />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-form-item label="家长电话">
|
<el-form-item label="家长电话">
|
||||||
<el-input v-model="form.mobile" placeholder="请输入" maxlength="11" show-word-limit />
|
<el-input v-model="form.parentPhone" placeholder="请输入" maxlength="11" show-word-limit />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
<el-row :gutter="24">
|
<el-row :gutter="24">
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-form-item label="负责电销老师">
|
<el-form-item label="负责电销老师">
|
||||||
<el-input v-model="form.teleName" placeholder="请输入" disabled />
|
<el-input v-model="form.telemarketingTeacherName" placeholder="请输入" disabled />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-form-item label="负责招生老师">
|
<el-form-item label="负责招生老师">
|
||||||
<el-input v-model="form.admissionName" placeholder="请输入" disabled />
|
<el-input v-model="form.recruitTeacherName" placeholder="请输入" disabled />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
<el-row :gutter="24">
|
<el-row :gutter="24">
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-form-item label="数据来源">
|
<el-form-item label="数据来源">
|
||||||
<el-select v-model="form.source" placeholder="请选择" style="width: 100%" disabled>
|
<el-select v-model="form.listSource" placeholder="请选择" style="width: 100%" disabled>
|
||||||
<el-option v-for="option in clueSource" :key="option.value" :label="option.label" :value="option.value" />
|
<el-option v-for="option in clueSourceOptions" :key="option.value" :label="option.label" :value="option.value" />
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
|
@ -77,7 +77,9 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import { customerDetail } from '@/api/customer'
|
||||||
import ProDialog, { type IParams } from '@/components/ProDialog/index.vue'
|
import ProDialog, { type IParams } from '@/components/ProDialog/index.vue'
|
||||||
|
import { clueSourceOptions } from '@/enums'
|
||||||
|
|
||||||
const emit = defineEmits(['refreshList'])
|
const emit = defineEmits(['refreshList'])
|
||||||
const proDialogRef = ref<InstanceType<typeof ProDialog>>()
|
const proDialogRef = ref<InstanceType<typeof ProDialog>>()
|
||||||
|
@ -86,22 +88,37 @@ const sexOptions = ref([
|
||||||
{ label: '男', value: 1 },
|
{ label: '男', value: 1 },
|
||||||
{ label: '女', value: 2 }
|
{ label: '女', value: 2 }
|
||||||
])
|
])
|
||||||
const clueSource = ref([{ label: '线下名单', value: 1 }])
|
|
||||||
const form = ref({
|
const form = ref({
|
||||||
|
id: '',
|
||||||
studentName: '',
|
studentName: '',
|
||||||
sex: 1,
|
sex: 1,
|
||||||
codeNumber: '',
|
idCard: '',
|
||||||
major: '',
|
major: '',
|
||||||
school: '',
|
graduationSchool: '',
|
||||||
address: '',
|
homeAddress: '',
|
||||||
name: '',
|
parentName: '',
|
||||||
mobile: '',
|
parentPhone: '',
|
||||||
teleName: '',
|
telemarketingTeacherName: '',
|
||||||
admissionName: '',
|
recruitTeacherName: '',
|
||||||
source: 1
|
listSource: 0
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const fetchDetail = async (id: number) => {
|
||||||
|
try {
|
||||||
|
const result = await customerDetail({ 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] as any
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
const openDialog = (params: IParams) => {
|
const openDialog = (params: IParams) => {
|
||||||
proDialogRef.value?.openDialog(params)
|
proDialogRef.value?.openDialog(params)
|
||||||
|
fetchDetail(params.data.id)
|
||||||
}
|
}
|
||||||
const handleCancel = (callback: () => void) => {
|
const handleCancel = (callback: () => void) => {
|
||||||
callback()
|
callback()
|
||||||
|
|
|
@ -15,23 +15,25 @@ import searchForm from './modules/search-form.vue'
|
||||||
import customerList from './modules/customer-list.vue'
|
import customerList from './modules/customer-list.vue'
|
||||||
import customerDialog from './components/customer-dialog.vue'
|
import customerDialog from './components/customer-dialog.vue'
|
||||||
import { usePaging } from '@/hooks/usePaging'
|
import { usePaging } from '@/hooks/usePaging'
|
||||||
import { postLists } from '@/api/org/post'
|
import { customerLists } from '@/api/customer'
|
||||||
|
|
||||||
const queryParams = reactive({
|
const queryParams = reactive({
|
||||||
name: '',
|
studentName: ''
|
||||||
conversionStatus: ''
|
|
||||||
})
|
})
|
||||||
const { pager, getLists, resetPage, resetParams } = usePaging({
|
const { pager, getLists, resetPage, resetParams } = usePaging({
|
||||||
fetchFun: postLists,
|
fetchFun: customerLists,
|
||||||
params: queryParams
|
params: queryParams
|
||||||
})
|
})
|
||||||
getLists()
|
getLists()
|
||||||
const customerDialogRef = ref()
|
const customerDialogRef = ref()
|
||||||
const handleEdit = row => {
|
const handleEdit = row => {
|
||||||
|
const { id } = row
|
||||||
customerDialogRef.value.openDialog({
|
customerDialogRef.value.openDialog({
|
||||||
title: '编辑客户',
|
title: '编辑客户',
|
||||||
width: 800,
|
width: 800,
|
||||||
data: { ...row }
|
data: {
|
||||||
|
id
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -3,6 +3,9 @@
|
||||||
<el-tabs v-model="activeTab">
|
<el-tabs v-model="activeTab">
|
||||||
<el-tab-pane label="成交用户" name="complete">
|
<el-tab-pane label="成交用户" name="complete">
|
||||||
<ProTable ref="proTableRef" :columns="columns" :tableData="tableData" :loading="loading" :maxHeight="530">
|
<ProTable ref="proTableRef" :columns="columns" :tableData="tableData" :loading="loading" :maxHeight="530">
|
||||||
|
<template #listSource="{ row }">
|
||||||
|
{{ ClueSourceMap[row.listSource] }}
|
||||||
|
</template>
|
||||||
<template #operation="{ row }">
|
<template #operation="{ row }">
|
||||||
<slot name="operation" :row="row" />
|
<slot name="operation" :row="row" />
|
||||||
</template>
|
</template>
|
||||||
|
@ -13,6 +16,8 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import { ClueSourceMap } from '@/enums'
|
||||||
|
|
||||||
defineProps({
|
defineProps({
|
||||||
loading: {
|
loading: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
|
@ -27,18 +32,18 @@ defineProps({
|
||||||
const activeTab = ref('complete')
|
const activeTab = ref('complete')
|
||||||
const proTableRef = ref()
|
const proTableRef = ref()
|
||||||
const columns = reactive([
|
const columns = reactive([
|
||||||
{ prop: 'accountName', label: '学生名字', width: 180 },
|
{ prop: 'studentName', label: '学生名字', width: 180 },
|
||||||
{ prop: 'sex', label: '性别', width: 180 },
|
{ prop: 'sex', label: '性别', width: 180 },
|
||||||
{ prop: 'mobile', label: '身份证号码', width: 180 },
|
{ prop: 'idCard', label: '身份证号码', width: 180 },
|
||||||
{ prop: 'mobile', label: '报读专业', width: 180 },
|
{ prop: 'major', label: '报读专业', width: 180 },
|
||||||
{ prop: 'organization', label: '毕业院校', width: 180 },
|
{ prop: 'graduationSchool', label: '毕业院校', width: 180 },
|
||||||
{ prop: 'position', label: '家庭地址', width: 180 },
|
{ prop: 'homeAddress', label: '家庭地址', width: 180 },
|
||||||
{ prop: 'position', label: '家长姓名', width: 180 },
|
{ prop: 'parentName', label: '家长姓名', width: 180 },
|
||||||
{ prop: 'position', label: '家长电话', width: 180 },
|
{ prop: 'parentPhone', label: '家长电话', width: 180 },
|
||||||
{ prop: 'accountStatus', label: '负责电销老师', width: 180 },
|
{ prop: 'telemarketingTeacherName', label: '负责电销老师', width: 180 },
|
||||||
{ prop: 'accountStatus', label: '负责招生老师', width: 180 },
|
{ prop: 'recruitTeacherName', label: '负责招生老师', width: 180 },
|
||||||
{ prop: 'accountStatus', label: '数据来源', width: 180 },
|
{ prop: 'listSource', label: '数据来源', width: 180 },
|
||||||
{ prop: 'accountStatus', label: '更新时间', width: 180 },
|
{ prop: 'updateTime', label: '更新时间', width: 180 },
|
||||||
{ prop: 'operation', label: '操作', fixed: 'right', width: 250 }
|
{ prop: 'operation', label: '操作', fixed: 'right', width: 250 }
|
||||||
])
|
])
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<el-card shadow="never" class="!border-none">
|
<el-card shadow="never" class="!border-none">
|
||||||
<el-form ref="formRef" class="mb-[-16px]" :model="modelValue" :inline="true">
|
<el-form ref="formRef" class="mb-[-16px]" :model="modelValue" :inline="true">
|
||||||
<el-form-item label="学生名字">
|
<el-form-item label="学生名字">
|
||||||
<el-input class="w-[280px]" placeholder="请输入" v-model="modelValue.name" clearable @keyup.enter="$emit('resetPage')" />
|
<el-input class="w-[280px]" placeholder="请输入" v-model="modelValue.studentName" clearable @keyup.enter="$emit('resetPage')" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-button type="primary" @click="$emit('resetPage')">查询</el-button>
|
<el-button type="primary" @click="$emit('resetPage')">查询</el-button>
|
||||||
|
@ -17,7 +17,7 @@ defineProps({
|
||||||
modelValue: {
|
modelValue: {
|
||||||
type: Object,
|
type: Object,
|
||||||
default: () => ({
|
default: () => ({
|
||||||
name: ''
|
studentName: ''
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,107 +1,14 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="workbench">
|
<div class="workbench">
|
||||||
<div class="lg:flex">
|
<data-overview />
|
||||||
<el-card
|
<div class="mb-4 function">2</div>
|
||||||
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">
|
<div class="lg:flex">
|
||||||
<el-card class="flex-1 !border-none md:mr-4 mb-4" shadow="never">
|
<el-card class="flex-1 !border-none md:mr-4 mb-4" shadow="never">
|
||||||
<template #header>
|
<template #header>
|
||||||
<span>销售额趋势图(近15天)</span>
|
<span>销售额趋势图(近15天)</span>
|
||||||
</template>
|
</template>
|
||||||
<div>
|
<div>
|
||||||
<v-charts
|
<v-charts style="height: 350px" :option="workbenchData.businessOption" :autoresize="true" />
|
||||||
style="height: 350px"
|
|
||||||
:option="workbenchData.businessOption"
|
|
||||||
:autoresize="true"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</el-card>
|
</el-card>
|
||||||
|
|
||||||
|
@ -110,11 +17,7 @@
|
||||||
<span>用户访问量(近15天)</span>
|
<span>用户访问量(近15天)</span>
|
||||||
</template>
|
</template>
|
||||||
<div>
|
<div>
|
||||||
<v-charts
|
<v-charts style="height: 350px" :option="workbenchData.visitorOption" :autoresize="true" />
|
||||||
style="height: 350px"
|
|
||||||
:option="workbenchData.visitorOption"
|
|
||||||
:autoresize="true"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</el-card>
|
</el-card>
|
||||||
</div>
|
</div>
|
||||||
|
@ -122,68 +25,10 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import goods_lists from './images/goods_lists.png'
|
import dataOverview from './components/data-overview.vue'
|
||||||
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'
|
import vCharts from 'vue-echarts'
|
||||||
// 表单数据
|
// 表单数据
|
||||||
const workbenchData: any = reactive({
|
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: {
|
businessOption: {
|
||||||
xAxis: {
|
xAxis: {
|
||||||
type: 'category',
|
type: 'category',
|
||||||
|
@ -236,20 +81,7 @@ const workbenchData: any = reactive({
|
||||||
})
|
})
|
||||||
|
|
||||||
// 获取工作台主页数据
|
// 获取工作台主页数据
|
||||||
const getData = async () => {
|
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(() => {
|
onMounted(() => {
|
||||||
getData()
|
getData()
|
||||||
|
|
Loading…
Reference in New Issue