一单n制等功能,接入随手拍之前我先提交一版本
This commit is contained in:
@@ -117,7 +117,10 @@ const executorLabel = computed(() => {
|
||||
if (runMode === 4) {
|
||||
const rosterItems = detail.value.rosterItems || []
|
||||
if (rosterItems.length > 0) {
|
||||
return rosterItems.map((item) => item.identityName).filter(Boolean).join('、') || '-'
|
||||
return rosterItems
|
||||
.map((item) => (item.userName || item.identityName || '').trim())
|
||||
.filter(Boolean)
|
||||
.join('、') || '-'
|
||||
}
|
||||
return '-'
|
||||
}
|
||||
|
||||
@@ -46,35 +46,39 @@
|
||||
<up-textarea v-model="formData.selfVerifyContent" placeholder="请输入隐患治理责任单位自行验收的情况"></up-textarea>
|
||||
|
||||
<view class="flex margin-bottom margin-top">
|
||||
<view class="text-gray">下一步流程</view>
|
||||
<view class="text-gray">是否结束销号</view>
|
||||
<view class="text-red">*</view>
|
||||
</view>
|
||||
<view class="static-field">{{ nextStepDisplay }}</view>
|
||||
|
||||
<view class="flex margin-bottom margin-top">
|
||||
<view class="text-gray">下一步处理人</view>
|
||||
<view class="text-red">*</view>
|
||||
</view>
|
||||
<view class="select-trigger" @click="openAssigneePopup">
|
||||
<view class="select-content" :class="{ 'text-gray': !selectedAssigneeName }">
|
||||
{{ selectedAssigneeName || '请选择下一步处理人' }}
|
||||
</view>
|
||||
<text class="cuIcon-unfold"></text>
|
||||
</view>
|
||||
|
||||
<view class="flex margin-bottom margin-top">
|
||||
<view class="text-gray">短信提醒</view>
|
||||
<view class="text-red">*</view>
|
||||
</view>
|
||||
<up-radio-group v-model="sendMsgFlagRadio" placement="row" activeColor="#2667e9">
|
||||
<up-radio-group :key="'hazard-end-' + hazardEndRadio" v-model="hazardEndRadio" placement="row" activeColor="#2667e9">
|
||||
<up-radio
|
||||
label="是"
|
||||
name="yes"
|
||||
label="否"
|
||||
name="no"
|
||||
:customStyle="{ marginRight: '48rpx' }"
|
||||
></up-radio>
|
||||
<up-radio label="否" name="no"></up-radio>
|
||||
<up-radio label="是" name="yes"></up-radio>
|
||||
</up-radio-group>
|
||||
|
||||
<template v-if="!hazardEnd">
|
||||
<view class="flex margin-bottom margin-top">
|
||||
<view class="text-gray">下一步流程</view>
|
||||
<view class="text-red">*</view>
|
||||
</view>
|
||||
<view class="static-field">{{ nextStepDisplay }}</view>
|
||||
|
||||
<view class="flex margin-bottom margin-top">
|
||||
<view class="text-gray">短信提醒</view>
|
||||
<view class="text-red">*</view>
|
||||
</view>
|
||||
<up-radio-group v-model="sendMsgFlagRadio" placement="row" activeColor="#2667e9">
|
||||
<up-radio
|
||||
label="是"
|
||||
name="yes"
|
||||
:customStyle="{ marginRight: '48rpx' }"
|
||||
></up-radio>
|
||||
<up-radio label="否" name="no"></up-radio>
|
||||
</up-radio-group>
|
||||
</template>
|
||||
|
||||
<view class="flex margin-top-xl" style="gap: 20rpx;">
|
||||
<button class="round flex-sub" @click="handleCancel">取消</button>
|
||||
<button class="bg-blue round flex-sub" @click="handleSubmit">提交申请</button>
|
||||
@@ -90,6 +94,7 @@
|
||||
@close="showHazardPicker = false"
|
||||
></up-picker>
|
||||
|
||||
<!-- 暂时注释:下一步处理人弹窗
|
||||
<u-popup :show="showAssigneePopup" mode="bottom" round="20" @close="cancelAssigneeSelect">
|
||||
<view class="user-popup">
|
||||
<view class="popup-header">
|
||||
@@ -118,11 +123,12 @@
|
||||
</view>
|
||||
</view>
|
||||
</u-popup>
|
||||
-->
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, reactive, computed } from 'vue';
|
||||
import { ref, reactive, computed, nextTick } from 'vue';
|
||||
import { onLoad } from '@dcloudio/uni-app';
|
||||
import {
|
||||
applyDelete,
|
||||
@@ -145,6 +151,9 @@
|
||||
const selectableHazardList = ref([]);
|
||||
const selectedDeptName = ref('');
|
||||
const aiGenerating = ref(false);
|
||||
const hazardEndRadio = ref('no');
|
||||
const hazardEnd = computed(() => hazardEndRadio.value === 'yes');
|
||||
const normalizeHazardEndRadio = (value) => (value === 'yes' ? 'yes' : 'no');
|
||||
const sendMsgFlagRadio = ref('yes');
|
||||
const sendMsgFlag = computed(() => sendMsgFlagRadio.value === 'yes');
|
||||
|
||||
@@ -542,10 +551,11 @@
|
||||
uni.showToast({ title: '请选择隐患', icon: 'none' });
|
||||
return;
|
||||
}
|
||||
if (!selectedAssigneeIdentityId.value) {
|
||||
uni.showToast({ title: '请选择下一步处理人', icon: 'none' });
|
||||
return;
|
||||
}
|
||||
// 暂时注释:下一步处理人必选校验
|
||||
// if (!selectedAssigneeIdentityId.value) {
|
||||
// uni.showToast({ title: '请选择下一步处理人', icon: 'none' });
|
||||
// return;
|
||||
// }
|
||||
|
||||
const params = {
|
||||
hazardId: Number(selectedHazardId.value),
|
||||
@@ -555,9 +565,14 @@
|
||||
mainTreatmentContent: formData.mainTreatmentContent || '',
|
||||
treatmentResult: formData.treatmentResult || '',
|
||||
selfVerifyContent: formData.selfVerifyContent || '',
|
||||
assigneeIdentityId: selectedAssigneeIdentityId.value,
|
||||
sendMsgFlag: sendMsgFlag.value
|
||||
hazardEnd: hazardEnd.value,
|
||||
quickApprove: hazardEnd.value ? null : true,
|
||||
sendMsgFlag: hazardEnd.value ? null : sendMsgFlag.value
|
||||
};
|
||||
// 非快速审批时需传 assigneeIdentityId
|
||||
// if (!params.quickApprove) {
|
||||
// params.assigneeIdentityId = selectedAssigneeIdentityId.value;
|
||||
// }
|
||||
|
||||
try {
|
||||
const res = await applyDelete(params);
|
||||
@@ -587,16 +602,19 @@
|
||||
const hazardFromOptions = buildWriteoffHazardFromOptions(options);
|
||||
if (hazardFromOptions?.hazardId) {
|
||||
await applySelectedHazard(hazardFromOptions);
|
||||
return;
|
||||
} else {
|
||||
if (!hazardLocked.value) {
|
||||
await fetchSelectableHazardList();
|
||||
}
|
||||
|
||||
if (taskId.value) {
|
||||
await fetchNextStep();
|
||||
}
|
||||
}
|
||||
|
||||
if (!hazardLocked.value) {
|
||||
await fetchSelectableHazardList();
|
||||
}
|
||||
|
||||
if (taskId.value) {
|
||||
await fetchNextStep();
|
||||
}
|
||||
nextTick(() => {
|
||||
hazardEndRadio.value = normalizeHazardEndRadio(hazardEndRadio.value);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
@@ -196,34 +196,14 @@
|
||||
@close="showHazardPicker = false"
|
||||
></up-picker>
|
||||
|
||||
<u-popup :show="showAssigneePopup" mode="bottom" round="20" @close="cancelAssigneeSelect">
|
||||
<view class="user-popup">
|
||||
<view class="popup-header">
|
||||
<view class="popup-title text-bold">选择下一步处理人</view>
|
||||
<view class="popup-close" @click="cancelAssigneeSelect">×</view>
|
||||
</view>
|
||||
<scroll-view class="user-list-scroll" scroll-y>
|
||||
<view v-if="assigneeLoading" class="empty-tip">加载中...</view>
|
||||
<view v-else-if="assigneeList.length === 0" class="empty-tip">暂无人员数据</view>
|
||||
<template v-else>
|
||||
<view
|
||||
v-for="user in assigneeList"
|
||||
:key="getAssigneeItemKey(user)"
|
||||
class="user-item"
|
||||
:class="{ active: String(pickerAssigneeIdentityId) === String(resolveAssigneeIdentityId(user)) }"
|
||||
@click="onAssigneeItemClick(user)"
|
||||
>
|
||||
<text class="user-item-text">{{ formatAssigneeDisplayName(user) }}</text>
|
||||
<text v-if="String(pickerAssigneeIdentityId) === String(resolveAssigneeIdentityId(user))" class="cuIcon-check text-blue"></text>
|
||||
</view>
|
||||
</template>
|
||||
</scroll-view>
|
||||
<view class="popup-footer">
|
||||
<button class="btn-cancel" @click="cancelAssigneeSelect">取消</button>
|
||||
<button class="btn-confirm bg-blue" @click="confirmAssigneeSelect">确定</button>
|
||||
</view>
|
||||
</view>
|
||||
</u-popup>
|
||||
<FlowAssigneePickerPopup
|
||||
:show="showAssigneePopup"
|
||||
:task-id="taskId"
|
||||
v-model:picker-identity-id="pickerAssigneeIdentityId"
|
||||
v-model:picker-name="pickerAssigneeName"
|
||||
@cancel="cancelAssigneeSelect"
|
||||
@confirm="confirmAssigneeSelect"
|
||||
/>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
@@ -237,9 +217,9 @@
|
||||
getRectifyDetail,
|
||||
generateWriteoffContent,
|
||||
getFlowNextNodes,
|
||||
getDeptUsers,
|
||||
getWriteoffForm
|
||||
} from '@/request/api.js';
|
||||
import FlowAssigneePickerPopup from '@/components/flow/FlowAssigneePickerPopup.vue';
|
||||
import { uploadToCloud, toSubmitFileUrl } from '@/utils/upload.js';
|
||||
import { buildWriteoffHazardFromOptions } from '@/utils/hazardNav.js';
|
||||
|
||||
@@ -278,8 +258,6 @@
|
||||
const pickerAssigneeIdentityId = ref('');
|
||||
const pickerAssigneeName = ref('');
|
||||
const showAssigneePopup = ref(false);
|
||||
const assigneeList = ref([]);
|
||||
const assigneeLoading = ref(false);
|
||||
|
||||
const showCanvas = ref(true);
|
||||
const signatureUrl = ref('');
|
||||
@@ -435,96 +413,19 @@
|
||||
};
|
||||
};
|
||||
|
||||
const getStoredUserInfo = () => {
|
||||
try {
|
||||
const stored = uni.getStorageSync('userInfo');
|
||||
if (!stored) return {};
|
||||
return typeof stored === 'string' ? JSON.parse(stored) : stored;
|
||||
} catch (error) {
|
||||
return {};
|
||||
}
|
||||
};
|
||||
|
||||
const getCurrentDeptId = () => {
|
||||
const userInfo = getStoredUserInfo();
|
||||
const identity = userInfo.userIdentity;
|
||||
if (identity?.deptId != null && identity.deptId !== '') {
|
||||
return String(identity.deptId);
|
||||
}
|
||||
if (userInfo.deptId != null && userInfo.deptId !== '') {
|
||||
return String(userInfo.deptId);
|
||||
}
|
||||
return '';
|
||||
};
|
||||
|
||||
const resolveAssigneeIdentityId = (user) => {
|
||||
if (!user) return '';
|
||||
const id = user.identityId ?? user.userIdentityId ?? user.userId ?? '';
|
||||
return id === '' || id == null ? '' : String(id);
|
||||
};
|
||||
|
||||
const getAssigneeItemKey = (user) => {
|
||||
const identityId = resolveAssigneeIdentityId(user);
|
||||
if (identityId) return `identity-${identityId}`;
|
||||
return `user-${user.userId || user.nickName || ''}`;
|
||||
};
|
||||
|
||||
const formatAssigneeDisplayName = (user) => {
|
||||
if (!user) return '';
|
||||
const name = user.nickName || user.userName || user.name || '';
|
||||
const identityName = user.identityName || '';
|
||||
if (name && identityName) return `${name}(${identityName})`;
|
||||
return name || identityName || '未知人员';
|
||||
};
|
||||
|
||||
const resolveAssigneeDeptUserType = () => {
|
||||
if (formData.approvalResult === 2) return 3;
|
||||
return quickApproveRadio.value === 'yes' ? 2 : 3;
|
||||
};
|
||||
|
||||
const fetchAssigneeList = async () => {
|
||||
const deptId = getCurrentDeptId();
|
||||
if (!deptId) {
|
||||
assigneeList.value = [];
|
||||
const openAssigneePopup = () => {
|
||||
if (!taskId.value) {
|
||||
uni.showToast({ title: '缺少任务ID', icon: 'none' });
|
||||
return;
|
||||
}
|
||||
assigneeLoading.value = true;
|
||||
try {
|
||||
const res = await getDeptUsers(deptId, { type: resolveAssigneeDeptUserType() });
|
||||
if (res.code === 0) {
|
||||
assigneeList.value = res.data || [];
|
||||
} else {
|
||||
assigneeList.value = [];
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取部门人员失败:', error);
|
||||
assigneeList.value = [];
|
||||
} finally {
|
||||
assigneeLoading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
const openAssigneePopup = async () => {
|
||||
pickerAssigneeIdentityId.value = selectedAssigneeIdentityId.value;
|
||||
pickerAssigneeName.value = selectedAssigneeName.value;
|
||||
showAssigneePopup.value = true;
|
||||
await fetchAssigneeList();
|
||||
};
|
||||
|
||||
const onAssigneeItemClick = (user) => {
|
||||
const identityId = resolveAssigneeIdentityId(user);
|
||||
if (!identityId) return;
|
||||
pickerAssigneeIdentityId.value = String(identityId);
|
||||
pickerAssigneeName.value = formatAssigneeDisplayName(user);
|
||||
};
|
||||
|
||||
const confirmAssigneeSelect = () => {
|
||||
if (!pickerAssigneeIdentityId.value) {
|
||||
uni.showToast({ title: '请选择下一步处理人', icon: 'none' });
|
||||
return;
|
||||
}
|
||||
selectedAssigneeIdentityId.value = pickerAssigneeIdentityId.value;
|
||||
selectedAssigneeName.value = pickerAssigneeName.value;
|
||||
const confirmAssigneeSelect = ({ identityId, name }) => {
|
||||
selectedAssigneeIdentityId.value = identityId;
|
||||
selectedAssigneeName.value = name;
|
||||
showAssigneePopup.value = false;
|
||||
};
|
||||
|
||||
@@ -1098,100 +999,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
.user-popup {
|
||||
background: #fff;
|
||||
|
||||
.popup-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 30rpx;
|
||||
border-bottom: 1rpx solid #eee;
|
||||
|
||||
.popup-title {
|
||||
font-size: 32rpx;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.popup-close {
|
||||
font-size: 40rpx;
|
||||
color: #999;
|
||||
line-height: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.user-list-scroll {
|
||||
max-height: 600rpx;
|
||||
padding: 0 30rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.empty-tip {
|
||||
padding: 80rpx 20rpx;
|
||||
text-align: center;
|
||||
color: #909399;
|
||||
font-size: 26rpx;
|
||||
}
|
||||
|
||||
.user-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 24rpx 0;
|
||||
border-bottom: 1rpx solid #f5f5f5;
|
||||
|
||||
&:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
&.active {
|
||||
.user-item-text {
|
||||
color: #2667E9;
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
|
||||
.user-item-text {
|
||||
flex: 1;
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
}
|
||||
}
|
||||
|
||||
.popup-footer {
|
||||
display: flex;
|
||||
gap: 24rpx;
|
||||
padding: 24rpx 30rpx;
|
||||
padding-bottom: calc(24rpx + env(safe-area-inset-bottom));
|
||||
background: #fff;
|
||||
|
||||
button {
|
||||
flex: 1;
|
||||
height: 80rpx;
|
||||
line-height: 80rpx;
|
||||
border-radius: 40rpx;
|
||||
font-size: 30rpx;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
|
||||
&::after {
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
|
||||
.btn-cancel {
|
||||
background: #fff;
|
||||
color: #2667E9;
|
||||
border: 2rpx solid #2667E9;
|
||||
}
|
||||
|
||||
.btn-confirm {
|
||||
color: #fff;
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.signature-action-btn {
|
||||
margin: 0;
|
||||
padding: 0 20rpx;
|
||||
|
||||
@@ -472,9 +472,9 @@
|
||||
<view
|
||||
v-else
|
||||
class="executor-radio"
|
||||
:class="{ 'executor-radio-active': selectedExecutorId === item.userId }"
|
||||
:class="{ 'executor-radio-active': selectedExecutorIdentityId === item.identityId }"
|
||||
>
|
||||
<view v-if="selectedExecutorId === item.userId" class="executor-radio-dot"></view>
|
||||
<view v-if="selectedExecutorIdentityId === item.identityId" class="executor-radio-dot"></view>
|
||||
</view>
|
||||
<view class="executor-info">
|
||||
<text class="executor-name">{{ item.nickName }}</text>
|
||||
@@ -521,7 +521,7 @@ const formData = reactive({
|
||||
modeName: '',
|
||||
selectDeptId: '',
|
||||
selectDeptName: '',
|
||||
executorId: '',
|
||||
executorIdentityId: '',
|
||||
executorNames: '',
|
||||
rosterIdentityIds: [],
|
||||
cycleId: '',
|
||||
@@ -641,7 +641,7 @@ const todayMinDate = computed(() => getTodayTimestamp())
|
||||
const endDateMinDate = computed(() => {
|
||||
if (formData.startDate) {
|
||||
const [year, month, day] = formData.startDate.split('-').map(Number)
|
||||
return new Date(year, month - 1, day + 1).getTime()
|
||||
return new Date(year, month - 1, day).getTime()
|
||||
}
|
||||
return getTodayTimestamp()
|
||||
});
|
||||
@@ -665,7 +665,7 @@ const cycleColumns = ref([['每天一次', '每周一次', '每月一次', '每
|
||||
// 执行人员选择器
|
||||
const showExecutorPopup = ref(false);
|
||||
const executorList = ref([]);
|
||||
const selectedExecutorId = ref(null);
|
||||
const selectedExecutorIdentityId = ref(null);
|
||||
const selectedRosterIdentityIds = ref([]);
|
||||
|
||||
const pageScrollLockStyle = computed(() => {
|
||||
@@ -786,23 +786,55 @@ const onModeConfirm = (e) => {
|
||||
}
|
||||
|
||||
const clearExecutorSelection = () => {
|
||||
formData.executorId = ''
|
||||
formData.executorIdentityId = ''
|
||||
formData.executorNames = ''
|
||||
formData.rosterIdentityIds = []
|
||||
selectedExecutorId.value = null
|
||||
selectedExecutorIdentityId.value = null
|
||||
selectedRosterIdentityIds.value = []
|
||||
}
|
||||
|
||||
const getDeptUsersQueryParams = () => {
|
||||
if (formData.runMode === 4) {
|
||||
return { type: 4 }
|
||||
}
|
||||
if (formData.runMode === 1) {
|
||||
return { type: 5 }
|
||||
}
|
||||
return {}
|
||||
}
|
||||
|
||||
const syncSingleExecutorSelection = (rawValue) => {
|
||||
if (formData.runMode === 4 || rawValue === undefined || rawValue === null || rawValue === '') {
|
||||
return
|
||||
}
|
||||
const num = Number(rawValue)
|
||||
if (Number.isNaN(num)) return
|
||||
const byIdentity = executorList.value.find((user) => Number(user.identityId) === num)
|
||||
if (byIdentity) {
|
||||
selectedExecutorIdentityId.value = byIdentity.identityId
|
||||
formData.executorIdentityId = byIdentity.identityId
|
||||
return
|
||||
}
|
||||
const byUser = executorList.value.find((user) => Number(user.userId) === num)
|
||||
if (byUser) {
|
||||
selectedExecutorIdentityId.value = byUser.identityId
|
||||
formData.executorIdentityId = byUser.identityId
|
||||
}
|
||||
}
|
||||
|
||||
const fetchDeptUsers = async (deptId) => {
|
||||
if (!deptId) {
|
||||
executorList.value = []
|
||||
return
|
||||
}
|
||||
try {
|
||||
const params = formData.runMode === 4 ? { type: 4 } : {}
|
||||
const params = getDeptUsersQueryParams()
|
||||
const res = await getDeptUsers(deptId, params)
|
||||
if (res.code === 0 && res.data) {
|
||||
executorList.value = res.data || []
|
||||
if (formData.runMode === 1) {
|
||||
syncSingleExecutorSelection(formData.executorIdentityId)
|
||||
}
|
||||
} else {
|
||||
executorList.value = []
|
||||
}
|
||||
@@ -813,7 +845,7 @@ const fetchDeptUsers = async (deptId) => {
|
||||
}
|
||||
|
||||
const selectExecutor = (item) => {
|
||||
selectedExecutorId.value = item.userId
|
||||
selectedExecutorIdentityId.value = item.identityId
|
||||
}
|
||||
|
||||
const toggleRosterExecutor = (item) => {
|
||||
@@ -841,12 +873,12 @@ const confirmExecutorSelect = () => {
|
||||
showExecutorPopup.value = false
|
||||
return
|
||||
}
|
||||
if (!selectedExecutorId.value) {
|
||||
if (!selectedExecutorIdentityId.value) {
|
||||
uni.showToast({ title: '请选择执行人员', icon: 'none' })
|
||||
return
|
||||
}
|
||||
const selectedUser = executorList.value.find(u => u.userId === selectedExecutorId.value)
|
||||
formData.executorId = selectedExecutorId.value
|
||||
const selectedUser = executorList.value.find((user) => user.identityId === selectedExecutorIdentityId.value)
|
||||
formData.executorIdentityId = selectedExecutorIdentityId.value
|
||||
formData.executorNames = selectedUser?.nickName || selectedUser?.nickname || ''
|
||||
showExecutorPopup.value = false
|
||||
}
|
||||
@@ -859,7 +891,7 @@ const openExecutorPopup = () => {
|
||||
if (formData.runMode === 4) {
|
||||
selectedRosterIdentityIds.value = [...(formData.rosterIdentityIds || [])]
|
||||
} else {
|
||||
selectedExecutorId.value = formData.executorId || null
|
||||
selectedExecutorIdentityId.value = formData.executorIdentityId || null
|
||||
}
|
||||
fetchDeptUsers(formData.deptId)
|
||||
showExecutorPopup.value = true
|
||||
@@ -933,7 +965,7 @@ const onStartDateConfirm = (e) => {
|
||||
})
|
||||
return
|
||||
}
|
||||
if (formData.endDate && parseDateValue(selectedDate) >= parseDateValue(formData.endDate)) {
|
||||
if (formData.endDate && parseDateValue(selectedDate) > parseDateValue(formData.endDate)) {
|
||||
formData.endDate = ''
|
||||
}
|
||||
formData.startDate = selectedDate
|
||||
@@ -949,8 +981,8 @@ const onEndDateConfirm = (e) => {
|
||||
})
|
||||
return
|
||||
}
|
||||
if (formData.startDate && parseDateValue(selectedDate) <= parseDateValue(formData.startDate)) {
|
||||
uni.showToast({ title: '计划结束日期必须晚于计划开始日期', icon: 'none' })
|
||||
if (formData.startDate && parseDateValue(selectedDate) < parseDateValue(formData.startDate)) {
|
||||
uni.showToast({ title: '计划结束日期不能早于计划开始日期', icon: 'none' })
|
||||
return
|
||||
}
|
||||
formData.endDate = selectedDate
|
||||
@@ -1466,7 +1498,7 @@ const handleSave = async () => {
|
||||
uni.showToast({ title: '请选择模式', icon: 'none' });
|
||||
return;
|
||||
}
|
||||
if (formData.runMode === 1 && !formData.executorId) {
|
||||
if (formData.runMode === 1 && !formData.executorIdentityId) {
|
||||
uni.showToast({ title: '请选择执行人员', icon: 'none' });
|
||||
return;
|
||||
}
|
||||
@@ -1482,8 +1514,8 @@ const handleSave = async () => {
|
||||
uni.showToast({ title: '请选择计划日期', icon: 'none' });
|
||||
return;
|
||||
}
|
||||
if (parseDateValue(formData.endDate) <= parseDateValue(formData.startDate)) {
|
||||
uni.showToast({ title: '计划结束日期必须晚于计划开始日期', icon: 'none' });
|
||||
if (parseDateValue(formData.endDate) < parseDateValue(formData.startDate)) {
|
||||
uni.showToast({ title: '计划结束日期不能早于计划开始日期', icon: 'none' });
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1536,8 +1568,8 @@ const handleSave = async () => {
|
||||
planEndTime: `${formData.endDate} 00:00:00`
|
||||
};
|
||||
|
||||
if (formData.runMode === 1 && formData.executorId) {
|
||||
params.executorId = formData.executorId;
|
||||
if (formData.runMode === 1 && formData.executorIdentityId) {
|
||||
params.executorIdentityId = formData.executorIdentityId;
|
||||
}
|
||||
|
||||
if (formData.runMode === 4 && formData.rosterIdentityIds?.length) {
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
class="round cu-btn bg-blue" @click="Rectification(item)">立即整改</button>
|
||||
<button v-if="item.statusName === '待验收' && item.canEdit"
|
||||
class="round cu-btn light bg-blue" @click="editRectification(item)">编辑整改信息</button>
|
||||
<button v-if="canShowAcceptanceButton(item, userRole)"
|
||||
<button v-if="canShowAcceptanceButton(item)"
|
||||
class="round cu-btn bg-blue" @click="acceptance(item)">立即验收</button>
|
||||
<button v-if="item.statusName === '待交办'"
|
||||
class="round cu-btn bg-blue" @click="assignHazard(item)">隐患交办</button>
|
||||
|
||||
@@ -64,23 +64,44 @@
|
||||
</view>
|
||||
<up-upload :fileList="fileList1" @afterRead="afterRead" @delete="deletePic" name="1" multiple imageMode="aspectFill" :maxCount="10"></up-upload>
|
||||
|
||||
<view v-if="formData.result === 1" class="flex margin-bottom margin-top">
|
||||
<view class="text-gray">是否快速审批</view>
|
||||
<view class="text-red">*</view>
|
||||
</view>
|
||||
<view v-if="formData.result === 1" class="flex" style="gap: 20rpx;">
|
||||
<button :class="['result-btn', formData.quickApproveRadio === 'yes' ? 'active' : '']" @click="onQuickApproveChange('yes')">是</button>
|
||||
<button :class="['result-btn', formData.quickApproveRadio === 'no' ? 'active' : '']" @click="onQuickApproveChange('no')">否</button>
|
||||
</view>
|
||||
<template v-if="formData.result === 1">
|
||||
<view class="flex margin-bottom margin-top">
|
||||
<view class="text-gray">是否结束隐患验收</view>
|
||||
<view class="text-red">*</view>
|
||||
</view>
|
||||
<up-radio-group :key="'hazard-end-' + hazardEndRadio" v-model="hazardEndRadio" placement="row" activeColor="#2667e9" @change="onHazardEndChange">
|
||||
<up-radio
|
||||
label="否"
|
||||
name="no"
|
||||
:customStyle="{ marginRight: '48rpx' }"
|
||||
></up-radio>
|
||||
<up-radio label="是" name="yes"></up-radio>
|
||||
</up-radio-group>
|
||||
</template>
|
||||
|
||||
<template v-if="formData.result === 1 && hazardEndRadio !== 'yes'">
|
||||
<view class="flex margin-bottom margin-top">
|
||||
<view class="text-gray">是否快速审批</view>
|
||||
<view class="text-red">*</view>
|
||||
</view>
|
||||
<up-radio-group :key="'quick-approve-' + quickApproveRadio" v-model="quickApproveRadio" placement="row" activeColor="#2667e9" @change="onQuickApproveChange">
|
||||
<up-radio
|
||||
label="是"
|
||||
name="yes"
|
||||
:customStyle="{ marginRight: '48rpx' }"
|
||||
></up-radio>
|
||||
<up-radio label="否" name="no"></up-radio>
|
||||
</up-radio-group>
|
||||
</template>
|
||||
|
||||
<!-- 隐藏的 Canvas,用于渲染防作弊时间戳水印 -->
|
||||
<canvas canvas-id="watermarkCanvas" :width="canvasWidth" :height="canvasHeight" :style="{ width: canvasWidth + 'px', height: canvasHeight + 'px', position: 'fixed', left: '-9999px', top: '-9999px' }"></canvas>
|
||||
|
||||
<view class="flex margin-bottom margin-top">
|
||||
<view v-if="!(formData.result === 1 && hazardEndRadio === 'yes')" class="flex margin-bottom margin-top">
|
||||
<view class="text-gray">下一步流程</view>
|
||||
<view class="text-red">*</view>
|
||||
</view>
|
||||
<view class="static-field">{{ nextStepDisplay }}</view>
|
||||
<view v-if="!(formData.result === 1 && hazardEndRadio === 'yes')" class="static-field">{{ nextStepDisplay }}</view>
|
||||
|
||||
<template v-if="showAssigneeSection">
|
||||
<view class="flex margin-bottom margin-top">
|
||||
@@ -96,34 +117,14 @@
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<u-popup :show="showAssigneePopup" mode="bottom" round="20" @close="cancelAssigneeSelect">
|
||||
<view class="user-popup">
|
||||
<view class="popup-header">
|
||||
<view class="popup-title text-bold">选择下一步处理人</view>
|
||||
<view class="popup-close" @click="cancelAssigneeSelect">×</view>
|
||||
</view>
|
||||
<scroll-view class="user-list-scroll" scroll-y>
|
||||
<view v-if="assigneeLoading" class="empty-tip">加载中...</view>
|
||||
<view v-else-if="assigneeList.length === 0" class="empty-tip">暂无人员数据</view>
|
||||
<template v-else>
|
||||
<view
|
||||
v-for="user in assigneeList"
|
||||
:key="getAssigneeItemKey(user)"
|
||||
class="user-item"
|
||||
:class="{ active: String(pickerAssigneeIdentityId) === String(resolveAssigneeIdentityId(user)) }"
|
||||
@click="onAssigneeItemClick(user)"
|
||||
>
|
||||
<text class="user-item-text">{{ formatAssigneeDisplayName(user) }}</text>
|
||||
<text v-if="String(pickerAssigneeIdentityId) === String(resolveAssigneeIdentityId(user))" class="cuIcon-check text-blue"></text>
|
||||
</view>
|
||||
</template>
|
||||
</scroll-view>
|
||||
<view class="popup-footer">
|
||||
<button class="btn-cancel" @click="cancelAssigneeSelect">取消</button>
|
||||
<button class="btn-confirm bg-blue" @click="confirmAssigneeSelect">确定</button>
|
||||
</view>
|
||||
</view>
|
||||
</u-popup>
|
||||
<FlowAssigneePickerPopup
|
||||
:show="showAssigneePopup"
|
||||
:task-id="taskId"
|
||||
v-model:picker-identity-id="pickerAssigneeIdentityId"
|
||||
v-model:picker-name="pickerAssigneeName"
|
||||
@cancel="cancelAssigneeSelect"
|
||||
@confirm="confirmAssigneeSelect"
|
||||
/>
|
||||
|
||||
<!-- 短信提醒(暂不使用)
|
||||
<view class="flex margin-bottom margin-top">
|
||||
@@ -193,7 +194,8 @@
|
||||
<script setup>
|
||||
import { ref, reactive, computed, nextTick, getCurrentInstance } from 'vue';
|
||||
import { onLoad, onHide } from '@dcloudio/uni-app';
|
||||
import { acceptanceRectification, getHiddenDangerDetail, getRectifyDetail, getFlowNextNodes, getDeptUsers } from '@/request/api.js';
|
||||
import { acceptanceRectification, getHiddenDangerDetail, getRectifyDetail, getFlowNextNodes } from '@/request/api.js';
|
||||
import FlowAssigneePickerPopup from '@/components/flow/FlowAssigneePickerPopup.vue';
|
||||
import { toImageUrl } from '@/request/request.js';
|
||||
import { buildDraftKey, buildDraftKeyCompact, DRAFT_NS } from '@/utils/draftCache.js';
|
||||
import { useDraftCache } from '@/utils/useDraftCache.js';
|
||||
@@ -274,40 +276,22 @@
|
||||
if (formData.result === 2) {
|
||||
return { pass: false };
|
||||
}
|
||||
if (hazardEndRadio.value === 'yes') {
|
||||
return { pass: true, hazardEnd: true };
|
||||
}
|
||||
return {
|
||||
pass: true,
|
||||
quickApprove: formData.quickApproveRadio === 'yes'
|
||||
quickApprove: quickApproveRadio.value === 'yes'
|
||||
};
|
||||
};
|
||||
|
||||
const getStoredUserInfo = () => {
|
||||
try {
|
||||
const stored = uni.getStorageSync('userInfo');
|
||||
if (!stored) return {};
|
||||
return typeof stored === 'string' ? JSON.parse(stored) : stored;
|
||||
} catch (error) {
|
||||
return {};
|
||||
}
|
||||
};
|
||||
|
||||
const getCurrentDeptId = () => {
|
||||
const userInfo = getStoredUserInfo();
|
||||
const identity = userInfo.userIdentity;
|
||||
if (identity?.deptId != null && identity.deptId !== '') {
|
||||
return String(identity.deptId);
|
||||
}
|
||||
if (userInfo.deptId != null && userInfo.deptId !== '') {
|
||||
return String(userInfo.deptId);
|
||||
}
|
||||
return '';
|
||||
};
|
||||
|
||||
const rectifierDisplayName = computed(() => rectifyData.rectifierName?.trim() || '暂无');
|
||||
|
||||
// 通过且快速审批时无需选择下一步处理人
|
||||
// 通过且快速审批时无需选择下一步处理人;结束验收时也不显示
|
||||
const showAssigneeSection = computed(() => {
|
||||
if (formData.result === 1 && hazardEndRadio.value === 'yes') return false;
|
||||
if (formData.result === 2) return true;
|
||||
if (formData.result === 1 && formData.quickApproveRadio === 'no') return true;
|
||||
if (formData.result === 1 && quickApproveRadio.value === 'no') return true;
|
||||
return false;
|
||||
});
|
||||
|
||||
@@ -316,76 +300,20 @@
|
||||
const pickerAssigneeIdentityId = ref('');
|
||||
const pickerAssigneeName = ref('');
|
||||
const showAssigneePopup = ref(false);
|
||||
const assigneeList = ref([]);
|
||||
const assigneeLoading = ref(false);
|
||||
|
||||
const resolveAssigneeIdentityId = (user) => {
|
||||
if (!user) return '';
|
||||
const id = user.identityId ?? user.userIdentityId ?? user.userId ?? '';
|
||||
return id === '' || id == null ? '' : String(id);
|
||||
};
|
||||
|
||||
const getAssigneeItemKey = (user) => {
|
||||
const identityId = resolveAssigneeIdentityId(user);
|
||||
if (identityId) return `identity-${identityId}`;
|
||||
return `user-${user.userId || user.nickName || ''}`;
|
||||
};
|
||||
|
||||
const formatAssigneeDisplayName = (user) => {
|
||||
if (!user) return '';
|
||||
const name = user.nickName || user.userName || user.name || '';
|
||||
const identityName = user.identityName || '';
|
||||
if (name && identityName) return `${name}(${identityName})`;
|
||||
return name || identityName || '未知人员';
|
||||
};
|
||||
|
||||
const resolveAssigneeDeptUserType = () => (
|
||||
formData.quickApproveRadio === 'yes' ? 2 : 3
|
||||
);
|
||||
|
||||
const fetchAssigneeList = async () => {
|
||||
const deptId = getCurrentDeptId();
|
||||
if (!deptId) {
|
||||
assigneeList.value = [];
|
||||
const openAssigneePopup = () => {
|
||||
if (!taskId.value) {
|
||||
uni.showToast({ title: '缺少任务ID', icon: 'none' });
|
||||
return;
|
||||
}
|
||||
assigneeLoading.value = true;
|
||||
try {
|
||||
const res = await getDeptUsers(deptId, { type: resolveAssigneeDeptUserType() });
|
||||
if (res.code === 0) {
|
||||
assigneeList.value = res.data || [];
|
||||
} else {
|
||||
assigneeList.value = [];
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取部门人员失败:', error);
|
||||
assigneeList.value = [];
|
||||
} finally {
|
||||
assigneeLoading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
const openAssigneePopup = async () => {
|
||||
pickerAssigneeIdentityId.value = selectedAssigneeIdentityId.value;
|
||||
pickerAssigneeName.value = selectedAssigneeName.value;
|
||||
showAssigneePopup.value = true;
|
||||
await fetchAssigneeList();
|
||||
};
|
||||
|
||||
const onAssigneeItemClick = (user) => {
|
||||
const identityId = resolveAssigneeIdentityId(user);
|
||||
if (!identityId) return;
|
||||
pickerAssigneeIdentityId.value = String(identityId);
|
||||
pickerAssigneeName.value = formatAssigneeDisplayName(user);
|
||||
};
|
||||
|
||||
const confirmAssigneeSelect = () => {
|
||||
if (!pickerAssigneeIdentityId.value) {
|
||||
uni.showToast({ title: '请选择下一步处理人', icon: 'none' });
|
||||
return;
|
||||
}
|
||||
selectedAssigneeIdentityId.value = pickerAssigneeIdentityId.value;
|
||||
selectedAssigneeName.value = pickerAssigneeName.value;
|
||||
const confirmAssigneeSelect = ({ identityId, name }) => {
|
||||
selectedAssigneeIdentityId.value = identityId;
|
||||
selectedAssigneeName.value = name;
|
||||
showAssigneePopup.value = false;
|
||||
};
|
||||
|
||||
@@ -396,22 +324,36 @@
|
||||
const onResultChange = (result) => {
|
||||
formData.result = result;
|
||||
if (result === 2) {
|
||||
hazardEndRadio.value = 'no';
|
||||
selectedAssigneeIdentityId.value = '';
|
||||
selectedAssigneeName.value = '';
|
||||
} else if (!formData.quickApproveRadio) {
|
||||
formData.quickApproveRadio = 'yes';
|
||||
} else if (!quickApproveRadio.value) {
|
||||
quickApproveRadio.value = 'yes';
|
||||
}
|
||||
fetchNextStep();
|
||||
};
|
||||
|
||||
const onQuickApproveChange = (value) => {
|
||||
formData.quickApproveRadio = value;
|
||||
const onHazardEndChange = (value) => {
|
||||
if (value === 'yes') {
|
||||
quickApproveRadio.value = 'yes';
|
||||
selectedAssigneeIdentityId.value = '';
|
||||
selectedAssigneeName.value = '';
|
||||
} else {
|
||||
fetchNextStep();
|
||||
}
|
||||
};
|
||||
|
||||
const onQuickApproveChange = () => {
|
||||
selectedAssigneeIdentityId.value = '';
|
||||
selectedAssigneeName.value = '';
|
||||
fetchNextStep();
|
||||
};
|
||||
|
||||
const fetchNextStep = async () => {
|
||||
if (formData.result === 1 && hazardEndRadio.value === 'yes') {
|
||||
nextStepName.value = '';
|
||||
return;
|
||||
}
|
||||
nextStepLoading.value = true;
|
||||
try {
|
||||
const currentTaskId = taskId.value;
|
||||
@@ -478,11 +420,19 @@
|
||||
// 整改附件
|
||||
const rectifyAttachments = ref([]);
|
||||
|
||||
// 是否结束隐患验收
|
||||
const hazardEndRadio = ref('no');
|
||||
const hazardEnd = computed(() => hazardEndRadio.value === 'yes');
|
||||
const normalizeHazardEndRadio = (value) => (value === 'yes' ? 'yes' : 'no');
|
||||
|
||||
// 是否快速审批
|
||||
const quickApproveRadio = ref('yes');
|
||||
const normalizeQuickApproveRadio = (value) => (value === 'no' ? 'no' : 'yes');
|
||||
|
||||
// 表单数据
|
||||
const formData = reactive({
|
||||
result: 1, // 验收结果 1.通过 2.不通过
|
||||
verifyRemark: '', // 验收备注
|
||||
quickApproveRadio: 'yes' // 是否快速审批 yes/no,仅通过时有效
|
||||
verifyRemark: '' // 验收备注
|
||||
});
|
||||
|
||||
const fileList1 = ref([]);
|
||||
@@ -564,7 +514,8 @@
|
||||
formData: {
|
||||
result: formData.result,
|
||||
verifyRemark: formData.verifyRemark,
|
||||
quickApproveRadio: formData.quickApproveRadio
|
||||
hazardEndRadio: hazardEndRadio.value,
|
||||
quickApproveRadio: quickApproveRadio.value
|
||||
},
|
||||
selectedAssigneeIdentityId: selectedAssigneeIdentityId.value,
|
||||
selectedAssigneeName: selectedAssigneeName.value,
|
||||
@@ -581,7 +532,8 @@
|
||||
const form = data.formData || {};
|
||||
formData.result = form.result !== undefined ? form.result : 1;
|
||||
formData.verifyRemark = form.verifyRemark || '';
|
||||
formData.quickApproveRadio = form.quickApproveRadio === 'no' ? 'no' : 'yes';
|
||||
hazardEndRadio.value = normalizeHazardEndRadio(form.hazardEndRadio ?? (form.hazardEnd === true ? 'yes' : 'no'));
|
||||
quickApproveRadio.value = normalizeQuickApproveRadio(form.quickApproveRadio);
|
||||
selectedAssigneeIdentityId.value = data.selectedAssigneeIdentityId || '';
|
||||
selectedAssigneeName.value = data.selectedAssigneeName || '';
|
||||
fileList1.value = data.fileList1 || [];
|
||||
@@ -602,7 +554,8 @@
|
||||
clearForm: () => {
|
||||
formData.result = 1;
|
||||
formData.verifyRemark = '';
|
||||
formData.quickApproveRadio = 'yes';
|
||||
hazardEndRadio.value = 'no';
|
||||
quickApproveRadio.value = 'yes';
|
||||
selectedAssigneeIdentityId.value = '';
|
||||
selectedAssigneeName.value = '';
|
||||
fileList1.value = [];
|
||||
@@ -636,7 +589,8 @@
|
||||
bindAutoSave(() => [
|
||||
formData.result,
|
||||
formData.verifyRemark,
|
||||
formData.quickApproveRadio,
|
||||
hazardEndRadio.value,
|
||||
quickApproveRadio.value,
|
||||
selectedAssigneeIdentityId.value,
|
||||
selectedAssigneeName.value,
|
||||
fileList1.value,
|
||||
@@ -772,11 +726,14 @@
|
||||
};
|
||||
|
||||
const validateFormBeforeSubmit = () => {
|
||||
if (formData.result === 1 && !formData.quickApproveRadio) {
|
||||
if (formData.result === 1 && hazardEndRadio.value === 'yes') {
|
||||
return true;
|
||||
}
|
||||
if (formData.result === 1 && !quickApproveRadio.value) {
|
||||
uni.showToast({ title: '请选择是否快速审批', icon: 'none' });
|
||||
return false;
|
||||
}
|
||||
if (formData.result === 1 && formData.quickApproveRadio === 'no' && !selectedAssigneeIdentityId.value) {
|
||||
if (formData.result === 1 && quickApproveRadio.value === 'no' && !selectedAssigneeIdentityId.value) {
|
||||
uni.showToast({ title: '请选择下一步处理人', icon: 'none' });
|
||||
return false;
|
||||
}
|
||||
@@ -854,14 +811,19 @@
|
||||
result: formData.result,
|
||||
verifyRemark: formData.verifyRemark || '',
|
||||
attachments: attachments,
|
||||
signPath: signatureServerPath.value || '' // 电子签名路径
|
||||
signPath: signatureServerPath.value || '', // 电子签名路径
|
||||
hazardEnd: formData.result === 1 && hazardEndRadio.value === 'yes'
|
||||
// sendMsgFlag: sendMsgFlag.value
|
||||
};
|
||||
|
||||
if (formData.result === 1) {
|
||||
params.quickApprove = formData.quickApproveRadio === 'yes';
|
||||
if (formData.quickApproveRadio === 'no') {
|
||||
params.assigneeIdentityId = selectedAssigneeIdentityId.value;
|
||||
if (hazardEndRadio.value === 'yes') {
|
||||
params.quickApprove = null;
|
||||
} else {
|
||||
params.quickApprove = quickApproveRadio.value === 'yes';
|
||||
if (quickApproveRadio.value === 'no') {
|
||||
params.assigneeIdentityId = selectedAssigneeIdentityId.value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1035,6 +997,10 @@
|
||||
|
||||
// 页面打开时自动恢复草稿
|
||||
restoreDraft();
|
||||
nextTick(() => {
|
||||
hazardEndRadio.value = normalizeHazardEndRadio(hazardEndRadio.value);
|
||||
quickApproveRadio.value = normalizeQuickApproveRadio(quickApproveRadio.value);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -1091,100 +1057,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
.user-popup {
|
||||
background: #fff;
|
||||
|
||||
.popup-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 30rpx;
|
||||
border-bottom: 1rpx solid #eee;
|
||||
|
||||
.popup-title {
|
||||
font-size: 32rpx;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.popup-close {
|
||||
font-size: 40rpx;
|
||||
color: #999;
|
||||
line-height: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.user-list-scroll {
|
||||
max-height: 600rpx;
|
||||
padding: 0 30rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.empty-tip {
|
||||
padding: 80rpx 20rpx;
|
||||
text-align: center;
|
||||
color: #909399;
|
||||
font-size: 26rpx;
|
||||
}
|
||||
|
||||
.user-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 24rpx 0;
|
||||
border-bottom: 1rpx solid #f5f5f5;
|
||||
|
||||
&:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
&.active {
|
||||
.user-item-text {
|
||||
color: #2667E9;
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
|
||||
.user-item-text {
|
||||
flex: 1;
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
}
|
||||
}
|
||||
|
||||
.popup-footer {
|
||||
display: flex;
|
||||
gap: 24rpx;
|
||||
padding: 24rpx 30rpx;
|
||||
padding-bottom: calc(24rpx + env(safe-area-inset-bottom));
|
||||
background: #fff;
|
||||
|
||||
button {
|
||||
flex: 1;
|
||||
height: 80rpx;
|
||||
line-height: 80rpx;
|
||||
border-radius: 40rpx;
|
||||
font-size: 30rpx;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
|
||||
&::after {
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
|
||||
.btn-cancel {
|
||||
background: #fff;
|
||||
color: #2667E9;
|
||||
border: 2rpx solid #2667E9;
|
||||
}
|
||||
|
||||
.btn-confirm {
|
||||
color: #fff;
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 签名相关样式
|
||||
.signature-box {
|
||||
width: 100%;
|
||||
|
||||
@@ -209,30 +209,45 @@
|
||||
></canvas>
|
||||
|
||||
<view class="form-label margin-bottom margin-top">
|
||||
<view class="text-gray">下一步流程</view>
|
||||
<view class="text-gray">是否结束隐患整改</view>
|
||||
<view class="text-red">*</view>
|
||||
</view>
|
||||
<view class="static-field">{{ nextStepDisplay }}</view>
|
||||
|
||||
<view class="form-label margin-bottom margin-top">
|
||||
<view class="text-gray">下一步处理人</view>
|
||||
<view class="text-red">*</view>
|
||||
</view>
|
||||
<view class="static-field">管理人员</view>
|
||||
|
||||
<view class="form-label margin-bottom margin-top">
|
||||
<view class="text-gray">短信提醒</view>
|
||||
<view class="text-red">*</view>
|
||||
</view>
|
||||
<up-radio-group v-model="sendMsgFlagRadio" placement="row" activeColor="#2667e9">
|
||||
<up-radio-group :key="'hazard-end-' + hazardEndRadio" v-model="hazardEndRadio" placement="row" activeColor="#2667e9">
|
||||
<up-radio
|
||||
label="是"
|
||||
name="yes"
|
||||
label="否"
|
||||
name="no"
|
||||
:customStyle="{ marginRight: '48rpx' }"
|
||||
></up-radio>
|
||||
<up-radio label="否" name="no"></up-radio>
|
||||
<up-radio label="是" name="yes"></up-radio>
|
||||
</up-radio-group>
|
||||
|
||||
<template v-if="!hazardEnd">
|
||||
<view class="form-label margin-bottom margin-top">
|
||||
<view class="text-gray">下一步流程</view>
|
||||
<view class="text-red">*</view>
|
||||
</view>
|
||||
<view class="static-field">{{ nextStepDisplay }}</view>
|
||||
|
||||
<view class="form-label margin-bottom margin-top">
|
||||
<view class="text-gray">下一步处理人</view>
|
||||
<view class="text-red">*</view>
|
||||
</view>
|
||||
<view class="static-field">管理人员</view>
|
||||
|
||||
<view class="form-label margin-bottom margin-top">
|
||||
<view class="text-gray">短信提醒</view>
|
||||
<view class="text-red">*</view>
|
||||
</view>
|
||||
<up-radio-group v-model="sendMsgFlagRadio" placement="row" activeColor="#2667e9">
|
||||
<up-radio
|
||||
label="是"
|
||||
name="yes"
|
||||
:customStyle="{ marginRight: '48rpx' }"
|
||||
></up-radio>
|
||||
<up-radio label="否" name="no"></up-radio>
|
||||
</up-radio-group>
|
||||
</template>
|
||||
|
||||
<!-- 电子签名(表单最底部) -->
|
||||
<view class="form-label margin-bottom margin-top flex justify-between align-center" style="width: 100%;">
|
||||
<view class="flex align-center">
|
||||
@@ -541,6 +556,11 @@
|
||||
const rectifyTimeValue = ref(Date.now());
|
||||
const selectedRectifyTime = ref('');
|
||||
|
||||
// 是否结束隐患整改
|
||||
const hazardEndRadio = ref('no');
|
||||
const hazardEnd = computed(() => hazardEndRadio.value === 'yes');
|
||||
const normalizeHazardEndRadio = (value) => (value === 'yes' ? 'yes' : 'no');
|
||||
|
||||
// 短信提醒
|
||||
const sendMsgFlagRadio = ref('yes');
|
||||
const sendMsgFlag = computed(() => sendMsgFlagRadio.value === 'yes');
|
||||
@@ -946,7 +966,8 @@
|
||||
memberIds: selectedIdentityIds.value.map((id) => Number(id)),
|
||||
rectifyTime: selectedRectifyTime.value || formatDateValue(rectifyTimeValue.value),
|
||||
signPath: signatureServerPath.value || '',
|
||||
sendMsgFlag: sendMsgFlag.value
|
||||
hazardEnd: hazardEnd.value,
|
||||
sendMsgFlag: hazardEnd.value ? null : sendMsgFlag.value
|
||||
};
|
||||
if (selectedDeadlineDate.value) {
|
||||
params.deadline = selectedDeadlineDate.value;
|
||||
@@ -1354,7 +1375,8 @@
|
||||
signatureLocalPath: signatureLocalPath.value,
|
||||
showCanvas: showCanvas.value,
|
||||
signaturePaths: signaturePaths.value,
|
||||
sendMsgFlagRadio: sendMsgFlagRadio.value
|
||||
sendMsgFlagRadio: sendMsgFlagRadio.value,
|
||||
hazardEndRadio: hazardEndRadio.value
|
||||
}),
|
||||
hasContent: rectifyDraftHasContent,
|
||||
applyPayload: (data) => {
|
||||
@@ -1375,6 +1397,7 @@
|
||||
showCanvas.value = false;
|
||||
}
|
||||
sendMsgFlagRadio.value = data.sendMsgFlagRadio === 'no' ? 'no' : 'yes';
|
||||
hazardEndRadio.value = normalizeHazardEndRadio(data.hazardEndRadio ?? (data.hazardEnd === true ? 'yes' : 'no'));
|
||||
},
|
||||
clearForm: () => {
|
||||
formData.rectifyPlan = '';
|
||||
@@ -1393,6 +1416,7 @@
|
||||
signatureRef.value.clear();
|
||||
}
|
||||
sendMsgFlagRadio.value = 'yes';
|
||||
hazardEndRadio.value = 'no';
|
||||
},
|
||||
canSave: () => !!(hazardId.value || rectifyId.value),
|
||||
onAfterRestore: (data) => {
|
||||
@@ -1422,7 +1446,8 @@
|
||||
signatureLocalPath.value,
|
||||
showCanvas.value,
|
||||
signaturePaths.value,
|
||||
sendMsgFlagRadio.value
|
||||
sendMsgFlagRadio.value,
|
||||
hazardEndRadio.value
|
||||
]);
|
||||
|
||||
onHide(() => {
|
||||
@@ -1469,6 +1494,10 @@
|
||||
initRectifyTimeDefault();
|
||||
}
|
||||
|
||||
nextTick(() => {
|
||||
hazardEndRadio.value = normalizeHazardEndRadio(hazardEndRadio.value);
|
||||
});
|
||||
|
||||
// 从列表页带入的限定整改时间(待整改交办 deadline)
|
||||
if (options.deadline) {
|
||||
applyDeadlineFromOptions(options.deadline);
|
||||
|
||||
@@ -45,11 +45,20 @@
|
||||
</view>
|
||||
</view>
|
||||
<!-- 我的检查计划 -->
|
||||
<view v-if="!isApprovalRole" class="bg-white margin-top radius" style="padding: 40rpx; margin-left: -30rpx; margin-right: -30rpx;">
|
||||
<view class="flex margin-bottom-xl align-center justify-between">
|
||||
<view v-if="showCheckPlanSection" class="bg-white margin-top radius" style="padding: 40rpx; margin-left: -30rpx; margin-right: -30rpx;">
|
||||
<view class="flex margin-bottom align-center justify-between">
|
||||
<view class="text-bold margin-left-xs" style="font-size: 32rpx;">我的检查计划</view>
|
||||
<!-- <button class="cu-btn round sm line-blue inspect-list-btn" @click="goInspectList">检查列表</button> -->
|
||||
</view>
|
||||
<view class="danger-tab-list plan-tab-list">
|
||||
<view
|
||||
class="danger-tab-item"
|
||||
:class="{ 'danger-tab-active': activePlanTab === index }"
|
||||
v-for="(tab, index) in planTabs"
|
||||
:key="tab.value"
|
||||
@click="switchPlanTab(index)"
|
||||
>{{ tab.label }}</view>
|
||||
</view>
|
||||
<!-- 无数据提示 -->
|
||||
<view v-if="checkPlanData.length === 0" class="text-center text-gray padding">
|
||||
暂无检查计划
|
||||
@@ -184,7 +193,7 @@
|
||||
class="round cu-btn bg-blue" @click.stop="goRectification(item)">立即整改</button>
|
||||
<button v-if="item.statusName === '待验收' && item.canEdit"
|
||||
class="round cu-btn light bg-blue" @click.stop="editRectification(item)">编辑整改信息</button>
|
||||
<button v-if="canShowAcceptanceButton(item, currentRoleKey)"
|
||||
<button v-if="canShowAcceptanceButton(item)"
|
||||
class="round cu-btn bg-blue" @click.stop="goAcceptance(item)">立即验收</button>
|
||||
<button v-if="item.statusName === '待交办'"
|
||||
class="round cu-btn bg-blue" @click.stop="assignHazard(item)">隐患交办</button>
|
||||
@@ -266,7 +275,7 @@
|
||||
import { getProfileDetail } from '@/request/three_one_api/info.js';
|
||||
import { onLoad, onShow, onReachBottom } from '@dcloudio/uni-app';
|
||||
import { toImageUrl } from '@/request/request.js';
|
||||
import { applyProfileToUserInfo, applyStoredUserInfo, resolveIdentityName, resolveUserIdentityRoleKey } from '@/utils/userInfo.js';
|
||||
import { applyProfileToUserInfo, applyStoredUserInfo, resolveIdentityName, resolveUserIdentityRoleKey, isGovernmentEntityAdmin } from '@/utils/userInfo.js';
|
||||
import {
|
||||
buildRectificationUrl,
|
||||
buildEditRectificationUrl,
|
||||
@@ -302,6 +311,7 @@
|
||||
const currentRoleKey = computed(() => resolveUserIdentityRoleKey(userInfo));
|
||||
|
||||
const isApprovalRole = computed(() => currentRoleKey.value === 'approval');
|
||||
const showCheckPlanSection = computed(() => !isApprovalRole.value && currentRoleKey.value !== 'manage');
|
||||
|
||||
// 展示用身份名称(兼容接口字段与本地缓存)
|
||||
const displayIdentityName = computed(() => {
|
||||
@@ -375,17 +385,22 @@
|
||||
|
||||
// common角色只能看到的菜单名称
|
||||
const commonMenuNames = ['隐患排查', '隐患销号'];
|
||||
|
||||
// 政府类型管理员(organizationEntityType=0/1 且 admin/manage)隐藏的菜单
|
||||
const govEntityAdminHiddenMenuNames = ['成员管理', '信息填报', '区域设置', '证件管理'];
|
||||
|
||||
// 根据角色动态展示菜单
|
||||
// 根据角色与组织实体类型动态展示菜单
|
||||
const infoList = computed(() => {
|
||||
let list = allMenuList;
|
||||
if (currentRoleKey.value === 'approval') {
|
||||
return allMenuList.filter(item => item.name === '隐患排查');
|
||||
list = list.filter(item => item.name === '隐患排查');
|
||||
} else if (currentRoleKey.value === 'common') {
|
||||
list = list.filter(item => commonMenuNames.includes(item.name));
|
||||
}
|
||||
if (currentRoleKey.value === 'common') {
|
||||
return allMenuList.filter(item => commonMenuNames.includes(item.name));
|
||||
if (isGovernmentEntityAdmin(userInfo)) {
|
||||
list = list.filter(item => !govEntityAdminHiddenMenuNames.includes(item.name));
|
||||
}
|
||||
// admin、manage 及其他角色展示全部菜单
|
||||
return allMenuList;
|
||||
return list;
|
||||
});
|
||||
const goInspectList = () => {
|
||||
uni.navigateTo({
|
||||
@@ -456,6 +471,12 @@
|
||||
|
||||
//我的检查计划
|
||||
const PLAN_INITIAL_SIZE = 4;
|
||||
const planTabs = [
|
||||
{ label: '全部', value: 0 },
|
||||
{ label: '未完成', value: 4 },
|
||||
{ label: '已完成', value: 3 }
|
||||
];
|
||||
const activePlanTab = ref(0);
|
||||
const checkPlanParams = ref({
|
||||
pageNum: 1,
|
||||
pageSize: PLAN_INITIAL_SIZE,
|
||||
@@ -466,6 +487,19 @@
|
||||
const planShowAll = ref(false);
|
||||
const expandedPlanMap = ref({});
|
||||
|
||||
const buildCheckPlanListParams = (pageSize) => ({
|
||||
pageNum: 1,
|
||||
pageSize,
|
||||
name: checkPlanParams.value.name,
|
||||
planStatus: planTabs[activePlanTab.value].value
|
||||
});
|
||||
|
||||
const switchPlanTab = (index) => {
|
||||
if (activePlanTab.value === index) return;
|
||||
activePlanTab.value = index;
|
||||
getCheckPlanLists();
|
||||
};
|
||||
|
||||
const hasMoreCheckPlans = computed(() => {
|
||||
return !planShowAll.value && checkPlanTotal.value > PLAN_INITIAL_SIZE;
|
||||
});
|
||||
@@ -494,11 +528,7 @@
|
||||
const getCheckPlanLists = async () => {
|
||||
planShowAll.value = false;
|
||||
try {
|
||||
const res = await getCheckPlanList({
|
||||
pageNum: 1,
|
||||
pageSize: PLAN_INITIAL_SIZE,
|
||||
name: checkPlanParams.value.name
|
||||
});
|
||||
const res = await getCheckPlanList(buildCheckPlanListParams(PLAN_INITIAL_SIZE));
|
||||
if (res.code === 0) {
|
||||
const records = res.data?.records || [];
|
||||
checkPlanTotal.value = Number(res.data?.total ?? records.length);
|
||||
@@ -515,11 +545,7 @@
|
||||
const loadMoreCheckPlans = async () => {
|
||||
if (!hasMoreCheckPlans.value) return;
|
||||
try {
|
||||
const res = await getCheckPlanList({
|
||||
pageNum: 1,
|
||||
pageSize: checkPlanTotal.value,
|
||||
name: checkPlanParams.value.name
|
||||
});
|
||||
const res = await getCheckPlanList(buildCheckPlanListParams(checkPlanTotal.value));
|
||||
if (res.code === 0) {
|
||||
const records = res.data?.records || [];
|
||||
initPlanExpandedState(records);
|
||||
@@ -552,7 +578,9 @@
|
||||
if (isApprovalRole.value) {
|
||||
fetchWorkbenchList();
|
||||
} else {
|
||||
getCheckPlanLists();
|
||||
if (showCheckPlanSection.value) {
|
||||
getCheckPlanLists();
|
||||
}
|
||||
resetHiddenDangerList();
|
||||
fetchHiddenDangerList();
|
||||
}
|
||||
@@ -1117,7 +1145,8 @@
|
||||
margin-left: 10rpx;
|
||||
}
|
||||
|
||||
.workbench-tab-list {
|
||||
.workbench-tab-list,
|
||||
.plan-tab-list {
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,48 +1,56 @@
|
||||
<template>
|
||||
<view class="content">
|
||||
<view class="header">
|
||||
<image src="/static/index/index_bg.png" class="bg-image"></image>
|
||||
<view class="padding login">
|
||||
<view class="text-xl text-black text-bold">账号登录</view>
|
||||
<view class="padding-top">欢迎登录湘西州“三个一”安全管理平台</view>
|
||||
<view class="status-bar" :style="{ height: statusBarHeight + 'px' }"></view>
|
||||
|
||||
<view class="brand-section">
|
||||
<view class="brand-logo">
|
||||
<image class="brand-logo-image" src="/static/logo1.png" mode="aspectFit"></image>
|
||||
</view>
|
||||
<view class="brand-title">湘西州三个一安全管理平台</view>
|
||||
<view class="brand-subtitle">隐患早发现、风险早处置,守护安全生产</view>
|
||||
</view>
|
||||
|
||||
<view class="role-card">
|
||||
<view class="role-card-title">选择角色</view>
|
||||
<view class="role-grid">
|
||||
<view
|
||||
v-for="item in roleList"
|
||||
:key="item.id"
|
||||
class="role-item"
|
||||
:class="{ 'role-item--active': selectedRole === item.id }"
|
||||
@click="selectRole(item.id)"
|
||||
>
|
||||
<view class="role-icon-wrap">
|
||||
<u-icon
|
||||
:name="item.icon"
|
||||
:size="22"
|
||||
:color="selectedRole === item.id ? '#ffffff' : '#b0b8c8'"
|
||||
></u-icon>
|
||||
</view>
|
||||
<text class="role-name">{{ item.name }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="list">
|
||||
<view class="list-call">
|
||||
<image class="img" src="/static/index/phone.png"></image>
|
||||
<input class="sl-input" v-model="username" type="text" placeholder="请输入用户名" />
|
||||
<view class="login-card">
|
||||
<view class="list">
|
||||
<view class="list-call">
|
||||
<image class="img" src="/static/index/phone.png"></image>
|
||||
<input class="sl-input" v-model="username" type="text" placeholder="请输入用户名" />
|
||||
</view>
|
||||
<view class="list-call">
|
||||
<image class="img" src="/static/index/lock.png"></image>
|
||||
<input class="sl-input" v-model="password" type="text" maxlength="32" placeholder="请输入密码" :password="showPassword"/>
|
||||
<image class="eye-img" :src="showPassword ? '/static/index/cl.png' : '/static/index/op.png'" @click="changePassword"></image>
|
||||
</view>
|
||||
</view>
|
||||
<view class="list-call">
|
||||
<image class="img" src="/static/index/lock.png"></image>
|
||||
<input class="sl-input" v-model="password" type="text" maxlength="32" placeholder="请输入密码" :password="showPassword"/>
|
||||
<image class="eye-img" :src="showPassword ? '/static/index/cl.png' : '/static/index/op.png'" @click="changePassword"></image>
|
||||
</view>
|
||||
<!-- <view class="agreement">
|
||||
<navigator url="reg" open-type="navigate" class="link">注册成员账号</navigator>
|
||||
<navigator url="forget" open-type="navigate" class="link">忘记密码?</navigator>
|
||||
</view> -->
|
||||
</view>
|
||||
|
||||
<view class="padding-lr">
|
||||
<button class="button-login" hover-class="button-hover" @click="handleLogin">
|
||||
登录
|
||||
</button>
|
||||
<!-- <view class="button-login" hover-class="button-hover" @tap="handleLogin('member')">
|
||||
<text>登录普通成员</text>
|
||||
</view> -->
|
||||
|
||||
<!-- <view class="button-report margin-top" hover-class="button-hover" @tap="goToReport">
|
||||
<image src="/static/index/photos.png" class="icon-image"></image>
|
||||
<text>随手拍举报</text>
|
||||
</view> -->
|
||||
|
||||
<!-- <view class="protocol-box">
|
||||
<navigator url="agreement" open-type="navigate" class="protocol-link">《用户协议》</navigator>
|
||||
</view> -->
|
||||
</view>
|
||||
|
||||
|
||||
</view>
|
||||
</template>
|
||||
|
||||
@@ -50,30 +58,74 @@
|
||||
import { ref } from 'vue';
|
||||
import { login } from '@/request/api.js';
|
||||
|
||||
// 响应式数据
|
||||
const statusBarHeight = uni.getSystemInfoSync().statusBarHeight || 0;
|
||||
|
||||
// 督导组跳转目标小程序配置
|
||||
const SUPERVISION_MINI_PROGRAM = {
|
||||
appId: 'wxe3533791db8a8734',
|
||||
path: 'pages/index/index',
|
||||
// develop=开发版 trial=体验版 release=正式版
|
||||
envVersion: 'release'
|
||||
};
|
||||
|
||||
const roleList = [
|
||||
{ id: 'enterprise', name: '企业', icon: 'home-fill' },
|
||||
{ id: 'personal', name: '个人', icon: 'account-fill' },
|
||||
{ id: 'supervision', name: '督导组', icon: 'man-add-fill' },
|
||||
{ id: 'government', name: '政务', icon: 'order' }
|
||||
// { id: 'family', name: '家庭', icon: 'home' }
|
||||
];
|
||||
|
||||
const selectedRole = ref('enterprise');
|
||||
const username = ref('');
|
||||
const password = ref('');
|
||||
const showPassword = ref(true);
|
||||
|
||||
// 方法定义
|
||||
const changePassword = () => {
|
||||
showPassword.value = !showPassword.value;
|
||||
}
|
||||
const selectRole = (roleId) => {
|
||||
if (roleId === 'supervision') {
|
||||
navigateToSupervisionMiniProgram();
|
||||
return;
|
||||
}
|
||||
selectedRole.value = roleId;
|
||||
};
|
||||
|
||||
const getPhoneNumber = () => {
|
||||
// 获取手机号的逻辑,可以接入一键登录SDK
|
||||
const navigateToSupervisionMiniProgram = () => {
|
||||
// #ifdef MP-WEIXIN
|
||||
uni.navigateToMiniProgram({
|
||||
appId: SUPERVISION_MINI_PROGRAM.appId,
|
||||
path: SUPERVISION_MINI_PROGRAM.path,
|
||||
extraData: {
|
||||
from: 'threeonecheck',
|
||||
role: 'supervision'
|
||||
},
|
||||
envVersion: SUPERVISION_MINI_PROGRAM.envVersion,
|
||||
success() {
|
||||
console.log('跳转督导组小程序成功');
|
||||
},
|
||||
fail(err) {
|
||||
console.error('跳转督导组小程序失败:', err);
|
||||
uni.showModal({
|
||||
title: '跳转失败',
|
||||
content: '请确认两个小程序已关联,且目标小程序已添加您为开发者。开发阶段可在微信开发者工具中测试。',
|
||||
showCancel: false
|
||||
});
|
||||
}
|
||||
});
|
||||
// #endif
|
||||
|
||||
// #ifndef MP-WEIXIN
|
||||
uni.showToast({
|
||||
title: '获取手机号功能待实现',
|
||||
title: '请在微信小程序中使用',
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
// #endif
|
||||
};
|
||||
|
||||
const changePassword = () => {
|
||||
showPassword.value = !showPassword.value;
|
||||
};
|
||||
|
||||
const handleLogin = async () => {
|
||||
console.log('点击登录按钮');
|
||||
console.log('用户名:', username.value);
|
||||
console.log('密码:', password.value);
|
||||
|
||||
// 验证用户名
|
||||
if (!username.value) {
|
||||
uni.showToast({
|
||||
icon: 'none',
|
||||
@@ -81,8 +133,7 @@ const handleLogin = async () => {
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// 验证密码
|
||||
|
||||
if (!password.value) {
|
||||
uni.showToast({
|
||||
icon: 'none',
|
||||
@@ -90,39 +141,35 @@ const handleLogin = async () => {
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
console.log('开始调用登录接口...');
|
||||
|
||||
const res = await login({
|
||||
username: username.value,
|
||||
password: password.value
|
||||
});
|
||||
|
||||
console.log('登录接口返回:', res);
|
||||
|
||||
|
||||
if (res.code === 0) {
|
||||
// 登录成功,保存token和用户信息
|
||||
if (res.data.token) {
|
||||
uni.setStorageSync('token', res.data.token);
|
||||
}
|
||||
// 保存用户信息
|
||||
|
||||
const userInfo = {
|
||||
userId: res.data.userId,
|
||||
username: res.data.username,
|
||||
nickName: res.data.nickName,
|
||||
deptId: res.data.deptId,
|
||||
deptName: res.data.deptName,
|
||||
role:res.data.role,
|
||||
isDept:res.data.isDept
|
||||
role: res.data.role,
|
||||
isDept: res.data.isDept
|
||||
};
|
||||
uni.setStorageSync('userInfo', JSON.stringify(userInfo));
|
||||
|
||||
uni.setStorageSync('loginRole', selectedRole.value);
|
||||
|
||||
uni.showToast({
|
||||
title: '登录成功',
|
||||
icon: 'success'
|
||||
});
|
||||
|
||||
|
||||
setTimeout(() => {
|
||||
uni.reLaunch({
|
||||
url: '/pages/index/index'
|
||||
@@ -141,110 +188,131 @@ const handleLogin = async () => {
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// const handleLogin = () => {
|
||||
// if (phone.value.length != 11) {
|
||||
// uni.showToast({
|
||||
// icon: 'none',
|
||||
// title: '手机号不正确'
|
||||
// });
|
||||
// return;
|
||||
// }
|
||||
// if (password.value.length < 6) {
|
||||
// uni.showToast({
|
||||
// icon: 'none',
|
||||
// title: '密码不正确'
|
||||
// });
|
||||
// return;
|
||||
// }
|
||||
|
||||
// // 登录请求
|
||||
// uni.request({
|
||||
// url: 'http://example.com/api/login',
|
||||
// data: {
|
||||
// phone: phone.value,
|
||||
// password: password.value
|
||||
// },
|
||||
// method: 'POST',
|
||||
// dataType: 'json',
|
||||
// success: (res) => {
|
||||
// if (res.data.code != 200) {
|
||||
// uni.showToast({
|
||||
// title: res.data.msg || '登录失败',
|
||||
// icon: 'none'
|
||||
// });
|
||||
// } else {
|
||||
// // 登录成功,保存token等信息
|
||||
// uni.setStorageSync('token', res.data.data.token);
|
||||
// uni.setStorageSync('userInfo', JSON.stringify(res.data.data.userInfo));
|
||||
|
||||
// // 返回上一页或首页
|
||||
// uni.navigateBack({
|
||||
// delta: 1,
|
||||
// fail: () => {
|
||||
// uni.switchTab({
|
||||
// url: '/pages/index/index'
|
||||
// });
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
// },
|
||||
// fail: () => {
|
||||
// uni.showToast({
|
||||
// title: '网络请求失败',
|
||||
// icon: 'none'
|
||||
// });
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
|
||||
const goToReport = () => {
|
||||
//跳转到主页面 跳到分包
|
||||
uni.navigateTo({
|
||||
url: '/subpackages/suishoupai/pages/index/index'
|
||||
})
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
page {
|
||||
background-color: #FFFFFF;
|
||||
background: linear-gradient(180deg, #eef4ff 0%, #f8fbff 45%, #ffffff 100%);
|
||||
}
|
||||
|
||||
.content {
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
background-color: #FFFFFF;
|
||||
background: linear-gradient(180deg, #eef4ff 0%, #f8fbff 45%, #ffffff 100%);
|
||||
padding-bottom: 60rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.header {
|
||||
.status-bar {
|
||||
width: 100%;
|
||||
position: relative;
|
||||
margin-bottom: 0;
|
||||
|
||||
.bg-image {
|
||||
width: 100%;
|
||||
vertical-align: bottom;
|
||||
}
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.login {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
color: #666666;
|
||||
font-size: 28rpx;
|
||||
.brand-section {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 120rpx 48rpx 32rpx;
|
||||
}
|
||||
|
||||
.brand-logo {
|
||||
margin-bottom: 28rpx;
|
||||
}
|
||||
|
||||
.brand-logo-image {
|
||||
width: 130rpx;
|
||||
height: 130rpx;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.brand-title {
|
||||
font-size: 40rpx;
|
||||
font-weight: 700;
|
||||
color: #1a1a2e;
|
||||
text-align: center;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.brand-subtitle {
|
||||
margin-top: 16rpx;
|
||||
font-size: 26rpx;
|
||||
color: #8a94a6;
|
||||
text-align: center;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.role-card {
|
||||
margin: 0 40rpx 16rpx;
|
||||
padding: 32rpx 28rpx 28rpx;
|
||||
background: #ffffff;
|
||||
border-radius: 24rpx;
|
||||
box-shadow: 0 8rpx 32rpx rgba(47, 108, 242, 0.08);
|
||||
}
|
||||
|
||||
.role-card-title {
|
||||
font-size: 30rpx;
|
||||
font-weight: 600;
|
||||
color: #1a1a2e;
|
||||
margin-bottom: 24rpx;
|
||||
}
|
||||
|
||||
.role-grid {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.role-item {
|
||||
width: 22%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
margin-bottom: 8rpx;
|
||||
}
|
||||
|
||||
.role-icon-wrap {
|
||||
width: 88rpx;
|
||||
height: 88rpx;
|
||||
border-radius: 20rpx;
|
||||
background: #f5f7fb;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.role-item--active .role-icon-wrap {
|
||||
background: linear-gradient(145deg, #4a8af7 0%, #2f6cf2 100%);
|
||||
box-shadow: 0 8rpx 20rpx rgba(47, 108, 242, 0.3);
|
||||
}
|
||||
|
||||
.role-name {
|
||||
margin-top: 12rpx;
|
||||
font-size: 24rpx;
|
||||
color: #8a94a6;
|
||||
line-height: 1.2;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.role-item--active .role-name {
|
||||
color: #2f6cf2;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.login-card {
|
||||
margin: 16rpx 40rpx 0;
|
||||
padding: 32rpx 28rpx;
|
||||
background: #ffffff;
|
||||
border-radius: 24rpx;
|
||||
box-shadow: 0 8rpx 32rpx rgba(47, 108, 242, 0.08);
|
||||
}
|
||||
|
||||
.list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding-top: 50rpx;
|
||||
padding-left: 70rpx;
|
||||
padding-right: 70rpx;
|
||||
background-color: #FFFFFF;
|
||||
margin-top: -2rpx; /* 消除可能的间隙 */
|
||||
background-color: transparent;
|
||||
|
||||
.list-call {
|
||||
display: flex;
|
||||
@@ -256,8 +324,12 @@ page {
|
||||
background: #F5F7FB;
|
||||
border-radius: 16rpx;
|
||||
border: 2rpx solid #F5F7FB;
|
||||
margin-top: 30rpx;
|
||||
margin-top: 24rpx;
|
||||
padding: 0 30rpx;
|
||||
|
||||
&:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.img {
|
||||
width: 30rpx;
|
||||
@@ -278,31 +350,9 @@ page {
|
||||
}
|
||||
}
|
||||
|
||||
.agreement {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
font-size: 30rpx;
|
||||
margin-top: 30rpx;
|
||||
color: #3D83F6;
|
||||
text-align: center;
|
||||
height: 40rpx;
|
||||
line-height: 40rpx;
|
||||
|
||||
.link {
|
||||
font-size: 30rpx;
|
||||
color: #3D83F6;
|
||||
|
||||
&:active {
|
||||
opacity: 0.8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.padding-lr {
|
||||
padding-left: 70rpx;
|
||||
padding-right: 70rpx;
|
||||
padding-left: 40rpx;
|
||||
padding-right: 40rpx;
|
||||
}
|
||||
|
||||
.button-login {
|
||||
@@ -316,7 +366,7 @@ page {
|
||||
text-align: center;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
margin-top: 130rpx;
|
||||
margin-top: 48rpx;
|
||||
border: none;
|
||||
|
||||
&::after {
|
||||
@@ -324,70 +374,7 @@ page {
|
||||
}
|
||||
}
|
||||
|
||||
.button-report {
|
||||
color: #FFFFFF;
|
||||
font-size: 34rpx;
|
||||
width: 100%;
|
||||
height: 100rpx;
|
||||
background: linear-gradient(90deg, #FF7878 0%, #F2505B 100%);
|
||||
border-radius: 50rpx;
|
||||
line-height: 100rpx;
|
||||
text-align: center;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.margin-top {
|
||||
margin-top: 30rpx;
|
||||
}
|
||||
|
||||
.button-hover {
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.text-blue {
|
||||
color: #3D83F6;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.icon-image {
|
||||
width: 36rpx;
|
||||
height: 36rpx;
|
||||
margin-right: 8rpx;
|
||||
}
|
||||
|
||||
.text-xl {
|
||||
font-size: 36rpx;
|
||||
}
|
||||
|
||||
.text-black {
|
||||
color: #000000;
|
||||
}
|
||||
|
||||
.text-bold {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.padding {
|
||||
padding: 30rpx;
|
||||
}
|
||||
|
||||
.padding-top {
|
||||
padding-top: 15rpx;
|
||||
}
|
||||
|
||||
.protocol-box {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin-top: 40rpx;
|
||||
|
||||
.protocol-link {
|
||||
font-size: 28rpx;
|
||||
color: #3D83F6;
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user