<template>
|
|
<view class="content">
|
|
<navbar title="员工管理" leftClick @leftClick="$utils.navigateBack" />
|
|
<view class="header">
|
|
<view class="title">员工管理</view>
|
|
<view class="subtitle">管理企业员工信息和权限</view>
|
|
</view>
|
|
|
|
<!-- 搜索栏 -->
|
|
<view class="search-bar">
|
|
<view class="search-input">
|
|
<uv-icon name="search" size="20" color="#999"></uv-icon>
|
|
<input v-model="searchKeyword" placeholder="搜索员工姓名或手机号" @input="onSearch" />
|
|
</view>
|
|
<view class="add-btn" @click="addStaff">
|
|
<uv-icon name="plus" size="20" color="#fff"></uv-icon>
|
|
<text>添加</text>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 统计信息 -->
|
|
<view class="stats-container">
|
|
<view class="stats-item">
|
|
<view class="stats-number">{{ totalStaff }}</view>
|
|
<view class="stats-label">总员工数</view>
|
|
</view>
|
|
<view class="stats-item">
|
|
<view class="stats-number">{{ activeStaff }}</view>
|
|
<view class="stats-label">在职员工</view>
|
|
</view>
|
|
<view class="stats-item">
|
|
<view class="stats-number">{{ onlineStaff }}</view>
|
|
<view class="stats-label">在线员工</view>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 员工列表 -->
|
|
<view class="staff-list">
|
|
<view v-if="filteredStaffList.length === 0" class="empty-state">
|
|
<view class="empty-icon">👥</view>
|
|
<view class="empty-text">暂无员工信息</view>
|
|
</view>
|
|
|
|
<view v-for="(item, index) in filteredStaffList" :key="index" class="staff-item">
|
|
<view class="staff-avatar">
|
|
<image :src="item.avatar" mode="aspectFill"></image>
|
|
<view class="online-status" :class="{online: item.isOnline}"></view>
|
|
</view>
|
|
|
|
<view class="staff-info">
|
|
<view class="staff-header">
|
|
<view class="name">{{ item.name }}</view>
|
|
<view class="role-badge" :class="item.role">{{ getRoleText(item.role) }}</view>
|
|
</view>
|
|
|
|
<view class="staff-details">
|
|
<text>手机:{{ item.phone }}</text>
|
|
<text>部门:{{ item.department }}</text>
|
|
<text>入职时间:{{ item.joinDate }}</text>
|
|
</view>
|
|
|
|
<view class="staff-stats">
|
|
<view class="stat-item">
|
|
<text class="stat-label">本月订单:</text>
|
|
<text class="stat-value">{{ item.monthlyOrders }}</text>
|
|
</view>
|
|
<view class="stat-item">
|
|
<text class="stat-label">评分:</text>
|
|
<text class="stat-value">{{ item.rating }}分</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<view class="staff-actions">
|
|
<view class="action-btn" @click="viewStaff(item)">
|
|
<uv-icon name="eye" size="16" color="#007AFF"></uv-icon>
|
|
</view>
|
|
<view class="action-btn" @click="editStaff(item)">
|
|
<uv-icon name="edit-pen" size="16" color="#ff9500"></uv-icon>
|
|
</view>
|
|
<view class="action-btn" @click="deleteStaff(item)">
|
|
<uv-icon name="trash" size="16" color="#ff3b30"></uv-icon>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</template>
|
|
|
|
<script>
|
|
import navbar from '@/components/base/navbar.vue'
|
|
|
|
export default {
|
|
name: 'StaffManage',
|
|
components: {
|
|
navbar
|
|
},
|
|
data() {
|
|
return {
|
|
searchKeyword: '',
|
|
totalStaff: 15,
|
|
activeStaff: 12,
|
|
onlineStaff: 8,
|
|
staffList: [
|
|
{
|
|
id: 1,
|
|
name: '张师傅',
|
|
phone: '13800138001',
|
|
avatar: '/static/re/logo.png',
|
|
role: 'driver',
|
|
department: '运输部',
|
|
joinDate: '2023-06-15',
|
|
isOnline: true,
|
|
monthlyOrders: 28,
|
|
rating: 4.8
|
|
},
|
|
{
|
|
id: 2,
|
|
name: '李师傅',
|
|
phone: '13800138002',
|
|
avatar: '/static/re/logo.png',
|
|
role: 'driver',
|
|
department: '运输部',
|
|
joinDate: '2023-08-20',
|
|
isOnline: false,
|
|
monthlyOrders: 22,
|
|
rating: 4.6
|
|
},
|
|
{
|
|
id: 3,
|
|
name: '王主管',
|
|
phone: '13800138003',
|
|
avatar: '/static/re/logo.png',
|
|
role: 'supervisor',
|
|
department: '调度部',
|
|
joinDate: '2023-03-10',
|
|
isOnline: true,
|
|
monthlyOrders: 45,
|
|
rating: 4.9
|
|
},
|
|
{
|
|
id: 4,
|
|
name: '赵师傅',
|
|
phone: '13800138004',
|
|
avatar: '/static/re/logo.png',
|
|
role: 'driver',
|
|
department: '运输部',
|
|
joinDate: '2023-09-05',
|
|
isOnline: true,
|
|
monthlyOrders: 31,
|
|
rating: 4.7
|
|
},
|
|
{
|
|
id: 5,
|
|
name: '陈操作员',
|
|
phone: '13800138005',
|
|
avatar: '/static/re/logo.png',
|
|
role: 'operator',
|
|
department: '操作部',
|
|
joinDate: '2023-11-12',
|
|
isOnline: false,
|
|
monthlyOrders: 18,
|
|
rating: 4.5
|
|
}
|
|
]
|
|
}
|
|
},
|
|
computed: {
|
|
filteredStaffList() {
|
|
if (!this.searchKeyword) {
|
|
return this.staffList;
|
|
}
|
|
return this.staffList.filter(staff =>
|
|
staff.name.includes(this.searchKeyword) ||
|
|
staff.phone.includes(this.searchKeyword)
|
|
);
|
|
}
|
|
},
|
|
onLoad() {
|
|
uni.setNavigationBarTitle({
|
|
title: '员工管理'
|
|
});
|
|
},
|
|
methods: {
|
|
onSearch() {
|
|
// 搜索逻辑已在computed中实现
|
|
},
|
|
getRoleText(role) {
|
|
switch(role) {
|
|
case 'driver': return '司机';
|
|
case 'supervisor': return '主管';
|
|
case 'operator': return '操作员';
|
|
default: return '员工';
|
|
}
|
|
},
|
|
addStaff() {
|
|
uni.navigateTo({
|
|
url: '/pages_order/staff/addStaff'
|
|
});
|
|
},
|
|
viewStaff(staff) {
|
|
uni.navigateTo({
|
|
url: `/pages_order/staff/staffDetail?id=${staff.id}`
|
|
});
|
|
},
|
|
editStaff(staff) {
|
|
uni.navigateTo({
|
|
url: `/pages_order/staff/editStaff?id=${staff.id}`
|
|
});
|
|
},
|
|
deleteStaff(staff) {
|
|
uni.showModal({
|
|
title: '确认删除',
|
|
content: `确定要删除员工${staff.name}吗?此操作不可恢复。`,
|
|
success: (res) => {
|
|
if (res.confirm) {
|
|
const index = this.staffList.findIndex(item => item.id === staff.id);
|
|
if (index > -1) {
|
|
this.staffList.splice(index, 1);
|
|
this.totalStaff--;
|
|
this.activeStaff--;
|
|
if (staff.isOnline) {
|
|
this.onlineStaff--;
|
|
}
|
|
uni.showToast({
|
|
title: '删除成功',
|
|
icon: 'success'
|
|
});
|
|
}
|
|
}
|
|
}
|
|
});
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style scoped lang="scss">
|
|
.content {
|
|
padding: 20rpx;
|
|
min-height: 100vh;
|
|
background-color: #f5f5f5;
|
|
}
|
|
|
|
.header {
|
|
background-color: #fff;
|
|
padding: 30rpx;
|
|
border-radius: 10rpx;
|
|
margin-bottom: 20rpx;
|
|
text-align: center;
|
|
|
|
.title {
|
|
font-size: 36rpx;
|
|
font-weight: bold;
|
|
color: #333;
|
|
margin-bottom: 10rpx;
|
|
}
|
|
|
|
.subtitle {
|
|
font-size: 28rpx;
|
|
color: #666;
|
|
}
|
|
}
|
|
|
|
.search-bar {
|
|
display: flex;
|
|
gap: 20rpx;
|
|
margin-bottom: 20rpx;
|
|
|
|
.search-input {
|
|
flex: 1;
|
|
display: flex;
|
|
align-items: center;
|
|
padding: 20rpx;
|
|
background-color: #fff;
|
|
border-radius: 25rpx;
|
|
gap: 15rpx;
|
|
|
|
input {
|
|
flex: 1;
|
|
font-size: 28rpx;
|
|
border: none;
|
|
outline: none;
|
|
}
|
|
}
|
|
|
|
.add-btn {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8rpx;
|
|
padding: 20rpx 30rpx;
|
|
background-color: #007AFF;
|
|
color: #fff;
|
|
border-radius: 25rpx;
|
|
font-size: 28rpx;
|
|
}
|
|
}
|
|
|
|
.stats-container {
|
|
display: flex;
|
|
background-color: #fff;
|
|
border-radius: 10rpx;
|
|
margin-bottom: 20rpx;
|
|
padding: 30rpx 0;
|
|
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
|
|
|
|
.stats-item {
|
|
flex: 1;
|
|
text-align: center;
|
|
|
|
.stats-number {
|
|
font-size: 48rpx;
|
|
font-weight: bold;
|
|
color: #007AFF;
|
|
margin-bottom: 10rpx;
|
|
}
|
|
|
|
.stats-label {
|
|
font-size: 24rpx;
|
|
color: #666;
|
|
}
|
|
}
|
|
}
|
|
|
|
.staff-list {
|
|
.empty-state {
|
|
text-align: center;
|
|
padding: 100rpx 0;
|
|
background-color: #fff;
|
|
border-radius: 10rpx;
|
|
|
|
.empty-icon {
|
|
font-size: 120rpx;
|
|
margin-bottom: 20rpx;
|
|
}
|
|
|
|
.empty-text {
|
|
font-size: 28rpx;
|
|
color: #999;
|
|
}
|
|
}
|
|
|
|
.staff-item {
|
|
display: flex;
|
|
background-color: #fff;
|
|
border-radius: 10rpx;
|
|
padding: 30rpx;
|
|
margin-bottom: 20rpx;
|
|
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
|
|
|
|
.staff-avatar {
|
|
position: relative;
|
|
width: 120rpx;
|
|
height: 120rpx;
|
|
margin-right: 20rpx;
|
|
|
|
image {
|
|
width: 100%;
|
|
height: 100%;
|
|
border-radius: 60rpx;
|
|
}
|
|
|
|
.online-status {
|
|
position: absolute;
|
|
bottom: 5rpx;
|
|
right: 5rpx;
|
|
width: 24rpx;
|
|
height: 24rpx;
|
|
border-radius: 12rpx;
|
|
background-color: #ccc;
|
|
border: 3rpx solid #fff;
|
|
|
|
&.online {
|
|
background-color: #34c759;
|
|
}
|
|
}
|
|
}
|
|
|
|
.staff-info {
|
|
flex: 1;
|
|
|
|
.staff-header {
|
|
display: flex;
|
|
align-items: center;
|
|
margin-bottom: 15rpx;
|
|
gap: 15rpx;
|
|
|
|
.name {
|
|
font-size: 32rpx;
|
|
font-weight: bold;
|
|
color: #333;
|
|
}
|
|
|
|
.role-badge {
|
|
padding: 6rpx 12rpx;
|
|
border-radius: 15rpx;
|
|
font-size: 22rpx;
|
|
color: #fff;
|
|
|
|
&.driver {
|
|
background-color: #007AFF;
|
|
}
|
|
|
|
&.supervisor {
|
|
background-color: #ff9500;
|
|
}
|
|
|
|
&.operator {
|
|
background-color: #34c759;
|
|
}
|
|
}
|
|
}
|
|
|
|
.staff-details {
|
|
font-size: 26rpx;
|
|
color: #666;
|
|
line-height: 1.4;
|
|
margin-bottom: 15rpx;
|
|
|
|
text {
|
|
display: block;
|
|
margin-bottom: 5rpx;
|
|
}
|
|
}
|
|
|
|
.staff-stats {
|
|
display: flex;
|
|
gap: 30rpx;
|
|
|
|
.stat-item {
|
|
font-size: 24rpx;
|
|
|
|
.stat-label {
|
|
color: #666;
|
|
}
|
|
|
|
.stat-value {
|
|
color: #007AFF;
|
|
font-weight: bold;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
.staff-actions {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 15rpx;
|
|
|
|
.action-btn {
|
|
width: 60rpx;
|
|
height: 60rpx;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
background-color: #f8f8f8;
|
|
border-radius: 30rpx;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
</style>
|