Commit c345acd0 authored by Lowry's avatar Lowry

Merge branch 'chronic-master' of…

Merge branch 'chronic-master' of http://gitlab.yiboshi.com/nightkis1995/frontend-h5 into chronic-master
parents b78c8d16 953c1652
import { fetchBase } from '../fetch.js'
// 根据居民ID查询服务医生
export function getServiceDoc(params) {
return fetchBase({ url: `/chronic-resident/v1/chronic-visit-record/service-doctor`, body: params, loading: true })
}
// 获取IM账号信息
export function getAccount(idCard) {
return fetchBase({ url: `/chronic-resident/v1/chronic-resident-im/refresh-token/${idCard}`, loading: true })
}
<svg viewBox="64 64 896 896" focusable="false"><path d="M854.6 288.7c6 6 9.4 14.1 9.4 22.6V928c0 17.7-14.3 32-32 32H192c-17.7 0-32-14.3-32-32V96c0-17.7 14.3-32 32-32h424.7c8.5 0 16.7 3.4 22.7 9.4l215.2 215.3zM790.2 326L602 137.8V326h188.2z" /></svg>
\ No newline at end of file
<svg viewBox="64 64 896 896" focusable="false"><path d="M696 480H544V328c0-4.4-3.6-8-8-8h-48c-4.4 0-8 3.6-8 8v152H328c-4.4 0-8 3.6-8 8v48c0 4.4 3.6 8 8 8h152v152c0 4.4 3.6 8 8 8h48c4.4 0 8-3.6 8-8V544h152c4.4 0 8-3.6 8-8v-48c0-4.4-3.6-8-8-8z" /><path d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm0 820c-205.4 0-372-166.6-372-372s166.6-372 372-372 372 166.6 372 372-166.6 372-372 372z" /></svg>
\ No newline at end of file
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
import 'vant/es/toast/style/index' import 'vant/es/toast/style/index'
import 'vant/es/notify/style/index' import 'vant/es/notify/style/index'
import 'vant/es/dialog/style/index' import 'vant/es/dialog/style/index'
import 'vant/es/image-preview/style/index'
// 自定义svg 图标组件 // 自定义svg 图标组件
import DocIcon from '@/components/docIcon/index' import DocIcon from '@/components/docIcon/index'
......
<template>
<div class="file-view">
<!-- 文件预览 -->
<div v-if="!isImage" class="flex items-center">
<doc-icon type="file-filled" style="color: #999; font-size: 20px"/>
<a class="ml-2" @click.prevent="onDown">下载</a>
</div>
<van-image :src="file.url" v-else @click="viewImage">
<template v-slot:loading>
<van-loading type="spinner" size="20" />
</template>
</van-image>
</div>
</template>
<script>
export default {
props: {
file: {
type: Object,
default: () => ({})
}
},
emits: ['view-image'],
computed: {
isImage() {
const array = ['JPG', 'PNG', 'JEPG', 'GIF']
return array.includes(this.file.type) || array.includes(this.file.ext.toLocaleUpperCase())
}
},
methods: {
onDown() {
window.open(this.file.url, '_blank')
},
viewImage() {
this.$emit('view-image', this.file)
}
}
}
</script>
<style lang="less" scoped>
.file-view {
width: 100px;
}
</style>
<template>
<div class="flex flex-col nim-index" style="height: 100vh">
<div class="py-2 px-3 text-black text-center shrink-0 doc-nav-bar">
<span>专家在线咨询</span>
</div>
<img src="@/assets/image/residentWX/banner.png" alt="" class="shrink-0 w-full">
<div style="color: #8C8C8C;" class="py-2 px-3">以下为您提供慢病筛查的专家,可向其进行慢病咨询</div>
<div class="grow flex">
<div class="h-full list-l">
<div class="p-3 active">
咨询过的专家
</div>
<div v-for="item in orgList" :key="item.unitId"
:class="['p-3', { 'active': item.unitId === activeOrg.unitId }]"
@click="onOrgChange(item)">
<span>{{ item.unitName || '-' }}</span>
</div>
</div>
<div class="h-full p-3 list-r">
<div class="mb-3 p-4 card" v-for="item in innerDoctorList" :key="item.identityCard">
<div class="mb-3">
<span class="text-16 mr-2 font-semibold">{{item.staffName}}</span>
<span>{{item.officeName || '-'}}</span>
</div>
<div class="mb-3">{{item.unitName || '-'}}</div>
<div>
<van-button plain round type="primary"
@click="toSession(item)">咨询医生</van-button>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import { useStore } from '@/residentWX/store'
import { getServiceDoc } from '@/api/residentWX/nim.js'
import { showFailToast } from 'vant'
export default {
data() {
return {
store: useStore(),
orgList: [],
doctorList: [],
activeOrg: {}
}
},
computed: {
userInfo() {
return this.store.userInfo
},
innerDoctorList() {
return this.doctorList.filter(e => e.unitId === this.activeOrg.unitId)
}
},
created() {
this.init()
},
methods: {
init() {
console.log(this.userInfo)
this.load()
},
load() {
getServiceDoc({ residentInfoId: this.userInfo.residentInfoId }).then(res => {
const list = res.data || []
const orgList = []
this.doctorList = list
list.forEach(e => {
if (orgList.some(e => e.unitId === e.unitId)) return
orgList.push({
unitId: e.unitId,
unitName: e.unitName
})
})
this.orgList = orgList
if (orgList.length) {
this.activeOrg = orgList[0]
}
})
},
onOrgChange(item) {
this.activeOrg = item || {}
},
// 聊天页面
toSession(item = {}) {
if (!item.identityCard) {
showFailToast('缺失医生信息')
return
}
const path = `/residentWX/nim/${item.identityCard}`
this.$router.push({
path,
query: {
name: item.staffName
}
})
}
},
}
</script>
<style lang="less" scoped>
@import url('../utils/common.less');
.nim-index {
background: #f8fafc;
}
.list-l {
width: 35%;
background: transparent;
>div {
line-height: 1.5;
}
.active {
background-color: #fff;
}
}
.list-r {
width: 65%;
background: #fff;
.card {
background-color: #E4E8EE;
background: linear-gradient(to bottom, #E5F3FF 0%, #E9FAFC 100%);
border-radius: 8px;
border: 1px solid #E4E8EE;
.van-button {
height: 26px;
line-height: 26px;
font-size: 14px;
}
}
}
</style>
<template> <template>
<div class="flex flex-col session" style="height: 100vh"> <div class="flex flex-col session" style="height: 100vh">
<div class="py-2 px-3 text-black text-center shrink-0 head"> <div class="py-2 px-3 text-black text-center shrink-0 doc-nav-bar">
<span @click="onBack" class="text-12 back-bt"> <span @click="onBack" class="text-12 back-bt">
<doc-icon type="doc-left2" /> <doc-icon type="doc-left2" />
</span> </span>
<span>{{ targetId }}</span> <span>{{ targetName }}</span>
</div> </div>
<div class="p-3 grow overflow-y-auto content"> <div class="p-3 grow overflow-y-auto content">
<van-list <van-list
v-model:loading="loading" v-model:loading="loading"
:finished="finished" :finished="finished"
finished-text="没有更多了" finished-text="没有更多消息了"
direction="up" direction="up"
:disabled="scrollDisabled" :disabled="scrollDisabled"
@load="loadHistory" @load="loadHistory"
...@@ -18,39 +18,75 @@ ...@@ -18,39 +18,75 @@
<div v-for="item in msgs" :key="item.time" <div v-for="item in msgs" :key="item.time"
:class="['flex msg-row', item.from === accountId ? 'self' : 'target']"> :class="['flex msg-row', item.from === accountId ? 'self' : 'target']">
<div class="shrink-0 avatar"> <div class="shrink-0 avatar">
<img src="@/assets/image/nim/avatar-doctor.svg" alt="" v-show="item.from !== accountId"> <img src="@/assets/image/residentWX/avatar-doctor.svg" alt="" v-show="item.from !== accountId">
</div>
<div class="msg-cont">
<span v-if="item.type === 'text'">{{ item.text }}</span>
<FileView v-else-if="['image', 'file'].includes(item.type)" :file="item.file"
@viewImage="viewImage"/>
</div> </div>
<div class="msg-cont">{{ item.text }}</div>
<div class="shrink-0 avatar"> <div class="shrink-0 avatar">
<img src="@/assets/image/nim/avatar-man.png" alt="" v-show="item.from === accountId"> <img src="@/assets/image/residentWX/avatar-man.png" alt="" v-show="item.from === accountId">
</div> </div>
</div> </div>
</van-list> </van-list>
<div ref="bottom"></div> <div ref="bottom"></div>
</div> </div>
<div class="shrink-0 px-3 py-2 footer"> <div class="shrink-0 px-3 py-2 footer">
<van-cell-group> <van-field type="textarea" rows="1"
<van-field :autosize="{ minHeight: 24, maxHeight: 76 }"
maxlength="500"
v-model="inputValue" v-model="inputValue"
center center
> >
<template #left-icon>
<div style="color: #555; font-size: .2rem" class="mr-1"
@click="() => visible = true">
<doc-icon type="plus-circle"/>
</div>
</template>
<template #button> <template #button>
<van-button size="small" type="primary" <van-button size="small" type="primary"
@click="sendMsg">发送</van-button> @click="sendMsg">发送</van-button>
</template> </template>
</van-field> </van-field>
</van-cell-group>
</div> </div>
<input type="file"
:accept="sendType == 'image' ? '.jpg,.jpeg,.png,.gif' : '*'"
ref="fileElem"
style="display: none;"
@change="handleFiles"
:key="inputKey">
<van-action-sheet
v-model:show="visible"
:actions="actionsList"
cancel-text="取消"
close-on-click-action
@select="fileSelect"
/>
</div> </div>
</template> </template>
<script> <script>
import { useStore } from '@/residentWX/store'
import NIM from '@yxim/nim-web-sdk/dist/SDK/NIM_Web_NIM.js' import NIM from '@yxim/nim-web-sdk/dist/SDK/NIM_Web_NIM.js'
import { showNotify, showToast } from 'vant' import { showNotify, showToast, showImagePreview, showSuccessToast, showFailToast } from 'vant'
import { getAccount } from '@/api/residentWX/nim.js'
import FileView from './FileView.vue'
// 6c51376a55f54b2fa586d7b4c85757f8
const APPKEY = '8cee1ccf8ab46779976091db68a67955'
export default { export default {
components: {
FileView
},
data() { data() {
return { return {
store: useStore(),
accountId: '',
token: '',
msgs: [], msgs: [],
nim: null, nim: null,
// 输入的信息 // 输入的信息
...@@ -62,15 +98,27 @@ export default { ...@@ -62,15 +98,27 @@ export default {
// 是否加载完成 // 是否加载完成
finished: false, finished: false,
scrollDisabled: true, scrollDisabled: true,
// image file
sendType: 'image',
inputKey: 1,
// 上传功能面板
visible: false,
actionsList: [
{ name: '上传图片', type: 'image' },
{ name: '上传文件', type: 'file' }
]
} }
}, },
computed: { computed: {
accountId() { userInfo() {
return this.$route.query.accountId return this.store.userInfo
}, },
// 聊天对象 // 聊天对象
targetName() {
return this.$route.query.name
},
targetId() { targetId() {
return this.accountId === '18487350810' ? '18987175004' : '18487350810' return `doc_${this.$route.params.id}`.toLocaleLowerCase()
} }
}, },
created() { created() {
...@@ -78,13 +126,27 @@ export default { ...@@ -78,13 +126,27 @@ export default {
}, },
methods: { methods: {
init() { init() {
getAccount(this.userInfo.idCard).then(res => {
console.log('getAccount ===========>', res)
const result = res.data || {}
this.accountId = result.accountId
this.token = result.yunxinToken
this.connect()
})
},
// 连接到im服务
connect() {
if (!this.accountId || !this.token) {
showNotify({ type: 'warning', message: '聊天服务连接失败', duration: 0 })
return
}
this.isConnect = false this.isConnect = false
this.finished = false this.finished = false
this.nim = NIM.getInstance({ this.nim = NIM.getInstance({
debug: true, debug: false,
appKey: '6c51376a55f54b2fa586d7b4c85757f8', appKey: APPKEY,
account: this.accountId, account: this.accountId,
token: '123456', token: this.token,
onconnect: () => { onconnect: () => {
console.log('连接成功 ================>') console.log('连接成功 ================>')
this.isConnect = true this.isConnect = true
...@@ -101,12 +163,18 @@ export default { ...@@ -101,12 +163,18 @@ export default {
console.log(obj.duration) console.log(obj.duration)
}, },
ondisconnect: (error) => { ondisconnect: (error) => {
showNotify({ type: 'warning', message: '连接失败', duration: 0 }) // showNotify({ type: 'warning', message: '连接失败', duration: 0 })
console.warn('连接失败 ===============>')
}, },
onmsg: (msg) => { onmsg: (msg) => {
console.log('收到新消息===========>', msg); console.log('收到新消息===========>', msg);
this.msgs.push(msg) this.msgs.push(msg)
this.toBottom() this.toBottom()
},
onofflinemsgs: (obj) => {
console.log('收到离线消息===========>', obj);
this.msgs.push(...obj.msgs)
this.toBottom()
} }
}) })
}, },
...@@ -116,6 +184,7 @@ export default { ...@@ -116,6 +184,7 @@ export default {
showToast('不能发送空消息') showToast('不能发送空消息')
return return
} }
if (!this.nim) return
let msg = this.nim.sendText({ let msg = this.nim.sendText({
scene: 'p2p', scene: 'p2p',
to: this.targetId, to: this.targetId,
...@@ -124,18 +193,18 @@ export default { ...@@ -124,18 +193,18 @@ export default {
console.log('sendText ================>', error, msg) console.log('sendText ================>', error, msg)
} }
}) })
this.msgs.push(msg) this.pushMsg(msg)
this.inputValue = '' this.inputValue = ''
this.toBottom()
}, },
pushMsg(msg) { pushMsg(msg) {
this.msgs.push(msg) this.msgs.push(msg)
this.toBottom()
}, },
toBottom(behavior = 'smooth') { toBottom(behavior = 'smooth') {
const dom = this.$refs.bottom const dom = this.$refs.bottom
setTimeout(() => { setTimeout(() => {
dom && dom.scrollIntoView({block: 'start', behavior}) dom && dom.scrollIntoView({block: 'start', behavior})
}, 100) }, 300)
}, },
// 加载本地消息 // 加载本地消息
getLocalMsgs() { getLocalMsgs() {
...@@ -163,24 +232,136 @@ export default { ...@@ -163,24 +232,136 @@ export default {
loadHistory() { loadHistory() {
this.getLocalMsgs() this.getLocalMsgs()
}, },
onBack() { handleFiles() {
let files = this.$refs['fileElem'].files
if (files.length <= 0) {
this.$message.info('未选中文件,请尝试重新选择')
return
}
if (files[0].size / 1024 / 1024 > 100) {
this.$message.info('文件大小不能超过100M')
return
}
this.upload(files[0])
},
upload(file, hash) {
if (!this.nim) return
// 先上传再发送
const tempMsg = {
from: this.accountId,
text: '上传中...',
time: +new Date(),
percentage: 0,
type: 'text'
}
this.pushMsg(tempMsg)
this.nim.previewFile({
type: this.sendType,
blob: file,
// fastPass: { md5: hash },
uploadprogress: function(obj) {
console.log('文件总大小: ' + obj.total + 'bytes');
console.log('已经上传的大小: ' + obj.loaded + 'bytes');
console.log('上传进度: ' + obj.percentage);
console.log('上传进度文本: ' + obj.percentageText);
tempMsg.percentage = obj.percentage
},
done: (error, file) => {
this.inputKey = Math.random().toString(16).substring(2, 6)
if (!error) {
const msg = this.nim.sendFile({
scene: 'p2p',
to: this.targetId,
file: file
})
console.log('正在发送p2p image消息, id=' + msg.idClient)
this.pushMsg(msg)
this.msgs = this.msgs.filter(e => e.time !== tempMsg.time)
} else {
const msg = this.nim.sendText({
scene: 'p2p',
to: this.targetId,
text: '文件上传失败!',
isLocal: true,
custom: { type: 'file', status: 'fail' }
})
this.pushMsg(msg)
}
}
})
},
fileSelect(action) {
this.sendType = action.type
const dom = this.$refs['fileElem']
setTimeout(() => {
dom && dom.click()
}, 100)
},
// 图片查看
viewImage(file) {
const currt = file.url
const tempList = this.msgs.filter(e => ['file', 'image'].includes(e.type)).map(e => e.file)
const imageList = []
tempList.forEach(e => {
const array = ['JPG', 'PNG', 'JEPG', 'GIF']
if (array.includes(e.type) || array.includes(e.ext.toLocaleUpperCase())) {
imageList.push(e.url)
}
})
console.log('imageList', imageList)
const index = imageList.indexOf(currt) || 0
showImagePreview({
images: imageList,
startPosition: index,
closeable: true
})
},
clearMsg() {
this.nim.deleteLocalMsgsBySession({
scene: 'p2p',
to: this.targetId,
delLastMsg: true,
done: (error) => {
if (error) {
showFailToast('删除失败')
} else {
showSuccessToast('删除成功')
}
}
});
},
clearAllMsg() {
this.nim.deleteAllLocalMsgs({
done: (error) => {
if (error) {
showFailToast('删除失败')
} else {
showSuccessToast('删除成功')
} }
} }
})
},
onBack() {
this.$router.replace({ name: 'residentWX-nim' })
}
},
beforeUnmount() {
if (this.nim) {
this.nim.destroy({
done: function (err) {
console.log('nim 断开连接')
}
})
}
}
} }
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
.head { @import url('../utils/common.less');
position: relative;
border-bottom: 1px solid #3C3C435C;
.back-bt {
position: absolute;
left: .16rem;
top: 50%;
transform: translateY(-50%);
}
}
.footer { .footer {
border-top: 1px solid #3C3C431C; border-top: 1px solid #3C3C431C;
background-color: #eeeeee66; background-color: #eeeeee66;
......
...@@ -130,17 +130,17 @@ const routes = [ ...@@ -130,17 +130,17 @@ const routes = [
name: 'residentWX-guide-list', name: 'residentWX-guide-list',
component: () => import(/* webpackChunkName: "residentWX-guide" */ '@/residentWX/guide/List.vue') component: () => import(/* webpackChunkName: "residentWX-guide" */ '@/residentWX/guide/List.vue')
}, },
]
},
{ {
path: '/nim', path: 'nim',
name: 'nim', name: 'residentWX-nim',
component: () => import(/* webpackChunkName: "nim" */ '@/nim/Session.vue'), component: () => import(/* webpackChunkName: "nim" */ '@/residentWX/nim/Index.vue'),
}, },
{ {
path: '/nimTest', path: 'nim/:id',
name: 'nimTest', name: 'residentWX-nim-session',
component: () => import(/* webpackChunkName: "nim" */ '@/nim/Test.vue'), component: () => import(/* webpackChunkName: "nim" */ '@/residentWX/nim/Session.vue'),
}
]
} }
] ]
......
...@@ -39,7 +39,7 @@ module.exports = defineConfig({ ...@@ -39,7 +39,7 @@ module.exports = defineConfig({
} }
}, },
'/chronic-resident': { '/chronic-resident': {
target: 'http://192.168.1.174:8903', target: 'http://192.168.1.145:8903',
// target: 'https://beta-tumour.zmnyjk.com', // target: 'https://beta-tumour.zmnyjk.com',
changOrigin: true, changOrigin: true,
pathRewrite: { pathRewrite: {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment