Compare commits
23 Commits
tangjian
...
dev_tangji
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2b2a5c65aa | ||
|
|
d6b9d4baca | ||
|
|
3c4f562e17 | ||
|
|
b59c94fbd3 | ||
|
|
4315e42521 | ||
|
|
ae8e8cd9c0 | ||
|
|
f86a49d1e8 | ||
|
|
ca4bc80156 | ||
|
|
ff24a5cec9 | ||
|
|
7dbb60d774 | ||
|
|
2eeaf31cf4 | ||
|
|
20c98c6ed2 | ||
|
|
0e828bd15f | ||
|
|
460a5bd060 | ||
|
|
a1d8629dbe | ||
|
|
e489bfa89c | ||
|
|
23cebffc12 | ||
|
|
1e768b147f | ||
|
|
4bf63e1306 | ||
|
|
72392e9571 | ||
|
|
28047d7061 | ||
|
|
60788d7090 | ||
|
|
730b12c2e4 |
41
.dockerignore
Normal file
@@ -0,0 +1,41 @@
|
||||
### Java template
|
||||
# Compiled class file
|
||||
*.class
|
||||
# Log file
|
||||
*.log
|
||||
# BlueJ files
|
||||
*.ctxt
|
||||
# Mobile Tools for Java (J2ME)
|
||||
.mtj.tmp/
|
||||
# Package Files #
|
||||
*.jar
|
||||
*.war
|
||||
*.nar
|
||||
*.ear
|
||||
*.zip
|
||||
*.tar.gz
|
||||
*.rar
|
||||
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
|
||||
hs_err_pid*
|
||||
### Maven template
|
||||
target/
|
||||
pom.xml.tag
|
||||
pom.xml.releaseBackup
|
||||
pom.xml.versionsBackup
|
||||
pom.xml.next
|
||||
release.properties
|
||||
dependency-reduced-pom.xml
|
||||
buildNumber.properties
|
||||
.mvn/timing.properties
|
||||
# https://github.com/takari/maven-wrapper#usage-without-binary-jar
|
||||
.mvn/wrapper/maven-wrapper.jar
|
||||
### Example user template template
|
||||
### Example user template
|
||||
# IntelliJ project files
|
||||
.idea
|
||||
*.iml
|
||||
out
|
||||
gen
|
||||
!build
|
||||
!default.conf
|
||||
!nginx.conf
|
||||
76
.drone.yml
Normal file
@@ -0,0 +1,76 @@
|
||||
kind: pipeline
|
||||
type: docker
|
||||
name: fateverse-react
|
||||
steps:
|
||||
- name: build-package
|
||||
image: registry.cn-chengdu.aliyuncs.com/claywang/node:16.20.0
|
||||
volumes:
|
||||
- name: cache
|
||||
path: /drone/src/node_modules
|
||||
commands:
|
||||
- export CI=false
|
||||
- mkdir -p ./node_modules
|
||||
- export NODE_MODULES_PATH=`pwd`/node_modules
|
||||
- npm config set registry https://registry.npm.taobao.org
|
||||
- set NODE_OPTIONS=--openssl-legacy-provider
|
||||
- npm install
|
||||
- npm run build
|
||||
|
||||
- name: build-docker # 制作docker镜像
|
||||
image: docker # 使用官方docker镜像
|
||||
volumes: # 将容器内目录挂载到宿主机
|
||||
- name: docker
|
||||
path: /var/run/docker.sock # 挂载宿主机的docker
|
||||
- name: config
|
||||
path: /config
|
||||
environment: # 获取到密文的docker用户名和密码
|
||||
DOCKER_USERNAME:
|
||||
from_secret: docker_username
|
||||
DOCKER_PASSWORD:
|
||||
from_secret: docker_password
|
||||
REGISTRY:
|
||||
from_secret: registry
|
||||
REGISTRY_NAMESPACE:
|
||||
from_secret: registry_namespace
|
||||
commands: # 定义在Docker容器中执行的shell命令
|
||||
- sed -i 's/$REGISTRY/'"$REGISTRY"'/' deployment.yml
|
||||
- sed -i 's/$REGISTRY_NAMESPACE/'"$REGISTRY_NAMESPACE"'/' deployment.yml
|
||||
- sed -i 's/$DRONE_REPO_NAME/'"$DRONE_REPO_NAME"'/' deployment.yml
|
||||
- sed -i 's/$DRONE_COMMIT/'"$DRONE_COMMIT"'/' deployment.yml
|
||||
# docker登录,不能在脚本中登录,并且不能使用docker login -u -p
|
||||
- echo $DOCKER_PASSWORD | docker login $REGISTRY --username $DOCKER_USERNAME --password-stdin
|
||||
- chmod +x docker.sh
|
||||
- cat docker.sh
|
||||
- sh docker.sh
|
||||
# 执行完脚本删除本次制作的docker镜像,避免多次后当前runner空间不足
|
||||
- docker rmi -f $(docker images | grep $DRONE_REPO_NAME | awk '{print $3}')
|
||||
|
||||
- name: drone-rancher # rancher运行
|
||||
image: registry.cn-chengdu.aliyuncs.com/claywang/kubectl #阿里云的kubectl镜像,里面包含kubectl命令行工具
|
||||
volumes: # 将容器内目录挂载到宿主机
|
||||
- name: config
|
||||
path: /app/config # 将kubectl 配置文件挂载出来
|
||||
commands: # 定义在Docker容器中执行的shell命令
|
||||
# 通过kubectl指令运行deployment.yml,并指定授权文件kubectl_conf.yml
|
||||
- kubectl apply -f deployment.yml -n dev --kubeconfig=/app/config/hcy-text-kubectl.yml
|
||||
|
||||
volumes:
|
||||
- name: cache
|
||||
host:
|
||||
path: /home/npm/fateverse-react
|
||||
- name: config # k8s对接的配置文件
|
||||
host:
|
||||
path: /home/kubect
|
||||
- name: maven-cache # maven的缓存文件
|
||||
host:
|
||||
path: /home/data/maven/cache
|
||||
- name: docker # 宿主机中的docker
|
||||
host:
|
||||
path: /var/run/docker.sock
|
||||
|
||||
trigger:
|
||||
branch:
|
||||
# - prod
|
||||
- dev
|
||||
event:
|
||||
- push
|
||||
@@ -2,19 +2,17 @@ module.exports = {
|
||||
root: true,
|
||||
env: { browser: true, es2020: true },
|
||||
extends: [
|
||||
"eslint:recommended",
|
||||
"plugin:@typescript-eslint/recommended",
|
||||
"plugin:react-hooks/recommended",
|
||||
'eslint:recommended',
|
||||
'plugin:@typescript-eslint/recommended',
|
||||
'plugin:react-hooks/recommended',
|
||||
],
|
||||
ignorePatterns: ["dist", ".eslintrc.cjs"],
|
||||
parser: "@typescript-eslint/parser",
|
||||
plugins: ["react-refresh"],
|
||||
ignorePatterns: ['dist', '.eslintrc.cjs'],
|
||||
parser: '@typescript-eslint/parser',
|
||||
plugins: ['react-refresh'],
|
||||
rules: {
|
||||
"react-refresh/only-export-components": [
|
||||
"warn",
|
||||
'react-refresh/only-export-components': [
|
||||
'warn',
|
||||
{ allowConstantExport: true },
|
||||
],
|
||||
"@typescript-eslint/no-explicit-any": "off",
|
||||
"@typescript-eslint/no-unused-vars": "off",
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
9
Dockerfile
Normal file
@@ -0,0 +1,9 @@
|
||||
FROM nginx
|
||||
RUN rm -rf /etc/nginx/nginx.conf
|
||||
COPY nginx.conf /etc/nginx/
|
||||
#RUN useradd -b /home/clay -m -s /bin/bash clay
|
||||
#RUN chmod a+xr -R /home/clay && chown clay:clay -R /home/clay
|
||||
#USER clay
|
||||
COPY ./dist /home/clay
|
||||
WORKDIR /home/clay
|
||||
EXPOSE 80
|
||||
@@ -20,12 +20,11 @@ npm run dev
|
||||
```sh
|
||||
npm run build
|
||||
```
|
||||
|
||||
## 目录结构
|
||||
|
||||
```sh
|
||||
public #静态资源
|
||||
src
|
||||
src
|
||||
|--api #接口文件夹
|
||||
|--assets #图片,字体等静态资源文件
|
||||
|--components #公共组件
|
||||
@@ -52,4 +51,4 @@ src
|
||||
|--Notfound.tsx #404页面
|
||||
|--ParentView.tsx #三级菜单路由出口
|
||||
|--permission.ts #生成菜单文件
|
||||
```
|
||||
```
|
||||
49
deployment.yml
Normal file
@@ -0,0 +1,49 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: $DRONE_REPO_NAME
|
||||
spec:
|
||||
type: ClusterIP
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 80
|
||||
targetPort: 80
|
||||
selector:
|
||||
app: $DRONE_REPO_NAME
|
||||
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: $DRONE_REPO_NAME
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: $DRONE_REPO_NAME
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: $DRONE_REPO_NAME
|
||||
spec:
|
||||
imagePullSecrets:
|
||||
- name: harbor
|
||||
containers:
|
||||
- image: $REGISTRY/$REGISTRY_NAMESPACE/$DRONE_REPO_NAME:$DRONE_COMMIT
|
||||
name: $DRONE_REPO_NAME
|
||||
imagePullPolicy: Always
|
||||
env:
|
||||
- name: TIME_ZONE
|
||||
value: Asia/Shanghai
|
||||
- name: REF_NAME
|
||||
value: dev
|
||||
resources:
|
||||
requests:
|
||||
memory: 0.1Gi
|
||||
cpu: 0.1
|
||||
limits:
|
||||
memory: 2Gi
|
||||
cpu: 2
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
name: app-port
|
||||
15
docker.sh
Normal file
@@ -0,0 +1,15 @@
|
||||
#!/bin/sh
|
||||
# 定义应用组名
|
||||
group_name='clay'
|
||||
# 定义应用名称
|
||||
app_name=$DRONE_REPO_NAME
|
||||
# 定义应用版本
|
||||
app_version=$DRONE_COMMIT
|
||||
echo ${app_version}
|
||||
# 打包编译docker镜像
|
||||
echo '----build image start----'
|
||||
docker build -t ${group_name}/${app_name} .
|
||||
echo '----build image success----'
|
||||
docker tag ${group_name}/${app_name} $REGISTRY/$REGISTRY_NAMESPACE/${app_name}:${app_version}
|
||||
docker push $REGISTRY/$REGISTRY_NAMESPACE/${app_name}:${app_version}
|
||||
echo 'push success'
|
||||
50
nginx.conf
Normal file
@@ -0,0 +1,50 @@
|
||||
user nginx;
|
||||
worker_processes auto;
|
||||
|
||||
error_log /var/log/nginx/error.log notice;
|
||||
pid /var/run/nginx.pid;
|
||||
|
||||
|
||||
events {
|
||||
worker_connections 1024;
|
||||
}
|
||||
http {
|
||||
include /etc/nginx/mime.types;
|
||||
default_type application/octet-stream;
|
||||
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
|
||||
'$status $body_bytes_sent "$http_referer" '
|
||||
'"$http_user_agent" "$http_x_forwarded_for"';
|
||||
|
||||
add_header 'Access-Control-Allow-Origin' '*';
|
||||
add_header 'Access-Control-Allow-Headers' '*';
|
||||
add_header 'Access-Control-Allow-Methods' '*';
|
||||
|
||||
access_log /var/log/nginx/access.log main;
|
||||
|
||||
sendfile on;
|
||||
|
||||
keepalive_timeout 65;
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
listen [::]:80;
|
||||
|
||||
location /api {
|
||||
proxy_pass http://gateway.dev.svc.cluster.local:8080;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_set_header X-Forwarded-Port $server_port;
|
||||
proxy_set_header Host $host;
|
||||
rewrite "^/api/(.*)$" /$1 break;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection 'upgrade';
|
||||
}
|
||||
|
||||
location / {
|
||||
root /home/clay;
|
||||
index index.html index.htm;
|
||||
try_files $uri $uri/ /index.html;
|
||||
}
|
||||
}
|
||||
}
|
||||
7202
package-lock.json
generated
@@ -14,7 +14,6 @@
|
||||
"antd": "^5.7.3",
|
||||
"axios": "^1.4.0",
|
||||
"babel-plugin-import": "^1.13.8",
|
||||
"dayjs": "^1.11.10",
|
||||
"echarts": "^5.4.3",
|
||||
"js-cookie": "^3.0.5",
|
||||
"moment": "^2.29.4",
|
||||
@@ -25,10 +24,12 @@
|
||||
"react-router-dom": "^6.15.0",
|
||||
"redux-persist": "^6.0.0",
|
||||
"sass": "^1.64.2",
|
||||
"vite-plugin-imp": "^2.4.0"
|
||||
"vite-plugin-imp": "^2.4.0",
|
||||
"vite-plugin-svg-icons": "^2.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/js-cookie": "^3.0.3",
|
||||
"@types/node": "^20.9.0",
|
||||
"@types/react": "^18.2.15",
|
||||
"@types/react-dom": "^18.2.7",
|
||||
"@typescript-eslint/eslint-plugin": "^6.0.0",
|
||||
|
||||
@@ -5,7 +5,7 @@ import ParentView from './ParentView'
|
||||
import Loading from './Loading'
|
||||
import currentRouter from './router'
|
||||
import RouteInterception from './router/RouteInterception'
|
||||
import { useDispatch, useSelector } from 'react-redux'
|
||||
import { useSelector } from 'react-redux'
|
||||
import { Suspense, lazy, useEffect, useState } from 'react'
|
||||
const Views = import.meta.glob('./view/**/*.tsx')
|
||||
const transferReactNode = (comp: string) => {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { useEffect, useState } from "react";
|
||||
import NProgress from './mynprogress'
|
||||
import { Spin } from "antd";
|
||||
|
||||
|
||||
@@ -1,59 +1,60 @@
|
||||
import { Button, Form, Input, Image, message } from "antd";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import "./assets/styles/login.scss";
|
||||
import { useEffect, useState } from "react";
|
||||
import './assets/styles/login.scss'
|
||||
import { getCaptchaApi, loginApi } from "./api/login";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { setToken } from "./utils/auth";
|
||||
|
||||
type Login = {
|
||||
uuid?: string;
|
||||
username?: string;
|
||||
password?: string;
|
||||
code?: string;
|
||||
};
|
||||
uuid?: string,
|
||||
username?: string,
|
||||
password?: string,
|
||||
code?: string
|
||||
}
|
||||
|
||||
export default function Login() {
|
||||
const [messageApi, contextHolder] = message.useMessage();
|
||||
const [uuid, setUuid] = useState<string>("");
|
||||
const [captcha, setCaptcha] = useState<string>("");
|
||||
const navigate = useNavigate();
|
||||
const [messageApi, contextHolder] = message.useMessage()
|
||||
const [uuid, setUuid] = useState<string>('')
|
||||
const [captcha, setCaptcha] = useState<string>('')
|
||||
const navigate = useNavigate()
|
||||
|
||||
const getCaptcha = async () => {
|
||||
try {
|
||||
const { code, data } = await getCaptchaApi();
|
||||
const { code, data } = await getCaptchaApi()
|
||||
if (code === 1000) {
|
||||
setUuid(data.uuid);
|
||||
setCaptcha(data.img);
|
||||
setUuid(data.uuid)
|
||||
setCaptcha(data.img)
|
||||
}
|
||||
} catch (err: any) {
|
||||
messageApi.error(err);
|
||||
} catch(err: any) {
|
||||
messageApi.error(err)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const handleLogin = async (values: Login) => {
|
||||
values.uuid = uuid;
|
||||
values.uuid = uuid
|
||||
try {
|
||||
const { code, data, msg } = await loginApi(values);
|
||||
const { code, data, msg } = await loginApi(values)
|
||||
if (code === 1000) {
|
||||
setToken(data);
|
||||
messageApi.success(msg);
|
||||
navigate("/");
|
||||
return;
|
||||
setToken(data)
|
||||
messageApi.success(msg)
|
||||
navigate('/')
|
||||
return
|
||||
}
|
||||
messageApi.error(msg);
|
||||
getCaptcha();
|
||||
} catch (err: any) {
|
||||
messageApi.error(err);
|
||||
messageApi.error(msg)
|
||||
getCaptcha()
|
||||
} catch(err: any) {
|
||||
messageApi.error(err)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const handleLoginFailed = (errorInfo: any) => {
|
||||
console.log(errorInfo);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
getCaptcha();
|
||||
}, []);
|
||||
getCaptcha()
|
||||
}, [])
|
||||
return (
|
||||
<div id="login">
|
||||
{contextHolder}
|
||||
@@ -68,41 +69,35 @@ export default function Login() {
|
||||
<h3>FateVerse</h3>
|
||||
</Form.Item>
|
||||
<Form.Item<Login>
|
||||
label="用户名"
|
||||
name="username"
|
||||
rules={[{ required: true, message: "请输入用户名" }]}
|
||||
initialValue="admin"
|
||||
label='用户名'
|
||||
name='username'
|
||||
rules={[{ required: true, message: '请输入用户名' }]}
|
||||
initialValue='admin'
|
||||
>
|
||||
<Input placeholder="请输入用户名" />
|
||||
</Form.Item>
|
||||
<Form.Item<Login>
|
||||
label="密码"
|
||||
name="password"
|
||||
rules={[{ required: true, message: "请输入密码" }]}
|
||||
initialValue="123456"
|
||||
label='密码'
|
||||
name='password'
|
||||
rules={[{ required: true, message: '请输入密码' }]}
|
||||
initialValue='123456'
|
||||
>
|
||||
<Input.Password placeholder="请输入密码" />
|
||||
</Form.Item>
|
||||
<Form.Item<Login>
|
||||
label="验证码"
|
||||
name="code"
|
||||
rules={[{ required: true, message: "请输入验证码" }]}
|
||||
label='验证码'
|
||||
name='code'
|
||||
rules={[{ required: true, message: '请输入验证码' }]}
|
||||
>
|
||||
<div className="code-box">
|
||||
<Input placeholder="请输入验证码" />
|
||||
<Image
|
||||
src={"data:image/gif;base64," + captcha}
|
||||
preview={false}
|
||||
onClick={getCaptcha}
|
||||
/>
|
||||
<Image src={'data:image/gif;base64,' + captcha} preview={false} onClick={getCaptcha} />
|
||||
</div>
|
||||
</Form.Item>
|
||||
<Form.Item>
|
||||
<Button type="primary" htmlType="submit">
|
||||
登录
|
||||
</Button>
|
||||
<Button type="primary" htmlType="submit">登录</Button>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import React from 'react'
|
||||
|
||||
|
||||
export default function Notfound() {
|
||||
return <div>404</div>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React from 'react'
|
||||
|
||||
import { Outlet } from 'react-router-dom'
|
||||
|
||||
export default function ParentView() {
|
||||
|
||||
8
src/api/auth.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
import request from "../utils/request";
|
||||
|
||||
export const getAuthInfoApi = () => {
|
||||
return request({
|
||||
url: '/auth/info',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
import request from "../../utils/request";
|
||||
|
||||
export const getNoticeListApi = (params: any) => {
|
||||
return request({
|
||||
url: "/notice/notify",
|
||||
method: "get",
|
||||
params,
|
||||
});
|
||||
};
|
||||
|
||||
export const getNoticeInfoApi = (id: number) => {
|
||||
return request({
|
||||
url: "/notice/notify/" + id,
|
||||
method: "get",
|
||||
});
|
||||
};
|
||||
|
||||
export const deleteNoticeInfoApi = (id: number) => {
|
||||
return request({
|
||||
url: "/notice/notify/" + id,
|
||||
method: "delete",
|
||||
});
|
||||
};
|
||||
@@ -1,51 +0,0 @@
|
||||
import request from "../../utils/request";
|
||||
|
||||
interface postListParams {
|
||||
postCode?: string;
|
||||
postName?: string;
|
||||
state?: string;
|
||||
pageNum?: string;
|
||||
pageSize?: string;
|
||||
}
|
||||
|
||||
export const getPostListApi = (data: postListParams) => {
|
||||
const { postCode, postName, state, pageNum, pageSize } = data;
|
||||
const params = data
|
||||
? {
|
||||
postCode,
|
||||
postName,
|
||||
state,
|
||||
pageNum,
|
||||
pageSize: 500,
|
||||
}
|
||||
: undefined;
|
||||
|
||||
return request({
|
||||
url: "/admin/post",
|
||||
method: "get",
|
||||
params,
|
||||
});
|
||||
};
|
||||
|
||||
export const addPostApi = (data: any) => {
|
||||
return request({
|
||||
url: "/admin/post",
|
||||
method: "post",
|
||||
data,
|
||||
});
|
||||
};
|
||||
|
||||
export const editPostApi = (data: any) => {
|
||||
return request({
|
||||
url: "/admin/post",
|
||||
method: "put",
|
||||
data,
|
||||
});
|
||||
};
|
||||
|
||||
export const deletePostApi = (postId: any) => {
|
||||
return request({
|
||||
url: "/admin/post/" + postId,
|
||||
method: "delete",
|
||||
});
|
||||
};
|
||||
@@ -1,94 +0,0 @@
|
||||
import request from "../../utils/request";
|
||||
|
||||
interface userListParams {
|
||||
deptId?: string;
|
||||
userName?: string;
|
||||
phoneNumber?: string;
|
||||
state?: string;
|
||||
startTime?: string;
|
||||
endTime?: string;
|
||||
pageNum?: number;
|
||||
pageSize?: number;
|
||||
}
|
||||
|
||||
export const getDeptTreeApi = () => {
|
||||
return request({
|
||||
url: "/admin/dept",
|
||||
method: "get",
|
||||
});
|
||||
};
|
||||
|
||||
export const getUserInfoApi = (userId: string) => {
|
||||
return request({
|
||||
url: "/admin/user/info/" + userId,
|
||||
method: "get",
|
||||
});
|
||||
};
|
||||
|
||||
export const getRoleListApi = () => {
|
||||
return request({
|
||||
url: "/admin/role",
|
||||
method: "get",
|
||||
});
|
||||
};
|
||||
|
||||
export const getPostListApi = () => {
|
||||
return request({
|
||||
url: "/admin/post",
|
||||
method: "get",
|
||||
});
|
||||
};
|
||||
|
||||
export const getUserListApi = (data: userListParams) => {
|
||||
const {
|
||||
deptId,
|
||||
userName,
|
||||
phoneNumber,
|
||||
state,
|
||||
startTime,
|
||||
endTime,
|
||||
pageNum,
|
||||
pageSize,
|
||||
} = data;
|
||||
const params = data
|
||||
? {
|
||||
deptId,
|
||||
userName,
|
||||
phoneNumber,
|
||||
state,
|
||||
startTime,
|
||||
endTime,
|
||||
pageNum,
|
||||
pageSize: 500,
|
||||
}
|
||||
: undefined;
|
||||
|
||||
return request({
|
||||
url: "/admin/user",
|
||||
method: "get",
|
||||
params,
|
||||
});
|
||||
};
|
||||
|
||||
export const addUserApi = (data: any) => {
|
||||
return request({
|
||||
url: "/admin/user",
|
||||
method: "post",
|
||||
data,
|
||||
});
|
||||
};
|
||||
|
||||
export const editUserApi = (data: any) => {
|
||||
return request({
|
||||
url: "/admin/user",
|
||||
method: "put",
|
||||
data,
|
||||
});
|
||||
};
|
||||
|
||||
export const deleteUserApi = (userId: any) => {
|
||||
return request({
|
||||
url: "/admin/user/" + userId,
|
||||
method: "delete",
|
||||
});
|
||||
};
|
||||
@@ -3,4 +3,5 @@
|
||||
height: calc(100vh - 64px);
|
||||
padding: 20px;
|
||||
box-sizing: border-box;
|
||||
overflow: auto;
|
||||
}
|
||||
1
src/assets/svg/actual_size.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="1689263020512" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2369" xmlns:xlink="http://www.w3.org/1999/xlink" width="64" height="64"><path d="M704 128 704 192 832 192 832 320 896 320 896 192 896 128Z" p-id="2370"></path><path d="M832 832 704 832 704 896 896 896 896 832 896 704 832 704Z" p-id="2371"></path><path d="M192 704 128 704 128 832 128 896 320 896 320 832 192 832Z" p-id="2372"></path><path d="M192 192 320 192 320 128 128 128 128 192 128 320 192 320Z" p-id="2373"></path><path d="M256 319.808l0 384.384C256 739.008 284.544 768 319.808 768l384.384 0C739.008 768 768 739.456 768 704.192L768 319.808C768 284.992 739.456 256 704.192 256L319.808 256C284.992 256 256 284.544 256 319.808zM320 320l384 0 0 384L320 704 320 320z" p-id="2374"></path></svg>
|
||||
|
After Width: | Height: | Size: 944 B |
1
src/assets/svg/biaodan.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 class="icon" width="32px" height="32.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path fill="#ffffff" d="M258.133333 128A106.666667 106.666667 0 0 0 362.666667 213.333333h298.666666a106.666667 106.666667 0 0 0 104.533334-85.333333h87.424A128 128 0 0 1 981.333333 255.744v597.845333A127.872 127.872 0 0 1 853.290667 981.333333H170.666667A128 128 0 0 1 42.666667 853.589333V255.744A127.872 127.872 0 0 1 170.709333 128H258.133333zM298.666667 384a42.666667 42.666667 0 1 0 0 85.333333h256a42.666667 42.666667 0 0 0 0-85.333333H298.666667z m0 170.666667a42.666667 42.666667 0 0 0 0 85.333333h426.666666a42.666667 42.666667 0 0 0 0-85.333333H298.666667z m0 170.666666a42.666667 42.666667 0 0 0 0 85.333334h256a42.666667 42.666667 0 0 0 0-85.333334H298.666667zM362.666667 42.666667h298.666666a64 64 0 0 1 0 128h-298.666666a64 64 0 0 1 0-128z" /></svg>
|
||||
|
After Width: | Height: | Size: 1020 B |
1
src/assets/svg/bumenguanli.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 class="icon" width="32px" height="32.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path fill="#ffffff" d="M186.4 478.4c-44-0.8-80 33.6-81.6 77.6v128H63.2C30.4 683.2 3.2 708.8 2.4 742.4v170.4c0.8 32.8 28 58.4 60.8 57.6h165.6c32.8 0.8 60-24.8 60.8-58.4V742.4c-0.8-32.8-28-59.2-60.8-58.4h-54.4V545.6h302.4v139.2h-48c-32.8-0.8-60 24.8-61.6 58.4v170.4c0.8 32.8 28 58.4 61.6 57.6h166.4c32.8 0.8 60-24.8 60.8-58.4V742.4c-0.8-32.8-28-59.2-60.8-58.4h-48V545.6h302.4v139.2h-54.4c-32.8-0.8-60 24.8-60.8 58.4v170.4c0.8 32.8 28 58.4 60.8 57.6h166.4c32.8 0.8 60-24.8 60.8-58.4V742.4c-0.8-32.8-28-59.2-61.6-58.4h-41.6v-128c-0.8-44-37.6-78.4-81.6-77.6H186.4z m20.8 272.8c7.2 0 12.8 5.6 12.8 12v128.8c0 7.2-5.6 12-12.8 12H84.8c-7.2 0-12.8-5.6-12.8-12V763.2c0-7.2 5.6-12 12.8-12h122.4z m366.4 0c7.2 0 12.8 5.6 12.8 12v128.8c0 7.2-5.6 12-12.8 12H450.4c-7.2 0-12.8-5.6-12.8-12V763.2c0-7.2 5.6-12 12.8-12h123.2z m378.4 140.8c0 7.2-5.6 12-12.8 12h-122.4c-7.2 0-12.8-5.6-12.8-12V763.2c0-7.2 5.6-12 12.8-12h122.4c7.2 0 12.8 5.6 12.8 12v128.8zM671.2 251.2c-4.8-6.4-4.8-15.2 0-21.6l37.6-45.6-4-10.4-4.8-10.4c-3.2-8-6.4-15.2-9.6-20-4.8-10.4-11.2-20-19.2-28l-7.2-7.2-57.6 8c-8.8 0.8-16.8-4.8-20-12.8L568 50.4l-11.2-1.6c-28.8-6.4-57.6-6.4-86.4 0l-9.6 1.6-20 54.4c-3.2 7.2-10.4 11.2-18.4 11.2h-1.6l-56.8-9.6-8 8c-15.2 18.4-27.2 39.2-35.2 61.6l-4 9.6 37.6 45.6c4.8 5.6 4.8 14.4 0 20.8L315.2 296l4 9.6c3.2 12.8 8.8 24.8 15.2 35.2 4.8 9.6 11.2 18.4 18.4 26.4l7.2 7.2 59.2-9.6c8-0.8 15.2 3.2 18.4 11.2l19.2 54.4 11.2 1.6c28.8 6.4 59.2 6.4 88 0l9.6-2.4 20-56c3.2-7.2 10.4-12 18.4-11.2l57.6 9.6 8-7.2c15.2-17.6 26.4-37.6 34.4-60l4-9.6-36.8-44z m-157.6 71.2c-45.6 0-82.4-36.8-82.4-82.4 0-45.6 36.8-82.4 82.4-82.4 45.6 0 82.4 36.8 82.4 82.4 0 45.6-36.8 81.6-82.4 82.4z" /></svg>
|
||||
|
After Width: | Height: | Size: 1.9 KiB |
1
src/assets/svg/canshu.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="1689758652423" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2526" xmlns:xlink="http://www.w3.org/1999/xlink" width="32" height="32"><path d="M245.333333 341.333333c-17.066667 0-32 14.933333-32 32s14.933333 32 32 32h320c17.066667 0 32-14.933333 32-32s-14.933333-32-32-32h-320zM480 490.666667h-234.666667c-17.066667 0-32 14.933333-32 32s14.933333 32 32 32h234.666667c17.066667 0 32-14.933333 32-32s-14.933333-32-32-32zM394.666667 704c17.066667 0 32-14.933333 32-32s-14.933333-32-32-32h-149.333334c-17.066667 0-32 14.933333-32 32s14.933333 32 32 32h149.333334zM974.933333 650.666667L883.2 490.666667c-8.533333-12.8-21.333333-21.333333-36.266667-21.333334H661.333333c-14.933333 0-29.866667 8.533333-36.266666 21.333334L533.333333 650.666667c-8.533333 12.8-8.533333 29.866667 0 42.666666l91.733334 160c8.533333 12.8 21.333333 21.333333 36.266666 21.333334h185.6c14.933333 0 29.866667-8.533333 36.266667-21.333334l91.733333-160c8.533333-12.8 8.533333-29.866667 0-42.666666zM834.133333 810.666667h-160l-81.066666-138.666667 81.066666-138.666667h160l81.066667 138.666667-81.066667 138.666667z" p-id="2527"></path><path d="M791.466667 625.066667c-2.133333-4.266667-6.4-6.4-10.666667-6.4h-46.933333c-4.266667 0-8.533333 2.133333-10.666667 6.4l-23.466667 40.533333c-2.133333 4.266667-2.133333 8.533333 0 12.8l23.466667 40.533333c2.133333 4.266667 6.4 6.4 10.666667 6.4h46.933333c4.266667 0 8.533333-2.133333 10.666667-6.4l23.466666-40.533333c2.133333-4.266667 2.133333-8.533333 0-12.8l-23.466666-40.533333zM480 810.666667H106.666667V213.333333h597.333333v160c0 17.066667 14.933333 32 32 32s32-14.933333 32-32V192c0-23.466667-19.2-42.666667-42.666667-42.666667H85.333333c-23.466667 0-42.666667 19.2-42.666666 42.666667v640c0 23.466667 19.2 42.666667 42.666666 42.666667h394.666667c17.066667 0 32-14.933333 32-32s-14.933333-32-32-32z" p-id="2528"></path></svg>
|
||||
|
After Width: | Height: | Size: 2.0 KiB |
1
src/assets/svg/caozuorizhi.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 class="icon" width="32px" height="32.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path fill="#ffffff" d="M758.969877 1017.428352H58.739777a35.205133 35.205133 0 0 1-35.205134-35.205134V154.902586a35.205133 35.205133 0 0 1 35.205134-35.205133h700.2301a35.205133 35.205133 0 0 1 35.205134 35.205133v177.609898a35.205133 35.205133 0 0 1-70.410267 0V190.10772H93.94491v756.910365h629.819834V805.376099a35.205133 35.205133 0 0 1 70.410267 0V982.223218a35.205133 35.205133 0 0 1-35.205134 35.205134zM503.321935 70.410267v45.766673h-188.934216V70.410267h188.934216m0-70.410267h-188.934216a70.410267 70.410267 0 0 0-70.410266 70.410267v45.766673a70.410267 70.410267 0 0 0 70.410266 70.410266h188.934216a70.410267 70.410267 0 0 0 70.410266-70.410266V70.410267a70.410267 70.410267 0 0 0-70.410266-70.410267zM402.400553 428.329122h-199.495756a35.205133 35.205133 0 1 1 0-70.410267h199.495756a35.205133 35.205133 0 0 1 0 70.410267zM369.542428 603.181283h-166.637631a35.205133 35.205133 0 0 1 0-70.410266h166.637631a35.205133 35.205133 0 0 1 0 70.410266zM627.713406 778.033445h-424.808609a35.205133 35.205133 0 0 1 0-70.410266h424.808609a35.205133 35.205133 0 0 1 0 70.410266zM893.488692 1023.999977a107.187896 107.187896 0 0 1-96.415125-60.200778l-82.473893-169.137196h-3.344487a251.787113 251.787113 0 0 1-225.993486-141.219524 249.275814 249.275814 0 0 1-21.017464-157.00316 253.383079 253.383079 0 0 1 74.482327-136.04437 35.205133 35.205133 0 0 1 55.788401 10.197754L663.094564 511.272416l52.479119-25.582397L646.947143 345.010306a35.205133 35.205133 0 0 1 26.33344-50.237725 253.559105 253.559105 0 0 1 153.09539 25.12473 249.240609 249.240609 0 0 1 110.731879 113.278384 251.810583 251.810583 0 0 1-30.006509 267.641158l82.509098 169.184136a107.070545 107.070545 0 0 1-96.121749 153.998988zM735.933985 722.855266a35.205133 35.205133 0 0 1 31.625945 19.785285l92.800731 190.354156a36.672014 36.672014 0 0 0 65.88054-32.130552l-92.706851-190.36589a35.205133 35.205133 0 0 1 6.571625-40.145587 181.200821 181.200821 0 0 0 33.761722-206.325551 180.097727 180.097727 0 0 0-139.377122-100.31116l59.848726 122.7603a35.205133 35.205133 0 0 1-16.217831 47.080998l-115.766213 56.433829a35.205133 35.205133 0 0 1-47.092734-16.217832l-59.848726-122.795505a181.118676 181.118676 0 0 0 176.471598 272.11221 36.378638 36.378638 0 0 1 4.04859-0.234701z" /></svg>
|
||||
|
After Width: | Height: | Size: 2.5 KiB |
1
src/assets/svg/chart.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="1690337061706" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2298" xmlns:xlink="http://www.w3.org/1999/xlink" width="32" height="32"><path d="M888 792H200V168c0-4.4-3.6-8-8-8h-56c-4.4 0-8 3.6-8 8v688c0 4.4 3.6 8 8 8h752c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8z" p-id="2299"></path><path d="M288 712h56c4.4 0 8-3.6 8-8V560c0-4.4-3.6-8-8-8h-56c-4.4 0-8 3.6-8 8v144c0 4.4 3.6 8 8 8zM440 712h56c4.4 0 8-3.6 8-8V384c0-4.4-3.6-8-8-8h-56c-4.4 0-8 3.6-8 8v320c0 4.4 3.6 8 8 8zM592 712h56c4.4 0 8-3.6 8-8V462c0-4.4-3.6-8-8-8h-56c-4.4 0-8 3.6-8 8v242c0 4.4 3.6 8 8 8zM744 712h56c4.4 0 8-3.6 8-8V304c0-4.4-3.6-8-8-8h-56c-4.4 0-8 3.6-8 8v400c0 4.4 3.6 8 8 8z" p-id="2300"></path></svg>
|
||||
|
After Width: | Height: | Size: 858 B |
1
src/assets/svg/chaxun.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="1689752871415" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2396" width="48" height="48" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M896 64H128c-35.296 0-64 28.704-64 64v768c0 35.296 28.704 64 64 64h592a32 32 0 1 0 0-64H128V128h768v592a32 32 0 1 0 64 0V128c0-35.296-28.704-64-64-64z" p-id="2397"></path><path d="M791.744 746.496A206.752 206.752 0 0 0 832 624c0-114.688-93.312-208-208-208S416 509.312 416 624s93.312 208 208 208a206.752 206.752 0 0 0 122.496-40.256l110.88 110.88a31.904 31.904 0 0 0 45.248 0 31.968 31.968 0 0 0 0-45.248l-110.88-110.88zM480 624c0-79.392 64.608-144 144-144s144 64.608 144 144-64.608 144-144 144-144-64.608-144-144zM800 264a32 32 0 0 0-32-32H256a32 32 0 0 0 0 64h512a32 32 0 0 0 32-32zM256 422.656a32 32 0 0 0 0 64h96a32 32 0 0 0 0-64H256z" p-id="2398"></path></svg>
|
||||
|
After Width: | Height: | Size: 995 B |
1
src/assets/svg/clear.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="1689262997739" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1907" xmlns:xlink="http://www.w3.org/1999/xlink" width="64" height="64"><path d="M987.428571 268.190476h-950.857142a36.571429 36.571429 0 0 1 0-73.142857H243.809524V73.142857a73.142857 73.142857 0 0 1 73.142857-73.142857h390.095238a73.142857 73.142857 0 0 1 73.142857 73.142857v121.904762h207.238095a36.571429 36.571429 0 0 1 0 73.142857zM707.047619 121.904762a48.761905 48.761905 0 0 0-48.761905-48.761905H365.714286a48.761905 48.761905 0 0 0-48.761905 48.761905v73.142857h390.095238V121.904762zM341.333333 816.761905v-390.095238a36.571429 36.571429 0 0 1 73.142857 0v390.095238a36.571429 36.571429 0 0 1-73.142857 0z m268.190477 0v-390.095238a36.571429 36.571429 0 0 1 73.142857 0v390.095238a36.571429 36.571429 0 0 1-73.142857 0zM158.47619 316.952381a36.254476 36.254476 0 0 1 34.133334 24.380952H195.047619v560.761905a48.761905 48.761905 0 0 0 48.761905 48.761905h536.380952a48.761905 48.761905 0 0 0 48.761905-48.761905V341.333333h2.438095a36.059429 36.059429 0 0 1 68.266667 0h2.438095v609.52381a73.142857 73.142857 0 0 1-73.142857 73.142857H195.047619a73.142857 73.142857 0 0 1-73.142857-73.142857V341.333333h2.438095a36.254476 36.254476 0 0 1 34.133333-24.380952z" fill="#333333" p-id="1908"></path></svg>
|
||||
|
After Width: | Height: | Size: 1.4 KiB |
1
src/assets/svg/copy.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="1689263581410" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2531" width="32" height="32" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M746.932 698.108" fill="#A9B7B7" p-id="2532"></path><path d="M925.731 288.698c-1.261-1.18-3.607-3.272-6.902-6.343-5.486-5.112-11.615-10.758-18.236-16.891-18.921-17.526-38.003-35.028-56.046-51.397-2.038-1.848-2.038-1.835-4.077-3.682-24.075-21.795-44.156-39.556-58.996-52.076-8.682-7.325-15.517-12.807-20.539-16.426-3.333-2.402-6.043-4.13-8.715-5.396-3.365-1.595-6.48-2.566-10.905-2.483C729.478 134.227 720 143.77 720 155.734l0 42.475 0 42.475 0 84.95L720 347l21.205 0L890 347l0 595L358.689 942C323.429 942 295 913.132 295 877.922L295 177l361.205 0c11.736 0 21.25-9.771 21.25-21.5s-9.514-21.5-21.25-21.5l-382.5 0L252 134l0 21.734L252 813l-52.421 0C166.646 813 140 786.928 140 754.678L140 72l566.286 0C739.29 72 766 98.154 766 130.404L766 134l40 0 0-3.596C806 76.596 761.271 33 706.286 33L119.958 33 100 33l0 19.506 0 702.172C100 808.463 144.642 852 199.579 852L252 852l0 25.922C252 936.612 299.979 984 358.689 984l552.515 0L932 984l0-21.237L932 325.635 932 304l0.433 0C932.432 299 930.196 292.878 925.731 288.698zM762 304l0-63.315L762 198.21l0-0.273c14 11.479 30.3 26.369 49.711 43.942 2.022 1.832 2.136 1.832 4.157 3.665 17.923 16.259 36.957 33.492 55.779 50.926 2.878 2.666 5.713 5.531 8.391 7.531L762 304.001z" fill="#272636" p-id="2533"></path><path d="M816.936 436 407.295 436c-10.996 0-19.91 8.727-19.91 19.5 0 10.77 8.914 19.5 19.91 19.5l409.641 0c11 0 19.914-8.73 19.914-19.5C836.85 444.727 827.936 436 816.936 436z" fill="#272636" p-id="2534"></path><path d="M816.936 553 407.295 553c-10.996 0-19.91 8.727-19.91 19.5 0 10.774 8.914 19.5 19.91 19.5l409.641 0c11 0 19.914-8.726 19.914-19.5C836.85 561.727 827.936 553 816.936 553z" fill="#272636" p-id="2535"></path><path d="M816.936 689 407.295 689c-10.996 0-19.91 8.729-19.91 19.503 0 10.769 8.914 19.497 19.91 19.497l409.641 0c11 0 19.914-8.729 19.914-19.497C836.85 697.729 827.936 689 816.936 689z" fill="#272636" p-id="2536"></path></svg>
|
||||
|
After Width: | Height: | Size: 2.2 KiB |
1
src/assets/svg/daimashengcheng.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 class="icon" width="32px" height="32.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path fill="#ffffff" d="M768.7 719H255.3c-43.2 0-78.3-35.1-78.3-78.3V267.3c0-43.2 35.1-78.3 78.3-78.3h513.5c43.2 0 78.3 35.1 78.3 78.3v373.5c-0.1 43.1-35.2 78.2-78.4 78.2zM255.3 239c-15.6 0-28.3 12.7-28.3 28.3v373.5c0 15.6 12.7 28.3 28.3 28.3h513.5c15.6 0 28.3-12.7 28.3-28.3V267.3c0-15.6-12.7-28.3-28.3-28.3H255.3zM847 785H177c-13.8 0-25 11.2-25 25s11.2 25 25 25h670c13.8 0 25-11.2 25-25s-11.2-25-25-25zM701.8 564.5H532.2c-13.8 0-25 11.2-25 25s11.2 25 25 25h169.6c13.8 0 25-11.2 25-25s-11.2-25-25-25zM455.2 300.4c-6.4 0-12.8 2.4-17.7 7.3L303.2 442.1c-9.8 9.8-9.8 25.6 0 35.4l134.4 134.4c4.9 4.9 11.3 7.3 17.7 7.3s12.8-2.4 17.7-7.3c9.8-9.8 9.8-25.6 0-35.4L356.2 459.8l116.7-116.7c9.8-9.8 9.8-25.6 0-35.4-4.9-4.8-11.3-7.3-17.7-7.3z" /></svg>
|
||||
|
After Width: | Height: | Size: 996 B |
1
src/assets/svg/data.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="1689756990510" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1866" xmlns:xlink="http://www.w3.org/1999/xlink" width="32" height="32"><path d="M887.808 137.92c21.312 21.312 32.256 47.68 32.832 79.168v593.28c-0.576 31.488-11.52 57.856-32.832 79.168s-47.68 32.256-79.168 32.832h-593.28c-31.488-0.576-57.92-11.52-79.168-32.832-21.312-21.312-32.256-47.68-32.832-79.168v-593.28c0.576-31.488 11.52-57.856 32.832-79.168s47.68-32.256 79.168-32.832h593.28c31.488 0.64 57.856 11.584 79.168 32.832zM383.36 564.48c0-14.592-4.224-26.56-12.672-35.904-8.448-9.344-21.12-14.016-38.08-14.016-16.896 0-30.208 4.672-39.808 14.016s-12.992 21.312-10.048 35.904v128.64c0 14.016 4.8 25.792 14.464 35.456s21.568 14.464 35.904 14.464c14.272 0 26.112-4.8 35.456-14.464 9.344-9.6 14.272-21.44 14.848-35.456V564.48z m173.248-230.08c0-14.016-4.8-25.792-14.464-35.456s-21.568-14.464-35.904-14.464c-14.272 0-26.112 4.8-35.456 14.464-9.344 9.6-14.272 21.44-14.848 35.456v358.72c0.576 14.016 5.568 25.792 14.848 35.456 9.344 9.6 21.12 14.464 35.456 14.464 14.272 0 26.24-4.8 35.904-14.464s14.464-21.44 14.464-35.456V334.4zM736 508.48c-0.576-14.592-6.4-26.56-17.472-35.904s-23.936-14.016-38.528-14.016c-14.592 0-26.24 4.672-35.008 14.016s-11.968 21.312-9.6 35.904v184.64c0 14.016 4.8 25.792 14.464 35.456s21.568 14.464 35.904 14.464c14.272 0 26.112-4.8 35.456-14.464 9.344-9.6 14.272-21.44 14.848-35.456V508.48z" p-id="1867"></path></svg>
|
||||
|
After Width: | Height: | Size: 1.6 KiB |
1
src/assets/svg/datayuan.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="1689753422872" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5415" xmlns:xlink="http://www.w3.org/1999/xlink" width="32" height="32"><path d="M489.6 727.2h421.1c26.9 0 49.3 22.4 49.3 53.8v80.6c0 26.9-22.4 53.8-49.3 53.8H489.6c-26.9 0-49.3-22.4-49.3-53.8v-9H158.1c-17.9 0-31.4-13.4-31.4-31.4v-524h-13.4c-26.9 0-49.3-26.9-49.3-53.8v-80.6c0-31.4 22.4-53.8 49.3-53.8h85.1c26.9 0 49.3 22.4 49.3 53.8v80.6c0 26.9-22.4 53.8-49.3 53.8H185v188.2h250.9v-9c0-26.9 22.4-53.8 49.3-53.8h421.1c26.9 0 49.3 22.4 49.3 53.8V557c0 26.9-22.4 53.8-49.3 53.8H485.1c-26.9 0-49.3-22.4-49.3-53.8v-9H185v246.4h250.9V781c-0.1-26.9 22.3-53.8 53.7-53.8z m421.1-430h-551c-31.4 0-53.8-26.9-53.8-53.8v-80.6c0-31.4 22.4-53.8 53.8-53.8h551c26.9 0 49.3 22.4 49.3 53.8v80.6c0 26.9-22.4 53.8-49.3 53.8z" p-id="5416" fill="#ffffff"></path></svg>
|
||||
|
After Width: | Height: | Size: 996 B |
1
src/assets/svg/dingshirenwu.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 class="icon" width="32px" height="32.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path fill="#ffffff" d="M525.158 921.6a283.351 283.351 0 0 0 55.296 51.2H145.06a93.02 93.02 0 0 1-93.86-92.16V143.36a93.02 93.02 0 0 1 93.86-92.16h682.675a93.025 93.025 0 0 1 93.865 92.16v381.798a281.795 281.795 0 0 0-51.2-33.638V324.27h-768v555.52a42.24 42.24 0 0 0 42.66 41.81h380.098zM870.4 273.065v-128.87a42.24 42.24 0 0 0-42.665-41.795H145.06a42.24 42.24 0 0 0-42.66 41.795v128.87h768z m-358.4-51.2a34.135 34.135 0 1 1 34.13-34.135A34.13 34.13 0 0 1 512 221.865z m119.465 0A34.135 34.135 0 1 1 665.6 187.73a34.13 34.13 0 0 1-34.135 34.135z m119.47 0a34.135 34.135 0 1 1 34.13-34.135 34.13 34.13 0 0 1-34.13 34.135zM449.418 441.283L302.592 569.088a30.136 30.136 0 0 1-41.938 0l-59.684-51.779a28.001 28.001 0 0 1-3.236-38.83v-1.618a25.912 25.912 0 0 1 37.12-3.246l46.777 40.448 135.516-116.475h1.618a27.648 27.648 0 0 1 37.12 4.864c8.043 12.934 6.436 30.72-6.467 38.83z m-3.65 224.558L298.952 793.656a30.136 30.136 0 0 1-41.928 0l-59.694-51.768a28.001 28.001 0 0 1-3.251-38.83v-1.618a25.928 25.928 0 0 1 37.125-3.246l46.781 40.474 135.522-116.501h1.607a27.617 27.617 0 0 1 37.12 4.864c8.054 12.933 6.441 30.72-6.466 38.825zM742.4 972.8a230.4 230.4 0 1 1 230.4-230.4 230.4 230.4 0 0 1-230.4 230.4z m0-51.2a179.2 179.2 0 1 0-179.2-179.2 179.2 179.2 0 0 0 179.2 179.2z m-8.704-170.21l93.952-1.3a25.242 25.242 0 1 1 0.886 50.473l-119.742 1.654a27.832 27.832 0 0 1-26.112-27.515V656.983a25.513 25.513 0 1 1 51.026 0v94.413z m0 0" /></svg>
|
||||
|
After Width: | Height: | Size: 1.7 KiB |
1
src/assets/svg/fabu.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="1690372430043" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2365" width="32" height="32" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M682.47 101c72.01 0 130.041 59.663 131.194 133.157l0.018 2.231v467.066c0 16.519-13.383 29.91-29.891 29.91-16.273 0-29.509-13.012-29.883-29.204l-0.009-0.706V236.388c0-41.574-31.608-74.895-70.255-75.557l-1.174-0.01H202.212c-38.787 0-70.784 32.905-71.42 74.31l-0.01 1.257v601.224c0 41.574 31.609 74.895 70.256 75.557l1.174 0.01h642.917c21.34 0 38.686-17.111 39.082-38.37l0.007-0.743V199.292c0-16.52 13.382-29.91 29.89-29.91 16.273 0 29.509 13.01 29.892 29.204v675.48c0 54.093-43.385 98.047-97.236 98.92l-1.635 0.014H202.212c-72.01 0-130.041-59.663-131.195-133.157L71 837.612V236.388c0-73.768 57.311-134.17 129.034-135.37l2.178-0.018H682.47z m-78.027 616.612c12.7 0 22.994 10.301 22.994 23.008 0 12.492-9.949 22.658-22.35 23l-0.644 0.008H289.436c-12.699 0-22.993-10.301-22.993-23.008 0-12.491 9.948-22.658 22.35-22.999l0.643-0.009h315.007z m0-138.047c12.7 0 22.994 10.3 22.994 23.008 0 12.491-9.949 22.658-22.35 22.999l-0.644 0.008H289.436c-12.699 0-22.993-10.3-22.993-23.007 0-12.492 9.948-22.658 22.35-23l0.643-0.008h315.007z m0-138.048c12.7 0 22.994 10.301 22.994 23.008 0 12.492-9.949 22.658-22.35 23l-0.644 0.008H289.436c-12.699 0-22.993-10.301-22.993-23.008 0-12.491 9.948-22.658 22.35-22.999l0.643-0.009h315.007z m-75.876-132.181c12.7 0 22.994 10.3 22.994 23.008 0 12.491-9.949 22.658-22.35 22.999l-0.644 0.009H366.343c-12.699 0-22.993-10.301-22.993-23.008 0-12.492 9.948-22.658 22.35-23l0.643-0.008h162.224z" fill="#333333" p-id="2366"></path></svg>
|
||||
|
After Width: | Height: | Size: 1.7 KiB |
1
src/assets/svg/fit.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="1689263007214" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2215" xmlns:xlink="http://www.w3.org/1999/xlink" width="64" height="64"><path d="M597.333333 405.376c0-0.128 0.085333-0.256 0.085333-0.384C597.418667 404.821333 597.333333 404.650667 597.333333 404.522667L597.333333 192.768C597.333333 180.522667 606.933333 170.538667 618.666667 170.666667c11.733333-0.042667 21.376 9.813333 21.376 22.144L640.042667 384l191.189333 0c12.16 0 22.186667 9.6 22.101333 21.333333 0 11.733333-9.813333 21.333333-22.186667 21.333333l-211.754667 0c-0.128 0-0.256-0.085333-0.384-0.085333S618.837333 426.666667 618.709333 426.666667c-4.821333 0-9.045333-1.962667-12.629333-4.736-0.853333-0.64-1.749333-0.981333-2.432-1.706667-0.213333-0.213333-0.298667-0.469333-0.512-0.725333C599.68 415.744 597.333333 410.837333 597.333333 405.376zM362.666667 170.666667C350.933333 170.624 341.290667 180.48 341.290667 192.810667L341.290667 384 150.101333 384C137.898667 384 127.914667 393.6 128 405.333333 128 417.066667 137.813333 426.666667 150.186667 426.666667l211.754667 0c0.128 0 0.256-0.085333 0.384-0.085333S362.496 426.666667 362.624 426.666667c4.821333 0 9.045333-1.962667 12.629333-4.736 0.853333-0.64 1.749333-0.981333 2.432-1.706667 0.213333-0.213333 0.298667-0.469333 0.512-0.725333C381.653333 415.744 384 410.837333 384 405.376c0-0.128-0.085333-0.256-0.085333-0.384C383.914667 404.821333 384 404.650667 384 404.522667L384 192.768C384 180.522667 374.4 170.538667 362.666667 170.666667zM831.146667 640l-211.754667 0c-0.128 0-0.256 0.085333-0.384 0.085333S618.837333 640 618.709333 640c-4.821333 0-9.088 2.005333-12.672 4.778667-0.810667 0.597333-1.706667 0.938667-2.389333 1.664-0.213333 0.213333-0.298667 0.469333-0.512 0.725333C599.68 650.922667 597.333333 655.829333 597.333333 661.290667c0 0.128 0.085333 0.256 0.085333 0.384 0 0.170667-0.085333 0.341333-0.085333 0.469333l0 211.797333c0 12.202667 9.6 22.229333 21.333333 22.101333 11.733333 0.042667 21.376-9.813333 21.376-22.144L640.042667 682.666667l191.189333 0c12.16 0 22.186667-9.6 22.101333-21.333333C853.333333 649.6 843.52 640 831.146667 640zM378.154667 647.168c-0.213333-0.256-0.298667-0.512-0.512-0.725333-0.682667-0.725333-1.578667-1.066667-2.389333-1.664C371.712 642.005333 367.445333 640 362.624 640c-0.128 0-0.213333 0.085333-0.341333 0.085333S362.026667 640 361.898667 640L150.186667 640C137.813333 640 128 649.6 128 661.333333 127.914667 673.066667 137.898667 682.666667 150.101333 682.666667l191.189333 0 0 191.189333c0 12.288 9.642667 22.186667 21.376 22.144C374.4 896.128 384 886.144 384 873.898667l0-211.797333c0-0.128-0.085333-0.298667-0.085333-0.469333C383.914667 661.546667 384 661.418667 384 661.290667 384 655.829333 381.653333 650.922667 378.154667 647.168zM490.666667 469.333333c-35.328 0-64 28.672-64 64s28.672 64 64 64 64-28.672 64-64S525.994667 469.333333 490.666667 469.333333z" fill="#020202" p-id="2216"></path></svg>
|
||||
|
After Width: | Height: | Size: 3.0 KiB |
1
src/assets/svg/guanlidenglurizhi.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 class="icon" width="32px" height="32.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path fill="#ffffff" d="M136.3 410.2h70v150.2h-70zM206.3 851.3V733.8h-70v117.5c0 40.7 31.5 73.9 70.2 73.9h206.1v-70H207.5c-0.5-0.6-1.2-1.9-1.2-3.9zM206.3 139c0-2 0.7-3.3 1.1-3.9h619.8c0.5 0.6 1.1 1.8 1.1 3.9v151.1h70V139c0-40.7-31.5-73.9-70.2-73.9H206.5c-38.7 0-70.2 33.1-70.2 73.9v97.9h70V139zM886.8 677.2c-20-20-43-35.9-68-47.2 19.2-22.2 30.9-51.2 30.9-82.8 0-69.9-56.8-126.7-126.7-126.7s-126.7 56.8-126.7 126.7c0 31.6 11.7 60.6 30.9 82.8-25 11.4-48 27.2-68 47.2-43.8 43.8-67.9 101.9-67.9 163.8 0 6.1 0.2 12.2 0.7 18.2l69.8-5.5c-0.3-4.2-0.5-8.5-0.5-12.7 0-89.1 72.5-161.6 161.6-161.6S884.6 751.9 884.6 841c0 4.3-0.2 8.6-0.5 12.7l69.8 5.5c0.5-6 0.7-12.1 0.7-18.2 0-61.9-24.1-120-67.8-163.8zM723 490.5c31.3 0 56.7 25.4 56.7 56.7s-25.4 56.7-56.7 56.7-56.7-25.4-56.7-56.7 25.4-56.7 56.7-56.7zM93.9 288.5h154.8v70H93.9zM93.9 612.1h154.8v70H93.9z" /></svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
1
src/assets/svg/jiaoyanguize.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 class="icon" width="32px" height="32.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path fill="#ffffff" d="M564.906667 534.613333a216.746667 216.746667 0 1 1 216.746666-216.746666 217.173333 217.173333 0 0 1-216.746666 216.746666z m0-366.506666a149.76 149.76 0 1 0 149.76 149.76 150.186667 150.186667 0 0 0-149.76-149.76z" /><path fill="#ffffff" d="M216.32 896a33.706667 33.706667 0 0 1-33.28-33.706667c0-185.6 157.866667-392.96 384-392.96a33.706667 33.706667 0 0 1 0 66.986667c-181.76 0-317.866667 170.666667-317.866667 325.973333a33.706667 33.706667 0 0 1-32.853333 33.706667zM316.586667 488.96c-56.32 0-125.013333-72.106667-125.013334-156.586667A157.013333 157.013333 0 0 1 256 207.36 33.28 33.28 0 0 1 301.226667 213.333333a32.853333 32.853333 0 0 1-6.826667 47.36 87.893333 87.893333 0 0 0-35.84 71.68 97.28 97.28 0 0 0 58.026667 89.6 33.706667 33.706667 0 0 1 33.28 33.706667 33.28 33.28 0 0 1-33.28 33.28z" /><path fill="#ffffff" d="M115.2 725.333333a33.28 33.28 0 0 1-33.28-33.28c0-128 102.4-271.786667 234.666667-271.786666a33.706667 33.706667 0 0 1 0 66.986666c-90.453333 0-167.68 112.213333-167.68 204.8a33.706667 33.706667 0 0 1-33.706667 33.28zM810.666667 779.093333a128 128 0 1 1 130.133333-128 128 128 0 0 1-130.133333 128z m0-192.853333a63.146667 63.146667 0 1 0 63.146666 63.146667A63.146667 63.146667 0 0 0 810.666667 586.24z" /><path fill="#ffffff" d="M773.973333 724.906667m32.426667 0l4.266667 0q32.426667 0 32.426666 32.426666l0 145.493334q0 32.426667-32.426666 32.426666l-4.266667 0q-32.426667 0-32.426667-32.426666l0-145.493334q0-32.426667 32.426667-32.426666Z" /><path fill="#ffffff" d="M912.64 809.813333m0 34.56l0 0q0 34.56-34.56 34.56l-69.973333 0q-34.56 0-34.56-34.56l0 0q0-34.56 34.56-34.56l69.973333 0q34.56 0 34.56 34.56Z" /></svg>
|
||||
|
After Width: | Height: | Size: 1.9 KiB |
1
src/assets/svg/jiekou.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 class="icon" width="32px" height="32.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path fill="#ffffff" d="M591.644444 574.577778l-85.333333 85.333333-136.533333-136.533333 79.644444-79.644445-39.822222-39.822222-79.644444 79.644445-79.644445-79.644445-96.711111 96.711111a261.688889 261.688889 0 0 0-22.755556 347.022222L0 984.177778l39.822222 39.822222L170.666667 893.155556c45.511111 39.822222 102.4 56.888889 159.288889 56.888888 68.266667 0 136.533333-28.444444 187.733333-79.644444l96.711111-96.711111-73.955556-73.955556 85.333334-85.333333-34.133334-39.822222z m-113.777777 250.311111c-39.822222 39.822222-91.022222 62.577778-142.222223 62.577778-51.2 0-102.4-17.066667-136.533333-56.888889l-5.688889-5.688889c-73.955556-73.955556-73.955556-199.111111 5.688889-278.755556l51.2-51.2 278.755556 278.755556-51.2 51.2zM978.488889 91.022222l-39.822222-39.822222L813.511111 170.666667c-45.511111-39.822222-102.4-56.888889-159.288889-56.888889-68.266667 0-136.533333 28.444444-187.733333 79.644444L369.777778 284.444444l369.777778 369.777778 91.022222-91.022222a261.688889 261.688889 0 0 0 22.755555-347.022222l125.155556-125.155556z m-193.422222 426.666667l-45.511111 45.511111L460.8 284.444444l45.511111-45.511111c39.822222-39.822222 91.022222-62.577778 142.222222-62.577777 51.2 0 102.4 17.066667 136.533334 56.888888l5.688889 5.688889c79.644444 73.955556 73.955556 199.111111-5.688889 278.755556z" /></svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
1
src/assets/svg/mokuaiguanli.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 class="icon" width="32px" height="32.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path fill="#ffffff" d="M790.528 464h2.944a232 232 0 1 0-2.944 0zM793.472 64a168 168 0 0 1 0 336h-2.944A168 168 0 1 1 793.472 64zM425.6 560H38.4A38.432 38.432 0 0 0 0 598.4v387.2A38.464 38.464 0 0 0 38.4 1024h387.2a38.464 38.464 0 0 0 38.4-38.4V598.4a38.432 38.432 0 0 0-38.4-38.4zM400 960H64V624h336zM985.6 560H598.4a38.432 38.432 0 0 0-38.4 38.4v387.2a38.464 38.464 0 0 0 38.4 38.4h387.2a38.464 38.464 0 0 0 38.4-38.4V598.4a38.432 38.432 0 0 0-38.4-38.4zM960 960H624V624H960zM425.6 0H38.4A38.432 38.432 0 0 0 0 38.4v387.2a38.464 38.464 0 0 0 38.4 38.4h387.2a38.464 38.464 0 0 0 38.4-38.4V38.4A38.432 38.432 0 0 0 425.6 0z m-25.6 400H64V64h336z" /></svg>
|
||||
|
After Width: | Height: | Size: 912 B |
1
src/assets/svg/paste.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="1689263685428" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3855" xmlns:xlink="http://www.w3.org/1999/xlink" width="32" height="32"><path d="M426.666667 896H170.666667a128 128 0 0 1-128-128V213.333333a128 128 0 0 1 128-128h85.333333a42.666667 42.666667 0 0 1 42.666667 42.666667v42.666667h170.666666V128a42.666667 42.666667 0 0 1 42.666667-42.666667h85.333333a128 128 0 0 1 128 128v170.666667a42.666667 42.666667 0 0 1-85.333333 0V213.333333a42.666667 42.666667 0 0 0-42.666667-42.666666h-42.666666v42.666666a42.666667 42.666667 0 0 1-42.666667 42.666667H256a42.666667 42.666667 0 0 1-42.666667-42.666667V170.666667H170.666667a42.666667 42.666667 0 0 0-42.666667 42.666666v554.666667a42.666667 42.666667 0 0 0 42.666667 42.666667h256a42.666667 42.666667 0 0 1 0 85.333333z" p-id="3856"></path><path d="M512 256H256a42.666667 42.666667 0 0 1-42.666667-42.666667V42.666667a42.666667 42.666667 0 0 1 42.666667-42.666667h256a42.666667 42.666667 0 0 1 42.666667 42.666667v170.666666a42.666667 42.666667 0 0 1-42.666667 42.666667zM298.666667 170.666667h170.666666V85.333333H298.666667zM853.333333 1024h-341.333333a128 128 0 0 1-128-128V469.333333a128 128 0 0 1 128-128h341.333333a128 128 0 0 1 128 128v426.666667a128 128 0 0 1-128 128z m-341.333333-597.333333a42.666667 42.666667 0 0 0-42.666667 42.666666v426.666667a42.666667 42.666667 0 0 0 42.666667 42.666667h341.333333a42.666667 42.666667 0 0 0 42.666667-42.666667V469.333333a42.666667 42.666667 0 0 0-42.666667-42.666666z" p-id="3857"></path><path d="M768 597.333333h-170.666667a42.666667 42.666667 0 0 1 0-85.333333h170.666667a42.666667 42.666667 0 0 1 0 85.333333zM768 725.333333h-170.666667a42.666667 42.666667 0 0 1 0-85.333333h170.666667a42.666667 42.666667 0 0 1 0 85.333333zM768 853.333333h-170.666667a42.666667 42.666667 0 0 1 0-85.333333h170.666667a42.666667 42.666667 0 0 1 0 85.333333z" p-id="3858"></path></svg>
|
||||
|
After Width: | Height: | Size: 2.0 KiB |
1
src/assets/svg/quanxianzu.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 class="icon" width="32px" height="32.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path fill="#ffffff" d="M448 128l128 96h384v704H64V128h384z m-21.312 64H128v672h768v-576H554.688l-128-96zM512 448a64 64 0 0 1 32.064 119.424L544 704h-64V567.424A64 64 0 0 1 512 448z" /></svg>
|
||||
|
After Width: | Height: | Size: 448 B |
1
src/assets/svg/redo.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="1689263778560" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1632" width="32" height="32" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M765.013333 509.013333C487.253333 235.392 67.968 391.466667 65.792 697.941333l7.765333 2.645334c176.853333-218.112 417.024-291.84 605.866667-106.453334 1.706667 1.706667 1.792 4.608 0.085333 6.314667L561.92 718.08a4.266667 4.266667 0 0 0 2.986667 7.296h326.826666a4.266667 4.266667 0 0 0 4.266667-4.266667V394.24a4.224 4.224 0 0 0-7.253333-2.986667l-117.76 117.76a4.096 4.096 0 0 1-5.888 0z" fill="#8a8a8a" p-id="1633"></path></svg>
|
||||
|
After Width: | Height: | Size: 763 B |
1
src/assets/svg/selector.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="1689263027132" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2527" xmlns:xlink="http://www.w3.org/1999/xlink" width="64" height="64"><path d="M0 585.142857h73.142857v73.142857H0v-73.142857z m0 365.714286h73.142857v-73.142857H0v73.142857z m0-146.285714h73.142857v-73.142858H0v73.142858z m0-292.571429h73.142857v-73.142857H0v73.142857zM0 73.142857h73.142857V0H0v73.142857z m0 292.571429h73.142857v-73.142857H0v73.142857z m0-146.285715h73.142857v-73.142857H0v73.142857z m877.714286 438.857143h73.142857v-73.142857h-73.142857v73.142857z m73.142857-219.428571h-73.142857v73.142857h73.142857v-73.142857zM804.571429 0h-73.142858v73.142857h73.142858V0z m146.285714 0h-73.142857v73.142857h73.142857V0z m0 146.285714h-73.142857v73.142857h73.142857v-73.142857z m0 146.285715h-73.142857v73.142857h73.142857v-73.142857zM292.571429 73.142857h73.142857V0h-73.142857v73.142857z m585.142857 950.857143h73.142857v-73.142857h-73.142857v73.142857zM585.142857 73.142857h73.142857V0h-73.142857v73.142857z m146.285714 804.571429v73.142857h146.285715v-73.142857H731.428571z m219.428572-146.285715h-73.142857v146.285715h73.142857V731.428571z m0 146.285715v73.142857h73.142857v-73.142857h-73.142857z m-658.285714 73.142857h73.142857v-73.142857h-73.142857v73.142857z m-146.285715 0h73.142857v-73.142857h-73.142857v73.142857z m0-877.714286h73.142857V0h-73.142857v73.142857z m438.857143 877.714286h73.142857v-73.142857h-73.142857v73.142857zM438.857143 73.142857h73.142857V0h-73.142857v73.142857z m0 877.714286h73.142857v-73.142857h-73.142857v73.142857z" p-id="2528"></path></svg>
|
||||
|
After Width: | Height: | Size: 1.7 KiB |
1
src/assets/svg/shujujiankong.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 class="icon" width="32px" height="32.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path fill="#ffffff" d="M65.6 674.88v49.28c0 34.24 27.52 62.08 62.08 62.4h769.92c34.24 0 62.08-27.52 62.4-62.08v-49.6H65.6zM706.56 882.24h-52.48l-25.28-123.84c-3.2-14.72-16-25.28-30.72-25.28h-170.88c-14.72 0-27.84 10.56-30.72 25.28l-25.92 123.84h-51.2c-17.28 0-31.36 14.08-31.36 31.36s14.08 31.36 31.36 31.36h387.2c17.28-0.64 31.36-14.08 31.36-31.36s-14.08-31.36-31.36-31.36z m-271.36-0.64l17.92-86.4h119.68l17.92 86.4H435.2zM897.92 160H128c-34.24 0-62.08 27.52-62.4 62.08v407.36H960V222.4C960 187.84 932.48 160 897.92 160z m-489.6 399.36c-0.32 7.68-10.56 14.08-23.04 14.08h-22.72c-12.48 0-22.72-6.4-22.72-14.08v-68.48l68.48-31.68v100.16z m102.08 0c0 7.68-10.88 14.08-24.64 14.08h-24.64c-13.44 0-24.64-6.4-24.64-14.08v-142.4l23.04-9.92 50.56 22.08v130.24z m69.76 14.08h-20.8c-11.52 0-20.8-6.4-20.8-14.08V470.4l0.64 0.32c2.56 0.64 5.12 0.96 7.68 0.96 2.88-0.32 5.76-0.64 8-1.6 0.96-0.32 1.6-0.64 2.56-0.96 1.28-0.64 2.56-0.96 3.52-1.6l39.68-27.2 0.32 119.04c0 7.68-9.28 14.08-20.8 14.08z m115.2-16.32c0 7.68-10.56 13.76-23.36 13.76h-23.36c-13.12 0-23.36-6.08-23.36-13.76v-169.6l70.4-41.28v210.88z m-40.96-267.2l-118.08 101.76-85.76-72.64-77.44 68.48-42.88-31.68 119.36-103.68 84.8 70.08 78.4-70.08L580.16 224h115.2l0.32 96.64-41.28-30.72z" /></svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
1
src/assets/svg/shujuyuan.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="1689758652423" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2526" xmlns:xlink="http://www.w3.org/1999/xlink" width="32" height="32"><path d="M245.333333 341.333333c-17.066667 0-32 14.933333-32 32s14.933333 32 32 32h320c17.066667 0 32-14.933333 32-32s-14.933333-32-32-32h-320zM480 490.666667h-234.666667c-17.066667 0-32 14.933333-32 32s14.933333 32 32 32h234.666667c17.066667 0 32-14.933333 32-32s-14.933333-32-32-32zM394.666667 704c17.066667 0 32-14.933333 32-32s-14.933333-32-32-32h-149.333334c-17.066667 0-32 14.933333-32 32s14.933333 32 32 32h149.333334zM974.933333 650.666667L883.2 490.666667c-8.533333-12.8-21.333333-21.333333-36.266667-21.333334H661.333333c-14.933333 0-29.866667 8.533333-36.266666 21.333334L533.333333 650.666667c-8.533333 12.8-8.533333 29.866667 0 42.666666l91.733334 160c8.533333 12.8 21.333333 21.333333 36.266666 21.333334h185.6c14.933333 0 29.866667-8.533333 36.266667-21.333334l91.733333-160c8.533333-12.8 8.533333-29.866667 0-42.666666zM834.133333 810.666667h-160l-81.066666-138.666667 81.066666-138.666667h160l81.066667 138.666667-81.066667 138.666667z" p-id="2527" fill="#ffffff"></path><path d="M791.466667 625.066667c-2.133333-4.266667-6.4-6.4-10.666667-6.4h-46.933333c-4.266667 0-8.533333 2.133333-10.666667 6.4l-23.466667 40.533333c-2.133333 4.266667-2.133333 8.533333 0 12.8l23.466667 40.533333c2.133333 4.266667 6.4 6.4 10.666667 6.4h46.933333c4.266667 0 8.533333-2.133333 10.666667-6.4l23.466666-40.533333c2.133333-4.266667 2.133333-8.533333 0-12.8l-23.466666-40.533333zM480 810.666667H106.666667V213.333333h597.333333v160c0 17.066667 14.933333 32 32 32s32-14.933333 32-32V192c0-23.466667-19.2-42.666667-42.666667-42.666667H85.333333c-23.466667 0-42.666667 19.2-42.666666 42.666667v640c0 23.466667 19.2 42.666667 42.666666 42.666667h394.666667c17.066667 0 32-14.933333 32-32s-14.933333-32-32-32z" p-id="2528" fill="#ffffff"></path></svg>
|
||||
|
After Width: | Height: | Size: 2.0 KiB |
1
src/assets/svg/sql.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="1691830095931" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4048" xmlns:xlink="http://www.w3.org/1999/xlink" width="32" height="32"><path d="M776.533333 755.456H598.903467c-14.421333 0-26.112 12.475733-26.112 27.869867v168.618666h28.433066L776.533333 760.439467v-4.983467zM776.533333 699.733333v-88.183466c0-15.189333 11.4688-27.477333 25.6-27.477334s25.6 12.288 25.6 27.477334v160.136533c0 7.2192-2.645333 14.1312-7.338666 19.285333L630.2208 998.7072a24.746667 24.746667 0 0 1-18.261333 8.226133H228.693333C163.669333 1006.933333 110.933333 950.306133 110.933333 880.452267V143.530667C110.933333 73.693867 163.669333 17.066667 228.693333 17.066667h481.28C774.997333 17.066667 827.733333 73.693867 827.733333 143.547733v48.930134c0 15.189333-11.4688 27.477333-25.6 27.477333s-25.6-12.288-25.6-27.477333V143.530667c0-39.4752-29.7984-71.492267-66.56-71.492267H228.693333c-36.7616 0-66.56 32.017067-66.56 71.509333v736.887467c0 39.4752 29.7984 71.492267 66.56 71.492267H520.533333v-168.618667C520.533333 737.160533 555.6224 699.733333 598.903467 699.733333H776.533333zM367.7696 280.576c27.272533 0 47.530667 5.512533 60.416 16.896 13.687467 11.997867 19.1488 30.8224 16.093867 56.149333h-37.666134c-0.238933-14.2848-4.215467-24.6784-11.3664-30.839466-7.0656-6.485333-19.456-9.4208-36.317866-9.4208-14.609067 0-26.0608 1.9456-34.747734 6.178133-10.752 4.864-17.015467 12.970667-19.336533 24.0128-2.048 9.745067 1.4336 17.8688 11.246933 23.722667 4.317867 2.577067 16.605867 7.458133 36.608 14.267733 29.44 9.728 47.9232 17.527467 55.927467 22.7328 17.578667 12.014933 24.1664 28.5696 19.6608 50.005333-4.369067 20.770133-15.9744 37.3248-34.730667 49.322667-18.688 11.690667-43.042133 17.8688-72.584533 17.8688-28.5696 0-49.8176-5.5296-63.402667-16.554667-16.605867-13.653333-22.801067-35.072-18.210133-64.6144h37.666133c-1.092267 17.527467 2.389333 30.208 10.888534 37.666134 7.7312 6.485333 20.9408 10.069333 40.106666 10.069333 16.878933 0 31.112533-2.935467 42.018134-8.448 10.973867-5.8368 17.749333-13.312 19.797333-23.04 2.594133-12.356267-2.833067-22.084267-15.616-29.2352-4.061867-2.269867-17.902933-7.458133-41.915733-15.2576-26.658133-9.079467-43.144533-15.581867-49.152-19.473067-15.581867-10.717867-21.077333-26.299733-16.776534-46.762666 4.3008-20.445867 16.162133-36.676267 36.164267-48.366934 18.602667-11.3664 40.226133-16.878933 65.2288-16.878933z m249.122133 0c35.3792 0 60.910933 11.3664 76.509867 34.4064 14.8992 21.76 18.568533 50.653867 11.042133 86.357333-7.304533 34.747733-22.664533 62.976-45.346133 84.411734 6.109867 11.042133 12.424533 22.7328 18.261333 35.072l-29.184 21.418666a712.5504 712.5504 0 0 0-18.1248-35.703466c-18.944 9.728-40.482133 14.933333-63.863466 14.933333-35.703467 0-61.166933-11.690667-76.509867-34.423467-14.848-22.0672-18.244267-50.6368-10.8544-85.7088 7.441067-35.3792 22.869333-63.9488 47.0016-86.016 25.0368-23.381333 55.3472-34.747733 91.067733-34.747733z m-7.048533 33.450667c-24.0128 0-44.2368 8.106667-60.962133 24.337066-15.940267 15.581867-26.4704 36.352-32.085334 62.976-5.5296 26.299733-3.7376 47.086933 5.649067 62.6688 9.642667 15.906133 26.760533 24.029867 50.7904 24.029867a90.794667 90.794667 0 0 0 41.2672-9.4208c-8.704-14.2848-17.066667-26.948267-25.378133-38.314667l26.5728-21.418666a704.085333 704.085333 0 0 1 25.838933 37.649066c11.451733-14.2848 19.899733-32.785067 24.610133-55.1936 5.7344-27.255467 3.754667-48.6912-5.632-64.273066-9.710933-15.581867-26.624-23.04-50.670933-23.04z m171.434667-28.910934h37.666133l-41.949867 199.338667h125.320534l-6.826667 32.477867h-162.986667l48.776534-231.816534z" fill="#ffffff" p-id="4049"></path></svg>
|
||||
|
After Width: | Height: | Size: 3.7 KiB |
1
src/assets/svg/table.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 class="icon" width="32px" height="32.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path fill="#ffffff" d="M960 64H64v224h1v164h-1v64h1v160h-1v64h1v219.7h275v0.3h64v-0.3h216v0.3h64v-0.3h275V288h1V64zM620 452H404V288h216v164z m0 224H404V516h216v160z m64-160h211v160H684V516zM129 288h211v164H129V288z m0 228h211v160H129V516z m0 379.7V740h211v155.7H129z m275 0V740h216v155.7H404z m280 0V740h211v155.7H684zM895 452H684V288h211v164z" /></svg>
|
||||
|
After Width: | Height: | Size: 611 B |
1
src/assets/svg/tuoputu.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 class="icon" width="32px" height="32.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path fill="#ffffff" d="M928 768a160 160 0 1 1-192-156.8V544h-448v67.2a160 160 0 1 1-64 0V480h256v-64h-64a128 128 0 0 1-128-128v-64a128 128 0 0 1 128-128h192a128 128 0 0 1 128 128v64a128 128 0 0 1-128 128h-64v64h256v131.2a160 160 0 0 1 128 156.8zM256 672A96 96 0 1 0 352 768 96 96 0 0 0 256 672z m352-320a64 64 0 0 0 64-64v-64a64 64 0 0 0-64-64h-192a64 64 0 0 0-64 64v64a64 64 0 0 0 64 64h192z m160 320a96 96 0 1 0 96 96 96 96 0 0 0-96-96z" /></svg>
|
||||
|
After Width: | Height: | Size: 706 B |
1
src/assets/svg/undo.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="1689262813730" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1753" xmlns:xlink="http://www.w3.org/1999/xlink" width="64" height="64"><path d="M533.333333 341.333333c-113.066667 0-215.466667 42.24-294.4 110.933334L85.333333 298.666667v384h384l-154.453333-154.453334c59.306667-49.493333 134.826667-80.213333 218.453333-80.213333 151.04 0 279.466667 98.56 324.266667 234.666667l101.12-33.28C899.413333 470.613333 731.733333 341.333333 533.333333 341.333333z" fill="#8a8a8a" p-id="1754"></path></svg>
|
||||
|
After Width: | Height: | Size: 685 B |
1
src/assets/svg/xiaoyanjieguo.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 class="icon" width="32px" height="32.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path fill="#ffffff" d="M792.14 905.5H244.66a39.46 39.46 0 0 1-39.41-39.41V294.16a39.46 39.46 0 0 1 39.41-39.41h114.75V308H258.46v544.28h519.87V308H675.56v-53.25h116.58a39.46 39.46 0 0 1 39.41 39.41v571.93a39.46 39.46 0 0 1-39.41 39.41zM476.56 735.49L355.58 608l38.6-36.63 83.57 88.05 165.62-163.98 37.44 37.82-204.25 202.23zM679.71 367.17H357.25V198.54h322.46zM410.47 314h216v-62.2h-216z" /></svg>
|
||||
|
After Width: | Height: | Size: 654 B |
1
src/assets/svg/xitongjiankong.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="1689757664262" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2575" xmlns:xlink="http://www.w3.org/1999/xlink" width="32" height="32"><path d="M800.529 853.171c16.521 0 29.914 13.393 29.914 29.915 0 16.52-13.393 29.914-29.914 29.914H163.77c-16.521 0-29.914-13.393-29.914-29.914 0-16.522 13.393-29.915 29.914-29.915h636.759zM784.464 80C863.184 80 927 143.875 927 222.669v375.08c0 78.793-63.816 142.668-142.536 142.668H177.536C98.816 740.417 35 676.542 35 597.75v-375.08C35 143.875 98.816 80 177.536 80h606.928z m-90.181 152.253l-0.39 0.416-160.43 174.128-110.091-83.862-0.393-0.294c-12.863-9.494-29.72-7.109-40.246 5.695l-0.317 0.391-159.56 199.719-0.356 0.453c-11.52 14.898-10.787 37.753 1.659 51.612l0.38 0.417 0.39 0.414c12.824 13.384 32.497 12.531 44.425-1.927l0.36-0.443L410.9 402.25l108.507 82.656 0.37 0.279c12.157 8.986 27.996 7.408 38.657-3.854l0.322-0.344 178.78-194.045 0.383-0.423c12.53-14.048 13.084-37.228 1.153-52.065-11.932-14.837-31.876-15.768-44.79-2.2z" fill="#ffffff" p-id="2576"></path></svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
1
src/assets/svg/xitongjiekou.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 class="icon" width="32px" height="32.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path fill="#ffffff" d="M569.6 750.933333l-19.2-68.266666H42.666667v106.666666c0 46.933333 38.4 85.333333 85.333333 85.333334h448l-4.266667-4.266667c-32-34.133333-34.133333-85.333333-2.133333-119.466667zM266.666667 810.666667h-106.666667c-17.066667 0-32-14.933333-32-32S142.933333 746.666667 160 746.666667h106.666667c17.066667 0 32 14.933333 32 32s-14.933333 32-32 32zM573.866667 565.333333l138.666666-138.666666H42.666667v192h503.466666c4.266667-19.2 12.8-38.4 27.733334-53.333334zM266.666667 554.666667h-106.666667c-17.066667 0-32-14.933333-32-32S142.933333 490.666667 160 490.666667h106.666667c17.066667 0 32 14.933333 32 32s-14.933333 32-32 32zM789.333333 256c0-46.933333-38.4-85.333333-85.333333-85.333333H128c-46.933333 0-85.333333 38.4-85.333333 85.333333v106.666667h746.666666v-106.666667z m-522.666666 42.666667h-106.666667c-17.066667 0-32-14.933333-32-32S142.933333 234.666667 160 234.666667h106.666667c17.066667 0 32 14.933333 32 32s-14.933333 32-32 32z m298.666666 0c-17.066667 0-32-14.933333-32-32s14.933333-32 32-32 32 14.933333 32 32-14.933333 32-32 32z m106.666667 0c-17.066667 0-32-14.933333-32-32s14.933333-32 32-32 32 14.933333 32 32-14.933333 32-32 32zM964.266667 629.333333l-121.6-121.6c-17.066667-17.066667-42.666667-17.066667-59.733334 0l-29.866666 29.866667-29.866667-29.866667-102.4 102.4c-10.666667 10.666667-14.933333 27.733333-10.666667 42.666667l34.133334 117.333333-25.6 25.6c-8.533333 8.533333-8.533333 21.333333 0 29.866667l29.866666 29.866667c8.533333 8.533333 21.333333 8.533333 29.866667 0l25.6-25.6 117.333333 34.133333c14.933333 4.266667 32 0 42.666667-10.666667l102.4-102.4-29.866667-29.866666 29.866667-29.866667c14.933333-19.2 14.933333-46.933333-2.133333-61.866667z m-136.533334-14.933333l-29.866666-29.866667 29.866666-29.866666 29.866667 29.866666-29.866667 29.866667z m61.866667 59.733333l-29.866667-29.866666 29.866667-29.866667 29.866667 29.866667-29.866667 29.866666z" /></svg>
|
||||
|
After Width: | Height: | Size: 2.1 KiB |
1
src/assets/svg/yanshi.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="1689757603554" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2420" xmlns:xlink="http://www.w3.org/1999/xlink" width="32" height="32"><path d="M844.7 124.4H489c-13.8 0-25 11.2-25 25s11.2 25 25 25h355.7c9 0 16.3 7.3 16.3 16.3v329.8c0 9-7.3 16.3-16.3 16.3H489c-13.8 0-25 11.2-25 25s11.2 25 25 25h355.7c36.6 0 66.3-29.8 66.3-66.3V190.8c0-36.6-29.7-66.4-66.3-66.4z" p-id="2421"></path><path d="M648 515.4c1.9 0 3.8-0.2 5.7-0.7 9.1-2.1 16.2-9.1 18.5-18.1l24.2-93.6 40.2 38.1c6.6 6.3 16.2 8.5 24.9 5.7s15.2-10.1 16.9-19.1l36.1-190c2.6-13.6-6.3-26.6-19.9-29.2-13.6-2.6-26.6 6.3-29.2 19.9l-27.5 145-37.7-35.8c-6.4-6.1-15.6-8.3-24.1-5.9-8.5 2.4-15.1 9.2-17.3 17.8l-22.9 88.4-13.3-15.5c-9-10.5-24.8-11.7-35.3-2.6-10.5 9-11.7 24.8-2.6 35.3l44.5 51.7c4.7 5.4 11.6 8.6 18.8 8.6zM282.4 337.4c60.2 0 109.2-49 109.2-109.2S342.6 119 282.4 119s-109.2 49-109.2 109.2 49 109.2 109.2 109.2z m0-168.4c32.6 0 59.2 26.5 59.2 59.2s-26.5 59.2-59.2 59.2-59.2-26.5-59.2-59.2 26.6-59.2 59.2-59.2zM551.6 413.7c0-33.2-27-60.2-60.2-60.2H167c-14.8 0-28.6 5.9-38.9 16.5-10.3 10.6-15.6 24.6-15.1 39.4l6.9 197c0.6 17.1 9.4 33.1 23.6 42.8l29.4 20c1 0.7 1.6 1.8 1.7 3l14.2 165.6c1.6 18.4 9.9 35.4 23.5 47.8 13.6 12.5 31.2 19.3 49.7 19.3h40.5c37.8 0 69.2-28.4 73.1-66L410 503.7c0.2-1.6 1.3-3 2.8-3.5l96-29c25.6-7.6 42.8-30.8 42.8-57.5z m-57.3 9.8l-96 29c-20.9 6.3-35.9 24.5-38.1 46.2L325.8 834c-1.2 12-11.3 21.1-23.3 21.1H262c-12.3 0-22.3-9.2-23.4-21.5L224.4 668c-1.4-16.2-9.9-30.8-23.4-40l-29.4-20c-1.1-0.7-1.7-1.9-1.8-3.2l-6.9-197c0-1.4 0.6-2.4 1.1-2.9 0.5-0.6 1.5-1.2 2.9-1.2h324.4c5.6 0 10.2 4.6 10.2 10.2 0.1 4.3-2.8 8.3-7.2 9.6z" p-id="2422"></path></svg>
|
||||
|
After Width: | Height: | Size: 1.8 KiB |
1
src/assets/svg/zaixianyonghu.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 class="icon" width="32px" height="32.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path fill="#ffffff" d="M519.868669 583.569892A291.784946 291.784946 0 1 1 811.653615 291.784946 292.115269 292.115269 0 0 1 519.868669 583.569892z m0-528.516129A236.731183 236.731183 0 1 0 756.599852 291.784946 236.951398 236.951398 0 0 0 519.868669 55.053763zM35.395551 1024A27.526882 27.526882 0 0 1 7.868669 996.473118C7.868669 738.491183 237.55297 528.516129 519.868669 528.516129A546.463656 546.463656 0 0 1 745.589099 576.082581a27.526882 27.526882 0 1 1-22.021505 50.209032A492.84129 492.84129 0 0 0 519.868669 583.569892C267.942648 583.569892 62.922433 768.770753 62.922433 996.473118A27.526882 27.526882 0 0 1 35.395551 1024zM571.839422 854.874839a26.866237 26.866237 0 0 1-8.808602-1.431398 27.526882 27.526882 0 0 1-17.396989-34.793979 247.852043 247.852043 0 0 1 468.947957-2.972903 27.526882 27.526882 0 1 1-51.970753 18.167742 192.688172 192.688172 0 0 0-364.676129 2.312258 27.636989 27.636989 0 0 1-26.095484 18.71828zM652.548239 916.094624a27.196559 27.196559 0 0 1-11.891613-2.202151 27.636989 27.636989 0 0 1-12.88258-36.775914 170.446452 170.446452 0 0 1 152.719139-96.013763A168.574624 168.574624 0 0 1 932.771895 875.685161a27.526882 27.526882 0 1 1-49.43828 24.223656 113.851183 113.851183 0 0 0-102.950537-64.302795 115.062366 115.062366 0 0 0-103.060645 64.853333 27.747097 27.747097 0 0 1-24.774194 15.635269zM780.162863 962.670108m-52.190968 0a52.190968 52.190968 0 1 0 104.381936 0 52.190968 52.190968 0 1 0-104.381936 0Z" /></svg>
|
||||
|
After Width: | Height: | Size: 1.7 KiB |
1
src/assets/svg/zidianpeizhi.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 class="icon" width="32px" height="32.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path fill="#ffffff" d="M192 384h-64v512a64 64 0 0 0 64 64h512v-64H192zM544 288h-96v320h96c88.22 0 160-71.78 160-160s-71.78-160-160-160z" /><path fill="#ffffff" d="M832 64H320a64.19 64.19 0 0 0-64 64v640a64.19 64.19 0 0 0 64 64h512a64.19 64.19 0 0 0 64-64V128a64.19 64.19 0 0 0-64-64zM702.39 606.39A222.53 222.53 0 0 1 544 672H384V224h160a224 224 0 0 1 158.39 382.39z" /></svg>
|
||||
|
After Width: | Height: | Size: 635 B |
1
src/assets/svg/zoom-in.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="1689263495822" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1180" xmlns:xlink="http://www.w3.org/1999/xlink" width="64" height="64"><path d="M463.238095 146.285714c175.055238 0 316.952381 141.897143 316.952381 316.952381 0 77.775238-28.038095 149.040762-74.532571 204.214857l188.440381 194.535619-55.247238 57.002667-191.536762-197.705143A315.489524 315.489524 0 0 1 463.238095 780.190476c-175.055238 0-316.952381-141.897143-316.952381-316.952381S288.182857 146.285714 463.238095 146.285714z m0 73.142857C328.582095 219.428571 219.428571 328.582095 219.428571 463.238095s109.153524 243.809524 243.809524 243.809524a242.883048 242.883048 0 0 0 161.889524-61.513143l25.551238-26.355809A242.834286 242.834286 0 0 0 707.047619 463.238095c0-134.656-109.153524-243.809524-243.809524-243.809524z m36.571429 97.52381v109.714286H609.52381v73.142857h-109.714286V609.52381h-73.142857v-109.738667L316.952381 499.809524v-73.142857l109.714286-0.024381V316.952381h73.142857z" p-id="1181"></path></svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
1
src/assets/svg/zoom-out.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="1689263030318" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2681" xmlns:xlink="http://www.w3.org/1999/xlink" width="64" height="64"><path d="M463.238095 146.285714c175.055238 0 316.952381 141.897143 316.952381 316.952381 0 77.775238-28.038095 149.040762-74.532571 204.214857l188.440381 194.535619-55.247238 57.002667-191.536762-197.705143A315.489524 315.489524 0 0 1 463.238095 780.190476c-175.055238 0-316.952381-141.897143-316.952381-316.952381S288.182857 146.285714 463.238095 146.285714z m0 73.142857C328.582095 219.428571 219.428571 328.582095 219.428571 463.238095s109.153524 243.809524 243.809524 243.809524a242.883048 242.883048 0 0 0 161.889524-61.513143l25.551238-26.355809A242.834286 242.834286 0 0 0 707.047619 463.238095c0-134.656-109.153524-243.809524-243.809524-243.809524z m152.210286 219.428572v73.142857H316.952381v-73.142857h298.496z" p-id="2682"></path></svg>
|
||||
|
After Width: | Height: | Size: 1.0 KiB |
1
src/assets/svg/zu1773.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 class="icon" width="32px" height="30.12px" viewBox="0 0 1088 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path fill="#ffffff" d="M960 832H128c-70.4 0-128-57.6-128-128V128C0 57.6 57.6 0 128 0h832c70.4 0 128 57.6 128 128v576c0 70.4-57.6 128-128 128zM128 64c-38.4 0-64 25.6-64 64v576c0 38.4 25.6 64 64 64h832c38.4 0 64-25.6 64-64V128c0-38.4-25.6-64-64-64H128z" /><path fill="#ffffff" d="M160 672s-6.4 0 0 0c-25.6-6.4-32-19.2-32-38.4 0-6.4 6.4-19.2 121.6-224 6.4-6.4 12.8-12.8 25.6-19.2 12.8 0 19.2 6.4 25.6 12.8l89.6 134.4 160-332.8c6.4-12.8 12.8-19.2 32-19.2 12.8 0 25.6 6.4 25.6 19.2L768 550.4l96-147.2c6.4-12.8 32-19.2 44.8-12.8 12.8 6.4 19.2 32 12.8 44.8l-128 198.4c-6.4 12.8-19.2 19.2-32 12.8-12.8 0-19.2-6.4-25.6-19.2L576 288l-153.6 320c-6.4 12.8-12.8 19.2-25.6 19.2s-25.6-6.4-32-12.8L268.8 473.6C224 550.4 185.6 627.2 179.2 640c6.4 25.6-6.4 32-19.2 32zM544 1024c-19.2 0-32-12.8-32-32v-192c0-19.2 12.8-32 32-32s32 12.8 32 32v192c0 19.2-12.8 32-32 32z" /><path fill="#ffffff" d="M736 1024h-384c-19.2 0-32-12.8-32-32s12.8-32 32-32h384c19.2 0 32 12.8 32 32s-12.8 32-32 32z" /></svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
@@ -1,4 +1,4 @@
|
||||
import React, { useState } from "react";
|
||||
import { useState } from "react";
|
||||
|
||||
/**
|
||||
* @author {温华}
|
||||
@@ -7,7 +7,7 @@ import React, { useState } from "react";
|
||||
* @param {permission: string[]}
|
||||
*/
|
||||
|
||||
export default function Authenticationbtn({ permission }: any) {
|
||||
export default function Authenticationbtn({ permission, children }: any) {
|
||||
// 还需从缓存中获取用户权限数组
|
||||
const [visible, setVisible] = useState(true)
|
||||
const allPermission: string = "*:*:*"
|
||||
@@ -20,5 +20,6 @@ export default function Authenticationbtn({ permission }: any) {
|
||||
setVisible(hasPermission)
|
||||
}
|
||||
|
||||
return <div style={{display: visible ? 'block' : 'none'}}></div>
|
||||
if(visible) return <div>{children}</div>
|
||||
return null
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import React from "react";
|
||||
// import React from "react";
|
||||
|
||||
export default function ConfirmModel() {
|
||||
// export default function ConfirmModel() {
|
||||
|
||||
}
|
||||
// }
|
||||
143
src/components/Fvsearchform.tsx
Normal file
@@ -0,0 +1,143 @@
|
||||
import { Fragment, useState } from "react";
|
||||
import {Button, DatePicker, Form, Input, Select} from 'antd'
|
||||
import { useForm } from "antd/es/form/Form";
|
||||
import { formatDate } from "@/utils/tool";
|
||||
|
||||
const { RangePicker } = DatePicker
|
||||
|
||||
interface IItemConfig {
|
||||
name: string,
|
||||
type: string,
|
||||
key: string,
|
||||
options?: Array<any>,
|
||||
placeholder?: string,
|
||||
picker?: any,
|
||||
showTime?: boolean,
|
||||
showHour?: boolean,
|
||||
showMinute?: boolean,
|
||||
showSecond?: boolean,
|
||||
showNow?: boolean
|
||||
}
|
||||
|
||||
export interface ISearchformConfig {
|
||||
config: {
|
||||
name: string,
|
||||
formItem: Array<IItemConfig>
|
||||
},
|
||||
submit: (val: object)=>void
|
||||
}
|
||||
|
||||
interface ISubmitVal {
|
||||
[x: string]: any
|
||||
}
|
||||
|
||||
export default function Fvsearchform(props: ISearchformConfig) {
|
||||
const [val, setVal] = useState<object>()
|
||||
const [form] = useForm()
|
||||
const {config, submit} = props
|
||||
const handleSubmit = (value: ISubmitVal) => {
|
||||
if(Object.keys(value).length) {
|
||||
config.formItem.forEach(item => {
|
||||
for (const key in value) {
|
||||
if ( item.type == 'date' && item.key == key ) {
|
||||
value[key] && (value[key] = formatDate(value[key].$d))
|
||||
}
|
||||
if(item.type == 'rangedate' && item.key == key) {
|
||||
value[key] && (value[key] = value[key]?.map((date: any)=>date = formatDate(date.$d)))
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
setVal({...val, ...value})
|
||||
submit(value)
|
||||
}
|
||||
const handleReset = () => {
|
||||
form.resetFields()
|
||||
}
|
||||
return(
|
||||
<Fragment>
|
||||
<Form
|
||||
name={config?.name}
|
||||
form={form}
|
||||
onFinish={handleSubmit}
|
||||
layout="inline"
|
||||
>
|
||||
{
|
||||
config?.formItem.map((item:IItemConfig) => {
|
||||
if(item) {
|
||||
if(item.type === 'input') {
|
||||
return(
|
||||
<Form.Item
|
||||
key={item.key}
|
||||
label={item.name}
|
||||
name={item.key}
|
||||
>
|
||||
<Input placeholder={item?.placeholder || '请输入'} allowClear></Input>
|
||||
</Form.Item>
|
||||
)
|
||||
}
|
||||
if(item.type === 'select') {
|
||||
return(
|
||||
<Form.Item
|
||||
key={item.key}
|
||||
label={item.name}
|
||||
name={item.key}
|
||||
>
|
||||
<Select
|
||||
options={item?.options}
|
||||
placeholder={item?.placeholder || '请选择'}
|
||||
allowClear
|
||||
/>
|
||||
</Form.Item>
|
||||
)
|
||||
}
|
||||
if(item.type === 'date') {
|
||||
return(
|
||||
<Form.Item
|
||||
key={item.key}
|
||||
label={item.name}
|
||||
name={item.key}
|
||||
>
|
||||
<DatePicker
|
||||
picker={item.picker}
|
||||
showTime={item?.showTime}
|
||||
showNow={item?.showNow}
|
||||
format="YYYY-MM-DD HH:mm:ss"
|
||||
allowClear
|
||||
/>
|
||||
</Form.Item>
|
||||
)
|
||||
}
|
||||
if(item.type === 'rangedate') {
|
||||
return(
|
||||
<Form.Item
|
||||
key={item.key}
|
||||
label={item.name}
|
||||
name={item.key}
|
||||
>
|
||||
<RangePicker
|
||||
showTime={item?.showTime}
|
||||
showHour={item?.showHour}
|
||||
showMinute={item?.showMinute}
|
||||
showSecond={item?.showSecond}
|
||||
showNow={item?.showNow}
|
||||
picker={item.picker}
|
||||
format="YYYY-MM-DD HH:mm:ss"
|
||||
allowClear
|
||||
/>
|
||||
</Form.Item>
|
||||
)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
<Form.Item>
|
||||
<Button htmlType="submit" type="primary" >搜索</Button>
|
||||
</Form.Item>
|
||||
<Form.Item>
|
||||
<Button onClick={handleReset} htmlType="submit">重置</Button>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</Fragment>
|
||||
)
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useState, useEffect } from "react";
|
||||
// import { useState, useEffect } from "react";
|
||||
|
||||
export default function useDemo() {
|
||||
// export default function useDemo() {
|
||||
|
||||
}
|
||||
// }
|
||||
@@ -1,5 +1,4 @@
|
||||
import React from "react";
|
||||
import '../../assets/styles/appmain.scss'
|
||||
import '@/assets/styles/appmain.scss'
|
||||
import { Outlet } from "react-router-dom";
|
||||
|
||||
export default function AppMain() {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useEffect } from "react";
|
||||
import { useEffect } from "react";
|
||||
import { Layout } from 'antd'
|
||||
import { useDispatch, useSelector } from 'react-redux'
|
||||
import SideBar from "./sidebar";
|
||||
|
||||
@@ -3,7 +3,7 @@ import {
|
||||
MenuFoldOutlined,
|
||||
MenuUnfoldOutlined,
|
||||
} from '@ant-design/icons';
|
||||
import React from 'react'
|
||||
|
||||
import { useSelector, useDispatch } from 'react-redux'
|
||||
import { setCollapsed } from '../../stores/sidebar';
|
||||
|
||||
|
||||
19
src/layout/sidebar/Menuicon.tsx
Normal file
@@ -0,0 +1,19 @@
|
||||
import { useMemo } from "react"
|
||||
|
||||
interface IMenuIconProps {
|
||||
prefix?: string
|
||||
name: string
|
||||
color?: string,
|
||||
size?: number | string
|
||||
}
|
||||
export default function Menuicon(props: IMenuIconProps) {
|
||||
const { prefix = 'icon', name, color, size = 16 } = props
|
||||
const symbolId = useMemo(() => `#${prefix}-${name}`, [prefix, name])
|
||||
return (
|
||||
<span className="anticon">
|
||||
<svg aria-hidden="true" width={size} height={size} fill={color} >
|
||||
<use href={symbolId} fill={color} />
|
||||
</svg>
|
||||
</span>
|
||||
)
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Menu } from 'antd'
|
||||
import React, {Fragment, useEffect, useState} from 'react'
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import {Fragment, useEffect, useState} from 'react'
|
||||
import { useSelector } from 'react-redux';
|
||||
import { generateMenu } from '../../permission';
|
||||
import { useLocation, useNavigate } from 'react-router-dom';
|
||||
|
||||
@@ -8,7 +8,7 @@ export default function SideBar() {
|
||||
const navigate = useNavigate()
|
||||
const location = useLocation()
|
||||
const routes: [] = useSelector((store: any)=>store.permission)
|
||||
const dispatch = useDispatch()
|
||||
// const dispatch = useDispatch()
|
||||
const [menuItem, setMenuItem] = useState<Array<any>>([{
|
||||
key: '/',
|
||||
label: '首页',
|
||||
@@ -24,7 +24,7 @@ export default function SideBar() {
|
||||
const goPage = (val: any) => {
|
||||
console.log(val);
|
||||
|
||||
navigate(val.key)
|
||||
navigate(val.key, { replace: true })
|
||||
}
|
||||
useEffect(()=>{
|
||||
getMenu()
|
||||
@@ -36,6 +36,7 @@ export default function SideBar() {
|
||||
theme="dark"
|
||||
mode="inline"
|
||||
defaultSelectedKeys={[location.pathname]}
|
||||
selectedKeys={[location.pathname]}
|
||||
items={menuItem}
|
||||
onClick={goPage}
|
||||
/>
|
||||
|
||||
31
src/main.tsx
@@ -1,21 +1,26 @@
|
||||
import React from "react";
|
||||
import ReactDOM from "react-dom/client";
|
||||
import App from "./App.tsx";
|
||||
import "./index.css";
|
||||
import { BrowserRouter } from "react-router-dom";
|
||||
import React from 'react'
|
||||
import ReactDOM from 'react-dom/client'
|
||||
import App from './App.tsx'
|
||||
import './index.css'
|
||||
import { BrowserRouter } from 'react-router-dom'
|
||||
import { ConfigProvider } from 'antd'
|
||||
import zhCn from 'antd/locale/zh_CN'
|
||||
import 'virtual:svg-icons-register'
|
||||
|
||||
// redux toolkit
|
||||
import { Provider } from "react-redux";
|
||||
import store, { persistor } from "./stores/index.ts";
|
||||
import { PersistGate } from "redux-persist/integration/react";
|
||||
ReactDOM.createRoot(document.getElementById("root")!).render(
|
||||
import { Provider } from 'react-redux'
|
||||
import store, { persistor } from './stores/index.ts'
|
||||
import { PersistGate } from 'redux-persist/integration/react'
|
||||
ReactDOM.createRoot(document.getElementById('root')!).render(
|
||||
<React.StrictMode>
|
||||
<Provider store={store}>
|
||||
<PersistGate loading={null} persistor={persistor}>
|
||||
<PersistGate loading={null} persistor={persistor} >
|
||||
<BrowserRouter>
|
||||
<App />
|
||||
<ConfigProvider locale={zhCn}>
|
||||
<App />
|
||||
</ConfigProvider>
|
||||
</BrowserRouter>
|
||||
</PersistGate>
|
||||
</Provider>
|
||||
</React.StrictMode>
|
||||
);
|
||||
</React.StrictMode>,
|
||||
)
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import Menuicon from "./layout/sidebar/Menuicon"
|
||||
import { IRouter } from "./stores/permission"
|
||||
|
||||
// 生成菜单
|
||||
@@ -11,7 +12,7 @@ export const generateMenu = (routes: IRouter): Array<any> => {
|
||||
if(item.meta) {
|
||||
item.title = item.meta?.title
|
||||
item.label = item.meta?.title
|
||||
item.icon = item.meta?.icon
|
||||
item.icon = <Svgicon name={item.meta?.icon} />
|
||||
}
|
||||
if(item.children && item.children?.length) {
|
||||
item.children = generateChildMenu(item.children)
|
||||
@@ -29,11 +30,15 @@ const generateChildMenu = (routes: any): Array<any> => {
|
||||
if(item.meta) {
|
||||
item.title = item.meta?.title
|
||||
item.label = item.meta?.title
|
||||
item.icon = item.meta?.icon
|
||||
item.icon = <Svgicon name={item.meta?.icon} />
|
||||
}
|
||||
if(item.children && item.children?.length) {
|
||||
generateChildMenu(item.children)
|
||||
}
|
||||
return true
|
||||
})
|
||||
}
|
||||
|
||||
function Svgicon({name}:any) {
|
||||
return <Menuicon name={name} />
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
import { Navigate } from "react-router-dom"
|
||||
import Notfound from "../Notfound"
|
||||
import { getToken } from "../utils/auth"
|
||||
|
||||
const Views = import.meta.glob('../view/**/*.tsx')
|
||||
@@ -13,17 +12,17 @@ const hasMapFile = (filePath: string): boolean => {
|
||||
* @description 路由拦截组件
|
||||
* @param {children: ReactDOM, filePath: string(文件路径)}
|
||||
*/
|
||||
export default function RouteInterception ({children, filePath=""}: any) {
|
||||
if(getToken()) {
|
||||
if(filePath!=="") {
|
||||
if(hasMapFile(filePath)) {
|
||||
export default function RouteInterception({ children, filePath = "" }: any) {
|
||||
if (getToken()) {
|
||||
if (filePath !== "") {
|
||||
if (hasMapFile(filePath)) {
|
||||
return children
|
||||
} else {
|
||||
return <Notfound />
|
||||
return <Navigate to='/404' />
|
||||
}
|
||||
}
|
||||
return children
|
||||
} else {
|
||||
return <Navigate to='/login' />
|
||||
return <Navigate to='/login' replace={true} />
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,12 @@
|
||||
import { getToken } from '../utils/auth'
|
||||
import LayOut from '../layout/index'
|
||||
import Home from '../view/home'
|
||||
import { Suspense, lazy } from 'react'
|
||||
import Loading from '../Loading'
|
||||
import RouteInterception from './RouteInterception'
|
||||
interface Meta {
|
||||
title: string,
|
||||
redirect?: boolean
|
||||
}
|
||||
import Notfound from '../Notfound'
|
||||
// interface Meta {
|
||||
// title: string,
|
||||
// redirect?: boolean
|
||||
// }
|
||||
|
||||
type route = {
|
||||
path: string,
|
||||
@@ -21,6 +20,10 @@ const lazyLoad = (viewName: string) => {
|
||||
const LoginView = lazy(()=>import('../Login'))
|
||||
return <LoginView />
|
||||
}
|
||||
if(viewName === 'home') {
|
||||
const Home = lazy(()=>import('../view/home'))
|
||||
return <Home />
|
||||
}
|
||||
const View = lazy(()=>import(`../view/${viewName}.tsx`))
|
||||
return <View/>
|
||||
}
|
||||
@@ -29,11 +32,15 @@ const lazyLoad = (viewName: string) => {
|
||||
const currentRouter: Array<route> = [
|
||||
{
|
||||
path: '/',
|
||||
element: <RouteInterception><Suspense fallback={<Loading />}><LayOut /></Suspense></RouteInterception>,
|
||||
element: <RouteInterception><LayOut /></RouteInterception>,
|
||||
children: [
|
||||
{
|
||||
path: "", //登录后默认跳转路径
|
||||
element : <Home/>
|
||||
element : <Suspense fallback={<Loading />}>{lazyLoad('home')}</Suspense>
|
||||
},
|
||||
{
|
||||
path: "*",
|
||||
element: <Notfound />
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
53
src/stores/auth.ts
Normal file
@@ -0,0 +1,53 @@
|
||||
import { createSlice, createAsyncThunk } from '@reduxjs/toolkit'
|
||||
import { getAuthInfoApi } from '../api/auth'
|
||||
|
||||
export interface IAuthInfo {
|
||||
permissions: Array<string>,
|
||||
roles: Array<string>
|
||||
user: object
|
||||
}
|
||||
|
||||
const initAuthInfo = new Object() as IAuthInfo
|
||||
|
||||
export const getAuthInfo = createAsyncThunk('/auth/info',
|
||||
async () => {
|
||||
try {
|
||||
const {code, data} = await getAuthInfoApi()
|
||||
if(code === 1000) {
|
||||
return data
|
||||
}
|
||||
} catch (err) {
|
||||
return Promise.reject(err)
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
export const authInfoSlice = createSlice({
|
||||
name: 'authinfo',
|
||||
initialState: initAuthInfo,
|
||||
reducers: {
|
||||
addAuthInfo(state, {payload}) {
|
||||
state = {...payload}
|
||||
return state
|
||||
}
|
||||
},
|
||||
extraReducers(builder) {
|
||||
builder
|
||||
.addCase(getAuthInfo.pending, (state) => {
|
||||
console.log(state);
|
||||
|
||||
console.log('正在请求登录用户信息')
|
||||
})
|
||||
.addCase(getAuthInfo.fulfilled, (state, {payload}) => {
|
||||
console.log(state);
|
||||
return payload
|
||||
})
|
||||
.addCase(getAuthInfo.rejected, (state, err) => {
|
||||
console.log(state);
|
||||
console.log(err, 'rejected')
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
export const { addAuthInfo } = authInfoSlice.actions
|
||||
export default authInfoSlice.reducer
|
||||
@@ -1,10 +1,10 @@
|
||||
import { createSlice } from '@reduxjs/toolkit'
|
||||
|
||||
type CacheKey = string
|
||||
// type CacheKey = string
|
||||
|
||||
type CacheVal = any
|
||||
// type CacheVal = any
|
||||
|
||||
const initCache = new Map<CacheKey, CacheVal>([])
|
||||
// const initCache = new Map<CacheKey, CacheVal>([])
|
||||
|
||||
// 创建一个slice
|
||||
export const cacheSlice = createSlice({
|
||||
|
||||
@@ -4,6 +4,7 @@ import storage from "redux-persist/lib/storage";
|
||||
import cacheSlice from "./cache";
|
||||
import sidebarSlice from "./sidebar";
|
||||
import permissionSlice from "./permission";
|
||||
import authInfoSlice from "./auth"
|
||||
|
||||
const persistConfig = {
|
||||
key: 'root',
|
||||
@@ -14,7 +15,8 @@ const persistConfig = {
|
||||
const reducers = combineReducers({
|
||||
cache: cacheSlice,
|
||||
sidebar: sidebarSlice,
|
||||
permission: permissionSlice
|
||||
permission: permissionSlice,
|
||||
auth: authInfoSlice
|
||||
})
|
||||
|
||||
// configureStore创建一个redux数据
|
||||
|
||||
@@ -46,13 +46,16 @@ export const permissionSlice = createSlice({
|
||||
extraReducers(builder) {
|
||||
builder
|
||||
.addCase(getAsyncRouters.pending, (state) => {
|
||||
console.log(state);
|
||||
console.log('正在请求路由');
|
||||
})
|
||||
.addCase(getAsyncRouters.fulfilled, (state, { payload }) => {
|
||||
console.log(state);
|
||||
// 请求成功后处理路由
|
||||
return payload
|
||||
})
|
||||
.addCase(getAsyncRouters.rejected, (state, err) => {
|
||||
console.log(state);
|
||||
console.log(err,'rejected');
|
||||
|
||||
})
|
||||
|
||||
@@ -6,13 +6,13 @@ export interface IResponse<T=any> {
|
||||
}
|
||||
|
||||
// 定义请求方式枚举
|
||||
enum EMethod {
|
||||
GET = 'get',
|
||||
POST = 'post',
|
||||
PUT = 'put',
|
||||
DELETE = 'delete',
|
||||
PATCH = 'patch'
|
||||
}
|
||||
// enum EMethod {
|
||||
// GET = 'get',
|
||||
// POST = 'post',
|
||||
// PUT = 'put',
|
||||
// DELETE = 'delete',
|
||||
// PATCH = 'patch'
|
||||
// }
|
||||
|
||||
// 用户token类型定义
|
||||
export type IToken = string
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
export default function FormatData(DataStr: string) {
|
||||
const dateStr = DataStr;
|
||||
const date = new Date(dateStr);
|
||||
const year = date.getFullYear();
|
||||
const month = String(date.getMonth() + 1).padStart(2, "0");
|
||||
const day = String(date.getDate()).padStart(2, "0");
|
||||
const hours = String(date.getHours()).padStart(2, "0");
|
||||
const minutes = String(date.getMinutes()).padStart(2, "0");
|
||||
const seconds = String(date.getSeconds()).padStart(2, "0");
|
||||
|
||||
const formattedDate = `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
|
||||
return formattedDate;
|
||||
}
|
||||
@@ -1,86 +1,74 @@
|
||||
import { IResponse, IToken } from "@/type";
|
||||
import axios, {
|
||||
InternalAxiosRequestConfig,
|
||||
AxiosInstance,
|
||||
AxiosRequestConfig,
|
||||
} from "axios";
|
||||
import Cookie from "js-cookie";
|
||||
import axios, { InternalAxiosRequestConfig, AxiosInstance, AxiosRequestConfig } from "axios";
|
||||
import { getToken, removeToken } from "./auth";
|
||||
import { message } from "antd";
|
||||
|
||||
const service: AxiosInstance = axios.create({
|
||||
baseURL: import.meta.env.VITE_BASEURL,
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
timeout: 6000,
|
||||
});
|
||||
timeout: 6000
|
||||
})
|
||||
|
||||
// 请求前拦截
|
||||
service.interceptors.request.use((config: InternalAxiosRequestConfig) => {
|
||||
const Authorization: IToken = getToken() || "";
|
||||
const Authorization: IToken = getToken() || ''
|
||||
if (config && config.headers && Authorization) {
|
||||
config.headers.Authorization = Authorization;
|
||||
config.headers.Authorization = Authorization
|
||||
}
|
||||
return config;
|
||||
});
|
||||
return config
|
||||
})
|
||||
|
||||
const request = async <T = any>(
|
||||
config: AxiosRequestConfig
|
||||
): Promise<IResponse<T>> => {
|
||||
const request = async <T = any>(config: AxiosRequestConfig): Promise<IResponse<T>> => {
|
||||
try {
|
||||
const response = await service.request<IResponse<T>>(config);
|
||||
const { code, msg } = response.data;
|
||||
const response = await service.request<IResponse<T>>(config)
|
||||
const { code, msg } = response.data
|
||||
if (code !== 1000) {
|
||||
switch (code) {
|
||||
case 401:
|
||||
redirectLogin();
|
||||
break;
|
||||
case 402:
|
||||
message.error(msg);
|
||||
break;
|
||||
case 403:
|
||||
message.error(msg);
|
||||
break;
|
||||
case 405:
|
||||
message.error(msg);
|
||||
break;
|
||||
default:
|
||||
message.error("系统未知错误");
|
||||
case 401: redirectLogin()
|
||||
break
|
||||
case 402: message.error(msg)
|
||||
break
|
||||
case 403: message.error(msg)
|
||||
break
|
||||
case 405: message.error(msg)
|
||||
break
|
||||
default: message.error('系统未知错误')
|
||||
}
|
||||
return {
|
||||
code: -1,
|
||||
msg: "error",
|
||||
data: null as any,
|
||||
};
|
||||
msg: 'error',
|
||||
data: null as any
|
||||
}
|
||||
}
|
||||
return response.data;
|
||||
return response.data
|
||||
} catch (err: any) {
|
||||
switch (err) {
|
||||
}
|
||||
if (!window.navigator.onLine) {
|
||||
errorInfoRet("请检查网络连接");
|
||||
if(!window.navigator.onLine) {
|
||||
errorInfoRet('请检查网络连接')
|
||||
}
|
||||
return {
|
||||
code: -1,
|
||||
msg: "error",
|
||||
data: null as any,
|
||||
};
|
||||
msg: 'error',
|
||||
data: null as any
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const redirectLogin = () => {
|
||||
message.warning("用户登录已过期, 即将跳转到登录页面重新登录");
|
||||
removeToken();
|
||||
window.location.href = "/login";
|
||||
};
|
||||
message.warning('用户登录已过期, 即将跳转到登录页面重新登录')
|
||||
removeToken()
|
||||
window.location.href = '/login'
|
||||
}
|
||||
|
||||
const errorInfoRet = (msg: string) => {
|
||||
message.error(msg);
|
||||
message.error(msg)
|
||||
return {
|
||||
code: -1,
|
||||
msg,
|
||||
data: null as any,
|
||||
};
|
||||
};
|
||||
export default request;
|
||||
data: null as any
|
||||
}
|
||||
}
|
||||
export default request
|
||||
5
src/utils/tool.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
import moment from 'moment'
|
||||
|
||||
export function formatDate(date: Date, format='YYYY-MM-DD HH:mm:ss'): string {
|
||||
return moment(date).format(format)
|
||||
}
|
||||
@@ -1,5 +1,3 @@
|
||||
import React from 'react'
|
||||
|
||||
export default function Home() {
|
||||
return(
|
||||
<div>home</div>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React from "react";
|
||||
|
||||
export default function Dept() {
|
||||
return <div>dept</div>;
|
||||
}
|
||||
return(
|
||||
<div>dept</div>
|
||||
)
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
#content {
|
||||
display: flex;
|
||||
border-top: 1px solid black;
|
||||
.dept-content {
|
||||
flex: 20%;
|
||||
padding: 35px 12px 0 0;
|
||||
height: calc(100vh - 85px);
|
||||
}
|
||||
|
||||
.left-dept {
|
||||
flex: 20%;
|
||||
padding: 35px 12px 0 0;
|
||||
height: calc(100vh - 85px);
|
||||
border: 1px solid red;
|
||||
border-top: 1px solid black;
|
||||
}
|
||||
.right {
|
||||
flex: 80%;
|
||||
height: 190px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.search-content {
|
||||
display: flex;
|
||||
width: 500px;
|
||||
justify-content: space-around;
|
||||
padding: 35px 12px 0 0;
|
||||
margin-left: 20px;
|
||||
}
|
||||
}
|
||||
.table-content {
|
||||
margin: 12px 0 0 12px;
|
||||
|
||||
.ant-table-thead > tr > th {
|
||||
color: #909399;
|
||||
text-align: center;
|
||||
}
|
||||
.ant-table-tbody > tr > td {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
.add-content {
|
||||
display: flex;
|
||||
margin-left: 12px;
|
||||
margin-top: 20px;
|
||||
button:focus,
|
||||
button:focus-visible {
|
||||
outline: none;
|
||||
}
|
||||
}
|
||||
.user-mid-button {
|
||||
display: flex;
|
||||
margin-left: 12px;
|
||||
margin-top: 20px;
|
||||
button:focus,
|
||||
button:focus-visible {
|
||||
outline: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,242 +1,5 @@
|
||||
import "./index.scss";
|
||||
import { Select, Button, Table, Space, Tag, message, Modal } from "antd";
|
||||
|
||||
import {
|
||||
EditOutlined,
|
||||
DeleteOutlined,
|
||||
ExclamationCircleFilled,
|
||||
} from "@ant-design/icons";
|
||||
|
||||
import {
|
||||
getNoticeListApi,
|
||||
deleteNoticeInfoApi,
|
||||
} from "../../../../api/system/notice";
|
||||
|
||||
import { useEffect, useState } from "react";
|
||||
import { SearchOutlined, RedoOutlined } from "@ant-design/icons";
|
||||
|
||||
export default function Inform() {
|
||||
const [noticeInfo, setNoticeInfo] = useState<string>("");
|
||||
const [isNoticeOpen, setIsNoticeOpen] = useState<boolean>(false);
|
||||
const [listData, setListData] = useState([]);
|
||||
const [messageApi, contextHolder] = message.useMessage();
|
||||
const [queryParams, setQueryParams] = useState<QueryParamsType>({
|
||||
state: undefined,
|
||||
pageSize: undefined,
|
||||
pageNum: undefined,
|
||||
});
|
||||
const columns = [
|
||||
{
|
||||
title: "序号",
|
||||
dataIndex: "noticeId",
|
||||
key: "noticeId",
|
||||
render: (text: string) => <>{text ? text : "null"}</>,
|
||||
},
|
||||
{
|
||||
title: "公告标题",
|
||||
dataIndex: "noticeTitle",
|
||||
key: "noticeTitle",
|
||||
render: (text: string) => <>{text ? text : "null"}</>,
|
||||
},
|
||||
{
|
||||
title: "阅读状态",
|
||||
key: "state",
|
||||
dataIndex: "state",
|
||||
render: (text: string) => (
|
||||
<>
|
||||
{text === "1" ? (
|
||||
<Tag color="warning">已读</Tag>
|
||||
) : (
|
||||
<Tag color="error">未读</Tag>
|
||||
)}
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: "操作",
|
||||
key: "operate",
|
||||
dataIndex: "operate",
|
||||
render: (_: string, record: object) => (
|
||||
<div style={{ color: "#58aaff" }}>
|
||||
<Space>
|
||||
<EditOutlined />
|
||||
<a
|
||||
href="#"
|
||||
onClick={() => handleInfo(record)}
|
||||
style={{ color: " #58aaff" }}
|
||||
>
|
||||
详情
|
||||
</a>
|
||||
<DeleteOutlined />
|
||||
<a
|
||||
href="#"
|
||||
onClick={() => handleDel(record)}
|
||||
style={{ color: " #58aaff" }}
|
||||
>
|
||||
删除
|
||||
</a>
|
||||
</Space>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
interface QueryParamsType {
|
||||
state?: string;
|
||||
pageSize?: number;
|
||||
pageNum?: number;
|
||||
}
|
||||
|
||||
const getList = async (newQueryParams: object) => {
|
||||
try {
|
||||
const { code, data } = await getNoticeListApi(newQueryParams);
|
||||
if (code === 1000) {
|
||||
setListData(data.rows);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
};
|
||||
|
||||
const handleReset = async () => {
|
||||
setQueryParams({});
|
||||
getList({});
|
||||
};
|
||||
|
||||
const handleSearch = () => {
|
||||
getList(queryParams);
|
||||
};
|
||||
|
||||
const handleInfo = (record: any) => {
|
||||
setIsNoticeOpen(true);
|
||||
setNoticeInfo(record.noticeTitle);
|
||||
};
|
||||
|
||||
const handleInfoOk = () => {
|
||||
setIsNoticeOpen(false);
|
||||
};
|
||||
|
||||
const handleInfoCancel = () => {
|
||||
setIsNoticeOpen(false);
|
||||
};
|
||||
|
||||
const handleDel = async (record: any) => {
|
||||
Modal.confirm({
|
||||
title: `确定删除Id为-${record.noticeId}-, 名称为-${record.noticeTitle}-的岗位吗?`,
|
||||
icon: <ExclamationCircleFilled />,
|
||||
async onOk() {
|
||||
const { code } = await deleteNoticeInfoApi(record.noticeId);
|
||||
try {
|
||||
if (code === 1000) {
|
||||
messageApi.open({
|
||||
type: "success",
|
||||
content: "删除成功",
|
||||
});
|
||||
getList({});
|
||||
} else {
|
||||
messageApi.open({
|
||||
type: "error",
|
||||
content: "删除失败",
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
}
|
||||
},
|
||||
onCancel() {
|
||||
messageApi.open({
|
||||
type: "warning",
|
||||
content: "取消成功",
|
||||
});
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const handlePageChange = (page: number) => {
|
||||
setQueryParams({
|
||||
...queryParams,
|
||||
pageNum: page,
|
||||
});
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
getList(queryParams);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div id="content">
|
||||
<>
|
||||
<div className="right">
|
||||
<div className="search-content">
|
||||
<>
|
||||
<Space>
|
||||
<div>状态</div>
|
||||
<Select
|
||||
style={{ width: 220 }}
|
||||
placeholder="请选择状态"
|
||||
allowClear
|
||||
options={[
|
||||
{ value: "1", label: "已读" },
|
||||
{ value: "0", label: "未读" },
|
||||
]}
|
||||
value={queryParams.state}
|
||||
onChange={(value: any) =>
|
||||
setQueryParams({
|
||||
...queryParams,
|
||||
state: value,
|
||||
})
|
||||
}
|
||||
/>
|
||||
</Space>
|
||||
<Space>
|
||||
<div className="search-button">
|
||||
<Button type="primary" onClick={handleSearch}>
|
||||
<SearchOutlined />
|
||||
搜索
|
||||
</Button>
|
||||
</div>
|
||||
</Space>
|
||||
<Space>
|
||||
<div className="reset-button" onClick={handleReset}>
|
||||
<Button>
|
||||
<RedoOutlined />
|
||||
重置
|
||||
</Button>
|
||||
</div>
|
||||
</Space>
|
||||
</>
|
||||
</div>
|
||||
<Modal
|
||||
title="通知弹框"
|
||||
open={isNoticeOpen}
|
||||
onOk={handleInfoOk}
|
||||
onCancel={handleInfoCancel}
|
||||
footer={null}
|
||||
>
|
||||
<h1>{noticeInfo}</h1>
|
||||
</Modal>
|
||||
<div className="table-content">
|
||||
<>
|
||||
{contextHolder}
|
||||
<Table
|
||||
columns={columns}
|
||||
dataSource={listData}
|
||||
className="article-table"
|
||||
pagination={{
|
||||
onChange: handlePageChange,
|
||||
locale: {
|
||||
jump_to: "跳至",
|
||||
page: "页",
|
||||
},
|
||||
showQuickJumper: true,
|
||||
showTotal: (total, range) =>
|
||||
`第 ${range[0]}-${range[1]} 条,共 ${total} 条`,
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return(
|
||||
<div>公告1</div>
|
||||
)
|
||||
}
|
||||
5
src/view/system/notice/publish/index.tsx
Normal file
@@ -0,0 +1,5 @@
|
||||
export default function Inform() {
|
||||
return(
|
||||
<div>公告2</div>
|
||||
)
|
||||
}
|
||||
@@ -1,103 +0,0 @@
|
||||
#content {
|
||||
display: flex;
|
||||
border-top: 1px solid black;
|
||||
.dept-content {
|
||||
flex: 20%;
|
||||
padding: 35px 12px 0 0;
|
||||
height: calc(100vh - 85px);
|
||||
}
|
||||
|
||||
.left-dept {
|
||||
flex: 20%;
|
||||
padding: 35px 12px 0 0;
|
||||
height: calc(100vh - 85px);
|
||||
border: 1px solid red;
|
||||
border-top: 1px solid black;
|
||||
}
|
||||
.right {
|
||||
flex: 80%;
|
||||
height: 190px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.search-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 35px 12px 0 0;
|
||||
.content-top {
|
||||
display: flex;
|
||||
.input-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-right: 20px;
|
||||
width: 270px;
|
||||
div {
|
||||
width: 120px;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
:nth-child(3) {
|
||||
div {
|
||||
margin-right: -30px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.content-bottom {
|
||||
display: flex;
|
||||
margin-left: 12px;
|
||||
margin-top: 20px;
|
||||
div {
|
||||
margin-right: 10px;
|
||||
}
|
||||
.time-selector {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
div {
|
||||
width: 120px;
|
||||
font-weight: bold;
|
||||
}
|
||||
.time-picker {
|
||||
width: 400px;
|
||||
text-align: center;
|
||||
margin-left: -30px;
|
||||
margin-right: 25px;
|
||||
}
|
||||
}
|
||||
button:focus,
|
||||
button:focus-visible {
|
||||
outline: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
.table-content {
|
||||
margin: 12px 0 0 12px;
|
||||
|
||||
.ant-table-thead > tr > th {
|
||||
color: #909399;
|
||||
text-align: center;
|
||||
}
|
||||
.ant-table-tbody > tr > td {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
.add-content {
|
||||
display: flex;
|
||||
margin-left: 12px;
|
||||
margin-top: 20px;
|
||||
button:focus,
|
||||
button:focus-visible {
|
||||
outline: none;
|
||||
}
|
||||
}
|
||||
.user-mid-button {
|
||||
display: flex;
|
||||
margin-left: 12px;
|
||||
margin-top: 20px;
|
||||
button:focus,
|
||||
button:focus-visible {
|
||||
outline: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,473 +0,0 @@
|
||||
import "./index.scss";
|
||||
import {
|
||||
Input,
|
||||
Select,
|
||||
Button,
|
||||
Table,
|
||||
Space,
|
||||
Tag,
|
||||
message,
|
||||
Modal,
|
||||
Form,
|
||||
Row,
|
||||
Col,
|
||||
Radio,
|
||||
InputNumber,
|
||||
} from "antd";
|
||||
|
||||
import {
|
||||
EditOutlined,
|
||||
DeleteOutlined,
|
||||
ExclamationCircleFilled,
|
||||
} from "@ant-design/icons";
|
||||
|
||||
import {
|
||||
getPostListApi,
|
||||
addPostApi,
|
||||
editPostApi,
|
||||
deletePostApi,
|
||||
} from "../../../api/system/post";
|
||||
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { SearchOutlined, RedoOutlined, PlusOutlined } from "@ant-design/icons";
|
||||
|
||||
export default function Post() {
|
||||
const [form] = Form.useForm();
|
||||
const postIdList: number[] = [];
|
||||
const [echoData, setEchoData] = useState<QueryParamsType>({});
|
||||
const [listData, setListData] = useState([]);
|
||||
const [radioValue, setRadioValue] = useState(1);
|
||||
const [messageApi, contextHolder] = message.useMessage();
|
||||
const [modalTitle, setModalTitle] = useState<string>("");
|
||||
const [buttonType, setButtonType] = useState<string>("");
|
||||
const [isShowModal, setIsShowModal] = useState<boolean>(false);
|
||||
const [queryParams, setQueryParams] = useState<QueryParamsType>({
|
||||
postName: undefined,
|
||||
postCode: undefined,
|
||||
state: undefined,
|
||||
postSort: undefined,
|
||||
pageSize: undefined,
|
||||
pageNum: undefined,
|
||||
});
|
||||
const columns = [
|
||||
{
|
||||
title: "序号",
|
||||
dataIndex: "postId",
|
||||
key: "Id",
|
||||
render: (text: string) => <>{text ? text : "null"}</>,
|
||||
},
|
||||
{
|
||||
title: "岗位名称",
|
||||
dataIndex: "postName",
|
||||
key: "postName",
|
||||
render: (text: string) => <>{text ? text : "null"}</>,
|
||||
},
|
||||
{
|
||||
title: "岗位编码",
|
||||
dataIndex: "postCode",
|
||||
key: "postCode",
|
||||
render: (text: string) => <>{text ? text : "null"}</>,
|
||||
},
|
||||
{
|
||||
title: "排序",
|
||||
key: "postSort",
|
||||
dataIndex: "postSort",
|
||||
render: (text: string) => <>{text ? text : "--"}</>,
|
||||
},
|
||||
{
|
||||
title: "状态",
|
||||
key: "state",
|
||||
dataIndex: "state",
|
||||
render: (text: string) => (
|
||||
<>
|
||||
{text === "0" ? (
|
||||
<Tag color="processing">停用</Tag>
|
||||
) : (
|
||||
<Tag color="processing">正常</Tag>
|
||||
)}
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: "创建时间",
|
||||
key: "createTime",
|
||||
dataIndex: "createTime",
|
||||
render: (text: string) => <>{text ? text : "null"}</>,
|
||||
},
|
||||
{
|
||||
title: "操作",
|
||||
key: "operate",
|
||||
dataIndex: "operate",
|
||||
render: (_: string, record: object) => (
|
||||
<div style={{ color: "#58aaff" }}>
|
||||
<Space>
|
||||
<EditOutlined />
|
||||
<a
|
||||
href="#"
|
||||
onClick={() => handleEdit(record)}
|
||||
style={{ color: " #58aaff" }}
|
||||
>
|
||||
编辑
|
||||
</a>
|
||||
<DeleteOutlined />
|
||||
<a
|
||||
href="#"
|
||||
onClick={() => handleDel(record)}
|
||||
style={{ color: " #58aaff" }}
|
||||
>
|
||||
删除
|
||||
</a>
|
||||
</Space>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
interface QueryParamsType {
|
||||
postName?: string;
|
||||
postCode?: string;
|
||||
state?: string;
|
||||
postSort?: string;
|
||||
postId?: string;
|
||||
pageSize?: number;
|
||||
pageNum?: number;
|
||||
}
|
||||
|
||||
const getPostList = async (newQueryParams: object) => {
|
||||
try {
|
||||
const { code, data } = await getPostListApi(newQueryParams);
|
||||
if (code === 1000) {
|
||||
setListData(data.rows);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
};
|
||||
|
||||
const handleAdd = () => {
|
||||
setModalTitle("新增用户");
|
||||
setButtonType("ADD");
|
||||
setIsShowModal(true);
|
||||
};
|
||||
|
||||
const handleEdit = (data: any) => {
|
||||
setModalTitle("修改用户");
|
||||
setButtonType("EDIT");
|
||||
setIsShowModal(true);
|
||||
console.log(data);
|
||||
setEchoData({
|
||||
postId: data.postId,
|
||||
});
|
||||
handleEcho(data);
|
||||
};
|
||||
|
||||
const handleConfirm = () => {
|
||||
form.validateFields().then((values) => {
|
||||
console.log(values);
|
||||
console.log(buttonType);
|
||||
|
||||
if (buttonType === "ADD") {
|
||||
handleConfirmAdd(values);
|
||||
} else if (buttonType === "EDIT") {
|
||||
handleConfirmEdit(values);
|
||||
} else {
|
||||
messageApi.open({
|
||||
type: "error",
|
||||
content: "系统异常,请刷新后重试",
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const handleConfirmAdd = async (data: object) => {
|
||||
console.log(data);
|
||||
const { code } = await addPostApi(data);
|
||||
try {
|
||||
if (code === 1000) {
|
||||
messageApi.open({
|
||||
type: "success",
|
||||
content: "创建成功",
|
||||
});
|
||||
setQueryParams({});
|
||||
handleClear();
|
||||
} else {
|
||||
messageApi.open({
|
||||
type: "error",
|
||||
content: "岗位名称已经存在",
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
}
|
||||
};
|
||||
|
||||
const handleConfirmEdit = async (data: object) => {
|
||||
const editData = {
|
||||
...data,
|
||||
postId: echoData.postId,
|
||||
};
|
||||
console.log(editData);
|
||||
const { code } = await editPostApi(editData);
|
||||
try {
|
||||
if (code === 1000) {
|
||||
messageApi.open({
|
||||
type: "success",
|
||||
content: "修改成功",
|
||||
});
|
||||
setQueryParams({});
|
||||
handleClear();
|
||||
} else {
|
||||
messageApi.open({
|
||||
type: "error",
|
||||
content: "修改失败",
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
}
|
||||
};
|
||||
|
||||
const handleReset = async () => {
|
||||
setQueryParams({});
|
||||
getPostList({});
|
||||
};
|
||||
|
||||
const handleSearch = () => {
|
||||
getPostList(queryParams);
|
||||
};
|
||||
|
||||
const handleDel = async (record: any) => {
|
||||
Modal.confirm({
|
||||
title: `确定删除Id为-${record.postId}-, 岗位名称为-${record.postName}-的岗位吗?`,
|
||||
icon: <ExclamationCircleFilled />,
|
||||
async onOk() {
|
||||
const { code } = await deletePostApi(record.postId);
|
||||
try {
|
||||
if (code === 1000) {
|
||||
messageApi.open({
|
||||
type: "success",
|
||||
content: "删除成功",
|
||||
});
|
||||
setQueryParams({});
|
||||
} else {
|
||||
messageApi.open({
|
||||
type: "error",
|
||||
content: "删除失败",
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
}
|
||||
},
|
||||
onCancel() {
|
||||
messageApi.open({
|
||||
type: "warning",
|
||||
content: "取消成功",
|
||||
});
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const handleSearchValues = (e: any) => {
|
||||
const { name, value } = e.target;
|
||||
setQueryParams({ ...queryParams, [name]: value });
|
||||
};
|
||||
|
||||
const handlePageChange = (page: number) => {
|
||||
setQueryParams({
|
||||
...queryParams,
|
||||
pageNum: page,
|
||||
});
|
||||
};
|
||||
|
||||
const handleEcho = (data: any) => {
|
||||
const { postName, postCode, state, postSort } = data;
|
||||
form.setFieldsValue({
|
||||
postName,
|
||||
postCode,
|
||||
state,
|
||||
postSort,
|
||||
});
|
||||
};
|
||||
|
||||
const handleCancel = () => {
|
||||
handleClear();
|
||||
};
|
||||
|
||||
const handleClear = () => {
|
||||
form.resetFields();
|
||||
setIsShowModal(false);
|
||||
};
|
||||
|
||||
const onRadio = (e: any) => {
|
||||
setRadioValue(e.target.value);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
getPostList(queryParams);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div id="content">
|
||||
<>
|
||||
<div className="right">
|
||||
<div className="search-content">
|
||||
<>
|
||||
<div className="content-top">
|
||||
<div className="input-item">
|
||||
<div>岗位名称</div>
|
||||
<Input
|
||||
placeholder="请输入岗位名称"
|
||||
name="postName"
|
||||
allowClear
|
||||
value={queryParams.postName}
|
||||
onChange={handleSearchValues}
|
||||
/>
|
||||
</div>
|
||||
<div className="input-item">
|
||||
<div>岗位编码</div>
|
||||
<Input
|
||||
placeholder="请输入岗位编码"
|
||||
name="postCode"
|
||||
allowClear
|
||||
value={queryParams.postCode}
|
||||
onChange={handleSearchValues}
|
||||
/>
|
||||
</div>
|
||||
<div className="input-item">
|
||||
<div>状态</div>
|
||||
<Select
|
||||
style={{ width: 120 }}
|
||||
placeholder="用户状态"
|
||||
allowClear
|
||||
options={[
|
||||
{ value: "1", label: "正常" },
|
||||
{ value: "0", label: "停用" },
|
||||
]}
|
||||
value={queryParams.state}
|
||||
onChange={(value: any) =>
|
||||
setQueryParams({
|
||||
...queryParams,
|
||||
state: value,
|
||||
})
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="content-bottom">
|
||||
<div className="search-button">
|
||||
<Button type="primary" onClick={handleSearch}>
|
||||
<SearchOutlined />
|
||||
搜索
|
||||
</Button>
|
||||
</div>
|
||||
<div className="reset-button" onClick={handleReset}>
|
||||
<Button>
|
||||
<RedoOutlined />
|
||||
重置
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
</div>
|
||||
<div className="add-content">
|
||||
<>
|
||||
<Button type="primary" onClick={handleAdd}>
|
||||
<PlusOutlined />
|
||||
新增
|
||||
</Button>
|
||||
</>
|
||||
</div>
|
||||
<div className="table-content">
|
||||
<>
|
||||
{contextHolder}
|
||||
<Table
|
||||
columns={columns}
|
||||
dataSource={listData}
|
||||
className="article-table"
|
||||
pagination={{
|
||||
onChange: handlePageChange,
|
||||
locale: {
|
||||
jump_to: "跳至",
|
||||
page: "页",
|
||||
},
|
||||
showQuickJumper: true,
|
||||
showTotal: (total, range) =>
|
||||
`第 ${range[0]}-${range[1]} 条,共 ${total} 条`,
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
</div>
|
||||
<>
|
||||
{contextHolder}
|
||||
<Modal
|
||||
title={modalTitle}
|
||||
width={600}
|
||||
okText="确认"
|
||||
cancelText="取消"
|
||||
open={isShowModal}
|
||||
onOk={handleConfirm}
|
||||
onCancel={handleCancel}
|
||||
>
|
||||
<Form
|
||||
form={form}
|
||||
name="basic"
|
||||
initialValues={{ remember: true }}
|
||||
onFinish={handleConfirm}
|
||||
labelCol={{ span: 4 }}
|
||||
autoComplete="off"
|
||||
className="modal-form"
|
||||
>
|
||||
<Row>
|
||||
<Col span={24}>
|
||||
<Form.Item
|
||||
label="岗位名称"
|
||||
name="postName"
|
||||
rules={[{ required: true, message: "请输入岗位名称" }]}
|
||||
>
|
||||
<Input defaultValue={""} placeholder="请输入岗位名称" />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={24}>
|
||||
<Form.Item
|
||||
label="岗位编码"
|
||||
name="postCode"
|
||||
rules={[{ required: true, message: "请输入岗位编码" }]}
|
||||
>
|
||||
<Input defaultValue={""} placeholder="请输入岗位编码" />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={24}>
|
||||
<Form.Item
|
||||
label="显示顺序"
|
||||
name="postSort"
|
||||
rules={[{ required: false }]}
|
||||
>
|
||||
<InputNumber />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={24}>
|
||||
<Form.Item
|
||||
label="状态"
|
||||
name="state"
|
||||
rules={[
|
||||
{
|
||||
required: false,
|
||||
},
|
||||
]}
|
||||
>
|
||||
<Radio.Group onChange={onRadio} value={radioValue}>
|
||||
<Radio value="1">正常</Radio>
|
||||
<Radio value="0">停用</Radio>
|
||||
</Radio.Group>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
</Row>
|
||||
</Form>
|
||||
</Modal>
|
||||
</>
|
||||
</div>
|
||||
</>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,104 +0,0 @@
|
||||
#content {
|
||||
display: flex;
|
||||
border-top: 1px solid black;
|
||||
.dept-content {
|
||||
flex: 20%;
|
||||
padding: 35px 12px 0 0;
|
||||
height: calc(100vh - 85px);
|
||||
}
|
||||
|
||||
.left-dept {
|
||||
flex: 20%;
|
||||
padding: 35px 12px 0 0;
|
||||
height: calc(100vh - 85px);
|
||||
border: 1px solid red;
|
||||
border-top: 1px solid black;
|
||||
}
|
||||
.right-user {
|
||||
flex: 80%;
|
||||
height: 190px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.search-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 35px 12px 0 0;
|
||||
.content-top {
|
||||
display: flex;
|
||||
.input-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-right: 20px;
|
||||
width: 270px;
|
||||
div {
|
||||
width: 120px;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
:nth-child(3) {
|
||||
div {
|
||||
margin-right: -30px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.content-bottom {
|
||||
display: flex;
|
||||
margin-left: -20px;
|
||||
margin-top: 20px;
|
||||
div {
|
||||
margin-right: 10px;
|
||||
}
|
||||
.time-selector {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
div {
|
||||
width: 120px;
|
||||
font-weight: bold;
|
||||
}
|
||||
.time-picker {
|
||||
width: 400px;
|
||||
text-align: center;
|
||||
margin-left: -30px;
|
||||
margin-right: 25px;
|
||||
}
|
||||
}
|
||||
button:focus,
|
||||
button:focus-visible {
|
||||
outline: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
.table-content {
|
||||
margin: 12px 0 0 12px;
|
||||
|
||||
.ant-table-thead > tr > th {
|
||||
color: #909399;
|
||||
text-align: center;
|
||||
}
|
||||
.ant-table-tbody > tr > td {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
.add-content {
|
||||
display: flex;
|
||||
margin-left: 12px;
|
||||
margin-top: 20px;
|
||||
button:focus,
|
||||
button:focus-visible {
|
||||
outline: none;
|
||||
}
|
||||
}
|
||||
|
||||
.user-mid-button {
|
||||
display: flex;
|
||||
margin-left: 12px;
|
||||
margin-top: 20px;
|
||||
button:focus,
|
||||
button:focus-visible {
|
||||
outline: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,807 +1,7 @@
|
||||
import "./index.scss";
|
||||
import {
|
||||
Input,
|
||||
Tree,
|
||||
Select,
|
||||
DatePicker,
|
||||
Button,
|
||||
Table,
|
||||
Space,
|
||||
Tag,
|
||||
message,
|
||||
Modal,
|
||||
Form,
|
||||
Row,
|
||||
Col,
|
||||
TreeSelect,
|
||||
Radio,
|
||||
} from "antd";
|
||||
|
||||
import {
|
||||
EditOutlined,
|
||||
DeleteOutlined,
|
||||
ExclamationCircleFilled,
|
||||
} from "@ant-design/icons";
|
||||
|
||||
import {
|
||||
getUserListApi,
|
||||
deleteUserApi,
|
||||
getDeptTreeApi,
|
||||
addUserApi,
|
||||
getRoleListApi,
|
||||
getUserInfoApi,
|
||||
editUserApi,
|
||||
} from "../../../api/system/users";
|
||||
import dataLocale from "antd/es/date-picker/locale/zh_CN";
|
||||
import React, { useEffect, useState, useMemo } from "react";
|
||||
import { SearchOutlined, PlusOutlined } from "@ant-design/icons";
|
||||
|
||||
export default function User() {
|
||||
const postIdList: number[] = [];
|
||||
const [form] = Form.useForm();
|
||||
const [searchForm] = Form.useForm();
|
||||
const [echoId, setEchoId] = useState<any>();
|
||||
const [myTreeData, setMyTreeData] = useState<[]>([]);
|
||||
const [listData, setListData] = useState([]);
|
||||
const [radioValue, setRadioValue] = useState(1);
|
||||
const [searchTreeValue, setSearchTreeValue] = useState("");
|
||||
const [roleList, setRoleList] = useState<any[]>([]);
|
||||
const [messageApi, contextHolder] = message.useMessage();
|
||||
const [modalTitle, setModalTitle] = useState<string>("");
|
||||
const [buttonType, setButtonType] = useState<string>("");
|
||||
const [isShowModal, setIsShowModal] = useState<boolean>(false);
|
||||
const [autoExpandParent, setAutoExpandParent] = useState(true);
|
||||
const [expandedKeys, setExpandedKeys] = useState<React.Key[]>([
|
||||
100, 102, 101, 104,
|
||||
]);
|
||||
const [treeValue, setTreeValue] = useState<string>();
|
||||
const fieldNames = {
|
||||
label: "deptName",
|
||||
title: "deptName",
|
||||
value: "deptId",
|
||||
key: "deptName",
|
||||
};
|
||||
const [queryParams, setQueryParams] = useState<QueryParamsType>({
|
||||
deptId: undefined,
|
||||
userName: undefined,
|
||||
phoneNumber: undefined,
|
||||
state: undefined,
|
||||
startTime: undefined,
|
||||
endTime: undefined,
|
||||
pageNum: undefined,
|
||||
pageSize: undefined,
|
||||
});
|
||||
const columns = [
|
||||
{
|
||||
title: "序号",
|
||||
dataIndex: "userId",
|
||||
key: "Id",
|
||||
render: (text: string) => <>{text ? text : "null"}</>,
|
||||
},
|
||||
{
|
||||
title: "用户名称",
|
||||
dataIndex: "userName",
|
||||
key: "userName",
|
||||
render: (text: string) => <>{text ? text : "null"}</>,
|
||||
},
|
||||
{
|
||||
title: "用户昵称",
|
||||
dataIndex: "nickName",
|
||||
key: "nikeName",
|
||||
render: (text: string) => <>{text ? text : "null"}</>,
|
||||
},
|
||||
{
|
||||
title: "部门",
|
||||
key: "deptId",
|
||||
dataIndex: "deptName",
|
||||
render: (text: string) => <>{text ? text : "--"}</>,
|
||||
},
|
||||
{
|
||||
title: "手机号码",
|
||||
key: "phoneNumber",
|
||||
dataIndex: "phoneNumber",
|
||||
render: (text: string) => <>{text ? text : "--"}</>,
|
||||
},
|
||||
{
|
||||
title: "状态",
|
||||
key: "state",
|
||||
dataIndex: "state",
|
||||
render: (text: string) => (
|
||||
<>
|
||||
{text === "0" ? (
|
||||
<Tag color="processing">停用</Tag>
|
||||
) : (
|
||||
<Tag color="processing">正常</Tag>
|
||||
)}
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: "创建时间",
|
||||
key: "createTime",
|
||||
dataIndex: "createTime",
|
||||
render: (text: string) => <>{text ? text : "null"}</>,
|
||||
},
|
||||
{
|
||||
title: "操作",
|
||||
key: "operate",
|
||||
dataIndex: "operate",
|
||||
render: (_: string, record: object) => (
|
||||
<div style={{ color: "#58aaff" }}>
|
||||
<Space>
|
||||
<EditOutlined />
|
||||
<a
|
||||
href="#"
|
||||
onClick={() => handleEdit(record)}
|
||||
style={{ color: " #58aaff" }}
|
||||
>
|
||||
编辑
|
||||
</a>
|
||||
<DeleteOutlined />
|
||||
<a
|
||||
href="#"
|
||||
onClick={() => handleDel(record)}
|
||||
style={{ color: " #58aaff" }}
|
||||
>
|
||||
删除
|
||||
</a>
|
||||
</Space>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
interface AddUserType {
|
||||
email: string;
|
||||
nickName: string;
|
||||
password: string;
|
||||
phoneNumber: string;
|
||||
postIds: number[];
|
||||
roleIds: number[];
|
||||
sex: string;
|
||||
state: string;
|
||||
userName: string;
|
||||
}
|
||||
|
||||
interface QueryParamsType {
|
||||
deptId?: number;
|
||||
userName?: string;
|
||||
phoneNumber?: string;
|
||||
state?: string;
|
||||
startTime?: string | any;
|
||||
endTime?: string | any;
|
||||
pageNum?: number;
|
||||
pageSize?: number;
|
||||
}
|
||||
|
||||
let addUserParams: AddUserType = {
|
||||
email: "",
|
||||
nickName: "",
|
||||
password: "",
|
||||
phoneNumber: "",
|
||||
postIds: [],
|
||||
roleIds: [],
|
||||
sex: "",
|
||||
state: "",
|
||||
userName: "",
|
||||
};
|
||||
|
||||
const getDeptTreeData = async () => {
|
||||
try {
|
||||
const { code, data } = await getDeptTreeApi();
|
||||
if (code === 1000) {
|
||||
setMyTreeData(data);
|
||||
handleLoopPostList(data);
|
||||
setExpandedKeys(postIdList);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
};
|
||||
|
||||
const getUserList = async (newQueryParams: object) => {
|
||||
try {
|
||||
const { code, data } = await getUserListApi(newQueryParams);
|
||||
if (code === 1000) {
|
||||
setListData(data.rows);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
};
|
||||
|
||||
const getUserInfo = async () => {
|
||||
try {
|
||||
const { code, data } = await getUserInfoApi(echoId);
|
||||
if (code === 1000) {
|
||||
handleEcho(data);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
};
|
||||
|
||||
const getRoleList = async () => {
|
||||
try {
|
||||
const { code, data } = await getRoleListApi();
|
||||
if (code === 1000) {
|
||||
setRoleList(data.rows);
|
||||
}
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
}
|
||||
};
|
||||
|
||||
const handleAdd = () => {
|
||||
setModalTitle("新增用户");
|
||||
setButtonType("ADD");
|
||||
setIsShowModal(true);
|
||||
};
|
||||
|
||||
const handleEdit = (echoData: any) => {
|
||||
setModalTitle("修改用户");
|
||||
setButtonType("EDIT");
|
||||
setIsShowModal(true);
|
||||
setEchoId(echoData.userId);
|
||||
};
|
||||
|
||||
const handleConfirm = () => {
|
||||
form.validateFields().then((values) => {
|
||||
Object.keys(values).forEach(
|
||||
(key) => values[key] === undefined && delete values[key]
|
||||
);
|
||||
addUserParams = {
|
||||
...addUserParams,
|
||||
...values,
|
||||
userId: echoId,
|
||||
};
|
||||
if (buttonType === "ADD") {
|
||||
handleAddUser();
|
||||
} else if (buttonType === "EDIT") {
|
||||
handleEditUser();
|
||||
} else {
|
||||
messageApi.open({
|
||||
type: "error",
|
||||
content: "系统异常,请刷新后重试",
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const handleAddUser = async () => {
|
||||
const { code } = await addUserApi(addUserParams);
|
||||
try {
|
||||
if (code === 1000) {
|
||||
messageApi.open({
|
||||
type: "success",
|
||||
content: "创建成功",
|
||||
});
|
||||
setQueryParams({});
|
||||
handleClear();
|
||||
} else {
|
||||
messageApi.open({
|
||||
type: "error",
|
||||
content: "用户名已经存在",
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
}
|
||||
};
|
||||
|
||||
const handleEditUser = async () => {
|
||||
const { code } = await editUserApi(addUserParams);
|
||||
try {
|
||||
if (code === 1000) {
|
||||
messageApi.open({
|
||||
type: "success",
|
||||
content: "修改成功",
|
||||
});
|
||||
setQueryParams({});
|
||||
handleClear();
|
||||
} else {
|
||||
messageApi.open({
|
||||
type: "error",
|
||||
content: "修改失败",
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
}
|
||||
};
|
||||
|
||||
const handleReset = async () => {
|
||||
searchForm.resetFields();
|
||||
setQueryParams({});
|
||||
getUserList({});
|
||||
};
|
||||
|
||||
const handleSearch = () => {
|
||||
getUserList(queryParams);
|
||||
};
|
||||
|
||||
const handleDel = async (record: any) => {
|
||||
Modal.confirm({
|
||||
title: `确定删除Id为-${record.userId}-, 用户名为-${record.userName}-的用户吗?`,
|
||||
icon: <ExclamationCircleFilled />,
|
||||
async onOk() {
|
||||
const { code } = await deleteUserApi(record.userId);
|
||||
try {
|
||||
if (code === 1000) {
|
||||
messageApi.open({
|
||||
type: "success",
|
||||
content: "删除成功",
|
||||
});
|
||||
setQueryParams({});
|
||||
} else {
|
||||
messageApi.open({
|
||||
type: "error",
|
||||
content: "删除失败",
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
}
|
||||
},
|
||||
onCancel() {
|
||||
messageApi.open({
|
||||
type: "warning",
|
||||
content: "取消成功",
|
||||
});
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const handleTimePikerValue = (_: any, dates: string[]) => {
|
||||
setQueryParams({
|
||||
...queryParams,
|
||||
startTime: dates[0],
|
||||
endTime: dates[1],
|
||||
});
|
||||
searchForm.setFieldsValue({ dataTime: [dates[0], dates[1]] });
|
||||
};
|
||||
|
||||
const handleSearchValues = (e: any) => {
|
||||
const { name, value } = e.target;
|
||||
setQueryParams({ ...queryParams, [name]: value });
|
||||
};
|
||||
|
||||
const handlePageChange = (page: number) => {
|
||||
setQueryParams({
|
||||
...queryParams,
|
||||
pageNum: page,
|
||||
});
|
||||
};
|
||||
|
||||
const handleTreeSelect = (deptId: any) => {
|
||||
console.log(queryParams);
|
||||
getUserList({
|
||||
...queryParams,
|
||||
deptId: deptId[0],
|
||||
});
|
||||
};
|
||||
|
||||
const handleEcho = (data: any) => {
|
||||
const { userName, nickName, sex, state, phoneNumber, deptId, email } =
|
||||
data.user;
|
||||
const { postIds, roleIds } = data;
|
||||
form.setFieldsValue({
|
||||
userName,
|
||||
nickName,
|
||||
state,
|
||||
phoneNumber,
|
||||
sex,
|
||||
deptId,
|
||||
email,
|
||||
postIds,
|
||||
roleIds,
|
||||
});
|
||||
};
|
||||
|
||||
const handleCancel = () => {
|
||||
handleClear();
|
||||
};
|
||||
|
||||
const handleClear = () => {
|
||||
form.resetFields();
|
||||
setIsShowModal(false);
|
||||
};
|
||||
|
||||
const handleExpandKeys = (key: string, data: object[]) => {
|
||||
const filterRes = new RegExp(key, "i");
|
||||
data.forEach((item: any) => {
|
||||
if (filterRes.test(item?.title?.props?.children)) {
|
||||
postIdList.push(item.key);
|
||||
}
|
||||
item.children ? handleExpandKeys(key, item.children) : "";
|
||||
});
|
||||
};
|
||||
|
||||
const handleLoopPostList = (loopData: object[]) => {
|
||||
loopData.forEach((item: any) => {
|
||||
if (item?.deptId) {
|
||||
const flag = postIdList.some((someItem) => {
|
||||
someItem === item.deptId;
|
||||
});
|
||||
if (!flag) {
|
||||
postIdList.push(item.deptId);
|
||||
}
|
||||
}
|
||||
item.children ? handleLoopPostList(item.children) : "";
|
||||
});
|
||||
};
|
||||
|
||||
const onRadio = (e: any) => {
|
||||
setRadioValue(e.target.value);
|
||||
};
|
||||
|
||||
const onTreeSelect = (newValue: string) => {
|
||||
setTreeValue(newValue);
|
||||
};
|
||||
|
||||
const onTreeSearch = (e?: any) => {
|
||||
const { value } = e.target ? e.target : null;
|
||||
setSearchTreeValue(value);
|
||||
handleExpandKeys(value, treeData);
|
||||
setExpandedKeys(postIdList);
|
||||
setAutoExpandParent(true);
|
||||
};
|
||||
|
||||
const onExpand = (newExpandedKeys: React.Key[]) => {
|
||||
console.log(newExpandedKeys);
|
||||
setExpandedKeys(newExpandedKeys);
|
||||
setAutoExpandParent(false);
|
||||
};
|
||||
|
||||
const treeData = useMemo(() => {
|
||||
const loop = (data: any[]): any[] =>
|
||||
data.map((item) => {
|
||||
const strTitle = item.deptName as string;
|
||||
const index = strTitle.indexOf(searchTreeValue);
|
||||
const beforeStr = strTitle.substring(0, index);
|
||||
const afterStr = strTitle.slice(index + searchTreeValue.length);
|
||||
const title =
|
||||
index > -1 ? (
|
||||
<span>
|
||||
{beforeStr}
|
||||
<span className="site-tree-search-value">{searchTreeValue}</span>
|
||||
{afterStr}
|
||||
</span>
|
||||
) : (
|
||||
<span>{strTitle}</span>
|
||||
);
|
||||
if (item.children) {
|
||||
return { title, key: item.deptId, children: loop(item.children) };
|
||||
}
|
||||
return {
|
||||
title,
|
||||
key: item.deptId,
|
||||
};
|
||||
});
|
||||
return loop(myTreeData);
|
||||
}, [myTreeData]);
|
||||
|
||||
useEffect(() => {
|
||||
getDeptTreeData();
|
||||
getRoleList();
|
||||
getUserInfo();
|
||||
}, [echoId]);
|
||||
|
||||
useEffect(() => {
|
||||
getUserList({});
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div id="content">
|
||||
<div className="dept-content">
|
||||
<Input
|
||||
allowClear
|
||||
style={{ marginBottom: 8 }}
|
||||
prefix={<SearchOutlined />}
|
||||
placeholder="请输入部门名称"
|
||||
onChange={onTreeSearch}
|
||||
/>
|
||||
<Tree
|
||||
onExpand={onExpand}
|
||||
defaultExpandAll={true}
|
||||
expandedKeys={expandedKeys}
|
||||
autoExpandParent={autoExpandParent}
|
||||
treeData={treeData}
|
||||
onSelect={handleTreeSelect}
|
||||
/>
|
||||
</div>
|
||||
<>
|
||||
<div className="right-user">
|
||||
<Form
|
||||
layout="inline"
|
||||
form={searchForm}
|
||||
onFinish={handleSearch}
|
||||
style={{ fontWeight: "700", marginLeft: 12, marginTop: 23 }}
|
||||
>
|
||||
<Form.Item
|
||||
label="用户名称"
|
||||
name="userName"
|
||||
style={{ width: 300 + "px", marginTop: "10px" }}
|
||||
>
|
||||
<Input
|
||||
placeholder="请输入用户名称"
|
||||
name="userName"
|
||||
allowClear
|
||||
value={queryParams.userName}
|
||||
onChange={handleSearchValues}
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label="手机号码"
|
||||
name="phoneNumber"
|
||||
style={{ width: 300 + "px", marginTop: "10px" }}
|
||||
>
|
||||
<Input
|
||||
placeholder="请输入手机号码"
|
||||
name="phoneNumber"
|
||||
allowClear
|
||||
value={queryParams.phoneNumber}
|
||||
onChange={handleSearchValues}
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item label="状态" name="state" style={{ marginTop: "10px" }}>
|
||||
<Select
|
||||
style={{ width: 250 }}
|
||||
placeholder="用户状态"
|
||||
allowClear
|
||||
options={[
|
||||
{ value: "1", label: "正常" },
|
||||
{ value: "0", label: "停用" },
|
||||
]}
|
||||
value={queryParams.state}
|
||||
onChange={(value: any) =>
|
||||
setQueryParams({
|
||||
...queryParams,
|
||||
state: value,
|
||||
})
|
||||
}
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label="创建时间"
|
||||
name="dateTime"
|
||||
style={{ marginTop: "10px" }}
|
||||
>
|
||||
<DatePicker.RangePicker
|
||||
locale={dataLocale}
|
||||
showTime
|
||||
format="YYYY-MM-DD HH:mm:ss"
|
||||
onChange={handleTimePikerValue}
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item style={{ marginTop: "10px" }}>
|
||||
<Button
|
||||
type="primary"
|
||||
htmlType="submit"
|
||||
style={{ marginLeft: 20 + "px" }}
|
||||
>
|
||||
搜索
|
||||
</Button>
|
||||
</Form.Item>
|
||||
<Form.Item style={{ marginTop: "10px" }}>
|
||||
<Button onClick={handleReset}>重置</Button>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
|
||||
<div className="add-content">
|
||||
<>
|
||||
<Button type="primary" onClick={handleAdd}>
|
||||
<PlusOutlined />
|
||||
新增
|
||||
</Button>
|
||||
</>
|
||||
</div>
|
||||
<div className="table-content">
|
||||
<>
|
||||
{contextHolder}
|
||||
<Table
|
||||
columns={columns}
|
||||
dataSource={listData}
|
||||
className="article-table"
|
||||
pagination={{
|
||||
onChange: handlePageChange,
|
||||
locale: {
|
||||
jump_to: "跳至",
|
||||
page: "页",
|
||||
},
|
||||
showQuickJumper: true,
|
||||
showTotal: (total, range) =>
|
||||
`第 ${range[0]}-${range[1]} 条,共 ${total} 条`,
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
</div>
|
||||
<>
|
||||
{contextHolder}
|
||||
<Modal
|
||||
title={modalTitle}
|
||||
width={700}
|
||||
okText="确认"
|
||||
cancelText="取消"
|
||||
open={isShowModal}
|
||||
onOk={handleConfirm}
|
||||
onCancel={handleCancel}
|
||||
>
|
||||
<Form
|
||||
form={form}
|
||||
name="basic"
|
||||
initialValues={{ remember: true }}
|
||||
labelCol={{ span: 6 }}
|
||||
onFinish={handleConfirm}
|
||||
autoComplete="off"
|
||||
className="modal-form"
|
||||
>
|
||||
<Row>
|
||||
<Col span={12}>
|
||||
<Form.Item
|
||||
label="用户名称"
|
||||
name="userName"
|
||||
rules={[{ required: true, message: "请输入用户名称" }]}
|
||||
>
|
||||
<Input defaultValue={""} placeholder="请输入用户名称" />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<Form.Item
|
||||
label="用户昵称"
|
||||
name="nickName"
|
||||
rules={[{ required: true, message: "请输入用户昵称" }]}
|
||||
>
|
||||
<Input defaultValue={""} placeholder="请输入用户昵称" />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<Form.Item
|
||||
label="用户性别"
|
||||
name="sex"
|
||||
rules={[{ required: false }]}
|
||||
>
|
||||
<Select
|
||||
placeholder="请选择用户性别"
|
||||
options={[
|
||||
{ value: "0", label: "男" },
|
||||
{ value: "1", label: "女" },
|
||||
{ value: "2", label: "未知" },
|
||||
]}
|
||||
/>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<Form.Item
|
||||
label="用户密码"
|
||||
name="password"
|
||||
rules={[{ required: true, message: "请输入用户密码" }]}
|
||||
>
|
||||
<Input.Password
|
||||
defaultValue={""}
|
||||
placeholder="请输入密码"
|
||||
/>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<Form.Item
|
||||
label="归属部门"
|
||||
name="deptId"
|
||||
rules={[{ required: false }]}
|
||||
>
|
||||
<TreeSelect
|
||||
showSearch
|
||||
style={{ width: "100%" }}
|
||||
value={treeValue}
|
||||
dropdownStyle={{ maxHeight: 400, overflow: "auto" }}
|
||||
placeholder="请选择"
|
||||
allowClear
|
||||
fieldNames={fieldNames}
|
||||
treeDefaultExpandAll
|
||||
onChange={onTreeSelect}
|
||||
treeData={myTreeData}
|
||||
/>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<Form.Item
|
||||
label="手机号码"
|
||||
name="phoneNumber"
|
||||
rules={[{ required: false }]}
|
||||
>
|
||||
<Input placeholder="请输入手机号码" />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<Form.Item
|
||||
label="邮箱"
|
||||
name="email"
|
||||
rules={[{ required: false }]}
|
||||
>
|
||||
<Input defaultValue={""} placeholder="请输入邮箱" />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<Form.Item
|
||||
label="状态"
|
||||
name="state"
|
||||
rules={[
|
||||
{
|
||||
required: false,
|
||||
message: "Please input your password!",
|
||||
},
|
||||
]}
|
||||
>
|
||||
<Radio.Group onChange={onRadio} value={radioValue}>
|
||||
<Radio value="1">正常</Radio>
|
||||
<Radio value="0">停用</Radio>
|
||||
</Radio.Group>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<Form.Item
|
||||
label="岗位"
|
||||
name="postIds"
|
||||
rules={[
|
||||
{
|
||||
required: false,
|
||||
message: "Please input your password!",
|
||||
},
|
||||
]}
|
||||
>
|
||||
<Select
|
||||
mode="multiple"
|
||||
defaultValue={[]}
|
||||
options={[
|
||||
{ value: "董事长", label: "董事长" },
|
||||
{ value: "项目经理", label: "项目经理" },
|
||||
{ value: "人力资源", label: "人力资源" },
|
||||
{ value: "普通员工", label: "普通员工" },
|
||||
]}
|
||||
placeholder="请选择岗位"
|
||||
/>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<Form.Item
|
||||
label="角色"
|
||||
name="roleIds"
|
||||
rules={[
|
||||
{
|
||||
required: false,
|
||||
message: "Please input your password!",
|
||||
},
|
||||
]}
|
||||
>
|
||||
<Select mode="multiple" placeholder="请选择角色">
|
||||
{roleList.map((item) => (
|
||||
<Select.Option key={item.roleId} value={item.roleId}>
|
||||
{item.roleName}
|
||||
</Select.Option>
|
||||
))}
|
||||
</Select>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={24}>
|
||||
<Form.Item
|
||||
label="备注"
|
||||
labelCol={{ span: 3 }}
|
||||
rules={[
|
||||
{
|
||||
required: false,
|
||||
message: "Please input your password!",
|
||||
},
|
||||
]}
|
||||
>
|
||||
<Input.TextArea placeholder="请输入内容" />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
</Row>
|
||||
</Form>
|
||||
</Modal>
|
||||
</>
|
||||
</div>
|
||||
</>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return(
|
||||
<div>user</div>
|
||||
)
|
||||
}
|
||||
@@ -1,15 +1,21 @@
|
||||
import { defineConfig } from 'vite'
|
||||
import path from 'path'
|
||||
import react from '@vitejs/plugin-react'
|
||||
import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({
|
||||
base: './',
|
||||
plugins: [
|
||||
react(),
|
||||
createSvgIconsPlugin({
|
||||
iconDirs: [path.resolve(process.cwd(),'src/assets/svg')],
|
||||
symbolId: 'icon-[dir]-[name]'
|
||||
})
|
||||
],
|
||||
resolve: {
|
||||
alias: {
|
||||
'@': 'src/'
|
||||
'@': path.resolve(__dirname, 'src')
|
||||
}
|
||||
},
|
||||
build: {
|
||||
|
||||