feat: init object
This commit is contained in:
commit
3736305284
16
.editorconfig
Normal file
16
.editorconfig
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
# http://editorconfig.org
|
||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
end_of_line = lf
|
||||||
|
charset = utf-8
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
insert_final_newline = true
|
||||||
|
|
||||||
|
[*.md]
|
||||||
|
trim_trailing_whitespace = false
|
||||||
|
|
||||||
|
[Makefile]
|
||||||
|
indent_style = tab
|
8
.eslintignore
Normal file
8
.eslintignore
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
/lambda/
|
||||||
|
/scripts
|
||||||
|
/config
|
||||||
|
.history
|
||||||
|
public
|
||||||
|
dist
|
||||||
|
.umi
|
||||||
|
mock
|
7
.eslintrc.js
Normal file
7
.eslintrc.js
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
module.exports = {
|
||||||
|
extends: [require.resolve('@umijs/lint/dist/config/eslint')],
|
||||||
|
globals: {
|
||||||
|
page: true,
|
||||||
|
REACT_APP_ENV: true,
|
||||||
|
},
|
||||||
|
};
|
41
.gitignore
vendored
Normal file
41
.gitignore
vendored
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||||
|
|
||||||
|
# dependencies
|
||||||
|
**/node_modules
|
||||||
|
# roadhog-api-doc ignore
|
||||||
|
/src/utils/request-temp.js
|
||||||
|
_roadhog-api-doc
|
||||||
|
|
||||||
|
# production
|
||||||
|
/dist
|
||||||
|
|
||||||
|
# misc
|
||||||
|
.DS_Store
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-error.log
|
||||||
|
|
||||||
|
/coverage
|
||||||
|
.idea
|
||||||
|
yarn.lock
|
||||||
|
package-lock.json
|
||||||
|
*bak
|
||||||
|
.vscode
|
||||||
|
|
||||||
|
|
||||||
|
# visual studio code
|
||||||
|
.history
|
||||||
|
*.log
|
||||||
|
functions/*
|
||||||
|
.temp/**
|
||||||
|
|
||||||
|
# umi
|
||||||
|
.umi
|
||||||
|
.umi-production
|
||||||
|
.umi-test
|
||||||
|
|
||||||
|
# screenshot
|
||||||
|
screenshot
|
||||||
|
.firebase
|
||||||
|
.eslintcache
|
||||||
|
|
||||||
|
build
|
7
.husky/commit-msg
Normal file
7
.husky/commit-msg
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
. "$(dirname "$0")/_/husky.sh"
|
||||||
|
|
||||||
|
# Export Git hook params
|
||||||
|
export GIT_PARAMS=$*
|
||||||
|
|
||||||
|
npx --no-install fabric verify-commit
|
4
.husky/pre-commit
Normal file
4
.husky/pre-commit
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
. "$(dirname "$0")/_/husky.sh"
|
||||||
|
|
||||||
|
npx --no-install lint-staged
|
22
.prettierignore
Normal file
22
.prettierignore
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
**/*.svg
|
||||||
|
.umi
|
||||||
|
.umi-production
|
||||||
|
/dist
|
||||||
|
.dockerignore
|
||||||
|
.DS_Store
|
||||||
|
.eslintignore
|
||||||
|
*.png
|
||||||
|
*.toml
|
||||||
|
docker
|
||||||
|
.editorconfig
|
||||||
|
Dockerfile*
|
||||||
|
.gitignore
|
||||||
|
.prettierignore
|
||||||
|
LICENSE
|
||||||
|
.eslintcache
|
||||||
|
*.lock
|
||||||
|
yarn-error.log
|
||||||
|
.history
|
||||||
|
CNAME
|
||||||
|
/build
|
||||||
|
/public
|
21
.prettierrc.js
Normal file
21
.prettierrc.js
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
module.exports = {
|
||||||
|
singleQuote: true,
|
||||||
|
trailingComma: 'all',
|
||||||
|
printWidth: 100,
|
||||||
|
proseWrap: 'never',
|
||||||
|
endOfLine: 'lf',
|
||||||
|
overrides: [
|
||||||
|
{
|
||||||
|
files: '.prettierrc',
|
||||||
|
options: {
|
||||||
|
parser: 'json',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
files: 'document.ejs',
|
||||||
|
options: {
|
||||||
|
parser: 'html',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
57
README.md
Normal file
57
README.md
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
# Ant Design Pro
|
||||||
|
|
||||||
|
This project is initialized with [Ant Design Pro](https://pro.ant.design). Follow is the quick guide for how to use.
|
||||||
|
|
||||||
|
## Environment Prepare
|
||||||
|
|
||||||
|
Install `node_modules`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install
|
||||||
|
```
|
||||||
|
|
||||||
|
or
|
||||||
|
|
||||||
|
```bash
|
||||||
|
yarn
|
||||||
|
```
|
||||||
|
|
||||||
|
## Provided Scripts
|
||||||
|
|
||||||
|
Ant Design Pro provides some useful script to help you quick start and build with web project, code style check and test.
|
||||||
|
|
||||||
|
Scripts provided in `package.json`. It's safe to modify or add additional script:
|
||||||
|
|
||||||
|
### Start project
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm start
|
||||||
|
```
|
||||||
|
|
||||||
|
### Build project
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run build
|
||||||
|
```
|
||||||
|
|
||||||
|
### Check code style
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run lint
|
||||||
|
```
|
||||||
|
|
||||||
|
You can also use script to auto fix some lint error:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run lint:fix
|
||||||
|
```
|
||||||
|
|
||||||
|
### Test code
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm test
|
||||||
|
```
|
||||||
|
|
||||||
|
## More
|
||||||
|
|
||||||
|
You can view full document on our [official website](https://pro.ant.design). And welcome any feedback in our [github](https://github.com/ant-design/ant-design-pro).
|
149
config/config.ts
Normal file
149
config/config.ts
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
// https://umijs.org/config/
|
||||||
|
import { defineConfig } from '@umijs/max';
|
||||||
|
import { join } from 'path';
|
||||||
|
import defaultSettings from './defaultSettings';
|
||||||
|
import proxy from './proxy';
|
||||||
|
import routes from './routes';
|
||||||
|
const { REACT_APP_ENV = 'dev' } = process.env;
|
||||||
|
export default defineConfig({
|
||||||
|
/**
|
||||||
|
* @name 开启 hash 模式
|
||||||
|
* @description 让 build 之后的产物包含 hash 后缀。通常用于增量发布和避免浏览器加载缓存。
|
||||||
|
* @doc https://umijs.org/docs/api/config#hash
|
||||||
|
*/
|
||||||
|
hash: true,
|
||||||
|
/**
|
||||||
|
* @name 兼容性设置
|
||||||
|
* @description 设置 ie11 不一定完美兼容,需要检查自己使用的所有依赖
|
||||||
|
* @doc https://umijs.org/docs/api/config#targets
|
||||||
|
*/
|
||||||
|
// targets: {
|
||||||
|
// ie: 11,
|
||||||
|
// },
|
||||||
|
/**
|
||||||
|
* @name 路由的配置,不在路由中引入的文件不会编译
|
||||||
|
* @description 只支持 path,component,routes,redirect,wrappers,title 的配置
|
||||||
|
* @doc https://umijs.org/docs/guides/routes
|
||||||
|
*/
|
||||||
|
// umi routes: https://umijs.org/docs/routing
|
||||||
|
routes,
|
||||||
|
/**
|
||||||
|
* @name 主题的配置
|
||||||
|
* @description 虽然叫主题,但是其实只是 less 的变量设置
|
||||||
|
* @doc antd的主题设置 https://ant.design/docs/react/customize-theme-cn
|
||||||
|
* @doc umi 的theme 配置 https://umijs.org/docs/api/config#theme
|
||||||
|
*/
|
||||||
|
theme: {
|
||||||
|
// 如果不想要 configProvide 动态设置主题需要把这个设置为 default
|
||||||
|
// 只有设置为 variable, 才能使用 configProvide 动态设置主色调
|
||||||
|
'root-entry-name': 'variable',
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* @name moment 的国际化配置
|
||||||
|
* @description 如果对国际化没有要求,打开之后能减少js的包大小
|
||||||
|
* @doc https://umijs.org/docs/api/config#ignoremomentlocale
|
||||||
|
*/
|
||||||
|
ignoreMomentLocale: true,
|
||||||
|
/**
|
||||||
|
* @name 代理配置
|
||||||
|
* @description 可以让你的本地服务器代理到你的服务器上,这样你就可以访问服务器的数据了
|
||||||
|
* @see 要注意以下 代理只能在本地开发时使用,build 之后就无法使用了。
|
||||||
|
* @doc 代理介绍 https://umijs.org/docs/guides/proxy
|
||||||
|
* @doc 代理配置 https://umijs.org/docs/api/config#proxy
|
||||||
|
*/
|
||||||
|
proxy: proxy[REACT_APP_ENV as keyof typeof proxy],
|
||||||
|
/**
|
||||||
|
* @name 快速热更新配置
|
||||||
|
* @description 一个不错的热更新组件,更新时可以保留 state
|
||||||
|
*/
|
||||||
|
fastRefresh: true,
|
||||||
|
//============== 以下都是max的插件配置 ===============
|
||||||
|
/**
|
||||||
|
* @name 数据流插件
|
||||||
|
* @@doc https://umijs.org/docs/max/data-flow
|
||||||
|
*/
|
||||||
|
model: {},
|
||||||
|
/**
|
||||||
|
* 一个全局的初始数据流,可以用它在插件之间共享数据
|
||||||
|
* @description 可以用来存放一些全局的数据,比如用户信息,或者一些全局的状态,全局初始状态在整个 Umi 项目的最开始创建。
|
||||||
|
* @doc https://umijs.org/docs/max/data-flow#%E5%85%A8%E5%B1%80%E5%88%9D%E5%A7%8B%E7%8A%B6%E6%80%81
|
||||||
|
*/
|
||||||
|
initialState: {},
|
||||||
|
/**
|
||||||
|
* @name layout 插件
|
||||||
|
* @doc https://umijs.org/docs/max/layout-menu
|
||||||
|
*/
|
||||||
|
title: 'Ant Design Pro',
|
||||||
|
layout: {
|
||||||
|
locale: true,
|
||||||
|
...defaultSettings,
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* @name moment2dayjs 插件
|
||||||
|
* @description 将项目中的 moment 替换为 dayjs
|
||||||
|
* @doc https://umijs.org/docs/max/moment2dayjs
|
||||||
|
*/
|
||||||
|
moment2dayjs: {
|
||||||
|
preset: 'antd',
|
||||||
|
plugins: ['duration'],
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* @name 国际化插件
|
||||||
|
* @doc https://umijs.org/docs/max/i18n
|
||||||
|
*/ /**
|
||||||
|
* @name antd 插件
|
||||||
|
* @description 内置了 babel import 插件
|
||||||
|
* @doc https://umijs.org/docs/max/antd#antd
|
||||||
|
*/
|
||||||
|
antd: {},
|
||||||
|
/**
|
||||||
|
* @name 网络请求配置
|
||||||
|
* @description 它基于 axios 和 ahooks 的 useRequest 提供了一套统一的网络请求和错误处理方案。
|
||||||
|
* @doc https://umijs.org/docs/max/request
|
||||||
|
*/
|
||||||
|
request: {},
|
||||||
|
/**
|
||||||
|
* @name 权限插件
|
||||||
|
* @description 基于 initialState 的权限插件,必须先打开 initialState
|
||||||
|
* @doc https://umijs.org/docs/max/access
|
||||||
|
*/
|
||||||
|
access: {},
|
||||||
|
/**
|
||||||
|
* @name <head> 中额外的 script
|
||||||
|
* @description 配置 <head> 中额外的 script
|
||||||
|
*/
|
||||||
|
headScripts: [
|
||||||
|
// 解决首次加载时白屏的问题
|
||||||
|
{
|
||||||
|
src: '/scripts/loading.js',
|
||||||
|
async: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
//================ pro 插件配置 =================
|
||||||
|
presets: ['umi-presets-pro'],
|
||||||
|
/**
|
||||||
|
* @name openAPI 插件的配置
|
||||||
|
* @description 基于 openapi 的规范生成serve 和mock,能减少很多样板代码
|
||||||
|
* @doc https://pro.ant.design/zh-cn/docs/openapi/
|
||||||
|
*/
|
||||||
|
openAPI: [
|
||||||
|
{
|
||||||
|
requestLibPath: "import { request } from '@umijs/max'",
|
||||||
|
// 或者使用在线的版本
|
||||||
|
schemaPath: "http://localhost:8101/api/v2/api-docs",
|
||||||
|
projectName:'hebi',
|
||||||
|
// schemaPath: join(__dirname, 'oneapi.json'),
|
||||||
|
mock: false,
|
||||||
|
},
|
||||||
|
// {
|
||||||
|
// requestLibPath: "import { request } from '@umijs/max'",
|
||||||
|
// schemaPath: 'https://gw.alipayobjects.com/os/antfincdn/CA1dOm%2631B/openapi.json',
|
||||||
|
// projectName: 'swagger',
|
||||||
|
// },
|
||||||
|
],
|
||||||
|
mfsu: {
|
||||||
|
strategy: 'normal',
|
||||||
|
},
|
||||||
|
esbuildMinifyIIFE: true,
|
||||||
|
requestRecord: {},
|
||||||
|
});
|
28
config/defaultSettings.ts
Normal file
28
config/defaultSettings.ts
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
import { ProLayoutProps } from '@ant-design/pro-components';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name
|
||||||
|
*/
|
||||||
|
const Settings: ProLayoutProps & {
|
||||||
|
pwa?: boolean;
|
||||||
|
logo?: string;
|
||||||
|
} = {
|
||||||
|
navTheme: 'light',
|
||||||
|
// 拂晓蓝
|
||||||
|
colorPrimary: '#1890ff',
|
||||||
|
layout: 'mix',
|
||||||
|
contentWidth: 'Fluid',
|
||||||
|
fixedHeader: false,
|
||||||
|
fixSiderbar: true,
|
||||||
|
colorWeak: false,
|
||||||
|
title: '智能数据分析系统',
|
||||||
|
pwa: true,
|
||||||
|
logo: ' https://gw.alipayobjects.com/zos/antfincdn/upvrAjAPQX/Logo_Tech%252520UI.svg',
|
||||||
|
iconfontUrl: '',
|
||||||
|
token: {
|
||||||
|
// 参见ts声明,demo 见文档,通过token 修改样式
|
||||||
|
//https://procomponents.ant.design/components/layout#%E9%80%9A%E8%BF%87-token-%E4%BF%AE%E6%94%B9%E6%A0%B7%E5%BC%8F
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Settings;
|
44
config/proxy.ts
Normal file
44
config/proxy.ts
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
/**
|
||||||
|
* @name 代理的配置
|
||||||
|
* @see 在生产环境 代理是无法生效的,所以这里没有生产环境的配置
|
||||||
|
* -------------------------------
|
||||||
|
* The agent cannot take effect in the production environment
|
||||||
|
* so there is no configuration of the production environment
|
||||||
|
* For details, please see
|
||||||
|
* https://pro.ant.design/docs/deploy
|
||||||
|
*
|
||||||
|
* @doc https://umijs.org/docs/guides/proxy
|
||||||
|
*/
|
||||||
|
export default {
|
||||||
|
// 如果需要自定义本地开发服务器 请取消注释按需调整
|
||||||
|
// dev: {
|
||||||
|
// // localhost:8000/api/** -> https://preview.pro.ant.design/api/**
|
||||||
|
// '/api/': {
|
||||||
|
// // 要代理的地址
|
||||||
|
// target: 'https://preview.pro.ant.design',
|
||||||
|
// // 配置了这个可以从 http 代理到 https
|
||||||
|
// // 依赖 origin 的功能可能需要这个,比如 cookie
|
||||||
|
// changeOrigin: true,
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name 详细的代理配置
|
||||||
|
* @doc https://github.com/chimurai/http-proxy-middleware
|
||||||
|
*/
|
||||||
|
test: {
|
||||||
|
// localhost:8000/api/** -> https://preview.pro.ant.design/api/**
|
||||||
|
'/api/': {
|
||||||
|
target: 'https://proapi.azurewebsites.net',
|
||||||
|
changeOrigin: true,
|
||||||
|
pathRewrite: { '^': '' },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
pre: {
|
||||||
|
'/api/': {
|
||||||
|
target: 'your pre url',
|
||||||
|
changeOrigin: true,
|
||||||
|
pathRewrite: { '^': '' },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
24
config/routes.ts
Normal file
24
config/routes.ts
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
export default [
|
||||||
|
{path: '/user',layout: false,routes: [
|
||||||
|
{ name: '登录', path: '/user/login', component: './User/Login' },
|
||||||
|
{ name: '注册', path: '/user/register', component: './User/Register' }
|
||||||
|
]},
|
||||||
|
{path:"/", redirect: "/add_chart"},
|
||||||
|
|
||||||
|
{ path: '/add_chart', name :"智能分析", icon: "barChart", component: './AddChart' },
|
||||||
|
{ path: '/add_async', name :"智能分析(异步)", icon: "DotChartOutlined", component: './AddChartAsync' },
|
||||||
|
{ path: '/my_chart', name :"我的图表", icon: "PictureOutlined", component: './MyChart' },
|
||||||
|
{ path: '/forum', name :"交流论坛", icon: "CrownOutlined", component: './Forum' },
|
||||||
|
{
|
||||||
|
path: '/admin',
|
||||||
|
name: '管理页',
|
||||||
|
icon: 'crown',
|
||||||
|
access: 'canAdmin',
|
||||||
|
routes: [
|
||||||
|
{ path: '/admin', redirect: '/admin/sub-page' },
|
||||||
|
{ path: '/admin/sub-page', name: '二级管理页', component: './Admin' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{ path: '/', redirect: '/welcome' },
|
||||||
|
{ path: '*', layout: false, component: './404' },
|
||||||
|
];
|
1
icon.svg
Normal file
1
icon.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1738593107479" class="icon" viewBox="0 0 1146 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5383" width="223.828125" height="200" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M998.4 141.913043c-26.713043-23.930435-55.652174-44.521739-86.817391-60.660869-36.173913-18.921739-73.46087-32.834783-113.530435-41.182609-34.504348-7.234783-69.565217-11.130435-104.626087-9.460869-42.852174 2.226087-84.034783 10.017391-124.66087 24.486956-35.06087 12.8-68.452174 28.93913-100.173913 49.530435-22.817391 15.026087-45.078261 31.165217-64.556521 50.086956-109.078261 105.73913-220.93913 267.686957-218.156522 428.52174-4.452174 38.956522 7.791304 120.765217 13.913043 144.13913 10.573913 42.852174 25.6 84.034783 48.417392 123.547826 5.008696-15.582609 8.904348-30.052174 14.469565-44.521739 6.678261-18.921739 15.582609-36.730435 25.6-53.982609 25.6-41.73913 61.217391-68.452174 111.860869-72.904348 37.286957-3.33913 72.904348 2.226087 109.078261 8.904348 49.530435 9.46087 98.504348 21.704348 148.591305 27.269566 32.834783 3.895652 65.113043 5.565217 98.504347 3.33913 86.26087-5.565217 161.947826-37.286957 229.843479-88.486957 165.843478-125.773913 161.947826-354.504348 12.243478-488.626087z m-260.452174 421.843479c-27.826087 0-50.086957-23.373913-50.086956-51.756522 0-27.826087 22.817391-51.2 50.643478-50.643478 28.382609 0 51.2 22.817391 51.756522 51.2 0 28.93913-22.817391 51.756522-52.313044 51.2z" fill="#046FFF" p-id="5384" data-spm-anchor-id="a313x.search_index.0.i16.4e7f3a81wduNu9"></path><path d="M370.086957 455.234783c-37.286957-21.147826-79.582609-33.391304-125.773914-33.391305-81.808696 0-154.713043 38.956522-200.904347 99.06087 28.93913 22.817391 65.113043 40.626087 106.295652 46.747826 99.06087 15.582609 182.53913-71.791304 220.382609-112.417391z" fill="#045DE5" p-id="5385"></path><path d="M602.156522 885.982609c-30.052174-30.608696-67.895652-53.982609-111.304348-66.226087-78.469565-22.26087-159.165217-5.008696-220.382609 40.069565 21.704348 29.495652 51.756522 56.765217 89.043478 74.017391 91.269565 42.295652 195.33913-18.921739 242.643479-47.860869z" fill="#3B97FF" p-id="5386"></path><path d="M427.965217 1001.182609c-23.373913-1.669565-55.095652-6.678261-80.695652-21.704348-45.634783-27.269565-67.33913-52.313043-76.8-120.208696 23.373913-2.782609 49.530435-1.113043 74.573913 9.46087 60.104348 24.486957 75.686957 97.391304 82.921739 132.452174z" fill="#045CE5" p-id="5387"></path></svg>
|
After Width: | Height: | Size: 2.5 KiB |
11
jsconfig.json
Normal file
11
jsconfig.json
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"jsx": "react-jsx",
|
||||||
|
"emitDecoratorMetadata": true,
|
||||||
|
"experimentalDecorators": true,
|
||||||
|
"baseUrl": ".",
|
||||||
|
"paths": {
|
||||||
|
"@/*": ["./src/*"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
104
package.json
Normal file
104
package.json
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
{
|
||||||
|
"name": "ant-design-pro",
|
||||||
|
"version": "6.0.0",
|
||||||
|
"private": true,
|
||||||
|
"description": "An out-of-box UI solution for enterprise applications",
|
||||||
|
"scripts": {
|
||||||
|
"analyze": "cross-env ANALYZE=1 max build",
|
||||||
|
"build": "max build",
|
||||||
|
"deploy": "npm run build && npm run gh-pages",
|
||||||
|
"dev": "npm run start:dev",
|
||||||
|
"gh-pages": "gh-pages -d dist",
|
||||||
|
"i18n-remove": "pro i18n-remove --locale=zh-CN --write",
|
||||||
|
"postinstall": "max setup",
|
||||||
|
"jest": "jest",
|
||||||
|
"lint": "npm run lint:js && npm run lint:prettier && npm run tsc",
|
||||||
|
"lint-staged": "lint-staged",
|
||||||
|
"lint-staged:js": "eslint --ext .js,.jsx,.ts,.tsx ",
|
||||||
|
"lint:fix": "eslint --fix --cache --ext .js,.jsx,.ts,.tsx --format=pretty ./src ",
|
||||||
|
"lint:js": "eslint --cache --ext .js,.jsx,.ts,.tsx --format=pretty ./src",
|
||||||
|
"lint:prettier": "prettier -c --write \"**/**.{js,jsx,tsx,ts,less,md,json}\" --end-of-line auto",
|
||||||
|
"openapi": "max openapi",
|
||||||
|
"prepare": "husky install",
|
||||||
|
"prettier": "prettier -c --write \"**/**.{js,jsx,tsx,ts,less,md,json}\"",
|
||||||
|
"preview": "npm run build && max preview --port 8000",
|
||||||
|
"record": "cross-env NODE_ENV=development REACT_APP_ENV=test max record --scene=login",
|
||||||
|
"serve": "umi-serve",
|
||||||
|
"start": "cross-env UMI_ENV=dev max dev",
|
||||||
|
"start:dev": "cross-env REACT_APP_ENV=dev MOCK=none UMI_ENV=dev max dev",
|
||||||
|
"start:no-mock": "cross-env MOCK=none UMI_ENV=dev max dev",
|
||||||
|
"start:pre": "cross-env REACT_APP_ENV=pre UMI_ENV=dev max dev",
|
||||||
|
"start:test": "cross-env REACT_APP_ENV=test MOCK=none UMI_ENV=dev max dev",
|
||||||
|
"test": "jest",
|
||||||
|
"test:coverage": "npm run jest -- --coverage",
|
||||||
|
"test:update": "npm run jest -- -u",
|
||||||
|
"tsc": "tsc --noEmit"
|
||||||
|
},
|
||||||
|
"lint-staged": {
|
||||||
|
"**/*.{js,jsx,ts,tsx}": "npm run lint-staged:js",
|
||||||
|
"**/*.{js,jsx,tsx,ts,less,md,json}": [
|
||||||
|
"prettier --write"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"browserslist": [
|
||||||
|
"> 1%",
|
||||||
|
"last 2 versions",
|
||||||
|
"not ie <= 10"
|
||||||
|
],
|
||||||
|
"dependencies": {
|
||||||
|
"@ant-design/icons": "^4.8.1",
|
||||||
|
"@ant-design/pro-components": "^2.6.48",
|
||||||
|
"@umijs/route-utils": "^2.2.2",
|
||||||
|
"antd": "5.24.5",
|
||||||
|
"antd-style": "^3.6.1",
|
||||||
|
"classnames": "^2.5.1",
|
||||||
|
"echarts": "^5.6.0",
|
||||||
|
"echarts-for-react": "^3.0.2",
|
||||||
|
"lodash": "^4.17.21",
|
||||||
|
"moment": "^2.30.1",
|
||||||
|
"omit.js": "^2.0.2",
|
||||||
|
"querystring": "^0.2.1",
|
||||||
|
"rc-menu": "^9.12.4",
|
||||||
|
"rc-util": "^5.38.1",
|
||||||
|
"react": "^18.2.0",
|
||||||
|
"react-dom": "^18.2.0",
|
||||||
|
"react-echarts": "^0.1.1",
|
||||||
|
"react-helmet-async": "^1.3.0",
|
||||||
|
"react-intl": "^7.1.6"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@ant-design/pro-cli": "^3.3.0",
|
||||||
|
"@testing-library/react": "^13.4.0",
|
||||||
|
"@types/antd": "^1.0.4",
|
||||||
|
"@types/classnames": "^2.3.1",
|
||||||
|
"@types/express": "^4.17.21",
|
||||||
|
"@types/history": "^4.7.11",
|
||||||
|
"@types/jest": "^29.5.11",
|
||||||
|
"@types/lodash": "^4.14.202",
|
||||||
|
"@types/react": "^18.2.48",
|
||||||
|
"@types/react-dom": "^18.2.18",
|
||||||
|
"@types/react-helmet": "^6.1.11",
|
||||||
|
"@umijs/fabric": "^2.14.1",
|
||||||
|
"@umijs/lint": "^4.1.1",
|
||||||
|
"@umijs/max": "^4.1.1",
|
||||||
|
"cross-env": "^7.0.3",
|
||||||
|
"eslint": "^8.56.0",
|
||||||
|
"express": "^4.18.2",
|
||||||
|
"gh-pages": "^3.2.3",
|
||||||
|
"husky": "^7.0.4",
|
||||||
|
"jest": "^29.7.0",
|
||||||
|
"jest-environment-jsdom": "^29.7.0",
|
||||||
|
"lint-staged": "^10.5.4",
|
||||||
|
"mockjs": "^1.1.0",
|
||||||
|
"prettier": "^2.8.8",
|
||||||
|
"react-dev-inspector": "^1.9.0",
|
||||||
|
"swagger-ui-dist": "^4.19.1",
|
||||||
|
"ts-node": "^10.9.2",
|
||||||
|
"typescript": "^5.3.3",
|
||||||
|
"umi-presets-pro": "^2.0.3",
|
||||||
|
"umi-serve": "^1.9.11"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12.0.0"
|
||||||
|
}
|
||||||
|
}
|
21929
pnpm-lock.yaml
generated
Normal file
21929
pnpm-lock.yaml
generated
Normal file
File diff suppressed because it is too large
Load Diff
1
public/CNAME
Normal file
1
public/CNAME
Normal file
@ -0,0 +1 @@
|
|||||||
|
preview.pro.ant.design
|
BIN
public/favicon.ico
Normal file
BIN
public/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 7.1 KiB |
1
public/logo.svg
Normal file
1
public/logo.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1738588519475" class="icon" viewBox="0 0 1033 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="12751" xmlns:xlink="http://www.w3.org/1999/xlink" width="201.7578125" height="200"><path d="M0 197.797058m108.406521-28.832589l526.886667-140.134623q108.406521-28.832589 137.239111 79.573932l140.134622 526.886667q28.832589 108.406521-79.573932 137.239111l-526.886667 140.134622q-108.406521 28.832589-137.239111-79.573932l-140.134622-526.886667q-28.832589-108.406521 79.573932-137.23911Z" fill="#0F62FE" p-id="12752"></path><path d="M262.810642 253.195618m160.250391 0l449.053646 0q160.250391 0 160.250391 160.250391l0 449.053647q0 160.250391-160.250391 160.250391l-449.053646 0q-160.250391 0-160.250391-160.250391l0-449.053647q0-160.250391 160.250391-160.250391Z" fill="#C1D0FF" fill-opacity=".4" p-id="12753"></path><path d="M463.123631 611.981822c0-17.701258 14.34882-32.050078 32.050078-32.050079h8.012519c17.701258 0 32.050078 14.34882 32.050079 32.050079v224.355355h-72.112676V611.981822zM612.694936 469.533646c0-17.701258 14.34882-32.050078 32.050078-32.050078h8.01252c17.701258 0 32.050078 14.34882 32.050078 32.050078v366.805133h-72.112676V469.533646zM762.266241 560.344338c0-17.701258 14.34882-32.050078 32.050078-32.050078h8.01252c17.701258 0 32.050078 14.34882 32.050078 32.050078v275.994441h-72.112676V560.344338z" fill="#FFFFFF" p-id="12754"></path></svg>
|
After Width: | Height: | Size: 1.5 KiB |
202
public/scripts/loading.js
Normal file
202
public/scripts/loading.js
Normal file
@ -0,0 +1,202 @@
|
|||||||
|
/**
|
||||||
|
* loading 占位
|
||||||
|
* 解决首次加载时白屏的问题
|
||||||
|
*/
|
||||||
|
(function () {
|
||||||
|
const _root = document.querySelector('#root');
|
||||||
|
if (_root && _root.innerHTML === '') {
|
||||||
|
_root.innerHTML = `
|
||||||
|
<style>
|
||||||
|
html,
|
||||||
|
body,
|
||||||
|
#root {
|
||||||
|
height: 100%;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
#root {
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-size: 100% auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loading-title {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loading-sub-title {
|
||||||
|
margin-top: 20px;
|
||||||
|
font-size: 1rem;
|
||||||
|
color: #888;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-loading-warp {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 26px;
|
||||||
|
}
|
||||||
|
.ant-spin {
|
||||||
|
position: absolute;
|
||||||
|
display: none;
|
||||||
|
-webkit-box-sizing: border-box;
|
||||||
|
box-sizing: border-box;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
color: rgba(0, 0, 0, 0.65);
|
||||||
|
color: #1890ff;
|
||||||
|
font-size: 14px;
|
||||||
|
font-variant: tabular-nums;
|
||||||
|
line-height: 1.5;
|
||||||
|
text-align: center;
|
||||||
|
list-style: none;
|
||||||
|
opacity: 0;
|
||||||
|
-webkit-transition: -webkit-transform 0.3s
|
||||||
|
cubic-bezier(0.78, 0.14, 0.15, 0.86);
|
||||||
|
transition: -webkit-transform 0.3s
|
||||||
|
cubic-bezier(0.78, 0.14, 0.15, 0.86);
|
||||||
|
transition: transform 0.3s cubic-bezier(0.78, 0.14, 0.15, 0.86);
|
||||||
|
transition: transform 0.3s cubic-bezier(0.78, 0.14, 0.15, 0.86),
|
||||||
|
-webkit-transform 0.3s cubic-bezier(0.78, 0.14, 0.15, 0.86);
|
||||||
|
-webkit-font-feature-settings: "tnum";
|
||||||
|
font-feature-settings: "tnum";
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-spin-spinning {
|
||||||
|
position: static;
|
||||||
|
display: inline-block;
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-spin-dot {
|
||||||
|
position: relative;
|
||||||
|
display: inline-block;
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
font-size: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-spin-dot-item {
|
||||||
|
position: absolute;
|
||||||
|
display: block;
|
||||||
|
width: 9px;
|
||||||
|
height: 9px;
|
||||||
|
background-color: #1890ff;
|
||||||
|
border-radius: 100%;
|
||||||
|
-webkit-transform: scale(0.75);
|
||||||
|
-ms-transform: scale(0.75);
|
||||||
|
transform: scale(0.75);
|
||||||
|
-webkit-transform-origin: 50% 50%;
|
||||||
|
-ms-transform-origin: 50% 50%;
|
||||||
|
transform-origin: 50% 50%;
|
||||||
|
opacity: 0.3;
|
||||||
|
-webkit-animation: antspinmove 1s infinite linear alternate;
|
||||||
|
animation: antSpinMove 1s infinite linear alternate;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-spin-dot-item:nth-child(1) {
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-spin-dot-item:nth-child(2) {
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
-webkit-animation-delay: 0.4s;
|
||||||
|
animation-delay: 0.4s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-spin-dot-item:nth-child(3) {
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
-webkit-animation-delay: 0.8s;
|
||||||
|
animation-delay: 0.8s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-spin-dot-item:nth-child(4) {
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
-webkit-animation-delay: 1.2s;
|
||||||
|
animation-delay: 1.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-spin-dot-spin {
|
||||||
|
-webkit-transform: rotate(45deg);
|
||||||
|
-ms-transform: rotate(45deg);
|
||||||
|
transform: rotate(45deg);
|
||||||
|
-webkit-animation: antrotate 1.2s infinite linear;
|
||||||
|
animation: antRotate 1.2s infinite linear;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-spin-lg .ant-spin-dot {
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
font-size: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-spin-lg .ant-spin-dot i {
|
||||||
|
width: 14px;
|
||||||
|
height: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media all and (-ms-high-contrast: none), (-ms-high-contrast: active) {
|
||||||
|
.ant-spin-blur {
|
||||||
|
background: #fff;
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@-webkit-keyframes antSpinMove {
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes antSpinMove {
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@-webkit-keyframes antRotate {
|
||||||
|
to {
|
||||||
|
-webkit-transform: rotate(405deg);
|
||||||
|
transform: rotate(405deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes antRotate {
|
||||||
|
to {
|
||||||
|
-webkit-transform: rotate(405deg);
|
||||||
|
transform: rotate(405deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<div style="
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
height: 100%;
|
||||||
|
min-height: 362px;
|
||||||
|
">
|
||||||
|
<div class="page-loading-warp">
|
||||||
|
<div class="ant-spin ant-spin-lg ant-spin-spinning">
|
||||||
|
<span class="ant-spin-dot ant-spin-dot-spin">
|
||||||
|
<i class="ant-spin-dot-item"></i>
|
||||||
|
<i class="ant-spin-dot-item"></i>
|
||||||
|
<i class="ant-spin-dot-item"></i>
|
||||||
|
<i class="ant-spin-dot-item"></i>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="loading-title">
|
||||||
|
正在加载资源
|
||||||
|
</div>
|
||||||
|
<div class="loading-sub-title">
|
||||||
|
初次加载资源可能需要较多时间 请耐心等待
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
})();
|
11
src/access.ts
Normal file
11
src/access.ts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
//控制页面访问权限
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see https://umijs.org/docs/max/access#access
|
||||||
|
* */
|
||||||
|
export default function access(initialState: { currentUser?: API.CurrentUser } | undefined) {
|
||||||
|
const { currentUser } = initialState ?? {};
|
||||||
|
return {
|
||||||
|
canAdmin: currentUser && currentUser.access === 'admin',
|
||||||
|
};
|
||||||
|
}
|
116
src/app.tsx
Normal file
116
src/app.tsx
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
import { AvatarDropdown, AvatarName, Footer, Question } from '@/components';
|
||||||
|
import { SettingDrawer } from '@ant-design/pro-components';
|
||||||
|
import type { RunTimeLayoutConfig } from '@umijs/max';
|
||||||
|
import { history} from '@umijs/max';
|
||||||
|
import { errorConfig } from './requestErrorConfig';
|
||||||
|
import { getLoginUserUsingGet } from './services/hebi/userController';
|
||||||
|
const isDev = process.env.NODE_ENV === 'development';
|
||||||
|
const loginPath = '/user/login';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see https://umijs.org/zh-CN/plugins/plugin-initial-state
|
||||||
|
* */
|
||||||
|
export async function getInitialState(): Promise<{
|
||||||
|
currentUser?: API.LoginUserVO;
|
||||||
|
}> {
|
||||||
|
const fetchUserInfo = async () => {
|
||||||
|
try {
|
||||||
|
const res = await getLoginUserUsingGet();
|
||||||
|
return res.data;
|
||||||
|
} catch (error) {
|
||||||
|
history.push(loginPath);
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
};
|
||||||
|
// 如果不是登录页面,执行
|
||||||
|
const { location } = history;
|
||||||
|
if (location.pathname !== loginPath) {
|
||||||
|
const currentUser = await fetchUserInfo();
|
||||||
|
return {
|
||||||
|
currentUser,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export const layout: RunTimeLayoutConfig = ({ initialState, setInitialState }) => {
|
||||||
|
return {
|
||||||
|
actionsRender: () => [<Question key="doc" />],
|
||||||
|
avatarProps: {
|
||||||
|
src: initialState?.currentUser?.userAvatar,
|
||||||
|
title: <AvatarName />,
|
||||||
|
render: (_, avatarChildren) => {
|
||||||
|
return <AvatarDropdown>{avatarChildren}</AvatarDropdown>;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
waterMarkProps: {
|
||||||
|
content: initialState?.currentUser?.name,
|
||||||
|
},
|
||||||
|
footerRender: () => <Footer />,
|
||||||
|
onPageChange: () => {
|
||||||
|
const { location } = history;
|
||||||
|
// 如果没有登录,重定向到 login
|
||||||
|
if (!initialState?.currentUser && location.pathname !== loginPath) {
|
||||||
|
history.push(loginPath);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
bgLayoutImgList: [
|
||||||
|
{
|
||||||
|
src: 'https://mdn.alipayobjects.com/yuyan_qk0oxh/afts/img/D2LWSqNny4sAAAAAAAAAAAAAFl94AQBr',
|
||||||
|
left: 85,
|
||||||
|
bottom: 100,
|
||||||
|
height: '303px',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
src: 'https://mdn.alipayobjects.com/yuyan_qk0oxh/afts/img/C2TWRpJpiC0AAAAAAAAAAAAAFl94AQBr',
|
||||||
|
bottom: -68,
|
||||||
|
right: -45,
|
||||||
|
height: '303px',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
src: 'https://mdn.alipayobjects.com/yuyan_qk0oxh/afts/img/F6vSTbj8KpYAAAAAAAAAAAAAFl94AQBr',
|
||||||
|
bottom: 0,
|
||||||
|
left: 0,
|
||||||
|
width: '331px',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
|
menuHeaderRender: undefined,
|
||||||
|
childrenRender: (children) => {
|
||||||
|
// if (initialState?.loading) return <PageLoading />;
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{children}
|
||||||
|
{isDev && (
|
||||||
|
<SettingDrawer
|
||||||
|
disableUrlParams
|
||||||
|
enableDarkTheme
|
||||||
|
settings={initialState?.settings}
|
||||||
|
onSettingChange={(settings) => {
|
||||||
|
setInitialState((preInitialState) => ({
|
||||||
|
...preInitialState,
|
||||||
|
settings,
|
||||||
|
}));
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
...initialState?.settings,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name request 配置,可以配置错误处理
|
||||||
|
* 它基于 axios 和 ahooks 的 useRequest 提供了一套统一的网络请求和错误处理方案。
|
||||||
|
* @doc https://umijs.org/docs/max/request#配置
|
||||||
|
*/
|
||||||
|
export const request = {
|
||||||
|
|
||||||
|
baseURL:"http://localhost:8101",
|
||||||
|
withCredentials:true,
|
||||||
|
...errorConfig,
|
||||||
|
};
|
35
src/components/Footer/index.tsx
Normal file
35
src/components/Footer/index.tsx
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
import { GithubOutlined } from '@ant-design/icons';
|
||||||
|
import { DefaultFooter } from '@ant-design/pro-components';
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
const Footer: React.FC = () => {
|
||||||
|
return (
|
||||||
|
<DefaultFooter
|
||||||
|
style={{
|
||||||
|
background: 'none',
|
||||||
|
}}
|
||||||
|
links={[
|
||||||
|
{
|
||||||
|
key: 'Ant Design Pro',
|
||||||
|
title: 'Ant Design Pro',
|
||||||
|
href: 'https://pro.ant.design',
|
||||||
|
blankTarget: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'github',
|
||||||
|
title: <GithubOutlined />,
|
||||||
|
href: 'https://github.com/ant-design/ant-design-pro',
|
||||||
|
blankTarget: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'Ant Design',
|
||||||
|
title: 'Ant Design',
|
||||||
|
href: 'https://ant.design',
|
||||||
|
blankTarget: true,
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Footer;
|
27
src/components/HeaderDropdown/index.tsx
Normal file
27
src/components/HeaderDropdown/index.tsx
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
import { Dropdown } from 'antd';
|
||||||
|
import type { DropDownProps } from 'antd/es/dropdown';
|
||||||
|
import React from 'react';
|
||||||
|
import { createStyles } from 'antd-style';
|
||||||
|
import classNames from 'classnames';
|
||||||
|
|
||||||
|
const useStyles = createStyles(({ token }) => {
|
||||||
|
return {
|
||||||
|
dropdown: {
|
||||||
|
[`@media screen and (max-width: ${token.screenXS}px)`]: {
|
||||||
|
width: '100%',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
export type HeaderDropdownProps = {
|
||||||
|
overlayClassName?: string;
|
||||||
|
placement?: 'bottomLeft' | 'bottomRight' | 'topLeft' | 'topCenter' | 'topRight' | 'bottomCenter';
|
||||||
|
} & Omit<DropDownProps, 'overlay'>;
|
||||||
|
|
||||||
|
const HeaderDropdown: React.FC<HeaderDropdownProps> = ({ overlayClassName: cls, ...restProps }) => {
|
||||||
|
const { styles } = useStyles();
|
||||||
|
return <Dropdown overlayClassName={classNames(styles.dropdown, cls)} {...restProps} />;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default HeaderDropdown;
|
138
src/components/RightContent/AvatarDropdown.tsx
Normal file
138
src/components/RightContent/AvatarDropdown.tsx
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
import { LogoutOutlined, SettingOutlined, UserOutlined } from '@ant-design/icons';
|
||||||
|
import { history, useModel } from '@umijs/max';
|
||||||
|
import { Spin } from 'antd';
|
||||||
|
import { createStyles } from 'antd-style';
|
||||||
|
import { stringify } from 'querystring';
|
||||||
|
import type { MenuInfo } from 'rc-menu/lib/interface';
|
||||||
|
import React, { useCallback } from 'react';
|
||||||
|
import { flushSync } from 'react-dom';
|
||||||
|
import HeaderDropdown from '../HeaderDropdown';
|
||||||
|
import { userLogoutUsingPost } from '@/services/hebi/userController';
|
||||||
|
|
||||||
|
export type GlobalHeaderRightProps = {
|
||||||
|
menu?: boolean;
|
||||||
|
children?: React.ReactNode;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const AvatarName = () => {
|
||||||
|
const { initialState } = useModel('@@initialState');
|
||||||
|
const { currentUser } = initialState || {};
|
||||||
|
return <span className="anticon">{currentUser?.userName}</span>;
|
||||||
|
};
|
||||||
|
|
||||||
|
const useStyles = createStyles(({ token }) => {
|
||||||
|
return {
|
||||||
|
action: {
|
||||||
|
display: 'flex',
|
||||||
|
height: '48px',
|
||||||
|
marginLeft: 'auto',
|
||||||
|
overflow: 'hidden',
|
||||||
|
alignItems: 'center',
|
||||||
|
padding: '0 8px',
|
||||||
|
cursor: 'pointer',
|
||||||
|
borderRadius: token.borderRadius,
|
||||||
|
'&:hover': {
|
||||||
|
backgroundColor: token.colorBgTextHover,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
export const AvatarDropdown: React.FC<GlobalHeaderRightProps> = ({ menu, children }) => {
|
||||||
|
/**
|
||||||
|
* 退出登录,并且将当前的 url 保存
|
||||||
|
*/
|
||||||
|
const loginOut = async () => {
|
||||||
|
await userLogoutUsingPost();
|
||||||
|
const { search, pathname } = window.location;
|
||||||
|
const urlParams = new URL(window.location.href).searchParams;
|
||||||
|
/** 此方法会跳转到 redirect 参数所在的位置 */
|
||||||
|
const redirect = urlParams.get('redirect');
|
||||||
|
// Note: There may be security issues, please note
|
||||||
|
if (window.location.pathname !== '/user/login' && !redirect) {
|
||||||
|
history.replace({
|
||||||
|
pathname: '/user/login',
|
||||||
|
search: stringify({
|
||||||
|
redirect: pathname + search,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const { styles } = useStyles();
|
||||||
|
|
||||||
|
const { initialState, setInitialState } = useModel('@@initialState');
|
||||||
|
|
||||||
|
const onMenuClick = useCallback(
|
||||||
|
(event: MenuInfo) => {
|
||||||
|
const { key } = event;
|
||||||
|
if (key === 'logout') {
|
||||||
|
flushSync(() => {
|
||||||
|
setInitialState((s) => ({ ...s, currentUser: undefined }));
|
||||||
|
});
|
||||||
|
loginOut();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
history.push(`/account/${key}`);
|
||||||
|
},
|
||||||
|
[setInitialState],
|
||||||
|
);
|
||||||
|
|
||||||
|
const loading = (
|
||||||
|
<span className={styles.action}>
|
||||||
|
<Spin
|
||||||
|
size="small"
|
||||||
|
style={{
|
||||||
|
marginLeft: 8,
|
||||||
|
marginRight: 8,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!initialState) {
|
||||||
|
return loading;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { currentUser } = initialState;
|
||||||
|
|
||||||
|
if (!currentUser || !currentUser.userName) {
|
||||||
|
return loading;
|
||||||
|
}
|
||||||
|
|
||||||
|
const menuItems = [
|
||||||
|
...(menu
|
||||||
|
? [
|
||||||
|
{
|
||||||
|
key: 'center',
|
||||||
|
icon: <UserOutlined />,
|
||||||
|
label: '个人中心',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'settings',
|
||||||
|
icon: <SettingOutlined />,
|
||||||
|
label: '个人设置',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'divider' as const,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
: []),
|
||||||
|
{
|
||||||
|
key: 'logout',
|
||||||
|
icon: <LogoutOutlined />,
|
||||||
|
label: '退出登录',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<HeaderDropdown
|
||||||
|
menu={{
|
||||||
|
selectedKeys: [],
|
||||||
|
onClick: onMenuClick,
|
||||||
|
items: menuItems,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</HeaderDropdown>
|
||||||
|
);
|
||||||
|
};
|
27
src/components/RightContent/index.tsx
Normal file
27
src/components/RightContent/index.tsx
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
import { QuestionCircleOutlined } from '@ant-design/icons';
|
||||||
|
import '@umijs/max';
|
||||||
|
export type SiderTheme = 'light' | 'dark';
|
||||||
|
export const SelectLang = () => {
|
||||||
|
return (
|
||||||
|
<UmiSelectLang
|
||||||
|
style={{
|
||||||
|
padding: 4,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
export const Question = () => {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: 'flex',
|
||||||
|
height: 26,
|
||||||
|
}}
|
||||||
|
onClick={() => {
|
||||||
|
window.open('https://pro.ant.design/docs/getting-started');
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<QuestionCircleOutlined />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
11
src/components/index.ts
Normal file
11
src/components/index.ts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
/**
|
||||||
|
* 这个文件作为组件的目录
|
||||||
|
* 目的是统一管理对外输出的组件,方便分类
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* 布局组件
|
||||||
|
*/
|
||||||
|
import Footer from './Footer';
|
||||||
|
import { Question } from './RightContent';
|
||||||
|
import { AvatarDropdown, AvatarName } from './RightContent/AvatarDropdown';
|
||||||
|
export { AvatarDropdown, AvatarName, Footer, Question};
|
50
src/global.css
Normal file
50
src/global.css
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
html,
|
||||||
|
body,
|
||||||
|
#root {
|
||||||
|
height: 100%;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
|
||||||
|
}
|
||||||
|
.colorWeak {
|
||||||
|
filter: invert(80%);
|
||||||
|
}
|
||||||
|
.ant-layout {
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
.ant-pro-sider.ant-layout-sider.ant-pro-sider-fixed {
|
||||||
|
left: unset;
|
||||||
|
}
|
||||||
|
canvas {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
text-rendering: optimizeLegibility;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
}
|
||||||
|
ul,
|
||||||
|
ol {
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.ant-table {
|
||||||
|
width: 100%;
|
||||||
|
overflow-x: auto;
|
||||||
|
}
|
||||||
|
.ant-table-thead > tr > th,
|
||||||
|
.ant-table-tbody > tr > th,
|
||||||
|
.ant-table-thead > tr > td,
|
||||||
|
.ant-table-tbody > tr > td {
|
||||||
|
white-space: pre;
|
||||||
|
}
|
||||||
|
.ant-table-thead > tr > th > span,
|
||||||
|
.ant-table-tbody > tr > th > span,
|
||||||
|
.ant-table-thead > tr > td > span,
|
||||||
|
.ant-table-tbody > tr > td > span {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.margin-16 {
|
||||||
|
margin-bottom: 18px;
|
||||||
|
}
|
57
src/global.less
Normal file
57
src/global.less
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
html,
|
||||||
|
body,
|
||||||
|
#root {
|
||||||
|
height: 100%;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial,
|
||||||
|
'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol',
|
||||||
|
'Noto Color Emoji';
|
||||||
|
}
|
||||||
|
|
||||||
|
.colorWeak {
|
||||||
|
filter: invert(80%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-layout {
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
.ant-pro-sider.ant-layout-sider.ant-pro-sider-fixed {
|
||||||
|
left: unset;
|
||||||
|
}
|
||||||
|
|
||||||
|
canvas {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
text-rendering: optimizeLegibility;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul,
|
||||||
|
ol {
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.ant-table {
|
||||||
|
width: 100%;
|
||||||
|
overflow-x: auto;
|
||||||
|
&-thead > tr,
|
||||||
|
&-tbody > tr {
|
||||||
|
> th,
|
||||||
|
> td {
|
||||||
|
white-space: pre;
|
||||||
|
> span {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.margin-16{
|
||||||
|
margin-bottom: 18px;
|
||||||
|
}
|
92
src/global.tsx
Normal file
92
src/global.tsx
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
import '@umijs/max';
|
||||||
|
import { Button, message, notification } from 'antd';
|
||||||
|
import defaultSettings from '../config/defaultSettings';
|
||||||
|
const { pwa } = defaultSettings;
|
||||||
|
const isHttps = document.location.protocol === 'https:';
|
||||||
|
const clearCache = () => {
|
||||||
|
// remove all caches
|
||||||
|
if (window.caches) {
|
||||||
|
caches
|
||||||
|
.keys()
|
||||||
|
.then((keys) => {
|
||||||
|
keys.forEach((key) => {
|
||||||
|
caches.delete(key);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch((e) => console.log(e));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// if pwa is true
|
||||||
|
if (pwa) {
|
||||||
|
// Notify user if offline now
|
||||||
|
window.addEventListener('sw.offline', () => {
|
||||||
|
message.warning('当前处于离线状态');
|
||||||
|
});
|
||||||
|
|
||||||
|
// Pop up a prompt on the page asking the user if they want to use the latest version
|
||||||
|
window.addEventListener('sw.updated', (event: Event) => {
|
||||||
|
const e = event as CustomEvent;
|
||||||
|
const reloadSW = async () => {
|
||||||
|
// Check if there is sw whose state is waiting in ServiceWorkerRegistration
|
||||||
|
// https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerRegistration
|
||||||
|
const worker = e.detail && e.detail.waiting;
|
||||||
|
if (!worker) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// Send skip-waiting event to waiting SW with MessageChannel
|
||||||
|
await new Promise((resolve, reject) => {
|
||||||
|
const channel = new MessageChannel();
|
||||||
|
channel.port1.onmessage = (msgEvent) => {
|
||||||
|
if (msgEvent.data.error) {
|
||||||
|
reject(msgEvent.data.error);
|
||||||
|
} else {
|
||||||
|
resolve(msgEvent.data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
worker.postMessage(
|
||||||
|
{
|
||||||
|
type: 'skip-waiting',
|
||||||
|
},
|
||||||
|
[channel.port2],
|
||||||
|
);
|
||||||
|
});
|
||||||
|
clearCache();
|
||||||
|
window.location.reload();
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
const key = `open${Date.now()}`;
|
||||||
|
const btn = (
|
||||||
|
<Button
|
||||||
|
type="primary"
|
||||||
|
onClick={() => {
|
||||||
|
notification.destroy(key);
|
||||||
|
reloadSW();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{'刷新'}
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
|
notification.open({
|
||||||
|
message: '有新内容',
|
||||||
|
description: '请点击“刷新”按钮或者手动刷新页面',
|
||||||
|
btn,
|
||||||
|
key,
|
||||||
|
onClose: async () => null,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
} else if ('serviceWorker' in navigator && isHttps) {
|
||||||
|
// unregister service worker
|
||||||
|
const { serviceWorker } = navigator;
|
||||||
|
if (serviceWorker.getRegistrations) {
|
||||||
|
serviceWorker.getRegistrations().then((sws) => {
|
||||||
|
sws.forEach((sw) => {
|
||||||
|
sw.unregister();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
serviceWorker.getRegistration().then((sw) => {
|
||||||
|
if (sw) sw.unregister();
|
||||||
|
});
|
||||||
|
clearCache();
|
||||||
|
}
|
16
src/pages/404.tsx
Normal file
16
src/pages/404.tsx
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import { history } from '@umijs/max';
|
||||||
|
import { Button, Result } from 'antd';
|
||||||
|
import React from 'react';
|
||||||
|
const NoFoundPage: React.FC = () => (
|
||||||
|
<Result
|
||||||
|
status="404"
|
||||||
|
title="404"
|
||||||
|
subTitle={'抱歉,您访问的页面不存在。'}
|
||||||
|
extra={
|
||||||
|
<Button type="primary" onClick={() => history.push('/')}>
|
||||||
|
{'返回首页'}
|
||||||
|
</Button>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
export default NoFoundPage;
|
126
src/pages/AddChart/index.tsx
Normal file
126
src/pages/AddChart/index.tsx
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
import { genChartByAiUsingPost } from '@/services/hebi/chartController';
|
||||||
|
import { UploadOutlined } from '@ant-design/icons';
|
||||||
|
import {Button,Card,Col,Divider,Form,Input,message,Row,Select,Space,Spin,Upload,} from 'antd';
|
||||||
|
import TextArea from 'antd/es/input/TextArea';
|
||||||
|
import ReactECharts from 'echarts-for-react';
|
||||||
|
import React, { useState } from 'react';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加图表页面
|
||||||
|
* @constructor
|
||||||
|
*/
|
||||||
|
const AddChart: React.FC = () => {
|
||||||
|
const [chart, setChart] = useState<API.BiResponse>();
|
||||||
|
const [option, setOption] = useState<any>();
|
||||||
|
const [submitting, setSubmitting] = useState<boolean>(false);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 提交
|
||||||
|
* @param values
|
||||||
|
*/
|
||||||
|
const onFinish = async (values: any) => {
|
||||||
|
// 避免重复提交
|
||||||
|
if (submitting) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setSubmitting(true);
|
||||||
|
setChart(undefined);
|
||||||
|
setOption(undefined);
|
||||||
|
// 对接后端,上传数据
|
||||||
|
const params = {
|
||||||
|
...values,
|
||||||
|
file: undefined,
|
||||||
|
};
|
||||||
|
try {
|
||||||
|
const res = await genChartByAiUsingPost(params, {}, values.file.file.originFileObj);
|
||||||
|
if (!res?.data) {
|
||||||
|
message.error('分析失败');
|
||||||
|
} else {
|
||||||
|
message.success('分析成功');
|
||||||
|
const chartOption = JSON.parse(res.data.genChart ?? '');
|
||||||
|
if (!chartOption) {
|
||||||
|
throw new Error('图表代码解析错误');
|
||||||
|
} else {
|
||||||
|
setChart(res.data);
|
||||||
|
setOption(chartOption);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e: any) {
|
||||||
|
message.error('分析失败,' + e.message);
|
||||||
|
}
|
||||||
|
setSubmitting(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="add-chart">
|
||||||
|
<Row gutter={24}>
|
||||||
|
<Col span={12}>
|
||||||
|
<Card title="智能分析">
|
||||||
|
<Form
|
||||||
|
name="addChart"
|
||||||
|
labelAlign="left"
|
||||||
|
labelCol={{ span: 4 }}
|
||||||
|
wrapperCol={{ span: 16 }}
|
||||||
|
onFinish={onFinish}
|
||||||
|
initialValues={{}}
|
||||||
|
>
|
||||||
|
<Form.Item
|
||||||
|
name="goal"
|
||||||
|
label="分析目标"
|
||||||
|
rules={[{ required: true, message: '请输入分析目标' }]}
|
||||||
|
>
|
||||||
|
<TextArea placeholder="请输入你的分析需求,比如:分析网站用户的增长情况" />
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item name="name" label="图表名称">
|
||||||
|
<Input placeholder="请输入图表名称" />
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item name="chartType" label="图表类型">
|
||||||
|
<Select
|
||||||
|
options={[
|
||||||
|
{ value: '折线图', label: '折线图' },
|
||||||
|
{ value: '柱状图', label: '柱状图' },
|
||||||
|
{ value: '堆叠图', label: '堆叠图' },
|
||||||
|
{ value: '散点图', label: '散点图' },
|
||||||
|
{ value: '饼图', label: '饼图' },
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item name="file" label="原始数据">
|
||||||
|
{/* 上传文件限制数量 */}
|
||||||
|
<Upload name="file" maxCount={1}>
|
||||||
|
<Button icon={<UploadOutlined />}>上传 excel 文件</Button>
|
||||||
|
</Upload>
|
||||||
|
</Form.Item>
|
||||||
|
|
||||||
|
<Form.Item wrapperCol={{ span: 16, offset: 4 }}>
|
||||||
|
<Space>
|
||||||
|
<Button
|
||||||
|
type="primary"
|
||||||
|
htmlType="submit"
|
||||||
|
loading={submitting}
|
||||||
|
disabled={submitting}
|
||||||
|
>
|
||||||
|
提交
|
||||||
|
</Button>
|
||||||
|
<Button htmlType="reset">重置</Button>
|
||||||
|
</Space>
|
||||||
|
</Form.Item>
|
||||||
|
</Form>
|
||||||
|
</Card>
|
||||||
|
</Col>
|
||||||
|
<Col span={12}>
|
||||||
|
<Card title="可视化图表">
|
||||||
|
{option ? <ReactECharts option={option} /> : <div>请先在左侧进行提交</div>}
|
||||||
|
<Spin spinning={submitting} />
|
||||||
|
</Card>
|
||||||
|
<Divider />
|
||||||
|
<Card title="分析结论">
|
||||||
|
{chart?.genResult ?? <div>请先在左侧进行提交</div>}
|
||||||
|
<Spin spinning={submitting} />
|
||||||
|
</Card>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
export default AddChart;
|
98
src/pages/AddChartAsync/index.tsx
Normal file
98
src/pages/AddChartAsync/index.tsx
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
import { genChartByAiAsyncUsingPost } from '@/services/hebi/chartController';
|
||||||
|
import { UploadOutlined } from '@ant-design/icons';
|
||||||
|
import { Button, Card, Form, Input, message, Select, Space, Upload } from 'antd';
|
||||||
|
import { useForm } from 'antd/es/form/Form';
|
||||||
|
import TextArea from 'antd/es/input/TextArea';
|
||||||
|
import React, { useState } from 'react';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加图表(异步)页面
|
||||||
|
* @constructor
|
||||||
|
*/
|
||||||
|
const AddChartAsync: React.FC = () => {
|
||||||
|
const [form] = useForm();
|
||||||
|
const [submitting, setSubmitting] = useState<boolean>(false);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 提交
|
||||||
|
* @param values
|
||||||
|
*/
|
||||||
|
const onFinish = async (values: any) => {
|
||||||
|
// 避免重复提交
|
||||||
|
if (submitting) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setSubmitting(true);
|
||||||
|
// 对接后端,上传数据
|
||||||
|
const params = {
|
||||||
|
...values,
|
||||||
|
file: undefined,
|
||||||
|
};
|
||||||
|
try {
|
||||||
|
const res = await genChartByAiAsyncUsingPost(params, {}, values.file.file.originFileObj);
|
||||||
|
// const res = await genChartByAiAsyncMqUsingPOST(params, {}, values.file.file.originFileObj);
|
||||||
|
if (!res?.data) {
|
||||||
|
message.error('分析失败');
|
||||||
|
} else {
|
||||||
|
message.success('分析任务提交成功,稍后请在我的图表页面查看');
|
||||||
|
form.resetFields();
|
||||||
|
}
|
||||||
|
} catch (e: any) {
|
||||||
|
message.error('分析失败,' + e.message);
|
||||||
|
}
|
||||||
|
setSubmitting(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="add-chart-async">
|
||||||
|
<Card title="智能分析">
|
||||||
|
<Form
|
||||||
|
form={form}
|
||||||
|
name="addChart"
|
||||||
|
labelAlign="left"
|
||||||
|
labelCol={{ span: 4 }}
|
||||||
|
wrapperCol={{ span: 16 }}
|
||||||
|
onFinish={onFinish}
|
||||||
|
initialValues={{}}
|
||||||
|
>
|
||||||
|
<Form.Item
|
||||||
|
name="goal"
|
||||||
|
label="分析目标"
|
||||||
|
rules={[{ required: true, message: '请输入分析目标' }]}
|
||||||
|
>
|
||||||
|
<TextArea placeholder="请输入你的分析需求,比如:分析网站用户的增长情况" />
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item name="name" label="图表名称">
|
||||||
|
<Input placeholder="请输入图表名称" />
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item name="chartType" label="图表类型">
|
||||||
|
<Select
|
||||||
|
options={[
|
||||||
|
{ value: '折线图', label: '折线图' },
|
||||||
|
{ value: '柱状图', label: '柱状图' },
|
||||||
|
{ value: '堆叠图', label: '堆叠图' },
|
||||||
|
{ value: '饼图', label: '饼图' },
|
||||||
|
{ value: '雷达图', label: '雷达图' },
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item name="file" label="原始数据">
|
||||||
|
<Upload name="file" maxCount={1}>
|
||||||
|
<Button icon={<UploadOutlined />}>上传 CSV 文件</Button>
|
||||||
|
</Upload>
|
||||||
|
</Form.Item>
|
||||||
|
|
||||||
|
<Form.Item wrapperCol={{ span: 16, offset: 4 }}>
|
||||||
|
<Space>
|
||||||
|
<Button type="primary" htmlType="submit" loading={submitting} disabled={submitting}>
|
||||||
|
提交
|
||||||
|
</Button>
|
||||||
|
<Button htmlType="reset">重置</Button>
|
||||||
|
</Space>
|
||||||
|
</Form.Item>
|
||||||
|
</Form>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
export default AddChartAsync;
|
44
src/pages/Admin.tsx
Normal file
44
src/pages/Admin.tsx
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
import { HeartTwoTone, SmileTwoTone } from '@ant-design/icons';
|
||||||
|
import { PageContainer } from '@ant-design/pro-components';
|
||||||
|
import '@umijs/max';
|
||||||
|
import { Alert, Card, Typography } from 'antd';
|
||||||
|
import React from 'react';
|
||||||
|
const Admin: React.FC = () => {
|
||||||
|
return (
|
||||||
|
<PageContainer content={' 这个页面只有 admin 权限才能查看'}>
|
||||||
|
<Card>
|
||||||
|
<Alert
|
||||||
|
message={'更快更强的重型组件,已经发布。'}
|
||||||
|
type="success"
|
||||||
|
showIcon
|
||||||
|
banner
|
||||||
|
style={{
|
||||||
|
margin: -12,
|
||||||
|
marginBottom: 48,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Typography.Title
|
||||||
|
level={2}
|
||||||
|
style={{
|
||||||
|
textAlign: 'center',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<SmileTwoTone /> 基于AIGC的智能数据分析系统 <HeartTwoTone twoToneColor="#eb2f96" />
|
||||||
|
</Typography.Title>
|
||||||
|
</Card>
|
||||||
|
<p
|
||||||
|
style={{
|
||||||
|
textAlign: 'center',
|
||||||
|
marginTop: 24,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Want to add more pages? Please refer to{' '}
|
||||||
|
<a href="https://pro.ant.design/docs/block-cn" target="_blank" rel="noopener noreferrer">
|
||||||
|
use block
|
||||||
|
</a>
|
||||||
|
。
|
||||||
|
</p>
|
||||||
|
</PageContainer>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
export default Admin;
|
405
src/pages/Forum/index.tsx
Normal file
405
src/pages/Forum/index.tsx
Normal file
@ -0,0 +1,405 @@
|
|||||||
|
import {LikeFilled,LikeOutlined,MessageOutlined,PlusOutlined,SendOutlined,} from '@ant-design/icons';
|
||||||
|
import type { UploadFile, UploadProps } from 'antd';
|
||||||
|
import {Avatar,Button,Card,Comment,Divider,Form,Image,Input,List,message,Space,Tooltip,Upload} from 'antd';
|
||||||
|
import moment from 'moment';
|
||||||
|
import React, { useState } from 'react';
|
||||||
|
|
||||||
|
const { TextArea } = Input;
|
||||||
|
|
||||||
|
type CommentType = {
|
||||||
|
id: string;
|
||||||
|
author: string;
|
||||||
|
avatar: string;
|
||||||
|
content: string;
|
||||||
|
datetime: string;
|
||||||
|
likes: number;
|
||||||
|
liked: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
type PostType = {
|
||||||
|
id: string;
|
||||||
|
author: string;
|
||||||
|
avatar: string;
|
||||||
|
content: string;
|
||||||
|
images: string[];
|
||||||
|
datetime: string;
|
||||||
|
likes: number;
|
||||||
|
liked: boolean;
|
||||||
|
comments: CommentType[];
|
||||||
|
commentVisible: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
const Forum: React.FC = () => {
|
||||||
|
// 当前用户信息
|
||||||
|
const currentUser = {
|
||||||
|
name: '当前用户',
|
||||||
|
avatar: 'https://joeschmoe.io/api/v1/random',
|
||||||
|
};
|
||||||
|
|
||||||
|
// 帖子列表数据
|
||||||
|
const [posts, setPosts] = useState<PostType[]>([
|
||||||
|
{
|
||||||
|
id: '1',
|
||||||
|
author: '用户1',
|
||||||
|
avatar: 'https://joeschmoe.io/api/v1/1',
|
||||||
|
content: '这是一个示例帖子内容,欢迎大家讨论!',
|
||||||
|
images: ['https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png'],
|
||||||
|
datetime: '2023-05-01 10:00:00',
|
||||||
|
likes: 5,
|
||||||
|
liked: false,
|
||||||
|
comments: [
|
||||||
|
{
|
||||||
|
id: '1-1',
|
||||||
|
author: '用户2',
|
||||||
|
avatar: 'https://joeschmoe.io/api/v1/2',
|
||||||
|
content: '这个帖子很有意义!',
|
||||||
|
datetime: '2023-05-01 10:30:00',
|
||||||
|
likes: 2,
|
||||||
|
liked: false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
commentVisible: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '2',
|
||||||
|
author: '用户3',
|
||||||
|
avatar: 'https://joeschmoe.io/api/v1/3',
|
||||||
|
content: '分享一张有趣的图片',
|
||||||
|
images: [
|
||||||
|
'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',
|
||||||
|
'https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg',
|
||||||
|
],
|
||||||
|
datetime: '2023-05-02 15:00:00',
|
||||||
|
likes: 10,
|
||||||
|
liked: true,
|
||||||
|
comments: [],
|
||||||
|
commentVisible: false,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
// 新帖子内容
|
||||||
|
const [postContent, setPostContent] = useState('');
|
||||||
|
const [fileList, setFileList] = useState<UploadFile[]>([]);
|
||||||
|
const [previewOpen, setPreviewOpen] = useState(false);
|
||||||
|
const [previewImage, setPreviewImage] = useState('');
|
||||||
|
|
||||||
|
// 处理图片预览
|
||||||
|
const handlePreview = async (file: UploadFile) => {
|
||||||
|
if (!file.url && !file.preview) {
|
||||||
|
file.preview = URL.createObjectURL(file.originFileObj as any);
|
||||||
|
}
|
||||||
|
setPreviewImage(file.url || (file.preview as string));
|
||||||
|
setPreviewOpen(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 处理图片变化
|
||||||
|
const handleChange: UploadProps['onChange'] = ({ fileList: newFileList }) => {
|
||||||
|
setFileList(newFileList);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 上传按钮
|
||||||
|
const uploadButton = (
|
||||||
|
<div>
|
||||||
|
<PlusOutlined />
|
||||||
|
<div style={{ marginTop: 8 }}>上传图片</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
// 发布新帖子
|
||||||
|
const handlePostSubmit = () => {
|
||||||
|
if (!postContent.trim() && fileList.length === 0) {
|
||||||
|
message.warning('请填写内容或上传图片');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const newPost: PostType = {
|
||||||
|
id: Date.now().toString(),
|
||||||
|
author: currentUser.name,
|
||||||
|
avatar: currentUser.avatar,
|
||||||
|
content: postContent,
|
||||||
|
images: fileList.map((file) => file.url || (file.preview as string)),
|
||||||
|
datetime: moment().format('YYYY-MM-DD HH:mm:ss'),
|
||||||
|
likes: 0,
|
||||||
|
liked: false,
|
||||||
|
comments: [],
|
||||||
|
commentVisible: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
setPosts([newPost, ...posts]);
|
||||||
|
setPostContent('');
|
||||||
|
setFileList([]);
|
||||||
|
message.success('帖子发布成功');
|
||||||
|
};
|
||||||
|
|
||||||
|
// 点赞帖子
|
||||||
|
const handleLikePost = (postId: string) => {
|
||||||
|
setPosts(
|
||||||
|
posts.map((post) => {
|
||||||
|
if (post.id === postId) {
|
||||||
|
return {
|
||||||
|
...post,
|
||||||
|
likes: post.liked ? post.likes - 1 : post.likes + 1,
|
||||||
|
liked: !post.liked,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return post;
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 切换评论可见性
|
||||||
|
const toggleCommentVisible = (postId: string) => {
|
||||||
|
setPosts(
|
||||||
|
posts.map((post) => {
|
||||||
|
if (post.id === postId) {
|
||||||
|
return {
|
||||||
|
...post,
|
||||||
|
commentVisible: !post.commentVisible,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return post;
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 添加评论
|
||||||
|
const handleAddComment = (postId: string, content: string) => {
|
||||||
|
if (!content.trim()) {
|
||||||
|
message.warning('评论内容不能为空');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const newComment: CommentType = {
|
||||||
|
id: `${postId}-${Date.now()}`,
|
||||||
|
author: currentUser.name,
|
||||||
|
avatar: currentUser.avatar,
|
||||||
|
content: content,
|
||||||
|
datetime: moment().format('YYYY-MM-DD HH:mm:ss'),
|
||||||
|
likes: 0,
|
||||||
|
liked: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
setPosts(
|
||||||
|
posts.map((post) => {
|
||||||
|
if (post.id === postId) {
|
||||||
|
return {
|
||||||
|
...post,
|
||||||
|
comments: [...post.comments, newComment],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return post;
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 点赞评论
|
||||||
|
const handleLikeComment = (postId: string, commentId: string) => {
|
||||||
|
setPosts(
|
||||||
|
posts.map((post) => {
|
||||||
|
if (post.id === postId) {
|
||||||
|
return {
|
||||||
|
...post,
|
||||||
|
comments: post.comments.map((comment) => {
|
||||||
|
if (comment.id === commentId) {
|
||||||
|
return {
|
||||||
|
...comment,
|
||||||
|
likes: comment.liked ? comment.likes - 1 : comment.likes + 1,
|
||||||
|
liked: !comment.liked,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return comment;
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return post;
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div style={{ maxWidth: 800, margin: '0 auto', padding: 20 }}>
|
||||||
|
{/* 发布新帖子区域 */}
|
||||||
|
<Card title="发布新帖子" style={{ marginBottom: 20 }}>
|
||||||
|
<Form.Item>
|
||||||
|
<TextArea
|
||||||
|
rows={4}
|
||||||
|
value={postContent}
|
||||||
|
onChange={(e) => setPostContent(e.target.value)}
|
||||||
|
placeholder="分享你的想法..."
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
|
|
||||||
|
<Form.Item>
|
||||||
|
<Upload
|
||||||
|
listType="picture-card"
|
||||||
|
fileList={fileList}
|
||||||
|
onPreview={handlePreview}
|
||||||
|
onChange={handleChange}
|
||||||
|
beforeUpload={() => false} // 阻止自动上传
|
||||||
|
multiple
|
||||||
|
>
|
||||||
|
{fileList.length >= 4 ? null : uploadButton}
|
||||||
|
</Upload>
|
||||||
|
</Form.Item>
|
||||||
|
|
||||||
|
<Form.Item>
|
||||||
|
<Button type="primary" onClick={handlePostSubmit} icon={<SendOutlined />}>
|
||||||
|
发布
|
||||||
|
</Button>
|
||||||
|
</Form.Item>
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
{/* 图片预览 */}
|
||||||
|
{previewImage && (
|
||||||
|
<Image
|
||||||
|
wrapperStyle={{ display: 'none' }}
|
||||||
|
preview={{
|
||||||
|
visible: previewOpen,
|
||||||
|
onVisibleChange: (visible) => setPreviewOpen(visible),
|
||||||
|
afterOpenChange: (visible) => !visible && setPreviewImage(''),
|
||||||
|
}}
|
||||||
|
src={previewImage}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* 帖子列表 */}
|
||||||
|
<List
|
||||||
|
itemLayout="vertical"
|
||||||
|
size="large"
|
||||||
|
dataSource={posts}
|
||||||
|
renderItem={(post) => (
|
||||||
|
<Card style={{ marginBottom: 20 }}>
|
||||||
|
<Comment
|
||||||
|
author={<a>{post.author}</a>}
|
||||||
|
avatar={<Avatar src={post.avatar} alt={post.author} />}
|
||||||
|
content={<p>{post.content}</p>}
|
||||||
|
datetime={
|
||||||
|
<Tooltip title={post.datetime}>
|
||||||
|
<span>{moment(post.datetime).fromNow()}</span>
|
||||||
|
</Tooltip>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* 帖子图片 */}
|
||||||
|
{post.images.length > 0 && (
|
||||||
|
<div style={{ marginTop: 16 }}>
|
||||||
|
<Image.PreviewGroup>
|
||||||
|
<Space wrap>
|
||||||
|
{post.images.map((img, index) => (
|
||||||
|
<Image
|
||||||
|
key={index}
|
||||||
|
width={150}
|
||||||
|
height={150}
|
||||||
|
src={img}
|
||||||
|
style={{ objectFit: 'cover' }}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</Space>
|
||||||
|
</Image.PreviewGroup>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* 帖子操作 */}
|
||||||
|
<div style={{ marginTop: 16 }}>
|
||||||
|
<Space>
|
||||||
|
<span onClick={() => handleLikePost(post.id)} style={{ cursor: 'pointer' }}>
|
||||||
|
{post.liked ? <LikeFilled style={{ color: '#1890ff' }} /> : <LikeOutlined />}
|
||||||
|
<span style={{ paddingLeft: 8 }}>{post.likes}</span>
|
||||||
|
</span>
|
||||||
|
<span onClick={() => toggleCommentVisible(post.id)} style={{ cursor: 'pointer' }}>
|
||||||
|
<MessageOutlined />
|
||||||
|
<span style={{ paddingLeft: 8 }}>{post.comments.length}</span>
|
||||||
|
</span>
|
||||||
|
</Space>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* 评论区域 */}
|
||||||
|
{post.commentVisible && (
|
||||||
|
<div style={{ marginTop: 16 }}>
|
||||||
|
<Divider orientation="left" plain>
|
||||||
|
评论
|
||||||
|
</Divider>
|
||||||
|
|
||||||
|
{/* 评论列表 */}
|
||||||
|
<List
|
||||||
|
dataSource={post.comments}
|
||||||
|
renderItem={(comment) => (
|
||||||
|
<Comment
|
||||||
|
author={<a>{comment.author}</a>}
|
||||||
|
avatar={<Avatar src={comment.avatar} alt={comment.author} />}
|
||||||
|
content={<p>{comment.content}</p>}
|
||||||
|
datetime={
|
||||||
|
<Tooltip title={comment.datetime}>
|
||||||
|
<span>{moment(comment.datetime).fromNow()}</span>
|
||||||
|
</Tooltip>
|
||||||
|
}
|
||||||
|
actions={[
|
||||||
|
<span
|
||||||
|
key="comment-like"
|
||||||
|
onClick={() => handleLikeComment(post.id, comment.id)}
|
||||||
|
style={{ cursor: 'pointer' }}
|
||||||
|
>
|
||||||
|
{comment.liked ? (
|
||||||
|
<LikeFilled style={{ color: '#1890ff' }} />
|
||||||
|
) : (
|
||||||
|
<LikeOutlined />
|
||||||
|
)}
|
||||||
|
<span style={{ paddingLeft: 8 }}>{comment.likes}</span>
|
||||||
|
</span>,
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* 添加评论 */}
|
||||||
|
<Comment
|
||||||
|
avatar={<Avatar src={currentUser.avatar} alt={currentUser.name} />}
|
||||||
|
content={
|
||||||
|
<Editor
|
||||||
|
onSubmit={(content) => handleAddComment(post.id, content)}
|
||||||
|
placeholder="写下你的评论..."
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</Card>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 评论编辑器组件
|
||||||
|
const Editor = ({
|
||||||
|
onSubmit,
|
||||||
|
placeholder,
|
||||||
|
}: {
|
||||||
|
onSubmit: (content: string) => void;
|
||||||
|
placeholder: string;
|
||||||
|
}) => {
|
||||||
|
const [value, setValue] = useState('');
|
||||||
|
|
||||||
|
const handleSubmit = () => {
|
||||||
|
onSubmit(value);
|
||||||
|
setValue('');
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<TextArea
|
||||||
|
rows={2}
|
||||||
|
onChange={(e) => setValue(e.target.value)}
|
||||||
|
value={value}
|
||||||
|
placeholder={placeholder}
|
||||||
|
/>
|
||||||
|
<Form.Item style={{ marginTop: 16, marginBottom: 0 }}>
|
||||||
|
<Button htmlType="submit" onClick={handleSubmit} type="primary" disabled={!value.trim()}>
|
||||||
|
发表评论
|
||||||
|
</Button>
|
||||||
|
</Form.Item>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Forum;
|
154
src/pages/MyChart/index.tsx
Normal file
154
src/pages/MyChart/index.tsx
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
import { listChartByPageUsingPost } from '@/services/hebi/chartController';
|
||||||
|
import { useModel } from '@@/exports';
|
||||||
|
import { Avatar, Card, Input, List, message, Result } from 'antd';
|
||||||
|
import ReactECharts from 'echarts-for-react';
|
||||||
|
import React, { useEffect, useState } from 'react';
|
||||||
|
const { Search } = Input;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加图表页面
|
||||||
|
* @constructor
|
||||||
|
*/
|
||||||
|
const MyChartPage: React.FC = () => {
|
||||||
|
const initSearchParams = {
|
||||||
|
current: 1,
|
||||||
|
pageSize: 6,
|
||||||
|
sortField:'createTime',
|
||||||
|
sortOrder:'desc',
|
||||||
|
};
|
||||||
|
|
||||||
|
const [searchParams, setSearchParams] = useState<API.ChartQueryRequest>({
|
||||||
|
...initSearchParams,
|
||||||
|
});
|
||||||
|
//获取用户头像可以从初始化状态中获取
|
||||||
|
const { initialState } = useModel('@@initialState');
|
||||||
|
const { currentUser } = initialState ?? {};
|
||||||
|
const [chartList, setChartList] = useState<API.Chart[]>();
|
||||||
|
const [total, setTotal] = useState<number>(0);
|
||||||
|
const [loading, setLoading] = useState<boolean>(true);
|
||||||
|
|
||||||
|
const loadData = async () => {
|
||||||
|
setLoading(true);
|
||||||
|
try {
|
||||||
|
const res = await listChartByPageUsingPost(searchParams);
|
||||||
|
if (res.data) {
|
||||||
|
setChartList(res.data.records ?? []);
|
||||||
|
setTotal(res.data.total ?? 0);
|
||||||
|
// 隐藏图标的tittle
|
||||||
|
if (res.data.records) {
|
||||||
|
res.data.records.forEach((data) => {
|
||||||
|
if(data.status==="succeed"){
|
||||||
|
const chartOption = JSON.parse(data.genChart ?? '{}');
|
||||||
|
chartOption.title = undefined;
|
||||||
|
data.genChart = JSON.stringify(chartOption);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
message.error('获取我的图表失败');
|
||||||
|
}
|
||||||
|
} catch (e: any) {
|
||||||
|
message.error('获取我的图表失败' + e.message);
|
||||||
|
}
|
||||||
|
setLoading(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 钩子函数
|
||||||
|
useEffect(() => {
|
||||||
|
loadData();
|
||||||
|
}, [searchParams]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="my-chart-page">
|
||||||
|
<div>
|
||||||
|
<Search
|
||||||
|
placeholder="请输入图表名称"
|
||||||
|
loading={loading}
|
||||||
|
enterButton
|
||||||
|
onSearch={(value) => {
|
||||||
|
setSearchParams({
|
||||||
|
...initSearchParams,
|
||||||
|
name: value,
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="margin-16"></div>
|
||||||
|
<List
|
||||||
|
itemLayout="vertical"
|
||||||
|
grid={{
|
||||||
|
gutter: 16,
|
||||||
|
xs: 1,
|
||||||
|
sm: 1,
|
||||||
|
md: 1,
|
||||||
|
lg: 2,
|
||||||
|
xl: 2,
|
||||||
|
xxl: 2,
|
||||||
|
}}
|
||||||
|
pagination={{
|
||||||
|
onChange: (page, pageSize) => {
|
||||||
|
setSearchParams({
|
||||||
|
...searchParams,
|
||||||
|
current: page,
|
||||||
|
pageSize,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
current: searchParams.current,
|
||||||
|
pageSize: searchParams.pageSize,
|
||||||
|
total: total,
|
||||||
|
}}
|
||||||
|
loading={loading}
|
||||||
|
dataSource={chartList}
|
||||||
|
renderItem={(item) => (
|
||||||
|
<List.Item key={item.id}>
|
||||||
|
<Card style={{ width: '100%' }}>
|
||||||
|
<List.Item.Meta
|
||||||
|
// 若第一个操作数为 false 或者可以转换为 false 的值(如 null、undefined、0、''、NaN 等),则整个表达式的结果就是这个操作数,并且不会再计算第二个操作数。
|
||||||
|
// 若第一个操作数为 true 或者可以转换为 true 的值,那么整个表达式的结果取决于第二个操作数,也就是会返回第二个操作数的值。
|
||||||
|
avatar={<Avatar src={currentUser && currentUser.userAvatar} />}
|
||||||
|
title={item.name}
|
||||||
|
description={item.chartType ? '图表类型:' + item.chartType : undefined}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<>
|
||||||
|
{item.status === 'wait' && (
|
||||||
|
<>
|
||||||
|
<Result
|
||||||
|
status="warning"
|
||||||
|
title="图表待生成"
|
||||||
|
subTitle={item.execMessage ?? '当前图表生成队列繁忙,请耐心你等候'}
|
||||||
|
></Result>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
{item.status === 'running' && (
|
||||||
|
<>
|
||||||
|
<Result status="info" title="图表生成中" subTitle={item.execMessage}></Result>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
{item.status === 'succeed' && (
|
||||||
|
<>
|
||||||
|
{'分析目标:' + item.goal}
|
||||||
|
<ReactECharts option={JSON.parse(item.genChart ?? '{}')} />
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
{item.status === 'failed' && (
|
||||||
|
<>
|
||||||
|
<Result
|
||||||
|
status="error"
|
||||||
|
title="图表生成失败"
|
||||||
|
subTitle={item.execMessage}
|
||||||
|
></Result>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
|
||||||
|
</Card>
|
||||||
|
</List.Item>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
总数:
|
||||||
|
{total}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
export default MyChartPage;
|
203
src/pages/User/Login/index.tsx
Normal file
203
src/pages/User/Login/index.tsx
Normal file
@ -0,0 +1,203 @@
|
|||||||
|
import { Footer } from '@/components';
|
||||||
|
import {
|
||||||
|
LockOutlined,
|
||||||
|
UserOutlined,
|
||||||
|
} from '@ant-design/icons';
|
||||||
|
import {
|
||||||
|
LoginForm,
|
||||||
|
ProFormText,
|
||||||
|
} from '@ant-design/pro-components';
|
||||||
|
import { Helmet, history, Link, useModel } from '@umijs/max';
|
||||||
|
import { message, Tabs } from 'antd';
|
||||||
|
import { createStyles } from 'antd-style';
|
||||||
|
import React, { useState,useEffect } from 'react';
|
||||||
|
import { flushSync } from 'react-dom';
|
||||||
|
import Settings from '../../../../config/defaultSettings';
|
||||||
|
import { listChartByPageUsingPost } from '@/services/hebi/chartController';
|
||||||
|
import { getLoginUserUsingGet, userLoginUsingPost } from '@/services/hebi/userController';
|
||||||
|
|
||||||
|
|
||||||
|
const useStyles = createStyles(({ token }) => {
|
||||||
|
return {
|
||||||
|
action: {
|
||||||
|
marginLeft: '8px',
|
||||||
|
color: 'rgba(0, 0, 0, 0.2)',
|
||||||
|
fontSize: '24px',
|
||||||
|
verticalAlign: 'middle',
|
||||||
|
cursor: 'pointer',
|
||||||
|
transition: 'color 0.3s',
|
||||||
|
'&:hover': {
|
||||||
|
color: token.colorPrimaryActive,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
lang: {
|
||||||
|
width: 42,
|
||||||
|
height: 42,
|
||||||
|
lineHeight: '42px',
|
||||||
|
position: 'fixed',
|
||||||
|
right: 16,
|
||||||
|
borderRadius: token.borderRadius,
|
||||||
|
':hover': {
|
||||||
|
backgroundColor: token.colorBgTextHover,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
container: {
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'column',
|
||||||
|
height: '100vh',
|
||||||
|
overflow: 'auto',
|
||||||
|
backgroundImage:
|
||||||
|
"url('https://mdn.alipayobjects.com/yuyan_qk0oxh/afts/img/V-_oS6r-i7wAAAAAAAAAAAAAFl94AQBr')",
|
||||||
|
backgroundSize: '100% 100%',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
const Login: React.FC = () => {
|
||||||
|
const [type, setType] = useState<string>('account');
|
||||||
|
const { setInitialState } = useModel('@@initialState');
|
||||||
|
const { styles } = useStyles();
|
||||||
|
|
||||||
|
//获取用户的登录信息
|
||||||
|
const fetchUserInfo = async () => {
|
||||||
|
const userInfo = await getLoginUserUsingGet();
|
||||||
|
if (userInfo) {
|
||||||
|
flushSync(() => {
|
||||||
|
setInitialState((s) => ({
|
||||||
|
...s,
|
||||||
|
currentUser: userInfo,
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//测试
|
||||||
|
useEffect(()=>{
|
||||||
|
listChartByPageUsingPost({}).then(res=>{
|
||||||
|
console.error('res:',res)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const handleSubmit = async (values: API.UserLoginRequest) => {
|
||||||
|
try {
|
||||||
|
// 登录
|
||||||
|
const res = await userLoginUsingPost(values);
|
||||||
|
if (res.code === 0) {
|
||||||
|
const defaultLoginSuccessMessage = '登录成功!';
|
||||||
|
message.success(defaultLoginSuccessMessage);
|
||||||
|
await fetchUserInfo();
|
||||||
|
const urlParams = new URL(window.location.href).searchParams;
|
||||||
|
history.push(urlParams.get('redirect') || '/');
|
||||||
|
return;
|
||||||
|
}else{
|
||||||
|
message.error(res.message);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
const defaultLoginFailureMessage = '登录失败,请重试!';
|
||||||
|
console.log(error);
|
||||||
|
message.error(defaultLoginFailureMessage);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
//登录页面
|
||||||
|
<div className={styles.container}>
|
||||||
|
<Helmet>
|
||||||
|
<title>
|
||||||
|
{'登录'}- {Settings.title}
|
||||||
|
</title>
|
||||||
|
</Helmet>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
flex: '1',
|
||||||
|
padding: '32px 0',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<LoginForm
|
||||||
|
contentStyle={{
|
||||||
|
minWidth: 280,
|
||||||
|
maxWidth: '75vw',
|
||||||
|
}}
|
||||||
|
logo={<img alt="logo" src="/logo.svg" />}
|
||||||
|
title="基于AIGC的智能数据分析系统"
|
||||||
|
subTitle={'本系统助力于让数据分析变得简单高效'}
|
||||||
|
onFinish={async (values) => {
|
||||||
|
await handleSubmit(values as API.UserLoginRequest);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Tabs
|
||||||
|
activeKey={type}
|
||||||
|
onChange={setType}
|
||||||
|
centered
|
||||||
|
items={[
|
||||||
|
{
|
||||||
|
key: 'account',
|
||||||
|
label: '登录',
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{type === 'account' && (
|
||||||
|
<>
|
||||||
|
<ProFormText
|
||||||
|
name="userAccount"
|
||||||
|
fieldProps={{
|
||||||
|
size: 'large',
|
||||||
|
prefix: <UserOutlined />,
|
||||||
|
}}
|
||||||
|
placeholder={'请输入用户名'}
|
||||||
|
rules={[
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: '用户名是必填项!',
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
<ProFormText.Password
|
||||||
|
name="userPassword"
|
||||||
|
fieldProps={{
|
||||||
|
size: 'large',
|
||||||
|
prefix: <LockOutlined />,
|
||||||
|
}}
|
||||||
|
placeholder={'请输入密码'}
|
||||||
|
rules={[
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: '密码是必填项!',
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
marginBottom: 12,
|
||||||
|
display: 'flex',
|
||||||
|
// 元素靠右排列
|
||||||
|
justifyContent: 'flex-end',
|
||||||
|
// 设置元素之间的间距
|
||||||
|
gap: 16,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
|
||||||
|
<Link
|
||||||
|
to="/user/register"
|
||||||
|
>
|
||||||
|
注册
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
</LoginForm>
|
||||||
|
</div>
|
||||||
|
<Footer />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
export default Login;
|
185
src/pages/User/Register/index.tsx
Normal file
185
src/pages/User/Register/index.tsx
Normal file
@ -0,0 +1,185 @@
|
|||||||
|
import { Footer } from '@/components';
|
||||||
|
import { userRegisterUsingPost } from '@/services/hebi/userController';
|
||||||
|
import { LockOutlined, PictureOutlined, UserOutlined } from '@ant-design/icons';
|
||||||
|
import { ProForm, ProFormText } from '@ant-design/pro-components';
|
||||||
|
import { Helmet, history, Link } from '@umijs/max';
|
||||||
|
import { Avatar, Card, Form, message, Typography, Upload } from 'antd';
|
||||||
|
import { createStyles } from 'antd-style';
|
||||||
|
import React, { useState } from 'react';
|
||||||
|
import Settings from '../../../../config/defaultSettings';
|
||||||
|
|
||||||
|
const { Title } = Typography;
|
||||||
|
|
||||||
|
const useStyles = createStyles(({ token }) => {
|
||||||
|
return {
|
||||||
|
container: {
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'column',
|
||||||
|
height: '100vh',
|
||||||
|
overflow: 'auto',
|
||||||
|
backgroundImage:
|
||||||
|
"url('https://mdn.alipayobjects.com/yuyan_qk0oxh/afts/img/V-_oS6r-i7wAAAAAAAAAAAAAFl94AQBr')",
|
||||||
|
backgroundSize: '100% 100%',
|
||||||
|
},
|
||||||
|
card: {
|
||||||
|
minWidth: 320,
|
||||||
|
maxWidth: '75vw',
|
||||||
|
padding: token.paddingLG,
|
||||||
|
background: 'transparent',
|
||||||
|
border: 'none',
|
||||||
|
boxShadow: 'none',
|
||||||
|
},
|
||||||
|
header: {
|
||||||
|
textAlign: 'center',
|
||||||
|
marginBottom: 24,
|
||||||
|
display: 'flex',
|
||||||
|
justifyContent: 'center',
|
||||||
|
alignItems: 'center',
|
||||||
|
gap: '16px',
|
||||||
|
},
|
||||||
|
loginLink: {
|
||||||
|
display: 'block',
|
||||||
|
textAlign: 'center',
|
||||||
|
marginBottom: 24,
|
||||||
|
},
|
||||||
|
avatarUploader: {
|
||||||
|
display: 'flex',
|
||||||
|
justifyContent: 'center',
|
||||||
|
marginBottom: 24,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const Register: React.FC = () => {
|
||||||
|
const { styles } = useStyles();
|
||||||
|
const [avatarUrl, setAvatarUrl] = useState<string>();
|
||||||
|
const [form] = Form.useForm();
|
||||||
|
|
||||||
|
const handleSubmit = async (values: Record<string, any>) => {
|
||||||
|
try {
|
||||||
|
if (values.userPassword !== values.checkPassword) {
|
||||||
|
message.error('两次输入的密码不一致!');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const res = await userRegisterUsingPost({ ...values, userAvatar: avatarUrl });
|
||||||
|
if (res.code === 0) {
|
||||||
|
message.success('注册成功!');
|
||||||
|
history.push('/user/login');
|
||||||
|
} else {
|
||||||
|
message.error(res.message);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
message.error('注册失败,请重试!');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const uploadButton = (
|
||||||
|
<div>
|
||||||
|
<PictureOutlined />
|
||||||
|
<div style={{ marginTop: 8 }}>上传头像</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={styles.container}>
|
||||||
|
<Helmet>
|
||||||
|
<title>{'注册'} - {Settings.title}</title>
|
||||||
|
</Helmet>
|
||||||
|
|
||||||
|
<div style={{ flex: '1', padding: '32px 0', display: 'flex', justifyContent: 'center', alignItems: 'center' }}>
|
||||||
|
<Card className={styles.card}>
|
||||||
|
<div className={styles.header}>
|
||||||
|
<img alt="logo" src="/logo.svg" style={{ height: 44 }} />
|
||||||
|
<div>
|
||||||
|
<Title level={3} style={{ margin: 0 }}>基于AIGC的智能数据分析系统</Title>
|
||||||
|
<div style={{ color: 'rgba(0,0,0,.45)' }}>本系统助力于让数据分析变得简单高效</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Link to="/user/login" className={styles.loginLink}>已有账号?立即登录</Link>
|
||||||
|
|
||||||
|
<ProForm
|
||||||
|
form={form}
|
||||||
|
onFinish={handleSubmit}
|
||||||
|
submitter={{
|
||||||
|
searchConfig: { submitText: '注册' },
|
||||||
|
render: (_, dom) => dom.pop(),
|
||||||
|
submitButtonProps: {
|
||||||
|
size: 'large',
|
||||||
|
style: { width: '100%' },
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<ProForm.Item
|
||||||
|
name="userAvatar"
|
||||||
|
rules={[{ required: true, message: '请上传头像' }]}
|
||||||
|
className={styles.avatarUploader}
|
||||||
|
>
|
||||||
|
<Upload
|
||||||
|
name="avatar"
|
||||||
|
listType="picture-card"
|
||||||
|
showUploadList={false}
|
||||||
|
action="https://www.mocky.io/v2/5cc8019d300000980a055e76"
|
||||||
|
onChange={(info) => {
|
||||||
|
if (info.file.status === 'done') {
|
||||||
|
setAvatarUrl(info.file.response.url);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{avatarUrl ? <Avatar src={avatarUrl} size={64} /> : uploadButton}
|
||||||
|
</Upload>
|
||||||
|
</ProForm.Item>
|
||||||
|
|
||||||
|
<ProFormText
|
||||||
|
name="userAccount"
|
||||||
|
fieldProps={{ size: 'large', prefix: <UserOutlined /> }}
|
||||||
|
placeholder="请输入账号"
|
||||||
|
rules={[
|
||||||
|
{ required: true, message: '账号是必填项!' },
|
||||||
|
{ min: 4, message: '账号长度不能小于4位' },
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<ProFormText
|
||||||
|
name="userName"
|
||||||
|
fieldProps={{ size: 'large', prefix: <UserOutlined /> }}
|
||||||
|
placeholder="请输入用户名"
|
||||||
|
rules={[{ required: true, message: '用户名是必填项!' }]}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<ProFormText.Password
|
||||||
|
name="userPassword"
|
||||||
|
fieldProps={{ size: 'large', prefix: <LockOutlined /> }}
|
||||||
|
placeholder="请输入密码"
|
||||||
|
rules={[
|
||||||
|
{ required: true, message: '密码是必填项!' },
|
||||||
|
{ min: 8, message: '密码长度不能小于8位' },
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<ProFormText.Password
|
||||||
|
name="checkPassword"
|
||||||
|
fieldProps={{ size: 'large', prefix: <LockOutlined /> }}
|
||||||
|
placeholder="请确认密码"
|
||||||
|
rules={[
|
||||||
|
{ required: true, message: '请确认密码!' },
|
||||||
|
({ getFieldValue }) => ({
|
||||||
|
validator(_, value) {
|
||||||
|
if (!value || getFieldValue('userPassword') === value) {
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error('两次输入的密码不一致!'));
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
</ProForm>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
<Footer />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Register;
|
164
src/pages/Welcome.tsx
Normal file
164
src/pages/Welcome.tsx
Normal file
@ -0,0 +1,164 @@
|
|||||||
|
import { PageContainer } from '@ant-design/pro-components';
|
||||||
|
import { useModel } from '@umijs/max';
|
||||||
|
import { Card, theme } from 'antd';
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 每个单独的卡片,为了复用样式抽成了组件
|
||||||
|
* @param param0
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
const InfoCard: React.FC<{
|
||||||
|
title: string;
|
||||||
|
index: number;
|
||||||
|
desc: string;
|
||||||
|
href: string;
|
||||||
|
}> = ({ title, href, index, desc }) => {
|
||||||
|
const { useToken } = theme;
|
||||||
|
|
||||||
|
const { token } = useToken();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
backgroundColor: token.colorBgContainer,
|
||||||
|
boxShadow: token.boxShadow,
|
||||||
|
borderRadius: '8px',
|
||||||
|
fontSize: '14px',
|
||||||
|
color: token.colorTextSecondary,
|
||||||
|
lineHeight: '22px',
|
||||||
|
padding: '16px 19px',
|
||||||
|
minWidth: '220px',
|
||||||
|
flex: 1,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: 'flex',
|
||||||
|
gap: '4px',
|
||||||
|
alignItems: 'center',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
width: 48,
|
||||||
|
height: 48,
|
||||||
|
lineHeight: '22px',
|
||||||
|
backgroundSize: '100%',
|
||||||
|
textAlign: 'center',
|
||||||
|
padding: '8px 16px 16px 12px',
|
||||||
|
color: '#FFF',
|
||||||
|
fontWeight: 'bold',
|
||||||
|
backgroundImage:
|
||||||
|
"url('https://gw.alipayobjects.com/zos/bmw-prod/daaf8d50-8e6d-4251-905d-676a24ddfa12.svg')",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{index}
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
fontSize: '16px',
|
||||||
|
color: token.colorText,
|
||||||
|
paddingBottom: 8,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{title}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
fontSize: '14px',
|
||||||
|
color: token.colorTextSecondary,
|
||||||
|
textAlign: 'justify',
|
||||||
|
lineHeight: '22px',
|
||||||
|
marginBottom: 8,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{desc}
|
||||||
|
</div>
|
||||||
|
<a href={href} target="_blank" rel="noreferrer">
|
||||||
|
了解更多 {'>'}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const Welcome: React.FC = () => {
|
||||||
|
const { token } = theme.useToken();
|
||||||
|
const { initialState } = useModel('@@initialState');
|
||||||
|
return (
|
||||||
|
<PageContainer>
|
||||||
|
<Card
|
||||||
|
style={{
|
||||||
|
borderRadius: 8,
|
||||||
|
}}
|
||||||
|
bodyStyle={{
|
||||||
|
backgroundImage:
|
||||||
|
initialState?.settings?.navTheme === 'realDark'
|
||||||
|
? 'background-image: linear-gradient(75deg, #1A1B1F 0%, #191C1F 100%)'
|
||||||
|
: 'background-image: linear-gradient(75deg, #FBFDFF 0%, #F5F7FF 100%)',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
backgroundPosition: '100% -30%',
|
||||||
|
backgroundRepeat: 'no-repeat',
|
||||||
|
backgroundSize: '274px auto',
|
||||||
|
backgroundImage:
|
||||||
|
"url('https://gw.alipayobjects.com/mdn/rms_a9745b/afts/img/A*BuFmQqsB2iAAAAAAAAAAAAAAARQnAQ')",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
fontSize: '20px',
|
||||||
|
color: token.colorTextHeading,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
欢迎使用 基于AIGC的智能数据分析系统
|
||||||
|
</div>
|
||||||
|
<p
|
||||||
|
style={{
|
||||||
|
fontSize: '14px',
|
||||||
|
color: token.colorTextSecondary,
|
||||||
|
lineHeight: '22px',
|
||||||
|
marginTop: 16,
|
||||||
|
marginBottom: 32,
|
||||||
|
width: '65%',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
基于AIGC的智能数据分析系统 是一个整合了 umi,Ant Design 和 ProComponents
|
||||||
|
的脚手架方案。致力于在设计规范和基础组件的基础上,继续向上构建,提炼出典型模板/业务组件/配套设计资源,进一步提升企业级中后台产品设计研发过程中的『用户』和『设计者』的体验。
|
||||||
|
</p>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: 'flex',
|
||||||
|
flexWrap: 'wrap',
|
||||||
|
gap: 16,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<InfoCard
|
||||||
|
index={1}
|
||||||
|
href="https://umijs.org/docs/introduce/introduce"
|
||||||
|
title="了解 umi"
|
||||||
|
desc="umi 是一个可扩展的企业级前端应用框架,umi 以路由为基础的,同时支持配置式路由和约定式路由,保证路由的功能完备,并以此进行功能扩展。"
|
||||||
|
/>
|
||||||
|
<InfoCard
|
||||||
|
index={2}
|
||||||
|
title="了解 基于AIGC的智能数据分析系统"
|
||||||
|
href="https://ant.design"
|
||||||
|
desc="antd 是基于 基于AIGC的智能数据分析系统 设计体系的 React UI 组件库,主要用于研发企业级中后台产品。"
|
||||||
|
/>
|
||||||
|
<InfoCard
|
||||||
|
index={3}
|
||||||
|
title="了解 Pro Components"
|
||||||
|
href="https://procomponents.ant.design"
|
||||||
|
desc="ProComponents 是一个基于 基于AIGC的智能数据分析系统 做了更高抽象的模板组件,以 一个组件就是一个页面为开发理念,为中后台开发带来更好的体验。"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
</PageContainer>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Welcome;
|
110
src/requestErrorConfig.ts
Normal file
110
src/requestErrorConfig.ts
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
import type { RequestOptions } from '@@/plugin-request/request';
|
||||||
|
import type { RequestConfig } from '@umijs/max';
|
||||||
|
import { message, notification } from 'antd';
|
||||||
|
|
||||||
|
// 错误处理方案: 错误类型
|
||||||
|
enum ErrorShowType {
|
||||||
|
SILENT = 0,
|
||||||
|
WARN_MESSAGE = 1,
|
||||||
|
ERROR_MESSAGE = 2,
|
||||||
|
NOTIFICATION = 3,
|
||||||
|
REDIRECT = 9,
|
||||||
|
}
|
||||||
|
// 与后端约定的响应数据格式
|
||||||
|
interface ResponseStructure {
|
||||||
|
success: boolean;
|
||||||
|
data: any;
|
||||||
|
errorCode?: number;
|
||||||
|
errorMessage?: string;
|
||||||
|
showType?: ErrorShowType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name 错误处理
|
||||||
|
* pro 自带的错误处理, 可以在这里做自己的改动
|
||||||
|
* @doc https://umijs.org/docs/max/request#配置
|
||||||
|
*/
|
||||||
|
export const errorConfig: RequestConfig = {
|
||||||
|
// 错误处理: umi@3 的错误处理方案。
|
||||||
|
errorConfig: {
|
||||||
|
// 错误抛出
|
||||||
|
errorThrower: (res) => {
|
||||||
|
const { success, data, errorCode, errorMessage, showType } =
|
||||||
|
res as unknown as ResponseStructure;
|
||||||
|
if (!success) {
|
||||||
|
const error: any = new Error(errorMessage);
|
||||||
|
error.name = 'BizError';
|
||||||
|
error.info = { errorCode, errorMessage, showType, data };
|
||||||
|
throw error; // 抛出自制的错误
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 错误接收及处理
|
||||||
|
errorHandler: (error: any, opts: any) => {
|
||||||
|
if (opts?.skipErrorHandler) throw error;
|
||||||
|
// 我们的 errorThrower 抛出的错误。
|
||||||
|
if (error.name === 'BizError') {
|
||||||
|
const errorInfo: ResponseStructure | undefined = error.info;
|
||||||
|
if (errorInfo) {
|
||||||
|
const { errorMessage, errorCode } = errorInfo;
|
||||||
|
switch (errorInfo.showType) {
|
||||||
|
case ErrorShowType.SILENT:
|
||||||
|
// do nothing
|
||||||
|
break;
|
||||||
|
case ErrorShowType.WARN_MESSAGE:
|
||||||
|
message.warning(errorMessage);
|
||||||
|
break;
|
||||||
|
case ErrorShowType.ERROR_MESSAGE:
|
||||||
|
message.error(errorMessage);
|
||||||
|
break;
|
||||||
|
case ErrorShowType.NOTIFICATION:
|
||||||
|
notification.open({
|
||||||
|
description: errorMessage,
|
||||||
|
message: errorCode,
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case ErrorShowType.REDIRECT:
|
||||||
|
// TODO: redirect
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
message.error(errorMessage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (error.response) {
|
||||||
|
// Axios 的错误
|
||||||
|
// 请求成功发出且服务器也响应了状态码,但状态代码超出了 2xx 的范围
|
||||||
|
message.error(`Response status:${error.response.status}`);
|
||||||
|
} else if (error.request) {
|
||||||
|
// 请求已经成功发起,但没有收到响应
|
||||||
|
// \`error.request\` 在浏览器中是 XMLHttpRequest 的实例,
|
||||||
|
// 而在node.js中是 http.ClientRequest 的实例
|
||||||
|
message.error('None response! Please retry.');
|
||||||
|
} else {
|
||||||
|
// 发送请求时出了点问题
|
||||||
|
message.error('Request error, please retry.');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
// 请求拦截器
|
||||||
|
requestInterceptors: [
|
||||||
|
(config: RequestOptions) => {
|
||||||
|
// 拦截请求配置,进行个性化处理。
|
||||||
|
// const url = config?.url?.concat('?token = 123');
|
||||||
|
// return { ...config, url };
|
||||||
|
return config;
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
|
// 响应拦截器
|
||||||
|
responseInterceptors: [
|
||||||
|
(response) => {
|
||||||
|
// 拦截响应数据,进行个性化处理
|
||||||
|
const { data } = response as unknown as ResponseStructure;
|
||||||
|
|
||||||
|
if (data?.success === false) {
|
||||||
|
message.error('请求失败!');
|
||||||
|
}
|
||||||
|
return response;
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
65
src/service-worker.js
Normal file
65
src/service-worker.js
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
/* eslint-disable no-restricted-globals */
|
||||||
|
/* eslint-disable no-underscore-dangle */
|
||||||
|
/* globals workbox */
|
||||||
|
workbox.core.setCacheNameDetails({
|
||||||
|
prefix: 'antd-pro',
|
||||||
|
suffix: 'v5',
|
||||||
|
});
|
||||||
|
// Control all opened tabs ASAP
|
||||||
|
workbox.clientsClaim();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use precaching list generated by workbox in build process.
|
||||||
|
* https://developers.google.com/web/tools/workbox/reference-docs/latest/workbox.precaching
|
||||||
|
*/
|
||||||
|
workbox.precaching.precacheAndRoute(self.__precacheManifest || []);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register a navigation route.
|
||||||
|
* https://developers.google.com/web/tools/workbox/modules/workbox-routing#how_to_register_a_navigation_route
|
||||||
|
*/
|
||||||
|
workbox.routing.registerNavigationRoute('/index.html');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use runtime cache:
|
||||||
|
* https://developers.google.com/web/tools/workbox/reference-docs/latest/workbox.routing#.registerRoute
|
||||||
|
*
|
||||||
|
* Workbox provides all common caching strategies including CacheFirst, NetworkFirst etc.
|
||||||
|
* https://developers.google.com/web/tools/workbox/reference-docs/latest/workbox.strategies
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** Handle API requests */
|
||||||
|
workbox.routing.registerRoute(/\/api\//, workbox.strategies.networkFirst());
|
||||||
|
|
||||||
|
/** Handle third party requests */
|
||||||
|
workbox.routing.registerRoute(
|
||||||
|
/^https:\/\/gw\.alipayobjects\.com\//,
|
||||||
|
workbox.strategies.networkFirst(),
|
||||||
|
);
|
||||||
|
workbox.routing.registerRoute(
|
||||||
|
/^https:\/\/cdnjs\.cloudflare\.com\//,
|
||||||
|
workbox.strategies.networkFirst(),
|
||||||
|
);
|
||||||
|
workbox.routing.registerRoute(/\/color.less/, workbox.strategies.networkFirst());
|
||||||
|
|
||||||
|
/** Response to client after skipping waiting with MessageChannel */
|
||||||
|
addEventListener('message', (event) => {
|
||||||
|
const replyPort = event.ports[0];
|
||||||
|
const message = event.data;
|
||||||
|
if (replyPort && message && message.type === 'skip-waiting') {
|
||||||
|
event.waitUntil(
|
||||||
|
self.skipWaiting().then(
|
||||||
|
() => {
|
||||||
|
replyPort.postMessage({
|
||||||
|
error: null,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
(error) => {
|
||||||
|
replyPort.postMessage({
|
||||||
|
error,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
190
src/services/hebi/chartController.ts
Normal file
190
src/services/hebi/chartController.ts
Normal file
@ -0,0 +1,190 @@
|
|||||||
|
// @ts-ignore
|
||||||
|
/* eslint-disable */
|
||||||
|
import { request } from '@umijs/max';
|
||||||
|
|
||||||
|
/** addChart POST /api/chart/add */
|
||||||
|
export async function addChartUsingPost(
|
||||||
|
body: API.ChartAddRequest,
|
||||||
|
options?: { [key: string]: any },
|
||||||
|
) {
|
||||||
|
return request<API.BaseResponseLong_>('/api/chart/add', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
data: body,
|
||||||
|
...(options || {}),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** deleteChart POST /api/chart/delete */
|
||||||
|
export async function deleteChartUsingPost(
|
||||||
|
body: API.DeleteRequest,
|
||||||
|
options?: { [key: string]: any },
|
||||||
|
) {
|
||||||
|
return request<API.BaseResponseBoolean_>('/api/chart/delete', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
data: body,
|
||||||
|
...(options || {}),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** editChart POST /api/chart/edit */
|
||||||
|
export async function editChartUsingPost(
|
||||||
|
body: API.ChartEditRequest,
|
||||||
|
options?: { [key: string]: any },
|
||||||
|
) {
|
||||||
|
return request<API.BaseResponseBoolean_>('/api/chart/edit', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
data: body,
|
||||||
|
...(options || {}),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** genChartByAi POST /api/chart/gen */
|
||||||
|
export async function genChartByAiUsingPost(
|
||||||
|
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
|
||||||
|
params: API.genChartByAiUsingPOSTParams,
|
||||||
|
body: {},
|
||||||
|
file?: File,
|
||||||
|
options?: { [key: string]: any },
|
||||||
|
) {
|
||||||
|
const formData = new FormData();
|
||||||
|
|
||||||
|
if (file) {
|
||||||
|
formData.append('file', file);
|
||||||
|
}
|
||||||
|
|
||||||
|
Object.keys(body).forEach((ele) => {
|
||||||
|
const item = (body as any)[ele];
|
||||||
|
|
||||||
|
if (item !== undefined && item !== null) {
|
||||||
|
if (typeof item === 'object' && !(item instanceof File)) {
|
||||||
|
if (item instanceof Array) {
|
||||||
|
item.forEach((f) => formData.append(ele, f || ''));
|
||||||
|
} else {
|
||||||
|
formData.append(ele, JSON.stringify(item));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
formData.append(ele, item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return request<API.BaseResponseBiResponse_>('/api/chart/gen', {
|
||||||
|
method: 'POST',
|
||||||
|
params: {
|
||||||
|
...params,
|
||||||
|
},
|
||||||
|
data: formData,
|
||||||
|
requestType: 'form',
|
||||||
|
...(options || {}),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** genChartByAiAsync POST /api/chart/gen/async */
|
||||||
|
export async function genChartByAiAsyncUsingPost(
|
||||||
|
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
|
||||||
|
params: API.genChartByAiAsyncUsingPOSTParams,
|
||||||
|
body: {},
|
||||||
|
file?: File,
|
||||||
|
options?: { [key: string]: any },
|
||||||
|
) {
|
||||||
|
const formData = new FormData();
|
||||||
|
|
||||||
|
if (file) {
|
||||||
|
formData.append('file', file);
|
||||||
|
}
|
||||||
|
|
||||||
|
Object.keys(body).forEach((ele) => {
|
||||||
|
const item = (body as any)[ele];
|
||||||
|
|
||||||
|
if (item !== undefined && item !== null) {
|
||||||
|
if (typeof item === 'object' && !(item instanceof File)) {
|
||||||
|
if (item instanceof Array) {
|
||||||
|
item.forEach((f) => formData.append(ele, f || ''));
|
||||||
|
} else {
|
||||||
|
formData.append(ele, JSON.stringify(item));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
formData.append(ele, item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return request<API.BaseResponseBiResponse_>('/api/chart/gen/async', {
|
||||||
|
method: 'POST',
|
||||||
|
params: {
|
||||||
|
...params,
|
||||||
|
},
|
||||||
|
data: formData,
|
||||||
|
requestType: 'form',
|
||||||
|
...(options || {}),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** getChartById GET /api/chart/get */
|
||||||
|
export async function getChartByIdUsingGet(
|
||||||
|
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
|
||||||
|
params: API.getChartByIdUsingGETParams,
|
||||||
|
options?: { [key: string]: any },
|
||||||
|
) {
|
||||||
|
return request<API.BaseResponseChart_>('/api/chart/get', {
|
||||||
|
method: 'GET',
|
||||||
|
params: {
|
||||||
|
...params,
|
||||||
|
},
|
||||||
|
...(options || {}),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** listChartByPage POST /api/chart/list/page */
|
||||||
|
export async function listChartByPageUsingPost(
|
||||||
|
body: API.ChartQueryRequest,
|
||||||
|
options?: { [key: string]: any },
|
||||||
|
) {
|
||||||
|
return request<API.BaseResponsePageChart_>('/api/chart/list/page', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
data: body,
|
||||||
|
...(options || {}),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** listMyChartByPage POST /api/chart/my/list/page */
|
||||||
|
export async function listMyChartByPageUsingPost(
|
||||||
|
body: API.ChartQueryRequest,
|
||||||
|
options?: { [key: string]: any },
|
||||||
|
) {
|
||||||
|
return request<API.BaseResponsePageChart_>('/api/chart/my/list/page', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
data: body,
|
||||||
|
...(options || {}),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** updateChart POST /api/chart/update */
|
||||||
|
export async function updateChartUsingPost(
|
||||||
|
body: API.ChartUpdateRequest,
|
||||||
|
options?: { [key: string]: any },
|
||||||
|
) {
|
||||||
|
return request<API.BaseResponseBoolean_>('/api/chart/update', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
data: body,
|
||||||
|
...(options || {}),
|
||||||
|
});
|
||||||
|
}
|
44
src/services/hebi/fileController.ts
Normal file
44
src/services/hebi/fileController.ts
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
// @ts-ignore
|
||||||
|
/* eslint-disable */
|
||||||
|
import { request } from '@umijs/max';
|
||||||
|
|
||||||
|
/** uploadFile POST /api/file/upload */
|
||||||
|
export async function uploadFileUsingPost(
|
||||||
|
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
|
||||||
|
params: API.uploadFileUsingPOSTParams,
|
||||||
|
body: {},
|
||||||
|
file?: File,
|
||||||
|
options?: { [key: string]: any },
|
||||||
|
) {
|
||||||
|
const formData = new FormData();
|
||||||
|
|
||||||
|
if (file) {
|
||||||
|
formData.append('file', file);
|
||||||
|
}
|
||||||
|
|
||||||
|
Object.keys(body).forEach((ele) => {
|
||||||
|
const item = (body as any)[ele];
|
||||||
|
|
||||||
|
if (item !== undefined && item !== null) {
|
||||||
|
if (typeof item === 'object' && !(item instanceof File)) {
|
||||||
|
if (item instanceof Array) {
|
||||||
|
item.forEach((f) => formData.append(ele, f || ''));
|
||||||
|
} else {
|
||||||
|
formData.append(ele, JSON.stringify(item));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
formData.append(ele, item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return request<API.BaseResponseString_>('/api/file/upload', {
|
||||||
|
method: 'POST',
|
||||||
|
params: {
|
||||||
|
...params,
|
||||||
|
},
|
||||||
|
data: formData,
|
||||||
|
requestType: 'form',
|
||||||
|
...(options || {}),
|
||||||
|
});
|
||||||
|
}
|
20
src/services/hebi/index.ts
Normal file
20
src/services/hebi/index.ts
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
// @ts-ignore
|
||||||
|
/* eslint-disable */
|
||||||
|
// API 更新时间:
|
||||||
|
// API 唯一标识:
|
||||||
|
import * as chartController from './chartController';
|
||||||
|
import * as fileController from './fileController';
|
||||||
|
import * as postController from './postController';
|
||||||
|
import * as postFavourController from './postFavourController';
|
||||||
|
import * as postThumbController from './postThumbController';
|
||||||
|
import * as queueController from './queueController';
|
||||||
|
import * as userController from './userController';
|
||||||
|
export default {
|
||||||
|
chartController,
|
||||||
|
fileController,
|
||||||
|
postController,
|
||||||
|
postFavourController,
|
||||||
|
postThumbController,
|
||||||
|
queueController,
|
||||||
|
userController,
|
||||||
|
};
|
135
src/services/hebi/postController.ts
Normal file
135
src/services/hebi/postController.ts
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
// @ts-ignore
|
||||||
|
/* eslint-disable */
|
||||||
|
import { request } from '@umijs/max';
|
||||||
|
|
||||||
|
/** addPost POST /api/post/add */
|
||||||
|
export async function addPostUsingPost(body: API.PostAddRequest, options?: { [key: string]: any }) {
|
||||||
|
return request<API.BaseResponseLong_>('/api/post/add', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
data: body,
|
||||||
|
...(options || {}),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** deletePost POST /api/post/delete */
|
||||||
|
export async function deletePostUsingPost(
|
||||||
|
body: API.DeleteRequest,
|
||||||
|
options?: { [key: string]: any },
|
||||||
|
) {
|
||||||
|
return request<API.BaseResponseBoolean_>('/api/post/delete', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
data: body,
|
||||||
|
...(options || {}),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** editPost POST /api/post/edit */
|
||||||
|
export async function editPostUsingPost(
|
||||||
|
body: API.PostEditRequest,
|
||||||
|
options?: { [key: string]: any },
|
||||||
|
) {
|
||||||
|
return request<API.BaseResponseBoolean_>('/api/post/edit', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
data: body,
|
||||||
|
...(options || {}),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** getPostVOById GET /api/post/get/vo */
|
||||||
|
export async function getPostVoByIdUsingGet(
|
||||||
|
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
|
||||||
|
params: API.getPostVOByIdUsingGETParams,
|
||||||
|
options?: { [key: string]: any },
|
||||||
|
) {
|
||||||
|
return request<API.BaseResponsePostVO_>('/api/post/get/vo', {
|
||||||
|
method: 'GET',
|
||||||
|
params: {
|
||||||
|
...params,
|
||||||
|
},
|
||||||
|
...(options || {}),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** listPostByPage POST /api/post/list/page */
|
||||||
|
export async function listPostByPageUsingPost(
|
||||||
|
body: API.PostQueryRequest,
|
||||||
|
options?: { [key: string]: any },
|
||||||
|
) {
|
||||||
|
return request<API.BaseResponsePagePost_>('/api/post/list/page', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
data: body,
|
||||||
|
...(options || {}),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** listPostVOByPage POST /api/post/list/page/vo */
|
||||||
|
export async function listPostVoByPageUsingPost(
|
||||||
|
body: API.PostQueryRequest,
|
||||||
|
options?: { [key: string]: any },
|
||||||
|
) {
|
||||||
|
return request<API.BaseResponsePagePostVO_>('/api/post/list/page/vo', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
data: body,
|
||||||
|
...(options || {}),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** listMyPostVOByPage POST /api/post/my/list/page/vo */
|
||||||
|
export async function listMyPostVoByPageUsingPost(
|
||||||
|
body: API.PostQueryRequest,
|
||||||
|
options?: { [key: string]: any },
|
||||||
|
) {
|
||||||
|
return request<API.BaseResponsePagePostVO_>('/api/post/my/list/page/vo', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
data: body,
|
||||||
|
...(options || {}),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** searchPostVOByPage POST /api/post/search/page/vo */
|
||||||
|
export async function searchPostVoByPageUsingPost(
|
||||||
|
body: API.PostQueryRequest,
|
||||||
|
options?: { [key: string]: any },
|
||||||
|
) {
|
||||||
|
return request<API.BaseResponsePagePostVO_>('/api/post/search/page/vo', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
data: body,
|
||||||
|
...(options || {}),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** updatePost POST /api/post/update */
|
||||||
|
export async function updatePostUsingPost(
|
||||||
|
body: API.PostUpdateRequest,
|
||||||
|
options?: { [key: string]: any },
|
||||||
|
) {
|
||||||
|
return request<API.BaseResponseBoolean_>('/api/post/update', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
data: body,
|
||||||
|
...(options || {}),
|
||||||
|
});
|
||||||
|
}
|
48
src/services/hebi/postFavourController.ts
Normal file
48
src/services/hebi/postFavourController.ts
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
// @ts-ignore
|
||||||
|
/* eslint-disable */
|
||||||
|
import { request } from '@umijs/max';
|
||||||
|
|
||||||
|
/** doPostFavour POST /api/post_favour/ */
|
||||||
|
export async function doPostFavourUsingPost(
|
||||||
|
body: API.PostFavourAddRequest,
|
||||||
|
options?: { [key: string]: any },
|
||||||
|
) {
|
||||||
|
return request<API.BaseResponseInt_>('/api/post_favour/', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
data: body,
|
||||||
|
...(options || {}),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** listFavourPostByPage POST /api/post_favour/list/page */
|
||||||
|
export async function listFavourPostByPageUsingPost(
|
||||||
|
body: API.PostFavourQueryRequest,
|
||||||
|
options?: { [key: string]: any },
|
||||||
|
) {
|
||||||
|
return request<API.BaseResponsePagePostVO_>('/api/post_favour/list/page', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
data: body,
|
||||||
|
...(options || {}),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** listMyFavourPostByPage POST /api/post_favour/my/list/page */
|
||||||
|
export async function listMyFavourPostByPageUsingPost(
|
||||||
|
body: API.PostQueryRequest,
|
||||||
|
options?: { [key: string]: any },
|
||||||
|
) {
|
||||||
|
return request<API.BaseResponsePagePostVO_>('/api/post_favour/my/list/page', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
data: body,
|
||||||
|
...(options || {}),
|
||||||
|
});
|
||||||
|
}
|
18
src/services/hebi/postThumbController.ts
Normal file
18
src/services/hebi/postThumbController.ts
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
// @ts-ignore
|
||||||
|
/* eslint-disable */
|
||||||
|
import { request } from '@umijs/max';
|
||||||
|
|
||||||
|
/** doThumb POST /api/post_thumb/ */
|
||||||
|
export async function doThumbUsingPost(
|
||||||
|
body: API.PostThumbAddRequest,
|
||||||
|
options?: { [key: string]: any },
|
||||||
|
) {
|
||||||
|
return request<API.BaseResponseInt_>('/api/post_thumb/', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
data: body,
|
||||||
|
...(options || {}),
|
||||||
|
});
|
||||||
|
}
|
26
src/services/hebi/queueController.ts
Normal file
26
src/services/hebi/queueController.ts
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
// @ts-ignore
|
||||||
|
/* eslint-disable */
|
||||||
|
import { request } from '@umijs/max';
|
||||||
|
|
||||||
|
/** add GET /api/queue/add */
|
||||||
|
export async function addUsingGet(
|
||||||
|
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
|
||||||
|
params: API.addUsingGETParams,
|
||||||
|
options?: { [key: string]: any },
|
||||||
|
) {
|
||||||
|
return request<any>('/api/queue/add', {
|
||||||
|
method: 'GET',
|
||||||
|
params: {
|
||||||
|
...params,
|
||||||
|
},
|
||||||
|
...(options || {}),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** get GET /api/queue/get */
|
||||||
|
export async function getUsingGet(options?: { [key: string]: any }) {
|
||||||
|
return request<string>('/api/queue/get', {
|
||||||
|
method: 'GET',
|
||||||
|
...(options || {}),
|
||||||
|
});
|
||||||
|
}
|
426
src/services/hebi/typings.d.ts
vendored
Normal file
426
src/services/hebi/typings.d.ts
vendored
Normal file
@ -0,0 +1,426 @@
|
|||||||
|
declare namespace API {
|
||||||
|
type addUsingGETParams = {
|
||||||
|
/** name */
|
||||||
|
name?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
type BaseResponseBiResponse_ = {
|
||||||
|
code?: number;
|
||||||
|
data?: BiResponse;
|
||||||
|
message?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
type BaseResponseBoolean_ = {
|
||||||
|
code?: number;
|
||||||
|
data?: boolean;
|
||||||
|
message?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
type BaseResponseChart_ = {
|
||||||
|
code?: number;
|
||||||
|
data?: Chart;
|
||||||
|
message?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
type BaseResponseInt_ = {
|
||||||
|
code?: number;
|
||||||
|
data?: number;
|
||||||
|
message?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
type BaseResponseLoginUserVO_ = {
|
||||||
|
code?: number;
|
||||||
|
data?: LoginUserVO;
|
||||||
|
message?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
type BaseResponseLong_ = {
|
||||||
|
code?: number;
|
||||||
|
data?: number;
|
||||||
|
message?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
type BaseResponsePageChart_ = {
|
||||||
|
code?: number;
|
||||||
|
data?: PageChart_;
|
||||||
|
message?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
type BaseResponsePagePost_ = {
|
||||||
|
code?: number;
|
||||||
|
data?: PagePost_;
|
||||||
|
message?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
type BaseResponsePagePostVO_ = {
|
||||||
|
code?: number;
|
||||||
|
data?: PagePostVO_;
|
||||||
|
message?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
type BaseResponsePageUser_ = {
|
||||||
|
code?: number;
|
||||||
|
data?: PageUser_;
|
||||||
|
message?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
type BaseResponsePageUserVO_ = {
|
||||||
|
code?: number;
|
||||||
|
data?: PageUserVO_;
|
||||||
|
message?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
type BaseResponsePostVO_ = {
|
||||||
|
code?: number;
|
||||||
|
data?: PostVO;
|
||||||
|
message?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
type BaseResponseString_ = {
|
||||||
|
code?: number;
|
||||||
|
data?: string;
|
||||||
|
message?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
type BaseResponseUser_ = {
|
||||||
|
code?: number;
|
||||||
|
data?: User;
|
||||||
|
message?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
type BaseResponseUserVO_ = {
|
||||||
|
code?: number;
|
||||||
|
data?: UserVO;
|
||||||
|
message?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
type BiResponse = {
|
||||||
|
chartId?: number;
|
||||||
|
genChart?: string;
|
||||||
|
genResult?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
type Chart = {
|
||||||
|
chartData?: string;
|
||||||
|
chartType?: string;
|
||||||
|
createTime?: string;
|
||||||
|
execMessage?: string;
|
||||||
|
genChart?: string;
|
||||||
|
genResult?: string;
|
||||||
|
goal?: string;
|
||||||
|
id?: number;
|
||||||
|
isDelete?: number;
|
||||||
|
name?: string;
|
||||||
|
status?: string;
|
||||||
|
updateTime?: string;
|
||||||
|
userId?: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
type ChartAddRequest = {
|
||||||
|
chartData?: string;
|
||||||
|
chartType?: string;
|
||||||
|
goal?: string;
|
||||||
|
name?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
type ChartEditRequest = {
|
||||||
|
chartData?: string;
|
||||||
|
chartType?: string;
|
||||||
|
goal?: string;
|
||||||
|
id?: number;
|
||||||
|
name?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
type ChartQueryRequest = {
|
||||||
|
chartType?: string;
|
||||||
|
current?: number;
|
||||||
|
goal?: string;
|
||||||
|
id?: number;
|
||||||
|
name?: string;
|
||||||
|
pageSize?: number;
|
||||||
|
sortField?: string;
|
||||||
|
sortOrder?: string;
|
||||||
|
userId?: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
type ChartUpdateRequest = {
|
||||||
|
chartData?: string;
|
||||||
|
chartType?: string;
|
||||||
|
createTime?: string;
|
||||||
|
genChart?: string;
|
||||||
|
genResult?: string;
|
||||||
|
goal?: string;
|
||||||
|
id?: number;
|
||||||
|
isDelete?: number;
|
||||||
|
name?: string;
|
||||||
|
updateTime?: string;
|
||||||
|
userId?: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
type DeleteRequest = {
|
||||||
|
id?: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
type genChartByAiAsyncUsingPOSTParams = {
|
||||||
|
chartType?: string;
|
||||||
|
goal?: string;
|
||||||
|
name?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
type genChartByAiUsingPOSTParams = {
|
||||||
|
chartType?: string;
|
||||||
|
goal?: string;
|
||||||
|
name?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
type getChartByIdUsingGETParams = {
|
||||||
|
/** id */
|
||||||
|
id?: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
type getPostVOByIdUsingGETParams = {
|
||||||
|
/** id */
|
||||||
|
id?: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
type getUserByIdUsingGETParams = {
|
||||||
|
/** id */
|
||||||
|
id?: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
type getUserVOByIdUsingGETParams = {
|
||||||
|
/** id */
|
||||||
|
id?: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
type LoginUserVO = {
|
||||||
|
createTime?: string;
|
||||||
|
id?: number;
|
||||||
|
updateTime?: string;
|
||||||
|
userAvatar?: string;
|
||||||
|
userName?: string;
|
||||||
|
userProfile?: string;
|
||||||
|
userRole?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
type OrderItem = {
|
||||||
|
asc?: boolean;
|
||||||
|
column?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
type PageChart_ = {
|
||||||
|
countId?: string;
|
||||||
|
current?: number;
|
||||||
|
maxLimit?: number;
|
||||||
|
optimizeCountSql?: boolean;
|
||||||
|
orders?: OrderItem[];
|
||||||
|
pages?: number;
|
||||||
|
records?: Chart[];
|
||||||
|
searchCount?: boolean;
|
||||||
|
size?: number;
|
||||||
|
total?: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
type PagePost_ = {
|
||||||
|
countId?: string;
|
||||||
|
current?: number;
|
||||||
|
maxLimit?: number;
|
||||||
|
optimizeCountSql?: boolean;
|
||||||
|
orders?: OrderItem[];
|
||||||
|
pages?: number;
|
||||||
|
records?: Post[];
|
||||||
|
searchCount?: boolean;
|
||||||
|
size?: number;
|
||||||
|
total?: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
type PagePostVO_ = {
|
||||||
|
countId?: string;
|
||||||
|
current?: number;
|
||||||
|
maxLimit?: number;
|
||||||
|
optimizeCountSql?: boolean;
|
||||||
|
orders?: OrderItem[];
|
||||||
|
pages?: number;
|
||||||
|
records?: PostVO[];
|
||||||
|
searchCount?: boolean;
|
||||||
|
size?: number;
|
||||||
|
total?: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
type PageUser_ = {
|
||||||
|
countId?: string;
|
||||||
|
current?: number;
|
||||||
|
maxLimit?: number;
|
||||||
|
optimizeCountSql?: boolean;
|
||||||
|
orders?: OrderItem[];
|
||||||
|
pages?: number;
|
||||||
|
records?: User[];
|
||||||
|
searchCount?: boolean;
|
||||||
|
size?: number;
|
||||||
|
total?: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
type PageUserVO_ = {
|
||||||
|
countId?: string;
|
||||||
|
current?: number;
|
||||||
|
maxLimit?: number;
|
||||||
|
optimizeCountSql?: boolean;
|
||||||
|
orders?: OrderItem[];
|
||||||
|
pages?: number;
|
||||||
|
records?: UserVO[];
|
||||||
|
searchCount?: boolean;
|
||||||
|
size?: number;
|
||||||
|
total?: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
type Post = {
|
||||||
|
content?: string;
|
||||||
|
createTime?: string;
|
||||||
|
favourNum?: number;
|
||||||
|
id?: number;
|
||||||
|
isDelete?: number;
|
||||||
|
tags?: string;
|
||||||
|
thumbNum?: number;
|
||||||
|
title?: string;
|
||||||
|
updateTime?: string;
|
||||||
|
userId?: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
type PostAddRequest = {
|
||||||
|
content?: string;
|
||||||
|
tags?: string[];
|
||||||
|
title?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
type PostEditRequest = {
|
||||||
|
content?: string;
|
||||||
|
id?: number;
|
||||||
|
tags?: string[];
|
||||||
|
title?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
type PostFavourAddRequest = {
|
||||||
|
postId?: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
type PostFavourQueryRequest = {
|
||||||
|
current?: number;
|
||||||
|
pageSize?: number;
|
||||||
|
postQueryRequest?: PostQueryRequest;
|
||||||
|
sortField?: string;
|
||||||
|
sortOrder?: string;
|
||||||
|
userId?: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
type PostQueryRequest = {
|
||||||
|
content?: string;
|
||||||
|
current?: number;
|
||||||
|
favourUserId?: number;
|
||||||
|
id?: number;
|
||||||
|
notId?: number;
|
||||||
|
orTags?: string[];
|
||||||
|
pageSize?: number;
|
||||||
|
searchText?: string;
|
||||||
|
sortField?: string;
|
||||||
|
sortOrder?: string;
|
||||||
|
tags?: string[];
|
||||||
|
title?: string;
|
||||||
|
userId?: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
type PostThumbAddRequest = {
|
||||||
|
postId?: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
type PostUpdateRequest = {
|
||||||
|
content?: string;
|
||||||
|
id?: number;
|
||||||
|
tags?: string[];
|
||||||
|
title?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
type PostVO = {
|
||||||
|
content?: string;
|
||||||
|
createTime?: string;
|
||||||
|
favourNum?: number;
|
||||||
|
hasFavour?: boolean;
|
||||||
|
hasThumb?: boolean;
|
||||||
|
id?: number;
|
||||||
|
tagList?: string[];
|
||||||
|
thumbNum?: number;
|
||||||
|
title?: string;
|
||||||
|
updateTime?: string;
|
||||||
|
user?: UserVO;
|
||||||
|
userId?: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
type uploadFileUsingPOSTParams = {
|
||||||
|
biz?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
type User = {
|
||||||
|
createTime?: string;
|
||||||
|
id?: number;
|
||||||
|
isDelete?: number;
|
||||||
|
updateTime?: string;
|
||||||
|
userAccount?: string;
|
||||||
|
userAvatar?: string;
|
||||||
|
userName?: string;
|
||||||
|
userPassword?: string;
|
||||||
|
userRole?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
type UserAddRequest = {
|
||||||
|
userAccount?: string;
|
||||||
|
userAvatar?: string;
|
||||||
|
userName?: string;
|
||||||
|
userRole?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
type UserLoginRequest = {
|
||||||
|
userAccount?: string;
|
||||||
|
userPassword?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
type UserQueryRequest = {
|
||||||
|
current?: number;
|
||||||
|
id?: number;
|
||||||
|
mpOpenId?: string;
|
||||||
|
pageSize?: number;
|
||||||
|
sortField?: string;
|
||||||
|
sortOrder?: string;
|
||||||
|
unionId?: string;
|
||||||
|
userName?: string;
|
||||||
|
userProfile?: string;
|
||||||
|
userRole?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
type UserRegisterRequest = {
|
||||||
|
checkPassword?: string;
|
||||||
|
userAccount?: string;
|
||||||
|
userPassword?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
type UserUpdateMyRequest = {
|
||||||
|
userAvatar?: string;
|
||||||
|
userName?: string;
|
||||||
|
userProfile?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
type UserUpdateRequest = {
|
||||||
|
id?: number;
|
||||||
|
userAvatar?: string;
|
||||||
|
userName?: string;
|
||||||
|
userProfile?: string;
|
||||||
|
userRole?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
type UserVO = {
|
||||||
|
createTime?: string;
|
||||||
|
id?: number;
|
||||||
|
userAvatar?: string;
|
||||||
|
userName?: string;
|
||||||
|
userProfile?: string;
|
||||||
|
userRole?: string;
|
||||||
|
};
|
||||||
|
}
|
166
src/services/hebi/userController.ts
Normal file
166
src/services/hebi/userController.ts
Normal file
@ -0,0 +1,166 @@
|
|||||||
|
// @ts-ignore
|
||||||
|
/* eslint-disable */
|
||||||
|
import { request } from '@umijs/max';
|
||||||
|
|
||||||
|
/** addUser POST /api/user/add */
|
||||||
|
export async function addUserUsingPost(body: API.UserAddRequest, options?: { [key: string]: any }) {
|
||||||
|
return request<API.BaseResponseLong_>('/api/user/add', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
data: body,
|
||||||
|
...(options || {}),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** deleteUser POST /api/user/delete */
|
||||||
|
export async function deleteUserUsingPost(
|
||||||
|
body: API.DeleteRequest,
|
||||||
|
options?: { [key: string]: any },
|
||||||
|
) {
|
||||||
|
return request<API.BaseResponseBoolean_>('/api/user/delete', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
data: body,
|
||||||
|
...(options || {}),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** getUserById GET /api/user/get */
|
||||||
|
export async function getUserByIdUsingGet(
|
||||||
|
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
|
||||||
|
params: API.getUserByIdUsingGETParams,
|
||||||
|
options?: { [key: string]: any },
|
||||||
|
) {
|
||||||
|
return request<API.BaseResponseUser_>('/api/user/get', {
|
||||||
|
method: 'GET',
|
||||||
|
params: {
|
||||||
|
...params,
|
||||||
|
},
|
||||||
|
...(options || {}),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** getLoginUser GET /api/user/get/login */
|
||||||
|
export async function getLoginUserUsingGet(options?: { [key: string]: any }) {
|
||||||
|
return request<API.BaseResponseLoginUserVO_>('/api/user/get/login', {
|
||||||
|
method: 'GET',
|
||||||
|
...(options || {}),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** getUserVOById GET /api/user/get/vo */
|
||||||
|
export async function getUserVoByIdUsingGet(
|
||||||
|
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
|
||||||
|
params: API.getUserVOByIdUsingGETParams,
|
||||||
|
options?: { [key: string]: any },
|
||||||
|
) {
|
||||||
|
return request<API.BaseResponseUserVO_>('/api/user/get/vo', {
|
||||||
|
method: 'GET',
|
||||||
|
params: {
|
||||||
|
...params,
|
||||||
|
},
|
||||||
|
...(options || {}),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** listUserByPage POST /api/user/list/page */
|
||||||
|
export async function listUserByPageUsingPost(
|
||||||
|
body: API.UserQueryRequest,
|
||||||
|
options?: { [key: string]: any },
|
||||||
|
) {
|
||||||
|
return request<API.BaseResponsePageUser_>('/api/user/list/page', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
data: body,
|
||||||
|
...(options || {}),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** listUserVOByPage POST /api/user/list/page/vo */
|
||||||
|
export async function listUserVoByPageUsingPost(
|
||||||
|
body: API.UserQueryRequest,
|
||||||
|
options?: { [key: string]: any },
|
||||||
|
) {
|
||||||
|
return request<API.BaseResponsePageUserVO_>('/api/user/list/page/vo', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
data: body,
|
||||||
|
...(options || {}),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** userLogin POST /api/user/login */
|
||||||
|
export async function userLoginUsingPost(
|
||||||
|
body: API.UserLoginRequest,
|
||||||
|
options?: { [key: string]: any },
|
||||||
|
) {
|
||||||
|
return request<API.BaseResponseLoginUserVO_>('/api/user/login', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
data: body,
|
||||||
|
...(options || {}),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** userLogout POST /api/user/logout */
|
||||||
|
export async function userLogoutUsingPost(options?: { [key: string]: any }) {
|
||||||
|
return request<API.BaseResponseBoolean_>('/api/user/logout', {
|
||||||
|
method: 'POST',
|
||||||
|
...(options || {}),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** userRegister POST /api/user/register */
|
||||||
|
export async function userRegisterUsingPost(
|
||||||
|
body: API.UserRegisterRequest,
|
||||||
|
options?: { [key: string]: any },
|
||||||
|
) {
|
||||||
|
return request<API.BaseResponseLong_>('/api/user/register', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
data: body,
|
||||||
|
...(options || {}),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** updateUser POST /api/user/update */
|
||||||
|
export async function updateUserUsingPost(
|
||||||
|
body: API.UserUpdateRequest,
|
||||||
|
options?: { [key: string]: any },
|
||||||
|
) {
|
||||||
|
return request<API.BaseResponseBoolean_>('/api/user/update', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
data: body,
|
||||||
|
...(options || {}),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** updateMyUser POST /api/user/update/my */
|
||||||
|
export async function updateMyUserUsingPost(
|
||||||
|
body: API.UserUpdateMyRequest,
|
||||||
|
options?: { [key: string]: any },
|
||||||
|
) {
|
||||||
|
return request<API.BaseResponseBoolean_>('/api/user/update/my', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
data: body,
|
||||||
|
...(options || {}),
|
||||||
|
});
|
||||||
|
}
|
20
src/typings.d.ts
vendored
Normal file
20
src/typings.d.ts
vendored
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
declare module 'slash2';
|
||||||
|
declare module '*.css';
|
||||||
|
declare module '*.less';
|
||||||
|
declare module '*.scss';
|
||||||
|
declare module '*.sass';
|
||||||
|
declare module '*.svg';
|
||||||
|
declare module '*.png';
|
||||||
|
declare module '*.jpg';
|
||||||
|
declare module '*.jpeg';
|
||||||
|
declare module '*.gif';
|
||||||
|
declare module '*.bmp';
|
||||||
|
declare module '*.tiff';
|
||||||
|
declare module 'omit.js';
|
||||||
|
declare module 'numeral';
|
||||||
|
declare module '@antv/data-set';
|
||||||
|
declare module 'mockjs';
|
||||||
|
declare module 'react-fittext';
|
||||||
|
declare module 'bizcharts-plugin-slider';
|
||||||
|
|
||||||
|
declare const REACT_APP_ENV: 'test' | 'dev' | 'pre' | false;
|
23
tsconfig.json
Normal file
23
tsconfig.json
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "esnext",
|
||||||
|
"module": "esnext",
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"importHelpers": true,
|
||||||
|
"jsx": "preserve",
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"sourceMap": true,
|
||||||
|
"baseUrl": "./",
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"experimentalDecorators": true,
|
||||||
|
"strict": true,
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
"allowSyntheticDefaultImports": true,
|
||||||
|
"paths": {
|
||||||
|
"@/*": ["./src/*"],
|
||||||
|
"@@/*": ["./src/.umi/*"],
|
||||||
|
"@@test/*": ["./src/.umi-test/*"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"include": ["./**/*.d.ts", "./**/*.ts", "./**/*.tsx"]
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user