diff --git a/src/assets/icons/doctor/close-circle.svg b/src/assets/icons/doctor/close-circle.svg new file mode 100644 index 0000000000000000000000000000000000000000..33556908c8b142d55664513b2d76bc952d96f513 --- /dev/null +++ b/src/assets/icons/doctor/close-circle.svg @@ -0,0 +1,5 @@ +<svg width="17" height="17" viewBox="0 0 17 17" fill="none" xmlns="http://www.w3.org/2000/svg"> +<circle opacity="0.8" cx="8.8335" cy="8.68945" r="8" fill="#1F1F1F"/> +<path d="M6.16699 6.02295L11.5003 11.3563" stroke="white" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/> +<path d="M11.5005 6.02295L6.16715 11.3563" stroke="white" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/> +</svg> diff --git a/src/assets/icons/doctor/doc-upload.svg b/src/assets/icons/doctor/doc-upload.svg index f0ad5cec9a202979e96be2914d90c3e5767b0fb6..fddd35cf0657de26792553bc71cbdc6d38c01177 100644 --- a/src/assets/icons/doctor/doc-upload.svg +++ b/src/assets/icons/doctor/doc-upload.svg @@ -1,4 +1,4 @@ -<svg width="20" height="21" viewBox="0 0 20 21" fill="none" xmlns="http://www.w3.org/2000/svg"> -<path d="M7.75993 17.1936C5.98659 17.33 2.35807 16.7844 2.03068 13.5105C1.70329 10.2367 4.07684 9.1454 5.30454 9.00898C5.44085 7.23564 6.69562 3.68896 10.6243 3.68896C14.5529 3.68896 15.2622 7.23564 15.1258 9.00898C16.4899 9.41822 19.0544 10.9733 18.3997 13.9198C17.7449 16.8662 14.3073 17.33 12.6704 17.1936" stroke="#607FF0" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="bevel"/> -<path d="M7.72949 12.692L10.1849 10.2366M10.1849 10.2366L12.6403 12.692M10.1849 10.2366V17.1935" stroke="#607FF0" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"/> +<svg width="19" height="17" viewBox="0 0 19 17" fill="none" xmlns="http://www.w3.org/2000/svg"> +<path d="M6.75993 15.1941C4.98659 15.3305 1.35807 14.7849 1.03068 11.511C0.703294 8.23717 3.07684 7.14588 4.30454 7.00947C4.44085 5.23613 5.69562 1.68945 9.62425 1.68945C13.5529 1.68945 14.2622 5.23613 14.1258 7.00947C15.4899 7.41871 18.0544 8.97379 17.3997 11.9203C16.7449 14.8667 13.3073 15.3305 11.6704 15.1941" stroke="#607FF0" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="bevel"/> +<path d="M6.72949 10.6927L9.18489 8.2373M9.18489 8.2373L11.6403 10.6927M9.18489 8.2373V15.1943" stroke="#607FF0" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"/> </svg> diff --git a/src/doctor/components/checkBtn/CheckBtn.vue b/src/doctor/components/checkBtn/CheckBtn.vue index fce1f6056f23f4446787074f39f4f727e436229a..2cdb363f9931c28ce7e6f9efc780654ef50f7043 100644 --- a/src/doctor/components/checkBtn/CheckBtn.vue +++ b/src/doctor/components/checkBtn/CheckBtn.vue @@ -1,6 +1,12 @@ <template> - <div class="check-btn"> - + <div class="flex flex-wrap check-btn"> + <div v-for="item in options" :key="item[fieldNames.value]" + @click="onClick(item)" + :class="['py-2 px-3 shrink-0 check-btn-item', + { 'check-btn-item-active': isSelect(item) }, + { 'check-btn-item-disabled': isDisabled(item) }]"> + {{ item[fieldNames.text] }} + </div> </div> </template> @@ -8,11 +14,97 @@ export default { name: 'CheckBtn', props:{ + value: [String, Number, Array], + // 选项 + options: { default: () =>[] }, + fieldNames: { + type: Object, + default: () => { + return {text: 'name', value: 'code'} + } + }, + // 是否多选 + multiple: Boolean + }, + emits: ['update:value', 'change'], + data() { + return { + innerValue: undefined + } + }, + created() { + this.init() + }, + methods: { + init() { + this.innerValue = this.value + if (this.multiple) { + if (this.value != null && !Array.isArray(this.value)) { + console.warn('CheckBtn: multiple must be Array type') + } + this.innerValue = this.innerValue || [] + } + }, + onClick(item){ + if (this.isDisabled(item)) { + return + } + if (this.multiple) { + if (this.innerValue.includes(item[this.fieldNames.value])) { + this.innerValue = this.innerValue.filter(e => e !== item[this.fieldNames.value]) + } else { + this.innerValue.push(item[this.fieldNames.value]) + } + } else { + this.innerValue = item[this.fieldNames.value] + } + this.$emit('update:value', this.innerValue) + this.$emit('change', this.innerValue, item) + }, + // 是否选中 + isSelect(item){ + if (this.multiple) { + return this.innerValue.includes(item[this.fieldNames.value]) + } else { + return item[this.fieldNames.value] === this.innerValue + } + }, + isDisabled(item){ + return item.disabled + } + }, + watch: { + value: { + handler(value) { + this.innerValue = value + }, + immediate: true + }, } } </script> <style lang="less" scoped> - +.check-btn { + row-gap: 10px; + column-gap: 10px; +} +.check-btn-item { + border: 1px solid transparent; + background-color: #FAFAFA; + border-radius: 8px; + transition: all .2s; +} +.check-btn-item-active { + border: 1px solid var(--van-primary-color); + background-color: #F0F6FF; + color: var(--van-primary-color); +} +.check-btn-item-disabled { + background-color: #F0F6FF; + color: var(--van-primary-color); + // opacity: 0.5; + filter: grayscale(1); +} </style> diff --git a/src/doctor/components/docImageUpload/DocImageUpload.vue b/src/doctor/components/docImageUpload/DocImageUpload.vue new file mode 100644 index 0000000000000000000000000000000000000000..24a2738484b4e512506d7eb1fed1daa4d826cbd8 --- /dev/null +++ b/src/doctor/components/docImageUpload/DocImageUpload.vue @@ -0,0 +1,172 @@ +<template> + <div class="doc-image-upload"> + <div class="text-12 description">{{ description }}</div> + <div class="mt-2 py-3 text-center upload-btn" @click="fileSelect"> + <doc-icon type="doc-upload" class="mr-2 text-16"/> + <span>{{ btText }}</span> + </div> + <div class="flex flex-wrap justify-between mt-4 image-box"> + <div v-for="item in innerImage" :key="item.id"> + <div v-if="item.fileType === 'pdf'" class=""> + <doc-icon type="doc-PDF" /> + </div> + <div v-else> + <img src="@/assets/image/doctor/empty.png" style="width: 100%"/> + </div> + <span class="close-btn" @click="removeImage(item)"> + <doc-icon type="close-circle" /> + </span> + </div> + </div> + <input type="file" + accept=".jpg,.jpeg,.png,.pdf" + ref="fileElem" + style="display: none;" + @change="handleFiles" + :key="inputKey"> + </div> +</template> + +<script> +import { showToast } from 'vant' + +export default { + name: 'DocImageUpload', + props: { + // 上传描述 + description: { default: '温馨提示:请上传JPG、PNG格式图片,文件大小不超过5M' }, + // 传入的img数据 { id, trueDownloadUrl } + imageData: { default: () => [] }, + // 上传按键的文字 + btText: { default: '上传图片' }, + // 图片框大小 + size: String, + // 上传最大数量 + maxLength: { default: 1 }, + lengthMessage: { default: '已达到图片上限,请移除后再上传' } + }, + data() { + return { + // 内部图片对象 + innerImage: [], + file: null, + spinning: false, + inputKey: '1', + // viewer显示 + visible: false + } + }, + computed: { + fileElem() { + return this.$refs['fileElem'] + }, + ids() { + return this.innerImage.map(e => e.id).join(',') + } + }, + methods:{ + init() { + if (this.imageData?.length) { + this.innerImage = [...this.imageData] + } else { + this.innerImage = [ + { fileType: 'pdf', id: 1 }, + { fileType: 'png', id: 2 }, + { fileType: 'png', id: 3 } + ] + } + }, + fileSelect() { + console.log(this.innerImage, this.maxLength) + if (this.innerImage?.length >= this.maxLength) { + showToast(this.lengthMessage) + return + } + const dom = this.$refs['fileElem'] + if (dom) { + dom.click() + } + }, + upload() { + let formData = new FormData() + formData.append('file', this.file) + this.spinning = true + fileUpload(formData).then(res => { + // this.$message.success('上传成功') + let result = res.data || {} + this.$emit('upload', result) + this.addImage(result) + this.inputKey = Math.random().toString(16).substring(2, 6) + this.$emit('change', this.ids, this.innerImage) + this.formItemContext.onFieldChange() + }).finally(() => { + this.spinning = false + }) + }, + handleFiles() { + let files = this.$refs['fileElem'].files + if (files.length <= 0) { + showToast('未选中文件,请尝试重新选择') + return + } + if (files[0].size / 1024 / 1024 > 5) { + showToast('图片大小不能超过5M') + return + } + this.file = files[0] + this.upload() + }, + addImage(data = {}) { + if (!data.id) { + console.warn('addImage 文件为空') + return + } + if (!this.innerImage.find(e => e.id === data.id)) { + this.innerImage.push(data) + } + }, + removeImage(item) { + if (!item) return + this.innerImage = this.innerImage.filter(e => e.id != item.id) + this.$emit('change', this.ids, this.innerImage) + } + }, + watch: { + imageData: { + handler(value) { + this.init() + }, + immediate: true + } + } +} +</script> + +<style lang="less" scoped> +.description { + color: #A5AEBE; +} +.upload-btn { + color: var(--van-primary-color); + border: 1px solid #eee; + background-color: #FAFAFA; + border-radius: 8px; +} +.image-box { + >div { + width: calc(33.3vw - 8px); + position: relative; + border: 1px solid #999; + border-radius: 2px; + img { + object-fit: contain; + } + } + .close-btn { + position: absolute; + font-size: 16px; + top: -8px; + right: -8px; + } +} +</style> diff --git a/src/test/Index.vue b/src/test/Index.vue index c5ee885e0a8e0f61d5acebd4e0310a0f3318bed5..98c13d0bb923d74e17c15c7b5f25b5805b1e39ca 100644 --- a/src/test/Index.vue +++ b/src/test/Index.vue @@ -6,22 +6,42 @@ <span class="ml-2">{{unitData.value}}</span> </div> <DocUnit v-model:show="unitData.visible" v-model:value="unitData.value"/> + <div class="flex items-center"> + <h4>多选/单选按键</h4> + <span>{{ checkData }}</span> + </div> + <CheckBtn :options="checkOptions" v-model:value="checkData"/> + + <h4>upload</h4> + <DocImageUpload /> </div> </template> <script> import DocUnit from '@/doctor/components/docUnit/DocUnit.vue' +import CheckBtn from '@/doctor/components/checkBtn/CheckBtn.vue' +import DocImageUpload from '@/doctor/components/docImageUpload/DocImageUpload.vue' export default { components:{ - DocUnit + DocUnit, + CheckBtn, + DocImageUpload }, data(){ return { unitData: { visible: false, value: undefined - } + }, + checkData: undefined, + checkOptions: [ + { name: '血常规', code: 1, disabled: true }, + { name: '尿常规', code: 2 }, + { name: '肝功能', code: 3 }, + { name: '肾功能', code: 4 }, + { name: '电解质', code: 5 } + ] } }, created() {