Commit eeb7db42 authored by 杨贺晨吉's avatar 杨贺晨吉

feat: 开发

parent 15c8858f
# Tuia-Manager-System-Demo
# adx-manager-node
此工程为推啊后台管理系统DEMO,基于React + TypeScript + Vite + Mobx搭建。
此工程为推啊ADX后台管理系统,通用项目结构tuia-manager-system-demo,基于React + TypeScript + Vite + Mobx搭建。
[TOC]
......@@ -8,7 +8,7 @@
**工程目录结构**
```
tuia-manager-system-demo
adx-manager-node
├── dist # 构建目录
├── mock # 模拟数据
├── server # 部署脚本
......@@ -32,7 +32,7 @@ tuia-manager-system-demo
### Yapi-MOCK助手插件
1. 安装YAPI-MOCK助手(https://marketplace.visualstudio.com/items?itemName=Hidetoxic.yapi-mock-helper)
2. 在yapi-mock.config.json中指定项目代理服务器端口
3. 在vite.config.ts的server.proxy指定代理地址为本地指定端口(demo端口为10089,建议fork后修改)
3. 在vite.config.ts的server.proxy指定代理地址为本地指定端口(adx-manager-node端口为10089,建议fork后修改)
4. 启动项目后,从资源管理器,启动YAPI-MOCK助手
![alt text](https://yun.dui88.com/jjq/images/d2skfpns6sl6jgf1rylpd.png)
5. 通过VSCode状态栏,以切换代理地址
......
......@@ -8,22 +8,31 @@ export {}
declare global {
const Button: typeof import('antd')['Button']
const Card: typeof import('antd')['Card']
const Checkbox: typeof import('antd')['Checkbox']
const DatePicker: typeof import('antd')['DatePicker']
const Form: typeof import('antd')['Form']
const Input: typeof import('antd')['Input']
const Layout: typeof import('antd')['Layout']
const Link: typeof import('react-router-dom')['Link']
const Menu: typeof import('antd')['Menu']
const Modal: typeof import('antd')['Modal']
const NavLink: typeof import('react-router-dom')['NavLink']
const Navigate: typeof import('react-router-dom')['Navigate']
const Observer: typeof import('mobx-react-lite')['Observer']
const Outlet: typeof import('react-router-dom')['Outlet']
const REGEX: typeof import('pixiu-number-toolkit')['REGEX']
const Radio: typeof import('antd')['Radio']
const Result: typeof import('antd')['Result']
const Role: typeof import('./src/constants/enums/index')['Role']
const Route: typeof import('react-router-dom')['Route']
const Routes: typeof import('react-router-dom')['Routes']
const Rules: typeof import('./src/utils/REG')['Rules']
const Select: typeof import('antd')['Select']
const Space: typeof import('antd')['Space']
const Spin: typeof import('antd')['Spin']
const Switch: typeof import('antd')['Switch']
const Table: typeof import('antd')['Table']
const Upload: typeof import('antd')['Upload']
const UserList: typeof import('./src/constants/userList')['UserList']
const action: typeof import('mobx')['action']
const autorun: typeof import('mobx')['autorun']
......
......@@ -2,4 +2,15 @@ import jsConfig from '@tuia/eslint-config-common/global.js'
import reactConfig from '@tuia/eslint-config-common/react.js'
import tsConfig from '@tuia/eslint-config-common/typeScript.js'
import reactRefresh from 'eslint-plugin-react-refresh'
export default [...jsConfig, ...reactConfig, ...tsConfig, { ignores: ['dist'] }, reactRefresh.configs.vite]
export default [
...jsConfig,
...reactConfig,
...tsConfig,
{ ignores: ['dist'] },
reactRefresh.configs.vite,
{
rules: {
'import/no-unresolved': 'off',
},
},
]
......@@ -4,7 +4,7 @@
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="https://yun.tuisnake.com/tuia/payment/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + React + TS</title>
<title>ADX管理平台</title>
</head>
<body>
<div id="root"></div>
......
{
"name": "demo",
"name": "adx-manager-node",
"private": true,
"version": "0.0.0",
"type": "module",
......
......@@ -4,7 +4,7 @@ import { StyleProvider } from '@ant-design/cssinjs'
import routes from '~react-pages'
import { ConfigProvider } from 'antd'
import Layouts from './layouts'
import Layouts from './layouts/index.tsx'
const App: React.FC = () => {
return (
......
import { UserOutlined, SettingOutlined } from '@ant-design/icons'
import { UserOutlined, SettingOutlined, UserAddOutlined } from '@ant-design/icons'
const { Header, Content, Sider } = Layout
......@@ -23,6 +23,23 @@ const menuItems = [
icon: <SettingOutlined />,
label: '系统管理',
},
{
key: '/media',
icon: <UserAddOutlined />,
label: '媒体管理',
children: [
{
key: '/media/mediaAccount',
label: '媒体管理',
icon: <UserAddOutlined />,
},
{
key: '/media/mediaManage',
label: '媒体流量管理',
icon: <UserAddOutlined />,
},
],
},
]
const BasicLayout: React.FC<React.PropsWithChildren> = ({ children }) => {
......
......@@ -2,7 +2,7 @@ import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import { HashRouter } from 'react-router-dom'
import App from './App'
import App from './App.tsx'
import './index.css'
import '@ant-design/v5-patch-for-react-19'
......
interface AddAccountProps {
open: boolean
handleClose: () => void
}
const AddModal: React.FC<AddAccountProps> = observer((prop: AddAccountProps) => {
const { handleClose, open } = prop
const handleOk = () => {
handleClose()
}
const handleCancel = () => {
handleClose()
}
return (
<Modal title='Basic Modal' open={open} onOk={handleOk} onCancel={handleCancel}>
<p>Some contents...</p>
<p>Some contents...</p>
<p>Some contents...</p>
</Modal>
)
})
export default AddModal
import List from './list.tsx'
import Search from './search.tsx'
const StatementTypeIn = observer(() => {
return (
<Space direction='vertical' style={{ display: 'flex' }} size='middle'>
<Search />
<List />
</Space>
)
})
export default StatementTypeIn
import type { TableProps } from 'antd'
import AddModal from './addAccount.tsx'
interface DataType {
key: string
name: string
age: number
address: string
}
const List: React.FC = observer(() => {
const [isModalOpen, setIsModalOpen] = useState(false)
const handleShowAddModal = () => {
setIsModalOpen(true)
}
const columns: TableProps<DataType>['columns'] = [
{
title: '姓名',
dataIndex: 'name',
key: 'name',
},
{
title: '年龄',
dataIndex: 'age',
key: 'age',
},
{
title: '住址',
dataIndex: 'address',
key: 'address',
},
{
title: 'Action',
key: 'action',
render: () => (
<Space size='middle'>
<a onClick={handleShowAddModal}>查看</a>
</Space>
),
},
]
const dataSource: DataType[] = [
{
key: '1',
name: '胡彦斌',
age: 32,
address: '西湖区湖底公园1号',
},
{
key: '2',
name: '胡彦祖',
age: 42,
address: '西湖区湖底公园1号',
},
]
return (
<>
<Table dataSource={dataSource} columns={columns} />
<AddModal open={isModalOpen} handleClose={() => setIsModalOpen(false)} />
</>
)
})
export default List
const { Item: FormItem } = Form
const Search: React.FC = observer(() => {
const [form] = Form.useForm()
function handleSearch(e: React.MouseEvent<HTMLElement, MouseEvent>) {
e.preventDefault()
form
.validateFields()
.then((values) => {
values.dealIdList = values.dealIdList?.split(',')
console.log('Received values of form: ', values)
})
.catch((err) => {
console.error('Validation Failed:', err)
})
}
return (
<Form layout='inline' form={form}>
<FormItem name='dealIdList' rules={[Rules.ids]}>
<Input style={{ width: 200 }} placeholder='请输入排期单ID间隔用,隔开' />
</FormItem>
<FormItem name='dealName' rules={[Rules.name]}>
<Input style={{ width: 200 }} placeholder='请输入排期单名称' />
</FormItem>
<FormItem>
<Button
type='primary'
htmlType='submit'
onClick={(e: React.MouseEvent<HTMLElement, MouseEvent>) => handleSearch(e)}>
搜索
</Button>
</FormItem>
</Form>
)
})
export default Search
const About = () => <div>About</div>
const About = () => <div>About2</div>
export default About
const UtilsExample: React.FC = () => {
// 金额对于后端来说只能是number & string & 空 & null & undefined
const a = prefixYuan(yuanToLi('300000', 2))
const b = smartFenToYuan('0', 3)
const c = liToYuan('0')
const d = digitUppercase('0')
// 正则
const e = buildREG(REGEX.INTEGER, 'undefined')
const f = precentAddSuffix(35)
return (
<div>
<p>1: {a}</p>
<p>2: {b}</p>
<p>3: {c}</p>
<p>4: {d}</p>
<p>5: {e}</p>
<p>6: {f}</p>
</div>
)
}
export default UtilsExample
......@@ -42,7 +42,27 @@ export default defineConfig(({ mode }) => ({
],
imports: [
{
antd: ['message', 'Spin', 'Layout', 'Menu', 'theme', 'Button', 'Form', 'Input', 'Card', 'Result'],
antd: [
'Space',
'message',
'Spin',
'Layout',
'Menu',
'theme',
'Button',
'Form',
'Input',
'Card',
'Result',
'Table',
'Select',
'DatePicker',
'Modal',
'Checkbox',
'Radio',
'Switch',
'Upload',
],
axios: [['default', 'axios']],
'pixiu-number-toolkit': ['REGEX'],
},
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment