BalanceTable.vue 90 KB

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