初始化
This commit is contained in:
@@ -0,0 +1,12 @@
|
||||
---
|
||||
description: 用户要求 git commit、提交代码、写 commit message 或创建提交时,必须先加载 commit-convention skill 并严格遵守
|
||||
alwaysApply: false
|
||||
---
|
||||
|
||||
# Git 提交规范自动激活
|
||||
|
||||
当用户要求**提交代码**、**git commit**、**写提交说明**或执行提交流程时:
|
||||
|
||||
1. 必须先加载 `.cursor/skills/commit-convention/SKILL.md`。
|
||||
2. Agent 代提交时 subject **必须**以 `[Ai]` 开头,并写清业务变更或 Bug 修复,禁止敷衍 subject。
|
||||
3. 未获用户明确授权不得 commit;不得提交 `.env` 等含密钥文件;默认不 push。
|
||||
@@ -0,0 +1,42 @@
|
||||
---
|
||||
description: 项目通用规范,涵盖技术栈、目录结构、编码约定
|
||||
alwaysApply: true
|
||||
---
|
||||
|
||||
# 项目约定
|
||||
|
||||
## 技术栈
|
||||
|
||||
- **框架**: Vue 2 + Vue CLI 4
|
||||
- **路由**: Vue Router 3 (history 模式)
|
||||
- **状态管理**: Vuex 3
|
||||
- **语言**: JavaScript (无 TypeScript)
|
||||
- **UI 库**: Element UI + Vant 2
|
||||
- **样式**: SCSS + scoped + PostCSS px2rem (rootValue: 37.5)
|
||||
- **移动端适配**: lib-flexible + postcss-plugin-px2rem
|
||||
- **HTTP**: Axios
|
||||
|
||||
## 目录结构
|
||||
|
||||
```
|
||||
src/
|
||||
├── api/ # API 请求模块
|
||||
├── assets/ # 静态资源 (图片、样式)
|
||||
├── plugins/ # 插件 (Element UI、flexible 等)
|
||||
├── router/ # 路由配置
|
||||
├── store/ # Vuex store
|
||||
├── utils/ # 工具函数
|
||||
├── views/ # 页面视图
|
||||
│ └── land/ # 落地页
|
||||
│ ├── index.vue # 主入口,根据设备/模板切换组件
|
||||
│ └── components/ # 落地页子组件 (mobile1, pc2 等)
|
||||
```
|
||||
|
||||
## 编码规范
|
||||
|
||||
- 使用 ES6+ 语法,Options API 风格
|
||||
- 组件通过 props 接收 `os`、`configs`、`switchData` 等父级数据
|
||||
- 事件通过 `$emit` 向上传递 (`recordClick`、`getApkInfo`)
|
||||
- 图片资源使用相对路径引用,放在 `assets/images/` 对应子目录下
|
||||
- px 值会被 PostCSS 自动转为 rem,带 `pcm` 选择器前缀的除外
|
||||
- 始终用中文回复
|
||||
@@ -0,0 +1,73 @@
|
||||
---
|
||||
description: SCSS 样式编写规范,包含移动端适配和 px2rem 规则
|
||||
globs: "**/*.vue,**/*.scss"
|
||||
alwaysApply: false
|
||||
---
|
||||
|
||||
# SCSS 样式规范
|
||||
|
||||
## px2rem 适配
|
||||
|
||||
- 项目使用 `postcss-plugin-px2rem`,rootValue 为 **37.5**
|
||||
- 设计稿以 **375px** 宽度为基准,直接写 px 值即可自动转换
|
||||
- 带 `pcm` 选择器前缀的样式**不会**被转换 (PC 端样式)
|
||||
|
||||
## 样式写法
|
||||
|
||||
- 使用 `<style lang="scss" scoped>` 保证组件样式隔离
|
||||
- 深层覆盖 Vant 组件样式使用 `::v-deep`:
|
||||
|
||||
```scss
|
||||
::v-deep .van-tabs__wrap {
|
||||
.van-tab--active {
|
||||
background: #f68804;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 常用模式
|
||||
|
||||
### 全屏背景图
|
||||
|
||||
```scss
|
||||
.contentBlock {
|
||||
height: 940px;
|
||||
width: 343px;
|
||||
background: url("./../../../assets/images/{template}/content.webp") no-repeat;
|
||||
background-size: 100% 100%;
|
||||
}
|
||||
```
|
||||
|
||||
### 固定定位浮层
|
||||
|
||||
```scss
|
||||
.floatingBox {
|
||||
position: fixed;
|
||||
right: 0;
|
||||
top: 187px;
|
||||
z-index: 998;
|
||||
}
|
||||
```
|
||||
|
||||
### 下载按钮
|
||||
|
||||
```scss
|
||||
.downBtn {
|
||||
border-radius: 24px;
|
||||
background: #ff6f2e;
|
||||
color: #fff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
```
|
||||
|
||||
## 颜色常量 (项目常用)
|
||||
|
||||
| 用途 | 色值 |
|
||||
|------|------|
|
||||
| 页面背景 | `#141414` |
|
||||
| 主按钮 | `#ff6f2e` / `#f68804` |
|
||||
| Tab 背景 | `#2d2c2f` |
|
||||
| 弹窗按钮 | `#5b92ee` |
|
||||
| 文字白色 | `#ffffff` |
|
||||
@@ -0,0 +1,72 @@
|
||||
---
|
||||
description: Vue 组件开发规范,适用于落地页组件
|
||||
globs: "**/*.vue"
|
||||
alwaysApply: false
|
||||
---
|
||||
|
||||
# Vue 组件规范
|
||||
|
||||
## 组件结构
|
||||
|
||||
遵循 `<template>` → `<script>` → `<style>` 顺序:
|
||||
|
||||
```vue
|
||||
<template>
|
||||
<div class="pageName">
|
||||
<!-- 内容 -->
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: ["os", "configs", "switchData"],
|
||||
data() {
|
||||
return {};
|
||||
},
|
||||
watch: {},
|
||||
mounted() {},
|
||||
methods: {},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.pageName {
|
||||
/* 样式 */
|
||||
}
|
||||
</style>
|
||||
```
|
||||
|
||||
## 命名约定
|
||||
|
||||
- 文件名: 小写或 camelCase (`mobile1.vue`, `selectLinePopup.vue`)
|
||||
- 新落地页模板: `mobile{N}.vue` (移动端) / `pc{N}.vue` (PC 端)
|
||||
- CSS 类名: camelCase (`headerBox`, `floatingBox`, `bottomBox`)
|
||||
- 事件名: camelCase (`getApkInfo`, `recordClick`)
|
||||
|
||||
## Props 通信
|
||||
|
||||
落地页组件接收三个核心 props:
|
||||
|
||||
| Prop | 说明 |
|
||||
|------|------|
|
||||
| `os` | 设备信息 (isPhone, userAgent 等) |
|
||||
| `configs` | 配置列表 (tg_group, potato_group 等) |
|
||||
| `switchData` | 开关数据 (下载链接、功能开关) |
|
||||
|
||||
## 事件追踪
|
||||
|
||||
使用 `landingPageClick` 上报用户点击行为,传入 tab 和坐标:
|
||||
|
||||
```js
|
||||
import { landingPageClick } from "@/utils/eventTracker";
|
||||
landingPageClick(this, { tab_key, tab_name, click_coordinates_x, click_coordinates_y });
|
||||
```
|
||||
|
||||
## 图片资源引用
|
||||
|
||||
图片放在 `src/assets/images/{templateName}/` 下,在 SCSS 中通过相对路径引用:
|
||||
|
||||
```scss
|
||||
background: url("./../../../assets/images/mobile1/logo.png") no-repeat;
|
||||
background-size: 100% 100%;
|
||||
```
|
||||
@@ -0,0 +1,97 @@
|
||||
---
|
||||
name: commit-convention
|
||||
description: 为本仓库生成符合团队规范的 Git 提交信息,并在用户要求提交代码时执行完整提交流程。用于 git commit、提交代码、写 commit message、创建提交、push 前整理提交等场景;Agent 代提交时必须使用 [Ai] 标记并写清业务变更。
|
||||
---
|
||||
|
||||
# Git 提交规范(Agent 代提交)
|
||||
|
||||
## 触发条件
|
||||
|
||||
满足任一条件,**必须先加载本 skill**,再执行 `git add` / `git commit`:
|
||||
|
||||
- 用户明确要求:提交、commit、git commit、保存提交、push 前先 commit 等
|
||||
- 用户规则中的「committing-changes-with-git」流程已启动
|
||||
|
||||
**未获用户明确授权时,不得执行 commit。**
|
||||
|
||||
---
|
||||
|
||||
## Agent 代提交:标记规则(强制)
|
||||
|
||||
由 Cursor Agent 发起的提交,**必须**在 subject 前加 `[Ai]`:
|
||||
|
||||
```text
|
||||
[Ai] <type>(<scope>): <subject>
|
||||
|
||||
<body 可选:业务背景、影响范围、关联 Bug>
|
||||
```
|
||||
|
||||
- `type`:`feat` | `fix` | `refactor` | `style` | `perf` | `chore` | `docs` | `test` | `build` | `ci`
|
||||
- `scope`:模块/页面,如 `benefits`、`mine`、`community`、`player`
|
||||
- 可在正文末尾追加 trailer(可选):
|
||||
|
||||
```text
|
||||
Co-Authored-By: Cursor <noreply@cursor.com>
|
||||
```
|
||||
|
||||
用户本人手动提交、且明确说明「人工提交」时,建议使用 `[Human]`;Agent **不要**替用户假标 `[Human]`。
|
||||
|
||||
---
|
||||
|
||||
## Subject 质量(强制)
|
||||
|
||||
提交说明必须让人一眼看懂**改了什么业务**或**修了什么问题**。
|
||||
|
||||
### 必须做到
|
||||
|
||||
1. 先并行执行:`git status`、`git diff`(含 staged)、`git log -5 --oneline` 了解风格与变更范围
|
||||
2. subject 用**完整语义**描述,优先中文;可中英混用 scope
|
||||
3. 多文件、多模块时:一条 commit 只包同一业务目标;若混杂无关改动,先询问是否拆分
|
||||
4. body 写:原因、用户可见变化、风险点(如有)
|
||||
|
||||
### 严禁(subject 不得仅为或等同于)
|
||||
|
||||
`test`、`修改`、`update`、`fix`、`xxx`、`111`、`wip`、`temp`、`提交`、`save`、纯标点、纯数字、单字
|
||||
|
||||
### 示例
|
||||
|
||||
```text
|
||||
# ✅
|
||||
[Ai] feat(benefits): 新增七日签到弹窗与连续签到奖励展示
|
||||
[Ai] fix(player): 修复横屏切换后 HLS 首帧黑屏
|
||||
[Ai] refactor(mine): 签到任务列表抽离 useSignTask composable
|
||||
|
||||
# ❌
|
||||
[Ai] fix: 修改
|
||||
[Ai] feat: test
|
||||
修改播放器
|
||||
111
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 提交流程(与 user rule 对齐)
|
||||
|
||||
1. `git status` + `git diff` + `git log`(可并行)
|
||||
2. 根据 diff **撰写**符合本规范的 message(HEREDOC 传 `-m`)
|
||||
3. 只 `git add` 与本次任务相关的文件
|
||||
4. **不得**提交 `.env`、密钥、凭据类文件;若用户在 staged 中含此类文件,警告并排除
|
||||
5. `git commit` 后 `git status` 确认成功
|
||||
6. hook 失败时:**不要** `commit --amend`,修 message 后**新建 commit**
|
||||
7. **除非用户明确要求,否则不 `git push`**
|
||||
|
||||
---
|
||||
|
||||
## 输出给用户
|
||||
|
||||
提交完成后简要说明:
|
||||
|
||||
- commit hash(若有)
|
||||
- 本次纳入的文件范围
|
||||
- message 摘要(一行)
|
||||
|
||||
---
|
||||
|
||||
## 与本地 Hook / CI 的关系
|
||||
|
||||
本 skill 约束 **Agent 行为**。若仓库后续接入 `husky` + `commitlint` 或 CI,以仓库脚本校验为准;Agent 仍须预先满足 `[Ai]` 与 subject 质量,避免 hook 拒绝。
|
||||
@@ -0,0 +1,196 @@
|
||||
---
|
||||
name: figma-to-landpage
|
||||
description: 将 Figma 设计稿转换为 Vue 2 落地页组件。当用户提供 Figma 链接并要求生成落地页、实现设计稿、创建新模板时触发。适用于移动端和 PC 端落地页开发。
|
||||
---
|
||||
|
||||
# Figma 转落地页
|
||||
|
||||
将 Figma 设计稿翻译为本项目的 Vue 2 落地页组件,保持视觉还原度。
|
||||
|
||||
## 工作流程
|
||||
|
||||
### 第 1 步: 获取设计稿信息
|
||||
|
||||
从 Figma URL 中提取 `fileKey` 和 `nodeId`:
|
||||
- URL 格式: `https://figma.com/design/:fileKey/:fileName?node-id=1-2`
|
||||
- 将 `node-id` 中的 `-` 转为 `:`
|
||||
|
||||
依次调用:
|
||||
1. `get_design_context(fileKey, nodeId)` — 获取布局、颜色、字体等结构化数据
|
||||
2. `get_screenshot(fileKey, nodeId)` — 获取视觉截图作为还原参考
|
||||
|
||||
如果设计太复杂导致返回截断:
|
||||
1. 先调 `get_metadata(fileKey, nodeId)` 获取节点树
|
||||
2. 对各子节点分别调 `get_design_context`
|
||||
|
||||
### 第 2 步: 确定模板编号
|
||||
|
||||
查看 `src/views/land/components/` 下已有的模板文件:
|
||||
- 移动端: `mobile1.vue`, `mobile2.vue`, ...
|
||||
- PC 端: `pc1.vue`, `pc2.vue`, ...
|
||||
|
||||
新模板使用下一个序号。
|
||||
|
||||
### 第 3 步: 下载资源
|
||||
|
||||
将设计稿中的图片、图标导出并放入:
|
||||
```
|
||||
src/assets/images/{templateName}/
|
||||
```
|
||||
|
||||
例如 `mobile3` 模板的资源放在 `src/assets/images/mobile3/`。
|
||||
|
||||
Figma MCP 返回的 localhost 资源链接可直接下载使用。
|
||||
|
||||
### 第 4 步: 创建组件文件
|
||||
|
||||
在 `src/views/land/components/` 下创建新的 `.vue` 文件。
|
||||
|
||||
**必须遵循的组件结构:**
|
||||
|
||||
```vue
|
||||
<template>
|
||||
<div class="mobilePage" @click="pageClick">
|
||||
<!-- 顶部固定区域 -->
|
||||
<div class="headerBox" @click.stop="getApkInfo(os.isPhone && switchData.shopIosDownUrl ? 'shopIos' : true, $event)">
|
||||
<div class="header-bg"></div>
|
||||
</div>
|
||||
|
||||
<!-- 主体内容区 -->
|
||||
<div class="main">
|
||||
<!-- Figma 设计内容转换到这里 -->
|
||||
</div>
|
||||
|
||||
<!-- 社交浮窗 -->
|
||||
<div class="floatingBox" v-if="configs && configs.length">
|
||||
<div class="telegram" v-if="cTg" @click="jumpUrl(cTg)"></div>
|
||||
<div class="potato" v-if="cPotato" @click="jumpUrl(cPotato)"></div>
|
||||
<div class="business" v-if="cBusiness" @click="jumpUrl(cBusiness)"></div>
|
||||
<div class="channel" v-if="cChannel" @click="jumpUrl(cChannel)"></div>
|
||||
</div>
|
||||
|
||||
<!-- 下载按钮区 -->
|
||||
<div class="bottomBox" @click.stop="getApkInfo(true, $event)"></div>
|
||||
|
||||
<!-- 安卓/iOS 提示弹窗 -->
|
||||
<van-overlay :show="androidPromptShow" z-index="999" class="androidOverlay">
|
||||
<!-- ... -->
|
||||
</van-overlay>
|
||||
<van-overlay :show="iosPromptShow" z-index="999" class="iosOverlay">
|
||||
<!-- ... -->
|
||||
</van-overlay>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { landingPageClick } from "@/utils/eventTracker";
|
||||
export default {
|
||||
props: ["os", "configs", "switchData"],
|
||||
data() {
|
||||
return {
|
||||
androidPromptShow: false,
|
||||
iosPromptShow: false,
|
||||
showTip: false,
|
||||
currUrl: window.location.href,
|
||||
cTg: "",
|
||||
cPotato: "",
|
||||
cBusiness: "",
|
||||
cChannel: "",
|
||||
showIosTip: true,
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
configs(configs) {
|
||||
configs.forEach((item) => {
|
||||
if (item.configType === "tg_group") this.cTg = item.link;
|
||||
else if (item.configType === "potato_group") this.cPotato = item.link;
|
||||
else if (item.configType === "sw_cooperate") this.cBusiness = item.link;
|
||||
else if (item.configType === "qd_cooperate") this.cChannel = item.link;
|
||||
});
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
pageClick(event) {
|
||||
landingPageClick(this, {
|
||||
tab_key: "main",
|
||||
tab_name: "主页",
|
||||
click_coordinates_x: event.clientX,
|
||||
click_coordinates_y: event.clientY,
|
||||
});
|
||||
},
|
||||
doCopy() {
|
||||
this.$copyText(this.currUrl).then(() => { this.showTip = false; });
|
||||
},
|
||||
async showInstallTutorial(type) {
|
||||
if (type === "ios") this.iosPromptShow = true;
|
||||
else this.androidPromptShow = true;
|
||||
},
|
||||
async getApkInfo(flag, event) {
|
||||
let type = this.os.isPhone ? "ios" : "android";
|
||||
if (flag === "shopIos") type = "shopIos";
|
||||
if (flag === "androidSpare") type = "androidSpare";
|
||||
if (flag && flag !== "shopIos") await this.showInstallTutorial(type);
|
||||
this.$emit("recordClick", type);
|
||||
setTimeout(() => { this.$emit("getApkInfo", type); }, 500);
|
||||
landingPageClick(this, {
|
||||
tab_name: "下载按钮",
|
||||
tab_key: "download",
|
||||
click_coordinates_x: event.clientX,
|
||||
click_coordinates_y: event.clientY,
|
||||
});
|
||||
},
|
||||
jumpUrl(url) { window.open(url); },
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
/* 样式使用 SCSS + scoped,px 值基于 375 设计稿 */
|
||||
</style>
|
||||
```
|
||||
|
||||
### 第 5 步: 样式转换要点
|
||||
|
||||
将 Figma 设计数据转为 SCSS 时注意:
|
||||
|
||||
1. **尺寸**: 基于 375px 设计稿直接写 px,px2rem 自动转换
|
||||
2. **颜色**: 使用 Figma 给出的精确色值
|
||||
3. **图片**: 大面积背景用 webp 格式,图标用 png
|
||||
4. **字体**: Figma 字体映射到系统字体栈
|
||||
5. **布局**: 优先 Flex 布局,配合 `position: fixed` 实现吸顶/吸底
|
||||
6. **Vant 组件覆写**: 使用 `::v-deep` 覆盖 Vant 默认样式
|
||||
7. **PC 端样式**: 选择器加 `pcm` 前缀以避免 px2rem 转换
|
||||
|
||||
### 第 6 步: 注册组件
|
||||
|
||||
在 `src/views/land/index.vue` 中导入并注册新模板:
|
||||
|
||||
```js
|
||||
import mobileN from "./components/mobileN";
|
||||
// 在 components 中注册
|
||||
```
|
||||
|
||||
并在模板切换逻辑中添加对应条件。
|
||||
|
||||
### 第 7 步: 验证
|
||||
|
||||
- [ ] 视觉与 Figma 截图对比一致
|
||||
- [ ] 移动端/PC 端分别测试
|
||||
- [ ] 下载按钮、社交链接、弹窗功能正常
|
||||
- [ ] 事件追踪正常上报
|
||||
- [ ] 图片资源加载无误
|
||||
|
||||
## Figma 到 Vue 映射参考
|
||||
|
||||
| Figma 属性 | Vue/SCSS 对应 |
|
||||
|------------|--------------|
|
||||
| Auto Layout (横向) | `display: flex` |
|
||||
| Auto Layout (纵向) | `display: flex; flex-direction: column` |
|
||||
| Fill 颜色 | `background-color: #xxx` |
|
||||
| 图片 Fill | `background: url("...") no-repeat; background-size: 100% 100%` |
|
||||
| 固定位置 | `position: fixed` |
|
||||
| 圆角 | `border-radius: Npx` |
|
||||
| 文字样式 | `font-size`, `font-weight`, `line-height`, `color` |
|
||||
| 阴影 | `box-shadow` |
|
||||
| 间距 (Gap) | `gap: Npx` 或 `margin`/`padding` |
|
||||
| 透明度 | `opacity` 或 `rgba()` |
|
||||
Reference in New Issue
Block a user