feat(credit): 重构小程序端客户管理功能
- 优化代码结构,使用函数组件和Hooks替代类组件 - 实现表单验证和错误处理机制 - 添加加载状态和提交防抖保护 - 增加城市选择和文件上传功能 - 实现推荐状态切换和长按删除功能 - 统一错误提示和用户反馈机制 - 优化页面标题和导航体验
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
import request from '@/utils/request';
|
import request from '@/utils/request';
|
||||||
|
import { withCreditUserScope } from '@/api/credit/utils/data-scope';
|
||||||
import type { ApiResult, PageResult } from '@/api/index';
|
import type { ApiResult, PageResult } from '@/api/index';
|
||||||
import type { CreditMpCustomer, CreditMpCustomerParam } from './model';
|
import type { CreditMpCustomer, CreditMpCustomerParam } from './model';
|
||||||
|
|
||||||
@@ -8,7 +9,7 @@ import type { CreditMpCustomer, CreditMpCustomerParam } from './model';
|
|||||||
export async function pageCreditMpCustomer(params: CreditMpCustomerParam) {
|
export async function pageCreditMpCustomer(params: CreditMpCustomerParam) {
|
||||||
const res = await request.get<ApiResult<PageResult<CreditMpCustomer>>>(
|
const res = await request.get<ApiResult<PageResult<CreditMpCustomer>>>(
|
||||||
'/credit/credit-mp-customer/page',
|
'/credit/credit-mp-customer/page',
|
||||||
params
|
withCreditUserScope(params)
|
||||||
);
|
);
|
||||||
if (res.code === 0) {
|
if (res.code === 0) {
|
||||||
return res.data;
|
return res.data;
|
||||||
@@ -22,7 +23,7 @@ export async function pageCreditMpCustomer(params: CreditMpCustomerParam) {
|
|||||||
export async function listCreditMpCustomer(params?: CreditMpCustomerParam) {
|
export async function listCreditMpCustomer(params?: CreditMpCustomerParam) {
|
||||||
const res = await request.get<ApiResult<CreditMpCustomer[]>>(
|
const res = await request.get<ApiResult<CreditMpCustomer[]>>(
|
||||||
'/credit/credit-mp-customer',
|
'/credit/credit-mp-customer',
|
||||||
params
|
withCreditUserScope(params)
|
||||||
);
|
);
|
||||||
if (res.code === 0 && res.data) {
|
if (res.code === 0 && res.data) {
|
||||||
return res.data;
|
return res.data;
|
||||||
@@ -62,6 +63,9 @@ export async function updateCreditMpCustomer(data: CreditMpCustomer) {
|
|||||||
* 删除小程序端客户
|
* 删除小程序端客户
|
||||||
*/
|
*/
|
||||||
export async function removeCreditMpCustomer(id?: number) {
|
export async function removeCreditMpCustomer(id?: number) {
|
||||||
|
if (id == null) {
|
||||||
|
return Promise.reject(new Error('缺少id'));
|
||||||
|
}
|
||||||
const res = await request.del<ApiResult<unknown>>(
|
const res = await request.del<ApiResult<unknown>>(
|
||||||
'/credit/credit-mp-customer/' + id
|
'/credit/credit-mp-customer/' + id
|
||||||
);
|
);
|
||||||
@@ -75,11 +79,10 @@ export async function removeCreditMpCustomer(id?: number) {
|
|||||||
* 批量删除小程序端客户
|
* 批量删除小程序端客户
|
||||||
*/
|
*/
|
||||||
export async function removeBatchCreditMpCustomer(data: (number | undefined)[]) {
|
export async function removeBatchCreditMpCustomer(data: (number | undefined)[]) {
|
||||||
|
const ids = (data || []).filter((v): v is number => typeof v === 'number');
|
||||||
const res = await request.del<ApiResult<unknown>>(
|
const res = await request.del<ApiResult<unknown>>(
|
||||||
'/credit/credit-mp-customer/batch',
|
'/credit/credit-mp-customer/batch',
|
||||||
{
|
ids
|
||||||
data
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
if (res.code === 0) {
|
if (res.code === 0) {
|
||||||
return res.message;
|
return res.message;
|
||||||
|
|||||||
@@ -1,98 +1,136 @@
|
|||||||
import {useEffect, useState, useRef} from "react";
|
import { useEffect, useMemo, useRef, useState } from 'react'
|
||||||
import {useRouter} from '@tarojs/taro'
|
import Taro, { useRouter } from '@tarojs/taro'
|
||||||
import {Button, Loading, CellGroup, Input, TextArea, Form} from '@nutui/nutui-react-taro'
|
import { View } from '@tarojs/components'
|
||||||
import Taro from '@tarojs/taro'
|
import { Button, CellGroup, Form, Input, Loading, TextArea } from '@nutui/nutui-react-taro'
|
||||||
import {View} from '@tarojs/components'
|
|
||||||
import {CreditMpCustomer} from "@/api/credit/creditMpCustomer/model";
|
import type { CreditMpCustomer } from '@/api/credit/creditMpCustomer/model'
|
||||||
import {getCreditMpCustomer, listCreditMpCustomer, updateCreditMpCustomer, addCreditMpCustomer} from "@/api/credit/creditMpCustomer";
|
import { addCreditMpCustomer, getCreditMpCustomer, updateCreditMpCustomer } from '@/api/credit/creditMpCustomer'
|
||||||
|
|
||||||
|
export default function CreditMpCustomerAddPage() {
|
||||||
|
const { params } = useRouter()
|
||||||
|
const id = useMemo(() => {
|
||||||
|
const n = Number(params?.id)
|
||||||
|
return Number.isFinite(n) && n > 0 ? n : undefined
|
||||||
|
}, [params?.id])
|
||||||
|
|
||||||
const AddCreditMpCustomer = () => {
|
|
||||||
const {params} = useRouter();
|
|
||||||
const [loading, setLoading] = useState<boolean>(true)
|
|
||||||
const [FormData, setFormData] = useState<CreditMpCustomer>({})
|
|
||||||
const formRef = useRef<any>(null)
|
const formRef = useRef<any>(null)
|
||||||
|
const [loading, setLoading] = useState(true)
|
||||||
const reload = async () => {
|
const [initialValues, setInitialValues] = useState<Partial<CreditMpCustomer>>({})
|
||||||
if (params.id) {
|
const [submitting, setSubmitting] = useState(false)
|
||||||
const data = await getCreditMpCustomer(Number(params.id))
|
|
||||||
setFormData(data)
|
|
||||||
} else {
|
|
||||||
setFormData({})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 提交表单
|
|
||||||
const submitSucceed = async (values: any) => {
|
|
||||||
try {
|
|
||||||
if (params.id) {
|
|
||||||
// 编辑模式
|
|
||||||
await updateCreditMpCustomer({
|
|
||||||
...values,
|
|
||||||
id: Number(params.id)
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
// 新增模式
|
|
||||||
await addCreditMpCustomer(values)
|
|
||||||
}
|
|
||||||
|
|
||||||
Taro.showToast({
|
|
||||||
title: `操作成功`,
|
|
||||||
icon: 'success'
|
|
||||||
})
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
return Taro.navigateBack()
|
|
||||||
}, 1000)
|
|
||||||
} catch (error) {
|
|
||||||
Taro.showToast({
|
|
||||||
title: `操作失败`,
|
|
||||||
icon: 'error'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const submitFailed = (error: any) => {
|
|
||||||
console.log(error, 'err...')
|
|
||||||
}
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
reload().then(() => {
|
Taro.setNavigationBarTitle({ title: id ? '编辑小程序端客户' : '新增小程序端客户' })
|
||||||
|
}, [id])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const run = async () => {
|
||||||
|
setLoading(true)
|
||||||
|
try {
|
||||||
|
if (id) {
|
||||||
|
const data = await getCreditMpCustomer(id)
|
||||||
|
setInitialValues(data || {})
|
||||||
|
} else {
|
||||||
|
setInitialValues({})
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error('加载失败:', e)
|
||||||
|
Taro.showToast({ title: (e as any)?.message || '加载失败', icon: 'none' })
|
||||||
|
} finally {
|
||||||
setLoading(false)
|
setLoading(false)
|
||||||
})
|
}
|
||||||
}, []);
|
}
|
||||||
|
run()
|
||||||
|
}, [id])
|
||||||
|
|
||||||
|
const onFinish = async (values: any) => {
|
||||||
|
if (submitting) return
|
||||||
|
setSubmitting(true)
|
||||||
|
try {
|
||||||
|
if (id) {
|
||||||
|
await updateCreditMpCustomer({ ...values, id })
|
||||||
|
} else {
|
||||||
|
await addCreditMpCustomer(values)
|
||||||
|
}
|
||||||
|
Taro.showToast({ title: '操作成功', icon: 'success' })
|
||||||
|
setTimeout(() => Taro.navigateBack(), 800)
|
||||||
|
} catch (e) {
|
||||||
|
console.error('保存失败:', e)
|
||||||
|
Taro.showToast({ title: (e as any)?.message || '操作失败', icon: 'none' })
|
||||||
|
} finally {
|
||||||
|
setSubmitting(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (loading) {
|
if (loading) {
|
||||||
return <Loading className={'px-2'}>加载中</Loading>
|
return <Loading className="px-2">加载中</Loading>
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<View className="bg-gray-50 min-h-screen px-3 pt-3 pb-6">
|
||||||
<Form
|
<Form
|
||||||
ref={formRef}
|
ref={formRef}
|
||||||
divider
|
divider
|
||||||
initialValues={FormData}
|
initialValues={initialValues}
|
||||||
labelPosition="left"
|
labelPosition="left"
|
||||||
onFinish={(values) => submitSucceed(values)}
|
onFinish={onFinish}
|
||||||
onFinishFailed={(errors) => submitFailed(errors)}
|
|
||||||
footer={
|
footer={
|
||||||
<div
|
<Button nativeType="submit" type="primary" size="large" loading={submitting} block>
|
||||||
style={{
|
{id ? '更新' : '保存'}
|
||||||
display: 'flex',
|
|
||||||
justifyContent: 'center',
|
|
||||||
width: '100%'
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Button
|
|
||||||
nativeType="submit"
|
|
||||||
type="success"
|
|
||||||
size="large"
|
|
||||||
className={'w-full'}
|
|
||||||
block
|
|
||||||
>
|
|
||||||
{params.id ? '更新' : '保存'}
|
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<CellGroup style={{padding: '4px 0'}}>
|
<CellGroup>
|
||||||
<Form.Item name="toUser" label="拖欠方" initialValue={FormData.toUser} required>
|
<Form.Item
|
||||||
|
name="toUser"
|
||||||
|
label="拖欠方"
|
||||||
|
required
|
||||||
|
rules={[{ required: true, message: '请输入拖欠方' }]}
|
||||||
|
>
|
||||||
|
<Input placeholder="请输入拖欠方/付款方名称" maxLength={50} />
|
||||||
|
</Form.Item>
|
||||||
|
|
||||||
|
<Form.Item
|
||||||
|
name="price"
|
||||||
|
label="拖欠金额"
|
||||||
|
required
|
||||||
|
rules={[{ required: true, message: '请输入拖欠金额' }]}
|
||||||
|
>
|
||||||
|
<Input placeholder="请输入拖欠金额" type="number" />
|
||||||
|
</Form.Item>
|
||||||
|
|
||||||
|
<Form.Item
|
||||||
|
name="years"
|
||||||
|
label="拖欠年数"
|
||||||
|
required
|
||||||
|
rules={[{ required: true, message: '请输入拖欠年数' }]}
|
||||||
|
>
|
||||||
|
<Input placeholder="请输入拖欠年数" type="number" />
|
||||||
|
</Form.Item>
|
||||||
|
|
||||||
|
<Form.Item name="province" label="省份">
|
||||||
|
<Input placeholder="可选" maxLength={20} />
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item name="city" label="城市">
|
||||||
|
<Input placeholder="可选" maxLength={20} />
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item name="region" label="辖区">
|
||||||
|
<Input placeholder="可选" maxLength={20} />
|
||||||
|
</Form.Item>
|
||||||
|
|
||||||
|
<Form.Item name="url" label="链接">
|
||||||
|
<Input placeholder="可选" maxLength={200} />
|
||||||
|
</Form.Item>
|
||||||
|
|
||||||
|
<Form.Item name="files" label="文件">
|
||||||
|
<TextArea placeholder="可选(可填文件URL或JSON)" maxLength={1000} rows={3} />
|
||||||
|
</Form.Item>
|
||||||
|
|
||||||
|
<Form.Item name="comments" label="备注">
|
||||||
|
<TextArea placeholder="可选" maxLength={200} showCount rows={3} />
|
||||||
|
</Form.Item>
|
||||||
|
</CellGroup>
|
||||||
|
</Form>
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,64 +1,129 @@
|
|||||||
import {useState} from "react";
|
import { useCallback, useState } from 'react'
|
||||||
import Taro, {useDidShow} from '@tarojs/taro'
|
import Taro, { useDidShow } from '@tarojs/taro'
|
||||||
import {Button, Cell, CellGroup, Space, Empty, ConfigProvider, Divider} from '@nutui/nutui-react-taro'
|
import { View, Text } from '@tarojs/components'
|
||||||
import {Dongdong, ArrowRight, CheckNormal, Checked} from '@nutui/icons-react-taro'
|
import { Button, Cell, CellGroup, ConfigProvider, Empty, Space } from '@nutui/nutui-react-taro'
|
||||||
import {View} from '@tarojs/components'
|
import { ArrowRight, CheckNormal, Checked } from '@nutui/icons-react-taro'
|
||||||
import {CreditMpCustomer} from "@/api/credit/creditMpCustomer/model";
|
|
||||||
import {listCreditMpCustomer, removeCreditMpCustomer, updateCreditMpCustomer} from "@/api/credit/creditMpCustomer";
|
|
||||||
|
|
||||||
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 [list, setList] = useState<CreditMpCustomer[]>([])
|
||||||
|
const [loading, setLoading] = useState(false)
|
||||||
|
|
||||||
const reload = () => {
|
const reload = useCallback(async () => {
|
||||||
listCreditMpCustomer({
|
setLoading(true)
|
||||||
// 添加查询条件
|
try {
|
||||||
})
|
const data = await listCreditMpCustomer()
|
||||||
.then(data => {
|
|
||||||
setList(data || [])
|
setList(data || [])
|
||||||
})
|
} catch (e) {
|
||||||
.catch(() => {
|
console.error('获取数据失败:', e)
|
||||||
Taro.showToast({
|
Taro.showToast({ title: (e as any)?.message || '获取数据失败', icon: 'none' })
|
||||||
title: '获取数据失败',
|
} finally {
|
||||||
icon: 'error'
|
setLoading(false)
|
||||||
});
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const onDel = async (id?: number) => {
|
|
||||||
await removeCreditMpCustomer(id)
|
|
||||||
Taro.showToast({
|
|
||||||
title: '删除成功',
|
|
||||||
icon: 'success'
|
|
||||||
});
|
|
||||||
reload();
|
|
||||||
}
|
}
|
||||||
|
}, [])
|
||||||
|
|
||||||
useDidShow(() => {
|
useDidShow(() => {
|
||||||
reload()
|
reload()
|
||||||
});
|
})
|
||||||
|
|
||||||
if (list.length == 0) {
|
const goAdd = () => Taro.navigateTo({ url: '/credit/creditMpCustomer/add' })
|
||||||
return (
|
|
||||||
<ConfigProvider>
|
const goEdit = (id?: number) => {
|
||||||
<div className={'h-full flex flex-col justify-center items-center'} style={{
|
if (!id) return
|
||||||
height: 'calc(100vh - 300px)',
|
Taro.navigateTo({ url: `/credit/creditMpCustomer/add?id=${id}` })
|
||||||
}}>
|
}
|
||||||
<Empty
|
|
||||||
style={{
|
const onToggleRecommend = async (row: CreditMpCustomer) => {
|
||||||
backgroundColor: 'transparent'
|
if (!row?.id) return
|
||||||
}}
|
const next = row.recommend === 1 ? 0 : 1
|
||||||
description="暂无数据"
|
try {
|
||||||
/>
|
await updateCreditMpCustomer({ ...row, recommend: next })
|
||||||
<Space>
|
Taro.showToast({ title: next === 1 ? '已设为推荐' : '已取消推荐', icon: 'success' })
|
||||||
<Button onClick={() => Taro.navigateTo({url: '/credit/creditMpCustomer/add'})}>新增小程序端客户</Button>
|
reload()
|
||||||
</Space>
|
} catch (e) {
|
||||||
</div>
|
console.error('更新失败:', e)
|
||||||
</ConfigProvider>
|
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 (
|
return (
|
||||||
<>
|
<View className="bg-gray-50 min-h-screen">
|
||||||
{list.map((item, _) => (
|
<ConfigProvider>
|
||||||
<Cell.Group key={item.
|
<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>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import { ArrowRight, Close } from '@nutui/icons-react-taro'
|
|||||||
import FixedButton from '@/components/FixedButton'
|
import FixedButton from '@/components/FixedButton'
|
||||||
import RegionData from '@/api/json/regions-data.json'
|
import RegionData from '@/api/json/regions-data.json'
|
||||||
import { uploadFileByPath } from '@/api/system/file'
|
import { uploadFileByPath } from '@/api/system/file'
|
||||||
|
import { addCreditMpCustomer } from '@/api/credit/creditMpCustomer'
|
||||||
|
|
||||||
import './add.scss'
|
import './add.scss'
|
||||||
|
|
||||||
@@ -28,6 +29,7 @@ export default function CreditOrderAddPage() {
|
|||||||
|
|
||||||
const [cityVisible, setCityVisible] = useState(false)
|
const [cityVisible, setCityVisible] = useState(false)
|
||||||
const [cityText, setCityText] = useState('')
|
const [cityText, setCityText] = useState('')
|
||||||
|
const [cityValue, setCityValue] = useState<string[]>([])
|
||||||
|
|
||||||
const [attachments, setAttachments] = useState<Attachment[]>([])
|
const [attachments, setAttachments] = useState<Attachment[]>([])
|
||||||
const [uploading, setUploading] = useState(false)
|
const [uploading, setUploading] = useState(false)
|
||||||
@@ -67,11 +69,21 @@ export default function CreditOrderAddPage() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const chooseAndUploadImages = async () => {
|
const chooseAndUploadImages = async () => {
|
||||||
const res = await Taro.chooseImage({
|
let res: any
|
||||||
|
try {
|
||||||
|
res = await Taro.chooseImage({
|
||||||
count: 9,
|
count: 9,
|
||||||
sizeType: ['compressed'],
|
sizeType: ['compressed'],
|
||||||
sourceType: ['album', 'camera']
|
sourceType: ['album', 'camera']
|
||||||
})
|
})
|
||||||
|
} catch (e) {
|
||||||
|
const msg = String((e as any)?.errMsg || (e as any)?.message || e || '')
|
||||||
|
if (msg.includes('cancel')) return
|
||||||
|
console.error('选择图片失败:', e)
|
||||||
|
Taro.showToast({ title: '选择图片失败', icon: 'none' })
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
const paths = (res?.tempFilePaths || []).filter(Boolean)
|
const paths = (res?.tempFilePaths || []).filter(Boolean)
|
||||||
if (!paths.length) return
|
if (!paths.length) return
|
||||||
|
|
||||||
@@ -95,11 +107,21 @@ export default function CreditOrderAddPage() {
|
|||||||
const chooseAndUploadDocs = async () => {
|
const chooseAndUploadDocs = async () => {
|
||||||
// 微信小程序:从会话/聊天等入口选择文件
|
// 微信小程序:从会话/聊天等入口选择文件
|
||||||
// H5 等环境可能不支持,走 try/catch 提示即可
|
// H5 等环境可能不支持,走 try/catch 提示即可
|
||||||
|
let res: any
|
||||||
|
try {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
const res = await Taro.chooseMessageFile({
|
res = await Taro.chooseMessageFile({
|
||||||
count: 9,
|
count: 9,
|
||||||
type: 'file'
|
type: 'file'
|
||||||
})
|
})
|
||||||
|
} catch (e) {
|
||||||
|
const msg = String((e as any)?.errMsg || (e as any)?.message || e || '')
|
||||||
|
if (msg.includes('cancel')) return
|
||||||
|
console.error('选择文件失败:', e)
|
||||||
|
Taro.showToast({ title: '当前环境不支持选取文件', icon: 'none' })
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
const tempFiles = (res?.tempFiles || []) as Array<{ path?: string; name?: string }>
|
const tempFiles = (res?.tempFiles || []) as Array<{ path?: string; name?: string }>
|
||||||
const paths = tempFiles.map(f => f?.path).filter(Boolean) as string[]
|
const paths = tempFiles.map(f => f?.path).filter(Boolean) as string[]
|
||||||
@@ -187,27 +209,44 @@ export default function CreditOrderAddPage() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const payload = {
|
const [province, city, region] = cityValue
|
||||||
payer,
|
const files = attachments.map(a => ({
|
||||||
amount,
|
name: a.name,
|
||||||
years,
|
url: a.url,
|
||||||
remark,
|
thumbnail: a.thumbnail,
|
||||||
city: cityText,
|
isImage: a.isImage
|
||||||
files: attachments.map(a => ({ name: a.name, url: a.url, isImage: a.isImage }))
|
}))
|
||||||
}
|
|
||||||
|
|
||||||
setSubmitting(true)
|
setSubmitting(true)
|
||||||
try {
|
try {
|
||||||
// TODO: 这里可替换为真实接口提交(如后端提供 `/credit/order`)
|
await addCreditMpCustomer({
|
||||||
console.log('发需求提交:', payload)
|
toUser: payer,
|
||||||
|
price: String(amount),
|
||||||
|
years: String(years),
|
||||||
|
comments: remark || undefined,
|
||||||
|
province: province || undefined,
|
||||||
|
city: city || undefined,
|
||||||
|
region: region || undefined,
|
||||||
|
files: files.length ? JSON.stringify(files) : undefined
|
||||||
|
})
|
||||||
|
|
||||||
Taro.showToast({ title: '提交成功', icon: 'success' })
|
Taro.showToast({ title: '提交成功', icon: 'success' })
|
||||||
Taro.eventCenter.trigger('credit:order:created', payload)
|
Taro.eventCenter.trigger('credit:order:created', {
|
||||||
|
toUser: payer,
|
||||||
|
price: String(amount),
|
||||||
|
years: String(years),
|
||||||
|
comments: remark || undefined,
|
||||||
|
province: province || undefined,
|
||||||
|
city: city || undefined,
|
||||||
|
region: region || undefined,
|
||||||
|
files
|
||||||
|
})
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
Taro.navigateBack()
|
Taro.navigateBack()
|
||||||
}, 800)
|
}, 800)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error('提交失败:', e)
|
console.error('提交失败:', e)
|
||||||
Taro.showToast({ title: '提交失败,请重试', icon: 'none' })
|
Taro.showToast({ title: (e as any)?.message || '提交失败,请重试', icon: 'none' })
|
||||||
} finally {
|
} finally {
|
||||||
setSubmitting(false)
|
setSubmitting(false)
|
||||||
}
|
}
|
||||||
@@ -217,7 +256,7 @@ export default function CreditOrderAddPage() {
|
|||||||
console.log('表单校验失败:', err)
|
console.log('表单校验失败:', err)
|
||||||
}
|
}
|
||||||
|
|
||||||
const canSubmit = !uploading && !submitting
|
const canSubmit = !uploading && !submitting && agree
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View className="credit-order-add-page">
|
<View className="credit-order-add-page">
|
||||||
@@ -292,7 +331,7 @@ export default function CreditOrderAddPage() {
|
|||||||
))}
|
))}
|
||||||
</View>
|
</View>
|
||||||
) : (
|
) : (
|
||||||
<Text className="attachments__empty"></Text>
|
<Text className="attachments__empty">未添加附件</Text>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
@@ -324,8 +363,10 @@ export default function CreditOrderAddPage() {
|
|||||||
options={cityOptions as any}
|
options={cityOptions as any}
|
||||||
title="选择城市"
|
title="选择城市"
|
||||||
onChange={(value: any[]) => {
|
onChange={(value: any[]) => {
|
||||||
const txt = value.filter(Boolean).slice(0, 2).join(' ')
|
const list = (value || []).filter(Boolean).slice(0, 3).map(v => String(v))
|
||||||
setCityText(txt)
|
setCityValue(list)
|
||||||
|
const txt = list.slice(0, 2).join(' ')
|
||||||
|
setCityText(txt || '')
|
||||||
setCityVisible(false)
|
setCityVisible(false)
|
||||||
}}
|
}}
|
||||||
onClose={() => setCityVisible(false)}
|
onClose={() => setCityVisible(false)}
|
||||||
@@ -339,4 +380,3 @@ export default function CreditOrderAddPage() {
|
|||||||
</View>
|
</View>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user