user-select.vue 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. <template>
  2. <el-dialog v-model="state.showDialog" destroy-on-close :title="title" append-to-body draggable width="780px">
  3. <div style="padding: 0px 0px 8px 8px; background-color: var(--ba-bg-color)">
  4. <el-row :gutter="8" style="width: 100%">
  5. <el-col :xs="24" :sm="9">
  6. <div class="my-flex-column h100">
  7. <org-menu @node-click="onOrgNodeClick" class="my-flex-fill"></org-menu>
  8. </div>
  9. </el-col>
  10. <el-col :xs="24" :sm="15">
  11. <el-card shadow="never" :body-style="{ paddingBottom: '0' }" style="margin-top: 8px">
  12. <el-form :model="state.filterModel" :inline="true" @submit.stop.prevent>
  13. <el-form-item label="姓名" prop="name">
  14. <el-input v-model="state.filterModel.name" placeholder="姓名" @keyup.enter="onQuery" />
  15. </el-form-item>
  16. <el-form-item>
  17. <el-button type="primary" icon="ele-Search" @click="onQuery"> 查询 </el-button>
  18. </el-form-item>
  19. </el-form>
  20. </el-card>
  21. <el-card shadow="never" style="margin-top: 8px">
  22. <el-table
  23. ref="userTableRef"
  24. :data="state.userListData"
  25. style="width: 100%"
  26. v-loading="state.loading"
  27. row-key="id"
  28. default-expand-all
  29. :tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
  30. :highlight-current-row="!multiple"
  31. @row-click="onRowClick"
  32. @row-dblclick="onRowDbClick"
  33. >
  34. <el-table-column v-if="multiple" type="selection" width="55" />
  35. <el-table-column prop="name" label="姓名" min-width="80" show-overflow-tooltip />
  36. <el-table-column prop="mobile" label="手机号" min-width="120" show-overflow-tooltip />
  37. <!-- <el-table-column prop="email" label="邮箱" min-width="120" show-overflow-tooltip /> -->
  38. </el-table>
  39. <div class="my-flex my-flex-end" style="margin-top: 20px">
  40. <el-pagination
  41. v-model:currentPage="state.pageInput.currentPage"
  42. v-model:page-size="state.pageInput.pageSize"
  43. :total="state.total"
  44. :page-sizes="[10, 20, 50, 100]"
  45. small
  46. background
  47. @size-change="onSizeChange"
  48. @current-change="onCurrentChange"
  49. layout="total, sizes, prev, pager, next"
  50. />
  51. </div>
  52. </el-card>
  53. </el-col>
  54. </el-row>
  55. </div>
  56. <template #footer>
  57. <span class="dialog-footer">
  58. <el-button @click="onCancel" size="default">取 消</el-button>
  59. <el-button type="primary" @click="onSure" size="default" :loading="sureLoading">确 定</el-button>
  60. </span>
  61. </template>
  62. </el-dialog>
  63. </template>
  64. <script lang="ts" setup name="admin/user/components/user-select">
  65. import { ref, reactive, defineAsyncComponent } from 'vue'
  66. import { ElTable } from 'element-plus'
  67. import { UserGetPageOutput, PageInputUserGetPageDto, OrgListOutput } from '/@/api/admin/data-contracts'
  68. import { UserApi } from '/@/api/admin/User'
  69. // 引入组件
  70. const OrgMenu = defineAsyncComponent(() => import('/@/views/admin/org/components/org-menu.vue'))
  71. const props = defineProps({
  72. title: {
  73. type: String,
  74. default: '',
  75. },
  76. multiple: {
  77. type: Boolean,
  78. default: false,
  79. },
  80. sureLoading: {
  81. type: Boolean,
  82. default: false,
  83. },
  84. })
  85. const emits = defineEmits(['sure'])
  86. const userTableRef = ref<InstanceType<typeof ElTable>>()
  87. const state = reactive({
  88. showDialog: false,
  89. loading: false,
  90. filterModel: {
  91. name: '',
  92. },
  93. total: 0,
  94. pageInput: {
  95. currentPage: 1,
  96. pageSize: 20,
  97. filter: {
  98. orgId: null,
  99. },
  100. } as PageInputUserGetPageDto,
  101. userListData: [] as Array<UserGetPageOutput>,
  102. })
  103. // 打开对话框
  104. const open = () => {
  105. state.showDialog = true
  106. if (state.pageInput.filter) {
  107. state.pageInput.filter.orgId = null
  108. }
  109. onQuery()
  110. }
  111. // 关闭对话框
  112. const close = () => {
  113. state.showDialog = false
  114. }
  115. const onQuery = async () => {
  116. state.loading = true
  117. const res = await new UserApi().getPage(state.pageInput).catch(() => {
  118. state.loading = false
  119. })
  120. state.userListData = res?.data?.list ?? []
  121. state.total = res?.data?.total ?? 0
  122. state.loading = false
  123. }
  124. const onSizeChange = (val: number) => {
  125. state.pageInput.pageSize = val
  126. onQuery()
  127. }
  128. const onCurrentChange = (val: number) => {
  129. state.pageInput.currentPage = val
  130. onQuery()
  131. }
  132. const onOrgNodeClick = (node: OrgListOutput | null) => {
  133. if (state.pageInput.filter) {
  134. state.pageInput.filter.orgId = node?.id
  135. }
  136. onQuery()
  137. }
  138. const onRowClick = (row: UserGetPageOutput) => {
  139. // TODO: improvement typing when refactor table
  140. // eslint-disable-next-line @typescript-eslint/ban-ts-comment
  141. // @ts-expect-error
  142. userTableRef.value!.toggleRowSelection(row, props.multiple ? undefined : true)
  143. }
  144. const onRowDbClick = () => {
  145. if (!props.multiple) {
  146. onSure()
  147. }
  148. }
  149. // 取消
  150. const onCancel = () => {
  151. state.showDialog = false
  152. }
  153. // 确定
  154. const onSure = () => {
  155. const selectionRows = userTableRef.value!.getSelectionRows() as UserGetPageOutput[]
  156. emits('sure', props.multiple ? selectionRows : selectionRows.length > 0 ? selectionRows[0] : null)
  157. }
  158. defineExpose({
  159. open,
  160. close,
  161. })
  162. </script>
  163. <style scoped lang="scss">
  164. :deep(.el-dialog__body) {
  165. padding: 5px 10px;
  166. }
  167. </style>