UniappVue3/src/pages/WorkOrderEdit/compoents/BasicsInfo.vue

493 lines
17 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!-- 工单基础信息 -->
<template>
<view class="MainBox">
<view class="FormBox">
<view class="FormItem">
<view class="FormLableBox mustBox">项目名称</view>
<view class="FormValueBox">
<u-input v-model="formData.ProjectName" placeholder="请输入项目名称"></u-input>
</view>
</view>
<view class="FormItem">
<view class="FormLableBox mustBox">作业地点</view>
<view class="MapBox" id="tianditu-map"> </view>
<view class="FormValueBox">
<u-input v-model="formData.SpecificAddress" placeholder="请输入具体楼层或区域"></u-input>
</view>
</view>
<view class="FormItem">
<view class="FormLableBox mustBox">作业周期</view>
<view class="FormValueBox">
<view class="date-range-box">
<view class="date-item">
<u-input v-model="startDateText" placeholder="开始日期" readonly>
<template #suffix>
<u-button type="primary" size="small"
@click="showStartDatePicker = true">选择日期</u-button>
</template>
</u-input>
<up-datetime-picker :show="showStartDatePicker" v-model="startDate" mode="date"
:minDate="minTimestamp" @confirm="HandleStartDateConfirm"
@cancel="showStartDatePicker = false"></up-datetime-picker>
</view>
<view class="date-separator">至</view>
<view class="date-item">
<u-input v-model="endDateText" placeholder="结束日期" readonly>
<template #suffix>
<u-button type="primary" size="small"
@click="showEndDatePicker = true">选择日期</u-button>
</template>
</u-input>
<up-datetime-picker :show="showEndDatePicker" v-model="endDate" mode="date"
:minDate="minTimestamp" @confirm="HandleEndDateConfirm"
@cancel="showEndDatePicker = false"></up-datetime-picker>
</view>
</view>
</view>
</view>
<view class="FormItem">
<view class="FormLableBox FlexBox">
<view class="mustBox">作业负责人</view>
<view class="addBtn" @click="showMemberPickerA = true">添加</view>
</view>
<view class="FormValueBox">
<u-input v-model="formData.supervisorName" placeholder="请输入作业负责人" readonly></u-input>
</view>
<u-picker :show="showMemberPickerA" :columns="[MemberArr]" keyName="name" @confirm="HandleMemberConfirmA"
@cancel="showMemberPickerA = false"></u-picker>
</view>
<view class="FormItem">
<view class="FormLableBox FlexBox">
<view class="mustBox">作业班成员</view>
<view class="addBtn" @click="showMemberPicker = true">添加</view>
</view>
<view class="FormValueBox">
<view class="MemberBox">
<u-tag v-for="(member, index) in formData.MemberList" :key="member.id" closable shape="circle"
@close="RemoveMember(index)">
{{ member.name }}
</u-tag>
</view>
</view>
<u-picker :show="showMemberPicker" :columns="[MemberArr]" keyName="name" @confirm="HandleMemberConfirm"
@cancel="showMemberPicker = false"></u-picker>
</view>
</view>
</view>
</template>
<script setup>
import { ref, computed, onMounted, watch, defineExpose } from "vue";
import dayjs from 'dayjs';
import { getUserList } from '@/api';
const props = defineProps({
allData: {
type: Object,
default: () => ({})
}
})
// 地图实例
let mapEntity = null;
// 当前标记点
let currentMarker = null;
const showMemberPickerA = ref(false); // 是否显示成员选择器1
const showStartDatePicker = ref(false); // 是否显示开始日期选择器
const showEndDatePicker = ref(false); // 是否显示结束日期选择器
const startDate = ref(null); // 开始日期时间戳
const endDate = ref(null); // 结束日期时间戳
const startDateText = ref(''); // 开始日期显示文本
const endDateText = ref(''); // 结束日期显示文本
const minTimestamp = ref(dayjs('2020-01-01').valueOf()); // 最小可选日期时间戳
// 结束日期的最小时间戳(不能小于开始日期)
const endDateMinTimestamp = computed(() => {
if (startDate.value) {
return startDate.value;
}
return minTimestamp.value;
});
const showMemberPicker = ref(false); // 是否显示成员选择器
//成员列表信息
const MemberArr = ref([]); // 作业班成员列表
// 表单信息
const formData = ref({
ProjectName: "", // 项目名称
Location: "", // 作业地点(经纬度)
SpecificAddress: "", // 具体楼层或区域
period: [], // 作业周期 [开始日期, 结束日期]
supervisorName: "", // 作业负责人
supervisorId: "", // 作业负责人ID
MemberList: [], // 作业班成员列表
});
// 更新作业周期
const UpdatePeriod = () => {
if (startDateText.value && endDateText.value) {
formData.value.period = [startDateText.value, endDateText.value];
} else if (startDateText.value) {
formData.value.period = [startDateText.value, ''];
} else if (endDateText.value) {
formData.value.period = ['', endDateText.value];
} else {
formData.value.period = [];
}
console.log('作业周期:', formData.value.period);
};
// 暴露方法给父组件调用
defineExpose({
getFormData: () => formData.value,
});
// 从 allData 中恢复之前填写的数据
const restoreFormData = (data) => {
if (!data || Object.keys(data).length === 0) return;
if (data.ProjectName) formData.value.ProjectName = data.ProjectName;
if (data.Location) formData.value.Location = data.Location;
if (data.SpecificAddress) formData.value.SpecificAddress = data.SpecificAddress;
if (data.supervisorName) formData.value.supervisorName = data.supervisorName;
if (data.supervisorId) formData.value.supervisorId = data.supervisorId;
if (data.MemberList && Array.isArray(data.MemberList)) {
formData.value.MemberList = [...data.MemberList];
}
if (data.period && Array.isArray(data.period) && data.period.length >= 2) {
if (data.period[0]) {
// 处理日期字符串,提取日期部分(处理 "2020-01-01 00:00:00" 格式)
const startDateStr = String(data.period[0]).split(' ')[0];
startDateText.value = startDateStr;
startDate.value = dayjs(startDateStr).isValid() ? dayjs(startDateStr).valueOf() : null;
}
if (data.period[1]) {
// 处理日期字符串,提取日期部分(处理 "2020-01-01 00:00:00" 格式)
const endDateStr = String(data.period[1]).split(' ')[0];
endDateText.value = endDateStr;
endDate.value = dayjs(endDateStr).isValid() ? dayjs(endDateStr).valueOf() : null;
}
// 更新 formData.period确保数据同步
UpdatePeriod();
}
};
// 监听 allData.BasicsInfo 的变化,恢复表单数据
watch(() => props.allData?.BasicsInfo, (newData) => {
if (newData && Object.keys(newData).length > 0) {
restoreFormData(newData);
}
}, { immediate: true, deep: true });
// 获取作业班成员列表
const fetchUserList = async () => {
try {
const res = await getUserList();
console.log('获取用户列表成功:', res);
// 接口返回的数据结构为 { total: number, rows: [...], code: 200, msg: "查询成功" }
if (res && res.rows && Array.isArray(res.rows)) {
// 将用户数据转换为组件需要的格式 { id: userId, name: nickName || userName }
MemberArr.value = res.rows.map(user => ({
id: user.userId,
name: user.nickName || user.userName || ''
}));
console.log('转换后的成员列表:', MemberArr.value);
} else if (res && res.data && Array.isArray(res.data)) {
// 兼容其他可能的数据结构
MemberArr.value = res.data.map(user => ({
id: user.userId || user.id,
name: user.nickName || user.userName || user.name || ''
}));
} else if (Array.isArray(res)) {
// 兼容直接返回数组的情况
MemberArr.value = res.map(user => ({
id: user.userId || user.id,
name: user.nickName || user.userName || user.name || ''
}));
} else {
console.warn('用户列表数据格式不正确:', res);
uni.showToast({
title: '获取用户列表失败',
icon: 'none',
duration: 2000
});
}
} catch (error) {
console.error('获取用户列表失败:', error);
uni.showToast({
title: error.message || '获取用户列表失败',
icon: 'none',
duration: 2000
});
}
};
// 生命周期钩子函数
onMounted(() => {
initTiandituMap();
// 获取作业班成员列表
fetchUserList();
// 组件挂载后,从 allData 中恢复数据
if (props.allData?.BasicsInfo && Object.keys(props.allData.BasicsInfo).length > 0) {
restoreFormData(props.allData.BasicsInfo);
}
});
// 处理开始日期确认事件
const HandleStartDateConfirm = (e) => {
console.log('选中的开始日期:', e);
// 如果没有选择日期,使用默认值
const selectedDate = (e.value && dayjs(e.value).isValid()) ? e.value : minTimestamp.value;
startDateText.value = dayjs(selectedDate).format('YYYY-MM-DD');
startDate.value = selectedDate;
endDateText.value = '';
endDate.value = null;
showStartDatePicker.value = false;
UpdatePeriod();
};
// 处理结束日期确认事件
const HandleEndDateConfirm = (e) => {
console.log('选中的结束日期:', e);
// 如果没有选择日期,使用默认值
const selectedDate = (e.value && dayjs(e.value).isValid()) ? e.value : minTimestamp.value;
// 检查是否选择了开始日期
if (startDate.value && dayjs(selectedDate).isBefore(dayjs(startDate.value))) {
uni.showToast({
title: '结束日期不能小于开始日期',
icon: 'none',
duration: 2000
});
return;
}
endDateText.value = dayjs(selectedDate).format('YYYY-MM-DD');
endDate.value = selectedDate;
showEndDatePicker.value = false;
UpdatePeriod();
};
// 处理作业负责人选择确认事件
const HandleMemberConfirmA = (e) =>{
console.log('选中的作业负责人完整信息:', e.value);
if (e.value) {
formData.value.supervisorName = e.value[0].name;
formData.value.supervisorId = e.value[0].id;
showMemberPickerA.value = false;
}
}
// 处理作业组成员选择确认事件
const HandleMemberConfirm = (e) => {
console.log('选中的成员完整信息:', e);
console.log('e.value:', e.value);
console.log('e.value[0]:', e.value ? e.value[0] : 'undefined');
console.log('MemberArr:', MemberArr.value);
if (e.value && e.value.length > 0) {
const selectedMember = e.value[0];
console.log('选中的成员:', selectedMember);
console.log('selectedMember 的类型:', typeof selectedMember);
let memberInfo;
// 判断返回的是对象还是字符串
if (typeof selectedMember === 'object' && selectedMember !== null) {
// 如果是对象,直接使用
memberInfo = selectedMember;
console.log('返回的是对象,直接使用:', memberInfo);
} else {
// 如果是字符串,从 MemberArr 中根据id查找
memberInfo = MemberArr.value.find(item => item.id === selectedMember);
console.log('返回的是字符串,从 MemberArr 根据id查找', memberInfo);
}
if (memberInfo && memberInfo.id) {
// 根据id检查成员是否已存在
const isExist = formData.value.MemberList.some(item => item.id === memberInfo.id);
console.log('成员是否已存在:', isExist);
console.log('当前成员列表:', formData.value.MemberList);
if (!isExist) {
formData.value.MemberList.push({
id: memberInfo.id,
name: memberInfo.name
});
console.log('添加成员成功:', memberInfo);
console.log('添加后的成员列表:', formData.value.MemberList);
} else {
uni.showToast({
title: '该成员已存在',
icon: 'none',
duration: 2000
});
}
} else {
console.log('未找到成员信息或成员信息无效');
}
} else {
console.log('e.value 为空或长度为0');
}
showMemberPicker.value = false;
};
// 删除成员
const RemoveMember = (index) => {
formData.value.MemberList.splice(index, 1);
console.log('删除成员成功');
};
// 初始化天地图
const initTiandituMap = () => {
try {
// 1. 创建地图容器
const container = document.getElementById("tianditu-map");
if (!container) {
console.error("地图容器未找到");
return;
}
// 2. 初始化地图中心点设为北京缩放级别12
mapEntity = new T.Map("tianditu-map");
const centerPoint = new T.LngLat(116.403874, 39.914885);
mapEntity.centerAndZoom(centerPoint, 12);
// 3. 开启地图拖拽、缩放交互
mapEntity.enableDrag();
mapEntity.enableScrollWheelZoom();
// 4. 添加天地图图层(矢量图层 + 注记图层)
const vecLayer = new T.TileLayer("vec_w", { key: "你的天地图Key" });
const cvaLayer = new T.TileLayer("cva_w", { key: "你的天地图Key" });
const layerGroup = new T.LayerGroup([vecLayer, cvaLayer]);
mapEntity.addLayer(layerGroup);
// 5. 添加地图点击事件监听器
mapEntity.addEventListener("click", (e) => {
const lng = e.lnglat.getLng();
const lat = e.lnglat.getLat();
// 如果已存在标记点,先移除
if (currentMarker) {
mapEntity.removeOverLay(currentMarker);
}
// 创建新的标记点
const marker = new T.Marker(new T.LngLat(lng, lat));
mapEntity.addOverLay(marker);
currentMarker = marker;
// 将经纬度存储到Location字段
formData.value.Location = `${lng},${lat}`;
console.log("标记点位置:", lng, lat);
});
console.log("天地图初始化成功");
} catch (error) {
console.error("天地图初始化失败:", error);
}
};
</script>
<style lang="scss" scoped>
.FlexBox {
display: flex;
align-items: center;
justify-content: space-between;
gap: 20rpx;
}
.addBtn {
font-size: 30rpx;
color: #2979ff;
font-weight: bold;
}
.MainBox {
padding: 20rpx;
background-color: #fff;
height: 100%;
overflow: auto;
}
.mustBox::after {
content: "*";
color: red;
font-size: 30rpx;
margin-left: 10rpx;
}
.MapBox {
width: 100%;
height: 400rpx;
}
.MemberBox {
height: 100rpx;
display: flex;
align-items: center;
justify-content: flex-start;
gap: 20rpx;
flex-wrap: wrap;
border: 1rpx solid #e4e7ed;
padding: 20rpx;
border-radius: 10rpx;
}
.FormBox {
// background-color: #f5f5f5;
height: 100%;
.FormItem {
padding: 20rpx;
background-color: #fff;
.FormLableBox {
font-size: 30rpx;
font-weight: bold;
margin-bottom: 20rpx;
}
.FormValueBox {
font-size: 30rpx;
margin-top: 20rpx;
.date-range-box {
display: flex;
align-items: center;
gap: 20rpx;
flex: 1;
.date-item {
flex: 1;
}
.date-separator {
color: #999;
font-size: 28rpx;
}
}
}
}
}
</style>