From a1d7e81859f554f3a53680cc35f0f49bf1f77098 Mon Sep 17 00:00:00 2001
From: wwf <1971391498@qq.com>
Date: 星期四, 14 五月 2026 14:37:02 +0800
Subject: [PATCH] 导入项目

---
 src/components/UserSelectForm/index.vue |  171 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 171 insertions(+), 0 deletions(-)

diff --git a/src/components/UserSelectForm/index.vue b/src/components/UserSelectForm/index.vue
new file mode 100644
index 0000000..5ed99f8
--- /dev/null
+++ b/src/components/UserSelectForm/index.vue
@@ -0,0 +1,171 @@
+<template>
+  <Dialog v-model="dialogVisible" title="浜哄憳閫夋嫨" width="800">
+    <el-row class="gap2" v-loading="formLoading">
+      <el-col :span="6">
+        <ContentWrap class="h-1/1">
+          <el-tree
+            ref="treeRef"
+            :data="deptTree"
+            :expand-on-click-node="false"
+            :props="defaultProps"
+            default-expand-all
+            highlight-current
+            node-key="id"
+            @node-click="handleNodeClick"
+          />
+        </ContentWrap>
+      </el-col>
+      <el-col :span="17">
+        <el-transfer
+          v-model="selectedUserIdList"
+          :titles="['鏈��', '宸查��']"
+          filterable
+          filter-placeholder="鎼滅储鎴愬憳"
+          :data="transferUserList"
+          :props="{ label: 'nickname', key: 'id' }"
+        />
+      </el-col>
+    </el-row>
+    <template #footer>
+      <el-button
+        :disabled="formLoading || !selectedUserIdList?.length"
+        type="primary"
+        @click="submitForm"
+      >
+        纭� 瀹�
+      </el-button>
+      <el-button @click="dialogVisible = false">鍙� 娑�</el-button>
+    </template>
+  </Dialog>
+</template>
+<script lang="ts" setup>
+import { defaultProps, handleTree } from '@/utils/tree'
+import * as DeptApi from '@/api/system/dept'
+import * as UserApi from '@/api/system/user'
+
+defineOptions({ name: 'UserSelectForm' })
+const emit = defineEmits<{
+  confirm: [id: any, userList: any[]]
+}>()
+const { t } = useI18n() // 鍥介檯
+const message = useMessage() // 娑堟伅寮圭獥
+const deptTree = ref<Tree[]>([]) // 閮ㄩ棬鏍戝舰缁撴瀯鍖�
+const deptList = ref<any[]>([]) // 淇濆瓨鎵佸钩鍖栫殑閮ㄩ棬鍒楄〃鏁版嵁
+const userList = ref<UserApi.UserVO[]>([]) // 鎵�鏈夌敤鎴峰垪琛�
+const filteredUserList = ref<UserApi.UserVO[]>([]) // 褰撳墠閮ㄩ棬杩囨护鍚庣殑鐢ㄦ埛鍒楄〃
+const selectedUserIdList: any = ref([]) // 閫変腑鐨勭敤鎴峰垪琛�
+const dialogVisible = ref(false) // 寮圭獥鐨勬槸鍚﹀睍绀�
+const formLoading = ref(false) // 琛ㄥ崟鐨勫姞杞戒腑
+const activityId = ref()
+
+/** 璁$畻灞炴�э細鍚堝苟宸查�夋嫨鐨勭敤鎴峰拰褰撳墠閮ㄩ棬杩囨护鍚庣殑鐢ㄦ埛 */
+const transferUserList = computed(() => {
+  // 1.1 鑾峰彇鎵�鏈夊凡閫夋嫨鐨勭敤鎴�
+  const selectedUsers = userList.value.filter((user: any) =>
+    selectedUserIdList.value.includes(user.id)
+  )
+
+  // 1.2 鑾峰彇褰撳墠閮ㄩ棬杩囨护鍚庣殑鏈�夋嫨鐢ㄦ埛
+  const filteredUnselectedUsers = filteredUserList.value.filter(
+    (user: any) => !selectedUserIdList.value.includes(user.id)
+  )
+
+  // 2. 鍚堝苟骞跺幓閲�
+  return [...selectedUsers, ...filteredUnselectedUsers]
+})
+
+/** 鎵撳紑寮圭獥 */
+const open = async (id: number, selectedList?: any[]) => {
+  activityId.value = id
+  resetForm()
+
+  // 鍔犺浇閮ㄩ棬銆佺敤鎴峰垪琛�
+  const deptData = await DeptApi.getSimpleDeptList()
+  deptList.value = deptData // 淇濆瓨鎵佸钩缁撴瀯鐨勯儴闂ㄦ暟鎹�
+  deptTree.value = handleTree(deptData) // 杞崲鎴愭爲褰㈢粨鏋�
+  userList.value = await UserApi.getSimpleUserList()
+
+  // 鍒濆鐘舵�佷笅锛岃繃婊ゅ垪琛ㄧ瓑浜庢墍鏈夌敤鎴峰垪琛�
+  filteredUserList.value = [...userList.value]
+  selectedUserIdList.value = selectedList?.map((item: any) => item.id) || []
+  dialogVisible.value = true
+}
+
+/** 鑾峰彇鎸囧畾閮ㄩ棬鍙婂叾鎵�鏈夊瓙閮ㄩ棬鐨処D鍒楄〃 */
+const getChildDeptIds = (deptId: number, deptList: any[]): number[] => {
+  const ids = [deptId]
+  const children = deptList.filter((dept) => dept.parentId === deptId)
+  children.forEach((child) => {
+    ids.push(...getChildDeptIds(child.id, deptList))
+  })
+  return ids
+}
+
+/** 鑾峰彇閮ㄩ棬杩囨护鍚庣殑鐢ㄦ埛鍒楄〃 */
+const filterUserList = async (deptId?: number) => {
+  formLoading.value = true
+  try {
+    if (!deptId) {
+      // 濡傛灉娌℃湁閫夋嫨閮ㄩ棬锛屾樉绀烘墍鏈夌敤鎴�
+      filteredUserList.value = [...userList.value]
+      return
+    }
+
+    // 鐩存帴浣跨敤宸蹭繚瀛樼殑閮ㄩ棬鍒楄〃鏁版嵁杩涜杩囨护
+    const deptIds = getChildDeptIds(deptId, deptList.value)
+
+    // 杩囨护鍑鸿繖浜涢儴闂ㄤ笅鐨勭敤鎴�
+    filteredUserList.value = userList.value.filter((user) => deptIds.includes(user.deptId))
+  } finally {
+    formLoading.value = false
+  }
+}
+
+/** 鎻愪氦閫夋嫨 */
+const submitForm = async () => {
+  try {
+    message.success(t('common.updateSuccess'))
+    dialogVisible.value = false
+    // 浠庢墍鏈夌敤鎴峰垪琛ㄤ腑绛涢�夊嚭宸查�夋嫨鐨勭敤鎴�
+    const emitUserList = userList.value.filter((user: any) =>
+      selectedUserIdList.value.includes(user.id)
+    )
+    // 鍙戦�佹搷浣滄垚鍔熺殑浜嬩欢
+    emit('confirm', activityId.value, emitUserList)
+  } finally {
+  }
+}
+
+/** 閲嶇疆琛ㄥ崟 */
+const resetForm = () => {
+  deptTree.value = []
+  deptList.value = []
+  userList.value = []
+  filteredUserList.value = []
+  selectedUserIdList.value = []
+}
+
+/** 澶勭悊閮ㄩ棬琚偣鍑� */
+const handleNodeClick = (row: { [key: string]: any }) => {
+  filterUserList(row.id)
+}
+
+defineExpose({ open }) // 鎻愪緵 open 鏂规硶锛岀敤浜庢墦寮�寮圭獥
+</script>
+
+<style lang="scss" scoped>
+:deep() {
+  .el-transfer {
+    display: flex;
+  }
+  .el-transfer__buttons {
+    display: flex !important;
+    flex-direction: column-reverse;
+    justify-content: center;
+    gap: 20px;
+    .el-transfer__button:nth-child(2) {
+      margin: 0;
+    }
+  }
+}
+</style>

--
Gitblit v1.8.0