diff --git a/common/util.js b/common/util.js index c2eee71..9295a69 100644 --- a/common/util.js +++ b/common/util.js @@ -1,5 +1,5 @@ import {img_domian} from "./config"; -import marketApi from '@/api/market.js'; +import marketApi from '@/api/apiRoute.js'; function formatTime(time) { if (typeof time !== 'number' || time < 0) { @@ -231,13 +231,17 @@ async function getDict(dictKey) { return cache.data; } // 缓存无效,请求接口 - const res = await marketApi.common_Dictionary({ dictKey }); + const res = await marketApi.common_Dictionary({ key: dictKey }); if (res && res.code === 1) { + // 处理接口返回的数据,确保返回格式一致 + // 接口返回的是 [{name: "抖音", value: "1", sort: 0, memo: ""}, ...] + const formattedData = Array.isArray(res.data) ? res.data : []; + uni.setStorageSync(cacheKey, { - data: res.data, + data: formattedData, expire: now + 3600 * 1000 }); - return res.data; + return formattedData; } else { return []; } diff --git a/pages/market/clue/add_clues.vue b/pages/market/clue/add_clues.vue index 5530eea..ec24fce 100644 --- a/pages/market/clue/add_clues.vue +++ b/pages/market/clue/add_clues.vue @@ -904,8 +904,8 @@ export default { return } let arr = [] - // 兼容后端返回格式 - (dictionary.dictionary || dictionary).forEach((v)=>{ + // 处理接口返回的数据结构 [{name: "抖音", value: "1", sort: 0, memo: ""}, ...] + dictionary.forEach((v) => { arr.push({ text: v.name, value: v.value }) }) this.picker_config[inputName].options = arr diff --git a/pages/market/clue/edit_clues.vue b/pages/market/clue/edit_clues.vue index b3e4757..d0b77bb 100644 --- a/pages/market/clue/edit_clues.vue +++ b/pages/market/clue/edit_clues.vue @@ -27,6 +27,21 @@ + + + + + {{ formData.source_channel ? picker_config.source_channel.text : '点击选择' }} + + + @@ -198,17 +213,17 @@ - + - + 报名 - + 未报名 @@ -463,18 +478,41 @@ methods: { //初始化 async init() { - await this.getDict('source_channel') //获取字典-来源渠道 - await this.getDict('source') //获取字典-来源 - await this.getDict('purchasing_power') //获取字典-购买力 - await this.getDict('initial_intent') //获取字典-客户初步意向度 - await this.getDict('cognitive_idea') //获取字典-认知理念 - await this.getDict('status') //获取字典-客户状态 - await this.getDict('decision_maker') //获取字典-决策人 - await this.getDict('distance') //获取字典-距离 - // this.getStaffList()//获取人员列表 - // this.getAreaTree()//获取地区树形结构 - - await this.getInfo() //获取资源共享-详情(客户资源详情) + try { + uni.showLoading({ + title: '加载中...', + mask: true + }); + + // 先加载所有字典数据 + const dictPromises = [ + this.getDict('source_channel'), //获取字典-来源渠道 + this.getDict('source'), //获取字典-来源 + this.getDict('purchasing_power'), //获取字典-购买力 + this.getDict('initial_intent'), //获取字典-客户初步意向度 + this.getDict('cognitive_idea'), //获取字典-认知理念 + this.getDict('status'), //获取字典-客户状态 + this.getDict('decision_maker'), //获取字典-决策人 + this.getDict('distance'), //获取字典-距离 + ]; + + await Promise.all(dictPromises); + + // 加载校区列表 + await this.get_campus_list(); + + // 获取资源共享详情并回显数据 + await this.getInfo(); + + } catch (error) { + console.error('初始化失败:', error); + uni.showToast({ + title: '加载数据失败,请重试', + icon: 'none' + }); + } finally { + uni.hideLoading(); + } }, async get_campus_list(){ @@ -538,6 +576,7 @@ decision_maker: customerResource.decision_maker || '', //决策人 initial_intent: customerResource.initial_intent || '', //客户初步意向度: high-高, medium-中, low-低 status: customerResource.status || '', //客户状态: active-活跃, inactive-不活跃, pending-待定 + campus: customerResource.campus || '', // 校区 //六要素信息 purchasing_power: sixSpeed.purchase_power || '', //购买力 @@ -554,24 +593,72 @@ this.formData.promised_visit_time = this.$util.formatToDateTime(sixSpeed.promised_visit_time, 'Y-m-d'); //格式化时间(Y-m-d H:i) - this.formData.optional_class_time = this.$util.formatToDateTime(sixSpeed.promised_visit_time, + this.formData.optional_class_time = this.$util.formatToDateTime(sixSpeed.preferred_class_time, 'Y-m-d'); //格式化时间(Y-m-d H:i) + + // 获取校区列表,确保校区选择器数据已加载 + await this.get_campus_list() + + // 等待所有字典数据加载完成后再进行回显 + await this.setPickerText() + }, - //下拉窗文本回显 - this.picker_config.source_channel.text = customerResource.source_channel_name || '点击选择' //来源渠道 - this.picker_config.source.text = customerResource.source_name || '点击选择' //来源 - this.picker_config.consultant.text = customerResource.consultant_name || '点击选择' //顾问 - this.picker_config.initial_intent.text = customerResource.initial_intent_name || '点击选择' //客户初步意向度 - this.picker_config.status.text = customerResource.status_name || '点击选择' //客户状态 - - this.picker_config.decision_maker.text = customerResource.decision_maker || '点击选择' //决策人 + // 设置选择器文本回显 + async setPickerText() { + const { customerResource = {}, sixSpeed = {} } = await this.getResourceDetail() || {} + + // 设置选择器文本回显 + this.setPickerTextByValue('source_channel', this.formData.source_channel, customerResource.source_channel_name) + this.setPickerTextByValue('source', this.formData.source, customerResource.source_name) + this.setPickerTextByValue('consultant', this.formData.consultant, customerResource.consultant_name) + this.setPickerTextByValue('initial_intent', this.formData.initial_intent, customerResource.initial_intent_name) + this.setPickerTextByValue('status', this.formData.status, customerResource.status_name) + this.setPickerTextByValue('decision_maker', this.formData.decision_maker, customerResource.decision_maker_name || customerResource.decision_maker) + this.setPickerTextByValue('campus', this.formData.campus, customerResource.campus_name) + + // 六要素相关 + this.setPickerTextByValue('purchasing_power', this.formData.purchasing_power, sixSpeed.purchase_power_name) + this.setPickerTextByValue('cognitive_idea', this.formData.cognitive_idea, sixSpeed.concept_awareness_name) + this.setPickerTextByValue('distance', this.formData.distance, sixSpeed.distance_name || sixSpeed.distance) + }, - //六要素相关 - this.picker_config.purchasing_power.text = sixSpeed.purchase_power_name || '点击选择' //购买力 - this.picker_config.cognitive_idea.text = sixSpeed.concept_awareness_name || '点击选择' //认知理念 - this.picker_config.distance.text = sixSpeed.distance || '点击选择' //距离 + // 根据值设置选择器文本 + setPickerTextByValue(pickerName, value, defaultText) { + if (!value) { + this.picker_config[pickerName].text = '点击选择' + return + } + + // 先尝试从选项中找到匹配的文本 + const options = this.picker_config[pickerName].options || [] + const option = options.find(opt => opt.value == value) + + if (option) { + this.picker_config[pickerName].text = option.text + } else if (defaultText) { + // 如果找不到匹配的选项但有默认文本,则使用默认文本 + this.picker_config[pickerName].text = defaultText + } else { + this.picker_config[pickerName].text = '点击选择' + } + }, - await this.get_campus_list()//获取校区 + // 获取资源详情(缓存数据,避免重复请求) + async getResourceDetail() { + if (this._resourceDetail) { + return this._resourceDetail + } + + let params = { + resource_sharing_id: this.resource_sharing_id + } + + let res = await apiRoute.xs_resourceSharingInfo(params) + if (res.code == 1) { + this._resourceDetail = res.data + return res.data + } + return null }, //获取字典-课程id选择 @@ -705,25 +792,17 @@ return } - - let res = await apiRoute.common_Dictionary({ - key: key - }) - if (res.code != 1) { - uni.showToast({ - title: res.msg, - icon: 'none' - }) + // 使用 util.getDict 获取并缓存字典 + let dictionary = await this.$util.getDict(key) + if(!dictionary || !Array.isArray(dictionary) || dictionary.length === 0){ + uni.showToast({ title: '暂无选项', icon: 'none' }) return } - - let dictionary = res.data.dictionary + let arr = [] - dictionary.forEach((v, k) => { - arr.push({ - text: v.name, - value: v.value, - }) + // 处理接口返回的数据结构 [{name: "抖音", value: "1", sort: 0, memo: ""}, ...] + dictionary.forEach((v) => { + arr.push({ text: v.name, value: v.value }) }) if (inputName == 'source_channel') { @@ -733,10 +812,6 @@ value: '0', }) } - if (inputName == 'status') { - //插入到arr的头部 - console.log(arr) - } this.picker_config[inputName].options = arr }, @@ -971,15 +1046,26 @@ changeCicker(e) { console.log('监听-下拉选择器', this.picker_input_name, e) let input_name = this.picker_input_name + + // 更新表单数据 this.formData[input_name] = e.value - this.picker_config[input_name]['text'] = e.text + + // 更新选择器文本 + this.picker_config[input_name].text = e.text + + // 特殊处理:来源选择 if (input_name == 'source') { - if (e.value != 1) { - this.formData.source_channel = '0' //0=线下 + if (e.value == 1) { + // 如果选择了线上,则清空来源渠道,等待用户选择 + this.formData.source_channel = '' + this.picker_config.source_channel.text = '点击选择' } else { - this.formData.source_channel = '' //线下 + // 如果选择了其他来源,则设置来源渠道为线下 + this.formData.source_channel = '0' //0=线下 + this.picker_config.source_channel.text = '线下' } } + this.cancelCicker() }, //关闭下拉选择器 diff --git a/pages/market/clue/index.vue b/pages/market/clue/index.vue index e039227..2d0c71b 100644 --- a/pages/market/clue/index.vue +++ b/pages/market/clue/index.vue @@ -15,57 +15,64 @@ - - - - - + + + + + + + + {{ v.customerResource.name }} + {{ v.customerResource.phone_number }} + + + 所属校区:{{ v.customerResource.campus_name }} + + + 来源:{{ v.customerResource.source }} + + + 来源渠道:{{ v.customerResource.source_channel }} - {{ v.customerResource.name }} - {{ v.customerResource.phone_number }} - - - 所属校区:{{ v.customerResource.campus_name }} - - - 来源渠道:{{ v.customerResource.source_channel }} + + + + + + + + + + + - - {{ $util.formatToDateTime((v.customerResource.updated_at || ''), 'm-d H:i') }} - 跟进 + + {{ $util.formatToDateTime((v.customerResource.communication_time || ''), 'm-d H:i') }} + 拨打电话 + + + 暂未联系 + + 是否有效:{{ v.sixSpeed && v.sixSpeed.efficacious === 1 ? '有效' : '无效' }} + - - - - - 是否有效:{{ v.customerResource && v.customerResource.initial_intent_name || '' }} - - - - - - - - @@ -81,22 +88,34 @@ - - - - - + + + + + + + + {{v.customerResource.name}} + + + + 决策人:{{v.customerResource.name}} {{v.customerResource.decision_maker}} - {{v.customerResource.name}} - - - 决策人:{{v.customerResource.name}} {{v.customerResource.decision_maker}} + + + 分配 + + + - - {{ $util.formatToDateTime((v.customerResource.updated_at || ''),'m-d H:i') }} 跟进 + + {{ $util.formatToDateTime((v.customerResource.communication_time || ''),'m-d H:i') }} 拨打电话 + + + 暂未联系 @@ -116,9 +135,6 @@ - - 分配 - @@ -136,7 +152,7 @@ 筛选 - + 校区筛选 @@ -146,8 +162,8 @@ - - + + 时间筛选 @@ -238,7 +254,7 @@ shared_at_str: '', //共享时间|开始时间(Y-m-d)-结束时间(Y-m-d) phone_number: '', //客户资源表-手机号 name: '', //客户资源表-用户姓名 - campus_name:'', + campus_name: '', }, //数据列表 tableList_1: [], //表格数据 @@ -253,7 +269,7 @@ shared_at_str: '', //共享时间|[开始时间(Y-m-d),结束时间(Y-m-d)] phone_number: '', //客户资源表-手机号 name: '', //客户资源表-用户姓名 - campus_name:'', + campus_name: '', }, //数据列表 tableList_2: [], //表格数据 @@ -274,7 +290,7 @@ //抽屉搜索条件展示窗相关 showDrawer: false, //是否展示|false=否 showDrawerForm: { - campus_name:'', + campus_name: '', shared_at_str: '', //共享时间|[开始时间(Y-m-d),结束时间(Y-m-d)] phone_number: '', //客户资源表-手机号 name: '', //客户资源表-用户姓名 @@ -358,11 +374,11 @@ //获取全部员工 - async getPersonnelAll(campus='') { + async getPersonnelAll(campus = '') { let res = await apiRoute.common_getPersonnelAll({ personnel_id: this.userInfo.id, //客户id account_type: 'market', //账号类型|teacher=老师,market=销售 - campus:campus + campus: campus }) if (res.code != 1) { uni.showToast({ @@ -411,10 +427,6 @@ //判断是否还有数据 if (this.filteredData_1.page * this.filteredData_1.limit > this.filteredData_1.total) { this.loading = false - uni.showToast({ - title: '暂无更多', - icon: 'none' - }) return } @@ -470,10 +482,6 @@ //判断是否还有数据 if (this.filteredData_2.page * this.filteredData_2.limit > this.filteredData_2.total) { this.loading = false - uni.showToast({ - title: '暂无更多', - icon: 'none' - }) return } @@ -556,28 +564,27 @@ return; } - - let param = { - staff_id: this.userInfo.id, //员工id - resource_id: item.customerResource.id, //资源ID - resource_type: '', //资源类型(如设备、文件、系统等) - communication_type: 'phone', //沟通类型: phone-电话, email-邮件, meeting-会议, other-其他 - communication_result: 'success', //沟通结果: success-成功, failure-失败, pending-待定 - remarks: null, //备注 - tag: null, //标签 - } - - let res = await apiRoute.xs_communicationRecordsAdd(param) //添加通过记录 - if (res.code != 1) { - uni.showToast({ - title: res.msg, - icon: 'none' - }) - return - } - uni.makePhoneCall({ - phoneNumber: tel + phoneNumber: tel, + success: () => { + let param = { + staff_id: this.userInfo.id, //员工id + resource_id: item.customerResource.id, //资源ID + resource_type: '', //资源类型(如设备、文件、系统等) + communication_type: 'phone', //沟通类型: phone-电话, email-邮件, meeting-会议, other-其他 + communication_result: 'success', //沟通结果: success-成功, failure-失败, pending-待定 + remarks: null, //备注 + tag: null, //标签 + } + apiRoute.xs_communicationRecordsAdd(param).then(ressuccess=>{ + if(ressuccess.code != 1){ + uni.showToast({ + title: res.msg, + icon: 'none' + }) + } + }) + } }) }, @@ -756,7 +763,55 @@ background: #434544; border-radius: 16rpx; display: flex; - align-items: center; + flex-direction: column; + + .card-content { + display: flex; + justify-content: space-between; + + .card-left { + flex: 1; + padding-right: 10rpx; + } + + .card-right { + min-width: 120rpx; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + padding: 20rpx; + + .btn-item { + margin-bottom: 20rpx; + display: flex; + justify-content: center; + align-items: center; + width: 80rpx; + height: 80rpx; + background-color: rgba(255, 255, 255, 0.1); + border-radius: 50%; + + &:last-child { + margin-bottom: 0; + } + + .image { + width: 60rpx; + height: 60rpx; + } + } + } + } + + .card-footer { + width: 100%; + border-top: 1rpx solid rgba(255, 255, 255, 0.1); + padding: 20rpx; + box-sizing: border-box; + background-color: rgba(0, 0, 0, 0.1); + border-radius: 0 0 16rpx 16rpx; + } } .card-image { @@ -810,8 +865,8 @@ } .image { - width: 70rpx; - height: 70rpx; + width: 60rpx; + height: 60rpx; } .neck {