瀏覽代碼

feat:下载pdf

guotianliang 4 年之前
當前提交
34ce8f00dc

+ 24 - 0
.eslintrc.js

@@ -0,0 +1,24 @@
+module.exports = {
+    // root:true,
+    // "env": {
+    //     "browser": true,
+    //     "es6": true
+    // },
+    // "extends": [
+    //     "eslint:recommended",
+    //     "plugin:vue/essential"
+    // ],
+    // "globals": {
+    //     "Atomics": "readonly",
+    //     "SharedArrayBuffer": "readonly"
+    // },
+    // "parserOptions": {
+    //     "ecmaVersion": 2018,
+    //     "sourceType": "module"
+    // },
+    // "plugins": [
+    //     "vue"
+    // ],
+    // "rules": {
+    // }
+};

+ 23 - 0
.gitignore

@@ -0,0 +1,23 @@
+.DS_Store
+node_modules
+/dist
+
+
+# local env files
+.env.local
+.env.*.local
+
+# Log files
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+pnpm-debug.log*
+
+# Editor directories and files
+.idea
+.vscode
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw?

+ 16 - 0
babel.config.js

@@ -0,0 +1,16 @@
+module.exports = {
+  presets: [
+    '@vue/cli-plugin-babel/preset'
+  ],
+  plugins: [
+    [
+      "component",
+      {
+        "libraryName": "meri-design",
+        "camel2Dash": false,
+        "libDir": "dist",
+        "styleLibrary": { "name": "theme", "base": true }
+      }
+    ]
+  ]
+}

文件差異過大導致無法顯示
+ 12989 - 0
package-lock.json


+ 47 - 0
package.json

@@ -0,0 +1,47 @@
+{
+  "name": "sagacloud-pdf-pages",
+  "version": "0.1.0",
+  "private": true,
+  "scripts": {
+    "serve": "vue-cli-service serve",
+    "build": "vue-cli-service build",
+    "lint": "vue-cli-service lint"
+  },
+  "dependencies": {
+    "axios": "^0.21.0",
+    "core-js": "^3.6.5",
+    "echarts": "^4.7.0",
+    "element-ui": "^2.13.2",
+    "html2canvas": "^1.0.0-rc.7",
+    "jspdf": "^2.2.0",
+    "meri-design": "^1.4.4",
+    "moment": "^2.29.1",
+    "vue": "^2.6.11",
+    "vue-router": "^3.2.0",
+    "vuex": "^3.4.0"
+  },
+  "devDependencies": {
+    "@vue/cli-plugin-babel": "^4.5.0",
+    "@vue/cli-plugin-eslint": "^4.5.0",
+    "@vue/cli-service": "^4.5.0",
+    "@vue/eslint-config-prettier": "^6.0.0",
+    "babel-eslint": "^10.1.0",
+    "babel-plugin-component": "^1.1.1",
+    "babel-plugin-syntax-jsx": "^6.18.0",
+    "babel-plugin-transform-runtime": "^6.23.0",
+    "babel-plugin-transform-vue-jsx": "^3.5.0",
+    "babel-preset-env": "^1.3.2",
+    "eslint": "^6.7.2",
+    "eslint-plugin-prettier": "^3.1.3",
+    "eslint-plugin-vue": "^7.3.0",
+    "less": "^3.13.0",
+    "less-loader": "^5.0.0",
+    "prettier": "^1.19.1",
+    "vue-template-compiler": "^2.6.11"
+  },
+  "browserslist": [
+    "> 1%",
+    "last 2 versions",
+    "not dead"
+  ]
+}

二進制
public/favicon.ico


+ 17 - 0
public/index.html

@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <meta charset="utf-8">
+    <meta http-equiv="X-UA-Compatible" content="IE=edge">
+    <meta name="viewport" content="width=device-width,initial-scale=1.0">
+    <link rel="icon" href="<%= BASE_URL %>favicon.ico">
+    <title><%= htmlWebpackPlugin.options.title %></title>
+  </head>
+  <body>
+    <noscript>
+      <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
+    </noscript>
+    <div id="app"></div>
+    <!-- built files will be auto injected -->
+  </body>
+</html>

+ 20 - 0
src/App.vue

@@ -0,0 +1,20 @@
+<template>
+  <div id="app">
+    <router-view/>
+     <img src="../static/images/logo.png" alt="" id="logo" style="width: 116px;"/>
+  </div>
+</template>
+
+<style>
+#app{
+
+    background: #cccccc;
+}
+#logo{
+  display: none;
+}
+.page_box{
+    width: 1200px;
+    margin: 0 auto;
+}
+</style>

+ 72 - 0
src/api/ReportForm/ReportForm.js

@@ -0,0 +1,72 @@
+import httputils from '@/api/httputils';
+
+// 合同查询
+export function queryContract({ postParams}) {
+    return httputils.postJson(`/duoduo-service/review-service/week/contract/query`, postParams)
+}
+// 合同新增/编辑
+export function editContract({ postParams}) {
+    return httputils.postJson(`/duoduo-service/review-service/week/contract/save`, postParams)
+}
+// 查询空间组列表
+export function querySpacegroup({ postParams}) {
+    return httputils.postJson(`/duoduo-service/object-service/object/spacegroup/query`, postParams)
+}
+// 查询周报
+export function queryWeek({ getParams}) {
+    return httputils.getJson(`/duoduo-service/review-service/week/query`, getParams)
+}
+// 周报---14天逐日达标率及平均温度
+export function queryWeekday({ postParams}) {
+    return httputils.postJson(`/duoduo-service/review-service/week/day/query`, postParams)
+}
+// 周报---空间环境温度不达标率(偏冷,偏热列表)
+export function querySubstandardList({ postParams}) {
+    return httputils.postJson(`/duoduo-service/review-service/week/queryNoStandardList`, postParams)
+}
+// 周报---日逐刻平均温度及达标率
+export function queryDay({postParams}) {
+    // postParams.criteria.time={
+    //     $gte:"060000",
+    //     $lte:"200000"
+    // }
+
+
+    return httputils.postJson(`/duoduo-service/review-service/week/quarter/queryAvgTempComplianceRate`, postParams)
+}
+// 周报---各温度区间的空间数量
+export function querysectionSpace({postParams}) {
+    return httputils.postJson(`/duoduo-service/review-service/week/day/queryTempSpaceRate`, postParams)
+}
+// 周报---各楼层平均温度及偏冷(热)空间数量
+export function querysectionFloor({postParams}) {
+    return httputils.postJson(`/duoduo-service/review-service/week/day/queryFloorAvgTempSpaceRate`, postParams)
+}
+// 周报---各达标区间空间数量分布
+export function queryStandardList({postParams}) {
+    return httputils.postJson(`/duoduo-service/review-service/week/queryStandardList`, postParams)
+}
+// 周报---环境温度分析
+export function queryWeekSpace({postParams}) {
+    return httputils.postJson(`/duoduo-service/review-service/week/spaceType/query`, postParams)
+}
+// 周报---用户活跃度统计
+export function queryUserActivity({postParams}) {
+    return httputils.postJson(`/duoduo-service/duoduoenv-service/user/queryUserActivityStatistics`, postParams)
+}
+// 周报---环境温度分析 (时间维度) 逐刻
+export function queryTempRate({postParams}) {
+    return httputils.postJson(`/duoduo-service/review-service/week/quarter/queryTempQuarterRate`, postParams)
+}
+// 解释保存
+export function explainSave({ getParams}) {
+    return httputils.getJson(`/duoduo-service/review-service/week/save`, getParams)
+}
+// 供冷供暖查询
+export function querySeason({ getParams}) {
+    return httputils.getJson(`/duoduo-service/custom-service/custom/getSeasonBySeasonDate`, getParams)
+}
+// 周报---合同与管控时间段
+export function queryCustormList({postParams}) {
+    return httputils.postJson(`/duoduo-service/review-service/week/contract/queryCustormList`, postParams)
+}

+ 189 - 0
src/api/httputils.js

@@ -0,0 +1,189 @@
+import axios from 'axios'
+import store from '@/store'
+import { MessageBox } from 'element-ui'
+
+var CancelToken = axios.CancelToken
+var cancel
+
+// 创建axios实例
+const axiosservice = axios.create({
+    timeout: 30000, // 请求超时时间
+    retry: 4, //重新请求次数
+    retryDelay: 1000, //重新请求的间隔
+    credentials: true, // 接口每次请求会跨域携带cookie
+    cancelToken: new CancelToken(function executor(c) {
+        // executor 函数接收一个 cancel 函数作为参数
+        cancel = c
+    })
+})
+
+axiosservice.interceptors.request.use(
+    config => {
+        config.withCredentials = true // 允许携带token ,这个是解决跨域产生的相关问题
+        // let token = store.getters['ssoToken']
+        // if (token) {
+        //     config.headers = {
+        //         'sso-token': token
+        //     }
+        // }
+        return config
+    },
+    error => {
+        return Promise.reject(error)
+    }
+)
+
+axiosservice.interceptors.response.use(
+    function(res) {
+        //在这里对返回的数据进行处理
+        //console.log('axios interceptors res = ', res.status, res)
+        // let resp = res.data
+        // if (resp.result === 'unauthc') {
+        //     store.commit('logined', false)
+        //     MessageBox.confirm('未登陆或登陆信息已失效, 是否重新登陆?', '提示', {
+        //         confirmButtonText: '确定',
+        //         cancelButtonText: '取消',
+        //         type: 'error'
+        //     })
+        //         .then(resp => {
+        //             //console.log('--------------------------- confirm', resp)
+        //             //router.push('/login')
+        //             window.location.reload()
+        //         })
+        //         .catch(error => {
+        //             //console.log('--------------------------- cancel', error)
+        //             console.log('')
+        //         })
+        // } else if (resp.result == 'unauthorization') {
+        //     MessageBox.alert('无权操作', { title: '警告', type: 'error' })
+        // }
+        //console.log('axios interceptors resp2 = ', resp.success, resp.errorCode, resp.errorMessage, res)
+        return res
+    },
+    function(err) {
+        //Do something with response error
+        console.log('axios interceptors err = ', err)
+        return Promise.reject(err)
+    }
+)
+
+/* 下载方法 */
+function downFile(blob, fileName,cb) {
+    // 非IE下载
+    if ('download' in document.createElement('a')) {
+        let link = document.createElement('a')
+        link.href = window.URL.createObjectURL(blob) // 创建下载的链接
+        link.download = fileName // 下载后文件名
+        link.style.display = 'none'
+        document.body.appendChild(link)
+        link.click() // 点击下载
+        window.URL.revokeObjectURL(link.href) // 释放掉blob对象
+        document.body.removeChild(link) // 下载完成移除元素
+        if(cb&&typeof cb==="function"){
+            cb()
+        }
+    } else {
+        // IE10+下载
+        window.navigator.msSaveBlob(blob, fileName)
+        if(cb&&typeof cb==="function"){
+            cb()
+        }
+    }
+}
+
+export default {
+    //获取cookie
+    getCookie(name) {
+        var arr,
+            reg = new RegExp('(^| )' + name + '=([^;]*)(;|$)')
+        if ((arr = document.cookie.match(reg))) {
+            return unescape(arr[2])
+        } else {
+            /* 如果没有参数,那么就获取本域下的所有cookie */
+            return document.cookie
+        }
+    },
+
+    async getJson(url, params) {
+        try {
+            let response = await axiosservice({
+                url,
+                params,
+                method: 'get'
+            })
+            return response.data
+        } catch (err) {
+            throw err
+        }
+    },
+    async postJson(url, data) {
+        try {
+            let response = await axiosservice({
+                url,
+                data,
+                method: 'post'
+            })
+            return response.data
+        } catch (err) {
+            throw err
+        }
+    },
+    async fetchJson(url, params, data) {
+        try {
+            let response = await axiosservice({
+                url,
+                params,
+                data,
+                method: 'post'
+            })
+            return response
+        } catch (err) {
+            throw err
+        }
+    },
+    async postupload(url, data) {
+        try {
+            let response = await axiosservice({
+                url,
+                data,
+                method: 'post',
+                headers: {
+                    'Content-Type': 'multipart/form-data'
+                }
+            })
+            return response.data
+        } catch (err) {
+            throw err
+        }
+    },
+    download(url, requestData,cb) {
+        // 响应类型:arraybuffer, blob
+        axiosservice
+            .post(url, requestData, { responseType: 'blob' })
+            .then(resp => {
+                let headers = resp.headers
+                let contentType = headers['content-type']
+
+                console.log('响应头信息', headers)
+                if (!resp.data) {
+                    console.error('响应异常:', resp)
+                    return false
+                } else {
+                    console.log('下载文件:', resp)
+                    const blob = new Blob([resp.data], { type: contentType })
+
+                    const contentDisposition = resp.headers['content-disposition']
+                    let fileName = 'unknown'
+                    if (contentDisposition) {
+                        fileName = window.decodeURI(resp.headers['content-disposition'].split('=')[1])
+                    }
+                    console.log('文件名称:', fileName)
+                    downFile(blob, fileName,cb)
+                }
+            })
+            .catch(function(error) {
+                console.log(error)
+            })
+    },
+    axios: axiosservice
+}

+ 58 - 0
src/components/HelloWorld.vue

@@ -0,0 +1,58 @@
+<template>
+  <div class="hello">
+    <h1>{{ msg }}</h1>
+    <p>
+      For a guide and recipes on how to configure / customize this project,<br>
+      check out the
+      <a href="https://cli.vuejs.org" target="_blank" rel="noopener">vue-cli documentation</a>.
+    </p>
+    <h3>Installed CLI Plugins</h3>
+    <ul>
+      <li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-babel" target="_blank" rel="noopener">babel</a></li>
+      <li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-eslint" target="_blank" rel="noopener">eslint</a></li>
+    </ul>
+    <h3>Essential Links</h3>
+    <ul>
+      <li><a href="https://vuejs.org" target="_blank" rel="noopener">Core Docs</a></li>
+      <li><a href="https://forum.vuejs.org" target="_blank" rel="noopener">Forum</a></li>
+      <li><a href="https://chat.vuejs.org" target="_blank" rel="noopener">Community Chat</a></li>
+      <li><a href="https://twitter.com/vuejs" target="_blank" rel="noopener">Twitter</a></li>
+      <li><a href="https://news.vuejs.org" target="_blank" rel="noopener">News</a></li>
+    </ul>
+    <h3>Ecosystem</h3>
+    <ul>
+      <li><a href="https://router.vuejs.org" target="_blank" rel="noopener">vue-router</a></li>
+      <li><a href="https://vuex.vuejs.org" target="_blank" rel="noopener">vuex</a></li>
+      <li><a href="https://github.com/vuejs/vue-devtools#vue-devtools" target="_blank" rel="noopener">vue-devtools</a></li>
+      <li><a href="https://vue-loader.vuejs.org" target="_blank" rel="noopener">vue-loader</a></li>
+      <li><a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">awesome-vue</a></li>
+    </ul>
+  </div>
+</template>
+
+<script>
+export default {
+  name: 'HelloWorld',
+  props: {
+    msg: String
+  }
+}
+</script>
+
+<!-- Add "scoped" attribute to limit CSS to this component only -->
+<style scoped>
+h3 {
+  margin: 40px 0 0;
+}
+ul {
+  list-style-type: none;
+  padding: 0;
+}
+li {
+  display: inline-block;
+  margin: 0 10px;
+}
+a {
+  color: #42b983;
+}
+</style>

+ 17 - 0
src/main.js

@@ -0,0 +1,17 @@
+import Vue from 'vue'
+import App from './App.vue'
+import router from './router'
+import store from './store'
+import htmlToPdf from '@/utils/htmlToPdf'
+import ElementUI from 'element-ui'
+import 'element-ui/lib/theme-chalk/index.css'
+import "@/public/css-reset.css";
+Vue.use(htmlToPdf)
+Vue.use(ElementUI)
+Vue.config.productionTip = false
+
+new Vue({
+  router,
+  store,
+  render: h => h(App)
+}).$mount('#app')

+ 33 - 0
src/public/css-reset.css

@@ -0,0 +1,33 @@
+body,h1,h2,h3,h4,h5,h6,hr,p,blockquote,dl,dt,dd,ul,ol,li,pre,form,fieldset,legend,button,input,textarea,th,td{margin:0;padding:0}
+/* body,button,input,select,textarea{font:12px/1.5 Arial,"Microsoft YaHei","\65b0\5b8b\4f53"} */
+h1,h2,h3,h4,h5,h6{font-size:100%}address,cite,dfn,var,em,i,u{font-style:normal}ol,ul{list-style:none}a{text-decoration:none}a:hover{text-decoration:underline}img{border:none;vertical-align:middle}:focus{outline:0}button,input,select,textarea{font-size:100%}table{border-collapse:collapse;border-spacing:0}
+/* 滚动条样式 */
+/* body ::-webkit-scrollbar {
+  width: 5px;
+  height: 5px;
+} */
+
+body ::-webkit-scrollbar-track {
+  background-color: rgba(0, 0, 0, 0);
+  border-radius: 3px;
+}
+
+body ::-webkit-scrollbar-thumb {
+  border-radius: 3px;
+  background: #e6e6e6;
+  border: 1px solid #e6e6e6;
+}
+
+
+body ::-webkit-scrollbar-thumb:vertical:hover {
+  background: #e6e6e6;
+  border: 1px solid #e6e6e6;
+}
+.clearfix{overflow: hidden;}
+.left {
+  float: left;
+}
+
+.right {
+  float: right;
+}

+ 23 - 0
src/router/index.js

@@ -0,0 +1,23 @@
+import Vue from 'vue'
+import VueRouter from 'vue-router'
+
+Vue.use(VueRouter)
+
+const routes = [
+  {
+    path: '/',
+    component: () => import(/* webpackChunkName: "ReportForm" */ '../views/ReportForm/weekReport/reportDetail.vue')
+  },
+  {
+    path: '/weekpdf',
+    component: () => import(/* webpackChunkName: "ReportForm" */ '../views/ReportForm/weekReport/reportDetail.vue')
+  },
+]
+
+const router = new VueRouter({
+  mode: 'history',
+  base: process.env.BASE_URL,
+  routes
+})
+
+export default router

+ 15 - 0
src/store/index.js

@@ -0,0 +1,15 @@
+import Vue from 'vue'
+import Vuex from 'vuex'
+
+Vue.use(Vuex)
+
+export default new Vuex.Store({
+  state: {
+  },
+  mutations: {
+  },
+  actions: {
+  },
+  modules: {
+  }
+})

+ 50 - 0
src/utils/htmlToPdf.js

@@ -0,0 +1,50 @@
+import html2Canvas from 'html2canvas'
+import JsPDF from 'jspdf'
+import { Loading } from 'element-ui';
+
+
+export default{
+    install (Vue, options) {
+        Vue.prototype.getPdf = function (id, title,sgin) {
+            let loadingInstance = Loading.service({target:'page_main'});
+            html2Canvas(document.querySelector(`#${id}`), {
+                // allowTaint: true
+                useCORS: true,
+                scale: 2,
+                scrollY: 0,
+            }).then(function (canvas) {
+                let contentWidth = canvas.width;
+                let contentHeight = canvas.height;
+                let pageHeight = contentWidth / 592.28 * 841.89;
+                let leftHeight = contentHeight;
+                let position = 0;
+                let imgWidth = 595.28;
+                let imgHeight = 592.28 / contentWidth * contentHeight;
+                let pageData = canvas.toDataURL('image/jpeg', 1.0);
+                let PDF = new JsPDF('', 'pt', 'a4');
+                let logo =document.querySelector(`#logo`);
+                // let pageNumber=1;
+                if (leftHeight < pageHeight) {
+                    PDF.addImage(pageData, 'JPEG', 0, 0, imgWidth, imgHeight);
+                    PDF.addImage(logo, 'PNG', 10, 6);
+
+                } else {
+                    while (leftHeight > 0) {
+                        PDF.addImage(pageData, 'JPEG', 0, position, imgWidth, imgHeight);
+                        PDF.addImage(logo, 'PNG', 10, 6);
+                        // PDF.setFont('msyh')
+                        // PDF.text(500,13,sgin);
+                        leftHeight -= pageHeight;
+                        position -= 841.89;
+                        if (leftHeight > 0) {
+                            PDF.addPage();
+                        }
+                    }
+                }
+                PDF.save(title + '.pdf')
+                loadingInstance.close();
+            }
+        )
+        }
+    }
+}

+ 5 - 0
src/views/About.vue

@@ -0,0 +1,5 @@
+<template>
+  <div class="about">
+    <h1>This is an about page</h1>
+  </div>
+</template>

+ 17 - 0
src/views/Home.vue

@@ -0,0 +1,17 @@
+<template>
+  <div class="home">
+    <HelloWorld msg="Welcome to Your Vue.js App"/>
+  </div>
+</template>
+
+<script>
+// @ is an alias to /src
+import HelloWorld from '@/components/HelloWorld.vue'
+
+export default {
+  name: 'Home',
+  components: {
+    HelloWorld
+  }
+}
+</script>

+ 390 - 0
src/views/ReportForm/weekReport/barChart.vue

@@ -0,0 +1,390 @@
+<template>
+  <div :id="chartId" class="linechart">
+
+  </div>
+</template>
+
+<script>
+import echarts from "echarts";
+import moment from "moment"
+export default {
+    props:{
+        chartId:String,
+        chartDate:{
+            default:null
+        },
+        xType:String,
+        normalChart:{
+            type:Boolean,
+            default:false,
+        },
+        weekNormalChart:{
+          type:Boolean,
+            default:false,
+        },
+        numberChart:{
+            type:Boolean,
+            default:false,
+        },
+        yType:{
+            type:String,
+            default:"rate"
+        },
+        sjChartType:{
+            type:String
+        }
+    },
+    data(){
+        return {
+            chartInit:null
+        }
+    },
+    mounted(){
+        this.$once("hook:beforeDestroy", () => {
+            if (this.chartInit) {
+                this.chartInit.clear();
+            }
+        })
+    },
+    methods:{
+        moment,
+        showChartInfo(divId, infoStr="暂无数据"){
+            let msgOption = {
+                title: {
+                    show: true,
+                    textStyle:{
+                    color:'grey',
+                    fontSize:14
+                    },
+                    text: infoStr,
+                    left: 'center',
+                    top: 'center'
+                },
+                xAxis: {
+                    show: false
+                },
+                yAxis: {
+                    show: false
+                },
+                series: []
+            };
+             this.chartInit= echarts.init(document.getElementById(divId));
+             this.chartInit.hideLoading()
+             this.chartInit.setOption(msgOption)
+        },
+        initDayTime(value){
+            value =value.slice(4,6)+'-'+ value.slice(6,8)
+            return value
+        },
+        initHourTime(value){
+            value =value.slice(0,2)+':'+ value.slice(2,4)
+            return value
+        },
+        drawChart(id = this.chartId,data={}){
+            if(!data||!Object.keys(data).length){
+                this.showChartInfo(id);
+                return
+            }
+            let that=this;
+            this.chartInit&&(this.chartInit=null)
+            this.chartInit= echarts.init(document.getElementById(id));
+            let dataX;
+            if(this.xType=="day"){
+                dataX=data.date||[];
+            }else if(this.xType=="hour"){
+                dataX=data.time||[];
+            }else{
+                dataX=data.floorName||[];
+            }
+            let option = {
+                tooltip: {
+                    trigger: 'axis',
+                    axisPointer: {            // 坐标轴指示器,坐标轴触发有效
+                        type: ''        // 默认为直线,可选为:'line' | 'shadow'
+                    },
+                    formatter: params=> {
+                        var showHtm="";
+                        let name = params[0].name;
+
+                        if(this.xType&&this.xType!=="floor"){
+                           name = this.xType=="day"?this.initDayTime(params[0].name):this.initHourTime(params[0].name)
+                        }
+                        for(var i=0;i<params.length;i++){
+                            //名称
+                            var text =  params[i].marker +params[i].seriesName;
+                            //值
+                            var value = (params[i].value || '--');
+                            value = this.yType=="rate"?(value!=='--'?((value*100).toFixed(1)+'%'):'--'):value;
+                            showHtm+= text+ ':' + value +'<br>'
+                        }
+                        showHtm =`${name}<br/>${showHtm}`;
+                        return showHtm;
+                    }
+                },
+                 grid: {
+                    left: "50",
+                    right: "50",
+                    bottom: "30",
+                    top:"7",
+                    borderColor:'#E9E9E9',
+                },
+                color: ['#0091FF','#FFFFFF','#F9908B'],
+                animation:false,
+                xAxis: {
+                    type: 'category',
+                    // boundaryGap: false,
+                    data: dataX,
+                    axisTick:{
+                        show:false
+                    },
+                    interval:0,
+                    axisLine:{
+                        lineStyle:{
+                            color:'#D9D9D9',
+                            // width:8,//这里是为了突出显示加上的
+                        }
+                    },
+                    axisLabel: {
+                        color:'#848484',
+                        interval:0,
+                        fontSize:11,
+                        formatter:(value)=>{
+                            if(this.xType=="hour"&&value.endsWith("0000")){
+                                return value.slice(0,2)+':'+value.slice(2,4)
+                            }else if(this.xType=="hour"&&!value.endsWith("0000")){
+                                return ''
+                            }
+                            if(this.xType=="day"){
+                                return value.slice(4,6)+'-'+value.slice(6,8)+'\n'+'周'+this.getWeek(moment(value).format('E'))
+                            }else{
+                                return value
+                            }
+                            // !this.normalChart&&(value = value*100+'%');
+
+                        }
+                    },
+                },
+                yAxis: {
+                    type: 'value',
+                    position:'left',
+                    axisLabel: {
+                        color:'#848484',
+                        fontSize:12,
+                        formatter:(value)=>{
+                            if(!this.normalChart&&!this.numberChart){
+                                value = value*100+'%'
+                            }
+                            return value
+                        }
+                    },
+
+                    splitLine: {
+                        show: false,
+                        lineStyle:{
+                            color: ['#E9E9E9'],
+                            width: 1,
+                            type: 'dashed'
+                        }
+                  },
+                    nameTextStyle:{
+                        color:'#848484'
+                    },
+                    axisTick: {
+                        show: false
+                    },
+                    axisLine: {
+                        show: false
+                    },
+                },
+                series: [
+                    {
+                        name: this.yType=="rate"?'偏冷占比':'偏冷数量',
+                        type: 'bar',
+                        stack: '达标率',
+                        data: this.yType=="rate"?data.coldProprotion:data.coldSpaceNum,
+                        barWidth: '50%',
+                        barMaxWidth:'50'
+                    },
+                    {
+                        name: this.yType=="rate"?'达标占比':'达标数量',
+                        data: this.yType=="rate"?data.normalProprotion:data.normalSpaceNum,
+                        stack: '达标率',
+                        type: 'bar',
+                        itemStyle: {
+                            barBorderColor: '#D6DADF',
+                        },
+                        barWidth: '50%',
+                        barMaxWidth:'50',
+                        label: {
+                            normal: {
+                                show: (this.yType=="rate"&&this.xType=='day'||(this.sjChartType))?true:false,
+                                position: 'inside',
+                                color:"#1F2329",
+                                formatter: (params)=>{
+                                    return !params.value?'':`${parseInt(params.value*100)}%`;
+                                }
+                            },
+
+                        },
+                    },
+                    {
+                        name: this.yType=="rate"?'偏热占比':'偏热数量',
+                        stack: '达标率',
+                        data: this.yType=="rate"?data.hotProprotion:data.hotSpaceNum,
+                        type: 'bar',
+                         barMaxWidth:'50',
+                        barWidth: '50%',
+                    }
+                ]
+            };
+            if(this.normalChart){
+                let normalDatex=["<=23","23~24","24~25","25~26","26~27",">27"]
+                option.xAxis.data=normalDatex;
+                option.grid.top="45"
+                option.title={
+                    subtext: '空间数量'
+                }
+                option.series=[];
+                option.series=[
+                    {name: '空间数量',
+                        type: 'bar',
+                        stack: '达标率',
+                        color:"#82c7fc",
+                        barWidth: '30%',
+                        data: data[0]?[data[0].oneSpaceNum,data[0].twoSpaceNum,data[0].threeSpaceNum,data[0].fourSpaceNum,data[0].fiveSpaceNum,data[0].sixSpaceNum]:[]
+                    }
+                ]
+            }
+            if(this.weekNormalChart){
+                let normalDatex=["≥90%","80%~90%","70%~80%","<70%"];
+                option.xAxis.data=normalDatex;
+                option.xAxis.name="达标区间";
+                option.yAxis.show=false;
+                // option.grid.top="45"
+                option.title={
+                    subtext: '空间数量'
+                }
+                option.grid= {
+                    top:"18",
+                    left: "50",
+                    right: "65",
+                    bottom: "30",
+                };
+                option.series=[];
+                option.series=[
+                    {name: '空间数量',
+                        type: 'bar',
+                        stack: '数量',
+                        color:"#82c7fc",
+                        barWidth: '30%',
+                        itemStyle: {
+                        //通常情况下:
+                        normal:{
+                    //每个柱子的颜色即为colorList数组里的每一项,如果柱子数目多于colorList的长度,则柱子颜色循环使用该数组
+                                color: function (params){
+                                    var colorList = ['#0091FF','#0091FF','#0091FF','#0091FF'];
+                                    return colorList[params.dataIndex];
+                                }
+                            },
+                            //鼠标悬停时:
+                            emphasis: {
+                                shadowBlur: 10,
+                                shadowOffsetX: 0,
+                                shadowColor: 'rgba(0, 0, 0, 0.5)'
+                            }
+                        },
+                        label: {
+                            normal: {
+                                show: true,
+                                position: 'top',
+                                color:"#1F2329",
+                                formatter: (params)=>{
+                                    return `${parseInt(params.value)}`
+                                }
+                            },
+
+                        },
+                        data: data?[data.oneSpaceNum,data.twoSpaceNum,data.threeSpaceNum,data.foureSpaceNum]:[]
+                    }
+                ]
+            }
+            if(this.numberChart){
+                option.grid.top="22"
+                option.title={
+                    top:-13,
+                    left:0,
+                    subtext: '空间数量'
+                }
+            }
+            if(this.sjChartType){
+                if(this.sjChartType=="regions"){
+                    let normalDatex=["内区","外区"];
+                    option.xAxis.data=normalDatex;
+                }
+                if(this.sjChartType=="orientation"){
+                    let normalDatex=["东","南","西","北"];
+                    option.xAxis.data=normalDatex;
+                }
+                if(this.sjChartType=="localtion" || this.sjChartType=="freshAir" ){
+                    let normalDatex=data.objectName;
+                    option.xAxis.data=normalDatex;
+                }
+                option.yAxis.show=false;
+                option.grid= {
+                    left: "0",
+                    right: "0",
+                    bottom: "30",
+                    top:"7",
+                    borderColor:'#E9E9E9',
+                };
+            }
+            this.chartInit.setOption(option);
+            window.addEventListener("resize",function(){
+                that.chartInit.resize();
+            })
+        },
+         getWeek (week) {
+            switch (Number(week)) {
+                case 1:
+                    return '一'
+                case 2:
+                    return '二'
+                case 3:
+                    return '三'
+                case 4:
+                    return '四'
+                case 5:
+                    return '五'
+                case 6:
+                    return '六'
+                case 7:
+                    return '日'
+                default:
+                    return '--'
+            }
+        },
+    },
+    watch:{
+        chartDate:{
+            handler(newval){
+                if (this.chartInit) {
+                    this.chartInit.clear();
+                }
+                this.chartDate=newval;
+                this.$nextTick(()=>{
+                    this.drawChart(this.chartId,this.chartDate)
+                })
+            },
+            deep:true,
+             immediate: true,
+        }
+    }
+}
+</script>
+
+<style lang="less" scoped>
+.linechart{
+    width: 100%;
+    height: 240px;
+}
+</style>

+ 82 - 0
src/views/ReportForm/weekReport/chartLegend.vue

@@ -0,0 +1,82 @@
+<template>
+  <div class="legend">
+      <div v-for="(item,index) in legendObj" :key="index" v-show="(item.name!='平均温度')||avgTemp">
+          <span :style="{background:item.color}" :class="{'dotLine':dotLine}"></span>{{numType?item.numName:item.name}}
+      </div>
+  </div>
+</template>
+
+<script>
+export default {
+    props:{
+        lineShow:{
+            type:Boolean,
+            default:false
+        },
+        numType:{
+            type:Boolean,
+            default:true
+        },
+        dotLine:{
+            type:Boolean,
+            default:false
+        },
+        avgTemp:{
+            type:Boolean,
+            default:true
+        }
+    },
+    data(){
+        return {
+            legendObj:[
+                {name:"偏冷占比",numName:"偏冷",color:"#0091FF"},
+                {name:"达标占比",numName:"达标",color:"#ffffff"},
+                {name:"偏热占比",numName:"偏热",color:"#F9908B"},
+                {name:"平均温度",numName:"平均温度",color:"#ffffff"},
+            ]
+        }
+    }
+}
+</script>
+
+<style lang="less" scoped>
+.legend{
+    display: inline-block;
+    color: #848484;
+    &>div{
+        display: inline-block;
+        margin-right: 16px;
+        &>span{
+            display: inline-block;
+            vertical-align: middle;
+            margin-right: 4px;
+            width:12px;
+            height:12px;
+            border:1px solid rgba(214,218,223,1);
+        }
+    }
+    &>div:nth-child(4){
+        position: relative;
+        z-index: 2;
+        &>span{
+            width:8px;
+            height:8px;
+            border-radius: 50%;
+            position: relative;
+            border:2px solid #0091ff;
+        }
+        &>span.dotLine::after{
+            content: '';
+            box-sizing: content-box;
+            top: 1px;
+            left:-4px;
+            z-index: -1;
+            background: #0091ff;
+            position: absolute;
+            display: inline-block;
+            width: 12px;
+            height: 2px;
+        }
+    }
+}
+</style>

+ 212 - 0
src/views/ReportForm/weekReport/lineChart.vue

@@ -0,0 +1,212 @@
+<template>
+  <div :id="chartId" class="linechart"></div>
+</template>
+
+<script>
+import echarts from "echarts";
+export default {
+    props:{
+        chartId:String,
+        chartDate:{
+            default:null,
+        },
+        xType:String,
+        contant:{
+            type:Boolean,
+            default:false
+        }
+    },
+    data(){
+        return {
+            chartInit:null
+        }
+    },
+    mounted(){
+        this.$once("hook:beforeDestroy", () => {
+            if (this.chartInit) {
+                this.chartInit.clear();
+            }
+        })
+    },
+    methods:{
+        showChartInfo(divId, infoStr="暂无数据"){
+            let msgOption = {
+                title: {
+                    show: true,
+                    textStyle:{
+                    color:'grey',
+                    fontSize:14
+                    },
+                    text: infoStr,
+                    left: 'center',
+                    top: 'center'
+                },
+                xAxis: {
+                    show: false
+                },
+                yAxis: {
+                    show: false
+                },
+                series: []
+            };
+             this.chartInit= echarts.init(document.getElementById(divId));
+             this.chartInit.hideLoading()
+             this.chartInit.setOption(msgOption)
+            // initChart(divId).clear()
+        },
+        initDayTime(value){
+            value =value.slice(4,6)+'-'+ value.slice(6,8)
+            return value
+        },
+        initHourTime(value){
+            value =value.slice(0,2)+':'+ value.slice(2,4)
+            return value
+        },
+        drawChart(id = this.chartId,data){
+            if(!data||!Object.keys(data).length){
+                this.showChartInfo(id);
+                return
+            }
+            let that=this;
+            this.chartInit= echarts.init(document.getElementById(id));
+            let dataY=data.avgTemp || [];
+            let dataX;
+            if(this.xType=="day"){
+                dataX=data.date||[];
+            }else if(this.xType=="hour"){
+                dataX=data.time||[];
+            }else{
+                dataX=data.floorName||[];
+            }
+            const dataYcope = dataY.filter(Boolean);
+            let maxTemp=parseInt(Math.max.call(null,...dataYcope)+2) ;
+            let minTemp=parseInt(Math.min.call(null,...dataYcope));
+            let option = {
+                tooltip: {
+                    trigger: 'axis',
+                    axisPointer: {            // 坐标轴指示器,坐标轴触发有效
+                        type: ''        // 默认为直线,可选为:'line' | 'shadow'
+                    },
+                    formatter: params=> {
+                        var showHtm="";
+                        let name = params[0].name;
+                        if(this.xType&&this.xType!=="floor"){
+                           name = this.xType=="day"?this.initDayTime(params[0].name):this.initHourTime(params[0].name)
+                        }
+                        for(var i=0;i<params.length;i++){
+                            //名称
+                            var text =  params[i].marker +params[i].seriesName;
+                            //值
+                            var value = params[i].value?params[i].value.toFixed(1):'--';
+                            // value = ;
+                            showHtm+= text+ ':' + value +'<br>'
+                        }
+                        showHtm =`${name}<br/>${showHtm}`;
+                        return showHtm;
+                    }
+                },
+                 grid: {
+                    left: "50",
+                    right: "50",
+                    bottom: "8",
+                    top:"15",
+                    color:'#f7f7f7',
+                    borderColor:'#f7f7f7',
+                },
+                animation:false,
+                xAxis: {
+                    type: 'category',
+                    // boundaryGap: false,
+                    show:false,
+                    data: dataX
+                },
+                yAxis: {
+                    type: 'value',
+                    position:'right',
+                    axisLabel: {
+                        color:'#848484',
+                        fontSize:12,
+                        formatter:(value)=>{
+                            return value+'°C'
+                        }
+                    },
+                    splitLine: {
+                        show: false,
+                        lineStyle:{
+                            color: ['#E9E9E9'],
+                            width: 1,
+                            type: 'dashed'
+                        }
+                  },
+                    min:minTemp,
+                    max:maxTemp,
+                    minInterval:2,
+                    axisTick: {
+                        show: false
+                    },
+                    axisLine: {
+                        show: false
+                    },
+                },
+                series: [{
+                    data: dataY,
+                    type: 'line',
+                    color: "#0091FF",
+                    name:"平均温度",
+                    symbolSize: 6,
+                    lineStyle: {
+                        color: "#0091FF",
+                        width: !this.contant?0:1,
+                    },
+                    label: {
+                        normal: {
+                            show: true,
+                            position: 'top',
+                            formatter:(parme)=>{
+                                if(this.xType==="floor"){
+                                    return parme.value.toFixed(1)|| ''
+                                }
+                                if(this.xType==="hour"&&parme.name.endsWith("0000")){
+                                    return parme.value.toFixed(1) || ''
+                                }else if(this.xType==="day"){
+                                    return parme.value.toFixed(1) || ''
+                                }
+                                return ''
+
+                            }
+                        },
+
+                    },
+                }]
+            };
+            this.chartInit.setOption(option);
+            window.addEventListener("resize",function(){
+                that.chartInit.resize();
+            })
+        }
+    },
+    watch:{
+        chartDate:{
+            handler(newval){
+                if (this.chartInit) {
+                    this.chartInit.clear();
+                }
+                this.chartDate=newval;
+                this.$nextTick(()=>{
+                    this.drawChart(this.chartId,this.chartDate)
+                })
+            },
+            deep:true,
+            immediate: true,
+        }
+    }
+}
+</script>
+
+<style lang="less" scoped>
+.linechart{
+    width: 100%;
+    height: 80px;
+    // height: 110px;
+}
+</style>

文件差異過大導致無法顯示
+ 2233 - 0
src/views/ReportForm/weekReport/reportDetail.vue


+ 124 - 0
src/views/ReportForm/weekReport/ringChart.vue

@@ -0,0 +1,124 @@
+<template>
+  <div :id="chartId" class="linechart">
+
+  </div>
+</template>
+
+<script>
+import echarts from "echarts";
+export default {
+    props:{chartDate:false,chartId:String,},
+    data(){
+        return {
+            chartInit:null
+        }
+    },
+    methods:{
+        showChartInfo(divId, infoStr="暂无数据"){
+            let msgOption = {
+                title: {
+                    show: true,
+                    textStyle:{
+                    color:'grey',
+                    fontSize:14
+                    },
+                    text: infoStr,
+                    left: 'center',
+                    top: 'center'
+                },
+                xAxis: {
+                    show: false
+                },
+                yAxis: {
+                    show: false
+                },
+                series: []
+            };
+             this.chartInit= echarts.init(document.getElementById(divId));
+             this.chartInit.hideLoading()
+             this.chartInit.setOption(msgOption)
+        },
+        drawChart(id=this.chartId,data){
+            if(!data||!Object.keys(data).length){
+                this.showChartInfo(id);
+                return
+            }
+            let that=this;
+            this.chartInit= echarts.init(document.getElementById(id));
+            let dataX;
+            let option = {
+                tooltip: {
+                    trigger: 'item',
+                    formatter: '{a} <br/>{b}:{d}%'
+                },
+                animation:false,
+                legend: {
+                    show:false
+                },
+                color:['#FFFFFF','#0091FF','#F9908B'],
+                series: [
+                    {
+                        name: '',
+                        type: 'pie',
+                        radius: ['70%', '100%'],
+                        avoidLabelOverlap: false,
+                        label: {
+                            show: false,
+                            position: 'center'
+                        },
+                        emphasis: {
+                            //  show: false,
+                            // label: {
+                            //     show: true,
+                            //     fontSize: '30',
+                            //     fontWeight: 'bold'
+                            // }
+                        },
+                         itemStyle:{
+                            show:false,
+                            borderColor:'#e1e4e8',
+                            borderWidth:1,
+                        },
+                        labelLine: {
+                            show: false
+                        },
+                        hoverAnimation: false,
+                        data: [
+                            {value: data.weeknormalProprotion, name: '达标率'},
+                            {value: data.weekcoldProprotion, name: '偏冷率'},
+                            {value: data.weekhotProprotion, name: '偏热率'},
+                        ]
+                    }
+                ]
+            };
+
+            this.chartInit.setOption(option);
+            window.addEventListener("resize",function(){
+                that.chartInit.resize();
+            })
+        }
+    },
+    watch:{
+        chartDate:{
+            handler(newval){
+                if (this.chartInit) {
+                    this.chartInit.clear();
+                }
+                this.chartDate=newval;
+                this.$nextTick(()=>{
+                    this.drawChart(this.chartId,this.chartDate)
+                })
+            },
+            deep:true,
+            immediate: true,
+        }
+    }
+}
+</script>
+
+<style lang="less" scoped>
+.linechart{
+    width: 100%;
+    height: 128px;
+}
+</style>

+ 0 - 0
static/.gitkeep


二進制
static/images/cold.png


二進制
static/images/happy.png


二進制
static/images/hot.png


二進制
static/images/icon_down.png


二進制
static/images/icon_up.png


二進制
static/images/logo.png


二進制
static/images/no.jpg


二進制
static/images/summer.png


二進制
static/images/winter.png


+ 43 - 0
vue.config.js

@@ -0,0 +1,43 @@
+const fs = require('fs');
+// const copywebpackplugin = require('copy-webpack-plugin');
+// const { name } = require("./package.json");
+const name = dist;
+publicPath = process.env.NODE_ENV === "development" ? "/" : `/${name}`;
+module.exports = {
+  publicPath: publicPath, //相对路径
+  outputDir: name, //打包名称
+  // assetsDir: `${pagesInfo.outputDir}/assets`,
+  productionSourceMap: false,
+  lintOnSave: false, //关闭lint代码
+  css: {
+    loaderOptions: {
+      less: {
+        javascriptEnabled: true,
+      },
+    },
+  },
+  devServer: {
+    historyApiFallback: {
+      // rewrites: pagesInfo.devServerPath,
+    },
+    port: 9906,
+    proxy: {
+      "/duoduo-service": {
+          target: "http://api.sagacloud.cn",
+          changeOrigin: true,
+          secure: false,
+      }
+    }
+  },
+  chainWebpack: (config) => {
+    // config
+    //   .plugin('copy')
+    //   .use(copywebpackplugin, [
+    //     [{
+    //       from: 'src/public',
+    //       to: 'public',
+    //       toType: 'dir',
+    //     }],
+    //   ]);
+  },
+};