路由报表模板配置页面

This commit is contained in:
zhujiyan
2024-06-19 08:49:10 +08:00
parent cdc640c4b2
commit a24e54c0ec
23 changed files with 6747 additions and 3 deletions

View File

@@ -6,6 +6,13 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>电能质量数据监测云平台</title> <title>电能质量数据监测云平台</title>
</head> </head>
<!-- 在这里全局引入luckysheet的样式文件和js文件 -->
<link rel="stylesheet" href="/static/luckysheet/pluginsCss.css" />
<link rel="stylesheet" href="/static/luckysheet/plugins.css" />
<link rel="stylesheet" href="/static/luckysheet/luckysheet.css" />
<link rel="stylesheet" href="/static/luckysheet/iconfont.css" />
<script src="/static/luckysheet/plugin.js"></script>
<script src="/static/luckysheet/luckysheet.umd.js"></script>
<body> <body>
<div id="app"></div> <div id="app"></div>
<script type="module" src="/src/main.ts"></script> <script type="module" src="/src/main.ts"></script>

View File

@@ -21,9 +21,12 @@
"echarts-liquidfill": "^3.1.0", "echarts-liquidfill": "^3.1.0",
"echarts4": "npm:echarts@^4.9.0", "echarts4": "npm:echarts@^4.9.0",
"element-plus": "^2.7.5", "element-plus": "^2.7.5",
"exceljs": "v4.4.0",
"file-saver": "v2.0.5",
"html2canvas": "^1.4.1", "html2canvas": "^1.4.1",
"jquery": "^3.7.1", "jquery": "^3.7.1",
"lodash-es": "^4.17.21", "lodash-es": "^4.17.21",
"luckyexcel": "v1.0.1",
"mitt": "^3.0.1", "mitt": "^3.0.1",
"nprogress": "^0.2.0", "nprogress": "^0.2.0",
"pinia": "^2.1.7", "pinia": "^2.1.7",

592
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,11 @@
import request from '@/utils/request'
export function getQualityAssessData(data: any) {
return request({
url: '/harmonic-boot/asses/getQualityAssessData',
method: 'post',
data: data
})
}

View File

@@ -0,0 +1,9 @@
import request from '@/utils/request'
export function getHistoryResult(data: any) {
return request({
url: '/harmonic-boot/harmonic/getHistoryResult',
method: 'post',
data: data
})
}

View File

@@ -0,0 +1,9 @@
import request from '@/utils/request'
export function getHarmInHarmData(data: any) {
return request({
url: '/harmonic-boot/inHarm/getHarmInHarmData',
method: 'post',
data: data
})
}

View File

@@ -0,0 +1,165 @@
import createAxios from '@/utils/request'
// 获取参数指标
export function getIndex() {
return createAxios({
url: '/harmonic-boot/customReport/reportChooseTree',
method: 'get'
})
}
//、查询数据激活报表模板
export function updateTemplateActive(data) {
return createAxios({
url: '/harmonic-boot/customReport/updateTemplateActive',
method: 'post',
data
})
}
//获取报表模板 //部门树查询
export function getTemplateList(data:any) {
return createAxios({
url: '/harmonic-boot/customReport/getTemplateList',
// url:'/api3/harmonic-boot/customReport/getTemplateList',
method: 'post',
data
})
}
//删除报表模板
export function delTemplate(data) {
return createAxios({
url: '/harmonic-boot/customReport/delTemplate',
method: 'post',
data
})
}
//修改获取数据
export function getCustomReportTemplateById(params) {
return createAxios({
url: '/harmonic-boot/customReport/getCustomReportTemplateById',
method: 'get',
params
})
}
//修改获取数据
export function viewCustomReportTemplateById(params) {
return createAxios({
url: '/harmonic-boot/customReport/viewCustomReportTemplateById',
method: 'get',
params
})
}
//修改模板
export function dateTemplateup(data) {
return createAxios({
url: '/harmonic-boot/customReport/updateTemplate',
method: 'POST',
data
})
}
//新增报表模板
export function addTemplate(data) {
return createAxios({
url: '/harmonic-boot/customReport/addTemplate',
method: 'post',
data: data
})
}
//模板对应指标替换
export function getCustomReport(data: any) {
return createAxios({
url: '/harmonic-boot/customReport/getCustomReport',
method: 'POST',
data
})
}
//绑定模板
export function updateBindTemplate(data) {
return createAxios({
url: '/harmonic-boot/customReport/updateBindTemplate',
method: 'post',
data
})
}
//根据模板ID查询数据
export function getDataByTempId(params) {
return createAxios({
url: '/harmonic-boot/customReport/getDataByTempId',
method: 'get',
params
})
}
//根据部门查询模板
export function getTemplateByDept(params) {
return createAxios({
url: '/harmonic-boot/customReport/getTemplateByDept',
method: 'get',
params
})
}
//资源管理 查询数据
export function queryData(data) {
return createAxios({
url: '/system-boot/resourceAdministration/queryData',
method: 'post',
data
})
}
//资源管理 查询数据
export function uploadFile(data) {
return createAxios({
url: '/system-boot/resourceAdministration/uploadFile',
method: 'post',
data
})
}
//资源管理 删除资源
export function deleteFile(params) {
return createAxios({
url: '/system-boot/resourceAdministration/deleteFile',
method: 'get',
params
})
}
//资源管理 下载资源
export function downloadFile(params) {
return createAxios({
url: '/system-boot/resourceAdministration/downloadFile',
method: 'get',
params,
responseType: 'blob'
})
}
//资源管理 修改资源
export function updateFile(data) {
return createAxios({
url: '/system-boot/resourceAdministration/updateFile',
method: 'post',
data
})
}
//合格率报告
export function pageTable(data) {
return createAxios({
url: '/harmonic-boot/qualifiedReport/pageTable',
method: 'post',
data
})
}
//合格率报告
export function targetLimitChooseTree() {
return createAxios({
url: '/harmonic-boot/customReport/targetLimitChooseTree',
method: 'get'
})
}
//监测点指标
export function terminalChooseTree() {
return createAxios({
url: '/harmonic-boot/customReport/terminalChooseTree',
method: 'get'
})
}

View File

@@ -0,0 +1,16 @@
import request from '@/utils/request'
export function getHistoryTableData(data:any) {
return request({
url: '/harmonic-boot/normLimit/getHistoryTableData',
method: 'post',
data: data
})
}
export function getHistoryLineData(data:any) {
return request({
url: '/harmonic-boot/harmonic/getHistoryLineData',
method: 'post',
data: data
})
}

View File

@@ -0,0 +1,9 @@
import request from '@/utils/request'
export function getSteadyData(data: any) {
return request({
url: '/harmonic-boot/pollution/getSteadyData',
method: 'post',
data: data
})
}

View File

@@ -13,6 +13,19 @@ export function queryByCode(code: string) {
data: form data: form
}) })
} }
// 字典树接口2
export function queryByAllCode() {
let form = new FormData()
// form.append('code', code)
return createAxios({
url: '/system-boot/dictTree/queryTree',
method: 'GET',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
// data: form
})
}
// 字典树接口通过code // 字典树接口通过code
export function queryCsDictTree(pid: string) { export function queryCsDictTree(pid: string) {
@@ -28,6 +41,19 @@ export function queryCsDictTree(pid: string) {
}) })
} }
/**
* 根据id查询字典值
*/
export const getDictTreeById = (id: any) => {
let form = new FormData()
form.append('id', id)
return createAxios({
url: '/system-boot/dictTree/queryById',
method: 'POST',
data:form
})
}
// 字典树接口通过id // 字典树接口通过id
export function queryByid(id: string) { export function queryByid(id: string) {
let form = new FormData() let form = new FormData()
@@ -42,7 +68,6 @@ export function queryByid(id: string) {
}) })
} }
//新增字典树数据 //新增字典树数据
export const addDictTree = (data: any) => { export const addDictTree = (data: any) => {
return createAxios({ return createAxios({
@@ -52,12 +77,19 @@ export const addDictTree = (data: any) => {
}) })
} }
// 编辑统计指标配置项 // 编辑统计指标配置项
export const updateStatistical = (data) => { export const updateStatistical = (data: any) => {
return createAxios({ return createAxios({
url: '/system-boot/dic/update', url: '/system-boot/dic/update',
method: 'PUT', method: 'PUT',
data: data data: data
}) })
} }
// 单位绑定
export function codeDicTree(data: any) {
return createAxios({
url: '/system-boot/dic/codeDicTree',
method: 'get',
params: data
})
}

View File

@@ -0,0 +1,108 @@
<template>
<el-tabs v-model="activeName" class="demo-tabs">
<el-tab-pane label="数据单位" name="0">
绑定数据单位:
<el-cascader
:popper-append-to-body="false"
ref="cascaderUnit"
placeholder="请选择数据单位"
v-model="value"
:options="options1"
filterable
@change="handleChange"
:props="{
value: 'code',
label: 'name'
}"
></el-cascader>
</el-tab-pane>
<el-tab-pane label="数据指标" name="1">
绑定数据指标:
<el-cascader
:popper-append-to-body="false"
ref="cascaderUnit"
placeholder="请选择数据指标"
v-model="value"
:options="options2"
filterable
@change="handleChange"
:props="{
value: 'name',
label: 'showName'
}"
></el-cascader>
</el-tab-pane>
<el-tab-pane label="合格率判定" name="2">
绑定合格率判定:
<el-cascader
:popper-append-to-body="false"
ref="cascaderhgl"
placeholder="请选择数据合格率"
v-model="value"
:options="options3"
filterable
@change="handleChange"
:props="{
value: 'name',
label: 'showName'
}"
></el-cascader>
</el-tab-pane>
<el-tab-pane label="监测点台账指标" name="3">
绑定数据指标:
<el-cascader
:popper-append-to-body="false"
ref="cascaderjcd"
placeholder="请选择监测点台账"
v-model="value"
:options="options4"
filterable
@change="handleChange"
:props="{
value: 'name',
label: 'showName'
}"
></el-cascader>
</el-tab-pane>
</el-tabs>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue'
import { codeDicTree } from '@/api/system-boot/dictTree'
import { targetLimitChooseTree, getIndex, terminalChooseTree } from '@/api/harmonic-boot/luckyexcel'
const emit = defineEmits(['setValue'])
const activeName = ref('0')
const value = ref([])
const options1 = ref([])
const options2 = ref([])
const options3 = ref([])
const options4: any = ref([])
const handleChange = (e: any) => {
value.value = []
emit('setValue', e)
}
codeDicTree({ code: 'Device_Unit' }).then(res => {
options1.value = res.data
})
getIndex().then(res => {
options2.value = res.data
})
targetLimitChooseTree().then(res => {
options3.value = res.data
})
terminalChooseTree().then(res => {
options4.value = res.data
})
onMounted(() => {})
</script>
<style lang="scss" scoped>
:deep(.el-tab-pane) {
padding: 10px;
}
</style>

View File

@@ -0,0 +1,102 @@
<template>
<el-dialog draggable v-model="dialogVisible" title="模板绑定" width="500px" :before-close="handleClose">
<el-tree
default-expand-all
show-checkbox
node-key="id"
:data="dataTree"
:expand-on-click-node="false"
ref="tree"
style="height: 440px; overflow-y: auto"
>
<template #default="{ node, data }">
<span class="custom-tree-node">
<span>{{ data.name }}</span>
<span>
<el-switch
v-model="data.activation"
active-value="1"
inactive-value="0"
:active-text="data.activation == 1 ? '激活 ' : '未激活'"
/>
</span>
</span>
</template>
</el-tree>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="bind">绑定</el-button>
<el-button @click="handleClose">取消</el-button>
</div>
</template>
</el-dialog>
</template>
<script lang="ts" setup>
import { ref } from 'vue'
import { ElMessageBox } from 'element-plus'
import { useDictData } from '@/stores/dictData'
import { getDataByTempId, updateBindTemplate } from '@/api/harmonic-boot/luckyexcel'
const emit = defineEmits(['shutDown'])
const dictData = useDictData()
const dialogVisible = ref(false)
const keyarr: any = ref([])
const idarr: any = ref([])
const dataTree: any = ref([])
const area = ref(dictData.state.area)
const handleClose = () => {
dialogVisible.value = false
// emit('handleClose')
}
const open = (row: any) => {
dialogVisible.value = true
getDataByTempId({ id: row.id }).then(res => {
res.data.forEach(item => {
keyarr.value.push({
name: item.deptName,
id: item.deptId,
activation: item.activation
})
idarr.value.push({ id: item.deptId })
})
gettreeData(area.value, keyarr.value)
dataTree.value = area.value
})
}
//过滤数据
const gettreeData = (mdata, ids) => {
mdata.forEach(m => {
ids.forEach(n => {
if (m.id == n.id && n.activation == 1) {
m.activation = 1
} else {
m.activation = 0
}
})
if (m.children != null || m.children.length > 0) {
gettreeData(m.children, ids)
} else {
m.children = null
}
})
}
// 绑定
const bind = () => {
updateBindTemplate().then(res => {
// ElMessage.success('绑定成功')
})
}
defineExpose({ open })
</script>
<style scoped lang="scss">
.custom-tree-node {
flex: 1;
display: flex;
align-items: center;
justify-content: space-between;
font-size: 14px;
padding-right: 8px;
}
</style>

View File

@@ -0,0 +1,349 @@
// import { createCellPos } from './translateNumToLetter'
import Excel from 'exceljs'
import FileSaver from 'file-saver'
const exportExcel = function(luckysheet, value) {
// 参数为luckysheet.getluckysheetfile()获取的对象
// 1.创建工作簿,可以为工作簿添加属性
const workbook = new Excel.Workbook()
// 2.创建表格,第二个参数可以配置创建什么样的工作表
if (Object.prototype.toString.call(luckysheet) === '[object Object]') {
luckysheet = [luckysheet]
}
luckysheet.forEach(function(table) {
if (table.data.length === 0) return true
// ws.getCell('B2').fill = fills.
const worksheet = workbook.addWorksheet(table.name)
const merge = (table.config && table.config.merge) || {}
const borderInfo = (table.config && table.config.borderInfo) || {}
// 3.设置单元格合并,设置单元格边框,设置单元格样式,设置值
setStyleAndValue(table.data, worksheet)
setMerge(merge, worksheet)
setBorder(borderInfo, worksheet)
return true
})
// return
// 4.写入 buffer
const buffer = workbook.xlsx.writeBuffer().then(data => {
// console.log('data', data)
const blob = new Blob([data], {
type: 'application/vnd.ms-excel;charset=utf-8'
})
console.log("导出成功!")
FileSaver.saveAs(blob, `${value}.xlsx`)
})
return buffer
}
var setMerge = function(luckyMerge = {}, worksheet) {
const mergearr = Object.values(luckyMerge)
mergearr.forEach(function(elem) {
// elem格式{r: 0, c: 0, rs: 1, cs: 2}
// 按开始行,开始列,结束行,结束列合并(相当于 K10:M12
worksheet.mergeCells(
elem.r + 1,
elem.c + 1,
elem.r + elem.rs,
elem.c + elem.cs
)
})
}
var setBorder = function(luckyBorderInfo, worksheet) {
if (!Array.isArray(luckyBorderInfo)) return
// console.log('luckyBorderInfo', luckyBorderInfo)
luckyBorderInfo.forEach(function(elem) {
// 现在只兼容到borderType 为range的情况
// console.log('ele', elem)
if (elem.rangeType === 'range') {
let border = borderConvert(elem.borderType, elem.style, elem.color)
let rang = elem.range[0]
// console.log('range', rang)
let row = rang.row
let column = rang.column
for (let i = row[0] + 1; i < row[1] + 2; i++) {
for (let y = column[0] + 1; y < column[1] + 2; y++) {
worksheet.getCell(i, y).border = border
}
}
}
if (elem.rangeType === 'cell') {
// col_index: 2
// row_index: 1
// b: {
// color: '#d0d4e3'
// style: 1
// }
const { col_index, row_index } = elem.value
const borderData = Object.assign({}, elem.value)
delete borderData.col_index
delete borderData.row_index
let border = addborderToCell(borderData, row_index, col_index)
// console.log('bordre', border, borderData)
worksheet.getCell(row_index + 1, col_index + 1).border = border
}
// console.log(rang.column_focus + 1, rang.row_focus + 1)
// worksheet.getCell(rang.row_focus + 1, rang.column_focus + 1).border = border
})
}
var setStyleAndValue = function(cellArr, worksheet) {
if (!Array.isArray(cellArr)) return
cellArr.forEach(function(row, rowid) {
row.every(function(cell, columnid) {
if (!cell) return true
let fill = fillConvert(cell.bg)
let font = fontConvert(
cell.ff,
cell.fc,
cell.bl,
cell.it,
cell.fs,
cell.cl,
cell.ul
)
let alignment = alignmentConvert(cell.vt, cell.ht, cell.tb, cell.tr)
let value = ''
if (cell.f) {
value = { formula: cell.f, result: cell.v }
} else if (!cell.v && cell.ct && cell.ct.s) {
// xls转为xlsx之后内部存在不同的格式都会进到富文本里即值不存在与cell.v而是存在于cell.ct.s之后
// value = cell.ct.s[0].v
cell.ct.s.forEach(arr => {
value += arr.v
})
} else {
value = cell.v
}
// style 填入到_value中可以实现填充色
let letter = createCellPos(columnid)
let target = worksheet.getCell(letter + (rowid + 1))
// console.log('1233', letter + (rowid + 1))
for (const key in fill) {
target.fill = fill
break
}
target.font = font
target.alignment = alignment
target.value = value
return true
})
})
}
var fillConvert = function(bg) {
if (!bg) {
return {}
}
// const bgc = bg.replace('#', '')
let fill = {
type: 'pattern',
pattern: 'solid',
fgColor: { argb: bg.replace('#', '') }
}
return fill
}
var fontConvert = function(
ff = 0,
fc = '#000000',
bl = 0,
it = 0,
fs = 10,
cl = 0,
ul = 0
) {
// luckysheetff(样式), fc(颜色), bl(粗体), it(斜体), fs(大小), cl(删除线), ul(下划线)
const luckyToExcel = {
0: '微软雅黑',
1: '宋体Song',
2: '黑体ST Heiti',
3: '楷体ST Kaiti',
4: '仿宋ST FangSong',
5: '新宋体ST Song',
6: '华文新魏',
7: '华文行楷',
8: '华文隶书',
9: 'Arial',
10: 'Times New Roman ',
11: 'Tahoma ',
12: 'Verdana',
num2bl: function(num) {
return num === 0 ? false : true
}
}
// 出现Bug导入的时候ff为luckyToExcel的val
let font = {
name: typeof ff === 'number' ? luckyToExcel[ff] : ff,
family: 1,
size: fs,
color: { argb: fc.replace('#', '') },
bold: luckyToExcel.num2bl(bl),
italic: luckyToExcel.num2bl(it),
underline: luckyToExcel.num2bl(ul),
strike: luckyToExcel.num2bl(cl)
}
return font
}
var alignmentConvert = function(
vt = 'default',
ht = 'default',
tb = 'default',
tr = 'default'
) {
// luckysheet:vt(垂直), ht(水平), tb(换行), tr(旋转)
const luckyToExcel = {
vertical: {
0: 'middle',
1: 'top',
2: 'bottom',
default: 'top'
},
horizontal: {
0: 'center',
1: 'left',
2: 'right',
default: 'left'
},
wrapText: {
0: false,
1: false,
2: true,
default: false
},
textRotation: {
0: 0,
1: 45,
2: -45,
3: 'vertical',
4: 90,
5: -90,
default: 0
}
}
let alignment = {
vertical: luckyToExcel.vertical[vt],
horizontal: luckyToExcel.horizontal[ht],
wrapText: luckyToExcel.wrapText[tb],
textRotation: luckyToExcel.textRotation[tr]
}
return alignment
}
var borderConvert = function(borderType, style = 1, color = '#000') {
// 对应luckysheet的config中borderinfo的的参数
if (!borderType) {
return {}
}
const luckyToExcel = {
type: {
'border-all': 'all',
'border-top': 'top',
'border-right': 'right',
'border-bottom': 'bottom',
'border-left': 'left'
},
style: {
0: 'none',
1: 'thin',
2: 'hair',
3: 'dotted',
4: 'dashDot', // 'Dashed',
5: 'dashDot',
6: 'dashDotDot',
7: 'double',
8: 'medium',
9: 'mediumDashed',
10: 'mediumDashDot',
11: 'mediumDashDotDot',
12: 'slantDashDot',
13: 'thick'
}
}
let template = {
style: luckyToExcel.style[style],
color: { argb: color.replace('#', '') }
}
let border = {}
if (luckyToExcel.type[borderType] === 'all') {
border['top'] = template
border['right'] = template
border['bottom'] = template
border['left'] = template
} else {
border[luckyToExcel.type[borderType]] = template
}
// console.log('border', border)
return border
}
function addborderToCell(borders, row_index, col_index) {
let border = {}
const luckyExcel = {
type: {
l: 'left',
r: 'right',
b: 'bottom',
t: 'top'
},
style: {
0: 'none',
1: 'thin',
2: 'hair',
3: 'dotted',
4: 'dashDot', // 'Dashed',
5: 'dashDot',
6: 'dashDotDot',
7: 'double',
8: 'medium',
9: 'mediumDashed',
10: 'mediumDashDot',
11: 'mediumDashDotDot',
12: 'slantDashDot',
13: 'thick'
}
}
// console.log('borders', borders)
for (const bor in borders) {
// console.log(bor)
if (borders[bor].color.indexOf('rgb') === -1) {
border[luckyExcel.type[bor]] = {
style: luckyExcel.style[borders[bor].style],
color: { argb: borders[bor].color.replace('#', '') }
}
} else {
border[luckyExcel.type[bor]] = {
style: luckyExcel.style[borders[bor].style],
color: { argb: borders[bor].color }
}
}
}
return border
}
function createCellPos(n) {
let ordA = 'A'.charCodeAt(0)
let ordZ = 'Z'.charCodeAt(0)
let len = ordZ - ordA + 1
let s = ''
while (n >= 0) {
s = String.fromCharCode((n % len) + ordA) + s
n = Math.floor(n / len) - 1
}
return s
}
export {
exportExcel
}

View File

@@ -0,0 +1,115 @@
<template>
<el-dialog draggable :title="title" v-model="formVisible" width="30%" :before-close="closeDialog">
<el-form :model="formdata" label-width="100px" :rules="rules" ref="ruleForm">
<el-form-item label="模板名称:" prop="name">
<el-input placeholder="模板名称" v-model="formdata.name" style="width: 100%"></el-input>
</el-form-item>
<el-form-item label="部门:" prop="deptId">
<Area
v-model="formdata.deptId"
style="width: 100%"
collapse-tags
:props="{ multiple: true, label: 'name', value: 'id', emitPath: false }"
/>
</el-form-item>
<el-form-item label="模板类型:" prop="reportType">
<el-select style="width: 100%" v-model="formdata.reportType" placeholder="请选择模板类型">
<el-option
v-for="item in classificationData"
:key="item.id"
:label="item.label"
:value="item.id"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="报表类型:" prop="reportForm">
<el-select style="width: 100%" v-model="formdata.reportForm" placeholder="请选择报表类型">
<el-option
v-for="item in reportFormList"
:key="item.value"
:label="item.label"
:value="item.value"
></el-option>
</el-select>
</el-form-item>
</el-form>
<template #footer>
<el-button @click="closeDialog"> </el-button>
<el-button type="primary" @click="preservation"> </el-button>
</template>
</el-dialog>
</template>
<script setup lang="ts">
import Area from '@/components/form/area/index.vue'
import { getCustomReportTemplateById } from '@/api/harmonic-boot/luckyexcel'
import { ref, reactive } from 'vue'
const emit = defineEmits(['submitForm'])
const title = ref('')
const list = ref({})
const ruleForm = ref()
const formVisible = ref(false)
const classificationData = [
{
label: '电能质量报表类型',
id: '1'
},
{
label: '用能报表类型',
id: '2'
}
]
const reportFormList = [
{
value: '1',
label: '分析报表'
},
{
value: '2',
label: '统计报表'
},
{
value: '3',
label: '自定义报表'
}
]
const rules = {
name: [{ required: true, message: '请输入模板名称', trigger: 'blur' }],
deptId: [{ required: true, message: '请选择部门', trigger: 'change' }],
reportType: [{ required: true, message: '请选择模板类型', trigger: 'change' }],
reportForm: [{ required: true, message: '请选择报表类型', trigger: 'change' }]
}
const formdata = ref({
name: '',
deptId: [],
reportType: '',
reportForm: ''
})
// 确定
const preservation = () => {
ruleForm.value.validate((valid: boolean) => {
if (valid) {
emit('submitForm', formdata.value, title.value)
formVisible.value = false
}
})
}
// 关闭
const closeDialog = () => {
formVisible.value = false
}
const open = (text: string, row?: any) => {
title.value = text
if (row.id) {
getCustomReportTemplateById({ id: row.id }).then(res => {
formdata.value = res.data
formdata.value.deptId = res.data.valueTitle.split(',')
})
}
formVisible.value = true
}
defineExpose({ open })
</script>
<style lang="scss" scoped></style>

View File

@@ -0,0 +1,133 @@
<template>
<div class="default-main">
<div v-show="show && lookShow">
<TableHeader ref="TableHeaderRef">
<template #operation>
<el-button icon="el-icon-Plus" type="primary" @click="add">新增</el-button>
</template>
</TableHeader>
<Table ref="tableRef" />
</div>
<luckysheet ref="luckysheetRef" v-if="!show" @shutDown="shutDown" />
<!-- 查看 -->
<look ref="lookRef" v-if="!lookShow" @shutDown="shutDown" />
<!-- 绑定 -->
<department ref="departmentRef" />
</div>
</template>
<script setup lang="ts">
import { ref, onMounted, provide, nextTick } from 'vue'
import TableStore from '@/utils/tableStore'
import Table from '@/components/table/index.vue'
import TableHeader from '@/components/table/header/index.vue'
import { delTemplate } from '@/api/harmonic-boot/luckyexcel'
import { useDictData } from '@/stores/dictData'
import { ElMessage } from 'element-plus'
import luckysheet from './luckysheet.vue'
import look from './look.vue'
import department from './department.vue'
defineOptions({
name: 'Distributedphotovoltaic/templateConfiguration'
})
const luckysheetRef = ref()
const lookRef = ref()
const departmentRef = ref()
const show = ref(true)
const lookShow = ref(true)
const tableStore: any = new TableStore({
url: '/harmonic-boot/customReport/getTemplateList',
method: 'POST',
isWebPaging: true,
column: [
{ field: 'name', title: '模板名称' },
{ field: 'createBy', title: '创建用户' },
{ field: 'updateBy', title: '更新用户' },
{ field: 'createTime', title: '创建时间' },
{ field: 'updateTime', title: '更新时间' },
{
title: '操作',
width: '220',
render: 'buttons',
buttons: [
{
name: 'edit',
title: '查看 ',
type: 'primary',
icon: 'el-icon-Plus',
render: 'basicButton',
click: row => {
lookShow.value = false
setTimeout(() => {
lookRef.value.open(row)
}, 10)
}
},
{
name: 'edit',
title: '编辑',
type: 'primary',
icon: 'el-icon-Plus',
render: 'basicButton',
click: row => {
show.value = false
setTimeout(() => {
luckysheetRef.value.open('编辑报表模板', row)
}, 10)
}
},
// {
// name: 'edit',
// title: '绑定',
// type: 'primary',
// icon: 'el-icon-Plus',
// render: 'basicButton',
// click: row => {
// departmentRef.value.open(row)
// }
// },
{
name: 'del',
text: '删除',
type: 'danger',
icon: 'el-icon-Delete',
render: 'confirmButton',
popconfirm: {
confirmButtonText: '确认',
cancelButtonText: '取消',
confirmButtonType: 'danger',
title: '确定删除?'
},
click: row => {
delTemplate({ tempId: row.id, deptId: row.deptId }).then(res => {
ElMessage.success('删除成功')
tableStore.index()
})
}
}
]
}
],
loadCallback: () => {}
})
tableStore.table.params = {}
tableStore.table.params.pageSize = 20
tableStore.table.params.pageNum = 1
provide('tableStore', tableStore)
// 关闭
const shutDown = () => {
show.value = true
lookShow.value = true
tableStore.index()
}
const add = () => {
show.value = false
setTimeout(() => {
luckysheetRef.value.open('新增报表模板')
}, 10)
}
onMounted(() => {
tableStore.index()
})
</script>

View File

@@ -0,0 +1,105 @@
<template>
<div class="default-main">
<div class="mb10" style="display: flex; justify-content: flex-end">
<el-upload
ref="upload"
action=""
:auto-upload="false"
:show-file-list="false"
:limit="1"
:on-change="beforeUpload"
>
<el-button icon="el-icon-Upload" type="primary" class="mr10">导入excel</el-button>
</el-upload>
<el-button @click="downloadExcel" class="" type="primary" icon="el-icon-Download">导出excel</el-button>
<el-button type="primary" icon="el-icon-ArrowLeftBold" @click="emit('shutDown')">返回</el-button>
</div>
<div style="display: flex">
<div id="luckysheet" :style="{ height: height, flex: 1 }"></div>
</div>
</div>
</template>
<script setup lang="ts">
import { exportExcel } from './export.js'
import { mainHeight } from '@/utils/layout'
import LuckyExcel from 'luckyexcel'
import { ref, onMounted } from 'vue'
import { ElMessage } from 'element-plus'
import { viewCustomReportTemplateById } from '@/api/harmonic-boot/luckyexcel'
const emit = defineEmits(['shutDown'])
const height = mainHeight(65).height
const options: any = ref({
container: 'luckysheet',
title: '', // 表 头名
lang: 'zh', // 中文
showtoolbar: false, // 是否显示工具栏
showinfobar: false, // 是否显示顶部信息栏
showsheetbar: true, // 是否显示底部sheet按钮
data: [
{
name: 'Cell',
index: 0,
defaultRowHeight: 27,
defaultColWidth: 105,
chart: [] //图表配置
}
]
})
// 加载luckysheet
const info = () => {
luckysheet.create(options.value)
}
//绑定value
const setValue = (e: any) => {
let data = luckysheet.getRange()
luckysheet.setCellValue(
data[0].row[0],
data[0].column[0],
{
v: e[e.length - 1],
tr: e
}
// checkedNodes[0].data.label
)
}
// 下载表格
const downloadExcel = () => {
exportExcel(luckysheet.getAllSheets(), '报表模板')
}
// 导入
const beforeUpload = (file: any) => {
LuckyExcel.transformExcelToLucky(file.raw, function (exportJson: any) {
if (exportJson.sheets == null || exportJson.sheets.length == 0) {
ElMessage.warning('读取excel文件内容失败,目前只能上传xlsx文件!')
return
}
luckysheet.destroy()
options.value.title = exportJson.info.name
options.value.data = exportJson.sheets
luckysheet.create(options.value)
})
}
const open = async (row: any) => {
await viewCustomReportTemplateById({ id: row.id }).then((Response:any) => {
Response.forEach((item: any) => {
item.celldata.forEach((k: any) => {
item.data[k.r][k.c].v = k.v
})
})
options.value.data = Response
})
info()
}
defineExpose({ open })
onMounted(() => {})
</script>
<style lang="scss" scoped>
:deep(.el-tab-pane) {
padding: 10px;
}
</style>

View File

@@ -0,0 +1,144 @@
<template>
<div class="default-main">
<div class="mb10" style="display: flex; justify-content: flex-end">
<el-upload
ref="upload"
action=""
:auto-upload="false"
:show-file-list="false"
:limit="1"
:on-change="beforeUpload"
>
<el-button icon="el-icon-Upload" type="primary" class="mr10">导入excel</el-button>
</el-upload>
<el-button @click="downloadExcel" class="" type="primary" icon="el-icon-Download">导出excel</el-button>
<el-button type="primary" icon="el-icon-Check" @click="preservation">保存</el-button>
<el-button type="primary" icon="el-icon-ArrowLeftBold" @click="emit('shutDown')">返回</el-button>
</div>
<div style="display: flex">
<div id="luckysheet" :style="{ height: height, flex: 1 }"></div>
<bind style="width: 500px" class="ml10" @setValue="setValue" />
</div>
<!-- 信息框 -->
<addForm ref="formFer" @submitForm="submitForm" />
</div>
</template>
<script setup lang="ts">
import { exportExcel } from './export.js'
import { mainHeight } from '@/utils/layout'
import LuckyExcel from 'luckyexcel'
import { ref, onMounted } from 'vue'
import { ElMessage } from 'element-plus'
import { addTemplate, dateTemplateup, viewCustomReportTemplateById } from '@/api/harmonic-boot/luckyexcel'
import bind from './bind.vue'
import addForm from './form.vue'
const emit = defineEmits(['shutDown'])
const formFer = ref()
const title = ref('')
const list = ref({})
const height = mainHeight(65).height
const options: any = ref({
container: 'luckysheet',
title: '', // 表 头名
lang: 'zh', // 中文
showtoolbar: true, // 是否显示工具栏
showinfobar: false, // 是否显示顶部信息栏
showsheetbar: true, // 是否显示底部sheet按钮
data: [
{
name: 'Cell',
index: 0,
defaultRowHeight: 27,
defaultColWidth: 105,
chart: [] //图表配置
}
]
})
// 加载luckysheet
const info = () => {
luckysheet.create(options.value)
}
//绑定value
const setValue = (e: any) => {
let data = luckysheet.getRange()
luckysheet.setCellValue(
data[0].row[0],
data[0].column[0],
{
v: e[e.length - 1],
tr: e
}
// checkedNodes[0].data.label
)
}
// 下载表格
const downloadExcel = () => {
exportExcel(luckysheet.getAllSheets(), '报表模板')
}
// 导入
const beforeUpload = (file: any) => {
LuckyExcel.transformExcelToLucky(file.raw, function (exportJson: any) {
if (exportJson.sheets == null || exportJson.sheets.length == 0) {
ElMessage.warning('读取excel文件内容失败,目前只能上传xlsx文件!')
return
}
luckysheet.destroy()
options.value.title = exportJson.info.name
options.value.data = exportJson.sheets
luckysheet.create(options.value)
})
}
// 保存
const preservation = () => {
formFer.value.open(title.value, list.value)
}
// 新增
const submitForm = (formdata: any, text: string) => {
console.log('🚀 ~ submitForm ~ text:', text)
let userStr = JSON.stringify(luckysheet.getAllSheets())
let blob = new Blob([userStr], {
type: 'application/json;charset=UTF-8'
})
let files = new window.File([blob], 'content.json', {
type: 'application/json;charset=UTF-8'
})
let params = new FormData()
params.append('fileContent', files)
params.append('deptId', formdata.deptId)
params.append('valueTitle', formdata.deptId)
params.append('name', formdata.name)
params.append('reportType', formdata.reportType)
params.append('reportForm', formdata.reportForm)
if (text == '新增报表模板') {
addTemplate(params).then(res => {
ElMessage.success('新增成功!')
emit('shutDown')
})
} else if (text == '编辑报表模板') {
params.append('id', list.value.id)
dateTemplateup(params).then(res => {
ElMessage.success('编辑成功!')
emit('shutDown')
})
}
}
const open = async (text: string, row?: any) => {
title.value = text
if (row) {
list.value = row
await viewCustomReportTemplateById({ id: row.id }).then(Response => {
options.value.data = Response
})
}
info()
}
defineExpose({ open })
onMounted(() => {})
</script>
<style lang="scss" scoped>
:deep(.el-tab-pane) {
padding: 10px;
}
</style>