diff --git a/src/api/modules/api.js b/src/api/modules/api.js index ae55350..26cc2dc 100644 --- a/src/api/modules/api.js +++ b/src/api/modules/api.js @@ -1239,4 +1239,12 @@ export function updateMessageType(data) { method: 'post', data: data }) +} + +// 日报 +export function findByProjectId(data) { + return request({ + url: `/autoSR/customer/message/findByProjectId?id=${data}`, + method: 'GET', + }) } \ No newline at end of file diff --git a/src/page/index/top/index.vue b/src/page/index/top/index.vue index 50d25bb..61fe2b9 100644 --- a/src/page/index/top/index.vue +++ b/src/page/index/top/index.vue @@ -10,11 +10,12 @@ -->
-
- +
+
@@ -42,8 +43,18 @@ : "项目后台" }}
- - 切换后台 + + 切换后台
{{ companyName }}
- {{ + {{ orgType == 0 ? "切换后台" : orgType == 1 @@ -71,7 +91,8 @@ : orgType == 2 ? "切换公司" : "切换项目" - }} + }}
@@ -109,42 +130,41 @@ 通知(0)
--> - + - + - - + + + + - + - - + + - + - - + + {{ userInfo.username }} - + - - - 首页 - + + + 首页 + - + - - 主题设置 - + + 主题设置 + - - 帮助中心 - + + 帮助中心 + - - 账号设置 - + + 账号设置 + - + - - 退出系统 - + + 退出系统 + @@ -251,13 +276,14 @@ export default { filters: {}, data() { return { - circleUrl:"https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png", + circleUrl: + "https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png", options: [], value: "", companyName: localStorage.getItem("topName"), orgType: localStorage.getItem("orgType"), info: {}, - activeName: 'first', + activeName: "2", gridData: [], // 消息列表 gridDatas: [], // 日/周报列表 }; @@ -297,40 +323,61 @@ export default { getMessage() { // 固定获取当前的项目的 let paramsData = { - id: '', // + id: "", // num: 1, // 第几页 - size: 10, // 条数 - } - this.$api.http.messageList(paramsData).then(res => { - console.log(res, 'asdkdakl;asdadl;skdasl;adskl;sadkl;dsak;ldsa;lksd') - if (res.success) { - this.gridData = res.data.list.records - } - }).catch(e => { - console.log(e) - }) + size: 5, // 条数 + messageType: Number(this.activeName), + }; + this.$api.http + .messageList(paramsData) + .then((res) => { + console.log(res, "asdkdakl;asdadl;skdasl;adskl;sadkl;dsak;ldsa;lksd"); + if (res.success) { + if (paramsData.messageType == 3) + this.gridData = res.data.list.records; + if (paramsData.messageType != 3) + this.gridDatas = res.data.list.records; + } + }) + .catch((e) => { + console.log(e); + }); }, // 跳转公告列表页面 toMessageList() { - this.$router.push('/message') + this.$router.push("/message"); }, // 弹窗消息点击触发事件 msgTaps(e) { - console.log(e, 'asdjilksajl') - return + console.log(e, "asdjilksajl"); + // return + if (e.messageType == 1) { + // 日报 + this.$router.push({ + path: "/reportExcel/dayReport", + query: { + id: e.id, + }, + }); + } - // 日报 - // this.$router.push('/reportExcel/dayReport') - // 周报 - // this.$router.push('/reportExcel/weekReport') + if (e.messageType == 2) { + // 周报 + this.$router.push({ + path: "/reportExcel/weekReport", + query: { + id: e.id, + }, + }); + } }, // 弹窗消息点击触发事件 msgTap(e) { - console.log(e, 'asdjilksajl') - this.$store.commit('setMessage', e) - this.$router.push('/message/detail') + console.log(e, "asdjilksajl"); + this.$store.commit("setMessage", e); + this.$router.push("/message/detail"); }, handleScreen() { @@ -545,7 +592,7 @@ export default { setScreen() { this.$store.commit("SET_FULLSCREEN"); }, - helpCenter(){ + helpCenter() { this.$router.push({ path: "/login" }); }, logout() { @@ -564,76 +611,82 @@ export default { \ No newline at end of file diff --git a/src/views/reportExcel/weekReport.vue b/src/views/reportExcel/weekReport.vue index 380079c..f47f70a 100644 --- a/src/views/reportExcel/weekReport.vue +++ b/src/views/reportExcel/weekReport.vue @@ -3,11 +3,11 @@

- 桃源山庄数智工牌日报 - 01月24日 + {{ projectName }}销讲助手周报 + {{ weekObj.weekDate }}

- 生成时间:2022-01-30 8:00 + 生成时间:{{ weekObj.createTime || "--" }}

@@ -16,40 +16,210 @@
数据简报
- +
+
销讲场景执行排名
-
+
+ 暂无数据 +
+
-
- 销讲场景平均执行对比上周下跌12%,其中【送客执行】最强为99%,【区位介绍】执行最弱为25%; + +
+ 销讲场景平均执行对比上周 + {{ rankTop("fractionPKName") }}{{ rankTop("fractionPK") }}% + +
-
顾问工作统计
+
+ 顾问工作统计 +
- + + + + + +
+ 顾问平均执行率对比上周 + {{ rankTop("ranktype") }} + {{ rankTop("people") }} + 人,其中 + {{ rankTop("topName") }} + 上升 + {{ rankTop("topPk") || 0 }}% + 为最高, + {{ rankTop("lastName") }} + 下降 + {{ rankTop("lastPk") || 0 }}% + 降幅最大。 +
+ +
+
顾问排名
+
+
+
执行率TOP10
+
+
{{ percent.title }}
+
+ +
+
{{ percent.value || 0 }}%
+
+
+ 暂无数据 +
+
+
+
接待量TOP10
+
+
{{ percent.title }}
+
+ +
+
{{ percent.value || 0 }}
+
+ +
+ 暂无数据 +
+
+
+
+
+
{{ getTimeLine(weekObj.createTime, 2) }}
+
+
@@ -58,28 +228,383 @@ import * as echarts from "echarts"; export default { data() { return { - xData: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"], //横坐标 - yData: [23, 24, 18, 25, 27, 28, 25], //数据 + tableHead: [ + { + title: "顾问", + type: "name", + }, + { + title: "接待量", + type: "activeCustomer", + }, + { + title: "平均接待时长", + type: "avgDuration", + }, + { + title: "平均执行率", + type: "fraction", + }, + { + title: "对比上周", + type: "pk", + }, + ], + id: "", // id + + needList: ["JDLTop", "ZXLTop", "XJTop1"], // 需要转换数组的内容 + + // 简报 + numlist: [ + { + name: "接待量 (次)", + num: "", + setName: "receptionCount1", + percent: "", + percentName: "receptionCountPK", + preNum: "", // 上周数量 + preNumName: "receptionCount2", // + }, + { + name: "有效接待 (次)", + num: "", + setName: "activeCustomer1", + percent: "", + percentName: "activeCustomerPK", + preNum: "", // 上周数量 + preNumName: "activeCustomer2", // + }, + { + name: "平均执行率(%)", + num: "", + setName: "fraction1", + percent: "", + percentName: "fractionPK", + preNum: "", // 上周数量 + preNumName: "fraction2", // + }, + { + name: "平均接待时长(分)", + num: "", + setName: "avgDuration1", + percent: "", + percentName: "avgDurationPK", + preNum: "", // 上周数量 + preNumName: "avgDuration2", // + }, + { + name: "违禁接待 (次)", + num: "", + setName: "prohibitedNum1", + percent: "", + percentName: "prohibitedNumPK", + preNum: "", // 上周数量 + preNumName: "prohibitedNum2", // + }, + { + name: "客户画像触达 (次)", + num: "", + setName: "reachSum1", + percent: "", + percentName: "reachSumPK", + preNum: "", // 上周数量 + preNumName: "reachSum2", // + }, + { + name: "已标记", + num: "", + setName: "labelledReceptionNum1", + percent: "", + percentName: "labelledReceptionNumPK", + preNum: "", // 上周数量 + preNumName: "labelledReceptionNum2", // + }, + { + name: "未标记", + num: "", + setName: "unlabelledReceptionNum1", + percent: "", + percentName: "unlabelledReceptionNumPK", + preNum: "", // 上周数量 + preNumName: "unlabelledReceptionNum2", // + }, + ], + weekObj: {}, // 周报详情 + projectName: "", // 项目名称 + + xData: [], //横坐标 + color: ["#E7483C", "#FF8C13", "#FFCC00", "#43CD80"], + yData: [], //数据 myChartStyle: { width: "100%", height: "400px" }, //图表样式 }; }, + + computed: { + // 排名最高与最低 + rankTop() { + return (name) => { + let obj = {}; + try { + if ( + this.weekObj.customerInfo1.length && + this.weekObj.customerInfo2.length + ) { + obj.ranktype = + this.weekObj.customerInfo1.length - + this.weekObj.customerInfo2.length > + 0 + ? "上升" + : "下降"; + obj.people = Math.abs( + this.weekObj.customerInfo1.length - + this.weekObj.customerInfo2.length + ); + } + + if ( + this.weekObj.customerInfo1 && + this.weekObj.customerInfo1.length > 0 + ) { + obj.topName = this.weekObj.customerInfo1[0].name; + obj.topPk = Math.abs(this.weekObj.customerInfo1[0].pk); + (obj.lastName = + this.weekObj.customerInfo1[ + this.weekObj.customerInfo1.length - 1 + ].name), + (obj.lastPk = Math.abs( + this.weekObj.customerInfo1[ + this.weekObj.customerInfo1.length - 1 + ].pk + )); + } + + if ( + this.weekObj.customerInfo1.length && + this.weekObj.customerInfo2.length + ) { + obj.class = + this.weekObj.customerInfo1.length - + this.weekObj.customerInfo2.length > + 0 + ? "up" + : "down"; + } + + if (this.weekObj.fractionPK) { + obj.fractionPKName = this.weekObj.fractionPK > 0 ? "上涨" : "下跌"; + obj.fractionPK = Math.abs(this.weekObj.fractionPK); + } + + if (this.weekObj.XJTop1List && this.weekObj.XJTop1List.length > 0) { + obj.fractionBastName = this.weekObj.XJTop1List[0].title; + obj.fractionBastValue = this.weekObj.XJTop1List[0].value; + } + + if (this.weekObj.XJTop1List && this.weekObj.XJTop1List.length > 0) { + obj.fractionLastName = + this.weekObj.XJTop1List[this.weekObj.XJTop1List.length - 1].title; + obj.fractionLastValue = + this.weekObj.XJTop1List[this.weekObj.XJTop1List.length - 1].value; + } + + return obj[name] || ""; + } catch (e) { + console.log(e); + return ""; + } + }; + }, + }, + mounted() { - this.initEcharts(); + if (this.$route.query.id) this.id = this.$route.query.id; + + this.getMessage(); }, methods: { + // 截图 + savePicture() { + let save = document.querySelector("#screenShorts"); + html2canvas(save, { + allowTaint: true, ///允许跨域图片 + useCORS: true, //是否尝试使用CORS从服务器加载图像 + width: save2.offsetWidth, //为了解决安卓手机截图后出现白边的问题 + height: save2.offsetHeight, //为了解决安卓手机截图后出现白边的问题 + }).then((canvas) => { + let height = save.offsetHeight + "px"; + let width = save.offsetWidth + "px"; + canvas.style = `width:${width};height:${height};position:fixed;z-index:9999;`; + //为canvas添加样式 + let url = canvas.toDataURL("image/png"); //得到图片的base64编码数据 + let a = document.createElement("a"); // 生成一个a元素 + a.download = "photo"; // 设置图片名称 + a.href = url; // 将生成的URL设置为a.href属性 + }); + }, + + // 转换时间 + getTimeLine(date, type = 1) { + let resu = "--"; + if (!date) return resu; + let time = new Date(date.replace(/-/g, "/")); + time.setDate(time.getDate() - 7); + let arr = date.split(" "); + let str = arr[0]; + let result = str.split("-"); + + let m = + time.getMonth() + 1 < 10 + ? `0${time.getMonth() + 1}` + : time.getMonth() + 1; + let d = time.getDate() < 10 ? `0${time.getDate()}` : time.getDate(); + + if (type == 1) { + resu = `${m}.${d}-${result[1]}.${result[2]}`; + } else { + resu = `${m}月${d}日~${result[1]}月${result[2]}日`; + } + return resu; + }, + + // 获取消息详情 + getMessage() { + this.$api.api.findByProjectId(this.id).then((res) => { + if (res.code == 10000) { + console.log('dsadasd') + let data = JSON.parse(res.data.zkMessage.content); + console.log(data); + this.bubbleSort(data.customerInfo1, "pk"); + this.bubbleSort(data.customerInfo2, "pk"); + data.customerInfo1.reverse(); + data.customerInfo2.reverse(); + this.weekObj = { + ...res.data.zkMessage, + ...data, + }; + console.log(this.weekObj, "this.weekObj"); + this.projectName = res.data.projectName; + console.log(this.projectName) + this.numlist.forEach((item) => { + if (this.weekObj[item.setName]) { + item.num = this.weekObj[item.setName]; + } + if (this.weekObj[item.percentName]) { + item.percent = this.weekObj[item.percentName]; + } + if (this.weekObj[item.preNumName]) { + item.preNum = this.weekObj[item.preNumName]; + } + }); + this.init(); + } + }); + }, + + // 把对象转成数组并在后续的步骤方便处理 + init() { + console.log(this.weekObj, "this.weekObj"); + console.log(this.weekObj.XJTop1, "this.weekObj"); + this.needList.forEach((item) => { + console.log(this.weekObj[item], "this.weekObj[item]" + item); + if (this.weekObj[item] && Object.keys(this.weekObj[item]).length > 0) { + this.weekObj[item + "List"] = []; // 销讲执行 + for (let i in this.weekObj[item]) { + this.weekObj[item + "List"].push({ + title: i, + value: this.weekObj[item][i], + }); + } + } + }); + this.sortInitArr(); + }, + + // 排序对象转换后的数组 + sortInitArr() { + this.needList.forEach((item) => { + if (this.weekObj[item + "List"]) { + this.bubbleSort(this.weekObj[item + "List"]); + } + }); + + this.reverseList(); + }, + + // 反转数组并处理数据渲染echarts + reverseList() { + this.needList.forEach((item) => { + if (this.weekObj[item + "List"]) { + this.weekObj[item + "List"].reverse(); + } + }); + console.log(this.weekObj.XJTop1List, "this.weekObj.XJTop1List"); + if (this.weekObj.XJTop1List && this.weekObj.XJTop1List.length > 0) { + this.weekObj.XJTop1List.map((item, index) => { + this.xData.push(item.title); + this.yData.push({ + value: item.value, + itemStyle: { + color: this.$options.filters.setColor(index), + }, + }); + }); + this.$nextTick(() => { + this.initEcharts(); + }); + } + }, + + // 冒泡排序 + bubbleSort(arr, keys = "value") { + for (let i = 0; i < arr.length - 1; i += 1) { + //通过 arr.length 次把第一位放到最后,完成排序 + //-i是因为最后的位置是会动态改变的,当完成一次后,最后一位会变成倒数第二位 + for (let j = 0; j < arr.length - 1 - i; j += 1) { + if (arr[j][keys] > arr[j + 1][keys]) { + const temp = arr[j]; + arr[j] = arr[j + 1]; + arr[j + 1] = temp; + } + } + } + }, + initEcharts() { // 基本柱状图 const option = { xAxis: { data: this.xData, + axisLabel: { + interval: 0, + rotate: 20, + }, + }, + + yAxis: { + max: () => { + return 100; + }, }, - yAxis: {}, series: [ { type: "bar", //形状为柱状图 - barWidth: '40', + barWidth: "40", data: this.yData, + + itemStyle: { + normal: { + label: { + show: true, + distance: 20, + position: "top", + textStyle: { + color: "#333", + fontSize: 16, + }, + }, + }, + }, }, ], }; @@ -91,6 +616,50 @@ export default { }); }, }, + + filters: { + // 转换时间 + getTimeLine(date, type = 1) { + if (!date) return "--"; + let time = new Date(date); + time.setDate(time.getDate() - 7); + let arr = date.split(" "); + let str = arr[0]; + let result = str.split("-"); + + let m = + time.getMonth() + 1 < 10 + ? "0" + (time.getMonth() + 1) + : time.getMonth() + 1; + let d = time.getDate() < 10 ? "0" + time.getDate() : time.getDate(); + + if (type == 1) { + return m + "." + d + "-" + result[1] + "." + result[2]; + } else { + return m + "月" + d + "日~" + result[1] + "月" + result[2] + "日"; + } + }, + + // 设置颜色 + setColor(index) { + let color = ""; + switch (index) { + case 0: + color = "#E7483C"; + break; + case 1: + color = "#FF8C13"; + break; + case 2: + color = "#FFCC00"; + break; + default: + color = "#4FC78F"; + break; + } + return color; + }, + }, }; @@ -99,111 +668,226 @@ export default { margin: 20px 0 0 0; padding: 0 16px; width: 100%; + min-width: 1100px; +} - .page-box { - padding: 16px 18px; - background: #fff; +.page-box { + padding: 16px 18px; + background: #fff; +} - .head-box { - width: 100%; - display: flex; - flex-direction: column; - justify-content: center; +.page-box .head-box { + width: 100%; + display: flex; + flex-direction: column; + justify-content: center; +} - .h-item { - margin: 0; +.head-box .h-item { + margin: 0; +} - .titles { - margin: 0 16px 0 0; - font-size: 18px; - font-weight: 500; - } +.head-box .h-item .titles { + margin: 0 16px 0 0; + font-size: 18px; + font-weight: 500; +} - .times { - font-size: 14px; - color: #666666; - } - } - } - } - - .simple { - margin: 16px 0 0 0; - padding: 16px 18px; - width: 100%; - background: #fff; - - .simple-title { - font-size: 16px; - font-weight: 500; - } - .simple-box { - margin-top: 16px; - display: flex; - flex-wrap: wrap; - - .simple-item { - position: relative; - margin: 0 20px 16px 0; - padding: 20px; - width: 370px; - height: 150px; - border: 1px solid #e0e0e0; - border-radius: 4px; - overflow: hidden; - - &::before { - content: ""; - display: block; - position: absolute; - z-index: 1; - right: -40px; - bottom: -40px; - width: 125px; - height: 125px; - border-radius: 50%; - border: 30px solid rgba($color: #2671e2, $alpha: 0.06); - } +.head-box .h-item .times { + font-size: 14px; + color: #666666; +} - &:nth-of-type(4n) { - margin: 0 0 16px 0; - } +.ranking { + margin-top: 20px; + padding: 0 20px; + width: 100%; + background: #fff; +} - .middle-text { - margin: 18px 0; - font-size: 32px; - font-weight: bold; - } +.ranking .ranking-desc { + padding: 20px 0; + display: flex; + justify-content: center; +} - .bottom-text { - .b-t-text { - margin-left: 20px; - } - } - } - } - } - - .ranking { - margin-top: 20px; - width: 100%; - background: #fff; - .ranking-title { - padding: 16px 18px; - border-bottom: 1px solid #e0e0e0; - font-size: 16px; - font-weight: 600; - } - - .ranking-desc { - padding: 0 0 20px 0; - display: flex; - justify-content: center; - } - } - - .bottom { - height: 100px; - } +.ranking .ranking-title { + border-bottom: 1px solid #e0e0e0; + line-height: 54px; + font-size: 16px; + font-weight: 600; +} + +.bottom { + height: 100px; +} + +.simple { + margin: 16px 0 0 0; + padding: 16px 18px; + width: 100%; + background: #fff; +} + +.simple .simple-title { + line-height: 54px; + font-weight: 600; + font-size: 16px; +} + +.simple-boxs { + padding: 16px 0 0 0; +} + +.simple .simple-box { + display: flex; + flex-wrap: wrap; +} + +.simple .simple-item { + position: relative; + margin: 0 2.6% 16px 0; + padding: 20px; + width: 23%; + height: 150px; + border: 1px solid #e0e0e0; + border-radius: 4px; + overflow: hidden; +} + +.simple .simple-item::before { + content: ""; + display: block; + position: absolute; + z-index: 1; + right: -40px; + bottom: -40px; + width: 125px; + height: 125px; + border-radius: 50%; + border: 30px solid rgba(38, 113, 226, 0.06); +} + +.simple .simple-item:nth-of-type(4n) { + margin: 0 0 16px 0; +} + +.simple .simple-item .middle-text { + margin: 15px 0; + font-size: 32px; + font-weight: bold; +} + +.simple .simple-item .bottom-text .b-t-text { + margin-left: 20px; +} + +.simple-desc { + padding: 20px 0; + display: flex; + justify-content: center; +} + +.up { + color: #43cd80; +} + +.down { + color: #e6273a; +} + +.empity { + width: 100%; + height: 300px; + display: flex; + justify-content: center; + align-items: center; + font-size: 32px; + font-weight: 600; +} + +.adviser { + padding: 16px 18px; + width: 100%; + height: auto; + background: #fff; +} + +.adviser .adviser-title { + border-bottom: 1px solid #e0e0e0; + line-height: 54px; + font-weight: 600; + font-size: 16px; +} + +.adviser .adviser-box { + padding: 16px 0; + display: flex; +} + +.adviser .adviser-box .aitemsbox { + display: flex; +} + +.adviser .adviser-box .aitemsbox .left, +.adviser .adviser-box .aitemsbox .right, +.adviser .adviser-box .aitemsbox .middel { + flex-shrink: 0; +} + +.adviser .adviser-box .aitemsbox .left { + width: 110px; + line-height: 32px; +} + +.adviser .adviser-box .aitemsbox .right { + width: 90px; + line-height: 32px; +} + +.adviser .adviser-box .aitemsbox .left, +.adviser .adviser-box .aitemsbox .right { + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; +} + +.adviser .adviser-box .aitemsbox .middle { + margin: 0 20px; + width: 480px; + height: 32px; + display: flex; + align-items: center; +} + +.adviser .adviser-box .aitemsbox .middles-progress { + width: 100%; + height: 16px; +} + +.adviser .adviser-box .aitems .aitemstitle { + padding: 16px 0 14px 86px; + width: 100%; + font-size: 16px; + font-weight: bold; +} + +.adviser .adviser-box .aitems { + flex: 1; + display: flex; + align-items: center; + flex-direction: column; +} + +.adviser .adviser-box .aitems .empty { + width: 100%; + height: 400px; + display: flex; + justify-content: center; + align-items: center; +} + +.adviser .adviser-box .lside { + border-right: 1px solid #e0e0e0; } \ No newline at end of file diff --git a/vue.config.js b/vue.config.js index 69ec1fe..bef3690 100644 --- a/vue.config.js +++ b/vue.config.js @@ -3,10 +3,10 @@ * https://cli.vuejs.org/zh/config/ */ // const url = 'http://192.168.31.161:9999' //长龙 -// const url = 'http://192.168.31.101:9999' // 胜浩 +const url = 'http://192.168.31.108:9999' // 胜浩 // const url = 'https://zanyong.hfju.com' // 正式域名 // const url = 'http://127.0.0.1:9999' // 本地 -const url = 'http://81.70.55.170:9999' // 新测试 +// const url = 'http://81.70.55.170:9999' // 新测试 // const url = 'http://82.156.35.22:9999' // 新正式ip const CompressionWebpackPlugin = require('compression-webpack-plugin') const productionGzipExtensions = ['js', 'css']