WidgetReport.vue 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910
  1. <template>
  2. <div
  3. class="widget-report widget-view fm-report-table"
  4. :class="{
  5. active: selectWidget.key && selectWidget.key == element.key,
  6. 'is_hidden': element.options.hidden
  7. }"
  8. @click.stop="handleSelectWidget(index)"
  9. @mouseover.stop="handleMouseover"
  10. @mouseout="handleMouseout"
  11. ref="widgetReport"
  12. >
  13. <div>
  14. <table class="fm-report-table__table" :style="{
  15. 'border': 0,
  16. 'width': element.options.width || 'auto'
  17. }"
  18. :class="{
  19. [element.options && element.options.customClass]: element.options.customClass ? true : false
  20. }"
  21. >
  22. <tr>
  23. <template v-for="(th, i) in element.headerRow">
  24. <th :key="i" :style="{
  25. 'border-style': 'solid',
  26. 'border-width': element.options.borderWidth + 'px',
  27. 'border-color': element.options.borderColor,
  28. 'width': th.options.width,
  29. }"
  30. class="widget-report-item widget-report-header"
  31. valign="top"
  32. @click.stop="handleSelectHeaderWidget(i)"
  33. :class="{
  34. active: select.key && select.key == th.key
  35. }"
  36. @mouseover.stop="handleMouseoverTH(i)"
  37. @mouseout="handleMouseoutTH(i)"
  38. :ref="`widgetTH_${i}`"
  39. ><div style="text-align: center; height: 10px;line-height: 10px;font-size: 12px;">{{th.options.width}}</div></th>
  40. </template>
  41. </tr>
  42. <tr :key="rowIndex" v-for="(row, rowIndex) in element.rows">
  43. <td :style="{
  44. 'border-style': 'solid',
  45. 'border-width': element.options.borderWidth + 'px',
  46. 'border-color': element.options.borderColor,
  47. 'width': column.options.width,
  48. 'height': column.options.height,
  49. 'text-align': column.options.textAlign,
  50. 'vertical-align': column.options.verticalAlign,
  51. }"
  52. v-for="(column, i) in row.columns" :key="rowIndex + '-' + i"
  53. v-if="!column.options.invisible"
  54. :colspan="column.options.colspan"
  55. :rowspan="column.options.rowspan"
  56. class="widget-report-item fm-report-table__td"
  57. :class="{
  58. active: selectWidget.key && selectWidget.key == column.key,
  59. [column.options.customClass]: column.options.customClass?true: false,
  60. selected: selectIndex == i && column.options.colspan == 1
  61. }"
  62. @click.stop="handleSelectItemWidget(rowIndex, i)"
  63. valign="top"
  64. @mouseover.stop="handleMouseoverTD(rowIndex, i)"
  65. @mouseout="handleMouseoutTD(rowIndex, i)"
  66. :ref="`widgetTD_${rowIndex}_${i}`"
  67. >
  68. <draggable
  69. v-model="column.list"
  70. v-bind="{group:{name: 'people', put: handlePut}, ghostClass: 'ghost',animation: 200, handle: '.drag-widget'}"
  71. :no-transition-on-drag="true"
  72. @add="handleWidgetItemAdd($event, element, rowIndex, i)"
  73. @update="handleWidgetItemUpdate"
  74. @start="setDragging(true)"
  75. @end="setDragging(false)"
  76. class="widget-col-list"
  77. :style="{
  78. 'text-align': column.options.textAlign,
  79. 'vertical-align': column.options.verticalAlign,
  80. }"
  81. >
  82. <template v-for="(c, cindex) in column.list" v-if="c && c.key">
  83. <widget-tab-item
  84. v-if="c.type === 'tabs'"
  85. :key="c.key"
  86. :element="c"
  87. :select.sync="selectWidget"
  88. :index="cindex" :data="column"
  89. @select-change="handleSelectChange($event, column)"
  90. :platform="platform"
  91. :form-key="formKey"
  92. :subform="subform"
  93. >
  94. </widget-tab-item>
  95. <widget-collapse
  96. v-else-if="c.type === 'collapse'"
  97. :key="c.key"
  98. :element="c"
  99. :select.sync="selectWidget"
  100. :index="cindex"
  101. :data="column"
  102. @select-change="handleSelectChange($event, column)"
  103. :platform="platform"
  104. :form-key="formKey"
  105. :subform="subform"
  106. >
  107. </widget-collapse>
  108. <widget-table
  109. v-else-if="c.type === 'table'"
  110. :key="c.key"
  111. :element="c"
  112. :select.sync="selectWidget"
  113. :index="cindex" :data="column"
  114. @select-change="handleSelectChange($event, column)"
  115. :platform="platform"
  116. :form-key="formKey"
  117. >
  118. </widget-table>
  119. <widget-sub-form
  120. v-else-if="c.type === 'subform'"
  121. :key="c.key"
  122. :element="c"
  123. :select.sync="selectWidget"
  124. :index="cindex"
  125. :data="column"
  126. @select-change="handleSelectChange($event, column)"
  127. :platform="platform"
  128. :form-key="formKey"
  129. >
  130. </widget-sub-form>
  131. <widget-card
  132. v-else-if="c.type === 'card'"
  133. :key="c.key"
  134. :element="c"
  135. :select.sync="selectWidget"
  136. :index="cindex"
  137. :data="column"
  138. @select-change="handleSelectChange($event, column)"
  139. :platform="platform"
  140. :form-key="formKey"
  141. >
  142. </widget-card>
  143. <widget-group
  144. v-else-if="c.type === 'group'"
  145. :key="c.key"
  146. :element="c"
  147. :select.sync="selectWidget"
  148. :index="cindex"
  149. :data="column"
  150. @select-change="handleSelectChange($event, column)"
  151. :platform="platform"
  152. :form-key="formKey"
  153. >
  154. </widget-group>
  155. <widget-inline
  156. v-else-if="c.type === 'inline'"
  157. :key="c.key"
  158. :element="c"
  159. :select.sync="selectWidget"
  160. :index="cindex" :data="column"
  161. @select-change="handleSelectChange($event, column)"
  162. :platform="platform"
  163. :form-key="formKey"
  164. ></widget-inline>
  165. <widget-report
  166. v-else-if="c.type === 'report'"
  167. :key="c.key"
  168. :element="c"
  169. :select.sync="selectWidget"
  170. :index="cindex" :data="column"
  171. @select-change="handleSelectChange($event, column)"
  172. :platform="platform"
  173. :form-key="formKey"
  174. :subform="subform"
  175. >
  176. </widget-report>
  177. <widget-form-item
  178. v-else-if="c.type !== 'grid'"
  179. :key="c.key"
  180. :element="c"
  181. :select.sync="selectWidget"
  182. :index="cindex" :data="column"
  183. @select-change="handleSelectChange($event, column)"
  184. :form-key="formKey"
  185. >
  186. </widget-form-item>
  187. <widget-col-item
  188. v-else
  189. :key="c.key"
  190. :element="c"
  191. :select.sync="selectWidget"
  192. :index="cindex" :data="column"
  193. @select-change="handleSelectChange($event, column)"
  194. :platform="platform"
  195. :form-key="formKey"
  196. :subform="subform"
  197. >
  198. </widget-col-item>
  199. </template>
  200. </draggable>
  201. <div class="widget-view-action widget-col-action" v-if="selectWidget.key == column.key">
  202. <el-dropdown size="small" trigger="click">
  203. <span class="el-dropdown-link">
  204. <i class="fm-iconfont icon-biaogeshezhi" :title="$t('fm.tooltip.cellsetting')"></i>
  205. </span>
  206. <el-dropdown-menu slot="dropdown">
  207. <el-dropdown-item command="insertleft" @click.native.stop="handleInsertLeft">{{$t('fm.tooltip.insertcolumnleft')}}</el-dropdown-item>
  208. <el-dropdown-item command="insertright" @click.native.stop="handleInsertRight">{{$t('fm.tooltip.insertcolumnright')}}</el-dropdown-item>
  209. <el-dropdown-item command="insertbefore" @click.native.stop="handleInserBefore">{{$t('fm.tooltip.insertrowbefore')}}</el-dropdown-item>
  210. <el-dropdown-item command="insertafter" @click.native.stop="handleInserAfter">{{$t('fm.tooltip.insertrowafter')}}</el-dropdown-item>
  211. <el-dropdown-item command="right" @click.native.stop="handleRight(column)" :disabled="!showRight" divided>{{$t('fm.tooltip.mergeright')}}</el-dropdown-item>
  212. <el-dropdown-item command="bottom" @click.native.stop="handleBottom(column)" :disabled="!showBottom">{{$t('fm.tooltip.mergedown')}}</el-dropdown-item>
  213. <el-dropdown-item command="splitcolumns" @click.native.stop="handleSplitColumn" divided :disabled="!showSplitColumn">{{$t('fm.tooltip.splitcolumns')}}</el-dropdown-item>
  214. <el-dropdown-item command="splitrows" @click.native.stop="handleSplitRow" :disabled="!showSplitRow">{{$t('fm.tooltip.splitrows')}}</el-dropdown-item>
  215. <el-dropdown-item command="removecolumn" @click.native.stop="handleRemoveColumn" :disabled="!showRemoveColumn" divided>{{$t('fm.tooltip.deletecolumn')}}</el-dropdown-item>
  216. <el-dropdown-item command="removerow" @click.native.stop="handleRemoveRow" :disabled="!showRemoveRow" >{{$t('fm.tooltip.deleterow')}}</el-dropdown-item>
  217. <el-dropdown-item command="setcolwidth" @click.native.stop="handleSetColumnWidth" :disabled="column.options.colspan !== 1" divided>{{$t('fm.tooltip.setcolwidth')}}</el-dropdown-item>
  218. </el-dropdown-menu>
  219. </el-dropdown>
  220. </div>
  221. <div class="widget-view-type ">
  222. <span>{{column.type ? $t('fm.components.fields.' + column.type) : ''}}</span>
  223. </div>
  224. </td>
  225. </tr>
  226. </table>
  227. </div>
  228. <div class="widget-view-action widget-col-action" v-if="selectWidget.key == element.key">
  229. <i class="fm-iconfont icon--charuhang" @click.stop="handleAddRow(index)" :title="$t('fm.tooltip.addrow')"></i>
  230. <i class="fm-iconfont icon--charulie" @click.stop="handleAddColumns(index)" :title="$t('fm.tooltip.addcolumn')"></i>
  231. <i class="fm-iconfont icon-icon_clone" @click.stop="handleReportClone(index)" :title="$t('fm.tooltip.clone')"></i>
  232. <i class="fm-iconfont icon-trash" @click.stop="handleWidgetDelete(index)" :title="$t('fm.tooltip.trash')"></i>
  233. </div>
  234. <div class="widget-view-drag widget-col-drag" v-if="selectWidget.key == element.key">
  235. <i class="fm-iconfont icon-drag drag-widget"></i>
  236. </div>
  237. <div class="widget-view-model " :style="{'color': element.options.dataBind ? '' : '#666'}">
  238. <span>{{element.model}}</span>
  239. </div>
  240. <div class="widget-view-type ">
  241. <span>{{element.type ? $t('fm.components.fields.' + element.type) : ''}}</span>
  242. </div>
  243. </div>
  244. </template>
  245. <script>
  246. import WidgetFormItem from './WidgetFormItem'
  247. import WidgetTable from './WidgetTable'
  248. import WidgetInline from './WidgetInline'
  249. import Draggable from 'vuedraggable'
  250. import _ from 'lodash'
  251. import { CloneLayout } from '../util/layout-clone.js'
  252. import { EventBus } from '../util/event-bus.js'
  253. import { generateKeyToTD, generateKeyToTH, generateKeyToCol, fixDraggbleList, addClass, removeClass } from '../util'
  254. export default {
  255. name: 'widget-report',
  256. components: {
  257. Draggable,
  258. WidgetFormItem,
  259. WidgetTable,
  260. WidgetInline,
  261. WidgetColItem: () => import('./WidgetColItem.vue'),
  262. WidgetTabItem: () => import('./WidgetTabItem.vue'),
  263. WidgetSubForm: () => import('./WidgetSubForm.vue'),
  264. WidgetCollapse: () => import('./WidgetCollapse.vue'),
  265. WidgetCard: () => import('./WidgetCard.vue'),
  266. WidgetGroup: () => import('./WidgetGroup.vue')
  267. },
  268. props: ['element', 'select', 'index', 'data', 'platform', 'formKey', 'subform'],
  269. inject: ['getDragging', 'setDragging'],
  270. data () {
  271. return {
  272. selectWidget: this.select || {},
  273. selectR: -1,
  274. selectC: -1,
  275. selectIndex: -1
  276. }
  277. },
  278. created () {
  279. // 处理v1.5.8以前的表格
  280. console.log('created', this.element)
  281. if (!this.element.headerRow) {
  282. this.element.headerRow = this.element.rows[0].columns.map(item => ({
  283. type: 'th',
  284. options: {
  285. width: item.options.width
  286. },
  287. key: Math.random().toString(36).slice(-8)
  288. }))
  289. }
  290. },
  291. computed: {
  292. showRight () {
  293. if (this.selectR >= 0 && this.selectC >= 0) {
  294. const currentRowspan = this.element.rows[this.selectR].columns[this.selectC].options.rowspan
  295. const currentColspan = this.element.rows[this.selectR].columns[this.selectC].options.colspan
  296. if (this.selectC + currentColspan < this.element.rows[this.selectR].columns.length) {
  297. const nextColumn = this.element.rows[this.selectR].columns[currentColspan + this.selectC]
  298. if (!nextColumn.options.invisible && currentRowspan == nextColumn.options.rowspan) {
  299. return true
  300. }
  301. }
  302. }
  303. return false
  304. },
  305. showBottom () {
  306. if (this.selectR >= 0 && this.selectC >= 0) {
  307. const currentRowspan = this.element.rows[this.selectR].columns[this.selectC].options.rowspan
  308. const currentColspan = this.element.rows[this.selectR].columns[this.selectC].options.colspan
  309. if (currentRowspan + this.selectR < this.element.rows.length) {
  310. const nextColumn = this.element.rows[currentRowspan + this.selectR].columns[this.selectC]
  311. if (!nextColumn.options.invisible && currentColspan == nextColumn.options.colspan) {
  312. return true
  313. }
  314. }
  315. }
  316. return false
  317. },
  318. showRemoveRow () {
  319. if (this.element.rows.length > 1 && this.selectR >= 0 && this.selectC >= 0) {
  320. const currentRowspan = this.element.rows[this.selectR].columns[this.selectC].options.rowspan
  321. if (currentRowspan == 1) {
  322. return true
  323. } else {
  324. let i = 0
  325. for (; i < this.element.rows[this.selectR].columns.length; i++) {
  326. if (currentRowspan != this.element.rows[this.selectR].columns[i].options.rowspan || this.element.rows[this.selectR].columns[i].options.invisible) {
  327. return false
  328. }
  329. }
  330. if (this.element.rows[this.selectR].columns.length == i) {
  331. return true
  332. }
  333. }
  334. }
  335. return false
  336. },
  337. showRemoveColumn () {
  338. if (this.selectR >= 0 && this.selectC >= 0 && this.element.rows[this.selectR].columns.length > 1) {
  339. const currentColspan = this.element.rows[this.selectR].columns[this.selectC].options.colspan
  340. if (currentColspan == 1) {
  341. return true
  342. } else {
  343. let i = 0;
  344. for (; i < this.element.rows.length; i++) {
  345. if (currentColspan != this.element.rows[i].columns[this.selectC].options.colspan || this.element.rows[i].columns[this.selectC].options.invisible) {
  346. return false
  347. }
  348. }
  349. if (this.element.rows.length == i) {
  350. return true
  351. }
  352. }
  353. }
  354. return false
  355. },
  356. showSplitColumn () {
  357. if (this.selectR >= 0 && this.selectC >= 0) {
  358. return this.element.rows[this.selectR].columns[this.selectC].options.colspan > 1
  359. }
  360. return false
  361. },
  362. showSplitRow () {
  363. if (this.selectR >= 0 && this.selectC >= 0) {
  364. return this.element.rows[this.selectR].columns[this.selectC].options.rowspan > 1
  365. }
  366. return false
  367. }
  368. },
  369. methods: {
  370. handleMouseover (e) {
  371. !this.getDragging() && addClass(this.$refs['widgetReport'], 'is-hover')
  372. },
  373. handleMouseout (e) {
  374. removeClass(this.$refs['widgetReport'], 'is-hover')
  375. },
  376. handleMouseoverTD (r, i) {
  377. !this.getDragging() && addClass(this.$refs[`widgetTD_${r}_${i}`][0], 'is-hover')
  378. },
  379. handleMouseoutTD (r, i) {
  380. removeClass(this.$refs[`widgetTD_${r}_${i}`][0], 'is-hover')
  381. },
  382. handleMouseoverTH (i) {
  383. !this.getDragging() && addClass(this.$refs[`widgetTH_${i}`][0], 'is-hover')
  384. },
  385. handleMouseoutTH (i) {
  386. removeClass(this.$refs[`widgetTH_${i}`][0], 'is-hover')
  387. },
  388. handlePut (a, b, c) {
  389. if (c.className.split(' ').indexOf('widget-dialog') >=0 || c.className.split(' ').indexOf('dialog-put') >= 0 || c.children[0].className.split(' ').indexOf('dialog-put') >= 0) {
  390. return false
  391. }
  392. return true
  393. },
  394. handleSelectWidget (index) {
  395. this.selectWidget = this.data.list[index]
  396. },
  397. handleSelectItemWidget (rowIndex, colIndex) {
  398. this.selectWidget = this.data.list[this.index].rows[rowIndex].columns[colIndex]
  399. this.selectR = rowIndex
  400. this.selectC = colIndex
  401. },
  402. handleSelectHeaderWidget (index) {
  403. this.selectWidget = this.data.list[this.index].headerRow[index]
  404. },
  405. handleWidgetDelete (index) {
  406. if (this.data.list.length == 1) {
  407. this.$emit('select-change', -1)
  408. } else {
  409. if (this.data.list.length - 1 == index) {
  410. this.$emit('select-change', index - 1)
  411. } else {
  412. this.$emit('select-change', index)
  413. }
  414. }
  415. this.data.list.splice(index, 1)
  416. setTimeout(() => {
  417. EventBus.$emit('on-history-add-' + this.formKey)
  418. }, 20)
  419. },
  420. handleWidgetItemAdd ($event, element, rowIndex, colIndex) {
  421. const newIndex = $event.newIndex
  422. fixDraggbleList(element.rows[rowIndex].columns[colIndex].list, newIndex)
  423. const key = Math.random().toString(36).slice(-8)
  424. this.$set(element.rows[rowIndex].columns[colIndex].list, newIndex, _.cloneDeep(element.rows[rowIndex].columns[colIndex].list[newIndex]))
  425. this.$set(element.rows[rowIndex].columns[colIndex].list, newIndex, {
  426. ...element.rows[rowIndex].columns[colIndex].list[newIndex],
  427. options: {
  428. ...element.rows[rowIndex].columns[colIndex].list[newIndex].options,
  429. remoteFunc: element.rows[rowIndex].columns[colIndex].list[newIndex].options.remoteFunc || 'func_'+key,
  430. remoteOption: element.rows[rowIndex].columns[colIndex].list[newIndex].options.remoteOption || 'option_'+key,
  431. tableColumn: false,
  432. hideLabel: true,
  433. subform: this.subform ? true : false
  434. },
  435. key: element.rows[rowIndex].columns[colIndex].list[newIndex].key ? element.rows[rowIndex].columns[colIndex].list[newIndex].key : key,
  436. model: element.rows[rowIndex].columns[colIndex].list[newIndex].model ? element.rows[rowIndex].columns[colIndex].list[newIndex].model : element.rows[rowIndex].columns[colIndex].list[newIndex].type + '_' + key,
  437. rules: element.rows[rowIndex].columns[colIndex].list[newIndex].rules ? [...element.rows[rowIndex].columns[colIndex].list[newIndex].rules] : []
  438. })
  439. if (element.rows[rowIndex].columns[colIndex].list[newIndex].type == 'report') {
  440. element.rows[rowIndex].columns[colIndex].list[newIndex].rows = generateKeyToTD(element.rows[rowIndex].columns[colIndex].list[newIndex].rows)
  441. element.rows[rowIndex].columns[colIndex].list[newIndex].headerRow = generateKeyToTH(element.rows[rowIndex].columns[colIndex].list[newIndex].headerRow)
  442. }
  443. if (element.rows[rowIndex].columns[colIndex].list[newIndex].type == 'grid') {
  444. element.rows[rowIndex].columns[colIndex].list[newIndex].columns = generateKeyToCol(element.rows[rowIndex].columns[colIndex].list[newIndex].columns)
  445. }
  446. this.selectWidget = element.rows[rowIndex].columns[colIndex].list[newIndex]
  447. EventBus.$emit('on-history-add-' + this.formKey)
  448. },
  449. handleWidgetItemUpdate () {
  450. EventBus.$emit('on-history-add-' + this.formKey)
  451. },
  452. handleReportClone (index) {
  453. let cloneData = _.cloneDeep(this.data.list[index])
  454. this.data.list.splice(index + 1, 0, CloneLayout(cloneData))
  455. this.$nextTick(() => {
  456. this.selectWidget = this.data.list[index + 1]
  457. this.$nextTick(() => { EventBus.$emit('on-history-add-' + this.formKey) })
  458. })
  459. },
  460. handleAddRow (index) {
  461. const columns = this.data.list[index].rows[this.data.list[index].rows.length - 1].columns.length
  462. this.data.list[index].rows.push({
  463. columns: Array.from({length: columns}, _ => {
  464. return {
  465. type: 'td',
  466. list: [],
  467. options: {
  468. customClass: '',
  469. colspan: 1,
  470. rowspan: 1,
  471. align: 'left',
  472. valign: 'top',
  473. width: '',
  474. height: '',
  475. },
  476. key: Math.random().toString(36).slice(-8)
  477. }
  478. })
  479. })
  480. this.$nextTick(() => { EventBus.$emit('on-history-add-' + this.formKey) })
  481. },
  482. handleAddColumns (index) {
  483. this.data.list[index].headerRow.push({
  484. type: 'th',
  485. options: {
  486. width: ''
  487. },
  488. key: Math.random().toString(36).slice(-8)
  489. })
  490. this.data.list[index].rows.forEach(item => {
  491. item.columns.push({
  492. type: 'td',
  493. list: [],
  494. options: {
  495. customClass: '',
  496. colspan: 1,
  497. rowspan: 1,
  498. align: 'left',
  499. valign: 'top',
  500. width: '',
  501. height: '',
  502. },
  503. key: Math.random().toString(36).slice(-8)
  504. })
  505. })
  506. this.$nextTick(() => { EventBus.$emit('on-history-add-' + this.formKey) })
  507. },
  508. insertColumns (insertIndex) {
  509. this.element.headerRow.splice(insertIndex, 0,{
  510. type: 'th',
  511. options: {
  512. width: ''
  513. },
  514. key: Math.random().toString(36).slice(-8)
  515. })
  516. for (let i = 0; i < this.element.rows.length; i++) {
  517. const prevIndex = this.findPrevColIndex(i, insertIndex)
  518. if (prevIndex != insertIndex && this.element.rows[i].columns[insertIndex].options.invisible) {
  519. this.element.rows[i].columns.splice(insertIndex, 0, {
  520. type: 'td',
  521. list: [],
  522. options: {
  523. customClass: '',
  524. colspan: 1,
  525. rowspan: 1,
  526. align: 'left',
  527. valign: 'top',
  528. width: '',
  529. height: '',
  530. invisible: true
  531. },
  532. key: Math.random().toString(36).slice(-8)
  533. })
  534. // 插入隐藏列后,进行标记计算
  535. const beforeColspan = this.element.rows[i].columns[prevIndex].options.colspan
  536. this.element.rows[i].columns[prevIndex].options.colspan = beforeColspan + 1
  537. for (let j = 0; j < beforeColspan + 1; j++) {
  538. this.element.rows[i].columns[prevIndex + j].options.markCol = j
  539. }
  540. } else {
  541. this.element.rows[i].columns.splice(insertIndex, 0, {
  542. type: 'td',
  543. list: [],
  544. options: {
  545. customClass: '',
  546. colspan: 1,
  547. rowspan: 1,
  548. align: 'left',
  549. valign: 'top',
  550. width: '',
  551. height: '',
  552. },
  553. key: Math.random().toString(36).slice(-8)
  554. })
  555. }
  556. }
  557. },
  558. insertRow (insertIndex) {
  559. const rowArray = []
  560. for (let i = 0; i < this.element.rows[0].columns.length; i++) {
  561. const prevIndex = this.findPrevRowIndex(insertIndex, i)
  562. if (prevIndex != insertIndex && this.element.rows[insertIndex].columns[i].options.invisible) {
  563. rowArray.push({
  564. type: 'td',
  565. list: [],
  566. options: {
  567. customClass: '',
  568. colspan: 1,
  569. rowspan: 1,
  570. align: 'left',
  571. valign: 'top',
  572. width: '',
  573. height: '',
  574. invisible: true
  575. },
  576. key: Math.random().toString(36).slice(-8)
  577. })
  578. this.element.rows[prevIndex].columns[i].options.rowspan = this.element.rows[prevIndex].columns[i].options.rowspan + 1
  579. } else {
  580. rowArray.push({
  581. type: 'td',
  582. list: [],
  583. options: {
  584. customClass: '',
  585. colspan: 1,
  586. rowspan: 1,
  587. align: 'left',
  588. valign: 'top',
  589. width: '',
  590. height: '',
  591. },
  592. key: Math.random().toString(36).slice(-8)
  593. })
  594. }
  595. }
  596. this.element.rows.splice(insertIndex, 0, {
  597. columns: rowArray
  598. })
  599. // 行插入成功后,处理标记
  600. this.$nextTick(() => {
  601. for (let i = 0; i < this.element.rows[insertIndex].columns.length; i++) {
  602. if (this.element.rows[insertIndex].columns[i].options.invisible) {
  603. const prevIndex = this.findPrevRowIndex(insertIndex - 1, i)
  604. if (!this.element.rows[prevIndex].columns[i].options.invisible) {
  605. this.markTableItem(prevIndex, i)
  606. }
  607. }
  608. }
  609. })
  610. },
  611. handleInsertLeft () {
  612. const insertIndex = this.selectC
  613. this.insertColumns(insertIndex)
  614. this.selectC = this.selectC++
  615. this.$nextTick(() => { EventBus.$emit('on-history-add-' + this.formKey) })
  616. },
  617. handleInsertRight () {
  618. const insertColIndex = this.element.rows[this.selectR].columns[this.selectC].options.colspan > 1
  619. ? this.findNextColIndex(this.selectR, this.selectC + 1) : this.selectC + 1
  620. this.insertColumns(insertColIndex)
  621. this.$nextTick(() => { EventBus.$emit('on-history-add-' + this.formKey) })
  622. },
  623. handleInserBefore () {
  624. const insertIndex = this.selectR
  625. this.insertRow(insertIndex)
  626. this.selectR = this.selectR++
  627. this.$nextTick(() => { EventBus.$emit('on-history-add-' + this.formKey) })
  628. },
  629. handleInserAfter () {
  630. const insertRowIndex = this.element.rows[this.selectR].columns[this.selectC].options.rowspan > 1
  631. ? this.findNextRowIndex(this.selectR + 1, this.selectC) : this.selectR + 1
  632. this.insertRow(insertRowIndex)
  633. this.$nextTick(() => { EventBus.$emit('on-history-add-' + this.formKey) })
  634. },
  635. // 合并的表格做上标记
  636. markTableItem (R, C) {
  637. const colspan = this.element.rows[R].columns[C].options.colspan
  638. const rowspan = this.element.rows[R].columns[C].options.rowspan
  639. for (let i = 0; i < rowspan; i++) {
  640. for (let j = 0; j < colspan; j++) {
  641. this.element.rows[R + i].columns[C + j].options.markCol = j
  642. this.element.rows[R + i].columns[C + j].options.markRow = i
  643. }
  644. }
  645. },
  646. handleRight (column) {
  647. const currentColspan = column.options.colspan
  648. const nextC = this.selectC + currentColspan
  649. const nextColspan = this.element.rows[this.selectR].columns[nextC].options.colspan
  650. this.$set(column.options, 'colspan', currentColspan + nextColspan) // 设置当前colspan
  651. this.element.rows[this.selectR].columns[nextC].options.invisible = true // 将被合并项隐藏
  652. // 处理表格中元素
  653. const tempList = [...this.element.rows[this.selectR].columns[nextC].list]
  654. this.element.rows[this.selectR].columns[nextC].list = []
  655. column.list = column.list.concat(tempList)
  656. // 将合并的表格做上标记
  657. this.markTableItem(this.selectR, this.selectC)
  658. this.$nextTick(() => { EventBus.$emit('on-history-add-' + this.formKey) })
  659. },
  660. handleBottom (column) {
  661. const currentRowspan = column.options.rowspan
  662. const nextR = this.selectR + currentRowspan
  663. const nextRowspan = this.element.rows[nextR].columns[this.selectC].options.rowspan
  664. this.$set(column.options, 'rowspan', currentRowspan + nextRowspan)
  665. this.element.rows[nextR].columns[this.selectC].options.invisible = true
  666. const tempList = [...this.element.rows[nextR].columns[this.selectC].list]
  667. this.element.rows[nextR].columns[this.selectC].list = []
  668. column.list = column.list.concat(tempList)
  669. // 将合并的表格做上标记
  670. this.markTableItem(this.selectR, this.selectC)
  671. this.$nextTick(() => { EventBus.$emit('on-history-add-' + this.formKey) })
  672. },
  673. handleSplitColumn () {
  674. const currentColspan = this.element.rows[this.selectR].columns[this.selectC].options.colspan
  675. const currentRowspan = this.element.rows[this.selectR].columns[this.selectC].options.rowspan
  676. for (let i = 0; i < currentColspan; i++) {
  677. this.element.rows[this.selectR].columns[this.selectC + i].options.invisible = false
  678. this.element.rows[this.selectR].columns[this.selectC + i].options.colspan = 1
  679. this.element.rows[this.selectR].columns[this.selectC + i].options.rowspan = currentRowspan
  680. this.markTableItem(this.selectR, this.selectC + i)
  681. }
  682. this.$nextTick(() => { EventBus.$emit('on-history-add-' + this.formKey) })
  683. },
  684. handleSplitRow () {
  685. const currentColspan = this.element.rows[this.selectR].columns[this.selectC].options.colspan
  686. const currentRowspan = this.element.rows[this.selectR].columns[this.selectC].options.rowspan
  687. for (let i = 0; i < currentRowspan; i++) {
  688. this.element.rows[this.selectR + i].columns[this.selectC].options.invisible = false
  689. this.element.rows[this.selectR + i].columns[this.selectC].options.rowspan = 1
  690. this.element.rows[this.selectR + i].columns[this.selectC].options.colspan = currentColspan
  691. this.markTableItem(this.selectR + i, this.selectC)
  692. }
  693. this.$nextTick(() => { EventBus.$emit('on-history-add-' + this.formKey) })
  694. },
  695. findPrevRowIndex (rowIndex, colIndex) {
  696. if (rowIndex >= this.element.rows.length || !this.element.rows[rowIndex].columns[colIndex].options.markRow) {
  697. return rowIndex
  698. } else {
  699. return this.findPrevRowIndex(rowIndex - 1, colIndex)
  700. }
  701. },
  702. findPrevColIndex (rowIndex, colIndex) {
  703. if (colIndex >= this.element.rows[rowIndex].columns.length || !this.element.rows[rowIndex].columns[colIndex].options.markCol) {
  704. return colIndex
  705. } else {
  706. return this.findPrevColIndex(rowIndex, colIndex - 1)
  707. }
  708. },
  709. findNextColIndex (rowIndex, colIndex) {
  710. if (colIndex >= this.element.rows[rowIndex].columns.length || !this.element.rows[rowIndex].columns[colIndex].options.markCol) {
  711. return colIndex
  712. } else {
  713. return this.findNextColIndex(rowIndex, colIndex + 1)
  714. }
  715. },
  716. findNextRowIndex (rowIndex, colIndex) {
  717. if (rowIndex >= this.element.rows.length || !this.element.rows[rowIndex].columns[colIndex].options.markRow) {
  718. return rowIndex
  719. } else {
  720. return this.findNextRowIndex(rowIndex + 1, colIndex)
  721. }
  722. },
  723. handleRemoveRow () {
  724. for (let j = 0; j < this.element.rows[this.selectR].columns.length; j++) {
  725. const currentRowspan = this.element.rows[this.selectR].columns[j].options.rowspan
  726. const currentcolspan = this.element.rows[this.selectR].columns[j].options.colspan
  727. const invisible = this.element.rows[this.selectR].columns[j].options.invisible
  728. if (invisible) {
  729. const prevIndex = this.findPrevRowIndex(this.selectR, j)
  730. if (prevIndex != this.selectR && this.element.rows[prevIndex].columns[j].options.rowspan > 1) {
  731. this.element.rows[prevIndex].columns[j].options.rowspan = this.element.rows[prevIndex].columns[j].options.rowspan - 1
  732. }
  733. } else if (currentRowspan > 1) {
  734. this.element.rows[this.selectR + 1].columns[j].list = [...this.element.rows[this.selectR].columns[j].list]
  735. this.element.rows[this.selectR + 1].columns[j].options.invisible = false
  736. this.element.rows[this.selectR + 1].columns[j].options.rowspan = currentRowspan - 1
  737. this.element.rows[this.selectR + 1].columns[j].options.colspan = currentcolspan
  738. // 重新计算标记
  739. this.markTableItem(this.selectR + 1, j)
  740. } else {
  741. }
  742. }
  743. this.element.rows.splice(this.selectR, 1)
  744. this.$nextTick(() => { EventBus.$emit('on-history-add-' + this.formKey) })
  745. },
  746. handleRemoveColumn () {
  747. for (let i = 0; i < this.element.rows.length; i++) {
  748. const currentColspan = this.element.rows[i].columns[this.selectC].options.colspan
  749. const currentRowspan = this.element.rows[i].columns[this.selectC].options.rowspan
  750. const invisible = this.element.rows[i].columns[this.selectC].options.invisible
  751. if (invisible) {
  752. const prevIndex = this.findPrevColIndex(i, this.selectC)
  753. if (prevIndex != this.selectC && this.element.rows[i].columns[prevIndex].options.colspan > 1) {
  754. this.element.rows[i].columns[prevIndex].options.colspan = this.element.rows[i].columns[prevIndex].options.colspan - 1
  755. }
  756. } else if (currentColspan > 1) {
  757. this.element.rows[i].columns[this.selectC + 1].list = [...this.element.rows[i].columns[this.selectC].list]
  758. this.element.rows[i].columns[this.selectC + 1].options.invisible = false
  759. this.element.rows[i].columns[this.selectC + 1].options.colspan = currentColspan - 1
  760. this.element.rows[i].columns[this.selectC + 1].options.rowspan = currentRowspan
  761. // 重新计算标记
  762. this.markTableItem(i, this.selectC + 1)
  763. } else {
  764. }
  765. this.element.rows[i].columns.splice(this.selectC, 1)
  766. }
  767. this.element.headerRow.splice(this.selectC, 1)
  768. this.$nextTick(() => { EventBus.$emit('on-history-add-' + this.formKey) })
  769. },
  770. handleSetColumnWidth () {
  771. this.selectWidget = this.data.list[this.index].headerRow[this.selectC]
  772. },
  773. handleSelectChange (index, item) {
  774. setTimeout(() => {
  775. index >=0 ? (this.selectWidget = item.list[index]) : (this.selectWidget = this.data.list[this.index])
  776. })
  777. }
  778. },
  779. watch: {
  780. select (val) {
  781. this.selectWidget = val
  782. this.element.headerRow && (this.selectIndex = this.element.headerRow.findIndex(item => item.key === val.key))
  783. },
  784. selectWidget: {
  785. deep: false,
  786. handler (val) {
  787. this.$emit('update:select', val)
  788. this.element.headerRow && (this.selectIndex = this.element.headerRow.findIndex(item => item.key === val.key))
  789. }
  790. },
  791. }
  792. }
  793. </script>