Browse Source

新增 API 控制器,优化路由,增加隐私政策、服务条款、常见问题和反馈页面,调整样式和布局,提升用户体验

re
dash 3 months ago
parent
commit
3157f30b55
  1. BIN
      database/development.sqlite3-shm
  2. BIN
      database/development.sqlite3-wal
  3. 7
      docs/links.md
  4. 1
      public/css/layouts/root.css
  5. 14
      public/css/page/index.css
  6. 58
      src/controllers/Api/ApiController.js
  7. 9
      src/controllers/Page/PageController.js
  8. 2
      src/views/layouts/empty.pug
  9. 4
      src/views/layouts/root.pug
  10. 1
      src/views/page/extra/faq.pug
  11. 3
      src/views/page/extra/feedback.pug
  12. 3
      src/views/page/extra/privacy.pug
  13. 3
      src/views/page/extra/terms.pug
  14. 3
      src/views/page/index/index.pug
  15. 7
      src/views/page/profile/index.pug

BIN
database/development.sqlite3-shm

Binary file not shown.

BIN
database/development.sqlite3-wal

Binary file not shown.

7
docs/links.md

@ -0,0 +1,7 @@
https://pkmer.cn/Pkmer-Docs/10-obsidian/obsidian%E7%A4%BE%E5%8C%BA%E6%8F%92%E4%BB%B6/readme/obsidian-local-rest-api_readme/
https://trix-editor.org/js/attachments.js
https://github.com/basecamp/trix/tree/main
https://icon-sets.iconify.design/?query=info

1
public/css/layouts/root.css

@ -5,6 +5,7 @@ body {
height: 100%;
font-family: Arial, sans-serif;
color: #333;
scroll-behavior: smooth;
}
body {

14
public/css/page/index.css

@ -52,4 +52,18 @@
.list a:hover {
text-decoration: underline;
}
.material-symbols-light--info-rounded {
display: inline-block;
width: 24px;
height: 24px;
--svg: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%23000' d='M12 16.5q.214 0 .357-.144T12.5 16v-4.5q0-.213-.144-.356T11.999 11t-.356.144t-.143.356V16q0 .213.144.356t.357.144M12 9.577q.262 0 .439-.177t.176-.438t-.177-.439T12 8.346t-.438.177t-.177.439t.177.438t.438.177M12.003 21q-1.867 0-3.51-.708q-1.643-.709-2.859-1.924t-1.925-2.856T3 12.003t.709-3.51Q4.417 6.85 5.63 5.634t2.857-1.925T11.997 3t3.51.709q1.643.708 2.859 1.922t1.925 2.857t.709 3.509t-.708 3.51t-1.924 2.859t-2.856 1.925t-3.509.709'/%3E%3C/svg%3E");
background-color: currentColor;
-webkit-mask-image: var(--svg);
mask-image: var(--svg);
-webkit-mask-repeat: no-repeat;
mask-repeat: no-repeat;
-webkit-mask-size: 100% 100%;
mask-size: 100% 100%;
}

58
src/controllers/Api/ApiController.js

@ -0,0 +1,58 @@
import { formatResponse } from "utils/helper.js"
import Router from "utils/router.js"
class AuthController {
constructor() {}
/**
* 通用请求函数依次请求网址数组返回第一个成功的响应及其类型
* @param {string[]} urls
* @returns {Promise<{type: string, data: any}>}
*/
async fetchFirstSuccess(urls) {
for (const url of urls) {
try {
const res = await fetch(url, { method: "get", mode: "cors", redirect: "follow" })
if (!res.ok) continue
const contentType = res.headers.get("content-type") || ""
let data, type
if (contentType.includes("application/json")) {
data = await res.json()
type = "json"
} else if (contentType.includes("text/")) {
data = await res.text()
type = "text"
} else {
data = await res.blob()
type = "blob"
}
return { type, data }
} catch (e) {
// ignore and try next url
}
}
throw new Error("All requests failed")
}
async random(ctx) {
const { type, data } = await this.fetchFirstSuccess(["https://api.miaomc.cn/image/get"])
if (type === "blob") {
ctx.set("Content-Type", "image/jpeg")
ctx.body = data
} else {
ctx.body = formatResponse(false, "Failed to fetch image")
}
}
/**
* 路由注册
*/
static createRoutes() {
const controller = new AuthController()
const router = new Router({ prefix: "/api/pics" })
router.get("/random", controller.random.bind(controller), { auth: false })
return router
}
}
export default AuthController

9
src/controllers/Page/PageController.js

@ -171,10 +171,11 @@ class PageController {
router.get("/articles", controller.pageGet("page/articles/index"), { auth: false })
router.get("/about", controller.pageGet("page/about/index"), { auth: false })
router.get("/terms", controller.pageGet("page/index/terms"), { auth: false })
router.get("/privacy", controller.pageGet("page/index/privacy"), { auth: false })
router.get("/faq", controller.pageGet("page/index/faq"), { auth: false })
// router.get("/feedback", controller.pageGet("page/index/feedback"), { auth: false })
router.get("/terms", controller.pageGet("page/extra/terms"), { auth: false })
router.get("/privacy", controller.pageGet("page/extra/privacy"), { auth: false })
router.get("/faq", controller.pageGet("page/extra/faq"), { auth: false })
router.get("/feedback", controller.pageGet("page/extra/feedback"), { auth: false })
router.get("/profile", controller.pageGet("page/profile/index"), { auth: true })
router.get("/login", controller.loginGet.bind(controller), { auth: "try" })
router.post("/login", controller.loginPost.bind(controller), { auth: false })
router.get("/captcha", controller.captchaGet.bind(controller), { auth: false })

2
src/views/layouts/empty.pug

@ -24,7 +24,7 @@ block $$content
else
.right.menu.desktop-only
a.menu-item(hx-post="/logout") 退出
a.menu-item() 欢迎您 , #{$user.username}
a.menu-item(href="/profile") 欢迎您 , #{$user.username}
// 移动端:汉堡按钮
button.menu-toggle(type="button" aria-label="打开菜单")
span.bar

4
src/views/layouts/root.pug

@ -38,9 +38,9 @@ html(lang="zh-CN")
block $$scripts
script.
//- 处理滚动条位置
const el = document.querySelector('.simplebar-content-wrapper')
const scrollTop = sessionStorage.getItem('scrollTop-'+location.pathname)
window.onload = function() {
const el = document.querySelector('.simplebar-content-wrapper')
const scrollTop = sessionStorage.getItem('scrollTop-'+location.pathname)
el.scrollTop = scrollTop
el.addEventListener("scroll", function(e) {
sessionStorage.setItem('scrollTop-'+location.pathname, e.target.scrollTop)

1
src/views/page/index/faq.pug → src/views/page/extra/faq.pug

@ -1,7 +1,6 @@
extends /layouts/empty.pug
block pageHead
+css('css/page/index.css')
block pageContent
.faq.container(class="mt-[20px] bg-white rounded-[12px] shadow p-6 border border-gray-100")

3
src/views/page/index/feedback.pug → src/views/page/extra/feedback.pug

@ -1,7 +1,6 @@
extends /layouts/empty.pug
block pageHead
+css('css/page/index.css')
block pageContent
.feedback.container(class="mt-[20px] bg-white rounded-[12px] shadow p-6 border border-gray-100")
@ -9,7 +8,7 @@ block pageContent
p(class="text-gray-600 mb-6") 欢迎提出您的建议或问题,我们会尽快处理。
form(class="space-y-4" method="post" action="#" onsubmit="alert('感谢反馈!'); return false;")
.grid.grid-cols-1.md\:grid-cols-2.gap-4
.grid.grid-cols-1(class="md:grid-cols-2 gap-4")
.form-item
label.block.text-sm.text-gray-600.mb-1(for="name") 您的称呼
input#name(type="text" name="name" placeholder="例如:张三" class="w-full border border-gray-200 rounded px-3 py-2 focus:outline-none focus:ring-2 focus:ring-blue-200")

3
src/views/page/index/privacy.pug → src/views/page/extra/privacy.pug

@ -1,8 +1,5 @@
extends /layouts/empty.pug
block pageHead
+css('css/page/index.css')
block pageContent
.privacy.container(class="mt-[20px] bg-white rounded-[12px] shadow p-6 border border-gray-100")
h1(class="text-2xl font-bold mb-4") 隐私政策

3
src/views/page/index/terms.pug → src/views/page/extra/terms.pug

@ -1,8 +1,5 @@
extends /layouts/empty.pug
block pageHead
+css('css/page/index.css')
block pageContent
.terms.container(class="mt-[20px] bg-white rounded-[12px] shadow p-6 border border-gray-100")
h1(class="text-2xl font-bold mb-4") 服务条款

3
src/views/page/index/index.pug

@ -7,8 +7,9 @@ block pageHead
+js("https://unpkg.com/tippy.js@5")
mixin item(url, desc)
a(href=url data-tippy-content=desc target="_blank" class="inline-block text-[16px] p-[10px] rounded-[10px] shadow")
a(href=url target="_blank" class="inline-flex items-center text-[16px] p-[10px] rounded-[10px] shadow")
block
.material-symbols-light--info-rounded(data-tippy-content=desc)
mixin card(blog)
.article-card(class="bg-white rounded-[12px] shadow p-6 transition hover:shadow-lg border border-gray-100")

7
src/views/page/profile/index.pug

@ -0,0 +1,7 @@
extends /layouts/empty.pug
block pageHead
block pageContent
div sad
Loading…
Cancel
Save