Browse Source

added language

main
mac 2 months ago
parent
commit
d8480d5af0
  1. 2
      .env
  2. 10
      src/App.tsx
  3. 10
      src/components/CountdownTimer.tsx
  4. 4
      src/components/SearchForm/index.tsx
  5. 51
      src/components/layout/Header.tsx
  6. 22
      src/components/layout/Slider.tsx
  7. 19
      src/components/profitChart.tsx
  8. 2
      src/language/index.ts
  9. 131
      src/language/zh.json
  10. 42
      src/pages/account/index.tsx
  11. 55
      src/pages/deposit/index.tsx
  12. 18
      src/pages/home/index.tsx
  13. 10
      src/pages/link/index.tsx
  14. 63
      src/pages/record/assets/index.tsx
  15. 40
      src/pages/record/bonus/index.tsx
  16. 17
      src/pages/record/deposit/index.tsx
  17. 12
      src/pages/record/escrow/index.tsx
  18. 20
      src/pages/record/withdraw/index.tsx
  19. 32
      src/pages/security/index.tsx
  20. 21
      src/pages/submit/index.tsx
  21. 4
      src/pages/team/index.tsx
  22. 46
      src/pages/transfer/index.tsx
  23. 36
      src/pages/withdraw/index.tsx
  24. 16
      src/router/index.tsx
  25. 6
      src/router/renderRouter.tsx
  26. 4
      src/router/routes.tsx
  27. 3
      src/styles/app.scss
  28. 17
      src/styles/home.scss
  29. 3
      src/utils/index.ts

2
.env

@ -1,3 +1,3 @@
SKIP_PREFLIGHT_CHECK=true
GENERATE_SOURCEMAP=false
REACT_APP_BASEURL='https://matontrading.com'
REACT_APP_BASEURL='http://203.161.61.234:8082'

10
src/App.tsx

@ -1,23 +1,23 @@
import { Suspense, lazy } from "react";
import RenderRouter from "./router";
import { HashRouter, Route, Routes } from 'react-router-dom';
import { Spin } from "antd";
import { useRouter } from "./hooks/useRouter";
const Submit = lazy(() => import("./pages/submit"));
function App() {
return (
<HashRouter>
<Suspense fallback={<div className='row-center' style={{ height: '80vh' }}>
<div className='tac'>
{/* <Loading color='#1BEDFF' size={30} /> */}
<div className='fz-16 sub-text mt-1'>...</div>
</div>
<Spin size="large" tip="Loading" />
</div>}>
<Routes>
<Route path="/submit" element={<Submit />} />
</Routes>
</Suspense>
<RenderRouter />
{<RenderRouter />}
</HashRouter>
);
}

10
src/components/CountdownTimer.tsx

@ -19,7 +19,7 @@ const CountdownTimer = forwardRef<CountdownTimerRef, CountdownTimerProps>((props
const { t } = useTranslation()
const [seconds, setSeconds] = useState(initialSeconds);
const [isActive, setIsActive] = useState(false);
const [title, setTitle] = useState(t('Send verification code'))
const [title, setTitle] = useState('Send verification code')
useImperativeHandle(ref, () => ({
handleStop,
@ -30,7 +30,7 @@ const CountdownTimer = forwardRef<CountdownTimerRef, CountdownTimerProps>((props
const handleStop = () => {
setIsActive(false);
setTitle(t('Send verification code'))
setTitle('Send verification code')
};
const handleStart = () => {
@ -46,8 +46,6 @@ const CountdownTimer = forwardRef<CountdownTimerRef, CountdownTimerProps>((props
useEffect(() => {
let interval: any = null;
console.log(seconds);
console.log(isActive);
if (isActive && seconds > 0) {
interval = setInterval(() => {
@ -55,7 +53,7 @@ const CountdownTimer = forwardRef<CountdownTimerRef, CountdownTimerProps>((props
}, 1000);
} else {
clearInterval(interval)
seconds <= 0 && setTitle(t('Resend'))
seconds <= 0 && setTitle('Resend')
setIsActive(false)
// onComplete && onComplete(seconds)
}
@ -64,7 +62,7 @@ const CountdownTimer = forwardRef<CountdownTimerRef, CountdownTimerProps>((props
}, [isActive, seconds, onComplete]);
return (
<div>{isActive ? <span className='fz-18 fw550'>{seconds}s</span> : title}</div>
<div style={{ whiteSpace: 'pre-wrap' }}>{isActive ? <span className='fz-18 fw550'>{seconds}s</span> : t(title)}</div>
);
});

4
src/components/SearchForm/index.tsx

@ -1,5 +1,6 @@
import React, { forwardRef, useImperativeHandle, FC } from 'react'
import { Form, Button } from 'antd'
import { useTranslation } from 'react-i18next';
interface SearchProps {
config: object[];
@ -12,6 +13,7 @@ interface SearchProps {
const SearchForm: FC<SearchProps> = forwardRef(
(props: SearchProps, ref) => {
const { config, handleSearch, beforeSearch, onFieldsChange } = props
const { t } = useTranslation()
const [form] = Form.useForm()
const getFields = (): JSX.Element[] => {
return config.map((item: any) => {
@ -62,7 +64,7 @@ const SearchForm: FC<SearchProps> = forwardRef(
{getFields()}
<Form.Item>
<Button htmlType="submit" type="primary">
{t('Search')}
</Button>
</Form.Item>
</Form>

51
src/components/layout/Header.tsx

@ -8,6 +8,8 @@ import Slider from "./Slider"
import { useRouter } from "../../hooks/useRouter"
import { AiOutlineMenuUnfold, AiOutlineMenuFold } from "react-icons/ai";
import { IoIosArrowDown } from "react-icons/io";
import LanguageMenu from "../LanguageMenu"
import { useTranslation } from "react-i18next"
const Header = () => {
@ -17,6 +19,7 @@ const Header = () => {
const [open, setOpen] = useState(false);
const [openMenu, setOpenMenu] = useState(false);
const fileInputRef = useRef<HTMLInputElement>(null)
const { t } = useTranslation()
const panelStyle: React.CSSProperties = {
background: 'none',
@ -26,49 +29,49 @@ const Header = () => {
const PopoverData = [
{
label: '资金管理',
label: t('Assets Manage'),
key: '1',
style: panelStyle,
children: (
<div style={{ width: 160 }}>
<p className="tp" onClick={() => to('/transfer')}></p>
<p className="mt-1 tp" onClick={() => to('/assetsRecords')}></p>
<p className="mt-1 tp" onClick={() => to('/escrowRecords')}></p>
<p className="tp" onClick={() => to('/transfer')}>{t('Assets transfer')}</p>
<p className="mt-1 tp" onClick={() => to('/assetsRecords')}>{t('Billing records')}</p>
<p className="mt-1 tp" onClick={() => to('/escrowRecords')}>{t('Escrow records')}</p>
</div>
)
},
{
label: '存款',
label: t('Deposit'),
style: panelStyle,
key: '2',
children: (
<div style={{ width: 160 }}>
<p className="tp" onClick={() => push('/deposit')}></p>
<p className="mt-1 tp" onClick={() => push('/depositRecords')}></p>
<p className="tp" onClick={() => push('/deposit')}>{t('Transfer deposit')}</p>
<p className="mt-1 tp" onClick={() => push('/depositRecords')}>{t('Deposit records')}</p>
</div>
)
},
{
label: '取款',
label: t('Withdraw'),
style: panelStyle,
key: '3',
children: (
<div style={{ width: 160 }}>
<p className="tp" onClick={() => push('/account')}></p>
<p className="mt-1 tp" onClick={() => push('/withdraw')}></p>
<p className="mt-1 tp" onClick={() => push('/withdrawRecords')}></p>
<p className="tp" onClick={() => push('/account')}>{t('Collection account')}</p>
<p className="mt-1 tp" onClick={() => push('/withdraw')}>{t('Handle withdraw')}</p>
<p className="mt-1 tp" onClick={() => push('/withdrawRecords')}>{t('Withdraw records')}</p>
</div>
)
},
{
label: '我的团队',
label: t('My team'),
style: panelStyle,
key: '4',
children: (
<div style={{ width: 160 }}>
<p className="tp" onClick={() => push('/link')}>广</p>
<p className="mt-1 tp" onClick={() => to('/team')}></p>
<p className="mt-1 tp" onClick={() => push('/bonusRecords')}></p>
<p className="tp" onClick={() => push('/link')}>{t('Sponsored link')}</p>
<p className="mt-1 tp" onClick={() => to('/team')}>{t('Team details')}</p>
<p className="mt-1 tp" onClick={() => push('/bonusRecords')}>{t('Bonus details')}</p>
</div>
)
@ -94,10 +97,10 @@ const Header = () => {
const popoverAvatar = (
<div style={{ minWidth: 150 }}>
<div className="tx-over" style={{ maxWidth: 300 }}>{userInfo.name}</div>
<div className="mt-1 tp" onClick={() => push('/security')}></div>
<div className="tx-over" style={{ maxWidth: 300 }}>{t('Hello')}{userInfo.name}</div>
<div className="mt-1 tp" onClick={() => push('/security')}>{t('Security settings')}</div>
<div className="divider mtb-1"></div>
<div className="tp" onClick={logout}>退</div>
<div className="tp" onClick={logout}>{t('Log out')}</div>
</div>
)
@ -109,7 +112,7 @@ const Header = () => {
<div></div> */}
{
PopoverData.map((item, index) => (
<div className="mr-4" key={index}>
<div className="mr-3" key={index}>
<Popover placement="bottomLeft" content={item.children}>
<div className="tp row-items">
<div>{item.label}</div>
@ -130,6 +133,9 @@ const Header = () => {
</div>
</Button>
</Popover>
<div style={{ marginTop: 5 }} className="ml-1">
<LanguageMenu width={40} />
</div>
</div>
</div>
)
@ -141,7 +147,12 @@ const Header = () => {
<Popover content={popoverAvatar} placement="bottomRight" trigger="click">
<img src="https://cfile.uworkcrm.com/static/images/avtar.jpg" alt="" className="avatar tp" />
</Popover>
<div className="text-white ml-1 fz-24 tp" onClick={showDrawer}><AiOutlineMenuFold /></div>
<div className="row-items">
<div className="text-white ml-1 fz-24 tp" onClick={showDrawer}><AiOutlineMenuFold /></div>
<div className="ml-1">
<LanguageMenu width={30} />
</div>
</div>
</div>
</div>
)

22
src/components/layout/Slider.tsx

@ -12,21 +12,23 @@ import { BiMoneyWithdraw } from "react-icons/bi";
import { GrUserSettings } from "react-icons/gr";
import { MdOutlineSecurity } from "react-icons/md";
import { CiWallet } from "react-icons/ci";
import { useTranslation } from "react-i18next";
const Slider = () => {
const { push } = useRouter()
const { screenWidth, userInfo } = store.state
const { t } = useTranslation()
const tabs = [
{ title: 'Android 下载', id: 1, Icon: <BsAndroid2 /> },
{ title: 'IPhone 下载', id: 2, Icon: <BsApple /> },
{ title: '仪表盘', id: 3, Icon: <IoHome /> },
{ title: '办理存款', id: 4, Icon: <FaUserNinja /> },
{ title: '资金划转', id: 5, Icon: <RiExchangeBoxLine /> },
{ title: '办理取款', id: 6, Icon: <BiMoneyWithdraw /> },
{ title: '收款账户', id: 7, Icon: <GrUserSettings /> },
{ title: '安全设定', id: 8, Icon: <MdOutlineSecurity /> },
{ title: 'Android Download', id: 1, Icon: <BsAndroid2 /> },
{ title: 'IPhone Download', id: 2, Icon: <BsApple /> },
{ title: 'Dashboard', id: 3, Icon: <IoHome /> },
{ title: 'Handle deposit', id: 4, Icon: <FaUserNinja /> },
{ title: 'Assets transfer', id: 5, Icon: <RiExchangeBoxLine /> },
{ title: 'Handle withdraw', id: 6, Icon: <BiMoneyWithdraw /> },
{ title: 'Collection account', id: 7, Icon: <GrUserSettings /> },
{ title: 'Security settings', id: 8, Icon: <MdOutlineSecurity /> },
]
const handleLeftMenu = (id: number) => {
@ -70,7 +72,7 @@ const Slider = () => {
<div className="row-center mt-1">
<Button className="balance-button">
<div>
<div> ${userInfo.total_assets || 0}</div>
<div>{t('total assets')}${userInfo.total_assets || 0}</div>
<div className="fz-wb-550 row-center"><CiWallet /> <span style={{ marginLeft: 5 }}>${userInfo.balance || 0}</span></div>
</div>
</Button>
@ -81,7 +83,7 @@ const Slider = () => {
<div key={index} className="tab-box mb-2 text-white row-center tp" onClick={() => handleLeftMenu(item.id)}>
<div>
<div className="tac fz-26">{item.Icon}</div>
<div className="tac">{item.title}</div>
<div className="tac">{t(item.title)}</div>
</div>
</div>
))

19
src/components/profitChart.tsx

@ -1,15 +1,17 @@
import React, { useEffect, useRef } from 'react';
import ReactECharts from 'echarts-for-react';
import echarts from 'echarts/types/dist/echarts';
import { useTranslation } from 'react-i18next';
const ProfitChart = (props: any) => {
const { data } = props
const reactECharts = useRef<ReactECharts>(null)
const { t, i18n } = useTranslation()
const option = {
title: {
text: '我的收益走势',
text: t('My earnings trend'),
left: 'left',
textStyle: {
color: '#333',
@ -26,7 +28,7 @@ const ProfitChart = (props: any) => {
},
tooltip: {
trigger: 'axis',
formatter: '{b0}<br />Profit: {c0}',
formatter: `{b0}<br />${t('Profit')}: {c0}`,
backgroundColor: 'rgba(255, 255, 255, 0.9)',
borderColor: '#ccc',
borderWidth: 1,
@ -90,19 +92,20 @@ const ProfitChart = (props: any) => {
]
};
useEffect(() => {
const handleResize = () => {
if (!reactECharts.current) return
const instance = reactECharts.current.getEchartsInstance()
instance.resize()
}
const handleResize = () => {
if (!reactECharts.current) return
const instance = reactECharts.current.getEchartsInstance()
instance.resize()
}
useEffect(() => {
window.addEventListener('resize', handleResize)
return () => {
window.removeEventListener('resize', handleResize)
}
}, [])
return (
<ReactECharts option={option} style={{ height: '100%', width: '100%' }} ref={reactECharts} />
);

2
src/language/index.ts

@ -12,7 +12,7 @@ const resources = {
i18n.use(initReactI18next).init({
resources,
lng: window.sessionStorage.getItem(TRADER_LANGUAGE) || "zh",
lng: window.localStorage.getItem(TRADER_LANGUAGE) || "zh",
interpolation: {
escapeValue: false,
},

131
src/language/zh.json

@ -20,5 +20,134 @@
"Resend": "重新发送",
"Register Successful": "注册成功",
"Verification code sent successfully": "验证码发送成功",
"Failed to send verification code": "验证码发送失败"
"Failed to send verification code": "验证码发送失败",
"total assets": "总资产",
"Android Download": "安卓下载",
"IPhone Download": "IOS下载",
"Dashboard": "仪表盘",
"Handle deposit": "办理存款",
"Assets transfer": "资金划转",
"Handle withdraw": "办理取款",
"Collection account": "收款账户",
"Security settings": "安全设定",
"Assets Manage": "资金管理",
"Deposit": "存款",
"Withdraw": "取款",
"My team": "我的团队",
"Billing records": "账单记录",
"Escrow records": "托管记录",
"Transfer deposit": "转账存款",
"Deposit records": "存款记录",
"Withdraw records": "取款记录",
"Sponsored link": "推荐链接",
"Team details": "团队详情",
"Bonus details": "奖金明细",
"Hello": "您好",
"Log out": "退出登录",
"Total revenue": "总收益",
"My earnings trend": "我的收益走势",
"Profit": "收益",
"Account": "账户",
"Capital": "资本",
"Balance": "余额",
"Creditworthiness": "信用度",
"net worth": "净值",
"Account status": "账户状态",
"Assets transfer-matters needing attention": "资金划转-注意事项",
"1.Please ensure the safety of the equipment during use,Prevent data from being tampered with or leaked。": "1.在使用过程中请务必确认设备安全,防止数据被篡改或泄露。",
"2.In the process of fund transfer, if there is a delay or other situation,Please handle it later or contact customer service。": "2.资金转账过程中如遇卡顿等情况,请稍后处理或联系客服。",
"3.After fund transfer operation,There may be delays in the system;If exceeding10Minutes have not yet arrived,Please contact customer service。": "3.资金转账操作后,系统会有延时情况;如超过10分钟仍未到账,请联系客服。",
"Assets operations": "资金操作",
"Please select an operation type...": "请选择操作类型...",
"Wallet balance": "钱包余额",
"Asset account amount": "资产账户金额",
"Capital account": "资金账户",
"Member account": "会员账号",
"Please enter the other party’s login account (email)": "请输入对方登录账户(邮箱)",
"Email format error": "邮箱格式错误",
"Please enter the transfer amount": "请输入转账金额",
"Transfer amount": "转账金额",
"submit": "提交",
"Submit": "提交",
"Submit success": "提交成功",
"Cash Wallet-Asset Account": "现金钱包-资产账户",
"Asset Account-Cash Wallet": "资产账户-现金钱包",
"Cash Wallet-Other Members": "现金钱包-其他会员",
"Status": "状态",
"Time": "时间",
"Event": "事件",
"Order": "订单",
"Amount": "金额",
"Describe": "描述",
"Remaining": "剩余",
"Assets account records": "资金账户记录",
"Start time": "开始时间",
"End time": "结束时间",
"Transfer amount must be greater than 0": "转账金额必须大于 0",
"Please upload payment voucher": "请上传付款凭证",
"Strategy Quantitative Deposit-Deposit Notes": "策略量化存款-存款注意事项",
"Dear customer, please be sure to carefully check that all wallet addresses are consistent when transferring funds. After the transfer is completed, please upload the transfer voucher in time.": "尊敬的客户,请您转账时务必仔细检查钱包地址全部一致。转账完毕后,请及时上传转账凭证。",
"Deposit To": "存款到",
"Deposit amount": "存款金额",
"Please enter the deposit amount": "请输入存款金额",
"Next": "下一步",
"Please transfer money to the account below": "请向下方账户转账",
"Wallet type": "钱包类型",
"Wallet Address": "钱包地址",
"Upload payment voucher": "上传付款凭证",
"Delete": "删除",
"Cancel": "取消",
"Amount received": "到账金额",
"Payment amount": "付款金额",
"Symbol": "币种",
"Added successfully": "添加成功",
"Strips are bound": "条已绑定",
"Fill in the payment account": "填写收款账户",
"Valid": "有效",
"Add payment account": "添加收款账户",
"Receive methods": "收款方式",
"Please choose receive methods": "请选择收款方式",
"Please enter a chain type": "请输入链类型",
"Please enter a wallet type": "请输入钱包地址",
"Save": "保存",
"Chain type": "链类型",
"Insufficient balance": "余额不足",
"Hint": "提示",
"Please make sure the device is safe during use to prevent data tampering or leakage.": "在使用过程中请务必确认设备安全,防止数据篡改或泄露。",
"Withdraw account": "取款账号",
"Cash Wallet": "现金钱包",
"Please enter the withdrawal amount": "请输入取款金额",
"Please select a receive method...": "请选择收款方式...",
"please enter verification code": "请输入验证码",
"Withdraw amount": "取款金额",
"Account name": "收款户名",
"Receive address": "收款地址",
"Promotion links": "推广链接",
"Agent promotion link": "代理推广链接",
"Referral code": "推荐码",
"Copy link": "复制链接",
"Copy successfully": "复制成功",
"Please choose the type": "请选择类型",
"Trading profit": "交易利润",
"Profit dividends": "盈利分红",
"Super reward": "超级奖励",
"Trading commissions": "交易佣金",
"Star reward": "星级奖励",
"All types": "全部类型",
"Order number": "订单号",
"Please enter order number": "请输入订单号",
"Please enter the capital account": "请输入资金账户",
"From": "来自",
"Search": "搜索",
"Platform announcement": "平台公告",
"Modification successful, please log in again": "修改成功,请重新登录",
"Please enter a new password": "请输入新密码",
"Password must contain letters and numbers and be 8-32 characters long": "密码必须包含字母和数字,长度为8-32位",
"Change login password": "修改登录密码",
"1. Please make sure the device is safe during use to prevent data from being tampered with or leaked.": "1.在使用过程中请务必确认设备安全,防止数据被篡改或泄露。",
"2. The email verification code may be delayed, please wait patiently.": "2.邮箱验证码可能会延时送达,请您耐心等待。",
"Password must be a combination of letters and numbers":"密码必须是字母加数字的组合",
"New password":"新密码",
"Please enter a account":"请输入账号",
"Please enter a password":"请输入密码"
}

42
src/pages/account/index.tsx

@ -5,6 +5,7 @@ import store from '../../store'
import { getTime } from '../../utils'
import { useEffect, useState } from 'react'
import { http_addReceiveAccount, http_token } from '../../http/api'
import { useTranslation } from 'react-i18next'
const Account = () => {
@ -13,6 +14,7 @@ const Account = () => {
const [visible, setVisible] = useState(false)
const [options, setOptions] = useState([])
const [tokenId, setTokenId] = useState(-1)
const { t } = useTranslation()
const getData = async () => {
const res: any = await http_token()
@ -20,7 +22,7 @@ const Account = () => {
if (res.code === 0) {
res.data.forEach((item: any) => {
_options.push({
label: `${item.symbol}取款 - 币种${item.symbol}`,
label: `${item.symbol} ${t('Withdraw')} - ${t('Symbol')}${item.symbol}`,
value: item.id
})
})
@ -36,7 +38,7 @@ const Account = () => {
if (res.code === 0) {
store.getReceiveAccount()
notification.success({
message: '添加成功'
message: t('Added successfully')
})
form.resetFields()
setTokenId(-1)
@ -46,37 +48,37 @@ const Account = () => {
useEffect(() => {
getData()
}, [])
}, [t])
return (
<div className='account'>
<div className="row-between mb-2">
<div className="row-items">
<div className='text-white fz-22'></div>
<div className="fz-22 ml-1 fz-wb-550 text-blue">{receiveAccount.length} </div>
<div className="fz-14 text-white"></div>
<div className='text-white fz-22'>{t('Handle deposit')}</div>
<div className="fz-22 ml-1 fz-wb-550 text-blue">{receiveAccount.length} </div>
<div className="fz-14 text-white">{t('Strips are bound')}</div>
</div>
<div className="fz-wb-550 text-white tp" onClick={() => setVisible(true)}></div>
<div className="fz-wb-550 text-white tp" onClick={() => setVisible(true)}>+{t('Fill in the payment account')}</div>
</div>
{
receiveAccount.map(item => (
<div className='container p-2 mb-2' key={item.id}>
<div className='text-success'></div>
<div className='text-success'>{t('Valid')}</div>
<div className='border p-2 mt-2 fz-14'>
<div>{item.type}</div>
<div className='text-sub'></div>
<div className='text-sub'>{t('Wallet type')}</div>
<div className='mt-2'>{item.address}</div>
<div className='text-sub'></div>
<div className='text-sub'>{t('Wallet Address')}</div>
<QRCode value={item.address} bordered={false} />
</div>
<div className='fz-14 mt-2'> <span className='fz-wb-550 text-blue'>{getTime(item.time * 1000)}</span></div>
<div className='fz-14 mt-2'>{t('Time')} <span className='fz-wb-550 text-blue'>{getTime(item.time * 1000)}</span></div>
</div>
))
}
<Modal
open={visible}
onClose={() => setVisible(false)}
title="添加收款账户"
title={t('Add payment account')}
footer={null}
>
<Form
@ -85,25 +87,25 @@ const Account = () => {
className='mt-2'
onFinish={onFinish}
>
<Form.Item label={<span className='fz-wb-550'></span>}>
<Select style={{ height: 45 }} options={options} placeholder="请选择收款方式" onSelect={val => setTokenId(val)} />
<Form.Item label={<span className='fz-wb-550'>{t('Receive methods')}</span>}>
<Select style={{ height: 45 }} options={options} placeholder={t('Please choose receive methods')} onSelect={val => setTokenId(val)} />
</Form.Item>
{
tokenId >= 0 && (
<>
<Form.Item name="type" rules={[{ required: true, message: '请输入链类型' }]} label={<span className='fz-wb-550'></span>}>
<Input style={{ height: 45 }} placeholder='请输入链类型' />
<Form.Item name="type" rules={[{ required: true, message: t('Please enter a chain type') }]} label={<span className='fz-wb-550'>{t('Chain type')}</span>}>
<Input style={{ height: 45 }} placeholder={t('Please enter a chain type')} />
</Form.Item>
<Form.Item name="address" rules={[{ required: true, message: '请输入钱包地址' }]} label={<span className='fz-wb-550'></span>}>
<Input style={{ height: 45 }} placeholder='请输入钱包地址' />
<Form.Item name="address" rules={[{ required: true, message: t('Please enter a wallet type') }]} label={<span className='fz-wb-550'>{t('Wallet Address')}</span>}>
<Input style={{ height: 45 }} placeholder={t('Please enter a wallet type')} />
</Form.Item>
</>
)
}
<div className='row-justify-end'>
<Button onClick={() => setVisible(false)}></Button>
<Button className='ml-1' type='primary' htmlType='submit'></Button>
<Button onClick={() => setVisible(false)}>{t('Cancel')}</Button>
<Button className='ml-1' type='primary' htmlType='submit'>{t('Save')}</Button>
</div>
</Form>
</Modal>

55
src/pages/deposit/index.tsx

@ -6,6 +6,7 @@ import { observer } from 'mobx-react'
import store from '../../store'
import { copy } from '../../utils'
import imageCompression from 'browser-image-compression';
import { useTranslation } from 'react-i18next'
const Deposit = () => {
@ -19,6 +20,7 @@ const Deposit = () => {
const [imgUrl, setImgUrl] = useState([] as string[])
const fileRef = useRef<HTMLInputElement>(null)
let [loading, setLoading] = useState([] as any)
const { t } = useTranslation()
const getData = async () => {
const res: any = await http_depositAddress()
@ -39,10 +41,10 @@ const Deposit = () => {
const validateAmount = (_: any, value: string) => {
if (!value) {
return Promise.reject(new Error('请输入转账金额'))
return Promise.reject(new Error(t('Please enter the transfer amount')))
}
if (Number(value) <= 0) {
return Promise.reject(new Error('转账金额必须大于 0'))
return Promise.reject(new Error(t('Transfer amount must be greater than 0')))
}
return Promise.resolve();
}
@ -59,7 +61,7 @@ const Deposit = () => {
const submit = async (index: number) => {
const file = urls[index]
if (!file) return notification.warning({ message: '请上传付款凭证' });
if (!file) return notification.warning({ message: t('Please upload payment voucher') });
try {
loading[index] = true
setLoading([...loading])
@ -69,7 +71,6 @@ const Deposit = () => {
useWebWorker: true,
initialQuality: 1
});
const result: any = await http_upload(compressedFile)
if (result.code === 0) {
const res: any = await http_transferDeposit({
@ -85,7 +86,7 @@ const Deposit = () => {
visibles[index] = false
setVisibles([...visibles])
notification.success({
message: '提交成功'
message: t('Submit success')
})
}
}
@ -100,7 +101,7 @@ const Deposit = () => {
try {
if (fileList && fileList.length > 0) {
urls[index] = fileList[0]
console.log('当前文件大小', fileList[0].size / 1024 / 1024);
// console.log('当前文件大小', fileList[0].size / 1024 / 1024);
setUrls([...urls])
fileToBase64(fileList[0]).then((res: any) => {
if (res) {
@ -121,14 +122,13 @@ const Deposit = () => {
return (
<div className="deposit">
<div className='text-white fz-22 mb-2 tp' onClick={() => setVisibles(receiveAdds.map(v => false))}></div>
<div className='text-white fz-22 mb-2'>{t('Handle deposit')}</div>
{
receiveAdds.map((item, index) => !visibles[index] && (
<div className="flex-1 container" key={index}>
<div className='p-2'>
<div className='fz-wb-550'>-</div>
<div className='text-sub fz-14 mt-1'></div>
<div className='fz-wb-550'>{t('Strategy Quantitative Deposit-Deposit Notes')}</div>
<div className='text-sub fz-14 mt-1'>{t('Dear customer, please be sure to carefully check that all wallet addresses are consistent when transferring funds. After the transfer is completed, please upload the transfer voucher in time.')}</div>
</div>
<div className='divider' style={{ backgroundColor: '#8492a6' }}></div>
<div className='p-2'>
@ -137,15 +137,15 @@ const Deposit = () => {
onFinish={val => onFinish(val, index)}
form={form}
>
<Form.Item label={<span className='fz-wb-550'></span>}>
<Select style={{ height: 50 }} value={`(CFD)${userInfo.account} 余额:${userInfo.account_balance}`} className='tac' />
<Form.Item label={<span className='fz-wb-550'>{t('Deposit To')}</span>}>
<Select style={{ height: 50 }} value={`(CFD)${userInfo.account} ${t('Balance')}:${userInfo.account_balance}`} className='tac' />
</Form.Item>
<Form.Item name="amount" rules={[{ validator: validateAmount }]} label={<span className='fz-wb-550'></span>}>
<Input style={{ height: 50 }} placeholder='请输入存款金额' />
<Form.Item name="amount" rules={[{ validator: validateAmount }]} label={<span className='fz-wb-550'>{t('Deposit amount')}</span>}>
<Input style={{ height: 50 }} placeholder={t('Please enter the deposit amount')} />
</Form.Item>
<Form.Item>
<div className='row-justify-end'>
<Button type='primary' htmlType='submit' style={{ borderRadius: 30 }}></Button>
<Button type='primary' htmlType='submit' style={{ borderRadius: 30 }}>{t('Next')}</Button>
</div>
</Form.Item>
</Form>
@ -158,24 +158,24 @@ const Deposit = () => {
receiveAdds.map((item: any, index: number) => visibles[index] && (
<div key={item.id} className="flex-1 container mb-2">
<div className='p-2'>
<div className='fz-wb-550'>-</div>
<div className='text-sub fz-14 mt-1'></div>
<div className='fz-wb-550'>{t('Strategy Quantitative Deposit-Deposit Notes')}</div>
<div className='text-sub fz-14 mt-1'>{t('Dear customer, please be sure to carefully check that all wallet addresses are consistent when transferring funds. After the transfer is completed, please upload the transfer voucher in time.')}</div>
</div>
<div className='divider' style={{ backgroundColor: '#8492a6' }}></div>
<div className='p-2'>
<div className='text-sub'></div>
<div className='text-sub'>{t('Please transfer money to the account below')}</div>
<div className='plr-1'>
<div className='row-items mt-2'>
<div className='fz-wb-550 fz-14'></div>
<div className='fz-wb-550 fz-14'>{t('Wallet type')}</div>
<Tag color='#87d068' className='ml-1'>{item.type}</Tag>
</div>
<div className='mt-2 fz-wb-550 fz-14'></div>
<div className='mt-2 fz-wb-550 fz-14'>{t('Wallet Address')}</div>
<Tag color='#87d068' className='mt-1' onClick={() => copy(item.address)}>{item.address}</Tag>
<div className='mt-2'>
<QRCode value={item.address} />
</div>
<div className='mt-2 row-items'>
<div className='fz-14 fz-wb-550 mr-2'></div>
<div className='fz-14 fz-wb-550 mr-2'>{t('Upload payment voucher')}</div>
<input ref={fileRef} type="file" onChange={e => onChange(e.target.files, index)} style={{ display: 'none' }} />
<div className='upload row-center'>
{
@ -186,7 +186,7 @@ const Deposit = () => {
imgUrl[index] = ''
fileRef.current!.value = ''
setImgUrl([...imgUrl])
}}></Button>
}}>{t('Delete')}</Button>
<Image
style={{ width: '100%' }}
src={imgUrl[index]}
@ -195,7 +195,7 @@ const Deposit = () => {
) : (
<div style={{ color: '#c2c6cd' }} className='tac' onClick={() => fileRef.current!.click()}>
<div className='fz-24'>+</div>
<div className='fz-12'></div>
<div className='fz-12'>{t('Upload payment voucher')}</div>
</div>
)
}
@ -204,7 +204,14 @@ const Deposit = () => {
</div>
<div className='row-center mt-4'>
<Button loading={!!loading[index]} type='primary' disabled={!urls[index]} onClick={() => submit(index)}></Button>
<Button onClick={() => {
urls[index] = null
imgUrl[index] = ''
fileRef.current!.value = ''
visibles[index] = false
setImgUrl([...imgUrl])
}} style={{ marginRight: 20 }}>{t('Cancel')}</Button>
<Button loading={!!loading[index]} type='primary' disabled={!urls[index]} onClick={() => submit(index)}>{t('Submit')}</Button>
</div>
</div>
</div>

18
src/pages/home/index.tsx

@ -6,10 +6,12 @@ import { useEffect, useState } from 'react';
import store from '../../store';
import { http_earn_trend } from '../../http/api';
import { observer } from 'mobx-react';
import { useTranslation } from 'react-i18next';
const Home = () => {
const { token, userInfo } = store.state
const { t } = useTranslation()
const [chartData, setChartData] = useState({
times: [],
values: []
@ -43,14 +45,14 @@ const Home = () => {
return (
<div className="home">
<div className="text-white fz-22 fz-wb-500 mb-2"></div>
<div className="text-white fz-22 fz-wb-500 mb-2">{t('Dashboard')}</div>
<div className='box'>
<div className="income p-1">
<ProfitChart data={chartData} />
</div>
<div className="total-income row-center">
<div>
<div className='tac fz-22 mb-1'></div>
<div className='tac fz-22 mb-1'>{t('Total revenue')}</div>
<Progress type="circle" percent={50} size={150} strokeColor="#f7b93f" format={() => `$${userInfo.total_income || 0}`} />
</div>
</div>
@ -58,7 +60,7 @@ const Home = () => {
<div className='CFD-box mt-2 p-2'>
<div className='row-between'>
<div>CFD {userInfo.account}</div>
<div>CFD {t('Account')} {userInfo.account}</div>
<HiDotsVertical />
</div>
<div className='mt-2'>
@ -66,28 +68,28 @@ const Home = () => {
<tbody>
<tr style={{ background: '#fff' }}>
<td className='tac'>
<p></p>
<p>{t('Capital')}</p>
<p className='text-success'>${userInfo.account_capital || 0}</p>
</td>
</tr>
<tr style={{ background: '#fff' }}>
<td className='tac'>
<p></p>
<p>{t('Balance')}</p>
<p className='text-success'>${userInfo.account_balance || 0}</p>
</td>
</tr>
<tr style={{ background: '#fff' }}>
<td className='tac'>
<p></p>
<p>{t('Creditworthiness')}</p>
<p className='text-success'>${userInfo.account_credit || 0}</p>
</td>
</tr>
<tr style={{ background: '#fff' }}>
<td className='tac'>
<p></p>
<p>{t('net worth')}</p>
<p className='text-success'>${userInfo.account_net_worth || 0}</p>
</td>
</tr>
@ -95,7 +97,7 @@ const Home = () => {
</tbody>
</table>
</div>
<div className='mt-2'>{userInfo.account_status}</div>
<div className='mt-2'>{t('Account status')}{userInfo.account_status}</div>
</div>
<div className='mt-2'>

10
src/pages/link/index.tsx

@ -5,24 +5,26 @@ import { IoCopyOutline } from "react-icons/io5";
import { copy } from '../../utils';
import { observer } from 'mobx-react';
import store from '../../store';
import { useTranslation } from 'react-i18next';
const Link = () => {
const { userInfo } = store.state
const { t } = useTranslation()
return (
<div className='link'>
<div className='text-white fz-22 mb-2'>广</div>
<div className='text-white fz-22 mb-2'>{t('Promotion links')}</div>
<div className='container ptb-2'>
<div className='plr-2'>广</div>
<div className='plr-2'>{t('Agent promotion link')}</div>
<div className='divider mt-2'></div>
<div className='plr-2'>
<div className='row-center'>
<QRCode value={`${window.origin}/#/createProxy?code=${userInfo.inviti_code}`} bordered={false} />
</div>
<div className='tac fz-14 fz-wb-550 mt-1 row-center'>
<span></span>
<span>{t('Referral code')}</span>
<span className='text-success'>{userInfo.inviti_code}</span>
<IoCopyOutline className='ml-1 tp' onClick={() => copy(userInfo.inviti_code)} />
</div>
@ -40,7 +42,7 @@ const Link = () => {
backgroundColor: '#007DBA'
}}
onClick={() => copy(`${window.origin}/#/createProxy?code=${userInfo.inviti_code}`)}
></Button>
>{t('Copy link')}</Button>
</div>
</div>
</div>

63
src/pages/record/assets/index.tsx

@ -7,11 +7,12 @@ import { useMemo } from 'react'
import { ConfigProvider, Tabs } from 'antd'
import { http_account_assetsRecords, http_cash } from '../../../http/api'
import { getTime } from '../../../utils'
import { useTranslation } from 'react-i18next'
const AssetsRecords = () => {
const { screenWidth } = store.state
const { t } = useTranslation()
const containerWidth = useMemo(() => {
if (screenWidth > 1420) {
return 1420 - 310
@ -28,12 +29,12 @@ const AssetsRecords = () => {
apiFun={http_account_assetsRecords}
columns={[
{
title: '状态',
title: t('Status'),
dataIndex: 'status',
width: 150
},
{
title: '时间',
title: t('Time'),
dataIndex: 'time',
width: 200,
render: (time: number) => (
@ -41,28 +42,28 @@ const AssetsRecords = () => {
)
},
{
title: '事件',
title: t('Event'),
dataIndex: 'event',
width: 150
},
{
title: '订单',
title: t('Order'),
dataIndex: 'order',
width: 120
},
{
title: '账户',
title: t('Account'),
dataIndex: 'account'
},
{
title: '金额',
title: t('Amount'),
dataIndex: 'amount',
render: (val: string) => (
<span>${val}</span>
)
},
{
title: '描述',
title: t('Describe'),
dataIndex: 'describe'
},
@ -78,7 +79,7 @@ const AssetsRecords = () => {
extraProps={{ type: 1 }}
columns={[
{
title: '时间',
title: t('Time'),
dataIndex: 'time',
width: 200,
render: (time: number) => (
@ -86,26 +87,26 @@ const AssetsRecords = () => {
)
},
{
title: '订单',
title: t('Order'),
dataIndex: 'order',
},
{
title: '描述',
title: t('Describe'),
dataIndex: 'describe',
},
{
title: '金额',
title: t('Describe'),
dataIndex: 'amount'
},
{
title: '剩余',
title: t('Remaining'),
dataIndex: 'balance',
render: (val: string) => (
<span>${val}</span>
)
},
{
title: '状态',
title: t('Status'),
dataIndex: 'status'
},
]}
@ -120,7 +121,7 @@ const AssetsRecords = () => {
extraProps={{ type: 2 }}
columns={[
{
title: '时间',
title: t('Time'),
dataIndex: 'time',
width: 200,
render: (time: number) => (
@ -128,26 +129,26 @@ const AssetsRecords = () => {
)
},
{
title: '订单',
title: t('Order'),
dataIndex: 'order',
},
{
title: '描述',
title: t('Describe'),
dataIndex: 'describe',
},
{
title: '金额',
title: t('Amount'),
dataIndex: 'amount'
},
{
title: '剩余',
title: t('Remaining'),
dataIndex: 'balance',
render: (val: string) => (
<span>${val}</span>
)
},
{
title: '状态',
title: t('Status'),
dataIndex: 'status'
},
]}
@ -162,7 +163,7 @@ const AssetsRecords = () => {
extraProps={{ type: 3 }}
columns={[
{
title: '时间',
title: t('Time'),
dataIndex: 'time',
width: 200,
render: (time: number) => (
@ -170,26 +171,26 @@ const AssetsRecords = () => {
)
},
{
title: '订单',
title: t('Order'),
dataIndex: 'order',
},
{
title: '描述',
title: t('Describe'),
dataIndex: 'describe',
},
{
title: '金额',
title: t('Amount'),
dataIndex: 'amount'
},
{
title: '剩余',
title: t('Remaining'),
dataIndex: 'balance',
render: (val: string) => (
<span>${val}</span>
)
},
{
title: '状态',
title: t('Status'),
dataIndex: 'status'
},
]}
@ -199,7 +200,7 @@ const AssetsRecords = () => {
return (
<div className="records" >
<div className='text-white fz-22'></div>
<div className='text-white fz-22'>{t('Billing records')}</div>
<ConfigProvider theme={{
components: {
Tabs: {
@ -212,22 +213,22 @@ const AssetsRecords = () => {
<Tabs defaultActiveKey='1' tabPosition="top" items={[
{
key: '1',
label: '资金账户记录',
label: t('Assets account records'),
children: AccountRecord(),
},
{
key: '2',
label: '现金钱包->资金账户',
label: t('Cash Wallet-Asset Account'),
children: WalletToAsseetRecord(),
},
{
key: '3',
label: '现金钱包->其他会员',
label: t('Cash Wallet-Other Members'),
children: AssetToVipRecords(),
},
{
key: '4',
label: '资产账户->现金钱包',
label: t('Asset Account-Cash Wallet'),
children: AssetToWalletRecords(),
}
]} />

40
src/pages/record/bonus/index.tsx

@ -7,10 +7,12 @@ import { useMemo } from 'react'
import { http_bonus } from '../../../http/api'
import { getTime } from '../../../utils'
import { Input, Select } from 'antd'
import { useTranslation } from 'react-i18next'
const BonusRecords = () => {
const { screenWidth } = store.state
const { t } = useTranslation()
const containerWidth = useMemo(() => {
if (screenWidth > 1420) {
@ -23,48 +25,48 @@ const BonusRecords = () => {
}, [screenWidth])
const options = [
{ label: '请选择类型', value: 0 },
{ label: '交易利润', value: 1 },
{ label: '盈利分红', value: 2 },
{ label: '超级奖励', value: 3 },
{ label: '交易佣金', value: 4 },
{ label: '星级奖励', value: 5 },
{ label: t('Please choose the type'), value: 0 },
{ label: t('Trading profit'), value: 1 },
{ label: t('Profit dividends'), value: 2 },
{ label: t('Super reward'), value: 3 },
{ label: t('Trading commissions'), value: 4 },
{ label: t('Star reward'), value: 5 },
]
const searchConfigList = [
{
key: 'type',
name: 'type',
label: '全部类型',
label: t('All types'),
initialValue: 0,
slot: <Select style={{ maxWidth: 200, minWidth: 150 }} placeholder="请选择类型" options={options} />
slot: <Select style={{ maxWidth: 200, minWidth: 150 }} placeholder={t('Please choose the type')} options={options} />
},
{
key: 'order',
name: 'order',
label: '订单号',
label: t('Order number'),
initialValue: '',
slot: <Input style={{ maxWidth: 200, minWidth: 150 }} placeholder='请输入订单号' />
slot: <Input style={{ maxWidth: 200, minWidth: 150 }} placeholder={t('Please enter order number')} />
},
{
key: 'assets',
name: 'assets',
label: '资金账户',
label: t('Capital account'),
initialValue: '',
slot: <Input style={{ maxWidth: 200, minWidth: 150 }} placeholder='请输入资金账户' />
slot: <Input style={{ maxWidth: 200, minWidth: 150 }} placeholder={t('Please enter the capital account')} />
}
]
return (
<div className="records" >
<div className='text-white fz-22 mb-2'></div>
<div className='text-white fz-22 mb-2'>{t('Bonus details')}</div>
<div className="container p-2" style={{ '--screen': `${containerWidth}px` } as React.CSSProperties}>
<MyTable
searchConfigList={searchConfigList}
apiFun={http_bonus}
columns={[
{
title: '时间',
title: t('Time'),
dataIndex: 'time',
width: 200,
render: (time: number) => (
@ -72,30 +74,30 @@ const BonusRecords = () => {
)
},
{
title: '订单',
title: t('Order'),
dataIndex: 'order'
},
{
title: '事件',
title: t('Event'),
dataIndex: 'event',
width: 200
},
{
title: '来自',
title: t('From'),
dataIndex: 'source'
},
// {
// title: '受益'
// },
{
title: '金额',
title: t('Amount'),
dataIndex: 'amount',
render: (val: string) => (
<span>${val}</span>
)
},
{
title: '余额',
title: t('Balance'),
dataIndex: 'balance',
render: (val: string) => (
<span>${val}</span>

17
src/pages/record/deposit/index.tsx

@ -6,11 +6,12 @@ import store from '../../../store'
import { useMemo } from 'react'
import { http_depositHistory, http_withdrawRecords } from '../../../http/api'
import { getTime } from '../../../utils'
import { useTranslation } from 'react-i18next'
const DepositRecords = () => {
const { screenWidth } = store.state
const { t } = useTranslation()
const containerWidth = useMemo(() => {
if (screenWidth > 1420) {
return 1420 - 310
@ -23,18 +24,18 @@ const DepositRecords = () => {
return (
<div className="records" >
<div className='text-white fz-22 mb-2'></div>
<div className='text-white fz-22 mb-2'>{t('Deposit records')}</div>
<div className="container p-2" style={{ '--screen': `${containerWidth}px` } as React.CSSProperties}>
<MyTable
apiFun={http_depositHistory}
columns={[
{
title: '状态',
title: t('Status'),
dataIndex: 'status',
width: 150,
},
{
title: '时间',
title: t('Time'),
dataIndex: 'time',
width: 200,
render: (time: number) => (
@ -42,11 +43,11 @@ const DepositRecords = () => {
)
},
{
title: '订单',
title: t('Order'),
dataIndex: 'order'
},
{
title: '到账金额',
title: t('Amount received'),
dataIndex: 'amount',
width: 160,
render: (val: string) => (
@ -54,7 +55,7 @@ const DepositRecords = () => {
)
},
{
title: '付款金额',
title: t('Payment amount'),
dataIndex: 'payment_amount',
width: 160,
render: (val: string) => (
@ -62,7 +63,7 @@ const DepositRecords = () => {
)
},
{
title: '账号',
title: t('Account'),
dataIndex: 'account'
}
]}

12
src/pages/record/escrow/index.tsx

@ -6,10 +6,12 @@ import store from '../../../store'
import { useMemo } from 'react'
import { http_escrowRecords } from '../../../http/api'
import { getTime } from '../../../utils'
import { useTranslation } from 'react-i18next'
const EscrowRecords = () => {
const { screenWidth } = store.state
const { t } = useTranslation()
const containerWidth = useMemo(() => {
if (screenWidth > 1420) {
@ -23,18 +25,18 @@ const EscrowRecords = () => {
return (
<div className="records" >
<div className='text-white fz-22 mb-2'></div>
<div className='text-white fz-22 mb-2'>{t('Escrow records')}</div>
<div className="container p-2" style={{ '--screen': `${containerWidth}px` } as React.CSSProperties}>
<MyTable
apiFun={http_escrowRecords}
columns={[
{
title: '账号',
title: t('Account'),
dataIndex: 'account',
width: 200
},
{
title: '开始时间',
title: t('Start time'),
dataIndex: 'start_time',
width: 200,
render: (time: number) => (
@ -42,7 +44,7 @@ const EscrowRecords = () => {
)
},
{
title: '结束时间',
title: t('End time'),
dataIndex: 'end_time',
width: 200,
render: (time: number) => (
@ -50,7 +52,7 @@ const EscrowRecords = () => {
)
},
{
title: '金额',
title: t('Amount'),
dataIndex: 'amount',
width: 160,
render: (val: string) => (

20
src/pages/record/withdraw/index.tsx

@ -6,10 +6,12 @@ import store from '../../../store'
import { useMemo } from 'react'
import { http_withdrawRecords } from '../../../http/api'
import { getTime } from '../../../utils'
import { useTranslation } from 'react-i18next'
const WithdrawRecords = () => {
const { screenWidth } = store.state
const { t } = useTranslation()
const containerWidth = useMemo(() => {
if (screenWidth > 1420) {
@ -23,18 +25,18 @@ const WithdrawRecords = () => {
return (
<div className="records" >
<div className='text-white fz-22 mb-2'></div>
<div className='text-white fz-22 mb-2'>{t('Withdraw records')}</div>
<div className="container p-2" style={{ '--screen': `${containerWidth}px` } as React.CSSProperties}>
<MyTable
apiFun={http_withdrawRecords}
columns={[
{
title: '状态',
title: t('Status'),
dataIndex: 'status',
width: 150,
},
{
title: '时间',
title: t('Time'),
dataIndex: 'time',
width: 200,
render: (time: number) => (
@ -42,33 +44,33 @@ const WithdrawRecords = () => {
)
},
{
title: '订单',
title: t('Order'),
dataIndex: 'order'
},
{
title: '取款金额',
title: t('Withdraw amount'),
dataIndex: 'amount',
render: (val: string) => (
<span>${val}</span>
)
},
{
title: '到账金额',
title: t('Amount received'),
dataIndex: 'receipt_amount',
render: (val: string) => (
<span>${val}</span>
)
},
{
title: '账号',
title: t('Account'),
dataIndex: 'account'
},
{
title: '收款户名',
title: t('Account name'),
dataIndex: 'type'
},
{
title: '收款地址',
title: t('Receive address'),
dataIndex: 'address'
}
]}

32
src/pages/security/index.tsx

@ -6,18 +6,20 @@ import CountdownTimer, { CountdownTimerRef } from "../../components/CountdownTim
import { useRef } from "react"
import { observer } from "mobx-react"
import store from "../../store"
import { useTranslation } from "react-i18next"
const Security = () => {
const { userInfo } = store.state
const [form] = Form.useForm()
const countdownRef = useRef<CountdownTimerRef>(null)
const { t } = useTranslation()
const onFinish: FormProps<HttpRequestPs.ResetPassword>['onFinish'] = async (values) => {
const res: any = await http_reset_password(values)
if (res.code === 0) {
notification.success({
message: '修改成功,请重新登录'
message: t('Modification successful, please log in again')
})
store.setToken('')
}
@ -25,11 +27,11 @@ const Security = () => {
const validatePassword = (_: any, value: string) => {
if (!value) {
return Promise.reject(new Error("请输入新密码"));
return Promise.reject(new Error(t('Please enter a new password')));
}
const regex = /^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d]{8,32}$/;
if (!regex.test(value)) {
return Promise.reject(new Error("密码必须包含字母和数字,长度为8-32位"));
return Promise.reject(new Error(t('Password must contain letters and numbers and be 8-32 characters long')));
}
return Promise.resolve();
};
@ -44,11 +46,11 @@ const Security = () => {
})
if (res.code === 0) {
notification.success({
message: '验证码发送成功'
message: t('Verification code sent successfully')
})
} else {
notification.error({
message: '验证码发送失败'
message: t('Failed to send verification code')
})
countdownRef.current?.handleStop()
}
@ -61,31 +63,31 @@ const Security = () => {
return (
<div className="securify">
<div className='text-white fz-22 mb-2'></div>
<div className='text-white fz-22 mb-2'>{t('Security settings')}</div>
<div className="container pb-2">
<div className="p-2">
<div className="fz-wb-550"></div>
<div className="fz-wb-550">{t('Change login password')}</div>
<div className="text-sub fz-14 mt-1">
<p>1.使</p>
<p>2.</p>
<p>{t('1. Please make sure the device is safe during use to prevent data from being tampered with or leaked.')}</p>
<p>{t('2. The email verification code may be delayed, please wait patiently.')}</p>
</div>
</div>
<div className="divider"></div>
<div className="plr-2">
<Form layout="vertical" form={form} onFinish={onFinish}>
<Form.Item name="password" rules={[{ validator: validatePassword }]} label={<span className="fz-wb-550" ></span>}>
<Input.Password style={{ height: 50 }} placeholder="密码必须是字母加数字的组合" />
<Form.Item name="password" rules={[{ validator: validatePassword }]} label={<span className="fz-wb-550" >{t('New password')}</span>}>
<Input.Password style={{ height: 50 }} placeholder={t('Password must be a combination of letters and numbers')} />
</Form.Item>
<Form.Item name="code" rules={[{ required: true, message: '请输入验证码' }]} label={<span className="fz-wb-550"></span>}>
<Form.Item name="code" rules={[{ required: true, message: t('please enter verification code') }]} label={<span className="fz-wb-550">{t('Verification Code')}</span>}>
<div className="row-items">
<Input style={{ height: 50 }} placeholder="密码必须是字母加数字的组合" />
<Button type="primary" style={{ height: 50, width: 150 }} className="ml-1" onClick={getVerifyCode}>
<Input style={{ height: 50 }} placeholder={t('please enter verification code')} />
<Button type="primary" style={{ height: 50, minWidth: 150, maxWidth: 180 }} className="ml-1" onClick={getVerifyCode}>
<CountdownTimer initialSeconds={60} ref={countdownRef} />
</Button>
</div>
</Form.Item>
<Form.Item className="row-center">
<Button type="primary" htmlType="submit" style={{ borderRadius: 50 }}></Button>
<Button type="primary" htmlType="submit" style={{ borderRadius: 50 }}>{t('Submit')}</Button>
</Form.Item>
</Form>
</div>

21
src/pages/submit/index.tsx

@ -5,6 +5,8 @@ import { useRouter } from '../../hooks/useRouter'
import store from '../../store'
import { useEffect, useState } from 'react'
import { http_code, http_login, http_submit } from '../../http/api'
import { useTranslation } from 'react-i18next'
import LanguageMenu from '../../components/LanguageMenu'
type FieldType = {
account: string;
password: string;
@ -13,6 +15,7 @@ type FieldType = {
const Submit = () => {
const [form] = Form.useForm()
const { t } = useTranslation()
const onFinish: FormProps<FieldType>['onFinish'] = async (values) => {
const res: any = await http_submit({
@ -20,7 +23,7 @@ const Submit = () => {
})
if (res.code === 0) {
notification.success({
message: '提交成功'
message: t('Submit success')
})
form.resetFields()
}
@ -31,8 +34,12 @@ const Submit = () => {
}, [])
return (
<div className='login'>
<div className='login' style={{ position: 'relative' }}>
<div style={{ position: 'absolute', top: 20, right: 20 }}>
<LanguageMenu width={40} />
</div>
<div className='container'>
<div className='row-center'>
<img src={require('../../assets/login.png')} className='img' alt="" />
</div>
@ -47,25 +54,25 @@ const Submit = () => {
rules={[
{
required: true,
message: '请输入账号!',
message: t('Please enter a account'),
},
]}
>
<Input className='input' placeholder='账号' ></Input>
<Input className='input' placeholder={t('Account')} ></Input>
</Form.Item>
<Form.Item
name="password"
rules={[
{
required: true,
message: '请输入密码!',
message: t('Please enter a password'),
},
]}
>
<Input.Password className='input' placeholder='请输入密码' />
<Input.Password className='input' placeholder={t('Please enter a password')} />
</Form.Item>
<Form.Item>
<Button htmlType="submit"></Button>
<Button htmlType="submit">{t('Submit')}</Button>
</Form.Item>
</Form>
</div>

4
src/pages/team/index.tsx

@ -4,12 +4,14 @@ import { useEffect, useState } from 'react'
import { http_team } from '../../http/api'
import { observer } from 'mobx-react'
import store from '../../store'
import { useTranslation } from 'react-i18next'
const Team = () => {
const { token } = store.state
const [rootAccount, setRootState] = useState('')
const [teamAccount, setTeamAccount] = useState([])
const { t } = useTranslation()
useEffect(() => {
const getData = async () => {
@ -25,7 +27,7 @@ const Team = () => {
return (
<div className='team'>
<div className='text-white fz-22 mb-2'></div>
<div className='text-white fz-22 mb-2'>{t('Team details')}</div>
<div className='container p-2'>

46
src/pages/transfer/index.tsx

@ -4,15 +4,17 @@ import { useState } from 'react'
import { observer } from 'mobx-react'
import store from '../../store'
import { http_transfer } from '../../http/api'
import { useTranslation } from 'react-i18next'
const Transfer = () => {
const { userInfo } = store.state
const [form] = Form.useForm()
const { t } = useTranslation()
const options = [
{ label: '现金钱包-资产账户', value: 1 },
{ label: '现金钱包-其他会员', value: 2 },
{ label: '资产账户-现金钱包', value: 3 }
{ label: t('Cash Wallet-Asset Account'), value: 1 },
{ label: t('Cash Wallet-Other Members'), value: 2 },
{ label: t('Asset Account-Cash Wallet'), value: 3 }
]
const [type, setType] = useState(-1)
@ -30,7 +32,7 @@ const Transfer = () => {
store.getUserInfo()
form.resetFields()
notification.success({
message: '提交成功'
message: t('Submit success')
})
}
@ -38,14 +40,14 @@ const Transfer = () => {
return (
<div className="deposit">
<div className='text-white fz-22 mb-2'></div>
<div className='text-white fz-22 mb-2'>{t('Assets transfer')}</div>
<div className="flex-1 container">
<div className='p-2'>
<div className='fz-wb-550'>-</div>
<div className='fz-wb-550'>{t('Assets transfer-matters needing attention')}</div>
<div className='text-sub fz-14 mt-1'>
<p>1.使</p>
<p>2.</p>
<p>3.10</p>
<p>{t('1.Please ensure the safety of the equipment during use,Prevent data from being tampered with or leaked。')}</p>
<p>{t('2.In the process of fund transfer, if there is a delay or other situation,Please handle it later or contact customer service。')}</p>
<p>{t('3.After fund transfer operation,There may be delays in the system;If exceeding10Minutes have not yet arrived,Please contact customer service。')}</p>
</div>
</div>
<div className='divider' style={{ backgroundColor: '#8492a6' }}></div>
@ -55,17 +57,17 @@ const Transfer = () => {
onFinish={onFinish}
form={form}
>
<Form.Item label={<span className='fz-wb-550'></span>}>
<Select style={{ height: 50 }} placeholder="请选择操作类型..." options={options} onSelect={onSelect} />
<Form.Item label={<span className='fz-wb-550'>{t('Assets operations')}</span>}>
<Select style={{ height: 50 }} placeholder={t('Please select an operation type...')} options={options} onSelect={onSelect} />
{
type < 3 ? (
<div>
<span className='fz-12 text-primary'></span>
<span className='fz-12 text-primary'>{t('Wallet balance')}</span>
<span className='fz-12 text-success'>${userInfo.balance}</span>
</div>
) : (
<div>
<span className='fz-12 text-primary'></span>
<span className='fz-12 text-primary'>{t('Asset account amount')}</span>
<span className='fz-12 text-success'>${userInfo.account_balance}</span>
</div>
)
@ -74,35 +76,35 @@ const Transfer = () => {
{
type === 2 && (
<Form.Item name="email" label="会员账号" rules={[{ required: true, message: "请输入对方登录账户(邮箱)" }, { type: 'email', message: '邮箱格式错误' }]}>
<Input style={{ height: 50 }} placeholder='请输入对方登录账户(邮箱)' />
<Form.Item name="email" label={t('Member account')} rules={[{ required: true, message: t('Please enter the other party’s login account (email)') }, { type: 'email', message: t('Email format error') }]}>
<Input style={{ height: 50 }} placeholder={t('Please enter the other party’s login account (email)')} />
</Form.Item>
)
}
{
type === 1 && (
<Form.Item label={<span className='fz-wb-550'></span>}>
<Input style={{ height: 50 }} placeholder='请输入转账金额' value={`(CFD) ${userInfo.account},余额${userInfo.account_balance}`} disabled />
<Form.Item label={<span className='fz-wb-550'>{t('Capital account')}</span>}>
<Input style={{ height: 50 }} placeholder={t('Please enter the transfer amount')} value={`(CFD) ${userInfo.account},${t('Balance')}${userInfo.account_balance}`} disabled />
</Form.Item>
)
}
{
type === 3 && (
<Form.Item label={<span className='fz-wb-550'></span>}>
<Input style={{ height: 50 }} placeholder='请输入转账金额' value={`(CFD) ${userInfo.account},余额${userInfo.account_balance}`} disabled />
<Form.Item label={<span className='fz-wb-550'>{t('Capital account')}</span>}>
<Input style={{ height: 50 }} placeholder={t('Please enter the transfer amount')} value={`(CFD) ${userInfo.account},${t('Balance')}${userInfo.account_balance}`} disabled />
</Form.Item>
)
}
<Form.Item name="amount" rules={[{ required: true, message: "请输入转账金额" }]} label={<span className='fz-wb-550'></span>}>
<Input style={{ height: 50 }} placeholder='请输入转账金额' />
<Form.Item name="amount" rules={[{ required: true, message: t('Please enter the transfer amount') }]} label={<span className='fz-wb-550'>{t('Transfer amount')}</span>}>
<Input style={{ height: 50 }} placeholder={t('Please enter the transfer amount')} />
</Form.Item>
<Form.Item>
<div className='row-center'>
<Button type='primary' htmlType='submit' style={{ borderRadius: 30 }}></Button>
<Button type='primary' htmlType='submit' style={{ borderRadius: 30 }}>{t('submit')}</Button>
</div>
</Form.Item>
</Form>

36
src/pages/withdraw/index.tsx

@ -5,12 +5,14 @@ import store from '../../store'
import { useMemo, useRef, useState } from 'react'
import CountdownTimer, { CountdownTimerRef } from '../../components/CountdownTimer'
import { http_send_email, http_withdraw } from '../../http/api'
import { useTranslation } from 'react-i18next'
const Withdraw = () => {
const [form] = Form.useForm()
const { receiveAccount, userInfo } = store.state
const countdownRef = useRef<CountdownTimerRef>(null)
const { t } = useTranslation()
const options = useMemo(() => {
const map = receiveAccount.map(item => ({
@ -24,7 +26,7 @@ const Withdraw = () => {
if (Number(values.amount) > Number(userInfo.balance)) {
notification.warning({
message: '余额不足'
message: t('Insufficient balance')
})
return
}
@ -36,7 +38,7 @@ const Withdraw = () => {
if (res.code === 0) {
form.resetFields()
notification.success({
message: '提交成功'
message: t('Submit success')
})
}
@ -52,11 +54,11 @@ const Withdraw = () => {
})
if (res.code === 0) {
notification.success({
message: '验证码发送成功'
message: t('Verification code sent successfully')
})
} else {
notification.error({
message: '验证码发送失败'
message: t('Failed to send verification code')
})
countdownRef.current?.handleStop()
}
@ -68,11 +70,11 @@ const Withdraw = () => {
return (
<div className="widthdraw">
<div className='text-white fz-22 mb-2'></div>
<div className='text-white fz-22 mb-2'>{t('Handle withdraw')}</div>
<div className="flex-1 container">
<div className='p-2'>
<div className='fz-wb-550'></div>
<div className='text-primary fz-14 mt-1'>使</div>
<div className='fz-wb-550'>{t('Hint')}</div>
<div className='text-primary fz-14 mt-1'>{t('Please make sure the device is safe during use to prevent data tampering or leakage.')}</div>
</div>
<div className='divider' style={{ backgroundColor: '#8492a6' }}></div>
<div className='p-2'>
@ -82,25 +84,25 @@ const Withdraw = () => {
form={form}
>
<div className={'form-box'}>
<Form.Item className='input' label={<span className='fz-wb-550'></span>}>
<Select style={{ height: 40 }} value={`现金钱包 余额:$${userInfo.balance}`} />
<Form.Item className='input' label={<span className='fz-wb-550'>{t('Withdraw account')}</span>}>
<Select style={{ height: 40 }} value={`${t('Cash Wallet')} ${t('Balance')}:$${userInfo.balance}`} />
</Form.Item>
<Form.Item name="amount" rules={[{ required: true, message: '请输入取款金额' }]} className='input' label={<span className='fz-wb-550'></span>}>
<Form.Item name="amount" rules={[{ required: true, message: t('Please enter the withdrawal amount') }]} className='input' label={<span className='fz-wb-550'>{t('Withdraw amount')}</span>}>
<div className='row-items'>
<Input style={{ height: 40, flex: 1 }} placeholder='请输入取款金额' />
<Input style={{ height: 40, flex: 1 }} placeholder={t('Please enter the withdrawal amount')} />
<div className='fz-wb-550 ml-1'>USD</div>
</div>
</Form.Item>
</div>
<div className='form-box'>
<Form.Item name="receiving_account_id" rules={[{ required: true, message: '请选择收款方式...' }]} className='input' label={<span className='fz-wb-550'></span>}>
<Select style={{ height: 40 }} placeholder="选择收款方式..." options={options} />
<Form.Item name="receiving_account_id" rules={[{ required: true, message: t('Please select a receive method...') }]} className='input' label={<span className='fz-wb-550'>{t('Receive methods')}</span>}>
<Select style={{ height: 40 }} placeholder={t('Please select a receive method...')} options={options} />
</Form.Item>
<Form.Item rules={[{ required: true, message: '请选择收款方式...' }]} name="code" className='input' label={<span className='fz-wb-550'></span>}>
<Form.Item rules={[{ required: true, message: t('please enter verification code') }]} name="code" className='input' label={<span className='fz-wb-550'>{t('Verification Code')}</span>}>
<div className='row-items'>
<Input style={{ height: 40, flex: 1 }} placeholder='请输入验证码' />
<Button type="primary" className='ml-1' style={{ height: 40, width: 100 }} onClick={getVerifyCode}>
<Input style={{ height: 40, flex: 1 }} placeholder={t('please enter verification code')} />
<Button type="primary" className='ml-1' style={{ height: 40, minWidth: 100, maxWidth: 150 }} onClick={getVerifyCode}>
<CountdownTimer ref={countdownRef} initialSeconds={60} />
</Button>
</div>
@ -109,7 +111,7 @@ const Withdraw = () => {
<Form.Item>
<div className='row-center'>
<Button type='primary' htmlType='submit' style={{ borderRadius: 30 }}></Button>
<Button type='primary' htmlType='submit' style={{ borderRadius: 30 }}>{t('Submit')}</Button>
</div>
</Form.Item>
</Form>

16
src/router/index.tsx

@ -10,6 +10,7 @@ import { unLoginPath } from "./routes";
import { Divider, Modal } from "antd";
import { NotifyStatus_Type } from "../types";
import { http_notify } from "../http/api";
import { useTranslation } from "react-i18next";
import LanguageMenu from "../components/LanguageMenu";
const LayoutRouter = () => {
@ -18,6 +19,8 @@ const LayoutRouter = () => {
const [visible, setVisible] = useState(false)
const { token, screenWidth } = store.state
const [notifys, setNotifys] = useState([] as any)
const { t } = useTranslation()
//
useEffect(() => {
@ -31,6 +34,7 @@ const LayoutRouter = () => {
}
}, [])
useEffect(() => {
if (!token && !unLoginPath.includes(location.pathname) && location.pathname !== "/submit") {
@ -46,8 +50,6 @@ const LayoutRouter = () => {
try {
const res: any = await http_notify()
if (res.code === 0) {
console.log(res);
setNotifys(res.data)
const type = window.localStorage.getItem('NotifyStatus') || NotifyStatus_Type.show
if (type === NotifyStatus_Type.show && res.data && res.data.length > 0) {
@ -72,14 +74,16 @@ const LayoutRouter = () => {
}
}, [token])
if (location.pathname === '/submit') return <></>
return (
<>
{
!token ? (
<>
{/* <div style={{ position: 'absolute', top: 20, right: 20 }}>
<LanguageMenu />
</div> */}
<div style={{ position: 'absolute', top: 20, right: 20 }}>
<LanguageMenu width={40} />
</div>
<RenderRouter />
</>
) : (
@ -103,7 +107,7 @@ const LayoutRouter = () => {
onCancel={() => setVisible(false)}
footer={() => null}
width={screenWidth > 1000 ? '60%' : '90%'}
title="平台公告"
title={t('Platform announcement')}
>
<div style={{ minHeight: 300 }}>
{

6
src/router/renderRouter.tsx

@ -2,14 +2,12 @@ import { Suspense } from "react";
import { Route, Routes } from "react-router-dom";
import routes from "./routes";
import { observer } from "mobx-react";
import { Spin } from "antd";
const RenderRouter = () => {
return (
<Suspense fallback={<div className='row-center' style={{ height: '80vh' }}>
<div className='tac'>
{/* <Loading color='#1BEDFF' size={30} /> */}
<div className='fz-16 sub-text mt-1'>...</div>
</div>
<Spin size="large" tip="Loading" />
</div>}>
<Routes>
{routes.map(item => {

4
src/router/routes.tsx

@ -74,10 +74,6 @@ const routes = [
path: "/assetsRecords",
element: <AssetsRecords />
},
{
path: "/personal",
element: <Personal />
},
{
path: '/withdrawRecords',
element: <WithdrawRecords />

3
src/styles/app.scss

@ -58,7 +58,7 @@
}
.balance-button {
width: 158px;
width: 188px;
height: 58px;
border-radius: 29px;
background-color: #fff;
@ -66,6 +66,7 @@
font-size: 14px;
font-weight: normal;
text-align: center;
overflow: hidden;
}
}

17
src/styles/home.scss

@ -62,7 +62,7 @@
border-radius: 5px;
}
.upload{
.upload {
width: 100px;
height: 100px;
border-style: dashed;
@ -73,14 +73,15 @@
user-select: none;
overflow: hidden;
position: relative;
.delete{
.delete {
position: absolute;
top: 0;
right: 0;
z-index: 1;
}
&:active{
&:active {
opacity: 0.6;
}
}
@ -190,8 +191,10 @@
}
}
.ant-tabs-nav-wrap {
overflow: hidden;
overflow-x: scroll;
width: 400px;
@media (max-width:1000px) {
.ant-tabs-nav-wrap {
overflow: hidden;
overflow-x: scroll;
max-width: calc(var(--width) - 30px);
}
}

3
src/utils/index.ts

@ -1,4 +1,5 @@
import { notification } from "antd"
import i18next from "i18next"
export function copy(value: string, cb?: Function) {
// 动态创建 textarea 标签
@ -18,7 +19,7 @@ export function copy(value: string, cb?: Function) {
document.execCommand('Copy')
document.body.removeChild(textarea)
notification.success({
message: '复制成功'
message: i18next.t('Copy successfully')
})
if (cb && Object.prototype.toString.call(cb) === '[object Function]') {
cb()

Loading…
Cancel
Save