index.vue 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. <template>
  2. <div class="select-table">
  3. <div class="select-table-box">
  4. <page-layout-list class="dialog-table">
  5. <template #filter v-if="searchFieldList.length > 0">
  6. <cip-search-form v-model:model="searchFilter" :field-list="searchFieldList" @search="handleSearch"></cip-search-form>
  7. </template>
  8. <cip-table v-if="checkType === 'radio'"
  9. :data="itemList"
  10. :columns="tableColumns"
  11. :offset="offset"
  12. ref="tableRef"
  13. size="small"
  14. :select-type="checkType"
  15. :select-radio="selectRadio"
  16. :select-label="optionProps.value"
  17. @current-change="currentChange"
  18. v-loading="listLoading">
  19. </cip-table>
  20. <cip-table v-if="checkType === 'checkbox'"
  21. :data="itemList"
  22. :columns="tableColumns"
  23. :offset="offset"
  24. ref="tableRef"
  25. size="small"
  26. :select-type="checkType"
  27. @select="onSelect"
  28. @select-all="onSelectAll"
  29. :selectable="selectable"
  30. v-loading="listLoading">
  31. </cip-table>
  32. <template #pagination v-if="withPagination">
  33. <cip-pagination v-model:offset="offset"
  34. v-model:limit="limit"
  35. :total="total"
  36. :current-page="currentPage"
  37. @refresh="getItemList"></cip-pagination>
  38. </template>
  39. </page-layout-list>
  40. <slot name="group"></slot>
  41. <tags v-if="!$slots.group && withTags" class="dialog-tags" :options="checkOptions" :keyProp="optionProps" @update:options="changeOptions"></tags>
  42. </div>
  43. </div>
  44. </template>
  45. <script>
  46. import { useCurd } from '@cip/hooks/use-curd'
  47. import { useTableCacheSelect } from '@cip/components/hooks/table-cache-select'
  48. import { ref, computed, nextTick, watch, watchEffect } from 'vue'
  49. import { ElLoading } from 'element-plus'
  50. import PageLayoutList from '@cip/components/page-layout/list'
  51. import CipSearchForm from '@cip/components/cip-search-form'
  52. import CipTable from '@cip/components/cip-table'
  53. import CipPagination from '@cip/components/cip-pagination'
  54. import { useFormInput, useOptions } from '@cip/components/hooks/form-input'
  55. import { formInputProps } from '../../form-input-props'
  56. import Tags from './tags'
  57. export default {
  58. components: { Tags, PageLayoutList, CipSearchForm, CipTable, CipPagination },
  59. directives: {
  60. loading: ElLoading.directive
  61. },
  62. props: formInputProps,
  63. emits: ['update:modelValue'],
  64. setup (props, context) {
  65. const { emitInput, ...formInput } = useFormInput(props, context)
  66. const { optionProps } = useOptions(props, false, formInput.emitInput)
  67. const checkOptions = computed(() => {
  68. return cacheSelectedList.value.length === 0 ? props.modelValue : cacheSelectedList.value
  69. })
  70. // 类型
  71. const checkType = computed(() => {
  72. return props.config?.checkType ?? 'radio'
  73. })
  74. // 列表头
  75. const tableColumns = computed(() => {
  76. return props.config?.tableColumns ?? []
  77. })
  78. // 搜索头
  79. const searchFieldList = computed(() => {
  80. return props.config?.searchFieldList ?? []
  81. })
  82. // 是否显示分页
  83. const withPagination = computed(() => {
  84. return props.config?.withPagination ?? true
  85. })
  86. // 是否显示选中tag
  87. const withTags = computed(() => {
  88. return props.config?.withTags ?? true
  89. })
  90. // 表格行是否可选,这里整个表格行为一致, selectable为function
  91. const selectable = computed(() => {
  92. return props.config?.selectable ?? (() => true)
  93. })
  94. // 右侧数据改变
  95. const changeOptions = (item) => {
  96. cacheSelectedList.value = item
  97. emitInput(item)
  98. handleSelectShow()
  99. }
  100. const tableRef = ref()
  101. const CURD = useCurd(props.config.entity, { ...props.config.curdFn, itemType: props.config.itemType })
  102. const { itemList, getItemList, searchFilter, search } = CURD
  103. watch(() => props.config?.defaultSearchFilter, val => {
  104. getTableList(val)
  105. })
  106. // 外层触发请求
  107. const getTableList = (item = {}) => {
  108. searchFilter.value = { ...props.config.defaultSearchFilter, ...searchFilter.value, ...item }
  109. getItemList()
  110. }
  111. getTableList()
  112. const { cacheSelectedList, onSelect, onSelectAll } = useTableCacheSelect(itemList, optionProps.value.value, val => {
  113. emitInput(val)
  114. })
  115. // 已选择的radio
  116. const selectRadio = computed(() => {
  117. if (props.modelValue && props.modelValue[optionProps.value.value]) {
  118. return props.modelValue[optionProps.value.value]
  119. }
  120. return radioCache.value
  121. })
  122. // radio类型时的缓存
  123. const radioCache = computed(() => {
  124. const cache = itemList.value?.find(v => v[optionProps.value.value] === props.modelValue)
  125. return cache ? cache[optionProps.value.value] : undefined
  126. })
  127. const currentChange = (currentRow, oldCurrentRow) => {
  128. // 单选不能取消,只能有值时才填入
  129. if (currentRow) {
  130. emitInput(currentRow[optionProps.value.value])
  131. }
  132. }
  133. // checkbox类型更新选中视图
  134. const showSelectedView = (rows, select) => {
  135. nextTick(() => {
  136. rows.forEach(row => {
  137. tableRef.value.cipTableRef.value.toggleRowSelection(row, select)
  138. })
  139. })
  140. }
  141. // tag组件传入值需要更新table选中视图
  142. const handleSelectShow = () => {
  143. const selectedPropsCode = cacheSelectedList.value.map(button => button[optionProps.value.value])
  144. const rows = itemList.value.filter(item => {
  145. return !selectedPropsCode.includes(item[optionProps.value.value])
  146. })
  147. showSelectedView(rows, false)
  148. }
  149. if (checkType.value === 'checkbox') {
  150. // 分页切换时缓存数据处理
  151. watch(() => [itemList.value, props.modelValue], list => {
  152. cacheHandle()
  153. })
  154. } else {
  155. const unWatch = watchEffect(() => {
  156. if (props.modelValue && props.modelValue[optionProps.value.value]) {
  157. const checkItem = itemList.value.filter(item => item[optionProps.value.value] === props.modelValue[optionProps.value.value])[0]
  158. if (checkItem) {
  159. emitInput(checkItem)
  160. unWatch()
  161. }
  162. }
  163. })
  164. }
  165. // 缓存数据处理
  166. const cacheHandle = () => {
  167. if (cacheSelectedList.value.length === 0) {
  168. cacheSelectedList.value = props.modelValue ?? []
  169. }
  170. const cacheSelectButtonCode = cacheSelectedList.value.map(button => button[optionProps.value.value])
  171. const rows = itemList.value.filter(item => {
  172. const selectList = props.modelValue || (cacheSelectButtonCode.includes(item[optionProps.value.value]) ? cacheSelectButtonCode : [])
  173. return selectList.findIndex(v => v[optionProps.value.value] === item[optionProps.value.value]) !== -1
  174. })
  175. showSelectedView(rows, true)
  176. }
  177. // 搜索
  178. const handleSearch = () => {
  179. search()
  180. }
  181. return {
  182. changeOptions,
  183. checkOptions,
  184. getTableList,
  185. handleSearch,
  186. optionProps,
  187. checkType,
  188. tableColumns,
  189. searchFieldList,
  190. withPagination,
  191. withTags,
  192. ...CURD,
  193. tableRef,
  194. selectable,
  195. selectRadio,
  196. currentChange,
  197. onSelect,
  198. onSelectAll,
  199. cacheSelectedList
  200. }
  201. }
  202. }
  203. </script>
  204. <style lang="less" scoped>
  205. .select-table{
  206. flex: 1;
  207. .select-table-box{
  208. display: flex;
  209. }
  210. .dialog-table{
  211. flex: 1;
  212. margin: 0 15px 15px 0;
  213. padding: 0;
  214. }
  215. .dialog-tags{
  216. padding: 8px 0;
  217. flex-basis: 220px;
  218. }
  219. }
  220. </style>