This commit is contained in:
zoujiandong
2025-08-03 16:29:54 +08:00
parent 43abd1f3d6
commit 6e320c3944
74 changed files with 1954 additions and 974 deletions
+13 -1
View File
@@ -89,7 +89,13 @@ onMounted(()=>{
padding-bottom: 20rpx;
background-color: #f9fafb;
position: relative;
height:200rpx;
/* #ifdef H5 */
height:120rpx;
/* #endif */
/* #ifdef MP-WEIXIN */
height:200rpx;
/* #endif */
background: radial-gradient(
60% 90% at 4% 2%,
#43c9c3 0%,
@@ -109,7 +115,13 @@ onMounted(()=>{
);
}
.namebox {
/* #ifdef H5 */
padding-top: 51rpx;
/* #endif */
/* #ifdef MP-WEIXIN */
padding-top: 102rpx;
/* #endif */
margin: 0rpx 30rpx 0rpx;
display: flex;
align-items: center;
+7 -1
View File
@@ -53,7 +53,13 @@ const goBack = () => {
);
}
.namebox {
padding-top: 102rpx;
/* #ifdef H5 */
padding-top: 51rpx;
/* #endif */
/* #ifdef MP-WEIXIN */
padding-top: 102rpx;
/* #endif */
justify-content: center;
margin: 0rpx 30rpx 0rpx;
position: relative;
+7 -1
View File
@@ -49,7 +49,13 @@
);
}
.namebox {
padding-top: 102rpx;
/* #ifdef H5 */
padding-top: 51rpx;
/* #endif */
/* #ifdef MP-WEIXIN */
padding-top: 102rpx;
/* #endif */
margin: 0rpx 30rpx 0rpx;
display: flex;
align-items: center;
+9 -2
View File
@@ -30,7 +30,7 @@
<up--image
:src="userHeadImg"
@click="goMy"
mode="widthFix"
width="62rpx"
height="62rpx"
radius="50%"
@@ -114,6 +114,7 @@ onLoad(()=>{
<style lang="scss" scoped>
.navbox {
padding-bottom: 20rpx;
background-color: #f9fafb;
position: relative;
@@ -137,7 +138,13 @@ onLoad(()=>{
);
}
.namebox {
padding-top: 102rpx;
/* #ifdef H5 */
padding-top: 51rpx;
/* #endif */
/* #ifdef MP_WEIXIN */
padding-top: 102rpx;
/* #endif */
margin: 0rpx 30rpx 0rpx;
display: flex;
align-items: center;
+10 -4
View File
@@ -33,7 +33,7 @@
<up--image
:src="userHeadImg"
@click="goMy"
mode="widthFix"
width="62rpx"
height="62rpx"
radius="50%"
@@ -74,7 +74,7 @@ watch(()=>props.type,(newVal)=>{
}else if(newVal==='hospital'){
placeholder.value='输入医院名称'
}else if(newVal==='video'){
placeholder.value='疾病名称、标题、作者搜索'
placeholder.value='输入疾病名称、标题、作者搜索'
}else if(newVal==='article' ){
placeholder.value='搜索疾病、症状、医院'
}else if(newVal==='case'){
@@ -82,7 +82,7 @@ watch(()=>props.type,(newVal)=>{
}else if(newVal==='myCase'){
placeholder.value='输入疾病名称、标题搜索'
}else if(newVal==='cert'){
placeholder.value='疾病名称、标题搜索'
placeholder.value='输入疾病名称、标题搜索'
}
},{immediate: true })
@@ -153,7 +153,13 @@ const search=()=>{
background: none!important;
}
.namebox {
padding-top: 102rpx;
/* #ifdef H5 */
padding-top: 51rpx;
/* #endif */
/* #ifdef MP-WEIXIN */
padding-top: 102rpx;
/* #endif */
margin: 0rpx 30rpx 0rpx;
display: flex;
align-items: center;
+342 -87
View File
@@ -1,5 +1,6 @@
<template>
<view class="page">
<view class="navbox">
<view class="bg"></view>
<view class="namebox">
@@ -85,6 +86,12 @@
</view>
<view class="btn" @click="confirm">确定</view>
</view>
<canvas
v-if="showCanvas"
type="2d"
id="pwatermarkCanvas"
style="width: 200px; height: 200px; position: fixed; top: -9999px"
/>
</view>
<up-popup
:round="10"
@@ -137,9 +144,12 @@
import throttle from "@/utils/throttle"
import addImg from "@/static/add.png";
import videoImg from "@/static/videoicon.png";
import { nextTick, reactive, ref,watch } from "vue";
import { initCustomFormatter, nextTick, reactive, ref,watch } from "vue";
import { onLoad } from "@dcloudio/uni-app";
import videoface from "@/static/videoface.jpg";
import { getCurrentInstance } from 'vue'
const instace = getCurrentInstance();
import api from "@/api/api";
import dayjs from "dayjs";
import {
@@ -148,8 +158,10 @@
addText,
} from "@/uni_modules/sv-editor/components/common/utils.js";
import svEditor from "@/uni_modules/sv-editor/components/sv-editor/sv-editor.vue";
const editorCtx=ref(null);
const PeditorCtx=ref(null);
const htmlContent=ref('');
const keyboardHeight=ref(0);
const videoface=ref('https://caseplatform.oss-cn-beijing.aliyuncs.com/prod/static/shipinfengmian.jpg')
const editorHeight=ref(300);
const navName=ref('病例信息');
const placeholder=ref('患者基本情况,检查结果,诊疗图片或视频');
@@ -164,6 +176,7 @@
default:''
}
})
const showCanvas=ref(false);
watch(()=>props.editorType,(newVal)=>{
console.log(11111111)
console.log(newVal)
@@ -195,48 +208,56 @@
};
const ready = (e) => {
console.log(e);
editorCtx.value = e;
PeditorCtx.value = e;
if(props.editorType=="info"){
if(props.editorCotent){
editorCtx.value.initHtml(props.editorCotent,async (videoUrl) => {
console.log('peditor')
console.log(props.editorCotent)
PeditorCtx.value.initHtml(props.editorCotent,async (videoUrl) => {
let res='';
// #ifdef APP || H5
// res = await this.editorCtx.createVideoThumbnail(videoUrl)
// res = await this.PeditorCtx.createVideoThumbnail(videoUrl)
// #endif
const fox = videoface
res = await editorCtx.value.createCoverThumbnail(fox)
showEditor.value=false;
res = await PeditorCtx.value.createCoverThumbnail(videoface.value)
return res
})
setTimeout(async()=>{
console.log('qaz')
let res=await PeditorCtx.value.getLastContent();
console.log(res);
},6000)
}else{
let html =
"<p>【患者信息】:</p><br/><p>【主诉】:</p><br/><p>【现病史及既往史】:</p><br/><p>【检查】:</p><br/><p>【临床诊断】:</p><br/><p>【治疗经过及结果】:</p><br/><br/>";
editorCtx.value.initHtml(html);
PeditorCtx.value.initHtml(html);
}
}else{
if(props.editorCotent){
editorCtx.value.initHtml(props.editorCotent,async (videoUrl) => {
PeditorCtx.value.initHtml(props.editorCotent,async (videoUrl) => {
let res='';
// #ifdef APP || H5
// res = await this.editorCtx.createVideoThumbnail(videoUrl)
// res = await this.PeditorCtx.createVideoThumbnail(videoUrl)
// #endif
const fox = videoface
res = await editorCtx.value.createCoverThumbnail(fox)
showEditor.value=false;
res = await PeditorCtx.value.createCoverThumbnail(videoface.value)
return res
})
}else{
let html =
"";
editorCtx.value.initHtml(html);
PeditorCtx.value.initHtml(html);
}
}
@@ -249,11 +270,13 @@
emits('closeEditor')
})
const confirm=async ()=>{
console.log('qqq')
const res = await editorCtx.value.getLastContent();
const res = await PeditorCtx.value.getLastContent();
let html = PeditorCtx.value.exportHtml(res.html.replace('undefined',''));
emits('changeEditor',{
type:props.editorType,
content:res.html
content:html
})
}
const foucus=()=>{
@@ -263,7 +286,7 @@
}
const clearMuBan=()=>{
editorCtx.value.initHtml("");
PeditorCtx.value.initHtml("");
}
const updatePosition=(c_keyboardHeight)=>{
const toolbarHeight = 50
@@ -288,17 +311,235 @@
scrollTop: 0,
success() {
updatePosition(keyboardHeight)
editorCtx.value.scrollView()
PeditorCtx.value.scrollView()
}
})
}, duration)
})
});
const fillTextToImgWx = (base64) => {
let maskText = "@肝胆相照临床病例库";
return new Promise((resolve, reject) => {
wx.createSelectorQuery().in(instace.proxy)
.select("#pwatermarkCanvas")
.fields({
node: true,
size: true,
})
.exec((res) => {
const canvas = res[0].node;
const ctx = canvas.getContext("2d");
let textMetrics = ctx.measureText(maskText);
console.log(textMetrics);
//水印文字宽度
let {
width: textWidth,
actualBoundingBoxAscent,
actualBoundingBoxDescent,
} = textMetrics;
//水印文字高度
let textHeight = actualBoundingBoxAscent
? actualBoundingBoxAscent + actualBoundingBoxDescent
: textMetrics.fontBoundingBoxAscent +
textMetrics.fontBoundingBoxDescent;
let imgHeight, imgWidth;
let font = ""; //fontsize"px Arial";
let fontColor = "#fff";
let strokeWidth = 3;
uni.getImageInfo({
src: base64,
success: (imageRes) => {
// 设置canvas宽高
let scale =28;
// (imageRes.width / 800) * 30 > 12
// ? (imageRes.width / 800) * 30
// : 12;
font = scale + "px Arial";
console.log(imageRes);
canvas.width = imageRes.width;
canvas.height = imageRes.height;
imgHeight = imageRes.height;
imgWidth = imageRes.width;
// 创建目标图片对象
const image = canvas.createImage();
image.src = "";
image.src = base64;
image.onload = () => {
// 清除画布
//ctx.clearRect(0, 0, canvas.width, canvas.height);
// 将图片绘制到canvas上
ctx.drawImage(image, 0, 0, canvas.width, canvas.height);
let posXmargin = 10; //this.data.posXmargin // 自定义离左/右边的距离
let posYmargin = 10; // this.data.posYmargin // 自定义离上/下边的距离
let randomNumber = 3; //Math.floor(Math.random() * (3 + 1));
console.log("randomNumber:" + randomNumber);
switch (randomNumber) {
case 0: //左上角
let lt_x = posXmargin;
let lt_y = posYmargin + textHeight;
ctx.font = font;
ctx.fillStyle = fontColor;
ctx.storkStyle = "black";
ctx.strokeWidth = strokeWidth;
ctx.fillStyle = "#fff";
ctx.fillText(maskText, lt_x, lt_y);
//ctx.restore()
//ctx.save()
break;
case 1: //左下角
let lb_x = posXmargin;
let lb_y = imgHeight - posYmargin;
ctx.font = font;
ctx.fillStyle = fontColor;
ctx.strokeStyle = "black";
ctx.strokeWidth = strokeWidth;
ctx.fillStyle = "#fff";
ctx.fillText(maskText, lb_x, lb_y);
//ctx.restore()
//ctx.save()
break;
case 2: //右上角
let rt_x =
imgWidth - textWidth * 2.9 - posXmargin <= 0
? 10
: imgWidth - textWidth * 2.9 - posXmargin;
let rt_y = posYmargin + textHeight * 2;
ctx.font = font;
ctx.fillStyle = fontColor;
ctx.strokeStyle = "black";
ctx.strokeWidth = strokeWidth;
ctx.fillStyle = "#fff";
ctx.fillText(maskText, rt_x, rt_y);
ctx.restore();
ctx.save();
break;
case 3: //右下角
let rb_x =
imgWidth - textWidth * 6 - posXmargin <= 0
? 10
: imgWidth - 276- posXmargin;
console.log(rb_x)
let rb_y = imgHeight - posYmargin;
ctx.font = font;
ctx.fillStyle = fontColor;
ctx.strokeStyle = "black";
ctx.strokeWidth = strokeWidth;
ctx.fillStyle = "#fff";
ctx.fillText(maskText, rb_x, rb_y);
//ctx.restore()
//ctx.save()
break;
}
//ctx.restore()
// 将canvas转为图片
//setTimeout(() => {
wx.canvasToTempFilePath({
canvas: canvas,
success: function (res) {
// 输出生成的带水印的图片临时路径
resolve(res.tempFilePath);
//wx.previewImage({ urls: [res.tempFilePath] });
},
fail: function (res) {
// reject(res)
console.error(res);
},
});
//})
};
},
});
});
});
};
const fillTextToImg = (base64) => {
const img = new Image();
img.src = base64;
img.setAttribute("crossOrigin", "Anonymous");
return new Promise((resolve, reject) => {
img.onload = () => {
const canvas = document.createElement("canvas");
const ctx = canvas.getContext("2d");
canvas.width = img.width;
canvas.height = img.height;
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
const remFontSize = 30; //canvas.width / 35;
ctx.font = remFontSize + "px '微软雅黑'";
ctx.textAlign = "right";
ctx.strokeStyle = "#000";
ctx.fillStyle = "#fff";
const uploadTime = new Date();
const name = "@肝胆相照临床病例库";
const spaceH = remFontSize * 0.1;
let randomNumber = 3//Math.floor(Math.random() * (3 + 1));
let position = [
{
top: remFontSize,
left: name.length * 30 || 30,
},
{
top: remFontSize,
left: canvas.width - remFontSize * 0.1 - spaceH,
},
{
top: canvas.height - remFontSize * 0.5 - spaceH,
left: name.length * 30 || 30,
},
{
top: canvas.height - remFontSize * 0.5 - spaceH,
left: canvas.width - remFontSize * 0.1 - spaceH,
},
];
ctx.strokeText(
name,
position[randomNumber].left,
position[randomNumber].top
);
ctx.fillText(
name,
position[randomNumber].left,
position[randomNumber].top
);
resolve(canvas.toDataURL("image/jpeg"));
};
});
};
const generateRandomNumber = () => {
let randomNumber = Math.floor(1000 + Math.random() * 9000);
return randomNumber;
};
// 图片转64代
const getImageBase64 = (url) => {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.open("GET", url, true);
xhr.responseType = "blob";
xhr.onload = function () {
if (this.status == 200) {
const fileReader = new FileReader();
fileReader.onloadend = function () {
resolve(fileReader.result); // Base64编码的字符串
};
fileReader.readAsDataURL(xhr.response); // 将blob转换为base64
} else {
reject("Could not fetch the file.");
}
};
xhr.onerror = function () {
reject("XHR error");
};
xhr.send();
});
};
const getImageFormat = (imageUrl) => {
console.log(imageUrl);
const lastDotIndex = imageUrl.lastIndexOf(".");
@@ -307,66 +548,76 @@
}
return "unknown";
};
const handleUpload = (file) => {
api
.getOss({
scene: 1,
})
.then((rep) => {
let result = rep.data;
if (result.code == 200) {
let { access_id, dir, policy, signature, host } = result.data;
let time = dayjs().format("YYYYMMDDHHmmss");
let random = generateRandomNumber();
let filename = time + random;
let imgType = "." + getImageFormat(file);
return new Promise((resolve, reject) => {
uni.uploadFile({
url: host, // 仅为示例,非真实的接口地址
filePath: file,
name: "file",
formData: {
OSSAccessKeyId: access_id,
policy,
key: dir + time + random + imgType,
signature,
},
success(res) {
if (res.statusCode === 204) {
let url = host + "/" + dir + filename + imgType;
//imgList.value.push(url);
addImage([url]);
}
},
fail: (err) => {
console.log(err);
},
});
});
}
});
};
const pFun = (files) => {
uni.showLoading({
title: "正在上传图片...",
mask: true,
});
const getOss=(temurl)=>{
api
.getOss({
scene: 1,
})
.then((rep) => {
let result = rep.data;
if (result.code == 200) {
let { access_id, dir, policy, signature, host } = result.data;
let time = dayjs().format("YYYYMMDDHHmmss");
let random = generateRandomNumber();
let filename = time + random;
let imgType = "." + getImageFormat(temurl);
return new Promise((resolve, reject) => {
uni.uploadFile({
url: host, // 仅为示例,非真实的接口地址
filePath:temurl,
name: "file",
formData: {
OSSAccessKeyId: access_id,
policy,
key: dir + time + random + imgType,
signature,
},
success(res) {
if (res.statusCode === 204) {
let url = host + "/" + dir + filename + imgType;
//imgList.value.push(url);
addImage([url]);
}
},
fail: (err) => {
console.log(err);
},
});
});
}
});
}
const readImages = async (localIds) => {
uni.showLoading({
title: "正在上传图片...",
mask: true,
});
console.log(localIds);
let promiseFun = [];
for (let i = 0; i < files.length; i++) {
promiseFun.push(handleUpload(files[i]));
}
Promise.all(promiseFun).then((res) => {
uni.hideLoading();
// setTimeout(()=>{
// console.log(imgList.value.length)
// addImage(imgList.value)
// })
});
};
for (var i = 0; i < localIds.length; i++) {
let img = null;
// #ifdef H5
let imgBase64 = await getImageBase64(localIds[i]);
img = await fillTextToImg(imgBase64);
// #endif
// #ifdef MP-WEIXIN
img = await fillTextToImgWx(localIds[i]);
// #endif
promiseFun.push(getOss(img))
};
Promise.all(promiseFun).then((res) => {
uni.showToast({
duration: 1000,
message: "上传成功",
icon:"none"
});
});
}
const insertImage = (file) => {
showCanvas.value=true;
//if (!(!isFocusInfo.value && !isFocusResult.value)) {
uni.chooseImage({
count: 9, //默认9
@@ -374,7 +625,8 @@
sourceType: ["album"], //从相册选择
extension: [".jpg", ".png", ".jpeg"],
success: function (res) {
pFun(res.tempFilePaths);
readImages(res.tempFilePaths);
},
});
//}
@@ -384,7 +636,7 @@
title: "正在上传视频...",
mask: true,
});
const videos = await addVideo(async (editorCtx) => {
const videos = await addVideo(async (PeditorCtx) => {
return new Promise((resolve) => {
api
.getOss({
@@ -413,11 +665,7 @@
async success(res) {
if (res.statusCode === 204) {
let url = host + "/" + dir + filename + imgType;
let imgUrl =videoface;
const fileThumbnail = await editorCtx.createCoverThumbnail(
imgUrl
);
const fileThumbnail = await PeditorCtx.createCoverThumbnail(videoface.value);
resolve([
{
videoUrl: url,
@@ -466,9 +714,16 @@
console.log('qqqqqq')
showTitle.value = true;
};
const initData=(data)=>{
console.log('init');
console.log(data)
htmlContent.value=data;
}
defineExpose({initData})
</script>
<style lang='scss'scoped>
<style lang='scss' scoped>
.row{
padding: 30rpx 30rpx 0;
display: flex;