Browse Source

添加互动图

master
xh-pan1 1 year ago
parent
commit
611af16514
  1. 2
      .env.development
  2. 6
      canvas-container/components/canvasEditPage.vue
  3. 1
      canvas-container/components/canvasShow/config/api.js
  4. 1
      canvas-container/components/leftBar/panel.vue
  5. 160
      canvas-container/components/toolBar/toolModule/interactiondiagram-select.vue
  6. 36
      canvas-container/components/toolBar/toolModule/tool-select-link.vue
  7. 49
      src/api/image.js
  8. BIN
      src/assets/images/point_enter.png
  9. BIN
      src/assets/images/point_source.png
  10. 191
      src/components/Product/product-select.vue
  11. 6
      src/utils/request.js
  12. 1
      src/views/marketing/compose/add.vue
  13. 1
      src/views/marketing/price/add.vue
  14. 271
      src/views/resource/interactiondiagram/detail copy.vue
  15. 936
      src/views/resource/interactiondiagram/detail.vue
  16. 190
      src/views/resource/interactiondiagram/index.vue

2
.env.development

@ -12,3 +12,5 @@ VUE_APP_BASE_API = '/dev-api'
VUE_APP_DOMAIN_PREFIX = 'http://localhost:9004'
# VUE_APP_DOMAIN_PREFIX = 'http://122.9.152.120/ceres-business-api'

6
canvas-container/components/canvasEditPage.vue

@ -9,8 +9,10 @@
@change="pageChange"
filter=".undraggable"
>
<div class="list-group-item" v-for="(item,index) in componentsData" :key="index" :class="[{'on':activeComponent == index,'undraggable':item.undraggable},'item-'+item.type]" @click="selectComponent(item,index)">
<component v-show="!item.isEmpty" :isNoData.sync='item.isEmpty' :is="componentMap[terminal-1].get(item.type)" :componentContent="item.componentContent" :terminal="terminal" :typeId="typeId" :shopId="shopId" @cleckLoading="cleckLoading"></component>
<div class="list-group-item" v-for="(item,index) in componentsData" :key="index"
:class="[{'on':activeComponent == index,'undraggable':item.undraggable},'item-'+item.type]" @click="selectComponent(item,index)">
<component v-show="!item.isEmpty" :isNoData.sync='item.isEmpty' :is="componentMap[terminal-1].get(item.type)" :componentContent="item.componentContent"
:terminal="terminal" :typeId="typeId" :shopId="shopId" @cleckLoading="cleckLoading"></component>
<div class="no-data" v-show="item.isEmpty">
<i class="iconfont icon-kong"></i>
<p>暂无数据<br>请在右边窗口编辑内容</p>

1
canvas-container/components/canvasShow/config/api.js

@ -10,6 +10,7 @@ export const api = {
getClassify: BASEURL + '/canvas/getClassify', // 查询分类层级
getProductGroup: BASEURL + '/canvas/getProductGroup', // 查询分类层级
getProducts: BASEURL + '/canvas/getProducts', // 选择商品查询
getInteractionDiagrams: BASEURL + '/canvas/getInteractionDiagrams', // 选择互动图查询
saveCanvas: BASEURL + '/canvas/saveCanvas', // 保存画布
getCanvas: BASEURL + '/canvas/getCanvas', // 读取画布
getShops: BASEURL + '/canvas/getShops', // 选择店铺查询

1
canvas-container/components/leftBar/panel.vue

@ -18,6 +18,7 @@
:list="item.classList"
:clone="cloneItem"
:group="{ name: 'pageEdit', pull: 'clone', put: false }"
:options="{sort:false}"
>
<div @mouseover="hoverItem (classItem)" @mouseout="hoverItemOut" class="childItem list-group-item" v-for="(classItem, index) of item.classList" :key="index">

160
canvas-container/components/toolBar/toolModule/interactiondiagram-select.vue

@ -0,0 +1,160 @@
<template>
<div class="interaction-diagram-select">
<el-form :inline="true" :model="formData" class="demo-form-inline">
<el-form-item label="">
<el-input v-model="formData.keyword" maxlength="20" placeholder="互动图名称"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="onSubmit">{{ $t('common.query') }}</el-button>
</el-form-item>
</el-form>
<el-table
ref="multipleTable"
:data="tableData"
max-height="500"
border
row-key="interactionDiagramId"
@selection-change="handleSelectionChange"
style="width: 100%">
<el-table-column
v-if="isMultiple"
width="40"
type="selection"
:reserve-selection="true"
fixed="left"
>
</el-table-column>
<el-table-column label="" width="40" align="center" v-else>
<template slot-scope="scope">
<el-radio v-model="tableRadio" :label="scope.row"><i></i></el-radio>
</template>
</el-table-column>
<el-table-column
prop="interactionDiagramName"
label="互动图名称">
</el-table-column>
</el-table>
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="currentPage"
:hide-on-single-page="true"
:page-sizes="[10, 20, 50, 100]"
:page-size="pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="total">
</el-pagination>
</div>
</template>
<script>
import api from '@@/components/canvasShow/config/api'
import {sendReqMixin} from '@@/components/canvasShow/config/mixin'
import {checkEmptyChild} from '@@/config/common'
// import {getShopId} from "@@/utils/auth.js"
export default {
name: 'interactiondiagram-select',
mixins: [sendReqMixin],
data () {
return {
tableRadio: '',
formData: {
keyword: ''
},
currentPage: 1,
total: 0,
pageSize: 10,
tableData: [],
multipleSelection: []
}
},
props: {
selectedRows: {
type: Array,
default: () => []
},
isMultiple: {
type: Boolean,
default: false
}
},
mounted () {
this.getTableData()
},
methods: {
//
getCategory () {
var _this = this
let params = {
url: api.getClassify,
method: 'GET'
}
this.sendReq(params, (res) => {
_this.categoryList = res.data
checkEmptyChild(_this.categoryList)
})
},
//
getTableData () {
var _this = this
var paramsUrl = `${api.getInteractionDiagrams}?page=${this.currentPage}&pageSize=${this.pageSize}`
if (this.formData.keyword) {
paramsUrl += `&interactionDiagramName=${this.formData.keyword}`
}
// let shopId = parseInt(getShopId())
// if (shopId && this.typeId===3) {
// paramsUrl += `&shopId=${shopId}`
// }
let params = {
url: paramsUrl,
method: 'GET'
}
this.sendReq(params, (res) => {
_this.tableData = res.data.list
_this.total = res.data.total
//
// if(_this.selectedRows.length > 0){
// _this.selectedRows.forEach(row => {
// this.$refs.multipleTable.toggleRowSelection(row,true);
// });
// }
})
},
//
onSubmit () {
this.getTableData()
},
//
handleSizeChange (val) {
this.pageSize = val
this.getTableData()
},
//
handleCurrentChange (val) {
this.currentPage = val
this.getTableData()
},
//
handleSelectionChange(val) {
this.multipleSelection = val
}
}
}
</script>
<style lang="scss" scoped>
.interaction-diagram-select{
.el-pagination{
padding: 0px;
margin-top: 30px;
}
.el-table{
.img{
width: 80px;
height: 80px;
}
}
}
</style>

36
canvas-container/components/toolBar/toolModule/tool-select-link.vue

@ -38,6 +38,13 @@
<el-button type="primary" @click="productChanged">{{ $t('common.sure') }}</el-button>
</span>
</el-dialog>
<el-dialog title="选择互动图" :visible.sync="interactiondiagramVisible">
<interactiondiagram-select ref="interactiondiagramSelect"></interactiondiagram-select>
<span slot="footer" class="dialog-footer">
<el-button @click="interactiondiagramVisible = false">{{ $t('common.cancel') }}</el-button>
<el-button type="primary" @click="interactiondiagramChanged">{{ $t('common.sure') }}</el-button>
</span>
</el-dialog>
<el-dialog title="选择店辅" :visible.sync="shopVisible">
<shop-select ref="shopSelect"></shop-select>
<span slot="footer" class="dialog-footer">
@ -64,13 +71,14 @@
<script>
import ProductSelect from './product-select'
import InteractiondiagramSelect from './interactiondiagram-select'
import ShopSelect from './shop-select'
import CategorySelect from './category-select'
import CustomPageSelect from './custom-page-select'
import NoticeSelect from "./notice-select";
export default {
name: 'tool-select-link',
components: {NoticeSelect, CustomPageSelect, CategorySelect, ShopSelect, ProductSelect },
components: {NoticeSelect, CustomPageSelect, CategorySelect, ShopSelect, ProductSelect, InteractiondiagramSelect },
data () {
return {
selsectValue: '',
@ -78,6 +86,7 @@
selectName: '',
typeText: '',
productVisible: false,
interactiondiagramVisible: false,
shopVisible: false,
categoryVisible: false,
customVisible: false,
@ -122,6 +131,10 @@
label: '商品详情'
},
{
value: '/interactiondiagramdetail',
label: '互动图详情'
},
{
value: '/notice',
label: '公告'
},
@ -145,6 +158,7 @@
this.shopVisible = false
this.productVisible = false
this.confirmBtnVisible = true
this.interactiondiagramVisible = false
this.selectName = ''
this.typeText = ''
switch (value) {
@ -157,6 +171,9 @@
case '/detail':
this.typeText = '商品'
break
case '/interactiondiagramdetail':
this.typeText = '互动图'
break
case '/custom':
this.typeText = '自定义'
case '/notice':
@ -185,6 +202,9 @@
case '商品':
this.productVisible = true
break
case '互动图':
this.interactiondiagramVisible = true
break
case '自定义':
this.customVisible = true
case '公告':
@ -222,6 +242,20 @@
}
this.$emit('update:linkObj', linkObj)
},
//
interactiondiagramChanged () {
console.log(this.$refs.interactiondiagramSelect)
var data = this.$refs.interactiondiagramSelect.tableRadio
this.interactiondiagramVisible = false
this.selectName = this.$refs.interactiondiagramSelect.tableRadio.interactionDiagramName
let linkObj = {
selsectValue: this.selsectValue,
selectName: this.selectName,
typeText: this.typeText,
data: data
}
this.$emit('update:linkObj', linkObj)
},
//
shopChanged () {
var data = this.$refs.shopSelect.tableRadio

49
src/api/image.js

@ -0,0 +1,49 @@
import request from '@/utils/request'
//* ******************** 互动图 *********************
// 互动图查询
export function interactionDiagramGetAll(params) {
console.log(params)
return request({
url: '/cereInteractionDiagram/getAll',
method: 'get',
params
})
}
// 互动图详情
export function interactionDiagramGetById(params) {
return request({
url: '/cereInteractionDiagram/getById',
method: 'get',
params
})
}
// 添加互动图
export function interactionDiagramAdd(data) {
return request({
url: '/cereInteractionDiagram/save',
method: 'post',
data
})
}
// 修改互动图
export function interactionDiagramUpdate(data) {
return request({
url: '/cereInteractionDiagram/update',
method: 'post',
data
})
}
// 删除互动图
export function interactionDiagramDelete(data) {
return request({
url: '/cereInteractionDiagram/delete',
method: 'post',
data
})
}

BIN
src/assets/images/point_enter.png

After

Width: 200  |  Height: 200  |  Size: 6.4 KiB

BIN
src/assets/images/point_source.png

After

Width: 200  |  Height: 200  |  Size: 8.4 KiB

191
src/components/Product/product-select.vue

@ -0,0 +1,191 @@
<template>
<div class="product-select">
<el-form :inline="true" :model="formData" class="demo-form-inline">
<el-form-item label="">
<el-input v-model="formData.search" maxlength="20" placeholder="商品名称"></el-input>
</el-form-item>
<!-- <el-form-item label="上架状态">-->
<!-- <el-select v-model="formData.status" :placeholder="$t('common.choose')">-->
<!-- <el-option :label="$t('common.all')" value=""></el-option>-->
<!-- <el-option label="上架" value="1"></el-option>-->
<!-- <el-option label="下架" value="0"></el-option>-->
<!-- </el-select>-->
<!-- </el-form-item>-->
<!-- <el-form-item label="商品分类">
<el-cascader
ref="cascader"
v-model="formData.categoryId"
:options="categoryList"
:props="{ checkStrictly: true,label: 'categoryName',value: 'id',children: 'childs' }"
clearable></el-cascader>
</el-form-item> -->
<el-form-item>
<el-button type="primary" @click="onSubmit">{{ $t('common.query') }}</el-button>
</el-form-item>
</el-form>
<el-table
ref="multipleTable"
:data="tableData"
max-height="500"
border
row-key="productId"
@selection-change="handleSelectionChange"
style="width: 100%">
<el-table-column
v-if="isMultiple"
width="40"
type="selection"
:reserve-selection="true"
fixed="left"
>
</el-table-column>
<el-table-column label="" width="40" align="center" v-else>
<template slot-scope="scope">
<el-radio v-model="tableRadio" :label="scope.row"><i></i></el-radio>
</template>
</el-table-column>
<el-table-column label="产品主图" width="180" align="center">
<template slot-scope="scope">
<el-image
style="width: 80px; height: 80px"
:src="scope.row.productImage"
fit="contain"></el-image>
</template>
</el-table-column>
<el-table-column
prop="productName"
label="产品名称"
width="180">
</el-table-column>
<el-table-column
prop="productId"
label="产品ID">
</el-table-column>
<el-table-column
prop="price"
label="售价">
</el-table-column>
<el-table-column
prop="originalPrice"
label="原价">
</el-table-column>
<el-table-column
prop="stockNumber"
label="库存">
</el-table-column>
<el-table-column
prop="volume"
label="销量">
</el-table-column>
</el-table>
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="currentPage"
:hide-on-single-page="true"
:page-sizes="[10, 20, 50, 100]"
:page-size="pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="total">
</el-pagination>
</div>
</template>
<script>
import { getClassifyGetAll } from '@/api/commodity'
export default {
name: 'product-select',
data () {
return {
tableRadio: '',
formData: {
search: '',
shelveState: '1',
},
currentPage: 1,
total: 0,
pageSize: 10,
tableData: [],
multipleSelection: []
}
},
props: {
selectedRows: {
type: Array,
default: () => []
},
isMultiple: {
type: Boolean,
default: false
}
},
mounted () {
// this.getCategory()
this.getTableData()
},
methods: {
//
// getCategory () {
// var _this = this
// let params = {
// url: api.getClassify,
// method: 'GET'
// }
// this.sendReq(params, (res) => {
// _this.categoryList = res.data
// checkEmptyChild(_this.categoryList)
// })
// },
reset(){
this.currentPage = 1
this.pageSize = 10
this.getTableData()
},
//
getTableData () {
var _this = this
this.formData.page = this.currentPage
this.formData.pageSize = this.pageSize
getClassifyGetAll(this.formData).then(res => {
if (res.code === '') {
_this.tableData = res.data.list
_this.total = res.data.total
}
})
},
//
onSubmit () {
this.getTableData()
},
//
handleSizeChange (val) {
this.pageSize = val
this.getTableData()
},
//
handleCurrentChange (val) {
this.currentPage = val
this.getTableData()
},
//
handleSelectionChange(val) {
this.multipleSelection = val
}
}
}
</script>
<style lang="scss" scoped>
.product-select{
.el-pagination{
padding: 0px;
margin-top: 30px;
}
.el-table{
.img{
width: 80px;
height: 80px;
}
}
}
</style>

6
src/utils/request.js

@ -30,6 +30,10 @@ export const QYuploadUrl = `${baseURL}/file/uploadQyMedia` // 微信客服上传
// request interceptor
service.interceptors.request.use(
config => {
// config.paramsSerializer = function(params) {
// let result = qs.stringify(params, { arrayFormat: 'repeat' })
// return result
// }
if (store.getters.token) {
config.headers['Authorization-business'] = getToken()
config.headers['businessId'] = getBusinessId()
@ -59,7 +63,7 @@ service.interceptors.response.use(
if (response.config.responseType === 'blob') {
return response.data
}
if (res.code !== '') {
if (res.code !== '' && res.code !== '200') {
Message({
message: res.message || 'Error',
type: 'error',

1
src/views/marketing/compose/add.vue

@ -251,7 +251,6 @@
<script>
import { composeAdd, composeUpate, getComposeDetail, getComposeSelectProduct } from '@/api/marketing'
import { getClassifyGetAll } from '@/api/commodity'
function InitComposeForm() {
this.composeProducts = [] //
this.composeName = '' //

1
src/views/marketing/price/add.vue

@ -236,7 +236,6 @@
<script>
import { priceAdd, priceUpate, getPriceDetail, getComposeSelectProduct } from '@/api/marketing'
// import { getClassifyGetAll } from '@/api/commodity'
function InitPriceForm() {
this.priceProducts = [] //

271
src/views/resource/interactiondiagram/detail copy.vue

@ -0,0 +1,271 @@
<template>
<!--
<div class="canvas">
<div class="topBox">
<ul>
<li v-for="(item,index) in deviceList" :key="index" @click="toggleDevice(item.id)" :class="{'on':terminal == item.id}">
<i class="iconfont" :class="'icon-' + item.name"></i>
</li>
</ul>
<el-button class="btn-save" type="primary" @click="canvasSave">保存画布</el-button>
</div>
<div class="bottomWarp">
<div class="leftBox">
<left-bar></left-bar>
</div>
<div class="mainContentWarp">
<div class="mainContent" :class="'view-' + terminal">
<cereshop-layout :terminal="terminal" :typeId="typeId" :shopId="shopId" @showRightBox="showRightBox"></cereshop-layout>
</div>
</div>
<div class="RightBox">
<tool-panel v-if="comChoose"></tool-panel>
<div v-else class="noChoose">
<div> <i class="iconfont icon-kong"></i><p>没有选定的组件<br>请拖拽左侧组件栏添加或者选择一个组件</p></div>
</div>
</div>
</div>
</div>-->
</template>
<script>
//import leftBar from '../components/leftBar/panel.vue'
//import toolPanel from '../components/toolBar/toolPanel'
//import CereshopLayout from '../components/canvasEditPage'
//import { mapGetters, mapMutations } from 'vuex'
//import api from '@@/components/canvasShow/config/api'
//import {sendReqMixin} from '@@/components/canvasShow/config/mixin'
//import {getShopId, initShopId} from "@@/utils/auth.js"
//import Cookies from 'js-cookie'
export default {
// mixins: [sendReqMixin],
// components: {
// CereshopLayout,
// leftBar,
// toolPanel
// },
data () {
return {
comChoose: false,
deviceList: [
{
id: 1,
name: 'xiaochengxu'
},
{
id: 2,
name: 'h5'
},
{
id: 4,
name: 'pc'
},
{
id: 3,
name: 'app'
}
],
canvasId: '',
shopId: 0
}
}
// computed: {
// ...mapGetters([
// 'terminal',
// 'componentsData',
// 'typeId'
// ])
// },
// mounted () {
// initShopId()
// this.shopId = parseInt(getShopId())
// if(this.shopId && this.shopId > 0 ){
// this.setTypeId(3)
// }else{
// this.setTypeId(1)
// }
//
// this.canvasGet()
// },
// methods: {
// ...mapMutations({
// setTerminal: 'SET_TERMINAL',
// setTypeId: 'SET_TYPEID',
// setActiveComponent: 'SET_ACTIVECOMPONENT',
// setComponentsData: 'SET_COMPONENTSDATA'
// }),
// toggleDevice (id) {
// this.setActiveComponent({})
// this.setTerminal(id)
// this.canvasGet()
// },
// //
// canvasSave () {
// //
// let cloneComponentsData = JSON.parse(JSON.stringify(this.componentsData))
// for (let i = 0; i < cloneComponentsData.length; i++) {
// delete cloneComponentsData[i].iconClass
// if (cloneComponentsData[i].type === 'productList') {
// cloneComponentsData[i].componentContent.productData.imgTextData = [] //
// }
// }
// var paramsData = {
// terminal: this.terminal,
// json: JSON.stringify(cloneComponentsData)
// }
// if (this.canvasId) {
// paramsData.canvasId = this.canvasId
// }
// if (this.shopId && this.typeId == 3) {
// paramsData.shopId = this.shopId
// }
// paramsData.type = this.typeId
// console.log(paramsData)
// let params = {
// url: api.saveCanvas,
// method: 'POST',
// data: paramsData
// }
// this.sendReq(params, (res) => {
// if (res.message) {
// this.$message.error(res.message)
// } else {
// this.$message({
// message: '',
// type: 'success'
// })
// }
// })
// },
// //
// canvasGet () {
// var _this = this
// this.setComponentsData([])
// var apiUrl = api.getCanvas + '?terminal=' + this.terminal + '&type=' + this.typeId
// if (this.shopId && this.typeId == 3) {
// apiUrl += '&shopId=' + this.shopId
// }
// let params = {
// url: apiUrl,
// method: 'GET'
// }
// this.sendReq(params, (res) => {
// if(typeof(uni) !== 'undefined'){
// uni.setStorage({key: 'sendNum',data: 0});
// } else {
// localStorage.setItem('sendNum', 0)
// }
// if (JSON.stringify(res.data) !== '{}') {
// _this.canvasId = res.data.canvasId
// var componentsData = JSON.parse(res.data.json)
// for (let i = 0; i < componentsData.length; i++) {
// componentsData[i].componentContent.hasDatas = true
// }
// _this.setComponentsData(componentsData)
// } else {
// _this.canvasId = ''
// }
// },(err)=>{
//
// })
// },
// //
// showRightBox (flag) {
// this.comChoose = flag
// }
// }
}
</script>
<style lang="scss" scoped>
.canvas {
position: relative;
display: flex;
flex-direction: column;
height: 100%;
.topBox{
height: 52px;
line-height: 52px;
border-bottom: 1px solid #F0F3F4;
position: relative;
display: flex;
justify-content: center;
.btn-black{
position: absolute;
left: 20px;
top: 0;
}
li{
width: 56px;
height: 52px;
cursor: pointer;
text-align: center;
display: inline-block;
.iconfont{
font-size: 24px;
}
&:hover,&.on{
background-color: $mainColor;
color: #fff;
}
}
.btn-save{
position: absolute;
right: 20px;
top: 5px;
}
}
.bottomWarp{
flex: 1;
display: flex;
height: 0;
}
.leftBox {
height: 100%;
overflow-y: auto;
overflow-x: hidden;
}
.mainContentWarp{
background-color: #F0F3F4;
overflow: auto;
height: 100%;
flex: 1;
.mainContent{
margin: 0 auto;
max-width: 100%;
width: 750px;
&.view-4{
width: 1300px;
}
}
}
.RightBox {
height: 100%;
overflow: auto;
.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;
}
}
}
}
</style>

936
src/views/resource/interactiondiagram/detail.vue

@ -0,0 +1,936 @@
<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>

190
src/views/resource/interactiondiagram/index.vue

@ -0,0 +1,190 @@
<!-- -->
<template>
<div>
<div class="pending">
<!-- 搜索 -->
<div class="formSearch">
<el-form :inline="true" :model="formParams" class="demo-form-inline">
<el-form-item label="互动图名称">
<el-input v-model="formParams.interactionDiagramName" placeholder="请输入互动图名称" />
</el-form-item>
<el-form-item>
<el-button type="success" plain @click="add">新增互动图</el-button>
<el-button type="primary" plain @click="search">{{ $t('common.query') }}</el-button>
</el-form-item>
</el-form>
</div>
<!-- 表格 -->
<div class="tableBox">
<el-table
ref="multipleTable"
:data="tableData"
border
:header-cell-style="{ background: '#EEF3FF', color: '#333333' }"
tooltip-effect="dark"
style="width: 100%"
>
<el-table-column label="互动图名称" width="600">
<template slot-scope="scope">{{ scope.row.interactionDiagramName }}</template>
</el-table-column>
<el-table-column :label="$t('common.operate')" show-overflow-tooltip>
<template slot-scope="scope">
<div class="btnList">
<el-button type="text" :visible="false" @click="seeMore(scope.row)">{{ $t('common.view') }}</el-button>
<el-button type="text" :visible="false" @click="edit(scope.row)">{{ $t('common.edit') }}</el-button>
<el-button type="text" @click="del(scope.row)">{{ $t('common.delete') }}</el-button>
</div>
</template>
</el-table-column>
</el-table>
<div class="fenye">
<el-pagination
:current-page="currentPage"
:page-sizes="[10, 20, 50, 100]"
:page-size="10"
layout="total, sizes, prev, pager, next, jumper"
:total="total"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
/>
</div>
</div>
</div>
<!-- 方案组件 -->
<InteractionDiagramDetail
ref="edit"
:dialog-visible="dialog.isVisible"
:type="dialog.type"
@close="editClose"
@success="getLists"
/>
</div>
</template>
<script>
import { interactionDiagramGetAll, interactionDiagramDelete } from '@/api/image'
import InteractionDiagramDetail from './detail'
export default {
components: {
InteractionDiagramDetail
},
data() {
//
return {
formParams: {
interactionDiagramName: '',
page: 1,
pageSize: 10
},
total: 1,
tableData: [],
currentPage: 1,
dialog: {
type: 'add',
isVisible: false
}
}
},
// data
computed: {},
// data
watch: {},
// - 访this
created() {},
// - 访DOM
mounted() {
this.getList(this.formParams)
},
//
methods: {
handleSizeChange(val) {
this.formParams.pageSize = val
this.getList(this.formParams)
},
handleCurrentChange(val) {
this.formParams.page = val
this.getList(this.formParams)
},
getLists() {
this.getList(this.formParams)
},
//
search() {
this.total = 1
this.formParams.page = 1
this.getList(this.formParams)
},
//
add() {
this.dialog = {
type: 'add',
isVisible: true
}
},
//
seeMore(row) {
const { interactionDiagramId } = row
this.dialog = {
type: 'check',
isVisible: true
}
this.$refs.edit.setParams({
interactionDiagramId: interactionDiagramId
})
},
//
edit(row) {
const { interactionDiagramId } = row
this.dialog = {
type: 'edit',
isVisible: true
}
this.$refs.edit.setParams({
interactionDiagramId: interactionDiagramId
})
},
//
editClose() {
this.dialog.isVisible = false
},
//
del(row) {
this.$confirm('选中数据将被永久删除, 是否继续?', '提示', {
confirmButtonText: this.$t('common.sure'),
cancelButtonText: this.$t('common.cancel'),
type: 'warning'
})
.then(() => {
interactionDiagramDelete({ interactionDiagramId: row.interactionDiagramId }).then(res => {
if (res.code === '' || res.code === '200') {
this.$message({
type: 'success',
message: this.$t('common.deletesuccess')
})
}
this.getList(this.formParams)
})
})
.catch(() => {})
},
//
async getList(formParams) {
const res = await interactionDiagramGetAll(formParams)
this.tableData = res.data.list
this.total = res.data.total
}
}
}
</script>
<style lang='scss' scoped>
//@import url(); css
@import url("../../../styles/elDialog.scss");
.pending {
padding: 30px;
background: #FFFFFF;
border-radius: 10px;
}
.fenye {
margin-top: 20px;
}
</style>
Loading…
Cancel
Save