api接口封装
1.接口函数封装
import request from '@/utils/request' import apiUrl from '../apiUrl' // 根据主键获取单条记录 export function itemById(params) { return request({ url: apiUrl.dataSourceApi.getItemById, method: 'get', params: params }) }
2.接口地址封装
export default { // 数据来源管理 dataSourceApi: { queryAllData: '/web/bdp/datasourcemanager/datasourceinfo/all/1', // 获取所有来源数据源信息 getItemById: '/web/bdp/datasourcemanager/datasourceinfo/item', // 根据主键获取单条记录 getAllData: '/web/bdp/datasourcemanager/databaserelease/all/1', // 获取数据来源已支持的数据库类型 }, }
vue常用组件
折线图组件
<template> <div class="trend-map"> <div id="tendChart" /> </div> </template> <script> import echarts from 'echarts' export default { name: 'TrendMap', props: { objData: { type: Object, default: function() { return {} } } }, data() { return { yData: [820, 932, 901, 934, 1290, 1330, 1320], xData: [ '2020-05-11', '2020-05-12', '2020-05-13', '2020-05-14', '2020-05-15', '2020-05-16', '2020-05-17'] } }, watch: { objData: { handler(val) { // this.queryNetworkBandwith() }, deep: true } }, mounted() { this.draw() // 临时展示作用 }, methods: { queryTPSTransation() { const params = { number: '40', period: this.objData.period, rtTaskNo: this.objData.rtTaskNo } queryTPSTransation(params).then(res => { if (res.code === 0) { this.xData = res.data.time this.yData = res.data.data this.draw() } }) }, draw() { var option = { grid: { top: '20%', left: '5%', right: '5%', bottom: '15%' }, title: { text: '存储趋势图', textStyle: { color: '#fff', fontSize: 16 }, left: '1%', top: '3%', bottom: '20%' }, color: ['#00a3e5'], tooltip: { trigger: 'axis', padding: [2, 10], textStyle: { fontSize: 16 }, formatter: function(params) { var result = params[0].axisValue + '<br/>' params.forEach(function(item) { result += item.seriesName + ':' + item.value + ' MB</br>' }) return result } }, xAxis: [{ type: 'category', axisLine: { show: true, lineStyle: { color: '#fff' } }, splitLine: { show: false }, boundaryGap: true, data: this.xData }], yAxis: [{ name: 'MB', type: 'value', splitLine: { show: false }, axisLine: { show: true, lineStyle: { color: '#fff' } }, axisLabel: { show: true, margin: 20, textStyle: { color: '#fff' } }, axisTick: { show: true } }], series: [{ name: '存储趋势图', type: 'line', smooth: true, // 是否平滑 showAllSymbol: true, symbol: 'none', symbolSize: 5, lineStyle: { normal: { color: '#00a3e5', width: 2 } }, data: this.yData }] } // 初始化图表 const chartObj = echarts.init(document.getElementById('tendChart')) chartObj.setOption(option) if (option && typeof option === 'object') { chartObj.setOption(option) } } } } </script> <style scoped lang="scss"> .trend-map{ margin-top: 15px; background-color: #343d47; } #tendChart { height: 400px; } </style>
柱状图组件
<template> <div class="trend-map"> <div class="occupy-more" @click="navToMoreDetail">更多<i class="fa fa-angle-right fa-fw" /></div> <div id="occupyChart" /> </div> </template> <script> import echarts from 'echarts' export default { name: 'TrendMap', props: { objData: { type: Object, default: function() { return {} } } }, data() { return { yData: Array.from({ length: 10 }, v => Math.random() * 10240000), xData: Array.from({ length: 10 }, (v, w) => 'powersi' + w) } }, computed: {}, watch: { objData: { handler(val) { // this.queryNetworkBandwith() }, deep: true } }, mounted() { this.draw() // 临时展示作用 }, methods: { queryTPSTransation() { const params = { number: '40', period: this.objData.period, rtTaskNo: this.objData.rtTaskNo } queryTPSTransation(params).then(res => { if (res.code === 0) { this.xData = res.data.time this.yData = res.data.data this.draw() } }) }, draw() { var option = { grid: { top: '20%', left: '2%', right: '5%', bottom: '15%', containLabel: true }, title: { text: '表占用存储Top', textStyle: { color: '#fff', fontSize: 16 }, left: '1%', top: '3%', bottom: '20%' }, tooltip: { trigger: 'axis', padding: [2, 10], textStyle: { fontSize: 16 }, formatter: function(data) { // 格式化为字节并格式化tooltip var filesize = data[0].value var result = data[0].axisValue + '<br/>' if (filesize == null || filesize == '') { return '0 Bytes' } var unitArr = [ 'Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB' ] var index = 0 var srcsize = parseFloat(filesize) index = Math.floor(Math.log(srcsize) / Math.log(1024)) var size = srcsize / Math.pow(1024, index) size = size.toFixed(2) // 保留的小数位数 result += data[0].seriesName + ':' + size + unitArr[index] + '</br>' return result } }, color: ['#00a3e5'], xAxis: { data: this.xData, type: 'category', boundaryGap: [0, 0.01], show: true, axisLine: { show: true, lineStyle: { color: '#fff' } } }, yAxis: { type: 'value', data: this.yData, axisTick: { show: true }, axisLine: { show: true, lineStyle: { color: '#fff' } }, axisLabel: { interval: 0, margin: 15 } }, series: [ { name: '2011年', type: 'bar', data: this.yData, barWidth: 20, // 柱图宽度 itemStyle: { normal: { borderRadius: 10, label: { show: true, // 开启显示 position: 'top', // 在上方显示 textStyle: { // 数值样式 color: '#fff', fontSize: 16, top: 10 }, formatter: function(data) { // 格式化为字节 var filesize = data.value if (filesize == null || filesize == '') { return '0 Bytes' } var unitArr = [ 'Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB' ] var index = 0 var srcsize = parseFloat(filesize) index = Math.floor(Math.log(srcsize) / Math.log(1024)) var size = srcsize / Math.pow(1024, index) size = size.toFixed(2) // 保留的小数位数 return size + unitArr[index] } } } } } ] } // 初始化图表 const chartObj = echarts.init(document.getElementById('occupyChart')) chartObj.setOption(option) if (option && typeof option === 'object') { chartObj.setOption(option) } }, navToMoreDetail() { this.$router.push('/dataMap/myData') } } } </script> <style scoped lang="scss" scoped> .trend-map { margin-top: 15px; background-color: #343d47; position: relative; } .occupy-more { position: absolute; right: 40px; top: 10px; z-index: 999; font-size: 14px; cursor: pointer; padding: 3px 3px 3px 6px; &:hover{ background-color: #212a33; border-radius: 3px; } } #occupyChart { height: 400px; } </style>
echart tootip格式化
tooltip: { trigger: 'axis', padding: [2, 10], textStyle: { fontSize: 16 }, formatter: function (data) { // 格式化为字节并格式化tooltip var filesize = data[0].value var result = data[0].axisValue + '<br/>' if (filesize == null || filesize == '') { return '0 Bytes' } var unitArr = new Array('Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB') var index = 0 var srcsize = parseFloat(filesize) index = Math.floor(Math.log(srcsize) / Math.log(1024)) var size = srcsize / Math.pow(1024, index) size = size.toFixed(2) // 保留的小数位数 result += data[0].seriesName + ':' + size + unitArr[index] + '</br>' return result } },
随机生成数据
yData: Array.from({ length: 10 }, v => Math.random() * 10240000), xData: Array.from({ length: 10 }, (v, w) => 'powersi' + w)
标准头部
<header> <span class="title">服务器管理</span> <div class="query"> <el-form :inline="true" class="demo-form-inline"> <el-form-item> <el-input v-model="dbName" clearable placeholder="请输入服务器名称" @keyup.enter.native="getData"> <template slot="prepend">搜索</template> <el-button slot="append" icon="el-icon-search" @click.native.prevent="getData" /> </el-input> </el-form-item> <el-form-item> <el-button type="primary" icon="el-icon-plus" @click="showDatabase = true">新增服务器</el-button> </el-form-item> </el-form> </div> </header>
element-ui表格
<div class=" taskOperationMonitoring"> <!-- 服务器管理 --> <div class="data-sourse"> <el-table :data="tableData" height="650" stripe style="width: 100%;"> <el-table-column type="index" label="序号" align="center" width="50" /> <el-table-column prop="ips" label="服务器IP地址" align="center" width="180" /> <el-table-column prop="port" label="端口" align="center" /> <el-table-column prop="host" label="主机" align="center" width="180" /> <el-table-column prop="username" label="用户名" align="center" /> <el-table-column prop="password" label="密码" align="center" /> <el-table-column prop="privat" label="私钥" align="center" /> <el-table-column prop="cpu" label="CPU核数" align="center" /> <el-table-column prop="storage" label="内存(GB)" align="center" /> <el-table-column prop="sd" label="磁盘大小(GB)" align="center" /> <el-table-column prop="isSD" label="是否SSD" align="center"> <template slot-scope="scope"> <span v-if="scope.taskStas= '1'" class="success">正常</span> <span v-else class="danger">异常</span> </template> </el-table-column> <el-table-column prop="other" label="备注" align="center" /> <el-table-column label="操作" align="center" width="140"> <template slot-scope="scope"> <el-button type="primary" size="mini" @click="details(scope.row)">编辑</el-button> <el-button type="primary" size="mini" @click="deleteItem(scope.row)">删除</el-button> </template> </el-table-column> </el-table> <el-pagination :current-page="currentPage" :page-sizes="[10, 20, 30, 40]" :page-size="pageSize" layout="total, sizes, prev, pager, next, jumper" :total="total" @size-change="handleSizeChange" @current-change="handleCurrentChange" /> </div> </div> data() { return { tableData: Array(15).fill(item), currentPage: 1, pageSize: 20, total: 20 } }
页面跳转清除定时器
data() { return { timer: null // 定时器名称 } }, mounted(){ this.timer = (() => { // 某些操作 }, 1000) }, //最后在beforeDestroy()生命周期内清除定时器: beforeDestroy() { clearInterval(this.timer); this.timer = null; }
vue通用模板
<template> <div class=""> 地区间参保覆盖情况分析 </div> </template> <script> export default { name: '', components: {}, mixins: [], props: {}, data() { return {} }, computed: {}, watch: {}, created() {}, mounted() {}, methods: {}, } </script> <style scoped lang="scss"> </style>
filters过滤器
引入
import { toThousandFilter, numberToPercent } from '../../../filters'
// import parseTime, formatTime and set to filter export { parseTime, formatTime } from '@/utils' /** * Show plural label if time is plural number * @param {number} time * @param {string} label * @return {string} */ function pluralize(time, label) { if (time === 1) { return time + label } return time + label + 's' } /** * @param {number} time */ export function timeAgo(time) { const between = Date.now() / 1000 - Number(time) if (between < 3600) { return pluralize(~~(between / 60), ' minute') } else if (between < 86400) { return pluralize(~~(between / 3600), ' hour') } else { return pluralize(~~(between / 86400), ' day') } } /** * Number formatting * like 10000 => 10k * @param {number} num * @param {number} digits */ export function numberFormatter(num, digits) { const si = [ { value: 1E18, symbol: 'E' }, { value: 1E15, symbol: 'P' }, { value: 1E12, symbol: 'T' }, { value: 1E9, symbol: 'G' }, { value: 1E6, symbol: 'M' }, { value: 1E3, symbol: 'k' } ] for (let i = 0; i < si.length; i++) { if (num >= si[i].value) { return (num / si[i].value).toFixed(digits).replace(/\.0+$|(\.[0-9]*[1-9])0+$/, '$1') + si[i].symbol } } return num.toString() } /** * 10000 => "10,000" * @param {number} num */ export function toThousandFilter(num) { return (+num || 0).toString().replace(/^-?\d+/g, m => m.replace(/(?=(?!\b)(\d{3})+$)/g, ',')) } /** * Upper case first char * @param {String} string */ export function uppercaseFirst(string) { return string.charAt(0).toUpperCase() + string.slice(1) } /** * money formatting * like 10000 => 1万元 * @param {number | String} value */ export function moneyFilter(value) { if (!value) return '0元' let result = 0 if (parseFloat(value) >= 10000) { result = (value / 10000).toFixed(2) + '万元' } else if (parseFloat(value) >= 100000000) { result = (value / 100000000).toFixed(2) + '亿元' } else { result = value + '元' } return result } /** * count formatting * like 10000 => 1万次 * @param {number | String} value */ export function conutFilter(value) { if (!value) return '0次' let result = 0 if (parseFloat(value) >= 10000) { result = (value / 10000).toFixed(2) + '万次' } else if (parseFloat(value) >= 100000000) { result = (value / 100000000).toFixed(2) + '亿次' } else { result = value + '次' } return result } export function numberToPercent(value, total, fixed) { // console.log(value) // console.log(total) // console.log((value / total * 100).toFixed(fixed) + '%') return (value / total * 100).toFixed(fixed) + '%' }
基本路由配置
{ path: '/assistDecision', component: Layout, alwaysShow: true, redirect: '/assistDecision/medicalPriceAnalyze', meta: { title: '数据分析平台', icon: 'icon' }, children: [ { path: 'medicalPriceAnalyze', component: () => import('@/views/assist-decision/medical-price-analyze/index'), name: 'medicalPriceAnalyze', meta: { title: '医疗机构费用分析', icon: 'icon', noCache: true } } }
utils公共函数使用
引入
import { deepClone } from '@/utils/index'
获取select的label值
/** * 获取select的label值 * @param value 选中id * @param arr 原数组 * @param idName id的字段名 * @param labelName name的字段名 * @returns {*} */ export function getSelectLabel(value, arr, idName, labelName) { return arr.find(item => { return item[idName] === value })[labelName] }
时间格式化
/** * Parse the time to string * @param {(Object|string|number)} time * @param {string} cFormat * @returns {string | null} */ export function parseTime(time, cFormat) { if (arguments.length === 0) { return null } const format = cFormat || '{y}-{m}-{d} {h}:{i}:{s}' let date if (typeof time === 'object') { date = time } else { if ((typeof time === 'string')) { if ((/^[0-9]+$/.test(time))) { // support "1548221490638" time = parseInt(time) } else { // support safari // https://stackoverflow.com/questions/4310953/invalid-date-in-safari time = time.replace(new RegExp(/-/gm), '/') } } if ((typeof time === 'number') && (time.toString().length === 10)) { time = time * 1000 } date = new Date(time) } const formatObj = { y: date.getFullYear(), m: date.getMonth() + 1, d: date.getDate(), h: date.getHours(), i: date.getMinutes(), s: date.getSeconds(), a: date.getDay() } const time_str = format.replace(/{([ymdhisa])+}/g, (result, key) => { const value = formatObj[key] // Note: getDay() returns 0 on Sunday if (key === 'a') { return ['日', '一', '二', '三', '四', '五', '六'][value] } return value.toString().padStart(2, '0') }) return time_str }
时间转几小时前
/** * @param {number} time * @param {string} option * @returns {string} */ export function formatTime(time, option) { if (('' + time).length === 10) { time = parseInt(time) * 1000 } else { time = +time } const d = new Date(time) const now = Date.now() const diff = (now - d) / 1000 if (diff < 30) { return '刚刚' } else if (diff < 3600) { // less 1 hour return Math.ceil(diff / 60) + '分钟前' } else if (diff < 3600 * 24) { return Math.ceil(diff / 3600) + '小时前' } else if (diff < 3600 * 24 * 2) { return '1天前' } if (option) { return parseTime(time, option) } else { return ( d.getMonth() + 1 + '月' + d.getDate() + '日' + d.getHours() + '时' + d.getMinutes() + '分' ) } }
获取url的参数
/** * @param {string} url * @returns {Object} */ export function getQueryObject(url) { url = url == null ? window.location.href : url const search = url.substring(url.lastIndexOf('?') + 1) const obj = {} const reg = /([^?&=]+)=([^?&=]*)/g search.replace(reg, (rs, $1, $2) => { const name = decodeURIComponent($1) let val = decodeURIComponent($2) val = String(val) obj[name] = val return rs }) return obj }
获取字节长度
/** * @param {string} input value * @returns {number} output value */ export function byteLength(str) { // returns the byte length of an utf8 string let s = str.length for (var i = str.length - 1; i >= 0; i--) { const code = str.charCodeAt(i) if (code > 0x7f && code <= 0x7ff) { s++ } else if (code > 0x7ff && code <= 0xffff) s += 2 if (code >= 0xDC00 && code <= 0xDFFF) i-- } return s }
清除数组
/** * @param {Array} actual * @returns {Array} */ export function cleanArray(actual) { const newArray = [] for (let i = 0; i < actual.length; i++) { if (actual[i]) { newArray.push(actual[i]) } } return newArray }
json转数组
/** * @param {Object} json * @returns {Array} */ export function param(json) { if (!json) return '' return cleanArray( Object.keys(json).map(key => { if (json[key] === undefined) return '' return encodeURIComponent(key) + '=' + encodeURIComponent(json[key]) }) ).join('&') }
字符串转对象
/** * @param {string} url * @returns {Object} */ export function param2Obj(url) { const search = url.split('?')[1] if (!search) { return {} } return JSON.parse( '{"' + decodeURIComponent(search) .replace(/"/g, '\\"') .replace(/&/g, '","') .replace(/=/g, '":"') .replace(/\+/g, ' ') + '"}' ) }
富文本过滤成普通文本
/** * @param {string} val * @returns {string} */ export function html2Text(val) { const div = document.createElement('div') div.innerHTML = val return div.textContent || div.innerText }
对象克隆
/** * Merges two objects, giving the last one precedence * @param {Object} target * @param {(Object|Array)} source * @returns {Object} */ export function objectMerge(target, source) { if (typeof target !== 'object') { target = {} } if (Array.isArray(source)) { return source.slice() } Object.keys(source).forEach(property => { const sourceProperty = source[property] if (typeof sourceProperty === 'object') { target[property] = objectMerge(target[property], sourceProperty) } else { target[property] = sourceProperty } }) return target }
toggle效果
/** * @param {HTMLElement} element * @param {string} className */ export function toggleClass(element, className) { if (!element || !className) { return } let classString = element.className const nameIndex = classString.indexOf(className) if (nameIndex === -1) { classString += '' + className } else { classString = classString.substr(0, nameIndex) + classString.substr(nameIndex + className.length) } element.className = classString }
获取当前时间
/** * @param {string} type * @returns {Date} */ export function getTime(type) { if (type === 'start') { return new Date().getTime() - 3600 * 1000 * 24 * 90 } else { return new Date(new Date().toDateString()) } }
防抖函数
/** * @param {Function} func * @param {number} wait * @param {boolean} immediate * @return {*} */ export function debounce(func, wait, immediate) { let timeout, args, context, timestamp, result const later = function() { // 据上一次触发时间间隔 const last = +new Date() - timestamp // 上次被包装函数被调用时间间隔 last 小于设定时间间隔 wait if (last < wait && last > 0) { timeout = setTimeout(later, wait - last) } else { timeout = null // 如果设定为immediate===true,因为开始边界已经调用过了此处无需调用 if (!immediate) { result = func.apply(context, args) if (!timeout) context = args = null } } } return function(...args) { context = this timestamp = +new Date() const callNow = immediate && !timeout // 如果延时不存在,重新设定延时 if (!timeout) timeout = setTimeout(later, wait) if (callNow) { result = func.apply(context, args) context = args = null } return result } }
vue项目开发笔记记录(二):https://developer.aliyun.com/article/1483518