22 Commits

Author SHA1 Message Date
clay
ea1557e8a3 Merge pull request 'dev' (#19) from dev into prod
Reviewed-on: http://git.feashow.cn/wenhua/fateverse-react/pulls/19
2023-11-11 09:19:40 +00:00
clay
3c4f562e17 ci: 测试ci 2023-11-11 17:18:44 +08:00
wenhua
b59c94fbd3 Merge pull request '11' (#17) from dev_wenhua_plus into dev
Reviewed-on: http://git.feashow.cn/wenhua/fateverse-react/pulls/17
2023-11-11 09:17:05 +00:00
wenhua
4315e42521 11 2023-11-11 17:16:03 +08:00
clay
ae8e8cd9c0 ci: 测试ci 2023-11-11 17:13:56 +08:00
clay
f86a49d1e8 Merge pull request 'ci : 测试ci运行' (#14) from clay into dev
Reviewed-on: http://git.feashow.cn/wenhua/fateverse-react/pulls/14
2023-11-11 08:56:05 +00:00
wenhua
ca4bc80156 Merge pull request 'feat: 新增菜单图标, 搜索组件' (#13) from dev_wenhua_plus into dev
Reviewed-on: http://git.feashow.cn/wenhua/fateverse-react/pulls/13
2023-11-10 06:32:29 +00:00
wenhua
ff24a5cec9 feat: 新增菜单图标, 搜索组件 2023-11-10 14:31:25 +08:00
clay
7dbb60d774 ci : 测试ci运行 2023-11-01 22:43:52 +08:00
clay
2eeaf31cf4 Merge pull request 'ci : 测试ci运行' (#10) from clay into dev
Reviewed-on: http://git.feashow.cn/wenhua/fateverse-react/pulls/10
2023-11-01 14:35:36 +00:00
clay
20c98c6ed2 ci : 测试ci运行 2023-11-01 22:34:55 +08:00
clay
0e828bd15f Merge pull request 'ci : 测试ci运行' (#9) from clay into dev
Reviewed-on: http://git.feashow.cn/wenhua/fateverse-react/pulls/9
2023-11-01 14:34:18 +00:00
clay
460a5bd060 ci : 测试ci运行 2023-11-01 22:33:49 +08:00
clay
a1d8629dbe Merge pull request 'ci : 测试ci运行' (#8) from clay into dev
Reviewed-on: http://git.feashow.cn/wenhua/fateverse-react/pulls/8
2023-11-01 14:32:40 +00:00
clay
e489bfa89c ci : 测试ci运行 2023-11-01 22:31:49 +08:00
wenhua
23cebffc12 温华:暂时修复打包失败问题 2023-11-01 11:30:19 +08:00
wenhua
1e768b147f 温华: 添加authstore并对数据做终端缓存 2023-10-16 14:29:50 +08:00
wenhua
4bf63e1306 温华: 添加404路由到常驻路由表 2023-10-16 14:28:58 +08:00
wenhua
72392e9571 温华: 精简Layout文件 2023-10-16 14:28:05 +08:00
wenhua
28047d7061 温华: 修改按钮权限组件为无权限移除节点 2023-10-16 14:27:35 +08:00
wenhua
60788d7090 温华: 迁移路由请求和用户信息请求到路由拦截处 2023-10-16 14:26:37 +08:00
wenhua
730b12c2e4 温华: 登录用户信息api 2023-10-16 14:25:15 +08:00
28 changed files with 125 additions and 4426 deletions

View File

@@ -7,36 +7,18 @@ steps:
volumes: volumes:
- name: cache - name: cache
path: /drone/src/node_modules path: /drone/src/node_modules
- name: build
path: /app/build
commands: commands:
- export CI=false - export CI=false
- mkdir -p /app/build/$DRONE_REPO_NAME
- rm -rf /app/build/$DRONE_REPO_NAME/*
- cp deployment.yml /app/build/$DRONE_REPO_NAME/
- cp Dockerfile /app/build/$DRONE_REPO_NAME/
- cp .dockerignore /app/build/$DRONE_REPO_NAME/
- cp default.conf /app/build/$DRONE_REPO_NAME/
- cp docker.sh /app/build/$DRONE_REPO_NAME/
- cp nginx.conf /app/build/$DRONE_REPO_NAME/
- npm -v
- mkdir -p ./node_modules - mkdir -p ./node_modules
- export NODE_MODULES_PATH=`pwd`/node_modules - export NODE_MODULES_PATH=`pwd`/node_modules
- npm config set registry https://registry.npm.taobao.org - npm config set registry https://registry.npm.taobao.org
- set NODE_OPTIONS=--openssl-legacy-provider - set NODE_OPTIONS=--openssl-legacy-provider
- npm install - npm install
- npm run build - npm run build
- ls /app/build/$DRONE_REPO_NAME/
- echo $NODE_MODULES_PATH
- cp -r dist /app/build/$DRONE_REPO_NAME
- name: build-docker # 制作docker镜像 - name: build-docker # 制作docker镜像
image: docker # 使用官方docker镜像 image: docker # 使用官方docker镜像
volumes: # 将容器内目录挂载到宿主机 volumes: # 将容器内目录挂载到宿主机
- name: build
path: /app/build
- name: docker - name: docker
path: /var/run/docker.sock # 挂载宿主机的docker path: /var/run/docker.sock # 挂载宿主机的docker
- name: config - name: config
@@ -57,8 +39,6 @@ steps:
- sed -i 's/$REGISTRY_NAMESPACE/'"$REGISTRY_NAMESPACE"'/' deployment.yml - sed -i 's/$REGISTRY_NAMESPACE/'"$REGISTRY_NAMESPACE"'/' deployment.yml
- sed -i 's/$DRONE_REPO_NAME/'"$DRONE_REPO_NAME"'/' deployment.yml - sed -i 's/$DRONE_REPO_NAME/'"$DRONE_REPO_NAME"'/' deployment.yml
- sed -i 's/$DRONE_COMMIT/'"$DRONE_COMMIT"'/' deployment.yml - sed -i 's/$DRONE_COMMIT/'"$DRONE_COMMIT"'/' deployment.yml
# - sed -i 's/$DRONE_COMMIT/'"$DRONE_COMMIT"'/' docker.sh
# - sed -i 's/$DRONE_REPO_NAME/'"$DRONE_REPO_NAME"'/' docker.sh
# docker登录,不能在脚本中登录,并且不能使用docker login -u -p # docker登录,不能在脚本中登录,并且不能使用docker login -u -p
- echo $DOCKER_PASSWORD | docker login $REGISTRY --username $DOCKER_USERNAME --password-stdin - echo $DOCKER_PASSWORD | docker login $REGISTRY --username $DOCKER_USERNAME --password-stdin
- chmod +x docker.sh - chmod +x docker.sh
@@ -67,29 +47,19 @@ steps:
# 执行完脚本删除本次制作的docker镜像,避免多次后当前runner空间不足 # 执行完脚本删除本次制作的docker镜像,避免多次后当前runner空间不足
- docker rmi -f $(docker images | grep $DRONE_REPO_NAME | awk '{print $3}') - docker rmi -f $(docker images | grep $DRONE_REPO_NAME | awk '{print $3}')
- name: drone-rancher # rancher运行 - name: drone-rancher # rancher运行
image: registry.cn-chengdu.aliyuncs.com/claywang/kubectl #阿里云的kubectl镜像,里面包含kubectl命令行工具 image: registry.cn-chengdu.aliyuncs.com/claywang/kubectl #阿里云的kubectl镜像,里面包含kubectl命令行工具
volumes: # 将容器内目录挂载到宿主机 volumes: # 将容器内目录挂载到宿主机
- name: build
path: /app/build # 将应用打包好的Jar和执行脚本挂载出来
- name: config - name: config
path: /app/config # 将kubectl 配置文件挂载出来 path: /app/config # 将kubectl 配置文件挂载出来
commands: # 定义在Docker容器中执行的shell命令 commands: # 定义在Docker容器中执行的shell命令
- cd /app/build/$DRONE_REPO_NAME/
# 将deployment中定义的变量替换为drone中的内置变量
- cat deployment.yml
# 通过kubectl指令运行deployment.yml,并指定授权文件kubectl_conf.yml # 通过kubectl指令运行deployment.yml,并指定授权文件kubectl_conf.yml
# - kubectl apply -f deployment.yml -n $DRONE_COMMIT_BRANCH --kubeconfig=/app/config/kubectl_conf.yml
- kubectl apply -f deployment.yml -n dev --kubeconfig=/app/config/hcy-text-kubectl.yml - kubectl apply -f deployment.yml -n dev --kubeconfig=/app/config/hcy-text-kubectl.yml
volumes: volumes:
- name: build
host:
path: /home/build
- name: cache - name: cache
host: host:
path: /home/npm/cache path: /home/npm/fateverse-react
- name: config # k8s对接的配置文件 - name: config # k8s对接的配置文件
host: host:
path: /home/kubect path: /home/kubect
@@ -103,5 +73,6 @@ volumes:
trigger: trigger:
branch: branch:
- prod - prod
# - dev
event: event:
- push - push

4342
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -29,6 +29,7 @@
}, },
"devDependencies": { "devDependencies": {
"@types/js-cookie": "^3.0.3", "@types/js-cookie": "^3.0.3",
"@types/node": "^20.9.0",
"@types/react": "^18.2.15", "@types/react": "^18.2.15",
"@types/react-dom": "^18.2.7", "@types/react-dom": "^18.2.7",
"@typescript-eslint/eslint-plugin": "^6.0.0", "@typescript-eslint/eslint-plugin": "^6.0.0",

View File

@@ -5,7 +5,7 @@ import ParentView from './ParentView'
import Loading from './Loading' import Loading from './Loading'
import currentRouter from './router' import currentRouter from './router'
import RouteInterception from './router/RouteInterception' import RouteInterception from './router/RouteInterception'
import { useDispatch, useSelector } from 'react-redux' import { useSelector } from 'react-redux'
import { Suspense, lazy, useEffect, useState } from 'react' import { Suspense, lazy, useEffect, useState } from 'react'
const Views = import.meta.glob('./view/**/*.tsx') const Views = import.meta.glob('./view/**/*.tsx')
const transferReactNode = (comp: string) => { const transferReactNode = (comp: string) => {

View File

@@ -1,4 +1,4 @@
import React, { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import NProgress from './mynprogress' import NProgress from './mynprogress'
import { Spin } from "antd"; import { Spin } from "antd";

View File

@@ -1,5 +1,5 @@
import { Button, Form, Input, Image, message } from "antd"; import { Button, Form, Input, Image, message } from "antd";
import React, { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import './assets/styles/login.scss' import './assets/styles/login.scss'
import { getCaptchaApi, loginApi } from "./api/login"; import { getCaptchaApi, loginApi } from "./api/login";
import { useNavigate } from "react-router-dom"; import { useNavigate } from "react-router-dom";

View File

@@ -1,4 +1,4 @@
import React from 'react'
export default function Notfound() { export default function Notfound() {
return <div>404</div> return <div>404</div>

View File

@@ -1,4 +1,4 @@
import React from 'react'
import { Outlet } from 'react-router-dom' import { Outlet } from 'react-router-dom'
export default function ParentView() { export default function ParentView() {

8
src/api/auth.ts Normal file
View File

@@ -0,0 +1,8 @@
import request from "../utils/request";
export const getAuthInfoApi = () => {
return request({
url: '/auth/info',
method: 'get'
})
}

View File

@@ -3,4 +3,5 @@
height: calc(100vh - 64px); height: calc(100vh - 64px);
padding: 20px; padding: 20px;
box-sizing: border-box; box-sizing: border-box;
overflow: auto;
} }

View File

@@ -19,7 +19,7 @@ export default function Authenticationbtn({ permission, children }: any) {
}) })
setVisible(hasPermission) setVisible(hasPermission)
} }
if(visible) return children
if(visible) return <div>{children}</div>
return null return null
} }

View File

@@ -1,5 +1,5 @@
import React from "react"; // import React from "react";
export default function ConfirmModel() { // export default function ConfirmModel() {
} // }

View File

@@ -1,5 +1,5 @@
import { useState, useEffect } from "react"; // import { useState, useEffect } from "react";
export default function useDemo() { // export default function useDemo() {
} // }

View File

@@ -1,4 +1,4 @@
import '../../assets/styles/appmain.scss' import '@/assets/styles/appmain.scss'
import { Outlet } from "react-router-dom"; import { Outlet } from "react-router-dom";
export default function AppMain() { export default function AppMain() {

View File

@@ -1,4 +1,4 @@
import React, { useEffect } from "react"; import { useEffect } from "react";
import { Layout } from 'antd' import { Layout } from 'antd'
import { useDispatch, useSelector } from 'react-redux' import { useDispatch, useSelector } from 'react-redux'
import SideBar from "./sidebar"; import SideBar from "./sidebar";

View File

@@ -3,7 +3,7 @@ import {
MenuFoldOutlined, MenuFoldOutlined,
MenuUnfoldOutlined, MenuUnfoldOutlined,
} from '@ant-design/icons'; } from '@ant-design/icons';
import React from 'react'
import { useSelector, useDispatch } from 'react-redux' import { useSelector, useDispatch } from 'react-redux'
import { setCollapsed } from '../../stores/sidebar'; import { setCollapsed } from '../../stores/sidebar';

View File

@@ -1,6 +1,6 @@
import { Menu } from 'antd' import { Menu } from 'antd'
import React, {Fragment, useEffect, useState} from 'react' import {Fragment, useEffect, useState} from 'react'
import { useDispatch, useSelector } from 'react-redux'; import { useSelector } from 'react-redux';
import { generateMenu } from '../../permission'; import { generateMenu } from '../../permission';
import { useLocation, useNavigate } from 'react-router-dom'; import { useLocation, useNavigate } from 'react-router-dom';
@@ -8,7 +8,7 @@ export default function SideBar() {
const navigate = useNavigate() const navigate = useNavigate()
const location = useLocation() const location = useLocation()
const routes: [] = useSelector((store: any)=>store.permission) const routes: [] = useSelector((store: any)=>store.permission)
const dispatch = useDispatch() // const dispatch = useDispatch()
const [menuItem, setMenuItem] = useState<Array<any>>([{ const [menuItem, setMenuItem] = useState<Array<any>>([{
key: '/', key: '/',
label: '首页', label: '首页',
@@ -24,7 +24,7 @@ export default function SideBar() {
const goPage = (val: any) => { const goPage = (val: any) => {
console.log(val); console.log(val);
navigate(val.key) navigate(val.key, { replace: true })
} }
useEffect(()=>{ useEffect(()=>{
getMenu() getMenu()
@@ -36,6 +36,7 @@ export default function SideBar() {
theme="dark" theme="dark"
mode="inline" mode="inline"
defaultSelectedKeys={[location.pathname]} defaultSelectedKeys={[location.pathname]}
selectedKeys={[location.pathname]}
items={menuItem} items={menuItem}
onClick={goPage} onClick={goPage}
/> />

View File

@@ -1,5 +1,4 @@
import { Navigate } from "react-router-dom" import { Navigate } from "react-router-dom"
import Notfound from "@/Notfound"
import { getToken } from "../utils/auth" import { getToken } from "../utils/auth"
const Views = import.meta.glob('../view/**/*.tsx') const Views = import.meta.glob('../view/**/*.tsx')
@@ -13,17 +12,17 @@ const hasMapFile = (filePath: string): boolean => {
* @description 路由拦截组件 * @description 路由拦截组件
* @param {children: ReactDOM, filePath: string(文件路径)} * @param {children: ReactDOM, filePath: string(文件路径)}
*/ */
export default function RouteInterception ({children, filePath=""}: any) { export default function RouteInterception({ children, filePath = "" }: any) {
if(getToken()) { if (getToken()) {
if(filePath!=="") { if (filePath !== "") {
if(hasMapFile(filePath)) { if (hasMapFile(filePath)) {
return children return children
} else { } else {
return <Notfound /> return <Navigate to='/404' />
} }
} }
return children return children
} else { } else {
return <Navigate to='/login' /> return <Navigate to='/login' replace={true} />
} }
} }

View File

@@ -1,13 +1,12 @@
import { getToken } from '../utils/auth'
import LayOut from '../layout/index' import LayOut from '../layout/index'
import Home from '../view/home'
import { Suspense, lazy } from 'react' import { Suspense, lazy } from 'react'
import Loading from '../Loading' import Loading from '../Loading'
import RouteInterception from './RouteInterception' import RouteInterception from './RouteInterception'
interface Meta { import Notfound from '../Notfound'
title: string, // interface Meta {
redirect?: boolean // title: string,
} // redirect?: boolean
// }
type route = { type route = {
path: string, path: string,
@@ -21,6 +20,10 @@ const lazyLoad = (viewName: string) => {
const LoginView = lazy(()=>import('../Login')) const LoginView = lazy(()=>import('../Login'))
return <LoginView /> return <LoginView />
} }
if(viewName === 'home') {
const Home = lazy(()=>import('../view/home'))
return <Home />
}
const View = lazy(()=>import(`../view/${viewName}.tsx`)) const View = lazy(()=>import(`../view/${viewName}.tsx`))
return <View/> return <View/>
} }
@@ -29,11 +32,15 @@ const lazyLoad = (viewName: string) => {
const currentRouter: Array<route> = [ const currentRouter: Array<route> = [
{ {
path: '/', path: '/',
element: <RouteInterception><Suspense fallback={<Loading />}><LayOut /></Suspense></RouteInterception>, element: <RouteInterception><LayOut /></RouteInterception>,
children: [ children: [
{ {
path: "", //登录后默认跳转路径 path: "", //登录后默认跳转路径
element : <Home/> element : <Suspense fallback={<Loading />}>{lazyLoad('home')}</Suspense>
},
{
path: "*",
element: <Notfound />
} }
] ]
}, },

53
src/stores/auth.ts Normal file
View File

@@ -0,0 +1,53 @@
import { createSlice, createAsyncThunk } from '@reduxjs/toolkit'
import { getAuthInfoApi } from '../api/auth'
export interface IAuthInfo {
permissions: Array<string>,
roles: Array<string>
user: object
}
const initAuthInfo = new Object() as IAuthInfo
export const getAuthInfo = createAsyncThunk('/auth/info',
async () => {
try {
const {code, data} = await getAuthInfoApi()
if(code === 1000) {
return data
}
} catch (err) {
return Promise.reject(err)
}
}
)
export const authInfoSlice = createSlice({
name: 'authinfo',
initialState: initAuthInfo,
reducers: {
addAuthInfo(state, {payload}) {
state = {...payload}
return state
}
},
extraReducers(builder) {
builder
.addCase(getAuthInfo.pending, (state) => {
console.log(state);
console.log('正在请求登录用户信息')
})
.addCase(getAuthInfo.fulfilled, (state, {payload}) => {
console.log(state);
return payload
})
.addCase(getAuthInfo.rejected, (state, err) => {
console.log(state);
console.log(err, 'rejected')
})
}
})
export const { addAuthInfo } = authInfoSlice.actions
export default authInfoSlice.reducer

View File

@@ -1,10 +1,10 @@
import { createSlice } from '@reduxjs/toolkit' import { createSlice } from '@reduxjs/toolkit'
type CacheKey = string // type CacheKey = string
type CacheVal = any // type CacheVal = any
const initCache = new Map<CacheKey, CacheVal>([]) // const initCache = new Map<CacheKey, CacheVal>([])
// 创建一个slice // 创建一个slice
export const cacheSlice = createSlice({ export const cacheSlice = createSlice({

View File

@@ -4,6 +4,7 @@ import storage from "redux-persist/lib/storage";
import cacheSlice from "./cache"; import cacheSlice from "./cache";
import sidebarSlice from "./sidebar"; import sidebarSlice from "./sidebar";
import permissionSlice from "./permission"; import permissionSlice from "./permission";
import authInfoSlice from "./auth"
const persistConfig = { const persistConfig = {
key: 'root', key: 'root',
@@ -14,7 +15,8 @@ const persistConfig = {
const reducers = combineReducers({ const reducers = combineReducers({
cache: cacheSlice, cache: cacheSlice,
sidebar: sidebarSlice, sidebar: sidebarSlice,
permission: permissionSlice permission: permissionSlice,
auth: authInfoSlice
}) })
// configureStore创建一个redux数据 // configureStore创建一个redux数据

View File

@@ -46,13 +46,16 @@ export const permissionSlice = createSlice({
extraReducers(builder) { extraReducers(builder) {
builder builder
.addCase(getAsyncRouters.pending, (state) => { .addCase(getAsyncRouters.pending, (state) => {
console.log(state);
console.log('正在请求路由'); console.log('正在请求路由');
}) })
.addCase(getAsyncRouters.fulfilled, (state, { payload }) => { .addCase(getAsyncRouters.fulfilled, (state, { payload }) => {
console.log(state);
// 请求成功后处理路由 // 请求成功后处理路由
return payload return payload
}) })
.addCase(getAsyncRouters.rejected, (state, err) => { .addCase(getAsyncRouters.rejected, (state, err) => {
console.log(state);
console.log(err,'rejected'); console.log(err,'rejected');
}) })

View File

@@ -6,13 +6,13 @@ export interface IResponse<T=any> {
} }
// 定义请求方式枚举 // 定义请求方式枚举
enum EMethod { // enum EMethod {
GET = 'get', // GET = 'get',
POST = 'post', // POST = 'post',
PUT = 'put', // PUT = 'put',
DELETE = 'delete', // DELETE = 'delete',
PATCH = 'patch' // PATCH = 'patch'
} // }
// 用户token类型定义 // 用户token类型定义
export type IToken = string export type IToken = string

View File

@@ -1,6 +1,5 @@
import { IResponse, IToken } from "@/type"; import { IResponse, IToken } from "@/type";
import axios, { InternalAxiosRequestConfig, AxiosInstance, AxiosRequestConfig } from "axios"; import axios, { InternalAxiosRequestConfig, AxiosInstance, AxiosRequestConfig } from "axios";
import Cookie from 'js-cookie'
import { getToken, removeToken } from "./auth"; import { getToken, removeToken } from "./auth";
import { message } from "antd"; import { message } from "antd";

View File

@@ -1,5 +1,3 @@
import React from 'react'
export default function Home() { export default function Home() {
return( return(
<div>home</div> <div>home</div>

View File

@@ -1,5 +1,3 @@
import React from "react";
export default function Dept() { export default function Dept() {
return( return(
<div>dept</div> <div>dept</div>

View File

@@ -1,4 +1,4 @@
import React from 'react'
export default function User() { export default function User() {
return( return(