diff --git a/.github/workflows/scraping.yml b/.github/workflows/scraping.yml
deleted file mode 100644
index 87546e9..0000000
--- a/.github/workflows/scraping.yml
+++ /dev/null
@@ -1,39 +0,0 @@
-name: update data.json
-
-on:
- workflow_dispatch:
- schedule:
- - cron: "0 * * * *"
-
-jobs:
- scrape_and_save:
- runs-on: ubuntu-latest
- steps:
- - name: Checkout code
- uses: actions/checkout@v4
- - name: Set up Python
- uses: actions/setup-python@v5
- with:
- python-version: "3.x"
- - name: Install dependencies
- run: |
- python -m pip install --upgrade pip
- pip install -r requirements.txt
- - name: Run scraping script
- env:
- ACCESS_TOKEN: ${{ secrets.ACCESS_TOKEN }}
- DATABASE_ID: ${{ secrets.DATABASE_ID }}
- run: |
- python scripts/scrape.py
- - name: Commit data.json
- run: |
- git diff --quiet --exit-code public/assets/data.json || (
- git config --global user.name "NowScott"
- git config --global user.email "nowscott@qq.com"
- git add public/assets/data.json
- DATE=$(TZ="Asia/Shanghai" date "+%Y-%m-%d %H:%M:%S")
- git commit -m "Update data.json at $DATE"
- git push origin main
- )
-
-
diff --git a/.gitignore b/.gitignore
index d3e06cd..df6cc99 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,99 @@
-.env
-.DS_store
-node_modules
-package-lock.json
\ No newline at end of file
+# Node.js 相关
+node_modules/
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+
+# 日志文件
+logs
+*.log
+pids
+*.pid
+*.seed
+*.pid.lock
+
+# 运行时数据
+lib-cov
+coverage/
+*.lcov
+
+# jscoverage/JSCover 生成的目录
+lib-cov
+
+# istanbul 使用的覆盖率目录
+coverage/
+
+# nyc 测试覆盖率输出目录
+.nyc_output/
+
+# Grunt 中间存储目录(https://gruntjs.com/creating-plugins#storing-task-files)
+.grunt/
+
+# Bower 依赖目录(https://bower.io/)
+bower_components/
+
+# 编译的二进制扩展(https://nodejs.org/api/addons.html)
+build/Release
+
+# 依赖目录
+jspm_packages/
+
+# Next.js 构建输出
+.next/
+
+# dotenv 环境变量文件
+.env.local
+.env.development.local
+.env.test.local
+.env.production.local
+.env
+
+# Next.js 生成的文件
+*.next
+out/
+.next/
+out/
+build/
+dist/
+
+# macOS 特定文件
+.DS_Store
+.AppleDouble
+.LSOverride
+
+# 图标文件必须以两个回车结尾
+Icon\r\r
+
+# 缩略图
+._*
+
+# 可能出现在卷根目录下的文件
+.DocumentRevisions-V100
+.fseventsd
+.Spotlight-V100
+.TemporaryItems
+.Trashes
+.VolumeIcon.icns
+.com.apple.timemachine.donotpresent
+
+# 可能在远程 AFP 共享上创建的目录
+.AppleDB
+.AppleDesktop
+Network Trash Folder
+Temporary Items
+.apdisk
+
+# 编辑器和 IDE 相关
+.idea/
+.vscode/
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw?
+
+# TypeScript 缓存文件
+*.tsbuildinfo
+
+# 可选的 npm 缓存目录
+.npm
diff --git a/lib/contextMenu.js b/lib/contextMenu.js
new file mode 100644
index 0000000..dfd0371
--- /dev/null
+++ b/lib/contextMenu.js
@@ -0,0 +1,110 @@
+const fontData = {
+ "fonts": [
+ {
+ "name": "Smiley Sans Oblique",
+ "displayName": "得意黑"
+ },
+ {
+ "name": "LXGW WenKai",
+ "displayName": "霞鹜文楷"
+ },
+ {
+ "name": "KingHwa_OldSong",
+ "displayName": "京華老宋体"
+ },
+ {
+ "name": "MuzaiPixel",
+ "displayName": "目哉像素体"
+ },
+ {
+ "name": "LXGW Marker Gothic",
+ "displayName": "霞鹜漫黑"
+ }
+ ]
+ };
+
+ export const populateContextMenu = () => {
+ const menu = document.getElementById('customContextMenu').querySelector('ul');
+ menu.innerHTML = ''; // 清空现有的菜单项,防止重复添加
+
+ fontData.fonts.forEach((font) => {
+ let li = document.createElement('li');
+ li.textContent = font.displayName; // 显示中文字体名
+ li.style.cursor = 'pointer';
+ li.style.fontFamily = font.name; // 设置每个字体选项的字体样式
+ li.onclick = () => {
+ changeFont(font.name); // 调用更改字体的函数
+ };
+ menu.appendChild(li);
+ });
+ };
+
+ export const changeFont = (font) => {
+ document.documentElement.style.setProperty('--main-font-family', `"${font}"`);
+ setCookie('userFont', font, 7); // 更新Cookie,持续7天
+ updateMenuSelection(font); // 更新菜单选择状态
+ document.getElementById('customContextMenu').style.display = 'none'; // 隐藏菜单
+ };
+
+ const updateMenuSelection = (selectedFont) => {
+ const items = document.querySelectorAll('#customContextMenu li');
+ items.forEach(item => {
+ if (item.textContent.trim() === fontData.fonts.find(f => f.name === selectedFont).displayName) { // 使用正确的友好名称进行比较
+ item.classList.add('selected-font');
+ } else {
+ item.classList.remove('selected-font');
+ }
+ });
+ };
+
+ const setCookie = (name, value, days) => {
+ var expires = "";
+ if (days) {
+ var date = new Date();
+ date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
+ expires = "; expires=" + date.toUTCString();
+ }
+ document.cookie = name + "=" + (value || "") + expires + "; path=/";
+ };
+
+ const getCookie = (name) => {
+ var nameEQ = name + "=";
+ var ca = document.cookie.split(';');
+ for (var i = 0; i < ca.length; i++) {
+ var c = ca[i];
+ while (c.charAt(0) == ' ') c = c.substring(1, c.length);
+ if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length, c.length);
+ }
+ return null;
+ };
+
+ const loadFont = () => {
+ var userFont = getCookie('userFont');
+ if (userFont) {
+ document.documentElement.style.setProperty('--main-font-family', userFont);
+ updateMenuSelection(userFont); // 更新菜单选择状态
+ }
+ };
+
+ export const initializeContextMenu = () => {
+ populateContextMenu(); // 填充右键菜单
+ loadFont(); // 加载用户之前选择的字体
+
+ // 处理右键菜单事件
+ document.addEventListener('contextmenu', function (event) {
+ event.preventDefault();
+ var contextMenu = document.getElementById('customContextMenu');
+ contextMenu.style.display = 'block';
+ contextMenu.style.left = event.pageX + 'px';
+ contextMenu.style.top = event.pageY + 'px';
+ });
+
+ // 处理点击事件,隐藏自定义的右键菜单
+ document.addEventListener('click', function (event) {
+ var contextMenu = document.getElementById('customContextMenu');
+ if (event.target.offsetParent !== contextMenu) {
+ contextMenu.style.display = 'none';
+ }
+ });
+ };
+
\ No newline at end of file
diff --git a/lib/dataLoader.js b/lib/dataLoader.js
new file mode 100644
index 0000000..3ed58fe
--- /dev/null
+++ b/lib/dataLoader.js
@@ -0,0 +1,80 @@
+// 随机排序
+export const randomSort = arr => {
+ for (let i = 0, l = arr.length; i < l; i++) {
+ let rc = parseInt(Math.random() * l);
+ const empty = arr[i];
+ arr[i] = arr[rc];
+ arr[rc] = empty;
+ }
+ return arr;
+};
+// 去重
+export const unique = arr => Array.from(new Set(arr));
+// 提取tags
+export const extractTags = posts => {
+ const allTags = new Set();
+ posts.forEach(post => {
+ if (post.state !== '隐藏') {//避免隐藏网页的tag被写入
+ post.tags.forEach(tag => allTags.add(tag));
+ }
+ });
+ return [...allTags];
+};
+
+// 通过tags筛选
+export const filterPostsByTags = (posts, tags) => {
+ return posts.filter(post => tags.every(tag => post.tags.includes(tag)));
+};
+
+//通过搜索筛选
+export const filterPostsBySearch = (posts, query) => {
+ if(query === '隐藏'){
+ return posts
+ }
+ // 返回符合查询条件的帖子
+ return posts.filter(post =>
+ post.name.toLowerCase().includes(query.toLowerCase()) ||
+ post.brief.toLowerCase().includes(query.toLowerCase()) ||
+ post.tags.some(tag => tag.toLowerCase().includes(query.toLowerCase()))
+ );
+};
+
+
+export const renderTags = (tags, onList, toggleTagButton) => {
+ return tags.map((tag, index) => (
+
+ ));
+};
+
+export const toggleTagButton = (tag, onList, setOnList, tags, setTags) => {
+ let newOnList;
+ if (onList.includes(tag)) {
+ newOnList = onList.filter(item => item !== tag);
+ } else {
+ newOnList = [...onList, tag];
+ }
+ setOnList(newOnList);
+ // 重新排序标签列表,使选中的标签排在前面
+ const sortedTags = newOnList.concat(tags.filter(t => !newOnList.includes(t)));
+ setTags(sortedTags);
+};
+
+export const updateResults = (posts, onList, setFilteredPosts, setTags) => {
+ const filtered = posts.filter(post =>
+ onList.every(tag => post.tags.includes(tag))
+ );
+ setFilteredPosts(filtered);
+ // 更新标签列表,只显示可选的标签
+ const availableTags = Array.from(new Set(filtered.flatMap(post => post.tags)));
+ const sortedTags = onList.concat(availableTags.filter(tag => !onList.includes(tag)));
+ setTags(sortedTags);
+};
+
+
diff --git a/lib/notion.js b/lib/notion.js
new file mode 100644
index 0000000..37674a5
--- /dev/null
+++ b/lib/notion.js
@@ -0,0 +1,50 @@
+import { Client } from '@notionhq/client';
+
+// 创建 Notion 客户端实例,使用环境变量中的 NOTION_TOKEN 进行身份验证
+const notion = new Client({ auth: process.env.NOTION_TOKEN });
+
+// 获取指定数据库的所有页面
+export const getAllPages = async (databaseId) => {
+ let results = []; // 存储所有页面的数组
+ let hasMore = true; // 用于迭代查询,检查是否还有更多页面需要获取
+ let startCursor = undefined; // 用于获取下一页的游标
+
+ // 当仍有更多页面需要获取时循环执行
+ while (hasMore) {
+ // 查询数据库的一页数据
+ const response = await notion.databases.query({
+ database_id: databaseId,
+ start_cursor: startCursor,
+ });
+
+ // 将当前页的结果追加到结果数组中
+ results = results.concat(response.results);
+ // 更新是否还有更多页面的标志
+ hasMore = response.has_more;
+ // 更新下一页的游标,以便下次查询时获取下一页数据
+ startCursor = response.next_cursor;
+ }
+
+ return results; // 返回所有页面的数组
+};
+
+// 获取指定数据库的页面并转换为适合显示的格式
+export const getDatabase = async (databaseId) => {
+ // 获取指定数据库的所有页面
+ const pages = await getAllPages(databaseId);
+ // 将页面格式化为适合显示的格式
+ return pages
+ .filter(page => page.properties.empty.formula.string !== 'empty') // 过滤掉空的页面
+ .filter(page => page.properties.state.select.name !== '断开连接') // 过滤掉状态为 "断开连接" 的页面
+ .map(page => {
+ const properties = page.properties;
+ return {
+ id: page.id, // 页面的 ID
+ name: properties.name.title[0].plain_text, // 页面的名称
+ state: properties.state.select.name, // 页面的状态
+ brief: properties.brief.rich_text[0].plain_text, // 页面的简介
+ tags: properties.tags.multi_select.map(tag => tag.name), // 页面的标签数组
+ web: properties.web.url, // 页面的网址
+ };
+ });
+};
\ No newline at end of file
diff --git a/lib/theme.js b/lib/theme.js
new file mode 100644
index 0000000..50f1b7c
--- /dev/null
+++ b/lib/theme.js
@@ -0,0 +1,31 @@
+export const applyTheme = (theme) => {
+ const dark_mode = document.getElementById('darkcss');
+ const dark_mode_icon = document.getElementById('icon');
+ const dark_mode_btn = document.getElementById('darkbtn');
+
+ if (theme === 'dark') {
+ dark_mode.setAttribute('href', '/css/dark.css');
+ dark_mode_icon.src = '/assets/svg/sun.svg';
+ dark_mode_btn.className = 'dark';
+ console.log('切换为深色模式');
+ } else {
+ dark_mode.setAttribute('href', '/css/daytime.css');
+ dark_mode_icon.src = '/assets/svg/moon.svg';
+ dark_mode_btn.className = 'daytime';
+ console.log('切换为浅色模式');
+ }
+};
+
+export const initializeTheme = () => {
+ const dark_mode_btn = document.getElementById('darkbtn');
+ const currentHour = new Date().getHours();
+ const theme = (currentHour >= 22 || currentHour < 8) ? 'dark' : 'daytime';
+
+ applyTheme(theme);
+
+ dark_mode_btn.onclick = () => {
+ const currentTheme = dark_mode_btn.className;
+ const newTheme = (currentTheme === 'daytime') ? 'dark' : 'daytime';
+ applyTheme(newTheme);
+ };
+};
diff --git a/next.config.js b/next.config.js
new file mode 100644
index 0000000..5a06939
--- /dev/null
+++ b/next.config.js
@@ -0,0 +1,9 @@
+module.exports = {
+ env: {
+ NOTION_TOKEN: process.env.NOTION_TOKEN,
+ DATABASE_ID: process.env.DATABASE_ID,
+ },
+ future: {
+ webpack5: true,
+ },
+};
diff --git a/package-lock.json b/package-lock.json
new file mode 100644
index 0000000..151f2a5
--- /dev/null
+++ b/package-lock.json
@@ -0,0 +1,528 @@
+{
+ "name": "my-vercel-notion-app",
+ "version": "1.0.0",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "my-vercel-notion-app",
+ "version": "1.0.0",
+ "dependencies": {
+ "@notionhq/client": "^0.4.11",
+ "next": "latest",
+ "react": "latest",
+ "react-dom": "latest"
+ }
+ },
+ "node_modules/@next/env": {
+ "version": "14.2.3",
+ "resolved": "https://registry.npmjs.org/@next/env/-/env-14.2.3.tgz",
+ "integrity": "sha512-W7fd7IbkfmeeY2gXrzJYDx8D2lWKbVoTIj1o1ScPHNzvp30s1AuoEFSdr39bC5sjxJaxTtq3OTCZboNp0lNWHA=="
+ },
+ "node_modules/@next/swc-darwin-arm64": {
+ "version": "14.2.3",
+ "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.2.3.tgz",
+ "integrity": "sha512-3pEYo/RaGqPP0YzwnlmPN2puaF2WMLM3apt5jLW2fFdXD9+pqcoTzRk+iZsf8ta7+quAe4Q6Ms0nR0SFGFdS1A==",
+ "cpu": [
+ "arm64"
+ ],
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-darwin-x64": {
+ "version": "14.2.3",
+ "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.2.3.tgz",
+ "integrity": "sha512-6adp7waE6P1TYFSXpY366xwsOnEXM+y1kgRpjSRVI2CBDOcbRjsJ67Z6EgKIqWIue52d2q/Mx8g9MszARj8IEA==",
+ "cpu": [
+ "x64"
+ ],
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-linux-arm64-gnu": {
+ "version": "14.2.3",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.2.3.tgz",
+ "integrity": "sha512-cuzCE/1G0ZSnTAHJPUT1rPgQx1w5tzSX7POXSLaS7w2nIUJUD+e25QoXD/hMfxbsT9rslEXugWypJMILBj/QsA==",
+ "cpu": [
+ "arm64"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-linux-arm64-musl": {
+ "version": "14.2.3",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.2.3.tgz",
+ "integrity": "sha512-0D4/oMM2Y9Ta3nGuCcQN8jjJjmDPYpHX9OJzqk42NZGJocU2MqhBq5tWkJrUQOQY9N+In9xOdymzapM09GeiZw==",
+ "cpu": [
+ "arm64"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-linux-x64-gnu": {
+ "version": "14.2.3",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.2.3.tgz",
+ "integrity": "sha512-ENPiNnBNDInBLyUU5ii8PMQh+4XLr4pG51tOp6aJ9xqFQ2iRI6IH0Ds2yJkAzNV1CfyagcyzPfROMViS2wOZ9w==",
+ "cpu": [
+ "x64"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-linux-x64-musl": {
+ "version": "14.2.3",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.3.tgz",
+ "integrity": "sha512-BTAbq0LnCbF5MtoM7I/9UeUu/8ZBY0i8SFjUMCbPDOLv+un67e2JgyN4pmgfXBwy/I+RHu8q+k+MCkDN6P9ViQ==",
+ "cpu": [
+ "x64"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-win32-arm64-msvc": {
+ "version": "14.2.3",
+ "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.3.tgz",
+ "integrity": "sha512-AEHIw/dhAMLNFJFJIJIyOFDzrzI5bAjI9J26gbO5xhAKHYTZ9Or04BesFPXiAYXDNdrwTP2dQceYA4dL1geu8A==",
+ "cpu": [
+ "arm64"
+ ],
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-win32-ia32-msvc": {
+ "version": "14.2.3",
+ "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.3.tgz",
+ "integrity": "sha512-vga40n1q6aYb0CLrM+eEmisfKCR45ixQYXuBXxOOmmoV8sYST9k7E3US32FsY+CkkF7NtzdcebiFT4CHuMSyZw==",
+ "cpu": [
+ "ia32"
+ ],
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-win32-x64-msvc": {
+ "version": "14.2.3",
+ "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.3.tgz",
+ "integrity": "sha512-Q1/zm43RWynxrO7lW4ehciQVj+5ePBhOK+/K2P7pLFX3JaJ/IZVC69SHidrmZSOkqz7ECIOhhy7XhAFG4JYyHA==",
+ "cpu": [
+ "x64"
+ ],
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@notionhq/client": {
+ "version": "0.4.13",
+ "resolved": "https://registry.npmjs.org/@notionhq/client/-/client-0.4.13.tgz",
+ "integrity": "sha512-tHC95h4JZYteHmIL49xdta0Yb9q0peXySqo9cqTQEVzpPwUdcPNgWQljMqfrSVKqlpGNX+DhXztY0LR6f3Iw6A==",
+ "dependencies": {
+ "@types/node-fetch": "^2.5.10",
+ "node-fetch": "^2.6.1"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@swc/counter": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz",
+ "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ=="
+ },
+ "node_modules/@swc/helpers": {
+ "version": "0.5.5",
+ "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.5.tgz",
+ "integrity": "sha512-KGYxvIOXcceOAbEk4bi/dVLEK9z8sZ0uBB3Il5b1rhfClSpcX0yfRO0KmTkqR2cnQDymwLB+25ZyMzICg/cm/A==",
+ "dependencies": {
+ "@swc/counter": "^0.1.3",
+ "tslib": "^2.4.0"
+ }
+ },
+ "node_modules/@types/node": {
+ "version": "20.12.12",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.12.tgz",
+ "integrity": "sha512-eWLDGF/FOSPtAvEqeRAQ4C8LSA7M1I7i0ky1I8U7kD1J5ITyW3AsRhQrKVoWf5pFKZ2kILsEGJhsI9r93PYnOw==",
+ "dependencies": {
+ "undici-types": "~5.26.4"
+ }
+ },
+ "node_modules/@types/node-fetch": {
+ "version": "2.6.11",
+ "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.11.tgz",
+ "integrity": "sha512-24xFj9R5+rfQJLRyM56qh+wnVSYhyXC2tkoBndtY0U+vubqNsYXGjufB2nn8Q6gt0LrARwL6UBtMCSVCwl4B1g==",
+ "dependencies": {
+ "@types/node": "*",
+ "form-data": "^4.0.0"
+ }
+ },
+ "node_modules/asynckit": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
+ },
+ "node_modules/busboy": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz",
+ "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==",
+ "dependencies": {
+ "streamsearch": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=10.16.0"
+ }
+ },
+ "node_modules/caniuse-lite": {
+ "version": "1.0.30001620",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001620.tgz",
+ "integrity": "sha512-WJvYsOjd1/BYUY6SNGUosK9DUidBPDTnOARHp3fSmFO1ekdxaY6nKRttEVrfMmYi80ctS0kz1wiWmm14fVc3ew==",
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ]
+ },
+ "node_modules/client-only": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz",
+ "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA=="
+ },
+ "node_modules/combined-stream": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
+ "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+ "dependencies": {
+ "delayed-stream": "~1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/delayed-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+ "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/form-data": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
+ "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
+ "dependencies": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.8",
+ "mime-types": "^2.1.12"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/graceful-fs": {
+ "version": "4.2.11",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
+ "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="
+ },
+ "node_modules/js-tokens": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="
+ },
+ "node_modules/loose-envify": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
+ "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
+ "dependencies": {
+ "js-tokens": "^3.0.0 || ^4.0.0"
+ },
+ "bin": {
+ "loose-envify": "cli.js"
+ }
+ },
+ "node_modules/mime-db": {
+ "version": "1.52.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
+ "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/mime-types": {
+ "version": "2.1.35",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
+ "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+ "dependencies": {
+ "mime-db": "1.52.0"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/nanoid": {
+ "version": "3.3.7",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz",
+ "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "bin": {
+ "nanoid": "bin/nanoid.cjs"
+ },
+ "engines": {
+ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
+ }
+ },
+ "node_modules/next": {
+ "version": "14.2.3",
+ "resolved": "https://registry.npmjs.org/next/-/next-14.2.3.tgz",
+ "integrity": "sha512-dowFkFTR8v79NPJO4QsBUtxv0g9BrS/phluVpMAt2ku7H+cbcBJlopXjkWlwxrk/xGqMemr7JkGPGemPrLLX7A==",
+ "dependencies": {
+ "@next/env": "14.2.3",
+ "@swc/helpers": "0.5.5",
+ "busboy": "1.6.0",
+ "caniuse-lite": "^1.0.30001579",
+ "graceful-fs": "^4.2.11",
+ "postcss": "8.4.31",
+ "styled-jsx": "5.1.1"
+ },
+ "bin": {
+ "next": "dist/bin/next"
+ },
+ "engines": {
+ "node": ">=18.17.0"
+ },
+ "optionalDependencies": {
+ "@next/swc-darwin-arm64": "14.2.3",
+ "@next/swc-darwin-x64": "14.2.3",
+ "@next/swc-linux-arm64-gnu": "14.2.3",
+ "@next/swc-linux-arm64-musl": "14.2.3",
+ "@next/swc-linux-x64-gnu": "14.2.3",
+ "@next/swc-linux-x64-musl": "14.2.3",
+ "@next/swc-win32-arm64-msvc": "14.2.3",
+ "@next/swc-win32-ia32-msvc": "14.2.3",
+ "@next/swc-win32-x64-msvc": "14.2.3"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.1.0",
+ "@playwright/test": "^1.41.2",
+ "react": "^18.2.0",
+ "react-dom": "^18.2.0",
+ "sass": "^1.3.0"
+ },
+ "peerDependenciesMeta": {
+ "@opentelemetry/api": {
+ "optional": true
+ },
+ "@playwright/test": {
+ "optional": true
+ },
+ "sass": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/node-fetch": {
+ "version": "2.7.0",
+ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
+ "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==",
+ "dependencies": {
+ "whatwg-url": "^5.0.0"
+ },
+ "engines": {
+ "node": "4.x || >=6.0.0"
+ },
+ "peerDependencies": {
+ "encoding": "^0.1.0"
+ },
+ "peerDependenciesMeta": {
+ "encoding": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/picocolors": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz",
+ "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew=="
+ },
+ "node_modules/postcss": {
+ "version": "8.4.31",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz",
+ "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==",
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/postcss"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "dependencies": {
+ "nanoid": "^3.3.6",
+ "picocolors": "^1.0.0",
+ "source-map-js": "^1.0.2"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14"
+ }
+ },
+ "node_modules/react": {
+ "version": "18.3.1",
+ "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
+ "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==",
+ "dependencies": {
+ "loose-envify": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/react-dom": {
+ "version": "18.3.1",
+ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",
+ "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==",
+ "dependencies": {
+ "loose-envify": "^1.1.0",
+ "scheduler": "^0.23.2"
+ },
+ "peerDependencies": {
+ "react": "^18.3.1"
+ }
+ },
+ "node_modules/scheduler": {
+ "version": "0.23.2",
+ "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz",
+ "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==",
+ "dependencies": {
+ "loose-envify": "^1.1.0"
+ }
+ },
+ "node_modules/source-map-js": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz",
+ "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/streamsearch": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz",
+ "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==",
+ "engines": {
+ "node": ">=10.0.0"
+ }
+ },
+ "node_modules/styled-jsx": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.1.tgz",
+ "integrity": "sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==",
+ "dependencies": {
+ "client-only": "0.0.1"
+ },
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "peerDependencies": {
+ "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0"
+ },
+ "peerDependenciesMeta": {
+ "@babel/core": {
+ "optional": true
+ },
+ "babel-plugin-macros": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/tr46": {
+ "version": "0.0.3",
+ "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
+ "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="
+ },
+ "node_modules/tslib": {
+ "version": "2.6.2",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz",
+ "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q=="
+ },
+ "node_modules/undici-types": {
+ "version": "5.26.5",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
+ "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA=="
+ },
+ "node_modules/webidl-conversions": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
+ "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="
+ },
+ "node_modules/whatwg-url": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
+ "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
+ "dependencies": {
+ "tr46": "~0.0.3",
+ "webidl-conversions": "^3.0.0"
+ }
+ }
+ }
+}
diff --git a/package.json b/package.json
index 773253a..d9c362e 100644
--- a/package.json
+++ b/package.json
@@ -1,5 +1,16 @@
-{
- "dependencies": {
- "axios": "^1.4.0"
- }
-}
+{
+ "name": "my-vercel-notion-app",
+ "version": "1.0.0",
+ "scripts": {
+ "dev": "next dev",
+ "build": "next build",
+ "start": "next start"
+ },
+ "dependencies": {
+ "@notionhq/client": "^0.4.11",
+ "next": "latest",
+ "react": "latest",
+ "react-dom": "latest"
+ }
+ }
+
\ No newline at end of file
diff --git a/pages/_document.js b/pages/_document.js
new file mode 100644
index 0000000..409574d
--- /dev/null
+++ b/pages/_document.js
@@ -0,0 +1,22 @@
+import Document, { Html, Head, Main, NextScript } from 'next/document';
+
+class MyDocument extends Document {
+ render() {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+ }
+}
+
+export default MyDocument;
diff --git a/pages/index.js b/pages/index.js
new file mode 100644
index 0000000..3185024
--- /dev/null
+++ b/pages/index.js
@@ -0,0 +1,140 @@
+import Head from 'next/head';
+import { getDatabase } from '../lib/notion';
+import { useEffect, useState } from 'react';
+import {
+ randomSort,
+ unique,
+ extractTags,
+ filterPostsBySearch,
+ toggleTagButton,
+ updateResults,
+} from '../lib/dataLoader';
+import { initializeTheme } from '../lib/theme';
+import { initializeContextMenu } from '../lib/contextMenu';
+
+export default function Home({ initialPosts, lastFetched }) {
+ const [posts, setPosts] = useState(initialPosts);
+ const [normalPosts, setNormalPosts] = useState([]);
+ const [hiddenPosts, setHiddenPosts] = useState([]);
+ const [searchQuery, setSearchQuery] = useState('');
+ const [tags, setTags] = useState([]);
+ const [onList, setOnList] = useState([]);
+ const [filteredPosts, setFilteredPosts] = useState(initialPosts);
+
+ useEffect(() => {
+ initializeTheme();
+ initializeContextMenu();
+ console.log(`数据更新时间: ${new Date(lastFetched).toLocaleString()}`);
+ // 使用 setPosts 更新状态
+ setPosts(initialPosts);
+ }, [initialPosts, lastFetched]);
+
+ useEffect(() => {
+ const filteredNormalPosts = initialPosts.filter(post => post.state !== '隐藏');
+ const filteredHiddenPosts = initialPosts.filter(post => post.state === '隐藏');
+ setNormalPosts(filteredNormalPosts);
+ setHiddenPosts(filteredHiddenPosts);
+ }, [initialPosts]);
+
+ useEffect(() => {
+ const extractedTags = randomSort(extractTags(normalPosts));
+ setTags(extractedTags);
+ }, [normalPosts]);
+
+ useEffect(() => {
+ if(searchQuery === '隐藏'){
+ setFilteredPosts(filterPostsBySearch(hiddenPosts, searchQuery));
+ }else{
+ setFilteredPosts(filterPostsBySearch(normalPosts, searchQuery));
+ }
+ }, [searchQuery, normalPosts, hiddenPosts]);
+
+ useEffect(() => {
+ updateResults(posts, onList, setFilteredPosts, setTags);
+ }, [onList]);
+
+ const handleToggleTagButton = tag => {
+ toggleTagButton(tag, onList, setOnList, tags, setTags);
+ };
+
+ const searchFunction = () => {
+ const keyword = searchQuery.toLowerCase();
+ const reslist = filterPostsBySearch(posts, keyword);
+ setFilteredPosts(reslist.length > 0 ? reslist : []);
+ };
+
+ return (
+
+
+
网站索引
+
+
+
+
+
+
+
+
+
+
+
+ setSearchQuery(e.target.value)} />
+
+
+
选择标签
+
+ {tags.map(tag => (
+
+ ))}
+
+
筛选网页
+
+ {filteredPosts.length > 0 ? (
+ filteredPosts.map(post => (
+
+ {post.name}
+
+ ))
+ ) : (
+
未找到符合条件的网页
+ )}
+
+
Copyright © 2021 - NowScott
+
+
+ );
+}
+
+export async function getStaticProps() {
+ const databaseId = process.env.DATABASE_ID;
+ const posts = await getDatabase(databaseId);
+ // 获取数据的时间点
+ const lastFetched = new Date().toISOString();
+ // 排序和去重操作在服务器端执行,以确保一致性
+ const sortedPosts = randomSort(unique(posts));
+ return {
+ props: {
+ initialPosts: sortedPosts,
+ lastFetched
+ },
+ revalidate: 3600, // 每小时重新生成静态页面
+ };
+}
diff --git a/public/assets/data.json b/public/assets/data.json
deleted file mode 100644
index 489ede3..0000000
--- a/public/assets/data.json
+++ /dev/null
@@ -1,1910 +0,0 @@
-[
- {
- "name": "数学求解",
- "web": "https://zs.symbolab.com/",
- "tags": [
- "🧠学习"
- ],
- "brief": "Symbolab:方程搜索和数学求解器 - 一步步求解代数,三角函数和微积分问题",
- "state": "正常"
- },
- {
- "name": "Poe",
- "web": "https://poe.com/",
- "tags": [
- "🤖AI"
- ],
- "brief": "Poe可让您提问、获得即时回答、并与AI机器人互动对话。",
- "state": "正常"
- },
- {
- "name": "开发文档",
- "web": "https://wangdoc.com/",
- "tags": [
- "🐱Code",
- "📒笔记",
- "🧠学习"
- ],
- "brief": "提供高质量的、自主版权的、可以自由使用的中文软件文档",
- "state": "正常"
- },
- {
- "name": "矩阵计算",
- "web": "https://m.matrix.reshish.com/zh/",
- "tags": [
- "🧠学习"
- ],
- "brief": "最为便捷的在线矩阵计算器",
- "state": "正常"
- },
- {
- "name": "即刻",
- "web": "https://web.okjike.com/",
- "tags": [
- "📱数码",
- "👁️🗨️媒体"
- ],
- "brief": "与更多同好分享你的见闻与感受,每一个独到的声音,都值得被更多人倾听。",
- "state": "正常"
- },
- {
- "name": "Telegraph",
- "web": "https://telegra.ph/",
- "tags": [
- "📒笔记"
- ],
- "brief": "匿名发布文章",
- "state": "正常"
- },
- {
- "name": "荔枝商店",
- "web": "https://lizhi.shop/",
- "tags": [
- "📱数码",
- "🧰软件",
- "🛒购物"
- ],
- "brief": "数码荔枝 x 软件商店 - 专注于分享最新鲜优秀的正版软件",
- "state": "正常"
- },
- {
- "name": "云盘资源",
- "web": "https://www.aliyunpanziyuan.com/",
- "tags": [
- "📦资源",
- "🔍搜索"
- ],
- "brief": "阿里云盘资源网-网盘资源共享平台",
- "state": "正常"
- },
- {
- "name": "Sudoku",
- "web": "https://sudoku.nowscott.top/",
- "tags": [
- "🕹️游戏"
- ],
- "brief": "基于React的Sudoku",
- "state": "正常"
- },
- {
- "name": "渐变色",
- "web": "https://uigradients.com/",
- "tags": [
- "🪣色彩"
- ],
- "brief": "提供上百种渐变色",
- "state": "正常"
- },
- {
- "name": "日本色",
- "web": "https://nipponcolors.com/",
- "tags": [
- "🪣色彩"
- ],
- "brief": "日本传统颜色",
- "state": "正常"
- },
- {
- "name": "中文网字",
- "web": "https://chinese-font.netlify.app/",
- "tags": [
- "📦资源",
- "🐱Code"
- ],
- "brief": "收集免费可商用的 Web 字体文件,字体分包工具",
- "state": "正常"
- },
- {
- "name": "IT之家",
- "web": "https://www.ithome.com/",
- "tags": [
- "🗞️新闻",
- "📱数码"
- ],
- "brief": "青岛软媒旗下的前沿科技门户网站",
- "state": "正常"
- },
- {
- "name": "OpenArt",
- "web": "https://openart.ai/home",
- "tags": [
- "🖼️图片",
- "🤖AI"
- ],
- "brief": "AI艺术生成器",
- "state": "正常"
- },
- {
- "name": "7ED",
- "web": "https://www.7ed.net/",
- "tags": [
- "🕸️网络",
- "🔧工具"
- ],
- "brief": "包含静态资源 CDN 加速服务、Git 资源加速服务、海外图片内地加速服务、Bing 每日图片 API等。",
- "state": "正常"
- },
- {
- "name": "文心一言",
- "web": "https://yiyan.baidu.com/",
- "tags": [
- "🤖AI"
- ],
- "brief": "百度的大语言模型",
- "state": "正常"
- },
- {
- "name": "通义千问",
- "web": "https://tongyi.aliyun.com/qianwen/",
- "tags": [
- "🤖AI"
- ],
- "brief": "阿里做的大语言模型助手",
- "state": "正常"
- },
- {
- "name": "Buzzing",
- "web": "https://www.buzzing.cc/",
- "tags": [
- "🗞️新闻"
- ],
- "brief": "用中文浏览国外社交媒体里的热门讨论,母语快速导读, 感兴趣再进原文深度阅读",
- "state": "正常"
- },
- {
- "name": "SpeedTest",
- "web": "https://speed.cloudflare.com/",
- "tags": [
- "🕸️网络",
- "🔧工具"
- ],
- "brief": "Cloudflare的测速工具",
- "state": "正常"
- },
- {
- "name": "网站图标",
- "web": "https://fontawesome.com/",
- "tags": [
- "♻︎图标",
- "🐱Code"
- ],
- "brief": "一些图标",
- "state": "正常"
- },
- {
- "name": "在线工具",
- "web": "https://tool.lu/",
- "tags": [
- "🔧工具"
- ],
- "brief": "有很多各式各样的在线工具",
- "state": "正常"
- },
- {
- "name": "抖音",
- "web": "https://www.douyin.com/",
- "tags": [
- "⛹️♀️娱乐",
- "👁️🗨️媒体"
- ],
- "brief": "抖音 - 记录美好生活",
- "state": "正常"
- },
- {
- "name": "小红书",
- "web": "https://www.xiaohongshu.com/explore",
- "tags": [
- "👁️🗨️媒体",
- "⛹️♀️娱乐"
- ],
- "brief": "小红书 - 你的生活指南",
- "state": "正常"
- },
- {
- "name": "GropAI",
- "web": "https://groq.com/",
- "tags": [
- "🤖AI"
- ],
- "brief": "人工智能接口系统",
- "state": "正常"
- },
- {
- "name": "HuggingChat",
- "web": "https://huggingface.co/chat/",
- "tags": [
- "🤖AI"
- ],
- "brief": "让社区最好的AI聊天模型面向所有人开放。",
- "state": "正常"
- },
- {
- "name": "站长之家",
- "web": "https://tool.chinaz.com/",
- "tags": [
- "🔧工具",
- "🕸️网络"
- ],
- "brief": "提供各种查询工具",
- "state": "正常"
- },
- {
- "name": "豆包AI",
- "web": "https://www.doubao.com/chat/",
- "tags": [
- "🤖AI"
- ],
- "brief": "抖音旗下的AI助手",
- "state": "正常"
- },
- {
- "name": "敲字背单词",
- "web": "https://qwerty.kaiyi.cool/",
- "tags": [
- "🧠学习",
- "⛹️♀️娱乐"
- ],
- "brief": "为键盘工作者设计的单词记忆与英语肌肉记忆锻炼软件",
- "state": "正常"
- },
- {
- "name": "免费歌曲",
- "web": "https://tool.liumingye.cn/music/#/",
- "tags": [
- "🎵音频"
- ],
- "brief": "免费下载歌曲",
- "state": "正常"
- },
- {
- "name": "牛客网",
- "web": "https://www.nowcoder.com/",
- "tags": [
- "🐱Code",
- "🧠学习"
- ],
- "brief": "找工作神器|笔试题库|面试经验|实习招聘内推,求职就业一站解决",
- "state": "正常"
- },
- {
- "name": "秒搜",
- "web": "https://miaosou.fun/",
- "tags": [
- "🔍搜索",
- "📦资源"
- ],
- "brief": "一个很好用的网盘资源搜索引擎",
- "state": "正常"
- },
- {
- "name": "在线测试",
- "web": "https://www.onlinemictest.com/",
- "tags": [
- "🔧工具"
- ],
- "brief": "提供各种测试工具",
- "state": "正常"
- },
- {
- "name": "开源程序书",
- "web": "https://github.com/EbookFoundation/free-programming-books/blob/main/books/free-programming-books-zh.md",
- "tags": [
- "🐱Code",
- "🧠学习"
- ],
- "brief": "一些开源的程序书籍",
- "state": "正常"
- },
- {
- "name": "SOC-PK",
- "web": "https://www.socpk.com/",
- "tags": [
- "📱数码"
- ],
- "brief": "极客湾做的移动芯片排行",
- "state": "正常"
- },
- {
- "name": "BibiGPT",
- "web": "https://b.jimmylv.cn/",
- "tags": [
- "🤖AI",
- "📒笔记",
- "📺视频"
- ],
- "brief": "一键总结音视频",
- "state": "正常"
- },
- {
- "name": "深言达意",
- "web": "https://shenyandayi.com/",
- "tags": [
- "🤖AI",
- "🧠学习"
- ],
- "brief": "清华开发的根据句子找词的工具,基于AI模型",
- "state": "正常"
- },
- {
- "name": "图形计算器",
- "web": "https://www.desmos.com/calculator?lang=zh-CN",
- "tags": [
- "🧠学习",
- "🖼️图片"
- ],
- "brief": "绘制函数图形并进行可视化",
- "state": "正常"
- },
- {
- "name": "B站封面",
- "web": "https://bilicover.magecorn.com/",
- "tags": [
- "🖼️图片",
- "🔧工具"
- ],
- "brief": "提取B站视频封面",
- "state": "正常"
- },
- {
- "name": "LaTeX公式",
- "web": " https://www.latexlive.com/",
- "tags": [
- "🐱Code",
- "📒笔记"
- ],
- "brief": "在线编辑LaTeX公式的工具",
- "state": "正常"
- },
- {
- "name": "Notion头像",
- "web": "https://notion-avatar.vercel.app/zh",
- "tags": [
- "✒️设计",
- "🖼️图片"
- ],
- "brief": "制作notion风格的头像",
- "state": "正常"
- },
- {
- "name": "Gemini",
- "web": "https://gemini.google.com/",
- "tags": [
- "🤖AI"
- ],
- "brief": "谷歌人工智能的一个大型语言模型",
- "state": "正常"
- },
- {
- "name": "Claude",
- "web": "https://claude.ai/",
- "tags": [
- "🤖AI"
- ],
- "brief": "Anthropic公司开发的一个人工智能助手",
- "state": "正常"
- },
- {
- "name": "Theb.AI",
- "web": "https://beta.theb.ai/",
- "tags": [
- "🤖AI"
- ],
- "brief": "一个基于API的聊天机器人 可选择多种模型",
- "state": "正常"
- },
- {
- "name": "硬件测试仪",
- "web": "https://hardwaretester.com/",
- "tags": [
- "🕹️游戏",
- "🔧工具"
- ],
- "brief": "提供手柄、GPU、麦克风以及midi功能的测试",
- "state": "正常"
- },
- {
- "name": "中文手写板",
- "web": "https://handraw.top/",
- "tags": [
- "🧠学习",
- "📒笔记"
- ],
- "brief": "中文友好的手写白板工具",
- "state": "正常"
- },
- {
- "name": "星标历史图",
- "web": "https://star-history.com/",
- "tags": [
- "🐱Code",
- "🖼️图片"
- ],
- "brief": "GitHub上缺失的星标历史图",
- "state": "正常"
- },
- {
- "name": "Figma",
- "web": "https://www.figma.com/",
- "tags": [
- "✏️协作",
- "✒️设计",
- "🖼️图片"
- ],
- "brief": "Figma是一款协作设计工具,用于创建用户界面和原型。",
- "state": "正常"
- },
- {
- "name": "手写板",
- "web": "https://excalidraw.com/",
- "tags": [
- "🧠学习",
- "📒笔记"
- ],
- "brief": "手写效果白板工具",
- "state": "正常"
- },
- {
- "name": "AColor",
- "web": "https://color.adobe.com/",
- "tags": [
- "🪣色彩"
- ],
- "brief": "Adobe的一个配色网站",
- "state": "正常"
- },
- {
- "name": "徽章制作",
- "web": "https://shields.io/",
- "tags": [
- "🐱Code",
- "♻︎图标"
- ],
- "brief": "提供各种服务的简洁、一致的易读徽章(badge、徽标)",
- "state": "正常"
- },
- {
- "name": "SIcon",
- "web": "https://simpleicons.org/",
- "tags": [
- "🐱Code",
- "♻︎图标"
- ],
- "brief": "SimpleIcons包含很多种流行品牌的免费 SVG 图标库",
- "state": "正常"
- },
- {
- "name": "Gmail",
- "web": "https://mail.google.com/mail/",
- "tags": [
- "📧邮箱"
- ],
- "brief": "谷歌邮箱",
- "state": "正常"
- },
- {
- "name": "Outlook",
- "web": "https://outlook.live.com/mail/",
- "tags": [
- "📧邮箱"
- ],
- "brief": "微软邮箱",
- "state": "正常"
- },
- {
- "name": "instagram",
- "web": "https://www.instagram.com/",
- "tags": [
- "👁️🗨️媒体"
- ],
- "brief": "一款Meta的社交媒体平台",
- "state": "正常"
- },
- {
- "name": "PH风格",
- "web": "https://logoly.pro/",
- "tags": [
- "⛹️♀️娱乐",
- "♻︎图标",
- "🖼️图片"
- ],
- "brief": "在线的 PornHub 风格 Logo 生成工具",
- "state": "正常"
- },
- {
- "name": "HomeBrew",
- "web": "https://brew.sh/index_zh-cn",
- "tags": [
- "🍎Apple",
- "🐱Code"
- ],
- "brief": "macOS(或 Linux)缺失的软件包的管理器",
- "state": "正常"
- },
- {
- "name": "MongoDB",
- "web": "https://cloud.mongodb.com/",
- "tags": [
- "🐱Code",
- "🔢数据"
- ],
- "brief": "一种高性能、可扩展和灵活的开源文档数据库管理系统",
- "state": "正常"
- },
- {
- "name": "开发者搜索",
- "web": "https://kaifa.baidu.com/",
- "tags": [
- "🐱Code",
- "🧠学习",
- "🔍搜索"
- ],
- "brief": "一个面向开发者的知识搜索平台",
- "state": "正常"
- },
- {
- "name": "网页存档",
- "web": "https://archive.ph/",
- "tags": [
- "📒笔记",
- "🔢数据"
- ],
- "brief": "将网页永久保存,即使原来的消失了,仍然可以通过存档查看网页内容",
- "state": "正常"
- },
- {
- "name": "阿里云盘",
- "web": "https://www.aliyundrive.com/",
- "tags": [
- "☁️云",
- "📦资源"
- ],
- "brief": "一款速度快、不打扰、够安全、易于分享的网盘",
- "state": "正常"
- },
- {
- "name": "TMDB",
- "web": "https://www.themoviedb.org/",
- "tags": [
- "🔢数据",
- "📺视频"
- ],
- "brief": "一个电影数据库网站",
- "state": "正常"
- },
- {
- "name": "Steam",
- "web": "https://store.steampowered.com/",
- "tags": [
- "🕹️游戏",
- "🏠主页"
- ],
- "brief": "一个游戏集合的官网",
- "state": "正常"
- },
- {
- "name": "Discord",
- "web": "https://discord.com/app/",
- "tags": [
- "✏️协作",
- "👁️🗨️媒体"
- ],
- "brief": "在这里,您可以轻而易举地每日谈天说地,时常消遣娱乐",
- "state": "正常"
- },
- {
- "name": "谷歌学术",
- "web": "https://scholar.google.com.hk/?hl=zh-CN",
- "tags": [
- "🧠学习",
- "🔍搜索"
- ],
- "brief": "轻松地大范围搜索学术文献",
- "state": "正常"
- },
- {
- "name": "微信读书",
- "web": "https://weread.qq.com/",
- "tags": [
- "🧠学习"
- ],
- "brief": "一个看书的网站",
- "state": "正常"
- },
- {
- "name": "代码高亮",
- "web": "http://word.wd1x.com/",
- "tags": [
- "🐱Code",
- "📒笔记"
- ],
- "brief": "在线生成可以在word/PPT中高亮的代码,支持各类主流语言在线着色",
- "state": "正常"
- },
- {
- "name": "Mac应用",
- "web": "https://decrypt.day/",
- "tags": [
- "🍎Apple",
- "🧰软件"
- ],
- "brief": "查找并下载最新解密的IPA应用程序",
- "state": "正常"
- },
- {
- "name": "Netlify",
- "web": "https://app.netlify.com/",
- "tags": [
- "🐱Code",
- "☁️云"
- ],
- "brief": "一个免服务器构建网页的网站",
- "state": "正常"
- },
- {
- "name": "Notion",
- "web": "https://www.notion.so/",
- "tags": [
- "✏️协作",
- "📒笔记",
- "✅效率"
- ],
- "brief": "一款功能强大的协作工具和笔记应用",
- "state": "正常"
- },
- {
- "name": "Slack",
- "web": "https://slack.com/",
- "tags": [
- "✏️协作",
- "✅效率"
- ],
- "brief": "一个团队协作的网站",
- "state": "正常"
- },
- {
- "name": "飞布API",
- "web": "https://www.fireboom.io/",
- "tags": [
- "🐱Code",
- "☁️云"
- ],
- "brief": "可视化API开发平台",
- "state": "正常"
- },
- {
- "name": "Caj2PDF",
- "web": "https://caj2pdf.cn/",
- "tags": [
- "⚙️转换",
- "🧠学习"
- ],
- "brief": "学术必备!!!",
- "state": "正常"
- },
- {
- "name": "DS可视化",
- "web": "https://visualgo.net/",
- "tags": [
- "🐱Code",
- "🧠学习"
- ],
- "brief": "数据结构和算法动态可视化",
- "state": "正常"
- },
- {
- "name": "CodeForces",
- "web": "https://codeforces.com/",
- "tags": [
- "🐱Code"
- ],
- "brief": "一个俄罗斯的刷题网站,有模拟竞赛",
- "state": "正常"
- },
- {
- "name": "字幕库",
- "web": "https://zmk.pw/",
- "tags": [
- "📦资源"
- ],
- "brief": "字幕下载网站",
- "state": "正常"
- },
- {
- "name": "国家统计局",
- "web": "http://www.stats.gov.cn/",
- "tags": [
- "🔢数据"
- ],
- "brief": "中国统计信息网",
- "state": "正常"
- },
- {
- "name": "任务清单",
- "web": "https://habitica.com/",
- "tags": [
- "✅效率"
- ],
- "brief": "用闯关的方式完成任务",
- "state": "正常"
- },
- {
- "name": "隔离食用手册",
- "web": "https://cook.yunyoujun.cn/",
- "tags": [
- "🔹其他"
- ],
- "brief": "多种多样的菜谱任你选择",
- "state": "正常"
- },
- {
- "name": "Jobs纪念馆",
- "web": "https://stevejobsarchive.com/",
- "tags": [
- "🍎Apple",
- "🔹其他"
- ],
- "brief": "乔布斯纪念网站",
- "state": "正常"
- },
- {
- "name": "中国色",
- "web": "http://zhongguose.com/",
- "tags": [
- "🪣色彩"
- ],
- "brief": "提供各种中国的传统颜色的名称,CMYK值,RGB值,16进制表示",
- "state": "正常"
- },
- {
- "name": "京东",
- "web": "https://www.jd.com/",
- "tags": [
- "🛒购物"
- ],
- "brief": "电商购物平台",
- "state": "正常"
- },
- {
- "name": "W32DI",
- "web": "https://win32diskimager.org/",
- "tags": [
- "🧰软件"
- ],
- "brief": "Win32DiskImager一个将原始磁盘映像写入可移动设备的程序",
- "state": "正常"
- },
- {
- "name": "推文图制作",
- "web": "https://poet.so/",
- "tags": [
- "🔧工具",
- "🖼️图片"
- ],
- "brief": "创造漂亮的推文图片",
- "state": "正常"
- },
- {
- "name": "轻松传",
- "web": "https://easychuan.cn/",
- "tags": [
- "📁文件"
- ],
- "brief": "轻松传文件到各种地方",
- "state": "正常"
- },
- {
- "name": "在线LaTeX",
- "web": "https://cn.overleaf.com/",
- "tags": [
- "🐱Code",
- "📒笔记"
- ],
- "brief": "在线 LaTeX 编辑器,无需安装,实时共享,版本控制,数百免费模板",
- "state": "正常"
- },
- {
- "name": "影视飓风",
- "web": "https://www.ysjf.com/index",
- "tags": [
- "🕊️up主",
- "🏠主页"
- ],
- "brief": "影视飓风官网",
- "state": "正常"
- },
- {
- "name": "Lightly",
- "web": "https://lightly.teamcode.com/",
- "tags": [
- "🐱Code",
- "☁️云"
- ],
- "brief": "在线编译工具,免费用户500Mb内存",
- "state": "正常"
- },
- {
- "name": "ChatGPT",
- "web": "https://chat.openai.com/",
- "tags": [
- "🤖AI"
- ],
- "brief": "OpenAi做的智能助手",
- "state": "正常"
- },
- {
- "name": "小红书创作",
- "web": "https://creator.xiaohongshu.com",
- "tags": [
- "👁️🗨️媒体"
- ],
- "brief": "小红书后台",
- "state": "正常"
- },
- {
- "name": "小米有品",
- "web": "https://www.xiaomiyoupin.com/",
- "tags": [
- "🛒购物"
- ],
- "brief": "小米有品,购物平台",
- "state": "正常"
- },
- {
- "name": "网易新闻",
- "web": "https://news.163.com/",
- "tags": [
- "🗞️新闻"
- ],
- "brief": "包含各种新闻的门户网站",
- "state": "正常"
- },
- {
- "name": "Pixabay",
- "web": "https://pixabay.com/",
- "tags": [
- "🖼️图片",
- "📦资源"
- ],
- "brief": "令人惊叹的免费图片和免版税库存",
- "state": "正常"
- },
- {
- "name": "Horizons",
- "web": "https://yx.g8hh.com/heart-of-galaxy-horizons/",
- "tags": [
- "🕹️游戏"
- ],
- "brief": "一款图文并茂的网页游戏",
- "state": "正常"
- },
- {
- "name": "谷歌",
- "web": "https://www.google.com/",
- "tags": [
- "🔍搜索"
- ],
- "brief": "需要魔法才能用的检索工具",
- "state": "正常"
- },
- {
- "name": "Github",
- "web": "https://github.com/",
- "tags": [
- "🐱Code",
- "✏️协作",
- "☁️云"
- ],
- "brief": "存代码的地方",
- "state": "正常"
- },
- {
- "name": "全球logo",
- "web": "https://www.logonews.cn/",
- "tags": [
- "🖼️图片",
- "📦资源"
- ],
- "brief": "logo情报网站",
- "state": "正常"
- },
- {
- "name": "爱给网",
- "web": "https://www.aigei.com/",
- "tags": [
- "🎵音频",
- "📦资源",
- "📺视频"
- ],
- "brief": "中国最大的数字娱乐免费素材下载网站",
- "state": "正常"
- },
- {
- "name": "学习通",
- "web": "https://i.chaoxing.com/",
- "tags": [
- "🧠学习"
- ],
- "brief": "网课学习",
- "state": "正常"
- },
- {
- "name": "微博",
- "web": "https://weibo.com/",
- "tags": [
- "👁️🗨️媒体"
- ],
- "brief": "国内最大的媒体",
- "state": "正常"
- },
- {
- "name": "ChatExcel",
- "web": "https://chatexcel.com/",
- "tags": [
- "🤖AI"
- ],
- "brief": "仅通过聊天来操控您的Excel表格",
- "state": "正常"
- },
- {
- "name": "猜中国省份",
- "web": "https://vultr.youmu.moe/quiz/",
- "tags": [
- "⛹️♀️娱乐"
- ],
- "brief": "你对我们的国家熟悉嘛?",
- "state": "正常"
- },
- {
- "name": "知乎",
- "web": "https://www.zhihu.com/",
- "tags": [
- "🧠学习",
- "👁️🗨️媒体"
- ],
- "brief": "看看别人怎么说?",
- "state": "正常"
- },
- {
- "name": "Wordle",
- "web": "https://www.nytimes.com/games/wordle/index.html",
- "tags": [
- "🕹️游戏"
- ],
- "brief": "很好玩的填字游戏",
- "state": "正常"
- },
- {
- "name": "哔哩哔哩",
- "web": "https://www.bilibili.com/",
- "tags": [
- "📺视频",
- "👁️🗨️媒体"
- ],
- "brief": "一个看视频的网站",
- "state": "正常"
- },
- {
- "name": "软件目录",
- "web": "https://www.yuque.com/books/share/ec226b31-5272-4792-811b-c22334cf0a9a?#%20%E3%80%8A%E8%BD%AF%E4%BB%B6%E7%9B%AE%E5%BD%95%E3%80%8B",
- "tags": [
- "🧰软件"
- ],
- "brief": "一些付费软件的免费安装包",
- "state": "正常"
- },
- {
- "name": "itellyou",
- "web": "https://next.itellyou.cn/",
- "tags": [
- "🧰软件"
- ],
- "brief": "操作系统镜像|windows|linux",
- "state": "正常"
- },
- {
- "name": "羽享平台",
- "web": "http://yuzhuyi.ysepan.com/",
- "tags": [
- "🧠学习",
- "📦资源",
- "🧰软件"
- ],
- "brief": "各种资源的网页",
- "state": "正常"
- },
- {
- "name": "花生壳",
- "web": "https://hsk.oray.com/",
- "tags": [
- "☁️云"
- ],
- "brief": "提供内网穿透和动态域名解析服务,支持外网访问内网服务器",
- "state": "正常"
- },
- {
- "name": "Vercel",
- "web": "https://vercel.com/",
- "tags": [
- "🐱Code",
- "☁️云"
- ],
- "brief": "搭建网站",
- "state": "正常"
- },
- {
- "name": "Youtube",
- "web": "https://www.youtube.com/",
- "tags": [
- "📺视频"
- ],
- "brief": "需要魔法才能访问的视频平台",
- "state": "正常"
- },
- {
- "name": "Logo制作",
- "web": "https://www.designevo.com/cn",
- "tags": [
- "🔧工具",
- "♻︎图标"
- ],
- "brief": "一款专业制作Logo的免费软件",
- "state": "正常"
- },
- {
- "name": "全渠道搜索",
- "web": "http://dir.scmor.com/",
- "tags": [
- "🔍搜索",
- "🔧工具"
- ],
- "brief": "各种搜索渠道",
- "state": "正常"
- },
- {
- "name": "阿里云",
- "web": "https://www.aliyun.com/",
- "tags": [
- "☁️云"
- ],
- "brief": "阿里云平台,图床服务",
- "state": "正常"
- },
- {
- "name": "耳聆网",
- "web": "https://www.ear0.com/",
- "tags": [
- "🎵音频",
- "📦资源"
- ],
- "brief": "提供全面的声音资源和版权保护机制,满足各方面音频素材需求",
- "state": "正常"
- },
- {
- "name": "Phind",
- "web": "https://phind.com/",
- "tags": [
- "🔍搜索",
- "🐱Code"
- ],
- "brief": "面向程序员的搜索引擎",
- "state": "正常"
- },
- {
- "name": "爱奇艺体育",
- "web": "https://ssports.iqiyi.com/",
- "tags": [
- "📺视频"
- ],
- "brief": "中国知名的体育赛事平台",
- "state": "正常"
- },
- {
- "name": "擦除画面",
- "web": "https://www.magiceraser.io/",
- "tags": [
- "🖼️图片",
- "🔧工具"
- ],
- "brief": "可以去背景",
- "state": "正常"
- },
- {
- "name": "测速网",
- "web": "https://www.speedtest.cn/",
- "tags": [
- "🕸️网络",
- "🔧工具"
- ],
- "brief": "你的网速怎么样?",
- "state": "正常"
- },
- {
- "name": "QQ邮箱",
- "web": "https://mail.qq.com",
- "tags": [
- "📧邮箱"
- ],
- "brief": "腾讯邮箱",
- "state": "正常"
- },
- {
- "name": "-LKs-",
- "web": "http://lkssite.vip/",
- "tags": [
- "🕊️up主"
- ],
- "brief": "一个墨镜区up做的网址大全",
- "state": "正常"
- },
- {
- "name": "打字网站",
- "web": "https://dazidazi.com/",
- "tags": [
- "⛹️♀️娱乐"
- ],
- "brief": "一个up主做的打字网站",
- "state": "正常"
- },
- {
- "name": "芒果商城",
- "web": "https://www.mgidshop.com/",
- "tags": [
- "🍎Apple",
- "🛒购物"
- ],
- "brief": "购买日区美区小火箭、美区苹果ID",
- "state": "正常"
- },
- {
- "name": "据义查句",
- "web": "https://wantquotes.net/",
- "tags": [
- "🧠学习",
- "🔧工具"
- ],
- "brief": "根据意思来查找名人名言",
- "state": "正常"
- },
- {
- "name": "微信公众",
- "web": "https://mp.weixin.qq.com/",
- "tags": [
- "👁️🗨️媒体"
- ],
- "brief": "公众号和小程序的后台",
- "state": "正常"
- },
- {
- "name": "飞桨",
- "web": "https://aistudio.baidu.com/aistudio/index",
- "tags": [
- "🐱Code",
- "☁️云"
- ],
- "brief": "一个强大且易用的开源深度学习平台",
- "state": "正常"
- },
- {
- "name": "Pexels",
- "web": "https://www.pexels.com/zh-cn/",
- "tags": [
- "🖼️图片",
- "📦资源"
- ],
- "brief": "摄影作者在这里免费分享最精彩的素材图片和视频",
- "state": "正常"
- },
- {
- "name": "Git文档",
- "web": "https://gitee.com/progit/index.html",
- "tags": [
- "🐱Code",
- "🧠学习",
- "📒笔记"
- ],
- "brief": "快来学习Git!",
- "state": "正常"
- },
- {
- "name": "SpellingBee",
- "web": "https://www.nytimes.com/puzzles/spelling-bee",
- "tags": [
- "🕹️游戏"
- ],
- "brief": "很难的凑字游戏",
- "state": "正常"
- },
- {
- "name": "sojson在线",
- "web": "https://www.sojson.com/",
- "tags": [
- "⚙️转换"
- ],
- "brief": "json转换为其他的格式",
- "state": "正常"
- },
- {
- "name": "FirstWeb",
- "web": "http://info.cern.ch/",
- "tags": [
- "🔹其他"
- ],
- "brief": "万维网第一个网页",
- "state": "正常"
- },
- {
- "name": "格式转换",
- "web": "https://www.aconvert.com/cn/",
- "tags": [
- "⚙️转换"
- ],
- "brief": "内含多种格式转换",
- "state": "正常"
- },
- {
- "name": "青柠起始页",
- "web": "https://limestart.cn/",
- "tags": [
- "🏠主页"
- ],
- "brief": "一个up主做的起始页,很精美",
- "state": "正常"
- },
- {
- "name": "AppleStore",
- "web": "https://www.apple.com.cn/retail/storelist/",
- "tags": [
- "🍎Apple",
- "🛒购物"
- ],
- "brief": "中国苹果直营店位置",
- "state": "正常"
- },
- {
- "name": "猫啃网",
- "web": "https://www.maoken.com/",
- "tags": [
- "📦资源"
- ],
- "brief": "最新最全的可免费商用中文字体下载网站",
- "state": "正常"
- },
- {
- "name": "钢笔工具",
- "web": "https://bezier.method.ac/",
- "tags": [
- "⛹️♀️娱乐"
- ],
- "brief": "一个帮助你熟练掌握钢笔工具的网站",
- "state": "正常"
- },
- {
- "name": "今日头条",
- "web": "https://www.toutiao.com/",
- "tags": [
- "👁️🗨️媒体"
- ],
- "brief": "字节跳动旗下文字和视频网站",
- "state": "正常"
- },
- {
- "name": "亚马逊",
- "web": "https://www.amazon.cn/",
- "tags": [
- "🛒购物"
- ],
- "brief": "全球购物平台",
- "state": "正常"
- },
- {
- "name": "比特虫.ico",
- "web": "https://www.bitbug.net/",
- "tags": [
- "♻︎图标",
- "✒️设计",
- "⚙️转换"
- ],
- "brief": "制作网站图标的网站",
- "state": "正常"
- },
- {
- "name": "油管解析",
- "web": "https://fotoun.com/?p=161",
- "tags": [
- "🔧工具",
- "📺视频"
- ],
- "brief": "YouTube视频在线解析网站",
- "state": "正常"
- },
- {
- "name": "monkeytype",
- "web": "https://monkeytype.com/",
- "tags": [
- "⛹️♀️娱乐"
- ],
- "brief": "练习打字的网站",
- "state": "正常"
- },
- {
- "name": "Unsplash",
- "web": "https://unsplash.com/",
- "tags": [
- "🖼️图片",
- "📦资源"
- ],
- "brief": "互联网的视觉资源,由各地的创作者提供支持",
- "state": "正常"
- },
- {
- "name": "知到",
- "web": "https://www.zhihuishu.com/",
- "tags": [
- "🧠学习"
- ],
- "brief": "网课平台",
- "state": "正常"
- },
- {
- "name": "密码测试",
- "web": "https://www.passwordmonster.com/",
- "tags": [
- "🔧工具",
- "⛹️♀️娱乐"
- ],
- "brief": "测试密码安全程度",
- "state": "正常"
- },
- {
- "name": "油管封面",
- "web": "https://www.strerr.com/index.html",
- "tags": [
- "🔧工具",
- "🖼️图片"
- ],
- "brief": "提供油管封面预览和下载功能",
- "state": "正常"
- },
- {
- "name": "Apple.cn",
- "web": "https://www.apple.com.cn/",
- "tags": [
- "🍎Apple"
- ],
- "brief": "一个伟大公司的官网",
- "state": "正常"
- },
- {
- "name": "食物图片",
- "web": "https://www.foodiesfeed.com/",
- "tags": [
- "🖼️图片",
- "📦资源"
- ],
- "brief": "搜索超过1802张免费美食照片",
- "state": "正常"
- },
- {
- "name": "网易邮箱",
- "web": "https://mail.163.com/",
- "tags": [
- "📧邮箱"
- ],
- "brief": "网易邮箱163、126",
- "state": "正常"
- },
- {
- "name": "赛博耶稣",
- "web": "https://yesu.ink/",
- "tags": [
- "🤖AI"
- ],
- "brief": "一个配备有ChatGPT的耶稣陪伴在您的身边",
- "state": "正常"
- },
- {
- "name": "图寻",
- "web": "https://tuxun.fun/",
- "tags": [
- "⛹️♀️娱乐"
- ],
- "brief": "探索真实世界,收集线索,找出自己的位置",
- "state": "正常"
- },
- {
- "name": "Potplayer",
- "web": "https://potplayer.daum.net/",
- "tags": [
- "🧰软件"
- ],
- "brief": "贼好用的win播放器",
- "state": "正常"
- },
- {
- "name": "汉兜",
- "web": "https://handle.antfu.me/",
- "tags": [
- "🕹️游戏"
- ],
- "brief": "汉字猜字游戏",
- "state": "正常"
- },
- {
- "name": "世界名画",
- "web": "https://www.nbfox.com/",
- "tags": [
- "🖼️图片",
- "📦资源"
- ],
- "brief": "高清著名画作",
- "state": "正常"
- },
- {
- "name": "ChatMind",
- "web": "https://www.chatmind.tech/",
- "tags": [
- "🤖AI"
- ],
- "brief": "AI生成思维导图的效率工具, 为用户提供智能化思维导图方案",
- "state": "正常"
- },
- {
- "name": "找鼠标",
- "web": "https://pointerpointer.com/",
- "tags": [
- "⛹️♀️娱乐"
- ],
- "brief": "你的鼠标在哪都能被找到",
- "state": "正常"
- },
- {
- "name": "腾讯云",
- "web": "https://cloud.tencent.com/",
- "tags": [
- "☁️云"
- ],
- "brief": "腾讯云平台,云主机",
- "state": "正常"
- },
- {
- "name": "图标库",
- "web": "https://www.iconfont.cn/",
- "tags": [
- "♻︎图标",
- "✒️设计"
- ],
- "brief": "可以找到很多官方图标",
- "state": "正常"
- },
- {
- "name": "离谱相关性",
- "web": "http://tylervigen.com/spurious-correlations",
- "tags": [
- "⛹️♀️娱乐",
- "🔹其他"
- ],
- "brief": "什么是离谱的呢?",
- "state": "正常"
- },
- {
- "name": "连通性检验",
- "web": "https://ip.skk.moe/",
- "tags": [
- "🕸️网络",
- "🔧工具"
- ],
- "brief": "检测你的电脑是否能连接一些节点",
- "state": "正常"
- },
- {
- "name": "UU在线工具",
- "web": "https://uutool.cn/",
- "tags": [
- "🔧工具"
- ],
- "brief": "很多的工具",
- "state": "正常"
- },
- {
- "name": "淘宝",
- "web": "https://www.taobao.com/",
- "tags": [
- "🛒购物"
- ],
- "brief": "买!买!买!",
- "state": "正常"
- },
- {
- "name": "80S",
- "web": "https://www.80sgod.com/",
- "tags": [
- "📺视频"
- ],
- "brief": "提供最新高清MP4电影,电视剧,动漫下载.采用迅雷磁力链方式下载",
- "state": "正常"
- },
- {
- "name": "油猴脚本",
- "web": "https://greasyfork.org/zh-CN",
- "tags": [
- "🔧工具",
- "🧰软件"
- ],
- "brief": "这里是一个提供用户脚本的网站",
- "state": "正常"
- },
- {
- "name": "DeepL",
- "web": "https://www.deepl.com/translator",
- "tags": [
- "🧠学习"
- ],
- "brief": "一个很好用的翻译网站",
- "state": "正常"
- },
- {
- "name": "国外手机号",
- "web": "https://sms-activate.org",
- "tags": [
- "🔧工具"
- ],
- "brief": "虚拟号码来在线接受短信",
- "state": "正常"
- },
- {
- "name": "Kaggle",
- "web": "https://www.kaggle.com/",
- "tags": [
- "🔢数据",
- "🧠学习"
- ],
- "brief": "找一些成品的数据文件以及其他开发者对数据的处理",
- "state": "正常"
- },
- {
- "name": "视频号",
- "web": "https://channels.weixin.qq.com/",
- "tags": [
- "👁️🗨️媒体"
- ],
- "brief": "微信视频号",
- "state": "正常"
- },
- {
- "name": "在线剪视频",
- "web": "https://online-video-cutter.com/cn/",
- "tags": [
- "🔧工具",
- "📺视频"
- ],
- "brief": "从任何在线视频中剪切片段",
- "state": "正常"
- },
- {
- "name": "拼接音视频",
- "web": "https://maple3142.github.io/mergemp4/",
- "tags": [
- "🔧工具",
- "👁️🗨️媒体"
- ],
- "brief": "将音频和视频拼到一起(不负责对齐)",
- "state": "正常"
- },
- {
- "name": "赛博佛祖",
- "web": "https://fozu.ink/",
- "tags": [
- "🤖AI"
- ],
- "brief": "一个配备有ChatGPT的佛陪伴在您的身边",
- "state": "正常"
- },
- {
- "name": "MD排版",
- "web": "https://md.guozh.net/",
- "tags": [
- "⚙️转换",
- "📒笔记"
- ],
- "brief": "让markdown可以很好的发在公众号上",
- "state": "正常"
- },
- {
- "name": "谷歌翻译",
- "web": "https://translate.google.com/",
- "tags": [
- "🧠学习"
- ],
- "brief": "(也许)需要魔法才能用的翻译工具",
- "state": "正常"
- },
- {
- "name": "即时工具",
- "web": "https://www.67tool.com/",
- "tags": [
- "🔧工具"
- ],
- "brief": "一些工具",
- "state": "正常"
- },
- {
- "name": "Jetbrains",
- "web": "https://www.jetbrains.com/zh-cn/",
- "tags": [
- "🐱Code",
- "🧰软件",
- "🏠主页"
- ],
- "brief": "为专业人士和团队制作开发者工具",
- "state": "正常"
- },
- {
- "name": "新榜",
- "web": "https://newrank.cn/",
- "tags": [
- "👁️🗨️媒体"
- ],
- "brief": "更多更好的KOL自媒体,品效合一的传播销售方案,尽在新榜",
- "state": "正常"
- },
- {
- "name": "耳机评测站",
- "web": "https://www.woodenears.com/",
- "tags": [
- "📱数码"
- ],
- "brief": "耳机测评网站",
- "state": "正常"
- },
- {
- "name": "图司机",
- "web": "https://www.tusij.com/",
- "tags": [
- "🖼️图片",
- "✒️设计"
- ],
- "brief": "简单修图网页",
- "state": "正常"
- },
- {
- "name": "OTP",
- "web": "https://otp.landian.vip/zh-cn/",
- "tags": [
- "🧰软件",
- "🔧工具"
- ],
- "brief": "OfficeToolPlus软件的工具网页",
- "state": "正常"
- },
- {
- "name": "ChatDoc",
- "web": "https://chatdoc.com/chatdoc/#/upload",
- "tags": [
- "🤖AI"
- ],
- "brief": "一个文件阅读助手,可以快速从文档中提取、定位和汇总信息",
- "state": "正常"
- },
- {
- "name": "壁纸",
- "web": "https://wallhaven.cc/",
- "tags": [
- "🖼️图片",
- "📦资源"
- ],
- "brief": "好看高清壁纸",
- "state": "正常"
- },
- {
- "name": "慕课",
- "web": "https://www.icourse163.org/",
- "tags": [
- "🧠学习"
- ],
- "brief": "网课,内含很多精品公开课",
- "state": "正常"
- },
- {
- "name": "知网",
- "web": "https://www.cnki.net/",
- "tags": [
- "🧠学习",
- "📦资源"
- ],
- "brief": "面向读者提供各类学术资源统一检索、统一导航、在线阅读和下载服务",
- "state": "正常"
- },
- {
- "name": "Gitee",
- "web": "https://gitee.com/",
- "tags": [
- "🐱Code",
- "☁️云",
- "✏️协作"
- ],
- "brief": "存代码用的,国内访问很快",
- "state": "正常"
- },
- {
- "name": "Typora",
- "web": "https://www.typoraio.cn/",
- "tags": [
- "📒笔记"
- ],
- "brief": "一款 Markdown 编辑器和阅读器",
- "state": "正常"
- },
- {
- "name": "流程图导图",
- "web": "https://www.processon.com/",
- "tags": [
- "🖼️图片",
- "🧠学习"
- ],
- "brief": "流程清晰可见",
- "state": "正常"
- },
- {
- "name": "进化",
- "web": "https://evolve.g8hh.com/",
- "tags": [
- "🕹️游戏"
- ],
- "brief": "从原生质开始,逐步解锁高级生命形式,开启属于自己的文明",
- "state": "正常"
- },
- {
- "name": "一网一匠",
- "web": "https://ywyj.cn/",
- "tags": [
- "🔧工具",
- "🕊️up主"
- ],
- "brief": "一个up主叫一网一匠做的主页",
- "state": "正常"
- },
- {
- "name": "PY标准库",
- "web": "https://docs.python.org/zh-cn/3/library/",
- "tags": [
- "🐱Code",
- "🧠学习"
- ],
- "brief": "语言参考手册描述了Python的语法和语义,库参考则介绍了Python标准库",
- "state": "正常"
- },
- {
- "name": "W3school",
- "web": "https://www.w3school.com.cn/",
- "tags": [
- "🧠学习"
- ],
- "brief": "全球最大的中文 Web 技术教程",
- "state": "正常"
- },
- {
- "name": "cal计算器",
- "web": "https://www.calculator.net/calorie-calculator.html",
- "tags": [
- "🔧工具"
- ],
- "brief": "估算每天需要摄入的卡路里数量,以维持、减重或增重",
- "state": "正常"
- },
- {
- "name": "重开模拟器",
- "web": "https://liferestart.syaro.io/public/index.html",
- "tags": [
- "🕹️游戏"
- ],
- "brief": "如果能重来~",
- "state": "正常"
- },
- {
- "name": "空投",
- "web": "https://airportal.cn/",
- "tags": [
- "📁文件"
- ],
- "brief": "快速传文件",
- "state": "正常"
- },
- {
- "name": "少数派",
- "web": "https://sspai.com/",
- "tags": [
- "📱数码",
- "👁️🗨️媒体",
- "🗞️新闻"
- ],
- "brief": "写文字的平台,数码科技相关",
- "state": "正常"
- },
- {
- "name": "ChatPDF",
- "web": "https://www.chatpdf.com/",
- "tags": [
- "🤖AI"
- ],
- "brief": "ChatPDF是一种快速简便的方法,可以与任何PDF文件进行对话",
- "state": "正常"
- },
- {
- "name": "SQLKiller",
- "web": "https://www.sqlkiller.com/",
- "tags": [
- "🤖AI"
- ],
- "brief": "直接描述你的取数需求,一键生成SQL",
- "state": "正常"
- },
- {
- "name": "X",
- "web": "https://twitter.com/",
- "tags": [
- "👁️🗨️媒体"
- ],
- "brief": "国外媒体,已被马斯克收购",
- "state": "正常"
- },
- {
- "name": "播客搜索",
- "web": "https://pod.link/",
- "tags": [
- "🔧工具",
- "🎵音频"
- ],
- "brief": "搜索播客的网站",
- "state": "正常"
- },
- {
- "name": "CSDN",
- "web": "https://www.csdn.net/",
- "tags": [
- "🐱Code",
- "🔍搜索"
- ],
- "brief": "代码有关的问题来问我",
- "state": "正常"
- },
- {
- "name": "Topbook",
- "web": "https://topbook.cc/overview",
- "tags": [
- "🕊️up主",
- "🏠主页",
- "✅效率"
- ],
- "brief": "一个百科全书",
- "state": "正常"
- },
- {
- "name": "XFastest",
- "web": "https://news.xfastest.com/",
- "tags": [
- "🗞️新闻"
- ],
- "brief": "香港科技新闻网站",
- "state": "正常"
- }
-]
\ No newline at end of file
diff --git a/public/css/style.css b/public/css/style.css
index c649e9f..6254abb 100644
--- a/public/css/style.css
+++ b/public/css/style.css
@@ -1,7 +1,8 @@
-@import url('https://cdn.jsdelivr.net/npm/cn-fontsource-smiley-sans-oblique-regular@1.0.1/font.min.css');
-@import url('https://npm.elemecdn.com/lxgw-wenkai-webfont@1.6.0/style.css');
-@import url('https://jhlst.nowscott.top/result.css');
-@import url('https://zqfs.nowscott.top/result.css');
+@import url('https://chinese-fonts-cdn.deno.dev/chinesefonts3/packages/dyh/dist/SmileySans-Oblique/result.css');
+@import url('https://chinese-fonts-cdn.deno.dev/chinesefonts3/packages/lxgwwenkai/dist/LXGWWenKai-Regular/result.css');
+@import url('https://chinese-fonts-cdn.deno.dev/chinesefonts3/packages/jhlst/dist/京華老宋体v1_007/result.css');
+@import url('https://chinese-fonts-cdn.deno.dev/chinesefonts3/packages/mzxst/dist/MZPXorig/result.css');
+@import url('https://chinese-fonts-cdn.deno.dev/chinesefonts3/packages/lxgwmanhei/dist/LXGWMarkerGothic/result.css');
* {
margin: 0;
diff --git a/public/image/favicon.ico b/public/images/favicon.ico
similarity index 100%
rename from public/image/favicon.ico
rename to public/images/favicon.ico
diff --git a/public/index.html b/public/index.html
deleted file mode 100644
index a09772b..0000000
--- a/public/index.html
+++ /dev/null
@@ -1,50 +0,0 @@
-
-
-
-
-
-
-
-
- 网站索引
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
筛选网页
-
-
-
-
-
\ No newline at end of file
diff --git a/public/js/context-menu.js b/public/js/context-menu.js
deleted file mode 100644
index 4c311c9..0000000
--- a/public/js/context-menu.js
+++ /dev/null
@@ -1,91 +0,0 @@
-// 字体列表
-const fonts = ['Smiley Sans Oblique', 'LXGW WenKai', 'Zhuque Fangsong', 'KingHwa_OldSong'];
-const fontnames = ['得意黑', '霞鹜文楷', '朱雀仿宋', '京華老宋体'];
-
-function populateContextMenu() {
- const menu = document.getElementById('customContextMenu').querySelector('ul');
- menu.innerHTML = ''; // 清空现有的菜单项,防止重复添加
-
- fonts.forEach((font, index) => {
- let li = document.createElement('li');
- li.textContent = fontnames[index]; // 显示中文字体名
- li.style.cursor = 'pointer';
- li.style.fontFamily = font; // 设置每个字体选项的字体样式
- li.onclick = () => {
- changeFont(font); // 调用更改字体的函数
- };
- menu.appendChild(li);
- });
-}
-
-
-function changeFont(font) {
- document.documentElement.style.setProperty('--main-font-family', `"${font}"`);
- setCookie('userFont', font, 7); // 更新Cookie,持续7天
- updateMenuSelection(font); // 更新菜单选择状态
- document.getElementById('customContextMenu').style.display = 'none'; // 隐藏菜单
-}
-
-function updateMenuSelection(selectedFont) {
- const items = document.querySelectorAll('#customContextMenu li');
- items.forEach(item => {
- if (item.textContent.trim() === fontnames[fonts.indexOf(selectedFont)]) { // 使用正确的友好名称进行比较
- item.classList.add('selected-font');
- } else {
- item.classList.remove('selected-font');
- }
- });
-}
-
-
-
-document.addEventListener('DOMContentLoaded', function() {
- populateContextMenu(); // 填充右键菜单
- loadFont(); // 加载用户之前选择的字体
-});
-
-// 处理右键菜单事件
-document.addEventListener('contextmenu', function (event) {
- event.preventDefault();
- var contextMenu = document.getElementById('customContextMenu');
- contextMenu.style.display = 'block';
- contextMenu.style.left = event.pageX + 'px';
- contextMenu.style.top = event.pageY + 'px';
-});
-
-// 处理点击事件,隐藏自定义的右键菜单
-document.addEventListener('click', function (event) {
- var contextMenu = document.getElementById('customContextMenu');
- if (event.target.offsetParent !== contextMenu) {
- contextMenu.style.display = 'none';
- }
-});
-
-function setCookie(name, value, days) {
- var expires = "";
- if (days) {
- var date = new Date();
- date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
- expires = "; expires=" + date.toUTCString();
- }
- document.cookie = name + "=" + (value || "") + expires + "; path=/";
-}
-
-function getCookie(name) {
- var nameEQ = name + "=";
- var ca = document.cookie.split(';');
- for (var i = 0; i < ca.length; i++) {
- var c = ca[i];
- while (c.charAt(0) == ' ') c = c.substring(1, c.length);
- if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length, c.length);
- }
- return null;
-}
-
-function loadFont() {
- var userFont = getCookie('userFont');
- if (userFont) {
- document.documentElement.style.setProperty('--main-font-family', userFont);
- updateMenuSelection(userFont); // 更新菜单选择状态
- }
-}
diff --git a/public/js/data-loader.js b/public/js/data-loader.js
deleted file mode 100644
index 850d094..0000000
--- a/public/js/data-loader.js
+++ /dev/null
@@ -1,119 +0,0 @@
-window.onload = function () {
- var sources, taglist = [], onlist = [], reslist = [];
-
- function randomSort(arr) {
- for (let i = 0, l = arr.length; i < l; i++) {
- let rc = parseInt(Math.random() * l);
- const empty = arr[i];
- arr[i] = arr[rc];
- arr[rc] = empty;
- }
- return arr;
- }
-
- function unique(arr) { return Array.from(new Set(arr)); }
-
- function renderWebs(list) {
- for (let l in list) {
- var a = document.createElement('a');
- a.id = 'web';
- a.href = list[l].web;
- a.target = '_blank';
- a.innerHTML = list[l].name;
- a.title = list[l].brief;
- document.getElementById('webs-container').appendChild(a);
- }
- }
-
- function renderTags(tags) {
- document.getElementById('tags-container').innerHTML = ''; // 清空旧标签以重新渲染
- tags.forEach((tag, index) => {
- var button = document.createElement('button');
- button.id = 'tag' + index;
- button.innerHTML = tag;
- // 设置按钮的类名基于是否被选中
- button.className = onlist.includes(tag) ? 'tag on' : 'tag off';
- document.getElementById('tags-container').appendChild(button);
- button.onclick = () => toggleTagButton(button.id);
- });
- }
-
- function toggleTagButton(buttonId) {
- var button = document.getElementById(buttonId);
- var tagText = button.textContent;
- var tagIndex = onlist.indexOf(tagText);
-
- if (tagIndex === -1) {
- onlist.push(tagText); // 添加到选中列表
- } else {
- onlist.splice(tagIndex, 1); // 从选中列表移除
- }
-
- button.className = button.className === 'tag off' ? 'tag on' : 'tag off';
- updateResults(); // 更新结果和标签列表
- }
-
- function updateResults() {
- reslist = sources.filter(source => onlist.every(tag => source.tags.includes(tag)));
- document.getElementById('webs-container').innerHTML = reslist.length > 0 ? '' : '未找到符合条件的网页';
- renderWebs(randomSort(unique(reslist)));
-
- // 更新标签列表,将选中的标签放在前面
- let availableTags = [];
- reslist.forEach(source => {
- source.tags.forEach(tag => {
- if (!availableTags.includes(tag)) {
- availableTags.push(tag);
- }
- });
- });
-
- onlist.forEach(tag => {
- const index = availableTags.indexOf(tag);
- if (index > -1) {
- availableTags.splice(index, 1);
- }
- });
-
- const sortedTags = onlist.concat(availableTags.filter(tag => !onlist.includes(tag)));
- renderTags(sortedTags);
- }
-
- function searchFunction() {
- var keyword = document.getElementById('s-in').value.toLowerCase();
- reslist = sources.filter(source =>
- source.name.toLowerCase().includes(keyword) ||
- source.brief.toLowerCase().includes(keyword) ||
- source.tags.some(tag => tag.toLowerCase().includes(keyword))
- );
- document.getElementById('webs-container').innerHTML = reslist.length > 0 ? '' : '未找到符合条件的网页';
- renderWebs(randomSort(unique(reslist)));
- }
-
- function extractAndRenderTags(sources) {
- let taglist = [];
- sources.forEach(source => {
- source.tags.forEach(tag => {
- if (!taglist.includes(tag)) {
- taglist.push(tag);
- }
- });
- });
- taglist = randomSort(unique(taglist)); // 随机排序并去重标签列表
- renderTags(taglist); // 渲染标签列表
- }
-
- fetch("/assets/data.json") // 从服务器上获取数据
- .then(response => response.json())
- .then(data => {
- sources = data; // 存储数据源
- renderWebs(randomSort(unique(sources))); // 初始渲染网页列表
- extractAndRenderTags(sources); // 使用封装后的函数处理和渲染标签
- document.getElementById('s-btn').onclick = searchFunction; // 绑定搜索按钮的点击事件
- document.addEventListener('keydown', event => {
- if (event.keyCode === 13) {
- document.getElementById('s-btn').click();
- }
- });
- });
-}
diff --git a/public/js/main.js b/public/js/main.js
deleted file mode 100644
index e98c977..0000000
--- a/public/js/main.js
+++ /dev/null
@@ -1,23 +0,0 @@
-if ('serviceWorker' in navigator) {
- window.addEventListener('load', () => {
- navigator.serviceWorker.register('/service-worker.js').then(registration => {
- registration.onupdatefound = () => {
- const installingWorker = registration.installing;
- installingWorker.onstatechange = () => {
- if (installingWorker.state === 'installed') {
- if (navigator.serviceWorker.controller) {
- // 新内容已下载,用户需要重新加载页面以获取更新
- if (confirm('新版本已更新,是否立即刷新页面?')) {
- window.location.reload();
- }
- } else {
- console.log('Content is now available offline!');
- }
- }
- };
- };
- }).catch(error => {
- console.log('Service Worker registration failed:', error);
- });
- });
-}
diff --git a/public/js/theme.js b/public/js/theme.js
deleted file mode 100644
index 0721c25..0000000
--- a/public/js/theme.js
+++ /dev/null
@@ -1,65 +0,0 @@
-document.addEventListener('DOMContentLoaded', function () {
- var currentTime = new Date(); // 创建一个 Date 对象
- var currentHour = currentTime.getHours(); // 获取当前时间(小时)
-
- var dark_mode = document.getElementById('darkcss');
- var dark_mode_icon = document.getElementById('icon');
- var dark_mode_btn = document.getElementById('darkbtn');
-
- // 读取 cookie 中的模式设置
- var userPref = getCookie('themeMode');
-
- if (userPref) {
- applyTheme(userPref);
- } else {
- // 如果没有用户偏好设置,根据时间自动切换模式
- if (currentHour >= 22 || currentHour < 8) {
- applyTheme('dark');
- } else {
- applyTheme('daytime');
- }
- }
-
- dark_mode_btn.onclick = function () {
- var newTheme = (dark_mode_btn.className === 'daytime') ? 'dark' : 'daytime';
- applyTheme(newTheme);
- setCookie('themeMode', newTheme, 12); // 设置 cookie,有效期为 12 小时
- }
-});
-
-function applyTheme(theme) {
- var dark_mode = document.getElementById('darkcss');
- var dark_mode_icon = document.getElementById('icon');
- var dark_mode_btn = document.getElementById('darkbtn');
-
- if (theme === 'dark') {
- dark_mode.href = "/css/dark.css";
- dark_mode_icon.src = 'assets/svg/sun.svg';
- dark_mode_btn.className = 'dark';
- } else {
- dark_mode.href = "/css/daytime.css";
- dark_mode_icon.src = 'assets/svg/moon.svg';
- dark_mode_btn.className = 'daytime';
- }
-}
-
-function setCookie(name, value, hours) {
- var expires = "";
- if (hours) {
- var date = new Date();
- date.setTime(date.getTime() + (hours * 60 * 60 * 1000));
- expires = "; expires=" + date.toUTCString();
- }
- document.cookie = name + "=" + (value || "") + expires + "; path=/";
-}
-
-function getCookie(name) {
- var nameEQ = name + "=";
- var ca = document.cookie.split(';');
- for (var i = 0; i < ca.length; i++) {
- var c = ca[i];
- while (c.charAt(0) == ' ') c = c.substring(1, c.length);
- if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length, c.length);
- }
- return null;
-}
diff --git a/public/service-worker.js b/public/service-worker.js
deleted file mode 100644
index 8dd3715..0000000
--- a/public/service-worker.js
+++ /dev/null
@@ -1,90 +0,0 @@
-const CACHE_NAME = 'indwebindex-cache-v2'; // 更新缓存版本
-const urlsToCache = [
- '/',
- '/index.html',
- '/css/dark.css',
- '/css/context-menu.css',
- '/css/style.css',
- '/css/daytime.css',
- '/js/data-loader.js',
- '/js/theme.js',
- '/js/context-menu.js',
- '/js/main.js',
- '/image/favicon.ico',
- '/assets/svg/search.svg',
- '/assets/svg/sun.svg',
- '/assets/svg/moon.svg',
- '/assets/data.json',
- 'https://cdn.jsdelivr.net/npm/cn-fontsource-smiley-sans-oblique-regular@1.0.1/font.min.css',
- 'https://npm.elemecdn.com/lxgw-wenkai-webfont@1.6.0/style.css',
- 'https://jhlst.nowscott.top/result.css',
- 'https://zqfs.nowscott.top/result.css'
-];
-
-self.addEventListener('install', event => {
- event.waitUntil(
- caches.open(CACHE_NAME)
- .then(cache => {
- console.log('Opened cache');
- return cache.addAll(urlsToCache);
- })
- );
-});
-
-self.addEventListener('fetch', event => {
- // 检查请求的来源是否为 chrome-extension 或者其他不支持的协议
- if (event.request.url.startsWith('chrome-extension://') ||
- !event.request.url.startsWith('http') ||
- event.request.method !== 'GET') {
- return; // 直接返回,不处理此请求
- }
-
- event.respondWith(
- caches.match(event.request).then(response => {
- if (response) {
- // 检查缓存版本是否过期
- return caches.open(CACHE_NAME).then(cache => {
- return fetch(event.request).then(fetchResponse => {
- if (fetchResponse && fetchResponse.status === 200) {
- cache.put(event.request, fetchResponse.clone());
- }
- return fetchResponse;
- }).catch(() => {
- console.error('Fetch failed, returning cached response', event.request.url);
- return response;
- }); // 如果网络请求失败,使用缓存
- });
- } else {
- return fetch(event.request).then(fetchResponse => {
- if (fetchResponse && fetchResponse.status === 200) {
- return caches.open(CACHE_NAME).then(cache => {
- cache.put(event.request, fetchResponse.clone());
- return fetchResponse;
- });
- } else {
- return fetchResponse;
- }
- }).catch(error => {
- console.error('Fetch failed for:', event.request.url, error);
- throw error; // 处理错误并返回
- });
- }
- })
- );
-});
-
-self.addEventListener('activate', event => {
- const cacheWhitelist = [CACHE_NAME];
- event.waitUntil(
- caches.keys().then(cacheNames => {
- return Promise.all(
- cacheNames.map(cacheName => {
- if (cacheWhitelist.indexOf(cacheName) === -1) {
- console.log('Deleting old cache:', cacheName);
- return caches.delete(cacheName);
- }
- })
- );
- })
- );
-});
diff --git a/requirements.txt b/requirements.txt
deleted file mode 100644
index 69f7794..0000000
--- a/requirements.txt
+++ /dev/null
@@ -1 +0,0 @@
-notion_client==2.2.1
diff --git a/scripts/scrape.py b/scripts/scrape.py
deleted file mode 100644
index 57c324b..0000000
--- a/scripts/scrape.py
+++ /dev/null
@@ -1,72 +0,0 @@
-import os
-import json
-from notion_client import Client
-import traceback # 引入 traceback 用于打印详细的错误信息
-
-# 本地调试时候取消注释来加载本地环境变量
-# from dotenv import load_dotenv
-# dotenv_path = '.env'
-# load_dotenv(dotenv_path)
-
-notion = Client(auth=os.getenv("ACCESS_TOKEN"))
-database_id = os.getenv("DATABASE_ID")
-
-def process_data(pages):
- processed_data = []
- for item in pages['results']:
- properties = item['properties']
- name = properties['name']['title'][0]['text']['content'] if properties['name']['title'] else ''
- web = properties.get('web', {}).get('url', '')
- tags = [tag['name'] for tag in properties.get('tags', {}).get('multi_select', [])]
- brief_text_list = properties.get('brief', {}).get('rich_text', [])
- brief = brief_text_list[0].get('text', {}).get('content', '') if brief_text_list else ''
-
- # 对 state 的处理添加 None 检查
- state_prop = properties.get('state')
- if state_prop and 'select' in state_prop and state_prop['select']:
- state = state_prop['select'].get('name', '')
- else:
- state = ''
-
- processed_data.append({
- "name": name,
- "web": web,
- "tags": tags,
- "brief": brief,
- "state": state
- })
- return processed_data
-
-
-def fetch_database(database_id):
- """从Notion数据库获取所有数据,并处理"""
- data = []
- has_more = True
- start_cursor = None
- while has_more:
- try:
- response = notion.databases.query(database_id=database_id, start_cursor=start_cursor)
- data.extend(process_data(response))
- has_more = response.get('has_more', False) # type: ignore
- start_cursor = response.get('next_cursor') # type: ignore
- except Exception as e:
- print("Failed to query database:", e)
- traceback.print_exc()
- break # 出错时退出循环
- return data
-
-def main():
- """主函数,获取数据并保存到文件"""
- try:
- data = fetch_database(database_id)
- # 过滤数据
- filtered_data = [item for item in data if item['name'] and item['state'] == '正常']
- # 保存到JSON文件
- with open('public/assets/data.json', 'w', encoding='utf-8') as f:
- json.dump(filtered_data, f, ensure_ascii=False, indent=4)
- except Exception as e:
- print(f"An error occurred: {e}")
- traceback.print_exc()
-
-if __name__ == "__main__":
- main()
diff --git a/vercel.json b/vercel.json
index c6d9b51..c0d1f72 100644
--- a/vercel.json
+++ b/vercel.json
@@ -1,4 +1,13 @@
{
- "cleanUrls": true,
- "trailingSlash": false
-}
\ No newline at end of file
+ "version": 2,
+ "builds": [
+ {
+ "src": "next.config.js",
+ "use": "@vercel/next"
+ }
+ ],
+ "routes": [
+ { "src": "/(.*)", "dest": "/$1" }
+ ]
+ }
+
\ No newline at end of file