上传图片
This commit is contained in:
parent
a67ad3a01a
commit
82d23803bd
@ -1,3 +1,3 @@
|
|||||||
NODE_ENV=development
|
NODE_ENV=development
|
||||||
VITE_APP_TITLE='肝胆相照临床病例库'
|
VITE_APP_TITLE='肝胆相照临床病例库'
|
||||||
VITE_APP_API_URL='http://127.0.0.1:5480'
|
VITE_APP_API_URL='https://dev-casedata.igandan.com/admin/api'
|
||||||
@ -1,3 +1,3 @@
|
|||||||
NODE_ENV=development
|
NODE_ENV=development
|
||||||
VITE_APP_TITLE='肝胆相照临床病例库'
|
VITE_APP_TITLE='肝胆相照临床病例库'
|
||||||
VITE_APP_API_URL='http://127.0.0.1:5480'
|
VITE_APP_API_URL='https://dev-casedata.igandan.com/admin/api'
|
||||||
|
|||||||
@ -17,6 +17,11 @@
|
|||||||
<title> %VITE_APP_TITLE%</title>
|
<title> %VITE_APP_TITLE%</title>
|
||||||
<link rel="icon" href="/favicon.ico"/>
|
<link rel="icon" href="/favicon.ico"/>
|
||||||
</head>
|
</head>
|
||||||
|
<style>
|
||||||
|
.editor-tip{
|
||||||
|
display: none!important;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
<body>
|
<body>
|
||||||
<div id="app"></div>
|
<div id="app"></div>
|
||||||
<script type="module" src="/src/main.js"></script>
|
<script type="module" src="/src/main.js"></script>
|
||||||
|
|||||||
@ -96,4 +96,5 @@
|
|||||||
:deep(.ant-table-column-sorters) {
|
:deep(.ant-table-column-sorters) {
|
||||||
align-items: flex-start !important;
|
align-items: flex-start !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
* @Date: 2025-08-04 10:17:15
|
* @Date: 2025-08-04 10:17:15
|
||||||
* @Copyright gdxz
|
* @Copyright gdxz
|
||||||
*/
|
*/
|
||||||
import { postRequest, getRequest } from '/@/lib/axios';
|
import { postRequest, getRequest,uploadRequest} from '/@/lib/axios';
|
||||||
|
|
||||||
export const caseClinicalArticleApi = {
|
export const caseClinicalArticleApi = {
|
||||||
|
|
||||||
@ -22,7 +22,12 @@ export const caseClinicalArticleApi = {
|
|||||||
add: (param) => {
|
add: (param) => {
|
||||||
return postRequest('/caseClinicalArticle/add', param);
|
return postRequest('/caseClinicalArticle/add', param);
|
||||||
},
|
},
|
||||||
|
getOssSign:(type)=>{ //获取上传文件 Policy
|
||||||
|
return getRequest('/file/getOSSPolicy/'+type)
|
||||||
|
},
|
||||||
|
ossUpload:(url,data)=>{
|
||||||
|
return uploadRequest(url,data);
|
||||||
|
},
|
||||||
/**
|
/**
|
||||||
* 修改 @author xing
|
* 修改 @author xing
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -1,16 +1,16 @@
|
|||||||
<!--
|
<!--
|
||||||
* 编辑器
|
* 编辑器
|
||||||
*
|
*
|
||||||
* @Author: 1024创新实验室-主任:卓大
|
* @Author: 1024创新实验室-主任:卓大
|
||||||
* @Date: 2022-09-12 15:34:33
|
* @Date: 2022-09-12 15:34:33
|
||||||
* @Wechat: zhuda1024
|
* @Wechat: zhuda1024
|
||||||
* @Email: lab1024@163.com
|
* @Email: lab1024@163.com
|
||||||
* @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012
|
* @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012
|
||||||
*
|
*
|
||||||
-->
|
-->
|
||||||
<template>
|
<template>
|
||||||
<div style="border: 1px solid #ccc">
|
<div style="border: 1px solid #ccc" class="myeditor">
|
||||||
<Toolbar style="border-bottom: 1px solid #ccc" :editor="editorRef" />
|
<Toolbar style="border-bottom: 1px solid #ccc" :editor="editorRef" :defaultConfig="toolbarConfig" />
|
||||||
<Editor
|
<Editor
|
||||||
style="overflow-y: hidden"
|
style="overflow-y: hidden"
|
||||||
:style="{ height: `${height}px` }"
|
:style="{ height: `${height}px` }"
|
||||||
@ -24,23 +24,76 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { shallowRef, onBeforeUnmount, watch, ref } from 'vue';
|
import { shallowRef, onBeforeUnmount, watch, ref } from 'vue';
|
||||||
import { FILE_FOLDER_TYPE_ENUM } from '/@/constants/support/file-const';
|
import { FILE_FOLDER_TYPE_ENUM } from '/@/constants/support/file-const';
|
||||||
import { fileApi } from '/@/api/support/file-api';
|
import { caseClinicalArticleApi } from '/@/api/business/case-clinical-article/case-clinical-article-api';
|
||||||
import '@wangeditor-next/editor/dist/css/style.css';
|
import '@wangeditor/editor/dist/css/style.css';
|
||||||
import { Editor, Toolbar } from '@wangeditor-next/editor-for-vue';
|
import { Editor, Toolbar } from '@wangeditor/editor-for-vue';
|
||||||
import { smartSentry } from '/@/lib/smart-sentry';
|
import { smartSentry } from '/@/lib/smart-sentry';
|
||||||
|
import { SmartLoading } from '/@/components/framework/smart-loading';
|
||||||
//菜单
|
//菜单
|
||||||
const editorConfig = { MENU_CONF: {} };
|
import dayjs from 'dayjs';
|
||||||
|
import { FileUtil } from '/@/utils/fileutil';
|
||||||
|
let props = defineProps({
|
||||||
|
modelValue: String,
|
||||||
|
height: {
|
||||||
|
type: Number,
|
||||||
|
default: 500,
|
||||||
|
},
|
||||||
|
editorConfig: {
|
||||||
|
type: Object,
|
||||||
|
default: { MENU_CONF: {} }
|
||||||
|
},
|
||||||
|
toolbarConfig: {
|
||||||
|
type: Object,
|
||||||
|
default: {}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const editorConfig = props.editorConfig;
|
||||||
|
console.log(editorConfig);
|
||||||
|
const getImg = (file) => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
caseClinicalArticleApi.getOssSign(1).then((res) => {
|
||||||
|
console.log(res.data);
|
||||||
|
let { accessid, dir, policy, signature, host } = res.data;
|
||||||
|
let filename = dayjs().format('YYYYMMDDHHmmss') + FileUtil.UUID() + '.' + 'png';
|
||||||
|
let formData = new FormData();
|
||||||
|
formData.append('OSSAccessKeyId', accessid);
|
||||||
|
formData.append('policy', policy);
|
||||||
|
formData.append('signature', signature);
|
||||||
|
formData.append('key', dir + filename);
|
||||||
|
formData.append('file', file, filename);
|
||||||
|
formData.append('success_action_status', 200);
|
||||||
|
caseClinicalArticleApi
|
||||||
|
.ossUpload(host, formData)
|
||||||
|
.then((res) => {
|
||||||
|
console.log(host + dir + filename);
|
||||||
|
resolve(host + dir + filename);
|
||||||
|
SmartLoading.hide();
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.log(err);
|
||||||
|
|
||||||
|
alert('上传失败');
|
||||||
|
SmartLoading.hide();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
//上传
|
//上传
|
||||||
let customUpload = {
|
let customUpload = {
|
||||||
async customUpload(file, insertFn) {
|
async customUpload(file, insertFn) {
|
||||||
try {
|
try {
|
||||||
const formData = new FormData();
|
SmartLoading.show();
|
||||||
formData.append('file', file);
|
// const formData = new FormData();
|
||||||
let res = await fileApi.uploadFile(formData, FILE_FOLDER_TYPE_ENUM.COMMON.value);
|
// formData.append('file', file);
|
||||||
let data = res.data;
|
// let res = await fileApi.uploadFile(formData, FILE_FOLDER_TYPE_ENUM.COMMON.value);
|
||||||
insertFn(data.fileUrl);
|
// let data = res.data;
|
||||||
|
getImg(file).then((data) => {
|
||||||
|
console.log(data);
|
||||||
|
insertFn(data);
|
||||||
|
});
|
||||||
|
//insertFn(data.fileUrl);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
smartSentry.captureError(error);
|
smartSentry.captureError(error);
|
||||||
}
|
}
|
||||||
@ -51,16 +104,11 @@
|
|||||||
|
|
||||||
// ----------------------- 以下是公用变量 emits props ----------------
|
// ----------------------- 以下是公用变量 emits props ----------------
|
||||||
const editorHtml = ref();
|
const editorHtml = ref();
|
||||||
let props = defineProps({
|
|
||||||
modelValue: String,
|
|
||||||
height: {
|
|
||||||
type: Number,
|
|
||||||
default: 500,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
watch(
|
watch(
|
||||||
() => props.modelValue,
|
() => props.modelValue,
|
||||||
(nVal) => {
|
(nVal) => {
|
||||||
|
console.log(nVal);
|
||||||
editorHtml.value = nVal;
|
editorHtml.value = nVal;
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -74,6 +122,9 @@
|
|||||||
const editorRef = shallowRef();
|
const editorRef = shallowRef();
|
||||||
const handleCreated = (editor) => {
|
const handleCreated = (editor) => {
|
||||||
editorRef.value = editor;
|
editorRef.value = editor;
|
||||||
|
|
||||||
|
console.log( Toolbar ) // 当前菜单排序和分组
|
||||||
|
|
||||||
};
|
};
|
||||||
const handleChange = (editor) => {
|
const handleChange = (editor) => {
|
||||||
emit('update:modelValue', editorHtml.value);
|
emit('update:modelValue', editorHtml.value);
|
||||||
@ -99,20 +150,15 @@
|
|||||||
getHtml,
|
getHtml,
|
||||||
getText,
|
getText,
|
||||||
});
|
});
|
||||||
</script>
|
|
||||||
|
|
||||||
|
</script>
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.w-e-full-screen-container {
|
.w-e-full-screen-container {
|
||||||
z-index: 9999 !important;
|
z-index: 9999 !important;
|
||||||
}
|
}
|
||||||
</style>
|
|
||||||
<!-- 解决弹窗高度警告信息显示 -->
|
.myeditor >>> button[data-tooltip="编辑图片"]{
|
||||||
<style>
|
display: none !important;
|
||||||
::v-deep .w-e-text-container {
|
}
|
||||||
height: 420px !important;
|
|
||||||
}
|
|
||||||
.w-e-text-container .w-e-scroll {
|
|
||||||
height: 500px !important;
|
|
||||||
-webkit-overflow-scrolling: touch;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@ -56,9 +56,9 @@ smartAxios.interceptors.response.use(
|
|||||||
(response) => {
|
(response) => {
|
||||||
// 根据content-type ,判断是否为 json 数据
|
// 根据content-type ,判断是否为 json 数据
|
||||||
let contentType = response.headers['content-type'] ? response.headers['content-type'] : response.headers['Content-Type'];
|
let contentType = response.headers['content-type'] ? response.headers['content-type'] : response.headers['Content-Type'];
|
||||||
if (contentType.indexOf('application/json') === -1) {
|
// if (contentType.indexOf('application/json') === -1) {
|
||||||
return Promise.resolve(response);
|
// return Promise.resolve(response);
|
||||||
}
|
// }
|
||||||
|
|
||||||
// 如果是json数据
|
// 如果是json数据
|
||||||
if (response.data && response.data instanceof Blob) {
|
if (response.data && response.data instanceof Blob) {
|
||||||
@ -153,7 +153,9 @@ export const postRequest = (url, data) => {
|
|||||||
method: 'post',
|
method: 'post',
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
export const uploadRequest = (url, data) => {
|
||||||
|
return request({ data, url, method: 'post', headers: { 'Content-Type': 'multipart/form-data' } });
|
||||||
|
};
|
||||||
// ================================= 加密 =================================
|
// ================================= 加密 =================================
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
91
src/utils/fileutil.js
Normal file
91
src/utils/fileutil.js
Normal 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);
|
||||||
|
}
|
||||||
|
//转换成文件,添加文件的type,name,lastModifiedDate属性
|
||||||
|
var blob = new Blob([ab], { type: fileType });
|
||||||
|
blob.lastModifiedDate = new Date();
|
||||||
|
blob.name = fileName;
|
||||||
|
return blob;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export { FileUtil }
|
||||||
@ -151,7 +151,8 @@
|
|||||||
<a-form-item label="内容" name="articleContent" v-if="!isLinkChecked">
|
<a-form-item label="内容" name="articleContent" v-if="!isLinkChecked">
|
||||||
<div class="editor-container">
|
<div class="editor-container">
|
||||||
<div class="editor-tip">请在此处编辑文章内容,支持富文本格式、图片上传、表格等功能</div>
|
<div class="editor-tip">请在此处编辑文章内容,支持富文本格式、图片上传、表格等功能</div>
|
||||||
<UEditor v-model="form.articleContent" :id="'article_content'" />
|
<!-- <UEditor v-model="form.articleContent" :id="'article_content'" /> -->
|
||||||
|
<SmartWangeditor ref="rubricRef" :modelValue="form.articleContent" :height="500" :toolbarConfig="rubricToolbarConfig"/>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
@ -222,7 +223,8 @@
|
|||||||
import { smartSentry } from '/@/lib/smart-sentry';
|
import { smartSentry } from '/@/lib/smart-sentry';
|
||||||
import FileUpload from '/@/components/support/file-upload/index.vue';
|
import FileUpload from '/@/components/support/file-upload/index.vue';
|
||||||
import SmartEnumSelect from '/@/components/framework/smart-enum-select/index.vue';
|
import SmartEnumSelect from '/@/components/framework/smart-enum-select/index.vue';
|
||||||
import UEditor from '/@/components/business/ueditor.vue';
|
//import UEditor from '/@/components/business/ueditor.vue';
|
||||||
|
import SmartWangeditor from '/@/components/framework/wangeditor/index.vue';
|
||||||
import { FILE_FOLDER_TYPE_ENUM } from '/@/constants/support/file-const';
|
import { FILE_FOLDER_TYPE_ENUM } from '/@/constants/support/file-const';
|
||||||
import { PlusOutlined, DeleteOutlined } from '@ant-design/icons-vue';
|
import { PlusOutlined, DeleteOutlined } from '@ant-design/icons-vue';
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
@ -234,7 +236,12 @@
|
|||||||
// ------------------------ 显示与隐藏 ------------------------
|
// ------------------------ 显示与隐藏 ------------------------
|
||||||
// 是否显示
|
// 是否显示
|
||||||
const visibleFlag = ref(false);
|
const visibleFlag = ref(false);
|
||||||
|
const rubricRef = ref();
|
||||||
|
|
||||||
|
|
||||||
|
const rubricToolbarConfig = {
|
||||||
|
toolbarKeys : ['bold', 'underline', 'italic', 'through', 'code', 'sub', 'sup', 'clearStyle', 'color', 'bgColor', 'fontSize', 'fontFamily', 'indent', 'delIndent', 'justifyLeft', 'justifyRight', 'justifyCenter', 'justifyJustify', 'lineHeight', 'insertImage', 'deleteImage', 'editImage', 'divider', 'insertLink', 'editLink', 'unLink', 'viewLink', 'codeBlock', 'blockquote', 'headerSelect', 'redo', 'undo', 'fullScreen', 'enter', 'bulletedList', 'numberedList','uploadImage' ]
|
||||||
|
}
|
||||||
async function show(rowData) {
|
async function show(rowData) {
|
||||||
// 重置表单数据
|
// 重置表单数据
|
||||||
Object.assign(form, formDefault);
|
Object.assign(form, formDefault);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user