feat(credit): 重构小程序端客户管理功能
- 优化代码结构,使用函数组件和Hooks替代类组件 - 实现表单验证和错误处理机制 - 添加加载状态和提交防抖保护 - 增加城市选择和文件上传功能 - 实现推荐状态切换和长按删除功能 - 统一错误提示和用户反馈机制 - 优化页面标题和导航体验
This commit is contained in:
@@ -1,64 +1,129 @@
|
||||
import {useState} from "react";
|
||||
import Taro, {useDidShow} from '@tarojs/taro'
|
||||
import {Button, Cell, CellGroup, Space, Empty, ConfigProvider, Divider} from '@nutui/nutui-react-taro'
|
||||
import {Dongdong, ArrowRight, CheckNormal, Checked} from '@nutui/icons-react-taro'
|
||||
import {View} from '@tarojs/components'
|
||||
import {CreditMpCustomer} from "@/api/credit/creditMpCustomer/model";
|
||||
import {listCreditMpCustomer, removeCreditMpCustomer, updateCreditMpCustomer} from "@/api/credit/creditMpCustomer";
|
||||
import { useCallback, useState } from 'react'
|
||||
import Taro, { useDidShow } from '@tarojs/taro'
|
||||
import { View, Text } from '@tarojs/components'
|
||||
import { Button, Cell, CellGroup, ConfigProvider, Empty, Space } from '@nutui/nutui-react-taro'
|
||||
import { ArrowRight, CheckNormal, Checked } from '@nutui/icons-react-taro'
|
||||
|
||||
const CreditMpCustomerList = () => {
|
||||
import type { CreditMpCustomer } from '@/api/credit/creditMpCustomer/model'
|
||||
import { listCreditMpCustomer, removeCreditMpCustomer, updateCreditMpCustomer } from '@/api/credit/creditMpCustomer'
|
||||
|
||||
export default function CreditMpCustomerListPage() {
|
||||
const [list, setList] = useState<CreditMpCustomer[]>([])
|
||||
const [loading, setLoading] = useState(false)
|
||||
|
||||
const reload = () => {
|
||||
listCreditMpCustomer({
|
||||
// 添加查询条件
|
||||
})
|
||||
.then(data => {
|
||||
setList(data || [])
|
||||
})
|
||||
.catch(() => {
|
||||
Taro.showToast({
|
||||
title: '获取数据失败',
|
||||
icon: 'error'
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
const onDel = async (id?: number) => {
|
||||
await removeCreditMpCustomer(id)
|
||||
Taro.showToast({
|
||||
title: '删除成功',
|
||||
icon: 'success'
|
||||
});
|
||||
reload();
|
||||
}
|
||||
const reload = useCallback(async () => {
|
||||
setLoading(true)
|
||||
try {
|
||||
const data = await listCreditMpCustomer()
|
||||
setList(data || [])
|
||||
} catch (e) {
|
||||
console.error('获取数据失败:', e)
|
||||
Taro.showToast({ title: (e as any)?.message || '获取数据失败', icon: 'none' })
|
||||
} finally {
|
||||
setLoading(false)
|
||||
}
|
||||
}, [])
|
||||
|
||||
useDidShow(() => {
|
||||
reload()
|
||||
});
|
||||
})
|
||||
|
||||
if (list.length == 0) {
|
||||
return (
|
||||
<ConfigProvider>
|
||||
<div className={'h-full flex flex-col justify-center items-center'} style={{
|
||||
height: 'calc(100vh - 300px)',
|
||||
}}>
|
||||
<Empty
|
||||
style={{
|
||||
backgroundColor: 'transparent'
|
||||
}}
|
||||
description="暂无数据"
|
||||
/>
|
||||
<Space>
|
||||
<Button onClick={() => Taro.navigateTo({url: '/credit/creditMpCustomer/add'})}>新增小程序端客户</Button>
|
||||
</Space>
|
||||
</div>
|
||||
</ConfigProvider>
|
||||
)
|
||||
const goAdd = () => Taro.navigateTo({ url: '/credit/creditMpCustomer/add' })
|
||||
|
||||
const goEdit = (id?: number) => {
|
||||
if (!id) return
|
||||
Taro.navigateTo({ url: `/credit/creditMpCustomer/add?id=${id}` })
|
||||
}
|
||||
|
||||
const onToggleRecommend = async (row: CreditMpCustomer) => {
|
||||
if (!row?.id) return
|
||||
const next = row.recommend === 1 ? 0 : 1
|
||||
try {
|
||||
await updateCreditMpCustomer({ ...row, recommend: next })
|
||||
Taro.showToast({ title: next === 1 ? '已设为推荐' : '已取消推荐', icon: 'success' })
|
||||
reload()
|
||||
} catch (e) {
|
||||
console.error('更新失败:', e)
|
||||
Taro.showToast({ title: (e as any)?.message || '更新失败', icon: 'none' })
|
||||
}
|
||||
}
|
||||
|
||||
const onDel = async (id?: number) => {
|
||||
if (!id) return
|
||||
const res = await Taro.showModal({ title: '提示', content: '确认删除该记录?' })
|
||||
if (!res.confirm) return
|
||||
|
||||
try {
|
||||
await removeCreditMpCustomer(id)
|
||||
Taro.showToast({ title: '删除成功', icon: 'success' })
|
||||
reload()
|
||||
} catch (e) {
|
||||
console.error('删除失败:', e)
|
||||
Taro.showToast({ title: (e as any)?.message || '删除失败', icon: 'none' })
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{list.map((item, _) => (
|
||||
<Cell.Group key={item.
|
||||
<View className="bg-gray-50 min-h-screen">
|
||||
<ConfigProvider>
|
||||
<View className="px-3 pt-3">
|
||||
<Space>
|
||||
<Button type="primary" size="small" onClick={goAdd}>
|
||||
新增小程序端客户
|
||||
</Button>
|
||||
<Button size="small" loading={loading} onClick={reload}>
|
||||
刷新
|
||||
</Button>
|
||||
</Space>
|
||||
</View>
|
||||
|
||||
{!list.length ? (
|
||||
<View className="px-3 pt-10">
|
||||
<Empty description={loading ? '加载中...' : '暂无数据'} />
|
||||
</View>
|
||||
) : (
|
||||
<View className="px-3 pt-3 pb-6">
|
||||
<CellGroup>
|
||||
{list.map(row => {
|
||||
const recommended = row.recommend === 1
|
||||
const title = row.toUser || '-'
|
||||
const price = row.price ? `${row.price}元` : '-'
|
||||
const years = row.years ? `${row.years}年` : '-'
|
||||
const location = [row.province, row.city, row.region].filter(Boolean).join(' ')
|
||||
const desc = `${price} · ${years}${location ? ` · ${location}` : ''}`
|
||||
|
||||
return (
|
||||
<View key={row.id} onLongPress={() => onDel(row.id)}>
|
||||
<Cell
|
||||
title={title}
|
||||
description={desc}
|
||||
extra={
|
||||
<View className="flex items-center gap-3">
|
||||
<View
|
||||
className="flex items-center"
|
||||
onClick={e => {
|
||||
e.stopPropagation()
|
||||
onToggleRecommend(row)
|
||||
}}
|
||||
>
|
||||
{recommended ? <Checked size={16} /> : <CheckNormal size={16} />}
|
||||
<Text className="ml-1 text-xs text-gray-500">{recommended ? '推荐' : '未推荐'}</Text>
|
||||
</View>
|
||||
<ArrowRight color="#cccccc" />
|
||||
</View>
|
||||
}
|
||||
onClick={() => goEdit(row.id)}
|
||||
/>
|
||||
</View>
|
||||
)
|
||||
})}
|
||||
</CellGroup>
|
||||
<View className="mt-2 text-xs text-gray-400">
|
||||
长按任意一条可删除
|
||||
</View>
|
||||
</View>
|
||||
)}
|
||||
</ConfigProvider>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user