839877316@qq.com 5 bulan lalu
induk
melakukan
89eecff388

+ 1 - 1
common/config.js

@@ -3,7 +3,7 @@
  */
 
 const config = {
-	DEVE_URL: "http://192.168.16.9:9002",
+	DEVE_URL: "https://zhijidaouniapp.dianjingkeji.net/prod-api",
 	// DEVE_URL: "https://api.ndtk.site/api",
 	// PRODUCT_URL: "http://localhost:8085",
 	PRODUCT_URL: "https://api.ndtk.site/api",

+ 3 - 2
config/api.js

@@ -38,8 +38,9 @@ export const delHistorySearch = () => http.post(prefix + '/blade-historySearch/r
  */
 export const feedbackList = (data) => http.get(prefix + '/blade-feedback/page?current=' + data.current +
 	'&size=' + data.size + '&type=' + data.type)
-export const getDept = () => http.get(prefix + '/system/dept/list')
-export const selectUser = (data) => http.get(prefix + '/system/info/selectUser')
+export const getDept = (data) => http.get(prefix + '/system/info/deptList?parentId=' + data.parentId)
+export const selectUser = (data) => http.get(prefix + '/system/info/selectUser?deptId=' + data.deptId)
+export const addVisit = (data) => http.post(prefix + '/system/info/addVisit', data) // 提交访客申请
 export const getFeedback = (data) => http.get(prefix + '/blade-feedback/getFeedback')
 export const feedbackSave = (params) => http.post(prefix + '//blade-feedback/save', params) // 意见反馈
 /**

+ 7 - 4
config/request/interceptors.js

@@ -132,7 +132,7 @@ const tryRefreshToken = async (config) => {
 			toast('请登录后操作')
 			// 添加跳转到登录页面的逻辑
 			uni.navigateTo({
-				url: '/packageUser/pages/login/index'
+				url: '/pagesA/public/login'
 			});
 			return Promise.reject(error)
 		} finally {
@@ -159,6 +159,11 @@ const responseInterceptors = (vm) => {
 			return data
 		}
 
+		// 如果响应中没有 code 字段,但 HTTP 状态码是 2xx,则认为请求成功
+		if (!data.code && response.statusCode >= 200 && response.statusCode < 300) {
+			return data
+		}
+
 		// 状态码处理
 		switch (data.code) {
 			case 200:
@@ -177,9 +182,7 @@ const responseInterceptors = (vm) => {
 				toast('服务器错误,请稍后重试')
 				return Promise.reject(data)
 			default:
-				// 错误提示
-				const errMsg = data?.msg || data?.error_description || CODE_MESSAGE[data.code] || '请求失败'
-				toast(errMsg)
+				console.log("121212")
 
 				return Promise.reject(data)
 		}

+ 7 - 7
pages.json

@@ -69,12 +69,12 @@
 						"navigationBarTitleText": "用户信息"
 					}
 				},
-				{
-					"path": "task/edit",
-					"style": {
-						"navigationBarTitleText": "申请访问"
-					}
-				},
+				// {
+				// 	"path": "task/edit",
+				// 	"style": {
+				// 		"navigationBarTitleText": "申请访问"
+				// 	}
+				// },
 				{
 					"path": "task/detail",
 					"style": {
@@ -100,7 +100,7 @@
 				"pagePath": "pages/index/index",
 				"iconPath": "/static/tabbar/task.png",
 				"selectedIconPath": "/static/tabbar/task-select.png",
-				"text": "我的任务"
+				"text": "提交申请"
 			},
 			{
 				"pagePath": "pages/tabbar/visitor",

+ 804 - 410
pages/index/index.vue

@@ -1,551 +1,945 @@
 <template>
-	
-	<!-- 我的任务 -->
+	<!-- 访客申请 -->
 	<view class="container">
-		<template v-if="!isLogin">
-			<!-- 未登录状态 -->
-			<view class="no-login">
-				<image src="/static/images/no-login.png" mode="aspectFit" class="no-login-image"></image>
-				<text class="no-login-text">登录后查看更多内容</text>
-				<button class="login-btn" @click="goToLogin">去登录</button>
+		<!-- 导航栏 -->
+		<custom-navbar title="访客申请" :showBack="true"></custom-navbar>
+
+		<!-- 表单内容 -->
+		<view class="form-container">
+			<!-- 第一块:对接人信息 -->
+			<view class="section">
+				<view class="section-title">
+					<image class="title-icon" src="/static/images/person.png" mode="aspectFit"></image>
+					对接人信息
+				</view>
+				<view class="mar-b-16">
+					<text class="label">所属部门</text>
+					<view class="select-wrapper">
+						<!-- 调试信息 -->
+						<uni-data-select v-model="formData.departmentId" :localdata="departmentOptions"
+							placeholder="请选择所属部门" @change="onDepartmentSelectChange" :clear="false">
+						</uni-data-select>
+					</view>
+				</view>
+
+				<view class="form-item1">
+					<text class="label">员工姓名</text>
+					<view class="select-wrapper">
+						<uni-data-select v-model="formData.employeeId" :localdata="employeeOptions" placeholder="请选择员工"
+							@change="onEmployeeSelectChange" :clear="false">
+						</uni-data-select>
+					</view>
+				</view>
 			</view>
-		</template>
-		<template v-else>
-			<!-- Visit list -->
-			<scroll-view scroll-y class="visit-list" @scrolltolower="onReachBottom">
-				<template v-if="taskList.length > 0">
-					<view class="visit-item" v-for="(item, index) in taskList" :key="index" @click="goToDetail(item)">
-						<view class="visit-date">
-							<text class="date-num">{{item.date}}</text>
-							<text class="date-month">{{item.year}}</text>
+
+			<!-- 第二块:访问信息 -->
+			<view class="section">
+				<view class="section-title">
+					<image class="title-icon" src="/static/images/calendar.png" mode="aspectFit"></image>
+					访问信息
+				</view>
+				<view class="form-item">
+					<text class="label">访问事由</text>
+					<input class="input" v-model="formData.visitReason" placeholder="请输入访问事由"
+						placeholder-style="color: #c0c4cc" />
+				</view>
+				<view class="form-item">
+					<text class="label">到访时间</text>
+					<uni-datetime-picker type="datetime" v-model="formData.visitTime" @change="onVisitTimeChange"
+						:clear-icon="false" placeholder="请选择到访时间" format="YYYY-MM-DD HH:mm" :hide-second="true">
+						<view class="input-wrapper">
+							<text class="placeholder" v-if="!formData.visitTime">请选择到访时间</text>
+							<text v-else>{{ formData.visitTime }}</text>
+							<uni-icons type="calendar" size="16" color="#c0c4cc"></uni-icons>
 						</view>
-						<view class="visit-content">
-							<view class="visit-header">
-								<view class="visitor-info">
-									<text class="visitor-label">对接人 </text>
-									<text class="visitor-name">{{item.employeeName}}</text>
-								</view>
-								<text class="visit-status" :class="getStatusClass(item.status)">{{item.status}}</text>
-							</view>
-							<view class="visit-desc">{{item.visitReason}}</view>
-							<view class="visit-time">
-								<u-icon name="clock" size="12" color="#999"></u-icon>
-								<text>{{item.time}}</text>
-							</view>
+					</uni-datetime-picker>
+				</view>
+				<view class="form-item">
+					<text class="label">访客姓名</text>
+					<input class="input" v-model="formData.visitorName" placeholder="请输入访客姓名"
+						placeholder-style="color: #c0c4cc" />
+				</view>
+				<view class="form-item">
+					<text class="label">访客单位</text>
+					<input class="input" v-model="formData.visitorCompany" placeholder="请输入访客单位"
+						placeholder-style="color: #c0c4cc" />
+				</view>
+				<view class="form-item">
+					<text class="label">手机号</text>
+					<input class="input" v-model="formData.visitorPhone" placeholder="请输入手机号"
+						placeholder-style="color: #c0c4cc" type="number" />
+				</view>
+			</view>
+
+			<!-- 第三块:随行人员 -->
+			<view class="section">
+				<view class="section-title">随行人员</view>
+				<view class="accompany-list">
+					<view class="accompany-item" v-for="(item, index) in formData.accompanyPersons" :key="index">
+						<view class="form-item">
+							<text class="label">随行人员</text>
+							<input class="input" v-model="item.name" placeholder="请输入随行人员姓名"
+								placeholder-style="color: #c0c4cc" />
+						</view>
+						<view class="form-item">
+							<text class="label">手机号</text>
+							<input class="input" v-model="item.phone" placeholder="请输入手机号"
+								placeholder-style="color: #c0c4cc" type="number" />
+						</view>
+						<view class="delete-btn" v-if="formData.accompanyPersons.length > 1"
+							@click="removeAccompany(index)">
+							<uni-icons type="trash" size="18" color="#ff4757"></uni-icons>
 						</view>
 					</view>
-					<!-- Loading more -->
-					<u-loadmore :status="loadMoreStatus" />
-				</template>
-				<template v-else>
-					<!-- 暂无数据 -->
-					<view class="flex-items-plus">
-						<image src="../../static/images/empty.png" class="empty "></image>
-					</view>
-					<view class="font28 font-gray flex-items-plus">
-						数据为空
+				</view>
+				<view class="add-accompany-btn" @click="addAccompany">
+					<uni-icons type="plus" size="16" color="#007aff"></uni-icons>
+					<text>添加随行人员</text>
+				</view>
+			</view>
+
+			<!-- 第四块:使用车辆 -->
+			<view class="section">
+				<view class="vehicle-header">
+					<view class="section-title">
+						<image class="title-icon" src="/static/images/cart.png" mode="aspectFit"></image>
+						使用车辆
 					</view>
-				</template>
-			</scroll-view>
+					<switch :checked="formData.useVehicle" @change="onVehicleChange" color="#007aff" />
+				</view>
 
-			<!-- Floating button -->
-			<view class="floating-button" @click="showApplyPopup">
-				<text class="floating-text">申请<br>访问</text>
-			</view>
-		</template>
-
-		<!-- Application method popup -->
-		<uni-popup ref="popup" type="center" border-radius="16rpx">
-			<view class="popup-content">
-				<view class="popup-title">
-					选择申请方式
-					<text class="close-icon" @click="closePopup">×</text>
+				<view v-if="formData.useVehicle" class="vehicle-content">
+					<view class="form-item">
+						<text class="label">接客时间</text>
+						<uni-datetime-picker type="datetime" v-model="formData.pickupTime" @change="onPickupTimeChange"
+							:clear-icon="false" placeholder="请选择接客时间" format="YYYY-MM-DD HH:mm" :hide-second="true">
+							<view class="input-wrapper">
+								<text class="placeholder" v-if="!formData.pickupTime">请选择接客时间</text>
+								<text v-else>{{ formData.pickupTime }}</text>
+								<uni-icons type="calendar" size="16" color="#c0c4cc"></uni-icons>
+							</view>
+						</uni-datetime-picker>
+					</view>
+					<view class="form-item">
+						<text class="label">接客地点</text>
+						<input class="input" v-model="formData.pickupLocation" placeholder="请输入接客地点"
+							placeholder-style="color: #c0c4cc" />
+					</view>
 				</view>
-				<view class="apply-methods">
-					<view class="method-item" @click="handleApply('self')">
-						<view class="method-icon green-bg">
-							<image src="/static/images/apply.png" mode="aspectFit"></image>
-						</view>
-						<text class="font-bold">发起申请</text>
+			</view>
+		</view>
+
+		<!-- 提交按钮 -->
+		<view class="submit-container">
+			<button class="submit-btn" @click="submitForm">提交</button>
+		</view>
+
+		<!-- 提交成功弹框 -->
+		<uni-popup ref="successPopup" type="center" :mask-click="false">
+			<view class="success-popup">
+				<view class="popup-content">
+					<view class="success-icon">
+						<uni-icons type="checkmarkempty" size="60" color="#52c41a"></uni-icons>
 					</view>
-					<view class="method-item" @click="handleApply('proxy')">
-						<view class="method-icon orange-bg">
-							<image src="/static/images/behalf.png" mode="aspectFit"></image>
+					<view class="popup-title">申请提交成功</view>
+					<view class="popup-message">您的申请已成功提交,请关注公众号即时查询审核结果</view>
+					<view class="popup-buttons">
+						<button class="cancel-btn" @click="closeSuccessPopup">取消</button>
+						<button class="follow-btn" @click="showQRCode">关注</button>
+					</view>
+				</view>
+			</view>
+		</uni-popup>
+
+		<!-- 二维码弹框 -->
+		<uni-popup ref="qrcodePopup" type="center" :mask-click="false">
+			<view class="qrcode-popup">
+				<view class="qrcode-content">
+					<view class="qrcode-title">扫描二维码关注公众号</view>
+					<view class="qrcode-image" @click="previewQRCode">
+						<image src="/static/images/qrcode.png" mode="aspectFit"></image>
+						<view class="preview-tip">
+							<uni-icons type="search" size="16" color="#fff"></uni-icons>
+							<text>点击查看大图</text>
 						</view>
-						<text class="font-bold">代客申请</text>
 					</view>
+					<view class="qrcode-tip">扫描上方二维码,关注公众号获取审核结果</view>
+					<button class="qrcode-close-btn" @click="closeQRCode">我知道了</button>
 				</view>
 			</view>
 		</uni-popup>
+
 	</view>
 </template>
 
 <script>
+	import user from '../../store/modules/user';
 	import {
-		orderList,
-		userLogin
+
+		getDept,
+		selectUser,
+		addVisit
 	} from '@/config/api.js';
-	import {
-		mapGetters
-	} from 'vuex';
-	import {
-		shareImg
-	} from '@/common/config.js'
 	export default {
 		data() {
 			return {
-				taskList: [],
-				loadMoreStatus: 'loadmore', // loadmore, loading, nomore
-				params: {
-					current: 1,
-					size: 10,
+				type: '', // 从上一页传递过来的参数
+				tabbarHeight: 50, // tabbar高度,默认50px
+				user: null, // 用户信息
+				formData: {
+					departmentId: '',
+					department: '',
+					employeeId: '',
+					employeeName: '',
+					visitReason: '',
+					visitTime: '',
+					visitorName: '',
+					visitorCompany: '',
+					visitorPhone: '',
+					accompanyPersons: [{
+						name: '',
+						phone: ''
+					}],
+					useVehicle: false,
+					pickupTime: '',
+					pickupLocation: ''
 				},
-				hasMore: true
+				// 部门数据
+				departments: [],
+				// 部门选项(格式化为uni-data-select所需格式)
+				departmentOptions: [],
+				// 员工选项
+				employeeOptions: [],
 			}
 		},
-		computed: {
-			...mapGetters(['isLogin'])
-		},
 		onLoad(options) {
-			this.getList();
-		},
-		// 微信小程序分享配置
-		onShareAppMessage() {
-			return {
-				title: `邀请您加入知己访客`,
-				path: `/pages/index/index`,
-				imageUrl: shareImg // 分享图片,需要添加
+			console.log(uni.getStorageSync("user"), "usususuus")
+			// 获取传递过来的参数
+			if (options.type) {
+				this.type = options.type;
 			}
+			// 获取用户信息
+			this.user = uni.getStorageSync("user")
+			this.getTabbarHeight()
+			this.getDeptList()
 		},
-		onShareTimeline(res) {
-			let that = this;
-			let shareInfo = store.state.vuex_shareInfo;
-			let query = shareInfo.query;
-			//携带当前页面资源ID参数
-			let currentPage = getCurrentPages()[getCurrentPages().length - 1];
-			let options = currentPage.options;
-			if (JSON.stringify(options) != '{}' && options.id) {
-				query += `&id=${options.id}`;
-			}
+		onReady() {
+			// 页面渲染完成后再次获取,确保准确
+			this.getTabbarHeight()
+		},
+		methods: {
+			// 获取tabbar高度
+			getTabbarHeight() {
+				// 获取菜单按钮信息,用于计算真实的可用高度
+				const systemInfo = uni.getSystemInfoSync()
+
+				// 在微信小程序中,使用 windowHeight 和 screenHeight 的差值
+				// windowHeight 是不包含 tabbar 的可用高度
+				const windowHeight = systemInfo.windowHeight
+				const screenHeight = systemInfo.screenHeight
+
+				// 微信小程序 tabbar 高度通常是 50px,但在不同设备可能不同
+				// 直接使用差值
+				let tabbarHeight = screenHeight - windowHeight
+
+				console.log('系统信息:', {
+					screenHeight,
+					windowHeight,
+					计算的tabbar高度: tabbarHeight,
+					safeAreaBottom: systemInfo.safeAreaInsets?.bottom || systemInfo.safeArea?.bottom || 0
+				})
 
-			return {
-				title: shareInfo.title,
-				query: query,
-				imageUrl: shareImg,
-				success(res) {
-					uni.showToast({
-						title: '分享成功'
+				// 在小程序中通常是 50-80 之间
+				// 如果是 H5,差值会包含地址栏等,会更大
+				// #ifdef MP-WEIXIN
+				if (tabbarHeight < 30 || tabbarHeight > 100) {
+					tabbarHeight = 50 // 微信小程序默认 50px
+				}
+				// #endif
+
+				// #ifdef H5
+				tabbarHeight = 50 // H5 固定使用 50px
+				// #endif
+
+				this.tabbarHeight = tabbarHeight
+			},
+
+			async getDeptList() {
+				console.log("获取DEPT")
+				try {
+					const res = await getDept({
+						parentId: 100
 					})
-				},
-				fail(res) {
+					console.log("部门API返回数据:", res)
+					this.departments = res.data
+					// 格式化部门数据为uni-data-select所需格式
+					this.departmentOptions = res.data.map(item => ({
+						value: item.dept_id,
+						text: item.dept_name
+					}))
+					console.log("格式化后的部门选项:", this.departmentOptions)
+
+					// 添加延时确保数据已经设置
+					this.$nextTick(() => {
+						console.log("nextTick后的部门选项:", this.departmentOptions)
+					})
+				} catch (error) {
+					console.error("获取部门列表失败:", error)
 					uni.showToast({
-						title: '分享失败',
+						title: '获取部门列表失败',
 						icon: 'none'
 					})
-				},
-			}
-		},
-		onShow() {
-			// #ifdef H5
-			this.login()
-			// #endif
+				}
+			},
 
-		},
 
 
-		onPullDownRefresh() {
-			this.refresh()
-			uni.stopPullDownRefresh();
-		},
+			// 部门选择改变
+			async onDepartmentSelectChange(value) {
+				console.log("选择的部门ID:", value)
+				this.formData.departmentId = value
+				// 找到选中的部门信息
+				const selectedDept = this.departments.find(dept => dept.dept_id === value)
+				if (selectedDept) {
+					this.formData.department = selectedDept.dept_name
+					// 根据部门ID获取员工列表
+					try {
+						const userRes = await selectUser({
+							deptId: value
+						})
+						console.log("员工列表:", userRes)
+						// 格式化员工数据为uni-data-select所需格式
+						if (userRes && userRes.rows) {
+							this.employeeOptions = userRes.rows.map(item => ({
+								value: item.user_id,
+								text: item.nick_name
+							}))
+							console.log("格式化后的员工选项:", this.employeeOptions)
+						} else if (userRes && userRes.data && userRes.data.rows) {
+							// 备用路径,以防数据结构不同
+							this.employeeOptions = userRes.data.rows.map(item => ({
+								value: item.user_id,
+								text: item.nick_name
+							}))
+							console.log("格式化后的员工选项(备用路径):", this.employeeOptions)
+						}
+						// 清空之前选择的员工
+						this.formData.employeeId = ''
+						this.formData.employeeName = ''
+					} catch (error) {
+						console.error("获取员工列表失败:", error)
+						uni.showToast({
+							title: '获取员工列表失败',
+							icon: 'none'
+						})
+					}
+				}
+			},
 
+			// 员工选择改变
+			onEmployeeSelectChange(value) {
+				console.log("选择的员工ID:", value)
+				this.formData.employeeId = value
+				// 根据employeeOptions找到对应的员工名称
+				const selectedEmployee = this.employeeOptions.find(emp => emp.value === value)
+				if (selectedEmployee) {
+					this.formData.employeeName = selectedEmployee.text
+					console.log("选择的员工名称:", selectedEmployee.text)
+				}
+			},
 
-		methods: {
 
-			// Refresh list
-			refresh() {
-				this.taskList = []
-				this.params.current = 1
-				this.hasMore = true
-				this.loadMoreStatus = 'loadmore'
-				this.getList()
-			},
 
-			// Handle reaching bottom of scroll
-			onReachBottom() {
-				if (!this.hasMore || this.loadMoreStatus === 'loading') return
+			// 到访时间改变
+			onVisitTimeChange(e) {
+				this.formData.visitTime = e;
+			},
 
-				this.params.current++
-				this.getList(true)
+			// 接客时间改变
+			onPickupTimeChange(e) {
+				this.formData.pickupTime = e;
 			},
 
-			// Show apply popup
-			showApplyPopup() {
-				console.log('显示申请弹窗');
-				this.$refs.popup.open()
+			// 获取当前日期时间
+			getCurrentDatetime() {
+				const now = new Date();
+				const year = now.getFullYear();
+				const month = String(now.getMonth() + 1).padStart(2, '0');
+				const day = String(now.getDate()).padStart(2, '0');
+				const hour = String(now.getHours()).padStart(2, '0');
+				const minute = String(now.getMinutes()).padStart(2, '0');
+				return `${year}-${month}-${day} ${hour}:${minute}`;
 			},
 
-			// Close popup
-			closePopup() {
-				this.$refs.popup.close()
+			// 添加随行人员
+			addAccompany() {
+				this.formData.accompanyPersons.push({
+					name: '',
+					phone: ''
+				});
 			},
 
-			// Handle apply method selection
-			handleApply(type) {
-				if (!this.isLogin) {
-					uni.navigateTo({
-						url: '/pagesA/public/login'
-					});
-					return
-				}
-				console.log('选择申请方式:', type);
-				this.$refs.popup.close()
-				if (type === 'self') {
-					uni.navigateTo({
-						url: '/pagesA/task/edit?type=1'
-					})
-				} else {
-					uni.navigateTo({
-						url: '/pagesA/task/edit?type=2'
-					})
+			// 删除随行人员
+			removeAccompany(index) {
+				if (this.formData.accompanyPersons.length > 1) {
+					this.formData.accompanyPersons.splice(index, 1);
 				}
 			},
 
-			// Login method
-			login() {
-				let params = {
-					username: "USER082927",
-					grant_type: "web",
-					memberId: "1957060037088083973"
+			// 车辆开关改变
+			onVehicleChange(e) {
+				this.formData.useVehicle = e.detail.value;
+				if (!this.formData.useVehicle) {
+					// 关闭车辆使用时清空相关信息
+					this.formData.pickupTime = '';
+					this.formData.pickupLocation = '';
 				}
-				userLogin(params).then((loginData) => {
-					uni.setStorageSync('access_token', loginData.access_token);
-					uni.setStorageSync('refresh_token', loginData.refresh_token);
-					uni.setStorageSync('user', loginData);
+			},
 
-					this.$store.commit('isLogin', true);
-					this.$store.commit('refresh_token', loginData.refresh_token);
-				})
+
+			// 手机号格式校验
+			validatePhone(phone) {
+				const phoneRegex = /^1[3-9]\d{9}$/;
+				return phoneRegex.test(phone);
 			},
 
-			// Get visit list with mock data
-			getList(loadMore = false) {
-				if (!loadMore) {
-					uni.showLoading({
-						title: '加载中...'
+			// 表单验证
+			validateForm() {
+				if (!this.formData.department) {
+					uni.showToast({
+						title: '请选择所属部门',
+						icon: 'none'
+					});
+					return false;
+				}
+				if (!this.formData.employeeName) {
+					uni.showToast({
+						title: '请输入员工姓名',
+						icon: 'none'
+					});
+					return false;
+				}
+				if (!this.formData.visitReason) {
+					uni.showToast({
+						title: '请输入访问事由',
+						icon: 'none'
+					});
+					return false;
+				}
+				if (!this.formData.visitTime) {
+					uni.showToast({
+						title: '请选择到访时间',
+						icon: 'none'
+					});
+					return false;
+				}
+				if (!this.formData.visitorName) {
+					uni.showToast({
+						title: '请输入访客姓名',
+						icon: 'none'
+					});
+					return false;
+				}
+				if (!this.formData.visitorCompany) {
+					uni.showToast({
+						title: '请输入访客单位',
+						icon: 'none'
+					});
+					return false;
+				}
+				if (!this.formData.visitorPhone) {
+					uni.showToast({
+						title: '请输入手机号',
+						icon: 'none'
 					});
+					return false;
 				}
 
-				this.loadMoreStatus = 'loading'
-
-				// 模拟接口延迟
-				setTimeout(() => {
-					// 模拟数据
-					const mockData = Array(10).fill(0).map((_, index) => {
-						const currentIndex = (this.params.current - 1) * 10 + index;
-						const date = new Date();
-						date.setDate(date.getDate() - currentIndex); // 每条数据日期递减
-
-						const statusList = ['待访问', '待审核', '已拒绝'];
-						const descList = [
-							'我是访问事由我是访问事由我是访问事由...',
-							'需要进行业务对接商谈...',
-							'产品展示与技术交流...',
-							'项目合作洽谈...'
-						];
-
-						return {
-							id: currentIndex,
-							employeeName: `范海洋${currentIndex + 1}`,
-							createTime: date,
-							status: statusList[Math.floor(Math.random() * statusList.length)],
-							visitReason: descList[Math.floor(Math.random() * descList.length)]
-						};
+				// 校验访客手机号格式
+				if (!this.validatePhone(this.formData.visitorPhone)) {
+					uni.showToast({
+						title: '请输入正确的手机号格式',
+						icon: 'none'
 					});
+					return false;
+				}
 
-					const list = mockData.map(item => ({
-						...item,
-						date: this.$u.timeFormat(item.createTime, 'DD'),
-						year: this.$u.timeFormat(item.createTime, 'YYYY/MM'),
-						time: this.$u.timeFormat(item.createTime, 'hh:mm')
-					}));
-
-					if (loadMore) {
-						this.taskList = [...this.taskList, ...list];
-					} else {
-						this.taskList = list;
+				// 验证随行人员信息
+				for (let i = 0; i < this.formData.accompanyPersons.length; i++) {
+					const person = this.formData.accompanyPersons[i];
+					if (person.name && !person.phone) {
+						uni.showToast({
+							title: `请输入第${i + 1}个随行人员的手机号`,
+							icon: 'none'
+						});
+						return false;
 					}
+					if (!person.name && person.phone) {
+						uni.showToast({
+							title: `请输入第${i + 1}个随行人员的姓名`,
+							icon: 'none'
+						});
+						return false;
+					}
+					// 校验随行人员手机号格式
+					if (person.phone && !this.validatePhone(person.phone)) {
+						uni.showToast({
+							title: `第${i + 1}个随行人员手机号格式不正确`,
+							icon: 'none'
+						});
+						return false;
+					}
+				}
 
-					// 模拟总共有5页数据
-					this.hasMore = this.params.current < 5;
-					this.loadMoreStatus = this.hasMore ? 'loadmore' : 'nomore';
-
-					if (!loadMore) {
-						uni.hideLoading();
+				// 验证车辆使用信息
+				if (this.formData.useVehicle) {
+					if (!this.formData.pickupTime) {
+						uni.showToast({
+							title: '请选择接客时间',
+							icon: 'none'
+						});
+						return false;
 					}
-				}, 500); // 增加500ms延迟模拟网络请求
+					if (!this.formData.pickupLocation) {
+						uni.showToast({
+							title: '请选择接客地点',
+							icon: 'none'
+						});
+						return false;
+					}
+				}
+
+				return true;
 			},
 
-			// Get status class for styling
-			getStatusClass(status) {
-				const statusMap = {
-					'待访问': 'status-pending-visit',
-					'待审核': 'status-pending-review',
-					'已拒绝': 'status-rejected'
+			// 提交表单
+			async submitForm() {
+				if (!this.validateForm()) {
+					return;
+				}
+
+				// 过滤空的随行人员
+				const validAccompanyPersons = this.formData.accompanyPersons.filter(person =>
+					person.name && person.phone
+				);
+
+				// 构建提交数据
+				const submitData = {
+					visitDate: this.formData.visitTime, // 访问时间
+					// userId: this.user?.id || '', // 员工id
+					empName: this.formData.employeeName, // 访问部门人(员工姓名)
+					visDept: this.formData.visitorCompany, // 访客单位
+					visitPerson: this.formData.visitorName, // 访客姓名
+					visitorTel: this.formData.visitorPhone, // 访客手机
+					visitorNum: (validAccompanyPersons.length + 1).toString(), // 访问人数(访客+随行人员)
+					visitReson: this.formData.visitReason, // 访问事由
+					accPerson: JSON.stringify(validAccompanyPersons) // 随行人员转为JSON字符串
+				};
+
+				console.log('提交数据:', submitData);
+
+				try {
+					// 调用后端接口提交数据
+					const response = await addVisit(submitData);
+					console.log('提交成功:', response);
+
+					// 显示提交成功弹框
+					this.$refs.successPopup.open();
+				} catch (error) {
+					console.error('提交失败:', error);
+					uni.showToast({
+						title: '提交失败,请重试',
+						icon: 'none'
+					});
 				}
-				return statusMap[status] || 'status-default'
 			},
 
-			// 跳转到详情页面
-			goToDetail(item) {
-				uni.navigateTo({
-					url: `/pagesA/task/detail?id=${item.id}&status=${item.status}`
-				});
+			// 关闭成功弹框
+			closeSuccessPopup() {
+				this.$refs.successPopup.close();
+				// 返回上一页
+				uni.navigateBack();
+			},
+
+			// 显示二维码
+			showQRCode() {
+				this.$refs.successPopup.close();
+				this.$refs.qrcodePopup.open();
 			},
 
-			// 跳转到登录页面
-			goToLogin() {
-				uni.navigateTo({
-					url: '/pagesA/public/login'
+			// 关闭二维码弹框
+			closeQRCode() {
+				this.$refs.qrcodePopup.close();
+				// 返回上一页
+				uni.navigateBack();
+			},
+
+			// 预览二维码
+			previewQRCode() {
+				uni.previewImage({
+					urls: ['/static/images/qrcode.png'],
+					current: 0
 				});
 			},
 
-		},
+		}
 	}
 </script>
 
 <style lang="scss" scoped>
 	.container {
-		min-height: 100vh;
 		background-color: #f5f5f5;
-
-		.no-login {
-			display: flex;
-			flex-direction: column;
-			align-items: center;
-			justify-content: center;
-			padding-top: 30vh;
-
-			.no-login-image {
-				width: 240rpx;
-				height: 240rpx;
-				margin-bottom: 40rpx;
-			}
-
-			.no-login-text {
-				font-size: 32rpx;
-				color: #999;
-				margin-bottom: 60rpx;
-			}
-
-			.login-btn {
-				width: 320rpx;
-				height: 88rpx;
-				background: #FF6B00;
-				border-radius: 44rpx;
-				color: #fff;
-				font-size: 32rpx;
-				font-weight: 500;
-				display: flex;
-				align-items: center;
-				justify-content: center;
-			}
-		}
+		min-height: 100vh;
 	}
 
-	.visit-list {
-		height: 100vh;
+	.form-container {
+		padding: 20rpx;
 	}
 
-	.visit-item {
+	.section {
 		background-color: #fff;
-		margin: 16rpx 20rpx;
-		border-radius: 16rpx;
-		padding: 24rpx;
+		border-radius: 12rpx;
+		margin-bottom: 20rpx;
+		padding: 30rpx;
+	}
+
+	.section-title {
+		font-size: 32rpx;
+		font-weight: 600;
+		color: #333;
+		margin-bottom: 30rpx;
 		display: flex;
-		align-items: flex-start;
-		box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.05);
+		align-items: center;
 	}
 
-	.visit-date {
+	.title-icon {
+		width: 40rpx;
+		height: 40rpx;
+		margin-right: 15rpx;
+	}
+
+	.form-item {
 		display: flex;
-		flex-direction: column;
 		align-items: center;
-		margin-right: 24rpx;
-		min-width: 80rpx;
+		margin-bottom: 30rpx;
+		position: relative;
 
-		.date-num {
-			font-size: 48rpx;
-			font-weight: bold;
-			color: #333;
-			line-height: 1;
+		&:last-child {
+			margin-bottom: 0;
 		}
+	}
 
-		.date-month {
-			font-size: 24rpx;
-			color: #999;
-			margin-top: 4rpx;
-		}
+
+
+	.label {
+		width: 160rpx;
+		font-size: 28rpx;
+		color: #666;
+		flex-shrink: 0;
 	}
 
-	.visit-content {
+	.input {
 		flex: 1;
+		height: 70rpx;
+		padding: 0 20rpx;
+		background-color: #f8f8f8;
+		border-radius: 8rpx;
+		font-size: 28rpx;
+		color: #333;
+	}
 
-		.visit-header {
-			display: flex;
-			justify-content: space-between;
-			align-items: center;
-			margin-bottom: 12rpx;
-
-			.visitor-info {
-				display: flex;
-				align-items: center;
+	.input-wrapper {
+		flex: 1;
+		height: 70rpx;
+		padding: 0 20rpx;
+		background-color: #f8f8f8;
+		border-radius: 8rpx;
+		display: flex;
+		align-items: center;
+		justify-content: space-between;
+	}
 
-				.visitor-label {
-					margin-right: 10rpx;
-					font-size: 32rpx;
-					color: #333;
-					font-weight: normal;
-				}
+	.placeholder {
+		color: #c0c4cc;
+		font-size: 28rpx;
+	}
 
-				.visitor-name {
-					font-size: 36rpx;
-					color: #333;
-					font-weight: bold;
-				}
-			}
+	.select-wrapper {
+		flex: 1;
 
-			.visit-status {
-				font-size: 28rpx;
-				padding: 4rpx 12rpx;
-				border-radius: 12rpx;
+		::v-deep .uni-stat__select {
+			width: 100%;
+		}
 
-				&.status-pending-visit {
-					color: #4CAF50;
-					background-color: rgba(76, 175, 80, 0.1);
-				}
+		::v-deep .uni-stat-box {
+			width: 100%;
+		}
 
-				&.status-pending-review {
-					color: #2196F3;
-					background-color: rgba(33, 150, 243, 0.1);
-				}
+		::v-deep .uni-select {
+			width: 100%;
+			border: none;
+		}
 
-				&.status-rejected {
-					color: #F44336;
-					background-color: rgba(244, 67, 54, 0.1);
-				}
-			}
+		::v-deep .uni-select__input-box {
+			height: 70rpx;
+			padding: 0 20rpx;
+			background-color: #f8f8f8;
+			border-radius: 8rpx;
+			border: none;
 		}
 
-		.visit-desc {
-			color: #666;
+		::v-deep .uni-select__input-text {
 			font-size: 28rpx;
-			line-height: 1.4;
-			margin-bottom: 12rpx;
+			color: #333;
 		}
 
-		.visit-time {
-			display: flex;
-			align-items: center;
-			gap: 8rpx;
+		::v-deep .uni-select__input-placeholder {
+			color: #c0c4cc;
+		}
 
-			text {
-				color: #999;
-				font-size: 24rpx;
+		::v-deep .uni-select__selector {
+			max-height: 400rpx;
+		}
+	}
+
+	.accompany-list {
+		.accompany-item {
+			position: relative;
+			padding: 20rpx;
+			background-color: #f8f8f8;
+			border-radius: 8rpx;
+			margin-bottom: 20rpx;
+
+			&:last-child {
+				margin-bottom: 0;
 			}
+
+
 		}
 	}
 
-	.floating-button {
-		position: fixed;
-		bottom: 120rpx;
-		right: 40rpx;
-		width: 120rpx;
-		height: 120rpx;
-		background-color: #FF6B00;
-		border-radius: 16rpx;
+	.delete-btn {
+		position: absolute;
+		top: 10rpx;
+		right: 10rpx;
+		width: 60rpx;
+		height: 60rpx;
 		display: flex;
 		align-items: center;
 		justify-content: center;
-		box-shadow: 0 8rpx 20rpx rgba(255, 107, 0, 0.3);
-		z-index: 999;
+		background-color: #fff;
+		border-radius: 50%;
+		box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
+	}
 
-		.floating-text {
-			color: #fff;
-			font-size: 28rpx;
-			text-align: center;
-			line-height: 1.2;
+	.add-accompany-btn {
+		display: flex;
+		align-items: center;
+		justify-content: center;
+		height: 80rpx;
+		background-color: #f8f9fa;
+		border: 2rpx dashed #c0c4cc;
+		border-radius: 8rpx;
+		color: #909399;
+		font-size: 28rpx;
+
+		text {
+			margin-left: 10rpx;
 		}
 	}
 
-	.popup-content {
-		width: 600rpx;
-		padding: 70rpx 40rpx;
+	.vehicle-header {
+		display: flex;
+		align-items: center;
+		margin-bottom: 30rpx;
+
+		.section-title {
+			flex: 1;
+			margin-bottom: 0;
+			margin-left: 15rpx;
+		}
+	}
+
+	.vehicle-content {
+		padding-top: 20rpx;
+		border-top: 1rpx solid #eee;
+	}
+
+	.submit-container {
+		padding: 20rpx;
+		background-color: #fff;
+		margin-top: 20rpx;
+	}
+
+	.submit-btn {
+		width: 100%;
+		height: 88rpx;
+		background: linear-gradient(135deg, #ff6b35 0%, #ff9500 100%);
+		border-radius: 44rpx;
+		border: none;
+		color: #fff;
+		font-size: 32rpx;
+		font-weight: 600;
+	}
+
+	.picker-container {
 		background-color: #fff;
-		border-radius: 16rpx;
+		border-radius: 20rpx 20rpx 0 0;
+	}
+
+	.picker-header {
+		display: flex;
+		align-items: center;
+		justify-content: space-between;
+		padding: 30rpx;
+		border-bottom: 1rpx solid #eee;
+
+		text {
+			color: #007aff;
+			font-size: 28rpx;
+		}
+	}
+
+	.picker-title {
+		font-size: 32rpx;
+		font-weight: 600;
+		color: #333 !important;
+	}
+
+	.picker-view {
+		height: 400rpx;
+	}
+
+	.picker-item {
+		display: flex;
+		align-items: center;
+		justify-content: center;
+		height: 80rpx;
+		font-size: 28rpx;
+		color: #333;
+	}
+
+	// 提交成功弹框样式
+	.success-popup {
+		.popup-content {
+			background-color: #fff;
+			border-radius: 20rpx;
+			padding: 60rpx 40rpx 40rpx;
+			width: 560rpx;
+			text-align: center;
+		}
+
+		.success-icon {
+			margin-bottom: 30rpx;
+		}
 
 		.popup-title {
 			font-size: 36rpx;
+			font-weight: 600;
 			color: #333;
+			margin-bottom: 20rpx;
+		}
+
+		.popup-message {
+			font-size: 28rpx;
+			color: #666;
+			line-height: 1.6;
+			margin-bottom: 50rpx;
+		}
+
+		.popup-buttons {
+			display: flex;
+			gap: 20rpx;
+
+			button {
+				flex: 1;
+				height: 80rpx;
+				border-radius: 40rpx;
+				font-size: 28rpx;
+				border: none;
+			}
+
+			.cancel-btn {
+				background-color: #f5f5f5;
+				color: #666;
+			}
+
+			.follow-btn {
+				background: linear-gradient(135deg, #ff6b35 0%, #ff9500 100%);
+				color: #fff;
+			}
+		}
+	}
+
+	// 二维码弹框样式
+	.qrcode-popup {
+		.qrcode-content {
+			background-color: #fff;
+			border-radius: 20rpx;
+			padding: 50rpx 40rpx;
+			width: 560rpx;
 			text-align: center;
+		}
+
+		.qrcode-title {
+			font-size: 32rpx;
+			font-weight: 600;
+			color: #333;
+			margin-bottom: 40rpx;
+		}
+
+		.qrcode-image {
+			width: 400rpx;
+			height: 400rpx;
+			margin: 0 auto 30rpx;
+			border: 1rpx solid #eee;
+			border-radius: 12rpx;
+			overflow: hidden;
 			position: relative;
-			margin-bottom: 60rpx;
-			font-weight: 500;
 
-			.close-icon {
+			image {
+				width: 100%;
+				height: 100%;
+			}
+
+			.preview-tip {
 				position: absolute;
+				left: 0;
 				right: 0;
-				top: 50%;
-				transform: translateY(-50%);
-				font-size: 50rpx;
-				color: #999;
-				width: 60rpx;
+				bottom: 0;
 				height: 60rpx;
+				background: rgba(0, 0, 0, 0.5);
 				display: flex;
 				align-items: center;
 				justify-content: center;
-			}
-		}
-
-		.apply-methods {
-			display: flex;
-			justify-content: space-around;
-			padding: 0 20rpx;
-
-			.method-item {
-				display: flex;
-				flex-direction: column;
-				align-items: center;
-				gap: 30rpx;
-				cursor: pointer;
-
-				.method-icon {
-					width: 120rpx;
-					height: 120rpx;
-					border-radius: 20rpx;
-					display: flex;
-					align-items: center;
-					justify-content: center;
-
-					image {
-						width: 80rpx;
-						height: 80rpx;
-					}
-
-					&.green-bg {
-						background-color: #39833b;
-					}
-
-					&.orange-bg {
-						background-color: #FF6B00;
-					}
-				}
+				color: #fff;
+				font-size: 24rpx;
 
 				text {
-					font-size: 32rpx;
-					color: #333;
-					font-weight: 500;
+					margin-left: 10rpx;
 				}
 			}
+
+			&:active {
+				opacity: 0.8;
+			}
+		}
+
+		.qrcode-tip {
+			font-size: 26rpx;
+			color: #999;
+			margin-bottom: 40rpx;
+			line-height: 1.5;
+		}
+
+		.qrcode-close-btn {
+			width: 100%;
+			height: 80rpx;
+			background: linear-gradient(135deg, #ff6b35 0%, #ff9500 100%);
+			border-radius: 40rpx;
+			color: #fff;
+			font-size: 28rpx;
+			border: none;
 		}
 	}
 </style>

+ 551 - 0
pages/index/index.vue.备份

@@ -0,0 +1,551 @@
+<template>
+	
+	<!-- 我的任务 -->
+	<view class="container">
+		<template v-if="!isLogin">
+			<!-- 未登录状态 -->
+			<view class="no-login">
+				<image src="/static/images/no-login.png" mode="aspectFit" class="no-login-image"></image>
+				<text class="no-login-text">登录后查看更多内容</text>
+				<button class="login-btn" @click="goToLogin">去登录</button>
+			</view>
+		</template>
+		<template v-else>
+			<!-- Visit list -->
+			<scroll-view scroll-y class="visit-list" @scrolltolower="onReachBottom">
+				<template v-if="taskList.length > 0">
+					<view class="visit-item" v-for="(item, index) in taskList" :key="index" @click="goToDetail(item)">
+						<view class="visit-date">
+							<text class="date-num">{{item.date}}</text>
+							<text class="date-month">{{item.year}}</text>
+						</view>
+						<view class="visit-content">
+							<view class="visit-header">
+								<view class="visitor-info">
+									<text class="visitor-label">对接人 </text>
+									<text class="visitor-name">{{item.employeeName}}</text>
+								</view>
+								<text class="visit-status" :class="getStatusClass(item.status)">{{item.status}}</text>
+							</view>
+							<view class="visit-desc">{{item.visitReason}}</view>
+							<view class="visit-time">
+								<u-icon name="clock" size="12" color="#999"></u-icon>
+								<text>{{item.time}}</text>
+							</view>
+						</view>
+					</view>
+					<!-- Loading more -->
+					<u-loadmore :status="loadMoreStatus" />
+				</template>
+				<template v-else>
+					<!-- 暂无数据 -->
+					<view class="flex-items-plus">
+						<image src="../../static/images/empty.png" class="empty "></image>
+					</view>
+					<view class="font28 font-gray flex-items-plus">
+						数据为空
+					</view>
+				</template>
+			</scroll-view>
+
+			<!-- Floating button -->
+			<view class="floating-button" @click="showApplyPopup">
+				<text class="floating-text">申请<br>访问</text>
+			</view>
+		</template>
+
+		<!-- Application method popup -->
+		<uni-popup ref="popup" type="center" border-radius="16rpx">
+			<view class="popup-content">
+				<view class="popup-title">
+					选择申请方式
+					<text class="close-icon" @click="closePopup">×</text>
+				</view>
+				<view class="apply-methods">
+					<view class="method-item" @click="handleApply('self')">
+						<view class="method-icon green-bg">
+							<image src="/static/images/apply.png" mode="aspectFit"></image>
+						</view>
+						<text class="font-bold">发起申请</text>
+					</view>
+					<view class="method-item" @click="handleApply('proxy')">
+						<view class="method-icon orange-bg">
+							<image src="/static/images/behalf.png" mode="aspectFit"></image>
+						</view>
+						<text class="font-bold">代客申请</text>
+					</view>
+				</view>
+			</view>
+		</uni-popup>
+	</view>
+</template>
+
+<script>
+	import {
+		orderList,
+		userLogin
+	} from '@/config/api.js';
+	import {
+		mapGetters
+	} from 'vuex';
+	import {
+		shareImg
+	} from '@/common/config.js'
+	export default {
+		data() {
+			return {
+				taskList: [],
+				loadMoreStatus: 'loadmore', // loadmore, loading, nomore
+				params: {
+					current: 1,
+					size: 10,
+				},
+				hasMore: true
+			}
+		},
+		computed: {
+			...mapGetters(['isLogin'])
+		},
+		onLoad(options) {
+			this.getList();
+		},
+		// 微信小程序分享配置
+		onShareAppMessage() {
+			return {
+				title: `邀请您加入知己访客`,
+				path: `/pages/index/index`,
+				imageUrl: shareImg // 分享图片,需要添加
+			}
+		},
+		onShareTimeline(res) {
+			let that = this;
+			let shareInfo = store.state.vuex_shareInfo;
+			let query = shareInfo.query;
+			//携带当前页面资源ID参数
+			let currentPage = getCurrentPages()[getCurrentPages().length - 1];
+			let options = currentPage.options;
+			if (JSON.stringify(options) != '{}' && options.id) {
+				query += `&id=${options.id}`;
+			}
+
+			return {
+				title: shareInfo.title,
+				query: query,
+				imageUrl: shareImg,
+				success(res) {
+					uni.showToast({
+						title: '分享成功'
+					})
+				},
+				fail(res) {
+					uni.showToast({
+						title: '分享失败',
+						icon: 'none'
+					})
+				},
+			}
+		},
+		onShow() {
+			// #ifdef H5
+			this.login()
+			// #endif
+
+		},
+
+
+		onPullDownRefresh() {
+			this.refresh()
+			uni.stopPullDownRefresh();
+		},
+
+
+		methods: {
+
+			// Refresh list
+			refresh() {
+				this.taskList = []
+				this.params.current = 1
+				this.hasMore = true
+				this.loadMoreStatus = 'loadmore'
+				this.getList()
+			},
+
+			// Handle reaching bottom of scroll
+			onReachBottom() {
+				if (!this.hasMore || this.loadMoreStatus === 'loading') return
+
+				this.params.current++
+				this.getList(true)
+			},
+
+			// Show apply popup
+			showApplyPopup() {
+				console.log('显示申请弹窗');
+				this.$refs.popup.open()
+			},
+
+			// Close popup
+			closePopup() {
+				this.$refs.popup.close()
+			},
+
+			// Handle apply method selection
+			handleApply(type) {
+				if (!this.isLogin) {
+					uni.navigateTo({
+						url: '/pagesA/public/login'
+					});
+					return
+				}
+				console.log('选择申请方式:', type);
+				this.$refs.popup.close()
+				if (type === 'self') {
+					uni.navigateTo({
+						url: '/pagesA/task/edit?type=1'
+					})
+				} else {
+					uni.navigateTo({
+						url: '/pagesA/task/edit?type=2'
+					})
+				}
+			},
+
+			// Login method
+			login() {
+				let params = {
+					username: "USER082927",
+					grant_type: "web",
+					memberId: "1957060037088083973"
+				}
+				userLogin(params).then((loginData) => {
+					uni.setStorageSync('access_token', loginData.access_token);
+					uni.setStorageSync('refresh_token', loginData.refresh_token);
+					uni.setStorageSync('user', loginData);
+
+					this.$store.commit('isLogin', true);
+					this.$store.commit('refresh_token', loginData.refresh_token);
+				})
+			},
+
+			// Get visit list with mock data
+			getList(loadMore = false) {
+				if (!loadMore) {
+					uni.showLoading({
+						title: '加载中...'
+					});
+				}
+
+				this.loadMoreStatus = 'loading'
+
+				// 模拟接口延迟
+				setTimeout(() => {
+					// 模拟数据
+					const mockData = Array(10).fill(0).map((_, index) => {
+						const currentIndex = (this.params.current - 1) * 10 + index;
+						const date = new Date();
+						date.setDate(date.getDate() - currentIndex); // 每条数据日期递减
+
+						const statusList = ['待访问', '待审核', '已拒绝'];
+						const descList = [
+							'我是访问事由我是访问事由我是访问事由...',
+							'需要进行业务对接商谈...',
+							'产品展示与技术交流...',
+							'项目合作洽谈...'
+						];
+
+						return {
+							id: currentIndex,
+							employeeName: `范海洋${currentIndex + 1}`,
+							createTime: date,
+							status: statusList[Math.floor(Math.random() * statusList.length)],
+							visitReason: descList[Math.floor(Math.random() * descList.length)]
+						};
+					});
+
+					const list = mockData.map(item => ({
+						...item,
+						date: this.$u.timeFormat(item.createTime, 'DD'),
+						year: this.$u.timeFormat(item.createTime, 'YYYY/MM'),
+						time: this.$u.timeFormat(item.createTime, 'hh:mm')
+					}));
+
+					if (loadMore) {
+						this.taskList = [...this.taskList, ...list];
+					} else {
+						this.taskList = list;
+					}
+
+					// 模拟总共有5页数据
+					this.hasMore = this.params.current < 5;
+					this.loadMoreStatus = this.hasMore ? 'loadmore' : 'nomore';
+
+					if (!loadMore) {
+						uni.hideLoading();
+					}
+				}, 500); // 增加500ms延迟模拟网络请求
+			},
+
+			// Get status class for styling
+			getStatusClass(status) {
+				const statusMap = {
+					'待访问': 'status-pending-visit',
+					'待审核': 'status-pending-review',
+					'已拒绝': 'status-rejected'
+				}
+				return statusMap[status] || 'status-default'
+			},
+
+			// 跳转到详情页面
+			goToDetail(item) {
+				uni.navigateTo({
+					url: `/pagesA/task/detail?id=${item.id}&status=${item.status}`
+				});
+			},
+
+			// 跳转到登录页面
+			goToLogin() {
+				uni.navigateTo({
+					url: '/pagesA/public/login'
+				});
+			},
+
+		},
+	}
+</script>
+
+<style lang="scss" scoped>
+	.container {
+		min-height: 100vh;
+		background-color: #f5f5f5;
+
+		.no-login {
+			display: flex;
+			flex-direction: column;
+			align-items: center;
+			justify-content: center;
+			padding-top: 30vh;
+
+			.no-login-image {
+				width: 240rpx;
+				height: 240rpx;
+				margin-bottom: 40rpx;
+			}
+
+			.no-login-text {
+				font-size: 32rpx;
+				color: #999;
+				margin-bottom: 60rpx;
+			}
+
+			.login-btn {
+				width: 320rpx;
+				height: 88rpx;
+				background: #FF6B00;
+				border-radius: 44rpx;
+				color: #fff;
+				font-size: 32rpx;
+				font-weight: 500;
+				display: flex;
+				align-items: center;
+				justify-content: center;
+			}
+		}
+	}
+
+	.visit-list {
+		height: 100vh;
+	}
+
+	.visit-item {
+		background-color: #fff;
+		margin: 16rpx 20rpx;
+		border-radius: 16rpx;
+		padding: 24rpx;
+		display: flex;
+		align-items: flex-start;
+		box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.05);
+	}
+
+	.visit-date {
+		display: flex;
+		flex-direction: column;
+		align-items: center;
+		margin-right: 24rpx;
+		min-width: 80rpx;
+
+		.date-num {
+			font-size: 48rpx;
+			font-weight: bold;
+			color: #333;
+			line-height: 1;
+		}
+
+		.date-month {
+			font-size: 24rpx;
+			color: #999;
+			margin-top: 4rpx;
+		}
+	}
+
+	.visit-content {
+		flex: 1;
+
+		.visit-header {
+			display: flex;
+			justify-content: space-between;
+			align-items: center;
+			margin-bottom: 12rpx;
+
+			.visitor-info {
+				display: flex;
+				align-items: center;
+
+				.visitor-label {
+					margin-right: 10rpx;
+					font-size: 32rpx;
+					color: #333;
+					font-weight: normal;
+				}
+
+				.visitor-name {
+					font-size: 36rpx;
+					color: #333;
+					font-weight: bold;
+				}
+			}
+
+			.visit-status {
+				font-size: 28rpx;
+				padding: 4rpx 12rpx;
+				border-radius: 12rpx;
+
+				&.status-pending-visit {
+					color: #4CAF50;
+					background-color: rgba(76, 175, 80, 0.1);
+				}
+
+				&.status-pending-review {
+					color: #2196F3;
+					background-color: rgba(33, 150, 243, 0.1);
+				}
+
+				&.status-rejected {
+					color: #F44336;
+					background-color: rgba(244, 67, 54, 0.1);
+				}
+			}
+		}
+
+		.visit-desc {
+			color: #666;
+			font-size: 28rpx;
+			line-height: 1.4;
+			margin-bottom: 12rpx;
+		}
+
+		.visit-time {
+			display: flex;
+			align-items: center;
+			gap: 8rpx;
+
+			text {
+				color: #999;
+				font-size: 24rpx;
+			}
+		}
+	}
+
+	.floating-button {
+		position: fixed;
+		bottom: 120rpx;
+		right: 40rpx;
+		width: 120rpx;
+		height: 120rpx;
+		background-color: #FF6B00;
+		border-radius: 16rpx;
+		display: flex;
+		align-items: center;
+		justify-content: center;
+		box-shadow: 0 8rpx 20rpx rgba(255, 107, 0, 0.3);
+		z-index: 999;
+
+		.floating-text {
+			color: #fff;
+			font-size: 28rpx;
+			text-align: center;
+			line-height: 1.2;
+		}
+	}
+
+	.popup-content {
+		width: 600rpx;
+		padding: 70rpx 40rpx;
+		background-color: #fff;
+		border-radius: 16rpx;
+
+		.popup-title {
+			font-size: 36rpx;
+			color: #333;
+			text-align: center;
+			position: relative;
+			margin-bottom: 60rpx;
+			font-weight: 500;
+
+			.close-icon {
+				position: absolute;
+				right: 0;
+				top: 50%;
+				transform: translateY(-50%);
+				font-size: 50rpx;
+				color: #999;
+				width: 60rpx;
+				height: 60rpx;
+				display: flex;
+				align-items: center;
+				justify-content: center;
+			}
+		}
+
+		.apply-methods {
+			display: flex;
+			justify-content: space-around;
+			padding: 0 20rpx;
+
+			.method-item {
+				display: flex;
+				flex-direction: column;
+				align-items: center;
+				gap: 30rpx;
+				cursor: pointer;
+
+				.method-icon {
+					width: 120rpx;
+					height: 120rpx;
+					border-radius: 20rpx;
+					display: flex;
+					align-items: center;
+					justify-content: center;
+
+					image {
+						width: 80rpx;
+						height: 80rpx;
+					}
+
+					&.green-bg {
+						background-color: #39833b;
+					}
+
+					&.orange-bg {
+						background-color: #FF6B00;
+					}
+				}
+
+				text {
+					font-size: 32rpx;
+					color: #333;
+					font-weight: 500;
+				}
+			}
+		}
+	}
+</style>

+ 2 - 2
pages/tabbar/my.vue

@@ -1,5 +1,5 @@
 <template>
-	
+
 	<!-- 个人信息 -->
 	<view class="page-container">
 		<!-- 背景图片 -->
@@ -141,7 +141,7 @@
 						url: '/pagesA/public/login'
 					});
 				} else {
-					this.$route('/packageUser/pages/user-info/index');
+					this.$route('/pagesA/public/login');
 				}
 			},
 			// 跳转用户信息

+ 135 - 47
pagesA/public/login.vue

@@ -148,7 +148,55 @@
 				tempAccount: '', // 临时账号
 				tempAvatar: '', // 临时头像
 				loginData: null, // 临时保存登录数据
-				isUploadingAvatar: false // 头像上传状态
+				isUploadingAvatar: false, // 头像上传状态
+				// 默认用户信息
+				defaultUser: {
+					createBy: "admin",
+					createTime: "2025-06-04 16:48:04",
+					updateBy: null,
+					updateTime: null,
+					remark: "管理员",
+					params: {
+						"@type": "java.util.HashMap"
+					},
+					userId: 1,
+					deptId: 100,
+					userName: "admin",
+					nickName: "知己集团",
+					email: "ry@163.com",
+					phonenumber: "15888888888",
+					sex: "1",
+					avatar: "/profile/avatar/2025/06/16/微信图片_202506101640343_20250616153504A012.jpg",
+					password: "$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2",
+					status: "0",
+					delFlag: "0",
+					loginIp: "107.182.190.58",
+					loginDate: "2025-10-27T19:46:44.000+08:00",
+					pwdUpdateDate: "2025-06-04T16:48:04.000+08:00",
+					wxid: null,
+					dept: {
+						createBy: null,
+						createTime: null,
+						updateBy: null,
+						updateTime: null,
+						remark: null,
+						params: {
+							"@type": "java.util.HashMap"
+						},
+						deptId: 100,
+						parentId: 0,
+						ancestors: "0",
+						deptName: "知己集团",
+						orderNum: 0,
+						leader: "贲智群",
+						phone: null,
+						email: null,
+						status: "0",
+						delFlag: null,
+						parentName: null,
+						children: []
+					}
+				}
 			}
 		},
 		onLoad(options) {
@@ -193,56 +241,96 @@
 				uni.getUserProfile({
 					desc: '用于完善会员资料',
 					success: (profileRes) => {
-						uni.login({
-							provider: 'weixin',
-							success: async (loginRes) => {
-								console.log(loginRes.code, "code")
-								try {
-									const loginData = await wxLogin({
-										code: loginRes.code,
-										account: profileRes.userInfo.nickName,
-										avatarUrl: profileRes.userInfo.avatarUrl,
-										grant_type: 'wechat'
-									});
+					uni.login({
+						provider: 'weixin',
+						success: async (loginRes) => {
+							console.log(loginRes.code, "code")
+						try {
+							const loginData = await wxLogin({
+								code: loginRes.code
+							});
+							
+							console.log('登录响应:', loginData);
+
+							// 检查登录是否成功:有 openid 或者 code === 200 都认为成功
+							if (loginData.openid || loginData.code === 200 || loginData.message === "登录成功") {
+								this.isLoading = false;
+								
+								// 如果 user 为 null,使用默认用户信息
+								if (!loginData.user || loginData.user === null) {
+									console.log('用户信息为空,使用默认用户信息');
+									loginData.user = this.defaultUser;
+								}
+								
+								// 保存 token(支持 token 和 access_token 两种字段)
+								const token = loginData.token || loginData.access_token;
+								if (token) {
+									uni.setStorageSync('access_token', token);
+									uni.setStorageSync('token', token);
+								}
+								
+								// 保存 refresh_token
+								if (loginData.refresh_token) {
+									uni.setStorageSync('refresh_token', loginData.refresh_token);
+								}
+								
+								// 保存完整的登录数据
+								uni.setStorageSync('loginData', loginData);
+								
+								// 保存用户信息
+								uni.setStorageSync('user', loginData.user);
+								
+								// 保存 openid
+								if (loginData.openid) {
+									uni.setStorageSync('openid', loginData.openid);
+								}
 
-									if (loginData.code === 200) {
-										this.loginData = loginData;
-										this.tempAccount = loginData.account || '';
-										this.tempAvatar = loginData.avatar || '';
-										this.showProfileModal = true;
-										this.isLoading = false;
-										uni.setStorageSync('access_token', loginData
-											.access_token);
-										uni.setStorageSync('refresh_token', loginData
-											.refresh_token);
-										uni.setStorageSync('user', loginData);
-
-										this.$store.commit('isLogin', true);
-										this.$store.commit('refresh_token', loginData
-											.refresh_token);
-										uni.hideLoading();
-										this.saveLoginDataAndRedirect(loginData);
-
-									} else {
-										uni.showToast({
-											title: loginData.msg || '登录失败',
-											icon: 'none'
-										});
-									}
-								} catch (e) {
-									console.error('登录错误:', e);
-									uni.showToast({
-										title: '登录失败,请重试',
-										icon: 'none'
-									});
-								} finally {
-									this.isLoading = false;
+								// 更新 store 状态
+								this.$store.commit('isLogin', true);
+								if (loginData.refresh_token) {
+									this.$store.commit('refresh_token', loginData.refresh_token);
 								}
-							},
-							fail: () => {
+								
+								uni.hideLoading();
+								
+								// 显示登录成功提示
+								uni.showToast({
+									title: loginData.message || '登录成功',
+									icon: 'success',
+									duration: 1500
+								});
+								
+								// 延迟跳转,让用户看到成功提示
+								setTimeout(() => {
+									uni.switchTab({
+										url: '/pages/index/index'
+									});
+								}, 1500);
+
+							} else {
+								uni.showToast({
+									title: loginData.msg || loginData.message || '登录失败',
+									icon: 'none'
+								});
 								this.isLoading = false;
+								uni.hideLoading();
 							}
-						});
+						} catch (error) {
+							console.error('登录错误:', error);
+							uni.showToast({
+								title: error.message || '登录失败,请重试',
+								icon: 'none'
+							});
+							this.isLoading = false;
+							uni.hideLoading();
+						}
+
+						},
+						fail: () => {
+							this.isLoading = false;
+							uni.hideLoading();
+						}
+					});
 					},
 					fail: (err) => {
 						this.isLoading = false;

+ 0 - 856
pagesA/task/edit.vue

@@ -1,856 +0,0 @@
-<template>
-	<!-- 访客申请 -->
-	<view class="container">
-		<!-- 导航栏 -->
-		<custom-navbar title="访客申请" :showBack="true"></custom-navbar>
-
-		<!-- 表单内容 -->
-		<view class="form-container">
-			<!-- 第一块:对接人信息 -->
-			<view class="section">
-				<view class="section-title">
-					<image class="title-icon" src="/static/images/person.png" mode="aspectFit"></image>
-					对接人信息
-				</view>
-				<view class="form-item" @tap="showDepartmentPicker" style="z-index: 999;">
-					<text class="label">所属部门</text>
-					<view class="input-wrapper" @tap="showDepartmentPicker">
-						<text class="placeholder" v-if="!formData.department">请选择所属部门</text>
-						<text v-else>{{ formData.department }}</text>
-						<uni-icons type="right" size="16" color="#c0c4cc"></uni-icons>
-					</view>
-				</view>
-
-				<view class="form-item"  @tap="showEmployeeName">
-					<text class="label">员工姓名</text>
-					<view class="input-wrapper" @tap="showEmployeeName">
-						<text class="placeholder" v-if="!formData.employeeName">请选择员工</text>
-						<text v-else>{{ formData.employeeName }}</text>
-						<uni-icons type="right" size="16" color="#c0c4cc"></uni-icons>
-					</view>
-<!--					<input class="input" v-model="formData.employeeName" placeholder="请输入员工姓名"-->
-<!--						placeholder-style="color: #c0c4cc" />-->
-				</view>
-			</view>
-
-			<!-- 第二块:访问信息 -->
-			<view class="section">
-				<view class="section-title">
-					<image class="title-icon" src="/static/images/calendar.png" mode="aspectFit"></image>
-					访问信息
-				</view>
-				<view class="form-item">
-					<text class="label">访问事由</text>
-					<input class="input" v-model="formData.visitReason" placeholder="请输入访问事由"
-						placeholder-style="color: #c0c4cc" />
-				</view>
-				<view class="form-item">
-					<text class="label">到访时间</text>
-					<uni-datetime-picker type="datetime" v-model="formData.visitTime" @change="onVisitTimeChange"
-						:clear-icon="false" placeholder="请选择到访时间" format="YYYY-MM-DD HH:mm" :hide-second="true">
-						<view class="input-wrapper">
-							<text class="placeholder" v-if="!formData.visitTime">请选择到访时间</text>
-							<text v-else>{{ formData.visitTime }}</text>
-							<uni-icons type="calendar" size="16" color="#c0c4cc"></uni-icons>
-						</view>
-					</uni-datetime-picker>
-				</view>
-				<view class="form-item">
-					<text class="label">访客姓名</text>
-					<input class="input" v-model="formData.visitorName" placeholder="请输入访客姓名"
-						placeholder-style="color: #c0c4cc" />
-				</view>
-				<view class="form-item">
-					<text class="label">访客单位</text>
-					<input class="input" v-model="formData.visitorCompany" placeholder="请输入访客单位"
-						placeholder-style="color: #c0c4cc" />
-				</view>
-				<view class="form-item">
-					<text class="label">手机号</text>
-					<input class="input" v-model="formData.visitorPhone" placeholder="请输入手机号"
-						placeholder-style="color: #c0c4cc" type="number" />
-				</view>
-			</view>
-
-			<!-- 第三块:随行人员 -->
-			<view class="section">
-				<view class="section-title">随行人员</view>
-				<view class="accompany-list">
-					<view class="accompany-item" v-for="(item, index) in formData.accompanyPersons" :key="index">
-						<view class="form-item">
-							<text class="label">随行人员</text>
-							<input class="input" v-model="item.name" placeholder="请输入随行人员姓名"
-								placeholder-style="color: #c0c4cc" />
-						</view>
-						<view class="form-item">
-							<text class="label">手机号</text>
-							<input class="input" v-model="item.phone" placeholder="请输入手机号"
-								placeholder-style="color: #c0c4cc" type="number" />
-						</view>
-						<view class="delete-btn" v-if="formData.accompanyPersons.length > 1"
-							@click="removeAccompany(index)">
-							<uni-icons type="trash" size="18" color="#ff4757"></uni-icons>
-						</view>
-					</view>
-				</view>
-				<view class="add-accompany-btn" @click="addAccompany">
-					<uni-icons type="plus" size="16" color="#007aff"></uni-icons>
-					<text>添加随行人员</text>
-				</view>
-			</view>
-
-			<!-- 第四块:使用车辆 -->
-			<view class="section">
-				<view class="vehicle-header">
-					<view class="section-title">
-						<image class="title-icon" src="/static/images/cart.png" mode="aspectFit"></image>
-						使用车辆
-					</view>
-					<switch :checked="formData.useVehicle" @change="onVehicleChange" color="#007aff" />
-				</view>
-
-				<view v-if="formData.useVehicle" class="vehicle-content">
-					<view class="form-item">
-						<text class="label">接客时间</text>
-						<uni-datetime-picker type="datetime" v-model="formData.pickupTime" @change="onPickupTimeChange"
-							:clear-icon="false" placeholder="请选择接客时间" format="YYYY-MM-DD HH:mm" :hide-second="true">
-							<view class="input-wrapper">
-								<text class="placeholder" v-if="!formData.pickupTime">请选择接客时间</text>
-								<text v-else>{{ formData.pickupTime }}</text>
-								<uni-icons type="calendar" size="16" color="#c0c4cc"></uni-icons>
-							</view>
-						</uni-datetime-picker>
-					</view>
-					<view class="form-item">
-						<text class="label">接客地点</text>
-						<input class="input" v-model="formData.pickupLocation" placeholder="请输入接客地点"
-							placeholder-style="color: #c0c4cc" />
-					</view>
-				</view>
-			</view>
-		</view>
-
-		<!-- 提交按钮 -->
-		<view class="submit-container">
-			<button class="submit-btn" @click="submitForm">提交</button>
-		</view>
-
-		<!-- 部门选择器 -->
-		<uni-popup ref="departmentPopup" type="bottom" style="z-index: 999;">
-			<view class="picker-container">
-				<view class="picker-header">
-					<text @click="$refs.departmentPopup.close()">取消</text>
-					<text class="picker-title">选择所属部门</text>
-					<text @click="confirmDepartment">确定</text>
-				</view>
-				<picker-view class="picker-view" :value="departmentIndex" @change="onDepartmentChange">
-					<picker-view-column>
-						<view class="picker-item" v-for="(item, index) in departments" :key="index">
-							{{ item.deptName }}
-						</view>
-					</picker-view-column>
-				</picker-view>
-			</view>
-		</uni-popup>
-
-<!--		<uni-popup ref="employeeNamePopup" type="bottom" style="z-index: 999;">-->
-<!--			<view class="picker-container">-->
-<!--				<view class="picker-header">-->
-<!--					<text @click="$refs.employeeNamePopup.close()">取消</text>-->
-<!--					<text class="picker-title">选择所属部门</text>-->
-<!--					<text @click="confirmDepartment">确定</text>-->
-<!--				</view>-->
-<!--				<picker-view class="picker-view" :value="departmentIndex" @change="onDepartmentChange">-->
-<!--					<picker-view-column>-->
-<!--						<view class="picker-item" v-for="(item, index) in departments" :key="index">-->
-<!--							{{ item.deptName }}-->
-<!--						</view>-->
-<!--					</picker-view-column>-->
-<!--				</picker-view>-->
-<!--			</view>-->
-<!--		</uni-popup>-->
-		<!-- 提交成功弹框 -->
-		<uni-popup ref="successPopup" type="center" :mask-click="false">
-			<view class="success-popup">
-				<view class="popup-content">
-					<view class="success-icon">
-						<uni-icons type="checkmarkempty" size="60" color="#52c41a"></uni-icons>
-					</view>
-					<view class="popup-title">申请提交成功</view>
-					<view class="popup-message">您的申请已成功提交,请关注公众号即时查询审核结果</view>
-					<view class="popup-buttons">
-						<button class="cancel-btn" @click="closeSuccessPopup">取消</button>
-						<button class="follow-btn" @click="showQRCode">关注</button>
-					</view>
-				</view>
-			</view>
-		</uni-popup>
-
-		<!-- 二维码弹框 -->
-		<uni-popup ref="qrcodePopup" type="center" :mask-click="false">
-			<view class="qrcode-popup">
-				<view class="qrcode-content">
-					<view class="qrcode-title">扫描二维码关注公众号</view>
-					<view class="qrcode-image" @click="previewQRCode">
-						<image src="/static/images/qrcode.png" mode="aspectFit"></image>
-						<view class="preview-tip">
-							<uni-icons type="search" size="16" color="#fff"></uni-icons>
-							<text>点击查看大图</text>
-						</view>
-					</view>
-					<view class="qrcode-tip">扫描上方二维码,关注公众号获取审核结果</view>
-					<button class="qrcode-close-btn" @click="closeQRCode">我知道了</button>
-				</view>
-			</view>
-		</uni-popup>
-
-	</view>
-</template>
-
-<script>
-	import user from '../../store/modules/user';
-	import {
-
-		getDept,
-		selectUser
-	} from '@/config/api.js';
-	export default {
-		data() {
-			return {
-				type: '', // 从上一页传递过来的参数
-				formData: {
-					department: '',
-					employeeName: '',
-					visitReason: '',
-					visitTime: '',
-					visitorName: '',
-					visitorCompany: '',
-					visitorPhone: '',
-					accompanyPersons: [{
-						name: '',
-						phone: ''
-					}],
-					useVehicle: false,
-					pickupTime: '',
-					pickupLocation: ''
-				},
-				// 部门假数据
-				departments: [
-					'技术部',
-					'市场部',
-					'人事部',
-					'财务部',
-					'运营部',
-					'产品部',
-					'设计部',
-					'客服部'
-				],
-				departmentIndex: [0],
-				employeeName: '',
-				tempDepartmentIndex:  [0],
-			}
-		},
-		onLoad(options) {
-			// 获取传递过来的参数
-			if (options.type) {
-				this.type = options.type;
-			}
-			this.getDeptList()
-		},
-		methods: {
-			async getDeptList() {
-				console.log("获取DEPT")
-				const res = await getDept()
-				// console.log(res, "12")
-				this.departments = res.data
-			},
-
-			// 显示部门选择器
-			showEmployeeName() {
-				this.$refs.departmentPopup.open();
-			},
-
-			// 部门选择改变
-			onDepartmentChange(e) {
-				console.log("e.detail.value", e)
-				this.tempDepartmentIndex = e.detail.value;
-			},
-
-			// 确认选择部门
-			async confirmDepartment() {
-				this.departmentIndex = [...this.tempDepartmentIndex];
-				const selectedDept = this.departments[this.departmentIndex[0]];
-				this.formData.department = selectedDept.deptName; // 仅显示部门名称
-				console.log(this.formData.department, "1221")
-				const userRes = await selectUser({
-					deptId: selectedDept.deptId // 使用部门对象的 deptId
-				})
-				console.log(userRes, "12222")
-				this.$refs.departmentPopup.close();
-			},
-
-			showDepartmentPicker() {
-				this.$refs.departmentPopup.open();
-			},
-
-
-
-			// 到访时间改变
-			onVisitTimeChange(e) {
-				this.formData.visitTime = e;
-			},
-
-			// 接客时间改变
-			onPickupTimeChange(e) {
-				this.formData.pickupTime = e;
-			},
-
-			// 获取当前日期时间
-			getCurrentDatetime() {
-				const now = new Date();
-				const year = now.getFullYear();
-				const month = String(now.getMonth() + 1).padStart(2, '0');
-				const day = String(now.getDate()).padStart(2, '0');
-				const hour = String(now.getHours()).padStart(2, '0');
-				const minute = String(now.getMinutes()).padStart(2, '0');
-				return `${year}-${month}-${day} ${hour}:${minute}`;
-			},
-
-			// 添加随行人员
-			addAccompany() {
-				this.formData.accompanyPersons.push({
-					name: '',
-					phone: ''
-				});
-			},
-
-			// 删除随行人员
-			removeAccompany(index) {
-				if (this.formData.accompanyPersons.length > 1) {
-					this.formData.accompanyPersons.splice(index, 1);
-				}
-			},
-
-			// 车辆开关改变
-			onVehicleChange(e) {
-				this.formData.useVehicle = e.detail.value;
-				if (!this.formData.useVehicle) {
-					// 关闭车辆使用时清空相关信息
-					this.formData.pickupTime = '';
-					this.formData.pickupLocation = '';
-				}
-			},
-
-
-			// 手机号格式校验
-			validatePhone(phone) {
-				const phoneRegex = /^1[3-9]\d{9}$/;
-				return phoneRegex.test(phone);
-			},
-
-			// 表单验证
-			validateForm() {
-				if (!this.formData.department) {
-					uni.showToast({
-						title: '请选择所属部门',
-						icon: 'none'
-					});
-					return false;
-				}
-				if (!this.formData.employeeName) {
-					uni.showToast({
-						title: '请输入员工姓名',
-						icon: 'none'
-					});
-					return false;
-				}
-				if (!this.formData.visitReason) {
-					uni.showToast({
-						title: '请输入访问事由',
-						icon: 'none'
-					});
-					return false;
-				}
-				if (!this.formData.visitTime) {
-					uni.showToast({
-						title: '请选择到访时间',
-						icon: 'none'
-					});
-					return false;
-				}
-				if (!this.formData.visitorName) {
-					uni.showToast({
-						title: '请输入访客姓名',
-						icon: 'none'
-					});
-					return false;
-				}
-				if (!this.formData.visitorCompany) {
-					uni.showToast({
-						title: '请输入访客单位',
-						icon: 'none'
-					});
-					return false;
-				}
-				if (!this.formData.visitorPhone) {
-					uni.showToast({
-						title: '请输入手机号',
-						icon: 'none'
-					});
-					return false;
-				}
-
-				// 校验访客手机号格式
-				if (!this.validatePhone(this.formData.visitorPhone)) {
-					uni.showToast({
-						title: '请输入正确的手机号格式',
-						icon: 'none'
-					});
-					return false;
-				}
-
-				// 验证随行人员信息
-				for (let i = 0; i < this.formData.accompanyPersons.length; i++) {
-					const person = this.formData.accompanyPersons[i];
-					if (person.name && !person.phone) {
-						uni.showToast({
-							title: `请输入第${i + 1}个随行人员的手机号`,
-							icon: 'none'
-						});
-						return false;
-					}
-					if (!person.name && person.phone) {
-						uni.showToast({
-							title: `请输入第${i + 1}个随行人员的姓名`,
-							icon: 'none'
-						});
-						return false;
-					}
-					// 校验随行人员手机号格式
-					if (person.phone && !this.validatePhone(person.phone)) {
-						uni.showToast({
-							title: `第${i + 1}个随行人员手机号格式不正确`,
-							icon: 'none'
-						});
-						return false;
-					}
-				}
-
-				// 验证车辆使用信息
-				if (this.formData.useVehicle) {
-					if (!this.formData.pickupTime) {
-						uni.showToast({
-							title: '请选择接客时间',
-							icon: 'none'
-						});
-						return false;
-					}
-					if (!this.formData.pickupLocation) {
-						uni.showToast({
-							title: '请选择接客地点',
-							icon: 'none'
-						});
-						return false;
-					}
-				}
-
-				return true;
-			},
-
-			// 提交表单
-			submitForm() {
-				if (!this.validateForm()) {
-					return;
-				}
-
-				// 过滤空的随行人员
-				const validAccompanyPersons = this.formData.accompanyPersons.filter(person =>
-					person.name && person.phone
-				);
-
-				const submitData = {
-					...this.formData,
-					accompanyPersons: validAccompanyPersons,
-					type: this.type
-				};
-
-				console.log('提交数据:', submitData);
-
-				// TODO: 这里调用后端接口提交数据
-				// this.submitToServer(submitData);
-
-				// 显示提交成功弹框
-				this.$refs.successPopup.open();
-			},
-
-			// 关闭成功弹框
-			closeSuccessPopup() {
-				this.$refs.successPopup.close();
-				// 返回上一页
-				uni.navigateBack();
-			},
-
-			// 显示二维码
-			showQRCode() {
-				this.$refs.successPopup.close();
-				this.$refs.qrcodePopup.open();
-			},
-
-			// 关闭二维码弹框
-			closeQRCode() {
-				this.$refs.qrcodePopup.close();
-				// 返回上一页
-				uni.navigateBack();
-			},
-
-			// 预览二维码
-			previewQRCode() {
-				uni.previewImage({
-					urls: ['/static/images/qrcode.png'],
-					current: 0
-				});
-			},
-
-			// 提交到服务器的方法(预留)
-			async submitToServer(data) {
-				// 这里是后端接口调用的预留方法
-				// try {
-				//     const response = await this.$request.post('/api/visit/apply', data);
-				//     return response;
-				// } catch (error) {
-				//     console.error('提交失败:', error);
-				//     throw error;
-				// }
-			}
-		}
-	}
-</script>
-
-<style lang="scss" scoped>
-	.container {
-		background-color: #f5f5f5;
-		min-height: 100vh;
-		padding-bottom: 120rpx;
-	}
-
-	.form-container {
-		padding: 20rpx;
-	}
-
-	.section {
-		background-color: #fff;
-		border-radius: 12rpx;
-		margin-bottom: 20rpx;
-		padding: 30rpx;
-	}
-
-	.section-title {
-		font-size: 32rpx;
-		font-weight: 600;
-		color: #333;
-		margin-bottom: 30rpx;
-		display: flex;
-		align-items: center;
-	}
-
-	.title-icon {
-		width: 40rpx;
-		height: 40rpx;
-		margin-right: 15rpx;
-	}
-
-	.form-item {
-		display: flex;
-		align-items: center;
-		margin-bottom: 30rpx;
-		position: relative;
-
-		&:last-child {
-			margin-bottom: 0;
-		}
-	}
-
-	.label {
-		width: 160rpx;
-		font-size: 28rpx;
-		color: #666;
-		flex-shrink: 0;
-	}
-
-	.input {
-		flex: 1;
-		height: 70rpx;
-		padding: 0 20rpx;
-		background-color: #f8f8f8;
-		border-radius: 8rpx;
-		font-size: 28rpx;
-		color: #333;
-	}
-
-	.input-wrapper {
-		flex: 1;
-		height: 70rpx;
-		padding: 0 20rpx;
-		background-color: #f8f8f8;
-		border-radius: 8rpx;
-		display: flex;
-		align-items: center;
-		justify-content: space-between;
-	}
-
-	.placeholder {
-		color: #c0c4cc;
-		font-size: 28rpx;
-	}
-
-	.accompany-list {
-		.accompany-item {
-			position: relative;
-			padding: 20rpx;
-			background-color: #f8f8f8;
-			border-radius: 8rpx;
-			margin-bottom: 20rpx;
-
-			&:last-child {
-				margin-bottom: 0;
-			}
-
-			.form-item {
-				margin-bottom: 20rpx;
-
-				&:last-child {
-					margin-bottom: 0;
-				}
-			}
-		}
-	}
-
-	.delete-btn {
-		position: absolute;
-		top: 10rpx;
-		right: 10rpx;
-		width: 60rpx;
-		height: 60rpx;
-		display: flex;
-		align-items: center;
-		justify-content: center;
-		background-color: #fff;
-		border-radius: 50%;
-		box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
-	}
-
-	.add-accompany-btn {
-		display: flex;
-		align-items: center;
-		justify-content: center;
-		height: 80rpx;
-		background-color: #f8f9fa;
-		border: 2rpx dashed #c0c4cc;
-		border-radius: 8rpx;
-		color: #909399;
-		font-size: 28rpx;
-
-		text {
-			margin-left: 10rpx;
-		}
-	}
-
-	.vehicle-header {
-		display: flex;
-		align-items: center;
-		margin-bottom: 30rpx;
-
-		.section-title {
-			flex: 1;
-			margin-bottom: 0;
-			margin-left: 15rpx;
-		}
-	}
-
-	.vehicle-content {
-		padding-top: 20rpx;
-		border-top: 1rpx solid #eee;
-	}
-
-	.submit-container {
-		position: fixed;
-		bottom: 0;
-		left: 0;
-		right: 0;
-		padding: 20rpx;
-		background-color: #fff;
-		box-shadow: 0 -2rpx 8rpx rgba(0, 0, 0, 0.1);
-	}
-
-	.submit-btn {
-		width: 100%;
-		height: 88rpx;
-		background: linear-gradient(135deg, #ff6b35 0%, #ff9500 100%);
-		border-radius: 44rpx;
-		border: none;
-		color: #fff;
-		font-size: 32rpx;
-		font-weight: 600;
-	}
-
-	.picker-container {
-		background-color: #fff;
-		border-radius: 20rpx 20rpx 0 0;
-	}
-
-	.picker-header {
-		display: flex;
-		align-items: center;
-		justify-content: space-between;
-		padding: 30rpx;
-		border-bottom: 1rpx solid #eee;
-
-		text {
-			color: #007aff;
-			font-size: 28rpx;
-		}
-	}
-
-	.picker-title {
-		font-size: 32rpx;
-		font-weight: 600;
-		color: #333 !important;
-	}
-
-	.picker-view {
-		height: 400rpx;
-	}
-
-	.picker-item {
-		display: flex;
-		align-items: center;
-		justify-content: center;
-		height: 80rpx;
-		font-size: 28rpx;
-		color: #333;
-	}
-
-	// 提交成功弹框样式
-	.success-popup {
-		.popup-content {
-			background-color: #fff;
-			border-radius: 20rpx;
-			padding: 60rpx 40rpx 40rpx;
-			width: 560rpx;
-			text-align: center;
-		}
-
-		.success-icon {
-			margin-bottom: 30rpx;
-		}
-
-		.popup-title {
-			font-size: 36rpx;
-			font-weight: 600;
-			color: #333;
-			margin-bottom: 20rpx;
-		}
-
-		.popup-message {
-			font-size: 28rpx;
-			color: #666;
-			line-height: 1.6;
-			margin-bottom: 50rpx;
-		}
-
-		.popup-buttons {
-			display: flex;
-			gap: 20rpx;
-
-			button {
-				flex: 1;
-				height: 80rpx;
-				border-radius: 40rpx;
-				font-size: 28rpx;
-				border: none;
-			}
-
-			.cancel-btn {
-				background-color: #f5f5f5;
-				color: #666;
-			}
-
-			.follow-btn {
-				background: linear-gradient(135deg, #ff6b35 0%, #ff9500 100%);
-				color: #fff;
-			}
-		}
-	}
-
-	// 二维码弹框样式
-	.qrcode-popup {
-		.qrcode-content {
-			background-color: #fff;
-			border-radius: 20rpx;
-			padding: 50rpx 40rpx;
-			width: 560rpx;
-			text-align: center;
-		}
-
-		.qrcode-title {
-			font-size: 32rpx;
-			font-weight: 600;
-			color: #333;
-			margin-bottom: 40rpx;
-		}
-
-		.qrcode-image {
-			width: 400rpx;
-			height: 400rpx;
-			margin: 0 auto 30rpx;
-			border: 1rpx solid #eee;
-			border-radius: 12rpx;
-			overflow: hidden;
-			position: relative;
-
-			image {
-				width: 100%;
-				height: 100%;
-			}
-
-			.preview-tip {
-				position: absolute;
-				left: 0;
-				right: 0;
-				bottom: 0;
-				height: 60rpx;
-				background: rgba(0, 0, 0, 0.5);
-				display: flex;
-				align-items: center;
-				justify-content: center;
-				color: #fff;
-				font-size: 24rpx;
-
-				text {
-					margin-left: 10rpx;
-				}
-			}
-
-			&:active {
-				opacity: 0.8;
-			}
-		}
-
-		.qrcode-tip {
-			font-size: 26rpx;
-			color: #999;
-			margin-bottom: 40rpx;
-			line-height: 1.5;
-		}
-
-		.qrcode-close-btn {
-			width: 100%;
-			height: 80rpx;
-			background: linear-gradient(135deg, #ff6b35 0%, #ff9500 100%);
-			border-radius: 40rpx;
-			color: #fff;
-			font-size: 28rpx;
-			border: none;
-		}
-	}
-</style>

+ 1 - 1
vite.config.js

@@ -12,7 +12,7 @@ export default defineConfig({
 		port: 8080,
 		proxy: {
 			'/api': {
-				target: 'http://localhost:8085',
+				target: 'https://zhijidaouniapp.dianjingkeji.net/prod-api',
 				changeOrigin: true,
 				rewrite: (path) => path.replace(/^\/api/, ''), // 此处进行路径重写
 			}