index.vue 8.2 KB

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