完成:黄家明项目的开发并存档
This commit is contained in:
@@ -52,6 +52,8 @@ export interface HjmCar {
|
||||
address?: string,
|
||||
// 用户ID
|
||||
userId?: number;
|
||||
// 认领状态
|
||||
claim?: number;
|
||||
// 排序(数字越小越靠前)
|
||||
sortNumber?: number;
|
||||
// 备注
|
||||
|
||||
101
src/api/hjm/hjmViolation/index.ts
Normal file
101
src/api/hjm/hjmViolation/index.ts
Normal file
@@ -0,0 +1,101 @@
|
||||
import request from '@/utils/request';
|
||||
import type { ApiResult, PageResult } from '@/api/index';
|
||||
import type { HjmViolation, HjmViolationParam } from './model';
|
||||
|
||||
/**
|
||||
* 分页查询黄家明_违章记录
|
||||
*/
|
||||
export async function pageHjmViolation(params: HjmViolationParam) {
|
||||
const res = await request.get<ApiResult<PageResult<HjmViolation>>>(
|
||||
'/hjm/hjm-violation/page',
|
||||
params
|
||||
);
|
||||
if (res.code === 0) {
|
||||
return res.data;
|
||||
}
|
||||
return Promise.reject(new Error(res.message));
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询黄家明_违章记录列表
|
||||
*/
|
||||
export async function listHjmViolation(params?: HjmViolationParam) {
|
||||
const res = await request.get<ApiResult<HjmViolation[]>>(
|
||||
'/hjm/hjm-violation',
|
||||
params
|
||||
);
|
||||
if (res.code === 0 && res.data) {
|
||||
return res.data;
|
||||
}
|
||||
return Promise.reject(new Error(res.message));
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加黄家明_违章记录
|
||||
*/
|
||||
export async function addHjmViolation(data: HjmViolation) {
|
||||
const res = await request.post<ApiResult<unknown>>(
|
||||
'/hjm/hjm-violation',
|
||||
data
|
||||
);
|
||||
if (res.code === 0) {
|
||||
return res.message;
|
||||
}
|
||||
return Promise.reject(new Error(res.message));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改黄家明_违章记录
|
||||
*/
|
||||
export async function updateHjmViolation(data: HjmViolation) {
|
||||
const res = await request.put<ApiResult<unknown>>(
|
||||
'/hjm/hjm-violation',
|
||||
data
|
||||
);
|
||||
if (res.code === 0) {
|
||||
return res.message;
|
||||
}
|
||||
return Promise.reject(new Error(res.message));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除黄家明_违章记录
|
||||
*/
|
||||
export async function removeHjmViolation(id?: number) {
|
||||
const res = await request.del<ApiResult<unknown>>(
|
||||
'/hjm/hjm-violation/' + id
|
||||
);
|
||||
if (res.code === 0) {
|
||||
return res.message;
|
||||
}
|
||||
return Promise.reject(new Error(res.message));
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除黄家明_违章记录
|
||||
*/
|
||||
export async function removeBatchHjmViolation(data: (number | undefined)[]) {
|
||||
const res = await request.del<ApiResult<unknown>>(
|
||||
'/hjm/hjm-violation/batch',
|
||||
{
|
||||
data
|
||||
}
|
||||
);
|
||||
if (res.code === 0) {
|
||||
return res.message;
|
||||
}
|
||||
return Promise.reject(new Error(res.message));
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据id查询黄家明_违章记录
|
||||
*/
|
||||
export async function getHjmViolation(id: number) {
|
||||
const res = await request.get<ApiResult<HjmViolation>>(
|
||||
'/hjm/hjm-violation/' + id
|
||||
);
|
||||
if (res.code === 0 && res.data) {
|
||||
return res.data;
|
||||
}
|
||||
return Promise.reject(new Error(res.message));
|
||||
}
|
||||
43
src/api/hjm/hjmViolation/model/index.ts
Normal file
43
src/api/hjm/hjmViolation/model/index.ts
Normal file
@@ -0,0 +1,43 @@
|
||||
import type { PageParam } from '@/api/index';
|
||||
|
||||
/**
|
||||
* 黄家明_违章记录
|
||||
*/
|
||||
export interface HjmViolation {
|
||||
// 自增ID
|
||||
id?: number;
|
||||
// 车辆编号
|
||||
code?: string;
|
||||
// 标题
|
||||
title?: string;
|
||||
// 文章分类ID
|
||||
categoryId?: number;
|
||||
// 处罚金额
|
||||
money?: string;
|
||||
// 扣分
|
||||
score?: string;
|
||||
// 录入员
|
||||
adminId?: number;
|
||||
// 用户ID
|
||||
userId?: number;
|
||||
// 排序(数字越小越靠前)
|
||||
sortNumber?: number;
|
||||
// 备注
|
||||
comments?: string;
|
||||
// 状态, 0未处理, 1已处理
|
||||
status?: number;
|
||||
// 租户id
|
||||
tenantId?: number;
|
||||
// 创建时间
|
||||
createTime?: string;
|
||||
// 修改时间
|
||||
updateTime?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 黄家明_违章记录搜索条件
|
||||
*/
|
||||
export interface HjmViolationParam extends PageParam {
|
||||
id?: number;
|
||||
keywords?: string;
|
||||
}
|
||||
@@ -15,7 +15,8 @@ export default defineAppConfig({
|
||||
"register",
|
||||
"forget",
|
||||
"setting",
|
||||
"agreement"
|
||||
"agreement",
|
||||
"sms-login"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -34,7 +35,8 @@ export default defineAppConfig({
|
||||
"company/company",
|
||||
"profile/profile",
|
||||
"setting/setting",
|
||||
"userVerify/index"
|
||||
"userVerify/index",
|
||||
"userVerify/admin"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -48,6 +50,8 @@ export default defineAppConfig({
|
||||
"exam/exam",
|
||||
"bx/bx",
|
||||
"bx/bx-add",
|
||||
"violation/add",
|
||||
"violation/list",
|
||||
"trajectory/trajectory",
|
||||
"gps-log/gps-log"
|
||||
// "bx/bx-list",
|
||||
|
||||
@@ -21,7 +21,7 @@ const List = () => {
|
||||
|
||||
const reload = () => {
|
||||
// 搜索条件
|
||||
const where = {status: 1,deleted: 0, keywords}
|
||||
const where = {status: 1, deleted: 0, keywords}
|
||||
// 判断身份
|
||||
const roleCode = Taro.getStorageSync('RoleCode');
|
||||
if(roleCode == 'kuaidiyuan'){
|
||||
@@ -33,8 +33,13 @@ const List = () => {
|
||||
where.organizationId = Taro.getStorageSync('OrganizationId');
|
||||
}
|
||||
if(roleCode == 'kuaidi'){
|
||||
if(Taro.getStorageSync('OrganizationId') == Taro.getStorageSync('OrganizationParentId')){
|
||||
// @ts-ignore
|
||||
where.organizationParentId = Taro.getStorageSync('OrganizationParentId');
|
||||
}else {
|
||||
// @ts-ignore
|
||||
where.organizationId = Taro.getStorageSync('OrganizationId');
|
||||
}
|
||||
}
|
||||
|
||||
// 获取车辆列表
|
||||
|
||||
@@ -115,7 +115,7 @@ const Query = () => {
|
||||
title: '请上传车辆图片',
|
||||
icon: 'error'
|
||||
});
|
||||
// return false
|
||||
return false
|
||||
}
|
||||
if (!FormData.gpsNo) {
|
||||
Taro.showToast({
|
||||
@@ -130,7 +130,7 @@ const Query = () => {
|
||||
...FormData,
|
||||
status: 1
|
||||
}).then(() => {
|
||||
Taro.showToast({title: `绑定成功`, icon: 'success'})
|
||||
Taro.showToast({title: `安装成功`, icon: 'success'})
|
||||
setTimeout(() => {
|
||||
return Taro.navigateBack()
|
||||
}, 1000)
|
||||
@@ -311,7 +311,7 @@ const Query = () => {
|
||||
const onClaimVehicle = () => {
|
||||
updateHjmCar({
|
||||
...FormData,
|
||||
status: 2,
|
||||
claim: 1,
|
||||
driverId: Taro.getStorageSync('UserId'),
|
||||
driverName: Taro.getStorageSync('RealName')
|
||||
}).then(() => {
|
||||
@@ -361,6 +361,7 @@ const Query = () => {
|
||||
return false
|
||||
}
|
||||
|
||||
|
||||
// 4.查询角色
|
||||
const role = await listUserRole({userId: Taro.getStorageSync('UserId')})
|
||||
const roleCode = role[0].roleCode;
|
||||
@@ -394,9 +395,15 @@ const Query = () => {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 1.符合条件则由安装人员安装车辆,否则提示无权限
|
||||
console.log(roleCode,'roleCode..')
|
||||
// 1.已认领则展示车辆
|
||||
if (carInfo.status == 2) {
|
||||
setClaimVehicle(false)
|
||||
Taro.setNavigationBarTitle({
|
||||
title: '车辆信息'
|
||||
})
|
||||
return false
|
||||
}
|
||||
// 2.符合条件则由安装人员安装车辆,否则提示无权限
|
||||
if (carInfo.status == 0 && roleCode != 'Installer') {
|
||||
Taro.setNavigationBarTitle({
|
||||
title: '安装设备'
|
||||
@@ -408,24 +415,29 @@ const Query = () => {
|
||||
setDisabled(true)
|
||||
return false
|
||||
}
|
||||
// 2.如果已安装,则判断是否已认领车辆
|
||||
// 3.如果已安装,则判断是否已认领车辆
|
||||
if (carInfo.status == 1 && roleCode == 'kuaidiyuan') {
|
||||
// 2.1先查询名下有多少辆车
|
||||
const carCount = await pageHjmCar({driverId: Taro.getStorageSync('UserId')})
|
||||
if (carCount?.count && carCount?.count == 0) {
|
||||
if (carCount?.count == 0) {
|
||||
// 2.2无车辆则认领
|
||||
setClaimVehicle(true)
|
||||
Taro.setNavigationBarTitle({
|
||||
title: '认领车辆'
|
||||
})
|
||||
} else {
|
||||
// 2.3存在车辆则展示车辆信息
|
||||
setClaimVehicle(false)
|
||||
Taro.setNavigationBarTitle({
|
||||
title: '车辆信息'
|
||||
})
|
||||
}
|
||||
return false
|
||||
}
|
||||
// if(carInfo.status == 1 && Taro.getStorageSync('UserId') != carInfo.driverId){
|
||||
// Taro.showToast({
|
||||
// title: '暂无权限',
|
||||
// icon: 'error'
|
||||
// })
|
||||
// setTimeout(() => {
|
||||
// Taro.navigateBack()
|
||||
// },2000)
|
||||
// return false
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -448,6 +460,8 @@ const Query = () => {
|
||||
})
|
||||
}, [])
|
||||
|
||||
// @ts-ignore
|
||||
// @ts-ignore
|
||||
return (
|
||||
<>
|
||||
{/* 未安装 */}
|
||||
@@ -539,10 +553,11 @@ const Query = () => {
|
||||
onChange={(value) => setFormData({...FormData, gpsNo: value})}
|
||||
/>
|
||||
<div
|
||||
className="right"
|
||||
className="right p-1"
|
||||
style={{display: 'flex', alignItems: 'center'}}
|
||||
onClick={saveGpsNo}
|
||||
>
|
||||
<Scan onClick={saveGpsNo}/>
|
||||
<Scan />
|
||||
</div>
|
||||
</div>
|
||||
</Form.Item>
|
||||
@@ -637,7 +652,6 @@ const Query = () => {
|
||||
)}
|
||||
</div>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
label={'操作员'}
|
||||
name="driver"
|
||||
@@ -648,10 +662,7 @@ const Query = () => {
|
||||
</Form>
|
||||
</div>
|
||||
</div>
|
||||
) : ''}
|
||||
|
||||
{/* 已安装 */}
|
||||
{FormData?.status != 0 ? (
|
||||
) : (
|
||||
<div className={'car-info w-full bg-white'}>
|
||||
{/* 显示多张图片 */}
|
||||
<div style={{
|
||||
@@ -705,6 +716,9 @@ const Query = () => {
|
||||
<Cell className={'car-info-item-content'}>
|
||||
电子围栏:{FormData.fenceName}
|
||||
</Cell>
|
||||
<Cell className={'car-info-item-content'}>
|
||||
安装状态:{FormData.status == 2 ? '已绑定' : '未绑定'}
|
||||
</Cell>
|
||||
<Cell className={'car-info-item-content'}>
|
||||
操作员:{FormData.status == 2 ? FormData.driver : '-'}
|
||||
</Cell>
|
||||
@@ -754,7 +768,7 @@ const Query = () => {
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
) : ''}
|
||||
)}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
3
src/hjm/violation/add.config.ts
Normal file
3
src/hjm/violation/add.config.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export default definePageConfig({
|
||||
navigationBarTitleText: '添加违章记录'
|
||||
})
|
||||
244
src/hjm/violation/add.tsx
Normal file
244
src/hjm/violation/add.tsx
Normal file
@@ -0,0 +1,244 @@
|
||||
import {useEffect, useState} from "react";
|
||||
import Taro from '@tarojs/taro'
|
||||
import {
|
||||
Button,
|
||||
TextArea,
|
||||
Cell,
|
||||
Input,
|
||||
} from '@nutui/nutui-react-taro'
|
||||
import {addHjmViolation} from "@/api/hjm/hjmViolation";
|
||||
import {HjmViolation} from "@/api/hjm/hjmViolation/model";
|
||||
|
||||
/**
|
||||
* 添加违章记录页面
|
||||
*/
|
||||
function Add() {
|
||||
const [loading, setLoading] = useState<boolean>(false)
|
||||
const [lastSubmitTime, setLastSubmitTime] = useState<number>(0) // 最后提交时间
|
||||
const [formData, setFormData] = useState<HjmViolation>({
|
||||
code: '',
|
||||
title: '',
|
||||
money: '',
|
||||
score: '',
|
||||
comments: ''
|
||||
})
|
||||
|
||||
// 初始化页面数据
|
||||
const initPageData = async () => {
|
||||
try {
|
||||
setLoading(false)
|
||||
} catch (error) {
|
||||
console.error('初始化失败:', error)
|
||||
Taro.showToast({
|
||||
title: '初始化失败',
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 提交表单
|
||||
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.code?.trim()) {
|
||||
Taro.showToast({
|
||||
title: '请输入车辆编号',
|
||||
icon: 'none'
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
if (!formData.title?.trim()) {
|
||||
Taro.showToast({
|
||||
title: '请输入违章标题',
|
||||
icon: 'none'
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// if (!formData.money?.trim()) {
|
||||
// Taro.showToast({
|
||||
// title: '请输入处罚金额',
|
||||
// icon: 'none'
|
||||
// })
|
||||
// return
|
||||
// }
|
||||
//
|
||||
// if (!formData.score?.trim()) {
|
||||
// Taro.showToast({
|
||||
// title: '请输入扣分',
|
||||
// icon: 'none'
|
||||
// })
|
||||
// return
|
||||
// }
|
||||
|
||||
setLoading(true)
|
||||
|
||||
// 构建提交数据
|
||||
const submitData: HjmViolation = {
|
||||
...formData,
|
||||
status: 0 // 0未处理, 1已处理
|
||||
}
|
||||
|
||||
addHjmViolation(submitData).then((res) => {
|
||||
console.log(res)
|
||||
Taro.showToast({
|
||||
title: '提交成功',
|
||||
icon: 'success'
|
||||
})
|
||||
// 清空表单
|
||||
setFormData({
|
||||
code: '',
|
||||
title: '',
|
||||
money: '',
|
||||
score: '',
|
||||
comments: ''
|
||||
})
|
||||
|
||||
setTimeout(() => {
|
||||
Taro.navigateBack()
|
||||
}, 2000)
|
||||
}).finally(() => {
|
||||
setLoading(false)
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
initPageData().then(r => {
|
||||
console.log(r, 'rr')
|
||||
})
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<div style={{
|
||||
backgroundColor: '#f5f5f5',
|
||||
minHeight: '100vh',
|
||||
paddingBottom: '80px'
|
||||
}}>
|
||||
{/* 页面标题 */}
|
||||
{/*<div style={{*/}
|
||||
{/* backgroundColor: '#fff',*/}
|
||||
{/* margin: '16px',*/}
|
||||
{/* borderRadius: '12px',*/}
|
||||
{/* padding: '16px',*/}
|
||||
{/* boxShadow: '0 2px 8px rgba(0,0,0,0.06)'*/}
|
||||
{/*}}>*/}
|
||||
{/* <div style={{*/}
|
||||
{/* display: 'flex',*/}
|
||||
{/* alignItems: 'center',*/}
|
||||
{/* gap: '8px',*/}
|
||||
{/* marginBottom: '12px'*/}
|
||||
{/* }}>*/}
|
||||
{/* <Truck size={18} color="#1890ff"/>*/}
|
||||
{/* <span style={{fontSize: '16px', fontWeight: 'bold'}}>添加违章记录</span>*/}
|
||||
{/* </div>*/}
|
||||
{/*</div>*/}
|
||||
|
||||
|
||||
{/* 违章信息表单 */}
|
||||
<div style={{
|
||||
backgroundColor: '#fff',
|
||||
margin: '16px 16px 16px',
|
||||
borderRadius: '12px',
|
||||
overflow: 'hidden'
|
||||
}}>
|
||||
<div style={{
|
||||
padding: '16px',
|
||||
borderBottom: '1px solid #f0f0f0'
|
||||
}}>
|
||||
<span style={{fontSize: '16px', fontWeight: 'bold'}}>违章信息</span>
|
||||
</div>
|
||||
<Cell.Group>
|
||||
<Cell title="车辆编号" style={{padding: '12px 16px'}}>
|
||||
<Input
|
||||
placeholder="YT000001"
|
||||
value={formData.code}
|
||||
onChange={(value) => setFormData({...formData, code: value})}
|
||||
style={{backgroundColor: '#ffffff', borderRadius: '8px'}}
|
||||
/>
|
||||
</Cell>
|
||||
<Cell title="违章标题" style={{padding: '12px 16px'}}>
|
||||
<Input
|
||||
placeholder="不按规定停车"
|
||||
value={formData.title}
|
||||
onChange={(value) => setFormData({...formData, title: value})}
|
||||
style={{backgroundColor: '#ffffff', borderRadius: '8px'}}
|
||||
/>
|
||||
</Cell>
|
||||
<Cell title="违章描述" style={{padding: '12px 16px'}}>
|
||||
<TextArea
|
||||
placeholder={'XX路1号...'}
|
||||
value={formData.comments}
|
||||
onChange={(value) => setFormData({...formData, comments: value})}
|
||||
style={{backgroundColor: '#ffffff', borderRadius: '8px'}}
|
||||
/>
|
||||
</Cell>
|
||||
<Cell title="处罚金额" style={{padding: '12px 16px'}}>
|
||||
<Input
|
||||
type="number"
|
||||
placeholder="200(元)"
|
||||
maxLength={3}
|
||||
value={formData.money}
|
||||
onChange={(value) => setFormData({...formData, money: value})}
|
||||
style={{backgroundColor: '#ffffff', borderRadius: '8px'}}
|
||||
/>
|
||||
</Cell>
|
||||
<Cell title="扣分" style={{padding: '12px 16px'}}>
|
||||
<Input
|
||||
type="number"
|
||||
maxLength={2}
|
||||
placeholder="2(分)"
|
||||
value={formData.score}
|
||||
onChange={(value) => setFormData({...formData, score: value})}
|
||||
style={{backgroundColor: '#ffffff', borderRadius: '8px'}}
|
||||
/>
|
||||
</Cell>
|
||||
</Cell.Group>
|
||||
</div>
|
||||
|
||||
{/* 提交按钮 */}
|
||||
<div style={{
|
||||
position: 'fixed',
|
||||
bottom: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
backgroundColor: '#fff',
|
||||
padding: '16px',
|
||||
borderTop: '1px solid #f0f0f0'
|
||||
}}>
|
||||
<Button
|
||||
type="primary"
|
||||
block
|
||||
loading={loading}
|
||||
disabled={loading}
|
||||
onClick={handleSubmit}
|
||||
>
|
||||
{loading ? '提交中...' : '提交违章记录'}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Add
|
||||
3
src/hjm/violation/list.config.ts
Normal file
3
src/hjm/violation/list.config.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export default definePageConfig({
|
||||
navigationBarTitleText: '违章记录'
|
||||
})
|
||||
260
src/hjm/violation/list.tsx
Normal file
260
src/hjm/violation/list.tsx
Normal file
@@ -0,0 +1,260 @@
|
||||
import React, {useEffect, useState} from "react";
|
||||
import {
|
||||
Loading,
|
||||
Empty,
|
||||
Button,
|
||||
Input,
|
||||
Tag,
|
||||
Space
|
||||
} from '@nutui/nutui-react-taro'
|
||||
import {Search, Calendar, Truck, File, AddCircle} from '@nutui/icons-react-taro'
|
||||
import Taro from '@tarojs/taro'
|
||||
import {pageHjmViolation} from "@/api/hjm/hjmViolation";
|
||||
import {HjmViolation} from "@/api/hjm/hjmViolation/model";
|
||||
|
||||
|
||||
/**
|
||||
* 报险记录列表页面
|
||||
*/
|
||||
const List: React.FC = () => {
|
||||
const [list, setList] = useState<HjmViolation[]>([])
|
||||
const [loading, setLoading] = useState<boolean>(false)
|
||||
const [keywords, setKeywords] = useState<string>('')
|
||||
const [refreshing, setRefreshing] = useState<boolean>(false)
|
||||
console.log(refreshing)
|
||||
// 获取状态显示
|
||||
const getStatusDisplay = (status?: number) => {
|
||||
switch (status) {
|
||||
case 0:
|
||||
return {text: '未处理', color: '#faad14', bgColor: '#fffbe6'}
|
||||
case 1:
|
||||
return {text: '已处理', color: '#52c41a', bgColor: '#f6ffed'}
|
||||
case 2:
|
||||
return {text: '已驳回', color: '#ff4d4f', bgColor: '#fff2f0'}
|
||||
default:
|
||||
return {text: '未知', color: '#8c8c8c', bgColor: '#f5f5f5'}
|
||||
}
|
||||
}
|
||||
|
||||
const reload = async (showLoading = true) => {
|
||||
try {
|
||||
if (showLoading) setLoading(true)
|
||||
setRefreshing(true)
|
||||
|
||||
const res = await pageHjmViolation({
|
||||
keywords: keywords.trim(),
|
||||
})
|
||||
|
||||
setList(res?.list || [])
|
||||
} catch (error) {
|
||||
console.error('获取报险记录失败:', error)
|
||||
Taro.showToast({
|
||||
title: '获取报险记录失败',
|
||||
icon: 'error'
|
||||
})
|
||||
} finally {
|
||||
setLoading(false)
|
||||
setRefreshing(false)
|
||||
}
|
||||
}
|
||||
|
||||
const onSearch = () => {
|
||||
reload()
|
||||
}
|
||||
|
||||
const onKeywordsChange = (value: string) => {
|
||||
setKeywords(value)
|
||||
}
|
||||
|
||||
const onAddInsurance = () => {
|
||||
Taro.navigateTo({
|
||||
url: '/hjm/violation/add'
|
||||
})
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
reload().then()
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<>
|
||||
{/* 搜索栏 */}
|
||||
<div style={{
|
||||
position: 'fixed',
|
||||
top: '20px',
|
||||
left: 0,
|
||||
right: 0,
|
||||
display: "none",
|
||||
zIndex: 20,
|
||||
padding: '0 16px',
|
||||
backgroundColor: '#f5f5f5'
|
||||
}}>
|
||||
<div style={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
backgroundColor: '#fff',
|
||||
padding: '8px 12px',
|
||||
borderRadius: '20px',
|
||||
boxShadow: '0 2px 8px rgba(0,0,0,0.1)'
|
||||
}}>
|
||||
<Search size={16} color="#999"/>
|
||||
<Input
|
||||
placeholder="搜索报险记录"
|
||||
value={keywords}
|
||||
onChange={onKeywordsChange}
|
||||
onConfirm={onSearch}
|
||||
style={{
|
||||
border: 'none',
|
||||
backgroundColor: 'transparent',
|
||||
flex: 1,
|
||||
marginLeft: '8px'
|
||||
}}
|
||||
/>
|
||||
<Button
|
||||
type="primary"
|
||||
size="small"
|
||||
onClick={onSearch}
|
||||
loading={loading}
|
||||
>
|
||||
搜索
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 报险记录列表 */}
|
||||
<div style={{
|
||||
marginTop: '10px',
|
||||
paddingBottom: '80px'
|
||||
}}>
|
||||
{loading && list.length === 0 ? (
|
||||
<div style={{
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
height: '200px'
|
||||
}}>
|
||||
<Loading type="spinner">加载中...</Loading>
|
||||
</div>
|
||||
) : list.length === 0 ? (
|
||||
<Empty description="暂无报险记录">
|
||||
<Button type="primary" onClick={onAddInsurance}>
|
||||
立即报险
|
||||
</Button>
|
||||
</Empty>
|
||||
) : (
|
||||
<div style={{padding: '0 16px'}}>
|
||||
{list.map((item, index) => {
|
||||
const statusDisplay = getStatusDisplay(item.status)
|
||||
|
||||
return (
|
||||
<div
|
||||
key={index}
|
||||
style={{
|
||||
backgroundColor: '#fff',
|
||||
borderRadius: '12px',
|
||||
padding: '16px',
|
||||
marginBottom: '12px',
|
||||
boxShadow: '0 2px 8px rgba(0,0,0,0.06)',
|
||||
border: '1px solid #f0f0f0'
|
||||
}}
|
||||
>
|
||||
<div style={{
|
||||
display: 'flex',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'flex-start',
|
||||
marginBottom: '12px'
|
||||
}}>
|
||||
<div style={{flex: 1}}>
|
||||
<div style={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
gap: '8px',
|
||||
marginBottom: '8px'
|
||||
}}>
|
||||
<File size={16} color="#1890ff"/>
|
||||
<span style={{
|
||||
fontSize: '16px',
|
||||
fontWeight: 'bold',
|
||||
color: '#262626'
|
||||
}}>
|
||||
{item.title}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<Space direction="vertical">
|
||||
<div style={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
gap: '8px'
|
||||
}}>
|
||||
<Truck size={14} color="#8c8c8c"/>
|
||||
<span style={{fontSize: '13px', color: '#8c8c8c'}}>
|
||||
车辆编号:{item.code}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div style={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
gap: '8px'
|
||||
}}>
|
||||
<Calendar size={14} color="#8c8c8c"/>
|
||||
<span style={{fontSize: '13px', color: '#8c8c8c'}}>
|
||||
提交时间:{item.createTime}
|
||||
</span>
|
||||
</div>
|
||||
</Space>
|
||||
</div>
|
||||
|
||||
<Tag
|
||||
color={statusDisplay.color}
|
||||
style={{
|
||||
backgroundColor: statusDisplay.bgColor,
|
||||
border: `1px solid ${statusDisplay.color}`,
|
||||
fontSize: '12px'
|
||||
}}
|
||||
>
|
||||
{statusDisplay.text}
|
||||
</Tag>
|
||||
</div>
|
||||
|
||||
{/* 备注信息 */}
|
||||
{item.comments && (
|
||||
<div style={{
|
||||
backgroundColor: '#f8f9fa',
|
||||
padding: '8px 12px',
|
||||
borderRadius: '6px',
|
||||
fontSize: '13px',
|
||||
color: '#595959',
|
||||
lineHeight: '1.4'
|
||||
}}>
|
||||
{item.comments.length > 50
|
||||
? `${item.comments.substring(0, 50)}...`
|
||||
: item.comments
|
||||
}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div style={{
|
||||
position: 'fixed',
|
||||
bottom: '20px',
|
||||
right: '20px',
|
||||
zIndex: 30,
|
||||
padding: '8px',
|
||||
borderRadius: '20px',
|
||||
overflow: "hidden",
|
||||
backgroundColor: '#ff0000',
|
||||
}}>
|
||||
<AddCircle size={28} color={'#ffffff'} onClick={onAddInsurance} />
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default List
|
||||
@@ -39,6 +39,12 @@ const ExpirationTime = () => {
|
||||
if(data.certification){
|
||||
setIsAdmin( true)
|
||||
}
|
||||
if(Taro.getStorageSync('certification') == 'jj'){
|
||||
setIsAdmin(true)
|
||||
}
|
||||
if(Taro.getStorageSync('certification') == 'yz'){
|
||||
setIsAdmin(true)
|
||||
}
|
||||
data.roles?.map((item, index) => {
|
||||
if (index == 0) {
|
||||
setRoleName(item.roleCode)
|
||||
|
||||
@@ -65,6 +65,7 @@ const Header = (props: any) => {
|
||||
setRoleName('交警')
|
||||
Taro.setStorageSync('RoleName', '交警')
|
||||
Taro.setStorageSync('RoleCode', 'jiaojing')
|
||||
Taro.setStorageSync('certification', 'jj')
|
||||
return false;
|
||||
}
|
||||
// 邮政协会/管局
|
||||
@@ -73,6 +74,7 @@ const Header = (props: any) => {
|
||||
setRoleName('邮政协会/管局')
|
||||
Taro.setStorageSync('RoleName', '邮政协会/管局')
|
||||
Taro.setStorageSync('RoleCode', 'youzheng')
|
||||
Taro.setStorageSync('certification', 'yz')
|
||||
return false;
|
||||
}
|
||||
// 快递公司
|
||||
|
||||
@@ -116,16 +116,15 @@ function Home() {
|
||||
setLongitude(res.longitude)
|
||||
}
|
||||
|
||||
console.log(Taro.getStorageSync('RoleName'))
|
||||
// 已认证用户
|
||||
if(Taro.getStorageSync('Certification')){
|
||||
if (Taro.getStorageSync('certification')) {
|
||||
setIsAdmin(true)
|
||||
setScale(11)
|
||||
pageHjmCarByMap(res.latitude,res.longitude)
|
||||
pageHjmCarByMap(res.latitude, res.longitude)
|
||||
}
|
||||
|
||||
// 游客
|
||||
if(!Taro.getStorageSync('access_token') || Taro.getStorageSync('RoleName') == '注册用户'){
|
||||
if (!Taro.getStorageSync('access_token') || Taro.getStorageSync('RoleName') == '注册用户') {
|
||||
setScale(15)
|
||||
const arr = []
|
||||
// @ts-ignore
|
||||
@@ -145,7 +144,7 @@ function Home() {
|
||||
}
|
||||
|
||||
const onQuery = () => {
|
||||
if(!keywords){
|
||||
if (!keywords) {
|
||||
Taro.showToast({
|
||||
title: '请输入关键字',
|
||||
icon: 'none'
|
||||
@@ -155,36 +154,36 @@ function Home() {
|
||||
reload();
|
||||
}
|
||||
|
||||
const pageHjmCarByMap = (latitude?: any,longitude?: any) => {
|
||||
const pageHjmCarByMap = (latitude?: any, longitude?: any) => {
|
||||
// 搜索条件
|
||||
const where = {}
|
||||
|
||||
if(latitude){
|
||||
if (latitude) {
|
||||
// @ts-ignore
|
||||
where.latitude = latitude
|
||||
}
|
||||
if(longitude){
|
||||
if (longitude) {
|
||||
// @ts-ignore
|
||||
where.longitude = longitude
|
||||
}
|
||||
// 判断身份
|
||||
const roleCode = Taro.getStorageSync('RoleCode');
|
||||
if(roleCode == 'kuaidiyuan'){
|
||||
if (roleCode == 'kuaidiyuan') {
|
||||
// @ts-ignore
|
||||
where.driverId = Taro.getStorageSync('UserId')
|
||||
}
|
||||
if(roleCode == 'zhandian'){
|
||||
if (roleCode == 'zhandian') {
|
||||
// @ts-ignore
|
||||
where.organizationId = Taro.getStorageSync('OrganizationId');
|
||||
}
|
||||
if(roleCode == 'kuaidi'){
|
||||
if (roleCode == 'kuaidi') {
|
||||
// @ts-ignore
|
||||
where.organizationParentId = Taro.getStorageSync('OrganizationParentId');
|
||||
}
|
||||
|
||||
pageByQQMap(where).then(res => {
|
||||
console.log(res,'pageByQQMap')
|
||||
if(res?.count == 0){
|
||||
console.log(res, 'pageByQQMap')
|
||||
if (res?.count == 0) {
|
||||
const arr = []
|
||||
// @ts-ignore
|
||||
arr.push({
|
||||
@@ -226,16 +225,16 @@ function Home() {
|
||||
}
|
||||
|
||||
const reload = () => {
|
||||
if(!Taro.getStorageSync('access_token')){
|
||||
if (!Taro.getStorageSync('access_token')) {
|
||||
return false;
|
||||
}
|
||||
if(!isAdmin){
|
||||
if (!isAdmin) {
|
||||
return false;
|
||||
}
|
||||
setMarkers([])
|
||||
setScale(12)
|
||||
pageHjmCar({keywords,deleted: 0}).then(res => {
|
||||
if(res?.count == 0){
|
||||
pageHjmCar({keywords, deleted: 0}).then(res => {
|
||||
if (res?.count == 0) {
|
||||
Taro.showToast({
|
||||
title: '没有搜索结果',
|
||||
icon: 'none'
|
||||
@@ -247,7 +246,7 @@ function Home() {
|
||||
const data = res?.list[0];
|
||||
setLongitude(data?.longitude)
|
||||
setLatitude(data?.latitude)
|
||||
if(isAdmin){
|
||||
if (isAdmin) {
|
||||
setMarkers([{
|
||||
id: data.id,
|
||||
latitude: data.latitude,
|
||||
@@ -268,7 +267,7 @@ function Home() {
|
||||
}])
|
||||
}
|
||||
}
|
||||
console.log(list.length,'carList.length')
|
||||
console.log(list.length, 'carList.length')
|
||||
})
|
||||
};
|
||||
|
||||
@@ -308,8 +307,12 @@ function Home() {
|
||||
getUserInfo().then((data) => {
|
||||
if (data) {
|
||||
// 是否管理员
|
||||
console.log(data.certification, 'certification')
|
||||
if(data.certification){
|
||||
if (data.certification) {
|
||||
setIsAdmin(true)
|
||||
}
|
||||
// 是否交警
|
||||
if (Taro.getStorageSync('certification') == 'jj') {
|
||||
console.log('交警', '12312')
|
||||
setIsAdmin(true)
|
||||
}
|
||||
setUserInfo(data)
|
||||
@@ -319,9 +322,12 @@ function Home() {
|
||||
if (!data.openid) {
|
||||
Taro.login({
|
||||
success: (res) => {
|
||||
// 排查交警和邮政角色不保存openid
|
||||
if (Taro.getStorageSync('RoleCode') !== 'jiaojing' || Taro.getStorageSync('RoleCode') !== 'youzheng' || Taro.getStorageSync('RoleCode') !== 'Installer') {
|
||||
getWxOpenId({code: res.code}).then(() => {
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,9 +3,10 @@ import navTo from "@/utils/common";
|
||||
import UserFooter from "./UserFooter";
|
||||
import Taro from '@tarojs/taro'
|
||||
import {ArrowRight, ShieldCheck, Truck, LogisticsError} from '@nutui/icons-react-taro'
|
||||
import {CSSProperties} from "react";
|
||||
import {CSSProperties, useEffect, useState} from "react";
|
||||
|
||||
const UserCell = () => {
|
||||
const [roleName, setRoleName] = useState<string>('')
|
||||
const InfiniteUlStyle: CSSProperties = {
|
||||
height: '88vh',
|
||||
padding: '16px',
|
||||
@@ -30,6 +31,10 @@ const UserCell = () => {
|
||||
})
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
setRoleName(Taro.getStorageSync('RoleCode'))
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<>
|
||||
<div style={InfiniteUlStyle} id="scroll">
|
||||
@@ -50,6 +55,29 @@ const UserCell = () => {
|
||||
}}
|
||||
/>
|
||||
</Cell.Group>
|
||||
{
|
||||
roleName === 'kuaidi' && (
|
||||
<Cell.Group divider={true}>
|
||||
<Cell
|
||||
className="nutui-cell-clickable"
|
||||
title={
|
||||
<div style={{display: 'inline-flex', alignItems: 'center'}}>
|
||||
<ShieldCheck size={16}/>
|
||||
<span className={'pl-3 text-sm'}>实名认证审核</span>
|
||||
</div>
|
||||
}
|
||||
align="center"
|
||||
extra={<ArrowRight color="#cccccc" size={18}/>}
|
||||
onClick={() => {
|
||||
navTo('/user/userVerify/admin', true)
|
||||
}}
|
||||
/>
|
||||
</Cell.Group>
|
||||
)
|
||||
}
|
||||
{
|
||||
roleName === 'kuaidiyuan' && (
|
||||
<>
|
||||
<Cell.Group divider={true}>
|
||||
<Cell
|
||||
className="nutui-cell-clickable"
|
||||
@@ -82,6 +110,30 @@ const UserCell = () => {
|
||||
}}
|
||||
/>
|
||||
</Cell.Group>
|
||||
</>
|
||||
)
|
||||
}
|
||||
{
|
||||
roleName === 'jiaojing' && (
|
||||
<Cell.Group divider={true}>
|
||||
<Cell
|
||||
className="nutui-cell-clickable"
|
||||
title={
|
||||
<div style={{display: 'inline-flex', alignItems: 'center'}}>
|
||||
<Truck size={16}/>
|
||||
<span className={'pl-3 text-sm'}>违章记录</span>
|
||||
</div>
|
||||
}
|
||||
align="center"
|
||||
extra={<ArrowRight color="#cccccc" size={18}/>}
|
||||
onClick={() => {
|
||||
navTo('/hjm/violation/list', true)
|
||||
}}
|
||||
/>
|
||||
</Cell.Group>
|
||||
)
|
||||
}
|
||||
|
||||
{/*<Cell.Group divider={true} description={*/}
|
||||
{/* <div style={{display: 'inline-flex', alignItems: 'center'}}>*/}
|
||||
{/* <span style={{marginTop: '12px'}}>管理</span>*/}
|
||||
@@ -171,7 +223,14 @@ const UserCell = () => {
|
||||
title="账号安全"
|
||||
align="center"
|
||||
extra={<ArrowRight color="#cccccc" size={18}/>}
|
||||
onClick={() => navTo('/user/profile/profile',true)}
|
||||
onClick={() => navTo('/user/profile/profile', true)}
|
||||
/>
|
||||
<Cell
|
||||
className="nutui-cell-clickable"
|
||||
title="短信登录"
|
||||
align="center"
|
||||
extra={<ArrowRight color="#cccccc" size={18}/>}
|
||||
onClick={() => navTo('/passport/sms-login', true)}
|
||||
/>
|
||||
<Cell
|
||||
className="nutui-cell-clickable"
|
||||
|
||||
4
src/passport/sms-login.config.ts
Normal file
4
src/passport/sms-login.config.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
export default definePageConfig({
|
||||
navigationBarTitleText: '验证码登录',
|
||||
navigationBarTextStyle: 'black'
|
||||
})
|
||||
204
src/passport/sms-login.tsx
Normal file
204
src/passport/sms-login.tsx
Normal file
@@ -0,0 +1,204 @@
|
||||
import {useEffect, useState} from "react";
|
||||
import Taro from '@tarojs/taro'
|
||||
import {Input, Button} from '@nutui/nutui-react-taro'
|
||||
import {loginBySms, sendSmsCaptcha} from "@/api/passport/login";
|
||||
import {LoginParam} from "@/api/passport/login/model";
|
||||
|
||||
const SmsLogin = () => {
|
||||
const [loading, setLoading] = useState<boolean>(false)
|
||||
const [sendingCode, setSendingCode] = useState<boolean>(false)
|
||||
const [countdown, setCountdown] = useState<number>(0)
|
||||
const [formData, setFormData] = useState<LoginParam>({
|
||||
phone: '',
|
||||
code: ''
|
||||
})
|
||||
|
||||
const reload = () => {
|
||||
Taro.hideTabBar()
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
reload()
|
||||
}, [])
|
||||
|
||||
// 倒计时效果
|
||||
useEffect(() => {
|
||||
let timer: NodeJS.Timeout
|
||||
if (countdown > 0) {
|
||||
timer = setTimeout(() => {
|
||||
setCountdown(countdown - 1)
|
||||
}, 1000)
|
||||
}
|
||||
return () => {
|
||||
if (timer) clearTimeout(timer)
|
||||
}
|
||||
}, [countdown])
|
||||
|
||||
// 验证手机号格式
|
||||
const validatePhone = (phone: string): boolean => {
|
||||
const phoneRegex = /^1[3-9]\d{9}$/
|
||||
return phoneRegex.test(phone)
|
||||
}
|
||||
|
||||
// 发送短信验证码
|
||||
const handleSendCode = async () => {
|
||||
if (!formData.phone) {
|
||||
Taro.showToast({
|
||||
title: '请输入手机号码',
|
||||
icon: 'none'
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
if (!validatePhone(formData.phone)) {
|
||||
Taro.showToast({
|
||||
title: '请输入正确的手机号码',
|
||||
icon: 'none'
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
if (sendingCode || countdown > 0) {
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
setSendingCode(true)
|
||||
await sendSmsCaptcha({ phone: formData.phone })
|
||||
|
||||
Taro.showToast({
|
||||
title: '验证码已发送',
|
||||
icon: 'success'
|
||||
})
|
||||
|
||||
// 开始60秒倒计时
|
||||
setCountdown(60)
|
||||
} catch (error: any) {
|
||||
Taro.showToast({
|
||||
title: error.message || '发送失败',
|
||||
icon: 'error'
|
||||
})
|
||||
} finally {
|
||||
setSendingCode(false)
|
||||
}
|
||||
}
|
||||
|
||||
// 处理登录
|
||||
const handleLogin = async () => {
|
||||
// 防止重复提交
|
||||
if (loading) {
|
||||
return
|
||||
}
|
||||
|
||||
// 表单验证
|
||||
if (!formData.phone) {
|
||||
Taro.showToast({
|
||||
title: '请输入手机号码',
|
||||
icon: 'none'
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
if (!validatePhone(formData.phone)) {
|
||||
Taro.showToast({
|
||||
title: '请输入正确的手机号码',
|
||||
icon: 'none'
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
if (!formData.code) {
|
||||
Taro.showToast({
|
||||
title: '请输入验证码',
|
||||
icon: 'none'
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
if (formData.code.length !== 6) {
|
||||
Taro.showToast({
|
||||
title: '请输入6位验证码',
|
||||
icon: 'none'
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
setLoading(true)
|
||||
|
||||
await loginBySms({
|
||||
phone: formData.phone,
|
||||
code: formData.code
|
||||
})
|
||||
|
||||
Taro.showToast({
|
||||
title: '登录成功',
|
||||
icon: 'success'
|
||||
})
|
||||
|
||||
// 延迟跳转到首页
|
||||
setTimeout(() => {
|
||||
Taro.reLaunch({
|
||||
url: '/pages/index/index'
|
||||
})
|
||||
}, 1500)
|
||||
|
||||
} catch (error: any) {
|
||||
Taro.showToast({
|
||||
title: error.message || '登录失败',
|
||||
icon: 'error'
|
||||
})
|
||||
} finally {
|
||||
setLoading(false)
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className={'flex flex-col justify-center px-5 pt-3'}>
|
||||
<div className={'flex flex-col justify-between items-center my-2'}>
|
||||
<Input
|
||||
type="number"
|
||||
placeholder="请输入手机号码"
|
||||
maxLength={11}
|
||||
value={formData.phone}
|
||||
onChange={(value) => setFormData({...formData, phone: value})}
|
||||
style={{backgroundColor: '#ffffff', borderRadius: '8px'}}
|
||||
/>
|
||||
</div>
|
||||
<div className={'flex justify-between items-center bg-white rounded-lg my-2 pr-2'}>
|
||||
<Input
|
||||
type="number"
|
||||
placeholder="请输入6位验证码"
|
||||
maxLength={6}
|
||||
value={formData.code}
|
||||
onChange={(value) => setFormData({...formData, code: value})}
|
||||
style={{ backgroundColor: '#ffffff', borderRadius: '8px'}}
|
||||
/>
|
||||
<Button
|
||||
size="small"
|
||||
type={countdown > 0 ? "default" : "primary"}
|
||||
loading={sendingCode}
|
||||
disabled={sendingCode || countdown > 0}
|
||||
onClick={handleSendCode}
|
||||
>
|
||||
{countdown > 0 ? `${countdown}s` : sendingCode ? '发送中...' : '获取验证码'}
|
||||
</Button>
|
||||
</div>
|
||||
<div className={'flex justify-center my-5'}>
|
||||
<Button
|
||||
type="info"
|
||||
size={'large'}
|
||||
className={'w-full rounded-lg p-2'}
|
||||
loading={loading}
|
||||
disabled={loading}
|
||||
onClick={handleLogin}
|
||||
>
|
||||
{loading ? '登录中...' : '登录'}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
export default SmsLogin
|
||||
3
src/user/userVerify/admin.config.ts
Normal file
3
src/user/userVerify/admin.config.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export default definePageConfig({
|
||||
navigationBarTitleText: '实名认证管理'
|
||||
})
|
||||
248
src/user/userVerify/admin.tsx
Normal file
248
src/user/userVerify/admin.tsx
Normal file
@@ -0,0 +1,248 @@
|
||||
import React, {useEffect, useState} from "react";
|
||||
import {
|
||||
Loading,
|
||||
Empty,
|
||||
Button,
|
||||
Input,
|
||||
Tag,
|
||||
Space
|
||||
} from '@nutui/nutui-react-taro'
|
||||
import {Search, Calendar, Truck, File, AddCircle} from '@nutui/icons-react-taro'
|
||||
import Taro from '@tarojs/taro'
|
||||
import {pageHjmViolation} from "@/api/hjm/hjmViolation";
|
||||
import {UserVerify} from "@/api/system/userVerify/model";
|
||||
import {pageUserVerify} from "@/api/system/userVerify";
|
||||
|
||||
|
||||
/**
|
||||
* 报险记录列表页面
|
||||
*/
|
||||
const List: React.FC = () => {
|
||||
const [list, setList] = useState<UserVerify[]>([])
|
||||
const [loading, setLoading] = useState<boolean>(false)
|
||||
const [keywords, setKeywords] = useState<string>('')
|
||||
const [refreshing, setRefreshing] = useState<boolean>(false)
|
||||
console.log(refreshing)
|
||||
// 获取状态显示
|
||||
const getStatusDisplay = (status?: number) => {
|
||||
switch (status) {
|
||||
case 0:
|
||||
return {text: '未处理', color: '#faad14', bgColor: '#fffbe6'}
|
||||
case 1:
|
||||
return {text: '已处理', color: '#52c41a', bgColor: '#f6ffed'}
|
||||
case 2:
|
||||
return {text: '已驳回', color: '#ff4d4f', bgColor: '#fff2f0'}
|
||||
default:
|
||||
return {text: '未知', color: '#8c8c8c', bgColor: '#f5f5f5'}
|
||||
}
|
||||
}
|
||||
|
||||
const reload = async (showLoading = true) => {
|
||||
try {
|
||||
if (showLoading) setLoading(true)
|
||||
setRefreshing(true)
|
||||
|
||||
const res = await pageUserVerify({
|
||||
keywords: keywords.trim(),
|
||||
})
|
||||
|
||||
setList(res?.list || [])
|
||||
} catch (error) {
|
||||
console.error('获取报险记录失败:', error)
|
||||
Taro.showToast({
|
||||
title: '获取报险记录失败',
|
||||
icon: 'error'
|
||||
})
|
||||
} finally {
|
||||
setLoading(false)
|
||||
setRefreshing(false)
|
||||
}
|
||||
}
|
||||
|
||||
const onSearch = () => {
|
||||
reload()
|
||||
}
|
||||
|
||||
const onKeywordsChange = (value: string) => {
|
||||
setKeywords(value)
|
||||
}
|
||||
|
||||
const onAddInsurance = () => {
|
||||
Taro.navigateTo({
|
||||
url: '/hjm/violation/add'
|
||||
})
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
reload().then()
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<>
|
||||
{/* 搜索栏 */}
|
||||
<div style={{
|
||||
position: 'fixed',
|
||||
top: '20px',
|
||||
left: 0,
|
||||
right: 0,
|
||||
display: "none",
|
||||
zIndex: 20,
|
||||
padding: '0 16px',
|
||||
backgroundColor: '#f5f5f5'
|
||||
}}>
|
||||
<div style={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
backgroundColor: '#fff',
|
||||
padding: '8px 12px',
|
||||
borderRadius: '20px',
|
||||
boxShadow: '0 2px 8px rgba(0,0,0,0.1)'
|
||||
}}>
|
||||
<Search size={16} color="#999"/>
|
||||
<Input
|
||||
placeholder="搜索报险记录"
|
||||
value={keywords}
|
||||
onChange={onKeywordsChange}
|
||||
onConfirm={onSearch}
|
||||
style={{
|
||||
border: 'none',
|
||||
backgroundColor: 'transparent',
|
||||
flex: 1,
|
||||
marginLeft: '8px'
|
||||
}}
|
||||
/>
|
||||
<Button
|
||||
type="primary"
|
||||
size="small"
|
||||
onClick={onSearch}
|
||||
loading={loading}
|
||||
>
|
||||
搜索
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 报险记录列表 */}
|
||||
<div style={{
|
||||
marginTop: '10px',
|
||||
paddingBottom: '80px'
|
||||
}}>
|
||||
{loading && list.length === 0 ? (
|
||||
<div style={{
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
height: '200px'
|
||||
}}>
|
||||
<Loading type="spinner">加载中...</Loading>
|
||||
</div>
|
||||
) : list.length === 0 ? (
|
||||
<Empty description="暂无报险记录">
|
||||
<Button type="primary" onClick={onAddInsurance}>
|
||||
立即报险
|
||||
</Button>
|
||||
</Empty>
|
||||
) : (
|
||||
<div style={{padding: '0 16px'}}>
|
||||
{list.map((item, index) => {
|
||||
const statusDisplay = getStatusDisplay(item.status)
|
||||
|
||||
return (
|
||||
<div
|
||||
key={index}
|
||||
style={{
|
||||
backgroundColor: '#fff',
|
||||
borderRadius: '12px',
|
||||
padding: '16px',
|
||||
marginBottom: '12px',
|
||||
boxShadow: '0 2px 8px rgba(0,0,0,0.06)',
|
||||
border: '1px solid #f0f0f0'
|
||||
}}
|
||||
>
|
||||
<div style={{
|
||||
display: 'flex',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'flex-start',
|
||||
marginBottom: '12px'
|
||||
}}>
|
||||
<div style={{flex: 1}}>
|
||||
<div style={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
gap: '8px',
|
||||
marginBottom: '8px'
|
||||
}}>
|
||||
<File size={16} color="#1890ff"/>
|
||||
<span style={{
|
||||
fontSize: '16px',
|
||||
fontWeight: 'bold',
|
||||
color: '#262626'
|
||||
}}>
|
||||
{item.realName}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<Space direction="vertical">
|
||||
<div style={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
gap: '8px'
|
||||
}}>
|
||||
<Truck size={14} color="#8c8c8c"/>
|
||||
<span style={{fontSize: '13px', color: '#8c8c8c'}}>
|
||||
手机号码:{item.phone}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div style={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
gap: '8px'
|
||||
}}>
|
||||
<Calendar size={14} color="#8c8c8c"/>
|
||||
<span style={{fontSize: '13px', color: '#8c8c8c'}}>
|
||||
提交时间:{item.createTime}
|
||||
</span>
|
||||
</div>
|
||||
</Space>
|
||||
</div>
|
||||
|
||||
<Tag
|
||||
color={statusDisplay.color}
|
||||
style={{
|
||||
backgroundColor: statusDisplay.bgColor,
|
||||
border: `1px solid ${statusDisplay.color}`,
|
||||
fontSize: '12px'
|
||||
}}
|
||||
>
|
||||
{item.statusText}
|
||||
</Tag>
|
||||
</div>
|
||||
|
||||
{/* 备注信息 */}
|
||||
{item.comments && (
|
||||
<div style={{
|
||||
backgroundColor: '#f8f9fa',
|
||||
padding: '8px 12px',
|
||||
borderRadius: '6px',
|
||||
fontSize: '13px',
|
||||
color: '#595959',
|
||||
lineHeight: '1.4'
|
||||
}}>
|
||||
{item.comments.length > 50
|
||||
? `${item.comments.substring(0, 50)}...`
|
||||
: item.comments
|
||||
}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default List
|
||||
Reference in New Issue
Block a user