优化细节

This commit is contained in:
2025-07-24 19:37:45 +08:00
parent 3e315bf9ee
commit 3693b2d5ed
54 changed files with 1143 additions and 595 deletions

View File

@@ -1,4 +1,4 @@
export default definePageConfig({
navigationBarTitleText: '常见问题',
navigationBarTitleText: '关于我们',
navigationBarTextStyle: 'black'
})

View File

@@ -1,15 +1,30 @@
import {useEffect, useState} from "react";
import {CmsArticle} from "@/api/cms/cmsArticle/model";
import {listCmsArticle} from "@/api/cms/cmsArticle";
import {Collapse} from '@nutui/nutui-react-taro'
import {ArrowDown} from '@nutui/icons-react-taro'
import {Collapse, Avatar, Cell, Divider} from '@nutui/nutui-react-taro'
import {ArrowRight} from '@nutui/icons-react-taro'
import {CmsNavigation} from "@/api/cms/cmsNavigation/model";
import {listCmsNavigation} from "@/api/cms/cmsNavigation";
// 显示html富文本
import {View, RichText} from '@tarojs/components'
const Helper = () => {
const [list, setList] = useState<CmsArticle[]>([])
const [nav, setNav] = useState<CmsNavigation>()
const [category, setCategory] = useState<CmsNavigation[]>([])
const reload = () => {
listCmsArticle({model: 'help'}).then(res => {
const reload = async () => {
const navs = await listCmsNavigation({model: 'page', parentId: 0});
if (navs.length > 0) {
const nav = navs[0];
setNav(nav);
// 查询子栏目
const category = await listCmsNavigation({parentId: nav.navigationId})
setCategory(category)
}
listCmsArticle({model: 'page'}).then(res => {
setList(res)
}).catch(error => {
console.error("Failed to fetch goods detail:", error);
@@ -17,25 +32,55 @@ const Helper = () => {
}
useEffect(() => {
reload()
reload().then()
}, []);
return (
<div className={'p-3'}>
{list.map((item, index) => (
<Collapse defaultActiveName={['1', '2']} expandIcon={<ArrowDown/>}>
<Collapse.Item
title={
<div className={'flex items-center'}>
<div className={'text-sm'}>{item.title}</div>
</div>
}
name={`${index}`}
>
<div className={'text-sm'}>{item.comments}</div>
</Collapse.Item>
</Collapse>
<div className={'px-3'}>
<Cell>
{nav && (
<View className={'flex flex-col justify-center items-center w-full'}>
<Avatar
src={nav?.icon}
size={'100'}
/>
<View className={'font-bold text-sm'}>
{nav?.comments}
</View>
<View className={'text-left py-3 text-gray-600'}>
<RichText
nodes={'时里院子市集是一家B2C模式的会员电商平台以健康安全食品中国国家地理标志产品药食同源产品等为主线愿景是守护5亿家庭餐桌健康;选品原则是健康,好吃,方便,实惠。通过严格的筛选供货商,从选品、采购发货、仓储物流产品检测、售前售后等各环节严格把控,提升用户满意度。平台采取透明公开化,以持续为用户提供物美价廉的好产品为准准则,为用户创造价值为唯一宗旨,倡导终身用户,终身服务的经营理念。'}/>
</View>
</View>
)}
</Cell>
{category.map((item, index) => (
<Cell
title={(
<div className={'font-bold'} id={`${index}`}>
{item.categoryName}
</div>
)}
description={(
<>
<Divider/>
<View className={'item flex justify-between items-center my-2'}>
<View>{item.categoryName}</View>
<ArrowRight size={16} className={'text-gray-400'}/>
</View>
<View className={'item flex justify-between items-center my-2'}>
<View>{item.categoryName}</View>
<ArrowRight size={16} className={'text-gray-400'}/>
</View>
</>
)}
>
</Cell>
))}
<Cell className={'flex flex-col'}>
<span>线0771-88888888</span>
<span>9:00-18:00</span>
</Cell>
</div>
);
};

View File

@@ -1,76 +1,75 @@
import {useEffect, useState} from "react";
import {Button, Cell, CellGroup, Input, TextArea, Form, Picker, Cascader} from '@nutui/nutui-react-taro'
import {useRouter} from '@tarojs/taro'
import {Button, Loading, CellGroup, Input, TextArea, Form} from '@nutui/nutui-react-taro'
import {Scan, ArrowRight} from '@nutui/icons-react-taro'
import Taro from '@tarojs/taro'
import {View} from '@tarojs/components'
import {Address} from '@nutui/nutui-react-taro'
import {ShopUserAddress} from "@/api/shop/shopUserAddress/model";
import {listShopUserAddress} from "@/api/shop/shopUserAddress";
import {updateUserInfo} from "@/api/layout";
import {getBszxClassForTree} from "@/api/bszx/bszxClass";
import {getShopUserAddress, listShopUserAddress, updateShopUserAddress} from "@/api/shop/shopUserAddress";
import RegionData from '@/api/json/regions-data.json';
const pickerOptions = [
{value: 4, text: 'BeiJing'},
{value: 1, text: 'NanJing'},
{value: 2, text: 'WuXi'},
{value: 8, text: 'DaQing'},
{value: 9, text: 'SuiHua'},
{value: 10, text: 'WeiFang'},
{value: 12, text: 'ShiJiaZhuang'},
]
const AddUserAddress = () => {
const {params} = useRouter();
const [loading, setLoading] = useState<boolean>(true)
const [text, setText] = useState<string>('')
const [optionsDemo1, setOptionsDemo1] = useState([])
const [visible, setVisible] = useState(false)
const [FormData, setFormData] = useState<ShopUserAddress>({})
const OrderConfirm = () => {
const [list, setList] = useState<ShopUserAddress[]>([])
const [classList, setClassList] = useState<any[]>()
const [FormData, setFormData] = useState<ShopUserAddress>(
{
userId: undefined,
name: undefined,
phone: undefined,
country: undefined,
province: undefined,
city: undefined,
region: undefined,
address: undefined,
fullAddress: undefined,
lat: undefined,
lng: undefined,
gender: undefined,
type: undefined,
isDefault: undefined,
}
)
const [navBarState, setNavBarState] = useState({
visible: false
})
const changeNarBar = (visible) => {
setNavBarState({
visible
})
const reload = async () => {
const address = await getShopUserAddress(Number(params.id))
setFormData(address)
// 设置所在地区
setText(`${address.province} ${address.city} ${address.region}`)
// 整理地区数据
setRegionData()
}
// 获取班级数据树
getBszxClassForTree().then(res => {
setClassList(res);
})
const change6 = (value: any, path: any) => {
const branch = path[0];
changeNarBar(false)
}
const reload = () => {
listShopUserAddress({userId: Taro.getStorageSync('UserId')}).then(res => {
setList(res)
}).catch(error => {
console.error("Failed to fetch goods detail:", error);
})
/**
* 处理地区数据
*/
function setRegionData() {
// @ts-ignore
setOptionsDemo1(RegionData?.map((a) => {
return {
value: a.label,
text: a.label,
children: a.children?.map((b) => {
return {
value: b.label,
text: b.label,
children: b.children?.map((c) => {
return {
value: c.label,
text: c.label
}
})
}
})
}
}))
}
// 提交表单
const submitSucceed = (values: any) => {
console.log(values, 'values')
updateUserInfo(values).then(() => {
const submitSucceed = async (values: any) => {
const defaultAddress = await listShopUserAddress({isDefault: true})
if(!defaultAddress) return
const setNotDefault = await updateShopUserAddress({
...defaultAddress[0],
isDefault: false
})
if(!setNotDefault) return
updateShopUserAddress({
...values,
id: Number(params.id),
province: FormData.province,
city: FormData.city,
region: FormData.region
}).then(() => {
Taro.showToast({title: `保存成功`, icon: 'success'})
setTimeout(() => {
return Taro.navigateBack()
@@ -87,9 +86,15 @@ const OrderConfirm = () => {
}
useEffect(() => {
reload()
reload().then(() => {
setLoading(false)
})
}, []);
if (loading) {
return <Loading className={'px-2'}></Loading>
}
return (
<>
<Form
@@ -132,63 +137,47 @@ const OrderConfirm = () => {
</CellGroup>
<View className={'bg-gray-100 h-3'}></View>
<CellGroup style={{padding: '4px 0'}}>
<Form.Item name="name" label="收货人" required>
<Form.Item name="name" label="收货人" initialValue={FormData.name} required>
<Input placeholder="请输入收货人姓名"/>
</Form.Item>
<Form.Item name="phone" label="手机号" required>
<Form.Item name="phone" label="手机号" initialValue={FormData.phone} required>
<Input placeholder="请输入手机号"/>
</Form.Item>
<Form.Item
label="所在地区"
name="region"
required
initialValue={FormData.region}
rules={[{message: '请输入您的所在地区'}]}
required
>
<div className={'flex justify-between items-center'} onClick={() => changeNarBar(true)}>
<Input placeholder="选择所在地区" disabled/>
<div className={'flex justify-between items-center'} onClick={() => setVisible(true)}>
<Input placeholder="选择所在地区" value={text} disabled/>
<ArrowRight className={'text-gray-400'}/>
</div>
</Form.Item>
<Form.Item name="address" label="收货地址" required>
<Form.Item name="address" label="收货地址" initialValue={FormData.address} required>
<Input placeholder="请输入详细收货地址"/>
</Form.Item>
</CellGroup>
</Form>
<Cascader
popupProps={{
className: 'cascader-popup',
}}
visible={navBarState.visible}
optionKey={{valueKey: 'name', textKey: 'name', childrenKey: 'children'}}
title="选择所在地区"
options={classList}
closeable
onChange={change6}
onClose={() => {
changeNarBar(false)
<Address
visible={visible}
options={optionsDemo1}
title="选择地址"
onChange={(value, _) => {
setFormData({
...FormData,
province: `${value[0]}`,
city: `${value[1]}`,
region: `${value[2]}`
})
setText(value.join(' '))
}}
onClose={() => setVisible(false)}
/>
{/*<CellGroup>*/}
{/* <Cell>*/}
{/* <div className={'flex items-center'}>*/}
{/* <Image src={goods.image} width="80" height="80"/>*/}
{/* <div className={'ml-2'}>*/}
{/* <div className={'text-sm font-bold'}>{goods.name}</div>*/}
{/* <div className={'text-red-500 text-lg'}>¥{goods.price}</div>*/}
{/* </div>*/}
{/* </div>*/}
{/* </Cell>*/}
{/*</CellGroup>*/}
{/*<div className={'fixed-bottom'}>*/}
{/* <div className={'total-price'}>*/}
{/* 合计:<span className={'text-red-500 text-xl font-bold'}>¥{goods.price}</span>*/}
{/* </div>*/}
{/* <Button type="primary" size="large" className={'submit-btn'}>提交订单</Button>*/}
{/*</div>*/}
</>
);
};
export default OrderConfirm;
export default AddUserAddress;

View File

@@ -4,17 +4,54 @@ import {Dongdong, ArrowRight, CheckNormal, Checked} from '@nutui/icons-react-tar
import Taro from '@tarojs/taro'
import {View} from '@tarojs/components'
import {ShopUserAddress} from "@/api/shop/shopUserAddress/model";
import {listShopUserAddress} from "@/api/shop/shopUserAddress";
import {listShopUserAddress, removeShopUserAddress, updateShopUserAddress} from "@/api/shop/shopUserAddress";
const Address = () => {
const [list, setList] = useState<ShopUserAddress[]>([{},{},{},{}])
const [list, setList] = useState<ShopUserAddress[]>([])
const [address, setAddress] = useState<ShopUserAddress>()
const reload = () => {
listShopUserAddress({userId: Taro.getStorageSync('UserId')}).then(res => {
// setList(res)
}).catch(error => {
console.error("Failed to fetch goods detail:", error);
listShopUserAddress({
userId: Taro.getStorageSync('UserId')
})
.then(data => {
setList(data || [])
// 默认地址
setAddress(data.find(item => item.isDefault))
})
.catch(() => {
Taro.showToast({
title: '获取地址失败',
icon: 'error'
});
})
}
const onDefault = async (item) => {
if(address){
await updateShopUserAddress({
...address,
isDefault: false
})
}
await updateShopUserAddress({
id: item.id,
isDefault: true
})
Taro.showToast({
title: '设置成功',
icon: 'success'
});
reload();
}
const onDel = async (id?: number) => {
await removeShopUserAddress(id)
Taro.showToast({
title: '删除成功',
icon: 'success'
});
reload();
}
useEffect(() => {
@@ -35,26 +72,14 @@ const Address = () => {
/>
<Space>
<Button onClick={() => Taro.navigateTo({url: '/user/address/add'})}></Button>
<Button type="success" fill="dashed"></Button>
<Button type="success" fill="dashed"
onClick={() => Taro.navigateTo({url: '/user/address/wxAddress'})}></Button>
</Space>
</div>
</ConfigProvider>
)
}
if (list.length == 0) {
return (
<CellGroup>
<Cell className={''}>
<Space>
<Button></Button>
<Button></Button>
</Space>
</Cell>
</CellGroup>
)
}
return (
<>
<CellGroup>
@@ -70,46 +95,31 @@ const Address = () => {
</div>
</Cell>
</CellGroup>
{list.map((item,index) => (
// <CellGroup key={item.id}>
// <Cell title={item.name}
// extra={
// <Button
// type="primary"
// size="small"
// >
// 修改
// </Button>
// }
// >
// <div className={'text-sm'}>{item.fullAddress}</div>
//
// </Cell>
// </CellGroup>
{list.map((item, _) => (
<Cell.Group>
<Cell className={'flex flex-col gap-1'}>
<View>
<View className={'font-medium text-sm'}> 13800010001</View>
<View className={'font-medium text-sm'}>{item.name} {item.phone}</View>
</View>
<View className={'text-xs'}>
广西13
{item.province} {item.city} {item.region} {item.address}
</View>
</Cell>
<Cell
align="center"
title={
<View className={'flex items-center gap-1'}>
{index == 0 ? <Checked className={'text-green-600'} size={16}/> : <CheckNormal size={16} />}
<View className={'flex items-center gap-1'} onClick={() => onDefault(item)}>
{item.isDefault ? <Checked className={'text-green-600'} size={16}/> : <CheckNormal size={16}/>}
<View className={'text-gray-400'}></View>
</View>
}
extra={
<>
<View className={'text-gray-400'}>
<View className={'text-gray-400'} onClick={() => onDel(item.id)}>
</View>
<Divider direction={'vertical'}/>
<View className={'text-gray-400'}>
<View className={'text-gray-400'} onClick={() => Taro.navigateTo({url: '/user/address/add?id=' + item.id})}>
</View>
</>

View File

@@ -1,90 +1,65 @@
import {useEffect, useState} from "react";
import {Button, Cell, CellGroup, Space, Empty, ConfigProvider} from '@nutui/nutui-react-taro'
import {Dongdong} from '@nutui/icons-react-taro'
import {useEffect} from "react";
import Taro from '@tarojs/taro'
import {ShopUserAddress} from "@/api/shop/shopUserAddress/model";
import {listShopUserAddress} from "@/api/shop/shopUserAddress";
import {addShopUserAddress} from "@/api/shop/shopUserAddress";
const Address = () => {
const [list, setList] = useState<ShopUserAddress[]>([{
id: 1,
name: '张三',
phone: '13800138000',
country: '中国',
province: '广东省',
city: '广州市',
region: '天河区',
address: '黄埔大道西10号',
fullAddress: '广东省广州市天河区黄埔大道西10号',
lat: '23.129163',
lng: '113.382391',
gender: 1,
type: 'home',
isDefault: true,
userId: 1,
tenantId: 1,
createTime: '2021-09-01 10:10:10',
},
{
id: 2,
name: '李四',
phone: '13800138000',
country: '中国',
province: '广西壮族自治区',
city: '南宁市',
region: '青秀区',
address: '青秀区民族大道100号',
fullAddress: '广西壮族自治区南宁市青秀区民族大道100号',
lat: '23.129163',
lng: '113.382391',
gender: 1,
type: 'home',
isDefault: true,
userId: 1,
tenantId: 1,
createTime: '2021-09-01 10:10:10',
},
{
id: 3,
name: '张三',
phone: '13800138000',
country: '中国',
province: '广西',
city: '南宁市',
region: '青秀区',
address: '青秀区民族大道100号',
fullAddress: '广西壮族自治区南宁市青秀区民族大道100号',
lat: '23.129163',
lng: '113.382391',
gender: 1,
type: 'home',
isDefault: true,
userId: 1,
tenantId: 1,
createTime: '2021-09-01 10:10:10',
}])
const reload = () => {
listShopUserAddress({userId: Taro.getStorageSync('UserId')}).then(res => {
// setList(res)
}).catch(error => {
console.error("Failed to fetch goods detail:", error);
})
/**
* 从微信API获取用户收货地址
* 调用微信原生地址选择界面,获取成功后保存到服务器并刷新列表
*/
const getWeChatAddress = () => {
Taro.chooseAddress()
.then(res => {
// 格式化微信返回的地址数据为后端所需格式
const addressData = {
name: res.userName,
phone: res.telNumber,
country: res.nationalCode || '中国',
province: res.provinceName,
city: res.cityName,
region: res.countyName,
address: res.detailInfo,
postalCode: res.postalCode,
isDefault: false
}
console.log(res, 'addrs..')
// 调用保存地址的API假设存在该接口
addShopUserAddress(addressData)
.then((msg) => {
console.log(msg)
Taro.showToast({
title: `${msg}`,
icon: 'none'
})
setTimeout(() => {
// 保存成功后返回
Taro.navigateBack()
}, 1000)
})
.catch(error => {
console.error('保存地址失败:', error)
Taro.showToast({title: '保存地址失败', icon: 'error'})
})
})
.catch(err => {
console.error('获取微信地址失败:', err)
// 处理用户拒绝授权的情况
if (err.errMsg.includes('auth deny')) {
Taro.showModal({
title: '授权失败',
content: '请在设置中允许获取地址权限',
showCancel: false
})
}
})
}
useEffect(() => {
reload()
getWeChatAddress()
}, []);
return (
<>
{list.map((item) => (
<div className={'flex flex-col bg-white my-3 py-1 px-4'}>
<div className={'py-1'}>{item.province}{item.city}{item.region}</div>
<div className={'py-1'}>{item.address}</div>
<div className={'text-gray-500 py-1'}>{item.name} {item.phone}</div>
</div>
))}
</>
);
};

View File

@@ -1,23 +1,22 @@
import {useEffect, useState} from "react";
import {CmsArticle} from "@/api/cms/cmsArticle/model";
import {listCmsArticle} from "@/api/cms/cmsArticle";
import {Collapse} from '@nutui/nutui-react-taro'
import {Collapse, Image, SearchBar} from '@nutui/nutui-react-taro'
import {ArrowDown} from '@nutui/icons-react-taro'
import {CmsNavigation} from "@/api/cms/cmsNavigation/model";
import {listCmsNavigation} from "@/api/cms/cmsNavigation";
const Helper = () => {
const [list, setList] = useState<CmsArticle[]>([])
const [navigation, setNavigation] = useState<CmsNavigation>()
const [category, setCategory] = useState();
const getData = () => {
fetch("https://storage.360buyimg.com/nutui/3x/new-categoryData.js")
.then((response) => response.json())
.then((res) => {
setCategory(res.categoryInfo.category)
})
.catch((err) => console.log("Oh, error", err));
};
const reload = () => {
const reload = async () => {
const navs = await listCmsNavigation({model: 'help', parentId: 0});
if (navs.length > 0) {
const nav = navs[0];
setNavigation(nav);
}
listCmsArticle({model: 'help'}).then(res => {
setList(res)
}).catch(error => {
@@ -26,13 +25,35 @@ const Helper = () => {
}
useEffect(() => {
reload()
getData();
reload().then()
}, []);
return (
<>
{/*<Category category={category} showSecondLevelQuickNav={true}></Category>*/}
<SearchBar shape="round" maxLength={5} className={'mt-2'} />
{navigation && (
<Image
src={navigation.icon}
mode={'scaleToFill'}
className={'mt-2 mb-4 w-full'}
height={120}
lazyLoad={false}
/>
)}
{list.map((item, index) => (
<Collapse defaultActiveName={['1', '2']} expandIcon={<ArrowDown/>}>
<Collapse.Item
title={
<div className={'flex items-center'}>
<div className={'text-sm'}>{item.title}</div>
</div>
}
name={`${index}`}
>
<div className={'text-sm'}>{item.comments}</div>
</Collapse.Item>
</Collapse>
))}
</>
);
};

View File

@@ -73,7 +73,7 @@ function Profile() {
avatar: `${detail.avatarUrl}`,
})
Taro.uploadFile({
url: 'https://server.websoft.top/api/oss/upload',
url: 'https://server.gxwebsoft.com/api/oss/upload',
filePath: detail.avatarUrl,
name: 'file',
header: {

View File

@@ -233,11 +233,11 @@ function Index() {
>
<div className={'flex gap-2'}>
<div onClick={uploadSfz1}>
<Image src={FormData.sfz1}
<Image src={FormData.sfz1} lazyLoad={false}
radius="10%" width="80" height="80"/>
</div>
<div onClick={uploadSfz2}>
<Image src={FormData.sfz2} mode={'scaleToFill'}
<Image src={FormData.sfz2} mode={'scaleToFill'} lazyLoad={false}
radius="10%" width="80" height="80"/>
</div>
</div>
@@ -286,7 +286,7 @@ function Index() {
]}
>
<div onClick={uploadZzImg}>
<Image src={FormData.zzImg} mode={'scaleToFill'}
<Image src={FormData.zzImg} mode={'scaleToFill'} lazyLoad={false}
radius="10%" width="80" height="80"/>
</div>
</Form.Item>