index.vue 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  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. const props = defineProps({
  46. modelValue: {},
  47. tableConfig: {
  48. url: null,
  49. label: null, //显示值
  50. value: null, //数据值
  51. isTree: false,
  52. data: [],//默认数据
  53. isMultiple: false, //是否多选
  54. columns: [], //每一项对应的列表项
  55. },
  56. displayLabel: {}
  57. } as any)
  58. const emit = defineEmits(['update:modelValue'])
  59. // tableRef
  60. const tableRef = ref()
  61. // template上使用data
  62. const data = ref()
  63. // 多选值
  64. const multipleSelection = ref()
  65. watch(multipleSelection, // 监听multipleSelection的变化,
  66. (value) => {
  67. const {tableConfig} = props
  68. //是否多选
  69. if (!tableConfig.isMultiple) {
  70. data.value = value ? value[tableConfig.label] : null
  71. } else {
  72. const result = value ? value.map((item: any) => {
  73. return item[tableConfig.label]
  74. }) : null
  75. data.value = result
  76. }
  77. }, // 当multipleSelection值触发后,同步修改data.value的值
  78. {immediate: true} // 立即触发一次,给data赋值初始值
  79. )
  80. // 搜索值
  81. const search = ref(undefined)
  82. //表格数据
  83. const tableData = ref()
  84. // 分页的配置
  85. const pageConfig = reactive({
  86. page: 1,
  87. limit: 10,
  88. total: 0
  89. })
  90. /**
  91. * 表格多选
  92. * @param val:Array
  93. */
  94. const handleSelectionChange = (val: any) => {
  95. multipleSelection.value = val
  96. const {tableConfig} = props
  97. const result = val.map((item: any) => {
  98. return item[tableConfig.value]
  99. })
  100. emit('update:modelValue', result)
  101. }
  102. /**
  103. * 表格单选
  104. * @param val:Object
  105. */
  106. const handleCurrentChange = (val: any) => {
  107. multipleSelection.value = val
  108. const {tableConfig} = props
  109. emit('update:modelValue', val[tableConfig.value])
  110. }
  111. /**
  112. * 获取字典值
  113. */
  114. const getDict = async () => {
  115. const url = props.tableConfig.url
  116. const params = {
  117. page: pageConfig.page,
  118. limit: pageConfig.limit,
  119. search: search
  120. }
  121. const dicts = dict({url: url, params: params})
  122. await dicts.reloadDict()
  123. const dictData: any = dicts.data
  124. const {data, page, limit, total} = dictData
  125. pageConfig.page = page
  126. pageConfig.limit = limit
  127. pageConfig.total = total
  128. if (props.tableConfig.data === undefined || props.tableConfig.data.length === 0) {
  129. if (props.tableConfig.isTree) {
  130. tableData.value = XEUtils.toArrayTree(data, {parentKey: 'parent', key: 'id', children: 'children'})
  131. } else {
  132. tableData.value = data
  133. }
  134. } else {
  135. tableData.value = props.tableConfig.data
  136. }
  137. }
  138. /**
  139. * 下拉框展开/关闭
  140. * @param bool
  141. */
  142. const visibleChange = (bool: any) => {
  143. if (bool) {
  144. getDict()
  145. }
  146. }
  147. /**
  148. * 分页
  149. * @param page
  150. */
  151. const handlePageChange = (page: any) => {
  152. pageConfig.page = page
  153. getDict()
  154. }
  155. // 监听displayLabel的变化,更新数据
  156. watch(() => {
  157. return props.displayLabel
  158. }, (value) => {
  159. const {tableConfig} = props
  160. const result = value ? value.map((item: any) => {
  161. return item[tableConfig.label]
  162. }) : null
  163. data.value = result
  164. }, {immediate: true})
  165. </script>
  166. <style scoped>
  167. .option {
  168. height: auto;
  169. line-height: 1;
  170. padding: 5px;
  171. background-color: #fff;
  172. }
  173. </style>
  174. <style lang="scss">
  175. .popperClass {
  176. height: 320px;
  177. }
  178. .el-select-dropdown__wrap {
  179. max-height: 310px !important;
  180. }
  181. .tableSelector {
  182. .el-icon, .el-tag__close {
  183. display: none;
  184. }
  185. }
  186. </style>