MixedTable.vue 71 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114
  1. <template>
  2. <div class="table-wrapper" @keydown="handlekeyDownKeys">
  3. <template v-if="config.data.length">
  4. <!-- 工具栏 -->
  5. <toolBarSection v-if="!disabled" :cell="selectCell?selectCell:selectedCells" @openConDialog="openConDialog" @cellMerge="toolCellMergeFun"
  6. :echoParameter="{hasMergedCell}"/>
  7. <!-- 公式显示区 -->
  8. <div class="formula-wrapper" v-if="!disabled">
  9. <span style="flex-shrink: 0;color:#C0C4CC">{{$t('OnlineExcelPage.formula_lable')}}</span>
  10. <el-input
  11. v-if="selectCell&&selectCell.DataType===6"
  12. v-model="selectCell.Value"
  13. @change="updateValueByFormula"
  14. />
  15. </div>
  16. <div class="el-table__body-wrapper">
  17. <table
  18. @mouseover="handleMouseOver"
  19. @mouseout="handleMouseOut"
  20. border="0"
  21. class="table el-table__body"
  22. id="myTable"
  23. :style="disabled ? 'width:100%' : ''"
  24. ref="tableRef"
  25. style="position: relative;width: auto;"
  26. @mousedown="selectCellHandle"
  27. >
  28. <thead>
  29. <tr>
  30. <!-- 行头 -->
  31. <th class="th-tg sm" style="width:36px"></th>
  32. <!-- 列头 -->
  33. <th
  34. :style="config.data[0][index].ShowStyle?getShowCss(config.data[0][index].ShowStyle,'header'):{}"
  35. @mousemove="handleMouseMove" @mouseout="handleMouseOut" @mousedown="handleMouseDown($event,index)"
  36. v-for="(item, index) in columnHeader"
  37. :key="index"
  38. class="th-tg th-col"
  39. :data-cindex="item"
  40. :data-rindex="-1"
  41. @contextmenu.prevent="rightClickHandle"
  42. >
  43. {{ item }}
  44. </th>
  45. </tr>
  46. </thead>
  47. <tbody>
  48. <tr v-for="(row, index) in config.data" :key="index">
  49. <!-- 行头 -->
  50. <th
  51. :style="config.data[index][0].ShowStyle?getShowCss(config.data[index][0].ShowStyle,'height'):{}"
  52. @mousemove="handleMouseMoveHeight" @mouseout="handleMouseOutHeight" @mousedown="handleMouseDownHeight($event,index)"
  53. class="th-tg th-row sm"
  54. @contextmenu.prevent="rightClickHandle"
  55. :data-rindex="rowHeader[index]"
  56. :data-cindex="-1"
  57. >
  58. {{ rowHeader[index] }}
  59. </th>
  60. <td
  61. v-for="(cell, cell_index) in row"
  62. :key="`${index}_${cell_index}`"
  63. :data-rindex="rowHeader[index]"
  64. :data-cindex="columnHeader[cell_index]"
  65. :data-datarindex="index"
  66. :data-datacindex="cell_index"
  67. :style="cell.ShowStyle?getShowCss(cell.ShowStyle):{}"
  68. :initIndex="initIndex(index,cell_index,rowHeader[index],columnHeader[cell_index])"
  69. :data-key="cell.Uid"
  70. v-show="!cell.merData || cell.merData.type!=='merged'"
  71. :colspan="(cell.merData && cell.merData.type=='merge' && cell.merData.mer)?cell.merData.mer.colspan || 1:1"
  72. :rowspan="(cell.merData && cell.merData.type=='merge' && cell.merData.mer)?cell.merData.mer.rowspan || 1:1"
  73. @click="clickCell($event, cell)"
  74. @dblclick="dblClickCellHandle($event,cell)"
  75. @contextmenu.prevent="rightClickHandle($event,cell)"
  76. @mouseenter="getRelationEdbInfo(cell)"
  77. >
  78. <!-- 插入单元格禁止编辑 -->
  79. <!-- [4,5,6,7,8].includes(cell.DataType)&&!cell.CanEdit -->
  80. <template
  81. v-if="!cell.CanEdit
  82. ||disabled
  83. ||(cell.DataType===1&&[1,2].includes(cell.DataTimeType))"
  84. >
  85. <!-- 单元格类型5 7显示指标浮窗 -->
  86. <el-popover
  87. v-if="[5,7].includes(cell.DataType)&&!disabled"
  88. placement="top-start"
  89. width="350"
  90. trigger="hover"
  91. >
  92. <ul>
  93. <li style="display:flex;margin:10px;">
  94. <label style="min-width:80px;">{{$t('OnlineExcelPage.indicator_name_lbl')}}</label>
  95. {{cellrelationEdbInfo.EdbName}}
  96. </li>
  97. <li style="display:flex;margin:10px;">
  98. <label style="min-width:80px;">{{$t('OnlineExcelPage.lastest_date_lab')}}</label>
  99. {{cellrelationEdbInfo.LatestDate}}
  100. </li>
  101. <li style="display:flex;margin:10px;">
  102. <label style="min-width:80px;">{{$t('Table.edb_id')}}</label>
  103. {{cellrelationEdbInfo.EdbCode}}
  104. </li>
  105. </ul>
  106. <span
  107. slot="reference"
  108. :data-rindex="rowHeader[index]"
  109. :data-cindex="columnHeader[cell_index]"
  110. :data-datarindex="index"
  111. :data-datacindex="cell_index"
  112. :data-key="cell.Uid"
  113. >{{ isShowDecimal(cell)?showDecimalValue(cell):isShowFormat(cell.ShowStyle)?cell.ShowFormatValue:cell.ShowValue }}</span>
  114. </el-popover>
  115. <!-- 数字格式化显示 -->
  116. <span
  117. v-else-if="cell.ShowStyle"
  118. :data-rindex="rowHeader[index]"
  119. :data-cindex="columnHeader[cell_index]"
  120. :data-datarindex="index"
  121. :data-datacindex="cell_index"
  122. :data-key="cell.Uid"
  123. >
  124. {{isShowDecimal(cell)?showDecimalValue(cell):isShowFormat(cell.ShowStyle)?cell.ShowFormatValue:cell.DataTime?cell.ShowValue:[8,7,6,5,1].includes(cell.DataType)?cell.ShowValue:cell.Value}}
  125. </span>
  126. <span
  127. :data-rindex="rowHeader[index]"
  128. :data-cindex="columnHeader[cell_index]"
  129. :data-datarindex="index"
  130. :data-datacindex="cell_index"
  131. :data-key="cell.Uid"
  132. v-else
  133. >{{ cell.ShowValue }}</span>
  134. </template>
  135. <el-autocomplete
  136. v-else
  137. v-model="cell.Value"
  138. :ref="`inputRef${cell.Uid}`"
  139. popper-class="edb-select-popover"
  140. :data-key="cell.Uid"
  141. :data-rindex="rowHeader[index]"
  142. :data-cindex="columnHeader[cell_index]"
  143. :data-datarindex="index"
  144. :data-datacindex="cell_index"
  145. :fetch-suggestions="searchTarget"
  146. @change.native="changeVal($event, cell)"
  147. @keydown.native="keyEnterHandle($event,cell)"
  148. @blur="() => {$set(cell,'CanEdit',false)}"
  149. >
  150. <!-- @select="selectTarget($event,cell)"
  151. @click="clickCell($event, cell)"
  152. :highlight-first-item="cell.DataType===2"
  153. -->
  154. <template slot-scope="scope">
  155. <edbDetailPopover :info="scope.item">
  156. <div slot="reference" v-if="cell.DataType===2" class="edb-item">
  157. <span class="edb-item-name text_oneLine">{{ scope.item.EdbName }}</span>
  158. <i class="el-icon-check" style="color:#0052D9;font-size:18px;"/>
  159. </div>
  160. <div slot="reference" v-else>{{ scope.item.EdbName }}</div>
  161. </edbDetailPopover>
  162. </template>
  163. </el-autocomplete>
  164. </td>
  165. </tr>
  166. </tbody>
  167. <!-- 选区 -->
  168. <div ref="selectionRef" id="selection-id"
  169. style="position: absolute;border: 2px solid #0052D9;background-color: rgba(0, 82, 217, 0.1);visibility: hidden;z-index: 1;pointer-events: none;"></div>
  170. <!-- 行列选中样式 -->
  171. <div ref="rowColSelectRef" id="row-col-select"
  172. style="position: absolute;border-color: #18ad18;border-style: solid;background-color: transparent;visibility: hidden;z-index: 1;pointer-events: none;"></div>
  173. </table>
  174. </div>
  175. <!-- 右键菜单 -->
  176. <div class="contextMenu-wrapper" id="contextMenu-wrapper" @mouseleave="()=>{activeNames=[];hideContextMenu()}">
  177. <div :class="['item',{'deletesty': menu.key==='reset'}]" v-for="menu in config.contextMenuOption" :key="menu.key" @click="handleContext(menu.key)">
  178. <span v-if="!menu.children">{{menu.label}}</span>
  179. <el-collapse v-model="activeNames" @change="handleChange" v-if="menu.children" class="mixed-edb-slide-collapse">
  180. <el-collapse-item name="1">
  181. <template slot="title">
  182. {{menu.label}}
  183. </template>
  184. <div class="subMenu-wrapper">
  185. <div slot="reference" class="item" v-for="submenu in menu.children" :key="submenu.key" @click="edbCalculateInsertOpen(submenu)">
  186. <el-popover
  187. width="300"
  188. trigger="hover"
  189. placement="right"
  190. >
  191. <div v-html="formulaTip.get(submenu.fromEdbKey)"></div>
  192. <div slot="reference" style="width:100%">{{submenu.label}}</div>
  193. </el-popover>
  194. </div>
  195. </div>
  196. </el-collapse-item>
  197. </el-collapse>
  198. </div>
  199. </div>
  200. </template>
  201. <div class="nodata" v-else>
  202. <tableNoData :text="$t('Table.prompt_slogan')"/>
  203. </div>
  204. <!-- 选择指标 -->
  205. <selectTargetValueDia
  206. :isShow.sync="isSelectTargetValueDialog"
  207. :info="insertTargetValueInfo"
  208. @insert="insertSelectData"
  209. ref="selectTargetValueRef"
  210. />
  211. <!-- 插入系统/指标日期弹窗 -->
  212. <insertDateDia
  213. :isShow.sync="isInsertDateDialog"
  214. :info="insertDateInfo"
  215. @insert="insertDatehandle"
  216. />
  217. <!-- 指标计算弹窗 -->
  218. <calculateEdbDia
  219. ref="calculateEdbDiaRef"
  220. :isShow.sync="isInsertCalculate"
  221. :info="insertCalculateInfo"
  222. @insert="insertCalculateData"
  223. />
  224. <!-- 日期计算弹窗 -->
  225. <calculateDateDia
  226. ref="calculateDateDiaRef"
  227. :isShow.sync="isInsertCalculateDate"
  228. :info="insertCalculateDateInfo"
  229. @insert="insertCalculateDateValue"
  230. />
  231. <condition-dia
  232. :chooseCell="selectCell?selectCell:selectedCells"
  233. ref="conditionDia"
  234. @changeRule="getExcelRule"
  235. @deleteRule="deleteExcelRule"
  236. @editRule="editExcelRule"
  237. />
  238. </div>
  239. </template>
  240. <script>
  241. import {
  242. getRowHeaderCode,
  243. getColumnHeaderCode,
  244. selectCellStyle,
  245. selectMoreCellStyle,
  246. setRelationStyle,
  247. getRightClickMenu,
  248. checkDateFormat,
  249. setFocus,
  250. findCellByKey,
  251. resetRelationStyle,
  252. resetDialogCellStyle,
  253. extractFactorsFromFormula,
  254. findCellByFactorMixed,
  255. splitString,
  256. toUpperCase,
  257. findCellKeyByFactor,
  258. isNumberValue,
  259. transNumPercentType,
  260. getDecimalPlaces,
  261. transDecimalPlace,
  262. resetStyle
  263. } from "../common/customTable";
  264. import * as sheetInterface from "@/api/modules/sheetApi.js";
  265. import { dataBaseInterface } from '@/api/api.js';
  266. import md5 from '@/utils/md5.js';
  267. import selectTargetValueDia from './selectTargetValueDia.vue';
  268. import insertDateDia from './insertDateDia.vue';
  269. import calculateEdbDia from './calculateEdbDia.vue';
  270. import calculateDateDia from './calculateDateDia.vue';
  271. import toolBarSection from './toolBarSection.vue';
  272. import conditionDia from './conditionDia.vue'
  273. import { formulaTip } from '@/views/dataEntry_manage/databaseComponents/util';
  274. import conditionTableMixin from "../mixins/conditionTableMixin.js"
  275. export default {
  276. mixins:[conditionTableMixin],
  277. props: {
  278. disabled: { //是否只预览
  279. type: Boolean,
  280. default: false,
  281. },
  282. sourceFrom:{
  283. type: Object,
  284. default: ()=>{
  285. return {}
  286. },
  287. }
  288. },
  289. components: {
  290. conditionDia,
  291. selectTargetValueDia,
  292. insertDateDia,
  293. calculateEdbDia,
  294. calculateDateDia,
  295. toolBarSection
  296. },
  297. computed: {
  298. //列头
  299. columnHeader() {
  300. return getColumnHeaderCode(
  301. this.config.data[0] ? this.config.data[0].length : 0
  302. );
  303. },
  304. //行头
  305. rowHeader() {
  306. let total_length = this.config.data.length;
  307. // console.log(this.config.data)
  308. return getRowHeaderCode(total_length);
  309. },
  310. },
  311. watch:{
  312. 'config.data':{
  313. handler(newVal){
  314. if(!this.disabled && this.hasInit){
  315. this.$emit("autoSave")
  316. }
  317. },
  318. deep:true
  319. },
  320. insertRelationArr:{
  321. handler(newVal){
  322. if(!this.disabled && this.hasInit){
  323. this.$emit("autoSave")
  324. }
  325. },
  326. deep:true
  327. },
  328. 'endCell.row':{
  329. handler(newVal){
  330. this.setSelectionStyle()
  331. }
  332. },
  333. 'endCell.column':{
  334. handler(newVal){
  335. this.setSelectionStyle()
  336. }
  337. }
  338. },
  339. data() {
  340. return {
  341. config: {
  342. /* 单元格类型
  343. 1手动日期格 DataTimeType 0 /系统日期导入格 DataTimeType 1 /指标日期导入格 DataTimeType 2
  344. 2指标格 //eta1.5.6又弃用了
  345. 3自定义输入
  346. 4插入值 表格里有关联的日期和指标格 // eta1.1.6弃用了
  347. 5弹窗里的插入值 有关联日期格
  348. 6公式计算单元格
  349. 7指标计算的插入值单元格
  350. 8日期计算值单元格
  351. */
  352. data: [],
  353. contextMenuOption: [],
  354. },
  355. selectCell: {},//选中单元格info
  356. rightClickCell: {},//右键单元格 key c r
  357. insertTargetCell: {},//选择右键插入时的单元格 可和右键单元格不一样 key c r
  358. insertRelationArr: [], //表格单元格依赖关系数组
  359. isSelectTargetValueDialog: false,//选择指标插入值弹窗
  360. insertTargetValueInfo: {},//编辑 关联info
  361. cellrelationEdbInfo: {}, //指标浮窗信息
  362. copyCellItem: {},//复制时的单元格信息 用于粘贴赋值
  363. calculateClickCell: null,//双击公式单元格时的单元格信息 用于之后选其他单元格拼接公式
  364. isInsertDateDialog: false,//导入日期弹窗
  365. insertDateInfo: {},
  366. isInsertCalculate: false,//插入指标计算值
  367. insertCalculateInfo: {},//指标计算单元格info
  368. formulaTip,
  369. hasInit:false,
  370. isInsertCalculateDate: false,//日期计算弹窗
  371. insertCalculateDateInfo: {},//日期计算info
  372. activeNames: [],
  373. // 合并单元格data
  374. isSelectionStart:false, //选区开始
  375. startCell:{// 选区时鼠标开始的单元格
  376. row:null,
  377. column:null
  378. },
  379. endCell:{// 选区时鼠标结束的单元格
  380. row:null,
  381. column:null
  382. },
  383. selectionStart:{// 选区范围的左上角单元格
  384. row:null,
  385. rowSpan:0,
  386. column:null,
  387. colSpan:0
  388. },
  389. selectionEnd:{// 选区范围的右下角角单元格
  390. row:null,
  391. rowSpan:0,
  392. column:null,
  393. colSpan:0
  394. },
  395. hasMergedCell:false,// 选区内是否有合并的单元格
  396. selectedCells:[],
  397. // 选区有'值'单元格 因为超一个单元格有值不让合并,所以记录一个就行
  398. hasValueCellItem:{
  399. cellNumber:0, //有几个
  400. row:null,
  401. column:null
  402. },
  403. // 做个缓存
  404. cacheKey:'',
  405. cacheCellDom:{},
  406. //规则列表
  407. excelRuleList:[]
  408. };
  409. },
  410. mounted() {
  411. if(this.$route.path === '/addMixedSheet' && !this.$route.query.id) this.initData();
  412. },
  413. methods: {
  414. // 获取规则
  415. async getExcelRule(ExcelInfoId='',){
  416. const res = await dataBaseInterface.getRuleList({ExcelInfoId:ExcelInfoId?ExcelInfoId:this.$route.query.id})
  417. // console.log(res)
  418. if(res.Ret !== 200) return
  419. this.excelRuleList = res.Data.List?res.Data.List:[];
  420. this.commonInitCell()
  421. },
  422. openConDialog({chooseItem,chooseCells}){
  423. this.$refs.conditionDia.openDialog(chooseItem,chooseCells,this.excelRuleList,this.$route.query.id)
  424. },
  425. /* 输入时实时搜索 满足日期格式不搜索 有=视为输入公式不搜索 eta1.5.6弃用了*/
  426. async searchTarget(query,cb) {
  427. return cb([])
  428. //又要过滤掉2020-05-这样的奇葩其他格式 不让检索
  429. let dateOtherRegex = /^(?:(?:19|20)\d\d)([-])(0[1-9]|1[0-2])(-?)$/
  430. if(!query
  431. ||checkDateFormat(query)
  432. ||dateOtherRegex.test(query)
  433. ||query.startsWith('=')
  434. ) return cb([])
  435. const { DataType,EdbInfoId } = this.selectCell;
  436. const res = DataType===2
  437. ? await dataBaseInterface.targetDetail({EdbInfoId})
  438. : await sheetInterface.searchTarget({
  439. KeyWord: query,
  440. CurrentIndex: 1,
  441. PageSize: 1000
  442. })
  443. if(res.Ret !== 200) return
  444. let arr = DataType===2 ? [res.Data] : (res.Data.List||[])
  445. cb(arr);
  446. },
  447. /* 单击 */
  448. clickCell(e, cell) {
  449. if(this.disabled) return
  450. selectCellStyle(e);
  451. this.clearSelection()
  452. this.hasMergedCell = !!(cell && cell.merData)
  453. this.selectCell = cell;
  454. setFocus(e);
  455. //是插值单元格时寻找关联依赖的单元格 设置选框
  456. if([4,5,7].includes(cell.DataType)) {
  457. const { key } = e.target.dataset;
  458. if(!this.insertRelationArr.find(_ => _.key===key)) return
  459. let { relation_date,relation_edb } = this.insertRelationArr.find(_ => _.key===key)
  460. relation_date.key && setRelationStyle(relation_date)
  461. relation_edb.key && setRelationStyle(relation_edb)
  462. }
  463. //选择指标弹窗打开时选择日期更新弹窗数据
  464. this.isSelectTargetValueDialog&&this.$refs.selectTargetValueRef.changeRleationDate(this.selectCell)
  465. //计算指标弹窗打开时选择日期更新弹窗数据
  466. this.isInsertCalculate&&this.$refs.calculateEdbDiaRef.changeRleationDate(this.selectCell)
  467. //日期计算弹窗打开选中日期框时且有选中item时更新选中值
  468. cell.DataType===1&&this.isInsertCalculateDate&&this.$refs.calculateDateDiaRef.selectIndex&&this.$refs.calculateDateDiaRef.setSelectItemValue(this.selectCell)
  469. },
  470. /* 插入值 往左往上寻找同行同列是否有符合条件的一指标一日期 */
  471. async insertValue() {
  472. let params = this.findNearestCell();
  473. console.log(params)
  474. if(!params) {
  475. this.selectCell.DataType = 3;
  476. this.selectCell.DataTimeType = 0;
  477. this.selectCell.ShowValue = '';
  478. this.selectCell.Value = '';
  479. this.selectCell.DataTime = '';
  480. this.selectCell.EdbInfoId = 0;
  481. this.$message.warning(this.$t('OnlineExcelPage.no_here_val_msg') );
  482. return
  483. }
  484. const { EdbInfoId,Date,DataTimeType } = params
  485. const res = await sheetInterface.insertData({EdbInfoId,Date})
  486. if(res.Ret !==200) return
  487. res.Data ? this.$message.success(this.$t('OnlineExcelPage.insert_success_msg') ) : this.$message.warning(this.$t('OnlineExcelPage.the_date_no_val_msg') )
  488. this.selectCell.DataType = 4;
  489. this.selectCell.ShowValue = res.Data;
  490. this.selectCell.Value = res.Data;
  491. this.selectCell.EdbInfoId = EdbInfoId;
  492. this.selectCell.DataTime = Date;
  493. this.setRelation(params)
  494. },
  495. // 建立插入单元格和依赖单元格关联关系
  496. setRelation(data,cellType=4) {
  497. const { insert_cell } = data;
  498. let relation_obj = {
  499. type: cellType,
  500. key: insert_cell.key,
  501. relation_date: {
  502. type: 1,
  503. key: insert_cell.relation_date
  504. },
  505. relation_edb: {
  506. type: 2,
  507. key: insert_cell.relation_edb
  508. }
  509. }
  510. let haveIndex = this.insertRelationArr.findIndex(_ => _.key===insert_cell.key);
  511. if(haveIndex===-1) {
  512. this.insertRelationArr.push(relation_obj)
  513. }else {
  514. this.insertRelationArr.splice(haveIndex,1,relation_obj)
  515. }
  516. console.log(this.insertRelationArr)
  517. },
  518. /* 向左向上找出所有格子 找出离插入单元格最近的两个符合条件的单元格 看是否满足一指标一日期的条件
  519. 不满足就无法插入值
  520. */
  521. findNearestCell() {
  522. let { rindex,cindex,key } = this.rightClickCell;
  523. let index_row = this.rowHeader.findIndex(_ => _===rindex);
  524. let index_col = this.columnHeader.findIndex(_ => _===cindex);
  525. //同行左侧所有格子
  526. let row_cell_arr = this.config.data[index_row].filter((_,cell_index) => cell_index<index_col);
  527. //同列上侧所有格子
  528. let col_cell_arr = this.config.data.filter((row,row_index) => row_index<index_row).map(row=> row[index_col]);
  529. if(!row_cell_arr.length || !col_cell_arr.length){
  530. return null
  531. }
  532. //寻找最近的符合1 2类型的两个格子
  533. let params = null;
  534. for (let i = row_cell_arr.length - 1; i >= 0; i--) {
  535. for (let j = col_cell_arr.length - 1; j >= 0; j--) {
  536. if(!params) {
  537. if((row_cell_arr[i].DataType===1&&col_cell_arr[j].DataType===2)
  538. ||(row_cell_arr[i].DataType===2&&col_cell_arr[j].DataType===1)) {
  539. params = {
  540. DataTimeType: row_cell_arr[i].DataType===1 ? row_cell_arr[i].DataTimeType : col_cell_arr[j].DataTimeType,
  541. Date: row_cell_arr[i].DataType===1 ? row_cell_arr[i].ShowValue : col_cell_arr[j].ShowValue,
  542. EdbInfoId: row_cell_arr[i].DataType===2 ? row_cell_arr[i].EdbInfoId : col_cell_arr[j].EdbInfoId,
  543. insert_cell: {
  544. key,
  545. relation_date: row_cell_arr[i].DataType===1 ? row_cell_arr[i].Uid: col_cell_arr[j].Uid,
  546. relation_edb: row_cell_arr[i].DataType===2 ? row_cell_arr[i].Uid: col_cell_arr[j].Uid,
  547. },
  548. }
  549. break
  550. }
  551. }
  552. }
  553. }
  554. return params;
  555. },
  556. /* 输入框失焦 设置单元格类型 处理关联关系 */
  557. async changeVal(e, cell) {
  558. // 是日期格式 DataType为1
  559. // 自定义内容 DataType 3
  560. //有=号为输入公式 DataType 6
  561. const {value} = e.target;
  562. if(!value){ //无值重置单元格
  563. cell.DataType = 3;
  564. cell.ShowValue = value;
  565. cell.Value = value;
  566. cell.EdbInfoId = 0;
  567. cell.DataTime = '';
  568. cell.Extra=''
  569. }else {
  570. //指标类型不做格式处理
  571. if(cell.DataType===2) return
  572. console.log(checkDateFormat(value))
  573. let dateFormat = checkDateFormat(value);
  574. if(dateFormat) { //是日期格式
  575. cell.DataType = 1;
  576. cell.Extra='';
  577. cell.ShowValue = dateFormat;
  578. cell.DataTime = dateFormat;
  579. cell.Value = dateFormat;
  580. }else if(value.startsWith('=')) { //公式单元格
  581. cell.Value = value;
  582. cell.DataType = 6;
  583. let calculateVal = await this.getValueByFormula(value);
  584. if(!calculateVal) return
  585. cell.ShowValue = calculateVal;
  586. //处理公式关系
  587. this.$set(cell,'Extra',this.dealFormulaConstruction(value))
  588. }else {//自定义值
  589. cell.DataType = 3;
  590. cell.ShowValue = value;
  591. cell.Value = value;
  592. cell.EdbInfoId = 0;
  593. cell.DataTime = '';
  594. cell.Extra=''
  595. }
  596. }
  597. /* 不是数字类型,清除原来设置的格式 */
  598. let cellValueStyle = cell.ShowStyle?JSON.parse(cell.ShowStyle):{}
  599. if(!isNumberValue(value)){
  600. cell.ShowStyle = JSON.stringify({...cellValueStyle,pn:0,nt:'',last:'',decimal:null});
  601. }else{
  602. cell.ShowFormatValue = cellValueStyle.nt?transNumPercentType(value,cellValueStyle.nt):''
  603. const num = getDecimalPlaces(cell.ShowFormatValue?cell.ShowFormatValue+'':value+'')
  604. //last 记录最先操作方式
  605. cell.ShowStyle = JSON.stringify({...cellValueStyle,pn:0,last:'nt',decimal:num})
  606. }
  607. //判断是否是有插入值的依赖单元格 更新值或重置关系
  608. this.checkCellRelation(cell)
  609. this.commonInitCell('edit')
  610. },
  611. /* 当前单元格是否和插入值有关联 无就不管 */
  612. async checkCellRelation(cell) {
  613. if(!this.insertRelationArr.length) return
  614. const key= cell.Uid;
  615. //有关联的N组数组
  616. let haveRelationArr = this.insertRelationArr.filter(_ => _.relation_date.key===key||_.relation_edb.key===key);
  617. if(!haveRelationArr.length) return
  618. //去处理每一组关联的情况
  619. haveRelationArr.forEach(relation => {
  620. const { relation_date,relation_edb,type } = relation;
  621. if((relation_date.key === key && cell.DataType === 1) || (relation_edb.key === key && cell.DataType === 2)) { //单元格类型不变只变值仍有关联关系 更新值
  622. // 根据关系关联数组去更新每种单元格类型的值
  623. this.updateRelationCell(relation,cell)
  624. }else {
  625. // 清除插入值单元格式和关联关系
  626. this.clearInsertCell(relation.key);
  627. }
  628. })
  629. },
  630. // 清除插入值单元格式和关联关系
  631. clearInsertCell(key) {
  632. this.config.data.forEach(row => {
  633. row.forEach(cell => {
  634. if(cell.Uid === key) {
  635. cell.DataType = 3;
  636. cell.EdbInfoId = 0;
  637. cell.DataTime = '';
  638. cell.ShowValue = '';
  639. cell.Value = '';
  640. cell.ShowStyle = ''
  641. }
  642. })
  643. })
  644. let relationIndex = this.insertRelationArr.findIndex(_ => _.key===key)
  645. this.insertRelationArr.splice(relationIndex,1)
  646. },
  647. // 替换关联关系
  648. replaceCellRelation(originKey,replaceKey){
  649. if(!this.insertRelationArr.length) return
  650. this.insertRelationArr = JSON.parse(JSON.stringify(this.insertRelationArr).replaceAll(originKey,replaceKey))
  651. },
  652. /* 单元格更新时去更新有依赖关系单元格的值 目前只更4 5 7*/
  653. updateRelationCell(relation,cell) {
  654. const cellTypeMap = {
  655. 4: this.refreshRelationInsertCell,
  656. 5: this.refreshRelationByEdbInsertCell,
  657. 7: this.refreshRelationByEdbCalculateCell,
  658. }
  659. cellTypeMap[relation.type]&& cellTypeMap[relation.type](relation,cell)
  660. },
  661. //关联类型4的单元格值刷新
  662. async refreshRelationInsertCell({relation_date,relation_edb},cell) {
  663. //刷新插入值结果
  664. let params = null;
  665. if(relation_date.key === key && cell.DataType === 1) { //修改的是依赖日期格
  666. let { EdbInfoId } = findCellByKey(this.config.data,relation.key)
  667. params = {
  668. EdbInfoId,
  669. Date: cell.ShowValue
  670. }
  671. } else if( relation_edb.key === key && cell.DataType === 2) { //修改的依赖指标格
  672. let {ShowValue} = findCellByKey(this.config.data,relation_date.key)
  673. params = {
  674. EdbInfoId: cell.EdbInfoId,
  675. Date: ShowValue
  676. }
  677. }
  678. const res = await sheetInterface.insertData(params)
  679. if(res.Ret !==200) return
  680. //现在日期无值也不清除关系了
  681. // !res.Data && this.clearInsertCell(relation.key);
  682. this.config.data.forEach(row => {
  683. row.forEach(cell => {
  684. if(cell.Uid === relation.key) {
  685. cell.DataType = relation.type;
  686. cell.ShowValue = res.Data;
  687. cell.Value = res.Data;
  688. cell.EdbInfoId = params.EdbInfoId;
  689. cell.DataTime = params.Date;
  690. }
  691. })
  692. })
  693. },
  694. //关联类型5的弹窗插值单元格值刷新
  695. async refreshRelationByEdbInsertCell(relation,cell) {
  696. let { EdbInfoId,Value } = findCellByKey(this.config.data,relation.key)
  697. let params = {
  698. EdbInfoId,
  699. MoveForward: JSON.parse(Value).MoveForward,
  700. DateChange: JSON.parse(Value).DateChange,
  701. Date: cell.ShowValue
  702. }
  703. const res = await sheetInterface.getDateLatelyData(params)
  704. if(res.Ret !== 200) return
  705. let value = (res.Data.List&&res.Data.List.length)
  706. ? res.Data.List.find(_ => _.DataTime===res.Data.Date)
  707. ? res.Data.List.find(_ => _.DataTime===res.Data.Date).Value.toString()
  708. : ''
  709. : ''
  710. this.config.data.forEach(row => {
  711. row.forEach(cell => {
  712. if(cell.Uid === relation.key) {
  713. cell.ShowValue = value;
  714. cell.ShowFormatValue = cell.ShowStyle ? transDecimalPlace(value,JSON.parse(cell.ShowStyle)) : '';
  715. }
  716. })
  717. })
  718. },
  719. //关联类型7的指标计算单元格值刷新
  720. async refreshRelationByEdbCalculateCell(relation,cell) {
  721. console.log(relation,cell)
  722. console.log(findCellByKey(this.config.data,relation.key))
  723. let { Value } = findCellByKey(this.config.data,relation.key)
  724. const {
  725. Source,
  726. Frequency,
  727. Formula,
  728. EdbInfoId,
  729. MoveFrequency,
  730. MoveType,
  731. Calendar,
  732. MoveForward,
  733. DateChange
  734. } = JSON.parse(Value);
  735. let params = {
  736. DataTime: cell.ShowValue,
  737. Source,
  738. Frequency,
  739. Formula,
  740. EdbInfoId,
  741. MoveFrequency,
  742. MoveType,
  743. Calendar,
  744. MoveForward,
  745. DateChange,
  746. }
  747. const res = await sheetInterface.getMixedCalculateData(params)
  748. if(res.Ret !== 200) return
  749. let value = res.Data.ShowValue||"";
  750. this.config.data.forEach(row => {
  751. row.forEach(cell => {
  752. if(cell.Uid === relation.key) {
  753. cell.ShowValue = value;
  754. cell.ShowFormatValue = cell.ShowStyle ? transDecimalPlace(value,JSON.parse(cell.ShowStyle)) : '';
  755. }
  756. })
  757. })
  758. },
  759. /* 输入公式的计算值 */
  760. async getValueByFormula(val) {
  761. // 提取因数数组
  762. let factors = extractFactorsFromFormula(val)
  763. //根据因数找单元格
  764. let isAllCell = factors.some(_ => findCellByFactorMixed(this.config.data,_)===null||isNaN(findCellByFactorMixed(this.config.data,_)))
  765. if(isAllCell) {
  766. this.$message.warning(this.$t('OnlineExcelPage.formula_val_error_msg') )
  767. return '';
  768. }
  769. let TagMap = {};
  770. factors.forEach(_ => {
  771. if(!TagMap[_]) {
  772. TagMap[_] = Number(findCellByFactorMixed(this.config.data,_))
  773. }
  774. });
  775. const res = await sheetInterface.calculateCustomCellData({
  776. CalculateFormula: val,
  777. TagMap
  778. })
  779. if(res.Ret !== 200) return
  780. return res.Data
  781. },
  782. /* 顶部公式改变 */
  783. async updateValueByFormula(value) {
  784. this.changeVal({target: {value}},this.selectCell)
  785. },
  786. /* 右键 */
  787. rightClickHandle(e,cell) {
  788. if(this.disabled) return
  789. const { rindex,cindex,key,datacindex,datarindex } = e.target.dataset;
  790. this.rightClickCell = {
  791. rindex,
  792. cindex,
  793. datarindex,
  794. datacindex,
  795. key
  796. }
  797. this.selectCell = cell;
  798. let pos;
  799. if(rindex==='-1') { //列头处
  800. pos = 'col'
  801. }else if(cindex==='-1') { //行头
  802. pos = 'row'
  803. }else if( datarindex>=this.selectionStart.row && datarindex<=this.selectionEnd.row &&
  804. datacindex>=this.selectionStart.column && datacindex<=this.selectionEnd.column &&
  805. (this.selectionEnd.row-this.selectionStart.row>0||this.selectionEnd.column-this.selectionStart.column>0)){
  806. // 选区
  807. pos = 'selection'
  808. }else {//单元格
  809. pos = 'cell'
  810. }
  811. pos==='cell' && this.clickCell(e,cell);
  812. this.config.contextMenuOption = pos === 'cell'
  813. ? getRightClickMenu(pos,(cell.DataType===1&&[1,2].includes(cell.DataTimeType))||[5,7,8].includes(cell.DataType),false,{cellMerged:this.hasMergedCell})
  814. : getRightClickMenu(pos,false,false,{cellMerged:this.hasMergedCell})
  815. this.$nextTick(() => {
  816. let dom = $('#contextMenu-wrapper')[0];
  817. if(e.clientY > window.innerHeight/2) {
  818. dom.style.left = e.clientX-3 + 'px';
  819. dom.style.top = e.clientY-dom.offsetHeight-3 + 'px';
  820. }else {
  821. dom.style.left = e.clientX-3 + 'px';
  822. dom.style.top = e.clientY-3 + 'px';
  823. }
  824. if(['col','row'].includes(pos)){
  825. this.clearSelection()
  826. selectMoreCellStyle(e);
  827. }
  828. })
  829. },
  830. /* */
  831. hideContextMenu() {
  832. const dom = $('#contextMenu-wrapper')[0];
  833. dom.style.left = '-9999px';
  834. dom.style.top = '-9999px';
  835. },
  836. /* 右键事件 */
  837. async handleContext(key) {
  838. //可右键编辑的单元格类型
  839. let editHandlesMap = {
  840. 1: this.insertDateOpen,
  841. 5: this.selectTargetOpen,
  842. 7: this.edbCalculateInsertOpen,
  843. 8: this.insertDateCalculateOpen
  844. }
  845. const keyMap = {
  846. 'del': this.delColOrRow,//删除
  847. 'insert-col-left': this.insertCol,//向左插入列
  848. 'insert-col-right': this.insertCol,//向右插入列
  849. 'insert-row-up': this.insertRow,//向上插入行
  850. 'insert-row-down': this.insertRow,//向下插入行
  851. 'insert-value': this.insertValue,//插入值
  852. 'choose-target': this.selectTargetOpen,//选择指标插入值
  853. 'insert-date': this.insertDateOpen,//导入系统日期
  854. 'insert-date-calculate': this.insertDateCalculateOpen,//日期计算弹窗
  855. 'reset': this.clearCell, //清空
  856. 'cell-edit': this.selectCell ? editHandlesMap[this.selectCell.DataType] : null,
  857. 'cell-merge':this.mergeCellFun,
  858. 'cell-unmerge':this.unmergeCellsFun
  859. }
  860. keyMap[key] && keyMap[key](key)
  861. key!=='insert-edb-calculate' && this.hideContextMenu()
  862. },
  863. /* 打开选择指标弹窗
  864. 打开弹窗后仍可以在页面上点击 多存一个选择指标时的当前单元格信息 */
  865. selectTargetOpen(type) {
  866. this.insertTargetCell = this.selectCell;
  867. resetDialogCellStyle();
  868. setRelationStyle({ key:this.insertTargetCell.Uid },'td-choose-insert-target')
  869. if(type === 'cell-edit') {
  870. this.insertTargetValueInfo = {
  871. ...this.insertTargetCell
  872. }
  873. }else {
  874. this.insertTargetValueInfo = {}
  875. }
  876. this.isSelectTargetValueDialog = true;
  877. this.resetDialogStatus('insertEdbVal')
  878. },
  879. /* 插入选择指标的值 */
  880. insertSelectData({ edbId,value,relationDate,relationUid,str,sourceName }) {
  881. this.insertTargetCell.DataType = 5;
  882. this.insertTargetCell.ShowValue = value;
  883. this.insertTargetCell.Value = str;
  884. this.insertTargetCell.EdbInfoId = edbId;
  885. this.insertTargetCell.DataTime = relationDate;
  886. this.insertTargetCell.ShowFormatValue = this.insertTargetCell.ShowStyle ? transDecimalPlace(value,JSON.parse(this.insertTargetCell.ShowStyle)) : '';
  887. value ? this.$message.success(this.$t('ETable.Msg.insertion_success_msg')) : this.$message.warning(this.$t('ETable.Msg.date_no_data'))
  888. this.updateSourceFrom(sourceName)
  889. //如果有关联表格日期就建立新的关联关系
  890. if(relationDate&&relationUid) {
  891. let relation = {
  892. insert_cell: {
  893. key: this.insertTargetCell.Uid,
  894. relation_date: relationUid,
  895. relation_edb: '',
  896. }
  897. }
  898. this.setRelation(relation,5);
  899. }else { //重新插值后之后原来有关联的清除关系
  900. let haveIndex = this.insertRelationArr.findIndex(_ => _.key===this.insertTargetCell.Uid);
  901. haveIndex!==-1 && this.insertRelationArr.splice(haveIndex,1)
  902. resetRelationStyle();
  903. }
  904. this.commonInitCell('edit')
  905. },
  906. /*
  907. 清除单元格内容 格式 关联关系
  908. config:{
  909. single:true 清除单个,不考虑合并单元格的联系
  910. }
  911. */
  912. clearCell(c) {
  913. const isCell = c && typeof(c)=='object' && c.Uid
  914. const cell = isCell ? c: this.selectCell
  915. if([4,5].includes(cell.DataType)) resetRelationStyle();
  916. cell.DataType = 3;
  917. cell.ShowValue = '';
  918. cell.Value = '';
  919. cell.DataTime = '';
  920. cell.DataTimeType = 0;
  921. cell.EdbInfoId = 0;
  922. cell.ShowStyle = '';
  923. cell.ShowFormatValue = '';
  924. cell.Extra && (cell.Extra = '');
  925. this.checkCellRelation(cell)
  926. },
  927. findDataByStartKey(key){
  928. if(!key) return {data:{},row:-1,col:-1}
  929. let mergeCellDom = this.$refs.tableRef.querySelector(`[data-key="${key}"]`)
  930. let row = +mergeCellDom.dataset.datarindex
  931. let col = +mergeCellDom.dataset.datacindex
  932. return {data:this.config.data[row][col],row,col}
  933. },
  934. /* 删除行列 */
  935. delColOrRow() {
  936. let { rindex,cindex } = this.rightClickCell;
  937. if(rindex==='-1') { //删除列
  938. console.log('删除列',cindex)
  939. if(this.columnHeader.length === 1) return this.$message.warning(this.$t('OnlineExcelPage.keep_one_column_msg') )
  940. let index = this.columnHeader.findIndex(_ => _ === cindex);
  941. // 处理删除列对合并单元格的影响
  942. let startMainKey=''
  943. this.config.data.map((row,rowInd) => {
  944. let rowEle=row[index]
  945. if(rowEle.merData){
  946. let {data,row,col} = this.findDataByStartKey(rowEle.merData.mer.sKey)
  947. let r = row
  948. let c = col
  949. let rs = data.merData.mer.rowspan
  950. let cs = data.merData.mer.colspan
  951. if(cs == 1) return //只有一列
  952. if(rowEle.merData.type == 'merged'){
  953. // 每个大单元格只处理一次
  954. if(startMainKey != rowEle.merData.mer.sKey){
  955. if(data.merData.mer.colspan==2 && data.merData.mer.rowspan==1){
  956. //删除这一列之后,只有一个单元格了
  957. data.merData=null
  958. return
  959. }
  960. data.merData.mer.colspan--
  961. startMainKey = rowEle.merData.mer.sKey
  962. }
  963. }else{
  964. // 右一列的单元格作为新的左上角单元格
  965. const newStartCell = this.config.data[r][c+1]
  966. if(rowEle.merData.mer.colspan==2 && rowEle.merData.mer.rowspan==1){
  967. //删除这一列之后,只有一个单元格了
  968. newStartCell.merData=null
  969. return
  970. }
  971. newStartCell.merData=rowEle.merData
  972. newStartCell.merData.mer.sKey = newStartCell.Uid
  973. newStartCell.merData.mer.colspan--
  974. for (let i = r; i < (r+rs); i++) {
  975. for (let j = c+1; j < (c+cs); j++) {
  976. const element = this.config.data[i][j];
  977. if(element.merData.type == 'merged'){
  978. element.merData.mer.sKey = newStartCell.Uid
  979. }
  980. }
  981. }
  982. }
  983. }
  984. })
  985. //删除时清除关系
  986. if(this.insertRelationArr.length) {
  987. let delCellIds = this.config.data.map(row => row[index].Uid);
  988. this.clearRelationInsertCell(delCellIds);
  989. }
  990. this.config.data.forEach(row => {
  991. row.splice(index,1)
  992. })
  993. // 删除的是最后一列
  994. if(!(index < this.config.data[0].length)){
  995. resetStyle()
  996. }
  997. }else if(cindex === '-1') { //删除行
  998. console.log('删除行',rindex)
  999. if(this.rowHeader.length === 1) return this.$message.warning(this.$t('OnlineExcelPage.keep_one_row_msg') )
  1000. let index = this.rowHeader.findIndex(_ => _ === rindex)
  1001. // 处理删除行对合并单元格的影响
  1002. let startMainKey=''
  1003. this.config.data[index].map((rowEle,rowInd) => {
  1004. if(rowEle.merData){
  1005. let {data,row,col} = this.findDataByStartKey(rowEle.merData.mer.sKey)
  1006. let r = row
  1007. let c = col
  1008. let rs = data.merData.mer.rowspan
  1009. let cs = data.merData.mer.colspan
  1010. if(rs == 1) return //只有一行
  1011. if(rowEle.merData.type == 'merged'){
  1012. // 每个大单元格只处理一次
  1013. if(startMainKey != rowEle.merData.mer.sKey){
  1014. if(data.merData.mer.colspan==1 && data.merData.mer.rowspan==2){
  1015. //删除这一行之后,只有一个单元格了
  1016. data.merData=null
  1017. return
  1018. }
  1019. data.merData.mer.rowspan--
  1020. startMainKey = rowEle.merData.mer.sKey
  1021. }
  1022. }else{
  1023. // 下一行的单元格作为新的左上角单元格
  1024. const newStartCell = this.config.data[r+1][c]
  1025. if(rowEle.merData.mer.colspan==1 && rowEle.merData.mer.rowspan==2){
  1026. //删除这一行之后,只有一个单元格了
  1027. newStartCell.merData=null
  1028. return
  1029. }
  1030. newStartCell.merData=rowEle.merData
  1031. newStartCell.merData.mer.sKey = newStartCell.Uid
  1032. newStartCell.merData.mer.rowspan--
  1033. for (let i = r+1; i < (r+rs); i++) {
  1034. for (let j = c; j < (c+cs); j++) {
  1035. const element = this.config.data[i][j];
  1036. if(element.merData.type == 'merged'){
  1037. element.merData.mer.sKey = newStartCell.Uid
  1038. }
  1039. }
  1040. }
  1041. }
  1042. }
  1043. })
  1044. if(this.insertRelationArr.length) {
  1045. //删除时清除关系
  1046. let delCellIds = this.config.data[index].map(cell => cell.Uid);
  1047. this.clearRelationInsertCell(delCellIds);
  1048. }
  1049. this.config.data.splice(index,1)
  1050. // 删除的是最后一行
  1051. if(!(index < this.config.data.length)){
  1052. resetStyle()
  1053. }
  1054. }
  1055. },
  1056. /* 删除时清除关联关系 和删除单元格有关联的插入值单元格和 */
  1057. clearRelationInsertCell(delCellIds) {
  1058. //清除关联插入值得单元格
  1059. let haveRelationArr = this.insertRelationArr.filter(_ => delCellIds.includes(_.relation_date.key)||delCellIds.includes(_.relation_edb.key));
  1060. // console.log(haveRelationArr)
  1061. haveRelationArr.forEach(relation => {
  1062. !delCellIds.includes(relation)&&this.clearInsertCell(relation.key);
  1063. })
  1064. this.insertRelationArr = this.insertRelationArr.filter(_ => !delCellIds.includes(_.key)&&!delCellIds.includes(_.relation_date.key)&&!delCellIds.includes(_.relation_edb.key))
  1065. },
  1066. /* 插入列 */
  1067. insertCol(key) {
  1068. let { cindex } = this.rightClickCell;
  1069. let index = this.columnHeader.findIndex(_ => _ === cindex);
  1070. let checkIndex = key==='insert-col-left'?index-1:index+1
  1071. let startMainKey=''
  1072. this.config.data.forEach((row,rindex) => {
  1073. let isEnlargeCell = !!(row[index].merData && row[checkIndex] && row[checkIndex].merData)
  1074. if(isEnlargeCell && startMainKey != row[index].merData.mer.sKey){
  1075. const data = row[index].merData.type == 'merge'?row[index]:this.findDataByStartKey(row[index].merData.mer.sKey).data
  1076. data.merData.mer.colspan++
  1077. startMainKey = row[index].merData.mer.sKey
  1078. }
  1079. row.splice(key==='insert-col-left'?index:index+1,0,{
  1080. ShowValue: "",
  1081. Value: "",
  1082. DataType: 3,
  1083. DataTime: "",
  1084. ShowStyle:JSON.stringify({width:140,height:35}),
  1085. EdbInfoId: 0,
  1086. Uid: md5.hex_md5(`${new Date().getTime()}${rindex}`),
  1087. merData:isEnlargeCell?{
  1088. type:'merged',
  1089. mer:{
  1090. sKey:row[index].merData.mer.sKey,//左上角第一个单元格的Uid
  1091. }
  1092. }:null
  1093. })
  1094. })
  1095. },
  1096. /* 插入行 */
  1097. insertRow(key) {
  1098. let { rindex } = this.rightClickCell;
  1099. let index = this.rowHeader.findIndex(_ => _ === rindex)
  1100. let checkIndex = key==='insert-row-up'?index-1:index+1
  1101. let startMainKey=''
  1102. let row = new Array(this.columnHeader.length).fill("").map((_,cindex) => {
  1103. let isEnlargeCell = !!(this.config.data[index][cindex].merData &&(this.config.data[checkIndex]&&this.config.data[checkIndex][cindex]) && this.config.data[checkIndex][cindex].merData)
  1104. if(isEnlargeCell && startMainKey != this.config.data[index][cindex].merData.mer.sKey){
  1105. const data = this.config.data[index][cindex].merData.type == 'merge'?
  1106. this.config.data[index][cindex]:
  1107. this.findDataByStartKey(this.config.data[index][cindex].merData.mer.sKey).data
  1108. data.merData.mer.rowspan++
  1109. startMainKey = this.config.data[index][cindex].merData.mer.sKey
  1110. }
  1111. return {
  1112. ShowValue: "",
  1113. Value: "",
  1114. DataType: 3,
  1115. DataTime: "",
  1116. EdbInfoId: 0,
  1117. Uid: md5.hex_md5(`${new Date().getTime()}${cindex}`),
  1118. merData:isEnlargeCell?{
  1119. type:'merged',
  1120. mer:{
  1121. sKey:this.config.data[index][cindex].merData.mer.sKey,//左上角第一个单元格的Uid
  1122. }
  1123. }:null
  1124. }
  1125. });
  1126. this.config.data.splice( key==='insert-row-up'?index:index+1,0,row)
  1127. },
  1128. /* 单元格类型5 浮到上面展示指标信息浮窗 */
  1129. async getRelationEdbInfo({EdbInfoId,DataType}) {
  1130. if(![5,7].includes(DataType)||this.disabled) return
  1131. const res = await dataBaseInterface.targetDetail({EdbInfoId})
  1132. if(res.Ret !== 200) return
  1133. this.cellrelationEdbInfo = res.Data;
  1134. },
  1135. /* 导入系统/指标日期弹窗 */
  1136. insertDateOpen(type) {
  1137. this.insertTargetCell = this.selectCell;
  1138. resetDialogCellStyle();
  1139. if(type === 'cell-edit') { //编辑日期
  1140. this.insertDateInfo = {
  1141. ...this.insertTargetCell
  1142. }
  1143. }else {
  1144. this.insertDateInfo = {
  1145. // key:type
  1146. }
  1147. }
  1148. this.isInsertDateDialog = true;
  1149. this.resetDialogStatus();
  1150. },
  1151. /* 弹窗都是无遮罩的 弹一个就重置其他的 */
  1152. resetDialogStatus(type='init') {
  1153. if(type!=='insertEdbVal') {
  1154. this.$refs.selectTargetValueRef&&this.$refs.selectTargetValueRef.initData();
  1155. this.isSelectTargetValueDialog = false;
  1156. }
  1157. if(type!=='insertEdbCalculateVal') {
  1158. this.$refs.calculateEdbDiaRef&&this.$refs.calculateEdbDiaRef.initData();
  1159. this.isInsertCalculate = false;
  1160. }
  1161. if(type!=='insertDateCalculateVal') {
  1162. this.$refs.calculateDateDiaRef&&this.$refs.calculateDateDiaRef.initData();
  1163. this.isInsertCalculateDate = false;
  1164. }
  1165. },
  1166. /* 插入系统/指标日期 */
  1167. insertDatehandle({insertValue,dataTimeType,str,sourceName}) {
  1168. this.updateSourceFrom(sourceName)
  1169. this.insertTargetCell.DataType = 1;
  1170. this.insertTargetCell.DataTimeType = dataTimeType;
  1171. this.insertTargetCell.ShowValue = insertValue;
  1172. this.insertTargetCell.Value = str;
  1173. this.insertTargetCell.EdbInfoId = 0;
  1174. this.insertTargetCell.DataTime = insertValue;
  1175. this.commonInitCell('edit')
  1176. },
  1177. /* 指标计算弹窗 */
  1178. edbCalculateInsertOpen(item) {
  1179. this.insertTargetCell = this.selectCell;
  1180. resetDialogCellStyle();
  1181. setRelationStyle({ key:this.insertTargetCell.Uid },'td-choose-insert-target');
  1182. if(item === 'cell-edit') { //编辑
  1183. const { Value } = this.insertTargetCell;
  1184. let menuInfo = this.config.contextMenuOption
  1185. .find(_ => _.key==='insert-edb-calculate').children
  1186. .find(menu => menu.source === JSON.parse(Value).Source);
  1187. this.insertCalculateInfo = {
  1188. ...menuInfo,
  1189. ...this.insertTargetCell
  1190. }
  1191. }else {
  1192. this.insertCalculateInfo = {
  1193. ...item
  1194. }
  1195. }
  1196. this.isInsertCalculate = true;
  1197. this.resetDialogStatus('insertEdbCalculateVal')
  1198. },
  1199. /* 导入指标计算值 */
  1200. insertCalculateData(item) {
  1201. // console.log(item)
  1202. const { InsertValue,EdbInfoId,Str,relationDate,relationUid,sourceName } = item;
  1203. this.insertTargetCell.DataType = 7;
  1204. this.insertTargetCell.ShowValue = InsertValue;
  1205. this.insertTargetCell.Value = Str;
  1206. this.insertTargetCell.EdbInfoId = EdbInfoId;
  1207. this.insertTargetCell.DataTime = relationDate;
  1208. this.insertTargetCell.ShowFormatValue = this.insertTargetCell.ShowStyle ? transDecimalPlace(InsertValue,JSON.parse(this.insertTargetCell.ShowStyle)) : '';
  1209. InsertValue ? this.$message.success(this.$t('ETable.Msg.insertion_success_msg')) : this.$message.warning(this.$t('ETable.Msg.date_no_data'))
  1210. this.updateSourceFrom(sourceName)
  1211. //如果有关联表格日期就建立新的关联关系
  1212. if(relationDate&&relationUid) {
  1213. let relation = {
  1214. insert_cell: {
  1215. key: this.insertTargetCell.Uid,
  1216. relation_date: relationUid,
  1217. relation_edb: '',
  1218. }
  1219. }
  1220. this.setRelation(relation,7);
  1221. }else { //重新插值后之后原来有关联的清除关系
  1222. let haveIndex = this.insertRelationArr.findIndex(_ => _.key===this.insertTargetCell.Uid);
  1223. haveIndex!==-1 && this.insertRelationArr.splice(haveIndex,1)
  1224. resetRelationStyle();
  1225. }
  1226. this.commonInitCell('edit')
  1227. },
  1228. /* 日期计算弹窗 */
  1229. insertDateCalculateOpen(type) {
  1230. this.insertTargetCell = this.selectCell;
  1231. resetDialogCellStyle()
  1232. setRelationStyle({ key:this.insertTargetCell.Uid },'td-choose-insert-target')
  1233. if(type === 'cell-edit') { //编辑
  1234. this.insertCalculateDateInfo = {
  1235. ...this.insertTargetCell
  1236. }
  1237. }else {
  1238. this.insertCalculateDateInfo = {}
  1239. }
  1240. this.isInsertCalculateDate = true;
  1241. this.resetDialogStatus('insertDateCalculateVal');
  1242. },
  1243. /* 插入日期计算值 */
  1244. insertCalculateDateValue(data) {
  1245. const { insertValue,str } = data;
  1246. this.insertTargetCell.DataType = 8;
  1247. this.insertTargetCell.ShowValue = insertValue;
  1248. this.insertTargetCell.Value = str;
  1249. this.insertTargetCell.EdbInfoId = 0;
  1250. this.insertTargetCell.DataTime = '';
  1251. this.insertTargetCell.ShowFormatValue = this.insertTargetCell.ShowStyle ? transDecimalPlace(insertValue,JSON.parse(this.insertTargetCell.ShowStyle)) : '';
  1252. this.$message.success(this.$t('ETable.Msg.insertion_success_msg'))
  1253. this.commonInitCell('edit')
  1254. },
  1255. /* 初始化8行5列 */
  1256. initData(initData=null) {
  1257. this.hasInit=false
  1258. if(initData) {
  1259. const { CellRelation,Data } = initData;
  1260. this.config.data = Data;
  1261. this.insertRelationArr = JSON.parse(CellRelation);
  1262. this.getTableWidth()
  1263. }else {
  1264. this.config.data = new Array(8).fill("").map((_,_rindex) => {
  1265. return new Array(5).fill("").map((cell,_cindex) => ({
  1266. ShowValue: "",
  1267. ShowStyle:JSON.stringify({width:140,height:35}),
  1268. ShowFormatValue: '',
  1269. Value: "",
  1270. DataType: 3,
  1271. DataTimeType: 0,
  1272. DataTime: "",
  1273. EdbInfoId:0,
  1274. Uid: md5.hex_md5(`${new Date().getTime()}${_rindex}${_cindex}`),
  1275. }));
  1276. });
  1277. this.getTableWidth()
  1278. }
  1279. this.$nextTick(()=>{
  1280. this.hasInit=true
  1281. if(this.$route.query.id){
  1282. this.getExcelRule()
  1283. }
  1284. })
  1285. },
  1286. /* 处理因数结构 =a1+b1 => [{ Tag: a,Row:1,Key:'' }] */
  1287. dealFormulaConstruction(val) {
  1288. // 提取因数数组
  1289. let factors = extractFactorsFromFormula(val)
  1290. let arr = factors.map(str => ({
  1291. Tag: splitString(toUpperCase(str))[0],
  1292. Row: splitString(toUpperCase(str))[1],
  1293. Key: findCellKeyByFactor(str)
  1294. }))
  1295. return JSON.stringify(arr)
  1296. },
  1297. /* 要支持复制粘贴把公式也带过去 公式单元格类型为6 其余就正常复制文本 */
  1298. copyCellHandle(e,cell) {
  1299. console.log(cell)
  1300. this.copyCellItem = cell;
  1301. // 阻止默认的复制操作
  1302. e.preventDefault();
  1303. },
  1304. /* 要支持复制粘贴把公式也带过去 公式单元格类型为6 其余就正常复制文本 */
  1305. pasteCellHandle(e,cell) {
  1306. if(this.copyCellItem.DataType === 6) {
  1307. cell.DataType = this.copyCellItem.DataType;
  1308. cell.ShowValue = this.copyCellItem.ShowValue;
  1309. cell.Value = this.copyCellItem.Value;
  1310. cell.DataTime = this.copyCellItem.DataTime;
  1311. cell.EdbInfoId = this.copyCellItem.EdbInfoId;
  1312. cell.ShowStyle = this.copyCellItem.ShowStyle;
  1313. cell.ShowFormatValue = this.copyCellItem.ShowFormatValue;
  1314. cell.Extra = this.copyCellItem.Extra;
  1315. }else {
  1316. cell.DataType = 3;
  1317. cell.ShowValue = this.copyCellItem.ShowValue;
  1318. cell.Value = this.copyCellItem.ShowValue;
  1319. cell.ShowStyle = this.copyCellItem.ShowStyle;
  1320. cell.ShowFormatValue = this.copyCellItem.ShowFormatValue;
  1321. cell.DataTime = '';
  1322. cell.EdbInfoId = 0;
  1323. }
  1324. // 阻止默认的粘贴操作
  1325. e.preventDefault();
  1326. },
  1327. /* 单元格enter失焦 */
  1328. keyEnterHandle(e,cell) {
  1329. if(e.keyCode===13) {
  1330. //非得搞个要回车失焦
  1331. e.target.nodeName && e.target.blur();
  1332. this.$refs[`inputRef${e.target.dataset.key}`]&&this.$refs[`inputRef${e.target.dataset.key}`][0].close()
  1333. }
  1334. },
  1335. /* 双击切换状态 插值单元格不允许切换 可切换类型1,2,3,6*/
  1336. dblClickCellHandle(e,cell) {
  1337. if(this.disabled || ![1,2,3,6].includes(cell.DataType) || [1,2].includes(cell.DataTimeType)) return
  1338. this.$set(cell,'CanEdit',true)
  1339. console.log(cell)
  1340. this.$nextTick(() => {
  1341. if(e.target.childNodes[0].childNodes[0].childNodes[1].nodeName==='INPUT') e.target.childNodes[0].childNodes[0].childNodes[1].focus();
  1342. })
  1343. },
  1344. /* 处理保存的参数 */
  1345. getSaveParams() {
  1346. const { data } = this.config;
  1347. let params = {
  1348. CellRelation: JSON.stringify(this.insertRelationArr),
  1349. Data: data
  1350. }
  1351. return params
  1352. },
  1353. /* tab禁掉 */
  1354. handlekeyDownKeys(e) {
  1355. if(e.keyCode === 9) {
  1356. e.preventDefault();
  1357. }
  1358. },
  1359. // 更新数据来源
  1360. updateSourceFrom(source){
  1361. if(!source) return
  1362. let concatSourceArr = this.sourceFrom.text?`${this.sourceFrom.text},${source}`.split(','):[source];
  1363. let sourceStr = Array.from(new Set(concatSourceArr)).join(',');
  1364. this.$set(this.sourceFrom,'text',sourceStr)
  1365. this.$emit('updateSourceName')
  1366. },
  1367. // ==================================================合并单元格
  1368. // 选区开始
  1369. selectCellHandle(e) {
  1370. // 不是左键的mousedown事件
  1371. if(e.button!==0) return
  1372. if(this.disabled) return
  1373. this.isSelectionStart=true
  1374. let startTd;
  1375. if(e.target.nodeName==='TD'){
  1376. startTd = e.target
  1377. }else if(e.target.parentNode.nodeName==='TD'){
  1378. startTd = e.target.parentNode
  1379. }else if(e.target.parentNode.parentNode.nodeName==='TD'){
  1380. startTd = e.target.parentNode.parentNode
  1381. }else if(e.target.parentNode.parentNode.parentNode.nodeName==='TD'){
  1382. startTd = e.target.parentNode.parentNode.parentNode
  1383. }
  1384. if(!startTd) return
  1385. this.startCell={
  1386. row:+startTd.dataset.datarindex,
  1387. column:+startTd.dataset.datacindex
  1388. }
  1389. document.addEventListener('mousemove',this.selectZoneHandle)
  1390. document.addEventListener('mouseup',this.selectCellEndHandle)
  1391. },
  1392. // 选取
  1393. selectZoneHandle(e) {
  1394. if(!this.isSelectionStart) return
  1395. if(this.disabled) return
  1396. const selection = window.getSelection();
  1397. if (selection.rangeCount>0) {
  1398. // 清除选中的文本范围
  1399. selection.removeAllRanges();
  1400. }
  1401. let tableRect=this.$refs.tableRef.getBoundingClientRect()
  1402. const mouseX = e.pageX;
  1403. const mouseY = e.pageY;
  1404. let endTd;
  1405. if(mouseX >= tableRect.left && mouseX <= tableRect.right &&
  1406. mouseY >= tableRect.top && mouseY <= tableRect.bottom){
  1407. // 表格内
  1408. if(e.target.nodeName==='TD'){
  1409. endTd = e.target
  1410. }else if(e.target.parentNode.nodeName==='TD'){
  1411. endTd = e.target.parentNode
  1412. }else if(e.target.parentNode.parentNode.nodeName==='TD'){
  1413. endTd = e.target.parentNode.parentNode
  1414. }else if(e.target.parentNode.parentNode.parentNode.nodeName==='TD'){
  1415. endTd = e.target.parentNode.parentNode.parentNode
  1416. }
  1417. if(!endTd) return
  1418. this.endCell={
  1419. row:+endTd.dataset.datarindex,
  1420. column:+endTd.dataset.datacindex
  1421. }
  1422. }
  1423. },
  1424. // 选区结束
  1425. selectCellEndHandle(){
  1426. this.isSelectionStart=false
  1427. // click事件走在mouseup事件前面,延迟下
  1428. setTimeout(()=>{
  1429. if((this.selectionStart.row || this.selectionStart.row==0)
  1430. && (this.selectionEnd.row || this.selectionEnd.row==0)
  1431. && (this.selectionStart.column || this.selectionStart.column==0)
  1432. && (this.selectionEnd.column || this.selectionEnd.column==0)){
  1433. this.selectedCells=[]
  1434. resetStyle()
  1435. this.selectCell=null
  1436. // 选区
  1437. for (let i = this.selectionStart.row; i < this.selectionEnd.row+1; i++) {
  1438. for (let j = this.selectionStart.column; j < this.selectionEnd.column+1; j++) {
  1439. this.selectedCells.push(this.config.data[i][j])
  1440. }
  1441. }
  1442. }else{
  1443. this.selectedCells=[]
  1444. }
  1445. },1)
  1446. document.removeEventListener('mousemove',this.selectZoneHandle)
  1447. document.removeEventListener('mouseup',this.selectCellEndHandle)
  1448. },
  1449. findCellDom(key){
  1450. if(!key) return null
  1451. if(key !== this.cacheKey){
  1452. // 重新找
  1453. this.cacheCellDom = this.$refs.tableRef.querySelector(`[data-key="${key}"]`)
  1454. this.cacheKey=key
  1455. }
  1456. return this.cacheCellDom
  1457. },
  1458. // 确定选区范围和设置选区样式
  1459. setSelectionStyle(){
  1460. if(!this.isSelectionStart) return
  1461. // 开始的单元格没有
  1462. if(!( (this.startCell.row || this.startCell.row==0) &&
  1463. (this.startCell.column || this.startCell.column==0))) return
  1464. // 结束的单元格没有
  1465. if(!( (this.endCell.row || this.endCell.row==0) &&
  1466. (this.endCell.column || this.endCell.column==0))) return
  1467. // 递归确定选区范围
  1468. const findZone = ({sR,eR,sC,eC})=>{
  1469. this.hasValueCellItem.cellNumber=0
  1470. for (let i = sR; i < eR+1; i++) {
  1471. for (let j = sC; j < eC+1; j++) {
  1472. const element = this.config.data[i][j]
  1473. if(element.Value){
  1474. this.hasValueCellItem.cellNumber++
  1475. this.hasValueCellItem.row=i
  1476. this.hasValueCellItem.column=j
  1477. }
  1478. if(element.merData && element.merData.type==='merge'){
  1479. if(i+element.merData.mer.rowspan-1 > eR){
  1480. // 该单元格的行有合并 重新规定选取范围
  1481. return findZone({sR,eR:i+element.merData.mer.rowspan-1,sC,eC})
  1482. }
  1483. if(j+element.merData.mer.colspan-1 > eC){
  1484. // 该单元格的列有合并 重新规定选取范围
  1485. return findZone({sR,eR,sC,eC:j+element.merData.mer.colspan-1})
  1486. }
  1487. this.hasMergedCell=true
  1488. }
  1489. if(element.merData && element.merData.type==='merged' ){
  1490. let item = this.findCellDom(element.merData.mer.sKey)
  1491. let row = +item.dataset.datarindex
  1492. let col = +item.dataset.datacindex
  1493. if(row < sR){
  1494. // 该单元格的行有被合并 重新规定选取范围
  1495. return findZone({sR:row,eR,sC,eC})
  1496. }
  1497. if(col < sC){
  1498. // 该单元格的行有被合并 重新规定选取范围
  1499. return findZone({sR,eR,sC:col,eC})
  1500. }
  1501. this.hasMergedCell=true
  1502. }
  1503. }
  1504. }
  1505. // 防止选中的区域不是整个的单元格(合并后的),后面确定selectionRef 区域大小有问题
  1506. if(this.config.data[eR][eC].merData && this.config.data[eR][eC].merData.type==='merged'){
  1507. let item = this.findCellDom(this.config.data[eR][eC].merData.mer.sKey)
  1508. let row = +item.dataset.datarindex
  1509. let col = +item.dataset.datacindex
  1510. eR=row
  1511. eC=col
  1512. this.hasMergedCell=true
  1513. }
  1514. return {startR:sR,
  1515. endR:eR,
  1516. startC:sC,
  1517. endC:eC}
  1518. }
  1519. // 看是否是从下往上、从右往左选的
  1520. let rowReverse = this.startCell.row > this.endCell.row
  1521. let colReverse = this.startCell.column > this.endCell.column
  1522. let postion={
  1523. sR:rowReverse?this.endCell.row:this.startCell.row,
  1524. eR:rowReverse?this.startCell.row:this.endCell.row,
  1525. sC:colReverse?this.endCell.column:this.startCell.column,
  1526. eC:colReverse?this.startCell.column:this.endCell.column
  1527. }
  1528. this.hasMergedCell=false
  1529. const zone = findZone(postion)
  1530. let start = this.config.data[zone.startR][zone.startC]
  1531. let end = this.config.data[zone.endR][zone.endC]
  1532. this.selectionStart.row = zone.startR
  1533. this.selectionStart.column = zone.startC
  1534. this.selectionStart.rowSpan = start.merData?start.merData.mer.rowspan:1
  1535. this.selectionStart.colSpan = start.merData?start.merData.mer.colspan:1
  1536. this.selectionEnd.row = zone.endR
  1537. this.selectionEnd.column = zone.endC
  1538. this.selectionEnd.rowSpan = end.merData?end.merData.mer.rowspan:1
  1539. this.selectionEnd.colSpan = end.merData?end.merData.mer.colspan:1
  1540. let tableRect = this.$refs.tableRef.getBoundingClientRect()
  1541. let startTd = this.$refs.tableRef.querySelector(`[data-key="${start.Uid}"]`)
  1542. let endTd = this.$refs.tableRef.querySelector(`[data-key="${end.Uid}"]`)
  1543. if(!(startTd && endTd)) return
  1544. let startRect = startTd.getBoundingClientRect()
  1545. let endRect = endTd.getBoundingClientRect()
  1546. this.$refs.selectionRef.style.left = startRect.left-tableRect.left+'px'
  1547. this.$refs.selectionRef.style.top = startRect.top-tableRect.top+'px'
  1548. let width = Math.abs(endRect.right - startRect.right) + startRect.width
  1549. let height = Math.abs(endRect.bottom - startRect.bottom) + startRect.height
  1550. this.$refs.selectionRef.style.width = width+'px'
  1551. this.$refs.selectionRef.style.height = height + 'px'
  1552. this.$refs.selectionRef.style.visibility='visible'
  1553. },
  1554. clearSelection(){
  1555. this.$refs.selectionRef.style.width = 0
  1556. this.$refs.selectionRef.style.height = 0
  1557. this.$refs.selectionRef.style.visibility='hidden'
  1558. this.selectionStart={
  1559. row:null,
  1560. rowSpan:0,
  1561. column:null,
  1562. colSpan:0
  1563. }
  1564. this.selectionEnd={
  1565. row:null,
  1566. rowSpan:0,
  1567. column:null,
  1568. colSpan:0,
  1569. }
  1570. this.selectedCells=[]
  1571. },
  1572. mergeCellFun(){
  1573. // 无选区
  1574. if(!((this.selectionStart.row || this.selectionStart.row==0)
  1575. && (this.selectionEnd.row || this.selectionEnd.row==0)
  1576. && (this.selectionStart.column || this.selectionStart.column==0)
  1577. && (this.selectionEnd.column || this.selectionEnd.column==0))) return
  1578. if(this.hasValueCellItem.cellNumber>1 || this.hasValueCellItem.cellNumber<0){
  1579. return this.$message.warning(this.$t('ETable.Msg.merge_cell_fail_msg'))
  1580. }
  1581. const firstCell = this.config.data[this.selectionStart.row][this.selectionStart.column]
  1582. if(this.hasValueCellItem.cellNumber!=0 && (this.hasValueCellItem.row!=this.selectionStart.row || this.hasValueCellItem.column!=this.selectionStart.column)){
  1583. const reserveCell=this.config.data[this.hasValueCellItem.row][this.hasValueCellItem.column]
  1584. // 将原本有值的单元格 移给左上角第一个单元格
  1585. firstCell.ShowValue=reserveCell.ShowValue
  1586. firstCell.ShowStyle=reserveCell.ShowStyle
  1587. firstCell.ShowFormatValue=reserveCell.ShowFormatValue
  1588. firstCell.Value=reserveCell.Value
  1589. firstCell.DataType=reserveCell.DataType
  1590. firstCell.DataTimeType=reserveCell.DataTimeType
  1591. firstCell.DataTime=reserveCell.DataTime
  1592. firstCell.EdbInfoId=reserveCell.EdbInfoId
  1593. reserveCell.CanEdit && (firstCell.CanEdit=reserveCell.CanEdit)
  1594. reserveCell.Extra && (firstCell.Extra=reserveCell.Extra)
  1595. // 处理合并后的依赖关系 就是替换
  1596. this.replaceCellRelation(reserveCell.Uid,firstCell.Uid)
  1597. // 清空
  1598. this.clearCell(reserveCell)
  1599. }
  1600. this.$set(firstCell,'merData',{
  1601. type:'merge',
  1602. mer:{
  1603. sKey:firstCell.Uid,//保留的单元格的Uid
  1604. rowspan: this.selectionEnd.row - this.selectionStart.row+1,
  1605. colspan: this.selectionEnd.column - this.selectionStart.column+1,
  1606. }
  1607. })
  1608. for (let i = this.selectionStart.row; i < this.selectionEnd.row+1; i++) {
  1609. for (let j = this.selectionStart.column; j < this.selectionEnd.column+1; j++) {
  1610. const element = this.config.data[i][j]
  1611. if(i == this.selectionStart.row && j == this.selectionStart.column){
  1612. continue
  1613. }
  1614. element.merData={
  1615. type:'merged',
  1616. mer:{
  1617. sKey:firstCell.Uid,//左上角第一个单元格的Uid
  1618. }
  1619. }
  1620. }
  1621. }
  1622. let startCell = this.config.data[this.selectionStart.row][this.selectionStart.column]
  1623. let target = this.$refs.tableRef.querySelector(`[data-key="${startCell && startCell.Uid}"]`)
  1624. // 触发单元格的点击事件
  1625. target.click()
  1626. },
  1627. unmergeCellsFun(){
  1628. if((this.selectionStart.row || this.selectionStart.row==0)
  1629. && (this.selectionEnd.row || this.selectionEnd.row==0)
  1630. && (this.selectionStart.column || this.selectionStart.column==0)
  1631. && (this.selectionEnd.column || this.selectionEnd.column==0)){
  1632. // 选区
  1633. for (let i = this.selectionStart.row; i < this.selectionEnd.row+1; i++) {
  1634. for (let j = this.selectionStart.column; j < this.selectionEnd.column+1; j++) {
  1635. this.unmergeCellFun(this.config.data[i][j])
  1636. }
  1637. }
  1638. }else{
  1639. // 单个单元格
  1640. this.selectCell && this.unmergeCellFun(this.selectCell)
  1641. }
  1642. this.hasMergedCell=false
  1643. // 取消合并后,调整选区(有的话)
  1644. if((this.selectionStart.row || this.selectionStart.row==0)
  1645. && (this.selectionEnd.row || this.selectionEnd.row==0)
  1646. && (this.selectionStart.column || this.selectionStart.column==0)
  1647. && (this.selectionEnd.column || this.selectionEnd.column==0)){
  1648. this.selectionStart.rowSpan=1
  1649. this.selectionStart.colSpan=1
  1650. this.selectionEnd.row += (this.selectionEnd.rowSpan-1)
  1651. this.selectionEnd.column += (this.selectionEnd.colSpan-1)
  1652. this.selectionEnd.rowSpan=1
  1653. this.selectionEnd.colSpan=1
  1654. }
  1655. },
  1656. unmergeCellFun(cell){
  1657. if(!(cell.merData && cell.merData.type=='merge')) return
  1658. let {row,col} = this.findDataByStartKey(cell.merData.mer.sKey)
  1659. const sRow = row,
  1660. sCol = col,
  1661. eRow = row+cell.merData.mer.rowspan-1,
  1662. eCol = col+cell.merData.mer.colspan-1
  1663. for (let i = sRow; i < eRow+1; i++) {
  1664. for (let j = sCol; j < eCol+1; j++) {
  1665. this.config.data[i][j].merData=null
  1666. }
  1667. }
  1668. },
  1669. toolCellMergeFun(){
  1670. if(this.hasMergedCell) this.unmergeCellsFun()
  1671. else this.mergeCellFun()
  1672. }
  1673. },
  1674. };
  1675. </script>
  1676. <style scoped lang="scss">
  1677. .nodata {
  1678. text-align: center;
  1679. font-size: 16px;
  1680. color: #666;
  1681. padding: 100px 0;
  1682. }
  1683. .table-wrapper {
  1684. width: 100%;
  1685. overflow: auto;
  1686. * { box-sizing: border-box; }
  1687. .formula-wrapper {
  1688. height: 42px;
  1689. display: flex;
  1690. align-items: center;
  1691. background: #fff;
  1692. border-radius: 4px;
  1693. box-shadow: 0 3px 6px rgba(0, 0, 0, 0.05);
  1694. border: 1px solid #DCDFE6;
  1695. margin-bottom: 15px;
  1696. padding: 0 15px;
  1697. }
  1698. .table td,th {
  1699. width: 104px;
  1700. min-width: 104px;
  1701. height: 35px;
  1702. max-height: 35px;
  1703. background: #fff;
  1704. text-align: center;
  1705. word-break: break-all;
  1706. border: 1px solid #dcdfe6;
  1707. overflow: hidden;
  1708. text-overflow: ellipsis;
  1709. position: relative;
  1710. color: #606266;
  1711. &.td-chose::after {
  1712. position: absolute;
  1713. top: 0;
  1714. left: 0;
  1715. right: 0;
  1716. bottom: 0;
  1717. content: "";
  1718. display: block;
  1719. outline: 0;
  1720. border: 2px solid #0033ff;
  1721. box-shadow: 0 0 5px rgba(73, 177, 249, 0.5);
  1722. }
  1723. &.td-relation::after {
  1724. position: absolute;
  1725. top: 0;
  1726. left: 0;
  1727. right: 0;
  1728. bottom: 0;
  1729. content: "";
  1730. display: block;
  1731. outline: 0;
  1732. border: 2px dashed #0033ff;
  1733. box-shadow: 0 0 5px rgba(73, 177, 249, 0.5);
  1734. }
  1735. // &.td-col-select::after {
  1736. // position: absolute;
  1737. // top: 0;
  1738. // left: 0;
  1739. // right: 0;
  1740. // bottom: 0;
  1741. // content: "";
  1742. // display: block;
  1743. // outline: 0;
  1744. // border: 1px solid rgb(24, 173, 24);
  1745. // border-bottom: none;
  1746. // border-top: none;
  1747. // }
  1748. // &.td-row-select::after {
  1749. // position: absolute;
  1750. // top: 0;
  1751. // left: 0;
  1752. // right: 0;
  1753. // bottom: 0;
  1754. // content: "";
  1755. // display: block;
  1756. // outline: 0;
  1757. // border: 1px solid rgb(24, 173, 24);
  1758. // border-left: none;
  1759. // border-right: none;
  1760. // }
  1761. &.td-choose-insert-target::after {
  1762. position: absolute;
  1763. top: 0;
  1764. left: 0;
  1765. right: 0;
  1766. bottom: 0;
  1767. content: "";
  1768. display: block;
  1769. outline: 0;
  1770. border: 2px dashed orange;
  1771. box-shadow: 0 0 5px rgba(73, 177, 249, 0.5);
  1772. }
  1773. }
  1774. .th-tg {
  1775. background: #ebeef5;
  1776. &:hover {
  1777. cursor: pointer;
  1778. background: #ddd;
  1779. /* border: 2px solid #409eff; */
  1780. }
  1781. &.sm {
  1782. width: 36px;
  1783. min-width: 36px;
  1784. max-width: 36px;
  1785. }
  1786. }
  1787. //整行选中
  1788. tr {
  1789. position: relative;
  1790. &.choose-all::after {
  1791. position: absolute;
  1792. top: 0;
  1793. left: 0;
  1794. right: 0;
  1795. bottom: 0;
  1796. content: "";
  1797. display: block;
  1798. outline: 0;
  1799. border: 2px solid #5897fb;
  1800. box-shadow: 0 0 5px rgba(73, 177, 249, 0.5);
  1801. }
  1802. }
  1803. .contextMenu-wrapper {
  1804. position: fixed;
  1805. z-index: 99;
  1806. top: -9999px;
  1807. left: -9999px;
  1808. background: #fff;
  1809. padding: 10px 0;
  1810. min-width: 180px;
  1811. max-height: 400px;
  1812. overflow-y: auto;
  1813. /* border: 1px solid #999; */
  1814. box-shadow: 0 1px 4px #999;
  1815. .item {
  1816. padding: 10px 25px;
  1817. cursor: pointer;
  1818. &:hover {
  1819. background-color: #f5f7fa;
  1820. }
  1821. &:hover .subMenu-wrapper {
  1822. display: block;
  1823. }
  1824. }
  1825. .subMenu-wrapper {
  1826. width: 180px;
  1827. /* display: none; */
  1828. padding: 10px 0;
  1829. /* box-shadow: 0 1px 4px #999; */
  1830. /* background: #fff; */
  1831. /* position: absolute;
  1832. right: -178px;
  1833. top:-205px;
  1834. max-height: 400px;
  1835. overflow-y: auto; */
  1836. .item {
  1837. &:hover {
  1838. background: #fff;
  1839. }
  1840. }
  1841. }
  1842. }
  1843. }
  1844. </style>
  1845. <style lang="scss">
  1846. .table-wrapper {
  1847. td {
  1848. .el-input__inner {
  1849. border: none;
  1850. outline: none;
  1851. text-align: center;
  1852. height: 34px;
  1853. line-height: 34px;
  1854. }
  1855. }
  1856. .el-input.is-disabled .el-input__inner {
  1857. background-color: #fff;
  1858. }
  1859. }
  1860. .formula-wrapper .el-input__inner { border: none; outline: none; }
  1861. .edb-select-popover {
  1862. width: 300px !important;
  1863. .edb-item {
  1864. display: flex;
  1865. justify-content: space-between;
  1866. align-items: center;
  1867. .edb-item-name {
  1868. max-width: 260px;
  1869. }
  1870. }
  1871. }
  1872. .mixed-edb-slide-collapse {
  1873. border: none !important;
  1874. .el-collapse-item__header {
  1875. padding: 0;
  1876. height: auto;
  1877. line-height: normal;
  1878. margin-bottom: 0 !important;
  1879. background: transparent !important;
  1880. }
  1881. .el-collapse-item__wrap {
  1882. background: transparent !important;
  1883. border: none !important;
  1884. }
  1885. .el-collapse-item__content {
  1886. padding: 0 !important;
  1887. }
  1888. }
  1889. .el-table__body-wrapper{
  1890. overflow-x: auto;
  1891. }
  1892. </style>