ciyon_ai/aiskill/ciyon-移动前端.md
2026-04-15 17:28:46 +08:00

492 lines
18 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Ciyon移动端开发框架 Skill指南
## 框架概述
CiYon是一个基于uniapp的轻量级跨平台移动应用开发框架采用Vue3 + Vite技术栈支持小程序、H5、App多端发布。
## 项目结构
```
ai_mapshare/
├── fapp/ciyon_ap/ # uniapp移动端项目
│ ├── pages/ # 页面目录
│ │ ├── main/ # 参考主页面
│ │ ├── me/ # 个人中心
│ │ ├── pub/ # 公共页面
│ │ └── demo/ # 示例页面
│ ├── components/ # 60+自定义组件库
│ ├── util/ # 工具函数库
│ ├── static/ # 静态资源
│ ├── App.vue # 应用入口
│ ├── main.js # 主入口文件
│ ├── pages.json # 页面配置
│ ├── manifest.json # 应用配置
│ └── vite.config.js # Vite配置
```
## 技术栈
- **前端**: Vue3 + Vite + Uniapp
- **通信**: HTTP POST API(JSON)
- **参考页面**:
- /fapp/ciyon_ap/pages/demo/curd/demo_list.vue
- /fapp/ciyon_ap/pages/demo/curd/demo_edit.vue
- /fapp/ciyon_ap/pages/main/index.vue
- /fapp/ciyon_ap/pages/main/me.vue
## 开发规范
### 页面开发规范
- 页面存放在 `pages/` 对应模块目录下
- 页面注册在 `pages.json` 中配置路由
- 使用uniapp标准生命周期
### 目录及文件名命名规范
- 在`pages/`下新建项目目录
- `/pages/[项目目录]/index.vue`作为首页主页面
- `/pages/[项目目录]/me.vue` 作为个人中心主页面
- `/pages/[项目目录]/xx_xx.vue` 其他页面均要有一定含义建议与数据表名称相关。模块_功能
- 例如:`order_list.vue` 列表页、`order_info.vue` 详情页、`order_edit.vue` 编辑页、`order_ship.vue` 功能页
- 例如: `user_info.vue`、`user_order.vue`、`user_address.vue`
- 页面起名尽量贴合业务,不要用`detail.vue`、`list.vue`、`edit.vue`、`add.vue`等通用名称。
### vue文件API方法命名规范
- 页面初始化方法一般为`init`
- func: 'xx.xx_init'
- 列表页初始化传入once(bool)参数once=true首次请求获取初始化数据
this.pagepost.once = !this.init.once;
参考 /fapp/ciyon_ap/pages/demo/curd/demo_list.vue
参考 /fapp/ciyon_ap/pages/demo/curd/demo_edit.vue
API参考 /web/ampap/demo/demo.php
- 更新 `update`、删除 `delete`、审核 `audit`等方法按此命名。
- 综合举例:
- 前端文件: /pages/[项目目录]/[模块]_list.vue
- 前端调用: this.callfunc({func:'[模块].[功能]_init'})、this.callfunc({func:'[模块].[功能]_delete'})
- 后端文件: /web/am[项目目录]/[模块].php
- 后端函数: json_[功能]_init()、json_[功能]_delete()
### 组件使用规范
组件前缀统一使用 `ciy-`已提供60+组件:
**表单组件**:
- `ciy-input` - 基础输入框
- `ciy-textarea` - 文本域
- `ciy-select` - 选择器
- `ciy-radio` - 单选
- `ciy-checkbox` - 复选
- `ciy-checkitem` - 检查项
- `ciy-switch` - 开关
- `ciy-selbool` - 布尔选择
- `ciy-selcas` - 级联选择
- `ciy-selpage` - 页面选择
- `ciy-slider` - 滑块
- `ciy-inputnumber` - 数字输入
- `ciy-inputbet` - 范围输入
- `ciy-inputcyc` - 周期输入
- `ciy-inputdatetime` - 日期时间
- `ciy-inputdaterange` - 日期范围
- `ciy-inputtimepoint` - 时间点
- `ciy-inputunitedit` - 单位编辑
- `ciy-inputocr` - OCR输入
- `ciy-capcode` - 验证码输入
- `ciy-searchbar` - 搜索栏
- `ciy-query` - 查询组件
- `ciy-selmap` - 地图选择位置
- `ciy-mapbox` - 地图展示组件(基于 Leaflet
- `ciy-upload` - 文件上传
**展示组件**:
- `ciy-showmoney` - 金额展示
- `ciy-shownum` - 数字展示
- `ciy-showimgs` - 多图片展示
- `ciy-textmore` - 文本展开
- `ciy-chart-pie` - 饼图
- `ciy-markdown` - Markdown渲染
- `ciy-svgimg` - 单图片显示
- `ciy-totalsem` - 总计语义
- `ciy-gesture` - 手势识别
- `ciy-handsign` - 手势识别
- `ciy-audio` - 音频播放
**功能组件**:
- `ciy-camera` - 相机在ciy-aicameraocr中
- `ciy-aivoice` - AI语音
- `ciy-gesture` - 手势识别
- `ciy-handsign` - 手势识别
- `ciy-btreader` - 蓝牙读卡器
- `ciy-header` - 页面头部
- `ciy-tabbar` - 底部导航
- `ciy-dialog` - 弹窗
- `ciy-toast` - 提示
- `ciy-alert` - 警告
- `ciy-popmenu` - 弹出菜单
- `ciy-calendar` - 日历
- `ciy-ratestar` - 评分
- `ciy-segment` - 分段器
- `ciy-swiper` - 轮播
- `ciy-swipelist` - 滑动列表
- `ciy-listend` - 列表底部
- `ciy-movable` - 可移动
**动画组件**:
- `ciy-ani` - 动画
- `ciy-aniheight` - 高度动画
- `ciy-anipop` - 弹出动画
**认证组件**:
- `ciy-auth` - 认证
**自定义组件**:
- `diy-apuser` - AP用户
- `diy-xxlist` - XX列表
**调试组件**:
- `ciy-dbg` - 调试
### API通信规范
**请求封装**:
```javascript
// 使用 callfunc 方法调用API
await this.callfunc({
func: 'main.index_init', // API函数名格式后端API文件名.前端页面名_方法
data: { // 要发送的数据
id: 123,
name: 'test'
},
srv: 't', // 服务器标识,默认't'
loadhide: false, // 是否隐藏加载提示默认false
cache: 0, // 缓存时间0不缓存一般不缓存
cachekey: '' // 自定义缓存键
}).then(res => {
// 处理响应
});
```
**API路径规则**:
- 前端调用格式:`{func: 'module.method'}`
- URL映射通过 `jsnurl` 配置映射到实际URL
- API命名与页面关联方法名应与前端页面文件名对应便于识别和维护。格式建议`{后端API文件名}.{前端页面名}_{操作方法名}`
- 示例:`{func: 'aaa.index_init'}` 对应后端API `/web/ambap/aaa.php`、对应移动端 `pages/aaa/index.vue`
- 示例:`{func: 'bbb.detail_init'}` 对应后端API `/web/ambap/bbb.php`、对应移动端 `pages/bbb/detail.vue`
- 示例:
- 前端调用:`{func: 'main.index_init'}`
- 另一个示例:`{func: 'login.login_mobile'}`
- **重要**:后端函数名必须与前端的 func 参数完全一致,例如前端 `func: 'aimap.index_init'`,后端函数名为 `json_index_init()`
**响应格式**:
```javascript
// 成功响应
{
code: 1, // 1表示成功
// 其他业务数据...
}
// 失败响应
{
code: 非1, // 非1表示失败2表示需要重新登录
errmsg: '错误信息', // 错误提示
// 其他错误数据...
}
```
### 工具函数
**util/ciy.js** - 核心工具库:
**API请求**:
- `callfunc(opt)` - 统一API请求方法
- `calltxt(opt)` - 纯文本请求
**存储管理**:
- `getstorage(key, def)` - 读取storage
- `setstorage(key, val)` - 写入storage
- `removestorage(key)` - 删除storage支持通配符*
- `clearstorage()` - 清空所有storage
**用户认证**:
- `getauth()` - 获取用户信息,未登录自动调起登录
**提示交互**:
- `alert(content)` - 弹窗提示await
- `toast(content, icon)` - 轻提示await
- `askmsg(content)` - 询问确认框await
- `inputmsg(content, def)` - 输入框await
- `popmenu(options)` - 弹出上拉菜单await
**页面跳转**:
- `gourl(url, type, initdata, initkey)` - 页面跳转
- `http://` - 打开H5页面
- `!` - 打开原型图页面
- `*` - alert提示
- `$` - 需要登录
- `%` - 需要登录且完善信息
- `^` - 需要登录且实名认证
- `&` - 需要登录且绑定银行卡
- `goweb(url, name)` - 带授权打开H5页面
- `goloc(lat, lng, bet)` - 打开地图
- `gophone(phone)` - 拨打电话
**数据处理**:
- `json_parse(data)` - 字符串转json
- `json_string(data)` - json转字符串
- `toint(val)` - 转整数
- `tofloat(val)` - 转小数
- `tostr(val)` - 转字符串
- `tostamp(val)` - 转时间戳
- `todatetime(val)` - 时间戳转日期时间
- `tofix(val, dec)` - 处理小数显示
- `tounit(val)` - 显示多级单位
- `tocyc(val)` - 显示周期 月/天/分钟
- `tomsk(val)` - 显示文字遮罩
- `totimespan(val)` - 将时间转成 xx天后/xx小时前
- `totimesec(val)` - 将秒数转成 xx天/xx小时
- `totimepoint(val)` - 将数字转成 xx:xx[:xx]
- `todayage(val)` - 返回日龄天数
- `tobr(val)` - 将\n替换成<br/>,用于显示多行文本。结合 v-html 使用:`v-html="tobr(item.descs)"`
- `topad0(num, len)` - 数字前面补0
- `tonumtho(num)` - 整数部分千分位显示
- `tonumdec(num)` - 小数部分
**类型校验**:
- `isfloat0(val)` - 校验float是否0
- `isarray(val)` - 判断是否array
- `isobject(val)` - 判断是否object
- `islocalmedia(val)` - 判断是否本地文件
- `isimg(val)` - 是否图片
- `isvideo(val)` - 是否视频
- `file_ext(filename)` - 获取文件扩展名
- `file_stor(url)` - db存储的url转云存储的绝对url
**字典处理**:
- `ccode(catalog, val, key, def)` - 以id查询字典中的值
- `scode(catalog, vals, key)` - 以ids查询字典中的多个name
- `mcode(catalog, val)` - 以id查询字典中的多级name
- `bcode(catalog, val)` - 以int查询字典中的多个name
- `hascode(val, codes)` - 某个数字是否在多个数字中
- `hasstr(str, substr)` - 字符串是否包含另一个字符串
**编码转换**:
- `enbase64(str)` - base64编码
- `svg2bg(svg)` - 将svg转成backgroundImage语法
**其他工具**:
- `sleep(ms)` - 延迟毫秒await
- `copyboard(text)` - 拷贝文本
- `getstrparam(str, sep)` - 解析简易参数
- `urlparam(url)` - 解析url
- `shareparam(opt)` - 分享链接转换
- `arrayfind(arr, val)` - 从数组中匹配值
- `objdeepmerge(dest, src)` - object合并
- `objtolist(list, obj/id)` - 将object并入list数组将id从list数组中移除
- `objclone(obj)` - 深度复制obj
- `str2date(str)` - 字符串转Date
- `bin2hex(bin)` - bin转hex字符串
- `hex2bin(hex)` - hex字符串转bin
- `style2obj(style)` - 将style属性转成object
- `nopower(power)` - 权限检查
- `getroute()` - 获取当前路由
- `getpage(idx)` - 获取当前/上页页面
- `getrect(selector)` - 获取元素尺寸await
- `file_upload1(file)` - 上传单个文件返回urlawait
- `file_uploads(files)` - 上传多个文件await
- `go(e, cb)` - golang式异步错误处理
- `goe(e, cb)` - golang式异步错误处理增强版
**页面控制**:
- `pagenoscroll(isno)` - 禁止页面滚动
- `settheme()` - 设置暗黑模式
- `setfont()` - 设置敬老模式
- `setTabbar()` - 设置Tabbar
- `executepnt(pntid)` - 触发积分埋点
**加载资源**:
- `load_ciydict()` - 获取远程静态dictawait
- `load_svgicon(url)` - 获取远程静态svgiconawait
**扫描功能**:
- `scanqr()` - 扫二维码await
### 开发流程
**App.vue 全局配置**:
- app.globalData.jsnurl.t配置入口域名的API入口 例如 'https://ciyon.local.ciy.cn/ambap/'
- 在development中 配置本地的入口域名的API入口用于调试一般以.local.ciy.cn为主体
- app.globalData.tabbarArr作为底部TabBar定义全局定义给ciy-tabbar组件使用。
- tabbar虽然自定义但pages.json需正常配置。且App.vue的globalData.mainpage应指向首页。
- tabbar图标用svg定义默认双色模式。选中颜色bgsel1/bgsel2未选中颜色bggray1/bggray2。
- **tabbarArr 配置要点**
- `fullpath` 必须与实际页面路径一致,如 `/pages/aimap/index`
- `name` 使用 i18n 代码,需在 `util/lang/*.json` 中同步配置翻译
- 所有 tabbar 页面都必须在模板底部添加 `<ciy-tabbar ref="tabbar"></ciy-tabbar>` 组件
- **语言翻译配置**:所有 tabbar 的 name如 tabbar.topic、tabbar.msg需在所有语言文件zh-Hans.json、en.json、zh-Hant.json、ja.json、fr.json中添加对应的翻译
**新建页面**:
1.`pages/` 对应模块下创建 `.vue` 文件
2.`pages.json` 中注册页面路由
3. 使用组件和工具函数开发功能
**新建组件**:
1.`components/` 下创建组件目录和文件
2. 组件名使用 `ciy-` 前缀
3. 支持通过 props 传递参数
4. 通过 $emit 触发事件
5. 有用户的明确指令,才能新建组件
**调用API**:
1. 确定API函数名格式`模块.方法`,如 `main.index_init`
2. 使用 `callfunc()` 发送请求:
```javascript
var retjson = await this.callfunc({
func: 'main.index_init',
data: {
id: 123
}
});
if (retjson.code != 1)
return this.alert(retjson.errmsg);
// 处理成功响应
```
3. 处理返回数据,成功时 `code=1`,失败时有 `errmsg`
**首次请求优化**
页面首次加载通过 `once` 标志位一次性返回所有初始化数据,减少后续翻页重复带出初始化数据:
```javascript
async getlist() {
this.pagepost.pageno = this.pageno + 1;
this.pagepost.once = !this.init.once;
var retjson = await this.callfunc({
func: 'demo.index_list',
data: this.pagepost
});
this.pageno++;
if (this.pageno == 1)
this.init.list = [];
this.init = this.objdeepmerge(this.init, retjson);
if (retjson.once) {
}
}
```
### 样式规范
- 全局样式: `util/style.css`
- 组件内使用 scoped CSS
- 使用 rem 单位适配
### 常用组件
**表单组件**ciy-input、ciy-select、ciy-radio、ciy-checkbox、ciy-selbool、ciy-inputbet、ciy-upload等
**展示组件**ciy-showmoney、ciy-showimgs、ciy-markdown等
**功能组件**ciy-auth、ciy-dialog、ciy-toast、ciy-popmenu等
**导航组件**
- ciy-header - 页面头部所有页面使用navigationStyle为custom
- ciy-tabbar - 底部导航tabbar页面必须添加
- ciy-segment - 分段器(使用 `:lis` 属性传递数组,如 `:lis="[{id:1,name:'选项1'}]"`,不要使用 `:options`
**地图组件**
- ciy-selmap - 国内地图选择组件(微信小程序用)
- ciy-mapbox - 通用地图展示选择组件(基于 Leaflet
- 经纬度在数据库中存储时,应乘以 10000000取整数
- 例如30.2589121 → 存储为 302589121
- 在前端使用时,除以 10000000 恢复原始值
**ciy-mapbox组件地图瓦片提供商**
- 推荐使用 Esri World Imagery卫星影像+ CartoDB Positron Labels标注层
- Esri World Imagery 提供高质量的卫星影像,适合展示地理位置
- CartoDB 标注层提供清晰的文字标注,可叠加在影像层上方
**复杂查询组件**
- ciy-query - 支持多种输入类型input、select、checkbox、radio、date、range等
### 常用配置
**pages.json** - 页面配置:
- 页面路由
- 导航栏样式
- 底部TabBar仅需配置 `pagePath`,其他配置由 App.vue 的 `tabbarArr` 定义)
- 全局样式
- 分包配置:主包放置核心页面(如 aimap、pub其他功能页面放入子包以优化性能
**manifest.json** - 应用配置:
**manifest.json** - 应用配置:
- 应用信息
- 权限配置
- SDK配置
- 多端打包设置
**vite.config.js** - 构建配置:
- 别名配置
- 插件配置
- 构建优化
- 所有页面编译时都带ciy-auth、ciy-alert、ciy-toast、ciy-popmenu组件无需手写
## 框架已完成事项(无需开发)
### 注册登录、找回密码功能与后端login.*接口
复用基本无需修改ciy-auth组件和login API接口
新建需复制ap_user、ap_usr_*有关表结构。
登录成功自动同时加载所有字典项到前端前端缓存到localstorage备用。
### 默认navigationStyle为custom
使用ciy-header组件定义顶部标题栏。可复制新组件自定义。
使用ciy-tabbar组件定义底部导航栏。可复制新组建自定义样式。已自动隐藏系统自带的默认tabbar。
### 已完成通用组件
任意页面均支持未登录 弹出登录/注册界面。
弹出框已美化支持ciy-alert、ciy-toast
弹出菜单已美化ciy-popmenu组件支持多种排版方式突破了默认组件的数量限制。
### 已给所有page注入通用变量
this.g为所有缓存的字典项
this.me为登录的用户完整数据
this.init作为页面初始化统一接收后端请求返回的数据。一般用this.init.code!=1作为骨架屏标识。
this.opn页面传入参数可随意使用不用在onload另行存储。
this.pageno翻页页码
this.pagedata页面间传递数据对于页面深度点击传参非常有效。可替代vuex/Pinia
this.pagepost页面object变量
## 注意事项
1. **命名规范**: 组件统一使用 `ciy-` 前缀目录
2. **API调用**: 使用 `callfunc()` 方法,函数名格式为 `模块.方法`,后端函数名必须与前端 func 参数对应
3. **Token管理**: 自动处理Token无需手动管理Token存储在 `localStorage`
4. **响应格式**: 成功 `{code: 1, ...}`,失败 `{code: 非1, errmsg: '错误信息', ...}`
5. **组件复用**: 优先使用现有组件,避免重复开发
6. **多端适配**: 使用uniapp条件编译处理平台差异
7. **性能优化**:
- 使用 `cache` 参数设置缓存时间
- 避免频繁请求
- 使用 `loadhide: true` 取消不必要的加载提示
- 合理使用分包,主包放置核心页面,其他功能放入子包
8. **页面跳转**: 使用 `gourl()` 方法,支持多种特殊前缀($需要登录、*提示等)
9. **数据传递**: 使用 `pagedata` 对象进行页面间数据传递
10. **字典数据**: 通过 `g` 对象访问字典数据,自动同步更新
11. **用户信息**: 通过 `me` 对象访问当前用户信息
12. **路由参数**: 通过 `opn` 对象访问页面URL参数
13. **用户认证**: 注册、登录、找回密码等功能已集成在 `ciy-auth` 组件中,直接复用,无需重复开发
14. **TabBar配置**
- pages.json 中只配置 `pagePath`,其他样式由 App.vue 的 `tabbarArr` 定义
- tabbarArr 中的 `fullpath` 必须与实际页面路径完全一致
- 所有 tabbar 页面必须在模板底部添加 `<ciy-tabbar ref="tabbar"></ciy-tabbar>`
- tabbarArr 中的 `name` 需在所有语言文件中配置翻译
15. **组件使用注意**
- ciy-segment 使用 `:lis` 属性传递数组,不要使用 `:options`
- 遵循框架定义的属性名称,避免使用非标准属性
## 编译及自动调试
运行cmd编译移动端H5
"D:\Program Files\HBuilderX\cli.exe" publish --platform h5 --project "D:\Dreams\ciy\ai_xxx\fapp\ciyon_ap" --webTitle 众产
编译后访问: https://xxx.local.ciy.cn/ 调试