18 KiB
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通信规范
请求封装:
// 使用 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()
响应格式:
// 成功响应
{
code: 1, // 1表示成功
// 其他业务数据...
}
// 失败响应
{
code: 非1, // 非1表示失败,2表示需要重新登录
errmsg: '错误信息', // 错误提示
// 其他错误数据...
}
工具函数
util/ciy.js - 核心工具库:
API请求:
callfunc(opt)- 统一API请求方法calltxt(opt)- 纯文本请求
存储管理:
getstorage(key, def)- 读取storagesetstorage(key, val)- 写入storageremovestorage(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)- 字符串转jsonjson_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替换成
,用于显示多行文本。结合 v-html 使用:v-html="tobr(item.descs)"topad0(num, len)- 数字前面补0tonumtho(num)- 整数部分千分位显示tonumdec(num)- 小数部分
类型校验:
isfloat0(val)- 校验float是否0isarray(val)- 判断是否arrayisobject(val)- 判断是否objectislocalmedia(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查询字典中的多个namemcode(catalog, val)- 以id查询字典中的多级namebcode(catalog, val)- 以int查询字典中的多个namehascode(val, codes)- 某个数字是否在多个数字中hasstr(str, substr)- 字符串是否包含另一个字符串
编码转换:
enbase64(str)- base64编码svg2bg(svg)- 将svg转成backgroundImage语法
其他工具:
sleep(ms)- 延迟毫秒(await)copyboard(text)- 拷贝文本getstrparam(str, sep)- 解析简易参数urlparam(url)- 解析urlshareparam(opt)- 分享链接转换arrayfind(arr, val)- 从数组中匹配值objdeepmerge(dest, src)- object合并objtolist(list, obj/id)- 将object并入list数组,将id从list数组中移除objclone(obj)- 深度复制objstr2date(str)- 字符串转Datebin2hex(bin)- bin转hex字符串hex2bin(hex)- hex字符串转binstyle2obj(style)- 将style属性转成objectnopower(power)- 权限检查getroute()- 获取当前路由getpage(idx)- 获取当前/上页页面getrect(selector)- 获取元素尺寸(await)file_upload1(file)- 上传单个文件返回url(await)file_uploads(files)- 上传多个文件(await)go(e, cb)- golang式异步错误处理goe(e, cb)- golang式异步错误处理(增强版)
页面控制:
pagenoscroll(isno)- 禁止页面滚动settheme()- 设置暗黑模式setfont()- 设置敬老模式setTabbar()- 设置Tabbarexecutepnt(pntid)- 触发积分埋点
加载资源:
load_ciydict()- 获取远程静态dict(await)load_svgicon(url)- 获取远程静态svgicon(await)
扫描功能:
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/indexname使用 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)中添加对应的翻译
新建页面:
- 在
pages/对应模块下创建.vue文件 - 在
pages.json中注册页面路由 - 使用组件和工具函数开发功能
新建组件:
- 在
components/下创建组件目录和文件 - 组件名使用
ciy-前缀 - 支持通过 props 传递参数
- 通过 $emit 触发事件
- 有用户的明确指令,才能新建组件
调用API:
- 确定API函数名,格式:
模块.方法,如main.index_init - 使用
callfunc()发送请求:var retjson = await this.callfunc({ func: 'main.index_init', data: { id: 123 } }); if (retjson.code != 1) return this.alert(retjson.errmsg); // 处理成功响应 - 处理返回数据,成功时
code=1,失败时有errmsg
首次请求优化:
页面首次加载通过 once 标志位一次性返回所有初始化数据,减少后续翻页重复带出初始化数据:
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变量
注意事项
- 命名规范: 组件统一使用
ciy-前缀目录 - API调用: 使用
callfunc()方法,函数名格式为模块.方法,后端函数名必须与前端 func 参数对应 - Token管理: 自动处理Token,无需手动管理,Token存储在
localStorage中 - 响应格式: 成功
{code: 1, ...},失败{code: 非1, errmsg: '错误信息', ...} - 组件复用: 优先使用现有组件,避免重复开发
- 多端适配: 使用uniapp条件编译处理平台差异
- 性能优化:
- 使用
cache参数设置缓存时间 - 避免频繁请求
- 使用
loadhide: true取消不必要的加载提示 - 合理使用分包,主包放置核心页面,其他功能放入子包
- 使用
- 页面跳转: 使用
gourl()方法,支持多种特殊前缀($需要登录、*提示等) - 数据传递: 使用
pagedata对象进行页面间数据传递 - 字典数据: 通过
g对象访问字典数据,自动同步更新 - 用户信息: 通过
me对象访问当前用户信息 - 路由参数: 通过
opn对象访问页面URL参数 - 用户认证: 注册、登录、找回密码等功能已集成在
ciy-auth组件中,直接复用,无需重复开发 - TabBar配置:
- pages.json 中只配置
pagePath,其他样式由 App.vue 的tabbarArr定义 - tabbarArr 中的
fullpath必须与实际页面路径完全一致 - 所有 tabbar 页面必须在模板底部添加
<ciy-tabbar ref="tabbar"></ciy-tabbar> - tabbarArr 中的
name需在所有语言文件中配置翻译
- pages.json 中只配置
- 组件使用注意:
- ciy-segment 使用
:lis属性传递数组,不要使用:options - 遵循框架定义的属性名称,避免使用非标准属性
- ciy-segment 使用
编译及自动调试
运行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/ 调试