提交代码

This commit is contained in:
2025-06-26 11:41:12 +08:00
commit d75fb55eec
396 changed files with 42172 additions and 0 deletions

View File

@@ -0,0 +1,211 @@
import {useEffect, useState} from 'react'
import {navigateTo} from '@tarojs/taro'
import Taro from '@tarojs/taro'
import {Button} from '@tarojs/components';
import {Image} from '@nutui/nutui-react-taro'
import {getUserInfo, getWxOpenId} from "@/api/layout";
import {TenantId} from "@/utils/config";
import {User} from "@/api/system/user/model";
// import News from "./News";
import {myPageBszxBm} from "@/api/bszx/bszxBm";
import {listCmsNavigation} from "@/api/cms/cmsNavigation";
const OrderIcon = () => {
const [loading, setLoading] = useState(true)
const [isLogin, setIsLogin] = useState<boolean>(false)
const [userInfo, setUserInfo] = useState<User>()
const [bmLogs, setBmLogs] = useState<any>()
const [navItems, setNavItems] = useState<any>([])
/* 获取用户手机号 */
const handleGetPhoneNumber = ({detail}) => {
const {code, encryptedData, iv} = detail
Taro.login({
success: function () {
if (code) {
Taro.request({
url: 'https://server.gxwebsoft.com/api/wx-login/loginByMpWxPhone',
method: 'POST',
data: {
code,
encryptedData,
iv,
notVerifyPhone: true,
refereeId: 0,
sceneType: 'save_referee',
tenantId: TenantId
},
header: {
'content-type': 'application/json',
TenantId
},
success: function (res) {
Taro.setStorageSync('access_token', res.data.data.access_token)
Taro.setStorageSync('UserId', res.data.data.user.userId)
setUserInfo(res.data.data.user)
Taro.setStorageSync('Phone', res.data.data.user.phone)
setIsLogin(true)
Taro.showToast({
title: '登录成功',
icon: 'success'
});
}
})
} else {
console.log('登录失败!')
}
}
})
}
const onLogin = (item: any, index: number) => {
if(!isLogin){
return navigateTo({url: `/pages/category/category?id=${item.navigationId}`})
}else {
// 报名链接
if(index == 0){
console.log(bmLogs,'bmLogs')
if(bmLogs && bmLogs.length > 0){
return navigateTo({url: `/bszx/bm-cert/bm-cert?id=${bmLogs[0].id}`})
}else {
navigateTo({url: `/user/profile/profile`})
}
}
// 善款明细
if(item.navigationId == 4119){
return navigateTo({url: `/bszx/pay-record/pay-record`})
}
return navigateTo({url: `/pages/category/category?id=${item.navigationId}`})
}
}
const reload = () => {
// 读取栏目
listCmsNavigation({parentId: 2828,hide: 0}).then(res => {
console.log(res,'9999')
setNavItems(res);
})
Taro.getUserInfo({
success: (res) => {
const avatar = res.userInfo.avatarUrl;
setUserInfo({
avatar,
nickname: res.userInfo.nickName,
sexName: res.userInfo.gender == 1 ? '男' : '女'
})
getUserInfo().then((data) => {
if (data) {
setUserInfo(data)
setIsLogin(true);
console.log(userInfo, 'userInfo...')
Taro.setStorageSync('UserId', data.userId)
// 获取openId
if (!data.openid) {
Taro.login({
success: (res) => {
getWxOpenId({code: res.code}).then(() => {
})
}
})
}
}
}).catch(() => {
console.log('未登录')
});
}
});
// 报名日志
myPageBszxBm({limit: 1}).then(res => {
if (res.list) {
setBmLogs(res.list);
}
})
setLoading(false);
};
const showAuthModal = () => {
Taro.showModal({
title: '授权提示',
content: '需要获取您的用户信息',
confirmText: '去授权',
cancelText: '取消',
success: (res) => {
if (res.confirm) {
// 用户点击确认,打开授权设置页面
openSetting();
}
}
});
};
const openSetting = () => {
// Taro.openSetting调起客户端小程序设置界面返回用户设置的操作结果。设置界面只会出现小程序已经向用户请求过的权限。
Taro.openSetting({
success: (res) => {
if (res.authSetting['scope.userInfo']) {
// 用户授权成功,可以获取用户信息
reload();
} else {
// 用户拒绝授权,提示授权失败
Taro.showToast({
title: '授权失败',
icon: 'none'
});
}
}
});
};
useEffect(() => {
Taro.getSetting({
success: (res) => {
if (res.authSetting['scope.userInfo']) {
// 用户已经授权过,可以直接获取用户信息
console.log('用户已经授权过,可以直接获取用户信息')
reload();
} else {
// 用户未授权,需要弹出授权窗口
console.log('用户未授权,需要弹出授权窗口')
showAuthModal();
}
}
});
reload();
}, [])
return (
<div className={'my-3'}>
<div className={'pt-4 bg-yellow-50 rounded-2xl'}
style={{background: 'linear-gradient(to bottom, #ffffff, #ffffcc)'}}>
<div className={'flex justify-between pb-2 px-1'}>
{
navItems.map((item, index) => (
<div key={index} className={'text-center'}>
{
isLogin && !loading ?
<div className={'flex flex-col justify-center items-center'} onClick={() => {
onLogin(item, index)
}}>
<Image src={item.icon} height={28} width={28}/>
<div className={'mt-2'} style={{fontSize: '15px'}}>{item?.title}</div>
</div>
:
<Button className={'text-white'} open-type="getPhoneNumber" onGetPhoneNumber={handleGetPhoneNumber}>
<div className={'flex flex-col justify-center items-center'}>
<Image src={item.icon} height={28} width={28}/>
<div className={'mt-2 text-gray-700'} style={{fontSize: '15px'}}>{item?.title}</div>
</div>
</Button>
}
</div>
))
}
</div>
</div>
{/*<image src={'https://oss.wsdns.cn/20250224/18a2f3b807c94aac8a67af34e95534d6.jpeg'} className={'book'}>倡议书</image>*/}
{/*<News id={categoryId}/>*/}
</div>
)
}
export default OrderIcon

View File

@@ -0,0 +1,209 @@
import {Button} from '@nutui/nutui-react-taro'
import {Avatar, Tag} from '@nutui/nutui-react-taro'
import {getUserInfo, getWxOpenId} from '@/api/layout';
import Taro from '@tarojs/taro';
import {useEffect, useState} from "react";
import {User} from "@/api/system/user/model";
import navTo from "@/utils/common";
import {TenantId} from "@/utils/config";
function UserCard() {
const [IsLogin, setIsLogin] = useState<boolean>(false)
const [userInfo, setUserInfo] = useState<User>()
const [roleName, setRoleName] = useState<string>('注册用户')
useEffect(() => {
// Taro.getSetting获取用户的当前设置。返回值中只会出现小程序已经向用户请求过的权限。
Taro.getSetting({
success: (res) => {
if (res.authSetting['scope.userInfo']) {
// 用户已经授权过,可以直接获取用户信息
console.log('用户已经授权过,可以直接获取用户信息')
reload();
} else {
// 用户未授权,需要弹出授权窗口
console.log('用户未授权,需要弹出授权窗口')
showAuthModal();
}
}
});
}, []);
const reload = () => {
Taro.getUserInfo({
success: (res) => {
const avatar = res.userInfo.avatarUrl;
setUserInfo({
avatar,
nickname: res.userInfo.nickName,
sexName: res.userInfo.gender == 1 ? '男' : '女'
})
getUserInfo().then((data) => {
if (data) {
setUserInfo(data)
setIsLogin(true);
Taro.setStorageSync('UserId', data.userId)
// 获取openId
if (!data.openid) {
Taro.login({
success: (res) => {
getWxOpenId({code: res.code}).then(() => {
})
}
})
}
// 判断身份
const roleName = Taro.getStorageSync('RoleName');
if(roleName){
setRoleName(roleName)
}
}
}).catch(() => {
console.log('未登录')
});
}
});
};
const showAuthModal = () => {
Taro.showModal({
title: '授权提示',
content: '需要获取您的用户信息',
confirmText: '去授权',
cancelText: '取消',
success: (res) => {
if (res.confirm) {
// 用户点击确认,打开授权设置页面
openSetting();
}
}
});
};
const openSetting = () => {
// Taro.openSetting调起客户端小程序设置界面返回用户设置的操作结果。设置界面只会出现小程序已经向用户请求过的权限。
Taro.openSetting({
success: (res) => {
if (res.authSetting['scope.userInfo']) {
// 用户授权成功,可以获取用户信息
reload();
} else {
// 用户拒绝授权,提示授权失败
Taro.showToast({
title: '授权失败',
icon: 'none'
});
}
}
});
};
/* 获取用户手机号 */
const handleGetPhoneNumber = ({detail}) => {
const {code, encryptedData, iv} = detail
Taro.login({
success: function () {
if (code) {
Taro.request({
url: 'https://server.gxwebsoft.com/api/wx-login/loginByMpWxPhone',
method: 'POST',
data: {
code,
encryptedData,
iv,
notVerifyPhone: true,
refereeId: 0,
sceneType: 'save_referee',
tenantId: TenantId
},
header: {
'content-type': 'application/json',
TenantId
},
success: function (res) {
if(res.data.code == 1){
Taro.showToast({
title: res.data.message,
icon: 'error',
duration: 2000
})
return false;
}
// 登录成功
Taro.setStorageSync('access_token', res.data.data.access_token)
Taro.setStorageSync('UserId', res.data.data.user.userId)
setUserInfo(res.data.data.user)
setIsLogin(true)
}
})
} else {
console.log('登录失败!')
}
}
})
}
return (
<>
<div className={'p-4'}>
<div
className={'user-card w-full flex flex-col justify-around rounded-xl shadow-sm'}
style={{
background: 'linear-gradient(to bottom, #ffffff, #ffffff)', // 这种情况建议使用类名来控制样式(引入外联样式)
// width: '720rpx',
// margin: '10px auto 0px auto',
height: '180px',
// borderRadius: '22px 22px 0 0',
}}
>
<div className={'user-card-header flex w-full justify-between items-center pt-4'}>
<div className={'flex items-center mx-4'}>
{
IsLogin ? (
<Avatar size="large" src={userInfo?.avatar} shape="round"/>
) : (
<Button className={'text-black'} open-type="getPhoneNumber" onGetPhoneNumber={handleGetPhoneNumber}>
<Avatar size="large" src={userInfo?.avatar} shape="round"/>
</Button>
)
}
<div className={'user-info flex flex-col px-2'}>
<div className={'py-1 text-black font-bold'}>{IsLogin ? userInfo?.mobile : '请点击头像登录'}</div>
{IsLogin ? (
<div className={'grade text-xs py-1'}>
<Tag type="success" round>
<div className={'p-1'}>{roleName || '注册用户'}</div>
</Tag>
</div>
) : ''}
</div>
</div>
<div className={'mx-4 text-sm px-3 py-1 text-black border-gray-400 border-solid border-2 rounded-3xl'}
onClick={() => navTo('/user/profile/profile', true)}>
{'个人资料'}
</div>
</div>
<div className={'flex justify-around mt-5'}>
<div className={'item flex justify-center flex-col items-center'}>
<span className={'text-sm text-gray-500'}></span>
<span className={'text-xl'}>¥ 0.00</span>
</div>
<div className={'item flex justify-center flex-col items-center'}>
<span className={'text-sm text-gray-500'}></span>
<span className={'text-xl'}>0</span>
</div>
<div className={'item flex justify-center flex-col items-center'}>
<span className={'text-sm text-gray-500'}></span>
<span className={'text-xl'}>100</span>
</div>
</div>
</div>
</div>
</>
)
}
export default UserCard;

View File

@@ -0,0 +1,202 @@
import {Cell, InfiniteLoading} from '@nutui/nutui-react-taro'
import navTo from "@/utils/common";
import UserFooter from "./UserFooter";
import Taro from '@tarojs/taro'
import {ArrowRight, ShieldCheck, Truck, LogisticsError, Presentation, Coupon, PickedUp} from '@nutui/icons-react-taro'
import {CSSProperties} from "react";
const UserCell = () => {
const InfiniteUlStyle: CSSProperties = {
height: '88vh',
padding: '16px',
overflowY: 'auto',
overflowX: 'hidden',
}
const onLogout = () => {
Taro.showModal({
title: '提示',
content: '确定要退出登录吗?',
success: function (res) {
if (res.confirm) {
Taro.removeStorageSync('access_token')
Taro.removeStorageSync('TenantId')
Taro.removeStorageSync('UserId')
Taro.removeStorageSync('userInfo')
Taro.reLaunch({
url: '/pages/index/index'
})
}
}
})
}
return (
<>
<div className={'px-4'}>
{/*<Cell*/}
{/* className="nutui-cell-clickable"*/}
{/* title={*/}
{/* <div style={{display: 'inline-flex', alignItems: 'center'}}>*/}
{/* <Truck size={16}/>*/}
{/* <span className={'pl-3 text-sm'}>开通会员</span>*/}
{/* </div>*/}
{/* }*/}
{/*/>*/}
<Cell.Group divider={true} description={
<div style={{display: 'inline-flex', alignItems: 'center'}}>
<span style={{marginTop: '12px'}}></span>
</div>
}>
<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}/>}
/>
<Cell
className="nutui-cell-clickable"
title={
<div style={{display: 'inline-flex', alignItems: 'center'}}>
<LogisticsError size={16}/>
<span className={'pl-3 text-sm'}></span>
</div>
}
align="center"
extra={<ArrowRight color="#cccccc" size={18}/>}
/>
<Cell
className="nutui-cell-clickable"
title={
<div style={{display: 'inline-flex', alignItems: 'center'}}>
<LogisticsError size={16}/>
<span className={'pl-3 text-sm'}></span>
</div>
}
align="center"
extra={<ArrowRight color="#cccccc" size={18}/>}
/>
<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/index', true)
}}
/>
</Cell.Group>
{/*<Cell.Group divider={true} description={*/}
{/* <div style={{display: 'inline-flex', alignItems: 'center'}}>*/}
{/* <span style={{marginTop: '12px'}}>管理</span>*/}
{/* </div>*/}
{/*}>*/}
{/* <Cell*/}
{/* className="nutui-cell-clickable"*/}
{/* title={*/}
{/* <div style={{display: 'inline-flex', alignItems: 'center'}}>*/}
{/* <Presentation size={18}/>*/}
{/* <span style={{marginLeft: '5px'}}>分析</span>*/}
{/* </div>*/}
{/* }*/}
{/* align="center"*/}
{/* extra={<ArrowRight color="#cccccc" size={18}/>}*/}
{/* onClick={() => {*/}
{/* navTo('/bszx/bm-cert/bm-cert', true)*/}
{/* }}*/}
{/* />*/}
{/* <Cell*/}
{/* className="nutui-cell-clickable"*/}
{/* title={*/}
{/* <div style={{display: 'inline-flex', alignItems: 'center'}}>*/}
{/* <PickedUp size={18}/>*/}
{/* <span style={{marginLeft: '5px'}}>客户</span>*/}
{/* </div>*/}
{/* }*/}
{/* align="center"*/}
{/* extra={<ArrowRight color="#cccccc" size={18}/>}*/}
{/* onClick={() => {*/}
{/* navTo('/bszx/pay-log/pay-log', true)*/}
{/* }}*/}
{/* />*/}
{/* <Cell*/}
{/* className="nutui-cell-clickable"*/}
{/* title={*/}
{/* <div style={{display: 'inline-flex', alignItems: 'center'}}>*/}
{/* <Coupon size={18}/>*/}
{/* <span style={{marginLeft: '5px'}}>折扣</span>*/}
{/* </div>*/}
{/* }*/}
{/* align="center"*/}
{/* extra={<ArrowRight color="#cccccc" size={18}/>}*/}
{/* onClick={() => {*/}
{/* navTo('/user/profile/profile', true)*/}
{/* }}*/}
{/* />*/}
{/*</Cell.Group>*/}
{/*<Cell.Group divider={true} description={*/}
{/* <div style={{display: 'inline-flex', alignItems: 'center'}}>*/}
{/* <span style={{marginTop: '12px'}}>设置与帮助</span>*/}
{/* </div>*/}
{/*}>*/}
{/* <Cell*/}
{/* className="nutui-cell-clickable"*/}
{/* title="店铺设置"*/}
{/* align="center"*/}
{/* extra={<ArrowRight color="#cccccc" size={18}/>}*/}
{/* onClick={() => Taro.navigateTo({url: '/website/modify'})}*/}
{/* />*/}
{/* <Cell*/}
{/* className="nutui-cell-clickable"*/}
{/* title="帮助中心"*/}
{/* align="center"*/}
{/* extra={<ArrowRight color="#cccccc" size={18}/>}*/}
{/* onClick={() => {*/}
{/* navTo('/user/profile/profile', true)*/}
{/* }}*/}
{/* />*/}
{/* <Cell*/}
{/* className="nutui-cell-clickable"*/}
{/* title="问题反馈"*/}
{/* align="center"*/}
{/* extra={<ArrowRight color="#cccccc" size={18}/>}*/}
{/* onClick={() => {*/}
{/* navTo('/user/profile/profile', true)*/}
{/* }}*/}
{/* />*/}
{/*</Cell.Group>*/}
<Cell.Group divider={true} description={
<div style={{display: 'inline-flex', alignItems: 'center'}}>
<span style={{marginTop: '12px'}}></span>
</div>
}>
<Cell
className="nutui-cell-clickable"
title="账号安全"
align="center"
extra={<ArrowRight color="#cccccc" size={18}/>}
onClick={() => navTo('/user/profile/profile', true)}
/>
<Cell
className="nutui-cell-clickable"
title="退出登录"
align="center"
extra={<ArrowRight color="#cccccc" size={18}/>}
onClick={onLogout}
/>
</Cell.Group>
</div>
<UserFooter/>
</>
)
}
export default UserCell

View File

@@ -0,0 +1,102 @@
import {loginBySms} from "@/api/passport/login";
import {useState} from "react";
import Taro from '@tarojs/taro'
import {Popup} from '@nutui/nutui-react-taro'
import {UserParam} from "@/api/system/user/model";
import {Button} from '@nutui/nutui-react-taro'
import {Form, Input} from '@nutui/nutui-react-taro'
import {Copyright, Version} from "@/utils/config";
const UserFooter = () => {
const [openLoginByPhone, setOpenLoginByPhone] = useState(false)
const [clickNum, setClickNum] = useState<number>(0)
const [FormData, setFormData] = useState<UserParam>(
{
phone: undefined,
password: undefined
}
)
const onLoginByPhone = () => {
setFormData({})
setClickNum(clickNum + 1);
if (clickNum > 10) {
setOpenLoginByPhone(true);
}
}
const closeLoginByPhone = () => {
setClickNum(0)
setOpenLoginByPhone(false)
}
// 提交表单
const submitByPhone = (values: any) => {
loginBySms({
phone: values.phone,
code: values.code
}).then(() => {
setOpenLoginByPhone(false);
setTimeout(() => {
Taro.reLaunch({
url: '/pages/index/index'
})
},1000)
})
}
return (
<>
<div className={'text-center bg-gray-50 py-4 w-full text-gray-300'} onClick={onLoginByPhone}>
<div className={'text-xs text-gray-400 py-1'}>{Version}</div>
<div className={'text-xs text-gray-400 py-1'}>Copyright © { new Date().getFullYear() } {Copyright}</div>
</div>
<Popup
style={{width: '350px', padding: '10px'}}
visible={openLoginByPhone}
closeOnOverlayClick={false}
closeable={true}
onClose={closeLoginByPhone}
>
<Form
style={{width: '350px',padding: '10px'}}
divider
initialValues={FormData}
labelPosition="left"
onFinish={(values) => submitByPhone(values)}
footer={
<div
style={{
display: 'flex',
justifyContent: 'center',
width: '100%'
}}
>
<Button nativeType="submit" block style={{backgroundColor: '#000000',color: '#ffffff'}}>
</Button>
</div>
}
>
<Form.Item
label={'手机号码'}
name="phone"
required
rules={[{message: '手机号码'}]}
>
<Input placeholder="请输入手机号码" maxLength={11} type="text"/>
</Form.Item>
<Form.Item
label={'短信验证码'}
name="code"
required
rules={[{message: '短信验证码'}]}
>
<Input placeholder="请输入短信验证码" maxLength={6} type="text"/>
</Form.Item>
</Form>
</Popup>
</>
)
}
export default UserFooter

View File

@@ -0,0 +1,5 @@
export default definePageConfig({
navigationBarTitleText: '我的',
navigationStyle: 'custom',
navigationBarBackgroundColor: '#e9fff2'
})

8
src/pages/user/user.scss Normal file
View File

@@ -0,0 +1,8 @@
page {
background: linear-gradient(to bottom, #e9fff2, #f9fafb);
background-size: 100%;
}
.header-bg{
background: url('https://oss.wsdns.cn/20250621/edb5d4da976b4d97ba185cb7077d2858.jpg') no-repeat top center;
background-size: 100%;
}

19
src/pages/user/user.tsx Normal file
View File

@@ -0,0 +1,19 @@
import {useEffect} from 'react'
import UserCard from "./components/UserCard";
import UserCell from "./components/UserCell";
import './user.scss'
function User() {
useEffect(() => {
}, []);
return (
<>
<div className={'w-full header-bg pt-36'}>
<UserCard />
<UserCell />
</div>
</>
)
}
export default User