|
|
<template> <div> <el-dialog :close-on-click-modal="false" :title="title" :type="type" :visible.sync="isVisible" :modal-append-to-body="false" :center="true" width="80%" top="50px" class="dialog-wrap"> <el-form ref="ruleForm" :model="params" class="canvas">
<div class="mainContentWarp"> <div class="mainContent"> <div class="canvasContent" ref="canvasContent" :style="{ width: `${canvasWidth}px`, height: `${canvasHeight}px` }" @dragover.prevent @mousedown="laryerMouseDown" @mousemove="laryerMouseMove" @mouseup="laryerMouseUp" @drop="handleDrap" v-if="params.interactionDiagramImage"> <img class="img-bg" ref="canvasBgContent" :src="params.interactionDiagramImage" />
<div class="drap-container-item" v-for="(point, index) in pointList" :key="index" :style="{ top: `${canvasHeight * point.pointY}px`, left: `${canvasWidth * point.pointX}px` }" @mousedown.stop="handleMouseDown($event, point, index)" @click="handleClick(point, index)">
<div :class="showPoint == point ? 'point_source_active' : 'point_source'" /> <!-- :class="[point.pointX < 0.2 ? 'product-detail-right' : (point.pointX > 0.8 ? 'product-detail-left' : 'product-detail-centerv'), point.pointY > 0.8 ? 'product-detail-top' : 'product-detail-bottom']" --> <div class="product-detail" v-if="showPoint == point && (point.product && point.product.productName)"> <div class="product-name">{{ (point.product && point.product.productName) ? point.product.productName : '' }}</div> <div class="product-price">¥{{ (point.product && point.product.price) ? point.product.price : '' }}</div> </div> </div>
</div>
</div> </div> <div class="RightBox"> <div slot="footer" class="btn-wrap"> <el-button type="primary" @click="onSubmit">{{ $t('common.save') }}</el-button> <!-- <el-button @click="isVisible = false">{{ $t('common.cancel') }}</el-button> --> </div>
<el-form-item label="平台类型" hidden> <el-radio-group v-model="params.terminal"> <el-radio :disabled="isDisabled" :label="1">小程序</el-radio> <el-radio :disabled="isDisabled" :label="2">H5</el-radio> <el-radio :disabled="isDisabled" :label="3">APP</el-radio> <el-radio :disabled="isDisabled" :label="4">PC</el-radio> </el-radio-group> </el-form-item>
<el-form-item label="互动图名称"> <el-input v-model="params.interactionDiagramName" maxlength="20" :readonly="isDisabled" onblur="value=value.replace(/(^\s*)|(\s*$)/g, '')" /> </el-form-item>
<el-form-item style="margin-bottom: 5px;margin-top:5px" label="互动图背景"> </el-form-item> <div class="span-wrap"> <el-upload list-type="picture-card" :show-file-list="false" :on-remove="handleRemove" :headers="headers" :data="dataObj" :multiple="false" :on-success="handleImageSuccess" :action="action" :auto-upload="true" :before-upload="beforeUpload"> <i v-if="!params.interactionDiagramImage" slot="trigger" class="el-icon-plus" /> <div v-else class="attr-value-img"> <img class="attr-thumbnail" :src="params.interactionDiagramImage"> </div> </el-upload> <div v-if="params.interactionDiagramImage" class="attr-actions"> <span class="attr-delete" @click="handleRemove()"> <i class="el-icon-delete" /> </span> </div> </div>
<!-- <el-button type="primary" @click="onSubmit">拖动添加互动点</el-button> -->
<el-form-item style="margin-bottom: 5px;margin-top:5px" label="拖动添加互动点"> </el-form-item>
<div class="point_source" @dragstart="handleDrapEvList($event, newPoint)" @dragover.prevent draggable="true"/>
<el-form-item style="margin-bottom: 5px;margin-top:5px" label="互动点信息"> </el-form-item>
<div class="product-list"> <div class="list-group-item" v-for="(point, index) in pointList" :key="index"> <div class="item-index"> {{ (index + 1) }}. </div> <div class="item-right"> <div class="item-btns"> <div class="item-btn-item" @click="selectProduct(point, index)"> 设置商品 </div> <div class="item-btn-item" @click="delComponent(point, index)"> 删除 </div> </div> <div class="item-product"> {{ (point.product && point.product.productName) ? point.product.productName : '未设置商品' }} </div> </div> </div> </div> </div> </el-form>
</el-dialog>
<el-dialog title="选择商品" :visible.sync="productVisible" width="70%" top="50px"> <product-select ref="productSelect"></product-select> <span slot="footer" class="dialog-footer"> <el-button @click="productVisible = false">{{ $t('common.cancel') }}</el-button> <el-button type="primary" @click="productChanged">{{ $t('common.sure') }}</el-button> </span> </el-dialog> </div> </template> <script>
import { interactionDiagramGetById, interactionDiagramAdd, interactionDiagramUpdate } from '@/api/image' import { uploadUrl } from '@/utils/request' import { getToken } from '@/utils/auth' import ProductSelect from '@/components/Product/product-select' import draggable from 'vuedraggable' export default { components: { draggable, ProductSelect },
props: { dialogVisible: { type: Boolean, default: false }, type: { type: String, default: 'add' } }, data() { return { params: { interactionDiagramId: 0, interactionDiagramName: '', interactionDiagramImage: '', imageWidth: 0, imageHeight: 0,//新增的都是采购入库单
pointData: '', terminal: 1 }, newPoint: { type: 1, data: '', pointX: 0, pointY: 0, },
dropPoint: {}, showPoint: {}, selectPoint: null, //上次点击点位置
lastClickPoint: {},
interactionDiagramId: null, pointList: [],
canvasWidth: 0, canvasHeight: 0,
productVisible : false,
action: uploadUrl, headers: { 'Authorization-business': getToken() }, dataObj: { folderId: 1 } } }, computed: { isVisible: { get() { return this.dialogVisible }, set() { this.close() this.reset() } }, isDisabled() { return this.type === 'check' }, title() { const titleMap = { add: '新建互动图', check: '查看互动图', edit: '修改互动图' } return titleMap[this.type] } }, mounted() { // this.getStorehouseList();
}, methods: { // 获取仓库
// async getStorehouseList() {
// const res = await storehouseGetList({})
// this.storehouseList = res.data
// if(this.storehouseList && this.storehouseList.length > 0){
// this.params.storehouseId = this.storehouseList[0].storehouseId
// this.params.storehouseName = this.storehouseList[0].storehouseName
// this.getProductList();
// }
// },
// // 获取商品
// async getProductList() {
// const res = await getClassifyGetList({ storehouseId: this.params.storehouseId})
// this.productList = res.data
// if(this.productList && this.productList.length > 0){
// this.params.productId = this.productList[0].productId
// this.params.productName = this.productList[0].productName
// this.getSkuList();
// }
// },
// async getSkuList() {
// const res = await getClassifyGetById({ productId: this.params.productId})
// this.skuList = res.data.skus
// if(this.skuList && this.skuList.length > 0){
// this.params.skuId = this.skuList[0].skuId
// this.params.skuName = this.skuList[0].skuName
// if(this.skuList[0].skuAttrCodeDTOList.length > 0){
// //多款式
// this.isSkuVisible = 1
// }else{
// this.isSkuVisible = 0
// }
// }
// },
// async changeStorehouseValue(){
// this.getProductList();
// },
// async changeProductValue(){
// this.getSkuList();
// },
handleImageSuccess(response, file, fileList) { console.log('handleImageSuccess') this.params.interactionDiagramImage = response.data.url this.pointList = [] this.params.pointData = '' }, handleRemove(file) { this.params.interactionDiagramImage = '' }, beforeUpload(file) { if (file) { function getFileData(file) { return new Promise(function (resolve, reject) { let reader = new FileReader() reader.readAsDataURL(file); reader.onload = function (event) {
resolve(reader.result) } }) } function getImage(result) { return new Promise(function (resolve, reject) { let img = new Image(); img.src = result; img.onload = function () { //注意只有onload以后才可以拿到图片信息
resolve({ width: img.width, height: img.height }) } }) } return getFileData(file).then(res => { getImage(res).then(r => { this.params.imageWidth = r.width this.params.imageHeight = r.height console.log(this.params.imageHeight, this.params.imageWidth, 'afterFileWidth')
//控件宽高
// const canvasContent = this.$refs.canvasContent;
// const position = canvasContent.getBoundingClientRect();
const position = { height: 650, width: 900 }
// 图片的原始宽度
var naturalWidth = this.params.imageWidth; var naturalHeight = this.params.imageHeight;
//计算图片显示宽高
var showHeight = position.height; var showWidth = naturalWidth * showHeight / naturalHeight;
if (showWidth > position.width) { showWidth = position.width; showHeight = naturalHeight * showWidth / naturalWidth; }
this.canvasWidth = showWidth; this.canvasHeight = showHeight; }) }) } },
// 点击画布的时候, 取消选择组件
laryerMouseDown(ev) { console.log("laryerMouseDown"); // this.curControl = null;
}, // 给画布绑定的mousemove事件
laryerMouseMove(ev) { console.log("laryerMouseMove"); // 判断是需要移动的类型
// if (this.flag == "move") {
// // 用当前移动的距离减去点击的位置
// let dx = ev.pageX - this.containerMoveObj.x,
// dy = ev.pageY - this.containerMoveObj.y;
// // 上次旧的位置加上 处理完的距离就得到当前位置
// this.curControl.pointX = this.curControl.pointX + dx / this.canvasWidth,
// this.curControl.pointY = this.curControl.pointY + dy / this.canvasHeight;
// // 记录下当前点击的位置
// this.containerMoveObj.x = ev.pageX;
// this.containerMoveObj.y = ev.pageY;
// }
}, // 给画布绑定的mouseup事件
laryerMouseUp(ev) { console.log("laryerMouseUp"); //在鼠标抬起的时候判断是否
// if (this.flag == "") {
// return false;
// }
// 用当前移动的距离减去点击的位置
// let dx = ev.pageX - this.containerMoveObj.x,
// dy = ev.pageY - this.containerMoveObj.y;
// // 上次旧的位置加上 处理完的距离就得到当前位置
// this.curControl.pointX = this.curControl.pointX + dx / this.canvasWidth,
// this.curControl.pointY = this.curControl.pointY + dy / this.canvasHeight;
// // 记录下当前点击的位置
// this.containerMoveObj.x = ev.pageX;
// this.containerMoveObj.y = ev.pageY;
// this.flag = "";
}, // 点击元素获取组件配置
handleClick(row, index) { console.log("handleClick"); if(this.showPoint == row){ this.showPoint = null }else{ this.showPoint = row } }, // 移动元素
handleMouseDown(e, row, index) { console.log("handleMouseDown"); e = e || window.event; this.dropPoint = row; // 记录下当前点击的位置
this.lastClickPoint.pointX = e.offsetX; this.lastClickPoint.pointY = e.offsetY; }, handleDrapEvList(e, pointData) { console.log("handleDrapEvList") this.lastClickPoint.pointX = e.offsetX; this.lastClickPoint.pointY = e.offsetY; }, // 监听拖拽元素结束
handleDrap(event) { console.log("handleDrap") event.preventDefault(); event = event || window.event; // console.log("event.offsetX:" + event.offsetX)
// console.log("event.offsetY:" + event.offsetY)
// console.log("event.pageX:" + event.pageX)
// console.log("event.pageY:" + event.pageY)
const canvasContent = this.$refs.canvasContent; const position = canvasContent.getBoundingClientRect(); // console.log('canvasContent')
// 获取绑定到拖拽元素身上的 drapData属性
if (this.lastClickPoint.pointX != null) { var showX = event.pageX - position.left - this.lastClickPoint.pointX; var showY = event.pageY - position.top - this.lastClickPoint.pointY; var pointX = showX / this.canvasWidth; var pointY = showY / this.canvasHeight;
if (this.dropPoint != null) { this.dropPoint.pointX = pointX this.dropPoint.pointY = pointY this.dropPoint = null } else { var point = { type: 1, data: '', pointX: pointX, pointY: pointY } this.pointList.push(point); } } },
close() { this.$emit('close') }, async reset() { this.params = { interactionDiagramId: 0, interactionDiagramName: '', interactionDiagramImage: '', imageWidth: 0, imageHeight: 0,//新增的都是采购入库单
pointData: '', terminal: 1 } this.pointList = [] // if(this.storehouseList && this.storehouseList.length > 0){
// this.params.storehouseId = this.storehouseList[0].storehouseId
// this.params.storehouseName = this.storehouseList[0].storehouseName
// this.getProductList();
// }
}, // 查看详情
async getDetails() { const res = await interactionDiagramGetById({ interactionDiagramId: this.interactionDiagramId }) if (res.code === '') { this.params = res.data
// //控件宽高
// const canvasContent = this.$refs.canvasContent;
// console.log('canvasContent')
// const position = canvasContent.getBoundingClientRect();
const position = { height: 650, width: 900 }
// 图片的原始宽度
var naturalWidth = this.params.imageWidth; var naturalHeight = this.params.imageHeight;
//计算图片显示宽高
var showHeight = position.height; var showWidth = naturalWidth * showHeight / naturalHeight;
if (showWidth > position.width) { showWidth = position.width; showHeight = naturalHeight * showWidth / naturalWidth; }
this.canvasWidth = showWidth; this.canvasHeight = showHeight;
if (this.params.pointData) { this.pointList = JSON.parse(this.params.pointData); } } }, async onSubmit() { if (this.params.interactionDiagramName === '') { this.$message.error('请输入互动图名称') } else if (this.type === 'add') { this.params.pointData = JSON.stringify(this.pointList) this.add() } else if (this.type === 'edit') { this.params.pointData = JSON.stringify(this.pointList) this.update() } else { this.isVisible = false } }, async add() { const res = await interactionDiagramAdd(this.params) if (res.code === '' || res.code === '200') { this.isVisible = false this.$message({ message: this.$t('common.addsuccessful'), type: 'success' }) this.$emit('success') } }, async update() { const res = await interactionDiagramUpdate(this.params) if (res.code === '' || res.code === '200') { this.isVisible = false this.$message({ message: this.$t('common.successful'), type: 'success' }); this.$emit('success') } }, setParams(val = {}) { if (val['params']) { this.params = val['params'] this.interactionDiagramId = this.params.interactionDiagramId this.getDetails() } else if (val['interactionDiagramId']) { this.interactionDiagramId = val['interactionDiagramId'] this.getDetails() } }, selectProduct(row, index){ this.selectPoint = row if(this.$refs.productSelect){ this.$refs.productSelect.reset() } this.productVisible = true }, productChanged () { console.log(this.$refs.productSelect) var data = this.$refs.productSelect.tableRadio this.productVisible = false if(this.selectPoint != null){ this.selectPoint.product = data this.selectPoint = null } }, } } </script> <style lang="scss" scoped> .el-form-item { margin-bottom: 0px !important; } ::v-deep .el-form-item__label{ line-height: 30px !important; } .point_source_active{ align-items: center; background: hsla(0,0%,47%,.5); border: 2px solid transparent; border-radius: 50%; display: flex; height: 32px; justify-content: center; opacity: 1; padding: 0; transition: border-color .25s ease-in-out,opacity .25s ease-in-out,visibility .25s ease-in-out; width: 32px;
&:after { background: #fff; border-radius: 50%; box-shadow: 0 1px 4px #0000008c; content: ""; display: block; height: 12px; position: relative; transition: transform .25s ease-in-out; width: 12px; transform: scale(.667); } } .point_source { align-items: center; background: hsla(0,0%,47%,.5); border: 2px solid transparent; border-radius: 50%; display: flex; height: 32px; justify-content: center; opacity: 1; padding: 0; transition: border-color .25s ease-in-out,opacity .25s ease-in-out,visibility .25s ease-in-out; width: 32px; &:after { background: #fff; border-radius: 50%; box-shadow: 0 1px 4px #0000008c; content: ""; display: block; height: 12px; position: relative; transition: transform .25s ease-in-out; width: 12px; } }
.span-wrap { position: relative; display: inline-block;
.attr-actions { line-height: 120px; position: absolute; width: 100%; height: 100%; left: 0; top: 0; cursor: default; text-align: center; color: #fff; opacity: 0; font-size: 20px; background-color: rgba(0, 0, 0, 0.5); -webkit-transition: opacity 0.3s; transition: opacity 0.3s; z-index: 1;
&:hover { opacity: 1;
.attr-preview { display: inline-block; }
i { color: #fff; font-size: 20px; } } }
.attr-preview { display: none; cursor: pointer; font-size: 20px; color: #fff; }
.attr-delete { margin-left: 15px; color: #fff; }
.attr-value-img { width: 100%; height: 100%;
img { width: 100%; height: 100%; object-fit: contain; } } }
.dialog-wrap { ::v-deep .el-dialog { display: flex; flex-direction: column; height: 90vh; max-width: 1400px; overflow: hidden;
.el-dialog__body { flex: 1; overflow: auto; } }
.dialog-from { width: 90%; margin: auto;
}
.btn-wrap { margin: 0px auto 10px; text-align: right; }
.canvas { display: flex; flex-direction: row; flex-wrap: nowrap; align-content: flex-start; justify-content: center; align-items: flex-start;
.mainContentWarp { background-color: #F0F3F4; height: 100%; flex: 1;
.mainContent { margin: 0 auto; width: 900px; height: 650px; display: flex; flex-direction: row; flex-wrap: nowrap; align-content: center; justify-content: center; align-items: center;
.canvasContent { width: 100%; height: 100%; position: relative;
.img-bg { width: 100%; height: 100%; object-fit: contain; }
.drap-container-item { -webkit-user-select: none; -moz-user-select: none; -o-user-select: none; user-select: none; position: absolute; user-select: none; cursor: pointer; border: 1px solid transparent;
.drap-item-img { width: 40px; height: 40px; object-fit: contain; }
.drap-item-name { text-align: center; } .product-detail-top{ position: relative; top: -100px; } .product-detail-bottom{ } .product-detail-left{ position: relative; left: -100px; } .product-detail-right{ } .product-detail-centerv{ margin-top: -25%; margin-bottom: 25%; } .product-detail-centerh{ margin-left: -25%; margin-right: 25%; } .product-detail{ display: flex; flex-direction: column; flex-wrap: nowrap; align-content: flex-start; justify-content: center; align-items: flex-start; background: white; padding-left: 10px; padding-right: 10px; padding-top: 8px; padding-bottom: 8px; border-radius: 4px; margin-left: -25%; margin-right: 25%; .product-name{ width: 100%; height: auto; font-size: 16px; font-family: Source Han Sans CN; font-weight: bold; color: #252744; display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; line-height: 20px; text-align: left; } .product-price{ width: auto; height: 20px; line-height: 20px; font-size: 14px; font-family: Source Han Sans CN; font-weight: bold; color: #252744; } } }
.drap-container-item-active { border: 1px solid skyblue; } } } }
.RightBox { background-color: #FFFFFF; height: 100%; overflow: auto; margin-left: 20px;
.noChoose { width: 320px; display: flex; height: 100%; -webkit-box-align: center; align-items: center; -webkit-box-pack: center; justify-content: center; color: #999; text-align: center; font-size: 16px; line-height: 1.8;
.iconfont { font-size: 100px; color: $mainColor; } } } }
.form-item-row {
// padding-top: 40px;
::v-deep .el-input { width: 80px; margin: 0 5px; } } }
.product-list { height: 280px; overflow-y: auto; &::-webkit-scrollbar-track-piece { background: #d3dce6; }
&::-webkit-scrollbar { width: 6px; }
&::-webkit-scrollbar-thumb { background: #99a9bf; border-radius: 20px; } .list-group-item { display: flex; -webkit-box-orient: horizontal; -webkit-box-direction: normal; -ms-flex-direction: row; flex-direction: row; -ms-flex-wrap: nowrap; flex-wrap: nowrap; -ms-flex-line-pack: center; align-content: flex-start; -webkit-box-pack: start; -ms-flex-pack: start; justify-content: flex-start; -webkit-box-align: center; -ms-flex-align: center; align-items: flex-start; margin-bottom: 15px;
.item-index { margin-right: 8px; margin-top: 8px; font-size: 16px; }
.item-right { display: flex; flex-direction: column; flex-wrap: nowrap; align-content: center; justify-content: flex-start; align-items: flex-start;
.item-btns { display: flex; flex-direction: row; flex-wrap: nowrap; align-content: center; justify-content: center; align-items: center;
.item-btn-item { border-radius: 4px; background: $mainColor; text-align: center; height: 36px; color: #ffffff; font-size: 14px; display: flex; align-items: center; justify-content: center; cursor: pointer; margin-bottom: 10px; margin-left: 2px; margin-right: 2px; padding-left: 8px; padding-right: 8px;
span { font-size: 18px; color: #ffffff; margin-right: 5px; } }
}
.item-product {} } }
} </style>
|