xm-child-table.vue 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998
  1. <template>
  2. <div :class="[$style.wrapper, $style.sdFormforxmchild]">
  3. <div v-if="captionvisiable" :class="[$style.caption]">
  4. {{ label }}
  5. <div v-if="!readOnly" :class="$style.header">
  6. <a-button v-if="addbuttonvisiable" type="link" @click="add">
  7. <a-icon type="plus-circle" :theme="'filled'" />
  8. 添加
  9. </a-button>
  10. <a-button
  11. v-if="deletebuttonvisiable"
  12. :class="$style.relativeBtn"
  13. type="link"
  14. :disabled="selectedRowKeys.length === 0"
  15. @click="remove(selectedRowKeys)"
  16. >
  17. <a-icon type="minus-circle" :theme="'filled'" />
  18. 删除
  19. </a-button>
  20. <a-button v-if="savebuttonvisiable" type="link" @click="save">
  21. <a-icon type="check-circle" :theme="'filled'" />
  22. 保存
  23. </a-button>
  24. </div>
  25. </div>
  26. <sd-table
  27. v-if="sdtableflag"
  28. ref="sdtable"
  29. size="middle"
  30. :columns="_columns"
  31. :width="width"
  32. :sortable="false"
  33. :data-source="value"
  34. :row-key="(record, index) => index"
  35. :pagination="false"
  36. :row-selection="
  37. readOnly
  38. ? null
  39. : {
  40. getCheckboxProps(record) {
  41. return {
  42. props: { disabled: !showSelection(record) },
  43. }
  44. },
  45. selectedRowKeys: selectedRowKeys,
  46. onChange: onSelectChange,
  47. onSelectAll: onSelectAll,
  48. }
  49. "
  50. :custom-row="
  51. (record, index) => {
  52. return {
  53. on: {
  54. click: () => {
  55. edit(index)
  56. },
  57. },
  58. }
  59. }
  60. "
  61. @update:data-source="fnupdate"
  62. @change="onChange"
  63. >
  64. <template
  65. v-for="(field, index) in fields"
  66. :slot="'sd_' + field.name"
  67. slot-scope="text, record, index"
  68. >
  69. <slot v-bind="{ field, text, record, value, index }" :name="field.name + '_xm'">
  70. <sdForm :ref="field.name + '_' + index" :init-values="[field]" :read-only="readOnly">
  71. <template v-slot="scope">
  72. <slot v-bind="{ field, text, record, value, index }" :name="field.name">
  73. <sd-form-item
  74. v-if="field.dataType === 'date'"
  75. :hidden="field.dataType === 'id'"
  76. :name="field.name"
  77. :label="null"
  78. :input-props="{
  79. defaultValue:
  80. value[index][field.name] !== undefined
  81. ? moment(Number(value[index][field.name]))
  82. : value[index][field.name],
  83. nodename: field.name + '_' + index,
  84. }"
  85. @change="savetableh(index, field)"
  86. />
  87. <sd-attachment
  88. v-else-if="field.dataType === 'attachment'"
  89. :group-id="JSON.parse(value[index][field.name]).value"
  90. :read-only="readOnly"
  91. />
  92. <span
  93. v-else-if="
  94. dzcl &&
  95. (field.name === 'userType' || field.name === 'userId') &&
  96. (value[index]['userType'] === '04' || value[index]['userType'] === '05') &&
  97. !readOnly
  98. "
  99. >
  100. <span v-if="field.name === 'userType'">
  101. <span
  102. v-if="value[index]['userType'] === '04' || value[index]['userType'] === '05'"
  103. >
  104. {{
  105. usertypeselectList.find((i) => i.value === value[index]['userType'])?.label
  106. }}</span
  107. >
  108. <span v-else></span>
  109. </span>
  110. <span>{{ getDisplayVaule(field, text) }}</span>
  111. </span>
  112. <sd-form-item
  113. v-else-if="dzcl && field.name === 'userType'"
  114. :hidden="field.dataType === 'id'"
  115. :name="field.name"
  116. :label="null"
  117. >
  118. <template slot="read">
  119. <span
  120. v-if="value[index]['userType'] === '04' || value[index]['userType'] === '05'"
  121. >
  122. {{
  123. usertypeselectList.find((i) => i.value === value[index]['userType'])?.label
  124. }}</span
  125. >
  126. <span v-else>{{ getDisplayVaule(field, text) }}</span>
  127. </template>
  128. <a-select v-model="value[index][field.name]" @change="savetableh(index, field)">
  129. <a-select-option
  130. v-for="(key, index) in selectitem"
  131. :key="index"
  132. :value="key.value"
  133. >
  134. {{ key.label }}
  135. </a-select-option>
  136. </a-select>
  137. </sd-form-item>
  138. <sd-form-item
  139. v-else
  140. :hidden="field.dataType === 'id'"
  141. :name="field.name"
  142. :label="null"
  143. :input-props="{
  144. defaultValue:
  145. field.dataType === 'selectperson' &&
  146. value[index][field.name] !== undefined &&
  147. typeof value[index][field.name] !== 'object'
  148. ? JSON.parse(value[index][field.name])
  149. : value[index][field.name],
  150. }"
  151. @blur="savetableh(index, field)"
  152. @change="savetableh(index, field)"
  153. />
  154. </slot>
  155. </template>
  156. </sdForm>
  157. </slot>
  158. </template>
  159. </sd-table>
  160. <a-modal
  161. v-model="visible"
  162. :title="label || '详情'"
  163. destroy-on-close
  164. v-bind="{ width: 800 }"
  165. :mask-closable="false"
  166. :footer="readOnly ? null : undefined"
  167. @ok="save"
  168. @cancel="attkeys[action] = Math.random()"
  169. >
  170. <sdForm ref="form" :init-values="editRecord" :read-only="readOnly">
  171. <template v-slot="scope">
  172. <!--
  173. @slot 详情表单内容,8.0.4及以后版本支持
  174. @binding {object} model 整个表单的数据,可用于 v-model 绑定
  175. @binding {object} fields 后台返回的字段定义
  176. -->
  177. <slot v-bind="scope" name="form">
  178. <sd-form-item
  179. v-for="field in fields"
  180. :key="field.name"
  181. :hidden="field.dataType === 'id'"
  182. :name="field.name"
  183. />
  184. </slot>
  185. </template>
  186. </sdForm>
  187. </a-modal>
  188. <div :class="$style.loading">
  189. <a-spin v-if="!sdtableflag" />
  190. </div>
  191. </div>
  192. </template>
  193. <script>
  194. import Vue from 'vue'
  195. import { Modal } from 'ant-design-vue'
  196. import { getComponentSpec } from '@/common/components/sd-form'
  197. import moment from 'moment'
  198. import axios from '@/common/services/axios-instance'
  199. import components from './_import-components/xm-child-table-import'
  200. // Vue.use(DatePicker)
  201. // Vue.use(TimePicker)
  202. /**
  203. * 主子表、动态表格字段
  204. * @displayName XmChildTable 主子表
  205. */
  206. export default {
  207. name: 'XmChildTable',
  208. components: {
  209. ...components,
  210. sdForm: () => import('@/common/components/sd-form'),
  211. },
  212. model: {
  213. prop: 'value',
  214. event: 'change',
  215. },
  216. props: {
  217. /**
  218. * 字表的值,{key:value}的格式
  219. */
  220. value: {
  221. type: Array,
  222. default: () => [],
  223. },
  224. /**
  225. * 字表的字段属性
  226. */
  227. fields: {
  228. type: Array,
  229. default: () => [],
  230. },
  231. /**
  232. * 是否只读
  233. */
  234. readOnly: {
  235. type: Boolean,
  236. default: false,
  237. },
  238. /**
  239. * 标签名
  240. */
  241. label: {
  242. type: String,
  243. default: '',
  244. },
  245. /**
  246. * 自定义子表列属性,如[{dataIndex:'shuxingmingzi15',width:'120px'}],8.0.4及以后版本支持
  247. */
  248. columns: {
  249. type: Array,
  250. default: () => [],
  251. },
  252. /**
  253. * 某行是否可选
  254. * @since 8.0.11
  255. */
  256. showSelection: {
  257. type: Function,
  258. default: () => true,
  259. },
  260. width: {
  261. type: Number,
  262. default: 100,
  263. },
  264. datachange: {
  265. type: Function,
  266. default: null,
  267. },
  268. dzcl: {
  269. type: Boolean,
  270. default: false,
  271. },
  272. addfun: {
  273. type: Function,
  274. default: null,
  275. },
  276. captionvisiable: {
  277. type: Boolean,
  278. default: true,
  279. },
  280. addbuttonvisiable: {
  281. type: Boolean,
  282. default: true,
  283. },
  284. deletebuttonvisiable: {
  285. type: Boolean,
  286. default: true,
  287. },
  288. savebuttonvisiable: {
  289. type: Boolean,
  290. default: false,
  291. },
  292. fncheckdelete: {
  293. type: Function,
  294. default: null,
  295. },
  296. // 是否批量提交
  297. patchSave: {
  298. type: Boolean,
  299. default: false,
  300. },
  301. changeflag: {
  302. type: Boolean,
  303. default: false,
  304. },
  305. },
  306. data() {
  307. return {
  308. selectedRowKeys: [],
  309. visible: false,
  310. editRecord: this.fields, // 待修改或编辑的记录
  311. attkeys: {}, // 附件组件的key,行编辑了就修改对应的附件key,强制更新附件列表
  312. savevisible: true,
  313. adddataxm: {},
  314. selectitem: [],
  315. sjjs: this.getsjsl(),
  316. ndata: [],
  317. newfield: [],
  318. validflag: true,
  319. sdtableflag: true,
  320. localLoading: false,
  321. sorter: null, // 排序属性
  322. defaultValue: [], // 默认数据
  323. usertypeselectList: [],
  324. }
  325. },
  326. computed: {
  327. _columns() {
  328. const fields = JSON.parse(JSON.stringify(this.fields))
  329. return fields
  330. .filter((item) => item.dataType !== 'id')
  331. .map((item) => {
  332. const t = {
  333. dataIndex: item.name,
  334. key: item.name,
  335. title: item.caption,
  336. scopedSlots: { customRender: 'sd_' + item.name },
  337. width: item.width || '40',
  338. }
  339. const column = this.columns.find((c) => c.dataIndex === item.name)
  340. if (column) Object.assign(t, column)
  341. return t
  342. })
  343. .filter((item) => item.sdHidden !== true)
  344. },
  345. },
  346. mounted() {
  347. if (this.datachange) {
  348. this.datachange()
  349. }
  350. if (this.dzcl) {
  351. this.fields.forEach((item) => {
  352. if (item.name === 'userType') {
  353. this.usertypeselectList = [...item.attr.selectListItem]
  354. let index = item.attr.selectListItem.findIndex((item) => item.value === '04')
  355. if (index > -1) item.attr.selectListItem.splice(index, 1)
  356. index = item.attr.selectListItem.findIndex((item) => item.value === '05')
  357. if (index > -1) item.attr.selectListItem.splice(index, 1)
  358. this.selectitem = item.attr.selectListItem
  359. }
  360. })
  361. }
  362. // 默认排序,赋值有用
  363. Object.assign(this.defaultValue, this.value)
  364. // this.pagination.pageSize = this.pages
  365. // 增加默认排序
  366. const defaultSorters = this.columns
  367. .filter((col) => col.defaultSortOrder)
  368. .map((col) => ({
  369. field: col.dataIndex,
  370. order: col.defaultSortOrder,
  371. }))
  372. // 排序方法
  373. if (defaultSorters.length > 0) {
  374. this.sorter = { ...defaultSorters[0] }
  375. this.sorterFun(defaultSorters[0], true)
  376. }
  377. },
  378. destroyed() {
  379. const data = this.value || [] // 兼容初始值是null的情况
  380. const index = data.findIndex((item) => item.editable === true)
  381. if (index !== -1) {
  382. this.optbuttonClick('delete', [], index)
  383. }
  384. },
  385. methods: {
  386. // 排序点击之后,重新排序
  387. onChange(pagination, filters, sorter) {
  388. this.sorter = { ...sorter }
  389. this.sorterFun(this.sorter)
  390. },
  391. // 排序方法
  392. sorterFun(sorts, isDefault) {
  393. if (!sorts) {
  394. // 如果没有sorts,说明是父组件调用,则增加默认值
  395. Object.assign(this.defaultValue, this.value)
  396. sorts = this.sorter
  397. }
  398. // 没有排序,则使用默认排序
  399. if (!sorts?.order) {
  400. while (this.value.length > 0) {
  401. this.value.splice(0, 1)
  402. }
  403. this.defaultValue.forEach((item) => {
  404. this.value.push(item)
  405. })
  406. return
  407. }
  408. const sortValue = this.value.sort((a, b) => {
  409. if (sorts.order === 'ascend') {
  410. // 升序
  411. if (a[sorts.field] + '' < b[sorts.field] + '') {
  412. return -1
  413. }
  414. if (a[sorts.field] + '' === b[sorts.field] + '') {
  415. return 0
  416. }
  417. if (a[sorts.field] + '' > b[sorts.field] + '') {
  418. return 1
  419. }
  420. } else {
  421. // 降序
  422. if (a[sorts.field] + '' < b[sorts.field] + '') {
  423. return 1
  424. }
  425. if (a[sorts.field] + '' === b[sorts.field] + '') {
  426. return 0
  427. }
  428. if (a[sorts.field] + '' > b[sorts.field] + '') {
  429. return -1
  430. }
  431. }
  432. })
  433. this.$set(this, 'value', sortValue)
  434. },
  435. fnupdate(data) {
  436. this.sdtableflag = false
  437. this.value = data
  438. setTimeout(() => {
  439. this.sdtableflag = true
  440. }, 100)
  441. this.$emit('change', this.value)
  442. },
  443. moment,
  444. getsjsl() {
  445. let index
  446. this.fields.forEach((f) => {
  447. if (f.sdHidden === true) {
  448. index = index + 1
  449. }
  450. })
  451. return index
  452. },
  453. fngetfield(field, value) {
  454. const editRecord = [field]
  455. editRecord.forEach((item) => {
  456. // 把值放到字段信息fields里
  457. item.value = value[item.name]
  458. if (item.attr.controlType === 'DictType') {
  459. if (item.attr.selectListItem.find((t) => t.value === item.value) !== undefined) {
  460. item.attr.displayValue = item.attr.selectListItem.find(
  461. (t) => t.value === item.value
  462. ).label
  463. }
  464. }
  465. })
  466. return editRecord
  467. },
  468. getDisplayVaule(field, text) {
  469. if (getComponentSpec(field).getDisplayValue) {
  470. if (typeof text !== 'undefined' && text !== null) {
  471. const value = getComponentSpec(field).parseBackendValue?.(text) || text
  472. return getComponentSpec(field).getDisplayValue(value)
  473. } else {
  474. return ''
  475. }
  476. }
  477. return text
  478. },
  479. changolddata() {
  480. const h = new Promise((resolve) => {
  481. if (this.value !== null) {
  482. if (this.value.length > 0) {
  483. this.value.forEach((d, index) => {
  484. if (d.mainId === 0) {
  485. // 获取该行数据
  486. d.mainId = Math.random()
  487. }
  488. this.savetableh(index, null).then((r) => {
  489. if (index === this.value.length - 1) {
  490. resolve(true)
  491. }
  492. })
  493. })
  494. } else {
  495. resolve(false)
  496. }
  497. } else {
  498. resolve(true)
  499. }
  500. })
  501. return h
  502. },
  503. savetableh(i, field) {
  504. // 保存最新增的行
  505. const data = this.value || [] // 兼容初始值是null的情况
  506. const value = data[i]
  507. let fields = this.fields
  508. if (field !== null) {
  509. fields = [field]
  510. }
  511. const savef = new Promise((resolve) => {
  512. fields.forEach((item, index) => {
  513. const refname = item.name
  514. const dataType = item.dataType
  515. if (this.$refs[refname + '_' + i]) {
  516. if (dataType === 'attachment') {
  517. } else if (
  518. typeof this.$refs[refname + '_' + i][0].model[refname] === 'object' &&
  519. dataType !== 'date'
  520. ) {
  521. if (this.$refs[refname + '_' + i][0].model[refname] !== undefined) {
  522. value[item.name] = JSON.stringify(this.$refs[refname + '_' + i][0].model[refname])
  523. }
  524. } else if (dataType === 'date') {
  525. if (this.$refs[refname + '_' + i][0].model[refname] !== undefined) {
  526. value[item.name] = this.$refs[refname + '_' + i][0].getFieldValue(refname).valueOf()
  527. }
  528. } else {
  529. if (this.dzcl && refname === 'userType') {
  530. if (value[item.name] !== '04' && value[item.name] !== '05') {
  531. this.$refs[refname + '_' + i][0].setFieldValue(refname, value[item.name])
  532. }
  533. } else {
  534. if (this.$refs[refname + '_' + i][0].model[refname] !== undefined) {
  535. value[item.name] = this.$refs[refname + '_' + i][0].getFieldValue(refname)
  536. }
  537. }
  538. }
  539. }
  540. })
  541. // 一行数据已存储
  542. data[i] = value
  543. this.value = data
  544. if (!this.patchSave) {
  545. this.$emit('saved', data)
  546. }
  547. // this.$emit('change', data)
  548. resolve(true)
  549. // 打开结束时间
  550. if (field && field.name === 'joinStartTime') {
  551. document
  552. .querySelector("[nodename='joinEndTime_" + i + "'] .ant-calendar-picker-input")
  553. .click()
  554. }
  555. })
  556. if (this.changeflag) {
  557. this.$emit('change', this.value)
  558. }
  559. return savef
  560. },
  561. add() {
  562. this.action = 'add'
  563. const data = this.value || [] // 兼容初始值是null的情况
  564. // 判断当前动态表格中是否有已打开编辑的行,如果有则需要保存后才能再新增
  565. // if (data.length > 0) {
  566. // 有数据则再新增时需要先保存前面的数据
  567. this.changolddata().then((res) => {
  568. this.editRecord = this.fields
  569. const attachobj = this.fields.find((obj) => obj.dataType === 'attachment')
  570. let d1 = { mainId: 0 }
  571. if (attachobj !== undefined) {
  572. d1[attachobj.name] =
  573. '{"value":"' + Math.round(Math.random() * 100000000000000000).toString() + '"}'
  574. }
  575. this.editRecord.mainId = 0
  576. if (this.addfun) {
  577. d1 = this.addfun(d1)
  578. data.push(d1)
  579. this.adddataxm = d1
  580. if (!this.patchSave) {
  581. this.$emit('change', data)
  582. }
  583. } else {
  584. data.push(d1)
  585. this.adddataxm = d1
  586. if (!this.patchSave) {
  587. this.$emit('change', data)
  588. }
  589. }
  590. })
  591. },
  592. edit(index) {},
  593. setvalid() {
  594. this.value.forEach((h, index) => {
  595. // if (this.validflag) {
  596. const value = {}
  597. this.fields.forEach((item, fi) => {
  598. const refname = item.name
  599. const dataType = item.dataType
  600. if (this.$refs[refname + '_' + index]) {
  601. this.$refs[refname + '_' + index][0].validateFields().then((res) => {})
  602. }
  603. })
  604. })
  605. },
  606. valid() {
  607. this.validflag = true
  608. const data = this.value || [] // 兼容初始值是null的情况
  609. // 特殊处理userType
  610. if (this.dzcl) {
  611. const usertypeobj = this.fields.find((item) => item.name === 'userType')
  612. if (usertypeobj !== undefined) {
  613. data.forEach((h, hi) => {
  614. if (
  615. h.userType !== '04' &&
  616. h.userType !== '05' &&
  617. h.userType !== '' &&
  618. h.userType !== undefined
  619. ) {
  620. if (this.$refs['userType_' + hi]) {
  621. this.$refs['userType_' + hi][0].setFieldValue('userType', h.userType)
  622. }
  623. }
  624. })
  625. }
  626. }
  627. const valid = new Promise((resolve) => {
  628. // 轮询所有行数据
  629. if (data.length === 0) {
  630. resolve(true)
  631. } else {
  632. data.forEach((h, index) => {
  633. // if (this.validflag) {
  634. const value = {}
  635. this.fields.forEach((item, fi) => {
  636. const refname = item.name
  637. const dataType = item.dataType
  638. if (this.$refs[refname + '_' + index]) {
  639. this.$refs[refname + '_' + index][0]
  640. .validateFields()
  641. .then((res) => {
  642. if (!res) {
  643. this.validflag = false
  644. } else {
  645. if (index === data.length - 1 && fi === this.fields.length - 1) {
  646. setTimeout(() => {
  647. if (this.validflag) {
  648. resolve(true)
  649. } else {
  650. resolve(false)
  651. }
  652. }, 1000)
  653. }
  654. }
  655. })
  656. .catch(() => {
  657. this.validflag = false
  658. })
  659. } else {
  660. if (index === data.length - 1 && fi === this.fields.length - 1) {
  661. setTimeout(() => {
  662. if (this.validflag) {
  663. resolve(true)
  664. } else {
  665. resolve(false)
  666. }
  667. }, 1000)
  668. }
  669. }
  670. })
  671. })
  672. }
  673. })
  674. return valid
  675. },
  676. save() {
  677. if (this.readOnly || !this.visible) {
  678. // 判断visable为false时,modal没有是为了防止快速重复点击确定
  679. this.visible = false
  680. }
  681. this.changolddata().then((res) => {})
  682. const save = new Promise((resolve, reject) => {
  683. const data = this.value || [] // 兼容初始值是null的情况
  684. // 轮询所有行数据
  685. if (data.length === 0) {
  686. resolve(false)
  687. } else {
  688. let canSubmit = true
  689. data.forEach((h, index) => {
  690. const value = {}
  691. this.fields.forEach((item, fi) => {
  692. const refname = item.name
  693. const dataType = item.dataType
  694. if (this.$refs[refname + '_' + index]) {
  695. return this.$refs[refname + '_' + index][0]
  696. .validateFields()
  697. .then(() => {
  698. if (index === data.length - 1 && fi === this.fields.length - 1) {
  699. setTimeout(() => {
  700. if (canSubmit) {
  701. resolve(true)
  702. // 添加或修改之后,直接排序
  703. Object.assign(this.defaultValue, this.value)
  704. this.sorterFun(this.sorter)
  705. this.$emit('change', this.value)
  706. } else {
  707. resolve(false)
  708. }
  709. }, 0)
  710. }
  711. })
  712. .catch(() => {
  713. canSubmit = false
  714. })
  715. }
  716. })
  717. if (index === data.length - 1) {
  718. // resolve(true)
  719. if (canSubmit) {
  720. // this.$emit('change', this.value)
  721. // resolve(true)
  722. }
  723. }
  724. })
  725. }
  726. })
  727. return save
  728. },
  729. onSelectAll(selected, selectedRows, changeRows) {
  730. if (selected) {
  731. const arr = []
  732. this.value.forEach((itc, index) => {
  733. arr.push(index)
  734. })
  735. this.selectedRowKeys = arr
  736. } else {
  737. this.selectedRowKeys = []
  738. }
  739. },
  740. onSelectChange(selectedRowKeys) {
  741. this.selectedRowKeys = selectedRowKeys
  742. this.$emit('onSelectChange', this.selectedRowKeys)
  743. },
  744. remove(keys) {
  745. // 用的序号作key,从大往小删,防止串了
  746. const removeKeys = keys.sort((a, b) => b - a)
  747. if (this.fncheckdelete !== null) {
  748. if (this.fncheckdelete(this.value, removeKeys)) {
  749. const v = this.value
  750. this.sdtableflag = false
  751. removeKeys.forEach((key) => {
  752. this.value.splice(key, 1)
  753. })
  754. this.selectedRowKeys = []
  755. this.$emit('change', this.value)
  756. setTimeout(() => {
  757. this.sdtableflag = true
  758. }, 100)
  759. // 增加发布删除后事件
  760. this.$emit('deleted')
  761. this.$emit('onSelectChange', this.selectedRowKeys)
  762. } else {
  763. Modal.warning({
  764. title: '提示',
  765. content: '选择的子表数据不允许删除,请检查!',
  766. })
  767. return false
  768. }
  769. } else {
  770. this.sdtableflag = false
  771. removeKeys.forEach((key) => {
  772. this.value.splice(key, 1)
  773. })
  774. this.selectedRowKeys = []
  775. // 增加发布删除后事件
  776. this.$emit('deleted')
  777. this.$emit('onSelectChange', this.selectedRowKeys)
  778. setTimeout(() => {
  779. this.sdtableflag = true
  780. }, 100)
  781. this.$emit('change', this.value)
  782. }
  783. },
  784. optbuttonClick(val, record, i) {
  785. let value = {}
  786. const data = this.value || [] // 兼容初始值是null的情况
  787. const adddata = this.adddataxm || {}
  788. let index = 0
  789. const qqcs = this._columns.length - 2
  790. const editrow = data.find((c) => c.editable === true)
  791. switch (val) {
  792. case 'save':
  793. value = data[i]
  794. this.fields.forEach((item) => {
  795. const refname = item.name
  796. const dataType = item.dataType
  797. if (this.$refs[refname]) {
  798. this.$refs[refname][0].validateFields().then(() => {
  799. this.$refs[refname][0].getBackendValues().forEach((item) => {
  800. if (item.name === refname) {
  801. if (dataType === 'attachment') {
  802. if (adddata[refname] !== undefined) {
  803. var obj = JSON.parse(adddata[refname])
  804. value[item.name] = '{"value":"' + obj.value + '"}'
  805. } else {
  806. value[item.name] = item.value
  807. }
  808. } else {
  809. value[item.name] = item.value
  810. }
  811. }
  812. })
  813. index = index + 1
  814. if (index === qqcs) {
  815. this.attkeys[0] = Math.random()
  816. value.editable = false
  817. data.splice(i, 1)
  818. data.splice(i, 0, value)
  819. this.$emit('change', data)
  820. this.value = data
  821. }
  822. })
  823. }
  824. })
  825. this.adddataxm = {}
  826. // event.stopPropagation()
  827. break
  828. case 'delete':
  829. if (this.fncheckdelete !== null) {
  830. if (this.fncheckdelete(data, i)) {
  831. data.splice(i, 1)
  832. this.$emit('change', data)
  833. this.adddataxm = {}
  834. } else {
  835. Modal.warning({
  836. title: '提示',
  837. content: '选择的子表数据不允许删除,请检查!',
  838. })
  839. return false
  840. }
  841. } else {
  842. data.splice(i, 1)
  843. this.$emit('change', data)
  844. this.adddataxm = {}
  845. }
  846. this.value = data
  847. break
  848. case 'edit':
  849. // 判断当前动态表格中是否有已打开编辑的行,如果有则需要保存后才能再新增
  850. if (editrow !== undefined) {
  851. Modal.warning({
  852. title: '提示',
  853. content: '请先保存动态表格中内容!',
  854. })
  855. return false
  856. }
  857. if (data[i].editable === undefined || data[i].editable === false) {
  858. data[i].editable = true
  859. const value = data[i]
  860. data.splice(i, 1)
  861. data.splice(i, 0, value)
  862. this.$emit('change', data)
  863. this.editRecord = JSON.parse(JSON.stringify(this.fields))
  864. this.editRecord[0].editable = true
  865. this.editRecord.forEach((item) => {
  866. // 把值放到字段信息fields里
  867. item.value = value[item.name]
  868. if (item.attr.controlType === 'DictType') {
  869. if (item.attr.selectListItem.find((t) => t.value === item.value) !== undefined) {
  870. item.attr.displayValue = item.attr.selectListItem.find(
  871. (t) => t.value === item.value
  872. ).label
  873. }
  874. }
  875. })
  876. this.adddataxm = value
  877. }
  878. break
  879. }
  880. },
  881. fnsettablesize() {
  882. const obj = this.$refs.sdtable
  883. obj.columnInfos.forEach((col) => {
  884. col.width = col.defaultWidth
  885. col.show = col.defaultShow
  886. })
  887. },
  888. },
  889. }
  890. </script>
  891. <style module lang="scss">
  892. @use '@/common/design' as *;
  893. @use "@/common/components/sd-web-print.scss" as print;
  894. .header {
  895. position: absolute;
  896. top: 0;
  897. right: 0;
  898. :global .ant-input-search {
  899. width: 200px;
  900. }
  901. :global .ant-btn {
  902. margin: 5px;
  903. }
  904. }
  905. .caption {
  906. // position: relative;
  907. position: absolute;
  908. width: 100%;
  909. min-height: 40px;
  910. margin: 3px 0;
  911. text-align: center;
  912. }
  913. .wrapper {
  914. :global(.ant-table-tbody) {
  915. .clickable-cell {
  916. color: $primary-color;
  917. cursor: pointer;
  918. &:hover {
  919. color: $primary-5;
  920. }
  921. &:active {
  922. color: $primary-7;
  923. }
  924. }
  925. }
  926. }
  927. // 打印状态下 子表上选择列的按钮
  928. @include print.wrapper-for-printer {
  929. .wrapper {
  930. :global(.ant-table-thead .anticon) {
  931. display: none;
  932. }
  933. }
  934. }
  935. .operatecol {
  936. // display: flex;
  937. // flex-wrap: wrap;
  938. justify-content: flex-end;
  939. width: 100px;
  940. :global(.ant-btn-sm) {
  941. padding: 0 0;
  942. }
  943. :global(.menu_sd-table-header_common) {
  944. display: none;
  945. }
  946. }
  947. .sdFormforxmchild {
  948. :global(.ant-upload.ant-upload-drag p.ant-upload-drag-icon) {
  949. margin-bottom: 0;
  950. }
  951. :global(.ant-upload-text) {
  952. display: none !important;
  953. }
  954. :global(.ant-upload.ant-upload-drag .ant-upload) {
  955. padding: 0 0;
  956. }
  957. :global(.ant-form-item) {
  958. margin-bottom: 6px;
  959. }
  960. :global(.actionlist_sd-attachment_common > span) {
  961. overflow: hidden;
  962. text-overflow: ellipsis;
  963. white-space: nowrap;
  964. }
  965. :global(.actionlist_sd-attachment_common > span :hover) {
  966. white-space: normal;
  967. // overflow: auto;
  968. }
  969. :global(.ant-upload.ant-upload-drag) {
  970. text-align: left;
  971. background: none;
  972. border: none;
  973. }
  974. :global(.ant-upload.ant-upload-drag p.ant-upload-drag-icon .anticon) {
  975. font-size: 28px;
  976. }
  977. :global(.form_sd-form_common > .ant-form-item > .ant-form-item-control-wrapper) {
  978. width: 100%;
  979. }
  980. .loading {
  981. position: fixed;
  982. top: 310px;
  983. left: 50%;
  984. text-align: center;
  985. }
  986. :global(.ant-calendar-cell) {
  987. border: none !important;
  988. }
  989. }
  990. .relative-btn {
  991. position: relative;
  992. z-index: 1;
  993. }
  994. </style>