基础数据渲染
准备静态结构
<template>
<div class="rule-container">
<div class="create-container">
<el-button type="primary">增加停车计费规则</el-button>
<el-button>导出Excel</el-button>
</div>
<!-- 表格区域 -->
<div class="table">
<el-table :data="ruleList" style="width: 100%">
<el-table-column type="index" label="序号" />
<el-table-column label="计费规则编号" prop="ruleNumber" />
<el-table-column label="计费规则名称" prop="ruleName" />
<el-table-column label="免费时长(分钟)" prop="freeDuration" />
<el-table-column label="收费上线(元)" prop="chargeCeiling" />
<el-table-column label="计费方式">
<template #default="scope">
{{ scope.row.chargeType }}
</template>
</el-table-column>
<el-table-column label="计费规则" prop="ruleNameView"/>
<el-table-column label="操作" fixed="right" width="120">
<template #default="scope">
<el-button size="mini" type="text">编辑</el-button>
<el-button size="mini" type="text">删除</el-button>
</template>
</el-table-column>
</el-table>
</div>
</div>
</template>
<script>
export default {
name: 'Building',
data() {
return {
ruleList: [],
params: {
page: 1,
pageSize: 10
},
total: 0,
dialogVisible: false
}
}
}
</script>
<style lang="scss" scoped>
.rule-container {
padding: 20px;
background-color: #fff;
}
.search-container {
display: flex;
align-items: center;
border-bottom: 1px solid rgb(237, 237, 237, .9);
padding-bottom: 20px;
.search-label {
width: 100px;
}
.search-main {
width: 220px;
margin-right: 10px;
}
}
.create-container{
margin: 10px 0px;
}
.page-container{
padding:4px 0px;
text-align: right;
}
.form-container{
padding:0px 80px;
}
</style>
{
path: '/parking',
component: Layout,
meta: { title: '行车管理', icon: 'el-icon-guide' },
children: [
{
path: 'rule',
component: () => import('@/views/car/car-rule'),
meta: { title: '计费规则管理' }
}]
},
封装接口
import request from '@/utils/request'
/**
* 获取规则列表
* @param { page, pageSize} params
* @returns
*/
export function getRuleListAPI(params) {
return request({
url: 'parking/rule/list',
params
})
}
获取并渲染数据
import { getRuleListAPI } from '@/apis/car'
mounted() {
this.getRuleList()
}
methods: {
// 获取规则列表
async getRuleList() {
const res = await getRuleListAPI(this.params)
this.ruleList = res.data.rows
}
}
<el-table :data="ruleList" style="width: 100%">
导出功能实现
背景:
- 后端主导实现
流程:前端调用到导出excel接口 -> 后端返回excel文件流 -> 浏览器会识别并自动下载
场景:大部分场景都有后端来做- 前端主导实现
流程:前端获取要导出的数据 -> 把常规数据处理成一个excel文件 -> 浏览器识别下载
场景:少数据量的导出
实现基础导出
Tutorial | SheetJS Community Edition
插件导出流程:
- 创建一个工作簿
- 创建一个工作表
- 把工作表加入到工作簿中
- 调用插件方法导出
npm i --save https://cdn.sheetjs.com/xlsx-0.20.0/xlsx-0.20.0.tgz
使用三方插件做需求
- 不考虑具体业务 实现一个能跑起来最简单的DEMO [基础环境 + 基础效果]
- 在基础DEMO基础上按照实际的业务数据去做对应的修改
import { utils, writeFileXLSX } from 'xlsx'
exportToExcel() {
// 创建一个新的工作簿
const workbook = utils.book_new()
// 创建一个工作表 要求一个对象数组格式
const worksheet = utils.json_to_sheet(
[
{ name: '张三', age: 18 },
{ name: '李四', age: 28 }
]
)
// 把工作表添加到工作簿 Data为工作表名称
utils.book_append_sheet(workbook, worksheet, 'Data')
// 改写表头
utils.sheet_add_aoa(worksheet, [['姓名', '年龄']], { origin: 'A1' })
// 导出方法进行导出
writeFileXLSX(workbook, 'SheetJSVueAoO.xlsx')
}
按照业务数据导出
// 导出excel
async exportToExcel() {
// 获取要导出的业务数据
const res = await getRuleListAPI(this.params)
// 表头英文字段key
const tableHeaderKeys = ['ruleNumber', 'ruleName', 'freeDuration', 'chargeCeiling', 'chargeType', 'ruleNameView']
// 表头中文字段value
const tableHeaderValues = ['计费规则编号', '计费规则名称', '免费时长(分钟)', '收费上线(元)', '计费方式', '计费规则']
// 以excel表格的顺序调整后端数据
const sheetData = res.data.rows.map((item) => {
const obj = {}
tableHeaderKeys.forEach(key => {
obj[key] = item[key]
})
return obj
})
// 创建一个工作表
const worksheet = utils.json_to_sheet(sheetData)
// 创建一个新的工作簿
const workbook = utils.book_new()
// 把工作表添加到工作簿
utils.book_append_sheet(workbook, worksheet, 'Data')
// 改写表头
utils.sheet_add_aoa(worksheet, [tableHeaderValues], { origin: 'A1' })
writeFileXLSX(workbook, 'SheetJSVueAoO.xlsx')
}
适配付费状态
// 适配收费状态
formatChargeType(type) {
const TYPEMAP = {
'duration': '按时长收费',
'turn': '按次收费',
'partition': '分段收费'
}
return TYPEMAP[type]
}
// 适配table
<el-table-column label="计费方式">
<template #default="scope">
{{ formatChargeType(scope.row.chargeType ) }}
</template>
</el-table-column>
// 适配excel表格
const sheetData = res.data.rows.map(item => {
const _obj = {}
headerKeys.forEach(key => {
// 赋值
// 针对计费规则做处理
if (key === 'chargeType') {
_obj[key] = this.formatChargeType(item[key])
} else {
_obj[key] = item[key]
}
})
return _obj
})
添加计费规则
控制弹框打开关闭
<!-- 弹框 -->
<el-dialog :visible="dialogVisible" width="680px" title="新增规则">
<!-- 表单接口 -->
<div class="form-container">
<el-form ref="addForm" :model="addForm" :rules="addFormRules" label-position="top">
<el-form-item label="计费规则编号" prop="ruleNumber">
<el-input v-model="addForm.ruleNumber" />
</el-form-item>
<el-form-item label="计费规则名称" prop="ruleName">
<el-input v-model="addForm.ruleName" />
</el-form-item>
<el-form-item label="计费方式" prop="chargeType">
<el-radio-group v-model="addForm.chargeType" size="small">
<el-radio label="duration" border>时长收费</el-radio>
<el-radio label="turn" border>按次收费</el-radio>
<el-radio label="partition" border>分段收费</el-radio>
</el-radio-group>
</el-form-item>
<div class="flex-container">
<el-form-item label="免费时长">
<el-input v-model="addForm.freeDuration" />
</el-form-item>
<el-form-item label="收费上限">
<el-input v-model="addForm.chargeCeiling" />
</el-form-item>
</div>
<el-form-item label="计费规则">
<!-- 按时长收费区域 -->
<div class="duration">
每 <el-input v-model="addForm.durationTime" class="input-box" /> 小时 <el-input v-model="addForm.durationPrice" class="input-box" /> 元
</div>
<!-- 按次收费区域 -->
<div class="turn">
每次 <el-input v-model="addForm.turnPrice" class="input-box" /> 元
</div>
<!-- 按分段收费区域 -->
<div class="partition">
<div class="item"><el-input v-model="addForm.partitionFrameTime" class="input-box" />小时内,每小时收费<el-input v-model="addForm.partitionFramePrice" class="input-box" /> 元</div>
<div class="item">每增加<el-input v-model="addForm.partitionIncreaseTime" class="input-box" />小时,增加<el-input v-model="addForm.partitionIncreasePrice" class="input-box" /> 元</div>
</div>
</el-form-item>
</el-form>
</div>
<template #footer>
<el-button size="mini" @click="dialogVisible = false">取 消</el-button>
<el-button size="mini" type="primary">确 定</el-button>
</template>
</el-dialog>
data() {
return {
dialogVisible: true, // 控制弹框关闭打开
addForm: {
ruleNumber: '', // 计费规则编号
ruleName: '', // 计费规则名称
chargeType: 'duration', // 计费规则类型 duration / turn / partition
chargeCeiling: null,
freeDuration: null,
// 时长计费独有字段
durationTime: null, // 时长计费单位时间
durationPrice: null, // 时长计费单位价格
durationType: 'hour',
// 按次收费独有字段
turnPrice: null,
// 分段计费独有字段
partitionFrameTime: null, // 段内时间
partitionFramePrice: null, // 段内费用
partitionIncreaseTime: null, // 超出时间
partitionIncreasePrice: null // 超出费为收费价钱
}, // 计费规则表单对象
addFormRules: {
ruleNumber: [
{
required: true,
message: '请输入规则编号',
trigger: 'blur'
}
],
ruleName: [
{
required: true,
message: '请输入规则名称',
trigger: 'blur'
}
],
chargeType: [
{
required: true,
message: '请选择收费类型',
trigger: 'blur'
}
]
} // 计费规则校验规则对象
}
}
根据计费方式适配计费规则
<el-form-item label="计费规则">
<!-- 按时长收费区域 -->
<div v-if="addForm.chargeType === 'duration'" class="duration">
每 <el-input v-model="addForm.durationTime" class="input-box" /> 小时 <el-input v-model="addForm.durationPrice" class="input-box" /> 元
</div>
<!-- 按次收费区域 -->
<div v-if="addForm.chargeType === 'turn'" class="turn">
每次 <el-input v-model="addForm.turnPrice" class="input-box" /> 元
</div>
<!-- 按分段收费区域 -->
<div v-if="addForm.chargeType==='partition'" class="partition">
<div class="item"><el-input v-model="addForm.partitionFrameTime" class="input-box" />小时内,每小时收费<el-input v-model="addForm.partitionFramePrice" class="input-box" /> 元</div>
<div class="item">每增加<el-input v-model="addForm.partitionIncreaseTime" class="input-box" />小时,增加<el-input v-model="addForm.partitionIncreasePrice" class="input-box" /> 元</div>
</div>
</el-form-item>
确认提交
/**
* 创建规则
* @returns
*/
export function createRuleAPI(data) {
return request({
url: '/parking/rule',
method: 'POST',
data
})
}
confirmAdd() {
this.$refs.addForm.validate(async valid => {
if (valid) {
await createRuleAPI(this.addForm)
this.getRuleList()
this.dialogVisible = false
}
})
}
作者:王江伟 创建时间:2024-07-17 15:52
最后编辑:王江伟 更新时间:2024-07-23 16:14
最后编辑:王江伟 更新时间:2024-07-23 16:14