修复:保险支持5张图片

This commit is contained in:
2025-06-14 17:12:45 +08:00
parent de0f6c43b1
commit 47b6a3d8de
17 changed files with 746 additions and 184 deletions

View File

@@ -1,32 +1,38 @@
import {useEffect, useState, useCallback} from "react";
import {useEffect, useState} from "react";
import Taro from '@tarojs/taro'
import {
Image,
Button,
TextArea,
Cell,
Loading,
Space
} from '@nutui/nutui-react-taro'
import {Camera, Truck} from '@nutui/icons-react-taro'
import {Truck} from '@nutui/icons-react-taro'
import {addHjmBxLog} from "@/api/hjm/hjmBxLog";
import {pageHjmCar} from "@/api/hjm/hjmCar";
import {uploadFile} from "@/api/system/file";
import {HjmBxLog} from "@/api/hjm/hjmBxLog/model";
import {HjmCar} from "@/api/hjm/hjmCar/model";
import {listCmsWebsiteField} from "@/api/cms/cmsWebsiteField";
import {CmsWebsiteField} from "@/api/cms/cmsWebsiteField/model";
// 图片数据接口
interface UploadedImageData {
url: string;
}
/**
* 一键报险 - 添加报险记录页面
*/
function BxAdd() {
const [loading, setLoading] = useState<boolean>(false)
const [uploading, setUploading] = useState<boolean>(false)
const [bxFiled, setBxFiled] = useState<CmsWebsiteField>()
const [bxFiled2, setBxFiled2] = useState<CmsWebsiteField>()
const [carInfo, setCarInfo] = useState<HjmCar | null>(null)
const [lastClickTime, setLastClickTime] = useState<number>(0)
const [fileList, setFileList] = useState<any[]>([]) // 图片文件列表
const [formData, setFormData] = useState<HjmBxLog>({
carId: undefined,
accidentType: undefined,
image: '',
image: undefined,
comments: '',
status: 0 // 0: 待审核, 1: 已通过, 2: 已驳回
})
@@ -46,6 +52,16 @@ function BxAdd() {
// 初始化页面数据
const initPageData = async () => {
try {
listCmsWebsiteField({}).then(data => {
const bxPhone = data.find(item => item.name === 'bxPhone');
const bxPhone2 = data.find(item => item.name === 'bxPhone2');
if (bxPhone) {
setBxFiled(bxPhone);
}
if (bxPhone2) {
setBxFiled2(bxPhone2);
}
})
pageHjmCar({driverId: Taro.getStorageSync('UserId')}).then(res => {
const car = res?.list[0];
setLoading(true)
@@ -76,77 +92,130 @@ function BxAdd() {
}
}
// 拍照上传 - 使用 useCallback 防止重复触发
const takePhoto = useCallback((event?: any) => {
// 阻止事件冒泡
if (event) {
event.stopPropagation()
event.preventDefault()
}
// 防抖:防止快速连续点击
const now = Date.now()
if (now - lastClickTime < 1000) { // 1秒内不允许重复点击
console.log('点击过于频繁,请稍候...')
return
}
setLastClickTime(now)
// 防止重复点击
if (uploading) {
console.log('正在上传中,请稍候...')
// 选择并上传图片
const handleChooseImage = () => {
if (fileList.length >= 5) {
Taro.showToast({
title: '正在上传中...',
icon: 'loading'
title: '最多只能上传5张图片',
icon: 'none'
})
return
}
console.log('开始拍照上传...')
Taro.chooseImage({
count: 1,
count: 5 - fileList.length, // 剩余可选择的数量
sizeType: ['compressed'],
sourceType: ['camera'],
success: async (res) => {
try {
setUploading(true)
console.log('选择图片成功:', res.tempFilePaths[0])
sourceType: ['album', 'camera'],
success: (res) => {
console.log('选择图片成功:', res)
// 这里应该调用实际的上传接口
const uploadResult = await uploadFile()
setFormData(prev => ({
...prev,
image: uploadResult.url || res.tempFilePaths[0]
}))
Taro.showToast({
title: '照片上传成功',
icon: 'success'
})
} catch (error) {
console.error('上传失败:', error)
Taro.showToast({
title: '上传失败,请重试',
icon: 'error'
})
} finally {
setUploading(false)
}
// 逐个上传选中的图片
res.tempFilePaths.forEach((filePath, index) => {
uploadSingleImage(filePath, index)
})
},
fail: (error) => {
console.error('选择图片失败:', error)
fail: (err) => {
console.log('选择图片失败:', err)
Taro.showToast({
title: '选择图片失败',
icon: 'error'
})
setUploading(false)
}
})
}, [uploading, lastClickTime])
}
// 提交表单
// 上传单张图片
const uploadSingleImage = (filePath: string, index: number) => {
const TenantId = Taro.getStorageSync('TenantId')
Taro.uploadFile({
url: 'https://server.gxwebsoft.com/api/oss/upload',
filePath: filePath,
name: 'file',
header: {
'content-type': 'application/json',
TenantId
},
success: (res) => {
try {
const data = JSON.parse(res.data);
console.log('上传成功', data)
if (data.code === 0) {
// 更新文件列表
const newFile = {
name: `图片${Date.now()}_${index}`,
url: data.data.url,
status: 'success',
message: '上传成功',
type: 'image',
uid: `${Date.now()}_${index}`,
}
setFileList(prev => {
const newList = [...prev, newFile]
// 同时更新表单数据 - 使用JSON格式存储
const imageData: UploadedImageData[] = newList.map(f => ({
url: f.url
}))
setFormData(prevForm => ({
...prevForm,
image: JSON.stringify(imageData)
}))
return newList
})
Taro.showToast({
title: '上传成功',
icon: 'success'
})
} else {
Taro.showToast({
title: data.message || '上传失败',
icon: 'error'
})
}
} catch (error) {
console.error('解析响应失败:', error)
Taro.showToast({
title: '上传失败',
icon: 'error'
})
}
},
fail: (err) => {
console.log('上传请求失败', err);
Taro.showToast({
title: '上传失败',
icon: 'error'
})
}
})
}
// 处理文件删除
const handleFileRemove = (file: any) => {
console.log('删除文件:', file)
const newFileList = fileList.filter(f => f.uid !== file.uid)
setFileList(newFileList)
// 更新表单数据 - 使用JSON格式存储
if (newFileList.length === 0) {
setFormData(prev => ({
...prev,
image: undefined
}))
} else {
const imageData: UploadedImageData[] = newFileList.map(f => ({
url: f.url
}))
setFormData(prev => ({
...prev,
image: JSON.stringify(imageData)
}))
}
}
// 提交表单
const handleSubmit = async () => {
// 表单验证
if (!formData.carId) {
@@ -165,9 +234,9 @@ function BxAdd() {
return
}
if (!formData.image) {
if (!formData.image || fileList.length === 0) {
Taro.showToast({
title: '请上传事故现场照片',
title: '请上传现场照片',
icon: 'none'
})
return
@@ -183,6 +252,25 @@ function BxAdd() {
comments: `${accidentDescription || '无'}`
}
console.log('提交的图片数据:', formData.image)
console.log('完整提交数据:', submitData)
// 解析JSON格式的图片数据示例
if (formData.image) {
try {
const parsedImages: UploadedImageData[] = JSON.parse(formData.image)
console.log('解析后的图片数据:', parsedImages)
console.log('图片数量:', parsedImages.length)
parsedImages.forEach((img, index) => {
console.log(`图片${index + 1}:`, {
url: img.url
})
})
} catch (error) {
console.error('解析图片数据失败:', error)
}
}
await addHjmBxLog(submitData)
Taro.showToast({
@@ -206,7 +294,9 @@ function BxAdd() {
}
useEffect(() => {
initPageData()
initPageData().then(r => {
console.log(r,'rr')
})
}, [])
if (loading && !carInfo) {
@@ -228,6 +318,16 @@ function BxAdd() {
minHeight: '100vh',
paddingBottom: '80px'
}}>
<div style={{
backgroundColor: '#fff',
margin: '16px',
borderRadius: '12px',
padding: '16px',
boxShadow: '0 2px 8px rgba(0,0,0,0.06)'
}}>
{bxFiled && (<div>{bxFiled.comments}{bxFiled.value}</div>)}
{bxFiled2 && (<div>{bxFiled2.comments}{bxFiled2.value}</div>)}
</div>
{/* 车辆信息卡片 */}
{carInfo && (
<div style={{
@@ -264,6 +364,95 @@ function BxAdd() {
</div>
)}
{/* 现场照片 */}
<div style={{
backgroundColor: '#fff',
margin: '0 16px 16px',
borderRadius: '12px',
padding: '16px'
}}>
<div style={{marginBottom: '12px'}}>
<span style={{fontSize: '16px', fontWeight: 'bold'}}></span>
<span style={{color: '#ff4d4f', fontSize: '12px', marginLeft: '8px'}}>*5</span>
{fileList.length > 0 && (
<span style={{color: '#52c41a', fontSize: '12px', marginLeft: '8px'}}>
{fileList.length}
</span>
)}
</div>
<div style={{
display: 'flex',
flexWrap: 'wrap',
gap: '12px'
}}>
{/* 显示已上传的图片 */}
{fileList.map((file) => (
<div key={file.uid} style={{
position: 'relative',
width: '100px',
height: '100px',
borderRadius: '8px',
overflow: 'hidden',
border: '1px solid #d9d9d9'
}}>
<img
src={file.url}
alt={file.name}
style={{
width: '100%',
height: '100%',
objectFit: 'cover'
}}
/>
<Button
size="small"
type="default"
style={{
position: 'absolute',
top: '-8px',
right: '-8px',
width: '24px',
height: '24px',
borderRadius: '12px',
fontSize: '12px',
minWidth: '24px',
padding: 0
}}
onClick={() => handleFileRemove(file)}
>
×
</Button>
</div>
))}
{/* 添加图片按钮 */}
{fileList.length < 5 && (
<Button
size="small"
onClick={handleChooseImage}
style={{
width: '100px',
height: '100px',
borderRadius: '8px',
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
border: '2px dashed #d9d9d9',
backgroundColor: '#fafafa'
}}
>
<span style={{fontSize: '24px', color: '#d9d9d9'}}>+</span>
<span style={{fontSize: '12px', marginTop: '4px', color: '#666'}}>
</span>
</Button>
)}
</div>
</div>
{/* 事故信息表单 */}
<div style={{
backgroundColor: '#fff',
@@ -277,9 +466,7 @@ function BxAdd() {
}}>
<span style={{fontSize: '16px', fontWeight: 'bold'}}></span>
</div>
<Cell.Group>
{/* 事故类型 */}
<Cell
title="事故类型"
description={accidentType || '请选择事故类型'}
@@ -292,16 +479,6 @@ function BxAdd() {
})
}}
/>
{/* 事故时间 */}
{/*<Cell*/}
{/* title="事故时间"*/}
{/* description={accidentTime ? new Date(accidentTime).toLocaleString() : '请选择事故时间'}*/}
{/* onClick={() => {*/}
{/* const now = new Date()*/}
{/* setAccidentTime(now.toISOString().slice(0, 16))*/}
{/* }}*/}
{/*/>*/}
</Cell.Group>
</div>
@@ -323,79 +500,6 @@ function BxAdd() {
/>
</div>
{/* 现场照片 */}
<div style={{
backgroundColor: '#fff',
margin: '0 16px 16px',
borderRadius: '12px',
padding: '16px'
}}>
<div style={{marginBottom: '12px'}}>
<span style={{fontSize: '16px', fontWeight: 'bold'}}></span>
<span style={{color: '#ff4d4f', fontSize: '12px', marginLeft: '8px'}}>*</span>
</div>
<div style={{
display: 'flex',
flexWrap: 'wrap',
gap: '12px'
}}>
{formData.image && (
<div style={{position: 'relative'}}>
<Image
src={formData.image}
width="100"
height="100"
radius="8px"
mode="aspectFill"
/>
<Button
size="small"
type="default"
style={{
position: 'absolute',
top: '-8px',
right: '-8px',
width: '24px',
height: '24px',
borderRadius: '12px',
fontSize: '12px'
}}
onClick={() => setFormData(prev => ({...prev, image: ''}))}
>
×
</Button>
</div>
)}
{!formData.image && (
<Button
size="small"
loading={uploading}
disabled={uploading}
onClick={takePhoto}
style={{
width: '100px',
height: '100px',
borderRadius: '8px',
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
border: '2px dashed #d9d9d9',
opacity: uploading ? 0.6 : 1,
cursor: uploading ? 'not-allowed' : 'pointer'
}}
>
<Camera size={24}/>
<span style={{fontSize: '12px', marginTop: '4px'}}>
{uploading ? '上传中...' : '拍照'}
</span>
</Button>
)}
</div>
</div>
{/* 提交按钮 */}
<div style={{
position: 'fixed',