feat: login

This commit is contained in:
2025-09-09 16:58:30 +08:00
parent d6457f59f7
commit f33f597a9a
41 changed files with 10998 additions and 3594 deletions

View File

@@ -1,20 +1,20 @@
// https://umijs.org/config/
import { join } from 'node:path';
import { defineConfig } from '@umijs/max';
import defaultSettings from './defaultSettings';
import proxy from './proxy';
import { join } from "node:path";
import { defineConfig } from "@umijs/max";
import defaultSettings from "./defaultSettings";
import proxy from "./proxy";
import routes from './routes';
import routes from "./routes";
const { UMI_ENV = 'dev' } = process.env;
const { UMI_ENV = "dev" } = process.env;
/**
* @name 使用公共路径
* @description 部署时的路径,如果部署在非根目录下,需要配置这个变量
* @doc https://umijs.org/docs/api/config#publicpath
*/
const PUBLIC_PATH: string = '/';
const PUBLIC_PATH: string = "/";
export default defineConfig({
/**
@@ -83,7 +83,7 @@ export default defineConfig({
* @name layout 插件
* @doc https://umijs.org/docs/max/layout-menu
*/
title: 'Ant Design Pro',
title: "Ant Design Pro",
layout: {
locale: true,
...defaultSettings,
@@ -94,8 +94,8 @@ export default defineConfig({
* @doc https://umijs.org/docs/max/moment2dayjs
*/
moment2dayjs: {
preset: 'antd',
plugins: ['duration'],
preset: "antd",
plugins: ["duration"],
},
/**
* @name 国际化插件
@@ -103,7 +103,7 @@ export default defineConfig({
*/
locale: {
// default zh-CN
default: 'zh-CN',
default: "zh-CN",
antd: true,
// default true, when it is true, will use `navigator.language` overwrite default
baseNavigator: true,
@@ -119,7 +119,7 @@ export default defineConfig({
theme: {
cssVar: true,
token: {
fontFamily: 'AlibabaSans, sans-serif',
fontFamily: "AlibabaSans, sans-serif",
},
},
},
@@ -142,10 +142,10 @@ export default defineConfig({
*/
headScripts: [
// 解决首次加载时白屏的问题
{ src: join(PUBLIC_PATH, 'scripts/loading.js'), async: true },
{ src: join(PUBLIC_PATH, "scripts/loading.js"), async: true },
],
//================ pro 插件配置 =================
presets: ['umi-presets-pro'],
presets: ["umi-presets-pro"],
/**
* @name openAPI 插件的配置
* @description 基于 openapi 的规范生成serve 和mock能减少很多样板代码
@@ -154,20 +154,19 @@ export default defineConfig({
openAPI: [
{
requestLibPath: "import { request } from '@umijs/max'",
// 或者使用在线的版本
// schemaPath: "https://gw.alipayobjects.com/os/antfincdn/M%24jrzTTYJN/oneapi.json"
schemaPath: join(__dirname, 'oneapi.json'),
schemaPath: join(__dirname, "oneapi/prodapi.json"),
mock: false,
projectName: "prodApi",
},
{
requestLibPath: "import { request } from '@umijs/max'",
schemaPath:
'https://gw.alipayobjects.com/os/antfincdn/CA1dOm%2631B/openapi.json',
projectName: 'swagger',
},
// {schemaPath: "./docs/apifox-api.json",
// requestLibPath: "import { request } from '@umijs/max'",
// schemaPath: join(__dirname, "oneapi.json"),
// projectName: "login",
// },
],
mock: {
include: ['mock/**/*', 'src/pages/**/_mock.ts'],
include: ["mock/**/*", "src/pages/**/_mock.ts"],
},
/**
* @name 是否开启 mako
@@ -179,6 +178,6 @@ export default defineConfig({
requestRecord: {},
exportStatic: {},
define: {
'process.env.CI': process.env.CI,
"process.env.CI": process.env.CI,
},
});

View File

@@ -1,4 +1,4 @@
import type { ProLayoutProps } from '@ant-design/pro-components';
import type { ProLayoutProps } from "@ant-design/pro-components";
/**
* @name
@@ -7,18 +7,18 @@ const Settings: ProLayoutProps & {
pwa?: boolean;
logo?: string;
} = {
navTheme: 'light',
navTheme: "light",
// 拂晓蓝
colorPrimary: '#1890ff',
layout: 'mix',
contentWidth: 'Fluid',
colorPrimary: "#1890ff",
layout: "mix",
contentWidth: "Fluid",
fixedHeader: false,
fixSiderbar: true,
colorWeak: false,
title: 'Ant Design Pro',
title: "tashow - 管理后台",
pwa: true,
logo: 'https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg',
iconfontUrl: '',
logo: "https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg",
iconfontUrl: "",
token: {
// 参见ts声明demo 见文档通过token 修改样式
//https://procomponents.ant.design/components/layout#%E9%80%9A%E8%BF%87-token-%E4%BF%AE%E6%94%B9%E6%A0%B7%E5%BC%8F

View File

@@ -1,593 +0,0 @@
{
"openapi": "3.0.1",
"info": {
"title": "Ant Design Pro",
"version": "1.0.0"
},
"servers": [
{
"url": "http://localhost:8000/"
},
{
"url": "https://localhost:8000/"
}
],
"paths": {
"/api/currentUser": {
"get": {
"tags": ["api"],
"description": "获取当前的用户",
"operationId": "currentUser",
"responses": {
"200": {
"description": "Success",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CurrentUser"
}
}
}
},
"401": {
"description": "Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
}
}
}
},
"x-swagger-router-controller": "api"
},
"/api/login/captcha": {
"post": {
"description": "发送验证码",
"operationId": "getFakeCaptcha",
"tags": ["login"],
"parameters": [
{
"name": "phone",
"in": "query",
"description": "手机号",
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "Success",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/FakeCaptcha"
}
}
}
}
}
}
},
"/api/login/outLogin": {
"post": {
"description": "登录接口",
"operationId": "outLogin",
"tags": ["login"],
"responses": {
"200": {
"description": "Success",
"content": {
"application/json": {
"schema": {
"type": "object"
}
}
}
},
"401": {
"description": "Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
}
}
}
},
"x-swagger-router-controller": "api"
},
"/api/login/account": {
"post": {
"tags": ["login"],
"description": "登录接口",
"operationId": "login",
"requestBody": {
"description": "登录系统",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/LoginParams"
}
}
},
"required": true
},
"responses": {
"200": {
"description": "Success",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/LoginResult"
}
}
}
},
"401": {
"description": "Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
}
}
},
"x-codegen-request-body-name": "body"
},
"x-swagger-router-controller": "api"
},
"/api/notices": {
"summary": "getNotices",
"description": "NoticeIconItem",
"get": {
"tags": ["api"],
"operationId": "getNotices",
"responses": {
"200": {
"description": "Success",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/NoticeIconList"
}
}
}
}
}
}
},
"/api/rule": {
"get": {
"tags": ["rule"],
"description": "获取规则列表",
"operationId": "rule",
"parameters": [
{
"name": "current",
"in": "query",
"description": "当前的页码",
"schema": {
"type": "number"
}
},
{
"name": "pageSize",
"in": "query",
"description": "页面的容量",
"schema": {
"type": "number"
}
}
],
"responses": {
"200": {
"description": "Success",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/RuleList"
}
}
}
},
"401": {
"description": "Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
}
}
}
},
"post": {
"tags": ["rule"],
"description": "新建规则",
"operationId": "addRule",
"responses": {
"200": {
"description": "Success",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/RuleListItem"
}
}
}
},
"401": {
"description": "Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
}
}
}
},
"put": {
"tags": ["rule"],
"description": "新建规则",
"operationId": "updateRule",
"responses": {
"200": {
"description": "Success",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/RuleListItem"
}
}
}
},
"401": {
"description": "Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
}
}
}
},
"delete": {
"tags": ["rule"],
"description": "删除规则",
"operationId": "removeRule",
"responses": {
"200": {
"description": "Success",
"content": {
"application/json": {
"schema": {
"type": "object"
}
}
}
},
"401": {
"description": "Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
}
}
}
},
"x-swagger-router-controller": "api"
},
"/swagger": {
"x-swagger-pipe": "swagger_raw"
}
},
"components": {
"schemas": {
"CurrentUser": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"avatar": {
"type": "string"
},
"userid": {
"type": "string"
},
"email": {
"type": "string"
},
"signature": {
"type": "string"
},
"title": {
"type": "string"
},
"group": {
"type": "string"
},
"tags": {
"type": "array",
"items": {
"type": "object",
"properties": {
"key": {
"type": "string"
},
"label": {
"type": "string"
}
}
}
},
"notifyCount": {
"type": "integer",
"format": "int32"
},
"unreadCount": {
"type": "integer",
"format": "int32"
},
"country": {
"type": "string"
},
"access": {
"type": "string"
},
"geographic": {
"type": "object",
"properties": {
"province": {
"type": "object",
"properties": {
"label": {
"type": "string"
},
"key": {
"type": "string"
}
}
},
"city": {
"type": "object",
"properties": {
"label": {
"type": "string"
},
"key": {
"type": "string"
}
}
}
}
},
"address": {
"type": "string"
},
"phone": {
"type": "string"
}
}
},
"LoginResult": {
"type": "object",
"properties": {
"status": {
"type": "string"
},
"type": {
"type": "string"
},
"currentAuthority": {
"type": "string"
}
}
},
"PageParams": {
"type": "object",
"properties": {
"current": {
"type": "number"
},
"pageSize": {
"type": "number"
}
}
},
"RuleListItem": {
"type": "object",
"properties": {
"key": {
"type": "integer",
"format": "int32"
},
"disabled": {
"type": "boolean"
},
"href": {
"type": "string"
},
"avatar": {
"type": "string"
},
"name": {
"type": "string"
},
"owner": {
"type": "string"
},
"desc": {
"type": "string"
},
"callNo": {
"type": "integer",
"format": "int32"
},
"status": {
"type": "integer",
"format": "int32"
},
"updatedAt": {
"type": "string",
"format": "datetime"
},
"createdAt": {
"type": "string",
"format": "datetime"
},
"progress": {
"type": "integer",
"format": "int32"
}
}
},
"RuleList": {
"type": "object",
"properties": {
"data": {
"type": "array",
"items": {
"$ref": "#/components/schemas/RuleListItem"
}
},
"total": {
"type": "integer",
"description": "列表的内容总数",
"format": "int32"
},
"success": {
"type": "boolean"
}
}
},
"FakeCaptcha": {
"type": "object",
"properties": {
"code": {
"type": "integer",
"format": "int32"
},
"status": {
"type": "string"
}
}
},
"LoginParams": {
"type": "object",
"properties": {
"username": {
"type": "string"
},
"password": {
"type": "string"
},
"autoLogin": {
"type": "boolean"
},
"type": {
"type": "string"
}
}
},
"ErrorResponse": {
"required": ["errorCode"],
"type": "object",
"properties": {
"errorCode": {
"type": "string",
"description": "业务约定的错误码"
},
"errorMessage": {
"type": "string",
"description": "业务上的错误信息"
},
"success": {
"type": "boolean",
"description": "业务上的请求是否成功"
}
}
},
"NoticeIconList": {
"type": "object",
"properties": {
"data": {
"type": "array",
"items": {
"$ref": "#/components/schemas/NoticeIconItem"
}
},
"total": {
"type": "integer",
"description": "列表的内容总数",
"format": "int32"
},
"success": {
"type": "boolean"
}
}
},
"NoticeIconItemType": {
"title": "NoticeIconItemType",
"description": "已读未读列表的枚举",
"type": "string",
"properties": {},
"enum": ["notification", "message", "event"]
},
"NoticeIconItem": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"extra": {
"type": "string",
"format": "any"
},
"key": { "type": "string" },
"read": {
"type": "boolean"
},
"avatar": {
"type": "string"
},
"title": {
"type": "string"
},
"status": {
"type": "string"
},
"datetime": {
"type": "string",
"format": "date"
},
"description": {
"type": "string"
},
"type": {
"extensions": {
"x-is-enum": true
},
"$ref": "#/components/schemas/NoticeIconItemType"
}
}
}
}
}
}

View File

6627
config/oneapi/prodapi.json Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -11,33 +11,33 @@
*/
export default {
// 如果需要自定义本地开发服务器 请取消注释按需调整
// dev: {
// // localhost:8000/api/** -> https://preview.pro.ant.design/api/**
// '/api/': {
// // 要代理的地址
// target: 'https://preview.pro.ant.design',
// // 配置了这个可以从 http 代理到 https
// // 依赖 origin 的功能可能需要这个,比如 cookie
// changeOrigin: true,
// },
// },
dev: {
// localhost:8000/api/** -> https://preview.pro.ant.design/api/**
"/admin-api/": {
// 要代理的地址
target: "http://192.168.1.114:48080",
// 配置了这个可以从 http 代理到 https
// 依赖 origin 的功能可能需要这个,比如 cookie
changeOrigin: true,
},
},
/**
* @name 详细的代理配置
* @doc https://github.com/chimurai/http-proxy-middleware
*/
test: {
// localhost:8000/api/** -> https://preview.pro.ant.design/api/**
'/api/': {
target: 'https://proapi.azurewebsites.net',
"/api/": {
target: "https://proapi.azurewebsites.net",
changeOrigin: true,
pathRewrite: { '^': '' },
pathRewrite: { "^": "" },
},
},
pre: {
'/api/': {
target: 'your pre url',
"/api/": {
target: "your pre url",
changeOrigin: true,
pathRewrite: { '^': '' },
pathRewrite: { "^": "" },
},
},
};

View File

@@ -12,52 +12,52 @@
*/
export default [
{
path: '/user',
path: "/user",
layout: false,
routes: [
{
name: 'login',
path: '/user/login',
component: './user/login',
name: "login",
path: "/user/login",
component: "./user/login",
},
],
},
{
path: '/welcome',
name: 'welcome',
icon: 'smile',
component: './Welcome',
path: "/welcome",
name: "welcome",
icon: "smile",
component: "./Welcome",
},
{
path: '/admin',
name: 'admin',
icon: 'crown',
access: 'canAdmin',
path: "/admin",
name: "admin",
icon: "crown",
access: "canAdmin",
routes: [
{
path: '/admin',
redirect: '/admin/sub-page',
path: "/admin",
redirect: "/admin/sub-page",
},
{
path: '/admin/sub-page',
name: 'sub-page',
component: './Admin',
path: "/admin/sub-page",
name: "sub-page",
component: "./Admin",
},
],
},
// {
// name: 'list.table-list',
// icon: 'table',
// path: '/list',
// component: './table-list',
// },
{
name: 'list.table-list',
icon: 'table',
path: '/list',
component: './table-list',
path: "/",
redirect: "/welcome",
},
{
path: '/',
redirect: '/welcome',
},
{
component: '404',
component: "404",
layout: false,
path: './*',
path: "./*",
},
];

View File

@@ -37,22 +37,26 @@
"dependencies": {
"@ant-design/icons": "^5.6.1",
"@ant-design/pro-components": "^2.8.9",
"antd": "^5.26.4",
"@ant-design/v5-patch-for-react-19": "^1.0.3",
"antd": "^5.26.4",
"antd-style": "^3.7.0",
"classnames": "^2.5.1",
"dayjs": "^1.11.13",
"jsencrypt": "^3.5.4",
"react": "^19.1.0",
"react-dom": "^19.1.0"
"react-dom": "^19.1.0",
"web-storage-cache": "^1.1.1"
},
"devDependencies": {
"@ant-design/pro-cli": "^3.3.0",
"@biomejs/biome": "^2.1.1",
"@commitlint/cli": "^19.8.1",
"@commitlint/config-conventional": "^19.8.1",
"@testing-library/dom": "^10.4.0",
"@testing-library/react": "^16.3.0",
"@types/express": "^5.0.3",
"@types/jest": "^30.0.0",
"@types/node": "^24.0.13",
"@types/react": "^19.1.8",
"@types/react-dom": "^19.1.6",
"@types/react-helmet": "^6.1.11",
@@ -68,9 +72,7 @@
"ts-node": "^10.9.2",
"typescript": "^5.6.3",
"umi-presets-pro": "^2.0.3",
"umi-serve": "^1.9.11",
"@biomejs/biome": "^2.1.1",
"@types/node": "^24.0.13"
"umi-serve": "^1.9.11"
},
"engines": {
"node": ">=20.0.0"

39
pnpm-lock.yaml generated
View File

@@ -29,12 +29,18 @@ importers:
dayjs:
specifier: ^1.11.13
version: 1.11.18
jsencrypt:
specifier: ^3.5.4
version: 3.5.4
react:
specifier: ^19.1.0
version: 19.1.1
react-dom:
specifier: ^19.1.0
version: 19.1.1(react@19.1.1)
web-storage-cache:
specifier: ^1.1.1
version: 1.1.1
devDependencies:
'@ant-design/pro-cli':
specifier: ^3.3.0
@@ -6624,6 +6630,9 @@ packages:
canvas:
optional: true
jsencrypt@3.5.4:
resolution: {integrity: sha512-kNjfYEMNASxrDGsmcSQh/rUTmcoRfSUkxnAz+MMywM8jtGu+fFEZ3nJjHM58zscVnwR0fYmG9sGkTDjqUdpiwA==}
jsesc@2.5.2:
resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==}
engines: {node: '>=4'}
@@ -10737,6 +10746,9 @@ packages:
wcwidth@1.0.1:
resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==}
web-storage-cache@1.1.1:
resolution: {integrity: sha512-D0MieGooOs8RpsrK+vnejXnvh4OOv/+lTFB35JRkJJQt+uOjPE08XpaE0QBLMTRu47B1KGT/Nq3Gbag3Orinzw==}
web-streams-polyfill@3.3.3:
resolution: {integrity: sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==}
engines: {node: '>= 8'}
@@ -14812,7 +14824,7 @@ snapshots:
'@types/history@5.0.0':
dependencies:
history: 4.10.1
history: 5.3.0
'@types/hoist-non-react-statics@3.3.7(@types/react@19.1.12)':
dependencies:
@@ -14917,7 +14929,7 @@ snapshots:
'@types/history': 4.7.11
'@types/react': 19.1.12
'@types/react-router': 5.1.20
redux: 3.7.2
redux: 4.2.1
'@types/react-router@5.1.20':
dependencies:
@@ -15247,7 +15259,7 @@ snapshots:
'@svgr/core': 6.5.1
'@umijs/bundler-utils': 4.4.12
'@umijs/utils': 4.4.12
'@vitejs/plugin-react': 4.0.0(vite@4.5.2(@types/node@24.3.1)(less@4.4.1)(lightningcss@1.22.1)(sugarss@2.0.0)(terser@5.44.0))
'@vitejs/plugin-react': 4.0.0(vite@4.5.2(@types/node@24.3.1)(less@4.1.3)(lightningcss@1.22.1)(sugarss@2.0.0)(terser@5.44.0))
core-js: 3.34.0
less: 4.1.3
postcss-preset-env: 7.5.0(postcss@8.5.6)
@@ -15934,13 +15946,13 @@ snapshots:
'@unrs/resolver-binding-win32-x64-msvc@1.11.1':
optional: true
'@vitejs/plugin-react@4.0.0(vite@4.5.2(@types/node@24.3.1)(less@4.4.1)(lightningcss@1.22.1)(sugarss@2.0.0)(terser@5.44.0))':
'@vitejs/plugin-react@4.0.0(vite@4.5.2(@types/node@24.3.1)(less@4.1.3)(lightningcss@1.22.1)(sugarss@2.0.0)(terser@5.44.0))':
dependencies:
'@babel/core': 7.28.4
'@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.28.4)
'@babel/plugin-transform-react-jsx-source': 7.27.1(@babel/core@7.28.4)
react-refresh: 0.14.2
vite: 4.5.2(@types/node@24.3.1)(less@4.4.1)(lightningcss@1.22.1)(sugarss@2.0.0)(terser@5.44.0)
vite: 4.5.2(@types/node@24.3.1)(less@4.1.3)(lightningcss@1.22.1)(sugarss@2.0.0)(terser@5.44.0)
transitivePeerDependencies:
- supports-color
@@ -20412,6 +20424,8 @@ snapshots:
- supports-color
- utf-8-validate
jsencrypt@3.5.4: {}
jsesc@2.5.2: {}
jsesc@3.0.2: {}
@@ -25430,19 +25444,6 @@ snapshots:
sugarss: 2.0.0
terser: 5.44.0
vite@4.5.2(@types/node@24.3.1)(less@4.4.1)(lightningcss@1.22.1)(sugarss@2.0.0)(terser@5.44.0):
dependencies:
esbuild: 0.18.20
postcss: 8.5.6
rollup: 3.29.5
optionalDependencies:
'@types/node': 24.3.1
fsevents: 2.3.3
less: 4.4.1
lightningcss: 1.22.1
sugarss: 2.0.0
terser: 5.44.0
vm-browserify@1.1.2: {}
w3c-xmlserializer@5.0.0:
@@ -25476,6 +25477,8 @@ snapshots:
dependencies:
defaults: 1.0.4
web-storage-cache@1.1.1: {}
web-streams-polyfill@3.3.3: {}
webidl-conversions@3.0.1: {}

View File

@@ -1,11 +1,13 @@
import { UserVO } from "./services/login/types";
/**
* @see https://umijs.org/docs/max/access#access
* */
export default function access(
initialState: { currentUser?: API.CurrentUser } | undefined,
initialState: { currentUser?: UserVO } | undefined
) {
const { currentUser } = initialState ?? {};
return {
canAdmin: currentUser && currentUser.access === 'admin',
canAdmin: currentUser && currentUser.username === "admin",
};
}

View File

@@ -1,39 +1,39 @@
import { LinkOutlined } from '@ant-design/icons';
import type { Settings as LayoutSettings } from '@ant-design/pro-components';
import { SettingDrawer } from '@ant-design/pro-components';
import type { RequestConfig, RunTimeLayoutConfig } from '@umijs/max';
import { history, Link } from '@umijs/max';
import React from 'react';
import { LinkOutlined } from "@ant-design/icons";
import type { Settings as LayoutSettings } from "@ant-design/pro-components";
import { SettingDrawer } from "@ant-design/pro-components";
import type { RequestConfig, RunTimeLayoutConfig } from "@umijs/max";
import { history, Link } from "@umijs/max";
import React from "react";
import {
AvatarDropdown,
AvatarName,
Footer,
Question,
SelectLang,
} from '@/components';
import { currentUser as queryCurrentUser } from '@/services/ant-design-pro/api';
import defaultSettings from '../config/defaultSettings';
import { errorConfig } from './requestErrorConfig';
import '@ant-design/v5-patch-for-react-19';
} from "@/components";
import { getInfo } from "@/services/login";
import type { UserVO, TokenType } from "@/services/login/types";
import defaultSettings from "../config/defaultSettings";
import { errorConfig } from "./requestErrorConfig";
import "@ant-design/v5-patch-for-react-19";
const isDev = process.env.NODE_ENV === 'development';
const isDev = process.env.NODE_ENV === "development";
const isDevOrTest = isDev || process.env.CI;
const loginPath = '/user/login';
const loginPath = "/user/login";
/**
* @see https://umijs.org/docs/api/runtime-config#getinitialstate
* */
export async function getInitialState(): Promise<{
settings?: Partial<LayoutSettings>;
currentUser?: API.CurrentUser;
currentUser?: { user: UserVO };
loading?: boolean;
fetchUserInfo?: () => Promise<API.CurrentUser | undefined>;
fetchUserInfo?: () => Promise<{ user: UserVO } | undefined>;
}> {
const fetchUserInfo = async () => {
// history.push(loginPath);
try {
const msg = await queryCurrentUser({
skipErrorHandler: true,
});
const msg = await getInfo();
return msg.data;
} catch (_error) {
history.push(loginPath);
@@ -43,8 +43,8 @@ export async function getInitialState(): Promise<{
// 如果不是登录页面,执行
const { location } = history;
if (
![loginPath, '/user/register', '/user/register-result'].includes(
location.pathname,
![loginPath, "/user/register", "/user/register-result"].includes(
location.pathname
)
) {
const currentUser = await fetchUserInfo();
@@ -71,14 +71,14 @@ export const layout: RunTimeLayoutConfig = ({
<SelectLang key="SelectLang" />,
],
avatarProps: {
src: initialState?.currentUser?.avatar,
src: initialState?.currentUser?.user.avatar,
title: <AvatarName />,
render: (_, avatarChildren) => (
<AvatarDropdown>{avatarChildren}</AvatarDropdown>
),
},
waterMarkProps: {
content: initialState?.currentUser?.name,
content: initialState?.currentUser?.user.nickname,
},
footerRender: () => <Footer />,
onPageChange: () => {
@@ -90,22 +90,22 @@ export const layout: RunTimeLayoutConfig = ({
},
bgLayoutImgList: [
{
src: 'https://mdn.alipayobjects.com/yuyan_qk0oxh/afts/img/D2LWSqNny4sAAAAAAAAAAAAAFl94AQBr',
src: "https://mdn.alipayobjects.com/yuyan_qk0oxh/afts/img/D2LWSqNny4sAAAAAAAAAAAAAFl94AQBr",
left: 85,
bottom: 100,
height: '303px',
height: "303px",
},
{
src: 'https://mdn.alipayobjects.com/yuyan_qk0oxh/afts/img/C2TWRpJpiC0AAAAAAAAAAAAAFl94AQBr',
src: "https://mdn.alipayobjects.com/yuyan_qk0oxh/afts/img/C2TWRpJpiC0AAAAAAAAAAAAAFl94AQBr",
bottom: -68,
right: -45,
height: '303px',
height: "303px",
},
{
src: 'https://mdn.alipayobjects.com/yuyan_qk0oxh/afts/img/F6vSTbj8KpYAAAAAAAAAAAAAFl94AQBr',
src: "https://mdn.alipayobjects.com/yuyan_qk0oxh/afts/img/F6vSTbj8KpYAAAAAAAAAAAAAFl94AQBr",
bottom: 0,
left: 0,
width: '331px',
width: "331px",
},
],
links: isDevOrTest
@@ -151,6 +151,6 @@ export const layout: RunTimeLayoutConfig = ({
* @doc https://umijs.org/docs/max/request#配置
*/
export const request: RequestConfig = {
baseURL: isDev ? '' : 'https://proapi.azurewebsites.net',
baseURL: isDev ? "" : "https://proapi.azurewebsites.net",
...errorConfig,
};

View File

@@ -2,15 +2,15 @@ import {
LogoutOutlined,
SettingOutlined,
UserOutlined,
} from '@ant-design/icons';
import { history, useModel } from '@umijs/max';
import type { MenuProps } from 'antd';
import { Spin } from 'antd';
import { createStyles } from 'antd-style';
import React from 'react';
import { flushSync } from 'react-dom';
import { outLogin } from '@/services/ant-design-pro/api';
import HeaderDropdown from '../HeaderDropdown';
} from "@ant-design/icons";
import { history, useModel } from "@umijs/max";
import type { MenuProps } from "antd";
import { Spin } from "antd";
import { createStyles } from "antd-style";
import React from "react";
import { flushSync } from "react-dom";
import { loginOut } from "@/services/login";
import HeaderDropdown from "../HeaderDropdown";
export type GlobalHeaderRightProps = {
menu?: boolean;
@@ -18,23 +18,23 @@ export type GlobalHeaderRightProps = {
};
export const AvatarName = () => {
const { initialState } = useModel('@@initialState');
const { initialState } = useModel("@@initialState");
const { currentUser } = initialState || {};
return <span className="anticon">{currentUser?.name}</span>;
return <span className="anticon">{currentUser?.user.nickname}</span>;
};
const useStyles = createStyles(({ token }) => {
return {
action: {
display: 'flex',
height: '48px',
marginLeft: 'auto',
overflow: 'hidden',
alignItems: 'center',
padding: '0 8px',
cursor: 'pointer',
display: "flex",
height: "48px",
marginLeft: "auto",
overflow: "hidden",
alignItems: "center",
padding: "0 8px",
cursor: "pointer",
borderRadius: token.borderRadius,
'&:hover': {
"&:hover": {
backgroundColor: token.colorBgTextHover,
},
},
@@ -49,29 +49,29 @@ export const AvatarDropdown: React.FC<GlobalHeaderRightProps> = ({
* 退出登录,并且将当前的 url 保存
*/
const loginOut = async () => {
await outLogin();
await loginOut();
const { search, pathname } = window.location;
const urlParams = new URL(window.location.href).searchParams;
const searchParams = new URLSearchParams({
redirect: pathname + search,
});
/** 此方法会跳转到 redirect 参数所在的位置 */
const redirect = urlParams.get('redirect');
const redirect = urlParams.get("redirect");
// Note: There may be security issues, please note
if (window.location.pathname !== '/user/login' && !redirect) {
if (window.location.pathname !== "/user/login" && !redirect) {
history.replace({
pathname: '/user/login',
pathname: "/user/login",
search: searchParams.toString(),
});
}
};
const { styles } = useStyles();
const { initialState, setInitialState } = useModel('@@initialState');
const { initialState, setInitialState } = useModel("@@initialState");
const onMenuClick: MenuProps['onClick'] = (event) => {
const onMenuClick: MenuProps["onClick"] = (event) => {
const { key } = event;
if (key === 'logout') {
if (key === "logout") {
flushSync(() => {
setInitialState((s) => ({ ...s, currentUser: undefined }));
});
@@ -99,7 +99,7 @@ export const AvatarDropdown: React.FC<GlobalHeaderRightProps> = ({
const { currentUser } = initialState;
if (!currentUser || !currentUser.name) {
if (!currentUser || !currentUser.user.nickname) {
return loading;
}
@@ -107,24 +107,24 @@ export const AvatarDropdown: React.FC<GlobalHeaderRightProps> = ({
...(menu
? [
{
key: 'center',
key: "center",
icon: <UserOutlined />,
label: '个人中心',
label: "个人中心",
},
{
key: 'settings',
key: "settings",
icon: <SettingOutlined />,
label: '个人设置',
label: "个人设置",
},
{
type: 'divider' as const,
type: "divider" as const,
},
]
: []),
{
key: 'logout',
key: "logout",
icon: <LogoutOutlined />,
label: '退出登录',
label: "退出登录",
},
];

39
src/hooks/web/useCache.ts Normal file
View File

@@ -0,0 +1,39 @@
/**
* 配置浏览器本地存储的方式,可直接存储对象数组。
*/
import WebStorageCache from "web-storage-cache";
type CacheType = "localStorage" | "sessionStorage";
export const CACHE_KEY = {
// 用户相关
ROLE_ROUTERS: "roleRouters",
USER: "user",
// 系统设置
IS_DARK: "isDark",
LANG: "lang",
THEME: "theme",
LAYOUT: "layout",
DICT_CACHE: "dictCache",
// 登录表单
LoginForm: "loginForm",
TenantId: "tenantId",
};
export const useCache = (type: CacheType = "localStorage") => {
const wsCache: WebStorageCache = new WebStorageCache({
storage: type,
});
return {
wsCache,
};
};
export const deleteUserCache = () => {
const { wsCache } = useCache();
wsCache.delete(CACHE_KEY.USER);
wsCache.delete(CACHE_KEY.ROLE_ROUTERS);
// 注意,不要清理 LoginForm 登录表单
};

View File

@@ -1,80 +1,80 @@
import { PlusOutlined } from '@ant-design/icons';
import {
type ActionType,
ModalForm,
ProFormText,
ProFormTextArea,
} from '@ant-design/pro-components';
import { FormattedMessage, useIntl, useRequest } from '@umijs/max';
import { Button, message } from 'antd';
import type { FC } from 'react';
import { addRule } from '@/services/ant-design-pro/api';
// import { PlusOutlined } from '@ant-design/icons';
// import {
// type ActionType,
// ModalForm,
// ProFormText,
// ProFormTextArea,
// } from '@ant-design/pro-components';
// import { FormattedMessage, useIntl, useRequest } from '@umijs/max';
// import { Button, message } from 'antd';
// import type { FC } from 'react';
// import { addRule } from '@/services/ant-design-pro/api';
interface CreateFormProps {
reload?: ActionType['reload'];
}
// interface CreateFormProps {
// reload?: ActionType['reload'];
// }
const CreateForm: FC<CreateFormProps> = (props) => {
const { reload } = props;
// const CreateForm: FC<CreateFormProps> = (props) => {
// const { reload } = props;
const [messageApi, contextHolder] = message.useMessage();
/**
* @en-US International configuration
* @zh-CN 国际化配置
* */
const intl = useIntl();
// const [messageApi, contextHolder] = message.useMessage();
// /**
// * @en-US International configuration
// * @zh-CN 国际化配置
// * */
// const intl = useIntl();
const { run, loading } = useRequest(addRule, {
manual: true,
onSuccess: () => {
messageApi.success('Added successfully');
reload?.();
},
onError: () => {
messageApi.error('Adding failed, please try again!');
},
});
// const { run, loading } = useRequest(addRule, {
// manual: true,
// onSuccess: () => {
// messageApi.success('Added successfully');
// reload?.();
// },
// onError: () => {
// messageApi.error('Adding failed, please try again!');
// },
// });
return (
<>
{contextHolder}
<ModalForm
title={intl.formatMessage({
id: 'pages.searchTable.createForm.newRule',
defaultMessage: 'New rule',
})}
trigger={
<Button type="primary" icon={<PlusOutlined />}>
<FormattedMessage id="pages.searchTable.new" defaultMessage="New" />
</Button>
}
width="400px"
modalProps={{ okButtonProps: { loading } }}
onFinish={async (value) => {
await run({ data: value as API.RuleListItem });
// return (
// <>
// {contextHolder}
// <ModalForm
// title={intl.formatMessage({
// id: 'pages.searchTable.createForm.newRule',
// defaultMessage: 'New rule',
// })}
// trigger={
// <Button type="primary" icon={<PlusOutlined />}>
// <FormattedMessage id="pages.searchTable.new" defaultMessage="New" />
// </Button>
// }
// width="400px"
// modalProps={{ okButtonProps: { loading } }}
// onFinish={async (value) => {
// await run({ data: value as API.RuleListItem });
return true;
}}
>
<ProFormText
rules={[
{
required: true,
message: (
<FormattedMessage
id="pages.searchTable.ruleName"
defaultMessage="Rule name is required"
/>
),
},
]}
width="md"
name="name"
/>
<ProFormTextArea width="md" name="desc" />
</ModalForm>
</>
);
};
// return true;
// }}
// >
// <ProFormText
// rules={[
// {
// required: true,
// message: (
// <FormattedMessage
// id="pages.searchTable.ruleName"
// defaultMessage="Rule name is required"
// />
// ),
// },
// ]}
// width="md"
// name="name"
// />
// <ProFormTextArea width="md" name="desc" />
// </ModalForm>
// </>
// );
// };
export default CreateForm;
// export default CreateForm;

View File

@@ -1,251 +1,251 @@
import {
ProFormDateTimePicker,
ProFormRadio,
ProFormSelect,
ProFormText,
ProFormTextArea,
StepsForm,
} from '@ant-design/pro-components';
import { FormattedMessage, useIntl, useRequest } from '@umijs/max';
import { Modal, message } from 'antd';
import React, { cloneElement, useCallback, useState } from 'react';
import { updateRule } from '@/services/ant-design-pro/api';
// import {
// ProFormDateTimePicker,
// ProFormRadio,
// ProFormSelect,
// ProFormText,
// ProFormTextArea,
// StepsForm,
// } from '@ant-design/pro-components';
// import { FormattedMessage, useIntl, useRequest } from '@umijs/max';
// import { Modal, message } from 'antd';
// import React, { cloneElement, useCallback, useState } from 'react';
// import { updateRule } from '@/services/ant-design-pro/api';
export type FormValueType = {
target?: string;
template?: string;
type?: string;
time?: string;
frequency?: string;
} & Partial<API.RuleListItem>;
// export type FormValueType = {
// target?: string;
// template?: string;
// type?: string;
// time?: string;
// frequency?: string;
// } & Partial<API.RuleListItem>;
export type UpdateFormProps = {
trigger?: React.ReactElement<any>;
onOk?: () => void;
values: Partial<API.RuleListItem>;
};
// export type UpdateFormProps = {
// trigger?: React.ReactElement<any>;
// onOk?: () => void;
// values: Partial<API.RuleListItem>;
// };
const UpdateForm: React.FC<UpdateFormProps> = (props) => {
const { onOk, values, trigger } = props;
// const UpdateForm: React.FC<UpdateFormProps> = (props) => {
// const { onOk, values, trigger } = props;
const intl = useIntl();
// const intl = useIntl();
const [open, setOpen] = useState(false);
// const [open, setOpen] = useState(false);
const [messageApi, contextHolder] = message.useMessage();
// const [messageApi, contextHolder] = message.useMessage();
const { run } = useRequest(updateRule, {
manual: true,
onSuccess: () => {
messageApi.success('Configuration is successful');
onOk?.();
},
onError: () => {
messageApi.error('Configuration failed, please try again!');
},
});
// const { run } = useRequest(updateRule, {
// manual: true,
// onSuccess: () => {
// messageApi.success('Configuration is successful');
// onOk?.();
// },
// onError: () => {
// messageApi.error('Configuration failed, please try again!');
// },
// });
const onCancel = useCallback(() => {
setOpen(false);
}, []);
// const onCancel = useCallback(() => {
// setOpen(false);
// }, []);
const onOpen = useCallback(() => {
setOpen(true);
}, []);
// const onOpen = useCallback(() => {
// setOpen(true);
// }, []);
const onFinish = useCallback(
async (values?: any) => {
await run({ data: values });
// const onFinish = useCallback(
// async (values?: any) => {
// await run({ data: values });
onCancel();
},
[onCancel, run],
);
// onCancel();
// },
// [onCancel, run],
// );
return (
<>
{contextHolder}
{trigger
? cloneElement(trigger, {
onClick: onOpen,
})
: null}
<StepsForm
stepsProps={{
size: 'small',
}}
stepsFormRender={(dom, submitter) => {
return (
<Modal
width={640}
styles={{
body: {
padding: '32px 40px 48px',
},
}}
destroyOnHidden
title={intl.formatMessage({
id: 'pages.searchTable.updateForm.ruleConfig',
defaultMessage: '规则配置',
})}
open={open}
footer={submitter}
onCancel={onCancel}
>
{dom}
</Modal>
);
}}
onFinish={onFinish}
>
<StepsForm.StepForm
initialValues={values}
title={intl.formatMessage({
id: 'pages.searchTable.updateForm.basicConfig',
defaultMessage: '基本信息',
})}
>
<ProFormText
name="name"
label={intl.formatMessage({
id: 'pages.searchTable.updateForm.ruleName.nameLabel',
defaultMessage: '规则名称',
})}
width="md"
rules={[
{
required: true,
message: (
<FormattedMessage
id="pages.searchTable.updateForm.ruleName.nameRules"
defaultMessage="请输入规则名称!"
/>
),
},
]}
/>
<ProFormTextArea
name="desc"
width="md"
label={intl.formatMessage({
id: 'pages.searchTable.updateForm.ruleDesc.descLabel',
defaultMessage: '规则描述',
})}
placeholder={intl.formatMessage({
id: 'pages.searchTable.updateForm.ruleDesc.descPlaceholder',
defaultMessage: '请输入至少五个字符',
})}
rules={[
{
required: true,
message: (
<FormattedMessage
id="pages.searchTable.updateForm.ruleDesc.descRules"
defaultMessage="请输入至少五个字符的规则描述!"
/>
),
min: 5,
},
]}
/>
</StepsForm.StepForm>
<StepsForm.StepForm
initialValues={{
target: '0',
template: '0',
}}
title={intl.formatMessage({
id: 'pages.searchTable.updateForm.ruleProps.title',
defaultMessage: '配置规则属性',
})}
>
<ProFormSelect
name="target"
width="md"
label={intl.formatMessage({
id: 'pages.searchTable.updateForm.object',
defaultMessage: '监控对象',
})}
valueEnum={{
0: '表一',
1: '表二',
}}
/>
<ProFormSelect
name="template"
width="md"
label={intl.formatMessage({
id: 'pages.searchTable.updateForm.ruleProps.templateLabel',
defaultMessage: '规则模板',
})}
valueEnum={{
0: '规则模板一',
1: '规则模板二',
}}
/>
<ProFormRadio.Group
name="type"
label={intl.formatMessage({
id: 'pages.searchTable.updateForm.ruleProps.typeLabel',
defaultMessage: '规则类型',
})}
options={[
{
value: '0',
label: '强',
},
{
value: '1',
label: '弱',
},
]}
/>
</StepsForm.StepForm>
<StepsForm.StepForm
initialValues={{
type: '1',
frequency: 'month',
}}
title={intl.formatMessage({
id: 'pages.searchTable.updateForm.schedulingPeriod.title',
defaultMessage: '设定调度周期',
})}
>
<ProFormDateTimePicker
name="time"
width="md"
label={intl.formatMessage({
id: 'pages.searchTable.updateForm.schedulingPeriod.timeLabel',
defaultMessage: '开始时间',
})}
rules={[
{
required: true,
message: (
<FormattedMessage
id="pages.searchTable.updateForm.schedulingPeriod.timeRules"
defaultMessage="请选择开始时间!"
/>
),
},
]}
/>
<ProFormSelect
name="frequency"
label={intl.formatMessage({
id: 'pages.searchTable.updateForm.object',
defaultMessage: '监控对象',
})}
width="md"
valueEnum={{
month: '月',
week: '周',
}}
/>
</StepsForm.StepForm>
</StepsForm>
</>
);
};
// return (
// <>
// {contextHolder}
// {trigger
// ? cloneElement(trigger, {
// onClick: onOpen,
// })
// : null}
// <StepsForm
// stepsProps={{
// size: 'small',
// }}
// stepsFormRender={(dom, submitter) => {
// return (
// <Modal
// width={640}
// styles={{
// body: {
// padding: '32px 40px 48px',
// },
// }}
// destroyOnHidden
// title={intl.formatMessage({
// id: 'pages.searchTable.updateForm.ruleConfig',
// defaultMessage: '规则配置',
// })}
// open={open}
// footer={submitter}
// onCancel={onCancel}
// >
// {dom}
// </Modal>
// );
// }}
// onFinish={onFinish}
// >
// <StepsForm.StepForm
// initialValues={values}
// title={intl.formatMessage({
// id: 'pages.searchTable.updateForm.basicConfig',
// defaultMessage: '基本信息',
// })}
// >
// <ProFormText
// name="name"
// label={intl.formatMessage({
// id: 'pages.searchTable.updateForm.ruleName.nameLabel',
// defaultMessage: '规则名称',
// })}
// width="md"
// rules={[
// {
// required: true,
// message: (
// <FormattedMessage
// id="pages.searchTable.updateForm.ruleName.nameRules"
// defaultMessage="请输入规则名称!"
// />
// ),
// },
// ]}
// />
// <ProFormTextArea
// name="desc"
// width="md"
// label={intl.formatMessage({
// id: 'pages.searchTable.updateForm.ruleDesc.descLabel',
// defaultMessage: '规则描述',
// })}
// placeholder={intl.formatMessage({
// id: 'pages.searchTable.updateForm.ruleDesc.descPlaceholder',
// defaultMessage: '请输入至少五个字符',
// })}
// rules={[
// {
// required: true,
// message: (
// <FormattedMessage
// id="pages.searchTable.updateForm.ruleDesc.descRules"
// defaultMessage="请输入至少五个字符的规则描述!"
// />
// ),
// min: 5,
// },
// ]}
// />
// </StepsForm.StepForm>
// <StepsForm.StepForm
// initialValues={{
// target: '0',
// template: '0',
// }}
// title={intl.formatMessage({
// id: 'pages.searchTable.updateForm.ruleProps.title',
// defaultMessage: '配置规则属性',
// })}
// >
// <ProFormSelect
// name="target"
// width="md"
// label={intl.formatMessage({
// id: 'pages.searchTable.updateForm.object',
// defaultMessage: '监控对象',
// })}
// valueEnum={{
// 0: '表一',
// 1: '表二',
// }}
// />
// <ProFormSelect
// name="template"
// width="md"
// label={intl.formatMessage({
// id: 'pages.searchTable.updateForm.ruleProps.templateLabel',
// defaultMessage: '规则模板',
// })}
// valueEnum={{
// 0: '规则模板一',
// 1: '规则模板二',
// }}
// />
// <ProFormRadio.Group
// name="type"
// label={intl.formatMessage({
// id: 'pages.searchTable.updateForm.ruleProps.typeLabel',
// defaultMessage: '规则类型',
// })}
// options={[
// {
// value: '0',
// label: '强',
// },
// {
// value: '1',
// label: '弱',
// },
// ]}
// />
// </StepsForm.StepForm>
// <StepsForm.StepForm
// initialValues={{
// type: '1',
// frequency: 'month',
// }}
// title={intl.formatMessage({
// id: 'pages.searchTable.updateForm.schedulingPeriod.title',
// defaultMessage: '设定调度周期',
// })}
// >
// <ProFormDateTimePicker
// name="time"
// width="md"
// label={intl.formatMessage({
// id: 'pages.searchTable.updateForm.schedulingPeriod.timeLabel',
// defaultMessage: '开始时间',
// })}
// rules={[
// {
// required: true,
// message: (
// <FormattedMessage
// id="pages.searchTable.updateForm.schedulingPeriod.timeRules"
// defaultMessage="请选择开始时间!"
// />
// ),
// },
// ]}
// />
// <ProFormSelect
// name="frequency"
// label={intl.formatMessage({
// id: 'pages.searchTable.updateForm.object',
// defaultMessage: '监控对象',
// })}
// width="md"
// valueEnum={{
// month: '月',
// week: '周',
// }}
// />
// </StepsForm.StepForm>
// </StepsForm>
// </>
// );
// };
export default UpdateForm;
// export default UpdateForm;

View File

@@ -1,330 +1,330 @@
import type {
ActionType,
ProColumns,
ProDescriptionsItemProps,
} from '@ant-design/pro-components';
import {
FooterToolbar,
PageContainer,
ProDescriptions,
ProTable,
} from '@ant-design/pro-components';
import { FormattedMessage, useIntl, useRequest } from '@umijs/max';
import { Button, Drawer, Input, message } from 'antd';
import React, { useCallback, useRef, useState } from 'react';
import { removeRule, rule } from '@/services/ant-design-pro/api';
import CreateForm from './components/CreateForm';
import UpdateForm from './components/UpdateForm';
// import type {
// ActionType,
// ProColumns,
// ProDescriptionsItemProps,
// } from '@ant-design/pro-components';
// import {
// FooterToolbar,
// PageContainer,
// ProDescriptions,
// ProTable,
// } from '@ant-design/pro-components';
// import { FormattedMessage, useIntl, useRequest } from '@umijs/max';
// import { Button, Drawer, Input, message } from 'antd';
// import React, { useCallback, useRef, useState } from 'react';
// import { removeRule, rule } from '@/services/ant-design-pro/api';
// import CreateForm from './components/CreateForm';
// import UpdateForm from './components/UpdateForm';
const TableList: React.FC = () => {
const actionRef = useRef<ActionType | null>(null);
// const TableList: React.FC = () => {
// const actionRef = useRef<ActionType | null>(null);
const [showDetail, setShowDetail] = useState<boolean>(false);
const [currentRow, setCurrentRow] = useState<API.RuleListItem>();
const [selectedRowsState, setSelectedRows] = useState<API.RuleListItem[]>([]);
// const [showDetail, setShowDetail] = useState<boolean>(false);
// const [currentRow, setCurrentRow] = useState<API.RuleListItem>();
// const [selectedRowsState, setSelectedRows] = useState<API.RuleListItem[]>([]);
/**
* @en-US International configuration
* @zh-CN 国际化配置
* */
const intl = useIntl();
// /**
// * @en-US International configuration
// * @zh-CN 国际化配置
// * */
// const intl = useIntl();
const [messageApi, contextHolder] = message.useMessage();
// const [messageApi, contextHolder] = message.useMessage();
const { run: delRun, loading } = useRequest(removeRule, {
manual: true,
onSuccess: () => {
setSelectedRows([]);
actionRef.current?.reloadAndRest?.();
// const { run: delRun, loading } = useRequest(removeRule, {
// manual: true,
// onSuccess: () => {
// setSelectedRows([]);
// actionRef.current?.reloadAndRest?.();
messageApi.success('Deleted successfully and will refresh soon');
},
onError: () => {
messageApi.error('Delete failed, please try again');
},
});
// messageApi.success('Deleted successfully and will refresh soon');
// },
// onError: () => {
// messageApi.error('Delete failed, please try again');
// },
// });
const columns: ProColumns<API.RuleListItem>[] = [
{
title: (
<FormattedMessage
id="pages.searchTable.updateForm.ruleName.nameLabel"
defaultMessage="Rule name"
/>
),
dataIndex: 'name',
render: (dom, entity) => {
return (
<a
onClick={() => {
setCurrentRow(entity);
setShowDetail(true);
}}
>
{dom}
</a>
);
},
},
{
title: (
<FormattedMessage
id="pages.searchTable.titleDesc"
defaultMessage="Description"
/>
),
dataIndex: 'desc',
valueType: 'textarea',
},
{
title: (
<FormattedMessage
id="pages.searchTable.titleCallNo"
defaultMessage="Number of service calls"
/>
),
dataIndex: 'callNo',
sorter: true,
hideInForm: true,
renderText: (val: string) =>
`${val}${intl.formatMessage({
id: 'pages.searchTable.tenThousand',
defaultMessage: ' 万 ',
})}`,
},
{
title: (
<FormattedMessage
id="pages.searchTable.titleStatus"
defaultMessage="Status"
/>
),
dataIndex: 'status',
hideInForm: true,
valueEnum: {
0: {
text: (
<FormattedMessage
id="pages.searchTable.nameStatus.default"
defaultMessage="Shut down"
/>
),
status: 'Default',
},
1: {
text: (
<FormattedMessage
id="pages.searchTable.nameStatus.running"
defaultMessage="Running"
/>
),
status: 'Processing',
},
2: {
text: (
<FormattedMessage
id="pages.searchTable.nameStatus.online"
defaultMessage="Online"
/>
),
status: 'Success',
},
3: {
text: (
<FormattedMessage
id="pages.searchTable.nameStatus.abnormal"
defaultMessage="Abnormal"
/>
),
status: 'Error',
},
},
},
{
title: (
<FormattedMessage
id="pages.searchTable.titleUpdatedAt"
defaultMessage="Last scheduled time"
/>
),
sorter: true,
dataIndex: 'updatedAt',
valueType: 'dateTime',
renderFormItem: (item, { defaultRender, ...rest }, form) => {
const status = form.getFieldValue('status');
if (`${status}` === '0') {
return false;
}
if (`${status}` === '3') {
return (
<Input
{...rest}
placeholder={intl.formatMessage({
id: 'pages.searchTable.exception',
defaultMessage: 'Please enter the reason for the exception!',
})}
/>
);
}
return defaultRender(item);
},
},
{
title: (
<FormattedMessage
id="pages.searchTable.titleOption"
defaultMessage="Operating"
/>
),
dataIndex: 'option',
valueType: 'option',
render: (_, record) => [
<UpdateForm
trigger={
<a>
<FormattedMessage
id="pages.searchTable.config"
defaultMessage="Configuration"
/>
</a>
}
key="config"
onOk={actionRef.current?.reload}
values={record}
/>,
<a key="subscribeAlert" href="https://procomponents.ant.design/">
<FormattedMessage
id="pages.searchTable.subscribeAlert"
defaultMessage="Subscribe to alerts"
/>
</a>,
],
},
];
// const columns: ProColumns<API.RuleListItem>[] = [
// {
// title: (
// <FormattedMessage
// id="pages.searchTable.updateForm.ruleName.nameLabel"
// defaultMessage="Rule name"
// />
// ),
// dataIndex: 'name',
// render: (dom, entity) => {
// return (
// <a
// onClick={() => {
// setCurrentRow(entity);
// setShowDetail(true);
// }}
// >
// {dom}
// </a>
// );
// },
// },
// {
// title: (
// <FormattedMessage
// id="pages.searchTable.titleDesc"
// defaultMessage="Description"
// />
// ),
// dataIndex: 'desc',
// valueType: 'textarea',
// },
// {
// title: (
// <FormattedMessage
// id="pages.searchTable.titleCallNo"
// defaultMessage="Number of service calls"
// />
// ),
// dataIndex: 'callNo',
// sorter: true,
// hideInForm: true,
// renderText: (val: string) =>
// `${val}${intl.formatMessage({
// id: 'pages.searchTable.tenThousand',
// defaultMessage: ' 万 ',
// })}`,
// },
// {
// title: (
// <FormattedMessage
// id="pages.searchTable.titleStatus"
// defaultMessage="Status"
// />
// ),
// dataIndex: 'status',
// hideInForm: true,
// valueEnum: {
// 0: {
// text: (
// <FormattedMessage
// id="pages.searchTable.nameStatus.default"
// defaultMessage="Shut down"
// />
// ),
// status: 'Default',
// },
// 1: {
// text: (
// <FormattedMessage
// id="pages.searchTable.nameStatus.running"
// defaultMessage="Running"
// />
// ),
// status: 'Processing',
// },
// 2: {
// text: (
// <FormattedMessage
// id="pages.searchTable.nameStatus.online"
// defaultMessage="Online"
// />
// ),
// status: 'Success',
// },
// 3: {
// text: (
// <FormattedMessage
// id="pages.searchTable.nameStatus.abnormal"
// defaultMessage="Abnormal"
// />
// ),
// status: 'Error',
// },
// },
// },
// {
// title: (
// <FormattedMessage
// id="pages.searchTable.titleUpdatedAt"
// defaultMessage="Last scheduled time"
// />
// ),
// sorter: true,
// dataIndex: 'updatedAt',
// valueType: 'dateTime',
// renderFormItem: (item, { defaultRender, ...rest }, form) => {
// const status = form.getFieldValue('status');
// if (`${status}` === '0') {
// return false;
// }
// if (`${status}` === '3') {
// return (
// <Input
// {...rest}
// placeholder={intl.formatMessage({
// id: 'pages.searchTable.exception',
// defaultMessage: 'Please enter the reason for the exception!',
// })}
// />
// );
// }
// return defaultRender(item);
// },
// },
// {
// title: (
// <FormattedMessage
// id="pages.searchTable.titleOption"
// defaultMessage="Operating"
// />
// ),
// dataIndex: 'option',
// valueType: 'option',
// render: (_, record) => [
// <UpdateForm
// trigger={
// <a>
// <FormattedMessage
// id="pages.searchTable.config"
// defaultMessage="Configuration"
// />
// </a>
// }
// key="config"
// onOk={actionRef.current?.reload}
// values={record}
// />,
// <a key="subscribeAlert" href="https://procomponents.ant.design/">
// <FormattedMessage
// id="pages.searchTable.subscribeAlert"
// defaultMessage="Subscribe to alerts"
// />
// </a>,
// ],
// },
// ];
/**
* Delete node
* @zh-CN 删除节点
*
* @param selectedRows
*/
const handleRemove = useCallback(
async (selectedRows: API.RuleListItem[]) => {
if (!selectedRows?.length) {
messageApi.warning('请选择删除项');
// /**
// * Delete node
// * @zh-CN 删除节点
// *
// * @param selectedRows
// */
// const handleRemove = useCallback(
// async (selectedRows: API.RuleListItem[]) => {
// if (!selectedRows?.length) {
// messageApi.warning('请选择删除项');
return;
}
// return;
// }
await delRun({
data: {
key: selectedRows.map((row) => row.key),
},
});
},
[delRun, messageApi.warning],
);
// await delRun({
// data: {
// key: selectedRows.map((row) => row.key),
// },
// });
// },
// [delRun, messageApi.warning],
// );
return (
<PageContainer>
{contextHolder}
<ProTable<API.RuleListItem, API.PageParams>
headerTitle={intl.formatMessage({
id: 'pages.searchTable.title',
defaultMessage: 'Enquiry form',
})}
actionRef={actionRef}
rowKey="key"
search={{
labelWidth: 120,
}}
toolBarRender={() => [
<CreateForm key="create" reload={actionRef.current?.reload} />,
]}
request={rule}
columns={columns}
rowSelection={{
onChange: (_, selectedRows) => {
setSelectedRows(selectedRows);
},
}}
/>
{selectedRowsState?.length > 0 && (
<FooterToolbar
extra={
<div>
<FormattedMessage
id="pages.searchTable.chosen"
defaultMessage="Chosen"
/>{' '}
<a style={{ fontWeight: 600 }}>{selectedRowsState.length}</a>{' '}
<FormattedMessage
id="pages.searchTable.item"
defaultMessage="项"
/>
&nbsp;&nbsp;
<span>
<FormattedMessage
id="pages.searchTable.totalServiceCalls"
defaultMessage="Total number of service calls"
/>{' '}
{selectedRowsState.reduce(
(pre, item) => pre + (item.callNo ?? 0),
0,
)}{' '}
<FormattedMessage
id="pages.searchTable.tenThousand"
defaultMessage="万"
/>
</span>
</div>
}
>
<Button
loading={loading}
onClick={() => {
handleRemove(selectedRowsState);
}}
>
<FormattedMessage
id="pages.searchTable.batchDeletion"
defaultMessage="Batch deletion"
/>
</Button>
<Button type="primary">
<FormattedMessage
id="pages.searchTable.batchApproval"
defaultMessage="Batch approval"
/>
</Button>
</FooterToolbar>
)}
// return (
// <PageContainer>
// {contextHolder}
// <ProTable<API.RuleListItem, API.PageParams>
// headerTitle={intl.formatMessage({
// id: 'pages.searchTable.title',
// defaultMessage: 'Enquiry form',
// })}
// actionRef={actionRef}
// rowKey="key"
// search={{
// labelWidth: 120,
// }}
// toolBarRender={() => [
// <CreateForm key="create" reload={actionRef.current?.reload} />,
// ]}
// request={rule}
// columns={columns}
// rowSelection={{
// onChange: (_, selectedRows) => {
// setSelectedRows(selectedRows);
// },
// }}
// />
// {selectedRowsState?.length > 0 && (
// <FooterToolbar
// extra={
// <div>
// <FormattedMessage
// id="pages.searchTable.chosen"
// defaultMessage="Chosen"
// />{' '}
// <a style={{ fontWeight: 600 }}>{selectedRowsState.length}</a>{' '}
// <FormattedMessage
// id="pages.searchTable.item"
// defaultMessage="项"
// />
// &nbsp;&nbsp;
// <span>
// <FormattedMessage
// id="pages.searchTable.totalServiceCalls"
// defaultMessage="Total number of service calls"
// />{' '}
// {selectedRowsState.reduce(
// (pre, item) => pre + (item.callNo ?? 0),
// 0,
// )}{' '}
// <FormattedMessage
// id="pages.searchTable.tenThousand"
// defaultMessage="万"
// />
// </span>
// </div>
// }
// >
// <Button
// loading={loading}
// onClick={() => {
// handleRemove(selectedRowsState);
// }}
// >
// <FormattedMessage
// id="pages.searchTable.batchDeletion"
// defaultMessage="Batch deletion"
// />
// </Button>
// <Button type="primary">
// <FormattedMessage
// id="pages.searchTable.batchApproval"
// defaultMessage="Batch approval"
// />
// </Button>
// </FooterToolbar>
// )}
<Drawer
width={600}
open={showDetail}
onClose={() => {
setCurrentRow(undefined);
setShowDetail(false);
}}
closable={false}
>
{currentRow?.name && (
<ProDescriptions<API.RuleListItem>
column={2}
title={currentRow?.name}
request={async () => ({
data: currentRow || {},
})}
params={{
id: currentRow?.name,
}}
columns={columns as ProDescriptionsItemProps<API.RuleListItem>[]}
/>
)}
</Drawer>
</PageContainer>
);
};
// <Drawer
// width={600}
// open={showDetail}
// onClose={() => {
// setCurrentRow(undefined);
// setShowDetail(false);
// }}
// closable={false}
// >
// {currentRow?.name && (
// <ProDescriptions<API.RuleListItem>
// column={2}
// title={currentRow?.name}
// request={async () => ({
// data: currentRow || {},
// })}
// params={{
// id: currentRow?.name,
// }}
// columns={columns as ProDescriptionsItemProps<API.RuleListItem>[]}
// />
// )}
// </Drawer>
// </PageContainer>
// );
// };
export default TableList;
// export default TableList;

File diff suppressed because it is too large Load Diff

View File

@@ -1,397 +1,283 @@
import {
AlipayCircleOutlined,
AlipayOutlined,
LockOutlined,
MobileOutlined,
TaobaoCircleOutlined,
TaobaoOutlined,
UserOutlined,
WeiboCircleOutlined,
} from '@ant-design/icons';
WeiboOutlined,
} from "@ant-design/icons";
import {
LoginForm,
LoginFormPage,
ProConfigProvider,
ProFormCaptcha,
ProFormCheckbox,
ProFormText,
} from '@ant-design/pro-components';
import {
FormattedMessage,
Helmet,
SelectLang,
useIntl,
useModel,
} from '@umijs/max';
import { Alert, App, Tabs } from 'antd';
import { createStyles } from 'antd-style';
import React, { useState } from 'react';
import { flushSync } from 'react-dom';
import { Footer } from '@/components';
import { login } from '@/services/ant-design-pro/api';
import { getFakeCaptcha } from '@/services/ant-design-pro/login';
import Settings from '../../../../config/defaultSettings';
} from "@ant-design/pro-components";
import { Button, Divider, Space, Tabs, message, theme } from "antd";
import type { CSSProperties } from "react";
import { useState } from "react";
const useStyles = createStyles(({ token }) => {
return {
action: {
marginLeft: '8px',
color: 'rgba(0, 0, 0, 0.2)',
fontSize: '24px',
verticalAlign: 'middle',
cursor: 'pointer',
transition: 'color 0.3s',
'&:hover': {
color: token.colorPrimaryActive,
},
},
lang: {
width: 42,
height: 42,
lineHeight: '42px',
position: 'fixed',
right: 16,
borderRadius: token.borderRadius,
':hover': {
backgroundColor: token.colorBgTextHover,
},
},
container: {
display: 'flex',
flexDirection: 'column',
height: '100vh',
overflow: 'auto',
backgroundImage:
"url('https://mdn.alipayobjects.com/yuyan_qk0oxh/afts/img/V-_oS6r-i7wAAAAAAAAAAAAAFl94AQBr')",
backgroundSize: '100% 100%',
},
};
});
type LoginType = "phone" | "account";
const ActionIcons = () => {
const { styles } = useStyles();
return (
<>
<AlipayCircleOutlined
key="AlipayCircleOutlined"
className={styles.action}
/>
<TaobaoCircleOutlined
key="TaobaoCircleOutlined"
className={styles.action}
/>
<WeiboCircleOutlined
key="WeiboCircleOutlined"
className={styles.action}
/>
</>
);
const iconStyles: CSSProperties = {
color: "rgba(0, 0, 0, 0.2)",
fontSize: "18px",
verticalAlign: "middle",
cursor: "pointer",
};
const Lang = () => {
const { styles } = useStyles();
const Page = () => {
const [loginType, setLoginType] = useState<LoginType>("phone");
const { token } = theme.useToken();
return (
<div className={styles.lang} data-lang>
{SelectLang && <SelectLang />}
</div>
);
};
const LoginMessage: React.FC<{
content: string;
}> = ({ content }) => {
return (
<Alert
<div
style={{
marginBottom: 24,
backgroundColor: "white",
height: "100vh",
}}
message={content}
type="error"
showIcon
/>
);
};
const Login: React.FC = () => {
const [userLoginState, setUserLoginState] = useState<API.LoginResult>({});
const [type, setType] = useState<string>('account');
const { initialState, setInitialState } = useModel('@@initialState');
const { styles } = useStyles();
const { message } = App.useApp();
const intl = useIntl();
const fetchUserInfo = async () => {
const userInfo = await initialState?.fetchUserInfo?.();
if (userInfo) {
flushSync(() => {
setInitialState((s) => ({
...s,
currentUser: userInfo,
}));
});
}
};
const handleSubmit = async (values: API.LoginParams) => {
try {
// 登录
const msg = await login({ ...values, type });
if (msg.status === 'ok') {
const defaultLoginSuccessMessage = intl.formatMessage({
id: 'pages.login.success',
defaultMessage: '登录成功!',
});
message.success(defaultLoginSuccessMessage);
await fetchUserInfo();
const urlParams = new URL(window.location.href).searchParams;
window.location.href = urlParams.get('redirect') || '/';
return;
}
console.log(msg);
// 如果失败去设置用户错误信息
setUserLoginState(msg);
} catch (error) {
const defaultLoginFailureMessage = intl.formatMessage({
id: 'pages.login.failure',
defaultMessage: '登录失败,请重试!',
});
console.log(error);
message.error(defaultLoginFailureMessage);
}
};
const { status, type: loginType } = userLoginState;
return (
<div className={styles.container}>
<Helmet>
<title>
{intl.formatMessage({
id: 'menu.login',
defaultMessage: '登录页',
})}
{Settings.title && ` - ${Settings.title}`}
</title>
</Helmet>
<Lang />
<div
style={{
flex: '1',
padding: '32px 0',
>
<LoginFormPage
backgroundImageUrl="https://mdn.alipayobjects.com/huamei_gcee1x/afts/img/A*y0ZTS6WLwvgAAAAAAAAAAAAADml6AQ/fmt.webp"
logo="https://github.githubassets.com/favicons/favicon.png"
backgroundVideoUrl="https://gw.alipayobjects.com/v/huamei_gcee1x/afts/video/jXRBRK_VAwoAAAAAAAAAAAAAK4eUAQBr"
title="Github"
containerStyle={{
backgroundColor: "rgba(0, 0, 0,0.65)",
backdropFilter: "blur(4px)",
}}
>
<LoginForm
contentStyle={{
minWidth: 280,
maxWidth: '75vw',
}}
logo={<img alt="logo" src="/logo.svg" />}
title="Ant Design"
subTitle={intl.formatMessage({
id: 'pages.layouts.userLayout.title',
})}
initialValues={{
autoLogin: true,
}}
actions={[
<FormattedMessage
key="loginWith"
id="pages.login.loginWith"
defaultMessage="其他登录方式"
/>,
<ActionIcons key="icons" />,
]}
onFinish={async (values) => {
await handleSubmit(values as API.LoginParams);
}}
>
<Tabs
activeKey={type}
onChange={setType}
centered
items={[
{
key: 'account',
label: intl.formatMessage({
id: 'pages.login.accountLogin.tab',
defaultMessage: '账户密码登录',
}),
},
{
key: 'mobile',
label: intl.formatMessage({
id: 'pages.login.phoneLogin.tab',
defaultMessage: '手机号登录',
}),
},
]}
/>
{status === 'error' && loginType === 'account' && (
<LoginMessage
content={intl.formatMessage({
id: 'pages.login.accountLogin.errorMessage',
defaultMessage: '账户或密码错误(admin/ant.design)',
})}
/>
)}
{type === 'account' && (
<>
<ProFormText
name="username"
fieldProps={{
size: 'large',
prefix: <UserOutlined />,
}}
placeholder={intl.formatMessage({
id: 'pages.login.username.placeholder',
defaultMessage: '用户名: admin or user',
})}
rules={[
{
required: true,
message: (
<FormattedMessage
id="pages.login.username.required"
defaultMessage="请输入用户名!"
/>
),
},
]}
/>
<ProFormText.Password
name="password"
fieldProps={{
size: 'large',
prefix: <LockOutlined />,
}}
placeholder={intl.formatMessage({
id: 'pages.login.password.placeholder',
defaultMessage: '密码: ant.design',
})}
rules={[
{
required: true,
message: (
<FormattedMessage
id="pages.login.password.required"
defaultMessage="请输入密码!"
/>
),
},
]}
/>
</>
)}
{status === 'error' && loginType === 'mobile' && (
<LoginMessage content="验证码错误" />
)}
{type === 'mobile' && (
<>
<ProFormText
fieldProps={{
size: 'large',
prefix: <MobileOutlined />,
}}
name="mobile"
placeholder={intl.formatMessage({
id: 'pages.login.phoneNumber.placeholder',
defaultMessage: '手机号',
})}
rules={[
{
required: true,
message: (
<FormattedMessage
id="pages.login.phoneNumber.required"
defaultMessage="请输入手机号!"
/>
),
},
{
pattern: /^1\d{10}$/,
message: (
<FormattedMessage
id="pages.login.phoneNumber.invalid"
defaultMessage="手机号格式错误!"
/>
),
},
]}
/>
<ProFormCaptcha
fieldProps={{
size: 'large',
prefix: <LockOutlined />,
}}
captchaProps={{
size: 'large',
}}
placeholder={intl.formatMessage({
id: 'pages.login.captcha.placeholder',
defaultMessage: '请输入验证码',
})}
captchaTextRender={(timing, count) => {
if (timing) {
return `${count} ${intl.formatMessage({
id: 'pages.getCaptchaSecondText',
defaultMessage: '获取验证码',
})}`;
}
return intl.formatMessage({
id: 'pages.login.phoneLogin.getVerificationCode',
defaultMessage: '获取验证码',
});
}}
name="captcha"
rules={[
{
required: true,
message: (
<FormattedMessage
id="pages.login.captcha.required"
defaultMessage="请输入验证码!"
/>
),
},
]}
onGetCaptcha={async (phone) => {
const result = await getFakeCaptcha({
phone,
});
if (!result) {
return;
}
message.success('获取验证码成功验证码为1234');
}}
/>
</>
)}
<div
style={{
marginBottom: 24,
}}
>
<ProFormCheckbox noStyle name="autoLogin">
<FormattedMessage
id="pages.login.rememberMe"
defaultMessage="自动登录"
/>
</ProFormCheckbox>
<a
subTitle="全球最大的代码托管平台"
activityConfig={{
style: {
boxShadow: "0px 0px 8px rgba(0, 0, 0, 0.2)",
color: token.colorTextHeading,
borderRadius: 8,
backgroundColor: "rgba(255,255,255,0.25)",
backdropFilter: "blur(4px)",
},
title: "活动标题,可配置图片",
subTitle: "活动介绍说明文字",
action: (
<Button
size="large"
style={{
float: 'right',
borderRadius: 20,
background: token.colorBgElevated,
color: token.colorPrimary,
width: 120,
}}
>
<FormattedMessage
id="pages.login.forgotPassword"
defaultMessage="忘记密码"
/>
</a>
</Button>
),
}}
actions={
<div
style={{
display: "flex",
justifyContent: "center",
alignItems: "center",
flexDirection: "column",
}}
>
<Divider plain>
<span
style={{
color: token.colorTextPlaceholder,
fontWeight: "normal",
fontSize: 14,
}}
>
</span>
</Divider>
<Space align="center" size={24}>
<div
style={{
display: "flex",
justifyContent: "center",
alignItems: "center",
flexDirection: "column",
height: 40,
width: 40,
border: "1px solid " + token.colorPrimaryBorder,
borderRadius: "50%",
}}
>
<AlipayOutlined style={{ ...iconStyles, color: "#1677FF" }} />
</div>
<div
style={{
display: "flex",
justifyContent: "center",
alignItems: "center",
flexDirection: "column",
height: 40,
width: 40,
border: "1px solid " + token.colorPrimaryBorder,
borderRadius: "50%",
}}
>
<TaobaoOutlined style={{ ...iconStyles, color: "#FF6A10" }} />
</div>
<div
style={{
display: "flex",
justifyContent: "center",
alignItems: "center",
flexDirection: "column",
height: 40,
width: 40,
border: "1px solid " + token.colorPrimaryBorder,
borderRadius: "50%",
}}
>
<WeiboOutlined style={{ ...iconStyles, color: "#1890ff" }} />
</div>
</Space>
</div>
</LoginForm>
</div>
<Footer />
}
>
<Tabs
centered
activeKey={loginType}
onChange={(activeKey) => setLoginType(activeKey as LoginType)}
>
<Tabs.TabPane key={"account"} tab={"账号密码登录"} />
<Tabs.TabPane key={"phone"} tab={"手机号登录"} />
</Tabs>
{loginType === "account" && (
<>
<ProFormText
name="username"
fieldProps={{
size: "large",
prefix: (
<UserOutlined
style={{
color: token.colorText,
}}
className={"prefixIcon"}
/>
),
}}
placeholder={"用户名: admin or user"}
rules={[
{
required: true,
message: "请输入用户名!",
},
]}
/>
<ProFormText.Password
name="password"
fieldProps={{
size: "large",
prefix: (
<LockOutlined
style={{
color: token.colorText,
}}
className={"prefixIcon"}
/>
),
}}
placeholder={"密码: ant.design"}
rules={[
{
required: true,
message: "请输入密码!",
},
]}
/>
</>
)}
{loginType === "phone" && (
<>
<ProFormText
fieldProps={{
size: "large",
prefix: (
<MobileOutlined
style={{
color: token.colorText,
}}
className={"prefixIcon"}
/>
),
}}
name="mobile"
placeholder={"手机号"}
rules={[
{
required: true,
message: "请输入手机号!",
},
{
pattern: /^1\d{10}$/,
message: "手机号格式错误!",
},
]}
/>
<ProFormCaptcha
fieldProps={{
size: "large",
prefix: (
<LockOutlined
style={{
color: token.colorText,
}}
className={"prefixIcon"}
/>
),
}}
captchaProps={{
size: "large",
}}
placeholder={"请输入验证码"}
captchaTextRender={(timing, count) => {
if (timing) {
return `${count} ${"获取验证码"}`;
}
return "获取验证码";
}}
name="captcha"
rules={[
{
required: true,
message: "请输入验证码!",
},
]}
onGetCaptcha={async () => {
message.success("获取验证码成功验证码为1234");
}}
/>
</>
)}
<div
style={{
marginBlockEnd: 24,
}}
>
<ProFormCheckbox noStyle name="autoLogin">
</ProFormCheckbox>
<a
style={{
float: "right",
}}
>
</a>
</div>
</LoginFormPage>
</div>
);
};
export default Login;
export default () => {
return (
<ProConfigProvider dark>
<Page />
</ProConfigProvider>
);
};

View File

@@ -1,102 +0,0 @@
// @ts-ignore
import { startMock } from '@@/requestRecordMock';
import { TestBrowser } from '@@/testBrowser';
import { fireEvent, render } from '@testing-library/react';
import React, { act } from 'react';
const waitTime = (time: number = 100) => {
return new Promise((resolve) => {
setTimeout(() => {
resolve(true);
}, time);
});
};
let server: {
close: () => void;
};
describe('Login Page', () => {
beforeAll(async () => {
server = await startMock({
port: 8000,
scene: 'login',
});
});
afterAll(() => {
server?.close();
});
it('should show login form', async () => {
const historyRef = React.createRef<any>();
const rootContainer = render(
<TestBrowser
historyRef={historyRef}
location={{
pathname: '/user/login',
}}
/>,
);
await rootContainer.findAllByText('Ant Design');
act(() => {
historyRef.current?.push('/user/login');
});
expect(
rootContainer.baseElement?.querySelector('.ant-pro-form-login-desc')
?.textContent,
).toBe(
'Ant Design is the most influential web design specification in Xihu district',
);
expect(rootContainer.asFragment()).toMatchSnapshot();
rootContainer.unmount();
});
it('should login success', async () => {
const historyRef = React.createRef<any>();
const rootContainer = render(
<TestBrowser
historyRef={historyRef}
location={{
pathname: '/user/login',
}}
/>,
);
await rootContainer.findAllByText('Ant Design');
const userNameInput = await rootContainer.findByPlaceholderText(
'Username: admin or user',
);
act(() => {
fireEvent.change(userNameInput, { target: { value: 'admin' } });
});
const passwordInput = await rootContainer.findByPlaceholderText(
'Password: ant.design',
);
act(() => {
fireEvent.change(passwordInput, { target: { value: 'ant.design' } });
});
await (await rootContainer.findByText('Login')).click();
// 等待接口返回结果
await waitTime(5000);
await rootContainer.findAllByText('Ant Design Pro');
expect(rootContainer.asFragment()).toMatchSnapshot();
await waitTime(2000);
rootContainer.unmount();
});
});

View File

@@ -1,94 +0,0 @@
// @ts-ignore
/* eslint-disable */
import { request } from '@umijs/max';
/** 获取当前的用户 GET /api/currentUser */
export async function currentUser(options?: { [key: string]: any }) {
return request<{
data: API.CurrentUser;
}>('/api/currentUser', {
method: 'GET',
...(options || {}),
});
}
/** 退出登录接口 POST /api/login/outLogin */
export async function outLogin(options?: { [key: string]: any }) {
return request<Record<string, any>>('/api/login/outLogin', {
method: 'POST',
...(options || {}),
});
}
/** 登录接口 POST /api/login/account */
export async function login(body: API.LoginParams, options?: { [key: string]: any }) {
return request<API.LoginResult>('/api/login/account', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
data: body,
...(options || {}),
});
}
/** 此处后端没有提供注释 GET /api/notices */
export async function getNotices(options?: { [key: string]: any }) {
return request<API.NoticeIconList>('/api/notices', {
method: 'GET',
...(options || {}),
});
}
/** 获取规则列表 GET /api/rule */
export async function rule(
params: {
// query
/** 当前的页码 */
current?: number;
/** 页面的容量 */
pageSize?: number;
},
options?: { [key: string]: any },
) {
return request<API.RuleList>('/api/rule', {
method: 'GET',
params: {
...params,
},
...(options || {}),
});
}
/** 更新规则 PUT /api/rule */
export async function updateRule(options?: { [key: string]: any }) {
return request<API.RuleListItem>('/api/rule', {
method: 'POST',
data: {
method: 'update',
...(options || {}),
},
});
}
/** 新建规则 POST /api/rule */
export async function addRule(options?: { [key: string]: any }) {
return request<API.RuleListItem>('/api/rule', {
method: 'POST',
data: {
method: 'post',
...(options || {}),
},
});
}
/** 删除规则 DELETE /api/rule */
export async function removeRule(options?: { [key: string]: any }) {
return request<Record<string, any>>('/api/rule', {
method: 'POST',
data: {
method: 'delete',
...(options || {}),
},
});
}

View File

@@ -1,21 +0,0 @@
// @ts-ignore
/* eslint-disable */
import { request } from '@umijs/max';
/** 发送验证码 POST /api/login/captcha */
export async function getFakeCaptcha(
params: {
// query
/** 手机号 */
phone?: string;
},
options?: { [key: string]: any },
) {
return request<API.FakeCaptcha>('/api/login/captcha', {
method: 'GET',
params: {
...params,
},
...(options || {}),
});
}

View File

@@ -1,101 +0,0 @@
// @ts-ignore
/* eslint-disable */
declare namespace API {
type CurrentUser = {
name?: string;
avatar?: string;
userid?: string;
email?: string;
signature?: string;
title?: string;
group?: string;
tags?: { key?: string; label?: string }[];
notifyCount?: number;
unreadCount?: number;
country?: string;
access?: string;
geographic?: {
province?: { label?: string; key?: string };
city?: { label?: string; key?: string };
};
address?: string;
phone?: string;
};
type LoginResult = {
status?: string;
type?: string;
currentAuthority?: string;
};
type PageParams = {
current?: number;
pageSize?: number;
};
type RuleListItem = {
key?: number;
disabled?: boolean;
href?: string;
avatar?: string;
name?: string;
owner?: string;
desc?: string;
callNo?: number;
status?: number;
updatedAt?: string;
createdAt?: string;
progress?: number;
};
type RuleList = {
data?: RuleListItem[];
/** 列表的内容总数 */
total?: number;
success?: boolean;
};
type FakeCaptcha = {
code?: number;
status?: string;
};
type LoginParams = {
username?: string;
password?: string;
autoLogin?: boolean;
type?: string;
};
type ErrorResponse = {
/** 业务约定的错误码 */
errorCode: string;
/** 业务上的错误信息 */
errorMessage?: string;
/** 业务上的请求是否成功 */
success?: boolean;
};
type NoticeIconList = {
data?: NoticeIconItem[];
/** 列表的内容总数 */
total?: number;
success?: boolean;
};
type NoticeIconItemType = 'notification' | 'message' | 'event';
type NoticeIconItem = {
id?: string;
extra?: string;
key?: string;
read?: boolean;
avatar?: string;
title?: string;
status?: string;
datetime?: string;
description?: string;
type?: NoticeIconItemType;
};
}

153
src/services/login/index.ts Normal file
View File

@@ -0,0 +1,153 @@
import { request } from "@umijs/max";
import * as API from "./types";
export interface SmsCodeVO {
mobile: string;
scene: number;
}
export interface SmsLoginVO {
mobile: string;
code: string;
}
// 登录
// export const login = (data: UserLoginVO) => {
// return request.post({ url: '/system/auth/login', data })
// }
export async function login(
body: API.UserLoginVO,
options?: { [key: string]: any }
) {
return request<API.TokenType>("/system/auth/login", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
data: body,
...(options || {}),
});
}
// 注册
// export const register = (data: RegisterVO) => {
// return request.post({ url: "/system/auth/register", data });
// };
// 使用租户名,获得租户编号
// export const getTenantIdByName = (name: string) => {
// return request.get({ url: "/system/tenant/get-id-by-name?name=" + name });
// };
export async function getTenantIdByName(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: { name: string },
options?: { [key: string]: any }
) {
return request("/system/tenant/get-id-by-name", {
method: "GET",
params: {
...params,
},
...(options || {}),
});
}
// 使用租户域名,获得租户信息
// export const getTenantByWebsite = (website: string) => {
// return request.get({
// url: "/system/tenant/get-by-website?website=" + website,
// });
// };
export async function getTenantByWebsite(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: { website: string },
options?: { [key: string]: any }
) {
return request("/system/tenant/get-by-website", {
method: "GET",
params: {
...params,
},
...(options || {}),
});
}
// 登出
// export const loginOut = () => {
// return request.post({ url: "/system/auth/logout" });
// };
export async function loginOut(
body: API.UserLoginVO,
options?: { [key: string]: any }
) {
return request("/system/auth/logout", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
data: body,
...(options || {}),
});
}
// 获取用户权限信息
// export const getInfo = () => {
// return request.get({ url: "/system/auth/get-permission-info" });
// };
export async function getInfo(options?: { [key: string]: any }) {
return request<IResponse<{ user: API.UserVO }>>(
"/system/auth/get-permission-info",
{
method: "GET",
headers: {
"Content-Type": "application/json",
},
...(options || {}),
}
);
}
//获取登录验证码
// export const sendSmsCode = (data: SmsCodeVO) => {
// return request.post({ url: "/system/auth/send-sms-code", data });
// };
// // 短信验证码登录
// export const smsLogin = (data: SmsLoginVO) => {
// return request.post({ url: "/system/auth/sms-login", data });
// };
// 社交快捷登录,使用 code 授权码
// export function socialLogin(type: string, code: string, state: string) {
// return request.post({
// url: "/system/auth/social-login",
// data: {
// type,
// code,
// state,
// },
// });
// }
// 社交授权的跳转
// export const socialAuthRedirect = (type: number, redirectUri: string) => {
// return request.get({
// url:
// "/system/auth/social-auth-redirect?type=" +
// type +
// "&redirectUri=" +
// redirectUri,
// });
// };
// 获取验证图片以及 token
// export const getCode = (data: any) => {
// debugger;
// return request.postOriginal({ url: "system/captcha/get", data });
// };
// 滑动或者点选验证
// export const reqCheck = (data: any) => {
// return request.postOriginal({ url: "system/captcha/check", data });
// };
// 通过短信重置密码
// export const smsResetPassword = (data: any) => {
// return request.post({ url: "/system/auth/reset-password", data });
// };

View File

@@ -0,0 +1,41 @@
import request from '@/config/axios'
// 获得授权信息
export const getAuthorize = (clientId: string) => {
return request.get({ url: '/system/oauth2/authorize?clientId=' + clientId })
}
// 发起授权
export const authorize = (
responseType: string,
clientId: string,
redirectUri: string,
state: string,
autoApprove: boolean,
checkedScopes: string[],
uncheckedScopes: string[]
) => {
// 构建 scopes
const scopes = {}
for (const scope of checkedScopes) {
scopes[scope] = true
}
for (const scope of uncheckedScopes) {
scopes[scope] = false
}
// 发起请求
return request.post({
url: '/system/oauth2/authorize',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
params: {
response_type: responseType,
client_id: clientId,
redirect_uri: redirectUri,
state: state,
auto_approve: autoApprove,
scope: JSON.stringify(scopes)
}
})
}

View File

@@ -0,0 +1,38 @@
export type UserLoginVO = {
username: string
password: string
captchaVerification: string
socialType?: string
socialCode?: string
socialState?: string
}
export type TokenType = {
id: number // 编号
accessToken: string // 访问令牌
refreshToken: string // 刷新令牌
userId: number // 用户编号
userType: number //用户类型
clientId: string //客户端编号
expiresTime: number //过期时间
}
export type UserVO = {
id: number
username: string
nickname: string
deptId: number
email: string
mobile: string
sex: number
avatar: string
loginIp: string
loginDate: string
}
export type RegisterVO = {
tenantName: string
username: string
password: string
captchaVerification: string
}

View File

@@ -0,0 +1,51 @@
// @ts-ignore
/* eslint-disable */
import { request } from "@umijs/max";
/** 获取菜单页面的表 GET /product/category/categoryList */
export async function getProductCategoryCategoryList(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.getProductCategoryCategoryListParams,
options?: { [key: string]: any }
) {
return request<API.CommonResultListCategoryDto>(
"/product/category/categoryList",
{
method: "GET",
params: {
...params,
},
...(options || {}),
}
);
}
/** 创建产品类目 创建产品类目 POST /product/category/create */
export async function postProductCategoryCreate(
body: API.CategorySaveReqVO,
options?: { [key: string]: any }
) {
return request<API.CommonResultLong>("/product/category/create", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
data: body,
...(options || {}),
});
}
/** 更新产品类目 更新产品类目 PUT /product/category/update */
export async function putProductCategoryUpdate(
body: API.CategorySaveReqVO,
options?: { [key: string]: any }
) {
return request<API.CommonResultBoolean>("/product/category/update", {
method: "PUT",
headers: {
"Content-Type": "application/json",
},
data: body,
...(options || {}),
});
}

View File

@@ -2,9 +2,9 @@
/* eslint-disable */
// API 更新时间:
// API 唯一标识:
import * as api from './api';
import * as login from './login';
import * as product from "./product";
import * as category from "./category";
export default {
api,
login,
product,
category,
};

View File

@@ -0,0 +1,601 @@
// @ts-ignore
/* eslint-disable */
import { request } from "@umijs/max";
/** 创建商品 创建商品 POST /prod/create */
export async function postProdCreate(
body: API.ProdSaveReqVO,
options?: { [key: string]: any }
) {
return request<API.CommonResultLong>("/prod/create", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
data: body,
...(options || {}),
});
}
/** 创建商品 创建商品 POST /product/prod/create */
export async function postProductProdCreate(
body: API.ProdSaveReqVO,
options?: { [key: string]: any }
) {
return request<API.CommonResultLong>("/product/prod/create", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
data: body,
...(options || {}),
});
}
/** 创建商品服务配置 创建商品服务配置 POST /product/prod/createProdService */
export async function postProductProdCreateProdService(
body: API.ProdServiceVO,
options?: { [key: string]: any }
) {
return request<API.CommonResultBoolean>("/product/prod/createProdService", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
data: body,
...(options || {}),
});
}
/** 删除商品 删除商品 DELETE /product/prod/delete */
export async function deleteProductProdOpenApiDelete(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.deleteProductProd_openAPI_deleteParams,
options?: { [key: string]: any }
) {
return request<API.CommonResultBoolean>("/product/prod/delete", {
method: "DELETE",
params: {
...params,
},
...(options || {}),
});
}
/** 批量删除商品 批量删除商品 DELETE /product/prod/deleteSkuList */
export async function deleteProductProdDeleteSkuList(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.deleteProductProdDeleteSkuListParams,
options?: { [key: string]: any }
) {
return request<API.CommonResultBoolean>("/product/prod/deleteSkuList", {
method: "DELETE",
params: {
...params,
},
...(options || {}),
});
}
/** 获得商品回收站分页列表 获得商品回收站分页列表 GET /product/prod/getProdRecycleBinPageList */
export async function getProductProdGetProdRecycleBinPageList(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.getProductProdGetProdRecycleBinPageListParams,
options?: { [key: string]: any }
) {
return request<API.CommonResultPageResultProdRestoreListVO>(
"/product/prod/getProdRecycleBinPageList",
{
method: "GET",
params: {
// pageNo has a default value: 1
pageNo: "1",
// pageSize has a default value: 10
pageSize: "10",
...params,
},
...(options || {}),
}
);
}
/** 获得商品服务信息 获得商品服务信息 GET /product/prod/getProdService */
export async function getProductProdGetProdService(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.getProductProdGetProdServiceParams,
options?: { [key: string]: any }
) {
return request<API.CommonResultProdServiceVO>(
"/product/prod/getProdService",
{
method: "GET",
params: {
...params,
},
...(options || {}),
}
);
}
/** 获得商品分页 获得商品分页 GET /product/prod/page */
export async function getProductProdPage(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.getProductProdPageParams,
options?: { [key: string]: any }
) {
return request<API.CommonResultPageResultProdListVO>("/product/prod/page", {
method: "GET",
params: {
// pageNo has a default value: 1
pageNo: "1",
// pageSize has a default value: 10
pageSize: "10",
...params,
},
...(options || {}),
});
}
/** 恢复商品 恢复商品 POST /product/prod/restoreProdList */
export async function postProductProdRestoreProdList(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.postProductProdRestoreProdListParams,
options?: { [key: string]: any }
) {
return request<API.CommonResultBoolean>("/product/prod/restoreProdList", {
method: "POST",
params: {
...params,
},
...(options || {}),
});
}
/** 更新商品 更新商品 PUT /product/prod/update */
export async function putProductProdUpdate(
body: API.ProdSaveReqVO,
options?: { [key: string]: any }
) {
return request<API.CommonResultBoolean>("/product/prod/update", {
method: "PUT",
headers: {
"Content-Type": "application/json",
},
data: body,
...(options || {}),
});
}
/** 批量上下架 批量上下架 DELETE /product/prod/updateSkuShelfList */
export async function deleteProductProdUpdateSkuShelfList(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.deleteProductProdUpdateSkuShelfListParams,
options?: { [key: string]: any }
) {
return request<API.CommonResultBoolean>("/product/prod/updateSkuShelfList", {
method: "DELETE",
params: {
...params,
},
...(options || {}),
});
}
/** 修改商品服务配置 修改商品服务配置 POST /product/prod/uptateProdService */
export async function postProductProdUptateProdService(
body: API.ProdServiceInfoVO,
options?: { [key: string]: any }
) {
return request<API.CommonResultBoolean>("/product/prod/uptateProdService", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
data: body,
...(options || {}),
});
}
/** 创建sku扩展服务配置 创建sku扩展服务配置 POST /product/sku/createSkuExtend */
export async function postProductSkuCreateSkuExtend(
body: API.SkuExtendVO,
options?: { [key: string]: any }
) {
return request<API.CommonResultBoolean>("/product/sku/createSkuExtend", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
data: body,
...(options || {}),
});
}
/** 删除单品SKU 删除单品SKU DELETE /product/sku/delete */
export async function deleteProductSkuOpenApiDelete(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.deleteProductSku_openAPI_deleteParams,
options?: { [key: string]: any }
) {
return request<API.CommonResultBoolean>("/product/sku/delete", {
method: "DELETE",
params: {
...params,
},
...(options || {}),
});
}
/** 删除规格值 删除规格值 PUT /product/sku/deleteProp */
export async function putProductSkuDeleteProp(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.putProductSkuDeletePropParams,
options?: { [key: string]: any }
) {
return request<API.CommonResultBoolean>("/product/sku/deleteProp", {
method: "PUT",
params: {
...params,
},
...(options || {}),
});
}
/** 批量删除SKU 批量删除SKU DELETE /product/sku/deleteSkuList */
export async function deleteProductSkuDeleteSkuList(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.deleteProductSkuDeleteSkuListParams,
options?: { [key: string]: any }
) {
return request<API.CommonResultBoolean>("/product/sku/deleteSkuList", {
method: "DELETE",
params: {
...params,
},
...(options || {}),
});
}
/** 禁用或者启用规格值 禁用规格值 PUT /product/sku/disableProp */
export async function putProductSkuDisableProp(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.putProductSkuDisablePropParams,
options?: { [key: string]: any }
) {
return request<API.CommonResultBoolean>("/product/sku/disableProp", {
method: "PUT",
params: {
...params,
},
...(options || {}),
});
}
/** 获得单品SKU 获得单品SKU GET /product/sku/get */
export async function getProductSkuGet(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.getProductSkuGetParams,
options?: { [key: string]: any }
) {
return request<API.CommonResultSkuRespVO>("/product/sku/get", {
method: "GET",
params: {
...params,
},
...(options || {}),
});
}
/** 获取规格回收站 获取规格回收站 GET /product/sku/getPropRecycleBinList */
export async function getProductSkuGetPropRecycleBinList(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.getProductSkuGetPropRecycleBinListParams,
options?: { [key: string]: any }
) {
return request<API.CommonResultPageResultProPropRecycleBinVO>(
"/product/sku/getPropRecycleBinList",
{
method: "GET",
params: {
// pageNo has a default value: 1
pageNo: "1",
// pageSize has a default value: 10
pageSize: "10",
...params,
},
...(options || {}),
}
);
}
/** 获取sku扩展服务配置信息 获取sku扩展服务配置信息 POST /product/sku/getSkuExtend */
export async function postProductSkuGetSkuExtend(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.postProductSkuGetSkuExtendParams,
options?: { [key: string]: any }
) {
return request<API.CommonResultSkuExtendVO>("/product/sku/getSkuExtend", {
method: "POST",
params: {
...params,
},
...(options || {}),
});
}
/** 获得SKU分页列表 获得SKU分页列表 GET /product/sku/getSkuPageList */
export async function getProductSkuGetSkuPageList(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.getProductSkuGetSkuPageListParams,
options?: { [key: string]: any }
) {
return request<API.CommonResultPageResultSkuDO>(
"/product/sku/getSkuPageList",
{
method: "GET",
params: {
// pageNo has a default value: 1
pageNo: "1",
// pageSize has a default value: 10
pageSize: "10",
...params,
},
...(options || {}),
}
);
}
/** 获取sku规格 获取sku规格 GET /product/sku/getSKuPropList */
export async function getProductSkuGetSKuPropList(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.getProductSkuGetSKuPropListParams,
options?: { [key: string]: any }
) {
return request<API.CommonResultSkuPropInfoVO>("/product/sku/getSKuPropList", {
method: "GET",
params: {
...params,
},
...(options || {}),
});
}
/** 获得SKU回收站分页列表 获得SKU回收站分页列表 GET /product/sku/getSkuRecycleBinPageList */
export async function getProductSkuGetSkuRecycleBinPageList(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.getProductSkuGetSkuRecycleBinPageListParams,
options?: { [key: string]: any }
) {
return request<API.CommonResultPageResultSkuRecycleBinVO>(
"/product/sku/getSkuRecycleBinPageList",
{
method: "GET",
params: {
// pageNo has a default value: 1
pageNo: "1",
// pageSize has a default value: 10
pageSize: "10",
...params,
},
...(options || {}),
}
);
}
/** 恢复规格 恢复规格 POST /product/sku/restorePropList */
export async function postProductSkuRestorePropList(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.postProductSkuRestorePropListParams,
options?: { [key: string]: any }
) {
return request<API.CommonResultBoolean>("/product/sku/restorePropList", {
method: "POST",
params: {
...params,
},
...(options || {}),
});
}
/** 恢复SKU 恢复SKU POST /product/sku/restoreSkuList */
export async function postProductSkuRestoreSkuList(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.postProductSkuRestoreSkuListParams,
options?: { [key: string]: any }
) {
return request<API.CommonResultBoolean>("/product/sku/restoreSkuList", {
method: "POST",
params: {
...params,
},
...(options || {}),
});
}
/** 更新单品SKU 更新单品SKU PUT /product/sku/update */
export async function putProductSkuUpdate(
body: API.SkuSaveReqVO,
options?: { [key: string]: any }
) {
return request<API.CommonResultBoolean>("/product/sku/update", {
method: "PUT",
headers: {
"Content-Type": "application/json",
},
data: body,
...(options || {}),
});
}
/** 修改配送方式 修改配送方式 POST /product/sku/updateDeliver */
export async function postProductSkuUpdateDeliver(
body: API.SkuServiceDeliverDO[],
options?: { [key: string]: any }
) {
return request<API.CommonResultBoolean>("/product/sku/updateDeliver", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
data: body,
...(options || {}),
});
}
/** 修物料配置 修物料配置 POST /product/sku/updateMaterial */
export async function postProductSkuUpdateMaterial(
body: API.SkuServiceMaterialDO[],
options?: { [key: string]: any }
) {
return request<API.CommonResultBoolean>("/product/sku/updateMaterial", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
data: body,
...(options || {}),
});
}
/** 修改属性规格值 修改属性规格值 PUT /product/sku/updateProdProp */
export async function putProductSkuUpdateProdProp(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.putProductSkuUpdateProdPropParams,
options?: { [key: string]: any }
) {
return request<API.CommonResultBoolean>("/product/sku/updateProdProp", {
method: "PUT",
params: {
...params,
},
...(options || {}),
});
}
/** 新增统一保存sku规格 更新sku规格 PUT /product/sku/updateProp */
export async function putProductSkuUpdateProp(
body: API.SkuPropVO,
options?: { [key: string]: any }
) {
return request<API.CommonResultBoolean>("/product/sku/updateProp", {
method: "PUT",
headers: {
"Content-Type": "application/json",
},
data: body,
...(options || {}),
});
}
/** 修改属性下面规格值 修改属性下面规格值 PUT /product/sku/updatePropValue */
export async function putProductSkuUpdatePropValue(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.putProductSkuUpdatePropValueParams,
options?: { [key: string]: any }
) {
return request<API.CommonResultBoolean>("/product/sku/updatePropValue", {
method: "PUT",
params: {
...params,
},
...(options || {}),
});
}
/** 修改扩展服务信息配置(遗体接运扩展服务,遗体清洁配置,追思告别配置,骨灰处理配置...... 修改扩展服务信息配置(遗体接运扩展服务,遗体清洁配置,追思告别配置,骨灰处理配置...... POST /product/sku/updateServiceDetails */
export async function postProductSkuUpdateServiceDetails(
body: API.SkuServiceDetailsDO[],
options?: { [key: string]: any }
) {
return request<API.CommonResultBoolean>("/product/sku/updateServiceDetails", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
data: body,
...(options || {}),
});
}
/** 修改单品上下架 修改单品上下架 PUT /product/sku/updateSkuShelf */
export async function putProductSkuUpdateSkuShelf(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.putProductSkuUpdateSkuShelfParams,
options?: { [key: string]: any }
) {
return request<API.CommonResultBoolean>("/product/sku/updateSkuShelf", {
method: "PUT",
params: {
...params,
},
...(options || {}),
});
}
/** 修改单品上下架 修改单品上下架 POST /product/sku/updateSkuShelf */
export async function postProductSkuUpdateSkuShelf(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.postProductSkuUpdateSkuShelfParams,
options?: { [key: string]: any }
) {
return request<API.CommonResultBoolean>("/product/sku/updateSkuShelf", {
method: "POST",
params: {
...params,
},
...(options || {}),
});
}
/** 批量上下架 批量上下架 PUT /product/sku/updateSkuShelfList */
export async function putProductSkuUpdateSkuShelfList(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.putProductSkuUpdateSkuShelfListParams,
options?: { [key: string]: any }
) {
return request<API.CommonResultBoolean>("/product/sku/updateSkuShelfList", {
method: "PUT",
params: {
...params,
},
...(options || {}),
});
}
/** 批量上下架 批量上下架 POST /product/sku/updateSkuShelfList */
export async function postProductSkuUpdateSkuShelfList(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.postProductSkuUpdateSkuShelfListParams,
options?: { [key: string]: any }
) {
return request<API.CommonResultBoolean>("/product/sku/updateSkuShelfList", {
method: "POST",
params: {
...params,
},
...(options || {}),
});
}
/** 修改接运地址配置 修改接运地址配置 POST /product/sku/updateTransportAdress */
export async function postProductSkuUpdateTransportAdress(
body: API.SkuServiceTransportDO[],
options?: { [key: string]: any }
) {
return request<API.CommonResultBoolean>(
"/product/sku/updateTransportAdress",
{
method: "POST",
headers: {
"Content-Type": "application/json",
},
data: body,
...(options || {}),
}
);
}

2086
src/services/prodApi/typings.d.ts vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,12 +0,0 @@
// @ts-ignore
/* eslint-disable */
// API 更新时间:
// API 唯一标识:
import * as pet from './pet';
import * as store from './store';
import * as user from './user';
export default {
pet,
store,
user,
};

View File

@@ -1,153 +0,0 @@
// @ts-ignore
/* eslint-disable */
import { request } from '@umijs/max';
/** Update an existing pet PUT /pet */
export async function updatePet(body: API.Pet, options?: { [key: string]: any }) {
return request<any>('/pet', {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
},
data: body,
...(options || {}),
});
}
/** Add a new pet to the store POST /pet */
export async function addPet(body: API.Pet, options?: { [key: string]: any }) {
return request<any>('/pet', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
data: body,
...(options || {}),
});
}
/** Find pet by ID Returns a single pet GET /pet/${param0} */
export async function getPetById(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.getPetByIdParams,
options?: { [key: string]: any },
) {
const { petId: param0, ...queryParams } = params;
return request<API.Pet>(`/pet/${param0}`, {
method: 'GET',
params: { ...queryParams },
...(options || {}),
});
}
/** Updates a pet in the store with form data POST /pet/${param0} */
export async function updatePetWithForm(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.updatePetWithFormParams,
body: { name?: string; status?: string },
options?: { [key: string]: any },
) {
const { petId: param0, ...queryParams } = params;
const formData = new FormData();
Object.keys(body).forEach((ele) => {
const item = (body as any)[ele];
if (item !== undefined && item !== null) {
formData.append(
ele,
typeof item === 'object' && !(item instanceof File) ? JSON.stringify(item) : item,
);
}
});
return request<any>(`/pet/${param0}`, {
method: 'POST',
params: { ...queryParams },
data: formData,
...(options || {}),
});
}
/** Deletes a pet DELETE /pet/${param0} */
export async function deletePet(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.deletePetParams & {
// header
api_key?: string;
},
options?: { [key: string]: any },
) {
const { petId: param0, ...queryParams } = params;
return request<any>(`/pet/${param0}`, {
method: 'DELETE',
headers: {},
params: { ...queryParams },
...(options || {}),
});
}
/** uploads an image POST /pet/${param0}/uploadImage */
export async function uploadFile(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.uploadFileParams,
body: { additionalMetadata?: string; file?: string },
file?: File,
options?: { [key: string]: any },
) {
const { petId: param0, ...queryParams } = params;
const formData = new FormData();
if (file) {
formData.append('file', file);
}
Object.keys(body).forEach((ele) => {
const item = (body as any)[ele];
if (item !== undefined && item !== null) {
formData.append(
ele,
typeof item === 'object' && !(item instanceof File) ? JSON.stringify(item) : item,
);
}
});
return request<API.ApiResponse>(`/pet/${param0}/uploadImage`, {
method: 'POST',
params: { ...queryParams },
data: formData,
requestType: 'form',
...(options || {}),
});
}
/** Finds Pets by status Multiple status values can be provided with comma separated strings GET /pet/findByStatus */
export async function findPetsByStatus(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.findPetsByStatusParams,
options?: { [key: string]: any },
) {
return request<API.Pet[]>('/pet/findByStatus', {
method: 'GET',
params: {
...params,
},
...(options || {}),
});
}
/** Finds Pets by tags Muliple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing. GET /pet/findByTags */
export async function findPetsByTags(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.findPetsByTagsParams,
options?: { [key: string]: any },
) {
return request<API.Pet[]>('/pet/findByTags', {
method: 'GET',
params: {
...params,
},
...(options || {}),
});
}

View File

@@ -1,48 +0,0 @@
// @ts-ignore
/* eslint-disable */
import { request } from '@umijs/max';
/** Returns pet inventories by status Returns a map of status codes to quantities GET /store/inventory */
export async function getInventory(options?: { [key: string]: any }) {
return request<Record<string, any>>('/store/inventory', {
method: 'GET',
...(options || {}),
});
}
/** Place an order for a pet POST /store/order */
export async function placeOrder(body: API.Order, options?: { [key: string]: any }) {
return request<API.Order>('/store/order', {
method: 'POST',
data: body,
...(options || {}),
});
}
/** Find purchase order by ID For valid response try integer IDs with value >= 1 and <= 10. Other values will generated exceptions GET /store/order/${param0} */
export async function getOrderById(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.getOrderByIdParams,
options?: { [key: string]: any },
) {
const { orderId: param0, ...queryParams } = params;
return request<API.Order>(`/store/order/${param0}`, {
method: 'GET',
params: { ...queryParams },
...(options || {}),
});
}
/** Delete purchase order by ID For valid response try integer IDs with positive integer value. Negative or non-integer values will generate API errors DELETE /store/order/${param0} */
export async function deleteOrder(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.deleteOrderParams,
options?: { [key: string]: any },
) {
const { orderId: param0, ...queryParams } = params;
return request<any>(`/store/order/${param0}`, {
method: 'DELETE',
params: { ...queryParams },
...(options || {}),
});
}

View File

@@ -1,112 +0,0 @@
declare namespace API {
type ApiResponse = {
code?: number;
type?: string;
message?: string;
};
type Category = {
id?: number;
name?: string;
};
type deleteOrderParams = {
/** ID of the order that needs to be deleted */
orderId: number;
};
type deletePetParams = {
api_key?: string;
/** Pet id to delete */
petId: number;
};
type deleteUserParams = {
/** The name that needs to be deleted */
username: string;
};
type findPetsByStatusParams = {
/** Status values that need to be considered for filter */
status: ('available' | 'pending' | 'sold')[];
};
type findPetsByTagsParams = {
/** Tags to filter by */
tags: string[];
};
type getOrderByIdParams = {
/** ID of pet that needs to be fetched */
orderId: number;
};
type getPetByIdParams = {
/** ID of pet to return */
petId: number;
};
type getUserByNameParams = {
/** The name that needs to be fetched. Use user1 for testing. */
username: string;
};
type loginUserParams = {
/** The user name for login */
username: string;
/** The password for login in clear text */
password: string;
};
type Order = {
id?: number;
petId?: number;
quantity?: number;
shipDate?: string;
/** Order Status */
status?: 'placed' | 'approved' | 'delivered';
complete?: boolean;
};
type Pet = {
id?: number;
category?: Category;
name: string;
photoUrls: string[];
tags?: Tag[];
/** pet status in the store */
status?: 'available' | 'pending' | 'sold';
};
type Tag = {
id?: number;
name?: string;
};
type updatePetWithFormParams = {
/** ID of pet that needs to be updated */
petId: number;
};
type updateUserParams = {
/** name that need to be updated */
username: string;
};
type uploadFileParams = {
/** ID of pet to update */
petId: number;
};
type User = {
id?: number;
username?: string;
firstName?: string;
lastName?: string;
email?: string;
password?: string;
phone?: string;
/** User Status */
userStatus?: number;
};
}

View File

@@ -1,100 +0,0 @@
// @ts-ignore
/* eslint-disable */
import { request } from '@umijs/max';
/** Create user This can only be done by the logged in user. POST /user */
export async function createUser(body: API.User, options?: { [key: string]: any }) {
return request<any>('/user', {
method: 'POST',
data: body,
...(options || {}),
});
}
/** Get user by user name GET /user/${param0} */
export async function getUserByName(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.getUserByNameParams,
options?: { [key: string]: any },
) {
const { username: param0, ...queryParams } = params;
return request<API.User>(`/user/${param0}`, {
method: 'GET',
params: { ...queryParams },
...(options || {}),
});
}
/** Updated user This can only be done by the logged in user. PUT /user/${param0} */
export async function updateUser(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.updateUserParams,
body: API.User,
options?: { [key: string]: any },
) {
const { username: param0, ...queryParams } = params;
return request<any>(`/user/${param0}`, {
method: 'PUT',
params: { ...queryParams },
data: body,
...(options || {}),
});
}
/** Delete user This can only be done by the logged in user. DELETE /user/${param0} */
export async function deleteUser(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.deleteUserParams,
options?: { [key: string]: any },
) {
const { username: param0, ...queryParams } = params;
return request<any>(`/user/${param0}`, {
method: 'DELETE',
params: { ...queryParams },
...(options || {}),
});
}
/** Creates list of users with given input array POST /user/createWithArray */
export async function createUsersWithArrayInput(
body: API.User[],
options?: { [key: string]: any },
) {
return request<any>('/user/createWithArray', {
method: 'POST',
data: body,
...(options || {}),
});
}
/** Creates list of users with given input array POST /user/createWithList */
export async function createUsersWithListInput(body: API.User[], options?: { [key: string]: any }) {
return request<any>('/user/createWithList', {
method: 'POST',
data: body,
...(options || {}),
});
}
/** Logs user into the system GET /user/login */
export async function loginUser(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.loginUserParams,
options?: { [key: string]: any },
) {
return request<string>('/user/login', {
method: 'GET',
params: {
...params,
},
...(options || {}),
});
}
/** Logs out current logged in user session GET /user/logout */
export async function logoutUser(options?: { [key: string]: any }) {
return request<any>('/user/logout', {
method: 'GET',
...(options || {}),
});
}

View File

View File

@@ -0,0 +1,119 @@
import { request } from "@umijs/max";
export interface PermissionAssignUserRoleReqVO {
userId: number;
roleIds: number[];
}
export interface PermissionAssignRoleMenuReqVO {
roleId: number;
menuIds: number[];
}
export interface PermissionAssignRoleDataScopeReqVO {
roleId: number;
dataScope: number;
dataScopeDeptIds: number[];
}
// export async function postProductProdRestoreProdList(
// // 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
// params: API.postProductProdRestoreProdListParams,
// options?: { [key: string]: any }
// ) {
// return request<API.CommonResultBoolean>("/product/prod/restoreProdList", {
// method: "POST",
// params: {
// ...params,
// },
// ...(options || {}),
// });
// }
// export async function getRoleMenuList(
// // 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
// params: API.getProductCategoryCategoryListParams,
// options?: { [key: string]: any }
// ) {
// return request<API.CommonResultListCategoryDto>(
// "/product/category/categoryList",
// {
// method: "GET",
// params: {
// ...params,
// },
// ...(options || {}),
// }
// );
// }
// 查询角色拥有的菜单权限
// export const getRoleMenuList = async (roleId: number) => {
// return await request.get({ url: '/system/permission/list-role-menus?roleId=' + roleId })
// }
export async function getRoleMenuList(roleId: number) {
return request("/system/permission/list-role-menus", {
method: "GET",
params: {
roleId,
},
});
}
// // 赋予角色菜单权限
// export const assignRoleMenu = async (data: PermissionAssignRoleMenuReqVO) => {
// return await request.post({ url: '/system/permission/assign-role-menu', data })
// }
export async function assignRoleMenu(
params: PermissionAssignRoleMenuReqVO,
options?: { [key: string]: any }
) {
return request("/system/permission/assign-role-menu", {
method: "POST",
params: {
...params,
},
...(options || {}),
});
}
// // 赋予角色数据权限
// export const assignRoleDataScope = async (data: PermissionAssignRoleDataScopeReqVO) => {
// return await request.post({ url: '/system/permission/assign-role-data-scope', data })
// }
export async function assignRoleDataScope(
params: PermissionAssignRoleDataScopeReqVO,
options?: { [key: string]: any }
) {
return request("/system/permission/assign-role-data-scope", {
method: "POST",
params: {
...params,
},
...(options || {}),
});
}
// // 查询用户拥有的角色数组
// export const getUserRoleList = async (userId: number) => {
// return await request.get({ url: '/system/permission/list-user-roles?userId=' + userId })
// }
export async function getUserRoleList(userId: number) {
return request("/system/permission/list-user-roles", {
method: "GET",
params: {
userId,
},
});
}
// // 赋予用户角色
// export const assignUserRole = async (data: PermissionAssignUserRoleReqVO) => {
// return await request.post({ url: '/system/permission/assign-user-role', data })
// }
export async function assignUserRole(
params: PermissionAssignUserRoleReqVO,
options?: { [key: string]: any }
) {
return request("/system/permission/assign-user-role", {
method: "POST",
params: {
...params,
},
...(options || {}),
});
}

0
src/services/system/typings.d.ts vendored Normal file
View File

78
src/types/global.d.ts vendored Normal file
View File

@@ -0,0 +1,78 @@
export {};
declare global {
interface Fn<T = any> {
(...arg: T[]): T;
}
type Nullable<T> = T | null;
type ElRef<T extends HTMLElement = HTMLDivElement> = Nullable<T>;
type Recordable<T = any, K = string> = Record<
K extends null | undefined ? string : K,
T
>;
type ComponentRef<T> = InstanceType<T>;
type LocaleType = "zh-CN" | "en";
declare type TimeoutHandle = ReturnType<typeof setTimeout>;
declare type IntervalHandle = ReturnType<typeof setInterval>;
type AxiosHeaders =
| "application/json"
| "application/x-www-form-urlencoded"
| "multipart/form-data";
type AxiosMethod =
| "get"
| "post"
| "delete"
| "put"
| "GET"
| "POST"
| "DELETE"
| "PUT";
type AxiosResponseType =
| "arraybuffer"
| "blob"
| "document"
| "json"
| "text"
| "stream";
interface AxiosConfig {
params?: any;
data?: any;
url?: string;
method?: AxiosMethod;
headersType?: string;
responseType?: AxiosResponseType;
}
interface IResponse<T> {
code: string;
data: T;
msg: string;
}
interface PageParam {
pageSize?: number;
pageNo?: number;
total?: number;
}
interface Tree {
id: number;
name: string;
children?: Tree[] | any[];
}
// 分页数据公共返回
interface PageResult<T> {
list: T; // 数据
total: number; // 总量
msg: string;
}
}

72
src/utils/auth.ts Normal file
View File

@@ -0,0 +1,72 @@
import { useCache, CACHE_KEY } from "@/hooks/web/useCache";
import type { TokenType } from "@/services/login/types";
import { decrypt, encrypt } from "@/utils/jsencrypt";
const { wsCache } = useCache();
const AccessTokenKey = "ACCESS_TOKEN";
const RefreshTokenKey = "REFRESH_TOKEN";
// 获取token
export const getAccessToken = () => {
// 此处与TokenKey相同此写法解决初始化时Cookies中不存在TokenKey报错
const accessToken = wsCache.get(AccessTokenKey);
return accessToken ? accessToken : wsCache.get("ACCESS_TOKEN");
};
// 刷新token
export const getRefreshToken = () => {
return wsCache.get(RefreshTokenKey);
};
// 设置token
export const setToken = (token: TokenType) => {
wsCache.set(RefreshTokenKey, token.refreshToken);
wsCache.set(AccessTokenKey, token.accessToken);
};
// 删除token
export const removeToken = () => {
wsCache.delete(AccessTokenKey);
wsCache.delete(RefreshTokenKey);
};
/** 格式化tokenjwt格式 */
export const formatToken = (token: string): string => {
return "Bearer " + token;
};
// ========== 账号相关 ==========
export type LoginFormType = {
tenantName: string;
username: string;
password: string;
rememberMe: boolean;
};
export const getLoginForm = () => {
const loginForm: LoginFormType = wsCache.get(CACHE_KEY.LoginForm);
if (loginForm) {
loginForm.password = decrypt(loginForm.password) as string;
}
return loginForm;
};
export const setLoginForm = (loginForm: LoginFormType) => {
loginForm.password = encrypt(loginForm.password) as string;
wsCache.set(CACHE_KEY.LoginForm, loginForm, { exp: 30 * 24 * 60 * 60 });
};
export const removeLoginForm = () => {
wsCache.delete(CACHE_KEY.LoginForm);
};
// ========== 租户相关 ==========
export const getTenantId = () => {
return wsCache.get(CACHE_KEY.TenantId);
};
export const setTenantId = (username: string) => {
wsCache.set(CACHE_KEY.TenantId, username);
};

31
src/utils/jsencrypt.ts Normal file
View File

@@ -0,0 +1,31 @@
import { JSEncrypt } from 'jsencrypt'
// 密钥对生成 http://web.chacuo.net/netrsakeypair
const publicKey =
'MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKoR8mX0rGKLqzcWmOzbfj64K8ZIgOdH\n' +
'nzkXSOVOZbFu/TJhZ7rFAN+eaGkl3C4buccQd/EjEsj9ir7ijT7h96MCAwEAAQ=='
const privateKey =
'MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAqhHyZfSsYourNxaY\n' +
'7Nt+PrgrxkiA50efORdI5U5lsW79MmFnusUA355oaSXcLhu5xxB38SMSyP2KvuKN\n' +
'PuH3owIDAQABAkAfoiLyL+Z4lf4Myxk6xUDgLaWGximj20CUf+5BKKnlrK+Ed8gA\n' +
'kM0HqoTt2UZwA5E2MzS4EI2gjfQhz5X28uqxAiEA3wNFxfrCZlSZHb0gn2zDpWow\n' +
'cSxQAgiCstxGUoOqlW8CIQDDOerGKH5OmCJ4Z21v+F25WaHYPxCFMvwxpcw99Ecv\n' +
'DQIgIdhDTIqD2jfYjPTY8Jj3EDGPbH2HHuffvflECt3Ek60CIQCFRlCkHpi7hthh\n' +
'YhovyloRYsM+IS9h/0BzlEAuO0ktMQIgSPT3aFAgJYwKpqRYKlLDVcflZFCKY7u3\n' +
'UP8iWi1Qw0Y='
// 加密
export const encrypt = (txt: string) => {
const encryptor = new JSEncrypt()
encryptor.setPublicKey(publicKey) // 设置公钥
return encryptor.encrypt(txt) // 对数据进行加密
}
// 解密
export const decrypt = (txt: string) => {
const encryptor = new JSEncrypt()
encryptor.setPrivateKey(privateKey) // 设置私钥
return encryptor.decrypt(txt) // 对数据进行解密
}

View File

@@ -19,5 +19,5 @@
}
},
"include": ["./**/*.d.ts", "./**/*.ts", "./**/*.tsx"],
"exclude": ["config"]
"exclude": ["config", "src/services/*/*.ts"]
}