Browse Source

按照最新设计图进行修改和新增(新增考勤打卡和运维、修改原出入库,未联调接口)

htc 1 month ago
parent
commit
526b4c18ca

+ 174 - 0
components/CusCalendar/index.vue

@@ -0,0 +1,174 @@
+<template>
+	<view class="box">
+		<div class="week">
+			<div class="w_pre" v-for="(pre,idx) in weekList" :key="idx">{{pre}}</div>
+		</div>
+		<div class="date">
+			<div class="d_pre" v-for="(pre,idx) in calendarList" :key="idx" @tap="selectDay(pre,idx)">
+				<div class="day" :class="{'dq':pre.iscurrentday,'select':pre.select,'wd':pre.isweekday}">{{pre.day}}</div>
+				<div class="status" :class="{'zc':pre.status==1,'yc':pre.status==2}" v-if="pre.isweekday"></div>
+			</div>
+		</div>
+	</view>
+</template>
+
+<script>
+	export default {
+		data(){
+			return {
+				weekList:['一','二','三','四','五','六','日'],
+				year:new Date().getFullYear(),
+				month:new Date().getMonth()+1,
+				calendarList:[]
+			}
+		},
+		created() {
+			this.getDataByMonth(this.year,this.month);
+		},
+		methods:{
+			getDataByMonth(year,month){
+				const daysInMonth = new Date(year, month, 0).getDate();
+				let calendar = [];
+				for (let day = 1; day <= daysInMonth; day++) {
+					let date = new Date(year, month - 1, day); // 注意月份从0开始
+					let nyr = `${year}-${String(month).padStart(2, '0')}-${String(day).padStart(2, '0')}`;
+					calendar.push({
+					  nyr,
+					  year,
+					  month,
+					  day,
+					  week: date.getDay()||7,
+					  isweekday:(date.getDay()||7)<6,
+					  iscurrentday:nyr==new Date().Format('yyyy-MM-dd')
+					});
+				}
+				let qlist = this.insertDays(year,month,calendar);
+				let hlist = this.appendDays(year,month,calendar);
+				let list = qlist.concat(calendar).concat(hlist);
+				this.calendarList = JSON.parse(JSON.stringify(list));
+				this.calendarList.forEach((c,i)=>{
+					this.$set(this.calendarList[i],'select',false);
+					this.$set(this.calendarList[i],'status',1);
+				})
+			},
+			insertDays(year,month,calendar){
+				let week = calendar[0].week;
+				if(week==1) return []
+				let qyear = month==1?(year-1):year;
+				let qmonth = month==1?12:month-1;
+				let daysInMonth = new Date(qyear, qmonth, 0).getDate();
+				let list = [];
+				for (let day = daysInMonth-week+2; day <= daysInMonth; day++) {
+					let date = new Date(qyear, qmonth - 1, day);
+					list.push({
+					  nyr: `${qyear}-${String(qmonth).padStart(2, '0')}-${String(day).padStart(2, '0')}`,
+					  year:qyear,
+					  month:qmonth,
+					  day,
+					  week: date.getDay()||7
+					});
+				}
+				return list
+			},
+			appendDays(year,month,calendar){
+				let week = calendar[calendar.length-1].week;
+				if(week==7) return []
+				let hyear = month==12?(year+1):year;
+				let hmonth = month==12?1:month+1;
+				let daysInMonth = new Date(hyear, hmonth, 0).getDate();
+				let list = [];
+				for (let day = 1; day <= 7-week; day++) {
+					let date = new Date(hyear, hmonth - 1, day);
+					list.push({
+					  nyr: `${hyear}-${String(hmonth).padStart(2, '0')}-${String(day).padStart(2, '0')}`,
+					  year:hyear,
+					  month:hmonth,
+					  day,
+					  week: date.getDay()||7
+					});
+				}
+				return list
+			},
+			async selectDay(pre,idx){
+				if(pre?.month==this.month){
+					this.calendarList.forEach((c,i)=>{
+						this.$set(this.calendarList[i],'select',i===idx);
+					})
+				}else{
+					this.year = pre.year;
+					this.month = pre.month;
+					await this.getDataByMonth(pre.year,pre.month)
+					let idx = this.calendarList.findIndex(c=>c.month==pre.month);
+					this.$set(this.calendarList[idx],'select',true);
+					this.$emit('selectDay',pre);
+				}
+			},
+		}
+	}
+</script>
+
+<style scoped lang="less">
+	.box{
+		.week{
+			display: flex;
+			.w_pre{
+				width: calc(100% / 7);
+				font-family: PingFangSC, PingFang SC;
+				font-weight: 400;
+				font-size: 28rpx;
+				color: #9D9D9D;
+				line-height: 72rpx;
+				text-align: center;
+			}
+		}
+	
+		.date{
+			display: flex;
+			flex-wrap: wrap;
+			.d_pre{
+				width: calc(100% / 7);
+				display: flex;
+				flex-direction: column;
+				align-items: center;
+				padding: 15rpx 0;
+				.day{
+					width: 64rpx;
+					height: 64rpx;
+					border-radius: 16rpx;
+					background: #FFFFFF;
+					font-family: PingFangSC, PingFang SC;
+					font-weight: 400;
+					font-size: 28rpx;
+					color: #9D9D9D;
+					line-height: 64rpx;
+					text-align: center;
+					&.wd{
+						color: #1D2129;
+					}
+					&.dq{
+						color: #2E69EB;
+						font-weight: bold;
+						background: rgba(46,105,235,0.1);
+					}
+					&.select{
+						color: #FFFFFF;
+						font-weight: bold;
+						background: #2E69EB;
+					}
+				}
+				.status{
+					width: 10rpx;
+					height: 10rpx;
+					border-radius: 50%;
+					margin-top: 5rpx;
+					&.zc{
+						background: #2E69EB;
+					}
+					&.yc{
+						background: #FEA400;
+					}
+				}
+			}
+		}
+	}
+</style>

+ 95 - 0
components/CusTabbar/clock.vue

@@ -0,0 +1,95 @@
+<template>
+	<view class="bottom_tabbar">
+		<view v-for="(item,index) in list" :key="index" @tap="changeTabbar(index)">
+			<image :src="tabbarIndex===index?item.activeImg:item.inactiveImg"></image>
+			<text :class="{'active':tabbarIndex===index}">{{item.text}}</text>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		props: {
+			tabbarIndex: 0
+		},
+		data() {
+			return {
+				tabbarValue: 0,
+				list: [
+					{
+						inactiveImg: this.$imgBase+'clockingin/clock_inactive.png',
+						activeImg: this.$imgBase+'clockingin/clock_active.png',
+						text: '打卡',
+						path: '/pagesClockin/index'
+					},
+					{
+						inactiveImg: this.$imgBase+'clockingin/statistics_inactive.png',
+						activeImg: this.$imgBase+'clockingin/statistics_active.png',
+						text: '统计',
+						path: '/pagesStatistics/index'
+					},
+					{
+						inactiveImg: this.$imgBase+'clockingin/set_inactive.png',
+						activeImg: this.$imgBase+'clockingin/set_active.png',
+						text: '设置',
+						path: '/pagesSetting/index'
+					},
+				]
+			}
+		},
+		mounted() {
+			this.tabbarValue = this.tabbarIndex;
+		},
+		methods: {
+			changeTabbar(e) {
+				this.tabbarValue = e;
+				uni.reLaunch({
+					url: this.list[e].path
+				})
+			}
+		}
+	}
+</script>
+
+<style scoped lang="less">
+	.bottom_tabbar {
+		width: 100%;
+		height: 168rpx;
+		background: #FFFFFF;
+		display: flex;
+		position: fixed;
+		left: 0;
+		bottom: 0;
+		z-index: 999;
+		padding-top: 10rpx;
+		box-sizing: border-box;
+		border-top: 1rpx solid lavender;
+
+		&>view {
+			width: calc(100% / 3);
+			height: 100%;
+			display: flex;
+			flex-direction: column;
+			align-items: center;
+
+			image {
+				width: 48rpx;
+				height: 48rpx;
+			}
+
+			text {
+				margin-top: 6rpx;
+				font-family: PingFangSC, PingFang SC;
+				font-weight: 400;
+				font-size: 24rpx;
+				color: #86909C;
+				line-height: 33rpx;
+				text-align: center;
+				&.active{
+					font-weight: bold;
+					color: #198CFF;
+				}
+			}
+		}
+	}
+</style>

+ 11 - 11
components/CusTabbar/index.vue

@@ -16,11 +16,17 @@
 			return {
 				tabbarValue: 0,
 				list: [
+					// {
+					// 	inactiveImg: this.$imgBase+'icon_home_grey.png',
+					// 	activeImg: this.$imgBase+'icon_home_blue.png',
+					// 	text: '首页',
+					// 	path: '/pagesHome/index'
+					// },
 					{
-						inactiveImg: this.$imgBase+'icon_home_grey.png',
-						activeImg: this.$imgBase+'icon_home_blue.png',
-						text: '首页',
-						path: '/pagesHome/index'
+						inactiveImg: this.$imgBase+'icon_storage_grey.png',
+						activeImg: this.$imgBase+'icon_storage_blue.png',
+						text: '仓储管理',
+						path: '/pagesStorage/home'
 					},
 					{
 						inactiveImg: this.$imgBase+'icon_code_grey.png',
@@ -28,12 +34,6 @@
 						text: '扫码',
 						path: '/pagesCode/index'
 					},
-					{
-						inactiveImg: this.$imgBase+'icon_storage_grey.png',
-						activeImg: this.$imgBase+'icon_storage_blue.png',
-						text: '仓储管理',
-						path: '/pagesStorage/home'
-					},
 				],
 				loginSuccessUrl:''
 			}
@@ -67,7 +67,7 @@
 		border-top: 1rpx solid lavender;
 
 		&>view {
-			width: calc(100% / 3);
+			width: calc(100% / 2);
 			height: 100%;
 			display: flex;
 			flex-direction: column;

+ 1 - 1
manifest.json

@@ -116,7 +116,7 @@
         },
         "permission" : {
             "scope.userLocation" : {
-                "desc" : "获取当前天气"
+                "desc" : "需要获取您的位置以计算距离"
             }
         }
     },

+ 88 - 0
pages.json

@@ -1,5 +1,19 @@
 {
 	"pages": [
+		// {
+		// 	"path": "pages/operation/index",
+		// 	"style": {
+		// 		"navigationStyle": "custom"
+		// 	}
+		// },
+		
+		{
+			"path": "pagesClockin/index",
+			"style": {
+				"navigationStyle": "custom"
+			}
+		},
+		
 		{
 			"path": "pages/login/wxLogin",
 			"style": {
@@ -261,6 +275,80 @@
 					}
 				}
 			]
+		},
+		// {
+		// 	"root": "pagesClockin",
+		// 	"pages": [
+		// 		{
+		// 			"path": "index",
+		// 			"style": {
+		// 				"navigationStyle": "custom"
+		// 			}
+		// 		}
+		// 	]
+		// },
+		{
+			"root": "pagesStatistics",
+			"pages": [
+				{
+					"path": "index",
+					"style": {
+						"navigationStyle": "custom"
+					}
+				}
+			]
+		},
+		{
+			"root": "pagesSetting",
+			"pages": [
+				{
+					"path": "index",
+					"style": {
+						"navigationStyle": "custom"
+					}
+				}
+			]
+		},
+		{
+			"root": "pagesOperation",
+			"pages": [
+				{
+					"path": "record/index",
+					"style": {
+						"navigationStyle": "custom"
+					}
+				},
+				{
+					"path": "record/add",
+					"style": {
+						"navigationStyle": "custom"
+					}
+				},
+				{
+					"path": "record/detail",
+					"style": {
+						"navigationStyle": "custom"
+					}
+				},
+				{
+					"path": "repair/index",
+					"style": {
+						"navigationStyle": "custom"
+					}
+				},
+				{
+					"path": "workorder/index",
+					"style": {
+						"navigationStyle": "custom"
+					}
+				},
+				{
+					"path": "workorder/detail",
+					"style": {
+						"navigationStyle": "custom"
+					}
+				}
+			]
 		}
 	],
 	"globalStyle": {

+ 2 - 2
pages/login/wxLogin.vue

@@ -25,7 +25,7 @@
 			decryptPhoneNumber(e){
 				if(uni.getStorageSync('token')){
 					uni.reLaunch({
-						url:'/pagesHome/index'
+						url:'/pagesStorage/home'
 					})
 					return
 				}
@@ -53,7 +53,7 @@
 								that.$showToast('登录成功');
 								setTimeout(()=>{
 									uni.reLaunch({
-										url:'/pagesHome/index'
+										url:'/pagesStorage/home'
 									})
 								},1500)
 							}else that.$showToast(res.data.msg)

+ 336 - 0
pages/operation/index.vue

@@ -0,0 +1,336 @@
+<template>
+	<view class="page" :style="{'min-height':h+'px', 'padding-top':mt+'px'}">
+		<cus-header title='运维服务' bgColor="transparent" :showback="false"></cus-header>
+		<image class="topbg" :src="imgBase+'operation/top_bg.png'" mode="widthFix"></image>
+		<div class="order">
+			<div class="pre">
+				<div class="top">
+					<div class="left">
+						<p>本月巡检次数</p>
+						<p>{{5}}/{{40}}</p>
+					</div>
+					<div class="right">
+						<p>异常:<span>{{0}}</span></p>
+						<p>正常:<span>{{40}}</span></p>
+					</div>
+				</div>
+				<div class="bottom">
+					<div class="jd" :style="{'width':10+'%'}"></div>
+				</div>
+			</div>
+			<div class="pre">
+				<div class="top">
+					<div class="left">
+						<p>故障工单</p>
+						<p>{{14}}/{{28}}</p>
+					</div>
+					<div class="right">
+						<p>已解决:<span>{{5}}</span></p>
+						<p>未解决:<span>{{40}}</span></p>
+					</div>
+				</div>
+				<div class="bottom">
+					<div class="jd green" :style="{'width':50+'%'}"></div>
+				</div>
+			</div>
+		</div>
+		<div class="menu">
+			<div class="pre" @tap="turnPage('/pagesOperation/record/add')">
+				<image :src="imgBase+'operation/menu_xjtd.png'" mode="widthFix"></image>
+				<p>巡检提单</p>
+			</div>
+			<div class="pre" @tap="turnPage('/pagesOperation/record/index')">
+				<image :src="imgBase+'operation/menu_xjjl.png'" mode="widthFix"></image>
+				<p>巡检记录</p>
+			</div>
+			<div class="pre" @tap="turnPage('/pagesOperation/repair/index')">
+				<image :src="imgBase+'operation/menu_gzbx.png'" mode="widthFix"></image>
+				<p>故障报修</p>
+			</div>
+			<div class="pre" @tap="turnPage('/pagesOperation/workorder/index')">
+				<image :src="imgBase+'operation/menu_gzgd.png'" mode="widthFix"></image>
+				<p>故障工单</p>
+			</div>
+		</div>
+		<div class="list">
+			<div class="title">
+				<div class="left">故障工单</div>
+				<div class="right" @tap="turnPage('/pagesOperation/workorder/index')">
+					<span>更多</span>
+					<image :src="imgBase+'operation/arrow_right.png'" mode="widthFix"></image>
+				</div>
+			</div>
+			<div class="boxs">
+				<div class="item" v-for="(item,index) in [1,2]" :key="index">
+					<div class="left">
+						<div class="name">长鑫科技集团股份有限公司</div>
+						<p>故障类型<span>{{'类型1'}}</span></p>
+						<p>故障描述<span>{{'巡检任务'}}</span></p>
+						<p>故障时间<span>{{'2025-03-28 13:00'}}</span></p>
+					</div>
+					<div class="right">
+						<div class="top" :class="{'djj':index===0,'yjj':index===1}">{{index===0?'待解决':'已解决'}}</div>
+						<div class="bottom" @tap="toDetail(item)">查看</div>
+					</div>
+				</div>
+			</div>
+		</div>
+	</view>
+</template>
+
+<script>
+	export default {
+		data(){
+			return {
+				
+				
+			}
+		},
+		methods:{
+			turnPage(url){
+				if(!url) return
+				uni.navigateTo({ url })
+			},
+			toDetail(item){
+				uni.navigateTo({
+					url:'/pagesOperation/workorder/detail?id='+item?.id
+				})
+			}
+		}
+	}
+</script>
+
+<style scoped lang="less">
+	.page{
+		padding: 0 24rpx 40rpx;
+		background: #F5F8FA;
+		box-sizing: border-box;
+		
+		.topbg{
+			width: 100%;
+			position: fixed;
+			top: 0;
+			left: 0;
+			z-index: 0;
+		}
+		
+		.order{
+			display: flex;
+			justify-content: space-between;
+			position: relative;
+			margin-top: 218rpx;
+			.pre{
+				width: calc(50% - 9rpx);
+				background: rgba(255,255,255,0.7);
+				border-radius: 12rpx;
+				border: 2rpx solid #FFFFFF;
+				padding: 30rpx 20rpx;
+				box-sizing: border-box;
+				.top{
+					display: flex;
+					align-items: center;
+					justify-content: space-between;
+					.left{
+						p{
+							font-family: PingFangSC, PingFang SC;
+							font-weight: 400;
+							font-size: 24rpx;
+							color: #657588;
+							line-height: 24rpx;
+							&:last-child{
+								font-family: DINAlternate, DINAlternate;
+								font-weight: bold;
+								font-size: 36rpx;
+								color: #333333;
+								line-height: 36rpx;
+								margin-top: 20rpx;
+							}
+						}
+					}
+					.right{
+						p{
+							font-family: PingFangSC, PingFang SC;
+							font-weight: 400;
+							font-size: 20rpx;
+							color: #657588;
+							position: relative;
+							padding-left: 16rpx;
+							&::before{
+								content: '';
+								width: 10rpx;
+								height: 10rpx;
+								background: #FEA400;
+								border-radius: 50%;
+								position: absolute;
+								left: 0;
+								top: 50%;
+								margin-top: -5rpx;
+							}
+							&:last-child{
+								margin-top: 20rpx;
+								&::before{
+									background: #DDE0E6;
+								}
+							}
+							span{
+								color: #1D2129;
+							}
+						}
+					}
+				}
+				.bottom{
+					width: 100%;
+					height: 6rpx;
+					background: #DFE5EE;
+					border-radius: 3rpx;
+					margin-top: 24rpx;
+					position: relative;
+					.jd{
+						height: 6rpx;
+						background: #FEA400;
+						border-radius: 3rpx;
+						position: absolute;
+						left: 0;
+						top: 0;
+						&.green{
+							background: #31D1D6;
+						}
+					}
+				}
+			}
+		}
+	
+		.menu{
+			padding: 38rpx 0;
+			background: #FFFFFF;
+			border-radius: 12rpx;
+			margin-top: 20rpx;
+			display: flex;
+			position: relative;
+			.pre{
+				width: 25%;
+				display: flex;
+				flex-direction: column;
+				align-items: center;
+				image{
+					width: 64rpx;
+					height: 64rpx;
+				}
+				p{
+					font-family: PingFangSC, PingFang SC;
+					font-weight: 400;
+					font-size: 24rpx;
+					color: #4E5969;
+					line-height: 30rpx;
+					text-align: center;
+					margin-top: 18rpx;
+				}
+			}
+		}
+	
+		.list{
+			margin-top: 49rpx;
+			.title{
+				display: flex;
+				align-items: center;
+				justify-content: space-between;
+				.left{
+					font-family: PingFang-SC, PingFang-SC;
+					font-weight: bold;
+					font-size: 36rpx;
+					color: #1D2129;
+					line-height: 50rpx;
+				}
+				.right{
+					display: flex;
+					align-items: center;
+					span{
+						font-family: PingFangSC, PingFang SC;
+						font-weight: 400;
+						font-size: 26rpx;
+						color: #86909C;
+						line-height: 26rpx;
+					}
+					image{
+						width: 24rpx;
+						height: 24rpx;
+						margin-left: 13rpx;
+					}
+				}
+			}
+			.boxs{
+				margin-top: 36rpx;
+				.item{
+					background: #FFFFFF;
+					box-shadow: inset 0rpx -1rpx 0rpx 0rpx #ECEEF5;
+					padding: 36rpx 27rpx;
+					display: flex;
+					.left{
+						width: calc(100% - 115rpx);
+						padding-right: 20rpx;
+						box-sizing: border-box;
+						.name{
+							font-family: PingFang-SC, PingFang-SC;
+							font-weight: bold;
+							font-size: 30rpx;
+							color: #1D2129;
+							line-height: 42rpx;
+							text-align: left;
+							white-space: nowrap;
+							overflow: hidden;
+							text-overflow: ellipsis;
+						}
+						p{
+							margin-top: 36rpx;
+							font-family: PingFangSC, PingFang SC;
+							font-weight: 400;
+							font-size: 26rpx;
+							color: #86909C;
+							line-height: 26rpx;
+							span{
+								color: #1D2129;
+								margin-left: 64rpx;
+							}
+						}
+					}
+					.right{
+						width: 115rpx;
+						display: flex;
+						flex-direction: column;
+						justify-content: space-between;
+						.top{
+							width: 104rpx;
+							height: 48rpx;
+							border-radius: 6rpx;
+							font-family: PingFangSC, PingFang SC;
+							font-weight: 400;
+							font-size: 26rpx;
+							line-height: 48rpx;
+							text-align: center;
+							&.djj{
+								color: #FEA400;
+								background: rgba(254,164,0,0.08);
+							}
+							&.yjj{
+								color: #05C17F;
+								background: rgba(20,204,140,0.08);
+							}
+						}
+						.bottom{
+							width: 115rpx;
+							height: 64rpx;
+							background: #2E69EB;
+							border-radius: 16rpx;
+							font-family: PingFang-SC, PingFang-SC;
+							font-weight: bold;
+							font-size: 28rpx;
+							color: #FFFFFF;
+							line-height: 64rpx;
+							text-align: center;
+						}
+					}
+				}
+			}
+		}
+	}
+</style>

+ 385 - 0
pagesClockin/index.vue

@@ -0,0 +1,385 @@
+<template>
+	<view class="tabPage" :style="{'min-height':h+'px', 'padding-top':mt+'px'}">
+		<cus-header title='打卡' bgColor="transparent" :showback="false"></cus-header>
+		<image class="topbg" :src="imgBase+'clockingin/topbg.png'" mode="widthFix"></image>
+		<div class="info">
+			<div class="i_avatar">
+				<image :src="imgBase+'clockingin/default_avatar.png'"></image>
+			</div>
+			<div class="i_name_date">
+				<p>{{username}}</p>
+				<p class="date">{{dateweek}}</p>
+			</div>
+		</div>
+		<div class="card">
+			<div class="c_title">今日打卡</div>
+			<div class="c_worktime">
+				<div class="cw_pre">
+					<p>上班08:30</p>
+					<div class="cwp_time">
+						<image :src="imgBase+'clockingin/checked_active.png'"></image>
+						<span>打卡{{sbClockTime||'- -'}}</span>
+					</div>
+					<div class="cwp_status active">已打卡</div>
+				</div>
+				<div class="cw_pre">
+					<p>下班20:00</p>
+					<div class="cwp_time">
+						<image :src="imgBase+'clockingin/checked_inactive.png'"></image>
+						<span>{{xbClockTime||'- -'}}</span>
+					</div>
+					<div class="cwp_status inactive">未打卡</div>
+				</div>
+			</div>
+			<div class="c_clock">
+				<div class="cc_box" :style="{'background-image':'url('+imgBase+'clockingin/clock_active_bg.png)'}" @tap="clock">
+					<p>{{isSW?'上班':'下班'}}打卡</p>
+					<p class="time">{{currentSFM}}</p>
+				</div>
+				<div class="cc_location">
+					<image :src="imgBase+'clockingin/location_active.png'"></image>
+					<span>已进入考勤范围:谷锐特设备自动化有限公司</span>
+					<!-- <span>当前定位不在考勤范围内</span> -->
+				</div>
+			</div>
+		</div>
+		<u-popup :show="show" @close="close" mode="center" :round="32" :customStyle="{'width':'calc(100% - 120rpx)'}">
+			<div class="up_box">
+				<div class="upb_close">
+					<image :src="imgBase+'clockingin/close.png'" @tap="close"></image>
+				</div>
+				<image class="upb_text" :src="imgBase+'clockingin/clock_success.png'"></image>
+				<p class="upb_time">打卡时间 {{clockTime}}</p>
+				<image class="upb_img" :src="imgBase+'clockingin/clock_success2.png'"></image>
+				<div class="upb_btn" @tap="close">我知道了</div>
+			</div>
+		</u-popup>
+		<Tabbar :tabbarIndex="0"></Tabbar>
+	</view>
+</template>
+
+<script>
+	var timer = null;
+	const QQMapWX = require('../static/lib/qqmap-wx-jssdk.min.js');
+	const qqmapsdk = new QQMapWX({
+	  key: 'V3NBZ-6NRKT-QOQXY-LU6RY-PNHJ5-QDBTQKEY'
+	});
+	import Tabbar from '@/components/CusTabbar/clock.vue'
+	export default {
+		components:{ Tabbar },
+		data(){
+			return {
+				username:'王勇毅',
+				dateweek:'',
+				sbClockTime:'08::24',
+				xbClockTime:'',
+				isSW:true,//是否是上午,12点前是上午,12点后是下午
+				currentSFM:new Date().Format('hh:mm:ss'),
+				show:false,
+				clockTime:'',
+				distance: null,
+				targetLocation: { //谷锐特 31.962084,117.020446  /跨境电商大厦 31.865786,117.15297
+					latitude: 31.865786,
+					longitude: 117.15297
+				}
+			}
+		},
+		created() {
+			this.getDateWeek();
+			this.getCurrentSFM();
+			this.getCurrentHour();
+		},
+		onUnload() {
+			clearInterval(timer)
+		},
+		mounted() {
+			this.getCurrentLocation();
+		},
+		methods:{
+			getDateWeek(){
+				let date = new Date().Format('yyyy年MM月dd日');
+				let cfg = {0:'天',1:'一',2:'二',3:'三',4:'四',5:'五',6:'六'};
+				let week = cfg[new Date().getDay()];
+				this.dateweek = date+' 星期'+week;
+			},
+			getCurrentSFM(){
+				timer = setInterval(()=>{
+					this.currentSFM = new Date().Format('hh:mm:ss');
+				},1000)
+			},
+			getCurrentHour(){
+				this.isSW =  new Date().getHours()>12?false:true;
+			},
+			clock(){
+				this.clockTime = new Date().Format('hh:mm');
+				this.show = true;
+			},
+			close(){
+				this.show = false;
+			},
+			// 获取当前位置
+			async getCurrentLocation() {
+			  try {
+				const res = await uni.getLocation({
+				  type: 'gcj02 ', // 腾讯地图使用GCJ-02坐标系/
+				  isHighAccuracy: true
+				});
+				console.log(res);
+				this.calculateDistance(
+				  res[1].latitude, 
+				  res[1].longitude,
+				  this.targetLocation.latitude,
+				  this.targetLocation.longitude
+				);
+				console.log(this.distance,'distance');
+			  } catch (err) {
+				uni.showToast({
+				  title: '获取位置失败,请检查权限设置',
+				  icon: 'none'
+				});
+			  }
+			},
+			// 计算两点间距离
+			calculateDistance(lat1, lng1, lat2, lng2) {
+			  qqmapsdk.calculateDistance({
+				mode: 'straight', // 直线距离
+				from: `${lat1},${lng1}`,
+				to: `${lat2},${lng2}`,
+				success: (res) => {
+				  if(res.result && res.result.elements.length > 0) {
+					this.distance = res.result.elements[0].distance;
+				  }
+				},
+				fail: (err) => {
+				  uni.showToast({
+					title: '距离计算失败',
+					icon: 'none'
+				  });
+				}
+			  });
+			}
+		}
+	}
+</script>
+
+<style scoped lang="less">
+	.tabPage{
+		padding: 0 24rpx 188rpx;
+		background: #F4F8FB;
+		
+		.topbg{
+			width: 100%;
+			position: fixed;
+			top: 0;
+			left: 0;
+			z-index: 0;
+		}
+	
+		.info{
+			position: relative;
+			background: #FFFFFF;
+			border-radius: 16rpx;
+			margin-top: 20rpx;
+			padding: 48rpx 24rpx;
+			display: flex;
+			align-items: center;
+			.i_avatar{
+				width: 98rpx;
+				height: 98rpx;
+				image{
+					width: 100%;
+					height: 100%;
+				}
+			}
+			.i_name_date{
+				padding-left: 24rpx;
+				p{
+					font-family: PingFang-SC, PingFang-SC;
+					font-weight: bold;
+					font-size: 36rpx;
+					color: #1D2129;
+					line-height: 36rpx;
+					&.date{
+						font-size: 28rpx;
+						color: #657588;
+						line-height: 28rpx;
+						margin-top: 22rpx;
+					}
+				}
+			}
+		}
+	
+		.card{
+			position: relative;
+			background: #FFFFFF;
+			border-radius: 16rpx;
+			padding: 44rpx 24rpx 211rpx;
+			margin-top: 20rpx;
+			
+			.c_title{
+				font-family: PingFang-SC, PingFang-SC;
+				font-weight: bold;
+				font-size: 36rpx;
+				color: #1D2129;
+				line-height: 36rpx;
+			}
+			
+			.c_worktime{
+				margin-top: 40rpx;
+				display: flex;
+				justify-content: space-between;
+				.cw_pre{
+					width: calc(50% - 15rpx);
+					background: #F5F8FA;
+					border-radius: 16rpx;
+					position: relative;
+					padding: 36rpx 20rpx;
+					box-sizing: border-box;
+					&>p{
+						font-family: PingFangSC, PingFang SC;
+						font-weight: 400;
+						font-size: 32rpx;
+						color: #1D2129;
+						line-height: 32rpx;
+					}
+					.cwp_time{
+						display: flex;
+						align-items: center;
+						margin-top: 32rpx;
+						image{
+							width: 28rpx;
+							height: 28rpx;
+						}
+						span{
+							font-family: PingFangSC, PingFang SC;
+							font-weight: 400;
+							font-size: 28rpx;
+							color: #86909C;
+							line-height: 36rpx;
+							margin-left: 12rpx;
+						}
+					}
+					.cwp_status{
+						width: 108rpx;
+						height: 54rpx;
+						border-radius: 0rpx 16rpx 0rpx 12rpx;
+						font-family: PingFang-SC, PingFang-SC;
+						font-weight: bold;
+						font-size: 24rpx;
+						line-height: 54rpx;
+						text-align: center;
+						position: absolute;
+						top: 0;
+						right: 0;
+						&.active{
+							color: #14D08E;
+							background: rgba(20, 204, 140, 0.08);
+						}
+						&.inactive{
+							color: #86909C;
+							background: #EFEFEF;
+						}
+					}
+				}
+			}
+		
+			.c_clock{
+				display: flex;
+				flex-direction: column;
+				align-items: center;
+				margin-top: 117rpx;
+				
+				.cc_box{
+					width: 306rpx;
+					height: 306rpx;
+					background-repeat: no-repeat;
+					background-size: 100% 100%;
+					display: flex;
+					flex-direction: column;
+					align-items: center;
+					justify-content: center;
+					p{
+						font-family: PingFang-SC, PingFang-SC;
+						font-weight: bold;
+						font-size: 40rpx;
+						color: #FFFFFF;
+						line-height: 56rpx;
+						&.time{
+							font-size: 32rpx;
+							line-height: 45rpx;
+							margin-top: 8px;
+						}
+					}
+				}
+				
+				.cc_location{
+					margin-top: 64rpx;
+					display: flex;
+					align-items: center;
+					image{
+						width: 36rpx;
+						height: 36rpx;
+					}
+					span{
+						font-family: PingFangSC, PingFang SC;
+						font-weight: 400;
+						font-size: 26rpx;
+						color: #86909C;
+						line-height: 26rpx;
+						margin-left: 10rpx;
+					}
+				}
+			}
+		}
+	
+		.up_box{
+			background: linear-gradient( 134deg, #E7F4FD 0%, #FFFFFF 100%);
+			border-radius: 32rpx;
+			padding: 40rpx;
+			display: flex;
+			flex-direction: column;
+			align-items: center;
+			.upb_close{
+				width: 100%;
+				display: flex;
+				justify-content: flex-end;
+				image{
+					width: 32rpx;
+					height: 32rpx;
+				}
+			}
+			.upb_text{
+				width: 210rpx;
+				height: 50rpx;
+				margin-top: 16rpx;
+			}
+			.upb_time{
+				font-family: PingFangSC, PingFang SC;
+				font-weight: 400;
+				font-size: 28rpx;
+				color: #86909C;
+				line-height: 32rpx;
+				margin-top: 36rpx;
+			}
+			.upb_img{
+				width: 344rpx;
+				height: 194rpx;
+				margin-top: 216rpx;
+			}
+			.upb_btn{
+				width: 446rpx;
+				height: 88rpx;
+				background: #0171F6;
+				border-radius: 32rpx;
+				font-family: PingFang-SC, PingFang-SC;
+				font-weight: bold;
+				font-size: 32rpx;
+				color: #FFFFFF;
+				line-height: 88rpx;
+				text-align: center;
+				margin-top: 112rpx;
+				letter-spacing: 2rpx;
+			}
+		}
+	}
+</style>

+ 322 - 0
pagesOperation/record/add.vue

@@ -0,0 +1,322 @@
+<template>
+	<view class="page" :style="{'min-height':h+'px', 'padding-top':mt+'px'}">
+		<cus-header title='添加巡检记录'></cus-header>
+		<div class="boxs">
+			<div class="box">
+				<div class="box_item">
+					<div class="left">项目订单号</div>
+					<div class="right select" @tap="handleSelect(1)">
+						<text>{{orderNo}}</text>
+						<image :src="imgBase+'operation/arrow_right.png'" mode="widthFix"></image>
+					</div>
+				</div>
+				<div class="box_item">
+					<div class="left">巡检地点</div>
+					<div class="right select" @tap="handleSelect(2)">
+						<text>{{placeText}}</text>
+						<image :src="imgBase+'operation/arrow_right.png'" mode="widthFix"></image>
+					</div>
+				</div>
+				<div class="box_item">
+					<div class="left">巡检任务</div>
+					<div class="right">
+						<input type="text" placeholder="请输入巡检任务"  placeholder-class="inp_ph" v-model="dto.ccc">
+					</div>
+				</div>
+				<div class="box_item">
+					<div class="left">巡检负责人</div>
+					<div class="right">
+						<input type="text" placeholder="请输入巡检负责人"  placeholder-class="inp_ph" v-model="dto.ddd">
+					</div>
+				</div>
+				<div class="box_item">
+					<div class="left">巡检时间</div>
+					<div class="right select" @tap="handleSelect(3)">
+						<text>{{dateText}}</text>
+						<image :src="imgBase+'operation/arrow_right.png'" mode="widthFix"></image>
+					</div>
+				</div>
+			</div>
+			<div class="box">
+				<div class="box_item">
+					<div class="left">巡检结果</div>
+					<div class="right">
+						<u-radio-group v-model="dto.fff" :size="30" :iconSize="30">
+							<u-radio :labelSize="30" label="正常"></u-radio>
+							<u-radio :labelSize="30" label="有异常"></u-radio>
+						</u-radio-group>
+					</div>
+				</div>
+				<div class="box_item2">
+					<div class="top">备注</div>
+					<div class="bottom">
+						<u--textarea v-model="dto.ggg" placeholder="请输入备注" placeholder-class="inp_ph2" border="none" height="110"></u--textarea>
+					</div>
+				</div>
+			</div>
+			<div class="box">
+				<div class="box_item2">
+					<div class="top">巡检打卡</div>
+					<div class="bottom" style="padding-top: 24rpx;">
+						<u-upload width="180" height="180"
+							:fileList="fileList"
+						    @afterRead="afterRead"
+						    @delete="deletePic"
+						    multiple
+						    :maxCount="5"
+						></u-upload>
+					</div>
+				</div>
+			</div>
+		</div>
+		<div class="bottom_btn">
+			<div class="btn" @tap="submit">提交</div>
+		</div>
+		<u-picker :itemHeight="88" :show="show1" :columns="columns1" keyName="label" title="项目订单号"
+			@cancel="show1=false" @confirm="e=>confirm(e,1)" :immediateChange="true"></u-picker>
+		<u-picker :itemHeight="88" :show="show2" :columns="columns3" keyName="label" title="巡检地点"
+			@cancel="show2=false" @confirm="e=>confirm(e,2)" :immediateChange="true"></u-picker>
+		<u-datetime-picker :itemHeight="88" :show="show3" v-model="dto.eee" mode="date" title="巡检时间"
+			@cancel="show3=false" @confirm="e=>confirm(e,3)" :immediateChange="true" :minDate="minDate" :maxDate="maxDate"></u-datetime-picker>
+	</view>
+</template>
+
+<script>
+	export default {
+		data(){
+			return {
+				dto:{
+					aaa:'',
+					bbb:'',
+					ccc:'',
+					ddd:'',
+					eee:'',
+					fff:'',
+					ggg:'',
+					hhh:''
+				},
+				fileList:[],
+				orderNo:'请选择项目订单号',
+				placeText:'请选择巡检地点',
+				dateText:'请选择巡检时间',
+				show1:false,
+				show2:false,
+				show3:false,
+				columns1:[[
+					{value:1,label:'PO20250408001'},
+					{value:2,label:'PO20250408002'}
+				]],
+				columns3:[[
+					{value:1,label:'长鑫科技集团股份有限公司'},
+					{value:2,label:'峻凌电子(合肥)有限公司'}
+				]],
+				minDate:'',
+				maxDate:'',
+			}
+		},
+		onLoad() {
+			let d = new Date();
+			this.minDate = new Date(d.getFullYear()-3,d.getMonth()+1,d.getDate()).getTime();
+			this.maxDate = new Date().getTime();
+		},
+		methods:{
+			handleSelect(type){
+				if(type==1) this.show1 = true;
+				else if(type==2) this.show2 = true;
+				else if(type==3) this.show3 = true;
+			},
+			confirm(e,type){
+				if(type==1){
+					this.orderNo = e.value[0].label;
+					this.dto.aaa = e.value[0].value;
+					this.show1 = false;
+				}else if(type==2){
+					this.placeText = e.value[0].label;
+					this.dto.bbb = e.value[0].value;
+					this.show2 = false;
+				}else if(type==3){
+					this.dateText = new Date(e.value).Format('yyyy-MM-dd');
+					this.dto.eee = JSON.parse(JSON.stringify(this.dateText));
+					this.show3 = false;
+				}
+			},
+			// 删除图片
+			deletePic(event) {
+				this.fileList.splice(event.index, 1);
+			},
+			// 新增图片
+			async afterRead(event) {
+				// 当设置 multiple 为 true 时, file 为数组格式,否则为对象格式
+				let lists = [].concat(event.file);
+				let fileListLen = this.fileList.length;
+				lists.map((item) => {
+				  this.fileList.push({
+					...item,
+					status: "uploading",
+					message: "上传中",
+				  });
+				});
+				for (let i = 0; i < lists.length; i++) {
+				  const result = await this.uploadFilePromise(lists[i].url);
+				  let item = this.fileList[fileListLen];
+				  this.fileList.splice(
+					fileListLen,
+					1,
+					Object.assign(item, {
+					  status: "success",
+					  message: "",
+					  url: result,
+					})
+				  );
+				  fileListLen++;
+				}
+			},
+			uploadFilePromise(url) {
+				return new Promise((resolve, reject) => {
+				  let a = uni.uploadFile({
+					url: "http://192.168.2.21:7001/upload", // 仅为示例,非真实的接口地址
+					filePath: url,
+					name: "file",
+					formData: {
+					  user: "test",
+					},
+					success: (res) => {
+					  setTimeout(() => {
+						resolve(res.data.data);
+					  }, 1000);
+					},
+				  });
+				});
+			},
+			submit(){
+				uni.navigateBack()
+			}
+		}
+	}
+</script>
+<style>
+	.inp_ph{
+		font-family: PingFangSC, PingFang SC;
+		font-weight: 400;
+		font-size: 28rpx;
+		color: #B9C0C8;
+		line-height: 40rpx;
+		text-align: right;
+	}
+	.inp_ph2{
+		font-family: PingFangSC, PingFang SC;
+		font-weight: 400;
+		font-size: 28rpx;
+		color: #B9C0C8;
+		line-height: 40rpx;
+		text-align: left;
+	}
+</style>
+<style scoped lang="less">
+	::v-deep .u-radio:last-child{
+		margin-left: 93rpx !important;
+	}
+	::v-deep .u-upload__button .u-icon__icon{
+		font-size: 48rpx !important;
+	}
+	
+	.page{
+		padding-bottom: 168rpx;
+		background: #F4F8FB;
+		
+		.boxs{
+			padding: 0 24rpx;
+			.box{
+				background: #FFFFFF;
+				border-radius: 16rpx;
+				margin-top: 20rpx;
+				padding: 0 24rpx;
+			}
+		}
+		
+		.box_item{
+			display: flex;
+			align-items: center;
+			justify-content: space-between;
+			box-shadow: inset 0rpx -1rpx 0rpx 0rpx #ECEEF5;
+			padding: 24rpx 0;
+			.left{
+				font-family: PingFangSC, PingFang SC;
+				font-weight: 400;
+				font-size: 30rpx;
+				color: #1D2129;
+				line-height: 42rpx;
+			}
+			.right{
+				input{
+					font-family: PingFangSC, PingFang SC;
+					font-weight: 400;
+					font-size: 28rpx;
+					color: #4E5969;
+					line-height: 40rpx;
+					text-align: right;
+				}
+				&.select{
+					display: flex;
+					align-items: center;
+					text{
+						font-family: PingFangSC, PingFang SC;
+						font-weight: 400;
+						font-size: 28rpx;
+						color: #B9C0C8;
+						line-height: 40rpx;
+					}
+					image{
+						width: 24rpx;
+						height: 24rpx;
+						margin-left: 10rpx;
+					}
+				}
+			}
+		}
+		.box_item2{
+			.top{
+				font-family: PingFangSC, PingFang SC;
+				font-weight: 400;
+				font-size: 30rpx;
+				color: #1D2129;
+				line-height: 42rpx;
+				padding-top: 24rpx;
+			}
+			.bottom{
+				padding-bottom: 24rpx;
+				input{
+					font-family: PingFangSC, PingFang SC;
+					font-weight: 400;
+					font-size: 28rpx;
+					color: #4E5969;
+					line-height: 40rpx;
+				}
+			}
+		}
+		
+		.bottom_btn{
+			width: 100%;
+			height: 148rpx;
+			padding: 20rpx 48rpx;
+			box-sizing: border-box;
+			background: #FFFFFF;
+			position: fixed;
+			bottom: 0;
+			left: 0;
+			z-index: 9;
+			.btn{
+				width: 100%;
+				height: 88rpx;
+				background: #2E69EB;
+				border-radius: 16rpx;
+				font-family: PingFang-SC, PingFang-SC;
+				font-weight: bold;
+				font-size: 32rpx;
+				color: #FFFFFF;
+				line-height: 88rpx;
+				text-align: center;
+			}
+		}
+	}
+</style>

+ 144 - 0
pagesOperation/record/detail.vue

@@ -0,0 +1,144 @@
+<template>
+	<view class="page" :style="{'min-height':h+'px', 'padding-top':mt+'px'}">
+		<cus-header title='详情'></cus-header>
+		<div class="boxs">
+			<div class="box">
+				<div class="box_item">
+					<div class="left">项目订单号</div>
+					<div class="right">{{'PO0098877666'}}</div>
+				</div>
+				<div class="box_item">
+					<div class="left">巡检地点</div>
+					<div class="right">{{'长鑫科技集团股份有限公司'}}</div>
+				</div>
+				<div class="box_item">
+					<div class="left">巡检任务</div>
+					<div class="right">{{'日常巡检'}}</div>
+				</div>
+				<div class="box_item">
+					<div class="left">巡检负责人</div>
+					<div class="right">{{'王安宇'}}</div>
+				</div>
+				<div class="box_item">
+					<div class="left">巡检时间</div>
+					<div class="right">{{'2025-03-28'}}</div>
+				</div>
+			</div>
+			<div class="box">
+				<div class="box_item">
+					<div class="left">巡检结果</div>
+					<div class="right">{{'正常'}}</div>
+				</div>
+				<div class="box_item2">
+					<div class="top">备注</div>
+					<div class="bottom">{{''}}</div>
+				</div>
+			</div>
+			<div class="box">
+				<div class="box_item2">
+					<div class="top">巡检打卡</div>
+					<div class="bottom">{{''}}</div>
+				</div>
+			</div>
+		</div>
+		<div class="bottom">
+			<div class="btn" @tap="back">返回</div>
+		</div>
+	</view>
+</template>
+
+<script>
+	export default {
+		data(){
+			return {
+				
+			}
+		},
+		methods:{
+			back(){
+				uni.navigateBack()
+			}
+		}
+	}
+</script>
+
+<style scoped lang="less">
+	.page{
+		padding-bottom: 168rpx;
+		background: #F4F8FB;
+		
+		.boxs{
+			padding: 0 24rpx;
+			.box{
+				background: #FFFFFF;
+				border-radius: 16rpx;
+				margin-top: 20rpx;
+				padding: 0 24rpx;
+			}
+		}
+		
+		.box_item{
+			display: flex;
+			align-items: center;
+			justify-content: space-between;
+			box-shadow: inset 0rpx -1rpx 0rpx 0rpx #ECEEF5;
+			padding: 24rpx 0;
+			.left{
+				font-family: PingFangSC, PingFang SC;
+				font-weight: 400;
+				font-size: 30rpx;
+				color: #1D2129;
+				line-height: 42rpx;
+			}
+			.right{
+				font-family: PingFangSC, PingFang SC;
+				font-weight: 400;
+				font-size: 28rpx;
+				color: #4E5969;
+				line-height: 40rpx;
+				text-align: right;
+			}
+		}
+		.box_item2{
+			.top{
+				font-family: PingFangSC, PingFang SC;
+				font-weight: 400;
+				font-size: 30rpx;
+				color: #1D2129;
+				line-height: 42rpx;
+				padding: 24rpx 0;
+			}
+			.bottom{
+				font-family: PingFangSC, PingFang SC;
+				font-weight: 400;
+				font-size: 28rpx;
+				color: #4E5969;
+				line-height: 40rpx;
+			}
+		}
+		
+		.bottom{
+			width: 100%;
+			height: 148rpx;
+			padding: 20rpx 48rpx;
+			box-sizing: border-box;
+			background: #FFFFFF;
+			position: fixed;
+			bottom: 0;
+			left: 0;
+			z-index: 9;
+			.btn{
+				width: 100%;
+				height: 88rpx;
+				background: #2E69EB;
+				border-radius: 16rpx;
+				font-family: PingFang-SC, PingFang-SC;
+				font-weight: bold;
+				font-size: 32rpx;
+				color: #FFFFFF;
+				line-height: 88rpx;
+				text-align: center;
+			}
+		}
+	}
+</style>

+ 259 - 0
pagesOperation/record/index.vue

@@ -0,0 +1,259 @@
+<template>
+	<view class="page" :style="{'min-height':h+'px', 'padding-top':mt+'px'}">
+		<cus-header title='巡检记录'></cus-header>
+		<div class="query">
+			<div class="pre" @tap="selectQuery(1)">
+				<span>{{statusText}}</span>
+				<u-icon name="arrow-down-fill" color="#C0C4CC" size="20rpx"></u-icon>
+			</div>
+			<div class="pre" @tap="selectQuery(2)">
+				<span>{{timeText}}</span>
+				<u-icon name="arrow-down-fill" color="#C0C4CC" size="20rpx"></u-icon>
+			</div>
+			<div class="pre" @tap="selectQuery(3)">
+				<span>{{placeText}}</span>
+				<u-icon name="arrow-down-fill" color="#C0C4CC" size="20rpx"></u-icon>
+			</div>
+		</div>
+		<div class="boxs" v-if="list.length">
+			<div class="box" v-for="(item,index) in list" :key="index" @tap="toDetail(item)">
+				<div class="top">
+					<div class="left">{{'长鑫科技集团股份有限公司'}}</div>
+					<div class="right">
+						<div class="status" :class="{'zc':index===0,'yc':index===1}">{{index===0?'正常':'异常'}}</div>
+						<image :src="imgBase+'operation/arrow_right.png'" mode="widthFix"></image>
+					</div>
+				</div>
+				<div class="text">
+					<div class="left">巡检时间</div>
+					<p>{{'2025-03-28'}}</p>
+				</div>
+				<div class="text">
+					<div class="left">巡检负责人</div>
+					<p>{{'王安宇'}}</p>
+				</div>
+			</div>
+		</div>
+		<template v-else>
+			<page-empty :height="'calc(100vh - 200px)'"></page-empty>
+		</template>
+		<div class="bottom">
+			<div class="btn" @tap="addRecord">添加巡检记录</div>
+		</div>
+		<u-picker :itemHeight="88" :show="show1" :columns="columns1" keyName="label" title="巡检状态"
+			@cancel="show1=false" @confirm="e=>confirm(e,1)" :immediateChange="true"></u-picker>
+		<u-datetime-picker :itemHeight="88" :show="show2" v-model="queryParams.month" mode="year-month" title="巡检时间"
+			@cancel="show2=false" @confirm="e=>confirm(e,2)" :immediateChange="true" :minDate="minDate" :maxDate="maxDate"></u-datetime-picker>
+		<u-picker :itemHeight="88" :show="show3" :columns="columns3" keyName="label" title="巡检地点"
+			@cancel="show3=false" @confirm="e=>confirm(e,3)" :immediateChange="true"></u-picker>
+	</view>
+</template>
+
+<script>
+	import pageEmpty from '@/components/pageEmpty/index.vue'
+	export default {
+		components:{
+			pageEmpty
+		},
+		data(){
+			return {
+				statusText:'巡检状态',
+				timeText:'巡检时间',
+				placeText:'巡检地点',
+				queryParams:{
+					status:'',
+					month:'',
+					place:''
+				},
+				show1:false,
+				show2:false,
+				show3:false,
+				columns1:[[
+					{value:0,label:'正常'},
+					{value:1,label:'异常'}
+				]],
+				columns3:[[
+					{value:1,label:'长鑫科技集团股份有限公司'},
+					{value:2,label:'峻凌电子(合肥)有限公司'}
+				]],
+				minDate:'',
+				maxDate:'',
+				page:1,
+				limit:10,
+				isOver:false,
+				list:[]
+			}
+		},
+		onReachBottom() {
+			if(this.isOver) return
+			this.getList();
+		},
+		onLoad() {
+			let d = new Date();
+			this.minDate = new Date(d.getFullYear()-3,d.getMonth()+1,d.getDate()).getTime();
+			this.maxDate = new Date().getTime();
+			this.getList();
+		},
+		methods:{
+			getList(){
+				this.list = [1,2]
+			},
+			selectQuery(type){
+				if(type==1) this.show1 = true;
+				else if(type==2) this.show2 = true;
+				else if(type==3) this.show3 = true;
+			},
+			confirm(e,type){
+				if(type==1){
+					this.statusText = e.value[0].label;
+					this.queryParams.status = e.value[0].value;
+					this.show1 = false;
+				}else if(type==2){
+					this.timeText = new Date(e.value).Format('yyyy-MM');
+					this.queryParams.month = new Date(e.value).Format('yyyy-MM');
+					this.show2 = false;
+				}else if(type==3){
+					this.placeText = e.value[0].label;
+					this.queryParams.place = e.value[0].value;
+					this.show3 = false;
+				}
+			},
+			addRecord(){
+				uni.navigateTo({
+					url:'/pagesOperation/record/add'
+				})
+			},
+			toDetail(item){
+				uni.navigateTo({
+					url:'/pagesOperation/record/detail'
+				})
+			}
+		}
+	}
+</script>
+
+<style scoped lang="less">
+	.page{
+		padding-bottom: 168rpx;
+		background: #F4F8FB;
+		
+		.query{
+			width: 100%;
+			height: 88rpx;
+			background: #FFFFFF;
+			display: flex;
+			.pre{
+				width: calc(100% / 3);
+				height: 88rpx;
+				display: flex;
+				align-items: center;
+				justify-content: center;
+				span{
+					font-family: PingFangSC, PingFang SC;
+					font-weight: 400;
+					font-size: 26rpx;
+					color: #86909C;
+					line-height: 26rpx;
+					margin-right: 12rpx;
+				}
+			}
+		}
+	
+		.boxs{
+			padding: 0 24rpx;
+			.box{
+				background: #FFFFFF;
+				border-radius: 16rpx;
+				margin-top: 20rpx;
+				padding: 36rpx 24rpx;
+				.top{
+					display: flex;
+					align-items: center;
+					justify-content: space-between;
+					.left{
+						width: calc(100% - 146rpx);
+						padding-right: 20rpx;
+						font-family: PingFang-SC, PingFang-SC;
+						font-weight: bold;
+						font-size: 30rpx;
+						color: #1D2129;
+						line-height: 30rpx;
+						overflow: hidden;
+						white-space: nowrap;
+						text-overflow: ellipsis;
+					}
+					.right{
+						display: flex;
+						align-items: center;
+						.status{
+							width: 88rpx;
+							height: 42rpx;
+							border-radius: 6rpx;
+							font-family: PingFang-SC, PingFang-SC;
+							font-weight: bold;
+							font-size: 26rpx;
+							color: #FFFFFF;
+							line-height: 42rpx;
+							text-align: center;
+							&.zc{
+								background: #14CC8C;
+							}
+							&.yc{
+								background: #FF4141;
+							}
+						}
+						image{
+							width: 24rpx;
+							height: 24rpx;
+							margin-left: 10rpx;
+						}
+					}
+				}
+				.text{
+					margin-top: 36rpx;
+					display: flex;
+					align-items: center;
+					.left{
+						width: 168rpx;
+						font-family: PingFangSC, PingFang SC;
+						font-weight: 400;
+						font-size: 26rpx;
+						color: #86909C;
+						line-height: 26rpx;
+					}
+					p{
+						font-family: PingFangSC, PingFang SC;
+						font-weight: 400;
+						font-size: 26rpx;
+						color: #1D2129;
+						line-height: 26rpx;
+					}
+				}
+			}
+		}
+			
+		.bottom{
+			width: 100%;
+			height: 148rpx;
+			padding: 20rpx 48rpx;
+			box-sizing: border-box;
+			background: #FFFFFF;
+			position: fixed;
+			bottom: 0;
+			left: 0;
+			z-index: 9;
+			.btn{
+				width: 100%;
+				height: 88rpx;
+				background: #2E69EB;
+				border-radius: 16rpx;
+				font-family: PingFang-SC, PingFang-SC;
+				font-weight: bold;
+				font-size: 32rpx;
+				color: #FFFFFF;
+				line-height: 88rpx;
+				text-align: center;
+			}
+		}
+	}
+</style>

+ 345 - 0
pagesOperation/repair/index.vue

@@ -0,0 +1,345 @@
+<template>
+	<view class="page" :style="{'min-height':h+'px', 'padding-top':mt+'px'}">
+		<cus-header title='故障报修'></cus-header>
+		<div class="boxs">
+			<div class="box">
+				<div class="box_item">
+					<div class="left">项目订单号</div>
+					<div class="right select" @tap="handleSelect(1)">
+						<text>{{orderNo}}</text>
+						<image :src="imgBase+'operation/arrow_right.png'" mode="widthFix"></image>
+					</div>
+				</div>
+				<div class="box_item">
+					<div class="left">报修地点</div>
+					<div class="right select" @tap="handleSelect(2)">
+						<text>{{placeText}}</text>
+						<image :src="imgBase+'operation/arrow_right.png'" mode="widthFix"></image>
+					</div>
+				</div>
+				<div class="box_item">
+					<div class="left">产品名称</div>
+					<div class="right select" @tap="handleSelect(3)">
+						<text>{{productText}}</text>
+						<image :src="imgBase+'operation/arrow_right.png'" mode="widthFix"></image>
+					</div>
+				</div>
+				<div class="box_item">
+					<div class="left">产品编号</div>
+					<div class="right select" @tap="handleSelect(4)">
+						<text>{{productNo}}</text>
+						<image :src="imgBase+'operation/arrow_right.png'" mode="widthFix"></image>
+					</div>
+				</div>
+			</div>
+			<div class="box">
+				<div class="box_item">
+					<div class="left">故障发生时间</div>
+					<div class="right select" @tap="handleSelect(5)">
+						<text>{{dateText}}</text>
+						<image :src="imgBase+'operation/arrow_right.png'" mode="widthFix"></image>
+					</div>
+				</div>
+				<div class="box_item">
+					<div class="left">故障类型</div>
+					<div class="right select" @tap="handleSelect(6)">
+						<text>{{typeText}}</text>
+						<image :src="imgBase+'operation/arrow_right.png'" mode="widthFix"></image>
+					</div>
+				</div>
+				<div class="box_item">
+					<div class="left">报修人员</div>
+					<div class="right">
+						<input type="text" placeholder="请输入报修人员"  placeholder-class="inp_ph" v-model="dto.ggg">
+					</div>
+				</div>
+				<div class="box_item2">
+					<div class="top">故障描述</div>
+					<div class="bottom">
+						<u--textarea v-model="dto.hhh" placeholder="故障描述" placeholder-class="inp_ph2" border="none" height="110"></u--textarea>
+					</div>
+				</div>
+			</div>
+			<div class="box">
+				<div class="box_item2">
+					<div class="top">故障照片</div>
+					<div class="bottom" style="padding-top: 24rpx;">
+						<u-upload width="180" height="180"
+							:fileList="fileList"
+						    @afterRead="afterRead"
+						    @delete="deletePic"
+						    multiple
+						    :maxCount="5"
+						></u-upload>
+					</div>
+				</div>
+			</div>
+		</div>
+		<div class="bottom_btn">
+			<div class="btn" @tap="submit">提交</div>
+		</div>
+		<u-picker :itemHeight="88" :show="show1" :columns="columns1" keyName="label" title="项目订单号"
+			@cancel="show1=false" @confirm="e=>confirm(e,1,'orderNo','aaa')" :immediateChange="true"></u-picker>
+		<u-picker :itemHeight="88" :show="show2" :columns="columns2" keyName="label" title="报修地点"
+			@cancel="show2=false" @confirm="e=>confirm(e,2,'placeText','bbb')" :immediateChange="true"></u-picker>
+		<u-picker :itemHeight="88" :show="show3" :columns="columns3" keyName="label" title="产品名称"
+			@cancel="show3=false" @confirm="e=>confirm(e,3,'productText','ccc')" :immediateChange="true"></u-picker>
+		<u-picker :itemHeight="88" :show="show4" :columns="columns4" keyName="label" title="产品编号"
+			@cancel="show4=false" @confirm="e=>confirm(e,4,'productNo','ddd')" :immediateChange="true"></u-picker>
+		<u-datetime-picker :itemHeight="88" :show="show5" v-model="dto.eee" mode="date" title="故障发生时间"
+			@cancel="show5=false" @confirm="e=>confirm(e,5)" :immediateChange="true" :minDate="minDate" :maxDate="maxDate"></u-datetime-picker>
+		<u-picker :itemHeight="88" :show="show6" :columns="columns6" keyName="label" title="故障类型"
+			@cancel="show6=false" @confirm="e=>confirm(e,6,'typeText','fff')" :immediateChange="true"></u-picker>
+	</view>
+</template>
+
+<script>
+	export default {
+		data(){
+			return {
+				dto:{
+					aaa:'',
+					bbb:'',
+					ccc:'',
+					ddd:'',
+					eee:'',
+					fff:'',
+					ggg:'',
+					hhh:''
+				},
+				fileList:[],
+				orderNo:'请选择项目订单号',
+				placeText:'请选择报修地点',
+				productText:'请选择产品名称',
+				productNo:'请选择产品编号',
+				dateText:'请选择故障发生时间',
+				typeText:'请选择故障类型',
+				show1:false,
+				show2:false,
+				show3:false,
+				show4:false,
+				show5:false,
+				show6:false,
+				columns1:[[
+					{value:1,label:'PO20250408001'},
+					{value:2,label:'PO20250408002'}
+				]],
+				columns2:[[
+					{value:1,label:'长鑫科技集团股份有限公司'},
+					{value:2,label:'峻凌电子(合肥)有限公司'}
+				]],
+				columns3:[[
+					{value:1,label:'产品名称A'},
+					{value:2,label:'产品名称B'},
+				]],
+				columns4:[[
+					{value:1,label:'P20250408001'},
+					{value:2,label:'P20250408002'},
+				]],
+				columns6:[[
+					{value:1,label:'类型A'},
+					{value:2,label:'类型B'},
+				]],
+				minDate:'',
+				maxDate:'',
+			}
+		},
+		onLoad() {
+			let d = new Date();
+			this.minDate = new Date(d.getFullYear()-3,d.getMonth()+1,d.getDate()).getTime();
+			this.maxDate = new Date().getTime();
+		},
+		methods:{
+			handleSelect(type){
+				this['show'+type] = true;
+			},
+			confirm(e,type,param,key){
+				if(type!=5){
+					this[param] = e.value[0].label;
+					this.dto[key] = e.value[0].value;
+				}else{
+					this.dateText = new Date(e.value).Format('yyyy-MM-dd');
+					this.dto.eee = JSON.parse(JSON.stringify(this.dateText));
+				}
+				this['show'+type] = false;
+			},
+			// 删除图片
+			deletePic(event) {
+				this.fileList.splice(event.index, 1);
+			},
+			// 新增图片
+			async afterRead(event) {
+				// 当设置 multiple 为 true 时, file 为数组格式,否则为对象格式
+				let lists = [].concat(event.file);
+				let fileListLen = this.fileList.length;
+				lists.map((item) => {
+				  this.fileList.push({
+					...item,
+					status: "uploading",
+					message: "上传中",
+				  });
+				});
+				for (let i = 0; i < lists.length; i++) {
+				  const result = await this.uploadFilePromise(lists[i].url);
+				  let item = this.fileList[fileListLen];
+				  this.fileList.splice(
+					fileListLen,
+					1,
+					Object.assign(item, {
+					  status: "success",
+					  message: "",
+					  url: result,
+					})
+				  );
+				  fileListLen++;
+				}
+			},
+			uploadFilePromise(url) {
+				return new Promise((resolve, reject) => {
+				  let a = uni.uploadFile({
+					url: "http://192.168.2.21:7001/upload", // 仅为示例,非真实的接口地址
+					filePath: url,
+					name: "file",
+					formData: {
+					  user: "test",
+					},
+					success: (res) => {
+					  setTimeout(() => {
+						resolve(res.data.data);
+					  }, 1000);
+					},
+				  });
+				});
+			},
+			submit(){
+				uni.navigateBack()
+			}
+		}
+	}
+</script>
+<style>
+	.inp_ph{
+		font-family: PingFangSC, PingFang SC;
+		font-weight: 400;
+		font-size: 28rpx;
+		color: #B9C0C8;
+		line-height: 40rpx;
+		text-align: right;
+	}
+	.inp_ph2{
+		font-family: PingFangSC, PingFang SC;
+		font-weight: 400;
+		font-size: 28rpx;
+		color: #B9C0C8;
+		line-height: 40rpx;
+		text-align: left;
+	}
+</style>
+<style scoped lang="less">
+	::v-deep .u-radio:last-child{
+		margin-left: 93rpx !important;
+	}
+	::v-deep .u-upload__button .u-icon__icon{
+		font-size: 48rpx !important;
+	}
+	
+	.page{
+		padding-bottom: 168rpx;
+		background: #F4F8FB;
+		
+		.boxs{
+			padding: 0 24rpx;
+			.box{
+				background: #FFFFFF;
+				border-radius: 16rpx;
+				margin-top: 20rpx;
+				padding: 0 24rpx;
+			}
+		}
+		
+		.box_item{
+			display: flex;
+			align-items: center;
+			justify-content: space-between;
+			box-shadow: inset 0rpx -1rpx 0rpx 0rpx #ECEEF5;
+			padding: 24rpx 0;
+			.left{
+				font-family: PingFangSC, PingFang SC;
+				font-weight: 400;
+				font-size: 30rpx;
+				color: #1D2129;
+				line-height: 42rpx;
+			}
+			.right{
+				input{
+					font-family: PingFangSC, PingFang SC;
+					font-weight: 400;
+					font-size: 28rpx;
+					color: #4E5969;
+					line-height: 40rpx;
+					text-align: right;
+				}
+				&.select{
+					display: flex;
+					align-items: center;
+					text{
+						font-family: PingFangSC, PingFang SC;
+						font-weight: 400;
+						font-size: 28rpx;
+						color: #B9C0C8;
+						line-height: 40rpx;
+					}
+					image{
+						width: 24rpx;
+						height: 24rpx;
+						margin-left: 10rpx;
+					}
+				}
+			}
+		}
+		.box_item2{
+			.top{
+				font-family: PingFangSC, PingFang SC;
+				font-weight: 400;
+				font-size: 30rpx;
+				color: #1D2129;
+				line-height: 42rpx;
+				padding-top: 24rpx;
+			}
+			.bottom{
+				padding-bottom: 24rpx;
+				input{
+					font-family: PingFangSC, PingFang SC;
+					font-weight: 400;
+					font-size: 28rpx;
+					color: #4E5969;
+					line-height: 40rpx;
+				}
+			}
+		}
+		
+		.bottom_btn{
+			width: 100%;
+			height: 148rpx;
+			padding: 20rpx 48rpx;
+			box-sizing: border-box;
+			background: #FFFFFF;
+			position: fixed;
+			bottom: 0;
+			left: 0;
+			z-index: 9;
+			.btn{
+				width: 100%;
+				height: 88rpx;
+				background: #2E69EB;
+				border-radius: 16rpx;
+				font-family: PingFang-SC, PingFang-SC;
+				font-weight: bold;
+				font-size: 32rpx;
+				color: #FFFFFF;
+				line-height: 88rpx;
+				text-align: center;
+			}
+		}
+	}
+</style>

+ 396 - 0
pagesOperation/workorder/detail.vue

@@ -0,0 +1,396 @@
+<template>
+	<view class="page" :style="{'min-height':h+'px', 'padding-top':mt+'px'}">
+		<cus-header title='故障报修'></cus-header>
+		<div class="box">
+			<div class="b_title">
+				故障信息
+				<div class="b_status" :class="{'djj':dto.status===1,'yjj':dto.status===0}">{{dto.status===0?'已解决':'未解决'}}</div>
+			</div>
+			<div class="bs_item">
+				<div class="left">项目订单号</div>
+				<div class="right">{{'PO0098877666'}}</div>
+			</div>
+			<div class="bs_item">
+				<div class="left">报修地点</div>
+				<div class="right">{{'长鑫科技集团股份有限公司'}}</div>
+			</div>
+			<div class="bs_item">
+				<div class="left">产品名称</div>
+				<div class="right">{{'高温罩'}}</div>
+			</div>
+			<div class="bs_item">
+				<div class="left">产品编号</div>
+				<div class="right">{{'GRT9988811'}}</div>
+			</div>
+			<div class="bs_item">
+				<div class="left">故障发生时间</div>
+				<div class="right">{{'2025-03-11 13:00'}}</div>
+			</div>
+			<div class="bs_item">
+				<div class="left">故障类型</div>
+				<div class="right">{{'类型A'}}</div>
+			</div>
+			<div class="bs_item">
+				<div class="left">报修人员</div>
+				<div class="right">{{'王安宇'}}</div>
+			</div>
+			<div class="bs_item">
+				<div class="left">报修时间</div>
+				<div class="right">{{'2025-03-12 13:00'}}</div>
+			</div>
+			<div class="bs_item">
+				<div class="left">故障描述</div>
+				<div class="right">{{'故障描述故障描述'}}</div>
+			</div>
+		</div>
+		<div class="box">
+			<div class="b_title">故障照片</div>
+			<div style="padding-top: 24rpx;">
+				<u-upload width="180" height="180"
+					:fileList="fileList"
+					@afterRead="afterRead"
+					@delete="deletePic"
+					multiple
+					:maxCount="5"
+				></u-upload>
+			</div>
+		</div>
+		<div class="box">
+			<div class="b_title">故障处理</div>
+			<div class="b_item">
+				<div class="left">问题状态</div>
+				<div class="right">
+					<u-radio-group v-model="params.aaa" :size="30" :iconSize="30">
+						<u-radio :labelSize="26" :label="0">已解决</u-radio>
+						<u-radio :labelSize="26" :label="1">未解决</u-radio>
+					</u-radio-group>
+				</div>
+			</div>
+			<div class="b_item">
+				<div class="left">故障原因</div>
+				<div class="right">
+					<input type="text" placeholder="请输入故障原因"  placeholder-class="inp_ph" v-model="params.bbb">
+				</div>
+			</div>
+			<div class="b_item">
+				<div class="left">维修开始时间</div>
+				<div class="right select" @tap="handleSelect(1)">
+					<text>{{startDateText}}</text>
+					<image :src="imgBase+'operation/arrow_right.png'" mode="widthFix"></image>
+				</div>
+			</div>
+			<div class="b_item">
+				<div class="left">维修结束时间</div>
+				<div class="right select" @tap="handleSelect(2)">
+					<text>{{endDateText}}</text>
+					<image :src="imgBase+'operation/arrow_right.png'" mode="widthFix"></image>
+				</div>
+			</div>
+			<div class="b_item">
+				<div class="left">维修人员</div>
+				<div class="right">
+					<input type="text" placeholder="请输入维修人员"  placeholder-class="inp_ph" v-model="params.eee">
+				</div>
+			</div>
+			<div class="b_item2">
+				<div class="top">维修描述</div>
+				<div class="bottom">
+					<u--textarea v-model="dto.fff" placeholder="请输入维修描述" placeholder-class="inp_ph2" border="none" height="110"></u--textarea>
+				</div>
+			</div>
+		</div>
+		<div class="bottom_btn">
+			<div class="btn" @tap="submit">提交</div>
+			<!-- <div class="btn" @tap="back">返回</div> -->
+		</div>
+		<u-datetime-picker :itemHeight="88" :show="show1" v-model="dto.ccc" mode="date" title="维修开始时间"
+			@cancel="show1=false" @confirm="e=>confirm(e,1,'ccc','startDateText')" :immediateChange="true" :minDate="minDate" :maxDate="maxDate"></u-datetime-picker>
+		<u-datetime-picker :itemHeight="88" :show="show2" v-model="dto.ccc" mode="date" title="维修结束时间"
+			@cancel="show2=false" @confirm="e=>confirm(e,2,'ddd','endDateText')" :immediateChange="true" :minDate="minDate" :maxDate="maxDate"></u-datetime-picker>
+	</view>
+</template>
+
+<script>
+	export default {
+		data(){
+			return {
+				dto:{
+					status:1
+				},
+				params:{
+					aaa:'',
+					bbb:'',
+					ccc:'',
+					ddd:'',
+					eee:'',
+					fff:''
+				},
+				fileList:[],
+				show1:false,
+				show2:false,
+				startDateText:'请输入维修开始时间',
+				endDateText:'请输入维修结束时间',
+				minDate:'',
+				maxDate:'',
+			}
+		},
+		mounted() {
+			let d = new Date();
+			this.minDate = new Date(d.getFullYear()-3,d.getMonth()+1,d.getDate()).getTime();
+			this.maxDate = new Date().getTime();
+		},
+		methods:{
+			handleSelect(type){
+				this['show'+type] = true;
+			},
+			confirm(e,type,key,param){
+				this[param] = new Date(e.value).Format('yyyy-MM-dd');
+				this.params[key] = new Date(e.value).Format('yyyy-MM-dd');
+				this['show'+type] = false;
+			},
+			submit(){
+				uni.navigateBack()
+			},
+			back(){
+				uni.navigateBack()
+			},
+			// 删除图片
+			deletePic(event) {
+				this.fileList.splice(event.index, 1);
+			},
+			// 新增图片
+			async afterRead(event) {
+				// 当设置 multiple 为 true 时, file 为数组格式,否则为对象格式
+				let lists = [].concat(event.file);
+				let fileListLen = this.fileList.length;
+				lists.map((item) => {
+				  this.fileList.push({
+					...item,
+					status: "uploading",
+					message: "上传中",
+				  });
+				});
+				for (let i = 0; i < lists.length; i++) {
+				  const result = await this.uploadFilePromise(lists[i].url);
+				  let item = this.fileList[fileListLen];
+				  this.fileList.splice(
+					fileListLen,
+					1,
+					Object.assign(item, {
+					  status: "success",
+					  message: "",
+					  url: result,
+					})
+				  );
+				  fileListLen++;
+				}
+			},
+			uploadFilePromise(url) {
+				return new Promise((resolve, reject) => {
+				  let a = uni.uploadFile({
+					url: "http://192.168.2.21:7001/upload", // 仅为示例,非真实的接口地址
+					filePath: url,
+					name: "file",
+					formData: {
+					  user: "test",
+					},
+					success: (res) => {
+					  setTimeout(() => {
+						resolve(res.data.data);
+					  }, 1000);
+					},
+				  });
+				});
+			},
+		}
+	}
+</script>
+<style>
+	.inp_ph{
+		font-family: PingFangSC, PingFang SC;
+		font-weight: 400;
+		font-size: 28rpx;
+		color: #B9C0C8;
+		line-height: 40rpx;
+		text-align: right;
+	}
+	.inp_ph2{
+		font-family: PingFangSC, PingFang SC;
+		font-weight: 400;
+		font-size: 28rpx;
+		color: #B9C0C8;
+		line-height: 40rpx;
+		text-align: left;
+	}
+</style>
+<style scoped lang="less">
+	::v-deep .u-radio:last-child{
+		margin-left: 93rpx !important;
+	}
+	::v-deep .u-upload__button .u-icon__icon{
+		font-size: 48rpx !important;
+	}
+	
+	.page{
+		padding:0 24rpx 168rpx;
+		background: #F4F8FB;
+		
+		.box{
+			background: #FFFFFF;
+			border-radius: 16rpx;
+			margin-top: 20rpx;
+			padding: 36rpx 24rpx;
+			
+			.b_title{
+				padding-left: 16rpx;
+				position: relative;
+				font-family: PingFang-SC, PingFang-SC;
+				font-weight: bold;
+				font-size: 32rpx;
+				color: #1D2129;
+				line-height: 32rpx;
+				&::before{
+					content: '';
+					width: 6rpx;
+					height: 32rpx;
+					background: #2E69EB;
+					position: absolute;
+					left: 0;
+					top: 50%;
+					margin-top: -16rpx;
+				}
+				.b_status{
+					width: 104rpx;
+					height: 48rpx;
+					border-radius: 6rpx;
+					font-family: PingFangSC, PingFang SC;
+					font-weight: 400;
+					font-size: 26rpx;
+					line-height: 48rpx;
+					text-align: center;
+					position: absolute;
+					left: 168rpx;
+					top: 50%;
+					margin-top: -24rpx;
+					&.djj{
+						color: #FEA400;
+						background: rgba(254,164,0,0.08);
+					}
+					&.yjj{
+						color: #05C17F;
+						background: rgba(20,204,140,0.08);
+					}
+				}
+			}
+		
+			.bs_item{
+				display: flex;
+				align-items: center;
+				justify-content: space-between;
+				margin-top: 36rpx;
+				.left{
+					width: 180rpx;
+					font-family: PingFangSC, PingFang SC;
+					font-weight: 400;
+					font-size: 26rpx;
+					color: #86909C;
+					line-height: 26rpx;
+				}
+				.right{
+					width: calc(100% - 180rpx);
+					font-family: PingFangSC, PingFang SC;
+					font-weight: 400;
+					font-size: 26rpx;
+					color: #1D2129;
+					line-height: 26rpx;
+					text-align: right;
+				}
+			}
+			
+			.b_item{
+				display: flex;
+				align-items: center;
+				justify-content: space-between;
+				box-shadow: inset 0rpx -1rpx 0rpx 0rpx #ECEEF5;
+				padding: 24rpx 0;
+				.left{
+					font-family: PingFangSC, PingFang SC;
+					font-weight: 400;
+					font-size: 30rpx;
+					color: #1D2129;
+					line-height: 42rpx;
+				}
+				.right{
+					input{
+						font-family: PingFangSC, PingFang SC;
+						font-weight: 400;
+						font-size: 28rpx;
+						color: #4E5969;
+						line-height: 40rpx;
+						text-align: right;
+					}
+					&.select{
+						display: flex;
+						align-items: center;
+						text{
+							font-family: PingFangSC, PingFang SC;
+							font-weight: 400;
+							font-size: 28rpx;
+							color: #B9C0C8;
+							line-height: 40rpx;
+						}
+						image{
+							width: 24rpx;
+							height: 24rpx;
+							margin-left: 10rpx;
+						}
+					}
+				}
+			}
+			.b_item2{
+				.top{
+					font-family: PingFangSC, PingFang SC;
+					font-weight: 400;
+					font-size: 30rpx;
+					color: #1D2129;
+					line-height: 42rpx;
+					padding-top: 24rpx;
+				}
+				.bottom{
+					padding-bottom: 24rpx;
+					input{
+						font-family: PingFangSC, PingFang SC;
+						font-weight: 400;
+						font-size: 28rpx;
+						color: #4E5969;
+						line-height: 40rpx;
+					}
+				}
+			}
+		}
+		
+		.bottom_btn{
+			width: 100%;
+			height: 148rpx;
+			padding: 20rpx 48rpx;
+			box-sizing: border-box;
+			background: #FFFFFF;
+			position: fixed;
+			bottom: 0;
+			left: 0;
+			z-index: 9;
+			.btn{
+				width: 100%;
+				height: 88rpx;
+				background: #2E69EB;
+				border-radius: 16rpx;
+				font-family: PingFang-SC, PingFang-SC;
+				font-weight: bold;
+				font-size: 32rpx;
+				color: #FFFFFF;
+				line-height: 88rpx;
+				text-align: center;
+			}
+		}
+	}
+</style>

+ 271 - 0
pagesOperation/workorder/index.vue

@@ -0,0 +1,271 @@
+<template>
+	<view class="page" :style="{'min-height':h+'px', 'padding-top':mt+'px'}">
+		<cus-header title='故障工单'></cus-header>
+		<div class="status">
+			<div class="pre" :class="{'active':sidx===0}" @tap="changeStatus('',0)">全部</div>
+			<div class="pre" :class="{'active':sidx===1}" @tap="changeStatus(1,1)">待解决</div>
+			<div class="pre" :class="{'active':sidx===2}" @tap="changeStatus(0,2)">已解决</div>
+		</div>
+		<div class="query">
+			<div class="pre" @tap="selectQuery(1)">
+				<span>{{typeText}}</span>
+				<u-icon name="arrow-down-fill" color="#C0C4CC" size="20rpx"></u-icon>
+			</div>
+			<div class="pre" @tap="selectQuery(2)">
+				<span>{{timeText}}</span>
+				<u-icon name="arrow-down-fill" color="#C0C4CC" size="20rpx"></u-icon>
+			</div>
+			<div class="pre" @tap="selectQuery(3)">
+				<span>{{placeText}}</span>
+				<u-icon name="arrow-down-fill" color="#C0C4CC" size="20rpx"></u-icon>
+			</div>
+		</div>
+		<div class="boxs" v-if="list.length">
+			<div class="item" v-for="(item,index) in [1,2]" :key="index">
+				<div class="left">
+					<div class="name">长鑫科技集团股份有限公司</div>
+					<p>故障类型<span>{{'类型1'}}</span></p>
+					<p>故障描述<span>{{'巡检任务'}}</span></p>
+					<p>故障时间<span>{{'2025-03-28 13:00'}}</span></p>
+				</div>
+				<div class="right">
+					<div class="top" :class="{'djj':index===0,'yjj':index===1}">{{index===0?'待解决':'已解决'}}</div>
+					<div class="bottom" @tap="toDetail(item)">查看</div>
+				</div>
+			</div>
+		</div>
+		<template v-else>
+			<page-empty :height="'calc(100vh - 140px)'"></page-empty>
+		</template>
+		<u-picker :itemHeight="88" :show="show1" :columns="columns1" keyName="label" title="故障类型"
+			@cancel="show1=false" @confirm="e=>confirm(e,1)" :immediateChange="true"></u-picker>
+		<u-datetime-picker :itemHeight="88" :show="show2" v-model="queryParams.month" mode="year-month" title="巡检时间"
+			@cancel="show2=false" @confirm="e=>confirm(e,2)" :immediateChange="true" :minDate="minDate" :maxDate="maxDate"></u-datetime-picker>
+		<u-picker :itemHeight="88" :show="show3" :columns="columns3" keyName="label" title="巡检地点"
+			@cancel="show3=false" @confirm="e=>confirm(e,3)" :immediateChange="true"></u-picker>
+	</view>
+</template>
+
+<script>
+	import pageEmpty from '@/components/pageEmpty/index.vue'
+	export default {
+		components:{
+			pageEmpty
+		},
+		data(){
+			return {
+				sidx:0,
+				typeText:'故障类型',
+				timeText:'巡检时间',
+				placeText:'巡检地点',
+				queryParams:{
+					type:'',
+					month:'',
+					place:'',
+					status:''
+				},
+				show1:false,
+				show2:false,
+				show3:false,
+				columns1:[[
+					{value:0,label:'类型1'},
+					{value:1,label:'类型2'}
+				]],
+				columns3:[[
+					{value:1,label:'长鑫科技集团股份有限公司'},
+					{value:2,label:'峻凌电子(合肥)有限公司'}
+				]],
+				minDate:'',
+				maxDate:'',
+				page:1,
+				limit:10,
+				isOver:false,
+				list:[]
+			}
+		},
+		onReachBottom() {
+			if(this.isOver) return
+			this.getList();
+		},
+		onLoad() {
+			let d = new Date();
+			this.minDate = new Date(d.getFullYear()-3,d.getMonth()+1,d.getDate()).getTime();
+			this.maxDate = new Date().getTime();
+			this.getList();
+		},
+		methods:{
+			changeStatus(status,idx){
+				this.queryParams.status = status;
+				this.sidx = idx;
+				this.getList();
+			},
+			getList(){
+				this.list = [1,2]
+			},
+			selectQuery(type){
+				if(type==1) this.show1 = true;
+				else if(type==2) this.show2 = true;
+				else if(type==3) this.show3 = true;
+			},
+			toDetail(item){
+				uni.navigateTo({
+					url:'/pagesOperation/workorder/detail?id='+item?.id
+				})
+			},
+			confirm(e,type){
+				if(type==1){
+					this.typeText = e.value[0].label;
+					this.queryParams.type = e.value[0].value;
+					this.show1 = false;
+				}else if(type==2){
+					this.timeText = new Date(e.value).Format('yyyy-MM');
+					this.queryParams.month = new Date(e.value).Format('yyyy-MM');
+					this.show2 = false;
+				}else if(type==3){
+					this.placeText = e.value[0].label;
+					this.queryParams.place = e.value[0].value;
+					this.show3 = false;
+				}
+			}
+		}
+	}
+</script>
+
+<style scoped lang="less">
+	.page{
+		padding-bottom: 40rpx;
+		background: #F4F8FB;
+		
+		.status{
+			width: 100%;
+			height: 90rpx;
+			background: #FFFFFF;
+			box-shadow: inset 0rpx -1rpx 0rpx 0rpx #ECEEF5;
+			display: flex;
+			.pre{
+				width: calc(100% / 3);
+				height: 90rpx;
+				font-family: PingFang-SC, PingFang-SC;
+				font-weight: bold;
+				font-size: 30rpx;
+				color: #1D2129;
+				line-height: 90rpx;
+				text-align: center;
+				position: relative;
+				&.active{
+					font-weight: bold;
+					font-size: 32rpx;
+					color: #2E69EB;
+					&::after{
+						content: '';
+						width: 59rpx;
+						height: 5rpx;
+						background: #2E69EB;
+						position: absolute;
+						bottom: 0;
+						left: 50%;
+						margin-left: -30rpx;
+					}
+				}
+			}
+		}
+		
+		.query{
+			width: 100%;
+			height: 88rpx;
+			background: #FFFFFF;
+			display: flex;
+			.pre{
+				width: calc(100% / 3);
+				height: 88rpx;
+				display: flex;
+				align-items: center;
+				justify-content: center;
+				span{
+					font-family: PingFangSC, PingFang SC;
+					font-weight: 400;
+					font-size: 26rpx;
+					color: #86909C;
+					line-height: 26rpx;
+					margin-right: 12rpx;
+				}
+			}
+		}
+	
+		.boxs{
+			padding: 0 24rpx;
+			margin-top: 20rpx;
+			.item{
+				background: #FFFFFF;
+				box-shadow: inset 0rpx -1rpx 0rpx 0rpx #ECEEF5;
+				padding: 36rpx 27rpx;
+				display: flex;
+				.left{
+					width: calc(100% - 115rpx);
+					padding-right: 20rpx;
+					box-sizing: border-box;
+					.name{
+						font-family: PingFang-SC, PingFang-SC;
+						font-weight: bold;
+						font-size: 30rpx;
+						color: #1D2129;
+						line-height: 42rpx;
+						text-align: left;
+						white-space: nowrap;
+						overflow: hidden;
+						text-overflow: ellipsis;
+					}
+					p{
+						margin-top: 36rpx;
+						font-family: PingFangSC, PingFang SC;
+						font-weight: 400;
+						font-size: 26rpx;
+						color: #86909C;
+						line-height: 26rpx;
+						span{
+							color: #1D2129;
+							margin-left: 64rpx;
+						}
+					}
+				}
+				.right{
+					width: 115rpx;
+					display: flex;
+					flex-direction: column;
+					justify-content: space-between;
+					.top{
+						width: 104rpx;
+						height: 48rpx;
+						border-radius: 6rpx;
+						font-family: PingFangSC, PingFang SC;
+						font-weight: 400;
+						font-size: 26rpx;
+						line-height: 48rpx;
+						text-align: center;
+						&.djj{
+							color: #FEA400;
+							background: rgba(254,164,0,0.08);
+						}
+						&.yjj{
+							color: #05C17F;
+							background: rgba(20,204,140,0.08);
+						}
+					}
+					.bottom{
+						width: 115rpx;
+						height: 64rpx;
+						background: #2E69EB;
+						border-radius: 16rpx;
+						font-family: PingFang-SC, PingFang-SC;
+						font-weight: bold;
+						font-size: 28rpx;
+						color: #FFFFFF;
+						line-height: 64rpx;
+						text-align: center;
+					}
+				}
+			}
+		}
+			
+	}
+</style>

+ 107 - 0
pagesSetting/index.vue

@@ -0,0 +1,107 @@
+<template>
+	<view class="tabPage" :style="{'min-height':h+'px', 'padding-top':mt+'px'}">
+		<cus-header title='设置' :showback="false"></cus-header>
+		<div class="card">
+			<div class="item">
+				<div class="left">上班打卡提醒</div>
+				<div class="right">
+					<u-switch v-model="sbRemind" size="48" activeColor="#2E69EB" inactiveColor="#B9C0C8"></u-switch>
+				</div>
+			</div>
+			<div class="item">
+				<div class="left">提醒时间</div>
+				<div class="right" @tap="sbShow=true">
+					<span>上班前{{sbqMinutes}}分钟</span>
+					<u-icon name="arrow-right" color="#606266" size="28"></u-icon>
+				</div>
+			</div>
+		</div>
+		<div class="card">
+			<div class="item">
+				<div class="left">下班打卡提醒</div>
+				<div class="right">
+					<u-switch v-model="xbRemind" size="48" activeColor="#2E69EB" inactiveColor="#B9C0C8"></u-switch>
+				</div>
+			</div>
+			<div class="item">
+				<div class="left">提醒时间</div>
+				<div class="right" @tap="xbShow=true">
+					<span>下班后{{xbhMinutes}}分钟</span>
+					<u-icon name="arrow-right" color="#606266" size="28"></u-icon>
+				</div>
+			</div>
+		</div>
+		<u-picker :itemHeight="88" :immediateChange="true" :show="sbShow" :columns="[[5,10,15,20,25,30]]" @confirm="sbConfirm" @close="sbShow=false"></u-picker>
+		<u-picker :itemHeight="88" :immediateChange="true" :show="xbShow" :columns="[[5,10,15,20,25,30]]" @confirm="xbConfirm" @close="xbShow=false"></u-picker>
+		<Tabbar :tabbarIndex="2"></Tabbar>
+	</view>
+</template>
+
+<script>
+	import Tabbar from '@/components/CusTabbar/clock.vue'
+	export default {
+		components:{ Tabbar },
+		data(){
+			return {
+				sbRemind:false,
+				xbRemind:false,
+				sbShow:false,
+				xbShow:false,
+				sbqMinutes:5,
+				xbhMinutes:5
+			}
+		},
+		methods:{
+			sbConfirm(e){
+				this.sbqMinutes = e.value[0];
+				this.sbShow = false;
+			},
+			xbConfirm(e){
+				this.xbhMinutes = e.value[0];
+				this.xbShow = false;
+			}
+		}
+	}
+</script>
+
+<style scoped lang="less">
+	.tabPage{
+		padding: 0 24rpx 188rpx;
+		background: #F4F8FB;
+		
+		.card{
+			background: #FFFFFF;
+			border-radius: 16rpx;
+			margin-top: 20rpx;
+			padding: 0 24rpx;
+			.item{
+				height: 120rpx;
+				display: flex;
+				align-items: center;
+				justify-content: space-between;
+				&:last-child{
+					border-top: 1rpx solid #EFEFEF;
+				}
+				.left{
+					font-family: PingFangSC, PingFang SC;
+					font-weight: 400;
+					font-size: 32rpx;
+					color: #1D2129;
+					line-height: 45rpx;
+				}
+				.right{
+					display: flex;
+					align-items: center;
+					span{
+						font-family: PingFangSC, PingFang SC;
+						font-weight: 400;
+						font-size: 26rpx;
+						color: #86909C;
+						line-height: 37rpx;
+						margin-right: 10rpx;
+					}
+				}
+			}
+		}
+	}
+</style>

+ 214 - 0
pagesStatistics/index.vue

@@ -0,0 +1,214 @@
+<template>
+	<view class="tabPage" :style="{'min-height':h+'px', 'padding-top':mt+'px'}">
+		<cus-header title='统计' :showback="false"></cus-header>
+		<div class="card">
+			<div class="c_top">
+				<div class="ct_left" @tap="show=true">{{currentDay}}</div>
+				<div class="ct_right">统计截至{{currentTime}}</div>
+			</div>
+			<div class="c_nums">
+				<div class="cn_pre">
+					<p>{{16}}</p>
+					<p class="text">出勤天数</p>
+				</div>
+				<div class="cn_pre">
+					<p>{{416}}</p>
+					<p class="text">总工时</p>
+				</div>
+				<div class="cn_pre">
+					<p>{{46}}</p>
+					<p class="text">餐补次数</p>
+				</div>
+			</div>
+			<div class="c_calendar">
+				<Calendar ref="calendarRef" @selectDay="selectDay"></Calendar>
+			</div>
+			<div class="c_tip">当日班次:{{'固定上下班'}} 班次 {{'08:30-17:30'}}</div>
+			<div class="c_tip">出勤统计:打卡{{2}}次,工时{{10}}小时</div>
+			<div class="c_time">
+				<image :src="imgBase+'clockingin/time_line.png'"></image>
+				<div class="ct_info">
+					<div class="cti_pre">
+						<div class="ctip_left">上班 {{'08:19'}}</div>
+						<div class="ctip_right">
+							<image :src="imgBase+'clockingin/location_inactive.png'"></image>
+							<span>{{'谷锐特设备自动化有限公司'}}</span>
+						</div>
+					</div>
+					<div class="cti_pre">
+						<div class="ctip_left">下班 {{'20:30'}}</div>
+						<div class="ctip_right">
+							<image :src="imgBase+'clockingin/location_inactive.png'"></image>
+							<span>{{'谷锐特设备自动化有限公司'}}</span>
+						</div>
+					</div>
+				</div>
+			</div>
+		</div>
+		<u-datetime-picker :itemHeight="88" :show="show" v-model="yearMonth" mode="year-month" @confirm="confirm" @cancel="show=false" :immediateChange="true" :minDate="minDate" :maxDate="maxDate"></u-datetime-picker>
+		<Tabbar :tabbarIndex="1"></Tabbar>
+	</view>
+</template>
+
+<script>
+	import Calendar from '@/components/CusCalendar/index.vue'
+	import Tabbar from '@/components/CusTabbar/clock.vue'
+	export default {
+		components:{ Calendar,Tabbar },
+		data(){
+			return {
+				currentDay:'',
+				currentTime:'',
+				show:false,
+				yearMonth:new Date().Format('yyyy-MM'),
+				minDate:'',
+				maxDate:'',
+			}
+		},
+		onLoad() {
+			this.currentDay = new Date().Format('yyyy MM.dd');
+			this.currentTime = new Date().Format('yyyy-MM-dd hh:mm');
+		},
+		mounted() {
+			let d = new Date();
+			this.minDate = new Date(d.getFullYear()-1,d.getMonth()+1,d.getDate()).getTime();
+			this.maxDate = new Date().getTime();	
+		},
+		methods:{
+			selectDay(obj){
+				this.currentDay = new Date(obj.year,obj.month-1,1).Format('yyyy MM.dd');
+			},
+			confirm(e){
+				this.currentDay = new Date(e.value).Format('yyyy MM.dd');
+				let year = new Date(e.value).Format('yyyy');
+				let month = Number(new Date(e.value).Format('MM'));
+				this.$refs.calendarRef.year = year;
+				this.$refs.calendarRef.month = month;
+				this.$refs.calendarRef.getDataByMonth(year,month);
+				this.show = false;
+			},
+		}
+	}
+</script>
+
+<style scoped lang="less">
+	.tabPage{
+		padding: 0 24rpx 188rpx;
+		background: #F4F8FB;
+		
+		.card{
+			background: #FFFFFF;
+			border-radius: 16rpx;
+			padding: 40rpx 30rpx;
+			margin-top: 20rpx;
+			
+			.c_top{
+				display: flex;
+				align-items: center;
+				justify-content: space-between;
+				.ct_left{
+					font-family: PingFang-SC, PingFang-SC;
+					font-weight: bold;
+					font-size: 32rpx;
+					color: #1D2129;
+					line-height: 45rpx;
+				}
+				.ct_right{
+					font-family: PingFangSC, PingFang SC;
+					font-weight: 400;
+					font-size: 24rpx;
+					color: #86909C;
+					line-height: 33rpx;
+					text-align: right;
+				}
+			}
+			
+			.c_nums{
+				display: flex;
+				margin-top: 54rpx;
+				.cn_pre{
+					width: calc(100% / 3);
+					display: flex;
+					flex-direction: column;
+					align-items: center;
+					p{
+						font-family: PingFang-SC, PingFang-SC;
+						font-weight: bold;
+						font-size: 36rpx;
+						color: #1D2129;
+						line-height: 36rpx;
+						text-align: center;
+						&.text{
+							font-weight: 400;
+							font-size: 24rpx;
+							color: #86909C;
+							line-height: 24rpx;
+							margin-top: 16rpx;
+						}
+					}
+				}
+			}
+		
+			.c_calendar{
+				border-top: 1rpx solid #EFEFEF;
+				border-bottom: 1rpx solid #EFEFEF;
+				margin-top: 36rpx;
+				padding: 20rpx 0;
+			}
+			
+			.c_tip{
+				font-family: PingFangSC, PingFang SC;
+				font-weight: 400;
+				font-size: 24rpx;
+				color: #86909C;
+				line-height: 24rpx;
+				text-align: left;
+				margin-top: 24rpx;
+			}
+			
+			.c_time{
+				margin-top: 40rpx;
+				display: flex;
+				align-items: center;
+				&>image{
+					width: 10rpx;
+					height: 82rpx;
+				}
+				.ct_info{
+					margin-left: 10rpx;
+					.cti_pre{
+						display: flex;
+						align-items: center;
+						&:last-child{
+							margin-top: 48rpx;
+						}
+						.ctip_left{
+							font-family: PingFang-SC, PingFang-SC;
+							font-weight: bold;
+							font-size: 24rpx;
+							color: #1D2129;
+							line-height: 24rpx;
+						}
+						.ctip_right{
+							display: flex;
+							align-items: center;
+							margin-left: 20rpx;
+							image{
+								width: 24rpx;
+								height: 24rpx;
+							}
+							span{
+								font-family: PingFangSC, PingFang SC;
+								font-weight: 400;
+								font-size: 24rpx;
+								color: #86909C;
+								line-height: 24rpx;
+								margin-left: 8rpx;
+							}
+						}
+					}
+				}
+			}
+		}
+	}
+</style>

+ 1 - 1
pagesStorage/home.vue

@@ -45,7 +45,7 @@
 				<l-echart ref="cktjChartRef" :canvas2d="true" @finished="initCktj"></l-echart>
 			</div>
 		</div>
-		<Tabbar :tabbarIndex="2"></Tabbar>
+		<Tabbar :tabbarIndex="0"></Tabbar>
 	</div>
 </template>
 

File diff suppressed because it is too large
+ 1122 - 0
static/lib/qqmap-wx-jssdk.js


File diff suppressed because it is too large
+ 1 - 0
static/lib/qqmap-wx-jssdk.min.js