diff --git a/.cloudbase/container/debug.json b/.cloudbase/container/debug.json deleted file mode 100644 index 0d44458..0000000 --- a/.cloudbase/container/debug.json +++ /dev/null @@ -1 +0,0 @@ -{"containers":[],"config":{}} \ No newline at end of file diff --git a/app.js b/app.js index e5ae361..01b45ed 100644 --- a/app.js +++ b/app.js @@ -1,4 +1,3 @@ -// app.js App({ towxml: require('/towxml/index'), globalData: { diff --git a/app.json b/app.json index a23e110..b27272f 100644 --- a/app.json +++ b/app.json @@ -3,16 +3,18 @@ "pages/system/welcome/index", "pages/home/index", "pages/test/index", - "pages/joinFlow/access/index", - "pages/joinFlow/manual/index", "pages/joinFlow/person/index", - "pages/expert/index" + "pages/expert/index", + "pages/chat/index" ], "tabBar": { "custom": true, "list": [ { "pagePath": "pages/home/index" + }, + { + "pagePath": "pages/chat/index" }, { "pagePath": "pages/expert/index" @@ -65,6 +67,7 @@ "t-cascader": "tdesign-miniprogram/cascader/cascader", "t-form": "tdesign-miniprogram/form/form", "t-form-item": "tdesign-miniprogram/form-item/form-item", - "t-divider": "tdesign-miniprogram/divider/divider" + "t-divider": "tdesign-miniprogram/divider/divider", + "t-loading": "tdesign-miniprogram/loading/loading" } } \ No newline at end of file diff --git a/app.scss b/app.scss index f301de9..af67f45 100644 --- a/app.scss +++ b/app.scss @@ -15,7 +15,9 @@ navigator { page { + --td-brand-color: rgba(0, 106, 106, 1); --background: linear-gradient(135deg, rgba(0, 33, 33, 1), rgba(0, 106, 106, 1)); + --area-bottom: calc(130rpx + env(safe-area-inset-bottom)); .t-navbar__capsule::before { display: none; } diff --git a/custom-tab-bar/index.js b/custom-tab-bar/index.js index bb31e41..1fbe696 100644 --- a/custom-tab-bar/index.js +++ b/custom-tab-bar/index.js @@ -19,6 +19,11 @@ Component({ label: '首页', icon: 'home' }, + { + path: "/pages/chat/index", + label: 'AI助手', + icon: 'chat-bubble' + }, { path: "/pages/expert/index", label: '专家服务', diff --git a/pages/chat/index.js b/pages/chat/index.js new file mode 100644 index 0000000..6999467 --- /dev/null +++ b/pages/chat/index.js @@ -0,0 +1,292 @@ +import request, { streamRequest } from "@/utils/request"; +import { copyText } from "@/utils/common" +let outTimer; //输出定时器 +let outStrList = [];//输出字符串数组 +const app = getApp() + +let chat_uuid +//工具 +let toolText = '' +let toolInfo = {} +Page({ + data: { + chatList: [], //会话记录 + aiStatus: 3,//1表示接口响应中,2表示接口响应完毕,3表示完全输出完毕 + keyboardBottom: 0, //底部键盘高度 + scrollTop: 0, //滚动条位置 + inputText: '',//输入框内容 + }, + onLoad() { + let str = `您好!我是术极守护AI助手 🤖\n\n我可以为您解答术后康复相关的问题。请注意,我只能提供基于康复指南的一般性建议,如遇紧急情况请立即就医或联系您的主治医生。` + let mdResult = app.towxml(str, 'markdown', { + base: "www.xxx.com", + }); + let list = [ + { + loading: false, + end: true, + chat_type: 2, + md_content: mdResult, + chat_content: str, + quick_btn: [ + { text: '🩹伤口有轻微渗液怎么办?' }, + { text: '🌡️术后轻微发烧正常吗?' }, + { text: '🚿什么时候可以洗澡?' }, + { text: '🥗饮食需要注意什么?' } + ] + } + ] + this.setData({ + chatList: list + }) + }, + onShow() { + this.getTabBar((tabBar) => { + tabBar.setData({ + selected: 'AI助手', + }) + }) + }, + //监听键盘弹出 + bindkeyboardheightchange(event) { + let height = event.detail.height + let { keyboardBottom } = this.data + let scrollTop = 0 + //获取当前滚动距离 + const query = wx.createSelectorQuery().in(this) + query.select(".silder").scrollOffset() + query.exec(function (res) { + scrollTop = res[0].scrollTop + }) + this.setData({ + keyboardBottom: height > 0 ? height - 50 : keyboardBottom, + }, () => { + if (height > 0) { + setTimeout(() => { + this.setData({ + scrollTop: scrollTop + height + }) + }, 300) + } + }) + }, + //键盘失去焦点 + bindkeyboardBlur() { + let { scrollTop, keyboardBottom } = this.data + let endScrollTop = scrollTop - keyboardBottom + this.setData({ + keyboardBottom: 0 + }, () => { + this.setData({ + scrollTop: endScrollTop + }) + }) + }, + //监听输入框内容 + changeInput(e) { + let value = e.detail.value + this.setData({ + inputText: value + }) + }, + async handQuick(e) { + let { data } = e.currentTarget.dataset + this.pushUserTemplate(data.text) + this.sendMessage(data.text) + + }, + + // 文字提交发送 + submitInput() { + let { inputText, aiStatus } = this.data + if (!inputText.trim() == '' && aiStatus) { + console.log('111--'); + this.pushUserTemplate(inputText) + this.sendMessage(inputText) + } + }, + //发送聊天 + async sendMessage(text) { + let { chatList, aiStatus } = this.data + if (aiStatus == 3) { + let that = this + //初始化变量 + toolText = '' + toolInfo = {} + chat_uuid = String(new Date().getTime()) + this.setData({ + aiStatus: 1 + }) + //输出 + this.timerOutput() + //请求 + streamRequest("/ai/chat", { + message: text, + chat_uuid: chat_uuid, + }, this.onChunkReceived).then(() => { + console.log('-------------成功-----------'); + if (this.data.aiStatus != 3) { + that.setData({ + aiStatus: 2 + }) + } + }).catch(() => { + console.log("------失败1---------"); + that.data.chatList.at(-1).loading = false + that.setData({ + aiStatus: 3, + chatList: chatList + }) + }) + } + }, + + //填充用户的聊天数据 + pushUserTemplate(text) { + let { chatList } = this.data + let userItem = { + loading: false, + chat_type: 1, + con_type: 1, + chat_content: text, + md_content: '', + } + let aiItem = { + chat_type: 2, + chat_content: '', + md_content: '', + con_type: 1, + loading: true, + } + chatList.push(userItem) + + chatList.push(aiItem) + + //要修改的数据 + let setData = { + chatList, + scrollTop: 80000, + inputText: '' + } + this.setData(setData, () => { + this.setData({ + scrollTop: 80000 + }) + }) + }, + //只填充ai的默认回复 + pushAiTemplate(text, options = {}) { + let { chatList } = this.data + let mdResult = app.towxml(text, 'markdown', { + base: "www.xxx.com", + }); + let aiItem = { + chat_type: 2, + chat_content: text, + md_content: mdResult, + con_type: 1, + quick_btn: options.quick_btn || [], + ...options + } + chatList.push(aiItem) + //要修改的数据 + let setData = { + chatList, + scrollTop: 80000, + inputText: '' + } + this.setData(setData, () => { + this.setData({ + scrollTop: 80000 + }) + }) + }, + + //定时器输出 + timerOutput() { + let { chatList } = this.data + let that = this + clearInterval(outTimer) + outStrList = [] + let lastChat = this.data.chatList.at(-1) + //定时 + outTimer = setInterval(async () => { + if ((outStrList.length == 0) && that.data.aiStatus == 2) { + clearInterval(outTimer) + lastChat.end = true + //如果有工具,设置工具对象 + let text = lastChat.chat_content + // 上传AI响应结果 + if (text) { + await request.post("/ai/history/upload", { + chat_content: text, + chat_uuid: chat_uuid, + }) + } + //调用工具 + if (toolText) { } + that.setData({ + chatList, + aiStatus: 3 + }) + + } else if (outStrList.length > 0) { + let firstValue = outStrList.shift(); + lastChat.chat_content += firstValue + //转换md + let mdResult = app.towxml(lastChat.chat_content, 'markdown', { + base: "www.xxx.com", + }); + lastChat.md_content = mdResult + lastChat.loading = false + that.setData({ + chatList: chatList, + scrollTop: 80000 + }) + } + }, 50) + }, + //流回调 + onChunkReceived(data) { + data.forEach((item) => { + let value = item?.choices[0].delta.content ?? '' + let call = item?.choices[0].delta.tool_calls + //储存tool的id和名称 + if (call) { + if (call[0].id) { + toolInfo.tool_call_id = call[0].id + toolInfo.name = call[0].function.name + } + let tool = call[0].function.arguments ?? '' + toolText += tool + } + if (value) { + outStrList.push(value) + } + }) + }, + //停止 + async stopMessage() { + clearInterval(outTimer) + let lastChat = this.data.chatList.at(-1) + lastChat.chat_status = 2 + this.setData({ + aiStatus: 3, + chatList: this.data.chatList + }) + await request.post("/ai/history/upload", { + chat_content: lastChat.chat_content || 'nocontent', + chat_status: 2, + chat_uuid: chat_uuid + }) + }, + //复制文字 + copy(e) { + let { content, chat_content } = e.currentTarget.dataset.text + console.log(e); + if (!content) { + content = chat_content + } + copyText(content) + }, +}) \ No newline at end of file diff --git a/pages/chat/index.json b/pages/chat/index.json new file mode 100644 index 0000000..8e2df44 --- /dev/null +++ b/pages/chat/index.json @@ -0,0 +1,6 @@ +{ + "usingComponents": { + "towxml": "/towxml/towxml" + }, + "navigationStyle": "custom" +} \ No newline at end of file diff --git a/pages/chat/index.scss b/pages/chat/index.scss new file mode 100644 index 0000000..95cadff --- /dev/null +++ b/pages/chat/index.scss @@ -0,0 +1,179 @@ +@import "./makedown.scss"; + +.c-container { + display: flex; + flex-direction: column; + height: 100vh; + padding-bottom: var(--area-bottom); + + .t-navbar__content { + backdrop-filter: blur(18px); + } +} + +.silder { + overflow: auto; + flex: 1; + padding: 30rpx 0; + box-sizing: border-box; + + .chat-item { + padding: 10rpx 30rpx; + + &+.chat-item { + margin-top: 30rpx; + } + + .lawyer-info { + margin-bottom: 20rpx; + font-size: 0.75rem; + + image { + width: 50rpx; + height: 50rpx; + border-radius: 50%; + margin-right: 10rpx; + display: block; + } + } + + .chat-image { + width: 250rpx; + height: 250rpx; + border-radius: 20rpx; + } + + .chat-message { + max-width: calc(100% - 100rpx); + min-height: 60rpx; + width: fit-content; + padding: 20rpx; + border-radius: 10rpx; + font-size: 0.9rem; + overflow: hidden; + + .loading { + height: 40rpx; + width: 40rpx; + border-radius: 50%; + box-shadow: inset 0 0 0 var(--td-brand-color); + animation: load 2s linear infinite alternate; + } + + .stop-tip { + margin-top: 20rpx; + font-size: 0.64rem; + color: var(--text-3); + } + + .m-footer { + margin-top: 10rpx; + + .tip { + @extend .stop-tip; + margin-top: 0; + opacity: 0.1; + } + + .sound-icon { + color: var(--text-2); + font-size: 1rem; + } + } + } + + .quick-warpper { + font-size: 0.75rem; + gap: 30rpx; + margin-top: 20rpx; + display: flex; + flex-wrap: wrap; + + .quick-item { + background-color: white; + padding: 10rpx 20rpx; + border-radius: 50rpx; + border: 1px solid #dfdddd; + + &.color { + color: white; + border-color: transparent; + ; + } + } + } + } + + .ai-msg { + .chat-message { + background-color: white; + border-radius: 20rpx 30rpx 30rpx 10rpx; + box-shadow: 0 0 15rpx #e2e2e2; + } + + } + + .user-msg { + display: flex; + flex-direction: column; + align-items: flex-end; + + .chat-message { + background-color: var(--td-brand-color); + color: white; + border-radius: 30rpx 30rpx 0 30rpx; + } + } +} + +.bottom-position { + margin: 0 30rpx; + position: relative; + + //输入框 + .input-warpper { + box-shadow: 0 0 15rpx #e2e2e2; + padding: 20rpx 30rpx; + background-color: white; + border-radius: 50rpx; + + input { + flex: 1; + } + + + .push-btn { + border-radius: 50%; + width: 65rpx; + height: 65rpx; + color: var(--text-3); + transition: opacity 0.3s; + + &.active-push { + background-color: var(--td-brand-color); + color: white; + } + } + + .stop-btn { + font-size: 65rpx; + color: var(--td-brand-color); + } + } +} + +//占位 +.empty { + transition: height 0.3s; +} + +//ai响应loading +@keyframes load { + 0% { + box-shadow: inset -20rpx 40rpx 0 var(--td-brand-color); + } + + 100% { + box-shadow: inset 20rpx -40rpx 0 var(--td-brand-color); + } +} \ No newline at end of file diff --git a/pages/chat/index.wxml b/pages/chat/index.wxml new file mode 100644 index 0000000..cc122ee --- /dev/null +++ b/pages/chat/index.wxml @@ -0,0 +1,103 @@ + + + + + + + + + AI助手 + + + + + + + + + {{item.tool}} + + + {{item.chat_content}} + + + + + (已停止) + + + + AI助手仅提供基于康复指南的一般性建议,不构成医疗诊断。如遇紧急情况请立即就医 + + + + + + + + + + {{quick.text}} + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pages/chat/makedown.scss b/pages/chat/makedown.scss new file mode 100644 index 0000000..964f6be --- /dev/null +++ b/pages/chat/makedown.scss @@ -0,0 +1,17 @@ +.h2w__main, +.h2w__p { + padding: 0 !important; + margin: 0 !important; + font-size: 0.9rem; + +} + +.h2w__li { + margin-top: 20rpx; +} + + +.h2w__h3 { + font-size: 32rpx !important; + margin-top: 20rpx !important; +} \ No newline at end of file diff --git a/pages/chat/read.md b/pages/chat/read.md new file mode 100644 index 0000000..3c4e09d --- /dev/null +++ b/pages/chat/read.md @@ -0,0 +1,15 @@ + 聊天列表类型 +``` typescript +interface ChatType{ + loading: boolean, // 是否开始响应 + end:boolean,//响应输出完成 + chat_type: 1 | 2, // 1用户,2ai普通响应 + chat_content: string, //文本内容 + md_content: string, //md格式 + con_type:1, //消息类型,1文本,2图片 + tool:string, //用工具时的默认内容,为空代表不是工具 + chat_status?:number, //2停止 + quick_btn:[], //快捷菜单按钮,为空不显示 + drugList:[],//药品信息,只用来设置提醒 +} +``` \ No newline at end of file diff --git a/pages/expert/index.js b/pages/expert/index.js index 509cf71..0248814 100644 --- a/pages/expert/index.js +++ b/pages/expert/index.js @@ -1,9 +1,77 @@ +import request from "@/utils/request" + +const app = getApp() Page({ + data: { + list: [ + { + s: "李", + name: "李医生", + title: "主任医师 · 骨科专家", + desc: "20年临床经验" + }, + { + s: "王", + name: "王医生", + title: "副主任医师 · 康复医学", + desc: "15年临床经验" + }, + { + s: "张", + name: "张护士长", + title: "主管护师 · 伤口护理", + desc: "18年护理经验" + } + ], + count: 0 + }, onShow() { + let userInfo = app.globalData.userInfo + this.setData({ + count: userInfo.consult_remains + }) this.getTabBar((tabBar) => { tabBar.setData({ selected: '专家服务', }) }) + }, + + async onPlay() { + if (this.data.count <= 0) { + wx.showToast({ + title: '免费次数已用完', + icon: 'none' + }); + return; + } + // 2. 弹窗确认 + wx.showModal({ + title: '拨打专家热线', + content: '确认拨打专家咨询电话吗?本次咨询将使用1次免费机会', + success: async (res) => { + if (res.confirm) { + try { + wx.showLoading({ title: '正在呼叫...', mask: true }); + const info = await request.get("/expert/phone"); + this.setData({ + count: this.data.count - 1 + }); + wx.hideLoading(); + + // 5. 吊起拨号盘 + if (info && info.expert_phone) { + wx.makePhoneCall({ + phoneNumber: info.expert_phone, + }); + } else { + wx.showToast({ title: '暂无专家电话', icon: 'none' }); + } + } catch (error) { + wx.hideLoading(); + } + } + } + }); } }) \ No newline at end of file diff --git a/pages/expert/index.scss b/pages/expert/index.scss index 4b400bb..f8d486d 100644 --- a/pages/expert/index.scss +++ b/pages/expert/index.scss @@ -1,5 +1,6 @@ page { background-color: rgba(247, 249, 252, 1); + padding-bottom: 200rpx; } .head { @@ -47,11 +48,175 @@ page { color: rgba(255, 255, 255, 0.8); } } - .btn{ + + .btn { padding: 50rpx 0; background-color: rgba(29, 120, 116, 1); } - .c-2{ - + + .service-card { + width: 100%; + background-color: #fff; + border-radius: 12px; + padding: 16px; + box-sizing: border-box; + box-shadow: 0 2px 6px rgba(0, 0, 0, 0.05); + margin-top: 30rpx; + + .flex-align { + display: flex; + align-items: center; + } + + .header { + .icon { + width: 32px; + height: 32px; + background-color: #f0f5f0; // 图标背景色 + border-radius: 50%; + display: flex; + justify-content: center; + align-items: center; + margin-right: 8px; + } + + .title { + font-size: 16px; + font-weight: 600; + color: #333; + } + } + + .content { + margin-top: 12px; + + .row { + display: flex; + justify-content: space-between; + margin-top: 6px; + + .label { + font-size: 14px; + color: #666; + } + + .time { + font-size: 14px; + font-weight: 600; + color: #18a74f; // 绿色 + } + } + } + + .status { + display: flex; + align-items: center; + margin-top: 12px; + + .dot { + width: 8px; + height: 8px; + border-radius: 50%; + background-color: #18a74f; + margin-right: 6px; + } + + .text { + font-size: 12px; + color: #18a74f; + } + } + } + + .emergency-card { + background: rgba(255, 235, 238, 1); + border-radius: 16rpx; + padding: 32rpx; + margin-top: 30rpx; + gap: 30rpx; + display: flex; + align-items: flex-start; + --color: rgba(198, 40, 40, 1); + color: var(--color); + + + .icon { + width: 90rpx; + aspect-ratio: 1; + background-color: rgba(186, 26, 26, 0.15); + border-radius: 20rpx; + } + + .t-1 { + font-weight: 700; + font-size: 34rpx; + margin-bottom: 20rpx; + } + + .num { + font-weight: 700; + font-size: 40rpx; + } + + .item { + font-size: 28rpx; + line-height: 60rpx; + display: flex; + align-items: center; + gap: 20rpx; + + &::before { + content: ""; + display: block; + width: 8rpx; + height: 8rpx; + background-color: var(--color); + border-radius: 50%; + } + } + } + + .service { + background-color: white; + --color: black; + + .icon { + background-color: rgba(0, 106, 106, 0.1); + } + } + + .express { + background-color: white; + padding: 30rpx; + border-radius: 16rpx; + margin-top: 30rpx; + + .item { + gap: 30rpx; + margin-top: 40rpx; + + .icon { + width: 100rpx; + aspect-ratio: 1; + border-radius: 50%; + color: white; + font-weight: 700; + background: linear-gradient(rgba(29, 120, 116, 1), rgba(46, 139, 139, 1)); + } + + .t-1 { + font-weight: 700; + } + + .t-2 { + font-size: 28rpx; + color: rgba(69, 70, 78, 1); + } + + .t-3 { + font-size: 24rpx; + color: rgba(69, 70, 78, 1); + } + } } } \ No newline at end of file diff --git a/pages/expert/index.wxml b/pages/expert/index.wxml index 79a9a36..1de41b8 100644 --- a/pages/expert/index.wxml +++ b/pages/expert/index.wxml @@ -14,21 +14,91 @@ 可咨询次数 - 3 + {{count}} - 本月剩余 3 次免费咨询机会 + 本月剩余 {{count}} 次免费咨询机会 + icon="call-1" + bind:tap="onPlay"> 一键拨打专家电话 - - - + + + + + + 服务时间 + + + + + 工作日 + 09:00 - 21:00 + + + 周末及节假日 + 10:00 - 18:00 + + + + + + 当前服务中 + + + + + + + + + 紧急情况处理 + 如遇以下紧急情况,请立即拨打 + 120 或前往急诊 + + + 大量出血或伤口裂开 + 高热不退(体温≥39°C) + 剧烈疼痛无法缓解 + 呼吸困难或胸痛 + 意识模糊或昏迷 + + + + + + + + + + 服务说明 + + + 每次通话时长不超过15分钟 + 专家会根据您的情况提供专业建议 + 复杂问题可能需要您到院面诊 + 建议提前准备好相关检查报告 + 咨询记录会同步到您的康复档案 + + + + + + 专家团队 + + {{item.s}} + + {{item.name}} + {{item.title}} + {{item.desc}} + \ No newline at end of file diff --git a/pages/home/index.js b/pages/home/index.js index c686d29..2c9df2a 100644 --- a/pages/home/index.js +++ b/pages/home/index.js @@ -1,7 +1,15 @@ +import request from "@/utils/request" Page({ - data: { + detail: { + overview: {}, + tasks: [{}, {}, {}], + }, + loading: true, + }, + onLoad() { + this.init() }, onShow() { @@ -10,5 +18,31 @@ Page({ selected: '首页', }) }) + }, + + async init() { + let res = await request.get("/home") + this.setData({ + detail: res, + loading: false, + }) + }, + //手动标记是否完成 + handDone(e) { + const { data } = e.currentTarget.dataset; + const newTasks = this.data.detail.tasks.map(v => { + if (v.task_id == data.task_id) { + // 如果当前是 1 则变为 0,如果是 0 则变为 1 + return { ...v, is_completed: v.is_completed == 1 ? 0 : 1 }; + } + return v; + }); + request.post("/home/task-record", { + ...data, + is_completed: data.is_completed == 1 ? 0 : 1 + }) + this.setData({ + 'detail.tasks': newTasks + }); } }) \ No newline at end of file diff --git a/pages/home/index.scss b/pages/home/index.scss index 5580e62..edb13a9 100644 --- a/pages/home/index.scss +++ b/pages/home/index.scss @@ -1,5 +1,6 @@ page { background-color: rgba(247, 249, 252, 1); + padding-bottom: 160rpx; } .header { @@ -78,11 +79,15 @@ page { width: 90rpx; aspect-ratio: 1; border-radius: 20rpx; - background-color: var(--color); + background-color: var(--back); color: rgba(99, 63, 0, 1); } .content { + flex: 1; + --td-tag-default-light-color: var(--back); + --td-tag-default-font-color: var(--color); + .time { margin-left: 20rpx; color: rgba(69, 70, 78, 1); diff --git a/pages/home/index.wxml b/pages/home/index.wxml index af80c27..8a532c9 100644 --- a/pages/home/index.wxml +++ b/pages/home/index.wxml @@ -1,22 +1,25 @@ + + - 术后第 2 天 - 康复进行中 + 术后第 {{detail.overview.postoperative_day || 0}} 天 + {{detail.overview.status_text}} - 2 + {{detail.overview.postoperative_day || 0}} DAYS 今日任务完成度 - 0/5 + {{taskUtils.getDoneCount(detail.tasks)}}/{{detail.overview.total_task_count}} - @@ -25,20 +28,31 @@ - - - - - - 用药 - 08:00 + + + - 服用抗生素 - 头孢类抗生素,饭后服用 - + + + + + + {{item.category_label}} + {{item.time_label}} + + {{item.title}} + {{item.content}} + + @@ -47,4 +61,22 @@ 💡 温馨提示: 请按时完成康复任务,如有任何不适请及时联系医护人员 - \ No newline at end of file + + + + + var getDoneCount = function (tasks) { + if (!tasks || !tasks.length) return 0; + var count = 0; + for (var i = 0; i < tasks.length; i++) { + if (tasks[i].is_completed == 1 || tasks[i].is_completed === true) { + count++; + } + } + return count; + }; + + module.exports = { + getDoneCount: getDoneCount + }; + \ No newline at end of file diff --git a/pages/joinFlow/access/index.js b/pages/joinFlow/access/index.js deleted file mode 100644 index d74469b..0000000 --- a/pages/joinFlow/access/index.js +++ /dev/null @@ -1,31 +0,0 @@ -// pages/auth/access/index.js -Page({ - - data: { - - }, - - handClick(e) { - let { type } = e.currentTarget.dataset - //拍照 - if (type == 1) { - wx.scanCode({ - onlyFromCamera: true, - scanType: ['qrCode'], - success(res) { - console.log(res); - }, - fail(err) { - wx.showToast({ - title: '扫码失败', - icon: 'none' - }) - } - }) - } else { - wx.navigateTo({ - url: "/pages/joinFlow/manual/index", - }) - } - } -}) \ No newline at end of file diff --git a/pages/joinFlow/access/index.json b/pages/joinFlow/access/index.json deleted file mode 100644 index 965b8e8..0000000 --- a/pages/joinFlow/access/index.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "usingComponents": {}, - "navigationStyle": "custom" -} \ No newline at end of file diff --git a/pages/joinFlow/access/index.scss b/pages/joinFlow/access/index.scss deleted file mode 100644 index 59f969d..0000000 --- a/pages/joinFlow/access/index.scss +++ /dev/null @@ -1,80 +0,0 @@ -page { - height: 100vh; - display: flex; - flex-direction: column; -} - -.banner { - height: 400rpx; - background-image: var(--background); - padding: 30rpx; - - .text-1 { - color: white; - font-size: 60rpx; - font-weight: bold; - } - - .text-2 { - font-size: 28rpx; - color: rgba(255, 255, 255, 0.8); - } -} - -.content { - flex: 1; - background-color: white; - transform: translateY(-20rpx); - border-radius: 30rpx 30rpx 0 0; - padding: 80rpx 30rpx 30rpx; - - .text-1 { - text-align: center; - font-weight: 700; - font-size: 45rpx; - } - - .text-2 { - font-size: 28rpx; - text-align: center; - color: rgba(69, 70, 78, 1); - margin-top: 20rpx; - margin-bottom: 60rpx; - } - - .item { - box-shadow: 0 4rpx 12rpx rgba(11, 27, 61, 0.14); - padding: 30rpx; - border-radius: 30rpx; - gap: 30rpx; - margin-bottom: 60rpx; - - .icon { - width: 90rpx; - aspect-ratio: 1; - background-color: rgba(0, 106, 106, 0.1); - font-size: 50rpx; - border-radius: 20rpx; - color: rgba(46, 139, 87, 1); - } - - .t-1 { - font-weight: bold; - } - - .t-2 { - margin-top: 10rpx; - font-size: 24rpx; - color: rgba(69, 70, 78, 1); - } - } - - .tip { - background-color: rgba(255, 221, 180, 1); - padding: 30rpx; - border-radius: 20rpx; - color: rgba(99, 63, 0, 1); - font-size: 28rpx; - line-height: 44rpx; - } -} \ No newline at end of file diff --git a/pages/joinFlow/access/index.wxml b/pages/joinFlow/access/index.wxml deleted file mode 100644 index 9df19eb..0000000 --- a/pages/joinFlow/access/index.wxml +++ /dev/null @@ -1,40 +0,0 @@ - - - - 开始使用 - 请选择康复计划接入方式 - - - - - - 扫码接入 - 扫描医护人员提供的二维码 - - - - - - - - 手动选择 - 搜索医院、科室、手术名称 - - - - - 💡 温馨提示: - 首次使用需要录入基本信息,请准备好您的手术相关资料 - - \ No newline at end of file diff --git a/pages/joinFlow/manual/index.js b/pages/joinFlow/manual/index.js deleted file mode 100644 index ef2952e..0000000 --- a/pages/joinFlow/manual/index.js +++ /dev/null @@ -1,36 +0,0 @@ -Page({ - data: { - formData: { - hospital: "", - department: "" - } - }, - onInputChange(e) { - console.log("dsds"); - const {field} = e.currentTarget.dataset; - this.setData({ - [`formData.${field}`]: e.detail.value, - }); - }, - - onSubmit() { - let {formData} = this.data - let errorText = "" - if (!formData.hospital.trim()) { - errorText = "请填写医院名称" - } - if (!formData.department.trim()) { - errorText = "请填写科室名称" - } - if (errorText) { - wx.showToast({ - title: errorText, - icon: "none" - }) - return; - } - wx.navigateTo({ - url: "/pages/joinFlow/person/index" - }) - } -}) \ No newline at end of file diff --git a/pages/joinFlow/manual/index.json b/pages/joinFlow/manual/index.json deleted file mode 100644 index 965b8e8..0000000 --- a/pages/joinFlow/manual/index.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "usingComponents": {}, - "navigationStyle": "custom" -} \ No newline at end of file diff --git a/pages/joinFlow/manual/index.scss b/pages/joinFlow/manual/index.scss deleted file mode 100644 index cf0f457..0000000 --- a/pages/joinFlow/manual/index.scss +++ /dev/null @@ -1,8 +0,0 @@ -.content { - margin-top: 60rpx; - - .btn { - margin-top: 60rpx; - padding: 40rpx 30rpx; - } -} \ No newline at end of file diff --git a/pages/joinFlow/manual/index.wxml b/pages/joinFlow/manual/index.wxml deleted file mode 100644 index ae33c20..0000000 --- a/pages/joinFlow/manual/index.wxml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - 确认 - - - \ No newline at end of file diff --git a/pages/joinFlow/person/index.js b/pages/joinFlow/person/index.js index 8ceaa8c..b4ea1a1 100644 --- a/pages/joinFlow/person/index.js +++ b/pages/joinFlow/person/index.js @@ -1,21 +1,100 @@ +import request from "@/utils/request" +import { getToken, setToken } from "@/utils/auth/manageToken" +import { formatDate } from "@/utils/common" +const app = getApp() Page({ data: { + loading: true, + parmas: {}, + mood: "manual", showPicker: false, date: new Date().getTime(), + //手术 showSurgery: false, surgeryList: [], selectSurgery: [], + //医院信息 + hospital: "", + department: "", + //其他信息 age: "", allergy: "", comorbidity: "", }, + onLoad(e) { + if (Object.keys(e).length > 0) { + this.setData({ + parmas: e, + mood: "scan" + }) + } + this.init() + }, + //初始化 + async init() { + let token = getToken() + //如果存在 + if (token) { + let info = await request.get("/my-info") + this.handUser(info) + } else { + wx.login({ + success: async (res) => { + let response = await request.post("/login", { + "wx_code": res.code + }) + setToken(response.accessToken) + this.handUser(response) + }, + }) + } + }, + //处理信息 + async handUser(data) { + app.globalData.userInfo = data.userInfo + if (data.needProfile == 0) { + wx.switchTab({ + url: "/pages/home/index", + }) + } else { + let res = await request.get("/profile/surgicals") + this.setData({ + surgeryList: res.list, + }) + } + this.setData({ + loading: false, + }) + }, + onInputChange(e) { const { field } = e.currentTarget.dataset; this.setData({ [`${field}`]: e.detail.value, }); }, + //选择手术 + changeSurgeryShow() { + this.setData({ + showSurgery: !this.data.showSurgery + }) + }, + handSelectSurgery(e) { + let { data } = e.currentTarget.dataset + let { selectSurgery } = this.data + let isHave = selectSurgery.find(item => item.id == data.id) + if (isHave) { + this.setData({ + selectSurgery: selectSurgery.filter((item) => item.id != data.id) + }) + } else { + this.setData({ + selectSurgery: [...selectSurgery, data] + }) + } + }, + //选择时间 chaneTimeShow() { this.setData({ @@ -29,22 +108,26 @@ Page({ }) }, - //选择手术 - changeSurgeryShow() { - this.setData({ - showSurgery: !this.data.showSurgery - }) - }, //提交 - onSubmit() { - let { date, age, allergy, comorbidity } = this.data + async onSubmit() { + let { mood, hospital, department, date, age, allergy, comorbidity, parmas, selectSurgery } = this.data let errorText = "" - if (!date) { + if (mood == 'manual' && !hospital.trim()) { + errorText = "请输入医院" + } + else if (mood == 'manual' && !department.trim()) { + errorText = "请输入科室" + } + + else if (selectSurgery.length == 0) { + errorText = "请选择手术" + } + else if (!date) { errorText = "请选择时间" } - if (!age.trim()) { + else if (!age.trim()) { errorText = "请填写年龄" } if (errorText) { @@ -54,8 +137,29 @@ Page({ }) return } - wx.switchTab({ - url: '/pages/home/index', - }) + try { + wx.showLoading({ + title: '提交中', + mask: true + }) + await request.post("/profile", { + entry_mode: mood, + ...parmas, + hospital_name: hospital, + department_name: department, + surgical_ids: selectSurgery.map(item => item.id), + surgical_date: formatDate(date, 'YYYY-MM-DD'), + age: age, + allergy_history: allergy, + complication: comorbidity + }) + wx.hideLoading() + wx.switchTab({ + url: '/pages/home/index', + }) + } catch (e) { + console.log(e); + wx.hideLoading() + } } }) \ No newline at end of file diff --git a/pages/joinFlow/person/index.scss b/pages/joinFlow/person/index.scss index d642297..a06156e 100644 --- a/pages/joinFlow/person/index.scss +++ b/pages/joinFlow/person/index.scss @@ -1,4 +1,4 @@ -page { +.page { height: 100vh; display: flex; flex-direction: column; @@ -21,6 +21,7 @@ page { } } + .content { flex: 1; height: 0; @@ -29,6 +30,10 @@ page { border-radius: 30rpx 30rpx 0 0; padding: 50rpx 0 0; + .ce { + white-space: nowrap; + } + .text-1 { font-weight: 700; font-size: 45rpx; diff --git a/pages/joinFlow/person/index.wxml b/pages/joinFlow/person/index.wxml index d782bec..4df3c2b 100644 --- a/pages/joinFlow/person/index.wxml +++ b/pages/joinFlow/person/index.wxml @@ -1,55 +1,84 @@ -