添加组件

master
suixy 6 months ago
parent 2f4bf558dd
commit 05df4b2245

@ -0,0 +1,163 @@
<template>
<div class="product-container">
<!-- 左侧大图 + 缩略图 -->
<div class="product-left">
<!-- 大图 -->
<div class="main-img">
<el-image :src="activeImg" fit="contain"></el-image>
</div>
<!-- 缩略图 -->
<div class="thumb-list">
<div
v-for="(img, index) in data.imgList"
:key="index"
class="thumb-item"
:class="{ active: activeIndex === index }"
@mouseenter="changeImg(index)"
>
<i class="del el-icon-circle-close" @click="data.imgList.splice(index, 1);"></i>
<UploadEl style=" " field="url" :data="img"/>
</div>
<div class="thumb-item"
@click="data.imgList.push({url:''})">
<i class="el-icon-circle-plus" style="font-size: 1vw; line-height: 60px"></i>
</div>
</div>
</div>
<!-- 右侧文字 -->
<div class="product-right">
<h2 class="title">产品特点</h2>
<ul class="features">
<li v-for="(item, i) in data.features" :key="i" style="position: relative;">
<i class="del el-icon-circle-close" @click="data.features.splice(i, 1);"></i>
<i class="el-icon-circle-check"></i>
<span contenteditable="true" @blur="edit2('name',i,$event)">
{{ item.name }}
</span>
</li>
<li class="thumb-item"
@click="data.features.push({name:''})">
<i class="el-icon-circle-plus" style="font-size: 1vw; line-height: 60px"></i>
</li>
</ul>
</div>
</div>
</template>
<script>
import UploadEl from "@/components/editEl/uploadEl.vue";
export default {
name: 'PlatformFeatures',
props: ['data'],
components: {UploadEl},
computed: {
activeImg() {
return this.data?.imgList?.[this.activeIndex]?.url;
},
},
data() {
return {
activeIndex: 0,
}
},
mounted() {
},
methods: {
changeImg(index) {
this.activeIndex = index;
},
edit2(key, index, e) {
this.$props.data.features[index][key] = e.target.innerText
},
}
}
</script>
<style lang="less" scoped>
@import "~@/style.less";
.product-container {
padding: 5vw 10vw;
display: flex;
gap: 40px;
}
.product-left {
width: 400px;
}
.main-img {
width: 100%;
height: 300px;
border: 1px solid #eee;
display: flex;
justify-content: center;
align-items: center;
}
.thumb-list {
margin-top: 16px;
display: flex;
gap: 10px;
}
.thumb-item {
width: 80px;
height: 60px;
border: 2px solid transparent;
cursor: pointer;
position: relative;
}
.thumb-item.active {
border-color: #409eff;
}
.thumb-item .el-image {
width: 100%;
height: 100%;
}
.features {
list-style: none;
padding: 0;
margin: 0;
}
.features li {
font-size: 14px;
margin-bottom: 10px;
color: #333;
display: flex;
align-items: center;
line-height: 24px;
}
.features i {
color: #409eff;
margin-right: 6px;
}
.product-left {
width: 400px;
}
.product-right {
flex: 1;
}
.del {
position: absolute;
right: 0;
top: 0;
cursor: pointer;
}
</style>

@ -0,0 +1,111 @@
<template>
<div class="param-container" style="padding: 5vw 10vw;background-color: #0001">
<h2 class="title1" style="line-height: 40px">产品参数</h2>
<div class="paramsTable" v-for="(param, index) in data.params" :key="index" style="position: relative;">
<i class="del el-icon-circle-close" @click="data.params.splice(index, 1);"></i>
<div class="th">
<div class="th1" contenteditable="true" @blur="edit3('title',index,$event)">{{ param.title }}</div>
<div class="th2">参数值</div>
</div>
<div class="td">
<div v-for="(item, idx) in param.list" :key="idx" style="position: relative;">
<i class="del el-icon-circle-close" @click="data.params[index].list.splice(idx, 1);"></i>
<div class="td1" contenteditable="true" @blur="edit4('name',index,idx,$event)">{{ item.name }}</div>
<div class="td2" contenteditable="true" @blur="edit4('value',index,idx,$event)">{{ item.value }}</div>
</div>
</div>
<div class="td">
<div class="td1"
@click="data.params[index].list.push({name:'',value:''})">
<i class="el-icon-circle-plus" style="font-size: 1vw; line-height: 60px"></i>
</div>
</div>
</div>
<div class="td"
@click="data.params.push({title:'',list:[]})">
<i class="el-icon-circle-plus" style="font-size: 1vw; line-height: 60px"></i>
</div>
</div>
</template>
<script>
import UploadEl from "@/components/editEl/uploadEl.vue";
export default {
name: 'PlatformFeatures',
props: ['data'],
components: {UploadEl},
data() {
return {}
},
mounted() {
},
methods: {
edit3(key, index, e) {
this.$props.data.params[index][key] = e.target.innerText
},
edit4(key, index, index1, e) {
this.$props.data.params[index].list[index1][key] = e.target.innerText
},
}
}
</script>
<style lang="less" scoped>
@import "~@/style.less";
.paramsTable {
.th {
background-color: #DBDFE7;
line-height: 3vw;
font-size: 1.3vw;
font-weight: 700;
text-align: left;
.th1 {
width: calc(30% - 2vw - 2px);
display: inline-block;
padding-left: 2vw;
border-right: 1px solid #0001
}
.th2 {
width: calc(70% - 2vw - 2px);
display: inline-block;
padding-left: 2vw;
}
}
.td {
line-height: 3vw;
font-size: 0.9vw;
text-align: left;
.td1 {
background-color: #F2F4F8;
width: calc(30% - 2vw - 2px);
display: inline-block;
padding-left: 2vw;
border: 1px solid #0001
}
.td2 {
background-color: #EEEEEE;
width: calc(70% - 2vw - 2px);
display: inline-block;
padding-left: 2vw;
border: 1px solid #0001
}
}
}
.del {
position: absolute;
right: 0;
top: 0;
cursor: pointer;
}
</style>

@ -0,0 +1,99 @@
<template>
<div class="param-container" style="padding: 5vw 10vw;background-color: #fff">
<h2 class="title1" style="line-height: 40px">资料下载</h2>
<div>
<div v-for="(i,k) in data.fileList" class="fileCard" style="text-align: left;position: relative;">
<div class="cardTitle" contenteditable="true" @blur="edit5('name',k,$event)">{{ i.name }}</div>
<div class="cardValue" contenteditable="true" @blur="edit5('value',k,$event)">{{ i.value }}</div>
<UploadFile style="position:absolute;top: 50%;right: 10px;transform: translateY(-50%)" :data="i" field="url"/>
</div>
<div class="fileCard"
@click="data.fileList.push({name:'名称',value:'介绍',url:'',fileName:''})">
<i class="el-icon-circle-plus" style="font-size: 1vw; line-height: 100px"></i>
</div>
</div>
</div>
</template>
<script>
import UploadEl from "@/components/editEl/uploadEl.vue";
import UploadFile from "@/components/editEl/uploadFile.vue";
export default {
name: 'PlatformFeatures',
props: ['data'],
components: {UploadFile, UploadEl},
data() {
return {}
},
mounted() {
},
methods: {
edit5(key, index, e) {
this.$props.data.fileList[index][key] = e.target.innerText
},
}
}
</script>
<style lang="less" scoped>
@import "~@/style.less";
.fileCard {
vertical-align: top;
display: inline-block;
width: 40%;
height: 100px;
border: 1px solid #ccc;
border-radius: 10px;
margin-top: 1vw;
position: relative;
.cardTitle {
position: absolute;
top: 10px;
left: 20px;
font-size: 22px;
font-weight: 700;
line-height: 45px;
width: calc(100% - 80px);
white-space: nowrap; /* 不换行 */
overflow: hidden; /* 超出部分隐藏 */
text-overflow: ellipsis; /* 超出部分显示省略号 */
}
.cardValue {
position: absolute;
top: 55px;
width: calc(100% - 80px);
left: 20px;
font-size: 14px;
line-height: 45px;
color: #aaa;
white-space: nowrap; /* 不换行 */
overflow: hidden; /* 超出部分隐藏 */
text-overflow: ellipsis; /* 超出部分显示省略号 */
}
.downIcon {
position: absolute;
right: 20px;
top: 50%;
transform: translateY(-50%);
}
&:nth-child(2n) {
margin-left: 5%;
}
}
.del {
position: absolute;
right: 0;
top: 0;
cursor: pointer;
}
</style>

@ -0,0 +1,115 @@
<template>
<div class="banner">
<UploadEl style="width: 100%; height: 100%;position:absolute;top: 0;left: 0;" :data="data" field="banner"/>
<UploadEl style="width: 40%; height: 40%;position:absolute;right:10%;top: 30%;" :data="data" field="banner1"/>
<div class="bannerInfo" contenteditable="true" @blur="edit1('bannerTitle',$event)">{{ data.bannerTitle }}</div>
<div class="bannerValue" contenteditable="true" @blur="edit1('bannerValue',$event)">{{ data.bannerValue }}</div>
</div>
</template>
<script>
import UploadEl from "@/components/editEl/uploadEl.vue";
import UploadFile from "@/components/editEl/uploadFile.vue";
export default {
name: 'PlatformFeatures',
props: ['data'],
components: {UploadFile, UploadEl},
data() {
return {}
},
mounted() {
},
methods: {
edit1(key, e) {
this.data[key] = e.target.innerText
},
}
}
</script>
<style lang="less" scoped>
@import "~@/style.less";
.banner {
width: 100%;
height: 35.5vw;
position: relative;
.bannerInfo {
position: absolute;
top: 35%;
left: 19%;
width: 40%;
text-align: left;
font-size: 2.5vw;
color: #000;
font-weight: 700;
line-height: 3vw;
letter-spacing: 2px;
word-break: break-all;
}
.bannerValue {
position: absolute;
top: calc(35% + 3vw);
left: 19%;
width: 40%;
text-align: left;
font-size: 1vw;
color: #000;
font-weight: 500;
line-height: 2vw;
word-break: break-all;
}
.bannerBtn {
position: absolute;
top: 58%;
left: 19%;
width: 11.5vw;
font-size: 1.2vw;
line-height: 2vw;
letter-spacing: 2px;
}
.tabs {
position: absolute;
bottom: 0;
width: 100%;
background: linear-gradient(to bottom, fade(@standard-color, 10), fade(#fff, 10));
backdrop-filter: saturate(50%) blur(4px);
.content {
width: 62%;
position: relative;
left: 50%;
bottom: 0;
transform: translateX(-50%);
.tab {
display: inline-block;
width: 50%;
line-height: 6.2vw;
font-size: 1.6vw;
letter-spacing: 3px;
}
.tab.active {
color: @standard-color;
width: calc(50% - 3px);
border: 1px solid #fff;
box-shadow: 0 0 3px #0002;
}
}
}
}
.del {
position: absolute;
right: 0;
top: 0;
cursor: pointer;
}
</style>

@ -21,7 +21,11 @@ export default {
},
computed: {
fileList() {
return [{url: this.$props.data[this.$props.field || 'file'], name: this.$props.data.fileName}]
if (this.$props.data[this.$props.field || 'file']) {
return [{url: this.$props.data[this.$props.field || 'file'], name: this.$props.data.fileName}]
} else {
return []
}
},
},
methods: {

@ -0,0 +1,136 @@
<template>
<div class="product-container">
<!-- 左侧大图 + 缩略图 -->
<div class="product-left">
<!-- 大图 -->
<div class="main-img">
<el-image :src="activeImg" fit="contain"></el-image>
</div>
<!-- 缩略图 -->
<div class="thumb-list">
<div
v-for="(img, index) in data.imgList"
:key="index"
class="thumb-item"
:class="{ active: activeIndex === index }"
@mouseenter="changeImg(index)"
>
<el-image :src="img.url" fit="cover"></el-image>
</div>
</div>
</div>
<!-- 右侧文字 -->
<div class="product-right">
<h2 class="title">产品特点</h2>
<ul class="features">
<li v-for="(item, i) in data.features" :key="i">
<i class="el-icon-circle-check"></i> {{ item.name }}
</li>
</ul>
</div>
</div>
</template>
<script>
export default {
name: 'PlatformFeatures',
props: ['data'],
computed: {
activeImg() {
return this.data?.imgList?.[this.activeIndex]?.url;
},
},
data() {
return {
activeIndex: 0,
}
},
mounted() {
},
methods: {
changeImg(index) {
this.activeIndex = index;
},
}
}
</script>
<style lang="less" scoped>
@import "~@/style.less";
.product-container {
padding: 5vw 10vw;
display: flex;
gap: 40px;
}
.product-left {
width: 400px;
}
.main-img {
width: 100%;
height: 300px;
border: 1px solid #eee;
display: flex;
justify-content: center;
align-items: center;
}
.thumb-list {
margin-top: 16px;
display: flex;
gap: 10px;
}
.thumb-item {
width: 80px;
height: 60px;
border: 2px solid transparent;
cursor: pointer;
position: relative;
}
.thumb-item.active {
border-color: #409eff;
}
.thumb-item .el-image {
width: 100%;
height: 100%;
}
.features {
list-style: none;
padding: 0;
margin: 0;
}
.features li {
font-size: 14px;
margin-bottom: 10px;
color: #333;
display: flex;
align-items: center;
line-height: 24px;
}
.features i {
color: #409eff;
margin-right: 6px;
}
.product-left {
width: 400px;
}
.product-right {
flex: 1;
}
</style>

@ -0,0 +1,85 @@
<template>
<div class="param-container" style="padding: 5vw 10vw;background-color: #0001">
<h2 class="title1" style="line-height: 40px">产品参数</h2>
<div class="paramsTable" v-for="(param, index) in data.params" :key="index">
<div class="th">
<div class="th1">{{ param.title }}</div>
<div class="th2">参数值</div>
</div>
<div class="td">
<div v-for="(item, idx) in param.list" :key="idx">
<div class="td1">{{ item.name }}</div>
<div class="td2">{{ item.value }}</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'PlatformFeatures',
props: ['data'],
computed: {},
data() {
return {}
},
mounted() {
},
methods: {}
}
</script>
<style lang="less" scoped>
@import "~@/style.less";
.paramsTable {
.th {
background-color: #DBDFE7;
line-height: 3vw;
font-size: 1.3vw;
font-weight: 700;
text-align: left;
.th1 {
width: calc(30% - 2vw - 2px);
display: inline-block;
padding-left: 2vw;
border-right: 1px solid #0001
}
.th2 {
width: calc(70% - 2vw - 2px);
display: inline-block;
padding-left: 2vw;
}
}
.td {
line-height: 3vw;
font-size: 0.9vw;
text-align: left;
.td1 {
background-color: #F2F4F8;
width: calc(30% - 2vw - 2px);
display: inline-block;
padding-left: 2vw;
border: 1px solid #0001
}
.td2 {
background-color: #EEEEEE;
width: calc(70% - 2vw - 2px);
display: inline-block;
padding-left: 2vw;
border: 1px solid #0001
}
}
}
</style>

@ -0,0 +1,105 @@
<template>
<div class="param-container" style="padding: 5vw 10vw;background-color: #fff">
<h2 class="title1" style="line-height: 40px">资料下载</h2>
<div>
<div v-for="i in data.fileList" class="fileCard" style="text-align: left">
<div class="cardTitle">{{ i.name }}</div>
<div class="cardValue">{{ i.value }}</div>
<el-button @click="downFile(i.url,i.fileName)" type="primary" class="downIcon" icon="el-icon-download "
circle></el-button>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'PlatformFeatures',
props: ['data'],
computed: {},
data() {
return {}
},
mounted() {
},
methods: {
async downFile(url, filename) {
try {
const response = await fetch(url, {mode: 'cors'});
if (!response.ok) throw new Error('网络错误');
const blob = await response.blob(); //
const blobUrl = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = blobUrl;
a.download = filename || url.split('/').pop();
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(blobUrl); //
} catch (err) {
console.error('下载失败:', err);
}
}
}
}
</script>
<style lang="less" scoped>
@import "~@/style.less";
.fileCard {
vertical-align: top;
display: inline-block;
width: 40%;
height: 100px;
border: 1px solid #ccc;
border-radius: 10px;
margin-top: 1vw;
position: relative;
.cardTitle {
position: absolute;
top: 10px;
left: 20px;
font-size: 22px;
font-weight: 700;
line-height: 45px;
width: calc(100% - 80px);
white-space: nowrap; /* 不换行 */
overflow: hidden; /* 超出部分隐藏 */
text-overflow: ellipsis; /* 超出部分显示省略号 */
}
.cardValue {
position: absolute;
top: 55px;
width: calc(100% - 80px);
left: 20px;
font-size: 14px;
line-height: 45px;
color: #aaa;
white-space: nowrap; /* 不换行 */
overflow: hidden; /* 超出部分隐藏 */
text-overflow: ellipsis; /* 超出部分显示省略号 */
}
.downIcon {
position: absolute;
right: 20px;
top: 50%;
transform: translateY(-50%);
}
&:nth-child(2n) {
margin-left: 5%;
}
}
</style>

@ -0,0 +1,109 @@
<template>
<div class="banner">
<el-image
style="width: 100%; height: 100%;position:absolute;top: 0;left: 0;"
:src="data.banner"
fit="contain"></el-image>
<el-image
style="width: 40%; height: 40%;position:absolute;right:10%;top: 30%;"
:src="data.banner1"
fit="contain"></el-image>
<div class="bannerInfo">{{ data.bannerTitle }}</div>
<div class="bannerValue">{{ data.bannerValue }}</div>
</div>
</template>
<script>
export default {
name: 'PlatformFeatures',
props: ['data'],
computed: {},
data() {
return {}
},
mounted() {
},
methods: {}
}
</script>
<style lang="less" scoped>
@import "~@/style.less";
.banner {
width: 100%;
height: 35.5vw;
position: relative;
.bannerInfo {
position: absolute;
top: 35%;
left: 19%;
width: 40%;
text-align: left;
font-size: 2.5vw;
color: #000;
font-weight: 700;
line-height: 3vw;
letter-spacing: 2px;
word-break: break-all;
}
.bannerValue {
position: absolute;
top: calc(35% + 3vw);
left: 19%;
width: 40%;
text-align: left;
font-size: 1vw;
color: #000;
font-weight: 500;
line-height: 2vw;
word-break: break-all;
}
.bannerBtn {
position: absolute;
top: 58%;
left: 19%;
width: 11.5vw;
font-size: 1.2vw;
line-height: 2vw;
letter-spacing: 2px;
}
.tabs {
position: absolute;
bottom: 0;
width: 100%;
background: linear-gradient(to bottom, fade(@standard-color, 10), fade(#fff, 10));
backdrop-filter: saturate(50%) blur(4px);
.content {
width: 62%;
position: relative;
left: 50%;
bottom: 0;
transform: translateX(-50%);
.tab {
display: inline-block;
width: 50%;
line-height: 6.2vw;
font-size: 1.6vw;
letter-spacing: 3px;
}
.tab.active {
color: @standard-color;
width: calc(50% - 3px);
border: 1px solid #fff;
box-shadow: 0 0 3px #0002;
}
}
}
}
</style>

@ -7,7 +7,7 @@ Vue.use(Router)
export default new Router({
routes: [
{
path: '/editor', component: () => import('@/views/pageEditor/index.vue'),
path: '/editor', component: () => import('@/views/editPage/index.vue'),
},
// {
// path: '/test', component: () => import('@/views/page/index.vue'),

@ -0,0 +1,530 @@
<template>
<div>
<div class="top">
<div class="title">
页面编辑器
</div>
<el-select clearable @change="typeChange" v-model="type" size="small" style="margin-right: 12px;"
placeholder="请选择">
<el-option
label="行业方案"
value="1">
</el-option>
<el-option
label="产品中心"
value="2">
</el-option>
</el-select>
<el-cascader
@change="pageChange"
size="small"
v-model="value"
:props="props"
:options="options"></el-cascader>
<el-button type="primary" size="small" style="margin-left: 12px;" @click="save"><i
class="el-icon-upload"></i>
</el-button>
</div>
<div class="container">
<div class="component" v-for="(i,k) in components">
<i class="del el-icon-circle-close" @click="components.splice(k, 1);"></i>
<i class="up el-icon-top" @click="moveUp(k);"></i>
<i class="down el-icon-bottom" @click="moveDown(k);"></i>
<Carousel v-if="i.type === 'carousel'" :data="i.value"/>
<EditEl1 v-if="i.type === 1" :data="i.value"/>
<EditEl2 v-if="i.type === 2" :data="i.value"/>
<EditEl3 v-if="i.type === 3" :data="i.value"/>
<EditEl4 v-if="i.type === 4" :data="i.value"/>
<EditEl5 v-if="i.type === 5" :data="i.value"/>
<EditEl6 v-if="i.type === 6" :data="i.value"/>
<EditEl7 v-if="i.type === 7" :data="i.value"/>
<EditEl8 v-if="i.type === 8" :data="i.value"/>
<EditEl9 v-if="i.type === 9" :data="i.value"/>
<EditEl10 v-if="i.type ===10" :data="i.value"/>
<EditEl11 v-if="i.type === 11" :data="i.value"/>
<EditEl12 v-if="i.type === 12" :data="i.value"/>
<EditEl13 v-if="i.type === 13" :data="i.value"/>
<EditEl14 v-if="i.type === 14" :data="i.value"/>
<EditEl15 v-if="i.type === 15" :data="i.value"/>
</div>
<div class="addItem">
<div style="width:100%;height:100%;" @click="add">
<i class="el-icon-circle-plus" style="font-size: 3vw; line-height: 16.7vw"></i>
</div>
</div>
</div>
<el-dialog
title="添加组件"
:visible.sync="addEl"
width="80%">
<el-card shadow="hover" style="width: 200px;display: inline-block;height:70px">
<div style="width: 100%;height: 100%" @click="addItem('carousel')">
轮播图
</div>
</el-card>
<el-card shadow="hover" style="width: 200px;display: inline-block;height:70px">
<div style="width: 100%;height: 100%" @click="addItem(1)">
图标 +文字+内容横铺4个
</div>
</el-card>
<el-card shadow="hover" style="width: 200px;display: inline-block;height:70px">
<div style="width: 100%;height: 100%" @click="addItem(2)">
左标题+内容右图片
</div>
</el-card>
<el-card shadow="hover" style="width: 200px;display: inline-block;height:70px">
<div style="width: 100%;height: 100%" @click="addItem(3)">
左图标右标题+内容一行2个
</div>
</el-card>
<el-card shadow="hover" style="width: 200px;display: inline-block;height:70px">
<div style="width: 100%;height: 100%" @click="addItem(4)">
左大图右标题+内容一行2个
</div>
</el-card>
<el-card shadow="hover" style="width: 200px;display: inline-block;height:70px">
<div style="width: 100%;height: 100%" @click="addItem(5)">
上标题+下图片
</div>
</el-card>
<el-card shadow="hover" style="width: 200px;display: inline-block;height:70px">
<div style="width: 100%;height: 100%" @click="addItem(6)">
上标题+内容下图片
</div>
</el-card>
<el-card shadow="hover" style="width: 200px;display: inline-block;height:70px">
<div style="width: 100%;height: 100%" @click="addItem(7)">
图标标题内容一行3个
</div>
</el-card>
<el-card shadow="hover" style="width: 200px;display: inline-block;height:70px">
<div style="width: 100%;height: 100%" @click="addItem(8)">
左图右列表
</div>
</el-card>
<el-card shadow="hover" style="width: 200px;display: inline-block;height:70px">
<div style="width: 100%;height: 100%" @click="addItem(9)">
上图下内容一行4个
</div>
</el-card>
<el-card shadow="hover" style="width: 200px;display: inline-block;height:70px">
<div style="width: 100%;height: 100%" @click="addItem(10)">
一行3张图
</div>
</el-card>
<el-card shadow="hover" style="width: 200px;display: inline-block;height:70px">
<div style="width: 100%;height: 100%" @click="addItem(11)">
图标标题内容一行3个(大图)
</div>
</el-card>
<el-card shadow="hover" style="width: 200px;display: inline-block;height:70px">
<div style="width: 100%;height: 100%" @click="addItem(12)">
产品特点+图片
</div>
</el-card>
<el-card shadow="hover" style="width: 200px;display: inline-block;height:70px">
<div style="width: 100%;height: 100%" @click="addItem(13)">
产品参数
</div>
</el-card>
<el-card shadow="hover" style="width: 200px;display: inline-block;height:70px">
<div style="width: 100%;height: 100%" @click="addItem(14)">
资料下载
</div>
</el-card>
<el-card shadow="hover" style="width: 200px;display: inline-block;height:70px">
<div style="width: 100%;height: 100%" @click="addItem(15)">
产品banner
</div>
</el-card>
<span slot="footer" class="dialog-footer">
<el-button @click="addEl = false"> </el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import Carousel from "@/components/editEl/carousel.vue";
import EditEl1 from "@/components/editEl/editEl1.vue";
import EditEl2 from "@/components/editEl/editEl2.vue";
import EditEl3 from "@/components/editEl/editEl3.vue";
import EditEl4 from "@/components/editEl/editEl4.vue";
import EditEl5 from "@/components/editEl/editEl5.vue";
import EditEl6 from "@/components/editEl/editEl6.vue";
import EditEl7 from "@/components/editEl/editEl7.vue";
import EditEl8 from "@/components/editEl/editEl8.vue";
import EditEl9 from "@/components/editEl/editEl9.vue";
import EditEl10 from "@/components/editEl/editEl10.vue";
import {selectConfigTypeList} from "@/api/menu";
import {listHwWebMenu, selectMenuTree} from "@/api/hwWebMenu";
import {getHwWeb, listHwWeb1, updateHwWeb, updateHwWeb1} from "@/api/hwWeb";
import EditEl11 from "@/components/editEl/editEl11.vue";
import EditEl12 from "@/components/editEl/editEl12.vue";
import EditEl13 from "@/components/editEl/editEl13.vue";
import EditEl14 from "@/components/editEl/editEl14.vue";
import EditEl15 from "@/components/editEl/editEl15.vue";
export default {
components: {
Carousel,
EditEl1,
EditEl2,
EditEl3,
EditEl4,
EditEl5,
EditEl6,
EditEl7,
EditEl8,
EditEl9,
EditEl10,
EditEl11,
EditEl12,
EditEl13,
EditEl14,
EditEl15,
},
data() {
return {
a: '1',
addEl: false,
props: {},
type: '',
value: [],
options: [],
componentsM: [
{
type: 'carousel',
value: {
list: [
{
icon: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg',
title: '111',
value: '222'
}
],
},
},
{
type: 1,
value: {
title: '123',
subTitle: '456',
list: [
{
icon: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg',
title: '111',
value: '222'
},
],
},
},
{
type: 2,
value: {
title: '123',
subTitle: '456',
contentTitle: 'contentTitle',
contentSubTitle: 'DEVELOPMENT PLATFORM',
contentInfo: 'contentInfo',
icon: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg',
},
},
{
type: 3,
value: {
title: '123',
subTitle: '456',
list: [
{
icon: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg',
itemTitle: '111',
itemInfo: '222'
},
],
},
},
{
type: 4,
value: {
icon: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg',
title: '123',
subTitle: '456',
list: [
{
title: '111',
value: '222'
}
],
},
},
{
type: 5,
value: {
icon: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg',
title: '123',
subTitle: '456',
},
},
{
type: 6,
value: {
icon: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg',
title: '123',
subTitle: '456',
info: '789',
},
},
{
type: 7,
value: {
title: '123',
subTitle: '456',
list: [
{
icon: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg',
title: '111',
value: '222'
},
],
},
},
{
type: 8,
value: {
title: '123',
subTitle: '456',
list: [
{
icon: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg',
title: '111',
leftTitle: '222',
leftInfo: '333',
infos: [
{title: '111', info: '222'},
{title: '111', info: '222'},
{title: '111', info: '222'},
]
},
],
},
},
{
type: 9,
value: {
title: '123',
subTitle: '456',
list: [
{
icon: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg',
value: '222'
},
],
},
},
{
type: 10,
value: {
title: '123',
subTitle: '456',
list: [
{
icon: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg',
title: '111',
value: '222'
}
],
},
},
{
type: 11,
value: {
title: '123',
subTitle: '456',
list: [
{
icon: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg',
title: '111',
value: '222'
},
],
},
},
{
type: 12,
value: {
imgList: [],
features: [],
},
},
{
type: 13,
value: {
params: [],
},
},
{
type: 14,
value: {
fileList: [],
},
},
{
type: 15,
value: {
banner: '',
banner1: '',
bannerTitle: '设备名称',
bannerValue: '设备介绍',
},
},
],
components: [],
}
},
mounted() {
},
methods: {
edit(key, e) {
this[key] = e.target.innerText
},
add() {
this.addEl = true
},
save() {
if (!this.value.at(-1)) {
return
}
if (this.type === '1') {
updateHwWeb({
webCode: this.value.at(-1),
// webJson: JSON.stringify(this.components),
webJsonString: JSON.stringify(this.components),
})
}
if (this.type === '2') {
updateHwWeb1({
webCode: this.value[0],
deviceId: this.value[2],
webJsonString: JSON.stringify(this.components),
})
}
},
pageChange(e) {
if (this.type === '1') {
getHwWeb(e.at(-1)).then(res => {
this.components = JSON.parse(res?.data?.webJsonString || '[]')
})
} else {
listHwWeb1({webCode: e[0], deviceId: e[2]}).then(e => {
this.components = JSON.parse(e.rows?.[0]?.webJsonString || '[]')
})
}
console.log(e)
},
addItem(e) {
this.components.push(JSON.parse(JSON.stringify({
type: e,
value: this.componentsM.find(v => v.type === e)?.value,
})))
this.addEl = false
},
moveUp(k) {
if (k > 0) {
const item = this.components[k]
this.components.splice(k, 1) //
this.components.splice(k - 1, 0, item) //
}
},
moveDown(k) {
if (k < this.components.length - 1) {
const item = this.components[k]
this.components.splice(k, 1) //
this.components.splice(k + 1, 0, item) //
}
},
typeChange(e) {
if (e === '1') {
selectMenuTree().then(v => {
console.log(v)
this.options = v.data.find(vv => vv.webMenuId === 4).children
})
this.props = {checkStrictly: true, value: 'webMenuId', label: 'webMenuName'}
}
if (e === '2') {
getHwWeb(7).then(res => {
console.log(JSON.parse(res?.data?.webJsonString || '{}').productList || [])
this.options = JSON.parse(res?.data?.webJsonString || '{}').productList || []
// this.pageData = JSON.parse(res?.data?.webJsonString || '[]')
})
this.props = {checkStrictly: true, value: 'id', label: 'name', children: 'list'}
}
}
}
}
</script>
<style scoped lang="less">
.top {
position: sticky;
top: 0;
z-index: 999;
width: 100%;
height: 50px;
background: #fff;
box-shadow: 0 6px 4px -4px rgba(0, 0, 0, 0.2);
text-align: left;
.title {
line-height: 50px;
margin-left: 12px;
display: inline-block;
margin-right: 12px;
}
}
.container {
width: 90%;
text-align: left;
margin: 0 auto;
}
.component {
text-align: center;
position: relative;
.up {
position: absolute;
right: 50px;
top: 10px;
cursor: pointer;
z-index: 99999;
}
.down {
position: absolute;
right: 30px;
top: 10px;
cursor: pointer;
z-index: 99999;
}
.del {
position: absolute;
right: 10px;
top: 10px;
cursor: pointer;
z-index: 99999;
}
}
.addItem {
width: 100%;
text-align: center;
}
</style>

@ -22,6 +22,10 @@
<EditEl9 v-if="i.type === 9" :data="i.value"/>
<EditEl10 v-if="i.type ===10" :data="i.value"/>
<EditEl11 v-if="i.type === 11" :data="i.value"/>
<EditEl12 v-if="i.type === 12" :data="i.value"/>
<EditEl13 v-if="i.type === 13" :data="i.value"/>
<EditEl14 v-if="i.type === 14" :data="i.value"/>
<EditEl15 v-if="i.type === 15" :data="i.value"/>
</div>
</div>
@ -42,6 +46,11 @@ import EditEl8 from "@/components/el/el8.vue";
import EditEl9 from "@/components/el/el9.vue";
import EditEl10 from "@/components/el/el10.vue";
import EditEl11 from "@/components/el/el11.vue";
import EditEl12 from "@/components/el/el12.vue";
import EditEl13 from "@/components/el/el13.vue";
import EditEl14 from "@/components/el/el14.vue";
import EditEl15 from "@/components/el/el15.vue";
import Copyright from '@/components/copyright'
import ContactUs from "@/views/index/contactUs.vue";
import Carousel from "@/components/el/carousel.vue";
@ -69,6 +78,10 @@ export default {
EditEl9,
EditEl10,
EditEl11,
EditEl12,
EditEl13,
EditEl14,
EditEl15,
},
data() {
return {
@ -76,383 +89,6 @@ export default {
addEl: false,
value: [],
components: [],
// components: [
// {
// type: 'carousel',
// value: {
// list: [
// {
// icon: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg',
// title: '111',
// value: '222'
// },
// {
// icon: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg',
// title: '222',
// value: '333'
// },
// {
// icon: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg',
// title: '333',
// value: '444'
// },
// {
// icon: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg',
// title: '444',
// value: '555'
// },
// {
// icon: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg',
// title: '555',
// value: '666'
// },
// {
// icon: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg',
// title: '666',
// value: '777'
// },
// {
// icon: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg',
// title: '666',
// value: '777'
// },
// ],
// },
// },
// {
// type: 1,
// value: {
// title: '123',
// subTitle: '456',
// list: [
// {
// icon: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg',
// title: '111',
// value: '222'
// },
// {
// icon: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg',
// title: '222',
// value: '333'
// },
// {
// icon: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg',
// title: '333',
// value: '444'
// },
// {
// icon: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg',
// title: '444',
// value: '555'
// },
// {
// icon: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg',
// title: '555',
// value: '666'
// },
// {
// icon: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg',
// title: '666',
// value: '777'
// },
// {
// icon: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg',
// title: '666',
// value: '777'
// },
// ],
// },
// },
// {
// type: 2,
// value: {
// title: '123',
// subTitle: '456',
// contentTitle: 'contentTitle',
// contentSubTitle: 'DEVELOPMENT PLATFORM',
// contentInfo: 'contentInfo',
// icon: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg',
// },
// },
// {
// type: 3,
// value: {
// title: '123',
// subTitle: '456',
// list: [
// {
// icon: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg',
// itemTitle: '111',
// itemInfo: '222'
// },
// {
// icon: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg',
// itemTitle: '222',
// itemInfo: '333'
// },
// {
// icon: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg',
// itemTitle: '333',
// itemInfo: '444'
// },
// {
// icon: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg',
// itemTitle: '444',
// itemInfo: '555'
// },
// {
// icon: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg',
// itemTitle: '555',
// itemInfo: '666'
// },
// {
// icon: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg',
// itemTitle: '666',
// itemInfo: '777'
// },
// ],
// },
// },
// {
// type: 4,
// value: {
// icon: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg',
// title: '123',
// subTitle: '456',
// list: [
// {
// title: '111',
// value: '222'
// },
// {
// title: '111',
// value: '222'
// },
// {
// title: '111',
// value: '222'
// },
// ],
// },
// },
// {
// type: 5,
// value: {
// icon: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg',
// title: '123',
// subTitle: '456',
// },
// },
// {
// type: 6,
// value: {
// icon: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg',
// title: '123',
// subTitle: '456',
// info: '789',
// },
// },
// {
// type: 7,
// value: {
// title: '123',
// subTitle: '456',
// list: [
// {
// icon: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg',
// title: '111',
// value: '222'
// },
// {
// icon: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg',
// title: '222',
// value: '333'
// },
// {
// icon: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg',
// title: '333',
// value: '444'
// },
// {
// icon: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg',
// title: '444',
// value: '555'
// },
// {
// icon: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg',
// title: '555',
// value: '666'
// },
// {
// icon: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg',
// title: '666',
// value: '777'
// },
// {
// icon: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg',
// title: '666',
// value: '777'
// },
// ],
// },
// },
// {
// type: 8,
// value: {
// title: '123',
// subTitle: '456',
// list: [
// {
// icon: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg',
// title: '111',
// leftTitle: '222',
// leftInfo: '333',
// infos: [
// {title: '111', info: '222'},
// {title: '111', info: '222'},
// {title: '111', info: '222'},
// ]
// },
// {
// icon: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg',
// title: '111',
// leftTitle: '222',
// leftInfo: '333',
// infos: [
// {title: '111', info: '222'},
// {title: '111', info: '222'},
// {title: '111', info: '222'},
// ]
// },
// ],
// },
// },
// {
// type: 9,
// value: {
// title: '123',
// subTitle: '456',
// list: [
// {
// icon: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg',
// value: '222'
// },
// {
// icon: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg',
// value: '333'
// },
// {
// icon: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg',
// value: '444'
// },
// {
// icon: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg',
// value: '555'
// },
// {
// icon: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg',
// value: '666'
// },
// {
// icon: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg',
// value: '777'
// },
// {
// icon: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg',
// value: '777'
// },
// ],
// },
// },
// {
// type: 10,
// value: {
// title: '123',
// subTitle: '456',
// list: [
// {
// icon: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg',
// title: '111',
// value: '222'
// },
// {
// icon: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg',
// title: '222',
// value: '333'
// },
// {
// icon: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg',
// title: '333',
// value: '444'
// },
// {
// icon: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg',
// title: '444',
// value: '555'
// },
// {
// icon: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg',
// title: '555',
// value: '666'
// },
// {
// icon: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg',
// title: '666',
// value: '777'
// },
// {
// icon: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg',
// title: '666',
// value: '777'
// },
// ],
// },
// },
// // {
// // type: 11,
// // value: {
// // title: '123',
// // subTitle: '456',
// // list: [
// // {
// // icon: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg',
// // title: '111',
// // value: '222'
// // },
// // {
// // icon: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg',
// // title: '222',
// // value: '333'
// // },
// // {
// // icon: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg',
// // title: '333',
// // value: '444'
// // },
// // {
// // icon: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg',
// // title: '444',
// // value: '555'
// // },
// // {
// // icon: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg',
// // title: '555',
// // value: '666'
// // },
// // {
// // icon: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg',
// // title: '666',
// // value: '777'
// // },
// // {
// // icon: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg',
// // title: '666',
// // value: '777'
// // },
// // ],
// // },
// // },
// ]
}
},
watch: {
@ -463,24 +99,11 @@ export default {
}
},
mounted() {
console.log(this.$route.query?.id)
getHwWeb(this.$route.query.id).then(res => {
this.components = JSON.parse(res?.data?.webJsonString || '[]')
})
},
methods: {
handleChange(val) {
console.log(val)
},
edit(key, e) {
this[key] = e.target.innerText
},
add() {
this.addEl = true
},
save() {
console.log(this.components)
}
}
}
</script>

@ -0,0 +1,543 @@
<template>
<div>
<div class="banner">
<el-image
style="width: 100%; height: 100%;position:absolute;top: 0;left: 0;"
:src="data.banner"
fit="contain"></el-image>
<el-image
style="width: 40%; height: 40%;position:absolute;right:10%;top: 30%;"
:src="data.banner1"
fit="contain"></el-image>
<div class="bannerInfo">{{ data.bannerTitle }}</div>
<div class="bannerValue">{{ data.bannerValue }}</div>
</div>
<div class="product-container">
<!-- 左侧大图 + 缩略图 -->
<div class="product-left">
<!-- 大图 -->
<div class="main-img">
<el-image :src="activeImg" fit="contain"></el-image>
</div>
<!-- 缩略图 -->
<div class="thumb-list">
<div
v-for="(img, index) in data.imgList"
:key="index"
class="thumb-item"
:class="{ active: activeIndex === index }"
@mouseenter="changeImg(index)"
>
<el-image :src="img.url" fit="cover"></el-image>
</div>
</div>
</div>
<!-- 右侧文字 -->
<div class="product-right">
<h2 class="title">产品特点</h2>
<ul class="features">
<li v-for="(item, i) in data.features" :key="i">
<i class="el-icon-circle-check"></i> {{ item.name }}
</li>
</ul>
</div>
</div>
<div class="param-container" style="padding: 5vw 10vw;background-color: #0001">
<h2 class="title1" style="line-height: 40px">产品参数</h2>
<div class="paramsTable" v-for="(param, index) in data.params" :key="index">
<div class="th">
<div class="th1">{{ param.title }}</div>
<div class="th2">参数值</div>
</div>
<div class="td">
<div v-for="(item, idx) in param.list" :key="idx">
<div class="td1">{{ item.name }}</div>
<div class="td2">{{ item.value }}</div>
</div>
</div>
</div>
</div>
<div class="param-container" style="padding: 5vw 10vw;background-color: #fff">
<h2 class="title1" style="line-height: 40px">资料下载</h2>
<div>
<div v-for="i in data.fileList" class="fileCard" style="text-align: left">
<div class="cardTitle">{{ i.name }}</div>
<div class="cardValue">{{ i.value }}</div>
<el-button @click="downFile(i.url,i.fileName)" type="primary" class="downIcon" icon="el-icon-download "
circle></el-button>
</div>
</div>
</div>
<ContactUs class="contactUs"/>
<Copyright class="copyright"/>
</div>
</template>
<script>
import ContactUs from '@/components/contactUs'
import Copyright from '@/components/copyright'
import {selectMenuTree} from "@/api/productCenter";
import {listHwWeb1} from "@/api/hwWeb";
export default {
name: 'ProductCenter',
components: {
ContactUs,
Copyright,
},
data() {
return {
activeIndex: 0,
data: {}
}
},
computed: {
activeImg() {
return this.data.imgList[this.activeIndex];
},
},
mounted() {
this.getData()
},
watch: {
'$route'() {
this.getData()
}
},
methods: {
changeImg(index) {
this.activeIndex = index;
},
getData() {
listHwWeb1({webCode: this.$route.query.type, deviceId: this.$route.query.id}).then(e => {
console.log(e)
this.data = e.rows?.[0]?.webJsonString ? JSON.parse(e.rows[0].webJsonString) : {
banner: '',
banner1: '',
bannerTitle: '设备名称',
bannerValue: '设备介绍',
imgList: [],
features: [],
params: [],
fileList: [],
}
})
},
async downFile(url, filename) {
try {
const response = await fetch(url, {mode: 'cors'});
if (!response.ok) throw new Error('网络错误');
const blob = await response.blob(); //
const blobUrl = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = blobUrl;
a.download = filename || url.split('/').pop();
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(blobUrl); //
} catch (err) {
console.error('下载失败:', err);
}
}
}
}
</script>
<style lang="less" scoped>
@import "~@/style.less";
.banner {
width: 100%;
height: 35.5vw;
position: relative;
.bannerInfo {
position: absolute;
top: 35%;
left: 19%;
width: 40%;
text-align: left;
font-size: 2.5vw;
color: #000;
font-weight: 700;
line-height: 3vw;
letter-spacing: 2px;
word-break: break-all;
}
.bannerValue {
position: absolute;
top: calc(35% + 3vw);
left: 19%;
width: 40%;
text-align: left;
font-size: 1vw;
color: #000;
font-weight: 500;
line-height: 2vw;
word-break: break-all;
}
.bannerBtn {
position: absolute;
top: 58%;
left: 19%;
width: 11.5vw;
font-size: 1.2vw;
line-height: 2vw;
letter-spacing: 2px;
}
.tabs {
position: absolute;
bottom: 0;
width: 100%;
background: linear-gradient(to bottom, fade(@standard-color, 10), fade(#fff, 10));
backdrop-filter: saturate(50%) blur(4px);
.content {
width: 62%;
position: relative;
left: 50%;
bottom: 0;
transform: translateX(-50%);
.tab {
display: inline-block;
width: 50%;
line-height: 6.2vw;
font-size: 1.6vw;
letter-spacing: 3px;
}
.tab.active {
color: @standard-color;
width: calc(50% - 3px);
border: 1px solid #fff;
box-shadow: 0 0 3px #0002;
}
}
}
}
.tabs {
text-align: left;
margin-top: 2.3vw;
/deep/ .el-tabs__header {
margin: 0 10vw 15px;
}
/deep/ .el-tabs__content {
padding: 0 10vw;
background-color: fade(@standard-color, 10);
}
/deep/ .el-tabs__nav-wrap::after {
display: none;
}
/deep/ .el-tabs__item {
letter-spacing: 3px;
padding: 0 2vw;
height: 2.9vw;
font-size: 1.6vw;
}
/deep/ .el-tabs__item {
line-height: 2.9vw;
}
/deep/ .el-tabs__item.is-active {
font-weight: 600;
color: @standard-color;
}
/deep/ .el-tabs__active-bar {
height: 4px;
background-color: @standard-color;
}
.content {
padding: 2.2vw 0;
display: inline-block;
width: 47%;
cursor: pointer;
&:nth-child(2n) {
margin-left: 5%;
}
&:hover {
.itemTitle {
color: #5c8eff;
}
.img-wrap {
.image {
transform: scale(1.2);
}
}
}
.custom-card {
width: 100%;
padding: 16px;
border-radius: 16px;
display: inline-block;
}
.itemTitle {
font-size: 26px;
font-weight: 600;
margin: 0;
text-align: center;
transition: all 0.5s ease;
}
.description {
font-size: 14px;
color: #666;
margin: 0;
margin-top: 12px;
line-height: 1.6;
overflow: hidden;
display: -webkit-box;
-webkit-line-clamp: 2; /* 限制两行 */
-webkit-box-orient: vertical;
text-overflow: ellipsis;
}
.btn-wrap {
display: flex;
justify-content: center;
}
.more-btn {
margin-top: 12px;
background-color: transparent;
border: 1px solid #dcdfe6;
border-radius: 20px;
padding: 6px 16px;
font-size: 14px;
color: #333;
display: flex;
align-items: center;
gap: 4px;
}
.more-btn:hover {
border-color: #409eff;
color: #409eff;
background-color: rgba(64, 158, 255, 0.05);
}
.icon {
font-size: 16px;
margin-left: 4px;
}
.img-wrap {
margin-top: 12px;
overflow: hidden;
.image {
transition: transform 0.5s ease;
}
}
}
}
.contactUs {
width: 100%;
background-color: #2e445c;
}
.copyright {
width: 100%;
background-color: #1d3348;
}
.product-container {
padding: 5vw 10vw;
display: flex;
gap: 40px;
}
.product-left {
width: 400px;
}
.main-img {
width: 100%;
height: 300px;
border: 1px solid #eee;
display: flex;
justify-content: center;
align-items: center;
}
.thumb-list {
margin-top: 16px;
display: flex;
gap: 10px;
}
.thumb-item {
width: 80px;
height: 60px;
border: 2px solid transparent;
cursor: pointer;
}
.thumb-item.active {
border-color: #409eff;
}
.thumb-item .el-image {
width: 100%;
height: 100%;
}
.product-right {
flex: 1;
}
.title {
font-size: 20px;
font-weight: bold;
margin-bottom: 12px;
}
.features {
list-style: none;
padding: 0;
margin: 0;
}
.features li {
font-size: 14px;
margin-bottom: 10px;
color: #333;
display: flex;
align-items: center;
line-height: 24px;
}
.features i {
color: #409eff;
margin-right: 6px;
}
.paramsTable {
.th {
background-color: #DBDFE7;
line-height: 3vw;
font-size: 1.3vw;
font-weight: 700;
text-align: left;
.th1 {
width: calc(30% - 2vw - 2px);
display: inline-block;
padding-left: 2vw;
border-right: 1px solid #0001
}
.th2 {
width: calc(70% - 2vw - 2px);
display: inline-block;
padding-left: 2vw;
}
}
.td {
line-height: 3vw;
font-size: 0.9vw;
text-align: left;
.td1 {
background-color: #F2F4F8;
width: calc(30% - 2vw - 2px);
display: inline-block;
padding-left: 2vw;
border: 1px solid #0001
}
.td2 {
background-color: #EEEEEE;
width: calc(70% - 2vw - 2px);
display: inline-block;
padding-left: 2vw;
border: 1px solid #0001
}
}
}
.fileCard {
display: inline-block;
width: 40%;
height: 100px;
border: 1px solid #ccc;
border-radius: 10px;
margin-top: 1vw;
position: relative;
.cardTitle {
position: absolute;
top: 10px;
left: 20px;
font-size: 22px;
font-weight: 700;
line-height: 45px;
width: calc(100% - 80px);
white-space: nowrap; /* 不换行 */
overflow: hidden; /* 超出部分隐藏 */
text-overflow: ellipsis; /* 超出部分显示省略号 */
}
.cardValue {
position: absolute;
top: 55px;
width: calc(100% - 80px);
left: 20px;
font-size: 14px;
line-height: 45px;
color: #aaa;
white-space: nowrap; /* 不换行 */
overflow: hidden; /* 超出部分隐藏 */
text-overflow: ellipsis; /* 超出部分显示省略号 */
}
.downIcon {
position: absolute;
right: 20px;
top: 50%;
transform: translateY(-50%);
}
&:nth-child(2n) {
margin-left: 5%;
}
}
</style>

@ -1,373 +1,125 @@
<template>
<div>
<div class="banner">
<el-image
style="width: 100%; height: 100%;position:absolute;top: 0;left: 0;"
:src="data.banner"
fit="contain"></el-image>
<el-image
style="width: 40%; height: 40%;position:absolute;right:10%;top: 30%;"
:src="data.banner1"
fit="contain"></el-image>
<div class="bannerInfo">{{ data.bannerTitle }}</div>
<div class="bannerValue">{{ data.bannerValue }}</div>
</div>
<div class="product-container">
<!-- 左侧大图 + 缩略图 -->
<div class="product-left">
<!-- 大图 -->
<div class="main-img">
<el-image :src="activeImg" fit="contain"></el-image>
</div>
<!-- 缩略图 -->
<div class="thumb-list">
<div
v-for="(img, index) in data.imgList"
:key="index"
class="thumb-item"
:class="{ active: activeIndex === index }"
@mouseenter="changeImg(index)"
>
<el-image :src="img.url" fit="cover"></el-image>
</div>
</div>
<div class="container">
<div v-if="$route.query.id === '1'">
<Carousel1 class="carousel"/>
<ProductCenter class="productCenter"/>
<ClassicCase class="classicCase"/>
<!-- <NewsCenter class="newsCenter"/>-->
<ContactUs class="contactUs"/>
<Copyright class="copyright"/>
</div>
<!-- 右侧文字 -->
<div class="product-right">
<h2 class="title">产品特点</h2>
<ul class="features">
<li v-for="(item, i) in data.features" :key="i">
<i class="el-icon-circle-check"></i> {{ item.name }}
</li>
</ul>
</div>
</div>
<div class="param-container" style="padding: 5vw 10vw;background-color: #0001">
<h2 class="title1" style="line-height: 40px">产品参数</h2>
<div class="paramsTable" v-for="(param, index) in data.params" :key="index">
<div class="th">
<div class="th1">{{ param.title }}</div>
<div class="th2">参数值</div>
</div>
<div class="td">
<div v-for="(item, idx) in param.list" :key="idx">
<div class="td1">{{ item.name }}</div>
<div class="td2">{{ item.value }}</div>
</div>
</div>
<div v-if="$route.query.id !== '1'" class="component" v-for="(i,k) in components">
<Carousel v-if="i.type === 'carousel'" :data="i.value"/>
<El1 v-if="i.type === 1" :data="i.value"/>
<El2 v-if="i.type === 2" :data="i.value"/>
<El3 v-if="i.type === 3" :data="i.value"/>
<El4 v-if="i.type === 4" :data="i.value"/>
<El5 v-if="i.type === 5" :data="i.value"/>
<El6 v-if="i.type === 6" :data="i.value"/>
<El7 v-if="i.type === 7" :data="i.value"/>
<El8 v-if="i.type === 8" :data="i.value"/>
<El9 v-if="i.type === 9" :data="i.value"/>
<El10 v-if="i.type ===10" :data="i.value"/>
<El11 v-if="i.type === 11" :data="i.value"/>
<El12 v-if="i.type === 12" :data="i.value"/>
<El13 v-if="i.type === 13" :data="i.value"/>
<El14 v-if="i.type === 14" :data="i.value"/>
<El15 v-if="i.type === 15" :data="i.value"/>
</div>
</div>
<div class="param-container" style="padding: 5vw 10vw;background-color: #fff">
<h2 class="title1" style="line-height: 40px">资料下载</h2>
<div>
<div v-for="i in data.fileList" class="fileCard" style="text-align: left">
<div class="cardTitle">{{ i.name }}</div>
<div class="cardValue">{{ i.value }}</div>
<el-button @click="downFile(i.url,i.fileName)" type="primary" class="downIcon" icon="el-icon-download "
circle></el-button>
</div>
</div>
</div>
<ContactUs class="contactUs"/>
<Copyright class="copyright"/>
</div>
</template>
<script>
import ContactUs from '@/components/contactUs'
import El1 from "@/components/el/el1.vue";
import El2 from "@/components/el/el2.vue";
import El3 from "@/components/el/el3.vue";
import El4 from "@/components/el/el4.vue";
import El5 from "@/components/el/el5.vue";
import El6 from "@/components/el/el6.vue";
import El7 from "@/components/el/el7.vue";
import El8 from "@/components/el/el8.vue";
import El9 from "@/components/el/el9.vue";
import El10 from "@/components/el/el10.vue";
import El11 from "@/components/el/el11.vue";
import El12 from "@/components/el/el12.vue";
import El13 from "@/components/el/el13.vue";
import El14 from "@/components/el/el14.vue";
import El15 from "@/components/el/el15.vue";
import Copyright from '@/components/copyright'
import {selectMenuTree} from "@/api/productCenter";
import {listHwWeb1} from "@/api/hwWeb";
import ContactUs from "@/views/index/contactUs.vue";
import Carousel from "@/components/el/carousel.vue";
import {getHwWeb, listHwWeb1} from "@/api/hwWeb";
import ProductCenter from "@/views/index/productCenter.vue";
import ClassicCase from "@/views/index/classicCase.vue";
import Carousel1 from "@/views/index/carousel.vue";
export default {
name: 'ProductCenter',
components: {
ClassicCase,
ProductCenter,
Carousel1,
Carousel,
ContactUs,
Copyright,
El1,
El2,
El3,
El4,
El5,
El6,
El7,
El8,
El9,
El10,
El11,
El12,
El13,
El14,
El15,
},
data() {
return {
activeIndex: 0,
data: {}
a: '1',
addEl: false,
value: [],
components: [],
}
},
computed: {
activeImg() {
return this.data.imgList[this.activeIndex];
},
},
mounted() {
this.getData()
},
watch: {
'$route'() {
this.getData()
listHwWeb1({webCode: this.$route.query.type, deviceId: this.$route.query.id}).then(e => {
this.components = JSON.parse(e.rows?.[0]?.webJsonString || '[]')
})
}
},
mounted() {
listHwWeb1({webCode: this.$route.query.type, deviceId: this.$route.query.id}).then(e => {
this.components = JSON.parse(e.rows?.[0]?.webJsonString || '[]')
})
},
methods: {
changeImg(index) {
this.activeIndex = index;
},
getData() {
listHwWeb1({webCode: this.$route.query.type, deviceId: this.$route.query.id}).then(e => {
console.log(e)
this.data = e.rows?.[0]?.webJsonString ? JSON.parse(e.rows[0].webJsonString) : {
banner: '',
banner1: '',
bannerTitle: '设备名称',
bannerValue: '设备介绍',
imgList: [],
features: [],
params: [],
fileList: [],
}
})
},
async downFile(url, filename) {
try {
const response = await fetch(url, {mode: 'cors'});
if (!response.ok) throw new Error('网络错误');
const blob = await response.blob(); //
const blobUrl = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = blobUrl;
a.download = filename || url.split('/').pop();
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(blobUrl); //
} catch (err) {
console.error('下载失败:', err);
}
}
}
}
</script>
<style scoped lang="less">
<style lang="less" scoped>
@import "~@/style.less";
.banner {
width: 100%;
height: 35.5vw;
position: relative;
.bannerInfo {
position: absolute;
top: 35%;
left: 19%;
width: 40%;
text-align: left;
font-size: 2.5vw;
color: #000;
font-weight: 700;
line-height: 3vw;
letter-spacing: 2px;
word-break: break-all;
}
.bannerValue {
position: absolute;
top: calc(35% + 3vw);
left: 19%;
width: 40%;
text-align: left;
font-size: 1vw;
color: #000;
font-weight: 500;
line-height: 2vw;
word-break: break-all;
}
.bannerBtn {
position: absolute;
top: 58%;
left: 19%;
width: 11.5vw;
font-size: 1.2vw;
line-height: 2vw;
letter-spacing: 2px;
}
.tabs {
position: absolute;
bottom: 0;
width: 100%;
background: linear-gradient(to bottom, fade(@standard-color, 10), fade(#fff, 10));
backdrop-filter: saturate(50%) blur(4px);
.content {
width: 62%;
position: relative;
left: 50%;
bottom: 0;
transform: translateX(-50%);
.tab {
display: inline-block;
width: 50%;
line-height: 6.2vw;
font-size: 1.6vw;
letter-spacing: 3px;
}
.tab.active {
color: @standard-color;
width: calc(50% - 3px);
border: 1px solid #fff;
box-shadow: 0 0 3px #0002;
}
}
}
}
.tabs {
.container {
width: 90%;
text-align: left;
margin-top: 2.3vw;
/deep/ .el-tabs__header {
margin: 0 10vw 15px;
}
/deep/ .el-tabs__content {
padding: 0 10vw;
background-color: fade(@standard-color, 10);
}
/deep/ .el-tabs__nav-wrap::after {
display: none;
}
/deep/ .el-tabs__item {
letter-spacing: 3px;
padding: 0 2vw;
height: 2.9vw;
font-size: 1.6vw;
}
/deep/ .el-tabs__item {
line-height: 2.9vw;
}
/deep/ .el-tabs__item.is-active {
font-weight: 600;
color: @standard-color;
}
/deep/ .el-tabs__active-bar {
height: 4px;
background-color: @standard-color;
}
.content {
padding: 2.2vw 0;
display: inline-block;
width: 47%;
cursor: pointer;
&:nth-child(2n) {
margin-left: 5%;
}
&:hover {
.itemTitle {
color: #5c8eff;
}
.img-wrap {
.image {
transform: scale(1.2);
}
}
}
.custom-card {
width: 100%;
padding: 16px;
border-radius: 16px;
display: inline-block;
}
.itemTitle {
font-size: 26px;
font-weight: 600;
margin: 0;
text-align: center;
transition: all 0.5s ease;
}
.description {
font-size: 14px;
color: #666;
margin: 0;
margin-top: 12px;
line-height: 1.6;
overflow: hidden;
display: -webkit-box;
-webkit-line-clamp: 2; /* 限制两行 */
-webkit-box-orient: vertical;
text-overflow: ellipsis;
}
.btn-wrap {
display: flex;
justify-content: center;
}
.more-btn {
margin-top: 12px;
background-color: transparent;
border: 1px solid #dcdfe6;
border-radius: 20px;
padding: 6px 16px;
font-size: 14px;
color: #333;
display: flex;
align-items: center;
gap: 4px;
}
.more-btn:hover {
border-color: #409eff;
color: #409eff;
background-color: rgba(64, 158, 255, 0.05);
}
.icon {
font-size: 16px;
margin-left: 4px;
}
.img-wrap {
margin-top: 12px;
overflow: hidden;
.image {
transition: transform 0.5s ease;
}
}
}
margin: 0 auto;
}
.component {
text-align: center;
position: relative;
}
.contactUs {
width: 100%;
background-color: #2e445c;
@ -378,166 +130,25 @@ export default {
background-color: #1d3348;
}
.product-container {
padding: 5vw 10vw;
display: flex;
gap: 40px;
}
.product-left {
width: 400px;
}
.main-img {
.carousel {
width: 100%;
height: 300px;
border: 1px solid #eee;
display: flex;
justify-content: center;
align-items: center;
height: 650px;
}
.thumb-list {
margin-top: 16px;
display: flex;
gap: 10px;
}
.thumb-item {
width: 80px;
height: 60px;
border: 2px solid transparent;
cursor: pointer;
}
.thumb-item.active {
border-color: #409eff;
}
.thumb-item .el-image {
.productCenter {
width: 100%;
height: 100%;
text-align: center;
}
.product-right {
flex: 1;
.classicCase {
width: 100%;
background-image: linear-gradient(to top, rgba(255, 255, 255, 1), rgba(255, 255, 255, 0)), url("~@/assets/image/bg.jpg");
background-size: 100% 36.41vw;
background-repeat: no-repeat;
}
.title {
font-size: 20px;
font-weight: bold;
margin-bottom: 12px;
.newsCenter {
width: 100%;
}
.features {
list-style: none;
padding: 0;
margin: 0;
}
.features li {
font-size: 14px;
margin-bottom: 10px;
color: #333;
display: flex;
align-items: center;
line-height: 24px;
}
.features i {
color: #409eff;
margin-right: 6px;
}
.paramsTable {
.th {
background-color: #DBDFE7;
line-height: 3vw;
font-size: 1.3vw;
font-weight: 700;
text-align: left;
.th1 {
width: calc(30% - 2vw - 2px);
display: inline-block;
padding-left: 2vw;
border-right: 1px solid #0001
}
.th2 {
width: calc(70% - 2vw - 2px);
display: inline-block;
padding-left: 2vw;
}
}
.td {
line-height: 3vw;
font-size: 0.9vw;
text-align: left;
.td1 {
background-color: #F2F4F8;
width: calc(30% - 2vw - 2px);
display: inline-block;
padding-left: 2vw;
border: 1px solid #0001
}
.td2 {
background-color: #EEEEEE;
width: calc(70% - 2vw - 2px);
display: inline-block;
padding-left: 2vw;
border: 1px solid #0001
}
}
}
.fileCard {
display: inline-block;
width: 40%;
height: 100px;
border: 1px solid #ccc;
border-radius: 10px;
margin-top: 1vw;
position: relative;
.cardTitle {
position: absolute;
top: 10px;
left: 20px;
font-size: 22px;
font-weight: 700;
line-height: 45px;
width: calc(100% - 80px);
white-space: nowrap; /* 不换行 */
overflow: hidden; /* 超出部分隐藏 */
text-overflow: ellipsis; /* 超出部分显示省略号 */
}
.cardValue {
position: absolute;
top: 55px;
width: calc(100% - 80px);
left: 20px;
font-size: 14px;
line-height: 45px;
color: #aaa;
white-space: nowrap; /* 不换行 */
overflow: hidden; /* 超出部分隐藏 */
text-overflow: ellipsis; /* 超出部分显示省略号 */
}
.downIcon {
position: absolute;
right: 20px;
top: 50%;
transform: translateY(-50%);
}
&:nth-child(2n) {
margin-left: 5%;
}
}
</style>
</style>

@ -24,7 +24,8 @@
<template v-for="(ii,kk) in i.list">
<div class="content">
<el-card class="custom-card" shadow="hover" @click="toDetail(ii.id)"
style="min-height: 300px;height: 30vw;box-sizing: border-box">
style="min-height: 300px;height: 30vw;box-sizing: border-box;position: relative;">
<i class="del el-icon-circle-close" @click="data.list[k].list.splice(kk, 1);"></i>
<!-- 标题 -->
<h2 class="itemTitle" contenteditable="true" @blur="edit2('name', k,kk,$event)">{{ ii.name }}</h2>
@ -101,6 +102,12 @@ export default {
<style lang="less" scoped>
@import "~@/style.less";
.del {
position: absolute;
right: 10px;
top: 10px;
cursor: pointer;
}
.title {
padding-top: 4.2vw;
width: 100%;
@ -261,4 +268,8 @@ export default {
animation: fadeOutLeft;
animation-duration: 0.5s;
}
/deep/ .el-tabs__new-tab {
color: #409eff;
}
</style>

Loading…
Cancel
Save