Selaa lähdekoodia

feat: 优化运输工单

liujt 2 kuukautta sitten
vanhempi
commit
5590bddb1e

+ 101 - 76
pages/dispatchManage/taskWork/OrderTask.vue

@@ -1,49 +1,63 @@
 <template>
 	<view class="marginTop">
-		<view class="list-wrap" v-for="(item, index) in list" :key="index" v-show="list.length !== 0"
-			@click="goDetail(item)">
-			<view class="item">
-				<view class="s1">
-					<text class="title">{{ item.code }}</text>
-				</view>
-				<!-- <view class="s2">
-					{{ item.createTime }}
-				</view> -->
-			</view>
-			<view class="item">
-				<view class="s1">任务类型:{{getDict('logistic_delivery_type',item.taskType ) }}</view>
-			</view>
-			<view class="item">
-				<view class="s1">任务名称:{{ item.taskCode }}</view>
-			</view>
-			
-			<div v-if="type==2">
-				<view class="item">
-					<view class="s1">开始时间:{{ item.realStartTime}}</view>
-				</view>
-				<view class="item">
-					<view class="s1">完成时间:{{ item.realEndTime }}</view>
-				</view>
-			</div>
-			<div v-else>
-				<view class="item">
-					<view class="s1">应开工时间:{{ item.planTimeStart}}</view>
-				</view>
-				<view class="item">
-					<view class="s1">应完成时间:{{ item.planTimeEnd }}</view>
-				</view>
-			</div>
-			<view class="item">
-				<view class="s1">
-					<view class="state">
-						{{ dict.status[item.status] }}
+		<u-list>
+			<u-list-item v-for="(item, index) in list" :key="index" v-show="list.length !== 0">
+				<view class="card_box" @click="goDetail(item)">
+					<view class="item_box flex_between">
+						<view class="rx-sc">
+							<view class="round">{{ Number(index) + 1 }}</view>
+							<view class="orderId">{{ item.code }}</view>
+						</view>
+						<view class="state">{{ dict.status[item.status] }}</view>
+					</view>
+					<view class="item_box rx-bc">
+						<view class="item_one perce50 rx-sc">
+							<view class="lable">任务类型:</view>
+							<view>{{ getDict('logistic_delivery_type', item.taskType) }}</view>
+						</view>
 					</view>
+					<view class="item_box rx-bc">
+						<view class="item_one perce50 rx-sc">
+							<view class="lable">任务名称:</view>
+							<view>{{ item.taskCode }}</view>
+						</view>
+					</view>
+					<div v-if="type == 2">
+						<view class="item_box rx-bc">
+							<view class="item_one perce50 rx-sc">
+								<view class="lable">开始时间:</view>
+								<view>{{ item.realStartTime }}</view>
+							</view>
+						</view>
+						<view class="item_box rx-bc">
+							<view class="item_one perce50 rx-sc">
+								<view class="lable">完成时间:</view>
+								<view>{{ item.realEndTime }}</view>
+							</view>
+						</view>
+					</div>
+					<div v-else>
+						<view class="item_box rx-bc">
+							<view class="item_one perce50 rx-sc">
+								<view class="lable">应开工时间:</view>
+								<view>{{ item.planTimeStart }}</view>
+							</view>
+						</view>
+						<view class="item_box rx-bc">
+							<view class="item_one perce50 rx-sc">
+								<view class="lable">应完成时间:</view>
+								<view>{{ item.planTimeEnd }}</view>
+							</view>
+						</view>
+					</div>
+				</view>
+			</u-list-item>
+			<u-list-item v-if="list.length === 0">
+				<view style='margin-top: 20vh;'>
+					<u-empty iconSize='150' textSize='32' text='暂无数据'></u-empty>
 				</view>
-			</view>
-		</view>
-		<view v-show="list.length === 0" class="no_data">
-			<u-empty mode="data"></u-empty>
-		</view>
+			</u-list-item>
+		</u-list>
 	</view>
 </template>
 
@@ -120,49 +134,60 @@
 		border-top: 20rpx solid $page-bg;
 	}
 
-	.center {
-		text-align: center;
-		margin-bottom: 10rpx;
-		color: #999;
-	}
-
-	.no_data {
-		position: fixed;
-		top: 50%;
-		left: 50%;
-		transform: translate(-50%, -50%);
-		color: #999;
-		font-size: 28rpx;
-	}
+	.card_box {
+		width: 750rpx;
+		padding: 16rpx 32rpx;
+		box-sizing: border-box;
+		border-bottom: 2rpx solid #E1E1E1;
 
-	.list-wrap {
-		padding: 10rpx;
+		.item_box {
+			margin-top: 10rpx;
 
-		.item {
-			display: flex;
-			justify-content: space-between;
-			padding: 10rpx;
-			color: rgb(170, 170, 170);
-			font-size: 28rpx;
-			word-break: break-all;
+			.round {
+				width: 40rpx;
+				height: 40rpx;
+				line-height: 40rpx;
+				border-radius: 50%;
+				background: $theme-color;
+				color: #fff;
+				text-align: center;
+				font-size: 20rpx;
+			}
 
-			.title {
-				color: #333333;
+			.orderId {
+				color: #000;
+				font-family: PingFang HK;
 				font-size: 28rpx;
+				font-style: normal;
+				font-weight: 600;
+				margin-left: 16rpx;
+			}
+
+			.item_one {
+				width: 100%;
+				font-size: 26rpx;
+				font-style: normal;
+				font-weight: 400;
+				line-height: 38rpx;
+				word-wrap: break-word;
 			}
 
-			.state {
-				font-size: 12px;
-				color: #7f7f7f;
-				background: #f1f1f1;
-				display: inline;
-				padding: 2px 5px;
-				border-radius: 10px;
+			.perce50 {
+				width: 100%;
 			}
 		}
 
-		&+.list-wrap {
-			border-top: 1px solid rgba(242, 242, 242, 1);
+		.flex_between {
+			display: flex;
+			justify-content: space-between;
 		}
 	}
+
+	.state {
+		font-size: 28rpx;
+		background-color: $page-bg;
+		display: inline-block;
+		padding: 2px 5px;
+		border-radius: 18rpx;
+	}
 </style>

+ 4 - 4
pages/dispatchManage/taskWork/index.vue

@@ -94,7 +94,7 @@
 					status: 0,
 					pageNum: 1,
 					size: 1,
-					userId: this.userInfo.userId
+					// userId: this.userInfo.userId
 				}).then(res => {
 					this.tabList[0].number = res.count
 				})
@@ -102,7 +102,7 @@
 					status: 1,
 					pageNum: 1,
 					size: 1,
-					userId: this.userInfo.userId
+					// userId: this.userInfo.userId
 				}).then(res => {
 					this.tabList[1].number = res.count
 				})
@@ -110,7 +110,7 @@
 					status: 2,
 					pageNum: 1,
 					size: 1,
-					userId: this.userInfo.userId
+					// userId: this.userInfo.userId
 				}).then(res => {
 					this.tabList[2].number = res.count
 				})
@@ -134,7 +134,7 @@
 					status: [this.tabList[this.pickTabIndex].value],
 					pageNum: page,
 					size,
-					userId: this.userInfo.userId
+					// userId: this.userInfo.userId
 				}
 				logistictraklistnotePageListAPI(params)
 					.then(res => {

+ 486 - 66
pages/dispatchManage/taskWork/reportDetail.vue

@@ -3,57 +3,98 @@
 		<uni-nav-bar fixed="true" statusBar="true" left-icon="back" title="报工信息" @clickLeft="back"></uni-nav-bar>
 		<view class="maintenance-wrapper">
 			<view class="maintenance-content">
-
-				<view :scroll-y='true' class="kd-baseInfo">
+				<scroll-view :scroll-y='true' class="kd-baseInfo">
+					<view class="kd-cell">
+						<text class="kd-label">开始里程</text>
+						<uni-easyinput v-model="formData.startMileage" type="number" :clearable="false" :inputBorder="false" @blur="validateStartMileage">
+							<template #right>
+								<view>KM</view>
+							</template>
+						</uni-easyinput>
+					</view>
+					<view class="kd-cell">
+						<text class="kd-label">结束里程</text>
+						<uni-easyinput v-model="formData.endMileage" type="number" :clearable="false" :inputBorder="false" @blur="validateEndMileage">
+							<template #right>
+								<view>KM</view>
+							</template>
+						</uni-easyinput>
+					</view>
 					<view class="kd-cell">
-						<text class="kd-label">里程</text>
-						<uni-easyinput v-model="formData.mileage" :clearable='false' :inputBorder='false'>
+						<text class="kd-label">里程</text>
+						<uni-easyinput v-model="formData.mileage" type="number" :clearable="false" :inputBorder="false" :disabled="true">
 							<template #right>
 								<view>KM</view>
 							</template>
 						</uni-easyinput>
 					</view>
-					<template v-for="(item,index) in formData.costList">
-						<view style="margin-top: 20px;">
+					<view class="kd-cell" style="display: block;">
+						<text class="kd-label">开始里程图片</text>
+						<view class="image-list">
+							<view class="image-item" v-for="(img, index) in (formData.startMileageImages || [])" :key="index">
+								<image :src="getImageUrl(img)" mode="aspectFill" @click="previewImage(formData.startMileageImages, index)"></image>
+								<view class="delete-btn" v-if="formData.status == 1" @click="deleteImage('start', index)">×</view>
+							</view>
+							<view class="image-add" v-if="formData.status == 1 && (!formData.startMileageImages || formData.startMileageImages.length < 9)" @click="chooseImage('start')">
+								<text>+</text>
+							</view>
+						</view>
+					</view>
+					<view class="kd-cell" style="display: block;">
+						<text class="kd-label">结束里程图片</text>
+						<view class="image-list">
+							<view class="image-item" v-for="(img, index) in (formData.endMileageImages || [])" :key="index">
+								<image :src="getImageUrl(img)" mode="aspectFill" @click="previewImage(formData.endMileageImages, index)"></image>
+								<view class="delete-btn" v-if="formData.status == 1" @click="deleteImage('end', index)">×</view>
+							</view>
+							<view class="image-add" v-if="formData.status == 1 && (!formData.endMileageImages || formData.endMileageImages.length < 9)" @click="chooseImage('end')">
+								<text>+</text>
+							</view>
+						</view>
+					</view>
+
+					<template v-if="formData.costList && formData.costList.length > 0">
+						<view class="kd-cell-divider"></view>
+						<view class="kd-cell">
+							<text class="kd-label">费用信息</text>
+							<text class="kd-content"></text>
+						</view>
+						<view v-for="(item, index) in formData.costList" :key="index">
 							<view class="kd-cell">
 								<text class="kd-label">费用类型</text>
-								<text class="kd-content">{{ getDict('logistic_list_cost_type',item.costType )}}</text>
-
+								<text class="kd-content">{{ getDict('logistic_list_cost_type', item.costType) }}</text>
 							</view>
 							<view class="kd-cell">
 								<text class="kd-label">金额</text>
-								<text class="kd-content">{{item.cost}}</text>
-
+								<text class="kd-content">{{ item.cost }}</text>
 							</view>
 							<view class="kd-cell">
 								<text class="kd-label">备注</text>
-								<text class="kd-content">{{item.remark}}</text>
+								<text class="kd-content">{{ item.remark }}</text>
 							</view>
-
-							<view style="float: right;" v-if='formData.status==1'>
-								<button class="btn-reassignment del" type="primary"
-									@click="handleDelFee(index)">删除</button>
+							<view v-if="formData.status == 1" style="float: right;">
+								<button class="btn-reassignment del" type="primary" @click="handleDelFee(index)">删除</button>
 							</view>
 						</view>
-
 					</template>
+					<template v-else>
+						<view class="kd-cell">
+							<text class="kd-label">费用信息</text>
+							<text class="kd-content" style="color: #999;">暂无费用信息</text>
+						</view>
+					</template>
+				</scroll-view>
 
-
-				</view>
-				<template v-if='formData.status==1'>
+				<template v-if="formData.status == 1">
 					<button class="btn-execute" type="primary" @click="handleExecute(2)">保存</button>
-					<button class="btn-reassignment " type="primary" @click="handleAddFee">新增费用</button>
-
+					<button class="btn-reassignment" type="primary" @click="handleAddFee">新增费用</button>
 				</template>
 				<template v-else>
 					<button class="btn-execute" type="primary" @click="back(1)">返回</button>
 				</template>
-
 			</view>
 		</view>
 
-
-
 		<u-popup :show="popShow" @close="close">
 			<view class="select-container">
 				<view class="title">
@@ -64,8 +105,7 @@
 				<view class="select-wrapper">
 					<view class="col deptInp">
 						<text class="label">费用类型:</text>
-						<zxz-uni-data-select :localdata="costTypeList" v-model="form.costType"
-							filterable></zxz-uni-data-select>
+						<zxz-uni-data-select :localdata="costTypeList" v-model="form.costType" filterable></zxz-uni-data-select>
 					</view>
 
 					<view class="col userInp">
@@ -75,7 +115,6 @@
 					<view class="col userInp">
 						<text class="label">备注:</text>
 						<uni-easyinput v-model="form.remark" type='textarea'></uni-easyinput>
-
 					</view>
 				</view>
 			</view>
@@ -98,11 +137,33 @@
 				info: {},
 				formData: {
 					costList: []
-				}
+				},
+				isSubmitting: false // 防重复提交标志
 			}
 		},
 		onLoad(options) {
-			this.formData = JSON.parse(options.item)
+			console.log('options~~~', options)
+			let initData = JSON.parse(options.item)
+			
+			// 处理开始里程图片(使用路径生成URL,同步ID)
+			initData.startMileageImages = initData.startMileageImagesPaths
+				? initData.startMileageImagesPaths.split(',').map((path, index) => ({
+					id: initData.startMileageImagesFileIds.split(',')[index] || '', // 对应ID
+					url: `${window.location.origin}/api/main/file/getFile?objectName=${path}`, // 使用路径作为参数
+					status: 'done'
+				}))
+				: [];
+
+			// 处理结束里程图片(同上)
+			initData.endMileageImages = initData.endMileageImagesPaths
+				? initData.endMileageImagesPaths.split(',').map((path, index) => ({
+					id: initData.endMileageImagesFileIds.split(',')[index] || '',
+					url: `${window.location.origin}/api/main/file/getFile?objectName=${path}`,
+					status: 'done'
+				}))
+				: [];
+			this.formData = initData
+			console.log('initData~~~', initData)
 			this.costTypeList = this.formData.dictList['logistic_list_cost_type'].map(item => {
 				let values = Object.keys(item)
 				return {
@@ -117,6 +178,15 @@
 					let find = this.formData.dictList[dictName].find(item => item[val]) || {}
 					return find[val] ? find[val] : ''
 				}
+			},
+			// 获取图片URL
+			getImageUrl() {
+				return (img) => {
+					if (typeof img === 'string') {
+						return img
+					}
+					return img.url
+				}
 			}
 		},
 		methods: {
@@ -125,32 +195,298 @@
 					delta: num
 				})
 			},
-			async handleExecute(status) {
-				if (!this.formData.mileage) {
+			// 验证开始里程
+			validateStartMileage() {
+				const start = parseFloat(this.formData.startMileage)
+				const end = parseFloat(this.formData.endMileage)
+				if (start !== 0 && !start) {
 					uni.showToast({
-						icon: 'error',
-						title: '请输入里程'
+						icon: 'none',
+						title: '请输入开始里程'
+					})
+					return
+				}
+				if (start && end && start >= end) {
+					uni.showToast({
+						icon: 'none',
+						title: '开始里程必须小于结束里程'
+					})
+					this.formData.startMileage = ''
+					this.formData.mileage = ''
+				} else if (start !== '' && end !== '') {
+					this.calcTotalMileage()
+				}
+			},
+			// 验证结束里程
+			validateEndMileage() {
+				const start = parseFloat(this.formData.startMileage)
+				const end = parseFloat(this.formData.endMileage)
+				if (!end) {
+					uni.showToast({
+						icon: 'none',
+						title: '请输入结束里程'
+					})
+					return
+				}
+				if (start && end && end <= start) {
+					uni.showToast({
+						icon: 'none',
+						title: '结束里程必须大于开始里程'
+					})
+					this.formData.endMileage = ''
+					this.formData.mileage = ''
+				} else if (start !== '' && end !== '') {
+					this.calcTotalMileage()
+				}
+			},
+			// 计算总里程
+			calcTotalMileage() {
+				const start = parseFloat(this.formData.startMileage) || 0
+				const end = parseFloat(this.formData.endMileage) || 0
+				this.formData.mileage = (end - start).toFixed(2)
+			},
+			// 选择图片
+			chooseImage(type) {
+				const maxCount = 9
+				const currentImages = type === 'start' ? (this.formData.startMileageImages || []) : (this.formData.endMileageImages || [])
+				const remainingCount = maxCount - currentImages.length
+
+				if (remainingCount <= 0) {
+					uni.showToast({
+						icon: 'none',
+						title: '最多上传9张图片'
 					})
 					return
 				}
-				await logistictraklistnoteUpdateAPI({...this.formData,status})
+
+				uni.chooseImage({
+					count: remainingCount,
+					sizeType: ['compressed'],
+					sourceType: ['camera', 'album'],
+					success: (res) => {
+						const tempFilePaths = res.tempFilePaths
+						this.uploadImages(tempFilePaths, type)
+					}
+				})
+			},
+			// 上传多张图片
+			async uploadImages(filePaths, type) {
+				uni.showLoading({
+					title: '上传中...'
+				})
+
+				const uploadPromises = filePaths.map(filePath => {
+					return new Promise((resolve, reject) => {
+						uni.uploadFile({
+							url: this.apiUrl + '/main/file/upload',
+							filePath: filePath,
+							name: 'multiPartFile',
+							header: {
+								authorization: uni.getStorageSync("token")
+							},
+							success: (res) => {
+								const data = JSON.parse(res.data)
+								console.log('data~~~', data)
+								if (data.code == 0) {
+									// 构建完整的图片URL
+									// const fileNames = data.data.storePath.split('/')
+									// const url = this.apiUrl +
+									// 	'/main/file/getFile?objectName=' + data.data.storePath +
+									// 	'&fullfilename=' + fileNames[fileNames.length - 1]
+									resolve(data.data)
+								} else {
+									reject(data.message || '上传失败')
+								}
+							},
+							fail: () => {
+								reject('上传失败')
+							}
+						})
+					})
+				})
+
+				try {
+					const results = await Promise.all(uploadPromises)
+					console.log('results~~~', results)
+					if (type === 'start') {
+						if (!this.formData.startMileageImages) {
+							this.formData.startMileageImages = []
+						}
+						this.formData.startMileageImages.push(...results)
+					} else {
+						if (!this.formData.endMileageImages) {
+							this.formData.endMileageImages = []
+						}
+						this.formData.endMileageImages.push(...results)
+					}
+					console.log('startMileageImages~~~', this.formData.startMileageImages)
+					// 强制更新视图
+					this.$forceUpdate()
+					uni.hideLoading()
+					uni.showToast({
+						title: '上传成功',
+						icon: 'success'
+					})
+				} catch (error) {
+					uni.hideLoading()
+					uni.showToast({
+						title: error || '上传失败',
+						icon: 'none'
+					})
+				}
+			},
+			// 删除图片
+			deleteImage(type, index) {
 				uni.showModal({
-					title: `此工单报工成功`,
-					content: '',
-					confirmText: '确认',
-					showCancel: false, // 是否显示取消按钮,默认为 true
+					title: '确认删除',
+					content: '确定要删除这张图片吗?',
+					confirmColor: '#157A2C',
 					success: res => {
 						if (res.confirm) {
-							this.back(2)
+							console.log('index~~~', index)
+							if (type === 'start') {
+								this.formData.startMileageImages.splice(index, 1)
+							} else {
+								this.formData.endMileageImages.splice(index, 1)
+							}
+							this.$forceUpdate();
+							console.log('startMileageImages~~~', this.formData.startMileageImages)
+							console.log('endMileageImages~~~', this.formData.endMileageImages)
 						}
 					}
 				})
 			},
+			// 预览图片
+			previewImage(images, index) {
+				// 处理图片数据,确保是字符串数组
+				const urls = images.map(img => {
+					if (typeof img === 'string') {
+						return img
+					} else if (img && img.url) {
+						return img.url
+					}
+					return ''
+				}).filter(url => url) // 过滤掉空字符串
+				uni.previewImage({
+					urls: urls,
+					current: index
+				})
+			},
+			async handleExecute(status) {
+				// 防重复提交检查
+				if (this.isSubmitting) {
+					return
+				}
+				this.isSubmitting = true
+
+				try {
+					// 验证开始里程(允许0,但不允许负数、空值或NaN)
+					if (this.formData.startMileage === '' || this.formData.startMileage === null || this.formData.startMileage === undefined || isNaN(this.formData.startMileage) || parseFloat(this.formData.startMileage) < 0) {
+						uni.showToast({
+							icon: 'none',
+							title: '请输入有效的开始里程'
+						})
+						return
+					}
+
+					// 验证结束里程(不允许为0、负数、空值或NaN)
+					if (!this.formData.endMileage || isNaN(this.formData.endMileage) || parseFloat(this.formData.endMileage) <= 0) {
+						uni.showToast({
+							icon: 'none',
+							title: '请输入有效的结束里程'
+						})
+						return
+					}
+
+					// 验证里程关系:结束里程必须大于开始里程
+					if (parseFloat(this.formData.endMileage) <= parseFloat(this.formData.startMileage)) {
+						uni.showToast({
+							icon: 'none',
+							title: '结束里程必须大于开始里程'
+						})
+						return
+					}
+
+					// 验证开始里程图片
+					if (!this.formData.startMileageImages || this.formData.startMileageImages.length === 0) {
+						uni.showToast({
+							icon: 'none',
+							title: '请上传开始里程图片'
+						})
+						return
+					}
+
+					// 验证结束里程图片
+					if (!this.formData.endMileageImages || this.formData.endMileageImages.length === 0) {
+						uni.showToast({
+							icon: 'none',
+							title: '请上传结束里程图片'
+						})
+						return
+					}
+
+					// 验证费用信息
+					if (!this.formData.costList || this.formData.costList.length === 0) {
+						uni.showToast({
+							icon: 'none',
+							title: '请添加费用信息'
+						})
+						return
+					}
+
+					// 显示加载状态
+					uni.showLoading({
+						title: '提交中...',
+						mask: true
+					})
+
+					const data = JSON.parse(JSON.stringify(this.formData))
+					data.endMileageImagesFileIds = data.endMileageImages.map(img => img.id).join(',')
+					data.startMileageImagesFileIds = data.startMileageImages.map(img => img.id).join(',')
+					console.log('data~~~', data)
+				
+					// 调用API
+					await logistictraklistnoteUpdateAPI({...data, status})
+
+					uni.hideLoading()
+					uni.showModal({
+						title: '此工单报工成功',
+						content: '',
+						confirmText: '确认',
+						showCancel: false,
+						success: res => {
+							if (res.confirm) {
+								this.back(2)
+							}
+						}
+					})
+				} catch (error) {
+					uni.hideLoading()
+					uni.showToast({
+						icon: 'none',
+						title: error.message || '提交失败,请重试',
+						duration: 3000
+					})
+					console.error('提交失败:', error)
+				} finally {
+					this.isSubmitting = false
+				}
+			},
 			handleAddFee() {
+				this.form = {}
 				this.popShow = true
 			},
 			handleDelFee(index) {
-				this.formData.costList.splice(index, 1)
+				uni.showModal({
+					title: '确认删除',
+					content: '确定要删除这条费用信息吗?',
+					confirmColor: '#157A2C',
+					success: res => {
+						if (res.confirm) {
+							this.formData.costList.splice(index, 1)
+						}
+					}
+				})
 			},
 			submit() {
 				if (!this.form.costType) {
@@ -174,7 +510,6 @@
 				this.form = {}
 				this.close()
 			},
-
 			close() {
 				this.popShow = false
 			},
@@ -249,7 +584,6 @@
 	.maintenance-content {
 		padding-top: 40rpx;
 		box-sizing: border-box;
-		// height: calc(100vh - 88rpx);
 		position: absolute;
 		top: 0;
 		bottom: 0;
@@ -260,28 +594,99 @@
 	}
 
 	.kd-cell {
-		line-height: 90rpx;
-		border-bottom: 1px dashed #dadada;
+			line-height: 90rpx;
+			border-bottom: 1px dashed #dadada;
+			display: flex;
+			justify-content: space-between;
+
+			.kd-label {
+				display: inline-block;
+				width: 7em;
+				font-weight: bold;
+			}
+
+			.kd-content {
+				flex: 1;
+				text-align: left;
+				word-break: break-all;
+			}
+
+			&.block {
+				display: block;
+			}
+		}
+
+	.kd-cell-divider {
+		border-bottom: 2px solid #dadada;
+		margin: 10px 0;
+	}
+
+	.upload-btn {
+		flex: 1;
+		text-align: center;
+		color: $theme-color;
+	}
+
+	.image-list {
 		display: flex;
-		justify-content: space-between;
+		flex-wrap: wrap;
+		padding: 10rpx 0;
+		margin-left: 7em;
 
-		.kd-label {
-			display: inline-block;
-			width: 7em;
-			font-weight: bold;
+		.image-item {
+			position: relative;
+			width: 150rpx;
+			height: 150rpx;
+			margin: 0 10rpx 10rpx 0;
+			box-sizing: border-box;
+
+			image {
+				width: 100%;
+				height: 100%;
+				border-radius: 8rpx;
+			}
+
+			.delete-btn {
+				position: absolute;
+				top: -10rpx;
+				right: -10rpx;
+				width: 40rpx;
+				height: 40rpx;
+				line-height: 40rpx;
+				text-align: center;
+				background-color: #ff4d4f;
+				color: #fff;
+				border-radius: 50%;
+				font-size: 32rpx;
+				cursor: pointer;
+				z-index: 10;
+			}
 		}
 
-		.kd-content {
-			flex: 1;
-			text-align: left;
-			word-break: break-all;
+		.image-add {
+			width: 150rpx;
+			height: 150rpx;
+			border: 2rpx dashed #d9d9d9;
+			border-radius: 8rpx;
+			display: flex;
+			align-items: center;
+			justify-content: center;
+			font-size: 60rpx;
+			color: #999;
+			margin: 0 10rpx 10rpx 0;
+			cursor: pointer;
+			box-sizing: border-box;
+
+			&:active {
+				background-color: #f5f5f5;
+			}
 		}
 	}
 
 	.kd-baseInfo {
 		padding: 0 32rpx;
 		font-size: 28rpx;
-		height: 70%;
+		height: 75%;
 	}
 
 	.kd-equipment {
@@ -409,21 +814,36 @@
 			position: relative;
 			font-size: 32rpx;
 			color: #fff;
+			padding: 0 30rpx;
+			box-sizing: border-box;
 
-			// .btn-box {
-			//   position: absolute;
-			//   top: 50%;
-			//   right: 10rpx;
-			//   transform: translateY(-50%);
-			// }
 			.btn {
-				width: 80rpx;
-				height: 32rpx;
-				display: inline-block;
-				font-size: 32rpx;
+				display: flex;
+				align-items: center;
+				justify-content: center;
+				width: 120rpx;
+				height: 56rpx;
+				font-size: 28rpx;
 				border: 1px solid #fff;
 				text-align: center;
-				line-height: 30rpx;
+				line-height: 56rpx;
+				border-radius: 8rpx;
+				transition: opacity 0.3s;
+				cursor: pointer;
+
+				&:active {
+					opacity: 0.7;
+				}
+
+				&.cancel {
+					background-color: transparent;
+					color: #fff;
+				}
+
+				&.confirm {
+					background-color: rgba(255, 255, 255, 0.2);
+					color: #fff;
+				}
 			}
 		}
 
@@ -495,4 +915,4 @@
 			}
 		}
 	}
-</style>
+</style>

+ 26 - 11
pages/dispatchManage/taskWork/transfer.vue

@@ -165,21 +165,36 @@
 			position: relative;
 			font-size: 32rpx;
 			color: #fff;
+			padding: 0 30rpx;
+			box-sizing: border-box;
 
-			// .btn-box {
-			//   position: absolute;
-			//   top: 50%;
-			//   right: 10rpx;
-			//   transform: translateY(-50%);
-			// }
 			.btn {
-				width: 80rpx;
-				height: 32rpx;
-				display: inline-block;
-				font-size: 32rpx;
+				display: flex;
+				align-items: center;
+				justify-content: center;
+				width: 120rpx;
+				height: 56rpx;
+				font-size: 28rpx;
 				border: 1px solid #fff;
 				text-align: center;
-				line-height: 30rpx;
+				line-height: 56rpx;
+				border-radius: 8rpx;
+				transition: opacity 0.3s;
+				cursor: pointer;
+
+				&:active {
+					opacity: 0.7;
+				}
+
+				&.cancel {
+					background-color: transparent;
+					color: #fff;
+				}
+
+				&.confirm {
+					background-color: rgba(255, 255, 255, 0.2);
+					color: #fff;
+				}
 			}
 		}