vue项目开发笔记记录(一):https://developer.aliyun.com/article/1483515
深克隆
/** * This is just a simple version of deep copy * Has a lot of edge cases bug * If you want to use a perfect deep copy, use lodash's _.cloneDeep * @param {Object} source * @returns {Object} */ export function deepClone(source) { if (!source && typeof source !== 'object') { throw new Error('error arguments', 'deepClone') } const targetObj = source.constructor === Array ? [] : {} Object.keys(source).forEach(keys => { if (source[keys] && typeof source[keys] === 'object') { targetObj[keys] = deepClone(source[keys]) } else { targetObj[keys] = source[keys] } }) return targetObj }
数组去重
/** * @param {Array} arr * @returns {Array} */ export function uniqueArr(arr) { return Array.from(new Set(arr)) }
创建唯一ID
/** * @returns {string} */ export function createUniqueString() { const timestamp = +new Date() + '' const randomNum = parseInt((1 + Math.random()) * 65536) + '' return (+(randomNum + timestamp)).toString(32) }
判断元素受否有该class
/** * Check if an element has a class * @param {HTMLElement} elm * @param {string} cls * @returns {boolean} */ export function hasClass(ele, cls) { return !!ele.className.match(new RegExp('(\\s|^)' + cls + '(\\s|$)')) }
元素添加class
/** * Add class to element * @param {HTMLElement} elm * @param {string} cls */ export function addClass(ele, cls) { if (!hasClass(ele, cls)) ele.className += ' ' + cls }
获取hasClass
/** * Remove class from element * @param {HTMLElement} elm * @param {string} cls */ export function removeClass(ele, cls) { if (hasClass(ele, cls)) { const reg = new RegExp('(\\s|^)' + cls + '(\\s|$)') ele.className = ele.className.replace(reg, ' ') } }
时间格式化,不包含时分秒
/** * 时间格式化,不包含时分秒 * @param _date * @returns {string} * @constructor */ export function FormatDateNoTime(_date) { if (_date === '' || _date === null || _date === undefined) { return '' } else { const now = new Date(_date) const year = now.getFullYear() const month = now.getMonth() + 1 < 10 ? '0' + (now.getMonth() + 1) : now.getMonth() + 1 const date = now.getDate() < 10 ? '0' + now.getDate() : now.getDate() return year + '/' + month + '/' + date } }
生成年份
<el-form-item label="统计年度" prop="opspTrtCode"> <el-select v-model="searchForm.opspTrtCode" clearable placeholder="请选择统计年度" allow-create style="width:100%" :fetch-suggestions="searchType" :trigger-on-focus="false"> <el-option label="全部" value="" /> <el-option v-for="item in initSelectYear()" :key="item.value" :label="item.label" :value="item.value" /> </el-select> </el-form-item>
initSelectYear() { var myDate = new Date() var year = myDate.getFullYear() // 获取当前年 var years = [] for (let i = 0; i < 30; i++) { years.push({ value: year - i, label: year - i + '年' }) } return years }
地图组件标点
<template> <div class="interzone-map"> <div id="interzoneMap" /> </div> </template> <script> import echarts from 'echarts' import './map/js/china' // import './map/js/province/anhui' // import './map/js/province/zhejiang' // import './map/js/province/aomen' // import './map/js/province/xianggang' // import './map/js/province/guangdong' // import './map/js/province/jiangxi' // import './map/js/province/jiangsu' // import './map/js/province/fujian' // import './map/js/province/gansu' // import './map/js/province/guizhou' // import './map/js/province/sichuan' // import './map/js/province/hubei' export default { name: 'EchartMap', components: {}, mixins: [], props: {}, data() { return { myChart: null, map_name: 'china', // 地图 mapData: [], geoCoordMap: {} } }, computed: {}, watch: {}, created() {}, mounted() { this.myChart = echarts.init(document.getElementById('interzoneMap')) window.onresize = () => { // 根据窗口大小调整曲线大小 this.myChart.resize() } this.init_map() // 地图初始化 }, methods: { init_map() { var data = [ { name: '海门', value: 88.76 }, { name: '鄂尔多斯', value: 88.6 }, { name: '招远', value: 39.21 }, { name: '舟山', value: 87.54 }, { name: '齐齐哈尔', value: 19.64 }, { name: '盐城', value: 54.2 } ] var geoCoordMap = { 海门: [121.15, 31.89], 鄂尔多斯: [109.781327, 39.608266], 招远: [120.38, 37.35], 舟山: [122.207216, 29.985295], 齐齐哈尔: [123.97, 47.33], 盐城: [120.13, 33.38] } // 获取数据和坐标 var convertData = function(data) { var res = [] for (var i = 0; i < data.length; i++) { var geoCoord = geoCoordMap[data[i].name] if (geoCoord) { res.push({ name: data[i].name, value: geoCoord.concat(data[i].value) }) } } return res } var optionMap = { backgroundColor: '#FFFFFF', title: { text: '全国参保覆盖情况', subtext: '2020年', x: 'center' }, // 提示框 tooltip: { trigger: 'item', formatter: function(params) { // 添加数字,否则为坐标 return ( params.name + '<br>' + '参保覆盖率' + '' + ':' + '' + params.value[2] + '' + '%' ) }, padding: [ 5, // 上 10, // 右 5, // 下 10 // 左 ], textStyle: { color: '#fff', fontSize: '13' } }, // 左侧小导航图标 visualMap: { show: false }, // 地图 geo: { map: 'china', roam: false, itemStyle: { // 正常状态下 normal: { areaColor: '#ffe7b2', borderColor: '#111' }, // 选定某一区域下 相当于 hover emphasis: { areaColor: '#ff6341' } }, z: 1 }, // 配置属性 series: [ { name: '参保覆盖率', type: 'scatter', coordinateSystem: 'geo', data: convertData(data), roam: false, label: { normal: { show: true // 省份名称 }, emphasis: { show: false } }, symbolSize: function(val) { return val[2] / 8 // 也可以根据这里的数值更改大小 val[2] / x x越小,标点越大 } }, { name: '参保覆盖率', type: 'effectScatter', coordinateSystem: 'geo', data: convertData( data .sort(function(a, b) { // 这里是多个数据比较大小 return b.value - a.value }) .slice(0, 1000) ), // slice里面的数可以是0 ,意思是全部显示 0,1000 意思是显示这组数据中最大前1000组 symbolSize: function(val) { return val[2] / 5 }, showEffectOn: 'render', rippleEffect: { brushType: 'stroke' }, hoverAnimation: true, label: { normal: { formatter: '{b}', position: 'right', show: false }, emphasis: { show: false } } } ] } // 使用制定的配置项和数据显示图表 this.myChart.setOption(optionMap) this.myChart.on('click', (params) => { console.log(params) }) } } } </script> <style scoped lang="scss"> .interzone-map { width: 100%; height: 100%; #interzoneMap { width: 100%; height: 100%; } } </style>
Echart组件封装
<template> <div class="My_Charts_Wrapper"> <div :id="id" :class="className" class="My_Charts" :style="{height:height,width:width}" /> </div> </template> <script> import echarts from 'echarts' require('echarts/theme/macarons') import resize from './mixins/resize' export default { name: 'MyCharts', components: {}, mixins: [resize], props: { id: { type: String, default: 'myCharts' }, className: { type: String, default: 'chart' }, width: { type: String, default: '100%' }, height: { type: String, default: '100%' }, options: { type: Object, default: function() { return {} } } }, data() { return { chart: null, defaultOptions: { grid: { left: '3%', right: '4%', bottom: '3%', top: '30', containLabel: true }, tooltip: { trigger: 'axis', axisPointer: { type: 'shadow' } } } } }, computed: {}, watch: { options: { deep: true, handler(val) { this.setOptions(Object.assign(val, this.options)) } } }, created() { }, mounted() { this.$nextTick(() => { this.init() }) }, beforeDestroy() { if (!this.chart) { return } this.chart.dispose() this.chart = null }, methods: { init() { this.chart = echarts.init(document.getElementById(this.id), 'macarons') this.setOptions() }, setOptions() { this.chart.setOption(Object.assign(this.defaultOptions, this.options)) } } } </script> <style scoped lang="scss"> .My_Charts_Wrapper { width: 100%; height: 100%; } .My_Charts { >div { margin: 0 auto; } /deep/ .charts-table { width: 100%; border: 1px solid #dfe6ec; text-align: center; border-collapse: collapse; >thead{ >tr{ >th{ height: 40px; background: #F0F2F5; border-right: 1px solid #cecece; border-bottom: 1px solid #dfe6ec; &:last-child { border-right: none; } } } } >tbody { >tr{ >td{ height: 40px; border-right: 1px solid #cecece; border-bottom: 1px solid #dfe6ec; &:last-child { border-right: none; } } &:last-child { >td { border-bottom: none; } } } } } } </style>
引入码表字段
import { getInsutype } from '@/api/PaymentInAdvance/PaymentInAdvanceManage/Request' import { CHK_STAS } from '@/utils/constant'
获取码表对应字段,塞入下拉
import { getCodeTableDetailConvergence } from '@/api/Common/Request' // 查码表 getCodeTableDetailConvergence() { const codeType = CHK_STAS getCodeTableDetailConvergence({ codeType }).then(res => { this.$set(this.itemsDatas[2], 'options', res.data[CHK_STAS]) }) }
引入colunms
import Columns from './columns'
标准参考页面
<!-- 单位待转金查询 --> <template> <normal-layer :search-number="itemsDatas.length" title-name="单位待转金查询列表" title-need-handle > <template slot="search-header"> <form-items :items-datas="itemsDatas" :form-datas="queryForm"> <el-button @click="reset">重置</el-button> <el-button type="primary" @click="search">查询</el-button> </form-items> </template> <template slot="title-btns"> <el-button type="primary" @click="printClick">打印</el-button> </template> <my-table-view v-loading="loading" :data="tableData" :columns="columns" /> <Pagination /> </normal-layer> </template> <script> import NormalLayer from '@/views/components/PageLayers/normalLayer' import FormItems from '@/views/components/PageLayers/form-items' import PageHandle from '@/mixins/pageHandle' import Columns from './listCloumns' export default { components: { NormalLayer, FormItems }, mixins: [PageHandle], data() { return { loading: false, itemsDatas: [ { label: '单位编号', prop: 'xxx', type: 'input' }, { label: '单位名称', prop: 'xxx', type: 'input' }, { label: '单位类型', prop: 'xxx', type: 'select' } ], queryForm: { xxx: '' }, columns: Columns, tableData: [ { name: '白兰花', code: 'xxx', nameCode: 'xxx' }, { name: '白兰花', code: 'xxx', nameCode: 'xxx' } ] } }, watch: { }, methods: { printClick() { window.print() } } } </script> <style lang='scss' scoped> </style>
审核和批量审核弹窗
<audit-dialog v-model="showAuditDialog" dialog-title="单位注销审核" @submit="submit" @closeAll="AuditDialogIsShow" />
import AuditDialog from '@/views/components/AuditDialog'
// 批量审核 batchAuditClick() { if (this.multipleSelection.length <= 0) { this.$msgConfirm('请选择') } else { this.showAuditDialog = true } },
表格详情弹窗
<!-- 详情弹窗 --> <Details :show="DetaVisible" @update:show="DetaIsShow" />
DetaIsShow() { this.DetaVisible = false }
<my-table-view v-loading="loading" :data="tableData" :columns="columns" :multiple-selection.sync="multipleSelection" > <template slot="operation" slot-scope="scope"> <my-button icon="detail" @click="detailsClick(scope.row)" /> <my-button icon="audit" @click="review(scope.row)" /> </template> </my-table-view>
detailsClick(row) { this.DetaVisible = true }
获取查询条件
search() { let params = {} params = Object.assign({}, this.searchForm) console.log('查询条件', params) }
常用字段
'formCode':'表格编码' 'formNum':'金额' 'formDepart':'制表部门' 'formTime':'制表时间' 'formDealer':'经办人' 'status':'状态' 'operation':'操作'
获取银行类型
import { BANK_TYPE_CODE } from '@/utils/constant' import { getCodeTableDetailConvergence } from '@/api/Common/Request' getTableCode() { getCodeTableDetailConvergence({ codeType: BANK_TYPE_CODE }).then(res => { this.$set(this.itemsDatas[2], 'options', res.data[BANK_TYPE_CODE]) }) }
搜索重置
<template slot="search-header"> <form-items ref="queryForm" :items-datas="itemsDatas" :form-datas="queryForm" :rules="rules" :model="queryForm"> <el-button @click="reset('queryForm')">重置</el-button> <el-button type="primary" @click="search">查询</el-button> </form-items> </template>
reset(formName) { this.$refs[formName]['elForm'].resetFields() }
批量审核
<template slot="title-btns"> <el-button type="primary" @click="addClick">批量审核</el-button> </template>
addClick(row) { if (this.multipleSelection.length > 0) { this.showAuditDialog = true } else { this.$msgError('请至少选择一行!') } }
submit(v) { const params = { rchkFlag: v.data.statue, memo: v.data.content, taxItrcEvtId: this.multipleSelection.map(item => item.taxItrcEvtId) } // 保存灵活就业征集信息发送审核 Api.saveTaxFlexiblePaySendAud(params).then(res => { if (res.code === 0) { v.fn() this.search() } else { this.$msgError(res.message) } }) }
vue项目开发笔记记录(三):https://developer.aliyun.com/article/1483520