index.vue 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. <template>
  2. <el-select popper-class="popperClass" class="tableSelector" :multiple="props.tableConfig.isMultiple"
  3. @remove-tag="removeTag" v-model="data" placeholder="请选择" @visible-change="visibleChange">
  4. <template #empty>
  5. <div class="option">
  6. <el-input style="margin-bottom: 10px" v-model="search" clearable placeholder="请输入关键词" @change="getDict"
  7. @clear="getDict">
  8. <template #append>
  9. <el-button type="primary" icon="Search"/>
  10. </template>
  11. </el-input>
  12. <el-table
  13. ref="tableRef"
  14. :data="tableData"
  15. size="mini"
  16. border
  17. row-key="id"
  18. style="width: 400px"
  19. max-height="200"
  20. height="200"
  21. :highlight-current-row="!props.tableConfig.isMultiple"
  22. @selection-change="handleSelectionChange"
  23. @current-change="handleCurrentChange"
  24. >
  25. <el-table-column v-if="props.tableConfig.isMultiple" fixed type="selection" width="55"/>
  26. <el-table-column fixed type="index" label="#" width="50"/>
  27. <el-table-column :prop="item.prop" :label="item.label" :width="item.width"
  28. v-for="(item,index) in props.tableConfig.columns" :key="index"/>
  29. </el-table>
  30. <el-pagination style="margin-top: 10px" background
  31. v-model:current-page="pageConfig.page"
  32. v-model:page-size="pageConfig.limit"
  33. layout="prev, pager, next"
  34. :total="pageConfig.total"
  35. @current-change="handlePageChange"
  36. />
  37. </div>
  38. </template>
  39. </el-select>
  40. </template>
  41. <script setup lang="ts">
  42. import {defineProps, onMounted, reactive, ref, toRaw, watch} from 'vue'
  43. import {dict} from '@fast-crud/fast-crud'
  44. import XEUtils from 'xe-utils'
  45. import {request} from '/@/utils/service'
  46. const props = defineProps({
  47. modelValue: {},
  48. tableConfig: {
  49. url: null,
  50. label: null, //显示值
  51. value: null, //数据值
  52. isTree: false,
  53. data: [],//默认数据
  54. isMultiple: false, //是否多选
  55. columns: [], //每一项对应的列表项
  56. },
  57. displayLabel: {}
  58. } as any)
  59. const emit = defineEmits(['update:modelValue'])
  60. // tableRef
  61. const tableRef = ref()
  62. // template上使用data
  63. const data = ref()
  64. // 多选值
  65. const multipleSelection = ref()
  66. watch(multipleSelection, // 监听multipleSelection的变化,
  67. (value) => {
  68. const {tableConfig} = props
  69. //是否多选
  70. if (!tableConfig.isMultiple) {
  71. data.value = value ? value[tableConfig.label] : null
  72. } else {
  73. const result = value ? value.map((item: any) => {
  74. return item[tableConfig.label]
  75. }) : null
  76. data.value = result
  77. }
  78. }, // 当multipleSelection值触发后,同步修改data.value的值
  79. {immediate: true} // 立即触发一次,给data赋值初始值
  80. )
  81. // 搜索值
  82. const search = ref(undefined)
  83. //表格数据
  84. const tableData = ref()
  85. // 分页的配置
  86. const pageConfig = reactive({
  87. page: 1,
  88. limit: 10,
  89. total: 0
  90. })
  91. /**
  92. * 表格多选
  93. * @param val:Array
  94. */
  95. const handleSelectionChange = (val: any) => {
  96. multipleSelection.value = val
  97. const {tableConfig} = props
  98. const result = val.map((item: any) => {
  99. return item[tableConfig.value]
  100. })
  101. emit('update:modelValue', result)
  102. }
  103. /**
  104. * 表格单选
  105. * @param val:Object
  106. */
  107. const handleCurrentChange = (val: any) => {
  108. multipleSelection.value = val
  109. const {tableConfig} = props
  110. emit('update:modelValue', val[tableConfig.value])
  111. }
  112. /**
  113. * 获取字典值
  114. */
  115. const getDict = async () => {
  116. const url = props.tableConfig.url
  117. const params = {
  118. page: pageConfig.page,
  119. limit: pageConfig.limit,
  120. search: search.value
  121. }
  122. const {data, page, limit, total} = await request({
  123. url:url,
  124. params:params
  125. })
  126. pageConfig.page = page
  127. pageConfig.limit = limit
  128. pageConfig.total = total
  129. if (props.tableConfig.data === undefined || props.tableConfig.data.length === 0) {
  130. if (props.tableConfig.isTree) {
  131. tableData.value = XEUtils.toArrayTree(data, {parentKey: 'parent', key: 'id', children: 'children'})
  132. } else {
  133. tableData.value = data
  134. }
  135. } else {
  136. tableData.value = props.tableConfig.data
  137. }
  138. }
  139. /**
  140. * 下拉框展开/关闭
  141. * @param bool
  142. */
  143. const visibleChange = (bool: any) => {
  144. if (bool) {
  145. getDict()
  146. }
  147. }
  148. /**
  149. * 分页
  150. * @param page
  151. */
  152. const handlePageChange = (page: any) => {
  153. pageConfig.page = page
  154. getDict()
  155. }
  156. // 监听displayLabel的变化,更新数据
  157. watch(() => {
  158. return props.displayLabel
  159. }, (value) => {
  160. const {tableConfig} = props
  161. const result = value ? value.map((item: any) => {
  162. return item[tableConfig.label]
  163. }) : null
  164. data.value = result
  165. }, {immediate: true})
  166. </script>
  167. <style scoped>
  168. .option {
  169. height: auto;
  170. line-height: 1;
  171. padding: 5px;
  172. background-color: #fff;
  173. }
  174. </style>
  175. <style lang="scss">
  176. .popperClass {
  177. height: 320px;
  178. }
  179. .el-select-dropdown__wrap {
  180. max-height: 310px !important;
  181. }
  182. .tableSelector {
  183. .el-icon, .el-tag__close {
  184. display: none;
  185. }
  186. }
  187. </style>