Compare commits

..

217 Commits
v1.3 ... dev

Author SHA1 Message Date
imsyy
52602e91a5
🐞 fix: 更新壁纸接口 #302 2024-06-05 13:52:04 +08:00
imsyy
e7a4cf7171
🐞 fix: 修复移动端样式异常 2024-04-28 11:19:36 +08:00
imsyy
777979f0e3
🐞 fix: 修正时间统计错误 2024-04-28 10:00:45 +08:00
imsyy
70e7fa534f
🦄 refactor: 移除 env 2024-04-24 10:37:29 +08:00
imsyy
462aab20af
🐞 fix: 修复一系列问题 2024-04-24 10:36:23 +08:00
imsyy
e8b69c5ab5
feat: 优化部分样式 #259 2024-03-11 10:38:21 +08:00
底层用户
4b60e7edf1
Merge pull request #252 from L1bw/dev
fix: 修复备用接口获取天气时显示失败的问题
2024-03-11 09:42:42 +08:00
Libw·I
550545fa3e
fix: 修复备用接口获取天气时显示失败的问题 2024-02-24 21:18:09 +08:00
底层用户
c068f676d1
Merge pull request #230 from first19326/dev
fix: 修复了播放器未加载完成或加载失败时,键盘控制事件仍旧生效的问题
2024-01-03 13:48:13 +08:00
first19326
c94b230d45 feat: 更新 vue-aplayer 版本 2024-01-02 23:10:37 +08:00
first19326
27780c6558 fix: 修复了播放器未加载完成或加载失败时,键盘控制事件仍旧生效的问题 2024-01-02 23:09:43 +08:00
imsyy
f016348b97
feat: 新增 GitHub 仓库列表
- 更换播放器为 @worstone/vue-aplayer #158
2024-01-02 18:11:48 +08:00
底层用户
e2290042f7
Merge pull request #229 from first19326/dev
feat: 替换 vue3-aplayer 插件,并添加播放器设置选项
2024-01-02 15:59:16 +08:00
first19326
d085ccc832 feat: 替换 vue3-aplayer 插件,并添加播放器设置选项 2024-01-02 02:58:01 +08:00
底层用户
78e0d0505a
Merge pull request #226 from nova1751/dev
fix: fix the logo be cut in small screen #157
2023-12-19 14:52:54 +08:00
nova1751
f3dd5b8dc5 fix: fix the logo be cut in small screen #157 2023-12-16 13:31:19 +08:00
imsyy
a8b1d66330 fix: 修复教书先生API接口调用失败 #224 2023-12-11 16:11:22 +08:00
imsyy
b28f92b99f feat: Add Docker #107 2023-12-06 13:41:45 +08:00
imsyy
1e0fe3e724 feat: 添加部署说明 2023-12-02 09:36:47 +08:00
imsyy
c93d7d206b feat: add Actions 2023-12-02 09:11:18 +08:00
imsyy
3c2bc226ff feat: 修改部分样式 2023-11-13 09:19:31 +08:00
底层用户
015a139ce0
Merge pull request #214 from first19326/dev
feat: 优化 logo 区域样式
2023-11-13 09:15:21 +08:00
first19326
704d446328 feat: 优化字体加载方式 2023-11-11 21:17:29 +08:00
first19326
b7947467e1 feat: 优化 logo 区域样式 2023-11-10 23:54:42 +08:00
imsyy
e879efa7d4 fix: 首字母裁切 #82
> 域名过长的样式还没想好怎么调整 😂
2023-11-09 09:59:38 +08:00
底层用户
df854f3f19
Merge pull request #211 from first19326/dev
feat: 新增加载音乐失败的处理方法
2023-11-08 15:50:46 +08:00
first19326
5097e18e31 feat: 优化了一言数据加载 2023-11-04 20:28:41 +08:00
first19326
46b187d01f feat: 新增加载音乐失败的处理方法 2023-11-04 20:21:50 +08:00
imsyy
be94711dc8 feat: 支持配置音乐播放器开关 #209 2023-11-03 09:23:06 +08:00
底层用户
6c58920f77
Merge pull request #210 from first19326/dev
修复了一些小问题
2023-11-03 09:10:57 +08:00
first19326
17b278f467 fix: 修复壁纸展示状态无法点击下载按钮的问题 2023-11-03 00:49:56 +08:00
first19326
1f8afa7268 fix: 修复在Safari浏览器关闭音乐列表屏幕闪烁问题 2023-11-03 00:49:18 +08:00
first19326
418d73caba fix: 修复720px宽度的视窗下,移动端按钮未显示错误 2023-11-03 00:48:17 +08:00
first19326
9c03de74f8 fix: 修复壁纸展示状态下移动端菜单按钮未隐藏错误 2023-11-03 00:47:07 +08:00
imsyy
1716f53864 docs: update docs 2023-09-18 09:34:47 +08:00
imsyy
8cb8aba71f fix: 修复站点链接问题 #197 2023-09-18 09:32:23 +08:00
imsyy
802cca0f44 feat(dependencies): add ESLint #190 2023-08-26 16:03:07 +08:00
底层用户
75c75fff0f
Merge pull request #190 from OrzMiku/dev
添加 Prettier 并应用代码格式化
2023-08-26 15:47:01 +08:00
神奇のDz
40e45a539c feat(dependencies): add Prettier package 2023-08-23 13:39:30 +08:00
神奇のDz
981320feb2 style(formatting): apply Prettier code formatting 2023-08-23 13:38:17 +08:00
imsyy
8d23deeb40 fix: update README.md 2023-08-17 14:08:11 +08:00
imsyy
231c5b6cea feat: 支持图标分离设置 #183 2023-08-17 11:54:26 +08:00
imsyy
c12ddfb6b4 feat: 优化一系列问题 #146
- 重构进入动画逻辑 #146
- 精简部分代码
- 优化部分动画
- 新增部分设置项
2023-08-16 18:24:10 +08:00
imsyy
fe10751062 Merge branch 'dev' of github.com:imsyy/home into dev 2023-08-14 11:46:34 +08:00
imsyy
2496110d5d feat: 更改自定义参数引入方式 2023-08-14 11:46:28 +08:00
底层用户
d87d467dc7
feat: Create CODE_OF_CONDUCT.md 2023-08-01 14:13:33 +08:00
imsyy
c5b0b44fed fix: 修正说明 #176 #174 2023-08-01 14:11:38 +08:00
底层用户
a422495c5f
Merge pull request #176 from HaiBooLang/dev
完善README中自定义网站教程
2023-08-01 13:10:55 +08:00
HaiBooLang
65d1345169 完善README中自定义网站教程 2023-07-30 21:44:24 +08:00
imsyy
b9f9e5d527 fix: 无法立即显示时间 2023-07-26 14:51:16 +08:00
imsyy
9d2290d694 feat: 适配天气 API #162 #151 2023-07-03 17:51:58 +08:00
imsyy
7048a134be fix: 路由无法正常跳转 #142 2023-06-25 14:45:38 +08:00
imsyy
12808714c1 fix: 部分配置无效 #155 2023-06-19 11:21:37 +08:00
imsyy
21914f8937 feat: 添加 issue 模板 2023-06-17 16:31:20 +08:00
imsyy
ff83ffd53a fix: 修复部分参数配置无效 #148 2023-06-15 10:05:47 +08:00
imsyy
177b539e39 feat: 网站链接多页支持 #129 #20 #47 2023-06-12 11:39:06 +08:00
imsyy
acc8f54ef9 perf: 优化部分变量 & feat: 新增一个设置项 #124 2023-04-21 16:37:08 +08:00
imsyy
db0d3b92ae fix: 调整样式 2023-04-06 16:16:11 +08:00
imsyy
ab931acfb6 fix: 更换壁纸 API 接口 2023-04-03 09:42:07 +08:00
imsyy
faeb0b98fc 修复 时光胶囊显示错误 #101 2023-03-10 15:51:18 +08:00
imsyy
7adf606935 更新链接 2023-03-10 14:59:09 +08:00
imsyy
5c9e14a585 样式调整 2023-03-09 15:46:03 +08:00
imsyy
03eef44392 尝试修复音乐播放错误 #85 #93 2023-03-09 15:39:52 +08:00
imsyy
ddda08c037 添加配置项 2023-02-16 10:57:30 +08:00
imsyy
8f46b8dd46 去除强制 https 2023-02-14 09:01:51 +08:00
imsyy
82a6877681 修复音乐播放器无法获取歌曲名 2023-02-07 10:24:47 +08:00
imsyy
05eb444ccf Merge branch 'dev' of github.com:imsyy/home into dev 2023-02-07 09:57:40 +08:00
imsyy
15adc605a2 提供 api 部署说明 2023-02-07 09:56:08 +08:00
底层用户
cee5a05de0
Merge pull request #75 from imsyy/master
去除新春灯笼 & 临时更换 api
2023-02-06 13:35:04 +08:00
imsyy
fe89288f50 强制 https 2023-02-06 13:27:46 +08:00
imsyy
7b7c793e1b 去除新春灯笼 & 临时更换 api 2023-02-06 11:58:04 +08:00
底层用户
0c4a85b458 Merge branch 'dev' of github.com:imsyy/home into dev 2023-02-02 11:06:26 +08:00
底层用户
854cebff03 新增 建站日期显示及配置 2023-02-02 11:06:16 +08:00
底层用户
ff18b63416
Merge pull request #64 from sumingyd/master
更新部署说明
2023-02-02 09:49:39 +08:00
底层用户
50023ea536
Update README.md 2023-02-02 09:48:29 +08:00
宿命
47fd9d3ee8
更新部署说明 2023-02-02 00:18:37 +08:00
宿命
436b7281df
Update README.md 2023-02-02 00:17:34 +08:00
宿命
09165d971a
Update README.md 2023-02-02 00:16:22 +08:00
宿命
b5ab4ac07c
更新部署说明 2023-02-02 00:14:56 +08:00
底层用户
50adca44e8
Merge pull request #58 from imsyy/dev
fix 当域名较长时样式出现错误
2023-02-01 20:18:12 +08:00
底层用户
c4c040402b 感谢链接 2023-02-01 20:17:04 +08:00
底层用户
d3248d2fd9 fix 一些样式 2023-01-31 20:24:16 +08:00
底层用户
b8ed0c1926 fix 当域名较长时样式出现错误 #56 2023-01-31 17:02:00 +08:00
底层用户
65d24f05d1
Merge pull request #53 from imsyy/dev
fix 社交链接配置文件位置错误
2023-01-30 19:43:29 +08:00
底层用户
041daf4c22 fix 社交链接配置文件位置错误 2023-01-30 19:42:34 +08:00
底层用户
431f3732f6
Merge pull request #52 from imsyy/dev
社交链接添加配置文件
2023-01-30 18:49:00 +08:00
底层用户
97007b05c1 社交链接添加配置文件 #49 2023-01-30 18:47:01 +08:00
底层用户
4c63155ada 新增 百度统计 2023-01-30 11:41:27 +08:00
底层用户
d5fc31ee83
Merge pull request #50 from Aewait/master
env新增站点logo设置,社交链接添加gitee
2023-01-30 11:17:24 +08:00
Ewait
bd2b1a903d 社交链接添加gitee 2023-01-30 10:53:35 +08:00
Ewait
4b5aaa8705 添加主页站点logo设置到env 2023-01-30 10:48:27 +08:00
底层用户
9ca1237f24
Merge pull request #46 from imsyy/dev
添加 PWA
2023-01-15 17:51:47 +08:00
底层用户
489a55ce1f Merge branch 'dev' of github.com:imsyy/home into dev 2023-01-15 17:48:29 +08:00
底层用户
cb5650396c 添加 PWA 2023-01-15 17:47:35 +08:00
底层用户
8c230537ce
Merge pull request #45 from imsyy/dev
样式调整
2023-01-15 16:08:11 +08:00
底层用户
a5461c39aa Merge branch 'dev' of github.com:imsyy/home into dev 2023-01-15 16:07:00 +08:00
底层用户
3c5557654b 样式修改 2023-01-15 16:05:49 +08:00
底层用户
00a91bbb36
Merge pull request #44 from imsyy/dev
新年快乐
2023-01-15 13:32:57 +08:00
底层用户
6103cafb36
Merge branch 'master' into dev 2023-01-15 13:24:56 +08:00
底层用户
5b15716092 Vue 重构 & 新年快乐 2023-01-15 13:22:30 +08:00
底层用户
abcfa92d8b 更新简介 2023-01-15 13:20:24 +08:00
底层用户
e5310257ed 屏蔽右键 2023-01-15 12:41:33 +08:00
底层用户
5090ce2e89 样式调整 2023-01-15 12:30:27 +08:00
底层用户
021e3c0bbe 移动端适配 2023-01-15 11:43:03 +08:00
底层用户
4ce5492139 修复播放器 2023-01-14 23:18:41 +08:00
底层用户
e7beed15cd Fix Music Player 2023-01-14 23:15:02 +08:00
底层用户
6e416bfec0 Fix Bug 2023-01-14 19:34:39 +08:00
底层用户
9da5e50040 版本封存,即将使用 Vue 重构 2022-12-10 15:17:24 +08:00
底层用户
3463084339 完善设置页面 2022-11-27 14:44:53 +08:00
底层用户
8c6dc91075 新增设置页面 2022-11-27 00:11:51 +08:00
底层用户
48afe35097 新增盒子组件 2022-11-17 22:41:37 +08:00
底层用户
0e32dd4113 Test 2022-11-17 16:40:38 +08:00
底层用户
9bf33c5610 Test 2022-11-17 14:36:06 +08:00
底层用户
700b53e79d Fix URL 2022-11-17 14:13:03 +08:00
底层用户
af659fe259 Fix Aplayer 2022-11-16 15:10:12 +08:00
底层用户
a7348a1893 Fix Aplayer 2022-11-16 10:04:33 +08:00
底层用户
311f30e4f0 Vue refactoring 2022-11-15 22:19:29 +08:00
底层用户
c0e460f1a8 test 2022-11-15 22:15:10 +08:00
底层用户
ed11a572c9 Fix 移动端去除鼠标样式 2022-08-04 10:41:47 +08:00
底层用户
b4d0e55e8f Fix link 2022-08-03 20:14:24 +08:00
底层用户
005b7cb886 更换为 HarmonyOS Sans 2022-08-03 19:33:01 +08:00
底层用户
d22c329264 音乐控件优化 & JS 优化 2022-08-02 10:25:29 +08:00
底层用户
c3b0dcd6cf 添加 ICP 备案 & 调整样式 2022-07-27 10:53:34 +08:00
底层用户
e3ea1e7364 修改音乐控件键盘事件 2022-07-14 16:25:08 +08:00
底层用户
fa99da9260 Merge branch 'master' of github.com:imsyy/home 2022-07-10 23:17:51 +08:00
底层用户
92bcd4e73f Fix 壁纸 API #12 2022-07-10 23:17:41 +08:00
底层用户
ec54393a93 Fix 壁纸 API 2022-07-10 23:13:32 +08:00
底层用户
5eda25c75e Fix 天气点击 2022-07-09 11:04:34 +08:00
底层用户
5e2fcd656a Fix 天气点击 2022-07-09 11:00:45 +08:00
底层用户
0af8f0ec2e 调整播放控件逻辑 2022-07-09 10:13:12 +08:00
底层用户
7803016119 天气 Fix 2022-07-08 09:42:15 +08:00
底层用户
d95b2708c3 去除配置文件 & 天气 API 更换 2022-07-07 21:42:10 +08:00
底层用户
0f71818829 更新 51LA 统计 2022-07-04 11:48:10 +08:00
底层用户
966580e3d8
Merge pull request #10 from Waynenet/master
移动端去除鼠标样式
2022-07-01 09:04:59 +08:00
Wayne
3489249f61
移动端去除鼠标样式
移动端去除鼠标样式
2022-06-30 16:23:38 +08:00
底层用户
1eab49d8bb 修改鼠标样式 #7 2022-06-30 11:58:43 +08:00
底层用户
cdf644caba 更新配置文件说明 2022-06-28 17:50:15 +08:00
底层用户
4b570d3f98 添加配置文件 2022-06-28 17:27:23 +08:00
底层用户
2604d143e6
Merge pull request #8 from Waynenet/master
修复移动端音量调节
2022-06-24 09:27:14 +08:00
Wayne
ab5b3f317e
修复移动端音量调节
修复移动端音量调节
2022-06-23 22:44:17 +08:00
底层用户
829dee9451 up README_EN 2022-06-22 17:44:09 +08:00
底层用户
eaf640bfd8 up README_EN 2022-06-22 17:42:51 +08:00
底层用户
f03616018f 更换 CDN 2022-06-22 14:46:30 +08:00
底层用户
ee349baa25 PWA Test 2022-06-21 17:23:38 +08:00
底层用户
9805f64da6 更换 CDN 2022-06-21 15:30:02 +08:00
底层用户
9d7f369f61 字体压缩 & 速度优化 2022-06-21 12:02:27 +08:00
底层用户
80a41ec182 优化加载速度 & 精简文件 2022-06-20 21:20:45 +08:00
底层用户
ca1b3dc00b Fix 天气调整 2022-05-29 19:39:58 +08:00
底层用户
20e8d972e3 Fix 天气信息超出边界 2022-05-29 11:19:48 +08:00
底层用户
34e9007870 Fix 移动端样式 2022-05-26 18:42:06 +08:00
底层用户
c306b60eab up 3.0 2022-05-25 19:55:17 +08:00
底层用户
042231c094 Change iconfont to FontAwesome 2022-05-24 14:30:14 +08:00
底层用户
9c141815f5 Fix 变量名重复 2022-05-23 20:59:22 +08:00
底层用户
d063784d73 Fix 变量名重复 2022-05-23 20:58:51 +08:00
底层用户
5f79695cef 一言点击可更换 2022-05-22 13:50:08 +08:00
底层用户
30c55aaa29 Test 2022-05-22 12:49:00 +08:00
底层用户
3d0ae1d6e1 音乐播放方式改变 & 去除无用的代码压缩 2022-05-22 12:02:03 +08:00
底层用户
6f18cc9193 修复字体链接 2022-05-20 17:37:18 +08:00
底层用户
43e4f32aec Fix 壁纸堆叠顺序问题 2022-05-16 19:03:47 +08:00
底层用户
cba6a1587f up README.md 2022-05-04 18:12:01 +08:00
底层用户
2cf00823fe 速度优化 2022-05-04 17:19:19 +08:00
底层用户
48978b467f 速度优化 2022-05-03 20:06:35 +08:00
底层用户
f82aef306c fix 51LA 2022-05-03 19:45:44 +08:00
底层用户
49fb4b49d5 新增 51.LA 统计 2022-04-25 23:06:37 +08:00
底层用户
bd4ad30524 新增 壁纸设置 2022-04-14 16:47:10 +08:00
底层用户
dbdf84c352 新增 个性化设置 2022-04-12 22:42:42 +08:00
底层用户
1ac1c05022 up link 2022-03-21 17:29:30 +08:00
底层用户
bee5fe6465 fix api 2022-03-17 22:58:41 +08:00
底层用户
6a5920ce3f Fix 天气api 2022-03-14 10:41:34 +08:00
底层用户
0fc2ad45a4 弹窗样式修改 2022-03-04 18:52:51 +08:00
底层用户
427c9ff678 LICENSE 2022-02-10 16:09:09 +08:00
底层用户
141fed8583 fix volume 2022-02-07 10:21:45 +08:00
底层用户
2f5aea8d6e up font 2022-02-04 13:41:05 +08:00
底层用户
96cbc413df up img 2022-02-03 16:26:59 +08:00
底层用户
12bceb4c83 fix js 2022-02-03 16:08:32 +08:00
底层用户
b1ea5e3aba 样式调整 & Fix Bug 2022-02-03 16:05:44 +08:00
底层用户
3817e6e43d add Firefox support 2022-01-29 16:46:29 +08:00
底层用户
d07179342c v1.6 & fix cdn 2022-01-29 13:09:21 +08:00
底层用户
1c9441e606 fix cdn 2022-01-28 23:05:45 +08:00
底层用户
1671006805 add noscript 2022-01-24 09:58:27 +08:00
底层用户
bd9531044f 样式调整 2022-01-22 18:55:56 +08:00
底层用户
26d12e33a7 Merge branch 'master' of github.com:imsyy/home 2022-01-22 10:58:28 +08:00
底层用户
f9cc6c73eb fix 底栏歌词显示 & 去除百度统计 2022-01-22 10:56:58 +08:00
底层用户
5c3d5cdeb0
Update vercel.json 2022-01-22 10:18:47 +08:00
底层用户
9b0a355ae1 添加 Vercel 404 跳转 2022-01-22 10:17:35 +08:00
底层用户
b9a9a126e0 fix 2022-01-21 14:12:12 +08:00
底层用户
9cf78b28db 更换字体 & 完善加载动画 2022-01-21 13:39:47 +08:00
底层用户
3f649c4369 new Dome 2022-01-20 22:16:13 +08:00
底层用户
35c6d60a35 完善页面进入动画 2022-01-20 21:56:06 +08:00
底层用户
ec5f157f2a time 2022-01-20 21:49:09 +08:00
底层用户
35aebf1061 fix js 2022-01-20 20:50:55 +08:00
底层用户
6e6fa9d7e4 up music-list 2022-01-20 17:36:09 +08:00
底层用户
c73da0a4ac 新增载入动画 & fix 部分边距不一致 2022-01-20 12:12:25 +08:00
底层用户
ec133f786b up music 2022-01-18 20:11:30 +08:00
底层用户
5722d17f43 底栏增加歌词显示 2022-01-18 12:31:38 +08:00
底层用户
7ff8f34dbd v1.5 & 音乐播放器 & 移动端优化 2022-01-17 22:38:05 +08:00
底层用户
06bf60ad49 新增 音乐播放器 2022-01-16 23:30:27 +08:00
底层用户
f93e064b67 fix ico 2022-01-16 11:37:34 +08:00
底层用户
0e711ecd88 fix 百度统计 2022-01-16 10:34:31 +08:00
底层用户
34b48250bf Update some 2022-01-16 10:28:16 +08:00
底层用户
f6d50e2093 fix 弹窗ico 2022-01-14 17:35:16 +08:00
底层用户
758d3b9958 fix cdn 2022-01-13 17:53:21 +08:00
底层用户
4a35a0f1d9 fix cdn 2022-01-13 17:45:17 +08:00
底层用户
f8a88ad4ce v1.4 & fix cdn & fix ico 2022-01-13 14:48:37 +08:00
底层用户
42723f01a0 fix cdn & new 新年灯笼 2022-01-12 23:24:24 +08:00
底层用户
b8c3c871aa up url 2021-12-13 14:57:50 +08:00
底层用户
bf587526bd Merge branch 'master' of github.com:imsyy/home 2021-12-13 14:43:56 +08:00
底层用户
4c49b61be0 添加 纪念日自动变灰 2021-12-13 14:43:50 +08:00
底层用户
04296fd05e
去除备案 2021-11-17 16:30:19 +08:00
底层用户
917517c1b0 fix api 2021-11-17 16:29:00 +08:00
底层用户
e01e943353 fix api 2021-11-17 15:35:51 +08:00
底层用户
2d8b8e8b80 修复背景图片、CSS 移动端优化 2021-11-14 16:58:31 +08:00
底层用户
6f47dbbe56 new old 2021-10-27 15:59:03 +08:00
底层用户
0c973a3622 去除备案 2021-10-27 15:55:16 +08:00
底层用户
c95b5e6691 delete 2021-10-13 18:20:02 +08:00
底层用户
5085e9ea1b
Update README.md 2021-10-13 18:18:21 +08:00
底层用户
29e36c3401 fix 一些小问题 2021-10-13 18:16:29 +08:00
123 changed files with 9838 additions and 2218 deletions

15
.dockerignore Normal file
View File

@ -0,0 +1,15 @@
node_modules
npm-debug.log
Dockerfile*
docker-compose*
.dockerignore
.git
.github
.gitignore
README.md
LICENSE
.vscode
dist
build
images
script

51
.env.example Normal file
View File

@ -0,0 +1,51 @@
# 站点信息
VITE_SITE_NAME = "無名の主页" # 名称
VITE_SITE_ANTHOR = "無名" # 作者
VITE_SITE_KEYWORDS = "無名,个人主页" # 关键词
VITE_SITE_DES = "一个默默无闻的主页" # 站点简介
VITE_SITE_URL = "imsyy.top" # 站点地址
VITE_SITE_LOGO = "/images/icon/favicon.ico" # 站点主图标
VITE_SITE_MAIN_LOGO = "/images/icon/logo.png" # 主页图标
VITE_SITE_APPLE_LOGO = "/images/logo/apple-touch-icon.png" # Apple 端图标
# 简介文本
VITE_DESC_HELLO = "Hello World !"
VITE_DESC_TEXT = "一个建立于 21 世纪的小站,存活于互联网的边缘"
VITE_DESC_HELLO_OTHER = "Oops !"
VITE_DESC_TEXT_OTHER = "哎呀,这都被你发现了( 再点击一次可关闭 "
# 社交链接
## 请在 src/assets/socialLinks.json 文件中配置
# 网站链接
## 请在 src/assets/siteLinks.json 文件中配置
## 网站链接的图标名称可前往 https://www.xicons.org 自行挑选并在 src/components/Links/index.vue 中引入
# 天气 Key
## 请前往 高德开放平台注册 Web服务 Key
## 请注意不是 Web端 (JS API),免费申请,每日上限 5000 次
## 此处提供的服务可能会超量从而无法访问,请自行申请!请自行申请!请自行申请!
## 若此处设为空则调用 教书先生 API https://api.oioweb.cn/doc/weather/GetWeather
VITE_WEATHER_KEY = ""
# 建站日期
## 若不需要,请设为空即可
## 请按照 YYYY-MM-DD 格式填写或者仅填写年份 YYYY
VITE_SITE_START = "2020-10-24"
# ICP 备案号
## 若不需要,请设为空即可
VITE_SITE_ICP = "豫ICP备2022018134号-1"
# 歌曲 API 地址
## 请参照 https://github.com/xizeyoupan/Meting-API#deno-deploy 进行 API 服务部署
## 此处提供的服务可能会超量从而无法访问,请自行部署
## 若使用 QQ 音乐歌单,歌曲数量最好不要超出 50 首
## 备用https://api.wuenci.com/meting/api/
VITE_SONG_API = "https://api-meting.imsyy.top/api"
# 歌曲服务器 ( netease-网易云, tencent-qq音乐 )
VITE_SONG_SERVER = "netease"
# 播放类型 ( song-歌曲, playlist-播放列表, album-专辑, search-搜索, artist-艺术家 )
VITE_SONG_TYPE = "playlist"
# 播放 ID ( 若无需播放器,请设为空即可 )
VITE_SONG_ID = "9379831714"

3
.eslintignore Normal file
View File

@ -0,0 +1,3 @@
node_modules
dist
.gitignore

35
.eslintrc.json Normal file
View File

@ -0,0 +1,35 @@
{
"env": {
"browser": true,
"es2021": true
},
"extends": ["eslint:recommended", "plugin:vue/vue3-essential"],
"parserOptions": {
"ecmaVersion": "latest",
"sourceType": "module"
},
"plugins": ["vue"],
"rules": {
"vue/multi-word-component-names": "off"
},
"globals": {
"defineProps": true,
"defineEmits": true,
"withDefaults": true,
"h": true,
"vue": true,
"ref": true,
"reactive": true,
"computed": true,
"watch": true,
"provide": true,
"inject": true,
"defineComponent": true,
"onBeforeMount": true,
"onMounted": true,
"onBeforeUnmount": true,
"nextTick": true,
"ElMessage": true,
"$openList": true
}
}

22
.github/ISSUE_TEMPLATE/bug-en.yml vendored Normal file
View File

@ -0,0 +1,22 @@
name: Encountering an Issue
description: Please provide details about the issue you are encountering
labels: [bug]
body:
- type: input
id: site-url
validations:
required: true
attributes:
label: "Site URL"
placeholder: "Please provide the URL of the site where the issue occurred"
- type: input
id: problem
attributes:
label: "Description of the Issue"
description: "Include any error messages or screenshots if applicable"
placeholder: "Please describe the issue you are encountering"
- type: textarea
id: other
attributes:
label: "Additional Information"
description: "Is there anything else you would like to add?"

22
.github/ISSUE_TEMPLATE/bug.yml vendored Normal file
View File

@ -0,0 +1,22 @@
name: 遇到问题
description: 请填写遇到的问题的详细信息
labels: [bug]
body:
- type: input
id: site-url
validations:
required: true
attributes:
label: "站点链接"
placeholder: "请填写你的站点链接"
- type: input
id: problem
attributes:
label: "问题描述"
description: "有错误的话请提供报错截图"
placeholder: "请详细描述一下遇到的问题"
- type: textarea
id: other
attributes:
label: "补充信息"
description: "还需要说些什么吗"

14
.github/ISSUE_TEMPLATE/other-en.yml vendored Normal file
View File

@ -0,0 +1,14 @@
name: Other Information
description: Any other issues or questions related to usage
labels: [other]
body:
- type: textarea
id: title
attributes:
label: "Description of the Issue"
description: "Please provide a clear description of the issue you are experiencing"
- type: textarea
id: other
attributes:
label: "Additional Information"
description: "Is there any other information you would like to add?"

14
.github/ISSUE_TEMPLATE/other.yml vendored Normal file
View File

@ -0,0 +1,14 @@
name: 其他信息
description: 关于使用上的问题
labels: [other]
body:
- type: textarea
id: title
attributes:
label: "问题描述"
description: "请尽量清晰的描述您遇到的问题"
- type: textarea
id: other
attributes:
label: "补充信息"
description: "有需要补充的信息吗"

46
.github/workflows/build.yml vendored Normal file
View File

@ -0,0 +1,46 @@
# Dev 分支推送部署预览
## 仅部署 Win 端
name: Build Dev
on:
push:
branches:
- dev
- master
jobs:
release:
name: Build Website
runs-on: windows-latest
steps:
# 检出 Git 仓库
- name: Check out git repository
uses: actions/checkout@v4.1.1
# 安装 Node.js
- name: Install Node.js
uses: actions/setup-node@v4.0.0
with:
node-version: "18.x"
# 复制环境变量文件
- name: Copy .env.example
run: |
if (-not (Test-Path .env)) {
Copy-Item .env.example .env
} else {
Write-Host ".env file already exists. Skipping the copy step."
}
# 安装项目依赖
- name: Install Dependencies
run: npm install
# 构建程序
- name: Build Website
run: npm run build
env:
GITHUB_TOKEN: ${{ secrets.ACCESS_TOKEN }}
# 上传构建产物
- name: Upload artifacts
uses: actions/upload-artifact@v3.1.3
with:
name: Home
path: dist

25
.gitignore vendored Normal file
View File

@ -0,0 +1,25 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
dist
dist-ssr
*.local
.env
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

17
.hintrc Normal file
View File

@ -0,0 +1,17 @@
{
"extends": [
"development"
],
"hints": {
"compat-api/html": "off",
"no-protocol-relative-urls": "off",
"compat-api/css": [
"default",
{
"ignore": [
"backdrop-filter"
]
}
]
}
}

8
.prettierrc.json Normal file
View File

@ -0,0 +1,8 @@
{
"$schema": "https://json.schemastore.org/prettierrc",
"singleQuote": false,
"trailingComma": "all",
"tabWidth": 2,
"semi": true,
"printWidth": 100
}

3
.vscode/extensions.json vendored Normal file
View File

@ -0,0 +1,3 @@
{
"recommendations": ["Vue.volar"]
}

128
CODE_OF_CONDUCT.md Normal file
View File

@ -0,0 +1,128 @@
# Contributor Covenant Code of Conduct
## Our Pledge
We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, religion, or sexual identity
and orientation.
We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.
## Our Standards
Examples of behavior that contributes to a positive environment for our
community include:
* Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes,
and learning from the experience
* Focusing on what is best not just for us as individuals, but for the
overall community
Examples of unacceptable behavior include:
* The use of sexualized language or imagery, and sexual attention or
advances of any kind
* Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or email
address, without their explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Enforcement Responsibilities
Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.
Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.
## Scope
This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
one@imsyy.top.
All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the
reporter of any incident.
## Enforcement Guidelines
Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:
### 1. Correction
**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.
**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.
### 2. Warning
**Community Impact**: A violation through a single incident or series
of actions.
**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or
permanent ban.
### 3. Temporary Ban
**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.
**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.
### 4. Permanent Ban
**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction within
the community.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.0, available at
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
Community Impact Guidelines were inspired by [Mozilla's code of conduct
enforcement ladder](https://github.com/mozilla/diversity).
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see the FAQ at
https://www.contributor-covenant.org/faq. Translations are available at
https://www.contributor-covenant.org/translations.

17
Dockerfile Normal file
View File

@ -0,0 +1,17 @@
# 构建应用
FROM node:18 AS builder
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN [ ! -e ".env" ] && cp .env.example .env || true
RUN npm run build
# 最小化镜像
FROM node:18-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
RUN npm install -g http-server
EXPOSE 12445
CMD ["http-server", "dist", "-p", "12445"]

21
LICENSE Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2022 imsyy
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

252
README.md
View File

@ -1,32 +1,244 @@
简体中文 | [English](./README_EN.md)
<p>
<strong><h2>無名の主页 </h2></strong>
一个小主页,原来的看够了,重新弄一个
<strong><h2>無名の主页</h2></strong>
简单的小主页,原来的看够了,重新弄了一个
</p>
### 功能
![無名の主页](/screenshots/main.jpg)
> 主页的 Logo 字体已经过压缩,若用本站 Logo 以外的字母会变回默认字体,这里是 [完整字体](https://file.imsyy.top/font/Other/Pacifico-Regular.ttf),若无法下载,可将字体目录下的 `Pacifico-Regular-all.ttf` 进行替换
### 👀 Demo
> 由于 CDN 缓存原因,查看最新效果可能需要 `Ctrl` + `F5` 强制刷新浏览器缓存
- [無名の主页](https://www.imsyy.top)
- [無名の主页 - Dev](https://home-imsyy.vercel.app)
- [無名の主页 - 备用线路](https://home-5iw.pages.dev)
### 🎉 功能
- [x] 载入动画
- [x] 站点简介
- [x] 一言展示
- [x] 年月日及时间展示
- [x] 天气信息
- [x] 时间胶囊 *时光进度条*
- [x] Hitokoto 一言
- [x] 日期及时间
- [x] 实时天气
- [x] 时光进度条
- [x] 音乐播放器
- [x] 移动端适配
* [ ] 音乐插件
* [ ] 没想好
### ⚙️ 自动部署
### 插件
如果遇到构建环境或者打包过程出现错误,则可以采用 `Github Actions` 来进行自动构建
* [Bootstrap](https://getbootstrap.com/)
* [iziToast](https://izitoast.marcelodolza.com/)
* [iconfont](https://www.iconfont.cn/)
* [Font Awesome](https://fontawesome.com/)
* [vue.js](https://v3.vuejs.org/)
* [jQuery](https://jquery.com/)
- 在成功 `fork` 仓库后,前往 `Actions` 页面,若您是首次开启,则会出现下面的提示,点击开启
![步骤1](/screenshots/step1.jpg)
- 然后在仓库中进行任意修改后均会触发工作流的运行,在工作流完成后,会在下方生成一个可供下载的压缩包,这就是构建出的静态文件,可自行上传至服务器
![步骤2](/screenshots/step2.jpg)
### ⚙️ 手动部署
- **安装** [node.js](https://nodejs.org/zh-cn/) **环境**
> node > 16.16.0
> npm > 8.15.0
- 然后以 **管理员权限** 运行 `cmd` 终端,并 `cd` 到 项目根目录
- 在 `终端` 中输入:
```bash
# 安装 pnpm
npm install -g pnpm
# 安装依赖
pnpm install
# 预览
pnpm dev
# 构建
pnpm build
```
> 构建完成后,静态资源会在 **`dist` 目录** 中生成,可将 **`dist` 文件夹下的文件**上传至服务器,也可使用 `Vercel` 等托管平台一键导入并自动部署
### ⚙️ Docker 部署
> 安装及配置 Docker 将不在此处说明,请自行解决
```bash
# 构建
docker build -t home .
# 运行
docker run -p 12445:12445 -d home
```
### ⚙️ Vercel 部署
> 其他部署平台大致相同,在此不做说明
1. 点击本仓库右上角的 `Fork`,复制本仓库到你的 `GitHub` 账号
2. 复制 `/.env.example` 文件并重命名为 `/.env` 重要
3. 按需修改 `/.env` 文件中的配置
4. 点击 `Deploy`,即可成功部署
### 网站链接
`src/assets/siteLinks.json` 中可以自定义网站链接(以指向自己的网站):
```json
{
"icon": "Blog",
"name": "博客",
"link": "https://blog.imsyy.top/"
},
```
其中 `icon` 网站链接的图标可以在 `src/components/Links/index.vue` 中添加:
```js
// 可前往 https://www.xicons.org 自行挑选并在此处引入
// 此处引入的是 fa 类型
import {
Link,
Blog,
CompactDisc,
Cloud,
Compass,
Book,
Fire,
LaptopCode,
} from "@vicons/fa";
...
// 网站链接图标
const siteIcon = {
Blog,
Cloud,
CompactDisc,
Compass,
Book,
Fire,
LaptopCode,
};
```
### 社交链接
`src/assets/socialLinks.json` 中可以自定义社交链接。
### 天气
天气及地区获取需要 `高德开放平台` 相关 API
- 前往 [高德开放平台控制台](https://console.amap.com/dev/index) 创建一个 `Web 服务` 类型的 `Key`,并将 `Key` 填入 `.env` 中的 `VITE_WEATHER_KEY`
也可自行更换其他方式
### 音乐
> 本项目采用了基于 `MetingJS``Aplayer` 音乐播放器,可实现快速自定义歌单
> \*仅支持 **中国大陆地区**
请在 `.env` 文件中更改歌曲相关参数即可实现自定义歌单列表
```bash
# 歌曲 API 地址
VITE_SONG_API = "https://api-meting.imsyy.top"
# 歌曲服务器 ( netease-网易云, tencent-qq音乐 )
VITE_SONG_SERVER = "netease"
# 播放类型 ( song-歌曲, playlist-播放列表, album-专辑, search-搜索, artist-艺术家 )
VITE_SONG_TYPE = "playlist"
# 播放 ID
VITE_SONG_ID = "7452421335"
```
### 字体
现采用 `HarmonyOS Sans` 开源字体,采用字体拆分,提升加载速度
> 由于本站 `CDN` 已开启防盗链,**非本站域名不可访问**,请将字体引入链接更改为下方内容,否则 **自定义字体将失效**
>
> `https://s1.hdslb.com/bfs/static/jinkela/long/font/regular.css`
<details>
<summary>旧版方式</summary>
> 由于本项目引入了中文字体,需要压缩中文字体以提高网页加载速度( 也可以取消使用中文字体
#### 中文字体去除繁体
- 安装 `Python 3.7``pip`
- 运行 `pip install fonttools`
- 下载 [sc_unicode.txt](https://gist.githubusercontent.com/imaegoo/d64e5088b723c2e02c40985f55ff12db/raw/5ebd2ce49418c73459a9dfe050483409306a6c1d/sc_unicode.txt)
- 运行 `pyftsubset 字体名称.ttf --unicodes-file=sc_unicode.txt`
#### 字体进一步压缩
- 编译安装 `Google woff2`
```bash
sudo apt-get install -y git g++ make
git clone --recursive https://github.com/google/woff2.git
cd woff2
make clean all
```
- 再压缩字体
```
./woff2_compress ./字体名称.ttf
```
- 最终可对原字体进行缓加载,**先行加载压缩后的字体**
> 详细信息可前往 [虹墨空间站](https://www.imaegoo.com/2020/chinese-font-compress/) 查看原文
</details>
### 网站图标及网站背景
#### 网站背景
可以在 `public/images` 中修改网站背景
如果想要添加更多的本地图片作为网站背景,可以将图片重命名 `background+数字` 的形式,并在 `src/components/Background/index.vue` 中进行修改:
```js
if (type == 0) {
// 修改此处 Math.random() 后面的第一个数字为图片的数量
bgUrl.value = `/images/background${Math.floor(Math.random() * 10 + 1)}.webp`;
}
```
#### 网站图标
可以在 `public/images/icon` 中修改网站图标。
### 技术栈
- [Vue](https://cn.vuejs.org/)
- [Vite](https://vitejs.cn/vite3-cn/)
- [Pinia](https://pinia.vuejs.org/zh/)
- [IconPark](https://iconpark.oceanengine.com/official)
- [xicons](https://xicons.org/)
- [Aplayer](https://aplayer.js.org/)
### API
* [JsonBird](https://bird.ioliu.cn/)
* [天气 API](https://www.tianqiapi.com/)
* [Hitokoto - 一言](https://hitokoto.cn/)
- [韩小韩 WebAPI 接口](https://api.vvhan.com/)
- [搏天 API](https://api.btstu.cn/doc/sjbz.php)
- [教书先生 API](https://api.oioweb.cn/doc/weather/GetWeather)
- [高德开放平台](https://lbs.amap.com/)
- [Hitokoto 一言](https://hitokoto.cn/)
<a title="SSL" target="_blank" href="https://myssl.com/seal/detail?domain=blog.imsyy.top"><img src="https://img.shields.io/badge/MySSL-安全认证-brightgreen"></a>&nbsp;<a title="CDN" target="_blank" href="https://www.upyun.com/?utm_source=lianmeng&utm_medium=referral"><img src="https://img.shields.io/badge/CDN-%E5%8F%88%E6%8B%8D%E4%BA%91-blue"></a>&nbsp;<a title="beian" target="_blank" href="https://beian.miit.gov.cn/"><img src="https://img.shields.io/badge/%E8%B1%ABICP%E5%A4%87-20013231--2%E5%8F%B7-important"></a>&nbsp;<a title="Copyright" target="_blank" href="https://imsyy.top/"><img src="https://img.shields.io/badge/Copyright%20%C2%A9%202020--2021-%E7%84%A1%E5%90%8D-red"></a>
## Star History
[![Star History Chart](https://api.star-history.com/svg?repos=imsyy/home&type=Date)](https://star-history.com/#imsyy/home&Date)
<a title="SSL" target="_blank" href="https://myssl.com/seal/detail?domain=blog.imsyy.top"><img src="https://img.shields.io/badge/MySSL-安全认证-brightgreen"></a>&nbsp;<a title="CDN" target="_blank" href="https://cdnjs.com/"><img src="https://img.shields.io/badge/CDN-Cloudflare-blue"></a>&nbsp;<a title="Copyright" target="_blank" href="https://imsyy.top/"><img src="https://img.shields.io/badge/Copyright%20%C2%A9%202020--2023-%E7%84%A1%E5%90%8D-red"></a>

144
README_EN.md Normal file
View File

@ -0,0 +1,144 @@
English | [Chinese](./README.md)
<p>
<strong><h2>無名の主页</h2></strong>
Simple little homepage, had enough of the original one and made a new one
</p>
![無名の主页](https://s2.loli.net/2022/07/14/K5JigfvDoNewtuS.webp)
>The logo font on the home page has been compressed, so if you use a font other than this logo, it will change back to the default font, Here is the [full font](https://file.4everland.app/font/Other/Pacifico-Regular.ttf)
### Demo
>Due to CDN caching, you may need `Ctrl` + `F5` to force a browser cache refresh to see the latest results
- [無名の主页](https://www.imsyy.top)
- [無名の主页 - Dev](https://home-imsyy.vercel.app)
- [無名の主页 - Standby](https://home-5iw.pages.dev)
### Functions
- [x] Loading animation
- [x] Site description
- [x] Hitokoto
- [x] Date and time
- [x] Live weather
- [x] Time progress bar
- [x] Music player
- [x] Mobile adaptation
* [ ] Player cancels using Aplayer
### Deployment
* **Installation** [node.js](https://nodejs.org/zh-cn/) **Environment**
> node > 16.16.0
> npm > 8.15.0
* Then run the `cmd` terminal with **administrator privileges** and `cd` to the project root directory
* In the `terminal` type:
```bash
# Install pnpm
npm install -g pnpm
# Install the dependencies
pnpm install
# Preview
pnpm dev
# Build
pnpm build
```
> Once the build is complete, the files in the `dist` folder can be uploaded to the server or imported and automatically deployed with one click using a hosting platform such as `Vercel`.
### Weather
Weather and area access requires `高德开放平台` related API
- Go to [高德开放平台控制台](https://console.amap.com/dev/index) to create a `Key` of type `Web Service` and fill the `Key` into `VITE_WEATHER_KEY` in `.env`
It can also be replaced by other methods
### Music
>This project uses the `Aplayer` music player based on `MetingJS` for quick song list customization
>*Only supported in **Mainland China**
Please change the song related parameters in the `.env` file to customize the song list
```bash
# Songs API address
VITE_SONG_API = "https://api-meting.imsyy.top"
# Song server ( netease-netease, tencent-qq music )
VITE_SONG_SERVER = "netease"
# Playback type ( song-song, playlist-playlist, album-album, search-search, artist-artist )
VITE_SONG_TYPE = "playlist"
# Playback ID
VITE_SONG_ID = "7452421335"
```
### Fonts
Now using `HarmonyOS Sans` open source font, using font splitting to improve loading speed
>Because this site's `CDN` has opened anti-leech, **non-site domain name is not accessible**, please change the font import link to the following content, otherwise **custom fonts will be invalid**
>
>`https://cdn.jsdelivr.net/gh/imsyy/file/font/HarmonyOS_Sans/regular.min.css`
<details>
<summary>old way</summary>
>As Chinese fonts are introduced in this project, Chinese fonts need to be compressed to improve the loading speed of the page (you can also cancel the use of Chinese fonts)
#### Chinese font removal traditional
- Install `Python 3.7` and `pip`
- Run `pip install fonttools`
- Download [sc_unicode.txt](https://gist.githubusercontent.com/imaegoo/d64e5088b723c2e02c40985f55ff12db/raw/5ebd2ce49418c73459a9dfe050483409306a6c1d/sc_unicode.txt)
- Run `pyftsubset font-name.ttf --unicodes-file=sc_unicode.txt`
#### fonts further compressed
- Compile and install ``Google woff2``
```bash
sudo apt-get install -y git g++ make
git clone --recursive https://github.com/google/woff2.git
cd woff2
make clean all
```
- Compress the font again
```
. /woff2_compress . /font_name.ttf
```
- Eventually the original font can be slow loaded, **load the compressed font first**
>For more information, please go to [虹墨空间站](https://www.imaegoo.com/2020/chinese-font-compress/) to view the original article
</details>
### Technology Stack
* [Vue](https://cn.vuejs.org/)
* [Vite](https://vitejs.cn/vite3-cn/)
* [Pinia](https://pinia.vuejs.org/zh/)
* [IconPark](https://iconpark.oceanengine.com/official)
* [xicons](https://xicons.org/)
* [Aplayer](https://aplayer.js.org/)
### API
* [韩小韩 WebAPI 接口](https://api.vvhan.com/)
* [搏天 API](https://api.btstu.cn/doc/sjbz.php)
* [高德开放平台](https://lbs.amap.com/)
* [Hitokoto 一言](https://hitokoto.cn/)
<a title="SSL" target="_blank" href="https://myssl.com/seal/detail?domain=blog.imsyy.top"><img src="https://img.shields.io/badge/MySSL-安全认证-brightgreen"></a>&nbsp;<a title="CDN" target="_blank" href="https://cdnjs.com/"><img src="https://img.shields.io/badge/CDN-Cloudflare-blue"></a>&nbsp;<a title="Copyright" target="_blank" href="https://imsyy.top/"><img src="https://img.shields.io/badge/Copyright%20%C2%A9%202020--2023-%E7%84%A1%E5%90%8D-red"></a>

57
auto-imports.d.ts vendored Normal file
View File

@ -0,0 +1,57 @@
// Generated by 'unplugin-auto-import'
export {}
declare global {
const EffectScope: typeof import('vue')['EffectScope']
const ElMessage: typeof import('element-plus/es')['ElMessage']
const computed: typeof import('vue')['computed']
const createApp: typeof import('vue')['createApp']
const customRef: typeof import('vue')['customRef']
const defineAsyncComponent: typeof import('vue')['defineAsyncComponent']
const defineComponent: typeof import('vue')['defineComponent']
const effectScope: typeof import('vue')['effectScope']
const getCurrentInstance: typeof import('vue')['getCurrentInstance']
const getCurrentScope: typeof import('vue')['getCurrentScope']
const h: typeof import('vue')['h']
const inject: typeof import('vue')['inject']
const isProxy: typeof import('vue')['isProxy']
const isReactive: typeof import('vue')['isReactive']
const isReadonly: typeof import('vue')['isReadonly']
const isRef: typeof import('vue')['isRef']
const markRaw: typeof import('vue')['markRaw']
const nextTick: typeof import('vue')['nextTick']
const onActivated: typeof import('vue')['onActivated']
const onBeforeMount: typeof import('vue')['onBeforeMount']
const onBeforeUnmount: typeof import('vue')['onBeforeUnmount']
const onBeforeUpdate: typeof import('vue')['onBeforeUpdate']
const onDeactivated: typeof import('vue')['onDeactivated']
const onErrorCaptured: typeof import('vue')['onErrorCaptured']
const onMounted: typeof import('vue')['onMounted']
const onRenderTracked: typeof import('vue')['onRenderTracked']
const onRenderTriggered: typeof import('vue')['onRenderTriggered']
const onScopeDispose: typeof import('vue')['onScopeDispose']
const onServerPrefetch: typeof import('vue')['onServerPrefetch']
const onUnmounted: typeof import('vue')['onUnmounted']
const onUpdated: typeof import('vue')['onUpdated']
const provide: typeof import('vue')['provide']
const reactive: typeof import('vue')['reactive']
const readonly: typeof import('vue')['readonly']
const ref: typeof import('vue')['ref']
const resolveComponent: typeof import('vue')['resolveComponent']
const resolveDirective: typeof import('vue')['resolveDirective']
const shallowReactive: typeof import('vue')['shallowReactive']
const shallowReadonly: typeof import('vue')['shallowReadonly']
const shallowRef: typeof import('vue')['shallowRef']
const toRaw: typeof import('vue')['toRaw']
const toRef: typeof import('vue')['toRef']
const toRefs: typeof import('vue')['toRefs']
const triggerRef: typeof import('vue')['triggerRef']
const unref: typeof import('vue')['unref']
const useAttrs: typeof import('vue')['useAttrs']
const useCssModule: typeof import('vue')['useCssModule']
const useCssVars: typeof import('vue')['useCssVars']
const useSlots: typeof import('vue')['useSlots']
const watch: typeof import('vue')['watch']
const watchEffect: typeof import('vue')['watchEffect']
const watchPostEffect: typeof import('vue')['watchPostEffect']
const watchSyncEffect: typeof import('vue')['watchSyncEffect']
}

35
components.d.ts vendored Normal file
View File

@ -0,0 +1,35 @@
// generated by unplugin-vue-components
// We suggest you to commit this file into source control
// Read more: https://github.com/vuejs/core/pull/3399
import '@vue/runtime-core'
export {}
declare module '@vue/runtime-core' {
export interface GlobalComponents {
Background: typeof import('./src/components/Background.vue')['default']
ElCard: typeof import('element-plus/es')['ElCard']
ElCol: typeof import('element-plus/es')['ElCol']
ElCollapse: typeof import('element-plus/es')['ElCollapse']
ElCollapseItem: typeof import('element-plus/es')['ElCollapseItem']
ElProgress: typeof import('element-plus/es')['ElProgress']
ElRadio: typeof import('element-plus/es')['ElRadio']
ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup']
ElRow: typeof import('element-plus/es')['ElRow']
ElSlider: typeof import('element-plus/es')['ElSlider']
ElSwitch: typeof import('element-plus/es')['ElSwitch']
ElTooltip: typeof import('element-plus/es')['ElTooltip']
Footer: typeof import('./src/components/Footer.vue')['default']
Hitokoto: typeof import('./src/components/Hitokoto.vue')['default']
Links: typeof import('./src/components/Links.vue')['default']
Loading: typeof import('./src/components/Loading.vue')['default']
Message: typeof import('./src/components/Message.vue')['default']
MoreContent: typeof import('./src/components/MoreContent.vue')['default']
Music: typeof import('./src/components/Music.vue')['default']
Player: typeof import('./src/components/Player.vue')['default']
Set: typeof import('./src/components/Set.vue')['default']
SocialLinks: typeof import('./src/components/SocialLinks.vue')['default']
TimeCapsule: typeof import('./src/components/TimeCapsule.vue')['default']
Weather: typeof import('./src/components/Weather.vue')['default']
}
}

View File

@ -1,89 +0,0 @@
/*模糊渐入动画*/
@keyframes fade-in {
0% {
opacity: 0;
backdrop-filter: blur(0px);
}
100% {
opacity: 1;
backdrop-filter: blur(10px);
}
}
@-webkit-keyframes fade-in {
0% {
opacity: 0;
backdrop-filter: blur(0px);
}
100% {
opacity: 1;
backdrop-filter: blur(10px);
}
}
@-moz-keyframes fade-in {
0% {
opacity: 0;
backdrop-filter: blur(0px);
}
100% {
opacity: 1;
backdrop-filter: blur(10px);
}
}
@-o-keyframes fade-in {
0% {
opacity: 0;
backdrop-filter: blur(0px);
}
100% {
opacity: 1;
backdrop-filter: blur(10px);
}
}
/*渐入动画*/
@keyframes fade {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
@-webkit-keyframes fade {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
@-moz-keyframes fade {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
@-o-keyframes fade {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}

View File

@ -1,64 +0,0 @@
@font-face {
font-family: "iconfont";
src: url('../font/font_2831425_80aedhvquju.woff2') format('woff2'),
url('../font/font_2831425_80aedhvquju.woff') format('woff'),
url('../font/font_2831425_80aedhvquju.ttf') format('truetype');
}
@font-face {
font-family: "Pacifico-Regular";
src: url('../font/Pacifico-Regular.ttf');
}
@font-face {
font-family: "UnidreamLED";
src: url('../font/UnidreamLED.ttf');
}
.iconfont {
font-family: "iconfont" !important;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.icon-youxiang:before {
content: "\e605";
}
.icon-github:before {
content: "\e691";
}
.icon-telegram1:before {
content: "\e731";
}
.icon-QQ:before {
content: "\e882";
}
.icon-twitter:before {
content: "\e883";
}
.icon-github1:before {
content: "\e799";
}
.icon-weixin:before {
content: "\e600";
}
.icon-telegram:before {
content: "\e8db";
}
.icon-yinhao-copy:before {
content: "\e608";
}
.icon-yinhao-copy-copy:before {
content: "\e62e";
}

View File

@ -1,125 +0,0 @@
#loading-box .loading-left-bg,
#loading-box .loading-right-bg {
position: fixed;
z-index: 999998;
width: 50%;
height: 100%;
background-color: rgb(81 81 81 / 80%);
transition: all 0.7s cubic-bezier(0.42, 0, 0, 1.01);
backdrop-filter: blur(40px);
}
#loading-box .loading-right-bg {
right: 0;
}
#loading-box>.spinner-box {
position: fixed;
z-index: 999999;
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 100vh;
}
#loading-box .spinner-box .loading-word {
position: absolute;
color: #ffffff;
font-size: 0.95rem;
transform: translateY(64px);
text-align: center;
}
p.loading-title {
font-size: 1.25rem;
margin: 20px 10px 4px 10px;
}
#loading-box .spinner-box .configure-core {
width: 100%;
height: 100%;
background-color: #37474f;
}
div.loaded div.loading-left-bg {
transform: translate(-100%, 0);
}
div.loaded div.loading-right-bg {
transform: translate(100%, 0);
}
div.loaded div.spinner-box {
display: none !important;
}
.loader {
position: absolute;
top: calc(50% - 32px);
left: calc(50% - 32px);
width: 64px;
height: 64px;
border-radius: 50%;
perspective: 800px;
transition: all 0.7s cubic-bezier(0.42, 0, 0, 1.01);
}
.inner {
position: absolute;
box-sizing: border-box;
width: 100%;
height: 100%;
border-radius: 50%;
}
.inner.one {
left: 0%;
top: 0%;
animation: rotate-one 1s linear infinite;
border-bottom: 3px solid #EFEFFA;
}
.inner.two {
right: 0%;
top: 0%;
animation: rotate-two 1s linear infinite;
border-right: 3px solid #EFEFFA;
}
.inner.three {
right: 0%;
bottom: 0%;
animation: rotate-three 1s linear infinite;
border-top: 3px solid #EFEFFA;
}
@keyframes rotate-one {
0% {
transform: rotateX(35deg) rotateY(-45deg) rotateZ(0deg);
}
100% {
transform: rotateX(35deg) rotateY(-45deg) rotateZ(360deg);
}
}
@keyframes rotate-two {
0% {
transform: rotateX(50deg) rotateY(10deg) rotateZ(0deg);
}
100% {
transform: rotateX(50deg) rotateY(10deg) rotateZ(360deg);
}
}
@keyframes rotate-three {
0% {
transform: rotateX(35deg) rotateY(55deg) rotateZ(0deg);
}
100% {
transform: rotateX(35deg) rotateY(55deg) rotateZ(360deg);
}
}

View File

@ -1,254 +0,0 @@
@charset"utf-8";
/*小于1400px时*/
@media (max-width: 1400px) {}
/*小于1200px时*/
@media (max-width: 1200px) {
/*总布局*/
.container,
.container-lg,
.container-md,
.container-sm {
max-width: 1100px !important;
}
.weekday {
display: none;
}
}
/*小于992px时*/
@media (max-width: 992px) {
/*简介不可点击
.message {
pointer-events: none;
}
*/
/*一言*/
.col.hitokotos {
display: none;
}
/*日期显示*/
.weekday {
display: inline;
}
/*标题文字*/
.main-img img {
width: 110px;
}
span.img-title {
font-size: 4.75rem;
}
span.img-text {
font-size: 1.75rem;
}
}
/*小于840px时*/
@media (max-width: 840px) {
/*社交链接*/
.social {
max-width: 100%;
justify-content: center;
}
#link-text {
display: none !important;
}
.link i {
margin: 0px 20px;
}
}
/*小于789px时*/
@media (max-width: 789px) {
/*标题文字*/
span.img-text {
display: none;
}
}
/*小于768px时*/
@media (max-width: 768px) {
/*标题文字*/
.main-img img {
width: 100px;
}
span.img-title {
font-size: 4.5rem;
}
}
/*小于660px时*/
@media (max-width: 660px) {
/*左侧栏高度*/
.main-left {
transform: translateY(20px);
}
/*右侧栏隐藏*/
.col.right {
display: none;
}
/*标题文字*/
span.img-text {
display: inline;
}
/*简介*/
.message {
max-width: 100%;
pointer-events: none;
}
/*
.des {
justify-content: space-between;
}
*/
/*菜单栏按钮*/
.menu {
display: flex;
justify-content: center;
position: fixed;
top: 84%;
}
.munu-button {
padding: 5px 20px;
background: rgb(0 0 0 / 20%);
backdrop-filter: blur(10px);
border-radius: 6px;
font-size: 1.25rem;
transition: 0.5s;
width: 60px;
display: flex;
justify-content: center;
align-items: center;
height: 40px;
}
/*页脚文字*/
footer {
font-size: 0.85rem;
}
}
@media (min-width: 660px) {
.menu {
display: none !important;
}
/*时钟显示*/
span#win_text,
span#win_speed {
display: none;
}
}
/*小于390px时*/
@media (max-width: 390px) {
.main-img img {
display: none;
}
}
/*
菜单按钮
*/
.menus .col.left {
display: none;
}
.menus .col.right {
display: block !important;
transition: 0.5s;
padding: 0rem 0.75rem;
}
/*功能区调整*/
.menus .col.hitokotos {
display: block;
}
.menus .col.times {
display: none;
}
/*边界布局*/
.menus .row {
--bs-gutter-x: 0rem;
}
.menus .col.\32 {
margin: 0 0.75rem;
}
.menus .logo {
display: inline !important;
text-align: center;
position: fixed;
top: 8%;
font-family: 'Pacifico-Regular';
font-size: 1.75rem;
}
/*切换动画*/
/*
.hitokoto,
.time,
.link-card,
.message {
animation: fade-in;
-webkit-animation: fade-in 0.5s;
-moz-animation: fade-in 0.5s;
-o-animation: fade-in 0.5s;
-ms-animation: fade-in 0.5s;
}
*/
.logo,
.line,
.main-img,
.social,
.close,
.hitokoto,
.time,
.link-card,
.message,
#link-text {
animation: fade 0.5;
-webkit-animation: fade 0.5s;
-moz-animation: fade 0.5s;
-o-animation: fade 0.5s;
-ms-animation: fade 0.5s;
}
/*
移动端功能区切换
*/
.mobile .col.hitokotos {
display: none;
}
.mobile .col.times {
display: block;
}

View File

@ -1,387 +0,0 @@
@charset"utf-8";
/*全局样式*/
html,
body {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
*,
a,
p {
text-decoration: none;
transition: 0.3s;
color: #efefef;
user-select: none;
}
a:hover {
color: white;
}
.cards {
transition: 0.5s;
}
.cards:hover {
transform: scale(1.01);
transition: 0.5s;
}
.cards:active {
transform: scale(0.95);
transition: 0.5s;
}
/*页面样式*/
section {
display: block;
position: fixed;
width: 100%;
height: 100%;
}
main {
width: 100%;
height: 100%;
background: rgb(0 0 0 / 20%);
display: flex;
/*align-items: center;*/
}
.container {
width: 100%;
display: flex;
justify-content: space-around;
}
.row {
align-items: center;
justify-content: center;
width: 100%;
}
.main-left {
/*transform: translateY(240px);*/
transform: translateY(40px);
}
/*
.main-right {
transform: translateY(38%);
}
*/
.row.rightone {
display: flex;
align-items: center;
}
/*头像*/
.main-img {
display: flex;
align-items: center;
}
.main-img img {
border-radius: 50%;
width: 120px;
}
.img-title {
width: 100%;
margin-left: 12px;
font-family: Pacifico-Regular;
transform: translateY(-8%);
}
span.img-title {
font-size: 5rem;
}
span.img-text {
font-size: 2rem;
}
/*简介*/
.message {
background: rgb(0 0 0 / 25%);
backdrop-filter: blur(10px);
/*margin: 0.5rem;*/
padding: 1rem;
border-radius: 6px;
margin-top: 3.5rem;
max-width: 460px;
cursor:pointer;
}
.des {
display: flex;
justify-content: space-between;
}
p.des-title {
margin: 1rem 1rem;
line-height: 2rem;
font-family: Pacifico-Regular;
}
i.iconfont.icon-yinhao-copy {
align-self: flex-end;
}
/*社交链接*/
.social {
margin-top: 1rem;
display: flex;
align-items: center;
max-width: 460px;
}
.link i {
font-size: 1.75rem;
margin: 0px 10px;
}
#link-text {
display: none;
flex: 1;
text-align: right;
margin-right: 1rem;
}
/*一言*/
.hitokoto {
width: 100%;
background: rgb(0 0 0 / 25%);
backdrop-filter: blur(10px);
padding: 20px;
border-radius: 6px;
}
.hitokoto-all {
margin-top: 10px;
display: flex;
flex-direction: column;
}
.hitokoto-from {
margin-top: 10px;
font-weight: bold;
align-self: flex-end;
}
/*时间卡片*/
.time {
width: 100%;
background: rgb(0 0 0 / 25%);
backdrop-filter: blur(10px);
padding: 20px;
border-radius: 6px;
text-align: center;
display: flex;
flex-direction: column;
}
span.time-text {
font-size: 3.25rem;
letter-spacing: 2px;
font-family: UnidreamLED;
}
/*链接卡片*/
.line {
margin: 1rem 0.25rem;
margin-top: 2rem;
font-size: 1.10rem;
}
.link-card {
height: 100px;
width: 100%;
border-radius: 6px;
background: rgb(0 0 0 / 25%);
backdrop-filter: blur(10px);
display: flex;
align-items: center;
flex-direction: column;
justify-content: space-evenly;
}
.link-card:hover {
background: rgb(0 0 0 / 40%);
transition: 0.5s;
}
/*更多页面*/
.more {
display: none !important;
width: 46%;
z-index: 999;
position: fixed;
height: 82%;
right: 4%;
background: rgb(0 0 0 / 25%);
backdrop-filter: blur(10px);
top: 7%;
border-radius: 6px;
padding: 30px;
}
.mores .more {
display: flex !important;
justify-content: space-evenly;
flex-direction: column;
align-items: center;
animation: fade;
-webkit-animation: fade 0.3s;
-moz-animation: fade 0.3s;
-o-animation: fade 0.3s;
-ms-animation: fade 0.3s;
}
.mores .col.right {
display: none;
}
/*关闭按钮*/
.close {
display: none;
left: auto;
top: 4px;
right: 8px;
font-size: 1.45rem;
}
.close:hover {
transform: scale(1.2);
}
/*进度条*/
.progress {
width: 100%;
height: 20px;
align-items: center;
background: rgb(255 255 255 / 25%) !important;
backdrop-filter: blur(5px);
}
.progress-bar {
font-family: 'UnidreamLED';
background-color: #efefef !important;
color: rgb(86 77 89) !important;
font-size: 0.95rem;
height: 20px;
}
/*时间胶囊*/
.date {
width: 100%;
}
.date-text {
margin: 1rem 0rem 0.5rem 0rem;
}
/*更多页面链接*/
.mores .link-card {
height: 48px !important;
}
/*box*/
.box {
position: fixed;
left: 0;
right: 0;
top: 0;
bottom: 0;
z-index: 1996;
background-color: rgba(0, 0, 0, .5);
backdrop-filter: blur(20px);
animation: fade 0.3s;
}
.box-wrapper {
position: absolute;
top: 50%;
left: 50%;
-webkit-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
z-index: 1997;
width: 80%;
height: 80%;
background: rgb(255 255 255 / 40%);
border-radius: 6px;
-webkit-animation: fade .3s;
animation: fade .3s;
padding: 40px;
display: flex;
flex-direction: column;
justify-content: space-evenly;
}
.upnote {
margin-top: 2rem;
margin-left: 2rem;
display: flex;
flex-direction: column;
line-height: 40px;
font-size: 1.25rem;
}
.closebox {
left: auto;
top: 4px;
right: 8px;
font-size: 1.45rem;
}
.closebox:hover {
transform: scale(1.2);
}
/*页脚样式*/
footer {
text-align: center;
height: 46px;
backdrop-filter: blur(10px);
background: rgb(0 0 0 / 25%);
}
.power {
line-height: 46px;
opacity: 0.8;
}
/*弹窗样式*/
.iziToast {
background: rgb(0 0 0 / 45%) !important;
backdrop-filter: blur(10px) !important;
}
.iziToast-body .iziToast-message {
line-height: 18px !important;
}
.iziToast:after {
box-shadow: none !important;
}
.iziToast-message.slideIn {
margin-top: 5px !important;
}
.iziToast-message {
word-break: break-all !important;
}
.iziToast>.iziToast-close {
background: url(https://cdn.jsdelivr.net/gh/imsyy/file/pic/close.png) no-repeat 50% 50% !important;
background-size: 8px !important;
}

9
docker-compose.yml Normal file
View File

@ -0,0 +1,9 @@
version: '3'
services:
app:
build:
context: .
dockerfile: Dockerfile
ports:
- "12445:12445"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

View File

@ -1,330 +1,39 @@
<!DOCTYPE html>
<!doctype html>
<html lang="zh-CN">
<head>
<!-- 基础信息 -->
<meta charset="utf-8">
<meta http-equiv="Access-Control-Allow-Origin" content="*">
<meta name="renderer" content="webkit" />
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta name="force-rendering" content="webkit" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="無名の主页">
<meta name="keywords" content="無名,个人主页">
<meta name="author" content="無名">
<title>無名の主页</title>
<!-- 引入样式 -->
<link rel="stylesheet" type="text/css"
href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.1/dist/css/bootstrap.min.css">
<link rel="stylesheet" type="text/css" href="./css/style.css">
<link rel="stylesheet" type="text/css" href="./css/mobile.css">
<link rel="stylesheet" type="text/css" href="./css/font.css">
<link rel="stylesheet" type="text/css" href="./css/loading.css">
<link rel="stylesheet" type="text/css" href="./css/animation.css">
<link rel="icon" href="./favicon.ico">
<link rel="apple-touch-icon" href="./img/apple-touch-icon.png">
<!-- 引入 Izitoast -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/izitoast@1.4.0/dist/css/iziToast.min.css">
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/izitoast@1.4.0/dist/js/iziToast.min.js"></script>
<!-- 引入 Fontawesome -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/volantis-x/cdn-fontawesome-pro@master/css/all.min.css"
media="all">
<!--引入 Vue-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.min.js"></script>
<!-- 引入 jQuery -->
<script src="https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.min.js"></script>
<!-- 百度统计 -->
<head>
<meta charset="UTF-8" />
<meta http-equiv="Access-Control-Allow-Origin" content="*" />
<!-- <meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests"> -->
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="icon" href="%VITE_SITE_LOGO%" />
<link rel="apple-touch-icon" href="%VITE_SITE_APPLE_LOGO%" />
<link rel="bookmark" href="%VITE_SITE_APPLE_LOGO%" />
<link rel="apple-touch-icon-precomposed" sizes="200x200" href="%VITE_SITE_APPLE_LOGO%" />
<meta name="description" content="%VITE_SITE_DES%" />
<meta name="keywords" content="%VITE_SITE_KEYWORDS%" />
<meta name="author" content="%VITE_SITE_ANTHOR%" />
<meta name="theme-color" content="#424242" />
<title>%VITE_SITE_NAME%</title>
<!-- HarmonyOS Sans -->
<!-- 本站 CDN 已开启防盗链,非本站域名不可访问,请更改链接为下方内容,否则自定义字体将失效 -->
<link rel="stylesheet" href="https://s1.hdslb.com/bfs/static/jinkela/long/font/regular.css" />
<!-- <link rel="stylesheet" href="https://cdn.imsyy.top/gh/imsyy/file/font/HarmonyOS_Sans/regular.min.css" /> -->
<!-- IE Out -->
<script>
var _hmt = _hmt || [];
(function () {
var hm = document.createElement("script");
hm.src = "https://hm.baidu.com/hm.js?14e9f35ff8bc67fd4bcb5f07a6e6655a";
var s = document.getElementsByTagName("script")[0];
s.parentNode.insertBefore(hm, s);
})();
if (/*@cc_on!@*/ false || (!!window.MSInputMethodContext && !!document.documentMode))
window.location.href =
'https://support.dmeng.net/upgrade-your-browser.html?referrer=' +
encodeURIComponent(window.location.href);
</script>
<!-- IE 淘汰计划 -->
<script>
if ( /*@cc_on!@*/ false || (!!window.MSInputMethodContext && !!document.documentMode)) window.location.href =
"/upgrade-your-browser/index.html?referrer=" + encodeURIComponent(window.location.href);
</script>
</head>
<body>
<!--加载动画-->
<div id="loading-box">
<div class="loading-left-bg"></div>
<div class="loading-right-bg"></div>
<div class="spinner-box">
<div class="loader">
<div class="inner one"></div>
<div class="inner two"></div>
<div class="inner three"></div>
</div>
<div class="loading-word">
<p class="loading-title">無名の主页</p>加载中
</div>
</div>
</div>
<!--加载动画结束-->
<section id="section" class="section">
<main id="main" class="main">
<div class="container" id="container">
<div class="row" id="row">
<div class="col left">
<!--基本信息-->
<div class="main-left">
<!--Logo-->
<div class="main-img">
<img src="./img/logo.png" alt="img">
<div class="img-title">
<span class="img-title">imsyy</span>
<span class="img-text">.top</span>
</div>
</div>
<!--介绍信息-->
<div class="message cards" id="switchmore">
<div class="des" id="des"><i class="iconfont icon-yinhao-copy-copy"></i>
<p class="des-title"><span id="change">Hello&nbsp;World&nbsp;!</span><br /><span
id="change1">一个建立于 21 世纪的小站,存活于互联网的边缘</span></p>
<i class="iconfont icon-yinhao-copy"></i>
</div>
</div>
<!--社交链接-->
<div class="social" id="social">
<a href="https://github.com/imsyy" class="link" id="github" target="_blank">
<i class="iconfont icon-github"></i>
</a>
<a href="http://wpa.qq.com/msgrd?v=3&uin=1539250352&site=qq&menu=yes" class="link"
id="qq" target="_blank">
<i class="iconfont icon-QQ"></i>
</a>
<a href="mailto:one@imsyy.top" class="link" id="email">
<i class="iconfont icon-youxiang"></i>
</a>
<a href="https://t.me/bottom_user" class="link" id="telegram" target="_blank">
<i class="iconfont icon-telegram"></i>
</a>
<a href="https://twitter.com/iimmsyy" class="link" id="twitter" target="_blank">
<i class="iconfont icon-twitter"></i>
</a>
<a id="link-text">通过这里联系我</a>
</div>
</div>
</div>
<!--第二屏 Logo-->
<div class="logo cards" style="display: none" id="changemore">
<a>imsyy.top</a>
</div>
<div class="col right">
<div class="main-right">
<!--功能区-->
<div class="row rightone" id="rightone">
<div class="col hitokotos">
<!--一言-->
<div class="hitokoto cards" id="hitokoto">
<div class="hitokoto-ico"><i class="fad fa-comment-alt-lines"></i>&nbsp;一言</div>
<div class="hitokoto-all">
<div class="hitokoto-text"><span id="hitokoto_text">每一个人都应该明确自己的方向和位置</span>
</div>
<div class="hitokoto-from">-「&nbsp;<span id="from_text">無名</span>&nbsp;
</div>
</div>
</div>
</div>
<div class="col times">
<!--时间-->
<div class="time cards">
<div class="timeshow" id="time"></div>
<div class="weather">
<span id="city_text">天气</span>&nbsp;<span
id="wea_text">加载失败</span>&nbsp;<span id="tem_night">*</span>°C~<span
id="tem_day">*</span>°C&nbsp;<span id="win_text">风向</span><span
id="win_speed">*</span>
</div>
</div>
</div>
</div>
<!--分隔线-->
<div class="line">
<i class="fad fa-grip-lines-vertical"></i>
<span class="line-text">网站列表</span>
</div>
<!--网站链接-->
<div class="link">
<!--第一组-->
<div class="row">
<div class="col">
<a href="https://blog.imsyy.top/" target="_blank">
<div class="link-card cards">
<i class="fad fa-blog"></i>
<span class="link-name">博客</span>
</div>
</a>
</div>
<div class="col 2">
<a href="https://web.imsyy.top/" target="_blank">
<div class="link-card cards">
<i class="fad fa-spider-web"></i>
<span class="link-name">网址导航</span>
</div>
</a>
</div>
<div class="col">
<a href="https://music.imsyy.top/" target="_blank">
<div class="link-card cards">
<i class="fad fa-list-music"></i>
<span class="link-name">音乐</span>
</div>
</a>
</div>
</div>
<!--第二组-->
<div class="row" style="margin-top: 1.5rem;">
<div class="col">
<a href="https://lab.imsyy.top/" target="_blank">
<div class="link-card cards">
<i class="fad fa-flask"></i>
<span class="link-name">实验室</span>
</div>
</a>
</div>
<div class="col 2">
<a href="https://share.imsyy.top/" target="_blank">
<div class="link-card cards">
<i class="fad fa-cloud-download"></i>
<span class="link-name">网盘</span>
</div>
</a>
</div>
<div class="col">
<a href="https://photo.imsyy.top/" target="_blank">
<div class="link-card cards">
<i class="fad fa-image"></i>
<span class="link-name">相册</span>
</div>
</a>
</div>
</div>
</div>
</div>
</div>
</div>
<!--展开菜单按钮-->
<div class="menu" id="switchmenu">
<a class="munu-button cards" id="menu"><i class="fad fa-bars"></i></a>
</div>
<!--更多内容-->
<div class="more cards" id="more">
<!--关闭按钮-->
<div class="close fixed-top" id="close">
<i class="fad fa-times-circle"></i>
</div>
<div class="line" style="margin-top: 1rem;">
<i class="fad fa-grip-lines-vertical"></i>
<span class="line-text">时间胶囊</span>
<i class="fad fa-grip-lines-vertical"></i>
</div>
<div class="date" id="date">
<p class="date-text" style="margin-top: 0rem;">今日已经度过了大约&nbsp;{{hour}}&nbsp;小时</p>
<div v-html="jinduT()" class="marginbottom"></div>
<p class="date-text">本周已经度过了&nbsp;{{week}}&nbsp;天,今天是第&nbsp;{{curweek}}&nbsp;</p>
<div v-html="jinduZ()" class="marginbottom"></div>
<p class="date-text">本月已经度过了&nbsp;{{day}}&nbsp;天,今天是第&nbsp;{{curday}}&nbsp;</p>
<div v-html="jinduD()" class="marginbottom"></div>
<p class="date-text">{{year}}&nbsp;年已经度过了&nbsp;{{month}}&nbsp;个月,度过了&nbsp;{{outday}}&nbsp;</p>
<div v-html="jinduY()" class="marginbottom"></div>
</div>
<div class="line">
<i class="fad fa-grip-lines-vertical"></i>
<span class="line-text">杂七杂八</span>
<i class="fad fa-grip-lines-vertical"></i>
</div>
<!--网站链接-->
<div class="row">
<div class="col">
<a href="https://status.imsyy.top/" target="_blank">
<div class="link-card cards">
<span class="link-name">站点监测</span>
</div>
</a>
</div>
<div class="col 2">
<a href="https://player.imsyy.top/" target="_blank">
<div class="link-card cards">
<span class="link-name">播放器</span>
</div>
</a>
</div>
<div class="col">
<a href="https://write.imsyy.top/" target="_blank">
<div class="link-card cards">
<span class="link-name">Markdown</span>
</div>
</a>
</div>
</div>
<div class="row" style="margin-top: 1.5rem;">
<div class="col">
<a href="https://img.imsyy.top/" target="_blank">
<div class="link-card cards">
<span class="link-name">图片站</span>
</div>
</a>
</div>
<div class="col 2">
<a href="https://file.imsyy.top/" target="_blank">
<div class="link-card cards">
<span class="link-name">文件库</span>
</div>
</a>
</div>
<div class="col">
<a id="openmore">
<div class="link-card cards">
<span class="link-name">更多</span>
</div>
</a>
</div>
</div>
</div>
<!--更多页面-->
<div class="box" id="box" style="display: none">
<div class="box-wrapper">
<!--关闭按钮-->
<div class="closebox fixed-top" id="closemore">
<i class="fad fa-times-circle"></i>
</div>
<!--更新日志-->
<div class="img-title">
<span class="img-title">imsyy</span>
<span class="img-text">.top</span>
<span class="img-text">&nbsp;&nbsp;v&nbsp;1.3</span>
</div>
<div class="upnote">
<span class="uptext"><i class="fad fa-plus-circle"></i>&nbsp;点击左侧简介可弹出更多页面</span>
<span class="uptext"><i class="fad fa-plus-circle"></i>&nbsp;修复时间胶囊( 时光进度条 </span>
<span class="uptext"><i class="fad fa-plus-circle"></i>&nbsp;隐藏页面新增全屏弹窗</span>
<span class="uptext"><i class="fad fa-wrench"></i>&nbsp;星期进度条显示错误</span>
<span class="uptext"><i class="fad fa-wrench"></i>&nbsp;移动端动画及细节</span>
<span class="uptext"><i class="fad fa-wrench"></i>&nbsp;Js&nbsp;文件优化</span>
</div>
</div>
</div>
</div>
</main>
<footer id="footer" class="fixed-bottom footer">
<div class="power">Copyright&nbsp;&copy;&nbsp;2020
<script>
document.write(' - ' + (new Date()).getFullYear())
</script>&nbsp;無名&nbsp;|&nbsp;<a href="https://beian.miit.gov.cn/" target="_blank">豫ICP备20013231-2号</a>
</div>
</footer>
</section>
<!-- JS -->
<script type="text/javascript" src="./js/main.js"></script>
<script type="text/javascript" src="./js/time.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.1/dist/js/bootstrap.bundle.min.js"></script>
</body>
</head>
<body>
<!-- 主体内容 -->
<div id="app"></div>
<!-- noscript -->
<noscript>
<div style="text-align: center">请开启 JavaScript</div>
</noscript>
<script type="module" src="/src/main.js"></script>
</body>
</html>

View File

@ -1,307 +0,0 @@
//弹窗样式
iziToast.settings({
timeout: 10000,
icon: 'Fontawesome',
closeOnEscape: 'true',
position: 'topLeft',
transitionIn: 'bounceInRight',
transitionOut: 'fadeOutLeft',
displayMode: 'replace',
layout: '2',
titleColor: '#efefef',
messageColor: '#efefef',
iconColor: '#efefef',
});
iziToast.info({
icon: 'fad fa-vial',
title: '新版站点试运行',
message: '还存在亿些小问题 ~ <a href="./old/" style="color:#efefef">返回旧版</a>'
});
//控制台输出
/*
let date = '2021-09-27 21:32'
let a = 'background: #606060; color: #fff; border-radius: 3px 0 0 3px;'
let b = 'background: #1475B2; color: #fff; border-radius: 0 3px 3px 0;'
console.log(`%c Update Time %c ${date} `, a, b)
*/
/* 样式代码 */
var styleTitle1 = `
font-size: 20px;
font-weight: 600;
color: rgb(244,167,89);
`
var styleTitle2 = `
font-style: oblique;
font-size:14px;
color: rgb(244,167,89);
font-weight: 400;
`
var styleContent = `
color: rgb(30,152,255);
`
/* 内容代码 */
var title1 = '無名の主页'
var title2 = 'imsyy.top'
var content = `
1.3.0
更新日期2021-10-02 14:26:31
更新说明
1. 新增 点击左侧简介弹出更多页面
2. 修复 时间胶囊 时光进度条
3. 优化 移动端动画及细节
4. 优化 Js 文件优化
5. 修复 星期进度条显示错误
主页: https://imsyy.top
Github: https://github.com/imsyy/home
`
console.log(`%c${title1} %c${title2}
%c${content}`, styleTitle1, styleTitle2, styleContent)
//获取一言
fetch('https://v1.hitokoto.cn')
.then(response => response.json())
.then(data => {
const hitokoto = document.getElementById('hitokoto_text')
const from = document.getElementById('from_text')
hitokoto.innerText = data.hitokoto
from.innerText = data.from
})
.catch(console.error)
//获取天气
fetch('https://www.tianqiapi.com/free/day?appid=43986679&appsecret=TksqGZT7')
.then(response => response.json())
.then(data => {
const wea = document.getElementById('wea_text')
const city = document.getElementById('city_text')
const tem_night = document.getElementById('tem_night')
const tem_day = document.getElementById('tem_day')
const win = document.getElementById('win_text')
const win_speed = document.getElementById('win_speed')
wea.innerText = data.wea
city.innerText = data.city
tem_night.innerText = data.tem_night
tem_day.innerText = data.tem_day
win.innerText = data.win
win_speed.innerText = data.win_speed
})
.catch(console.error)
//获取时间
var t = null;
t = setTimeout(time, 1000);
function time() {
clearTimeout(t);
dt = new Date();
var y = dt.getYear() + 1900;
var mm = dt.getMonth() + 1;
var d = dt.getDate();
var weekday = ["星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"];
var day = dt.getDay();
var h = dt.getHours();
var m = dt.getMinutes();
var s = dt.getSeconds();
if (h < 10) {
h = "0" + h;
}
if (m < 10) {
m = "0" + m;
}
if (s < 10) {
s = "0" + s;
}
document.getElementById("time").innerHTML = y + "&nbsp;年&nbsp;" + mm + "&nbsp;月&nbsp;" + d + "&nbsp;日&nbsp;" + "<span class='weekday'>" + weekday[day] + "</span><br>" + "<span class='time-text'>" + h + ":" + m + ":" + s + "</span>";
t = setTimeout(time, 1000);
}
//必应壁纸
var url = 'https://bird.ioliu.cn/v1/?url=https://www.bing.com/HPImageArchive.aspx?format=js&idx=0&n=8';
var imgUrls = JSON.parse(sessionStorage.getItem("imgUrls"));
var index = sessionStorage.getItem("index");
var $section = $('#section');
if (imgUrls == null) {
imgUrls = new Array();
index = 0;
$.get(url, function (result) {
images = result.images;
for (let i = 0; i < images.length; i++) {
const item = images[i];
imgUrls.push(item.url);
}
var imgUrl = imgUrls[index];
var url = "https://www.bing.com" + imgUrl;
$section.css("background", "url('" + url + "') center center no-repeat #666");
$section.css("background-size", "cover");
sessionStorage.setItem("imgUrls", JSON.stringify(imgUrls));
sessionStorage.setItem("index", index);
});
} else {
if (index == 7)
index = 0;
else
index++;
var imgUrl = imgUrls[index];
var url = "https://www.bing.com" + imgUrl;
$section.css("background", "url('" + url + "') center center no-repeat #666");
$section.css("background-size", "cover");
sessionStorage.setItem("index", index);
}
//加载动画
window.addEventListener('load', function () {
document.body.style.overflow = 'auto';
document.getElementById('loading-box').classList.add("loaded")
}, false)
//链接提示文字
$("#social").mouseover(function () {
$("#social").css({
"background": "rgb(0 0 0 / 25%)",
'border-radius': '6px',
"backdrop-filter": "blur(5px)"
});
$("#link-text").css({
"display": "block",
});
}).mouseout(function () {
$("#social").css({
"background": "none",
"border-radius": "6px",
"backdrop-filter": "none"
});
$("#link-text").css({
"display": "none"
});
});
$("#github").mouseover(function () {
$("#link-text").html("去 Github 看看");
}).mouseout(function () {
$("#link-text").html("通过这里联系我");
});
$("#qq").mouseover(function () {
$("#link-text").html("有什么事吗");
}).mouseout(function () {
$("#link-text").html("通过这里联系我");
});
$("#email").mouseover(function () {
$("#link-text").html("来封 Email");
}).mouseout(function () {
$("#link-text").html("通过这里联系我");
});
$("#telegram").mouseover(function () {
$("#link-text").html("你懂的 ~");
}).mouseout(function () {
$("#link-text").html("通过这里联系我");
});
$("#twitter").mouseover(function () {
$("#link-text").html("你懂的 ~");
}).mouseout(function () {
$("#link-text").html("通过这里联系我");
});
//更多页面切换
var shoemore = false;
$('#switchmore').on('click', function () {
shoemore = !shoemore;
if (shoemore && $(document).width() >= 990) {
$('#container').attr('class', 'container mores');
$("#change").html("Oops&nbsp;!");
$("#change1").html("哎呀,这都被你发现了( 再点击一次可关闭 ");
} else {
$('#container').attr('class', 'container');
$("#change").html("Hello&nbsp;World&nbsp;!");
$("#change1").html("一个建立于 21 世纪的小站,存活于互联网的边缘");
}
});
//更多页面关闭按钮
$('#close').on('click', function () {
$('#container').attr('class', 'container');
$("#change").html("Hello&nbsp;World&nbsp;!");
$("#change1").html("一个建立于 21 世纪的小站,存活于互联网的边缘");
});
//菜单栏切换
var switchmenu = false;
$('#switchmenu').on('click', function () {
switchmenu = !switchmenu;
if (switchmenu) {
$('#row').attr('class', 'row menus');
$("#menu").html("<i class='fad fa-times'></i>");
} else {
$('#row').attr('class', 'row');
$("#menu").html("<i class='fad fa-bars'></i>");
}
});
//更多弹窗页面
$('#openmore').on('click', function () {
$('#box').css("display", "block");
$('#row').css("display", "none");
$('#more').css("cssText", "display:none !important");
});
$('#closemore').on('click', function () {
$('#box').css("display", "none");
$('#row').css("display", "flex");
$('#more').css("display", "flex");
});
//监听网页宽度
window.addEventListener('load', function () {
window.addEventListener('resize', function () {
//关闭移动端样式
if (window.innerWidth >= 600) {
$('#row').attr('class', 'row');
$("#menu").html("<i class='fad fa-bars'></i>");
//移除移动端切换功能区
$('#rightone').attr('class', 'row rightone');
}
if (window.innerWidth <= 990) {
//移动端隐藏更多页面
$('#container').attr('class', 'container');
$("#change").html("Hello&nbsp;World&nbsp;!");
$("#change1").html("一个建立于 21 世纪的小站,存活于互联网的边缘");
//移动端隐藏弹窗页面
$('#box').css("display", "none");
$('#row').css("display", "flex");
$('#more').css("display", "flex");
}
})
})
//移动端切换功能区
var changemore = false;
$('#changemore').on('click', function () {
changemore = !changemore;
if (changemore) {
$('#rightone').attr('class', 'row menus mobile');
} else {
$('#rightone').attr('class', 'row menus');
}
});
//更多页面显示关闭按钮
$("#more").hover(function () {
$('#close').css("display", "block");
}, function () {
$('#close').css("display", "none");
})
//屏蔽右键
document.oncontextmenu = function () {
iziToast.info({
icon: 'fad fa-do-not-enter',
title: '温馨提醒',
message: '为了浏览体验,本站禁用右键'
});
return false;
}

View File

@ -1,73 +0,0 @@
var vm = new Vue({
el: '#date',
data: {
hour: "",
week: "",
curweek: "",
day: "",
curday: "",
month: "",
outday: "",
},
created: function () { //这里是定时器
this.timer();
setInterval(this.timer, 60000);
},
methods: {
timer: function () {
var myDate = new Date();
var myYear = myDate.getFullYear(); // 获取当前年份
var myMonth = myDate.getMonth() + 1; // 获取当前月份
var myDay = myDate.getDate(); // 获取当前日1- 31
var myHours = myDate.getHours(); // 获取当前小时(0-23)
var myMinu = myDate.getMinutes(); // 获取当前分钟(0-59)
var mySec = myDate.getSeconds(); // 获取当前秒数(0-59)
var myWeek = myDate.getDay(); //获取当前星期几(0-6)
this.hour = myHours;
this.year = myYear;
this.month = myMonth - 1;
this.day = myDay - 1;
this.curday = myDay;
this.week = myWeek + 6;
this.curweek = myWeek + 7;
this.minute = myMinu;
this.age = myYear - this.yearForYour;
},
//今天
jinduT: function () {
var tian = ((this.hour * 60 + this.minute) / 24 / 60 * 100).toFixed(1);
return "<div class='progress'><div class='progress-bar' style='width:" + tian + "%'>" + tian + " %" +
"</div></div>";
},
//本周
jinduZ: function () {
var curdayWithHour = (this.week * 24 * 60 + this.hour * 60 + this.minute) / 7 / 24 / 60;
var zhou = (curdayWithHour * 100).toFixed(1);
return "<div class='progress'><div class='progress-bar' style='width:" + zhou + "%'>" + zhou + " %" +
"</div></div>";
},
//这个月
jinduD: function () {
var days = new Date(this.year, this.month + 1, 0).getDate();
var yue = ((this.day * 24 * 60 + this.hour * 60 + this.minute) / days / 24 / 60 * 100)
.toFixed(1);
return "<div class='progress'><div class='progress-bar" + "' style='width:" + yue +
"%'>" + yue + " %" + "</div></div>";
},
//年
jinduY: function () {
var olddate = new Date(this.year, 0);
var nowdate = new Date(this.year, this.month, this.day + 1);
var outday = (nowdate - olddate) / (1000 * 60 * 60 * 24) + 1; //
this.outday = outday; //已经过去天数
var isLeap = (0 === this.year % 4) && (0 === this.year % 100) || (0 === this.year %
400);
var days = isLeap ? 366 : 365; //今年的天数
var ye = (((outday - 1) * 24 * 60 + this.hour * 60 + this.minute) / days / 24 / 60 *
100).toFixed(1);
return "<div class='progress'><div class='progress-bar" + "' style='width:" + ye +
"%'>" + ye + " %" + "</div></div>";
}
}
})

44
package.json Normal file
View File

@ -0,0 +1,44 @@
{
"name": "home",
"author": "imsyy",
"github": "https://github.com/imsyy/home",
"home": "https://imsyy.top",
"private": true,
"version": "4.1.4",
"type": "module",
"scripts": {
"dev": "vite --host",
"build": "vite build",
"preview": "vite preview",
"format": "prettier --write src/",
"lint": "eslint . --ext .js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts,.vue --fix"
},
"dependencies": {
"@worstone/vue-aplayer": "^1.0.6",
"aplayer": "^1.10.1",
"axios": "^1.6.8",
"dayjs": "^1.11.10",
"element-plus": "^2.7.1",
"fetch-jsonp": "^1.3.0",
"pinia": "^2.1.7",
"pinia-plugin-persistedstate": "^3.2.1",
"swiper": "^11.1.1",
"vue": "^3.4.24"
},
"devDependencies": {
"@icon-park/vue-next": "^1.4.2",
"@vicons/fa": "^0.12.0",
"@vicons/utils": "^0.1.4",
"@vitejs/plugin-vue": "^4.6.2",
"eslint": "^8.57.0",
"eslint-plugin-vue": "^9.25.0",
"prettier": "^3.2.5",
"sass": "^1.75.0",
"terser": "^5.30.4",
"unplugin-auto-import": "^0.11.5",
"unplugin-vue-components": "^0.22.12",
"vite": "^4.5.3",
"vite-plugin-compression": "^0.5.1",
"vite-plugin-pwa": "^0.14.7"
}
}

5112
pnpm-lock.yaml Normal file

File diff suppressed because it is too large Load Diff

Binary file not shown.

3
public/font/README.md Normal file
View File

@ -0,0 +1,3 @@
## Logo 字体替换
可将该文件夹下的 `Pacifico-Regular-all.ttf` 替换原来的 `Pacifico-Regular.ttf`

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 93 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 95 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 138 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 92 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

BIN
public/images/icon/128.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

BIN
public/images/icon/144.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

BIN
public/images/icon/180.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

BIN
public/images/icon/192.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

BIN
public/images/icon/32.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

BIN
public/images/icon/48.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

BIN
public/images/icon/512.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

BIN
public/images/icon/72.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

BIN
public/images/icon/96.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

Before

Width:  |  Height:  |  Size: 5.1 KiB

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

View File

Before

Width:  |  Height:  |  Size: 264 KiB

After

Width:  |  Height:  |  Size: 264 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

View File

Before

Width:  |  Height:  |  Size: 5.1 KiB

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

BIN
public/images/icon/play.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

BIN
public/images/icon/qq.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

BIN
public/images/icon/warn.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

BIN
screenshots/main.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 245 KiB

BIN
screenshots/step1.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

BIN
screenshots/step2.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

191
src/App.vue Normal file
View File

@ -0,0 +1,191 @@
<template>
<!-- 加载 -->
<Loading />
<!-- 壁纸 -->
<Background @loadComplete="loadComplete" />
<!-- 主界面 -->
<Transition name="fade" mode="out-in">
<main id="main" v-if="store.imgLoadStatus">
<div class="container" v-show="!store.backgroundShow">
<section class="all" v-show="!store.setOpenState">
<MainLeft />
<MainRight v-show="!store.boxOpenState" />
<Box v-show="store.boxOpenState" />
</section>
<section class="more" v-show="store.setOpenState" @click="store.setOpenState = false">
<MoreSet />
</section>
</div>
<!-- 移动端菜单按钮 -->
<Icon
class="menu"
size="24"
v-show="!store.backgroundShow"
@click="store.mobileOpenState = !store.mobileOpenState"
>
<component :is="store.mobileOpenState ? CloseSmall : HamburgerButton" />
</Icon>
<!-- 页脚 -->
<Transition name="fade" mode="out-in">
<Footer v-show="!store.backgroundShow && !store.setOpenState" />
</Transition>
</main>
</Transition>
</template>
<script setup>
import { helloInit, checkDays } from "@/utils/getTime.js";
import { HamburgerButton, CloseSmall } from "@icon-park/vue-next";
import { mainStore } from "@/store";
import { Icon } from "@vicons/utils";
import Loading from "@/components/Loading.vue";
import MainLeft from "@/views/Main/Left.vue";
import MainRight from "@/views/Main/Right.vue";
import Background from "@/components/Background.vue";
import Footer from "@/components/Footer.vue";
import Box from "@/views/Box/index.vue";
import MoreSet from "@/views/MoreSet/index.vue";
import cursorInit from "@/utils/cursor.js";
import config from "@/../package.json";
const store = mainStore();
//
const getWidth = () => {
store.setInnerWidth(window.innerWidth);
};
//
const loadComplete = () => {
nextTick(() => {
//
helloInit();
//
checkDays();
});
};
//
watch(
() => store.innerWidth,
(value) => {
if (value < 990) {
store.boxOpenState = false;
}
},
);
onMounted(() => {
//
cursorInit();
//
document.oncontextmenu = () => {
ElMessage({
message: "为了浏览体验,本站禁用右键",
grouping: true,
duration: 2000,
});
return false;
};
//
window.addEventListener("mousedown", (event) => {
if (event.button == 1) {
store.backgroundShow = !store.backgroundShow;
ElMessage({
message: `${store.backgroundShow ? "开启" : "退出"}壁纸展示状态`,
grouping: true,
});
}
});
//
getWidth();
window.addEventListener("resize", getWidth);
//
const styleTitle1 = "font-size: 20px;font-weight: 600;color: rgb(244,167,89);";
const styleTitle2 = "font-size:12px;color: rgb(244,167,89);";
const styleContent = "color: rgb(30,152,255);";
const title1 = "無名の主页";
const title2 = `
_____ __ __ _______ ____ __
|_ _| \\/ |/ ____\\ \\ / /\\ \\ / /
| | | \\ / | (___ \\ \\_/ / \\ \\_/ /
| | | |\\/| |\\___ \\ \\ / \\ /
_| |_| | | |____) | | | | |
|_____|_| |_|_____/ |_| |_|`;
const content = `\n\n版本: ${config.version}\n主页: ${config.home}\nGithub: ${config.github}`;
console.info(`%c${title1} %c${title2} %c${content}`, styleTitle1, styleTitle2, styleContent);
});
onBeforeUnmount(() => {
window.removeEventListener("resize", getWidth);
});
</script>
<style lang="scss" scoped>
#main {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
transform: scale(1.2);
transition: transform 0.3s;
animation: fade-blur-main-in 0.65s cubic-bezier(0.25, 0.46, 0.45, 0.94) forwards;
animation-delay: 0.5s;
.container {
width: 100%;
height: 100vh;
margin: 0 auto;
.all {
width: 100%;
height: 100%;
padding: 0 0.75rem;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
}
.more {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: #00000080;
backdrop-filter: blur(20px);
z-index: 2;
animation: fade 0.5s;
}
@media (max-width: 1200px) {
padding: 0 2vw;
}
}
.menu {
position: fixed;
display: flex;
justify-content: center;
align-items: center;
top: 84%;
left: calc(50% - 28px);
width: 56px;
height: 34px;
background: rgb(0 0 0 / 20%);
backdrop-filter: blur(10px);
border-radius: 6px;
transition: transform 0.3s;
animation: fade 0.5s;
&:active {
transform: scale(0.95);
}
.i-icon {
transform: translateY(2px);
}
@media (min-width: 721px) {
display: none;
}
}
}
</style>

75
src/api/index.js Normal file
View File

@ -0,0 +1,75 @@
// import axios from "axios";
import fetchJsonp from "fetch-jsonp";
/**
* 音乐播放器
*/
// 获取音乐播放列表
export const getPlayerList = async (server, type, id) => {
const res = await fetch(
`${import.meta.env.VITE_SONG_API}?server=${server}&type=${type}&id=${id}`,
);
const data = await res.json();
if (data[0].url.startsWith("@")) {
// eslint-disable-next-line no-unused-vars
const [handle, jsonpCallback, jsonpCallbackFunction, url] = data[0].url.split("@").slice(1);
const jsonpData = await fetchJsonp(url).then((res) => res.json());
const domain = (
jsonpData.req_0.data.sip.find((i) => !i.startsWith("http://ws")) ||
jsonpData.req_0.data.sip[0]
).replace("http://", "https://");
return data.map((v, i) => ({
name: v.name || v.title,
artist: v.artist || v.author,
url: domain + jsonpData.req_0.data.midurlinfo[i].purl,
cover: v.cover || v.pic,
lrc: v.lrc,
}));
} else {
return data.map((v) => ({
name: v.name || v.title,
artist: v.artist || v.author,
url: v.url,
cover: v.cover || v.pic,
lrc: v.lrc,
}));
}
};
/**
* 一言
*/
// 获取一言数据
export const getHitokoto = async () => {
const res = await fetch("https://v1.hitokoto.cn");
return await res.json();
};
/**
* 天气
*/
// 获取高德地理位置信息
export const getAdcode = async (key) => {
const res = await fetch(`https://restapi.amap.com/v3/ip?key=${key}`);
return await res.json();
};
// 获取高德地理天气信息
export const getWeather = async (key, city) => {
const res = await fetch(
`https://restapi.amap.com/v3/weather/weatherInfo?key=${key}&city=${city}`,
);
return await res.json();
};
// 获取教书先生天气 API
// https://api.oioweb.cn/doc/weather/GetWeather
export const getOtherWeather = async () => {
const res = await fetch("https://api.oioweb.cn/api/weather/GetWeather");
return await res.json();
};

37
src/assets/siteLinks.json Normal file
View File

@ -0,0 +1,37 @@
[
{
"icon": "Blog",
"name": "博客",
"link": "https://blog.imsyy.top/"
},
{
"icon": "Cloud",
"name": "网盘",
"link": "https://pan.imsyy.top/"
},
{
"icon": "CompactDisc",
"name": "音乐",
"link": "https://music.imsyy.top/"
},
{
"icon": "Compass",
"name": "起始页",
"link": "https://nav.imsyy.top/"
},
{
"icon": "Book",
"name": "网址集",
"link": "https://web.imsyy.top/"
},
{
"icon": "Fire",
"name": "今日热榜",
"link": "https://hot.imsyy.top/"
},
{
"icon": "LaptopCode",
"name": "站点监测",
"link": "https://status.imsyy.top/"
}
]

View File

@ -0,0 +1,38 @@
[
{
"name": "Github",
"icon": "/images/icon/github.png",
"tip": "去 Github 看看",
"url": "https://github.com/imsyy"
},
{
"name": "BiliBili",
"icon": "/images/icon/bilibili.png",
"tip": "(゜-゜)つロ 干杯 ~",
"url": "https://space.bilibili.com/98544142"
},
{
"name": "QQ",
"icon": "/images/icon/qq.png",
"tip": "有什么事吗",
"url": "https://res.abeim.cn/api/qq/?qq=1539250352"
},
{
"name": "Email",
"icon": "/images/icon/email.png",
"tip": "来封 Email ~",
"url": "mailto:one@imsyy.top"
},
{
"name": "Twitter",
"icon": "/images/icon/twitter.png",
"tip": "你懂的 ~",
"url": "https://twitter.com/iimmsyy"
},
{
"name": "Telegram",
"icon": "/images/icon/telegram.png",
"tip": "你懂的 ~",
"url": "https://t.me/bottom_user"
}
]

View File

@ -0,0 +1,171 @@
<template>
<div :class="store.backgroundShow ? 'cover show' : 'cover'">
<img
v-show="store.imgLoadStatus"
:src="bgUrl"
class="bg"
alt="cover"
@load="imgLoadComplete"
@error.once="imgLoadError"
@animationend="imgAnimationEnd"
/>
<div :class="store.backgroundShow ? 'gray hidden' : 'gray'" />
<Transition name="fade" mode="out-in">
<a
v-if="store.backgroundShow && store.coverType != '3'"
class="down"
:href="bgUrl"
target="_blank"
>
下载壁纸
</a>
</Transition>
</div>
</template>
<script setup>
import { mainStore } from "@/store";
import { Error } from "@icon-park/vue-next";
const store = mainStore();
const bgUrl = ref(null);
const imgTimeout = ref(null);
const emit = defineEmits(["loadComplete"]);
//
// Math.random()
const bgRandom = Math.floor(Math.random() * 10 + 1);
//
const changeBg = (type) => {
if (type == 0) {
bgUrl.value = `/images/background${bgRandom}.jpg`;
} else if (type == 1) {
bgUrl.value = "https://api.dujin.org/bing/1920.php";
} else if (type == 2) {
bgUrl.value = "https://api.vvhan.com/api/wallpaper/views";
} else if (type == 3) {
bgUrl.value = "https://api.vvhan.com/api/wallpaper/acg";
}
};
//
const imgLoadComplete = () => {
imgTimeout.value = setTimeout(
() => {
store.setImgLoadStatus(true);
},
Math.floor(Math.random() * (600 - 300 + 1)) + 300,
);
};
//
const imgAnimationEnd = () => {
console.log("壁纸加载且动画完成");
//
emit("loadComplete");
};
//
const imgLoadError = () => {
console.error("壁纸加载失败:", bgUrl.value);
ElMessage({
message: "壁纸加载失败,已临时切换回默认",
icon: h(Error, {
theme: "filled",
fill: "#efefef",
}),
});
bgUrl.value = `/images/background${bgRandom}.jpg`;
};
//
watch(
() => store.coverType,
(value) => {
changeBg(value);
},
);
onMounted(() => {
//
changeBg(store.coverType);
});
onBeforeUnmount(() => {
clearTimeout(imgTimeout.value);
});
</script>
<style lang="scss" scoped>
.cover {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
transition: 0.25s;
z-index: -1;
&.show {
z-index: 1;
}
.bg {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
object-fit: cover;
backface-visibility: hidden;
filter: blur(20px) brightness(0.3);
transition:
filter 0.3s,
transform 0.3s;
animation: fade-blur-in 0.8s cubic-bezier(0.25, 0.46, 0.45, 0.94) forwards;
animation-delay: 0.45s;
}
.gray {
opacity: 1;
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
background-image: radial-gradient(rgba(0, 0, 0, 0) 0, rgba(0, 0, 0, 0.5) 100%),
radial-gradient(rgba(0, 0, 0, 0) 33%, rgba(0, 0, 0, 0.3) 166%);
transition: 1.5s;
&.hidden {
opacity: 0;
transition: 1.5s;
}
}
.down {
font-size: 16px;
color: white;
position: absolute;
bottom: 30px;
left: 0;
right: 0;
margin: 0 auto;
display: block;
padding: 20px 26px;
border-radius: 8px;
background-color: #00000030;
width: 120px;
height: 30px;
display: flex;
justify-content: center;
align-items: center;
&:hover {
transform: scale(1.05);
background-color: #00000060;
}
&:active {
transform: scale(1);
}
}
}
</style>

120
src/components/Footer.vue Normal file
View File

@ -0,0 +1,120 @@
<template>
<footer id="footer" :class="store.footerBlur ? 'blur' : null">
<Transition name="fade" mode="out-in">
<div v-if="!store.playerState || !store.playerLrcShow" class="power">
<span>
Copyright&nbsp;&copy;
<span v-if="siteStartDate?.length >= 4" class="site-start">
{{ siteStartDate.substring(0, 4) }}
-
</span>
{{ fullYear }}
<a :href="siteUrl">{{ siteAnthor }}</a>
</span>
<!-- 以下信息请不要修改哦 -->
<span class="hidden">
&amp;&nbsp;Made&nbsp;by
<a :href="config.github" target="_blank">
{{ config.author }}
</a>
</span>
<!-- 站点备案 -->
<a v-if="siteIcp" href="https://beian.miit.gov.cn" target="_blank">
&amp;
{{ siteIcp }}
</a>
</div>
<div v-else class="lrc">
<Transition name="fade" mode="out-in">
<div class="lrc-all" :key="store.getPlayerLrc">
<music-one theme="filled" size="18" fill="#efefef" />
<span class="lrc-text text-hidden" v-html="store.getPlayerLrc" />
<music-one theme="filled" size="18" fill="#efefef" />
</div>
</Transition>
</div>
</Transition>
</footer>
</template>
<script setup>
import { MusicOne } from "@icon-park/vue-next";
import { mainStore } from "@/store";
import config from "@/../package.json";
const store = mainStore();
const fullYear = new Date().getFullYear();
//
const siteStartDate = ref(import.meta.env.VITE_SITE_START);
const siteIcp = ref(import.meta.env.VITE_SITE_ICP);
const siteAnthor = ref(import.meta.env.VITE_SITE_ANTHOR);
const siteUrl = computed(() => {
const url = import.meta.env.VITE_SITE_URL;
if (!url) return "https://www.imsyy.top";
//
if (!url.startsWith("http://") && !url.startsWith("https://")) {
return "//" + url;
}
return url;
});
</script>
<style lang="scss" scoped>
#footer {
width: 100%;
position: absolute;
bottom: 0;
left: 0;
height: 46px;
line-height: 46px;
text-align: center;
z-index: 0;
font-size: 14px;
.power {
animation: fade 0.3s;
}
.lrc {
padding: 0 20px;
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
.lrc-all {
width: 98%;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
.lrc-text {
margin: 0 8px;
}
.i-icon {
width: 18px;
height: 18px;
display: inherit;
}
}
}
&.blur {
backdrop-filter: blur(10px);
background: rgb(0 0 0 / 25%);
font-size: 16px;
}
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.15s ease-in-out;
}
@media (max-width: 720px) {
font-size: 0.85rem;
&.blur {
font-size: 0.85rem;
}
}
@media (max-width: 480px) {
.hidden {
display: none;
}
}
}
</style>

128
src/components/Hitokoto.vue Normal file
View File

@ -0,0 +1,128 @@
<template>
<div
class="hitokoto cards"
v-show="!store.musicOpenState"
@mouseenter="openMusicShow = true"
@mouseleave="openMusicShow = false"
@click.stop
>
<!-- 打开音乐面板 -->
<Transition name="el-fade-in-linear">
<div
class="open-music"
v-show="openMusicShow && store.musicIsOk"
@click="store.musicOpenState = true"
>
<music-menu theme="filled" size="18" fill="#efefef" />
<span>打开音乐播放器</span>
</div>
</Transition>
<!-- 一言内容 -->
<Transition name="el-fade-in-linear" mode="out-in">
<div :key="hitokotoData.text" class="content" @click="updateHitokoto">
<span class="text">{{ hitokotoData.text }}</span>
<span class="from">-&nbsp;{{ hitokotoData.from }}&nbsp;</span>
</div>
</Transition>
</div>
</template>
<script setup>
import { MusicMenu, Error } from "@icon-park/vue-next";
import { getHitokoto } from "@/api";
import { mainStore } from "@/store";
import debounce from "@/utils/debounce.js";
const store = mainStore();
//
const openMusicShow = ref(false);
//
const hitokotoData = reactive({
text: "这里应该显示一句话",
from: "無名",
});
//
const getHitokotoData = async () => {
try {
const result = await getHitokoto();
hitokotoData.text = result.hitokoto;
hitokotoData.from = result.from;
} catch (error) {
ElMessage({
message: "一言获取失败",
icon: h(Error, {
theme: "filled",
fill: "#efefef",
}),
});
hitokotoData.text = "这里应该显示一句话";
hitokotoData.from = "無名";
}
};
//
const updateHitokoto = () => {
//
debounce(() => {
getHitokotoData();
}, 500);
};
onMounted(() => {
getHitokotoData();
});
</script>
<style lang="scss" scoped>
.hitokoto {
width: 100%;
height: 100%;
padding: 20px;
animation: fade 0.5s;
.open-music {
width: 100%;
position: absolute;
top: 0;
left: 0;
display: flex;
align-items: center;
justify-content: center;
background: #00000026;
padding: 4px 0;
border-radius: 8px 8px 0 0;
.i-icon {
width: 18px;
height: 18px;
display: block;
margin-right: 8px;
}
span {
font-size: 0.95rem;
}
}
.content {
height: 100%;
display: flex;
flex-direction: column;
justify-content: space-evenly;
.text {
font-size: 1.1rem;
word-break: break-all;
text-overflow: ellipsis;
overflow: hidden;
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
}
.from {
margin-top: 10px;
font-weight: bold;
align-self: flex-end;
font-size: 1.1rem;
}
}
}
</style>

182
src/components/Links.vue Normal file
View File

@ -0,0 +1,182 @@
<template>
<div v-if="siteLinks[0]" class="links">
<div class="line">
<Icon size="20">
<Link />
</Icon>
<span class="title">网站列表</span>
</div>
<!-- 网站列表 -->
<Swiper
v-if="siteLinks[0]"
:modules="[Pagination, Mousewheel]"
:slides-per-view="1"
:space-between="40"
:pagination="{
el: '.swiper-pagination',
clickable: true,
bulletElement: 'div',
}"
:mousewheel="true"
>
<SwiperSlide v-for="site in siteLinksList" :key="site">
<el-row class="link-all" :gutter="20">
<el-col v-for="(item, index) in site" :span="8" :key="item">
<div
class="item cards"
:style="index < 3 ? 'margin-bottom: 20px' : null"
@click="jumpLink(item)"
>
<Icon size="26">
<component :is="siteIcon[item.icon]" />
</Icon>
<span class="name text-hidden">{{ item.name }}</span>
</div>
</el-col>
</el-row>
</SwiperSlide>
<div class="swiper-pagination" />
</Swiper>
</div>
</template>
<script setup>
import { Icon } from "@vicons/utils";
// https://www.xicons.org
import { Link, Blog, CompactDisc, Cloud, Compass, Book, Fire, LaptopCode } from "@vicons/fa"; // 使
import { mainStore } from "@/store";
import { Swiper, SwiperSlide } from "swiper/vue";
import { Pagination, Mousewheel } from "swiper/modules";
import siteLinks from "@/assets/siteLinks.json";
const store = mainStore();
//
const siteLinksList = computed(() => {
const result = [];
for (let i = 0; i < siteLinks.length; i += 6) {
const subArr = siteLinks.slice(i, i + 6);
result.push(subArr);
}
return result;
});
//
const siteIcon = {
Blog,
Cloud,
CompactDisc,
Compass,
Book,
Fire,
LaptopCode,
};
//
const jumpLink = (data) => {
if (data.name === "音乐" && store.musicClick) {
if (typeof $openList === "function") $openList();
} else {
window.open(data.link, "_blank");
}
};
onMounted(() => {
console.log(siteLinks);
});
</script>
<style lang="scss" scoped>
.links {
.line {
margin: 2rem 0.25rem 1rem;
font-size: 1.1rem;
display: flex;
align-items: center;
animation: fade 0.5s;
.title {
margin-left: 8px;
font-size: 1.15rem;
text-shadow: 0 0 5px #00000050;
}
}
.swiper {
left: -10px;
width: calc(100% + 20px);
padding: 5px 10px 0;
z-index: 0;
.swiper-slide {
height: 100%;
}
.swiper-pagination {
margin-top: 12px;
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
:deep(.swiper-pagination-bullet) {
background-color: #fff;
width: 20px;
height: 4px;
margin: 0 4px;
border-radius: 4px;
opacity: 0.2;
transition: opacity 0.3s;
&.swiper-pagination-bullet-active {
opacity: 1;
}
&:hover {
opacity: 1;
}
}
}
}
.link-all {
height: 220px;
.item {
height: 100px;
width: 100%;
display: flex;
align-items: center;
flex-direction: row;
justify-content: center;
padding: 0 10px;
animation: fade 0.5s;
&:hover {
transform: scale(1.02);
background: rgb(0 0 0 / 40%);
transition: 0.3s;
}
&:active {
transform: scale(1);
}
.name {
font-size: 1.1rem;
margin-left: 8px;
}
@media (min-width: 720px) and (max-width: 820px) {
.name {
display: none;
}
}
@media (max-width: 720px) {
height: 80px;
}
@media (max-width: 460px) {
flex-direction: column;
.name {
font-size: 1rem;
margin-left: 0;
margin-top: 8px;
}
}
}
@media (max-width: 720px) {
height: 180px;
}
}
}
</style>

152
src/components/Loading.vue Normal file
View File

@ -0,0 +1,152 @@
<template>
<div id="loader-wrapper" :class="store.imgLoadStatus ? 'loaded' : null">
<div class="loader">
<div class="loader-circle" />
<div class="loader-text">
<span class="name">
{{ siteName }}
</span>
<span class="tip"> 加载中 </span>
</div>
</div>
<div class="loader-section section-left" />
<div class="loader-section section-right" />
</div>
</template>
<script setup>
import { mainStore } from "@/store";
const store = mainStore();
//
const siteName = import.meta.env.VITE_SITE_NAME;
</script>
<style lang="scss" scoped>
#loader-wrapper {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 999;
overflow: hidden;
.loader {
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
.loader-circle {
width: 150px;
height: 150px;
border-radius: 50%;
border: 3px solid transparent;
border-top-color: #fff;
animation: spin 1.8s linear infinite;
z-index: 2;
&:before {
content: "";
position: absolute;
top: 5px;
left: 5px;
right: 5px;
bottom: 5px;
border-radius: 50%;
border: 3px solid transparent;
border-top-color: #a4a4a4;
animation: spin-reverse 0.6s linear infinite;
}
&:after {
content: "";
position: absolute;
top: 15px;
left: 15px;
right: 15px;
bottom: 15px;
border-radius: 50%;
border: 3px solid transparent;
border-top-color: #d3d3d3;
animation: spin 1s linear infinite;
}
}
.loader-text {
display: flex;
flex-direction: column;
align-items: center;
color: #fff;
z-index: 2;
margin-top: 40px;
font-size: 24px;
.tip {
margin-top: 6px;
font-size: 18px;
opacity: 0.6;
}
}
}
.loader-section {
position: fixed;
top: 0;
width: 51%;
height: 100%;
background: #333;
z-index: 1;
&.section-left {
left: 0;
}
&.section-right {
right: 0;
}
}
&.loaded {
visibility: hidden;
transform: translateY(-100%);
transition:
transform 0.3s 1s ease-out,
visibility 0.3s 1s ease-out;
.loader {
.loader-circle,
.loader-text {
opacity: 0;
transition: opacity 0.3s ease-out;
}
}
.loader-section {
&.section-left {
transform: translateX(-100%);
transition: transform 0.5s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
}
&.section-right {
transform: translateX(100%);
transition: transform 0.5s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
}
}
}
}
@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
@keyframes spin-reverse {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(-360deg);
}
}
</style>

193
src/components/Message.vue Normal file
View File

@ -0,0 +1,193 @@
<template>
<!-- 基本信息 -->
<div class="message">
<!-- Logo -->
<div class="logo">
<img class="logo-img" :src="siteLogo" alt="logo" />
<div :class="{ name: true, 'text-hidden': true, long: siteUrl[0].length >= 6 }">
<span class="bg">{{ siteUrl[0] }}</span>
<span class="sm">.{{ siteUrl[1] }}</span>
</div>
</div>
<!-- 简介 -->
<div class="description cards" @click="changeBox">
<div class="content">
<Icon size="16">
<QuoteLeft />
</Icon>
<Transition name="fade" mode="out-in">
<div :key="descriptionText.hello + descriptionText.text" class="text">
<p>{{ descriptionText.hello }}</p>
<p>{{ descriptionText.text }}</p>
</div>
</Transition>
<Icon size="16">
<QuoteRight />
</Icon>
</div>
</div>
</div>
</template>
<script setup>
import { Icon } from "@vicons/utils";
import { QuoteLeft, QuoteRight } from "@vicons/fa";
import { Error } from "@icon-park/vue-next";
import { mainStore } from "@/store";
const store = mainStore();
// logo
const siteLogo = import.meta.env.VITE_SITE_MAIN_LOGO;
//
const siteUrl = computed(() => {
const url = import.meta.env.VITE_SITE_URL;
if (!url) return "imsyy.top".split(".");
//
if (url.startsWith("http://") || url.startsWith("https://")) {
const urlFormat = url.replace(/^(https?:\/\/)/, "");
return urlFormat.split(".");
}
return url.split(".");
});
//
const descriptionText = reactive({
hello: import.meta.env.VITE_DESC_HELLO,
text: import.meta.env.VITE_DESC_TEXT,
});
//
const changeBox = () => {
if (store.getInnerWidth >= 990) {
store.boxOpenState = !store.boxOpenState;
} else {
ElMessage({
message: "当前页面宽度不足以开启盒子",
grouping: true,
icon: h(Error, {
theme: "filled",
fill: "#efefef",
}),
});
}
};
//
watch(
() => store.boxOpenState,
(value) => {
if (value) {
descriptionText.hello = import.meta.env.VITE_DESC_HELLO_OTHER;
descriptionText.text = import.meta.env.VITE_DESC_TEXT_OTHER;
} else {
descriptionText.hello = import.meta.env.VITE_DESC_HELLO;
descriptionText.text = import.meta.env.VITE_DESC_TEXT;
}
},
);
</script>
<style lang="scss" scoped>
.message {
.logo {
display: flex;
flex-direction: row;
align-items: center;
animation: fade 0.5s;
max-width: 460px;
.logo-img {
border-radius: 50%;
width: 120px;
}
.name {
width: 100%;
padding-left: 22px;
transform: translateY(-8px);
font-family: "Pacifico-Regular";
.bg {
font-size: 5rem;
}
.sm {
margin-left: 6px;
font-size: 2rem;
@media (min-width: 720px) and (max-width: 789px) {
display: none;
}
}
}
@media (max-width: 768px) {
.logo-img {
width: 100px;
}
.name {
height: 128px;
.bg {
font-size: 4.5rem;
}
}
}
@media (max-width: 720px) {
max-width: 100%;
}
}
.description {
padding: 1rem;
margin-top: 3.5rem;
max-width: 460px;
animation: fade 0.5s;
.content {
display: flex;
justify-content: space-between;
.text {
margin: 0.75rem 1rem;
line-height: 2rem;
margin-right: auto;
transition: opacity 0.2s;
p {
&:nth-of-type(1) {
font-family: "Pacifico-Regular";
}
}
}
.xicon:nth-of-type(2) {
align-self: flex-end;
}
}
@media (max-width: 720px) {
max-width: 100%;
pointer-events: none;
}
}
@media (max-width: 390px) {
.logo {
flex-direction: column;
.logo-img {
display: none;
}
.name {
margin-left: 0;
height: auto;
transform: none;
text-align: center;
.bg {
font-size: 3.5rem;
}
.sm {
font-size: 1.4rem;
}
}
}
.description {
margin-top: 2.5rem;
}
}
}
</style>

View File

@ -0,0 +1,14 @@
<template>
<div class="more-content">您可在此编写任意内容</div>
</template>
<style lang="scss" scoped>
.more-content {
display: flex;
align-items: center;
justify-content: center;
margin-top: 20px;
width: 100%;
height: 100%;
}
</style>

312
src/components/Music.vue Normal file
View File

@ -0,0 +1,312 @@
<template>
<!-- 音乐控制面板 -->
<div
class="music"
@mouseenter="volumeShow = true"
@mouseleave="volumeShow = false"
v-show="store.musicOpenState"
>
<div class="btns">
<span @click="openMusicList()">音乐列表</span>
<span @click="store.musicOpenState = false">回到一言</span>
</div>
<div class="control">
<go-start theme="filled" size="30" fill="#efefef" @click="changeMusicIndex(0)" />
<Transition name="fade" mode="out-in">
<div :key="store.playerState" class="state" @click="changePlayState">
<play-one theme="filled" size="50" fill="#efefef" v-show="!store.playerState" />
<pause theme="filled" size="50" fill="#efefef" v-show="store.playerState" />
</div>
</Transition>
<go-end theme="filled" size="30" fill="#efefef" @click="changeMusicIndex(1)" />
</div>
<div class="menu">
<div class="name" v-show="!volumeShow">
<span>{{
store.getPlayerData.name
? store.getPlayerData.name + " - " + store.getPlayerData.artist
: "未播放音乐"
}}</span>
</div>
<div class="volume" v-show="volumeShow">
<div class="icon">
<volume-mute theme="filled" size="24" fill="#efefef" v-if="volumeNum == 0" />
<volume-small
theme="filled"
size="24"
fill="#efefef"
v-else-if="volumeNum > 0 && volumeNum < 0.7"
/>
<volume-notice theme="filled" size="24" fill="#efefef" v-else />
</div>
<el-slider v-model="volumeNum" :show-tooltip="false" :min="0" :max="1" :step="0.01" />
</div>
</div>
</div>
<!-- 音乐列表弹窗 -->
<Transition name="fade" mode="out-in">
<div class="music-list" v-show="musicListShow" @click="closeMusicList()">
<Transition name="zoom">
<div class="list" v-show="musicListShow" @click.stop>
<close-one
class="close"
theme="filled"
size="28"
fill="#ffffff60"
@click="closeMusicList()"
/>
<Player
ref="playerRef"
:songServer="playerData.server"
:songType="playerData.type"
:songId="playerData.id"
:volume="volumeNum"
/>
</div>
</Transition>
</div>
</Transition>
</template>
<script setup>
import {
GoStart,
PlayOne,
Pause,
GoEnd,
CloseOne,
VolumeMute,
VolumeSmall,
VolumeNotice,
} from "@icon-park/vue-next";
import Player from "@/components/Player.vue";
import { mainStore } from "@/store";
const store = mainStore();
//
const volumeShow = ref(false);
const volumeNum = ref(store.musicVolume ? store.musicVolume : 0.7);
//
const musicListShow = ref(false);
const playerRef = ref(null);
const playerData = reactive({
server: import.meta.env.VITE_SONG_SERVER,
type: import.meta.env.VITE_SONG_TYPE,
id: import.meta.env.VITE_SONG_ID,
});
//
const openMusicList = () => {
musicListShow.value = true;
playerRef.value.toggleList();
};
//
const closeMusicList = () => {
musicListShow.value = false;
playerRef.value.toggleList();
};
//
const changePlayState = () => {
playerRef.value.playToggle();
};
//
const changeMusicIndex = (type) => {
playerRef.value.changeSong(type);
};
onMounted(() => {
//
window.addEventListener("keydown", (e) => {
if (!store.musicIsOk) {
return;
}
if (e.code == "Space") {
changePlayState();
}
});
// window
window.$openList = openMusicList;
});
//
watch(
() => volumeNum.value,
(value) => {
store.musicVolume = value;
playerRef.value.changeVolume(store.musicVolume);
},
);
</script>
<style lang="scss" scoped>
.music {
width: 100%;
height: 100%;
background: #00000040;
backdrop-filter: blur(10px);
border-radius: 6px;
padding: 20px;
display: flex;
justify-content: space-between;
align-items: center;
flex-direction: column;
animation: fade 0.5s;
.btns {
display: flex;
align-items: center;
margin-bottom: 6px;
span {
background: #ffffff26;
padding: 2px 8px;
border-radius: 6px;
margin: 0px 6px;
text-overflow: ellipsis;
overflow-x: hidden;
white-space: nowrap;
&:hover {
background: #ffffff4d;
}
}
}
.control {
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-evenly;
width: 100%;
.state {
transition: opacity 0.1s;
.i-icon {
width: 50px;
height: 50px;
display: block;
}
}
.i-icon {
width: 36px;
height: 36px;
display: flex;
border-radius: 6px;
align-items: center;
justify-content: center;
border-radius: 6px;
transform: scale(1);
&:hover {
background: #ffffff33;
}
&:active {
transform: scale(0.95);
}
}
}
.menu {
height: 26px;
width: 100%;
line-height: 26px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
.name {
width: 100%;
text-align: center;
text-overflow: ellipsis;
overflow-x: hidden;
white-space: nowrap;
animation: fade 0.3s;
}
.volume {
width: 100%;
padding: 0 12px;
display: flex;
align-items: center;
flex-direction: row;
animation: fade 0.3s;
.icon {
margin-right: 12px;
span {
width: 24px;
height: 24px;
display: block;
}
}
:deep(*) {
transition: none;
}
:deep(.el-slider__button) {
transition: 0.3s;
}
.el-slider {
margin-right: 12px;
--el-slider-main-bg-color: #efefef;
--el-slider-runway-bg-color: #ffffff40;
--el-slider-button-size: 16px;
}
}
}
}
.music-list {
position: fixed;
top: 0;
left: 0;
margin: auto;
width: 100%;
height: 100%;
background-color: #00000080;
backdrop-filter: blur(20px);
z-index: 1;
.list {
position: absolute;
display: flex;
align-items: center;
justify-content: center;
top: calc(50% - 300px);
left: calc(50% - 320px);
width: 640px;
height: 600px;
background-color: #ffffff66;
border-radius: 6px;
z-index: 999;
@media (max-width: 720px) {
left: calc(50% - 45%);
width: 90%;
}
.close {
position: absolute;
top: 12px;
right: 12px;
width: 28px;
height: 28px;
display: block;
&:hover {
transform: scale(1.2);
}
&:active {
transform: scale(0.95);
}
}
}
}
//
.zoom-enter-active {
animation: zoom 0.4s ease-in-out;
}
.zoom-leave-active {
animation: zoom 0.3s ease-in-out reverse;
}
@keyframes zoom {
0% {
opacity: 0;
transform: scale(0) translateY(-600px);
}
100% {
opacity: 1;
transform: scale(1) translateY(0);
}
}
</style>

288
src/components/Player.vue Normal file
View File

@ -0,0 +1,288 @@
<template>
<APlayer
v-if="playList[0]"
ref="player"
:audio="playList"
:autoplay="store.playerAutoplay"
:theme="theme"
:autoSwitch="false"
:loop="store.playerLoop"
:order="store.playerOrder"
:volume="volume"
:showLrc="true"
:listFolded="listFolded"
:listMaxHeight="listMaxHeight"
:noticeSwitch="false"
@play="onPlay"
@pause="onPause"
@timeupdate="onTimeUp"
@error="loadMusicError"
/>
</template>
<script setup>
import { MusicOne, PlayWrong } from "@icon-park/vue-next";
import { getPlayerList } from "@/api";
import { mainStore } from "@/store";
import APlayer from "@worstone/vue-aplayer";
const store = mainStore();
// DOM
const player = ref(null);
//
const playList = ref([]);
//
const playIndex = ref(0);
//
const props = defineProps({
//
theme: {
type: String,
default: "#efefef",
},
//
volume: {
type: Number,
default: 0.7,
validator: (value) => {
return value >= 0 && value <= 1;
},
},
// ( netease-, tencent-qq )
songServer: {
type: String,
default: "netease", //'netease' | 'tencent'
},
// ( song-, playlist-, album-, search-, artist- )
songType: {
type: String,
default: "playlist",
},
// id
songId: {
type: String,
default: "7452421335",
},
//
listFolded: {
type: Boolean,
default: false,
},
//
listMaxHeight: {
type: Number,
default: 420,
},
});
const listHeight = computed(() => {
return props.listMaxHeight + "px";
});
//
onMounted(() => {
nextTick(() => {
try {
getPlayerList(props.songServer, props.songType, props.songId).then((res) => {
console.log(res);
//
store.musicIsOk = true;
//
playList.value = res;
console.log("音乐加载完成");
console.log(playList.value);
console.log(playIndex.value, playList.value.length, props.volume);
});
} catch (err) {
console.error(err);
store.musicIsOk = false;
ElMessage({
message: "播放器加载失败",
grouping: true,
icon: h(PlayWrong, {
theme: "filled",
fill: "#efefef",
}),
});
}
});
});
//
const onPlay = () => {
console.log("播放");
playIndex.value = player.value.aplayer.index;
//
store.setPlayerState(player.value.audioRef.paused);
//
store.setPlayerData(playList.value[playIndex.value].name, playList.value[playIndex.value].artist);
ElMessage({
message: store.getPlayerData.name + " - " + store.getPlayerData.artist,
grouping: true,
icon: h(MusicOne, {
theme: "filled",
fill: "#efefef",
}),
});
};
//
const onPause = () => {
store.setPlayerState(player.value.audioRef.paused);
};
//
const onTimeUp = () => {
let lyrics = player.value.aplayer.lyrics[playIndex.value];
let lyricIndex = player.value.aplayer.lyricIndex;
if (!lyrics || !lyrics[lyricIndex]) {
return;
}
let lrc = lyrics[lyricIndex][1];
if (lrc === "Loading") {
lrc = "歌词加载中";
} else if (lrc === "Not available") {
lrc = "歌词加载失败";
}
store.setPlayerLrc(lrc);
};
//
const playToggle = () => {
player.value.toggle();
};
//
const changeVolume = (value) => {
player.value.setVolume(value, false);
};
//
const changeSong = (type) => {
type === 0 ? player.value.skipBack() : player.value.skipForward();
nextTick(() => {
player.value.play();
});
};
//
const toggleList = () => {
player.value.toggleList();
};
//
const loadMusicError = () => {
let notice = "";
if (playList.value.length > 1) {
notice = "播放歌曲出现错误,播放器将在 2s 后进行下一首";
} else {
notice = "播放歌曲出现错误";
}
ElMessage({
message: notice,
grouping: true,
icon: h(PlayWrong, {
theme: "filled",
fill: "#EFEFEF",
duration: 2000,
}),
});
console.error(
"播放歌曲: " + player.value.aplayer.audio[player.value.aplayer.index].name + " 出现错误",
);
};
//
defineExpose({ playToggle, changeVolume, changeSong, toggleList });
</script>
<style lang="scss" scoped>
.aplayer {
width: 80%;
border-radius: 6px;
font-family: "HarmonyOS_Regular", sans-serif !important;
:deep(.aplayer-body) {
background-color: transparent;
.aplayer-pic {
display: none;
}
.aplayer-info {
margin-left: 0;
background-color: #ffffff40;
border-color: transparent !important;
.aplayer-music {
flex-grow: initial;
margin-bottom: 2px;
overflow: initial;
.aplayer-title {
font-size: 16px;
margin-right: 6px;
}
.aplayer-author {
color: #efefef;
}
}
.aplayer-lrc {
text-align: left;
margin: 7px 0 6px 6px;
height: 44px;
mask: linear-gradient(
#fff 15%,
#fff 85%,
hsla(0deg, 0%, 100%, 0.6) 90%,
hsla(0deg, 0%, 100%, 0)
);
-webkit-mask: linear-gradient(
#fff 15%,
#fff 85%,
hsla(0deg, 0%, 100%, 0.6) 90%,
hsla(0deg, 0%, 100%, 0)
);
&::before,
&::after {
display: none;
}
p {
color: #efefef;
}
.aplayer-lrc-current {
font-size: 0.95rem;
margin-bottom: 4px !important;
}
}
.aplayer-controller {
display: none;
}
}
}
:deep(.aplayer-list) {
margin-top: 6px;
height: v-bind(listHeight);
background-color: transparent;
ol {
&::-webkit-scrollbar-track {
background-color: transparent;
}
li {
border-color: transparent;
&.aplayer-list-light {
background: #ffffff40;
border-radius: 6px;
}
&:hover {
background: #ffffff26 !important;
border-radius: 6px !important;
}
.aplayer-list-index,
.aplayer-list-author {
color: #efefef;
}
}
}
}
}
</style>

202
src/components/Set.vue Normal file
View File

@ -0,0 +1,202 @@
<template>
<div class="setting">
<el-collapse class="collapse" v-model="activeName" accordion>
<el-collapse-item title="个性壁纸" name="1">
<div class="bg-set">
<el-radio-group v-model="coverType" text-color="#ffffff" @change="radioChange">
<el-radio value="0" size="large" border>默认壁纸</el-radio>
<el-radio value="1" size="large" border>每日一图</el-radio>
<el-radio value="2" size="large" border>随机风景</el-radio>
<el-radio value="3" size="large" border>随机动漫</el-radio>
</el-radio-group>
</div>
</el-collapse-item>
<el-collapse-item title="个性化调整" name="2">
<div class="item">
<span class="text">建站日期显示</span>
<el-switch
v-model="siteStartShow"
inline-prompt
:active-icon="CheckSmall"
:inactive-icon="CloseSmall"
/>
</div>
<div class="item">
<span class="text">音乐点击是否打开面板</span>
<el-switch
v-model="musicClick"
inline-prompt
:active-icon="CheckSmall"
:inactive-icon="CloseSmall"
/>
</div>
<div class="item">
<span class="text">底栏歌词显示</span>
<el-switch
v-model="playerLrcShow"
inline-prompt
:active-icon="CheckSmall"
:inactive-icon="CloseSmall"
/>
</div>
<div class="item">
<span class="text">底栏背景模糊</span>
<el-switch
v-model="footerBlur"
inline-prompt
:active-icon="CheckSmall"
:inactive-icon="CloseSmall"
/>
</div>
</el-collapse-item>
<el-collapse-item title="播放器配置" name="3">
<div class="item">
<span class="text">自动播放</span>
<el-switch
v-model="playerAutoplay"
inline-prompt
:active-icon="CheckSmall"
:inactive-icon="CloseSmall"
/>
</div>
<div class="item">
<span class="text">随机播放</span>
<el-switch
v-model="playerOrder"
inline-prompt
:active-icon="CheckSmall"
:inactive-icon="CloseSmall"
active-value="random"
inactive-value="list"
/>
</div>
<div class="item">
<span class="text">循环模式</span>
<el-radio-group v-model="playerLoop" size="small" text-color="#FFFFFF">
<el-radio value="all" border>列表</el-radio>
<el-radio value="one" border>单曲</el-radio>
<el-radio value="none" border>不循环</el-radio>
</el-radio-group>
</div>
</el-collapse-item>
<el-collapse-item title="其他设置" name="4">
<div>设置内容待增加</div>
</el-collapse-item>
</el-collapse>
</div>
</template>
<script setup>
import { CheckSmall, CloseSmall, SuccessPicture } from "@icon-park/vue-next";
import { mainStore } from "@/store";
import { storeToRefs } from "pinia";
const store = mainStore();
const {
coverType,
siteStartShow,
musicClick,
playerLrcShow,
footerBlur,
playerAutoplay,
playerOrder,
playerLoop,
} = storeToRefs(store);
//
const activeName = ref("1");
//
const radioChange = () => {
ElMessage({
message: "壁纸更换成功",
icon: h(SuccessPicture, {
theme: "filled",
fill: "#efefef",
}),
});
};
</script>
<style lang="scss" scoped>
.setting {
.collapse {
border-radius: 8px;
--el-collapse-content-bg-color: #ffffff10;
border-color: transparent;
overflow: hidden;
:deep(.el-collapse-item__header) {
background-color: #ffffff30;
color: #fff;
font-size: 15px;
padding-left: 18px;
border-color: transparent;
}
:deep(.el-collapse-item__wrap) {
border-color: transparent;
.el-collapse-item__content {
padding: 20px;
.item {
display: flex;
align-items: center;
justify-content: space-between;
flex-wrap: wrap;
font-size: 14px;
.el-switch__core {
border-color: transparent;
background-color: #ffffff30;
}
.el-radio-group {
.el-radio {
margin: 2px 10px 2px 0;
border-radius: 5px;
&:last-child {
margin-right: 0;
}
}
}
}
.el-radio-group {
justify-content: space-between;
.el-radio {
margin: 10px 16px;
background: #ffffff26;
border: 2px solid transparent;
border-radius: 8px;
.el-radio__label {
color: #fff;
}
.el-radio__inner {
background: #ffffff06 !important;
border: 2px solid #eeeeee !important;
}
&.is-checked {
background: #ffffff06 !important;
border: 2px solid #eeeeee !important;
}
.is-checked {
.el-radio__inner {
background-color: #ffffff30 !important;
border-color: #fff !important;
}
& + .el-radio__label {
color: #fff !important;
}
}
}
}
}
}
}
}
</style>

View File

@ -0,0 +1,88 @@
<template>
<!-- 社交链接 -->
<div class="social">
<div class="link">
<a
v-for="item in socialLinks"
:key="item.name"
:href="item.url"
target="_blank"
@mouseenter="socialTip = item.tip"
@mouseleave="socialTip = '通过这里联系我吧'"
>
<img class="icon" :src="item.icon" height="24" />
</a>
</div>
<span class="tip">{{ socialTip }}</span>
</div>
</template>
<script setup>
import socialLinks from "@/assets/socialLinks.json";
//
const socialTip = ref("通过这里联系我吧");
</script>
<style lang="scss" scoped>
.social {
margin-top: 1rem;
display: flex;
align-items: center;
justify-content: space-between;
max-width: 460px;
width: 100%;
height: 42px;
background-color: transparent;
border-radius: 6px;
backdrop-filter: blur(0);
animation: fade 0.5s;
transition:
background-color 0.3s,
backdrop-filter 0.3s;
@media (max-width: 840px) {
max-width: 100%;
justify-content: center;
.link {
justify-content: space-evenly !important;
width: 90%;
}
.tip {
display: none !important;
}
}
.link {
display: flex;
align-items: center;
justify-content: center;
a {
display: inherit;
.icon {
margin: 0 12px;
transition: transform 0.3s;
&:hover {
transform: scale(1.1);
}
&:active {
transform: scale(1);
}
}
}
}
.tip {
display: none;
margin-right: 12px;
animation: fade 0.5s;
}
@media (min-width: 768px) {
&:hover {
background-color: #00000040;
backdrop-filter: blur(5px);
.tip {
display: block;
}
}
}
}
</style>

View File

@ -0,0 +1,98 @@
<template>
<div class="time-capsule">
<div class="title">
<hourglass-full theme="two-tone" size="24" :fill="['#efefef', '#00000020']" />
<span>时光胶囊</span>
</div>
<div v-if="timeData" class="all-capsule">
<div v-for="(item, tag, index) in timeData" :key="index" class="capsule-item">
<div class="item-title">
<span class="percentage">
{{ item.name }}已度过
<strong>{{ item.passed }}</strong>
{{ tag === "day" ? "小时" : "天" }}
</span>
<span class="remaining">
剩余&nbsp;{{ item.remaining }}&nbsp;{{ tag === "day" ? "小时" : "天" }}
</span>
</div>
<el-progress :text-inside="true" :stroke-width="20" :percentage="item.percentage" />
</div>
<!-- 建站日期 -->
<div v-if="store.siteStartShow" class="capsule-item start">
<div class="item-title">{{ startDateText }}</div>
</div>
</div>
</div>
</template>
<script setup>
import { HourglassFull } from "@icon-park/vue-next";
import { getTimeCapsule, siteDateStatistics } from "@/utils/getTime.js";
import { mainStore } from "@/store";
const store = mainStore();
//
const timeData = ref(getTimeCapsule());
const startDate = ref(import.meta.env.VITE_SITE_START);
const startDateText = ref(null);
const timeInterval = ref(null);
onMounted(() => {
timeInterval.value = setInterval(() => {
timeData.value = getTimeCapsule();
if (startDate.value) startDateText.value = siteDateStatistics(new Date(startDate.value));
}, 1000);
});
onBeforeUnmount(() => {
clearInterval(timeInterval.value);
});
</script>
<style lang="scss" scoped>
.time-capsule {
width: 100%;
.title {
display: flex;
flex-direction: row;
align-items: center;
margin: 0.2rem 0 1.5rem;
font-size: 1.1rem;
.i-icon {
display: flex;
justify-content: center;
align-items: center;
margin-right: 6px;
}
}
.all-capsule {
.capsule-item {
margin-bottom: 1rem;
.item-title {
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
margin: 1rem 0rem 0.5rem 0rem;
font-size: 0.95rem;
.remaining {
opacity: 0.6;
font-size: 0.85rem;
font-style: oblique;
}
}
&:last-child {
margin-bottom: 0;
}
&.start {
.item-title {
justify-content: center;
opacity: 0.8;
font-size: 0.85rem;
}
}
}
}
}
</style>

114
src/components/Weather.vue Normal file
View File

@ -0,0 +1,114 @@
<template>
<div class="weather" v-if="weatherData.adCode.city && weatherData.weather.weather">
<span>{{ weatherData.adCode.city }}&nbsp;</span>
<span>{{ weatherData.weather.weather }}&nbsp;</span>
<span>{{ weatherData.weather.temperature }}</span>
<span class="sm-hidden">
&nbsp;{{
weatherData.weather.winddirection?.endsWith("风")
? weatherData.weather.winddirection
: weatherData.weather.winddirection + "风"
}}&nbsp;
</span>
<span class="sm-hidden">{{ weatherData.weather.windpower }}&nbsp;</span>
</div>
<div class="weather" v-else>
<span>天气数据获取失败</span>
</div>
</template>
<script setup>
import { getAdcode, getWeather, getOtherWeather } from "@/api";
import { Error } from "@icon-park/vue-next";
// Key
const mainKey = import.meta.env.VITE_WEATHER_KEY;
//
const weatherData = reactive({
adCode: {
city: null, //
adcode: null, //
},
weather: {
weather: null, //
temperature: null, //
winddirection: null, //
windpower: null, //
},
});
//
const getTemperature = (min, max) => {
try {
//
const average = (Number(min) + Number(max)) / 2;
return Math.round(average);
} catch (error) {
console.error("计算温度出现错误:", error);
return "NaN";
}
};
//
const getWeatherData = async () => {
try {
//
if (!mainKey) {
console.log("未配置,使用备用天气接口");
const result = await getOtherWeather();
console.log(result);
const data = result.result;
weatherData.adCode = {
city: data.city.City || "未知地区",
// adcode: data.city.cityId,
};
weatherData.weather = {
weather: data.condition.day_weather,
temperature: getTemperature(data.condition.min_degree, data.condition.max_degree),
winddirection: data.condition.day_wind_direction,
windpower: data.condition.day_wind_power,
};
} else {
// Adcode
const adCode = await getAdcode(mainKey);
console.log(adCode);
if (adCode.infocode !== "10000") {
throw "地区查询失败";
}
weatherData.adCode = {
city: adCode.city,
adcode: adCode.adcode,
};
//
const result = await getWeather(mainKey, weatherData.adCode.adcode);
weatherData.weather = {
weather: result.lives[0].weather,
temperature: result.lives[0].temperature,
winddirection: result.lives[0].winddirection,
windpower: result.lives[0].windpower,
};
}
} catch (error) {
console.error("天气信息获取失败:" + error);
onError("天气信息获取失败");
}
};
//
const onError = (message) => {
ElMessage({
message,
icon: h(Error, {
theme: "filled",
fill: "#efefef",
}),
});
console.error(message);
};
onMounted(() => {
//
getWeatherData();
});
</script>

22
src/main.js Normal file
View File

@ -0,0 +1,22 @@
import { createApp } from "vue";
import "@/style/style.scss";
import App from "@/App.vue";
// 引入 pinia
import { createPinia } from "pinia";
import piniaPluginPersistedstate from "pinia-plugin-persistedstate";
// swiper
import "swiper/css";
const app = createApp(App);
const pinia = createPinia();
pinia.use(piniaPluginPersistedstate);
app.use(pinia);
app.mount("#app");
// PWA
navigator.serviceWorker.addEventListener("controllerchange", () => {
// 弹出更新提醒
console.log("站点已更新,刷新后生效");
ElMessage("站点已更新,刷新后生效");
});

93
src/store/index.js Normal file
View File

@ -0,0 +1,93 @@
import { defineStore } from "pinia";
export const mainStore = defineStore("main", {
state: () => {
return {
imgLoadStatus: false, // 壁纸加载状态
innerWidth: null, // 当前窗口宽度
coverType: "0", // 壁纸种类
siteStartShow: false, // 建站日期显示
musicClick: false, // 音乐链接是否跳转
musicIsOk: false, // 音乐是否加载完成
musicVolume: 0, // 音乐音量;
musicOpenState: false, // 音乐面板开启状态
backgroundShow: false, // 壁纸展示状态
boxOpenState: false, // 盒子开启状态
mobileOpenState: false, // 移动端开启状态
mobileFuncState: false, // 移动端功能区开启状态
setOpenState: false, // 设置页面开启状态
playerState: false, // 当前播放状态
playerTitle: null, // 当前播放歌曲名
playerArtist: null, // 当前播放歌手名
playerLrc: "歌词加载中", // 当前播放歌词
playerLrcShow: true, // 是否显示底栏歌词
footerBlur: true, // 底栏模糊
playerAutoplay: false, // 是否自动播放
playerLoop: "all", // 循环播放 "all", "one", "none"
playerOrder: "list", // 循环顺序 "list", "random"
};
},
getters: {
// 获取歌词
getPlayerLrc(state) {
return state.playerLrc;
},
// 获取歌曲信息
getPlayerData(state) {
return {
name: state.playerTitle,
artist: state.playerArtist,
};
},
// 获取页面宽度
getInnerWidth(state) {
return state.innerWidth;
},
},
actions: {
// 更改当前页面宽度
setInnerWidth(value) {
this.innerWidth = value;
if (value >= 720) {
this.mobileOpenState = false;
this.mobileFuncState = false;
}
},
// 更改播放状态
setPlayerState(value) {
if (value) {
this.playerState = false;
} else {
this.playerState = true;
}
},
// 更改歌词
setPlayerLrc(value) {
this.playerLrc = value;
},
// 更改歌曲数据
setPlayerData(title, artist) {
this.playerTitle = title;
this.playerArtist = artist;
},
// 更改壁纸加载状态
setImgLoadStatus(value) {
this.imgLoadStatus = value;
},
},
persist: {
key: "data",
storage: window.localStorage,
paths: [
"coverType",
"musicVolume",
"siteStartShow",
"musicClick",
"playerLrcShow",
"footerBlur",
"playerAutoplay",
"playerLoop",
"playerOrder",
],
},
});

36
src/style/global.scss Normal file
View File

@ -0,0 +1,36 @@
// scss 全局变量
// 响应式布局
@mixin changeWidth($maxWidth: 1200px) {
.container {
max-width: $maxWidth;
}
}
// 首次调用
@include changeWidth;
/* 小于1380px时 */
@media (max-width: 1380px) {
.el-radio-group {
justify-content: center !important;
}
}
/* 小于1280px时 */
@media (max-width: 1280px) {
@include changeWidth($maxWidth: 1100px);
}
/* 小于992px时 */
@media (max-width: 992px) {
@include changeWidth($maxWidth: 900px);
}
/* 小于720px时 */
@media (max-width: 720px) {
// 隐藏元素
.xs-hidden {
display: none;
}
}

228
src/style/style.scss Normal file
View File

@ -0,0 +1,228 @@
/*
作者: imsyy
主页https://www.imsyy.top/
GitHubhttps://github.com/imsyy/home
版权所有请勿删除
*/
@charset "utf-8";
/*全局样式*/
html,
body {
width: 100%;
height: 100%;
// width: 100dvh;
// height: 100dvh;
margin: 0;
padding: 0;
background-color: #333;
overflow: hidden;
font-family: "HarmonyOS_Regular", sans-serif;
}
*,
a,
p {
margin: 0;
padding: 0;
user-select: none;
text-decoration: none;
color: #fff;
box-sizing: border-box;
&:hover {
transition: 0.3s;
}
}
// 字体文件
@font-face {
font-family: "Pacifico-Regular";
font-display: swap;
src: url("/font/Pacifico-Regular.ttf") format("truetype");
}
@font-face {
font-family: "UnidreamLED";
font-display: swap;
src: url("/font/UnidreamLED.ttf") format("truetype");
}
// 基础样式
#app {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 0;
}
// 卡片样式
.cards {
border-radius: 6px;
background-color: #00000040;
backdrop-filter: blur(10px);
transform: scale(1);
transition:
backdrop-filter 0.3s,
transform 0.3s;
&:hover {
transform: scale(1.01);
}
&:active {
transform: scale(0.98);
}
}
// 文字超出
.text-hidden {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
// 弹窗样式
.el-message {
--el-message-bg-color: #00000040 !important;
--el-message-text-color: #efefef !important;
-webkit-backdrop-filter: blur(10px);
backdrop-filter: blur(10px);
border-radius: 25px !important;
border-color: transparent !important;
.el-message__badge {
display: none;
}
.el-message__content {
white-space: nowrap;
}
}
// 进度条样式
.el-progress-bar {
.el-progress-bar__outer {
border-radius: 6px;
background-color: #00000020;
.el-progress-bar__inner {
background-color: #efefef;
border-radius: 6px;
text-align: center;
font-family: "UnidreamLED";
span {
color: #564d59;
font-size: 0.9rem;
}
}
}
}
// Tooltip 样式
.el-popper.is-dark {
background: #ffffff60 !important;
border: 1px solid transparent !important;
}
// 卡片样式
.el-card {
border-radius: 8px !important;
border: 1px solid transparent !important;
background-color: transparent !important;
.el-card__header {
font-weight: bold;
padding: 16px 20px !important;
background-color: #ffffff30 !important;
border-bottom: 1px solid transparent !important;
}
.el-card__body {
padding: 0 !important;
background-color: #ffffff10 !important;
}
}
// Transition 动画
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.3s ease-in-out;
}
.fade-enter-from,
.fade-leave-to {
opacity: 0;
}
// keyframes 动画
@keyframes fade {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
@keyframes fade-blur-in {
from {
filter: blur(20px) brightness(0.3);
transform: scale(1.6);
}
to {
filter: blur(0) brightness(1);
transform: scale(1);
}
}
@keyframes fade-blur-main-in {
from {
transform: scale(1.2);
}
to {
transform: scale(1);
}
}
// 隐藏元素
@media (min-width: 910px) and (max-width: 1200px) {
.sm-hidden {
display: none;
}
}
// 自定义鼠标
#cursor {
position: fixed;
width: 18px;
height: 18px;
background: #fff;
border-radius: 25px;
opacity: 0.25;
z-index: 10086;
pointer-events: none;
transition: 0.2s ease-in-out;
transition-property: background, opacity, transform;
&.hidden {
opacity: 0;
}
&.active {
opacity: 0.5;
transform: scale(0.5);
}
}
// 滚动条样式
::-webkit-scrollbar,
scrollbar {
width: 6px;
height: 6px;
background-color: transparent;
}
::-webkit-scrollbar-thumb,
scrollbar-thumb {
border-radius: 10px;
background-color: #eeeeee;
}

94
src/utils/cursor.js Normal file
View File

@ -0,0 +1,94 @@
let mainCursor;
Math.lerp = (a, b, n) => (1 - n) * a + n * b;
const getStyle = (el, attr) => {
try {
return window.getComputedStyle ? window.getComputedStyle(el)[attr] : el.currentStyle[attr];
} catch (e) {
console.error(e);
}
return false;
};
const cursorInit = () => {
mainCursor = new Cursor();
return mainCursor;
};
class Cursor {
constructor() {
this.pos = {
curr: null,
prev: null,
};
this.pt = [];
this.create();
this.init();
this.render();
}
move(left, top) {
this.cursor.style["left"] = `${left}px`;
this.cursor.style["top"] = `${top}px`;
}
create() {
if (!this.cursor) {
this.cursor = document.createElement("div");
this.cursor.id = "cursor";
this.cursor.classList.add("xs-hidden");
this.cursor.classList.add("hidden");
document.body.append(this.cursor);
}
var el = document.getElementsByTagName("*");
for (let i = 0; i < el.length; i++)
if (getStyle(el[i], "cursor") == "pointer") this.pt.push(el[i].outerHTML);
document.body.appendChild((this.scr = document.createElement("style")));
this.scr.innerHTML = `* {cursor: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8' width='10px' height='10px'><circle cx='4' cy='4' r='4' fill='white' /></svg>") 4 4, auto !important}`;
}
refresh() {
this.scr.remove();
this.cursor.classList.remove("active");
this.pos = {
curr: null,
prev: null,
};
this.pt = [];
this.create();
this.init();
this.render();
}
init() {
document.onmousemove = (e) => {
this.pos.curr == null && this.move(e.clientX - 8, e.clientY - 8);
this.pos.curr = {
x: e.clientX - 8,
y: e.clientY - 8,
};
this.cursor.classList.remove("hidden");
};
document.onmouseenter = () => this.cursor.classList.remove("hidden");
document.onmouseleave = () => this.cursor.classList.add("hidden");
document.onmousedown = () => this.cursor.classList.add("active");
document.onmouseup = () => this.cursor.classList.remove("active");
}
render() {
if (this.pos.prev) {
this.pos.prev.x = Math.lerp(this.pos.prev.x, this.pos.curr.x, 0.35);
this.pos.prev.y = Math.lerp(this.pos.prev.y, this.pos.curr.y, 0.35);
this.move(this.pos.prev.x, this.pos.prev.y);
} else {
this.pos.prev = this.pos.curr;
}
requestAnimationFrame(() => this.render());
}
}
export default cursorInit;

Some files were not shown because too many files have changed in this diff Show More