navbar
This commit is contained in:
parent
a897a9cb01
commit
9cf47f9a6b
78
main.js
78
main.js
@ -1,9 +1,43 @@
|
||||
import { div, span, main, section, aside, h3, p, ul, li } from '@laniakeasupercluster/widgets'
|
||||
import { div, span, main, section, aside, h3, p, ul, li, header, nav, a } from '@laniakeasupercluster/widgets'
|
||||
|
||||
const navData = [
|
||||
{ id: '1', name: 'Home', path: '/' },
|
||||
{ id: '2', name: 'Blog', path: '/blog' },
|
||||
{ id: '3', name: 'About', path: '/about' },
|
||||
{ id: '4', name: 'Contact', path: '/contact' }
|
||||
]
|
||||
|
||||
document.body.appendChild(header.flex({ justifyContent: 'space-between', alignItems: 'center' }).childs([
|
||||
nav.flex({ gap: '1rem' }).childs(navData.map(item => {
|
||||
const link = document.createElement('a')
|
||||
link.href = `/${item.path}`
|
||||
link.textContent = item.name
|
||||
link.style.padding = '.5rem'
|
||||
link.style.borderRadius = '.25rem'
|
||||
link.style.color = (item.path === window.location.pathname) ? '#00C16A' : '#333'
|
||||
return link
|
||||
})),
|
||||
div.text('sign'),
|
||||
]))
|
||||
|
||||
const blogata = await fetch('/api/blog').then(res => res.text())
|
||||
console.log(blogata)
|
||||
|
||||
const blogData = [
|
||||
{ id: '1', title: 'Blog 1', content: 'Content 1', date: new Date() },
|
||||
{ id: '2', title: 'Blog 2', content: 'Content 2', date: new Date() },
|
||||
{ id: '3', title: 'Blog 3', content: 'Content 3', date: new Date() },
|
||||
{ id: '3', title: 'Blog 3', content: 'Content 3', date: new Date() },
|
||||
{ id: '3', title: 'Blog 3', content: 'Content 3', date: new Date() },
|
||||
{ id: '3', title: 'Blog 3', content: 'Content 3', date: new Date() },
|
||||
{ id: '3', title: 'Blog 3', content: 'Content 3', date: new Date() },
|
||||
{ id: '3', title: 'Blog 3', content: 'Content 3', date: new Date() },
|
||||
{ id: '3', title: 'Blog 3', content: 'Content 3', date: new Date() },
|
||||
{ id: '3', title: 'Blog 3', content: 'Content 3', date: new Date() },
|
||||
{ id: '3', title: 'Blog 3', content: 'Content 3', date: new Date() },
|
||||
{ id: '3', title: 'Blog 3', content: 'Content 3', date: new Date() },
|
||||
{ id: '3', title: 'Blog 3', content: 'Content 3', date: new Date() },
|
||||
{ id: '3', title: 'Blog 3', content: 'Content 3', date: new Date() },
|
||||
]
|
||||
const tagData = ['JavaScript', 'CSS', 'HTML', 'Web', 'JavaScript', 'CSS', 'HTML', 'Web', 'JavaScript', 'CSS', 'HTML', 'Web', 'JavaScript', 'CSS', 'HTML', 'Web']
|
||||
const articleData = ['Article 1', 'Article 2', 'Article 3']
|
||||
@ -14,17 +48,53 @@ document.body.appendChild(div.grid({ gridTemplateColumns: '3fr 1fr', gap: '1rem'
|
||||
p.text(blog.content),
|
||||
p.text(blog.date),
|
||||
]))),
|
||||
aside.grid({ gridColumn: '2', flexDirection: 'column', gap: '1rem' }).childs([
|
||||
aside.flex({ gridColumn: '2', flexDirection: 'column', gap: '1rem' }).childs([
|
||||
div.childs([
|
||||
h3.font('bold').text('# TAG'),
|
||||
h3.font('bold').text('TAG'),
|
||||
div.flex({ gap: '.5rem', flexWrap: 'wrap' }).childs([
|
||||
// cursor-pointer overflow-clip hover:text-pink-500
|
||||
...tagData.map(tag => span.bg('rgba(200,200,200,.2)').radius('.25rem').px('8px').text(tag))
|
||||
]),
|
||||
]),
|
||||
div.childs([
|
||||
h3.font('bold 8px').text('# 归档'),
|
||||
h3.font('bold').text('归档'),
|
||||
ul.childs(articleData.map(article => li.text(article))),
|
||||
]),
|
||||
]),
|
||||
]))
|
||||
|
||||
const style = document.createElement('style')
|
||||
style.textContent = `
|
||||
body {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-wrap: nowrap;
|
||||
font-family: inherit;
|
||||
}
|
||||
body > header {
|
||||
gap: 1rem;
|
||||
width: 100%;
|
||||
line-height: 4rem;
|
||||
border-bottom: 1px solid #f5f6f5;
|
||||
}
|
||||
body header nav {
|
||||
display: flex;
|
||||
gap: 1rem;
|
||||
font-weight: bold;
|
||||
font-size: 1.25rem;
|
||||
width: 100%;
|
||||
max-width: 1280px;
|
||||
margin: 0 auto;
|
||||
padding: 0 1.3rem;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
body aside h3 {
|
||||
font-size: 1rem;
|
||||
font-weight: 700;
|
||||
}
|
||||
body aside h3::before {
|
||||
content: '# ';
|
||||
color: #00C16A;
|
||||
}
|
||||
`
|
||||
document.head.appendChild(style)
|
||||
|
1
routers/home.js
Normal file
1
routers/home.js
Normal file
@ -0,0 +1 @@
|
||||
export default {}
|
44
server.js
44
server.js
@ -14,6 +14,15 @@ const databases = new Map() // 所有数据库
|
||||
const FM = new HUB() // 频道消息分发器
|
||||
const messagelist = new Map() // 消息队列的nedb存储
|
||||
|
||||
|
||||
// 服务端推送
|
||||
// 1. 用户消息
|
||||
// 2. 系统消息
|
||||
// 3. 聊天消息
|
||||
// 4. 资源变化(观看中的资源变化)(预取集, 观看集, 缓存集)
|
||||
// 5. 操作同步(其它用户的协作动作)(用户是临时附着与资源的对象, 由于其变化频繁且可丢弃, 通过会话通道读取)
|
||||
|
||||
|
||||
const db = (name) => (databases.get(name) || function () {
|
||||
let database = new nedb({ filename: `./data/db/${name}.db`, autoload: true, timestampData: true })
|
||||
databases.set(name, database)
|
||||
@ -25,15 +34,10 @@ const session_store = sessionDb(session, db('session'))
|
||||
// 登录验证
|
||||
const online = function (req, res, next) {
|
||||
if (!req.session.account) return res.status(401).send('未登录')
|
||||
if (req.session.account.gid !== 1) req.params.uid = req.session.account.uid
|
||||
if (req.session.account.gid !== 1) req.params.uid = req.session.account.uid // 普通用户只能操作自己的
|
||||
next()
|
||||
}
|
||||
|
||||
// 权限(合并优化)
|
||||
const admin = function (account, item) {
|
||||
return (account.gid === 1 || account.uid === item.uid)
|
||||
}
|
||||
|
||||
// 列表计量
|
||||
const count_load = async (name, query) => await new Promise(resolve => db(name).count(query, (err, count) => resolve(count)))
|
||||
|
||||
@ -88,6 +92,7 @@ function session_create(req, res) {
|
||||
if (!doc) return res.status(400).send('账户不存在')
|
||||
return req.session.regenerate(function (err) {
|
||||
req.session.account = { uid: doc._id, gid: doc.gid ?? 0 }
|
||||
req.session.isAdmin = () => (req.session.account.gid === 1) // 是否管理员
|
||||
let { salt, password, ...user } = doc
|
||||
return res.json(user)
|
||||
})
|
||||
@ -199,6 +204,16 @@ const object_list = async function (req, res) {
|
||||
})
|
||||
}
|
||||
|
||||
const isAdmin = (req) => req.session?.account?.gid === 1
|
||||
|
||||
const 权限模组 = (req, res, next) => {
|
||||
// 创建任何对象, 如果不是管理员, 则不能设置 gid 和计算属性以及默认属性
|
||||
if (req.session?.account?.gid !== 1) {
|
||||
['_id', 'uid', 'top', 'user', 'createdAt', 'updatedAt', 'views', 'posts', 'likes', 'files'].forEach(i => delete req.body[i])
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 创建对象
|
||||
const object_create = async function (req, res) {
|
||||
|
||||
@ -406,14 +421,6 @@ function index_get(req, res) {
|
||||
const app = expressWs(express()).app
|
||||
const ServerSentEventsClient = {}
|
||||
|
||||
// 开发模式下使用 Vite
|
||||
if (process.argv.includes('--dev')) {
|
||||
const vite = await createServer({ server: { middlewareMode: 'html' } })
|
||||
app.use(vite.middlewares)
|
||||
} else {
|
||||
app.use(express.static('dist'))
|
||||
}
|
||||
|
||||
// Server-Sent Events (发送版本号来决定是否接收更新?)
|
||||
app.use((req, res, next) => {
|
||||
if (req.get('Accept') === 'text/event-stream') {
|
||||
@ -463,4 +470,13 @@ app.route('/api/session').get(online, session_list).post(session_create).delete(
|
||||
app.route('/api/session/:sid').delete(online, session_delete)
|
||||
app.route('/api/:name').get(object_list).post(object_create).put(db_compact)
|
||||
app.route('/api/:name/:_id').get(object_load).post(online, file_upload).put().patch(online, object_patch).delete(online, object_remove)
|
||||
|
||||
// 开发模式下使用 Vite
|
||||
if (process.argv.includes('--dev')) {
|
||||
const vite = await createServer({ server: { middlewareMode: 'html' } })
|
||||
app.use(vite.middlewares)
|
||||
} else {
|
||||
app.use(express.static('dist'))
|
||||
}
|
||||
|
||||
app.listen(2333)
|
||||
|
Loading…
Reference in New Issue
Block a user