提交
This commit is contained in:
1 parent
d634846222
commit
866b510125
9 files changed
+392
-58
No files matched your search
@@ -6,8 +6,9 @@
|
||||
:custom-style="{
|
||||
width: '95vw',
|
||||
height: '85vh',
|
||||
maxWidth: '800px',
|
||||
maxHeight: '700px',
|
||||
maxWidth: '95vw',
|
||||
maxHeight: '85vh',
|
||||
overflow: 'auto',
|
||||
}"
|
||||
@close="handleClose"
|
||||
>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
height="90%"
|
||||
border-radius="12"
|
||||
@close="cancel"
|
||||
:custom-style="{ width: '90vw' }"
|
||||
:custom-style="{ width: '90vw', maxHeight: '90vh', overflow: 'auto' }"
|
||||
>
|
||||
<view class="submit-verify-container">
|
||||
<view class="header">
|
||||
@@ -248,33 +248,37 @@
|
||||
width="80%"
|
||||
height="70%"
|
||||
border-radius="12"
|
||||
@close="backVisible = false"
|
||||
z-index="20080"
|
||||
@close="closeBackDialog"
|
||||
:custom-style="{ width: '90vw' }"
|
||||
>
|
||||
<view class="back-container">
|
||||
<view class="header">
|
||||
<text class="title">驳回</text>
|
||||
<u-icon name="close" size="24" @click="backVisible = false" />
|
||||
<u-icon name="close" size="24" @click="closeBackDialog" />
|
||||
</view>
|
||||
|
||||
<scroll-view scroll-y class="content" :show-scrollbar="false">
|
||||
<!-- 驳回节点 -->
|
||||
<view class="form-item">
|
||||
<text class="label">驳回节点</text>
|
||||
<u-picker
|
||||
v-model="backForm.nodeCode"
|
||||
mode="selector"
|
||||
:range="taskNodeList"
|
||||
range-key="nodeName"
|
||||
@change="handleBackNodeChange"
|
||||
>
|
||||
<u-input
|
||||
v-model="selectedBackNodeName"
|
||||
placeholder="请选择驳回节点"
|
||||
readonly
|
||||
suffix-icon="arrow-down"
|
||||
/>
|
||||
</u-picker>
|
||||
<view class="form-item horizontal-item">
|
||||
<text class="label horizontal-label">驳回节点</text>
|
||||
<view class="horizontal-control">
|
||||
<u-picker
|
||||
:columns="[taskNodeList]"
|
||||
keyName="nodeName"
|
||||
:defaultIndex="[selectedBackNodeIndex]"
|
||||
:show="showBackNodePicker"
|
||||
:closeOnClickOverlay="true"
|
||||
@confirm="onBackNodeConfirm"
|
||||
@cancel="onBackNodeClose"
|
||||
></u-picker>
|
||||
<view class="picker-input" @click="showBackNodePicker = true">
|
||||
<text class="picker-text">
|
||||
{{ selectedBackNodeName || '请选择驳回节点' }}
|
||||
</text>
|
||||
<u-icon name="arrow-down" size="16" color="#c0c4cc"></u-icon>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 消息提醒 -->
|
||||
@@ -342,7 +346,7 @@
|
||||
</u-button>
|
||||
<u-button
|
||||
type="info"
|
||||
@click="backVisible = false"
|
||||
@click="closeBackDialog"
|
||||
class="action-btn cancel-btn"
|
||||
>
|
||||
取消
|
||||
@@ -359,6 +363,7 @@
|
||||
width="90%"
|
||||
height="60%"
|
||||
border-radius="12"
|
||||
z-index="20080"
|
||||
@close="deleteSignatureVisible = false"
|
||||
>
|
||||
<view class="delete-signature-container">
|
||||
@@ -425,6 +430,8 @@ export default {
|
||||
backButtonDisabled: true,
|
||||
taskNodeList: [],
|
||||
selectedBackNodeName: '',
|
||||
selectedBackNodeIndex: 0,
|
||||
showBackNodePicker: false,
|
||||
nickName: {},
|
||||
nodeCode: '',
|
||||
buttonObj: {
|
||||
@@ -650,6 +657,7 @@ export default {
|
||||
this.backLoading = false;
|
||||
this.backButtonDisabled = false;
|
||||
if (this.taskNodeList.length > 0) {
|
||||
this.selectedBackNodeIndex = 0;
|
||||
this.backForm.nodeCode = this.taskNodeList[0].nodeCode;
|
||||
this.selectedBackNodeName = this.taskNodeList[0].nodeName;
|
||||
}
|
||||
@@ -663,11 +671,26 @@ export default {
|
||||
}
|
||||
},
|
||||
|
||||
// 退回节点变化
|
||||
handleBackNodeChange(e) {
|
||||
const index = e.detail.value;
|
||||
this.backForm.nodeCode = this.taskNodeList[index].nodeCode;
|
||||
this.selectedBackNodeName = this.taskNodeList[index].nodeName;
|
||||
// 确认选择驳回节点
|
||||
onBackNodeConfirm(e) {
|
||||
const { indexs, value } = e;
|
||||
this.selectedBackNodeIndex = indexs[0];
|
||||
this.backForm.nodeCode = value[0].nodeCode;
|
||||
this.selectedBackNodeName = value[0].nodeName;
|
||||
this.showBackNodePicker = false;
|
||||
},
|
||||
|
||||
// 取消选择驳回节点
|
||||
onBackNodeClose() {
|
||||
this.showBackNodePicker = false;
|
||||
},
|
||||
|
||||
// 关闭退回弹窗
|
||||
closeBackDialog() {
|
||||
this.backVisible = false;
|
||||
this.showBackNodePicker = false;
|
||||
this.selectedBackNodeIndex = 0;
|
||||
this.selectedBackNodeName = '';
|
||||
},
|
||||
|
||||
// 退回流程
|
||||
@@ -689,7 +712,7 @@ export default {
|
||||
|
||||
if (response.code === 200) {
|
||||
this.visible = false;
|
||||
this.backVisible = false;
|
||||
this.closeBackDialog();
|
||||
this.$emit('submitCallback');
|
||||
uni.showToast({
|
||||
title: '操作成功',
|
||||
@@ -1055,21 +1078,30 @@ export default {
|
||||
// 显示确认对话框
|
||||
showConfirm(content) {
|
||||
return new Promise((resolve) => {
|
||||
// 临时隐藏主弹窗,避免层级冲突
|
||||
// 临时隐藏所有弹窗,避免层级冲突
|
||||
const originalVisible = this.visible;
|
||||
const originalBackVisible = this.backVisible;
|
||||
const originalDeleteSignatureVisible = this.deleteSignatureVisible;
|
||||
|
||||
this.visible = false;
|
||||
this.backVisible = false;
|
||||
this.deleteSignatureVisible = false;
|
||||
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content,
|
||||
success: (res) => {
|
||||
// 恢复主弹窗显示状态
|
||||
// 恢复所有弹窗显示状态
|
||||
this.visible = originalVisible;
|
||||
this.backVisible = originalBackVisible;
|
||||
this.deleteSignatureVisible = originalDeleteSignatureVisible;
|
||||
resolve(res);
|
||||
},
|
||||
fail: () => {
|
||||
// 恢复主弹窗显示状态
|
||||
// 恢复所有弹窗显示状态
|
||||
this.visible = originalVisible;
|
||||
this.backVisible = originalBackVisible;
|
||||
this.deleteSignatureVisible = originalDeleteSignatureVisible;
|
||||
resolve({ confirm: false });
|
||||
},
|
||||
});
|
||||
@@ -1146,6 +1178,12 @@ export default {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 16rpx;
|
||||
max-height: 200rpx;
|
||||
overflow-y: auto;
|
||||
padding: 8rpx;
|
||||
border: 1rpx solid #e6e6e6;
|
||||
border-radius: 8rpx;
|
||||
background-color: #fafafa;
|
||||
}
|
||||
|
||||
.copy-tag {
|
||||
@@ -1300,4 +1338,50 @@ export default {
|
||||
padding: 0 24rpx;
|
||||
font-size: 24rpx;
|
||||
}
|
||||
|
||||
.picker-input {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
height: 80rpx;
|
||||
padding: 0 24rpx;
|
||||
background-color: #f8f9fa;
|
||||
border: 1rpx solid #e6e6e6;
|
||||
border-radius: 8rpx;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.picker-input:active {
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
|
||||
.picker-text {
|
||||
flex: 1;
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.picker-text:empty::before {
|
||||
content: attr(placeholder);
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.horizontal-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 20rpx;
|
||||
}
|
||||
|
||||
.horizontal-label {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.horizontal-control {
|
||||
flex: 1;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.horizontal-control .picker-input {
|
||||
width: 80% !important;
|
||||
}
|
||||
</style>
|
||||
@@ -6,7 +6,7 @@
|
||||
height="85%"
|
||||
border-radius="12"
|
||||
@close="close"
|
||||
:custom-style="{ width: '90vw' }"
|
||||
:custom-style="{ width: '90vw', maxHeight: '90vh', overflow: 'auto' }"
|
||||
>
|
||||
<view class="user-select-container">
|
||||
<!-- 标题栏 -->
|
||||
@@ -34,7 +34,11 @@
|
||||
<u-search
|
||||
v-model="searchKeyword"
|
||||
placeholder="请输入用户名称或手机号"
|
||||
:show-action="true"
|
||||
action-text="搜索"
|
||||
:animation="true"
|
||||
@search="handleSearch"
|
||||
@custom="handleSearch"
|
||||
@clear="handleSearch"
|
||||
bg-color="#f5f5f5"
|
||||
/>
|
||||
@@ -171,7 +175,7 @@ export default {
|
||||
// 初始化数据
|
||||
async initData() {
|
||||
try {
|
||||
await this.getDeptList();
|
||||
// await this.getDeptList();
|
||||
await this.getUserList();
|
||||
await this.initSelectUser();
|
||||
} catch (error) {
|
||||
@@ -223,6 +227,8 @@ export default {
|
||||
this.loadStatus = 'loading';
|
||||
}
|
||||
|
||||
this.queryParams.status = 0;
|
||||
|
||||
try {
|
||||
// 设置查询参数
|
||||
this.queryParams.userIds = this.userIds;
|
||||
@@ -232,22 +238,24 @@ export default {
|
||||
this.queryParams.userName = '';
|
||||
} else {
|
||||
this.queryParams.userName = this.searchKeyword;
|
||||
this.queryParams.nickName = this.searchKeyword;
|
||||
this.queryParams.phonenumber = '';
|
||||
}
|
||||
} else {
|
||||
this.queryParams.userName = '';
|
||||
this.queryParams.phonenumber = '';
|
||||
this.queryParams.nickName = '';
|
||||
}
|
||||
|
||||
// 设置部门ID
|
||||
if (this.currentDeptIndex > 0) {
|
||||
this.queryParams.deptId = this.deptList[this.currentDeptIndex].value;
|
||||
} else {
|
||||
this.queryParams.deptId = '';
|
||||
}
|
||||
// if (this.currentDeptIndex > 0) {
|
||||
// this.queryParams.deptId = this.deptList[this.currentDeptIndex].value;
|
||||
// } else {
|
||||
// this.queryParams.deptId = '';
|
||||
// }
|
||||
|
||||
const response = await request({
|
||||
url: '/system/user/list',
|
||||
url: '/system/user/listByOr',
|
||||
method: 'GET',
|
||||
data: this.queryParams,
|
||||
});
|
||||
@@ -290,6 +298,7 @@ export default {
|
||||
|
||||
// 搜索处理
|
||||
handleSearch() {
|
||||
console.log('执行到此-------------------');
|
||||
this.getUserList();
|
||||
},
|
||||
|
||||
@@ -364,14 +373,15 @@ export default {
|
||||
|
||||
// 初始化已选用户
|
||||
async initSelectUser() {
|
||||
console.log('this.data:', this.data);
|
||||
if (this.data) {
|
||||
const userIds = this.computedIds(this.data);
|
||||
if (userIds.length > 0) {
|
||||
try {
|
||||
const response = await request({
|
||||
url: '/system/user/optionselect',
|
||||
method: 'POST',
|
||||
data: userIds,
|
||||
url: '/system/user/optionselect?userIds=' + userIds,
|
||||
method: 'GET',
|
||||
// data: userIds,
|
||||
});
|
||||
|
||||
if (response.code === 200) {
|
||||
@@ -441,10 +451,16 @@ export default {
|
||||
border-bottom: 1rpx solid #f0f0f0;
|
||||
max-height: 200rpx;
|
||||
overflow-y: auto;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.user-tag {
|
||||
margin: 8rpx 16rpx 8rpx 0;
|
||||
display: inline-block;
|
||||
width: auto;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.search-section {
|
||||
|
||||
@@ -76,6 +76,7 @@
|
||||
</view>
|
||||
</template>
|
||||
<GridLayout :columns="3" gap="16px">
|
||||
<!-- 卡片开始 -->
|
||||
<ServiceItem
|
||||
v-if="hasPermi(['student:info:list'])"
|
||||
title="学生信息"
|
||||
@@ -89,7 +90,7 @@
|
||||
/>
|
||||
</template>
|
||||
</ServiceItem>
|
||||
|
||||
<!-- 卡片结束 -->
|
||||
<ServiceItem
|
||||
v-if="hasPermi(['student:dorm:list'])"
|
||||
title="宿舍管理"
|
||||
|
||||
@@ -158,7 +158,7 @@
|
||||
style="height: 60rpx !important"
|
||||
></u-search>
|
||||
|
||||
<scroll-view scroll-y class="user-list">
|
||||
<scroll-view scroll-y class="user-list" @scrolltolower="loadMoreUsers">
|
||||
<view
|
||||
v-for="user in userList"
|
||||
:key="user.userId"
|
||||
@@ -178,6 +178,18 @@
|
||||
@click.stop
|
||||
></u-checkbox>
|
||||
</view>
|
||||
|
||||
<!-- 用户列表加载更多 -->
|
||||
<u-loadmore
|
||||
v-if="userList.length > 0"
|
||||
:status="userLoadmoreStatus"
|
||||
:load-text="{
|
||||
loadmore: '轻轻上拉',
|
||||
loading: '努力加载中',
|
||||
nomore: '没有更多了',
|
||||
}"
|
||||
@loadmore="loadMoreUsers"
|
||||
></u-loadmore>
|
||||
</scroll-view>
|
||||
</view>
|
||||
|
||||
@@ -224,6 +236,15 @@ export default {
|
||||
userList: [], // 用户列表
|
||||
userSearchKeyword: '', // 用户搜索关键词
|
||||
userSearchTimer: null, // 搜索防抖定时器
|
||||
|
||||
// 用户列表分页参数
|
||||
userListParams: {
|
||||
pageNum: 1,
|
||||
pageSize: 20,
|
||||
total: 0,
|
||||
},
|
||||
userListLoading: false, // 用户列表加载状态
|
||||
userLoadmoreStatus: 'loadmore', // 用户列表加载更多状态
|
||||
};
|
||||
},
|
||||
|
||||
@@ -459,6 +480,11 @@ export default {
|
||||
// 打开申请人选择
|
||||
openUserSelect() {
|
||||
this.userSelectDialog.visible = true;
|
||||
// 重置分页数据
|
||||
this.userListParams.pageNum = 1;
|
||||
this.userListParams.total = 0;
|
||||
this.userLoadmoreStatus = 'loadmore';
|
||||
this.userSearchKeyword = '';
|
||||
this.loadUserList();
|
||||
},
|
||||
|
||||
@@ -466,6 +492,10 @@ export default {
|
||||
cancelUserSelect() {
|
||||
this.userSelectDialog.visible = false;
|
||||
this.userSearchKeyword = '';
|
||||
// 重置用户列表分页数据
|
||||
this.userListParams.pageNum = 1;
|
||||
this.userListParams.total = 0;
|
||||
this.userLoadmoreStatus = 'loadmore';
|
||||
},
|
||||
|
||||
// 确认申请人选择
|
||||
@@ -505,40 +535,90 @@ export default {
|
||||
},
|
||||
|
||||
// 加载用户列表
|
||||
async loadUserList() {
|
||||
async loadUserList(isLoadMore = false) {
|
||||
if (!isLoadMore) {
|
||||
this.userListLoading = true;
|
||||
this.userListParams.pageNum = 1;
|
||||
} else {
|
||||
this.userLoadmoreStatus = 'loading';
|
||||
}
|
||||
|
||||
try {
|
||||
const res = await request({
|
||||
url: '/system/user/list',
|
||||
url: '/system/user/listByOr',
|
||||
method: 'GET',
|
||||
params: {
|
||||
pageNum: 1,
|
||||
pageSize: 100,
|
||||
pageNum: this.userListParams.pageNum,
|
||||
pageSize: this.userListParams.pageSize,
|
||||
status: '0',
|
||||
userName: this.userSearchKeyword || undefined,
|
||||
nickName: this.userSearchKeyword || undefined,
|
||||
},
|
||||
});
|
||||
|
||||
if (res && res.code === 200) {
|
||||
// 每次加载用户列表时,所有用户默认都不选中
|
||||
this.userList = (res.rows || []).map((user) => ({
|
||||
const newUsers = (res.rows || []).map((user) => ({
|
||||
...user,
|
||||
selected: false,
|
||||
}));
|
||||
console.log('加载用户列表完成,用户数量:', this.userList.length);
|
||||
|
||||
if (isLoadMore) {
|
||||
// 加载更多,追加数据
|
||||
this.userList = [...this.userList, ...newUsers];
|
||||
// 判断是否还有更多数据
|
||||
if (newUsers.length < this.userListParams.pageSize) {
|
||||
this.userLoadmoreStatus = 'nomore';
|
||||
} else {
|
||||
this.userLoadmoreStatus = 'loadmore';
|
||||
}
|
||||
} else {
|
||||
// 首次加载或搜索,替换数据
|
||||
this.userList = newUsers;
|
||||
this.userListParams.total = res.total || 0;
|
||||
// 重置加载更多状态
|
||||
if (this.userList.length >= this.userListParams.total) {
|
||||
this.userLoadmoreStatus = 'nomore';
|
||||
} else {
|
||||
this.userLoadmoreStatus = 'loadmore';
|
||||
}
|
||||
}
|
||||
|
||||
console.log(
|
||||
'加载用户列表完成,当前用户数量:',
|
||||
this.userList.length,
|
||||
'总数量:',
|
||||
this.userListParams.total,
|
||||
);
|
||||
} else {
|
||||
this.userList = [];
|
||||
if (!isLoadMore) {
|
||||
this.userList = [];
|
||||
this.userListParams.total = 0;
|
||||
}
|
||||
uni.showToast({
|
||||
title: res?.msg || '获取用户列表失败',
|
||||
icon: 'none',
|
||||
});
|
||||
if (isLoadMore) {
|
||||
this.userLoadmoreStatus = 'loadmore';
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取用户列表失败:', error);
|
||||
this.userList = [];
|
||||
if (!isLoadMore) {
|
||||
this.userList = [];
|
||||
this.userListParams.total = 0;
|
||||
}
|
||||
uni.showToast({
|
||||
title: '获取用户列表失败',
|
||||
icon: 'none',
|
||||
});
|
||||
if (isLoadMore) {
|
||||
this.userLoadmoreStatus = 'loadmore';
|
||||
}
|
||||
} finally {
|
||||
if (!isLoadMore) {
|
||||
this.userListLoading = false;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -549,10 +629,24 @@ export default {
|
||||
}
|
||||
|
||||
this.userSearchTimer = setTimeout(() => {
|
||||
// 搜索时重置分页数据
|
||||
this.userListParams.pageNum = 1;
|
||||
this.userListParams.total = 0;
|
||||
this.userLoadmoreStatus = 'loadmore';
|
||||
this.loadUserList();
|
||||
}, 500);
|
||||
},
|
||||
|
||||
// 加载更多用户
|
||||
loadMoreUsers() {
|
||||
if (this.userLoadmoreStatus === 'nomore' || this.userLoadmoreStatus === 'loading') {
|
||||
return;
|
||||
}
|
||||
|
||||
this.userListParams.pageNum++;
|
||||
this.loadUserList(true);
|
||||
},
|
||||
|
||||
// 获取头像显示文字(取前两个字符)
|
||||
getAvatarText(nickName) {
|
||||
if (!nickName) return '';
|
||||
@@ -769,6 +863,12 @@ export default {
|
||||
}
|
||||
}
|
||||
|
||||
// 用户列表的loadmore样式
|
||||
::v-deep .u-loadmore {
|
||||
padding: 20rpx 0;
|
||||
font-size: 24rpx;
|
||||
}
|
||||
|
||||
.user-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
@@ -3050,7 +3050,15 @@ export default {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 1. 校验是否需要上传地理位置
|
||||
// 1. 校验请假时间
|
||||
const startTime = new Date(this.form.startTime);
|
||||
const endTime = new Date(this.form.endTime);
|
||||
if (endTime.getTime() <= startTime.getTime()) {
|
||||
uni.showToast({ title: '请假结束时间必须大于开始时间', icon: 'none' });
|
||||
return false;
|
||||
}
|
||||
|
||||
// 2. 校验是否需要上传地理位置
|
||||
if (leaveType.needLocationOnApply === '1') {
|
||||
if (!this.form.leaveLocation) {
|
||||
uni.showToast({ title: '该请假类型需要上传地理位置', icon: 'none' });
|
||||
@@ -3058,7 +3066,7 @@ export default {
|
||||
}
|
||||
}
|
||||
|
||||
// 2. 校验和设置销假状态
|
||||
// 3. 校验和设置销假状态
|
||||
if (leaveType.needCancelForNonLeave === '0' && this.form.isLeaveSchool === '0') {
|
||||
// 非离校请假且该类型不需要销假时,自动设置为不需要销假
|
||||
this.form.needCancel = '0';
|
||||
@@ -3067,7 +3075,7 @@ export default {
|
||||
this.form.needCancel = '1';
|
||||
}
|
||||
|
||||
// 3. 校验是否可以提前请假
|
||||
// 4. 校验是否可以提前请假
|
||||
if (leaveType.canApplyInAdvance === '0') {
|
||||
const now = new Date();
|
||||
now.setHours(23, 59, 59, 999);
|
||||
@@ -3078,7 +3086,7 @@ export default {
|
||||
}
|
||||
}
|
||||
|
||||
// 4. 校验最大申请时长
|
||||
// 5. 校验最大申请时长
|
||||
if (leaveType.maxApplyDuration && leaveType.maxApplyDuration > 0) {
|
||||
const start = new Date(this.form.startTime);
|
||||
const end = new Date(this.form.endTime);
|
||||
|
||||
Reference in new issue
Block a user