index.vue 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. <!--
  2. * @Descripttion: 表格选择器组件
  3. * @version: 1.3
  4. * @Author: sakuya
  5. * @Date: 2021年6月10日10:04:07
  6. * @LastEditors: sakuya
  7. * @LastEditTime: 2022年6月6日21:50:36
  8. -->
  9. <template>
  10. <el-select ref="select" v-model="defaultValue" :size="size" :clearable="clearable" :multiple="multiple" :collapse-tags="collapseTags" :collapse-tags-tooltip="collapseTagsTooltip" :placeholder="placeholder" :disabled="disabled" :placement="placement" @remove-tag="removeTag" @visible-change="visibleChange" @clear="clear">
  11. <template #empty>
  12. <div class="sc-table-select__table" :style="{ width: tableWidth + 'px' }" v-loading="loading">
  13. <div class="sc-table-select__header">
  14. <slot name="header" :queryForm="formData" :submit="formSubmit"></slot>
  15. </div>
  16. <el-table :class="!multiple && highlightCurrent && 'table-row-cursor'" ref="table" :data="tableData" :height="245" :highlight-current-row="!multiple && highlightCurrent" @row-click="click" @select="select" @select-all="selectAll">
  17. <el-table-column v-if="multiple" type="selection" width="45"></el-table-column>
  18. <el-table-column v-else type="index" width="60">
  19. <template #default="scope"><span>{{ scope.$index + (currentPage - 1) * pageSize + 1 }}</span></template>
  20. </el-table-column>
  21. <slot></slot>
  22. </el-table>
  23. <div v-if="!hidePagination" class="sc-table-select__page">
  24. <el-pagination small background :layout="paginationLayout" :total="total" :page-size="pageSize" :page-sizes="pageSizes" v-model:currentPage="currentPage" @current-change="getData" @update:page-size="pageSizeChange"></el-pagination>
  25. </div>
  26. </div>
  27. </template>
  28. </el-select>
  29. </template>
  30. <script>
  31. import config from "@/config/tableSelect";
  32. export default {
  33. props: {
  34. modelValue: null,
  35. apiObj: { type: Object, default: () => {} },
  36. apiKey: { type: String, default: "get" },
  37. params: { type: Object, default: () => {} },
  38. filters: { type: Object, default: () => {} },
  39. placeholder: { type: String, default: "请选择" },
  40. size: { type: String, default: "default" },
  41. clearable: { type: Boolean, default: false },
  42. multiple: { type: Boolean, default: false },
  43. collapseTags: { type: Boolean, default: false },
  44. collapseTagsTooltip: { type: Boolean, default: false },
  45. disabled: { type: Boolean, default: false },
  46. placement: { type: String, default: "bottom-start" },
  47. tableWidth: { type: Number, default: 400},
  48. props: { type: Object, default: () => {} },
  49. highlightCurrent: { type: Boolean, default: true },
  50. hidePagination: { type: Boolean, default: false },
  51. pageSizes: { type: Array, default: () => config.pageSizes },
  52. paginationLayout: { type: String, default: config.paginationLayout },
  53. applySql: { type: Boolean, default: false }
  54. },
  55. data() {
  56. return {
  57. loading: false,
  58. defaultValue: [],
  59. tableData: [],
  60. allTableData: [],
  61. pageSize: config.pageSize,
  62. total: 0,
  63. currentPage: 1,
  64. defaultProps: {
  65. label: config.props.label,
  66. value: config.props.value,
  67. page: config.request.page,
  68. pageSize: config.request.pageSize
  69. },
  70. formData: {}
  71. }
  72. },
  73. watch: {
  74. modelValue: {
  75. deep: true,
  76. handler() {
  77. this.defaultValue = this.modelValue
  78. this.autoCurrentLabel()
  79. }
  80. },
  81. apiKey() {
  82. this.getData()
  83. }
  84. },
  85. mounted() {
  86. this.defaultProps = Object.assign(this.defaultProps, this.props);
  87. this.defaultValue = this.modelValue;
  88. this.autoCurrentLabel();
  89. },
  90. methods: {
  91. //表格显示隐藏回调
  92. visibleChange(visible) {
  93. if (visible) {
  94. this.currentPage = 1
  95. this.formData = {}
  96. this.getData()
  97. } else {
  98. this.autoCurrentLabel()
  99. this.$emit("resetFilter");
  100. }
  101. },
  102. //获取表格数据
  103. async getData() {
  104. try {
  105. this.loading = true;
  106. const reqData = {
  107. [this.defaultProps.page]: this.defaultProps.page == "page" ? this.currentPage - 1 : this.currentPage,
  108. [this.defaultProps.pageSize]: this.pageSize
  109. }
  110. if (this.hidePagination) {
  111. delete reqData[this.defaultProps.page]
  112. delete reqData[this.defaultProps.pageSize]
  113. }
  114. if (this.applySql && this.$TOOL.data.get("APPLY_SQL")) reqData["applySql"] = this.$TOOL.data.get("APPLY_SQL");
  115. Object.assign(reqData, this.params, this.formData)
  116. const res = await this.apiObj[this.apiKey](reqData);
  117. const parseData = config.parseData(res);
  118. this.tableData = parseData.data || [];
  119. if (this.hidePagination) {
  120. this.allTableData = parseData.data || [];
  121. this.formFilter();
  122. }
  123. this.total = parseInt(parseData.total) || 0;
  124. this.loading = false;
  125. //表格默认赋值
  126. if (this.defaultValue) {
  127. this.$nextTick(() => {
  128. if (this.multiple) {
  129. this.defaultValue.forEach(row => {
  130. var setrow = this.tableData.filter(item => item[this.defaultProps.value] === row[this.defaultProps.value] )
  131. if (setrow.length > 0) {
  132. this.$refs.table.toggleRowSelection(setrow[0], true);
  133. }
  134. })
  135. } else {
  136. var setrow = this.tableData.filter(item => item[this.defaultProps.value] === this.defaultValue[this.defaultProps.value] )
  137. this.$refs.table.setCurrentRow(setrow[0]);
  138. }
  139. this.$refs.table.setScrollTop(0)
  140. })
  141. }
  142. } catch (error) {
  143. this.loading = false;
  144. }
  145. },
  146. //插糟表单提交
  147. formSubmit() {
  148. this.currentPage = 1
  149. this.getData()
  150. },
  151. //插糟表单筛选
  152. formFilter() {
  153. let array = this.allTableData.slice();
  154. for (const key in this.filters) {
  155. if (this.filters[key]) array = array.filter(a => a[key] && a[key].includes(this.filters[key]));
  156. }
  157. this.tableData = array.slice();
  158. },
  159. //条数变化
  160. pageSizeChange(size) {
  161. this.pageSize = size
  162. this.getData()
  163. },
  164. autoCurrentLabel() {
  165. this.$nextTick(() => {
  166. if (this.multiple) {
  167. this.$refs.select.states.selected.forEach(item => item.currentLabel = item.value[this.defaultProps.label])
  168. } else {
  169. if (this.defaultValue) this.$refs.select.states.selectedLabel = this.defaultValue[this.defaultProps.label]
  170. }
  171. })
  172. },
  173. //表格勾选事件
  174. select(rows, row) {
  175. var isSelect = rows.length && rows.indexOf(row) !== -1
  176. if (isSelect) {
  177. this.defaultValue.push(row)
  178. } else {
  179. this.defaultValue.splice(this.defaultValue.findIndex(item => item[this.defaultProps.value] == row[this.defaultProps.value]), 1)
  180. }
  181. this.autoCurrentLabel()
  182. this.$emit("update:modelValue", this.defaultValue);
  183. this.$emit("change", this.defaultValue);
  184. },
  185. //表格全选事件
  186. selectAll(rows) {
  187. var isAllSelect = rows.length > 0
  188. if (isAllSelect) {
  189. rows.forEach(row => {
  190. var isHas = this.defaultValue.find(item => item[this.defaultProps.value] == row[this.defaultProps.value])
  191. if(!isHas){
  192. this.defaultValue.push(row)
  193. }
  194. })
  195. } else {
  196. this.tableData.forEach(row => {
  197. var isHas = this.defaultValue.find(item => item[this.defaultProps.value] == row[this.defaultProps.value])
  198. if(isHas){
  199. this.defaultValue.splice(this.defaultValue.findIndex(item => item[this.defaultProps.value] == row[this.defaultProps.value]), 1)
  200. }
  201. })
  202. }
  203. this.autoCurrentLabel()
  204. this.$emit("update:modelValue", this.defaultValue);
  205. this.$emit("change", this.defaultValue);
  206. },
  207. click(row) {
  208. if (this.highlightCurrent) {
  209. if (this.multiple) {
  210. //处理多选点击行
  211. } else{
  212. this.defaultValue = row;
  213. this.$refs.select.blur();
  214. this.autoCurrentLabel();
  215. this.$emit("update:modelValue", this.defaultValue);
  216. this.$emit("change", this.defaultValue);
  217. }
  218. }
  219. },
  220. //tags删除后回调
  221. removeTag(tag){
  222. var row = this.findRowByKey(tag[this.defaultProps.value])
  223. this.$refs.table.toggleRowSelection(row, false);
  224. this.$emit("update:modelValue", this.defaultValue);
  225. },
  226. //清空后的回调
  227. clear(){
  228. this.$emit("update:modelValue", this.defaultValue);
  229. },
  230. // 关键值查询表格数据行
  231. findRowByKey (value) {
  232. return this.tableData.find(item => item[this.defaultProps.value] === value)
  233. },
  234. // 触发select隐藏
  235. blur(){
  236. this.$refs.select.blur();
  237. },
  238. // 触发select显示
  239. focus(){
  240. this.$refs.select.focus();
  241. }
  242. }
  243. }
  244. </script>
  245. <style scoped>
  246. .sc-table-select__table {
  247. min-width: 100%;
  248. padding: 5px 12px;
  249. }
  250. .sc-table-select__page {
  251. padding-top: 12px;
  252. }
  253. .sc-table-select__header :deep(.el-form) .el-form-item {
  254. margin-right: 20px;
  255. }
  256. .table-row-cursor :deep(.el-table__row) {
  257. cursor: pointer;
  258. }
  259. </style>