【招生小程序】 新增# 主账号-团队:对接数据简报、线索转化情况分析接口以及条件查询(团队、组织、日期)
parent
187a345608
commit
c8ace90b43
|
@ -8,5 +8,6 @@
|
||||||
# 请求域名
|
# 请求域名
|
||||||
# VITE_APP_BASE_URL= 'http://192.168.111.5:8086'
|
# VITE_APP_BASE_URL= 'http://192.168.111.5:8086'
|
||||||
VITE_APP_BASE_URL="http://192.168.111.98:8086"
|
VITE_APP_BASE_URL="http://192.168.111.98:8086"
|
||||||
|
# VITE_APP_BASE_URL="http://f35n565161.vicp.fun"
|
||||||
# VITE_APP_BASE_URL="https://124.220.209.120:8086"
|
# VITE_APP_BASE_URL="https://124.220.209.120:8086"
|
||||||
# VITE_APP_SOCKET_URL = 'wss://front.yuegoodlife.com'
|
# VITE_APP_SOCKET_URL = 'wss://front.yuegoodlife.com'
|
|
@ -0,0 +1,31 @@
|
||||||
|
import request from '@/utils/request'
|
||||||
|
|
||||||
|
// 组织列表
|
||||||
|
export function apiOrganizationList() {
|
||||||
|
return request.get({ url: '/organization/list' })
|
||||||
|
}
|
||||||
|
// 获取所有团队
|
||||||
|
export function apiOrganizationTeamList() {
|
||||||
|
return request.get({ url: '/organization/getAllGroup' })
|
||||||
|
}
|
||||||
|
// 获取组织
|
||||||
|
export function apiOrganizationByIdList() {
|
||||||
|
return request.get({ url: '/organization/getAllOrg' })
|
||||||
|
}
|
||||||
|
// 获取该账号下的所有组织架构以及人员
|
||||||
|
export function apiOrganizationAllList() {
|
||||||
|
return request.get({ url: '/organization/getAllChildOrgInfo' })
|
||||||
|
}
|
||||||
|
|
||||||
|
// 数据简报
|
||||||
|
export function apiDataOverview(params: any) {
|
||||||
|
return request.get({ url: '/control/dataPresentation', data: params })
|
||||||
|
}
|
||||||
|
// 线索转客户统计
|
||||||
|
export function convertProcessApi(params?: any) {
|
||||||
|
return request.get({ url: '/control/leadToCustomerStatistics', data: params })
|
||||||
|
}
|
||||||
|
// 线索转化情况统计
|
||||||
|
export function clueStatusApi(params?: any) {
|
||||||
|
return request.get({ url: '/control/clueStatistics', data: params })
|
||||||
|
}
|
|
@ -235,7 +235,7 @@ async function loginHandle(data: any) {
|
||||||
// appStore.setFirstLogin(true)
|
// appStore.setFirstLogin(true)
|
||||||
const { userInfo } = userStore
|
const { userInfo } = userStore
|
||||||
// 判断是主账号登录还是电销/招生登录
|
// 判断是主账号登录还是电销/招生登录
|
||||||
if (userInfo.postIds == 0) {
|
if (userInfo.postIds == 0 && userInfo.masterAccount == 1) {
|
||||||
cache.set(ROLEINDEX, 2)
|
cache.set(ROLEINDEX, 2)
|
||||||
setNextRoute()
|
setNextRoute()
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -144,7 +144,7 @@ export function getRangeDate(v) {
|
||||||
|
|
||||||
// 昨日
|
// 昨日
|
||||||
if (v === '-1') {
|
if (v === '-1') {
|
||||||
dateRange.start = formatTime(new Date(nowTime - oneDay), 'y-m-d')
|
dateRange.start = formatTime(new Date(nowTime), 'y-m-d')
|
||||||
dateRange.end = dateRange.start
|
dateRange.end = dateRange.start
|
||||||
// 本周
|
// 本周
|
||||||
} else if (v === '-7') {
|
} else if (v === '-7') {
|
||||||
|
|
|
@ -36,9 +36,10 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { defineComponent, ref, watch } from 'vue'
|
import { defineComponent, ref, watch } from 'vue'
|
||||||
import { deepClone, getRangeDate } from '@/components/da-dropdown/utils'
|
|
||||||
import picker from './picker.vue'
|
import picker from './picker.vue'
|
||||||
import dropdownFooter from '../widgets/admin/dropdown-footer.vue'
|
import dropdownFooter from '../widgets/admin/dropdown-footer.vue'
|
||||||
|
import { deepClone, getRangeDate } from '@/components/da-dropdown/utils'
|
||||||
|
import { getCurDate } from '@/utils/util'
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
components: { picker, dropdownFooter },
|
components: { picker, dropdownFooter },
|
||||||
|
@ -56,6 +57,7 @@ export default defineComponent({
|
||||||
const daterange = ref(null)
|
const daterange = ref(null)
|
||||||
const datetag = ref('')
|
const datetag = ref('')
|
||||||
const dateTagList = ref([
|
const dateTagList = ref([
|
||||||
|
{ value: '-1', label: '今天' },
|
||||||
{ value: '-7', label: '本周' },
|
{ value: '-7', label: '本周' },
|
||||||
{ value: '-14', label: '上周' },
|
{ value: '-14', label: '上周' },
|
||||||
{ value: '-30', label: '本月' },
|
{ value: '-30', label: '本月' },
|
||||||
|
@ -70,15 +72,18 @@ export default defineComponent({
|
||||||
const item = deepClone(dropdownItem || null)
|
const item = deepClone(dropdownItem || null)
|
||||||
if (clearValue === true) {
|
if (clearValue === true) {
|
||||||
daterange.value = {
|
daterange.value = {
|
||||||
start: '',
|
start: getCurDate('start', 'YYYY-MM-DD'),
|
||||||
end: ''
|
end: getCurDate('end', 'YYYY-MM-DD')
|
||||||
}
|
}
|
||||||
datetag.value = ''
|
datetag.value = '-1'
|
||||||
} else {
|
} else {
|
||||||
daterange.value = {
|
daterange.value = {
|
||||||
start: item.value?.start || '',
|
start: item.value?.start || '',
|
||||||
end: item.value?.end || ''
|
end: item.value?.end || ''
|
||||||
}
|
}
|
||||||
|
if (item.value?.start && item.value?.end) {
|
||||||
|
datetag.value = '-1'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,197 @@
|
||||||
|
<template>
|
||||||
|
<view class="da-dropdown-cell">
|
||||||
|
<view
|
||||||
|
class="da-dropdown-cell-item"
|
||||||
|
:class="[item.checked ? 'is-actived' : '', item.disabled ? 'is-disabled' : '']"
|
||||||
|
v-for="(item, index) in cellOptions"
|
||||||
|
:key="index"
|
||||||
|
@click="handleSelect(item)"
|
||||||
|
>
|
||||||
|
<text class="da-dropdown-cell-item--label">{{ item.label }}</text>
|
||||||
|
<text class="da-dropdown-cell-item--suffix">{{ item.suffix }}</text>
|
||||||
|
<text class="da-dropdown-cell-item--check" v-if="item.checked && showIcon" />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<dropdown-footer @reset="handleReset" @confirm="handleConfirm" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { defineComponent, watch, ref } from 'vue'
|
||||||
|
import dropdownFooter from '../widgets/admin/dropdown-footer.vue'
|
||||||
|
import { deepClone } from '@/components/da-dropdown/utils'
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
components: { dropdownFooter },
|
||||||
|
props: {
|
||||||
|
dropdownItem: {
|
||||||
|
type: Object,
|
||||||
|
default: null
|
||||||
|
},
|
||||||
|
dropdownIndex: {
|
||||||
|
type: Number
|
||||||
|
}
|
||||||
|
},
|
||||||
|
emits: ['success', 'reset', 'confirm'],
|
||||||
|
setup(props, { emit }) {
|
||||||
|
const cellOptions = ref([])
|
||||||
|
const showIcon = ref(false)
|
||||||
|
const selectedItem = ref()
|
||||||
|
|
||||||
|
function initData(options, value) {
|
||||||
|
const list = deepClone(options)
|
||||||
|
for (let i = 0; i < list.length; i++) {
|
||||||
|
const item = list[i]
|
||||||
|
if (item.value === value) {
|
||||||
|
item.checked = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
item.checked = false
|
||||||
|
selectedItem.value = null
|
||||||
|
}
|
||||||
|
cellOptions.value = list
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleSelect(item) {
|
||||||
|
if (item.disabled) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// 取消所有选项的选中状态
|
||||||
|
cellOptions.value.forEach(item => {
|
||||||
|
item.checked = false
|
||||||
|
})
|
||||||
|
// 选中当前选项
|
||||||
|
item.checked = true
|
||||||
|
selectedItem.value = item
|
||||||
|
|
||||||
|
if (props.dropdownItem?.prop) {
|
||||||
|
const res = { [props.dropdownItem.prop]: item.value }
|
||||||
|
emit('success', res, item, props.dropdownIndex)
|
||||||
|
} else {
|
||||||
|
console.error(`菜单项${props.dropdownItem.title}未定义prop,返回内容失败`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function handleReset() {
|
||||||
|
initData(cellOptions.value)
|
||||||
|
emit('reset')
|
||||||
|
}
|
||||||
|
function handleConfirm() {
|
||||||
|
emit('confirm', selectedItem.value)
|
||||||
|
}
|
||||||
|
watch(
|
||||||
|
() => props.dropdownItem,
|
||||||
|
v => {
|
||||||
|
if (v?.options?.length) {
|
||||||
|
initData(v.options, v.value)
|
||||||
|
} else {
|
||||||
|
cellOptions.value = []
|
||||||
|
}
|
||||||
|
showIcon.value = v?.showIcon || false
|
||||||
|
},
|
||||||
|
{ immediate: true, deep: true }
|
||||||
|
)
|
||||||
|
|
||||||
|
return {
|
||||||
|
cellOptions,
|
||||||
|
showIcon,
|
||||||
|
handleSelect,
|
||||||
|
handleReset,
|
||||||
|
handleConfirm
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
// 下拉列表
|
||||||
|
.da-dropdown-cell {
|
||||||
|
--cell-height: 80rpx;
|
||||||
|
|
||||||
|
width: 100%;
|
||||||
|
max-height: 60vh;
|
||||||
|
overflow: hidden auto;
|
||||||
|
|
||||||
|
&-item {
|
||||||
|
box-sizing: border-box;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
width: 100%;
|
||||||
|
height: var(--cell-height);
|
||||||
|
padding: 0 24rpx;
|
||||||
|
overflow: hidden;
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: var(--dropdown-text-color);
|
||||||
|
white-space: nowrap;
|
||||||
|
border-bottom: 1rpx solid #dedede;
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--label {
|
||||||
|
flex-grow: 1;
|
||||||
|
max-width: 80%;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
|
||||||
|
// #ifdef H5
|
||||||
|
:deep(> span) {
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
// #endif
|
||||||
|
}
|
||||||
|
|
||||||
|
&--suffix {
|
||||||
|
flex-grow: 1;
|
||||||
|
margin-left: 10px;
|
||||||
|
overflow: hidden;
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #999;
|
||||||
|
text-align: right;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
|
||||||
|
// #ifdef H5
|
||||||
|
:deep(> span) {
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
// #endif
|
||||||
|
}
|
||||||
|
|
||||||
|
&--check {
|
||||||
|
display: flex;
|
||||||
|
flex-shrink: 0;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: var(--cell-height);
|
||||||
|
height: var(--cell-height);
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
/* stylelint-disable-next-line font-family-no-missing-generic-family-keyword */
|
||||||
|
font-family: 'iconfont' !important;
|
||||||
|
font-size: calc(var(--cell-height) / 3 * 2);
|
||||||
|
font-style: normal;
|
||||||
|
content: '\e677';
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.is-actived {
|
||||||
|
color: $blue1;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.is-disabled {
|
||||||
|
color: #aaa;
|
||||||
|
background: #efefef;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -4,7 +4,7 @@
|
||||||
<scroll-view class="da-dropdown-picker-view" scroll-y>
|
<scroll-view class="da-dropdown-picker-view" scroll-y>
|
||||||
<view
|
<view
|
||||||
class="da-dropdown-picker-item"
|
class="da-dropdown-picker-item"
|
||||||
:class="vr.checked ? 'is-actived' : ''"
|
:class="[vr.checked ? 'is-actived' : '', vr.disabled ? 'is-disabled' : '']"
|
||||||
v-for="(vr, vri) in viewRow[vci]"
|
v-for="(vr, vri) in viewRow[vci]"
|
||||||
:key="vri"
|
:key="vri"
|
||||||
@click="handleSelect(vr, vci, vri)"
|
@click="handleSelect(vr, vci, vri)"
|
||||||
|
@ -84,6 +84,7 @@ export default defineComponent({
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleSelect(item, colIndex, _rowIndex) {
|
function handleSelect(item, colIndex, _rowIndex) {
|
||||||
|
if (item.disabled) return
|
||||||
let lastItem = false
|
let lastItem = false
|
||||||
viewCol.value.splice(colIndex)
|
viewCol.value.splice(colIndex)
|
||||||
viewCol.value[colIndex] = item.value
|
viewCol.value[colIndex] = item.value
|
||||||
|
@ -242,6 +243,10 @@ export default defineComponent({
|
||||||
&.is-actived {
|
&.is-actived {
|
||||||
color: $blue-1;
|
color: $blue-1;
|
||||||
}
|
}
|
||||||
|
&.is-disabled {
|
||||||
|
cursor: not-allowed;
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -62,7 +62,7 @@ const emit = defineEmits(['handleCardClick'])
|
||||||
|
|
||||||
const parsePostionText = computed(() => {
|
const parsePostionText = computed(() => {
|
||||||
const { postId } = props.item
|
const { postId } = props.item
|
||||||
const ids = postId.split(',')
|
const ids = postId?.split(',')
|
||||||
const positionsList = [
|
const positionsList = [
|
||||||
{ name: '电销老师', id: 5 },
|
{ name: '电销老师', id: 5 },
|
||||||
{ name: '招生老师', id: 6 }
|
{ name: '招生老师', id: 6 }
|
||||||
|
@ -93,7 +93,7 @@ const data = computed(() => {
|
||||||
})
|
})
|
||||||
const parsePostIds = computed(() => {
|
const parsePostIds = computed(() => {
|
||||||
const { postId } = props.item
|
const { postId } = props.item
|
||||||
return postId.split(',').map(Number)
|
return postId?.split(',').map(Number)
|
||||||
})
|
})
|
||||||
const containPostIds = computed(() => {
|
const containPostIds = computed(() => {
|
||||||
return parsePostIds.value.includes(5) && parsePostIds.value.includes(6)
|
return parsePostIds.value.includes(5) && parsePostIds.value.includes(6)
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
<u-dropdown-item title="组织">
|
<u-dropdown-item title="组织">
|
||||||
<view class="bg-white">
|
<view class="bg-white">
|
||||||
<DropdownPicker
|
<DropdownPicker
|
||||||
:dropdownItem="dropdownMenuList"
|
:dropdownItem="dropdownMenuOrgList"
|
||||||
@reset="() => handleReset('organization')"
|
@reset="() => handleReset('organization')"
|
||||||
@confirm="value => handleConfirm('organization', value)"
|
@confirm="value => handleConfirm('organization', value)"
|
||||||
/>
|
/>
|
||||||
|
@ -55,6 +55,7 @@ import telesaleCard from './components/telesale-card.vue'
|
||||||
import dateDropdownPicker from '@/components/date-dropdown/daterange.vue'
|
import dateDropdownPicker from '@/components/date-dropdown/daterange.vue'
|
||||||
import { useZPaging } from '@/hooks/useZPaging'
|
import { useZPaging } from '@/hooks/useZPaging'
|
||||||
import { apiTeleClueList } from '@/api/clue'
|
import { apiTeleClueList } from '@/api/clue'
|
||||||
|
import { apiOrganizationAllList } from '@/api/admin'
|
||||||
|
|
||||||
const dropdownMenuList2 = {
|
const dropdownMenuList2 = {
|
||||||
showQuick: true,
|
showQuick: true,
|
||||||
|
@ -65,31 +66,7 @@ const dropdownMenuList2 = {
|
||||||
// value: { start: '2022-01-01', end: '2022-02-01' },
|
// value: { start: '2022-01-01', end: '2022-02-01' },
|
||||||
}
|
}
|
||||||
const postId = ref()
|
const postId = ref()
|
||||||
const dropdownMenuList = [
|
const dropdownMenuOrgList = ref([])
|
||||||
{
|
|
||||||
label: '级联X1',
|
|
||||||
value: '1',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
label: '级联X11',
|
|
||||||
value: '11',
|
|
||||||
children: [
|
|
||||||
{ label: '级联X111', value: '111' },
|
|
||||||
{ label: '级联X122', value: '122' }
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{ label: '级联X12', value: '12' }
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: '级联X2',
|
|
||||||
value: '2',
|
|
||||||
children: [
|
|
||||||
{ label: '级联X21', value: '21' },
|
|
||||||
{ label: '级联X22', value: '22' }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
const queryParams = ref({
|
const queryParams = ref({
|
||||||
likeWork: ''
|
likeWork: ''
|
||||||
|
@ -140,6 +117,40 @@ const handleReset = (type: string) => {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
const fetchAllOrganizationList = async () => {
|
||||||
|
try {
|
||||||
|
const result = await apiOrganizationAllList()
|
||||||
|
dropdownMenuOrgList.value = renameFields(result)
|
||||||
|
console.log(dropdownMenuOrgList.value)
|
||||||
|
} catch (error) {}
|
||||||
|
}
|
||||||
|
const renameFields = (data: any[]): any[] => {
|
||||||
|
return data.map(item => {
|
||||||
|
const newItem = { ...item }
|
||||||
|
newItem.label = item.name
|
||||||
|
newItem.value = item.id
|
||||||
|
if (newItem.organizationVoList) {
|
||||||
|
newItem.children = renameFields(newItem.organizationVoList)
|
||||||
|
delete newItem.organizationVoList
|
||||||
|
}
|
||||||
|
if (newItem.userVos) {
|
||||||
|
newItem.userVos.forEach(item => {
|
||||||
|
item.label = item.username
|
||||||
|
item.value = item.id
|
||||||
|
})
|
||||||
|
newItem.children = newItem.children
|
||||||
|
? [...newItem.children, ...newItem.userVos]
|
||||||
|
: newItem.userVos
|
||||||
|
delete newItem.userVos
|
||||||
|
}
|
||||||
|
if (!newItem.children.length) {
|
||||||
|
newItem.disabled = true
|
||||||
|
}
|
||||||
|
return newItem
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fetchAllOrganizationList()
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss"></style>
|
<style scoped lang="scss"></style>
|
||||||
|
|
|
@ -29,6 +29,8 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref } from 'vue'
|
import { ref } from 'vue'
|
||||||
import card from '../../card.vue'
|
import card from '../../card.vue'
|
||||||
|
import { IForm } from '../index.vue'
|
||||||
|
import { clueStatusApi } from '@/api/admin'
|
||||||
|
|
||||||
interface ICluseStatus {
|
interface ICluseStatus {
|
||||||
label: string
|
label: string
|
||||||
|
@ -36,19 +38,26 @@ interface ICluseStatus {
|
||||||
}
|
}
|
||||||
const data = ref<ICluseStatus[]>([])
|
const data = ref<ICluseStatus[]>([])
|
||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
const fetchData = () => {
|
const dataMap: Record<string, string> = {
|
||||||
|
unclaimedCount: '待领取',
|
||||||
|
conversionCount: '转化中',
|
||||||
|
addedCount: '已添加',
|
||||||
|
abnormalCount: '异常待处理',
|
||||||
|
tradedCount: '已成交',
|
||||||
|
failCount: '已战败'
|
||||||
|
}
|
||||||
|
const fetchData = async (payload: IForm) => {
|
||||||
loading.value = true
|
loading.value = true
|
||||||
setTimeout(() => {
|
try {
|
||||||
data.value = [
|
const result = await clueStatusApi(payload)
|
||||||
{ label: '待领取', value: 28 },
|
data.value = Object.keys(dataMap).map(item => {
|
||||||
{ label: '转化中', value: 12 },
|
return {
|
||||||
{ label: '已添加', value: 53 },
|
label: dataMap[item],
|
||||||
{ label: '异常待处理', value: 56 },
|
value: result[item] || 0
|
||||||
{ label: '已成交', value: 12 },
|
}
|
||||||
{ label: '已战败', value: 100 }
|
|
||||||
]
|
|
||||||
loading.value = false
|
|
||||||
})
|
})
|
||||||
|
loading.value = false
|
||||||
|
} catch (error) {}
|
||||||
}
|
}
|
||||||
defineExpose({
|
defineExpose({
|
||||||
fetchData
|
fetchData
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref } from 'vue'
|
import { ref } from 'vue'
|
||||||
import card from '../../card.vue'
|
import card from '../../card.vue'
|
||||||
|
import { IForm } from '../index.vue'
|
||||||
|
|
||||||
interface IConvertedData {
|
interface IConvertedData {
|
||||||
name: string
|
name: string
|
||||||
|
@ -32,7 +33,7 @@ interface IConvertedData {
|
||||||
}
|
}
|
||||||
const data = ref<IConvertedData[]>([])
|
const data = ref<IConvertedData[]>([])
|
||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
const fetchData = () => {
|
const fetchData = (payload: IForm) => {
|
||||||
loading.value = true
|
loading.value = true
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
data.value = [
|
data.value = [
|
||||||
|
|
|
@ -25,6 +25,8 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref } from 'vue'
|
import { ref } from 'vue'
|
||||||
import card from '../../card.vue'
|
import card from '../../card.vue'
|
||||||
|
import { apiDataOverview } from '@/api/admin'
|
||||||
|
import { IForm } from '../index.vue'
|
||||||
|
|
||||||
interface DataItem {
|
interface DataItem {
|
||||||
label: string
|
label: string
|
||||||
|
@ -32,19 +34,28 @@ interface DataItem {
|
||||||
}
|
}
|
||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
const data = ref<DataItem[]>([])
|
const data = ref<DataItem[]>([])
|
||||||
const fetchData = () => {
|
const dataMap: Record<string, string> = {
|
||||||
|
followUpRecord: '新增跟进',
|
||||||
|
newCustomer: '新增客户',
|
||||||
|
transactionClient: '成交客户',
|
||||||
|
convertingClient: '转化中客户',
|
||||||
|
exceptionPending: '异常待处理',
|
||||||
|
defeatedClient: '战败客户'
|
||||||
|
}
|
||||||
|
|
||||||
|
const fetchData = async (payload: IForm) => {
|
||||||
|
if (data.value.length > 0) data.value = []
|
||||||
loading.value = true
|
loading.value = true
|
||||||
setTimeout(() => {
|
try {
|
||||||
data.value = [
|
const result = await apiDataOverview(payload)
|
||||||
{ label: '新增跟进', value: 368 },
|
data.value = Object.keys(dataMap).map(key => {
|
||||||
{ label: '新增客户', value: 368 },
|
return {
|
||||||
{ label: '成交客户', value: 368 },
|
label: dataMap[key],
|
||||||
{ label: '转化中客户', value: 368 },
|
value: result[key] || 0
|
||||||
{ label: '异常待处理', value: 368 },
|
}
|
||||||
{ label: '战败客户', value: 368 }
|
})
|
||||||
]
|
} catch (error) {}
|
||||||
loading.value = false
|
loading.value = false
|
||||||
}, 500)
|
|
||||||
}
|
}
|
||||||
defineExpose({
|
defineExpose({
|
||||||
fetchData
|
fetchData
|
||||||
|
|
|
@ -1,11 +1,20 @@
|
||||||
<template>
|
<template>
|
||||||
<view class="flex flex-col gap-[24rpx] mb-[20rpx]">
|
<view class="flex flex-col gap-[24rpx] mb-[20rpx]">
|
||||||
<view class="bg-white">
|
<view class="bg-white">
|
||||||
<u-dropdown ref="uDropdownRef" menu-icon="arrow-down-fill" :isFlex="false">
|
<u-dropdown ref="uDropdownRef" menu-icon="arrow-down-fill">
|
||||||
|
<u-dropdown-item title="团队">
|
||||||
|
<view class="bg-white">
|
||||||
|
<selectDropdown
|
||||||
|
:dropdownItem="dropdownMenuTeamList"
|
||||||
|
@reset="() => handleReset('team')"
|
||||||
|
@confirm="value => handleConfirm('team', value)"
|
||||||
|
/>
|
||||||
|
</view>
|
||||||
|
</u-dropdown-item>
|
||||||
<u-dropdown-item title="组织">
|
<u-dropdown-item title="组织">
|
||||||
<view class="bg-white">
|
<view class="bg-white">
|
||||||
<DropdownPicker
|
<selectDropdown
|
||||||
:dropdownItem="dropdownMenuList"
|
:dropdownItem="dropdownMenuAllOrgaList"
|
||||||
@reset="() => handleReset('organization')"
|
@reset="() => handleReset('organization')"
|
||||||
@confirm="value => handleConfirm('organization', value)"
|
@confirm="value => handleConfirm('organization', value)"
|
||||||
/>
|
/>
|
||||||
|
@ -14,7 +23,7 @@
|
||||||
<u-dropdown-item title="日期">
|
<u-dropdown-item title="日期">
|
||||||
<view class="bg-white p-[20rpx]">
|
<view class="bg-white p-[20rpx]">
|
||||||
<dateDropdownPicker
|
<dateDropdownPicker
|
||||||
:dropdownItem="dropdownMenuList2"
|
:dropdownItem="dropdownMenuDateList"
|
||||||
@reset="() => handleReset('date')"
|
@reset="() => handleReset('date')"
|
||||||
@confirm="value => handleConfirm('date', value)"
|
@confirm="value => handleConfirm('date', value)"
|
||||||
/>
|
/>
|
||||||
|
@ -35,74 +44,142 @@ import dataOverview from './components/data-overview.vue'
|
||||||
import convertedOverview from './components/converted-overview.vue'
|
import convertedOverview from './components/converted-overview.vue'
|
||||||
import rank from './components/rank.vue'
|
import rank from './components/rank.vue'
|
||||||
import clueStatus from './components/clue-status.vue'
|
import clueStatus from './components/clue-status.vue'
|
||||||
import DropdownPicker from '../orga-picker.vue'
|
|
||||||
import dateDropdownPicker from '@/components/date-dropdown/daterange.vue'
|
import dateDropdownPicker from '@/components/date-dropdown/daterange.vue'
|
||||||
|
import selectDropdown from '@/components/select-dropdown/index.vue'
|
||||||
|
import { apiOrganizationByIdList, apiOrganizationList, apiOrganizationTeamList } from '@/api/admin'
|
||||||
|
import { formateDate, getCurDate } from '@/utils/util'
|
||||||
|
|
||||||
|
export interface IForm {
|
||||||
|
organizationId: number | null
|
||||||
|
createTimeStart: string
|
||||||
|
createTimeEnd: string
|
||||||
|
userId: string
|
||||||
|
}
|
||||||
const clueStatusRef = ref<InstanceType<typeof clueStatus>>()
|
const clueStatusRef = ref<InstanceType<typeof clueStatus>>()
|
||||||
const rankRef = ref<InstanceType<typeof rank>>()
|
const rankRef = ref<InstanceType<typeof rank>>()
|
||||||
const convertedOverviewRef = ref<InstanceType<typeof convertedOverview>>()
|
const convertedOverviewRef = ref<InstanceType<typeof convertedOverview>>()
|
||||||
const dataOverviewRef = ref<InstanceType<typeof dataOverview>>()
|
const dataOverviewRef = ref<InstanceType<typeof dataOverview>>()
|
||||||
const uDropdownRef = ref()
|
const uDropdownRef = ref()
|
||||||
const dropdownMenuList = [
|
const organizationList = ref([])
|
||||||
{
|
const defaultValue = ref() //保存组织默认值
|
||||||
label: '级联X1',
|
const form = ref<IForm>({
|
||||||
value: '1',
|
organizationId: null,
|
||||||
children: [
|
createTimeStart: getCurDate('start'),
|
||||||
{
|
createTimeEnd: getCurDate('end'),
|
||||||
label: '级联X11',
|
userId: ''
|
||||||
value: '11'
|
})
|
||||||
},
|
const dropdownMenuDateList = {
|
||||||
{ label: '级联X12', value: '12' }
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: '级联X2',
|
|
||||||
value: '2',
|
|
||||||
children: [
|
|
||||||
{ label: '级联X21', value: '21' },
|
|
||||||
{ label: '级联X22', value: '22' }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
const dropdownMenuList2 = {
|
|
||||||
showQuick: true,
|
showQuick: true,
|
||||||
title: '日期范围',
|
title: '日期范围',
|
||||||
type: 'daterange',
|
type: 'daterange',
|
||||||
prop: 'god6'
|
prop: 'god6',
|
||||||
// 默认选中 2022-01-01到2022-02-01
|
value: { start: getCurDate('start', 'YYYY-MM-DD'), end: getCurDate('end', 'YYYY-MM-DD') }
|
||||||
// value: { start: '2022-01-01', end: '2022-02-01' },
|
|
||||||
}
|
}
|
||||||
|
const dropdownMenuTeamList = ref({
|
||||||
|
title: '下拉',
|
||||||
|
type: 'cell',
|
||||||
|
prop: 'god1',
|
||||||
|
showAll: true,
|
||||||
|
showIcon: true,
|
||||||
|
options: []
|
||||||
|
})
|
||||||
|
const dropdownMenuAllOrgaList = ref({
|
||||||
|
title: '下拉',
|
||||||
|
type: 'cell',
|
||||||
|
prop: 'god1',
|
||||||
|
showAll: true,
|
||||||
|
showIcon: true,
|
||||||
|
options: []
|
||||||
|
})
|
||||||
|
// 查询条件
|
||||||
const handleConfirm = (type: string, item) => {
|
const handleConfirm = (type: string, item) => {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 'organization':
|
case 'organization':
|
||||||
console.log(item)
|
console.log(item)
|
||||||
break
|
break
|
||||||
case 'date':
|
case 'date':
|
||||||
console.log(item)
|
form.value.createTimeStart = formateDate(item.start, 'start')
|
||||||
|
form.value.createTimeEnd = formateDate(item.end, 'end')
|
||||||
|
break
|
||||||
|
case 'team':
|
||||||
|
form.value.organizationId = item.value
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
fetchAllData()
|
||||||
|
closeDropDown()
|
||||||
}
|
}
|
||||||
|
// 重置条件
|
||||||
const handleReset = (type: string) => {
|
const handleReset = (type: string) => {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 'organization':
|
case 'organization':
|
||||||
break
|
break
|
||||||
case 'date':
|
case 'date':
|
||||||
|
form.value.createTimeStart = getCurDate('start')
|
||||||
|
form.value.createTimeEnd = getCurDate('end')
|
||||||
|
break
|
||||||
|
case 'team':
|
||||||
|
form.value.organizationId = defaultValue.value
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
fetchAllData()
|
||||||
|
closeDropDown()
|
||||||
}
|
}
|
||||||
const closeDropDown = () => {
|
const closeDropDown = () => {
|
||||||
uDropdownRef.value.close()
|
uDropdownRef.value.close()
|
||||||
}
|
}
|
||||||
onMounted(() => {
|
|
||||||
dataOverviewRef.value?.fetchData()
|
onMounted(async () => {
|
||||||
convertedOverviewRef.value?.fetchData()
|
await fetchOrganizationList()
|
||||||
rankRef.value?.fetchData()
|
fetchAllData()
|
||||||
clueStatusRef.value?.fetchData()
|
|
||||||
})
|
})
|
||||||
|
const fetchAllData = () => {
|
||||||
|
dataOverviewRef.value?.fetchData(form.value)
|
||||||
|
convertedOverviewRef.value?.fetchData(form.value)
|
||||||
|
rankRef.value?.fetchData(form.value)
|
||||||
|
clueStatusRef.value?.fetchData(form.value)
|
||||||
|
}
|
||||||
|
// 获取主账号下的所有组织架构
|
||||||
|
const fetchOrganizationList = async () => {
|
||||||
|
try {
|
||||||
|
const result = await apiOrganizationList()
|
||||||
|
organizationList.value = result ?? []
|
||||||
|
if (result.length > 0) {
|
||||||
|
form.value.organizationId = result[0].id
|
||||||
|
defaultValue.value = result[0].id
|
||||||
|
}
|
||||||
|
} catch (error) {}
|
||||||
|
}
|
||||||
|
// 获取团队列表
|
||||||
|
const fetchTeamList = async () => {
|
||||||
|
try {
|
||||||
|
const result = await apiOrganizationTeamList()
|
||||||
|
dropdownMenuTeamList.value.options =
|
||||||
|
result.map(item => {
|
||||||
|
return {
|
||||||
|
label: item.name,
|
||||||
|
value: item.id
|
||||||
|
}
|
||||||
|
}) ?? []
|
||||||
|
} catch (error) {}
|
||||||
|
}
|
||||||
|
// 获取组织列表
|
||||||
|
const fetchAllOrganizationList = async () => {
|
||||||
|
try {
|
||||||
|
const result = await apiOrganizationByIdList()
|
||||||
|
dropdownMenuAllOrgaList.value.options =
|
||||||
|
result.map(item => {
|
||||||
|
return {
|
||||||
|
label: item.name,
|
||||||
|
value: item.id
|
||||||
|
}
|
||||||
|
}) ?? []
|
||||||
|
} catch (error) {}
|
||||||
|
}
|
||||||
|
fetchTeamList()
|
||||||
|
fetchAllOrganizationList()
|
||||||
</script>
|
</script>
|
||||||
<style scoped></style>
|
<style scoped></style>
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { apiCluseDetail } from '@/api/clue'
|
import { apiCluseDetail } from '@/api/clue'
|
||||||
|
import { IForm } from '@/components/widgets/admin/team/index.vue'
|
||||||
import { computed, ref, shallowRef } from 'vue'
|
import { computed, ref, shallowRef } from 'vue'
|
||||||
|
|
||||||
// 获取线索详情
|
// 获取线索详情
|
||||||
|
@ -72,7 +73,7 @@ export function useRank({ width }: { width: number }) {
|
||||||
resolve(tabs.value)
|
resolve(tabs.value)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
const fetchData = async () => {
|
const fetchData = async (payload: IForm) => {
|
||||||
await fetchTabs()
|
await fetchTabs()
|
||||||
console.log(activeTab.value)
|
console.log(activeTab.value)
|
||||||
loading.value = true
|
loading.value = true
|
||||||
|
|
|
@ -120,7 +120,7 @@ export const setNextRoute = () => {
|
||||||
const { userInfo } = userStore
|
const { userInfo } = userStore
|
||||||
const ind = cache.get(ROLEINDEX) || 0
|
const ind = cache.get(ROLEINDEX) || 0
|
||||||
const obj = roles[ind]
|
const obj = roles[ind]
|
||||||
if (userInfo.postIds == 0 && obj.ids.length == 0) {
|
if (userInfo.postIds == 0 && obj.ids.length == 0 && userInfo.masterAccount == 1) {
|
||||||
tabBarStore.setTabBarList(obj.tabBarList)
|
tabBarStore.setTabBarList(obj.tabBarList)
|
||||||
uni.reLaunch({
|
uni.reLaunch({
|
||||||
url: obj.tabBarList[0].path
|
url: obj.tabBarList[0].path
|
||||||
|
|
|
@ -1,12 +1,5 @@
|
||||||
{
|
{
|
||||||
"pages": [
|
"pages": [
|
||||||
{
|
|
||||||
"path": "pages/admin/home/index",
|
|
||||||
"style": {
|
|
||||||
"navigationBarTitleText": ""
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
{
|
||||||
"path": "pages/index/index",
|
"path": "pages/index/index",
|
||||||
"style": {
|
"style": {
|
||||||
|
@ -14,6 +7,13 @@
|
||||||
"navigationStyle": "custom"
|
"navigationStyle": "custom"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"path": "pages/admin/home/index",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
"path": "pages/telesale/home/index",
|
"path": "pages/telesale/home/index",
|
||||||
"style": {
|
"style": {
|
||||||
|
|
|
@ -14,9 +14,9 @@ onLoad(() => {
|
||||||
// 已经登录 => 首页
|
// 已经登录 => 首页
|
||||||
setNextRoute()
|
setNextRoute()
|
||||||
} else {
|
} else {
|
||||||
// uni.navigateTo({
|
uni.navigateTo({
|
||||||
// url: '/bundle/pages/login/login'
|
url: '/bundle/pages/login/login'
|
||||||
// })
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -397,3 +397,12 @@ export function throttle(fn: any, gapTime: number) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// 获取今天
|
||||||
|
export function getCurDate(type: string, format = 'YYYY-MM-DD HH:mm:ss') {
|
||||||
|
return formateDate('today', type, format)
|
||||||
|
}
|
||||||
|
// 格式化日期
|
||||||
|
export function formateDate(value: string, type: string, format = 'YYYY-MM-DD HH:mm:ss') {
|
||||||
|
const date = value == 'today' ? dayjs() : dayjs(value)
|
||||||
|
return type == 'start' ? date.startOf('day').format(format) : date.endOf('day').format(format)
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue