feat: 首页版本号、简介布局与反显、密钥眼睛融合、定时拉取开关
This commit is contained in:
parent
c09857cc81
commit
64f3f6ea58
5
.codegraph/.gitignore
vendored
Normal file
5
.codegraph/.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
# CodeGraph data files — local to each machine, not for committing.
|
||||
# Ignore everything in .codegraph/ except this file itself, so transient
|
||||
# files (the database, daemon.pid, sockets, logs) never show up in git.
|
||||
*
|
||||
!.gitignore
|
||||
@ -13,7 +13,10 @@ jobs:
|
||||
|
||||
- name: Build Docker image
|
||||
run: |
|
||||
docker build -t awesome-index:latest .
|
||||
docker build \
|
||||
--build-arg GIT_BRANCH="${GITHUB_REF_NAME:-unknown}" \
|
||||
--build-arg BUILD_TIME="$(date +%Y%m%d%H%M%S)" \
|
||||
-t awesome-index:latest .
|
||||
|
||||
deploy:
|
||||
needs: build
|
||||
|
||||
@ -6,6 +6,10 @@ RUN npm ci --omit=dev --no-audit --no-fund
|
||||
FROM node:22-bookworm-slim
|
||||
WORKDIR /app
|
||||
ENV NODE_ENV=production
|
||||
ARG GIT_BRANCH=unknown
|
||||
ARG BUILD_TIME=unknown
|
||||
ENV GIT_BRANCH=$GIT_BRANCH
|
||||
ENV BUILD_TIME=$BUILD_TIME
|
||||
COPY --from=deps /app/node_modules ./node_modules
|
||||
COPY package.json ./
|
||||
COPY src ./src
|
||||
|
||||
@ -1676,32 +1676,44 @@ button.chip:hover {
|
||||
}
|
||||
.ai-key-field .input {
|
||||
width: 100%;
|
||||
padding-right: 42px;
|
||||
padding-right: 40px;
|
||||
}
|
||||
.pwd-field {
|
||||
position: relative;
|
||||
}
|
||||
.pwd-field .input {
|
||||
width: 100%;
|
||||
padding-right: 42px;
|
||||
padding-right: 40px;
|
||||
}
|
||||
.eye-toggle {
|
||||
position: absolute;
|
||||
right: 8px;
|
||||
right: 2px;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 4px;
|
||||
width: 34px;
|
||||
height: 100%;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
background: none;
|
||||
cursor: pointer;
|
||||
color: var(--ink-dim);
|
||||
border-radius: 0 8px 8px 0;
|
||||
}
|
||||
.eye-toggle:hover {
|
||||
color: var(--ink);
|
||||
}
|
||||
.eye-toggle .eye-closed {
|
||||
display: none;
|
||||
}
|
||||
.eye-toggle[data-show] .eye-open {
|
||||
display: none;
|
||||
}
|
||||
.eye-toggle[data-show] .eye-closed {
|
||||
display: inline;
|
||||
}
|
||||
.auth-row {
|
||||
margin-top: 14px;
|
||||
display: flex;
|
||||
|
||||
@ -127,10 +127,8 @@
|
||||
var show = input.type === "password";
|
||||
input.type = show ? "text" : "password";
|
||||
btn.setAttribute("aria-label", show ? "隐藏密码" : "显示密码");
|
||||
var open = btn.querySelector(".eye-open");
|
||||
var closed = btn.querySelector(".eye-closed");
|
||||
if (open) open.hidden = show;
|
||||
if (closed) closed.hidden = !show;
|
||||
if (show) btn.setAttribute("data-show", "");
|
||||
else btn.removeAttribute("data-show");
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@ -20,6 +20,8 @@ export const config = {
|
||||
aiIngestKey: str(env.AI_INGEST_KEY, ""),
|
||||
baseUrl: str(env.BASE_URL, `http://localhost:${num(env.PORT, 3000)}`),
|
||||
schedulerEnabled: env.SCHEDULER_DISABLED !== "1",
|
||||
gitBranch: str(env.GIT_BRANCH, "dev"),
|
||||
buildTime: str(env.BUILD_TIME, new Date().toISOString().replace(/[-T:]/g, "").slice(0, 14)),
|
||||
};
|
||||
|
||||
export function ensureDataDir() {
|
||||
|
||||
@ -32,6 +32,7 @@ export function registerTools(server) {
|
||||
stars: Number(e.stars),
|
||||
license: e.license,
|
||||
tags: e.tags,
|
||||
summary: e.summary,
|
||||
description: e.description_md,
|
||||
})),
|
||||
});
|
||||
|
||||
@ -44,7 +44,7 @@ const entryInput = z.object({
|
||||
title: z.string().min(1),
|
||||
url: z.string().url(),
|
||||
type: z.enum(entryService.ENTRY_TYPES),
|
||||
summary: z.string().max(1000).optional(),
|
||||
summary: z.string().max(200).optional(),
|
||||
description_md: z.string().max(5000).optional(),
|
||||
license: z.string().optional(),
|
||||
stars: z.number().nonnegative().optional(),
|
||||
@ -78,7 +78,7 @@ const patchInput = z.object({
|
||||
title: z.string().min(1).optional(),
|
||||
url: z.string().url().optional(),
|
||||
type: z.enum(entryService.ENTRY_TYPES).optional(),
|
||||
summary: z.string().max(1000).optional(),
|
||||
summary: z.string().max(200).optional(),
|
||||
description_md: z.string().max(5000).optional(),
|
||||
license: z.string().optional(),
|
||||
stars: z.number().nonnegative().optional(),
|
||||
|
||||
@ -15,12 +15,10 @@
|
||||
<form id="entry-edit-form" method="post" action="/admin/entries/<%= entry.id %>/edit" style="margin-top:22px;display:grid;gap:18px;max-width:820px">
|
||||
<div class="panel-box">
|
||||
<h3>基础信息</h3>
|
||||
<div class="field" style="margin-top:0"><label for="f-summary">简介(≤200 字,列表与详情页头部展示)</label>
|
||||
<input class="input" id="f-summary" name="summary" maxlength="200" value="<%= entry.summary || '' %>" /></div>
|
||||
<div class="form-row">
|
||||
<div class="field" style="flex:2"><label for="f-title">标题</label>
|
||||
<div class="field" style="flex:2;margin-top:0"><label for="f-title">标题</label>
|
||||
<input class="input" id="f-title" name="title" value="<%= entry.title %>" required /></div>
|
||||
<div class="field" style="flex:1"><label for="f-type">类型</label>
|
||||
<div class="field" style="flex:1;margin-top:0"><label for="f-type">类型</label>
|
||||
<select class="select" id="f-type" name="type" style="width:100%">
|
||||
<% for (const t of types) { %>
|
||||
<option value="<%= t %>" <%= entry.type === t ? 'selected' : '' %>><%= t %></option>
|
||||
@ -45,9 +43,14 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="panel-box">
|
||||
<h3>简介(≤200 字,列表与详情页头部展示)</h3>
|
||||
<textarea class="textarea" id="f-summary" name="summary" maxlength="200" rows="3" style="line-height:1.7;resize:vertical"><%= entry.summary || '' %></textarea>
|
||||
</div>
|
||||
|
||||
<div class="panel-box">
|
||||
<h3>内容描述(Markdown)</h3>
|
||||
<textarea class="textarea" id="f-desc" name="description_md" rows="16"><%= entry.description_md || '' %></textarea>
|
||||
<textarea class="textarea" id="f-desc" name="description_md" rows="16" style="line-height:1.7"><%= entry.description_md || '' %></textarea>
|
||||
<p style="font-size:12px;color:var(--ink-dim);margin-top:6px;font-family:var(--font-mono)">// 前台展示原文;保存后详情页与搜索都会生效</p>
|
||||
</div>
|
||||
|
||||
|
||||
@ -126,7 +126,7 @@
|
||||
<input class="input" name="key" type="password" value="<%= s.api_key || '' %>" placeholder="sk-…" autocomplete="off" />
|
||||
<button type="button" class="eye-toggle" data-eye-toggle aria-label="显示密钥">
|
||||
<svg class="eye-open" viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><circle cx="12" cy="12" r="3"/></svg>
|
||||
<svg class="eye-closed" viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" hidden><path d="M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19m-6.72-1.07a3 3 0 1 1-4.24-4.24"/><line x1="1" y1="1" x2="23" y2="23"/></svg>
|
||||
<svg class="eye-closed" viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19m-6.72-1.07a3 3 0 1 1-4.24-4.24"/><line x1="1" y1="1" x2="23" y2="23"/></svg>
|
||||
</button>
|
||||
</div>
|
||||
<button class="btn btn-sm" type="submit" style="flex:none">保存密钥</button>
|
||||
@ -139,7 +139,7 @@
|
||||
<form class="source-config" data-id="<%= s.id %>">
|
||||
<div class="switchline">
|
||||
启用定时拉取
|
||||
<input type="checkbox" name="enabled" <%= s.enabled ? 'checked' : '' %> style="accent-color:var(--riso-blue)" />
|
||||
<label class="toggle"><input type="checkbox" name="enabled" <%= s.enabled ? 'checked' : '' %> /><i></i></label>
|
||||
</div>
|
||||
<div style="display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-top:12px">
|
||||
<div>
|
||||
|
||||
@ -20,7 +20,7 @@
|
||||
<input class="input" id="login-pass" name="password" type="password" placeholder="••••••••" autocomplete="current-password" required />
|
||||
<button type="button" class="eye-toggle" data-eye-toggle aria-label="显示密码">
|
||||
<svg class="eye-open" viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><circle cx="12" cy="12" r="3"/></svg>
|
||||
<svg class="eye-closed" viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" hidden><path d="M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19m-6.72-1.07a3 3 0 1 1-4.24-4.24"/><line x1="1" y1="1" x2="23" y2="23"/></svg>
|
||||
<svg class="eye-closed" viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19m-6.72-1.07a3 3 0 1 1-4.24-4.24"/><line x1="1" y1="1" x2="23" y2="23"/></svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -37,7 +37,7 @@
|
||||
|
||||
<div class="footer-bar" style="border-top:1px solid rgba(233,235,228,.14)">
|
||||
<span>© 2026 honor3.com · Awesome Index</span>
|
||||
<span>由 DuckDB 驱动 · MCP 就绪 · 数据每日快照</span>
|
||||
<span>V <%= config.gitBranch %>-<%= config.buildTime %> · 由 DuckDB 驱动 · MCP 就绪 · 数据每日快照</span>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user