Commit d32ea405 authored by 高滢's avatar 高滢

feat(预制数据管理): excel数据回显

parent b2035663
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
:action="uploadFileUrl" :action="uploadFileUrl"
v-if="!disabled" v-if="!disabled"
:before-upload="handleBeforeUpload" :before-upload="handleBeforeUpload"
:on-change="handleFileChange"
:file-list="fileList" :file-list="fileList"
:limit="limit" :limit="limit"
:on-error="handleUploadError" :on-error="handleUploadError"
...@@ -61,9 +62,15 @@ ...@@ -61,9 +62,15 @@
<script setup> <script setup>
import { getToken } from '@/utils/auth' import { getToken } from '@/utils/auth'
import * as XLSX from "xlsx";
const props = defineProps({ const props = defineProps({
modelValue: [String, Object, Array], modelValue: [String, Object, Array],
// 是否需要获取Excel 中的数据
isExcelData: {
type: Boolean,
default: false
},
// 数量限制 // 数量限制
limit: { limit: {
type: Number, type: Number,
...@@ -97,7 +104,7 @@ const props = defineProps({ ...@@ -97,7 +104,7 @@ const props = defineProps({
}) })
const { proxy } = getCurrentInstance() const { proxy } = getCurrentInstance()
const emit = defineEmits() const emit = defineEmits(['getExcelData'])
const number = ref(0) const number = ref(0)
const uploadList = ref([]) const uploadList = ref([])
const uploadFileUrl = ref(import.meta.env.VITE_APP_BASE_API + '/file/upload') // 上传文件服务器地址 const uploadFileUrl = ref(import.meta.env.VITE_APP_BASE_API + '/file/upload') // 上传文件服务器地址
...@@ -129,7 +136,9 @@ watch( ...@@ -129,7 +136,9 @@ watch(
}, },
{ deep: true, immediate: true }, { deep: true, immediate: true },
) )
// function handleFileChange(file){
//
// }
// 上传前校检格式和大小 // 上传前校检格式和大小
function handleBeforeUpload(file) { function handleBeforeUpload(file) {
// 校检文件类型 // 校检文件类型
...@@ -176,6 +185,13 @@ function handleUploadError(err) { ...@@ -176,6 +185,13 @@ function handleUploadError(err) {
function handleUploadSuccess(res, file) { function handleUploadSuccess(res, file) {
if (res.code === 200) { if (res.code === 200) {
uploadList.value.push({ name: res.data.url, url: res.data.url }) uploadList.value.push({ name: res.data.url, url: res.data.url })
if(props.isExcelData){
readExcel(file.raw).then(res=>{
const jsonData = JSON.stringify(res);
// 将 JSON 数据传递给父组件
emit('getExcelData', jsonData);
})
}
uploadedSuccessfully() uploadedSuccessfully()
} else { } else {
number.value-- number.value--
...@@ -185,7 +201,39 @@ function handleUploadSuccess(res, file) { ...@@ -185,7 +201,39 @@ function handleUploadSuccess(res, file) {
uploadedSuccessfully() uploadedSuccessfully()
} }
} }
const readExcel = (file) => {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = (e) => {
try {
const data = e.target.result;
const workbook = XLSX.read(data, { type: 'array' });
const firstSheetName = workbook.SheetNames[0];
const worksheet = workbook.Sheets[firstSheetName];
// 关键修改:使用 sheet_to_json 的 header: 1 选项直接获取二维数组
const jsonData = XLSX.utils.sheet_to_json(worksheet, {
header: 1, // 生成二维数组
defval: "", // 空单元格用空字符串填充
blankrows: false // 不包含完全空的行
});
// 过滤掉空行(行的所有单元格都为空)
const filteredData = jsonData.filter(row =>
row.some(cell => cell !== "")
);
resolve(filteredData);
} catch (error) {
reject(error);
}
};
reader.onerror = (error) => reject(error);
reader.readAsArrayBuffer(file);
});
};
// 删除文件 // 删除文件
function handleDelete(index) { function handleDelete(index) {
fileList.value.splice(index, 1) fileList.value.splice(index, 1)
......
...@@ -25,7 +25,39 @@ ...@@ -25,7 +25,39 @@
</el-form> </el-form>
</div> </div>
<div> <div>
EXCEL <table border="1" cellspacing="0" cellpadding="5" style="border-collapse: collapse; width: 100%;">
<!-- 第一行表头 -->
<tr>
<template v-for="(item, index) in excelData[0]" :key="index">
<th
v-if="shouldShowFirstHeaderCell(index)"
:colspan="getFirstHeaderColspan(index)"
:rowspan="getFirstHeaderRowspan(index)"
>
{{ excelData[0][index] }}
</th>
</template>
</tr>
<!-- 第二行表头 -->
<tr>
<template v-for="(item, index) in excelData[1]" :key="'header2-' + index">
<th
v-if="shouldShowSecondHeaderCell(index)"
:rowspan="1"
>
{{ item }}
</th>
</template>
</tr>
<!-- 数据行 -->
<tr v-for="(row, rowIndex) in excelData.slice(2)" :key="'row-' + rowIndex">
<td v-for="(cell, cellIndex) in row" :key="'cell-' + rowIndex + '-' + cellIndex">
{{ cell }}
</td>
</tr>
</table>
</div> </div>
</div> </div>
</template> </template>
...@@ -34,17 +66,67 @@ import {getPreset} from "@/api/control/preset.js"; ...@@ -34,17 +66,67 @@ import {getPreset} from "@/api/control/preset.js";
import {onMounted} from "vue"; import {onMounted} from "vue";
import {useRouter} from "vue-router"; import {useRouter} from "vue-router";
const router = useRouter(); const router = useRouter();
let contentData = reactive({}) const contentData = ref({
remark: "",
relatedTemplateName: "",
relatedFormName: "",
excelData: ""
})
const excelData = ref([])
function getContentData(id){ function getContentData(id){
getPreset(id).then(res => { getPreset(id).then(res => {
contentData = res.data contentData.value = res.data
if( res.data.excelData){
excelData.value = JSON.parse( res.data.excelData)
}
}) })
} }
onMounted(() => { getContentData(router.currentRoute.value.query.id)
console.log('111',router.currentRoute.value.query.id) // 判断第一行表头单元格是否需要显示
const id = router.currentRoute.value.query.id function shouldShowFirstHeaderCell(index) {
getContentData(id) // 如果是第一个单元格,总是显示
}) if (index === 0) return true;
// 如果当前单元格不为空,显示
if (this.excelData[0][index] !== '') return true;
// 如果当前单元格为空,但前一个单元格不为空,不显示(因为会被前一个单元格合并)
if (this.excelData[0][index] === '' && this.excelData[0][index - 1] !== '') return false;
// 如果当前单元格为空,且前一个单元格也为空,显示(可能是连续空单元格中的第一个)
return true;
}
// 获取第一行表头的colspan值
function getFirstHeaderColspan(index) {
// 如果当前单元格为空,不需要合并(由前一个非空单元格处理合并)
if (this.excelData[0][index] === '') return 1;
// 计算后面连续空单元格的数量
let colspan = 1;
for (let i = index + 1; i < this.excelData[0].length; i++) {
if (this.excelData[0][i] === '') {
colspan++;
} else {
break;
}
}
return colspan;
}
// 获取第一行表头的rowspan值
function getFirstHeaderRowspan(index) {
// 如果第二行对应单元格为空,则合并两行
if (this.excelData[1][index] === '') return 2;
return 1;
}
// 判断第二行表头单元格是否需要显示
function shouldShowSecondHeaderCell(index) {
// 如果第二行单元格不为空,显示
return this.excelData[1][index] !== '';
}
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
......
...@@ -144,7 +144,7 @@ ...@@ -144,7 +144,7 @@
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="上传文件" prop="file"> <el-form-item label="上传文件" prop="file">
<FileUpload ref="upload" v-model="form.fileUrl" :modelValue="form.fileUrl" :limit="1" :fileType="['xls', 'xlsx']" :file-size="30" other-tips="请先下载模板填好数据再上传"/> <FileUpload ref="upload" :is-excel-data="true" v-model="form.fileUrl" :modelValue="form.fileUrl" :limit="1" :fileType="['xls', 'xlsx']" :file-size="30" other-tips="请先下载模板填好数据再上传" @getExcelData="getExcelData"/>
<el-button type="text" :disabled="form.relatedFormId==''||form.relatedFormId==null" @click="downloadTemplate">点击下载数据内容模板</el-button> <el-button type="text" :disabled="form.relatedFormId==''||form.relatedFormId==null" @click="downloadTemplate">点击下载数据内容模板</el-button>
</el-form-item> </el-form-item>
<el-form-item label="备注" prop="remark"> <el-form-item label="备注" prop="remark">
...@@ -340,6 +340,9 @@ function handleExport() { ...@@ -340,6 +340,9 @@ function handleExport() {
} }
getList(); getList();
function getExcelData(data) {
form.value.excelData = data
}
function downloadTemplate(){ function downloadTemplate(){
proxy.download('/control/preset/downloadTemplate', { proxy.download('/control/preset/downloadTemplate', {
formId: form.value.relatedFormId,fillMethod:'整行' formId: form.value.relatedFormId,fillMethod:'整行'
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment