初始上传

This commit is contained in:
2026-04-04 17:27:12 +08:00
parent 4d80d28eb4
commit b7e11774ee
11191 changed files with 1588469 additions and 0 deletions

View File

@@ -0,0 +1,430 @@
<template>
<base-page>
<view class="userlist">
<view class="userlist-box">
<view class="userlist-left">
<view class="user-title">
员工
<text class="iconfont icongengduo1"></text>
</view>
<view class="user-search">
<view class="search">
<text class="iconfont icon31sousuo"></text>
<input v-model="search_text" type="text" @input="search" placeholder="请输入员工名称/手机号" />
</view>
</view>
<view class="user-list-wrap">
<block v-if="list.length > 0">
<scroll-view :scroll-top="scrollTop" @scroll="scroll" scroll-y="true" class="user-list-scroll all-scroll" @scrolltolower="getUserListFn">
<view class="item" @click="userSelect(item, index)" v-for="(item, index) in list" :key="index" :class="index == selectUserKeys ? 'itemhover' : ''">
<image :src="$util.img(defaultImg.head)" mode="aspectFit"/>
<view class="item-right">
<view>
<view class="user-name">{{ item.username }}</view>
<view class="user-money">{{ item.group_name }}</view>
</view>
<view>
<view class="user-status">{{ item.status ? '正常' : '锁定' }}</view>
<view class="login-time">{{ item.login_time ? $util.timeFormat(item.login_time) : '--' }}</view>
</view>
</view>
</view>
</scroll-view>
</block>
<view class="notYet" v-else-if="!one_judge && list.length == 0">暂无员工</view>
</view>
<view class="add-user">
<button type="default" class="primary-btn" @click="addUser">添加员工</button>
</view>
</view>
<view class="userlist-right">
<view class="user-title">员工详情</view>
<view class="user-information">
<block v-if="JSON.stringify(detail) != '{}'">
<view class="title">基本信息</view>
<view class="information-box">
<view class="box-left">
<view class="information">
<view>员工名称</view>
<view>{{ detail.username }}</view>
</view>
<view class="information">
<view>员工角色</view>
<view>{{ detail.group_name }}</view>
</view>
<view class="information">
<view>员工状态</view>
<view>{{ detail.status ? '正常' : '锁定' }}</view>
</view>
<view class="information">
<view>最后登录IP</view>
<view>{{ detail.login_ip ? detail.login_ip : '--' }}</view>
</view>
<view class="information">
<view>最后登录时间</view>
<view>{{ detail.login_time ? $util.timeFormat(detail.login_time) : '--' }}</view>
</view>
</view>
<image class="user-img" :src="$util.img(defaultImg.head)" mode="widthFix"/>
</view>
<view class="title">操作日志</view>
<view>
<uni-table url="/cashier/storeapi/user/userlog" :cols="logCols" :option="{ uid: detail.uid }" :pagesize="7"></uni-table>
</view>
</block>
<block v-else>
<image class="cart-empty" src="@/static/cashier/cart_empty.png" mode="widthFix"/>
</block>
</view>
<view class="button-box flex justify-end" v-if="detail && (detail.is_admin == 0 || detail.is_system == 0)">
<button class="default-btn" @click="$refs.deletePop.open()">删除</button>
<button class="default-btn" @click="editUserAction(detail.uid)">修改</button>
</view>
</view>
<!-- 添加员工 -->
<uni-popup ref="addUserPop">
<view class="pop-box">
<view class="pop-header">
{{ parseInt(formData.uid) > 0 ? '修改' : '添加' }}员工
<view class="pop-header-close" @click="cancelAddUser()">
<text class="iconguanbi1 iconfont"></text>
</view>
</view>
<view class="common-scrollbar pop-content">
<view class="form-content">
<view class="form-item">
<view class="form-label">
<text class="required">*</text>
用户名
</view>
<view class="form-inline search-wrap">
<input type="text" :disabled="parseInt(formData.uid) > 0 ? true : false" class="form-input" v-model="formData.username" placeholder="请输入用户名" />
</view>
</view>
<view class="form-item" v-if="!parseInt(formData.uid)">
<view class="form-label">
<text class="required"></text>
密码
</view>
<view class="form-inline search-wrap">
<input type="text" class="form-input" v-model="formData.password" placeholder="请输入密码" />
</view>
</view>
<view class="form-item" v-else>
<view class="form-label">
<text class="required"></text>
状态
</view>
<view class="form-inline search-wrap">
<radio-group @change="statusChange" class="form-radio-group">
<label class="radio form-radio-item">
<radio value="1" :checked="formData.status == 1" />
正常
</label>
<label class="radio form-radio-item">
<radio value="0" :checked="formData.status == 0" />
锁定
</label>
</radio-group>
</view>
</view>
<view class="form-item">
<view class="form-label">
<text class="required"></text>
员工角色
</view>
<view class="form-inline">
<select-lay :zindex="10" :value="formData.group_id.toString()" name="names" placeholder="请选择员工角色" :options="userGroup" @selectitem="selectUserGroup"/>
</view>
</view>
</view>
</view>
<view class="pop-bottom">
<button type="primary" class="primary-btn" @click="save">{{ parseInt(formData.uid) > 0 ? '修改' : '添加' }}员工</button>
</view>
</view>
</uni-popup>
</view>
</view>
<!-- 删除 -->
<unipopup ref="deletePop" type="center">
<view class="confirm-pop">
<view class="title">确定要删除该员工数据吗</view>
<view class="btn">
<button type="primary" class="default-btn btn save" @click="$refs.deletePop.close()">取消</button>
<button type="primary" class="primary-btn btn" @click="deleteUserFn(detail.uid)">确定</button>
</view>
</view>
</unipopup>
</base-page>
</template>
<script>
import {
getUserList,
getUserDetail,
getAllGroups,
addUser,
editUser,
deleteUser
} from '@/api/user.js'
import unipopup from '@/components/uni-popup/uni-popup.vue';
export default {
components: {
unipopup
},
data() {
return {
//选中的员工下标
selectUserKeys: 0,
//搜索的数据
search_text: '',
// 初始是请求第几页
page: 1,
// 每次返回数据数
page_size: 8,
//员工列表数据
list: [],
// 第一次请求列表做详情渲染判断
one_judge: true,
//无限滚动请求锁
listLock: true,
scrollTop: 0,
//员工详情数据
detail: {},
logCols: [{
width: 60,
title: '操作记录',
align: 'left',
field: 'action_name'
}, {
width: 20,
title: '操作IP地址',
align: 'left',
field: 'ip'
}, {
width: 20,
title: '操作时间',
align: 'right',
templet: data => {
return this.$util.timeFormat(data.create_time);
}
}],
formData: {
username: '',
password: '',
group_id: ''
},
userGroup: [],
isRepeat: false
};
},
onLoad() {
// 初始化请求员工列表数据
this.getUserListFn();
this.getUserGroup();
},
methods: {
// 选中的员工数据
userSelect(item, keys) {
this.selectUserKeys = keys;
this.getUserDetailFn(item.uid);
this.one_judge = true;
this.isRepeat = false;
this.formData = {
username: '',
password: '',
group_id: ''
};
},
statusChange(e) {
this.formData.status = e.detail.value;
},
// 搜索员工
search() {
this.page = 1;
this.list = [];
this.one_judge = true;
this.listLock = true;
this.getUserListFn();
},
/**
* 请求的列表数据
*/
getUserListFn() {
if (!this.listLock) return false;
getUserList({
page: this.page,
page_size: this.page_size,
username: this.search_text
}).then(res => {
if (res.data.list.length == 0 && this.one_judge) {
this.detail = {};
this.one_judge = false;
}
if (res.code >= 0 && res.data.list.length != 0) {
if (this.list.length == 0) {
this.list = res.data.list;
} else {
this.list = this.list.concat(res.data.list);
}
//初始时加载一遍详情数据
if (this.one_judge) {
this.getUserDetailFn(this.list[0].uid);
}
}
if (this.page == 1) {
this.scrollTop = 0
}
if (res.data.list.length < this.page_size) {
this.listLock = false
} else {
this.page++
}
});
},
scroll(e) {
this.scrollTop = e.detail.scrollTop
},
getUserDetailFn(uid) {
getUserDetail(uid).then(res => {
if (res.code == 0) {
this.detail = res.data;
this.one_judge = false;
}
});
},
getUserGroup() {
getAllGroups().then(res => {
if (res.code == 0 && res.data) {
this.userGroup = res.data.map(item => {
return {
label: item.group_name,
value: item.group_id,
create_uid:item.create_uid,
store_id:item.store_id,
};
});
}
})
},
editUserAction(uid) {
getUserDetail(uid).then(res => {
if (res.code == 0) {
if(res.data.create_user_info){
this.formData = {
username: res.data.username,
group_id: res.data.group_id,
uid: res.data.uid,
status: res.data.status
};
this.$refs.addUserPop.open();
}
}
});
},
deleteUserFn(uid) {
if(this.isRepeat) return false;
this.isRepeat = true;
deleteUser(uid).then(res => {
if (res.code >= 0) {
this.page = 1;
this.list = [];
this.one_judge = true;
this.listLock = true;
this.getUserListFn();
this.$refs.deletePop.close()
} else {
this.$util.showToast({
title: res.message
});
}
this.isRepeat = false
});
},
addUser() {
this.$refs.addUserPop.open();
},
cancelAddUser() {
this.formData = {
username: '',
password: '',
group_id: ''
};
this.$refs.addUserPop.close();
},
selectUserGroup(index, item) {
if (index >= 0) {
this.formData.group_id = parseInt(item.value);
} else {
this.formData.group_id = 0;
}
},
save() {
if (!this.verify() || this.isRepeat) return;
this.isRepeat = true;
let action = '';
if (parseInt(this.formData.uid) > 0) {
action = editUser(this.formData);
} else {
action = addUser(this.formData);
}
action.then(res => {
if (res.code >= 0) {
this.$util.showToast({
title: '操作成功'
});
this.page = 1;
this.list = [];
this.one_judge = true;
this.listLock = true;
this.cancelAddUser();
this.getUserListFn();
this.isRepeat = false;
this.formData = {
username: '',
password: '',
group_id: ''
};
} else {
this.isRepeat = false;
this.$util.showToast({
title: res.message
});
}
});
},
verify() {
if (!this.formData.username) {
this.$util.showToast({
title: '请输入用户名'
});
return false;
}
if (parseInt(this.formData.uid) == 0 && !this.formData.password) {
this.$util.showToast({
title: '请输入密码'
});
return false;
}
if (!this.formData.group_id) {
this.$util.showToast({
title: '请选择员工角色'
});
return false;
}
return true;
}
}
};
</script>
<style scoped lang="scss">
@import './public/css/user.scss';
</style>

View File

@@ -0,0 +1,482 @@
.userlist {
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: space-between;
box-sizing: border-box;
.userlist-box {
width: 100%;
height: 100%;
background: #ffffff;
display: flex;
.userlist-left {
width: 5rem;
height: 100%;
border-right: 0.01rem solid #e6e6e6;
box-sizing: border-box;
display: flex;
flex-direction: column;
.notYet {
color: #e6e6e6;
font-size: 0.4rem;
margin-top: 3rem;
text-align: center;
}
.add-user {
padding: 0.24rem 0.2rem;
background: #fff;
button {
height: .4rem;
line-height: .4rem;
}
}
.user-title {
text-align: center;
line-height: 0.6rem;
font-size: 0.18rem;
font-weight: 500;
height: 0.6rem;
border-bottom: 0.01rem solid #e6e6e6;
box-sizing: border-box;
position: relative;
.icongengduo1 {
position: absolute;
top: 50%;
right: 0.2rem;
transform: translateY(-50%);
font-size: 0.3rem;
color: $primary-color;
}
}
.user-search {
width: 100%;
height: 0.6rem;
border-bottom: 0.01rem solid #e6e6e6;
display: flex;
align-items: center;
justify-content: center;
padding: 0 0.2rem;
box-sizing: border-box;
.search {
width: 5.6rem;
height: 0.4rem;
border-radius: 0.04rem;
background: #f5f5f5;
display: flex;
align-items: center;
padding: 0 0.2rem;
box-sizing: border-box;
.iconfont {
font-size: 0.16rem;
color: #909399;
margin-right: 0.11rem;
}
input {
width: 80%;
height: 60%;
border: none;
font-size: 0.14rem;
}
}
}
.user-list-wrap {
flex: 1;
height: 0;
}
.user-list-scroll {
width: 100%;
height: 100%;
.itemhover {
background: var(--primary-color-light-9);
}
.item {
width: 100%;
display: flex;
align-items: center;
padding: 0.2rem;
box-sizing: border-box;
border-bottom: 0.01rem solid #e6e6e6;
image {
width: 0.7rem;
height: 0.7rem;
margin-right: 0.1rem;
}
.item-right {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
height: 0.6rem;
width: 100%;
.user-name {
font-size: 0.16rem;
}
.user-money {
font-size: 0.14rem;
margin-top: 0.1rem;
}
.login-time {
margin-top: 0.1rem;
}
.user-status {
text-align: right;
color: $primary-color;
font-size: 0.16rem;
}
}
}
}
}
.userlist-right {
width: 0;
flex: 1;
height: 100%;
border-right: 0.01rem solid #e6e6e6;
box-sizing: border-box;
position: relative;
.user-title {
text-align: center;
line-height: 0.6rem;
font-size: 0.18rem;
font-weight: 500;
height: 0.6rem;
border-bottom: 0.01rem solid #e6e6e6;
box-sizing: border-box;
position: relative;
.icongengduo1, .iconguanbi1 {
position: absolute;
top: 50%;
right: 0.2rem;
transform: translateY(-50%);
font-size: 0.3rem;
color: $primary-color;
cursor: pointer;
}
}
.user-information {
width: 100%;
padding: 0.2rem 0.2rem 0.2rem 0.2rem;
box-sizing: border-box;
height: calc(100% - 1.38rem);
overflow-y: auto;
position: relative;
.title {
font-size: 0.18rem;
margin-bottom: 0.32rem;
}
.title2 {
margin-bottom: 0.35rem;
}
.information-box {
display: flex;
justify-content: space-between;
.box-left {
width: 5rem;
.information {
width: 100%;
padding-left: 0.1rem;
box-sizing: border-box;
display: flex;
align-items: center;
margin-bottom: 0.15rem;
view {
color: #303133;
font-size: 0.14rem;
}
view:nth-child(1) {
width: 1.3rem;
margin-right: 0.16rem;
text-align: right;
}
view:nth-child(2) {
width: 74%;
margin-right: 0.23rem;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
}
}
.information:last-child {
margin-bottom: 0.35rem;
}
}
.user-img {
width: 1.5rem;
height: 1.5rem;
}
}
.table {
width: 100%;
height: 2.6rem;
box-sizing: border-box;
.table-all {
width: 100%;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 0.38rem;
box-sizing: border-box;
.table-td {
font-size: 0.14rem;
text-align: left;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
}
}
.table-th {
height: 0.56rem;
background: #f7f8fa;
}
.table-tb {
width: 100%;
height: calc(100% - 0.56rem);
.table-tr {
height: 0.7rem;
border-bottom: 0.01rem solid #e6e6e6;
box-sizing: border-box;
.table-td {
image {
width: 0.5rem;
height: 0.5rem;
}
text-overflow: -o-ellipsis-lastline;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
line-clamp: 2;
-webkit-box-orient: vertical;
}
}
}
}
}
.button-box {
width: 100%;
position: absolute;
bottom: 0;
left: 0;
box-sizing: border-box;
padding: 0.24rem 0.2rem;
button {
width: 1rem;
height: 0.4rem;
line-height: 0.4rem;
margin-left: 0.1rem;
margin-right: 0;
}
}
}
}
}
view {
color: #303133;
}
/deep/ .uni-scroll-view::-webkit-scrollbar {
width: 0.05rem;
height: 0.3rem;
}
/deep/ .uni-scroll-view::-webkit-scrollbar-thumb {
border-radius: 0.1rem;
box-shadow: inset 0 0 0.05rem rgba(0, 0, 0, 0.2);
background: rgba(193, 193, 193, 1);
}
.user-information::-webkit-scrollbar {
width: 0.05rem;
height: 0.3rem;
}
.user-information::-webkit-scrollbar-thumb {
border-radius: 0.1rem;
box-shadow: inset 0 0 0.05rem rgba(0, 0, 0, 0.2);
background: rgba(193, 193, 193, 1);
}
.cart-empty {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 2.1rem;
}
.form-content {
margin-top: 0.2rem;
.form-item {
margin-bottom: 0.1rem;
display: flex;
.form-label {
width: 1.3rem;
text-align: right;
padding-right: 0.1rem;
box-sizing: border-box;
height: 0.32rem;
line-height: 0.32rem;
.required {
color: red;
margin-right: 0.03rem;
}
}
.form-inline {
width: 2.4rem;
line-height: 0.32rem;
margin-right: 0.1rem;
box-sizing: border-box;
.form-input {
border-width: 0.01rem;
border-style: solid;
background-color: #fff;
color: rgba(0, 0, 0, 0.85);
border-radius: 0.02rem;
padding-left: 0.1rem;
height: 0.32rem;
line-height: 0.32rem;
font-size: 0.14rem;
border-color: #e6e6e6;
}
button {
width: calc(50% - 0.05rem);
display: inline-block;
margin-right: 0.1rem;
&:nth-child(2) {
margin-right: 0;
}
}
}
.search-wrap {
position: relative;
}
}
}
.form-radio-group {
display: flex;
align-items: center;
}
.form-checkbox-item, .form-radio-item {
margin-right: 26rpx;
display: flex;
align-items: center;
}
/deep/ .uni-radio-input, .uni-checkbox-input {
width: .18rem;
height: .18rem;
}
// pop弹框
.pop-box {
background: #ffffff;
width: 4.2rem;
height: 3.38rem;
.pop-header {
padding: 0 0.15rem 0 0.2rem;
height: 0.5rem;
line-height: 0.5rem;
border-bottom: 0.01rem solid #f0f0f0;
font-size: 0.14rem;
color: #333;
overflow: hidden;
border-radius: 0.02rem 0.2rem 0 0;
box-sizing: border-box;
display: flex;
justify-content: space-between;
.pop-header-text {
}
.pop-header-close {
cursor: pointer;
text {
font-size: 0.18rem;
}
}
}
.pop-content {
height: calc(100% - 1.05rem);
padding: 0.2rem;
box-sizing: border-box;
}
.form-content {
margin-top: 0;
padding-top: 0.2rem;
display: flex;
flex-direction: column;
align-items: center;
.form-label {
width: .9rem;
}
}
.pop-bottom {
padding: 0.1rem;
border-top: 0.01rem solid #eee;
button {
width: 95%;
}
}
}