Compare commits

..

2 Commits

Author SHA1 Message Date
YuanFeng 21a0ca112e Merge branch 'dev' of https://git.yfgame.vip/r/hangtag into dev
# Please enter a commit message to explain why this merge is necessary,
# especially if it merges an updated upstream into a topic branch.
#
# Lines starting with '#' will be ignored, and an empty message aborts
# the commit.
2024-10-23 23:58:42 +08:00
YuanFeng fd26dc46c1 优化 图稿大图问题 2024-10-23 23:57:47 +08:00
24 changed files with 869 additions and 802 deletions

View File

@ -327,8 +327,7 @@ public class MybatisPlusUtil {
if (ignoreKeys.contains(orderField)) {
continue;
}
if ("desc".equalsIgnoreCase(QueryConfigUtils.toStr(s2[1],""))) {
if (s2.length > 1 && "desc".equalsIgnoreCase(QueryConfigUtils.toStr(s2[1],""))) {
queryWrapper.orderByDesc(orderField);
} else {
queryWrapper.orderByAsc(orderField);
@ -366,6 +365,7 @@ public class MybatisPlusUtil {
// 条件查询
if (QueryConfigUtils.isNotEmpty(filter)) {
Set<String> keySet = options.keySet();
// 过滤配置
Map<String, FilterItem> filterMap = new HashMap<>();
for (String s : keySet) {
// 处理驼峰字段

View File

@ -74,6 +74,7 @@ public class QueryConfigUtils {
registerWrapperHandler(new BetweenHandler<>());
registerWrapperHandler(new EqHandler<>());
registerWrapperHandler(new GeHandler<>());
registerWrapperHandler(new GtHandler<>());
registerWrapperHandler(new InHandler<>());
registerWrapperHandler(new InSetHandler<>());
registerWrapperHandler(new KeywordHandler<>());
@ -447,7 +448,7 @@ public class QueryConfigUtils {
}
/**
* 跳过数据
* 跳过数据处理器
*
* @param str str
* @return boolean

View File

@ -1,13 +1,11 @@
package cn.hangtag.framework.mybatis.build.where.handler;
import cn.hangtag.framework.mybatis.build.QueryConfigUtils;
import cn.hangtag.framework.mybatis.build.WrapperInfo;
import cn.hangtag.framework.mybatis.build.enums.QueryFilterTypeEnum;
import cn.hangtag.framework.mybatis.build.where.WhereWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import java.util.List;
public class GeHandler<T> implements WhereWrapper<T> {
@Override
public QueryFilterTypeEnum getType() {

View File

@ -0,0 +1,19 @@
package cn.hangtag.framework.mybatis.build.where.handler;
import cn.hangtag.framework.mybatis.build.WrapperInfo;
import cn.hangtag.framework.mybatis.build.enums.QueryFilterTypeEnum;
import cn.hangtag.framework.mybatis.build.where.WhereWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
public class GtHandler<T> implements WhereWrapper<T> {
@Override
public QueryFilterTypeEnum getType() {
return QueryFilterTypeEnum.GT;
}
@Override
public QueryWrapper<T> handler(WrapperInfo<T> wrapperInfo) {
return wrapperInfo.getQueryWrapper().gt(wrapperInfo.getField(), wrapperInfo.getValue());
}
}

View File

@ -54,6 +54,7 @@
"crypto-js": "^4.2.0",
"dayjs": "^1.11.10",
"diagram-js": "^12.8.0",
"dom-to-image": "^2.6.0",
"driver.js": "^1.3.1",
"echarts": "^5.5.0",
"echarts-wordcloud": "^2.1.0",

View File

@ -211,13 +211,8 @@ const updateVisible = (visible: boolean) => {
defineExpose({}) // open
const submit = () => {
// base64
convertImageToBase64(that.iconUrl).then((res:string) => {
that.iconUrl = res;
emit("update:modelValue", that.iconUrl)
updateVisible(false)
})
emit("update:modelValue", that.iconUrl)
updateVisible(false)
}
const clearData = ()=>{
that.iconUrl = '';

View File

@ -13,7 +13,7 @@
<template #footer>
<span class="dialog-footer">
<el-button @click="updateVisible(false)"> </el-button>
<el-button type="primary" @click="submit"></el-button>
<el-button type="primary" @click="submit">批稿</el-button>
</span>
</template>
</Dialog>
@ -60,10 +60,13 @@ const previewByDraftDesignId = (id: string | number,prop={})=>{
that.loading = false;
},100)
}
const submit = async ()=>{
const res = await designPropEditRef.value.getPropInfo()
emit("submit",res);
updateVisible(false)
const submit = ()=>{
useMessage().confirm("是否提交?").then(async (r) => {
const res = await designPropEditRef.value.getPropInfo()
emit("submit",res);
updateVisible(false)
})
}
defineExpose({
preview,

View File

@ -1,93 +1,88 @@
<!-- eslint-disable vue/this-in-template -->
<template>
<div style="max-height: 90vh; overflow:auto;" v-loading="loading">
<span>
仅供参考(for reference only),绿色边框属于边界
</span>
<div style="padding-bottom: 4px">
<el-button @click="that.currentZoom -= 1" :disabled="that.currentZoom <= 1">-
</el-button>
<el-select v-model="that.currentZoom" style="width: 90px">
<el-option
v-for="item in zoomList"
:key="item.value"
:label="(Math.floor(item.value))"
:value="item.value"
/>
<el-option
v-if="!zoomList.some(o => o.value === that.currentZoom)"
:label="(Math.floor(that.currentZoom))"
:value="that.currentZoom"
/>
</el-select>
<el-button @click="that.currentZoom += 1" :disabled="that.currentZoom >= 30">+
</el-button>
<el-checkbox style="margin: 8px" v-model="that.reView">实时预览</el-checkbox>
<el-button
v-show="!that.reView"
style="margin: 8px"
type="primary"
size="small"
@click="updateDesign">
<span>更新</span>
<span
style="color: #ff0000;font-size: 20px; padding-left: 4px">{{
that.changeCount > 0 ? '*' : ''
}}</span>
</el-button>
</div>
<div v-if="that.sizeInfo" style="margin-left: 60px" :title="`${that.sizeInfo.width}mm`">
<span>
:{{ that.sizeInfo.width }}mm
</span>
</div>
<div>
<div
style="display: flex;">
<div v-if="that.sizeInfo" :title="`${that.sizeInfo.height}mm`">
<span class="vertical-text">
{{ that.sizeInfo.height }}
:class ="{ 'hidden-div': that.hideCreate}"
:id="that.svgId"
:style="{
width: `${imageSize.width * 6}px`,
height: `${imageSize.height * 6}px`,
}">
<div v-if="that.previewUrl" v-html="that.previewUrl" >
</div>
</div>
<div style="max-height: 90vh; overflow:auto;" v-loading="loading">
<span>
仅供参考(for reference only)
</span>
<div style="padding-bottom: 4px">
<el-checkbox style="margin: 8px" v-model="that.reView">实时预览</el-checkbox>
<el-button
v-show="!that.reView"
style="margin: 8px"
type="primary"
size="small"
@click="updateDesign">
<span>更新</span>
<span
style="color: #ff0000;font-size: 20px; padding-left: 4px">{{
that.changeCount > 0 ? '*' : ''
}}</span>
</el-button>
</div>
<div>
<el-alert
title="按住鼠标左键进行拖动按住Ctrl 滚动鼠标进行缩小放放大"
type="info" effect="dark"/>
</div>
<div v-if="that.sizeInfo" :title="`${that.sizeInfo.width}mm`">
<span>
:{{ that.sizeInfo.width }}mm {{ that.sizeInfo.height }}
</span>
<span>mm</span>
</div>
<div v-if="that.previewUrl" style="margin: 2px; box-shadow: 0 0 1px 1px rgb(0,255,0)">
<el-image
:title="showImgTitle"
@click="imagePreview(that.previewUrl)"
v-loading="loading"
:src="that.previewUrl"/>
</div>
<div class="flex flex-col">
<div>
<el-form label-width="180px">
<el-form-item label="风格样式" v-show="that.draftDesignList.length > 1">
<div class="flex ml-3">
<div>
<el-select class="min-w-100" v-model="that.draftDesignId" @change="changeType">
<el-option
v-for="(item) in that.draftDesignList"
:key="item.id"
:label="item.label"
:value="item.id"
/>
</el-select>
</div>
</div>
</el-form-item>
</el-form>
</div>
<div style="width: 100%" v-if="that.propOrderByList && that.propOrderByList.length > 0">
<el-scrollbar height="600px">
<el-form label-width="180px">
<el-form-item
v-for="(tmp) in that.propOrderByList"
:key="tmp.key"
:label="getLabelName(that.propInfo[tmp.key])">
<div
v-if="that.propInfo[tmp.key].multiLanguage && that.propInfo[tmp.key].shape === ShapeType.vueTextCell">
<div
style="padding: 4px">
<div style="display: flex;align-items: center;">
</div>
<el-row>
<el-col :span="11">
<div
:class ="{ 'hidden-div': false }" style="width:100%;height: 580px; border: 1px solid #090805">
<DraftDesign ref="draftDesignEditRef" @init-succeed="initSucceed"/>
</div>
</el-col>
<el-col :span="12">
<div style="display: flex;">
<div class="flex flex-col">
<div>
<el-form label-width="180px">
<el-form-item label="风格样式" v-show="that.draftDesignList.length > 1">
<div class="flex ml-3">
<div>
<el-select class="min-w-100" v-model="that.draftDesignId" @change="changeType">
<el-option
v-for="(item) in that.draftDesignList"
:key="item.id"
:label="item.label"
:value="item.id"
/>
</el-select>
</div>
</div>
</el-form-item>
</el-form>
</div>
<div style="width: 100%" v-if="that.propOrderByList && that.propOrderByList.length > 0">
<el-scrollbar height="600px">
<el-form label-width="180px">
<el-form-item
v-for="(tmp) in that.propOrderByList"
:key="tmp.key"
:label="getLabelName(that.propInfo[tmp.key])">
<div
v-if="that.propInfo[tmp.key].multiLanguage && that.propInfo[tmp.key].shape === ShapeType.vueTextCell">
<div
style="padding: 4px">
<div style="display: flex;align-items: center;">
<span>
<i
v-if="that.propInfo[tmp.key].canInput"
@ -96,56 +91,56 @@
<i v-else class="icon-lk_cell_add" style="font-size: 20px"> </i>
</span>
<el-select-v2
v-model="that.propInfo[tmp.key].dataInfo[0].showLabel"
filterable
:options="getIngredientInfoListByType(that.propInfo[tmp.key].groupType)"
placeholder="Please select"
@change="changeData(-1,tmp.key)"
size="large"
style="min-width: 280px;width: 100%"
/>
<div v-if="that.propInfo[tmp.key].groupType === '1'">
<div
style="display: flex;align-items: center; margin-left: 10px; width: 220px">
<el-row>
<el-col span="4">
<div>占比</div>
</el-col>
<el-col span="14">
<el-input-number
:min="-1" :max="100"
v-model="that.propInfo[tmp.key].dataInfo[0].ratio"
@change="changeData(0,tmp.key)"
/>
</el-col>
<el-col span="4">
<div> %</div>
</el-col>
</el-row>
</div>
</div>
<el-button
v-if="that.propInfo[tmp.key].canChange"
@click="deleteList(that.propInfo[tmp.key],index)">
<i class="icon-lk_delete"> </i>
</el-button>
</div>
</div>
<el-select-v2
v-model="that.propInfo[tmp.key].dataInfo[0].showLabel"
filterable
:options="getIngredientInfoListByType(that.propInfo[tmp.key].groupType)"
placeholder="Please select"
@change="changeData(-1,tmp.key)"
size="large"
style="min-width: 280px;width: 100%"
/>
<div v-if="that.propInfo[tmp.key].groupType === '1'">
<div
style="display: flex;align-items: center; margin-left: 10px; width: 220px">
<el-row>
<el-col span="4">
<div>占比</div>
</el-col>
<el-col span="14">
<el-input-number
:min="-1" :max="100"
v-model="that.propInfo[tmp.key].dataInfo[0].ratio"
@change="changeData(0,tmp.key)"
/>
</el-col>
<el-col span="4">
<div> %</div>
</el-col>
</el-row>
</div>
</div>
<el-button
v-if="that.propInfo[tmp.key].canChange"
@click="deleteList(that.propInfo[tmp.key],index)">
<i class="icon-lk_delete"> </i>
</el-button>
</div>
</div>
<el-button
v-if="that.propInfo[tmp.key].canChange"
@click="appendList(that.propInfo[tmp.key])">
添加
</el-button>
</div>
<el-button
v-if="that.propInfo[tmp.key].canChange"
@click="appendList(that.propInfo[tmp.key])">
添加
</el-button>
</div>
<div v-else-if="!that.propInfo[tmp.key].isCombo">
<div
v-for="(text,index) in that.propInfo[tmp.key].dataInfo"
:key="index"
style="padding: 4px">
<div style="display: flex;align-items: center;">
<div v-else-if="!that.propInfo[tmp.key].isCombo">
<div
v-for="(text,index) in that.propInfo[tmp.key].dataInfo"
:key="index"
style="padding: 4px">
<div style="display: flex;align-items: center;">
<span>
<i
v-if="that.propInfo[tmp.key].canInput"
@ -153,120 +148,119 @@
style="font-size: 20px"> </i>
<i v-else class="icon-lk_cell_add" style="font-size: 20px"> </i>
</span>
<el-autocomplete
v-if="that.propInfo[tmp.key].canInput"
v-model="that.propInfo[tmp.key].dataInfo[index].showLabel"
:fetch-suggestions="querySearch"
clearable
class="inline-input w-50"
placeholder="Please Input"
@change="changeData"
@select="changeData"
/>
<el-autocomplete
v-if="that.propInfo[tmp.key].canInput"
v-model="that.propInfo[tmp.key].dataInfo[index].showLabel"
:fetch-suggestions="querySearch"
clearable
class="inline-input w-50"
placeholder="Please Input"
@change="changeData"
@select="changeData"
/>
<el-select-v2
v-else
v-model="that.propInfo[tmp.key].dataInfo[index].showLabel"
filterable
:options="getIngredientInfoListByType(that.propInfo[tmp.key].groupType)"
placeholder="Please select"
@change="changeData(index,tmp.key)"
size="large"
style="min-width: 280px;width: 100%"
/>
<div v-if="that.propInfo[tmp.key].groupType === '1'">
<el-select-v2
v-else
v-model="that.propInfo[tmp.key].dataInfo[index].showLabel"
filterable
:options="getIngredientInfoListByType(that.propInfo[tmp.key].groupType)"
placeholder="Please select"
@change="changeData(index,tmp.key)"
size="large"
style="min-width: 280px;width: 100%"
/>
<div v-if="that.propInfo[tmp.key].groupType === '1'">
<div
style="display: flex;align-items: center; margin-left: 10px; width: 220px">
<el-row>
<el-col span="4">
<div>占比</div>
</el-col>
<el-col span="14">
<el-input-number
:min="-1" :max="100"
v-model="that.propInfo[tmp.key].dataInfo[index].ratio"
@change="changeData(index,tmp.key)"
/>
</el-col>
<el-col span="4">
<div> %</div>
</el-col>
</el-row>
</div>
</div>
<el-button
v-if="that.propInfo[tmp.key].canChange"
@click="deleteList(that.propInfo[tmp.key],index)">
<i class="icon-lk_delete"> </i>
</el-button>
</div>
</div>
<div
style="display: flex;align-items: center; margin-left: 10px; width: 220px">
<el-row>
<el-col span="4">
<div>占比</div>
</el-col>
<el-col span="14">
<el-input-number
:min="-1" :max="100"
v-model="that.propInfo[tmp.key].dataInfo[index].ratio"
@change="changeData(index,tmp.key)"
/>
</el-col>
<el-col span="4">
<div> %</div>
</el-col>
</el-row>
</div>
</div>
<el-button
v-if="that.propInfo[tmp.key].canChange"
@click="deleteList(that.propInfo[tmp.key],index)">
<i class="icon-lk_delete"> </i>
</el-button>
</div>
</div>
<el-button
v-if="that.propInfo[tmp.key].canChange"
@click="appendList(that.propInfo[tmp.key])">
添加
</el-button>
</div>
<el-button
v-if="that.propInfo[tmp.key].canChange"
@click="appendList(that.propInfo[tmp.key])">
添加
</el-button>
</div>
<div v-else-if="that.propInfo[tmp.key].shape === ShapeType.vueShapeImage">
<div
v-for="(img,index) in that.propInfo[tmp.key].dataInfo"
:key="index" style="display: flex">
<div class="img-box" v-if="img.url">
<div style="display: flex">
<img :src="img.url" width="60px" height="60px"/>
<el-select-v2
v-model="that.propInfo[tmp.key].dataInfo[0].showLabel"
filterable
:options="washingInfoListByType(that.propInfo[tmp.key].groupType)"
placeholder="Please select"
@change="changeComboData(that.propInfo[tmp.key],that.propInfo[tmp.key].dataInfo[0].showLabel)"
size="large"
style="min-width: 280px;width: 100%"
>
<template #default="{ item }">
<div style="display: flex;">
<img :src="item.url" width="30px" height="30px"/>
<span>
<div v-else-if="that.propInfo[tmp.key].shape === ShapeType.vueShapeImage">
<div
v-for="(img,index) in that.propInfo[tmp.key].dataInfo"
:key="index" style="display: flex">
<div class="img-box" v-if="img.url">
<div style="display: flex">
<img :src="img.url" width="60px" height="60px"/>
<el-select-v2
v-model="that.propInfo[tmp.key].dataInfo[0].showLabel"
filterable
:options="washingInfoListByType(that.propInfo[tmp.key].groupType)"
placeholder="Please select"
@change="changeComboData(that.propInfo[tmp.key],that.propInfo[tmp.key].dataInfo[0].showLabel)"
size="large"
style="min-width: 280px;width: 100%"
>
<template #default="{ item }">
<div style="display: flex;">
<img :src="item.url" width="30px" height="30px"/>
<span>
{{ item.label }}
</span>
</div>
</template>
</el-select-v2>
</div>
</div>
<div v-else-if="img.label">
<el-input v-model="img.label" disabled/>
</div>
<el-button
v-if="that.propInfo[tmp.key].canChange"
@click="deleteList(that.propInfo[tmp.key],index)">
<i class="icon-lk_delete"> </i>
</el-button>
</div>
<el-button
v-if="that.propInfo[tmp.key].canChange"
@click="appendList(that.propInfo[tmp.key])">
添加
</el-button>
</div>
</template>
</el-select-v2>
</div>
</div>
<div v-else-if="img.label">
<el-input v-model="img.label" disabled/>
</div>
<el-button
v-if="that.propInfo[tmp.key].canChange"
@click="deleteList(that.propInfo[tmp.key],index)">
<i class="icon-lk_delete"> </i>
</el-button>
</div>
<el-button
v-if="that.propInfo[tmp.key].canChange"
@click="appendList(that.propInfo[tmp.key])">
添加
</el-button>
</div>
</div>
</el-form-item>
</el-form>
</el-scrollbar>
</div>
</div>
</el-form-item>
</el-form>
</el-scrollbar>
</div>
</div>
</div>
</div>
</el-col>
<div
:class="{ 'hidden-div': true }">
<DraftDesign ref="draftDesignEditRef" @init-succeed="initSucceed"/>
</div>
</div>
</el-row>
</div>
</div>
</template>
<script lang="ts" setup name="DynamicPropConfig">
@ -282,13 +276,14 @@ import {replaceDomain} from "@/utils";
import * as FileApi from "@/api/infra/file";
import {useLocaleStore} from "@/store/modules/locale";
import {ProductInfoApi} from "@/api/oms/productinfo";
import {convertImageToBase64} from "@/components/DraftDesign/utils/Dpi";
import domtoimage from 'dom-to-image';
//
const localeStore = useLocaleStore()
const emit = defineEmits(['change', 'initSucceed'])
const draftDesignEditRef = ref()
const that = reactive({
svgId: "svg_"+Math.random().toString(36).substring(2),
hideCreate: true,
propInfo: {
reView: true,
groupName: '', //
@ -321,38 +316,7 @@ const that = reactive({
data: {},
show: false,
})
const showImgTitle = computed(() => {
if (that.sizeInfo) {
return '宽:' + that.sizeInfo.width + 'mm 高:' + that.sizeInfo.height + 'mm'
}
})
const zoomList = [
{
value: 1,
label: '1'
},
{
value: 5,
label: '5'
},
{
value: 6,
label: '6'
},
{
value: 10,
label: '10'
}, {
value: 15,
label: '15'
}, {
value: 20,
label: '20'
}, {
value: 30,
label: '30'
},
]
const currentLocale = computed(() => localeStore.getCurrentLocale)
watch(() => that.currentZoom, () => {
showPng();
@ -364,7 +328,18 @@ const querySearch = (queryString: string, cb: any) => {
}) : that.ingredientInfoList
cb(results)
}
const imageSize =computed(()=>{
if(that.sizeInfo){
return {
width: that.sizeInfo.width,
height: that.sizeInfo.height
}
}
return {
width: 10,
height: 10
}
})
const imagePreview = (imgUrl: string) => {
createImageViewer({
zIndex: 9999999,
@ -469,6 +444,26 @@ const getIngredientInfoListByType = (type) => {
return that.ingredientInfoList.filter(item => item.type === type)
}
const toBase64 = async () =>{
let svgElement = document.getElementById(that.svgId);
console.log("svg2canvas",domtoimage)
domtoimage.toPng(svgElement)
.then((dataUrl) => {
that.previewData = dataUrl;
that.previewUrl =""
//
// const link = document.createElement('a');
// link.href = dataUrl;
// link.download = 'image.png';
// link.click();
})
.catch((error) => {
console.error('转换失败:', error);
});
}
const deleteList = (item, index) => {
item.dataInfo.splice(index, 1)
resetData();
@ -533,7 +528,6 @@ const loadConfig = (config: object, propData = {}) => {
that.pageConfig = config.pageConfig
that.data = config.data
that.propInfo = {...propData}
that.sizeInfo = that.pageConfig.editArea
// true, conf.pageConfig, conf.data, test
draftDesignEditRef.value.init(false, that.pageConfig, that.data, that.propInfo)
@ -594,11 +588,11 @@ const queryUseLabel = (label) => {
}
const showPng = () => {
that.hideCreate = true;
if (that.pageConfig && that.pageConfig.background) {
loading.value = true
setTimeout(() => {
draftDesignEditRef.value.toPngUrl((url) => {
draftDesignEditRef.value.toSVGData((url) => {
that.previewUrl = url
const info = draftDesignEditRef.value.getPropInfo();
that.propInfo = {
@ -630,52 +624,37 @@ const changeType = () => {
previewByDraftDesignId(that.draftDesignId, that.propInfo)
}
const getPropInfo = () => {
if (that.changeCount > 0) {
return new Promise((resolve) => {
draftDesignEditRef.value.init(false, that.pageConfig, that.data, that.propInfo).then(() => {
setTimeout(() => {
//
draftDesignEditRef.value.toPngUrl((url) => {
that.previewData = url
const info = draftDesignEditRef.value.getPropInfo();
resolve({
draftDesignData: draftDesignEditRef.value.getJson(),
propOrderByList: info.propOrderByList,
// 稿id
draftDesignId: that.draftDesignId,
previewImage: that.previewData,
propInfo: that.propInfo
})
}, {
widthScale: 6,
heightScale: 6
//
return new Promise((resolve) => {
//
draftDesignEditRef.value.toSVGData((url) => {
that.previewUrl = url
that.hideCreate = false;
let svgElement = document.getElementById(that.svgId);
domtoimage.toPng(svgElement)
.then((dataUrl) => {
that.previewData = dataUrl;
that.hideCreate = true;
that.previewUrl =""
const info = draftDesignEditRef.value.getPropInfo();
resolve({
draftDesignData: draftDesignEditRef.value.getJson(),
propOrderByList: info.propOrderByList,
// 稿id
draftDesignId: that.draftDesignId,
previewImage: that.previewData,
propInfo: that.propInfo
})
}, 400)
})
})
} else {
//
return new Promise((resolve) => {
//
draftDesignEditRef.value.toPngUrl((url) => {
that.previewData = url
const info = draftDesignEditRef.value.getPropInfo();
resolve({
draftDesignData: draftDesignEditRef.value.getJson(),
propOrderByList: info.propOrderByList,
// 稿id
draftDesignId: that.draftDesignId,
previewImage: that.previewData,
propInfo: that.propInfo
})
}, {
widthScale: 6,
heightScale: 6
})
.catch((error) => {
console.error('转换失败:', error);
});
}, {
widthScale: 6,
heightScale: 6
})
}
})
}
const submit = async () => {
const info = await getPropInfo();

View File

@ -168,8 +168,8 @@ const addNew = async () => {
shape: ShapeType.vueShapeImage,
data: {
label: '',
width: 40,
height: 40,
width: 32,
height: 32,
shape: VueCellShapeType.Image,
style: {
shape:{

View File

@ -181,20 +181,22 @@ export default defineComponent({
// this.cellInfo.showInput = val
},
changSize(size: any) {
if(size && size.width){
this.sizeWInfo.width = size.width;
this.sizeWInfo.height = size.height;
this.minSize = Math.min(size.height, size.width)
let s = size.height + 12;
if (s > 60) {
s = s + s / 3
}
if (s < 6) {
s = 6
} else if (s >= 1000) {
s = 1000
}
this.fontSize = s;
}
this.sizeWInfo.width = size.width;
this.sizeWInfo.height = size.height;
this.minSize = Math.min(size.height, size.width)
let s = size.height + 12;
if (s > 60) {
s = s + s / 3
}
if (s < 6) {
s = 6
} else if (s >= 1000) {
s = 1000
}
this.fontSize = s;
this.changeFontSize();
},
changeFontSize() {

View File

@ -6,6 +6,22 @@
:class="{ 'node-content-group' : cellInfo.editMode && cellInfo.propGroupId }"
:title="cellInfo.propGroupName"
v-reSize="changSize">
<img
:src="hrefBase64 || cellInfo.style.shape.href" x="0" y="0"
style="width: 100%;height: 100%;"
:style="{
width: '100%',
height: '100%',
fillOpacity: cellInfo.style.shape.fillOpacity,
strokeDasharray: cellInfo.style.shape.strokeDasharray,
strokeDashoffset: cellInfo.style.shape.strokeDashoffset,
opacity: cellInfo.style.shape.opacity,
transform: cellInfo.style.shape.transform,
clipPath: cellInfo.style.shape.clipPath,
filter: cellInfo.style.shape.filter
}"
/>
<svg
style="position: absolute;
width: 100%;height: 100%;
@ -13,20 +29,8 @@
transform: scale(0.1); "
:style="svgStyle"
>
/>
<image
:href="hrefBase64 || cellInfo.style.shape.href" x="0" y="0"
style="width: 100%;height: 100%;"
:fill-opacity="cellInfo.style.shape.fillOpacity"
:stroke-dasharray="cellInfo.style.shape.strokeDasharray"
:stroke-dashoffset="cellInfo.style.shape.strokeDashoffset"
:opacity="cellInfo.style.shape.opacity"
:transform="cellInfo.style.shape.transform"
:clip-path="cellInfo.style.shape.clipPath"
:filter="cellInfo.style.shape.filter"
/>
</svg>
</div>
</template>
@ -110,7 +114,6 @@ export default defineComponent({
fillColor: '', //
fillOpacity: '', //
href: '',
hrefBase64: null,
opacity: '', //
strokeDashoffset: '', // 线
strokeLinecap: undefined, // 线"round" | "butt" | "square" | "inherit" | undefined
@ -194,6 +197,9 @@ export default defineComponent({
setInput(val: boolean) {
},
changSize(size: any) {
if(!size){
return;
}
this.sizeWInfo.width = size.width;
this.sizeWInfo.height = size.height;
this.minSize = Math.min(size.height, size.width)
@ -206,7 +212,6 @@ export default defineComponent({
} else if (s >= 1000) {
s = 1000
}
// this.nodeInfo.store.data.size.width = size.width;
this.fontSize = s;
this.changeFontSize();
@ -235,7 +240,7 @@ export default defineComponent({
y: 0, // y
rx: 0, // x
ry: 0, // y
fillColor: '#000000', //
fillColor: 'rgba(0,0,0,0)', //
href: '',
label: '图片',
fillOpacity: '', //
@ -253,11 +258,21 @@ export default defineComponent({
}
}, info)
if(this.cellInfo.style.shape.href){
if(!this.hrefBase64 && this.cellInfo.style.shape.href && this.cellInfo.style.shape.href.indexOf("data:image") < 0){
// DataUri.imageToDataUri(this.cellInfo.style.shape.href,
// function (nu, url) {
// console.log("base64 ")
// //
// // @ts-ignore
// this.hrefBase64 = url; //
// }
// );
convertImageToBase64(this.cellInfo.style.shape.href).then((res)=>{
// @ts-ignore
// this.hrefBase64 = res
this.cellInfo.style.shape.href = res
// @ts-ignore
this.hrefBase64 = res
console.log("base64 完成")
// this.cellInfo.style.shape.href = res
})
}
setTimeout(() => {

View File

@ -68,12 +68,12 @@ export const graphOptions = (elId:string, viewMode = false) => {
vertexDeletable: true // 边的路径点是否可以被删除
}, // 对齐线
snapline: true, // 撤销/重做
snapline: viewMode, // 撤销/重做
history: !viewMode, //
// 显示网格
grid: {
visible: true,
visible: !viewMode,
size: 2, // 网格大小
type: 'doubleMesh', // // 'dot' | 'fixedDot' | 'mesh'
args: [{
@ -91,7 +91,7 @@ export const graphOptions = (elId:string, viewMode = false) => {
},
panning: {
// 画布移动
enabled: false,
enabled: viewMode,
pageVisible: false, // 是否分页
pageBreak: true,
pannable: true,// 是否平移

View File

@ -277,7 +277,7 @@ const rightKeyMenu = computed(() => {
value: 'mergeGroup',
icon: 'icon-lk_cell_add',
disabled: disabledMenu.value,
label: '设置洗涤说明',
label: '设置图文变量',
handler: (item) => {
const cells = that.selectedCellsList
if (cells.length === 0) {
@ -302,7 +302,7 @@ const rightKeyMenu = computed(() => {
value: 'mergeGroup',
icon: 'icon-lk_cell_tree',
disabled: disabledMenu.value,
label: '设为属性项',
label: '设为变量',
handler: (item) => {
const cells = that.selectedCellsList
if (cells.length === 0) {
@ -470,7 +470,7 @@ const init = (isDesignMode: boolean, bgConfig: any, data = {}, propDataInfo = {}
size: 'auto auto',
opacity: 1,
angle: 20,
color: '#F5F7FD',
color: '#F5F7FD',
...bgConfig.background || {}
},
} as any
@ -481,19 +481,22 @@ const init = (isDesignMode: boolean, bgConfig: any, data = {}, propDataInfo = {}
height: maxSize,
}
graph = new Graph(options)
//
graph.use(
new Scroller({
enabled: true,
pageVisible: true, //
pageBreak: false,
pannable: true,//
// pageWidth: that.pageConfig.editArea.width * 10,
// pageHeight: that.pageConfig.editArea.height * 10,
// modifiers: ['ctrl', 'meta'],
}),
)
if (that.editState) {
//
graph.use(
new Scroller({
enabled: true,
pageVisible: true, //
pageBreak: false,
pannable: true,//
// pageWidth: that.pageConfig.editArea.width * 10,
// pageHeight: that.pageConfig.editArea.height * 10,
// modifiers: ['ctrl', 'meta'],
}),
)
// 线
graph.use(
new Snapline({
@ -700,6 +703,7 @@ const toPngUrl = (callback: (url: string) => void, options?: {
let widthScale = options && options.widthScale ? options.widthScale : 5
let heightScale = options && options.heightScale ? options.heightScale : 5
graph.toPNG((dataUri) => {
that.previewUrl = dataUri;
callback(that.previewUrl)
@ -714,9 +718,42 @@ const toPngUrl = (callback: (url: string) => void, options?: {
bottom: 0
},
quality: 1,
copyStyles: true,
...options
})
}
const toSVGData = (callback: (url: string) => void, options?: {
width: number,
height: number,
widthScale: number,
heightScale: number,
padding: {
top: number,
left: number,
right: number,
bottom: number
}
}) => {
let widthScale = options && options.widthScale ? options.widthScale : 5
let heightScale = options && options.heightScale ? options.heightScale : 5
graph.toSVG((dataUri) => {
that.previewUrl = dataUri;
callback(that.previewUrl)
}, {
viewBox: {
x: 0,
y: 0,
width: that.pageConfig.width * (widthScale),
height: that.pageConfig.height * (heightScale),
},
preserveDimensions:{
width: that.pageConfig.width * (widthScale),
height: that.pageConfig.height * (heightScale),
},
})
}
const setPropList = (propDataInfo) => {
const keys = Object.keys(propDataInfo)
for (let i = 0; i < keys.length; i++) {
@ -937,7 +974,9 @@ const getDeviceDPI = () => {
}
let rulerContainer = document.createElement('div');
const addDrawRuler = () => {
if(!that.editState){
return;
}
//
const dpi = getDeviceDPI();
const mmPerInch = 25.4; // 1 = 25.4
@ -1601,6 +1640,7 @@ defineExpose({
init,
getPropInfo,
toPngUrl,
toSVGData,
clearData,
getJson,
})

View File

@ -85,28 +85,7 @@
<span>{{ scope.$index + 1 }}</span>
</template>
</el-table-column>
<el-table-column prop="locale" label="地区语言" width="180">
<template #header>
<div>
<span class="color-red">*</span>
<span>地区语言</span>
</div>
</template>
<template #default="scope">
<div
:class="{ 'duplicate-tips' : duplicateCheck(scope.row.locale) }">
<el-select v-model="scope.row.locale" placeholder="地区语言">
<el-option
v-for="dict in getStrDictOptions(DICT_TYPE.LANGUAGE_LOCALE)"
:key="`${dict.value}`"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</div>
</template>
</el-table-column>
<el-table-column prop="value">
<template #header>
@ -137,16 +116,7 @@
</el-collapse>
</div>
</el-form-item>
<el-form-item label="地区标识" prop="locale">
<el-select v-model="formData.locale" placeholder="请选择语言标识">
<el-option
v-for="dict in getStrDictOptions(DICT_TYPE.LANGUAGE_LOCALE)"
:key="`${dict.value}`"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="启用状态" prop="enabled">
<el-checkbox v-model="formData.enabled">是否启用</el-checkbox>
</el-form-item>

View File

@ -54,6 +54,7 @@
"crypto-js": "^4.2.0",
"dayjs": "^1.11.10",
"diagram-js": "^12.8.0",
"dom-to-image": "^2.6.0",
"driver.js": "^1.3.1",
"echarts": "^5.5.0",
"echarts-wordcloud": "^2.1.0",

View File

@ -13,7 +13,7 @@
<template #footer>
<span class="dialog-footer">
<el-button @click="updateVisible(false)"> </el-button>
<el-button type="primary" @click="submit"></el-button>
<el-button type="primary" @click="submit">批稿</el-button>
</span>
</template>
</Dialog>
@ -60,10 +60,13 @@ const previewByDraftDesignId = (id: string | number,prop={})=>{
that.loading = false;
},100)
}
const submit = async ()=>{
const res = await designPropEditRef.value.getPropInfo()
emit("submit",res);
updateVisible(false)
const submit = ()=>{
useMessage().confirm("是否提交?").then(async (r) => {
const res = await designPropEditRef.value.getPropInfo()
emit("submit",res);
updateVisible(false)
})
}
defineExpose({
preview,

View File

@ -1,93 +1,88 @@
<!-- eslint-disable vue/this-in-template -->
<template>
<div style="max-height: 90vh; overflow:auto;" v-loading="loading">
<span>
仅供参考(for reference only),绿色边框属于边界
</span>
<div style="padding-bottom: 4px">
<el-button @click="that.currentZoom -= 1" :disabled="that.currentZoom <= 1">-
</el-button>
<el-select v-model="that.currentZoom" style="width: 90px">
<el-option
v-for="item in zoomList"
:key="item.value"
:label="(Math.floor(item.value))"
:value="item.value"
/>
<el-option
v-if="!zoomList.some(o => o.value === that.currentZoom)"
:label="(Math.floor(that.currentZoom))"
:value="that.currentZoom"
/>
</el-select>
<el-button @click="that.currentZoom += 1" :disabled="that.currentZoom >= 30">+
</el-button>
<el-checkbox style="margin: 8px" v-model="that.reView">实时预览</el-checkbox>
<el-button
v-show="!that.reView"
style="margin: 8px"
type="primary"
size="small"
@click="updateDesign">
<span>更新</span>
<span
style="color: #ff0000;font-size: 20px; padding-left: 4px">{{
that.changeCount > 0 ? '*' : ''
}}</span>
</el-button>
</div>
<div v-if="that.sizeInfo" style="margin-left: 60px" :title="`${that.sizeInfo.width}mm`">
<span>
:{{ that.sizeInfo.width }}mm
</span>
</div>
<div>
<div
style="display: flex;">
<div v-if="that.sizeInfo" :title="`${that.sizeInfo.height}mm`">
<span class="vertical-text">
{{ that.sizeInfo.height }}
:class ="{ 'hidden-div': that.hideCreate}"
:id="that.svgId"
:style="{
width: `${imageSize.width * 6}px`,
height: `${imageSize.height * 6}px`,
}">
<div v-if="that.previewUrl" v-html="that.previewUrl" >
</div>
</div>
<div style="max-height: 90vh; overflow:auto;" v-loading="loading">
<span>
仅供参考(for reference only)
</span>
<div style="padding-bottom: 4px">
<el-checkbox style="margin: 8px" v-model="that.reView">实时预览</el-checkbox>
<el-button
v-show="!that.reView"
style="margin: 8px"
type="primary"
size="small"
@click="updateDesign">
<span>更新</span>
<span
style="color: #ff0000;font-size: 20px; padding-left: 4px">{{
that.changeCount > 0 ? '*' : ''
}}</span>
</el-button>
</div>
<div>
<el-alert
title="按住鼠标左键进行拖动按住Ctrl 滚动鼠标进行缩小放放大"
type="info" effect="dark"/>
</div>
<div v-if="that.sizeInfo" :title="`${that.sizeInfo.width}mm`">
<span>
:{{ that.sizeInfo.width }}mm {{ that.sizeInfo.height }}
</span>
<span>mm</span>
</div>
<div v-if="that.previewUrl" style="margin: 2px; box-shadow: 0 0 1px 1px rgb(0,255,0)">
<el-image
:title="showImgTitle"
@click="imagePreview(that.previewUrl)"
v-loading="loading"
:src="that.previewUrl"/>
</div>
<div class="flex flex-col">
<div>
<el-form label-width="180px">
<el-form-item label="风格样式" v-show="that.draftDesignList.length > 1">
<div class="flex ml-3">
<div>
<el-select class="min-w-100" v-model="that.draftDesignId" @change="changeType">
<el-option
v-for="(item) in that.draftDesignList"
:key="item.id"
:label="item.label"
:value="item.id"
/>
</el-select>
</div>
</div>
</el-form-item>
</el-form>
</div>
<div style="width: 100%" v-if="that.propOrderByList && that.propOrderByList.length > 0">
<el-scrollbar height="600px">
<el-form label-width="180px">
<el-form-item
v-for="(tmp) in that.propOrderByList"
:key="tmp.key"
:label="getLabelName(that.propInfo[tmp.key])">
<div
v-if="that.propInfo[tmp.key].multiLanguage && that.propInfo[tmp.key].shape === ShapeType.vueTextCell">
<div
style="padding: 4px">
<div style="display: flex;align-items: center;">
</div>
<el-row>
<el-col :span="11">
<div
:class ="{ 'hidden-div': false }" style="width:100%;height: 580px; border: 1px solid #090805">
<DraftDesign ref="draftDesignEditRef" @init-succeed="initSucceed"/>
</div>
</el-col>
<el-col :span="12">
<div style="display: flex;">
<div class="flex flex-col">
<div>
<el-form label-width="180px">
<el-form-item label="风格样式" v-show="that.draftDesignList.length > 1">
<div class="flex ml-3">
<div>
<el-select class="min-w-100" v-model="that.draftDesignId" @change="changeType">
<el-option
v-for="(item) in that.draftDesignList"
:key="item.id"
:label="item.label"
:value="item.id"
/>
</el-select>
</div>
</div>
</el-form-item>
</el-form>
</div>
<div style="width: 100%" v-if="that.propOrderByList && that.propOrderByList.length > 0">
<el-scrollbar height="600px">
<el-form label-width="180px">
<el-form-item
v-for="(tmp) in that.propOrderByList"
:key="tmp.key"
:label="getLabelName(that.propInfo[tmp.key])">
<div
v-if="that.propInfo[tmp.key].multiLanguage && that.propInfo[tmp.key].shape === ShapeType.vueTextCell">
<div
style="padding: 4px">
<div style="display: flex;align-items: center;">
<span>
<i
v-if="that.propInfo[tmp.key].canInput"
@ -96,56 +91,56 @@
<i v-else class="icon-lk_cell_add" style="font-size: 20px"> </i>
</span>
<el-select-v2
v-model="that.propInfo[tmp.key].dataInfo[0].showLabel"
filterable
:options="getIngredientInfoListByType(that.propInfo[tmp.key].groupType)"
placeholder="Please select"
@change="changeData(-1,tmp.key)"
size="large"
style="min-width: 280px;width: 100%"
/>
<div v-if="that.propInfo[tmp.key].groupType === '1'">
<div
style="display: flex;align-items: center; margin-left: 10px; width: 220px">
<el-row>
<el-col span="4">
<div>占比</div>
</el-col>
<el-col span="14">
<el-input-number
:min="-1" :max="100"
v-model="that.propInfo[tmp.key].dataInfo[0].ratio"
@change="changeData(0,tmp.key)"
/>
</el-col>
<el-col span="4">
<div> %</div>
</el-col>
</el-row>
</div>
</div>
<el-button
v-if="that.propInfo[tmp.key].canChange"
@click="deleteList(that.propInfo[tmp.key],index)">
<i class="icon-lk_delete"> </i>
</el-button>
</div>
</div>
<el-select-v2
v-model="that.propInfo[tmp.key].dataInfo[0].showLabel"
filterable
:options="getIngredientInfoListByType(that.propInfo[tmp.key].groupType)"
placeholder="Please select"
@change="changeData(-1,tmp.key)"
size="large"
style="min-width: 280px;width: 100%"
/>
<div v-if="that.propInfo[tmp.key].groupType === '1'">
<div
style="display: flex;align-items: center; margin-left: 10px; width: 220px">
<el-row>
<el-col span="4">
<div>占比</div>
</el-col>
<el-col span="14">
<el-input-number
:min="-1" :max="100"
v-model="that.propInfo[tmp.key].dataInfo[0].ratio"
@change="changeData(0,tmp.key)"
/>
</el-col>
<el-col span="4">
<div> %</div>
</el-col>
</el-row>
</div>
</div>
<el-button
v-if="that.propInfo[tmp.key].canChange"
@click="deleteList(that.propInfo[tmp.key],index)">
<i class="icon-lk_delete"> </i>
</el-button>
</div>
</div>
<el-button
v-if="that.propInfo[tmp.key].canChange"
@click="appendList(that.propInfo[tmp.key])">
添加
</el-button>
</div>
<el-button
v-if="that.propInfo[tmp.key].canChange"
@click="appendList(that.propInfo[tmp.key])">
添加
</el-button>
</div>
<div v-else-if="!that.propInfo[tmp.key].isCombo">
<div
v-for="(text,index) in that.propInfo[tmp.key].dataInfo"
:key="index"
style="padding: 4px">
<div style="display: flex;align-items: center;">
<div v-else-if="!that.propInfo[tmp.key].isCombo">
<div
v-for="(text,index) in that.propInfo[tmp.key].dataInfo"
:key="index"
style="padding: 4px">
<div style="display: flex;align-items: center;">
<span>
<i
v-if="that.propInfo[tmp.key].canInput"
@ -153,120 +148,119 @@
style="font-size: 20px"> </i>
<i v-else class="icon-lk_cell_add" style="font-size: 20px"> </i>
</span>
<el-autocomplete
v-if="that.propInfo[tmp.key].canInput"
v-model="that.propInfo[tmp.key].dataInfo[index].showLabel"
:fetch-suggestions="querySearch"
clearable
class="inline-input w-50"
placeholder="Please Input"
@change="changeData"
@select="changeData"
/>
<el-autocomplete
v-if="that.propInfo[tmp.key].canInput"
v-model="that.propInfo[tmp.key].dataInfo[index].showLabel"
:fetch-suggestions="querySearch"
clearable
class="inline-input w-50"
placeholder="Please Input"
@change="changeData"
@select="changeData"
/>
<el-select-v2
v-else
v-model="that.propInfo[tmp.key].dataInfo[index].showLabel"
filterable
:options="getIngredientInfoListByType(that.propInfo[tmp.key].groupType)"
placeholder="Please select"
@change="changeData(index,tmp.key)"
size="large"
style="min-width: 280px;width: 100%"
/>
<div v-if="that.propInfo[tmp.key].groupType === '1'">
<el-select-v2
v-else
v-model="that.propInfo[tmp.key].dataInfo[index].showLabel"
filterable
:options="getIngredientInfoListByType(that.propInfo[tmp.key].groupType)"
placeholder="Please select"
@change="changeData(index,tmp.key)"
size="large"
style="min-width: 280px;width: 100%"
/>
<div v-if="that.propInfo[tmp.key].groupType === '1'">
<div
style="display: flex;align-items: center; margin-left: 10px; width: 220px">
<el-row>
<el-col span="4">
<div>占比</div>
</el-col>
<el-col span="14">
<el-input-number
:min="-1" :max="100"
v-model="that.propInfo[tmp.key].dataInfo[index].ratio"
@change="changeData(index,tmp.key)"
/>
</el-col>
<el-col span="4">
<div> %</div>
</el-col>
</el-row>
</div>
</div>
<el-button
v-if="that.propInfo[tmp.key].canChange"
@click="deleteList(that.propInfo[tmp.key],index)">
<i class="icon-lk_delete"> </i>
</el-button>
</div>
</div>
<div
style="display: flex;align-items: center; margin-left: 10px; width: 220px">
<el-row>
<el-col span="4">
<div>占比</div>
</el-col>
<el-col span="14">
<el-input-number
:min="-1" :max="100"
v-model="that.propInfo[tmp.key].dataInfo[index].ratio"
@change="changeData(index,tmp.key)"
/>
</el-col>
<el-col span="4">
<div> %</div>
</el-col>
</el-row>
</div>
</div>
<el-button
v-if="that.propInfo[tmp.key].canChange"
@click="deleteList(that.propInfo[tmp.key],index)">
<i class="icon-lk_delete"> </i>
</el-button>
</div>
</div>
<el-button
v-if="that.propInfo[tmp.key].canChange"
@click="appendList(that.propInfo[tmp.key])">
添加
</el-button>
</div>
<el-button
v-if="that.propInfo[tmp.key].canChange"
@click="appendList(that.propInfo[tmp.key])">
添加
</el-button>
</div>
<div v-else-if="that.propInfo[tmp.key].shape === ShapeType.vueShapeImage">
<div
v-for="(img,index) in that.propInfo[tmp.key].dataInfo"
:key="index" style="display: flex">
<div class="img-box" v-if="img.url">
<div style="display: flex">
<img :src="img.url" width="60px" height="60px"/>
<el-select-v2
v-model="that.propInfo[tmp.key].dataInfo[0].showLabel"
filterable
:options="washingInfoListByType(that.propInfo[tmp.key].groupType)"
placeholder="Please select"
@change="changeComboData(that.propInfo[tmp.key],that.propInfo[tmp.key].dataInfo[0].showLabel)"
size="large"
style="min-width: 280px;width: 100%"
>
<template #default="{ item }">
<div style="display: flex;">
<img :src="item.url" width="30px" height="30px"/>
<span>
<div v-else-if="that.propInfo[tmp.key].shape === ShapeType.vueShapeImage">
<div
v-for="(img,index) in that.propInfo[tmp.key].dataInfo"
:key="index" style="display: flex">
<div class="img-box" v-if="img.url">
<div style="display: flex">
<img :src="img.url" width="60px" height="60px"/>
<el-select-v2
v-model="that.propInfo[tmp.key].dataInfo[0].showLabel"
filterable
:options="washingInfoListByType(that.propInfo[tmp.key].groupType)"
placeholder="Please select"
@change="changeComboData(that.propInfo[tmp.key],that.propInfo[tmp.key].dataInfo[0].showLabel)"
size="large"
style="min-width: 280px;width: 100%"
>
<template #default="{ item }">
<div style="display: flex;">
<img :src="item.url" width="30px" height="30px"/>
<span>
{{ item.label }}
</span>
</div>
</template>
</el-select-v2>
</div>
</div>
<div v-else-if="img.label">
<el-input v-model="img.label" disabled/>
</div>
<el-button
v-if="that.propInfo[tmp.key].canChange"
@click="deleteList(that.propInfo[tmp.key],index)">
<i class="icon-lk_delete"> </i>
</el-button>
</div>
<el-button
v-if="that.propInfo[tmp.key].canChange"
@click="appendList(that.propInfo[tmp.key])">
添加
</el-button>
</div>
</template>
</el-select-v2>
</div>
</div>
<div v-else-if="img.label">
<el-input v-model="img.label" disabled/>
</div>
<el-button
v-if="that.propInfo[tmp.key].canChange"
@click="deleteList(that.propInfo[tmp.key],index)">
<i class="icon-lk_delete"> </i>
</el-button>
</div>
<el-button
v-if="that.propInfo[tmp.key].canChange"
@click="appendList(that.propInfo[tmp.key])">
添加
</el-button>
</div>
</div>
</el-form-item>
</el-form>
</el-scrollbar>
</div>
</div>
</el-form-item>
</el-form>
</el-scrollbar>
</div>
</div>
</div>
</div>
</el-col>
<div
:class="{ 'hidden-div': true }">
<DraftDesign ref="draftDesignEditRef" @init-succeed="initSucceed"/>
</div>
</div>
</el-row>
</div>
</div>
</template>
<script lang="ts" setup name="DynamicPropConfig">
@ -282,13 +276,14 @@ import {replaceDomain} from "@/utils";
import * as FileApi from "@/api/infra/file";
import {useLocaleStore} from "@/store/modules/locale";
import {ProductInfoApi} from "@/api/oms/productinfo";
import {convertImageToBase64} from "@/components/DraftDesign/utils/Dpi";
import domtoimage from 'dom-to-image';
//
const localeStore = useLocaleStore()
const emit = defineEmits(['change', 'initSucceed'])
const draftDesignEditRef = ref()
const that = reactive({
svgId: "svg_"+Math.random().toString(36).substring(2),
hideCreate: true,
propInfo: {
reView: true,
groupName: '', //
@ -321,38 +316,7 @@ const that = reactive({
data: {},
show: false,
})
const showImgTitle = computed(() => {
if (that.sizeInfo) {
return '宽:' + that.sizeInfo.width + 'mm 高:' + that.sizeInfo.height + 'mm'
}
})
const zoomList = [
{
value: 1,
label: '1'
},
{
value: 5,
label: '5'
},
{
value: 6,
label: '6'
},
{
value: 10,
label: '10'
}, {
value: 15,
label: '15'
}, {
value: 20,
label: '20'
}, {
value: 30,
label: '30'
},
]
const currentLocale = computed(() => localeStore.getCurrentLocale)
watch(() => that.currentZoom, () => {
showPng();
@ -364,7 +328,18 @@ const querySearch = (queryString: string, cb: any) => {
}) : that.ingredientInfoList
cb(results)
}
const imageSize =computed(()=>{
if(that.sizeInfo){
return {
width: that.sizeInfo.width,
height: that.sizeInfo.height
}
}
return {
width: 10,
height: 10
}
})
const imagePreview = (imgUrl: string) => {
createImageViewer({
zIndex: 9999999,
@ -469,6 +444,26 @@ const getIngredientInfoListByType = (type) => {
return that.ingredientInfoList.filter(item => item.type === type)
}
const toBase64 = async () =>{
let svgElement = document.getElementById(that.svgId);
console.log("svg2canvas",domtoimage)
domtoimage.toPng(svgElement)
.then((dataUrl) => {
that.previewData = dataUrl;
that.previewUrl =""
//
// const link = document.createElement('a');
// link.href = dataUrl;
// link.download = 'image.png';
// link.click();
})
.catch((error) => {
console.error('转换失败:', error);
});
}
const deleteList = (item, index) => {
item.dataInfo.splice(index, 1)
resetData();
@ -533,7 +528,6 @@ const loadConfig = (config: object, propData = {}) => {
that.pageConfig = config.pageConfig
that.data = config.data
that.propInfo = {...propData}
that.sizeInfo = that.pageConfig.editArea
// true, conf.pageConfig, conf.data, test
draftDesignEditRef.value.init(false, that.pageConfig, that.data, that.propInfo)
@ -594,11 +588,11 @@ const queryUseLabel = (label) => {
}
const showPng = () => {
that.hideCreate = true;
if (that.pageConfig && that.pageConfig.background) {
loading.value = true
setTimeout(() => {
draftDesignEditRef.value.toPngUrl((url) => {
draftDesignEditRef.value.toSVGData((url) => {
that.previewUrl = url
const info = draftDesignEditRef.value.getPropInfo();
that.propInfo = {
@ -630,52 +624,37 @@ const changeType = () => {
previewByDraftDesignId(that.draftDesignId, that.propInfo)
}
const getPropInfo = () => {
if (that.changeCount > 0) {
return new Promise((resolve) => {
draftDesignEditRef.value.init(false, that.pageConfig, that.data, that.propInfo).then(() => {
setTimeout(() => {
//
draftDesignEditRef.value.toPngUrl((url) => {
that.previewData = url
const info = draftDesignEditRef.value.getPropInfo();
resolve({
draftDesignData: draftDesignEditRef.value.getJson(),
propOrderByList: info.propOrderByList,
// 稿id
draftDesignId: that.draftDesignId,
previewImage: that.previewData,
propInfo: that.propInfo
})
}, {
widthScale: 6,
heightScale: 6
//
return new Promise((resolve) => {
//
draftDesignEditRef.value.toSVGData((url) => {
that.previewUrl = url
that.hideCreate = false;
let svgElement = document.getElementById(that.svgId);
domtoimage.toPng(svgElement)
.then((dataUrl) => {
that.previewData = dataUrl;
that.hideCreate = true;
that.previewUrl =""
const info = draftDesignEditRef.value.getPropInfo();
resolve({
draftDesignData: draftDesignEditRef.value.getJson(),
propOrderByList: info.propOrderByList,
// 稿id
draftDesignId: that.draftDesignId,
previewImage: that.previewData,
propInfo: that.propInfo
})
}, 400)
})
})
} else {
//
return new Promise((resolve) => {
//
draftDesignEditRef.value.toPngUrl((url) => {
that.previewData = url
const info = draftDesignEditRef.value.getPropInfo();
resolve({
draftDesignData: draftDesignEditRef.value.getJson(),
propOrderByList: info.propOrderByList,
// 稿id
draftDesignId: that.draftDesignId,
previewImage: that.previewData,
propInfo: that.propInfo
})
}, {
widthScale: 6,
heightScale: 6
})
.catch((error) => {
console.error('转换失败:', error);
});
}, {
widthScale: 6,
heightScale: 6
})
}
})
}
const submit = async () => {
const info = await getPropInfo();

View File

@ -168,8 +168,8 @@ const addNew = async () => {
shape: ShapeType.vueShapeImage,
data: {
label: '',
width: 40,
height: 40,
width: 32,
height: 32,
shape: VueCellShapeType.Image,
style: {
shape:{

View File

@ -181,20 +181,22 @@ export default defineComponent({
// this.cellInfo.showInput = val
},
changSize(size: any) {
if(size && size.width){
this.sizeWInfo.width = size.width;
this.sizeWInfo.height = size.height;
this.minSize = Math.min(size.height, size.width)
let s = size.height + 12;
if (s > 60) {
s = s + s / 3
}
if (s < 6) {
s = 6
} else if (s >= 1000) {
s = 1000
}
this.fontSize = s;
}
this.sizeWInfo.width = size.width;
this.sizeWInfo.height = size.height;
this.minSize = Math.min(size.height, size.width)
let s = size.height + 12;
if (s > 60) {
s = s + s / 3
}
if (s < 6) {
s = 6
} else if (s >= 1000) {
s = 1000
}
this.fontSize = s;
this.changeFontSize();
},
changeFontSize() {

View File

@ -6,6 +6,22 @@
:class="{ 'node-content-group' : cellInfo.editMode && cellInfo.propGroupId }"
:title="cellInfo.propGroupName"
v-reSize="changSize">
<img
:src="hrefBase64 || cellInfo.style.shape.href" x="0" y="0"
style="width: 100%;height: 100%;"
:style="{
width: '100%',
height: '100%',
fillOpacity: cellInfo.style.shape.fillOpacity,
strokeDasharray: cellInfo.style.shape.strokeDasharray,
strokeDashoffset: cellInfo.style.shape.strokeDashoffset,
opacity: cellInfo.style.shape.opacity,
transform: cellInfo.style.shape.transform,
clipPath: cellInfo.style.shape.clipPath,
filter: cellInfo.style.shape.filter
}"
/>
<svg
style="position: absolute;
width: 100%;height: 100%;
@ -13,20 +29,8 @@
transform: scale(0.1); "
:style="svgStyle"
>
/>
<image
:href="hrefBase64 || cellInfo.style.shape.href" x="0" y="0"
style="width: 100%;height: 100%;"
:fill-opacity="cellInfo.style.shape.fillOpacity"
:stroke-dasharray="cellInfo.style.shape.strokeDasharray"
:stroke-dashoffset="cellInfo.style.shape.strokeDashoffset"
:opacity="cellInfo.style.shape.opacity"
:transform="cellInfo.style.shape.transform"
:clip-path="cellInfo.style.shape.clipPath"
:filter="cellInfo.style.shape.filter"
/>
</svg>
</div>
</template>
@ -110,7 +114,6 @@ export default defineComponent({
fillColor: '', //
fillOpacity: '', //
href: '',
hrefBase64: null,
opacity: '', //
strokeDashoffset: '', // 线
strokeLinecap: undefined, // 线"round" | "butt" | "square" | "inherit" | undefined
@ -194,6 +197,9 @@ export default defineComponent({
setInput(val: boolean) {
},
changSize(size: any) {
if(!size){
return;
}
this.sizeWInfo.width = size.width;
this.sizeWInfo.height = size.height;
this.minSize = Math.min(size.height, size.width)
@ -206,7 +212,6 @@ export default defineComponent({
} else if (s >= 1000) {
s = 1000
}
// this.nodeInfo.store.data.size.width = size.width;
this.fontSize = s;
this.changeFontSize();
@ -235,7 +240,7 @@ export default defineComponent({
y: 0, // y
rx: 0, // x
ry: 0, // y
fillColor: '#000000', //
fillColor: 'rgba(0,0,0,0)', //
href: '',
label: '图片',
fillOpacity: '', //
@ -253,11 +258,21 @@ export default defineComponent({
}
}, info)
if(this.cellInfo.style.shape.href){
if(!this.hrefBase64 && this.cellInfo.style.shape.href && this.cellInfo.style.shape.href.indexOf("data:image") < 0){
// DataUri.imageToDataUri(this.cellInfo.style.shape.href,
// function (nu, url) {
// console.log("base64 ")
// //
// // @ts-ignore
// this.hrefBase64 = url; //
// }
// );
convertImageToBase64(this.cellInfo.style.shape.href).then((res)=>{
// @ts-ignore
// this.hrefBase64 = res
this.cellInfo.style.shape.href = res
// @ts-ignore
this.hrefBase64 = res
console.log("base64 完成")
// this.cellInfo.style.shape.href = res
})
}
setTimeout(() => {

View File

@ -68,12 +68,12 @@ export const graphOptions = (elId:string, viewMode = false) => {
vertexDeletable: true // 边的路径点是否可以被删除
}, // 对齐线
snapline: true, // 撤销/重做
snapline: viewMode, // 撤销/重做
history: !viewMode, //
// 显示网格
grid: {
visible: true,
visible: !viewMode,
size: 2, // 网格大小
type: 'doubleMesh', // // 'dot' | 'fixedDot' | 'mesh'
args: [{
@ -91,7 +91,7 @@ export const graphOptions = (elId:string, viewMode = false) => {
},
panning: {
// 画布移动
enabled: false,
enabled: viewMode,
pageVisible: false, // 是否分页
pageBreak: true,
pannable: true,// 是否平移

View File

@ -277,7 +277,7 @@ const rightKeyMenu = computed(() => {
value: 'mergeGroup',
icon: 'icon-lk_cell_add',
disabled: disabledMenu.value,
label: '设置洗涤说明',
label: '设置图文变量',
handler: (item) => {
const cells = that.selectedCellsList
if (cells.length === 0) {
@ -302,7 +302,7 @@ const rightKeyMenu = computed(() => {
value: 'mergeGroup',
icon: 'icon-lk_cell_tree',
disabled: disabledMenu.value,
label: '设为属性项',
label: '设为变量',
handler: (item) => {
const cells = that.selectedCellsList
if (cells.length === 0) {
@ -470,7 +470,7 @@ const init = (isDesignMode: boolean, bgConfig: any, data = {}, propDataInfo = {}
size: 'auto auto',
opacity: 1,
angle: 20,
color: '#F5F7FD',
color: '#F5F7FD',
...bgConfig.background || {}
},
} as any
@ -481,19 +481,22 @@ const init = (isDesignMode: boolean, bgConfig: any, data = {}, propDataInfo = {}
height: maxSize,
}
graph = new Graph(options)
//
graph.use(
new Scroller({
enabled: true,
pageVisible: true, //
pageBreak: false,
pannable: true,//
// pageWidth: that.pageConfig.editArea.width * 10,
// pageHeight: that.pageConfig.editArea.height * 10,
// modifiers: ['ctrl', 'meta'],
}),
)
if (that.editState) {
//
graph.use(
new Scroller({
enabled: true,
pageVisible: true, //
pageBreak: false,
pannable: true,//
// pageWidth: that.pageConfig.editArea.width * 10,
// pageHeight: that.pageConfig.editArea.height * 10,
// modifiers: ['ctrl', 'meta'],
}),
)
// 线
graph.use(
new Snapline({
@ -700,6 +703,7 @@ const toPngUrl = (callback: (url: string) => void, options?: {
let widthScale = options && options.widthScale ? options.widthScale : 5
let heightScale = options && options.heightScale ? options.heightScale : 5
graph.toPNG((dataUri) => {
that.previewUrl = dataUri;
callback(that.previewUrl)
@ -714,9 +718,42 @@ const toPngUrl = (callback: (url: string) => void, options?: {
bottom: 0
},
quality: 1,
copyStyles: true,
...options
})
}
const toSVGData = (callback: (url: string) => void, options?: {
width: number,
height: number,
widthScale: number,
heightScale: number,
padding: {
top: number,
left: number,
right: number,
bottom: number
}
}) => {
let widthScale = options && options.widthScale ? options.widthScale : 5
let heightScale = options && options.heightScale ? options.heightScale : 5
graph.toSVG((dataUri) => {
that.previewUrl = dataUri;
callback(that.previewUrl)
}, {
viewBox: {
x: 0,
y: 0,
width: that.pageConfig.width * (widthScale),
height: that.pageConfig.height * (heightScale),
},
preserveDimensions:{
width: that.pageConfig.width * (widthScale),
height: that.pageConfig.height * (heightScale),
},
})
}
const setPropList = (propDataInfo) => {
const keys = Object.keys(propDataInfo)
for (let i = 0; i < keys.length; i++) {
@ -937,7 +974,9 @@ const getDeviceDPI = () => {
}
let rulerContainer = document.createElement('div');
const addDrawRuler = () => {
if(!that.editState){
return;
}
//
const dpi = getDeviceDPI();
const mmPerInch = 25.4; // 1 = 25.4
@ -1601,6 +1640,7 @@ defineExpose({
init,
getPropInfo,
toPngUrl,
toSVGData,
clearData,
getJson,
})

View File

@ -115,7 +115,6 @@ const delItem = () => {
}
const openItem = () => {
designPreviewDialogRef.value.previewByProductId(formData.value.productId, JSON.parse(formData.value.propInfo || '{}'))
}
const getSizeInfo = computed(() => {
if (formData.value.specInfo) {
@ -140,11 +139,11 @@ const submit = (data:any) => {
formData.value.propOrderByList = data.propOrderByList;
formData.value.draftDesignId = data.draftDesignId;
formData.value.previewImage = data.previewImage;
formData.value.draftDesignInfo = data.draftDesignInfo;
formData.value.draftDesignInfo = {...data.draftDesignInfo};
//
formData.value.specInfo = {
...formData.value.specInfo,
mainColor: data.draftDesignInfo.label
mainColor: formData.value.draftDesignInfo.label || "默认"
};
change();
}

View File

@ -0,0 +1,5 @@
ALTER TABLE oms_brand ADD COLUMN `product_count` int DEFAULT 0 COMMENT '产品数量';
ALTER TABLE oms_draft_design_data ADD COLUMN `product_count` int DEFAULT 0 COMMENT '产品数量';
ALTER TABLE oms_saleorder ADD COLUMN `delivery_address` int DEFAULT 0 COMMENT '交货地址';
ALTER TABLE oms_saleorder ADD COLUMN `delivery_remark` int DEFAULT 0 COMMENT '交货备注';