Files
im-uniapp/components/oa/oa-user-select/index.vue
2025-07-24 15:45:18 +08:00

223 lines
5.7 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view>
<!-- 已选用户展示 -->
<view v-if="multi ? selectedUsers.length : selectedUser" class="selected-user">
<template v-if="multi">
<view v-for="user in selectedUsers" :key="user.userId" class="user-tag">
<text>{{ user.nickName }}</text>
<text class="remove-btn" @click="removeUser(user)">×</text>
</view>
</template>
<template v-else>
<text>{{ selectedUser.nickName }}</text>
<text class="remove-btn" @click="clearUser">×</text>
</template>
</view>
<button type="primary" size="mini" @click="openPopup">{{ multi ? '选择人员' : '选择负责人' }}</button>
<uni-popup ref="popup" type="center">
<view class="user-select-popup">
<view class="popup-header">
<text>{{ multi ? '选择人员' : '选择负责人' }}</text>
<text class="close-btn" @click="closePopup">×</text>
</view>
<view style="padding: 16rpx;">
<input
v-model="userSearchKeyword"
placeholder="请输入昵称搜索"
class="form-input"
style="width: 100%;"
/>
</view>
<view style="height: 400rpx; overflow-y: auto;">
<uni-data-checkbox
:multiple="multi"
v-model="innerValue"
:localdata="filteredUserList"
:map="{text:'nickName', value:'userId'}"
selectedColor="#409EFF"
/>
<view v-if="filteredUserList.length === 0" style="text-align:center;color:#999;padding:20rpx;">
暂无匹配用户
</view>
</view>
<view class="popup-footer">
<button type="primary" size="mini" @click="confirmSelect" :disabled="multi ? !innerValue.length : !innerValue">确定</button>
</view>
</view>
</uni-popup>
</view>
</template>
<script>
import { selectUser } from '@/api/oa/user';
export default {
name: 'OaUserSelect',
props: {
value: {
type: [String, Number, Array],
default: ''
},
multi: {
type: Boolean,
default: false
}
},
data() {
return {
userList: [],
userSearchKeyword: '',
innerValue: this.multi ? [] : '',
selectedUser: null,
selectedUsers: []
};
},
computed: {
filteredUserList() {
if (!this.userSearchKeyword.trim()) return this.userList;
return this.userList.filter(user =>
user.nickName && user.nickName.includes(this.userSearchKeyword.trim())
);
}
},
watch: {
value: {
immediate: true,
handler(val) {
this.innerValue = this.multi ? (Array.isArray(val) ? val : []) : (val || '');
if (this.multi) {
this.selectedUsers = this.userList.filter(u => this.innerValue.includes(u.userId));
} else {
this.selectedUser = this.userList.find(u => u.userId === this.innerValue) || null;
}
}
},
userList(val) {
if (this.multi) {
this.selectedUsers = val.filter(u => this.innerValue.includes(u.userId));
} else {
this.selectedUser = val.find(u => u.userId === this.innerValue) || null;
}
},
multi(val) {
// 切换单多选时重置
this.innerValue = val ? [] : '';
}
},
methods: {
async openPopup() {
if (!this.userList.length) {
const res = await selectUser({ pageNum: 1, pageSize: 999 });
this.userList = res.rows || [];
}
// innerValue已由watch同步
this.$refs.popup.open();
},
closePopup() {
this.$refs.popup.close();
},
selectUser(user) {
if (this.multi) {
const idx = this.selectedUsers.findIndex(u => u.userId === user.userId);
if (idx > -1) {
this.selectedUsers.splice(idx, 1);
} else {
this.selectedUsers.push(user);
}
} else {
this.tempUser = user;
}
},
isSelected(user) {
if (this.multi) {
return this.selectedUsers.some(u => u.userId === user.userId);
} else {
return this.value === user.userId;
}
},
confirmSelect() {
this.$emit('input', this.innerValue);
if (this.multi) {
this.selectedUsers = this.userList.filter(u => this.innerValue.includes(u.userId));
} else {
this.selectedUser = this.userList.find(u => u.userId === this.innerValue) || null;
}
this.closePopup();
},
clearUser() {
this.$emit('input', this.multi ? [] : '');
if (this.multi) {
this.selectedUsers = [];
} else {
this.selectedUser = null;
}
},
removeUser(user) {
if (this.multi) {
this.innerValue = this.innerValue.filter(id => id !== user.userId);
this.selectedUsers = this.selectedUsers.filter(u => u.userId !== user.userId);
this.$emit('input', this.innerValue);
}
}
}
};
</script>
<style scoped>
.selected-user {
display: flex;
align-items: center;
gap: 8rpx;
margin-bottom: 8rpx;
}
.remove-btn {
color: #ff4757;
margin-left: 8rpx;
font-size: 28rpx;
cursor: pointer;
}
.user-select-popup {
background: #fff;
border-radius: 16rpx;
padding: 24rpx;
width: 600rpx;
max-width: 90vw;
}
.popup-header {
display: flex;
justify-content: space-between;
align-items: center;
font-size: 30rpx;
font-weight: bold;
margin-bottom: 16rpx;
}
.close-btn {
color: #888;
font-size: 36rpx;
cursor: pointer;
}
.user-list {
margin-top: 8rpx;
}
.user-row {
display: flex;
align-items: center;
gap: 16rpx;
padding: 12rpx 0;
border-bottom: 1rpx solid #f0f0f0;
cursor: pointer;
}
.user-row.selected {
background: #e6fffb;
}
.user-dept {
color: #999;
font-size: 24rpx;
margin-left: auto;
}
.popup-footer {
display: flex;
justify-content: flex-end;
margin-top: 16rpx;
}
</style>