Browse Source

add other fn
Signed-off-by: caner <5658514@qq.com>

caner 3 years ago
parent
commit
f3bb9c3829

+ 0 - 1
.env.development

@@ -1,2 +1 @@
 #VITE_SERVER_URL=http://20.20.20.4:8762
 #VITE_SERVER_URL=http://20.20.20.4:8762
-VITE_SERVER_URL=http://lqai.caner.top:9080

+ 1 - 1
.env.production

@@ -1 +1 @@
-VITE_SERVER_URL=https://srbg.jdjinsui.com:8765
+VITE_SERVER_URL=https://****.com:8765

+ 4 - 1
.eslintrc.cjs

@@ -22,6 +22,10 @@ module.exports = {
     'jsx-quotes': 0, // 强制使用单引号
     'jsx-quotes': 0, // 强制使用单引号
     'max-len': 0, // 强制一行的最大长度
     'max-len': 0, // 强制一行的最大长度
     semi: [2, 'never'], // 禁止使用分号
     semi: [2, 'never'], // 禁止使用分号
+    'no-unused-vars': 2,
+    "no-unneeded-ternary": 2,//禁止不必要的嵌套 var isYes = answer === 1 ? true : false;
+    "no-unreachable": 2,//不能有无法执行的代码
+    "no-unused-expressions": 2,//禁止无用的表达式    
     'linebreak-style': [0, 'error', 'windows'],
     'linebreak-style': [0, 'error', 'windows'],
     'import/no-unresolved': 0,
     'import/no-unresolved': 0,
     'import/extensions': 0,
     'import/extensions': 0,
@@ -46,7 +50,6 @@ module.exports = {
     'vue/require-explicit-emits': 0,
     'vue/require-explicit-emits': 0,
     'vue/no-v-html': 0,
     'vue/no-v-html': 0,
     'vue/order-in-components': 0,
     'vue/order-in-components': 0,
-    'no-unused-vars': 1,
     'vue/no-reserved-component-names': 0,
     'vue/no-reserved-component-names': 0,
     'no-promise-executor-return': 0,
     'no-promise-executor-return': 0,
     'no-sparse-arrays': 0,
     'no-sparse-arrays': 0,

+ 5 - 10
src/pages/index/App.vue

@@ -1,15 +1,10 @@
 <template>
 <template>
   <loading v-if="show" />
   <loading v-if="show" />
-  <n-config-provider
-    preflight-style-disabled
-    inline-theme-disabled
-    :theme-overrides="themeOverrides"
-    :locale="zhCN"
-    :date-locale="dateZhCN"
-  >
-        <n-notification-provider>
-          <router-view />
-        </n-notification-provider>
+  <n-config-provider preflight-style-disabled inline-theme-disabled :theme-overrides="themeOverrides" :locale="zhCN"
+    :date-locale="dateZhCN">
+    <n-notification-provider>
+      <router-view />
+    </n-notification-provider>
   </n-config-provider>
   </n-config-provider>
 </template>
 </template>
 <script setup lang='ts'>
 <script setup lang='ts'>

+ 13 - 14
src/utils/JsFn.ts

@@ -19,7 +19,6 @@ export const unique = (arr: Array<any>, key: string) => {
 /**
 /**
  * 同步睡眠
  * 同步睡眠
  * @param ms 毫秒
  * @param ms 毫秒
- * @returns
  */
  */
 export const sleep = (ms: number) => { return new Promise((resolve) => { setTimeout(resolve, ms) }) }
 export const sleep = (ms: number) => { return new Promise((resolve) => { setTimeout(resolve, ms) }) }
 
 
@@ -56,24 +55,24 @@ export const search = (data: Array<any>, key: string) => {
  * @param fmt 日期格式
  * @param fmt 日期格式
  * @returns 
  * @returns 
  */
  */
-export const fomartTime = (date: Date, fmt = 'yyyy-MM-dd hh:mm:ss') => {
+ export const fomartTime = (date: Date, fmt = 'yyyy-MM-dd hh:mm:ss') => {
   if (!date) return ''
   if (!date) return ''
   const o = {
   const o = {
-    "M+": date.getMonth() + 1,                 //月份 
-    "d+": date.getDate(),                    //日 
-    "h+": date.getHours(),                   //小时 
-    "m+": date.getMinutes(),                 //分 
-    "s+": date.getSeconds(),                 //秒 
-    "q+": Math.floor((date.getMonth() + 3) / 3), //季度 
-    "S": date.getMilliseconds()             //毫秒 
+      "M+": date.getMonth() + 1,                 //月份 
+      "d+": date.getDate(),                    //日 
+      "h+": date.getHours(),                   //小时 
+      "m+": date.getMinutes(),                 //分 
+      "s+": date.getSeconds(),                 //秒 
+      "q+": Math.floor((date.getMonth() + 3) / 3), //季度 
+      "S": date.getMilliseconds()             //毫秒 
   } as any
   } as any
   if (/(y+)/.test(fmt)) {
   if (/(y+)/.test(fmt)) {
-    fmt = fmt.replace(RegExp.$1, (date.getFullYear() + "").substr(4 - RegExp.$1.length));
+      fmt = fmt.replace(RegExp.$1, (date.getFullYear() + "").substr(4 - RegExp.$1.length));
   }
   }
   for (let k in o) {
   for (let k in o) {
-    if (new RegExp("(" + k + ")").test(fmt)) {
-      fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
-    }
+      if (new RegExp("(" + k + ")").test(fmt)) {
+          fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
+      }
   }
   }
   return fmt;
   return fmt;
 }
 }
@@ -85,7 +84,7 @@ export const fomartTime = (date: Date, fmt = 'yyyy-MM-dd hh:mm:ss') => {
 */
 */
 export const mileage2string = (num: number) => {
 export const mileage2string = (num: number) => {
   const a = Math.floor(num / 1000).toString()
   const a = Math.floor(num / 1000).toString()
-  const ab = (num % 1000).toString()
+  const ab =parseFloat((num % 1000).toFixed(1)) 
   const b = Math.floor(num % 1000).toString()
   const b = Math.floor(num % 1000).toString()
   const c = b.length === 1 ? `00${ab}` : b.length === 2 ? `0${ab}` : ab
   const c = b.length === 1 ? `00${ab}` : b.length === 2 ? `0${ab}` : ab
   return `${a}+${c}`
   return `${a}+${c}`

+ 140 - 0
src/utils/exp2File.ts

@@ -0,0 +1,140 @@
+import * as XLSX from 'xlsx'
+
+/**
+   * 解析后的浮点数转时间戳
+   * @param num 时间浮点
+   */
+const number2times = (num: number) => {
+    const utc_value = (num - 25569) * 86400
+    const date_info = new Date(utc_value * 1000).getTime()
+    const newtime = (date_info - 8 * 3600 * 1000)
+    return newtime
+}
+
+/**
+ * 自动下载
+ * @param url 保存地址|blob
+ * @param saveName 文件名
+ */
+const openDownloadDialog = (url: any, saveName: string) => {
+    if (typeof url === 'object' && url instanceof Blob) {
+        url = URL.createObjectURL(url) // 创建blob地址
+    }
+    const aLink = document.createElement('a')
+    aLink.href = url
+    aLink.download = saveName || '' // HTML5新增的属性,指定保存文件名,可以不要后缀,注意,file:///模式下不会生效
+    let event
+    if (window.MouseEvent) event = new MouseEvent('click')
+    else {
+        event = document.createEvent('MouseEvents')
+        event.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null)
+    }
+    aLink.dispatchEvent(event)
+}
+
+/**
+ * 解析excel表格
+ * @param file 文件
+ * @returns 
+ */
+export const exp2json = async (file: File) => {
+    return await new Promise((resolve, reject) => {
+        try {
+            const reader = new FileReader()
+            reader.onload = (e: any) => {
+                const wb = XLSX.read(e.target.result, {
+                    type: 'binary'
+                }) // 读取完成的数据
+                // 转成json header解析第一行标题
+                const data = XLSX.utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]], { header: 1 })
+                resolve(data)
+            }
+            reader.readAsBinaryString(file)
+        } catch (error) {
+            console.log('解析错误')
+            reject(error)
+        }
+    })
+}
+
+/**
+ * 导出excel表格
+ * @param arr 数据是数组包含的对象
+ * @param fileName 名字
+ */
+export const exp2excel = (arr: Array<any>, fileName:string,cellMerges?:Array<any>) => {
+    const sheet = XLSX.utils.json_to_sheet(arr);
+    // excel宽高设置
+    sheet["!cols"] = arr.map(() => {
+        return { wch: 30 }
+    })
+    if(cellMerges){
+        sheet['!merges'] = cellMerges; // <====合并单元格
+    }
+    // 转blob
+    const sheet2blob = (sheet: any, sheetName='sheet1') => {
+        const workbook = {
+            SheetNames: [sheetName],
+            Sheets: {} as any
+        };
+        workbook.Sheets[sheetName] = sheet;
+        // 生成excel的配置项
+        const wopts = {
+            bookType: 'xlsx', // 要生成的文件类型
+            bookSST: false, // 是否生成Shared String Table,官方解释是,如果开启生成速度会下降,但在低版本IOS设备上有更好的兼容性
+            type: 'binary'
+        } as any
+        const wbout = XLSX.write(workbook, wopts);
+        // 字符串转ArrayBuffer
+        const s2ab = (s: string) => {
+            let buf = new ArrayBuffer(s.length);
+            let view = new Uint8Array(buf);
+            for (let i = 0; i != s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF;
+            return buf;
+        }
+        const blob = new Blob([s2ab(wbout)], { type: "application/octet-stream" });
+
+        return blob;
+    }
+    openDownloadDialog(sheet2blob(sheet), fileName + '.xlsx')
+}
+
+/**
+ * dom导出excel
+ * @param domID domID
+ * @param fileName 文件名
+ */
+export const dom2excel = (domID: string, fileName: string) => {
+    const dom = document.getElementsByTagName(domID)
+    if (!dom) return
+    const wb = XLSX.utils.table_to_book(dom[0])
+    const baty = XLSX.write(wb, { bookType: 'xlsx', bookSST: false, type: 'binary' })
+    // 字符串转ArrayBuffer
+    const s2ab = (s: any) => {
+        const buf = new ArrayBuffer(s.length)
+        const view = new Uint8Array(buf)
+        for (let i = 0; i !== s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF
+        return buf
+    }
+    const blob = new Blob([s2ab(baty)], { type: 'application/octet-stream' })
+    openDownloadDialog(blob, fileName + '.xlsx')
+}
+/**
+ * 数组按指定key值分组
+ * @param {*} array 
+ * @param {*} id 
+ * @returns 
+ */
+ export function groupBy(array:Array<any>, id:string) {
+    let groups = {} as any;
+    array.forEach((o) => {
+        let group = JSON.stringify(o[id]);
+        if (typeof o[id] === 'string') {
+            group = o[id]
+        }
+        groups[group] = groups[group] || [];
+        groups[group].push(o);
+    });
+    // return Object.values(groups);
+    return groups;
+}

+ 147 - 0
src/utils/html2File.ts

@@ -0,0 +1,147 @@
+import html2canvas from "html2canvas";
+import JSPDF from "jspdf";
+import { getActivePinia } from "pinia";
+
+/**
+ * loading
+ * @param type 是否显示
+ */
+const resetLoaing = (type: boolean) => {
+    const store = getActivePinia()
+    if (!store) return
+    const obj = store.state.value
+    for (const key in obj) {
+        const el = obj[key]
+        if ('loading' in el) {
+            el.loading = type
+            break
+        }
+    }
+
+}
+
+/**
+ * 导出PDF
+ * @param domID 需要输出PDF的页面id
+ * @param fileName 文件名
+ * @param type  默认A4分页
+ * @param wMultiple 宽倍数
+ * @param hMultiple 高倍数
+ * @returns 
+ */
+export const exp2pdf = async (domID: string, fileName: string, type = 'A4', wMultiple = null, hMultiple = null) => {
+    const dom = document.getElementById(domID)
+    if (!dom) return
+    resetLoaing(true)
+    const domHeight = dom.offsetHeight // 获取DOM高度
+    const domWidth = dom.offsetWidth // 获取DOM宽度
+    const canvas = await html2canvas(dom, {
+        logging: false,
+        useCORS: true, // 允许图片跨域   
+        scale: 1.5,
+        width: wMultiple ? wMultiple * domWidth : undefined,
+        height: hMultiple ? hMultiple * domHeight : undefined
+    })
+
+    if (type === 'A4') {
+        // A4分页
+        const pdf = new JSPDF("p", "mm", "a4") // A4纸,纵向
+        const ctx = canvas.getContext("2d") as any
+        const a4w = 200;
+        const a4h = 277 // A4大小,210mm x 297mm,四边各保留20mm的边距
+        const imgHeight = Math.floor(a4h * canvas.width / a4w) // 按A4显示比例换算一页图像的像素高度
+        let renderedHeight = 0
+        while (renderedHeight < canvas.height) {
+            const page = document.createElement("canvas")
+            page.width = canvas.width
+            page.height = Math.min(imgHeight, canvas.height - renderedHeight) // 可能内容不足一页
+            // 用getImageData剪裁指定区域,并画到前面创建的canvas对象中
+            page.getContext("2d")?.putImageData(ctx.getImageData(0, renderedHeight, canvas.width, Math.min(imgHeight, canvas.height - renderedHeight)), 0, 0)
+            pdf.addImage(page.toDataURL("image/jpeg", 1.0), "JPEG", 10, 10, a4w, Math.min(a4h, a4w * page.height / page.width)) // 添加图像到页面,保留10mm边距
+            renderedHeight += imgHeight
+            if (renderedHeight < canvas.height) { pdf.addPage() } // 如果后面还有内容,添加一个空页
+            // delete page;
+        }
+        pdf.save(fileName)
+
+    } else {
+        // 整张
+        const pdf = new JSPDF('p', 'px', [domWidth, domHeight])
+        pdf.addImage(canvas.toDataURL("image/jpeg", 1.0), "JPEG", 10, 10, domWidth, domHeight)
+        pdf.save(fileName)
+    }
+    resetLoaing(false)
+}
+
+/**
+ * 导出PNG
+ * @param domID 需要输出PDF的页面id
+ * @param fileName 文件名
+ * @param bkcolor 背景色
+ */
+export const exp2png = async (domID: string, fileName: string, bkcolor: string) => {
+    resetLoaing(true)
+    window.scroll(0, 0) // 首先先顶部
+    const design = document.getElementById(domID) as HTMLElement
+    if (!design) return
+    const imgHeight = design.offsetHeight // 获取DOM高度
+    const imgWidth = design.offsetWidth // 获取DOM宽度
+    const scale = window.devicePixelRatio <= 3 ? 3 : window.devicePixelRatio // 获取设备像素比
+    const canvas = await html2canvas(design, {
+        backgroundColor: bkcolor, // 设置背景颜色
+        useCORS: true, // 允许图片跨域
+        scale: scale, // 缩放3倍,使得图片更加清晰=>越清晰图片越大
+        width: imgWidth,
+        height: imgHeight,
+        imageTimeout: 5000 // 设置图片的超时,设置0为禁用
+    })
+    const download = (url: string, fileName: string) => {
+        let aLink = document.createElement('a')
+        aLink.href = url
+        aLink.download = fileName || '' // HTML5新增的属性,指定保存文件名,可以不要后缀,注意,file:///模式下不会生效
+        let event
+        if (window.MouseEvent) event = new MouseEvent('click')
+        else {
+            event = document.createEvent('MouseEvents')
+            event.initMouseEvent(
+                'click',
+                true,
+                false,
+                window,
+                0,
+                0,
+                0,
+                0,
+                0,
+                false,
+                false,
+                false,
+                false,
+                0,
+                null
+            )
+        }
+        aLink.dispatchEvent(event)
+    }
+    // 两种下载方式url + blob
+    let imgURL = canvas.toDataURL('image/png') as any
+    if (typeof imgURL === 'object' && imgURL instanceof Blob) {
+        imgURL = URL.createObjectURL(imgURL) // 创建blob地址
+        download(imgURL, fileName)
+    } else {
+        // url  +  请求得到blob
+        let htmlrq = new XMLHttpRequest() as any
+        htmlrq.open('GET', imgURL, true)
+        htmlrq.responseType = 'blob'
+        htmlrq.onload = function (e: any) {
+            if (e.target.status === 200) {
+                imgURL = URL.createObjectURL(e.target.response) // 创建blob地址
+                download(imgURL, fileName)
+            } else {
+                console.error('下载错误')
+            }
+        }
+        htmlrq.send()
+    }
+    resetLoaing(true)
+}

+ 34 - 0
src/utils/registerMenu.js

@@ -0,0 +1,34 @@
+import { Boot } from '@wangeditor/editor'
+import {exp2pdf} from '@/utils/html2File'
+console.warn('此插件注册富文本自定义按钮')
+// 注册一个保存按钮
+class SaveBtn {
+
+    constructor() {
+        this.title = '导出PDF'
+        this.iconSvg = '<svg viewBox="0 0 1024 1024" style="width:22px;height:22px;" version="1.1" xmlns="http://www.w3.org/2000/svg" ><path d="M773.696 134.812444l-509.155556 0c-69.76 0-126.520889 56.760889-126.520889 126.542222l0 501.326222c0 69.781333 56.760889 126.499556 126.520889 126.499556l509.141333 0c69.781333 0 126.520889-56.718222 126.520889-126.499556L900.202667 261.361778C900.202667 191.573333 843.441778 134.833778 773.696 134.812444zM324.437333 184.213333l389.347556 0 0 279.608889L324.437333 463.822222 324.437333 184.213333zM850.872889 762.680889c0 42.552889-34.616889 77.191111-77.169778 77.191111l-509.155556 0c-42.552889 0-77.169778-34.638222-77.169778-77.191111L187.377778 261.383111c0-42.574222 34.616889-77.169778 77.169778-77.169778l0-0.021333 10.567111 0 0 329.009778 488.007111 0 0.021333 0L763.143111 184.184889l10.567111 0c42.56 0 77.169778 34.595556 77.169778 77.169778L850.88 762.680889zM591.772444 256.832l49.329778 0 0 164.522667-49.329778 0 0-164.522667ZM591.772444 256.832"></path></svg>'
+        this.tag = 'button'
+    }
+
+    getValue() {
+        return ''
+    }
+
+    isActive() {
+        return false
+    }
+
+    isDisabled() {
+        return false
+    }
+
+    exec() {
+        exp2pdf('exportPDF', '监控量测报告'+new Date().toLocaleDateString())
+    }
+}
+Boot.registerMenu({
+    key: 'SaveBtn',
+    factory() {
+        return new SaveBtn()
+    }
+})

+ 41 - 0
src/utils/resizeChart.js

@@ -0,0 +1,41 @@
+class ResizeChart {
+
+  /**
+   * 监听
+   * @param {Array | Object} charts 
+   */
+  on(charts) {
+    window.addEventListener('resize', ()=>{
+      if (Array.isArray(charts) && charts.length) {
+        for (let k = 0; k < charts.length; k++) {
+          const el = charts[k];
+          if (el.echart) el.echart.resize()
+        }
+      }else{
+        charts.resize()
+      }      
+    })
+  }
+
+  /**
+   * 移除监听
+   * @param {Array | Object} charts 
+   */
+  off(charts) {
+    window.removeEventListener('resize', ()=>{
+      if (Array.isArray(charts) && charts.length) {
+        for (let k = 0; k < charts.length; k++) {
+          const el = charts[k];
+          if (el.echart) el.echart.dispose()
+        }
+      }else{
+        charts.dispose()
+      }
+    })
+  }
+}
+
+
+
+
+export default new ResizeChart()

File diff suppressed because it is too large
+ 11 - 0
src/utils/weather.js


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