Compare commits
50 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
84be1acf65 | ||
|
|
d5cd4f3144 | ||
|
|
4d27397291 | ||
|
|
8dd1f5cca5 | ||
|
|
cc252b5d1a | ||
|
|
c681cb916b | ||
|
|
206f0aaa50 | ||
|
|
53c6f3fcfd | ||
|
|
d4a5115a80 | ||
|
|
74272d61d2 | ||
|
|
874d1e7731 | ||
|
|
69c3e6d30e | ||
|
|
f9dd9ad3a2 | ||
|
|
5629955dd3 | ||
|
|
77a690a071 | ||
|
|
8b455b1920 | ||
|
|
2d2a8abfd4 | ||
|
|
2c739324d6 | ||
|
|
cae91485f6 | ||
|
|
b66f47dfbb | ||
|
|
fb0df465a1 | ||
|
|
cef264c692 | ||
|
|
fe7d56027b | ||
|
|
4ff6564ffb | ||
|
|
3f699fa2c6 | ||
|
|
dcf6c37195 | ||
|
|
a2cb9fd8ba | ||
|
|
aee0973a53 | ||
|
|
5564c92d33 | ||
|
|
550332d963 | ||
|
|
105f9eafa2 | ||
|
|
63ea420c03 | ||
|
|
6ec1b72063 | ||
|
|
39843877fd | ||
|
|
6294a3db0c | ||
|
|
cd369ddf09 | ||
|
|
1693b0e236 | ||
|
|
ce5fc2355b | ||
|
|
4f9ba9cf44 | ||
|
|
da8ef2019f | ||
|
|
800aabf5ee | ||
|
|
184ff88bd2 | ||
|
|
d233a42754 | ||
|
|
a130f428b9 | ||
|
|
ca03f17f28 | ||
|
|
e57fd125f7 | ||
|
|
696cb2e0fa | ||
|
|
c4f322edd6 | ||
|
|
7ed22e2d58 | ||
|
|
11ade5d7ae |
37
.cursor/rules/Api-Module-Split.mdc
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
---
|
||||||
|
description: 接口迁移到 xk-api 后必须拆出独立模块文件,禁止再往 api.js 大文件里塞
|
||||||
|
alwaysApply: true
|
||||||
|
---
|
||||||
|
|
||||||
|
# API 模块拆分规则(xk-api 迁移必读)
|
||||||
|
|
||||||
|
`request/api/api.js`(约 600+ 行大杂烩)是历史遗留的 Yii 接口聚合文件。
|
||||||
|
**任何迁移到 xk-api 的接口、以及所有新增的 xk-api 接口,一律不得写进 `api.js`**,必须提取/新建到 `request/api/` 下的独立业务模块文件。
|
||||||
|
|
||||||
|
## 必须做
|
||||||
|
|
||||||
|
1. **按业务域建独立文件**:`request/api/<module>.js`,小驼峰命名(已有先例:`patient.js`、`order.js`、`register.js`、`product.js`、`medicalRecord.js`、`specialPrescription.js`)
|
||||||
|
2. **统一走 http 封装**:`import { post, get } from './http'`,第三参传 `3`(`HttpUrlMap[3] = '/xkApi'`),不要手拼 `/xkApi` 字符串到 `http()` 老封装上
|
||||||
|
3. **文件头注释标明后端与取值方式**,每个函数注释标 HTTP 方法与路径,例如:
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { post, get } from './http'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 就诊人相关接口统一走 xk-api(type=3)
|
||||||
|
* 取值:unwrapXkApi → code / result / message
|
||||||
|
*/
|
||||||
|
/** 就诊人列表 xk-api POST /patient/list */
|
||||||
|
export async function getPatientListApi(params = {}) {
|
||||||
|
return await post('/patient/list', params, 3)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
4. **迁移某接口时**(Yii → xk-api):把它从 `api.js` 挪到对应模块文件,`api.js` 里原函数直接删除(调用方改 import),确实来不及改完所有调用方时才允许在 `api.js` 保留一行 re-export 并标 `@deprecated`
|
||||||
|
5. 页面取值统一 `unwrapXkApi`(见 Api-Response.mdc)
|
||||||
|
|
||||||
|
## 禁止做
|
||||||
|
|
||||||
|
- 禁止在 `api.js` 中新增任何函数(包括 Yii 接口——新 Yii 接口也应放模块文件)
|
||||||
|
- 禁止新代码再用 `normalizeXkApiResponse` 这类「把 xk-api 响应抹成 errcode/data」的兼容层;那是存量代码的过渡产物
|
||||||
|
- 禁止一个模块文件里混装两个后端的接口而不加注释区分;同一文件确需并存时,每个函数注释必须标明 `// xk-api` 或 `// Yii`
|
||||||
49
.cursor/rules/Api-Response.mdc
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
---
|
||||||
|
description: Yii 与 xk-api 接口响应取值规范(按后端固定写死,禁止混取)
|
||||||
|
alwaysApply: true
|
||||||
|
---
|
||||||
|
|
||||||
|
# 接口响应取值(Yii vs xk-api)
|
||||||
|
|
||||||
|
写请求代码时**先确认该接口走哪个后端**,再按对应字段固定取值。
|
||||||
|
**禁止**运行时猜测(如「有 code 就取 result」),**禁止** `result || data` / `code ?? errcode` 混写兼容。
|
||||||
|
|
||||||
|
## 形态对照
|
||||||
|
|
||||||
|
| | Yii(oldApi) | xk-api(Laravel jok) |
|
||||||
|
|---|---|---|
|
||||||
|
| 成功码 | `errcode: 0` | `code: 0` |
|
||||||
|
| 业务数据 | `data` | `result` |
|
||||||
|
| 提示文案 | `msg` | `message` |
|
||||||
|
|
||||||
|
## 强制用法
|
||||||
|
|
||||||
|
统一用 `@/utils/api-response.js`,按后端选方法:
|
||||||
|
|
||||||
|
```js
|
||||||
|
// 该接口是 xk-api
|
||||||
|
import { unwrapXkApi } from '@/utils/api-response.js'
|
||||||
|
const { ok, payload, message } = unwrapXkApi(res)
|
||||||
|
|
||||||
|
// 该接口是 Yii
|
||||||
|
import { unwrapYiiApi } from '@/utils/api-response.js'
|
||||||
|
const { ok, payload, message } = unwrapYiiApi(res)
|
||||||
|
```
|
||||||
|
|
||||||
|
也可直接写死(患者端完整响应在 `res.data`):
|
||||||
|
|
||||||
|
```js
|
||||||
|
// xk-api
|
||||||
|
if (res.data.code == 0) { const data = res.data.result }
|
||||||
|
|
||||||
|
// Yii
|
||||||
|
if (res.data.errcode == 0) { const data = res.data.data }
|
||||||
|
```
|
||||||
|
|
||||||
|
API 封装文件注释里标明后端,例如:`// xk-api POST /patient/list`。
|
||||||
|
|
||||||
|
## 禁止
|
||||||
|
|
||||||
|
- 禁止 `unwrapApi` 一类「自动识别后端再取值」
|
||||||
|
- 禁止 `res.data.result || res.data.data`
|
||||||
|
- 禁止把 xk-api 再 `normalize` 成 errcode/data 后按 Yii 读
|
||||||
11
.cursor/rules/Clarify-Before-Act.mdc
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
---
|
||||||
|
description: 不懂先问,明确目标后再动手
|
||||||
|
alwaysApply: true
|
||||||
|
---
|
||||||
|
|
||||||
|
# 先问再做
|
||||||
|
|
||||||
|
1. **不懂就问**:需求、业务口径、技术选型、影响范围等有不确定之处,必须先向你确认,禁止凭猜测直接改代码。
|
||||||
|
2. **一问一答**:每次只提一个最关键的问题,等你回复后再继续;避免一次抛出多个选项把讨论打散。
|
||||||
|
3. **说明提问原因**:每个问题都要附带「我为什么要问」——例如缺什么信息、有哪些备选理解、猜错会有什么后果。
|
||||||
|
4. **目标对齐后再动手**:确认对你的目标(要达成什么、不做什么、验收标准)有明确认知后,再开始查代码、写 SQL、改页面。
|
||||||
12
.cursor/rules/Code-Standards.md
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
---
|
||||||
|
description:
|
||||||
|
alwaysApply: true
|
||||||
|
---
|
||||||
|
|
||||||
|
1. 写代码的时候要补充详细的中文注释(每个方法是干嘛的,为什么要这样写),如果是工作区,则所有项目都适用该规则
|
||||||
|
2. 注意不要生成太多的空行,上一部分代码和下一部分代码中间的空行不要大于2行
|
||||||
|
3. 有封装好的方法、组件需要复用,不要重复造轮子
|
||||||
|
4. 小程序端的抽屉全部需要用page-container来防止用户意外退出页面(记得使用v-if而不是v-show)
|
||||||
|
5. 数据库的(created_at、updated_at、deleted_at)统一使用时间戳,不要使用字符串,并且我在查询器中一级格式化成字符串了,无需再次格式化
|
||||||
|
6. 微信小程序 `.vue` 模板(会编译成 WXML)禁止使用 `??`、`?.` 等现代运算符,否则会报 `unexpected token '?'`;模板里用 `||` / 显式判断,脚本里可用 `??`/`?.`
|
||||||
|
7. 微信小程序模板里 `:class` / `:style` 禁止写 `fn(arg)` 方法调用(如 `:class="sexClass(p)"` 会编译失败);用对象/数组字面量(如 `:class="{ male: p.sex == 1 }"`),或把结果先算进 data/computed 再绑定
|
||||||
15
.cursor/rules/Code-Standards.mdc
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
---
|
||||||
|
description:
|
||||||
|
alwaysApply: true
|
||||||
|
---
|
||||||
|
|
||||||
|
1. 写代码的时候要补充详细的中文注释(每个方法是干嘛的,为什么要这样写),如果是工作区,则所有项目都适用该规则
|
||||||
|
2. 注意不要生成太多的空行,上一部分代码和下一部分代码中间的空行不要大于2行
|
||||||
|
3. 有封装好的方法、组件需要复用,不要重复造轮子
|
||||||
|
4. 小程序端的抽屉全部需要用page-container来防止用户意外退出页面(记得使用v-if而不是v-show)
|
||||||
|
5. 数据库的(created_at、updated_at、deleted_at)统一使用时间戳,不要使用字符串,并且我在查询器中一级格式化成字符串了,无需再次格式化
|
||||||
|
6. 微信小程序 `.vue` 模板(会编译成 WXML)禁止使用 `??`、`?.` 等现代运算符,否则会报 `unexpected token '?'`;模板里用 `||` / 显式判断,脚本里可用 `??`/`?.`
|
||||||
|
7. 微信小程序模板里 `:class` / `:style` 禁止写 `fn(arg)` 方法调用(如 `:class="sexClass(p)"` 会编译失败);用对象/数组字面量(如 `:class="{ male: p.sex == 1 }"`),或把结果先算进 data/computed 再绑定
|
||||||
|
8. 接口取值:写代码时先确认接口是 xk-api 还是 Yii,再固定用 `code/result/message` 或 `errcode/data/msg`(可用 `unwrapXkApi` / `unwrapYiiApi`);禁止运行时猜测、禁止 `result || data`(详见 Api-Response.mdc)
|
||||||
|
9. 卡片强调样式:禁止用左侧竖色条(`border-left` 色条/左侧色块)做卡片强调或分类标识,统一用「1px 同色系边框 + 同色低透明度外发光(box-shadow 微光)」;历史页面暂不强制回改,新增/改动的卡片必须遵守
|
||||||
|
10. API 模块拆分:迁移到 xk-api 的接口和所有新增接口必须放 `request/api/<module>.js` 独立模块文件,禁止再往 `request/api/api.js` 大文件里新增(详见 Api-Module-Split.mdc)
|
||||||
2
.gitignore
vendored
@@ -117,3 +117,5 @@ dist
|
|||||||
/.hbuilderx/
|
/.hbuilderx/
|
||||||
/.idea/
|
/.idea/
|
||||||
/database/
|
/database/
|
||||||
|
/utils/utils.js
|
||||||
|
/.cursor/skills/
|
||||||
|
|||||||
3
.idea/inspectionProfiles/Project_Default.xml
generated
@@ -14,7 +14,7 @@
|
|||||||
<inspection_tool class="HtmlUnknownTag" enabled="true" level="WARNING" enabled_by_default="true">
|
<inspection_tool class="HtmlUnknownTag" enabled="true" level="WARNING" enabled_by_default="true">
|
||||||
<option name="myValues">
|
<option name="myValues">
|
||||||
<value>
|
<value>
|
||||||
<list size="16">
|
<list size="17">
|
||||||
<item index="0" class="java.lang.String" itemvalue="nobr" />
|
<item index="0" class="java.lang.String" itemvalue="nobr" />
|
||||||
<item index="1" class="java.lang.String" itemvalue="noembed" />
|
<item index="1" class="java.lang.String" itemvalue="noembed" />
|
||||||
<item index="2" class="java.lang.String" itemvalue="comment" />
|
<item index="2" class="java.lang.String" itemvalue="comment" />
|
||||||
@@ -31,6 +31,7 @@
|
|||||||
<item index="13" class="java.lang.String" itemvalue="u-form-item" />
|
<item index="13" class="java.lang.String" itemvalue="u-form-item" />
|
||||||
<item index="14" class="java.lang.String" itemvalue="u-checkbox-group" />
|
<item index="14" class="java.lang.String" itemvalue="u-checkbox-group" />
|
||||||
<item index="15" class="java.lang.String" itemvalue="u-checkbox" />
|
<item index="15" class="java.lang.String" itemvalue="u-checkbox" />
|
||||||
|
<item index="16" class="java.lang.String" itemvalue="u-parse" />
|
||||||
</list>
|
</list>
|
||||||
</value>
|
</value>
|
||||||
</option>
|
</option>
|
||||||
|
|||||||
1
.mimocode/.cron-lock
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{"pid":36108,"startedAt":1783929676073}
|
||||||
179
App.vue
@@ -12,6 +12,16 @@
|
|||||||
export default {
|
export default {
|
||||||
// //初始化状态-如果登录过,保持登录状态
|
// //初始化状态-如果登录过,保持登录状态
|
||||||
onLaunch: async function() {
|
onLaunch: async function() {
|
||||||
|
|
||||||
|
silentLogin().then((loginResult) => {
|
||||||
|
if (loginResult.success) {
|
||||||
|
this.tryHandlePendingSceneActions()
|
||||||
|
} else {
|
||||||
|
console.error('静默登录失败:', loginResult.message);
|
||||||
|
}
|
||||||
|
}).catch((error) => {
|
||||||
|
console.error('静默登录异常:', error);
|
||||||
|
});
|
||||||
const version = 4 // 如果当前版本和后台返回的版本一致,那就是审核中,审核通过后 后台设置加1,如果后台的比本地的大 那就是生产版本
|
const version = 4 // 如果当前版本和后台返回的版本一致,那就是审核中,审核通过后 后台设置加1,如果后台的比本地的大 那就是生产版本
|
||||||
const res = await getVersion()
|
const res = await getVersion()
|
||||||
const val = Number(res.data.data.value)
|
const val = Number(res.data.data.value)
|
||||||
@@ -34,54 +44,54 @@
|
|||||||
// 存储当前版本,也可以使用globalData
|
// 存储当前版本,也可以使用globalData
|
||||||
uni.setStorageSync('isShow_envVersion', isShow)
|
uni.setStorageSync('isShow_envVersion', isShow)
|
||||||
|
|
||||||
// 检查是否已登录,如果未登录才检查配置并决定是否静默登录
|
// // 检查是否已登录,如果未登录才检查配置并决定是否静默登录
|
||||||
const token = uni.getStorageSync('token');
|
// const token = uni.getStorageSync('token');
|
||||||
const userInfo = uni.getStorageSync('userinfo');
|
// const userInfo = uni.getStorageSync('userinfo');
|
||||||
|
|
||||||
if (!token || !userInfo) {
|
// if (!token || !userInfo) {
|
||||||
// 未登录,获取系统配置,判断是否需要静默登录
|
// 未登录,获取系统配置,判断是否需要静默登录
|
||||||
try {
|
// try {
|
||||||
const configRes = await getSystemConfig({
|
// const configRes = getSystemConfig({
|
||||||
method: "get",
|
// method: "get",
|
||||||
data: {
|
// data: {
|
||||||
store_id: uni.getStorageSync('store_id') || '11001'
|
// store_id: uni.getStorageSync('store_id') || '11001'
|
||||||
}
|
// }
|
||||||
});
|
// });
|
||||||
|
//
|
||||||
// 根据配置决定是否静默登录
|
// 根据配置决定是否静默登录
|
||||||
// 注意:需要根据实际接口返回格式解析 need_login 字段
|
// 注意:需要根据实际接口返回格式解析 need_login 字段
|
||||||
const isGuest = isGuestMode();
|
// const isGuest = isGuestMode();
|
||||||
let needLogin = true; // 默认需要登录页
|
// let needLogin = false; // 默认需要登录页
|
||||||
|
//
|
||||||
if (isGuest && (configRes.data.code === 0 || configRes.data.code === '0')) {
|
// if (isGuest && (configRes.data.code === 0 || configRes.data.code === '0')) {
|
||||||
// 新格式:从 result 中获取
|
// // 新格式:从 result 中获取
|
||||||
const configData = configRes.data.result || {};
|
// const configData = configRes.data.result || {};
|
||||||
needLogin = configData.need_login !== false; // false 表示静默登录
|
// needLogin = configData.need_login !== false; // false 表示静默登录
|
||||||
} else if (!isGuest && (configRes.data.errcode === 0 || configRes.data.errcode === '0')) {
|
// } else if (!isGuest && (configRes.data?.errcode === 0 || configRes.data?.errcode === '0')) {
|
||||||
// 旧格式:从 data 中获取
|
// // 旧格式:从 data 中获取
|
||||||
const configData = configRes.data.data || {};
|
// const configData = configRes.data.data || {};
|
||||||
needLogin = configData.need_login !== false; // false 表示静默登录
|
// needLogin = configData.need_login !== false; // false 表示静默登录
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
// 如果配置为静默登录(need_login: false),直接执行静默登录
|
// // 如果配置为静默登录(need_login: false),直接执行静默登录
|
||||||
if (!needLogin) {
|
// if (!needLogin) {
|
||||||
// 执行静默登录(不显示提示,不跳转)
|
// // 执行静默登录(不显示提示,不跳转)
|
||||||
silentLogin().then((loginResult) => {
|
// silentLogin().then((loginResult) => {
|
||||||
if (loginResult.success) {
|
// if (loginResult.success) {
|
||||||
console.log('静默登录成功');
|
// console.log('静默登录成功');
|
||||||
} else {
|
// } else {
|
||||||
console.error('静默登录失败:', loginResult.message);
|
// console.error('静默登录失败:', loginResult.message);
|
||||||
}
|
// }
|
||||||
}).catch((error) => {
|
// }).catch((error) => {
|
||||||
console.error('静默登录异常:', error);
|
// console.error('静默登录异常:', error);
|
||||||
});
|
// });
|
||||||
}
|
// }
|
||||||
// 如果配置为需要登录页(need_login: true),不执行任何操作,等待用户手动登录
|
// // 如果配置为需要登录页(need_login: true),不执行任何操作,等待用户手动登录
|
||||||
} catch (error) {
|
// } catch (error) {
|
||||||
// 配置接口调用失败,不影响应用启动,仅记录日志
|
// // 配置接口调用失败,不影响应用启动,仅记录日志
|
||||||
console.error('获取系统配置失败:', error);
|
// console.error('获取系统配置失败:', error);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
console.log('获取更新机制', uni.canIUse('getUpdateManager'))
|
console.log('获取更新机制', uni.canIUse('getUpdateManager'))
|
||||||
// 获取小程序更新机制兼容
|
// 获取小程序更新机制兼容
|
||||||
@@ -145,28 +155,32 @@
|
|||||||
},
|
},
|
||||||
|
|
||||||
onShow: function(e) {
|
onShow: function(e) {
|
||||||
// console.log('App Show')
|
|
||||||
// this.$store.dispatch('initLogin')
|
|
||||||
// 解析scene里面的参数
|
// 解析scene里面的参数
|
||||||
if (e === undefined)
|
if (e === undefined)
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
const scene = decodeURIComponent(e.query.scene)
|
const rawScene = e.query && e.query.scene
|
||||||
|
? decodeURIComponent(e.query.scene)
|
||||||
|
: ''
|
||||||
// 这里接收扫码参数
|
// 这里接收扫码参数
|
||||||
if (scene) {
|
if (rawScene) {
|
||||||
|
// 就诊人认领:cup={user_patient_id}
|
||||||
|
this.parseClaimPatientScene(rawScene)
|
||||||
|
// 医生代支付:ppay={order_id}
|
||||||
|
this.parseProxyPayScene(rawScene)
|
||||||
|
|
||||||
// 判断scene中是否包含sal_id
|
// 判断scene中是否包含sal_id
|
||||||
let isSalespersonId = decodeURIComponent(e.query.scene).includes('sal_id');
|
let isSalespersonId = rawScene.includes('sal_id');
|
||||||
const scene = decodeURIComponent(e.query.scene).split('STORE_QR_CODE_')
|
const scene = rawScene.split('STORE_QR_CODE_')
|
||||||
if (scene[1]) {
|
if (scene[1]) {
|
||||||
uni.setStorageSync('stores_id', scene[1])
|
uni.setStorageSync('stores_id', scene[1])
|
||||||
uni.setStorageSync('store_id', scene[1])
|
uni.setStorageSync('store_id', scene[1])
|
||||||
}
|
}
|
||||||
// uni.setStorageSync('stores_id', scene[1])
|
const st_id = rawScene.split('&')
|
||||||
const st_id = decodeURIComponent(e.query.scene).split('&')
|
let store_id = rawScene.split('STORE_QR_CODE_')
|
||||||
let store_id = decodeURIComponent(e.query.scene).split('STORE_QR_CODE_')
|
store_id = decodeURIComponent(store_id[1] || '').split('&')
|
||||||
store_id = decodeURIComponent(store_id[1]).split('&')
|
const doctors_id = rawScene.split('=')
|
||||||
const doctors_id = decodeURIComponent(e.query.scene).split('=')
|
if (store_id[0] && store_id[0] !== 'undefined') {
|
||||||
if (store_id[0] !== 'undefined') {
|
|
||||||
uni.setStorageSync('stores_id', store_id[0])
|
uni.setStorageSync('stores_id', store_id[0])
|
||||||
uni.setStorageSync('store_id', store_id[0])
|
uni.setStorageSync('store_id', store_id[0])
|
||||||
}
|
}
|
||||||
@@ -185,11 +199,9 @@
|
|||||||
console.log('userId', userId, st_id[0].split('su_id=')[1], res);
|
console.log('userId', userId, st_id[0].split('su_id=')[1], res);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
// console.log(st_id, '4444111111111');
|
|
||||||
// console.log(scene, '4444');
|
|
||||||
}
|
}
|
||||||
// const scene = decodeURIComponent(e.query.scene).split('STORE_QR_CODE_')
|
// 登录后触发认领弹窗 / 代付跳转
|
||||||
// console.log(scene, '11111');
|
this.tryHandlePendingSceneActions()
|
||||||
},
|
},
|
||||||
onHide: function() {
|
onHide: function() {
|
||||||
// console.log('App Hide')
|
// console.log('App Hide')
|
||||||
@@ -200,6 +212,51 @@
|
|||||||
// uni.removeStorageSync('token')
|
// uni.removeStorageSync('token')
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
/**
|
||||||
|
* 解析就诊人认领 scene:cup=123 或 up_id=123
|
||||||
|
*/
|
||||||
|
parseClaimPatientScene(rawScene) {
|
||||||
|
const cupMatch = String(rawScene).match(/(?:^|&)cup=(\d+)/)
|
||||||
|
const upMatch = String(rawScene).match(/(?:^|&)up_id=(\d+)/)
|
||||||
|
const id = Number((cupMatch && cupMatch[1]) || (upMatch && upMatch[1]) || 0)
|
||||||
|
if (id > 0) {
|
||||||
|
uni.setStorageSync('claim_user_patient_id', id)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 解析医生代支付 scene:ppay=订单ID
|
||||||
|
* 新扫码时重置「已确认」标记,以便重新弹出确认框
|
||||||
|
*/
|
||||||
|
parseProxyPayScene(rawScene) {
|
||||||
|
const match = String(rawScene).match(/(?:^|&)ppay=(\d+)/)
|
||||||
|
const orderId = Number((match && match[1]) || 0)
|
||||||
|
if (orderId > 0) {
|
||||||
|
uni.setStorageSync('proxy_pay_order_id', orderId)
|
||||||
|
uni.removeStorageSync('proxy_pay_confirmed')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 登录后:弹出认领模态 / 代付确认模态(不再直接跳转代付页)
|
||||||
|
*/
|
||||||
|
tryHandlePendingSceneActions() {
|
||||||
|
const token = uni.getStorageSync('token')
|
||||||
|
if (!token) return
|
||||||
|
const claimId = Number(uni.getStorageSync('claim_user_patient_id') || 0)
|
||||||
|
if (claimId > 0) {
|
||||||
|
// 通知首页等挂载了认领弹窗的页面打开
|
||||||
|
setTimeout(() => {
|
||||||
|
uni.$emit('open-claim-patient-modal')
|
||||||
|
}, 400)
|
||||||
|
}
|
||||||
|
const proxyOrderId = Number(uni.getStorageSync('proxy_pay_order_id') || 0)
|
||||||
|
const proxyConfirmed = Number(uni.getStorageSync('proxy_pay_confirmed') || 0) === 1
|
||||||
|
// 有代付扫码且尚未确认:弹确认框;已确认过则不自动跳(避免反复打断)
|
||||||
|
if (proxyOrderId > 0 && !proxyConfirmed) {
|
||||||
|
setTimeout(() => {
|
||||||
|
uni.$emit('open-proxy-pay-confirm-modal')
|
||||||
|
}, 500)
|
||||||
|
}
|
||||||
|
},
|
||||||
initWebSocket() {
|
initWebSocket() {
|
||||||
webSocketManager.connect();
|
webSocketManager.connect();
|
||||||
|
|
||||||
@@ -246,7 +303,7 @@
|
|||||||
|
|
||||||
// 从消息中提取发送者信息
|
// 从消息中提取发送者信息
|
||||||
let senderName = '新消息';
|
let senderName = '新消息';
|
||||||
let senderAvatar = '/static/xx/ysxx.png';
|
let senderAvatar = 'https://xiaokang88.oss-cn-hangzhou.aliyuncs.com/xk-client-wx/static/xx/ysxx.png';
|
||||||
|
|
||||||
// 尝试解析发送者ID获取更多信息
|
// 尝试解析发送者ID获取更多信息
|
||||||
const senderId = message.sender_user_id || '';
|
const senderId = message.sender_user_id || '';
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ export function isGuestMode() {
|
|||||||
export function setGuestMode() {
|
export function setGuestMode() {
|
||||||
uni.setStorageSync(GUEST_MODE_KEY, true);
|
uni.setStorageSync(GUEST_MODE_KEY, true);
|
||||||
// 同时设置store_id为11001
|
// 同时设置store_id为11001
|
||||||
uni.setStorageSync('store_id', GUEST_STORE_ID);
|
// uni.setStorageSync('store_id', GUEST_STORE_ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
30
common/utils/drug.js
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
export function isWesternRxDrug(drug) {
|
||||||
|
return drug && drug.type == 2 && (drug.is_otc === 0 || drug.is_otc === '0');
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isHealthFood(drug) {
|
||||||
|
return drug && (drug.type == 3 || drug.category_type === 'health_food');
|
||||||
|
}
|
||||||
|
|
||||||
|
export function canShowFunction(drug, prescriptionApproved) {
|
||||||
|
if (isHealthFood(drug)) return false;
|
||||||
|
if (isWesternRxDrug(drug)) return !!prescriptionApproved;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function canShowUsage(drug, prescriptionApproved) {
|
||||||
|
if (isHealthFood(drug)) return false;
|
||||||
|
if (isWesternRxDrug(drug)) return !!prescriptionApproved;
|
||||||
|
return drug && drug.type != 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function canShowInstruction(drug, prescriptionApproved) {
|
||||||
|
if (isWesternRxDrug(drug)) return !!prescriptionApproved;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isPrescriptionApprovedStatus(data) {
|
||||||
|
if (!data) return false;
|
||||||
|
const ps = data.prescription_status ?? data.status;
|
||||||
|
return data.status === true || ps === 1 || ps === '1' || ps === 3 || ps === '3' || ps === 4 || ps === '4';
|
||||||
|
}
|
||||||
0
components/HealthTeaCard/HealthTeaCard.vue
Normal file
@@ -2,7 +2,7 @@
|
|||||||
<view v-if="visible" class="notification-wrapper" :class="{ 'slide-in': visible }" :style="{ paddingTop: notificationTop + 'px' }">
|
<view v-if="visible" class="notification-wrapper" :class="{ 'slide-in': visible }" :style="{ paddingTop: notificationTop + 'px' }">
|
||||||
<view class="notification" @click="handleClick">
|
<view class="notification" @click="handleClick">
|
||||||
<!-- 头像 -->
|
<!-- 头像 -->
|
||||||
<image class="avatar" :src="avatar || '/static/xx/ysxx.png'" mode="aspectFill" />
|
<image class="avatar" :src="avatar || 'https://xiaokang88.oss-cn-hangzhou.aliyuncs.com/xk-client-wx/static/xx/ysxx.png'" mode="aspectFill" />
|
||||||
|
|
||||||
<!-- 内容区域 -->
|
<!-- 内容区域 -->
|
||||||
<view class="content">
|
<view class="content">
|
||||||
|
|||||||
539
components/c-upload/c-upload.vue
Normal file
@@ -0,0 +1,539 @@
|
|||||||
|
<template>
|
||||||
|
<view class="u-upload" v-if="!disabled">
|
||||||
|
<view
|
||||||
|
v-if="showUploadList"
|
||||||
|
class="u-list-item u-preview-wrap"
|
||||||
|
v-for="(item, index) in lists"
|
||||||
|
:key="index"
|
||||||
|
:style="{
|
||||||
|
width: $u.addUnit(width),
|
||||||
|
height: $u.addUnit(height)
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<view
|
||||||
|
v-if="deletable"
|
||||||
|
class="u-delete-icon"
|
||||||
|
@tap.stop="deleteItem(index)"
|
||||||
|
:style="{
|
||||||
|
background: delBgColor
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<u-icon class="u-icon" :name="delIcon" size="20" :color="delColor"></u-icon>
|
||||||
|
</view>
|
||||||
|
<u-line-progress
|
||||||
|
v-if="showProgress && item.progress > 0 && item.progress != 100 && !item.error"
|
||||||
|
:show-percent="false"
|
||||||
|
height="16"
|
||||||
|
class="u-progress"
|
||||||
|
:percent="item.progress"
|
||||||
|
></u-line-progress>
|
||||||
|
<view @tap.stop="retry(index)" v-if="item.error" class="u-error-btn">点击重试</view>
|
||||||
|
<image @tap.stop="doPreviewImage(item.url || item.path, index)" class="u-preview-image" v-if="!item.isImage" :src="item.url || item.path" :mode="imageMode"></image>
|
||||||
|
</view>
|
||||||
|
<slot name="file" :file="lists"></slot>
|
||||||
|
<view style="display: inline-block;" @tap="selectFile" v-if="maxCount > lists.length">
|
||||||
|
<slot name="addBtn"></slot>
|
||||||
|
<view
|
||||||
|
v-if="!customBtn"
|
||||||
|
class="u-list-item u-add-wrap"
|
||||||
|
hover-class="u-add-wrap__hover"
|
||||||
|
hover-stay-time="150"
|
||||||
|
:style="{
|
||||||
|
width: $u.addUnit(width),
|
||||||
|
height: $u.addUnit(height)
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<u-icon name="plus" class="u-add-btn" size="40"></u-icon>
|
||||||
|
<view class="u-add-tips">{{ uploadText }}</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { prepareImagePath } from '@/utils/image-compress.js';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'c-upload',
|
||||||
|
props: {
|
||||||
|
showUploadList: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
action: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
maxCount: {
|
||||||
|
type: [String, Number],
|
||||||
|
default: 52
|
||||||
|
},
|
||||||
|
showProgress: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
disabled: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
imageMode: {
|
||||||
|
type: String,
|
||||||
|
default: 'aspectFill'
|
||||||
|
},
|
||||||
|
header: {
|
||||||
|
type: Object,
|
||||||
|
default() {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
},
|
||||||
|
formData: {
|
||||||
|
type: Object,
|
||||||
|
default() {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
},
|
||||||
|
name: {
|
||||||
|
type: String,
|
||||||
|
default: 'file'
|
||||||
|
},
|
||||||
|
sizeType: {
|
||||||
|
type: Array,
|
||||||
|
default() {
|
||||||
|
return ['original', 'compressed'];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
sourceType: {
|
||||||
|
type: Array,
|
||||||
|
default() {
|
||||||
|
return ['album', 'camera'];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
previewFullImage: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
multiple: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
deletable: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
maxSize: {
|
||||||
|
type: [String, Number],
|
||||||
|
default: Number.MAX_VALUE
|
||||||
|
},
|
||||||
|
fileList: {
|
||||||
|
type: Array,
|
||||||
|
default() {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
uploadText: {
|
||||||
|
type: String,
|
||||||
|
default: '选择图片'
|
||||||
|
},
|
||||||
|
autoUpload: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
showTips: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
customBtn: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
width: {
|
||||||
|
type: [String, Number],
|
||||||
|
default: 200
|
||||||
|
},
|
||||||
|
height: {
|
||||||
|
type: [String, Number],
|
||||||
|
default: 200
|
||||||
|
},
|
||||||
|
delBgColor: {
|
||||||
|
type: String,
|
||||||
|
default: '#fa3534'
|
||||||
|
},
|
||||||
|
delColor: {
|
||||||
|
type: String,
|
||||||
|
default: '#ffffff'
|
||||||
|
},
|
||||||
|
delIcon: {
|
||||||
|
type: String,
|
||||||
|
default: 'close'
|
||||||
|
},
|
||||||
|
toJson: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
beforeUpload: {
|
||||||
|
type: Function,
|
||||||
|
default: null
|
||||||
|
},
|
||||||
|
beforeRemove: {
|
||||||
|
type: Function,
|
||||||
|
default: null
|
||||||
|
},
|
||||||
|
limitType: {
|
||||||
|
type: Array,
|
||||||
|
default() {
|
||||||
|
return ['png', 'jpg', 'jpeg', 'webp', 'gif', 'image'];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
index: {
|
||||||
|
type: [Number, String],
|
||||||
|
default: ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
lists: [],
|
||||||
|
isInCount: true,
|
||||||
|
uploading: false
|
||||||
|
};
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
fileList: {
|
||||||
|
immediate: true,
|
||||||
|
handler(val) {
|
||||||
|
val.map(value => {
|
||||||
|
let tmp = this.lists.some(val => {
|
||||||
|
return val.url == value.url;
|
||||||
|
})
|
||||||
|
!tmp && this.lists.push({ url: value.url, error: false, progress: 100 });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
lists(n) {
|
||||||
|
this.$emit('on-list-change', n, this.index);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
clear() {
|
||||||
|
this.lists = [];
|
||||||
|
},
|
||||||
|
reUpload() {
|
||||||
|
this.uploadFile();
|
||||||
|
},
|
||||||
|
selectFile() {
|
||||||
|
if (this.disabled) return;
|
||||||
|
const { maxCount, multiple, maxSize, sizeType, lists, sourceType } = this;
|
||||||
|
const newMaxCount = maxCount - lists.length;
|
||||||
|
uni.chooseImage({
|
||||||
|
count: multiple ? (newMaxCount > 9 ? 9 : newMaxCount) : 1,
|
||||||
|
sourceType: sourceType,
|
||||||
|
sizeType,
|
||||||
|
success: async (res) => {
|
||||||
|
const listOldLength = this.lists.length;
|
||||||
|
for (let index = 0; index < res.tempFiles.length; index++) {
|
||||||
|
const val = res.tempFiles[index];
|
||||||
|
if (!this.checkFileExt(val)) continue;
|
||||||
|
if (!multiple && index >= 1) continue;
|
||||||
|
if (val.size > maxSize) {
|
||||||
|
this.$emit('on-oversize', val, this.lists, this.index);
|
||||||
|
this.showToast('超出允许的文件大小');
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (maxCount <= lists.length) {
|
||||||
|
this.$emit('on-exceed', val, this.lists, this.index);
|
||||||
|
this.showToast('超出最大允许的文件个数');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const prepared = await prepareImagePath({
|
||||||
|
path: val.path,
|
||||||
|
size: val.size,
|
||||||
|
});
|
||||||
|
if (!prepared) continue;
|
||||||
|
|
||||||
|
lists.push({
|
||||||
|
url: prepared.path,
|
||||||
|
progress: 0,
|
||||||
|
error: false,
|
||||||
|
file: {
|
||||||
|
...val,
|
||||||
|
path: prepared.path,
|
||||||
|
size: prepared.size,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
this.$emit('on-choose-fail', error);
|
||||||
|
this.showToast('图片处理失败');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.$emit('on-choose-complete', this.lists, this.index);
|
||||||
|
if (this.autoUpload) this.uploadFile(listOldLength);
|
||||||
|
},
|
||||||
|
fail: (error) => {
|
||||||
|
this.$emit('on-choose-fail', error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
showToast(message, force = false) {
|
||||||
|
if (this.showTips || force) {
|
||||||
|
uni.showToast({
|
||||||
|
title: message,
|
||||||
|
icon: 'none'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
upload() {
|
||||||
|
this.uploadFile();
|
||||||
|
},
|
||||||
|
retry(index) {
|
||||||
|
this.lists[index].progress = 0;
|
||||||
|
this.lists[index].error = false;
|
||||||
|
this.lists[index].response = null;
|
||||||
|
uni.showLoading({
|
||||||
|
title: '重新上传'
|
||||||
|
});
|
||||||
|
this.uploadFile(index);
|
||||||
|
},
|
||||||
|
async uploadFile(index = 0) {
|
||||||
|
if (this.disabled) return;
|
||||||
|
if (this.uploading) return;
|
||||||
|
if (index >= this.lists.length) {
|
||||||
|
this.$emit('on-uploaded', this.lists, this.index);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (this.lists[index].progress == 100) {
|
||||||
|
if (this.autoUpload == false) this.uploadFile(index + 1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (this.beforeUpload && typeof(this.beforeUpload) === 'function') {
|
||||||
|
let beforeResponse = this.beforeUpload.bind(this.$u.$parent.call(this))(index, this.lists);
|
||||||
|
if (!!beforeResponse && typeof beforeResponse.then === 'function') {
|
||||||
|
await beforeResponse.then(res => {
|
||||||
|
}).catch(err => {
|
||||||
|
return this.uploadFile(index + 1);
|
||||||
|
})
|
||||||
|
} else if (beforeResponse === false) {
|
||||||
|
return this.uploadFile(index + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!this.action) {
|
||||||
|
this.showToast('请配置上传地址', true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.lists[index].error = false;
|
||||||
|
this.uploading = true;
|
||||||
|
const task = uni.uploadFile({
|
||||||
|
url: this.action,
|
||||||
|
filePath: this.lists[index].url,
|
||||||
|
name: this.name,
|
||||||
|
formData: this.formData,
|
||||||
|
header: this.header,
|
||||||
|
// #ifdef MP-ALIPAY
|
||||||
|
fileType:'image',
|
||||||
|
// #endif
|
||||||
|
success: res => {
|
||||||
|
let data = this.toJson && this.$u.test.jsonString(res.data) ? JSON.parse(res.data) : res.data;
|
||||||
|
if (![200, 201, 204].includes(res.statusCode)) {
|
||||||
|
this.uploadError(index, data);
|
||||||
|
} else {
|
||||||
|
this.lists[index].response = data;
|
||||||
|
this.lists[index].progress = 100;
|
||||||
|
this.lists[index].error = false;
|
||||||
|
this.$emit('on-success', data, index, this.lists, this.index);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
fail: e => {
|
||||||
|
this.uploadError(index, e);
|
||||||
|
},
|
||||||
|
complete: res => {
|
||||||
|
uni.hideLoading();
|
||||||
|
this.uploading = false;
|
||||||
|
this.uploadFile(index + 1);
|
||||||
|
this.$emit('on-change', res, index, this.lists, this.index);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
task.onProgressUpdate(res => {
|
||||||
|
if (res.progress > 0) {
|
||||||
|
this.lists[index].progress = res.progress;
|
||||||
|
this.$emit('on-progress', res, index, this.lists, this.index);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
uploadError(index, err) {
|
||||||
|
this.lists[index].progress = 0;
|
||||||
|
this.lists[index].error = true;
|
||||||
|
this.lists[index].response = null;
|
||||||
|
this.$emit('on-error', err, index, this.lists, this.index);
|
||||||
|
this.showToast('上传失败,请重试');
|
||||||
|
},
|
||||||
|
deleteItem(index) {
|
||||||
|
uni.showModal({
|
||||||
|
title: '提示',
|
||||||
|
content: '您确定要删除此项吗?',
|
||||||
|
success: async (res) => {
|
||||||
|
if (res.confirm) {
|
||||||
|
if (this.beforeRemove && typeof(this.beforeRemove) === 'function') {
|
||||||
|
let beforeResponse = this.beforeRemove.bind(this.$u.$parent.call(this))(index, this.lists);
|
||||||
|
if (!!beforeResponse && typeof beforeResponse.then === 'function') {
|
||||||
|
await beforeResponse.then(res => {
|
||||||
|
this.handlerDeleteItem(index);
|
||||||
|
}).catch(err => {
|
||||||
|
this.showToast('已终止移除');
|
||||||
|
})
|
||||||
|
} else if (beforeResponse === false) {
|
||||||
|
this.showToast('已终止移除');
|
||||||
|
} else {
|
||||||
|
this.handlerDeleteItem(index);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.handlerDeleteItem(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
handlerDeleteItem(index) {
|
||||||
|
if (this.lists[index].progress < 100 && this.lists[index].progress > 0) {
|
||||||
|
typeof this.lists[index].uploadTask != 'undefined' && this.lists[index].uploadTask.abort();
|
||||||
|
}
|
||||||
|
this.lists.splice(index, 1);
|
||||||
|
this.$forceUpdate();
|
||||||
|
this.$emit('on-remove', index, this.lists, this.index);
|
||||||
|
this.showToast('移除成功');
|
||||||
|
},
|
||||||
|
remove(index) {
|
||||||
|
if (index >= 0 && index < this.lists.length) {
|
||||||
|
this.lists.splice(index, 1);
|
||||||
|
this.$emit('on-list-change', this.lists, this.index);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
doPreviewImage(url, index) {
|
||||||
|
if (!this.previewFullImage) return;
|
||||||
|
const images = this.lists.map(item => item.url || item.path);
|
||||||
|
uni.previewImage({
|
||||||
|
urls: images,
|
||||||
|
current: url,
|
||||||
|
success: () => {
|
||||||
|
this.$emit('on-preview', url, this.lists, this.index);
|
||||||
|
},
|
||||||
|
fail: () => {
|
||||||
|
uni.showToast({
|
||||||
|
title: '预览图片失败',
|
||||||
|
icon: 'none'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
checkFileExt(file) {
|
||||||
|
let noArrowExt = false;
|
||||||
|
let fileExt = '';
|
||||||
|
const reg = /.+\./;
|
||||||
|
// #ifdef H5
|
||||||
|
fileExt = file.name.replace(reg, "").toLowerCase();
|
||||||
|
// #endif
|
||||||
|
// #ifndef H5
|
||||||
|
fileExt = file.path.replace(reg, "").toLowerCase();
|
||||||
|
// #endif
|
||||||
|
noArrowExt = this.limitType.some(ext => {
|
||||||
|
return ext.toLowerCase() === fileExt;
|
||||||
|
})
|
||||||
|
if (!noArrowExt) this.showToast(`不允许选择${fileExt}格式的文件`);
|
||||||
|
return noArrowExt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
@import 'uview-ui/libs/css/style.components.scss';
|
||||||
|
|
||||||
|
.u-upload {
|
||||||
|
@include vue-flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.u-list-item {
|
||||||
|
width: 200rpx;
|
||||||
|
height: 200rpx;
|
||||||
|
overflow: hidden;
|
||||||
|
margin: 10rpx;
|
||||||
|
background: rgb(244, 245, 246);
|
||||||
|
position: relative;
|
||||||
|
border-radius: 10rpx;
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
display: flex;
|
||||||
|
/* #endif */
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.u-preview-wrap {
|
||||||
|
border: 1px solid rgb(235, 236, 238);
|
||||||
|
}
|
||||||
|
|
||||||
|
.u-add-wrap {
|
||||||
|
flex-direction: column;
|
||||||
|
color: $u-content-color;
|
||||||
|
font-size: 26rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.u-add-tips {
|
||||||
|
margin-top: 20rpx;
|
||||||
|
line-height: 40rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.u-add-wrap__hover {
|
||||||
|
background-color: rgb(235, 236, 238);
|
||||||
|
}
|
||||||
|
|
||||||
|
.u-preview-image {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
border-radius: 10rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.u-delete-icon {
|
||||||
|
position: absolute;
|
||||||
|
top: 10rpx;
|
||||||
|
right: 10rpx;
|
||||||
|
z-index: 10;
|
||||||
|
background-color: $u-type-error;
|
||||||
|
border-radius: 100rpx;
|
||||||
|
width: 44rpx;
|
||||||
|
height: 44rpx;
|
||||||
|
@include vue-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.u-icon {
|
||||||
|
@include vue-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.u-progress {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 10rpx;
|
||||||
|
left: 8rpx;
|
||||||
|
right: 8rpx;
|
||||||
|
z-index: 9;
|
||||||
|
width: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.u-error-btn {
|
||||||
|
color: #ffffff;
|
||||||
|
background-color: $u-type-error;
|
||||||
|
font-size: 20rpx;
|
||||||
|
padding: 4px 0;
|
||||||
|
text-align: center;
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
z-index: 9;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
148
components/claim-patient-modal/claim-patient-modal.vue
Normal file
@@ -0,0 +1,148 @@
|
|||||||
|
<template>
|
||||||
|
<!-- 居中模态框确认认领(非底部抽屉) -->
|
||||||
|
<u-modal
|
||||||
|
v-model="show"
|
||||||
|
title="认领就诊人"
|
||||||
|
:content="modalContent"
|
||||||
|
:show-cancel-button="true"
|
||||||
|
confirm-text="确认认领"
|
||||||
|
cancel-text="取消"
|
||||||
|
confirm-color="#0d9488"
|
||||||
|
:mask-close-able="false"
|
||||||
|
@confirm="onConfirm"
|
||||||
|
@cancel="onClose"
|
||||||
|
></u-modal>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { claimPatientApi } from '@/request/api/patient.js'
|
||||||
|
import { unwrapXkApi } from '@/utils/api-response.js'
|
||||||
|
import { registePay } from '@/request/api/register.js'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 扫码认领医生创建的就诊人(居中 u-modal)
|
||||||
|
* App.vue 写入 claim_user_patient_id 后弹出
|
||||||
|
*/
|
||||||
|
export default {
|
||||||
|
name: 'ClaimPatientModal',
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
show: false,
|
||||||
|
userPatientId: 0,
|
||||||
|
needPay: false,
|
||||||
|
price: '0',
|
||||||
|
registerId: 0,
|
||||||
|
claiming: false,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
modalContent() {
|
||||||
|
const id = this.userPatientId || '—'
|
||||||
|
let text = '医生为您创建了就诊人档案(就诊人ID:' + id + '),确认后绑定到当前微信账号。'
|
||||||
|
if (this.needPay) {
|
||||||
|
text += '需支付挂号费:¥' + this.price + '。'
|
||||||
|
}
|
||||||
|
return text
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
/**
|
||||||
|
* 对外打开:读取 storage 中的认领 ID
|
||||||
|
*/
|
||||||
|
openFromStorage() {
|
||||||
|
const id = Number(uni.getStorageSync('claim_user_patient_id') || 0)
|
||||||
|
if (id < 1) return
|
||||||
|
const token = uni.getStorageSync('token')
|
||||||
|
if (!token) return
|
||||||
|
this.userPatientId = id
|
||||||
|
this.needPay = false
|
||||||
|
this.price = '0'
|
||||||
|
this.registerId = 0
|
||||||
|
this.show = true
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 取消认领:关闭并清理扫码标记
|
||||||
|
*/
|
||||||
|
onClose() {
|
||||||
|
this.show = false
|
||||||
|
uni.removeStorageSync('claim_user_patient_id')
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 确认认领;若有未付挂号费则拉起支付
|
||||||
|
*/
|
||||||
|
async onConfirm() {
|
||||||
|
if (this.claiming || this.userPatientId < 1) return
|
||||||
|
this.claiming = true
|
||||||
|
try {
|
||||||
|
const res = await claimPatientApi({ user_patient_id: this.userPatientId })
|
||||||
|
const { ok, payload, message } = unwrapXkApi(res)
|
||||||
|
if (!ok) {
|
||||||
|
uni.showToast({ title: message || '认领失败', icon: 'none' })
|
||||||
|
// 失败重新打开,允许重试
|
||||||
|
this.show = true
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const needPay = Number(payload && payload.need_pay_register) === 1
|
||||||
|
const registerId = Number(payload && payload.register_id) || 0
|
||||||
|
const price = (payload && payload.price) || '0'
|
||||||
|
uni.removeStorageSync('claim_user_patient_id')
|
||||||
|
if (needPay && registerId > 0) {
|
||||||
|
this.needPay = true
|
||||||
|
this.registerId = registerId
|
||||||
|
this.price = String(price)
|
||||||
|
this.show = false
|
||||||
|
await this.payRegister(registerId)
|
||||||
|
} else {
|
||||||
|
uni.showToast({ title: '认领成功', icon: 'success' })
|
||||||
|
this.show = false
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
uni.showToast({ title: (e && e.message) || '认领失败', icon: 'none' })
|
||||||
|
this.show = true
|
||||||
|
} finally {
|
||||||
|
this.claiming = false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 认领后支付挂号费(xk-api register/pay)
|
||||||
|
*/
|
||||||
|
async payRegister(registerId) {
|
||||||
|
try {
|
||||||
|
const res = await registePay({
|
||||||
|
method: 'post',
|
||||||
|
data: { register_id: registerId },
|
||||||
|
})
|
||||||
|
// registePay 为 xk-api:按 code/result/message 取值
|
||||||
|
if (res.data && (res.data.code == 0 || res.data.code === '0')) {
|
||||||
|
const data = res.data.result || {}
|
||||||
|
if (data.is_paid == 1 || data.is_pay == 1) {
|
||||||
|
uni.showToast({ title: '认领成功', icon: 'success' })
|
||||||
|
return
|
||||||
|
}
|
||||||
|
uni.requestPayment({
|
||||||
|
provider: data.appId,
|
||||||
|
timeStamp: data.timestamp || data.timeStamp,
|
||||||
|
nonceStr: data.nonceStr,
|
||||||
|
package: data.package,
|
||||||
|
signType: data.signType,
|
||||||
|
paySign: data.paySign,
|
||||||
|
success: () => {
|
||||||
|
uni.showToast({ title: '支付成功', icon: 'success' })
|
||||||
|
},
|
||||||
|
fail: () => {
|
||||||
|
uni.showToast({ title: '已认领,挂号费未支付', icon: 'none' })
|
||||||
|
},
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
uni.showToast({
|
||||||
|
title: (res.data && res.data.message) || '获取支付参数失败',
|
||||||
|
icon: 'none',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
uni.showToast({ title: '支付发起失败', icon: 'none' })
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
676
components/image-compress-popup/image-compress-popup.vue
Normal file
@@ -0,0 +1,676 @@
|
|||||||
|
<template>
|
||||||
|
|
||||||
|
<u-popup v-model="visible" mode="center" width="85%" border-radius="16" :mask-close-able="false">
|
||||||
|
|
||||||
|
<view class="popup-wrap">
|
||||||
|
|
||||||
|
<view class="popup-title">图片较大</view>
|
||||||
|
|
||||||
|
<view v-if="sizeText" class="size-text">{{ sizeText }}</view>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<view v-if="status === 'compressing'" class="compressing-panel">
|
||||||
|
|
||||||
|
<image
|
||||||
|
|
||||||
|
v-if="originalPath"
|
||||||
|
|
||||||
|
:src="originalPath"
|
||||||
|
|
||||||
|
mode="aspectFit"
|
||||||
|
|
||||||
|
class="preview-image single"
|
||||||
|
|
||||||
|
@click="previewImage(originalPath)"
|
||||||
|
|
||||||
|
/>
|
||||||
|
|
||||||
|
<text v-if="originalPath" class="preview-hint">点击预览</text>
|
||||||
|
|
||||||
|
<view class="compressing-status">
|
||||||
|
|
||||||
|
<u-loading mode="circle" />
|
||||||
|
|
||||||
|
<text class="progress-text">{{ progressText }}</text>
|
||||||
|
|
||||||
|
</view>
|
||||||
|
|
||||||
|
</view>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<view v-else-if="status === 'ready'" class="compare-panel">
|
||||||
|
|
||||||
|
<view class="preview-column">
|
||||||
|
|
||||||
|
<text class="preview-label">原图</text>
|
||||||
|
|
||||||
|
<image
|
||||||
|
|
||||||
|
:src="originalPath"
|
||||||
|
|
||||||
|
mode="aspectFit"
|
||||||
|
|
||||||
|
class="preview-image"
|
||||||
|
|
||||||
|
@click="previewImage(originalPath)"
|
||||||
|
|
||||||
|
/>
|
||||||
|
|
||||||
|
<text class="preview-size">{{ formatFileSize(originalSize) }}</text>
|
||||||
|
|
||||||
|
<text class="preview-hint">点击预览</text>
|
||||||
|
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="preview-column">
|
||||||
|
|
||||||
|
<text class="preview-label">压缩后</text>
|
||||||
|
|
||||||
|
<image
|
||||||
|
|
||||||
|
:src="compressedPath"
|
||||||
|
|
||||||
|
mode="aspectFit"
|
||||||
|
|
||||||
|
class="preview-image"
|
||||||
|
|
||||||
|
@click="previewImage(compressedPath)"
|
||||||
|
|
||||||
|
/>
|
||||||
|
|
||||||
|
<text class="preview-size">{{ formatFileSize(compressedSize) }}</text>
|
||||||
|
|
||||||
|
<text class="preview-hint">点击预览</text>
|
||||||
|
|
||||||
|
</view>
|
||||||
|
|
||||||
|
</view>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<view v-else-if="status === 'gifSkipped'" class="gif-panel">
|
||||||
|
|
||||||
|
<image
|
||||||
|
|
||||||
|
v-if="originalPath"
|
||||||
|
|
||||||
|
:src="originalPath"
|
||||||
|
|
||||||
|
mode="aspectFit"
|
||||||
|
|
||||||
|
class="preview-image single"
|
||||||
|
|
||||||
|
@click="previewImage(originalPath)"
|
||||||
|
|
||||||
|
/>
|
||||||
|
|
||||||
|
<text v-if="originalPath" class="preview-hint">点击预览</text>
|
||||||
|
|
||||||
|
<text class="hint-text">GIF 不支持压缩,将上传原图。</text>
|
||||||
|
|
||||||
|
</view>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<view v-else class="error-panel">
|
||||||
|
|
||||||
|
<image
|
||||||
|
|
||||||
|
v-if="originalPath"
|
||||||
|
|
||||||
|
:src="originalPath"
|
||||||
|
|
||||||
|
mode="aspectFit"
|
||||||
|
|
||||||
|
class="preview-image single"
|
||||||
|
|
||||||
|
@click="previewImage(originalPath)"
|
||||||
|
|
||||||
|
/>
|
||||||
|
|
||||||
|
<text v-if="originalPath" class="preview-hint">点击预览</text>
|
||||||
|
|
||||||
|
<text class="error-text">{{ errorMessage }}</text>
|
||||||
|
|
||||||
|
</view>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<view class="footer-actions">
|
||||||
|
|
||||||
|
<view class="btn btn-default" @click="finish('cancel')">取消</view>
|
||||||
|
|
||||||
|
<view
|
||||||
|
|
||||||
|
v-if="status === 'ready' || status === 'error'"
|
||||||
|
|
||||||
|
class="btn btn-default"
|
||||||
|
|
||||||
|
@click="finish('original')"
|
||||||
|
|
||||||
|
>
|
||||||
|
|
||||||
|
{{ originalButtonLabel }}
|
||||||
|
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view
|
||||||
|
|
||||||
|
v-if="status === 'ready'"
|
||||||
|
|
||||||
|
class="btn btn-primary"
|
||||||
|
|
||||||
|
@click="finish('compressed')"
|
||||||
|
|
||||||
|
>
|
||||||
|
|
||||||
|
{{ compressedButtonLabel }}
|
||||||
|
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view
|
||||||
|
|
||||||
|
v-if="status === 'gifSkipped'"
|
||||||
|
|
||||||
|
class="btn btn-primary"
|
||||||
|
|
||||||
|
@click="finish('original')"
|
||||||
|
|
||||||
|
>
|
||||||
|
|
||||||
|
{{ originalButtonLabel }}
|
||||||
|
|
||||||
|
</view>
|
||||||
|
|
||||||
|
</view>
|
||||||
|
|
||||||
|
</view>
|
||||||
|
|
||||||
|
</u-popup>
|
||||||
|
|
||||||
|
</template>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<script>
|
||||||
|
|
||||||
|
import {
|
||||||
|
|
||||||
|
formatFileSize,
|
||||||
|
|
||||||
|
formatSavingsPercent,
|
||||||
|
|
||||||
|
isGifPath,
|
||||||
|
|
||||||
|
tryCompressImage,
|
||||||
|
|
||||||
|
} from '@/utils/image-compress.js';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export default {
|
||||||
|
|
||||||
|
name: 'ImageCompressPopup',
|
||||||
|
|
||||||
|
data() {
|
||||||
|
|
||||||
|
return {
|
||||||
|
|
||||||
|
visible: false,
|
||||||
|
|
||||||
|
status: 'compressing',
|
||||||
|
|
||||||
|
progressText: '正在压缩,请稍候…',
|
||||||
|
|
||||||
|
errorMessage: '',
|
||||||
|
|
||||||
|
originalPath: '',
|
||||||
|
|
||||||
|
compressedPath: '',
|
||||||
|
|
||||||
|
originalSize: 0,
|
||||||
|
|
||||||
|
compressedSize: 0,
|
||||||
|
|
||||||
|
skipped: false,
|
||||||
|
|
||||||
|
resolver: null,
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
computed: {
|
||||||
|
|
||||||
|
sizeText() {
|
||||||
|
|
||||||
|
if (!this.originalSize) return '';
|
||||||
|
|
||||||
|
const originalText = formatFileSize(this.originalSize);
|
||||||
|
|
||||||
|
if (this.status === 'gifSkipped') {
|
||||||
|
|
||||||
|
return `原图 ${originalText}`;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.compressedSize && this.status === 'ready') {
|
||||||
|
|
||||||
|
const savings = formatSavingsPercent(this.originalSize, this.compressedSize);
|
||||||
|
|
||||||
|
return `原图 ${originalText} → 压缩后 ${formatFileSize(this.compressedSize)}${savings}`;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.compressedSize) {
|
||||||
|
|
||||||
|
return `原图 ${originalText} → 压缩后 ${formatFileSize(this.compressedSize)}`;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return `原图 ${originalText}`;
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
originalButtonLabel() {
|
||||||
|
|
||||||
|
if (!this.originalSize) return '使用原图';
|
||||||
|
|
||||||
|
return `使用原图 (${formatFileSize(this.originalSize)})`;
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
compressedButtonLabel() {
|
||||||
|
|
||||||
|
if (!this.compressedSize) return '使用压缩图';
|
||||||
|
|
||||||
|
return `使用压缩图 (${formatFileSize(this.compressedSize)})`;
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
|
||||||
|
formatFileSize,
|
||||||
|
|
||||||
|
previewImage(current) {
|
||||||
|
|
||||||
|
if (!this.originalPath) return;
|
||||||
|
|
||||||
|
const urls =
|
||||||
|
|
||||||
|
this.status === 'ready' && this.compressedPath
|
||||||
|
|
||||||
|
? [this.originalPath, this.compressedPath]
|
||||||
|
|
||||||
|
: [this.originalPath];
|
||||||
|
|
||||||
|
uni.previewImage({
|
||||||
|
|
||||||
|
urls,
|
||||||
|
|
||||||
|
current,
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
open({ path, size }) {
|
||||||
|
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
|
||||||
|
this.resolver = resolve;
|
||||||
|
|
||||||
|
this.originalPath = path;
|
||||||
|
|
||||||
|
this.originalSize = size;
|
||||||
|
|
||||||
|
this.compressedPath = '';
|
||||||
|
|
||||||
|
this.compressedSize = 0;
|
||||||
|
|
||||||
|
this.skipped = false;
|
||||||
|
|
||||||
|
this.errorMessage = '';
|
||||||
|
|
||||||
|
this.progressText = '正在压缩,请稍候…';
|
||||||
|
|
||||||
|
this.visible = true;
|
||||||
|
|
||||||
|
this.startCompress(path, size);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
async startCompress(path, size) {
|
||||||
|
|
||||||
|
if (isGifPath(path)) {
|
||||||
|
|
||||||
|
this.skipped = true;
|
||||||
|
|
||||||
|
this.status = 'gifSkipped';
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
this.status = 'compressing';
|
||||||
|
|
||||||
|
this.progressText = '正在压缩(质量 80%)…';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
const compressed = await tryCompressImage(path, [80, 60, 40], (quality) => {
|
||||||
|
|
||||||
|
this.progressText = `正在压缩(质量 ${quality}%)…`;
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
this.compressedPath = compressed.path;
|
||||||
|
|
||||||
|
this.compressedSize = compressed.size;
|
||||||
|
|
||||||
|
this.status = 'ready';
|
||||||
|
|
||||||
|
this.progressText = '';
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
|
||||||
|
this.status = 'error';
|
||||||
|
|
||||||
|
this.errorMessage = '图片压缩失败,请使用原图或取消';
|
||||||
|
|
||||||
|
this.progressText = '';
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
finish(choice) {
|
||||||
|
|
||||||
|
const result = { choice, path: null, size: 0, usedCompress: false };
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if (choice === 'cancel') {
|
||||||
|
|
||||||
|
this.visible = false;
|
||||||
|
|
||||||
|
this.resolver && this.resolver(null);
|
||||||
|
|
||||||
|
this.resolver = null;
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if (choice === 'compressed' && this.status === 'ready') {
|
||||||
|
|
||||||
|
result.path = this.compressedPath;
|
||||||
|
|
||||||
|
result.size = this.compressedSize;
|
||||||
|
|
||||||
|
result.usedCompress = true;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
result.path = this.originalPath;
|
||||||
|
|
||||||
|
result.size = this.originalSize;
|
||||||
|
|
||||||
|
result.usedCompress = false;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
this.visible = false;
|
||||||
|
|
||||||
|
this.resolver && this.resolver(result);
|
||||||
|
|
||||||
|
this.resolver = null;
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
|
||||||
|
.popup-wrap {
|
||||||
|
|
||||||
|
padding: 32rpx;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.popup-title {
|
||||||
|
|
||||||
|
font-size: 32rpx;
|
||||||
|
|
||||||
|
font-weight: 600;
|
||||||
|
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
margin-bottom: 16rpx;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.size-text {
|
||||||
|
|
||||||
|
font-size: 26rpx;
|
||||||
|
|
||||||
|
color: #666;
|
||||||
|
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
margin-bottom: 24rpx;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.preview-image {
|
||||||
|
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
height: 280rpx;
|
||||||
|
|
||||||
|
background: #fafafa;
|
||||||
|
|
||||||
|
border-radius: 12rpx;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.preview-image.single {
|
||||||
|
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.compare-panel {
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
gap: 16rpx;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.preview-column {
|
||||||
|
|
||||||
|
flex: 1;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.preview-label {
|
||||||
|
|
||||||
|
font-size: 26rpx;
|
||||||
|
|
||||||
|
font-weight: 500;
|
||||||
|
|
||||||
|
margin-bottom: 12rpx;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.preview-size {
|
||||||
|
|
||||||
|
margin-top: 8rpx;
|
||||||
|
|
||||||
|
font-size: 22rpx;
|
||||||
|
|
||||||
|
color: #999;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.preview-hint {
|
||||||
|
|
||||||
|
margin-top: 4rpx;
|
||||||
|
|
||||||
|
font-size: 22rpx;
|
||||||
|
|
||||||
|
color: #bbb;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.compressing-panel,
|
||||||
|
|
||||||
|
.gif-panel,
|
||||||
|
|
||||||
|
.error-panel {
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
gap: 24rpx;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.compressing-status {
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
gap: 16rpx;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.progress-text,
|
||||||
|
|
||||||
|
.hint-text {
|
||||||
|
|
||||||
|
font-size: 26rpx;
|
||||||
|
|
||||||
|
color: #666;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.error-text {
|
||||||
|
|
||||||
|
font-size: 26rpx;
|
||||||
|
|
||||||
|
color: #fa3534;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.footer-actions {
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
justify-content: flex-end;
|
||||||
|
|
||||||
|
flex-wrap: wrap;
|
||||||
|
|
||||||
|
gap: 16rpx;
|
||||||
|
|
||||||
|
margin-top: 32rpx;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
|
||||||
|
min-width: 160rpx;
|
||||||
|
|
||||||
|
padding: 16rpx 24rpx;
|
||||||
|
|
||||||
|
border-radius: 8rpx;
|
||||||
|
|
||||||
|
font-size: 26rpx;
|
||||||
|
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.btn-default {
|
||||||
|
|
||||||
|
background: #f5f5f5;
|
||||||
|
|
||||||
|
color: #333;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.btn-primary {
|
||||||
|
|
||||||
|
background: #2979ff;
|
||||||
|
|
||||||
|
color: #fff;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
|
|
||||||
@@ -0,0 +1,83 @@
|
|||||||
|
<template>
|
||||||
|
<!-- 居中模态框确认代付(非底部抽屉) -->
|
||||||
|
<u-modal
|
||||||
|
v-model="show"
|
||||||
|
title="医生代付确认"
|
||||||
|
:content="modalContent"
|
||||||
|
:show-cancel-button="true"
|
||||||
|
confirm-text="确认代付"
|
||||||
|
cancel-text="取消代付"
|
||||||
|
confirm-color="#0d9488"
|
||||||
|
:mask-close-able="false"
|
||||||
|
@confirm="onConfirm"
|
||||||
|
@cancel="onCancel"
|
||||||
|
></u-modal>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
/**
|
||||||
|
* 扫码代付前确认模态框
|
||||||
|
* App.vue 写入 proxy_pay_order_id 后弹出;取消则清理 storage
|
||||||
|
*/
|
||||||
|
export default {
|
||||||
|
name: 'ProxyPayConfirmModal',
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
show: false,
|
||||||
|
orderId: 0,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
modalContent() {
|
||||||
|
const id = this.orderId || '—'
|
||||||
|
return '医生邀请您代为支付药品订单(订单ID:' + id + ')。确认后进入支付页;取消则清除本次扫码,下次进入小程序不会再跳转。'
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
/**
|
||||||
|
* 清理本次代付扫码会话(storage)
|
||||||
|
*/
|
||||||
|
clearProxyPaySession() {
|
||||||
|
uni.removeStorageSync('proxy_pay_order_id')
|
||||||
|
uni.removeStorageSync('proxy_pay_confirmed')
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 对外打开:读取 storage 中的代付订单 ID
|
||||||
|
*/
|
||||||
|
openFromStorage() {
|
||||||
|
const id = Number(uni.getStorageSync('proxy_pay_order_id') || 0)
|
||||||
|
if (id < 1) return
|
||||||
|
// 已确认过并进过支付页:不再弹窗(避免首页 onShow 反复打断)
|
||||||
|
if (Number(uni.getStorageSync('proxy_pay_confirmed') || 0) === 1) return
|
||||||
|
const token = uni.getStorageSync('token')
|
||||||
|
if (!token) return
|
||||||
|
this.orderId = id
|
||||||
|
this.show = true
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 取消代付:清理扫码标记,下次进小程序不再跳转
|
||||||
|
*/
|
||||||
|
onCancel() {
|
||||||
|
this.clearProxyPaySession()
|
||||||
|
this.show = false
|
||||||
|
uni.showToast({ title: '已取消代付', icon: 'none' })
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 确认后进入订单支付页(保留 proxy_pay_order_id 供支付接口使用)
|
||||||
|
*/
|
||||||
|
onConfirm() {
|
||||||
|
const orderId = this.orderId || Number(uni.getStorageSync('proxy_pay_order_id') || 0)
|
||||||
|
if (orderId < 1) {
|
||||||
|
this.clearProxyPaySession()
|
||||||
|
this.show = false
|
||||||
|
return
|
||||||
|
}
|
||||||
|
uni.setStorageSync('proxy_pay_confirmed', 1)
|
||||||
|
this.show = false
|
||||||
|
uni.navigateTo({
|
||||||
|
url: '/subPackages/my/record-pay?order_id=' + orderId + '&proxy_pay=1',
|
||||||
|
})
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
181
components/unpaid-register-drawer/UnpaidRegisterDrawer.vue
Normal file
@@ -0,0 +1,181 @@
|
|||||||
|
<template>
|
||||||
|
<u-popup
|
||||||
|
v-model="popupVisible"
|
||||||
|
mode="bottom"
|
||||||
|
border-radius="24"
|
||||||
|
:safe-area-inset-bottom="true"
|
||||||
|
:closeable="true"
|
||||||
|
@close="onPopupClose"
|
||||||
|
>
|
||||||
|
<view class="drawer-inner">
|
||||||
|
<view class="drawer-header">
|
||||||
|
<text class="drawer-title">选择待支付挂号</text>
|
||||||
|
</view>
|
||||||
|
<view v-if="!list.length" class="drawer-empty">暂无待支付挂号订单</view>
|
||||||
|
<scroll-view v-else scroll-y class="drawer-scroll">
|
||||||
|
<view
|
||||||
|
v-for="item in list"
|
||||||
|
:key="item.id"
|
||||||
|
class="drawer-item"
|
||||||
|
@click="onSelect(item)"
|
||||||
|
>
|
||||||
|
<view class="item-main">
|
||||||
|
<view class="item-row">
|
||||||
|
<text class="item-label">就诊人</text>
|
||||||
|
<text class="item-value">{{ displayText(item.patient) }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="item-row">
|
||||||
|
<text class="item-label">医生</text>
|
||||||
|
<text class="item-value">{{ displayText(item.doctor) }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="item-row">
|
||||||
|
<text class="item-label">诊所</text>
|
||||||
|
<text class="item-value">{{ displayText(item.store) }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="item-row">
|
||||||
|
<text class="item-label">挂号时间</text>
|
||||||
|
<text class="item-value">{{ displayText(item.created_at) }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<u-icon name="arrow-right" color="#94A3B8" size="28"></u-icon>
|
||||||
|
</view>
|
||||||
|
</scroll-view>
|
||||||
|
</view>
|
||||||
|
</u-popup>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
/**
|
||||||
|
* 待支付挂号订单选择抽屉
|
||||||
|
* 首页多条待付款挂号时,供用户选择具体订单前往支付
|
||||||
|
*/
|
||||||
|
export default {
|
||||||
|
name: 'UnpaidRegisterDrawer',
|
||||||
|
props: {
|
||||||
|
// v-model 控制抽屉显示隐藏
|
||||||
|
value: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
// 待支付挂号列表,字段来自 fetchUnpaidRegisterListApi
|
||||||
|
list: {
|
||||||
|
type: Array,
|
||||||
|
default: () => [],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
popupVisible: {
|
||||||
|
get() {
|
||||||
|
return this.value;
|
||||||
|
},
|
||||||
|
set(val) {
|
||||||
|
this.$emit('input', val);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
/**
|
||||||
|
* 字段为空时显示占位符
|
||||||
|
* @param {string} val 展示值
|
||||||
|
*/
|
||||||
|
displayText(val) {
|
||||||
|
const text = val != null ? String(val).trim() : '';
|
||||||
|
return text || '--';
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 关闭抽屉
|
||||||
|
*/
|
||||||
|
onPopupClose() {
|
||||||
|
this.$emit('input', false);
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 选中某条挂号订单,通知父组件跳转支付
|
||||||
|
* @param {Object} item 挂号订单
|
||||||
|
*/
|
||||||
|
onSelect(item) {
|
||||||
|
if (!item || item.id == null) return;
|
||||||
|
this.$emit('select', item.id);
|
||||||
|
this.$emit('input', false);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.drawer-inner {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
max-height: 70vh;
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding: 24rpx 24rpx 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.drawer-header {
|
||||||
|
padding-bottom: 20rpx;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.drawer-title {
|
||||||
|
font-size: 32rpx;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #0f172a;
|
||||||
|
}
|
||||||
|
|
||||||
|
.drawer-empty {
|
||||||
|
padding: 48rpx 0 64rpx;
|
||||||
|
text-align: center;
|
||||||
|
color: #94a3b8;
|
||||||
|
font-size: 28rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.drawer-scroll {
|
||||||
|
max-height: 60vh;
|
||||||
|
min-height: 200rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.drawer-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 24rpx 20rpx;
|
||||||
|
margin-bottom: 16rpx;
|
||||||
|
background: linear-gradient(90deg, rgba(65, 117, 238, 0.06) 0%, rgba(65, 117, 238, 0.02) 100%);
|
||||||
|
border: 1rpx solid rgba(65, 117, 238, 0.15);
|
||||||
|
border-radius: 16rpx;
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
opacity: 0.85;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-main {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
margin-right: 16rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
margin-bottom: 10rpx;
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-label {
|
||||||
|
flex-shrink: 0;
|
||||||
|
width: 140rpx;
|
||||||
|
font-size: 26rpx;
|
||||||
|
color: #64748b;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-value {
|
||||||
|
flex: 1;
|
||||||
|
font-size: 26rpx;
|
||||||
|
color: #0f172a;
|
||||||
|
line-height: 1.5;
|
||||||
|
word-break: break-all;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
8
main.js
@@ -6,12 +6,20 @@ import Vue from 'vue'
|
|||||||
// main.js
|
// main.js
|
||||||
import uView from "uview-ui";
|
import uView from "uview-ui";
|
||||||
import share from '@/common/share.js'
|
import share from '@/common/share.js'
|
||||||
|
import {setGuestMode} from "@/common/utils/auth";
|
||||||
Vue.mixin(share)
|
Vue.mixin(share)
|
||||||
Vue.use(uView);
|
Vue.use(uView);
|
||||||
|
|
||||||
//防抖函数
|
//防抖函数
|
||||||
import common from './common/common.js'
|
import common from './common/common.js'
|
||||||
Vue.prototype.$noMultipleClicks = common.noMultipleClicks;
|
Vue.prototype.$noMultipleClicks = common.noMultipleClicks;
|
||||||
|
|
||||||
|
const token = uni.getStorageSync('token');
|
||||||
|
const userInfo = uni.getStorageSync('userinfo');
|
||||||
|
if (!token || !userInfo) {
|
||||||
|
console.log('未登录')
|
||||||
|
setGuestMode();
|
||||||
|
}
|
||||||
//时间戳的处理
|
//时间戳的处理
|
||||||
Vue.filter("formatDate", function(value) {
|
Vue.filter("formatDate", function(value) {
|
||||||
var date = new Date(value * 1000); //时间戳为10位需*1000,时间戳为13位的话不需乘1000
|
var date = new Date(value * 1000); //时间戳为10位需*1000,时间戳为13位的话不需乘1000
|
||||||
|
|||||||
181
mixins/patientTabList.js
Normal file
@@ -0,0 +1,181 @@
|
|||||||
|
/**
|
||||||
|
* 就诊人 Tab + swiper 列表公共逻辑(处方/挂号/病历复用)
|
||||||
|
* 页面需实现:fetchPatientList(patientId, page) → Promise 返回完整接口 res
|
||||||
|
*/
|
||||||
|
import { getPatientListApi } from '@/request/api/patient.js'
|
||||||
|
import { unwrapXkApi } from '@/utils/api-response.js'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
patientList: [],
|
||||||
|
patientTabs: [],
|
||||||
|
current: 0,
|
||||||
|
tabChanging: false,
|
||||||
|
infoList: [],
|
||||||
|
page: 1,
|
||||||
|
totalPage: 1,
|
||||||
|
total: 0,
|
||||||
|
loadMoreStatus: 'nomore',
|
||||||
|
isRefreshing: false,
|
||||||
|
scrollTop: 0,
|
||||||
|
emptyPatient: false,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
currentPatientId() {
|
||||||
|
const p = this.patientList[this.current]
|
||||||
|
return p ? Number(p.id) : 0
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
/**
|
||||||
|
* 拉取就诊人并加载当前 Tab 列表
|
||||||
|
*/
|
||||||
|
async bootstrapPatientTabs() {
|
||||||
|
try {
|
||||||
|
const res = await getPatientListApi({})
|
||||||
|
// getPatientListApi → xk-api
|
||||||
|
const { ok, payload } = unwrapXkApi(res)
|
||||||
|
if (!ok) {
|
||||||
|
this.patientList = []
|
||||||
|
this.patientTabs = []
|
||||||
|
this.emptyPatient = true
|
||||||
|
this.infoList = []
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// xk-api:{ list, latest_register_user_patient_id };兼容旧版纯数组
|
||||||
|
const list = Array.isArray(payload) ? payload : (payload && payload.list) || []
|
||||||
|
const latestId = Array.isArray(payload)
|
||||||
|
? 0
|
||||||
|
: Number((payload && payload.latest_register_user_patient_id) || 0)
|
||||||
|
this.patientList = list
|
||||||
|
this.patientTabs = list.map((p) => ({ name: p.name || '就诊人' }))
|
||||||
|
this.emptyPatient = list.length === 0
|
||||||
|
if (list.length === 0) {
|
||||||
|
this.infoList = []
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// 优先最近挂号就诊人,其次默认就诊人,否则第一个
|
||||||
|
let idx = -1
|
||||||
|
if (latestId > 0) {
|
||||||
|
idx = list.findIndex((p) => Number(p.id) === latestId)
|
||||||
|
}
|
||||||
|
if (idx < 0) {
|
||||||
|
idx = list.findIndex((p) => Number(p.is_default) === 1)
|
||||||
|
}
|
||||||
|
if (idx < 0) {
|
||||||
|
idx = 0
|
||||||
|
}
|
||||||
|
if (this.current >= list.length) {
|
||||||
|
this.current = idx
|
||||||
|
} else if (!this._tabsBootstrapped) {
|
||||||
|
this.current = idx
|
||||||
|
}
|
||||||
|
this._tabsBootstrapped = true
|
||||||
|
this.reloadCurrentTab()
|
||||||
|
} catch (e) {
|
||||||
|
console.error('bootstrapPatientTabs', e)
|
||||||
|
this.emptyPatient = true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onTabChange(index) {
|
||||||
|
if (this.tabChanging) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.tabChanging = true
|
||||||
|
this.changePatientTab(index)
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.tabChanging = false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
onSwiperChange(e) {
|
||||||
|
if (this.tabChanging) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.tabChanging = true
|
||||||
|
this.changePatientTab(e.detail.current)
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.tabChanging = false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
changePatientTab(index) {
|
||||||
|
const tabIndex = Number(index) || 0
|
||||||
|
this.current = tabIndex
|
||||||
|
this.reloadCurrentTab()
|
||||||
|
},
|
||||||
|
reloadCurrentTab() {
|
||||||
|
this.page = 1
|
||||||
|
this.infoList = []
|
||||||
|
this.loadMoreStatus = 'loading'
|
||||||
|
this.fetchCurrentList()
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 页面实现:return getXxxListApi({...})
|
||||||
|
*/
|
||||||
|
fetchPatientList() {
|
||||||
|
return Promise.reject(new Error('请实现 fetchPatientList'))
|
||||||
|
},
|
||||||
|
fetchCurrentList(callback) {
|
||||||
|
const patientId = this.currentPatientId
|
||||||
|
if (!patientId) {
|
||||||
|
this.infoList = []
|
||||||
|
this.loadMoreStatus = 'nomore'
|
||||||
|
if (typeof callback === 'function') {
|
||||||
|
callback()
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.fetchPatientList(patientId, this.page)
|
||||||
|
.then((res) => {
|
||||||
|
// fetchPatientList 约定走 xk-api(处方/挂号/病历)
|
||||||
|
const { ok, payload } = unwrapXkApi(res)
|
||||||
|
if (!ok || !payload) {
|
||||||
|
this.loadMoreStatus = 'nomore'
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const list = payload.list || []
|
||||||
|
const pagination = payload.pagination || {}
|
||||||
|
this.totalPage = Number(pagination.totalPage) || 1
|
||||||
|
this.total = Number(pagination.total) || 0
|
||||||
|
if (this.page > 1) {
|
||||||
|
this.infoList = this.infoList.concat(list)
|
||||||
|
} else {
|
||||||
|
this.infoList = list
|
||||||
|
}
|
||||||
|
this.loadMoreStatus = this.page >= this.totalPage ? 'nomore' : 'loadmore'
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
console.error('fetchCurrentList', e)
|
||||||
|
this.loadMoreStatus = 'nomore'
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
if (typeof callback === 'function') {
|
||||||
|
callback()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
onRefresherRefresh() {
|
||||||
|
this.isRefreshing = true
|
||||||
|
this.page = 1
|
||||||
|
this.infoList = []
|
||||||
|
this.fetchCurrentList(() => {
|
||||||
|
this.isRefreshing = false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
onOrderScrollToLower() {
|
||||||
|
if (this.page >= this.totalPage) {
|
||||||
|
this.loadMoreStatus = 'nomore'
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.page += 1
|
||||||
|
this.loadMoreStatus = 'loading'
|
||||||
|
this.fetchCurrentList()
|
||||||
|
},
|
||||||
|
goAddPatient() {
|
||||||
|
uni.navigateTo({
|
||||||
|
url: '/subPackages/my/myinfo-add',
|
||||||
|
})
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
104
pages.json
@@ -3,19 +3,32 @@
|
|||||||
// 下载安装方式
|
// 下载安装方式
|
||||||
// "^u-(.*)": "@/uview-ui/components/u-$1/u-$1.vue"
|
// "^u-(.*)": "@/uview-ui/components/u-$1/u-$1.vue"
|
||||||
// npm安装方式
|
// npm安装方式
|
||||||
|
// "^u-upload$": "@/components/c-upload/c-upload.vue",
|
||||||
"^u-(.*)": "uview-ui/components/u-$1/u-$1.vue",
|
"^u-(.*)": "uview-ui/components/u-$1/u-$1.vue",
|
||||||
// 消息通知组件
|
// 消息通知组件
|
||||||
"^MessageNotification": "@/components/MessageNotification/MessageNotification.vue"
|
"^MessageNotification": "@/components/MessageNotification/MessageNotification.vue",
|
||||||
|
"^ClaimPatientModal$": "@/components/claim-patient-modal/claim-patient-modal.vue",
|
||||||
|
"^ProxyPayConfirmModal$": "@/components/proxy-pay-confirm-modal/proxy-pay-confirm-modal.vue",
|
||||||
|
"^FollowUpDrugDrawer$": "@/subPackages/doctor/components/FollowUpDrugDrawer.vue",
|
||||||
|
// 列表骨架屏(分包组件,主包页需配合 componentPlaceholder)
|
||||||
|
"^ListSkeleton$": "@/subPackages/common/components/ListSkeleton.vue",
|
||||||
|
// 问诊助手壳(仅分包页使用,放分包以减小主包体积)
|
||||||
|
"^AssistantConsultationShell$": "@/subPackages/common/components/AssistantConsultationShell.vue"
|
||||||
},
|
},
|
||||||
"pages": [
|
"pages": [
|
||||||
{
|
{
|
||||||
"path": "pages/home/home",
|
"path": "pages/home/home",
|
||||||
"style": {
|
"style": {
|
||||||
// "navigationBarTitleText": "custom",
|
// "navigationBarTitleText": "custom",
|
||||||
"navigationStyle": "custom"
|
"navigationStyle": "custom",
|
||||||
|
"enablePullDownRefresh": true,
|
||||||
// "navigationStyle": "default",
|
// "navigationStyle": "default",
|
||||||
// "navigationBarBackgroundColor": "#298DFF",
|
// "navigationBarBackgroundColor": "#298DFF",
|
||||||
// "navigationBarTextStyle": "white"
|
// "navigationBarTextStyle": "white"
|
||||||
|
// 主包异步引用分包 ListSkeleton
|
||||||
|
"componentPlaceholder": {
|
||||||
|
"list-skeleton": "view"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -51,7 +64,12 @@
|
|||||||
{
|
{
|
||||||
"path": "pages/cate/index",
|
"path": "pages/cate/index",
|
||||||
"style": {
|
"style": {
|
||||||
"navigationBarTitleText": "健康资讯"
|
"navigationBarTitleText": "健康资讯",
|
||||||
|
"enablePullDownRefresh": true,
|
||||||
|
// 主包异步引用分包 ListSkeleton
|
||||||
|
"componentPlaceholder": {
|
||||||
|
"list-skeleton": "view"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// "needLogin": true
|
// "needLogin": true
|
||||||
},
|
},
|
||||||
@@ -65,7 +83,12 @@
|
|||||||
{
|
{
|
||||||
"path": "pages/index/index",
|
"path": "pages/index/index",
|
||||||
"style": {
|
"style": {
|
||||||
"navigationBarTitleText": "消息"
|
"navigationBarTitleText": "消息",
|
||||||
|
"enablePullDownRefresh": true,
|
||||||
|
// 主包异步引用分包 ListSkeleton
|
||||||
|
"componentPlaceholder": {
|
||||||
|
"list-skeleton": "view"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// "needLogin": true
|
// "needLogin": true
|
||||||
},
|
},
|
||||||
@@ -185,6 +208,28 @@
|
|||||||
"navigationBarTitleText": "商品详情",
|
"navigationBarTitleText": "商品详情",
|
||||||
"enablePullDownRefresh": false
|
"enablePullDownRefresh": false
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "follow-up/medication-info",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "用药信息",
|
||||||
|
"enablePullDownRefresh": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "special-prescription/list",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "特色药方",
|
||||||
|
"enablePullDownRefresh": false,
|
||||||
|
"disableScroll": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "special-prescription/detail",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "药方详情",
|
||||||
|
"enablePullDownRefresh": false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@@ -270,18 +315,32 @@
|
|||||||
"enablePullDownRefresh": false
|
"enablePullDownRefresh": false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"path": "my/mymedical",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "我的病历",
|
||||||
|
"enablePullDownRefresh": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "my/mymedical-detail",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "病历详情",
|
||||||
|
"enablePullDownRefresh": false
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"path": "my/myrecord",
|
"path": "my/myrecord",
|
||||||
"style": {
|
"style": {
|
||||||
"navigationBarTitleText": "处方记录",
|
"navigationBarTitleText": "我的处方",
|
||||||
"enablePullDownRefresh": true
|
"enablePullDownRefresh": false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "my/myappiont",
|
"path": "my/myappiont",
|
||||||
"style": {
|
"style": {
|
||||||
"navigationBarTitleText": "挂号记录",
|
"navigationBarTitleText": "我的挂号",
|
||||||
"enablePullDownRefresh": true
|
"enablePullDownRefresh": false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -312,6 +371,20 @@
|
|||||||
"navigationBarTitleText": "订单详情",
|
"navigationBarTitleText": "订单详情",
|
||||||
"enablePullDownRefresh": false
|
"enablePullDownRefresh": false
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "my/my-drug/invoice-apply",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "申请开票",
|
||||||
|
"enablePullDownRefresh": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "my/my-drug/invoice-detail",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "开票详情",
|
||||||
|
"enablePullDownRefresh": false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@@ -466,6 +539,21 @@
|
|||||||
"path": "chat/chat",
|
"path": "chat/chat",
|
||||||
"style": {
|
"style": {
|
||||||
"navigationBarTitleText": "在线问诊",
|
"navigationBarTitleText": "在线问诊",
|
||||||
|
"navigationStyle": "custom",
|
||||||
|
"enablePullDownRefresh": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "transfer/transfer-message",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "转诊消息",
|
||||||
|
"enablePullDownRefresh": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "transfer/transfer-consultation",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "转诊咨询",
|
||||||
"enablePullDownRefresh": false
|
"enablePullDownRefresh": false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,11 +43,11 @@
|
|||||||
<!-- 选择坐诊医生 -->
|
<!-- 选择坐诊医生 -->
|
||||||
<view class="doctor_list">选择坐诊医生</view>
|
<view class="doctor_list">选择坐诊医生</view>
|
||||||
<!-- 列表 -->
|
<!-- 列表 -->
|
||||||
<view class="list" v-for="(item,index) in doctorList" :key="item.id" @click="goLookDoctor(item.id)">
|
<view class="list" v-for="(item,index) in doctorList" :key="item.id">
|
||||||
<!-- 图片部分 -->
|
<!-- 图片部分 -->
|
||||||
<view class="list_info">
|
<view class="list_info">
|
||||||
<view class="list_left">
|
<view class="list_left" @click="goLookDoctor(item.id)">
|
||||||
<image :src="item.avatar || '/static/mine/avatar_1.png'" mode="医生头像"></image>
|
<image :src="item.avatar || 'https://xiaokang88.oss-cn-hangzhou.aliyuncs.com/xk-client-wx/static/mine/avatar_1.png'" mode="医生头像"></image>
|
||||||
<!-- 医生 -->
|
<!-- 医生 -->
|
||||||
<view class="list_title">
|
<view class="list_title">
|
||||||
<view class="titles_name">
|
<view class="titles_name">
|
||||||
@@ -61,10 +61,10 @@
|
|||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<view class="list_right">{{ typeMap[type] }}</view>
|
<view class="list_right" @click.stop="goRegister(item)">{{ typeMap[type] }}</view>
|
||||||
</view>
|
</view>
|
||||||
<!-- 文字部分 -->
|
<!-- 文字部分 -->
|
||||||
<view class="card">
|
<view class="card" @click="goLookDoctor(item.id)">
|
||||||
<!-- 擅长 -->
|
<!-- 擅长 -->
|
||||||
<view class="list_going">
|
<view class="list_going">
|
||||||
擅长:{{item.good_at}}
|
擅长:{{item.good_at}}
|
||||||
@@ -129,7 +129,7 @@
|
|||||||
import {
|
import {
|
||||||
dDropdown
|
dDropdown
|
||||||
} from '@/components/d-dropdown/d-dropdown'
|
} from '@/components/d-dropdown/d-dropdown'
|
||||||
import { isGuestMode } from '@/common/utils/auth.js'
|
import { isGuestMode, isLoggedIn, saveRedirectInfo, buildUrlWithParams } from '@/common/utils/auth.js'
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
dDropdown
|
dDropdown
|
||||||
@@ -172,11 +172,71 @@
|
|||||||
type: "",
|
type: "",
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onLoad(e) {
|
async onLoad(e) {
|
||||||
this.type = e.type
|
this.type = e.type
|
||||||
// console.log(e, 'idd');
|
// console.log(e, 'idd');
|
||||||
|
|
||||||
|
// 当 type === 2 (诊所在线问诊) 时,直接获取委托诊所和医生信息并跳转到挂号页面
|
||||||
|
if (this.type === '2') {
|
||||||
|
try {
|
||||||
|
const storeId = uni.getStorageSync('store_id') || '11001';
|
||||||
|
const { getClinicOnlineConsultationInfoApi } = await import('@/request/api/product');
|
||||||
|
const configRes = await getClinicOnlineConsultationInfoApi({ store_id: storeId });
|
||||||
|
|
||||||
|
if (configRes.data?.code === 0 || configRes.data?.code === '0') {
|
||||||
|
const result = configRes.data?.result;
|
||||||
|
|
||||||
|
if (result?.can_use && result?.delegate_doctor_id) {
|
||||||
|
// 直接跳转到就诊人选择页面,传递医生ID和挂号类型
|
||||||
|
uni.redirectTo({
|
||||||
|
url: `/subPackages/doctor/doctor-userinfo?id=${result.delegate_doctor_id}&r_type=2&delegate_store_id=${result.delegate_store_id || storeId}`
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
uni.showToast({
|
||||||
|
title: result?.message || '该门店暂不支持在线问诊功能',
|
||||||
|
icon: 'none',
|
||||||
|
duration: 2000
|
||||||
|
});
|
||||||
|
// 返回上一页
|
||||||
|
setTimeout(() => {
|
||||||
|
uni.navigateBack();
|
||||||
|
}, 2000);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
uni.showToast({
|
||||||
|
title: configRes.data?.message || '获取在线问诊信息失败',
|
||||||
|
icon: 'none',
|
||||||
|
duration: 2000
|
||||||
|
});
|
||||||
|
// 返回上一页
|
||||||
|
setTimeout(() => {
|
||||||
|
uni.navigateBack();
|
||||||
|
}, 2000);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取在线问诊信息失败:', error);
|
||||||
|
uni.showToast({
|
||||||
|
title: '获取在线问诊信息失败',
|
||||||
|
icon: 'none',
|
||||||
|
duration: 2000
|
||||||
|
});
|
||||||
|
// 返回上一页
|
||||||
|
setTimeout(() => {
|
||||||
|
uni.navigateBack();
|
||||||
|
}, 2000);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
resolveRegisterType(pageType) {
|
||||||
|
const t = String(pageType ?? '0');
|
||||||
|
if (['0', '1', '2', '3'].includes(t)) return t;
|
||||||
|
return '0';
|
||||||
|
},
|
||||||
closeDropdown() {
|
closeDropdown() {
|
||||||
this.$refs.uDropdown.close();
|
this.$refs.uDropdown.close();
|
||||||
this.getList()
|
this.getList()
|
||||||
@@ -254,6 +314,60 @@
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
|
async goRegister(item) {
|
||||||
|
if (!isLoggedIn()) {
|
||||||
|
const storeId = uni.getStorageSync('store_id') || '11001';
|
||||||
|
saveRedirectInfo('/subPackages/doctor/doctor-userinfo', {
|
||||||
|
id: item.id,
|
||||||
|
r_type: this.resolveRegisterType(this.type),
|
||||||
|
store_id: storeId,
|
||||||
|
});
|
||||||
|
uni.navigateTo({
|
||||||
|
url: buildUrlWithParams('/pages/login/login', {
|
||||||
|
redirect: 'doctor-userinfo',
|
||||||
|
doctor_id: item.id,
|
||||||
|
store_id: storeId,
|
||||||
|
})
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const rType = this.resolveRegisterType(this.type);
|
||||||
|
if (rType === '2') {
|
||||||
|
try {
|
||||||
|
const storeId = uni.getStorageSync('store_id') || '11001';
|
||||||
|
const { getClinicOnlineConsultationInfoApi } = await import('@/request/api/product');
|
||||||
|
const configRes = await getClinicOnlineConsultationInfoApi({ store_id: storeId });
|
||||||
|
if (configRes.data?.code === 0 || configRes.data?.code === '0') {
|
||||||
|
const result = configRes.data?.result;
|
||||||
|
if (result?.can_use && result?.delegate_doctor_id) {
|
||||||
|
uni.navigateTo({
|
||||||
|
url: `/subPackages/doctor/doctor-userinfo?id=${result.delegate_doctor_id}&r_type=2&delegate_store_id=${result.delegate_store_id || storeId}`
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
uni.showToast({
|
||||||
|
title: result?.message || '该门店暂不支持在线问诊功能',
|
||||||
|
icon: 'none',
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
uni.showToast({
|
||||||
|
title: configRes.data?.message || '获取在线问诊信息失败',
|
||||||
|
icon: 'none',
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取在线问诊信息失败:', error);
|
||||||
|
uni.showToast({ title: '获取在线问诊信息失败', icon: 'none' });
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uni.navigateTo({
|
||||||
|
url: `/subPackages/doctor/doctor-userinfo?id=${item.id}&r_type=${rType}`,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
goProduct() {
|
goProduct() {
|
||||||
uni.navigateTo({
|
uni.navigateTo({
|
||||||
url: '/subPackages/product/product?id=' + id
|
url: '/subPackages/product/product?id=' + id
|
||||||
|
|||||||
@@ -47,7 +47,7 @@
|
|||||||
<view class="it_info">{{item.small_info}}</view>
|
<view class="it_info">{{item.small_info}}</view>
|
||||||
<view class="it_price">
|
<view class="it_price">
|
||||||
<text>{{item.drugstore_drug.price}}</text>
|
<text>{{item.drugstore_drug.price}}</text>
|
||||||
<image src="/static/home/gwc.png" mode=""
|
<image src="https://xiaokang88.oss-cn-hangzhou.aliyuncs.com/xk-client-wx/static/home/gwc.png" mode=""
|
||||||
@tap.stop="toCartImg(item.drugstore_drug.drug_id)"></image>
|
@tap.stop="toCartImg(item.drugstore_drug.drug_id)"></image>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|||||||
@@ -5,7 +5,8 @@
|
|||||||
<view class="search">
|
<view class="search">
|
||||||
<u-search placeholder="输入文章标题" bg-color="#F5f5f5" color="#DDDDDD" border-color="#F5f5f5"
|
<u-search placeholder="输入文章标题" bg-color="#F5f5f5" color="#DDDDDD" border-color="#F5f5f5"
|
||||||
:show-action="false" maxlength="21" height="66" :clearabled="true" shape="round" v-model="keyword"
|
:show-action="false" maxlength="21" height="66" :clearabled="true" shape="round" v-model="keyword"
|
||||||
@search="toSearch">
|
@search="toSearch"
|
||||||
|
@clear="clearSearch">
|
||||||
</u-search>
|
</u-search>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
@@ -13,7 +14,9 @@
|
|||||||
<!-- //药品分类左 -->
|
<!-- //药品分类左 -->
|
||||||
<view class="goods">
|
<view class="goods">
|
||||||
<view class="goods_left" @touchmove.stop>
|
<view class="goods_left" @touchmove.stop>
|
||||||
<scroll-view scroll-y scroll-with-animation class="u-menu-scroll-view" :scroll-top="scrollTop"
|
<!-- 首次加载分类骨架 -->
|
||||||
|
<ListSkeleton v-if="categoryInitialLoading" type="category" :rows="8" />
|
||||||
|
<scroll-view v-else scroll-y scroll-with-animation class="u-menu-scroll-view" :scroll-top="scrollTop"
|
||||||
:scroll-into-view="itemId">
|
:scroll-into-view="itemId">
|
||||||
<view v-for="(item,index) in categoryLists" :key="item.id" class="u-tab-item"
|
<view v-for="(item,index) in categoryLists" :key="item.id" class="u-tab-item"
|
||||||
:class="[num == item.id ? 'u-item-active' : '']" @tap.stop="changeStyle(item.id)"
|
:class="[num == item.id ? 'u-item-active' : '']" @tap.stop="changeStyle(item.id)"
|
||||||
@@ -26,15 +29,18 @@
|
|||||||
<view class="goods_right">
|
<view class="goods_right">
|
||||||
<!-- 药品 -->
|
<!-- 药品 -->
|
||||||
<view class="second">
|
<view class="second">
|
||||||
<!-- 商品列表 -->
|
<!-- 首次或切分类且当前无文章时展示骨架,有旧文章则保留至新结果 -->
|
||||||
<view class="list" v-for="(item,index) in infoList" @click="toDetail(item.id)" :key="item.id">
|
<ListSkeleton v-if="showArticleSkeleton" type="article" :rows="4" />
|
||||||
<view class="list_">
|
<template v-else>
|
||||||
<image :src="item.cover||'/static/xx/cp.png'" mode=""></image>
|
<view class="list" v-for="(item,index) in infoList" @click="toDetail(item.id)" :key="item.id">
|
||||||
<view class="list_title">
|
<view class="list_">
|
||||||
{{item.title}}
|
<image :src="item.cover||'https://xiaokang88.oss-cn-hangzhou.aliyuncs.com/xk-client-wx/static/xx/cp.png'" mode=""></image>
|
||||||
|
<view class="list_title">
|
||||||
|
{{item.title}}
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</template>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
@@ -65,16 +71,36 @@
|
|||||||
selectIndex: 0,
|
selectIndex: 0,
|
||||||
arr: [], // 储存距离顶部高度的数组
|
arr: [], // 储存距离顶部高度的数组
|
||||||
scrollRightTop: 0, // 右边栏目scroll-view的滚动条高度
|
scrollRightTop: 0, // 右边栏目scroll-view的滚动条高度
|
||||||
show: false
|
show: false,
|
||||||
|
// 首次加载骨架
|
||||||
|
categoryInitialLoading: true,
|
||||||
|
articleInitialLoading: true,
|
||||||
|
// 切分类且当前列表为空时拉文章期间展示骨架
|
||||||
|
articleFetchingEmpty: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
// 是否展示右侧文章骨架:首次加载,或请求中且当前无文章可保留
|
||||||
|
showArticleSkeleton() {
|
||||||
|
return this.articleInitialLoading || this.articleFetchingEmpty
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onLoad(op) {
|
onLoad(op) {
|
||||||
|
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
// 搜索
|
// 搜索:按当前分类 + 标题关键词拉文章(不再误调分类接口)
|
||||||
toSearch() {
|
toSearch() {
|
||||||
this.getList()
|
this.infoList = []
|
||||||
|
this.articleFetchingEmpty = true
|
||||||
|
this.getArticleList()
|
||||||
|
},
|
||||||
|
// 清空搜索词后重新拉当前分类文章
|
||||||
|
clearSearch() {
|
||||||
|
this.keyword = ''
|
||||||
|
this.infoList = []
|
||||||
|
this.articleFetchingEmpty = true
|
||||||
|
this.getArticleList()
|
||||||
},
|
},
|
||||||
/*切换需要*/
|
/*切换需要*/
|
||||||
changeStyle(id) {
|
changeStyle(id) {
|
||||||
@@ -86,48 +112,76 @@
|
|||||||
url: '/pages/cate/info-detail?id=' + e
|
url: '/pages/cate/info-detail?id=' + e
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
//点击药品一级分类e
|
// 切分类:立即清空文章出骨架
|
||||||
handleCategory1(e, index) {
|
handleCategory1(e, index) {
|
||||||
this.num = e
|
this.num = e
|
||||||
this.cid = e
|
this.cid = e
|
||||||
|
this.infoList = []
|
||||||
|
this.articleFetchingEmpty = true
|
||||||
this.getArticleList()
|
this.getArticleList()
|
||||||
},
|
},
|
||||||
|
// 获取分类:返回 Promise 供下拉刷新等待
|
||||||
//获取药品分类
|
|
||||||
getList() {
|
getList() {
|
||||||
categoriesList({
|
return categoriesList({
|
||||||
method: "post",
|
method: "post",
|
||||||
data: {
|
data: {
|
||||||
store_id: uni.getStorageSync('store_id') || '11001',
|
store_id: uni.getStorageSync('store_id') || '11001',
|
||||||
}
|
}
|
||||||
}).then((res) => {
|
}).then((res) => {
|
||||||
// console.log(res, 'list');
|
if (res.data.code == 0) {
|
||||||
if (res.data.errcode == 0) {
|
const list = (res.data.result && res.data.result.list) || []
|
||||||
// console.log(res, 'res');
|
this.categoryLists = list
|
||||||
this.categoryLists = res.data.data.list
|
if (!list.length) {
|
||||||
this.cid = res.data.data.list.map(x => x.id)
|
this.infoList = []
|
||||||
this.num = res.data.data.list[0].id //初始选中
|
this.articleInitialLoading = false
|
||||||
// this.current = res.data.data[0].subs[0].id //初始选中2
|
this.articleFetchingEmpty = false
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const firstId = list[0].id
|
||||||
|
this.num = firstId
|
||||||
|
this.cid = firstId
|
||||||
|
return this.getArticleList()
|
||||||
}
|
}
|
||||||
|
}).finally(() => {
|
||||||
|
this.categoryInitialLoading = false
|
||||||
})
|
})
|
||||||
|
|
||||||
this.getArticleList()
|
|
||||||
},
|
},
|
||||||
// 文章列表
|
// 文章列表:可选 keyword 标题搜索
|
||||||
getArticleList() {
|
getArticleList() {
|
||||||
articleList({
|
if (!this.infoList || this.infoList.length === 0) {
|
||||||
|
this.articleFetchingEmpty = true
|
||||||
|
}
|
||||||
|
const data = {
|
||||||
|
store_id: uni.getStorageSync('store_id') || '11001',
|
||||||
|
cid: this.cid
|
||||||
|
}
|
||||||
|
const kw = (this.keyword || '').trim()
|
||||||
|
if (kw) {
|
||||||
|
data.keyword = kw
|
||||||
|
}
|
||||||
|
return articleList({
|
||||||
method: "get",
|
method: "get",
|
||||||
data: {
|
data
|
||||||
store_id: uni.getStorageSync('store_id') || '11001',
|
|
||||||
cid: this.cid
|
|
||||||
}
|
|
||||||
}).then((res) => {
|
}).then((res) => {
|
||||||
// console.log(res, 'list');
|
if (res.data.code == 0) {
|
||||||
if (res.data.errcode == 0) {
|
this.infoList = (res.data.result && res.data.result.list) || []
|
||||||
this.infoList = res.data.data.list
|
|
||||||
// console.log(res, 'list')
|
|
||||||
}
|
}
|
||||||
|
}).finally(() => {
|
||||||
|
this.articleInitialLoading = false
|
||||||
|
this.articleFetchingEmpty = false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 下拉刷新:清空分类/文章并重走开骨架
|
||||||
|
*/
|
||||||
|
onPullDownRefresh() {
|
||||||
|
this.categoryLists = []
|
||||||
|
this.infoList = []
|
||||||
|
this.categoryInitialLoading = true
|
||||||
|
this.articleInitialLoading = true
|
||||||
|
this.articleFetchingEmpty = false
|
||||||
|
Promise.resolve(this.getList()).finally(() => {
|
||||||
|
uni.stopPullDownRefresh()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -135,6 +189,7 @@
|
|||||||
// this.getList();
|
// this.getList();
|
||||||
},
|
},
|
||||||
onShow() {
|
onShow() {
|
||||||
|
// 不清空 categoryLists / infoList,成功后再替换
|
||||||
this.getList();
|
this.getList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,9 +44,9 @@
|
|||||||
}
|
}
|
||||||
}).then((res) => {
|
}).then((res) => {
|
||||||
// console.log(res, 'list');
|
// console.log(res, 'list');
|
||||||
if (res.data.errcode == 0) {
|
if (res.data.code == 0 && res.data.result) {
|
||||||
this.infoList = res.data.data
|
this.infoList = res.data.result
|
||||||
this.content = res.data.data.content
|
this.content = res.data.result.content
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -77,12 +77,12 @@
|
|||||||
<!-- 底部 -->
|
<!-- 底部 -->
|
||||||
<view class="footer">
|
<view class="footer">
|
||||||
<view class="box">
|
<view class="box">
|
||||||
<image src="/static/shop/home.png" mode=""></image>
|
<image src="https://xiaokang88.oss-cn-hangzhou.aliyuncs.com/xk-client-wx/static/shop/home.png" mode=""></image>
|
||||||
<text>首页</text>
|
<text>首页</text>
|
||||||
</view>
|
</view>
|
||||||
<view class="box" @click="toShop">
|
<view class="box" @click="toShop">
|
||||||
<u-badge type="error" :count="gwcNum" size="mini" :offset="[0,16]"></u-badge>
|
<u-badge type="error" :count="gwcNum" size="mini" :offset="[0,16]"></u-badge>
|
||||||
<image :src="gwcNum==0&&'/static/shop/gwc.png' || gwcNum>0&&'/static/shop/gwc_l.png'" mode=""></image>
|
<image :src="gwcNum==0&&'https://xiaokang88.oss-cn-hangzhou.aliyuncs.com/xk-client-wx/static/shop/gwc.png' || gwcNum>0&&'https://xiaokang88.oss-cn-hangzhou.aliyuncs.com/xk-client-wx/static/shop/gwc_l.png'" mode=""></image>
|
||||||
<text :class="gwcNum>0?'active':''">购物车</text>
|
<text :class="gwcNum>0?'active':''">购物车</text>
|
||||||
</view>
|
</view>
|
||||||
<view class="to_btns" @click="toAdd(drugDetailsList.drug_store_relation.drug_id)">
|
<view class="to_btns" @click="toAdd(drugDetailsList.drug_store_relation.drug_id)">
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="content safe-area-inset-bottom">
|
<view class="content safe-area-inset-bottom">
|
||||||
<MessageNotification />
|
<MessageNotification />
|
||||||
|
<ClaimPatientModal ref="claimPatientModal" />
|
||||||
|
<ProxyPayConfirmModal ref="proxyPayConfirmModal" />
|
||||||
<view class="head" @click="gologin">
|
<view class="head" @click="gologin">
|
||||||
<!-- 门店 -->
|
<!-- 门店 -->
|
||||||
<view class="store">
|
<view class="store">
|
||||||
@@ -25,14 +27,14 @@
|
|||||||
<!-- 图片展示 -->
|
<!-- 图片展示 -->
|
||||||
<view class="section" @click="gologin">
|
<view class="section" @click="gologin">
|
||||||
<u-swiper :list="list" :img-mode="aspectFill" :height="300" :interval="4000"></u-swiper>
|
<u-swiper :list="list" :img-mode="aspectFill" :height="300" :interval="4000"></u-swiper>
|
||||||
<!-- <image class="banner" mode="aspectFill" src="/static/home/banner.png"></image> -->
|
<!-- <image class="banner" mode="aspectFill" src="https://xiaokang88.oss-cn-hangzhou.aliyuncs.com/xk-client-wx/static/home/banner.png"></image> -->
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 导航栏 -->
|
<!-- 导航栏 -->
|
||||||
<view class="nav" v-if="isShow_envVersion==false">
|
<view class="nav" v-if="isShow_envVersion==false">
|
||||||
<view class="nav_service" @click="gologin">
|
<view class="nav_service" @click="gologin">
|
||||||
<view class="nav_service_img">
|
<view class="nav_service_img">
|
||||||
<image src="../../static/home/bg1.png" mode=""></image>
|
<image src="https://xiaokang88.oss-cn-hangzhou.aliyuncs.com/xk-client-wx/static/home/bg1.png" mode=""></image>
|
||||||
</view>
|
</view>
|
||||||
<view class="nav_service_title">
|
<view class="nav_service_title">
|
||||||
到店挂号
|
到店挂号
|
||||||
@@ -41,7 +43,7 @@
|
|||||||
|
|
||||||
<view class="nav_service" @click="gologin">
|
<view class="nav_service" @click="gologin">
|
||||||
<view class="nav_service_img">
|
<view class="nav_service_img">
|
||||||
<image src="../../static/home/bg2.png" mode=""></image>
|
<image src="https://xiaokang88.oss-cn-hangzhou.aliyuncs.com/xk-client-wx/static/home/bg2.png" mode=""></image>
|
||||||
</view>
|
</view>
|
||||||
<view class="nav_service_title">
|
<view class="nav_service_title">
|
||||||
预约购药
|
预约购药
|
||||||
@@ -105,7 +107,7 @@
|
|||||||
<!-- 图片部分 -->
|
<!-- 图片部分 -->
|
||||||
<view class="list_infos">
|
<view class="list_infos">
|
||||||
<view class="list_lefts">
|
<view class="list_lefts">
|
||||||
<image :src="item.avatar || '/static/mine/avatar_1.png'" mode="医生头像"></image>
|
<image :src="item.avatar || 'https://xiaokang88.oss-cn-hangzhou.aliyuncs.com/xk-client-wx/static/mine/avatar_1.png'" mode="医生头像"></image>
|
||||||
<!-- 医生 -->
|
<!-- 医生 -->
|
||||||
<view class="list_title">
|
<view class="list_title">
|
||||||
<view class="titles_name">
|
<view class="titles_name">
|
||||||
@@ -153,9 +155,9 @@
|
|||||||
show: true,
|
show: true,
|
||||||
doctorList: [],
|
doctorList: [],
|
||||||
list: [
|
list: [
|
||||||
// '/static/home/banner.png',
|
// 'https://xiaokang88.oss-cn-hangzhou.aliyuncs.com/xk-client-wx/static/home/banner.png',
|
||||||
// '/static/home/banner.png',
|
// 'https://xiaokang88.oss-cn-hangzhou.aliyuncs.com/xk-client-wx/static/home/banner.png',
|
||||||
// '/static/home/banner.png'
|
// 'https://xiaokang88.oss-cn-hangzhou.aliyuncs.com/xk-client-wx/static/home/banner.png'
|
||||||
],
|
],
|
||||||
info:[],
|
info:[],
|
||||||
isShow_envVersion: true
|
isShow_envVersion: true
|
||||||
@@ -239,11 +241,37 @@
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
/** 打开扫码认领就诊人弹窗 */
|
||||||
|
openClaimPatientModal() {
|
||||||
|
const modal = this.$refs.claimPatientModal
|
||||||
|
if (modal && modal.openFromStorage) {
|
||||||
|
modal.openFromStorage()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/** 打开医生代付确认弹窗 */
|
||||||
|
openProxyPayConfirmModal() {
|
||||||
|
const modal = this.$refs.proxyPayConfirmModal
|
||||||
|
if (modal && modal.openFromStorage) {
|
||||||
|
modal.openFromStorage()
|
||||||
|
}
|
||||||
|
},
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.getShow()
|
this.getShow()
|
||||||
this.getList()
|
this.getList()
|
||||||
}
|
uni.$on('open-claim-patient-modal', this.openClaimPatientModal)
|
||||||
|
uni.$on('open-proxy-pay-confirm-modal', this.openProxyPayConfirmModal)
|
||||||
|
this.openClaimPatientModal()
|
||||||
|
this.openProxyPayConfirmModal()
|
||||||
|
},
|
||||||
|
onShow() {
|
||||||
|
this.openClaimPatientModal()
|
||||||
|
this.openProxyPayConfirmModal()
|
||||||
|
},
|
||||||
|
onUnload() {
|
||||||
|
uni.$off('open-claim-patient-modal', this.openClaimPatientModal)
|
||||||
|
uni.$off('open-proxy-pay-confirm-modal', this.openProxyPayConfirmModal)
|
||||||
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -467,7 +495,7 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-around;
|
justify-content: space-around;
|
||||||
background: url('/static/home/bg01.png') no-repeat;
|
background: url('https://xiaokang88.oss-cn-hangzhou.aliyuncs.com/xk-client-wx/static/home/bg01.png') no-repeat;
|
||||||
background-size: 100% 100%;
|
background-size: 100% 100%;
|
||||||
|
|
||||||
.nav_service_img {
|
.nav_service_img {
|
||||||
@@ -490,7 +518,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.nav_service:last-child {
|
.nav_service:last-child {
|
||||||
background: url('/static/home/bg02.png') no-repeat;
|
background: url('https://xiaokang88.oss-cn-hangzhou.aliyuncs.com/xk-client-wx/static/home/bg02.png') no-repeat;
|
||||||
background-size: 100% 100%;
|
background-size: 100% 100%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<MessageNotification />
|
<MessageNotification />
|
||||||
<!-- 描述 -->
|
<!-- 描述 -->
|
||||||
<view class="card" v-for="item in list" :key="item.id" @click="toInfo(item.id)">
|
<view class="card" v-for="item in list" :key="item.id" @click="toInfo(item.id)">
|
||||||
<image :src="item.content['avatar']||'/static/mine/avatar_1.png'" mode=""></image>
|
<image :src="item.content['avatar']||'https://xiaokang88.oss-cn-hangzhou.aliyuncs.com/xk-client-wx/static/mine/avatar_1.png'" mode=""></image>
|
||||||
<view class="info">
|
<view class="info">
|
||||||
<view class="infos_title">
|
<view class="infos_title">
|
||||||
<text class="infos">{{item.content['doctor']}}医生</text>
|
<text class="infos">{{item.content['doctor']}}医生</text>
|
||||||
|
|||||||
@@ -12,85 +12,54 @@
|
|||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 消息列表 -->
|
<!-- 首次加载:宫格骨架,避免 num 未定义时闪「暂无新消息」 -->
|
||||||
<view class="list" @click="goSystem">
|
<view v-if="noticeInitialLoading" class="notice-grid">
|
||||||
<!-- 头像 -->
|
<view v-for="i in 4" :key="i" class="notice-card notice-card--sk">
|
||||||
<view class="avator">
|
<view class="notice-sk-icon"></view>
|
||||||
<view class="img">
|
<view class="notice-card__body">
|
||||||
<image src="/static/xx/xt.png" mode=""></image>
|
<view class="notice-sk-line notice-sk-line--title"></view>
|
||||||
</view>
|
<view class="notice-sk-line"></view>
|
||||||
<u-badge size="default" v-if="system.num>=0" :count="system.num" :is-dot="system.num==0?true:false"
|
|
||||||
type="error" :offset="system.num>0?[-4,-8]:[0,0]"></u-badge>
|
|
||||||
</view>
|
|
||||||
<!-- 描述 -->
|
|
||||||
<view class="info">
|
|
||||||
<view class="infos_title">
|
|
||||||
<text class="infos">系统消息</text>
|
|
||||||
<text class="time">{{ system.time }}</text>
|
|
||||||
</view>
|
|
||||||
<view class="preview" v-if="system.num >0">
|
|
||||||
您有{{ system.num }}条未读信息
|
|
||||||
</view>
|
|
||||||
<view class="preview" v-if="system.num==undefined">
|
|
||||||
暂无新消息
|
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
<!-- 四条固定入口:一行两列宫格,会话列表仍走下方长条 -->
|
||||||
<view class="list" @click="goOrder">
|
<view v-else class="notice-grid">
|
||||||
<!-- 头像 -->
|
<view
|
||||||
<view class="avator">
|
v-for="item in noticeEntries"
|
||||||
<view class="img">
|
:key="item.key"
|
||||||
<image src="/static/xx/cp.png" mode=""></image>
|
class="notice-card"
|
||||||
|
hover-class="notice-card-hover"
|
||||||
|
@click="onNoticeTap(item.key)"
|
||||||
|
>
|
||||||
|
<view class="notice-card__icon">
|
||||||
|
<image :src="item.icon" mode="aspectFit"></image>
|
||||||
|
<u-badge
|
||||||
|
size="mini"
|
||||||
|
v-if="item.showBadge"
|
||||||
|
:count="item.num"
|
||||||
|
:is-dot="item.isDot"
|
||||||
|
type="error"
|
||||||
|
:offset="item.num > 0 ? [-4, -4] : [0, 0]"
|
||||||
|
></u-badge>
|
||||||
</view>
|
</view>
|
||||||
<u-badge size="default" v-if="order.num>=0" :count="order.num" :is-dot="order.num==0?true:false"
|
<view class="notice-card__body">
|
||||||
type="error" :offset="order.num>0?[-4,-8]:[0,0]"></u-badge>
|
<text class="notice-card__title">{{ item.title }}</text>
|
||||||
</view>
|
<text class="notice-card__preview">{{ item.preview }}</text>
|
||||||
<!-- 描述 -->
|
<text v-if="item.time" class="notice-card__time">{{ item.time }}</text>
|
||||||
<view class="info">
|
|
||||||
<view class="infos_title">
|
|
||||||
<text class="infos">产品订单</text>
|
|
||||||
<text class="time">{{ order.time }}</text>
|
|
||||||
</view>
|
|
||||||
<view class="preview" v-if="order.num>0">
|
|
||||||
您有{{ order.num }}条未读信息
|
|
||||||
</view>
|
|
||||||
<view class="preview" v-if="order.num==undefined">
|
|
||||||
暂无新消息
|
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<view class="list" @click="goDoctor">
|
|
||||||
<!-- 头像 -->
|
|
||||||
<view class="avator">
|
|
||||||
<view class="img">
|
|
||||||
<image src="/static/xx/ysxx.png" mode=""></image>
|
|
||||||
</view>
|
|
||||||
<u-badge size="default" v-if="doctor.num>=0" :count="doctor.num" :is-dot="doctor.num==0?true:false"
|
|
||||||
type="error" :offset="doctor.num>0?[-4,-8]:[0,0]"></u-badge>
|
|
||||||
</view>
|
|
||||||
<!-- 描述 -->
|
|
||||||
<view class="info">
|
|
||||||
<view class="infos_title">
|
|
||||||
<text class="infos">医生消息</text>
|
|
||||||
<text class="time">{{ doctor.time }}</text>
|
|
||||||
</view>
|
|
||||||
<view class="preview" v-if="doctor.num>0">
|
|
||||||
您有{{ doctor.num }}条新的消息
|
|
||||||
</view>
|
|
||||||
<view class="preview" v-if="doctor.num==undefined">
|
|
||||||
暂无新消息
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<!-- 模拟<u-divider>在线问诊</u-divider>效果-->
|
|
||||||
|
|
||||||
<!-- 标题 - 在线咨询 -->
|
<!-- 标题 - 在线咨询 -->
|
||||||
<view v-if="checkDev('open-im') && onlineConsultationList.length > 0" class="title">
|
<view v-if="checkDev('open-im') && onlineConsultationList.length > 0" class="title">
|
||||||
<text>在线咨询</text>
|
<text>在线咨询</text>
|
||||||
</view>
|
</view>
|
||||||
|
<!-- IM 会话首次骨架:有旧数据时直接展示旧列表直至替换 -->
|
||||||
|
<ListSkeleton
|
||||||
|
v-if="checkDev('open-im') && chatInitialLoading && onlineConsultationList.length === 0 && onlineReconsultationList.length === 0"
|
||||||
|
type="message"
|
||||||
|
:rows="3"
|
||||||
|
/>
|
||||||
<!-- 在线咨询 - 用户 (type=1) -->
|
<!-- 在线咨询 - 用户 (type=1) -->
|
||||||
<view v-if="checkDev('open-im')" v-for="(item, index) in onlineConsultationList" :key="item.id" class="list" @click="goChat(item, index)">
|
<view v-if="checkDev('open-im')" v-for="(item, index) in onlineConsultationList" :key="item.id" class="list" @click="goChat(item, index)">
|
||||||
<!-- 头像 -->
|
<!-- 头像 -->
|
||||||
@@ -110,7 +79,6 @@
|
|||||||
</view>
|
</view>
|
||||||
<view class="preview">
|
<view class="preview">
|
||||||
<p>{{ item.last_message }}</p>
|
<p>{{ item.last_message }}</p>
|
||||||
<!-- <p v-if="item.un_read_count>0">您有{{item.un_read_count}}条新的消息</p>-->
|
|
||||||
</view>
|
</view>
|
||||||
<view class="preview" v-if="item.last_message===''">
|
<view class="preview" v-if="item.last_message===''">
|
||||||
暂无新消息
|
暂无新消息
|
||||||
@@ -141,7 +109,6 @@
|
|||||||
</view>
|
</view>
|
||||||
<view class="preview">
|
<view class="preview">
|
||||||
<p>{{ item.last_message }}</p>
|
<p>{{ item.last_message }}</p>
|
||||||
<!-- <p v-if="item.un_read_count>0">您有{{item.un_read_count}}条新的消息</p>-->
|
|
||||||
</view>
|
</view>
|
||||||
<view class="preview" v-if="item.last_message===''">
|
<view class="preview" v-if="item.last_message===''">
|
||||||
暂无新消息
|
暂无新消息
|
||||||
@@ -152,11 +119,15 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
/**
|
||||||
|
* 患者端消息首页:顶部四入口宫格(系统/订单/医生/转诊)+ 下方 IM 会话列表
|
||||||
|
*/
|
||||||
import {
|
import {
|
||||||
getseesionRead
|
getseesionRead
|
||||||
} from '../../request/api/api'
|
} from '../../request/api/api'
|
||||||
import {getSystemNoticeIndexApi} from '../../request/api/systemNotice'
|
import {getSystemNoticeIndexApi} from '../../request/api/systemNotice'
|
||||||
import {getChatFriendsListApi} from "@/request/api/im";
|
import {getChatFriendsListApi} from "@/request/api/im";
|
||||||
|
import {getTransferPrescriptionListApi} from "@/request/api/transferPrescription";
|
||||||
import {checkDev} from "@/utils/utils";
|
import {checkDev} from "@/utils/utils";
|
||||||
import MessageNotification from "@/components/MessageNotification/MessageNotification.vue";
|
import MessageNotification from "@/components/MessageNotification/MessageNotification.vue";
|
||||||
|
|
||||||
@@ -169,10 +140,30 @@ export default {
|
|||||||
order: [],
|
order: [],
|
||||||
system: [],
|
system: [],
|
||||||
doctor: [],
|
doctor: [],
|
||||||
|
transfer: {
|
||||||
|
num: 0,
|
||||||
|
time: ''
|
||||||
|
},
|
||||||
imChat: [],
|
imChat: [],
|
||||||
onlineConsultationList: [], // 在线咨询列表 (type=1)
|
onlineConsultationList: [], // 在线咨询列表 (type=1)
|
||||||
onlineReconsultationList: [], // 在线复诊列表 (type=3)
|
onlineReconsultationList: [], // 在线复诊列表 (type=3)
|
||||||
type: ""
|
type: "",
|
||||||
|
// 首次加载骨架:刷新时不再清空数据,故仅首次为 true
|
||||||
|
noticeInitialLoading: true,
|
||||||
|
chatInitialLoading: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
/**
|
||||||
|
* 顶部宫格入口:文案/角标在这里算好,模板禁止方法调用和 ?.
|
||||||
|
*/
|
||||||
|
noticeEntries() {
|
||||||
|
return [
|
||||||
|
this.buildNoticeEntry('system', '系统消息', 'https://xiaokang88.oss-cn-hangzhou.aliyuncs.com/xk-client-wx/static/xx/xt.png', this.system, '条未读信息', '暂无新消息'),
|
||||||
|
this.buildNoticeEntry('order', '产品订单', 'https://xiaokang88.oss-cn-hangzhou.aliyuncs.com/xk-client-wx/static/xx/cp.png', this.order, '条未读信息', '暂无新消息'),
|
||||||
|
this.buildNoticeEntry('doctor', '医生消息', 'https://xiaokang88.oss-cn-hangzhou.aliyuncs.com/xk-client-wx/static/xx/ysxx.png', this.doctor, '条新的消息', '暂无新消息'),
|
||||||
|
this.buildNoticeEntry('transfer', '转诊消息', 'https://xiaokang88.oss-cn-hangzhou.aliyuncs.com/xk-client-wx/static/xx/ysxx.png', this.transfer, '条转诊消息待处理', '暂无转诊消息')
|
||||||
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onLoad() {
|
onLoad() {
|
||||||
@@ -186,7 +177,35 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
checkDev,
|
checkDev,
|
||||||
|
/**
|
||||||
|
* 组装单条宫格入口(未读数未回来时不展示角标,避免闪 0)
|
||||||
|
*/
|
||||||
|
buildNoticeEntry(key, title, icon, raw, unreadSuffix, emptyText) {
|
||||||
|
const num = raw && raw.num
|
||||||
|
const hasNum = num !== undefined && num !== null
|
||||||
|
const unread = Number(num) || 0
|
||||||
|
let preview = emptyText
|
||||||
|
if (hasNum && unread > 0) {
|
||||||
|
preview = '您有' + unread + unreadSuffix
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
key,
|
||||||
|
title,
|
||||||
|
icon,
|
||||||
|
num: unread,
|
||||||
|
time: (raw && raw.time) || '',
|
||||||
|
preview,
|
||||||
|
showBadge: hasNum,
|
||||||
|
isDot: unread === 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/** 宫格点击:按 key 走原来的四个跳转 */
|
||||||
|
onNoticeTap(key) {
|
||||||
|
if (key === 'system') this.goSystem()
|
||||||
|
else if (key === 'order') this.goOrder()
|
||||||
|
else if (key === 'doctor') this.goDoctor()
|
||||||
|
else if (key === 'transfer') this.goTransfer()
|
||||||
|
},
|
||||||
/**
|
/**
|
||||||
* 处理聊天列表更新事件
|
* 处理聊天列表更新事件
|
||||||
* 收到新消息时自动刷新列表
|
* 收到新消息时自动刷新列表
|
||||||
@@ -204,7 +223,6 @@ export default {
|
|||||||
type: "all"
|
type: "all"
|
||||||
}
|
}
|
||||||
}).then((res) => {
|
}).then((res) => {
|
||||||
// console.log(res, 'res');
|
|
||||||
uni.showToast({
|
uni.showToast({
|
||||||
title: '清除成功',
|
title: '清除成功',
|
||||||
duration: 2000,
|
duration: 2000,
|
||||||
@@ -226,7 +244,6 @@ export default {
|
|||||||
type: "system"
|
type: "system"
|
||||||
}
|
}
|
||||||
}).then((res) => {
|
}).then((res) => {
|
||||||
// console.log(res, 'res');
|
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
// 详情
|
// 详情
|
||||||
@@ -241,7 +258,6 @@ export default {
|
|||||||
type: "order"
|
type: "order"
|
||||||
}
|
}
|
||||||
}).then((res) => {
|
}).then((res) => {
|
||||||
// console.log(res, 'res');
|
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
goDoctor() {
|
goDoctor() {
|
||||||
@@ -255,24 +271,20 @@ export default {
|
|||||||
type: "doctor_news"
|
type: "doctor_news"
|
||||||
}
|
}
|
||||||
}).then((res) => {
|
}).then((res) => {
|
||||||
// console.log(res, 'res');
|
})
|
||||||
|
},
|
||||||
|
// 转诊消息
|
||||||
|
goTransfer() {
|
||||||
|
uni.navigateTo({
|
||||||
|
url: '/subPackages/transfer/transfer-message'
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
goChat(item, index) {
|
goChat(item, index) {
|
||||||
uni.navigateTo({
|
uni.navigateTo({
|
||||||
url: `/subPackages/chat/chat?room_id=${item.room_id}&nick_name=${item.nick_name}&user_id=${item.id}&avatar=${encodeURIComponent(item.avatar || '')}&room_status=${item.room_status || 0}`
|
url: `/subPackages/chat/chat?room_id=${item.room_id}&nick_name=${item.nick_name}&user_id=${item.id}&avatar=${encodeURIComponent(item.avatar || '')}&room_status=${item.room_status || 0}`
|
||||||
})
|
})
|
||||||
// getseesionRead({
|
|
||||||
// method: "post",
|
|
||||||
// data: {
|
|
||||||
// store_id: uni.getStorageSync('store_id') || 11001,
|
|
||||||
// type: "doctor_news"
|
|
||||||
// }
|
|
||||||
// }).then((res) => {
|
|
||||||
// // console.log(res, 'res');
|
|
||||||
// })
|
|
||||||
},
|
},
|
||||||
//
|
// 获取系统/订单/医生消息概览;成功才覆盖,失败保留旧数据
|
||||||
async getInfo() {
|
async getInfo() {
|
||||||
try {
|
try {
|
||||||
const res = await getSystemNoticeIndexApi({
|
const res = await getSystemNoticeIndexApi({
|
||||||
@@ -285,16 +297,73 @@ export default {
|
|||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('获取消息概览失败:', error)
|
console.error('获取消息概览失败:', error)
|
||||||
|
} finally {
|
||||||
|
this.noticeInitialLoading = false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
// 拉取 IM 好友会话列表,成功后整份替换,失败不写空
|
||||||
getMyChatFriendsList() {
|
getMyChatFriendsList() {
|
||||||
getChatFriendsListApi().then((res) => {
|
return getChatFriendsListApi().then((res) => {
|
||||||
const allChatList = res.data.result || []
|
const allChatList = res.data.result || []
|
||||||
// 根据type字段区分在线咨询和在线复诊
|
// 根据type字段区分在线咨询和在线复诊
|
||||||
this.onlineConsultationList = allChatList.filter(item => item.type === 1 || !item.type) // type=1或未设置type的为在线咨询
|
this.onlineConsultationList = allChatList.filter(item => item.type === 1 || !item.type) // type=1或未设置type的为在线咨询
|
||||||
this.onlineReconsultationList = allChatList.filter(item => item.type === 3) // type=3的为在线复诊
|
this.onlineReconsultationList = allChatList.filter(item => (item.type === 3 || item.type === 2)) // type=3的为在线复诊
|
||||||
// 保持imChat兼容性(包含所有)
|
// 保持imChat兼容性(包含所有)
|
||||||
this.imChat = allChatList
|
this.imChat = allChatList
|
||||||
|
}).catch((error) => {
|
||||||
|
console.error('获取聊天列表失败:', error)
|
||||||
|
}).finally(() => {
|
||||||
|
this.chatInitialLoading = false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 获取转诊消息列表;失败不重置 transfer,避免闪空
|
||||||
|
getTransferList() {
|
||||||
|
return getTransferPrescriptionListApi().then((res) => {
|
||||||
|
if (res.data && res.data.code == 0) {
|
||||||
|
const transferList = res.data.result || []
|
||||||
|
// 统计待确认的转诊消息数量
|
||||||
|
const pendingCount = transferList.filter(item => item.status === 0).length
|
||||||
|
this.transfer.num = pendingCount
|
||||||
|
|
||||||
|
// 获取最新的转诊时间
|
||||||
|
if (transferList.length > 0) {
|
||||||
|
const latestTransfer = transferList[0]
|
||||||
|
if (latestTransfer.transfer_time) {
|
||||||
|
this.transfer.time = latestTransfer.transfer_time
|
||||||
|
} else if (latestTransfer.created_at) {
|
||||||
|
this.transfer.time = latestTransfer.created_at
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).catch((error) => {
|
||||||
|
console.error('获取转诊消息列表失败:', error)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 下拉刷新:重置骨架并并行重拉消息概览 / IM / 转诊
|
||||||
|
*/
|
||||||
|
refreshMessagePage() {
|
||||||
|
this.noticeInitialLoading = true
|
||||||
|
if (checkDev('open-im')) {
|
||||||
|
this.chatInitialLoading = true
|
||||||
|
this.onlineConsultationList = []
|
||||||
|
this.onlineReconsultationList = []
|
||||||
|
this.imChat = []
|
||||||
|
}
|
||||||
|
const tasks = [
|
||||||
|
this.getInfo(),
|
||||||
|
this.getTransferList()
|
||||||
|
]
|
||||||
|
if (checkDev('open-im')) {
|
||||||
|
tasks.push(this.getMyChatFriendsList())
|
||||||
|
} else {
|
||||||
|
this.chatInitialLoading = false
|
||||||
|
}
|
||||||
|
return Promise.all(tasks)
|
||||||
|
},
|
||||||
|
onPullDownRefresh() {
|
||||||
|
this.refreshMessagePage().finally(() => {
|
||||||
|
uni.stopPullDownRefresh()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -302,13 +371,10 @@ export default {
|
|||||||
this.getInfo()
|
this.getInfo()
|
||||||
},
|
},
|
||||||
onShow() {
|
onShow() {
|
||||||
this.order = []
|
// 不再清空列表:保留旧 UI,接口成功后再覆盖
|
||||||
this.system = []
|
|
||||||
this.doctor = []
|
|
||||||
this.onlineConsultationList = []
|
|
||||||
this.onlineReconsultationList = []
|
|
||||||
this.getInfo()
|
this.getInfo()
|
||||||
this.getMyChatFriendsList()
|
this.getMyChatFriendsList()
|
||||||
|
this.getTransferList()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
@@ -351,6 +417,108 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 顶部四入口:一行两列,卡片用同色细边框+微光(不用左侧色条) */
|
||||||
|
.notice-grid {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
padding: 0 24rpx 8rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.notice-card {
|
||||||
|
width: 343rpx;
|
||||||
|
margin: 0 16rpx 16rpx 0;
|
||||||
|
padding: 24rpx 20rpx;
|
||||||
|
box-sizing: border-box;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: flex-start;
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 20rpx;
|
||||||
|
border: 1px solid rgba(83, 109, 254, 0.28);
|
||||||
|
box-shadow: 0 0 6px rgba(83, 109, 254, 0.16);
|
||||||
|
}
|
||||||
|
|
||||||
|
.notice-card:nth-child(2n) {
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.notice-card-hover {
|
||||||
|
opacity: 0.88;
|
||||||
|
}
|
||||||
|
|
||||||
|
.notice-card__icon {
|
||||||
|
position: relative;
|
||||||
|
flex-shrink: 0;
|
||||||
|
width: 72rpx;
|
||||||
|
height: 72rpx;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: #E6EAFF;
|
||||||
|
overflow: visible;
|
||||||
|
|
||||||
|
image {
|
||||||
|
width: 72rpx;
|
||||||
|
height: 72rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.notice-card__body {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
margin-left: 16rpx;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.notice-card__title {
|
||||||
|
font-size: 28rpx;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #1E293B;
|
||||||
|
line-height: 40rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.notice-card__preview {
|
||||||
|
margin-top: 4rpx;
|
||||||
|
font-size: 22rpx;
|
||||||
|
color: #64748B;
|
||||||
|
line-height: 32rpx;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.notice-card__time {
|
||||||
|
margin-top: 4rpx;
|
||||||
|
font-size: 20rpx;
|
||||||
|
color: #94A3B8;
|
||||||
|
line-height: 28rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.notice-card--sk {
|
||||||
|
min-height: 140rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.notice-sk-icon {
|
||||||
|
width: 72rpx;
|
||||||
|
height: 72rpx;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: #EEF2FF;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.notice-sk-line {
|
||||||
|
height: 20rpx;
|
||||||
|
margin-top: 12rpx;
|
||||||
|
border-radius: 8rpx;
|
||||||
|
background: #F1F5F9;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.notice-sk-line--title {
|
||||||
|
height: 28rpx;
|
||||||
|
width: 140rpx;
|
||||||
|
flex: none;
|
||||||
|
}
|
||||||
|
|
||||||
.list {
|
.list {
|
||||||
width: 750rpx;
|
width: 750rpx;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<MessageNotification />
|
<MessageNotification />
|
||||||
<!-- 描述 -->
|
<!-- 描述 -->
|
||||||
<view class="card" v-for="item in list" :key="item.id">
|
<view class="card" v-for="item in list" :key="item.id">
|
||||||
<image src="/static/xx/cpdd.png" mode=""></image>
|
<image src="https://xiaokang88.oss-cn-hangzhou.aliyuncs.com/xk-client-wx/static/xx/cpdd.png" mode=""></image>
|
||||||
<view class="info">
|
<view class="info">
|
||||||
<view class="infos_title">
|
<view class="infos_title">
|
||||||
<text class="infos">订单</text>
|
<text class="infos">订单</text>
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
<view class="qualification-item" v-for="(item, index) in qualifications" :key="index" @click="previewImage(index)">
|
<view class="qualification-item" v-for="(item, index) in qualifications" :key="index" @click="previewImage(index)">
|
||||||
<view class="qualification-content">
|
<view class="qualification-content">
|
||||||
<text class="qualification-name">{{ item.name }}</text>
|
<text class="qualification-name">{{ item.name }}</text>
|
||||||
<image :src="item.image || '/static/mine/avatar_1.png'" mode="aspectFit" class="qualification-img"></image>
|
<image :src="item.image || 'https://xiaokang88.oss-cn-hangzhou.aliyuncs.com/xk-client-wx/static/mine/avatar_1.png'" mode="aspectFit" class="qualification-img"></image>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
<view class="title">
|
<view class="title">
|
||||||
欢迎登录
|
欢迎登录
|
||||||
</view>
|
</view>
|
||||||
<image src="@/static/empty/login.png" mode="aspectFit"></image>
|
<image src="https://xiaokang88.oss-cn-hangzhou.aliyuncs.com/xk-client-wx/static/empty/login.png" mode="aspectFit"></image>
|
||||||
|
|
||||||
<!-- 修改点1:移除 disabled 属性和 bg 样式判断,使其始终可点击且显示激活颜色 -->
|
<!-- 修改点1:移除 disabled 属性和 bg 样式判断,使其始终可点击且显示激活颜色 -->
|
||||||
<button class="btn" @click="handleLoginClick">一键登录</button>
|
<button class="btn" @click="handleLoginClick">一键登录</button>
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
<view class="info">
|
<view class="info">
|
||||||
<view class="pwd">
|
<view class="pwd">
|
||||||
<d-input :maxlength="11" height="96" v-model="form['mobile']"
|
<d-input :maxlength="11" height="96" v-model="form['mobile']"
|
||||||
:prefixIcon="require('../../static/choose/act.png')" borderRadius="96rpx" prefixIconSize="40rpx"
|
prefixIcon="https://xiaokang88.oss-cn-hangzhou.aliyuncs.com/xk-client-wx/static/choose/act.png" borderRadius="96rpx" prefixIconSize="40rpx"
|
||||||
placeholder="请输入手机号" @blur="check" @input="is_d=false" :placeholder-style="{fontSize:'32rpx'}"
|
placeholder="请输入手机号" @blur="check" @input="is_d=false" :placeholder-style="{fontSize:'32rpx'}"
|
||||||
:custom-style="{fontSize:'32rpx',paddingLeft:'60rpx'}" />
|
:custom-style="{fontSize:'32rpx',paddingLeft:'60rpx'}" />
|
||||||
</view>
|
</view>
|
||||||
@@ -57,6 +57,7 @@
|
|||||||
getCodes,
|
getCodes,
|
||||||
getsLogin
|
getsLogin
|
||||||
} from '../../request/api/api';
|
} from '../../request/api/api';
|
||||||
|
import { isPhone } from '@/utils/phone.js';
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
@@ -93,7 +94,8 @@
|
|||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (!/^1[345678]\d{9}$/.test(this.form['mobile'])) {
|
// 与后端 checkPhone 统一:含 19 号段
|
||||||
|
if (!isPhone(this.form['mobile'])) {
|
||||||
// uni.showToast({
|
// uni.showToast({
|
||||||
// title: '请输入正确的手机号',
|
// title: '请输入正确的手机号',
|
||||||
// duration: 2000,
|
// duration: 2000,
|
||||||
@@ -137,6 +139,14 @@
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
register() {
|
register() {
|
||||||
|
if (!isPhone(this.form['mobile'])) {
|
||||||
|
this.$refs.uToast.show({
|
||||||
|
title: '请输入正确的手机号',
|
||||||
|
type: 'default',
|
||||||
|
icon: false
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
if (this.form['pwd'] == []) {
|
if (this.form['pwd'] == []) {
|
||||||
uni.showToast({
|
uni.showToast({
|
||||||
title: '请输入验证码',
|
title: '请输入验证码',
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<!-- 头部 -->
|
<!-- 头部 -->
|
||||||
<view class="head">
|
<view class="head">
|
||||||
<view class="head_img">
|
<view class="head_img">
|
||||||
<image :src="infoList.user.avatarurl || '/static/mine/mr_tx.png' " mode=""></image>
|
<image :src="infoList.user.avatarurl || 'https://xiaokang88.oss-cn-hangzhou.aliyuncs.com/xk-client-wx/static/mine/mr_tx.png' " mode=""></image>
|
||||||
</view>
|
</view>
|
||||||
<view class="head_info">
|
<view class="head_info">
|
||||||
<view class="head_name">
|
<view class="head_name">
|
||||||
@@ -31,25 +31,25 @@
|
|||||||
</view>
|
</view>
|
||||||
<view class="info">
|
<view class="info">
|
||||||
<view class="item" @click="toAll(1)" style="position: relative;">
|
<view class="item" @click="toAll(1)" style="position: relative;">
|
||||||
<image src="/static/mine/dfk.png" mode=""></image>
|
<image src="https://xiaokang88.oss-cn-hangzhou.aliyuncs.com/xk-client-wx/static/mine/dfk.png" mode=""></image>
|
||||||
<text>待付款</text>
|
<text>待付款</text>
|
||||||
<u-badge type="error" :count="infoList.ProductOrder.unpay" :offset="[-2,20]"></u-badge>
|
<u-badge type="error" :count="infoList.ProductOrder.unpay" :offset="[-2,20]"></u-badge>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<view class="item" @click="toAll(2)" style="position: relative;">
|
<view class="item" @click="toAll(2)" style="position: relative;">
|
||||||
<image src="/static/mine/dfh.png" mode=""></image>
|
<image src="https://xiaokang88.oss-cn-hangzhou.aliyuncs.com/xk-client-wx/static/mine/dfh.png" mode=""></image>
|
||||||
<text>待发货</text>
|
<text>待发货</text>
|
||||||
<u-badge type="error" :count="infoList.ProductOrder.wait_send" :offset="[-2,20]"></u-badge>
|
<u-badge type="error" :count="infoList.ProductOrder.wait_send" :offset="[-2,20]"></u-badge>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<view class="item" @click="toAll(3)" style="position: relative;">
|
<view class="item" @click="toAll(3)" style="position: relative;">
|
||||||
<image src="/static/mine/dsh.png" mode=""></image>
|
<image src="https://xiaokang88.oss-cn-hangzhou.aliyuncs.com/xk-client-wx/static/mine/dsh.png" mode=""></image>
|
||||||
<text>待收货</text>
|
<text>待收货</text>
|
||||||
<u-badge type="error" :count="infoList.ProductOrder.wait_accept" :offset="[-2,20]"></u-badge>
|
<u-badge type="error" :count="infoList.ProductOrder.wait_accept" :offset="[-2,20]"></u-badge>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<view class="item" @click="toAll(4)">
|
<view class="item" @click="toAll(4)">
|
||||||
<image src="/static/mine/tk.png" mode=""></image>
|
<image src="https://xiaokang88.oss-cn-hangzhou.aliyuncs.com/xk-client-wx/static/mine/tk.png" mode=""></image>
|
||||||
<text>已完成</text>
|
<text>已完成</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
@@ -63,17 +63,17 @@
|
|||||||
|
|
||||||
<!-- 列表 -->
|
<!-- 列表 -->
|
||||||
<view class="list">
|
<view class="list">
|
||||||
<!-- <navigator url="../../subPackages/my/myorder" class="infos">
|
<navigator url="../../subPackages/my/mymedical" class="infos">
|
||||||
<image src="@/static/mine/01.png" mode=""></image>
|
<image src="https://xiaokang88.oss-cn-hangzhou.aliyuncs.com/xk-client-wx/static/mine/01.png" mode=""></image>
|
||||||
<text>问诊记录</text>
|
<text>我的病历</text>
|
||||||
</navigator> -->
|
</navigator>
|
||||||
<navigator url="../../subPackages/my/myrecord" class="infos">
|
<navigator url="../../subPackages/my/myrecord" class="infos">
|
||||||
<image src="@/static/mine/02.png" mode=""></image>
|
<image src="https://xiaokang88.oss-cn-hangzhou.aliyuncs.com/xk-client-wx/static/mine/02.png" mode=""></image>
|
||||||
<text>处方记录</text>
|
<text>我的处方</text>
|
||||||
</navigator>
|
</navigator>
|
||||||
<navigator url="../../subPackages/my/myappiont" class="infos">
|
<navigator url="../../subPackages/my/myappiont" class="infos">
|
||||||
<image src="@/static/mine/03.png" mode=""></image>
|
<image src="https://xiaokang88.oss-cn-hangzhou.aliyuncs.com/xk-client-wx/static/mine/03.png" mode=""></image>
|
||||||
<text>挂号记录</text>
|
<text>我的挂号</text>
|
||||||
</navigator>
|
</navigator>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
@@ -87,15 +87,15 @@
|
|||||||
<!-- 列表 -->
|
<!-- 列表 -->
|
||||||
<view class="list">
|
<view class="list">
|
||||||
<navigator class="infos" url="../../subPackages/my/myinfo" v-if="isShow_envVersion==false">
|
<navigator class="infos" url="../../subPackages/my/myinfo" v-if="isShow_envVersion==false">
|
||||||
<image src="@/static/mine/jzr.png" mode=""></image>
|
<image src="https://xiaokang88.oss-cn-hangzhou.aliyuncs.com/xk-client-wx/static/mine/jzr.png" mode=""></image>
|
||||||
<text>就诊人管理</text>
|
<text>就诊人管理</text>
|
||||||
</navigator>
|
</navigator>
|
||||||
<navigator url="../../subPackages/setup/area-list" class="infos">
|
<navigator url="../../subPackages/setup/area-list" class="infos">
|
||||||
<image src="@/static/mine/gy.png" mode=""></image>
|
<image src="https://xiaokang88.oss-cn-hangzhou.aliyuncs.com/xk-client-wx/static/mine/gy.png" mode=""></image>
|
||||||
<text>收货地址</text>
|
<text>收货地址</text>
|
||||||
</navigator>
|
</navigator>
|
||||||
<navigator url="../../subPackages/setup/customer-service" class="infos">
|
<navigator url="../../subPackages/setup/customer-service" class="infos">
|
||||||
<image src="@/static/mine/kfzx.png" mode=""></image>
|
<image src="https://xiaokang88.oss-cn-hangzhou.aliyuncs.com/xk-client-wx/static/mine/kfzx.png" mode=""></image>
|
||||||
<text>客服中心</text>
|
<text>客服中心</text>
|
||||||
</navigator>
|
</navigator>
|
||||||
</view>
|
</view>
|
||||||
@@ -106,8 +106,9 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import {
|
import {
|
||||||
getuserInfo
|
getUserInfoApi
|
||||||
} from '../../request/api/api'
|
} from '../../request/api/user'
|
||||||
|
import { unwrapXkApi } from '@/utils/api-response.js'
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
@@ -137,15 +138,13 @@
|
|||||||
|
|
||||||
// 用户信息
|
// 用户信息
|
||||||
getInfo() {
|
getInfo() {
|
||||||
getuserInfo({
|
getUserInfoApi({
|
||||||
method: "post",
|
store_id: uni.getStorageSync('store_id') || 11001
|
||||||
data: {
|
|
||||||
store_id: uni.getStorageSync('store_id') || 11001
|
|
||||||
}
|
|
||||||
}).then((res) => {
|
}).then((res) => {
|
||||||
// console.log(res, 'ingo');
|
// getUserInfoApi → xk-api
|
||||||
if (res.data.errcode == 0) {
|
const { ok, payload } = unwrapXkApi(res)
|
||||||
this.infoList = res.data.data
|
if (ok) {
|
||||||
|
this.infoList = payload
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,4 +1,37 @@
|
|||||||
import http from './request'
|
import http from './request'
|
||||||
|
import {
|
||||||
|
getPatientListApi,
|
||||||
|
savePatientApi,
|
||||||
|
deletePatientApi,
|
||||||
|
getPatientGuardianInfoApi,
|
||||||
|
getPatientRelationApi,
|
||||||
|
changePatientDefaultApi,
|
||||||
|
getPatientHealthInfoApi,
|
||||||
|
} from './patient.js'
|
||||||
|
|
||||||
|
/** 将 xk-api 的 code/result 格式转为旧版 errcode/data,兼容现有页面 */
|
||||||
|
function normalizeXkApiResponse(res) {
|
||||||
|
if (res && res.data && (res.data.code === 0 || res.data.code === '0')) {
|
||||||
|
res.data.errcode = 0;
|
||||||
|
res.data.data = res.data.result;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 就诊人列表专用:xk-api result 为 { list, latest_register_user_patient_id }
|
||||||
|
* 旧页面仍读 res.data.data 数组,这里把 list 摊平到 data
|
||||||
|
*/
|
||||||
|
function normalizePatientListResponse(res) {
|
||||||
|
if (res && res.data && (res.data.code === 0 || res.data.code === '0')) {
|
||||||
|
const result = res.data.result
|
||||||
|
const list = Array.isArray(result) ? result : ((result && result.list) || [])
|
||||||
|
res.data.errcode = 0
|
||||||
|
res.data.data = list
|
||||||
|
res.data.result = result
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
// 登录 授权 其他手机号授权
|
// 登录 授权 其他手机号授权
|
||||||
export async function getsLogin(params) {
|
export async function getsLogin(params) {
|
||||||
@@ -33,20 +66,20 @@ export async function getAgreem(params) {
|
|||||||
|
|
||||||
// 首页 门店 门店切换
|
// 首页 门店 门店切换
|
||||||
export async function storeChange(params) {
|
export async function storeChange(params) {
|
||||||
let data = await http('/oldApi/v1/store/store-change', params)
|
let data = await http('/xkApi/store/store-change', params)
|
||||||
return data
|
return normalizeXkApiResponse(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 首页 门店 用户所有门店
|
// 首页 门店 用户所有门店
|
||||||
export async function storeList(params) {
|
export async function storeList(params) {
|
||||||
let data = await http('/oldApi/v1/store/list', params)
|
let data = await http('/xkApi/store/list', params)
|
||||||
return data
|
return normalizeXkApiResponse(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 首页 门店 门店信息
|
// 首页 门店 门店信息
|
||||||
export async function storeInfo(params) {
|
export async function storeInfo(params) {
|
||||||
let data = await http('/oldApi/v1/store/info', params)
|
let data = await http('/xkApi/store/info', params)
|
||||||
return data
|
return normalizeXkApiResponse(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 医生列表
|
// 医生列表
|
||||||
@@ -79,90 +112,62 @@ export async function commentListTop(params) {
|
|||||||
return data
|
return data
|
||||||
}
|
}
|
||||||
|
|
||||||
// 医生 挂号信息
|
// 挂号域接口(registerList/registerCalendar/registe/registeInfo/registePay/registeUnpay/registeCancle)
|
||||||
export async function registerList(params) {
|
// 已按 Api-Module-Split 规则迁至 ./register.js,调用方请从 '@/request/api/register.js' 导入
|
||||||
let data = await http('/oldApi/v1/register/doc-register-info', params)
|
|
||||||
return data
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// 就诊人列表
|
/** 就诊人列表(xk-api POST /patient/list) */
|
||||||
export async function userList(params) {
|
export async function userList(params) {
|
||||||
let data = await http('/oldApi/v1/patient/list', params)
|
const data = (params && params.data) || params || {}
|
||||||
return data
|
return normalizePatientListResponse(await getPatientListApi(data))
|
||||||
}
|
}
|
||||||
|
|
||||||
// 就诊人关系
|
/** 就诊人关系(xk-api GET /patient/relation) */
|
||||||
export async function userRelation(params) {
|
export async function userRelation(params) {
|
||||||
let data = await http('/oldApi/v1/patient/relation', params)
|
const data = (params && params.data) || params || {}
|
||||||
return data
|
return normalizeXkApiResponse(await getPatientRelationApi(data))
|
||||||
}
|
}
|
||||||
|
|
||||||
// 编辑就诊人信息
|
/** 编辑就诊人头像等(仍走旧接口,业务极少用) */
|
||||||
export async function userInfo(params) {
|
export async function userInfo(params) {
|
||||||
let data = await http('/oldApi/v1/patient/edit-patient', params)
|
let data = await http('/oldApi/v1/patient/edit-patient', params)
|
||||||
return data
|
return data
|
||||||
}
|
}
|
||||||
|
|
||||||
// 就诊人保存
|
/** 就诊人保存(xk-api POST /patient/save) */
|
||||||
export async function userAdd(params) {
|
export async function userAdd(params) {
|
||||||
let data = await http('/oldApi/v1/patient/save', params)
|
const data = (params && params.data) || params || {}
|
||||||
return data
|
return normalizeXkApiResponse(await savePatientApi(data))
|
||||||
}
|
}
|
||||||
|
|
||||||
// 就诊人详情
|
/** 就诊人监护人信息(xk-api GET /patient/guardian-info) */
|
||||||
|
export async function userGuardianInfo(params) {
|
||||||
|
const query = (params && params.data) || params || {}
|
||||||
|
return normalizeXkApiResponse(await getPatientGuardianInfoApi(query))
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 删除就诊人(xk-api POST /patient/delete) */
|
||||||
|
export async function userPatientDel(params) {
|
||||||
|
const data = (params && params.data) || params || {}
|
||||||
|
return normalizeXkApiResponse(await deletePatientApi(data))
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 就诊人详情(列表已含字段;无独立详情时仍兼容旧 Yii) */
|
||||||
export async function userDetail(params) {
|
export async function userDetail(params) {
|
||||||
let data = await http('/oldApi/v1/patient/info', params)
|
let data = await http('/oldApi/v1/patient/info', params)
|
||||||
return data
|
return data
|
||||||
}
|
}
|
||||||
|
|
||||||
// 就诊人 切换默认接诊人
|
/** 切换默认就诊人(xk-api POST /patient/change-default) */
|
||||||
export async function userPatientChoose(params) {
|
export async function userPatientChoose(params) {
|
||||||
let data = await http('/oldApi/v1/patient/change-patient', params)
|
const data = (params && params.data) || params || {}
|
||||||
return data
|
return normalizeXkApiResponse(await changePatientDefaultApi(data))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 健康问诊详情(xk-api POST /patient/health-info) */
|
||||||
// 就诊人 - 健康信息
|
|
||||||
export async function userEidtPatient(params) {
|
export async function userEidtPatient(params) {
|
||||||
let data = await http('/oldApi/v1/patient/health-info', params)
|
const data = (params && params.data) || params || {}
|
||||||
return data
|
return normalizeXkApiResponse(await getPatientHealthInfoApi(data))
|
||||||
}
|
|
||||||
|
|
||||||
// 挂号
|
|
||||||
export async function registe(params) {
|
|
||||||
let data = await http('/oldApi/v1/register/register', params)
|
|
||||||
return data
|
|
||||||
}
|
|
||||||
|
|
||||||
// 挂号详情
|
|
||||||
export async function registeInfo(params) {
|
|
||||||
let data = await http('/oldApi/v1/register/register-detail', params)
|
|
||||||
return data
|
|
||||||
}
|
|
||||||
|
|
||||||
// 支付挂号
|
|
||||||
export async function registePay(params) {
|
|
||||||
let data = await http('/oldApi/v1/register/pay', params)
|
|
||||||
return data
|
|
||||||
}
|
|
||||||
|
|
||||||
// 取消挂号
|
|
||||||
export async function registeUnpay(params) {
|
|
||||||
let data = await http('/oldApi/v1/register/cancel', params)
|
|
||||||
return data
|
|
||||||
}
|
|
||||||
|
|
||||||
// 挂号退款
|
|
||||||
export async function registeCancle(params) {
|
|
||||||
let data = await http('/oldApi/v1/register/refund', params)
|
|
||||||
return data
|
|
||||||
}
|
|
||||||
|
|
||||||
// 挂号列表
|
|
||||||
export async function registeList(params) {
|
|
||||||
let data = await http('/oldApi/v1/register/list', params)
|
|
||||||
return data
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 设置 服务协议
|
// 设置 服务协议
|
||||||
@@ -244,16 +249,16 @@ export async function getPrescriptInfo(params) {
|
|||||||
return data
|
return data
|
||||||
}
|
}
|
||||||
|
|
||||||
// 我的 处方支付
|
// 我的 处方支付(xk-api)
|
||||||
export async function getPrescriptPay(params) {
|
export async function getPrescriptPay(params) {
|
||||||
let data = await http('/oldApi/v1/product-order/pay', params)
|
let data = await http('/xkApi/product-order/pay', params)
|
||||||
return data
|
return normalizeXkApiResponse(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 我的 处方-产品订单信息
|
// 我的 处方-产品订单信息(xk-api appoint-medicine)
|
||||||
export async function getProductInfo(params) {
|
export async function getProductInfo(params) {
|
||||||
let data = await http('/oldApi/v1/product-order/appoint-medicine', params)
|
let data = await http('/xkApi/product-order/appoint-medicine', params)
|
||||||
return data
|
return normalizeXkApiResponse(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 消息
|
// 消息
|
||||||
@@ -317,10 +322,21 @@ export async function getUseWayPay(params) {
|
|||||||
return data
|
return data
|
||||||
}
|
}
|
||||||
|
|
||||||
// 更新配送方式 http://xiaokang.com/member/v1/product-order/update-delivery
|
/**
|
||||||
|
* 更新配送方式(xk-api:单品包邮重算)
|
||||||
|
* 代付时带 proxy_pay=1,或与 getPayConfig 一样从 storage 自动附带
|
||||||
|
*/
|
||||||
export async function getDelivery(params) {
|
export async function getDelivery(params) {
|
||||||
let data = await http('/oldApi/v1/product-order/update-delivery', params)
|
const payload = params && typeof params === 'object' ? { ...params } : { method: 'post', data: {} }
|
||||||
return data
|
const data = payload.data && typeof payload.data === 'object' ? { ...payload.data } : {}
|
||||||
|
const orderId = Number(data.order_id || 0)
|
||||||
|
const proxyOrderId = Number(uni.getStorageSync('proxy_pay_order_id') || 0)
|
||||||
|
if (!data.proxy_pay && proxyOrderId > 0 && orderId === proxyOrderId) {
|
||||||
|
data.proxy_pay = 1
|
||||||
|
}
|
||||||
|
payload.data = data
|
||||||
|
let res = await http('/xkApi/product-order/update-delivery', payload)
|
||||||
|
return normalizeXkApiResponse(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 更新代煎服务费用 http://xiaokang.com/member/v1/product-order/update-decoct-service
|
// 更新代煎服务费用 http://xiaokang.com/member/v1/product-order/update-decoct-service
|
||||||
@@ -329,28 +345,51 @@ export async function getUpdateUseWay(params) {
|
|||||||
return data
|
return data
|
||||||
}
|
}
|
||||||
|
|
||||||
//资讯列表 /v1/info/article-list
|
//资讯列表(Laravel guest-info,列表不含正文)
|
||||||
export async function articleList(params) {
|
export async function articleList(params) {
|
||||||
let data = await http('/oldApi/v1/info/article-list', params)
|
let data = await http('/xkApi/guest/guest-info/article-list', params)
|
||||||
return data
|
return data
|
||||||
}
|
}
|
||||||
|
|
||||||
//分类列表 /v1/info/categories
|
//分类列表
|
||||||
export async function categoriesList(params) {
|
export async function categoriesList(params) {
|
||||||
let data = await http('/oldApi/v1/info/categories', params)
|
let data = await http('/xkApi/guest/guest-info/categories', params)
|
||||||
return data
|
return data
|
||||||
}
|
}
|
||||||
|
|
||||||
//资讯详情 /v1/info/article-info
|
//资讯详情(含正文)
|
||||||
export async function articleInfo(params) {
|
export async function articleInfo(params) {
|
||||||
let data = await http('/oldApi/v1/info/article-info', params)
|
let data = await http('/xkApi/guest/guest-info/article-info', params)
|
||||||
return data
|
return data
|
||||||
}
|
}
|
||||||
|
|
||||||
// v1/product-order/list
|
// v1/product-order/list
|
||||||
export async function getOrdlist(params) {
|
export async function getOrdlist(params) {
|
||||||
let data = await http('/oldApi/v1/product-order/list', params)
|
let data = await http('/xkApi/product-order/list', params)
|
||||||
return data
|
return normalizeXkApiResponse(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取待支付商品订单列表(首页提醒用)
|
||||||
|
*/
|
||||||
|
export async function fetchUnpaidProductOrderListApi(params = {}) {
|
||||||
|
const storeId = params.store_id || uni.getStorageSync('store_id') || '11001';
|
||||||
|
const res = await getOrdlist({
|
||||||
|
method: 'post',
|
||||||
|
data: {
|
||||||
|
store_id: storeId,
|
||||||
|
type: 'unpaid',
|
||||||
|
page: 1,
|
||||||
|
...params,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
if (res.data?.errcode != 0) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
const list = res.data?.data?.list || [];
|
||||||
|
return list.filter(
|
||||||
|
(item) => item.status === 0 && item.is_pay === 0 && item.cancel_status === 0
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// v1/product-order/list
|
// v1/product-order/list
|
||||||
@@ -418,9 +457,21 @@ export async function PayList(params) {
|
|||||||
// return data
|
// return data
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 商品订单支付(xk-api)
|
||||||
|
* 代付时在 data 中带 proxy_pay=1;也可从 storage proxy_pay_order_id 自动附带
|
||||||
|
*/
|
||||||
export async function getPayConfig(params) {
|
export async function getPayConfig(params) {
|
||||||
let data = await http('/oldApi/v1/product-order/pay', params)
|
const payload = params && typeof params === 'object' ? { ...params } : { method: 'post', data: {} }
|
||||||
return data
|
const data = payload.data && typeof payload.data === 'object' ? { ...payload.data } : {}
|
||||||
|
const orderId = Number(data.order_id || 0)
|
||||||
|
const proxyOrderId = Number(uni.getStorageSync('proxy_pay_order_id') || 0)
|
||||||
|
if (!data.proxy_pay && proxyOrderId > 0 && orderId === proxyOrderId) {
|
||||||
|
data.proxy_pay = 1
|
||||||
|
}
|
||||||
|
payload.data = data
|
||||||
|
let res = await http('/xkApi/product-order/pay', payload)
|
||||||
|
return normalizeXkApiResponse(res)
|
||||||
}
|
}
|
||||||
// getOrdlist 获取订单列表 https://zjxk.app.ctkj88.com/member/order/lists
|
// getOrdlist 获取订单列表 https://zjxk.app.ctkj88.com/member/order/lists
|
||||||
// export async function getOrdlist(params) {
|
// export async function getOrdlist(params) {
|
||||||
@@ -439,10 +490,10 @@ export async function getCancle(params) {
|
|||||||
// return data
|
// return data
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// 更换 订单详情 https://app.xiaokang88.com/member/v1/product-order/info
|
// 订单详情(xk-api product-order/info,drug-info 页)
|
||||||
export async function getOrdDetail(params) {
|
export async function getOrdDetail(params) {
|
||||||
let data = await http('/oldApi/v1/product-order/info', params)
|
let data = await http('/xkApi/product-order/info', params)
|
||||||
return data
|
return normalizeXkApiResponse(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -469,25 +520,18 @@ export async function postRefundBased(params) {
|
|||||||
// return data
|
// return data
|
||||||
|
|
||||||
// }
|
// }
|
||||||
|
/** 物流详情 → xk-api mobile(含多包裹 packages) */
|
||||||
export async function getLogistics(params) {
|
export async function getLogistics(params) {
|
||||||
let data = await http('/oldApi/v1/product-order/express', params)
|
let data = await http('/xkApi/product-order/express', params)
|
||||||
return data
|
return normalizeXkApiResponse(data)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//确认收货 https://zjxk.app.ctkj88.com/member/order/confirm
|
// 确认收货(签收)→ xk-api product-order/receive(改状态 + 解冻供应商/仓余额)
|
||||||
// https://zjxk.app.ctkj88.com/member/order/confirm
|
|
||||||
export async function confirmAccept(params) {
|
export async function confirmAccept(params) {
|
||||||
let data = await http('/newApi/order/confirm', params)
|
let data = await http('/xkApi/product-order/receive', params)
|
||||||
return data
|
return normalizeXkApiResponse(data)
|
||||||
}
|
}
|
||||||
//清空购物车
|
|
||||||
export async function clearAll(params) {
|
|
||||||
let data = await http('/newApi/cart/clearAll', params)
|
|
||||||
return data
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function getVersion(params) {
|
export async function getVersion(params) {
|
||||||
let data = await http('/v1/other/xcx-version?store_id=11001', params)
|
let data = await http('/v1/other/xcx-version?store_id=11001', params)
|
||||||
return data
|
return data
|
||||||
@@ -495,7 +539,8 @@ export async function getVersion(params) {
|
|||||||
|
|
||||||
// 获取系统配置信息
|
// 获取系统配置信息
|
||||||
export async function getSystemConfig(params) {
|
export async function getSystemConfig(params) {
|
||||||
let data = await http('/xkApi/platform/config', params)
|
// let data = await http('/xkApi/platform/config', params)
|
||||||
|
let data = await http('/xkApi/platform/config', params, 3)
|
||||||
return data
|
return data
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -26,3 +26,11 @@ export async function getCartCountsApi(params) {
|
|||||||
export async function saveCartApi(params) {
|
export async function saveCartApi(params) {
|
||||||
return await post(`${prefix}/save-cart`, params, 3)
|
return await post(`${prefix}/save-cart`, params, 3)
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* 清空购物车(当前用户+门店维度,迁自老 Yii /v1/cart/clear-all) xk-api POST /cart/clear-cart
|
||||||
|
* @param params { store_id: number }
|
||||||
|
* @returns {Promise<*>}
|
||||||
|
*/
|
||||||
|
export async function clearCartApi(params) {
|
||||||
|
return await post(`${prefix}/clear-cart`, params, 3)
|
||||||
|
}
|
||||||
|
|||||||
33
request/api/invoice.js
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
import { get, post } from './http'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将 xk-api 的 code/result 规范为 errcode/data,便于页面统一判断
|
||||||
|
*/
|
||||||
|
function normalizeXkApiResponse(res) {
|
||||||
|
if (res && res.data && (res.data.code === 0 || res.data.code === '0')) {
|
||||||
|
res.data.errcode = 0
|
||||||
|
res.data.data = res.data.result
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 申请开票
|
||||||
|
* @param {object} params order_id, title_type, title_name, tax_no, receive_type, email
|
||||||
|
*/
|
||||||
|
export async function applyInvoiceApi(params) {
|
||||||
|
const data = await post('/invoice/apply', params, 3)
|
||||||
|
return normalizeXkApiResponse(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 开票详情
|
||||||
|
* @param {object} params id 或 order_id
|
||||||
|
*/
|
||||||
|
export async function getInvoiceDetailApi(params) {
|
||||||
|
const data = await get('/invoice/detail', params, 3)
|
||||||
|
return normalizeXkApiResponse(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 与 config/xk.php invoice_notice 保持一致的订阅消息模板 ID */
|
||||||
|
export const INVOICE_NOTICE_TMPL_ID = '2FuQhhO74mABSqGx2cF7vRR2wGekrIMM9kZMvVI6h-Q'
|
||||||
19
request/api/medicalRecord.js
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
import { post, get } from './http'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 我的病历列表(xk-api POST /medical-record/list)
|
||||||
|
* 取值:unwrapXkApi → code/result/message
|
||||||
|
* @param {{ user_patient_id: number, page?: number, pageSize?: number }} params
|
||||||
|
*/
|
||||||
|
export async function getMedicalRecordListApi(params) {
|
||||||
|
return await post('/medical-record/list', params, 3)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 我的病历详情(xk-api GET /medical-record/detail)
|
||||||
|
* 取值:unwrapXkApi → code/result/message
|
||||||
|
* @param {{ id: number }} params
|
||||||
|
*/
|
||||||
|
export async function getMedicalRecordDetailApi(params) {
|
||||||
|
return await get('/medical-record/detail', params, 3)
|
||||||
|
}
|
||||||
@@ -1,6 +1,20 @@
|
|||||||
import {get, post, uploadFile} from './http'
|
import {get, post, uploadFile} from './http'
|
||||||
|
|
||||||
const prefix = '/order';
|
const prefix = '/order';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 在线复诊:创建就诊信息(挂号前)
|
||||||
|
*/
|
||||||
|
export async function createRegisterInfoApi(params) {
|
||||||
|
return await post(`${prefix}/create-register-info`, params, 3)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 在线复诊:可选西药列表(双端上架)
|
||||||
|
*/
|
||||||
|
export async function getWesternDrugsForFollowUpApi(params) {
|
||||||
|
return await get(`${prefix}/western-drugs-for-follow-up`, params, 3)
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* 获取扫码诊所的商品详情
|
* 获取扫码诊所的商品详情
|
||||||
* @param params
|
* @param params
|
||||||
@@ -26,6 +40,11 @@ export async function saveRegisterInfoApi(params) {
|
|||||||
return await post(`${prefix}/save-register-info`, params, 3)
|
return await post(`${prefix}/save-register-info`, params, 3)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 诊所在线复诊:确认是否曾用过所选西药 */
|
||||||
|
export async function confirmFollowUpDrugUseApi(params) {
|
||||||
|
return await post(`${prefix}/confirm-follow-up-drug-use`, params, 3)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询订单的处方状态
|
* 查询订单的处方状态
|
||||||
* @param params
|
* @param params
|
||||||
|
|||||||
46
request/api/patient.js
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
import { post, get } from './http'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 就诊人相关接口统一走 xk-api(type=3)
|
||||||
|
* 取值:unwrapXkApi → code / result / message
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** 就诊人列表 POST /patient/list → { list, latest_register_user_patient_id } */
|
||||||
|
export async function getPatientListApi(params = {}) {
|
||||||
|
return await post('/patient/list', params, 3)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 就诊人保存(新增/编辑)POST /patient/save */
|
||||||
|
export async function savePatientApi(params = {}) {
|
||||||
|
return await post('/patient/save', params, 3)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 删除就诊人 POST /patient/delete */
|
||||||
|
export async function deletePatientApi(params = {}) {
|
||||||
|
return await post('/patient/delete', params, 3)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 监护人信息 GET /patient/guardian-info */
|
||||||
|
export async function getPatientGuardianInfoApi(params = {}) {
|
||||||
|
return await get('/patient/guardian-info', params, 3)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 关系枚举 GET /patient/relation */
|
||||||
|
export async function getPatientRelationApi(params = {}) {
|
||||||
|
return await get('/patient/relation', params, 3)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 设为默认就诊人 POST /patient/change-default,传 up_id */
|
||||||
|
export async function changePatientDefaultApi(params = {}) {
|
||||||
|
return await post('/patient/change-default', params, 3)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 健康问诊详情 POST /patient/health-info,传 user_patient_id */
|
||||||
|
export async function getPatientHealthInfoApi(params = {}) {
|
||||||
|
return await post('/patient/health-info', params, 3)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 扫码认领医生创建的就诊人 POST /patient/claim,传 user_patient_id */
|
||||||
|
export async function claimPatientApi(params = {}) {
|
||||||
|
return await post('/patient/claim', params, 3)
|
||||||
|
}
|
||||||
10
request/api/prescription.js
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
import {post} from './http'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取处方记录列表
|
||||||
|
* @param params { up_id: number, store_id: number, page: number }
|
||||||
|
* @returns {Promise<*>}
|
||||||
|
*/
|
||||||
|
export async function getPrescriptionListApi(params) {
|
||||||
|
return await post('/prescription/list', params, 3)
|
||||||
|
}
|
||||||
@@ -40,6 +40,20 @@ export async function getHomeTopProductsApi(params) {
|
|||||||
export async function getHomeZonesApi(params) {
|
export async function getHomeZonesApi(params) {
|
||||||
return await get('/product/home-zones', params, 3)
|
return await get('/product/home-zones', params, 3)
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* 首页展示样式(待办入口排布 + 订单待办样式)
|
||||||
|
* xk-api GET /product/home-display-config;游客态 request.js 会改写到 guest
|
||||||
|
*/
|
||||||
|
export async function getHomeDisplayConfigApi() {
|
||||||
|
return await get('/product/home-display-config', {}, 3)
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 首页订单提醒(待支付挂号/商品、已发货、待确认收货)
|
||||||
|
* xk-api GET /product-order/home-remind;取值 unwrapXkApi → code / result / message
|
||||||
|
*/
|
||||||
|
export async function getHomeOrderRemindApi() {
|
||||||
|
return await get('/product-order/home-remind', {}, 3)
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* 更新商品介绍图
|
* 更新商品介绍图
|
||||||
* @param params
|
* @param params
|
||||||
@@ -51,11 +65,30 @@ export async function updateIntroductionImagesApi(params) {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 检查药店在线复诊配置(委托诊所和医生)
|
* 检查药店在线复诊配置(委托诊所和医生)
|
||||||
* @param params { store_id: number }
|
* @param params { store_id: number, guest?: number } - guest: 0=普通接口, 1=Guest接口
|
||||||
* @returns {Promise<*>}
|
* @returns {Promise<*>}
|
||||||
*/
|
*/
|
||||||
export async function checkOnlineConsultationConfigApi(params) {
|
export async function checkOnlineConsultationConfigApi(params) {
|
||||||
return await get('/store/check-online-consultation-config', params, 3)
|
const { guest = 0, ...restParams } = params;
|
||||||
|
// guest=1 时调用 Guest 接口,guest=0 时调用普通接口
|
||||||
|
const url = guest === 1
|
||||||
|
? '/guest/guest-platform/check-online-consultation-config'
|
||||||
|
: '/store/check-online-consultation-config';
|
||||||
|
return await get(url, restParams, 3)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取诊所在线问诊信息(委托诊所和委托医生)
|
||||||
|
* @param params { store_id: number, guest?: number } - guest: 0=普通接口, 1=Guest接口
|
||||||
|
* @returns {Promise<*>}
|
||||||
|
*/
|
||||||
|
export async function getClinicOnlineConsultationInfoApi(params) {
|
||||||
|
const { guest = 0, ...restParams } = params;
|
||||||
|
// guest=1 时调用 Guest 接口,guest=0 时调用普通接口
|
||||||
|
const url = guest === 1
|
||||||
|
? '/guest/guest-platform/get-clinic-online-consultation-info'
|
||||||
|
: '/store/get-clinic-online-consultation-info';
|
||||||
|
return await get(url, restParams, 3)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
124
request/api/register.js
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
import http from './request'
|
||||||
|
import {post} from './http'
|
||||||
|
import { unwrapXkApi } from '@/utils/api-response.js'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 挂号域接口统一模块(除 registerList 外均为 xk-api)
|
||||||
|
* 取值:unwrapXkApi → code / result / message
|
||||||
|
*
|
||||||
|
* 说明:registe/registeInfo 等函数迁自 api.js,保持「http(url, { method, data })」
|
||||||
|
* 老签名不动,避免改动全部调用方的传参结构;新增接口请用 post(url, params, 3) 新封装。
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取挂号记录列表 xk-api POST /register/list
|
||||||
|
* @param params { patient_id: number, store_id: number, page: number }
|
||||||
|
* @returns {Promise<*>}
|
||||||
|
*/
|
||||||
|
export async function getRegisterListApi(params) {
|
||||||
|
return await post('/register/list', params, 3)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取待支付挂号列表(首页提醒用) xk-api POST /register/list
|
||||||
|
* @param params
|
||||||
|
* @returns {Promise<Array>}
|
||||||
|
*/
|
||||||
|
export async function fetchUnpaidRegisterListApi(params = {}) {
|
||||||
|
const storeId = params.store_id || uni.getStorageSync('store_id') || '11001';
|
||||||
|
const res = await post('/register/list?pageSize=100', {
|
||||||
|
store_id: storeId,
|
||||||
|
page: 1,
|
||||||
|
...params,
|
||||||
|
}, 3);
|
||||||
|
// /register/list → xk-api
|
||||||
|
const { ok, payload } = unwrapXkApi(res)
|
||||||
|
if (!ok) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
const list = (payload && payload.list) || [];
|
||||||
|
return list.filter((item) => item.status === 0 && item.is_cancel !== 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 医生号源日历 xk-api GET /register/schedule-calendar(登录态)
|
||||||
|
* 返回 { register_status, register_price, book_days, days[] },days 含每天出诊/时段/余号
|
||||||
|
* 读值按 xk-api 形态:res.data.code == 0 → res.data.result
|
||||||
|
*/
|
||||||
|
export async function registerCalendar(params) {
|
||||||
|
let data = await http('/xkApi/register/schedule-calendar', params)
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 医生号源信息(游客态专用)
|
||||||
|
* URL 写老 Yii doc-register-info,但 request.js 会在 guest 模式下重写到
|
||||||
|
* xk-api /guest/guest-doctor/doc-register-info(响应 code/result 形态,result 带 calendar)
|
||||||
|
* @deprecated 登录态请勿使用(会打到老 Yii),登录态一律走 registerCalendar
|
||||||
|
*/
|
||||||
|
export async function registerList(params) {
|
||||||
|
let data = await http('/oldApi/v1/register/doc-register-info', params)
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 挂号建单 xk-api POST /register/create(迁自老 Yii /v1/register/register)
|
||||||
|
* 入参新增 visit_date(Y-m-d) + slot_id(0=全天兜底);返回 result{register_id, isHas}
|
||||||
|
* 读值按 xk-api 形态:res.data.code == 0 → res.data.result
|
||||||
|
*/
|
||||||
|
export async function registe(params) {
|
||||||
|
let data = await http('/xkApi/register/create', params)
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 挂号详情 xk-api POST /register/detail(迁自老 Yii /v1/register/register-detail)
|
||||||
|
* 返回 result 为单对象(老接口是 data.list[0]),附 appointment 预约日期/时段信息
|
||||||
|
*/
|
||||||
|
export async function registeInfo(params) {
|
||||||
|
let data = await http('/xkApi/register/detail', params)
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 挂号支付 xk-api POST /register/pay(易票联)
|
||||||
|
* 返回原生 xk-api 形态:res.data.code == 0 → res.data.result;0 元单 result.is_paid=1
|
||||||
|
* (原 normalize 成 errcode/data 的兼容层已删除,调用方一律按 code/result/message 取值)
|
||||||
|
*/
|
||||||
|
export async function registePay(params) {
|
||||||
|
let data = await http('/xkApi/register/pay', params)
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 取消挂号 xk-api POST /register/cancel(仅未支付单,迁自老 Yii /v1/register/cancel)
|
||||||
|
*/
|
||||||
|
export async function registeUnpay(params) {
|
||||||
|
let data = await http('/xkApi/register/cancel', params)
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 挂号退款 xk-api POST /register/refund(已支付未接诊单,迁自老 Yii /v1/register/refund)
|
||||||
|
* 注意:老 Yii refund 同时兼容未付取消,xk-api 拆成 cancel/refund 两个接口,页面按 status 分流
|
||||||
|
*/
|
||||||
|
export async function registeCancle(params) {
|
||||||
|
let data = await http('/xkApi/register/refund', params)
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改预约时间(患者本人改期) xk-api POST /register/reschedule
|
||||||
|
* 参数 { register_id, visit_date: 'Y-m-d', slot_id };就诊当天后端会拦截(提示联系医生/诊所)
|
||||||
|
*/
|
||||||
|
export async function registerReschedule(params = {}) {
|
||||||
|
return await post('/register/reschedule', params, 3)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 挂号改期记录 xk-api POST /register/reschedule-logs
|
||||||
|
* 返回 result 数组:谁在什么时候把预约从哪个时段改到哪个时段(详情页溯源展示)
|
||||||
|
*/
|
||||||
|
export async function registerRescheduleLogs(params = {}) {
|
||||||
|
return await post('/register/reschedule-logs', params, 3)
|
||||||
|
}
|
||||||
@@ -14,12 +14,66 @@ const arr = [
|
|||||||
'password'
|
'password'
|
||||||
]
|
]
|
||||||
|
|
||||||
// 敏感数据
|
// 敏感数据:响应解密后保留明文原字段,脱敏值写入 {field}_tm
|
||||||
const sensitiveData = [
|
const sensitiveData = [
|
||||||
'id_card',
|
'id_card',
|
||||||
'idcard'
|
'idcard',
|
||||||
|
'guardian_id_card'
|
||||||
]
|
]
|
||||||
|
|
||||||
|
// 仅展示脱敏、编辑需明文的字段
|
||||||
|
const displayMaskFields = [
|
||||||
|
'mobile',
|
||||||
|
'express_mobile',
|
||||||
|
'patient_mobile',
|
||||||
|
]
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 脱敏展示值(写入 field_tm)
|
||||||
|
*/
|
||||||
|
function maskFieldValue(key, plainText) {
|
||||||
|
if (plainText == null || plainText === '') {
|
||||||
|
return plainText
|
||||||
|
}
|
||||||
|
const str = String(plainText)
|
||||||
|
switch (key) {
|
||||||
|
case 'express_name':
|
||||||
|
case 'express_region':
|
||||||
|
case 'accept_name':
|
||||||
|
case 'patient':
|
||||||
|
return str.slice(0, 1).padEnd(str.length, '*')
|
||||||
|
case 'mobile':
|
||||||
|
case 'express_mobile':
|
||||||
|
case 'patient_mobile':
|
||||||
|
case 'guardian_mobile':
|
||||||
|
if (str.length <= 7) {
|
||||||
|
return str
|
||||||
|
}
|
||||||
|
return str.slice(0, 3).padEnd(str.length - 4, '*') + str.slice(-4)
|
||||||
|
case 'id_card':
|
||||||
|
case 'idcard':
|
||||||
|
case 'guardian_id_card':
|
||||||
|
if (str.length <= 10) {
|
||||||
|
return str
|
||||||
|
}
|
||||||
|
return str.slice(0, 6).padEnd(str.length - 4, '*') + str.slice(-4)
|
||||||
|
default:
|
||||||
|
return str
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 只读展示:优先 field_tm */
|
||||||
|
export function displayTm(obj, field) {
|
||||||
|
if (obj == null) {
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
const tm = obj[field + '_tm']
|
||||||
|
if (tm != null && tm !== '') {
|
||||||
|
return tm
|
||||||
|
}
|
||||||
|
return obj[field] ?? ''
|
||||||
|
}
|
||||||
|
|
||||||
const isDev = checkDev('dev');
|
const isDev = checkDev('dev');
|
||||||
|
|
||||||
// 环境URL配置
|
// 环境URL配置
|
||||||
@@ -29,14 +83,14 @@ const ENV_URLS = {
|
|||||||
main: "https://app.xiaokang88.com/member",
|
main: "https://app.xiaokang88.com/member",
|
||||||
xkApi: "https://api.xiaokang88.com/api/mobile",
|
xkApi: "https://api.xiaokang88.com/api/mobile",
|
||||||
shop: "https://shop.xiaokang88.com/member",
|
shop: "https://shop.xiaokang88.com/member",
|
||||||
im: "https://api.ws.g.xiaokang88.com/api"
|
im: "https://api.ws.g.xiaokang88.com/api",
|
||||||
},
|
},
|
||||||
// 测试环境
|
// 测试环境
|
||||||
test: {
|
test: {
|
||||||
main: "https://test.xk.app.nailaoyun.cn/member",
|
main: "https://xk.test.saas.api-yii.nailaoyun.cn/member",
|
||||||
xkApi: "https://test.xk.api.nailaoyun.cn/api/mobile",
|
xkApi: "https://xk.test.saas.api.nailaoyun.cn/api/mobile",
|
||||||
shop: "https://test.xk.shop.nailaoyun.cn/member",
|
shop: "https://test.xk.shop.nailaoyun.cn/member1",
|
||||||
im: "https://api.ws.g.nailaoyun.cn/api"
|
im: "https://xk.ws.nailaoyun.cn/api"
|
||||||
},
|
},
|
||||||
// 本地开发环境
|
// 本地开发环境
|
||||||
local: {
|
local: {
|
||||||
@@ -54,7 +108,7 @@ function getEnvUrls() {
|
|||||||
return ENV_URLS.local;
|
return ENV_URLS.local;
|
||||||
}
|
}
|
||||||
// 检查是否开启了开发者测试模式
|
// 检查是否开启了开发者测试模式
|
||||||
const devMode = uni.getStorageSync('dev_mode');
|
const devMode = checkDev('test');
|
||||||
return devMode ? ENV_URLS.test : ENV_URLS.prod;
|
return devMode ? ENV_URLS.test : ENV_URLS.prod;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,12 +135,24 @@ function request(url, params, method = 0) {
|
|||||||
} else if (url.indexOf('/xkApi/product/home-zones') !== -1) {
|
} else if (url.indexOf('/xkApi/product/home-zones') !== -1) {
|
||||||
url = url.replace('/xkApi/product/home-zones', '/guest/guest-product/home-zones');
|
url = url.replace('/xkApi/product/home-zones', '/guest/guest-product/home-zones');
|
||||||
baseURL = envUrls.xkApi;
|
baseURL = envUrls.xkApi;
|
||||||
|
} else if (url.indexOf('/xkApi/product/home-display-config') !== -1) {
|
||||||
|
url = url.replace('/xkApi/product/home-display-config', '/guest/guest-product/home-display-config');
|
||||||
|
baseURL = envUrls.xkApi;
|
||||||
} else if (url.indexOf('/xkApi/platform/config') !== -1) {
|
} else if (url.indexOf('/xkApi/platform/config') !== -1) {
|
||||||
url = url.replace('/xkApi/platform/config', '/guest/guest-platform/config');
|
url = url.replace('/xkApi/platform/config', '/guest/guest-platform/config');
|
||||||
baseURL = envUrls.xkApi;
|
baseURL = envUrls.xkApi;
|
||||||
} else if (url.indexOf('/xkApi/platform/qualifications') !== -1) {
|
} else if (url.indexOf('/xkApi/platform/qualifications') !== -1) {
|
||||||
url = url.replace('/xkApi/platform/qualifications', '/guest/guest-platform/qualifications');
|
url = url.replace('/xkApi/platform/qualifications', '/guest/guest-platform/qualifications');
|
||||||
baseURL = envUrls.xkApi;
|
baseURL = envUrls.xkApi;
|
||||||
|
} else if (url.indexOf('/xkApi/store/info') !== -1) {
|
||||||
|
url = url.replace('/xkApi/store/info', '/guest/guest-home/store-info');
|
||||||
|
baseURL = envUrls.xkApi;
|
||||||
|
} else if (url.indexOf('/xkApi/store/list') !== -1) {
|
||||||
|
url = url.replace('/xkApi/store/list', '/guest/guest-home/store-list');
|
||||||
|
baseURL = envUrls.xkApi;
|
||||||
|
} else if (url.indexOf('/xkApi/special-prescription/') !== -1) {
|
||||||
|
url = url.replace('/xkApi/special-prescription/', '/guest/guest-special-prescription/');
|
||||||
|
baseURL = envUrls.xkApi;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -112,12 +178,24 @@ function request(url, params, method = 0) {
|
|||||||
} else if (url.indexOf('/oldApi/v1/store/detail') !== -1) {
|
} else if (url.indexOf('/oldApi/v1/store/detail') !== -1) {
|
||||||
url = url.replace('/oldApi/v1/store/detail', '/guest/guest-home/store-detail');
|
url = url.replace('/oldApi/v1/store/detail', '/guest/guest-home/store-detail');
|
||||||
baseURL = envUrls.xkApi;
|
baseURL = envUrls.xkApi;
|
||||||
|
} else if (url.indexOf('/oldApi/v1/store/list') !== -1) {
|
||||||
|
url = url.replace('/oldApi/v1/store/list', '/guest/guest-home/store-list');
|
||||||
|
baseURL = envUrls.xkApi;
|
||||||
} else if (url.indexOf('/oldApi/v1/register/doc-register-info') !== -1) {
|
} else if (url.indexOf('/oldApi/v1/register/doc-register-info') !== -1) {
|
||||||
url = url.replace('/oldApi/v1/register/doc-register-info', '/guest/guest-doctor/doc-register-info');
|
url = url.replace('/oldApi/v1/register/doc-register-info', '/guest/guest-doctor/doc-register-info');
|
||||||
baseURL = envUrls.xkApi;
|
baseURL = envUrls.xkApi;
|
||||||
} else if (url.indexOf('/oldApi/v1/doctor/office-list') !== -1) {
|
} else if (url.indexOf('/oldApi/v1/doctor/office-list') !== -1) {
|
||||||
url = url.replace('/oldApi/v1/doctor/office-list', '/guest/guest-doctor/office-list');
|
url = url.replace('/oldApi/v1/doctor/office-list', '/guest/guest-doctor/office-list');
|
||||||
baseURL = envUrls.xkApi;
|
baseURL = envUrls.xkApi;
|
||||||
|
} else if (url.indexOf('/oldApi/v1/info/categories') !== -1) {
|
||||||
|
url = url.replace('/oldApi/v1/info/categories', '/guest/guest-info/categories');
|
||||||
|
baseURL = envUrls.xkApi;
|
||||||
|
} else if (url.indexOf('/oldApi/v1/info/article-list') !== -1) {
|
||||||
|
url = url.replace('/oldApi/v1/info/article-list', '/guest/guest-info/article-list');
|
||||||
|
baseURL = envUrls.xkApi;
|
||||||
|
} else if (url.indexOf('/oldApi/v1/info/article-info') !== -1) {
|
||||||
|
url = url.replace('/oldApi/v1/info/article-info', '/guest/guest-info/article-info');
|
||||||
|
baseURL = envUrls.xkApi;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -132,6 +210,12 @@ function request(url, params, method = 0) {
|
|||||||
} else if (url.indexOf('/v1/register/doc-register-info') !== -1 || url.indexOf('/member/v1/register/doc-register-info') !== -1) {
|
} else if (url.indexOf('/v1/register/doc-register-info') !== -1 || url.indexOf('/member/v1/register/doc-register-info') !== -1) {
|
||||||
url = url.replace(/\/member\/v1\/register\/doc-register-info|\/v1\/register\/doc-register-info/, '/guest/guest-doctor/doc-register-info');
|
url = url.replace(/\/member\/v1\/register\/doc-register-info|\/v1\/register\/doc-register-info/, '/guest/guest-doctor/doc-register-info');
|
||||||
baseURL = envUrls.xkApi;
|
baseURL = envUrls.xkApi;
|
||||||
|
} else if (url.indexOf('/v1/store/info') !== -1 || url.indexOf('/member/v1/store/info') !== -1) {
|
||||||
|
url = url.replace(/\/member\/v1\/store\/info|\/v1\/store\/info/, '/guest/guest-home/store-info');
|
||||||
|
baseURL = envUrls.xkApi;
|
||||||
|
} else if (url.indexOf('/v1/store/list') !== -1 || url.indexOf('/member/v1/store/list') !== -1) {
|
||||||
|
url = url.replace(/\/member\/v1\/store\/list|\/v1\/store\/list/, '/guest/guest-home/store-list');
|
||||||
|
baseURL = envUrls.xkApi;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -143,8 +227,9 @@ function request(url, params, method = 0) {
|
|||||||
}
|
}
|
||||||
if (url.split('/').indexOf('xkApi') !== -1) {
|
if (url.split('/').indexOf('xkApi') !== -1) {
|
||||||
baseURL = envUrls.xkApi;
|
baseURL = envUrls.xkApi;
|
||||||
// 如果是guest模式且是xkApi请求,添加/guest/前缀
|
// 如果是guest模式且是xkApi请求,添加/guest/前缀(但避免重复添加)
|
||||||
if (isGuestRequest) {
|
// 转诊相关接口需要登录,不转换为guest路由
|
||||||
|
if (isGuestRequest && url.indexOf('/guest/') === -1 && url.indexOf('/transfer-prescription') === -1) {
|
||||||
url = url.replace('/xkApi', '/guest/xkApi');
|
url = url.replace('/xkApi', '/guest/xkApi');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -155,10 +240,29 @@ function request(url, params, method = 0) {
|
|||||||
|
|
||||||
// 加密
|
// 加密
|
||||||
if (params != null) {
|
if (params != null) {
|
||||||
|
if (!params.data) {
|
||||||
|
params.data = {};
|
||||||
|
}
|
||||||
params.data = getRes(params.data, false);
|
params.data = getRes(params.data, false);
|
||||||
// 如果是guest模式,强制设置store_id为11001
|
const isProductApi = url.indexOf('/product/') !== -1;
|
||||||
|
if (isProductApi && !params.data.store_id) {
|
||||||
|
const localStoreId = uni.getStorageSync('store_id');
|
||||||
|
params.data.store_id = localStoreId || getGuestStoreId();
|
||||||
|
}
|
||||||
|
// 如果是guest模式,设置store_id(优先使用用户传入或本地存储的值)
|
||||||
if (isGuestRequest && params.data) {
|
if (isGuestRequest && params.data) {
|
||||||
params.data.store_id = getGuestStoreId();
|
// 优先使用用户传入的 store_id
|
||||||
|
if (!params.data.store_id) {
|
||||||
|
// 如果用户没传,尝试从本地存储获取
|
||||||
|
const localStoreId = uni.getStorageSync('store_id');
|
||||||
|
if (localStoreId) {
|
||||||
|
params.data.store_id = localStoreId;
|
||||||
|
} else {
|
||||||
|
// 如果本地存储也没有,使用默认值(保持向后兼容)
|
||||||
|
params.data.store_id = getGuestStoreId();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 如果用户已经传了 store_id,就使用用户传入的值,不做任何修改
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let num = 0;
|
let num = 0;
|
||||||
@@ -224,56 +328,47 @@ function request(url, params, method = 0) {
|
|||||||
|
|
||||||
function getRes(obj, isDecode = true) {
|
function getRes(obj, isDecode = true) {
|
||||||
try {
|
try {
|
||||||
|
if (obj == null || typeof obj !== 'object') {
|
||||||
|
return obj
|
||||||
|
}
|
||||||
for (const key in obj) {
|
for (const key in obj) {
|
||||||
|
if (key.endsWith('_tm')) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
if (Array.isArray(obj[key])) {
|
if (Array.isArray(obj[key])) {
|
||||||
obj[key] = getRes(obj[key])
|
obj[key] = getRes(obj[key], isDecode)
|
||||||
} else if (typeof obj[key] === 'object') {
|
} else if (obj[key] !== null && typeof obj[key] === 'object') {
|
||||||
obj[key] = getRes(obj[key])
|
obj[key] = getRes(obj[key], isDecode)
|
||||||
} else {
|
} else if (arr.indexOf(key) !== -1) {
|
||||||
// 判断obj[key]是否在arr中
|
// 未填写的敏感字段保持空串,禁止加解密(避免空值被解成密文乱码)
|
||||||
if (arr.indexOf(key) !== -1) {
|
if (obj[key] == null || obj[key] === '') {
|
||||||
let aseFile = ''
|
obj[key] = ''
|
||||||
if (isDecode === true) {
|
if (isDecode === true && (sensitiveData.indexOf(key) !== -1 || displayMaskFields.indexOf(key) !== -1)) {
|
||||||
aseFile = customBase64Decode(obj[key])
|
obj[key + '_tm'] = ''
|
||||||
} else {
|
|
||||||
aseFile = customBase64Encode(obj[key])
|
|
||||||
}
|
}
|
||||||
const isGarbled = /[\x00-\x08\x0B\x0C\x0E-\x1F\x7F-\xFF]|[\u{E000}-\u{F8FF}]/u.test(
|
continue
|
||||||
typeof aseFile === 'string' ? aseFile : ''
|
}
|
||||||
)
|
let plainValue = ''
|
||||||
if (isGarbled) {
|
if (isDecode === true) {
|
||||||
aseFile = obj[key]
|
plainValue = customBase64Decode(obj[key])
|
||||||
|
} else {
|
||||||
|
plainValue = customBase64Encode(obj[key])
|
||||||
|
}
|
||||||
|
const isGarbled = /[\x00-\x08\x0B\x0C\x0E-\x1F\x7F-\xFF]|[\u{E000}-\u{F8FF}]/u.test(
|
||||||
|
typeof plainValue === 'string' ? plainValue : ''
|
||||||
|
)
|
||||||
|
if (isGarbled) {
|
||||||
|
plainValue = obj[key]
|
||||||
|
}
|
||||||
|
if (isDecode === true) {
|
||||||
|
const needTm = sensitiveData.indexOf(key) !== -1
|
||||||
|
|| displayMaskFields.indexOf(key) !== -1
|
||||||
|
obj[key] = plainValue
|
||||||
|
if (needTm) {
|
||||||
|
obj[key + '_tm'] = maskFieldValue(key, plainValue)
|
||||||
}
|
}
|
||||||
// 为了修改,暂时不脱敏
|
} else {
|
||||||
if (isDecode === true) {
|
obj[key] = plainValue
|
||||||
|
|
||||||
if (sensitiveData.indexOf(key) !== -1) {
|
|
||||||
// 数据脱敏,自动匹配姓名、手机号、身份证
|
|
||||||
switch (key) {
|
|
||||||
case 'express_name':
|
|
||||||
case 'express_region':
|
|
||||||
case 'accept_name':
|
|
||||||
case 'patient':
|
|
||||||
// 保留前两个字符,其余用星号代替
|
|
||||||
aseFile = aseFile.slice(0, 1).padEnd(aseFile.length, '*');
|
|
||||||
break;
|
|
||||||
case 'mobile':
|
|
||||||
case 'express_mobile':
|
|
||||||
// 保留前三位和后四位,中间用星号代替
|
|
||||||
aseFile = aseFile.slice(0, 3).padEnd(aseFile.length - 4, '*') + aseFile.slice(-4);
|
|
||||||
break;
|
|
||||||
case 'id_card':
|
|
||||||
case 'idcard':
|
|
||||||
// 保留前六位和后四位,中间用星号代替
|
|
||||||
aseFile = aseFile.slice(0, 6).padEnd(aseFile.length - 4, '*') + aseFile.slice(-4);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
// 默认情况下,全部用星号代替
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
obj[key] = aseFile
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -285,17 +380,22 @@ function getRes(obj, isDecode = true) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function customBase64Decode(data) {
|
function customBase64Decode(data) {
|
||||||
|
// 空值直接返回空串,避免 Base64.decode(null/'' ) 失败后回退成密文原串
|
||||||
|
if (data == null || data === '') {
|
||||||
|
return ''
|
||||||
|
}
|
||||||
// return data
|
// return data
|
||||||
try {
|
try {
|
||||||
// 第一次Base64解码
|
// 第一次Base64解码
|
||||||
const decodedFirst = Base64.decode(data)
|
const decodedFirst = Base64.decode(data)
|
||||||
// 截取从第30个字符开始往后的内容
|
// 截取从第30个字符开始往后的内容
|
||||||
const subStr = decodedFirst.slice(30)
|
const subStr = decodedFirst.slice(30)
|
||||||
// 第二次Base64解码
|
// 第二次Base64解码;解出空串说明业务上就是未填写,不要回退成密文
|
||||||
return Base64.decode(subStr) != '' ? Base64.decode(subStr) : data
|
const decodedSecond = Base64.decode(subStr)
|
||||||
|
return decodedSecond !== '' ? decodedSecond : ''
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`解码Base64字符串【${data}】时发生错误`, error)
|
console.error(`解码Base64字符串【${data}】时发生错误`, error)
|
||||||
return data
|
return ''
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
105
request/api/specialPrescription.js
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
import { get, post } from './http'
|
||||||
|
|
||||||
|
export const SPECIAL_PRESCRIPTION_STORAGE_KEY = 'special_prescription_register_context'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 首页特色方配置
|
||||||
|
* @param params {{ store_id?: number|string }}
|
||||||
|
*/
|
||||||
|
export async function getSpecialPrescriptionHomeApi(params) {
|
||||||
|
return await get('/special-prescription/home', params, 3)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 特色方列表页配置
|
||||||
|
* @param params {{ store_id?: number|string }}
|
||||||
|
*/
|
||||||
|
export async function getSpecialPrescriptionListPageApi(params) {
|
||||||
|
return await get('/special-prescription/list-page', params, 3)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 特色方列表
|
||||||
|
* @param params {{ store_id?: number|string, category_id?: number, name?: string, page?: number, pageSize?: number }}
|
||||||
|
*/
|
||||||
|
export async function getSpecialPrescriptionListApi(params) {
|
||||||
|
return await get('/special-prescription/list', params, 3)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 特色方详情
|
||||||
|
* @param params {{ id: number|string, store_id?: number|string }}
|
||||||
|
*/
|
||||||
|
export async function getSpecialPrescriptionDetailApi(params) {
|
||||||
|
return await get('/special-prescription/detail', params, 3)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 特色方分类
|
||||||
|
*/
|
||||||
|
export async function getSpecialPrescriptionCategoriesApi(params = {}) {
|
||||||
|
return await get('/special-prescription/categories', params, 3)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 挂号成功后创建选方记录
|
||||||
|
* @param params {{ register_id, special_prescription_id, dose_count, store_id, doctor_id }}
|
||||||
|
*/
|
||||||
|
export async function createSpecialPrescriptionPatientRecordApi(params) {
|
||||||
|
return await post('/special-prescription/create-patient-record', params, 3)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存特色方挂号上下文(merge 已有值,避免后续页面未传 sku_id 时覆盖为 0)
|
||||||
|
* @param ctx {{ special_prescription_id, dose_count?, sku_id?, doctor_id? }}
|
||||||
|
*/
|
||||||
|
export function saveSpecialPrescriptionRegisterContext(ctx) {
|
||||||
|
if (!ctx || !ctx.special_prescription_id) return
|
||||||
|
const prev = getSpecialPrescriptionRegisterContext() || {}
|
||||||
|
const merged = {
|
||||||
|
special_prescription_id: ctx.special_prescription_id,
|
||||||
|
dose_count: ctx.dose_count != null ? ctx.dose_count : (prev.dose_count || 1),
|
||||||
|
doctor_id: ctx.doctor_id != null ? ctx.doctor_id : (prev.doctor_id || ''),
|
||||||
|
}
|
||||||
|
// 未传 sku_id 字段时保留 storage 已有值,防止中间页覆盖为 0
|
||||||
|
if (Object.prototype.hasOwnProperty.call(ctx, 'sku_id')) {
|
||||||
|
merged.sku_id = Number(ctx.sku_id) || 0
|
||||||
|
} else {
|
||||||
|
merged.sku_id = Number(prev.sku_id) || 0
|
||||||
|
}
|
||||||
|
uni.setStorageSync(SPECIAL_PRESCRIPTION_STORAGE_KEY, merged)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getSpecialPrescriptionRegisterContext() {
|
||||||
|
return uni.getStorageSync(SPECIAL_PRESCRIPTION_STORAGE_KEY) || null
|
||||||
|
}
|
||||||
|
|
||||||
|
export function clearSpecialPrescriptionRegisterContext() {
|
||||||
|
uni.removeStorageSync(SPECIAL_PRESCRIPTION_STORAGE_KEY)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 挂号成功后绑定特色方选方记录(幂等,失败不阻断流程)
|
||||||
|
* @param registerId
|
||||||
|
*/
|
||||||
|
export async function tryCreateSpecialPrescriptionPatientRecord(registerId) {
|
||||||
|
if (!registerId) return
|
||||||
|
const ctx = getSpecialPrescriptionRegisterContext()
|
||||||
|
if (!ctx || !ctx.special_prescription_id) return
|
||||||
|
|
||||||
|
try {
|
||||||
|
const res = await createSpecialPrescriptionPatientRecordApi({
|
||||||
|
register_id: registerId,
|
||||||
|
special_prescription_id: ctx.special_prescription_id,
|
||||||
|
dose_count: ctx.dose_count || 1,
|
||||||
|
sku_id: ctx.sku_id || 0,
|
||||||
|
store_id: uni.getStorageSync('store_id') || '11001',
|
||||||
|
doctor_id: ctx.doctor_id,
|
||||||
|
})
|
||||||
|
if (res.data?.code === 0 || res.data?.code === '0') {
|
||||||
|
clearSpecialPrescriptionRegisterContext()
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error('tryCreateSpecialPrescriptionPatientRecord', e)
|
||||||
|
}
|
||||||
|
}
|
||||||
78
request/api/transferPrescription.js
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
import {post, get} from './http'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取转诊消息列表
|
||||||
|
* @returns {Promise<*>}
|
||||||
|
*/
|
||||||
|
export async function getTransferPrescriptionListApi() {
|
||||||
|
return await post('/transfer-prescription/list', {}, 3)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取转诊详情
|
||||||
|
* @param params { id: number }
|
||||||
|
* @returns {Promise<*>}
|
||||||
|
*/
|
||||||
|
export async function getTransferPrescriptionDetailApi(params) {
|
||||||
|
return await get('/transfer-prescription/detail', params, 3)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 同意转诊
|
||||||
|
* @param params { id: number }
|
||||||
|
* @returns {Promise<*>}
|
||||||
|
*/
|
||||||
|
export async function agreeTransferPrescriptionApi(params) {
|
||||||
|
return await post('/transfer-prescription/agree', params, 3)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 拒绝转诊
|
||||||
|
* @param params { id: number, reason?: string }
|
||||||
|
* @returns {Promise<*>}
|
||||||
|
*/
|
||||||
|
export async function rejectTransferPrescriptionApi(params) {
|
||||||
|
return await post('/transfer-prescription/reject', params, 3)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取转诊问题列表(用于咨询页面)
|
||||||
|
* @returns {Promise<*>}
|
||||||
|
*/
|
||||||
|
export async function getTransferQuestionsApi() {
|
||||||
|
return await get('/transfer-prescription/get-questions', {}, 3)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 提交转诊问题答案
|
||||||
|
* @param params { transfer_id: number, answers: Array<{question_id: number, answer: string}> }
|
||||||
|
* @returns {Promise<*>}
|
||||||
|
*/
|
||||||
|
export async function submitTransferQuestionsApi(params) {
|
||||||
|
return await post('/transfer-prescription/submit-questions', params, 3)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取转诊助理配置(移动端)
|
||||||
|
* @returns {Promise<*>}
|
||||||
|
*/
|
||||||
|
export async function getTransferAssistantConfigApi() {
|
||||||
|
return await get('/transfer-assistant-config/get-config', {}, 3)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取转诊咨询协议信息(固定文案和协议列表)
|
||||||
|
* @returns {Promise<*>}
|
||||||
|
*/
|
||||||
|
export async function getTransferConsultationAgreementInfoApi() {
|
||||||
|
return await get('/transfer-consultation/get-agreement-info', {}, 3)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取协议详情(根据协议ID)
|
||||||
|
* @param {number} agreementId 协议ID
|
||||||
|
* @returns {Promise<*>}
|
||||||
|
*/
|
||||||
|
export async function getAgreementDetailApi(agreementId) {
|
||||||
|
return await get(`/agreement/get-detail?id=${agreementId}`, {}, 3)
|
||||||
|
}
|
||||||
10
request/api/user.js
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
import {post} from './http'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取用户信息(包含订单统计)
|
||||||
|
* @param params { store_id: number }
|
||||||
|
* @returns {Promise<*>}
|
||||||
|
*/
|
||||||
|
export async function getUserInfoApi(params) {
|
||||||
|
return await post('/user/info', params, 3)
|
||||||
|
}
|
||||||
|
Before Width: | Height: | Size: 6.3 KiB |
|
Before Width: | Height: | Size: 5.1 KiB |
|
Before Width: | Height: | Size: 594 B |
|
Before Width: | Height: | Size: 1019 B |
|
Before Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 45 KiB |
|
Before Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 38 KiB |
|
Before Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 59 KiB |
|
Before Width: | Height: | Size: 25 KiB |
|
Before Width: | Height: | Size: 44 KiB |
|
Before Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 37 KiB |
|
Before Width: | Height: | Size: 5.2 KiB |
|
Before Width: | Height: | Size: 226 KiB |
|
Before Width: | Height: | Size: 37 KiB |
|
Before Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 3.5 KiB |
|
Before Width: | Height: | Size: 5.0 KiB |
|
Before Width: | Height: | Size: 870 B |
|
Before Width: | Height: | Size: 859 B |
|
Before Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 3.4 KiB |
|
Before Width: | Height: | Size: 3.4 KiB |
|
Before Width: | Height: | Size: 3.7 KiB |
|
Before Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 4.0 KiB |
|
Before Width: | Height: | Size: 9.4 KiB |
|
Before Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 971 B |
|
Before Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 3.0 KiB |
|
Before Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 4.6 KiB |
|
Before Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 67 KiB |
BIN
static/share.png
|
Before Width: | Height: | Size: 24 KiB |
|
Before Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 1.0 KiB |
|
Before Width: | Height: | Size: 932 B |
|
Before Width: | Height: | Size: 1.7 KiB |