Compare commits

..

No commits in common. "dev" and "v1.1" have entirely different histories.
dev ... v1.1

123 changed files with 1982 additions and 9840 deletions

View File

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

View File

@ -1,51 +0,0 @@
# 站点信息
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"

View File

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

View File

@ -1,35 +0,0 @@
{
"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
}
}

View File

@ -1,22 +0,0 @@
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?"

View File

@ -1,22 +0,0 @@
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: "还需要说些什么吗"

View File

@ -1,14 +0,0 @@
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?"

View File

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

View File

@ -1,46 +0,0 @@
# 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
View File

@ -1,25 +0,0 @@
# 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
View File

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

View File

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

View File

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

View File

@ -1,128 +0,0 @@
# 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.

View File

@ -1,17 +0,0 @@
# 构建应用
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
View File

@ -1,21 +0,0 @@
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.

245
README.md
View File

@ -1,244 +1,5 @@
简体中文 | [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] Hitokoto 一言
- [x] 日期及时间
- [x] 实时天气
- [x] 时光进度条
- [x] 音乐播放器
- [x] 移动端适配
### ⚙️ 自动部署
如果遇到构建环境或者打包过程出现错误,则可以采用 `Github Actions` 来进行自动构建
- 在成功 `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
- [韩小韩 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/)
## 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>
<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>

View File

@ -1,144 +0,0 @@
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
View File

@ -1,57 +0,0 @@
// 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
View File

@ -1,35 +0,0 @@
// 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']
}
}

89
css/animation.css Normal file
View File

@ -0,0 +1,89 @@
/*模糊渐入动画*/
@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;
}
}

64
css/font.css Normal file
View File

@ -0,0 +1,64 @@
@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";
}

125
css/loading.css Normal file
View File

@ -0,0 +1,125 @@
#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);
}
}

225
css/mobile.css Normal file
View File

@ -0,0 +1,225 @@
@charset"utf-8";
/*小于1400px时*/
@media (max-width: 1400px) {
/*时钟显示*/
span#win_text,
span#win_speed {
display: none;
}
}
/*小于1200px时*/
@media (max-width: 1200px) {
/*总布局*/
.container,
.container-lg,
.container-md,
.container-sm {
max-width: 1100px !important;
}
/*天气模块*/
.weather {
display: none;
}
.weekday {
display: none;
}
}
/*小于992px时*/
@media (max-width: 992px) {
/*一言*/
.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;
}
}
/*小于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;
}
*/
/*社交链接*/
.social {
max-width: 100%;
justify-content: center;
}
#link-text {
display: none !important;
}
.link i {
margin: 0px 20px;
}
/*菜单栏按钮*/
.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;
}
/*页脚文字*/
footer {
font-size: 0.85rem;
}
}
@media (min-width: 660px) {
.menu {
display: none !important;
}
}
/*小于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;
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 {
animation: fade 0.5;
-webkit-animation: fade 0.5s;
-moz-animation: fade 0.5s;
-o-animation: fade 0.5s;
-ms-animation: fade 0.5s;
}

323
css/style.css Normal file
View File

@ -0,0 +1,323 @@
@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;
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;
}
.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;
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;
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 {
left: auto;
top: 4px;
right: 8px;
font-size: 1.45rem;
}
/*进度条*/
.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;
}
/*页脚样式*/
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;
}

View File

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

BIN
favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

Before

Width:  |  Height:  |  Size: 5.1 KiB

After

Width:  |  Height:  |  Size: 5.1 KiB

BIN
img/background.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View File

Before

Width:  |  Height:  |  Size: 264 KiB

After

Width:  |  Height:  |  Size: 264 KiB

View File

Before

Width:  |  Height:  |  Size: 5.1 KiB

After

Width:  |  Height:  |  Size: 5.1 KiB

BIN
img/weixin.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

View File

@ -1,39 +1,304 @@
<!doctype html>
<!DOCTYPE html>
<html lang="zh-CN">
<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>
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>
</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>
<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>
<!-- 百度统计 -->
<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);
})();
</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">
<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" onclick="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>
<div class="col right">
<div class="main-right">
<!--功能区-->
<div class="row 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://blog.imsyy.top/about/" target="_blank">
<div class="link-card cards">
<i class="fad fa-info-circle"></i>
<span class="link-name">关于</span>
</div>
</a>
</div>
</div>
</div>
</div>
</div>
</div>
<!--展开菜单按钮-->
<div class="menu">
<a class="munu-button cards" id="menu" onclick="switchMenu()"><i class="fad fa-bars"></i></a>
</div>
<!--第二屏 Logo-->
<div class="logo" style="display: none;">
<a>imsyy.top</a>
</div>
<!--更多内容-->
<div class="more cards">
<div class="close fixed-top" onclick="switchMore()"><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>
<div class="link-card cards">
<span class="link-name">还没搞</span>
</div>
</a>
</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>
</html>

215
js/main.js Normal file
View File

@ -0,0 +1,215 @@
//弹窗样式
iziToast.settings({
timeout: 10000,
icon: 'Fontawesome',
closeOnEscape: 'true',
position: 'topLeft',
transitionIn: 'bounceInRight',
transitionOut: 'fadeOutLeft',
displayMode: '2',
layout: '2',
titleColor: '#efefef',
messageColor: '#efefef',
iconColor: '#efefef',
});
iziToast.info({
icon: 'fad fa-vial',
title: '新版站点试运行',
message: '还存在亿些小问题 ~ <a href="./old/" style="color:#efefef">返回旧版</a>'
});
//获取一言
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)
//链接提示文字
window.onload = function () {
var link = document.getElementById("social");
link.onmouseover = function () {
document.getElementById("social").style.cssText = "background: rgb(0 0 0 / 25%);backdrop-filter: blur(5px);border-radius: 6px;transition: all 0.5s";
document.getElementById("link-text").style.cssText = "display: block;transition: all 0.5s";
};
link.onmouseout = function () {
document.getElementById("social").style.cssText = "background: none;backdrop-filter: none;border-radius: 6px;transition: all 0.5s";
document.getElementById("link-text").style.cssText = "display: none;transition: all 0.5s";
}
var link = document.getElementById("github");
link.onmouseover = function () {
document.getElementById("link-text").innerHTML = "去 Github 看看";
};
link.onmouseout = function () {
document.getElementById("link-text").innerHTML = "通过这里联系我";
}
var link1 = document.getElementById("qq");
link1.onmouseover = function () {
document.getElementById("link-text").innerHTML = "有什么事吗";
};
link1.onmouseout = function () {
document.getElementById("link-text").innerHTML = "通过这里联系我";
}
var link2 = document.getElementById("email");
link2.onmouseover = function () {
document.getElementById("link-text").innerHTML = "来封 Email";
};
link2.onmouseout = function () {
document.getElementById("link-text").innerHTML = "通过这里联系我";
}
var link3 = document.getElementById("telegram");
link3.onmouseover = function () {
document.getElementById("link-text").innerHTML = "你懂的 ~";
};
link3.onmouseout = function () {
document.getElementById("link-text").innerHTML = "通过这里联系我";
}
var link4 = document.getElementById("twitter");
link4.onmouseover = function () {
document.getElementById("link-text").innerHTML = "你懂的 ~";
};
link4.onmouseout = function () {
document.getElementById("link-text").innerHTML = "通过这里联系我";
}
};
//菜单栏切换
function switchMenu() {
var menu = document.cookie.replace(/(?:(?:^|.*;\s*)menu\s*\=\s*([^;]*).*$)|^.*$/, "$1") || '0';
if (menu == '0') {
document.getElementById("container").classList.add('menus');
document.getElementById("menu").innerHTML = "<i class='fad fa-times'></i>";
document.cookie = "menu=1;path=/";
} else {
document.getElementById("container").classList.remove('menus');
document.getElementById("menu").innerHTML = "<i class='fad fa-bars'></i>";
document.cookie = "menu=0;path=/";
}
}
//更多页面切换
function switchMore() {
var more = document.cookie.replace(/(?:(?:^|.*;\s*)more\s*\=\s*([^;]*).*$)|^.*$/, "$1") || '0';
if (more == '0') {
document.getElementById("container").classList.add('mores');
document.getElementById("change").innerHTML = "Oops&nbsp;!";
document.getElementById("change1").innerHTML = "哎呀,这都被你发现了( 再点击一次可关闭 ";
document.cookie = "more=1;path=/";
} else {
document.getElementById("container").classList.remove('mores');
document.getElementById("change").innerHTML = "Hello&nbsp;World&nbsp;!";
document.getElementById("change1").innerHTML = "一个建立于 21 世纪的小站,存活于互联网的边缘";
document.cookie = "more=0;path=/";
}
}
//监听网页宽度
window.addEventListener('load', function () {
//console.log(window.innerWidth);
window.addEventListener('resize', function () {
//console.log(window.innerWidth);
//关闭移动端样式
if (window.innerWidth >= 600) {
document.getElementById("container").classList.remove('menus');
}
//移动端隐藏更多页面
if (window.innerWidth <= 990) {
document.getElementById("container").classList.remove('mores');
document.getElementById("change").innerHTML = "Hello&nbsp;World&nbsp;!";
document.getElementById("change1").innerHTML = "一个建立于 21 世纪的小站,存活于互联网的边缘";
}
})
})

73
js/time.js Normal file
View File

@ -0,0 +1,73 @@
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() + 6; //获取当前星期几(0-6)
this.hour = myHours;
this.year = myYear;
this.month = myMonth - 1;
this.day = myDay - 1;
this.curday = myDay;
this.week = myWeek;
this.curweek = myWeek + 1;
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>";
}
}
})

View File

@ -1,44 +0,0 @@
{
"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"
}
}

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 93 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 95 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 138 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 92 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 245 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 67 KiB

View File

@ -1,191 +0,0 @@
<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>

View File

@ -1,75 +0,0 @@
// 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();
};

View File

@ -1,37 +0,0 @@
[
{
"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

@ -1,38 +0,0 @@
[
{
"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

@ -1,171 +0,0 @@
<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>

View File

@ -1,120 +0,0 @@
<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>

View File

@ -1,128 +0,0 @@
<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>

View File

@ -1,182 +0,0 @@
<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>

View File

@ -1,152 +0,0 @@
<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>

View File

@ -1,193 +0,0 @@
<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

@ -1,14 +0,0 @@
<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>

View File

@ -1,312 +0,0 @@
<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>

View File

@ -1,288 +0,0 @@
<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>

View File

@ -1,202 +0,0 @@
<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

@ -1,88 +0,0 @@
<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

@ -1,98 +0,0 @@
<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>

View File

@ -1,114 +0,0 @@
<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>

View File

@ -1,22 +0,0 @@
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("站点已更新,刷新后生效");
});

View File

@ -1,93 +0,0 @@
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",
],
},
});

View File

@ -1,36 +0,0 @@
// 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;
}
}

View File

@ -1,228 +0,0 @@
/*
作者: 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;
}

View File

@ -1,94 +0,0 @@
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