|
@@ -30,9 +30,10 @@
|
|
|
<el-tooltip :open-delay="400">
|
|
|
<div slot="content">
|
|
|
<p class="hint-message">1、新增指标:在预设好的指标列下输入指标名称、单位、数值并保存;</p>
|
|
|
- <p class="hint-message">2、新增日期:在第一列选择日期或插入日期行(需复制已有日期格式)输入数值并保存;</p>
|
|
|
- <p class="hint-message">3、删除指标:清空该指标下所有数据并保存,请勿直接删除指标列;</p>
|
|
|
+ <p class="hint-message">2、新增日期:在第一列选择日期或插入日期行(需复制已有日期格式)输入数值并保存;</p>
|
|
|
+ <p class="hint-message">3、清除指标:清空该指标下所有数据并保存,该操作不会删除指标,仅清除指标数据,请勿直接删除指标列;</p>
|
|
|
<p class="hint-message">4、删除日期:清空该日期对应所有数据并保存,请勿直接删除日期行;</p>
|
|
|
+ <p class="hint-message">5、指标名称编辑、单位编辑、频度编辑、指标删除等操作请在“手工指标列表”中完成;</p>
|
|
|
</div>
|
|
|
<div class="instruction-hint" >
|
|
|
<span>使用说明</span>
|
|
@@ -51,105 +52,101 @@ import EventBus from '@/api/bus.js'
|
|
|
export default {
|
|
|
name:'onlineExcelCopy',
|
|
|
data() {
|
|
|
- return {
|
|
|
- // 初始化数据
|
|
|
- options:{
|
|
|
- container:'luckysheet',
|
|
|
- lang: 'zh',
|
|
|
- gridKey:'handmade-excel',
|
|
|
- showinfobar:false,
|
|
|
- row:300,
|
|
|
- column:60,
|
|
|
- data:[
|
|
|
- {
|
|
|
- "name":"test",
|
|
|
- "celldata":[
|
|
|
- {
|
|
|
- "r":0,
|
|
|
- "c":0,
|
|
|
- "v":{
|
|
|
- ct: {fa: "General", t: "g"},
|
|
|
- m:"一级分类",
|
|
|
- v:"一级分类",
|
|
|
- bg:'#b4a7d6'
|
|
|
- },
|
|
|
- },
|
|
|
- {
|
|
|
- "r":1,
|
|
|
- "c":0,
|
|
|
- "v":{
|
|
|
- ct: {fa: "General", t: "g"},
|
|
|
- m:"指标分类",
|
|
|
- v:"指标分类",
|
|
|
- bg:'#b4a7d6'
|
|
|
- },
|
|
|
+ // 受保护的数据 维护一个二维数组 用于还原不能被修改或者以错误方式修改的数据
|
|
|
+ this.protectedData=[]
|
|
|
+
|
|
|
+ // 初始化数据
|
|
|
+ this.options={
|
|
|
+ container:'luckysheet',
|
|
|
+ lang: 'zh',
|
|
|
+ gridKey:'handmade-excel',
|
|
|
+ showinfobar:false,
|
|
|
+ row:300,
|
|
|
+ column:60,
|
|
|
+ data:[
|
|
|
+ {
|
|
|
+ "name":"test",
|
|
|
+ "celldata":[
|
|
|
+ {
|
|
|
+ "r":0,
|
|
|
+ "c":0,
|
|
|
+ "v":{
|
|
|
+ ct: {fa: "General", t: "g"},
|
|
|
+ m:"一级分类",
|
|
|
+ v:"一级分类",
|
|
|
+ bg:'#b4a7d6'
|
|
|
},
|
|
|
- {
|
|
|
- "r":2,
|
|
|
- "c":0,
|
|
|
- "v":{
|
|
|
- ct: {fa: "General", t: "g"},
|
|
|
- m:"频度",
|
|
|
- v:"频度",
|
|
|
- bg:'#b4a7d6'
|
|
|
- },
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "r":1,
|
|
|
+ "c":0,
|
|
|
+ "v":{
|
|
|
+ ct: {fa: "General", t: "g"},
|
|
|
+ m:"指标分类",
|
|
|
+ v:"指标分类",
|
|
|
+ bg:'#b4a7d6'
|
|
|
},
|
|
|
- {
|
|
|
- "r":3,
|
|
|
- "c":0,
|
|
|
- "v":{
|
|
|
- ct: {fa: "General", t: "g"},
|
|
|
- m:"指标名称",
|
|
|
- v:"指标名称",
|
|
|
- bg:'#b4a7d6'
|
|
|
- },
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "r":2,
|
|
|
+ "c":0,
|
|
|
+ "v":{
|
|
|
+ ct: {fa: "General", t: "g"},
|
|
|
+ m:"频度",
|
|
|
+ v:"频度",
|
|
|
+ bg:'#b4a7d6'
|
|
|
},
|
|
|
- {
|
|
|
- "r":4,
|
|
|
- "c":0,
|
|
|
- "v":{
|
|
|
- ct: {fa: "General", t: "g"},
|
|
|
- m:"单位",
|
|
|
- v:"单位",
|
|
|
- bg:'#b4a7d6'
|
|
|
- },
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "r":3,
|
|
|
+ "c":0,
|
|
|
+ "v":{
|
|
|
+ ct: {fa: "General", t: "g"},
|
|
|
+ m:"指标名称",
|
|
|
+ v:"指标名称",
|
|
|
+ bg:'#b4a7d6'
|
|
|
},
|
|
|
- ],
|
|
|
- "config":{
|
|
|
- "borderInfo":[{
|
|
|
- "rangeType": "range",
|
|
|
- "borderType": "border-all",
|
|
|
- "style": "1",
|
|
|
- "color": "#fff",
|
|
|
- "range": [{
|
|
|
- "row": [0,4],
|
|
|
- "column": [0,0]
|
|
|
- }]
|
|
|
- }],
|
|
|
},
|
|
|
- "frozen":{
|
|
|
- type: 'rangeBoth',
|
|
|
- range: {row_focus: 4, column_focus: 0}
|
|
|
+ {
|
|
|
+ "r":4,
|
|
|
+ "c":0,
|
|
|
+ "v":{
|
|
|
+ ct: {fa: "General", t: "g"},
|
|
|
+ m:"单位",
|
|
|
+ v:"单位",
|
|
|
+ bg:'#b4a7d6'
|
|
|
+ },
|
|
|
},
|
|
|
- "dataVerification":{}
|
|
|
- }
|
|
|
- ],
|
|
|
- hook:{
|
|
|
- cellUpdateBefore(r,c){
|
|
|
- // 禁止更新的单元格
|
|
|
- if([0,1,2,3,4].includes(r) && c==0){
|
|
|
- return false
|
|
|
- }
|
|
|
+ ],
|
|
|
+ "config":{
|
|
|
+ "borderInfo":[{
|
|
|
+ "rangeType": "range",
|
|
|
+ "borderType": "border-all",
|
|
|
+ "style": "1",
|
|
|
+ "color": "#fff",
|
|
|
+ "range": [{
|
|
|
+ "row": [0,4],
|
|
|
+ "column": [0,0]
|
|
|
+ }]
|
|
|
+ }],
|
|
|
},
|
|
|
- cellMousedownBefore(e,position){
|
|
|
- // 禁止鼠标选中的单元格
|
|
|
- if([0,1,2].includes(position.r) || ([3,4].includes(position.r) && position.c==0)){
|
|
|
- return false
|
|
|
- }
|
|
|
- }
|
|
|
- },
|
|
|
- showsheetbar:false
|
|
|
- },
|
|
|
+ "frozen":{
|
|
|
+ type: 'rangeBoth',
|
|
|
+ range: {row_focus: 4, column_focus: 0}
|
|
|
+ },
|
|
|
+ "dataVerification":{}
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ hook:{},
|
|
|
+ showsheetbar:false,
|
|
|
+ // cellRightClickConfig:{
|
|
|
+ // insertColumn:false,
|
|
|
+ // deleteRow:false,
|
|
|
+ // deleteColumn:false
|
|
|
+ // }
|
|
|
+ }
|
|
|
+
|
|
|
+ return {
|
|
|
dataForm:{
|
|
|
firstClassify:'',
|
|
|
secondClassify:'',
|
|
@@ -165,7 +162,9 @@ export default {
|
|
|
secondClassifyArray:[],
|
|
|
// 保存时候的加载框
|
|
|
saveLoading:false,
|
|
|
- isEdit:"false"
|
|
|
+ isEdit:"false",
|
|
|
+ refreshed:false,
|
|
|
+ haveSaveProtected:false
|
|
|
}
|
|
|
},
|
|
|
created() {
|
|
@@ -224,6 +223,102 @@ created() {
|
|
|
// if(res.Data.FrequencyList) this.dataForm.frequency = res.Data.FrequencyList[0]
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ // hook设置
|
|
|
+ // 处理复制粘贴造成的漏洞 - 记录数据
|
|
|
+ this.options.hook.cellAllRenderBefore=(data,sheet)=>{
|
|
|
+ if(this.haveSaveProtected) return
|
|
|
+ // console.log("全部刷新");
|
|
|
+ if(!this.protectedData.length>0){
|
|
|
+ for (let i = 0; i < 5; i++) {
|
|
|
+ if([0,1,2].includes(i)){
|
|
|
+ for (let j = 0; j < 2; j++) {
|
|
|
+ const element = data[i][j];
|
|
|
+ if(!Array.isArray(this.protectedData[i])) this.protectedData[i]=[]
|
|
|
+ this.protectedData[i][j] = element
|
|
|
+ }
|
|
|
+ }else{
|
|
|
+ for (let k = 0; k <= dataList.length; k++) {
|
|
|
+ const element = data[i][k];
|
|
|
+ if(!Array.isArray(this.protectedData[i])) this.protectedData[i]=[]
|
|
|
+ this.protectedData[i][k] = element
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ this.haveSaveProtected=true
|
|
|
+ }
|
|
|
+ this.options.hook.cellUpdateBefore=(r,c)=>{
|
|
|
+ // 禁止更新的单元格 已经有的指标名称和单位不允许更新
|
|
|
+ if(([0,1,2].includes(r) && c==0) || ([3,4].includes(r) && c<=dataList.length)){
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ this.options.hook.cellMousedownBefore=(e,position)=>{
|
|
|
+ // console.log(e,position);
|
|
|
+ // 禁止鼠标选中的单元格
|
|
|
+ if([0,1,2].includes(position.r) || ([3,4].includes(position.r) && position.c<=dataList.length)){
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 处理复制粘贴造成的漏洞 - 还原数据
|
|
|
+ this.options.hook.cellRenderBefore=(cell,position,sheet,ctx)=>{
|
|
|
+ // console.log('cellRenderBeforecellRenderBefore');
|
|
|
+ // 是否更改了受保护的数据
|
|
|
+ let haveUpdatedProtectedData=false
|
|
|
+ if([3,4].includes(position.r) && position.c>=0 && position.c<=dataList.length){
|
|
|
+ if(!cell) return
|
|
|
+ Object.keys(this.protectedData[position.r][position.c]).forEach(key => {
|
|
|
+ // console.log(_.isEqual(cell[key], this.protectedData[position.r][position.c][key]),'lodash');
|
|
|
+ if(!_.isEqual(cell[key], this.protectedData[position.r][position.c][key])){
|
|
|
+ haveUpdatedProtectedData=true
|
|
|
+ cell[key] = this.protectedData[position.r][position.c][key]
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }else if([0,1,2].includes(position.r)){
|
|
|
+ let cindex = position.c>1?1:position.c
|
|
|
+ // console.log(position.c,position.r,cell);
|
|
|
+ if(!cell){
|
|
|
+ if(cindex<1){
|
|
|
+ return
|
|
|
+ }
|
|
|
+ luckysheet.getSheet().data[position.r][position.c] = this.protectedData[position.r][cindex]
|
|
|
+ }else{
|
|
|
+ Object.keys(this.protectedData[position.r][cindex]).forEach(key => {
|
|
|
+ if(!_.isEqual(cell[key], this.protectedData[position.r][cindex][key])){
|
|
|
+ haveUpdatedProtectedData=true
|
|
|
+ cell[key] = this.protectedData[position.r][cindex][key]
|
|
|
+ }
|
|
|
+ });
|
|
|
+ if([0,1,2].includes(position.r) && position.c>0){
|
|
|
+ if(position.r==0){
|
|
|
+ if(cell.m !==this.firstClassName || cell.v !== this.firstClassName){
|
|
|
+ haveUpdatedProtectedData=true
|
|
|
+ cell.m = cell.v = this.firstClassName
|
|
|
+ }
|
|
|
+ }else if(position.r==1){
|
|
|
+ if(cell.m !==this.secondClassName || cell.v !== this.secondClassName){
|
|
|
+ haveUpdatedProtectedData=true
|
|
|
+ cell.m = cell.v = this.secondClassName
|
|
|
+ }
|
|
|
+ }else{
|
|
|
+ if(cell.m !==this.dataForm.frequency || cell.v !== this.dataForm.frequency){
|
|
|
+ haveUpdatedProtectedData=true
|
|
|
+ cell.m = cell.v = this.dataForm.frequency
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // console.log(cindex,position.r,'cindex,position.r',this.protectedData[position.r][cindex]);
|
|
|
+ }
|
|
|
+ if(haveUpdatedProtectedData){
|
|
|
+ // 还原数据后的手动刷新
|
|
|
+ this.refreshManual()
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
// 拿出所有数组
|
|
|
let arr = dataList.map((item => item.DataList)).flat()
|
|
|
// 拿出所有数组的日期并展平排序
|
|
@@ -238,7 +333,7 @@ created() {
|
|
|
return objList
|
|
|
})
|
|
|
/**
|
|
|
- * 当数据的长度大于默认的84时,行数需要设置成数据的长度+15
|
|
|
+ * 当数据的长度大于默认的300时,行数需要设置成数据的长度+15
|
|
|
*/
|
|
|
this.options.row = dateArr.length>(this.options.row-15) ? (dateArr.length+15):this.options.row
|
|
|
/**
|
|
@@ -257,7 +352,8 @@ created() {
|
|
|
"v":{
|
|
|
ct: {fa: "General", t: "g"},
|
|
|
m:item.SecName,
|
|
|
- v:item.SecName
|
|
|
+ v:item.SecName,
|
|
|
+ bg:'#cccccc'
|
|
|
}
|
|
|
},
|
|
|
{
|
|
@@ -266,7 +362,8 @@ created() {
|
|
|
"v":{
|
|
|
ct: {fa: "General", t: "g"},
|
|
|
m:item.Unit,
|
|
|
- v:item.Unit
|
|
|
+ v:item.Unit,
|
|
|
+ bg:'#cccccc'
|
|
|
}
|
|
|
})
|
|
|
})
|
|
@@ -343,6 +440,15 @@ created() {
|
|
|
"row": [5,row],
|
|
|
"column": [0,0]
|
|
|
}]
|
|
|
+ },{
|
|
|
+ "rangeType": "range",
|
|
|
+ "borderType": "border-all",
|
|
|
+ "style": "1",
|
|
|
+ "color": "#fff",
|
|
|
+ "range": [{
|
|
|
+ "row": [3,4],
|
|
|
+ "column": [1,dataList.length]
|
|
|
+ }]
|
|
|
})
|
|
|
// 设置数据验证
|
|
|
for (let i = 0; i < col; i++) {
|
|
@@ -360,6 +466,15 @@ created() {
|
|
|
luckysheet.create(this.options)
|
|
|
})
|
|
|
},
|
|
|
+ refreshManual: _.debounce(function() {
|
|
|
+ if(!this.refreshed) {
|
|
|
+ luckysheet.refresh()
|
|
|
+ this.refreshed=true
|
|
|
+ setTimeout(()=>{
|
|
|
+ this.refreshed=false
|
|
|
+ },1500)
|
|
|
+ }
|
|
|
+ },1000),
|
|
|
// 获取分类
|
|
|
async getClassify() {
|
|
|
let res=await dataInterence.getClassify()
|
|
@@ -393,25 +508,29 @@ created() {
|
|
|
this.dataForm.secondClassify = this.secondClassifyArray[0].ClassifyId
|
|
|
this.secondClassName = this.secondClassifyArray[0].ClassifyName
|
|
|
}
|
|
|
- for (let i= 1; i< col+1 ; i++) {
|
|
|
- luckysheet.setCellValue(0,i,this.firstClassName,{isRefresh:false})
|
|
|
- luckysheet.setCellValue(1,i,this.secondClassName,{isRefresh:i==col?true:false})
|
|
|
- }
|
|
|
+ luckysheet.refresh()
|
|
|
+ // for (let i= 1; i< col+1 ; i++) {
|
|
|
+ // luckysheet.setCellValue(0,i,this.firstClassName,{isRefresh:false})
|
|
|
+ // luckysheet.setCellValue(1,i,this.secondClassName,{isRefresh:i==col?true:false})
|
|
|
+ // }
|
|
|
},
|
|
|
// 切换选择二级分类
|
|
|
changeSecondClassify(id){
|
|
|
let col = this.options.column
|
|
|
let item = this.secondClassifyArray.find(item => item.ClassifyId == id)
|
|
|
- for (let i= 1; i< col+1; i++) {
|
|
|
- luckysheet.setCellValue(1,i,item.ClassifyName,{isRefresh:i==col?true:false})
|
|
|
- }
|
|
|
+ this.secondClassName=item.ClassifyName
|
|
|
+ // for (let i= 1; i< col+1; i++) {
|
|
|
+ // luckysheet.setCellValue(1,i,this.secondClassName,{isRefresh:i==col?true:false})
|
|
|
+ // }
|
|
|
+ luckysheet.refresh()
|
|
|
},
|
|
|
// 切换选择频度
|
|
|
changeFrequency(value){
|
|
|
- let col = this.options.column
|
|
|
- for (let i= 1; i< col+1; i++) {
|
|
|
- luckysheet.setCellValue(2,i,value,{isRefresh:i==col?true:false})
|
|
|
- }
|
|
|
+ // let col = this.options.column
|
|
|
+ // for (let i= 1; i< col+1; i++) {
|
|
|
+ // luckysheet.setCellValue(2,i,value,{isRefresh:i==col?true:false})
|
|
|
+ // }
|
|
|
+ luckysheet.refresh()
|
|
|
},
|
|
|
saveExcel(){
|
|
|
this.$refs.dataOptions.validate((valid)=>{
|