修复:保险支持5张图片

This commit is contained in:
2025-06-15 00:43:58 +08:00
parent 47b6a3d8de
commit 6a700e9d4b
7 changed files with 350 additions and 69 deletions

View File

@@ -18,8 +18,10 @@ const BestSellers = (props: any) => {
return (
<div key={index} className={'flex bg-white rounded-lg w-full p-3 mb-3'}
onClick={() => Taro.navigateTo({url: '/hjm/query?id=' + item.code})}>
<Image src={item.image} mode={'scaleToFill'}
radius="10%" width="80" height="80"/>
{ item.image && (
<Image src={JSON.parse(item.image)[0].url} mode={'scaleToFill'}
radius="10%" width="80" height="80"/>
)}
<div className={'mx-3 flex flex-col'}>
<Space direction={'vertical'}>
<div className={'car-no text-lg font-bold'}>{item.code}</div>

View File

@@ -29,6 +29,7 @@ function BxAdd() {
const [bxFiled2, setBxFiled2] = useState<CmsWebsiteField>()
const [carInfo, setCarInfo] = useState<HjmCar | null>(null)
const [fileList, setFileList] = useState<any[]>([]) // 图片文件列表
const [lastSubmitTime, setLastSubmitTime] = useState<number>(0) // 最后提交时间
const [formData, setFormData] = useState<HjmBxLog>({
carId: undefined,
accidentType: undefined,
@@ -64,7 +65,6 @@ function BxAdd() {
})
pageHjmCar({driverId: Taro.getStorageSync('UserId')}).then(res => {
const car = res?.list[0];
setLoading(true)
if (car) {
setCarInfo(car)
setFormData(prev => ({
@@ -217,6 +217,26 @@ function BxAdd() {
// 提交表单
const handleSubmit = async () => {
// 防止重复提交 - 检查loading状态
if (loading) {
Taro.showToast({
title: '正在提交中,请稍候...',
icon: 'loading'
})
return
}
// 防止快速连续点击 - 2秒内不允许重复提交
const now = Date.now()
if (now - lastSubmitTime < 2000) {
Taro.showToast({
title: '请勿频繁提交',
icon: 'none'
})
return
}
setLastSubmitTime(now)
// 表单验证
if (!formData.carId) {
Taro.showToast({
@@ -278,6 +298,8 @@ function BxAdd() {
icon: 'success'
})
formData.image = ''
setTimeout(() => {
Taro.navigateBack()
}, 2000)
@@ -513,9 +535,11 @@ function BxAdd() {
<Button
type="primary"
block
loading={loading}
disabled={loading}
onClick={handleSubmit}
>
{loading ? '提交中...' : '提交报险申请'}
</Button>
</div>
</div>

View File

@@ -13,6 +13,7 @@ import Taro from '@tarojs/taro'
import {pageHjmBxLog} from "@/api/hjm/hjmBxLog";
import {HjmBxLog} from "@/api/hjm/hjmBxLog/model";
/**
* 报险记录列表页面
*/
@@ -45,7 +46,12 @@ const Bx: React.FC = () => {
keywords: keywords.trim()
})
setList(res?.list || [])
setList(res?.list.map(d => {
console.log(d,'ddd')
d.image = JSON.parse(d.image);
console.log(d)
return d;
}) || [])
} catch (error) {
console.error('获取报险记录失败:', error)
Taro.showToast({
@@ -227,14 +233,16 @@ const Bx: React.FC = () => {
{/* 事故照片预览 */}
{item.image && (
<div style={{marginBottom: '12px'}}>
<Image
src={item.image}
width="60"
height="60"
radius="6px"
mode="aspectFill"
/>
<div style={{marginBottom: '12px'}} className={'flex gap-2'}>
{item.image.map((image) => (
<Image
src={image.url}
width="60"
height="60"
radius="6px"
mode="aspectFill"
/>
))}
</div>
)}
@@ -262,27 +270,20 @@ const Bx: React.FC = () => {
</div>
{/* 浮动添加按钮 */}
<div style={{
position: 'fixed',
bottom: '20px',
right: '20px',
zIndex: 30
}}>
<Button
type="primary"
shape="round"
size="large"
onClick={onAddInsurance}
style={{
width: '56px',
height: '56px',
borderRadius: '28px',
boxShadow: '0 4px 12px rgba(0,0,0,0.15)'
}}
>
+
</Button>
</div>
{/*<div style={{*/}
{/* position: 'fixed',*/}
{/* bottom: '20px',*/}
{/* right: '20px',*/}
{/* zIndex: 30*/}
{/*}}>*/}
{/* <Button*/}
{/* type="primary"*/}
{/* size="large"*/}
{/* onClick={onAddInsurance}*/}
{/* >*/}
{/* 一键报险*/}
{/* </Button>*/}
{/*</div>*/}
</>
)
}

View File

@@ -3,7 +3,7 @@ import {Map} from '@tarojs/components'
import {Search} from '@nutui/icons-react-taro'
import {Button, Input} from '@nutui/nutui-react-taro'
import {useRouter} from '@tarojs/taro'
import {getHjmCar, getHjmCarByCode} from "@/api/hjm/hjmCar";
import {getHjmCarByCode} from "@/api/hjm/hjmCar";
import {HjmCar} from "@/api/hjm/hjmCar/model";
import './location.scss'
@@ -50,7 +50,7 @@ const Location = () => {
}
const reload = () => {
const id = Number(params.id);
const code = params.id;
setScale(14)
// 执行搜索
if (keywords) {
@@ -74,8 +74,8 @@ const Location = () => {
return false;
}
// 获取车辆信息
if (id) {
getHjmCar(id).then(data => {
if (code) {
getHjmCarByCode(code).then(data => {
setItem(data)
setLatitude(data.latitude)
setLongitude(data.longitude)

View File

@@ -2,7 +2,8 @@ import {useEffect, useState} from "react";
import Taro, {useRouter} from '@tarojs/taro'
import {getHjmCarByCode, pageHjmCar, updateHjmCar} from "@/api/hjm/hjmCar";
import {HjmCar} from "@/api/hjm/hjmCar/model";
import './location.scss'
import './location.scss';
import { Swiper } from '@nutui/nutui-react-taro'
import {copyText} from "@/utils/common";
import {View} from '@tarojs/components'
import {
@@ -13,11 +14,21 @@ import {
Cell,
Image
} from '@nutui/nutui-react-taro'
import { ImagePreview } from '@nutui/nutui-react-taro'
import {Scan} from '@nutui/icons-react-taro'
import {pageDictData} from "@/api/system/dict-data";
import {DictData} from "@/api/system/dict-data/model";
import {myUserVerify} from "@/api/system/userVerify";
import {uploadFile} from "@/api/system/file";
// 图片数据接口
interface UploadedImageData {
url?: string;
src?: string;
name?: string;
uid?: string;
message?: string;
type?: string;
}
/**
* 文章终极列表
@@ -28,6 +39,8 @@ const Query = () => {
const [keywords, setKeywords] = useState<string>()
const [dict, setDict] = useState<DictData[]>([])
const [adminId, setAdminId] = useState<number>()
const [showPreview, setShowPreview] = useState(false)
const [fileList, setFileList] = useState<UploadedImageData[]>([]) // 图片文件列表
const [FormData, setFormData] = useState<HjmCar>(
{
// 自增ID
@@ -135,25 +148,133 @@ const Query = () => {
});
}
// 拍照上传功能
const takePhoto = () => {
uploadFile().then(res => {
setFormData({
...FormData,
image: res.url
// 选择并上传图片
const handleChooseImage = () => {
if (fileList.length >= 5) {
Taro.showToast({
title: '最多只能上传5张图片',
icon: 'none'
})
return
}
Taro.chooseImage({
count: 5 - fileList.length, // 剩余可选择的数量
sizeType: ['compressed'],
sourceType: ['album', 'camera'],
success: (res) => {
console.log('选择图片成功:', res)
// 逐个上传选中的图片
res.tempFilePaths.forEach((filePath, index) => {
uploadSingleImage(filePath, index)
})
},
fail: (err) => {
console.log('选择图片失败:', err)
Taro.showToast({
title: '选择图片失败',
icon: 'error'
})
}
})
}
// 删除图片
// const removeImage = (index: number) => {
// const newImages = uploadedImages.filter((_, i) => i !== index);
// setUploadedImages(newImages);
// setFormData({
// ...FormData,
// image: newImages.join(',')
// });
// }
// 上传单张图片
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,
name: f.name,
uid: f.uid
}))
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,
src: f.url,
name: f.name,
uid: f.uid
}))
setFormData(prev => ({
...prev,
image: JSON.stringify(imageData)
}))
}
}
// 打开地图选择位置
// const chooseLocation = async () => {
@@ -197,6 +318,29 @@ const Query = () => {
if(data){
setFormData(data)
setKeywords(data.code)
// 解析图片数据
if (data.image) {
try {
const parsedImages: UploadedImageData[] = JSON.parse(data.image)
setFileList(parsedImages.map((img) => ({
url: img.url,
src: img.url
})))
} catch (error) {
// 如果解析失败可能是旧格式的单个URL
if (typeof data.image === 'string' && data.image.trim()) {
setFileList([{
src: data.image,
url: data.image,
message: '上传成功',
type: 'image',
uid: `legacy_${Date.now()}`,
}])
}
}
}
if (data.status == 0) {
Taro.setNavigationBarTitle({
title: '安装设备'
@@ -326,11 +470,90 @@ const Query = () => {
name="image"
required
rules={[{message: '请上传照片'}]}
onClick={takePhoto}
>
<div style={{display: 'flex', flexDirection: 'column', gap: '10px'}}>
<Image src={FormData.image} mode={'scaleToFill'}
radius="10%" width="80" height="80"/>
<div style={{
display: 'flex',
flexWrap: 'wrap',
gap: '12px',
padding: '8px 0'
}}>
{/* 显示已上传的图片 */}
{fileList.map((file) => (
<div key={file.uid} style={{
position: 'relative',
width: '80px',
height: '80px',
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: '20px',
height: '20px',
borderRadius: '10px',
fontSize: '12px',
minWidth: '20px',
padding: 0,
lineHeight: '20px'
}}
onClick={() => handleFileRemove(file)}
>
×
</Button>
</div>
))}
{/* 添加图片按钮 */}
{fileList.length < 5 && (
<div
onClick={handleChooseImage}
style={{
width: '80px',
height: '80px',
borderRadius: '8px',
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
border: '2px dashed #d9d9d9',
backgroundColor: '#fafafa',
cursor: 'pointer'
}}
>
<span style={{fontSize: '20px', color: '#d9d9d9'}}>+</span>
<span style={{fontSize: '10px', marginTop: '2px', color: '#666'}}>
</span>
</div>
)}
{/* 显示上传数量提示 */}
{fileList.length > 0 && (
<div style={{
width: '100%',
fontSize: '12px',
color: '#52c41a',
textAlign: 'center',
marginTop: '4px'
}}>
{fileList.length}5
</div>
)}
</div>
</Form.Item>
@@ -349,7 +572,36 @@ const Query = () => {
{/* 已安装 */}
{FormData?.status == 1 ? (
<div className={'car-info w-full bg-white'}>
<Image src={FormData?.image} mode={'aspectFit'} width={'100%'} height={'300px'}/>
{/* 显示多张图片 */}
<div style={{
display: 'flex',
flexWrap: 'wrap',
gap: '8px',
padding: '16px',
justifyContent: 'center'
}}>
<ImagePreview
autoPlay
// @ts-ignore
images={fileList}
visible={showPreview}
onClose={() => setShowPreview(false)}
/>
<Swiper defaultValue={1} autoPlay indicator>
{fileList.map((item) => (
// @ts-ignore
<Swiper.Item key={item}>
<Image
width="100%"
height="100%"
mode={'aspectFit'}
onClick={() => setShowPreview(true)}
src={item.url}
/>
</Swiper.Item>
))}
</Swiper>
</div>
<div className={'px-2'}>
<Cell className={'car-info-item-title'} onClick={() => copyText(`${FormData?.code}`)}>
{FormData?.code}
@@ -372,11 +624,11 @@ const Query = () => {
<Cell className={'car-info-item-content'}>
{FormData.fenceName}
</Cell>
<div className={'flex justify-around'}>
<div className={'flex justify-around py-4'}>
<Button nativeType="submit" type="info" onClick={
() => {
Taro.navigateTo({
url: `/hjm/location?id=${FormData?.id}`
url: `/hjm/location?id=${FormData?.code}`
})
}
}>
@@ -385,7 +637,7 @@ const Query = () => {
<Button nativeType="submit" type="warning" onClick={
() => {
Taro.navigateTo({
url: `/hjm/trajectory/trajectory?id=${FormData?.id}`
url: `/hjm/trajectory/trajectory?id=${FormData?.code}`
})
}
}>

View File

@@ -2,7 +2,7 @@ import {useEffect, useState} from "react";
import {Map} from '@tarojs/components'
import Taro, {useRouter} from '@tarojs/taro'
import {DatePicker, Button, type PickerOption} from '@nutui/nutui-react-taro'
import {getHjmCar, getHjmCarByCode} from "@/api/hjm/hjmCar";
import {getHjmCarByCode} from "@/api/hjm/hjmCar";
import {HjmCar} from "@/api/hjm/hjmCar/model";
import './trajectory.scss'
import {pageHjmGpsLog} from "@/api/hjm/hjmGpsLog";
@@ -119,7 +119,7 @@ const Location = () => {
}
const reload = () => {
const id = Number(params.id);
const code = params.id;
setScale(16)
// 执行搜索
if (keywords) {
@@ -144,8 +144,8 @@ const Location = () => {
return false;
}
// 获取车辆信息
if (id) {
getHjmCar(id).then(data => {
if (code) {
getHjmCarByCode(code).then(data => {
setItem(data)
setLatitude(data.latitude)
setLongitude(data.longitude)