PVQ-UI
v1.2.10
Gitee

文档

PVQ-UI 的开发方案、项目规则、组件清单与调用方法。文档为代码唯一真源,本页直接渲染仓库中的真实 Markdown。

部署方案

PVQ-UI 部署方案(腾讯云 COS)

唯一真源:本文件。配置/脚本变更须先更新本文件再改代码。 关联:《PVQ-UI组件库开发方案.md》§3(产物 CDN 单一源)、《PVQ-UI组件库调用手册.md》。

1. 目标

组件库产物(CSS/JS)通过 coscli(腾讯云官方命令行)一键部署到腾讯云 COS;各插件经 pvq-ui-loader.php 以固定 URL 调用:

https://cdn-buke.pvq.ink/pvq-ui/v{ver}/pvq-ui.css

版本号隔离在路径中,旧版本保留不删,调用方显式锁版本(见《调用手册》§2)。

2. 前置条件

  • 安装 cosclihttps://cloud.tencent.com/document/product/436/63144
    • macOS:brew install coscli
    • 其他平台:下载官方二进制并加入 PATH
  • 腾讯云账号 + 已建存储桶(如 pvq-ui-125xxxxxxx
  • 将自定义域名 cdn-buke.pvq.ink 绑定到该桶的 CDN 加速域名(未绑定时见 §6 临时方案)

3. 配置文件

3.1 cos.config.example.json(入库模板)

真实文件 cos.config.json 不入库.gitignore 已忽略),本地复制后填入。

{
  "secretId":     "YOUR_SECRET_ID",
  "secretKey":    "YOUR_SECRET_KEY",
  "bucket":       "pvq-ui-125xxxxxxx",
  "region":       "ap-guangzhou",
  "customDomain": "https://cdn-buke.pvq.ink",
  "localDir":     "assets",
  "remotePrefix": "pvq-ui",
  "cacheControl": "max-age=31536000, immutable"
}
字段 说明
secretId / secretKey 腾讯云 API 密钥(仅本地,绝不入库)
bucket 存储桶名(含 APPID,如 pvq-ui-125xxxxxxx
region 地域,如 ap-guangzhou
customDomain 绑定的自定义域名,用于自检与 loader 默认 URL
localDir 本地产物目录,默认 assets
remotePrefix COS 内前缀,默认 pvq-ui
cacheControl 上传时设置的 Cache-Control 响应头

3.2 coscli 认证(独立于仓库)

coscli~/.cos.yaml(由 coscli config 生成,含 secretId/secretKey/buckets/region)。deploy.sh 不传任何密钥,只调用 coscli,密钥安全由 coscli 本地配置承担,与仓库解耦。

4. 部署流程

cp cos.config.example.json cos.config.json   # 填入真实 bucket / region / 密钥
coscli config                                # 按提示生成 ~/.cos.yaml
./scripts/deploy.sh                          # 自动读取 assets/css/pvq-ui.css 的 @version 部署
./scripts/deploy.sh 1.1.3                    # 或显式指定版本号

脚本步骤:校验 cosclicos.config.json → 读取版本号 → coscli sync assets/ cos://{bucket}/{prefix}/v{ver}/ --meta "Cache-Control: {cacheControl}"curl 自检自定义域名 URL 返回 200。

依赖:本地需有 php CLI(用于解析 JSON 与读取 @version)。

5. COS 存储结构 ↔ loader URL

cos://pvq-ui-125xxxxxxx/pvq-ui/v1.1.2/
  ├─ pvq-ui.css
  ├─ pvq-ui-admin.css
  ├─ pvq-ui-editor.css
  ├─ pvq-ui-frontend.css
  ├─ pvq-ui.js
  └─ components.json        # 组件清单机器可读唯一真源(§3.5),随库同版本发布

components.json 与库 CSS/JS 同目录同版本,官网画廊(site/inc/gallery.php)线上运行时读它,库一升级发布,画廊自动跟随多组件、变稳定性标签(详见《组件库开发方案》§3.5)。 对应 loader 默认 URL(CDN_BASE = https://cdn-buke.pvq.ink/pvq-ui,按 v{ver}/ 拼接): https://cdn-buke.pvq.ink/pvq-ui/v1.1.2/pvq-ui.css 等。

6. 调用方式

require_once 'pvq-ui-loader.php';
PVQ_UI_Loader::enqueue( array( 'admin' ), '1.1.2' );

自定义域名尚未绑定到 COS 时,站点可用常量覆盖为 COS 默认访问域名:

define( 'PVQ_UI_URL',        'https://pvq-ui-125xxxxxxx.cos.ap-guangzhou.myqcloud.com/pvq-ui/v1.1.2/pvq-ui.css' );
define( 'PVQ_UI_ADMIN_URL',  'https://pvq-ui-125xxxxxxx.cos.ap-guangzhou.myqcloud.com/pvq-ui/v1.1.2/pvq-ui-admin.css' );
define( 'PVQ_UI_EDITOR_URL', 'https://pvq-ui-125xxxxxxx.cos.ap-guangzhou.myqcloud.com/pvq-ui/v1.1.2/pvq-ui-editor.css' );
define( 'PVQ_UI_FRONT_URL',  'https://pvq-ui-125xxxxxxx.cos.ap-guangzhou.myqcloud.com/pvq-ui/v1.1.2/pvq-ui-frontend.css' );
define( 'PVQ_UI_JS_URL',     'https://pvq-ui-125xxxxxxx.cos.ap-guangzhou.myqcloud.com/pvq-ui/v1.1.2/pvq-ui.js' );

7. 缓存策略

上传即设 Cache-Control: max-age=31536000, immutable。版本号已在路径中,更新即换路径,旧 URL 永久有效,长缓存零风险。

8. 安全

  • cos.config.json(真实密钥)与 ~/.cos.yaml不入库;仅 cos.config.example.json 入库。
  • 严禁将 SecretId / SecretKey 提交到任何仓库或文档。
  • 本仓库 .gitignore 已忽略 cos.config.json.cos.yaml、本地临时文件。

9. 多版本共存与回滚

每次 deploy 上传到独立 v{ver}/ 目录,旧版本保留。回滚只需调用方把 enqueue 的版本号改回旧版,COS 上无需删除旧目录。

10. 本方案不 bump 库产物版本

本次新增的是部署工具链(配置 + 脚本 + 文档),CSS/JS 产物内容未变,不提升库版本号;仅在 readme.md 增加「部署」段、CHANGELOG.md 补一条部署工具记录。

11. 官网部署(FTP → pvq-ui.pvq.ink)

官网是库的对外门面:展示全部组件、说明与调用方法,位于仓库 site/。采用 PHP 动态渲染 doc/ 下的 Markdown(文档为单一真源,改一处网站自动同步),组件资源直接引用 COS CDN(cdn-buke.pvq.ink),不另存一份。

目标主机为 PHP 虚拟主机,部署走 FTP:

cp ftp.config.example.json ftp.config.json   # 填入真实 FTP 信息(host/user/pass/remoteDir…)
php scripts/deploy-ftp.php                    # PHP 原生 ftp 扩展,镜像 site/ + doc/ 到 remoteDir

脚本行为:

  1. ftp.config.json(真实文件,不入库)→ 连接(优先 FTPS ftp_ssl_connect,失败回退普通 FTP)→ 被动模式。
  2. 递归上传 site/remoteDir,并把 doc/remoteDir/doc(官网实时渲染用)。
  3. site/lib/Parsedown.php(Markdown 解析器)随 site/ 一并上传。

安全与耦合:

  • 真实 ftp.config.json 含 FTP 密码,不入库.gitignore 已忽略),仅 ftp.config.example.json 入库。
  • 网站版本与库版本耦合:site/inc/config.phpPVQ_UI_VERSION 必须与当前库版本一致;升库版本时同步修改它,否则网站引用的 CDN 资源路径会失效。
  • 域名 pvq-ui.pvq.ink 的 web 根指向 remoteDir,访问 https://pvq-ui.pvq.ink/ 即官网首页。
  • 组件清单 JSON 双轨(与《组件库开发方案》§3.5 一致)components.json 位于 site/inc/,随 site/deploy-ftp.php 上传到 web 根;同时 deploy.sh 把它同步到 COS pvq-ui/v{ver}/components.json。官网画廊 gallery.php 本地开发时读仓库内 site/inc/components.json(改 JSON 刷新即见),线上运行时读 COS 同版本 JSON——新增组件只改 components.json,画廊自动出现,无需改 gallery.php
  • doc/ 必须随部署进入 web 根内的 doc/ 目录:线上 deploy-ftp.phpdoc/ 上传到 remoteDir/doc,与铺在 web 根的 site/ 程序同级;docs.php 探测 is_dir(__DIR__.'/doc') 为真 → 走「同级 doc」分支,不越级访问。这是线上唯一正确形态,切勿让 docs.php 走到 ../doc 分支。

11.1 本地预览与 open_basedir 约束

docs.php 的文档根探测(site/docs.php:8):

$docBase = is_dir(__DIR__ . '/doc') ? __DIR__ . '/doc' : __DIR__ . '/../doc';
  • 线上(web 根 = remoteDirsite/ 内容铺在 web 根,doc/web根/doc):__DIR__.'/doc' 存在 → 走前半段,安全。
  • 本地直接把 site/ 当 web 根跑(宝塔建站 / 本地 nginx 根指向 site/):若主机对站点设 open_basedir 锁到 site/(+ /tmp),则仓库根 doc/(在 site/ 之外)不会被纳入 → docs.php 走到 ../doc 分支 → is_file()open_basedir 拦截,报 Warning: is_file(): open_basedir restriction in effect … 并落到「文档未找到」。

方案 A(推荐,贴合线上架构):让 site/doc 存在即可,不动环境安全配置。

  • 本地执行:cp -r doc site/doc真实复制,不可用软链——open_basedir 会解析软链真实路径,仍判越界)。
  • site/doc/ 加入 .gitignore:仓库根的 doc/ 才是单一真源,site/doc 仅本地预览派生产物,不得入库。
  • 之后 docs.php 探测 is_dir(__DIR__.'/doc') 为真,warning 消失、文档正常渲染。
  • 改了仓库根 doc/ 后需重新 cp -r doc site/doc 才反映到本地预览(线上由 deploy-ftp.php 自动同步,无需手动)。
  • 备选方案 B(不推荐):放宽 open_basedir 把仓库根纳入。代价是削弱站点安全隔离,仅为迁就代码,非长久之计。