74 changed files with 1745 additions and 3242 deletions
File diff suppressed because one or more lines are too long
@ -0,0 +1,20 @@ |
|||||
|
package io.sc.platform.core.constraints; |
||||
|
|
||||
|
import io.sc.platform.core.constraints.validator.IdentifierConstraintValidator; |
||||
|
|
||||
|
import javax.validation.Constraint; |
||||
|
import javax.validation.Payload; |
||||
|
import java.lang.annotation.*; |
||||
|
|
||||
|
/** |
||||
|
* 约束限制(代码) |
||||
|
*/ |
||||
|
@Documented |
||||
|
@Target({ElementType.METHOD, ElementType.FIELD}) |
||||
|
@Retention(RetentionPolicy.RUNTIME) |
||||
|
@Constraint(validatedBy= IdentifierConstraintValidator.class) |
||||
|
public @interface IdentifierConstraint { |
||||
|
String message() default "{io.sc.platform.core.constraints.IdentifierConstraint.message}"; |
||||
|
Class<?>[] groups() default { }; |
||||
|
Class<? extends Payload>[] payload() default { }; |
||||
|
} |
@ -0,0 +1,40 @@ |
|||||
|
package io.sc.platform.core.constraints.validator; |
||||
|
|
||||
|
import io.sc.platform.core.constraints.IdentifierConstraint; |
||||
|
import org.springframework.util.StringUtils; |
||||
|
|
||||
|
import javax.validation.ConstraintValidator; |
||||
|
import javax.validation.ConstraintValidatorContext; |
||||
|
import java.util.regex.Matcher; |
||||
|
import java.util.regex.Pattern; |
||||
|
|
||||
|
/** |
||||
|
* 代码限制验证器 |
||||
|
*/ |
||||
|
public class IdentifierConstraintValidator implements ConstraintValidator<IdentifierConstraint, String> { |
||||
|
// 标识符: 字母、数字和下划线,且首字符必须为字母
|
||||
|
private static final Pattern pattern =Pattern.compile("[A-Za-z][A-Za-z0-9_]*"); |
||||
|
private IdentifierConstraint constraintAnnotation; |
||||
|
|
||||
|
@Override |
||||
|
public void initialize(IdentifierConstraint constraintAnnotation) { |
||||
|
this.constraintAnnotation =constraintAnnotation; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public boolean isValid(String value, ConstraintValidatorContext context) { |
||||
|
if(!StringUtils.hasText(value)) { return true; } |
||||
|
Matcher matcher = pattern.matcher(value); |
||||
|
if(matcher.find()) { |
||||
|
int start =matcher.start(); |
||||
|
int end =matcher.end(); |
||||
|
if(start==0 && end==value.length()){ |
||||
|
return true; |
||||
|
}else{ |
||||
|
return false; |
||||
|
} |
||||
|
}else{ |
||||
|
return false; |
||||
|
} |
||||
|
} |
||||
|
} |
@ -1,21 +0,0 @@ |
|||||
package io.sc.platform.core.validation; |
|
||||
|
|
||||
import io.sc.platform.core.validation.annotation.Code; |
|
||||
|
|
||||
import javax.validation.ConstraintValidator; |
|
||||
import javax.validation.ConstraintValidatorContext; |
|
||||
|
|
||||
public class CodeValidator implements ConstraintValidator<Code, String> { |
|
||||
@Override |
|
||||
public void initialize(Code constraintAnnotation) { |
|
||||
ConstraintValidator.super.initialize(constraintAnnotation); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public boolean isValid(String value, ConstraintValidatorContext context) { |
|
||||
System.out.println(">>>>>>>>" + value); |
|
||||
return false; |
|
||||
} |
|
||||
|
|
||||
|
|
||||
} |
|
@ -1,43 +0,0 @@ |
|||||
package io.sc.platform.core.validation.annotation; |
|
||||
|
|
||||
import io.sc.platform.core.validation.CodeValidator; |
|
||||
|
|
||||
import javax.validation.Constraint; |
|
||||
import javax.validation.Payload; |
|
||||
import javax.validation.constraints.Pattern; |
|
||||
import java.lang.annotation.Documented; |
|
||||
import java.lang.annotation.Repeatable; |
|
||||
import java.lang.annotation.Retention; |
|
||||
import java.lang.annotation.Target; |
|
||||
|
|
||||
import static java.lang.annotation.ElementType.*; |
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME; |
|
||||
|
|
||||
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE }) |
|
||||
@Retention(RUNTIME) |
|
||||
@Repeatable(Code.List.class) |
|
||||
@Documented |
|
||||
@Constraint(validatedBy= CodeValidator.class) |
|
||||
public @interface Code { |
|
||||
/** |
|
||||
* @return the error message template |
|
||||
*/ |
|
||||
String message() default "{javax.validation.constraints.Pattern.message}"; |
|
||||
|
|
||||
/** |
|
||||
* @return the groups the constraint belongs to |
|
||||
*/ |
|
||||
Class<?>[] groups() default { }; |
|
||||
|
|
||||
/** |
|
||||
* @return the payload associated to the constraint |
|
||||
*/ |
|
||||
Class<? extends Payload>[] payload() default { }; |
|
||||
|
|
||||
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE }) |
|
||||
@Retention(RUNTIME) |
|
||||
@Documented |
|
||||
@interface List { |
|
||||
Code[] value(); |
|
||||
} |
|
||||
} |
|
@ -0,0 +1 @@ |
|||||
|
io.sc.platform.core.constraints.IdentifierConstraint.message=Contains only letters, numbers, or underscores, Note: The first character must be a letter. |
@ -0,0 +1 @@ |
|||||
|
io.sc.platform.core.constraints.IdentifierConstraint.message=\u50C5\u5305\u542B\u5B57\u6BCD\u3001\u6578\u5B57\u6216\u4E0B\u5283\u7DDA, \u6CE8\u610F: \u9996\u5B57\u6BCD\u5FC5\u9808\u70BA\u5B57\u6BCD\u3002 |
@ -0,0 +1 @@ |
|||||
|
io.sc.platform.core.constraints.IdentifierConstraint.message=\u4EC5\u5305\u542B\u5B57\u6BCD\u3001\u6570\u5B57\u6216\u4E0B\u5212\u7EBF, \u6CE8\u610F: \u9996\u5B57\u7B26\u5FC5\u987B\u4E3A\u5B57\u6BCD\u3002 |
@ -1,11 +0,0 @@ |
|||||
<template> |
|
||||
<div> |
|
||||
<LuckySheet></LuckySheet> |
|
||||
</div> |
|
||||
</template> |
|
||||
|
|
||||
<script setup lang="ts"> |
|
||||
import LuckySheet from './luckysheet/LuckySheet.vue'; |
|
||||
</script> |
|
||||
|
|
||||
<style scoped></style> |
|
@ -1,358 +0,0 @@ |
|||||
<template> |
|
||||
<w-dialog ref="dialogRef" :title="state.dialogTitle" :maximized="true" :buttons="dialog.buttons" body-padding="0px 0px 0px 0px"> |
|
||||
<div class="flex justify-end gap-2 p-1.5"> |
|
||||
<q-file v-model="impFile" label="导入Excel文件" input-class="w-[400px]" filled dense accept=".xlsx,.xls" @update:model-value="loadExcel($event)"> |
|
||||
<template #append> |
|
||||
<q-icon name="attachment" /> |
|
||||
</template> |
|
||||
</q-file> |
|
||||
<div class="flex flex-none"> |
|
||||
<q-btn label="选取变量" :icon="PlatformIconEnum.选取变量" @click="selectParams"></q-btn> |
|
||||
</div> |
|
||||
<div class="flex flex-none"> |
|
||||
<q-btn-dropdown :icon="PlatformIconEnum.设置" label="循环属性配置" unelevated outline> |
|
||||
<q-list> |
|
||||
<q-item v-close-popup clickable> |
|
||||
<q-item-section> |
|
||||
<q-item-label @click="openConfigDialog('main')"><q-icon :name="PlatformIconEnum.更多查询"></q-icon> 整体配置(首列)</q-item-label> |
|
||||
</q-item-section> |
|
||||
</q-item> |
|
||||
<q-item v-close-popup clickable> |
|
||||
<q-item-section> |
|
||||
<q-item-label @click="openConfigDialog('column')"><q-icon :name="PlatformIconEnum.更多查询"></q-icon> 列配置(非首列)</q-item-label> |
|
||||
</q-item-section> |
|
||||
</q-item> |
|
||||
</q-list> |
|
||||
</q-btn-dropdown> |
|
||||
</div> |
|
||||
<TemplateParamsSelectDialog ref="paramsSelectDialogRef" @set-params="setParams"></TemplateParamsSelectDialog> |
|
||||
<TemplateSetForeachPropsDialog ref="setForeachPropsDialogRef" @set-for-each-params="setForEachParams"></TemplateSetForeachPropsDialog> |
|
||||
<TemplateSetColumnParamsDialog ref="setColumnParamsDialogRef" @set-for-each-params="setForEachParams"></TemplateSetColumnParamsDialog> |
|
||||
</div> |
|
||||
<div id="luckysheet"></div> |
|
||||
</w-dialog> |
|
||||
</template> |
|
||||
|
|
||||
<script setup lang="ts"> |
|
||||
import { ref, reactive, nextTick, onBeforeMount } from 'vue'; |
|
||||
import LuckyExcel from 'luckyexcel'; |
|
||||
import { exportExcel } from './luckysheet/export'; |
|
||||
import { useQuasar } from 'quasar'; |
|
||||
import { axios, Environment, NotifyManager, PlatformIconEnum, Tools } from 'platform-core'; |
|
||||
|
|
||||
import TemplateParamsSelectDialog from './TemplateParamsSelectDialog.vue'; |
|
||||
import TemplateSetForeachPropsDialog from './TemplateSetForeachPropsDialog.vue'; |
|
||||
import TemplateSetColumnParamsDialog from './TemplateSetColumnParamsDialog.vue'; |
|
||||
|
|
||||
const $q = useQuasar(); |
|
||||
|
|
||||
const dialogRef = ref(); |
|
||||
const state = reactive({ |
|
||||
dialogTitle: '模板制定', |
|
||||
dataId: '', |
|
||||
}); |
|
||||
const dialog = { |
|
||||
buttons: [ |
|
||||
{ |
|
||||
icon: PlatformIconEnum.保存, |
|
||||
label: '保存', |
|
||||
click: () => { |
|
||||
save(); |
|
||||
}, |
|
||||
}, |
|
||||
], |
|
||||
}; |
|
||||
|
|
||||
const show = async (tableSelectedRow: any) => { |
|
||||
state.dialogTitle = '模板制定——' + tableSelectedRow.templateName + '(' + tableSelectedRow.templateCode + ')'; |
|
||||
state.dataId = tableSelectedRow.id; |
|
||||
dialogRef.value.show(); |
|
||||
nextTick(async () => { |
|
||||
if (window.luckysheet) { |
|
||||
window.luckysheet.destroy(); |
|
||||
} |
|
||||
const resp = await axios.get(Environment.apiContextPath('api/excel/template/') + state.dataId); |
|
||||
if (resp?.data?.templateConfig) { |
|
||||
luckysheetOptions.data = [eval('(' + resp.data.templateConfig + ')')]; |
|
||||
} |
|
||||
// eslint-disable-next-line |
|
||||
luckysheet.create(luckysheetOptions); |
|
||||
}); |
|
||||
}; |
|
||||
const hide = () => { |
|
||||
dialogRef.value.hide(); |
|
||||
}; |
|
||||
|
|
||||
const impFile = ref(null); |
|
||||
const paramsSelectDialogRef = ref(); |
|
||||
const setForeachPropsDialogRef = ref(); |
|
||||
const setColumnParamsDialogRef = ref(); |
|
||||
|
|
||||
const loadExcel = (value) => { |
|
||||
const { name } = value; |
|
||||
const suffixArr = name.split('.'); |
|
||||
const suffix = suffixArr[suffixArr.length - 1]; |
|
||||
if (suffix !== 'xlsx') { |
|
||||
NotifyManager.warn('只能导入 .xlsx 格式的Excel文件'); |
|
||||
return; |
|
||||
} |
|
||||
LuckyExcel.transformExcelToLucky(value, (exportJson) => { |
|
||||
if (exportJson.sheets === null || exportJson.sheets.length === 0) { |
|
||||
NotifyManager.warn('导入的Excel为空文件'); |
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
window.luckysheet.destroy(); |
|
||||
|
|
||||
const data = [ |
|
||||
{ |
|
||||
...exportJson.sheets[0], |
|
||||
...{ |
|
||||
column: 26, |
|
||||
row: 30, |
|
||||
}, |
|
||||
}, |
|
||||
]; |
|
||||
luckysheetOptions.data = data; |
|
||||
window.luckysheet.create({ |
|
||||
lang: 'zh', |
|
||||
container: 'luckysheet', |
|
||||
showinfobar: false, |
|
||||
showtoolbar: true, // 是否显示工具栏,设置字体,边框,插入这些工具按钮。 |
|
||||
sheetFormulaBar: true, // 是否显示公式栏 |
|
||||
showsheetbar: false, // 是否显示底部sheet页按钮 |
|
||||
data: data, |
|
||||
title: exportJson.info.name, |
|
||||
userInfo: exportJson.info.name.creator, |
|
||||
}); |
|
||||
}); |
|
||||
}; |
|
||||
|
|
||||
const downloadExcel = () => { |
|
||||
// eslint-disable-next-line |
|
||||
exportExcel(luckysheet.getAllSheets(), '下载'); |
|
||||
}; |
|
||||
|
|
||||
const luckysheetData = [ |
|
||||
{ |
|
||||
name: 'Cell', // 工作表名称 |
|
||||
color: '', // 工作表颜色 |
|
||||
index: 0, // 工作表索引 |
|
||||
status: 1, // 激活状态 |
|
||||
order: 0, // 工作表的下标 |
|
||||
hide: 0, // 是否隐藏 |
|
||||
defaultRowHeight: 19, // 自定义行高 |
|
||||
defaultColWidth: 73, // 自定义列宽 |
|
||||
column: 26, |
|
||||
row: 30, |
|
||||
celldata: [], // 初始化使用的单元格数据 |
|
||||
config: { |
|
||||
merge: {}, // 合并单元格 |
|
||||
rowlen: {}, // 表格行高 |
|
||||
columnlen: {}, // 表格列宽 |
|
||||
rowhidden: {}, // 隐藏行 |
|
||||
colhidden: {}, // 隐藏列 |
|
||||
borderInfo: [], // 边框 |
|
||||
authority: {}, // 工作表保护 |
|
||||
}, |
|
||||
scrollLeft: 0, // 左右滚动条位置 |
|
||||
scrollTop: 0, // 上下滚动条位置 |
|
||||
luckysheet_select_save: [], // 选中的区域 |
|
||||
calcChain: [], // 公式链 |
|
||||
isPivotTable: false, // 是否数据透视表 |
|
||||
pivotTable: {}, // 数据透视表设置 |
|
||||
filter_select: {}, // 筛选范围 |
|
||||
filter: null, // 筛选配置 |
|
||||
luckysheet_alternateformat_save: [], // 交替颜色 |
|
||||
luckysheet_alternateformat_save_modelCustom: [], // 自定义交替颜色 |
|
||||
luckysheet_conditionformat_save: {}, // 条件格式 |
|
||||
frozen: {}, // 冻结行列配置 |
|
||||
chart: [], // 图表配置 |
|
||||
zoomRatio: 1, // 缩放比例 |
|
||||
image: [], // 图片 |
|
||||
showGridLines: 1, // 是否显示网格线 |
|
||||
dataVerification: {}, // 数据验证配置 |
|
||||
}, |
|
||||
]; |
|
||||
const luckysheetOptions = { |
|
||||
container: 'luckysheet', // 设定DOM容器的id |
|
||||
lang: 'zh', // 设定表格语言 |
|
||||
title: '测试', // 设定表格名称 |
|
||||
allowEdit: true, // 是否允许编辑 |
|
||||
rowHeaderWidth: 46, // 行标题区域的宽度,如果设置为0,则表示隐藏行标题,也就是表格第一行,A,B,C这行,默认值46 |
|
||||
columnHeaderHeight: 20, // 列标题区域的高度,如果设置为0,则表示隐藏列标题,也就是序号这一行,默认值20 |
|
||||
showtoolbar: true, // 是否显示工具栏,设置字体,边框,插入这些工具按钮。 |
|
||||
showinfobar: false, // 是否显示顶部信息栏,luckysheet的logo,表格名称这一栏。 |
|
||||
userInfo: 'likunming', // 右上角用户信息,若需要展示,必须配合showinfobar使用 |
|
||||
sheetFormulaBar: true, // 是否显示公式栏 |
|
||||
defaultFontSize: 11, // 初始化默认字体大小,默认11 |
|
||||
showsheetbar: false, // 是否显示底部sheet页按钮 |
|
||||
data: luckysheetData, // 表格数据 |
|
||||
}; |
|
||||
const selectParams = () => { |
|
||||
// eslint-disable-next-line |
|
||||
const selectRange = luckysheet.getRange(); |
|
||||
if (!selectRange || selectRange.length === 0) { |
|
||||
NotifyManager.warn('请选择要插入变量的Excel单元格'); |
|
||||
return; |
|
||||
} else if (selectRange && selectRange.length > 1) { |
|
||||
NotifyManager.warn('只支持单个选区选取变量'); |
|
||||
return; |
|
||||
} |
|
||||
paramsSelectDialogRef.value.show(state.dataId); |
|
||||
}; |
|
||||
const setParams = (paramsCode: string | Array<string>) => { |
|
||||
if (typeof paramsCode === 'string') { |
|
||||
// eslint-disable-next-line |
|
||||
let rangeValue = luckysheet.getRangeValue(); |
|
||||
rangeValue[0][0] = { ...rangeValue[0][0], ...{ m: paramsCode, v: paramsCode } }; |
|
||||
// eslint-disable-next-line |
|
||||
luckysheet.setRangeValue(rangeValue); |
|
||||
} else { |
|
||||
// eslint-disable-next-line |
|
||||
const currRange = luckysheet.getRange(); |
|
||||
paramsCode.forEach((item, index) => { |
|
||||
const tmpRangeValue = [[{ m: item, v: item }]]; |
|
||||
const tmp = { |
|
||||
row: [currRange[0].row[0], currRange[0].row[1]], |
|
||||
column: [currRange[0].column[0] + index, currRange[0].column[1] + index], |
|
||||
}; |
|
||||
// eslint-disable-next-line |
|
||||
luckysheet.setRangeValue(tmpRangeValue, { range: tmp }); |
|
||||
}); |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
// eslint-disable-next-line |
|
||||
const psReg = /\@\{(.*)\}\@/; |
|
||||
const openConfigDialog = (configType) => { |
|
||||
// eslint-disable-next-line |
|
||||
const range = luckysheet.getRange(); |
|
||||
// eslint-disable-next-line |
|
||||
const rangeValue = luckysheet.getRangeValue(); |
|
||||
if (!range) { |
|
||||
NotifyManager.info('请选择要配置属性的单元格'); |
|
||||
return; |
|
||||
} else if (range && range.length > 1) { |
|
||||
NotifyManager.warn('多个选区无法配置属性,选择单元格既可'); |
|
||||
return; |
|
||||
} |
|
||||
let data = {}; |
|
||||
if (rangeValue[0] && rangeValue[0][0] && rangeValue[0][0].ps && rangeValue[0][0].ps.value) { |
|
||||
let tmp = rangeValue[0][0].ps.value.replaceAll('\n', ''); |
|
||||
data = JSON.parse(psReg.exec(tmp)[1]); |
|
||||
} |
|
||||
if (configType === 'main') { |
|
||||
setForeachPropsDialogRef.value.show(state.dataId, data); |
|
||||
} else { |
|
||||
setColumnParamsDialogRef.value.show(data); |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
const setForEachParams = (formData) => { |
|
||||
// eslint-disable-next-line |
|
||||
const range = luckysheet.getRange(); |
|
||||
let tmp = '@{{\n'; |
|
||||
Object.keys(formData).forEach((item) => { |
|
||||
if (!Tools.isEmpty(formData[item])) { |
|
||||
tmp += '"' + item + '"' + ':' + '"' + formData[item] + '"' + ',' + '\n'; |
|
||||
} |
|
||||
}); |
|
||||
tmp = tmp.substring(0, tmp.length - 2); |
|
||||
tmp += '\n}}@'; |
|
||||
// eslint-disable-next-line |
|
||||
luckysheet.insertComment(range[0].row[0], range[0].column[0], tmp); |
|
||||
// 插入批注后调整批注框大小 |
|
||||
luckysheetOptions.data[0].data[range[0].row[0]][range[0].column[0]].ps.width = 300; |
|
||||
luckysheetOptions.data[0].data[range[0].row[0]][range[0].column[0]].ps.height = 150; |
|
||||
luckysheetOptions.data[0].data[range[0].row[0]][range[0].column[0]].ps.isShow = false; |
|
||||
// eslint-disable-next-line |
|
||||
luckysheet.refresh(); |
|
||||
}; |
|
||||
const save = async () => { |
|
||||
// eslint-disable-next-line |
|
||||
if (!luckysheet.getAllSheets() || luckysheet.getAllSheets().length === 0) { |
|
||||
NotifyManager.warn('系统异常,未获取到需要保存的Sheet数据'); |
|
||||
return; |
|
||||
} |
|
||||
// 覆盖celldata数据缩减传给后端的数据量,该数据仅用以初始化表格,无需保存,初始化时可使用data属性。 |
|
||||
// eslint-disable-next-line |
|
||||
const saveData = { ...luckysheet.getAllSheets()[0], ...{ celldata: [] } }; |
|
||||
// 保存 |
|
||||
let requestParams = { |
|
||||
method: 'POST', |
|
||||
headers: { 'content-type': 'application/json;charset=utf-8;' }, |
|
||||
data: { templateConfig: JSON.stringify(saveData) }, |
|
||||
url: Environment.apiContextPath('api/excel/template/updateConfig/') + state.dataId, |
|
||||
}; |
|
||||
const resp = await axios(requestParams).catch((error) => { |
|
||||
console.info('error====', error); |
|
||||
NotifyManager.error('保存失败'); |
|
||||
}); |
|
||||
NotifyManager.info('保存成功'); |
|
||||
// dialogRef.value.dialogHide(); |
|
||||
}; |
|
||||
|
|
||||
const buttons = ref([ |
|
||||
{ |
|
||||
name: 'selectParams', |
|
||||
icon: 'find_in_page', |
|
||||
label: '选取变量', |
|
||||
click: selectParams, |
|
||||
}, |
|
||||
[ |
|
||||
{ |
|
||||
name: 'foreachPropsConfig', |
|
||||
icon: 'settings', |
|
||||
label: '循环属性配置', |
|
||||
}, |
|
||||
{ |
|
||||
name: 'mainConfig', |
|
||||
icon: 'build_circle', |
|
||||
label: '整体配置(首列)', |
|
||||
click: () => { |
|
||||
openConfigDialog('main'); |
|
||||
}, |
|
||||
}, |
|
||||
{ |
|
||||
name: 'columnConfig', |
|
||||
icon: 'build_circle', |
|
||||
label: '列配置(非首列)', |
|
||||
click: () => { |
|
||||
openConfigDialog('column'); |
|
||||
}, |
|
||||
}, |
|
||||
], |
|
||||
{ |
|
||||
name: 'download', |
|
||||
icon: 'download', |
|
||||
label: '导出文件', |
|
||||
click: downloadExcel, |
|
||||
}, |
|
||||
]); |
|
||||
|
|
||||
onBeforeMount(() => { |
|
||||
window.setInputZIndex = () => { |
|
||||
return true; |
|
||||
}; |
|
||||
window.setRightClickMenuZIndex = () => { |
|
||||
return true; |
|
||||
}; |
|
||||
}); |
|
||||
defineExpose({ |
|
||||
show, |
|
||||
hide, |
|
||||
}); |
|
||||
</script> |
|
||||
|
|
||||
<style scoped> |
|
||||
#luckysheet { |
|
||||
margin: 0px; |
|
||||
padding: 0px; |
|
||||
position: absolute; |
|
||||
width: 100%; |
|
||||
left: 0px; |
|
||||
top: 50px; |
|
||||
bottom: 0px; |
|
||||
} |
|
||||
</style> |
|
@ -1,131 +0,0 @@ |
|||||
<template> |
|
||||
<div style="height: 100%"> |
|
||||
<w-grid |
|
||||
ref="templateGridRef" |
|
||||
title="Excel模板列表" |
|
||||
sort-no |
|
||||
:data-url="Environment.apiContextPath('api/excel/template')" |
|
||||
:query-form-cols-num="2" |
|
||||
:query-form-fields="templateGrid.queryFormFields" |
|
||||
:toolbar-actions="templateGrid.toolbarActions" |
|
||||
:columns="templateGrid.columns" |
|
||||
:editor="templateGrid.editor" |
|
||||
:viewer="templateGrid.viewer" |
|
||||
:sort-by="['-lastModifyDate']" |
|
||||
></w-grid> |
|
||||
<TemplateParamsDialog ref="templateParamsDialogRef"></TemplateParamsDialog> |
|
||||
<TemplateConfigDialog ref="templateConfigDialogRef"></TemplateConfigDialog> |
|
||||
<TemplateReportDialog ref="templateReportDialogRef"></TemplateReportDialog> |
|
||||
</div> |
|
||||
</template> |
|
||||
|
|
||||
<script setup lang="ts"> |
|
||||
import { ref } from 'vue'; |
|
||||
import { Environment } from 'platform-core'; |
|
||||
|
|
||||
import TemplateParamsDialog from './TemplateParamsDialog.vue'; |
|
||||
import TemplateConfigDialog from './TemplateConfigDialog.vue'; |
|
||||
import TemplateReportDialog from './TemplateReportDialog.vue'; |
|
||||
|
|
||||
const templateGridRef = ref(); |
|
||||
const templateParamsDialogRef = ref(); |
|
||||
const templateConfigDialogRef = ref(); |
|
||||
const templateReportDialogRef = ref(); |
|
||||
|
|
||||
const templateGrid = { |
|
||||
queryFormFields: [ |
|
||||
{ label: '模板编码', name: 'templateCode', type: 'w-text' }, |
|
||||
{ label: '模板名称', name: 'templateName', type: 'w-text' }, |
|
||||
], |
|
||||
toolbarActions: [ |
|
||||
'query', |
|
||||
'reset', |
|
||||
'separator', |
|
||||
[ |
|
||||
{ |
|
||||
name: 'operate', |
|
||||
icon: 'difference', |
|
||||
label: '操作', |
|
||||
}, |
|
||||
'add', |
|
||||
{ |
|
||||
extend: 'edit', |
|
||||
afterClick: (args) => { |
|
||||
args.grid.setEditDataUrl(Environment.apiContextPath('api/excel/template/updateField')); |
|
||||
}, |
|
||||
}, |
|
||||
'remove', |
|
||||
], |
|
||||
{ |
|
||||
name: 'params', |
|
||||
icon: 'settings', |
|
||||
label: '变量维护', |
|
||||
click: (args) => { |
|
||||
templateParamsDialogRef.value.show(args.selecteds); |
|
||||
}, |
|
||||
}, |
|
||||
{ |
|
||||
name: 'templateConfig', |
|
||||
icon: 'build_circle', |
|
||||
label: '模板制定', |
|
||||
enableIf: (args) => { |
|
||||
if (args.selected) { |
|
||||
return true; |
|
||||
} else { |
|
||||
return false; |
|
||||
} |
|
||||
}, |
|
||||
click: (args) => { |
|
||||
templateConfigDialogRef.value.show(args.selected); |
|
||||
}, |
|
||||
}, |
|
||||
'separator', |
|
||||
{ |
|
||||
name: 'reportView', |
|
||||
icon: 'visibility', |
|
||||
label: '报表查看', |
|
||||
enableIf: (args) => { |
|
||||
if (args.selected) { |
|
||||
return true; |
|
||||
} else { |
|
||||
return false; |
|
||||
} |
|
||||
}, |
|
||||
click: (args) => { |
|
||||
templateReportDialogRef.value.show(args.selected); |
|
||||
}, |
|
||||
}, |
|
||||
'separator', |
|
||||
], |
|
||||
columns: [ |
|
||||
{ name: 'templateCode', label: '模板编码' }, |
|
||||
{ name: 'templateName', label: '模板名称' }, |
|
||||
{ name: 'lastModifier', label: '最后修改人' }, |
|
||||
{ name: 'lastModifyDate', label: '最后修改时间' }, |
|
||||
], |
|
||||
editor: { |
|
||||
dialog: { |
|
||||
width: '50%', |
|
||||
height: '30%', |
|
||||
}, |
|
||||
form: { |
|
||||
colsNum: 1, |
|
||||
fields: [ |
|
||||
{ label: '模板编码', name: 'templateCode', type: 'w-text', requiredIf: true }, |
|
||||
{ label: '模板名称', name: 'templateName', type: 'w-text', requiredIf: true }, |
|
||||
], |
|
||||
}, |
|
||||
}, |
|
||||
viewer: { |
|
||||
panel: { |
|
||||
fields: [ |
|
||||
{ name: 'id', label: '模板ID' }, |
|
||||
{ name: 'templateCode', label: '模板编码' }, |
|
||||
{ name: 'templateName', label: '模板名称' }, |
|
||||
{ name: 'lastModifier', label: '最后修改人' }, |
|
||||
{ name: 'lastModifyDate', label: '最后修改时间' }, |
|
||||
], |
|
||||
}, |
|
||||
}, |
|
||||
}; |
|
||||
</script> |
|
@ -1,464 +0,0 @@ |
|||||
<template> |
|
||||
<w-dialog ref="dialogRef" title="变量维护" :maximized="true"> |
|
||||
<w-grid |
|
||||
ref="templateParamsGridRef" |
|
||||
title="模板变量列表" |
|
||||
:auto-fetch-data="false" |
|
||||
:data-url="Environment.apiContextPath('api/excel/template/params')" |
|
||||
:sort-no="true" |
|
||||
:columns="templateParamsGrid.columns" |
|
||||
:toolbar-actions="templateParamsGrid.toolbarActions" |
|
||||
:query-form-cols-num="4" |
|
||||
:query-form-fields="templateParamsGrid.queryFormFields" |
|
||||
:pagination="{ |
|
||||
sortBy: 'lastModifyDate', |
|
||||
descending: true, |
|
||||
}" |
|
||||
></w-grid> |
|
||||
<w-dialog ref="templateParamsDialogRef" :title="state.templateParamsDialogTitle" width="80%" height="80%" :buttons="templateParamsDialog.buttons"> |
|
||||
<w-form ref="templateParamsAddEditFormRef" :cols-num="3" :fields="templateParamsDialog.formFields" class="p-1.5"> </w-form> |
|
||||
<w-grid |
|
||||
v-show="state.paramsType && state.paramsType === 'LIST'" |
|
||||
ref="templateParamsListFieldGridRef" |
|
||||
title="字段列表" |
|
||||
dense |
|
||||
:draggable="true" |
|
||||
:pageable="false" |
|
||||
:config-button="false" |
|
||||
:auto-fetch-data="false" |
|
||||
:fetch-data-url="Environment.apiContextPath('api/excel/template/params/list?sortBy=sortNo')" |
|
||||
:toolbar-actions="templateParamsListFieldGrid.toolbarActions" |
|
||||
:columns="templateParamsListFieldGrid.columns" |
|
||||
></w-grid> |
|
||||
<w-dialog |
|
||||
ref="templateParamsListFieldDialogRef" |
|
||||
:title="state.templateParamsListFieldDialogTitle" |
|
||||
width="60%" |
|
||||
height="50%" |
|
||||
:buttons="templateParamsListFieldDialog.buttons" |
|
||||
> |
|
||||
<w-form ref="templateParamsListFieldAddEditFormRef" :cols-num="1" :fields="templateParamsListFieldDialog.formFields" class="p-1.5"> </w-form> |
|
||||
</w-dialog> |
|
||||
</w-dialog> |
|
||||
</w-dialog> |
|
||||
</template> |
|
||||
|
|
||||
<script setup lang="ts"> |
|
||||
import { ref, reactive, nextTick } from 'vue'; |
|
||||
import { axios, Environment, NotifyManager } from 'platform-core'; |
|
||||
|
|
||||
const dialogRef = ref(); |
|
||||
const templateParamsGridRef = ref(); |
|
||||
const templateParamsDialogRef = ref(); |
|
||||
const templateParamsAddEditFormRef = ref(); |
|
||||
const templateParamsListFieldGridRef = ref(); |
|
||||
const templateParamsListFieldDialogRef = ref(); |
|
||||
const templateParamsListFieldAddEditFormRef = ref(); |
|
||||
|
|
||||
const state = reactive({ |
|
||||
templateArray: [], |
|
||||
tableSelectedTemplateId: null, |
|
||||
paramsType: null, |
|
||||
templateParamsDialogTitle: '新增变量', |
|
||||
templateParamsListFieldDialogTitle: '新增字段', |
|
||||
}); |
|
||||
|
|
||||
const templateParamsGrid = { |
|
||||
queryFormFields: [ |
|
||||
{ label: '变量编码', name: 'paramsCode', type: 'w-text' }, |
|
||||
{ label: '变量名称', name: 'paramsName', type: 'w-text' }, |
|
||||
{ |
|
||||
label: '变量类型', |
|
||||
name: 'paramsType', |
|
||||
type: 'w-select', |
|
||||
queryOperator: 'equals', |
|
||||
options: [ |
|
||||
{ label: '单值', value: 'SING' }, |
|
||||
{ label: '列表', value: 'LIST' }, |
|
||||
], |
|
||||
}, |
|
||||
{ |
|
||||
label: '所属模板', |
|
||||
name: 'reportExcelTemplate', |
|
||||
queryOperator: 'equals', |
|
||||
type: 'w-select', |
|
||||
clearable: true, |
|
||||
colspan: 2, |
|
||||
options: [], |
|
||||
}, |
|
||||
], |
|
||||
toolbarActions: [ |
|
||||
'query', |
|
||||
'reset', |
|
||||
'separator', |
|
||||
{ |
|
||||
extend: 'add', |
|
||||
click: () => { |
|
||||
templateParamsDialogRef.value.show(); |
|
||||
}, |
|
||||
afterClick: () => { |
|
||||
templateParamsAddEditFormRef.value.setStatus('add'); |
|
||||
state.templateParamsDialogTitle = '新增变量'; |
|
||||
templateParamsAddEditFormRef.value.getFields()['reportExcelTemplate'].options = state.templateArray; |
|
||||
state.paramsType = null; |
|
||||
if (state.tableSelectedTemplateId) { |
|
||||
templateParamsAddEditFormRef.value.setFieldValue('paramsIsCommon', false); |
|
||||
templateParamsAddEditFormRef.value.setFieldValue('reportExcelTemplate', state.tableSelectedTemplateId); |
|
||||
} |
|
||||
}, |
|
||||
}, |
|
||||
{ |
|
||||
extend: 'edit', |
|
||||
click: () => { |
|
||||
templateParamsDialogRef.value.show(); |
|
||||
}, |
|
||||
afterClick: (args) => { |
|
||||
templateParamsAddEditFormRef.value.setStatus('edit'); |
|
||||
state.templateParamsDialogTitle = '编辑变量'; |
|
||||
templateParamsAddEditFormRef.value.getFields()['reportExcelTemplate'].options = state.templateArray; |
|
||||
templateParamsAddEditFormRef.value.setData(args.selected); |
|
||||
state.paramsType = args.selected.paramsType; |
|
||||
if (args.selected['paramsIsCommon']) { |
|
||||
templateParamsAddEditFormRef.value.setFieldValue('reportExcelTemplate', null); |
|
||||
} else if (args.selected['reportExcelTemplate']) { |
|
||||
templateParamsAddEditFormRef.value.setFieldValue('reportExcelTemplate', args.selected['reportExcelTemplate']); |
|
||||
} |
|
||||
if (state.paramsType === 'LIST') { |
|
||||
const urlSearchParams = new URLSearchParams(); |
|
||||
urlSearchParams.append('criteria', JSON.stringify({ fieldName: 'reportExcelTemplateParams', operator: 'equals', value: args.selected.id })); |
|
||||
axios |
|
||||
.get(Environment.apiContextPath('api/excel/template/params/list?pageable=false&sortBy=sortNo'), { params: urlSearchParams }) |
|
||||
.then((resp) => { |
|
||||
if (resp.data.content) { |
|
||||
templateParamsListFieldGridRef.value.setLocalData(resp.data.content); |
|
||||
} |
|
||||
}) |
|
||||
.catch((error) => { |
|
||||
console.info('error====', error); |
|
||||
}); |
|
||||
} |
|
||||
}, |
|
||||
}, |
|
||||
{ |
|
||||
extend: 'clone', |
|
||||
click: () => { |
|
||||
templateParamsDialogRef.value.show(); |
|
||||
}, |
|
||||
afterClick: (args) => { |
|
||||
templateParamsAddEditFormRef.value.setStatus('clone'); |
|
||||
state.templateParamsDialogTitle = '复制变量'; |
|
||||
templateParamsAddEditFormRef.value.getFields()['reportExcelTemplate'].options = state.templateArray; |
|
||||
templateParamsAddEditFormRef.value.setData(args.selected); |
|
||||
state.paramsType = args.selected.paramsType; |
|
||||
if (args.selected['paramsIsCommon']) { |
|
||||
templateParamsAddEditFormRef.value.setFieldValue('reportExcelTemplate', null); |
|
||||
} else if (args.selected['reportExcelTemplate']) { |
|
||||
templateParamsAddEditFormRef.value.setFieldValue('reportExcelTemplate', args.selected['reportExcelTemplate']); |
|
||||
} |
|
||||
if (state.paramsType === 'LIST') { |
|
||||
const urlSearchParams = new URLSearchParams(); |
|
||||
urlSearchParams.append('criteria', JSON.stringify({ fieldName: 'reportExcelTemplateParams', operator: 'equals', value: args.selected.id })); |
|
||||
axios |
|
||||
.get(Environment.apiContextPath('api/excel/template/params/list?pageable=false&sortBy=sortNo'), { params: urlSearchParams }) |
|
||||
.then((resp) => { |
|
||||
if (resp.data.content) { |
|
||||
templateParamsListFieldGridRef.value.setLocalData(resp.data.content); |
|
||||
} |
|
||||
}) |
|
||||
.catch((error) => { |
|
||||
console.info('error====', error); |
|
||||
}); |
|
||||
} |
|
||||
}, |
|
||||
}, |
|
||||
'remove', |
|
||||
'separator', |
|
||||
], |
|
||||
columns: [ |
|
||||
{ name: 'paramsCode', label: '变量编码' }, |
|
||||
{ name: 'paramsName', label: '变量名称' }, |
|
||||
{ |
|
||||
name: 'paramsType', |
|
||||
label: '变量类型', |
|
||||
format: (val, row) => { |
|
||||
if (val === 'SING') { |
|
||||
return '单值'; |
|
||||
} else if (val === 'LIST') { |
|
||||
return '列表'; |
|
||||
} else { |
|
||||
return val; |
|
||||
} |
|
||||
}, |
|
||||
}, |
|
||||
{ |
|
||||
name: 'paramsIsCommon', |
|
||||
label: '变量是否通用', |
|
||||
format: (val, row) => { |
|
||||
if (val === true) { |
|
||||
return '所有模板均可使用'; |
|
||||
} else if (val === false) { |
|
||||
return '指定模板可使用'; |
|
||||
} else { |
|
||||
return val; |
|
||||
} |
|
||||
}, |
|
||||
}, |
|
||||
{ name: 'reportExcelTemplateName', label: '所属模板名称' }, |
|
||||
{ name: 'lastModifier', label: '最后修改人' }, |
|
||||
{ name: 'lastModifyDate', label: '最后修改时间' }, |
|
||||
], |
|
||||
}; |
|
||||
|
|
||||
const templateParamsDialog = { |
|
||||
buttons: [ |
|
||||
{ |
|
||||
icon: 'beenhere', |
|
||||
label: '提交', |
|
||||
click: async () => { |
|
||||
const validate = await templateParamsAddEditFormRef.value.validate(); |
|
||||
if (validate) { |
|
||||
const formStatus = templateParamsAddEditFormRef.value.getStatus(); |
|
||||
const formData = templateParamsAddEditFormRef.value.getData(); |
|
||||
if (formData.reportExcelTemplate) { |
|
||||
formData.reportExcelTemplate = { id: formData.reportExcelTemplate }; |
|
||||
} else { |
|
||||
formData.reportExcelTemplate = null; |
|
||||
} |
|
||||
const fieldRows = templateParamsListFieldGridRef.value.getRows(); |
|
||||
let url = Environment.apiContextPath('api/excel/template/params'); |
|
||||
if (formStatus === 'edit') { |
|
||||
url += '/edit'; |
|
||||
formData.id = templateParamsGridRef.value.getSelectedRows()[0].id; |
|
||||
fieldRows.forEach((item) => { |
|
||||
delete item.reportExcelTemplateParams; |
|
||||
}); |
|
||||
} else { |
|
||||
url += '/add'; |
|
||||
} |
|
||||
const resp = await axios |
|
||||
.post(url, { |
|
||||
params: formData, |
|
||||
list: formData.paramsType === 'LIST' ? fieldRows : [], |
|
||||
}) |
|
||||
.catch((error) => { |
|
||||
console.info('error====', error); |
|
||||
NotifyManager.error('操作失败'); |
|
||||
}); |
|
||||
NotifyManager.info('保存成功'); |
|
||||
templateParamsDialogRef.value.hide(); |
|
||||
templateParamsGridRef.value.refresh(); |
|
||||
} |
|
||||
}, |
|
||||
}, |
|
||||
{ |
|
||||
icon: 'published_with_changes', |
|
||||
label: 'SQL校验', |
|
||||
click: async () => { |
|
||||
const paramsSqlValue = templateParamsAddEditFormRef.value.getFieldValue('paramsSql'); |
|
||||
if (!paramsSqlValue) { |
|
||||
NotifyManager.warn('取值SQL为空'); |
|
||||
return; |
|
||||
} |
|
||||
const requestParams = { |
|
||||
method: 'POST', |
|
||||
headers: { 'content-type': 'text/plain;charset=utf-8;' }, |
|
||||
data: paramsSqlValue, |
|
||||
url: Environment.apiContextPath('api/jdbc/fetchMetaDataBySql'), |
|
||||
}; |
|
||||
const resp = await axios(requestParams); |
|
||||
if (resp && resp.data) { |
|
||||
NotifyManager.info('校验通过'); |
|
||||
} else { |
|
||||
NotifyManager.error('校验失败'); |
|
||||
} |
|
||||
}, |
|
||||
}, |
|
||||
], |
|
||||
formFields: [ |
|
||||
{ label: '变量编码', name: 'paramsCode', type: 'w-text', requiredIf: true }, |
|
||||
{ label: '变量名称', name: 'paramsName', type: 'w-text', requiredIf: true }, |
|
||||
{ |
|
||||
label: '变量类型', |
|
||||
name: 'paramsType', |
|
||||
type: 'w-select', |
|
||||
requiredIf: true, |
|
||||
options: [ |
|
||||
{ label: '单值', value: 'SING' }, |
|
||||
{ label: '列表', value: 'LIST' }, |
|
||||
], |
|
||||
'onUpdate:modelValue': (value) => { |
|
||||
state.paramsType = value; |
|
||||
}, |
|
||||
}, |
|
||||
{ |
|
||||
label: '变量是否通用', |
|
||||
name: 'paramsIsCommon', |
|
||||
type: 'w-select', |
|
||||
requiredIf: true, |
|
||||
options: [ |
|
||||
{ label: '所有模板均可使用', value: true }, |
|
||||
{ label: '指定模板可使用', value: false }, |
|
||||
], |
|
||||
'onUpdate:modelValue': (value) => { |
|
||||
if (typeof value === 'boolean' && value === false) { |
|
||||
templateParamsAddEditFormRef.value.setFieldValue('reportExcelTemplate', state.tableSelectedTemplateId); |
|
||||
} else { |
|
||||
templateParamsAddEditFormRef.value.setFieldValue('reportExcelTemplate', null); |
|
||||
} |
|
||||
}, |
|
||||
}, |
|
||||
{ |
|
||||
label: '所属模板', |
|
||||
name: 'reportExcelTemplate', |
|
||||
type: 'w-select', |
|
||||
colspan: 2, |
|
||||
requiredIf: true, |
|
||||
options: [], |
|
||||
showIf: (args) => { |
|
||||
const value = args.form?.getFieldValue('paramsIsCommon'); |
|
||||
if (typeof value === 'boolean' && value === false) { |
|
||||
return true; |
|
||||
} else { |
|
||||
return false; |
|
||||
} |
|
||||
}, |
|
||||
}, |
|
||||
{ |
|
||||
label: '取值SQL', |
|
||||
name: 'paramsSql', |
|
||||
type: 'w-textarea', |
|
||||
requiredIf: true, |
|
||||
colspan: 'full', |
|
||||
}, |
|
||||
], |
|
||||
}; |
|
||||
|
|
||||
const templateParamsListFieldGrid = { |
|
||||
toolbarActions: [ |
|
||||
{ |
|
||||
name: 'generateFieldsBySql', |
|
||||
icon: 'playlist_add_circle', |
|
||||
label: '根据取值SQL生成', |
|
||||
click: async () => { |
|
||||
const paramsSqlValue = templateParamsAddEditFormRef.value.getFieldValue('paramsSql'); |
|
||||
if (!paramsSqlValue) { |
|
||||
NotifyManager.warn('取值SQL为空,无法生成'); |
|
||||
return; |
|
||||
} |
|
||||
const requestParams = { |
|
||||
method: 'POST', |
|
||||
headers: { 'content-type': 'text/plain;charset=utf-8;' }, |
|
||||
data: paramsSqlValue, |
|
||||
url: Environment.apiContextPath('api/jdbc/fetchMetaDataBySql'), |
|
||||
}; |
|
||||
const resp: any = await axios(requestParams).catch((error) => { |
|
||||
console.info('error====', error); |
|
||||
NotifyManager.error('操作失败'); |
|
||||
}); |
|
||||
const listFieldsRow = { name: '', desc: '' }; |
|
||||
const listFields = <any>[]; |
|
||||
if (resp.data) { |
|
||||
resp.data.forEach((item, index) => { |
|
||||
listFields.push({ ...listFieldsRow, ...{ sortNo: index + 1, name: item.columnName, type: item.columnTypeName } }); |
|
||||
}); |
|
||||
templateParamsListFieldGridRef.value.setLocalData(listFields); |
|
||||
} |
|
||||
}, |
|
||||
}, |
|
||||
{ |
|
||||
extend: 'edit', |
|
||||
click: () => { |
|
||||
state.templateParamsListFieldDialogTitle = '编辑字段'; |
|
||||
templateParamsListFieldDialogRef.value.show(); |
|
||||
}, |
|
||||
afterClick: (args) => { |
|
||||
templateParamsListFieldAddEditFormRef.value.setStatus('edit'); |
|
||||
templateParamsListFieldAddEditFormRef.value.setData(args.selected); |
|
||||
}, |
|
||||
}, |
|
||||
{ |
|
||||
extend: 'remove', |
|
||||
click: (args) => { |
|
||||
if (args.tickeds) { |
|
||||
templateParamsListFieldGridRef.value.removeLocalData(args.tickeds); |
|
||||
} else { |
|
||||
templateParamsListFieldGridRef.value.removeLocalData(args.selecteds); |
|
||||
} |
|
||||
}, |
|
||||
}, |
|
||||
], |
|
||||
columns: [ |
|
||||
{ name: 'sortNo', label: '排序号' }, |
|
||||
{ name: 'name', label: '字段名' }, |
|
||||
{ name: 'desc', label: '字段描述' }, |
|
||||
], |
|
||||
}; |
|
||||
|
|
||||
const templateParamsListFieldDialog = { |
|
||||
buttons: [ |
|
||||
{ |
|
||||
icon: 'save', |
|
||||
label: '确定', |
|
||||
click: async () => { |
|
||||
const validateResult = await templateParamsListFieldAddEditFormRef.value.validate(); |
|
||||
if (validateResult) { |
|
||||
const formData = templateParamsListFieldAddEditFormRef.value.getData(); |
|
||||
const formStatus = templateParamsListFieldAddEditFormRef.value.getStatus(); |
|
||||
if (formStatus === 'add') { |
|
||||
templateParamsListFieldGridRef.value.addRow(formData, null); |
|
||||
} else { |
|
||||
templateParamsListFieldGridRef.value.replaceRow({ |
|
||||
...formData, |
|
||||
_rowKey_: templateParamsListFieldGridRef.value.getSelectedRows()[0]['_rowKey_'], |
|
||||
}); |
|
||||
} |
|
||||
templateParamsListFieldDialogRef.value.hide(); |
|
||||
} |
|
||||
}, |
|
||||
}, |
|
||||
], |
|
||||
formFields: [ |
|
||||
{ label: '字段名', name: 'name', type: 'w-text', requiredIf: true }, |
|
||||
{ label: '字段描述', name: 'desc', type: 'w-text' }, |
|
||||
], |
|
||||
}; |
|
||||
|
|
||||
const getTemplateListFun = async () => { |
|
||||
const resp = await axios.get(Environment.apiContextPath('api/excel/template?pageable=false')); |
|
||||
if (resp && resp.data?.content) { |
|
||||
const options = <any>[]; |
|
||||
resp.data.content.forEach((item) => { |
|
||||
options.push({ label: item.templateName, value: item.id }); |
|
||||
}); |
|
||||
state.templateArray = options; |
|
||||
templateParamsGridRef.value.getQueryForm().getFields()['reportExcelTemplate'].options = options; |
|
||||
|
|
||||
setTimeout(() => { |
|
||||
if (state.tableSelectedTemplateId) { |
|
||||
templateParamsGridRef.value.getQueryForm().setFieldValue('reportExcelTemplate', state.tableSelectedTemplateId); |
|
||||
} |
|
||||
// 设置完所属模板后加载变量列表的数据 |
|
||||
templateParamsGridRef.value.refresh(); |
|
||||
}, 100); |
|
||||
} |
|
||||
}; |
|
||||
const show = (tableSelected) => { |
|
||||
dialogRef.value.show(); |
|
||||
if (tableSelected && tableSelected.length > 0) { |
|
||||
state.tableSelectedTemplateId = tableSelected[0].id; |
|
||||
} else { |
|
||||
state.tableSelectedTemplateId = null; |
|
||||
} |
|
||||
nextTick(() => { |
|
||||
getTemplateListFun(); |
|
||||
}); |
|
||||
}; |
|
||||
const hide = () => { |
|
||||
dialogRef.value.hide(); |
|
||||
}; |
|
||||
|
|
||||
defineExpose({ |
|
||||
show, |
|
||||
hide, |
|
||||
}); |
|
||||
</script> |
|
@ -1,234 +0,0 @@ |
|||||
<template> |
|
||||
<w-dialog ref="dialogRef" title="选取变量" width="80%" height="80%" :buttons="dialog.buttons"> |
|
||||
<div class="h-full"> |
|
||||
<div class="h-[300px]"> |
|
||||
<w-grid |
|
||||
ref="templateParamsGridRef" |
|
||||
dense |
|
||||
sort-no |
|
||||
title="模板变量列表" |
|
||||
:auto-fetch-data="false" |
|
||||
:data-url="Environment.apiContextPath('api/excel/template/params')" |
|
||||
:columns="templateParamsGrid.columns" |
|
||||
:toolbar-actions="templateParamsGrid.toolbarActions" |
|
||||
:config-button="false" |
|
||||
:query-form-cols-num="3" |
|
||||
:query-form-fields="templateParamsGrid.queryFormFields" |
|
||||
:sort-by="['-lastModifyDate']" |
|
||||
@row-click="templateParamsGridClick" |
|
||||
></w-grid> |
|
||||
</div> |
|
||||
<div style="height: calc(100% - 300px)"> |
|
||||
<w-grid |
|
||||
v-show="state.showListFieldGrid" |
|
||||
ref="templateParamsListFieldGridRef" |
|
||||
dense |
|
||||
sort-no |
|
||||
:config-button="false" |
|
||||
:hide-bottom="false" |
|
||||
:pageable="false" |
|
||||
title="字段列表" |
|
||||
:auto-fetch-data="false" |
|
||||
:fetch-data-url="Environment.apiContextPath('api/excel/template/params/list')" |
|
||||
:columns="templateParamsListFieldGrid.columns" |
|
||||
></w-grid> |
|
||||
</div> |
|
||||
</div> |
|
||||
</w-dialog> |
|
||||
</template> |
|
||||
|
|
||||
<script setup lang="ts"> |
|
||||
import { ref, reactive, nextTick } from 'vue'; |
|
||||
import { useQuasar } from 'quasar'; |
|
||||
import { axios, Environment, NotifyManager, OperatorTypeEnum } from 'platform-core'; |
|
||||
|
|
||||
const $q = useQuasar(); |
|
||||
const emit = defineEmits<{ |
|
||||
( |
|
||||
e: 'setParams', // 设置模板变量 |
|
||||
paramsCode: string | Array<string>, // 变量编码(列表类型返回数组) |
|
||||
): void; |
|
||||
}>(); |
|
||||
|
|
||||
const dialogRef = ref(); |
|
||||
const templateParamsGridRef = ref(); |
|
||||
const templateParamsListFieldGridRef = ref(); |
|
||||
|
|
||||
const state = reactive({ |
|
||||
templateArray: [], |
|
||||
tableSelectedTemplateId: null, |
|
||||
showListFieldGrid: false, |
|
||||
}); |
|
||||
|
|
||||
const dialog = { |
|
||||
buttons: [ |
|
||||
{ |
|
||||
icon: 'save', |
|
||||
label: '确定', |
|
||||
click: async () => { |
|
||||
const paramsSelected = templateParamsGridRef.value.getSelectedRows(); |
|
||||
const listFieldSelected = templateParamsListFieldGridRef.value.getSelectedRows(); |
|
||||
if (paramsSelected && paramsSelected.length > 0) { |
|
||||
if (paramsSelected[0].paramsType === 'LIST' && (!listFieldSelected || listFieldSelected.length === 0)) { |
|
||||
const listFieldRows = templateParamsListFieldGridRef.value.getRows(); |
|
||||
const arr = <string[]>[]; |
|
||||
listFieldRows.forEach((item) => { |
|
||||
arr.push('#{' + item.name + '}'); |
|
||||
}); |
|
||||
emit('setParams', arr); |
|
||||
hide(); |
|
||||
return; |
|
||||
} else if (paramsSelected[0].paramsType === 'LIST' && listFieldSelected && listFieldSelected.length > 0) { |
|
||||
emit('setParams', '#{' + listFieldSelected[0].name + '}'); |
|
||||
hide(); |
|
||||
return; |
|
||||
} |
|
||||
} else { |
|
||||
NotifyManager.warn('请选择要插入的变量'); |
|
||||
return; |
|
||||
} |
|
||||
}, |
|
||||
}, |
|
||||
], |
|
||||
}; |
|
||||
|
|
||||
const templateParamsGrid = reactive({ |
|
||||
queryFormFields: [ |
|
||||
{ label: '变量名称', name: 'paramsName', type: 'w-text' }, |
|
||||
{ |
|
||||
label: '变量类型', |
|
||||
name: 'paramsType', |
|
||||
type: 'w-select', |
|
||||
queryOperator: 'equals', |
|
||||
options: [ |
|
||||
{ label: '单值', value: 'SING' }, |
|
||||
{ label: '列表', value: 'LIST' }, |
|
||||
], |
|
||||
}, |
|
||||
{ |
|
||||
label: '所属模板', |
|
||||
name: 'reportExcelTemplate', |
|
||||
type: 'w-select', |
|
||||
queryOperator: 'equals', |
|
||||
clearable: true, |
|
||||
colspan: 2, |
|
||||
options: [], |
|
||||
}, |
|
||||
], |
|
||||
toolbarActions: ['query', 'reset'], |
|
||||
columns: [ |
|
||||
{ name: 'paramsCode', label: '变量编码' }, |
|
||||
{ name: 'paramsName', label: '变量名称' }, |
|
||||
{ |
|
||||
name: 'paramsType', |
|
||||
label: '变量类型', |
|
||||
format: (val) => { |
|
||||
if (val === 'SING') { |
|
||||
return '单值'; |
|
||||
} else if (val === 'LIST') { |
|
||||
return '列表'; |
|
||||
} else { |
|
||||
return val; |
|
||||
} |
|
||||
}, |
|
||||
}, |
|
||||
{ |
|
||||
name: 'paramsIsCommon', |
|
||||
label: '变量是否通用', |
|
||||
format: (val) => { |
|
||||
if (val === true) { |
|
||||
return '所有模板均可使用'; |
|
||||
} else if (val === false) { |
|
||||
return '指定模板可使用'; |
|
||||
} else { |
|
||||
return val; |
|
||||
} |
|
||||
}, |
|
||||
}, |
|
||||
{ name: 'reportExcelTemplateName', label: '所属模板名称' }, |
|
||||
{ name: 'lastModifier', label: '最后修改人' }, |
|
||||
{ name: 'lastModifyDate', label: '最后修改时间' }, |
|
||||
], |
|
||||
}); |
|
||||
|
|
||||
const templateParamsListFieldGrid = reactive({ |
|
||||
columns: [ |
|
||||
{ name: 'name', label: '字段名' }, |
|
||||
{ name: 'desc', label: '字段描述' }, |
|
||||
{ |
|
||||
name: 'formatType', |
|
||||
label: '格式化类型', |
|
||||
format: (val) => { |
|
||||
if (val && OperatorTypeEnum[val]) { |
|
||||
return OperatorTypeEnum[val]; |
|
||||
} else { |
|
||||
return val; |
|
||||
} |
|
||||
}, |
|
||||
}, |
|
||||
{ name: 'formatValue', label: '格式化值' }, |
|
||||
], |
|
||||
}); |
|
||||
|
|
||||
const templateParamsGridClick = (args) => { |
|
||||
const { evt, row, index } = args; |
|
||||
if (row.paramsType === 'LIST') { |
|
||||
state.showListFieldGrid = true; |
|
||||
const urlSearchParams = new URLSearchParams(); |
|
||||
urlSearchParams.append('criteria', JSON.stringify({ fieldName: 'reportExcelTemplateParams', operator: 'equals', value: row.id })); |
|
||||
axios |
|
||||
.get(Environment.apiContextPath('api/excel/template/params/list?pageable=false&sortBy=sortNo'), { params: urlSearchParams }) |
|
||||
.then((resp) => { |
|
||||
if (resp.data.content) { |
|
||||
templateParamsListFieldGridRef.value.setLocalData(resp.data.content); |
|
||||
} |
|
||||
}) |
|
||||
.catch((error) => { |
|
||||
console.info('error====', error); |
|
||||
}); |
|
||||
} else { |
|
||||
// 清空字段列表 |
|
||||
templateParamsListFieldGridRef.value.setLocalData([]); |
|
||||
// 隐藏字段列表 |
|
||||
state.showListFieldGrid = false; |
|
||||
} |
|
||||
}; |
|
||||
const getTemplateListFun = async () => { |
|
||||
const resp = await axios.get(Environment.apiContextPath('api/excel/template?pageable=false')); |
|
||||
if (resp && resp.data?.content) { |
|
||||
const options = <any>[]; |
|
||||
resp.data.content.forEach((item) => { |
|
||||
options.push({ label: item.templateName, value: item.id }); |
|
||||
}); |
|
||||
state.templateArray = options; |
|
||||
templateParamsGridRef.value.getQueryForm().getFields()['reportExcelTemplate'].options = options; |
|
||||
|
|
||||
setTimeout(() => { |
|
||||
if (state.tableSelectedTemplateId) { |
|
||||
templateParamsGridRef.value.getQueryForm().setFieldValue('reportExcelTemplate', state.tableSelectedTemplateId); |
|
||||
} |
|
||||
// 设置完所属模板后加载变量列表的数据 |
|
||||
templateParamsGridRef.value.refresh(); |
|
||||
}, 100); |
|
||||
} |
|
||||
}; |
|
||||
const show = (templateId) => { |
|
||||
dialogRef.value.show(); |
|
||||
if (templateId) { |
|
||||
state.tableSelectedTemplateId = templateId; |
|
||||
} else { |
|
||||
state.tableSelectedTemplateId = null; |
|
||||
} |
|
||||
nextTick(() => { |
|
||||
getTemplateListFun(); |
|
||||
}); |
|
||||
}; |
|
||||
const hide = () => { |
|
||||
dialogRef.value.hide(); |
|
||||
}; |
|
||||
|
|
||||
defineExpose({ |
|
||||
show, |
|
||||
hide, |
|
||||
}); |
|
||||
</script> |
|
@ -1,34 +0,0 @@ |
|||||
<template> |
|
||||
<w-dialog ref="dialogRef" :title="state.dialogTitle" width="100%" height="100%" :maximized="true" :can-maximize="false" body-padding="0px 0px 0px 0px"> |
|
||||
<ExcelReport v-if="state.dataId" ref="excelReportRef" :template-id="state.dataId" style="height: 100%"></ExcelReport> |
|
||||
</w-dialog> |
|
||||
</template> |
|
||||
|
|
||||
<script setup lang="ts"> |
|
||||
import { ref, reactive } from 'vue'; |
|
||||
|
|
||||
import ExcelReport from './ExcelReport.vue'; |
|
||||
|
|
||||
const dialogRef = ref(); |
|
||||
const excelReportRef = ref(); |
|
||||
const state = reactive({ |
|
||||
dialogTitle: '模板制定', |
|
||||
dataId: '', |
|
||||
}); |
|
||||
|
|
||||
const show = (tableSelectedRow: any) => { |
|
||||
state.dataId = tableSelectedRow.id; |
|
||||
state.dialogTitle = '模板报表查看——' + tableSelectedRow.templateName + '(' + tableSelectedRow.templateCode + ')'; |
|
||||
dialogRef.value.show(); |
|
||||
}; |
|
||||
const hide = () => { |
|
||||
dialogRef.value.hide(); |
|
||||
}; |
|
||||
|
|
||||
defineExpose({ |
|
||||
show, |
|
||||
hide, |
|
||||
}); |
|
||||
</script> |
|
||||
|
|
||||
<style scoped></style> |
|
@ -1,91 +0,0 @@ |
|||||
<template> |
|
||||
<w-dialog ref="dialogRef" title="属性配置" width="80%" height="80%" :buttons="dialog.buttons"> |
|
||||
<w-form ref="formRef" :cols-num="1" :fields="form.fields" class="p-1.5"> </w-form> |
|
||||
</w-dialog> |
|
||||
</template> |
|
||||
|
|
||||
<script setup lang="ts"> |
|
||||
import { ref, nextTick } from 'vue'; |
|
||||
import { NotifyManager, Tools } from 'platform-core'; |
|
||||
|
|
||||
const emit = defineEmits<{ |
|
||||
( |
|
||||
e: 'setForEachParams', // 设置循环属性 |
|
||||
formData: any, // 循环属性对象 |
|
||||
): void; |
|
||||
}>(); |
|
||||
|
|
||||
const dialogRef = ref(); |
|
||||
const formRef = ref(); |
|
||||
|
|
||||
const dialog = { |
|
||||
buttons: [ |
|
||||
{ |
|
||||
icon: 'save', |
|
||||
label: '确定', |
|
||||
click: async () => { |
|
||||
const validate = await formRef.value.validate(); |
|
||||
if (validate) { |
|
||||
const formData = formRef.value.getData(); |
|
||||
let flag = false; |
|
||||
Object.keys(formData).forEach((item) => { |
|
||||
if (!Tools.isEmpty(formData[item])) { |
|
||||
flag = true; |
|
||||
} |
|
||||
}); |
|
||||
if (flag) { |
|
||||
emit('setForEachParams', formData); |
|
||||
dialogRef.value.hide(); |
|
||||
} else { |
|
||||
NotifyManager.warn('未配置任何属性'); |
|
||||
} |
|
||||
} |
|
||||
}, |
|
||||
}, |
|
||||
], |
|
||||
}; |
|
||||
const form = { |
|
||||
fields: [ |
|
||||
{ |
|
||||
label: '单元格格式', |
|
||||
name: 'cellFormat', |
|
||||
type: 'w-select', |
|
||||
options: [ |
|
||||
{ label: '纯文本', value: '1' }, |
|
||||
{ label: '数字格式-整数', value: '2' }, |
|
||||
{ label: '数字格式-两位小数', value: '3' }, |
|
||||
{ label: '数字格式-四位小数', value: '4' }, |
|
||||
{ label: '百分比整数', value: '5' }, |
|
||||
{ label: '百分比两位小数', value: '6' }, |
|
||||
{ label: '万元两位小数(示例:12万3456.00)', value: '7' }, |
|
||||
{ label: '千位符整数(示例:1,235)', value: '8' }, |
|
||||
{ label: '千位符两位小数(示例:1,234.56)', value: '9' }, |
|
||||
], |
|
||||
}, |
|
||||
{ |
|
||||
label: '单元格码值转换', |
|
||||
name: 'cellValueTransformed', |
|
||||
type: 'w-text', |
|
||||
hint: `当值匹配上时显示转换后的值,等号左边为原始值,右边为转换值,位置需对应,英文逗号分隔。示例:1,2=年,月 转换为空示例:-999=NULL`, |
|
||||
}, |
|
||||
{ label: '单元格批注', name: 'cellComment', type: 'w-textarea' }, |
|
||||
], |
|
||||
}; |
|
||||
|
|
||||
const show = (data) => { |
|
||||
dialogRef.value.show(); |
|
||||
nextTick(() => { |
|
||||
if (data) { |
|
||||
formRef.value.setData(data); |
|
||||
} |
|
||||
}); |
|
||||
}; |
|
||||
const hide = () => { |
|
||||
dialogRef.value.hide(); |
|
||||
}; |
|
||||
|
|
||||
defineExpose({ |
|
||||
show, |
|
||||
hide, |
|
||||
}); |
|
||||
</script> |
|
@ -1,250 +0,0 @@ |
|||||
<template> |
|
||||
<w-dialog ref="dialogRef" title="属性配置" width="80%" height="80%" :buttons="dialog.buttons"> |
|
||||
<w-form ref="formRef" :cols-num="1" :fields="form.fields" class="p-1.5"></w-form> |
|
||||
<w-dialog ref="listParamsDialogRef" dialog-title="选择循环的列表名" width="70%" height="70%" :buttons="listParamsDialog.buttons"> |
|
||||
<w-grid |
|
||||
ref="templateParamsGridRef" |
|
||||
title="模板变量列表" |
|
||||
sort-no |
|
||||
dense |
|
||||
:checkbox-selection="false" |
|
||||
:auto-fetch-data="false" |
|
||||
:data-url="Environment.apiContextPath('api/excel/template/params')" |
|
||||
:columns="templateParamsGrid.columns" |
|
||||
:toolbar-actions="templateParamsGrid.toolbarActions" |
|
||||
:query-form-cols-num="2" |
|
||||
:query-form-row-num="2" |
|
||||
:query-form-fields="templateParamsGrid.queryFormFields" |
|
||||
:sort-by="['-lastModifyDate']" |
|
||||
></w-grid> |
|
||||
</w-dialog> |
|
||||
</w-dialog> |
|
||||
</template> |
|
||||
|
|
||||
<script setup lang="ts"> |
|
||||
import { ref, reactive, nextTick } from 'vue'; |
|
||||
import { axios, Environment, NotifyManager, Tools } from 'platform-core'; |
|
||||
|
|
||||
const emit = defineEmits<{ |
|
||||
( |
|
||||
e: 'setForEachParams', // 设置循环属性 |
|
||||
formData: any, // 循环属性对象 |
|
||||
): void; |
|
||||
}>(); |
|
||||
|
|
||||
const dialogRef = ref(); |
|
||||
const formRef = ref(); |
|
||||
const listParamsDialogRef = ref(); |
|
||||
const templateParamsGridRef = ref(); |
|
||||
|
|
||||
const state = reactive({ |
|
||||
templateArray: [], |
|
||||
tableSelectedTemplateId: null, |
|
||||
}); |
|
||||
|
|
||||
const dialog = { |
|
||||
buttons: [ |
|
||||
{ |
|
||||
icon: 'save', |
|
||||
label: '确定', |
|
||||
click: async () => { |
|
||||
const validate = await formRef.value.validate(); |
|
||||
if (validate) { |
|
||||
const formData = formRef.value.getData(); |
|
||||
let flag = false; |
|
||||
Object.keys(formData).forEach((item) => { |
|
||||
if (!Tools.isEmpty(formData[item])) { |
|
||||
flag = true; |
|
||||
} |
|
||||
}); |
|
||||
if (flag) { |
|
||||
emit('setForEachParams', formData); |
|
||||
dialogRef.value.hide(); |
|
||||
} else { |
|
||||
NotifyManager.warn('未配置任何属性'); |
|
||||
} |
|
||||
} |
|
||||
}, |
|
||||
}, |
|
||||
], |
|
||||
}; |
|
||||
const templateParamsGrid = { |
|
||||
queryFormFields: [ |
|
||||
{ label: '变量编码', name: 'paramsCode', type: 'w-text' }, |
|
||||
{ label: '变量名称', name: 'paramsName', type: 'w-text' }, |
|
||||
{ |
|
||||
label: '所属模板', |
|
||||
name: 'reportExcelTemplate', |
|
||||
type: 'w-select', |
|
||||
clearable: true, |
|
||||
queryOperator: 'equals', |
|
||||
options: [], |
|
||||
}, |
|
||||
{ |
|
||||
label: '变量类型', |
|
||||
name: 'paramsType', |
|
||||
type: 'w-select', |
|
||||
queryOperator: 'equals', |
|
||||
options: [ |
|
||||
{ label: '单值', value: 'SING' }, |
|
||||
{ label: '列表', value: 'LIST' }, |
|
||||
], |
|
||||
}, |
|
||||
], |
|
||||
toolbarActions: ['query', 'reset', 'separator'], |
|
||||
columns: [ |
|
||||
{ name: 'paramsCode', label: '变量编码' }, |
|
||||
{ name: 'paramsName', label: '变量名称' }, |
|
||||
{ |
|
||||
name: 'paramsType', |
|
||||
label: '变量类型', |
|
||||
format: (val) => { |
|
||||
if (val === 'SING') { |
|
||||
return '单值'; |
|
||||
} else if (val === 'LIST') { |
|
||||
return '列表'; |
|
||||
} else { |
|
||||
return val; |
|
||||
} |
|
||||
}, |
|
||||
}, |
|
||||
{ |
|
||||
name: 'paramsIsCommon', |
|
||||
label: '变量是否通用', |
|
||||
format: (val) => { |
|
||||
if (val === true) { |
|
||||
return '所有模板均可使用'; |
|
||||
} else if (val === false) { |
|
||||
return '指定模板可使用'; |
|
||||
} else { |
|
||||
return val; |
|
||||
} |
|
||||
}, |
|
||||
}, |
|
||||
{ name: 'reportExcelTemplateName', label: '所属模板名称' }, |
|
||||
{ name: 'lastModifier', label: '最后修改人' }, |
|
||||
{ name: 'lastModifyDate', label: '最后修改时间' }, |
|
||||
], |
|
||||
}; |
|
||||
const form = { |
|
||||
fields: [ |
|
||||
{ |
|
||||
label: '循环的列表名', |
|
||||
name: 'listName', |
|
||||
type: 'w-grid-select', |
|
||||
requiredIf: true, |
|
||||
displayValue: 'paramsName', |
|
||||
grid: { |
|
||||
title: '模板变量列表', |
|
||||
primaryKey: 'paramsCode', |
|
||||
sortNo: true, |
|
||||
dense: true, |
|
||||
dataUrl: Environment.apiContextPath('api/excel/template/params'), |
|
||||
columns: templateParamsGrid.columns, |
|
||||
queryFormFields: templateParamsGrid.queryFormFields, |
|
||||
queryFormColsNum: 2, |
|
||||
queryFormRowNum: 2, |
|
||||
sortBy: ['-lastModifyDate'], |
|
||||
}, |
|
||||
}, |
|
||||
{ label: '循环列表中一行数据占几行', name: 'dataRowNum', type: 'w-number' }, |
|
||||
{ |
|
||||
label: '单元格值相等时字体加粗', |
|
||||
name: 'fontWeight', |
|
||||
type: 'w-text', |
|
||||
hint: `当值匹配上任意值字体加粗,英文逗号分隔。示例:合计,不适用`, |
|
||||
}, |
|
||||
{ |
|
||||
label: '单元格值相等时字体加粗-该行后续列都加粗', |
|
||||
name: 'fontWeightRow', |
|
||||
type: 'w-select', |
|
||||
options: [ |
|
||||
{ label: '是', value: 'true' }, |
|
||||
{ label: '否', value: 'false' }, |
|
||||
], |
|
||||
}, |
|
||||
{ |
|
||||
label: '单元格根据值设置背景色', |
|
||||
name: 'cellBgColor', |
|
||||
type: 'w-text', |
|
||||
hint: `当值匹配上时设置对应的背景色,等号左边为单元格值,右边为设置的背景色,位置需对应,英文逗号分隔。示例:不达标,达标,其他=#f44336,#2196f3,#bdbdbd`, |
|
||||
}, |
|
||||
{ |
|
||||
label: '单元格根据值设置背景色-该行后续列都设置相同背景色', |
|
||||
name: 'cellBgColorRow', |
|
||||
type: 'w-select', |
|
||||
options: [ |
|
||||
{ label: '是', value: 'true' }, |
|
||||
{ label: '否', value: 'false' }, |
|
||||
], |
|
||||
}, |
|
||||
{ |
|
||||
label: '单元格码值转换', |
|
||||
name: 'cellValueTransformed', |
|
||||
type: 'w-text', |
|
||||
hint: `当值匹配上时显示转换后的值,等号左边为原始值,右边为转换值,位置需对应,英文逗号分隔。示例:1,2=年,月 转换为空示例:-999=NULL`, |
|
||||
}, |
|
||||
{ label: '单元格批注', name: 'cellComment', type: 'w-textarea', rows: 2 }, |
|
||||
], |
|
||||
}; |
|
||||
|
|
||||
const listParamsDialog = { |
|
||||
buttons: [ |
|
||||
{ |
|
||||
icon: 'save', |
|
||||
label: '确定', |
|
||||
click: () => { |
|
||||
const tableSelected = templateParamsGridRef.value.getSelectedRows(); |
|
||||
if (!tableSelected || tableSelected.length === 0) { |
|
||||
NotifyManager.info('请选择模板变量'); |
|
||||
return; |
|
||||
} |
|
||||
formRef.value.setFieldValue('listName', tableSelected[0].paramsCode); |
|
||||
listParamsDialogRef.value.hide(); |
|
||||
}, |
|
||||
}, |
|
||||
], |
|
||||
}; |
|
||||
|
|
||||
const getTemplateListFun = async () => { |
|
||||
const resp = await axios.get(Environment.apiContextPath('api/excel/template?pageable=false')); |
|
||||
if (resp.data?.content) { |
|
||||
const options = <any>[]; |
|
||||
resp.data.content.forEach((item) => { |
|
||||
options.push({ label: item.templateName, value: item.id }); |
|
||||
}); |
|
||||
state.templateArray = options; |
|
||||
templateParamsGridRef.value.getQueryForm().getFields()['reportExcelTemplate'].options = options; |
|
||||
|
|
||||
setTimeout(() => { |
|
||||
if (state.tableSelectedTemplateId) { |
|
||||
templateParamsGridRef.value.getQueryForm().setFieldValue('reportExcelTemplate', state.tableSelectedTemplateId); |
|
||||
templateParamsGridRef.value.getQueryForm().setFieldValue('paramsType', 'LIST'); |
|
||||
} |
|
||||
templateParamsGridRef.value.refresh(); |
|
||||
}, 100); |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
const show = (templateId, data) => { |
|
||||
dialogRef.value.show(); |
|
||||
if (templateId) { |
|
||||
state.tableSelectedTemplateId = templateId; |
|
||||
} else { |
|
||||
state.tableSelectedTemplateId = null; |
|
||||
} |
|
||||
nextTick(() => { |
|
||||
if (data) { |
|
||||
formRef.value.setData(data); |
|
||||
} |
|
||||
}); |
|
||||
}; |
|
||||
const hide = () => { |
|
||||
dialogRef.value.hide(); |
|
||||
}; |
|
||||
|
|
||||
defineExpose({ |
|
||||
show, |
|
||||
hide, |
|
||||
}); |
|
||||
</script> |
|
@ -1,339 +0,0 @@ |
|||||
<template> |
|
||||
<q-card ref="cardRef" flat bordered :style="cardHeightComponent"> |
|
||||
<q-card-section class="p-2.5"> |
|
||||
<div class="flex gap-2"> |
|
||||
<div class="grow"> |
|
||||
<q-file v-model="impFile" label="导入Excel文件" outlined dense accept=".xlsx,.xls" @update:model-value="loadExcel($event)"> |
|
||||
<template #append> |
|
||||
<q-icon name="attachment" /> |
|
||||
</template> |
|
||||
</q-file> |
|
||||
</div> |
|
||||
<div class="flex flex-none"> |
|
||||
<q-btn label="选取变量" :icon="PlatformIconEnum.选取变量" @click="selectParams"></q-btn> |
|
||||
</div> |
|
||||
<div class="flex flex-none"> |
|
||||
<q-btn-dropdown :icon="PlatformIconEnum.设置" label="循环属性配置" unelevated outline> |
|
||||
<q-list> |
|
||||
<q-item v-close-popup clickable> |
|
||||
<q-item-section> |
|
||||
<q-item-label @click="openConfigDialog('main')"><q-icon :name="PlatformIconEnum.更多查询"></q-icon> 整体配置(首列)</q-item-label> |
|
||||
</q-item-section> |
|
||||
</q-item> |
|
||||
<q-item v-close-popup clickable> |
|
||||
<q-item-section> |
|
||||
<q-item-label @click="openConfigDialog('column')"><q-icon :name="PlatformIconEnum.更多查询"></q-icon> 列配置(非首列)</q-item-label> |
|
||||
</q-item-section> |
|
||||
</q-item> |
|
||||
</q-list> |
|
||||
</q-btn-dropdown> |
|
||||
</div> |
|
||||
<div class="flex flex-none"> |
|
||||
<q-btn label="保存并关闭" :icon="PlatformIconEnum.保存" @click="save"></q-btn> |
|
||||
</div> |
|
||||
<div class="flex flex-none"> |
|
||||
<q-btn label="导出文件" :icon="PlatformIconEnum.下载" @click="downloadExcel"></q-btn> |
|
||||
</div> |
|
||||
</div> |
|
||||
</q-card-section> |
|
||||
<TemplateParamsSelectDialog ref="paramsSelectDialogRef" @set-params="setParams"></TemplateParamsSelectDialog> |
|
||||
<TemplateSetForEachParamsDialog ref="setForEachParamsDialogRef" @set-for-each-params="setForEachParams"></TemplateSetForEachParamsDialog> |
|
||||
<TemplateSetColumnParamsDialog ref="setColumnParamsDialogRef" @set-for-each-params="setForEachParams"></TemplateSetColumnParamsDialog> |
|
||||
<div id="luckysheet"></div> |
|
||||
</q-card> |
|
||||
</template> |
|
||||
|
|
||||
<script setup lang="ts"> |
|
||||
import { ref, onMounted, computed, reactive } from 'vue'; |
|
||||
import { useRoute, onBeforeRouteUpdate } from 'vue-router'; |
|
||||
import LuckyExcel from 'luckyexcel'; |
|
||||
import { exportExcel } from './export'; |
|
||||
import { useQuasar } from 'quasar'; |
|
||||
import { axios, TagViewManager, Environment, PlatformIconEnum, Tools, NotifyManager } from 'platform-core'; |
|
||||
|
|
||||
import TemplateParamsSelectDialog from '@/views/excel_template/TemplateParamsSelectDialog.vue'; |
|
||||
import TemplateSetForEachParamsDialog from '@/views/excel_template/TemplateSetForeachPropsDialog.vue'; |
|
||||
import TemplateSetColumnParamsDialog from '@/views/excel_template/TemplateSetColumnParamsDialog.vue'; |
|
||||
|
|
||||
const gc = Environment.getConfigure(); |
|
||||
const $q = useQuasar(); |
|
||||
const impFile = ref(null); |
|
||||
const paramsSelectDialogRef = ref(); |
|
||||
const setForEachParamsDialogRef = ref(); |
|
||||
const setColumnParamsDialogRef = ref(); |
|
||||
const route = useRoute(); |
|
||||
const cardRef = ref(); |
|
||||
console.info('route------------', route); |
|
||||
|
|
||||
// 路由变更时 |
|
||||
onBeforeRouteUpdate((to, from, next) => { |
|
||||
console.info('to------------', to); |
|
||||
initExcel(to.query.templateId); |
|
||||
next(); |
|
||||
}); |
|
||||
|
|
||||
const state = reactive({ |
|
||||
cardY: 0, |
|
||||
}); |
|
||||
|
|
||||
const cardHeightComponent = computed(() => { |
|
||||
// 浏览器可视区域高度 |
|
||||
const screenHeight = $q.screen.height; |
|
||||
// 系统底部高度(一般用来显示XX版权所有那一层) |
|
||||
const footerHeight = gc.theme.footer.enable ? gc.theme.footer.height : 0; |
|
||||
const cardHeight = screenHeight - footerHeight - state.cardY - 10; |
|
||||
return { |
|
||||
height: cardHeight + 'px', |
|
||||
}; |
|
||||
}); |
|
||||
|
|
||||
const loadExcel = (value) => { |
|
||||
const { name } = value; |
|
||||
const suffixArr = name.split('.'); |
|
||||
const suffix = suffixArr[suffixArr.length - 1]; |
|
||||
if (suffix !== 'xlsx') { |
|
||||
NotifyManager.info('只能导入xlsx格式的Excel文件'); |
|
||||
return; |
|
||||
} |
|
||||
LuckyExcel.transformExcelToLucky(value, (exportJson) => { |
|
||||
if (exportJson.sheets === null || exportJson.sheets.length === 0) { |
|
||||
NotifyManager.info(`只能导入'xlsx'格式的Excel文件`); |
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
window.luckysheet.destroy(); |
|
||||
|
|
||||
const data = [ |
|
||||
{ |
|
||||
...exportJson.sheets[0], |
|
||||
...{ |
|
||||
column: 26, |
|
||||
row: 30, |
|
||||
}, |
|
||||
}, |
|
||||
]; |
|
||||
luckysheetOptions.data = data; |
|
||||
window.luckysheet.create({ |
|
||||
lang: 'zh', |
|
||||
container: 'luckysheet', |
|
||||
showinfobar: false, |
|
||||
showtoolbar: true, // 是否显示工具栏,设置字体,边框,插入这些工具按钮。 |
|
||||
sheetFormulaBar: true, // 是否显示公式栏 |
|
||||
showsheetbar: false, // 是否显示底部sheet页按钮 |
|
||||
data: data, |
|
||||
title: exportJson.info.name, |
|
||||
userInfo: exportJson.info.name.creator, |
|
||||
}); |
|
||||
}); |
|
||||
}; |
|
||||
|
|
||||
const downloadExcel = () => { |
|
||||
// eslint-disable-next-line |
|
||||
exportExcel(luckysheet.getAllSheets(), '下载'); |
|
||||
}; |
|
||||
|
|
||||
const luckysheetData = [ |
|
||||
{ |
|
||||
name: 'Cell', // 工作表名称 |
|
||||
color: '', // 工作表颜色 |
|
||||
index: 0, // 工作表索引 |
|
||||
status: 1, // 激活状态 |
|
||||
order: 0, // 工作表的下标 |
|
||||
hide: 0, // 是否隐藏 |
|
||||
defaultRowHeight: 19, // 自定义行高 |
|
||||
defaultColWidth: 73, // 自定义列宽 |
|
||||
column: 26, |
|
||||
row: 30, |
|
||||
celldata: [], // 初始化使用的单元格数据 |
|
||||
config: { |
|
||||
merge: {}, // 合并单元格 |
|
||||
rowlen: {}, // 表格行高 |
|
||||
columnlen: {}, // 表格列宽 |
|
||||
rowhidden: {}, // 隐藏行 |
|
||||
colhidden: {}, // 隐藏列 |
|
||||
borderInfo: [], // 边框 |
|
||||
authority: {}, // 工作表保护 |
|
||||
}, |
|
||||
scrollLeft: 0, // 左右滚动条位置 |
|
||||
scrollTop: 0, // 上下滚动条位置 |
|
||||
luckysheet_select_save: [], // 选中的区域 |
|
||||
calcChain: [], // 公式链 |
|
||||
isPivotTable: false, // 是否数据透视表 |
|
||||
pivotTable: {}, // 数据透视表设置 |
|
||||
filter_select: {}, // 筛选范围 |
|
||||
filter: null, // 筛选配置 |
|
||||
luckysheet_alternateformat_save: [], // 交替颜色 |
|
||||
luckysheet_alternateformat_save_modelCustom: [], // 自定义交替颜色 |
|
||||
luckysheet_conditionformat_save: {}, // 条件格式 |
|
||||
frozen: {}, // 冻结行列配置 |
|
||||
chart: [], // 图表配置 |
|
||||
zoomRatio: 1, // 缩放比例 |
|
||||
image: [], // 图片 |
|
||||
showGridLines: 1, // 是否显示网格线 |
|
||||
dataVerification: {}, // 数据验证配置 |
|
||||
}, |
|
||||
]; |
|
||||
const luckysheetOptions = { |
|
||||
container: 'luckysheet', // 设定DOM容器的id |
|
||||
lang: 'zh', // 设定表格语言 |
|
||||
title: '测试', // 设定表格名称 |
|
||||
allowEdit: true, // 是否允许编辑 |
|
||||
rowHeaderWidth: 46, // 行标题区域的宽度,如果设置为0,则表示隐藏行标题,也就是表格第一行,A,B,C这行,默认值46 |
|
||||
columnHeaderHeight: 20, // 列标题区域的高度,如果设置为0,则表示隐藏列标题,也就是序号这一行,默认值20 |
|
||||
showtoolbar: true, // 是否显示工具栏,设置字体,边框,插入这些工具按钮。 |
|
||||
showinfobar: false, // 是否显示顶部信息栏,luckysheet的logo,表格名称这一栏。 |
|
||||
userInfo: 'likunming', // 右上角用户信息,若需要展示,必须配合showinfobar使用 |
|
||||
sheetFormulaBar: true, // 是否显示公式栏 |
|
||||
defaultFontSize: 11, // 初始化默认字体大小,默认11 |
|
||||
showsheetbar: false, // 是否显示底部sheet页按钮 |
|
||||
data: luckysheetData, // 表格数据 |
|
||||
}; |
|
||||
const luckySheetEdit = () => { |
|
||||
luckysheetOptions.allowEdit = true; |
|
||||
luckysheetOptions.showtoolbar = true; |
|
||||
luckysheetOptions.sheetFormulaBar = true; |
|
||||
// eslint-disable-next-line |
|
||||
luckysheet.create(luckysheetOptions); |
|
||||
}; |
|
||||
const luckySheetSave = () => { |
|
||||
luckysheetOptions.allowEdit = false; |
|
||||
luckysheetOptions.showtoolbar = false; |
|
||||
luckysheetOptions.sheetFormulaBar = false; |
|
||||
// eslint-disable-next-line |
|
||||
luckysheet.create(luckysheetOptions); |
|
||||
}; |
|
||||
const selectParams = () => { |
|
||||
// eslint-disable-next-line |
|
||||
const selectRange = luckysheet.getRange(); |
|
||||
if (!selectRange || selectRange.length === 0) { |
|
||||
platformNotify($q, '请选择要插入变量的Excel单元格'); |
|
||||
return; |
|
||||
} else if (selectRange && selectRange.length > 1) { |
|
||||
platformNotify($q, '只支持单个选区选取变量'); |
|
||||
return; |
|
||||
} |
|
||||
paramsSelectDialogRef.value.dialogShow(route.query?.templateId); |
|
||||
}; |
|
||||
const setParams = (paramsCode: string | Array<string>) => { |
|
||||
if (typeof paramsCode === 'string') { |
|
||||
// eslint-disable-next-line |
|
||||
let rangeValue = luckysheet.getRangeValue(); |
|
||||
rangeValue[0][0] = { ...rangeValue[0][0], ...{ m: paramsCode, v: paramsCode } }; |
|
||||
// eslint-disable-next-line |
|
||||
luckysheet.setRangeValue(rangeValue); |
|
||||
} else { |
|
||||
// eslint-disable-next-line |
|
||||
const currRange = luckysheet.getRange(); |
|
||||
paramsCode.forEach((item, index) => { |
|
||||
const tmpRangeValue = [[{ m: item, v: item }]]; |
|
||||
const tmp = { |
|
||||
row: [currRange[0].row[0], currRange[0].row[1]], |
|
||||
column: [currRange[0].column[0] + index, currRange[0].column[1] + index], |
|
||||
}; |
|
||||
// eslint-disable-next-line |
|
||||
luckysheet.setRangeValue(tmpRangeValue, { range: tmp }); |
|
||||
}); |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
// eslint-disable-next-line |
|
||||
const psReg = /\@\{(.*)\}\@/; |
|
||||
const openConfigDialog = (configType) => { |
|
||||
// eslint-disable-next-line |
|
||||
const range = luckysheet.getRange(); |
|
||||
// eslint-disable-next-line |
|
||||
const rangeValue = luckysheet.getRangeValue(); |
|
||||
if (!range) { |
|
||||
NotifyManager.info('请选择要配置属性的单元格'); |
|
||||
return; |
|
||||
} else if (range && range.length > 1) { |
|
||||
NotifyManager.info('多个选区无法配置属性,选择单元格既可'); |
|
||||
return; |
|
||||
} |
|
||||
let data = {}; |
|
||||
if (rangeValue[0] && rangeValue[0][0] && rangeValue[0][0].ps && rangeValue[0][0].ps.value) { |
|
||||
let tmp = rangeValue[0][0].ps.value.replaceAll('\n', ''); |
|
||||
data = JSON.parse(psReg.exec(tmp)[1]); |
|
||||
} |
|
||||
if (configType === 'main') { |
|
||||
setForEachParamsDialogRef.value.dialogShow(route.query?.templateId, data); |
|
||||
} else { |
|
||||
setColumnParamsDialogRef.value.dialogShow(data); |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
const setForEachParams = (formData) => { |
|
||||
// eslint-disable-next-line |
|
||||
const range = luckysheet.getRange(); |
|
||||
let tmp = '@{{\n'; |
|
||||
Object.keys(formData).forEach((item) => { |
|
||||
if (!Tools.isEmpty(formData[item])) { |
|
||||
tmp += '"' + item + '"' + ':' + '"' + formData[item] + '"' + ',' + '\n'; |
|
||||
} |
|
||||
}); |
|
||||
tmp = tmp.substring(0, tmp.length - 2); |
|
||||
tmp += '\n}}@'; |
|
||||
// eslint-disable-next-line |
|
||||
luckysheet.insertComment(range[0].row[0], range[0].column[0], tmp); |
|
||||
// 插入批注后调整批注框大小 |
|
||||
luckysheetOptions.data[0].data[range[0].row[0]][range[0].column[0]].ps.width = 300; |
|
||||
luckysheetOptions.data[0].data[range[0].row[0]][range[0].column[0]].ps.height = 150; |
|
||||
luckysheetOptions.data[0].data[range[0].row[0]][range[0].column[0]].ps.isShow = false; |
|
||||
// eslint-disable-next-line |
|
||||
luckysheet.refresh(); |
|
||||
}; |
|
||||
const save = async () => { |
|
||||
// eslint-disable-next-line |
|
||||
if (!luckysheet.getAllSheets() || luckysheet.getAllSheets().length === 0) { |
|
||||
NotifyManager.info('系统异常,未获取到需要保存的Sheet数据') |
|
||||
return; |
|
||||
} |
|
||||
// 覆盖celldata数据缩减传给后端的数据量,该数据仅用以初始化表格,无需保存,初始化时可使用data属性。 |
|
||||
// eslint-disable-next-line |
|
||||
const saveData = { ...luckysheet.getAllSheets()[0], ...{ celldata: [] } }; |
|
||||
// 保存 |
|
||||
let requestParams = { |
|
||||
method: 'POST', |
|
||||
headers: { 'content-type': 'application/json;charset=utf-8;' }, |
|
||||
data: { templateConfig: JSON.stringify(saveData) }, |
|
||||
url: Environment.apiContextPath('api/excel/template/updateConfig/') + route.query.templateId, |
|
||||
}; |
|
||||
const resp = await axios(requestParams).catch((error) => { |
|
||||
console.info('error====', error); |
|
||||
NotifyManager.error('保存失败'); |
|
||||
}); |
|
||||
NotifyManager.error('保存成功') |
|
||||
// 关闭当前页 |
|
||||
// const index = TagViewManager.getTagViews().findIndex((item) => item.fullPath.indexOf(route.query.templateId) > -1); |
|
||||
TagViewManager.removeTagView({ mode: 'current' }); |
|
||||
}; |
|
||||
|
|
||||
const initExcel = async (templateId?: any) => { |
|
||||
if (window.luckysheet) { |
|
||||
window.luckysheet.destroy(); |
|
||||
} |
|
||||
const resp = await axios.get(Environment.apiContextPath('api/excel/template/') + (templateId ?? route.query.templateId)); |
|
||||
if (resp?.data?.templateConfig) { |
|
||||
luckysheetOptions.data = [eval('(' + resp.data.templateConfig + ')')]; |
|
||||
} |
|
||||
// eslint-disable-next-line |
|
||||
luckysheet.create(luckysheetOptions); |
|
||||
}; |
|
||||
|
|
||||
onMounted(async () => { |
|
||||
state.cardY = cardRef.value.$el.getBoundingClientRect()?.y; |
|
||||
initExcel(); |
|
||||
}); |
|
||||
</script> |
|
||||
|
|
||||
<style scoped> |
|
||||
#luckysheet { |
|
||||
margin: 0px; |
|
||||
padding: 0px; |
|
||||
position: absolute; |
|
||||
width: 100%; |
|
||||
left: 0px; |
|
||||
top: 70px; |
|
||||
bottom: 0px; |
|
||||
} |
|
||||
</style> |
|
@ -1,319 +0,0 @@ |
|||||
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) { |
|
||||
// luckysheet:ff(样式), 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 }; |
|
@ -1,27 +0,0 @@ |
|||||
const cellFormatMap = new Map(); |
|
||||
// 纯文本
|
|
||||
cellFormatMap.set('1', { fa: '@', t: 's' }); |
|
||||
// 数字格式-整数
|
|
||||
cellFormatMap.set('2', { fa: '0', t: 'n' }); |
|
||||
// 数字格式-两位小数
|
|
||||
cellFormatMap.set('3', { fa: '0.00', t: 'n' }); |
|
||||
// 数字格式-四位小数
|
|
||||
cellFormatMap.set('4', { fa: '0.0000', t: 'n' }); |
|
||||
// 百分比整数
|
|
||||
cellFormatMap.set('5', { fa: '0%', t: 'n' }); |
|
||||
// 百分比两位小数
|
|
||||
cellFormatMap.set('6', { fa: '0.00%', t: 'n' }); |
|
||||
// 万元两位小数(示例:12万3456.00)
|
|
||||
cellFormatMap.set('7', { fa: 'w0.00', t: 'n' }); |
|
||||
// 千位符整数(示例:1,235)
|
|
||||
cellFormatMap.set('8', { fa: '#,##0', t: 'n' }); |
|
||||
// 千位符两位小数(示例:1,234.56)
|
|
||||
cellFormatMap.set('9', { fa: '#,##0.00', t: 'n' }); |
|
||||
|
|
||||
/** |
|
||||
* 根据下拉框所选值获取单元格格式化对象 |
|
||||
* @param index |
|
||||
*/ |
|
||||
export function getExcelCellFormatObject(index: string) { |
|
||||
return cellFormatMap.get(index); |
|
||||
} |
|
Loading…
Reference in new issue