From 35fb4a40571d69b85caede7348101d71789b5fb3 Mon Sep 17 00:00:00 2001
From: chenyao <1219716595@qq.com>
Date: Tue, 04 Aug 2026 11:01:14 +0800
Subject: [PATCH] feat:提交吉安工单和移动端处置数据

---
 uniapps/work-app/src/subPackages/workDetail/HandleWorking/index-copy.vue |  602 +++++++++++++++++++++++++++---------------------------
 1 files changed, 298 insertions(+), 304 deletions(-)

diff --git a/uniapps/work-app/src/subPackages/workDetail/HandleWorking/index-copy.vue b/uniapps/work-app/src/subPackages/workDetail/HandleWorking/index-copy.vue
index e668b0d..26725c8 100644
--- a/uniapps/work-app/src/subPackages/workDetail/HandleWorking/index-copy.vue
+++ b/uniapps/work-app/src/subPackages/workDetail/HandleWorking/index-copy.vue
@@ -1,58 +1,55 @@
 <template>
-	<view class="handle-page">
-		<u-navbar title="待办处置" :is-back="true" back-text="" :back-icon-size="40" @left-click="onBackClick"></u-navbar>
+  <view class="handle-page">
+    <u-navbar title="待办处置" :is-back="true" back-text="" :back-icon-size="40" @left-click="onBackClick"></u-navbar>
 
-		<scroll-view class="form-scroll" scroll-y>
-			<view class="form-section description-section">
-				<view class="section-header">
-					<text class="section-title">处置描述</text>
-				</view>
-				<view class="description-wrapper">
+    <scroll-view class="form-scroll" scroll-y>
+      <view class="form-section description-section">
+        <view class="section-header">
+          <text class="section-title">处置描述</text>
+        </view>
+        <view class="description-wrapper">
 					<textarea
-						v-model="formData.disposeContent"
-						class="description-input"
-						maxlength="140"
-						placeholder="请输入"
-						placeholder-class="description-placeholder"
-						:show-confirm-bar="false"
-					/>
-					<text class="word-count">{{ descriptionLength }}/140</text>
-				</view>
-			</view>
+            v-model="formData.disposeContent"
+            class="description-input"
+            maxlength="140"
+            placeholder="请输入"
+            placeholder-class="description-placeholder"
+            :show-confirm-bar="false"
+          />
+          <text class="word-count">{{ descriptionLength }}/140</text>
+        </view>
+      </view>
 
-			<!--			<view class="form-section status-section">-->
-			<!--				<text class="section-title">处置中</text>-->
-			<!--				<switch class="status-switch" :checked="formData.isHandling" color="#00b578" @change="handleStatusChange" />-->
-			<!--			</view>-->
+      <!--			<view class="form-section status-section">-->
+      <!--				<text class="section-title">处置中</text>-->
+      <!--				<switch class="status-switch" :checked="formData.isHandling" color="#00b578" @change="handleStatusChange" />-->
+      <!--			</view>-->
 
-			<view class="form-section upload-section">
-				<view class="section-header upload-header">
-					<text class="section-title">附件上传</text>
-				</view>
-				<!--				<button class="select-file-btn" @click="handleChooseFile">选择文件</button>-->
-				<u-button color="#1D6FE9" class="select-file-btn" :disabled="uploading" @click="handleChooseFile">
-					{{ uploading ? '上传中...' : '选择文件' }}
-				</u-button>
+      <view class="form-section upload-section">
+        <view class="section-header upload-header">
+          <text class="section-title">附件上传</text>
+        </view>
+        <!--				<button class="select-file-btn" @click="handleChooseFile">选择文件</button>-->
+        <u-button color="#1D6FE9" class="select-file-btn" :disabled="uploading" @click="handleChooseFile">
+          {{ uploading ? '上传中...' : '选择文件' }}
+        </u-button>
 
-				<view v-if="attachmentList.length" class="attachment-list">
-					<view v-for="(file, index) in attachmentList" :key="`${file.path}-${index}`" class="attachment-item">
-						<view class="file-info">
-							<text class="file-name">{{ file.name }}</text>
-							<text v-if="file.size" class="file-size">{{ formatFileSize(file.size) }}</text>
-						</view>
-						<text class="remove-file-btn" @click.stop="handleRemoveFile(index)">×</text>
-					</view>
-				</view>
-			</view>
-		</scroll-view>
+        <view v-if="attachmentList.length" class="attachment-list">
+          <view v-for="(file, index) in attachmentList" :key="`${file.path}-${index}`" class="attachment-item">
+            <image class="attachment-image" :src="file.path" mode="aspectFill" @click="handlePreviewImage(index)" />
+            <text class="remove-file-btn" @click.stop="handleRemoveFile(index)">×</text>
+          </view>
+        </view>
+      </view>
+    </scroll-view>
 
-		<view class="action-footer">
-			<u-button color="#AEAEAE" class="custom-style" @click="handleCancel">取消</u-button>
-			<u-button color="#1D6FE9" class="custom-style" :disabled="submitting || uploading" @click="handleSubmit">
-				{{ submitting ? '提交中...' : '确定' }}
-			</u-button>
-		</view>
-	</view>
+    <view class="action-footer">
+      <u-button color="#AEAEAE" class="custom-style" @click="handleCancel">取消</u-button>
+      <u-button color="#1D6FE9" class="custom-style" :disabled="submitting || uploading" @click="handleSubmit">
+        {{ submitting ? '提交中...' : '确定' }}
+      </u-button>
+    </view>
+  </view>
 </template>
 
 <script setup>
@@ -67,13 +64,13 @@
 const uploading = ref(false)
 const attachmentList = ref([])
 const formData = ref({
-	disposeContent: '',
-	isHandling: true,
+  disposeContent: '',
+  isHandling: true,
 })
 const navbarTitleStyle = {
-	color: '#ffffff',
-	fontSize: '34rpx',
-	fontWeight: '500',
+  color: '#ffffff',
+  fontSize: '34rpx',
+  fontWeight: '500',
 }
 
 // 计算处置描述字数
@@ -81,12 +78,12 @@
 
 // 读取当前工单标识
 onLoad(options => {
-	eventId.value = options?.id ?? ''
+  eventId.value = options?.id ?? ''
 })
 
 // 返回上一页
 function handleBack() {
-	uni.navigateBack()
+  uni.navigateBack()
 }
 
 // 切换处置状态
@@ -96,375 +93,372 @@
 
 // 提取文件名称
 function getFileName(filePath = '') {
-	const normalizedPath = filePath.replace(/\\/g, '/')
-	return decodeURIComponent(normalizedPath.split('/').pop() || '未命名文件')
+  const normalizedPath = filePath.replace(/\\/g, '/')
+  return decodeURIComponent(normalizedPath.split('/').pop() || '未命名文件')
 }
 
 // 上传单个已选择文件
 async function uploadSelectedFile(file) {
-	const response = await uploadFileAPI(file.path)
-	const link = response?.data?.link || response?.data?.url || response?.link
-	if (!link) throw new Error('上传接口未返回文件地址')
-	return { ...file, link }
+  const response = await uploadFileAPI(file.path)
+  const link = response?.data?.link || response?.data?.url || response?.link
+  if (!link) throw new Error('上传接口未返回文件地址')
+  return { ...file, link }
 }
 
 // 处理已选择文件
 async function handleChooseSuccess(result) {
-	const selectedFiles = result.tempFiles?.length
-		? result.tempFiles
-		: (result.tempFilePaths ?? []).map(path => ({ path }))
-	const availableCount = MAX_FILE_COUNT - attachmentList.value.length
-	const normalizedFiles = selectedFiles
-		.slice(0, availableCount)
-		.map(file => {
-			const path = file.path || file.tempFilePath || ''
-			return {
-				name: file.name || getFileName(path),
-				path,
-				size: Number(file.size) || 0,
-			}
-		})
-		.filter(file => file.path)
-	if (!normalizedFiles.length) return
+  const selectedFiles = result.tempFiles?.length
+    ? result.tempFiles
+    : (result.tempFilePaths ?? []).map(path => ({ path }))
+  const availableCount = MAX_FILE_COUNT - attachmentList.value.length
+  const normalizedFiles = selectedFiles
+    .slice(0, availableCount)
+    .map(file => {
+      const path = file.path || file.tempFilePath || ''
+      return {
+        name: file.name || getFileName(path),
+        path,
+        size: Number(file.size) || 0,
+      }
+    })
+    .filter(file => file.path)
+  if (!normalizedFiles.length) return
 
-	uploading.value = true
-	uni.showLoading({ title: '上传中...', mask: true })
-	let failedCount = 0
-	try {
-		const uploadResults = await Promise.all(
-			normalizedFiles.map(async file => {
-				try {
-					return { success: true, file: await uploadSelectedFile(file) }
-				} catch {
-					return { success: false, file }
-				}
-			})
-		)
-		const uploadedFiles = uploadResults.filter(item => item.success).map(item => item.file)
-		failedCount = uploadResults.length - uploadedFiles.length
-		attachmentList.value.push(...uploadedFiles)
-	} finally {
-		uni.hideLoading()
-		uploading.value = false
-	}
-	uni.showToast({
-		title: failedCount ? `${failedCount}个文件上传失败` : '上传成功',
-		icon: failedCount ? 'none' : 'success',
-	})
+  uploading.value = true
+  uni.showLoading({ title: '上传中...', mask: true })
+  let failedCount = 0
+  try {
+    const uploadResults = await Promise.all(
+      normalizedFiles.map(async file => {
+        try {
+          return { success: true, file: await uploadSelectedFile(file) }
+        } catch {
+          return { success: false, file }
+        }
+      })
+    )
+    const uploadedFiles = uploadResults.filter(item => item.success).map(item => item.file)
+    failedCount = uploadResults.length - uploadedFiles.length
+    attachmentList.value.push(...uploadedFiles)
+  } finally {
+    uni.hideLoading()
+    uploading.value = false
+  }
+  uni.showToast({
+    title: failedCount ? `${failedCount}个文件上传失败` : '上传成功',
+    icon: failedCount ? 'none' : 'success',
+  })
 }
 
 // 处理选择文件失败
 function handleChooseFail(error) {
-	if (error?.errMsg?.includes('cancel')) return
-	uni.showToast({ title: '选择文件失败', icon: 'none' })
+  if (error?.errMsg?.includes('cancel')) return
+  uni.showToast({ title: '取消选择文件', icon: 'none' })
 }
 
 // 选择附件
 function handleChooseFile() {
-	if (uploading.value) return
-	const availableCount = MAX_FILE_COUNT - attachmentList.value.length
-	if (availableCount <= 0) {
-		uni.showToast({ title: `最多选择${MAX_FILE_COUNT}个附件`, icon: 'none' })
-		return
-	}
-	const options = {
-		count: availableCount,
-		type: 'all',
-		success: handleChooseSuccess,
-		fail: handleChooseFail,
-	}
+  if (uploading.value) return
+  const availableCount = MAX_FILE_COUNT - attachmentList.value.length
+  if (availableCount <= 0) {
+    uni.showToast({ title: `最多选择${MAX_FILE_COUNT}个附件`, icon: 'none' })
+    return
+  }
+  const options = {
+    count: availableCount,
+    type: 'image',
+    success: handleChooseSuccess,
+    fail: handleChooseFail,
+  }
 
-	// #ifdef H5
-	uni.chooseFile(options)
-	// #endif
+  // #ifdef H5
+  uni.chooseFile(options)
+  // #endif
 
-	// #ifdef MP-WEIXIN
-	uni.chooseMessageFile(options)
-	// #endif
+  // #ifdef MP-WEIXIN
+  uni.chooseMessageFile(options)
+  // #endif
 
-	// #ifdef APP-PLUS
-	uni.chooseImage({ ...options, sourceType: ['album', 'camera'] })
-	// #endif
+  // #ifdef APP-PLUS
+  uni.chooseImage({ ...options, sourceType: ['album', 'camera'] })
+  // #endif
 }
 
 // 移除附件
 function handleRemoveFile(index) {
-	attachmentList.value.splice(index, 1)
+  attachmentList.value.splice(index, 1)
 }
 
-// 格式化文件大小
-function formatFileSize(size) {
-	if (size < 1024) return `${size} B`
-	if (size < 1024 * 1024) return `${(size / 1024).toFixed(1)} KB`
-	return `${(size / 1024 / 1024).toFixed(1)} MB`
+// 预览已选择图片
+function handlePreviewImage(index) {
+  uni.previewImage({
+    current: index,
+    urls: attachmentList.value.map(file => file.path),
+  })
 }
 
 // 取消处置
 function handleCancel() {
-	uni.navigateBack()
+  uni.navigateBack()
 }
 
 // 提交处置信息
 async function handleSubmit() {
-	if (uploading.value) {
-		uni.showToast({ title: '请等待附件上传完成', icon: 'none' })
-		return
-	}
-	const disposeContent = formData.value.disposeContent.trim()
-	if (!disposeContent) {
-		uni.showToast({ title: '请输入处置描述', icon: 'none' })
-		return
-	}
-	if (!eventId.value) {
-		uni.showToast({ title: '工单信息缺失', icon: 'none' })
-		return
-	}
+  if (uploading.value) {
+    uni.showToast({ title: '请等待附件上传完成', icon: 'none' })
+    return
+  }
+  const disposeContent = formData.value.disposeContent.trim()
+  if (!disposeContent) {
+    uni.showToast({ title: '请输入处置描述', icon: 'none' })
+    return
+  }
+  if (!eventId.value) {
+    uni.showToast({ title: '工单信息缺失', icon: 'none' })
+    return
+  }
 
-	submitting.value = true
-	try {
-		await addDisposeRecord({
-			eventId: eventId.value,
-			recordType: 1,
-			disposeContent: formData.value.disposeContent,
-			targetEventStatus: eventStatus.value == 1 ? 3 : eventStatus.value,
-			updateEventStatus: true,
-			attachUrl: attachmentList.value.map(file => file.link),
-			// operateTime: '2026-07-30 14:00:00',
-			// eventStatus: formData.value.isHandling ? '1' : '3',
-			// handleDesc,
-			// attachmentList: attachmentList.value.map(file => ({
-			// 	attachName: file.name,
-			// 	filePath: file.path,
-			// })),
-		})
-		uni.showToast({ title: '提交成功', icon: 'success' })
-		setTimeout(() => {
-			submitting.value = false
-			uni.navigateBack()
-			// uni.navigateTo({
-			// 	url: `/subPackages/workDetail/HandleWork/index?id=${eventId.value}`,
-			// })
-		}, 1200)
-	} catch {
-		submitting.value = false
-		uni.showToast({ title: '提交失败,请重试', icon: 'none' })
-	}
+  submitting.value = true
+  try {
+    await addDisposeRecord({
+      eventId: eventId.value,
+      recordType: 1,
+      disposeContent: formData.value.disposeContent,
+      targetEventStatus: eventStatus.value == 1 ? 3 : eventStatus.value,
+      updateEventStatus: true,
+      attachUrl: attachmentList.value.map(file => file.link),
+      // operateTime: '2026-07-30 14:00:00',
+      // eventStatus: formData.value.isHandling ? '1' : '3',
+      // handleDesc,
+      // attachmentList: attachmentList.value.map(file => ({
+      // 	attachName: file.name,
+      // 	filePath: file.path,
+      // })),
+    })
+    uni.showToast({ title: '提交成功', icon: 'success' })
+    setTimeout(() => {
+      submitting.value = false
+      uni.navigateBack()
+      // uni.navigateTo({
+      // 	url: `/subPackages/workDetail/HandleWork/index?id=${eventId.value}`,
+      // })
+    }, 1200)
+  } catch {
+    submitting.value = false
+    uni.showToast({ title: '提交失败,请重试', icon: 'none' })
+  }
 }
 
 // 返回按钮点击事件
 const onBackClick = () => {
-	uni.navigateBack()
+  uni.navigateBack()
 }
 
 onLoad(options => {
-	console.log(options, '9090')
-	eventId.value = options?.id || ''
-	eventStatus.value = options?.eventStatus || ''
+  console.log(options, '9090')
+  eventId.value = options?.id || ''
+  eventStatus.value = options?.eventStatus || ''
 })
 </script>
 
 <style scoped lang="scss">
 .handle-page {
-	padding-top: 88rpx;
-	:deep() {
-		.u-navbar__content {
-			background: url('https://wrj.shuixiongit.com/aiskyminio/cloud-bucket/ztzf_app_assets/images/user/bg.png')
-				no-repeat !important;
-			background-size: 100% !important;
-			height: 88rpx !important;
-		}
-	}
+  padding-top: 88rpx;
+  :deep() {
+    .u-navbar__content {
+      background: url('https://wrj.shuixiongit.com/aiskyminio/cloud-bucket/ztzf_app_assets/images/user/bg.png')
+      no-repeat !important;
+      background-size: 100% !important;
+      height: 88rpx !important;
+    }
+  }
 
-	display: flex;
-	flex-direction: column;
-	box-sizing: border-box;
-	height: calc(100vh);
-	//padding-top: 88rpx;
-	//background: #111827;
-	//color: #f5f7fa;
+  display: flex;
+  flex-direction: column;
+  box-sizing: border-box;
+  height: calc(100vh);
+  //padding-top: 88rpx;
+  //background: #111827;
+  //color: #f5f7fa;
 
-	//:deep(.u-navbar__content) {
-	//	height: 88rpx !important;
-	//	background: #151c29 !important;
-	//}
+  //:deep(.u-navbar__content) {
+  //	height: 88rpx !important;
+  //	background: #151c29 !important;
+  //}
 }
 
 .form-scroll {
-	box-sizing: border-box;
-	height: 0;
-	flex: 1;
-	padding: 60rpx 24rpx 24rpx;
+	// #ifdef APP-PLUS
+	padding-top: 60rpx;
+	// #endif
+  box-sizing: border-box;
+  height: 0;
+  flex: 1;
+  padding: 0 24rpx 24rpx;
 }
 
 .form-section {
-	box-sizing: border-box;
-	margin-bottom: 20rpx;
-	background: #ffffff;
-	border: 1rpx solid rgba(255, 255, 255, 0.03);
+  box-sizing: border-box;
+  margin-bottom: 20rpx;
+  background: #ffffff;
+  border: 1rpx solid rgba(255, 255, 255, 0.03);
 }
 
 .section-header {
-	display: flex;
-	align-items: center;
-	justify-content: space-between;
-	height: 82rpx;
-	padding: 0 22rpx;
-	border-bottom: 1rpx solid #eeeeee;
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  height: 82rpx;
+  padding: 0 22rpx;
+  border-bottom: 1rpx solid #eeeeee;
 }
 
 .section-title {
-	font-size: 30rpx;
-	font-weight: 400;
-	color: #222324;
+  font-size: 30rpx;
+  font-weight: 400;
+  color: #222324;
 }
 
 .description-wrapper {
-	position: relative;
+  position: relative;
 }
 
 .word-count {
-	position: absolute;
-	right: 22rpx;
-	bottom: 16rpx;
-	font-size: 24rpx;
-	color: #999;
+  position: absolute;
+  right: 22rpx;
+  bottom: 16rpx;
+  font-size: 24rpx;
+  color: #999;
 }
 
 .description-input {
-	display: block;
-	box-sizing: border-box;
-	width: 100%;
-	height: 350rpx;
-	padding: 24rpx 22rpx;
-	font-size: 30rpx;
-	line-height: 1.6;
-	color: #222324;
-	background: transparent;
+  display: block;
+  box-sizing: border-box;
+  width: 100%;
+  height: 350rpx;
+  padding: 24rpx 22rpx;
+  font-size: 30rpx;
+  line-height: 1.6;
+  color: #222324;
+  background: transparent;
 }
 
 :deep(.description-placeholder) {
-	color: #999;
+  color: #999;
 }
 
 .status-section {
-	display: flex;
-	align-items: center;
-	justify-content: space-between;
-	height: 104rpx;
-	padding: 0 20rpx 0 22rpx;
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  height: 104rpx;
+  padding: 0 20rpx 0 22rpx;
 }
 
 .status-switch {
-	transform: scale(0.84);
-	transform-origin: right center;
+  transform: scale(0.84);
+  transform-origin: right center;
 }
 
 .upload-section {
-	padding-bottom: 22rpx;
+  padding-bottom: 22rpx;
 }
 
 .upload-header {
-	margin-bottom: 0;
+  margin-bottom: 0;
 }
 
 .select-file-btn {
-	width: 210rpx;
-	height: 70rpx;
-	margin: 0;
-	font-size: 28rpx;
-	line-height: 70rpx;
-	//color: #ffffff;
-	//background: #409eff;
-	//border-radius: 4rpx;
+  width: 210rpx;
+  height: 70rpx;
+  margin: 0;
+  font-size: 28rpx;
+  line-height: 70rpx;
+  //color: #ffffff;
+  //background: #409eff;
+  //border-radius: 4rpx;
 }
 
 .select-file-btn::after,
 .action-btn::after {
-	border: 0;
+  border: 0;
 }
 
 .custom-style {
-	width: 276rpx;
-	height: 76rpx;
-	font-family: 'Source Han Sans CN';
-	font-weight: 400;
-	font-size: 28rpx;
+  width: 276rpx;
+  height: 76rpx;
+  font-family: 'Source Han Sans CN';
+  font-weight: 400;
+  font-size: 28rpx;
 }
 
 .attachment-list {
-	padding: 10rpx 22rpx 0;
+  display: grid;
+  grid-template-columns: repeat(3, 1fr);
+  gap: 16rpx;
+  padding: 10rpx 22rpx 0;
 }
 
 .attachment-item {
-	display: flex;
-	align-items: center;
-	justify-content: space-between;
-	min-height: 70rpx;
-	border-bottom: 1rpx solid #eeeeee;
+  position: relative;
+  width: 100%;
+  aspect-ratio: 1;
+  overflow: hidden;
+  border-radius: 8rpx;
 }
 
-.file-info {
-	display: flex;
-	align-items: center;
-	width: 0;
-	flex: 1;
-}
-
-.file-name {
-	overflow: hidden;
-	font-size: 26rpx;
-	color: #222324;
-	text-overflow: ellipsis;
-	white-space: nowrap;
-}
-
-.file-size {
-	margin-left: 14rpx;
-	font-size: 22rpx;
-	color: #999;
-	white-space: nowrap;
+.attachment-image {
+  display: block;
+  width: 100%;
+  height: 100%;
 }
 
 .remove-file-btn {
-	width: 56rpx;
-	font-size: 42rpx;
-	line-height: 56rpx;
-	color: #999;
-	text-align: right;
+  position: absolute;
+  top: 6rpx;
+  right: 6rpx;
+  width: 40rpx;
+  height: 40rpx;
+  font-size: 32rpx;
+  line-height: 36rpx;
+  color: #ffffff;
+  text-align: center;
+  background: rgba(0, 0, 0, 0.55);
+  border-radius: 50%;
 }
 
 .action-footer {
-	display: flex;
-	align-items: center;
-	gap: 28rpx;
-	box-sizing: border-box;
-	padding: 22rpx 28rpx calc(22rpx + env(safe-area-inset-bottom));
-	//background: #111827;
+  display: flex;
+  align-items: center;
+  gap: 28rpx;
+  box-sizing: border-box;
+  padding: 22rpx 28rpx calc(22rpx + env(safe-area-inset-bottom));
+  //background: #111827;
 }
 
 .action-btn {
-	height: 82rpx;
-	margin: 0;
-	flex: 1;
-	font-size: 30rpx;
-	line-height: 80rpx;
-	color: #ffffff;
-	border-radius: 6rpx;
+  height: 82rpx;
+  margin: 0;
+  flex: 1;
+  font-size: 30rpx;
+  line-height: 80rpx;
+  color: #ffffff;
+  border-radius: 6rpx;
 }
 
 .cancel-btn {
-	color: #00b578;
-	background: transparent;
-	border: 2rpx solid #00b578;
+  color: #00b578;
+  background: transparent;
+  border: 2rpx solid #00b578;
 }
 
 .confirm-btn {
-	background: #00b578;
-	border: 2rpx solid #00b578;
+  background: #00b578;
+  border: 2rpx solid #00b578;
 }
 
 .confirm-btn[disabled] {
-	color: rgba(255, 255, 255, 0.72);
-	background: #087b58;
+  color: rgba(255, 255, 255, 0.72);
+  background: #087b58;
 }
 </style>

--
Gitblit v1.9.3