risk-identification-child-table.vue 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352
  1. <template>
  2. <div :class="$style.wrapper">
  3. <div :class="[$style.caption]">
  4. <div v-if="!readOnly" :class="$style.header">
  5. <a-button v-if="selectData" type="link" @click="select">
  6. <a-icon type="plus-circle" :theme="'filled'" />
  7. 选择
  8. </a-button>
  9. <a-button v-if="addData" type="link" @click="add">
  10. <a-icon type="plus-circle" :theme="'filled'" />
  11. 新增
  12. </a-button>
  13. <a-button
  14. type="link"
  15. :disabled="selectedRowKeys.length === 0"
  16. @click="remove(selectedRowKeys)"
  17. >
  18. <a-icon type="minus-circle" :theme="'filled'" />
  19. 删除
  20. </a-button>
  21. </div>
  22. </div>
  23. <sd-table
  24. ref="childTable"
  25. :key="sequenceColumn"
  26. size="middle"
  27. :columns="_columns"
  28. :sortable="false"
  29. :data-source="value"
  30. :row-key="(record, index) => index"
  31. :pagination="flagpage ? pagination : false"
  32. :row-selection="
  33. readOnly
  34. ? null
  35. : {
  36. getCheckboxProps(record) {
  37. return {
  38. props: { disabled: !showSelection(record) },
  39. }
  40. },
  41. selectedRowKeys: selectedRowKeys,
  42. onChange: onSelectChange,
  43. }
  44. "
  45. :custom-row="
  46. (record, index) => {
  47. return {
  48. on: {
  49. click: () => {
  50. edit(index)
  51. },
  52. },
  53. }
  54. }
  55. "
  56. @update:data-source="($event) => $emit('change', $event)"
  57. @change="onChange"
  58. >
  59. <template v-for="field in fields" :slot="'sd_' + field.name" slot-scope="text, record, index">
  60. <slot v-bind="{ field, text, record }" :name="field.name">
  61. <sd-attachment
  62. v-if="field.dataType === 'attachment'"
  63. :key="attkeys[index]"
  64. :group-id="JSON.parse(text).value"
  65. read-only
  66. />
  67. <sd-quill-reader v-else-if="field.dataType === 'tinymce'" :value="text" />
  68. <span v-else :key="field.name">
  69. {{ getDisplayVaule(field, text) }}
  70. </span>
  71. </slot>
  72. </template>
  73. </sd-table>
  74. </div>
  75. </template>
  76. <script>
  77. import sdChildTable from '@/common/components/sd-child-table/sd-child-table'
  78. import components from './_import-components/risk-identification-child-table-import'
  79. /**
  80. * 主子表、动态表格字段
  81. * @displayName RiskIdentificationChildTable 主子表
  82. */
  83. export default {
  84. name: 'RiskIdentificationChildTable',
  85. components: {
  86. ...components,
  87. },
  88. mixins: [sdChildTable],
  89. model: {
  90. prop: 'value',
  91. event: 'change',
  92. },
  93. props: {
  94. /**
  95. * 字表的值,{key:value}的格式
  96. */
  97. value: {
  98. type: Array,
  99. default: () => [],
  100. },
  101. /**
  102. * 字表的字段属性
  103. */
  104. fields: {
  105. type: Array,
  106. default: () => [],
  107. },
  108. /**
  109. * 是否只读
  110. */
  111. readOnly: {
  112. type: Boolean,
  113. default: false,
  114. },
  115. /**
  116. * 标签名
  117. */
  118. label: {
  119. type: String,
  120. default: '',
  121. },
  122. /**
  123. * 自定义子表列属性,如[{dataIndex:'shuxingmingzi15',width:'120px'}],8.0.4及以后版本支持
  124. */
  125. columns: {
  126. type: Array,
  127. default: () => [],
  128. },
  129. /**
  130. * 某行是否可选
  131. * @since 8.0.11
  132. */
  133. showSelection: {
  134. type: Function,
  135. default: () => true,
  136. },
  137. flagpage: {
  138. type: Boolean,
  139. default: false,
  140. },
  141. pages: {
  142. type: Number,
  143. default: 10,
  144. },
  145. // 是否显示选择按钮
  146. selectData: {
  147. type: Boolean,
  148. default: false,
  149. },
  150. // 是否显示新增按钮
  151. addData: {
  152. type: Boolean,
  153. default: false,
  154. },
  155. deletedIdentify: {
  156. type: Function,
  157. default: null,
  158. },
  159. type: {
  160. type: String,
  161. default: '',
  162. },
  163. },
  164. data() {
  165. return {
  166. editRecord: [], // 待修改或编辑的记录
  167. pagination: {
  168. current: 1,
  169. total: 0,
  170. showTotal: (total) => {
  171. return `总共 ${total} 条`
  172. },
  173. onChange: (page) => {
  174. this.pagination.current = page
  175. this.pageOption.startPosition = this.pageOption.maxResults * (page - 1)
  176. this.cardIndex = null
  177. this.updatedata(page)
  178. },
  179. pageSize: 10,
  180. }, // 分页属性
  181. sorter: null, // 排序属性
  182. defaultValue: [], // 默认数据
  183. }
  184. },
  185. computed: {
  186. _columns() {
  187. const fields = JSON.parse(JSON.stringify(this.fields))
  188. return [
  189. {
  190. title: '序号',
  191. dataIndex: 'sortNum',
  192. width: '50px',
  193. scopedSlots: { customRender: 'index' },
  194. sdHidden: this.sequenceColumn !== true,
  195. },
  196. ...fields
  197. .filter((item) => item.dataType !== 'id')
  198. .map((item) => {
  199. const t = {
  200. dataIndex: item.name,
  201. key: item.name,
  202. title: item.caption,
  203. scopedSlots: { customRender: 'sd_' + item.name },
  204. }
  205. const column = this.columns.find((c) => c.dataIndex === item.name)
  206. if (column) Object.assign(t, column)
  207. return t
  208. }),
  209. ].filter((item) => item.sdHidden !== true)
  210. },
  211. },
  212. mounted() {
  213. // 默认排序,赋值有用
  214. Object.assign(this.defaultValue, this.value)
  215. this.pagination.pageSize = this.pages
  216. // 增加默认排序
  217. const defaultSorters = this.columns
  218. .filter((col) => col.defaultSortOrder)
  219. .map((col) => ({
  220. field: col.dataIndex,
  221. order: col.defaultSortOrder,
  222. }))
  223. // 排序方法
  224. if (defaultSorters.length > 0) {
  225. this.sorter = { ...defaultSorters[0] }
  226. this.sorterFun(defaultSorters[0], true)
  227. }
  228. },
  229. methods: {
  230. // 排序点击之后,重新排序
  231. onChange(pagination, filters, sorter) {
  232. this.sorter = { ...sorter }
  233. this.sorterFun(this.sorter)
  234. },
  235. // 排序方法
  236. sorterFun(sorts, isDefault) {
  237. if (!sorts) {
  238. // 如果没有sorts,说明是父组件调用,则增加默认值
  239. Object.assign(this.defaultValue, this.value)
  240. sorts = this.sorter
  241. }
  242. // 没有排序,则使用默认排序
  243. if (!sorts?.order) {
  244. while (this.value.length > 0) {
  245. this.value.splice(0, 1)
  246. }
  247. this.defaultValue.forEach((item) => {
  248. this.value.push(item)
  249. })
  250. return
  251. }
  252. const sortValue = this.value.sort((a, b) => {
  253. if (sorts.order === 'ascend') {
  254. // 升序
  255. if (a[sorts.field] + '' < b[sorts.field] + '') {
  256. return -1
  257. }
  258. if (a[sorts.field] + '' === b[sorts.field] + '') {
  259. return 0
  260. }
  261. if (a[sorts.field] + '' > b[sorts.field] + '') {
  262. return 1
  263. }
  264. } else {
  265. // 降序
  266. if (a[sorts.field] + '' < b[sorts.field] + '') {
  267. return 1
  268. }
  269. if (a[sorts.field] + '' === b[sorts.field] + '') {
  270. return 0
  271. }
  272. if (a[sorts.field] + '' > b[sorts.field] + '') {
  273. return -1
  274. }
  275. }
  276. })
  277. this.$set(this, 'value', sortValue)
  278. },
  279. add() {
  280. // 发布选择事件,外部组件完成逻辑
  281. this.$emit('add')
  282. },
  283. select() {
  284. // 发布新增事件,外部组件完成逻辑
  285. this.$emit('select')
  286. },
  287. edit(index) {
  288. // 没有功能
  289. },
  290. remove(keys) {
  291. // 用的序号作key,从大往小删,防止串了
  292. const removeKeys = keys.sort((a, b) => b - a)
  293. const valueid = []
  294. removeKeys.forEach((key) => {
  295. valueid.push(this.value[key].id)
  296. this.value.splice(key, 1)
  297. })
  298. this.selectedRowKeys = []
  299. this.$emit('change', this.value)
  300. this.deletedIdentify(valueid, this.type)
  301. },
  302. },
  303. }
  304. </script>
  305. <style module lang="scss">
  306. @use '@/common/design' as *;
  307. .header {
  308. position: absolute;
  309. top: 0;
  310. right: 0;
  311. :global .ant-input-search {
  312. width: 200px;
  313. }
  314. :global .ant-btn {
  315. margin: 5px;
  316. }
  317. }
  318. .caption {
  319. // position: relative;
  320. position: absolute;
  321. top: -5px;
  322. width: 100%;
  323. min-height: 40px;
  324. margin: 3px 0;
  325. text-align: center;
  326. }
  327. .wrapper {
  328. :global(.ant-table-tbody) {
  329. .clickable-cell {
  330. color: $primary-color;
  331. cursor: pointer;
  332. &:hover {
  333. color: $primary-5;
  334. }
  335. &:active {
  336. color: $primary-7;
  337. }
  338. }
  339. }
  340. }
  341. </style>