一单四制优化及加入工作流
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
export const DRAFT_NS = {
|
||||
ASSIGN: 'draft_assign',
|
||||
ACCEPT: 'draft_accept',
|
||||
ACCEPT_APPROVAL: 'draft_accept_approval',
|
||||
RECTIFY: 'draft_rectify',
|
||||
INSPECTION_RESULT: 'draft_inspection_result',
|
||||
INSPECTION_SHEET: 'draft_inspection_sheet',
|
||||
|
||||
212
utils/hazardNav.js
Normal file
212
utils/hazardNav.js
Normal file
@@ -0,0 +1,212 @@
|
||||
/** 从列表项解析流程任务 ID */
|
||||
export function resolveItemTaskId(item) {
|
||||
if (!item) return '';
|
||||
const id = item.taskId ?? item.flowTaskId ?? item.currentTaskId ?? '';
|
||||
return id === '' || id == null ? '' : String(id);
|
||||
}
|
||||
|
||||
/** 从列表项解析被指派人身份 ID */
|
||||
export function resolveAssigneeIdentityId(item) {
|
||||
if (!item) return '';
|
||||
return item.assigneeIdentityId ?? item.identityId ?? '';
|
||||
}
|
||||
|
||||
/** 追加被指派人相关查询参数 */
|
||||
export function appendAssigneeQuery(url, item) {
|
||||
if (!item) return url;
|
||||
let result = url;
|
||||
if (item.assigneeId) {
|
||||
result += `&assigneeId=${item.assigneeId}`;
|
||||
}
|
||||
const assigneeIdentityId = resolveAssigneeIdentityId(item);
|
||||
if (assigneeIdentityId) {
|
||||
result += `&assigneeIdentityId=${assigneeIdentityId}`;
|
||||
}
|
||||
if (item.assigneeName) {
|
||||
result += `&assigneeName=${encodeURIComponent(item.assigneeName)}`;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/** 构建立即整改页 URL */
|
||||
export function buildRectificationUrl(item) {
|
||||
let url = `/pages/hiddendanger/rectification?hazardId=${item.hazardId}&assignId=${item.assignId || ''}`;
|
||||
if (item.taskId) {
|
||||
url += `&taskId=${encodeURIComponent(item.taskId)}`;
|
||||
}
|
||||
if (item.deadline) {
|
||||
url += `&deadline=${encodeURIComponent(item.deadline)}`;
|
||||
}
|
||||
return appendAssigneeQuery(url, item);
|
||||
}
|
||||
|
||||
/** 构建编辑整改页 URL */
|
||||
export function buildEditRectificationUrl(item) {
|
||||
let url = `/pages/hiddendanger/rectification?rectifyId=${item.rectifyId}&isEdit=1`;
|
||||
if (item.hazardId) {
|
||||
url += `&hazardId=${item.hazardId}`;
|
||||
}
|
||||
if (item.assignId) {
|
||||
url += `&assignId=${item.assignId}`;
|
||||
}
|
||||
if (item.taskId) {
|
||||
url += `&taskId=${encodeURIComponent(item.taskId)}`;
|
||||
}
|
||||
return url;
|
||||
}
|
||||
|
||||
/** 构建验收页 URL */
|
||||
export function buildAcceptanceUrl(item) {
|
||||
let url = `/pages/hiddendanger/acceptance?hazardId=${item.hazardId}&assignId=${item.assignId || ''}&rectifyId=${item.rectifyId || ''}`;
|
||||
if (item.taskId) {
|
||||
url += `&taskId=${encodeURIComponent(item.taskId)}`;
|
||||
}
|
||||
return url;
|
||||
}
|
||||
|
||||
/** 构建验收审批页 URL(approval 角色) */
|
||||
export function buildAcceptanceApprovalUrl(item) {
|
||||
let url = `/pages/hiddendanger/acceptance-approval?hazardId=${item.hazardId}&assignId=${item.assignId || ''}&rectifyId=${item.rectifyId || ''}`;
|
||||
if (item.taskId) {
|
||||
url += `&taskId=${encodeURIComponent(item.taskId)}`;
|
||||
}
|
||||
if (item.taskKey) {
|
||||
url += `&taskKey=${encodeURIComponent(item.taskKey)}`;
|
||||
}
|
||||
return url;
|
||||
}
|
||||
|
||||
/** 构建隐患交办页 URL */
|
||||
export function buildAssignmentUrl(item) {
|
||||
let url = `/pages/hiddendanger/assignment?hazardId=${item.hazardId}&assignId=${item.assignId || ''}`;
|
||||
const taskId = resolveItemTaskId(item);
|
||||
if (taskId) {
|
||||
url += `&taskId=${encodeURIComponent(taskId)}`;
|
||||
}
|
||||
return url;
|
||||
}
|
||||
|
||||
/** 构建销号申请页 URL(从列表卡片进入时锁定对应隐患) */
|
||||
export function buildWriteoffApplyUrl(item) {
|
||||
let url = `/pages/closeout/apply?hazardId=${item.hazardId}&locked=1`;
|
||||
if (item.assignId) {
|
||||
url += `&assignId=${item.assignId}`;
|
||||
}
|
||||
if (item.taskId) {
|
||||
url += `&taskId=${encodeURIComponent(item.taskId)}`;
|
||||
}
|
||||
return appendWriteoffHazardQuery(url, item);
|
||||
}
|
||||
|
||||
/** 构建销号审批页 URL */
|
||||
export function buildWriteoffApprovalUrl(item) {
|
||||
let url = `/pages/closeout/approval?hazardId=${item.hazardId}&locked=1`;
|
||||
if (item.assignId) {
|
||||
url += `&assignId=${item.assignId}`;
|
||||
}
|
||||
if (item.taskId) {
|
||||
url += `&taskId=${encodeURIComponent(item.taskId)}`;
|
||||
}
|
||||
return appendWriteoffHazardQuery(url, item);
|
||||
}
|
||||
|
||||
/** 构建销号领导审批页 URL(approval 角色) */
|
||||
export function buildLeaderWriteoffApprovalUrl(item) {
|
||||
let url = `/pages/closeout/leader-approval?hazardId=${item.hazardId}&locked=1`;
|
||||
if (item.assignId) {
|
||||
url += `&assignId=${item.assignId}`;
|
||||
}
|
||||
if (item.taskId) {
|
||||
url += `&taskId=${encodeURIComponent(item.taskId)}`;
|
||||
}
|
||||
if (item.taskKey) {
|
||||
url += `&taskKey=${encodeURIComponent(item.taskKey)}`;
|
||||
}
|
||||
return appendWriteoffHazardQuery(url, item);
|
||||
}
|
||||
|
||||
const decodeQueryValue = (value) => {
|
||||
if (value == null || value === '') return '';
|
||||
try {
|
||||
return decodeURIComponent(String(value));
|
||||
} catch (error) {
|
||||
return String(value);
|
||||
}
|
||||
};
|
||||
|
||||
/** 销号相关页 URL 追加列表项展示字段(title、deadline、deptName、rectifierName、deptId) */
|
||||
export function appendWriteoffHazardQuery(url, item) {
|
||||
if (!item) return url;
|
||||
let result = url;
|
||||
const title = item.title || item.hazardTitle;
|
||||
if (title) {
|
||||
result += `&title=${encodeURIComponent(title)}`;
|
||||
}
|
||||
if (item.deadline) {
|
||||
result += `&deadline=${encodeURIComponent(item.deadline)}`;
|
||||
}
|
||||
if (item.deptName) {
|
||||
result += `&deptName=${encodeURIComponent(item.deptName)}`;
|
||||
}
|
||||
if (item.deptId != null && item.deptId !== '') {
|
||||
result += `&deptId=${item.deptId}`;
|
||||
}
|
||||
if (item.rectifierName) {
|
||||
result += `&rectifierName=${encodeURIComponent(item.rectifierName)}`;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/** 从页面 onLoad options 解析列表传入的隐患信息(不再依赖 verified/list 对比) */
|
||||
export function buildWriteoffHazardFromOptions(options) {
|
||||
if (!options?.hazardId) return null;
|
||||
return {
|
||||
hazardId: options.hazardId,
|
||||
assignId: options.assignId || '',
|
||||
taskId: options.taskId || '',
|
||||
title: decodeQueryValue(options.title),
|
||||
hazardTitle: decodeQueryValue(options.title),
|
||||
deadline: decodeQueryValue(options.deadline),
|
||||
deptName: decodeQueryValue(options.deptName),
|
||||
deptId: options.deptId || '',
|
||||
rectifierName: decodeQueryValue(options.rectifierName)
|
||||
};
|
||||
}
|
||||
|
||||
const isTruthyFlag = (value) => value === true || value === 1 || value === '1';
|
||||
|
||||
/**
|
||||
* 立即验收按钮展示逻辑(首页、隐患排查列表等共用)
|
||||
*
|
||||
* 展示条件(需同时满足):
|
||||
* 1. statusName === '待验收'
|
||||
* 2. 当前角色为 admin 或 manage
|
||||
* 3. 流程节点类型 nodeType 允许验收
|
||||
*
|
||||
* 【历史变更】
|
||||
* - 最初:item.quickApprove != 0 时展示
|
||||
* - 中间:改为 item.result(null 或 3=驳回)时展示
|
||||
* - 现在:改为 item.nodeType 控制
|
||||
* 仅当 nodeType 为 null、1(重新整改)、2(驳回)、3(重新验收)时展示
|
||||
* 其他 nodeType 值不展示
|
||||
*/
|
||||
export function canShowAcceptanceButton(item, roleKey) {
|
||||
const canAcceptance = roleKey === 'admin' || roleKey === 'manage';
|
||||
const nodeType = item?.nodeType;
|
||||
// null:初始待验收;1:重新整改;2:驳回;3:重新验收
|
||||
const canAcceptByNodeType = nodeType == null
|
||||
|| nodeType === 1 || nodeType === '1'
|
||||
|| nodeType === 2 || nodeType === '2'
|
||||
|| nodeType === 3 || nodeType === '3';
|
||||
return item?.statusName === '待验收' && canAcceptance && canAcceptByNodeType;
|
||||
}
|
||||
|
||||
/** 销号申请按钮:待销号且 applyFlag 为 true */
|
||||
export function canShowWriteoffApplyButton(item) {
|
||||
return item?.statusName === '待销号' && isTruthyFlag(item?.applyFlag);
|
||||
}
|
||||
|
||||
/** 销号审批按钮:待销号、manage 角色且 writeOffFlag 为 true */
|
||||
export function canShowWriteoffApprovalButton(item, roleKey) {
|
||||
return item?.statusName === '待销号' && roleKey === 'manage' && isTruthyFlag(item?.writeOffFlag);
|
||||
}
|
||||
56
utils/identitySwitch.js
Normal file
56
utils/identitySwitch.js
Normal file
@@ -0,0 +1,56 @@
|
||||
import { switchIdentity } from '@/request/identity.js';
|
||||
import { getProfileDetail } from '@/request/three_one_api/info.js';
|
||||
import { saveUserInfoToStorage } from '@/utils/userInfo.js';
|
||||
|
||||
function unwrapPayload(res) {
|
||||
if (!res) return {};
|
||||
const data = res.data;
|
||||
if (data && typeof data === 'object' && (
|
||||
data.token ||
|
||||
data.identities ||
|
||||
data.currentIdentity ||
|
||||
data.roles
|
||||
)) {
|
||||
return data;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/** 根据个人信息接口刷新本地 userInfo */
|
||||
export async function refreshUserInfoStorage() {
|
||||
const res = await getProfileDetail();
|
||||
if (res.code === 0 && res.data) {
|
||||
return saveUserInfoToStorage(res.data);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/** 执行身份切换:更新 token,再通过 profile 接口刷新 userInfo */
|
||||
export async function performIdentitySwitch(identityId) {
|
||||
const res = await switchIdentity(identityId);
|
||||
const payload = unwrapPayload(res);
|
||||
|
||||
if (payload.token) {
|
||||
uni.setStorageSync('token', payload.token);
|
||||
}
|
||||
|
||||
if (payload.currentIdentity) {
|
||||
uni.setStorageSync('currentIdentity', JSON.stringify(payload.currentIdentity));
|
||||
}
|
||||
|
||||
await refreshUserInfoStorage();
|
||||
return payload;
|
||||
}
|
||||
|
||||
/** 切换成功后重启到首页,清空页面栈 */
|
||||
export function reLaunchAfterSwitch() {
|
||||
uni.showToast({
|
||||
title: '身份切换成功',
|
||||
icon: 'success'
|
||||
});
|
||||
setTimeout(() => {
|
||||
uni.reLaunch({
|
||||
url: '/pages/index/index'
|
||||
});
|
||||
}, 1500);
|
||||
}
|
||||
142
utils/userInfo.js
Normal file
142
utils/userInfo.js
Normal file
@@ -0,0 +1,142 @@
|
||||
/** 将 profile/detail 接口数据映射为本地 userInfo 结构 */
|
||||
function normalizeUserIdentity(raw) {
|
||||
if (!raw) return null;
|
||||
if (typeof raw === 'string') {
|
||||
try {
|
||||
return JSON.parse(raw);
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return raw;
|
||||
}
|
||||
|
||||
/** 从本地读取切换身份时缓存的 currentIdentity */
|
||||
export function getCurrentIdentityFromStorage() {
|
||||
try {
|
||||
const raw = uni.getStorageSync('currentIdentity');
|
||||
if (!raw) return null;
|
||||
return normalizeUserIdentity(raw);
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/** 规范化角色标识,去除首尾空格 */
|
||||
function normalizeRoleKey(value) {
|
||||
if (value == null || value === '') return '';
|
||||
return String(value).trim();
|
||||
}
|
||||
|
||||
/** 从 roles 数组解析 roleKey */
|
||||
function resolveRoleKey(roles, fallback = '') {
|
||||
if (!roles?.length) return normalizeRoleKey(fallback);
|
||||
const first = roles[0];
|
||||
if (typeof first === 'string') return normalizeRoleKey(first);
|
||||
return normalizeRoleKey(first.roleKey || first.role || fallback);
|
||||
}
|
||||
|
||||
/** 解析用于权限判断的角色标识,优先当前身份 roleKey */
|
||||
export function resolveUserRoleKey(userInfo) {
|
||||
if (!userInfo) return '';
|
||||
const identity = normalizeUserIdentity(userInfo.userIdentity);
|
||||
const currentIdentity = getCurrentIdentityFromStorage();
|
||||
|
||||
const identityRoleKey = normalizeRoleKey(identity?.roleKey);
|
||||
if (identityRoleKey) return identityRoleKey;
|
||||
|
||||
const currentRoleKey = normalizeRoleKey(currentIdentity?.roleKey);
|
||||
if (currentRoleKey) return currentRoleKey;
|
||||
|
||||
const storedRole = normalizeRoleKey(userInfo.role);
|
||||
if (storedRole) return storedRole;
|
||||
|
||||
const nameHint = [
|
||||
identity?.roleName,
|
||||
identity?.identityName,
|
||||
userInfo.identityName,
|
||||
currentIdentity?.roleName,
|
||||
currentIdentity?.identityName
|
||||
].filter(Boolean).join(' ');
|
||||
if (/审批|approval/i.test(nameHint)) return 'approval';
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/** 解析用于展示的身份名称 */
|
||||
export function resolveIdentityName(profile, userIdentity) {
|
||||
const identity = userIdentity || normalizeUserIdentity(profile?.userIdentity);
|
||||
if (identity?.identityName) {
|
||||
return identity.identityName;
|
||||
}
|
||||
if (profile?.identityName) {
|
||||
return profile.identityName;
|
||||
}
|
||||
if (identity) {
|
||||
const parts = [identity.deptName, identity.roleName, identity.postName].filter(Boolean);
|
||||
if (parts.length) return parts.join('-');
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
export function mapProfileToUserInfo(profile) {
|
||||
if (!profile) return {};
|
||||
const userIdentity = normalizeUserIdentity(profile.userIdentity);
|
||||
const currentIdentity = getCurrentIdentityFromStorage();
|
||||
const roleKey = normalizeRoleKey(
|
||||
userIdentity?.roleKey || currentIdentity?.roleKey || resolveRoleKey(profile.roles, '')
|
||||
);
|
||||
return {
|
||||
userId: profile.userId || '',
|
||||
username: profile.userName || '',
|
||||
nickName: profile.nickName || '',
|
||||
deptId: userIdentity?.deptId ?? currentIdentity?.deptId ?? profile.deptId ?? '',
|
||||
deptName: userIdentity?.deptName ?? currentIdentity?.deptName ?? profile.deptName ?? '',
|
||||
role: roleKey,
|
||||
avatar: profile.avatar || '',
|
||||
phone: profile.phonenumber || profile.phone || '',
|
||||
identityName: resolveIdentityName(profile, userIdentity),
|
||||
userIdentity: userIdentity || currentIdentity
|
||||
};
|
||||
}
|
||||
|
||||
/** 写入本地 userInfo 缓存 */
|
||||
export function saveUserInfoToStorage(profile) {
|
||||
const userInfo = mapProfileToUserInfo(profile);
|
||||
uni.setStorageSync('userInfo', JSON.stringify(userInfo));
|
||||
return userInfo;
|
||||
}
|
||||
|
||||
/** 将 profile 数据应用到页面 reactive 对象(逐项赋值,确保小程序视图更新) */
|
||||
export function applyProfileToUserInfo(target, profile) {
|
||||
const mapped = mapProfileToUserInfo(profile);
|
||||
Object.keys(mapped).forEach((key) => {
|
||||
target[key] = mapped[key];
|
||||
});
|
||||
uni.setStorageSync('userInfo', JSON.stringify(mapped));
|
||||
return mapped;
|
||||
}
|
||||
|
||||
/** 从本地缓存应用到页面 reactive 对象 */
|
||||
export function applyStoredUserInfo(target, stored) {
|
||||
if (!stored) return;
|
||||
const userIdentity = normalizeUserIdentity(stored.userIdentity);
|
||||
const currentIdentity = getCurrentIdentityFromStorage();
|
||||
const mergedIdentity = userIdentity || currentIdentity;
|
||||
const mapped = {
|
||||
userId: stored.userId || '',
|
||||
username: stored.username || '',
|
||||
nickName: stored.nickName || '',
|
||||
deptId: stored.deptId || mergedIdentity?.deptId || '',
|
||||
deptName: stored.deptName || mergedIdentity?.deptName || '',
|
||||
role: resolveUserRoleKey({ role: stored.role, userIdentity: mergedIdentity, identityName: stored.identityName }),
|
||||
avatar: stored.avatar || '',
|
||||
phone: stored.phone || '',
|
||||
userIdentity: mergedIdentity,
|
||||
identityName: stored.identityName || resolveIdentityName(stored, mergedIdentity)
|
||||
};
|
||||
Object.keys(mapped).forEach((key) => {
|
||||
target[key] = mapped[key];
|
||||
});
|
||||
return mapped;
|
||||
}
|
||||
Reference in New Issue
Block a user