联调 自定义报表

This commit is contained in:
GGJ
2024-03-27 20:29:51 +08:00
parent 668fbed3ef
commit 45ba496361
19 changed files with 1228 additions and 32 deletions

View File

@@ -8,12 +8,12 @@
</head> </head>
<!-- 在这里全局引入luckysheet的样式文件和js文件 --> <!-- 在这里全局引入luckysheet的样式文件和js文件 -->
<link rel="stylesheet" href="/public/assets/luckysheet/pluginsCss.css" /> <link rel="stylesheet" href="/static/luckysheet/pluginsCss.css" />
<link rel="stylesheet" href="/public/assets/luckysheet/plugins.css" /> <link rel="stylesheet" href="/static/luckysheet/plugins.css" />
<link rel="stylesheet" href="/public/assets/luckysheet/luckysheet.css" /> <link rel="stylesheet" href="/static/luckysheet/luckysheet.css" />
<link rel="stylesheet" href="/public/assets/luckysheet/iconfont.css" /> <link rel="stylesheet" href="/static/luckysheet/iconfont.css" />
<script src="/public/assets/luckysheet/plugin.js"></script> <script src="/static/luckysheet/plugin.js"></script>
<script src="/public/assets/luckysheet/luckysheet.umd.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

@@ -0,0 +1,166 @@
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) {
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) {
return createAxios({
url: '/harmonic-boot/customReport/getCustomReport',
method: 'post',
resposeType: 'blob',
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

@@ -54,10 +54,18 @@ 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

@@ -21,9 +21,9 @@ const dictData = useDictData()
const options = dictData.state.area const options = dictData.state.area
const areaName = ref(dictData.state.area[0].name) const areaName = ref(dictData.state.area[0].name)
const change = (e: any) => { const change = (e: any) => {
if (cascader.value.getCheckedNodes()[0].pathLabels.length == 1) { if (cascader.value.getCheckedNodes()[0]?.pathLabels.length == 1) {
areaName.value = cascader.value.getCheckedNodes()[0].pathLabels[0] areaName.value = cascader.value.getCheckedNodes()[0].pathLabels[0]
} else if (cascader.value.getCheckedNodes()[0].pathLabels.length >= 2) { } else if (cascader.value.getCheckedNodes()[0]?.pathLabels.length >= 2) {
areaName.value = cascader.value.getCheckedNodes()[0].pathLabels[1] areaName.value = cascader.value.getCheckedNodes()[0].pathLabels[1]
} }
} }

View File

@@ -23,7 +23,9 @@ export const useDictData = defineStore(
return list return list
} }
const areaSelect = () => { const areaSelect = () => {
return state.areaTree.filter(item => item.id == state.area[0]?.area) let list = state.areaTree.filter(item => item.id == state.area[0]?.area)
return list.length == 0 ? state.areaTree : list
} }
return { return {

View File

@@ -93,6 +93,7 @@ function createAxios<Data = any, T = ApiPromise<Data>>(
options.loading && closeLoading(options) // 关闭loading options.loading && closeLoading(options) // 关闭loading
if ( if (
Array.isArray(response.data) ||
response.data.code === 'A0000' || response.data.code === 'A0000' ||
response.data.type === 'application/json' || response.data.type === 'application/json' ||
response.data.type === 'application/octet-stream' || response.data.type === 'application/octet-stream' ||

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,98 @@
<template>
<el-dialog 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="handleClose">绑定</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 } 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
})
console.log('🚀 ~ getDataByTempId ~ item.activation:', item.activation)
idarr.value.push({ id: item.deptId })
})
gettreeData(area.value, keyarr.value)
dataTree.value = area.value
console.log('🚀 ~ getDataByTempId ~ dataTree.value:', dataTree.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
}
})
}
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,116 @@
<template>
<el-dialog :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
:disabled="title === '编辑报表模板'"
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

@@ -1,29 +1,133 @@
<template> <template>
<div class="default-main"> <div class="default-main">
<div id="luckysheet" :style="{ height: height }"></div> <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> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import LuckyExcel from 'luckyexcel' import { ref, onMounted, provide, nextTick } from 'vue'
import { exportExcel } from './export.js' import TableStore from '@/utils/tableStore'
import { mainHeight } from '@/utils/layout' import Table from '@/components/table/index.vue'
import { ref, onMounted } from '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({ defineOptions({
name: 'Distributedphotovoltaic/templateConfiguration' name: 'estimate/photovoltaic'
}) })
const height = mainHeight(20).height const luckysheetRef = ref()
const options = ref({ const lookRef = ref()
container: 'luckysheet', const departmentRef = ref()
title: '测试Excel', // 表 头名 const show = ref(true)
lang: 'zh', // 中文 const lookShow = ref(true)
showtoolbar: true, // 是否显示工具栏 const tableStore: any = new TableStore({
showinfobar: false, // 是否显示顶部信息栏 url: '/harmonic-boot/customReport/getTemplateList',
showsheetbar: true // 是否显示底部sheet按钮 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()
}) })
// LuckyExcel.destroy() }
}
]
}
],
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(() => { onMounted(() => {
luckysheet.create(options.value) tableStore.index()
}) })
</script> </script>
<style lang="scss" scoped></style>

View File

@@ -0,0 +1,100 @@
<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-Close" @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: 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 open = async (row: any) => {
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>

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-Close" @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>