添加组件

master
suixy 5 months ago
parent 87c4feb562
commit 2f4bf558dd

@ -8,6 +8,13 @@ export function listHwWeb(query) {
params: query
})
}
export function listHwWeb1(query) {
return request({
url: '/portal/hwWeb1/list',
method: 'get',
params: query
})
}
// 查询haiwei官网json详细
export function getHwWeb(webId) {
@ -34,6 +41,13 @@ export function updateHwWeb(data) {
data: data
})
}
export function updateHwWeb1(data) {
return request({
url: '/portal/hwWeb1',
method: 'put',
data: data
})
}
// 删除haiwei官网json
export function delHwWeb(webId) {

@ -7,14 +7,15 @@
:show-file-list="false"
:on-success="handleAvatarSuccess"
:before-upload="beforeAvatarUpload">
<img style="width: 100%;height: 100%;object-fit: contain" v-if="data.icon" :src="data.icon" class="avatar">
<img style="width: 100%;height: 100%;object-fit: contain" v-if="data[field||'icon']" :src="data[field||'icon']"
class="avatar">
<i v-else style="width: 100%;height: 100%;font-size: 2vw" class="el-icon-plus avatar-uploader-icon"></i>
</el-upload>
</div>
</template>
<script>
export default {
props: ['data'],
props: ['data', 'field'],
data() {
return {
imageUrl: '/prod-api' + "/file/upload",
@ -23,7 +24,8 @@ export default {
methods: {
handleAvatarSuccess(res, file) {
if (res.code === 200) {
this.$props.data.icon = res.data.url
console.log(this.$props.data.icon)
this.$props.data[this.$props.field || 'icon'] = res.data.url
}
},
beforeAvatarUpload(file) {

@ -0,0 +1,77 @@
<template>
<div style=" ">
<el-upload
class="upload-demo"
:action="imageUrl"
multiple
:limit="1"
:on-success="handleAvatarSuccess"
:file-list="fileList">
<el-button size="small" type="primary">点击上传</el-button>
</el-upload>
</div>
</template>
<script>
export default {
props: ['data', 'field'],
data() {
return {
imageUrl: '/prod-api' + "/file/upload",
}
},
computed: {
fileList() {
return [{url: this.$props.data[this.$props.field || 'file'], name: this.$props.data.fileName}]
},
},
methods: {
handleAvatarSuccess(res, file, fileList) {
console.log(fileList)
if (res.code === 200) {
console.log(res)
this.$props.data[this.$props.field || 'file'] = res.data.url
this.$props.data.fileName = res.data.name
}
},
beforeAvatarUpload(file) {
if (!(file.type === 'image/jpeg' || file.type === 'image/png')) {
this.$message.error('上传图片只能是 JPG 或 PNG 格式!');
}
return file.type === 'image/jpeg' || file.type === 'image/png'
}
}
}
</script>
<style scoped>
.avatar-uploader .el-upload {
border: 1px dashed #d9d9d9;
border-radius: 6px;
cursor: pointer;
position: relative;
overflow: hidden;
}
/deep/ .el-upload {
width: 100%;
height: 100%;
}
.avatar-uploader .el-upload:hover {
border-color: #409EFF;
}
.avatar-uploader-icon {
font-size: 28px;
color: #8c939d;
width: 178px;
height: 178px;
line-height: 4vw;
text-align: center;
}
.avatar {
width: 178px;
height: 178px;
display: block;
}
</style>

@ -24,9 +24,14 @@ export default new Router({
},
{
path: 'productCenter', component: () => import('@/views/productCenter/index.vue'),
}, {
},
{
path: 'productCenter/edit', component: () => import('@/views/productCenter/edit/index.vue'),
}, {
},
{
path: 'productCenter/detail', component: () => import('@/views/productCenter/detail.vue'),
},
{
path: 'productCenter/detail/edit', component: () => import('@/views/productCenter/edit/detail.vue'),
},
{

@ -6,7 +6,7 @@ const TokenKey = 'Admin-Token'
const service = axios.create({
baseURL: '/dev-api',
// baseURL: 'http://124.223.15.102:8888',
timeout: 10000,
timeout: 10000000,
});
function getToken() {
return Cookies.get(TokenKey)

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

@ -2,13 +2,13 @@
<div>
<div class="banner">
<el-image
style="width: 100%; height: 100%;position:absolute;top: 0;left: 0;"
:src="data.banner"
fit="contain"></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>
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>
@ -25,11 +25,11 @@
<!-- 缩略图 -->
<div class="thumb-list">
<div
v-for="(img, index) in data.imgList"
:key="index"
class="thumb-item"
:class="{ active: activeIndex === index }"
@mouseenter="changeImg(index)"
v-for="(img, index) in data.imgList"
:key="index"
class="thumb-item"
:class="{ active: activeIndex === index }"
@mouseenter="changeImg(index)"
>
<el-image :src="img" fit="cover"></el-image>
</div>
@ -148,7 +148,7 @@ export default {
{ name: "产品重量", value: "约288g" },
{ name: "外壳材料", value: "铝合金+PC" },
{ name: "外壳颜色", value: "黑色、银色" },
{ name: "工作温度", value: "-25℃~60℃" },
{ name: "工作温度", value: "-25℃~60℃" },
{ name: "存储温度", value: "-40℃~85℃" },
{ name: "工作湿度", value: "5%~95%RH 无冷凝" },
{ name: "IP等级", value: "IP54" },
@ -326,7 +326,7 @@ export default {
cursor: pointer;
&:nth-child(2n){
margin-left: 5%;
}
}
&:hover{
.itemTitle {

@ -1,14 +1,13 @@
<template>
<div>
{{data}}
<el-button @click="save" class="save" type="primary"> </el-button>
<div class="banner">
<UploadEl style="width: 100%; height: 100%;position:absolute;top: 0;left: 0;" :data="{icon:data.banner}"/>
<UploadEl style="width: 40%; height: 40%;position:absolute;right:10%;top: 30%;" :data="{icon:data.banner1}"/>
<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>
<div class="product-container">
<!-- 左侧大图 + 缩略图 -->
<div class="product-left">
@ -26,10 +25,11 @@
:class="{ active: activeIndex === index }"
@mouseenter="changeImg(index)"
>
<UploadEl style=" " :data="{icon:img}"/>
<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('')">
@click="data.imgList.push({url:''})">
<i class="el-icon-circle-plus" style="font-size: 1vw; line-height: 60px"></i>
</div>
@ -40,7 +40,8 @@
<div class="product-right">
<h2 class="title">产品特点</h2>
<ul class="features">
<li v-for="(item, i) in data.features" :key="i">
<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 }}
@ -57,13 +58,15 @@
<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="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">
<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>
@ -86,10 +89,14 @@
<h2 class="title1" style="line-height: 40px">资料下载</h2>
<div>
<div v-for="i in fileList" class="fileCard" style="text-align: left">
<div class="cardTitle">{{ i.name }}</div>
<div class="cardValue">{{ i.value }}</div>
<el-button @click="downFile(i)" type="primary" class="downIcon" icon="el-icon-download " circle></el-button>
<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>
@ -104,77 +111,27 @@ import ContactUs from '@/components/contactUs'
import Copyright from '@/components/copyright'
import {selectMenuTree} from "@/api/productCenter";
import UploadEl from "@/components/editEl/uploadEl.vue";
import UploadFile from "@/components/editEl/uploadFile.vue";
import {addHwWeb, listHwWeb, listHwWeb1, updateHwWeb, updateHwWeb1} from "@/api/hwWeb";
export default {
name: 'ProductCenter',
components: {
UploadEl,
UploadFile,
ContactUs,
Copyright,
},
data() {
return {
fileList: [
{
name: '操作指南',
value: '硬件操作指南',
url: ''
},
{
name: '操作指南',
value: '硬件操作指南',
url: ''
},
],
activeIndex: 0,
data:{
banner: 'https://www.genrace.com/template/default/images/pages/prodDetail-banner.jpg',
banner1:'https://www.genrace.com/static/upload/image/20250414/1744615648137412.png',
bannerTitle: 'HW-R300系列',
bannerValue: '中端距离1路输入体积小巧TCP/RS485。',
imgList: [
"http://1.13.177.47:9665/statics/2025/08/25/%E5%BA%94%E7%94%A8%E5%BC%80%E5%8F%91_20250825192156A181.png",
"https://www.genrace.com/static/upload/image/20250414/1744615648137412.png",
"http://1.13.177.47:9665/statics/2025/08/25/23_20250825192255A182.png",
],
features: [{name:"紧凑型圆极化天线"},],
params:[
{
title:'参数',
list:[
{ name: "射频协议", value: "ISO/IEC 18000-63 /EPC Gen2v2" },
{ name: "工作频段", value: "中国频段920-925MHz\n其他国家频段可定制" },
{ name: "发射功率", value: "10-26dBm 可调,步进 1 dB精度±1dB" },
{ name: "天线增益", value: "3dBi" },
{ name: "天线驻波比", value: "≦21" },
{ name: "盘点速率", value: "120 tag/s" },
{ name: "读卡距离", value: "读取TPALN9662标签,最大读距1.4m(读距随标签型号不同而有所差异)" },
{ name: "通讯接口", value: "TCP/IPM12-4-A航空头、 RS485M12-5-B 航空头)" },
{ name: "通讯协议", value: "Modbus-RTU通信协议网口TCP提供基于C#的SDK接口适配工业总线协议外接网关选配" },
{ name: "GPIO端口", value: "M12-5-B 航空接口,兼容 5~24V 电平1路输入" },
{ name: "声音指示", value: "1个蜂鸣器" },
{ name: "开发接口", value: "支持 C#、JAVA" },
{ name: "供电电源", value: "1224VDC(推荐 12V 标配适配器)" },
{ name: "整机峰值功率", value: "2.5W" },
{ name: "外形尺寸", value: "90mm*90mm*32 mm" },
{ name: "产品重量", value: "约288g" },
{ name: "外壳材料", value: "铝合金+PC" },
{ name: "外壳颜色", value: "黑色、银色" },
{ name: "工作温度", value: "-25℃~60℃" },
{ name: "存储温度", value: "-40℃~85℃" },
{ name: "工作湿度", value: "5%~95%RH 无冷凝" },
{ name: "IP等级", value: "IP54" },
]
},
]
}
data: {}
}
},
computed: {
activeImg() {
return this.data.imgList[this.activeIndex];
return this.data?.imgList?.[this.activeIndex]?.url;
},
},
mounted() {
@ -201,24 +158,49 @@ export default {
edit4(key, index,index1, e) {
this.data.params[index].list[index1][key] = e.target.innerText
},
edit5(key, index, e) {
console.log(this.data.fileList[index][key])
this.data.fileList[index][key] = e.target.innerText
},
getData() {
selectMenuTree().then(e => {
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: [],
}
})
},
save() {
updateHwWeb1({
webCode: this.$route.query.type,
deviceId: this.$route.query.id,
webJsonString: JSON.stringify(this.data),
})
},
downFile(e) {
const blob = new Blob([''], {type: 'text/plain'});
const a = document.createElement('a');
a.href = url;
//
const link = document.createElement('a');
link.href = URL.createObjectURL(blob);
link.download = '文档.txt'; //
// filename
if (filename) {
a.download = filename;
} else {
// filename URL
a.download = url.split('/').pop();
}
//
link.click();
//
URL.revokeObjectURL(link.href);
document.body.appendChild(a);
a.click(); //
document.body.removeChild(a);
}
}
}
@ -469,6 +451,7 @@ export default {
height: 60px;
border: 2px solid transparent;
cursor: pointer;
position: relative;
}
.thumb-item.active {
@ -550,6 +533,7 @@ export default {
}
.fileCard {
vertical-align: top;
display: inline-block;
width: 40%;
height: 100px;
@ -595,4 +579,18 @@ export default {
margin-left: 5%;
}
}
.del {
position: absolute;
right: 0;
top: 0;
cursor: pointer;
}
.save {
position: fixed;
top: 100px;
right: 10px;
z-index: 999;
}
</style>

@ -1,5 +1,6 @@
<template>
<div>
<el-button @click="save" class="save" type="primary"> </el-button>
<div class="banner">
<el-image
style="width: 100%; height: 100%;position:absolute;top: 0;left: 0;"
@ -25,6 +26,7 @@
<script>
import ProduceModel from './produceModel.vue'
import {selectMenuTree} from "@/api/productCenter";
import {getHwWeb, updateHwWeb} from "@/api/hwWeb";
export default {
name: 'ProductCenter',
@ -39,6 +41,7 @@ export default {
bannerTitle: '',
productList: []
},
webMenuId: 0,
tabsData: [],
}
},
@ -47,10 +50,12 @@ export default {
},
methods: {
getData() {
getHwWeb(7).then(res => {
this.pageData = JSON.parse(res?.data?.webJsonString || '[]')
})
selectMenuTree().then(e => {
let tabsData = e.data.find(v => v.webMenuId === 7).children
this.tabsData = tabsData
console.log(tabsData)
tabsData.forEach(e => {
if (!this.pageData.productList.map(v => v.id).includes(e.webMenuId)) {
this.pageData.productList.push({
@ -66,6 +71,12 @@ export default {
checkTabs(e) {
this.tabsActive = e.webMenuId
},
save() {
updateHwWeb({
webCode: 7,
webJsonString: JSON.stringify(this.pageData),
})
}
}
}
</script>
@ -141,4 +152,11 @@ export default {
width: 100%;
background-color: #1d3348;
}
.save {
position: fixed;
top: 100px;
right: 10px;
z-index: 999;
}
</style>

@ -11,7 +11,6 @@
</span>
</div>
{{ JSON.stringify(data.list) }}
<div class="tabs">
<el-tabs v-model="activeName" :editable="true" @edit="tabEdit">
<el-tab-pane :name="`${k}`" v-for="(i,k) in data.list">
@ -72,10 +71,7 @@ export default {
}
},
methods: {
toDetail(id) {
console.log(this.$props.data.id)
console.log(id)
if (id) {
this.$router.push(`/productCenter/detail/edit?type=${this.$props.data.id}&id=${id}`)
}

@ -3,23 +3,21 @@
<div class="banner">
<el-image
style="width: 100%; height: 100%;position:absolute;top: 0;left: 0;"
:src="banner"
:src="pageData.banner"
fit="contain"></el-image>
<div class="bannerInfo">{{ bannerTitle }}</div>
<div class="bannerInfo">{{ pageData.bannerTitle }}</div>
<div class="tabs">
<div class="content">
<div @click="checkTabs(i,k)"
:style="`width:${tabsActive === k ? (100/productList.length+'%'):`calc(${100/productList.length}% - 2px)`}`"
:class="`tab ${tabsActive === k ? 'active':''}`" v-for="(i,k) in productList">
{{ i.name }}
:style="`width:${tabsActive === i.webMenuId ? (100/tabsData.length+'%'):`calc(${100/tabsData.length}% - 2px)`}`"
:class="`tab ${tabsActive === i.webMenuId ? 'active':''}`" v-for="(i,k) in tabsData">
{{ i.webMenuName }}
</div>
</div>
</div>
</div>
<div v-for="i in productList">
<ProduceModel :id="`item${i.id}`" :i="i" v-if="itemId === i.id"/>
</div>
<ProduceModel v-if="tabsActive" :data="pageData.productList.find(e=>e.id===tabsActive) || {}"/>
<ContactUs class="contactUs"/>
@ -32,6 +30,7 @@ import ContactUs from '@/components/contactUs'
import Copyright from '@/components/copyright'
import ProduceModel from './produceModel.vue'
import {selectMenuTree} from "@/api/productCenter";
import {getHwWeb} from "@/api/hwWeb";
export default {
name: 'ProductCenter',
@ -43,207 +42,13 @@ export default {
data() {
return {
tabsActive: 0,
bannerTitle: '',
itemId: '11',
banner: 'http://1.13.177.47:9665/statics/2025/07/24/mesnac_20250724093713A002.jpg',
productList: [
{
name: '轮胎RFID',
id: '11',
list: [
{
name: '分类1',
list: [
{
name: 'RFID轮胎',
value:'软控为轮胎产业链提供RFID轮胎整体解决方案包括系列化轮胎用RFID标签系列化RFID标签封胶设备、定制RFID标签贴合设备RFID 轮胎生产过程数据采集系统,及基于不同应用场景的信息化管理系统等。',
icon: 'http://1.13.177.47:9665/statics/2025/08/22/%E8%B5%84%E6%BA%90%208@4x_20250822150647A156.png'
},
]
},
]
},
{
name: '超高频RFID',
id: '12',
// value:'',
list: [
{
name: '超高频RFID读写器',
list: [
{
name: '一体式读写器(高性能)',
id: '1',
value:'内置高性能圆极化天线,实现远距离识别。',
icon: 'http://1.13.177.47:9665/statics/2025/08/22/%E4%B8%80%E4%BD%93%E5%BC%8F%E8%AF%BB%E5%86%99%E5%99%A8%EF%BC%88%E9%AB%98%E6%80%A7%E8%83%BD%EF%BC%89%EF%BC%8C%E5%86%85%E7%BD%AE%E9%AB%98%E6%80%A7%E8%83%BD%E5%9C%86%E6%9E%81%E5%8C%96%E5%A4%A9%E7%BA%BF%EF%BC%8C%E5%AE%9E%E7%8E%B0%E8%BF%9C%E8%B7%9D%E7%A6%BB%E8%AF%86%E5%88%AB%E3%80%82_20250822101411A021.png'
},
{
name: '一体式读写器(标准型)',
id: '2',
value:'内置高性能圆极化天线,用最小体积实现最优识别性能。',
icon: 'http://1.13.177.47:9665/statics/2025/08/22/%E4%B8%80%E4%BD%93%E5%BC%8F%E8%AF%BB%E5%86%99%E5%99%A8%EF%BC%88%E6%A0%87%E5%87%86%E5%9E%8B%EF%BC%89%EF%BC%8C%E5%86%85%E7%BD%AE%E9%AB%98%E6%80%A7%E8%83%BD%E5%9C%86%E6%9E%81%E5%8C%96%E5%A4%A9%E7%BA%BF%EF%BC%8C%E7%94%A8%E6%9C%80%E5%B0%8F%E4%BD%93%E7%A7%AF%E5%AE%9E%E7%8E%B0%E6%9C%80%E4%BC%98%E8%AF%86%E5%88%AB%E6%80%A7%E8%83%BD%E3%80%82_20250822101455A022.png'
},
{
name: '两通道车载式读写器',
value:'采用工业化防振动设计理念,支持蓝牙连接,提供更加稳定可靠的物理及电器连接方式。',
icon: 'http://1.13.177.47:9665/statics/2025/08/22/%E4%B8%A4%E9%80%9A%E9%81%93%E8%BD%A6%E8%BD%BD%E5%BC%8F%E8%AF%BB%E5%86%99%E5%99%A8%EF%BC%8C%E9%87%87%E7%94%A8%E5%B7%A5%E4%B8%9A%E5%8C%96%E9%98%B2%E6%8C%AF%E5%8A%A8%E8%AE%BE%E8%AE%A1%E7%90%86%E5%BF%B5%EF%BC%8C%E6%94%AF%E6%8C%81%E8%93%9D%E7%89%99%E8%BF%9E%E6%8E%A5%EF%BC%8C%E6%8F%90%E4%BE%9B%E6%9B%B4%E5%8A%A0%E7%A8%B3%E5%AE%9A%E5%8F%AF%E9%9D%A0%E7%9A%84%E7%89%A9%E7%90%86%E5%8F%8A%E7%94%B5%E5%99%A8%E8%BF%9E%E6%8E%A5%E6%96%B9%E5%BC%8F%E3%80%82_20250822101528A024.png'
},
{
name: '蓝牙手持式读写器',
value:'蓝牙数据上传采集数据可轻松接入用户Android移动终端易于安装与部署。',
icon: 'http://1.13.177.47:9665/statics/2025/08/22/%E8%93%9D%E7%89%99%E6%89%8B%E6%8C%81%E5%BC%8F%E8%AF%BB%E5%86%99%E5%99%A8_20250822101633A026.png'
},
{
name: 'RFID通道机',
value:'解决在供应链流通中,标签漏读串读等问题,应用于单品级物品识别,如快递、服装、皮具箱包、酒类等行业。',
icon: 'http://1.13.177.47:9665/statics/2025/08/22/RFID%E9%80%9A%E9%81%93%E6%9C%BA%EF%BC%8C%E8%A7%A3%E5%86%B3%E5%9C%A8%E4%BE%9B%E5%BA%94%E9%93%BE%E6%B5%81%E9%80%9A%E4%B8%AD%EF%BC%8C%E6%A0%87%E7%AD%BE%E6%BC%8F%E8%AF%BB%E4%B8%B2%E8%AF%BB%E7%AD%89%E9%97%AE%E9%A2%98%EF%BC%8C%E5%BA%94%E7%94%A8%E4%BA%8E%E5%8D%95%E5%93%81%E7%BA%A7%E7%89%A9%E5%93%81%E8%AF%86%E5%88%AB%EF%BC%8C%E5%A6%82%E5%BF%AB%E9%80%92%E3%80%81%E6%9C%8D%E8%A3%85%E3%80%81%E7%9A%AE%E5%85%B7%E7%AE%B1%E5%8C%85%E3%80%81%E9%85%92%E7%B1%BB%E7%AD%89%E8%A1%8C%E4%B8%9A%E3%80%82_20250822101716A028.png'
},
{
name: 'RFID通道门',
value:'RFID通道门具有窄波束、高增益特点适用于超高频门禁通道类、物流仓储、人员、图书、档案馆、医疗系统、设备资产等应用。',
icon: 'http://1.13.177.47:9665/statics/2025/08/22/RFID%E9%80%9A%E9%81%93%E9%97%A8%E5%85%B7%E6%9C%89%E7%AA%84%E6%B3%A2%E6%9D%9F%E3%80%81%E9%AB%98%E5%A2%9E%E7%9B%8A%E7%89%B9%E7%82%B9%EF%BC%8C%E9%80%82%E7%94%A8%E4%BA%8E%E8%B6%85%E9%AB%98%E9%A2%91%E9%97%A8%E7%A6%81%E9%80%9A%E9%81%93%E7%B1%BB%E3%80%81%E7%89%A9%E6%B5%81%E4%BB%93%E5%82%A8%E3%80%81%E4%BA%BA%E5%91%98%E3%80%81%E5%9B%BE%E4%B9%A6%E3%80%81%E6%A1%A3%E6%A1%88%E9%A6%86%E3%80%81%E5%8C%BB%E7%96%97%E7%B3%BB%E7%BB%9F%E3%80%81%E8%AE%BE%E5%A4%87%E8%B5%84%E4%BA%A7%E7%AD%89%E5%BA%94%E7%94%A8%E3%80%82_20250822101703A027.png'
},
]
},
{
name: '超高频RFID标签',
list: [
{
name: '耐高温标签',
value: 'R耐温范围为100℃~230℃。',
icon: 'http://1.13.177.47:9665/statics/2025/08/22/22_20250822102031A033.png'
},
{
name: '电缆标签',
value: '粘贴缠绕于物体表面,允许多次翻折缠绕。',
icon: 'http://1.13.177.47:9665/statics/2025/08/22/2222_20250822102107A035.png'
},
]
},
]
},
{
name: '高频RFID',
id: '13',
value:'介绍',
list: [
{
name: '高频RFID读头',
list: [
{
name: 'HW-RFR-050-B-003-B1204S',
id: '3',
//value:'111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111',
icon: 'http://1.13.177.47:9665/statics/2025/08/22/%E9%AB%98%E9%A2%91RFID%E8%AF%BB%E5%A4%B4_20250822100334A019.png'
},
]
},
{
name: '高频RFID一体机',
list: [
{
name: 'HW-RSLIM-HF',
//value:'1',
icon: 'http://1.13.177.47:9665/statics/2025/08/22/%E9%AB%98%E9%A2%91RFID%E4%B8%80%E4%BD%93%E6%9C%BA_20250822100352A020.png'
},
]
},
{
name: '高频RFID标签',
list: [
{
name: 'HW-PD50-HF',
// value:'1',
icon: 'http://1.13.177.47:9665/statics/2025/08/22/%E9%AB%98%E9%A2%91RFID%E5%9C%86%E7%8E%AF%E6%A0%87%E7%AD%BE_20250822093525A018.png'
},
]
},
]
},
{
name: '传感器',
id: '14',
// value:'',
list: [
{
name: '物联网硬件产品系列',
list: [
{
name: '无线传感器接收显示仪',
value:'支持 WiFi、以太网、4G、LORA 等通讯方式Modbus_RTUModbus_TCP支持客户定制通讯协议开发。',
icon: 'http://1.13.177.47:9665/statics/2025/08/22/%E6%97%A0%E7%BA%BF%E4%BC%A0%E6%84%9F%E5%99%A8%E6%8E%A5%E6%94%B6%E6%98%BE%E7%A4%BA%E4%BB%AA%E3%80%82%E6%94%AF%E6%8C%81%20WiFi%E3%80%81%E4%BB%A5%E5%A4%AA%E7%BD%91%E3%80%814G%E3%80%81LORA%20%E7%AD%89%E9%80%9A%E8%AE%AF%E6%96%B9%E5%BC%8F%EF%BC%9BModbus_RTU%EF%BC%8CModbus_TCP%EF%BC%8C%E6%94%AF%E6%8C%81%E5%AE%A2%E6%88%B7%E5%AE%9A%E5%88%B6%E9%80%9A%E8%AE%AF%E5%8D%8F%E8%AE%AE%E5%BC%80%E5%8F%91%E3%80%82_20250822103145A037.png'
},
{
name: '车载物联定位终端',
value:'车载物联定位终端, 支持 GPS/ 北斗定位 通过 内置 TPMS 或 RFID 读写器 模块 读取到的设备相关数据 ,用 4G无线 通讯 的方式上传 到企业数据平台或阿里云物 联网平台。',
icon: 'http://1.13.177.47:9665/statics/2025/08/22/%E8%BD%A6%E8%BD%BD_20250822103928A038.png'
},
{
name: '工业物联云智能终端',
value:'工业物联云智能终端,可以对电力、蒸汽等智能仪表及传感器进行数据采集,通过网络 通信方式上传到上位机系统,进行数据的集中处理。',
icon: 'http://1.13.177.47:9665/statics/2025/08/22/%E5%B7%A5%E4%B8%9A%E7%89%A9%E8%81%94%E4%BA%91%E6%99%BA%E8%83%BD%E7%BB%88%E7%AB%AF%EF%BC%8C%E5%8F%AF%E4%BB%A5%E5%AF%B9%E7%94%B5%E5%8A%9B%E3%80%81%E8%92%B8%E6%B1%BD%E7%AD%89%E6%99%BA%E8%83%BD%E4%BB%AA%E8%A1%A8%E5%8F%8A%E4%BC%A0%E6%84%9F%E5%99%A8%E8%BF%9B%E8%A1%8C%E6%95%B0%E6%8D%AE%E9%87%87%E9%9B%86%EF%BC%8C%E9%80%9A%E8%BF%87%E7%BD%91%E7%BB%9C%20%E9%80%9A%E4%BF%A1%E6%96%B9%E5%BC%8F%E4%B8%8A%E4%BC%A0%E5%88%B0%E4%B8%8A%E4%BD%8D%E6%9C%BA%E7%B3%BB%E7%BB%9F%EF%BC%8C%E8%BF%9B%E8%A1%8C%E6%95%B0%E6%8D%AE%E7%9A%84%E9%9B%86%E4%B8%AD%E5%A4%84%E7%90%86%E3%80%82_20250822103947A039.png'
},
{
name: '工业物联云智能终端',
value:'工业物联云智能终端具有 8 路开关量输入检测、16 开关量输出、RS485 总线、网络等硬件接口。',
icon: 'http://1.13.177.47:9665/statics/2025/08/22/%E5%B7%A5%E4%B8%9A%E7%89%A9%E8%81%94%E4%BA%91%E6%99%BA%E8%83%BD%E7%BB%88%E7%AB%AF%E5%85%B7%E6%9C%89%208%20%E8%B7%AF%E5%BC%80%E5%85%B3%E9%87%8F%E8%BE%93%E5%85%A5%E6%A3%80%E6%B5%8B%E3%80%8116%20%E5%BC%80%E5%85%B3%E9%87%8F%E8%BE%93%E5%87%BA%E3%80%81RS485%20%E6%80%BB%E7%BA%BF%E3%80%81%E7%BD%91%E7%BB%9C%E7%AD%89%E7%A1%AC%E4%BB%B6%E6%8E%A5%E5%8F%A3%E3%80%82_20250822104006A040.png'
},
]
},
]
},
{
name: '物联终端',
id: '15',
// value:'',
list: [
{
name: '物联网硬件产品系列',
list: [
{
name: '温湿度传感器',
value:'温湿度传感器支持2路输入采用传感器探头+采集主机的形式',
icon: 'http://1.13.177.47:9665/statics/2025/08/22/%E6%B8%A9%E6%B9%BF%E5%BA%A6%E4%BC%A0%E6%84%9F%E5%99%A8%EF%BC%8C%E6%94%AF%E6%8C%812%E8%B7%AF%E8%BE%93%E5%85%A5%EF%BC%8C%E9%87%87%E7%94%A8%E4%BC%A0%E6%84%9F%E5%99%A8%E6%8E%A2%E5%A4%B4+%E9%87%87%E9%9B%86%E4%B8%BB%E6%9C%BA%E7%9A%84%E5%BD%A2%E5%BC%8F%E3%80%82_20250822104331A042.png'
},
{
name: '无线温度传感器',
value:'无线温度传感器,电池可用 3 年; 温度测量范围:-40125℃精度±0.5℃ 25℃通讯距离视距范围 1500 米。 ',
icon: 'http://1.13.177.47:9665/statics/2025/08/22/%E6%97%A0%E7%BA%BF%E6%B8%A9%E5%BA%A6%E4%BC%A0%E6%84%9F%E5%99%A8_20250822104419A043.png'
},
{
name: 'EPD无线显示器',
value:'EPD无线显示器300米视距范围内的通信电池2年使用寿命提供显示模板定制化的服务。',
icon: 'http://1.13.177.47:9665/statics/2025/08/22/EPD%E6%97%A0%E7%BA%BF%E6%98%BE%E7%A4%BA%E5%99%A8%EF%BC%8C300%E7%B1%B3%E8%A7%86%E8%B7%9D%E8%8C%83%E5%9B%B4%E5%86%85%E7%9A%84%E9%80%9A%E4%BF%A1%EF%BC%8C%E7%94%B5%E6%B1%A02%E5%B9%B4%E4%BD%BF%E7%94%A8%E5%AF%BF%E5%91%BD%EF%BC%8C%E6%8F%90%E4%BE%9B%E6%98%BE%E7%A4%BA%E6%A8%A1%E6%9D%BF%E5%AE%9A%E5%88%B6%E5%8C%96%E7%9A%84%E6%9C%8D%E5%8A%A1%E3%80%82_20250822104449A044.png'
},
{
name: '红外温度传感器',
value:'红外温度传感器无接触式测温DC9~36V供电2.4寸TFT显示屏显示温度测量范围0~150℃精度±1℃支持RS485、无线LORA通讯通讯距离1500米。',
icon: 'http://1.13.177.47:9665/statics/2025/08/22/%E7%BA%A2%E5%A4%96%E6%B8%A9%E5%BA%A6%E4%BC%A0%E6%84%9F%E5%99%A8%EF%BC%8C%E6%97%A0%E6%8E%A5%E8%A7%A6%E5%BC%8F%E6%B5%8B%E6%B8%A9%EF%BC%8CDC9~36V%E4%BE%9B%E7%94%B5%EF%BC%8C2.4%E5%AF%B8TFT%E6%98%BE%E7%A4%BA%E5%B1%8F%E6%98%BE%E7%A4%BA%EF%BC%8C%E6%B8%A9%E5%BA%A6%E6%B5%8B%E9%87%8F%E8%8C%83%E5%9B%B4%EF%BC%9A0~150%E2%84%83%EF%BC%8C%E7%B2%BE%E5%BA%A6%C2%B11%E2%84%83%EF%BC%8C%E6%94%AF%E6%8C%81RS485%E3%80%81%E6%97%A0%E7%BA%BFLORA%E9%80%9A%E8%AE%AF%EF%BC%8C%E9%80%9A%E8%AE%AF%E8%B7%9D%E7%A6%BB1500%E7%B1%B3%E3%80%82_20250822104525A045.png'
},
]
},
]
},
{
name: '工业软件',
id: '16',
// value:'',
list: [
{
name: 'MOM',
list: [
{
name: 'MOM',
value:'平台向下连接海量设备,支撑设备数据采集和反向控制;向上为业务系统提供统一调用接口,为应用层的系统提供物联能力。并且自身具有完整的数据可视化组件、设备模型、数据中心能力。',
icon: 'http://1.13.177.47:9665/statics/2025/08/22/mes_20250822132455A075.png'
},
]
},
]
},
]
pageData: {
banner: 'http://1.13.177.47:9665/statics/2025/07/24/mesnac_20250724093713A002.jpg',
bannerTitle: '',
productList: [],
},
webMenuId: 0,
tabsData: [],
}
},
mounted() {
@ -276,13 +81,18 @@ export default {
},
methods: {
getData() {
getHwWeb(7).then(res => {
this.pageData = JSON.parse(res?.data?.webJsonString || '[]')
})
selectMenuTree().then(e => {
console.log(e)
let tabsData = e.data.find(v => v.webMenuId === 7).children
this.tabsData = tabsData
console.log(tabsData)
this.tabsActive = tabsData[0].webMenuId
})
},
checkTabs(e, k) {
this.tabsActive = k
this.itemId = e.id
this.tabsActive = e.webMenuId
},
}
}

@ -2,17 +2,17 @@
<div>
<div class="title">
<span>
{{ i.name }}
{{ data.name }}
</span>
</div>
<div class="subTitle">
<span>
{{ i.value }}
{{ data.value }}
</span>
</div>
<div class="tabs">
<el-tabs v-model="activeName">
<el-tab-pane :name="`${k}`" v-for="(i,k) in i.list">
<el-tab-pane :name="`${k}`" v-for="(i,k) in data.list">
<template slot="label">
<span>
{{ i.name }}
@ -21,7 +21,7 @@
<transition name="fade">
<div v-if="activeName === `${k}`" style="position:relative;">
<template v-for="ii in i.list">
<div class="content" @click="toDetail(ii.id)">
<div class="content" @click.stop="toDetail(ii.id)">
<el-card class="custom-card" shadow="hover" style="min-height: 300px;height: 30vw;box-sizing: border-box">
<!-- 标题 -->
@ -32,7 +32,7 @@
<!-- 按钮 -->
<div class="btn-wrap" v-if="ii.id">
<el-button class="more-btn" @click="$emit('more')">
<el-button class="more-btn" @click.stop="toDetail(ii.id)">
了解更多
<i class="el-icon-arrow-right icon"></i>
</el-button>
@ -59,7 +59,7 @@
</template>
<script >
export default {
props:['i'],
props: ['data'],
data(){
return {
activeName: '0',
@ -67,11 +67,12 @@ export default {
},
methods:{
toDetail(id){
toDetail(id) {
console.log(123123)
if (id) {
this.$router.push('/productCenter/detail' + id)
this.$router.push(`/productCenter/detail?type=${this.$props.data.id}&id=${id}`)
}
}
},
}
}
</script>

Loading…
Cancel
Save