Files
threeonecheck_web/pages/membermanagemen/membermanagemen.vue
2026-02-08 09:30:43 +08:00

505 lines
11 KiB
Vue
Raw Permalink 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 class="page padding">
<!-- 成员管理卡片 -->
<view class="member-card bg-white radius">
<!-- 卡片头部公司名称 + 角色标签 -->
<view class="card-header">
<view class="flex align-center">
<view class="border-line"></view>
<view class="text-bold margin-left-sm">{{ userInfo.deptName || '未知部门' }}</view>
</view>
<view class="role-tag">{{ roleText }}</view>
</view>
<!-- 成员列表 -->
<view class="member-list">
<view
class="member-item"
v-for="(item, index) in list"
:key="item.userId"
:class="{ 'border-bottom': index < list.length - 1 }"
>
<view class="cu-avatar radius lg bg-gray" style="background-image:url(https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png);"></view>
<view class="member-info">
<view class="flex align-center">
<text class="member-name">{{ item.nickName }}</text>
<view class="status-tag" :class="item.statusName === '正常' ? 'status-normal' : 'status-locked'">
{{ item.statusName }}
</view>
</view>
<view class="member-phone text-gray">
<text>手机{{ item.phonenumber || '未设置' }}</text>
</view>
</view>
<button class="btn-lock bg-blue" @click="Lock(item)">
{{ item.status === '1' ? '解锁' : '锁定' }}
</button>
</view>
</view>
<!-- 添加成员按钮 -->
<view class="add-btn-wrapper">
<button class="add-btn" @click="showPopup = true">
<text class="cuIcon-add"></text>
<text>添加成员</text>
</button>
</view>
</view>
<!-- 添加成员弹出框 -->
<u-popup :show="showPopup" mode="center" round="20" @close="showPopup = false">
<view class="popup-content">
<view class="popup-header">
<view class="popup-title text-bold">添加成员</view>
<view class="popup-close" @click="showPopup = false">×</view>
</view>
<scroll-view class="popup-body" scroll-y>
<!-- 用户名 -->
<view class="form-item">
<view class="form-label">用户名<text class="text-red">*</text></view>
<up-input v-model="formData.username" placeholder="请输入用户名" border="surround"></up-input>
</view>
<!-- 昵称 -->
<view class="form-item">
<view class="form-label">昵称</view>
<up-input v-model="formData.nickname" placeholder="请输入昵称" border="surround"></up-input>
</view>
<!-- 手机号 -->
<view class="form-item">
<view class="form-label">手机号</view>
<up-input v-model="formData.phone" placeholder="请输入手机号" type="number" border="surround"></up-input>
</view>
<!-- 密码 -->
<view class="form-item">
<view class="form-label">密码<text class="text-red">*</text></view>
<up-input v-model="formData.password" placeholder="请输入密码6-16位" password border="surround"></up-input>
</view>
<!-- 角色类型 -->
<view class="form-item">
<view class="form-label">角色类型<text class="text-red">*</text></view>
<view class="form-select" @click="showRolePicker = true">
<text :class="selectedRoleName ? '' : 'text-gray'">
{{ selectedRoleName || '请选择角色类型' }}
</text>
<text class="cuIcon-unfold"></text>
</view>
<up-picker
:show="showRolePicker"
:columns="roleColumns"
@confirm="onRoleConfirm"
@cancel="showRolePicker = false"
@close="showRolePicker = false"
></up-picker>
</view>
</scroll-view>
<view class="popup-footer">
<button class="btn-cancel" @click="showPopup = false">取消</button>
<button class="btn-confirm bg-blue" @click="handleSubmit">确定</button>
</view>
</view>
</u-popup>
<TabBar />
</view>
</template>
<script setup>
import { ref, reactive, computed, onMounted } from 'vue';
import { addMember, getMemberList, lockOrUnlockMember } from '@/request/api.js';
// 用户信息从storage获取
const userInfo = ref({
deptId: '',
deptName: '',
nickName: '',
role: '',
userId: '',
username: ''
});
// 角色显示文本
const roleText = computed(() => {
const role = userInfo.value.role;
if (role === 'manage' || role === 'admin') {
return '管理人员';
} else if (role === 'common') {
return '执行人员';
}
return '成员';
});
// 获取用户信息
const getUserInfo = () => {
try {
const userInfoStr = uni.getStorageSync('userInfo');
if (userInfoStr) {
userInfo.value = JSON.parse(userInfoStr);
console.log('用户信息:', userInfo.value);
}
} catch (error) {
console.error('获取用户信息失败:', error);
}
};
// 成员列表
const list = ref([]);
// 获取成员列表
const fetchMemberList = async () => {
try {
const res = await getMemberList();
if (res.code === 0 && res.data) {
list.value = res.data;
console.log('成员列表:', res.data);
}
} catch (error) {
console.error('获取成员列表失败:', error);
}
};
// 弹窗控制
const showPopup = ref(false);
const showRolePicker = ref(false);
const selectedRoleName = ref('');
// 表单数据
const formData = reactive({
username: '',
nickname: '',
phone: '',
password: '',
roleType: ''
});
// 角色类型选择器数据
const roleColumns = reactive([
['管理员', '普通成员']
]);
// 角色名称与值的映射
const roleMap = {
'管理员': 'manage',
'普通成员': 'common'
};
// 角色类型选择确认
const onRoleConfirm = (e) => {
if (e.value && e.value.length > 0) {
selectedRoleName.value = e.value[0];
formData.roleType = roleMap[e.value[0]];
}
showRolePicker.value = false;
};
// 重置表单
const resetForm = () => {
formData.username = '';
formData.nickname = '';
formData.phone = '';
formData.password = '';
formData.roleType = '';
selectedRoleName.value = '';
};
// 提交表单
const handleSubmit = async () => {
if (!formData.username) {
uni.showToast({ title: '请输入用户名', icon: 'none' });
return;
}
if (!formData.password || formData.password.length < 6 || formData.password.length > 16) {
uni.showToast({ title: '请输入6-16位密码', icon: 'none' });
return;
}
if (!formData.roleType) {
uni.showToast({ title: '请选择角色类型', icon: 'none' });
return;
}
const params = {
userName: formData.username,
nickName: formData.nickname || '',
phonenumber: formData.phone || '',
password: formData.password,
roleType: formData.roleType
};
try {
const res = await addMember(params);
if (res.code === 0) {
uni.showToast({ title: '添加成功', icon: 'success' });
showPopup.value = false;
resetForm();
// 刷新成员列表
fetchMemberList();
} else {
uni.showToast({ title: res.msg || '添加失败', icon: 'none' });
}
} catch (error) {
console.error('添加成员失败:', error);
uni.showToast({ title: '请求失败', icon: 'none' });
}
};
// 锁定/解锁成员
const Lock = (item) => {
const isLocked = item.status === '1';
const actionText = isLocked ? '解锁' : '锁定';
const newStatus = isLocked ? '0' : '1';
uni.showModal({
title: '提示',
content: `确定要${actionText}该成员吗?`,
confirmColor: '#2667E9',
success: async (res) => {
if (res.confirm) {
try {
const result = await lockOrUnlockMember({
userId: item.userId,
lockStatus: Number(newStatus)
});
if (result.code === 0) {
uni.showToast({ title: `${actionText}成功`, icon: 'success' });
// 更新本地状态
item.status = newStatus;
item.statusName = newStatus === '1' ? '已锁定' : '正常';
} else {
uni.showToast({ title: result.msg || `${actionText}失败`, icon: 'none' });
}
} catch (error) {
console.error(`${actionText}成员失败:`, error);
uni.showToast({ title: '请求失败', icon: 'none' });
}
}
}
});
};
// 页面加载
onMounted(() => {
getUserInfo();
fetchMemberList();
});
</script>
<style lang="scss" scoped>
.page {
min-height: 100vh;
background: #EBF2FC;
}
// 成员卡片
.member-card {
padding: 0;
overflow: hidden;
}
// 卡片头部
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 30rpx;
border-bottom: 1rpx solid #f0f0f0;
.border-line {
width: 8rpx;
height: 32rpx;
background: #2667E9;
border-radius: 8rpx;
}
}
// 角色标签
.role-tag {
padding: 8rpx 24rpx;
background: #EEF3FF;
color: #2667E9;
font-size: 24rpx;
border-radius: 24rpx 0 0 24rpx;
margin-right: -30rpx;
}
// 成员列表
.member-list {
padding: 0 30rpx;
}
// 成员项
.member-item {
display: flex;
align-items: center;
padding: 24rpx 0;
&.border-bottom {
border-bottom: 1rpx solid #f5f5f5;
}
.cu-avatar {
flex-shrink: 0;
}
}
// 成员信息
.member-info {
flex: 1;
margin-left: 20rpx;
overflow: hidden;
.member-name {
font-size: 30rpx;
color: #333;
font-weight: 500;
}
.member-phone {
font-size: 24rpx;
margin-top: 8rpx;
}
}
// 状态标签
.status-tag {
margin-left: 12rpx;
padding: 4rpx 12rpx;
font-size: 22rpx;
border-radius: 6rpx;
&.status-normal {
background: #E8F5E9;
color: #4CAF50;
}
&.status-locked {
background: #FFEBEE;
color: #F44336;
}
}
// 锁定按钮
.btn-lock {
width: 120rpx;
height: 56rpx;
line-height: 56rpx;
padding: 0;
font-size: 26rpx;
border-radius: 28rpx;
flex-shrink: 0;
}
// 添加成员按钮
.add-btn-wrapper {
padding: 30rpx;
border-top: 1rpx solid #f0f0f0;
}
.add-btn {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 88rpx;
background: #fff;
border: 2rpx dashed #2667E9;
border-radius: 12rpx;
color: #2667E9;
font-size: 30rpx;
.cuIcon-add {
margin-right: 10rpx;
font-size: 32rpx;
}
&::after {
border: none;
}
}
// 弹出框样式
.popup-content {
width: 600rpx;
background: #fff;
border-radius: 20rpx;
overflow: hidden;
}
.popup-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 30rpx;
border-bottom: 1rpx solid #eee;
}
.popup-title {
font-size: 34rpx;
color: #333;
}
.popup-close {
font-size: 48rpx;
color: #999;
line-height: 1;
}
.popup-body {
padding: 30rpx;
max-height: 700rpx;
overflow-y: auto;
}
.form-item {
margin-bottom: 24rpx;
}
.form-label {
font-size: 28rpx;
color: #333;
margin-bottom: 12rpx;
display: flex;
align-items: center;
}
.form-select {
display: flex;
align-items: center;
justify-content: space-between;
height: 80rpx;
border: 2rpx solid #dadbde;
border-radius: 8rpx;
padding: 0 24rpx;
font-size: 28rpx;
}
.popup-footer {
display: flex;
border-top: 1rpx solid #eee;
button {
flex: 1;
height: 90rpx;
line-height: 90rpx;
border-radius: 0;
font-size: 30rpx;
&::after {
border: none;
}
}
}
.btn-cancel {
background: #fff;
color: #666;
}
.btn-confirm {
color: #fff;
}
</style>