【招生小程序】 新增# 1、对接电销的添加跟进、跟进记录列表;2、对接招生的添加进展;3、修复:刷新页面时底部导航栏显示首页路径错误;4、修复:点击底部导航栏中的总结模板后,再点击首页后,页面无反应的问题
parent
2de7edf2d4
commit
30d61360fa
|
@ -6,7 +6,7 @@
|
|||
# @FilePath: \chargingpile-uniapp\.env.development
|
||||
###
|
||||
# 请求域名
|
||||
# VITE_APP_BASE_URL= 'http://120.77.216.5:8084'
|
||||
VITE_APP_BASE_URL="http://192.168.111.98:8084"
|
||||
# VITE_APP_BASE_URL="https://wechat.szcxj2024.com"
|
||||
# VITE_APP_BASE_URL= 'http://192.168.111.5:8086'
|
||||
VITE_APP_BASE_URL="http://192.168.111.98:8086"
|
||||
# VITE_APP_BASE_URL="https://124.220.209.120:8086"
|
||||
# VITE_APP_SOCKET_URL = 'wss://front.yuegoodlife.com'
|
23
src/App.vue
23
src/App.vue
|
@ -13,7 +13,7 @@ import { getAllDict } from '@/hooks/useDictOptions'
|
|||
|
||||
const appStore = useAppStore()
|
||||
const userStore = useUserStore()
|
||||
// getAllDict()
|
||||
getAllDict()
|
||||
|
||||
onLaunch(async () => {
|
||||
appStore.getSystemInfoFn()
|
||||
|
@ -24,28 +24,9 @@ onLaunch(async () => {
|
|||
onShow(async () => {
|
||||
const token = userStore.token
|
||||
if (token) {
|
||||
await appStore.getConfig()
|
||||
// await appStore.getConfig()
|
||||
appStore.updateLocation()
|
||||
} else appStore.closeTimer()
|
||||
})
|
||||
|
||||
// function genDates() {
|
||||
// const weekdays = ['日', '一', '二', '三', '四', '五', '六']
|
||||
// const currentDate = new Date()
|
||||
// const currentDayOfWeek = currentDate.getDay()
|
||||
// let preDateOfWeek = currentDate.getDate() - 1
|
||||
// const daysInRange = []
|
||||
// for (let i = currentDayOfWeek; i <= weekdays.length - 1; i++) {
|
||||
// preDateOfWeek = preDateOfWeek + 1
|
||||
// daysInRange.push(preDateOfWeek)
|
||||
// }
|
||||
// let currentDateOfWeek = currentDate.getDate()
|
||||
// for (let i = 0; i <= weekdays.length - daysInRange.length; i++) {
|
||||
// currentDateOfWeek = currentDateOfWeek - 1
|
||||
// daysInRange.unshift(currentDateOfWeek)
|
||||
// }
|
||||
// console.log(daysInRange)
|
||||
// }
|
||||
// genDates()
|
||||
</script>
|
||||
<style lang="scss"></style>
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
import request from '@/utils/request'
|
||||
|
||||
// 新增线索
|
||||
export function apiAddCluse(params: any) {
|
||||
return request.post({ url: '/clue/add', data: params })
|
||||
}
|
||||
// 线索列表
|
||||
export function apiCluseList(params: any) {
|
||||
return request.get({ url: '/clue/list', data: params })
|
||||
}
|
||||
// 领取线索
|
||||
export function apiGetCluse(params: any) {
|
||||
return request.post({ url: '/clue/grabTheOrder', data: params })
|
||||
}
|
||||
// 线索详情
|
||||
export function apiCluseDetail(params: any) {
|
||||
return request.get({ url: '/clue/detail', data: params })
|
||||
}
|
||||
// 添加进展
|
||||
export function apiAddCluseProgress(params: any) {
|
||||
return request.post({ url: '/clue/addProgress', data: params })
|
||||
}
|
||||
// 转化完成
|
||||
export function apiCompleteCluse(params: any) {
|
||||
return request.post({ url: '/clue/conversionCompleted', data: params })
|
||||
}
|
||||
// 修改备注
|
||||
export function apiEditRemark(params: any) {
|
||||
return request.post({ url: '/clue/modifyRemarks', data: params })
|
||||
}
|
||||
// 修改跟进
|
||||
export function apiEditClue(params: any) {
|
||||
return request.post({ url: '/clue/edit', data: params })
|
||||
}
|
|
@ -2,10 +2,13 @@ import request from '@/utils/request'
|
|||
|
||||
// 所有字典以及字典下的所有数据
|
||||
export function dictAllDataList() {
|
||||
return request.get({
|
||||
url: '/setting/dict/type/allDataList',
|
||||
data: {
|
||||
pageSize: 60
|
||||
}
|
||||
})
|
||||
return request.get(
|
||||
{
|
||||
url: '/setting/dict/type/allDataList',
|
||||
data: {
|
||||
pageSize: 60
|
||||
}
|
||||
},
|
||||
{ isAuth: true }
|
||||
)
|
||||
}
|
||||
|
|
|
@ -193,7 +193,7 @@ async function handleLogin(e) {
|
|||
scene: LoginTypeEnum.MNP,
|
||||
iv: e.detail.iv,
|
||||
encryptedData: e.detail.encryptedData,
|
||||
channel: ChannelEnum.STAFF_PLATFORM
|
||||
channel: ChannelEnum.USER_PLATFORM
|
||||
})
|
||||
// 保存登录数据
|
||||
loginData.value = data
|
||||
|
@ -228,14 +228,14 @@ async function loginHandle(data: any) {
|
|||
// 获取用户信息
|
||||
await userStore.getUser()
|
||||
// 获取系统配置
|
||||
await appStore.getConfig()
|
||||
// await appStore.getConfig()
|
||||
|
||||
// 显示登录成功提示
|
||||
uni.$u.toast('登录成功')
|
||||
|
||||
// 隐藏登录加载框
|
||||
uni.hideLoading()
|
||||
appStore.setFirstLogin(true)
|
||||
// appStore.setFirstLogin(true)
|
||||
const { userInfo } = userStore
|
||||
if (userInfo.roles?.length > 1) {
|
||||
uni.redirectTo({
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
<view class="bg-[#FAFAFE]">
|
||||
<view class="bg-white px-[32rpx]">
|
||||
<TForm ref="tForm" :model="form" :rules="rules" errorType="toast">
|
||||
<TFormItem prop="publishName">
|
||||
<TFormItem prop="recruitTeacherName">
|
||||
<TInputField
|
||||
v-model="form.publishName"
|
||||
v-model="form.recruitTeacherName"
|
||||
label="发布人"
|
||||
placeholder=""
|
||||
inputAlign="left"
|
||||
|
@ -13,9 +13,9 @@
|
|||
:labelWidth="100"
|
||||
/>
|
||||
</TFormItem>
|
||||
<TFormItem prop="clientName">
|
||||
<TFormItem prop="studentName">
|
||||
<TInputField
|
||||
v-model="form.clientName"
|
||||
v-model="form.studentName"
|
||||
label="客户姓名"
|
||||
placeholder=""
|
||||
inputAlign="left"
|
||||
|
@ -24,9 +24,9 @@
|
|||
:labelWidth="100"
|
||||
/>
|
||||
</TFormItem>
|
||||
<TFormItem prop="mobile">
|
||||
<TFormItem prop="phone">
|
||||
<TInputField
|
||||
v-model="form.mobile"
|
||||
v-model="form.phone"
|
||||
label="电话"
|
||||
placeholder=""
|
||||
inputAlign="left"
|
||||
|
@ -35,8 +35,9 @@
|
|||
:labelWidth="100"
|
||||
/>
|
||||
</TFormItem>
|
||||
<TFormItem prop="desc">
|
||||
<TFormItem prop="basicInformation">
|
||||
<TTextareaField
|
||||
v-model="form.basicInformation"
|
||||
label="基本情况"
|
||||
placeholder=""
|
||||
autoHeight
|
||||
|
@ -45,9 +46,9 @@
|
|||
:labelWidth="100"
|
||||
/>
|
||||
</TFormItem>
|
||||
<TFormItem prop="status">
|
||||
<TFormItem prop="state">
|
||||
<TMultiSelect
|
||||
v-model="form.status"
|
||||
v-model="form.state"
|
||||
label="状态"
|
||||
:groupList="statusList"
|
||||
:labelWidth="100"
|
||||
|
@ -56,50 +57,84 @@
|
|||
</TForm>
|
||||
</view>
|
||||
<view class="px-[60rpx]">
|
||||
<u-button class="btn" color="#0E66FB" shape="circle" @click="handleSubmit">
|
||||
提交
|
||||
<u-button
|
||||
class="btn"
|
||||
color="#0E66FB"
|
||||
shape="circle"
|
||||
:loading="loading"
|
||||
@click="handleSubmit"
|
||||
>
|
||||
提交{{ form.state }}
|
||||
</u-button>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { apiAddCluseProgress, apiCluseEdit } from '@/api/clue'
|
||||
import { stateEnum } from '@/enums'
|
||||
import { useClueDetail } from '@/hooks/useCommon'
|
||||
import { toast } from '@/utils/util'
|
||||
import { onLoad } from '@dcloudio/uni-app'
|
||||
import { shallowRef } from 'vue'
|
||||
import { ref } from 'vue'
|
||||
|
||||
const { fetchClueDetail, clueDetailInfo } = useClueDetail()
|
||||
|
||||
const id = ref('')
|
||||
|
||||
const tForm = ref()
|
||||
const form = ref({
|
||||
publishName: '',
|
||||
clientName: '张三',
|
||||
mobile: '',
|
||||
desc: '',
|
||||
status: ''
|
||||
id: '',
|
||||
recruitTeacherName: '',
|
||||
studentName: '',
|
||||
phone: '',
|
||||
basicInformation: '',
|
||||
state: null
|
||||
})
|
||||
const rules = {
|
||||
status: [{ required: true, message: '请选择状态' }]
|
||||
state: [{ required: true, message: '请选择状态' }]
|
||||
}
|
||||
const statusList = shallowRef([
|
||||
{ label: '账号已添加', value: 1 },
|
||||
{ label: '账号不存在', value: 2 },
|
||||
{ label: '账号未通过', value: 3 }
|
||||
{ label: '账号已添加', value: stateEnum.ADD_RELATION },
|
||||
{ label: '账号不存在', value: stateEnum.NO_EXIST },
|
||||
{ label: '账号未通过', value: stateEnum.UN_PASS }
|
||||
])
|
||||
onLoad(option => {
|
||||
onLoad(async option => {
|
||||
if (option?.id) {
|
||||
id.value = option.id
|
||||
await fetchClueDetail(id.value)
|
||||
setFormData()
|
||||
}
|
||||
})
|
||||
const loading = ref(false)
|
||||
const handleSubmit = () => {
|
||||
tForm.value
|
||||
.validate()
|
||||
.then(valid => {
|
||||
.then(async valid => {
|
||||
if (valid) {
|
||||
console.log('校验通过')
|
||||
loading.value = true
|
||||
try {
|
||||
const data = {
|
||||
id: form.value.id,
|
||||
state: form.value.state
|
||||
}
|
||||
await apiAddCluseProgress(data)
|
||||
toast('添加进展成功')
|
||||
uni.navigateBack()
|
||||
uni.$emit('refreshPage')
|
||||
} catch (error) {}
|
||||
}
|
||||
})
|
||||
.catch(() => {})
|
||||
loading.value = false
|
||||
}
|
||||
const setFormData = () => {
|
||||
for (const key in clueDetailInfo.value) {
|
||||
if (Object.prototype.hasOwnProperty.call(form.value, key)) {
|
||||
form.value[key] = clueDetailInfo.value[key]
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
flex-direction: column;
|
||||
.wrapper {
|
||||
flex: 1;
|
||||
background-color: #fafafe;
|
||||
@apply flex flex-col;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -120,6 +120,13 @@ export default defineComponent({
|
|||
})
|
||||
})
|
||||
}
|
||||
const resetFields = () => {
|
||||
instance.proxy.children.map(child => {
|
||||
const prop = child.prop
|
||||
const value = uni.$u.getProperty(originalModel.value, prop)
|
||||
uni.$u.setProperty(props.model, prop, value)
|
||||
})
|
||||
}
|
||||
watch(
|
||||
() => props.rules,
|
||||
newVal => {
|
||||
|
@ -139,7 +146,8 @@ export default defineComponent({
|
|||
)
|
||||
return {
|
||||
children: [],
|
||||
validate
|
||||
validate,
|
||||
resetFields
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
:inputAlign="inputAlign"
|
||||
:readonly="readonly"
|
||||
:maxlength="maxlength"
|
||||
placeholderStyle="color: '#7c7e82'"
|
||||
></u-input>
|
||||
</view>
|
||||
</template>
|
||||
|
|
|
@ -58,7 +58,6 @@ const innerValue = ref(props.modelValue)
|
|||
const handleSelectedItem = (val: number) => {
|
||||
emit('update:modelValue', val)
|
||||
innerValue.value = val
|
||||
console.log(val)
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -58,7 +58,7 @@ const props = defineProps({
|
|||
default: false
|
||||
}
|
||||
})
|
||||
const emit = defineEmits(['update:modelValue'])
|
||||
const emit = defineEmits(['update:modelValue', 'onInput'])
|
||||
|
||||
const innerValue = ref('')
|
||||
|
||||
|
@ -96,6 +96,7 @@ const isShowClear = computed(() => {
|
|||
const onInput = e => {
|
||||
innerValue.value = e.detail.value
|
||||
emit('update:modelValue', innerValue.value)
|
||||
emit('onInput')
|
||||
}
|
||||
const onClear = () => {
|
||||
innerValue.value = ''
|
||||
|
|
|
@ -47,8 +47,8 @@ const { roles } = useRoleData()
|
|||
const emit = defineEmits(['update:modelValue', 'close'])
|
||||
const activeRole = ref(props.modelValue)
|
||||
const visible = ref(false)
|
||||
let currentRoutes = getCurrentPages() // 获取当前打开过的页面路由数组
|
||||
let currentRoute = currentRoutes[currentRoutes.length - 1].route //获取当前页面路由
|
||||
const currentRoutes = getCurrentPages() // 获取当前打开过的页面路由数组
|
||||
const currentRoute = currentRoutes[currentRoutes.length - 1].route //获取当前页面路由
|
||||
const handleActiveRole = (val: number) => {
|
||||
activeRole.value = val
|
||||
}
|
||||
|
|
|
@ -39,6 +39,7 @@ const props = withDefaults(defineProps<TabBarProps>(), {
|
|||
|
||||
const tabBarStore = useTabBarStore()
|
||||
const { tabBarList, activeTabBar } = storeToRefs(tabBarStore)
|
||||
|
||||
const handleTabbar = (index: number) => {
|
||||
tabBarStore.setActiveTabBar(index)
|
||||
navigateTo(unref(tabBarList)[index], 'reLaunch')
|
||||
|
|
|
@ -8,12 +8,7 @@
|
|||
<view class="px-[24rpx] py-[16rpx] flex flex-col gap-[16rpx]">
|
||||
<slot name="content" />
|
||||
</view>
|
||||
<view
|
||||
class="px-[32rpx] border-t border-solid border-[#F3F3F3] flex justify-end py-[12rpx]"
|
||||
v-if="isSlotAction"
|
||||
>
|
||||
<slot name="action" />
|
||||
</view>
|
||||
<slot name="action" v-if="isSlotAction" />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ import { computed } from 'vue'
|
|||
|
||||
const props = defineProps({
|
||||
curDate: {
|
||||
type: String,
|
||||
type: Number,
|
||||
default: new Date().getTime()
|
||||
},
|
||||
type: {
|
||||
|
|
|
@ -3,9 +3,9 @@
|
|||
<template #title>
|
||||
<view class="flex justify-between w-full py-[10rpx]">
|
||||
<view class="flex">
|
||||
<text>韩梅梅</text>
|
||||
<text>{{ item.studentName }}</text>
|
||||
<view class="flex ml-[48rpx] gap-[4rpx] items-center">
|
||||
<text class="text-primary">18138952909</text>
|
||||
<text class="text-primary">{{ item.phone }}</text>
|
||||
<u-copy content="uview-plus is great !">
|
||||
<TIcon name="icon-copy" color="#0E66FB" />
|
||||
</u-copy>
|
||||
|
@ -15,7 +15,10 @@
|
|||
</template>
|
||||
<template #content>
|
||||
<view class="flex flex-col gap-[16rpx]">
|
||||
<view class="flex gap-[8rpx] items-center">
|
||||
<view
|
||||
class="flex gap-[8rpx] items-center"
|
||||
v-if="item.situation == converStatusEnum.EXCEPTION"
|
||||
>
|
||||
<TIcon name="icon-warning" color="#F5222D" />
|
||||
<text class="text-error">待电销老师重新跟进</text>
|
||||
</view>
|
||||
|
@ -23,22 +26,33 @@
|
|||
<text class="text-muted w-[128rpx]">基本情况</text>
|
||||
<view class="flex gap-[4rpx] flex-1 items-end">
|
||||
<text>
|
||||
学生爸爸接电话,学生高三毕业,300多分,家长不清楚学生收到录取通知,家长说学生不读书了,我让家长先问问学生对未来的规划先和学生沟通一下,家长同意我们加他微信发专业资料给他看看,可以在微信上问问学生具体情况。推荐3+2,给家长发一下学校简介和专业资料。
|
||||
{{ item.basicInformation }}
|
||||
</text>
|
||||
<u-copy content="uview-plus is great !">
|
||||
<TIcon name="icon-copy" color="#0E66FB" />
|
||||
</u-copy>
|
||||
</view>
|
||||
</view>
|
||||
<view class="flex gap-[20rpx]">
|
||||
<view class="flex gap-[20rpx]" v-if="item.telemarketingTeacherId !== null">
|
||||
<text class="text-muted w-[128rpx]">电销老师</text>
|
||||
<text class="flex-1">王五</text>
|
||||
<text class="flex-1">{{ item.telemarketingTeacherName }}</text>
|
||||
</view>
|
||||
<view class="flex gap-[20rpx]">
|
||||
<view
|
||||
class="flex gap-[20rpx]"
|
||||
v-if="
|
||||
item.situation == converStatusEnum.CONVERTED_PROCESS && item.state !== null
|
||||
"
|
||||
>
|
||||
<text class="text-muted w-[128rpx]">状态</text>
|
||||
<text class="flex-1 text-error">账号不存在</text>
|
||||
<text class="flex-1 text-error">{{ parseStateText }}</text>
|
||||
</view>
|
||||
<view class="flex gap-[20rpx]">
|
||||
<view
|
||||
class="flex gap-[20rpx]"
|
||||
v-if="
|
||||
item.situation == converStatusEnum.CONVERTED ||
|
||||
item.situation == converStatusEnum.FAILED
|
||||
"
|
||||
>
|
||||
<text class="text-muted w-[128rpx]">备注</text>
|
||||
<view class="flex gap-[12rpx]">
|
||||
<text class="flex-1 text-error">已交一部分定位金</text>
|
||||
|
@ -51,19 +65,42 @@
|
|||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="flex gap-[20rpx]">
|
||||
<view class="flex gap-[20rpx]" v-if="item.situation == converStatusEnum.CONVERTED">
|
||||
<text class="text-muted w-[128rpx]">成交时间</text>
|
||||
<text class="flex-1">2025-02-10 16:04:00</text>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
<template #action>
|
||||
<view class="flex justify-end gap-[16rpx]">
|
||||
<u-button color="#0E66FB" shape="circle" @click="handleGet">领取</u-button>
|
||||
<u-button color="#0E66FB" shape="circle" @click="handleAddProgress">
|
||||
添加进展
|
||||
</u-button>
|
||||
<u-button color="#0E66FB" shape="circle" @click="handleComplete">转化完成</u-button>
|
||||
<view
|
||||
class="px-[32rpx] border-t border-solid border-[#F3F3F3] flex justify-end py-[12rpx]"
|
||||
>
|
||||
<view class="flex justify-end gap-[16rpx]">
|
||||
<u-button
|
||||
color="#0E66FB"
|
||||
shape="circle"
|
||||
v-if="item.situation == converStatusEnum.UN_RECEIVED"
|
||||
@click="handleGet"
|
||||
>
|
||||
领取
|
||||
</u-button>
|
||||
<u-button
|
||||
color="#0E66FB"
|
||||
shape="circle"
|
||||
v-if="item.situation == converStatusEnum.CONVERTED_PROCESS"
|
||||
@click="handleAddProgress"
|
||||
>
|
||||
添加进展
|
||||
</u-button>
|
||||
<u-button
|
||||
color="#0E66FB"
|
||||
shape="circle"
|
||||
v-if="item.situation == converStatusEnum.ADD_RELATION"
|
||||
@click="handleComplete"
|
||||
>
|
||||
转化完成
|
||||
</u-button>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
</w-card>
|
||||
|
@ -71,18 +108,36 @@
|
|||
|
||||
<script setup lang="ts">
|
||||
import { toast } from '@/utils/util'
|
||||
import { PropType } from 'vue'
|
||||
import { IClue } from '../telesale/clue-card.vue'
|
||||
import { converStatusEnum, stateEnum } from '@/enums'
|
||||
import { apiGetCluse } from '@/api/clue'
|
||||
import { computed } from 'vue'
|
||||
|
||||
const props = defineProps({
|
||||
item: {
|
||||
type: Object,
|
||||
type: Object as PropType<IClue>,
|
||||
default: () => ({})
|
||||
}
|
||||
})
|
||||
const emit = defineEmits(['handleUpdateRemark'])
|
||||
const emit = defineEmits(['handleUpdateRemark', 'refreshPage'])
|
||||
|
||||
const stateMap: Record<stateEnum, string> = {
|
||||
[stateEnum.ADD_RELATION]: '账号已添加',
|
||||
[stateEnum.NO_EXIST]: '账号不存在',
|
||||
[stateEnum.UN_PASS]: '账号未通过'
|
||||
}
|
||||
const parseStateText = computed(() => stateMap[props.item.state])
|
||||
// 领取
|
||||
const handleGet = () => {
|
||||
const { item } = props
|
||||
toast('领取成功')
|
||||
const handleGet = async () => {
|
||||
const {
|
||||
item: { id }
|
||||
} = props
|
||||
try {
|
||||
await apiGetCluse({ id })
|
||||
toast('领取成功')
|
||||
emit('refreshPage')
|
||||
} catch (error) {}
|
||||
}
|
||||
// 添加进展
|
||||
const handleAddProgress = () => {
|
||||
|
|
|
@ -3,15 +3,17 @@
|
|||
<template #title>
|
||||
<view class="flex justify-between w-full py-[10rpx]">
|
||||
<view class="flex">
|
||||
<text>韩梅梅</text>
|
||||
<text>{{ item.studentName }}</text>
|
||||
<view class="flex ml-[48rpx] gap-[4rpx] items-center">
|
||||
<text class="text-primary">18138952909</text>
|
||||
<text class="text-primary">{{ item.phone }}</text>
|
||||
<u-copy content="uview-plus is great !">
|
||||
<TIcon name="icon-copy" color="#0E66FB" />
|
||||
</u-copy>
|
||||
</view>
|
||||
</view>
|
||||
<text>待领取</text>
|
||||
<text v-if="item.situation == converStatusEnum.UN_RECEIVED" class="text-[#ED6D41]">
|
||||
待领取
|
||||
</text>
|
||||
</view>
|
||||
</template>
|
||||
<template #content>
|
||||
|
@ -23,34 +25,62 @@
|
|||
</view>
|
||||
<view class="flex gap-[20rpx] mb-[16rpx]">
|
||||
<text class="text-muted w-[128rpx]">跟进时间</text>
|
||||
<text class="flex-1">2025-02-08 11:11:30</text>
|
||||
<text class="flex-1">{{ item.createTime }}</text>
|
||||
</view>
|
||||
<view class="flex gap-[20rpx] mb-[16rpx]">
|
||||
<view class="flex gap-[20rpx] mb-[16rpx]" v-if="item.recruitTeacherId !== null">
|
||||
<text class="text-muted w-[128rpx]">招生老师</text>
|
||||
<text class="flex-1">王五</text>
|
||||
<text class="flex-1">{{ item.recruitTeacherName }}</text>
|
||||
</view>
|
||||
<view class="flex gap-[20rpx]">
|
||||
<view class="flex gap-[20rpx]" v-if="item.state !== null">
|
||||
<text class="text-muted w-[128rpx]">状态</text>
|
||||
<text class="flex-1">账号不存在</text>
|
||||
</view>
|
||||
</template>
|
||||
<template #action>
|
||||
<u-button color="#0E66FB" shape="circle" @click="handleEditFollow">修改跟进</u-button>
|
||||
<view
|
||||
class="px-[32rpx] border-t border-solid border-[#F3F3F3] flex justify-end py-[12rpx]"
|
||||
v-if="item.situation == converStatusEnum.EXCEPTION"
|
||||
>
|
||||
<u-button color="#0E66FB" shape="circle" @click="handleEditFollow">
|
||||
修改跟进
|
||||
</u-button>
|
||||
</view>
|
||||
</template>
|
||||
</w-card>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { PropType } from 'vue'
|
||||
import { computed } from 'vue'
|
||||
import { converStatusEnum, stateEnum } from '@/enums'
|
||||
|
||||
export interface IClue {
|
||||
studentName: string
|
||||
phone: string
|
||||
id: number
|
||||
basicInformation: string
|
||||
remark: string
|
||||
isConversion: number
|
||||
listSource: number //线索来源
|
||||
state: stateEnum //状态
|
||||
situation: number // 转化情况
|
||||
createTime: string // 跟进时间
|
||||
telemarketingTeacherName: string // 电销老师
|
||||
recruitTeacherName: string // 招生老师
|
||||
recruitTeacherId: number
|
||||
telemarketingTeacherId: number
|
||||
}
|
||||
const props = defineProps({
|
||||
item: {
|
||||
type: Object,
|
||||
type: Object as PropType<IClue>,
|
||||
default: () => ({})
|
||||
}
|
||||
})
|
||||
const ellipsisDesc = computed(
|
||||
() => item => item.desc?.length >= 14 ? item.desc?.slice(0, 14) + '...' : item.desc
|
||||
() => (item: IClue) =>
|
||||
item.basicInformation?.length >= 14
|
||||
? item.basicInformation?.slice(0, 14) + '...'
|
||||
: item.basicInformation
|
||||
)
|
||||
const handleEditFollow = () => {
|
||||
const { item } = props
|
||||
|
|
|
@ -2,57 +2,86 @@
|
|||
<view class="mt-[32rpx] p-[32rpx] bg-white">
|
||||
<view class="flex justify-between items-center mb-[20rpx]">
|
||||
<text class="text-[44rpx] font-bold">跟进信息</text>
|
||||
<text class="text-[28rpx]">全部清空</text>
|
||||
<text class="text-[28rpx]" @click="handleClear">全部清空</text>
|
||||
</view>
|
||||
<TForm ref="tForm" :model="form" :rules="rules" errorType="toast">
|
||||
<TFormItem prop="clientName">
|
||||
<TFormItem prop="studentName">
|
||||
<TInputField
|
||||
v-model="form.clientName"
|
||||
v-model="form.studentName"
|
||||
label="客户姓名"
|
||||
placeholder="请填写客户姓名(必填)"
|
||||
inputAlign="left"
|
||||
/>
|
||||
</TFormItem>
|
||||
<TFormItem prop="mobile">
|
||||
<TFormItem prop="phone">
|
||||
<TInputField
|
||||
v-model="form.mobile"
|
||||
v-model="form.phone"
|
||||
label="电话"
|
||||
placeholder="请填写电话(必填)"
|
||||
inputAlign="left"
|
||||
/>
|
||||
</TFormItem>
|
||||
<TFormItem prop="desc">
|
||||
<TTextareaField label="基本情况" placeholder="请填写基本情况(必填)" autoHeight />
|
||||
<TFormItem prop="basicInformation">
|
||||
<TTextareaField
|
||||
v-model="form.basicInformation"
|
||||
label="基本情况"
|
||||
placeholder="请填写基本情况(必填)"
|
||||
autoHeight
|
||||
/>
|
||||
</TFormItem>
|
||||
</TForm>
|
||||
<u-button class="btn" color="#0E66FB" shape="circle" @click="handleConfirm">确认</u-button>
|
||||
<u-button
|
||||
class="btn"
|
||||
color="#0E66FB"
|
||||
shape="circle"
|
||||
:loading="loading"
|
||||
@click="handleConfirm"
|
||||
>
|
||||
确认
|
||||
</u-button>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { apiAddCluse } from '@/api/clue'
|
||||
import { toast, validate } from '@/utils/util'
|
||||
import { validateContact } from '@/utils/validate'
|
||||
import { ref } from 'vue'
|
||||
|
||||
const tForm = ref()
|
||||
const form = ref({
|
||||
clientName: '',
|
||||
mobile: '',
|
||||
desc: ''
|
||||
studentName: '',
|
||||
phone: '',
|
||||
basicInformation: ''
|
||||
})
|
||||
const loading = ref(false)
|
||||
const rules = {
|
||||
clientName: [{ required: true, message: '请填写客户姓名', trigger: 'blur' }],
|
||||
mobile: [{ required: true, message: '请填写电话', trigger: 'blur' }],
|
||||
desc: [{ required: true, message: '请填写基本情况', trigger: 'blur' }]
|
||||
studentName: [{ required: true, message: '请填写客户姓名', trigger: 'blur' }],
|
||||
phone: [
|
||||
{ required: true, message: '请填写电话', trigger: 'blur' },
|
||||
{ validator: validateContact, trigger: 'blur' }
|
||||
],
|
||||
basicInformation: [{ required: true, message: '请填写基本情况', trigger: 'blur' }]
|
||||
}
|
||||
const handleConfirm = () => {
|
||||
tForm.value
|
||||
.validate()
|
||||
.then(valid => {
|
||||
.then(async valid => {
|
||||
if (valid) {
|
||||
console.log('校验通过')
|
||||
loading.value = true
|
||||
try {
|
||||
await apiAddCluse(form.value)
|
||||
toast('添加成功')
|
||||
handleClear()
|
||||
} catch (error) {}
|
||||
loading.value = false
|
||||
}
|
||||
})
|
||||
.catch(() => {})
|
||||
}
|
||||
const handleClear = () => {
|
||||
tForm.value.resetFields()
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
|
|
@ -1,46 +1,47 @@
|
|||
<template>
|
||||
<view class="flex-1 h-full flex flex-col">
|
||||
<TSearch
|
||||
v-model="searchValue"
|
||||
v-model="queryParams.likeWork"
|
||||
placeholder="搜索客户姓名/手机号码"
|
||||
backgroundColor="#F5F5F5"
|
||||
@on-input="searchChange"
|
||||
/>
|
||||
<view class="flex-1 mt-3 px-2 overflow-auto bg-[#FAFAFE]">
|
||||
<!-- <z-paging
|
||||
<z-paging
|
||||
ref="paging"
|
||||
v-model="dataList"
|
||||
@query="queryList"
|
||||
:fixed="false"
|
||||
height="100%"
|
||||
> -->
|
||||
|
||||
<clue-card
|
||||
v-for="(item, index) in dataList"
|
||||
:key="`${index} + 'unique'`"
|
||||
:item="item"
|
||||
/>
|
||||
<!-- </z-paging> -->
|
||||
>
|
||||
<clue-card
|
||||
v-for="(item, index) in dataList"
|
||||
:key="`${index} + 'unique'`"
|
||||
:item="item"
|
||||
/>
|
||||
</z-paging>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { apiOverhaulPagelist } from '@/api/overhaul'
|
||||
import { useZPaging } from '@/hooks/useZPaging'
|
||||
import { ref } from 'vue'
|
||||
import clueCard from './clue-card.vue'
|
||||
import { apiCluseList } from '@/api/clue'
|
||||
import { debounce } from 'lodash-es'
|
||||
|
||||
const searchValue = ref('')
|
||||
const queryParams = ref({})
|
||||
const dataList = ref([
|
||||
{
|
||||
id: 1
|
||||
}
|
||||
])
|
||||
const queryParams = ref({
|
||||
likeWork: ''
|
||||
})
|
||||
const dataList = ref([])
|
||||
const { paging, queryList, refresh, changeApi, setParams } = useZPaging(
|
||||
queryParams.value,
|
||||
apiOverhaulPagelist,
|
||||
apiCluseList,
|
||||
() => {}
|
||||
)
|
||||
const searchChange = debounce(() => {
|
||||
refresh()
|
||||
}, 300)
|
||||
</script>
|
||||
<style scoped></style>
|
||||
|
|
|
@ -6,8 +6,8 @@ export enum ThemeEnum {
|
|||
DARK = 'dark'
|
||||
}
|
||||
export enum ChannelEnum {
|
||||
USER_PLATFORM = 0,
|
||||
STAFF_PLATFORM = 1
|
||||
USER_PLATFORM = 0, // 用户端
|
||||
STAFF_PLATFORM = 1 //师傅端
|
||||
}
|
||||
// 客户端
|
||||
export enum ClientEnum {
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
export enum teleSaleEnum {
|
||||
ADD_FOLLOW = 0,
|
||||
FOLLOW_RECORD = 1
|
||||
}
|
||||
|
||||
export enum converStatusEnum {
|
||||
INTENTION = 0, //有意向
|
||||
UN_RECEIVED = 1, //待领取
|
||||
CONVERTED_PROCESS = 2, //转化中
|
||||
ADD_RELATION = 3, //已添加
|
||||
EXCEPTION = 4, //异常待处理
|
||||
CONVERTED = 5, //已成交
|
||||
FAILED = 6 //已战败
|
||||
}
|
||||
export enum stateEnum {
|
||||
ADD_RELATION = 0, //账号已添加
|
||||
NO_EXIST = 1, //账号不存在
|
||||
UN_PASS = 2 //账号未通过
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
import { apiCluseDetail } from '@/api/clue'
|
||||
import { ref } from 'vue'
|
||||
|
||||
// 获取线索详情
|
||||
export function useClueDetail() {
|
||||
const clueDetailInfo = ref()
|
||||
const fetchClueDetail = async (id: number | string) => {
|
||||
uni.showLoading({
|
||||
title: '加载中'
|
||||
})
|
||||
try {
|
||||
const result = await apiCluseDetail({ id })
|
||||
clueDetailInfo.value = result
|
||||
} catch (error) {}
|
||||
uni.hideLoading()
|
||||
}
|
||||
return {
|
||||
clueDetailInfo,
|
||||
fetchClueDetail
|
||||
}
|
||||
}
|
|
@ -23,110 +23,50 @@ export interface RoleItem {
|
|||
export function useRoleData() {
|
||||
const roles: RoleItem[] = [
|
||||
{
|
||||
name: '业务员',
|
||||
ids: [8, 9],
|
||||
name: '电销老师',
|
||||
ids: [5],
|
||||
tabBarList: [
|
||||
{
|
||||
text: '客户库',
|
||||
text: '首页',
|
||||
path: '/pages/telesale/home/index',
|
||||
inactiveIcon: clientInActive,
|
||||
activeIcon: clientActive,
|
||||
path: '/pages/salesman/client/index'
|
||||
activeIcon: clientActive
|
||||
},
|
||||
{
|
||||
text: '合同管理',
|
||||
path: '/pages/salesman/contract/index',
|
||||
text: '总结模板',
|
||||
path: '/pages/telesale/summary/index',
|
||||
inactiveIcon: contractInActive,
|
||||
activeIcon: contractActive
|
||||
},
|
||||
{
|
||||
text: '个人中心',
|
||||
path: '/pages/salesman/profile/index',
|
||||
path: '/pages/telesale/my/index',
|
||||
inactiveIcon: profileInActive,
|
||||
activeIcon: profileActive
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: '检修员',
|
||||
name: '招生老师',
|
||||
ids: [6],
|
||||
tabBarList: [
|
||||
{
|
||||
text: '工单池',
|
||||
text: '首页',
|
||||
inactiveIcon: order,
|
||||
activeIcon: orderActive,
|
||||
path: '/pages/overhaul/pool/index'
|
||||
path: '/pages/recruitsale/home/index'
|
||||
},
|
||||
{
|
||||
text: '我的任务',
|
||||
text: '总结模板',
|
||||
path: '/pages/recruitsale/summary/index',
|
||||
inactiveIcon: task,
|
||||
activeIcon: taskActive,
|
||||
path: '/pages/overhaul/task/index'
|
||||
activeIcon: taskActive
|
||||
},
|
||||
{
|
||||
text: '个人中心',
|
||||
path: '/pages/recruitsale/my/index',
|
||||
inactiveIcon: profileInActive,
|
||||
activeIcon: profileActive,
|
||||
path: '/pages/overhaul/my/index'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: '客户',
|
||||
ids: [1, 2, 11],
|
||||
tabBarList: [
|
||||
{
|
||||
text: '工单记录',
|
||||
inactiveIcon: order,
|
||||
activeIcon: orderActive,
|
||||
path: '/pages/client/workOrder/index'
|
||||
},
|
||||
{
|
||||
text: '个人中心',
|
||||
inactiveIcon: profileInActive,
|
||||
activeIcon: profileActive,
|
||||
path: '/pages/client/my/index'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: '维修员',
|
||||
ids: [7],
|
||||
tabBarList: [
|
||||
// {
|
||||
// text: '工单池',
|
||||
// inactiveIcon: order,
|
||||
// activeIcon: orderActive,
|
||||
// path: '/pages/repair/pool/index'
|
||||
// },
|
||||
{
|
||||
text: '工单列表',
|
||||
inactiveIcon: task,
|
||||
activeIcon: taskActive,
|
||||
path: '/pages/repair/task/index'
|
||||
},
|
||||
{
|
||||
text: '个人中心',
|
||||
inactiveIcon: profileInActive,
|
||||
activeIcon: profileActive,
|
||||
path: '/pages/repair/my/index'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: '维修主管',
|
||||
ids: [10],
|
||||
tabBarList: [
|
||||
{
|
||||
text: '工单列表',
|
||||
inactiveIcon: task,
|
||||
activeIcon: taskActive,
|
||||
path: '/pages/charge/order/index'
|
||||
},
|
||||
{
|
||||
text: '个人中心',
|
||||
inactiveIcon: profileInActive,
|
||||
activeIcon: profileActive,
|
||||
path: '/pages/charge/my/index'
|
||||
activeIcon: profileActive
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -1,29 +1,56 @@
|
|||
{
|
||||
"pages": [
|
||||
{
|
||||
"path": "pages/recruitsale/home/index",
|
||||
"path": "pages/index/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/recruitsale/summary/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/telesale/summary/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": ""
|
||||
"navigationBarTitleText": "首页",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/telesale/home/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": ""
|
||||
},
|
||||
"auth": true
|
||||
},
|
||||
{
|
||||
"path": "pages/recruitsale/home/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": ""
|
||||
},
|
||||
"auth": true
|
||||
},
|
||||
{
|
||||
"path": "pages/telesale/summary/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": ""
|
||||
},
|
||||
"auth": true
|
||||
},
|
||||
{
|
||||
"path": "pages/recruitsale/summary/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": ""
|
||||
},
|
||||
"auth": true
|
||||
},
|
||||
{
|
||||
"path": "pages/recruitsale/my/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "个人中心",
|
||||
"navigationStyle": "custom"
|
||||
},
|
||||
"auth": true
|
||||
},
|
||||
{
|
||||
"path": "pages/telesale/my/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "个人中心",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"path": "pages/salesman/contract/index",
|
||||
"style": {
|
||||
|
@ -44,21 +71,6 @@
|
|||
},
|
||||
"auth": true
|
||||
},
|
||||
{
|
||||
"path": "pages/client/my/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "个人中心",
|
||||
"navigationStyle": "custom"
|
||||
},
|
||||
"auth": true
|
||||
},
|
||||
{
|
||||
"path": "pages/salesman/profile/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "个人中心",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/overhaul/pool/index",
|
||||
"style": {
|
||||
|
|
|
@ -1,86 +1,19 @@
|
|||
<!--
|
||||
* @Author: micky
|
||||
* @Date: 2024-08-10 15:24:06
|
||||
* @LastEditors: micky
|
||||
* @LastEditTime: 2024-08-28 18:39:12
|
||||
* @FilePath: \chargingpile-uniapp\src\pages\index\index.vue
|
||||
-->
|
||||
<template>
|
||||
<view class="wrapper">
|
||||
<swiper class="swiper" @change="swiperChange">
|
||||
<swiper-item v-for="(item, index) in list" :key="index" class="item">
|
||||
<image :src="item.image"></image>
|
||||
<view class="title">{{ item.title }}</view>
|
||||
<view class="desc">{{ item.desc }}</view>
|
||||
</swiper-item>
|
||||
</swiper>
|
||||
<view class="rowDot">
|
||||
<view v-for="(item, index) in list" :key="index" class="dots">
|
||||
<view :class="['dot', index === swiperCurrent ? 'active' : '']"></view>
|
||||
</view>
|
||||
</view>
|
||||
<u-button
|
||||
type="primary"
|
||||
class="login-btn"
|
||||
shape="circle"
|
||||
v-if="swiperCurrent == 3"
|
||||
@click="toPage"
|
||||
>
|
||||
立即登录
|
||||
</u-button>
|
||||
</view>
|
||||
<view></view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { reactive, ref } from 'vue'
|
||||
import Step1 from '@/static/images/step_1.png'
|
||||
import Step2 from '@/static/images/step_2.png'
|
||||
import Step3 from '@/static/images/step_3.png'
|
||||
import Step4 from '@/static/images/step_4.png'
|
||||
import { onLoad } from '@dcloudio/uni-app'
|
||||
import { useUserStore } from '@/stores/user'
|
||||
import { ROLEINDEX } from '@/enums/cacheEnums'
|
||||
import { useRoleData } from '@/hooks/useRoleData'
|
||||
import { useTabBarStore } from '@/stores/tabbar'
|
||||
import { useUserStore } from '@/stores/user'
|
||||
import cache from '@/utils/cache'
|
||||
import { ROLEINDEX } from '@/enums/cacheEnums'
|
||||
import { onLoad } from '@dcloudio/uni-app'
|
||||
|
||||
const userStore = useUserStore()
|
||||
const { roles } = useRoleData()
|
||||
const tabBarStore = useTabBarStore()
|
||||
|
||||
const swiperCurrent = ref(0)
|
||||
const list = reactive([
|
||||
{
|
||||
image: Step1,
|
||||
title: '用户报修',
|
||||
desc: '用户可以通过在线报修、电话报修或扫码报修等多种方式提交维修请求。'
|
||||
},
|
||||
{
|
||||
image: Step2,
|
||||
title: '桩点检修',
|
||||
desc: '检修员接单后将上门对客户上报的桩点进行现场维修。'
|
||||
},
|
||||
{
|
||||
image: Step3,
|
||||
title: '上门巡检',
|
||||
desc: '检修员在巡检过程中发现设备异常时需提交检修单。'
|
||||
},
|
||||
{
|
||||
image: Step4,
|
||||
title: '模块维修',
|
||||
desc: '维修员通过扫描模块条形码来创建维修工单。'
|
||||
}
|
||||
])
|
||||
|
||||
const swiperChange = e => {
|
||||
swiperCurrent.value = e.detail.current
|
||||
}
|
||||
const toPage = () => {
|
||||
uni.redirectTo({
|
||||
url: '/bundle/pages/login/login'
|
||||
})
|
||||
}
|
||||
|
||||
const setNextRoute = () => {
|
||||
const ind = cache.get(ROLEINDEX) || 0
|
||||
const { userInfo } = userStore
|
||||
|
@ -100,51 +33,4 @@ onLoad(() => {
|
|||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.wrapper {
|
||||
@apply h-full relative z-10;
|
||||
.swiper {
|
||||
@apply px-[30px] h-[400px] pt-[150px];
|
||||
.item {
|
||||
@apply flex flex-col items-center;
|
||||
}
|
||||
image {
|
||||
@apply w-[100vw] h-[310px] mb-[48rpx];
|
||||
line-height: 90rpx;
|
||||
}
|
||||
.title {
|
||||
@apply text-[24px] text-[#2F2F52] mb-[15px];
|
||||
}
|
||||
.desc {
|
||||
@apply text-[#334155];
|
||||
}
|
||||
}
|
||||
.rowDot {
|
||||
@apply flex justify-center mt-[66px];
|
||||
.dots {
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
align-content: center;
|
||||
.dot {
|
||||
margin-right: 8rpx;
|
||||
width: 20rpx;
|
||||
height: 8rpx;
|
||||
opacity: 1;
|
||||
border-radius: 6rpx;
|
||||
background: #efefef;
|
||||
}
|
||||
.dot.active {
|
||||
width: 48rpx;
|
||||
background: #1a66ff;
|
||||
}
|
||||
}
|
||||
}
|
||||
:deep(.login-btn) {
|
||||
button {
|
||||
@apply w-[200px] h-[40px] -mt-[20px];
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<style scoped></style>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<template>
|
||||
<view class="flex-1 h-screen flex flex-col">
|
||||
<TContainer>
|
||||
<TSearch
|
||||
v-model="queryParams.searchValue"
|
||||
v-model="queryParams.likeWork"
|
||||
placeholder="搜索客户姓名/手机号码"
|
||||
backgroundColor="#F5F5F5"
|
||||
showBorder
|
||||
|
@ -13,27 +13,26 @@
|
|||
:activeStyle="{ color: '#0E66FB' }"
|
||||
lineWidth="49"
|
||||
lineColor="#0E66FB"
|
||||
:current="activeTab"
|
||||
@change="handleChangeTab"
|
||||
></u-tabs>
|
||||
<view class="flex-1 pt-[24rpx] px-[24rpx] overflow-auto bg-[#F8F8F8]">
|
||||
<!-- <z-paging
|
||||
<z-paging
|
||||
ref="paging"
|
||||
v-model="dataList"
|
||||
@query="queryList"
|
||||
:fixed="false"
|
||||
height="100%"
|
||||
> -->
|
||||
|
||||
<clue-card
|
||||
v-for="(item, index) in dataList"
|
||||
:key="`${index} + 'unique'`"
|
||||
:item="item"
|
||||
@handle-update-remark="handleUpdateRemark"
|
||||
/>
|
||||
<!-- </z-paging> -->
|
||||
>
|
||||
<clue-card
|
||||
v-for="(item, index) in dataList"
|
||||
:key="`${index} + 'unique'`"
|
||||
:item="item"
|
||||
@handle-update-remark="handleUpdateRemark"
|
||||
@refresh-page="refresh"
|
||||
/>
|
||||
</z-paging>
|
||||
</view>
|
||||
</view>
|
||||
</TContainer>
|
||||
<w-confirm-popup v-model="popupShow" @confirm="handleConfirm">
|
||||
<template #content>
|
||||
<TTextareaField v-model="contentText" border="surround" :required="false" />
|
||||
|
@ -48,40 +47,33 @@ import { ref } from 'vue'
|
|||
import clueCard from '@/components/widgets/recruitsale/clue-card.vue'
|
||||
import { shallowRef } from 'vue'
|
||||
import { computed } from 'vue'
|
||||
import { apiCluseList } from '@/api/clue'
|
||||
import { converStatusEnum } from '@/enums'
|
||||
import { onLoad } from '@dcloudio/uni-app'
|
||||
|
||||
const tabs = shallowRef([
|
||||
{ name: '待领取', value: 0 },
|
||||
{ name: '转化中', value: 1 },
|
||||
{ name: '已成交', value: 2 },
|
||||
{ name: '已战败', value: 3 }
|
||||
{ name: '待领取', value: converStatusEnum.UN_RECEIVED },
|
||||
{ name: '转化中', value: converStatusEnum.CONVERTED_PROCESS },
|
||||
{ name: '已成交', value: converStatusEnum.CONVERTED },
|
||||
{ name: '已战败', value: converStatusEnum.FAILED }
|
||||
])
|
||||
const activeTab = ref(0)
|
||||
const activeTab = ref(converStatusEnum.UN_RECEIVED)
|
||||
const queryParams = computed(() => {
|
||||
const payload = {
|
||||
status: activeTab.value,
|
||||
searchValue: ''
|
||||
situation: activeTab.value,
|
||||
likeWork: ''
|
||||
}
|
||||
return payload
|
||||
})
|
||||
const dataList = ref([
|
||||
{
|
||||
id: 1
|
||||
},
|
||||
{
|
||||
id: 2
|
||||
},
|
||||
{
|
||||
id: 3
|
||||
}
|
||||
])
|
||||
const dataList = ref([])
|
||||
const { paging, queryList, refresh, changeApi, setParams } = useZPaging(
|
||||
queryParams.value,
|
||||
apiOverhaulPagelist,
|
||||
apiCluseList,
|
||||
() => {}
|
||||
)
|
||||
const handleChangeTab = item => {
|
||||
activeTab.value = item.value
|
||||
// refresh(queryParams.value)
|
||||
refresh(queryParams.value)
|
||||
}
|
||||
const popupShow = ref(false)
|
||||
const contentText = ref('')
|
||||
|
@ -91,5 +83,10 @@ const handleUpdateRemark = item => {
|
|||
contentText.value = remark
|
||||
}
|
||||
const handleConfirm = () => {}
|
||||
onLoad(() => {
|
||||
uni.$on('refreshPage', () => {
|
||||
refresh(queryParams.value)
|
||||
})
|
||||
})
|
||||
</script>
|
||||
<style scoped></style>
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
<template>
|
||||
<TProfile :isShow="false"></TProfile>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts"></script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
|
@ -1,9 +1,15 @@
|
|||
<template>
|
||||
<view class="pb-[24rpx]">
|
||||
<w-date-more :curDate="curDate" type="recruitsale" />
|
||||
<date-strip v-model="curDate" @change="handleDateChange" height="160rpx" />
|
||||
<w-summary-form v-model="templateItems" @handle-confirm="handleConfirm" :readonly="type" />
|
||||
</view>
|
||||
<TContainer>
|
||||
<view class="pb-[24rpx]">
|
||||
<w-date-more :curDate="curDate" type="recruitsale" />
|
||||
<date-strip v-model="curDate" @change="handleDateChange" height="160rpx" />
|
||||
<w-summary-form
|
||||
v-model="templateItems"
|
||||
@handle-confirm="handleConfirm"
|
||||
:readonly="type"
|
||||
/>
|
||||
</view>
|
||||
</TContainer>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<view class="flex flex-col h-screen">
|
||||
<TContainer>
|
||||
<u-tabs
|
||||
:list="tabs"
|
||||
:scrollable="false"
|
||||
|
@ -11,10 +11,10 @@
|
|||
@change="handleChangeTab"
|
||||
></u-tabs>
|
||||
<view class="flex-1 bg-gray3">
|
||||
<follow-form v-if="activeTab === 0" />
|
||||
<follow-record v-else-if="activeTab === 1" />
|
||||
<follow-form v-if="activeTab === teleSaleEnum.ADD_FOLLOW" />
|
||||
<follow-record v-else-if="activeTab === teleSaleEnum.FOLLOW_RECORD" />
|
||||
</view>
|
||||
</view>
|
||||
</TContainer>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
|
@ -22,11 +22,12 @@ import { shallowRef } from 'vue'
|
|||
import { ref } from 'vue'
|
||||
import followForm from '@/components/widgets/telesale/follow-form.vue'
|
||||
import followRecord from '@/components/widgets/telesale/follow-record.vue'
|
||||
import { teleSaleEnum } from '@/enums'
|
||||
|
||||
const activeTab = ref(1)
|
||||
const activeTab = ref(teleSaleEnum.ADD_FOLLOW)
|
||||
const tabs = shallowRef([
|
||||
{ name: '新增跟进', value: 0 },
|
||||
{ name: '跟进动态', value: 1 }
|
||||
{ name: '新增跟进', value: teleSaleEnum.ADD_FOLLOW },
|
||||
{ name: '跟进动态', value: teleSaleEnum.FOLLOW_RECORD }
|
||||
])
|
||||
const handleChangeTab = item => {
|
||||
activeTab.value = item.value
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
<template>
|
||||
<TProfile :isShow="false"></TProfile>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts"></script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
|
@ -3,6 +3,7 @@
|
|||
<w-date-more :curDate="curDate" type="telesale" />
|
||||
<date-strip v-model="value" @change="handleDateChange" height="160rpx" />
|
||||
<w-summary-form v-model="templateItems" @handle-confirm="handleConfirm" />
|
||||
<tabbar />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
@font-face {
|
||||
font-family: 'iconfont'; /* Project id 4837700 */
|
||||
src: url('//at.alicdn.com/t/c/font_4837700_wjnzp8mer6o.woff2?t=1740542409608') format('woff2'),
|
||||
url('//at.alicdn.com/t/c/font_4837700_wjnzp8mer6o.woff?t=1740542409608') format('woff'),
|
||||
url('//at.alicdn.com/t/c/font_4837700_wjnzp8mer6o.ttf?t=1740542409608') format('truetype');
|
||||
src: url('//at.alicdn.com/t/c/font_4837700_mvrnof6x61s.woff2?t=1740644911077') format('woff2'),
|
||||
url('//at.alicdn.com/t/c/font_4837700_mvrnof6x61s.woff?t=1740644911077') format('woff'),
|
||||
url('//at.alicdn.com/t/c/font_4837700_mvrnof6x61s.ttf?t=1740644911077') format('truetype');
|
||||
}
|
||||
|
||||
.iconfont {
|
||||
|
@ -13,6 +13,14 @@
|
|||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
.icon-clear:before {
|
||||
content: '\e601';
|
||||
}
|
||||
|
||||
.icon-search:before {
|
||||
content: '\e67d';
|
||||
}
|
||||
|
||||
.icon-left:before {
|
||||
content: '\e83d';
|
||||
}
|
||||
|
|
|
@ -60,11 +60,11 @@ export const useAppStore = defineStore({
|
|||
return url ? `${this.config.domain}${url}` : ''
|
||||
// return url || ''
|
||||
},
|
||||
async getConfig() {
|
||||
const data = await apiConfig()
|
||||
this.config = data
|
||||
cache.set(CONFIG, data)
|
||||
},
|
||||
// async getConfig() {
|
||||
// const data = await apiConfig()
|
||||
// this.config = data
|
||||
// cache.set(CONFIG, data)
|
||||
// },
|
||||
|
||||
// setCityInfo(city: City) {
|
||||
// this.cityInfo = city
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* @LastEditTime: 2024-10-27 18:19:43
|
||||
* @FilePath: \chargingpile-uniapp\src\stores\user.ts
|
||||
*/
|
||||
import { apiUserInfo, getUserCenter } from '@/api/user'
|
||||
import { apiUserInfo } from '@/api/user'
|
||||
import { TOKEN_KEY, USER_INFO, CONFIG, ROLEINDEX } from '@/enums/cacheEnums'
|
||||
import cache from '@/utils/cache'
|
||||
import { defineStore } from 'pinia'
|
||||
|
@ -48,14 +48,6 @@ export const useUserStore = defineStore({
|
|||
const data = await apiUserInfo({
|
||||
token: this.token || this.temToken
|
||||
})
|
||||
let roleArr = []
|
||||
for (const key in data.roleMap) {
|
||||
roleArr.push({
|
||||
name: data.roleMap[key],
|
||||
id: Number(key)
|
||||
})
|
||||
}
|
||||
data.roles = roleArr
|
||||
this.userInfo = data
|
||||
cache.set(USER_INFO, data)
|
||||
}
|
||||
|
|
|
@ -288,3 +288,8 @@ page {
|
|||
}
|
||||
}
|
||||
}
|
||||
.u-tabbar {
|
||||
.u-tabbar__content {
|
||||
z-index: 99999 !important;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
const mobileReg =
|
||||
/^(?:(?:\+|00)86)?1(?:(?:3[\d])|(?:4[5-79])|(?:5[0-35-9])|(?:6[5-7])|(?:7[0-8])|(?:8[\d])|(?:9[189]))\d{8}$/
|
||||
|
||||
/**手机号码 */
|
||||
export function validateContact(rule: any, value: any, callback: any) {
|
||||
if (value) {
|
||||
if (!mobileReg.test(value)) {
|
||||
callback(new Error('请输入正确的电话'))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}
|
|
@ -31,7 +31,8 @@ module.exports = {
|
|||
lightblack: '#3D3D3D',
|
||||
border: '#F1F1F1',
|
||||
border2: '#F3F3F3',
|
||||
blue2: '#EEF6FF'
|
||||
blue2: '#EEF6FF',
|
||||
orage: '#ED6D41'
|
||||
},
|
||||
fontSize: {
|
||||
xs: '24rpx',
|
||||
|
|
Loading…
Reference in New Issue