BalanceTable.vue 91 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779
  1. <template>
  2. <div class="table-wrapper" @keydown="handlekeyDownKeys">
  3. <template v-if="config.data.length">
  4. <!-- 工具栏 -->
  5. <toolBarSection
  6. v-if="!disabled"
  7. :cell="selectCell?selectCell:mergeSelectedCells" @cellMerge="toolCellMergeFun"
  8. @openConDialog="openConDialog"
  9. :echoParameter="{hasMergedCell}"
  10. />
  11. <!-- 公式显示区 -->
  12. <div class="formula-wrapper" v-if="!disabled">
  13. <span style="flex-shrink: 0; color: #c0c4cc">{{
  14. $t("OnlineExcelPage.formula_lable")
  15. }}</span>
  16. <el-input
  17. v-if="selectCell && selectCell.DataType === 6"
  18. v-model="selectCell.Value"
  19. @change="updateValueByFormula"
  20. />
  21. </div>
  22. <!-- startSelectTable?'text-select-disabled111':'' -->
  23. <div class="table-content-wrap">
  24. <div class="left-wrap">
  25. <div style="padding:20px;background-color: #fff;" @mouseleave="endSelection">
  26. <div class="table-wrap">
  27. <table
  28. id="myTable"
  29. width="auto"
  30. border="0"
  31. class="table"
  32. ref="tableRef"
  33. :style="disabled ? 'width:100%' : ''"
  34. style="position: relative;"
  35. @mousedown="selectCellHandle"
  36. >
  37. <thead>
  38. <tr>
  39. <!-- 行头 -->
  40. <th class="th-tg sm"></th>
  41. <!-- 列头 -->
  42. <th
  43. v-for="(item, index) in columnHeader"
  44. :key="index"
  45. class="th-tg th-col"
  46. :data-cindex="item"
  47. :data-rindex="-1"
  48. @contextmenu.prevent="rightClickHandle"
  49. >
  50. {{ item }}
  51. </th>
  52. </tr>
  53. </thead>
  54. <tbody>
  55. <tr v-for="(row, index) in config.data" :key="index">
  56. <!-- 行头 -->
  57. <th
  58. class="th-tg th-row sm"
  59. @contextmenu.prevent="rightClickHandle"
  60. :data-rindex="rowHeader[index]"
  61. :data-cindex="-1"
  62. >
  63. {{ rowHeader[index] }}
  64. </th>
  65. <td
  66. v-for="(cell, cell_index) in row"
  67. :key="`${index}_${cell_index}`"
  68. :data-rindex="rowHeader[index]"
  69. :data-cindex="columnHeader[cell_index]"
  70. :data-key="cell.Uid"
  71. :data-datarindex="index"
  72. :data-datacindex="cell_index"
  73. :style="cell.ShowStyle?getShowCss(cell.ShowStyle):{}"
  74. :initIndex="initIndex(index,cell_index,rowHeader[index],columnHeader[cell_index])"
  75. v-show="!cell.merData || cell.merData.type!=='merged'"
  76. :colspan="(cell.merData && cell.merData.type=='merge' && cell.merData.mer)?cell.merData.mer.colspan || 1:1"
  77. :rowspan="(cell.merData && cell.merData.type=='merge' && cell.merData.mer)?cell.merData.mer.rowspan || 1:1"
  78. @click="clickCell($event, cell)"
  79. @dblclick="dblClickCellHandle($event, cell)"
  80. @contextmenu.prevent="rightClickHandle($event, cell)"
  81. @mouseenter="getRelationEdbInfo(cell)"
  82. @copy="copyCellHandle($event, cell)"
  83. @paste="pasteCellHandle($event, cell)"
  84. @mousedown="startSelection(index, cell_index)"
  85. @mouseover="extendSelection(index, cell_index)"
  86. @mouseup="endSelection"
  87. :class="{
  88. 'td_selected': isSelected(index, cell_index),
  89. 'text-select-disabled':startSelectTable
  90. }"
  91. >
  92. <!-- 插入单元格禁止编辑 -->
  93. <!-- [4,5,6,7,8].includes(cell.DataType)&&!cell.CanEdit -->
  94. <template
  95. v-if="
  96. !cell.CanEdit ||
  97. disabled ||
  98. (cell.DataType === 1 &&
  99. [1, 2].includes(cell.DataTimeType))
  100. "
  101. >
  102. <!-- 单元格类型5 7显示指标浮窗 -->
  103. <el-popover
  104. v-if="[5, 7].includes(cell.DataType) && !disabled"
  105. placement="top-start"
  106. width="350"
  107. trigger="hover"
  108. >
  109. <ul>
  110. <li style="display: flex; margin: 10px">
  111. <label style="min-width: 80px">{{
  112. $t("OnlineExcelPage.indicator_name_lbl")
  113. }}</label>
  114. {{ cellrelationEdbInfo.EdbName }}
  115. </li>
  116. <li style="display: flex; margin: 10px">
  117. <label style="min-width: 80px">{{
  118. $t("OnlineExcelPage.lastest_date_lab")
  119. }}</label>
  120. {{ cellrelationEdbInfo.LatestDate }}
  121. </li>
  122. <li style="display: flex; margin: 10px">
  123. <label style="min-width: 80px">{{
  124. $t("Table.edb_id")
  125. }}</label>
  126. {{ cellrelationEdbInfo.EdbCode }}
  127. </li>
  128. </ul>
  129. <span
  130. slot="reference"
  131. :data-rindex="rowHeader[index]"
  132. :data-cindex="columnHeader[cell_index]"
  133. :data-datarindex="index"
  134. :data-datacindex="cell_index"
  135. :data-key="cell.Uid"
  136. >{{
  137. cell.ShowStyle
  138. ? cell.ShowFormatValue
  139. : cell.ShowValue
  140. }}</span
  141. >
  142. </el-popover>
  143. <!-- 数字格式化显示 -->
  144. <span
  145. v-else-if="cell.ShowStyle"
  146. :data-rindex="rowHeader[index]"
  147. :data-cindex="columnHeader[cell_index]"
  148. :data-datarindex="index"
  149. :data-datacindex="cell_index"
  150. :data-key="cell.Uid"
  151. >
  152. {{isShowDecimal(cell)?showDecimalValue(cell):isShowFormat(cell.ShowStyle)?cell.ShowFormatValue:cell.DataTime?cell.ShowValue:[7,6,5].includes(cell.DataType)?cell.ShowValue:cell.Value}}
  153. </span>
  154. <span
  155. :data-rindex="rowHeader[index]"
  156. :data-cindex="columnHeader[cell_index]"
  157. :data-datarindex="index"
  158. :data-datacindex="cell_index"
  159. :data-key="cell.Uid"
  160. v-else
  161. >{{ cell.ShowValue }}</span
  162. >
  163. </template>
  164. <el-autocomplete
  165. v-else
  166. v-model="cell.Value"
  167. :ref="`inputRef${cell.Uid}`"
  168. popper-class="edb-select-popover"
  169. :data-key="cell.Uid"
  170. :data-rindex="rowHeader[index]"
  171. :data-cindex="columnHeader[cell_index]"
  172. :data-datarindex="index"
  173. :data-datacindex="cell_index"
  174. :fetch-suggestions="searchTarget"
  175. @change.native="changeVal($event, cell)"
  176. @keydown.native="keyEnterHandle($event, cell)"
  177. @blur="
  178. () => {
  179. $set(cell, 'CanEdit', false);
  180. }
  181. "
  182. >
  183. <!-- @select="selectTarget($event,cell)"
  184. @click="clickCell($event, cell)"
  185. :highlight-first-item="cell.DataType===2"
  186. -->
  187. <template slot-scope="scope">
  188. <edbDetailPopover :info="scope.item">
  189. <div
  190. slot="reference"
  191. v-if="cell.DataType === 2"
  192. class="edb-item"
  193. >
  194. <span class="edb-item-name text_oneLine">{{
  195. scope.item.EdbName
  196. }}</span>
  197. <i
  198. class="el-icon-check"
  199. style="color: #0052d9; font-size: 18px"
  200. />
  201. </div>
  202. <div slot="reference" v-else>
  203. {{ scope.item.EdbName }}
  204. </div>
  205. </edbDetailPopover>
  206. </template>
  207. </el-autocomplete>
  208. </td>
  209. </tr>
  210. </tbody>
  211. <!-- 合并单元格选区 -->
  212. <div ref="selectionRef" id="selection-id"
  213. style="position: absolute;border: 2px solid #0052D9;background-color: rgba(0, 82, 217, 0.1);visibility: hidden;z-index: 1;pointer-events: none;"></div>
  214. <!-- 行列选中样式 -->
  215. <div ref="rowColSelectRef" id="row-col-select"
  216. style="position: absolute;border-color: #18ad18;border-style: solid;background-color: transparent;visibility: hidden;z-index: 1;pointer-events: none;"></div>
  217. </table>
  218. </div>
  219. </div>
  220. <!-- 底部sheet -->
  221. <div class="bot-sheet-box">
  222. <ul class="sheet-list">
  223. <div
  224. class="sheet-item"
  225. v-for="(item, index) in sheetOpts"
  226. :key="item.ExcelInfoId"
  227. @contextmenu.prevent="handleShowSheetDel(index)"
  228. @mouseleave="item.showDel=false"
  229. >
  230. <div class="del-box" v-show="item.showDel" @click="delChildSheet">
  231. <span>{{$t('Table.delete_btn')}}</span>
  232. </div>
  233. <div
  234. :class="['el-button el-button--default el-button--mini box',activeSheetId===item.ExcelInfoId?'active':'']"
  235. size="mini"
  236. @dblclick="handleDbclickSheet(item)"
  237. @click="clickChangeSheet(item)"
  238. >
  239. <span class="text" v-if="!item.isEdit">{{ item.ExcelName }}</span>
  240. <input
  241. ref="sheetInput"
  242. v-else
  243. class="input"
  244. type="text"
  245. v-model="temSheetInputVal"
  246. @blur="handleModifySheetName"
  247. @keyup.enter="handleModifySheetName"
  248. />
  249. </div>
  250. </div>
  251. <el-button
  252. size="mini"
  253. icon="el-icon-plus"
  254. @click="handleAddSheet"
  255. v-if="!disabled&&sheetOpts.length < 10"
  256. ></el-button>
  257. </ul>
  258. <el-button type="text" icon="el-icon-plus" @click="isShowAddChart=true;clearSelection()" v-if="!disabled">{{$t('Chart.add_chart_btn')}}</el-button>
  259. </div>
  260. </div>
  261. <!-- 图表模块 -->
  262. <div class="right-wrap" v-if="chartList.length>0">
  263. <div class="chart-list">
  264. <BalanceSheetChartItem
  265. :chartData="item"
  266. :disabled="disabled"
  267. :isStaticTable="isStaticTable"
  268. v-for="item in chartList"
  269. :key="item.ChartInfo.ChartInfoId"
  270. @edit="handleEditChart"
  271. @delete="handleDelChart"
  272. />
  273. </div>
  274. </div>
  275. </div>
  276. <!-- 右键菜单 -->
  277. <div
  278. class="contextMenu-wrapper"
  279. id="contextMenu-wrapper"
  280. @mouseleave="
  281. () => {
  282. activeNames = [];
  283. hideContextMenu();
  284. }
  285. "
  286. >
  287. <div
  288. :class="['item', { deletesty: menu.key === 'reset' }]"
  289. v-for="menu in config.contextMenuOption"
  290. :key="menu.key"
  291. @click="handleContext(menu.key)"
  292. >
  293. <span v-if="!menu.children">{{ menu.label }}</span>
  294. <el-collapse
  295. v-model="activeNames"
  296. @change="handleChange"
  297. v-if="menu.children"
  298. >
  299. <el-collapse-item name="1">
  300. <template slot="title">
  301. {{ menu.label }}
  302. </template>
  303. <div class="subMenu-wrapper">
  304. <div
  305. slot="reference"
  306. class="item"
  307. v-for="submenu in menu.children"
  308. :key="submenu.key"
  309. @click="edbCalculateInsertOpen(submenu)"
  310. >
  311. <el-popover width="300" trigger="hover" placement="right">
  312. <div v-html="formulaTip.get(submenu.fromEdbKey)"></div>
  313. <div slot="reference" style="width: 100%">
  314. {{ submenu.label }}
  315. </div>
  316. </el-popover>
  317. </div>
  318. </div>
  319. </el-collapse-item>
  320. </el-collapse>
  321. <!-- 二级菜单 -->
  322. <!-- <div class="subMenu-wrapper" v-if="menu.children">
  323. <div slot="reference" class="item" v-for="submenu in menu.children" :key="submenu.key" @click="edbCalculateInsertOpen(submenu)">
  324. <el-popover
  325. width="300"
  326. trigger="hover"
  327. placement="right"
  328. >
  329. <div v-html="formulaTip.get(submenu.fromEdbKey)"></div>
  330. <div slot="reference" style="width:100%">{{submenu.label}}</div>
  331. </el-popover>
  332. </div>
  333. </div> -->
  334. </div>
  335. </div>
  336. </template>
  337. <div class="nodata" v-else>
  338. <tableNoData :text="$t('Table.prompt_slogan')" />
  339. </div>
  340. <!-- 选择指标 -->
  341. <selectTargetValueDia
  342. :isShow.sync="isSelectTargetValueDialog"
  343. :info="insertTargetValueInfo"
  344. @insert="insertSelectData"
  345. ref="selectTargetValueRef"
  346. />
  347. <!-- 插入系统/指标日期弹窗 -->
  348. <insertDateDia
  349. :isShow.sync="isInsertDateDialog"
  350. :info="insertDateInfo"
  351. @insert="insertDatehandle"
  352. />
  353. <!-- 指标计算弹窗 -->
  354. <calculateEdbDia
  355. ref="calculateEdbDiaRef"
  356. :isShow.sync="isInsertCalculate"
  357. :info="insertCalculateInfo"
  358. @insert="insertCalculateData"
  359. />
  360. <!-- 日期计算弹窗 -->
  361. <calculateDateDia
  362. ref="calculateDateDiaRef"
  363. :isShow.sync="isInsertCalculateDate"
  364. :info="insertCalculateDateInfo"
  365. @insert="insertCalculateDateValue"
  366. />
  367. <!-- 添加图表 -->
  368. <BalanceAddChart
  369. ref="balanceAddChart"
  370. :isShow.sync="isShowAddChart"
  371. :ExcelInfoId="activeSheetId"
  372. @success="addChartSuccess"
  373. />
  374. <condition-dia
  375. :chooseCell="selectCell?selectCell:mergeSelectedCells"
  376. ref="conditionDia"
  377. @changeRule="getExcelRule"
  378. @deleteRule="deleteExcelRule"
  379. @editRule="editExcelRule"
  380. />
  381. </div>
  382. </template>
  383. <script>
  384. import {
  385. getRowHeaderCode,
  386. getColumnHeaderCode,
  387. selectCellStyle,
  388. selectMoreCellStyle,
  389. setRelationStyle,
  390. getRightClickMenu,
  391. checkDateFormat,
  392. setFocus,
  393. findCellByKey,
  394. resetRelationStyle,
  395. resetDialogCellStyle,
  396. extractFactorsFromFormula,
  397. findCellByFactorMixed,
  398. splitString,
  399. toUpperCase,
  400. findCellKeyByFactor,
  401. isNumberVal,
  402. transDecimalPlace,
  403. resetStyle
  404. } from "../common/customTable";
  405. import * as sheetInterface from "@/api/modules/sheetApi.js";
  406. import { dataBaseInterface } from '@/api/api.js';
  407. import md5 from '@/utils/md5.js';
  408. import selectTargetValueDia from './selectTargetValueDia.vue';
  409. import insertDateDia from './insertDateDia.vue';
  410. import calculateEdbDia from './calculateEdbDia.vue';
  411. import calculateDateDia from './calculateDateDia.vue';
  412. import toolBarSection from './toolBarSection.vue';
  413. import { formulaTip } from '@/views/dataEntry_manage/databaseComponents/util';
  414. import BalanceAddChart from './BalanceAddChart.vue';
  415. import conditionDia from './conditionDia.vue'
  416. import BalanceSheetChartItem from './BalanceSheetChartItem.vue';
  417. import conditionTableMixin from "../mixins/conditionTableMixin.js"
  418. let autoSaveInterval=null;//自动保存定时器
  419. let dblclickInterval=null;//双击事件的定时器 为了解决同一个元素双击事件重复触发单击事件的问题
  420. export default {
  421. mixins:[conditionTableMixin],
  422. props: {
  423. disabled: { //是否只预览
  424. type: Boolean,
  425. default: false,
  426. },
  427. isStaticTable:{//当前是否为静态表
  428. type: Boolean,
  429. default: false,
  430. }
  431. },
  432. components: {
  433. conditionDia,
  434. selectTargetValueDia,
  435. insertDateDia,
  436. calculateEdbDia,
  437. calculateDateDia,
  438. toolBarSection,
  439. BalanceAddChart,
  440. BalanceSheetChartItem
  441. },
  442. computed: {
  443. //列头
  444. columnHeader() {
  445. return getColumnHeaderCode(
  446. this.config.data[0] ? this.config.data[0].length : 0
  447. );
  448. },
  449. //行头
  450. rowHeader() {
  451. let total_length = this.config.data.length;
  452. // console.log(this.config.data)
  453. return getRowHeaderCode(total_length);
  454. },
  455. },
  456. data() {
  457. return {
  458. config: {
  459. /* 单元格类型
  460. 1手动日期格 DataTimeType 0 /系统日期导入格 DataTimeType 1 /指标日期导入格 DataTimeType 2
  461. 2指标格 //eta1.5.6又弃用了
  462. 3自定义输入
  463. 4插入值 表格里有关联的日期和指标格 // eta1.1.6弃用了
  464. 5弹窗里的插入值 有关联日期格
  465. 6公式计算单元格
  466. 7指标计算的插入值单元格
  467. 8日期计算值单元格
  468. */
  469. data: [],
  470. contextMenuOption: [],
  471. },
  472. selectCell: {},//选中单元格info
  473. rightClickCell: {},//右键单元格 key c r
  474. insertTargetCell: {},//选择右键插入时的单元格 可和右键单元格不一样 key c r
  475. insertRelationArr: [], //表格单元格依赖关系数组
  476. isSelectTargetValueDialog: false,//选择指标插入值弹窗
  477. insertTargetValueInfo: {},//编辑 关联info
  478. cellrelationEdbInfo: {}, //指标浮窗信息
  479. copyCellItem: {},//复制时的单元格信息 用于粘贴赋值
  480. calculateClickCell: null,//双击公式单元格时的单元格信息 用于之后选其他单元格拼接公式
  481. isInsertDateDialog: false,//导入日期弹窗
  482. insertDateInfo: {},
  483. isInsertCalculate: false,//插入指标计算值
  484. insertCalculateInfo: {},//指标计算单元格info
  485. formulaTip,
  486. hasInit: false,
  487. isInsertCalculateDate: false,//日期计算弹窗
  488. insertCalculateDateInfo: {},//日期计算info
  489. activeNames: [],
  490. sheetOpts: [
  491. // {
  492. // ...
  493. // isEdit: false,//双击后修改名称置为true
  494. // showDel: false
  495. // }
  496. ],//表格sheet
  497. temSheetInputVal: '',
  498. activeSheetId:0,//当前子表id
  499. isShowAddChart:false,//添加图表
  500. chartList:[],//当前平衡表图表数据
  501. startSelectTable:false,//开始选择单元格
  502. selectionStart: null,
  503. selectionEnd: null,
  504. selectedCells: [],
  505. // 合并单元格data
  506. isSelectionStart:false, //选区开始
  507. startCell:{// 选区时鼠标开始的单元格
  508. row:null,
  509. column:null
  510. },
  511. endCell:{// 选区时鼠标结束的单元格
  512. e:null,
  513. row:null,
  514. column:null
  515. },
  516. mergeSelectionStart:{// 选区范围的左上角单元格
  517. row:null,
  518. rowSpan:0,
  519. column:null,
  520. colSpan:0
  521. },
  522. mergeSelectionEnd:{// 选区范围的右下角角单元格
  523. row:null,
  524. rowSpan:0,
  525. column:null,
  526. colSpan:0
  527. },
  528. hasMergedCell:false,// 选区内是否有合并的单元格
  529. mergeSelectedCells:[],
  530. // 选区有'值'单元格 因为超一个单元格有值不让合并,所以记录一个就行
  531. hasValueCellItem:{
  532. cellNumber:0, //有几个
  533. row:null,
  534. column:null
  535. },
  536. // 做个缓存
  537. cacheKey:'',
  538. cacheCellDom:{},
  539. //规则列表
  540. excelRuleList:[]
  541. };
  542. },
  543. watch:{
  544. 'endCell.row':{
  545. handler(newVal){
  546. this.setSelectionStyle()
  547. }
  548. },
  549. 'endCell.column':{
  550. handler(newVal){
  551. this.setSelectionStyle()
  552. }
  553. }
  554. },
  555. mounted() {
  556. if(!this.disabled){
  557. // 每分钟自动保存一次
  558. autoSaveInterval=setInterval(() => {
  559. this.saveChildSheet()
  560. }, 60*1000);
  561. }
  562. },
  563. beforeDestroy(){
  564. // 清除自动保存定时器
  565. clearInterval(autoSaveInterval)
  566. },
  567. methods: {
  568. // 获取规则
  569. async getExcelRule(){
  570. const res = await dataBaseInterface.getRuleList({ExcelInfoId:this.activeSheetId})
  571. // console.log(res)
  572. if(res.Ret !== 200) return
  573. this.excelRuleList = res.Data.List?res.Data.List:[];
  574. this.commonInitCell()
  575. },
  576. // 打开选择条件格式弹框
  577. openConDialog({chooseItem,chooseCells}){
  578. this.$refs.conditionDia.openDialog(chooseItem,chooseCells,this.excelRuleList,this.activeSheetId)
  579. },
  580. // 获取图表数据
  581. async getChartList(){
  582. const res = await sheetInterface.getBalanceChartData({
  583. ExcelInfoId: Number(this.activeSheetId)
  584. })
  585. if(res.Ret!==200) return
  586. this.chartList=res.Data.List||[]
  587. },
  588. // 添加图表成功回调
  589. addChartSuccess(){
  590. this.isShowAddChart=false
  591. this.getChartList()
  592. },
  593. // 编辑图表
  594. handleEditChart(e){
  595. this.isShowAddChart=true
  596. this.clearSelection()
  597. this.$refs.balanceAddChart.initEditData(e)
  598. },
  599. //删除图表
  600. handleDelChart(e){
  601. sheetInterface.delBalanceChart({ChartInfoId:e.ChartInfo.ChartInfoId}).then(res=>{
  602. if(res.Ret===200){
  603. this.chartList=this.chartList.filter(item=>item.ChartInfo.ChartInfoId!==e.ChartInfo.ChartInfoId)
  604. }
  605. })
  606. },
  607. startSelection(startRow, startCol) {
  608. // 只有添加图标弹窗弹起时有效
  609. if(!this.isShowAddChart) return
  610. if(this.disabled) return
  611. console.log('开始选择');
  612. this.startSelectTable=true
  613. this.selectionStart = { row: startRow, col: startCol };
  614. this.selectionEnd = { row: startRow, col: startCol };
  615. this.selectedCells = [];
  616. },
  617. extendSelection(endRow, endCol) {
  618. if(this.disabled) return
  619. if (this.selectionStart) {
  620. const start = this.selectionStart;
  621. const end = { row: endRow, col: endCol };
  622. const minRow = Math.min(start.row, end.row);
  623. const maxRow = Math.max(start.row, end.row);
  624. const minCol = Math.min(start.col, end.col);
  625. const maxCol = Math.max(start.col, end.col);
  626. this.selectedCells = [];
  627. for (let row = minRow; row <= maxRow; row++) {
  628. for (let col = minCol; col <= maxCol; col++) {
  629. this.selectedCells.push({ row, col });
  630. }
  631. }
  632. this.selectionEnd = end;
  633. }
  634. },
  635. // 选择表格结束
  636. endSelection() {
  637. // 只有添加图标弹窗弹起时有效
  638. if(!this.isShowAddChart) return
  639. if(this.disabled) return
  640. console.log('结束选择');
  641. // console.log(this.selectedCells);
  642. // console.log(this.selectionStart,this.selectionEnd);
  643. if(this.selectionStart){
  644. // 找到当前sheet 数据
  645. const sobj=this.sheetOpts.filter(_e=>_e.ExcelInfoId===this.activeSheetId)[0]
  646. // 如果选择的不是同行或者同列
  647. if(!(this.selectionStart.col==this.selectionEnd.col||this.selectionStart.row==this.selectionEnd.row)){
  648. this.$message.warning(this.$t('CustomAnalysisPage.only_allowed_select_msg'));
  649. return
  650. }
  651. // 判断选择的顺序如果是从后往前选择交换 start 和end
  652. if((this.selectionStart.col==this.selectionEnd.col&&this.selectionStart.row>this.selectionEnd.row)||(this.selectionStart.row==this.selectionEnd.row&&this.selectionStart.col>this.selectionEnd.col)){
  653. const temStart=JSON.parse(JSON.stringify(this.selectionStart))
  654. const temEnd=JSON.parse(JSON.stringify(this.selectionEnd))
  655. this.selectionEnd=temStart
  656. this.selectionStart=temEnd
  657. }
  658. const str=`${sobj.ExcelName}!$${this.columnHeader[this.selectionStart.col]}$${this.selectionStart.row+1}:$${this.columnHeader[this.selectionEnd.col]}$${this.selectionEnd.row+1}`
  659. this.$refs.balanceAddChart.tableSelect(this.selectionStart,this.selectionEnd,str)
  660. }
  661. this.selectionStart = null;
  662. this.startSelectTable=false
  663. this.removeTextSelection()
  664. },
  665. isSelected(row, col) {
  666. return this.selectedCells.some(cell => cell.row === row && cell.col === col);
  667. },
  668. removeTextSelection() {
  669. if (window.getSelection) {
  670. if (window.getSelection().empty) {
  671. // Chrome, Firefox, Opera
  672. window.getSelection().empty();
  673. } else if (window.getSelection().removeAllRanges) {
  674. // IE/Edge
  675. window.getSelection().removeAllRanges();
  676. }
  677. } else if (document.selection) { // for IE < 9
  678. document.selection.empty();
  679. }
  680. },
  681. // 点击添加sheet
  682. async handleAddSheet() {
  683. // 先自动保存一次
  684. const flag=await this.saveChildSheet()
  685. if(!flag) return
  686. this.sheetOpts.push({
  687. ExcelName: '',
  688. ExcelInfoId:0,
  689. isEdit: true,
  690. showDel: false
  691. })
  692. this.temSheetInputVal = ''
  693. // 自动切换到新增的sheet
  694. this.changeSheet(this.sheetOpts[this.sheetOpts.length-1])
  695. this.$nextTick(() => {
  696. this.$refs.sheetInput[0].focus()
  697. })
  698. },
  699. // 双击编辑sheet名称
  700. handleDbclickSheet(item) {
  701. if(this.disabled) return
  702. clearTimeout(dblclickInterval)//清除双击事件的定时器
  703. item.isEdit = true
  704. this.temSheetInputVal = item.ExcelName
  705. this.$nextTick(() => {
  706. this.$refs.sheetInput[0].focus()
  707. })
  708. },
  709. // 修改sheet名称
  710. handleModifySheetName() {
  711. console.log('修改名称');
  712. // 名称为空
  713. if (!this.temSheetInputVal) {
  714. this.$confirm('图表名称未填写', '提示', {
  715. confirmButtonText: '输入表名',
  716. cancelButtonText: '取消创建',
  717. type: 'warning'
  718. }).then(() => {
  719. this.$nextTick(() => {
  720. this.$refs.sheetInput[0].focus()
  721. })
  722. }).catch(() => {
  723. if(this.activeSheetId===0){//当是新增表格时
  724. this.sheetOpts = this.sheetOpts.filter(e => e.ExcelInfoId)
  725. // 自动切换sheet
  726. this.changeSheet(this.sheetOpts[this.sheetOpts.length-1])
  727. }else{// 当编辑子表名称时 重置掉好了
  728. this.sheetOpts.forEach(_e=>{
  729. _e.isEdit=false
  730. })
  731. }
  732. });
  733. return
  734. }
  735. // 如果activeSheetId=0 则是新增的子表
  736. if(this.activeSheetId===0){
  737. this.createNewChildSheet()
  738. return
  739. }
  740. // 修改sheet名称
  741. sheetInterface.balanceChildTableRename({
  742. ExcelName:this.temSheetInputVal,
  743. ExcelInfoId:this.activeSheetId
  744. }).then(res=>{
  745. if(res.Ret===200){
  746. this.sheetOpts.forEach(item => {
  747. if (item.ExcelInfoId===this.activeSheetId) {
  748. item.ExcelName = this.temSheetInputVal
  749. item.isEdit = false
  750. }
  751. })
  752. }
  753. })
  754. },
  755. // 右键显示删除sheet
  756. handleShowSheetDel(index) {
  757. if(this.disabled) return
  758. if (this.sheetOpts.length === 1) return
  759. this.sheetOpts[index].showDel = true
  760. // 切换到该子表
  761. this.changeSheet(this.sheetOpts[index])
  762. },
  763. // 初始化子表列表数据
  764. initSheetListData(data){
  765. console.log(data);
  766. this.sheetOpts=data.map(item=>{
  767. return{
  768. ...item,
  769. isEdit:false,
  770. showDel:false
  771. }
  772. })
  773. this.changeSheet(this.sheetOpts[0])
  774. },
  775. // 切换sheet
  776. changeSheet(item){
  777. this.activeSheetId=item.ExcelInfoId
  778. this.getSheetDetail()
  779. this.clearSelection()
  780. },
  781. // 点击切换子表
  782. async clickChangeSheet(item){
  783. if(this.isShowAddChart){
  784. this.$message.warning('添加图表时禁止切换')
  785. return
  786. }
  787. clearTimeout(dblclickInterval)//清除双击事件的定时器
  788. dblclickInterval=setTimeout(async () => {
  789. if(item.ExcelInfoId===this.activeSheetId) return
  790. //保存一次
  791. const flag=this.disabled?true:await this.saveChildSheet()
  792. if(!flag) return
  793. this.changeSheet(item)
  794. }, 150);
  795. },
  796. /* 获取表格详情 */
  797. async getSheetDetail(type) {
  798. // 如果是新增一个子表此时为0 直接创建一个空表
  799. if(this.activeSheetId===0) {
  800. this.initData(null);
  801. return
  802. }
  803. const res = await sheetInterface.sheetDetail({
  804. ExcelInfoId: Number(this.activeSheetId)
  805. })
  806. if(type==='refresh'){
  807. this.$parent.updating=false
  808. }
  809. if(res.Ret !== 200) return
  810. // this.isCanEdit = res.Data.CanEdit
  811. // if(!res.Data.CanEdit){
  812. // this.$message.warning(`${res.Data.Editor}${this.$t('OnlineExcelPage.currently_editing_msg') }`)
  813. // setTimeout(()=>{
  814. // this.backHandle()
  815. // },2000)
  816. // return
  817. // }
  818. const { ExcelName,ExcelClassifyId,TableData,ModifyTime,Button } = res.Data;
  819. // this.sheetButton=Button
  820. // this.sheetForm.name=ExcelName
  821. // this.sheetForm.classify=ExcelClassifyId
  822. // this.$nextTick(()=>{
  823. // this.sheetInit=true
  824. // })
  825. this.updateTime = this.$moment(ModifyTime).format('YYYY-MM-DD HH:mm:ss')
  826. this.initData(TableData);
  827. // 获取平衡表中的图表
  828. this.getChartList()
  829. type==='refresh' && this.$message.success(this.$t('OnlineExcelPage.table_data_update_msg') )
  830. },
  831. // 新增子表
  832. async createNewChildSheet(){
  833. // 判断是否重名
  834. const isDupName=this.sheetOpts.some(e=>e.ExcelName===this.temSheetInputVal)
  835. if(isDupName) {
  836. this.$confirm('此名称已被使用,请尝试其他名称', this.$t('Dialog.warn_tit'), {
  837. confirmButtonText: this.$t('Dialog.confirm_btn'),
  838. type: 'warning',
  839. showClose:false,
  840. center:true,
  841. showCancelButton:false
  842. }).then(()=>{
  843. this.$nextTick(() => {
  844. this.$refs.sheetInput[0].focus()
  845. })
  846. })
  847. return
  848. }
  849. const params={
  850. ExcelName: this.temSheetInputVal,
  851. ExcelType: 1,
  852. ExcelImage: '',
  853. ExcelClassifyId:0,//写死
  854. Source: 5,
  855. ParentId:Number(this.$route.query.id),
  856. TableData: {
  857. CellRelation:"[]",
  858. Data:[]
  859. }
  860. }
  861. const res=await sheetInterface.sheetAdd(params)
  862. if(res.Ret===200){
  863. this.changeSheet({ExcelInfoId:res.Data.ExcelInfoId})
  864. // 更新sheetOpts 内容
  865. this.sheetOpts.forEach(item=>{
  866. if(item.ExcelInfoId===0){
  867. item.ExcelInfoId=res.Data.ExcelInfoId
  868. item.ExcelName=this.temSheetInputVal
  869. item.isEdit=false
  870. }
  871. })
  872. }else{
  873. //创建子表失败 删除sheetOpts这个数据 并且切换到左边一个表
  874. const index=this.sheetOpts.findIndex(_e=>_e.ExcelInfoId===this.activeSheetId)
  875. this.changeSheet(this.sheetOpts[index-1])
  876. this.sheetOpts.splice(index,1)
  877. }
  878. },
  879. // 保存子表 type:manualSave 手动保存
  880. async saveChildSheet(type){
  881. console.log('执行保存表格操作');
  882. const item=this.sheetOpts.filter(e=>e.ExcelInfoId===this.activeSheetId)[0]
  883. // console.log(item);
  884. // console.log(this.sheetOpts,this.activeSheetId);
  885. if(!this.activeSheetId) return
  886. const params={
  887. ExcelInfoId:this.activeSheetId,
  888. ExcelName: item.ExcelName,
  889. ExcelType: 1,
  890. ExcelClassifyId: 0,
  891. ExcelImage:'',
  892. Source: 5,
  893. ParentId:Number(this.$route.query.id),
  894. TableData: this.getSaveParams()
  895. }
  896. const res = await sheetInterface.sheetEdit(params)
  897. if(res.Ret !==200) return false
  898. if(res.Data.Status==1){//有人在编辑 不允许编辑返回到列表
  899. this.$message.warning(res.Data.Msg)
  900. setTimeout(() => {
  901. this.$router.back()
  902. }, 1000);
  903. return false
  904. }
  905. // 更新保存时间
  906. this.$parent.updateTime=this.$moment().format('YYYY-MM-DD HH:mm:ss')
  907. type==='manualSave'&&this.$message.success(this.$t('MsgPrompt.saved_msg'))
  908. return true
  909. },
  910. //删除子表
  911. async delChildSheet(){
  912. await this.$confirm(this.$t('ETable.Msg.is_del_table_msg') , this.$t('Confirm.prompt') , {
  913. confirmButtonText: this.$t('Dialog.confirm_btn'),
  914. cancelButtonText: this.$t('Dialog.cancel_btn'),
  915. type: "warning",
  916. })
  917. const res=await sheetInterface.classifyDel({
  918. ExcelInfoId:this.activeSheetId
  919. })
  920. if(res.Ret!==200) return
  921. this.$message.success(res.Msg);
  922. const index=this.sheetOpts.findIndex(_e=>_e.ExcelInfoId===this.activeSheetId)
  923. if(index===0){
  924. this.changeSheet(this.sheetOpts[index+1])
  925. }else{
  926. this.changeSheet(this.sheetOpts[index-1])
  927. }
  928. this.sheetOpts.splice(index,1)
  929. },
  930. /* 输入时实时搜索 满足日期格式不搜索 有=视为输入公式不搜索 eta1.5.6弃用了*/
  931. async searchTarget(query, cb) {
  932. return cb([])
  933. //又要过滤掉2020-05-这样的奇葩其他格式 不让检索
  934. let dateOtherRegex = /^(?:(?:19|20)\d\d)([-])(0[1-9]|1[0-2])(-?)$/
  935. if (!query
  936. || checkDateFormat(query)
  937. || dateOtherRegex.test(query)
  938. || query.startsWith('=')
  939. ) return cb([])
  940. const { DataType, EdbInfoId } = this.selectCell;
  941. const res = DataType === 2
  942. ? await dataBaseInterface.targetDetail({ EdbInfoId })
  943. : await sheetInterface.searchTarget({
  944. KeyWord: query,
  945. CurrentIndex: 1,
  946. PageSize: 1000
  947. })
  948. if (res.Ret !== 200) return
  949. let arr = DataType === 2 ? [res.Data] : (res.Data.List || [])
  950. cb(arr);
  951. },
  952. /* 单击 */
  953. clickCell(e, cell) {
  954. if (this.disabled) return
  955. selectCellStyle(e);
  956. this.clearSelection()
  957. this.hasMergedCell = !!(cell && cell.merData)
  958. this.selectCell = cell;
  959. setFocus(e);
  960. //是插值单元格时寻找关联依赖的单元格 设置选框
  961. if ([4, 5, 7].includes(cell.DataType)) {
  962. const { key } = e.target.dataset;
  963. if (!this.insertRelationArr.find(_ => _.key === key)) return
  964. let { relation_date, relation_edb } = this.insertRelationArr.find(_ => _.key === key)
  965. relation_date.key && setRelationStyle(relation_date)
  966. relation_edb.key && setRelationStyle(relation_edb)
  967. }
  968. //选择指标弹窗打开时选择日期更新弹窗数据
  969. this.isSelectTargetValueDialog && this.$refs.selectTargetValueRef.changeRleationDate(this.selectCell)
  970. //计算指标弹窗打开时选择日期更新弹窗数据
  971. this.isInsertCalculate && this.$refs.calculateEdbDiaRef.changeRleationDate(this.selectCell)
  972. //日期计算弹窗打开选中日期框时且有选中item时更新选中值
  973. cell.DataType === 1 && this.isInsertCalculateDate && this.$refs.calculateDateDiaRef.selectIndex && this.$refs.calculateDateDiaRef.setSelectItemValue(this.selectCell)
  974. },
  975. /* 插入值 往左往上寻找同行同列是否有符合条件的一指标一日期 */
  976. async insertValue() {
  977. let params = this.findNearestCell();
  978. console.log(params)
  979. if (!params) {
  980. this.selectCell.DataType = 3;
  981. this.selectCell.DataTimeType = 0;
  982. this.selectCell.ShowValue = '';
  983. this.selectCell.Value = '';
  984. this.selectCell.DataTime = '';
  985. this.selectCell.EdbInfoId = 0;
  986. this.$message.warning(this.$t('OnlineExcelPage.no_here_val_msg'));
  987. return
  988. }
  989. const { EdbInfoId, Date, DataTimeType } = params
  990. const res = await sheetInterface.insertData({ EdbInfoId, Date })
  991. if (res.Ret !== 200) return
  992. res.Data ? this.$message.success(this.$t('OnlineExcelPage.insert_success_msg')) : this.$message.warning(this.$t('OnlineExcelPage.the_date_no_val_msg'))
  993. this.selectCell.DataType = 4;
  994. this.selectCell.ShowValue = res.Data;
  995. this.selectCell.Value = res.Data;
  996. this.selectCell.EdbInfoId = EdbInfoId;
  997. this.selectCell.DataTime = Date;
  998. this.setRelation(params)
  999. },
  1000. // 建立插入单元格和依赖单元格关联关系
  1001. setRelation(data, cellType = 4) {
  1002. const { insert_cell } = data;
  1003. let relation_obj = {
  1004. type: cellType,
  1005. key: insert_cell.key,
  1006. relation_date: {
  1007. type: 1,
  1008. key: insert_cell.relation_date
  1009. },
  1010. relation_edb: {
  1011. type: 2,
  1012. key: insert_cell.relation_edb
  1013. }
  1014. }
  1015. let haveIndex = this.insertRelationArr.findIndex(_ => _.key === insert_cell.key);
  1016. if (haveIndex === -1) {
  1017. this.insertRelationArr.push(relation_obj)
  1018. } else {
  1019. this.insertRelationArr.splice(haveIndex, 1, relation_obj)
  1020. }
  1021. console.log(this.insertRelationArr)
  1022. },
  1023. /* 向左向上找出所有格子 找出离插入单元格最近的两个符合条件的单元格 看是否满足一指标一日期的条件
  1024. 不满足就无法插入值
  1025. */
  1026. findNearestCell() {
  1027. let { rindex, cindex, key } = this.rightClickCell;
  1028. let index_row = this.rowHeader.findIndex(_ => _ === rindex);
  1029. let index_col = this.columnHeader.findIndex(_ => _ === cindex);
  1030. //同行左侧所有格子
  1031. let row_cell_arr = this.config.data[index_row].filter((_, cell_index) => cell_index < index_col);
  1032. //同列上侧所有格子
  1033. let col_cell_arr = this.config.data.filter((row, row_index) => row_index < index_row).map(row => row[index_col]);
  1034. if (!row_cell_arr.length || !col_cell_arr.length) {
  1035. return null
  1036. }
  1037. //寻找最近的符合1 2类型的两个格子
  1038. let params = null;
  1039. for (let i = row_cell_arr.length - 1; i >= 0; i--) {
  1040. for (let j = col_cell_arr.length - 1; j >= 0; j--) {
  1041. if (!params) {
  1042. if ((row_cell_arr[i].DataType === 1 && col_cell_arr[j].DataType === 2)
  1043. || (row_cell_arr[i].DataType === 2 && col_cell_arr[j].DataType === 1)) {
  1044. params = {
  1045. DataTimeType: row_cell_arr[i].DataType === 1 ? row_cell_arr[i].DataTimeType : col_cell_arr[j].DataTimeType,
  1046. Date: row_cell_arr[i].DataType === 1 ? row_cell_arr[i].ShowValue : col_cell_arr[j].ShowValue,
  1047. EdbInfoId: row_cell_arr[i].DataType === 2 ? row_cell_arr[i].EdbInfoId : col_cell_arr[j].EdbInfoId,
  1048. insert_cell: {
  1049. key,
  1050. relation_date: row_cell_arr[i].DataType === 1 ? row_cell_arr[i].Uid : col_cell_arr[j].Uid,
  1051. relation_edb: row_cell_arr[i].DataType === 2 ? row_cell_arr[i].Uid : col_cell_arr[j].Uid,
  1052. },
  1053. }
  1054. break
  1055. }
  1056. }
  1057. }
  1058. }
  1059. return params;
  1060. },
  1061. /* 选择指标 单元格类型为2 已经是指标单元格了就重置单元格 否则就视为选择指标*/
  1062. selectTarget(e, cell) {
  1063. const { EdbName, EdbInfoId } = e;
  1064. //如果已经是指标单元格了再次点击就清空
  1065. if (cell.DataType === 2 && cell.EdbInfoId) {
  1066. this.clearCell()
  1067. } else {
  1068. cell.DataType = 2;
  1069. cell.DataTime = '';
  1070. cell.ShowValue = EdbName;
  1071. cell.Value = EdbName;
  1072. cell.EdbInfoId = EdbInfoId;
  1073. }
  1074. this.checkCellRelation(cell)
  1075. },
  1076. /* 输入框失焦 设置单元格类型 处理关联关系 */
  1077. async changeVal(e, cell) {
  1078. // 是日期格式 DataType为1
  1079. // 自定义内容 DataType 3
  1080. //有=号为输入公式 DataType 6
  1081. const { value } = e.target;
  1082. if (!value) { //无值重置单元格
  1083. cell.DataType = 3;
  1084. cell.ShowValue = value;
  1085. cell.Value = value;
  1086. cell.EdbInfoId = 0;
  1087. cell.DataTime = '';
  1088. cell.Extra = ''
  1089. } else {
  1090. //指标类型不做格式处理
  1091. if (cell.DataType === 2) return
  1092. console.log(checkDateFormat(value))
  1093. let dateFormat = checkDateFormat(value);
  1094. if (dateFormat) { //是日期格式
  1095. cell.DataType = 1;
  1096. cell.Extra = '';
  1097. cell.ShowValue = dateFormat;
  1098. cell.DataTime = dateFormat;
  1099. cell.Value = dateFormat;
  1100. } else if (value.startsWith('=')) { //公式单元格
  1101. cell.DataType = 6;
  1102. let calculateVal = await this.getValueByFormula(value);
  1103. if (!calculateVal) return
  1104. cell.ShowValue = calculateVal;
  1105. //处理公式关系
  1106. this.$set(cell, 'Extra', this.dealFormulaConstruction(value))
  1107. } else {//自定义值
  1108. cell.DataType = 3;
  1109. cell.ShowValue = value;
  1110. cell.Value = value;
  1111. cell.EdbInfoId = 0;
  1112. cell.DataTime = '';
  1113. cell.Extra = ''
  1114. }
  1115. }
  1116. /* 不是数字类型,清除原来设置的格式 */
  1117. if (!isNumberVal(value)) {
  1118. cell.ShowStyle = '';
  1119. cell.ShowStyle = '';
  1120. };
  1121. //判断是否是有插入值的依赖单元格 更新值或重置关系
  1122. this.checkCellRelation(cell)
  1123. this.commonInitCell('edit')
  1124. },
  1125. /* 当前单元格是否和插入值有关联 无就不管 */
  1126. async checkCellRelation(cell) {
  1127. if (!this.insertRelationArr.length) return
  1128. const key = cell.Uid;
  1129. //有关联的N组数组
  1130. let haveRelationArr = this.insertRelationArr.filter(_ => _.relation_date.key === key || _.relation_edb.key === key);
  1131. if (!haveRelationArr.length) return
  1132. //去处理每一组关联的情况
  1133. haveRelationArr.forEach(async (relation) => {
  1134. const { relation_date, relation_edb, type } = relation;
  1135. if ((relation_date.key === key && cell.DataType === 1) || (relation_edb.key === key && cell.DataType === 2)) { //单元格类型不变只变值仍有关联关系 更新值
  1136. // 根据关系关联数组去更新每种单元格类型的值
  1137. this.updateRelationCell(relation,cell)
  1138. } else {
  1139. // 清除插入值单元格式和关联关系
  1140. this.updateInsertCell(relation.key);
  1141. }
  1142. })
  1143. },
  1144. // 清除插入值单元格式和关联关系
  1145. updateInsertCell(key) {
  1146. this.config.data.forEach(row => {
  1147. row.forEach(cell => {
  1148. if (cell.Uid === key) {
  1149. cell.DataType = 3;
  1150. cell.EdbInfoId = 0;
  1151. cell.DataTime = '';
  1152. cell.ShowValue = '';
  1153. cell.Value = '';
  1154. cell.ShowStyle = ''
  1155. }
  1156. })
  1157. })
  1158. let relationIndex = this.insertRelationArr.findIndex(_ => _.key === key)
  1159. this.insertRelationArr.splice(relationIndex, 1)
  1160. },
  1161. // 替换关联关系
  1162. replaceCellRelation(originKey,replaceKey){
  1163. if(!this.insertRelationArr.length) return
  1164. this.insertRelationArr = JSON.parse(JSON.stringify(this.insertRelationArr).replaceAll(originKey,replaceKey))
  1165. },
  1166. /* 单元格更新时去更新有依赖关系单元格的值 目前只更4 5 7*/
  1167. updateRelationCell(relation,cell) {
  1168. const cellTypeMap = {
  1169. 4: this.refreshRelationInsertCell,
  1170. 5: this.refreshRelationByEdbInsertCell,
  1171. 7: this.refreshRelationByEdbCalculateCell,
  1172. }
  1173. cellTypeMap[relation.type]&& cellTypeMap[relation.type](relation,cell)
  1174. },
  1175. //关联类型4的单元格值刷新
  1176. async refreshRelationInsertCell({relation_date,relation_edb},cell) {
  1177. //刷新插入值结果
  1178. let params = null;
  1179. if(relation_date.key === key && cell.DataType === 1) { //修改的是依赖日期格
  1180. let { EdbInfoId } = findCellByKey(this.config.data,relation.key)
  1181. params = {
  1182. EdbInfoId,
  1183. Date: cell.ShowValue
  1184. }
  1185. } else if( relation_edb.key === key && cell.DataType === 2) { //修改的依赖指标格
  1186. let {ShowValue} = findCellByKey(this.config.data,relation_date.key)
  1187. params = {
  1188. EdbInfoId: cell.EdbInfoId,
  1189. Date: ShowValue
  1190. }
  1191. }
  1192. const res = await sheetInterface.insertData(params)
  1193. if(res.Ret !==200) return
  1194. //现在日期无值也不清除关系了
  1195. // !res.Data && this.clearInsertCell(relation.key);
  1196. this.config.data.forEach(row => {
  1197. row.forEach(cell => {
  1198. if(cell.Uid === relation.key) {
  1199. cell.DataType = relation.type;
  1200. cell.ShowValue = res.Data;
  1201. cell.Value = res.Data;
  1202. cell.EdbInfoId = params.EdbInfoId;
  1203. cell.DataTime = params.Date;
  1204. }
  1205. })
  1206. })
  1207. },
  1208. //关联类型5的弹窗插值单元格值刷新
  1209. async refreshRelationByEdbInsertCell(relation,cell) {
  1210. let { EdbInfoId,Value } = findCellByKey(this.config.data,relation.key)
  1211. let params = {
  1212. EdbInfoId,
  1213. MoveForward: JSON.parse(Value).MoveForward,
  1214. DateChange: JSON.parse(Value).DateChange,
  1215. Date: cell.ShowValue
  1216. }
  1217. const res = await sheetInterface.getDateLatelyData(params)
  1218. if(res.Ret !== 200) return
  1219. let value = (res.Data.List&&res.Data.List.length)
  1220. ? res.Data.List.find(_ => _.DataTime===res.Data.Date)
  1221. ? res.Data.List.find(_ => _.DataTime===res.Data.Date).Value.toString()
  1222. : ''
  1223. : ''
  1224. this.config.data.forEach(row => {
  1225. row.forEach(cell => {
  1226. if(cell.Uid === relation.key) {
  1227. cell.ShowValue = value;
  1228. cell.ShowFormatValue = cell.ShowStyle ? transDecimalPlace(value,JSON.parse(cell.ShowStyle)) : '';
  1229. }
  1230. })
  1231. })
  1232. },
  1233. //关联类型7的指标计算单元格值刷新
  1234. async refreshRelationByEdbCalculateCell(relation,cell) {
  1235. console.log(relation,cell)
  1236. console.log(findCellByKey(this.config.data,relation.key))
  1237. let { Value } = findCellByKey(this.config.data,relation.key)
  1238. const {
  1239. Source,
  1240. Frequency,
  1241. Formula,
  1242. EdbInfoId,
  1243. MoveFrequency,
  1244. MoveType,
  1245. Calendar,
  1246. MoveForward,
  1247. DateChange
  1248. } = JSON.parse(Value);
  1249. let params = {
  1250. DataTime: cell.ShowValue,
  1251. Source,
  1252. Frequency,
  1253. Formula,
  1254. EdbInfoId,
  1255. MoveFrequency,
  1256. MoveType,
  1257. Calendar,
  1258. MoveForward,
  1259. DateChange,
  1260. }
  1261. const res = await sheetInterface.getMixedCalculateData(params)
  1262. if(res.Ret !== 200) return
  1263. let value = res.Data.ShowValue||"";
  1264. this.config.data.forEach(row => {
  1265. row.forEach(cell => {
  1266. if(cell.Uid === relation.key) {
  1267. cell.ShowValue = value;
  1268. cell.ShowFormatValue = cell.ShowStyle ? transDecimalPlace(value,JSON.parse(cell.ShowStyle)) : '';
  1269. }
  1270. })
  1271. })
  1272. },
  1273. /* 输入公式的计算值 */
  1274. async getValueByFormula(val) {
  1275. // 提取因数数组
  1276. let factors = extractFactorsFromFormula(val)
  1277. console.log(factors)
  1278. //根据因数找单元格
  1279. let isAllCell = factors.some(_ => findCellByFactorMixed(this.config.data, _) === null || isNaN(findCellByFactorMixed(this.config.data, _)))
  1280. if (isAllCell) {
  1281. this.$message.warning(this.$t('OnlineExcelPage.formula_val_error_msg'))
  1282. return '';
  1283. }
  1284. let TagMap = {};
  1285. factors.forEach(_ => {
  1286. if (!TagMap[_]) {
  1287. TagMap[_] = Number(findCellByFactorMixed(this.config.data, _))
  1288. }
  1289. });
  1290. const res = await sheetInterface.calculateCustomCellData({
  1291. CalculateFormula: val,
  1292. TagMap
  1293. })
  1294. if (res.Ret !== 200) return
  1295. return res.Data
  1296. },
  1297. /* 顶部公式改变 */
  1298. async updateValueByFormula(value) {
  1299. this.changeVal({ target: { value } }, this.selectCell)
  1300. },
  1301. /* 右键 */
  1302. rightClickHandle(e, cell) {
  1303. if (this.disabled) return
  1304. const { rindex, cindex, key,datacindex,datarindex } = e.target.dataset;
  1305. this.rightClickCell = {
  1306. rindex,
  1307. cindex,
  1308. datarindex,
  1309. datacindex,
  1310. key
  1311. }
  1312. this.selectCell = cell;
  1313. let pos;
  1314. if (rindex === '-1') { //列头处
  1315. pos = 'col'
  1316. } else if (cindex === '-1') { //行头
  1317. pos = 'row'
  1318. } else if( datarindex>=this.mergeSelectionStart.row && datarindex<=this.mergeSelectionEnd.row &&
  1319. datacindex>=this.mergeSelectionStart.column && datacindex<=this.mergeSelectionEnd.column &&
  1320. (this.mergeSelectionEnd.row-this.mergeSelectionStart.row>0||this.mergeSelectionEnd.column-this.mergeSelectionStart.column>0)){
  1321. // 选区
  1322. pos = 'selection'
  1323. }else {//单元格
  1324. pos = 'cell'
  1325. }
  1326. pos === 'cell' && this.clickCell(e, cell);
  1327. this.config.contextMenuOption = pos === 'cell'
  1328. ? getRightClickMenu(pos, (cell.DataType === 1 && [1, 2].includes(cell.DataTimeType)) || [5, 7, 8].includes(cell.DataType),this.isStaticTable,{cellMerged:this.hasMergedCell})
  1329. : getRightClickMenu(pos,false,false,{cellMerged:this.hasMergedCell})
  1330. this.$nextTick(() => {
  1331. let dom = $('#contextMenu-wrapper')[0];
  1332. if (e.clientY > window.innerHeight / 2) {
  1333. dom.style.left = e.clientX - 3 + 'px';
  1334. dom.style.top = e.clientY - dom.offsetHeight - 3 + 'px';
  1335. } else {
  1336. dom.style.left = e.clientX - 3 + 'px';
  1337. dom.style.top = e.clientY - 3 + 'px';
  1338. }
  1339. if(['col','row'].includes(pos)){
  1340. this.clearSelection()
  1341. selectMoreCellStyle(e);
  1342. }
  1343. })
  1344. },
  1345. /* */
  1346. hideContextMenu() {
  1347. const dom = $('#contextMenu-wrapper')[0];
  1348. dom.style.left = '-9999px';
  1349. dom.style.top = '-9999px';
  1350. },
  1351. /* 右键事件 */
  1352. async handleContext(key) {
  1353. //可右键编辑的单元格类型
  1354. let editHandlesMap = {
  1355. 1: this.insertDateOpen,
  1356. 5: this.selectTargetOpen,
  1357. 7: this.edbCalculateInsertOpen,
  1358. 8: this.insertDateCalculateOpen
  1359. }
  1360. const keyMap = {
  1361. 'del': this.delColOrRow,//删除
  1362. 'insert-col-left': this.insertCol,//向左插入列
  1363. 'insert-col-right': this.insertCol,//向右插入列
  1364. 'insert-row-up': this.insertRow,//向上插入行
  1365. 'insert-row-down': this.insertRow,//向下插入行
  1366. 'insert-value': this.insertValue,//插入值
  1367. 'choose-target': this.selectTargetOpen,//选择指标插入值
  1368. 'insert-date': this.insertDateOpen,//导入系统日期
  1369. // 'insert-edb-date': this.insertDateOpen,//导入指标日期
  1370. 'insert-date-calculate': this.insertDateCalculateOpen,//日期计算弹窗
  1371. 'reset': this.clearCell, //清空
  1372. 'cell-edit': this.selectCell ? editHandlesMap[this.selectCell.DataType] : null,
  1373. 'cell-merge':this.mergeCellFun,
  1374. 'cell-unmerge':this.unmergeCellsFun
  1375. }
  1376. keyMap[key] && keyMap[key](key)
  1377. key !== 'insert-edb-calculate' && this.hideContextMenu()
  1378. },
  1379. /* 打开选择指标弹窗
  1380. 打开弹窗后仍可以在页面上点击 多存一个选择指标时的当前单元格信息 */
  1381. selectTargetOpen(type) {
  1382. this.insertTargetCell = this.selectCell;
  1383. resetDialogCellStyle();
  1384. setRelationStyle({ key: this.insertTargetCell.Uid }, 'td-choose-insert-target')
  1385. if (type === 'cell-edit') {
  1386. this.insertTargetValueInfo = {
  1387. ...this.insertTargetCell
  1388. }
  1389. } else {
  1390. this.insertTargetValueInfo = {}
  1391. }
  1392. this.isSelectTargetValueDialog = true;
  1393. this.resetDialogStatus('insertEdbVal')
  1394. },
  1395. /* 插入选择指标的值 */
  1396. insertSelectData({ edbId, value, relationDate, relationUid, str }) {
  1397. this.insertTargetCell.DataType = 5;
  1398. this.insertTargetCell.ShowValue = value;
  1399. this.insertTargetCell.Value = str;
  1400. this.insertTargetCell.EdbInfoId = edbId;
  1401. this.insertTargetCell.DataTime = relationDate;
  1402. this.insertTargetCell.ShowFormatValue = this.insertTargetCell.ShowStyle ? transDecimalPlace(value, JSON.parse(this.insertTargetCell.ShowStyle)) : '';
  1403. value ? this.$message.success(this.$t('ETable.Msg.insertion_success_msg')) : this.$message.warning(this.$t('ETable.Msg.date_no_data'))
  1404. //如果有关联表格日期就建立新的关联关系
  1405. if (relationDate && relationUid) {
  1406. let relation = {
  1407. insert_cell: {
  1408. key: this.insertTargetCell.Uid,
  1409. relation_date: relationUid,
  1410. relation_edb: '',
  1411. }
  1412. }
  1413. this.setRelation(relation, 5);
  1414. } else { //重新插值后之后原来有关联的清除关系
  1415. let haveIndex = this.insertRelationArr.findIndex(_ => _.key === this.insertTargetCell.Uid);
  1416. haveIndex !== -1 && this.insertRelationArr.splice(haveIndex, 1)
  1417. resetRelationStyle();
  1418. }
  1419. this.commonInitCell('edit')
  1420. },
  1421. /* 清除单元格内容 格式 关联关系 */
  1422. clearCell(c) {
  1423. const isCell = c && typeof(c)=='object' && c.Uid
  1424. const cell = isCell ? c: this.selectCell
  1425. if ([4, 5].includes(cell.DataType)) resetRelationStyle();
  1426. cell.DataType = 3;
  1427. cell.ShowValue = '';
  1428. cell.Value = '';
  1429. cell.DataTime = '';
  1430. cell.DataTimeType = 0;
  1431. cell.EdbInfoId = 0;
  1432. cell.ShowStyle = '';
  1433. cell.ShowFormatValue = '';
  1434. cell.Extra && (cell.Extra = '');
  1435. this.checkCellRelation(cell)
  1436. },
  1437. findDataByStartKey(key){
  1438. if(!key) return {data:{},row:-1,col:-1}
  1439. let mergeCellDom = this.$refs.tableRef.querySelector(`[data-key="${key}"]`)
  1440. let row = +mergeCellDom.dataset.datarindex
  1441. let col = +mergeCellDom.dataset.datacindex
  1442. return {data:this.config.data[row][col],row,col}
  1443. },
  1444. /* 删除行列 */
  1445. delColOrRow() {
  1446. let { rindex, cindex } = this.rightClickCell;
  1447. if (rindex === '-1') { //删除列
  1448. console.log('删除列', cindex)
  1449. if (this.columnHeader.length === 1) return this.$message.warning(this.$t('OnlineExcelPage.keep_one_column_msg'))
  1450. let index = this.columnHeader.findIndex(_ => _ === cindex);
  1451. // 处理删除列对合并单元格的影响
  1452. let startMainKey=''
  1453. this.config.data.map((row,rowInd) => {
  1454. let rowEle=row[index]
  1455. if(rowEle.merData){
  1456. let {data,row,col} = this.findDataByStartKey(rowEle.merData.mer.sKey)
  1457. let r = row
  1458. let c = col
  1459. let rs = data.merData.mer.rowspan
  1460. let cs = data.merData.mer.colspan
  1461. if(cs == 1) return //只有一列
  1462. if(rowEle.merData.type == 'merged'){
  1463. // 每个大单元格只处理一次
  1464. if(startMainKey != rowEle.merData.mer.sKey){
  1465. if(data.merData.mer.colspan==2 && data.merData.mer.rowspan==1){
  1466. //删除这一列之后,只有一个单元格了
  1467. data.merData=null
  1468. return
  1469. }
  1470. data.merData.mer.colspan--
  1471. startMainKey = rowEle.merData.mer.sKey
  1472. }
  1473. }else{
  1474. // 右一列的单元格作为新的左上角单元格
  1475. const newStartCell = this.config.data[r][c+1]
  1476. if(rowEle.merData.mer.colspan==2 && rowEle.merData.mer.rowspan==1){
  1477. //删除这一列之后,只有一个单元格了
  1478. newStartCell.merData=null
  1479. return
  1480. }
  1481. // 有值的单元格就是左上角的单元格
  1482. newStartCell.merData=rowEle.merData
  1483. newStartCell.merData.mer.sKey = newStartCell.Uid
  1484. newStartCell.merData.mer.colspan--
  1485. for (let i = r; i < (r+rs); i++) {
  1486. for (let j = c+1; j < (c+cs); j++) {
  1487. const element = this.config.data[i][j];
  1488. if(element.merData.type == 'merged'){
  1489. element.merData.mer.sKey = newStartCell.Uid
  1490. }
  1491. }
  1492. }
  1493. }
  1494. }
  1495. })
  1496. //删除时清除关系
  1497. if (this.insertRelationArr.length) {
  1498. let delCellIds = this.config.data.map(row => row[index].Uid);
  1499. this.clearRelationInsertCell(delCellIds);
  1500. }
  1501. this.config.data.forEach(row => {
  1502. row.splice(index, 1)
  1503. })
  1504. // 删除的是最后一列
  1505. if(!(index < this.config.data[0].length)){
  1506. resetStyle()
  1507. }
  1508. } else if (cindex === '-1') { //删除行
  1509. console.log('删除行', rindex)
  1510. if (this.rowHeader.length === 1) return this.$message.warning(this.$t('OnlineExcelPage.keep_one_row_msg'))
  1511. let index = this.rowHeader.findIndex(_ => _ === rindex)
  1512. // 处理删除行对合并单元格的影响
  1513. let startMainKey=''
  1514. this.config.data[index].map((rowEle,rowInd) => {
  1515. if(rowEle.merData){
  1516. let {data,row,col} = this.findDataByStartKey(rowEle.merData.mer.sKey)
  1517. let r = row
  1518. let c = col
  1519. let rs = data.merData.mer.rowspan
  1520. let cs = data.merData.mer.colspan
  1521. if(rs == 1) return //只有一行
  1522. if(rowEle.merData.type == 'merged'){
  1523. // 每个大单元格只处理一次
  1524. if(startMainKey != rowEle.merData.mer.sKey){
  1525. if(data.merData.mer.colspan==1 && data.merData.mer.rowspan==2){
  1526. //删除这一行之后,只有一个单元格了
  1527. data.merData=null
  1528. return
  1529. }
  1530. data.merData.mer.rowspan--
  1531. startMainKey = rowEle.merData.mer.sKey
  1532. }
  1533. }else{
  1534. // 下一行的单元格作为新的左上角单元格
  1535. const newStartCell = this.config.data[r+1][c]
  1536. if(rowEle.merData.mer.colspan==1 && rowEle.merData.mer.rowspan==2){
  1537. //删除这一行之后,只有一个单元格了
  1538. newStartCell.merData=null
  1539. return
  1540. }
  1541. newStartCell.merData=rowEle.merData
  1542. newStartCell.merData.mer.sKey = newStartCell.Uid
  1543. newStartCell.merData.mer.rowspan--
  1544. for (let i = r+1; i < (r+rs); i++) {
  1545. for (let j = c; j < (c+cs); j++) {
  1546. const element = this.config.data[i][j];
  1547. if(element.merData.type == 'merged'){
  1548. element.merData.mer.sKey = newStartCell.Uid
  1549. }
  1550. }
  1551. }
  1552. }
  1553. }
  1554. })
  1555. if (this.insertRelationArr.length) {
  1556. //删除时清除关系
  1557. let delCellIds = this.config.data[index].map(cell => cell.Uid);
  1558. this.clearRelationInsertCell(delCellIds);
  1559. }
  1560. this.config.data.splice(index, 1)
  1561. // 删除的是最后一行
  1562. if(!(index < this.config.data.length)){
  1563. resetStyle()
  1564. }
  1565. }
  1566. },
  1567. /* 删除时清除关联关系 和删除单元格有关联的插入值单元格和 */
  1568. clearRelationInsertCell(delCellIds) {
  1569. //清除关联插入值得单元格
  1570. let haveRelationArr = this.insertRelationArr.filter(_ => delCellIds.includes(_.relation_date.key) || delCellIds.includes(_.relation_edb.key));
  1571. // console.log(haveRelationArr)
  1572. haveRelationArr.forEach(relation => {
  1573. !delCellIds.includes(relation) && this.updateInsertCell(relation.key);
  1574. })
  1575. this.insertRelationArr = this.insertRelationArr.filter(_ => !delCellIds.includes(_.key) && !delCellIds.includes(_.relation_date.key) && !delCellIds.includes(_.relation_edb.key))
  1576. },
  1577. /* 插入列 */
  1578. insertCol(key) {
  1579. let { cindex } = this.rightClickCell;
  1580. let index = this.columnHeader.findIndex(_ => _ === cindex);
  1581. let checkIndex = key==='insert-col-left'?index-1:index+1
  1582. let startMainKey=''
  1583. this.config.data.forEach((row, rindex) => {
  1584. let isEnlargeCell = !!(row[index].merData && row[checkIndex] && row[checkIndex].merData)
  1585. if(isEnlargeCell && startMainKey != row[index].merData.mer.sKey){
  1586. const data = row[index].merData.type == 'merge'?row[index]:this.findDataByStartKey(row[index].merData.mer.sKey).data
  1587. data.merData.mer.colspan++
  1588. startMainKey = row[index].merData.mer.sKey
  1589. }
  1590. row.splice(key === 'insert-col-left' ? index : index + 1, 0, {
  1591. ShowValue: "",
  1592. Value: "",
  1593. DataType: 3,
  1594. DataTime: "",
  1595. EdbInfoId: 0,
  1596. Uid: md5.hex_md5(`${new Date().getTime()}${rindex}`),
  1597. merData:isEnlargeCell?{
  1598. type:'merged',
  1599. mer:{
  1600. sKey:row[index].merData.mer.sKey,//左上角第一个单元格的Uid
  1601. }
  1602. }:null
  1603. })
  1604. })
  1605. },
  1606. /* 插入行 */
  1607. insertRow(key) {
  1608. let { rindex } = this.rightClickCell;
  1609. let index = this.rowHeader.findIndex(_ => _ === rindex)
  1610. let checkIndex = key==='insert-row-up'?index-1:index+1
  1611. let startMainKey=''
  1612. let row = new Array(this.columnHeader.length).fill("").map((_,cindex) => {
  1613. let isEnlargeCell = !!(this.config.data[index][cindex].merData && this.config.data[checkIndex][cindex] && this.config.data[checkIndex][cindex].merData)
  1614. if(isEnlargeCell && startMainKey != this.config.data[index][cindex].merData.mer.sKey){
  1615. const data = this.config.data[index][cindex].merData.type == 'merge'?
  1616. this.config.data[index][cindex]:
  1617. this.findDataByStartKey(this.config.data[index][cindex].merData.mer.sKey).data
  1618. data.merData.mer.rowspan++
  1619. startMainKey = this.config.data[index][cindex].merData.mer.sKey
  1620. }
  1621. return {
  1622. ShowValue: "",
  1623. Value: "",
  1624. DataType: 3,
  1625. DataTime: "",
  1626. EdbInfoId: 0,
  1627. Uid: md5.hex_md5(`${new Date().getTime()}${cindex}`),
  1628. merData:isEnlargeCell?{
  1629. type:'merged',
  1630. mer:{
  1631. sKey:this.config.data[index][cindex].merData.mer.sKey,//左上角第一个单元格的Uid
  1632. }
  1633. }:null
  1634. }
  1635. });
  1636. this.config.data.splice(key === 'insert-row-up' ? index : index + 1, 0, row)
  1637. },
  1638. /* 单元格类型5 浮到上面展示指标信息浮窗 */
  1639. async getRelationEdbInfo({ EdbInfoId, DataType }) {
  1640. if (![5, 7].includes(DataType) || this.disabled) return
  1641. const res = await dataBaseInterface.targetDetail({ EdbInfoId })
  1642. if (res.Ret !== 200) return
  1643. this.cellrelationEdbInfo = res.Data;
  1644. },
  1645. /* 导入系统/指标日期弹窗 */
  1646. insertDateOpen(type) {
  1647. this.insertTargetCell = this.selectCell;
  1648. resetDialogCellStyle();
  1649. if (type === 'cell-edit') { //编辑日期
  1650. this.insertDateInfo = {
  1651. ...this.insertTargetCell
  1652. }
  1653. } else {
  1654. this.insertDateInfo = {
  1655. // key:type
  1656. }
  1657. }
  1658. this.isInsertDateDialog = true;
  1659. this.resetDialogStatus();
  1660. },
  1661. /* 弹窗都是无遮罩的 弹一个就重置其他的 */
  1662. resetDialogStatus(type = 'init') {
  1663. if (type !== 'insertEdbVal') {
  1664. this.$refs.selectTargetValueRef && this.$refs.selectTargetValueRef.initData();
  1665. this.isSelectTargetValueDialog = false;
  1666. }
  1667. if (type !== 'insertEdbCalculateVal') {
  1668. this.$refs.calculateEdbDiaRef && this.$refs.calculateEdbDiaRef.initData();
  1669. this.isInsertCalculate = false;
  1670. }
  1671. if (type !== 'insertDateCalculateVal') {
  1672. this.$refs.calculateDateDiaRef && this.$refs.calculateDateDiaRef.initData();
  1673. this.isInsertCalculateDate = false;
  1674. }
  1675. if (type !== 'balanceAddChart') {
  1676. this.$refs.balanceAddChart && this.$refs.balanceAddChart.initData();
  1677. this.isShowAddChart = false;
  1678. }
  1679. },
  1680. /* 插入系统/指标日期 */
  1681. insertDatehandle({ insertValue, dataTimeType, str }) {
  1682. this.insertTargetCell.DataType = 1;
  1683. this.insertTargetCell.DataTimeType = dataTimeType;
  1684. this.insertTargetCell.ShowValue = insertValue;
  1685. this.insertTargetCell.Value = str;
  1686. this.insertTargetCell.EdbInfoId = 0;
  1687. this.insertTargetCell.DataTime = insertValue;
  1688. this.commonInitCell('edit')
  1689. },
  1690. /* 指标计算弹窗 */
  1691. edbCalculateInsertOpen(item) {
  1692. this.insertTargetCell = this.selectCell;
  1693. resetDialogCellStyle();
  1694. setRelationStyle({ key: this.insertTargetCell.Uid }, 'td-choose-insert-target');
  1695. if (item === 'cell-edit') { //编辑
  1696. const { Value } = this.insertTargetCell;
  1697. let menuInfo = this.config.contextMenuOption
  1698. .find(_ => _.key === 'insert-edb-calculate').children
  1699. .find(menu => menu.source === JSON.parse(Value).Source);
  1700. this.insertCalculateInfo = {
  1701. ...menuInfo,
  1702. ...this.insertTargetCell
  1703. }
  1704. } else {
  1705. this.insertCalculateInfo = {
  1706. ...item
  1707. }
  1708. }
  1709. this.isInsertCalculate = true;
  1710. this.resetDialogStatus('insertEdbCalculateVal')
  1711. },
  1712. /* 导入指标计算值 */
  1713. insertCalculateData(item) {
  1714. // console.log(item)
  1715. const { InsertValue, EdbInfoId, Str, relationDate, relationUid } = item;
  1716. this.insertTargetCell.DataType = 7;
  1717. this.insertTargetCell.ShowValue = InsertValue;
  1718. this.insertTargetCell.Value = Str;
  1719. this.insertTargetCell.EdbInfoId = EdbInfoId;
  1720. this.insertTargetCell.DataTime = relationDate;
  1721. this.insertTargetCell.ShowFormatValue = this.insertTargetCell.ShowStyle ? transDecimalPlace(InsertValue, JSON.parse(this.insertTargetCell.ShowStyle)) : '';
  1722. InsertValue ? this.$message.success(this.$t('ETable.Msg.insertion_success_msg')) : this.$message.warning(this.$t('ETable.Msg.date_no_data'))
  1723. //如果有关联表格日期就建立新的关联关系
  1724. if (relationDate && relationUid) {
  1725. let relation = {
  1726. insert_cell: {
  1727. key: this.insertTargetCell.Uid,
  1728. relation_date: relationUid,
  1729. relation_edb: '',
  1730. }
  1731. }
  1732. this.setRelation(relation, 7);
  1733. } else { //重新插值后之后原来有关联的清除关系
  1734. let haveIndex = this.insertRelationArr.findIndex(_ => _.key === this.insertTargetCell.Uid);
  1735. haveIndex !== -1 && this.insertRelationArr.splice(haveIndex, 1)
  1736. resetRelationStyle();
  1737. }
  1738. this.commonInitCell('edit')
  1739. },
  1740. /* 日期计算弹窗 */
  1741. insertDateCalculateOpen(type) {
  1742. this.insertTargetCell = this.selectCell;
  1743. resetDialogCellStyle()
  1744. setRelationStyle({ key: this.insertTargetCell.Uid }, 'td-choose-insert-target')
  1745. if (type === 'cell-edit') { //编辑
  1746. this.insertCalculateDateInfo = {
  1747. ...this.insertTargetCell
  1748. }
  1749. } else {
  1750. this.insertCalculateDateInfo = {}
  1751. }
  1752. this.isInsertCalculateDate = true;
  1753. this.resetDialogStatus('insertDateCalculateVal');
  1754. },
  1755. /* 插入日期计算值 */
  1756. insertCalculateDateValue(data) {
  1757. const { insertValue, str } = data;
  1758. this.insertTargetCell.DataType = 8;
  1759. this.insertTargetCell.ShowValue = insertValue;
  1760. this.insertTargetCell.Value = str;
  1761. this.insertTargetCell.EdbInfoId = 0;
  1762. this.insertTargetCell.DataTime = '';
  1763. this.insertTargetCell.ShowFormatValue = this.insertTargetCell.ShowStyle ? transDecimalPlace(insertValue, JSON.parse(this.insertTargetCell.ShowStyle)) : '';
  1764. this.$message.success(this.$t('ETable.Msg.insertion_success_msg'))
  1765. this.commonInitCell('edit')
  1766. },
  1767. /* 初始化8行5列 */
  1768. initData(initData = null) {
  1769. console.log('initData');
  1770. this.hasInit = false
  1771. if (initData&&initData.Data.length>0) {
  1772. const { CellRelation, Data } = initData;
  1773. this.config.data = Data;
  1774. this.insertRelationArr = JSON.parse(CellRelation);
  1775. } else {
  1776. this.config.data = new Array(8).fill("").map((_, _rindex) => {
  1777. return new Array(5).fill("").map((cell, _cindex) => ({
  1778. ShowValue: "",
  1779. ShowStyle: '',
  1780. ShowFormatValue: '',
  1781. Value: "",
  1782. DataType: 3,
  1783. DataTimeType: 0,
  1784. DataTime: "",
  1785. EdbInfoId: 0,
  1786. Uid: md5.hex_md5(`${new Date().getTime()}${_rindex}${_cindex}`)
  1787. }));
  1788. });
  1789. }
  1790. this.$nextTick(() => {
  1791. this.hasInit = true
  1792. if(this.activeSheetId){
  1793. this.getExcelRule()
  1794. }
  1795. })
  1796. },
  1797. /* 处理因数结构 =a1+b1 => [{ Tag: a,Row:1,Key:'' }] */
  1798. dealFormulaConstruction(val) {
  1799. // 提取因数数组
  1800. let factors = extractFactorsFromFormula(val)
  1801. let arr = factors.map(str => ({
  1802. Tag: splitString(toUpperCase(str))[0],
  1803. Row: splitString(toUpperCase(str))[1],
  1804. Key: findCellKeyByFactor(str)
  1805. }))
  1806. return JSON.stringify(arr)
  1807. },
  1808. /* 要支持复制粘贴把公式也带过去 公式单元格类型为6 其余就正常复制文本 */
  1809. copyCellHandle(e, cell) {
  1810. this.copyCellItem = cell;
  1811. // 阻止默认的复制操作
  1812. e.preventDefault();
  1813. },
  1814. /* 要支持复制粘贴把公式也带过去 公式单元格类型为6 其余就正常复制文本 */
  1815. pasteCellHandle(e, cell) {
  1816. if (this.copyCellItem.DataType === 6) {
  1817. cell.DataType = this.copyCellItem.DataType;
  1818. cell.ShowValue = this.copyCellItem.ShowValue;
  1819. cell.Value = this.copyCellItem.Value;
  1820. cell.DataTime = this.copyCellItem.DataTime;
  1821. cell.EdbInfoId = this.copyCellItem.EdbInfoId;
  1822. cell.ShowStyle = this.copyCellItem.ShowStyle;
  1823. cell.ShowFormatValue = this.copyCellItem.ShowFormatValue;
  1824. cell.Extra = this.copyCellItem.Extra;
  1825. } else {
  1826. cell.DataType = 3;
  1827. cell.ShowValue = this.copyCellItem.ShowValue;
  1828. cell.Value = this.copyCellItem.ShowValue;
  1829. cell.ShowStyle = this.copyCellItem.ShowStyle;
  1830. cell.ShowFormatValue = this.copyCellItem.ShowFormatValue;
  1831. cell.DataTime = '';
  1832. cell.EdbInfoId = 0;
  1833. }
  1834. // 阻止默认的粘贴操作
  1835. e.preventDefault();
  1836. },
  1837. /* 单元格enter失焦 */
  1838. keyEnterHandle(e, cell) {
  1839. if (e.keyCode === 13) {
  1840. //非得搞个要回车失焦
  1841. e.target.nodeName && e.target.blur();
  1842. this.$refs[`inputRef${e.target.dataset.key}`] && this.$refs[`inputRef${e.target.dataset.key}`][0].close()
  1843. // cell.DataType===6 && this.$set(cell,'CanEdit',false)
  1844. // this.$set(cell,'CanEdit',false)
  1845. }
  1846. },
  1847. /* 双击切换状态 插值单元格不允许切换 可切换类型1,2,3,6*/
  1848. dblClickCellHandle(e, cell) {
  1849. if (this.disabled || ![1, 2, 3, 6].includes(cell.DataType) || [1, 2].includes(cell.DataTimeType)) return
  1850. this.$set(cell, 'CanEdit', true)
  1851. console.log(cell)
  1852. this.$nextTick(() => {
  1853. if (e.target.childNodes[0].childNodes[0].childNodes[1].nodeName === 'INPUT') e.target.childNodes[0].childNodes[0].childNodes[1].focus();
  1854. })
  1855. },
  1856. /* 处理保存的参数 */
  1857. getSaveParams() {
  1858. const { data } = this.config;
  1859. let params = {
  1860. CellRelation: JSON.stringify(this.insertRelationArr),
  1861. Data: data
  1862. }
  1863. return params
  1864. },
  1865. /* tab禁掉 */
  1866. handlekeyDownKeys(e) {
  1867. if (e.keyCode === 9) {
  1868. e.preventDefault();
  1869. }
  1870. },
  1871. /* 改变单元格显示文本 */
  1872. // updateCellStyle({ ShowStyle, ShowFormatValue }) {
  1873. // this.$set(this.selectCell, 'ShowStyle', ShowStyle)
  1874. // this.$set(this.selectCell, 'ShowFormatValue', ShowFormatValue)
  1875. // },
  1876. // ==================================================合并单元格
  1877. // 选区开始
  1878. selectCellHandle(e) {
  1879. // 不是左键的mousedown事件
  1880. if(e.button!==0) return
  1881. if(this.disabled) return
  1882. if(this.isShowAddChart) return // 添加图表弹窗出现
  1883. this.isSelectionStart=true
  1884. let startTd;
  1885. if(e.target.nodeName==='TD'){
  1886. startTd = e.target
  1887. }else if(e.target.parentNode.nodeName==='TD'){
  1888. startTd = e.target.parentNode
  1889. }else if(e.target.parentNode.parentNode.nodeName==='TD'){
  1890. startTd = e.target.parentNode.parentNode
  1891. }else if(e.target.parentNode.parentNode.parentNode.nodeName==='TD'){
  1892. startTd = e.target.parentNode.parentNode.parentNode
  1893. }
  1894. if(!startTd) return
  1895. this.startCell={
  1896. row:+startTd.dataset.datarindex,
  1897. column:+startTd.dataset.datacindex
  1898. }
  1899. document.addEventListener('mousemove',this.selectZoneHandle)
  1900. document.addEventListener('mouseup',this.selectCellEndHandle)
  1901. },
  1902. // 选取
  1903. selectZoneHandle(e) {
  1904. if(!this.isSelectionStart) return
  1905. if(this.disabled) return
  1906. const selection = window.getSelection();
  1907. if (selection.rangeCount>0) {
  1908. // 清除选中的文本范围
  1909. selection.removeAllRanges();
  1910. }
  1911. let tableRect=this.$refs.tableRef.getBoundingClientRect()
  1912. const mouseX = e.pageX;
  1913. const mouseY = e.pageY;
  1914. let endTd;
  1915. if(mouseX >= tableRect.left && mouseX <= tableRect.right &&
  1916. mouseY >= tableRect.top && mouseY <= tableRect.bottom){
  1917. // 表格内
  1918. if(e.target.nodeName==='TD'){
  1919. endTd = e.target
  1920. }else if(e.target.parentNode.nodeName==='TD'){
  1921. endTd = e.target.parentNode
  1922. }else if(e.target.parentNode.parentNode.nodeName==='TD'){
  1923. endTd = e.target.parentNode.parentNode
  1924. }else if(e.target.parentNode.parentNode.parentNode.nodeName==='TD'){
  1925. endTd = e.target.parentNode.parentNode.parentNode
  1926. }
  1927. if(!endTd) return
  1928. this.endCell={
  1929. e:endTd,
  1930. row:+endTd.dataset.datarindex,
  1931. column:+endTd.dataset.datacindex
  1932. }
  1933. }
  1934. },
  1935. // 选区结束
  1936. selectCellEndHandle(){
  1937. this.isSelectionStart=false
  1938. // click事件走在mouseup事件前面,延迟下
  1939. setTimeout(()=>{
  1940. if((this.mergeSelectionStart.row || this.mergeSelectionStart.row==0)
  1941. && (this.mergeSelectionEnd.row || this.mergeSelectionEnd.row==0)
  1942. && (this.mergeSelectionStart.column || this.mergeSelectionStart.column==0)
  1943. && (this.mergeSelectionEnd.column || this.mergeSelectionEnd.column==0)){
  1944. this.mergeSelectedCells=[]
  1945. resetStyle()
  1946. this.selectCell=null
  1947. // 选区
  1948. for (let i = this.mergeSelectionStart.row; i < this.mergeSelectionEnd.row+1; i++) {
  1949. for (let j = this.mergeSelectionStart.column; j < this.mergeSelectionEnd.column+1; j++) {
  1950. this.mergeSelectedCells.push(this.config.data[i][j])
  1951. }
  1952. }
  1953. }else{
  1954. this.mergeSelectedCells=[]
  1955. }
  1956. },1)
  1957. document.removeEventListener('mousemove',this.selectZoneHandle)
  1958. document.removeEventListener('mouseup',this.selectCellEndHandle)
  1959. },
  1960. findCellDom(key){
  1961. if(!key) return null
  1962. if(key !== this.cacheKey){
  1963. // 重新找
  1964. this.cacheCellDom = this.$refs.tableRef.querySelector(`[data-key="${key}"]`)
  1965. this.cacheKey=key
  1966. }
  1967. return this.cacheCellDom
  1968. },
  1969. // 确定选区范围和设置选区样式
  1970. setSelectionStyle(){
  1971. if(!this.isSelectionStart) return
  1972. // 开始的单元格没有
  1973. if(!( (this.startCell.row || this.startCell.row==0) &&
  1974. (this.startCell.column || this.startCell.column==0))) return
  1975. // 结束的单元格没有
  1976. if(!( (this.endCell.row || this.endCell.row==0) &&
  1977. (this.endCell.column || this.endCell.column==0) && this.endCell.e)) return
  1978. // 递归确定选区范围
  1979. const findZone = ({sR,eR,sC,eC})=>{
  1980. this.hasValueCellItem.cellNumber=0
  1981. for (let i = sR; i < eR+1; i++) {
  1982. for (let j = sC; j < eC+1; j++) {
  1983. const element = this.config.data[i][j]
  1984. if(element.Value){
  1985. this.hasValueCellItem.cellNumber++
  1986. this.hasValueCellItem.row=i
  1987. this.hasValueCellItem.column=j
  1988. }
  1989. if(element.merData && element.merData.type==='merge'){
  1990. if(i+element.merData.mer.rowspan-1 > eR){
  1991. // 该单元格的行有合并 重新规定选取范围
  1992. return findZone({sR,eR:i+element.merData.mer.rowspan-1,sC,eC})
  1993. }
  1994. if(j+element.merData.mer.colspan-1 > eC){
  1995. // 该单元格的列有合并 重新规定选取范围
  1996. return findZone({sR,eR,sC,eC:j+element.merData.mer.colspan-1})
  1997. }
  1998. this.hasMergedCell=true
  1999. }
  2000. if(element.merData && element.merData.type==='merged' ){
  2001. let item = this.findCellDom(element.merData.mer.sKey)
  2002. let row = +item.dataset.datarindex
  2003. let col = +item.dataset.datacindex
  2004. if(row < sR){
  2005. // 该单元格的行有被合并 重新规定选取范围
  2006. return findZone({sR:row,eR,sC,eC})
  2007. }
  2008. if(col < sC){
  2009. // 该单元格的行有被合并 重新规定选取范围
  2010. return findZone({sR,eR,sC:col,eC})
  2011. }
  2012. this.hasMergedCell=true
  2013. }
  2014. }
  2015. }
  2016. // 防止选中的区域不是整个的单元格(合并后的),后面确定selectionRef 区域大小有问题
  2017. if(this.config.data[eR][eC].merData && this.config.data[eR][eC].merData.type==='merged'){
  2018. let item = this.findCellDom(this.config.data[eR][eC].merData.mer.sKey)
  2019. let row = +item.dataset.datarindex
  2020. let col = +item.dataset.datacindex
  2021. eR=row
  2022. eC=col
  2023. this.hasMergedCell=true
  2024. }
  2025. return {startR:sR,
  2026. endR:eR,
  2027. startC:sC,
  2028. endC:eC}
  2029. }
  2030. // 看是否是从下往上、从右往左选的
  2031. let rowReverse = this.startCell.row > this.endCell.row
  2032. let colReverse = this.startCell.column > this.endCell.column
  2033. let postion={
  2034. sR:rowReverse?this.endCell.row:this.startCell.row,
  2035. eR:rowReverse?this.startCell.row:this.endCell.row,
  2036. sC:colReverse?this.endCell.column:this.startCell.column,
  2037. eC:colReverse?this.startCell.column:this.endCell.column
  2038. }
  2039. this.hasMergedCell=false
  2040. const zone = findZone(postion)
  2041. let start = this.config.data[zone.startR][zone.startC]
  2042. let end = this.config.data[zone.endR][zone.endC]
  2043. this.mergeSelectionStart.row = zone.startR
  2044. this.mergeSelectionStart.column = zone.startC
  2045. this.mergeSelectionStart.rowSpan = start.merData?start.merData.mer.rowspan:1
  2046. this.mergeSelectionStart.colSpan = start.merData?start.merData.mer.colspan:1
  2047. this.mergeSelectionEnd.row = zone.endR
  2048. this.mergeSelectionEnd.column = zone.endC
  2049. this.mergeSelectionEnd.rowSpan = end.merData?end.merData.mer.rowspan:1
  2050. this.mergeSelectionEnd.colSpan = end.merData?end.merData.mer.colspan:1
  2051. let tableRect = this.$refs.tableRef.getBoundingClientRect()
  2052. let startTd = this.$refs.tableRef.querySelector(`[data-key="${start.Uid}"]`)
  2053. let endTd = this.$refs.tableRef.querySelector(`[data-key="${end.Uid}"]`)
  2054. if(!(startTd && endTd)) return
  2055. let startRect = startTd.getBoundingClientRect()
  2056. let endRect = endTd.getBoundingClientRect()
  2057. this.$refs.selectionRef.style.left = startRect.left-tableRect.left+'px'
  2058. this.$refs.selectionRef.style.top = startRect.top-tableRect.top+'px'
  2059. let width = Math.abs(endRect.right - startRect.right) + startRect.width
  2060. let height = Math.abs(endRect.bottom - startRect.bottom) + startRect.height
  2061. this.$refs.selectionRef.style.width = width+'px'
  2062. this.$refs.selectionRef.style.height = height + 'px'
  2063. this.$refs.selectionRef.style.visibility='visible'
  2064. },
  2065. clearSelection(){
  2066. if(this.$refs.selectionRef){
  2067. this.$refs.selectionRef.style.width = 0
  2068. this.$refs.selectionRef.style.height = 0
  2069. this.$refs.selectionRef.style.visibility='hidden'
  2070. }
  2071. this.mergeSelectionStart={
  2072. row:null,
  2073. rowSpan:0,
  2074. column:null,
  2075. colSpan:0
  2076. }
  2077. this.mergeSelectionEnd={
  2078. row:null,
  2079. rowSpan:0,
  2080. column:null,
  2081. colSpan:0
  2082. }
  2083. this.mergeSelectedCells=[]
  2084. },
  2085. mergeCellFun(){
  2086. // 无选区
  2087. if(!((this.mergeSelectionStart.row || this.mergeSelectionStart.row==0)
  2088. && (this.mergeSelectionEnd.row || this.mergeSelectionEnd.row==0)
  2089. && (this.mergeSelectionStart.column || this.mergeSelectionStart.column==0)
  2090. && (this.mergeSelectionEnd.column || this.mergeSelectionEnd.column==0))) return
  2091. if(this.hasValueCellItem.cellNumber>1 || this.hasValueCellItem.cellNumber<0){
  2092. return this.$message.warning(this.$t('ETable.Msg.merge_cell_fail_msg'))
  2093. }
  2094. const firstCell = this.config.data[this.mergeSelectionStart.row][this.mergeSelectionStart.column]
  2095. if(this.hasValueCellItem.cellNumber!=0
  2096. && (this.hasValueCellItem.row!=this.mergeSelectionStart.row
  2097. || this.hasValueCellItem.column!=this.mergeSelectionStart.column)){
  2098. const reserveCell=this.config.data[this.hasValueCellItem.row][this.hasValueCellItem.column]
  2099. // 将原本有值的单元格 移给左上角第一个单元格
  2100. firstCell.ShowValue=reserveCell.ShowValue
  2101. firstCell.ShowStyle=reserveCell.ShowStyle
  2102. firstCell.ShowFormatValue=reserveCell.ShowFormatValue
  2103. firstCell.Value=reserveCell.Value
  2104. firstCell.DataType=reserveCell.DataType
  2105. firstCell.DataTimeType=reserveCell.DataTimeType
  2106. firstCell.DataTime=reserveCell.DataTime
  2107. firstCell.EdbInfoId=reserveCell.EdbInfoId
  2108. firstCell.CanEdit && (firstCell.CanEdit=reserveCell.CanEdit)
  2109. firstCell.Extra && (firstCell.Extra=reserveCell.Extra)
  2110. // 处理合并后的依赖关系 就是替换
  2111. this.replaceCellRelation(reserveCell.Uid,firstCell.Uid)
  2112. // 清空
  2113. this.clearCell(reserveCell)
  2114. }
  2115. this.$set(firstCell,'merData',{
  2116. type:'merge',
  2117. mer:{
  2118. sKey:firstCell.Uid,//保留的单元格的Uid
  2119. rowspan: this.mergeSelectionEnd.row - this.mergeSelectionStart.row+1,
  2120. colspan: this.mergeSelectionEnd.column - this.mergeSelectionStart.column+1,
  2121. }
  2122. })
  2123. for (let i = this.mergeSelectionStart.row; i < this.mergeSelectionEnd.row+1; i++) {
  2124. for (let j = this.mergeSelectionStart.column; j < this.mergeSelectionEnd.column+1; j++) {
  2125. const element = this.config.data[i][j]
  2126. if(i == this.mergeSelectionStart.row && j == this.mergeSelectionStart.column){
  2127. continue
  2128. }
  2129. element.merData={
  2130. type:'merged',
  2131. mer:{
  2132. sKey:firstCell.Uid,//左上角第一个单元格的Uid
  2133. }
  2134. }
  2135. }
  2136. }
  2137. let startCell = this.config.data[this.mergeSelectionStart.row][this.mergeSelectionStart.column]
  2138. let target = this.$refs.tableRef.querySelector(`[data-key="${startCell && startCell.Uid}"]`)
  2139. // 触发单元格的点击事件
  2140. target.click()
  2141. },
  2142. unmergeCellsFun(){
  2143. if((this.mergeSelectionStart.row || this.mergeSelectionStart.row==0)
  2144. && (this.mergeSelectionEnd.row || this.mergeSelectionEnd.row==0)
  2145. && (this.mergeSelectionStart.column || this.mergeSelectionStart.column==0)
  2146. && (this.mergeSelectionEnd.column || this.mergeSelectionEnd.column==0)){
  2147. // 选区
  2148. for (let i = this.mergeSelectionStart.row; i < this.mergeSelectionEnd.row+1; i++) {
  2149. for (let j = this.mergeSelectionStart.column; j < this.mergeSelectionEnd.column+1; j++) {
  2150. this.unmergeCellFun(this.config.data[i][j])
  2151. }
  2152. }
  2153. }else{
  2154. // 单个单元格
  2155. this.selectCell && this.unmergeCellFun(this.selectCell)
  2156. }
  2157. this.hasMergedCell=false
  2158. // 取消合并后,调整选区(有的话)
  2159. if((this.mergeSelectionStart.row || this.mergeSelectionStart.row==0)
  2160. && (this.mergeSelectionEnd.row || this.mergeSelectionEnd.row==0)
  2161. && (this.mergeSelectionStart.column || this.mergeSelectionStart.column==0)
  2162. && (this.mergeSelectionEnd.column || this.mergeSelectionEnd.column==0)){
  2163. this.mergeSelectionStart.rowSpan=1
  2164. this.mergeSelectionStart.colSpan=1
  2165. this.mergeSelectionEnd.row += (this.mergeSelectionEnd.rowSpan-1)
  2166. this.mergeSelectionEnd.column += (this.mergeSelectionEnd.colSpan-1)
  2167. this.mergeSelectionEnd.rowSpan=1
  2168. this.mergeSelectionEnd.colSpan=1
  2169. }
  2170. },
  2171. unmergeCellFun(cell){
  2172. if(!(cell.merData && cell.merData.type=='merge')) return
  2173. let {row,col} = this.findDataByStartKey(cell.merData.mer.sKey)
  2174. const sRow = row,
  2175. sCol = col,
  2176. eRow = row+cell.merData.mer.rowspan-1,
  2177. eCol = col+cell.merData.mer.colspan-1
  2178. for (let i = sRow; i < eRow+1; i++) {
  2179. for (let j = sCol; j < eCol+1; j++) {
  2180. this.config.data[i][j].merData=null
  2181. }
  2182. }
  2183. },
  2184. toolCellMergeFun(){
  2185. if(this.hasMergedCell) this.unmergeCellsFun()
  2186. else this.mergeCellFun()
  2187. }
  2188. },
  2189. };
  2190. </script>
  2191. <style scoped lang="scss">
  2192. .nodata {
  2193. text-align: center;
  2194. font-size: 16px;
  2195. color: #666;
  2196. padding: 100px 0;
  2197. }
  2198. .table-wrapper {
  2199. width: 100%;
  2200. overflow: auto;
  2201. * { box-sizing: border-box; }
  2202. .table-content-wrap {
  2203. display: flex;
  2204. .left-wrap {
  2205. flex: 1;
  2206. overflow: hidden;
  2207. .text-select-disabled{
  2208. -webkit-user-select: none;
  2209. -moz-user-select: none;
  2210. -ms-user-select: none;
  2211. user-select: none;
  2212. }
  2213. }
  2214. .right-wrap {
  2215. width: 400px;
  2216. margin-left: 20px;
  2217. flex-shrink: 0;
  2218. .chart-list{
  2219. background-color: #fff;
  2220. height: 100%;
  2221. height: calc(100vh - 440px);
  2222. overflow-y: auto;
  2223. padding: 20px;
  2224. }
  2225. }
  2226. }
  2227. .table-wrap {
  2228. width: 100%;
  2229. background-color: #fff;
  2230. // padding: 20px;
  2231. height: calc(100vh - 480px);
  2232. overflow: auto;
  2233. }
  2234. .bot-sheet-box {
  2235. margin-top: 20px;
  2236. display: flex;
  2237. justify-content: space-between;
  2238. .sheet-list {
  2239. flex: 1;
  2240. font-size: 12px;
  2241. display: flex;
  2242. align-items: center;
  2243. flex-wrap: wrap;
  2244. gap: 10px;
  2245. .sheet-item {
  2246. position: relative;
  2247. .del-box {
  2248. position: absolute;
  2249. background-color: #fff;
  2250. padding: 5px;
  2251. top: -22px;
  2252. right: -16px;
  2253. z-index: 10;
  2254. width: 40px;
  2255. text-align: center;
  2256. cursor: pointer;
  2257. }
  2258. }
  2259. .input {
  2260. width: 75px;
  2261. background-color: transparent;
  2262. border: none;
  2263. box-sizing: border-box;
  2264. color: #0033ff;
  2265. text-align: center;
  2266. }
  2267. .box {
  2268. max-width: 120px;
  2269. min-width: 75px;
  2270. text-align: center;
  2271. background-color: #eff4ff;
  2272. .text {
  2273. display: block;
  2274. overflow: hidden;
  2275. white-space: nowrap;
  2276. text-overflow: ellipsis;
  2277. }
  2278. }
  2279. .active {
  2280. background-color: #fff;
  2281. color: #0033ff;
  2282. }
  2283. }
  2284. }
  2285. .formula-wrapper {
  2286. height: 42px;
  2287. display: flex;
  2288. align-items: center;
  2289. background: #fff;
  2290. border-radius: 4px;
  2291. box-shadow: 0 3px 6px rgba(0, 0, 0, 0.05);
  2292. border: 1px solid #dcdfe6;
  2293. margin-bottom: 15px;
  2294. padding: 0 15px;
  2295. }
  2296. .table td,
  2297. th {
  2298. width: 104px;
  2299. min-width: 104px;
  2300. height: 35px;
  2301. max-height: 35px;
  2302. background: #fff;
  2303. text-align: center;
  2304. word-break: break-all;
  2305. border: 1px solid #dcdfe6;
  2306. overflow: hidden;
  2307. text-overflow: ellipsis;
  2308. position: relative;
  2309. color: #606266;
  2310. &.td-chose::after {
  2311. position: absolute;
  2312. top: 0;
  2313. left: 0;
  2314. right: 0;
  2315. bottom: 0;
  2316. content: "";
  2317. display: block;
  2318. outline: 0;
  2319. border: 2px solid #0033ff;
  2320. box-shadow: 0 0 5px rgba(73, 177, 249, 0.5);
  2321. }
  2322. &.td-relation::after {
  2323. position: absolute;
  2324. top: 0;
  2325. left: 0;
  2326. right: 0;
  2327. bottom: 0;
  2328. content: "";
  2329. display: block;
  2330. outline: 0;
  2331. border: 2px dashed #0033ff;
  2332. box-shadow: 0 0 5px rgba(73, 177, 249, 0.5);
  2333. }
  2334. // &.td-col-select::after {
  2335. // position: absolute;
  2336. // top: 0;
  2337. // left: 0;
  2338. // right: 0;
  2339. // bottom: 0;
  2340. // content: "";
  2341. // display: block;
  2342. // outline: 0;
  2343. // border: 1px solid rgb(24, 173, 24);
  2344. // border-bottom: none;
  2345. // border-top: none;
  2346. // }
  2347. // &.td-row-select::after {
  2348. // position: absolute;
  2349. // top: 0;
  2350. // left: 0;
  2351. // right: 0;
  2352. // bottom: 0;
  2353. // content: "";
  2354. // display: block;
  2355. // outline: 0;
  2356. // border: 1px solid rgb(24, 173, 24);
  2357. // border-left: none;
  2358. // border-right: none;
  2359. // }
  2360. &.td-choose-insert-target::after {
  2361. position: absolute;
  2362. top: 0;
  2363. left: 0;
  2364. right: 0;
  2365. bottom: 0;
  2366. content: "";
  2367. display: block;
  2368. outline: 0;
  2369. border: 2px dashed orange;
  2370. box-shadow: 0 0 5px rgba(73, 177, 249, 0.5);
  2371. }
  2372. }
  2373. .th-tg {
  2374. background: #ebeef5;
  2375. &:hover {
  2376. cursor: pointer;
  2377. background: #ddd;
  2378. /* border: 2px solid #409eff; */
  2379. }
  2380. &.sm {
  2381. width: 36px;
  2382. min-width: 36px;
  2383. max-width: 36px;
  2384. }
  2385. }
  2386. //整行选中
  2387. tr {
  2388. position: relative;
  2389. &.choose-all::after {
  2390. position: absolute;
  2391. top: 0;
  2392. left: 0;
  2393. right: 0;
  2394. bottom: 0;
  2395. content: "";
  2396. display: block;
  2397. outline: 0;
  2398. border: 2px solid #5897fb;
  2399. box-shadow: 0 0 5px rgba(73, 177, 249, 0.5);
  2400. }
  2401. }
  2402. .td_selected{
  2403. background-color: #F5F7F9!important;
  2404. }
  2405. .contextMenu-wrapper {
  2406. position: fixed;
  2407. z-index: 99;
  2408. top: -9999px;
  2409. left: -9999px;
  2410. background: #fff;
  2411. padding: 10px 0;
  2412. min-width: 180px;
  2413. max-height: 400px;
  2414. overflow-y: auto;
  2415. /* border: 1px solid #999; */
  2416. box-shadow: 0 1px 4px #999;
  2417. .item {
  2418. padding: 10px 25px;
  2419. cursor: pointer;
  2420. &:hover {
  2421. background-color: #f5f7fa;
  2422. }
  2423. &:hover .subMenu-wrapper {
  2424. display: block;
  2425. }
  2426. }
  2427. .subMenu-wrapper {
  2428. width: 180px;
  2429. /* display: none; */
  2430. padding: 10px 0;
  2431. /* box-shadow: 0 1px 4px #999; */
  2432. /* background: #fff; */
  2433. /* position: absolute;
  2434. right: -178px;
  2435. top:-205px;
  2436. max-height: 400px;
  2437. overflow-y: auto; */
  2438. .item {
  2439. &:hover {
  2440. background: #fff;
  2441. }
  2442. }
  2443. }
  2444. }
  2445. }
  2446. </style>
  2447. <style lang="scss">
  2448. .table-wrapper {
  2449. td {
  2450. .el-input__inner {
  2451. border: none;
  2452. outline: none;
  2453. text-align: center;
  2454. height: 34px;
  2455. line-height: 34px;
  2456. }
  2457. }
  2458. .el-input.is-disabled .el-input__inner {
  2459. background-color: #fff;
  2460. }
  2461. .bot-sheet-box {
  2462. .el-button + .el-button {
  2463. margin-left: 0;
  2464. }
  2465. }
  2466. }
  2467. .formula-wrapper .el-input__inner {
  2468. border: none;
  2469. outline: none;
  2470. }
  2471. .edb-select-popover {
  2472. width: 300px !important;
  2473. .edb-item {
  2474. display: flex;
  2475. justify-content: space-between;
  2476. align-items: center;
  2477. .edb-item-name {
  2478. max-width: 260px;
  2479. }
  2480. }
  2481. }
  2482. .el-collapse {
  2483. border: none !important;
  2484. .el-collapse-item__header {
  2485. padding: 0;
  2486. height: auto;
  2487. line-height: normal;
  2488. margin-bottom: 0 !important;
  2489. background: transparent !important;
  2490. }
  2491. .el-collapse-item__wrap {
  2492. background: transparent !important;
  2493. border: none !important;
  2494. }
  2495. .el-collapse-item__content {
  2496. padding: 0 !important;
  2497. }
  2498. }
  2499. </style>