From 3b03f87a02458f719e2eb4bf112a13441b427d14 Mon Sep 17 00:00:00 2001
From: ‘chensiAb’ <‘chenchenco03@163.com’>
Date: Tue, 25 Mar 2025 13:54:34 +0800
Subject: [PATCH] Merge branch 'master' of ssh://dev.zhiheiot.com:29418/mob-components

---
 forms/textarea/CTextArea.vue                                     |    3 
 _cursor.ai/文档说明.md                                               |   47 
 _cursor.ai/plugins.doc/echarts.doc/CECharts.doc.md               |  138 ++
 _cursor.ai/prompts/创建一个请求.prompts.md                             |   79 +
 forms/checkbox/CCheckBox.vue                                     |    8 
 _cursor.ai/rules/type-surface.mdc                                |   43 
 _cursor.ai/rules/type-component.mdc                              |   57 
 _cursor.ai/layout.doc/description.doc/CDescription.doc.md        |  149 ++
 _cursor.ai/rules/type-pilot.mdc                                  |   47 
 _cursor.ai/plugins.doc/infiniteScroll.doc/CInfiniteScroll.doc.md |   91 +
 forms/datePicker/CDatePicker.vue                                 |    3 
 _cursor.ai/forms.doc/datePicker.doc/CDatePicker.doc.md           |   15 
 _cursor.ai/layout.doc/card.doc/CCard.doc.md                      |  134 ++
 forms/form/CForm.vue                                             |    5 
 forms/select/CSelect.vue                                         |    3 
 _cursor.ai/rules/all-dev-specification.mdc                       |  304 ++--
 _cursor.ai/rules/all-system-role.mdc                             |   21 
 _cursor.ai/link-rules.cmd                                        |   29 
 _cursor.ai/rules/fit-base-pilot.mdc                              |   28 
 _cursor.ai/forms.doc/imagePicker.doc/CImagePicker.doc.md         |   78 
 _cursor.ai/layout.doc/h5Page.doc/CH5Page.doc.md                  |  175 ++
 _cursor.ai/prompts/更新组件目录.prompts.md                             |   35 
 _cursor.ai/prompts/更新公共组件文档.prompts.md                           |   61 +
 _cursor.ai/工作共识.md                                               |  138 ++
 _cursor.ai/layout.doc/navCustomBar.doc/CNavCustomBar.doc.md      |   80 +
 _cursor.ai/layout.doc/drawer.doc/CDrawer.doc.md                  |  199 +++
 _cursor.ai/layout.doc/numerical.doc/CNumerical.doc.md            |  117 +
 _cursor.ai/plugins.doc/qrcode.doc/CQRCode.doc.md                 |   76 +
 forms/imagePicker/CImagePicker.vue                               |    3 
 _cursor.ai/forms.doc/input.doc/CInput.doc.md                     |    8 
 _cursor.ai/forms.doc/form.doc/CForm.doc.md                       |   18 
 _cursor.ai/plugins.doc/filter.doc/CFilter.doc.md                 |  132 ++
 _cursor.ai/layout.doc/homeNav.doc/CHomeNav.doc.md                |  127 ++
 _cursor.ai/rules/fit-base-fetcher.mdc                            |   66 
 _cursor.ai/forms.doc/numberStep.doc/CNumberStep.doc.md           |    4 
 forms/chinaArea/CChinaArea.vue                                   |    3 
 forms/numberValve/CNumberValve.vue                               |    5 
 _cursor.ai/forms.doc/select.doc/CSelect.doc.md                   |    4 
 _cursor.ai/forms.doc/chinaArea.doc/CChinaArea.doc.md             |   57 
 forms/numberStep/CNumberStep.vue                                 |    2 
 forms/userSignature/CSignatureLayer.vue                          |  182 +-
 _cursor.ai/layout.doc/alert.doc/CAlert.doc.md                    |  129 ++
 _cursor.ai/prompts/创建一个页面.prompts.md                             |   70 +
 forms/userSignature/cSignatureLayer.scss                         |    6 
 _cursor.ai/组件目录.md                                               |  176 ++
 forms/input/CInput.vue                                           |    2 
 _cursor.ai/rules/type-fetchers.mdc                               |   38 
 /dev/null                                                        |    0 
 _cursor.ai/layout.doc/waiting.doc/CWaiting.doc.md                |  107 +
 _cursor.ai/rules/all-project-info.mdc                            |  128 ++
 _cursor.ai/forms.doc/checkbox.doc/CCheckBox.doc.md               |   15 
 forms/switch/CSwitch.vue                                         |    3 
 _cursor.ai/common.doc/Tools.doc.md                               |    0 
 _cursor.ai/layout.doc/anchor.doc/CAnchor.doc.md                  |  150 ++
 54 files changed, 3,248 insertions(+), 350 deletions(-)

diff --git "a/_cursor.ai/101-\345\267\245\347\250\213\344\273\213\347\273\215.md" "b/_cursor.ai/101-\345\267\245\347\250\213\344\273\213\347\273\215.md"
deleted file mode 100644
index f1987f3..0000000
--- "a/_cursor.ai/101-\345\267\245\347\250\213\344\273\213\347\273\215.md"
+++ /dev/null
@@ -1,299 +0,0 @@
-# 工程介绍
-
-- [工程介绍](#工程介绍)
-  - [工程介绍](#工程介绍-1)
-  - [技术栈](#技术栈)
-  - [工程目录结构](#工程目录结构)
-    - [短路径映射](#短路径映射)
-  - [页面构成](#页面构成)
-    - [界面层和数据控制层的拆分](#界面层和数据控制层的拆分)
-  - [新页面模板](#新页面模板)
-    - [界面层空白模板](#界面层空白模板)
-      - [H5 空白界面模板](#h5-空白界面模板)
-      - [小程序空白界面模板](#小程序空白界面模板)
-      - [空白样式文件模板](#空白样式文件模板)
-    - [数据控制层空白模板](#数据控制层空白模板)
-      - [数据控制器空白模板](#数据控制器空白模板)
-      - [请求集空白模板](#请求集空白模板)
-
-## 工程介绍
-
-这是一套Web前端开发的工程文档,用于指导移动端(H5网页、混合App、小程序等)的开发
-
-## 技术栈
-
-- 语法框架:Vue(v2.5.0)
-- 工程框架:Taro(v3.2.13)
-- 显示框架:Taro-UI-Vue(v1.0.0-beta.10)
-- 样式:Sass
-
-说明:使用时,优先使用公共组件库的组件,其次是 Taro-UI-Vue 的组件,最后才是 Taro 本身的基础组件
-
-## 工程目录结构
-
-工程主要目录及其用途
-
-- root/(根目录)
-    - public/(静态资源目录)
-    - src/(开发源码目录)
-        - components/(公共资源目录)
-            - bases/(公共基类目录)
-            - common/(公共工具目录)
-            - forms/(公共表单组件目录)
-            - layout/(公共排版组件目录)
-            - plugins/(公共复杂组件目录)
-        - fetchers/(请求层目录)
-            - FName.js(请求集)
-        - pages/(界面层目录)
-            - pageGroup/(界面层分组目录)
-                - pageName/(界面层单页目录)
-                    - cmpt/(界面子组件目录)
-                        - CName.vue(子组件)
-                        - cName.scss(子组件样式)
-                    - page.vue(界面)
-                    - page.scss(界面样式)
-        - pilots/(数据控制层目录)
-            - _overall/(全局数据控制目录)
-            - pilotGroup/(数据控制层分组目录)
-                - mixin/(混合件目录)
-                    - MName.js(混合件)
-                - PName.js(数据控制器)
-
-### 短路径映射
-
-工程资源引用时,通常使用更短的引用路径:
-
-* `@components` 代表 `root/src/components`
-* `@fetchers` 代表 `root/src/fetchers`
-* `@pages` 代表 `root/src/pages`
-* `@pilots` 代表 `root/src/pilots`
-
-例如:'@components/layout/h5Page' 实际引用的是 'root/src/components/layout/h5Page'
-
-## 页面构成
-
-当我们说组件的时候,就是指普通 Vue 组件  
-
-当我们说业务页面的时候,则是由**界面层**和**数据控制层**两部分组成  
-同时页面层有子组件,数据层关联请求层,结构如下
-
-- 业务页面:
-    - 界面层(root/src/pages/pageGroup/pageName/page.vue)
-        - 界面子组件(root/src/pages/pageGroup/pageName/cmpt/CName.vue)
-    - 数据控制层(root/src/pilots/pilotsGroup/PName.js)
-        - 请求层(root/src/fetchers/FName.js)
-
-### 界面层和数据控制层的拆分
-
-一个业务页面的界面层和数据控制层,实际上是对一个 Vue 组件的拆分,最终运行的时候,还是会合二为一,还原成原本的 Vue 实例  
-因此,数据控制层其实是对这个 Vue 实例部分功能的一种转写,类似于语法糖
-
-**数据控制层写法**
-
-例如:
-
-```js
-// 数据控制器
-export class PIndex extends Pilot {
-    $data() {
-        return {
-            a: 1,
-        };
-    }
-    $computed = {
-        a2() {},
-    };
-    $mounted() {}
-    onOpenSelector() {}
-}
-```
-
-会转换成
-
-```js
-// 标准 Vue
-const Component = Vue.extend({
-    data() {
-        return {
-            a: 1,
-        };
-    },
-    computed: {
-        a2() {},
-    },
-    methods: {
-        onOpenSelector() {},
-    },
-    mounted() {},
-});
-```
-
-更多细节,请参照《数据控制层基类Pilot》
-
-## 新页面模板
-
-新建页面时,页面初始内容,可参考如下空白模板
-
-### 界面层空白模板
-
-#### H5 空白界面模板
-
-H5 界面需要 CPage、CContent、CNavBar 这三个基础页面组件
-
-```html
-/**
-* pageName - 页面名称
-* @author 作者
-*/
-
-<template>
-    <CPage>
-        <CNavBar title="页面名称" />
-        <CContent class="page-name">
-            <!-- 页面内容 -->
-        </CContent>
-    </CPage>
-</template>
-
-<script>
-    import Taro from '@tarojs/taro';
-    import {} from 'taro-ui-vue';
-    import {
-        PPageName
-    } from '@pilots/pilotGroup/PPageName';
-    import {
-        CPage,
-        CContent,
-        CNavBar
-    } from '@components/layout/h5Page';
-    import './pageName.scss';
-
-    export default {
-        name: 'PageName',
-        components: {},
-        ...new PPageName().createOptions(),
-    };
-</script>
-```
-
-#### 小程序空白界面模板
-
-```html
-/**
-* pageName - 页面名称
-* @author 作者
-*/
-
-<template>
-    <view class="page-name">
-        <!-- 页面内容 -->
-    </view>
-</template>
-
-<script>
-    import Taro from '@tarojs/taro';
-    import {} from 'taro-ui-vue';
-    import {
-        PPageName
-    } from '@pilots/pilotGroup/PPageName';
-    import './pageName.scss';
-
-    export default {
-        name: 'PageName',
-        components: {},
-        ...new PPageName().createOptions(),
-    };
-</script>
-```
-
-#### 空白样式文件模板
-
-```css
-/**
- * pageName - 页面名称
- * @author 作者
- */
-
-@import "../../../components/common/sassMixin";
-
-.page-name {}
-```
-
-### 数据控制层空白模板
-
-#### 数据控制器空白模板
-
-```js
-/**
- * PPageName - 页面名称
- * @author 作者
- */
-
-import Taro from '@tarojs/taro';
-import {
-    Pilot
-} from '@components/bases/Pilot';
-import {
-    $fetchCommon
-} from '@fetchers/FCommon';
-
-export class PPageName extends Pilot {
-
-    $data() {
-        return {};
-    }
-
-    $mounted() {
-        this.onLoadDataResource();
-    }
-
-    // 加载用户详情
-    onLoadDataResource() {
-        Taro.showLoading();
-        $fetchCommon.getPageDetail()
-            .then(res => {
-                Taro.hideLoading();
-                if (!res) {
-                    return;
-                }
-                // do something
-            });
-    }
-
-}
-```
-
-说明:请求异常由请求层的基类自动处理,数据控制层跳过错误的逻辑,只处理请求成功的后续业务
-
-#### 请求集空白模板
-
-```js
-/**
- * FCommon - 公用请求集
- * @author 作者
- */
-
-import {
-    Fetcher
-} from '@components/bases/Fetcher';
-
-class FCommon extends Fetcher {
-
-    constructor() {
-        super({
-            // url前缀(本地路径, 服务器路径)
-            urlPrefix: ['/api/common/', '/serverPath/'],
-        });
-    }
-
-    // 读取页面详情
-    getPageDetail() {
-        const url = this.spellURL('getPageDetail', 'page/Detail');
-        const send = {};
-        return this.post(url, send);
-    }
-
-}
-
-export const $fetchCommon = new FCommon();
-```
diff --git "a/_cursor.ai/301-\345\205\254\345\205\261\350\241\250\345\215\225\347\273\204\344\273\266.md" "b/_cursor.ai/301-\345\205\254\345\205\261\350\241\250\345\215\225\347\273\204\344\273\266.md"
deleted file mode 100644
index b040b7e..0000000
--- "a/_cursor.ai/301-\345\205\254\345\205\261\350\241\250\345\215\225\347\273\204\344\273\266.md"
+++ /dev/null
@@ -1,46 +0,0 @@
-# 公共表单组件
-
-- [公共表单组件](#公共表单组件)
-  - [组件列表](#组件列表)
-    - [表单容器组件](#表单容器组件)
-    - [基础输入组件](#基础输入组件)
-    - [选择组件](#选择组件)
-    - [开关组件](#开关组件)
-    - [数值组件](#数值组件)
-  - [表单项验证规则](#表单项验证规则)
-  - [完整表单示例](#完整表单示例)
-
-移动端表单组件库
-
-## 组件列表
-
-### 表单容器组件
-- [CForm 表单组件](./forms/CForm.md)
-- [CFormItem 表单项组件](./forms/CFormItem.md)
-- [CFormSubmit 表单提交按钮组件](./forms/CFormSubmit.md)
-- [CFormAgreement 表单协议组件](./forms/CFormAgreement.md)
-
-### 基础输入组件
-- [CInput 文本输入框组件](./forms/CInput.md)
-- [CInputPhoneCode 手机验证码输入框组件](./forms/CInputPhoneCode.md)
-- [CInputScanCode 扫码输入框组件](./forms/CInputScanCode.md)
-- [CInputExpressCode 快递单号输入框组件](./forms/CInputExpressCode.md)
-- [CTextArea 多行文本输入组件](./forms/CTextArea.md)
-
-### 选择组件
-- [CSelect 下拉选择组件](./forms/CSelect.md)
-- [CJumpSelect 跳转选择组件](./forms/CJumpSelect.md)
-- [CCheckBox 复选框组件](./forms/CCheckBox.md)
-- [CDatePicker 日期选择组件](./forms/CDatePicker.md)
-
-### 开关组件
-- [CSwitch 开关组件](./forms/CSwitch.md)
-- [CSwitchRadio 开关式单选组件](./forms/CSwitchRadio.md)
-
-### 数值组件
-- [CNumberStep 数字步进器组件](./forms/CNumberStep.md)
-- [CNumberValve 数值滑块组件](./forms/CNumberValve.md)
-
-## 表单项验证规则
-
-## 完整表单示例
\ No newline at end of file
diff --git "a/_cursor.ai/210-\345\205\254\345\205\261\345\267\245\345\205\267\347\256\261Tools.md" b/_cursor.ai/common.doc/Tools.doc.md
similarity index 100%
rename from "_cursor.ai/210-\345\205\254\345\205\261\345\267\245\345\205\267\347\256\261Tools.md"
rename to _cursor.ai/common.doc/Tools.doc.md
diff --git a/_cursor.ai/forms.doc/checkbox.doc/CCheckBox.doc.md b/_cursor.ai/forms.doc/checkbox.doc/CCheckBox.doc.md
index 1998ff2..dc8dac3 100644
--- a/_cursor.ai/forms.doc/checkbox.doc/CCheckBox.doc.md
+++ b/_cursor.ai/forms.doc/checkbox.doc/CCheckBox.doc.md
@@ -14,8 +14,12 @@
 
 - `itemRes` (Object,必填):表单数据资源对象,表单组件内部机制专用
 - `options` (Array,可选):选项列表,每个选项应包含 label 和 value 属性,默认为空数组
-- `boxType` (String,可选):勾选类型,可选值有 checkbox(多选)、radio(单选),默认为 checkbox
-- `displayType` (String,可选):显示模式,可选值有 plane(直接显示)、dialog(弹窗选择),默认为 plane
+- `boxType` (String,可选):勾选类型,默认为 checkbox
+    - `checkbox`:多选模式
+    - `radio`:单选模式
+- `displayType` (String,可选):显示模式,默认为 plane
+    - `plane`:直接显示模式
+    - `dialog`:弹窗选择模式
 - `placeholder` (String,可选):输入框占位提示文本
 
 ## 使用示例
@@ -121,12 +125,13 @@
 ## 注意事项
 
 1. 组件支持两种选择类型:
-   - `checkbox`:多选模式,可以选择多个选项,表单值为数组
-   - `radio`:单选模式,只能选择一个选项,表单值为单个值
+    - `checkbox`:多选模式,可以选择多个选项,表单值为数组
+    - `radio`:单选模式,只能选择一个选项,表单值为单个值
 2. 组件支持两种显示模式:
    - `plane`:直接显示模式,选项直接显示在表单项下方
    - `dialog`:弹窗选择模式,点击表单项后弹出选择弹窗
 3. 当选项较多时,建议使用弹窗选择模式(`displayType="dialog"`)
 4. 在多选模式下,表单值为选中项的 value 值组成的数组
 5. 在单选模式下,表单值为选中项的 value 值
-6. 组件会自动根据表单值显示已选项的文本,多个选项时用逗号分隔 
\ No newline at end of file
+6. 组件会自动根据表单值显示已选项的文本,多个选项时用逗号分隔
+7. 使用单选模式时,确保传入的表单值如果为单个值而非数组,否则可能导致显示异常 
\ No newline at end of file
diff --git a/_cursor.ai/forms.doc/chinaArea.doc/CChinaArea.doc.md b/_cursor.ai/forms.doc/chinaArea.doc/CChinaArea.doc.md
index 335fe08..7d0cb73 100644
--- a/_cursor.ai/forms.doc/chinaArea.doc/CChinaArea.doc.md
+++ b/_cursor.ai/forms.doc/chinaArea.doc/CChinaArea.doc.md
@@ -2,7 +2,7 @@
 
 ## 功能说明
 
-CChinaArea 是一个中国地区选择器组件,用于在表单中选择省市区地址。组件内置了完整的中国行政区划数据,支持省、市、区三级联动选择,并且可以设置默认值和只读模式。
+CChinaArea 是一个中国地区选择器组件,用于在表单中选择省市区地址。组件内置了完整的中国行政区划数据,支持省、市、区(街道)多级联动选择,并且可以通过地理定位自动获取当前位置。
 
 ## 引用方式
 
@@ -13,11 +13,11 @@
 ## 组件参数
 
 - `itemRes` (Object,必填):表单数据资源对象,表单组件内部机制专用
-- `level` (Number,可选):选择层级,可选值为 1(省)、2(省市)、3(省市区),默认为 3
+- `autoGeo` (Boolean,可选):是否自动通过地理定位获取省市区,默认为 false
+- `level` (Number,可选):联动级别,默认为 3
+  - `3`:省市区三级联动
+  - `4`:省市区街道四级联动
 - `placeholder` (String,可选):选择器占位提示文本
-- `readOnly` (Boolean,可选):只读模式,默认为 false
-- `separator` (String,可选):地址文本分隔符,默认为空格
-- `defaultCode` (String,可选):默认选中的区域编码
 
 ## 使用示例
 
@@ -47,12 +47,7 @@
   data() {
     return {
       form: {
-        address: {
-          province: '',
-          city: '',
-          district: '',
-          code: ''
-        }
+        address: []
       }
     };
   }
@@ -60,30 +55,34 @@
 </script>
 ```
 
-### 自定义配置
+### 四级联动
 
 ```html
-<CFormItem name="region" label="配送区域">
+<CFormItem name="region" label="详细区域">
   <CChinaArea 
-    :level="2" 
-    separator="/" 
-    defaultCode="330100" 
-    placeholder="请选择配送区域" 
+    :level="4" 
+    placeholder="请选择所在区域" 
+  />
+</CFormItem>
+```
+
+### 自动获取地理位置
+
+```html
+<CFormItem name="location" label="当前位置">
+  <CChinaArea 
+    :autoGeo="true" 
+    placeholder="正在获取位置..." 
   />
 </CFormItem>
 ```
 
 ## 注意事项
 
-1. 组件返回的数据格式为对象,包含以下字段:
-   - `province`:省份名称
-   - `city`:城市名称
-   - `district`:区县名称(仅在 level=3 时有值)
-   - `code`:选中区域的行政区划代码
-2. 可以通过 `defaultCode` 设置默认选中的区域
-3. `level` 参数决定了选择的层级:
-   - 1:仅选择省份
-   - 2:选择省份和城市
-   - 3:选择省份、城市和区县
-4. 组件会根据当前选择自动联动更新下级选项
-5. 在只读模式下,地址信息将以文本形式显示,使用 `separator` 分隔 
\ No newline at end of file
+1. 组件返回的数据格式为数组,包含选中的地区名称:
+   - 三级联动:`['浙江省', '杭州市', '西湖区']`
+   - 四级联动:`['浙江省', '杭州市', '西湖区', '文三路街道']`
+2. 当启用地理定位功能(`autoGeo=true`)时,组件会尝试获取当前位置的省市区信息
+3. 组件会根据当前选择自动联动更新下级选项
+4. 地区数据源来自内置的中国行政区划数据
+5. 位置信息在表单中显示时,地址各级之间会以 ` / ` 分隔 
\ No newline at end of file
diff --git a/_cursor.ai/forms.doc/datePicker.doc/CDatePicker.doc.md b/_cursor.ai/forms.doc/datePicker.doc/CDatePicker.doc.md
index 2e6991d..1fcedb4 100644
--- a/_cursor.ai/forms.doc/datePicker.doc/CDatePicker.doc.md
+++ b/_cursor.ai/forms.doc/datePicker.doc/CDatePicker.doc.md
@@ -13,11 +13,17 @@
 ## 组件参数
 
 - `itemRes` (Object,必填):表单数据资源对象,表单组件内部机制专用
-- `mode` (String,可选):日期时间选择器模式,可选值有 date、dateTime、dateRange,默认为 date
+- `mode` (String,可选):日期时间选择器模式,默认为 date
+  - `date`:选择单个日期,使用系统日期选择器
+  - `dateTime`:选择日期和时间,使用自定义的日期时间选择器
+  - `dateRange`:选择日期范围,使用自定义的日期范围选择器
 - `placeholder` (String,可选):输入框占位提示文本
 - `limitStart` (String,可选):可选日期的开始日期,格式为 YYYY-MM-DD
 - `limitEnd` (String,可选):可选日期的结束日期,格式为 YYYY-MM-DD
-- `fields` (String,可选):日期选择粒度,可选值有 year、month、day,默认为 day
+- `fields` (String,可选):日期选择粒度,默认为 day
+  - `year`:只选择年
+  - `month`:选择到月
+  - `day`:选择到日
 - `readOnly` (Boolean,可选):只读模式,默认为 false
 - `allowClear` (Boolean,可选):是否允许清除已选值,默认为 false
 
@@ -102,10 +108,7 @@
 
 ## 注意事项
 
-1. 不同的 `mode` 值对应不同的日期选择交互方式:
-   - `date`:选择单个日期,使用系统日期选择器
-   - `dateTime`:选择日期和时间,使用自定义的日期时间选择器
-   - `dateRange`:选择日期范围,使用自定义的日期范围选择器
+1. 不同的 `mode` 值对应不同的日期选择交互方式
 2. 当设置 `allowClear` 为 true 时,已选择日期后会显示清除图标,点击可清除已选值
 3. `limitStart` 和 `limitEnd` 参数仅在 `mode` 为 date 时生效
 4. 组件默认的可选日期范围是当前年份的前后 30 年
diff --git a/_cursor.ai/forms.doc/form.doc/CForm.doc.md b/_cursor.ai/forms.doc/form.doc/CForm.doc.md
index 3280a71..5869514 100644
--- a/_cursor.ai/forms.doc/form.doc/CForm.doc.md
+++ b/_cursor.ai/forms.doc/form.doc/CForm.doc.md
@@ -13,16 +13,18 @@
 ## 组件参数
 
 - `formData` (Object,必填):表单数据对象,用于存储表单各项的值
-- `autoScrollToError` (String,可选):是否自动滚动到错误位置,可选值有 on、off,默认为 off
+- `autoScrollToError` (String,可选):是否自动滚动到错误位置,默认为 off
+  - `on`:启用自动滚动
+  - `off`:禁用自动滚动
 - `onChange` (Function,可选):表单项变化的回调函数,参数为变化的表单项数据
 - `onFinish` (Function,可选):表单完成的回调函数,仅在提交且通过表单验证后调用,参数为整个表单数据
 
 ## 实例方法
 
 - `$submit`:手动触发表单提交,会执行表单验证
-- `$preVerify`:提前验证指定的表单项,参数为表单项名称数组和回调函数
-- `$setErrors`:直接设置表单错误,参数为错误对象,格式为 `{字段名: 错误信息}`
-- `$setScrollTop`:设置滚动位置,参数为滚动的 top 值
+- `$preVerify(keys, callback)`:提前验证指定的表单项,参数为表单项名称数组和回调函数
+- `$setErrors(errors)`:直接设置表单错误,参数为错误对象,格式为 `{字段名: 错误信息}`
+- `$setScrollTop(top)`:设置滚动位置,参数为滚动的 top 值
 
 ## 使用示例
 
@@ -31,7 +33,7 @@
 ```html
 <template>
   <CForm 
-    :form="form" 
+    :formData="form" 
     :onFinish="handleFinish"
   >
     <CFormItem name="username" label="用户名" required>
@@ -78,7 +80,7 @@
 
 ```html
 <CForm 
-  :form="form" 
+  :formData="form" 
   autoScrollToError="on" 
   :onFinish="handleFinish"
 >
@@ -98,11 +100,11 @@
 ```html
 <CForm 
   ref="form" 
-  :form="form" 
+  :formData="form" 
   :onFinish="handleFinish"
 >
   <!-- 表单项 -->
-  <button @tap="submitForm">提交</button>
+  <button @tap="evt => submitForm()">提交</button>
 </CForm>
 ```
 
diff --git a/_cursor.ai/forms.doc/imagePicker.doc/CImagePicker.doc.md b/_cursor.ai/forms.doc/imagePicker.doc/CImagePicker.doc.md
index 4af8934..5d60ec9 100644
--- a/_cursor.ai/forms.doc/imagePicker.doc/CImagePicker.doc.md
+++ b/_cursor.ai/forms.doc/imagePicker.doc/CImagePicker.doc.md
@@ -2,7 +2,7 @@
 
 ## 功能说明
 
-CImagePicker 是一个图片选择器组件,用于在表单中上传和管理图片。组件支持单张和多张图片上传,支持预览、删除等功能,并且可以限制上传图片的数量和大小。
+CImagePicker 是一个图片选择器组件,用于在表单中上传和管理图片。组件支持单张和多张图片上传,支持预览、删除等功能,并且可以限制上传图片的数量和来源。
 
 ## 引用方式
 
@@ -13,12 +13,16 @@
 ## 组件参数
 
 - `itemRes` (Object,必填):表单数据资源对象,表单组件内部机制专用
-- `maxCount` (Number,可选):最大上传图片数量,默认为 9
-- `maxSize` (Number,可选):单张图片最大大小,单位为 MB,默认为 5
-- `compress` (Boolean,可选):是否压缩图片,默认为 true
-- `quality` (Number,可选):图片压缩质量,取值范围 0-1,默认为 0.8
-- `placeholder` (String,可选):选择器占位提示文本
-- `readOnly` (Boolean,可选):只读模式,默认为 false
+- `count` (Number,可选):最大图片张数,默认为 1
+- `sourceType` (Array,可选):图片来源,默认为 ['album', 'camera']
+  - `album`:从相册选择
+  - `camera`:使用相机
+- `params` (Object,可选):上传图片的附加参数,默认为空对象
+- `needThumb` (Boolean,可选):是否开启缩略图,默认为 false
+
+## 实例方法
+
+- `$uploadImage(callback)`:上传图片到服务器,参数为回调函数,回调函数接收两个参数:状态和结果
 
 ## 使用示例
 
@@ -29,7 +33,7 @@
   <CForm :form="form">
     <CFormItem name="photos" label="图片上传">
       <CImagePicker 
-        :maxCount="3" 
+        :count="3" 
         placeholder="请上传图片" 
       />
     </CFormItem>
@@ -57,24 +61,58 @@
 </script>
 ```
 
-### 自定义配置
+### 限制图片来源
 
 ```html
-<CFormItem name="certificate" label="证书照片">
+<CFormItem name="idCard" label="身份证照片">
   <CImagePicker 
-    :maxCount="1" 
-    :maxSize="2" 
-    :compress="true" 
-    :quality="0.6" 
-    placeholder="请上传证书照片" 
+    :count="1" 
+    :sourceType="['camera']" 
+    placeholder="请拍摄身份证照片" 
   />
 </CFormItem>
 ```
 
+### 使用上传方法
+
+```html
+<template>
+  <CForm :form="form">
+    <CFormItem name="certificate" label="证书照片">
+      <CImagePicker 
+        ref="imagePicker"
+        :count="1" 
+        :params="{type: 'certificate'}" 
+        :needThumb="true"
+        placeholder="请上传证书照片" 
+      />
+    </CFormItem>
+    <button @tap="evt => handleUpload()">上传图片</button>
+  </CForm>
+</template>
+
+<script>
+export default {
+  // ...
+  methods: {
+    handleUpload() {
+      this.$refs.imagePicker.$uploadImage((state, result) => {
+        if (state === 'success') {
+          console.log('上传成功', result);
+        } else {
+          console.error('上传失败', result);
+        }
+      });
+    }
+  }
+};
+</script>
+```
+
 ## 注意事项
 
-1. 组件会自动处理图片上传,支持压缩和预览功能
-2. 上传的图片会被转换为 base64 格式存储在表单数据中
-3. 当设置 `maxCount` 为 1 时,组件会以单图模式运行
-4. 建议根据实际需求设置合适的 `maxSize` 和压缩参数
-5. 在只读模式下,只能查看已上传的图片,无法进行上传和删除操作 
\ No newline at end of file
+1. 组件会自动过滤不支持的图片格式,只允许上传 gif、png、jpg、jpeg 格式的图片
+2. 图片大小超过 1MB 的会自动进行压缩处理
+3. 通过 `$uploadImage` 方法可以将图片上传到服务器,上传成功后会自动更新表单值
+4. 如果设置了 `needThumb` 为 true,上传时会同时生成缩略图
+5. 组件内部集成了图片预览功能,点击已上传的图片可以放大查看 
\ No newline at end of file
diff --git a/_cursor.ai/forms.doc/input.doc/CInput.doc.md b/_cursor.ai/forms.doc/input.doc/CInput.doc.md
index a6c1dae..e762d3c 100644
--- a/_cursor.ai/forms.doc/input.doc/CInput.doc.md
+++ b/_cursor.ai/forms.doc/input.doc/CInput.doc.md
@@ -13,7 +13,13 @@
 ## 组件参数
 
 - `itemRes` (Object,必填):表单数据资源对象,表单组件内部机制专用
-- `type` (String,可选):输入框类型,可选值有 text、number、password、phone、idcard、digit
+- `type` (String,可选):输入框类型
+  - `text`:文本输入
+  - `number`:数字输入
+  - `password`:密码输入
+  - `phone`:手机号输入
+  - `idcard`:身份证号输入
+  - `digit`:带小数点的数字输入
 - `placeholder` (String,可选):输入框占位提示文本
 - `unit` (String,可选):输入框单位,设置后会在输入框右侧显示单位文本
 - `readOnly` (Boolean,可选):只读模式,默认为 false
diff --git a/_cursor.ai/forms.doc/numberStep.doc/CNumberStep.doc.md b/_cursor.ai/forms.doc/numberStep.doc/CNumberStep.doc.md
index 3ef361c..fa9e54f 100644
--- a/_cursor.ai/forms.doc/numberStep.doc/CNumberStep.doc.md
+++ b/_cursor.ai/forms.doc/numberStep.doc/CNumberStep.doc.md
@@ -16,7 +16,9 @@
 - `placeholder` (String,可选):输入框占位提示文本
 - `range` (Array,可选):取值范围,格式为 [最小值, 最大值],默认为 [0, 100]
 - `step` (Number,可选):步长,即每次点击增减按钮改变的数值,默认为 1
-- `correct` (String,可选):奇偶修正模式,可选值有 odd(奇数)、even(偶数),默认为空
+- `correct` (String,可选):奇偶修正模式,默认为空
+  - `odd`:只允许选择奇数
+  - `even`:只允许选择偶数
 - `unit` (String,可选):数值单位,显示在数字输入框右侧
 
 ## 使用示例
diff --git a/_cursor.ai/forms.doc/select.doc/CSelect.doc.md b/_cursor.ai/forms.doc/select.doc/CSelect.doc.md
index 42ab6cf..8a44b3e 100644
--- a/_cursor.ai/forms.doc/select.doc/CSelect.doc.md
+++ b/_cursor.ai/forms.doc/select.doc/CSelect.doc.md
@@ -16,7 +16,9 @@
 - `options` (Array,必填):选择菜单选项数组,每个选项应包含 name 和 value/id 属性
 - `placeholder` (String,可选):输入框占位提示文本
 - `readOnly` (Boolean,可选):只读模式,默认为 false
-- `selectByPage` (String,可选):开启选择菜单跳转选择页面模式,值为 'on'
+- `selectByPage` (String,可选):选择菜单模式
+  - 不设置:下拉选择模式
+  - `on`:跳转页面选择模式
 - `onOpenSelectorPage` (Function,可选):页面跳转模式下,发起选择的回调函数
 
 ## 使用示例
diff --git a/_cursor.ai/layout.doc/alert.doc/CAlert.doc.md b/_cursor.ai/layout.doc/alert.doc/CAlert.doc.md
new file mode 100644
index 0000000..0e83f04
--- /dev/null
+++ b/_cursor.ai/layout.doc/alert.doc/CAlert.doc.md
@@ -0,0 +1,129 @@
+# CAlert 弹窗
+
+## 功能说明
+
+基于 Taro UI 的模态框(AtModal)封装的alert弹窗组件,支持Alert(提示)和Confirm(确认)两种模式。
+
+## 引用方式
+
+```js
+import CAlert from '@components/layout/alert';
+```
+
+## 组件参数
+
+- `onConfirm` (Function,可选):确认模式下,点击确认按钮的回调函数
+
+## 实例方法
+
+- `$alert(option, callback)`:显示提示弹窗
+  - `option` (String|Object):弹窗配置,可以是字符串或对象
+    - 当为字符串时,直接作为弹窗内容
+    - 当为对象时,支持以下属性:
+      - `title` (String):弹窗标题
+      - `content` (String):弹窗主要内容
+      - `contents` (Array):弹窗内容数组,会逐行显示
+  - `callback` (Function):点击"知道了"按钮后的回调函数
+  
+- `$confirm(option, callback)`:显示确认弹窗
+  - `option` (String|Object):弹窗配置,参数同`$alert`
+  - `callback` (Function):点击"取消"或"确定"按钮后的回调函数
+
+## 使用示例
+
+### 基础提示框用法
+
+```html
+<template>
+  <view class="page">
+    <button @tap="evt => showAlert()">显示提示</button>
+    <CAlert ref="alert" />
+  </view>
+</template>
+
+<script>
+import CAlert from '@components/layout/alert';
+
+export default {
+  components: {
+    CAlert
+  },
+  methods: {
+    showAlert() {
+      this.$refs.alert.$alert('这是一条提示信息');
+    }
+  }
+}
+</script>
+```
+
+### 带标题的提示框
+
+```html
+<template>
+  <view class="page">
+    <button @tap="evt => showAlertWithTitle()">显示带标题的提示</button>
+    <CAlert ref="alert" />
+  </view>
+</template>
+
+<script>
+import CAlert from '@components/layout/alert';
+
+export default {
+  components: {
+    CAlert
+  },
+  methods: {
+    showAlertWithTitle() {
+      this.$refs.alert.$alert({
+        title: '提示',
+        content: '这是一条提示信息'
+      });
+    }
+  }
+}
+</script>
+```
+
+### 确认框用法
+
+```html
+<template>
+  <view class="page">
+    <button @tap="evt => showConfirm()">显示确认框</button>
+    <CAlert 
+      ref="alert" 
+      :onConfirm="handleConfirm"
+    />
+  </view>
+</template>
+
+<script>
+import CAlert from '@components/layout/alert';
+
+export default {
+  components: {
+    CAlert
+  },
+  methods: {
+    showConfirm() {
+      this.$refs.alert.$confirm('是否确认此操作?');
+    },
+    handleConfirm() {
+      console.log('用户点击了确认');
+      // 执行确认操作
+    }
+  }
+}
+</script>
+```
+
+## 注意事项
+
+1. 弹窗内容支持普通文本,不支持HTML结构
+2. 使用确认框时,需要通过props传入`onConfirm`回调函数来响应用户的确认操作
+3. 组件内部存在一个拼写错误,确认模式的变量名为`'comfirm'`而非`'confirm'`,但使用时仍应使用`$confirm`方法
+4. 组件基于Taro UI的模态框,在样式上与Taro UI保持一致
+
+<!-- 作者:Tevin --> 
\ No newline at end of file
diff --git a/_cursor.ai/layout.doc/anchor.doc/CAnchor.doc.md b/_cursor.ai/layout.doc/anchor.doc/CAnchor.doc.md
new file mode 100644
index 0000000..8c287b4
--- /dev/null
+++ b/_cursor.ai/layout.doc/anchor.doc/CAnchor.doc.md
@@ -0,0 +1,150 @@
+# CAnchor 应用内超连接
+
+## 功能说明
+
+应用内超连接组件,用于在应用内部页面之间进行跳转,封装了 Taro 的页面跳转方法,支持多种跳转模式。组件可包裹任何内容作为点击触发区域。
+
+## 引用方式
+
+```js
+import CAnchor from '@components/layout/anchor';
+```
+
+## 组件参数
+
+- `href` (String,必选):跳转目标路径,可以是页面路径,也可以是特殊值 'back'
+- `rel` (String,可选):跳转方式,默认值为 'navigate'
+  - `navigate`:保留当前页面,跳转到应用内的某个页面(对应 Taro.navigateTo)
+  - `redirect`:关闭当前页面,跳转到应用内的某个页面(对应 Taro.redirectTo)
+
+## 使用示例
+
+### 基础用法
+
+```html
+<template>
+  <view class="page">
+    <CAnchor href="/pages/order/detail?id=12345">
+      <view class="link-text">查看订单详情</view>
+    </CAnchor>
+  </view>
+</template>
+
+<script>
+import CAnchor from '@components/layout/anchor';
+
+export default {
+  components: {
+    CAnchor
+  }
+}
+</script>
+```
+
+### 包裹图片或按钮
+
+```html
+<template>
+  <view class="page">
+    <!-- 包裹图片 -->
+    <CAnchor href="/pages/product/detail?id=6789">
+      <image 
+        src="/static/images/product.jpg" 
+        mode="aspectFill" 
+        class="product-image"
+      />
+    </CAnchor>
+    
+    <!-- 包裹按钮 -->
+    <CAnchor href="/pages/cart/index">
+      <AtButton type="primary">
+        去购物车结算
+      </AtButton>
+    </CAnchor>
+  </view>
+</template>
+
+<script>
+import CAnchor from '@components/layout/anchor';
+import { AtButton } from 'taro-ui-vue';
+
+export default {
+  components: {
+    CAnchor,
+    AtButton
+  }
+}
+</script>
+```
+
+### 返回上一页
+
+```html
+<template>
+  <view class="page">
+    <CAnchor href="back">
+      <view class="back-link">
+        <AtIcon value="chevron-left" size="16" />
+        <text>返回上一页</text>
+      </view>
+    </CAnchor>
+  </view>
+</template>
+
+<script>
+import CAnchor from '@components/layout/anchor';
+import { AtIcon } from 'taro-ui-vue';
+
+export default {
+  components: {
+    CAnchor,
+    AtIcon
+  }
+}
+</script>
+
+<style>
+.back-link {
+  display: flex;
+  align-items: center;
+}
+</style>
+```
+
+### 重定向模式
+
+```html
+<template>
+  <view class="page">
+    <CAnchor 
+      href="/pages/login/index" 
+      rel="redirect"
+    >
+      <view class="redirect-link">
+        请先登录后再操作
+      </view>
+    </CAnchor>
+  </view>
+</template>
+
+<script>
+import CAnchor from '@components/layout/anchor';
+
+export default {
+  components: {
+    CAnchor
+  }
+}
+</script>
+```
+
+## 注意事项
+
+1. 组件通过默认插槽提供内容,可以包裹任何元素作为点击区域
+2. href 参数必须提供有效的页面路径,否则点击不会触发任何操作
+3. 当 href 设置为 'back' 时,等同于调用 Taro.navigateBack() 方法
+4. 页面路径应该以 '/' 开头,例如 '/pages/index/index'
+5. 可以在路径中添加查询参数,例如 '/pages/detail?id=123'
+6. 重定向模式会关闭当前页面,无法通过返回按钮回到当前页面
+
+<!-- 作者:Tevin --> 
\ No newline at end of file
diff --git a/_cursor.ai/layout.doc/card.doc/CCard.doc.md b/_cursor.ai/layout.doc/card.doc/CCard.doc.md
new file mode 100644
index 0000000..bc58fbe
--- /dev/null
+++ b/_cursor.ai/layout.doc/card.doc/CCard.doc.md
@@ -0,0 +1,134 @@
+# CCard 列表卡片
+
+## 功能说明
+
+一个用于显示信息的卡片组件,结构包括主体、标题、内容、操作区四个部分。适用于需要将信息以卡片形式展示的场景,如列表项、信息展示等。
+
+## 引用方式
+
+```js
+import { CCard, CCardTitle, CCardContent, CCardAction } from '@components/layout/card';
+```
+
+## 组件结构
+
+卡片组件由以下四个组件组成:
+
+1. `CCard` - 卡片主体,作为其他组件的容器
+2. `CCardTitle` - 卡片标题,显示标题内容和可选的额外操作
+3. `CCardContent` - 卡片内容区域
+4. `CCardAction` - 卡片底部操作区域,支持横向滚动
+
+## 组件参数
+
+### CCard
+
+无特定参数,通过插槽嵌套其他卡片子组件使用
+
+### CCardTitle
+
+- `title` (String,可选):标题文本,默认值为 '列表卡片标题'
+- `onTitleClick` (Function,可选):标题点击事件回调函数
+
+### CCardContent
+
+无特定参数,用于包裹卡片主要内容
+
+### CCardAction
+
+无特定参数,用于包裹卡片底部的操作按钮
+
+## 使用示例
+
+### 基础用法
+
+```html
+<template>
+  <view class="page">
+    <CCard>
+      <CCardTitle title="用户信息" />
+      <CCardContent>
+        <view class="user-info">
+          <view class="info-item">姓名:张三</view>
+          <view class="info-item">电话:13800138000</view>
+          <view class="info-item">地址:广州市天河区</view>
+        </view>
+      </CCardContent>
+    </CCard>
+  </view>
+</template>
+
+<script>
+import { CCard, CCardTitle, CCardContent } from '@components/layout/card';
+
+export default {
+  components: {
+    CCard,
+    CCardTitle,
+    CCardContent
+  }
+}
+</script>
+```
+
+### 完整卡片示例(带标题、内容和操作)
+
+```html
+<template>
+  <view class="page">
+    <CCard>
+      <CCardTitle title="订单信息">
+        <AtTag size="small" type="primary">新订单</AtTag>
+      </CCardTitle>
+      
+      <CCardContent>
+        <view class="order-info">
+          <view class="order-item">订单号:2023042501</view>
+          <view class="order-item">客户:李四</view>
+          <view class="order-item">金额:¥125.00</view>
+          <view class="order-item">状态:待处理</view>
+        </view>
+      </CCardContent>
+      
+      <CCardAction>
+        <AtButton size="small" type="secondary" @tap="evt => handleCancel()">取消</AtButton>
+        <AtButton size="small" type="primary" @tap="evt => handleConfirm()">确认</AtButton>
+      </CCardAction>
+    </CCard>
+  </view>
+</template>
+
+<script>
+import { CCard, CCardTitle, CCardContent, CCardAction } from '@components/layout/card';
+import { AtButton, AtTag } from 'taro-ui-vue';
+
+export default {
+  components: {
+    CCard,
+    CCardTitle,
+    CCardContent,
+    CCardAction,
+    AtButton,
+    AtTag
+  },
+  methods: {
+    handleCancel() {
+      console.log('取消订单');
+    },
+    handleConfirm() {
+      console.log('确认订单');
+    }
+  }
+}
+</script>
+```
+
+## 注意事项
+
+1. 卡片组件需要按照 `CCard > CCardTitle/CCardContent/CCardAction` 的层级结构使用
+2. `CCardTitle` 设置了底部边框,`CCardAction` 设置了顶部边框,都使用了 `m-border-strong-bottom/top` 样式类
+3. `CCardTitle` 组件支持通过默认插槽在标题右侧添加额外内容(如标签、按钮等)
+4. `CCardAction` 组件使用 `scroll-view` 实现,当操作按钮过多时支持横向滚动
+5. 卡片内容可以根据实际需要自由组织,`CCardContent` 不对内容做特定限制
+
+<!-- 作者:Tevin --> 
\ No newline at end of file
diff --git a/_cursor.ai/layout.doc/description.doc/CDescription.doc.md b/_cursor.ai/layout.doc/description.doc/CDescription.doc.md
new file mode 100644
index 0000000..8a62006
--- /dev/null
+++ b/_cursor.ai/layout.doc/description.doc/CDescription.doc.md
@@ -0,0 +1,149 @@
+# CDescription 描述列表项
+
+## 功能说明
+
+描述列表项组件,用于展示标签和内容的键值对形式信息,常用于详情页面的信息展示,支持不同的标签对齐方式和样式选项。
+
+## 引用方式
+
+```js
+import CDescription from '@components/layout/description';
+```
+
+## 组件参数
+
+- `label` (String,必选):左侧标签文本
+- `labelAlign` (String,可选):标签对齐方式,默认值为 'left'
+  - `left`:定宽左对齐
+  - `right`:定宽右对齐
+  - `none`:无固定宽度
+- `enlarged` (Boolean,可选):是否加大显示区域,默认值为 false
+- `hasBorder` (Boolean,可选):是否显示底部边框,默认值为 false
+
+## 使用示例
+
+### 基础用法
+
+```html
+<template>
+  <view class="page">
+    <CDescription label="名称">
+      <text>张三</text>
+    </CDescription>
+    <CDescription label="电话">
+      <text>13800138000</text>
+    </CDescription>
+    <CDescription label="地址">
+      <text>广州市天河区某某路某某号</text>
+    </CDescription>
+  </view>
+</template>
+
+<script>
+import CDescription from '@components/layout/description';
+
+export default {
+  components: {
+    CDescription
+  }
+}
+</script>
+```
+
+### 不同对齐方式和样式
+
+```html
+<template>
+  <view class="page">
+    <!-- 标签右对齐 -->
+    <CDescription 
+      label="订单编号" 
+      labelAlign="right"
+    >
+      <text>OR202304250001</text>
+    </CDescription>
+    
+    <!-- 带底部边框 -->
+    <CDescription 
+      label="金额" 
+      hasBorder
+    >
+      <text class="m-text-primary">¥198.00</text>
+    </CDescription>
+    
+    <!-- 加大显示区域 -->
+    <CDescription 
+      label="备注" 
+      enlarged
+    >
+      <text>此订单为加急订单,请优先处理,并且联系物流安排配送</text>
+    </CDescription>
+    
+    <!-- 无宽度限制的标签 -->
+    <CDescription 
+      label="客户提供的自定义信息要求" 
+      labelAlign="none"
+    >
+      <text>产品需要绿色包装</text>
+    </CDescription>
+  </view>
+</template>
+
+<script>
+import CDescription from '@components/layout/description';
+
+export default {
+  components: {
+    CDescription
+  }
+}
+</script>
+```
+
+### 在卡片内使用
+
+```html
+<template>
+  <view class="page">
+    <CCard>
+      <CCardTitle title="订单信息" />
+      <CCardContent>
+        <CDescription label="订单编号">
+          <text>OR202304250001</text>
+        </CDescription>
+        <CDescription label="下单时间">
+          <text>2023-04-25 14:30:25</text>
+        </CDescription>
+        <CDescription label="订单状态">
+          <text class="m-text-warning">待处理</text>
+        </CDescription>
+      </CCardContent>
+    </CCard>
+  </view>
+</template>
+
+<script>
+import CDescription from '@components/layout/description';
+import { CCard, CCardTitle, CCardContent } from '@components/layout/card';
+
+export default {
+  components: {
+    CDescription,
+    CCard,
+    CCardTitle,
+    CCardContent
+  }
+}
+</script>
+```
+
+## 注意事项
+
+1. 组件主要用于键值对形式的信息展示,内容部分通过默认插槽提供
+2. 标签宽度在labelAlign为left和right时是固定的,建议标签文字不要过长
+3. 当标签文字较长时,可以使用labelAlign="none"取消固定宽度限制
+4. 内容部分可以插入任何元素,不仅限于文本
+5. 组件适合连续使用来展示多个信息项,形成一个完整的描述列表
+6. 当设置hasBorder为true时,会在项目底部显示一条分隔线
+
+<!-- 作者:Tevin --> 
\ No newline at end of file
diff --git a/_cursor.ai/layout.doc/drawer.doc/CDrawer.doc.md b/_cursor.ai/layout.doc/drawer.doc/CDrawer.doc.md
new file mode 100644
index 0000000..1d8df88
--- /dev/null
+++ b/_cursor.ai/layout.doc/drawer.doc/CDrawer.doc.md
@@ -0,0 +1,199 @@
+# CDrawer 抽屉
+
+## 功能说明
+
+抽屉组件,可从页面不同方向滑出,通常用于展示临时的操作面板或内容区域,支持从顶部、左侧、右侧滑入。点击遮罩层可关闭抽屉。
+
+## 引用方式
+
+```js
+import CDrawer from '@components/layout/drawer';
+```
+
+## 组件参数
+
+- `show` (Boolean,必选):控制抽屉显示或隐藏,默认值为 false
+- `direction` (String,可选):抽屉滑出方向,默认值为 'right'
+  - `top`:从顶部滑出
+  - `left`:从左侧滑出
+  - `right`:从右侧滑出
+- `onClose` (Function,必选):抽屉关闭时的回调函数,通常用于设置 show 为 false
+
+## 使用示例
+
+### 基础用法 - 从右侧滑出
+
+```html
+<template>
+  <view class="page">
+    <button @tap="evt => openDrawer()">打开抽屉</button>
+    
+    <CDrawer 
+      :show="drawerVisible" 
+      :onClose="closeDrawer"
+    >
+      <view class="drawer-content">
+        <view class="drawer-title">筛选条件</view>
+        <view class="drawer-item">选项1</view>
+        <view class="drawer-item">选项2</view>
+        <view class="drawer-item">选项3</view>
+        <button @tap="evt => applyFilter()">确定</button>
+      </view>
+    </CDrawer>
+  </view>
+</template>
+
+<script>
+import CDrawer from '@components/layout/drawer';
+
+export default {
+  components: {
+    CDrawer
+  },
+  data() {
+    return {
+      drawerVisible: false
+    }
+  },
+  methods: {
+    openDrawer() {
+      this.drawerVisible = true;
+    },
+    closeDrawer() {
+      this.drawerVisible = false;
+    },
+    applyFilter() {
+      // 应用筛选逻辑
+      this.closeDrawer();
+    }
+  }
+}
+</script>
+
+<style>
+.drawer-content {
+  padding: 20px;
+}
+.drawer-title {
+  font-size: 18px;
+  font-weight: bold;
+  margin-bottom: 20px;
+}
+.drawer-item {
+  padding: 10px 0;
+}
+</style>
+```
+
+### 从左侧滑出的抽屉
+
+```html
+<template>
+  <view class="page">
+    <button @tap="evt => openDrawer()">打开导航菜单</button>
+    
+    <CDrawer 
+      :show="drawerVisible" 
+      direction="left"
+      :onClose="closeDrawer"
+    >
+      <view class="menu-content">
+        <view class="menu-item" @tap="evt => navigateTo('/pages/home/index')">首页</view>
+        <view class="menu-item" @tap="evt => navigateTo('/pages/order/list')">订单管理</view>
+        <view class="menu-item" @tap="evt => navigateTo('/pages/user/index')">用户中心</view>
+        <view class="menu-item" @tap="evt => navigateTo('/pages/setting/index')">系统设置</view>
+      </view>
+    </CDrawer>
+  </view>
+</template>
+
+<script>
+import CDrawer from '@components/layout/drawer';
+import Taro from '@tarojs/taro';
+
+export default {
+  components: {
+    CDrawer
+  },
+  data() {
+    return {
+      drawerVisible: false
+    }
+  },
+  methods: {
+    openDrawer() {
+      this.drawerVisible = true;
+    },
+    closeDrawer() {
+      this.drawerVisible = false;
+    },
+    navigateTo(url) {
+      this.closeDrawer();
+      Taro.navigateTo({ url });
+    }
+  }
+}
+</script>
+```
+
+### 从顶部滑出的抽屉
+
+```html
+<template>
+  <view class="page">
+    <button @tap="evt => openDrawer()">显示通知</button>
+    
+    <CDrawer 
+      :show="drawerVisible" 
+      direction="top"
+      :onClose="closeDrawer"
+    >
+      <view class="notification">
+        <view class="notification-title">系统通知</view>
+        <view class="notification-content">
+          您有3条未读消息,请及时查看处理。
+        </view>
+        <button @tap="evt => viewMessages()">查看详情</button>
+      </view>
+    </CDrawer>
+  </view>
+</template>
+
+<script>
+import CDrawer from '@components/layout/drawer';
+
+export default {
+  components: {
+    CDrawer
+  },
+  data() {
+    return {
+      drawerVisible: false
+    }
+  },
+  methods: {
+    openDrawer() {
+      this.drawerVisible = true;
+    },
+    closeDrawer() {
+      this.drawerVisible = false;
+    },
+    viewMessages() {
+      this.closeDrawer();
+      // 跳转到消息页面
+    }
+  }
+}
+</script>
+```
+
+## 注意事项
+
+1. 使用抽屉组件时,必须提供 onClose 回调函数,否则点击遮罩层无法关闭抽屉
+2. 抽屉内容通过默认插槽提供,可以根据需要自定义内容和样式
+3. 抽屉组件默认占满整个屏幕,内容区域的样式需要自行定义
+4. 抽屉打开时会添加遮罩层,防止用户与页面其他部分交互
+5. 抽屉内容区宽度固定,左右抽屉为屏幕宽度的80%,顶部抽屉为屏幕高度的40%
+6. 当前版本的组件不支持从底部滑出的抽屉,如有需要可考虑扩展组件
+
+<!-- 作者:Tevin --> 
\ No newline at end of file
diff --git a/_cursor.ai/layout.doc/h5Page.doc/CH5Page.doc.md b/_cursor.ai/layout.doc/h5Page.doc/CH5Page.doc.md
new file mode 100644
index 0000000..00e2eb4
--- /dev/null
+++ b/_cursor.ai/layout.doc/h5Page.doc/CH5Page.doc.md
@@ -0,0 +1,175 @@
+# CH5Page H5页面布局
+
+## 功能说明
+
+H5页面布局组件集,用于构建标准的H5页面结构,包含页面容器、导航栏和内容区域三个部分,适用于需要遵循统一布局规范的H5页面。
+
+## 引用方式
+
+```js
+import { CPage, CNavBar, CContent } from '@components/layout/h5Page';
+```
+
+## 组件结构
+
+H5页面布局组件由以下三个组件组成:
+
+1. `CPage` - 页面容器,作为整个页面的最外层容器
+2. `CNavBar` - 导航栏,显示页面标题和导航按钮
+3. `CContent` - 内容区域,显示页面主要内容,可选择是否支持滚动
+
+## 组件参数
+
+### CPage
+
+无特定参数,通过插槽嵌套其他组件使用
+
+### CNavBar
+
+- `title` (String,必选):导航栏标题
+- `iconType` (String,可选):左侧图标类型,默认值为 'chevron-left'
+- `onClickIcon` (Function,可选):左侧图标点击事件回调函数,返回true时将执行默认的返回上一页行为
+- `dropNav` (Array,可选):右侧下拉菜单配置,数组中的每项为对象,包含以下属性:
+  - `title` (String):菜单项标题
+  - `url` (String):点击菜单项跳转的页面路径
+
+### CContent
+
+- `scroll` (String,可选):是否开启滚动功能,默认值为 'off'
+  - `off`:不开启滚动
+  - `on`:开启滚动
+
+## 实例方法
+
+### CContent
+
+- `$scrollTop(top)`:滚动到指定位置
+  - `top` (Number):要滚动到的位置,单位为像素,默认为0
+
+## 使用示例
+
+### 基础用法
+
+```html
+<template>
+  <CPage>
+    <CNavBar title="页面标题" />
+    <CContent>
+      <view class="page-content">
+        <!-- 页面内容 -->
+        <view class="content-item">内容项1</view>
+        <view class="content-item">内容项2</view>
+        <view class="content-item">内容项3</view>
+      </view>
+    </CContent>
+  </CPage>
+</template>
+
+<script>
+import { CPage, CNavBar, CContent } from '@components/layout/h5Page';
+
+export default {
+  components: {
+    CPage,
+    CNavBar,
+    CContent
+  }
+}
+</script>
+```
+
+### 带滚动的内容和自定义返回事件
+
+```html
+<template>
+  <CPage>
+    <CNavBar 
+      title="详情页面" 
+      :onClickIcon="handleBackClick"
+    />
+    <CContent 
+      scroll="on"
+      ref="content"
+    >
+      <view class="page-content">
+        <!-- 长内容需要滚动 -->
+        <view class="content-section" v-for="i in 20" :key="i">
+          内容区域 {{i}}
+        </view>
+      </view>
+      <view class="scroll-top-btn" @tap="evt => scrollToTop()">回到顶部</view>
+    </CContent>
+  </CPage>
+</template>
+
+<script>
+import { CPage, CNavBar, CContent } from '@components/layout/h5Page';
+
+export default {
+  components: {
+    CPage,
+    CNavBar,
+    CContent
+  },
+  methods: {
+    handleBackClick() {
+      // 在返回前执行一些操作
+      console.log('用户点击了返回按钮');
+      // 返回true继续执行默认的返回行为
+      return true;
+    },
+    scrollToTop() {
+      this.$refs.content.$scrollTop(0);
+    }
+  }
+}
+</script>
+```
+
+### 带下拉菜单的导航栏
+
+```html
+<template>
+  <CPage>
+    <CNavBar 
+      title="订单列表" 
+      :dropNav="navMenuItems"
+    />
+    <CContent>
+      <!-- 页面内容 -->
+    </CContent>
+  </CPage>
+</template>
+
+<script>
+import { CPage, CNavBar, CContent } from '@components/layout/h5Page';
+
+export default {
+  components: {
+    CPage,
+    CNavBar,
+    CContent
+  },
+  data() {
+    return {
+      navMenuItems: [
+        { title: '新增订单', url: '/pages/order/create' },
+        { title: '订单筛选', url: '/pages/order/filter' },
+        { title: '导出订单', url: '/pages/order/export' }
+      ]
+    }
+  }
+}
+</script>
+```
+
+## 注意事项
+
+1. H5页面组件需要按照 `CPage > CNavBar + CContent` 的层级结构使用
+2. 当使用下拉菜单时,点击页面其他区域会自动关闭菜单
+3. CNavBar 的下拉菜单项需要设置 url 才能正常跳转
+4. CContent 设置 scroll="on" 后会自动处理内容区域的滚动,无需额外设置样式
+5. 当点击CNavBar的返回图标时,如果没有设置 onClickIcon 回调,将默认执行 Taro.navigateBack()
+6. 组件会监听页面点击和触摸事件来处理下拉菜单的关闭逻辑
+
+<!-- 作者:Tevin -->
\ No newline at end of file
diff --git a/_cursor.ai/layout.doc/homeNav.doc/CHomeNav.doc.md b/_cursor.ai/layout.doc/homeNav.doc/CHomeNav.doc.md
new file mode 100644
index 0000000..f8b1e18
--- /dev/null
+++ b/_cursor.ai/layout.doc/homeNav.doc/CHomeNav.doc.md
@@ -0,0 +1,127 @@
+# CHomeNav 首页导航
+
+## 功能说明
+
+用于首页显示导航菜单项的组件,支持两列或三列排版,可以显示分组标题。搭配CHomeItem子组件使用,用于展示一组功能入口。
+
+## 引用方式
+
+```js
+import { CHomeNav, CHomeItem } from '@components/layout/homeNav';
+```
+
+## 组件结构
+
+首页导航组件由以下两个组件组成:
+
+1. `CHomeNav` - 导航容器,作为导航项的容器,控制排版
+2. `CHomeItem` - 导航项,代表一个功能入口
+
+## 组件参数
+
+### CHomeNav
+
+- `layout` (String,可选):排版方式,默认值为 'two'
+  - `two`:两列排版
+  - `three`:三列排版
+- `title` (String,可选):分组标题,不设置则不显示
+
+### CHomeItem
+
+- `label` (String,必选):导航项名称
+- `icon` (String,必选):导航项图标地址
+- `href` (String,必选):点击后跳转的链接地址
+
+## 使用示例
+
+### 基础用法
+
+```html
+<template>
+  <view class="page">
+    <CHomeNav title="常用功能">
+      <CHomeItem
+        label="订单管理"
+        icon="/static/icons/order.png"
+        href="/pages/order/list"
+      />
+      <CHomeItem
+        label="客户管理"
+        icon="/static/icons/customer.png"
+        href="/pages/customer/list"
+      />
+      <CHomeItem
+        label="配送管理"
+        icon="/static/icons/delivery.png"
+        href="/pages/delivery/list"
+      />
+      <CHomeItem
+        label="数据统计"
+        icon="/static/icons/statistics.png"
+        href="/pages/statistics/index"
+      />
+    </CHomeNav>
+  </view>
+</template>
+
+<script>
+import { CHomeNav, CHomeItem } from '@components/layout/homeNav';
+
+export default {
+  components: {
+    CHomeNav,
+    CHomeItem
+  }
+}
+</script>
+```
+
+### 三列排版
+
+```html
+<template>
+  <view class="page">
+    <CHomeNav 
+      title="快捷功能" 
+      layout="three"
+    >
+      <CHomeItem
+        label="新增订单"
+        icon="/static/icons/add-order.png"
+        href="/pages/order/create"
+      />
+      <CHomeItem
+        label="新增客户"
+        icon="/static/icons/add-customer.png"
+        href="/pages/customer/create"
+      />
+      <CHomeItem
+        label="扫码收款"
+        icon="/static/icons/qr-payment.png"
+        href="/pages/payment/scan"
+      />
+    </CHomeNav>
+  </view>
+</template>
+
+<script>
+import { CHomeNav, CHomeItem } from '@components/layout/homeNav';
+
+export default {
+  components: {
+    CHomeNav,
+    CHomeItem
+  }
+}
+</script>
+```
+
+## 注意事项
+
+1. CHomeNav 组件内部需要包含 CHomeItem 子组件,不支持其他内容
+2. CHomeItem 组件使用了 CAnchor 组件处理链接跳转,能够根据链接类型自动选择合适的跳转方式
+3. 根据设计,当使用两列布局时图标稍大,三列布局时图标稍小
+4. 传给 CHomeItem 的 icon 应该是一个完整的图片路径
+5. 不管使用哪种布局,都会自动调整导航项的间距,保证美观
+
+<!-- 作者:Tevin --> 
\ No newline at end of file
diff --git a/_cursor.ai/layout.doc/navCustomBar.doc/CNavCustomBar.doc.md b/_cursor.ai/layout.doc/navCustomBar.doc/CNavCustomBar.doc.md
new file mode 100644
index 0000000..1c46be4
--- /dev/null
+++ b/_cursor.ai/layout.doc/navCustomBar.doc/CNavCustomBar.doc.md
@@ -0,0 +1,80 @@
+# CNavCustomBar 自定义导航条
+
+## 功能说明
+
+自定义导航条组件,用于在页面顶部显示导航信息,可以自动适配不同设备的状态栏高度,支持显示返回按钮和标题。
+
+## 引用方式
+
+```js
+import CNavCustomBar from '@components/layout/navCustomBar';
+```
+
+## 组件参数
+
+- `isNeedBackIcon` (Boolean,可选):是否需要显示返回按钮,默认值为 false
+- `title` (String,可选):导航栏标题文本,默认值为空字符串
+
+## 实例方法
+
+- `$getStatusBarHeight()`:获取状态栏高度
+- `$getNavBarHeight()`:获取导航栏的总高度(包括状态栏)
+
+## 使用示例
+
+### 基础用法
+
+```html
+<template>
+  <view class="page">
+    <CNavCustomBar 
+      title="页面标题" 
+      :isNeedBackIcon="true" 
+    />
+    <view class="content" :style="{paddingTop: navBarHeight + 'px'}">
+      <!-- 页面内容 -->
+    </view>
+  </view>
+</template>
+
+<script>
+import CNavCustomBar from '@components/layout/navCustomBar';
+
+export default {
+  components: {
+    CNavCustomBar
+  },
+  data() {
+    return {
+      navBarHeight: 0
+    }
+  },
+  mounted() {
+    this.navBarHeight = this.$refs.navBar.$getNavBarHeight();
+  }
+}
+</script>
+```
+
+### 自定义图标
+
+```html
+<template>
+  <view class="page">
+    <CNavCustomBar title="首页">
+      <template #icon>
+        <image class="menu-icon" src="../assets/menu.png" />
+      </template>
+    </CNavCustomBar>
+  </view>
+</template>
+```
+
+## 注意事项
+
+1. 组件使用固定定位显示在页面顶部,使用时需要给内容区域设置上内边距,值为导航栏高度,可通过 `$getNavBarHeight()` 方法获取
+2. 组件会自动适配不同设备的状态栏高度
+3. 当 `isNeedBackIcon` 为 true 时,点击返回按钮默认执行 Taro.navigateBack({ delta: 1 })
+4. 可以通过具名插槽 "icon" 自定义左侧图标,但仅在 isNeedBackIcon 为 false 时生效
+
+<!-- 作者:chensi --> 
\ No newline at end of file
diff --git a/_cursor.ai/layout.doc/numerical.doc/CNumerical.doc.md b/_cursor.ai/layout.doc/numerical.doc/CNumerical.doc.md
new file mode 100644
index 0000000..02abe60
--- /dev/null
+++ b/_cursor.ai/layout.doc/numerical.doc/CNumerical.doc.md
@@ -0,0 +1,117 @@
+# CNumerical 数值显示
+
+## 功能说明
+
+用于以美观的方式展示一组数值及其标题的组件,支持小数点分隔显示,可以自适应不同数量的数值项,并支持点击事件。
+
+## 引用方式
+
+```js
+import CNumerical from '@components/layout/numerical';
+```
+
+## 组件参数
+
+- `values` (Array,必选):数值集合,数组中的每项为对象,包含以下属性:
+  - `title` (String):数值项的标题
+  - `value` (Number|String):要显示的数值
+  - `textType` (String,可选):文本颜色类型,对应 CSS 类 'm-text-{textType}'
+  - `onClick` (Function,可选):点击数值项时的回调函数,接收当前项对象作为参数
+
+## 使用示例
+
+### 基础用法
+
+```html
+<template>
+  <view class="page">
+    <CNumerical :values="numericalValues" />
+  </view>
+</template>
+
+<script>
+import CNumerical from '@components/layout/numerical';
+
+export default {
+  components: {
+    CNumerical
+  },
+  data() {
+    return {
+      numericalValues: [
+        {
+          title: '今日销量',
+          value: 135
+        },
+        {
+          title: '月销量',
+          value: 3254
+        },
+        {
+          title: '总销量',
+          value: 58962
+        }
+      ]
+    }
+  }
+}
+</script>
+```
+
+### 带颜色样式和点击事件
+
+```html
+<template>
+  <view class="page">
+    <CNumerical :values="numericalValues" />
+  </view>
+</template>
+
+<script>
+import CNumerical from '@components/layout/numerical';
+
+export default {
+  components: {
+    CNumerical
+  },
+  data() {
+    return {
+      numericalValues: [
+        {
+          title: '收入(元)',
+          value: 9856.75,
+          textType: 'primary'
+        },
+        {
+          title: '支出(元)',
+          value: 4328.50,
+          textType: 'warning'
+        },
+        {
+          title: '详情',
+          value: 0,
+          onClick: (item) => {
+            console.log('用户点击了详情');
+            // 跳转到详情页或显示详情弹窗
+          }
+        }
+      ]
+    }
+  }
+}
+</script>
+```
+
+## 注意事项
+
+1. 组件会根据传入的数值项数量自动调整布局:
+   - 当数量能被3整除时,每行显示3个项目
+   - 当数量除以3余1时,最后4个项目每行显示2个
+   - 当数量除以3余2时,最后2个项目独占一行
+   - 当只有1个项目时,占满整行
+2. 数值会自动分离整数和小数部分,整数部分字体较大,小数部分字体较小
+3. 当整数部分超过4位数时,小数部分的字体会进一步缩小
+4. 具有onClick属性的项目会显示一个向右的箭头,并增加点击样式
+5. textType属性可以控制数值的颜色,通过添加类名 'm-text-{textType}' 实现
+
+<!-- 作者:Tevin --> 
\ No newline at end of file
diff --git a/_cursor.ai/layout.doc/waiting.doc/CWaiting.doc.md b/_cursor.ai/layout.doc/waiting.doc/CWaiting.doc.md
new file mode 100644
index 0000000..afc4d50
--- /dev/null
+++ b/_cursor.ai/layout.doc/waiting.doc/CWaiting.doc.md
@@ -0,0 +1,107 @@
+# CWaiting 等待中
+
+## 功能说明
+
+基于 Taro UI 的模态框和活动指示器封装的等待提示组件,用于显示加载中或处理中的状态,支持显示标题和副标题。
+
+## 引用方式
+
+```js
+import CWaiting from '@components/layout/waiting';
+```
+
+## 组件参数
+
+- `isOpened` (Boolean,必选):是否显示等待框
+- `title` (String,可选):等待框标题
+- `sub` (String,可选):等待框副标题
+- `subType` (String,可选):副标题的颜色类型,默认值为 'warning'
+
+## 使用示例
+
+### 基础用法
+
+```html
+<template>
+  <view class="page">
+    <button @tap="evt => showWaiting()">显示等待框</button>
+    <CWaiting 
+      :isOpened="waitingOpened" 
+      title="正在加载中..." 
+    />
+  </view>
+</template>
+
+<script>
+import CWaiting from '@components/layout/waiting';
+
+export default {
+  components: {
+    CWaiting
+  },
+  data() {
+    return {
+      waitingOpened: false
+    }
+  },
+  methods: {
+    showWaiting() {
+      this.waitingOpened = true;
+      // 模拟3秒后完成加载
+      setTimeout(() => {
+        this.waitingOpened = false;
+      }, 3000);
+    }
+  }
+}
+</script>
+```
+
+### 带副标题的等待框
+
+```html
+<template>
+  <view class="page">
+    <button @tap="evt => showWaitingWithSub()">显示带副标题的等待框</button>
+    <CWaiting 
+      :isOpened="waitingOpened" 
+      title="正在处理中..." 
+      sub="请勿关闭应用" 
+    />
+  </view>
+</template>
+
+<script>
+import CWaiting from '@components/layout/waiting';
+
+export default {
+  components: {
+    CWaiting
+  },
+  data() {
+    return {
+      waitingOpened: false
+    }
+  },
+  methods: {
+    showWaitingWithSub() {
+      this.waitingOpened = true;
+      // 模拟处理过程
+      setTimeout(() => {
+        this.waitingOpened = false;
+      }, 3000);
+    }
+  }
+}
+</script>
+```
+
+## 注意事项
+
+1. 等待框无法通过点击遮罩层关闭,需要手动控制 `isOpened` 属性来关闭等待框
+2. 副标题默认使用警告色(橙色),通过 CSS 类 'm-text-warning' 实现
+3. 组件基于 Taro UI 的 AtModal 和 AtActivityIndicator,在样式上保持与 Taro UI 一致
+4. 建议在异步操作完成后,记得将 `isOpened` 设置为 false 关闭等待框
+5. 组件不包含超时处理,如需超时处理,需要在使用组件的页面自行实现
+
+<!-- 作者:Tevin --> 
\ No newline at end of file
diff --git a/_cursor.ai/link-rules.cmd b/_cursor.ai/link-rules.cmd
new file mode 100644
index 0000000..8240806
--- /dev/null
+++ b/_cursor.ai/link-rules.cmd
@@ -0,0 +1,29 @@
+@echo off
+set BASE_DIR=%~dp0..\..\..\
+cd %BASE_DIR% || (
+    echo Failed to change directory. Please verify if the path is correct.
+    goto :end
+)
+
+if not exist "src\components\_cursor.ai\rules" (
+    echo Source directory does not exist: src\components\_cursor.ai\rules
+    goto :end
+)
+
+if exist ".cursor\rules" (
+    echo Target directory already exists: .cursor\rules
+    choice /c YN /m "Delete existing directory and recreate the link? (Y/N)"
+    if errorlevel 2 goto :end
+    rmdir ".cursor\rules"
+)
+
+mklink /j ".cursor\rules" "src\components\_cursor.ai\rules"
+if %errorlevel% equ 0 (
+    echo Link created successfully!
+) else (
+    echo Failed to create link. Please check if you have administrator privileges.
+)
+
+:end
+
+pause
\ No newline at end of file
diff --git a/_cursor.ai/plugins.doc/echarts.doc/CECharts.doc.md b/_cursor.ai/plugins.doc/echarts.doc/CECharts.doc.md
new file mode 100644
index 0000000..4b9df5b
--- /dev/null
+++ b/_cursor.ai/plugins.doc/echarts.doc/CECharts.doc.md
@@ -0,0 +1,138 @@
+# CECharts 图表组件
+
+## 功能说明
+
+该组件是对百度ECharts的封装,用于在小程序环境中渲染各类图表,支持触摸交互和数据更新。支持柱状图、折线图、饼图等各种ECharts支持的图表类型,组件内部已优化tooltip显示和触摸事件处理。
+
+## 引用方式
+
+```js
+import { CECharts } from '@components/plugins/echarts';
+```
+
+## 组件参数
+
+- `canvasId` (String,默认值:随机生成):画布ID,用于标识图表实例
+- `disableTouch` (Boolean,默认值:false):是否禁用触摸交互
+- `onReady` (Function,可选):图表准备就绪的回调函数
+  - 参数:`chart` (Object) ECharts实例对象,可通过此对象设置图表配置和数据
+
+## 实例方法
+
+- `init`:初始化图表方法
+  - `callback` (Function,必填):初始化完成的回调函数,参数为 `(canvas, width, height, dpr)`
+- `canvasToTempFilePath`:将图表转为临时文件路径
+  - `opt` (Object,必填):微信小程序 canvasToTempFilePath 的参数对象
+
+## 使用示例
+
+### 基础用法
+
+```html
+<template>
+  <view class="page">
+    <view class="chart-container">
+      <CECharts
+        ref="salesChart"
+        :onReady="handleSalesChartReady"
+      />
+    </view>
+  </view>
+</template>
+
+<script>
+import { CECharts } from '@components/plugins/echarts';
+
+export default {
+  components: {
+    CECharts
+  },
+  data() {
+    return {
+      salesData: []
+    }
+  },
+  methods: {
+    // 图表准备就绪回调
+    handleSalesChartReady(chart) {
+      // 保存图表实例
+      this.chart = chart;
+      
+      // 设置图表配置
+      chart.setOption({
+        title: {
+          text: '月度销售统计',
+          left: 'center'
+        },
+        tooltip: {
+          trigger: 'axis'
+        },
+        grid: {
+          left: '3%',
+          right: '4%',
+          bottom: '3%',
+          containLabel: true
+        },
+        xAxis: {
+          type: 'category',
+          data: ['1月', '2月', '3月', '4月', '5月', '6月']
+        },
+        yAxis: {
+          type: 'value'
+        },
+        series: [{
+          name: '销量',
+          type: 'bar',
+          data: [10, 52, 200, 334, 390, 330]
+        }]
+      });
+    },
+    
+    // 更新图表数据
+    updateChartData(newData) {
+      if (!this.chart) return;
+      
+      this.chart.setOption({
+        series: [{
+          data: newData
+        }]
+      });
+    }
+  },
+  mounted() {
+    // 获取数据
+    setTimeout(() => {
+      const newData = [50, 120, 180, 80, 70, 110];
+      this.updateChartData(newData);
+    }, 2000);
+  }
+}
+</script>
+```
+
+### 保存图表为图片
+
+```js
+// 保存图表为图片
+saveChartAsImage() {
+  const _this = this;
+  this.$refs.salesChart.canvasToTempFilePath({
+    success(res) {
+      console.log('保存成功:', res.tempFilePath);
+      // 可以进一步使用 wx.saveImageToPhotosAlbum 保存到相册
+    },
+    fail(err) {
+      console.error('保存失败:', err);
+    }
+  });
+}
+```
+
+## 注意事项
+
+- 该组件暂时仅适用于小程序环境,文件名为 `CECharts.weapp.vue`
+- 在小程序端使用需要确保 canvas 的 type 属性设置为 "2d"
+- 小程序对 canvas 的性能有一定限制,复杂图表可能会有性能问题
+- 组件自动会处理触摸事件,支持图表交互
+- 组件已禁用了渐进式渲染(progressive: 0)以提高兼容性
+- 组件内置了默认的 tooltip 样式和位置优化逻辑 
\ No newline at end of file
diff --git a/_cursor.ai/plugins.doc/filter.doc/CFilter.doc.md b/_cursor.ai/plugins.doc/filter.doc/CFilter.doc.md
new file mode 100644
index 0000000..f2c67ad
--- /dev/null
+++ b/_cursor.ai/plugins.doc/filter.doc/CFilter.doc.md
@@ -0,0 +1,132 @@
+# CFilter 筛选组件
+
+## 功能说明
+
+该组件用于实现页面筛选功能,包含顶部筛选条和展开的更多筛选抽屉,支持多种筛选控件类型,包括选择器、日期范围、单选和输入框等。
+
+## 引用方式
+
+```js
+import { CFilter } from '@components/plugins/filter';
+```
+
+## 组件参数
+
+- `filterData` (Object,默认值:{}):筛选数据对象
+- `bar` (Object,默认值:{}):筛选横条项目配置
+  - `type` (String):控件类型,可选值有 'select'、'dateRange'、'input'
+  - `label` (String):显示的标签
+  - `name` (String):字段名称
+  - `cancelable` (Boolean):是否可取消选择,仅对select类型有效
+- `items` (Array,默认值:[]):筛选展开层项目列表配置
+  - 每项格式同bar,但type可选值多一个'radio'
+- `selectOptions` (Object,默认值:{}):各个项目的选项列表
+  - 格式为 `{ 字段名: [{label: '显示文本', value: '值'}] }`
+- `onChange` (Function,必填):筛选变化时的回调函数
+  - 参数:`filterData` (Object) 变更后的筛选数据对象
+
+## 实例方法
+
+组件没有对外暴露的实例方法
+
+## 使用示例
+
+### 基础用法
+
+```html
+<template>
+  <view class="page">
+    <CFilter
+      :filterData="filterData"
+      :bar="barConfig"
+      :items="itemsConfig"
+      :selectOptions="selectOptions"
+      :onChange="handleFilterChange"
+    />
+    
+    <!-- 列表内容 -->
+    <view class="list">
+      <!-- 根据筛选结果显示内容 -->
+    </view>
+  </view>
+</template>
+
+<script>
+import { CFilter } from '@components/plugins/filter';
+
+export default {
+  components: {
+    CFilter
+  },
+  data() {
+    return {
+      // 筛选数据
+      filterData: {
+        status: 1,
+        memberType: '',
+        dateRange: '',
+        keyword: ''
+      },
+      // 顶部筛选条配置
+      barConfig: {
+        type: 'select',
+        label: '状态',
+        name: 'status',
+        cancelable: false
+      },
+      // 更多筛选项配置
+      itemsConfig: [
+        {
+          type: 'select',
+          label: '会员类型',
+          name: 'memberType'
+        },
+        {
+          type: 'dateRange',
+          label: '创建日期',
+          name: 'dateRange'
+        },
+        {
+          type: 'input',
+          label: '关键字',
+          name: 'keyword'
+        }
+      ],
+      // 选项数据
+      selectOptions: {
+        status: [
+          { label: '全部', value: '' },
+          { label: '正常', value: 1 },
+          { label: '停用', value: 0 }
+        ],
+        memberType: [
+          { label: '全部', value: '' },
+          { label: '普通会员', value: 'normal' },
+          { label: 'VIP会员', value: 'vip' }
+        ]
+      }
+    }
+  },
+  methods: {
+    // 筛选变化回调
+    handleFilterChange(filterData) {
+      console.log('筛选条件变化:', filterData);
+      // 根据筛选条件获取数据
+      this.getListData(filterData);
+    },
+    
+    // 获取列表数据
+    getListData(params) {
+      // 请求数据
+    }
+  }
+}
+</script>
+```
+
+## 注意事项
+
+- 筛选条(bar)只能配置一个筛选项
+- 抽屉式筛选(items)可以配置多个筛选项
+- 每个筛选项的类型(type)必须与组件类型匹配
+- select和radio类型的选项必须在selectOptions中配置对应的选项数据 
\ No newline at end of file
diff --git a/_cursor.ai/plugins.doc/infiniteScroll.doc/CInfiniteScroll.doc.md b/_cursor.ai/plugins.doc/infiniteScroll.doc/CInfiniteScroll.doc.md
new file mode 100644
index 0000000..42f04ea
--- /dev/null
+++ b/_cursor.ai/plugins.doc/infiniteScroll.doc/CInfiniteScroll.doc.md
@@ -0,0 +1,91 @@
+# CInfiniteScroll 无限滚动组件
+
+## 功能说明
+
+该组件实现了移动端常见的下拉刷新和上拉加载更多功能,支持自动加载第一页和手动触发加载,适用于列表展示场景。内置了加载状态、空数据状态和加载完成状态的显示,使用简单便捷。
+
+## 引用方式
+
+```js
+import { CInfiniteScroll } from '@components/plugins/infiniteScroll';
+```
+
+## 组件参数
+
+- `autoInit` (Boolean,默认值:false):是否自动初始化(自动加载第一页)
+- `onLoadMore` (Function,必填):发起加载页面数据的回调函数
+  - `current` (Number):当前页页码
+  - `next` (Number):需要加载的页面页码
+  - `success` (Function):当加载成功后调用
+    - 参数:`{ pageTotal: Number }` 总页数
+  - `fail` (Function):加载失败后调用
+
+## 实例方法
+
+- `$initScroll`:初始化加载第一页数据
+- `$refresh`:重置并刷新数据
+  - `autoStart` (String,可选):当值为 'off' 时不会自动加载,其他值或不传时会立即加载
+
+## 使用示例
+
+### 基础用法
+
+```html
+<template>
+  <view class="page">
+    <CInfiniteScroll
+      ref="scrollList"
+      :autoInit="true"
+      :onLoadMore="handleLoadMore"
+    >
+      <view class="list-item" v-for="(item, index) in list" :key="index">
+        {{ item.name }}
+      </view>
+    </CInfiniteScroll>
+  </view>
+</template>
+
+<script>
+import { CInfiniteScroll } from '@components/plugins/infiniteScroll';
+import { $fetchCommon } from '@fetchers/FCommon';
+
+export default {
+  components: {
+    CInfiniteScroll
+  },
+  data() {
+    return {
+      list: []
+    }
+  },
+  methods: {
+    handleLoadMore({ current, next, success, fail }) {
+      $fetchCommon.getList({ page: next }).then(res => {
+        // 拼接数据
+        if (current === 0) {
+          this.list = res.list;
+        } else {
+          this.list = this.list.concat(res.list);
+        }
+        success({
+          pageTotal: res.pageTotal
+        });
+      }).catch(() => {
+        fail();
+      });
+    },
+    // 手动刷新列表
+    refreshList() {
+      this.$refs.scrollList.$refresh();
+    }
+  }
+}
+</script>
+```
+
+## 注意事项
+
+- 组件通过检测滚动位置自动触发加载更多功能
+- 下拉刷新功能仅在滚动到顶部时可用
+- 加载状态会自动管理,包括"加载中"、"没有更多了"和"暂无数据"等提示
+- 组件内部对 H5 和小程序环境做了适配,在不同平台上使用相同的 API 即可 
\ No newline at end of file
diff --git a/_cursor.ai/plugins.doc/qrcode.doc/CQRCode.doc.md b/_cursor.ai/plugins.doc/qrcode.doc/CQRCode.doc.md
new file mode 100644
index 0000000..2ba3a34
--- /dev/null
+++ b/_cursor.ai/plugins.doc/qrcode.doc/CQRCode.doc.md
@@ -0,0 +1,76 @@
+# CQRCode 二维码组件
+
+## 功能说明
+
+该组件用于在页面中生成二维码,支持在H5环境下保存二维码图片到本地,界面简洁直观。
+
+## 引用方式
+
+```js
+import { CQRCode } from '@components/plugins/qrcode';
+```
+
+## 组件参数
+
+- `content` (String,默认值:'http://www.aisim.cn'):二维码内容,通常为URL地址
+- `size` (Number,默认值:200):二维码尺寸,单位为像素
+- `margin` (Number,默认值:2):二维码边距大小
+- `downloadable` (Boolean,默认值:false):是否显示"保存到手机"按钮
+
+## 实例方法
+
+组件没有对外暴露的实例方法
+
+## 使用示例
+
+### 基础用法
+
+```html
+<template>
+  <view class="page">
+    <!-- 简单用法 -->
+    <CQRCode content="https://www.example.com" />
+  </view>
+</template>
+
+<script>
+import { CQRCode } from '@components/plugins/qrcode';
+
+export default {
+  components: {
+    CQRCode
+  }
+}
+</script>
+```
+
+### 带保存按钮的用法
+
+```html
+<template>
+  <view class="page">
+    <CQRCode 
+      content="https://www.example.com" 
+      :size="300"
+      :margin="4"
+      :downloadable="true"
+    />
+  </view>
+</template>
+
+<script>
+import { CQRCode } from '@components/plugins/qrcode';
+
+export default {
+  components: {
+    CQRCode
+  }
+}
+</script>
+```
+
+## 注意事项
+
+- 目前在H5环境中支持保存二维码图片到本地
+- 小程序环境下的保存功能尚未实现
+- 二维码内容变更时会自动重新渲染 
\ No newline at end of file
diff --git "a/_cursor.ai/prompts/\345\210\233\345\273\272\344\270\200\344\270\252\350\257\267\346\261\202.prompts.md" "b/_cursor.ai/prompts/\345\210\233\345\273\272\344\270\200\344\270\252\350\257\267\346\261\202.prompts.md"
new file mode 100644
index 0000000..6021b06
--- /dev/null
+++ "b/_cursor.ai/prompts/\345\210\233\345\273\272\344\270\200\344\270\252\350\257\267\346\261\202.prompts.md"
@@ -0,0 +1,79 @@
+# 指令:创建一个请求
+
+我们以会员信息为例新开请求
+
+## 第一步:添加请求数据JSON文件
+
+在 mocks 文件夹下新建数据文件 `getUserInfo.json`
+```
+src/public/static/项目名称/mocks/user/getUserInfo.json
+```
+
+内容为:
+```json
+{
+    "state": {
+        "code": 2000,
+        "msg": "OK"
+    },
+    "data": {
+    }
+}
+```
+
+
+## 第二步:在请求集中添加请求
+
+在 `src/fetchers` 文件夹下,以 F 开头的请求请求集中,添加一个独立的请求方法,方法名和 json 文件一样
+
+例如:在 `FUser.js` 中添加 `getUserInfo`
+```js
+class FUser extends Fetcher {
+    constructor() {
+        super({
+            urlPrefix: ['/api/user/', '/mini/'],
+        });
+    }
+
+    // 读取会员信息
+    getUserInfo(user) {
+        const url = this.spellURL('getUserInfo', 'User/Info');
+        const send = {
+            ...this.transKeyName('underline', user),
+        };
+        return this.post(url, send);
+    }
+
+}
+
+export const $fetchUser = new FUser();
+```
+
+如果创建一个全新的请求集,那么构造器的 urlPrefix 参数的第一个值为 `'/api/分类名/'`
+
+## 第三步:在数据控制器中调用请求
+
+在需要的需要的数据控制文件中:
+- 使用 `import` 引入需要的使用的请求集
+- 在类中,添加一个独立方法,调用对应的数据请求
+
+```js
+import { $fetchUser } from '@fetchers/FUser';
+
+export class PLogisSender extends Pilot {
+
+    // 加载用户详情
+    onLoadUserDetail(user) {
+        Taro.showLoading();
+        $fetchUser.getUserDetail(user)
+            .then(res => {
+                Taro.hideLoading();
+                if (!res) {
+                    return;
+                }
+                this.userDetail = res.detail;
+            });
+    }
+
+}
+```
diff --git "a/_cursor.ai/prompts/\345\210\233\345\273\272\344\270\200\344\270\252\351\241\265\351\235\242.prompts.md" "b/_cursor.ai/prompts/\345\210\233\345\273\272\344\270\200\344\270\252\351\241\265\351\235\242.prompts.md"
new file mode 100644
index 0000000..42781bf
--- /dev/null
+++ "b/_cursor.ai/prompts/\345\210\233\345\273\272\344\270\200\344\270\252\351\241\265\351\235\242.prompts.md"
@@ -0,0 +1,70 @@
+# 指令:创建一个页面
+
+我们以会员中心为例新开页面  
+
+## 第一步:创建界面文件夹
+在界面层的目录 `src/pages/某分类名/` 下新建页面文件夹 `userCenter`
+```
+src/pages/user/userCenter
+```
+
+## 第二步:创建界面配置文件
+在刚刚新建的文件夹下新建配置文件 `userCenter.config.js`  
+
+内容为:
+```js
+export default {
+    navigationBarTitleText: '会员中心',
+}
+```
+
+## 第三步:创建空白界面
+继续在刚刚新建的文件夹下新建界面文件 `userCenter.vue`
+
+内容参考文件 `src/components/_cursor.ai/rules/type-surface.mdc` 中的空白模版
+
+### 样式
+
+同时创建样式文件 `userCenter.scss`
+```css
+/**
+ * userCenter
+ * @author 作者
+ */
+
+@import "../../../components/common/sassMixin";
+
+.user-center {}
+```
+
+## 第四步:创建数据控制器
+在业务数据控制层的目录 `src/pilots/某分类名/` 下创建数据控制器 `PUserCenter.js`
+
+内容参考文件:`src/components/_cursor.ai/rules/type-pilot.mdc` 中的空白模版
+
+
+## 第五步:添加页面路由
+在路由文件 `src/app.config.js` 中,添加会员中心的路由
+
+```js
+export default {
+    pages: [
+        'pages/home/index/index',
+        // 添加会员中心
+        'pages/user/userCenter/userCenter',
+    ],
+};
+```
+
+## 第六步:添加首页入口
+在首页菜单配置文件 `src/fetchers/datas/menu.json` 文件中,在 `menu` 属性的数组中,添加一条数据
+
+```json
+{
+    "authId": 1,
+    "name": "会员中心",
+    "url": "/pages/user/userCenter/userCenter",
+    "icon": ""
+}
+```
+注意:`authId` 不要重复
diff --git "a/_cursor.ai/prompts/\346\233\264\346\226\260\345\205\254\345\205\261\347\273\204\344\273\266\346\226\207\346\241\243.prompts.md" "b/_cursor.ai/prompts/\346\233\264\346\226\260\345\205\254\345\205\261\347\273\204\344\273\266\346\226\207\346\241\243.prompts.md"
new file mode 100644
index 0000000..eed6f00
--- /dev/null
+++ "b/_cursor.ai/prompts/\346\233\264\346\226\260\345\205\254\345\205\261\347\273\204\344\273\266\346\226\207\346\241\243.prompts.md"
@@ -0,0 +1,61 @@
+# 更新公共组件文档
+
+## 第一步,检查组件
+
+### 根据组件路径,检查是否为公共组件
+
+检查当前组件路径,如果不在公共组件目录内,则不是公共组件,不适用本更新策略,任务跳过
+
+公共组件的三个目录:
+- src/components/forms
+- src/components/layout
+- src/components/plugins
+
+### 读取组件,检查是否为 Vue 组件
+
+根据组件内容,判断为是不是 Vue 组件,如果不是,任务跳过
+
+## 第二步,检查文档是否已经存在
+
+每一个公共组件,都有一份组件文档
+
+如果当前组件为:
+src/components/forms/checkbox/CCheckBox.vue
+
+那么它对应的文档为:
+src/components/_cursor.ai/forms.doc/checkbox.doc/CCheckBox.doc.md
+
+其规律为:
+- 组件的文档都在 src/components/_cursor.ai/ 文件夹下,有类似的目录结构
+- 组件文件夹 forms/ 对应文档文件夹 forms.doc/(名称增加 `.doc`)
+- 组件子文件夹 checkbox/ 对应文档子文件夹 checkbox.doc/(名称增加 `.doc`)
+- 组件文件 CCheckBox.vue 对应文档文件 CCheckBox.doc.md(名称增加 `.doc`,但扩展名不变)
+
+## 第三步,如果文档不存在,创建
+
+依照位置与命名规律,按照文档格式创建对应的组件文档
+
+## 第四步,如果文档已存在,更新文档
+
+读取文档内容,将组件功能与文档对比
+- 判断文档是否符合文档格式的要求,如果不符合,请按格式修改
+- 判断是否需要修剪已有内容和增加新内容,如果有,更新文档
+
+## 文档格式
+
+文档格式为markdown,每份组件需要包含一下项目:
+- 由组件文件名+组件中文名组成大标题
+- 功能说明
+- 引用方式
+- 组件参数
+    - 请使用列表形式,例如:- `paramName` (String,可选):参数说明
+    - 如果是可枚举的几个具体值,请以二级列表的形式说明每个值,例如:- `enumValue`:枚举值说明
+    - 如果是回调函数,请以二级列表的形式说明函数的参数和返回值,例如:- 参数 `paramName` (String,可选):参数说明
+- 实例方法
+    - 是指 methods 中,名称仅以 `$` 符号开头的方法,没有 `$` 可省略
+    - 如果方法有参数,请以二级列表形式说明方法的参数和返回值,例如:- 参数 `paramName` (String,可选):参数说明
+- 使用示例
+    - 如果组件有多种使用模式,请分别提供不同模式的示例
+- 注意事项
+    - 重要或需要注意的问题
+    - 特殊的技术点或使用场景
\ No newline at end of file
diff --git "a/_cursor.ai/prompts/\346\233\264\346\226\260\347\273\204\344\273\266\347\233\256\345\275\225.prompts.md" "b/_cursor.ai/prompts/\346\233\264\346\226\260\347\273\204\344\273\266\347\233\256\345\275\225.prompts.md"
new file mode 100644
index 0000000..0c4c375
--- /dev/null
+++ "b/_cursor.ai/prompts/\346\233\264\346\226\260\347\273\204\344\273\266\347\233\256\345\275\225.prompts.md"
@@ -0,0 +1,35 @@
+# 更新公共组件目录
+
+## 第一步,读取列表
+
+依次读取三个公共组件文件夹的文件列表
+- `src/components/_cursor.ai/forms.doc/`
+- `src/components/_cursor.ai/layout.doc/`
+- `src/components/_cursor.ai/plugins.doc/`
+
+## 第二步,读取目录文档
+
+公共组件目录文件路径为:
+`src/components/_cursor.ai/组件目录.md`
+
+请读取此目录的内容,找出目录中未收录的公共组件
+
+## 第三步,补充目录
+
+对于目录中没有收录的组件,请添加进来,格式为
+
+```
+- **组件英文名 组件中文名**  
+    功能说明  
+    [组件文档 »](组件文档地址)  
+    [组件代码 »](组件代码文件地址)
+```
+
+例如:
+```
+- **CAlert 弹窗**  
+    基于 Taro UI 的模态框(AtModal)封装的alert弹窗组件,支持Alert(提示)和Confirm(确认)两种模式  
+    [组件文档 »](/src/components/_cursor.ai/layout.doc/alert.doc/CAlert.doc.md)  
+    [组件代码 »](/src/components/layout/alert/CAlert.vue)
+```
+
diff --git "a/_cursor.ai/102-\345\274\200\345\217\221\350\247\204\350\214\203.md" b/_cursor.ai/rules/all-dev-specification.mdc
similarity index 74%
rename from "_cursor.ai/102-\345\274\200\345\217\221\350\247\204\350\214\203.md"
rename to _cursor.ai/rules/all-dev-specification.mdc
index c73d973..f02256a 100644
--- "a/_cursor.ai/102-\345\274\200\345\217\221\350\247\204\350\214\203.md"
+++ b/_cursor.ai/rules/all-dev-specification.mdc
@@ -1,39 +1,24 @@
+---
+description: 
+globs: 
+alwaysApply: true
+---
+
 # 开发规范
 
-- [开发规范](#开发规范)
-  - [规范宗旨](#规范宗旨)
-  - [命名问题](#命名问题)
-    - [命名需要具有实义](#命名需要具有实义)
-    - [文件命名](#文件命名)
-      - [界面层文件](#界面层文件)
-      - [数据控制层文件](#数据控制层文件)
-      - [组件文件](#组件文件)
-      - [请求文件](#请求文件)
-    - [样式命名](#样式命名)
-      - [界面样式](#界面样式)
-      - [组件样式](#组件样式)
-    - [JS 变量和属性的命名](#js-变量和属性的命名)
-      - [变量命名的特别约定](#变量命名的特别约定)
-    - [JS 方法的命名](#js-方法的命名)
-      - [在数据控制层](#在数据控制层)
-      - [在组件内](#在组件内)
-  - [书写问题](#书写问题)
-    - [JS 中的书写](#js-中的书写)
-      - [变量定义符](#变量定义符)
-      - [模版中的函数调用](#模版中的函数调用)
-    - [CSS 属性顺序](#css-属性顺序)
+## 开发规范宗旨
 
-## 规范宗旨
-
-**代码首先是给人读的,其次才是给机器运行**,所以让代码容易阅读是应尽的责任
-
-除了尽可能不写难懂的代码外,我们还需要尽量遵守统一的规范,来帮助我们更高效率的相互阅读代码
-
-## 命名问题
+**代码首先是给人读的,其次才是给机器运行**,所以让代码容易阅读是你应尽的责任  
+包括但不限于以下内容:
+- 给变量、函数命名时,需要具有实义
+- 避免使用难懂的语法或设计,用最简单的方式解决问题
+- 避免单块代码过长,拆分为多个更简短的函数或方法
+- 避免代码重复,通过封装函数、类或模块进行复用,封装遵守单一职责原则
+- 写注释应解释 ‌"为什么"‌ 而不仅仅是 ‌"做什么"‌
 
 ### 命名需要具有实义
 
-命名的核心原则是名称含有具体的实体含义  
+命名的原则是名称中有具体实体含义的词汇  
 
 比如没有实义的
 
@@ -49,111 +34,7 @@
 
 改进后,从函数名一看便知,这是商品被选中了以后的需要进行的操作,又因为具备了在同一个页面的唯一性,能帮我们快速获取信息,知道这是哪个业务的哪个环节,大幅提高阅读效率,这就是实义
 
-### 文件命名
-
-常用文件命名约定
-
-#### 界面层文件
-
-界面层文件(.vue、.scss),采用小驼峰命名
-
-```
-index.vue
-index.scss
-```
-
-#### 数据控制层文件
-
-数据控制层文件(.js),以固定前缀 P 开头,再接大驼峰
-
-```
-PIndex.js
-```
-
-数据层代码定义的名称,需要和文件名一致
-
-```js
-export class PIndex extends Pilot {}
-```
-
-#### 组件文件
-
-不论是公共组件还是页面子组件(.vue、.scss),都以固定前缀 C 开头,再接大驼峰
-
-```
-CMenu.vue
-CMenu.scss
-```
-
-组件代码定义的名称,需要和文件名一致
-
-```js
-// CMenu.vue 的组件名,必须是 CMenu
-export default {
-    name: 'CMenu',
-}
-```
-
-#### 请求文件
-
-请求层文件(.js),以固定前缀 F 开头,再接大驼峰
-
-```
-FCommon.js
-```
-
-请求集合的代码定义名称,需要和文件名一致
-
-```js
-// FCommon.js 的类名称,必须是 FCommon
-class FCommon extends Fetcher {}
-
-// FCommon.js 代表的类的实例名称,则是 $fetchCommon
-export const $fetchCommon = new FCommon();
-```
-
-### 样式命名
-
-样式名的命名,采用横杠连接
-
-```css
-.page-name {}
-```
-
-#### 界面样式
-
-任何一个界面必定包含众多样式,所以:
-
-* 最父级样式名固定,与界面名称一直
-* 中间层,需要以父级为前缀,接板块说明
-* 末端则可单名,且尽量不含实义
-
-```css
-/** 在界面 userList.vue 中,最父级样式名名称固定 **/
-.user-list {
-
-    /** 中间多层,以父级为前缀 **/
-    .user-list-title {
-
-        /** 末端可单名,尽量非实义 **/
-        .left,
-        .text,
-        .icon,
-        .sub,
-        .close {}
-    }
-}
-```
-
-#### 组件样式
-
-组件样式名必须已 `c-` 开头,最父级样式名必须与组件名挂钩
-
-例如,组件 CMenu.vue 中,最父级样式名必须是:
-
-```css
-.c-menu {}
-```
+## 常见命名要求
 
 ### JS 变量和属性的命名
 
@@ -178,6 +59,8 @@
 ```js
 // 允许 is 开头的变量名
 let isOpened = false;
+// 更好的命名
+let selectorOpened = false;
 ```
 
 **事件变量用 evt**  
@@ -300,9 +183,123 @@
 }
 ```
 
-## 书写问题
+### 样式命名
 
-书写规则都由编辑器自动格式化即可,这里主要说明非格式化的几点约定
+样式名的命名,采用横杠连接
+
+```css
+.page-name {}
+```
+
+#### 界面样式
+
+任何一个界面必定包含众多样式,所以:
+
+* 最父级样式名固定,与界面名称一直
+* 中间层,需要以父级为前缀,接板块说明
+* 末端则可单名,且尽量不含实义
+
+```css
+/** 在界面 userList.vue 中,最父级样式名名称固定 **/
+.user-list {
+
+    /** 中间多层,以父级为前缀 **/
+    .user-list-title {
+
+        /** 末端可单名,尽量非实义 **/
+        .left,
+        .text,
+        .icon,
+        .sub,
+        .close {}
+    }
+}
+```
+
+#### 组件样式
+
+组件样式名必须已 `c-` 开头,最父级样式名必须与组件名挂钩
+
+例如,组件 CMenu.vue 中,最父级样式名必须是:
+
+```css
+.c-menu {}
+```
+
+
+### 文件命名
+
+常用文件命名约定
+
+#### 界面层文件
+
+界面层文件(.vue、.scss),采用小驼峰命名
+
+```
+index.vue
+index.scss
+```
+
+#### 数据控制层文件
+
+数据控制器文件(.js),以固定前缀 P 开头,再接大驼峰
+
+```
+PIndex.js
+```
+
+数据层代码定义的名称,需要和文件名一致
+
+```js
+export class PIndex extends Pilot {}
+```
+
+#### 组件文件
+
+不论是公共组件还是页面子组件(.vue、.scss),都以固定前缀 C 开头,再接大驼峰
+
+```
+CMenu.vue
+CMenu.scss
+```
+
+组件代码定义的名称,需要和文件名一致
+
+```js
+// CMenu.vue 的组件名,必须是 CMenu
+export default {
+    name: 'CMenu',
+}
+```
+
+#### 请求文件
+
+请求层文件(.js),以固定前缀 F 开头,再接大驼峰
+
+```
+FCommon.js
+```
+
+请求集合的代码定义名称,需要和文件名一致
+
+```js
+// FCommon.js 的类名称,必须是 FCommon
+class FCommon extends Fetcher {}
+
+// FCommon.js 代表的类的实例名称,则是 $fetchCommon
+export const $fetchCommon = new FCommon();
+```
+
+## 常见书写要求
+
+### 基础书写要求
+
+例如:
+- 使用四个空格代替 tab 进行缩进(包括代码和文档)
+- 单行代码宽度最多100个字符
+- js 代码使用单引号
+
+更多规则请参考根目录 `.prettierrc` 文件
 
 ### JS 中的书写
 
@@ -333,17 +330,46 @@
 * 对于普通数据,如果明确要变更变量值,才使用 `let`
 * 对于引用数据,如果明确需要重新赋值一个引用对象,才使用 `let`
 
+#### 变量判断
+
+为了避免弱类型带来的bug追踪困难,变量判断需要使用恒等号,必须判断类型一致
+
+```js
+// 需要同时判断值和类型
+if (order.state === 1) {}
+```
+
 #### 模版中的函数调用
 
-模版中调用函数,必须显式的书写 evt 变量和箭头函数,即: `evt => fncName()`  
-我们把 Taro 自身组件视为普通元素,元素绑定事件使用 `@tap` 的方式,非元素皆是组件,组件使用 `:onClick` 的方式绑定
+- 模版中调用函数,为了便于阅读,必须显式的书写 evt 变量和箭头函数,即:  `evt => fncName()`,**这是规范要求,不是代码冗余**
+- 把 Taro 自身组件视为普通元素,元素绑定事件使用 `@tap` 的方式
+- 非元素皆是组件,组件使用 `:onClick` 的方式绑定
 
 例如:
 ```html
+<!-- 元素绑定事件使用 -->
 <view @tap="() => onOpenOrderDetail()"></view>
+<!-- 组件绑定事件使用 -->
 <CMenu :onItemClick="evt => onMenuItemClick(evt)" />
 ```
 
+#### 以 JSDoc 格式写方法注释
+
+公共代码中的方法都需要以 JSDoc 的格式写注释
+
+```js
+export class Tools {
+    /**
+     * 显示消息提示框
+     * @param {string} msg - 提示的消息内容
+     * @param {number} [duration=2000] - 提示框显示时长(毫秒)
+     * @param {boolean} [mask=false] - 是否显示透明蒙层,防止触摸穿透
+     */
+    static toast(msg, duration = 2000, mask = false) {
+    }
+}
+```
+
 ### CSS 属性顺序
 
 为了避免 css 属性写重复,请按如下顺序书写:
diff --git a/_cursor.ai/rules/all-project-info.mdc b/_cursor.ai/rules/all-project-info.mdc
new file mode 100644
index 0000000..d4b6cef
--- /dev/null
+++ b/_cursor.ai/rules/all-project-info.mdc
@@ -0,0 +1,128 @@
+---
+description: 
+globs: 
+alwaysApply: true
+---
+
+# 项目介绍
+
+## 工程介绍
+
+这是一套Web前端开发的工程文档,用于指导移动端(H5网页、混合App、小程序等)的开发
+
+## 技术栈
+
+- 语法框架:Vue(v2.5.0)
+- 工程框架:Taro(v3.2.13)
+- 显示框架:Taro-UI-Vue(v1.0.0-beta.10)
+- 样式:Sass
+
+说明:使用时,优先使用公共组件库的组件,其次是 Taro-UI-Vue 的组件,最后才是 Taro 本身的基础元素组件
+
+## 工程目录结构
+
+工程主要目录及其用途
+
+- root/(根目录)
+    - public/(静态资源目录)
+    - src/(开发源码目录)
+        - components/(公共资源目录)
+            - bases/(公共基类目录)
+            - common/(公共工具目录)
+            - forms/(公共表单组件目录)
+            - layout/(公共排版组件目录)
+            - plugins/(公共复杂组件目录)
+        - fetchers/(请求层目录)
+            - FName.js(请求集)
+        - pages/(界面层目录)
+            - pageGroup/(界面层分组目录)
+                - pageName/(界面层单页目录)
+                    - cmpt/(界面子组件目录)
+                        - CName.vue(子组件)
+                        - cName.scss(子组件样式)
+                    - page.vue(界面)
+                    - page.scss(界面样式)
+        - pilots/(数据控制层目录)
+            - _overall/(全局数据控制目录)
+            - pilotGroup/(数据控制层分组目录)
+                - mixin/(混合件目录)
+                    - MName.js(混合件)
+                - PName.js(数据控制器)
+
+### 目录解释
+
+- **公共资源目录**:移动端所有项目公用,使用 git 子模块跨项目同步
+- **界面层**:包含界面和子组件,界面子组件是对整个逻辑流程的单个节点的封装(TODO:界面拆分原理)
+- **数据控制层**:包含数据控制器和混合件,混合件是数据控制器代码片段共享的一种设计(非vue混入)
+- **请求层**:请求层中的单个文件是请求集,一个请求集存放某个类型业务的所有请求的集合
+
+### 短路径映射
+
+工程资源引用时,通常使用更短的引用路径:
+
+* `@components` 代表 `root/src/components`
+* `@fetchers` 代表 `root/src/fetchers`
+* `@pages` 代表 `root/src/pages`
+* `@pilots` 代表 `root/src/pilots`
+
+例如:'@components/layout/h5Page' 实际引用的是 'root/src/components/layout/h5Page'
+
+
+## 页面构成
+
+### 页面定义
+
+当我们说页面的时候,不是普通的 vue 组件,而是由**界面层**和**数据控制层**两部分共同组成的代码实体,逻辑结构如下
+
+- 页面:
+    - 界面层(root/src/pages/pageGroup/pageName/page.vue)
+        - 界面子组件(root/src/pages/pageGroup/pageName/cmpt/CName.vue)
+    - 数据控制层(root/src/pilots/pilotsGroup/PName.js)
+        - 请求层(root/src/fetchers/FName.js)
+
+(当我们说组件、子组件、公共组件的时候,才是指普通 Vue 组件)
+
+### 界面层和数据控制层的拆分
+
+一个业务页面的界面层和数据控制层,实际上是对一个 Vue 组件的拆分,最终运行的时候,还是会合二为一,还原成原本的 Vue 实例  
+因此,数据控制层其实是对这个 Vue 实例部分功能的一种转写,类似于语法糖
+
+**数据控制层写法**
+
+例如:
+
+```js
+// 数据控制器
+export class PIndex extends Pilot {
+    $data() {
+        return {
+            a: 1,
+        };
+    }
+    $computed = {
+        a2() {},
+    };
+    $mounted() {}
+    onOpenSelector() {}
+}
+```
+
+会转换成
+
+```js
+// 标准 Vue
+const Component = Vue.extend({
+    data() {
+        return {
+            a: 1,
+        };
+    },
+    computed: {
+        a2() {},
+    },
+    methods: {
+        onOpenSelector() {},
+    },
+    mounted() {},
+});
+```
\ No newline at end of file
diff --git a/_cursor.ai/rules/all-system-role.mdc b/_cursor.ai/rules/all-system-role.mdc
new file mode 100644
index 0000000..d0410d7
--- /dev/null
+++ b/_cursor.ai/rules/all-system-role.mdc
@@ -0,0 +1,21 @@
+---
+description: 
+globs: 
+alwaysApply: true
+---
+# 角色
+
+## 你是一名拥有10年经验的资深Web前端开发工程师
+- 对代码质量有严格的要求,代码语义清晰、简洁高效
+- 拥有丰富的开发实践,擅长编写易于使用和维护的组件,能够设计干净健壮的架构
+- 懂得遵守最小改动原则,尽量不破坏现有功能
+- 擅长编用 markdown 写技术文档,层次分明、齐全易懂
+
+## 你是一个重视需求分析的开发者
+- 善于从用户角度理解业务需求
+- 会主动发现需求中存在缺陷,并与用户讨论完善
+- 倾向于选择最简单的解决方案,避免过度设计
+
+## 你是一个熟悉液化气行业的专业人士
+- 了解液化气充装、配送、销售等业务流程
+- 了解会员、订单、气瓶、电子秤等资产管理相关内容
\ No newline at end of file
diff --git "a/_cursor.ai/201-\350\257\267\346\261\202\345\261\202\345\237\272\347\261\273Fetcher.md" b/_cursor.ai/rules/fit-base-fetcher.mdc
similarity index 78%
rename from "_cursor.ai/201-\350\257\267\346\261\202\345\261\202\345\237\272\347\261\273Fetcher.md"
rename to _cursor.ai/rules/fit-base-fetcher.mdc
index 5166145..20ee33f 100644
--- "a/_cursor.ai/201-\350\257\267\346\261\202\345\261\202\345\237\272\347\261\273Fetcher.md"
+++ b/_cursor.ai/rules/fit-base-fetcher.mdc
@@ -1,25 +1,10 @@
-# 请求层基类 Fetcher.js
+---
+description: 数据控制器基类,所有数据控制器都必须继承此类
+globs: 
+alwaysApply: false
+---
 
-- [请求层基类 Fetcher.js](#请求层基类-fetcherjs)
-  - [功能说明](#功能说明)
-  - [引用方法](#引用方法)
-  - [构造函数](#构造函数)
-  - [主要方法](#主要方法)
-    - [`spellURL(devSuffix, serSuffix)`](#spellurldevsuffix-sersuffix)
-    - [`get(url, data, options)`](#geturl-data-options)
-    - [`post(url, data, options)`](#posturl-data-options)
-    - [`query(type, url, data, options)`](#querytype-url-data-options)
-    - [`stringToCamel(str)`](#stringtocamelstr)
-    - [`stringToUnderline(str)`](#stringtounderlinestr)
-    - [`transKeyName(type, json)`](#transkeynametype-json)
-  - [请求的 options 配置](#请求的-options-配置)
-    - [`hostType` 主机类型](#hosttype-主机类型)
-    - [`silence` 静音请求](#silence-静音请求)
-  - [响应处理](#响应处理)
-    - [处理流程](#处理流程)
-    - [前端统一响应数据格式](#前端统一响应数据格式)
-    - [前端统一响应状态码](#前端统一响应状态码)
-  - [请求调用](#请求调用)
+# 请求层基类 Fetcher.js
 
 ## 功能说明
 
@@ -29,15 +14,14 @@
 ## 引用方法
 
 ```js
-import {
-    Fetcher
-} from '@components/bases/Fetcher';
+import { Fetcher } from '@components/bases/Fetcher';
 ```
 
 ## 构造函数
 
-构造函数接受一个配置对象 options 作为参数,包含如下属性:
-* **urlPrefix** 数组,包含两项,第一项为本地 Mock 的 URL 前缀,第二项为服务器接口的前缀
+构造函数接受一个配置对象作为参数,包含如下属性:
+
+- **urlPrefix** 数组,包含两项,第一项为本地 Mock 的 URL 前缀,第二项为服务器接口的前缀
 
 ```js
 class FCommon extends Fetcher {
@@ -133,7 +117,7 @@
 - `type` (String):请求类型(如 `'get'`、`'post'`)
 - `url` (String):请求的 URL 地址
 - `data` (Object,可选):请求参数
-- `options` (Object,可选):请求配置
+- `options` (Object,可选):请求配置(参照下文)
 
 **返回值**  
 - (Promise):返回请求结果的 Promise
@@ -195,7 +179,7 @@
 **注意事项**  
 - 支持嵌套对象的递归转换
 
-## 请求的 options 配置
+## 请求 query 的 options 配置
 
 ### `hostType` 主机类型
 
@@ -277,7 +261,7 @@
 }
 ```
 
-注意,为了保证接口数据的扩展性,data 只能接 Object 类型,禁止接其他类型
+注意,为了保证接口数据的扩展性,**data 只能接 Object 类型**,禁止接其他类型
 
 ### 前端统一响应状态码
 
@@ -294,23 +278,31 @@
 ```js
 import { Fetcher } from '@components/bases/Fetcher';
 
-class FCommon extends Fetcher {}
+// 请求集
+class FCommon extends Fetcher {
+    
+    getUserInfo(user) {
+        const url = this.spellURL('getUserInfo', 'User/info');
+        const send = {..user};
+        return this.post(url, send);
+    }
+
+}
 
 // 全局单例
 export const $fetchCommon = new FCommon();
 ```
 
 ```js
-import {
-    $fetchCommon
-} from '@fetchers/FCommon';
+import { $fetchCommon } from '@fetchers/FCommon';
 
-export class PPageName extends Pilot {
+// 数据控制器
+export class PUserDetail extends Pilot {
 
-    // 在数据控制层中,发请求示例
     onLoadUserInfo() {
         Taro.showLoading();
-        $fetchCommon.getUserInfo(this.userId)
+        // 调用请求集发请求示例
+        $fetchCommon.getUserInfo({uid: this.userId})
             .then(res => {
                 Taro.hideLoading();
                 if (!res) {
@@ -322,3 +314,5 @@
 
 }
 ```
+
+
diff --git "a/_cursor.ai/202-\346\225\260\346\215\256\346\216\247\345\210\266\345\261\202\345\237\272\347\261\273Pilot.md" b/_cursor.ai/rules/fit-base-pilot.mdc
similarity index 87%
rename from "_cursor.ai/202-\346\225\260\346\215\256\346\216\247\345\210\266\345\261\202\345\237\272\347\261\273Pilot.md"
rename to _cursor.ai/rules/fit-base-pilot.mdc
index 63bfadb..ef70d86 100644
--- "a/_cursor.ai/202-\346\225\260\346\215\256\346\216\247\345\210\266\345\261\202\345\237\272\347\261\273Pilot.md"
+++ b/_cursor.ai/rules/fit-base-pilot.mdc
@@ -1,18 +1,10 @@
-# 数据控制层基类 Pilot.js
+---
+description: 数据控制器基类,所有数据控制器都需要继承此类
+globs: 
+alwaysApply: false
+---
 
-- [数据控制层基类 Pilot.js](#数据控制层基类-pilotjs)
-  - [功能说明](#功能说明)
-  - [引用方法](#引用方法)
-  - [主要方法](#主要方法)
-    - [`createOptions(dataAdd)`](#createoptionsdataadd)
-    - [`transAssets(assets)`](#transassetsassets)
-      - [静态图片地址转换说明](#静态图片地址转换说明)
-  - [页面合并流程](#页面合并流程)
-    - [第一步:生成合并对象](#第一步生成合并对象)
-    - [第二步:实际合并](#第二步实际合并)
-  - [页面能力扩展](#页面能力扩展)
-    - [跨页面通讯](#跨页面通讯)
-    - [跨端通讯](#跨端通讯)
+# 数据控制层基类 Pilot.js
 
 ## 功能说明
 
@@ -25,9 +17,7 @@
 ## 引用方法
 
 ```js
-import {
-    Pilot
-} from '@components/bases/Pilot';
+import { Pilot } from '@components/bases/Pilot';
 ```
 
 ## 主要方法
@@ -159,9 +149,7 @@
 
 ```js
 // 引入界面层对应数据控制器
-import {
-    PPageName
-} from '@pilots/pilotGroup/PPageName';
+import { PPageName } from '@pilots/pilotGroup/PPageName';
 
 export default {
     name: 'PageName',
diff --git a/_cursor.ai/rules/rules01.technologyStack.md b/_cursor.ai/rules/rules01.technologyStack.md
deleted file mode 100644
index e69de29..0000000
--- a/_cursor.ai/rules/rules01.technologyStack.md
+++ /dev/null
diff --git a/_cursor.ai/rules/type-component.mdc b/_cursor.ai/rules/type-component.mdc
new file mode 100644
index 0000000..8d4918b
--- /dev/null
+++ b/_cursor.ai/rules/type-component.mdc
@@ -0,0 +1,57 @@
+---
+description: 
+globs: src/pages/**/**/cmpt/*.vue,src/components/**/**/*.vue
+alwaysApply: false
+---
+
+# 界面子组件&公共组件
+
+界面子组件与公共组件,就是一个普通 Vue 组件
+
+## 子组件空白模板
+
+```html
+/**
+ * CExample - 示范组件
+ * @author Tevin
+ */
+
+<template>
+    <view class="c-example">
+        <!-- 组件内容 -->
+        <AtButton
+            type="primary"
+            size="small"
+            :onClick="evt => handleOpen()"
+        >示例按钮</AtButton>
+    </view>
+</template>
+
+<script>
+import Taro from '@tarojs/taro';
+import { AtButton } from 'taro-ui-vue';
+import './cExample.scss';
+
+export default {
+    name: 'CExample',
+    components: {
+        AtButton,
+    },
+    props: {
+        onOpened: Function,
+    },
+    data() {
+        return {
+        };
+    },
+    computed: {
+    },
+    methods: {
+        handleOpen() {
+            this.onOpened();
+        }
+    },
+    mounted() {},
+};
+</script>
+```
diff --git a/_cursor.ai/rules/type-fetchers.mdc b/_cursor.ai/rules/type-fetchers.mdc
new file mode 100644
index 0000000..babdf7e
--- /dev/null
+++ b/_cursor.ai/rules/type-fetchers.mdc
@@ -0,0 +1,38 @@
+---
+description: 
+globs: src/fetchers/F*.js
+alwaysApply: false
+---
+
+# 请求集
+
+## 请求集空白模板
+
+```js
+/**
+ * FCommon - 公用请求集
+ * @author 作者
+ */
+
+import { Fetcher } from '@components/bases/Fetcher';
+
+class FCommon extends Fetcher {
+
+    constructor() {
+        super({
+            // url前缀(本地路径, 服务器路径)
+            urlPrefix: ['/api/common/', '/serverPath/'],
+        });
+    }
+
+    // 读取页面详情
+    getPageDetail() {
+        const url = this.spellURL('getPageDetail', 'page/Detail');
+        const send = {};
+        return this.post(url, send);
+    }
+
+}
+
+export const $fetchCommon = new FCommon();
+```
diff --git a/_cursor.ai/rules/type-pilot.mdc b/_cursor.ai/rules/type-pilot.mdc
new file mode 100644
index 0000000..96010c5
--- /dev/null
+++ b/_cursor.ai/rules/type-pilot.mdc
@@ -0,0 +1,47 @@
+---
+description: 
+globs: src/pilots/**/P*.js
+alwaysApply: false
+---
+
+# 数据控制器
+
+## 数据控制器空白模板
+
+```js
+/**
+ * PPageName - 页面名称
+ * @author 作者
+ */
+
+import Taro from '@tarojs/taro';
+import { Pilot } from '@components/bases/Pilot';
+import { $fetchCommon } from '@fetchers/FCommon';
+
+export class PPageName extends Pilot {
+
+    $data() {
+        return {};
+    }
+
+    $mounted() {
+        this.onLoadDataResource();
+    }
+
+    // 加载用户详情
+    onLoadDataResource() {
+        Taro.showLoading();
+        $fetchCommon.getPageDetail()
+            .then(res => {
+                Taro.hideLoading();
+                if (!res) {
+                    return;
+                }
+                // do something
+            });
+    }
+
+}
+```
+
+说明:请求异常由请求层的基类自动处理,数据控制层跳过错误的逻辑,只处理请求成功的后续业务
\ No newline at end of file
diff --git a/_cursor.ai/rules/type-surface.mdc b/_cursor.ai/rules/type-surface.mdc
new file mode 100644
index 0000000..a501c45
--- /dev/null
+++ b/_cursor.ai/rules/type-surface.mdc
@@ -0,0 +1,43 @@
+---
+description: 
+globs: src/pages/**/**/*.vue
+alwaysApply: false
+---
+
+# 界面
+
+## 界面空白模板
+
+```html
+/**
+* pageName - 页面名称
+* @author 作者
+*/
+
+<template>
+    <CPage>
+        <CNavBar title="页面名称" />
+        <CContent class="page-name">
+            <!-- 页面内容 -->
+        </CContent>
+    </CPage>
+</template>
+
+<script>
+import Taro from '@tarojs/taro';
+import {} from 'taro-ui-vue';
+import { PPageName } from '@pilots/pilotGroup/PPageName';
+import { CPage, CContent, CNavBar } from '@components/layout/h5Page';
+import './pageName.scss';
+
+export default {
+    name: 'PageName',
+    components: {},
+    ...new PPageName().createOptions(),
+};
+</script>
+```
+
+说明:
+- H5 界面需要 CPage、CContent、CNavBar 这三个排版组件作为页面的基础布局(在小程序中则不需要)
+
diff --git "a/_cursor.ai/\345\267\245\344\275\234\345\205\261\350\257\206.md" "b/_cursor.ai/\345\267\245\344\275\234\345\205\261\350\257\206.md"
new file mode 100644
index 0000000..f0135bf
--- /dev/null
+++ "b/_cursor.ai/\345\267\245\344\275\234\345\205\261\350\257\206.md"
@@ -0,0 +1,138 @@
+# 前端工作共识
+
+尽管我们来自五湖四海,有着各自不同的编码习惯,但现在我们聚集在一起组成了一个团队。为了使团队合作更加流畅,减少沟通成本和内耗,我们需要在以下几个方面达成共识。
+
+## 1. 代码首先是给人读的,其次才是给机器运行
+
+团队开发与个人开发最大的区别在于:你身处一个团队中,大家需要相互配合。因此,**让代码容易阅读是你应尽的责任**。
+
+### 1.1 代码命名必须有实体意义
+
+> 好的代码,就像阅读小说一样流畅自然,看到哪里就能理解到哪里,是一种愉悦的体验,而不是像侦探破案一样需要推理猜测。
+
+要实现良好的阅读体验,代码命名必须包含与业务相关的真实实体名词:
+
+| 改前             | 改后                   | 意义               | 实体词    |
+| :--------------- | :--------------------- | :----------------- | :-------- |
+| onValueChange    | **onNoteValueChange**  | 备注的值改变       | note      |
+| onSelectChange   | **onFillSelectChange** | 充装记录的选择变化 | fill      |
+| onSelectedChange | **onSpecSelectChange** | 充装规格的选择变化 | spec      |
+| onItemChange     | **onPriceTypeChange**  | 价格类型变化       | priceType |
+
+这样的命名方式带来两个显著好处:
+1. 做无关模块开发时可以快速跳过不相关代码
+2. 做相关模块开发时一眼就能确定要查看的代码
+
+同时,让实体名词承担功能表述的作用,能让代码维护更依赖阅读而不是记忆,**极大减轻记忆负担**
+
+### 1.2 设计良好的模块与分层结构
+
+优秀的代码结构应该是有序且层次分明的,而非杂乱无章的流水账。良好的模块与分层设计能帮助我们更高效地掌控和阅读代码:
+
+#### 1.2.1 显示与业务分离
+将显示层与业务层清晰分开,各司其职:
+- 显示层:专注于信息呈现和用户交互
+- 业务层:专注于数据处理和业务逻辑
+
+这种分离使我们能快速定位问题所在——是界面问题还是数据问题,一目了然
+
+#### 1.2.2 主流程与次要操作分层
+对于复杂的操作流程,我们应将各个操作步骤封装为独立组件:
+- 主流程代码:保持简洁明了,仅包含关键流程和组件引用
+- 子组件:承担具体操作细节,各自负责单一职责
+
+这样设计后,主流程代码变得清晰易读,概览全局更加轻松。而当需要关注某个具体步骤时,只需查看相应的子组件即可,无需关注其他部分,大大提高了代码的掌控效率
+
+#### 1.2.3 公共代码复用
+模块化设计使代码复用变得自然而简单:
+- 通用功能抽离为独立公共组件
+- 跨页面的相似逻辑统一封装子组件
+- 跨项目公共资源共享,减轻决策负担
+
+这不仅减少了代码冗余,还提高了开发效率和代码质量
+
+## 2. 思考先行,开发随后
+
+### 2.1 理解清楚需求再动手
+
+由于我们的需求文档通常由老板和总监编写,没有专职人员完善需求细节,因此某些需求描述可能比较模糊  
+这种情况下,如果对业务理解不深,很容易导致开发的功能与实际需求不一致,最终导致需要推倒重来
+
+因此,我们需要在开发过程中不断积累对业务的理解,至少要达到能发现需求歧义的程度  
+
+有歧义是正常的,老板和总监对业务太熟悉了,往往会自然而然地认为某些理解是理所当然的    
+而对业务不熟悉的人,从需求文字字面出发,从而可能产生不同理解
+
+发现歧义时,请及时咨询我或旭诚,问清楚具体要求,一定要完全理解需求后再开始开发
+
+### 2.2 设计清晰方案再动手
+
+除了业务需求,在开发前还应该梳理清楚技术形式、模块拆分和实现方式,以最简洁的方案实现需求  
+切忌盲目开工,为求速度而书写毫无章法的代码
+
+如果不重视工程质量,因为前端代码过于灵活,一段时间后代码混乱到无法维护了,就被迫需要重构,我们应该避免这种事情发生
+
+只关注结果产量而不重视工程质量,这种代码在代码审查中一旦发现,就会被要求返工重写
+
+## 3. 用户体验是工作的一部分
+
+用户体验是我们前端开发者需要主动思考的问题,这是我们工作的重要组成部分
+
+我们公司的用户体验价值观是:**宁可技术实现复杂一些,也要让用户操作尽可能简单**  
+
+这不仅仅是口号,我们有着深入的实践经验:
+
+### 3.1 前端技术密集型案例
+
+我们电子秤开票界面,有个支持全键盘操作表格,有众多客户反馈,我们经过讨论确认后,专门开发的用户体验改进功能
+
+这个表格看似简单,用起来也简单,这正是我们的目标  
+
+但在技术层面,它是表格和表单的复合体,支持表格回车自动加行、方向键自由切换不同组件的焦点,以及表单验证等,集众多复杂功能于一体
+
+### 3.2 业务复杂型案例
+
+建档 app 中的"气瓶制造单位"选项  
+用户看到的只是一个普通下拉选框,旁边有个【管理】按钮可以增减选项内容,功能表面上看是很简单的
+
+但实际上,选项内容的变更需在同公司多个手机间同步,且这些厂家名称没有数据 ID,只能通过文字精确匹配  
+同时,输入名称必须符合工商注册名称,不能使用口语化的俗称,否则档案上传监管平台会通不过  
+还有,允许客户删除他们不需要的选项,仅从需要的厂家中选(对于新客户,支持一键恢复全国所有厂家,然后再慢慢删)
+
+这种复杂性对用户是完全透明的
+
+## 4. 拥抱 AI
+
+### 4.1 价值重塑
+
+当今世界正在被 AI 技术逐步重构,在这场技术变革浪潮中,提示词工程师已成为不可或缺的关键角色
+
+这并不意味着我们过去学习的技术知识变得无用,提示词工程师需要承担起工程建设的全部责任  
+当项目出现问题时,责任不在于 AI 而在指导 AI 的工程师,这正是工程师价值的核心所在
+
+同时,我们开发的产品是为人服务的  
+无论 Agent 多么智能,它都无法和真实的人那样体验产品,因此我们需要清晰地指导 AI 完成什么任务,告诉它做好了没,确保产品能够满足人的需求
+
+### 4.2 开发流程中的应用
+
+在代码生成方面,AI 能快速生成组件、功能、工作流程,但核心业务逻辑仍需人工审核  
+
+代码质量审查上,AI 能检查潜在bug、发现安全隐患、提示缺失注释,全方位提升代码质量标准
+
+文档编写与维护中,AI 协助编写各类文档,保证完整性和一致性,减轻维护负担  
+
+### 4.3 辅助开发的基本原则
+
+首先,我们需要了解 AI 的能力边界  
+AI 工具虽然强大但并非万能,我们需要理解它的优势和局限性。它在代码生成、问题诊断、知识获取等方面可以发挥巨大作用,但创造性设计、用户体验把控和业务理解仍然需要人类的专业判断
+
+其次,我们应该提高提示词工程能力  
+良好的提示词能让 AI 输出更准确、更符合项目需求的结果。学会如何结构化描述问题、提供足够上下文、明确说明需求和约束,是高效使用 AI 的关键技能
+
+最后,我们必须保持技术掌控和结果的主导权  
+AI 只是工具而非替代品。对生成的代码需要保持审查和理解,确保它符合我们的架构和规范,保持对代码的掌控力和理解力是开发者的基本要求
+
+### 4.4 调整心态,面向未来
+
+拥抱 AI 不是简单地使用工具,而是重新思考我们的工作方式和价值定位  
+在这个转变过程中,持续学习、开放心态和职业成长将是我们适应新时代的关键要素
diff --git "a/_cursor.ai/\346\226\207\346\241\243\350\257\264\346\230\216.md" "b/_cursor.ai/\346\226\207\346\241\243\350\257\264\346\230\216.md"
new file mode 100644
index 0000000..3515ffc
--- /dev/null
+++ "b/_cursor.ai/\346\226\207\346\241\243\350\257\264\346\230\216.md"
@@ -0,0 +1,47 @@
+# 文件夹介绍
+
+## 1. rules 文件夹
+
+rules 是指 AI 根据一定条件自动读取的工作环境设定,是我们控制项目代码生成质量的重要手段
+
+### 1.1 规则类型:全局使用 `Always` 
+
+所有的聊天(Agent、Ask、Edit)和 ctrl+k 编辑,都会参考此规则生成代码
+
+- [系统角色](/src/components/_cursor.ai/rules/all-system-role.mdc)
+- [项目介绍](/src/components/_cursor.ai/rules/all-project-info.mdc)
+- [开发规范](/src/components/_cursor.ai/rules/all-dev-specification.mdc)
+
+### 1.2 规则类型:按路径匹配 `Auto-Attached`
+
+当文件名称或路径匹配上时,会参考此规则生成代码
+
+- [请求集](/src/components/_cursor.ai/rules/type-fetchers.mdc)
+- [数据控制器](/src/components/_cursor.ai/rules/type-pilot.mdc)
+- [界面](/src/components/_cursor.ai/rules/type-surface.mdc)
+- [子组件&公共组件](/src/components/_cursor.ai/rules/type-component.mdc)
+
+### 1.3 规则类型:自主决定 `Agent-Requested`
+
+在 Agent 模式下,由 AI 根据 Description 的文字描述,自主决定是否需要参考此规则生成代码  
+非 Agent 模式需要我们自己 @ 此规则才能生效
+
+- [请求集基类](/src/components/_cursor.ai/rules/fit-base-fetcher.mdc)
+- [数据控制器基类](/src/components/_cursor.ai/rules/fit-base-pilot.mdc)
+- 表单验证规则
+
+## 2. prompts 文件夹
+
+prompts 存放我们主动提出的指令  
+和我们在聊天窗口要求 ai 完成工作一样,就是对需要经常执行的有具体要求的操作,存下来方便反复使用
+
+## 3. 文档文件夹
+
+公共组件库组件对应的文档
+
+| 文档目录      | 对应的组件目录          |
+| ------------- | ----------------------- |
+| `common.doc`  | src/components/common/  |
+| `forms.doc`   | src/components/forms/   |
+| `layout.doc`  | src/components/layout/  |
+| `plugins.doc` | src/components/plugins/ |
\ No newline at end of file
diff --git "a/_cursor.ai/\347\273\204\344\273\266\347\233\256\345\275\225.md" "b/_cursor.ai/\347\273\204\344\273\266\347\233\256\345\275\225.md"
new file mode 100644
index 0000000..db3bd9d
--- /dev/null
+++ "b/_cursor.ai/\347\273\204\344\273\266\347\233\256\345\275\225.md"
@@ -0,0 +1,176 @@
+# 公共组件目录
+
+移动端全部公共组件目录
+
+## 1. 表单类组件
+
+### 1.1 输入控件
+
+- **CInput 文本输入框**  
+    基础的文本输入框组件,用于在表单中收集用户的文本输入  
+    [组件文档 »](/src/components/_cursor.ai/forms.doc/input.doc/CInput.doc.md)  
+    [组件代码 »](/src/components/forms/input/CInput.vue)  
+
+- **CInputPhoneCode 手机验证码输入框**  
+    带验证码功能的手机号输入组件  
+    [组件文档 »](/src/components/_cursor.ai/forms.doc/input.doc/CInputPhoneCode.doc.md)  
+    [组件代码 »](/src/components/forms/input/CInputPhoneCode.vue)  
+
+- **CInputScanCode 扫码输入框**  
+    带扫码功能的输入框组件  
+    [组件文档 »](/src/components/_cursor.ai/forms.doc/input.doc/CInputScanCode.doc.md)  
+    [组件代码 »](/src/components/forms/input/CInputScanCode.vue)  
+
+- **CInputExpressCode 快递单号输入框**  
+    快递单号输入组件  
+    [组件文档 »](/src/components/_cursor.ai/forms.doc/input.doc/CInputExpressCode.doc.md)  
+    [组件代码 »](/src/components/forms/input/CInputExpressCode.vue)  
+
+- **CTextarea 多行文本输入**  
+    多行文本输入组件  
+    [组件文档 »](/src/components/_cursor.ai/forms.doc/textarea.doc/CTextarea.doc.md)  
+    [组件代码 »](/src/components/forms/textarea/CTextarea.vue)  
+
+### 1.2 选择控件
+
+- **CSelect 选择器**  
+    下拉选择组件  
+    [组件文档 »](/src/components/_cursor.ai/forms.doc/select.doc/CSelect.doc.md)  
+    [组件代码 »](/src/components/forms/select/CSelect.vue)  
+
+- **CDatePicker 日期选择器**  
+    日期选择组件  
+    [组件文档 »](/src/components/_cursor.ai/forms.doc/datePicker.doc/CDatePicker.doc.md)  
+    [组件代码 »](/src/components/forms/datePicker/CDatePicker.vue)  
+
+- **CChinaArea 中国区域选择器**  
+    中国省市区选择器组件  
+    [组件文档 »](/src/components/_cursor.ai/forms.doc/chinaArea.doc/CChinaArea.doc.md)  
+    [组件代码 »](/src/components/forms/chinaArea/CChinaArea.vue)  
+
+- **CImagePicker 图片选择器**  
+    图片上传选择组件  
+    [组件文档 »](/src/components/_cursor.ai/forms.doc/imagePicker.doc/CImagePicker.doc.md)  
+    [组件代码 »](/src/components/forms/imagePicker/CImagePicker.vue)  
+
+### 1.3 数值控件
+
+- **CNumberStep 数字步进器**  
+    数字加减步进器组件  
+    [组件文档 »](/src/components/_cursor.ai/forms.doc/numberStep.doc/CNumberStep.doc.md)  
+    [组件代码 »](/src/components/forms/numberStep/CNumberStep.vue)  
+
+- **CNumberValve 数字阀值**  
+    数字阀值设置组件  
+    [组件文档 »](/src/components/_cursor.ai/forms.doc/numberValve.doc/CNumberValve.doc.md)  
+    [组件代码 »](/src/components/forms/numberValve/CNumberValve.vue)  
+
+### 1.4 状态控件
+
+- **CCheckbox 复选框**  
+    复选框组件  
+    [组件文档 »](/src/components/_cursor.ai/forms.doc/checkbox.doc/CCheckbox.doc.md)  
+    [组件代码 »](/src/components/forms/checkbox/CCheckbox.vue)  
+
+- **CSwitch 开关**  
+    开关切换组件  
+    [组件文档 »](/src/components/_cursor.ai/forms.doc/switch.doc/CSwitch.doc.md)  
+    [组件代码 »](/src/components/forms/switch/CSwitch.vue)  
+
+### 1.5 特殊表单组件
+
+- **CForm 表单**  
+    表单容器组件,用于管理表单数据和验证  
+    [组件文档 »](/src/components/_cursor.ai/forms.doc/form.doc/CForm.doc.md)  
+    [组件代码 »](/src/components/forms/form/CForm.vue)  
+
+- **CUserSignature 用户签名**  
+    用户手写签名组件  
+    [组件文档 »](/src/components/_cursor.ai/forms.doc/userSignature.doc/CUserSignature.doc.md)  
+    [组件代码 »](/src/components/forms/userSignature/CUserSignature.vue)  
+
+## 2. 排版类组件
+
+### 2.1 容器组件
+
+- **CH5Page H5页面**  
+    H5页面容器组件  
+    [组件文档 »](/src/components/_cursor.ai/layout.doc/h5Page.doc/CH5Page.doc.md)  
+    [组件代码 »](/src/components/layout/h5Page/CH5Page.vue)  
+
+- **CCard 卡片**  
+    卡片容器组件  
+    [组件文档 »](/src/components/_cursor.ai/layout.doc/card.doc/CCard.doc.md)  
+    [组件代码 »](/src/components/layout/card/CCard.vue)  
+
+- **CDrawer 抽屉**  
+    抽屉组件  
+    [组件文档 »](/src/components/_cursor.ai/layout.doc/drawer.doc/CDrawer.doc.md)  
+    [组件代码 »](/src/components/layout/drawer/CDrawer.vue)  
+
+### 2.2 导航组件
+
+- **CNavCustomBar 自定义导航栏**  
+    自定义顶部导航栏组件  
+    [组件文档 »](/src/components/_cursor.ai/layout.doc/navCustomBar.doc/CNavCustomBar.doc.md)  
+    [组件代码 »](/src/components/layout/navCustomBar/CNavCustomBar.vue)  
+
+- **CHomeNav 首页导航**  
+    首页导航组件  
+    [组件文档 »](/src/components/_cursor.ai/layout.doc/homeNav.doc/CHomeNav.doc.md)  
+    [组件代码 »](/src/components/layout/homeNav/CHomeNav.vue)  
+
+- **CAnchor 锚点**  
+    页面锚点组件  
+    [组件文档 »](/src/components/_cursor.ai/layout.doc/anchor.doc/CAnchor.doc.md)  
+    [组件代码 »](/src/components/layout/anchor/CAnchor.vue)  
+
+### 2.3 交互提示组件
+
+- **CAlert 弹窗**  
+    基于 Taro UI 的模态框封装的alert弹窗组件  
+    [组件文档 »](/src/components/_cursor.ai/layout.doc/alert.doc/CAlert.doc.md)  
+    [组件代码 »](/src/components/layout/alert/CAlert.vue)  
+
+- **CWaiting 等待提示**  
+    加载等待提示组件  
+    [组件文档 »](/src/components/_cursor.ai/layout.doc/waiting.doc/CWaiting.doc.md)  
+    [组件代码 »](/src/components/layout/waiting/CWaiting.vue)  
+
+### 2.4 数据展示组件
+
+- **CNumerical 数值显示**  
+    数值显示组件  
+    [组件文档 »](/src/components/_cursor.ai/layout.doc/numerical.doc/CNumerical.doc.md)  
+    [组件代码 »](/src/components/layout/numerical/CNumerical.vue)  
+
+- **CDescription 描述列表**  
+    描述列表组件  
+    [组件文档 »](/src/components/_cursor.ai/layout.doc/description.doc/CDescription.doc.md)  
+    [组件代码 »](/src/components/layout/description/CDescription.vue)  
+
+## 3. 复杂插件类组件
+
+### 3.1 数据可视化
+
+- **CEcharts 图表**  
+    基于 Echarts 的图表组件  
+    [组件文档 »](/src/components/_cursor.ai/plugins.doc/echarts.doc/CEcharts.doc.md)  
+    [组件代码 »](/src/components/plugins/echarts/CEcharts.vue)  
+
+- **CQrcode 二维码**  
+    二维码生成组件  
+    [组件文档 »](/src/components/_cursor.ai/plugins.doc/qrcode.doc/CQrcode.doc.md)  
+    [组件代码 »](/src/components/plugins/qrcode/CQrcode.vue)  
+
+### 3.2 数据交互
+
+- **CFilter 筛选器**  
+    数据筛选器组件  
+    [组件文档 »](/src/components/_cursor.ai/plugins.doc/filter.doc/CFilter.doc.md)  
+    [组件代码 »](/src/components/plugins/filter/CFilter.vue)  
+
+- **CInfiniteScroll 无限滚动**  
+    无限滚动加载组件  
+    [组件文档 »](/src/components/_cursor.ai/plugins.doc/infiniteScroll.doc/CInfiniteScroll.doc.md)  
+    [组件代码 »](/src/components/plugins/infiniteScroll/CInfiniteScroll.vue)  
diff --git a/forms/checkbox/CCheckBox.vue b/forms/checkbox/CCheckBox.vue
index ef4718d..aa9c01a 100644
--- a/forms/checkbox/CCheckBox.vue
+++ b/forms/checkbox/CCheckBox.vue
@@ -1,5 +1,8 @@
 /**
  * CCheckBox
+ * 复选框组件,用于在表单中提供多选或单选功能
+ * 支持两种显示模式:直接显示模式和弹窗选择模式
+ * 支持两种选择类型:多选和单选
  * @author Tevin
  */
 
@@ -142,9 +145,8 @@
                         return;
                     }
                     const selectedIndex = this.options.findIndex(
-                        opt => opt.value === item
+                        opt => opt.value === item,
                     );
-                    console.log(item, selectedIndex);
                     if (selectedIndex < 0) {
                         return;
                     }
@@ -155,7 +157,7 @@
             // 单选
             else if (this.boxType === 'radio') {
                 const next = evt[evt.length - 1];
-                const selectedIndex = this.options.find(opt => opt.value === item);
+                const selectedIndex = this.options.findIndex(opt => opt.value === next);
                 if (selectedIndex < 0) {
                     this.itemRes.onChange('');
                 } else {
diff --git a/forms/chinaArea/CChinaArea.vue b/forms/chinaArea/CChinaArea.vue
index d16511d..faadcf5 100644
--- a/forms/chinaArea/CChinaArea.vue
+++ b/forms/chinaArea/CChinaArea.vue
@@ -1,5 +1,8 @@
 /**
  * CChinaArea - 表单项,中国地址三级联动
+ * 中国地区选择器组件,用于在表单中选择省市区地址
+ * 内置完整的中国行政区划数据,支持多级联动选择
+ * 支持自动通过地理定位获取省市区
  * @author Tevin
  */
 
diff --git a/forms/datePicker/CDatePicker.vue b/forms/datePicker/CDatePicker.vue
index 34bdb00..dd2c173 100644
--- a/forms/datePicker/CDatePicker.vue
+++ b/forms/datePicker/CDatePicker.vue
@@ -1,5 +1,8 @@
 /**
  * CDatePicker - 选择日期范围操作
+ * 日期选择组件,用于在表单中选择日期或日期范围
+ * 支持三种选择模式:日期选择、日期时间选择和日期范围选择
+ * 可限制日期选择范围,支持清除功能和只读模式
  * @author Tevin
  */
 
diff --git a/forms/form/CForm.vue b/forms/form/CForm.vue
index 944feef..7245951 100644
--- a/forms/form/CForm.vue
+++ b/forms/form/CForm.vue
@@ -1,5 +1,8 @@
 /**
  * CForm - 表单套装组件,套件的主体
+ * 表单容器组件,用于管理表单数据、处理表单验证和提交
+ * 支持自动滚动到错误位置,提供表单项变化回调和表单完成回调
+ * 提供手动提交、预验证和错误设置等功能
  * @author Tevin
  */
 
@@ -142,7 +145,7 @@
             Object.keys(errors).forEach(errorKey => {
                 if (typeof this.validators[errorKey] !== 'undefined') {
                     checklist.push(
-                        this.validators[errorKey]('setError', errors[errorKey])
+                        this.validators[errorKey]('setError', errors[errorKey]),
                     );
                 } else {
                     unchecks.push(errors[errorKey]);
diff --git a/forms/imagePicker/CImagePicker.vue b/forms/imagePicker/CImagePicker.vue
index b5a5c3b..e5f4238 100644
--- a/forms/imagePicker/CImagePicker.vue
+++ b/forms/imagePicker/CImagePicker.vue
@@ -1,5 +1,8 @@
 /**
  * CImagePicker
+ * 图片选择器组件,用于在表单中上传和管理图片
+ * 支持单张和多张图片上传,并提供压缩、预览等功能
+ * 可限制上传图片的数量和来源(相册/相机)
  * @author Tevin
  */
 
diff --git a/forms/input/CInput.vue b/forms/input/CInput.vue
index ef6e805..d20866e 100644
--- a/forms/input/CInput.vue
+++ b/forms/input/CInput.vue
@@ -1,5 +1,7 @@
 /**
  * CInput - 表单项,文本输入框
+ * 用于在表单中收集用户的文本输入
+ * 支持多种输入类型,可以设置占位提示文本,并且支持显示单位标识
  * @author Tevin
  */
 
diff --git a/forms/numberStep/CNumberStep.vue b/forms/numberStep/CNumberStep.vue
index b9ec157..b8b607c 100644
--- a/forms/numberStep/CNumberStep.vue
+++ b/forms/numberStep/CNumberStep.vue
@@ -1,5 +1,7 @@
 /**
  * CNumberStep
+ * 数字步进器组件,用于在表单中输入数字并通过步进按钮增减数值
+ * 支持设置数值范围、步长、奇偶修正和单位显示
  * @author Tevin
  */
 
diff --git a/forms/numberValve/CNumberValve.vue b/forms/numberValve/CNumberValve.vue
index f642855..777778b 100644
--- a/forms/numberValve/CNumberValve.vue
+++ b/forms/numberValve/CNumberValve.vue
@@ -1,5 +1,8 @@
 /**
  * CNumberValve
+ * 数值滑块组件,用于在表单中通过滑块选择数值
+ * 提供了滑动条和增减按钮两种方式来调整数值
+ * 支持设置数值范围、步长和单位显示
  * @author Tevin
  */
 
@@ -210,7 +213,7 @@
             currentNext = Math.min(currentNext, this.range[1]);
             // 设置
             const sliderLeft = Math.round(
-                ((currentNext - this.range[0]) / (this.range[1] - this.range[0])) * 100
+                ((currentNext - this.range[0]) / (this.range[1] - this.range[0])) * 100,
             );
             this.sliderLeft = sliderLeft;
             this.current = currentNext;
diff --git a/forms/select/CSelect.vue b/forms/select/CSelect.vue
index 5183bb9..aae68bb 100644
--- a/forms/select/CSelect.vue
+++ b/forms/select/CSelect.vue
@@ -1,5 +1,8 @@
 /**
  * CSelect
+ * 下拉选择组件,用于在表单中提供选项选择功能
+ * 支持两种选择模式:下拉选择模式和跳转页面选择模式
+ * 可配置为只读模式,并支持自定义占位文本
  * @author Tevin
  */
 
diff --git a/forms/switch/CSwitch.vue b/forms/switch/CSwitch.vue
index 9d459d9..6917985 100644
--- a/forms/switch/CSwitch.vue
+++ b/forms/switch/CSwitch.vue
@@ -1,5 +1,8 @@
 /**
  * CSwitch
+ * 开关组件,用于在表单中提供开关选择功能
+ * 基于 AtSwitch 封装,支持只读模式
+ * 能够显示必填和错误状态
  * @author Tevin
  */
 
diff --git a/forms/textarea/CTextArea.vue b/forms/textarea/CTextArea.vue
index b6aec4b..a72589e 100644
--- a/forms/textarea/CTextArea.vue
+++ b/forms/textarea/CTextArea.vue
@@ -1,5 +1,8 @@
 /**
  * CTextArea
+ * 多行文本输入组件,用于在表单中收集用户的多行文本输入
+ * 支持设置输入区域高度,可以通过行数或像素值来控制
+ * 支持只读模式和自动增高功能
  * @author Tevin
  */
 
diff --git a/forms/userSignature/CSignatureLayer.vue b/forms/userSignature/CSignatureLayer.vue
index 0d9c676..b5d71d1 100644
--- a/forms/userSignature/CSignatureLayer.vue
+++ b/forms/userSignature/CSignatureLayer.vue
@@ -16,10 +16,10 @@
             <canvas
                 class="drawing"
                 ref="drawing"
-                :canvasId="cavId"
-                :width="cavWidth"
-                :height="cavHeight"
+                type="2d"
+                :id="cavId"
                 :disableScroll="true"
+                v-if="cavShow"
                 @touchstart="evt => handleWriteStart(evt)"
                 @touchmove="evt => handleWriteMove(evt)"
                 @touchend="evt => handleWriteEnd(evt)"
@@ -45,8 +45,8 @@
 import Taro from '@tarojs/taro';
 import { $ } from '@tarojs/extend';
 import { AtFloatLayout, AtButton } from 'taro-ui-vue';
-import './cSignatureLayer.scss';
 import { Tools } from '@components/common/Tools';
+import './cSignatureLayer.scss';
 
 export default {
     name: 'CSignatureLayer',
@@ -59,8 +59,7 @@
         return {
             cavId: 'signCanvas-' + Date.now() + '-' + parseInt(Math.random() * 10000),
             layerOpened: false,
-            cavWidth: 0,
-            cavHeight: 0,
+            cavShow: false,
             curPoint: {},
             lastPoint: {},
             curLine: [],
@@ -70,40 +69,63 @@
             chirography: [],
             // 初始画圆的半径
             radius: 1,
+            canvasContext: null,
         };
     },
     methods: {
         _initDraw() {
-            this.canvasContext = Taro.createCanvasContext(this.cavId, this);
-            const $container = $(this.$refs.drawing).parent();
-            setTimeout(() => {
-                $container.width().then(w => (this.cavWidth = w));
-                $container.height().then(h => (this.cavHeight = h));
-            }, 0);
+            const query = Taro.createSelectorQuery();
+            query
+                .select(`#${this.cavId}`)
+                .fields({ node: true, size: true })
+                .exec(res => {
+                    // Canvas 对象
+                    const canvas = res[0].node;
+                    // Canvas 画布的实际绘制宽高
+                    const renderWidth = res[0].width;
+                    const renderHeight = res[0].height;
+                    // Canvas 绘制上下文
+                    this.canvasContext = canvas.getContext('2d');
+                    this.canvas = canvas;
+                    // 初始化画布大小
+                    const dpr = Taro.getSystemInfoSync().pixelRatio;
+                    canvas.width = renderWidth * dpr;
+                    canvas.height = renderHeight * dpr;
+                    this.canvasContext.scale(dpr, dpr);
+                    // 初始化变量
+                    this.handleRestDraw();
+                });
         },
         $onDraw(callback) {
-            this._initDraw();
             this.layerOpened = true;
             this._callback = callback;
-            setTimeout(() => {
-                this.handleRestDraw();
-            }, 10);
+            this.$nextTick(() => {
+                setTimeout(() => {
+                    this.cavShow = true;
+                    setTimeout(() => {
+                        this._initDraw();
+                    }, 100);
+                }, 300);
+            });
         },
         handleRestDraw() {
             this.firstTouch = true;
             this.curLine = [];
             this.chirography = [];
-            this.canvasContext.clearRect(0, 0, this.cavWidth, this.cavHeight);
-            this.canvasContext.draw();
+            this.canvasContext.clearRect(0, 0, this.canvas.width, this.canvas.height);
         },
         handleClose() {
             this.layerOpened = false;
+            this.cavShow = false;
+            setTimeout(() => {
+                this.canvasContext.clearRect(0, 0, this.canvas.width, this.canvas.height);
+            }, 100);
         },
         handleWriteStart(evt) {
-            if (evt.type != 'touchstart') {
-                return false;
+            if (evt.type !== 'touchstart' || !this.canvasContext) {
+                return;
             }
-            this.canvasContext.setFillStyle('#1A1A1A');
+            this.canvasContext.fillStyle = '#111111';
             const point = {
                 x: evt.touches[0].x,
                 y: evt.touches[0].y,
@@ -126,8 +148,8 @@
             this._pointToLine(this.curLine);
         },
         handleWriteMove(evt) {
-            if (evt.type != 'touchmove') {
-                return false;
+            if (evt.type !== 'touchmove') {
+                return;
             }
             if (evt.cancelable) {
                 // 判断默认行为是否已经被禁用
@@ -151,8 +173,8 @@
             this._pointToLine(this.curLine);
         },
         handleWriteEnd(evt) {
-            if (evt.type != 'touchend') {
-                return 0;
+            if (evt.type !== 'touchend') {
+                return;
             }
             const point = {
                 x: evt.changedTouches[0].x,
@@ -181,14 +203,14 @@
             if (point.x > this.cutArea.right) {
                 this.cutArea.right = point.x;
             }
-            if (this.cavWidth - point.x <= 0) {
-                this.cutArea.right = this.cavWidth;
+            if (this.canvas.width - point.x <= 0) {
+                this.cutArea.right = this.canvas.width;
             }
             if (point.y > this.cutArea.bottom) {
                 this.cutArea.bottom = point.y;
             }
-            if (this.cavHeight - point.y <= 0) {
-                this.cutArea.bottom = this.cavHeight;
+            if (this.canvas.height - point.y <= 0) {
+                this.cutArea.bottom = this.canvas.height;
             }
             if (point.x < this.cutArea.left) {
                 this.cutArea.left = point.x;
@@ -279,27 +301,28 @@
                 r2 = (line[1].r + line[0].r) / 2;
             }
             let n = 5;
-            let point = [];
+            let points = [];
             for (let i = 0; i < n; i++) {
                 let t = i / (n - 1);
                 let x = (1 - t) * (1 - t) * x0 + 2 * t * (1 - t) * x1 + t * t * x2;
                 let y = (1 - t) * (1 - t) * y0 + 2 * t * (1 - t) * y1 + t * t * y2;
                 let r = lastRadius + ((this.radius - lastRadius) / n) * i;
-                point.push({ x: x, y: y, r: r });
-                if (point.length == 3) {
-                    let a = this._ctaCalc(
-                        point[0].x,
-                        point[0].y,
-                        point[0].r,
-                        point[1].x,
-                        point[1].y,
-                        point[1].r,
-                        point[2].x,
-                        point[2].y,
-                        point[2].r,
+                points.push({ x: x, y: y, r: r });
+                if (points.length == 3) {
+                    this._bethelDraw(
+                        this._ctaCalc(
+                            points[0].x,
+                            points[0].y,
+                            points[0].r,
+                            points[1].x,
+                            points[1].y,
+                            points[1].r,
+                            points[2].x,
+                            points[2].y,
+                            points[2].r,
+                        ),
                     );
-                    this._bethelDraw(a, true);
-                    point = [{ x: x, y: y, r: r }];
+                    points = [{ x: x, y: y, r: r }];
                 }
             }
             this.curLine = line;
@@ -382,64 +405,75 @@
             }
             return a;
         },
-        _bethelDraw(point, isFill) {
+        _bethelDraw(points) {
             const ctx = this.canvasContext;
             ctx.beginPath();
-            ctx.moveTo(point[0].mx, point[0].my);
-            for (let i = 1; i < point.length; i++) {
+            ctx.moveTo(points[0].mx, points[0].my);
+            for (let i = 1; i < points.length; i++) {
                 ctx.bezierCurveTo(
-                    point[i].c1x,
-                    point[i].c1y,
-                    point[i].c2x,
-                    point[i].c2y,
-                    point[i].ex,
-                    point[i].ey,
+                    points[i].c1x,
+                    points[i].c1y,
+                    points[i].c2x,
+                    points[i].c2y,
+                    points[i].ex,
+                    points[i].ey,
                 );
             }
+            ctx.closePath();
             ctx.stroke();
-            if (isFill !== undefined) {
-                // 后绘制的图形会覆盖前面的图形, 绘制时注意先后顺序
-                ctx.fill();
-            }
-            ctx.draw(true);
+            ctx.fill();
         },
         _brushingGround(callback) {
             Taro.canvasToTempFilePath({
-                canvasId: this.cavId,
+                canvas: this.canvas,
                 x: 0,
                 y: 0,
-                width: Math.ceil(this.cavWidth),
-                height: Math.ceil(this.cavHeight),
-                destWidth: Math.ceil(this.cavWidth),
-                destHeight: Math.ceil(this.cavHeight),
+                width: Math.ceil(this.canvas.width),
+                height: Math.ceil(this.canvas.height),
+                destWidth: Math.ceil(this.canvas.width),
+                destHeight: Math.ceil(this.canvas.height),
                 quality: 1,
                 fileType: 'png',
                 success: res => {
                     const ctx = this.canvasContext;
-                    ctx.setFillStyle('#ffffff');
-                    ctx.fillRect(0, 0, this.cavWidth, this.cavHeight);
-                    ctx.drawImage(res.tempFilePath, 0, 0);
-                    ctx.draw(false, () => {
+                    ctx.fillStyle = '#ffffff';
+                    ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);
+                    // 重新绘制
+                    const image = this.canvas.createImage();
+                    image.onload = () => {
+                        const dpr = Taro.getSystemInfoSync().pixelRatio;
+                        ctx.drawImage(
+                            image,
+                            0,
+                            0,
+                            this.canvas.width / dpr,
+                            this.canvas.height / dpr,
+                        );
                         callback();
-                    });
+                    };
+                    image.src = res.tempFilePath;
                 },
             });
         },
         handleSaveDraw() {
             if (this.firstTouch) {
                 Tools.toast('请书写签名!');
+                return;
             }
             this._brushingGround(() => {
                 const delta = 20;
                 const clipArea = { x: 0, y: 0, w: 0, h: 0 };
                 clipArea.x = Math.max(this.cutArea.left - delta, 0);
                 clipArea.y = Math.max(this.cutArea.top - delta, 0);
-                const realRight = Math.min(this.cutArea.right + delta, this.cavWidth);
-                const realBottom = Math.min(this.cutArea.bottom + delta, this.cavHeight);
+                const realRight = Math.min(this.cutArea.right + delta, this.canvas.width);
+                const realBottom = Math.min(
+                    this.cutArea.bottom + delta,
+                    this.canvas.height,
+                );
                 clipArea.w = realRight - clipArea.x;
                 clipArea.h = realBottom - clipArea.y;
                 Taro.canvasToTempFilePath({
-                    canvasId: this.cavId,
+                    canvas: this.canvas,
                     x: clipArea.x,
                     y: clipArea.y,
                     width: clipArea.w,
@@ -456,10 +490,6 @@
             });
         },
     },
-    mounted() {
-        this.$nextTick(() => {
-            this._initDraw();
-        });
-    },
+    mounted() {},
 };
 </script>
\ No newline at end of file
diff --git a/forms/userSignature/cSignatureLayer.scss b/forms/userSignature/cSignatureLayer.scss
index 3a1d751..e64b271 100644
--- a/forms/userSignature/cSignatureLayer.scss
+++ b/forms/userSignature/cSignatureLayer.scss
@@ -19,7 +19,7 @@
         }
     }
     .c-signature-layer-btns {
-        @include position(absolute, n 0 0 n);
+        @include position(absolute, n 0 0 n, 3);
         width: 100%;
         height: 92px;
         font-size: 0;
@@ -32,7 +32,7 @@
         position: relative;
         height: calc(100% - 92px);
         .size-box-top {
-            @include position(absolute, 3% 3% n n);
+            @include position(absolute, 3% 3% n n, 2);
             width: 94%;
             height: 36px;
             pointer-events: none;
@@ -56,7 +56,7 @@
             }
         }
         .size-box-bottom {
-            @include position(absolute, n 3% 3% n);
+            @include position(absolute, n 3% 3% n, 2);
             width: 94%;
             height: 36px;
             pointer-events: none;

--
Gitblit v1.9.1