diff --git a/src/api/base.js b/src/api/base.js index 2c772532d118d86d352e66251da415715f1a31df..69ae4731564ba748769c8e97cab7b2a34c8af779 100644 --- a/src/api/base.js +++ b/src/api/base.js @@ -41,12 +41,14 @@ export function fileUpload(params) { return fetchBase({ url: `/chronic-admin/v1/pictures-info/qiniu`, body: params, contentType: 'file' }) } -// 获取模板管理数据 +// 获取字典管理数据 export function getTemplateList() { return fetchBase({ url: `/tumour-admin/v1/h5-app/dict`, loading: true }) } -//模板数据主键查询 +//字典数据主键查询 export function getTemplateById() { return fetchBase({ url: `/tumour-admin/v1/h5-app/dict`, loading: true }) -} \ No newline at end of file +} + + diff --git a/src/api/doctor/generalFU.js b/src/api/doctor/generalFU.js index 67dba26578a0a70e2663764669608cc3d0934bd6..d1a2ae0c90e67c194e50561e2ab4f9323c15f54e 100644 --- a/src/api/doctor/generalFU.js +++ b/src/api/doctor/generalFU.js @@ -28,6 +28,12 @@ export function getUnitByName(orgName) { return fetchBase({ url: `/tumour-admin/v1/sys-user/org-by-name/${orgName}` }) } +// 拼音码查询药品信息 +export function getDrug(code) { + return fetchBase({ url: `/tumour-admin/v1/remote-system/drugs/${code}` }) +} + + // 根据单位id查询科室 export function getOfficeList(unitId) { return fetchBase({ url: `/tumour-admin/v1/sys-user/org-office/${unitId}` }) diff --git a/src/api/doctor/workbench.js b/src/api/doctor/workbench.js index 30dd156ab75dfaef9a0d06ea2b7f2c344675c725..e8f2860a4f842906972b9124e0480c0d72d76e89 100644 --- a/src/api/doctor/workbench.js +++ b/src/api/doctor/workbench.js @@ -15,6 +15,16 @@ export function delVisit(params) { return fetchBase({ url: `/chronic-admin/v1/chronic-visit-task/delete`, body: params, loading: true }) } +// 模板 分页查询 +export function getTemplateByPage(params) { + return fetchBase({ url: `/tumour-admin/v1/template/page`, body: params, loading: true }) +} + +// 模板 主键查询 +export function getTemplateDetail(params, loading = true) { + return fetchBase({ url: `/tumour-admin/v1/template/query-id/${params.id}`, loading }) +} + // 待接诊列表 export function getReceiveByPage(params) { return fetchBase({ url: `/chronic-admin/v1/chronic-referral-task/page`, body: params }) diff --git a/src/doctor/components/docDrug/DocDrug.vue b/src/doctor/components/docDrug/DocDrug.vue new file mode 100644 index 0000000000000000000000000000000000000000..d745ac755d9fbb80b45af0aecd08ac2479eeba44 --- /dev/null +++ b/src/doctor/components/docDrug/DocDrug.vue @@ -0,0 +1,137 @@ +<template> + <div> + <van-field + v-model='innerValueName' + readonly + is-link + label='药品名称:' + placeholder='请选择' + class='input-back mt-2 form-input w-full' + @click='showDrug= true' + /> + <van-popup v-model:show='showDrug' position='bottom'> + <div class='pb-4 pr-4 pl-4'> + <van-picker + :columns='array' + :columns-field-names='fieldNames' + @confirm='drugConfirm' + @cancel='showDrug = false' + > + <template #columns-top> + <van-search v-model="searchStr" :placeholder='placeholder' @search='onSearch' clearable/> + </template> + </van-picker> + </div> + </van-popup> + </div> +</template> + +<script> + + +import { getDrug } from '@/api/doctor/generalFU' +import { debounce } from '@/utils/common' + +export default { + name: 'DocDrug', + props: { + value: [String, Number], + valueName: String, + placeholder: String, + fieldNames: { + type: Object, + default: () => { + return { text: 'chemicalName', value: 'id' } + } + } + }, + emits: ['update:value', 'change'], + data() { + return { + innerValue: null, + innerValueName: undefined, + array: [], + loading: false, + showDrug: false, + searchStr: '' + } + }, + created() { + this.onSearch = debounce(this.onSearch, 500) + this.onSearch('') + }, + methods: { + onSearch(value) { + if (this.loading) return + this.array = [] + if (!value) { + return + } + if (!value.trim()) return + this.loading = true + getDrug(value).then(res => { + this.array = res.data || [] + if (this.array.length && this.innerValue) { + let list = this.array.filter(item => item.id == this.innerValue) + if (list && list.length) { + this.innerValueName = list[0].chemicalName + } + } + }).finally(() => { + this.loading = false + }) + }, + drugConfirm({ selectedOptions }) { + this.innerValueName = selectedOptions[0].chemicalName + this.$emit('update:value', selectedOptions[0].id) + this.$emit('change', selectedOptions[0]) + this.searchStr = '' + this.showDrug = false + } + }, + watch: { + value: { + handler(value) { + this.innerValue = value + }, + immediate: true + }, + valueName: { + handler(value) { + if (!value) { + return + } + this.onSearch(value) + }, + immediate: true + }, + searchStr: { + handler(val) { + if (!val) return + this.onSearch(val) + } + } + } +} +</script> + +<style lang='less' scoped> +.form-input { + padding: 8px 12px; + border-radius: 8px; +} + +.input-back { + background: #FAFAFA; +} + +//灰色 +.greyColor { + color: var(--van-text-color-2); +} + +//确认按钮颜色 +.blueColor { + color: var(--van-primary-color) +} +</style> diff --git a/src/doctor/components/template/temDetail.vue b/src/doctor/components/template/temDetail.vue index 1cb011ad26fb58e2365bed47eb1ada8bf6c900d6..33195f4e4e0bec8654cfa12e2667b4776e3fa391 100644 --- a/src/doctor/components/template/temDetail.vue +++ b/src/doctor/components/template/temDetail.vue @@ -1,13 +1,143 @@ <template> + <van-popup v-model:show='innerShow' position='right' :style="{ height: '100%', width: '100%' }"> + <div class='flex flex-col' style='height: 100vh'> + <div class='p-3 text-black text-center shrink-0 doc-nav-bar'> + <span @click='onBack' class='text-12 back-bt'> + <doc-icon type='doc-left2' /> + </span> + <span>查看内容</span> + </div> + <div class='grow overflow-y-auto pl-4 pr-4 pt-3 pb-3'> + <div> + <div class='flex flex-col '> + <!-- 文本 --> + <div class='card' v-if='contentList?.length'> + <div class='font-semibold mb-1'>文本</div> + <div class='conten-bg'> + <div v-for='item in contentList' :key='item.templateMode' class='mb-1 flex' + :style='`order: ${item.templateMode}`'> + <span class='shrink-0 mr-1' + v-if="item.templateModeTrans != '无'">{{ item.templateModeTrans }} :</span> + <span> {{ item.templateContent }}</span> + </div> + </div> + </div> + </div> + <div class='card mt-4' v-if='mp4List?.length'> + <div class='font-semibold mb-1'>视频</div> + <div class='conten-bg'> + <Mp4 :files='mp4List' :activeMediaUrl='activeMediaUrl' + @play='e => activeMediaUrl = e.annexUrl' /> + </div> + </div> + + <div class='card flex flex-col mt-4' style='row-gap: .06rem;' v-if='mp3List?.length'> + <div class='font-semibold mb-1'>音频</div> + <div class='conten-bg'> + <Mp3 :file='item' v-for='item in mp3List' :key='item.annexId' + :activeMediaUrl='activeMediaUrl' + @play='e => activeMediaUrl = e.annexUrl' /> + </div> + </div> + </div> + </div> + + <div class='bbtn'> + <van-button type='primary' @click='toUse'>引用</van-button> + </div> + </div> + </van-popup> </template> <script> +import { showToast } from 'vant' +import { getTemplateDetail } from '@/api/doctor/workbench' +import Mp3 from '@/doctor/components/mediaPlay/Mp3.vue' +import Mp4 from '@/doctor/components/mediaPlay/Mp4.vue' + export default { - name: 'temDetail' + name: 'temDetail', + components: { Mp4, Mp3 }, + props: { + show: { default: false }, + id: String + }, + data() { + return { + info: {}, + activeMediaUrl: '' + } + }, + computed: { + innerShow() { + return this.show + }, + contentList() { + return this.info.contentList + }, + // 文件内容 + annexList() { + return this.info?.annexList || [] + }, + mp3List() { + return this.annexList.filter(e => e.type == 2) + }, + mp4List() { + return this.annexList.filter(e => e.type == 3) + } + }, + created() { + this.load() + }, + methods: { + async load() { + if (!this.id) { + showToast('未获取到信息') + return + } + let par = { + id: this.id + } + getTemplateDetail(par).then(res => { + let result = res.data || {} + this.info = result + }).finally(() => { + }) + }, + toUse() { + this.$emit('selectedInfo', this.id) + this.onBack() + }, + onBack() { + this.$emit('closeDetail', false) + } + } } </script> -<style scoped> +<style scoped lang='less'> +@import url('../../utils/common.less'); +.bbtn { + padding: 8px 12px; + border-top: 1px solid #D7D8DA; + + button { + width: 100%; + border-radius: 100px + } +} + +.card { + border: 1px solid #CFD5DE; + padding: 8px; + border-radius: 8px; + color: #262626; +} +.conten-bg { + background: #F8FAFC; + padding: 6px 10px; + border-radius: 4px; +} </style> \ No newline at end of file diff --git a/src/doctor/components/template/temList.vue b/src/doctor/components/template/temList.vue index 3d4f084527327e6a9ec797aa3858336a101b7db2..de02216010dff1087f0337d044c04c5ac821ef45 100644 --- a/src/doctor/components/template/temList.vue +++ b/src/doctor/components/template/temList.vue @@ -1,20 +1,255 @@ <template> - <van-popup v-model:show="show" position="right" :style="{ height: '100%' }" > - <div>1111111</div> + <van-popup v-model:show='innerShow' position='right' :style="{ height: '100%', width: '100%' }" :overlay='false' > + <div class='bg flex flex-col'> + <div class='p-3 flex items-center shrink-0 justify-between title bg-white'> + <div @click='onBack' class='text-12 back-bt'> + <doc-icon type='doc-left2' /> + </div> + <div>随访详情</div> + <div class='text-primary left-btn' @click='openSearch'>筛查</div> + </div> + + <div class='grow p-10 overflow-y-auto' ref='list'> + <van-pull-refresh v-model='loadingRefresh' @refresh='onRefresh' + :disabled='isRefreshDisable' style='min-height: 100%'> + <van-list + v-model:loading='loading' + :finished='finished' + :finished-text="list.length ? '没有更多了' : ''" + :immediate-check='false' + @load='onMore' + > + <div class='flex flex-col gap-y-2.5'> + <div class='py-3 px-4 doc-list-card' v-for='item in list' :key='item.id'> + <div class='flex flex-col gap-y-2.5'> + <div> + <span class='label'>模板分类</span> + <span>{{ item.templateClassifyTrans }}</span> + </div> + <div> + <span class='label'>模板名称</span> + <span>{{ item.templateName }}</span> + </div> + </div> + <div class='divider my-3'></div> + <div class='bt-group'> + <van-button round size='small' class='doc-btn-primary mr-3' + @click='toDetail(item)'>查看 + </van-button> + <van-button round size='small' class='doc-btn-primary' @click='toUse(item)'> + 引用 + </van-button> + </div> + </div> + </div> + </van-list> + <div class='text-center shrink-0 empty' v-if='!list.length'> + <img src='@/assets/image/doctor/empty.png' alt='' style='width: 1.2rem;'> + <p>暂无数据</p> + </div> + </van-pull-refresh> + + <van-popup v-model:show='searchVisible' position='top' :style="{ height: '60%' }" + style='position: absolute;transition: none' + :overlay-style="{ position: 'absolute' }" + transition='viewer-fade' + :teleport='listDom'> + <div class='h-full flex flex-col workbench-search-box'> + <div class='px-4 py-3 grow overflow-y-auto' style=''> + <van-field v-model='form.templateName' placeholder='请输入要查询的模板名称' maxlength='100' + class='doc-input' /> + <div class='my-3'>模板分类</div> + <CheckBtn :options="store.getDict('DC00082')" v-model:value='form.templateClassify' column-3 + class='check-btn-workbench' /> + <div class='my-3'>文件类型</div> + <CheckBtn :options="store.getDict('DC00093')" v-model:value='form.fileType' column-3 + class='check-btn-workbench' /> + + <div class='my-3'>共享类型</div> + <CheckBtn :options="store.getDict('DC00053')" v-model:value='form.templateType' column-3 + class='check-btn-workbench' /> + </div> + <div class='text-16 flex shrink-0 text-center bt-group'> + <div class='grow py-3' @click='reset'>重置</div> + <div class='grow py-3 submit-btn' @click='search'>确定</div> + </div> + </div> + </van-popup> + + <!-- 查看详情组件--> + <temDetail v-if='detailShow' :show='detailShow' :id='selectRecord.id' @closeDetail='detailClosed' @selectedInfo='detailToUse' :overlay='false'></temDetail> + </div> + </div> </van-popup> </template> <script> +import { showToast } from 'vant' +import CheckBtn from '@/doctor/components/checkBtn/CheckBtn' +import { getTemplateByPage } from '@/api/doctor/workbench' +import { useStore } from '@/doctor/store' +import TemDetail from '@/doctor/components/template/temDetail' + +const DefaultForm = { + templateName: undefined, + templateClassify: undefined, + //慢病 + businessType: 1, + //文件类型 + fileType: undefined, + //共享类型 + templateType: 1 +} + export default { name: 'temList', + components: { TemDetail, CheckBtn }, + props: { + show: { default: false } + }, data() { return { - show: false + store: useStore(), + list: [], + pagination: { + total: 0, + pageIndex: 1, + pageSize: 8 + }, + loading: false, + finished: false, + loadingRefresh: false, + isRefreshDisable: false, + // 搜索弹出框 + searchVisible: false, + form: { ...DefaultForm }, + //是否展示详情弹窗 + detailShow: false, + //选中项 + selectRecord: {} + } + }, + computed: { + innerShow() { + return this.show + }, + listDom() { + return this.$refs.list + } + }, + created() { + this.load() + }, + mounted() { + const list = this.$refs.list + if (list) { + list.addEventListener('scroll', () => { + if (list.scrollTop > 0) { + this.isRefreshDisable = true + } else { + this.isRefreshDisable = false + } + }) + } + }, + methods: { + load(loading = true) { + const query = { + pageIndex: this.pagination.pageIndex, + pageSize: this.pagination.pageSize, + ...this.form + } + getTemplateByPage(query, loading).then(res => { + if (this.pagination.pageIndex === 1) { + this.list = [] + } + this.list = this.list.concat(res.data.dataList || []) + this.pagination.total = res.data.total || 0 + this.finished = this.list.length >= this.pagination.total + }).finally(() => { + this.loading = false + this.loadingRefresh = false + }) + }, + search() { + this.pagination.pageIndex = 1 + this.load() + this.searchVisible = false + }, + reset() { + this.form = { ...DefaultForm } + this.search() + }, + onMore() { + this.pagination.pageIndex++ + this.load(false) + }, + onRefresh() { + this.pagination.pageIndex = 1 + this.load() + }, + openSearch() { + this.searchVisible = true + }, + toDetail(record) { + this.selectRecord = record + this.detailShow = true + }, + detailClosed(val) { + this.detailShow = val + }, + //列表引用 + toUse(record) { + this.$emit('selectRecord', record.id) + this.onBack() + }, + //详情选中引用 + detailToUse(val) { + this.$emit('selectRecord', val) + this.onBack() + }, + onBack() { + this.$emit('closed', false) } } } </script> -<style scoped> +<style scoped lang='less'> +.title { + font-size: 18px; + font-weight: 600; +} + +.bg-white { + background: #FFFFFF; +} + +.left-btn { + font-size: 14px; + font-weight: 400; +} + +.bg { + background: rgb(245, 245, 245); + height: 100vh; +} + +.p-10 { + padding: 10px; +} + +:deep(.workbench-search-box) { + color: #595959; + + .bt-group { + border-top: 1px solid #EBEBEC; + color: #262626; + .submit-btn { + color: #fff; + background-color: var(--van-primary-color); + } + } +} </style> \ No newline at end of file diff --git a/src/doctor/followUp/generalFU/detail/Detail.vue b/src/doctor/followUp/generalFU/detail/Detail.vue index 4326587d28c6241c9fe562c63c0ef795aa01d597..1d9cd3041d79b8f5419465275a5f4ac5dc768b0c 100644 --- a/src/doctor/followUp/generalFU/detail/Detail.vue +++ b/src/doctor/followUp/generalFU/detail/Detail.vue @@ -244,6 +244,7 @@ import Mp3 from '@/residentWX/components/mediaPlay/Mp3.vue' import Mp4 from '@/residentWX/components/mediaPlay/Mp4' import ImagePreview from '@/residentWX/components/imagePreview/imagePreview' import { fetchCurrencyById, messageResend } from '@/api/doctor/generalFU' +import { getTemplateDetail } from '@/api/doctor/workbench' export default { name: 'CurrencyFUDetail.vue', @@ -364,7 +365,6 @@ export default { }, methods: { async load() { - debugger if (!this.routerDetail.relationId) { showToast('未获取到信息') return diff --git a/src/doctor/followUp/generalFU/form/BaseInfo.vue b/src/doctor/followUp/generalFU/form/BaseInfo.vue index 8f630e804e47cef02bb9643899b53258172d71d4..06d6d6f7636673f536b3ade152580e4bb3e52351 100644 --- a/src/doctor/followUp/generalFU/form/BaseInfo.vue +++ b/src/doctor/followUp/generalFU/form/BaseInfo.vue @@ -191,7 +191,11 @@ class='input-back mt-2 form-input' :rules='rules.groupsArraysName' @click='showGroupsArrays= true' - /> + > + <template #input> + <span class='text-end'>{{form.groupsArraysName}}</span> + </template> + </van-field> <van-popup v-model:show='showGroupsArrays' position='bottom'> <div class='p-4'> <div class='flex justify-between mb-4'> diff --git a/src/doctor/followUp/generalFU/form/GeneralFUForm.vue b/src/doctor/followUp/generalFU/form/GeneralFUForm.vue index 614486a2c52915e509629d766eea9a9733fef41c..5bdc290c601fb3867495dd6152b41a4413582909 100644 --- a/src/doctor/followUp/generalFU/form/GeneralFUForm.vue +++ b/src/doctor/followUp/generalFU/form/GeneralFUForm.vue @@ -25,33 +25,37 @@ class='input-back mt-2 form-input' /> </div> +<!-- 健康指导--> <div v-if='showTwo'> - <div class='flex justify-between items-center'> - <div class='label-title mt-5'>健康指导</div> - <van-button class='doc-btn-primary'>选择内容</van-button> + <div class='flex justify-between items-center mt-5'> + <div class='label-title '>健康指导</div> + <van-button class='doc-btn-p' @click='toShowTem(1)'>选择内容</van-button> </div> - <div class='health mt-2'> - <div class='health-cell mt-2' v-for='item in form.visitHealthGuideList'> - <div class='no-req-label' v-if="item.name != '无'">{{ item.name }}</div> - <van-field - v-model='item.templateContent' - rows='1' - autosize - type='textarea' - placeholder='请输入' - class='input-back mt-2 form-input' - /> - </div> + <div class='mt-2'> + <GuideTextVideo :file-type="[1]" + :info="form.guide" + :content-title="'指导内容'" + :classify="1" + ref="guideRef"></GuideTextVideo> + </div> + </div> +<!-- 宣教内容--> + <div v-if='showThree'> + <div class='flex justify-between items-center mt-5'> + <div class='label-title '>宣教内容</div> + <van-button class='doc-btn-p' @click='toShowTem(2)'>选择内容</van-button> </div> </div> + <!-- 催检--> <div v-if='showFour'> <div class='no-req-label mt-5'>催检内容</div> <div class='tel-back mt-2'> <div class='tel'> <div style='text-indent: 2em;line-height: .2rem'> - <span v-if='modeEnumList.urgeResidentShow'>{{ firstForm.residentsRecord.residentName }}先生/女士,</span> + <span v-if='modeEnumList.urgeResidentShow'>{{ firstForm.residentsRecord.residentName + }}先生/女士,</span> <span v-else>您好,</span> <span>请您于{{ form.screenTime }}</span> <span>到{{ authInfo.unitName }}</span> @@ -64,33 +68,33 @@ </div> </div> <van-popup v-model:show='showTime1' position='bottom'> - <van-date-picker v-model='currentTime1' @confirm='timeConfirm1' @cancel='showTime1 = false' /> + <van-date-picker v-model='currentTime1' @confirm='timeConfirm1' @cancel='showTime1 = false' /> </van-popup> </div> -<!-- 上传随访照片--> + <!-- 上传随访照片--> <div v-if='showOne'> <div class='no-req-label mt-5'>上传随访记录</div> - <DocImageUpload - description="支持上传jpg、png、jpeg文件,大小请在10M以内" - lengthMessage="抱歉,最多可上传6个文件。" - :imageData="[]" - @change="(ids, option) => form.uploadVisitRecord = ids" - :maxLength="6" - class="mt-2" - /> + <DocImageUpload + description='支持上传jpg、png、jpeg文件,大小请在10M以内' + lengthMessage='抱歉,最多可上传6个文件。' + :imageData='[]' + @change='(ids, option) => form.uploadVisitRecord = ids' + :maxLength='6' + class='mt-2' + /> </div> -<!-- 现场随访照片--> + <!-- 现场随访照片--> <div> <div class='no-req-label mt-5'>现场随访照片</div> <DocImageUpload - description="支持上传jpg、png、jpeg文件,大小请在10M以内" - lengthMessage="抱歉,最多可上传6个文件。" - :imageData="[]" - @change="(ids, option) => form.sceneVisitImage = ids" - :maxLength="6" - class="mt-2" + description='支持上传jpg、png、jpeg文件,大小请在10M以内' + lengthMessage='抱歉,最多可上传6个文件。' + :imageData='[]' + @change='(ids, option) => form.sceneVisitImage = ids' + :maxLength='6' + class='mt-2' /> </div> @@ -114,6 +118,10 @@ </van-popup> </div> </van-form> + + <div> + <temList :show='showTem' @closed='closedTem' @selectRecord='getSelectTem'></temList> + </div> </div> </template> @@ -124,10 +132,13 @@ import DocIcon from '@/components/docIcon/DocIcon' import { showToast } from 'vant' import { fetchDataHandle } from '@/utils/common' import DocImageUpload from '@/doctor/components/docImageUpload/DocImageUpload' +import TemList from '@/doctor/components/template/temList' +import { getTemplateDetail } from '@/api/doctor/workbench' +import GuideTextVideo from '@/doctor/followUp/generalFU/form/GuideTextVideo' export default { name: 'GeneralFUForm', - components: { DocImageUpload, DocIcon }, + components: { GuideTextVideo, TemList, DocImageUpload, DocIcon }, props: { info: { default: () => { @@ -149,17 +160,11 @@ export default { return { store: useStore(), form: {}, - //展示用 - imgList: [], - imgList2: [], - //input图片值 - imgInputList1: [], - imgInputList2: [], showDate: false, showTime1: false, + showTem: false, currentTime1: null, - showImgList: [], - initSwipe: 0, + citeInfo: 1, rules: { visitContent: [{ required: true, message: '请输入' }], nextVisitDate: [{ required: true, message: '请选择' }] @@ -222,7 +227,7 @@ export default { res = true } return res - }, + } }, created() { const date = dayjs() @@ -243,7 +248,7 @@ export default { id: info.id, diseaseType: info.diseaseType, visitDate: info.visitDate || new dayjs(), - nextVisitDate: info.nextVisitDate || new dayjs().add(1, 'day').format('YYYY-MM-DD'), + nextVisitDate: info.nextVisitDate || new dayjs().add(1, 'day').format('YYYY-MM-DD'), isSms: info.isSms, isWx: info.isWx, screenTime: new dayjs().add(1, 'day').format('YYYY-MM-DD'), @@ -274,6 +279,26 @@ export default { this.form.screenTime = selectedValues.join('-') this.showTime1 = false }, + toShowTem(val) { + this.citeInfo =val + this.showTem = true + }, + closedTem(val) { + this.showTem = val + }, + //获取选中的模板 + async getSelectTem(val) { + if (val) { + let par = { id: val } + let result = await getTemplateDetail(par) + //健康指导 + if (this.citeInfo == 1) { + + } else { //宣教内容 + + } + } + }, onSubmit() { return new Promise((resolve, reject) => { this.$refs.form.validate().then(() => { @@ -303,6 +328,21 @@ export default { </script> <style scoped lang='less'> +// 按钮样式 +.doc-btn { + border: 0; + padding: 4px 8px; + height: 26px; + border-radius: 38px; +} + +.doc-btn-p { + .doc-btn(); + color: var(--van-primary-color); + background: #F0F3FF; + font-size: 13px; +} + .title { font-weight: bold; margin-bottom: 20px; diff --git a/src/doctor/followUp/generalFU/form/GuideTextVideo.vue b/src/doctor/followUp/generalFU/form/GuideTextVideo.vue new file mode 100644 index 0000000000000000000000000000000000000000..d1b4f995b35e4ae061233b587dfd39d51422809c --- /dev/null +++ b/src/doctor/followUp/generalFU/form/GuideTextVideo.vue @@ -0,0 +1,579 @@ +<template> + <van-form ref='form' + class='grow flex flex-col' style='min-height: 1px;flex-wrap: nowrap;'> + <div class='flex flex-col' v-if='fileType?.includes(1)'> + + <div class='health mt-2'> + <!-- 无选项--> + <div class='health-cell mt-2' v-for="item in form.contentList.filter(e => e.templateModeTrans == '无')"> + <div class='no-req-label'>{{ contentTitle }}</div> + <van-field + v-model='item.templateContent' + rows='1' + autosize + type='textarea' + placeholder='请输入' + class='input-back mt-2 form-input' + /> + </div> + <!-- 更多选项--> + <div class='health-cell mt-2'> + <div class='no-req-label'>更多{{ contentTitle }}</div> + <van-field + v-model='form.contentSelectName' + readonly + is-link + placeholder='请选择' + class='input-back mt-2 form-input' + :rules='rules.contentSelectName' + @click='showContentSelect= true' + > + <template #input> + <span class='text-end'>{{ form.contentSelectName }}</span> + </template> + </van-field> + <van-popup v-model:show='showContentSelect' position='bottom'> + <div class='p-4'> + <div class='flex justify-between mb-4'> + <div class='greyColor' @click='showContentSelect = false'>取消</div> + <div class='blueColor' @click='contentSelectConfirm'>确认</div> + </div> + <CheckBtn multiple column-2 :options='contentArray' v-model:value='checkContentSelect' + :fieldNames="{text: 'name', value: 'value'}" /> + </div> + </van-popup> + </div> + + <div class='health-cell mt-2' v-for="item in form.contentList.filter(e => e.templateModeTrans != '无')"> + <template v-if='item.templateMode === 5'> + <div class='no-req-label'>药物指导</div> + <div v-for='(item, index) in form.drugsList' :key='item._id' :style="{marginTop: index == 0 ? '0': '.16rem'}"> + <div class='text-driver' v-if='index'></div> + <DocDrug v-model:value='item.drugsCode' placeholder='拼音码查询药品' + :valueName="selectData.drugsList ? selectData.drugsList[index]?.helpCode : ''" + @change='drugChange($event, item)' /> + <div class='flex items-center justify-between w-full mt-2'> + <van-field + v-model='item.dose' + placeholder='输入' + label='剂量:' + type='digit' + class='input-back form-input' + style='flex: 1' + /> + <van-field + v-model='item.doseUnitName' + readonly + placeholder='请选择' + class='input-back ml-2 form-input' + style='width: .8rem' + @click='showDoseUnit= true' + /> + </div> + <van-popup v-model:show='showDoseUnit' position='bottom'> + <div class='p-4'> + <van-picker + :columns-field-names="{ text: 'name', value: 'value' }" + :columns="store.getDict('CP00081')" + @confirm='doseUnitConfirm($event, item)' + @cancel='showDoseUnit = false' + /> + </div> + </van-popup> + <van-field + v-model='item.frequencyName' + readonly + is-link + label='频次:' + placeholder='请选择' + class='input-back mt-2 form-input' + @click='showFrequency= true' + /> + <van-popup v-model:show='showFrequency' position='bottom'> + <div class='p-4'> + <van-picker + :columns-field-names="{ text: 'name', value: 'value' }" + :columns="store.getDict('CP00084')" + @confirm='frequencyConfirm($event, item)' + @cancel='showFrequency = false' + /> + </div> + </van-popup> + <van-field + v-model='item.usageMethodName' + readonly + is-link + label='用法:' + placeholder='请选择' + class='input-back mt-2 form-input' + @click='showUsageMethod= true' + /> + <van-popup v-model:show='showUsageMethod' position='bottom'> + <div class='p-4'> + <van-picker + :columns-field-names="{ text: 'name', value: 'value' }" + :columns="store.getDict('CP00083')" + @confirm='usageMethodConfirm($event, item)' + @cancel='showUsageMethod = false' + /> + </div> + </van-popup> + + <div class='mt-2 text-center'> + <van-button type='primary' plain class='btn-br' @click='addDrug'>增加</van-button> + <van-button plain class='btn-br' + @click='minusDrug(item, index)' + v-if='form?.drugsList?.length > 1' + style='margin-left: .16rem' + >删除 + </van-button> + </div> + </div> + </template> + + <div class='no-req-label' v-if='item.templateMode != 5'>{{ item.templateModeTrans }}</div> + <van-field + v-model='item.templateContent' + v-if='item.templateMode != 5' + rows='1' + autosize + type='textarea' + placeholder='请输入' + class='input-back mt-2 form-input' + /> + </div> + </div> + </div> + <div v-if='fileType.includes(2)' class='w-full'> + <div class='health-cell mt-2'> + <div class='no-req-label'>音频</div> + <Mp3 :file='item' v-for='item in _audio' :key='item.annexId' + :activeMediaUrl='activeMediaUrl' + @play='e => activeMediaUrl = e.annexUrl' + remove + @onRemove='getMP3RemoveInfo' + /> + </div> + </div> + <div v-if='fileType.includes(3)' class='w-full'> + <Mp4 :files='_video' :activeMediaUrl='activeMediaUrl' + @play='e => activeMediaUrl = e.annexUrl' + remove + @onRemove='getMP4RemoveInfo' + /> + </div> + + </van-form> +</template> + +<script> +import { fetchDataHandle } from '@/utils/common' +import { useStore } from '@/doctor/store' +import DocDrug from '@/doctor/components/docDrug/DocDrug' +import Mp3 from '@/doctor/components/mediaPlay/Mp3.vue' +import Mp4 from '@/doctor/components/mediaPlay/Mp4' +import CheckBtn from '@/doctor/components/checkBtn/CheckBtn' + +export default { + name: 'GuideTextVideo', + components: { CheckBtn, Mp4, Mp3, DocDrug }, + props: { + info: { + default: () => { + return {} + } + }, + //内容标题 + contentTitle: { + default: () => { + return '宣教内容' + } + }, + // 文件类型 1:文本 2、文字播报 3、视频 + fileType: Array, + // 分类 + classify: Number + }, + data() { + return { + store: useStore(), + //更多指导内容 + showContentSelect: false, + checkContentSelect: [], + //药物剂量 + showDoseUnit: false, + //药物频次 + showFrequency: false, + //药物用法 + showUsageMethod: false, + form: {}, + selectData: {}, + activeMediaUrl: '', + rules: {} + } + }, + computed: { + contentArray() { + let res = [] + res = this.store.getDict('DC00084').filter(item => item.value != 1) + return res + }, + // 音频、视频 回显使用 + _video() { + const annexList = this.selectData.annexList || [] + return annexList.filter(e => e.type === 3).map(e => { + return { + annexFileName: e.annexFileName, + trueDownloadUrl: e.annexUrl, + annexUrl: e.annexUrl, + relativeUrl: e.relativeUrl, + fileType: 'mp4', + md5Hash: e.annexMd5, + id: e.annexId + } + }) + }, + _audio() { + const annexList = this.selectData.annexList || [] + return annexList.filter(e => e.type === 2).map(e => { + return { + annexFileName: e.annexFileName, + trueDownloadUrl: e.annexUrl, + annexUrl: e.annexUrl, + relativeUrl: e.relativeUrl, + fileType: 'mp3', + md5Hash: e.annexMd5, + id: e.annexId + } + }) + } + }, + watch: { + 'info': { + handler() { + if (this.info) { + this.selectData = fetchDataHandle(this.info || {}, { + templateType: 'strToArrNum', + fileType: 'strToArrNum' + }) + const annexList = this.selectData.annexList || [] + this.selectData._video = annexList.filter(e => e.type === 3) + this.selectData._audio = annexList.filter(e => e.type === 2) + this.form = this.setTemForm(this.selectData) + } else { + this.form = this.setTemForm({}) + } + }, + immediate: true + }, + 'form.contentSelectName': { + handler() { + this.contentSelectChange() + } + } + }, + methods: { + //指导和宣教赋值 + setTemForm(info = {}) { + let contentList = [] + let initC = [ + { + templateContent: '', + templateId: '', + templateMode: 1, + templateModeTrans: '无' + } + ] + let infoC = info.contentList || [] + //判断父组件的数据里是否存在 无 的选项 + let resList = infoC.filter(item => item.templateMode !=1) + if (!resList.length) { + contentList = [...initC, ...infoC] + } else { + contentList = [...infoC] + } + const drugsList = info?.drugsList?.length ? info.drugsList.map(e => { + if (e.id) { + e._id = e.id + } + return e + }) : [] + const form = { + id: info.id, + templateType: info.templateType, + templateName: info.templateName, + templateMode: info.templateMode || 1, + fileType: info.fileType || [1], + templateClassify: info.templateClassify || 1, + businessType: info.businessType || 1, + contentList: JSON.parse(JSON.stringify(contentList)), + contentSelect: contentList.map(e => e.templateMode), + drugsList: JSON.parse(JSON.stringify(drugsList)), + annexList: info.annexList || [], + // 存放上传后返回的id + _video: JSON.parse(JSON.stringify(info._video || [])), + _audio: JSON.parse(JSON.stringify(info._audio || [])), + drugSelect: 1 + } + return form + }, + // 选择的模板内容变化 + contentSelectChange() { + const cont = this.form.contentList || [] + const addValue = this.checkContentSelect.filter(e => !cont.find(i => i.templateMode === e)) + if (addValue.length) { + addValue.forEach(e => { + this.form.contentList.push({ + templateMode: e, + templateModeTrans: this.store.getDictValue('DC00084', e), + templateContent: undefined, + id: undefined + }) + }) + // 药物指导处理 + if (addValue.includes(5)) { + this.addDrug() + } + } + }, + // 添加药品 + addDrug() { + this.form.drugsList.push(this.drugItem()) + }, + drugItem() { + let rowId = 0 + if (this.form.drugsList.length > 0) { + rowId = Math.max.apply(null, this.form.drugsList.map(item => Number(item._id))) + } + return { + _id: rowId + 1, + // 药品名称 + drugsName: undefined, + drugsCode: undefined, + // 剂量单位,[CP00081] + doseUnit: 1, + // 每次剂量 + dose: undefined, + // 频次,[CP00084] + frequency: undefined, + // 用法,[CP00083] + usageMethod: undefined, + // 每日几次 + // dayTime: undefined, + helpCode: undefined + } + }, + drugChange(option, item) { + item.drugsName = option.chemicalName + item.helpCode = option.helpCode + }, + minusDrug(item, index) { + this.form.drugsList = this.form.drugsList.filter(e => e._id !== item._id) + }, + getRef() { + return this.$refs.form + }, + contentSelectConfirm() { + let res = [] + this.contentArray.forEach(item => { + let selected = this.checkContentSelect.filter(i => i == item.value) + if (selected && selected.length) { + res.push(item.name) + } + }) + if (this.checkContentSelect && this.checkContentSelect.length) { + this.form.contentSelect = this.checkContentSelect.join() + this.form.contentSelectName = res.join() + } + this.showContentSelect = false + }, + doseUnitConfirm({ selectedValues, selectedOptions }, item) { + item.doseUnit = selectedValues[0] + item.doseUnitName = selectedOptions[0].name + this.showDoseUnit = false + }, + frequencyConfirm({ selectedValues, selectedOptions }, item) { + item.frequency = selectedValues[0] + item.frequencyName = selectedOptions[0].name + this.showFrequency = false + }, + usageMethodConfirm({ selectedValues, selectedOptions }, item) { + item.usageMethod = selectedValues[0] + item.usageMethodName = selectedOptions[0].name + this.showUsageMethod = false + }, + //删除MP3 + getMP3RemoveInfo(val) { + this.selectData.annexList.forEach((item, index) => { + if (item.relativeUrl == val.relativeUrl) { + this.selectData.annexList.splice(index, 1) + } + }) + }, + //删除MP4 + getMP4RemoveInfo(val) { + this.selectData.annexList.forEach((item, index) => { + if (item.relativeUrl == val.relativeUrl) { + this.selectData.annexList.splice(index, 1) + } + }) + }, + submit() { + return new Promise((resolve, reject) => { + this.$refs.form.validate().then(valid => { + /* if (this.form.fileType.includes(3) && !this.form._video.length) { + this.$message.info('请上传视频') + return + } + if (this.form.fileType.includes(2) && !this.form._audio.length) { + this.$message.info('请上传音频') + return + }*/ + const query = fetchDataHandle({ ...this.form }, { + templateType: 'arrToStr', + fileType: 'arrToStr' + }) + const annexList = [] + this._video.forEach(e => { + annexList.push({ + type: 3, + annexId: e.annexId, + relativeUrl: e.relativeUrl, + annexFileName: e.annexFileName + }) + }) + this._audio.forEach(e => { + annexList.push({ + type: 2, + annexId: e.annexId, + relativeUrl: e.relativeUrl, + annexFileName: e.annexFileName + }) + }) + query.annexList = annexList + const contentList = query.contentList + const item = contentList.find(e => e.templateMode == 5) + if (item) { + const drugsList = query.drugsList + let str = '' + drugsList.forEach(e => { + str = `药品名:${e.drugsName} 剂量:${e.dose} ${this.$dictValue('CP00081', e.doseUnit)} 频次:${this.$dictValue('CP00084', e.frequency)} 用法:${this.$dictValue('CP00083', e.usageMethod)}\n` + str + }) + item.templateContent = str + } + resolve(query) + }).catch(e => { + reject(e) + }) + }) + }, + getForm() { + return new Promise((resolve, reject) => { + const query = fetchDataHandle({ ...this.form }, { + templateType: 'arrToStr', + fileType: 'arrToStr' + }) + const annexList = [] + this._video.forEach(e => { + annexList.push({ + type: 3, + annexId: e.annexId, + annexUrl: e.annexUrl, + relativeUrl: e.relativeUrl, + annexFileName: e.annexFileName + }) + }) + this._audio.forEach(e => { + annexList.push({ + type: 2, + annexId: e.annexId, + annexUrl: e.annexUrl, + relativeUrl: e.relativeUrl, + annexFileName: e.annexFileName + }) + }) + query.annexList = annexList + const contentList = query.contentList + const item = contentList.find(e => e.templateMode == 5) + if (item) { + const drugsList = query.drugsList + let str = '' + drugsList.forEach(e => { + str = `药品名:${e.drugsName} 剂量:${e.dose} ${this.$dictValue('CP00081', e.doseUnit)} 频次:${this.$dictValue('CP00084', e.frequency)} 用法:${this.$dictValue('CP00083', e.usageMethod)}\n` + str + }) + item.templateContent = str + } + resolve(query) + }) + } + } +} +</script> + +<style lang='less' scoped> + +.action-box { + width: 56px; + font-size: 20px; + + .svg-icon { + vertical-align: baseline; + } +} + +.drug-list { + background-color: #F5F5F5; +} + + +.health { + padding: 1px 8px 8px 8px; + background: #FAFAFA; + border-radius: 8px; + + .health-cell { + padding: 8px; + background: #FFFFFF; + border-radius: 8px; + } +} + +.no-req-label { + font-size: 13px; + color: #595959; + font-weight: 500; +} + +.form-input { + padding: 8px 12px; + border-radius: 8px; +} + +.input-back { + background: #FAFAFA; +} + +.text-driver { + border: 1px solid #EEEEEE; + margin-bottom: 8px; + margin-top: 8px; +} + +.btn-br { + border-radius: 38px; + width: 112px; + padding: 4px 8px; + height: 26px; + font-size: 13px; +} + +//灰色 +.greyColor { + color: var(--van-text-color-2); +} + +//确认按钮颜色 +.blueColor { + color: var(--van-primary-color) +} +</style> \ No newline at end of file