理顺框架

This commit is contained in:
LittleBoy 2023-08-21 23:45:47 +08:00
parent 62a323bdf9
commit 07347cba09
15 changed files with 174 additions and 37 deletions

View File

@ -1,3 +1,56 @@
/* http://meyerweb.com/eric/tools/css/reset/
v5.0.1 | 20191019
License: none (public domain)
*/
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed,
figure, figcaption, footer, header, hgroup,
main, menu, nav, output, ruby, section, summary,
time, mark, audio, video {
margin: 0;
padding: 0;
border: 0;
font-size: 100%;
font: inherit;
vertical-align: baseline;
}
/* HTML5 display-role reset for older browsers */
article, aside, details, figcaption, figure,
footer, header, hgroup, main, menu, nav, section {
display: block;
}
/* HTML5 hidden-attribute fix for newer browsers */
*[hidden] {
display: none;
}
body {
line-height: 1;
}
menu, ol, ul {
list-style: none;
}
blockquote, q {
quotes: none;
}
blockquote:before, blockquote:after,
q:before, q:after {
content: '';
content: none;
}
table {
border-collapse: collapse;
border-spacing: 0;
}
:root {
--max-width: 1100px;
--border-radius: 12px;
@ -73,12 +126,6 @@
}
}
* {
box-sizing: border-box;
padding: 0;
margin: 0;
}
html,
body {
max-width: 100vw;

View File

@ -85,7 +85,10 @@ export const LoginComponent = () => {
{/* </div>*/}
{/*</div>*/}
</Modal>
{visible?'xxx':'0000'}
<Button type="primary" onClick={() => setVisible(true)}></Button>
{visible ? 'xxx' : '0000'}
<Button type="primary" onClick={() => {
setVisible(true)
// Modal.success({ title: 'This is a success message', content: 'bla bla bla...' });
}}></Button>
</div>)
}

View File

@ -25,7 +25,6 @@ export const AppRouter = () => (<WebRouter>
<div className="page-body-content">
<Routes>
<Route path="/" element={<DefaultPage/>}/>
<Route path="*" element={<NotFound/>}/>
</Routes>
</div>

View File

@ -1,9 +1,18 @@
.index{
.index {
display: flex;
align-items: center;
justify-content: center;
height: 100vh;
}
.modal{
.title{
font-size: 20px;
font-weight: 700;
color: #333;
margin-bottom: 20px;
}
.loginWrapper {
background-color: #fff;
padding: 15px 20px;
border-radius: 6px;
width: 350px;
}

View File

@ -1,10 +1,77 @@
import React from "react";
import React, {useRef, useState} from "react";
import {IconGithubLogo, IconWeibo} from "@douyinfe/semi-icons";
import css from './index.module.scss'
import {LoginComponent} from "../../components/LoginComponent.tsx";
import {useNavigate} from "react-router-dom";
import {useUserinfoStore} from "../../store/userinfoStore.ts";
import {Button, Divider, Form, Modal, Notification, Space} from "@douyinfe/semi-ui";
import {cx} from "@emotion/css";
const DefaultPage: React.FC = () => {
const [loading, setLoading] = useState(false);
const navigate = useNavigate();
const {login} = useUserinfoStore()
const onFinish = async (values: any) => {
setLoading(true);
try {
const user = await login(values)
setVisible(true);
navigate('/dashboard')
} catch (err) {
// 登录失败
console.log(err)
// 登录失败
Notification.error({
content: '登录失败,请检查用户名和密码'
})
}
setLoading(false);
};
const [visible, setVisible] = useState(false);
const hideModal = () => setVisible(false)
return (<div className={css.index}>
<LoginComponent/>
{/*<LoginComponent/>*/}
<div className={css.loginWrapper}>
<h2 className={cx('text-center', css.title)}></h2>
<Form
onSubmit={onFinish}
>
<Form.Input
field="account"
placeholder="请输入用户名"
noLabel
rules={[{required: true, message: '用户名不可空'}]}
/>
<Form.Input
type="password"
field="password"
placeholder="请输入登录密码"
noLabel
rules={[{required: true, message: '密码不可空'}]}
/>
<Form.Checkbox
field="remember"
value={false}
noLabel
></Form.Checkbox>
<div className='flex align-center space-between'>
<Button block type='primary' theme='solid' loading={loading} htmlType="submit"></Button>
</div>
</Form>
<div style={{padding: '30px 0 20px'}}>
<Divider>OR</Divider>
<div className="text-center" style={{marginTop: 20}}>
<Space>
<Button icon={<IconWeibo/>}>GOOGLE</Button>
<Button theme='solid' type="primary" icon={<IconGithubLogo/>}>GITHUB</Button>
</Space>
</div>
</div>
</div>
</div>);
}
export default DefaultPage;

View File

@ -35,7 +35,7 @@ Axios.interceptors.request.use(config => {
const token = Storage.get<string>(APP_CONFIG.LOGIN_TOKEN_KEY)
// const {token} = useUserinfoStore()
if (token) {
config.headers['Authorization'] = `Bearer ${token}`;
config.headers['Authorization'] = `${token}`; // Bearer
}
if (config.data && config.data instanceof FormData) {
config.headers['Content-Type'] = 'multipart/form-data';
@ -81,7 +81,7 @@ export function request<T>(url: string, method: RequestMethod, data: any = null,
if (code == 403) {
const state = useUserinfoStore.getState()
// 未登录 显示登录modal
state.showLogin(true);
// state.showLogin(true);
}
reject(new BizError(msg, code))
}

View File

@ -2,8 +2,8 @@ import {get, post} from "./request.ts";
import {UserModel} from "../../model";
export function login(user: string, password: string) {
return post<UserModel>('/api/user/info', {user, password})
export function login(username: string, password: string) {
return post<UserModel>('/api/user/login', {username, password})
}
export function getInfo() {

View File

@ -74,8 +74,7 @@ export const useUserinfoStore = create<{
},
login: (data) => {
return new Promise<void>((resolve, reject) => {
const promise = login(data.account, data.password);
promise.then((ret) => {
login(data.account, data.password).then((ret) => {
const token = ret.token;
Storage.put(LOGIN_TOKEN_KEY, token)
getInfo().then(userinfo => {

View File

@ -1,6 +1,7 @@
import { InitServerOption } from "./types";
// import { createServer as createServerOrigin } from "http";
import express = require("express");
// import express = require("express");
import * as express from "express";
export function createServer(options: Partial<InitServerOption>, callback?: () => void) {
// 创建express服务器

View File

@ -2,7 +2,7 @@ import {Application, Request, Response} from "express";
import {RouteHandleFunction, RouteHandleFunctionParam} from "../core/types";
import {home} from "./home";
import {appList, reportToServer, appEvent, eventData} from "./reportor";
import {loginHandler} from "./user.ts";
import {getUserInfo, loginHandler} from "./user.ts";
//
function createRoute(handler: RouteHandleFunction) {
@ -28,5 +28,6 @@ export function initRoutes(app: Application) {
app.all('/api/app/list', createRoute(appList))
app.all('/api/app/event', createRoute(appEvent))
app.all('/api/app/event-data', createRoute(eventData))
app.all('/api/login', createRoute(loginHandler))
app.all('/api/user/login', createRoute(loginHandler))
app.all('/api/user/info', createRoute(getUserInfo))
}

View File

@ -1,5 +1,5 @@
import { createPool } from 'mysql'
import { DB_CONFIG } from './../config';
import {createPool} from 'mysql'
import {DB_CONFIG} from './../config';
export const pool = createPool({
...DB_CONFIG,
@ -30,19 +30,23 @@ export async function selectArray<T>(sql: string, params: any = null) {
// })
// });
}
// 查询单个对象
export async function selectOne<T>(sql: string, params: any = null) {
// 执行查询sql并返回查询结果
const arr = await selectArray<T>(sql, params);
if (arr.length != 1) throw new Error("查询结果数量不等于1");
return arr[0];
// if (arr.length != 1) throw new Error("查询结果数量不等于1");
return arr.length > 0 ? arr[0] : null;
}
// 统计数据
export async function queryCount(sql: string, params: any = null) {
const obj = await selectOne<{ [key: string]: number }>(sql, params);
if(!obj) return 0;
const keys = Object.keys(obj);
return obj[keys[0]];
}
// 根据表名和条件判断数据是否存在
export async function isExistByTable(tableName: string, condition: any = {}) {
let sql = `select count(*) as count from ${tableName} where 1=1`;
@ -54,10 +58,12 @@ export async function isExistByTable(tableName: string, condition: any = {}) {
const count = await queryCount(sql, params);
return count > 0;
}
export async function isExist(sql: string, params: any) {
const count = await queryCount(sql, params);
return count > 0;
}
// 查询多条数据
function executeSQL<T>(sql: string, params: any) {
@ -76,10 +82,12 @@ export async function execute(sql: string, params: any = null) {
const ret = await executeSQL<{ affectedRows: number }>(sql, params)
return ret.affectedRows
}
export async function insertAndGetInsertId(tableName: string, data: any = null) {
const ret = await executeSQL<{ insertId: number }>(`insert into \`${tableName}\` set ?`, data)
return ret.insertId
}
export default {
selectArray,
executeSQL,

View File

@ -1,4 +1,4 @@
import { execute, selectArray, pool, queryCount } from './../src/service/mysql'
import { execute, selectArray, pool, queryCount } from './../service/service/mysql'
// 使用execute执行更新数据
describe('Database', () => {

View File

@ -1,5 +1,6 @@
import { Test } from 'supertest';
import { PORT } from './../config'
import {Test} from 'supertest';
import {PORT} from './../service/config'
const request = require("supertest");
// import { createServer } from './../src/core/server'

View File

@ -1,8 +1,9 @@
{
"compilerOptions": {
/* ESNext */
"target": "ESNext",
"lib": ["DOM", "DOM.Iterable", "ESNext"],
"module": "CommonJS",
"module": "commonjs",
"skipLibCheck": true,
/* Bundler mode */

View File

@ -12,11 +12,12 @@ export default defineConfig(({mode}) => {
'@/': '/front/'
}
},
define: {
buildVersion: JSON.stringify((new Date()).toLocaleString()),
mode:JSON.stringify(mode),
},
// define: {
// buildVersion: JSON.stringify((new Date()).toLocaleString()),
// mode:JSON.stringify(mode),
// },
build: {
outDir:'static',
// 小于10kb直接base64
assetsInlineLimit: 10240,
rollupOptions: {