【招生小程序】 新增# 主账号-个人:电销以及招生的线索数据和线索详情
parent
56aa0125b8
commit
d06d3f7c78
|
@ -18,7 +18,7 @@ export function apiOrganizationAllList() {
|
||||||
}
|
}
|
||||||
// 岗位列表
|
// 岗位列表
|
||||||
export function postLists(params?: any) {
|
export function postLists(params?: any) {
|
||||||
return request.get({ url: '/system/post/list', data: params })
|
return request.get({ url: '/system/post/list', data: params }, { ignoreCancel: true })
|
||||||
}
|
}
|
||||||
|
|
||||||
// 数据简报
|
// 数据简报
|
||||||
|
@ -45,3 +45,12 @@ export function rankListApi(params?: any) {
|
||||||
export function rankMoreListApi(params?: any) {
|
export function rankMoreListApi(params?: any) {
|
||||||
return request.get({ url: '/control/topAll', data: params })
|
return request.get({ url: '/control/topAll', data: params })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 具体某个成员的数据
|
||||||
|
export function personalListApi(params?: any) {
|
||||||
|
return request.get({ url: '/personageControl/personageControlList', data: params })
|
||||||
|
}
|
||||||
|
// 具体某个成员的详情
|
||||||
|
export function personalDetailApi(params?: any) {
|
||||||
|
return request.get({ url: '/personageControl/detail', data: params })
|
||||||
|
}
|
||||||
|
|
|
@ -11,18 +11,25 @@
|
||||||
</u-copy>
|
</u-copy>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
<text v-if="item.situation == converStatusEnum.UN_RECEIVED" class="text-[#ED6D41]">
|
||||||
|
未领取
|
||||||
|
</text>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
<template #content>
|
<template #content>
|
||||||
<view class="flex gap-[20rpx] mb-[16rpx]">
|
<view class="flex gap-[20rpx] mb-[16rpx]">
|
||||||
<text class="text-muted w-[128rpx]">基本情况</text>
|
<text class="text-muted w-[128rpx]">基本情况</text>
|
||||||
<text class="flex-1">
|
<text class="flex-1">
|
||||||
{{ ellipsisDesc(item) }}
|
{{ item.basicInformation }}
|
||||||
</text>
|
</text>
|
||||||
</view>
|
</view>
|
||||||
|
<view class="flex gap-[20rpx] mb-[16rpx]">
|
||||||
|
<text class="text-muted w-[128rpx]">电销老师</text>
|
||||||
|
<text class="flex-1">{{ item.telemarketingTeacherName }}</text>
|
||||||
|
</view>
|
||||||
<view class="flex gap-[20rpx] mb-[16rpx]">
|
<view class="flex gap-[20rpx] mb-[16rpx]">
|
||||||
<text class="text-muted w-[128rpx]">跟进时间</text>
|
<text class="text-muted w-[128rpx]">跟进时间</text>
|
||||||
<text class="flex-1">{{ item.createTime }}</text>
|
<text class="flex-1">{{ item.followUpTime }}</text>
|
||||||
</view>
|
</view>
|
||||||
<view class="flex gap-[20rpx] mb-[16rpx]">
|
<view class="flex gap-[20rpx] mb-[16rpx]">
|
||||||
<text class="text-muted w-[128rpx]">招生老师</text>
|
<text class="text-muted w-[128rpx]">招生老师</text>
|
||||||
|
@ -30,21 +37,21 @@
|
||||||
</view>
|
</view>
|
||||||
<view class="flex gap-[20rpx] mb-[16rpx]">
|
<view class="flex gap-[20rpx] mb-[16rpx]">
|
||||||
<text class="text-muted w-[128rpx]">领取时间</text>
|
<text class="text-muted w-[128rpx]">领取时间</text>
|
||||||
<text class="flex-1">{{ item.createTime }}</text>
|
<text class="flex-1">{{ item.getTime }}</text>
|
||||||
</view>
|
</view>
|
||||||
<view class="flex gap-[20rpx]">
|
<view class="flex gap-[20rpx] mb-[16rpx]">
|
||||||
<text class="text-muted w-[128rpx]">状态</text>
|
<text class="text-muted w-[128rpx]">状态</text>
|
||||||
<text class="flex-1 text-orage">{{ parseStateText }}</text>
|
<text class="flex-1 text-orage">{{ parseStateText }}</text>
|
||||||
</view>
|
</view>
|
||||||
<view class="flex gap-[20rpx]">
|
<view class="flex gap-[20rpx] mb-[16rpx]">
|
||||||
<text class="text-muted w-[128rpx]">备注</text>
|
<text class="text-muted w-[128rpx]">备注</text>
|
||||||
<view class="flex gap-[12rpx] flex-1">
|
<view class="flex gap-[12rpx] flex-1">
|
||||||
<text class="text-error">{{ item.remark }}</text>
|
<text class="text-error">{{ item.remark }}</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="flex gap-[20rpx]">
|
<view class="flex gap-[20rpx] mb-[16rpx]">
|
||||||
<text class="text-muted w-[128rpx]">成交时间</text>
|
<text class="text-muted w-[128rpx]">成交时间</text>
|
||||||
<text class="flex-1">{{ item.updateTime }}</text>
|
<text class="flex-1">{{ item.accomplishTime }}</text>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
</w-card>
|
</w-card>
|
||||||
|
@ -70,6 +77,9 @@ export interface IClue {
|
||||||
recruitTeacherId: number
|
recruitTeacherId: number
|
||||||
telemarketingTeacherId: number
|
telemarketingTeacherId: number
|
||||||
updateTime: string
|
updateTime: string
|
||||||
|
followUpTime: string //跟进时间
|
||||||
|
accomplishTime: string //成交时间
|
||||||
|
getTime: string //领取时间
|
||||||
}
|
}
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
item: {
|
item: {
|
||||||
|
@ -77,12 +87,6 @@ const props = defineProps({
|
||||||
default: () => ({})
|
default: () => ({})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
const ellipsisDesc = computed(
|
|
||||||
() => (item: IClue) =>
|
|
||||||
item.basicInformation?.length >= 14
|
|
||||||
? item.basicInformation?.slice(0, 14) + '...'
|
|
||||||
: item.basicInformation
|
|
||||||
)
|
|
||||||
const stateMap: Record<stateEnum, string> = {
|
const stateMap: Record<stateEnum, string> = {
|
||||||
[stateEnum.ADD_RELATION]: '账号已添加',
|
[stateEnum.ADD_RELATION]: '账号已添加',
|
||||||
[stateEnum.NO_EXIST]: '账号不存在',
|
[stateEnum.NO_EXIST]: '账号不存在',
|
||||||
|
|
|
@ -47,64 +47,91 @@ import { ref, shallowRef } from 'vue'
|
||||||
import clueCard from './components/clue-card.vue'
|
import clueCard from './components/clue-card.vue'
|
||||||
import datePopup from './components/date-popup.vue'
|
import datePopup from './components/date-popup.vue'
|
||||||
import { useZPaging } from '@/hooks/useZPaging'
|
import { useZPaging } from '@/hooks/useZPaging'
|
||||||
import { apiTeleClueList } from '@/api/clue'
|
|
||||||
import { computed } from 'vue'
|
import { computed } from 'vue'
|
||||||
import { debounce } from 'lodash-es'
|
import { debounce } from 'lodash-es'
|
||||||
import { nextTick } from 'vue'
|
import { nextTick } from 'vue'
|
||||||
import { formatDate, formateDate, getCurDate } from '@/utils/util'
|
import { formatDate, formateDate, getCurDate } from '@/utils/util'
|
||||||
|
import { personalDetailApi } from '@/api/admin'
|
||||||
|
import { converStatusEnum } from '@/enums'
|
||||||
|
|
||||||
const queryParams = ref({
|
const queryParams = ref({
|
||||||
likeWork: ''
|
likeWork: '',
|
||||||
|
userId: '',
|
||||||
|
teachedType: null,
|
||||||
|
status: null,
|
||||||
|
startTime: '',
|
||||||
|
endTime: ''
|
||||||
})
|
})
|
||||||
|
|
||||||
const dataList = ref([])
|
const dataList = ref([])
|
||||||
const { paging, queryList, refresh, changeApi, setParams } = useZPaging(
|
|
||||||
queryParams.value,
|
|
||||||
apiTeleClueList
|
|
||||||
)
|
|
||||||
const activeTab = ref(0)
|
const activeTab = ref(0)
|
||||||
const tabOptions: Record<string, any[]> = {
|
const tabOptions: Record<string, any[]> = {
|
||||||
telesale: [
|
telesale: [
|
||||||
{ name: '全部', value: 0 },
|
{ name: '全部', value: 0 },
|
||||||
{ name: '未领取', value: 1 },
|
{ name: '未领取', value: converStatusEnum.UN_RECEIVED },
|
||||||
{ name: '已领取', value: 2 },
|
{ name: '已领取', value: converStatusEnum.CONVERTED_PROCESS },
|
||||||
{ name: '异常待处理', value: 3 }
|
{ name: '异常待处理', value: converStatusEnum.EXCEPTION }
|
||||||
],
|
],
|
||||||
recruitsale: [
|
recruitsale: [
|
||||||
{ name: '转化中', value: 0 },
|
{ name: '转化中', value: converStatusEnum.CONVERTED_PROCESS },
|
||||||
{ name: '已添加', value: 1 },
|
{ name: '已添加', value: converStatusEnum.ADD_RELATION },
|
||||||
{ name: '异常待处理', value: 2 },
|
{ name: '异常待处理', value: converStatusEnum.EXCEPTION },
|
||||||
{ name: '已成交', value: 3 },
|
{ name: '已成交', value: converStatusEnum.CONVERTED },
|
||||||
{ name: '已战败', value: 4 }
|
{ name: '已战败', value: converStatusEnum.FAILED }
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
const tabs = computed(() => tabOptions[type.value])
|
const tabs = computed(() => tabOptions[type.value])
|
||||||
const isScrollable = computed(() => tabs.value?.length >= 5)
|
const isScrollable = computed(() => tabs.value?.length >= 5)
|
||||||
const handleChangeTab = item => {
|
const handleChangeTab = item => {
|
||||||
activeTab.value = item.value
|
activeTab.value = item.value
|
||||||
|
queryParams.value.status = activeTab.value
|
||||||
|
queryList()
|
||||||
}
|
}
|
||||||
const searchChange = debounce(() => {
|
const searchChange = debounce(() => {
|
||||||
refresh(queryParams.value)
|
queryList()
|
||||||
}, 300)
|
}, 300)
|
||||||
|
|
||||||
const type = ref('')
|
const type = ref('')
|
||||||
const dateTagFlag = ref('')
|
const paging = ref()
|
||||||
|
|
||||||
|
const queryList = async (pageNo = 1, pageSize = 10) => {
|
||||||
|
try {
|
||||||
|
uni.showLoading({
|
||||||
|
title: '加载中...'
|
||||||
|
})
|
||||||
|
const params = {
|
||||||
|
...queryParams.value,
|
||||||
|
pageNo,
|
||||||
|
pageSize
|
||||||
|
}
|
||||||
|
const result = await personalDetailApi(params)
|
||||||
|
paging.value.complete(result.lists)
|
||||||
|
} catch (e) {
|
||||||
|
paging.value.complete(false)
|
||||||
|
}
|
||||||
|
uni.hideLoading()
|
||||||
|
}
|
||||||
|
|
||||||
|
// const dateTagFlag = ref('')
|
||||||
onLoad(async options => {
|
onLoad(async options => {
|
||||||
setFormData(options)
|
setFormData(options)
|
||||||
dateTagFlag.value = options?.dateTag ?? ''
|
// dateTagFlag.value = options?.dateTag ?? ''
|
||||||
await nextTick()
|
// await nextTick()
|
||||||
datePopupRef.value?.setDefaultValue({ ...form.value, dateTag: dateTagFlag.value })
|
// datePopupRef.value?.setDefaultValue({ ...form.value, dateTag: dateTagFlag.value })
|
||||||
|
// datePopupRef.value?.setDefaultValue({ ...form.value })
|
||||||
// if (option.id) {
|
// if (option.id) {
|
||||||
// uni.setNavigationBarTitle({
|
uni.setNavigationBarTitle({
|
||||||
// title: '张三'
|
title:
|
||||||
// })
|
options.postIds == 5 ? '电销老师:' + options.username : '招生老师:' + options.username
|
||||||
type.value = options.type ?? ''
|
})
|
||||||
|
type.value = options.postIds == 5 ? 'telesale' : 'recruitsale'
|
||||||
// }
|
// }
|
||||||
})
|
})
|
||||||
const form = ref()
|
const form = ref()
|
||||||
// 设置表单数据
|
// 设置表单数据
|
||||||
const setFormData = options => {
|
const setFormData = options => {
|
||||||
form.value = Object.keys(options).reduce((acc, key) => {
|
queryParams.value = Object.keys(options).reduce((acc, key) => {
|
||||||
if (key == 'id' || key == 'dateTag' || key == 'type') {
|
if (key == 'username') {
|
||||||
return acc
|
return acc
|
||||||
}
|
}
|
||||||
acc[key] = decodeURIComponent(options[key])
|
acc[key] = decodeURIComponent(options[key])
|
||||||
|
@ -118,16 +145,16 @@ const handleShowPopup = () => {
|
||||||
}
|
}
|
||||||
const handleConfirmDate = (date: { [key: string]: string }) => {
|
const handleConfirmDate = (date: { [key: string]: string }) => {
|
||||||
const { start, end } = date
|
const { start, end } = date
|
||||||
form.value.createTimeStart = formateDate(start, 'start', 'YYYY-MM-DD')
|
queryParams.value.startTime = formateDate(start, 'start')
|
||||||
form.value.createTimeEnd = formateDate(end, 'end', 'YYYY-MM-DD')
|
queryParams.value.endTime = formateDate(end, 'end')
|
||||||
datePopupRef.value?.handleToggle(true)
|
datePopupRef.value?.handleToggle(true)
|
||||||
|
queryList()
|
||||||
}
|
}
|
||||||
const handleResetDate = () => {
|
const handleResetDate = () => {
|
||||||
form.value.createTimeStart = getCurDate('start', 'YYYY-MM-DD')
|
queryParams.value.startTime = getCurDate('start')
|
||||||
form.value.createTimeEnd = getCurDate('end', 'YYYY-MM-DD')
|
queryParams.value.endTime = getCurDate('end')
|
||||||
console.log(form.value)
|
|
||||||
|
|
||||||
datePopupRef.value?.handleToggle(true)
|
datePopupRef.value?.handleToggle(true)
|
||||||
|
queryList()
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style scoped></style>
|
<style scoped></style>
|
||||||
|
|
|
@ -239,7 +239,7 @@ async function loginHandle(data: any) {
|
||||||
cache.set(ROLEINDEX, 2)
|
cache.set(ROLEINDEX, 2)
|
||||||
setNextRoute()
|
setNextRoute()
|
||||||
} else {
|
} else {
|
||||||
if (userInfo.roles?.length > 1) {
|
if (userInfo.roles?.length >= 1) {
|
||||||
uni.redirectTo({
|
uni.redirectTo({
|
||||||
url: '/bundle/pages/select-role/index'
|
url: '/bundle/pages/select-role/index'
|
||||||
})
|
})
|
||||||
|
|
|
@ -11,11 +11,21 @@
|
||||||
{{ form.createTimeStart }} - {{ form.createTimeEnd }}
|
{{ form.createTimeStart }} - {{ form.createTimeEnd }}
|
||||||
</text>
|
</text>
|
||||||
</template>
|
</template>
|
||||||
|
<template v-else-if="key === 'timeRange'">
|
||||||
|
<text class="text-[#1E40AF]">{{ parseLabel(key) }}:</text>
|
||||||
|
<text class="text-primary">{{ form.startTime }} - {{ form.endTime }}</text>
|
||||||
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<text class="text-[#1E40AF]">{{ parseLabel(key) }}:</text>
|
<text class="text-[#1E40AF]">{{ parseLabel(key) }}:</text>
|
||||||
<text class="text-primary" v-if="key === 'organizationId'">
|
<text class="text-primary" v-if="key === 'organizationId'">
|
||||||
{{ findTargetNode(value) }}
|
{{ findTargetNode(value) }}
|
||||||
</text>
|
</text>
|
||||||
|
<text class="text-primary" v-else-if="key === 'userId'">
|
||||||
|
{{ findTargetMember(value) }}
|
||||||
|
</text>
|
||||||
|
<text class="text-primary" v-else-if="key === 'postId'">
|
||||||
|
{{ findTargetPosition(value) }}
|
||||||
|
</text>
|
||||||
<text class="text-primary" v-else>{{ value }}</text>
|
<text class="text-primary" v-else>{{ value }}</text>
|
||||||
</template>
|
</template>
|
||||||
</view>
|
</view>
|
||||||
|
@ -27,6 +37,7 @@ import { PropType } from 'vue'
|
||||||
import { IForm } from './team/index.vue'
|
import { IForm } from './team/index.vue'
|
||||||
import { computed } from 'vue'
|
import { computed } from 'vue'
|
||||||
import { AdminTabEnum } from '@/enums'
|
import { AdminTabEnum } from '@/enums'
|
||||||
|
import { usePositions } from '@/hooks/useCommon'
|
||||||
|
|
||||||
const formMap: Record<AdminTabEnum, any> = {
|
const formMap: Record<AdminTabEnum, any> = {
|
||||||
[AdminTabEnum.TEAM]: {
|
[AdminTabEnum.TEAM]: {
|
||||||
|
@ -36,7 +47,7 @@ const formMap: Record<AdminTabEnum, any> = {
|
||||||
[AdminTabEnum.PERSONALLY]: {
|
[AdminTabEnum.PERSONALLY]: {
|
||||||
postId: '岗位',
|
postId: '岗位',
|
||||||
userId: '用户',
|
userId: '用户',
|
||||||
createTimeRange: '日期'
|
timeRange: '日期'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
|
@ -51,10 +62,18 @@ const props = defineProps({
|
||||||
organizationList: {
|
organizationList: {
|
||||||
type: Array as PropType<any[]>,
|
type: Array as PropType<any[]>,
|
||||||
default: () => []
|
default: () => []
|
||||||
|
},
|
||||||
|
positionList: {
|
||||||
|
type: Array as PropType<any[]>,
|
||||||
|
default: () => []
|
||||||
|
},
|
||||||
|
memberList: {
|
||||||
|
type: Array as PropType<any[]>,
|
||||||
|
default: () => []
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
const filteredForm = computed(() => {
|
const filteredForm = computed(() => {
|
||||||
const { createTimeStart, createTimeEnd, ...rest } = props.form
|
const { createTimeStart, createTimeEnd, startTime = '', endTime = '', ...rest } = props.form
|
||||||
const activeTabMap = formMap[props.activeTab]
|
const activeTabMap = formMap[props.activeTab]
|
||||||
const filtered = Object.keys(rest).reduce((acc, key) => {
|
const filtered = Object.keys(rest).reduce((acc, key) => {
|
||||||
if (activeTabMap[key]) {
|
if (activeTabMap[key]) {
|
||||||
|
@ -66,6 +85,10 @@ const filteredForm = computed(() => {
|
||||||
if (createTimeStart && createTimeEnd) {
|
if (createTimeStart && createTimeEnd) {
|
||||||
filtered['createTimeRange'] = 'createTimeRange'
|
filtered['createTimeRange'] = 'createTimeRange'
|
||||||
}
|
}
|
||||||
|
if (startTime && endTime) {
|
||||||
|
filtered['timeRange'] = 'timeRange'
|
||||||
|
}
|
||||||
|
console.log(filtered)
|
||||||
|
|
||||||
return filtered
|
return filtered
|
||||||
})
|
})
|
||||||
|
@ -98,5 +121,14 @@ const findTargetNode = computed(() => (id: number) => {
|
||||||
}
|
}
|
||||||
return nodeInfo?.name || ''
|
return nodeInfo?.name || ''
|
||||||
})
|
})
|
||||||
|
const findTargetPosition = computed(() => (id: number) => {
|
||||||
|
if (!id) return
|
||||||
|
return props.positionList.find(item => item.id == id).label ?? ''
|
||||||
|
})
|
||||||
|
const findTargetMember = computed(() => (id: number) => {
|
||||||
|
if (!id) return
|
||||||
|
const nodeInfo = findNodeById(props.memberList, id)
|
||||||
|
if (nodeInfo && nodeInfo.id) return nodeInfo.username
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
<style scoped></style>
|
<style scoped></style>
|
||||||
|
|
|
@ -198,7 +198,7 @@ export default defineComponent({
|
||||||
|
|
||||||
&-item {
|
&-item {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
// align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
padding: 24rpx;
|
padding: 24rpx;
|
||||||
// font-size: 24rpx;
|
// font-size: 24rpx;
|
||||||
|
|
|
@ -48,7 +48,7 @@ const props = defineProps({
|
||||||
default: () => ({})
|
default: () => ({})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
const emit = defineEmits(['update:modelValue', 'refreshPage', 'confirm', 'reset'])
|
const emit = defineEmits(['update:modelValue', 'refreshPage', 'confirm', 'reset', 'getData'])
|
||||||
|
|
||||||
const localValue = computed({
|
const localValue = computed({
|
||||||
get() {
|
get() {
|
||||||
|
@ -81,8 +81,8 @@ const handleConfirm = (type: string, item, dateTag?: string) => {
|
||||||
case 'date':
|
case 'date':
|
||||||
localValue.value = {
|
localValue.value = {
|
||||||
...localValue.value,
|
...localValue.value,
|
||||||
createTimeStart: formateDate(item.start, 'start'),
|
startTime: formateDate(item.start, 'start'),
|
||||||
createTimeEnd: formateDate(item.end, 'end')
|
endTime: formateDate(item.end, 'end')
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
case 'position':
|
case 'position':
|
||||||
|
@ -94,7 +94,6 @@ const handleConfirm = (type: string, item, dateTag?: string) => {
|
||||||
default:
|
default:
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
emit('refreshPage')
|
|
||||||
emit('confirm', dateTag)
|
emit('confirm', dateTag)
|
||||||
closeDropDown()
|
closeDropDown()
|
||||||
}
|
}
|
||||||
|
@ -110,21 +109,20 @@ const handleReset = (type: string) => {
|
||||||
case 'date':
|
case 'date':
|
||||||
localValue.value = {
|
localValue.value = {
|
||||||
...localValue.value,
|
...localValue.value,
|
||||||
createTimeStart: getCurDate('start'),
|
startTime: getCurDate('start'),
|
||||||
createTimeEnd: getCurDate('end')
|
endTime: getCurDate('end')
|
||||||
}
|
}
|
||||||
|
|
||||||
break
|
break
|
||||||
case 'position':
|
case 'position':
|
||||||
localValue.value = {
|
localValue.value = {
|
||||||
...localValue.value,
|
...localValue.value,
|
||||||
postId: 0
|
postId: ''
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
emit('refreshPage')
|
|
||||||
emit('reset')
|
emit('reset')
|
||||||
closeDropDown()
|
closeDropDown()
|
||||||
}
|
}
|
||||||
|
@ -137,6 +135,7 @@ const fetchAllOrganizationList = async () => {
|
||||||
try {
|
try {
|
||||||
const result = await apiOrganizationAllList()
|
const result = await apiOrganizationAllList()
|
||||||
dropdownMenuOrgList.value = renameFields(result)
|
dropdownMenuOrgList.value = renameFields(result)
|
||||||
|
emit('getData', dropdownMenuOrgList.value)
|
||||||
} catch (error) {}
|
} catch (error) {}
|
||||||
}
|
}
|
||||||
const renameFields = (data: any[]): any[] => {
|
const renameFields = (data: any[]): any[] => {
|
||||||
|
|
|
@ -5,11 +5,13 @@
|
||||||
<view
|
<view
|
||||||
class="bg-primary rounded-full text-white w-[120rpx] h-[120rpx] flex items-center justify-center"
|
class="bg-primary rounded-full text-white w-[120rpx] h-[120rpx] flex items-center justify-center"
|
||||||
>
|
>
|
||||||
张三
|
{{ item.username }}
|
||||||
</view>
|
</view>
|
||||||
<view class="flex-1 flex flex-col gap-[12rpx]">
|
<view class="flex-1 flex flex-col gap-[12rpx]">
|
||||||
<text>张三</text>
|
<text>{{ item.username }}</text>
|
||||||
<text class="text-muted">湛江团队-A组 . {{ parsePostionText }}</text>
|
<text class="text-muted">
|
||||||
|
{{ item.organizationName }} . {{ parsePostionText }}
|
||||||
|
</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="flex gap-[12rpx] flex-wrap" v-if="!containPostIds">
|
<view class="flex gap-[12rpx] flex-wrap" v-if="!containPostIds">
|
||||||
|
@ -25,7 +27,7 @@
|
||||||
<view v-else class="flex gap-[12rpx] flex-wrap">
|
<view v-else class="flex gap-[12rpx] flex-wrap">
|
||||||
<view
|
<view
|
||||||
class="w-full flex flex-col gap-[24rpx] mb-[24rpx]"
|
class="w-full flex flex-col gap-[24rpx] mb-[24rpx]"
|
||||||
v-for="(value, key) in cardMap"
|
v-for="(value, key) in data"
|
||||||
:key="key"
|
:key="key"
|
||||||
>
|
>
|
||||||
<view class="flex justify-between items-center px-[24rpx]">
|
<view class="flex justify-between items-center px-[24rpx]">
|
||||||
|
@ -53,25 +55,37 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed } from 'vue'
|
import { computed } from 'vue'
|
||||||
import card from '../../card.vue'
|
import card from '../../card.vue'
|
||||||
|
import { PositionEnum } from '@/enums'
|
||||||
|
import { usePositions } from '@/hooks/useCommon'
|
||||||
|
import { watch } from 'vue'
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
item: {
|
item: {
|
||||||
type: Object,
|
type: Object,
|
||||||
default: () => {}
|
default: () => {}
|
||||||
|
},
|
||||||
|
positionList: {
|
||||||
|
type: Array,
|
||||||
|
default: () => []
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
const emit = defineEmits(['handleCardClick'])
|
const emit = defineEmits(['handleCardClick'])
|
||||||
|
|
||||||
const parsePostionText = computed(() => {
|
// 获取岗位ids
|
||||||
const { postId } = props.item
|
const parsePostIds = computed(() => {
|
||||||
const ids = postId?.split(',')
|
const { postIds } = props.item
|
||||||
const positionsList = [
|
return postIds?.split(',').map(Number)
|
||||||
{ name: '电销老师', id: 5 },
|
|
||||||
{ name: '招生老师', id: 6 }
|
|
||||||
]
|
|
||||||
const findItems = positionsList.filter(item => ids.includes(String(item.id)))
|
|
||||||
return findItems.map(item => item.name).join('/')
|
|
||||||
})
|
})
|
||||||
|
// 判断是否既是电销 + 招生
|
||||||
|
const containPostIds = computed(() => {
|
||||||
|
return parsePostIds.value?.includes(5) && parsePostIds.value?.includes(6)
|
||||||
|
})
|
||||||
|
|
||||||
|
const parsePostionText = computed(() => {
|
||||||
|
const findItems = props.positionList?.filter(item => parsePostIds.value?.includes(item.id))
|
||||||
|
return findItems.map(item => item.label).join('/')
|
||||||
|
})
|
||||||
|
const parseText = computed(() => (key: number) => key == 5 ? '电销' : '招生')
|
||||||
|
|
||||||
const cardMap: Record<number, Array<{ label: string; value: number }>> = {
|
const cardMap: Record<number, Array<{ label: string; value: number }>> = {
|
||||||
5: [
|
5: [
|
||||||
|
@ -88,30 +102,67 @@ const cardMap: Record<number, Array<{ label: string; value: number }>> = {
|
||||||
{ label: '战败客户', value: 368 }
|
{ label: '战败客户', value: 368 }
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
const parseText = computed(() => (key: number) => key == 5 ? '电销' : '招生')
|
|
||||||
const data = computed(() => {
|
const data = computed(() => {
|
||||||
const { postId } = props.item
|
if (!props.item) return []
|
||||||
return cardMap[postId]
|
const { postIds } = props.item
|
||||||
})
|
const dataMap: Record<string, any> = {
|
||||||
const parsePostIds = computed(() => {
|
telemarketingVo: [
|
||||||
const { postId } = props.item
|
{ field: 'newAddCount', label: '新增跟进' },
|
||||||
return postId?.split(',').map(Number)
|
{ field: 'unclaimedCount', label: '未领取' },
|
||||||
})
|
{ field: 'alreadyReceivedCount', label: '已领取' },
|
||||||
const containPostIds = computed(() => {
|
{ field: 'exceptionCount', label: '异常待处理' }
|
||||||
return parsePostIds.value.includes(5) && parsePostIds.value.includes(6)
|
],
|
||||||
|
recruitVo: [
|
||||||
|
{ field: 'conversionCount', label: '转化中' },
|
||||||
|
{ field: 'addedCount', label: '已添加' },
|
||||||
|
{ field: 'abnormalCount', label: '异常待处理' },
|
||||||
|
{ field: 'tradedCount', label: '成交客户' },
|
||||||
|
{ field: 'failCount', label: '战败客户' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
const ids = postIds?.split(',').map(Number)
|
||||||
|
const field =
|
||||||
|
ids?.length == 1 && ids?.includes(5)
|
||||||
|
? 'telemarketingVo'
|
||||||
|
: ids?.length == 1 && ids?.includes(6)
|
||||||
|
? 'recruitVo'
|
||||||
|
: ''
|
||||||
|
// 电销 and 招生
|
||||||
|
if (field == '' && ids.length >= 2) {
|
||||||
|
const obj: Record<number, Array<{ label: string; value: number }>> = {}
|
||||||
|
Object.keys(dataMap).map(key => {
|
||||||
|
const id = key === 'telemarketingVo' ? 5 : 6
|
||||||
|
obj[id] = dataMap[key].map(item => {
|
||||||
|
return {
|
||||||
|
label: item.label,
|
||||||
|
value: props.item[key][item.field]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
return obj
|
||||||
|
// 电销 or 招生
|
||||||
|
} else {
|
||||||
|
return dataMap[field].map(item => {
|
||||||
|
return {
|
||||||
|
label: item.label,
|
||||||
|
value: props.item[field][item.field]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const handleCardClick = () => {
|
const handleCardClick = () => {
|
||||||
if (containPostIds.value) return
|
if (containPostIds.value) return
|
||||||
const type =
|
// const type =
|
||||||
parsePostIds.value.length == 1 && parsePostIds.value.includes(5)
|
// parsePostIds.value.length == 1 && parsePostIds.value.includes(5)
|
||||||
? 'telesale'
|
// ? 'telesale'
|
||||||
: 'recruitsale'
|
// : 'recruitsale'
|
||||||
emit('handleCardClick', type, props.item)
|
emit('handleCardClick', props.item)
|
||||||
}
|
}
|
||||||
const handleMore = (key: number) => {
|
const handleMore = (key: number) => {
|
||||||
const type = key == 5 ? 'telesale' : 'recruitsale'
|
// const type = key == 5 ? 'telesale' : 'recruitsale'
|
||||||
emit('handleCardClick', type, props.item)
|
emit('handleCardClick', { ...props.item, postIds: key.toString() })
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style scoped></style>
|
<style scoped></style>
|
||||||
|
|
|
@ -1,77 +1,108 @@
|
||||||
<template>
|
<template>
|
||||||
<view class="flex-1 h-full flex flex-col">
|
<view class="flex-1 h-full flex flex-col">
|
||||||
<dropdownPicker v-model="form" @confirm="confirm" @reset-page="resetPage" />
|
<dropdownPicker
|
||||||
|
v-model="form"
|
||||||
|
@confirm="confirm"
|
||||||
|
@reset="refreshPage"
|
||||||
|
@get-data="getPickerData"
|
||||||
|
/>
|
||||||
|
<filter-value
|
||||||
|
:form="form"
|
||||||
|
:activeTab="activeTab"
|
||||||
|
:positionList="positionList"
|
||||||
|
:memberList="memberList"
|
||||||
|
/>
|
||||||
<view class="flex-1 mt-3 px-[32rpx] overflow-auto bg-[#FAFAFE]">
|
<view class="flex-1 mt-3 px-[32rpx] overflow-auto bg-[#FAFAFE]">
|
||||||
<!-- <z-paging
|
<z-paging
|
||||||
ref="paging"
|
ref="paging"
|
||||||
v-model="dataList"
|
v-model="dataList"
|
||||||
@query="queryList"
|
@query="queryList"
|
||||||
:fixed="false"
|
:fixed="false"
|
||||||
height="100%"
|
height="100%"
|
||||||
> -->
|
>
|
||||||
<template v-for="(item, index) in dataList" :key="`unique_${index}`">
|
<template v-for="(item, index) in dataList" :key="`unique_${index}`">
|
||||||
<telesale-card :item="item" @handleCardClick="handleCardClick" />
|
<telesale-card
|
||||||
|
:item="item"
|
||||||
|
:positionList="positionList"
|
||||||
|
@handleCardClick="handleCardClick"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
<!-- </z-paging> -->
|
</z-paging>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref } from 'vue'
|
import { PropType, computed, onMounted, ref } from 'vue'
|
||||||
import telesaleCard from './components/telesale-card.vue'
|
import telesaleCard from './components/telesale-card.vue'
|
||||||
|
import filterValue from '../filter-value.vue'
|
||||||
import { useZPaging } from '@/hooks/useZPaging'
|
import { useZPaging } from '@/hooks/useZPaging'
|
||||||
import { apiTeleClueList } from '@/api/clue'
|
import { apiTeleClueList } from '@/api/clue'
|
||||||
import { getCurDate } from '@/utils/util'
|
import { getCurDate } from '@/utils/util'
|
||||||
import dropdownPicker from './components/dropdown-picker.vue'
|
import dropdownPicker from './components/dropdown-picker.vue'
|
||||||
|
import { personalListApi } from '@/api/admin'
|
||||||
|
import { usePositions } from '@/hooks/useCommon'
|
||||||
|
import { AdminTabEnum } from '@/enums'
|
||||||
|
import { nextTick } from 'vue'
|
||||||
|
|
||||||
|
defineProps({
|
||||||
|
activeTab: {
|
||||||
|
type: Number as PropType<AdminTabEnum>,
|
||||||
|
default: AdminTabEnum.TEAM
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
const form = ref({
|
const form = ref({
|
||||||
postId: 0,
|
postId: '',
|
||||||
createTimeStart: getCurDate('start'),
|
startTime: getCurDate('start'),
|
||||||
createTimeEnd: getCurDate('end'),
|
endTime: getCurDate('end'),
|
||||||
userId: ''
|
userId: ''
|
||||||
})
|
})
|
||||||
|
|
||||||
const queryParams = ref({
|
const dataList = ref([])
|
||||||
likeWork: ''
|
|
||||||
})
|
|
||||||
const dataList = ref([{ id: 1, postId: '5,6', studentName: '张三' }])
|
|
||||||
const { paging, queryList, refresh, changeApi, setParams } = useZPaging(
|
const { paging, queryList, refresh, changeApi, setParams } = useZPaging(
|
||||||
queryParams.value,
|
form.value,
|
||||||
apiTeleClueList,
|
personalListApi,
|
||||||
() => {}
|
() => {}
|
||||||
)
|
)
|
||||||
const dateTagFlag = ref() //选择快捷日期标识
|
const dateTagFlag = ref() //选择快捷日期标识
|
||||||
const confirm = (dateTag?: string) => {
|
const confirm = (dateTag?: string) => {
|
||||||
console.log(form.value, dateTag)
|
console.log(form.value, dateTag)
|
||||||
dateTagFlag.value = dateTag
|
dateTagFlag.value = dateTag
|
||||||
|
refresh(form.value)
|
||||||
|
}
|
||||||
|
const refreshPage = () => {
|
||||||
|
refresh(form.value)
|
||||||
|
}
|
||||||
|
const splitpostIds = (postIds: string) => {
|
||||||
|
return postIds?.split(',').map(Number)[0]
|
||||||
}
|
}
|
||||||
const resetPage = () => {}
|
|
||||||
// 查看
|
// 查看
|
||||||
const handleCardClick = (type: string, item: any) => {
|
const handleCardClick = (item: any) => {
|
||||||
const { id } = item
|
const { id, postIds, username } = item
|
||||||
console.log(form.value)
|
|
||||||
const params = {
|
const params = {
|
||||||
...form.value,
|
userId: id,
|
||||||
dateTag: encodeURIComponent(dateTagFlag.value),
|
postIds: splitpostIds(postIds),
|
||||||
id,
|
teacherType: splitpostIds(postIds) == 5 ? 0 : 1,
|
||||||
type
|
username
|
||||||
|
// dateTag: encodeURIComponent(dateTagFlag.value),
|
||||||
}
|
}
|
||||||
const queryString = Object.keys(params)
|
const queryString = Object.keys(params)
|
||||||
.map(key => `${encodeURIComponent(key)}=${encodeURIComponent(params[key])}`)
|
.map(key => `${encodeURIComponent(key)}=${encodeURIComponent(params[key])}`)
|
||||||
.join('&')
|
.join('&')
|
||||||
|
|
||||||
switch (type) {
|
|
||||||
case 'telesale':
|
|
||||||
case 'recruitsale':
|
|
||||||
uni.navigateTo({
|
uni.navigateTo({
|
||||||
url: '/bundle/pages/clue-list/index?id=' + queryString
|
url: '/bundle/pages/clue-list/index?' + queryString
|
||||||
})
|
})
|
||||||
break
|
|
||||||
default:
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
const { positionList, fetchPositions } = usePositions()
|
||||||
|
|
||||||
|
const memberList = ref<any[]>([])
|
||||||
|
const getPickerData = (data: any[]) => {
|
||||||
|
memberList.value = data
|
||||||
|
}
|
||||||
|
onMounted(() => {
|
||||||
|
fetchPositions()
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss"></style>
|
<style scoped lang="scss"></style>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<view class="px-[32rpx]">
|
<view class="px-[32rpx] min-h-[250rpx] bg-white">
|
||||||
<template v-if="loading && !data.length">
|
<template v-if="loading && !data.length">
|
||||||
<view class="min-h-[200rpx] flex justify-center items-center">
|
<view class="min-h-[200rpx] flex justify-center items-center">
|
||||||
<u-loading-icon></u-loading-icon>
|
<u-loading-icon></u-loading-icon>
|
||||||
|
|
|
@ -26,11 +26,13 @@ import { getCurDate } from '@/utils/util'
|
||||||
import { AdminTabEnum } from '@/enums'
|
import { AdminTabEnum } from '@/enums'
|
||||||
|
|
||||||
export interface IForm {
|
export interface IForm {
|
||||||
organizationId: number | null
|
organizationId?: number | null
|
||||||
createTimeStart: string
|
createTimeStart?: string
|
||||||
createTimeEnd: string
|
createTimeEnd?: string
|
||||||
|
startTime?: string
|
||||||
|
endTime?: string
|
||||||
userId: string
|
userId: string
|
||||||
postId?: number
|
postId?: number | string
|
||||||
}
|
}
|
||||||
|
|
||||||
defineProps({
|
defineProps({
|
||||||
|
|
|
@ -161,6 +161,7 @@ const judgeShow = () => {
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
judgeShow()
|
judgeShow()
|
||||||
|
userStore.getUser()
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
|
Loading…
Reference in New Issue