npmrun 2 years ago
parent
commit
ba18d5dfbe
  1. BIN
      data/data.db
  2. 119
      public/style/views/color.css
  3. 15
      route.txt
  4. 1
      source/plugins/index.ts
  5. 23
      source/plugins/router-plugin/index.ts
  6. 26
      source/route/views/index.ts
  7. 71
      source/route/views/user.ts
  8. 13
      source/run.ts
  9. 2
      template/helper/helper.pug
  10. 53
      template/htmx/path/color.pug
  11. 2
      template/ui/header.pug
  12. 53
      template/views/color.pug

BIN
data/data.db

Binary file not shown.

119
public/style/views/color.css

@ -2,17 +2,22 @@
min-height: 100%;
padding-top: 20px;
position: relative;
}
.color_list {
}
h1{
font-size: 25px;
margin-bottom: 12px;
}
.color_list {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-ms-flex-wrap: wrap;
flex-wrap: wrap;
}
.color_list .color_item {
flex-wrap: wrap;
}
.color_list .color_item {
position: relative;
display: inline-block;
border-radius: 5px;
@ -20,71 +25,75 @@
padding: 5px 10px;
cursor: pointer;
width: 100px;
height: 125px;
}
.color_list .color_item:hover .color_add {
}
.color_list .color_item:hover .color_add {
-webkit-transform: translate(-50%, -50%) scale(1.3);
transform: translate(-50%, -50%) scale(1.3);
}
.color_list .color_item .color_add {
transform: translate(-50%, -50%) scale(1.3);
}
.color_list .color_item .color_add {
width: 50px;
height: 50px;
position: absolute;
top: 50%;
left: 50%;
-webkit-transition: -webkit-transform .3s linear;
transition: -webkit-transform .3s linear;
transition: transform .3s linear;
transition: transform .3s linear, -webkit-transform .3s linear;
-webkit-transition: -webkit-transform 0.3s linear;
transition: -webkit-transform 0.3s linear;
transition: transform 0.3s linear;
transition: transform 0.3s linear, -webkit-transform 0.3s linear;
-webkit-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
}
.color_list .color_item:hover {
transform: translate(-50%, -50%);
}
.color_list .color_item:hover {
background-color: rgba(0, 0, 0, 0.041);
}
.color_list .color_item:hover .color_toggle_list {
max-height: 99px;
}
.color_list .color_item .color_toggle_list {
}
.color_list .color_item:hover .color_toggle_list {
top: 0;
}
.color_list .color_item .color_toggle_list {
overflow: hidden;
position: absolute;
bottom: 0;
top: 100%;
left: 0;
right: 0;
width: 100%;
max-height: 0;
-webkit-transition: max-height .5s linear;
transition: max-height .5s linear;
background-color: rgba(180, 180, 180, 0.274);
}
.color_list .color_item .color_toggle_list .color_toggle_item {
display: inline-block;
height: 25px;
height: 100%;
-webkit-transition: top 0.3s ease;
transition: top 0.3s ease;
color: white;
background-color: rgba(0, 0, 0, 0.2);
/* filter: brightness(.7); */
display: flex;
flex-direction: column;
}
.color_list .color_item .color_toggle_list .color_toggle_item {
flex: 1;
height: 0;
box-sizing: border-box;
padding: 2px 6px;
}
.color_list .color_item .color_toggle_list .color_toggle_item:hover {
}
.color_list .color_item .color_toggle_list .color_toggle_item:hover {
background-color: rgba(0, 0, 0, 0.185);
}
.color_list .color_item .color_item_bg {
}
.color_list .color_item .color_item_bg {
height: 50px;
background-color: red;
position: relative;
}
.color_list .color_item .color_item_content .color_item_title {
overflow: hidden;
}
.color_list .color_item .color_item_content .color_item_title {
font-size: 1.2em;
font-weight: bold;
}
.color_list .color_item .color_item_content .color_item_desc {
}
.color_list .color_item .color_item_content .color_item_desc {
color: #a7a6a6;
display: -webkit-box;
-webkit-box-orient: vertical;
@ -92,5 +101,5 @@
overflow: hidden;
text-overflow: ellipsis;
word-break: break-all;
}
/*# sourceMappingURL=color.css.map */
}
/*# sourceMappingURL=color.css.map */

15
route.txt

@ -1,16 +1,17 @@
/home/topuser/Code/@project/hapi-demo/source/route/htmx对应路径:
不需权限 : GET /htmx/path/{path*}
/home/topuser/Code/@project/hapi-demo/source/route/views对应路径:
D:\1XYX\pro\hapi-demo\source\route\htmx对应路径:
不需权限(提供无需验证): GET /htmx/path/{path*}
D:\1XYX\pro\hapi-demo\source\route\views对应路径:
不需权限(提供无需验证): GET /404
不需权限(提供无需验证): GET /
不需权限(提供无需验证): GET /about
不需权限(提供无需验证): GET /color
需要权限 : GET /docs/{path*}
不需权限 : GET /{path*}
不需权限(提供无需验证): GET /{path*}
不需权限(提供无需验证): GET /login
不需权限 : POST /login
不需权限 : GET /nav
不需权限(提供无需验证): POST /login
不需权限(提供无需验证): GET /nav
不需权限(提供无需验证): GET /register
不需权限 : POST /register
不需权限(提供无需验证): POST /register
需要权限 : POST /user
需要权限 : GET /user
需要权限 : GET /user/logout

1
source/plugins/index.ts

@ -95,7 +95,6 @@ export default [
const isLogin = request.auth.isAuthenticated
// const { id } = request.auth.credentials;
// loggerSite.debug(`${isLogin?'当前登录ID:'+id:'未登录用户'}, 请求路径:${request.path}, 请求方法:${request.method}`)
// @ts-ignore
// console.log(isLogin, request.path, request.response.variety);
// let user;

23
source/plugins/router-plugin/index.ts

@ -71,16 +71,23 @@ class routePlugin {
if (auth && auth.length && auth.filter(v => route.startsWith(v)).length) {
options.auth = type
} else {
options.auth = false
// 默认是try
options.auth = {
strategy: type,
mode: "try",
}
}
} else if (ff.$auth) {
options.auth =
typeof ff.$auth === "boolean"
? type
: {
strategy: type,
mode: ff.$auth,
}
if(typeof ff.$auth === "boolean" && ff.$auth){
options.auth = type
}else if(typeof ff.$auth === "boolean"){
options.auth = false
}else {
options.auth = {
strategy: type,
mode: ff.$auth,
}
}
} else {
options.auth = false
}

26
source/route/views/index.ts

@ -28,11 +28,11 @@ export default class Index {
return h.redirect(`/login?next=${encodeURIComponent(request.path)}`).takeover()
}
const md = new MarkdownIt()
console.log(path.resolve(baseDir, "./docs/a.md"));
console.log(path.resolve(baseDir, "./docs/a.md"))
var result = md.render(fs.readFileSync(path.resolve(baseDir, "./docs/a.md"), "utf-8"))
const data = {
md: result
md: result,
}
if (isRenderHtmx) {
return h.view("htmx/path/about.pug", data)
@ -40,6 +40,18 @@ export default class Index {
return h.view("views/about.pug", data)
}
@route("/color")
async color(request: Req, h: Res) {
const filePath = path.resolve(baseDir, "template/views", "color.pug")
if (fs.existsSync(filePath)) {
const isRenderHtmx = Reflect.has(request.query, "htmx")
if (isRenderHtmx) {
return h.view(`htmx/path/color.pug`)
}
return h.view(`views/color.pug`)
}
}
@route("/docs/{path*}")
@auth()
async docs(req: Req, h: Res): ReturnValue {
@ -72,8 +84,12 @@ export default class Index {
@route("/{path*}")
async any(req: Req, h: Res): ReturnValue {
if (req.path) {
const filePath = path.resolve(baseDir, "template/views", "."+req.path+".pug")
if(fs.existsSync(filePath)){
const filePath = path.resolve(baseDir, "template/views", "." + req.path + ".pug")
if (fs.existsSync(filePath)) {
const isRenderHtmx = Reflect.has(req.query, "htmx")
if (isRenderHtmx) {
return h.view(`htmx/path${req.path}.pug`)
}
return h.view(`views${req.path}.pug`)
}
}

71
source/route/views/user.ts

@ -111,41 +111,46 @@ export default class {
@auth()
@route_path("/user")
async index_post(request: Req, h: Res): ReturnValue {
const { id, username, nickname, email, tel } = request.auth.credentials
const { filelist, fields } = await Save(request.payload, request)
const result = {}
if (fields["username"] && fields["username"][0] && username !== fields["username"][0]) {
result["username"] = fields["username"][0]
}
if (fields["tel"] && fields["tel"][0] && tel !== fields["tel"][0]) {
result["tel"] = fields["tel"][0]
}
if (fields["nickname"] && fields["nickname"][0] && nickname !== fields["nickname"][0]) {
result["nickname"] = fields["nickname"][0]
}
if (fields["email"] && fields["email"][0] && email !== fields["email"][0]) {
result["email"] = fields["email"][0]
}
if (fields["password"] && fields["password"][0]) {
const pwd = fields["password"][0]
let salt = bcrypt.genSaltSync(10)
let pwdLock = bcrypt.hashSync(pwd, salt)
result["password"] = pwdLock
}
if (filelist && filelist[0]) {
result["avatar"] = filelist[0]
}
if (JSON.stringify(result) !== "{}") {
const UserModel = request.getModel("user")
const user = await UserModel.findOne({ where: { username: fields["username"] } })
if (!!user && user.id !== id) {
request.yar.flash("error", "用户名已被他人占用")
try {
const { id, username, nickname, email, tel } = request.auth.credentials
const { filelist, fields } = await Save(request.payload, request)
const result = {}
if (fields["username"] && fields["username"][0] && username !== fields["username"][0]) {
result["username"] = fields["username"][0]
}
if (!!user && user.id === id) {
await UserModel.update(result, { where: { id } })
// @ts-ignore
request.auth.credentials = await UserModel.findOne({ where: { id } })
if (fields["tel"] && fields["tel"][0] && tel !== fields["tel"][0]) {
result["tel"] = fields["tel"][0]
}
if (fields["nickname"] && fields["nickname"][0] && nickname !== fields["nickname"][0]) {
result["nickname"] = fields["nickname"][0]
}
if (fields["email"] && fields["email"][0] && email !== fields["email"][0]) {
result["email"] = fields["email"][0]
}
if (fields["password"] && fields["password"][0]) {
const pwd = fields["password"][0]
let salt = bcrypt.genSaltSync(10)
let pwdLock = bcrypt.hashSync(pwd, salt)
result["password"] = pwdLock
}
if (filelist && filelist[0]) {
result["avatar"] = filelist[0]
}
if (JSON.stringify(result) !== "{}") {
const UserModel = request.getModel("user")
const user = await UserModel.findOne({ where: { username: fields["username"] } })
if (!!user && user.id !== id) {
request.yar.flash("error", "用户名已被他人占用")
}
if (!!user && user.id === id) {
await UserModel.update(result, { where: { id } })
// @ts-ignore
request.auth.credentials = await UserModel.findOne({ where: { id } })
}
}
} catch (error) {
loggerSite.error(error.message)
request.yar.flash("error", error.message)
}
return h.redirect("/user")
}

13
source/run.ts

@ -1,12 +1,13 @@
"use strict"
import plugins from "@/plugins"
import path from "path"
import { baseDir, isDev, sourceDir, templateDir } from "@/util"
import { baseDir, isDev, publicDir, sourceDir, templateDir } from "@/util"
import { validateJwt, validateSession } from "./auth"
import Hapi, { Server } from "@hapi/hapi"
import { Sequelize } from "sequelize"
import { Req } from "#/global"
import { sequelize } from "./plugins/sequelize"
import fs from "fs-extra"
// const Hapi = require("@hapi/hapi");
// const HapiSwagger = require("hapi-swagger");
// const HapiSwagger = require("hapi-swaggered-ui"); // swagger v2版本
@ -89,10 +90,18 @@ const run = async (): Promise<Server> => {
*/
// https://hapi.dev/module/vision/api/?v=6.1.0
await server.register(require("@hapi/vision"))
const Pug = require("pug")
Pug.filters.public = function (text, options) {
const p = path.resolve(publicDir, text)
if(fs.pathExistsSync(p)) {
return fs.readFileSync(p, "utf-8")
}
return ""
};
server.views({
engines: {
ejs: require("ejs"),
pug: require("pug"),
pug: Pug,
},
isCached: process.env.NODE_ENV === "development" ? false : true,
compileMode: "sync", // ejs

2
template/helper/helper.pug

@ -4,4 +4,4 @@ mixin script(src)
script(src="/public/"+src)
mixin security
include ./form_security.pug
include ./form_security.pug

53
template/htmx/path/color.pug

@ -0,0 +1,53 @@
include @/helper/flush.pug
include @/helper/helper.pug
block var
-title="颜色" // 网页标题
title 颜色
div(class="container page")
style
:public style/views/color.css
h1 颜色表
div(class="color_list")
-
var list=[
{ color:"#00ffff",title: "青色",describe:""},
{ color:"#222222",title: "辅助色",describe:""},
{ color:"#8f8f8f",title: "辅助色",describe:""},
{ color:"#00d1b2",title: "辅助色",describe:""},
{ color:"#999999",title: "辅助色",describe:""},
{ color:"#999999",title: "辅助色",describe:""},
{ color:"#999999",title: "辅助色",describe:""},
{ color:"#999999",title: "辅助色",describe:""},
{ color:"#999999",title: "辅助色",describe:""},
{ color:"#999999",title: "辅助色",describe:""},
{ color:"#999999",title: "辅助色",describe:""},
{ color:"#999999",title: "辅助色",describe:""},
{ color:"#999999",title: "辅助色",describe:""},
{ color:"#999999",title: "辅助色",describe:""},
{ color:"#999999",title: "辅助色",describe:""},
{ color:"#999999",title: "辅助色",describe:""},
{ color:"#999999",title: "辅助色",describe:""},
{ color:"#999999",title: "辅助色",describe:""},
{ color:"#999999",title: "辅助色",describe:""},
{ color:"#999999",title: "辅助色",describe:""},
]
each item in list
div(class="color_item")
div(class="color_item_bg" style=`background: ${item.color}`)
div(class="color_toggle_list")
div(class="color_toggle_item") hex
div(class="color_toggle_item") rgba
div(class="color_item_name") #{item.color}
div(class="color_item_content")
div(class="color_item_title") #{item.title}
div(class="color_item_desc") #{item.describe || "暂无描述"}
//- div(class="color_item")
//- img(src="/public/image/add.png", alt="添加" title="添加" class="color_add")
if isLogin
div
form(action="POST" method="post")
div(class=".wrapper_input"): input(type="text" tabindex="1" value="sadsa" name="a")
div(class=".wrapper_input"): input(type="text" tabindex="3" value="sadsa" name="b")
button(type="submit" tabindex="2") 提交

2
template/ui/header.pug

@ -12,6 +12,8 @@ nav.is-fixed-top.navbar(role='navigation', aria-label='main navigation', style="
.navbar-start
a.navbar-item(hx-get="/?htmx" hx-push-url="/" hx-trigger="click" hx-target="#single-page" hx-swap="innerHTML")
| 首页
a.navbar-item(hx-get="/color?htmx" hx-push-url="/color" hx-trigger="click" hx-target="#single-page" hx-swap="innerHTML")
| 颜色
.navbar-item.has-dropdown.is-hoverable
a.navbar-link
| 更多

53
template/views/color.pug

@ -1,51 +1,4 @@
extends /layout/layout
extends @/layout/single-page
block var
-title="颜色表" // 网页标题
block head
link(rel="stylesheet", href="/public/style/views/color.css")
block content
div(class="container page")
div(class="color_list")
-
var list=[
{ color:"#999999",title: "辅助色",describe:"灰色灰色灰色灰色灰色灰色灰色灰色灰色灰色灰色灰色灰色灰色灰色"},
{ color:"#999999",title: "辅助色",describe:"灰色灰色灰色灰色灰色灰色灰色灰色灰色灰色灰色灰色灰色灰色灰色"},
{ color:"#999999",title: "辅助色",describe:"灰色灰色灰色灰色灰色灰色灰色灰色灰色灰色灰色灰色灰色灰色灰色"},
{ color:"#000000",title: "辅助色",describe:""},
{ color:"#999999",title: "辅助色",describe:""},
{ color:"#999999",title: "辅助色",describe:""},
{ color:"#999999",title: "辅助色",describe:""},
{ color:"#999999",title: "辅助色",describe:""},
{ color:"#999999",title: "辅助色",describe:""},
{ color:"#999999",title: "辅助色",describe:""},
{ color:"#999999",title: "辅助色",describe:""},
{ color:"#999999",title: "辅助色",describe:""},
{ color:"#999999",title: "辅助色",describe:""},
{ color:"#999999",title: "辅助色",describe:""},
{ color:"#999999",title: "辅助色",describe:""},
{ color:"#999999",title: "辅助色",describe:""},
{ color:"#999999",title: "辅助色",describe:""},
{ color:"#999999",title: "辅助色",describe:""},
{ color:"#999999",title: "辅助色",describe:""},
{ color:"#999999",title: "辅助色",describe:""},
]
each item in list
div(class="color_item")
div(class="color_item_bg" style=`background: ${item.color}`)
div(class="color_toggle_list")
div(class="color_toggle_item") hex
div(class="color_toggle_item") rgba
div(class="color_item_name") #{item.color}
div(class="color_item_content")
div(class="color_item_title") #{item.title}
div(class="color_item_desc") #{item.describe || "暂无描述"}
div(class="color_item")
//- img(src="/public/image/add.png", alt="添加" title="添加" class="color_add")
div
form(action="POST" method="post")
div(class=".wrapper_input"): input(type="text" tabindex="1" value="sadsa" name="a")
div(class=".wrapper_input"): input(type="text" tabindex="3" value="sadsa" name="b")
button(type="submit" tabindex="2") 提交
block page
include @hxpath/color.pug

Loading…
Cancel
Save