<template>
	<!--补卡审批申请-->
	<view class="card-replacement">
		<view class="main">
			<view class="header">
				<view
					v-for="(item, idx) in detailInfo.checkNoTime"
					:key="idx"
				>
					{{ item }} 缺卡
				</view>
				<view>{{ detailInfo.applyNum }}</view>
			</view>

			<u--form
				labelPosition="left"
				:model="fmData"
				:rules="rules"
				ref="uForm"
				labelWidth="auto"
				class="dynamic-form"
			>
				<!--不可新增fmItem-->
				<view class="def-box">
					<u-form-item
						:key="item.id"
						v-for="item in defList"
						:label="item.name"
						:prop="item.valueKey"
						:required="!!item.isRequire"
						borderBottom
					>
						<!-- text  -->
						<c-input
							v-if="item.type === typeKeys.text"
							:placeholder="item.tips"
							class="input-text"
							type="text"
							v-model="fmData[item.valueKey]"
							border="none"
						></c-input>

						<!-- number  -->
						<c-input-number
							v-if="item.type === typeKeys.number"
							class="input-text"
							v-model="fmData[item.valueKey]"
							:placeholder="item.tips"
							border="none"
						></c-input-number>

						<!-- phoneNum  -->
						<c-input
							v-if="item.type === typeKeys.phoneNum"
							class="input-text"
							type="number"
							:placeholder="item.tips"
							maxlength="11"
							v-model="fmData[item.valueKey]"
							border="none"
						></c-input>

						<!-- select  -->
						<view
							class="align-right"
							v-if="item.type === typeKeys.select"
						>
							<pickerSelect
								v-model="fmData[item.valueKey]"
								:placeholder="item.tips || '请选择'"
								:columns="item.variables"
							></pickerSelect>
						</view>

						<!-- radio  -->
						<u-radio-group
							v-if="item.type === typeKeys.radio"
							v-model="fmData[item.valueKey]"
						>
							<u-radio
								:customStyle="{
									marginBottom: '8px',
									marginTop: '8px',
									marginRight: '8px',
								}"
								v-for="(item, index) in item.variables"
								:key="index"
								:label="item.name"
								:name="item.name"
							>
							</u-radio>
						</u-radio-group>

						<!-- checkbox  -->
						<u-checkbox-group
							v-if="item.type === typeKeys.checkbox"
							v-model="fmData[item.valueKey]"
						>
							<u-checkbox
								:customStyle="{
									marginBottom: '8px',
									marginTop: '8px',
									marginRight: '8px',
								}"
								v-for="(item, index) in item.variables"
								:key="index"
								:label="item.name"
								:name="item.name"
							>
							</u-checkbox>
						</u-checkbox-group>

						<!-- upload  -->
						<view
							v-if="item.type === typeKeys.upload"
							class="align-right"
						>
							<c-upload
								:accept="item.accept"
								:maxCount="item.uploadNum"
								v-model="fmData[item.valueKey]"
							>
							</c-upload>
						</view>

						<!-- textarea  -->
						<u--textarea
							v-if="item.type === typeKeys.textarea"
							v-model="fmData[item.valueKey]"
							:placeholder="item.tips"
						></u--textarea>

						<!-- time  -->
						<view
							class="align-right"
							v-if="item.type === typeKeys.time"
						>
							<dateSelect
								mode="time"
								v-model="fmData[item.valueKey]"
								@change="dateChange($event, item)"
								:placeholder="item.tips || '请选择'"
							></dateSelect>
						</view>

						<!-- date  -->
						<view
							class="align-right"
							v-if="item.type === typeKeys.date"
						>
							<dateSelect
								mode="date"
								@change="dateChange($event, item)"
								v-model="fmData[item.valueKey]"
								:placeholder="item.tips || '请选择'"
							></dateSelect>
						</view>

						<!-- datetime  -->
						<view
							class="align-right"
							:class="{ 'place-color': !fmData[item.valueKey] }"
							v-if="item.type === typeKeys.datetime"
						>
							<uni-datetime-picker
								v-model="fmData[item.valueKey]"
								:border="false"
								type="datetime"
								@change="dateChange($event, item)"
							/>
						</view>

						<!-- datetimerange  -->
						<view
							class="align-right"
							:class="{ 'place-color': !fmData[item.valueKey] }"
							v-if="item.type === typeKeys.datetimerange"
						>
							<uni-datetime-picker
								v-model="fmData[item.valueKey]"
								:border="false"
								type="datetimerange"
								@change="dateChange($event, item)"
							/>
						</view>
					</u-form-item>
				</view>
				<!--可新增fmItem-->
				<view class="add-group" :key="i" v-for="(arr, i) in addList">
					<view class="add-item-header">
						<view class="hd-left-title">序列</view>
						<c-button @click="delArr(i)" type="text">删除</c-button>
					</view>

					<u-form-item
						:label="item.name"
						:prop="item.valueKey"
						:required="!!item.isRequire"
						:key="item.id"
						v-for="item in arr"
						borderBottom
					>
						<!-- text  -->
						<c-input
							v-if="item.type === typeKeys.text"
							:placeholder="item.tips"
							class="input-text"
							type="text"
							v-model="fmData[item.valueKey]"
							border="none"
						></c-input>

						<!-- number  -->
						<c-input
							v-if="item.type === typeKeys.number"
							class="input-text"
							type="number"
							v-model="fmData[item.valueKey]"
							border="none"
						></c-input>

						<!-- phoneNum  -->
						<c-input
							v-if="item.type === typeKeys.phoneNum"
							class="input-text"
							type="number"
							:placeholder="item.tips"
							maxlength="11"
							v-model="fmData[item.valueKey]"
							border="none"
						></c-input>

						<!-- select  -->
						<view
							class="align-right"
							v-if="item.type === typeKeys.select"
						>
							<pickerSelect
								v-model="fmData[item.valueKey]"
								:placeholder="item.tips || '请选择'"
								:columns="item.variables"
							></pickerSelect>
						</view>

						<!-- radio  -->
						<u-radio-group
							v-if="item.type === typeKeys.radio"
							v-model="fmData[item.valueKey]"
						>
							<u-radio
								:customStyle="{
									marginBottom: '8px',
									marginTop: '8px',
									marginRight: '8px',
								}"
								v-for="(item, index) in item.variables"
								:key="index"
								:label="item.name"
								:name="item.name"
							>
							</u-radio>
						</u-radio-group>

						<!-- checkbox  -->
						<u-checkbox-group
							v-if="item.type === typeKeys.checkbox"
							v-model="fmData[item.valueKey]"
						>
							<u-checkbox
								:customStyle="{
									marginBottom: '8px',
									marginTop: '8px',
									marginRight: '8px',
								}"
								v-for="(item, index) in item.variables"
								:key="index"
								:label="item.name"
								:name="item.name"
							>
							</u-checkbox>
						</u-checkbox-group>

						<!-- upload  -->
						<view
							v-if="item.type === typeKeys.upload"
							class="align-right"
						>
							<c-upload
								:accept="item.accept"
								:maxCount="item.uploadNum"
								v-model="fmData[item.valueKey]"
							>
							</c-upload>
						</view>

						<!-- textarea  -->
						<u--textarea
							v-if="item.type === typeKeys.textarea"
							v-model="fmData[item.valueKey]"
							:placeholder="item.tips"
						></u--textarea>

						<!-- time  -->
						<view
							class="align-right"
							v-if="item.type === typeKeys.time"
						>
							<dateSelect
								mode="time"
								v-model="fmData[item.valueKey]"
								@change="dateChange($event, item, arr)"
								:placeholder="item.tips || '请选择'"
							></dateSelect>
						</view>

						<!-- date  -->
						<view
							class="align-right"
							v-if="item.type === typeKeys.date"
						>
							<dateSelect
								mode="date"
								@change="dateChange($event, item, arr)"
								v-model="fmData[item.valueKey]"
								:placeholder="item.tips || '请选择'"
							></dateSelect>
						</view>

						<!-- datetime  -->
						<view
							class="align-right"
							:class="{
								'place-color': !fmData[item.valueKey],
							}"
							v-if="item.type === typeKeys.datetime"
						>
							<uni-datetime-picker
								v-model="fmData[item.valueKey]"
								:border="false"
								type="datetime"
								@change="dateChange($event, item, arr)"
							/>
						</view>

						<!-- datetimerange  -->
						<view
							class="align-right"
							:class="{
								'place-color': !fmData[item.valueKey],
							}"
							v-if="item.type === typeKeys.datetimerange"
						>
							<uni-datetime-picker
								v-model="fmData[item.valueKey]"
								:border="false"
								type="datetimerange"
								@change="dateChange($event, item, arr)"
							/>
						</view>
					</u-form-item>

					<view
						class="add-item-footer"
						v-if="i === addList.length - 1"
					>
						<c-button size="mini" type="primary" @click="handleAdd">
							<u-icon name="plus" color="#fff" size="12"></u-icon>
							<text style="margin-left: 4px">增加</text>
						</c-button>
					</view>
				</view>
			</u--form>

			<!--流程图-->
			<footer-process
				:condList="condList"
				:infoDto="infoDto"
			></footer-process>
		</view>

		<view class="footer">
			<c-button
				:disabled="disabled"
				@click="handleSubmit"
				type="primary"
			>
				提交
			</c-button>
		</view>
	</view>
</template>

<script>
import { typeKeys } from '@/pages/approval/types';
import pickerSelect from '@/pages/approval/com/pickerSelect.vue';
import dateSelect from '@/pages/approval/com/dateSelect.vue';
import { process, start, priview } from '@/api/approval/index.js';
import FooterProcess from '@/pages/approval/approvalApply/footerProcess.vue';

export default {
	name: 'cardReplacement',
	props: {
		processType: String, // 流程类型
	},
	components: {
		FooterProcess,
		pickerSelect,
		dateSelect,
	},
	data() {
		return {
			condList: [], // 作为条件的项
			orderId: '',
			detailInfo: {
				checkNoTime: [], // tips
				elementBos: [],
			},
			infoDto: [], // 流程图
			typeKeys,
			fmData: {},
			rules: {},
			defList: [], // 默认项(不可新增)
			addList: [], // 新增项 二维数组[[]]
		};
	},
	computed: {
		disabled() {
			return (
				this.detailInfo.checkNoTime.length === 0 &&
				this.processType === '0' // 0补卡审批
			);
		},
	},
	created() {
		this.getForms();
	},
	methods: {
		watchList() {
			// 监听作为条件的项
			const { condList } = this;
			if (condList.length === 0) {
				return;
			}
			// 筛选出所有必填的 作为条件项
			const reqList = condList.filter((item) => item.isRequire === 1);
			condList.forEach((item) => {
				const { valueKey } = item;
				let val = this.getDefaultVal(item); // 获取默认数据
				Object.defineProperty(this.fmData, valueKey, {
					get: () => {
						return val;
					},
					set: (newVal) => {
						if (val === newVal) return;
						val = newVal;
						const isErr = reqList.some((it) => {
							const k = it.valueKey;
							return !this.fmData[k] && this.fmData[k] !== 0;
						}); // false：已全部填写完整
						const { text, number } = typeKeys;
						if (![text, number].includes(item.type)) {
							this.$forceUpdate();
						}

						if (!isErr) {
							uni.$u.debounce(this.getFlowChart, 300); // 防抖
						}
					},
				});
			});
		},
		async getFlowChart() {
			const params = {};
			this.condList.forEach((item) => {
				const key = item.valueKey;
				params[key] = this.fmData[key];
			});
			const { data } = await priview(this.orderId, params);
			this.infoDto = data;
		},
		delArr(idx) {
			uni.showModal({
				content: '确认删除吗？',
				success: (e) => {
					if (e.confirm) {
						this.addList.splice(idx, 1);
					}
				},
			});
		},
		handleAdd() {
			const firstArr = this.addList[0];
			const rdm = Math.random().toString(36).slice(-6);
			const newArr = firstArr.map((item) => {
				const valueKey = `${item.name}${rdm}`;
				this.setFmRule(item, valueKey); // 设置fm某一项的校验规则
				return {
					...item,
					valueKey,
				};
			});
			this.addList.push(newArr);
		},
		getDefaultVal(item) {
			// 获取默认数据类型
			return item.type === typeKeys.checkbox ? [] : undefined;
		},
		setDefList(data) {
			// 不是新增项
			data.forEach((item) => {
				const valueKey = item.name;
				this.setFmRule(item, valueKey); // 设置fm某一项的校验规则
				this.$set(this.fmData, valueKey, this.getDefaultVal(item)); // 确保数据响应式
				const variables = item.variables
					? JSON.parse(item.variables)
					: []; // 处理variables为array

				this.defList.push({ ...item, variables, valueKey });
			});
		},
		setFmRule(item, valueKey) {
			// 设置fm某一项的校验规则
			if (item.isRequire !== 1) {
				// ====1必填
				return;
			}
			const { checkbox, upload, number } = this.typeKeys;
			const ruleType = {
				[checkbox]: 'array',
				[upload]: 'array',
				[number]: 'number',
			};
			const rule = [
				{
					type: ruleType[item.type] || 'string',
					required: true,
					message: '该项必填',
					trigger: ['change'],
				},
			];
			// 必填
			this.$set(this.rules, valueKey, rule);
		},
		setAddList(data) {
			if (!data || data.length === 0) {
				return;
			}
			// 可新增项
			const newData = data.map((item) => {
				const valueKey = `${item.name}0`;
				this.setFmRule(item, valueKey); // 设置fm某一项的校验规则
				this.$set(this.fmData, valueKey, this.getDefaultVal(item)); // 确保数据响应式

				const variables = item.variables
					? JSON.parse(item.variables)
					: []; // 处理variables为array
				return { ...item, variables, valueKey };
			});
			this.addList = [newData];
		},
		/**
		 * 日期时间范围选择 计算得到小时
		 */
		dateTimeRangeChange(dtKey, calcItem) {
			const [startDate, endDate] = this.fmData[dtKey];
			const sumMilli = +new Date(endDate) - +new Date(startDate);
			const h = sumMilli / 1000 / 60 / 60;
			this.setCount(h, calcItem.countkey); // 为计算结果赋值
		},
		getCalcItem(addRrr) {
			const list = addRrr || this.defList;
			const calcItem = {
				countkey: '', // 总和的key
				dtKey: '', // 日期时间范围选择器的key 是否计算
				computeType: [], // 减数/被减数的类型
				rduKey: '', // 1减数的key
				miuKey: '', // 0被减数的key
			};
			list.forEach((item) => {
				const { valueKey } = item;

				if (item.isCompute === 1) {
					// 1是 0否 int
					// 日期时间范围选择器 是否计算 1是 0否 int
					calcItem.dtKey = valueKey;
				}
				if (item.isCount === 1) {
					// 减数
					calcItem.rduKey = valueKey;
					calcItem.computeType.push(item.type);
				}
				if (item.isCount === 0) {
					// 0被减数的key
					calcItem.miuKey = valueKey;
					calcItem.computeType.push(item.type);
				}
				if (item.getCount === 1) {
					// 获取计算结果 1是 0否 int
					calcItem.countkey = valueKey;
				}
			});

			return calcItem;
		},
		dateChange(val, item, addArr) {
			const calcItem = this.getCalcItem(addArr);
			const { rduKey, miuKey, countkey, computeType, dtKey } =
				calcItem;
			const [rType, mType] = computeType || [];
			if (
				countkey &&
				dtKey &&
				item.type === this.typeKeys.datetimerange
			) {
				// (计算结果key、总和key)存在
				this.dateTimeRangeChange(dtKey, calcItem); // 单独处理日期时间范围选择器
				return;
			}
			if (
				rduKey && // 减数key存在
				miuKey && // 被减数key 存在
				countkey && // 计算结果key存在
				computeType.length === 2 && // 减数和被减数的类型都有
				rType === mType && // 减数和被减数的类型相同
				this.fmData[rduKey] && // 表单中数据选了减数
				this.fmData[miuKey] && //表单中数据选了被减数
				[rduKey, miuKey].includes(item.valueKey) // 是 减数或者被减数
			) {
				this.calcType(rType, calcItem);
			}
		},
		/**
		 * 根据类型进不同函数
		 * @param {type} 选择器的类型
		 */
		calcType(type, calcItem) {
			// 根据类型进不同函数
			const { time, date, datetime } = this.typeKeys;
			if (type === time) {
				// 类型为time 得到小时
				this.timeCalc(calcItem);
				return;
			}

			if (type === date) {
				// 类型为date  日期-计算得到天
				this.dateCalc(calcItem);
				return;
			}
			if (type === datetime) {
				// 类型为datetime  日期-计算得到小时
				this.dateTimeCalc(calcItem);
				return;
			}
		},
		dateTimeCalc(calcItem) {
			// dateTime计算
			const { rduKey, miuKey, countkey } = calcItem;
			const rduDateTime = this.fmData[rduKey]; //减数
			const miuDateTime = this.fmData[miuKey]; //被减数
			const sumMilli =
				+new Date(rduDateTime) - +new Date(miuDateTime);
			const h = sumMilli / 1000 / 60 / 60;
			this.setCount(h, countkey); // 为计算结果赋值
		},
		/**
		 * 日期yyyy-mm-dd 计算得到天
		 */
		dateCalc(calcItem) {
			// 日期yyyy-mm-dd 计算得到天
			// 相差: 天 参数--day
			const { rduKey, miuKey, countkey } = calcItem;
			const rduDate = this.fmData[rduKey]; //减数
			const miuDate = this.fmData[miuKey]; //被减数
			const sumMilli = +new Date(rduDate) - +new Date(miuDate);
			const day = sumMilli / 1000 / 60 / 60 / 24;
			this.setCount(day, countkey); // 为计算结果赋值
		},
		setCount(num, countkey) {
			const res = Number(num).toFixed(2) * 1;
			this.fmData[countkey] = res; // 计算结果赋值
			if (this.processType === '2') {
				// 类型是出差
				const dayKey = this.defList.find(
					(item) => item.name === '出差天数'
				)?.valueKey; // 出差天数 fmkey
				const cKeys = this.addList.map((arr) => {
					return arr.find((item) => item.getCount === 1)?.valueKey; // 总和
				}); // 每个行程的时长的key
				if (dayKey && cKeys?.length) {
					let totalDays = 0;
					cKeys.forEach((key) => {
						totalDays += this.fmData[key];
					});
					this.fmData[dayKey] = totalDays;
				}
			}
		},
		/**
		 * time计算
		 */
		timeCalc(calcItem) {
			const { rduKey, miuKey, countkey } = calcItem;
			// time计算
			const [rduH, rudM] = this.fmData[rduKey].split(':'); //减数
			const [miuH, miuM] = this.fmData[miuKey].split(':'); //被减数
			const rduTotal = rduH * 60 + Number(rudM); // 总分钟-减数
			const miuTotal = miuH * 60 + Number(miuM); // 总分钟-被减数
			const minuteSum = rduTotal - miuTotal; // 得到
			const num = minuteSum / 60;
			this.setCount(num, countkey); // 为计算结果赋值
		},
		async handleSubmit() {
			await this.$refs.uForm.validate();
			try {
				uni.$c.loading();
				const { orderId, resultId } = this.detailInfo || {};
				const { fmData, defList, addList } = this;
				const data = {
					orderId,
					resultId,
					variables: { fmData, defList, addList },
				};
				await start(data);
				uni.hideLoading();
				await uni.$c.toast({
					icon: 'success',
					title: '提交成功',
				});
				// uni.switchTab({ url: '/pages/home/index' }); // 去首页
				this.getForms(); // 刷新
			} catch (e) {
				uni.hideLoading();
				throw new Error(e);
			}
		},
		async getForms() {
			try {
				this.defList = []; // 默认项(不可新增)
				this.addList = []; // 新增项
				uni.$c.loading();
				const { data } = await process({ type: this.processType });
				uni.hideLoading();
				this.orderId = data.orderId;
				const newData = {
					...data,
					elementBos: data.elementBos || [], //表单
					checkNoTime: data.checkNoTime || [], // 缺卡arr
				};
				//新增项
				const addList = newData.elementBos.filter(
					(item) => item.isAdd === 1
				);
				this.setAddList(addList);

				// 不是新增项
				const defList = newData.elementBos.filter(
					(item) => item.isAdd !== 1
				);
				this.setDefList(defList);

				// todo 查询流程图业务暂不需要判断addList （新增项）
				const condList = this.defList.filter(
					(item) => item.isCondition === 1
				); // 作为条件的项--全部有值后查询流程图
				this.condList = condList || [];
				if (this.condList.length === 0) {
					this.getFlowChart(); // 如果没有作为条件项--查询流程图
				}
				this.watchList(); // 监听作为条件的项

				this.detailInfo = newData;
			} catch (e) {
				uni.hideLoading();
				throw e;
			}
		},
	},
};
</script>

<style scoped lang="scss">
.card-replacement {
	display: flex;
	flex-direction: column;
	padding: 30rpx;
	flex: 1;
	overflow: hidden;

	.main {
		flex: 1;
		overflow-y: auto;

		.header {
			font-size: 12px;
			color: #989ca5;
			margin-bottom: 20rpx;
		}

		.dynamic-form {
			.def-box {
				background-color: #fff;
				padding: 0 20rpx;
				border-radius: 6px;
			}

			.add-group {
				background-color: #fff;
				padding: 20rpx;
				border-radius: 6px;
				margin-top: 20rpx;

				.add-item-header {
					display: flex;
					justify-content: space-between;
					background: rgba(67, 111, 246, 0.12);
					line-height: 60rpx;
					border-radius: 4px;
					padding: 0 6px;
					.hd-left-title {
						font-size: 14px;
						color: $u-tips-color;
					}
				}
				.add-item-footer {
					margin-top: 20rpx;
					.c-button {
						width: 70px;
						border-radius: 13px;
					}
				}
			}

			.uni-date {
				width: initial;
				flex: inherit;
			}

			.place-color {
				/deep/.uni-date__x-input {
					color: #c0c4cc;
				}
			}

			.align-right {
				width: 100%;
				display: flex;
				justify-content: flex-end;
				flex-wrap: wrap;
			}
			.u-radio-group {
				flex-wrap: wrap;
				justify-content: flex-end;
				width: 100%;
			}
			.u-checkbox-group {
				flex-wrap: wrap;
				justify-content: flex-end;
				width: 100%;
			}

			.input-text {
				/deep/ .uni-input-input {
					text-align: right;
				}
				/deep/ .uni-input-placeholder {
					text-align: right;
				}
			}

			/deep/ .u-form-item__body {
				display: flex;
				justify-content: space-between;

				.u-form-item__body__right {
					margin-left: 20rpx;
				}
			}
		}
	}
	.footer {
		margin-top: 20rpx;
		margin-bottom: 20rpx;
	}
}
</style>
