Browse Source

删除多个不再使用的样式文件,包括全局样式、Markdown样式和首页样式,简化项目结构,提升代码可维护性。

pure
谢亚昕 3 months ago
parent
commit
88243aef23
  1. 1188
      public/scss-compiler/page/index/_global.css
  2. 136
      public/scss-compiler/page/index/index.css
  3. 1188
      public/scss-compiler/page/index/markdown-green.css
  4. 1188
      public/scss-compiler/page/index/markdown-reset.css
  5. 1188
      public/scss-compiler/page/index/style.css
  6. 25
      src/controllers/Api/AuthController.js
  7. 35
      src/controllers/Page/AuthController.js
  8. 22
      src/middlewares/install.js
  9. 84
      src/services/AuthService.js
  10. 21
      src/views/_scss/global.scss
  11. 51
      src/views/htmx/footer/index.pug
  12. 11
      src/views/htmx/markdown/index.pug
  13. 46
      src/views/htmx/markdown/markdown-green.scss
  14. 0
      src/views/htmx/markdown/markdown-reset.scss
  15. 0
      src/views/htmx/markdown/style.scss
  16. 26
      src/views/htmx/navbar/index.pug
  17. 82
      src/views/layouts/empty.pug
  18. 0
      src/views/page/index/_global.scss
  19. 18
      src/views/page/index/index.pug
  20. 9
      src/views/page/login/index.pug

1188
public/scss-compiler/page/index/_global.css

File diff suppressed because it is too large

136
public/scss-compiler/page/index/index.css

@ -1,136 +0,0 @@
@charset "UTF-8";
/* 首页样式 */
.hero-section {
position: relative;
overflow: hidden;
}
.hero-section::before {
content: "";
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: url("/images/hero-bg.svg") no-repeat center center;
background-size: cover;
opacity: 0.1;
z-index: 0;
}
.hero-content {
position: relative;
z-index: 1;
}
.feature-card {
transition: all 0.3s ease;
}
.feature-card:hover {
transform: translateY(-5px);
}
.feature-card .material-symbols-light--article,
.feature-card .material-symbols-light--bookmark,
.feature-card .material-symbols-light--person {
transition: all 0.3s ease;
}
.feature-card:hover .material-symbols-light--article,
.feature-card:hover .material-symbols-light--bookmark,
.feature-card:hover .material-symbols-light--person {
transform: scale(1.1);
}
.stats-section {
position: relative;
}
.stats-section::before {
content: "";
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: url("/images/stats-bg.svg") no-repeat center center;
background-size: cover;
opacity: 0.05;
z-index: 0;
}
.stat-item {
transition: all 0.3s ease;
}
.stat-item:hover {
transform: scale(1.05);
}
.user-dashboard {
position: relative;
}
.user-dashboard::before {
content: "";
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: url("/images/dashboard-bg.svg") no-repeat center center;
background-size: cover;
opacity: 0.03;
z-index: 0;
}
.avatar {
transition: all 0.3s ease;
}
.avatar:hover {
transform: scale(1.05);
}
/* 响应式设计 */
@media (max-width: 768px) {
.hero-section {
padding: 4rem 0;
}
.hero-content h1 {
font-size: 2.5rem;
}
.features-grid {
grid-template-columns: 1fr;
}
.stats-grid {
grid-template-columns: 1fr 1fr;
}
.user-info {
text-align: center;
margin-bottom: 1.5rem;
}
.user-actions {
justify-content: center;
}
}
@media (max-width: 480px) {
.hero-content h1 {
font-size: 2rem;
}
.hero-content p {
font-size: 1rem;
}
.stats-grid {
grid-template-columns: 1fr;
}
.hero-actions {
flex-direction: column;
gap: 1rem;
}
.hero-actions a {
width: 100%;
text-align: center;
}
}

1188
public/scss-compiler/page/index/markdown-green.css

File diff suppressed because it is too large

1188
public/scss-compiler/page/index/markdown-reset.css

File diff suppressed because it is too large

1188
public/scss-compiler/page/index/style.css

File diff suppressed because it is too large

25
src/controllers/Api/AuthController.js

@ -0,0 +1,25 @@
import { R } from "utils/helper.js"
import Router from "utils/router.js"
import BaseController from "@/base/BaseController.js"
class AuthController extends BaseController {
constructor() {
super()
}
async loginPost(ctx) {
return this.success(ctx, null, "登录成功")
}
/**
* 路由注册
*/
static createRoutes() {
const controller = new AuthController()
const router = new Router({ prefix: "/api/auth", auth: "try" })
router.post("/login", controller.handleRequest(controller.loginPost))
return router
}
}
export default AuthController

35
src/controllers/Page/AuthController.js

@ -0,0 +1,35 @@
import Router from "utils/router.js"
import { logger } from "@/logger.js"
import BaseController from "@/base/BaseController.js"
export default class AuthController extends BaseController {
constructor() {
super()
}
// 首页
async loginGet(ctx) {
return this.render(ctx, "page/login/index", {})
}
async loginPost(ctx) {
console.log(ctx.request.body);
return this.success(ctx, null, "登录成功")
}
/**
* 创建基础页面相关路由
* @returns {Router} 路由实例
*/
static createRoutes() {
const controller = new AuthController()
const router = new Router({ auth: false })
// 首页
router.get("", controller.handleRequest(controller.loginGet))
router.get("/login", controller.handleRequest(controller.loginGet))
router.post("/login", controller.handleRequest(controller.loginPost))
return router
}
}

22
src/middlewares/install.js

@ -105,32 +105,17 @@ export default async app => {
options: {
basedir: resolve(__dirname, "../views"),
filters: {
"my-own-filter": function (text, options) {
if (options.addStart) text = "Start\n" + text
if (options.addEnd) text = text + "\nEnd"
return text
},
scss: function (text, options) {
//- process.env.SASS_PATH = "D:/@code/demo/koa3-demo/src/views/page/index"
const root = path.resolve(__dirname, "../views")
const publicPath = path.resolve(__dirname, "../../public")
const publicScssPath = path.resolve(publicPath, "scss-compiler")
const result = render(text, {
const globalScss = `@import "_scss/global";`
const result = render(globalScss + "\n" + text, {
...options,
includePaths: [...(options.includePaths || []), path.resolve(__dirname, "../views")],
})
const links = []
// result.dependencies.forEach(file => {
// const scssFile = path.resolve(publicScssPath, path.relative(root, file))
// const cssFile = scssFile.replace(path.extname(scssFile), ".css")
// if (!fs.existsSync(scssFile)) {
// fs.mkdirSync(path.parse(scssFile).dir, { recursive: true })
// }
// fs.writeFileSync(cssFile, result.body)
// links.push(cssFile)
// })
return `${links.map(v=>`<link rel="stylesheet" href="${config.base + path.relative(publicPath, v).replaceAll("\\", "/")}">`).join("\n")}
<style>${result.body}</style>`
return `<style>${result.body}</style>`
},
},
},
@ -153,6 +138,7 @@ export default async app => {
})
)
// 验证用户
// 注入全局变量:ctx.state.user
app.use(VerifyUserMiddleware())
// 请求体解析
app.use(bodyParser())

84
src/services/AuthService.js

@ -0,0 +1,84 @@
import UserModel from "../db/models/UserModel.js"
import CommonError from "utils/error/CommonError.js"
import { comparePassword } from "utils/bcrypt.js"
/**
* 认证服务类
* 提供认证相关的业务逻辑
*/
class AuthService {
// 注册新用户
static async register(data) {
try {
if (!data.username || !data.password) {
throw new CommonError("用户名和密码不能为空")
}
// 检查用户名是否已存在
const existUser = await UserModel.findByUsername(data.username)
if (existUser) {
throw new CommonError(`用户名${data.username}已存在`)
}
// 检查邮箱是否已存在
if (data.email) {
const existEmail = await UserModel.findByEmail(data.email)
if (existEmail) {
throw new CommonError(`邮箱${data.email}已被使用`)
}
}
// 密码加密
const hashed = await hashPassword(data.password)
const user = await UserModel.create({ ...data, password: hashed })
// 返回脱敏信息
const { password, ...userInfo } = Array.isArray(user) ? user[0] : user
return userInfo
} catch (error) {
if (error instanceof CommonError) throw error
throw new CommonError(`注册失败: ${error.message}`)
}
}
// 登录
static async login({ username, email, password }) {
try {
if (!password) {
throw new CommonError("密码不能为空")
}
if (!username && !email) {
throw new CommonError("用户名或邮箱不能为空")
}
let user
if (username) {
user = await UserModel.findByUsername(username)
} else if (email) {
user = await UserModel.findByEmail(email)
}
if (!user) {
throw new CommonError("用户不存在")
}
// 校验密码
const ok = await comparePassword(password, user.password)
if (!ok) {
throw new CommonError("密码错误")
}
// 生成token
const token = jwt.sign({ id: user.id, username: user.username }, JWT_SECRET, { expiresIn: "2h" })
// 返回token和用户信息
const { password: pwd, ...userInfo } = user
return { token, user: userInfo }
} catch (error) {
if (error instanceof CommonError) throw error
throw new CommonError(`登录失败: ${error.message}`)
}
}
}

21
src/views/_scss/global.scss

@ -0,0 +1,21 @@
@mixin chinese() {
&.chinese {
text-indent: 1.5em;
font-weight: 300;
h1,
h2,
h3,
h4,
h5,
h6,
ol,
ul,
blockquote,
details,
summary,
pre,
.tabs {
text-indent: 0;
}
}
}

51
src/views/htmx/footer/index.pug

@ -0,0 +1,51 @@
footer.footer.shadow.mt-5
.footer-panel(class="bg-white border-t border-gray-200")
.footer-content.container(class="pt-12 pb-6")
.footer-main(class="grid grid-cols-1 md:grid-cols-4 gap-8 mb-8")
.footer-section
h3.footer-title(class="text-lg font-semibold text-gray-900 mb-4") #{siteConfig.site_title}
p.footer-desc(class="text-gray-600 text-sm leading-relaxed") 明月照佳人,用真心对待世界。<br>岁月催人老,用真情对待自己。
.footer-section
h3.footer-title(class="text-lg font-semibold text-gray-900 mb-4") 快速链接
ul.footer-links(class="space-y-3")
li
a(href="/" class="text-gray-600 hover:text-blue-600 transition-colors duration-200 text-sm") 首页
li
a(href="/about" class="text-gray-600 hover:text-blue-600 transition-colors duration-200 text-sm") 关于我们
li
a(href="/contact" class="text-gray-600 hover:text-blue-600 transition-colors duration-200 text-sm") 联系我们
li
a(href="/help" class="text-gray-600 hover:text-blue-600 transition-colors duration-200 text-sm") 帮助中心
.footer-section
h3.footer-title(class="text-lg font-semibold text-gray-900 mb-4") 服务支持
ul.footer-links(class="space-y-3")
li
a(href="/terms" class="text-gray-600 hover:text-blue-600 transition-colors duration-200 text-sm") 服务条款
li
a(href="/privacy" class="text-gray-600 hover:text-blue-600 transition-colors duration-200 text-sm") 隐私政策
li
a(href="/faq" class="text-gray-600 hover:text-blue-600 transition-colors duration-200 text-sm") 常见问题
li
a(href="/feedback" class="text-gray-600 hover:text-blue-600 transition-colors duration-200 text-sm") 意见反馈
.footer-section
h3.footer-title(class="text-lg font-semibold text-gray-900 mb-4") 关注我
.social-links(class="flex space-x-4 flex-wrap")
a(href="#" class="social-link p-2 rounded-full bg-gray-100 hover:bg-blue-100 transition-colors duration-200" title="微信")
span.streamline-ultimate-color--wechat-logo
a(href="#" class="social-link p-2 rounded-full bg-gray-100 hover:bg-blue-100 transition-colors duration-200" title="QQ")
span.cib--tencent-qq
a(href="#" class="social-link p-2 rounded-full bg-gray-100 hover:bg-gray-200 transition-colors duration-200" title="GitHub")
span.ri--github-fill
a(href="https://blog.xieyaxin.top" target="_blank" class="social-link p-2 rounded-full bg-gray-100 hover:bg-gray-200 transition-colors duration-200" title="GitHub")
span.icomoon-free--blog
.footer-bottom(class="border-t border-gray-200 pt-6")
.footer-bottom-content(class="flex flex-col md:flex-row justify-between items-center")
.copyright(class="text-gray-500 text-sm mb-4 md:mb-0")
| © 2023-#{new Date().getFullYear()} #{siteConfig.site_author}. 保留所有权利。
.footer-actions(class="flex items-center space-x-6")
a(href="/sitemap" class="text-gray-500 hover:text-blue-600 transition-colors duration-200 text-sm") 网站地图
a(href="/rss" class="text-gray-500 hover:text-blue-600 transition-colors duration-200 text-sm") RSS订阅

11
src/views/htmx/markdown/index.pug

@ -0,0 +1,11 @@
:scss
@import "./style.scss";
@import "./markdown-reset.scss";
@import "./markdown-green.scss";
.markdown-body.green
:markdown-it(linkify langPrefix='highlight-')
# 关于
这是一个关于页面,欢迎访问。
> 世上本无事,庸人自扰之。

46
src/views/page/index/markdown-green.scss → src/views/htmx/markdown/markdown-green.scss

@ -1,47 +1,21 @@
@mixin chinese() {
&.chinese {
text-indent: 1.5em;
font-weight: 300;
h1,
h2,
h3,
h4,
h5,
h6,
ol,
ul,
blockquote,
details,
summary,
pre,
.tabs {
text-indent: 0;
}
}
}
// ::selection {
// background-color: #1abc9c;
// color: #fff;
// }
// pre ::selection {
// color: inherit;
// }
.markdown-body.green {
.markdown-body {
--color-base: #ef4444;
--markdown-bg: white;
--color-base-text: #fff;
--color-bg: #ff47479c;
--color-light: #ef44441a;
--color-extra: rgba(239, 68, 68, 0.3);
--color-more: rgba(239, 68, 68, 0.4);
}
--prism-background: #eeeeee;
--prism-font-size: 14px;
--prism-font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace;
.markdown-body.green {
background-color: var(--markdown-bg);
@apply p-3 lg:p-6;
::selection {
background-color: var(--color-base);
color: var(--color-base-text);
}
strong {
&::before {

0
src/views/page/index/markdown-reset.scss → src/views/htmx/markdown/markdown-reset.scss

0
src/views/page/index/style.scss → src/views/htmx/markdown/style.scss

26
src/views/htmx/navbar/index.pug

@ -0,0 +1,26 @@
nav.navbar(class="relative")
.placeholder.mb-5(class="h-[45px] w-full opacity-0")
.fixed-container(class="shadow fixed bg-white h-[45px] top-0 left-0 right-0 z-10")
.container.clearfix(class="h-full")
.navbar-brand
a(href="/" class="text-[20px]") #{siteConfig.site_title}
.left.menu.desktop-only
a.menu-item(
href="/articles"
class=(currentPath === '/articles' || currentPath === '/articles/'
? 'text-blue-600 font-bold border-b-2 border-blue-600'
: 'text-gray-700 hover:text-blue-600 hover:border-b-2 hover:border-blue-400'
)
) 所有文章
if !user
.right.menu.desktop-only
a.menu-item(href="/login") 登录
a.menu-item(href="/register") 注册
else
.right.menu.desktop-only
a.menu-item(href="/profile")
span 欢迎您,
span.font-semibold #{user.name || user.username}
a.menu-item(href="/notice")
.fe--notice-active
a.menu-item(hx-post="/logout") 退出

82
src/views/layouts/empty.pug

@ -5,87 +5,11 @@ block $$head
block pageHead
block $$content
nav.navbar(class="relative")
.placeholder.mb-5(class="h-[45px] w-full opacity-0")
.fixed-container(class="shadow fixed bg-white h-[45px] top-0 left-0 right-0 z-10")
.container.clearfix(class="h-full")
.navbar-brand
a(href="/" class="text-[20px]") #{siteConfig.site_title}
.left.menu.desktop-only
a.menu-item(
href="/articles"
class=(currentPath === '/articles' || currentPath === '/articles/'
? 'text-blue-600 font-bold border-b-2 border-blue-600'
: 'text-gray-700 hover:text-blue-600 hover:border-b-2 hover:border-blue-400'
)
) 所有文章
if !isLogin
.right.menu.desktop-only
a.menu-item(href="/login") 登录
a.menu-item(href="/register") 注册
else
.right.menu.desktop-only
a.menu-item(href="/profile")
span 欢迎您,
span.font-semibold #{user.name || user.username}
a.menu-item(href="/notice")
.fe--notice-active
a.menu-item(hx-post="/logout") 退出
include /htmx/navbar/index.pug
.page-layout
.page.container
block pageContent
footer.footer.shadow.mt-5
.footer-panel(class="bg-white border-t border-gray-200")
.footer-content.container(class="pt-12 pb-6")
.footer-main(class="grid grid-cols-1 md:grid-cols-4 gap-8 mb-8")
.footer-section
h3.footer-title(class="text-lg font-semibold text-gray-900 mb-4") #{siteConfig.site_title}
p.footer-desc(class="text-gray-600 text-sm leading-relaxed") 明月照佳人,用真心对待世界。<br>岁月催人老,用真情对待自己。
.footer-section
h3.footer-title(class="text-lg font-semibold text-gray-900 mb-4") 快速链接
ul.footer-links(class="space-y-3")
li
a(href="/" class="text-gray-600 hover:text-blue-600 transition-colors duration-200 text-sm") 首页
li
a(href="/about" class="text-gray-600 hover:text-blue-600 transition-colors duration-200 text-sm") 关于我们
li
a(href="/contact" class="text-gray-600 hover:text-blue-600 transition-colors duration-200 text-sm") 联系我们
li
a(href="/help" class="text-gray-600 hover:text-blue-600 transition-colors duration-200 text-sm") 帮助中心
.footer-section
h3.footer-title(class="text-lg font-semibold text-gray-900 mb-4") 服务支持
ul.footer-links(class="space-y-3")
li
a(href="/terms" class="text-gray-600 hover:text-blue-600 transition-colors duration-200 text-sm") 服务条款
li
a(href="/privacy" class="text-gray-600 hover:text-blue-600 transition-colors duration-200 text-sm") 隐私政策
li
a(href="/faq" class="text-gray-600 hover:text-blue-600 transition-colors duration-200 text-sm") 常见问题
li
a(href="/feedback" class="text-gray-600 hover:text-blue-600 transition-colors duration-200 text-sm") 意见反馈
.footer-section
h3.footer-title(class="text-lg font-semibold text-gray-900 mb-4") 关注我
.social-links(class="flex space-x-4 flex-wrap")
a(href="#" class="social-link p-2 rounded-full bg-gray-100 hover:bg-blue-100 transition-colors duration-200" title="微信")
span.streamline-ultimate-color--wechat-logo
a(href="#" class="social-link p-2 rounded-full bg-gray-100 hover:bg-blue-100 transition-colors duration-200" title="QQ")
span.cib--tencent-qq
a(href="#" class="social-link p-2 rounded-full bg-gray-100 hover:bg-gray-200 transition-colors duration-200" title="GitHub")
span.ri--github-fill
a(href="https://blog.xieyaxin.top" target="_blank" class="social-link p-2 rounded-full bg-gray-100 hover:bg-gray-200 transition-colors duration-200" title="GitHub")
span.icomoon-free--blog
.footer-bottom(class="border-t border-gray-200 pt-6")
.footer-bottom-content(class="flex flex-col md:flex-row justify-between items-center")
.copyright(class="text-gray-500 text-sm mb-4 md:mb-0")
| © 2023-#{new Date().getFullYear()} #{siteConfig.site_author}. 保留所有权利。
.footer-actions(class="flex items-center space-x-6")
a(href="/sitemap" class="text-gray-500 hover:text-blue-600 transition-colors duration-200 text-sm") 网站地图
a(href="/rss" class="text-gray-500 hover:text-blue-600 transition-colors duration-200 text-sm") RSS订阅
include /htmx/footer/index.pug
block $$scripts
block pageScripts

0
src/views/page/index/_global.scss

18
src/views/page/index/index.pug

@ -1,22 +1,6 @@
extends /layouts/empty.pug
block pageHead
:scss
@use "./_global.scss";
@use "./style.scss";
@use "./markdown-reset.scss";
@use "./markdown-green.scss";
block pageContent
.markdown-body
:markdown-it(linkify langPrefix='highlight-')
# Markdown
Markdown document with http://links.com and
```js
var codeBlocks;
```
> blockquote
include /htmx/markdown/index.pug

9
src/views/page/login/index.pug

@ -0,0 +1,9 @@
extends /layouts/empty.pug
block pageHead
block pageContent
form(action="/login" method="post")
input(type="text" name="username" placeholder="用户名")
input(type="password" name="password" placeholder="密码")
button(type="submit") 登录
Loading…
Cancel
Save