提交 df2c6b5d authored 作者: matian's avatar matian

各模块开发

上级 8ccb4680
......@@ -29,3 +29,8 @@ export function uploadFile(data: Record<string, any>) {
})
.then(() => data)
}
// 获取个人信息
// 获取用户信息
export function getUserInfo() {
return httpRequest.get('/api/users/v1/index/index/info')
}
......@@ -152,7 +152,7 @@ defineExpose({ refetch, tableRef })
>
<el-option
:label="option[item.labelKey] || option.label"
:value="option[item.valueKey] || option.value"
:value="option[item.valueKey] || option.value || parseInt(option[item.valueKey])"
v-for="(option, index) in item.options"
:key="index"
/>
......
import httpRequest from '@/utils/axios'
// 获取搜索条件
export function getConditionList(params: { channel: boolean }) {
return httpRequest.get('/api/users/v1/index/index/condition', { params })
}
export function getChannelList(params: {
created_time_start?: string
created_time_end?: string
title?: string
channel_id?: string
tags?: string
company_short_name?: string
}) {
return httpRequest.get('/api/users/v1/channel/index/index', { params })
}
// 获取详情
export function getChannelDetail(params: { id: string }) {
return httpRequest.get('/api/users/v1/channel/index/view', { params })
}
<script setup lang="ts">
import { getConditionList, getChannelList } from '../api'
const router = useRouter()
const tagsList = ref([])
getConditionList({ channel: true }).then(res => {
tagsList.value = res.data.channel.tags.reduce((t: any, cur: any) => {
t.push({ id: res.data.channel.tags.indexOf(cur), name: cur })
return t
}, [])
console.log(tagsList.value)
})
const shortcuts = [
{
text: '今日',
......@@ -12,10 +23,10 @@ const shortcuts = [
{
text: '昨日',
value: () => {
const end = new Date()
// const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24)
return [start.setHours(0, 0, 0, 0), end.setHours(23, 59, 59, 999)]
return [start.setHours(0, 0, 0, 0), start.setHours(23, 59, 59, 999)]
}
},
{
......@@ -95,57 +106,72 @@ const shortcuts = [
}
]
// 列表配置
const listOptions = {
remote: {
// httpRequest: getExperimentList,
params: { timeRange: '', project_name: '', origin: '', name: '', email: '', mobile: '' }
},
filters: [
{
type: 'input',
slots: 'createTime',
prop: 'createTime'
const listOptions = $computed(() => {
return {
remote: {
beforeRequest(params: any) {
params.created_time_start = params.createTime[0]
params.created_time_end = params.createTime[1]
},
httpRequest: getChannelList,
params: {
createTime: [],
created_time_start: '',
created_time_end: '',
title: '',
channel_id: '',
tags: '',
company_short_name: ''
}
},
filters: [
{
slots: 'createTime',
prop: 'createTime'
},
{
type: 'select',
prop: 'project_name',
placeholder: '渠道名称'
},
{
type: 'input',
prop: 'title',
placeholder: '渠道名称'
},
{
type: 'input',
prop: 'origin',
placeholder: '渠道编号'
},
{
type: 'select',
prop: 'email',
placeholder: '渠道标签'
},
{
type: 'input',
prop: 'channel_id',
placeholder: '渠道编号'
},
{
type: 'select',
prop: 'tags',
placeholder: '渠道标签',
options: tagsList.value,
labelKey: 'name',
valueKey: 'id'
},
// 与所在项目进行联动
{
type: 'input',
prop: 'email',
placeholder: '公司字号'
}
],
columns: [
{ label: '渠道编号', prop: 'name' },
{ label: '渠道名称', prop: 'mobile' },
{ label: '公司字号', prop: 'email' },
{ label: '渠道标签', prop: 'project_name' },
{ label: '渠道质量', prop: 'origin' },
{ label: '归属人', prop: 'origin' },
{ label: '渠道类型', prop: 'type' },
{ label: '状态', prop: 'status' },
{ label: '创建时间', prop: 'created_time' },
{ label: '更新时间', prop: 'updated_time' },
{ label: '操作', slots: 'table-x', width: 100 }
],
data: [{ name: 1 }, { name: 2 }]
}
// 与所在项目进行联动
{
type: 'input',
prop: 'company_short_name',
placeholder: '公司字号'
}
],
columns: [
{ label: '渠道编号', prop: 'channel_id' },
{ label: '渠道名称', prop: 'title' },
{ label: '公司字号', prop: 'company_short_name' },
{ label: '渠道标签', prop: 'tags' },
{ label: '渠道质量', prop: 'channel_quality' },
{ label: '归属人', prop: 'channel_owner_user_id_name' },
{ label: '渠道类型', prop: 'channel_type_name' },
{ label: '状态', prop: 'channel_status_name' },
{ label: '创建时间', prop: 'created_time' },
{ label: '更新时间', prop: 'updated_time' },
{ label: '操作', slots: 'table-x', width: 100 }
]
}
})
</script>
<template>
<AppCard title="渠道信息">
......@@ -162,9 +188,9 @@ const listOptions = {
</template>
<template #table-x="{ row }">
<el-button type="primary" link>
<router-link :to="`/channel/bp/detail/${row.id}`" target="_blank">查看</router-link>
</el-button>
<router-link :to="`/channel/bp/detail/?id=${row.id}`" target="_blank">
<el-link type="primary" plain>查看</el-link>
</router-link>
</template>
</AppList>
</AppCard>
......
<script setup lang="ts">
import { getChannelDetail } from '../api'
const route = useRoute()
const props = defineProps<Props>()
interface Props {
id: string
}
defineProps<Props>()
// function fetchInfo() {}
// onMounted(() => fetchInfo)
const channelInfo: any = ref({})
getChannelDetail({ id: route.query.id || props.id }).then(res => {
channelInfo.value = res.data
})
// 列表配置
const listOptions = {
columns: [
{ label: '#', prop: 'id' },
{ label: '项目', prop: 'name' },
{ label: '分成规则', prop: 'gender' },
{ label: '分成比例', prop: 'phone' },
{ label: '学员上限', prop: 'work' },
{ label: '有效期', prop: 'work' },
{ label: '跟进人', prop: 'work' },
{ label: '关联日期', prop: 'work' }
],
data: [{ id: 1 }, { id: 2 }]
}
const listOptions1 = {
columns: [
{ label: '#', prop: 'id' },
{ label: '用户ID', prop: 'name' },
{ label: '用户名', prop: 'gender' },
{ label: 'Email', prop: 'phone' },
{ label: '手机', prop: 'work' },
{ label: '角色', prop: 'sound' },
{ label: '加入日期', prop: 'sound' }
],
data: [{ id: 1 }, { id: 2 }]
}
const listOptions = $computed(() => {
return {
columns: [
{ label: '#', type: 'index' },
{ label: '项目', prop: 'project_id_name' },
{ label: '分成规则', prop: 'division_rule_name' },
{ label: '分成比例', prop: 'division_proportion_name' },
{ label: '学员上限', prop: 'unpaid_list_limit' },
{ label: '有效期', prop: 'expire_range' },
{ label: '跟进人', prop: 'follower_user_id_name' },
{ label: '关联日期', prop: 'created_time' }
],
data: channelInfo.value.contracts
}
})
const listOptions1 = $computed(() => {
return {
columns: [
{ label: '#', prop: 'id' },
{ label: '用户ID', prop: 'user_id' },
{ label: '用户名', prop: 'user_id_name' },
{ label: 'Email', prop: 'user_id_email' },
{ label: '手机', prop: 'user_id_mobile' },
{ label: '角色', prop: 'role_name' },
{ label: '加入日期', prop: 'created_time' }
],
data: channelInfo.value.members
}
})
</script>
<template>
<AppCard title="基本信息">
<el-descriptions :column="4">
<el-descriptions-item label="渠道编号">123123</el-descriptions-item>
<el-descriptions-item label="渠道名称">哈哈哈</el-descriptions-item>
<el-descriptions-item label="状态">技术部</el-descriptions-item>
<el-descriptions-item label="渠道类型">-</el-descriptions-item>
<el-descriptions-item label="联络人">2</el-descriptions-item>
<el-descriptions-item label="联络微信">高职</el-descriptions-item>
<el-descriptions-item label="联络电话">-</el-descriptions-item>
<el-descriptions-item label="联络邮箱">2020-10-10</el-descriptions-item>
<el-descriptions-item label="开户名">郝屋撩</el-descriptions-item>
<el-descriptions-item label="开户行">2020-10-10</el-descriptions-item>
<el-descriptions-item label="银行账户">-</el-descriptions-item>
<el-descriptions-item label="企业税号">-</el-descriptions-item>
<el-descriptions-item label="企业税率">-</el-descriptions-item>
<el-descriptions-item label="注册地址">-</el-descriptions-item>
<el-descriptions-item label="创建时间">-</el-descriptions-item>
<el-descriptions-item label="更新时间">-</el-descriptions-item>
<el-descriptions-item label="法人身份证正面">-</el-descriptions-item>
<el-descriptions-item label="法人身份证背面">-</el-descriptions-item>
<el-descriptions-item label="营业执照">-</el-descriptions-item>
<el-descriptions-item label="渠道摘要">-</el-descriptions-item>
<el-descriptions-item label="渠道编号">{{ channelInfo.channel_id || '-' }}</el-descriptions-item>
<el-descriptions-item label="渠道名称">{{ channelInfo.title || '-' }}</el-descriptions-item>
<el-descriptions-item label="状态">{{ channelInfo.channel_status_name || '-' }}</el-descriptions-item>
<el-descriptions-item label="渠道类型">{{ channelInfo.channel_id || '-' }}</el-descriptions-item>
<el-descriptions-item label="联络人">{{ channelInfo.partner?.contact_person || '-' }}</el-descriptions-item>
<el-descriptions-item label="联络微信">{{ channelInfo.partner?.contact_wechat || '-' }}</el-descriptions-item>
<el-descriptions-item label="联络电话">{{ channelInfo.partner?.contact_phone || '-' }}</el-descriptions-item>
<el-descriptions-item label="联络邮箱">{{ channelInfo.partner?.contact_email || '-' }}</el-descriptions-item>
<el-descriptions-item label="开户名">{{ channelInfo.partner?.bank_account_name || '-' }}</el-descriptions-item>
<el-descriptions-item label="开户行">{{ channelInfo.partner?.opening_bank || '-' }}</el-descriptions-item>
<el-descriptions-item label="银行账户">{{
channelInfo.partner?.bank_account_number || '-'
}}</el-descriptions-item>
<el-descriptions-item label="企业税号">{{ channelInfo.partner?.tax_number || '-' }}</el-descriptions-item>
<el-descriptions-item label="企业税率">{{ channelInfo.partner?.tax_rate || '-' }}</el-descriptions-item>
<el-descriptions-item label="注册地址">{{
channelInfo.partner?.company_registered_address || '-'
}}</el-descriptions-item>
<el-descriptions-item label="创建时间">{{ channelInfo.created_time || '-' }}</el-descriptions-item>
<el-descriptions-item label="更新时间">{{ channelInfo.updated_time || '-' }}</el-descriptions-item>
<el-descriptions-item label="法人身份证正面">
<img
v-if="channelInfo.partner?.company_legal_representative_id_card_front !== null"
:src="channelInfo.partner?.company_legal_representative_id_card_front"
/>
<div v-else>-</div>
</el-descriptions-item>
<el-descriptions-item label="法人身份证背面">
<img
v-if="channelInfo.partner?.company_legal_representative_id_card_back !== null"
:src="channelInfo.partner?.company_legal_representative_id_card_back"
/>
<div v-else>-</div>
</el-descriptions-item>
<el-descriptions-item label="营业执照">
<img v-if="channelInfo.partner?.business_license !== null" :src="channelInfo.partner?.business_license" />
<div v-else>-</div>
</el-descriptions-item>
<el-descriptions-item label="渠道摘要">{{ channelInfo.summary || '-' }}</el-descriptions-item>
</el-descriptions>
</AppCard>
<AppCard title="项目信息">
......@@ -68,10 +94,10 @@ const listOptions1 = {
</AppCard>
<AppCard title="渠道控制信息">
<el-descriptions :column="2">
<el-descriptions-item label="渠道质量">123123</el-descriptions-item>
<el-descriptions-item label="分配状态">哈哈哈</el-descriptions-item>
<el-descriptions-item label="回抽状态">技术部</el-descriptions-item>
<el-descriptions-item label="咨询框状态">-</el-descriptions-item>
<el-descriptions-item label="渠道质量">{{ channelInfo.channel_quality || '-' }}</el-descriptions-item>
<el-descriptions-item label="分配状态">{{ channelInfo.distribution_status || '-' }}</el-descriptions-item>
<el-descriptions-item label="回抽状态">{{ channelInfo.case_withdraw_status || '-' }}</el-descriptions-item>
<el-descriptions-item label="咨询框状态">{{ channelInfo.service_dialog_status || '-' }}</el-descriptions-item>
</el-descriptions>
</AppCard>
</template>
import httpRequest from '@/utils/axios'
// 获取课程列表
export function getCourseList() {
return httpRequest.get('/api/lab/v1/student/course/all')
export function getAllDataList() {
return httpRequest.get('/api/users/v1/index/index/index')
}
<script setup lang="ts">
import * as echarts from 'echarts'
const props = defineProps({
pieList: {
type: Array
}
})
console.log(props.pieList)
const echartsRef = ref()
onMounted(() => {
init()
})
const init = () => {
const myChart = echarts.init(echartsRef.value)
const option = {
title: {
text: '各系统数据比例分析',
text: '各系统数据\n' + '比例分析',
x: 'center',
textStyle: {
color: '#dbbb95',
fontSize: 16
},
top: '45%'
top: '40%'
},
legend: [
{
......@@ -32,7 +42,7 @@ onMounted(() => {
orient: 'vertical',
left: '60%',
data: [
{ value: 484, name: '尘客户' },
{ value: 484, name: '尘客户' },
{ value: 300, name: '企微客户' },
{ value: 300, name: '小鹅通客户' }
] //水平排列。(vertical为垂直排列}}
......@@ -43,7 +53,7 @@ onMounted(() => {
bottom: '10%',
type: 'pie',
avoidLabelOverlap: true, //避免标签重叠
radius: ['55%', '90%'],
radius: ['45%', '60%'],
color: ['#DA7559', '#C33C62', '#4886B4', '#E3C475', '#E09966', '#4E9D8C'],
itemStyle: {
borderRadius: 1,
......@@ -51,37 +61,22 @@ onMounted(() => {
borderWidth: 2
},
label: {
show: true,
position: 'inner', //将百分比显示在饼图内部
color: '#fff',
fontSize: '12',
formatter: '{d}%',
fontWeight: 'bold'
formatter: '{d}%'
},
labelLine: {
show: true,
length: 48,
length2: 220,
lineStyle: {
color: '#adadad',
width: 2
normal: {
length: 15, // 指示线长度
lineStyle: {
color: '#595959' // 指示线颜色
}
}
},
data: [
{ value: 1048, name: 'ZWS客户' },
{ value: 735, name: '院校客户' },
{ value: 580, name: '渠道客户' },
{ value: 484, name: '尘封客户' },
{ value: 300, name: '企微客户' },
{ value: 300, name: '小鹅通客户' }
]
data: props.pieList
}
]
}
option && myChart.setOption(option)
})
myChart.setOption(option)
}
</script>
<template>
......@@ -96,11 +91,3 @@ onMounted(() => {
></div>
</AppCard>
</template>
<style>
/* #main {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
} */
</style>
<script setup lang="ts">
const list = [
{
title: 'ZWS客户',
unit: 2,
num: '1111',
txt: '人',
icon: 'https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_user/zws.png'
},
{
title: '院校客户',
unit: 2,
num: '1111',
txt: '人',
icon: 'https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_user/school_customer.png'
},
{
title: '渠道客户',
unit: 2,
num: '1111',
txt: '人',
icon: 'https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_user/channel.png'
},
{
title: '尘峰客户',
unit: 2,
num: '1111',
txt: '人',
icon: 'https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_user/peak.png'
},
{
title: '企微客户',
unit: 2,
num: '1111',
txt: '人',
icon: 'https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_user/wechat.png'
},
{
title: '小鹅通客户',
unit: 2,
num: '1111',
txt: '人',
icon: 'https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_user/goose.png'
const props = defineProps({
totalList: {
type: Array
}
]
})
</script>
<template>
<div class="statistics-list">
<div class="item" v-for="(item, index) in list" :key="index">
<div class="item" v-for="(item, index) in props.totalList" :key="index">
<div class="item_desc">
<div class="tit">{{ item.title }}</div>
<div class="tit">{{ item.name }}</div>
<div class="text">
<span class="text_num">{{ item.num }}</span>
<span class="text_num">{{ item.value }}</span>
<span class="text_txt">{{ item.txt }}</span>
</div>
</div>
......@@ -85,6 +46,7 @@ const list = [
color: #666666;
}
.text {
white-space: nowrap;
.text_num {
font-size: 26px;
}
......
......@@ -2,12 +2,16 @@
import * as echarts from 'echarts'
const echartsRef = ref()
const props = defineProps({
lineList: Array
})
onMounted(() => {
const myChart = echarts.init(echartsRef.value)
const option = {
xAxis: {
type: 'category',
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
data: props.lineList?.map((item: any) => item.date)
},
tooltip: {
trigger: 'axis',
......@@ -16,6 +20,34 @@ onMounted(() => {
label: {
backgroundColor: '#aa1941'
}
},
formatter: function (params: any) {
let str = ''
//首先要看看params是怎样的数据结构,里面有什么内容;
//对params进行操作
params.forEach((item: any) => {
str +=
'<div style="margin-bottom:5px">' +
item.seriesName +
':' +
`<span style="color:${item.color}">` +
item.value +
'</span>' +
'人' +
'</br>' +
'</div>'
})
return (
'<div style="font-weight:bold">' +
params[0].name +
'</div>' +
'<div style="margin-bottom:10px">' +
`新增<span style="color:#c33c62">${params
.map((item: any) => item.value)
.reduce((a: any, b: any) => a + b)}</span>条数据` +
'</div>' +
str
)
}
},
yAxis: {
......@@ -23,12 +55,68 @@ onMounted(() => {
},
series: [
{
data: [150, 230, 224, 218, 135, 147, 260],
name: 'zws',
data: props.lineList?.map((item: any) => item.zws),
type: 'line',
color: '#da7559',
symbol: 'none',
areaStyle: {
color: '#da7559',
opacity: 0.04
}
},
{
name: '渠道',
data: props.lineList?.map((item: any) => item.channel),
type: 'line',
color: '#4886b4',
symbol: 'none',
areaStyle: {
color: '#4886b4',
opacity: 0.04
}
},
{
name: '尘峰',
data: props.lineList?.map((item: any) => item.dustess),
type: 'line',
color: '#e3c475',
symbol: 'none',
areaStyle: {
color: '#e3c475',
opacity: 0.04
}
},
{
name: '院校',
data: props.lineList?.map((item: any) => item.school),
type: 'line',
color: '#c33c62',
symbol: 'none',
areaStyle: {
color: '#c33c62',
opacity: 0.04
}
},
{
name: '企微',
data: props.lineList?.map((item: any) => item.wechat),
type: 'line',
color: '#e09966',
symbol: 'none',
areaStyle: {
color: '#e09966',
opacity: 0.04
}
},
{
name: '小鹅通',
data: props.lineList?.map((item: any) => item.xiaoe),
type: 'line',
color: '#C33C62',
color: '#4e9d8c',
symbol: 'none',
areaStyle: {
color: '#C33C62',
color: '#4e9d8c',
opacity: 0.04
}
}
......
......@@ -2,15 +2,78 @@
import Statistics from '../components/Statistics.vue'
import UserData from '../components/UserData.vue'
import Pie from '../components/Pie.vue'
import { getAllDataList } from '../api'
const flag = ref(false)
const totalList: any = ref([])
const pieList: any = ref([])
const lineList: any = ref([])
const list = [
{
name: 'ZWS客户',
tag: 'pie_zws',
value: '',
txt: '人',
icon: 'https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_user/zws.png'
},
{
name: '院校客户',
tag: 'pie_school',
value: '',
txt: '人',
icon: 'https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_user/school_customer.png'
},
{
name: '渠道客户',
tag: 'pie_channel',
value: '',
txt: '人',
icon: 'https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_user/channel.png'
},
{
name: '尘峰客户',
tag: 'pie_dustess',
value: '',
txt: '人',
icon: 'https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_user/peak.png'
},
{
name: '企微客户',
tag: 'pie_wechat',
value: '',
txt: '人',
icon: 'https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_user/wechat.png'
},
{
name: '小鹅通客户',
tag: 'pie_xiaoe',
value: '',
txt: '人',
icon: 'https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_user/goose.png'
}
]
getAllDataList().then((res: any) => {
lineList.value = res.data.line
totalList.value = list.map((item: any) => {
item.value = res.data.pie[item.tag]
return item
})
const newData:any = []
totalList.value.map((item: any) => {
newData.push({ name: item.name, value: item.value })
})
pieList.value = [...newData]
flag.value = true
})
</script>
<template>
<Statistics />
<Statistics :totalList="totalList" />
<div class="main_bottom" style="">
<div class="bottom_left">
<UserData />
<UserData v-if="flag" :lineList="lineList" />
</div>
<div class="bottom_right">
<Pie v-if="flag" :pieList="pieList" />
</div>
<div class="bottom_right"><Pie /></div>
</div>
</template>
<style lang="scss" scoped>
......
import httpRequest from '@/utils/axios'
// 获取联系人列表
export function getContactList(params: {
name?: string
phone?: string
type?: string
school_name?: string
college?: string
['per-page']?: string
page: string
}) {
return httpRequest.get('/api/users/v1/school/user/index', { params })
}
// 获取联系人详情
export function getContactDetail(params: { id: string }) {
return httpRequest.get('/api/users/v1/school/user/view', { params })
}
export function importContact(data: { file: any }) {
return httpRequest.post('/api/users/v1/school/user/import', data, {
headers: { 'Content-Type': 'multipart/form-data' }
})
}
<script lang="ts" setup>
import { ElMessage } from 'element-plus'
import { UploadFilled } from '@element-plus/icons-vue'
import { splitStrLast } from '@/utils/util'
import { importContact } from '../api'
const emit = defineEmits<Emits>()
const upload = ref()
const fileList = ref([]) // 文件列表
defineProps({
isShowImport: {
type: Boolean
}
})
interface Emits {
(e: 'update:isShowImport', isShowImportDialog: boolean): void
(e: 'create'): void
}
// 取消
const handleCancel = () => {
emit('update:isShowImport', false)
}
const beforeUpload = (file: any) => {
const suffix = splitStrLast(file.name, '.')
if (!['xlsx', 'xls'].includes(suffix)) {
ElMessage.warning('只能上传excel文件')
return false
} else {
return true
}
}
const fetchFileUpload = (option: any) => {
return new Promise(() => {
importContact({ file: option.file }).then(() => {
ElMessage.success('导入数据成功')
emit('update:isShowImport', false)
emit('create')
})
})
}
const handleSubmitUpload = () => {
upload.value.submit()
}
</script>
<template>
<el-dialog :model-value="isShowImport" draggable :before-close="handleCancel" title="批量导入联系人" width="30%">
<el-upload
style="text-align: center"
class="file-import"
ref="upload"
action="#"
accept=".xls,.xlsx"
drag
:auto-upload="false"
:file-list="fileList"
:limit="1"
:before-upload="beforeUpload"
:http-request="fetchFileUpload"
>
<el-icon class="el-icon--upload"><upload-filled /></el-icon>
<div class="el-upload__text">将文件拖至此处,点击上传</div>
</el-upload>
<div style="margin-bottom: 10px; text-align: center">
导入模板下载:<a
href="https://webapp-pub.ezijing.com/center_user/%E8%81%94%E7%B3%BB%E4%BA%BA.xlsx"
download="联系人模板"
><el-link type="primary">联系人模板.xlsx</el-link></a
>
</div>
<template #footer>
<span>
<el-button @click="handleCancel">取消</el-button>
<el-button type="primary" @click="handleSubmitUpload">确认</el-button>
</span>
</template>
</el-dialog>
</template>
<script setup lang="ts">
import BatchImport from '../components/BatchImport.vue'
import { getContactList } from '../api'
const appList = ref()
const isShowImport = ref(false)
// 列表配置
const listOptions = {
// remote: {
// httpRequest: getExperimentList,
// params: { name: '' }
// },
filters: [
{ type: 'input', prop: 'id', placeholder: '联系人姓名' },
{ type: 'input', prop: 'name', placeholder: '联系人手机号' },
{
type: 'select',
prop: 'nature',
placeholder: '联系人类型',
options: [
{
label: '院领导',
value: '0'
},
{
label: '院长',
value: '1'
}
]
const listOptions = $computed(() => {
return {
remote: {
httpRequest: getContactList,
params: { name: '', phone: '', type: '', school_name: '', college: '' }
},
{ type: 'input', prop: 'market', placeholder: '标题' },
{ type: 'input', prop: 'sale_before', placeholder: '大学/客户名称' },
{ type: 'input', prop: 'teach', placeholder: '所属学院' }
],
columns: [
{ label: '#', type: 'index' },
{ label: '标题', prop: 'id' },
{ label: '联系人姓名', prop: 'name' },
{ label: '联系人手机号', prop: 'nature' },
{ label: '所属学院', prop: 'department' },
{ label: '大学(客户名称)', prop: 'sale_step' },
{ label: '联系人类型', prop: ' master' },
{ label: '操作', slots: 'table-x', width: 100 }
],
data: [{ id: 1 }, { id: 2 }]
filters: [
{ type: 'input', prop: 'name', placeholder: '联系人姓名' },
{ type: 'input', prop: 'phone', placeholder: '联系人手机号' },
{
type: 'input',
prop: 'type',
placeholder: '联系人类型'
},
{ type: 'input', prop: 'school_name', placeholder: '客户名称(大学)' },
{ type: 'input', prop: 'college', placeholder: '所属学院' }
],
columns: [
{ label: '#', type: 'index' },
{ label: '联系人姓名', prop: 'name' },
{ label: '联系人手机号', prop: 'phone' },
{ label: '所属学院', prop: 'college' },
{ label: '客户名称(大学)', prop: 'school' },
{ label: '联系人类型', prop: ' type' },
{ label: '操作', slots: 'table-x', width: 100 }
]
}
})
const handleBatchImport = () => {
isShowImport.value = true
}
const handleRefetch = () => {
appList.value.refetch()
}
</script>
<template>
<AppCard title="联系人信息">
<AppList v-bind="listOptions" ref="appList">
<el-button type="primary" style="margin-bottom: 20px" @click="handleBatchImport">批量导入</el-button>
<template #table-x="{ row }">
<el-button type="primary" link>
<router-link :to="`/school/contact/detail/${row.id}`" target="_blank">查看</router-link>
......@@ -50,4 +53,5 @@ const listOptions = {
</template>
</AppList>
</AppCard>
<BatchImport v-model:isShowImport="isShowImport" v-if="isShowImport" @create="handleRefetch" />
</template>
<script setup lang="ts">
import { getContactDetail } from '../api'
const route = useRoute()
interface Props {
id: string
}
defineProps<Props>()
const props = defineProps<Props>()
const contactInfo: any = ref({})
const params: any = { id: route.query.id || props.id }
// function fetchInfo() {}
// onMounted(() => fetchInfo)
const activeName = ref('1')
// 列表配置
const listOptions = {
columns: [
{ label: '#', prop: 'id' },
{ label: '姓名', prop: 'name' },
{ label: '性别', prop: 'gender' },
{ label: '手机号', prop: 'phone' },
{ label: '职务', prop: 'work' },
{ label: '联系人类型', prop: 'sound' }
],
data: [{ id: 1 }, { id: 2 }]
}
getContactDetail(params).then(res => {
contactInfo.value = res.data
})
</script>
<template>
<AppCard title="联系人信息">
<el-descriptions :column="4">
<el-descriptions-item label="姓名">123123</el-descriptions-item>
<el-descriptions-item label="联系人手机号">哈哈哈</el-descriptions-item>
<el-descriptions-item label="所属学院">技术部</el-descriptions-item>
<el-descriptions-item label="客户(所属大学)">-</el-descriptions-item>
<el-descriptions-item label="负责人">2</el-descriptions-item>
<el-descriptions-item label="联系人类型">高职</el-descriptions-item>
<el-descriptions-item label="所属部门">-</el-descriptions-item>
<el-descriptions-item label="微信号">2020-10-10</el-descriptions-item>
<el-descriptions-item label="邮箱">郝屋撩</el-descriptions-item>
<el-descriptions-item label="QQ">2020-10-10</el-descriptions-item>
<el-descriptions-item label="其他电话">-</el-descriptions-item>
<el-descriptions-item label="重大事件">-</el-descriptions-item>
<el-descriptions-item label="生日">-</el-descriptions-item>
<el-descriptions-item label="在任时间">-</el-descriptions-item>
<el-descriptions-item label="兴趣爱好">-</el-descriptions-item>
<el-descriptions-item label="重要特征">-</el-descriptions-item>
<el-descriptions-item label="教育/背景">-</el-descriptions-item>
<el-descriptions-item label="个人诉求">-</el-descriptions-item>
<el-descriptions-item label="收入情况">-</el-descriptions-item>
<el-descriptions-item label="子女情况">-</el-descriptions-item>
<el-descriptions-item label="姓名">{{ contactInfo.name || '-' }}</el-descriptions-item>
<el-descriptions-item label="手机号">{{ contactInfo.phone || '-' }}</el-descriptions-item>
<el-descriptions-item label="客户名称">{{ contactInfo.school_name || '-' }}</el-descriptions-item>
<el-descriptions-item label="性别">{{ contactInfo.gender || '-' }}</el-descriptions-item>
<el-descriptions-item label="联系人类型">{{ contactInfo.type || '-' }}</el-descriptions-item>
<el-descriptions-item label="职务">{{ contactInfo.phopostne || '-' }}</el-descriptions-item>
<el-descriptions-item label="所属学院/系部/处室">{{ contactInfo.college || '-' }}</el-descriptions-item>
<el-descriptions-item label="所属学校">{{ contactInfo.school || '-' }}</el-descriptions-item>
<el-descriptions-item label="联系人编号">{{ contactInfo.number || '-' }}</el-descriptions-item>
<el-descriptions-item label="负责人">{{ contactInfo.leader || '-' }}</el-descriptions-item>
<el-descriptions-item label="归属部门">{{ contactInfo.department || '-' }}</el-descriptions-item>
<el-descriptions-item label="协作人">{{ contactInfo.collaborator || '-' }}</el-descriptions-item>
<el-descriptions-item label="微信号">{{ contactInfo.wechat || '-' }}</el-descriptions-item>
<el-descriptions-item label="QQ">{{ contactInfo.qq || '-' }}</el-descriptions-item>
<el-descriptions-item label="其他电话">{{ contactInfo.other_phone || '-' }}</el-descriptions-item>
<el-descriptions-item label="职称">{{ contactInfo.title || '-' }}</el-descriptions-item>
<el-descriptions-item label="生日">{{ contactInfo.birth || '-' }}</el-descriptions-item>
<el-descriptions-item label="在任时间">{{ contactInfo.time_in_office || '-' }}</el-descriptions-item>
<el-descriptions-item label="兴趣爱好">{{ contactInfo.hobby || '-' }}</el-descriptions-item>
<el-descriptions-item label="禁忌">{{ contactInfo.taboo || '-' }}</el-descriptions-item>
<el-descriptions-item label="教育">{{ contactInfo.education || '-' }}</el-descriptions-item>
<el-descriptions-item label="个人诉求">{{ contactInfo.appeal || '-' }}</el-descriptions-item>
<el-descriptions-item label="家庭收入">{{ contactInfo.income || '-' }}</el-descriptions-item>
<el-descriptions-item label="子女情况">{{ contactInfo.children || '-' }}</el-descriptions-item>
<el-descriptions-item label="重大事件">{{ contactInfo.major_events || '-' }}</el-descriptions-item>
<el-descriptions-item label="提交人">{{ contactInfo.submitter || '-' }}</el-descriptions-item>
<el-descriptions-item label="提交时间">{{ contactInfo.submit_time || '-' }}</el-descriptions-item>
<el-descriptions-item label="更新时间">{{ contactInfo.update_time || '-' }}</el-descriptions-item>
</el-descriptions>
</AppCard>
<AppCard>
<el-tabs v-model="activeName" class="demo-tabs">
<el-tab-pane :label="`项目1/商机信息1`" name="1"></el-tab-pane>
<el-tab-pane :label="`项目2/商机信息2`" name="2"></el-tab-pane>
<el-tab-pane :label="`项目3/商机信息3`" name="3"></el-tab-pane>
</el-tabs>
<div v-for="index in 3" :key="index" style="padding: 0 30px">
<el-descriptions :column="4" v-if="index === parseInt(activeName)">
<el-descriptions-item label="标题">标题{{ index }}</el-descriptions-item>
<el-descriptions-item label="项目名称">项目名称</el-descriptions-item>
<el-descriptions-item label="商机/编号">0041</el-descriptions-item>
<el-descriptions-item label="所属公海">-</el-descriptions-item>
<el-descriptions-item label="销售阶段">L3-洽谈</el-descriptions-item>
<el-descriptions-item label="所属分公司">-</el-descriptions-item>
<el-descriptions-item label="商机/类型">产业学院</el-descriptions-item>
<el-descriptions-item label="地址">北京</el-descriptions-item>
<el-descriptions-item label="市场">宁老师</el-descriptions-item>
<el-descriptions-item label="售前">-</el-descriptions-item>
<el-descriptions-item label="教研">-</el-descriptions-item>
<el-descriptions-item label="领取时间">2022-01-01</el-descriptions-item>
</el-descriptions>
</div>
</AppCard>
</template>
import httpRequest from '@/utils/axios'
// 获取课程列表
export function getProjectList(params: {
name?: string
number?: string
type?: string
stage?: string
market?: string
pre_sale?: string
teaching?: string
['per-page']?: string
page?: string
}) {
return httpRequest.get('/api/users/v1/school/project/index', { params })
}
// 获取学校详情
export function getProjectDetail(params: { id: string }) {
return httpRequest.get('/api/users/v1/school/project/view', { params })
}
export function importProject(data: { file: any }) {
return httpRequest.post('/api/users/v1/school/project/import', data, {
headers: { 'Content-Type': 'multipart/form-data' }
})
}
<script lang="ts" setup>
import { ElMessage } from 'element-plus'
import { UploadFilled } from '@element-plus/icons-vue'
import { splitStrLast } from '@/utils/util'
import { importProject } from '../api'
const emit = defineEmits<Emits>()
const upload = ref()
const fileList = ref([]) // 文件列表
defineProps({
isShowImport: {
type: Boolean
}
})
interface Emits {
(e: 'update:isShowImport', isShowImportDialog: boolean): void
(e: 'create'): void
}
// 取消
const handleCancel = () => {
emit('update:isShowImport', false)
}
const beforeUpload = (file: any) => {
const suffix = splitStrLast(file.name, '.')
if (!['xlsx', 'xls'].includes(suffix)) {
ElMessage.warning('只能上传excel文件')
return false
} else {
return true
}
}
const fetchFileUpload = (option: any) => {
return new Promise(() => {
importProject({ file: option.file }).then(() => {
ElMessage.success('导入数据成功')
emit('update:isShowImport', false)
emit('create')
})
})
}
const handleSubmitUpload = () => {
upload.value.submit()
}
</script>
<template>
<el-dialog :model-value="isShowImport" draggable :before-close="handleCancel" title="批量导入项目" width="30%">
<el-upload
style="text-align: center"
class="file-import"
ref="upload"
action="#"
accept=".xls,.xlsx"
drag
:auto-upload="false"
:file-list="fileList"
:limit="1"
:before-upload="beforeUpload"
:http-request="fetchFileUpload"
>
<el-icon class="el-icon--upload"><upload-filled /></el-icon>
<div class="el-upload__text">将文件拖至此处,点击上传</div>
</el-upload>
<div style="margin-bottom: 10px; text-align: center">
导入模板下载:<a href="https://webapp-pub.ezijing.com/center_user/%E9%A1%B9%E7%9B%AE.xlsx" download="项目模板"
><el-link type="primary">项目模板.xlsx</el-link></a
>
</div>
<template #footer>
<span>
<el-button @click="handleCancel">取消</el-button>
<el-button type="primary" @click="handleSubmitUpload">确认</el-button>
</span>
</template>
</el-dialog>
</template>
<script setup lang="ts">
import { getProjectList } from '../api'
import BatchImport from '../components/BatchImport.vue'
const isShowImport = ref(false)
const appList = ref()
// 列表配置
const listOptions = {
// remote: {
// httpRequest: getExperimentList,
// params: { name: '' }
// },
filters: [
{ type: 'input', prop: 'id', placeholder: '标题' },
{ type: 'input', prop: 'name', placeholder: '商机/项目' },
{ type: 'input', prop: 'nature', placeholder: '商机/编号' },
{ type: 'select', prop: 'department', placeholder: '商机/类型' },
{ type: 'input', prop: 'market', placeholder: '市场' },
{ type: 'input', prop: 'sale_before', placeholder: '售前' },
{ type: 'input', prop: 'teach', placeholder: '教研' },
{ type: 'select', prop: 'sale_step', placeholder: '销售阶段' }
],
columns: [
{ label: '标题', prop: 'id' },
{ label: '商机/项目', prop: 'name' },
{ label: '商机/编号', prop: 'nature' },
{ label: '商机/类型', prop: 'department' },
{ label: '销售阶段', prop: 'sale_step' },
{ label: '市场', prop: ' master' },
{ label: '售前', prop: 'created_time' },
{ label: '教研', prop: 'created_time' },
{ label: '创建时间', prop: 'created_time' },
{ label: '更新时间', prop: 'updated_time' },
{ label: '操作', slots: 'table-x', width: 100 }
],
data: [{ id: 1 }, { id: 2 }]
const listOptions = $computed(() => {
return {
remote: {
httpRequest: getProjectList,
params: { name: '', number: '', type: '', stage: '', market: '', pre_sale: '', teaching: '' }
},
filters: [
{ type: 'input', prop: 'name', placeholder: '商机/项目' },
{ type: 'input', prop: 'number', placeholder: '商机/编号' },
{ type: 'input', prop: 'type', placeholder: '商机/类型' },
{ type: 'input', prop: 'stage', placeholder: '销售阶段' },
{ type: 'input', prop: 'market', placeholder: '市场' },
{ type: 'input', prop: 'pre_sale', placeholder: '售前' },
{ type: 'input', prop: 'teaching', placeholder: '教研' }
],
columns: [
{ label: '#', type: 'index' },
{ label: '商机/项目名称', prop: 'name' },
{ label: '商机/编号', prop: 'number' },
{ label: '商机/类型', prop: 'type' },
{ label: '销售阶段', prop: 'stage' },
{ label: '市场', prop: ' market' },
{ label: '售前', prop: 'pre_sale' },
{ label: '教研', prop: 'teaching' },
{ label: '创建时间', prop: 'create_time' },
{ label: '更新时间', prop: 'update_time' },
{ label: '操作', slots: 'table-x', width: 100 }
]
}
})
const handleBatchImport = () => {
isShowImport.value = true
}
const handleRefetch = () => {
appList.value.refetch()
}
</script>
<template>
<AppCard title="项目信息">
<AppList v-bind="listOptions" ref="appList">
<el-button type="primary" style="margin-bottom: 20px" @click="handleBatchImport">批量导入</el-button>
<template #table-x="{ row }">
<el-button type="primary" link>
<router-link :to="`/school/project/detail/${row.id}`" target="_blank">查看</router-link>
......@@ -41,4 +53,5 @@ const listOptions = {
</template>
</AppList>
</AppCard>
<BatchImport v-model:isShowImport="isShowImport" v-if="isShowImport" @create="handleRefetch" />
</template>
<script setup lang="ts">
import { getProjectDetail } from '../api'
const route = useRoute()
interface Props {
id: string
}
defineProps<Props>()
// function fetchInfo() {}
// onMounted(() => fetchInfo)
const activeName = ref('1')
// 列表配置
const listOptions = {
columns: [
{ label: '#', prop: 'id' },
{ label: '姓名', prop: 'name' },
{ label: '性别', prop: 'gender' },
{ label: '手机号', prop: 'phone' },
{ label: '职务', prop: 'work' },
{ label: '联系人类型', prop: 'sound' }
],
data: [{ id: 1 }, { id: 2 }]
}
const props = defineProps<Props>()
const projectInfo: any = ref({})
const params: any = { id: route.query.id || props.id }
getProjectDetail(params).then(res => {
projectInfo.value = res.data
})
</script>
<template>
<AppCard>
<el-tabs v-model="activeName" class="demo-tabs">
<el-tab-pane label="项目1" name="1"></el-tab-pane>
<el-tab-pane label="项目2" name="2"></el-tab-pane>
<el-tab-pane label="项目3" name="3"></el-tab-pane>
</el-tabs>
<div v-for="index in 3" :key="index" style="padding: 0 30px">
<el-descriptions :column="4" v-if="index === parseInt(activeName)">
<el-descriptions-item label="标题">标题{{ index }}</el-descriptions-item>
<el-descriptions-item label="商机/项目">0041</el-descriptions-item>
<el-descriptions-item label="商机/编号">0041</el-descriptions-item>
<el-descriptions-item label="所属公海">-</el-descriptions-item>
<el-descriptions-item label="销售阶段">L3-洽谈</el-descriptions-item>
<el-descriptions-item label="所属分公司">-</el-descriptions-item>
<el-descriptions-item label="商机/类型">产业学院</el-descriptions-item>
<el-descriptions-item label="地址">北京</el-descriptions-item>
<el-descriptions-item label="市场">宁老师</el-descriptions-item>
<el-descriptions-item label="售前">-</el-descriptions-item>
<el-descriptions-item label="教研">-</el-descriptions-item>
<el-descriptions-item label="创建时间">2022-01-01</el-descriptions-item>
</el-descriptions>
</div>
<div class="title" style="margin-top: 15px">决策人</div>
<AppList v-bind="listOptions" ref="appList" style="padding: 0 15px"></AppList>
</AppCard>
<AppCard title="申请信息">
<AppList v-bind="listOptions" ref="appList"></AppList>
<AppCard title="项目详情">
<el-descriptions :column="4">
<el-descriptions-item label="项目名称">{{ projectInfo.name || '-' }}</el-descriptions-item>
<el-descriptions-item label="商机/编号">{{ projectInfo.number || '-' }}</el-descriptions-item>
<el-descriptions-item label="商机/类型">{{ projectInfo.type || '-' }}</el-descriptions-item>
<el-descriptions-item label="销售阶段">{{ projectInfo.stage || '-' }}</el-descriptions-item>
<el-descriptions-item label="所属分公司">{{ projectInfo.company || '-' }}</el-descriptions-item>
<el-descriptions-item label="二级学院/系">{{ projectInfo.college || '-' }}</el-descriptions-item>
<el-descriptions-item label="专业">{{ projectInfo.major || '-' }}</el-descriptions-item>
<el-descriptions-item label="负责人">{{ projectInfo.leader || '-' }}</el-descriptions-item>
<el-descriptions-item label="市场">{{ projectInfo.market || '-' }}</el-descriptions-item>
<el-descriptions-item label="售前">{{ projectInfo.pre_sale || '-' }}</el-descriptions-item>
<el-descriptions-item label="教研">{{ projectInfo.teaching || '-' }}</el-descriptions-item>
<el-descriptions-item label="创建时间">{{ projectInfo.create_time || '-' }}</el-descriptions-item>
</el-descriptions>
</AppCard>
</template>
import httpRequest from '@/utils/axios'
// 获取课程列表
export function getCourseList() {
return httpRequest.get('/api/lab/v1/student/course/all')
export function getSchoolList(params: {
name?: string
number?: string
nature?: string
department?: string
leader?: string
from?: string
['per-page']?: string
page?: string
}) {
return httpRequest.get('/api/users/v1/school/school/index', { params })
}
// 获取学校详情
export function getSchoolDetail(params: { id: string }) {
return httpRequest.get('/api/users/v1/school/school/view', { params })
}
// 获取学校详情
export function importSchool(data: { file: any }) {
return httpRequest.post('/api/users/v1/school/school/import', data, {
headers: { 'Content-Type': 'multipart/form-data' }
})
}
<script lang="ts" setup>
import { ElMessage } from 'element-plus'
import { UploadFilled } from '@element-plus/icons-vue'
import { splitStrLast } from '@/utils/util'
import { importSchool } from '../api'
const emit = defineEmits<Emits>()
const upload = ref()
const fileList = ref([]) // 文件列表
defineProps({
isShowImport: {
type: Boolean
}
})
interface Emits {
(e: 'update:isShowImport', isShowImportDialog: boolean): void
(e: 'create'): void
}
// 取消
const handleCancel = () => {
emit('update:isShowImport', false)
}
const beforeUpload = (file: any) => {
const suffix = splitStrLast(file.name, '.')
if (!['xlsx', 'xls'].includes(suffix)) {
ElMessage.warning('只能上传excel文件')
return false
} else {
return true
}
}
const fetchFileUpload = (option: any) => {
return new Promise(() => {
importSchool({ file: option.file }).then(() => {
ElMessage.success('导入数据成功')
emit('update:isShowImport', false)
emit('create')
})
})
}
const handleSubmitUpload = () => {
upload.value.submit()
}
</script>
<template>
<el-dialog :model-value="isShowImport" draggable :before-close="handleCancel" title="批量导入客户" width="30%">
<el-upload
style="text-align: center"
class="file-import"
ref="upload"
action="#"
accept=".xls,.xlsx"
drag
:auto-upload="false"
:file-list="fileList"
:limit="1"
:before-upload="beforeUpload"
:http-request="fetchFileUpload"
>
<el-icon class="el-icon--upload"><upload-filled /></el-icon>
<div class="el-upload__text">将文件拖至此处,点击上传</div>
</el-upload>
<div style="margin-bottom: 10px; text-align: center">
导入模板下载:<a href="https://webapp-pub.ezijing.com/center_user/%E5%AE%A2%E6%88%B7.xlsx" download="客户模板"
><el-link type="primary">客户模板.xlsx</el-link></a
>
</div>
<template #footer>
<span>
<el-button @click="handleCancel">取消</el-button>
<el-button type="primary" @click="handleSubmitUpload">确认</el-button>
</span>
</template>
</el-dialog>
</template>
<script setup lang="ts">
import { getSchoolList } from '../api'
import BatchImport from '../components/BatchImport.vue'
const appList = ref()
const isShowImport = ref(false)
// 列表配置
const listOptions = {
// remote: {
// httpRequest: getExperimentList,
// params: { name: '' }
// },
filters: [
{ type: 'input', prop: 'id', placeholder: '客户编号' },
{ type: 'input', prop: 'name', placeholder: '客户名称' },
{ type: 'input', prop: 'nature', placeholder: '院校性质' },
{ type: 'select', prop: 'department', placeholder: '归属部门' },
{ type: 'input', prop: 'master', placeholder: '负责人' },
{ type: 'input', prop: 'origin', placeholder: '客户来源' }
],
columns: [
{ label: '客户编号', prop: 'id' },
{ label: '客户名称', prop: 'name' },
{ label: '院校性质', prop: 'nature' },
{ label: '归属部门', prop: 'department' },
{ label: '客户来源', prop: 'origin' },
{ label: '负责人', prop: ' master' },
{ label: '创建时间', prop: 'created_time' },
{ label: '更新时间', prop: 'updated_time' },
{ label: '操作', slots: 'table-x', width: 100 }
],
data: [{ id: 1 }, { id: 2 }]
const listOptions = $computed(() => {
return {
remote: {
httpRequest: getSchoolList,
params: { name: '', number: '', nature: '', department: '', leader: '', from: '' }
},
filters: [
{ type: 'input', prop: 'name', placeholder: '客户编号' },
{ type: 'input', prop: 'number', placeholder: '客户名称' },
{ type: 'input', prop: 'nature', placeholder: '院校性质' },
{ type: 'input', prop: 'department', placeholder: '归属部门' },
{ type: 'input', prop: 'leader', placeholder: '负责人' },
{ type: 'input', prop: 'from', placeholder: '客户来源' }
],
columns: [
{ label: '#', type: 'index' },
{ label: '客户编号', prop: 'name' },
{ label: '客户名称', prop: 'number' },
{ label: '院校性质', prop: 'nature' },
{ label: '归属部门', prop: 'department' },
{ label: '客户来源', prop: 'from' },
{ label: '负责人', prop: ' leader' },
{ label: '创建时间', prop: 'create_time' },
{ label: '更新时间', prop: 'update_time' },
{ label: '操作', slots: 'table-x', width: 100 }
]
}
})
const handleBatchImport = () => {
isShowImport.value = true
}
const handleRefetch = () => {
appList.value.refetch()
}
</script>
<template>
<AppCard title="学校信息">
<AppList v-bind="listOptions" ref="appList">
<el-button type="primary" style="margin-bottom: 20px" @click="handleBatchImport">批量导入</el-button>
<template #table-x="{ row }">
<el-button type="primary" link>
<router-link :to="`/school/school/${row.id}`" target="_blank">查看</router-link>
......@@ -37,4 +50,5 @@ const listOptions = {
</template>
</AppList>
</AppCard>
<BatchImport v-model:isShowImport="isShowImport" v-if="isShowImport" @create="handleRefetch" />
</template>
<script setup lang="ts">
import { getSchoolDetail } from '../api'
const route = useRoute()
interface Props {
id: string
}
defineProps<Props>()
const activeName = ref('1')
const props = defineProps<Props>()
const schoolDatail: any = ref({})
const params: any = { id: route.query.id || props.id }
getSchoolDetail(params).then(res => {
schoolDatail.value = res.data
})
const activeName = ref(1)
// 列表配置
const listOptions = {
columns: [
{ label: '#', prop: 'id' },
{ label: '姓名', prop: 'name' },
{ label: '性别', prop: 'gender' },
{ label: '手机号', prop: 'phone' },
{ label: '职务', prop: 'work' },
{ label: '联系人类型', prop: 'sound' }
],
data: [{ id: 1 }, { id: 2 }]
}
const editableTabs = ref([
{
title: 'Tab 1',
name: '1',
content: 'Tab 1 content'
},
{
title: 'Tab 2',
name: '2',
content: 'Tab 2 content'
const listOptions = $computed(() => {
return {
columns: [
{ label: '#', type: 'index' },
{ label: '姓名', prop: 'name' },
{ label: '性别', prop: 'gender' },
{ label: '手机号', prop: 'phone' },
{ label: '职务', prop: 'post' },
{ label: '联系人类型', prop: 'type' }
],
data: schoolDatail.user
}
])
})
</script>
<template>
<AppCard title="基本信息">
<el-descriptions :column="4">
<el-descriptions-item label="客户编号">123123</el-descriptions-item>
<el-descriptions-item label="客户名称">哈哈哈</el-descriptions-item>
<el-descriptions-item label="归属部门">技术部</el-descriptions-item>
<el-descriptions-item label="所属公海">-</el-descriptions-item>
<el-descriptions-item label="省排名">2</el-descriptions-item>
<el-descriptions-item label="院校层次">高职</el-descriptions-item>
<el-descriptions-item label="退回原因">-</el-descriptions-item>
<el-descriptions-item label="领取时间">2020-10-10</el-descriptions-item>
<el-descriptions-item label="负责人">郝屋撩</el-descriptions-item>
<el-descriptions-item label="创建时间">2020-10-10</el-descriptions-item>
<el-descriptions-item label="规模">-</el-descriptions-item>
<el-descriptions-item label="地址">-</el-descriptions-item>
<el-descriptions-item label="客户编号">{{ schoolDatail.number || '-' }}</el-descriptions-item>
<el-descriptions-item label="客户名称">{{ schoolDatail.name || '-' }}</el-descriptions-item>
<el-descriptions-item label="归属部门">{{ schoolDatail.department || '-' }}</el-descriptions-item>
<el-descriptions-item label="所属公海">{{ schoolDatail.public || '-' }}</el-descriptions-item>
<el-descriptions-item label="省排名">{{ schoolDatail.ranking || '-' }}</el-descriptions-item>
<el-descriptions-item label="院校层次">{{ schoolDatail.level || '-' }}</el-descriptions-item>
<el-descriptions-item label="退回原因">{{ schoolDatail.reason || '-' }}</el-descriptions-item>
<el-descriptions-item label="领取时间">{{ schoolDatail.collection_time || '-' }}</el-descriptions-item>
<el-descriptions-item label="负责人">{{ schoolDatail.leader || '-' }}</el-descriptions-item>
<el-descriptions-item label="创建时间">{{ schoolDatail.create_time || '-' }}</el-descriptions-item>
<el-descriptions-item label="规模">{{ schoolDatail.scale || '-' }}</el-descriptions-item>
<el-descriptions-item label="地址">{{ schoolDatail.address || '-' }}</el-descriptions-item>
</el-descriptions>
</AppCard>
<AppCard>
<el-tabs v-model="activeName" class="demo-tabs">
<AppCard title="项目信息">
<el-tabs v-model="activeName" class="demo-tabs" lazy>
<el-tab-pane
v-for="(item, index) in editableTabs"
v-for="(item, index) in schoolDatail.project"
:key="index"
:label="`项目${index + 1}/商机信息${index + 1}`"
:name="item.name"
:label="`项目信息${index + 1}`"
:name="index + 1"
>
<el-descriptions>
<el-descriptions-item label="标题">标题{{ item.name }} </el-descriptions-item>
<el-descriptions-item label="项目名称">项目名称</el-descriptions-item>
<el-descriptions-item label="商机/编号">0041</el-descriptions-item>
<el-descriptions-item label="所属公海">-</el-descriptions-item>
<el-descriptions-item label="销售阶段">L3-洽谈</el-descriptions-item>
<el-descriptions-item label="所属分公司">-</el-descriptions-item>
<el-descriptions-item label="商机/类型">产业学院</el-descriptions-item>
<el-descriptions-item label="地址">北京</el-descriptions-item>
<el-descriptions-item label="市场">宁老师</el-descriptions-item>
<el-descriptions-item label="售前">-</el-descriptions-item>
<el-descriptions-item label="教研">-</el-descriptions-item>
<el-descriptions-item label="领取时间">2022-01-01</el-descriptions-item>
<el-descriptions-item label="项目名称">{{ item.name }}</el-descriptions-item>
<el-descriptions-item label="商机/编号">{{ item.number }}</el-descriptions-item>
<el-descriptions-item label="商机/类型">{{ item.type }}</el-descriptions-item>
<el-descriptions-item label="销售阶段">{{ item.stage }}</el-descriptions-item>
<el-descriptions-item label="所属分公司">{{ item.company }}</el-descriptions-item>
<el-descriptions-item label="二级学院/系">{{ item.college }}</el-descriptions-item>
<el-descriptions-item label="专业">{{ item.major }}</el-descriptions-item>
<el-descriptions-item label="负责人">{{ item.leader }}</el-descriptions-item>
<el-descriptions-item label="市场">{{ item.market }}</el-descriptions-item>
<el-descriptions-item label="售前">{{ item.pre_sale }}</el-descriptions-item>
<el-descriptions-item label="教研">{{ item.teaching }}</el-descriptions-item>
<el-descriptions-item label="更新时间">{{ item.update_time }}</el-descriptions-item>
</el-descriptions>
<div class="title" style="margin-top: 15px">决策人</div>
<AppList v-bind="listOptions" ref="appList" style="padding: 0 15px"></AppList>
</el-tab-pane>
</el-tabs>
<!-- <div v-for="index in 3" :key="index" style="padding: 0 30px"> -->
</AppCard>
<AppCard title="申请信息">
<AppCard title="联系人信息">
<AppList v-bind="listOptions" ref="appList"></AppList>
</AppCard>
</template>
import httpRequest from '@/utils/axios'
// 获取搜索条件
export function getConditionList(params: { all: boolean }) {
return httpRequest.get('/api/users/v1/index/index/condition', { params })
}
// 获取全部学员信息
export function getAllUserList(params: {
created_time_start?: string
created_time_end?: string
project_id?: string
system_id?: string
name?: string
email?: string
mobile?: string
}) {
return httpRequest.get('/api/users/v1/customer/all/index', { params })
}
<script setup lang="ts">
const isShowPickDialog = ref(false)
import { useInfoStore } from '@/stores/index'
import shortcuts from '@/utils/shortcut'
import { getConditionList, getAllUserList } from '../api'
const router = useRouter()
const store = useInfoStore()
const list = store.info
console.log(list)
const projectList = ref([])
const systemList = ref([])
getConditionList({ all: true }).then(res => {
projectList.value = res.data.all.projects
systemList.value = res.data.all.system_id
console.log(res)
})
// 列表配置
const listOptions = {
remote: {
// httpRequest: getExperimentList,
params: { timeRange: '', project_name: '', origin: '', name: '', email: '', mobile: '' }
},
filters: [
{
type: 'input',
slots: 'timeRange',
prop: 'timeRange'
},
{
type: 'select',
prop: 'project_name',
options: [
{ label: '玛丽伍德', value: '0' },
{ label: 'DBA', value: '1' },
{ label: '石溪', value: '2' },
{ label: '心理学', value: '3' }
],
placeholder: '所在项目'
},
{
type: 'select',
prop: 'origin',
options: [
{ label: 'ZWS', value: '0' },
{ label: '企微', value: '1' },
{ label: '尘峰', value: '2' },
{ label: '小鹅通', value: '3' }
],
placeholder: '用户来源'
const listOptions = $computed(() => {
return {
remote: {
beforeRequest(params: any) {
params.created_time_start = params.timeRange[0]
params.created_time_end = params.timeRange[1]
return params
},
httpRequest: getAllUserList,
params: {
timeRange: [],
created_time_start: '',
created_time_end: '',
project_id: '',
system_id: '',
name: '',
email: '',
mobile: ''
}
},
{
type: 'input',
prop: 'name',
placeholder: '用户姓名'
},
{
type: 'input',
prop: 'email',
placeholder: '邮箱'
},
{
type: 'input',
prop: 'mobile',
placeholder: '联系电话'
}
],
columns: [
{ label: '用户姓名', prop: 'name' },
{ label: '联系电话', prop: 'mobile' },
{ label: '邮箱', prop: 'email' },
{ label: '所在项目', prop: 'project_name' },
{ label: '用户来源', prop: 'user_origin' },
{ label: '创建时间', prop: 'created_time' },
{ label: '操作', slots: 'table-x', width: 100 }
],
data: [{ name: 1 }, { name: 2 }]
}
filters: [
{
slots: 'timeRange',
prop: 'timeRange'
},
{
type: 'select',
prop: 'project_id',
options: projectList.value,
valueKey: 'project_id',
labelKey: 'title',
placeholder: '所在项目'
},
{
type: 'select',
prop: 'system_id',
options: systemList.value,
valueKey: 'id',
labelKey: 'name',
placeholder: '用户来源'
},
{
type: 'input',
prop: 'name',
placeholder: '用户姓名'
},
{
type: 'input',
prop: 'email',
placeholder: '邮箱'
},
{
type: 'input',
prop: 'mobile',
placeholder: '联系电话'
}
],
columns: [
{ label: '用户姓名', prop: 'user_name' },
{ label: '联系电话', prop: 'phone_number' },
{ label: '邮箱', prop: 'email' },
{ label: '所在项目', prop: 'project_name' },
{
label: '用户来源',
prop: 'system_id',
computed(row: any) {
if (row.row.system_id === 'zws') {
return 'zws'
} else if (row.row.system_id === 'wechat') {
return '企微'
} else if (row.row.system_id === 'dustess') {
return '尘锋'
} else if (row.row.system_id === 'xiaoe') {
return '小鹅通'
}
}
},
{ label: '创建时间', prop: 'created_time' },
{ label: '操作', slots: 'table-x', width: 100 }
]
}
})
const shortcuts = [
{
text: '今日',
value: () => {
const end = new Date()
const start = new Date()
start.setTime(new Date(new Date().toLocaleDateString()).getTime())
return [start, end.setHours(23, 59, 59, 999)]
}
},
{
text: '昨日',
value: () => {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24)
return [start.setHours(0, 0, 0, 0), end.setHours(23, 59, 59, 999)]
}
},
{
text: '本周',
value: () => {
// let weeks = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六']
const end = new Date()
const start = new Date()
console.log(start.getDay())
start.setTime(start.getTime() - 3600 * 1000 * 24 * (start.getDay() - 1))
return [start.setHours(0, 0, 0, 0), end]
}
},
{
text: '上周',
value: () => {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * (start.getDay() + 6))
end.setTime(end.getTime() - 3600 * 1000 * 24 * end.getDay())
return [start.setHours(0, 0, 0, 0), end.setHours(23, 59, 59, 999)]
}
},
{
text: '过去7天',
value: () => {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * 7)
return [start.setHours(0, 0, 0, 0), end.setHours(23, 59, 59, 999)]
}
},
{
text: '过去14天',
value: () => {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * 14)
return [start.setHours(0, 0, 0, 0), end.setHours(23, 59, 59, 999)]
}
},
{
text: '过去30天',
value: () => {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * 30)
return [start.setHours(0, 0, 0, 0), end.setHours(23, 59, 59, 999)]
}
},
{
text: '过去60天',
value: () => {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * 60)
return [start.setHours(0, 0, 0, 0), end.setHours(23, 59, 59, 999)]
}
},
{
text: '过去90天',
value: () => {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * 90)
return [start.setHours(0, 0, 0, 0), end.setHours(23, 59, 59, 999)]
}
},
{
text: '过去180天',
value: () => {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * 180)
return [start.setHours(0, 0, 0, 0), end.setHours(23, 59, 59, 999)]
}
const handleDetail = (row: any) => {
if (row.system_id === 'zws') {
router.push(`/user/zws/detail/${row.id}`)
} else if (row.system_id === 'wechat') {
router.push(`/user/weixin/detail/${row.id}`)
} else if (row.system_id === 'dustess') {
router.push(`/user/chenfeng/detail/${row.id}`)
} else if (row.system_id === 'xiaoe') {
router.push(`/user/xiaoetong/detail/${row.id}`)
}
]
}
</script>
<template>
<AppCard title="全部学员信息">
......@@ -172,9 +126,7 @@ const shortcuts = [
/>
</template>
<template #table-x="{ row }">
<el-button type="primary" link>
<router-link :to="`/user/all/${row.id}`" target="_blank">查看</router-link>
</el-button>
<el-link type="primary" @click="handleDetail(row)"> 查看 </el-link>
</template>
</AppList>
</AppCard>
......
import httpRequest from '@/utils/axios'
// 获取搜索条件
export function getConditionList(params: { xiaoe: boolean }) {
return httpRequest.get('/api/users/v1/index/index/condition', { params })
}
// 获取全部学员信息
export function getGooseList(params: {
created_at_start?: string
created_at_end?: string
phone?: string
id?: string
wx_account?: string
name?: string
province?: string
company?: string
wx_email?: string
from?: string
sales?: string
}) {
return httpRequest.get('/api/users/v1/customer/xiaoe/index', { params })
}
// 获取小鹅通详情
export function getGooseUserDetail(params: { id: string }) {
return httpRequest.get('/api/users/v1/customer/xiaoe/view', { params })
}
\ No newline at end of file
......@@ -7,7 +7,7 @@ export const routes: Array<RouteRecordRaw> = [
component: AppLayout,
children: [
{ path: '', component: () => import('./views/List.vue') },
{ path: '/user/xiaoetong/detail/:id', component: () => import('./views/View.vue'), props: true }
{ path: '/user/xiaoetong/detail', component: () => import('./views/View.vue') }
]
}
]
<script setup lang="ts">
const shortcuts = [
{
text: '今日',
value: () => {
const end = new Date()
const start = new Date()
start.setTime(new Date(new Date().toLocaleDateString()).getTime())
return [start, end.setHours(23, 59, 59, 999)]
}
},
{
text: '昨日',
value: () => {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24)
return [start.setHours(0, 0, 0, 0), end.setHours(23, 59, 59, 999)]
}
},
{
text: '本周',
value: () => {
// let weeks = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六']
const end = new Date()
const start = new Date()
console.log(start.getDay())
start.setTime(start.getTime() - 3600 * 1000 * 24 * (start.getDay() - 1))
return [start.setHours(0, 0, 0, 0), end]
}
},
{
text: '上周',
value: () => {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * (start.getDay() + 6))
end.setTime(end.getTime() - 3600 * 1000 * 24 * end.getDay())
return [start.setHours(0, 0, 0, 0), end.setHours(23, 59, 59, 999)]
}
},
{
text: '过去7天',
value: () => {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * 7)
return [start.setHours(0, 0, 0, 0), end.setHours(23, 59, 59, 999)]
}
},
{
text: '过去14天',
value: () => {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * 14)
return [start.setHours(0, 0, 0, 0), end.setHours(23, 59, 59, 999)]
}
},
{
text: '过去30天',
value: () => {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * 30)
return [start.setHours(0, 0, 0, 0), end.setHours(23, 59, 59, 999)]
}
},
{
text: '过去60天',
value: () => {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * 60)
return [start.setHours(0, 0, 0, 0), end.setHours(23, 59, 59, 999)]
}
},
{
text: '过去90天',
value: () => {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * 90)
return [start.setHours(0, 0, 0, 0), end.setHours(23, 59, 59, 999)]
}
},
{
text: '过去180天',
value: () => {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * 180)
return [start.setHours(0, 0, 0, 0), end.setHours(23, 59, 59, 999)]
}
}
]
import shortcuts from '@/utils/shortcut'
import { getConditionList, getGooseList } from '../api'
const fromMapList = ref([])
const provinceMapList = ref([])
const salesList = ref([])
getConditionList({ xiaoe: true }).then(res => {
fromMapList.value = res.data.xiaoe.from_map.reduce((s: any, cur: any) => {
s.push({ id: res.data.xiaoe.from_map.indexOf(cur), name: cur })
return s
}, [])
provinceMapList.value = res.data.xiaoe.province_map.reduce((t: any, cur: any) => {
t.push({ id: res.data.xiaoe.province_map.indexOf(cur), name: cur })
return t
}, [])
console.log(provinceMapList.value)
salesList.value = res.data.xiaoe.sales
})
// 列表配置
const listOptions = {
remote: {
// httpRequest: getExperimentList,
params: { timeRange: '', project_name: '', origin: '', name: '', email: '', mobile: '' }
},
filters: [
{
type: 'input',
slots: 'createTime',
prop: 'createTime'
const listOptions = $computed(() => {
return {
remote: {
httpRequest: getGooseList,
beforeRequest(params: any) {
params.created_at_start = params.timeRange[0]
params.created_at_end = params.timeRange[1]
return params
},
params: {
timeRange: [],
created_at_start: '',
created_at_end: '',
phone: '',
id: '',
wx_account: '',
name: '',
province: '',
company: '',
wx_email: '',
from: '',
sales: ''
}
},
filters: [
{
slots: 'timeRange',
prop: 'timeRange'
},
{
type: 'input',
prop: 'name',
placeholder: '联系电话'
},
{
type: 'input',
prop: 'nickname',
placeholder: '用户ID'
},
{
type: 'input',
prop: 'remark',
placeholder: '微信号'
},
{
type: 'input',
prop: 'mobile',
placeholder: '用户姓名'
},
{
type: 'select',
prop: 'email',
placeholder: '地区'
},
{
type: 'input',
prop: 'email',
placeholder: '公司'
},
{
type: 'input',
prop: 'email',
placeholder: '邮箱'
},
{
type: 'input',
prop: 'phone',
placeholder: '联系电话'
},
{
type: 'input',
prop: 'id',
placeholder: '用户ID'
},
{
type: 'input',
prop: 'wx_account',
placeholder: '微信号'
},
{
type: 'input',
prop: 'name',
placeholder: '用户姓名'
},
{
type: 'select',
prop: 'province',
placeholder: '地区',
options: provinceMapList.value,
labelKey: 'name',
valueKey: 'id'
},
{
type: 'input',
prop: 'company',
placeholder: '公司'
},
{
type: 'input',
prop: 'wx_email',
placeholder: '邮箱'
},
{
type: 'select',
prop: 'origin',
options: [
{ label: '玛丽伍德', value: '0' },
{ label: 'DBA', value: '1' },
{ label: '石溪', value: '2' },
{ label: '心理学', value: '3' }
],
placeholder: '来源'
},
// 与所在项目进行联动
{
type: 'select',
prop: 'representative',
placeholder: '销售代表',
options: [
{ label: '玛丽伍德', value: '0' },
{ label: 'DBA', value: '1' },
{ label: '石溪', value: '2' },
{ label: '心理学', value: '3' }
]
}
],
columns: [
{ label: '用户姓名', prop: 'name' },
{ label: '联系电话', prop: 'mobile' },
{ label: '邮箱', prop: 'email' },
{ label: '微信号', prop: 'email' },
{ label: '公司', prop: 'project_name' },
{ label: '销售代表', prop: 'representative' },
{ label: '地区', prop: 'channel' },
{ label: '创建时间', prop: 'created_times' },
{ label: '操作', slots: 'table-x', width: 100 }
],
data: [{ id: 1 }, { id: 2 }]
}
{
type: 'select',
prop: 'from',
options: fromMapList.value,
placeholder: '来源',
labelKey: 'name',
valueKey: 'id'
},
{
type: 'select',
prop: 'sales',
placeholder: '销售代表',
options: salesList.value,
labelKey: 'name',
valueKey: 'id'
}
],
columns: [
{ label: '用户姓名', prop: 'name' },
{ label: '联系电话', prop: 'bind_phone' },
{ label: '邮箱', prop: 'wx_email' },
{ label: '微信号', prop: 'wx_account' },
{ label: '公司', prop: 'company' },
{ label: '销售代表', prop: 'sales' },
{ label: '地区', prop: 'province' },
{ label: '创建时间', prop: 'created_at' },
{ label: '操作', slots: 'table-x', width: 100 }
]
}
})
</script>
<template>
<AppCard title="小鹅通客户">
<AppList v-bind="listOptions" ref="appList">
<template v-slot:createTime="{ params }">
<template v-slot:timeRange="{ params }">
<el-date-picker
v-model="params.createTime"
v-model="params.timeRange"
type="datetimerange"
:shortcuts="shortcuts"
range-separator="To"
start-placeholder="创建开始时间"
end-placeholder="创建结束时间"
value-format="yyyy-MM-dd HH-mm-ss"
:shortcuts="shortcuts"
/>
</template>
<template #table-x="{ row }">
<el-button type="primary" link>
<router-link :to="`/user/xiaoetong/detail/${row.id}`" target="_blank">查看</router-link>
</el-button>
<router-link :to="`/user/xiaoetong/detail/?id=${row.id}`" target="_blank">
<el-link type="primary" plain>查看</el-link>
</router-link>
</template>
</AppList>
</AppCard>
......
<script setup lang="ts">
defineProps<Props>()
import { getGooseUserDetail } from '../api'
const route = useRoute()
const router = useRouter()
const props = defineProps<Props>()
interface Props {
id: string
}
interface IInfoList {
name: string
nickname: string
remark: string
mobile: string
company: string
email: string
addPeople: string
department: string
created_time: string
origin: string
}
const infoList = ref<IInfoList[]>([
{
name: '111',
nickname: '111',
remark: '111',
mobile: '111',
company: '111',
email: '111',
addPeople: '111',
department: '111',
created_time: '111',
origin: '111'
}
])
const gooseInfo: any = ref({})
const params: any = { id: route.query.id || props.id }
getGooseUserDetail(params).then(res => {
gooseInfo.value = res.data
})
</script>
<template>
<el-row justify="end">
<el-button type="primary">尘峰渠道</el-button>
<el-button type="primary">企微渠道</el-button>
<el-button type="primary">ZWS渠道</el-button>
<el-button
type="primary"
@click="router.push({ path: '/user/chenfeng/detail', query: { id: gooseInfo.other_system_customer?.dustess } })"
v-if="gooseInfo?.other_system_customer?.dustess !== null"
>尘峰渠道</el-button
>
<el-button
type="primary"
@click="router.push({ path: '/user/weixin/detail', query: { id: gooseInfo.other_system_customer?.wechat } })"
v-if="gooseInfo.other_system_customer?.wechat !== null"
>企微渠道</el-button
>
<el-button
type="primary"
@click="router.push({ path: '/user/zws/detail', query: { id: gooseInfo.other_system_customer?.zws } })"
v-if="gooseInfo.other_system_customer?.zws !== null"
>ZWS渠道</el-button
>
</el-row>
<div v-for="(item, index) in infoList" :key="index" style="margin-top: 20px">
<AppCard title="基本信息">
<el-descriptions :column="4">
<el-descriptions-item label="用户姓名">{{ item.name }}</el-descriptions-item>
<el-descriptions-item label="联系电话">{{ item.mobile }}</el-descriptions-item>
<el-descriptions-item label="微信号">{{ item.nickname }}</el-descriptions-item>
<el-descriptions-item label="用户ID">{{ item.remark }}</el-descriptions-item>
<el-descriptions-item label="真实姓名">{{ item.company }}</el-descriptions-item>
<el-descriptions-item label="邮箱">{{ item.email }}</el-descriptions-item>
<el-descriptions-item label="销售代表">{{ item.addPeople }}</el-descriptions-item>
<el-descriptions-item label="企业名称">{{ item.department }}</el-descriptions-item>
<el-descriptions-item label="行业">{{ item.created_time }}</el-descriptions-item>
<el-descriptions-item label="地址">{{ item.origin }}</el-descriptions-item>
<el-descriptions-item label="地区">{{ item.origin }}</el-descriptions-item>
<el-descriptions-item label="职位">{{ item.origin }}</el-descriptions-item>
<el-descriptions-item label="年龄">{{ item.origin }}</el-descriptions-item>
<el-descriptions-item label="生日">{{ item.origin }}</el-descriptions-item>
<el-descriptions-item label="性别">{{ item.origin }}</el-descriptions-item>
<el-descriptions-item label="创建时间">{{ item.origin }}</el-descriptions-item>
<el-descriptions-item label="备注">{{ item.origin }}</el-descriptions-item>
</el-descriptions>
</AppCard>
</div>
<AppCard title="基本信息">
<el-descriptions :column="4">
<el-descriptions-item label="用户姓名">{{ gooseInfo.name || '-' }}</el-descriptions-item>
<el-descriptions-item label="联系电话">{{ gooseInfo.bind_phone || '-' }}</el-descriptions-item>
<el-descriptions-item label="微信号">{{ gooseInfo.wx_account || '-' }}</el-descriptions-item>
<el-descriptions-item label="用户ID">{{ gooseInfo.id || '-' }}</el-descriptions-item>
<el-descriptions-item label="真实姓名">{{ gooseInfo.name || '-' }}</el-descriptions-item>
<el-descriptions-item label="邮箱">{{ gooseInfo.wx_email || '-' }}</el-descriptions-item>
<el-descriptions-item label="销售代表">{{ gooseInfo.sales || '-' }}</el-descriptions-item>
<el-descriptions-item label="企业名称">{{ gooseInfo.company || '-' }}</el-descriptions-item>
<el-descriptions-item label="行业">{{ gooseInfo.industry || '-' }}</el-descriptions-item>
<el-descriptions-item label="地址">{{ gooseInfo.address || '-' }}</el-descriptions-item>
<el-descriptions-item label="地区">{{ gooseInfo.province || '-' }}</el-descriptions-item>
<el-descriptions-item label="职位">{{ gooseInfo.job || '-' }}</el-descriptions-item>
<el-descriptions-item label="年龄">{{ gooseInfo.age || '-' }}</el-descriptions-item>
<el-descriptions-item label="生日">{{ gooseInfo.birth || '-' }}</el-descriptions-item>
<el-descriptions-item label="性别">{{ gooseInfo.gender || '-' }}</el-descriptions-item>
<el-descriptions-item label="创建时间">{{ gooseInfo.created_at || '-' }}</el-descriptions-item>
<el-descriptions-item label="备注">{{ gooseInfo.remark || '-' }}</el-descriptions-item>
</el-descriptions>
</AppCard>
</template>
import httpRequest from '@/utils/axios'
// 获取搜索条件
export function getConditionList(params: { dustess: boolean }) {
return httpRequest.get('/api/users/v1/index/index/condition', { params })
}
// 获取全部学员信息
export function getPeakUserList(params: {
createtime_start?: string
createtime_end?: string
name?: string
mobiles?: string
email?: string
corp_name?: string
source?: string
createuser_name?: string
owner?: string
}) {
return httpRequest.get('/api/users/v1/customer/dustess/index', { params })
}
// 获取详情
export function getPeakUserDetail(params: { id: string }) {
return httpRequest.get('/api/users/v1/customer/dustess/view', { params })
}
......@@ -7,7 +7,7 @@ export const routes: Array<RouteRecordRaw> = [
component: AppLayout,
children: [
{ path: '', component: () => import('./views/List.vue') },
{ path: '/user/chenfeng/detail/:id', component: () => import('./views/View.vue'), props: true }
{ path: '/user/chenfeng/detail', component: () => import('./views/View.vue') }
]
}
]
<script setup lang="ts">
const shortcuts = [
{
text: '今日',
value: () => {
const end = new Date()
const start = new Date()
start.setTime(new Date(new Date().toLocaleDateString()).getTime())
return [start, end.setHours(23, 59, 59, 999)]
}
},
{
text: '昨日',
value: () => {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24)
return [start.setHours(0, 0, 0, 0), end.setHours(23, 59, 59, 999)]
}
},
{
text: '本周',
value: () => {
// let weeks = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六']
const end = new Date()
const start = new Date()
console.log(start.getDay())
start.setTime(start.getTime() - 3600 * 1000 * 24 * (start.getDay() - 1))
return [start.setHours(0, 0, 0, 0), end]
}
},
{
text: '上周',
value: () => {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * (start.getDay() + 6))
end.setTime(end.getTime() - 3600 * 1000 * 24 * end.getDay())
return [start.setHours(0, 0, 0, 0), end.setHours(23, 59, 59, 999)]
}
},
{
text: '过去7天',
value: () => {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * 7)
return [start.setHours(0, 0, 0, 0), end.setHours(23, 59, 59, 999)]
}
},
{
text: '过去14天',
value: () => {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * 14)
return [start.setHours(0, 0, 0, 0), end.setHours(23, 59, 59, 999)]
}
},
{
text: '过去30天',
value: () => {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * 30)
return [start.setHours(0, 0, 0, 0), end.setHours(23, 59, 59, 999)]
}
},
{
text: '过去60天',
value: () => {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * 60)
return [start.setHours(0, 0, 0, 0), end.setHours(23, 59, 59, 999)]
}
},
{
text: '过去90天',
value: () => {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * 90)
return [start.setHours(0, 0, 0, 0), end.setHours(23, 59, 59, 999)]
}
},
{
text: '过去180天',
value: () => {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * 180)
return [start.setHours(0, 0, 0, 0), end.setHours(23, 59, 59, 999)]
}
}
]
import shortcuts from '@/utils/shortcut'
import { getConditionList, getPeakUserList } from '../api'
const staffList = ref([])
const sourceMapList = ref([])
getConditionList({ dustess: true }).then((res: any) => {
staffList.value = res.data.dustess.staff
sourceMapList.value = res.data.dustess.sourceMap
})
// 列表配置
const listOptions = {
remote: {
// httpRequest: getExperimentList,
params: { timeRange: '', project_name: '', origin: '', name: '', email: '', mobile: '' }
},
filters: [
{
type: 'input',
slots: 'createTime',
prop: 'createTime'
const listOptions = $computed(() => {
return {
remote: {
beforeRequest(params: any) {
params.createtime_start = params.timeRange[0]
params.createtime_end = params.timeRange[1]
return params
},
httpRequest: getPeakUserList,
params: {
timeRange: [],
createtime_start: '',
createtime_end: '',
name: '',
mobiles: '',
email: '',
corp_name: '',
source: '',
createuser_name: '',
owner: ''
}
},
filters: [
{
type: 'input',
slots: 'timeRange',
prop: 'timeRange'
},
{
type: 'input',
prop: 'name',
placeholder: '用户姓名'
},
{
type: 'input',
prop: 'name',
placeholder: '用户姓名'
},
{
type: 'input',
prop: 'mobile',
placeholder: '电话'
},
{
type: 'input',
prop: 'email',
placeholder: '邮箱'
},
{
type: 'input',
prop: 'mobiles',
placeholder: '电话'
},
{
type: 'input',
prop: 'email',
placeholder: '邮箱'
},
// 与所在项目进行联动
{
type: 'input',
prop: 'company_name',
placeholder: '公司'
},
{
type: 'select',
prop: 'company_name',
placeholder: '来源',
options: [
{ label: '社交推广', value: '0' },
{ label: '搜索引擎', value: '1' },
{ label: '客户介绍', value: '2' },
{ label: '个人开发', value: '3' },
{ label: '市场商机', value: '4' },
{ label: '其他', value: '5' },
{ label: '广告', value: '6' }
]
},
{
type: 'input',
prop: 'created_by',
placeholder: '创建人'
},
{
type: 'select',
prop: 'representative',
placeholder: '销售代表'
}
],
columns: [
{ label: '用户姓名', prop: 'name' },
{ label: '联系电话', prop: 'mobile' },
{ label: '邮箱', prop: 'email' },
{ label: '公司', prop: 'company_name' },
{ label: '创建人', prop: 'created_by' },
{ label: '销售代表', prop: 'representative' },
{ label: '来源', prop: 'origin' },
{ label: '创建时间', prop: 'created_time' },
{ label: '操作', slots: 'table-x', width: 100 }
],
data: [{ name: 1 }, { name: 2 }]
}
// 与所在项目进行联动
{
type: 'input',
prop: 'corp_name',
placeholder: '公司'
},
{
type: 'select',
prop: 'source',
placeholder: '来源',
options: sourceMapList.value,
labelKey: 'name',
valueKey: 'id'
},
{
type: 'input',
prop: 'createuser_name',
placeholder: '创建人'
},
{
type: 'select',
prop: 'owner',
placeholder: '销售代表',
options: staffList.value,
labelKey: 'name',
valueKey: 'id'
}
],
columns: [
{ label: '用户姓名', prop: 'name' },
{ label: '联系电话', prop: 'mobiles' },
{ label: '邮箱', prop: 'email' },
{ label: '公司', prop: 'corp_name' },
{ label: '创建人', prop: 'createuser_name' },
{ label: '销售代表', prop: 'owner_name' },
{ label: '来源', prop: 'source_name' },
{ label: '创建时间', prop: 'createtime' },
{ label: '操作', slots: 'table-x', width: 100 }
]
}
})
</script>
<template>
<AppCard title="尘峰客户">
<AppList v-bind="listOptions" ref="appList">
<template v-slot:createTime="{ params }">
<template v-slot:timeRange="{ params }">
<el-date-picker
v-model="params.createTime"
v-model="params.timeRange"
type="datetimerange"
:shortcuts="shortcuts"
range-separator="To"
start-placeholder="创建开始时间"
end-placeholder="创建结束时间"
value-format="yyyy-MM-dd HH-mm-ss"
:shortcuts="shortcuts"
/>
</template>
<template #table-x="{ row }">
<el-button type="primary" link>
<router-link :to="`/user/chenfeng/detail/${row.id}`" target="_blank">查看</router-link>
</el-button>
<router-link :to="`/user/chenfeng/detail/?id=${row.id}`" target="_blank">
<el-link type="primary" plain>查看</el-link>
</router-link>
</template>
</AppList>
</AppCard>
......
<script setup lang="ts">
defineProps<Props>()
import { getPeakUserDetail } from '../api'
interface Props {
id: string
}
interface IInfoList {
name: string
nickname: string
remark: string
mobile: string
company: string
email: string
addPeople: string
department: string
created_time: string
origin: string
}
const infoList = ref<IInfoList[]>([
{
name: '111',
nickname: '111',
remark: '111',
mobile: '111',
company: '111',
email: '111',
addPeople: '111',
department: '111',
created_time: '111',
origin: '111'
}
])
const route = useRoute()
const router = useRouter()
const props = defineProps<Props>()
const infoList: any = ref({})
const params: any = { id: route.query.id || props.id }
getPeakUserDetail(params).then(res => {
res.data.custom_fields = JSON.parse(res.data.custom_fields)
infoList.value = res.data
})
console.log(route.query.id, '0000')
</script>
<template>
<el-row justify="end">
<el-button type="primary">尘峰渠道</el-button>
<el-button type="primary">企微渠道</el-button>
<el-button type="primary">ZWS渠道</el-button>
<el-row justify="end" style="margin-bottom: 20px">
<el-button
type="primary"
@click="router.push({ path: '/user/chenfeng/detail', query: { id: infoList.other_system_customer?.xiaoe } })"
v-if="infoList.other_system_customer?.xiaoe !== null"
>小鹅通渠道</el-button
>
<el-button
type="primary"
@click="router.push({ path: '/user/weixin/detail', query: { id: infoList.other_system_customer?.wechat } })"
v-if="infoList.other_system_customer?.wechat !== null"
>企微渠道</el-button
>
<el-button
type="primary"
@click="router.push({ path: '/user/zws/detail', query: { id: infoList.other_system_customer?.zws } })"
v-if="infoList.other_system_customer?.zws !== null"
>ZWS渠道</el-button
>
</el-row>
<div v-for="(item, index) in infoList" :key="index" style="margin-top: 20px">
<AppCard :title="`基本信息${index + 1}`">
<el-descriptions :column="4">
<el-descriptions-item label="用户姓名">{{ item.name }}</el-descriptions-item>
<el-descriptions-item label="联系电话">{{ item.mobile }}</el-descriptions-item>
<el-descriptions-item label="性别">{{ item.nickname }}</el-descriptions-item>
<el-descriptions-item label="邮箱">{{ item.remark }}</el-descriptions-item>
<el-descriptions-item label="来源">{{ item.company }}</el-descriptions-item>
<el-descriptions-item label="公司">{{ item.email }}</el-descriptions-item>
<el-descriptions-item label="职务">{{ item.addPeople }}</el-descriptions-item>
<el-descriptions-item label="生日">{{ item.department }}</el-descriptions-item>
<el-descriptions-item label="销售代表">{{ item.created_time }}</el-descriptions-item>
<el-descriptions-item label="创建人">{{ item.origin }}</el-descriptions-item>
<el-descriptions-item label="创建时间">{{ item.origin }}</el-descriptions-item>
<el-descriptions-item></el-descriptions-item>
<el-descriptions-item label="备注">{{ item.origin }}</el-descriptions-item>
</el-descriptions>
</AppCard>
</div>
<AppCard>
<el-descriptions :column="4">
<el-descriptions-item label="用户姓名">{{ infoList.name || '-' }}</el-descriptions-item>
<el-descriptions-item label="联系电话">
<span v-for="(item, index) in infoList.mobiles" :key="index">
{{ item }}
</span>
</el-descriptions-item>
<el-descriptions-item label="性别">{{ infoList.gender || '-' }}</el-descriptions-item>
<el-descriptions-item label="邮箱">{{ infoList.email || '-' }}</el-descriptions-item>
<el-descriptions-item label="来源">{{ infoList.source_name || '-' }}</el-descriptions-item>
<el-descriptions-item label="公司">{{ infoList.corp_full_name || '-' }}</el-descriptions-item>
<el-descriptions-item label="职务">{{ infoList.position || '-' }}</el-descriptions-item>
<el-descriptions-item label="生日">{{ infoList.birthday || '-' }}</el-descriptions-item>
<el-descriptions-item label="销售代表">{{ infoList.owner_name || '-' }}</el-descriptions-item>
<el-descriptions-item label="创建人">{{ infoList.createuser_name || '-' }}</el-descriptions-item>
<el-descriptions-item label="创建时间">{{ infoList.createtime || '-' }}</el-descriptions-item>
<el-descriptions-item></el-descriptions-item>
<el-descriptions-item label="备注">
<span v-for="(item, index) in infoList.custom_fields" :key="index">
{{ item }}
</span>
</el-descriptions-item>
</el-descriptions>
</AppCard>
</template>
import httpRequest from '@/utils/axios'
// 获取搜索条件
export function getConditionList(params: { wechat: boolean }) {
return httpRequest.get('/api/users/v1/index/index/condition', { params })
}
// 获取全部学员信息
export function getWechatUserList(params: {
create_time_start?: string
create_time_end?: string
name?: string
remark?: string
remark_mobiles?: string
follow_name?: string
follow_department_id?: string
tag_id?: string
add_way?: string
corp_name?: string
['per-page']?: string
page?: string
}) {
return httpRequest.get('/api/users/v1/customer/wechat/index', { params })
}
// 获取详情
export function getwechatUserDetail(params: { id: string }) {
return httpRequest.get('/api/users/v1/customer/wechat/view', { params })
}
......@@ -7,7 +7,7 @@ export const routes: Array<RouteRecordRaw> = [
component: AppLayout,
children: [
{ path: '', component: () => import('./views/List.vue') },
{ path: '/user/weixin/detail/:id', component: () => import('./views/View.vue'), props: true }
{ path: '/user/weixin/detail', component: () => import('./views/View.vue'), props: true }
]
}
]
<script setup lang="ts">
const shortcuts = [
{
text: '今日',
value: () => {
const end = new Date()
const start = new Date()
start.setTime(new Date(new Date().toLocaleDateString()).getTime())
return [start, end.setHours(23, 59, 59, 999)]
}
},
{
text: '昨日',
value: () => {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24)
return [start.setHours(0, 0, 0, 0), end.setHours(23, 59, 59, 999)]
}
},
{
text: '本周',
value: () => {
// let weeks = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六']
const end = new Date()
const start = new Date()
console.log(start.getDay())
start.setTime(start.getTime() - 3600 * 1000 * 24 * (start.getDay() - 1))
return [start.setHours(0, 0, 0, 0), end]
}
},
{
text: '上周',
value: () => {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * (start.getDay() + 6))
end.setTime(end.getTime() - 3600 * 1000 * 24 * end.getDay())
return [start.setHours(0, 0, 0, 0), end.setHours(23, 59, 59, 999)]
}
},
{
text: '过去7天',
value: () => {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * 7)
return [start.setHours(0, 0, 0, 0), end.setHours(23, 59, 59, 999)]
}
},
{
text: '过去14天',
value: () => {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * 14)
return [start.setHours(0, 0, 0, 0), end.setHours(23, 59, 59, 999)]
}
},
{
text: '过去30天',
value: () => {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * 30)
return [start.setHours(0, 0, 0, 0), end.setHours(23, 59, 59, 999)]
}
},
{
text: '过去60天',
value: () => {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * 60)
return [start.setHours(0, 0, 0, 0), end.setHours(23, 59, 59, 999)]
}
},
{
text: '过去90天',
value: () => {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * 90)
return [start.setHours(0, 0, 0, 0), end.setHours(23, 59, 59, 999)]
}
},
{
text: '过去180天',
value: () => {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * 180)
return [start.setHours(0, 0, 0, 0), end.setHours(23, 59, 59, 999)]
}
}
]
import shortcuts from '@/utils/shortcut'
import { getConditionList, getWechatUserList } from '../api'
const departmentsList: any = ref([])
const addWayList: any = ref([])
const tagsList: any = ref([])
getConditionList({ wechat: true }).then(res => {
departmentsList.value = res.data.wechat.departments
addWayList.value = res.data.wechat.add_way
tagsList.value = res.data.wechat.tags.map((item: any) => {
item.tag = item.tag.map((it: any) => {
const keys: any = { id: 'group_id', name: 'group_name' }
it = Object.keys(it).reduce((acc, key) => ({ ...acc, ...{ [keys[key] || key]: it[key] } }), {})
return it
})
return item
})
console.log(tagsList.value, '123123123')
})
// 列表配置
const listOptions = {
remote: {
// httpRequest: getExperimentList,
params: { timeRange: '', project_name: '', origin: '', name: '', email: '', mobile: '' }
},
filters: [
{
type: 'input',
slots: 'createTime',
prop: 'createTime'
},
{
type: 'input',
prop: 'nickname',
placeholder: '微信昵称'
},
{
type: 'input',
prop: 'company_name',
placeholder: '公司'
},
{
type: 'input',
prop: 'remark',
placeholder: '备注名'
},
{
type: 'input',
prop: 'mobile',
placeholder: '联系电话'
const listOptions = $computed(() => {
return {
remote: {
beforeRequest(params: any) {
params.create_time_start = params.timeRange[0]
params.create_time_start = params.timeRange[1]
return params
},
httpRequest: getWechatUserList,
params: {
timeRange: [],
create_time_start: '',
create_time_end: '',
name: '',
remark: '',
remark_mobiles: '',
follow_name: '',
follow_department_id: '',
tag_id: '',
add_way: '',
corp_name: ''
}
},
filters: [
{
slots: 'timeRange',
prop: 'timeRange'
},
{
type: 'input',
prop: 'name',
placeholder: '微信昵称'
},
{
type: 'input',
prop: 'corp_name',
placeholder: '公司'
},
{
type: 'input',
prop: 'remark',
placeholder: '备注名'
},
{
type: 'input',
prop: 'remark_mobiles',
placeholder: '联系电话'
},
{
type: 'select',
prop: 'project_name',
options: [
{ label: '玛丽伍德', value: '0' },
{ label: 'DBA', value: '1' },
{ label: '石溪', value: '2' },
{ label: '心理学', value: '3' }
],
placeholder: '来源'
},
{
type: 'input',
prop: 'email',
placeholder: '添加人'
},
{
type: 'select',
prop: 'department',
options: [
{ label: '渠道部', value: '0' },
{ label: '售前部', value: '1' }
],
placeholder: '添加人所在部门'
},
{
type: 'select',
prop: 'company_label',
options: [
{ label: '玛丽伍德', value: '0' },
{ label: 'DBA', value: '1' },
{ label: '石溪', value: '2' },
{ label: '心理学', value: '3' }
],
placeholder: '企业标签'
}
],
columns: [
{ label: '微信昵称', prop: 'name' },
{ label: '联系电话', prop: 'mobile' },
{ label: '来源', prop: 'origin' },
{ label: '公司', prop: 'company_name' },
{ label: '添加人', prop: 'add' },
{ label: '添加人所在部门', prop: 'department' },
{ label: '创建时间', prop: 'created_times' },
{ label: '操作', slots: 'table-x', width: 100 }
],
data: [{ id: 1 }, { id: 2 }]
}
{
type: 'select',
prop: 'add_way',
options: addWayList.value,
placeholder: '来源',
labelKey: 'name',
valueKey: 'id'
},
{
type: 'input',
prop: 'follow_name',
placeholder: '添加人'
},
{
type: 'select',
prop: 'follow_department_id',
options: departmentsList.value,
placeholder: '添加人所在部门',
labelKey: 'name',
valueKey: 'id'
},
{
slots: 'tags',
prop: 'tag_id'
}
],
columns: [
{ label: '微信昵称', prop: 'name' },
{ label: '联系电话', prop: 'remark_mobiles', slots: 'remark_mobiles' },
{ label: '来源', prop: 'add_way_name', slots: 'add_way_name' },
{ label: '公司', prop: 'corp_name' },
{ label: '添加人', prop: 'user_name', slots: 'user_name' },
{ label: '添加人所在部门', prop: 'department_name', slots: 'department_name' },
{ label: '创建时间', prop: 'createtime', slots: 'createtime' },
{ label: '操作', slots: 'table-x', width: 100 }
]
}
})
</script>
<template>
<AppCard title="企微客户">
<AppList v-bind="listOptions" ref="appList">
<template v-slot:createTime="{ params }">
<template v-slot:tags="{ params }">
<el-cascader
placeholder="企业标签"
v-model="params.tag_id"
:options="tagsList"
:props="{ label: 'group_name', value: 'group_id', children: 'tag' }"
/>
</template>
<template v-slot:timeRange="{ params }">
<el-date-picker
v-model="params.createTime"
v-model="params.timeRange"
type="datetimerange"
:shortcuts="shortcuts"
range-separator="To"
start-placeholder="创建开始时间"
end-placeholder="创建结束时间"
value-format="yyyy-MM-dd HH-mm-ss"
:shortcuts="shortcuts"
/>
</template>
<template #remark_mobiles="{ row }">
<div v-for="(item, index) in row.follow" :key="index">
<p v-for="(it, index) in item.remark_mobiles" :key="index">
{{ it }}
</p>
</div>
</template>
<template #add_way_name="{ row }">
<div v-for="(item, index) in row.follow" :key="index">{{ item.add_way_name }}</div>
</template>
<template #user_name="{ row }">
<div v-for="(item, index) in row.follow" :key="index">{{ item.user_name }}</div>
</template>
<template #department_name="{ row }">
<div v-for="(item, index) in row.follow" :key="index">{{ item.department_name }}</div>
</template>
<template #createtime="{ row }">
<div v-for="(item, index) in row.follow" :key="index">{{ item.createtime }}</div>
</template>
<template #table-x="{ row }">
<el-button type="primary" link>
<router-link :to="`/user/weixin/detail/${row.id}`" target="_blank">查看</router-link>
</el-button>
<router-link :to="`/user/weixin/detail/?id=${row.external_userid}`" target="_blank">
<el-link type="primary" plain>查看</el-link>
</router-link>
</template>
</AppList>
</AppCard>
......
<script setup lang="ts">
defineProps<Props>()
import { getwechatUserDetail } from '../api'
const route = useRoute()
const router = useRouter()
const props = defineProps<Props>()
interface Props {
id: string
}
interface IInfoList {
name: string
nickname: string
remark: string
mobile: string
company: string
email: string
addPeople: string
department: string
created_time: string
origin: string
}
const infoList = ref<IInfoList[]>([
{
nickname: '1121',
origin: 'kkk',
remark: '222',
mobile: '222',
company: '22',
email: '22',
addPeople: '22',
department: '22',
created_time: '2'
},
{
nickname: '1121',
origin: 'kkk',
remark: '222',
mobile: '222',
company: '22',
email: '22',
addPeople: '22',
department: '22',
created_time: '2'
}
])
const wechatFollow: any = ref([])
const other_system_customers: any = ref({})
const params: any = { id: route.query.id || props.id }
getwechatUserDetail(params).then(res => {
const { follow, other_system_customer, ...info } = res.data
other_system_customers.value = other_system_customer
wechatFollow.value = res.data.follow.map((item: any) => {
item.wechatInfo = info
return item
})
})
</script>
<template>
<el-row justify="end">
<el-button type="primary">尘峰渠道</el-button>
<el-button type="primary">小鹅通渠道</el-button>
<el-button type="primary">ZWS渠道</el-button>
<el-button
type="primary"
@click="router.push({ path: '/user/chenfeng/detail', query: { id: other_system_customers.dustess } })"
v-if="other_system_customers.dustess !== null"
>尘峰渠道</el-button
>
<el-button
type="primary"
@click="router.push({ path: '/user/xiaoe/detail', query: { id: other_system_customers.xiaoe } })"
v-if="other_system_customers.xiaoe !== null"
>小鹅通渠道</el-button
>
<el-button
type="primary"
@click="router.push({ path: '/user/zws/detail', query: { id: other_system_customers.zws } })"
v-if="other_system_customers.zws !== null"
>ZWS渠道</el-button
>
</el-row>
<div v-for="(item, index) in infoList" :key="index" style="margin-top: 20px">
<div v-for="(item, index) in wechatFollow" :key="index" style="margin-top: 20px">
<AppCard :title="`基本信息${index + 1}`">
<el-descriptions :column="4">
<el-descriptions-item label="微信昵称">{{ item.nickname }}</el-descriptions-item>
<el-descriptions-item label="来源">{{ item.origin }}</el-descriptions-item>
<el-descriptions-item label="备注名">{{ item.remark }}</el-descriptions-item>
<el-descriptions-item label="联系电话">{{ item.mobile }}</el-descriptions-item>
<el-descriptions-item label="公司">{{ item.company }}</el-descriptions-item>
<el-descriptions-item label="创建时间">{{ item.created_time }}</el-descriptions-item>
<el-descriptions-item label="添加人">{{ item.addPeople }}</el-descriptions-item>
<el-descriptions-item label="添加人所在部门">{{ item.department }}</el-descriptions-item>
<el-descriptions-item label="微信昵称">{{ item.wechatInfo.name || '-' }}</el-descriptions-item>
<el-descriptions-item label="来源">{{ item.add_way_name || '-' }}</el-descriptions-item>
<el-descriptions-item label="备注名">{{ item.remark || '-' }}</el-descriptions-item>
<el-descriptions-item label="联系电话">
<span v-for="(it, index) in item.remark_mobiles" :key="index">{{ it }}</span>
</el-descriptions-item>
<el-descriptions-item label="公司">{{ item.wechatInfo.corp_full_name || '-' }}</el-descriptions-item>
<el-descriptions-item label="创建时间">{{ item.createtime || '-' }}</el-descriptions-item>
<el-descriptions-item label="添加人">{{ item.user_name || '-' }}</el-descriptions-item>
<el-descriptions-item label="添加人所在部门">{{ item.department_name || '-' }}</el-descriptions-item>
</el-descriptions>
</AppCard>
<AppCard :title="`企业信息${index + 1}`">
<el-descriptions :column="1">
<el-descriptions-item label="酒店高管">百度渠道 百度渠道 百度渠道</el-descriptions-item>
<el-descriptions-item label="分公司">留咨 留咨 留咨</el-descriptions-item>
<el-descriptions :column="1" v-if="item.tags.length > 0">
<el-descriptions-item>
<span v-for="(it, index) in item.tags" :key="index">{{ it }}</span>
</el-descriptions-item>
</el-descriptions>
<el-empty v-else></el-empty>
</AppCard>
</div>
</template>
import httpRequest from '@/utils/axios'
// 获取搜索条件
export function getConditionList(params: { zws: boolean }) {
return httpRequest.get('/api/users/v1/index/index/condition', { params })
}
// 获取全部学员信息
export function getZwsUserList(params: {
createTime?: string
create_time_start?: string
create_time_end?: string
updatedTime?: string
updated_time_start?: string
updated_time_end?: string
application_status?: string
project_id?: string
user_name?: string
email?: string
phone_number?: string
sales_rep?: string
channel?: string
}) {
return httpRequest.get('/api/users/v1/customer/zws/index', { params })
}
// 获取详情
export function getZwsUserDetail(params: { id: string }) {
return httpRequest.get('/api/users/v1/customer/zws/view', { params })
}
......@@ -7,7 +7,7 @@ export const routes: Array<RouteRecordRaw> = [
component: AppLayout,
children: [
{ path: '', component: () => import('./views/List.vue') },
{ path: ':id', component: () => import('./views/View.vue'), props: true }
{ path: '/user/zws/detail/:id', component: () => import('./views/View.vue'), props: true }
]
}
]
<script setup lang="ts">
const shortcuts = [
{
text: '今日',
value: () => {
const end = new Date()
const start = new Date()
start.setTime(new Date(new Date().toLocaleDateString()).getTime())
return [start, end.setHours(23, 59, 59, 999)]
}
},
{
text: '昨日',
value: () => {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24)
return [start.setHours(0, 0, 0, 0), end.setHours(23, 59, 59, 999)]
}
},
{
text: '本周',
value: () => {
// let weeks = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六']
const end = new Date()
const start = new Date()
console.log(start.getDay())
start.setTime(start.getTime() - 3600 * 1000 * 24 * (start.getDay() - 1))
return [start.setHours(0, 0, 0, 0), end]
}
},
{
text: '上周',
value: () => {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * (start.getDay() + 6))
end.setTime(end.getTime() - 3600 * 1000 * 24 * end.getDay())
return [start.setHours(0, 0, 0, 0), end.setHours(23, 59, 59, 999)]
}
},
{
text: '过去7天',
value: () => {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * 7)
return [start.setHours(0, 0, 0, 0), end.setHours(23, 59, 59, 999)]
}
},
{
text: '过去14天',
value: () => {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * 14)
return [start.setHours(0, 0, 0, 0), end.setHours(23, 59, 59, 999)]
}
},
{
text: '过去30天',
value: () => {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * 30)
return [start.setHours(0, 0, 0, 0), end.setHours(23, 59, 59, 999)]
}
},
{
text: '过去60天',
value: () => {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * 60)
return [start.setHours(0, 0, 0, 0), end.setHours(23, 59, 59, 999)]
}
},
{
text: '过去90天',
value: () => {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * 90)
return [start.setHours(0, 0, 0, 0), end.setHours(23, 59, 59, 999)]
}
},
{
text: '过去180天',
value: () => {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * 180)
return [start.setHours(0, 0, 0, 0), end.setHours(23, 59, 59, 999)]
}
}
]
import shortcuts from '@/utils/shortcut'
import { getConditionList, getZwsUserList } from '../api'
const agentsList = ref([])
const projectsList = ref([])
const applicationList = ref([])
const channelsList = ref([])
getConditionList({ zws: true }).then(res => {
console.log(res.data.zws.application_status_map)
agentsList.value = res.data.zws.agents
projectsList.value = res.data.zws.projects
applicationList.value = res.data.zws.application_status_map
channelsList.value = res.data.zws.channels
})
// 列表配置
const listOptions = {
remote: {
// httpRequest: getExperimentList,
params: { timeRange: '', project_name: '', origin: '', name: '', email: '', mobile: '' }
},
filters: [
{
type: 'input',
slots: 'createTime',
prop: 'createTime'
},
{
type: 'input',
slots: 'updatedTime',
prop: 'updatedTime'
},
{
type: 'select',
prop: 'apply_status',
options: [{ label: '通过面试', value: '0' }],
placeholder: '申请状态'
},
{
type: 'select',
prop: 'project_name',
options: [
{ label: '玛丽伍德', value: '0' },
{ label: 'DBA', value: '1' },
{ label: '石溪', value: '2' },
{ label: '心理学', value: '3' }
],
placeholder: '所在项目'
},
{
type: 'input',
prop: 'name',
placeholder: '用户姓名'
},
{
type: 'input',
prop: 'email',
placeholder: '邮箱'
},
{
type: 'input',
prop: 'mobile',
placeholder: '联系电话'
},
{
type: 'input',
prop: 'representative',
placeholder: '销售代表'
const listOptions = $computed(() => {
return {
remote: {
beforeRequest(params: any) {
params.create_time_start = params.createTime[0]
params.create_time_end = params.createTime[1]
params.updated_time_start = params.updatedTime[0]
params.updated_time_end = params.updatedTime[1]
return params
},
httpRequest: getZwsUserList,
params: {
createTime: [],
create_time_start: '',
create_time_end: '',
updatedTime: [],
updated_time_start: '',
updated_time_end: '',
application_status: '',
project_id: '',
user_name: '',
email: '',
phone_number: '',
sales_rep: '',
channel: ''
}
},
filters: [
{
slots: 'createTime',
prop: 'createTime'
},
{
slots: 'updatedTime',
prop: 'updatedTime'
},
{
type: 'select',
prop: 'application_status',
options: applicationList.value,
placeholder: '申请状态',
labelKey: 'name',
valueKey: 'id'
},
{
type: 'select',
prop: 'project_id',
options: projectsList.value,
placeholder: '所在项目',
labelKey: 'title',
valueKey: 'project_id'
},
{
type: 'input',
prop: 'user_name',
placeholder: '用户姓名'
},
{
type: 'input',
prop: 'email',
placeholder: '邮箱'
},
{
type: 'input',
prop: 'phone_number',
placeholder: '联系电话'
},
{
type: 'select',
prop: 'sales_rep',
placeholder: '销售代表',
options: agentsList.value,
labelKey: 'user_name',
valueKey: 'user_id'
},
// 与所在项目进行联动
{
type: 'select',
prop: 'mobile',
placeholder: '所属渠道',
options: [
{ label: 'ZWS', value: '0' },
{ label: '企微', value: '1' },
{ label: '尘峰', value: '2' },
{ label: '小鹅通', value: '3' }
]
}
],
columns: [
{ label: '用户姓名', prop: 'name' },
{ label: '联系电话', prop: 'mobile' },
{ label: '邮箱', prop: 'email' },
{ label: '所在项目', prop: 'project_name' },
{ label: '申请状态', prop: 'apply_status' },
{ label: '销售代表', prop: 'representative' },
{ label: '所属渠道', prop: 'channel' },
{ label: '创建时间', prop: 'created_times' },
{ label: '更新时间', prop: 'updated_time' },
{ label: '操作', slots: 'table-x', width: 100 }
],
data: [{ id: 1 }, { id: 2 }]
}
{
type: 'select',
prop: 'channel',
placeholder: '所属渠道',
options: channelsList.value,
labelKey: 'title',
valueKey: 'channel_id'
}
],
columns: [
{ label: '用户姓名', prop: 'user_name' },
{ label: '联系电话', prop: 'phone_number' },
{ label: '邮箱', prop: 'email' },
{ label: '所在项目', prop: 'project_name' },
{ label: '申请状态', prop: 'application_status_name' },
{ label: '销售代表', prop: 'sales_rep_name' },
{ label: '所属渠道', prop: 'channel_name' },
{ label: '创建时间', prop: 'created_time' },
{ label: '更新时间', prop: 'updated_time' },
{ label: '操作', slots: 'table-x', width: 100 }
]
}
})
</script>
<template>
<AppCard title="ZWS学员信息">
......@@ -201,9 +139,9 @@ const listOptions = {
/>
</template>
<template #table-x="{ row }">
<el-button type="primary" link>
<router-link :to="`/user/zws/${row.id}`" target="_blank">查看</router-link>
</el-button>
<router-link :to="`/user/zws/detail/?id=${row.id}`" target="_blank">
<el-link type="primary" plain>查看</el-link>
</router-link>
</template>
</AppList>
</AppCard>
......
import { defineStore } from 'pinia'
import { getUserInfo } from '@/api/base'
export interface IUserType {
info: IInfo[]
permissions: IPermissions[]
roles: []
}
export interface IInfo {
id: string
mobile: string
name: string
email: string
username: string
avatar: string
auth_key: null
}
export interface IPermissions {
id: string
name: string
tag: string
parent_id: string
type: number
desc: string
effect_uris: string
}
export const useInfoStore = defineStore({
id: 'map',
state: (): IUserType => {
return {
info: [],
permissions: [],
roles: []
}
},
actions: {
async getUserInfo() {
const res = await getUserInfo()
this.info = res.data.info || []
this.permissions = res.data.permissions || []
this.roles = res.data.roles || []
}
}
})
useInfoStore().getUserInfo()
......@@ -30,3 +30,5 @@ export interface PermissionType {
type: number
tag: string
}
const shortcuts = [
{
text: '今日',
value: () => {
const end = new Date()
const start = new Date()
start.setTime(new Date(new Date().toLocaleDateString()).getTime())
return [start, end.setHours(23, 59, 59, 999)]
}
},
{
text: '昨日',
value: () => {
// const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24)
return [start.setHours(0, 0, 0, 0), start.setHours(23, 59, 59, 999)]
}
},
{
text: '本周',
value: () => {
// let weeks = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六']
const end = new Date()
const start = new Date()
console.log(start.getDay())
start.setTime(start.getTime() - 3600 * 1000 * 24 * (start.getDay() - 1))
return [start.setHours(0, 0, 0, 0), end]
}
},
{
text: '上周',
value: () => {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * (start.getDay() + 6))
end.setTime(end.getTime() - 3600 * 1000 * 24 * end.getDay())
return [start.setHours(0, 0, 0, 0), end.setHours(23, 59, 59, 999)]
}
},
{
text: '过去7天',
value: () => {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * 7)
return [start.setHours(0, 0, 0, 0), end.setHours(23, 59, 59, 999)]
}
},
{
text: '过去14天',
value: () => {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * 14)
return [start.setHours(0, 0, 0, 0), end.setHours(23, 59, 59, 999)]
}
},
{
text: '过去30天',
value: () => {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * 30)
return [start.setHours(0, 0, 0, 0), end.setHours(23, 59, 59, 999)]
}
},
{
text: '过去60天',
value: () => {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * 60)
return [start.setHours(0, 0, 0, 0), end.setHours(23, 59, 59, 999)]
}
},
{
text: '过去90天',
value: () => {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * 90)
return [start.setHours(0, 0, 0, 0), end.setHours(23, 59, 59, 999)]
}
},
{
text: '过去180天',
value: () => {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * 180)
return [start.setHours(0, 0, 0, 0), end.setHours(23, 59, 59, 999)]
}
}
]
export default shortcuts
/**
* 文件下载
* @param {string} fileUrl 文件下载地址
* @param {string} fileName 文件名
* @returns {null}
*/
export function funDownload(fileUrl: any, fileName: any) {
// console.log(fileUrl)
const elink = document.createElement('a') // 创建一个a标签
elink.download = fileName // 设置a标签的下载属性
elink.style.display = 'none' // 将a标签设置为隐藏
elink.href = fileUrl // 把之前处理好的地址赋给a标签的href
document.body.appendChild(elink) // 将a标签添加到body中
elink.click() // 执行a标签的点击方法
// URL.revokeObjectURL(elink.href) // 下载完成释放URL 对象
document.body.removeChild(elink) // 移除a标签
}
/**
* 分割字符串,取得尾部
* @param {string} str 字符串
* @param {string} split 分割符
* @returns {string}
*/
export function splitStrLast(str: any, split: any) {
const fileNameArr = str.split(split)
const last = fileNameArr[fileNameArr.length - 1]
return last
}
......@@ -24,6 +24,12 @@ export default defineConfig(({ mode }) => ({
cert: fs.readFileSync(path.join(__dirname, './https/dev.ezijing.com.pem'))
},
proxy: {
'/api/users': {
// target: 'http://localhost-customer-system-backend.ezijing.com',
target: 'https://customer-backend-api.ezijing.com',
rewrite: path => path.replace(/^\/api\/users/, ''),
changeOrigin: true
},
'/api': 'https://resource-center.ezijing.com'
}
},
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论