This commit is contained in:
13713575202 2025-06-10 18:18:55 +08:00
commit 4f271fcb1d
24 changed files with 1084 additions and 93 deletions

View File

@ -26,6 +26,29 @@ export function getGoodDetail(id, params) {
});
}
// 获取购物车商品数量
export function getGoodNum(params) {
return request('user-center/shoppingCart/getShopCartGoodsCount', {
method: 'GET',
params,
});
}
// 商品加入购物车
export function addToCart(params) {
return request('/user-center/shoppingCart/addToCart', {
method: 'GET',
params,
});
}
// 立即购买商品按钮
export function quicklyBuy(data = {}) {
return request('goods/goodInfoManage/contentPage', {
method: 'POST',
data,
});
}
// 获取用户评价列表
export function agriculturalContent(data = {}) {
return request('goods/goodInfoManage/contentPage', {

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

View File

@ -0,0 +1,100 @@
<template>
<div>
<!-- 保留原有 el-breadcrumb class separator-icon -->
<el-breadcrumb :separator-icon="ArrowRight" class="breadcrumb">
<!-- 保留原有 el-breadcrumb-item class 结构 -->
<el-breadcrumb-item
v-for="(item, index) in breadcrumbs"
:key="index"
:class="['breadcrumb-item', { 'last-item': index === breadcrumbs.length - 1 }]"
class="breadcrumb-item"
@click="handleBreadcrumbClick(item)"
>
{{ item.title }}
</el-breadcrumb-item>
</el-breadcrumb>
</div>
</template>
<script setup>
import { ref, watch } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import { ArrowRight } from '@element-plus/icons-vue';
const router = useRouter();
const route = useRoute();
const breadcrumbs = ref([]);
//
const handleBreadcrumbClick = (item) => {
// 使paramsquery
router.push(item.fullPath || item.path);
};
watch(
route,
(newRoute) => {
breadcrumbs.value = newRoute.matched
.filter((item) => !item.meta?.hideInBread)
.map((item) => {
// namepath
const resolved = item.name
? router.resolve({
name: item.name,
params: newRoute.params,
query: newRoute.query,
})
: router.resolve({
path: item.path,
params: newRoute.params,
query: newRoute.query,
});
return {
title: item.meta?.title || item.name,
path: item.path, //
fullPath: resolved.href, //
meta: item.meta,
};
});
// sessionStorage
window.sessionStorage.setItem('currentChild', newRoute.name);
if (newRoute.name === 'main' || newRoute.name === 'smartFarmMain') {
window.sessionStorage.setItem('currentOpen', '0');
}
},
{ immediate: true }
);
</script>
<style lang="scss" scoped>
/* 完全保留原有样式 */
.breadcrumb {
padding: 0 10px 10px 10px;
font-size: 14px;
/* 保留hover效果 */
:deep(.el-breadcrumb__inner:not(.last-item):hover) {
color: var(--el-color-primary);
cursor: pointer;
}
/* 保留面包屑项的样式 */
:deep(.breadcrumb-item) {
&:hover {
color: var(--el-color-primary);
cursor: pointer;
}
}
:deep(.el-breadcrumb__inner) {
font-weight: bold;
}
:deep(.last-item .el-breadcrumb__inner) {
font-weight: normal !important;
}
:deep(.last-item .el-breadcrumb__inner:hover) {
color: var(--el-text-color-regular);
cursor: text;
}
}
</style>

View File

@ -53,7 +53,6 @@ watch(
imgUrl.value = props.url;
isViewVal.value = props.isView;
srcList = props.previewList;
console.log('getAssetsFile', getAssetsFile(imgUrl));
},
{
immediate: true,

View File

@ -14,10 +14,12 @@
</div>
</div>
<div class="layout-header-top-right">
<span class="block-icon" @click="toCart">
<div class="iconfont icon-shopcar" style="font-size: 12px"></div>
<span>购物车</span>
</span>
<el-badge :hidden="goodNum < 1" :value="goodNum" :max="99" class="item" :offset="[-3, 10]">
<span class="block-icon" @click="toCart">
<div class="iconfont icon-shopcar" style="font-size: 12px"></div>
<span>购物车</span>
</span>
</el-badge>
<span>商家中心</span>
<span @click="toUserCenter">个人中心</span>
<span class="block-icon" @click="toHome">
@ -30,7 +32,7 @@
<div class="layout-header-bottom-left">
<div class="layout-header-bottom-search">
<div class="title">
<img :src="getAssetsFile('images/logo.png')" />
<img :src="getAssetsFile('images/logo1.png')" />
</div>
<div class="search-warp">
<el-input v-model="keyword" placeholder="请输入关键词进行搜索"></el-input>
@ -41,12 +43,12 @@
<div class="layout-header-bottom-right">
<div class="layout-header-bottom-right-qr">
<div class="layout-header-bottom-right-qr-img">
<img :src="qrImg" alt="" />
<p>下载数农App</p>
<img :src="getAssetsFile('images/basic/QRCodeZWY.png')" alt="" />
<p>政务云App</p>
</div>
<div class="layout-header-bottom-right-qr-img">
<img :src="qrImg" alt="" />
<p>打开数农小程序</p>
<img :src="getAssetsFile('images/basic/QRCodeYYY.png')" alt="" />
<p>运营云APP</p>
</div>
</div>
</div>
@ -63,11 +65,13 @@
</template>
<script setup name="layout-header">
import { ref } from 'vue';
import { ref, onMounted, onBeforeUnmount } from 'vue';
import { qrImg } from './base64img';
import AppLink from '../Menu/Link.vue';
import { useRouter } from 'vue-router';
import { getAssetsFile } from '@/utils';
import { getGoodNum } from '@/apis/agricultural.js';
import { useMethodsStore } from '@/store/modules/methods';
const router = useRouter();
@ -105,6 +109,26 @@ const meuns = ref([
},
]);
const goodNum = ref(0);
const methodsStore = useMethodsStore();
const getGoods = () => {
getGoodNum().then((res) => {
goodNum.value = res.data ? res.data : 0;
});
};
onMounted(() => {
getGoods();
methodsStore.registerOuterMethod(getGoods);
});
//
onBeforeUnmount(() => {
methodsStore.registerOuterMethod(null);
});
function Search() {
console.log(keyword.value, 'search');
}
@ -235,26 +259,34 @@ const toCart = () => {
.title {
font-size: 45px;
white-space: nowrap;
img {
height: 70px;
}
}
.search-warp {
position: relative;
padding-left: 36px;
width: 80%;
.el-input {
width: 50%;
width: 76%;
height: 50px;
font-size: 18px;
flex-grow: 1;
border-radius: 14px;
:deep(.el-input__wrapper) {
padding-right: 100px;
border-radius: 14px;
border: 1px solid rgb(49, 202, 141);
box-shadow: none !important; /* 移除默认的阴影边框 */
}
}
.el-button {
position: absolute;
top: 50%;
right: 25%;
right: 11.8%;
border-radius: 12px;
padding: 0 24px;
height: 42px;
height: 43px;
font-size: 18px;
transform: translateY(-50%);
}
@ -297,4 +329,7 @@ const toCart = () => {
background-color: #f8f8f8;
}
}
.layout-header-bottom-right {
margin-top: 0;
}
</style>

View File

@ -383,29 +383,36 @@ export const constantRoutes = [
meta: { title: '电商交易' },
children: [
{
path: '/ecommerce',
path: '/sub-operation-service/ecommerce-agricultural',
component: Views,
redirect: '/sub-operation-service/ecommerce-agricultural',
name: 'agriculturalParent',
name: 'agricultural',
meta: { title: '农资交易', headerActive: 'ecommerce' },
children: [
{
path: '/sub-operation-service/ecommerce-agricultural',
path: '',
component: () => import('@/views/ecommerce/index.vue'),
name: 'agricultural',
meta: { title: '农资交易', headerActive: 'ecommerce' },
name: 'agriculturalMain',
meta: { title: '农资交易', headerActive: 'ecommerce', hideInBread: true },
},
{
path: '/sub-operation-service/ecommerce-agriculturalDetail',
component: () => import('@/views/ecommerce/agriculturalDetail.vue'),
name: 'agriculturalDetail',
path: 'ecommerce-agriculturalDetail',
component: Views,
name: 'agriculturalDetails',
meta: { title: '农资详情', headerActive: 'ecommerce' },
},
{
path: '/sub-operation-service/ecommerce-sourceCodeDetail',
component: () => import('@/views/ecommerce/sourceCodeDetail.vue'),
name: 'sourceCodeDetail',
meta: { title: '溯源详情', headerActive: 'ecommerce' },
children: [
{
path: '',
component: () => import('@/views/ecommerce/agriculturalDetail.vue'),
name: 'agriculturalDetail',
meta: { title: '农资详情', headerActive: 'ecommerce', hideInBread: true },
},
{
path: 'source',
component: () => import('@/views/ecommerce/sourceCodeDetail.vue'),
name: 'sourceCodeDetail',
meta: { title: '农产品溯源详情', headerActive: 'ecommerce' },
},
],
},
],
},
@ -430,12 +437,39 @@ export const constantRoutes = [
},
],
},
{
path: '/sub-operation-service/ecommerce-supplier',
component: () => import('@/views/ecommerce/supplier.vue'),
component: Views,
name: 'supplier',
meta: { title: '供应商服务', headerActive: 'ecommerce' },
meta: { title: '农产品交易', headerActive: 'ecommerce' },
children: [
{
path: '',
component: () => import('@/views/ecommerce/supplier.vue'),
name: 'supplierMain',
meta: { title: '农产品交易', headerActive: 'ecommerce', hideInBread: true },
},
{
path: 'detail',
component: Views,
name: 'supplierDetails',
meta: { title: '农产品详情', headerActive: 'ecommerce' },
children: [
{
path: '',
component: () => import('@/views/ecommerce/supplierDetail.vue'),
name: 'supplierDetail',
meta: { title: '农产品详情', headerActive: 'ecommerce', hideInBread: true },
},
{
path: 'source',
component: () => import('@/views/ecommerce/sourceCodeDetail.vue'),
name: 'sourceDetail',
meta: { title: '溯源详情', headerActive: 'ecommerce' },
},
],
},
],
},
{
path: '/sub-operation-service/ecommerce-land',

View File

@ -0,0 +1,21 @@
// store/methodsStore.js
import { defineStore } from 'pinia';
export const useMethodsStore = defineStore('methods', {
state: () => ({
outerMethod: null, // 存储外层组件的方法
}),
actions: {
// 注册外层组件的方法
registerOuterMethod(method) {
this.outerMethod = method;
},
// 调用外层组件的方法
callOuterMethod(...args) {
if (this.outerMethod && typeof this.outerMethod === 'function') {
return this.outerMethod(...args);
}
console.warn('外层方法未注册');
},
},
});

View File

@ -3,13 +3,6 @@
<common current-name="agricultural">
<template #main>
<div class="agricultural-detail-info">
<div class="top-title">
<div class="father-title" @click="toBack(-1)">
<el-icon><ArrowLeftBold /></el-icon>商品信息
</div>
<div class="current-title">查看详情</div>
</div>
<div class="top-info">
<el-row :gutter="16">
<el-col :span="12">
@ -64,10 +57,10 @@
</div>
</div>
<div class="top-btn">
<div class="item-btn sign">
<div class="item-btn sign" @click="buyGood">
<span>立即购买</span>
</div>
<div class="item-btn reservation">
<div class="item-btn reservation" @click="addGoodToCart">
<span>加入购物车</span>
</div>
</div>
@ -148,6 +141,11 @@ import { qrImg } from '@/layouts/component/Header/base64img.js';
import evaluate from './components/evaluate.vue';
import { useRoute, useRouter } from 'vue-router';
import { getGoodDetail } from '@/apis/agricultural.js';
import { addToCart, quicklyBuy } from '../../apis/agricultural.js';
import { useMethodsStore } from '@/store/modules/methods';
import { ElMessage } from 'element-plus';
const methodsStore = useMethodsStore();
const route = useRoute();
const router = useRouter();
@ -331,12 +329,18 @@ let saveInfo = reactive({
onMounted(() => {
showDetail.value = false;
// const num = Number(pId);
getGoodDetail(goodId).then(async (res) => {
currentGood.value = res.data;
//
await formattedData(res.data);
showDetail.value = true;
});
getGoodDetail(goodId)
.then(async (res) => {
if (res.code === 200) {
currentGood.value = res.data;
//
await formattedData(res.data);
showDetail.value = true;
}
})
.catch((e) => {
console.log(e);
});
// if (num === 55) {
// // 1. 0, 1, 2, 3
// const allIndices = [0, 1, 2, 3];
@ -388,22 +392,42 @@ const formattedData = (data) => {
currentGood.value.attribute = Object.entries(data.attribute).map(([key, value]) => ({ key, value }));
}
if (currentGood.value.detailUrl) {
currentGood.value.detailUrl = currentGood.value.detailUrl.replace(/'/g, '"');
currentGood.value.detailUrl = JSON.parse(currentGood.value.detailUrl);
currentGood.value.detailUrl = currentGood.value.detailUrl.split(',');
}
currentGood.value.goodUrls = data.goodUrl.split(',');
console.log(currentGood.value);
};
const toCodeDetail = () => {
let id = '01';
router.push('/sub-operation-service/ecommerce-sourceCodeDetail?id=' + id);
router.push('/sub-operation-service/ecommerce-agricultural/ecommerce-agriculturalDetail/source?id=' + goodId);
};
const toBack = (level) => {
router.go(level);
};
const buyGood = () => {
const obj = {
goodsId: goodId,
weightId: currentGood.value.netWeight[currentWeight.value].id, // ID
quantity: saveInfo.num,
};
// quicklyBuy(obj).then((res) => {});
};
const addGoodToCart = () => {
const obj = {
goodsId: goodId, // ID
weightId: currentGood.value.netWeight[currentWeight.value].id, // ID
quantity: saveInfo.num, // 1
};
addToCart(obj).then((res) => {
if (res.code === 200) {
methodsStore.callOuterMethod();
ElMessage.success('添加成功');
}
});
};
const toCopy = () => {};
</script>
<style lang="scss" scoped>
@ -587,9 +611,17 @@ const toCopy = () => {};
line-height: 42px;
&.sign {
background: $color-main;
cursor: pointer;
}
&.sign:hover {
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15); /* 添加阴影效果 */
}
&.reservation {
background: $color-warning;
cursor: pointer;
}
&.reservation:hover {
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15); /* 添加阴影效果 */
}
}
}

View File

@ -8,6 +8,7 @@
</template>
</div>
<div class="common-content">
<bread-comp></bread-comp>
<slot v-if="$slots.main" name="main"></slot>
<template v-else></template>
</div>

View File

@ -1,5 +1,28 @@
<template>
<div class="filter-top-warp">
<div style="width: 40%; margin-left: 10px">
<div class="search-container">
<div class="search-box">
<input type="text" placeholder="请输入农资商品名称" class="search-input" />
<button class="search-button">
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<circle cx="11" cy="11" r="8"></circle>
<line x1="21" y1="21" x2="16.65" y2="16.65"></line>
</svg>
</button>
</div>
</div>
</div>
<div v-for="(n, index) in maxLevelAndNodes.LevelKey" :key="index" class="filter-item">
<div class="single-item">
<div class="single-li all" :class="maxLevelAndNodes.LevelVal[n].id == '' ? 'li-act' : ''" @click="selectAll(n)">全部</div>
@ -127,6 +150,10 @@ const selectAll = (key) => {
const emit = defineEmits(['select']);
</script>
<style lang="scss" scoped>
.el-input-group--append > .el-input__wrapper {
border-top-left-radius: 16px !important;
border-bottom-left-radius: 16px !important;
}
.filter-top-warp {
padding: 16px;
width: 100%;
@ -162,4 +189,51 @@ const emit = defineEmits(['select']);
}
}
}
.search-container {
display: flex;
justify-content: center;
padding: 0 16px 0 0;
}
.search-box {
position: relative;
width: 100%;
max-width: 600px;
}
.search-input {
width: 100%;
padding: 10px;
border: 1px solid black;
border-radius: 14px;
font-size: 14px;
color: #333;
outline: none;
transition: border-color 0.3s;
}
.search-input:focus {
border-color: #409eff;
}
.search-input::placeholder {
color: #999;
}
.search-button {
position: absolute;
right: -10px;
top: 55%;
transform: translateY(-50%);
background: transparent;
border: none;
cursor: pointer;
padding: 4px;
color: #000;
}
.search-button:hover {
color: #409eff;
}
</style>

View File

@ -26,6 +26,10 @@ const props = defineProps({
type: Object,
default: () => {},
},
type: {
type: Number,
default: () => 1,
},
});
const handleImageError = (e) => {
@ -33,7 +37,11 @@ const handleImageError = (e) => {
};
const toDetail = (id, pid) => {
router.push('/sub-operation-service/ecommerce-agriculturalDetail?id=' + id + '&pid=' + pid);
if (props.type === 2) {
router.push('/sub-operation-service/ecommerce-supplier/detail?id=' + id + '&pid=' + pid);
} else {
router.push('/sub-operation-service/ecommerce-agricultural/ecommerce-agriculturalDetail?id=' + id + '&pid=' + pid);
}
};
</script>
<style lang="scss" scoped>
@ -46,11 +54,9 @@ const toDetail = (id, pid) => {
width: 100%;
height: 168px;
border-radius: 16px;
::v-deep() {
.el-image {
width: 100%;
height: 168px;
}
:deep(.el-image) {
width: 100%;
height: 168px;
}
}
.goods-name {

View File

@ -4,11 +4,6 @@
<template #main>
<div class="source-code-detail-info">
<div class="top-warp-b">
<div class="top-title">
<div class="father-title" @click="toBack(-2)">农资交易</div>
<div class="father-title father-after" @click="toBack(-1)">查看详情</div>
<div class="current-title">溯源详情</div>
</div>
<div class="top-img-txt">
<el-image :src="getAssetsFile('images/ecommerce/' + 'tracetxt.png')?.href ?? ''" fit="cover" />
</div>
@ -184,7 +179,7 @@
</common>
</div>
</template>
<script setup name="ecommerce">
<script setup>
import common from './components/common.vue';
import { ref, reactive, onMounted, watch, computed } from 'vue';
import { isEmpty, getAssetsFile } from '@/utils';

View File

@ -8,7 +8,7 @@
<div class="goods-list">
<template v-for="(n, index) in list" :key="n.id">
<div class="goods-item">
<goodsItem :data="n"></goodsItem>
<goodsItem :data="n" :type="2"></goodsItem>
</div>
</template>
</div>
@ -90,35 +90,11 @@ const handleCurrentChange = (val) => {
getList();
};
const sortTreeByDescendingId = (nodes) => {
if (!nodes || !nodes.length) return [];
// BigInt
const sortedNodes = [...nodes].sort((a, b) => {
const idA = BigInt(a.id);
const idB = BigInt(b.id);
return idA > idB ? -1 : idA < idB ? 1 : 0; //
});
// children
sortedNodes.forEach((node) => {
if (node.children && node.children.length) {
node.children = sortTreeByDescendingId(node.children);
}
});
return sortedNodes;
};
const getTree = () => {
transaction().then((res) => {
if (res.code === 200) {
// 2. 使
const sortedData = sortTreeByDescendingId(res.data);
treeList.splice(0, treeList.length, ...sortedData);
// let a = res.data.sort((a, b) => Number(b.id) - Number(a.id));
// treeList.splice(0, treeList.length, ...a);
// console.log('treeList', treeList);
let a = res.data.sort((a, b) => Number(b.id) - Number(a.id));
treeList.splice(0, treeList.length, ...a);
}
});
};

View File

@ -0,0 +1,692 @@
<template>
<div class="agricultural-detail-warp">
<common current-name="agricultural">
<template #main>
<div class="agricultural-detail-info">
<div class="top-info">
<el-row :gutter="16">
<el-col :span="12">
<banner
v-if="currentGood.goodUrls.length > 0"
name="landdetail"
:imglist="currentGood.goodUrls"
:is-montage="false"
indicator-pos="none"
arrow="always"
height="340px"
:is-view="true"
>
</banner>
</el-col>
<el-col :span="12" class="top-info-txt">
<h1 class="title">{{ currentGood.goodName }}</h1>
<div class="price-sold">
<span class="price">{{ currentPrice }}</span>
<span class="sold">{{ currentGood.salesVolume }}</span>
</div>
<div class="tips-list">
<el-row :gutter="16">
<el-col :span="24">发货地址{{ currentGood.detailAddress }}</el-col>
<el-col :span="24"
>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{{
currentGood.safeguard ? currentGood.safeguard.options[0].text : ''
}}</el-col
>
</el-row>
</div>
<div class="spu-sku-list">
<div class="spu-title">规格</div>
<div class="spu-sku-warp">
<div
v-for="(item, index) in currentGood.netWeight"
:key="index"
class="spu-sku-item"
:class="[index === currentWeight ? 'act' : 'normal']"
@click="currentWeight = index"
>
{{ item.goodSpecs }}{{ item.unit }}
</div>
</div>
<div class="goods-num">
<div class="num-title">数量</div>
<div class="num-warp">
<el-input-number v-model="saveInfo.num" :min="1" :max="10" />
<span v-if="currentStock !== 0" class="is-have">有货: {{ currentStock }}</span>
<span v-else class="is-have">售罄</span>
</div>
</div>
</div>
<div class="top-btn">
<div class="item-btn sign">
<span>立即购买</span>
</div>
<div class="item-btn reservation">
<span>加入购物车</span>
</div>
</div>
</el-col>
</el-row>
<signProcess></signProcess>
</div>
<div class="agricultural-detail-content">
<div class="detail-content">
<div class="tab-top">
<el-radio-group v-model="tabVal">
<el-radio-button v-for="(t, indext) in tabList" :key="t.name" :value="t.value">{{ t.label }}</el-radio-button>
</el-radio-group>
</div>
<div class="tab-content">
<div v-if="tabVal === 'detail'" class="content-detail">
<div v-if="showDetail" style="display: flex; justify-content: center">
<el-descriptions class="detail-des" title=" " :column="2" size="large" border>
<el-descriptions-item v-for="item in currentGood.attribute" :key="item.key">
<template #label>
<div class="cell-item">{{ item.value.name }}</div>
</template>
<span>{{ item.value.value }}</span>
</el-descriptions-item>
</el-descriptions>
</div>
<div style="display: flex; justify-content: center; flex-wrap: wrap">
<el-image
v-for="(item, index) in currentGood.detailUrl"
:key="index"
:src="item"
style="width: 90%; margin: 5px 0"
fit="contain"
/>
</div>
</div>
<div v-if="tabVal == 'sourceCode'" class="content-source-code">
<div class="code-warp">
<div class="code-img">
<el-image :src="qrImg" fit="cover" />
</div>
<div class="code-down">
<el-icon><Download /></el-icon>
<a>下载溯源码</a>
</div>
<div class="code-copy">
<div class="code-txt">
<span class="txt-ellipsis clamp1" style="width: 100%">10.5488754215478XE254.10405488754215478XE254201</span>
</div>
<div class="do-copy">
<el-button type="primary" @click="toCopy">复制</el-button>
</div>
</div>
<div class="code-to-detail">
<el-button type="primary" @click="toCodeDetail">点击查看溯源详情</el-button>
</div>
</div>
</div>
<div v-if="tabVal == 'evaluate'" class="content-evaluate">
<evaluate :good-id="goodId" :good-url="currentGood.goodUrls[0]"></evaluate>
</div>
</div>
</div>
</div>
</div>
</template>
</common>
</div>
</template>
<script setup name="ecommerce">
import common from './components/common.vue';
import banner from './components/banner.vue';
import { onMounted, reactive, ref, computed } from 'vue';
import { getAssetsFile } from '@/utils';
import { qrImg } from '@/layouts/component/Header/base64img.js';
import evaluate from './components/evaluate.vue';
import { useRoute, useRouter } from 'vue-router';
import { getGoodDetail } from '@/apis/agricultural.js';
const route = useRoute();
const router = useRouter();
const goodId = route.query.id; //
const pId = route.query.pid;
const currentWeight = ref(0);
let bannerList = reactive(['images/ecommerce/' + 'banner.png', 'images/ecommerce/' + 'banner.png']);
const tabList = reactive([
{ label: '详情介绍', value: 'detail' },
{ label: '溯源码', value: 'sourceCode' },
{ label: '评价', value: 'evaluate' },
]);
const currentIndex = ref(0);
const showDetail = ref(true);
const currentGood = ref({
showPic: false,
goodUrls: [],
attribute: [],
});
const currentPrice = computed(() => {
return currentGood.value?.netWeight?.[currentWeight.value]?.goodPrice ?? 0;
});
const currentStock = computed(() => {
return currentGood.value?.netWeight?.[currentWeight.value]?.goodStock ?? 0;
});
const mockData = [
{
goodName: '甜糯玉米种子',
sold: 1200,
price: 25,
sendAddress: '河南信阳',
safeguard: '七天保价',
weight: ['100g', '200g'],
goodUrl: ['images/mockPic/cornTop.png'],
detailUrl: ['cornBottom1.png', 'cornBottom2.png', 'cornBottom3.png', 'cornBottom4.png'],
},
{
goodName: '张塘王豇豆种子种籽',
sold: 1200,
price: 4.35,
sendAddress: '山东潍坊',
safeguard: '七天保价',
weight: ['100粒', '200粒'],
goodUrl: ['images/mockPic/beanTop.png'],
detailUrl: ['beanBottom1.png', 'beanBottom2.png', 'beanBottom3.png', 'beanBottom4.png'],
},
{
goodName: '茄子种子种籽',
sold: 1200,
price: 3.92,
sendAddress: '山东潍坊',
safeguard: '七天保价',
weight: ['100粒', '200粒'],
goodUrl: ['images/mockPic/eggplantTop.png'],
detailUrl: ['eggplantBottom1.png', 'eggplantBottom2.png', 'eggplantBottom3.png', 'eggplantBottom4.png'],
},
{
goodName: '正宗绿贝贝南瓜种籽',
sold: 1200,
price: 6.8,
sendAddress: '安徽马鞍山',
safeguard: '七天保价',
weight: ['10粒', '20粒'],
goodUrl: ['images/mockPic/pumpkinTop.png'],
detailUrl: ['pumpkinBottom1.png', 'pumpkinBottom2.png', 'pumpkinBottom3.png', 'pumpkinBottom4.png'],
},
{
goodName: '复合肥料18-5-7',
sold: 1200,
price: 154,
sendAddress: '浙江金华',
safeguard: '七天保价',
weight: ['25kg', '50kg'],
goodUrl: ['images/mockPic/fertilizerTop.png'],
detailUrl: ['fertilizerBottom1.png', 'fertilizerBottom2.png'],
},
{
goodName: '正宗硫酸钾 农用钾肥',
sold: 1200,
price: 13.5,
sendAddress: '内蒙古',
safeguard: '七天保价',
weight: ['5斤', '10斤'],
goodUrl: ['images/mockPic/KSO4Top.png'],
detailUrl: ['KSO4Bottom1.png', 'KSO4Bottom2.png', 'KSO4Bottom3.png', 'KSO4Bottom4.png'],
},
{
goodName: '噻虫嗪农药',
sold: 1200,
price: 8.6,
sendAddress: '内蒙古',
safeguard: '七天保价',
weight: ['500g'],
goodUrl: ['images/mockPic/pesticideTop.png'],
detailUrl: ['pesticideBottom1.png', 'pesticideBottom2.png', 'pesticideBottom3.png', 'pesticideBottom4.png', 'pesticideBottom5.png'],
},
{
goodName: '11.6%甲维氯笨氣虫苯甲铣胺酰胺笨甲先胺水稻钻心虫农药杀虫剂',
sold: 1200,
price: 35.6,
sendAddress: '山东烟台',
safeguard: '七天保价',
weight: ['500g', '1000g'],
goodUrl: ['images/mockPic/nyTop.png'],
detailUrl: ['nyBottom1.png', 'nyBottom2.png', 'nyBottom3.png', 'nyBottom4.png'],
},
{
goodName: '铁皮石斛种子',
sold: 13,
price: '80/g',
sendAddress: '耿马县',
safeguard: '七天保价',
weight: ['1g', '2g', '5g', '10g'],
goodUrl: ['images/mockPic/shihuTop.png'],
detailUrl: ['shihuBottom0.png', 'shihuBottom1.png', 'shihuBottom2.png', 'shihuBottom3.png'],
},
{
goodName: '黑皮甘蔗苗',
sold: 1400,
price: '0.7/株',
sendAddress: '耿马县',
safeguard: '七天保价',
weight: ['10株', '50株', '200株', '500株'],
goodUrl: ['images/mockPic/ganzheTop.png'],
detailUrl: ['ganzheBottom0.png', 'ganzheBottom1.png', 'ganzheBottom2.png', 'ganzheBottom3.png'],
},
{
goodName: '美人椒种子 -辣椒种子',
sold: 548,
price: '43/斤',
sendAddress: '耿马县',
safeguard: '七天保价',
weight: ['1斤', '2斤'],
goodUrl: ['images/mockPic/chiliTop.png'],
detailUrl: ['chiliBottom0.png', 'chiliBottom1.png', 'chiliBottom2.png', 'chiliBottom3.png'],
},
{
goodName: '四季青种子',
sold: 548,
price: '19.5/包',
sendAddress: '耿马县',
safeguard: '七天保价',
weight: ['1包500-2000粒', '2包', '4包'],
goodUrl: ['images/mockPic/leafyTop.png'],
detailUrl: ['leafyBottom0.png', 'leafyBottom1.png', 'leafyBottom2.png'],
},
{
goodName: '青花菜种子',
sold: 548,
price: '10/包',
sendAddress: '耿马县',
safeguard: '七天保价',
weight: ['1包300-800粒', '2包', '4包'],
goodUrl: ['images/mockPic/broccoliTop.png'],
detailUrl: ['broccoliBottom2.png', 'broccoliBottom1.png', 'broccoliBottom0.png'],
},
{
goodName: '黑叶小白菜种子',
sold: 82,
price: '60/公斤',
sendAddress: '耿马县',
safeguard: '七天保价',
weight: ['1公斤', '2公斤', '5公斤'],
goodUrl: ['images/mockPic/choyTop.png'],
detailUrl: ['choyBottom0.png', 'choyBottom1.png', 'choyBottom2.png', 'choyBottom3.png'],
},
];
let tabVal = ref('detail');
let saveInfo = reactive({
num: 0,
});
onMounted(() => {
showDetail.value = false;
// const num = Number(pId);
getGoodDetail(goodId)
.then(async (res) => {
if (res.code === 200) {
currentGood.value = res.data;
//
await formattedData(res.data);
showDetail.value = true;
}
})
.catch((e) => {
console.log(e);
});
// if (num === 55) {
// // 1. 0, 1, 2, 3
// const allIndices = [0, 1, 2, 3];
// // 2.
// const shuffledIndices = [...allIndices].sort(() => Math.random() - 0.5);
// // 3.
// currentIndex.value = shuffledIndices.slice(0, 1)[0];
// } else if (num === 61) {
// // 1. 0, 1, 2, 3
// const allIndices = [4, 5];
// // 2.
// const shuffledIndices = [...allIndices].sort(() => Math.random() - 0.5);
// // 3.
// currentIndex.value = shuffledIndices.slice(0, 1)[0];
// } else if (num === 65) {
// // 1. 0, 1, 2, 3
// const allIndices = [6, 7];
// // 2.
// const shuffledIndices = [...allIndices].sort(() => Math.random() - 0.5);
// // 3.
// currentIndex.value = shuffledIndices.slice(0, 1)[0];
// }
// if (Number(goodId) === 2140012566 || Number(goodId) === 2140012569) {
// getGoodDetail(Number(goodId)).then(async (res) => {
// currentGood = res.data;
// //
// await formattedData(res.data);
// showDetail.value = true;
// });
// currentIndex.value = 8;
// } else if (Number(goodId) === 2140012546 || Number(goodId) === 2140012547) {
// currentIndex.value = 9;
// } else if (Number(goodId) === 2140012562) {
// currentIndex.value = 2;
// } else if (Number(goodId) === 2140012563) {
// currentIndex.value = 10;
// } else if (Number(goodId) === 2140012586) {
// currentIndex.value = 11;
// } else if (Number(goodId) === 2140012587) {
// currentIndex.value = 12;
// } else if (Number(goodId) === 2140012588) {
// currentIndex.value = 13;
// }
});
//
const formattedData = (data) => {
if (currentGood.value.attribute) {
currentGood.value.attribute = Object.entries(data.attribute).map(([key, value]) => ({ key, value }));
}
if (currentGood.value.detailUrl) {
currentGood.value.detailUrl = currentGood.value.detailUrl.split(',');
}
currentGood.value.goodUrls = data.goodUrl.split(',');
};
const toCodeDetail = () => {
router.push('/sub-operation-service/ecommerce-supplier/detail/source?id=' + goodId);
};
const toBack = (level) => {
router.go(level);
};
const toCopy = () => {};
</script>
<style lang="scss" scoped>
.agricultural-detail-warp {
width: 100%;
.agricultural-detail-info {
overflow: hidden;
margin-bottom: 16px;
padding: 10px 24px;
width: 100%;
border-radius: 16px;
background: $color-fff;
.top-title {
width: 100%;
text-align: left;
.father-title,
.current-title {
display: inline-block;
vertical-align: middle;
font-weight: 700;
cursor: pointer;
}
.father-title {
font-size: 18px;
}
.current-title {
position: relative;
margin-left: 8px;
padding: 0 8px;
font-size: 16px;
color: $color-main;
}
.current-title::before {
position: absolute;
top: 30%;
left: 0;
content: '.';
transform: translateY(-50%);
}
}
.top-info {
margin: 16px 0;
text-align: left;
::v-deep() {
.ecommerce-banner {
position: relative;
padding: 0 48px !important;
}
.el-carousel {
position: unset !important;
}
.el-carousel__arrow--left {
left: 0 !important;
}
.el-carousel__arrow--right {
right: 0 !important;
}
}
}
.price-sold {
margin: 16px 0;
.price {
position: relative;
padding: 0 16px;
font-size: 32px;
color: $color-main;
}
.price::before {
position: absolute;
top: 50%;
left: 0;
font-size: 16px;
content: '¥';
transform: translateY(-50%);
}
.sold {
font-size: 16px;
color: $color-999;
}
.sold::before {
content: '已售';
}
}
.tag-list {
display: inline-flex;
justify-content: flex-start;
width: 100%;
color: $color-999;
gap: 10px;
.tag-item {
position: relative;
padding-left: 32px;
.iconfont {
position: absolute;
top: 50%;
left: 0;
transform: translateY(-50%);
&.icon-see {
font-size: 24px;
}
&.icon-ci {
font-size: 20px;
}
&.icon-time {
font-size: 24px;
}
}
font-size: 16px;
line-height: 32px;
}
}
.tips-list {
margin: 16px 0;
font-size: 16px;
line-height: 32px;
}
.spu-sku-list {
width: 100%;
.spu-title {
font-size: 16px;
}
.spu-sku-warp {
display: inline-flex;
justify-content: space-around;
margin-top: 16px;
width: 100%;
flex-wrap: wrap;
gap: 16px;
.spu-sku-item {
width: calc((100% - 16px) / 2);
font-size: 16px;
font-weight: 400;
border-radius: 8px;
text-align: center;
line-height: 40px;
cursor: pointer;
&.normal {
border: 1px solid $color-da;
color: $color-999;
}
&.act {
border: 1px solid $color-main;
color: $color-main;
}
}
}
.spu-sku-warp::after {
content: '';
flex: auto;
}
}
.goods-num {
margin: 16px 0;
.num-warp,
.num-title {
display: inline-block;
vertical-align: middle;
}
.num-title {
font-size: 16px;
}
.num-warp {
.is-have {
display: inline-block;
padding-left: 8px;
font-size: 12px;
color: $color-999;
}
}
}
.top-btn {
.item-btn {
display: inline-block;
margin: 8px 24px 8px 0;
margin-top: 16px;
padding: 0 24px;
font-size: 20px;
border-radius: 12px;
color: $color-fff;
line-height: 42px;
&.sign {
background: $color-main;
}
&.reservation {
background: $color-warning;
}
}
}
.agricultural-detail-content {
width: 100%;
text-align: left;
.detail-content {
.tab-top {
margin: 42px 0;
width: 100%;
text-align: center;
::v-deep() {
.el-radio-button:first-child .el-radio-button__inner {
border-radius: 16px 0 0 16px;
}
.el-radio-button:last-child .el-radio-button__inner {
border-radius: 0 16px 16px 0;
}
.el-radio-button__inner {
padding-right: 48px !important;
padding-left: 48px !important;
font-size: 20px;
line-height: 32px !important;
}
}
}
.tab-content {
margin: 24px 0;
width: 100%;
.content-detail,
.content-source-code,
.content-evaluate {
width: 100%;
}
.content-detail {
.detail-des {
margin-bottom: 24px;
width: 90%;
}
}
.content-source-code {
.code-warp {
width: 100%;
text-align: center;
.code-img {
margin: auto;
width: 230px;
height: 230px;
}
.code-down {
margin: 16px 0;
color: $color-main;
.el-icon,
a {
display: inline-block;
vertical-align: middle;
}
.el-icon {
font-size: 22px;
}
a {
font-size: 16px;
color: $color-main;
}
}
.code-copy {
.code-txt {
display: inline-block;
padding: 12px 8px;
width: 200px;
border-radius: 16px 0 0 16px;
background: $color-main-table-header;
vertical-align: middle;
}
.do-copy {
vertical-align: middle;
display: inline-block;
margin-left: -6px;
.el-button {
padding: 21px 16px;
font-size: 16px;
border-radius: 12px;
}
}
}
.code-to-detail {
margin: 24px 0;
.el-button {
padding: 16px 116px;
height: 48px;
font-size: 20px;
font-weight: 600;
border-radius: 24px;
line-height: 48px;
}
}
}
}
}
}
}
}
}
</style>

View File

@ -8,6 +8,7 @@
</template>
</div>
<div class="common-content">
<bread-comp></bread-comp>
<slot v-if="$slots.main" name="main"></slot>
<template v-else></template>
</div>
@ -17,6 +18,7 @@
<script setup>
import { ref, reactive, onMounted, watch } from 'vue';
import leftMenu from './leftMenu.vue';
import BreadComp from '@/components/breadComp.vue';
const props = defineProps({
currentName: { type: String, default: 'agricultural' },

View File

@ -107,7 +107,8 @@ onMounted(async () => {
<div style="display: flex; justify-content: space-between; align-items: center">
<div class="video-wrapper">
<video v-if="num === 1" ref="videoPlayer" src="../components/jiankong.mp4" controls loop autoplay muted></video>
<video v-else-if="num === 2" ref="videoPlayer" src="../components/jiankong1.mp4" controls loop autoplay muted></video>
<video v-else-if="num === 2" ref="videoPlayer" src="../components/jiankong6.mp4" controls loop autoplay muted></video>
<video v-else-if="num === 3" ref="videoPlayer" src="../components/jiankong5.mp4" controls loop autoplay muted></video>
<video v-else-if="num === 4" ref="videoPlayer" src="../components/jiankong2.mp4" controls loop autoplay muted></video>
<video v-else-if="num === 5" ref="videoPlayer" src="../components/jiankong3.mp4" controls loop autoplay muted></video>
<video v-else-if="num === 6" ref="videoPlayer" src="../components/jiankong4.mp4" controls loop autoplay muted></video>

View File

@ -147,7 +147,7 @@ const chooseIcon = (type) => {
</div>
<div style="margin-top: 10px; display: flex; justify-content: space-between">
<div style="display: flex; justify-content: space-between; margin-top: 10px">
<stream :title="'病害监测监控'" :devices="devices" style="width: 60%; height: fit-content"></stream>
<stream :title="'病害监测监控'" :num="3" :devices="devices" style="width: 60%; height: fit-content"></stream>
<div style="width: 38%">
<el-card style="border-radius: 16px; padding: 10px">
<div style="font-size: 16px; font-weight: bold; text-align: left; color: #000">病害数据</div>