2 Commits 22faadc7c9 ... ce31f08918

Author SHA1 Message Date
  Pojun ce31f08918 Merge branch 'master' of http://www.kingtomtech.com:10101/kingtom/rkz_fy-master 7 months ago
  Pojun 93030adcfd 可视化页面相关代码提交 7 months ago

+ 10 - 0
tip-front/src/main/java/com/minto/app/task/controller/TaskController.java

@@ -9604,4 +9604,14 @@ public class TaskController extends BaseController {
         ModelAndView view = new ModelAndView("apps/task/type/settingModal");
         return view;
     }
+
+    /**
+     * 数据可视化
+     * @return
+     */
+    @GetMapping("/task/dataVisualization")
+    public ModelAndView dataVisualization(HttpServletRequest request,HttpServletResponse response) throws Exception {
+        ModelAndView view = new ModelAndView("apps/task/dataVisualization/index");
+        return view;
+    }
 }

+ 323 - 0
tip-front/src/main/webapp/WEB-INF/pages/apps/task/dataVisualization/index.html

@@ -0,0 +1,323 @@
+<!--
+  ~ Copyright (c) 2014, 2023, Chengdu Minto Technology Co.,LTD. All rights reserved.
+  ~ DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+  -->
+<!DOCTYPE html>
+<html lang="en" xmlns:th="http://www.thymeleaf.org">
+<head>
+    <meta charset="UTF-8">
+    <title>督办事项整体情况分析</title>
+    <link href="../../../../../common/element-ui/theme-chalk/index.css" rel="stylesheet"
+          th:href="@{/common/element-ui/theme-chalk/index.css}">
+    <link href="../../../../../common/css/dataVi.css" rel="stylesheet" th:href="@{/common/css/dataVi.css}">
+    <style>
+        [v-cloak]{
+            display: none;
+        }
+    </style>
+</head>
+<body>
+<div class="flex-column" id="app" v-cloak>
+    <div class="page-header flex">
+        <div class="page-header-title">督办事项整体情况分析</div>
+        <div class="flex" style="align-items: center">
+            <dv-decoration-3 style="width: 250px; height: 30px"></dv-decoration-3>
+            <el-dropdown @command="changeYear">
+                <el-button size="small">
+                    {{defaultYear}}<i class="el-icon-caret-bottom el-icon--right"></i>
+                </el-button>
+                <el-dropdown-menu slot="dropdown">
+                    <el-dropdown-item v-for="(item,index) in yearsList" :key="index" :command="item">{{item}}</el-dropdown-item>
+                </el-dropdown-menu>
+            </el-dropdown>
+        </div>
+    </div>
+    <div class="content flex">
+        <div class="content-left flex-column">
+            <!-- 内容太多了. 用vue做了. 数据到时候想办法堆出来 -->
+            <div :key="index" class="container flex-column" v-for="(item,index) in leftData">
+                <div class="container-title">{{item.title}}</div>
+                <div class="container-cont">
+                    <div class="container-cont-main cornerBox flex">
+                        <div class="fs28 color-18">{{item.totalNumber}}</div>
+                        <div class="fs16 color-a0">{{item.totalUnit}}</div>
+                    </div>
+                    <div class="container-cont-sub flex mt10">
+                        <div
+                                :class="{'special ':chilIndex==2}"
+                                :key="chilIndex"
+                                class="pl20 cornerBox"
+                                v-for="(chid,chilIndex) in item.list"
+                        >
+                            <div :class="{'color-ff ':chilIndex==2}" class="fs24 color-18">{{chid.number}}</div>
+                            <div :class="{'color-ec ':chilIndex==2}" class="fs12 color-ae">{{chid.name}}</div>
+                        </div>
+                    </div>
+                    <div class="container-cont-step flex">
+                        <span class="fs14 color-18">办结率</span>
+                        <div class="step-box">
+                            <div
+                                    :style="{color:item.colors[0], left:(item.progress-4>0 ? item.progress-4 : item.progress)+'%'}"
+                                    class="step-box-progress fs12"
+                                    v-if="item.progress"
+                            >
+                                {{item.progress}}%
+                            </div>
+                            <!-- 倒三角 -->
+                            <div
+                                    :style="{
+                      borderTopColor:item.colors[1],
+                      left:(item.progress-3>0 ? item.progress-3 : item.progress)+'%'
+                    }"
+                                    class="step-percent-triangle"
+                            ></div>
+                            <dv-percent-pond
+                                    :config="{
+                                  value: item.progress,
+                                  borderWidth:0.5,
+                                  borderGap:2,
+                                  borderRadius:0,
+                                  localGradient:true,
+                                  colors:item.colors
+                                }"
+                                    class="step-box-pond"
+                            ></dv-percent-pond>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+        <div class="content-center flex-column">
+            <div class="container content-center-head flex">
+                <div class="center-head-left">
+                    <div class="fs28">{{tAllCount}}</div>
+                    <div class="fs22 title">共办理事项</div>
+                </div>
+                <div class="center-head-right flex">
+                    <div v-for="(item, index) in mainRenderData" :key="index">
+                        <div class="fs22 color-18">{{item.name}}</div>
+                        <div class="fs16 color-a0">{{item.text}}</div>
+                    </div>
+                </div>
+            </div>
+            <dv-border-box-8 class="container content-center-cont">
+                <div class="container-title">责任单位承办事项完成效率分析</div>
+                <dv-scroll-board :config="tableConfig" style="flex: 1"></dv-scroll-board>
+            </dv-border-box-8>
+        </div>
+        <div class="content-right">
+            <div class="container">
+                <div class="container-title">考核平均完成事项时长排名</div>
+            </div>
+            <div class="content-right-table">
+                <dv-scroll-ranking-board :config="config" style="width: 380px; height: 830px"></dv-scroll-ranking-board>
+            </div>
+        </div>
+    </div>
+</div>
+<script src="../../../../../common/jquery/jquery.min.js" th:src="@{/common/jquery/jquery.min.js}"
+        type="text/javascript"></script>
+<script src="../../../../../common/ajax.js" th:src="@{/tc_ttp/common/ajax.js}" type="text/javascript"></script>
+<script src="../../../../../tc_ttp/common/tc.js" th:src="@{/tc_ttp/common/tc.js}" type="text/javascript"></script>
+<script th:src="@{/common/vue/vue.min.js}" type="text/javascript"></script>
+<script src="../../../../../common/element-ui/index.js" th:src="@{/common/element-ui/index.js}"
+        type="text/javascript"></script>
+<script th:src="@{/common/js/datav.min.js}" type="text/javascript"></script>
+<script>
+    new Vue({
+        el: '#app',
+        data() {
+            return {
+                leftData: [],
+                config: {},
+                tableConfig: {},
+                tableHeader: [
+                    {name: "责任单位", value: "targetName"},
+                    {name: "办理事项总数", value: "count"},
+                    {name: "推进中事项", value: "doCount"},
+                    {name: "超期事项", value: "overdueCount"},
+                    {name: "超期率", value: "overduePercent"},
+                    {name: "被催办次数", value: "remindCount"},
+                    {name: "被退回次数", value: "backCount"},
+                    {name: "已办结事项", value: "finishCount"},
+                    {name: "办结率", value: "finishPercent"},
+                ],
+                mainRenderData:[
+                    {name:"仍在办理",text:"",key:"tDoCount",unit:"(项)"},
+                    {name:"已超期",text:"",key:"tOverdueCount",unit:"(项)"},
+                    {name:"超期率",text:"",key:"tOverduePercent",unit:"%"},
+                    {name:"已经办结",text:"",key:"tAllFinishCount",unit:"(项)"},
+                ],// 主要的渲染数据
+                tAllCount:{},// 中间总办理事项
+                defaultYear: new Date().getFullYear(),// 默认年份
+                yearsList: [],// 年份列表
+            };
+        },
+        methods: {
+            // 处理不同分辨率情况下容器缩放比例
+            resize() {
+                let container = document.querySelector('#app');
+                let scale = Math.min(
+                    window.innerWidth / container.clientWidth,
+                    window.innerHeight / container.clientHeight
+                );
+                container.style.transform = 'scale(' + scale + ')';
+            },
+            // 获取中间数据
+            getCenterData() {
+                let _that = this;
+                let param = {
+                    orgName: "",
+                    taskTypeId: "0",
+                    year: _that.defaultYear
+                };
+                callAjaxRequest("taskAnalysisWebService", "findTaskTaskAnalysisByManager", param, function (result) {
+                    _that.tAllCount = result.tAllCount || "";
+                    _that.setTableConfig(result.list || []);
+                    _that.setMainRenderData(result);
+                })
+            },
+            // 表格数据处理
+            setTableConfig(data) {
+                let _that = this;
+                // 按照header的顺序便利出数据
+                let renderData = [];
+                for (let i = 0, len = data.length; i < len; i++) {
+                    let item = data[i];
+                    let rowData = [];
+                    for (let j = 0; j < _that.tableHeader.length; j++) {
+                        let headerItem = _that.tableHeader[j];
+                        if (["overduePercent", "finishPercent"].includes(headerItem.value)) {
+                            item[headerItem.value] = item[headerItem.value] + "%"
+                        }
+                        rowData.push(item[headerItem.value])
+                    }
+                    renderData.push(rowData)
+                }
+                this.tableConfig = {
+                    rowNum: 15,
+                    headerHeight: 40,
+                    header: this.tableHeader.map(function (item) {
+                        return item.name
+                    }),
+                    data: renderData,
+                    align: 'center',
+                    oddRowBGC: 'transparent',
+                    evenRowBGC: 'transparent',
+                    headerBGC: 'transparent',
+                    columnWidth: [90, 100, 100, 90, 80, 100, 100, 100, 80],
+                }
+            },
+            // 中间区域头部数据
+            setMainRenderData(data){
+                this.mainRenderData.map(function (item){
+                    item.text = data[item.key]+item.unit
+                })
+            },
+            // 获取右侧数据,使用考核的接口, 固定按照平均完成时间排序
+            getRightData(){
+                let _that = this;
+                let param = {
+                    year: _that.defaultYear,
+                    taskTypeId: '0',
+                    orgName: '',
+                    gbTaskTypeId: '',
+                    order: "avgTime",
+                    asc: 1
+                }
+                callAjaxRequest("taskAnalysisWebService", "findEvaluateAnalysis", param, function (result) {
+                    let data = result.map(function (item){
+                        return{
+                            name: item.pname,
+                            value: item.avgtime
+                        }
+                    })
+                    _that.config = {
+                        rowNum: 12,
+                        data:data,
+                        sort:false,
+                        valueFormatter(item){
+                            return _that.formatTimestampToHMS(item.value)
+                        }
+                    }
+                })
+            },
+            formatTimestampToHMS (diffInMilliseconds) {
+                let diffInSeconds = Math.floor(diffInMilliseconds / 1000);
+                let days = Math.floor(diffInSeconds / (3600 * 24));
+                let hours = Math.floor((diffInSeconds % (3600 * 24)) / 3600);
+                let minutes = Math.floor((diffInSeconds % 3600) / 60);
+                let seconds = diffInSeconds % 60;
+                // 格式化输出,确保每部分都是两位数字
+                let formattedDays = days == 0 ? '' : ''+days+'天';
+                let formattedHours = ('0' + hours).slice(-2);
+                let formattedMinutes = ('0' + minutes).slice(-2);
+                let formattedSeconds = ('0' + seconds).slice(-2);
+                return `${formattedDays}${formattedHours}:${formattedMinutes}:${formattedSeconds}`;
+            },
+            // 年份默认当前年份,以及前2年?
+            initYearsList(){
+                for(let  i= 0; i <= 2; i++) {
+                    this.yearsList.push(this.defaultYear - i)
+                }
+            },
+            // 年份的变动
+            changeYear(e){
+                this.defaultYear = e;
+                this.getCenterData();
+                this.getRightData();
+                this.getLeftData();
+            },
+            // 获取左侧数据
+            getLeftData(){
+                let _that = this;
+                let param = {
+                    orgName: "",
+                    taskTypeId: "0",
+                    year: _that.defaultYear
+                };
+                callAjaxRequest("taskAnalysisWebService", "findTaskTaskAnalysisByType", param, function (result) {
+                    _that.setLeftData(result.list)
+                })
+            },
+            // 设置左侧数据
+            setLeftData(list){
+                let colors = [
+                    ['#FFF1BC', '#FED35D'],
+                    ['#428FE0', '#73F7FB'],
+                    ['#FF4A6B', 'rgba(255, 141, 182, 0.77)']
+                ]
+                let renderList = [];
+                // 数据永远是三条, 就算不满足也是3
+                for(let i = 0; i < 3; i++) {
+                    let item = list[i];
+                    renderList.push(
+                        {
+                            title: item ? item.targetName :"无类型统计",
+                            totalNumber:item ? item.allCount :"0",
+                            totalUnit: '办理事项总数(项)',
+                            list: [
+                                {name: '推进中(项)', number: item ? item.doCount : "0"},
+                                {name: '已办结(项)', number: item ? item.finishCount :"0"},
+                                {name: '超期事项(项)', number: item ? item.overdueCount :"0"},
+                            ],
+                            progress: item ? item.finishPercent : 0,
+                            colors: colors[i],
+                        }
+                    )
+                }
+                this.leftData = renderList
+            }
+        },
+        mounted() {
+            this.resize();
+            window.addEventListener('resize', this.resize);
+        },
+        created() {
+            this.initYearsList();
+            this.changeYear(this.defaultYear)
+        }
+    });
+</script>
+</body>
+</html>

+ 303 - 0
tip-front/src/main/webapp/common/css/dataVi.css

@@ -0,0 +1,303 @@
+html,
+body {
+	width: 1920px;
+	height: 1080px;
+	overflow: hidden;
+}
+* {
+	margin: 0;
+	padding: 0;
+	box-sizing: border-box;
+}
+[v-cloak] {
+	display: none;
+}
+/* 公用class */
+.flex {
+	display: flex;
+	flex-direction: row;
+}
+.flex-column {
+	display: flex;
+	flex-direction: column;
+}
+.flex-1 {
+	flex: 1;
+}
+.fs12 {
+	font-size: 12px;
+}
+.fs14 {
+	font-size: 14px;
+}
+.fs16 {
+	font-size: 16px;
+}
+.fs18 {
+	font-size: 18px;
+}
+.fs24 {
+	font-size: 24px;
+}
+.fs20 {
+	font-size: 20px;
+}
+.fs22 {
+	font-size: 22px;
+}
+.fs28 {
+	font-size: 28px;
+}
+.color-18 {
+	color: #edf6ff;
+	text-shadow: 0px 0px 9px #18b3e4;
+}
+.color-a0 {
+	color: #a0d2ff;
+}
+.color-ae {
+	color: #aeceec;
+}
+.color-ec {
+	color: #ecc4ae;
+}
+.color-ff {
+	color: #fff;
+	text-shadow: 0px 0px 5px #ff7d1f;
+}
+.mt10 {
+	margin-top: 10px;
+}
+.pl20 {
+	padding-left: 20px;
+}
+
+/* 公用class */
+#app {
+	/* 以设计图的尺寸作为基准, 做缩放处理 */
+	width: 1920px;
+	height: 1080px;
+	background-image: url(datav/page.jpeg);
+	background-repeat: no-repeat;
+	background-size: cover;
+	transform-origin: top left;
+	transform: scale(1); /* 根据实际情况调整缩放比例 */
+}
+.page-header {
+	height: 80px;
+	background: linear-gradient(180deg, #001940 0%, #244b84 139.06%);
+	align-items: center;
+	justify-content: space-between;
+	padding-right: 60px;
+}
+.page-header-title {
+	width: 650px;
+	height: 90px;
+	line-height: 90px;
+	background-image: url(datav/header.png);
+	background-repeat: no-repeat;
+	background-size: cover;
+	padding-left: 80px;
+
+	font-size: 32px;
+	color: #fff;
+	font-weight: 400;
+	letter-spacing: 6px;
+	text-shadow: 0px 0px 4px rgba(42, 114, 255, 1);
+}
+/* 带边角容器 */
+.cornerBox {
+	width: 200px;
+	height: 100px;
+	position: relative;
+	border: 1px solid #296297;
+	padding: 0 20px;
+	background: rgba(0, 14, 59, 0.5);
+}
+.cornerBox.special {
+	border: 1px solid #975e29;
+	background: rgba(59, 11, 0, 0.5);
+}
+.cornerBox::after {
+	content: '';
+	position: absolute;
+	top: -1px;
+	left: -1px;
+	width: 0;
+	height: 0;
+	border: 7px solid #00a3ff;
+	border-right-color: transparent;
+	border-bottom-color: transparent;
+}
+.cornerBox::before {
+	content: '';
+	position: absolute;
+	bottom: -1px;
+	right: -1px;
+	width: 0;
+	height: 0;
+	border: 7px solid #00a3ff;
+	border-left-color: transparent;
+	border-top-color: transparent;
+}
+.cornerBox.special::after {
+	border-left-color: #ff9900;
+	border-top-color: #ff9900;
+}
+.cornerBox.special::before {
+	border-right-color: #ff9900;
+	border-bottom-color: #ff9900;
+}
+/* 带边角容器 */
+.content {
+	padding: 50px 60px;
+	flex: 1;
+	overflow: hidden;
+}
+.content-left,
+.content-right {
+	width: 420px;
+	justify-content: space-between;
+}
+.content-left .container {
+	height: 274px;
+	padding-top: 10px;
+	background: linear-gradient(180deg, rgba(57, 95, 136, 0.282) 0%, rgba(7, 46, 87, 0.6) 100%);
+}
+.container .container-title {
+	height: 32px;
+	line-height: 32px;
+	color: #fff;
+	font-size: 16px;
+	font-weight: 600;
+	background-image: url(datav/title.png);
+	background-repeat: no-repeat;
+	background-size: contain;
+	padding-left: 20px;
+}
+.container .container-cont {
+	padding: 20px 20px 0;
+	flex: 1;
+}
+.container .container-cont-main {
+	width: 100%;
+	height: 60px;
+	justify-content: space-between;
+	align-items: center;
+}
+.container .container-cont-sub {
+	justify-content: space-between;
+}
+.container .container-cont-sub > div {
+	width: 118px;
+	height: 66px;
+	display: flex;
+	flex-direction: column;
+	justify-content: center;
+}
+.container .container-cont-step {
+	margin-top: 40px;
+	align-items: center;
+}
+.step-box {
+	flex: 1;
+	margin-left: 10px;
+	position: relative;
+}
+.step-box-pond {
+	height: 14px;
+}
+.step-box-progress {
+	position: absolute;
+	top: -30px;
+}
+.step-percent-triangle {
+	position: absolute;
+	top: -10px;
+	width: 0;
+	height: 0;
+	border: 7px solid transparent;
+}
+
+.dv-percent-pond text {
+	display: none;
+}
+
+/* 中间 */
+
+.content-center {
+	flex: 1;
+	margin: 0 60px;
+	overflow: hidden;
+}
+.content-center-head {
+	height: 210px;
+	align-items: center;
+	margin-bottom: 20px;
+}
+.center-head-left {
+	width: 180px;
+	height: 100%;
+	background-image: url(datav/center.png);
+	background-size: 100% 100%;
+	background-repeat: no-repeat;
+	text-align: center;
+	padding-top: 35px;
+	color: #fff;
+	text-shadow: 0px 0px 5px rgba(126, 255, 229, 1);
+}
+.center-head-left .title {
+	margin-top: 75px;
+	background: -webkit-linear-gradient(6.32deg, #218dff -1.45%, #37ffff 75.7%);
+	background: linear-gradient(6.32deg, #218dff -1.45%, #37ffff 75.7%);
+	-webkit-background-clip: text;
+	background-clip: text;
+	-webkit-text-fill-color: transparent;
+	color: transparent;
+	text-shadow: initial;
+}
+
+.center-head-right {
+	margin-left: 80px;
+	flex-wrap: wrap;
+	justify-content: space-between;
+	flex: 1;
+	padding: 25px 0;
+	height: 100%;
+	align-content: space-between;
+}
+
+.center-head-right > div {
+	display: flex;
+	align-items: center;
+	justify-content: space-between;
+	width: 260px;
+	height: 58px;
+	line-height: 58px;
+	padding: 0 40px 0 60px;
+	background-image: url(datav/center-box.png);
+	background-repeat: no-repeat;
+	background-size: cover;
+}
+
+.content-center-cont {
+	flex: 1;
+	background: linear-gradient(180deg, rgba(57, 95, 136, 0.282) 0%, rgba(7, 46, 87, 0.6) 100%);
+	padding-top: 10px;
+	overflow: hidden;
+}
+.content-center-cont .border-box-content {
+	flex: 1;
+	display: flex;
+	flex-direction: column;
+}
+.dv-scroll-board .header .header-item {
+	text-overflow: unset !important;
+}
+/* 右侧 */
+.content-right {
+	background: linear-gradient(180deg, rgba(57, 95, 136, 0.282) 0%, rgba(7, 46, 87, 0.6) 100%);
+}
+.content-right-table {
+	padding: 20px;
+}

BIN
tip-front/src/main/webapp/common/css/datav/center-box.png


BIN
tip-front/src/main/webapp/common/css/datav/center.png


BIN
tip-front/src/main/webapp/common/css/datav/header.png


BIN
tip-front/src/main/webapp/common/css/datav/page.jpeg


BIN
tip-front/src/main/webapp/common/css/datav/title.png


File diff suppressed because it is too large
+ 0 - 0
tip-front/src/main/webapp/common/js/datav.min.js


File diff suppressed because it is too large
+ 0 - 0
tip-front/src/main/webapp/tc_suite/crypto/crypto-js.min.js


+ 43 - 2
tip-front/src/main/webapp/tc_suite/index_mbdb.jsp

@@ -1501,14 +1501,18 @@
                                                          alt="">
                                                 </div>
 
-                                                <div style="margin-left: 40px;cursor: pointer" id="openImModal">
+                                                <div style="margin-left: 40px;cursor: pointer" id="openHuaDuApp" title="IM">
+                                                    <img src="${path}/tc_suite/home/images/msg.png" alt="" style="width: 16px;height: 16px">
+                                                </div>
+
+                                                <div style="margin-left: 40px;cursor: pointer" id="openImModal" title="IM">
                                                     <img src="${path}/tc_suite/home/images/msg.png" alt="" style="width: 16px;height: 16px">
                                                 </div>
 
                                                 <%--inspired 增加推荐框--%>
                                                 <c:set var="openRecommend"
                                                        value='<%=AppContext.getProperty("recommend.open")%>'/>
-                                                <div class="tipsDiv" id="meesageInfo">
+                                                <div class="tipsDiv" id="meesageInfo" title="消息">
                                                     <span class="tipsSpan" id="redSpot"></span>
                                                     <img src="${path}/tc_suite/home/images/tips.png"
                                                          alt="">
@@ -1698,6 +1702,8 @@
 <script type="text/javascript" src="${path}/webjars/sockjs-client/sockjs.min.js"></script>
 <script type="text/javascript" src="${path}/webjars/stomp-websocket/stomp.min.js"></script>
 <script type="text/javascript" src="${path}/main/layout/js/message.min.js${resSuffix}"></script>
+<script type="text/javascript" src="${path}/tc_suite/crypto/crypto-js.min.js${resSuffix}"></script>
+
 <script>
 
     let clientWidth = $(window).width();
@@ -3756,6 +3762,41 @@
         });
     });
 
+    $("#openHuaDuApp").click(function () {
+        function encrypt  (data) {
+            /* AES前端加密 */
+            let key = CryptoJS.enc.Utf8.parse('4Dd2Bb3Cc1Aa5Ee0');
+            let iv = CryptoJS.enc.Utf8.parse('4Dd2Bb3Cc1Aa5Ee0');
+            let str = CryptoJS.AES.encrypt(data, key, {
+                iv: iv,
+                mode: CryptoJS.mode.CBC,
+                padding: CryptoJS.pad.ZeroPadding,
+            }).toString();
+            let val = str
+                .replace('#', '%23')
+                .replace('%', '%25')
+                .replace('&', '%26')
+                .replace('+', '%2B')
+                .replace('//', '%2F')
+                .replace('?', '%3F');
+            return val;
+        };
+        $.ajax({
+            type: "post",
+            url: "http://47.105.108.132:9999/dockingLogin",
+            dataType: "json",
+            data:{
+                username:"admin",
+                password: encrypt('123456')
+            },
+            success: function (data) {
+                if(data.code == 200){
+                    window.open('http://47.105.108.132:9998/home?token='+data.data);
+                }
+            },
+        });
+    });
+
     /**
      * 检查是否有未读消息,,如果有就显示红点,没有就不显示
      */

Some files were not shown because too many files changed in this diff