const comsData = ref([]);
const closed = () => {
comsData.value = [];
};
const menu = useMenuStore();
const frame = useFrameStore();
const psdFileRef = ref(null);
const psdFileHandler = e => {
loadingInstance.value = ElLoading.service({
background: 'rgba(0, 0, 0, 0.8)',
text: '',
});
const reader = new FileReader();
reader.onloadend = () => {
onDrop({
dataTransfer: { files: [psdFileRef.value.files[0]] },
target: {
result: null,
},
})
};
reader.readAsText(psdFileRef.value.files[0], 'utf8');
loadingInstance.value.close();
};
var PSD = require('psd');
const onDragOver = e => {
e.stopPropagation();
e.preventDefault();
e.dataTransfer.dropEffect = 'copy';
};
const onDrop = e => {
repeatNumber++;
loadingInstance.value = ElLoading.service({
background: 'rgba(0, 0, 0, 0.8)',
text: '',
});
PSD.fromEvent(e).then(function (psd) {
const config = psd.tree().export();
const { children } = config;
const { width, height } = config.document;
dgc(children, psd.tree().children());
});
loadingInstance.value.close();
};
const dataURLtoBlob = dataurl => {
let arr = dataurl.split(','),
mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]),
n = bstr.length,
u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
return new Blob([u8arr], { type: mime });
};
let repeatNumber = 0;
const loadingInstance = ref(null);
const dgc = (c, tree) => {
for (let i = 0; i < c.length; i++) {
const item = c[i];
const t = tree[i];
const { visible, children, type } = item;
if (visible && children) {
dgc(children, t.children());
} else if (visible) {
const { name, text, width, height, bottom, left, top } = item;
if (text && width > 0 && height > 0) {
setCom(item, 'text');
} else if (width > 0 && height > 0) {
let file = new File([dataURLtoBlob(t.toPng().src)], `${name || 'file'}.png`);
let formData = new FormData();
formData.append('file', file);
setCom(item, 'rect', formData);
}
}
}
console.log('当前组件22', comsData.value);
};
const setCom = async (item, comType, formData) => {
const { name, text, width, height, bottom, left, top, type } = item;
const options = {
type: comType == 'text' ? 'text' : 'rect',
model: 'base',
style: {
left,
top,
'z-index': 100,
},
};
if (comType == 'text') {
const { value } = text;
const com = getInitialAttrs(options);
if (com) {
const { model, type } = com;
com.vueData[`${model}_${type}`].gWidth = null;
com.vueData[`${model}_${type}`].gHeight = null;
com.vueData[`${model}_${type}`].text = value;
com.vueData[`${model}_${type}`].fontSize = text.font.sizes[0];
com.vueData[`${model}_${type}`].color = `rgba(${text.font.colors[0]})`;
}
comsData.value.unshift(com);
} else if (comType == 'rect') {
const rectCom = getInitialAttrs(options);
const url = await sendImage(formData)
.then(res => {
if (res.data.StatusCode == 200) {
return res.data.Data;
}
repeatNumber = 0;
})
.catch(err => {
if (repeatNumber < 5) {
setCom(item, comType, formData, index);
}
});
if (rectCom) {
const { model, type } = rectCom;
rectCom.vueData[`${model}_${type}`].backgroundImage = url;
rectCom.vueData[`${model}_${type}`].gWidth = width;
rectCom.vueData[`${model}_${type}`].gHeight = height;
rectCom.vueData[`${model}_${type}`].urlPre = 'http://192.168.0.150:8008';
}
comsData.value.unshift(rectCom);
}
};
const sendImage = formData => {
const url = `${domain.uploadUrl}${uploadFile}`;
return axios({
method: 'post',
url,
data: formData,
headers: {
accesstoken: 'adcf40f89d4acd38bddb9',
app: 'cloudconfigure',
ext: '.png',
},
});
};
原来文件
<template>
<el-dialog
v-model="state.dialogVisible"
:title="props.dialogType == 'new' ? '新建页面' : '编辑页面'"
width="400px"
custom-class="pageDialog_container"
:destroy-on-close="true"
:before-close="close"
@closed="closed"
>
<!-- custom-class="pageList_dialog" -->
<!-- :rules="rules" -->
<el-form ref="pageFromRef" :model="state.pageFrom" :rules="rules" label-width="100px">
<el-form-item label="页面名称" prop="name">
<el-input
v-model="state.pageFrom.name"
autocomplete="off"
placeholder="请输入页面名称"
style="width: 250px"
/>
</el-form-item>
<el-form-item v-if="props.dialogType == 'new'" label="页面类型" prop="type">
<el-select v-model="state.pageFrom.type" placeholder="请选择页面类型" style="width: 250px">
<el-option
v-for="(item, index) in localPageList"
:value="item.value"
:label="item.label"
:key="item.value"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="页面权限" prop="authority">
<el-select
v-model="state.pageFrom.authority"
placeholder="请选择是页面权限"
style="width: 250px"
>
<el-option
v-for="(item, i) in authorityList"
:key="i"
:value="item.value"
:label="item.label"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="菜单隐藏" v-show="!state.pageFrom.isShowMenuPage" prop="isHide">
<el-select
v-model="state.pageFrom.isHide"
placeholder="请选择是否隐藏菜单栏"
style="width: 250px"
>
<el-option
v-for="item in menuStatus"
:key="item.value"
:label="item.label"
:value="item.value"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="弹框主题" v-show="state.pageFrom.isShowMenuPage">
<el-select v-model="state.pageFrom.themeProDialog" style="width: 250px">
<el-option
v-for="(item, i) in themeList"
:key="i"
:value="item.value"
:label="item.label"
>
</el-option>
</el-select>
</el-form-item>
<el-form-item v-if="props.dialogType == 'new'" label="窗口页面">
<el-switch
:disabled="dialogType == 'edit'"
v-model="state.pageFrom.isShowMenuPage"
></el-switch>
</el-form-item>
<el-form-item label="解析psd">
<div class="psdFile_container">
<el-icon class="hand_icon"><Plus /></el-icon>
<input
class="fileInput"
type="file"
ref="psdFileRef"
accept=".psd"
@change="psdFileHandler"
/>
</div>
</el-form-item>
</el-form>
<div class="dialog_footer flex_c">
<el-button type="primary" class="OKbtn" @click="confirmHandler">确定</el-button>
<el-button class="cancelbtn" @click="cancelHandler">取消</el-button>
</div>
</el-dialog>
</template>
<script setup>
import { ref, onMounted, reactive, toRefs, nextTick } from 'vue';
import { Plus } from '@element-plus/icons-vue';
import { useMenuStore, useFrameStore } from '@/store';
import { newPageList } from '@/hooks/useMouseMenu.js';
import { getInitialAttrs } from '@/components/CenterEdit/hooks/useCompt/add.js';
import { state as centerStore, setBodyVueMap, addPageCompt } from '@/hooks/useCenterHook.js';
import domain from '@/utils/http/domain.http.js';
import { uploadFile } from '@/utils/http/api.http';
import axios from 'axios';
import { ElMessage, ElLoading } from 'element-plus';
import { maxZindex } from '@/components/CenterEdit/hooks/useCompt/index.js';
const comsData = ref([]);
const closed = () => {
comsData.value = [];
};
const menu = useMenuStore();
const frame = useFrameStore();
const psdFileRef = ref(null);
const psdFileHandler = e => {
loadingInstance.value = ElLoading.service({
background: 'rgba(0, 0, 0, 0.8)',
text: '',
});
const reader = new FileReader();
reader.onloadend = () => {
onDrop({
dataTransfer: { files: [psdFileRef.value.files[0]] },
target: {
result: null,
},
})
};
reader.readAsText(psdFileRef.value.files[0], 'utf8');
loadingInstance.value.close();
};
var PSD = require('psd');
const onDragOver = e => {
e.stopPropagation();
e.preventDefault();
e.dataTransfer.dropEffect = 'copy';
};
const onDrop = e => {
repeatNumber++;
loadingInstance.value = ElLoading.service({
background: 'rgba(0, 0, 0, 0.8)',
text: '',
});
PSD.fromEvent(e).then(function (psd) {
const config = psd.tree().export();
const { children } = config;
const { width, height } = config.document;
dgc(children, psd.tree().children());
});
loadingInstance.value.close();
};
const dataURLtoBlob = dataurl => {
let arr = dataurl.split(','),
mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]),
n = bstr.length,
u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
return new Blob([u8arr], { type: mime });
};
let repeatNumber = 0;
const loadingInstance = ref(null);
const dgc = (c, tree) => {
for (let i = 0; i < c.length; i++) {
const item = c[i];
const t = tree[i];
const { visible, children, type } = item;
if (visible && children) {
dgc(children, t.children());
} else if (visible) {
const { name, text, width, height, bottom, left, top } = item;
if (text && width > 0 && height > 0) {
setCom(item, 'text');
} else if (width > 0 && height > 0) {
let file = new File([dataURLtoBlob(t.toPng().src)], `${name || 'file'}.png`);
let formData = new FormData();
formData.append('file', file);
setCom(item, 'rect', formData);
}
}
}
console.log('当前组件22', comsData.value);
};
const setCom = async (item, comType, formData) => {
const { name, text, width, height, bottom, left, top, type } = item;
const options = {
type: comType == 'text' ? 'text' : 'rect',
model: 'base',
style: {
left,
top,
'z-index': 100,
},
};
if (comType == 'text') {
const { value } = text;
const com = getInitialAttrs(options);
if (com) {
const { model, type } = com;
com.vueData[`${model}_${type}`].gWidth = null;
com.vueData[`${model}_${type}`].gHeight = null;
com.vueData[`${model}_${type}`].text = value;
com.vueData[`${model}_${type}`].fontSize = text.font.sizes[0];
com.vueData[`${model}_${type}`].color = `rgba(${text.font.colors[0]})`;
}
comsData.value.unshift(com);
} else if (comType == 'rect') {
const rectCom = getInitialAttrs(options);
const url = await sendImage(formData)
.then(res => {
if (res.data.StatusCode == 200) {
return res.data.Data;
}
repeatNumber = 0;
})
.catch(err => {
if (repeatNumber < 5) {
setCom(item, comType, formData, index);
}
});
if (rectCom) {
const { model, type } = rectCom;
rectCom.vueData[`${model}_${type}`].backgroundImage = url;
rectCom.vueData[`${model}_${type}`].gWidth = width;
rectCom.vueData[`${model}_${type}`].gHeight = height;
rectCom.vueData[`${model}_${type}`].urlPre = 'http://192.168.0.150:8008';
}
comsData.value.unshift(rectCom);
}
};
const sendImage = formData => {
const url = `${domain.uploadUrl}${uploadFile}`;
return axios({
method: 'post',
url,
data: formData,
headers: {
accesstoken: 'adcf40f89d4acd38bddb9',
app: 'cloudconfigure',
ext: '.png',
},
});
};
const localPageList = Object.freeze([
{ label: '单页面', value: 'opage' },
{ label: '多页面', value: 'mpage' },
]);
const authorityList = Object.freeze([
{ label: '零级权限', value: 0 },
{ label: '一级权限', value: 1 },
{ label: '二级权限', value: 2 },
{ label: '三级权限', value: 3 },
{ label: '四级权限', value: 4 },
{ label: '五级权限', value: 5 },
]);
const menuStatus = Object.freeze([
{
label: '显示菜单',
value: '0',
},
{
label: '隐藏菜单',
value: '1',
},
{
label: '全屏显示',
value: '2',
},
]);
const themeList = Object.freeze([
{ label: '主题一', value: 'black' },
{ label: '主题二', value: 'white' },
]);
const props = defineProps({
dialogType: {
type: String,
default: 'new',
},
pageItem: {
type: Object,
default: () => {
return {
name: '',
type: 'opage',
isHide: '0',
authority: 0,
isShowMenuPage: false,
themeProDialog: 'black',
size: 0,
};
},
},
});
const pageFromRef = ref(null);
const state = reactive({
dialogVisible: false,
pageFrom: {
name: '',
type: 'opage',
isHide: '0',
authority: 0,
isShowMenuPage: false,
themeProDialog: 'black',
size: 0,
},
});
const validatePageName = (rule, value, callback) => {
const tempI = menu.pageList.findIndex(item => item.name == value);
if (value === '') {
callback(new Error('请输入页面名称'));
} else if (tempI != -1) {
callback(new Error('页面名称不能重复哦!'));
} else {
callback();
}
};
const rules = reactive({
name: [{ required: true, validator: validatePageName, trigger: 'blur' }],
type: [{ required: true, message: '必填项', trigger: 'blur' }],
authority: [{ required: true, message: '必填项', trigger: 'blur' }],
});
const createdPageList = data => {
const type = props.dialogType;
if (type == 'new') {
newPageList(state.pageFrom);
addPsdCom(state.pageFrom.id, comsData.value);
} else {
editPageList();
}
};
const addPsdCom = (id, datas) => {
const page = centerStore.pageData.find(item => item.id == id);
datas.forEach((item, index) => {
const { model, type } = item;
item.vueData[`${model}_${type}`].gZindex = index + maxZindex.value;
setBodyVueMap(item);
});
page.pageCompts.push(...datas);
console.log('最终的centerStore', centerStore);
};
const editPageList = () => {
menu.replacePageList(JSON.parse(JSON.stringify(state.pageFrom)));
};
const confirmHandler = () => {
if (!pageFromRef.value) return;
pageFromRef.value.validate(valid => {
if (valid) {
createdPageList();
cancelHandler();
} else {
return false;
}
});
};
const cancelHandler = () => {
close();
};
const resetPageForm = () => {
state.pageFrom = {
name: '',
type: 'opage',
isHide: '0',
authority: 0,
isShowMenuPage: false,
themeProDialog: 'black',
};
};
const open = () => {
state.dialogVisible = true;
};
const close = () => {
if (!pageFromRef.value) return;
pageFromRef.value.resetFields();
resetPageForm();
state.dialogVisible = false;
};
const initEditData = params => {
Object.assign(state.pageFrom, params);
};
defineExpose({
...toRefs(state),
open,
close,
initEditData,
});
</script>
<style lang="less">
.pageDialog_container {
.el-dialog__body {
padding: 15px;
}
.el-dialog__footer {
padding: 0 !important;
}
}
#dropzone {
margin-left: 20px;
height: 32px;
width: 190px;
border: 1px #ababab dashed;
box-sizing: border-box;
}
#dropzone p {
text-align: center;
line-height: 32px;
margin: 0;
padding: 0;
}
.psdFile_container {
border: 1px #ababab dashed;
width: 40px;
height: 20px;
position: relative;
.hand_icon {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
.fileInput {
width: 40px;
height: 20px;
opacity: 0;
}
}
</style>
|