This commit is contained in:
zoujiandong 2025-07-10 10:07:20 +08:00
parent 3265d590bd
commit bbe721f610
10 changed files with 791 additions and 11 deletions

4
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,4 @@
{
"javascript.inlayHints.variableTypes.enabled": true,
"typescript.validate.enable": false
}

View File

@ -5,7 +5,7 @@
* @Date: 2024-01-11 15:18:32
* @Copyright gdxz
*/
import { postRequest, getRequest, download,uploadRequest } from '/@/lib/axios';
import { postRequest, getRequest, download,uploadRequest,putRequest} from '/@/lib/axios';
export const caseplatformCaseApi = {
@ -30,6 +30,22 @@ export const caseplatformCaseApi = {
return postRequest('/caseplatformCase/update', param);
},
updateMainDiagnose: (param) => {
return putRequest('/caseplatformCase/mainDiagnose', param);
},
updateDpmas: (param) => {
return putRequest('/caseplatformCase/dpmasImg', param);
},
updateCheck: (param) => {
return putRequest('/caseplatformCase/checkdataImg', param);
},
getOssSign:(type)=>{ //获取上传文件 Policy
return getRequest('/file/getOSSPolicy/'+type)
},
ossUpload:(url,data)=>{
return uploadRequest(url,data);
},
/**
* 详情 @author HMM
*/

View File

@ -96,6 +96,14 @@ export const postRequest = (url, data) => {
return request({ data, url, method: 'post' });
};
/**
* put请求
*/
export const putRequest = (url, data) => {
return request({ data, url, method: 'put' });
};
/**
* get请求
*/

91
src/utils/fileutil.js Normal file
View File

@ -0,0 +1,91 @@
const FileUtil = {
//file 为微信file 单文件
getFileName(file){
// size: 132224
// thumb: "http://tmp/0ftStiYfd18K517836423bbfde024c385140a666b344.png"
// type: "image"
// url: "http://tmp/0ftStiYfd18K517836423bbfde024c385140a666b344.png"
if(file){
const uuid = this.UUID().replace("/-/g","");
if(file.url && (file.url.indexOf(".") > -1)){
const fileType = file.url.split(".")[1];
return uuid+"."+fileType;
}else{
return;
}
}
return;
},
UUID () {
if (typeof crypto === 'object') {
if (typeof crypto.randomUUID === 'function') {
return crypto.randomUUID();
}
if (typeof crypto.getRandomValues === 'function' && typeof Uint8Array === 'function') {
const callback = (c) => {
const num = Number(c);
return (num ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (num / 4)))).toString(16);
};
return ([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g, callback);
}
}
let timestamp = new Date().getTime();
let perforNow = (typeof performance !== 'undefined' && performance.now && performance.now() * 1000) || 0;
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
let random = Math.random() * 16;
if (timestamp > 0) {
random = (timestamp + random) % 16 | 0;
timestamp = Math.floor(timestamp / 16);
} else {
random = (perforNow + random) % 16 | 0;
perforNow = Math.floor(perforNow / 16);
}
return (c === 'x' ? random : (random & 0x3) | 0x8).toString(16);
});
},
canvasToFile(){
let canvas = window.map3DControl.viewer.canvas;
let imgWidth = 1920;
let img = Canvas2Image.convertToImage(
canvas,
imgWidth,
(imgWidth * canvas.height) / canvas.width,
"png"
);
let file_name = new Date().getTime() + ".png";
let imgsrc = img.src.slice(22)
let file = this.convertBase64UrlToImgFile(
imgsrc,
file_name,
"image/png"
)
return file;
},
convertBase64UrlToImgFile(urlData, fileName, fileType) {
urlData = urlData.replace(/^data:image\/\w+;base64,/, "");
let bytes = wx.base64ToArrayBuffer(urlData);
// var bytes = wx.atob(urlData); //转换为byte
//处理异常,将ascii码小于0的转换为大于0
var ab = new ArrayBuffer(bytes.length);
var ia = new Int8Array(ab);
var i;
for (i = 0; i < bytes.length; i++) {
ia[i] = bytes.charCodeAt(i);
}
//转换成文件添加文件的typenamelastModifiedDate属性
var blob = new Blob([ab], { type: fileType });
blob.lastModifiedDate = new Date();
blob.name = fileName;
return blob;
}
}
export { FileUtil }

View File

@ -88,7 +88,7 @@
</a-descriptions-item>
</a-descriptions>
</a-tab-pane>
<a-tab-pane key="3" tab="DPMAS">
<a-tab-pane key="3" tab="人工肝治疗">
<a-descriptions
:column="2"
:title="'第' + (index + 1) + '次治疗'"
@ -273,7 +273,7 @@
{{ caseVO.day }}
</a-descriptions-item>
<a-descriptions-item label="出院情况 " :span="6" class="required">
{{ caseVO.dischargeSituation }}
<div class="row" v-html="caseVO.dischargeSituation"></div>
</a-descriptions-item>
<a-descriptions-item label="出院状态(单选)" :span="6" class="required">
<a-radio-group v-model:value="caseVO.dischargeStatus">
@ -309,7 +309,7 @@
保存
</a-button>
</div>
<imgEditor ref="imgEditorRef" v-if="showEdit"></imgEditor>
<imgEditor ref="imgEditorRef" v-if="showEdit" @freshDetail="getDetail"></imgEditor>
</div>
</a-modal>
</template>
@ -611,6 +611,9 @@ const openEditor = (data) => {
const saveEditor = () => {
imgEditorRef.value?.save();
};
const handleOk = () => {
showEdit.value = false;
};

View File

@ -3,16 +3,19 @@
</template>
<script setup>
import { message, Modal } from 'ant-design-vue';
import { ref,onBeforeUnmount} from 'vue';
import 'tui-image-editor/dist/tui-image-editor.css';
import 'tui-color-picker/dist/tui-color-picker.css';
import ImageEditor from 'tui-image-editor';
import { caseplatformCaseApi } from '/@/api/business/case/caseplatform-case-api';
const prosp=defineProps({
imgsrc:{
type:String,
default:''
}
})
const emit=defineEmits(['freshDetail'])
// tui-image-editor
const locale_zh = {
ZoomIn: '放大',
@ -168,8 +171,43 @@ const customTheme = {
'colorpicker.title.color': '#fff',
};
const instance = ref(null);
//console.log(props.src);
const HandleMainDiagnoseImg=()=>{
caseplatformCaseApi.updateMainDiagnose({
caseId:current_caseId.value,
mainDiagnose:JSON.stringify(caseVO.value.mainDiagnose)
}).then(res=>{
message.success('保存成功')
})
};
const HandleDpmasImg=(dmpsId)=>{
caseplatformCaseApi.updateDpmas({
caseId:current_caseId.value,
dmpsId:dmpsId,
dpmasImg:dpmasImg
}).then(res=>{
message.success('保存成功')
})
};
const HandleCheckImg=(dmpsId)=>{
caseplatformCaseApi.updatecheck({
caseId:current_caseId.value,
dmpsId:dmpsId,
checkImg:checkImg
}).then(res=>{
message.success('保存成功')
})
};
const getImageFormat=(imageUrl)=>{
console.log(imageUrl)
var parts = imageUrl.split('.');
return parts[parts.length - 1];
};
const getOss=()=>{
caseplatformCaseApi.getOssSign(1).then(res=>{
let { accessid, dir,policy,signature,host} = res;
let imgUrl = file;
})
}
const save = () => {
instance.value.resetZoom();
const base64String = instance.value.toDataURL(); // base64

View File

@ -0,0 +1,176 @@
export const caseTypeOption=[{
name:'DPMAS及联合模式',
value:"1"
},{
name:'CA280及联合模式',
value:'2'
}]
export const diagnoseOption=[
{
name:'肝衰竭',
value:'1',
},{
name:'肿瘤',
value:'2'
},{
name:'胆汁淤积性肝病',
value:'3'
},
{
name:'移植围手术期支持治疗',
value:'4'
},
{
name:'伴黄疸的MODS或脓毒症、重症中毒等',
value:'5'
},
{
name:'其他',
value:'-1'
}]
export const patientSickOption=[{
name:'乙肝',
value:"1"
},{
name:'丙肝',
value:'2'
},{
name:'酒精性肝病',
value:'3'
},{
name:'酒精性肝硬化',
value:'4'
},{
name:'自身免疫性肝炎AIH',
value:'5'
},{
name:'原发性胆汁性肝硬化PBC',
value:'6'
},{
name:'原发性硬化性胆管炎PSC',
value:'7'
},{
name:'非酒精性脂肪肝',
value:'8'
},{
name:'药物性肝损伤',
value:'9'
},{
name:'肝豆状核变性',
value:'10'
},{
name:'甲肝',
value:'11'
},{
name:'戊肝',
value:"12"
},{
name:'其他',
value:'-1'
}]
export const ganneiOption=[
{
name:'乙肝再激活',
value:'1'
},{
name:'大量饮酒',
value:'2'
},{
name:'药物毒物',
value:'3'
},
{
name:'戊型肝炎感染',
value:'4'
},
{
name:'甲型肝炎感染',
value:'5'
},
{
name:'丙肝再激活',
value:'6'
},
{
name:'其他',
value:'-1'
}]
export const ganwaiOption=[
{
name:'消化道出血',
value:'1'
},{
name:'感染',
value:'2'
},{
name:'手术',
value:'3'
},
{
name:'劳累',
value:'4'
},
{
name:'其他',
value:'-1'
}]
export const moshiOption=[{
name:'DPMAS',
value:'1'
},{
name:'DPMAS+PE',
value:'2'
},{
name:'DPMAS+其他',
value:'-1'
},{
name:'CA280吸附',
value:'3'
},{
name:'DPCAS',
value:'4'
}]
export const kangningOption=[{
name:'肝素',
value:'1'
},{
name:'低分子肝素',
value:'2'
},{
name:'枸橼酸',
value:'3'
},{
name:'甲磺酸萘莫司他',
value:'4'
},{
name:'其他',
value:'-1'
}]
export const hospitalOption=[{
name:'好转',
value:'1'
},{
name:'痊愈',
value:'2'
},{
name:'恶化',
value:'3'
},{
name:'死亡',
value:'4'
},{
name:'移植',
value:'5'
}]
export const il6Unit=[{
name:'pg/ml',
value:'1'
},{
name:'ng/mL',
value:'2'
},{
name:'ng/L',
value:'3'
}]

View File

@ -295,12 +295,8 @@
<a-textarea v-model:value="current_reason" placeholder="输入不通过原因" :auto-size="{ minRows: 2, maxRows: 8 }" />
</a-modal>
</div>
<a-modal v-model:visible="showEdit" title="编辑图片" width="100%" wrap-class-name="my-full-modal" @ok="handleOk">
<a-modal v-model:visible="showEdit" title="编辑图片" width="100%" wrap-class-name="my-full-modal" @ok="handleOk">
<div class="editorcon">
<!-- <a-image
:width="200"
:src="newSrc"
/> -->
<div class="save" @click="save">
<a-button type="primary" shape="round">
<template #icon>

View File

@ -0,0 +1,95 @@
<template>
<div class="imgecell">
<div class="mask"></div>
<div class="tool">
<eye-outlined style="color: #fff; font-size: 16px; cursor: pointer" @click="priviewImg" />
<form-outlined style="color: #fff; font-size: 16px; margin-left: 10px; cursor: pointer" @click="showeditor" />
</div>
<img class="viewimg" :src="src" alt="" />
<a-image
:width="100"
:style="{ display: 'none' }"
:preview="{
visible,
onVisibleChange: priviewImg,
}"
:src="src"
/>
</div>
</template>
<script setup>
import { ref} from 'vue';
const props = defineProps({
src: {
type: String,
default: '',
},
});
const emits = defineEmits(['openEditor']);
const visible = ref(false);
const priviewImg = (value) => {
visible.value = value;
};
const showeditor = () => {
emits('openEditor', props.src);
}
</script>
<style lang="less" >
#tui-image-editor {
height: 100%;
width: 100%;
position: relative;
}
.editbox {
width: 100%;
height: 100%;
z-index: 999;
position: fixed;
top: 0;
bottom: 0;
}
.editbox .mask {
position: absolute;
width: 100%;
height: 100%;
z-index: 1;
background: rgba(0, 0, 0, 0.4);
}
.viewimg {
width: 100px;
height: 100px;
object-fit: cover;
}
.imgecell {
margin-top: 4px;
position: relative;
width: 100px;
height: 100px;
border-radius: 4px;
margin-right: 12px;
overflow: hidden;
}
.imgecell .tool {
position: absolute;
width: 100%;
height: 100%;
z-index: 1;
display: flex;
justify-content: center;
align-items: center;
}
.imgecell .mask {
position: absolute;
width: 100%;
height: 100%;
z-index: 1;
background: rgba(0, 0, 0, 0.2);
}
</style>

View File

@ -0,0 +1,353 @@
<template>
<div id="tui-image-editor" ></div>
</template>
<script setup>
import { message, Modal } from 'ant-design-vue';
import { ref,onBeforeUnmount} from 'vue';
import 'tui-image-editor/dist/tui-image-editor.css';
import 'tui-color-picker/dist/tui-color-picker.css';
import ImageEditor from 'tui-image-editor';
import { caseplatformCaseApi } from '/@/api/business/case/caseplatform-case-api';
const prosp=defineProps({
imgsrc:{
type:String,
default:''
}
})
const emit=defineEmits(['freshDetail'])
// tui-image-editor
const locale_zh = {
ZoomIn: '放大',
ZoomOut: '缩小',
Hand: '手掌',
History: '历史',
Resize: '调整宽高',
Crop: '裁剪',
DeleteAll: '全部删除',
Delete: '删除',
Undo: '撤销',
Redo: '反撤销',
Reset: '重置',
Flip: '镜像',
Rotate: '旋转',
Draw: '画',
Shape: '形状标注',
Icon: '图标标注',
Text: '文字标注',
Mask: '遮罩',
Filter: '滤镜',
Bold: '加粗',
Italic: '斜体',
Underline: '下划线',
Left: '左对齐',
Center: '居中',
Right: '右对齐',
Color: '颜色',
'Text size': '字体大小',
Custom: '自定义',
Square: '正方形',
Apply: '应用',
Cancel: '取消',
'Flip X': 'X 轴',
'Flip Y': 'Y 轴',
Range: '区间',
Stroke: '描边',
Fill: '填充',
Circle: '圆',
Triangle: '三角',
Rectangle: '矩形',
Free: '曲线',
Straight: '直线',
Arrow: '箭头',
'Arrow-2': '箭头2',
'Arrow-3': '箭头3',
'Star-1': '星星1',
'Star-2': '星星2',
Polygon: '多边形',
Location: '定位',
Heart: '心形',
Bubble: '气泡',
'Custom icon': '自定义图标',
'Load Mask Image': '加载蒙层图片',
Grayscale: '灰度',
Blur: '模糊',
Sharpen: '锐化',
Emboss: '浮雕',
'Remove White': '除去白色',
Distance: '距离',
Brightness: '亮度',
Noise: '噪音',
'Color Filter': '彩色滤镜',
Sepia: '棕色',
Sepia2: '棕色2',
Invert: '负片',
Pixelate: '像素化',
Threshold: '阈值',
Tint: '色调',
Multiply: '正片叠底',
Blend: '混合色',
Width: '宽度',
Height: '高度',
'Lock Aspect Ratio': '锁定宽高比例',
};
//
const customTheme = {
'common.bi.image': '', // logo
'common.bisize.width': '0px',
'common.bisize.height': '0px',
'common.backgroundImage': 'none',
'common.backgroundColor': '#fff',
'common.border': 'none',
// header
'header.backgroundImage': 'none',
'header.backgroundColor': '#f3f4f6',
'header.border': '0px',
'header.display': 'none',
// load button
'loadButton.backgroundColor': '#fff',
'loadButton.border': '1px solid #ddd',
'loadButton.color': '#222',
'loadButton.fontFamily': 'NotoSans, sans-serif',
'loadButton.fontSize': '12px',
'loadButton.display': 'none', //
// download button
'downloadButton.backgroundColor': '#fdba3b',
'downloadButton.border': '1px solid #fdba3b',
'downloadButton.color': '#fff',
'downloadButton.fontFamily': 'NotoSans, sans-serif',
'downloadButton.fontSize': '12px',
'downloadButton.display': 'none', //
// icons default
'menu.normalIcon.color': '#fff',
'menu.activeIcon.color': '#4080ff',
'menu.disabledIcon.color': '#ccc',
'menu.hoverIcon.color': '#4080ff',
'submenu.normalIcon.color': 'rgba(255,255,255,.9)',
'submenu.activeIcon.color': '#4080ff',
'menu.iconSize.width': '16px',
'menu.iconSize.height': '16px',
'submenu.iconSize.width': '18px',
'submenu.iconSize.height': '18px',
// submenu primary color
'submenu.backgroundColor': 'transparent',
'submenu.partition.color': 'transparent',
// submenu labels
'submenu.normalLabel.color': 'rgba(255,255,255,.5)',
'submenu.normalLabel.fontWeight': 'lighter',
'submenu.activeLabel.color': '#fff',
'submenu.activeLabel.fontWeight': 'lighter',
// checkbox style
'checkbox.border': '1px solid #ccc',
'checkbox.backgroundColor': '#fff',
// rango style
'range.pointer.color': '#fff',
'range.bar.color': 'rgba(255,255,255,0.5)',
'range.subbar.color': '#fff',
'range.disabledPointer.color': '#414141',
'range.disabledBar.color': '#282828',
'range.disabledSubbar.color': '#414141',
'range.value.color': '#fff',
'range.value.fontWeight': 'lighter',
'range.value.fontSize': '11px',
'range.value.border': '1px solid #496fb9',
'range.value.backgroundColor': '#496fb9',
'range.title.color': '#fff',
'range.title.fontWeight': 'lighter',
// colorpicker style
'colorpicker.button.border': '1px solid #fff',
'colorpicker.title.color': '#fff',
};
const instance = ref(null);
const HandleMainDiagnoseImg=()=>{
caseplatformCaseApi.updateMainDiagnose({
caseId:current_caseId.value,
mainDiagnose:JSON.stringify(caseVO.value.mainDiagnose)
}).then(res=>{
message.success('保存成功')
})
};
const HandleDpmasImg=(dmpsId)=>{
caseplatformCaseApi.updateDpmas({
caseId:current_caseId.value,
dmpsId:dmpsId,
dpmasImg:dpmasImg
}).then(res=>{
message.success('保存成功')
})
};
const HandleCheckImg=(dmpsId)=>{
caseplatformCaseApi.updatecheck({
caseId:current_caseId.value,
dmpsId:dmpsId,
checkImg:checkImg
}).then(res=>{
message.success('保存成功')
})
};
const getImageFormat=(imageUrl)=>{
console.log(imageUrl)
var parts = imageUrl.split('.');
return parts[parts.length - 1];
};
const getOss=()=>{
caseplatformCaseApi.getOssSign(1).then(res=>{
let { accessid, dir,policy,signature,host} = res;
let imgUrl = file;
})
}
const save = () => {
instance.value.resetZoom();
const base64String = instance.value.toDataURL(); // base64
const data = window.atob(base64String.split(',')[1]);
const ia = new Uint8Array(data.length);
for (let i = 0; i < data.length; i++) {
ia[i] = data.charCodeAt(i);
}
const blob = new Blob([ia], { type: 'image/png' }); // blob
//便使uuid
const file = new File([blob], new Date().getTime() + '.jpeg', { type: blob.type });
fileToBase64(file).then((res) => {
newSrc.value = res;
});
};
const fileToBase64 = (file) => {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => resolve(reader.result);
reader.onerror = (error) => reject(error);
});
};
const init = (src) => {
instance.value = new ImageEditor(document.querySelector('#tui-image-editor'), {
includeUI: {
loadImage: {
path: src,
name: '编辑图片',
},
menu: ['draw', 'text'], // flipmask
initMenu: 'draw', //
menuBarPosition: 'bottom', //
locale: locale_zh, //
theme: customTheme, //
},
cssMaxWidth: 1000, // canvas
cssMaxHeight: 600, //
usageStatistics: false,
});
document.getElementsByClassName('tui-image-editor-main')[0].style.top = '45px'; //
//document.getElementsByClassName('tie-btn-reset tui-image-editor-item help')[0].style.display = 'none'; //
document.getElementsByClassName('tie-text-align-button')[0].style.display = 'none'; //
// //
// document.getElementsByClassName("tui-image-editor-main")[0].style.top = "0px";
// //
document.getElementsByClassName('tie-btn-reset tui-image-editor-item help')[0].style.display = 'none';
//
document.getElementsByClassName('tie-btn-hand tui-image-editor-item help')[0].style.display = 'none';
//
document.getElementsByClassName('tie-btn-history tui-image-editor-item help')[0].style.display = 'none';
//
document.getElementsByClassName('tie-btn-delete tui-image-editor-item')[0].style.display = 'none';
};
onBeforeUnmount(() => {
if (instance.value) {
instance.value.destroy();
instance.value = null;
}
});
defineExpose({init,save})
</script>
<style>
.tui-image-editor-help-menu {
background: skyblue !important;
}
.tui-image-editor-container .tui-image-editor-controls {
display: flex !important;
align-items: center !important;
background: transparent;
height: 40px !important;
}
.tui-image-editor-container .color-picker-value {
width: 20px !important;
height: 20px !important;
}
.tui-image-editor-container.bottom .tui-image-editor-submenu > div {
padding-bottom: 0 !important;
}
.tui-image-editor-container .tui-image-editor-submenu .tui-image-editor-submenu-item li {
display: flex !important;
}
.tui-image-editor-container .tui-image-editor-submenu .tui-image-editor-submenu-item .tui-image-editor-newline {
display: flex !important;
align-items: center;
}
.tui-image-editor-menu {
width: 300px !important;
height: 50px;
display: flex !important;
align-items: center !important;
justify-content: center;
background: skyblue !important;
}
.tui-image-editor-container .tui-image-editor-menu > .tui-image-editor-item,
.tui-image-editor-container .tui-image-editor-help-menu > .tui-image-editor-item.active {
padding: 0 !important;
width: 25px;
height: 25px;
display: flex !important;
justify-content: center !important;
align-items: center !important;
}
.tui-image-editor-container {
background: transparent !important;
}
.tui-image-editor-submenu-item {
display: flex !important;
justify-content: center !important;
width: 800px !important;
margin: 0 auto !important;
align-items: center !important;
background: skyblue !important;
}
.tui-image-editor-container .tui-image-editor-range {
top: 0 !important;
}
.tui-image-editor-container .tui-image-editor-range-value {
margin-top: 0;
}
.editorcon {
width: 100%;
height: 100%;
position: relative;
}
.save {
position: absolute;
right: 195px;
top: 14px;
z-index: 999;
cursor: pointer;
color:#fff;
font-size: 17px;
opacity: 0.8;
}
</style>