多租户商城-商户端
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

936 lines
26 KiB

<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>