Commit 07d14cda authored by 何远江's avatar 何远江

修改设置标题逻辑,添加附加信息设置

parent 0aa99b16
...@@ -80,5 +80,7 @@ export const authorityConfig = { ...@@ -80,5 +80,7 @@ export const authorityConfig = {
export const areaMarksColor = { export const areaMarksColor = {
'data': '#65d0ea', 'data': '#65d0ea',
'head': '#34718d', 'head': '#34718d',
'default': '#ffffff' 'default': '#ffffff',
'attch': '#e6ccb2',
'attch_head': '#b08968'
} }
\ No newline at end of file
import type { Recordable } from '@/types/global'
export function chatatABC(n: number) { export function chatatABC(n: number) {
var orda = 'a'.charCodeAt(0) var orda = 'a'.charCodeAt(0)
...@@ -17,21 +19,78 @@ export function chatatABC(n: number) { ...@@ -17,21 +19,78 @@ export function chatatABC(n: number) {
} }
export function getRangetxt(row0: number, row1: number, column0: number, column1: number) { export function getRangetxt(row0: number, row1: number, column0: number, column1: number) {
// let row0 = range["row"][0], row1 = range["row"][1]; // let row0 = range["row"][0], row1 = range["row"][1];
// let column0 = range["column"][0], column1 = range["column"][1]; // let column0 = range["column"][0], column1 = range["column"][1];
if (row0 == null && row1 == null) { if (row0 == null && row1 == null) {
return chatatABC(column0) + ":" + chatatABC(column1); return chatatABC(column0) + ':' + chatatABC(column1)
} else if (column0 == null && column1 == null) {
return row0 + 1 + ':' + (row1 + 1)
} else {
if (column0 == column1 && row0 == row1) {
return chatatABC(column0) + (row0 + 1)
} else {
return chatatABC(column0) + (row0 + 1) + ':' + chatatABC(column1) + (row1 + 1)
} }
else if (column0 == null && column1 == null) { }
return (row0 + 1) + ":" + (row1 + 1); }
export function getRangeState(range: any) {
let rowLen = range.length
let columnLen = range[0].length
let isOneRow = !(rowLen > 1)
let isOneColumn = !(columnLen > 1)
return {
rowLen,
columnLen,
isOneRow,
isOneColumn
}
}
export function handleRangeTitle(range: any, dataArea: Recordable) {
const { isOneColumn, isOneRow, rowLen, columnLen } = getRangeState(range)
const { beginColum, beginRow, endRow, endColum, sheetNum } = dataArea
const titles: Recordable[] = []
let isVertical = false
if (rowLen - 1 === endRow - beginRow && columnLen - 1 !== endColum - beginColum) {
isVertical = true
}
/**
* 横向:以列为单位取值,多值取最后有值单元格
*
* 纵向:以行为单位,多值取最后有值单元格
*/
for (let c = 0; c < (isVertical ? rowLen : columnLen); c++) {
const title = {
title: '',
sheet: sheetNum,
row: 0,
colum: 0
} }
else { for (let r = 0; r < (isVertical ? columnLen : rowLen); r++) {
if (column0 == column1 && row0 == row1) { const cell = isVertical ? range[c][r] : range[r][c]
return chatatABC(column0) + (row0 + 1); let v = ''
} // 如果获取值报错,那么断定单元格值为空,继续执行
else { try {
return chatatABC(column0) + (row0 + 1) + ":" + chatatABC(column1) + (row1 + 1); v = cell.v || cell?.ct?.s.map((itm) => itm.v).join('')
} } catch {}
if (v != '') {
title.title = v.replaceAll(' ', '')
title.colum = +beginColum + (isVertical ? r : c)
title.row = +beginRow + (isVertical ? c : r)
}
// 如果有单元格合并,跳过单元格
if (cell?.mc) {
r += isVertical ? cell.mc.rs - 1 : cell.mc.cs - 1
c += isVertical ? cell.mc.cs - 1 : cell.mc.rs - 1
}
} }
titles.push(title)
}
return titles
} }
...@@ -49,8 +49,16 @@ ...@@ -49,8 +49,16 @@
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="24"> <el-col :span="24">
<el-button type="primary" @click="setAreaMark('data')">设置数据区</el-button> <el-button-group class="mr-2">
<el-button type="primary" @click="setAreaMark('head')">设置标题区</el-button> <el-button type="primary" @click="setAreaMark('data')">设置数据区</el-button>
<el-button type="primary" @click="setAreaMark('head')">设置标题区</el-button>
</el-button-group>
<el-button-group>
<el-button type="primary" @click="setAreaMark('attch')">设置附加信息</el-button>
<el-button type="primary" @click="setAreaMark('attch_head')"
>设置附加标题</el-button
>
</el-button-group>
</el-col> </el-col>
</el-row> </el-row>
</el-form> </el-form>
...@@ -154,6 +162,40 @@ ...@@ -154,6 +162,40 @@
</template> </template>
</vxe-column> </vxe-column>
</vxe-table> </vxe-table>
<template v-if="currentAreaMark.desGroups.length">
<p class="font-bold">附加信息</p>
<vxe-table
:data="currentAreaMark.desGroups"
@cell-click="cellClick"
border
size="mini"
max-height="200"
>
<vxe-column title="附加区域" field="area" width="120">
<template #default="{ row }">
{{ getRangetxt(row.beginRow, row.endRow, row.beginColum, row.endColum) }}
</template>
</vxe-column>
<vxe-column title="附加title" field="area">
<template #default="{ row }">
{{ row.titles[0].title }}
</template>
</vxe-column>
<vxe-column title="操作" field="action" width="80">
<template #default="{ row, $rowIndex }">
<el-link
style="font-size: 12px"
type="danger"
@click.stop="delAttchInfo(row, $rowIndex)"
>删除</el-link
>
</template>
</vxe-column>
</vxe-table>
</template>
<el-button type="primary" size="small" @click="saveAreaMark">保存</el-button> <el-button type="primary" size="small" @click="saveAreaMark">保存</el-button>
<el-button <el-button
v-if="isEditCurrentArea" v-if="isEditCurrentArea"
...@@ -334,7 +376,7 @@ import { ...@@ -334,7 +376,7 @@ import {
removeExcelAreaConnect removeExcelAreaConnect
} from '@/api/excel' } from '@/api/excel'
import type { Recordable } from '@/types/global' import type { Recordable } from '@/types/global'
import { getRangetxt } from '@/utils/excel' import { getRangetxt, handleRangeTitle } from '@/utils/excel'
import type { VxeTableInstance } from 'vxe-table' import type { VxeTableInstance } from 'vxe-table'
import { apiDictFindById, apiDictList } from '@/api/common' import { apiDictFindById, apiDictList } from '@/api/common'
...@@ -472,24 +514,43 @@ const currentAreaMark = reactive<Recordable>({ ...@@ -472,24 +514,43 @@ const currentAreaMark = reactive<Recordable>({
oneself: 'N', oneself: 'N',
checkSelf: 'N', checkSelf: 'N',
checkNumber: 1, checkNumber: 1,
excelAreaTitle: [] excelAreaTitle: [],
desGroups: [],
titleArea: ''
}) })
const isEditCurrentArea = computed(() => !!currentAreaMark.excelAreaId) const isEditCurrentArea = computed(() => !!currentAreaMark.excelAreaId)
const currentTitlesArea = ref<Recordable>([])
const currentAttchInfo = reactive({
sheetNum: '',
beginRow: '',
beginColum: '',
endRow: '',
titles: []
})
// 删除附加信息
const delAttchInfo = (row, index) => {
currentAreaMark.desGroups.splice(index, 1)
// 选中要删除的区域,设置颜色
luckysheet.setRangeShow({
row: [row.beginRow, row.endRow],
column: [row.beginColum, row.endColum]
})
// const currentHeadAreaData = ref([]) luckysheet.setRangeFormat('bg', areaMarksColor['data'])
}
// watch( const resetAttchInfo = () => {
// () => currentAreaMark.excelAreaTitle, Object.assign(currentAttchInfo, {
// (val) => { sheetNum: '',
// currentHeadAreaData.value = val || [] beginRow: '',
// }, beginColum: '',
// { endRow: '',
// deep: true titles: []
// } })
// ) }
// const currentHeadAreaData = computed(() => currentAreaMark?.excelAreaTitle || []) const setAreaMark = async (type: 'data' | 'head' | 'attch' | 'attch_head' = 'data') => {
const setAreaMark = async (type: 'data' | 'head' = 'data') => {
if (type === 'data') { if (type === 'data') {
/** /**
* 判断是否有未保存的区域 * 判断是否有未保存的区域
...@@ -541,7 +602,7 @@ const setAreaMark = async (type: 'data' | 'head' = 'data') => { ...@@ -541,7 +602,7 @@ const setAreaMark = async (type: 'data' | 'head' = 'data') => {
'checkSelf', 'checkSelf',
'checkNumber' 'checkNumber'
]) ])
} else { } else if (type === 'head') {
if (currentAreaMark.excelAreaId) { if (currentAreaMark.excelAreaId) {
return ElMessage.error('请先保存或取消正在修改的数据区域!') return ElMessage.error('请先保存或取消正在修改的数据区域!')
} }
...@@ -558,70 +619,61 @@ const setAreaMark = async (type: 'data' | 'head' = 'data') => { ...@@ -558,70 +619,61 @@ const setAreaMark = async (type: 'data' | 'head' = 'data') => {
* 判断选择的 head区域 是否在数据区域 内部 * 判断选择的 head区域 是否在数据区域 内部
* 判断是否有重复的单元格添加,如有重复无需添加此单元格 * 判断是否有重复的单元格添加,如有重复无需添加此单元格
*/ */
const result: Recordable[] = []
const rangeData = luckysheet.getRangeValue() const rangeData = luckysheet.getRangeValue()
console.log('rangeData', rangeData)
// return const titles = handleRangeTitle(rangeData, unref(formState))
const { beginColum, beginRow, endColum, endRow } = formState as Recordable console.log('titles', titles)
const { beginColum: bc, beginRow: br, endColum: ec, endRow: er } = currentAreaMark
currentTitlesArea.value.push({
// 是否是纵向 excelAreaId: '',
let isVertical = rangeData.length > 1 excelAreaNicname: currentAreaMark.excelAreaNicname,
// if (!isRangeSide(unref(currentAreaMark), unref(formState))) { sr: formState.beginRow,
// return ElMessage.error('请选择区域边缘作为标题!') sc: formState.beginColum,
// } er: formState.endRow,
ec: formState.endColum
if (isVertical) { })
for (let r = 0; r < rangeData.length; r++) {
const item = rangeData[r][0]
const title = item.v || item.ct.s.map((itm) => itm.v).join('')
result.push({
title: title.replaceAll(' ', ''),
sheet: formState.sheetNum,
row: +beginRow + r,
colum: beginColum
})
// 如果有合并的,跳过合并单元格个数
if (item.mc) {
r += item.mc.rs - 1
}
}
} else {
// // 如果只有一列,只能是头部或者尾部
for (let c = 0; c < rangeData[0].length; c++) {
const item = rangeData[0][c]
const title = item.v || item.ct.s.map((itm) => itm.v).join('')
result.push({
title: title.replaceAll(' ', ''),
sheet: formState.sheetNum,
row: beginRow,
colum: +beginColum + c
})
// 如果有合并的,跳过合并单元格个数
if (item.mc) {
c += item.mc.cs - 1
}
}
}
// 清除之前的title颜色
// resetCurrentHeadArea(() => {
// luckysheet.setRangeShow({
// row: [beginRow, endRow],
// column: [beginColum, endColum]
// })
// // currentAreaMark.excelAreaTitle = result
// })
// 合并组装的表头区域数据 // 合并组装的表头区域数据
if (currentAreaMark.excelAreaTitle?.length > 0) { if (currentAreaMark.excelAreaTitle?.length > 0) {
const arr = [...result, ...unref(currentAreaMark.excelAreaTitle)] const arr = [...titles, ...unref(currentAreaMark.excelAreaTitle)]
// 合并,去重 // 合并,去重
currentAreaMark.excelAreaTitle = uniqArrayObject(arr) currentAreaMark.excelAreaTitle = uniqArrayObject(arr)
} else { } else {
currentAreaMark.excelAreaTitle = result currentAreaMark.excelAreaTitle = titles
} }
} else if (type === 'attch') {
// 是否设置数据区
if (!currentAreaMark.excelAreaNicname) {
return ElMessage.error('请先设置数据区!')
}
const area = {
sheetNum: formState.sheetNum,
beginRow: formState.beginRow,
beginColum: formState.beginColum,
endRow: formState.endRow,
endColum: formState.endColum,
titles: []
}
Object.assign(currentAttchInfo, area)
} else if (type === 'attch_head') {
// 验证是否在附加区域
// 验证是否设置附加区域
if (currentAttchInfo.beginRow == '') {
return ElMessage.error('请先设置附加信息区域!')
}
const res = {}
const rangeData = luckysheet.getRangeValue()
const titles = handleRangeTitle(rangeData, unref(currentAttchInfo))
Object.assign(res, currentAttchInfo, { titles })
// 设置完title 直接添加
currentAreaMark.desGroups.push(res)
// 重置附加信息区域
resetAttchInfo()
} }
function uniqArrayObject(arr = []) { function uniqArrayObject(arr = []) {
...@@ -649,28 +701,6 @@ const setAreaMark = async (type: 'data' | 'head' = 'data') => { ...@@ -649,28 +701,6 @@ const setAreaMark = async (type: 'data' | 'head' = 'data') => {
}, 100) }, 100)
} }
const isRangeSide = (range, insideRage) => {
const { beginColum, beginRow, endColum, endRow } = range
const { beginColum: bc, beginRow: br, endColum: ec, endRow: er } = insideRage
const sides = []
// 上
sides.push({ br: beginRow, er: beginRow, bc: beginColum, ec: endColum })
// 右
sides.push({ br: beginRow, er: endRow, bc: endColum, ec: endColum })
//下
sides.push({ br: endRow, er: endRow, bc: beginColum, ec: endColum })
// 左
sides.push({ br: beginRow, er: endRow, bc: beginColum, ec: beginColum })
const side = { br, bc, er, ec }
console.log('isRangeside', side, sides)
return !!sides.filter((item) => {
return item.bc == bc && item.br == br && item.ec == ec && item.er == er
}).length
}
const resetCurrentAreaState = (isedit: boolean = false) => { const resetCurrentAreaState = (isedit: boolean = false) => {
// 重置 其他属性 // 重置 其他属性
const tmp: Recordable = { const tmp: Recordable = {
...@@ -682,11 +712,14 @@ const resetCurrentAreaState = (isedit: boolean = false) => { ...@@ -682,11 +712,14 @@ const resetCurrentAreaState = (isedit: boolean = false) => {
excelAreaType: '', excelAreaType: '',
excelAreaNicname: '', excelAreaNicname: '',
excelAreaTitle: [], excelAreaTitle: [],
desGroups: [],
titleArea: '',
oneself: 'N', oneself: 'N',
checkSelf: 'N', checkSelf: 'N',
checkNumber: '' checkNumber: ''
} }
isedit && (tmp.excelAreaId = '') isedit && (tmp.excelAreaId = '')
currentTitlesArea.value = []
Object.assign(currentAreaMark, tmp) Object.assign(currentAreaMark, tmp)
} }
const resetCurrentArea = (fn?: Function) => { const resetCurrentArea = (fn?: Function) => {
...@@ -706,27 +739,10 @@ const resetCurrentArea = (fn?: Function) => { ...@@ -706,27 +739,10 @@ const resetCurrentArea = (fn?: Function) => {
} }
) )
} }
const resetCurrentHeadArea = (cb: any) => {
// 清除标题区域颜色 -> 设置成数据区域颜色
luckysheet.setRangeShow(
{
row: [currentAreaMark.beginRow, currentAreaMark.endRow],
column: [currentAreaMark.beginColum, currentAreaMark.endColum]
},
{
show: false,
success: () => {
luckysheet.setRangeFormat('bg', areaMarksColor['data'])
// 删除 excelAreaTitle 属性
delete currentAreaMark.excelAreaTitle
cb && cb()
}
}
)
}
const saveAreaMark = async () => { const saveAreaMark = async () => {
currentAreaMark.fileId = getFileInfo.value.orderFileId currentAreaMark.fileId = getFileInfo.value.orderFileId
currentAreaMark.titleArea = JSON.stringify(unref(currentTitlesArea))
// 如果有id 调用修改,否则调用新增 // 如果有id 调用修改,否则调用新增
const isEdit = !!currentAreaMark.excelAreaId const isEdit = !!currentAreaMark.excelAreaId
const { data } = isEdit const { data } = isEdit
...@@ -743,6 +759,7 @@ const saveAreaMark = async () => { ...@@ -743,6 +759,7 @@ const saveAreaMark = async () => {
} }
ElMessage.success('操作成功!') ElMessage.success('操作成功!')
resetCurrentAreaState(true) resetCurrentAreaState(true)
resetAttchInfo()
} }
const cachAreaMark = reactive<Recordable>({}) const cachAreaMark = reactive<Recordable>({})
...@@ -802,15 +819,13 @@ const toModify = (row) => { ...@@ -802,15 +819,13 @@ const toModify = (row) => {
Object.assign(cachAreaMark, cloneDeep(row)) Object.assign(cachAreaMark, cloneDeep(row))
Object.assign(currentAreaMark, row) Object.assign(currentAreaMark, row)
currentTitlesArea.value = JSON.parse(currentAreaMark.titleArea)
} }
const queryArea = async () => { const queryArea = async () => {
const { data } = await getExcelAreaByFileId(getFileInfo.value.orderFileId) const { data } = await getExcelAreaByFileId(getFileInfo.value.orderFileId)
data.result.forEach((item: any) => locaExcelAreaMarks[item.sheetNum || 0].push(item)) data.result.forEach((item: any) => locaExcelAreaMarks[item.sheetNum || 0].push(item))
} }
const toModifyConnect = (row: any) => {
Object.assign(currentConnectInfo, row)
connectVisible.value = true
}
const confirmConnect = () => { const confirmConnect = () => {
/** /**
* 1. 验证是否选择了要关联的title * 1. 验证是否选择了要关联的title
...@@ -998,88 +1013,92 @@ const loadExcel = () => { ...@@ -998,88 +1013,92 @@ const loadExcel = () => {
}, },
sheetActivate: (index: any) => { sheetActivate: (index: any) => {
const sheet = luckysheet.getSheet({ index }) const sheet = luckysheet.getSheet({ index })
if (!!isSetSheetMark.value[sheet.order]) { setSheetAreaMark(sheet)
return
}
isSetSheetMark.value[sheet.order] = true
console.log(isSetSheetMark, locaExcelAreaMarks)
if (locaExcelAreaMarks[sheet.order].length) {
locaExcelAreaMarks[sheet.order].forEach((item: any) => {
// 设置数据区标记
setTimeout(() => {
luckysheet.menuButton.customUpdateFormat(
null,
'bg',
areaMarksColor['data'],
item.beginRow,
item.endRow,
item.beginColum,
item.endColum,
false
)
}, 50)
if (item.excelAreaTitle.length) {
item.excelAreaTitle.forEach((cell: any) => {
// 设置数据区head标记
setTimeout(() => {
luckysheet.menuButton.customUpdateFormat(
null,
'bg',
areaMarksColor['head'],
cell.row,
cell.row,
cell.colum,
cell.colum,
false
)
}, 50)
})
}
})
}
}, },
workbookCreateAfter: () => { workbookCreateAfter: () => {
// 修改当前sheet 已经标记 const sheet = luckysheet.getSheet()
isSetSheetMark.value[0] = true setSheetAreaMark(sheet)
}
}
})
}
)
}
// 判断本地是否有第一个sheet页的标记 const setSheetAreaMark = (sheet: any) => {
if (locaExcelAreaMarks[0].length) { if (!!isSetSheetMark.value[sheet.order]) {
locaExcelAreaMarks[0].forEach((item: any) => { return
// 设置数据区标记 }
// 修改当前sheet 已经标记
isSetSheetMark.value[sheet.order] = true
// 判断本地是否记有第一个sheet页的标
if (locaExcelAreaMarks[sheet.order].length) {
locaExcelAreaMarks[sheet.order].forEach((item: any) => {
// 设置数据区标记
setTimeout(() => {
luckysheet.menuButton.customUpdateFormat(
null,
'bg',
areaMarksColor['data'],
item.beginRow,
item.endRow,
item.beginColum,
item.endColum,
false
)
}, 50)
if (item.excelAreaTitle.length) {
const areas = JSON.parse(item.titleArea)
areas.forEach((area: any) => {
setTimeout(() => {
luckysheet.menuButton.customUpdateFormat(
null,
'bg',
areaMarksColor['head'],
area.sr,
area.er,
area.sc,
area.ec,
false
)
}, 50)
})
}
if (item.desGroups.length) {
item.desGroups.forEach((area) => {
setTimeout(() => {
luckysheet.menuButton.customUpdateFormat(
null,
'bg',
areaMarksColor['attch'],
area.beginRow,
area.endRow,
area.beginColum,
area.endColum,
false
)
}, 50)
if (area.titles.length) {
area.titles.forEach((a) => {
setTimeout(() => {
luckysheet.menuButton.customUpdateFormat( luckysheet.menuButton.customUpdateFormat(
null, null,
'bg', 'bg',
areaMarksColor['data'], areaMarksColor['attch_head'],
item.beginRow, a.row,
item.endRow, a.row,
item.beginColum, a.colum,
item.endColum, a.colum,
false false
) )
if (item.excelAreaTitle.length) { }, 50)
item.excelAreaTitle.forEach((cell: any) => { })
// 设置数据区head标记
// luckysheet.setCellValue()
luckysheet.menuButton.customUpdateFormat(
null,
'bg',
areaMarksColor['head'],
cell.row,
cell.row,
cell.colum,
cell.colum,
false
)
})
}
})
}
} }
} })
}) }
} })
) }
} }
const queryDict = async (code: string) => { const queryDict = async (code: string) => {
......
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