├── public
├── favicon.png
├── logo
│ ├── lol.png
│ ├── 36kr.png
│ ├── acfun.png
│ ├── baidu.png
│ ├── sspai.png
│ ├── tieba.png
│ ├── v2ex.png
│ ├── weibo.png
│ ├── zhihu.png
│ ├── bilibili.png
│ ├── douyin.png
│ ├── genshin.png
│ ├── github.png
│ ├── honkai.png
│ ├── ithome.png
│ ├── jianshu.png
│ ├── juejin.png
│ ├── kuaishou.png
│ ├── ngabbs.png
│ ├── qq-news.png
│ ├── starrail.png
│ ├── thepaper.png
│ ├── toutiao.png
│ ├── weread.png
│ ├── douban-group.png
│ ├── douban-movie.png
│ ├── hellogithub.png
│ ├── netease-news.png
│ ├── zhihu-daily.png
│ ├── qq_music_toplist.png
│ └── netease_music_toplist.png
└── ico
│ ├── error.png
│ ├── favicon.png
│ ├── icon_error.png
│ └── powered-by-vercel.svg
├── screenshots
└── main.jpg
├── vercel.json
├── .vscode
└── extensions.json
├── .env
├── src
├── style
│ └── global.scss
├── router
│ ├── index.js
│ └── routes.js
├── api
│ ├── index.js
│ └── request.js
├── main.js
├── views
│ ├── 404.vue
│ ├── 403.vue
│ ├── 500.vue
│ ├── Home.vue
│ ├── Test.vue
│ ├── Setting.vue
│ └── List.vue
├── components
│ ├── Footer.vue
│ ├── Provider.vue
│ ├── Header.vue
│ └── HotList.vue
├── utils
│ └── getTime.js
├── App.vue
└── store
│ └── index.js
├── index.html
├── .gitignore
├── README.md
├── package.json
├── LICENSE
└── vite.config.js
/public/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsyy/DailyHot/HEAD/public/favicon.png
--------------------------------------------------------------------------------
/public/logo/lol.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsyy/DailyHot/HEAD/public/logo/lol.png
--------------------------------------------------------------------------------
/public/ico/error.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsyy/DailyHot/HEAD/public/ico/error.png
--------------------------------------------------------------------------------
/public/logo/36kr.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsyy/DailyHot/HEAD/public/logo/36kr.png
--------------------------------------------------------------------------------
/public/logo/acfun.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsyy/DailyHot/HEAD/public/logo/acfun.png
--------------------------------------------------------------------------------
/public/logo/baidu.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsyy/DailyHot/HEAD/public/logo/baidu.png
--------------------------------------------------------------------------------
/public/logo/sspai.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsyy/DailyHot/HEAD/public/logo/sspai.png
--------------------------------------------------------------------------------
/public/logo/tieba.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsyy/DailyHot/HEAD/public/logo/tieba.png
--------------------------------------------------------------------------------
/public/logo/v2ex.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsyy/DailyHot/HEAD/public/logo/v2ex.png
--------------------------------------------------------------------------------
/public/logo/weibo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsyy/DailyHot/HEAD/public/logo/weibo.png
--------------------------------------------------------------------------------
/public/logo/zhihu.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsyy/DailyHot/HEAD/public/logo/zhihu.png
--------------------------------------------------------------------------------
/screenshots/main.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsyy/DailyHot/HEAD/screenshots/main.jpg
--------------------------------------------------------------------------------
/public/ico/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsyy/DailyHot/HEAD/public/ico/favicon.png
--------------------------------------------------------------------------------
/public/logo/bilibili.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsyy/DailyHot/HEAD/public/logo/bilibili.png
--------------------------------------------------------------------------------
/public/logo/douyin.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsyy/DailyHot/HEAD/public/logo/douyin.png
--------------------------------------------------------------------------------
/public/logo/genshin.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsyy/DailyHot/HEAD/public/logo/genshin.png
--------------------------------------------------------------------------------
/public/logo/github.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsyy/DailyHot/HEAD/public/logo/github.png
--------------------------------------------------------------------------------
/public/logo/honkai.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsyy/DailyHot/HEAD/public/logo/honkai.png
--------------------------------------------------------------------------------
/public/logo/ithome.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsyy/DailyHot/HEAD/public/logo/ithome.png
--------------------------------------------------------------------------------
/public/logo/jianshu.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsyy/DailyHot/HEAD/public/logo/jianshu.png
--------------------------------------------------------------------------------
/public/logo/juejin.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsyy/DailyHot/HEAD/public/logo/juejin.png
--------------------------------------------------------------------------------
/public/logo/kuaishou.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsyy/DailyHot/HEAD/public/logo/kuaishou.png
--------------------------------------------------------------------------------
/public/logo/ngabbs.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsyy/DailyHot/HEAD/public/logo/ngabbs.png
--------------------------------------------------------------------------------
/public/logo/qq-news.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsyy/DailyHot/HEAD/public/logo/qq-news.png
--------------------------------------------------------------------------------
/public/logo/starrail.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsyy/DailyHot/HEAD/public/logo/starrail.png
--------------------------------------------------------------------------------
/public/logo/thepaper.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsyy/DailyHot/HEAD/public/logo/thepaper.png
--------------------------------------------------------------------------------
/public/logo/toutiao.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsyy/DailyHot/HEAD/public/logo/toutiao.png
--------------------------------------------------------------------------------
/public/logo/weread.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsyy/DailyHot/HEAD/public/logo/weread.png
--------------------------------------------------------------------------------
/vercel.json:
--------------------------------------------------------------------------------
1 | {
2 | "rewrites": [{ "source": "/:path*", "destination": "/index.html" }]
3 | }
4 |
--------------------------------------------------------------------------------
/public/ico/icon_error.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsyy/DailyHot/HEAD/public/ico/icon_error.png
--------------------------------------------------------------------------------
/public/logo/douban-group.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsyy/DailyHot/HEAD/public/logo/douban-group.png
--------------------------------------------------------------------------------
/public/logo/douban-movie.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsyy/DailyHot/HEAD/public/logo/douban-movie.png
--------------------------------------------------------------------------------
/public/logo/hellogithub.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsyy/DailyHot/HEAD/public/logo/hellogithub.png
--------------------------------------------------------------------------------
/public/logo/netease-news.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsyy/DailyHot/HEAD/public/logo/netease-news.png
--------------------------------------------------------------------------------
/public/logo/zhihu-daily.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsyy/DailyHot/HEAD/public/logo/zhihu-daily.png
--------------------------------------------------------------------------------
/.vscode/extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | "recommendations": ["Vue.volar", "Vue.vscode-typescript-vue-plugin"]
3 | }
4 |
--------------------------------------------------------------------------------
/public/logo/qq_music_toplist.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsyy/DailyHot/HEAD/public/logo/qq_music_toplist.png
--------------------------------------------------------------------------------
/public/logo/netease_music_toplist.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsyy/DailyHot/HEAD/public/logo/netease_music_toplist.png
--------------------------------------------------------------------------------
/.env:
--------------------------------------------------------------------------------
1 | # 全局 API 地址
2 | # VITE_GLOBAL_API="http://localhost:6688"
3 | VITE_GLOBAL_API="https://api-hot.imsyy.top"
4 |
5 | # ICP 备案号
6 | VITE_ICP = "豫ICP备2022018134号-1"
7 |
8 | # 全局目录
9 | VITE_DIR = "/"
--------------------------------------------------------------------------------
/src/style/global.scss:
--------------------------------------------------------------------------------
1 | // 全局样式
2 | * {
3 | margin: 0;
4 | padding: 0;
5 | -webkit-user-select: none;
6 | user-select: none;
7 | }
8 |
9 | html,
10 | body,
11 | #app {
12 | height: 100%;
13 | }
14 |
15 | // 动画
16 | .fade-enter-active,
17 | .fade-leave-active {
18 | transition: opacity 0.3s ease-in-out;
19 | }
20 |
21 | .fade-enter-from,
22 | .fade-leave-to {
23 | opacity: 0;
24 | }
25 |
--------------------------------------------------------------------------------
/src/router/index.js:
--------------------------------------------------------------------------------
1 | import { createRouter, createWebHashHistory } from "vue-router";
2 | import routes from "@/router/routes";
3 |
4 | const router = createRouter({
5 | history: createWebHashHistory(),
6 | routes,
7 | });
8 |
9 | // 路由守卫
10 | router.beforeEach(() => {
11 | $loadingBar.start();
12 | });
13 |
14 | router.afterEach(() => {
15 | $loadingBar.finish();
16 | });
17 |
18 | export default router;
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | 今日热榜 - 汇聚全网热点,热门尽览无余
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | pnpm-debug.log*
8 | lerna-debug.log*
9 |
10 | node_modules
11 | .DS_Store
12 | dist
13 | dist-ssr
14 | coverage
15 | *.local
16 |
17 | /cypress/videos/
18 | /cypress/screenshots/
19 |
20 | # Editor directories and files
21 | .vscode/*
22 | !.vscode/extensions.json
23 | .idea
24 | *.suo
25 | *.ntvs*
26 | *.njsproj
27 | *.sln
28 | *.sw?
29 |
--------------------------------------------------------------------------------
/src/api/index.js:
--------------------------------------------------------------------------------
1 | import axios from "@/api/request";
2 |
3 | /**
4 | * 获取热榜分类数据
5 | * @param {string} type 热榜分类名称
6 | * @param {boolean} isNew 是否拉取最新数据
7 | * @param {object} params 请求参数
8 | * @returns
9 | */
10 | export const getHotLists = (type, isNew = false, params) => {
11 | return axios({
12 | method: "GET",
13 | url: `/${type}`,
14 | params: {
15 | cache: !isNew,
16 | ...params,
17 | },
18 | });
19 | };
20 |
--------------------------------------------------------------------------------
/src/main.js:
--------------------------------------------------------------------------------
1 | import { createApp } from "vue";
2 | import { createPinia } from "pinia";
3 | import piniaPluginPersistedstate from "pinia-plugin-persistedstate";
4 |
5 | import App from "./App.vue";
6 | import router from "@/router";
7 |
8 | // 全局样式
9 | import "@/style/global.scss";
10 |
11 | const app = createApp(App);
12 |
13 | const pinia = createPinia();
14 | pinia.use(piniaPluginPersistedstate);
15 | app.use(pinia);
16 | app.use(router);
17 |
18 | app.mount("#app");
19 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |

3 |
今日热榜
4 |
汇聚全网热点,热门尽览无余
5 |
6 |

7 |
8 |
9 |
10 | ## 示例
11 |
12 | > 这里是示例站点
13 |
14 | - [今日热榜 - https://hot.imsyy.top/](https://hot.imsyy.top/)
15 |
16 |
17 | ## 部署
18 |
19 | ```bash
20 | // 安装依赖
21 | pnpm install
22 |
23 | // 开发
24 | pnpm dev
25 |
26 | // 打包
27 | pnpm build
28 | ```
29 |
30 | ## Vercel 部署
31 |
32 | 现已支持 Vercel 一键部署,无需服务器
33 |
34 | > 请注意,需要修改环境变量中的 API 地址
35 |
36 | 
37 |
--------------------------------------------------------------------------------
/src/views/404.vue:
--------------------------------------------------------------------------------
1 |
2 |
12 |
18 |
19 | 重新载入
20 |
21 |
22 |
23 |
24 |
25 |
33 |
34 |
39 |
--------------------------------------------------------------------------------
/src/views/403.vue:
--------------------------------------------------------------------------------
1 |
2 |
12 |
18 |
19 | 重新载入
20 |
21 |
22 |
23 |
24 |
25 |
33 |
34 |
39 |
--------------------------------------------------------------------------------
/src/views/500.vue:
--------------------------------------------------------------------------------
1 |
2 |
12 |
18 |
19 | 重新载入
20 |
21 |
22 |
23 |
24 |
25 |
33 |
34 |
39 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "dailyhot",
3 | "description": "今日热榜",
4 | "author": "imsyy",
5 | "github": "https://github.com/imsyy",
6 | "version": "1.2.0",
7 | "private": true,
8 | "scripts": {
9 | "dev": "vite",
10 | "build": "vite build",
11 | "preview": "vite preview"
12 | },
13 | "dependencies": {
14 | "@icon-park/vue-next": "^1.4.2",
15 | "@jridgewell/sourcemap-codec": "^1.5.0",
16 | "axios": "^1.7.7",
17 | "lunar-calendar": "^0.1.4",
18 | "pinia": "^2.2.6",
19 | "pinia-plugin-persistedstate": "^3.2.3",
20 | "sass": "^1.80.6",
21 | "scrollreveal": "^4.0.9",
22 | "terser": "^5.36.0",
23 | "vue": "^3.5.12",
24 | "vue-router": "^4.4.5",
25 | "vuedraggable": "^4.1.0"
26 | },
27 | "devDependencies": {
28 | "@vitejs/plugin-vue": "^4.6.2",
29 | "naive-ui": "^2.40.1",
30 | "unplugin-auto-import": "^0.12.2",
31 | "unplugin-vue-components": "^0.22.12",
32 | "vite": "^4.5.5",
33 | "vite-plugin-pwa": "^0.14.7"
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 底层用户
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/src/router/routes.js:
--------------------------------------------------------------------------------
1 | const routes = [
2 | // 首页
3 | {
4 | path: "/",
5 | name: "home",
6 | meta: {
7 | title: "首页",
8 | },
9 | component: () => import("@/views/Home.vue"),
10 | },
11 | // 新闻列表
12 | {
13 | path: "/list",
14 | name: "list",
15 | meta: {
16 | title: "新闻列表",
17 | },
18 | component: () => import("@/views/List.vue"),
19 | },
20 | // 设置页
21 | {
22 | path: "/setting",
23 | name: "setting",
24 | meta: {
25 | title: "全局设置",
26 | },
27 | component: () => import("@/views/Setting.vue"),
28 | },
29 | // 测试页面
30 | {
31 | path: "/test",
32 | name: "test",
33 | meta: {
34 | title: "test",
35 | },
36 | component: () => import("@/views/Test.vue"),
37 | },
38 | // 403
39 | {
40 | path: "/403",
41 | name: "403",
42 | meta: {
43 | title: "403",
44 | },
45 | component: () => import("@/views/403.vue"),
46 | },
47 | // 404
48 | {
49 | path: "/404",
50 | name: "404",
51 | meta: {
52 | title: "404",
53 | },
54 | component: () => import("@/views/404.vue"),
55 | },
56 | // 500
57 | {
58 | path: "/500",
59 | name: "500",
60 | meta: {
61 | title: "500",
62 | },
63 | component: () => import("@/views/500.vue"),
64 | },
65 | {
66 | path: "/:pathMatch(.*)",
67 | redirect: "/404",
68 | },
69 | ];
70 |
71 | export default routes;
72 |
--------------------------------------------------------------------------------
/src/components/Footer.vue:
--------------------------------------------------------------------------------
1 |
2 |
20 |
21 |
22 |
32 |
33 |
69 |
--------------------------------------------------------------------------------
/src/views/Home.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
12 |
18 |
19 |
20 |
21 |
22 | 此处暂无内容
23 |
24 |
25 | 出错了?点此重置
26 |
27 |
28 |
29 |
30 |
31 |
32 |
54 |
55 |
80 |
--------------------------------------------------------------------------------
/src/api/request.js:
--------------------------------------------------------------------------------
1 | import axios from "axios";
2 |
3 | switch (process.env.NODE_ENV) {
4 | case "production":
5 | axios.defaults.baseURL = import.meta.env.VITE_GLOBAL_API;
6 | break;
7 | case "development":
8 | axios.defaults.baseURL = import.meta.env.VITE_GLOBAL_API;
9 | break;
10 | default:
11 | axios.defaults.baseURL = import.meta.env.VITE_GLOBAL_API;
12 | break;
13 | }
14 |
15 | axios.defaults.timeout = 30000;
16 | axios.defaults.headers = { "Content-Type": "application/json" };
17 |
18 | // 请求拦截
19 | axios.interceptors.request.use(
20 | (request) => {
21 | // if (request.loadingBar != "Hidden") $loadingBar.start();
22 | const token = localStorage.getItem("token");
23 | if (token) {
24 | request.headers.Authorization = token;
25 | }
26 | return request;
27 | },
28 | (error) => {
29 | // $loadingBar.error();
30 | $message.error("请求失败,请稍后重试");
31 | return Promise.reject(error);
32 | }
33 | );
34 |
35 | // 响应拦截
36 | axios.interceptors.response.use(
37 | (response) => {
38 | // $loadingBar.finish();
39 | return response.data;
40 | },
41 | (error) => {
42 | $loadingBar.error();
43 | if (error.response) {
44 | let data = error.response.data;
45 | switch (error.response.status) {
46 | case 401:
47 | $message.error(data.message ? data.message : "请登录后使用");
48 | break;
49 | case 301:
50 | $message.error(data.message ? data.message : "请求路径发生跳转");
51 | break;
52 | case 403:
53 | $message.error(data.message ? data.message : "暂无访问权限");
54 | break;
55 | case 404:
56 | $message.error(data.message ? data.message : "请求资源不存在");
57 | break;
58 | case 500:
59 | $message.error(data.message ? data.message : "内部服务器错误");
60 | break;
61 | default:
62 | $message.error(data.message ? data.message : "请求失败,请稍后重试");
63 | break;
64 | }
65 | } else {
66 | $message.error(data.message ? data.message : "请求失败,请稍后重试");
67 | }
68 | return Promise.reject(error);
69 | }
70 | );
71 |
72 | export default axios;
73 |
--------------------------------------------------------------------------------
/src/utils/getTime.js:
--------------------------------------------------------------------------------
1 | import LunarCalendar from "lunar-calendar";
2 |
3 | export const formatTime = (timestamp) => {
4 | const date = new Date(timestamp);
5 | const now = new Date();
6 | const diffInSeconds = (now.getTime() - date.getTime()) / 1000;
7 | const diffInMinutes = diffInSeconds / 60;
8 | const diffInHours = diffInMinutes / 60;
9 |
10 | if (diffInSeconds < 60) {
11 | return "刚刚更新";
12 | } else if (diffInMinutes < 60) {
13 | const minutes = Math.floor(diffInMinutes);
14 | return `${minutes}分钟前更新`;
15 | } else if (diffInHours < 24) {
16 | const hours = Math.floor(diffInHours);
17 | return `${hours}小时前更新`;
18 | } else {
19 | const month = date.getMonth() + 1;
20 | const day = date.getDate();
21 | return `${month}月${day}日`;
22 | }
23 | };
24 |
25 | export const getCurrentTime = () => {
26 | const time = new Date();
27 | const year = time.getFullYear();
28 | const month =
29 | time.getMonth() + 1 < 10
30 | ? "0" + (time.getMonth() + 1)
31 | : time.getMonth() + 1;
32 | const day = time.getDate() < 10 ? "0" + time.getDate() : time.getDate();
33 | const hour = time.getHours() < 10 ? "0" + time.getHours() : time.getHours();
34 | const minute =
35 | time.getMinutes() < 10 ? "0" + time.getMinutes() : time.getMinutes();
36 | const second =
37 | time.getSeconds() < 10 ? "0" + time.getSeconds() : time.getSeconds();
38 | const weekday = [
39 | "星期日",
40 | "星期一",
41 | "星期二",
42 | "星期三",
43 | "星期四",
44 | "星期五",
45 | "星期六",
46 | ];
47 | // 获取农历
48 | const lunar = LunarCalendar.solarToLunar(
49 | time.getFullYear(),
50 | time.getMonth() + 1,
51 | time.getDate()
52 | );
53 | const currentTime = {
54 | time: {
55 | year,
56 | month,
57 | day,
58 | hour,
59 | minute,
60 | second,
61 | weekday: weekday[time.getDay()],
62 | text:
63 | year +
64 | "-" +
65 | month +
66 | "-" +
67 | day +
68 | " " +
69 | hour +
70 | ":" +
71 | minute +
72 | ":" +
73 | second,
74 | },
75 | lunar: {
76 | data: lunar,
77 | year: lunar.lunarYear,
78 | month: lunar.lunarMonthName,
79 | day: lunar.lunarDayName,
80 | GanZhiYear: lunar.GanZhiYear,
81 | GanZhiMonth: lunar.GanZhiMonth,
82 | GanZhiDay: lunar.GanZhiDay,
83 | text: lunar.lunarMonthName + lunar.lunarDayName,
84 | },
85 | };
86 | return currentTime;
87 | };
88 |
--------------------------------------------------------------------------------
/vite.config.js:
--------------------------------------------------------------------------------
1 | import { fileURLToPath, URL } from "node:url";
2 | import { defineConfig, loadEnv } from "vite";
3 | import { NaiveUiResolver } from "unplugin-vue-components/resolvers";
4 | import { VitePWA } from "vite-plugin-pwa";
5 | import vue from "@vitejs/plugin-vue";
6 | import AutoImport from "unplugin-auto-import/vite";
7 | import Components from "unplugin-vue-components/vite";
8 |
9 | export default defineConfig(({ mode }) => {
10 | return {
11 | base: loadEnv(mode, process.cwd())["VITE_DIR"],
12 | plugins: [
13 | vue(),
14 | AutoImport({
15 | imports: [
16 | "vue",
17 | {
18 | "naive-ui": [
19 | "useDialog",
20 | "useMessage",
21 | "useNotification",
22 | "useLoadingBar",
23 | ],
24 | },
25 | ],
26 | }),
27 | Components({
28 | resolvers: [NaiveUiResolver()],
29 | }),
30 | // PWA
31 | VitePWA({
32 | registerType: "autoUpdate",
33 | workbox: {
34 | cleanupOutdatedCaches: true,
35 | runtimeCaching: [
36 | {
37 | urlPattern: /(.*?)\.(woff2|woff|ttf)/,
38 | handler: "CacheFirst",
39 | options: {
40 | cacheName: "file-cache",
41 | },
42 | },
43 | {
44 | urlPattern:
45 | /(.*?)\.(webp|png|jpe?g|svg|gif|bmp|psd|tiff|tga|eps)/,
46 | handler: "CacheFirst",
47 | options: {
48 | cacheName: "image-cache",
49 | },
50 | },
51 | ],
52 | },
53 | manifest: {
54 | name: "今日热榜",
55 | short_name: "DailyHot",
56 | description: "汇聚全网热点,热门尽览无余",
57 | display: "standalone",
58 | start_url: "/",
59 | theme_color: "#fff",
60 | background_color: "#efefef",
61 | icons: [
62 | {
63 | src: "/ico/favicon.png",
64 | sizes: "200x200",
65 | type: "image/png",
66 | },
67 | ],
68 | },
69 | }),
70 | ],
71 | resolve: {
72 | alias: {
73 | "@": fileURLToPath(new URL("./src", import.meta.url)),
74 | },
75 | },
76 | server: {
77 | port: 6699,
78 | },
79 | build: {
80 | minify: "terser",
81 | terserOptions: {
82 | compress: {
83 | pure_funcs: ["console.log"],
84 | },
85 | },
86 | },
87 | };
88 | });
89 |
--------------------------------------------------------------------------------
/src/components/Provider.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
109 |
--------------------------------------------------------------------------------
/src/views/Test.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
9 |
10 |
Transition
11 |
25 |
26 |
27 |
34 | {{ element.name }}
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
90 |
91 |
121 |
--------------------------------------------------------------------------------
/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
50 |
51 |
114 |
--------------------------------------------------------------------------------
/public/ico/powered-by-vercel.svg:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/src/store/index.js:
--------------------------------------------------------------------------------
1 | import { defineStore } from "pinia";
2 |
3 | export const mainStore = defineStore("mainData", {
4 | state: () => {
5 | return {
6 | // 系统主题
7 | siteTheme: "light",
8 | siteThemeAuto: true,
9 | // 新闻类别
10 | defaultNewsArr: [
11 | {
12 | label: "哔哩哔哩",
13 | name: "bilibili",
14 | order: 0,
15 | show: true,
16 | },
17 | {
18 | label: "微博",
19 | name: "weibo",
20 | order: 1,
21 | show: true,
22 | },
23 | {
24 | label: "抖音",
25 | name: "douyin",
26 | order: 2,
27 | show: true,
28 | },
29 | {
30 | label: "知乎",
31 | name: "zhihu",
32 | order: 3,
33 | show: true,
34 | },
35 | {
36 | label: "36氪",
37 | name: "36kr",
38 | order: 4,
39 | show: true,
40 | },
41 | {
42 | label: "百度",
43 | name: "baidu",
44 | order: 5,
45 | show: true,
46 | },
47 | {
48 | label: "少数派",
49 | name: "sspai",
50 | order: 6,
51 | show: true,
52 | },
53 | {
54 | label: "IT之家",
55 | name: "ithome",
56 | order: 7,
57 | show: true,
58 | },
59 | {
60 | label: "澎湃新闻",
61 | name: "thepaper",
62 | order: 8,
63 | show: true,
64 | },
65 | {
66 | label: "今日头条",
67 | name: "toutiao",
68 | order: 9,
69 | show: true,
70 | },
71 | {
72 | label: "百度贴吧",
73 | name: "tieba",
74 | order: 10,
75 | show: true,
76 | },
77 | {
78 | label: "稀土掘金",
79 | name: "juejin",
80 | order: 11,
81 | show: true,
82 | },
83 | {
84 | label: "腾讯新闻",
85 | name: "qq-news",
86 | order: 12,
87 | show: true,
88 | },
89 | {
90 | label: "豆瓣电影",
91 | name: "douban-movie",
92 | order: 13,
93 | show: true,
94 | },
95 | {
96 | label: "原神",
97 | name: "genshin",
98 | order: 14,
99 | show: true,
100 | },
101 | {
102 | label: "崩坏:星穹铁道",
103 | name: "starrail",
104 | order: 16,
105 | show: true,
106 | },
107 | {
108 | label: "LOL",
109 | name: "lol",
110 | order: 15,
111 | show: true,
112 | },
113 | {
114 | label: "网易新闻",
115 | name: "netease-news",
116 | order: 17,
117 | show: true,
118 | },
119 | {
120 | label: "微信读书",
121 | name: "weread",
122 | order: 18,
123 | show: true,
124 | },
125 | {
126 | label: "豆瓣讨论小组",
127 | name: "douban-group",
128 | order: 19,
129 | show: true,
130 | },
131 | {
132 | label: "NGA",
133 | name: "ngabbs",
134 | order: 20,
135 | show: true,
136 | },
137 | {
138 | label: "HelloGitHub",
139 | name: "hellogithub",
140 | order: 21,
141 | show: true,
142 | },
143 | {
144 | label: "简书",
145 | name: "jianshu",
146 | order: 22,
147 | show: true,
148 | },
149 | {
150 | label: "知乎日报",
151 | name: "zhihu-daily",
152 | order: 23,
153 | show: true,
154 | },
155 | ],
156 | newsArr: [],
157 | // 链接跳转方式
158 | linkOpenType: "open",
159 | // 页头固定
160 | headerFixed: true,
161 | // 时间数据
162 | timeData: null,
163 | // 字体大小
164 | listFontSize: 16,
165 | };
166 | },
167 | getters: {},
168 | actions: {
169 | // 更改系统主题
170 | setSiteTheme(val) {
171 | $message.info(`已切换至${val === "dark" ? "深色模式" : "浅色模式"}`, {
172 | showIcon: false,
173 | });
174 | this.siteTheme = val;
175 | this.siteThemeAuto = false;
176 | },
177 | // 检查更新
178 | checkNewsUpdate() {
179 | const mainData = JSON.parse(localStorage.getItem("mainData"));
180 | let updatedNum = 0;
181 | if (!mainData) return false;
182 | console.log("列表尝试更新", this.defaultNewsArr, this.newsArr);
183 | // 执行比较并迁移
184 | if (this.newsArr.length > 0) {
185 | for (const newItem of this.defaultNewsArr) {
186 | const exists = this.newsArr.some(
187 | (news) => newItem.label === news.label && newItem.name === news.name
188 | );
189 | if (!exists) {
190 | console.log("列表有更新:", newItem);
191 | updatedNum++;
192 | this.newsArr.push(newItem);
193 | }
194 | }
195 | if (updatedNum) $message.success(`成功更新 ${updatedNum} 个榜单数据`);
196 | } else {
197 | console.log("列表无内容,写入默认");
198 | this.newsArr = this.defaultNewsArr;
199 | }
200 | },
201 | },
202 | persist: [
203 | {
204 | storage: localStorage,
205 | paths: [
206 | "siteTheme",
207 | "siteThemeAuto",
208 | "newsArr",
209 | "linkOpenType",
210 | "headerFixed",
211 | "listFontSize",
212 | ],
213 | },
214 | ],
215 | });
216 |
--------------------------------------------------------------------------------
/src/components/Header.vue:
--------------------------------------------------------------------------------
1 |
2 |
88 |
89 |
90 |
218 |
219 |
302 |
--------------------------------------------------------------------------------
/src/views/Setting.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
全局设置
4 |
基础设置
5 |
6 |
7 |
8 | 明暗模式
9 |
10 |
16 |
17 |
18 |
19 |
20 |
21 | 明暗模式跟随系统
22 | 明暗模式是否跟随系统当前模式
23 |
24 |
29 |
30 |
31 |
32 |
33 |
34 | 链接跳转方式
35 | 选择榜单列表内容的跳转方式
36 |
37 |
42 |
43 |
44 |
45 |
46 |
47 | 固定导航栏
48 | 导航栏是否固定
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 | 列表文本大小
57 |
64 |
65 | 我是将要显示的文字的大小
66 |
67 |
68 |
69 |
70 |
82 |
83 |
84 |
85 |
86 |
87 | 榜单排序
88 |
89 | 拖拽以排序,开关用以控制在页面中的显示状态
90 |
91 |
92 |
93 |
94 | 恢复默认
95 |
96 | 确认将排序恢复到默认状态?
97 |
98 |
99 |
106 |
107 |
112 |
113 |
![logo]()
114 |
115 |
116 |
122 |
123 |
124 |
125 |
126 |
杂项设置
127 |
128 |
129 |
130 | 重置所有数据
131 |
132 | 重置所有数据,你的自定义设置都将会丢失
133 |
134 |
135 |
136 |
137 | 重置
138 |
139 | 确认重置所有数据?你的自定义设置都将会丢失!
140 |
141 |
142 |
143 |
144 |
145 |
146 |
215 |
216 |
307 |
--------------------------------------------------------------------------------
/src/views/List.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
13 | {{ item.label }}
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
61 |
62 |
63 |
64 |
65 |
66 |
74 |
75 |
88 | {{ index + 1 + (pageNumber - 1) * 20 }}
89 |
90 |
91 |
92 |
93 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
220 |
221 |
395 |
--------------------------------------------------------------------------------
/src/components/HotList.vue:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
13 |
14 |
19 | {{ hotData.label }}
20 |
21 |
22 | {{ hotListData.type }}
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
37 |
44 |
45 |
46 |
47 | 重试
48 |
49 |
50 |
51 |
52 |
53 |
54 |
59 | {{ index + 1 }}
73 |
78 | {{ item.title }}
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 | {{ updateTime }}
95 |
96 | 获取失败
97 |
98 |
99 |
100 |
107 |
108 |
109 |
110 |
111 |
112 | 查看更多
113 |
114 |
115 |
116 |
123 |
124 |
125 |
126 |
127 |
128 | 获取最新
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
266 |
267 |
431 |
--------------------------------------------------------------------------------