Compare commits
5 Commits
c2e540cc0d
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
055eef9a0f | ||
|
|
ee87ae4fee | ||
|
|
8019ebd226 | ||
|
|
eb9ffb62ba | ||
|
|
96c35afab6 |
@@ -7,7 +7,7 @@ on:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build-and-deploy:
|
build-and-deploy:
|
||||||
runs-on: self-hosted
|
runs-on: debian
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
@@ -16,37 +16,81 @@ jobs:
|
|||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 20
|
node-version: 20
|
||||||
cache: npm
|
|
||||||
|
- name: Cache npm dependencies
|
||||||
|
# gitea 不支持 actions/cache@v4,使用 v3 代替
|
||||||
|
uses: actions/cache@v3
|
||||||
|
with:
|
||||||
|
path: ~/.npm
|
||||||
|
key: npm-${{ hashFiles('package-lock.json') }}
|
||||||
|
restore-keys: npm-
|
||||||
|
|
||||||
- name: Install
|
- name: Install
|
||||||
run: npm ci
|
run: npm ci
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
env:
|
env:
|
||||||
SITE_URL: ${{ secrets.SITE_URL }}
|
SITE_URL: ${{ vars.SITE_URL }}
|
||||||
run: npm run build
|
run: npm run build
|
||||||
|
|
||||||
- name: Write deploy key
|
- name: Install sshpass
|
||||||
env:
|
|
||||||
DEPLOY_SSH_KEY: ${{ secrets.DEPLOY_SSH_KEY }}
|
|
||||||
run: |
|
run: |
|
||||||
mkdir -p ~/.ssh
|
if ! command -v sshpass &> /dev/null; then
|
||||||
python3 - <<'PY'
|
if command -v apt-get &> /dev/null; then
|
||||||
import os
|
sudo apt-get update && sudo apt-get install -y sshpass
|
||||||
from pathlib import Path
|
elif command -v yum &> /dev/null; then
|
||||||
key = os.environ['DEPLOY_SSH_KEY']
|
sudo yum install -y sshpass
|
||||||
p = Path.home() / '.ssh' / 'deploy_key'
|
elif command -v apk &> /dev/null; then
|
||||||
p.write_text(key, encoding='utf-8')
|
sudo apk add --no-cache sshpass
|
||||||
PY
|
fi
|
||||||
chmod 600 ~/.ssh/deploy_key
|
fi
|
||||||
|
|
||||||
- name: Add known_hosts
|
- name: Add known_hosts
|
||||||
run: |
|
run: |
|
||||||
mkdir -p ~/.ssh
|
mkdir -p ~/.ssh
|
||||||
ssh-keyscan -p "${{ secrets.DEPLOY_SSH_PORT }}" -H "${{ secrets.DEPLOY_SSH_HOST }}" >> ~/.ssh/known_hosts
|
ssh-keyscan -p "${{ vars.DEPLOY_SSH_PORT }}" -H "${{ vars.DEPLOY_SSH_HOST }}" >> ~/.ssh/known_hosts
|
||||||
|
|
||||||
- name: Deploy via tar over SSH
|
- name: Deploy via tar over SSH
|
||||||
|
env:
|
||||||
|
SSHPASS: ${{ secrets.DEPLOY_SSH_PASSWORD }}
|
||||||
run: |
|
run: |
|
||||||
tar -C dist -czf - . | \
|
tar -C dist -czf - . | \
|
||||||
ssh -o BatchMode=yes -o StrictHostKeyChecking=yes -o ConnectTimeout=15 -i ~/.ssh/deploy_key -p "${{ secrets.DEPLOY_SSH_PORT }}" "${{ secrets.DEPLOY_SSH_USER }}@${{ secrets.DEPLOY_SSH_HOST }}" \
|
sshpass -e ssh -o StrictHostKeyChecking=yes -o ConnectTimeout=15 -p "${{ vars.DEPLOY_SSH_PORT }}" "${{ vars.DEPLOY_SSH_USER }}@${{ vars.DEPLOY_SSH_HOST }}" \
|
||||||
"bash -lc 'set -euo pipefail; tmp=\"\${{ secrets.DEPLOY_PATH }}.tmp\"; rm -rf \"\$tmp\"; mkdir -p \"\$tmp\"; tar -xzf - -C \"\$tmp\"; rm -rf \"\${{ secrets.DEPLOY_PATH }}\"; mv \"\$tmp\" \"\${{ secrets.DEPLOY_PATH }}\"'"
|
"set -euo pipefail; tmp='${{ vars.DEPLOY_PATH }}.tmp'; rm -rf \"\$tmp\"; mkdir -p \"\$tmp\"; tar -xzf - -C \"\$tmp\"; rm -rf '${{ vars.DEPLOY_PATH }}'; mv \"\$tmp\" '${{ vars.DEPLOY_PATH }}'"
|
||||||
|
|
||||||
|
- name: 发送通知
|
||||||
|
if: always()
|
||||||
|
continue-on-error: true
|
||||||
|
env:
|
||||||
|
WEBHOOK_URL: ${{ vars.WEBHOOK_URL }}
|
||||||
|
run: |
|
||||||
|
[ -z "$WEBHOOK_URL" ] && exit 0
|
||||||
|
|
||||||
|
if [ "${{ job.status }}" = "success" ]; then
|
||||||
|
status_text="部署成功 ✅"
|
||||||
|
else
|
||||||
|
status_text="部署失败 ❌"
|
||||||
|
fi
|
||||||
|
|
||||||
|
commit_title=$(git log -1 --pretty=format:"%s" 2>/dev/null || echo "N/A")
|
||||||
|
workflow_url="${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_number }}"
|
||||||
|
site_url="${{ vars.SITE_URL }}"
|
||||||
|
|
||||||
|
if [ "${{ job.status }}" = "success" ]; then
|
||||||
|
payload=$(jq -n \
|
||||||
|
--arg title "${{ github.event.repository.name }} ${status_text}" \
|
||||||
|
--arg commit "$commit_title" \
|
||||||
|
--arg author "${{ github.actor }}" \
|
||||||
|
--arg site "$site_url" \
|
||||||
|
--arg url "$workflow_url" \
|
||||||
|
'{msg_type: "text", content: {text: "\($title)\n提交:\($commit)\n作者:\($author)\n站点:\($site)\n详情:\($url)"}}')
|
||||||
|
else
|
||||||
|
payload=$(jq -n \
|
||||||
|
--arg title "${{ github.event.repository.name }} ${status_text}" \
|
||||||
|
--arg commit "$commit_title" \
|
||||||
|
--arg author "${{ github.actor }}" \
|
||||||
|
--arg url "$workflow_url" \
|
||||||
|
'{msg_type: "text", content: {text: "\($title)\n提交:\($commit)\n作者:\($author)\n详情:\($url)"}}')
|
||||||
|
fi
|
||||||
|
|
||||||
|
curl -sS -H "Content-Type: application/json" -X POST -d "$payload" "$WEBHOOK_URL"
|
||||||
|
|||||||
108
AGENTS.md
Normal file
108
AGENTS.md
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
# AI 代理指南
|
||||||
|
|
||||||
|
本文档为 AI 代理提供项目上下文和操作指南。
|
||||||
|
|
||||||
|
## 项目概述
|
||||||
|
|
||||||
|
- **类型**:Astro 静态博客站点
|
||||||
|
- **域名**:https://wuyouwulv.me
|
||||||
|
- **仓库**:voson/publish(Gitea)
|
||||||
|
- **部署**:Gitea Actions → SSH → Vultr 服务器
|
||||||
|
|
||||||
|
## 技术栈
|
||||||
|
|
||||||
|
- **框架**:Astro 5.x
|
||||||
|
- **语言**:TypeScript
|
||||||
|
- **样式**:全局 CSS
|
||||||
|
- **部署**:Gitea Actions + SSH 密码认证
|
||||||
|
|
||||||
|
## 目录结构
|
||||||
|
|
||||||
|
```
|
||||||
|
publish/
|
||||||
|
├── .gitea/workflows/deploy.yml # CI/CD 部署工作流
|
||||||
|
├── deploy/ # 部署文档和配置示例
|
||||||
|
├── public/ # 静态资源
|
||||||
|
├── src/
|
||||||
|
│ ├── components/ # Astro 组件
|
||||||
|
│ ├── content/blog/ # 博客文章(Markdown)
|
||||||
|
│ ├── layouts/ # 页面布局
|
||||||
|
│ ├── pages/ # 页面路由
|
||||||
|
│ └── styles/ # 全局样式
|
||||||
|
└── astro.config.mjs # Astro 配置
|
||||||
|
```
|
||||||
|
|
||||||
|
## 服务器配置
|
||||||
|
|
||||||
|
| 项目 | 值 |
|
||||||
|
|------|-----|
|
||||||
|
| 服务器 IP | `45.32.105.53` |
|
||||||
|
| SSH 用户 | `root` |
|
||||||
|
| SSH 端口 | `22` |
|
||||||
|
| 部署路径 | `/var/www/publish` |
|
||||||
|
| Web 服务器 | Caddy |
|
||||||
|
|
||||||
|
服务器配置文件位置:`/Users/voson/Library/Mobile Documents/com~apple~CloudDocs/refining/config.toml`
|
||||||
|
|
||||||
|
## Gitea 配置
|
||||||
|
|
||||||
|
- **实例**:https://gitea.refining.dev
|
||||||
|
- **仓库**:voson/publish(注意:不是 refining/publish)
|
||||||
|
- **Token**:见 `config.toml` 中的 `[services.gitea]`
|
||||||
|
|
||||||
|
### Actions 变量(vars)
|
||||||
|
|
||||||
|
| 变量 | 说明 |
|
||||||
|
|------|------|
|
||||||
|
| `SITE_URL` | 站点 URL,必须包含 `https://` |
|
||||||
|
| `DEPLOY_SSH_HOST` | 服务器 IP |
|
||||||
|
| `DEPLOY_SSH_PORT` | SSH 端口 |
|
||||||
|
| `DEPLOY_SSH_USER` | SSH 用户名 |
|
||||||
|
| `DEPLOY_PATH` | 部署目录 |
|
||||||
|
| `WEBHOOK_URL` | 飞书通知 Webhook |
|
||||||
|
|
||||||
|
### Actions 密钥(secrets)
|
||||||
|
|
||||||
|
| 密钥 | 说明 |
|
||||||
|
|------|------|
|
||||||
|
| `DEPLOY_SSH_PASSWORD` | SSH 登录密码 |
|
||||||
|
|
||||||
|
## 常见操作
|
||||||
|
|
||||||
|
### 查看构建日志
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 获取最近的运行
|
||||||
|
curl -s -H "Authorization: token TOKEN" \
|
||||||
|
"https://gitea.refining.dev/api/v1/repos/voson/publish/actions/runs?limit=1" | jq .
|
||||||
|
|
||||||
|
# 获取 job 日志
|
||||||
|
curl -s -H "Authorization: token TOKEN" \
|
||||||
|
"https://gitea.refining.dev/api/v1/repos/voson/publish/actions/jobs/JOB_ID/logs"
|
||||||
|
```
|
||||||
|
|
||||||
|
### 设置仓库变量
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -X POST -H "Authorization: token TOKEN" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{"data":"VALUE","value":"VALUE"}' \
|
||||||
|
"https://gitea.refining.dev/api/v1/repos/voson/publish/actions/variables/VAR_NAME"
|
||||||
|
```
|
||||||
|
|
||||||
|
### 手动部署
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd /Users/voson/publish
|
||||||
|
npm run build
|
||||||
|
tar -C dist -czf - . | sshpass -p 'PASSWORD' ssh root@45.32.105.53 \
|
||||||
|
"set -euo pipefail; tmp='/var/www/publish.tmp'; rm -rf \"\$tmp\"; mkdir -p \"\$tmp\"; tar -xzf - -C \"\$tmp\"; rm -rf '/var/www/publish'; mv \"\$tmp\" '/var/www/publish'"
|
||||||
|
```
|
||||||
|
|
||||||
|
## 注意事项
|
||||||
|
|
||||||
|
1. **仓库路径**:仓库是 `voson/publish`,不是 `refining/publish`
|
||||||
|
2. **SITE_URL**:必须包含 `https://` 前缀,否则 Astro 构建会报 "Invalid url"
|
||||||
|
3. **SSH 认证**:使用密码认证(sshpass),不是 SSH 密钥
|
||||||
|
4. **Gitea Cache**:Gitea 不支持 `actions/cache@v4`,必须使用 `v3`
|
||||||
|
5. **变量 vs 密钥**:敏感信息(密码)用 secrets,其他用 vars
|
||||||
62
README.md
62
README.md
@@ -1,62 +0,0 @@
|
|||||||
# Astro Starter Kit: Blog
|
|
||||||
|
|
||||||
```sh
|
|
||||||
npm create astro@latest -- --template blog
|
|
||||||
```
|
|
||||||
|
|
||||||
> 🧑🚀 **Seasoned astronaut?** Delete this file. Have fun!
|
|
||||||
|
|
||||||
Features:
|
|
||||||
|
|
||||||
- ✅ Minimal styling (make it your own!)
|
|
||||||
- ✅ 100/100 Lighthouse performance
|
|
||||||
- ✅ SEO-friendly with canonical URLs and OpenGraph data
|
|
||||||
- ✅ Sitemap support
|
|
||||||
- ✅ RSS Feed support
|
|
||||||
- ✅ Markdown & MDX support
|
|
||||||
|
|
||||||
## 🚀 Project Structure
|
|
||||||
|
|
||||||
Inside of your Astro project, you'll see the following folders and files:
|
|
||||||
|
|
||||||
```text
|
|
||||||
├── public/
|
|
||||||
├── src/
|
|
||||||
│ ├── components/
|
|
||||||
│ ├── content/
|
|
||||||
│ ├── layouts/
|
|
||||||
│ └── pages/
|
|
||||||
├── astro.config.mjs
|
|
||||||
├── README.md
|
|
||||||
├── package.json
|
|
||||||
└── tsconfig.json
|
|
||||||
```
|
|
||||||
|
|
||||||
Astro looks for `.astro` or `.md` files in the `src/pages/` directory. Each page is exposed as a route based on its file name.
|
|
||||||
|
|
||||||
There's nothing special about `src/components/`, but that's where we like to put any Astro/React/Vue/Svelte/Preact components.
|
|
||||||
|
|
||||||
The `src/content/` directory contains "collections" of related Markdown and MDX documents. Use `getCollection()` to retrieve posts from `src/content/blog/`, and type-check your frontmatter using an optional schema. See [Astro's Content Collections docs](https://docs.astro.build/en/guides/content-collections/) to learn more.
|
|
||||||
|
|
||||||
Any static assets, like images, can be placed in the `public/` directory.
|
|
||||||
|
|
||||||
## 🧞 Commands
|
|
||||||
|
|
||||||
All commands are run from the root of the project, from a terminal:
|
|
||||||
|
|
||||||
| Command | Action |
|
|
||||||
| :------------------------ | :----------------------------------------------- |
|
|
||||||
| `npm install` | Installs dependencies |
|
|
||||||
| `npm run dev` | Starts local dev server at `localhost:4321` |
|
|
||||||
| `npm run build` | Build your production site to `./dist/` |
|
|
||||||
| `npm run preview` | Preview your build locally, before deploying |
|
|
||||||
| `npm run astro ...` | Run CLI commands like `astro add`, `astro check` |
|
|
||||||
| `npm run astro -- --help` | Get help using the Astro CLI |
|
|
||||||
|
|
||||||
## 👀 Want to learn more?
|
|
||||||
|
|
||||||
Check out [our documentation](https://docs.astro.build) or jump into our [Discord server](https://astro.build/chat).
|
|
||||||
|
|
||||||
## Credit
|
|
||||||
|
|
||||||
This theme is based off of the lovely [Bear Blog](https://github.com/HermanMartinus/bearblog/).
|
|
||||||
138
deploy/README.md
138
deploy/README.md
@@ -1,26 +1,126 @@
|
|||||||
# Server deploy (static)
|
# 部署文档
|
||||||
|
|
||||||
This repo builds an Astro static site into `dist/` and deploys it to a Linux server via rsync over SSH.
|
本项目使用 Astro 构建静态站点,通过 Gitea Actions 自动部署到 Linux 服务器。
|
||||||
|
|
||||||
## One-time server setup
|
## 架构概览
|
||||||
|
|
||||||
1. Create a deploy directory, e.g. `/var/www/publish`.
|
```
|
||||||
2. Configure your web server (Caddy or Nginx) to serve that directory.
|
本地开发 → Git Push → Gitea Actions → 构建 → SSH 部署 → 服务器
|
||||||
3. Create an SSH key for CI and add its public key to the server.
|
↓
|
||||||
|
飞书通知
|
||||||
|
```
|
||||||
|
|
||||||
## Gitea Actions secrets (repo settings)
|
## 服务器信息
|
||||||
|
|
||||||
- `SITE_URL`
|
| 项目 | 值 |
|
||||||
- `PUBLIC_NEWSLETTER_ACTION`
|
|------|-----|
|
||||||
- `PUBLIC_NEWSLETTER_EMAIL_FIELD`
|
| IP | `45.32.105.53` |
|
||||||
- `PUBLIC_NEWSLETTER_TITLE` (optional)
|
| 用户名 | `root` |
|
||||||
- `PUBLIC_NEWSLETTER_DESCRIPTION` (optional)
|
| 部署路径 | `/var/www/publish` |
|
||||||
- `DEPLOY_SSH_HOST`
|
| Web 服务器 | Caddy |
|
||||||
- `DEPLOY_SSH_PORT`
|
| 站点域名 | `https://wuyouwulv.me` |
|
||||||
- `DEPLOY_SSH_USER`
|
|
||||||
- `DEPLOY_PATH`
|
|
||||||
- `DEPLOY_SSH_KEY` (private key)
|
|
||||||
|
|
||||||
## Example Caddyfile
|
## 一次性服务器配置
|
||||||
|
|
||||||
See `deploy/Caddyfile.example`.
|
1. 创建部署目录:
|
||||||
|
```bash
|
||||||
|
mkdir -p /var/www/publish
|
||||||
|
```
|
||||||
|
|
||||||
|
2. 配置 Caddy(参考 `Caddyfile.example`):
|
||||||
|
```bash
|
||||||
|
sudo vim /etc/caddy/Caddyfile
|
||||||
|
sudo systemctl reload caddy
|
||||||
|
```
|
||||||
|
|
||||||
|
3. 确保服务器已安装 `tar`(用于解压部署包)
|
||||||
|
|
||||||
|
## Gitea Actions 配置
|
||||||
|
|
||||||
|
### 仓库变量(vars)
|
||||||
|
|
||||||
|
在仓库设置 → Actions → Variables 中配置:
|
||||||
|
|
||||||
|
| 变量名 | 值 | 说明 |
|
||||||
|
|--------|-----|------|
|
||||||
|
| `SITE_URL` | `https://wuyouwulv.me` | 站点 URL,用于 Astro 构建 |
|
||||||
|
| `DEPLOY_SSH_HOST` | `45.32.105.53` | 服务器 IP |
|
||||||
|
| `DEPLOY_SSH_PORT` | `22` | SSH 端口 |
|
||||||
|
| `DEPLOY_SSH_USER` | `root` | SSH 用户名 |
|
||||||
|
| `DEPLOY_PATH` | `/var/www/publish` | 部署目录 |
|
||||||
|
| `WEBHOOK_URL` | 飞书 Webhook URL | 部署通知(可选) |
|
||||||
|
|
||||||
|
### 仓库密钥(secrets)
|
||||||
|
|
||||||
|
在仓库设置 → Actions → Secrets 中配置:
|
||||||
|
|
||||||
|
| 密钥名 | 说明 |
|
||||||
|
|--------|------|
|
||||||
|
| `DEPLOY_SSH_PASSWORD` | SSH 登录密码 |
|
||||||
|
|
||||||
|
### 通过 API 配置变量
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 设置变量
|
||||||
|
curl -X POST -H "Authorization: token YOUR_TOKEN" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{"data":"VALUE","value":"VALUE"}' \
|
||||||
|
"https://gitea.refining.dev/api/v1/repos/OWNER/REPO/actions/variables/VAR_NAME"
|
||||||
|
|
||||||
|
# 设置密钥
|
||||||
|
curl -X PUT -H "Authorization: token YOUR_TOKEN" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{"data":"SECRET_VALUE"}' \
|
||||||
|
"https://gitea.refining.dev/api/v1/repos/OWNER/REPO/actions/secrets/SECRET_NAME"
|
||||||
|
```
|
||||||
|
|
||||||
|
## 部署流程
|
||||||
|
|
||||||
|
1. **Checkout** - 检出代码
|
||||||
|
2. **Setup Node** - 安装 Node.js 20
|
||||||
|
3. **Cache npm** - 缓存 npm 依赖(使用 `actions/cache@v3`)
|
||||||
|
4. **Install** - `npm ci` 安装依赖
|
||||||
|
5. **Build** - `npm run build` 构建站点
|
||||||
|
6. **Install sshpass** - 安装 SSH 密码认证工具
|
||||||
|
7. **Add known_hosts** - 添加服务器到已知主机
|
||||||
|
8. **Deploy** - 通过 tar + SSH 部署到服务器
|
||||||
|
9. **通知** - 发送飞书通知(成功/失败)
|
||||||
|
|
||||||
|
## 手动部署
|
||||||
|
|
||||||
|
如需手动部署,可以在本地执行:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 构建
|
||||||
|
npm run build
|
||||||
|
|
||||||
|
# 部署(需要 sshpass)
|
||||||
|
tar -C dist -czf - . | \
|
||||||
|
sshpass -p 'PASSWORD' ssh -p 22 root@45.32.105.53 \
|
||||||
|
"set -euo pipefail; tmp='/var/www/publish.tmp'; rm -rf \"\$tmp\"; mkdir -p \"\$tmp\"; tar -xzf - -C \"\$tmp\"; rm -rf '/var/www/publish'; mv \"\$tmp\" '/var/www/publish'"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Caddy 配置示例
|
||||||
|
|
||||||
|
参考 `Caddyfile.example` 文件。
|
||||||
|
|
||||||
|
## 故障排查
|
||||||
|
|
||||||
|
### 构建失败:Invalid url
|
||||||
|
|
||||||
|
检查 `SITE_URL` 变量是否包含完整的 URL(包括 `https://` 前缀)。
|
||||||
|
|
||||||
|
### 部署失败:SSH 连接问题
|
||||||
|
|
||||||
|
1. 检查 `DEPLOY_SSH_PASSWORD` 密钥是否正确
|
||||||
|
2. 检查服务器 IP 和端口是否正确
|
||||||
|
3. 检查服务器是否允许密码登录
|
||||||
|
|
||||||
|
### 变量在 UI 中不显示
|
||||||
|
|
||||||
|
Gitea UI 可能有显示问题,可以通过 API 验证变量是否存在:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -s -H "Authorization: token YOUR_TOKEN" \
|
||||||
|
"https://gitea.refining.dev/api/v1/repos/OWNER/REPO/actions/variables" | jq .
|
||||||
|
```
|
||||||
|
|||||||
@@ -51,12 +51,25 @@ const hasContent = Astro.slots.has('default');
|
|||||||
if (!card) return;
|
if (!card) return;
|
||||||
|
|
||||||
const content = card.querySelector('[data-content]') as HTMLElement;
|
const content = card.querySelector('[data-content]') as HTMLElement;
|
||||||
|
const contentInner = content?.querySelector('.content-inner') as HTMLElement;
|
||||||
const fade = card.querySelector('[data-fade]') as HTMLElement;
|
const fade = card.querySelector('[data-fade]') as HTMLElement;
|
||||||
const btn = card.querySelector('[data-expand-btn]') as HTMLButtonElement;
|
const btn = card.querySelector('[data-expand-btn]') as HTMLButtonElement;
|
||||||
const text = btn?.querySelector('[data-expand-text]');
|
const text = btn?.querySelector('[data-expand-text]');
|
||||||
const icon = btn?.querySelector('[data-expand-icon]') as SVGElement;
|
const icon = btn?.querySelector('[data-expand-icon]') as SVGElement;
|
||||||
|
|
||||||
if (!content || !btn || !text || !icon) return;
|
if (!content || !contentInner || !btn || !text || !icon) return;
|
||||||
|
|
||||||
|
// 检查内容实际高度是否超过最大高度
|
||||||
|
const maxHeight = 800;
|
||||||
|
const actualHeight = contentInner.scrollHeight;
|
||||||
|
|
||||||
|
// 如果内容不超过最大高度,隐藏展开按钮和渐变效果
|
||||||
|
if (actualHeight <= maxHeight) {
|
||||||
|
content.style.maxHeight = 'none';
|
||||||
|
if (fade) fade.style.display = 'none';
|
||||||
|
btn.style.display = 'none';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let isExpanded = false;
|
let isExpanded = false;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user