mirror of
https://github.com/JefferyHcool/BiliNote.git
synced 2026-06-18 14:11:12 +08:00
Compare commits
11 Commits
v2.3.3
...
release/2.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2e3fda7df4 | ||
|
|
2ea95b2fad | ||
|
|
9d1a7cd699 | ||
|
|
f2d8ece0c1 | ||
|
|
7bc4b0114e | ||
|
|
f7ea6f72d9 | ||
|
|
905dbcce47 | ||
|
|
ebdb254fc6 | ||
|
|
1eb213e215 | ||
|
|
4425239717 | ||
|
|
717df2af7b |
12
.github/workflows/docker-build.yml
vendored
12
.github/workflows/docker-build.yml
vendored
@@ -42,6 +42,16 @@ jobs:
|
||||
type=sha,prefix=
|
||||
type=raw,value=latest,enable={{is_default_branch}}
|
||||
|
||||
- name: Resolve app version
|
||||
id: app-version
|
||||
shell: bash
|
||||
run: |
|
||||
if [[ "$GITHUB_REF" == refs/tags/v* ]]; then
|
||||
echo "version=${GITHUB_REF_NAME#v}" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
echo "version=" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
|
||||
- name: Build and Push Docker Image
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
@@ -50,6 +60,8 @@ jobs:
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
build-args: |
|
||||
VITE_APP_VERSION=${{ steps.app-version.outputs.version }}
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
platforms: linux/amd64,linux/arm64
|
||||
|
||||
@@ -56,7 +56,7 @@ async function upsertTask(record: TaskRecord) {
|
||||
|
||||
// ---------- 启动任务 ----------
|
||||
|
||||
async function startTask(url: string): Promise<{ ok: boolean, taskId?: string, error?: string }> {
|
||||
async function startTask(url: string, title?: string): Promise<{ ok: boolean, taskId?: string, error?: string }> {
|
||||
const platform = detectPlatform(url)
|
||||
if (!platform)
|
||||
return { ok: false, error: '当前链接不是支持的视频平台' }
|
||||
@@ -107,6 +107,7 @@ async function startTask(url: string): Promise<{ ok: boolean, taskId?: string, e
|
||||
message: '已提交',
|
||||
createdAt: Date.now(),
|
||||
updatedAt: Date.now(),
|
||||
title,
|
||||
})
|
||||
return { ok: true, taskId: body.data.task_id }
|
||||
}
|
||||
@@ -129,8 +130,8 @@ async function openSidePanelInTab(tabId?: number) {
|
||||
|
||||
// ---------- 消息桥 ----------
|
||||
|
||||
onMessage<{ url: string }, 'bilinote-start'>('bilinote-start', async ({ data, sender }) => {
|
||||
const result = await startTask(data.url)
|
||||
onMessage<{ url: string; title?: string }, 'bilinote-start'>('bilinote-start', async ({ data, sender }) => {
|
||||
const result = await startTask(data.url, data.title)
|
||||
// 成功就把侧边栏拉起来给用户看进度
|
||||
if (result.ok)
|
||||
await openSidePanelInTab(sender?.tabId)
|
||||
@@ -168,7 +169,7 @@ browser.contextMenus?.onClicked.addListener(async (info, tab) => {
|
||||
const url = info.linkUrl || tab?.url
|
||||
if (!url)
|
||||
return
|
||||
const result = await startTask(url)
|
||||
const result = await startTask(url, tab?.title)
|
||||
if (result.ok)
|
||||
await openSidePanelInTab(tab?.id)
|
||||
else
|
||||
|
||||
@@ -19,6 +19,7 @@ async function trigger() {
|
||||
const res = await sendMessage('bilinote-start', {
|
||||
url: window.location.href,
|
||||
platform,
|
||||
title: document.title,
|
||||
}, 'background')
|
||||
const ok = res && (res as any).ok
|
||||
toast.value = ok
|
||||
|
||||
@@ -79,6 +79,8 @@ export interface TaskRecord {
|
||||
createdAt: number
|
||||
updatedAt: number
|
||||
result?: NoteResult
|
||||
// 从浏览器 tab.title 抓取,任务完成前用来替代 videoUrl 显示
|
||||
title?: string
|
||||
}
|
||||
|
||||
// 与 backend/app/gpt/prompt_builder.py note_styles 一一对齐
|
||||
|
||||
@@ -43,6 +43,7 @@ async function poll(taskId: string) {
|
||||
createdAt: activeTask.value?.createdAt ?? Date.now(),
|
||||
updatedAt: Date.now(),
|
||||
result: res.result ?? activeTask.value?.result,
|
||||
title: activeTask.value?.title,
|
||||
})
|
||||
if (res.status !== 'SUCCESS' && res.status !== 'FAILED')
|
||||
pollTimer = setTimeout(() => poll(taskId), 3000)
|
||||
@@ -94,6 +95,7 @@ async function start() {
|
||||
message: '已提交',
|
||||
createdAt: Date.now(),
|
||||
updatedAt: Date.now(),
|
||||
title: tabTitle.value || undefined,
|
||||
})
|
||||
poll(task_id)
|
||||
// 提交后顺手把侧边栏拉起来,免得用户来回切窗口
|
||||
@@ -142,7 +144,10 @@ function selectTask(id: string) {
|
||||
}
|
||||
|
||||
const activeCover = computed(() => activeTask.value?.result?.audio_meta?.cover_url as string | undefined)
|
||||
const activeTitle = computed(() => (activeTask.value?.result?.audio_meta?.title as string | undefined) || tabTitle.value)
|
||||
const activeTitle = computed(() =>
|
||||
(activeTask.value?.result?.audio_meta?.title as string | undefined)
|
||||
|| activeTask.value?.title
|
||||
|| tabTitle.value)
|
||||
|
||||
function fmtTime(ts?: number) {
|
||||
if (!ts)
|
||||
@@ -331,8 +336,8 @@ onUnmounted(() => {
|
||||
:class="{ 'bg-blue-50': t.taskId === activeTaskId }"
|
||||
@click="selectTask(t.taskId)"
|
||||
>
|
||||
<span class="truncate flex-1" :title="t.videoUrl">
|
||||
{{ (t.result?.audio_meta as { title?: string } | undefined)?.title || t.videoUrl }}
|
||||
<span class="truncate flex-1" :title="t.title || t.videoUrl">
|
||||
{{ (t.result?.audio_meta as { title?: string } | undefined)?.title || t.title || t.videoUrl }}
|
||||
</span>
|
||||
<span class="text-gray-500 shrink-0">{{ t.status }}</span>
|
||||
</li>
|
||||
|
||||
@@ -41,6 +41,7 @@ async function poll(taskId: string) {
|
||||
message: res.message,
|
||||
result: res.result ?? cur.result,
|
||||
updatedAt: Date.now(),
|
||||
title: cur.title,
|
||||
})
|
||||
}
|
||||
if (res.status !== 'SUCCESS' && res.status !== 'FAILED')
|
||||
@@ -89,7 +90,10 @@ function downloadMarkdown() {
|
||||
}
|
||||
|
||||
const activeTitle = computed(() =>
|
||||
(activeTask.value?.result?.audio_meta as { title?: string } | undefined)?.title || activeTask.value?.videoUrl || '')
|
||||
(activeTask.value?.result?.audio_meta as { title?: string } | undefined)?.title
|
||||
|| activeTask.value?.title
|
||||
|| activeTask.value?.videoUrl
|
||||
|| '')
|
||||
|
||||
const activeCover = computed(() =>
|
||||
(activeTask.value?.result?.audio_meta as { cover_url?: string } | undefined)?.cover_url)
|
||||
@@ -140,8 +144,8 @@ onUnmounted(() => {
|
||||
:class="{ 'bg-white border': t.taskId === activeTaskId }"
|
||||
@click="selectTask(t.taskId)"
|
||||
>
|
||||
<span class="truncate flex-1" :title="t.videoUrl">
|
||||
{{ (t.result?.audio_meta as { title?: string } | undefined)?.title || t.videoUrl }}
|
||||
<span class="truncate flex-1" :title="t.title || t.videoUrl">
|
||||
{{ (t.result?.audio_meta as { title?: string } | undefined)?.title || t.title || t.videoUrl }}
|
||||
</span>
|
||||
<span class="text-gray-400 shrink-0">{{ STAGE_LABELS[t.status] || t.status }}</span>
|
||||
</li>
|
||||
@@ -170,7 +174,7 @@ onUnmounted(() => {
|
||||
class="text-sm font-medium leading-tight line-clamp-1 break-all flex-1 min-w-0 hover:text-blue-600"
|
||||
:href="activeTask.videoUrl"
|
||||
target="_blank"
|
||||
:title="activeTask.videoUrl"
|
||||
:title="activeTitle || activeTask.videoUrl"
|
||||
>{{ activeTitle }}</a>
|
||||
<span
|
||||
v-if="isDone"
|
||||
|
||||
@@ -5,6 +5,10 @@
|
||||
ARG BASE_REGISTRY=docker.io
|
||||
FROM ${BASE_REGISTRY}/library/node:20-alpine AS builder
|
||||
|
||||
# 可由发布 workflow 从 git tag 注入,用于前端 About 页展示版本;未传时由 Vite 回退读取 tauri.conf.json。
|
||||
ARG VITE_APP_VERSION=
|
||||
ENV VITE_APP_VERSION=${VITE_APP_VERSION}
|
||||
|
||||
# pnpm pin 到 9.x:lockfile 是 v9 生成;pnpm 11 要求 Node 22+ 与 node:20 不兼容
|
||||
RUN corepack enable && corepack prepare pnpm@9.15.0 --activate
|
||||
|
||||
|
||||
@@ -57,6 +57,7 @@
|
||||
"react-router-dom": "^7.5.1",
|
||||
"react-syntax-highlighter": "^15.6.1",
|
||||
"rehype-katex": "^6.0.2",
|
||||
"rehype-slug": "5.1.0",
|
||||
"remark-gfm": "3.0.1",
|
||||
"remark-math": "^5.1.1",
|
||||
"sonner": "^2.0.3",
|
||||
|
||||
168
BillNote_frontend/pnpm-lock.yaml
generated
168
BillNote_frontend/pnpm-lock.yaml
generated
@@ -13,7 +13,7 @@ importers:
|
||||
version: 2.4.0(antd@5.29.3(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
|
||||
'@hookform/resolvers':
|
||||
specifier: ^5.0.1
|
||||
version: 5.2.2(react-hook-form@7.72.0(react@19.2.4))
|
||||
version: 5.4.0(react-hook-form@7.72.0(react@19.2.4))
|
||||
'@lobehub/icons':
|
||||
specifier: ^1.97.1
|
||||
version: 1.98.0(@babel/core@7.29.0)(@types/mdast@4.0.4)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(antd@5.29.3(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(framer-motion@12.38.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(micromark-util-types@2.0.2)(micromark@4.0.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
|
||||
@@ -52,7 +52,7 @@ importers:
|
||||
version: 1.2.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
|
||||
'@tailwindcss/vite':
|
||||
specifier: ^4.1.3
|
||||
version: 4.2.2(vite@6.4.1(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.32.0)(yaml@2.8.3))
|
||||
version: 4.2.2(vite@6.4.2(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.32.0)(yaml@2.8.3))
|
||||
'@tauri-apps/api':
|
||||
specifier: ^2.11.0
|
||||
version: 2.11.0
|
||||
@@ -61,7 +61,7 @@ importers:
|
||||
version: 2.3.5
|
||||
'@uiw/react-markdown-preview':
|
||||
specifier: ^5.1.3
|
||||
version: 5.1.5(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
|
||||
version: 5.2.1(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
|
||||
antd:
|
||||
specifier: ^5.24.8
|
||||
version: 5.29.3(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
|
||||
@@ -76,13 +76,13 @@ importers:
|
||||
version: 2.1.1
|
||||
fuse.js:
|
||||
specifier: ^7.1.0
|
||||
version: 7.1.0
|
||||
version: 7.3.0
|
||||
github-markdown-css:
|
||||
specifier: ^5.8.1
|
||||
version: 5.9.0
|
||||
idb-keyval:
|
||||
specifier: ^6.2.2
|
||||
version: 6.2.2
|
||||
version: 6.2.4
|
||||
jszip:
|
||||
specifier: ^3.10.1
|
||||
version: 3.10.1
|
||||
@@ -149,6 +149,9 @@ importers:
|
||||
rehype-katex:
|
||||
specifier: ^6.0.2
|
||||
version: 6.0.3
|
||||
rehype-slug:
|
||||
specifier: 5.1.0
|
||||
version: 5.1.0
|
||||
remark-gfm:
|
||||
specifier: 3.0.1
|
||||
version: 3.0.1
|
||||
@@ -169,7 +172,7 @@ importers:
|
||||
version: 1.4.0
|
||||
uuid:
|
||||
specifier: ^11.1.0
|
||||
version: 11.1.0
|
||||
version: 11.1.1
|
||||
zod:
|
||||
specifier: ^3.24.2
|
||||
version: 3.25.76
|
||||
@@ -197,7 +200,7 @@ importers:
|
||||
version: 19.2.3(@types/react@19.2.14)
|
||||
'@vitejs/plugin-react':
|
||||
specifier: ^4.3.4
|
||||
version: 4.7.0(vite@6.4.1(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.32.0)(yaml@2.8.3))
|
||||
version: 4.7.0(vite@6.4.2(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.32.0)(yaml@2.8.3))
|
||||
autoprefixer:
|
||||
specifier: ^10.4.21
|
||||
version: 10.4.27(postcss@8.5.8)
|
||||
@@ -227,7 +230,7 @@ importers:
|
||||
version: 8.57.1(eslint@9.39.4(jiti@2.6.1))(typescript@5.7.3)
|
||||
vite:
|
||||
specifier: ^6.2.0
|
||||
version: 6.4.1(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.32.0)(yaml@2.8.3)
|
||||
version: 6.4.2(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.32.0)(yaml@2.8.3)
|
||||
|
||||
packages:
|
||||
|
||||
@@ -732,8 +735,8 @@ packages:
|
||||
react: ^16 || ^17 || ^18 || ^19
|
||||
react-dom: ^16 || ^17 || ^18 || ^19
|
||||
|
||||
'@hookform/resolvers@5.2.2':
|
||||
resolution: {integrity: sha512-A/IxlMLShx3KjV/HeTcTfaMxdwy690+L/ZADoeaTltLx+CVuzkeVIPuybK3jrRfw7YZnmdKsVVHAlEPIAEUNlA==}
|
||||
'@hookform/resolvers@5.4.0':
|
||||
resolution: {integrity: sha512-EIsqr/t/qbinPIhGjMdtvutIN1Kk4uwbROE9/UQ93CAVGR7GkA7Y92+fX80OzXi/OB67jVFYwKGO1WzkxmkFZw==}
|
||||
peerDependencies:
|
||||
react-hook-form: ^7.55.0
|
||||
|
||||
@@ -1786,6 +1789,9 @@ packages:
|
||||
'@types/estree@1.0.8':
|
||||
resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==}
|
||||
|
||||
'@types/estree@1.0.9':
|
||||
resolution: {integrity: sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==}
|
||||
|
||||
'@types/geojson@7946.0.16':
|
||||
resolution: {integrity: sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg==}
|
||||
|
||||
@@ -1910,8 +1916,8 @@ packages:
|
||||
'@uiw/copy-to-clipboard@1.0.20':
|
||||
resolution: {integrity: sha512-IFQhS62CLNon1YgYJTEzXR2N3WVXg7V1FaBRDLMlzU6JY5X6Hr3OPAcw4WNoKcz2XcFD6XCgwEjlsmj+JA0mWA==}
|
||||
|
||||
'@uiw/react-markdown-preview@5.1.5':
|
||||
resolution: {integrity: sha512-DNOqx1a6gJR7Btt57zpGEKTfHRlb7rWbtctMRO2f82wWcuoJsxPBrM+JWebDdOD0LfD8oe2CQvW2ICQJKHQhZg==}
|
||||
'@uiw/react-markdown-preview@5.2.1':
|
||||
resolution: {integrity: sha512-JjvcHveT6glhlJYJx1XGBZij6wkw+VwREV6Z6m/GpsjPPdLjF1x8nlPBSB/ATyUF4lD7C8ttMkCqVH9N9XMgEA==}
|
||||
peerDependencies:
|
||||
react: '>=16.8.0'
|
||||
react-dom: '>=16.8.0'
|
||||
@@ -1919,6 +1925,9 @@ packages:
|
||||
'@ungap/structured-clone@1.3.0':
|
||||
resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==}
|
||||
|
||||
'@ungap/structured-clone@1.3.1':
|
||||
resolution: {integrity: sha512-mUFwbeTqrVgDQxFveS+df2yfap6iuP20NAKAsBt5jDEoOTDew+zwLAOilHCeQJOVSvmgCX4ogqIrA0mnyr08yQ==}
|
||||
|
||||
'@upsetjs/venn.js@2.0.0':
|
||||
resolution: {integrity: sha512-WbBhLrooyePuQ1VZxrJjtLvTc4NVfpOyKx0sKqioq9bX1C1m7Jgykkn8gLrtwumBioXIqam8DLxp88Adbue6Hw==}
|
||||
|
||||
@@ -2689,8 +2698,8 @@ packages:
|
||||
function-bind@1.1.2:
|
||||
resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==}
|
||||
|
||||
fuse.js@7.1.0:
|
||||
resolution: {integrity: sha512-trLf4SzuuUxfusZADLINj+dE8clK1frKdmqiJNb1Es75fmI5oY6X2mxLVUciLLjxqw/xr72Dhy+lER6dGd02FQ==}
|
||||
fuse.js@7.3.0:
|
||||
resolution: {integrity: sha512-plz8RVjfcDedTGfVngWH1jmJvBvAwi1v2jecfDerbEnMcmOYUEEwKFTHbNoCiYyzaK2Ws8lABkTCcRSqCY1q4w==}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
gensync@1.0.0-beta.2:
|
||||
@@ -2794,9 +2803,15 @@ packages:
|
||||
hast-util-from-parse5@8.0.3:
|
||||
resolution: {integrity: sha512-3kxEVkEKt0zvcZ3hCRYI8rqrgwtlIOFMWkbclACvjlDw8Li9S2hk/d51OI0nr/gIpdMHNepwgOKqZ/sy0Clpyg==}
|
||||
|
||||
hast-util-has-property@2.0.1:
|
||||
resolution: {integrity: sha512-X2+RwZIMTMKpXUzlotatPzWj8bspCymtXH3cfG3iQKV+wPF53Vgaqxi/eLqGck0wKq1kS9nvoB1wchbCPEL8sg==}
|
||||
|
||||
hast-util-has-property@3.0.0:
|
||||
resolution: {integrity: sha512-MNilsvEKLFpV604hwfhVStK0usFY/QmM5zX16bo7EjnAEGofr5YyI37kzopBlZJkHD4t887i+q/C8/tr5Q94cA==}
|
||||
|
||||
hast-util-heading-rank@2.1.1:
|
||||
resolution: {integrity: sha512-iAuRp+ESgJoRFJbSyaqsfvJDY6zzmFoEnL1gtz1+U8gKtGGj1p0CVlysuUAUjq95qlZESHINLThwJzNGmgGZxA==}
|
||||
|
||||
hast-util-heading-rank@3.0.0:
|
||||
resolution: {integrity: sha512-EJKb8oMUXVHcWZTDepnr+WNbfnXKFNf9duMesmr4S8SXTJBJ9M4Yok08pu9vxdJwdlGRhVumk9mEhkEvKGifwA==}
|
||||
|
||||
@@ -2833,6 +2848,9 @@ packages:
|
||||
hast-util-to-parse5@8.0.1:
|
||||
resolution: {integrity: sha512-MlWT6Pjt4CG9lFCjiz4BH7l9wmrMkfkJYCxFwKQic8+RTZgWPuWxwAfjJElsXkex7DJjfSJsQIt931ilUgmwdA==}
|
||||
|
||||
hast-util-to-string@2.0.0:
|
||||
resolution: {integrity: sha512-02AQ3vLhuH3FisaMM+i/9sm4OXGSq1UhOOCpTLLQtHdL3tZt7qil69r8M8iDkZYyC0HCFylcYoP+8IO7ddta1A==}
|
||||
|
||||
hast-util-to-string@3.0.1:
|
||||
resolution: {integrity: sha512-XelQVTDWvqcl3axRfI0xSeoVKzyIFPwsAGSLIsKdJKQMXDYJS4WYrBNF/8J7RdhIcFI2BOHgAifggsvsxp/3+A==}
|
||||
|
||||
@@ -2883,8 +2901,8 @@ packages:
|
||||
resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
idb-keyval@6.2.2:
|
||||
resolution: {integrity: sha512-yjD9nARJ/jb1g+CvD0tlhUHOrJ9Sy0P8T9MF3YaLlHnSRpwPfpTX0XIvpmw3gAJUmEu3FiICLBDPXVwyEvrleg==}
|
||||
idb-keyval@6.2.4:
|
||||
resolution: {integrity: sha512-D/NzHWUmYJGXi++z67aMSrnisb9A3621CyRK5G89JyTlN13C8xf0g04DLxUKMufPem3e3L2JAXR6Z00OWy183Q==}
|
||||
|
||||
ignore@5.3.2:
|
||||
resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==}
|
||||
@@ -4228,12 +4246,6 @@ packages:
|
||||
'@types/react': '>=16'
|
||||
react: '>=16'
|
||||
|
||||
react-markdown@9.0.3:
|
||||
resolution: {integrity: sha512-Yk7Z94dbgYTOrdk41Z74GoKA7rThnsbbqBTRYuxoe08qvfQ9tJVhmAKw6BJS/ZORG7kTy/s1QvYzSuaoBA1qfw==}
|
||||
peerDependencies:
|
||||
'@types/react': '>=18'
|
||||
react: '>=18'
|
||||
|
||||
react-medium-image-zoom@5.4.1:
|
||||
resolution: {integrity: sha512-DD2iZYaCfAwiQGR8AN62r/cDJYoXhezlYJc5HY4TzBUGuGge43CptG0f7m0PEIM72aN6GfpjohvY1yYdtCJB7g==}
|
||||
peerDependencies:
|
||||
@@ -4372,8 +4384,8 @@ packages:
|
||||
regex@6.1.0:
|
||||
resolution: {integrity: sha512-6VwtthbV4o/7+OaAF9I5L5V3llLEsoPyq9P1JVXkedTP33c7MfCG0/5NOPcSJn0TzXcG9YUrR0gQSWioew3LDg==}
|
||||
|
||||
rehype-attr@3.0.3:
|
||||
resolution: {integrity: sha512-Up50Xfra8tyxnkJdCzLBIBtxOcB2M1xdeKe1324U06RAvSjYm7ULSeoM+b/nYPQPVd7jsXJ9+39IG1WAJPXONw==}
|
||||
rehype-attr@4.0.0:
|
||||
resolution: {integrity: sha512-tANn9EmhG4mEZlNdDDRKuS0OXPDvc6P6OjJ1yApzOjIdCvKNLiuU2HdMSLTpiVi3D/FyLK6B+ZZ8PYtRxiGg7Q==}
|
||||
engines: {node: '>=16'}
|
||||
|
||||
rehype-autolink-headings@7.1.0:
|
||||
@@ -4408,6 +4420,9 @@ packages:
|
||||
resolution: {integrity: sha512-L/FO96EOzSA6bzOam4DVu61/PB3AGKcSPXpa53yMIozoxH4qg1+bVZDF8zh1EsuxtSauAhzt5cCnvoplAaSLrw==}
|
||||
engines: {node: '>=16.0.0'}
|
||||
|
||||
rehype-slug@5.1.0:
|
||||
resolution: {integrity: sha512-Gf91dJoXneiorNEnn+Phx97CO7oRMrpi+6r155tTxzGuLtm+QrI4cTwCa9e1rtePdL4i9tSO58PeSS6HWfgsiw==}
|
||||
|
||||
rehype-slug@6.0.0:
|
||||
resolution: {integrity: sha512-lWyvf/jwu+oS5+hL5eClVd3hNdmwM1kAC0BUvEGD19pajQMIzcNUd/k9GsfQ+FfECvX+JE+e9/btsKH0EjJT6A==}
|
||||
|
||||
@@ -4822,12 +4837,12 @@ packages:
|
||||
util-deprecate@1.0.2:
|
||||
resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
|
||||
|
||||
uuid@11.1.0:
|
||||
resolution: {integrity: sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==}
|
||||
uuid@11.1.1:
|
||||
resolution: {integrity: sha512-vIYxrBCC/N/K+Js3qSN88go7kIfNPssr/hHCesKCQNAjmgvYS2oqr69kIufEG+O4+PfezOH4EbIeHCfFov8ZgQ==}
|
||||
hasBin: true
|
||||
|
||||
uuid@13.0.0:
|
||||
resolution: {integrity: sha512-XQegIaBTVUjSHliKqcnFqYypAd4S+WCYt5NIeRs6w/UAry7z8Y9j5ZwRRL4kzq9U3sD6v+85er9FvkEaBpji2w==}
|
||||
uuid@13.0.2:
|
||||
resolution: {integrity: sha512-vzi9uRZ926x4XV73S/4qQaTwPXM2JBj6/6lI/byHH1jOpCzb0zDbfytgA9LcN/hzb2l7WQSQnxITOVx5un/wGw==}
|
||||
hasBin: true
|
||||
|
||||
uvu@0.5.6:
|
||||
@@ -4856,8 +4871,8 @@ packages:
|
||||
vfile@6.0.3:
|
||||
resolution: {integrity: sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==}
|
||||
|
||||
vite@6.4.1:
|
||||
resolution: {integrity: sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==}
|
||||
vite@6.4.2:
|
||||
resolution: {integrity: sha512-2N/55r4JDJ4gdrCvGgINMy+HH3iRpNIz8K6SFwVsA+JbQScLiC+clmAxBgwiSPgcG9U15QmvqCGWzMbqda5zGQ==}
|
||||
engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0}
|
||||
hasBin: true
|
||||
peerDependencies:
|
||||
@@ -5534,7 +5549,7 @@ snapshots:
|
||||
react: 19.2.4
|
||||
react-dom: 19.2.4(react@19.2.4)
|
||||
|
||||
'@hookform/resolvers@5.2.2(react-hook-form@7.72.0(react@19.2.4))':
|
||||
'@hookform/resolvers@5.4.0(react-hook-form@7.72.0(react@19.2.4))':
|
||||
dependencies:
|
||||
'@standard-schema/utils': 0.3.0
|
||||
react-hook-form: 7.72.0(react@19.2.4)
|
||||
@@ -5725,7 +5740,7 @@ snapshots:
|
||||
unified: 11.0.5
|
||||
url-join: 5.0.0
|
||||
use-merge-value: 1.2.0(react@19.2.4)
|
||||
uuid: 13.0.0
|
||||
uuid: 13.0.2
|
||||
transitivePeerDependencies:
|
||||
- '@babel/core'
|
||||
- '@types/mdast'
|
||||
@@ -6456,12 +6471,12 @@ snapshots:
|
||||
postcss: 8.5.8
|
||||
tailwindcss: 4.2.2
|
||||
|
||||
'@tailwindcss/vite@4.2.2(vite@6.4.1(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.32.0)(yaml@2.8.3))':
|
||||
'@tailwindcss/vite@4.2.2(vite@6.4.2(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.32.0)(yaml@2.8.3))':
|
||||
dependencies:
|
||||
'@tailwindcss/node': 4.2.2
|
||||
'@tailwindcss/oxide': 4.2.2
|
||||
tailwindcss: 4.2.2
|
||||
vite: 6.4.1(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.32.0)(yaml@2.8.3)
|
||||
vite: 6.4.2(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.32.0)(yaml@2.8.3)
|
||||
|
||||
'@tauri-apps/api@2.11.0': {}
|
||||
|
||||
@@ -6664,6 +6679,8 @@ snapshots:
|
||||
|
||||
'@types/estree@1.0.8': {}
|
||||
|
||||
'@types/estree@1.0.9': {}
|
||||
|
||||
'@types/geojson@7946.0.16': {}
|
||||
|
||||
'@types/hast@2.3.10':
|
||||
@@ -6811,14 +6828,14 @@ snapshots:
|
||||
|
||||
'@uiw/copy-to-clipboard@1.0.20': {}
|
||||
|
||||
'@uiw/react-markdown-preview@5.1.5(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)':
|
||||
'@uiw/react-markdown-preview@5.2.1(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)':
|
||||
dependencies:
|
||||
'@babel/runtime': 7.29.2
|
||||
'@uiw/copy-to-clipboard': 1.0.20
|
||||
react: 19.2.4
|
||||
react-dom: 19.2.4(react@19.2.4)
|
||||
react-markdown: 9.0.3(@types/react@19.2.14)(react@19.2.4)
|
||||
rehype-attr: 3.0.3
|
||||
react-markdown: 10.1.0(@types/react@19.2.14)(react@19.2.4)
|
||||
rehype-attr: 4.0.0
|
||||
rehype-autolink-headings: 7.1.0
|
||||
rehype-ignore: 2.0.3
|
||||
rehype-prism-plus: 2.0.0
|
||||
@@ -6834,6 +6851,8 @@ snapshots:
|
||||
|
||||
'@ungap/structured-clone@1.3.0': {}
|
||||
|
||||
'@ungap/structured-clone@1.3.1': {}
|
||||
|
||||
'@upsetjs/venn.js@2.0.0':
|
||||
optionalDependencies:
|
||||
d3-selection: 3.0.0
|
||||
@@ -6846,7 +6865,7 @@ snapshots:
|
||||
'@use-gesture/core': 10.3.1
|
||||
react: 19.2.4
|
||||
|
||||
'@vitejs/plugin-react@4.7.0(vite@6.4.1(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.32.0)(yaml@2.8.3))':
|
||||
'@vitejs/plugin-react@4.7.0(vite@6.4.2(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.32.0)(yaml@2.8.3))':
|
||||
dependencies:
|
||||
'@babel/core': 7.29.0
|
||||
'@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.29.0)
|
||||
@@ -6854,7 +6873,7 @@ snapshots:
|
||||
'@rolldown/pluginutils': 1.0.0-beta.27
|
||||
'@types/babel__core': 7.20.5
|
||||
react-refresh: 0.17.0
|
||||
vite: 6.4.1(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.32.0)(yaml@2.8.3)
|
||||
vite: 6.4.2(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.32.0)(yaml@2.8.3)
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
@@ -7630,7 +7649,7 @@ snapshots:
|
||||
|
||||
estree-util-attach-comments@3.0.0:
|
||||
dependencies:
|
||||
'@types/estree': 1.0.8
|
||||
'@types/estree': 1.0.9
|
||||
|
||||
estree-util-build-jsx@3.0.1:
|
||||
dependencies:
|
||||
@@ -7742,7 +7761,7 @@ snapshots:
|
||||
|
||||
function-bind@1.1.2: {}
|
||||
|
||||
fuse.js@7.1.0: {}
|
||||
fuse.js@7.3.0: {}
|
||||
|
||||
gensync@1.0.0-beta.2: {}
|
||||
|
||||
@@ -7871,10 +7890,16 @@ snapshots:
|
||||
vfile-location: 5.0.3
|
||||
web-namespaces: 2.0.1
|
||||
|
||||
hast-util-has-property@2.0.1: {}
|
||||
|
||||
hast-util-has-property@3.0.0:
|
||||
dependencies:
|
||||
'@types/hast': 3.0.4
|
||||
|
||||
hast-util-heading-rank@2.1.1:
|
||||
dependencies:
|
||||
'@types/hast': 2.3.10
|
||||
|
||||
hast-util-heading-rank@3.0.0:
|
||||
dependencies:
|
||||
'@types/hast': 3.0.4
|
||||
@@ -7934,7 +7959,7 @@ snapshots:
|
||||
|
||||
hast-util-to-estree@3.1.3:
|
||||
dependencies:
|
||||
'@types/estree': 1.0.8
|
||||
'@types/estree': 1.0.9
|
||||
'@types/estree-jsx': 1.0.5
|
||||
'@types/hast': 3.0.4
|
||||
comma-separated-tokens: 2.0.3
|
||||
@@ -7969,7 +7994,7 @@ snapshots:
|
||||
|
||||
hast-util-to-jsx-runtime@2.3.6:
|
||||
dependencies:
|
||||
'@types/estree': 1.0.8
|
||||
'@types/estree': 1.0.9
|
||||
'@types/hast': 3.0.4
|
||||
'@types/unist': 3.0.3
|
||||
comma-separated-tokens: 2.0.3
|
||||
@@ -7997,6 +8022,10 @@ snapshots:
|
||||
web-namespaces: 2.0.1
|
||||
zwitch: 2.0.4
|
||||
|
||||
hast-util-to-string@2.0.0:
|
||||
dependencies:
|
||||
'@types/hast': 2.3.10
|
||||
|
||||
hast-util-to-string@3.0.1:
|
||||
dependencies:
|
||||
'@types/hast': 3.0.4
|
||||
@@ -8070,7 +8099,7 @@ snapshots:
|
||||
dependencies:
|
||||
safer-buffer: 2.1.2
|
||||
|
||||
idb-keyval@6.2.2: {}
|
||||
idb-keyval@6.2.4: {}
|
||||
|
||||
ignore@5.3.2: {}
|
||||
|
||||
@@ -8690,7 +8719,7 @@ snapshots:
|
||||
dependencies:
|
||||
'@types/hast': 3.0.4
|
||||
'@types/mdast': 4.0.4
|
||||
'@ungap/structured-clone': 1.3.0
|
||||
'@ungap/structured-clone': 1.3.1
|
||||
devlop: 1.1.0
|
||||
micromark-util-sanitize-uri: 2.0.1
|
||||
trim-lines: 3.0.1
|
||||
@@ -8760,7 +8789,7 @@ snapshots:
|
||||
roughjs: 4.6.6
|
||||
stylis: 4.3.6
|
||||
ts-dedent: 2.2.0
|
||||
uuid: 11.1.0
|
||||
uuid: 11.1.1
|
||||
|
||||
micromark-core-commonmark@1.1.0:
|
||||
dependencies:
|
||||
@@ -8957,7 +8986,7 @@ snapshots:
|
||||
|
||||
micromark-extension-mdx-expression@3.0.1:
|
||||
dependencies:
|
||||
'@types/estree': 1.0.8
|
||||
'@types/estree': 1.0.9
|
||||
devlop: 1.1.0
|
||||
micromark-factory-mdx-expression: 2.0.3
|
||||
micromark-factory-space: 2.0.1
|
||||
@@ -8968,7 +8997,7 @@ snapshots:
|
||||
|
||||
micromark-extension-mdx-jsx@3.0.2:
|
||||
dependencies:
|
||||
'@types/estree': 1.0.8
|
||||
'@types/estree': 1.0.9
|
||||
devlop: 1.1.0
|
||||
estree-util-is-identifier-name: 3.0.0
|
||||
micromark-factory-mdx-expression: 2.0.3
|
||||
@@ -8985,7 +9014,7 @@ snapshots:
|
||||
|
||||
micromark-extension-mdxjs-esm@3.0.0:
|
||||
dependencies:
|
||||
'@types/estree': 1.0.8
|
||||
'@types/estree': 1.0.9
|
||||
devlop: 1.1.0
|
||||
micromark-core-commonmark: 2.0.3
|
||||
micromark-util-character: 2.1.1
|
||||
@@ -9034,7 +9063,7 @@ snapshots:
|
||||
|
||||
micromark-factory-mdx-expression@2.0.3:
|
||||
dependencies:
|
||||
'@types/estree': 1.0.8
|
||||
'@types/estree': 1.0.9
|
||||
devlop: 1.1.0
|
||||
micromark-factory-space: 2.0.1
|
||||
micromark-util-character: 2.1.1
|
||||
@@ -9150,7 +9179,7 @@ snapshots:
|
||||
|
||||
micromark-util-events-to-acorn@2.0.3:
|
||||
dependencies:
|
||||
'@types/estree': 1.0.8
|
||||
'@types/estree': 1.0.9
|
||||
'@types/unist': 3.0.3
|
||||
devlop: 1.1.0
|
||||
estree-util-visit: 2.0.0
|
||||
@@ -9936,23 +9965,6 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
react-markdown@9.0.3(@types/react@19.2.14)(react@19.2.4):
|
||||
dependencies:
|
||||
'@types/hast': 3.0.4
|
||||
'@types/react': 19.2.14
|
||||
devlop: 1.1.0
|
||||
hast-util-to-jsx-runtime: 2.3.6
|
||||
html-url-attributes: 3.0.1
|
||||
mdast-util-to-hast: 13.2.1
|
||||
react: 19.2.4
|
||||
remark-parse: 11.0.0
|
||||
remark-rehype: 11.1.2
|
||||
unified: 11.0.5
|
||||
unist-util-visit: 5.1.0
|
||||
vfile: 6.0.3
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
react-medium-image-zoom@5.4.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4):
|
||||
dependencies:
|
||||
react: 19.2.4
|
||||
@@ -10078,7 +10090,7 @@ snapshots:
|
||||
|
||||
recma-parse@1.0.0:
|
||||
dependencies:
|
||||
'@types/estree': 1.0.8
|
||||
'@types/estree': 1.0.9
|
||||
esast-util-from-js: 2.0.1
|
||||
unified: 11.0.5
|
||||
vfile: 6.0.3
|
||||
@@ -10120,7 +10132,7 @@ snapshots:
|
||||
dependencies:
|
||||
regex-utilities: 2.3.0
|
||||
|
||||
rehype-attr@3.0.3:
|
||||
rehype-attr@4.0.0:
|
||||
dependencies:
|
||||
unified: 11.0.5
|
||||
unist-util-visit: 5.0.0
|
||||
@@ -10201,6 +10213,16 @@ snapshots:
|
||||
unified: 11.0.5
|
||||
unist-util-visit: 5.1.0
|
||||
|
||||
rehype-slug@5.1.0:
|
||||
dependencies:
|
||||
'@types/hast': 2.3.10
|
||||
github-slugger: 2.0.0
|
||||
hast-util-has-property: 2.0.1
|
||||
hast-util-heading-rank: 2.1.1
|
||||
hast-util-to-string: 2.0.0
|
||||
unified: 10.1.2
|
||||
unist-util-visit: 4.1.2
|
||||
|
||||
rehype-slug@6.0.0:
|
||||
dependencies:
|
||||
'@types/hast': 3.0.4
|
||||
@@ -10696,9 +10718,9 @@ snapshots:
|
||||
|
||||
util-deprecate@1.0.2: {}
|
||||
|
||||
uuid@11.1.0: {}
|
||||
uuid@11.1.1: {}
|
||||
|
||||
uuid@13.0.0: {}
|
||||
uuid@13.0.2: {}
|
||||
|
||||
uvu@0.5.6:
|
||||
dependencies:
|
||||
@@ -10741,7 +10763,7 @@ snapshots:
|
||||
'@types/unist': 3.0.3
|
||||
vfile-message: 4.0.3
|
||||
|
||||
vite@6.4.1(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.32.0)(yaml@2.8.3):
|
||||
vite@6.4.2(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.32.0)(yaml@2.8.3):
|
||||
dependencies:
|
||||
esbuild: 0.25.12
|
||||
fdir: 6.5.0(picomatch@4.0.3)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "../node_modules/@tauri-apps/cli/config.schema.json",
|
||||
"productName": "BiliNote",
|
||||
"version": "2.3.3",
|
||||
"version": "2.3.4",
|
||||
"identifier": "com.jefferyhuang.bilinote",
|
||||
"build": {
|
||||
"frontendDist": "../dist",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import './App.css'
|
||||
import { lazy, Suspense, useEffect } from 'react'
|
||||
import { BrowserRouter, Navigate, Routes, Route } from 'react-router-dom'
|
||||
import { BrowserRouter, HashRouter, Navigate, Routes, Route } from 'react-router-dom'
|
||||
import { useTaskPolling } from '@/hooks/useTaskPolling.ts'
|
||||
import { useCheckBackend } from '@/hooks/useCheckBackend.ts'
|
||||
import { systemCheck } from '@/services/system.ts'
|
||||
@@ -57,12 +57,16 @@ function App() {
|
||||
)
|
||||
}
|
||||
|
||||
// 桌面端使用 HashRouter 避免刷新 404;Web 端继续使用 BrowserRouter
|
||||
const isTauri = typeof window !== 'undefined' && '__TAURI_INTERNALS__' in window
|
||||
const Router = isTauri ? HashRouter : BrowserRouter
|
||||
|
||||
// 后端已初始化,渲染主应用
|
||||
return (
|
||||
<>
|
||||
<StartupBanner />
|
||||
<BackendHealthIndicator />
|
||||
<BrowserRouter>
|
||||
<Router>
|
||||
<Suspense fallback={<div className="flex h-screen items-center justify-center">加载中…</div>}>
|
||||
<Routes>
|
||||
<Route path="/onboarding" element={<Onboarding />} />
|
||||
@@ -86,7 +90,7 @@ function App() {
|
||||
</Route>
|
||||
</Routes>
|
||||
</Suspense>
|
||||
</BrowserRouter>
|
||||
</Router>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ import 'react-medium-image-zoom/dist/styles.css'
|
||||
import gfm from 'remark-gfm'
|
||||
import remarkMath from 'remark-math'
|
||||
import rehypeKatex from 'rehype-katex'
|
||||
import rehypeSlug from 'rehype-slug'
|
||||
import 'katex/dist/katex.min.css'
|
||||
import 'github-markdown-css/github-markdown-light.css'
|
||||
import { ScrollArea } from '@/components/ui/scroll-area.tsx'
|
||||
@@ -47,7 +48,7 @@ const steps = [
|
||||
]
|
||||
|
||||
const remarkPlugins = [gfm, remarkMath]
|
||||
const rehypePlugins = [rehypeKatex]
|
||||
const rehypePlugins = [rehypeKatex, rehypeSlug]
|
||||
|
||||
/**
|
||||
* 构建 ReactMarkdown components 对象,baseURL 用于修正图片路径。
|
||||
@@ -117,6 +118,51 @@ function createMarkdownComponents(baseURL: string) {
|
||||
)
|
||||
}
|
||||
|
||||
// 处理笔记内部锚点链接(如目录跳转)
|
||||
if (href?.startsWith('#')) {
|
||||
const handleAnchorClick = (e: React.MouseEvent) => {
|
||||
e.preventDefault()
|
||||
const id = decodeURIComponent(href.slice(1))
|
||||
|
||||
// 1. 优先精确匹配 id
|
||||
let target = document.getElementById(id)
|
||||
|
||||
// 2. 精确失败时按 heading 文本模糊匹配
|
||||
// LLM 生成的目录锚点可能和 heading 实际文本不完全一致
|
||||
//(例如 heading 带 *Content-[00:00]* 后缀,目录链接里没有)
|
||||
if (!target) {
|
||||
const normalize = (s: string) =>
|
||||
s.replace(/[-::\s*\[\]]/g, '').toLowerCase()
|
||||
const search = normalize(id)
|
||||
const headings = document.querySelectorAll('h1, h2, h3, h4, h5, h6')
|
||||
for (const h of headings) {
|
||||
const text = h.textContent || ''
|
||||
if (normalize(text).includes(search) || search.includes(normalize(text))) {
|
||||
target = h
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (target) {
|
||||
target.scrollIntoView({ behavior: 'smooth', block: 'start' })
|
||||
} else {
|
||||
toast.error('未找到对应章节')
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<a
|
||||
href={href}
|
||||
onClick={handleAnchorClick}
|
||||
className="text-primary hover:text-primary/80 inline-flex items-center gap-0.5 font-medium underline underline-offset-4"
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
</a>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<a
|
||||
href={href}
|
||||
|
||||
@@ -5,9 +5,14 @@ import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'
|
||||
import { Github, Star, ExternalLink, Download } from 'lucide-react'
|
||||
import { ScrollArea } from '@/components/ui/scroll-area.tsx'
|
||||
import logo from '@/assets/icon.svg'
|
||||
import wechatQr from '@/assets/wechat.png'
|
||||
|
||||
// 二维码统一走 GitHub 在线地址:后续在仓库替换图片后,已打包的 App 会自动更新,无需重新发版
|
||||
const GITHUB_DOC_RAW = 'https://raw.githubusercontent.com/JefferyHcool/BiliNote/master/doc'
|
||||
const wechatQr = `${GITHUB_DOC_RAW}/wechat-group-1.png`
|
||||
const remoteInstallQr = `${GITHUB_DOC_RAW}/remote-install-wechat.png`
|
||||
|
||||
export default function AboutPage() {
|
||||
const appVersion = __APP_VERSION__
|
||||
const images = [
|
||||
'https://common-1304618721.cos.ap-chengdu.myqcloud.com/20250504102850.png',
|
||||
'https://common-1304618721.cos.ap-chengdu.myqcloud.com/20250504103028.png',
|
||||
@@ -27,7 +32,7 @@ export default function AboutPage() {
|
||||
height={50}
|
||||
className="rounded-lg"
|
||||
/>
|
||||
<h1 className="text-4xl font-bold">BiliNote v2.0.0</h1>
|
||||
<h1 className="text-4xl font-bold">BiliNote v{appVersion}</h1>
|
||||
</div>
|
||||
<p className="text-muted-foreground mb-6 text-xl italic">
|
||||
AI 视频笔记生成工具 让 AI 为你的视频做笔记
|
||||
@@ -197,12 +202,28 @@ export default function AboutPage() {
|
||||
<section className="mb-16">
|
||||
<h2 className="mb-8 text-center text-3xl font-bold">联系和加入社区</h2>
|
||||
<div className="mx-auto max-w-3xl">
|
||||
<div className="flex flex-col items-center justify-center gap-8">
|
||||
<div className="flex flex-col items-center justify-center gap-10 md:flex-row md:items-start">
|
||||
<div className="text-center">
|
||||
<h3 className="mb-3 text-xl font-semibold">BiliNote 交流微信群</h3>
|
||||
<div className="bg-muted mx-auto flex h-52 w-52 items-center justify-center rounded-md">
|
||||
<img src={wechatQr} alt="BiliNote 交流微信群" className="h-full w-full object-contain" />
|
||||
</div>
|
||||
<p className="text-muted-foreground mt-3 text-sm">扫码加入交流群,一起讨论使用问题</p>
|
||||
</div>
|
||||
<div className="text-center">
|
||||
<h3 className="mb-3 text-xl font-semibold">BiliNote AI笔记系统一对一搭建服务</h3>
|
||||
<div className="bg-muted mx-auto flex h-52 w-52 items-center justify-center rounded-md">
|
||||
<img
|
||||
src={remoteInstallQr}
|
||||
alt="BiliNote AI笔记系统一对一搭建服务"
|
||||
className="h-full w-full object-contain"
|
||||
/>
|
||||
</div>
|
||||
<p className="text-muted-foreground mt-3 text-sm">
|
||||
专人一对一远程协助,从部署到上手全程陪跑
|
||||
<br />
|
||||
扫码加微信,备注「搭建服务」即可咨询
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
2
BillNote_frontend/src/vite-env.d.ts
vendored
2
BillNote_frontend/src/vite-env.d.ts
vendored
@@ -1 +1,3 @@
|
||||
/// <reference types="vite/client" />
|
||||
|
||||
declare const __APP_VERSION__: string
|
||||
|
||||
@@ -1,11 +1,25 @@
|
||||
import { defineConfig, loadEnv } from 'vite'
|
||||
import react from '@vitejs/plugin-react'
|
||||
import fs from 'fs'
|
||||
import path from 'path'
|
||||
import { fileURLToPath } from 'url'
|
||||
import tailwindcss from '@tailwindcss/vite'
|
||||
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url))
|
||||
|
||||
function readAppVersion() {
|
||||
const fallbackVersion = '0.0.0'
|
||||
|
||||
try {
|
||||
const tauriConfigPath = path.resolve(__dirname, 'src-tauri/tauri.conf.json')
|
||||
const tauriConfig = JSON.parse(fs.readFileSync(tauriConfigPath, 'utf-8')) as { version?: string }
|
||||
return tauriConfig.version || fallbackVersion
|
||||
}
|
||||
catch {
|
||||
return fallbackVersion
|
||||
}
|
||||
}
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig(({ mode }) => {
|
||||
// 在 Docker 环境中,父目录可能没有 .env 文件,使用当前目录
|
||||
@@ -14,9 +28,13 @@ export default defineConfig(({ mode }) => {
|
||||
|
||||
const apiBaseUrl = env.VITE_API_BASE_URL || 'http://127.0.0.1:8483'
|
||||
const port = parseInt(env.VITE_FRONTEND_PORT || '3015', 10)
|
||||
const appVersion = env.VITE_APP_VERSION || process.env.VITE_APP_VERSION || readAppVersion()
|
||||
|
||||
return {
|
||||
base: './',
|
||||
define: {
|
||||
__APP_VERSION__: JSON.stringify(appVersion),
|
||||
},
|
||||
plugins: [react(), tailwindcss()],
|
||||
resolve: {
|
||||
alias: {
|
||||
|
||||
@@ -35,6 +35,10 @@ COPY ./backend /tmp/backend
|
||||
ARG BASE_REGISTRY=docker.io
|
||||
FROM ${BASE_REGISTRY}/library/node:20-alpine AS frontend-builder
|
||||
|
||||
# 可由发布 workflow 从 git tag 注入,用于前端 About 页展示版本;未传时由 Vite 回退读取 tauri.conf.json。
|
||||
ARG VITE_APP_VERSION=
|
||||
ENV VITE_APP_VERSION=${VITE_APP_VERSION}
|
||||
|
||||
# pnpm 版本 pin 到 9 系列:
|
||||
# - lockfile (BillNote_frontend/pnpm-lock.yaml) 是 lockfileVersion '9.0',由 pnpm 9 生成
|
||||
# - pnpm 11+ 要求 Node 22+,与 node:20 不兼容(ERR_UNKNOWN_BUILTIN_MODULE)
|
||||
|
||||
12
README.md
12
README.md
@@ -3,7 +3,7 @@
|
||||
<p align="center">
|
||||
<img src="./doc/icon.svg" alt="BiliNote Banner" width="50" height="50" />
|
||||
</p>
|
||||
<h1 align="center" > BiliNote v2.3.3</h1>
|
||||
<h1 align="center" > BiliNote v2.3.4</h1>
|
||||
</div>
|
||||
|
||||
<p align="center"><i>AI 视频笔记生成工具 让 AI 为你的视频做笔记</i></p>
|
||||
@@ -53,6 +53,16 @@ BiliNote 是一个开源的 AI 视频笔记助手,支持通过哔哩哔哩、Y
|
||||
|
||||
> Windows 用户请注意:一定要在没有中文路径的环境下运行。
|
||||
|
||||
## 💎 BiliNote AI笔记系统一对一搭建服务
|
||||
|
||||
提供 **BiliNote AI笔记系统一对一搭建服务**:专人一对一远程协助,从环境部署、模型配置到上手使用全程陪跑,帮你快速跑通整套系统。扫码添加微信,备注「搭建服务」即可咨询:
|
||||
|
||||
<table align="center">
|
||||
<tr>
|
||||
<td align="center"><img src="./doc/remote-install-wechat.png" alt="BiliNote AI笔记系统一对一搭建服务" width="220" /><br/>BiliNote AI笔记系统一对一搭建服务</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
## 🔧 功能特性
|
||||
|
||||
- 支持多平台:Bilibili、YouTube、本地视频、抖音、快手
|
||||
|
||||
@@ -129,6 +129,10 @@ class ProviderService:
|
||||
try:
|
||||
# 过滤掉空值
|
||||
filtered_data = {k: v for k, v in data.items() if v is not None and k != 'id'}
|
||||
# 防御掩码污染:前端展示时 api_key 被 mask_key() 处理过(如 a92f****...2d3a),
|
||||
# 如果用户未重新输入直接保存,带星号的值不应覆盖原 key。
|
||||
if 'api_key' in filtered_data and '*' in str(filtered_data.get('api_key', '')):
|
||||
filtered_data.pop('api_key')
|
||||
print('更新模型供应商',filtered_data)
|
||||
update_provider(id, **filtered_data)
|
||||
# 获取更新后的供应商信息
|
||||
|
||||
@@ -1,11 +1,41 @@
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
from dotenv import load_dotenv
|
||||
|
||||
from app.utils.logger import get_logger
|
||||
logger = get_logger(__name__)
|
||||
|
||||
load_dotenv()
|
||||
|
||||
def _load_dotenv_from_multiple_paths():
|
||||
"""尝试多个位置加载 .env,适配源码运行和 PyInstaller 打包场景。
|
||||
|
||||
PyInstaller 打包后当前工作目录是 EXE 所在目录,而源码运行时 .env
|
||||
通常在项目根目录或 backend/ 同级。遍历常见候选路径确保能命中。
|
||||
"""
|
||||
candidates = []
|
||||
# 1. 当前工作目录(EXE 所在目录)
|
||||
candidates.append(os.path.join(os.getcwd(), '.env'))
|
||||
# 2. 本脚本所在目录(backend/)
|
||||
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
candidates.append(os.path.join(script_dir, '.env'))
|
||||
# 3. 项目根目录(backend/../.env)
|
||||
candidates.append(os.path.join(script_dir, '..', '.env'))
|
||||
# 4. PyInstaller 打包后的 _internal/ 子目录
|
||||
if getattr(sys, 'frozen', False):
|
||||
exe_dir = os.path.dirname(sys.executable)
|
||||
candidates.append(os.path.join(exe_dir, '_internal', '.env'))
|
||||
|
||||
for path in candidates:
|
||||
normalized = os.path.normpath(path)
|
||||
if os.path.isfile(normalized):
|
||||
load_dotenv(normalized)
|
||||
return
|
||||
# 都没找到,fallback 到默认行为(从 CWD 找)
|
||||
load_dotenv()
|
||||
|
||||
|
||||
_load_dotenv_from_multiple_paths()
|
||||
def check_ffmpeg_exists() -> bool:
|
||||
"""
|
||||
检查 ffmpeg 是否可用。优先使用 FFMPEG_BIN_PATH 环境变量指定的路径。
|
||||
|
||||
BIN
doc/remote-install-wechat.png
Normal file
BIN
doc/remote-install-wechat.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 482 KiB |
Reference in New Issue
Block a user