# uni-vue3 **Repository Path**: Fetor/uni-vue3 ## Basic Information - **Project Name**: uni-vue3 - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2024-10-08 - **Last Updated**: 2024-10-08 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # uni app 能用 promisify 风格的 uniapp 接口,就用, 尽量不要用回调式的了 # 代码风格 一个函数/方法, 只完成一个功能,不要在一个函数的参数上加标识来控制函数行为 -- 如果确实需要,拆成多个方法来做 !! 必须, 使用 prettier 来进行格式化, 对应的配置文件已上传,本地自行安装对应插件 # 项目 ## 小程序 2022 年 11 月 23 日 : 目前先不考虑 H5, 仅考虑小程序的版本 图片: 小程序不支持拼接相对路径的图片, 所以 uni-app 中,必须使用全路径图片, 或者网络路径图片, 不得使用 ./ 的形式拼接的图片 -- 尤其是使用 image 组件的时候 ### 项目架构 整体使用 vite+ts 的方式来开发和构建 ( uni-app@3 ) 小程序特性, 没有路由,没有 views 目录(改为 pages 目录) 关于 store, 各个页面之间可以保持数据, 可以正常使用 ### storage 需要持久化的数据, 用 `stores/util/useStorageString` 来处理, 可以缓存,并且在修改的时候直接持久化到本地 ```js import { useStore as useLocalData } from '@stores/local' const localData = useLocalData() /** * 经过验证, 小程序环境下,执行一万次uni.getStorageSync 和 store.xxx来获取某个值,时间差近千倍 * 所以: 尽量用自己的缓存, storage只用来持久化 * * 一个是效率问题, 第二个, 对于业务程序来说,可以隐藏实现细节 * store 可以用本地存储, 在H5端也可以用sessionStorage/indexDB 等形式来做存储,甚至可以用服务端做持久化存储 */ let arr = new Array(10000) arr.fill(1) let start = Date.now() let token = null arr.forEach(() => { token = uni.getStorageSync('token') }) let end = Date.now() console.log(`spent time ${end - start}`) start = Date.now() arr.forEach(() => { token = localData.token }) end = Date.now() console.log(`spent time local ${end - start}`) ``` ### 关于 语音听写 和 语音合成 播报和识别是有区别的: 识别需要录音,一次肯定只能有一个, 并且这个识别的时长是不确定的,不太可能搞一个队列出来 播报是需要生成声音, 可以搞多个一起来生成(小程序会有一个 socket 最大数量限制), 而且播放是一定会结束的, 可以搞成队列, 一个一个播是可以的 至于识别和播报的服务,区别不大, 本身识别和播报都是从讯飞公有云拿到的例子来的, 只是后来要用医疗的 aiui 做识别, 才把代码改成了 aiui 的版本, 可以把播报的版本也改过来, 也可以把识别的改成讯飞公有云 #### 关于 request 使用 uni.request, 暂时不考虑使用 axios, 对于业务来说, 这应该是不可感知的, 不影响 将每个接口封装成异步函数,尽量保留接口的详细信息 -- url 与返回值的对应关系 直接调用函数,业务中处理参数和响应值就行 ### 页面布局 在 assets/base.scss 中, 给 page 加上了样式: page{height:100vh;width:100vw}, 每个页面会自动撑满 后续布局请在此基础上进行, 可以直接使用 flex 进行自适应, 并且支持 contain:size 的方式来控制 flex 内容不至于将容器撑大, 内容布局的时候尽量不要使用 calc(100vh - Nrpx) 的方式来做了 ### UI 组件 项目组件使用 [uview plus](https://uiadmin.net/uview-plus/components/intro.html), 基于 uview2 的社区版本,支持 uniapp@3 和 vue@3 ### 分包 跟主业务无关的页面, 都扔到 subpackage-page 下面去, 避免主包体积过大 # im 聊天 部分逻辑遗留自诊后 ### 人机耦合 1. 诊后的逻辑是医生和健管师两种身份, 医生身份是自洽的,普通的聊天逻辑 健管师和智能助手用统一账号(融云账号)来发送消息, 所以无法通过融云的发送人 id 来识别健管师身份 -- 人机耦合 通过 `message.replyType=='AID'`_人机耦合_ / `message.contnet.extra.reply_type == 'ai_person'`_融云消息_ 来判断是健管师发送的消息 通过 `message.aidInfo`_人机耦合_ / `message.content.extra.user.aid_info` _融云消息_ 来读取健管师名字 如果获取到了健管师名字,则医生端/人机耦合界面需要显示健管师的名字 : 张三(健康管理师), 患者端不显示名字,直接显示 : 健康管理师 ### 发送视频 医生端/患者端, 直接发送融云标准小视频消息 人机耦合 发送的消息类型是 `IFLY:videoMsg` (前端不处理,这个是接口发送自己处理的,前端拿出来展示就好) 。 人机耦合发送的消息, 展示统一的封面 ### 语音消息 2023 年 8 月 9 日 语音消息在录音的同时, 直接做好转写, 将内容一起发过去 不是真的用语音内容去做转写 如果没有内容,就没有了, 直接提示转写失败 ### 关于 im 模块 2023 年 7 月 31 日 目前的问题: 模型 1. 可能有多个健管师, 多个医生/护士, 一个患者在会话里 2. 健管师和智能助手用的同一个融云 id 3. 健管师会离职,离职之后账号交给后来的健管师使用, 名字会改 发送者姓名展示 1. 患者端显示: 患者自己的名字(包括关系:本人,父母,子女…), 医生的名字, 护士的名字, 健管师不展示名字, 仅显示【健康管理师】 2. 医生/健管师端显示: 患者名字, 医生名字, 护士名字, 健管师需要展示姓名(而且要能随着账号改动) 数据 > 融云端: > > - 融云消息里面,只能通过融云 id 来获取当前消息谁发送的, 目前健管师跟智能助手用同一个 id, 这个在融云端暂时无法区分 > - 融云的 v4 版本没有引用消息, 只能自己实现, 与标准有区别 > - 引用消息, 不能把当前的发送人加到消息中去, 因为名字会改变,发到消息中之后,无法跟随改变 `接收时无法正常展示` > 服务端: > > - 服务端消息里面, 主消息(区别于引用消息) 将发送人姓名加到 aidInfo 里面, 可以作为展示用 > - 引用消息里面, 同融云版本, 不能将发送人信息发出去,`接收时无法正常显示` # 关于 ucharts 不要修改 uchart 的版本, 源码被我改过 - linearDirectionType 属性是我添加的,官方版本不支持 # 备注 ### 小程序配置信息 #### 全病程患者端 - AppId: 讯飞全程患者管理医护版 wx6b1e27f05d7b4774 ### 域名配置 ``` 融云已经升级到 5.8.0, 对应的域名也有升级, 按照当前最新的走 融云 request https://cdn.ronghub.com https://comet.rong-edge.com https://minicomet-b.rong-edge.com https://minicomet-b.rong-edge.com https://rtc-miniapp-wctgw-prod-bdcbj.ronghub.com https://nav.rong-edge.com https://nav-b.rong-edge.com https://collection.rong-edge.com 融云 socket wss://ws.rong-edge.com wss://ws-b.rong-edge.com 后端域名 研发环境 https://zhgl-dev.iflyhealth.com/ ``` # model 与 typescript module 与 es module model 是目录,用来定义一些数据结构, 与后端通信的数据结构,或者前端有必要独立出来数据模型,都可以放到这里面 在 ts 中, 如果一个模块被定义成 es module(有 import 或者 export ), 那么这个模块的内容就被限制在模块内部, 必须导入才能使用 如果不定义成模块, 那么成员默认全局可用, 这是老的 ts 规则导致的, 老的 ts 需要编译,最终直接将所有模块拼接到一个文件中, 在 html 中通过 script 标签引入, 然后所有内容都在全局空间, 所以全局可用 如果定义 ts module/namespace(这俩是一个东西), 则内容需要通过 namespace 引用, 同时, 文件中, 如果没有 namespace 之外的 export, 没有 import , 同样的,内容全局可用 -- 现在 ts 官方已经不建议使用 ts module 了, 但是如果全局可用, 不需要引入,在开发时会很方便, 好用的工具,做一定约束,很强大 又由于, 接口与类型描述是不存在最终代码的, 会被直接擦除调, 所以接口的内容,不影响最终运行结果和成果物 本项目 model 目录中, 使用了这种模式, 接口类型(interface/type 均可),允许单独放到一个文件中, 不定义成模块,让 ts 自行查询,全局可用 部分模块, 接口定义很多, 可以定义成 ts module , 来实现接口的代码组织 -- 建议将接口定义在模块内部, 这样能避免污染全局空间(虽然成果物是不存在的,但是引用的时候不够清晰)