<template>
	<view class="page padding">
		<view class="padding bg-white radius">
			<!-- 草稿恢复提示 -->
			<view v-if="showRestoreBanner" class="bg-orange-light text-orange padding-sm radius margin-bottom flex justify-between align-center" style="font-size: 24rpx; background-color: #FFF7EB; border: 1rpx solid #FFE4CC; width: 100%; box-sizing: border-box; display: flex; flex-direction: row; justify-content: space-between; align-items: center; margin-bottom: 20rpx;">
				<view class="flex align-center" style="display: flex; flex-direction: row; align-items: center;">
					<text class="cuIcon-info margin-right-xs" style="margin-right: 10rpx;"></text>
					<text>已自动恢复您上次未提交的内容</text>
				</view>
				<text class="text-blue text-bold" style="cursor: pointer; padding: 0 10rpx; color: #2667E9; font-weight: bold;" @click="clearDraft(true)">清空草稿</text>
			</view>
			<view class="form-header margin-bottom">
				<view class="form-label">
					<view class="text-gray">整改方案</view>
					<view class="text-red">*</view>
				</view>
				<button class="ai-rectify-btn" :loading="aiGenerating" :disabled="aiGenerating" @click="handleAiGenerate">
					<text v-if="!aiGenerating" class="cuIcon-magic ai-btn-icon"></text>
					{{ aiGenerating ? 'AI生成中...' : 'AI生成整改方案' }}
				</button>
			</view>
			<up-textarea v-model="formData.rectifyPlan" placeholder="请输入内容" :maxlength="-1" autoHeight></up-textarea>
			<view class="form-label margin-bottom margin-top">
				<view class="text-gray">整改措施</view>
				<view class="text-red">*</view>
			</view>
			<up-textarea v-model="formData.rectificationMeasures" placeholder="请输入整改措施"></up-textarea>
			<view class="form-label margin-bottom margin-top">
				<view class="text-gray">管控措施</view>
				<view class="text-red">*</view>
			</view>
			<up-textarea v-model="formData.controlMeasures" placeholder="请输入管控措施"></up-textarea>
			<view class="form-label margin-bottom margin-top">
				<view class="text-gray">整改完成情况</view>
				<view class="text-red">*</view>
			</view>
			<up-textarea v-model="formData.rectifyResult" placeholder="请输入内容"></up-textarea>
			<view class="form-label margin-bottom margin-top">
				<view class="text-gray">投资资金(计划)</view>
				<view class="text-red">*</view>
			</view>
			<up-input v-model="formData.planCost" placeholder="请输入内容" type="number"></up-input>
			<view class="form-label margin-bottom margin-top">
				<view class="text-gray">投资资金(实际)</view>
				<view class="text-red">*</view>
			</view>
			<up-input v-model="formData.actualCost" placeholder="请输入内容" type="number"></up-input>
			<view class="form-label margin-bottom margin-top">
				<view class="text-gray">限定整改时间</view>
				<view class="text-red">*</view>
			</view>
			<view class="readonly-field">
				<text :class="{ 'text-gray': !selectedDeadlineDate }">{{ selectedDeadlineDate || '暂无' }}</text>
			</view>
			<view class="form-label margin-bottom margin-top">
				<view class="text-gray">实际整改时间</view>
				<view class="text-red">*</view>
			</view>
			<view class="select-trigger" @click="showRectifyTimePicker = true">
				<view class="select-content" :class="{ 'text-gray': !selectedRectifyTime }">
					{{ selectedRectifyTime || '请选择实际整改时间' }}
				</view>
				<text class="cuIcon-unfold"></text>
			</view>
			<up-datetime-picker
				:show="showRectifyTimePicker"
				v-model="rectifyTimeValue"
				mode="datetime"
				@confirm="onRectifyTimeConfirm"
				@cancel="showRectifyTimePicker = false"
				@close="showRectifyTimePicker = false"
			></up-datetime-picker>
			<view class="form-label margin-bottom margin-top">
				<view class="text-gray">安全管理人员</view>
				<view class="text-red">*</view>
			</view>
			<view class="select-trigger" @click="openManagerPopup">
				<view class="select-content" :class="{ 'text-gray': selectedManagers.length === 0 }">
					{{ selectedManagers.length > 0 ? selectedManagersText : '请选择安全管理人员（可多选）' }}
				</view>
				<text class="cuIcon-unfold"></text>
			</view>

			<view class="form-label margin-bottom margin-top">
				<view class="text-gray">整改责任人</view>
				<view class="text-red">*</view>
			</view>
			<!-- 点击打开人员选择弹窗 -->
			<view class="select-trigger" @click="openUserPopup">
				<view class="select-content" :class="{ 'text-gray': selectedUsers.length === 0 }">
					{{ selectedUsers.length > 0 ? selectedUsersText : '请选择整改责任人（可多选）' }}
				</view>
				<text class="cuIcon-unfold"></text>
			</view>
			
			<!-- 安全管理人员：部门-人员级联多选弹窗 -->
			<u-popup :show="showManagerPopup" mode="bottom" round="20" @close="cancelManagerSelect">
				<view class="user-popup cascader-user-popup">
					<view class="popup-header">
						<view class="popup-title text-bold">选择安全管理人员</view>
						<view class="popup-close" @click="cancelManagerSelect">×</view>
					</view>
					<view v-if="managerPickerSelectedIdentityIds.length > 0" class="selected-summary">
						<text class="summary-label">已选 {{ managerPickerSelectedIdentityIds.length }} 人：</text>
						<text class="summary-text">{{ managerPickerSelectedText }}</text>
					</view>
					<view class="cascader-body">
						<scroll-view class="cascader-col dept-col" scroll-y>
							<view
								v-for="(dept, index) in managerDeptList"
								:key="'manager-dept-' + dept.deptId"
								:class="['cascader-item', { active: activeManagerDeptIndex === index }]"
								@click="activeManagerDeptIndex = index"
							>
								<text class="cascader-item-text">{{ dept.deptName }}</text>
								<text v-if="getManagerDeptSelectedCount(dept) > 0" class="dept-badge">{{ getManagerDeptSelectedCount(dept) }}</text>
							</view>
						</scroll-view>
						<scroll-view class="cascader-col user-col" scroll-y :key="'manager-dept-users-' + activeManagerDeptIndex">
							<view v-if="currentManagerDeptUsers.length === 0" class="empty-tip">该部门暂无人员</view>
							<view v-else>
								<view class="user-item" v-for="user in currentManagerDeptUsers" :key="'manager-identity-' + user.identityId">
									<up-checkbox
										usedAlone
										:checked="managerPickerSelectedSet.has(String(user.identityId))"
										:label="formatMemberDisplayName(user)"
										activeColor="#2667E9"
										shape="square"
										@change="(checked) => onManagerCheckChange(user.identityId, checked)"
									></up-checkbox>
								</view>
							</view>
						</scroll-view>
					</view>
					<view class="popup-footer">
						<button class="btn-cancel" @click="cancelManagerSelect">取消</button>
						<button class="btn-confirm bg-blue" @click="confirmManagerSelect">确定</button>
					</view>
				</view>
			</u-popup>

			<!-- 整改责任人：部门-人员级联多选弹窗 -->
			<u-popup :show="showUserPopup" mode="bottom" round="20" @close="cancelUserSelect">
				<view class="user-popup cascader-user-popup">
					<view class="popup-header">
						<view class="popup-title text-bold">选择整改责任人</view>
						<view class="popup-close" @click="cancelUserSelect">×</view>
					</view>
					<view v-if="userPickerSelectedIdentityIds.length > 0" class="selected-summary">
						<text class="summary-label">已选 {{ userPickerSelectedIdentityIds.length }} 人：</text>
						<text class="summary-text">{{ userPickerSelectedText }}</text>
					</view>
					<view class="cascader-body">
						<scroll-view class="cascader-col dept-col" scroll-y>
							<view
								v-for="(dept, index) in deptList"
								:key="dept.deptId"
								:class="['cascader-item', { active: activeDeptIndex === index }]"
								@click="activeDeptIndex = index"
							>
								<text class="cascader-item-text">{{ dept.deptName }}</text>
								<text v-if="getDeptSelectedCount(dept) > 0" class="dept-badge">{{ getDeptSelectedCount(dept) }}</text>
							</view>
						</scroll-view>
						<scroll-view class="cascader-col user-col" scroll-y :key="'dept-users-' + activeDeptIndex">
							<view v-if="currentDeptUsers.length === 0" class="empty-tip">该部门暂无人员</view>
							<view v-else>
								<view class="user-item" v-for="user in currentDeptUsers" :key="'identity-' + user.identityId" :class="{ 'user-item-locked': isLockedIdentity(user.identityId) }">
									<up-checkbox
										usedAlone
										:checked="userPickerSelectedSet.has(String(user.identityId))"
										:label="formatUserPickerLabel(user)"
										:disabled="isLockedIdentity(user.identityId)"
										activeColor="#2667E9"
										shape="square"
										@change="(checked) => onUserCheckChange(user.identityId, checked)"
									></up-checkbox>
								</view>
							</view>
						</scroll-view>
					</view>
					<view class="popup-footer">
						<button class="btn-cancel" @click="cancelUserSelect">取消</button>
						<button class="btn-confirm bg-blue" @click="confirmUserSelect">确定</button>
					</view>
				</view>
			</u-popup>
			
			<view class="form-label margin-bottom margin-top">
				<view class="text-gray">整改图片</view>
				<view class="text-red">*</view>
			</view>
			<up-upload :fileList="fileList1" @afterRead="afterRead" @delete="deletePic" name="1" multiple imageMode="aspectFill"
				:maxCount="10"></up-upload>
			<!-- 隐藏的 Canvas，用于渲染防作弊时间戳水印；弹窗打开时卸载，避免原生 canvas 穿透盖住弹层 -->
			<canvas
				v-if="!showUserPopup && !showManagerPopup && !showRectifyTimePicker"
				canvas-id="watermarkCanvas"
				:width="canvasWidth"
				:height="canvasHeight"
				:style="{ width: canvasWidth + 'px', height: canvasHeight + 'px', position: 'fixed', left: '-9999px', top: '-9999px' }"
			></canvas>
			<canvas
				v-if="!showUserPopup && !showManagerPopup && !showRectifyTimePicker"
				canvas-id="watermarkCanvas"
				:width="canvasWidth"
				:height="canvasHeight"
				:style="{ width: canvasWidth + 'px', height: canvasHeight + 'px', position: 'fixed', left: '-9999px', top: '-9999px' }"
			></canvas>

			<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>

			<!-- 电子签名（表单最底部） -->
			<view class="form-label margin-bottom margin-top flex justify-between align-center" style="width: 100%;">
				<view class="flex align-center">
					<view class="text-gray">电子签名</view>
					<view class="text-red">*</view>
				</view>
				<button v-if="showCanvas" class="cu-btn sm round line-blue" style="margin: 0; padding: 0 20rpx; height: 50rpx; font-size: 22rpx;" @click="clearSignature">清除重写</button>
				<button v-else class="cu-btn sm round line-blue" style="margin: 0; padding: 0 20rpx; height: 50rpx; font-size: 22rpx;" @click="reSign">重新签名</button>
			</view>
			<view class="signature-box margin-bottom">
				<view
					v-if="!showCanvas"
					class="signature-display flex align-center justify-center"
					style="width: 100%; height: 160px; background-color: #f8f8f8;"
				>
					<image
						v-if="signatureUrl"
						:src="signatureUrl"
						class="signature-img"
						mode="aspectFit"
						style="width: 100%; height: 100%;"
						@error="onSignatureImageError"
					></image>
					<text v-else class="signature-placeholder">暂无签名，请点击重新签名</text>
				</view>
				<!-- 弹窗/选择器打开时卸载 Canvas，解决微信原生 canvas 真机穿透盖住弹层的问题 -->
				<view v-if="showCanvas && !showUserPopup && !showManagerPopup && !showRectifyTimePicker" class="signature-pad-wrap">
					<wd-signature 
						ref="signatureRef"
						:width="signatureWidth"
						:height="160"
						backgroundColor="#f8f8f8"
						penColor="#000000"
						:lineWidth="3"
						:enableHistory="false"
						@confirm="(res) => onSignatureConfirm(res.tempFilePath)"
						@start="onSignatureStart"
						@signing="onSignatureSigning"
						@end="onSignatureEnd"
						@clear="onSignatureClear"
					>
						<template #footer></template>
					</wd-signature>
				</view>
			</view>

			<button class="bg-blue round margin-top-xl" @click="handleSubmit">{{ isEdit ? '保存修改' : '提交整改' }}</button>
		</view>
	</view>
</template>

<script setup>
	import {ref,reactive,computed,nextTick,getCurrentInstance} from 'vue'
	import {onLoad, onHide} from '@dcloudio/uni-app'
	import {
		submitRectification,
		updateRectification,
		// getDepartmentPersonUsers,
		// getDeptUsersWithSubordinates,
		getRelatedDeptUsers,
		getRectifyDetail,
		getHiddenDangerDetail,
		getFlowNextNodes,
		generateRectifyPlan
	} from '@/request/api.js'
	import { buildDraftKey, buildDraftKeyCompact, DRAFT_NS } from '@/utils/draftCache.js';
	import { useDraftCache } from '@/utils/useDraftCache.js';
	import {
		createUploadListHandlers,
		buildAttachmentItem,
		uploadToCloud,
		mapServerFileToUploadItem,
		toSubmitFileUrl
	} from '@/utils/upload.js'

	// 从页面参数获取的ID
	const hazardId = ref('');
	const assignId = ref('');
	const taskId = ref('');
	const rectifyId = ref(''); // 整改ID（编辑模式时使用）
	const isEdit = ref(false); // 是否为编辑模式

	// 下一步流程（编辑模式写死展示，新建整改走接口）
	const EDIT_NEXT_STEP_NAME = '隐患验收';
	const nextStepName = ref('');
	const nextStepLoading = ref(false);

	const nextStepDisplay = computed(() => {
		if (isEdit.value) return EDIT_NEXT_STEP_NAME;
		if (nextStepLoading.value) return '加载中...';
		return nextStepName.value || '暂无下一步流程';
	});

	const resolveTaskIdFromDetail = (data) => {
		if (!data) return '';
		if (data.taskId) return String(data.taskId);
		if (data.flowTaskId) return String(data.flowTaskId);
		if (data.currentTaskId) return String(data.currentTaskId);
		const assigns = data.assigns || [];
		for (const assign of assigns) {
			if (assign?.taskId) return String(assign.taskId);
		}
		return '';
	};

	const resolveNextTaskName = (data) => {
		if (!data) return '';
		const branches = data.branches || [];
		const matchedBranch = branches.find((item) => item.matched) || branches[0];
		return matchedBranch?.nextNode?.taskName || '';
	};

	const fetchNextStep = async () => {
		nextStepLoading.value = true;
		try {
			let currentTaskId = taskId.value;
			if (!currentTaskId && rectifyId.value) {
				const rectifyRes = await getRectifyDetail({ rectifyId: rectifyId.value });
				if (rectifyRes.code === 0 && rectifyRes.data) {
					const rectifyData = rectifyRes.data;
					currentTaskId = resolveTaskIdFromDetail(rectifyData);
					if (!hazardId.value && rectifyData.hazardId) {
						hazardId.value = rectifyData.hazardId;
					}
					if (!assignId.value && rectifyData.assignId) {
						assignId.value = rectifyData.assignId;
					}
					if (currentTaskId) {
						taskId.value = currentTaskId;
					}
				}
			}
			if (!currentTaskId && hazardId.value) {
				const detailRes = await getHiddenDangerDetail({
					hazardId: hazardId.value,
					assignId: assignId.value
				});
				if (detailRes.code === 0 && detailRes.data) {
					currentTaskId = resolveTaskIdFromDetail(detailRes.data);
					if (currentTaskId) {
						taskId.value = currentTaskId;
					}
				}
			}
			if (!currentTaskId) {
				nextStepName.value = '';
				return;
			}
			const res = await getFlowNextNodes({ taskId: currentTaskId });
			if (res.code === 0) {
				const payload = res.data && typeof res.data === 'object' ? res.data : res;
				nextStepName.value = resolveNextTaskName(payload);
			} else {
				nextStepName.value = '';
			}
		} catch (error) {
			console.error('获取下一步流程失败:', error);
			nextStepName.value = '';
		} finally {
			nextStepLoading.value = false;
		}
	};

	// 防作弊时间戳水印 Canvas 大小配置
	const canvasWidth = ref(300);
	const canvasHeight = ref(300);

	// 电子签名相关
	const showCanvas = ref(true);          // 是否显示签字画板
	const signatureUrl = ref('');          // 签名完整预览地址
	const signatureServerPath = ref('');  // 签名服务器相对路径
	const signatureWidth = ref(340);       // 签名画板宽度（动态计算）
	const signatureRef = ref(null);       // 签名组件 ref
	const isSignatureEmpty = ref(true);    // 签名是否为空
	const isSubmitting = ref(false);       // 是否正在提交表单
	const signatureLocalPath = ref(''); // 未上传云端的本地签名临时图
	const isDraftExporting = ref(false); // 是否为草稿导出（非提交上传）
	let signatureExportTimer = null;

	// 清除画布
	const clearSignature = () => {
		clearTimeout(signatureExportTimer);
		isSignatureEmpty.value = true;
		signatureLocalPath.value = '';
		if (signatureRef.value) {
			signatureRef.value.clear();
		}
	};

	/** 从整改详情里解析签名地址（兼容多种后端字段名） */
	const resolveSignPathFromData = (data) => {
		if (!data) return '';
		return (
			data.signPath ||
			data.signUrl ||
			data.signature ||
			data.signatureUrl ||
			data.signaturePath ||
			''
		);
	};

	/** 将签名地址应用到预览区 */
	const applySignatureFromServer = (signPath) => {
		const url = signPath ? toSubmitFileUrl(signPath) : '';
		if (!url) {
			showCanvas.value = true;
			signatureServerPath.value = '';
			signatureUrl.value = '';
			signatureLocalPath.value = '';
			isSignatureEmpty.value = true;
			return;
		}
		signatureServerPath.value = url;
		signatureUrl.value = url;
		signatureLocalPath.value = '';
		showCanvas.value = false;
		isSignatureEmpty.value = false;
	};

	/** 将本地临时签名图应用到预览区（草稿回显） */
	const applySignatureFromLocal = (localPath) => {
		if (!localPath) return;
		signatureLocalPath.value = localPath;
		signatureUrl.value = localPath;
		signatureServerPath.value = '';
		showCanvas.value = false;
		isSignatureEmpty.value = false;
	};

	const onSignatureStart = () => {
		isSignatureEmpty.value = false;
	};

	const onSignatureSigning = () => {
		isSignatureEmpty.value = false;
	};

	const onSignatureClear = () => {
		isSignatureEmpty.value = true;
		signatureLocalPath.value = '';
	};

	const scheduleSignatureDraftExport = () => {
		clearTimeout(signatureExportTimer);
		signatureExportTimer = setTimeout(() => {
			if (
				!showCanvas.value ||
				isSignatureEmpty.value ||
				!signatureRef.value ||
				isSubmitting.value ||
				isDraftExporting.value
			) {
				return;
			}
			isDraftExporting.value = true;
			signatureRef.value.confirm();
		}, 600);
	};

	const onSignatureEnd = () => {
		isSignatureEmpty.value = false;
		scheduleSignatureDraftExport();
	};

	const onSignatureImageError = () => {
		console.error('签名图片加载失败:', signatureUrl.value);
		uni.showToast({ title: '签名图片加载失败', icon: 'none' });
	};

	// 重新签字
	const reSign = () => {
		clearTimeout(signatureExportTimer);
		isSignatureEmpty.value = true;
		showCanvas.value = true;
		signatureUrl.value = '';
		signatureServerPath.value = '';
		signatureLocalPath.value = '';
		nextTick(() => {
			if (signatureRef.value) {
				signatureRef.value.clear();
			}
		});
	};

	// 签名导出失败
	const onSignatureError = (err) => {
		console.error('签名绘制失败:', err);
		uni.showToast({ title: '签名生成失败', icon: 'none' });
		isSubmitting.value = false;
		uni.hideLoading();
	};

	// 表单数据
	const formData = reactive({
		rectifyPlan: '', // 整改方案
		rectificationMeasures: '', // 整改措施
		controlMeasures: '', // 管控措施
		rectifyResult: '', // 整改完成情况
		planCost: '', // 投资资金(计划)
		actualCost: '' // 投资资金(实际)
	});

	const selectedDeadlineDate = ref('');
	const showRectifyTimePicker = ref(false);
	const rectifyTimeValue = ref(Date.now());
	const selectedRectifyTime = ref('');

	// 短信提醒
	const sendMsgFlagRadio = ref('yes');
	const sendMsgFlag = computed(() => sendMsgFlagRadio.value === 'yes');

	const formatDateValue = (timestamp) => {
		if (!timestamp) return '';
		const date = new Date(timestamp);
		if (Number.isNaN(date.getTime())) return '';
		const year = date.getFullYear();
		const month = String(date.getMonth() + 1).padStart(2, '0');
		const day = String(date.getDate()).padStart(2, '0');
		const hours = String(date.getHours()).padStart(2, '0');
		const minutes = String(date.getMinutes()).padStart(2, '0');
		const seconds = String(date.getSeconds()).padStart(2, '0');
		return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
	};

	// 将交办时限字符串转为日期选择器时间戳
	const parseDeadlineToTimestamp = (deadline) => {
		if (!deadline) return null;
		const decoded = decodeURIComponent(String(deadline)).trim();
		const normalized = decoded.replace('T', ' ').replace(/-/g, '/');
		const ts = new Date(normalized).getTime();
		return Number.isNaN(ts) ? null : ts;
	};

	const applyDeadlineFromOptions = (deadline) => {
		const ts = parseDeadlineToTimestamp(deadline);
		if (ts) {
			selectedDeadlineDate.value = formatDateValue(ts);
		} else if (deadline) {
			selectedDeadlineDate.value = String(deadline).trim().replace('T', ' ');
		}
	};

	const applyAssigneeFromOptions = (assigneeId, assigneeName, assigneeIdentityId) => {
		if (!assigneeIdentityId) return;
		const identityId = String(assigneeIdentityId);
		const name = assigneeName ? decodeURIComponent(String(assigneeName)).trim() : '';
		const exists = detailPersonPool.value.some((user) => String(user.identityId) === identityId);
		if (!exists) {
			detailPersonPool.value.push({
				userId: assigneeId || '',
				identityId: assigneeIdentityId,
				nickName: name,
				deptName: ''
			});
		}
		if (!lockedIdentityIds.value.includes(identityId)) {
			lockedIdentityIds.value = [...lockedIdentityIds.value, identityId];
		}
		selectedIdentityIds.value = mergeLockedIdentityIds([identityId]);
		syncSelectedMembersFromIdentityIds(selectedIdentityIds.value);
	};

	const setLockedDefaultIdentities = (ids) => {
		const normalized = parseIdList(ids);
		if (!normalized.length) return;
		lockedIdentityIds.value = normalized;
		selectedIdentityIds.value = mergeLockedIdentityIds(selectedIdentityIds.value);
		syncSelectedMembersFromIdentityIds(selectedIdentityIds.value);
	};

	const parseIdList = (raw) => {
		if (raw === null || raw === undefined || raw === '') return [];
		if (Array.isArray(raw)) {
			return raw.map((id) => String(id)).filter(Boolean);
		}
		return String(raw).split(',').map((id) => String(id).trim()).filter(Boolean);
	};

	const resolveManagerIdentityIdsFromDetail = (data) => {
		const ids = parseIdList(data.managerIds ?? data.manageIds ?? data.manageIdentityIds ?? data.managerIdentityIds);
		if (ids.length > 0) return ids;
		if (Array.isArray(data.managers) && data.managers.length > 0) {
			return data.managers
				.map((item) => String(item.identityId ?? item.userId))
				.filter(Boolean);
		}
		return [];
	};

	const getMembersByIdentityIdsFromTree = (ids, tree) => {
		const memberMap = new Map();
		(tree || []).forEach((dept) => {
			(dept.users || []).forEach((user) => {
				if (user.identityId != null && user.identityId !== '') {
					memberMap.set(String(user.identityId), buildMemberItem(user, dept));
				}
			});
		});
		return ids.map((id) => memberMap.get(String(id))).filter(Boolean);
	};

	const mergeMembersFromDetailPool = (ids, resolvedMembers) => {
		const memberMap = new Map(resolvedMembers.map((member) => [member.id, member]));
		ids.forEach((id) => {
			const key = String(id);
			if (memberMap.has(key)) return;
			const found = detailPersonPool.value.find((user) => String(user.identityId) === key);
			if (found) {
				memberMap.set(key, buildMemberItemFromDetail(found));
			}
		});
		return ids.map((id) => memberMap.get(String(id))).filter(Boolean);
	};

	const applyRectifyTimeValue = (timeStr) => {
		const ts = parseDeadlineToTimestamp(timeStr);
		if (ts) {
			rectifyTimeValue.value = ts;
			selectedRectifyTime.value = formatDateValue(ts);
		} else if (timeStr) {
			selectedRectifyTime.value = String(timeStr).trim().replace('T', ' ');
		}
	};

	const initRectifyTimeDefault = () => {
		rectifyTimeValue.value = Date.now();
		selectedRectifyTime.value = formatDateValue(rectifyTimeValue.value);
	};

	const onRectifyTimeConfirm = (e) => {
		rectifyTimeValue.value = e.value;
		selectedRectifyTime.value = formatDateValue(e.value);
		showRectifyTimePicker.value = false;
	};

	// 人员列表（安全管理人员、整改责任人：关联部门及人员，type=2）
	const managerDeptList = ref([])
	const deptList = ref([])
	const detailPersonPool = ref([])
	const showManagerPopup = ref(false)
	const selectedManagerIdentityIds = ref([])
	const selectedManagers = ref([])
	const activeManagerDeptIndex = ref(0)
	const managerPickerSelectedIdentityIds = ref([])
	const showUserPopup = ref(false)
	const selectedIdentityIds = ref([])
	const selectedUsers = ref([])
	const lockedIdentityIds = ref([])
	const activeDeptIndex = ref(0)
	const userPickerSelectedIdentityIds = ref([])

	const isLockedIdentity = (identityId) => lockedIdentityIds.value.includes(String(identityId));

	const mergeLockedIdentityIds = (ids) => {
		const merged = new Set([
			...(ids || []).map((id) => String(id)),
			...lockedIdentityIds.value.map((id) => String(id))
		]);
		return [...merged];
	};

	const formatMemberDisplayName = (user) => {
		if (user.identityName) {
			return `${user.nickName}_${user.identityName}`;
		}
		if (user.postName) {
			return `${user.nickName}_${user.postName}`;
		}
		return user.nickName || '';
	};

	const formatUserPickerLabel = (user) => {
		const name = formatMemberDisplayName(user);
		return isLockedIdentity(user.identityId) ? `${name}（默认）` : name;
	};

	const buildMemberItem = (user, dept) => ({
		id: String(user.identityId),
		userId: user.userId,
		name: formatMemberDisplayName(user),
		deptName: dept.deptName
	});

	const buildMemberItemFromDetail = (user) => ({
		id: String(user.identityId || user.userId),
		name: formatMemberDisplayName(user),
		deptName: user.deptName || ''
	});

	const buildSelectedPersonText = (users) => {
		if (users.length === 0) return '';
		if (users.length <= 2) {
			return users.map((u) => u.name).join('、');
		}
		return `${users[0].name}等${users.length}人`;
	};

	const selectedManagersText = computed(() => buildSelectedPersonText(selectedManagers.value));
	const selectedUsersText = computed(() => buildSelectedPersonText(selectedUsers.value));

	const currentManagerDeptUsers = computed(() => {
		const dept = managerDeptList.value[activeManagerDeptIndex.value];
		return dept?.users || [];
	});

	const managerPickerSelectedText = computed(() => {
		const users = getManagersByIdentityIds(managerPickerSelectedIdentityIds.value);
		return buildSelectedPersonText(users);
	});

	const managerPickerSelectedSet = computed(() => {
		return new Set(managerPickerSelectedIdentityIds.value.map((id) => String(id)));
	});

	const currentDeptUsers = computed(() => {
		const dept = deptList.value[activeDeptIndex.value];
		return dept?.users || [];
	});

	const userPickerSelectedText = computed(() => {
		const users = getMembersByIdentityIds(userPickerSelectedIdentityIds.value);
		return buildSelectedPersonText(users);
	});

	const userPickerSelectedSet = computed(() => {
		return new Set(userPickerSelectedIdentityIds.value.map((id) => String(id)));
	});

	const getManagersByIdentityIds = (ids) => {
		let members = getMembersByIdentityIdsFromTree(ids, managerDeptList.value);
		if (members.length < ids.length) {
			const deptMembers = getMembersByIdentityIdsFromTree(ids, deptList.value);
			const memberMap = new Map(members.map((member) => [member.id, member]));
			deptMembers.forEach((member) => {
				if (!memberMap.has(member.id)) memberMap.set(member.id, member);
			});
			members = ids.map((id) => memberMap.get(String(id))).filter(Boolean);
		}
		return mergeMembersFromDetailPool(ids, members);
	};

	const getMembersByIdentityIds = (ids) => {
		let members = getMembersByIdentityIdsFromTree(ids, deptList.value);
		return mergeMembersFromDetailPool(ids, members);
	};

	const syncSelectedManagersFromIdentityIds = (ids) => {
		selectedManagers.value = getManagersByIdentityIds(ids);
	};

	const syncSelectedMembersFromIdentityIds = (ids) => {
		selectedUsers.value = getMembersByIdentityIds(ids);
	};

	const getManagerDeptSelectedCount = (dept) => {
		if (!dept.users?.length) return 0;
		const selectedSet = new Set(managerPickerSelectedIdentityIds.value.map(String));
		return dept.users.filter((user) => selectedSet.has(String(user.identityId))).length;
	};

	const getDeptSelectedCount = (dept) => {
		if (!dept.users?.length) return 0;
		const selectedSet = new Set(userPickerSelectedIdentityIds.value.map(String));
		return dept.users.filter((user) => selectedSet.has(String(user.identityId))).length;
	};

	function onManagerCheckChange(identityId, checked) {
		const id = String(identityId);
		if (checked) {
			if (!managerPickerSelectedSet.value.has(id)) {
				managerPickerSelectedIdentityIds.value = [...managerPickerSelectedIdentityIds.value, id];
			}
			return;
		}
		managerPickerSelectedIdentityIds.value = managerPickerSelectedIdentityIds.value.filter((item) => String(item) !== id);
	}

	function onUserCheckChange(identityId, checked) {
		const id = String(identityId);
		if (!checked && isLockedIdentity(id)) {
			uni.showToast({ title: '默认整改责任人不可取消', icon: 'none' });
			return;
		}
		if (checked) {
			if (!userPickerSelectedSet.value.has(id)) {
				userPickerSelectedIdentityIds.value = [...userPickerSelectedIdentityIds.value, id];
			}
			return;
		}
		userPickerSelectedIdentityIds.value = userPickerSelectedIdentityIds.value.filter((item) => String(item) !== id);
	}

	const openManagerPopup = () => {
		managerPickerSelectedIdentityIds.value = [...selectedManagerIdentityIds.value];
		const firstDeptWithUsers = managerDeptList.value.findIndex((dept) => dept.users?.length > 0);
		activeManagerDeptIndex.value = firstDeptWithUsers >= 0 ? firstDeptWithUsers : 0;
		showManagerPopup.value = true;
	};

	const cancelManagerSelect = () => {
		showManagerPopup.value = false;
	};

	const openUserPopup = () => {
		userPickerSelectedIdentityIds.value = mergeLockedIdentityIds(selectedIdentityIds.value);
		const firstDeptWithUsers = deptList.value.findIndex((dept) => dept.users?.length > 0);
		activeDeptIndex.value = firstDeptWithUsers >= 0 ? firstDeptWithUsers : 0;
		showUserPopup.value = true;
	};

	const cancelUserSelect = () => {
		showUserPopup.value = false;
	};
	
	// 确认选择安全管理人员
	const confirmManagerSelect = () => {
		selectedManagerIdentityIds.value = managerPickerSelectedIdentityIds.value.map((id) => String(id));
		syncSelectedManagersFromIdentityIds(selectedManagerIdentityIds.value);
		showManagerPopup.value = false;
	};

	// 确认选择整改责任人
	const confirmUserSelect = () => {
		userPickerSelectedIdentityIds.value = mergeLockedIdentityIds(userPickerSelectedIdentityIds.value);
		selectedIdentityIds.value = userPickerSelectedIdentityIds.value.map((id) => String(id));
		syncSelectedMembersFromIdentityIds(selectedIdentityIds.value);
		showUserPopup.value = false;
	};
	
	// 获取关联部门及人员列表（全部上级部门、本部门、全部下级部门）
	const fetchRelatedDeptUsers = async () => {
		try {
			const res = await getRelatedDeptUsers({ type: 2 });
			if (res.code === 0 && res.data) {
				managerDeptList.value = res.data;
				deptList.value = res.data;
				if (selectedManagerIdentityIds.value.length > 0) {
					syncSelectedManagersFromIdentityIds(selectedManagerIdentityIds.value);
				}
				if (selectedIdentityIds.value.length > 0) {
					syncSelectedMembersFromIdentityIds(selectedIdentityIds.value);
				}
			}
		} catch (error) {
			console.error('获取关联部门人员列表失败:', error);
		}
	};

	// 获取安全管理人员候选列表（本部门及上级部门）
	// const fetchManagerDeptUsers = async () => {
	// 	try {
	// 		const res = await getDepartmentPersonUsers();
	// 		if (res.code === 0 && res.data) {
	// 			managerDeptList.value = res.data;
	// 			if (selectedManagerIds.value.length > 0) {
	// 				syncSelectedManagersFromIds(selectedManagerIds.value);
	// 			}
	// 		}
	// 	} catch (error) {
	// 		console.error('获取安全管理人员列表失败:', error);
	// 	}
	// };

	// 获取整改责任人候选列表（隐患关联部门人员）
	// const fetchRectifyDeptUsers = async () => {
	// 	console.log('当前hazardId:', hazardId.value);
	// 	try {
	// 		const res = await getDeptUsersWithSubordinates({ hazardId: hazardId.value });
	// 		if (res.code === 0 && res.data) {
	// 			deptList.value = res.data;
	// 			if (selectedUserIds.value.length > 0) {
	// 				syncSelectedUsersFromIds(selectedUserIds.value);
	// 			}
	// 			console.log('整改责任人部门树:', deptList.value);
	// 		}
	// 	} catch (error) {
	// 		console.error('获取整改责任人列表失败:', error);
	// 	}
	// };

	const fetchPersonnelLists = async () => {
		await fetchRelatedDeptUsers();
		if (selectedManagerIdentityIds.value.length > 0) {
			syncSelectedManagersFromIdentityIds(selectedManagerIdentityIds.value);
		}
	};

	const fileList1 = ref([]);
	const rectifyUploadInstance = getCurrentInstance();
	const { afterRead, deletePic } = createUploadListHandlers(fileList1, {
		watermark: {
			canvasId: 'watermarkCanvas',
			canvasWidthRef: canvasWidth,
			canvasHeightRef: canvasHeight,
			instance: rectifyUploadInstance
		}
	});

	// 构建提交/保存共用的整改业务字段
	const buildSharedRectifyParams = (attachments) => {
		const params = {
			rectifyPlan: formData.rectifyPlan,
			rectificationMeasures: formData.rectificationMeasures,
			controlMeasures: formData.controlMeasures,
			rectifyResult: formData.rectifyResult,
			planCost: Number(formData.planCost) || 0,
			actualCost: Number(formData.actualCost) || 0,
			attachments,
			managerIds: selectedManagerIdentityIds.value.map((id) => Number(id)),
			memberIds: selectedIdentityIds.value.map((id) => Number(id)),
			rectifyTime: selectedRectifyTime.value || formatDateValue(rectifyTimeValue.value),
			signPath: signatureServerPath.value || '',
			sendMsgFlag: sendMsgFlag.value
		};
		if (selectedDeadlineDate.value) {
			params.deadline = selectedDeadlineDate.value;
		}
		return params;
	};

	// 真正的提交/保存接口请求
	const executeSubmit = async () => {
		const attachments = fileList1.value
			.filter((f) => f.status === 'success')
			.map((file) => buildAttachmentItem(file));

		try {
			let res;
			if (isEdit.value) {
				const updateParams = {
					rectifyId: Number(rectifyId.value),
					hazardId: hazardId.value,
					assignId: assignId.value,
					...buildSharedRectifyParams(attachments)
				};
				res = await updateRectification(updateParams);
			} else {
				const params = {
					hazardId: hazardId.value,
					assignId: assignId.value,
					...buildSharedRectifyParams(attachments)
				};
				res = await submitRectification(params);
			}

			uni.hideLoading();
			if (res.code === 0) {
				clearDraft(false);
				uni.showToast({
					title: isEdit.value ? '保存成功' : '提交成功',
					icon: 'success'
				});
				setTimeout(() => {
					uni.navigateBack();
				}, 1500);
			} else {
				uni.showToast({
					title: res.msg || (isEdit.value ? '保存失败' : '提交失败'),
					icon: 'none'
				});
			}
		} catch (error) {
			uni.hideLoading();
			console.error(isEdit.value ? '保存整改失败:' : '提交整改失败:', error);
			uni.showToast({
				title: '操作失败',
				icon: 'none'
			});
		} finally {
			isSubmitting.value = false;
		}
	};

	// 签名导出成功回调
	const onSignatureConfirm = async (tempFilePath) => {
		if (isDraftExporting.value) {
			isDraftExporting.value = false;
			applySignatureFromLocal(tempFilePath);
			saveDraft();
			return;
		}

		try {
			const { url } = await uploadToCloud(tempFilePath);
			applySignatureFromServer(url);
			saveDraft();

			if (isSubmitting.value) {
				await executeSubmit();
			}
		} catch (err) {
			isSubmitting.value = false;
			uni.hideLoading();
			console.error('签名上传失败:', err);
			uni.showToast({ title: '签名上传失败，请重试', icon: 'none' });
		}
	};

	// 提交整改（触发签名导出或直接提交）
	const handleSubmit = async () => {
		if (!formData.rectifyPlan) {
			uni.showToast({
				title: '请输入整改方案',
				icon: 'none'
			});
			return;
		}
		if (!formData.rectificationMeasures) {
			uni.showToast({
				title: '请输入整改措施',
				icon: 'none'
			});
			return;
		}
		if (!formData.controlMeasures) {
			uni.showToast({
				title: '请输入管控措施',
				icon: 'none'
			});
			return;
		}
		if (!formData.rectifyResult) {
			uni.showToast({
				title: '请输入整改完成情况',
				icon: 'none'
			});
			return;
		}
		if (!selectedRectifyTime.value) {
			uni.showToast({
				title: '请选择实际整改时间',
				icon: 'none'
			});
			return;
		}
		if (selectedManagers.value.length === 0) {
			uni.showToast({
				title: '请选择安全管理人员',
				icon: 'none'
			});
			return;
		}
		if (selectedUsers.value.length === 0) {
			uni.showToast({
				title: '请选择整改责任人',
				icon: 'none'
			});
			return;
		}

		// 电子签名验证与处理
		if (showCanvas.value) {
			if (!signatureRef.value || isSignatureEmpty.value) {
				uni.showToast({
					title: '请进行电子签名',
					icon: 'none'
				});
				return;
			}
			
			isSubmitting.value = true;
			uni.showLoading({ title: '正在提交...', mask: true });
			// 触发组件导出，导出成功会回调 onSignatureConfirm
			signatureRef.value.confirm();
		} else {
			// 已经有回显的签名（云端或本地草稿）
			if (!signatureServerPath.value && !signatureLocalPath.value) {
				uni.showToast({
					title: '请进行电子签名',
					icon: 'none'
				});
				return;
			}
			isSubmitting.value = true;
			uni.showLoading({ title: '正在提交...', mask: true });
			try {
				if (!signatureServerPath.value && signatureLocalPath.value) {
					const { url } = await uploadToCloud(signatureLocalPath.value);
					applySignatureFromServer(url);
				}
				await executeSubmit();
			} catch (err) {
				isSubmitting.value = false;
				uni.hideLoading();
				console.error('签名上传失败:', err);
				uni.showToast({ title: '签名上传失败，请重试', icon: 'none' });
			}
		}
	};

	const handleSubmitOld = async () => {
		if (!formData.rectifyPlan) {
			uni.showToast({
				title: '请输入整改方案',
				icon: 'none'
			});
			return;
		}
		if (!formData.rectifyResult) {
			uni.showToast({
				title: '请输入整改完成情况',
				icon: 'none'
			});
			return;
		}
		if (selectedUsers.value.length === 0) {
			uni.showToast({
				title: '请选择整改人员',
				icon: 'none'
			});
			return;
		}

		const attachments = fileList1.value
			.filter((f) => f.status === 'success')
			.map((file) => buildAttachmentItem(file));

		const params = {
			hazardId: hazardId.value,
			assignId: assignId.value,
			rectifyPlan: formData.rectifyPlan,
			rectifyResult: formData.rectifyResult,
			planCost: Number(formData.planCost) || 0,
			actualCost: Number(formData.actualCost) || 0,
			attachments: attachments,
			memberIds: selectedIdentityIds.value.map(id => Number(id))
		};
		
		// 编辑模式需要传递rectifyId
		if (rectifyId.value) {
			params.rectifyId = rectifyId.value;
		}

		try {
			const res = await submitRectification(params);
			if (res.code === 0) {
				uni.showToast({
					title: isEdit.value ? '保存成功' : '提交成功',
					icon: 'success'
				});
				setTimeout(() => {
					uni.navigateBack();
				}, 1500);
			} else {
				uni.showToast({
					title: res.msg || (isEdit.value ? '保存失败' : '提交失败'),
					icon: 'none'
				});
			}
		} catch (error) {
			console.error('提交整改失败:', error);
			uni.showToast({
				title: '操作失败',
				icon: 'none'
			});
		}
	};

	// 获取整改详情（编辑模式）
	const fetchRectifyDetail = async () => {
		try {
			uni.showLoading({ title: '加载中...' });
			const res = await getRectifyDetail({ rectifyId: rectifyId.value });
			uni.hideLoading();
			
			if (res.code === 0 && res.data) {
				const data = res.data;
				// 回显表单数据
				formData.rectifyPlan = data.rectifyPlan || '';
				formData.rectificationMeasures = data.rectificationMeasures || '';
				formData.controlMeasures = data.controlMeasures || '';
				formData.rectifyResult = data.rectifyResult || '';
				formData.planCost = data.planCost ? String(data.planCost) : '';
				formData.actualCost = data.actualCost ? String(data.actualCost) : '';

				// 回显限定整改时间
				if (data.deadline) {
					applyDeadlineFromOptions(data.deadline);
				}

				// 回显实际整改时间
				if (data.rectifyTime) {
					applyRectifyTimeValue(data.rectifyTime);
				}
				
				// 回显电子签名
				const signPath = resolveSignPathFromData(data);
				console.log('整改详情签名路径:', signPath);
				applySignatureFromServer(signPath);
				
				// 保存hazardId和assignId
				hazardId.value = data.hazardId || '';
				assignId.value = data.assignId || '';
				const resolvedTaskId = resolveTaskIdFromDetail(data);
				if (resolvedTaskId) {
					taskId.value = resolvedTaskId;
				}
				detailPersonPool.value = [
					...(Array.isArray(data.managers) ? data.managers : []),
					...(Array.isArray(data.members) ? data.members : [])
				];

				// 先解析人员 ID，再拉取候选列表并回显
				const managerIdentityIdArr = resolveManagerIdentityIdsFromDetail(data);
				if (managerIdentityIdArr.length > 0) {
					selectedManagerIdentityIds.value = managerIdentityIdArr;
				}
				const memberIdentityIdArr = parseIdList(data.memberIds ?? data.memberIdentityIds);
				if (memberIdentityIdArr.length > 0) {
					selectedIdentityIds.value = memberIdentityIdArr;
				} else if (data.rectifierIdentityId) {
					selectedIdentityIds.value = [String(data.rectifierIdentityId)];
				}
				if (data.assigneeIdentityId) {
					setLockedDefaultIdentities(data.assigneeIdentityId);
				} else if (data.rectifierIdentityId) {
					setLockedDefaultIdentities(data.rectifierIdentityId);
				}
				await fetchPersonnelLists();

				// 回显附件
				if (data.attachments && data.attachments.length > 0) {
					fileList1.value = data.attachments.map((att) => mapServerFileToUploadItem(att));
				}
				
				// 设置页面标题
				uni.setNavigationBarTitle({ title: '编辑整改信息' });
			}
		} catch (error) {
			uni.hideLoading();
			console.error('获取整改详情失败:', error);
			uni.showToast({ title: '获取详情失败', icon: 'none' });
		}
	};

	// AI生成整改方案
	const aiGenerating = ref(false);
	const handleAiGenerate = async () => {
		if (!hazardId.value) {
			uni.showToast({ title: '缺少隐患信息', icon: 'none' });
			return;
		}
		
		aiGenerating.value = true;
		try {
			const detailRes = await getHiddenDangerDetail({
				hazardId: hazardId.value,
				assignId: assignId.value
			});
			
			if (detailRes.code !== 0 || !detailRes.data) {
				uni.showToast({ title: '获取隐患详情失败', icon: 'none' });
				return;
			}
			
			const { title, description } = detailRes.data;
			const aiRes = await generateRectifyPlan({ title, description });
			
			if (aiRes.code === 0 && aiRes.data) {
				if (aiRes.data.rawResponse) {
					formData.rectifyPlan = aiRes.data.rawResponse;
				}
				uni.showToast({ title: 'AI生成完成', icon: 'success', duration: 2000 });
			} else {
				uni.showToast({ title: aiRes.msg || 'AI生成失败', icon: 'none' });
			}
		} catch (error) {
			console.error('AI生成整改方案失败:', error);
			uni.showToast({ title: 'AI生成失败，请重试', icon: 'none' });
		} finally {
			aiGenerating.value = false;
		}
	};

	const signaturePaths = ref([]);

	const rectifyDraftHasContent = (data) => {
		const form = data.formData || {};
		return !!(
			form.rectifyPlan ||
			form.rectificationMeasures ||
			form.controlMeasures ||
			form.rectifyResult ||
			form.planCost ||
			form.actualCost ||
			(data.fileList1 && data.fileList1.length > 0) ||
			data.signatureServerPath ||
			data.signatureLocalPath ||
			(data.signaturePaths && data.signaturePaths.length > 0)
		);
	};

	const {
		showRestoreBanner,
		clear: clearDraft,
		restore: restoreDraft,
		save: saveDraft,
		bindAutoSave
	} = useDraftCache({
		getKey: () => buildDraftKey(DRAFT_NS.RECTIFY, hazardId.value, rectifyId.value),
		getFallbackKeys: () => {
			const primary = buildDraftKey(DRAFT_NS.RECTIFY, hazardId.value, rectifyId.value);
			const compact = buildDraftKeyCompact(DRAFT_NS.RECTIFY, hazardId.value, rectifyId.value);
			return compact !== primary ? [compact] : [];
		},
		getPayload: () => ({
			formData: {
				rectifyPlan: formData.rectifyPlan,
				rectificationMeasures: formData.rectificationMeasures,
				controlMeasures: formData.controlMeasures,
				rectifyResult: formData.rectifyResult,
				planCost: formData.planCost,
				actualCost: formData.actualCost
			},
			fileList1: fileList1.value,
			signatureServerPath: signatureServerPath.value,
			signatureUrl: signatureUrl.value,
			signatureLocalPath: signatureLocalPath.value,
			showCanvas: showCanvas.value,
			signaturePaths: signaturePaths.value,
			sendMsgFlagRadio: sendMsgFlagRadio.value
		}),
		hasContent: rectifyDraftHasContent,
		applyPayload: (data) => {
			const form = data.formData || {};
			formData.rectifyPlan = form.rectifyPlan || '';
			formData.rectificationMeasures = form.rectificationMeasures || '';
			formData.controlMeasures = form.controlMeasures || '';
			formData.rectifyResult = form.rectifyResult || '';
			formData.planCost = form.planCost || '';
			formData.actualCost = form.actualCost || '';
			fileList1.value = data.fileList1 || [];
			signaturePaths.value = data.signaturePaths || [];
			if (data.signatureServerPath || data.signatureUrl) {
				applySignatureFromServer(data.signatureServerPath || data.signatureUrl);
			} else if (data.signatureLocalPath) {
				applySignatureFromLocal(data.signatureLocalPath);
			} else if (data.showCanvas === false) {
				showCanvas.value = false;
			}
			sendMsgFlagRadio.value = data.sendMsgFlagRadio === 'no' ? 'no' : 'yes';
		},
		clearForm: () => {
			formData.rectifyPlan = '';
			formData.rectificationMeasures = '';
			formData.controlMeasures = '';
			formData.rectifyResult = '';
			formData.planCost = '';
			formData.actualCost = '';
			fileList1.value = [];
			signatureServerPath.value = '';
			signatureUrl.value = '';
			signatureLocalPath.value = '';
			showCanvas.value = true;
			signaturePaths.value = [];
			if (signatureRef.value) {
				signatureRef.value.clear();
			}
			sendMsgFlagRadio.value = 'yes';
		},
		canSave: () => !!(hazardId.value || rectifyId.value),
		onAfterRestore: (data) => {
			if (data.signatureServerPath || data.signatureUrl || data.signatureLocalPath) {
				return;
			}
			if (data.signaturePaths?.length > 0) {
				setTimeout(() => {
					if (signatureRef.value) {
						isSignatureEmpty.value = false;
					}
				}, 450);
			}
		}
	});

	bindAutoSave(() => [
		formData.rectifyPlan,
		formData.rectificationMeasures,
		formData.controlMeasures,
		formData.rectifyResult,
		formData.planCost,
		formData.actualCost,
		fileList1.value,
		signatureServerPath.value,
		signatureUrl.value,
		signatureLocalPath.value,
		showCanvas.value,
		signaturePaths.value,
		sendMsgFlagRadio.value
	]);

	onHide(() => {
		if (showCanvas.value && !isSignatureEmpty.value && signatureRef.value && !isDraftExporting.value) {
			isDraftExporting.value = true;
			signatureRef.value.confirm();
		}
		saveDraft();
	});

	onLoad((options) => {
		// 计算签名画布宽度
		try {
			const sysInfo = uni.getSystemInfoSync();
			signatureWidth.value = sysInfo.windowWidth - 40;
		} catch (e) {
			console.error('获取系统信息失败:', e);
		}
		if (options.hazardId) {
			hazardId.value = options.hazardId;
		}
		if (options.assignId) {
			assignId.value = options.assignId;
		}
		if (options.taskId) {
			taskId.value = options.taskId;
		}

		if (!options.rectifyId && options.assigneeIdentityId) {
			applyAssigneeFromOptions(options.assigneeId, options.assigneeName, options.assigneeIdentityId);
		}
		
		// 在hazardId赋值后调用，确保有值
		if (!options.rectifyId) fetchPersonnelLists();
		
		// 编辑模式：以接口详情为准，不使用本地草稿覆盖签名
		if (options.rectifyId) {
			rectifyId.value = options.rectifyId;
			isEdit.value = options.isEdit === '1';
			fetchRectifyDetail();
		} else {
			// 页面打开时自动恢复草稿 (不包含选择器缓存，以防打乱UI时钟)
			restoreDraft();
			initRectifyTimeDefault();
		}

		// 从列表页带入的限定整改时间（待整改交办 deadline）
		if (options.deadline) {
			applyDeadlineFromOptions(options.deadline);
		}

		if (!options.rectifyId) {
			fetchNextStep();
		}
	});
</script>

<style lang="scss" scoped>
	.page {
		min-height: 100vh;
		background: #EBF2FC;
	}
	
	.ai-rectify-btn {
		display: flex;
		align-items: center;
		justify-content: center;
		height: 60rpx;
		padding: 0 24rpx;
		margin: 0;
		font-size: 24rpx;
		color: #fff;
		background: linear-gradient(135deg, #4facfe 0%, #2668EA 100%);
		border-radius: 30rpx;
		border: none;
		white-space: nowrap;
		flex-shrink: 0;
		
		&::after {
			border: none;
		}
		
		.ai-btn-icon {
			margin-right: 6rpx;
			font-size: 26rpx;
		}
		
		&[disabled] {
			opacity: 0.7;
		}
	}
	
	.form-header {
		display: flex;
		align-items: center;
		justify-content: space-between;
		width: 100%;
	}
	
	.form-label {
		display: flex;
		align-items: center;
		
		.text-red {
			margin-left: 4rpx;
			line-height: 1;
		}
	}

	.date-input {
		background: #fff;
		border-radius: 8rpx;
		padding: 24rpx 20rpx;
		margin-bottom: 20rpx;
		border: 1rpx solid #F6F6F6;

		text {
			font-size: 28rpx;
			color: #333;
		}
	}

	.readonly-field {
		background: #f5f7fa;
		border: 1rpx solid #dcdfe6;
		border-radius: 8rpx;
		padding: 20rpx 24rpx;
		margin-bottom: 20rpx;
		font-size: 28rpx;
		color: #333;
	}

	.static-field {
		background: #fff;
		border: 1rpx solid #dcdfe6;
		border-radius: 8rpx;
		padding: 20rpx 24rpx;
		margin-bottom: 20rpx;
		font-size: 28rpx;
		color: #333;
		line-height: 1.5;
	}
	
	// 选择触发器样式
	.select-trigger {
		display: flex;
		align-items: center;
		justify-content: space-between;
		background: #fff;
		border: 1rpx solid #dcdfe6;
		border-radius: 8rpx;
		padding: 20rpx 24rpx;
		margin-bottom: 20rpx;
		
		.select-content {
			flex: 1;
			font-size: 28rpx;
			color: #333;
		}
	}
	
	// 人员选择弹窗
	.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;
			}
		}
		
		.popup-body {
			padding: 20rpx 30rpx;
			max-height: 600rpx;
			overflow-y: auto;
		}

		&.cascader-user-popup {
			.selected-summary {
				padding: 16rpx 30rpx;
				background: #f5f7fa;
				border-bottom: 1rpx solid #eee;
				font-size: 24rpx;
				line-height: 1.5;

				.summary-label {
					color: #909399;
				}

				.summary-text {
					color: #333;
				}
			}

			.cascader-body {
				display: flex;
				height: 600rpx;
				border-bottom: 1rpx solid #eee;
			}

			.cascader-col {
				height: 600rpx;
				box-sizing: border-box;
			}

			.dept-col {
				width: 38%;
				background: #f7f8fa;
				border-right: 1rpx solid #eee;
			}

			.user-col {
				width: 62%;
				padding: 10rpx 20rpx;
				box-sizing: border-box;
			}

			.cascader-item {
				display: flex;
				align-items: center;
				justify-content: space-between;
				padding: 28rpx 24rpx;
				font-size: 28rpx;
				color: #333;
				border-bottom: 1rpx solid #eef0f3;

				&.active {
					background: #fff;
					color: #2667E9;
					font-weight: 600;
					position: relative;

					&::before {
						content: '';
						position: absolute;
						left: 0;
						top: 0;
						bottom: 0;
						width: 6rpx;
						background: #2667E9;
					}
				}
			}

			.cascader-item-text {
				flex: 1;
				overflow: hidden;
				text-overflow: ellipsis;
				white-space: nowrap;
			}

			.dept-badge {
				min-width: 32rpx;
				height: 32rpx;
				line-height: 32rpx;
				padding: 0 8rpx;
				margin-left: 8rpx;
				border-radius: 16rpx;
				background: #2667E9;
				color: #fff;
				font-size: 20rpx;
				text-align: center;
			}

			.empty-tip {
				padding: 80rpx 20rpx;
				text-align: center;
				color: #909399;
				font-size: 26rpx;
			}
		}
		
		.user-item {
			padding: 24rpx 0;
			border-bottom: 1rpx solid #f5f5f5;
			
			&:last-child {
				border-bottom: none;
			}
		}

		.user-item-locked {
			opacity: 0.85;
		}
		
		.popup-footer {
			display: flex;
			border-top: 1rpx solid #eee;
			padding-bottom: env(safe-area-inset-bottom);
			
			button {
				flex: 1;
				height: 90rpx;
				line-height: 90rpx;
				border-radius: 0;
				font-size: 30rpx;
				
				&::after {
					border: none;
				}
			}
			
			.btn-cancel {
				background: #fff;
				color: #666;
			}
			
			.btn-confirm {
				color: #fff;
			}
		}
	}
	// 签名相关样式
	.signature-box {
		width: 100%;
		min-height: 240rpx;
		background: #f8f8f8;
		border: 1rpx dashed #dcdfe6;
		border-radius: 8rpx;
		margin-top: 16rpx;
		
		.signature-img {
			width: 100%;
			height: 100%;
		}
		
		.signature-placeholder {
			color: #909399;
			font-size: 28rpx;
		}
	}
	
	.signature-popup {
		width: 650rpx;
		background: #fff;
		border-radius: 16rpx;
		overflow: hidden;
		
		.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;
			}
		}
		
		.popup-body {
			padding: 40rpx 30rpx;
			background: #fff;
		}
		
		.popup-footer {
			display: flex;
			padding: 0 30rpx 30rpx;
			gap: 20rpx;
			
			button {
				flex: 1;
				height: 80rpx;
				line-height: 80rpx;
				font-size: 28rpx;
				border-radius: 40rpx;
				
				&::after {
					border: none;
				}
			}
			
			.btn-cancel {
				background: #f5f5f5;
				color: #666;
			}
			
			.btn-confirm {
				color: #fff;
			}
		}
	}
</style>