Compare commits

...

2 Commits

43 changed files with 3458 additions and 535 deletions

View File

@ -18,6 +18,14 @@ export function agriculturalList(params) {
});
}
// 获取商品详情接口
export function getGoodDetail(id, params) {
return request(`goods/goodInfoManage/getGoodInfo/${id}`, {
method: 'GET',
params,
});
}
// 获取用户评价列表
export function agriculturalContent(params) {
return request('goods/goodInfoManage/contentPage', {

View File

@ -27,3 +27,22 @@ export function brandList(params) {
params,
});
}
export function goodList(params) {
return request('brand/applicationrecord/getGoodsListByUserId', {
method: 'GET',
params,
});
}
export function authList(params) {
return request('brand/applicationrecord/page', {
method: 'GET',
params,
});
}
export function saveRecords(data) {
return request('brand/applicationrecord/save', {
method: 'POST',
data,
});
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 93 KiB

View File

@ -1,5 +1,5 @@
<template>
<div ref="chartRef" style="width: 100%; height: 170px"></div>
<div ref="chartRef" style="width: 100%; height: 100%"></div>
</template>
<script>
import { ref, reactive, watchEffect } from 'vue';
@ -260,8 +260,8 @@ export default {
},
legend: {
show: true,
right: '25%',
top: '25%',
left: '50%', //
top: 'center', //
orient: 'vertical',
icon: 'circle',
itemHeight: 12,

View File

@ -2,7 +2,7 @@
<div ref="chartRef" :style="{ height, width }"></div>
</template> -->
<template>
<div ref="chartRef" style="width: 100%; height: 260px"></div>
<div ref="chartRef" style="width: 100%; height: calc((100vh - 330px) / 3 - 40px)"></div>
</template>
<script>
import { ref, reactive, watch, watchEffect } from 'vue';

View File

@ -1,5 +1,5 @@
<template>
<div ref="chartRef" style="width: 100%; height: 170px"></div>
<div ref="chartRef" style="width: 100%; height: 100%"></div>
</template>
<script>
@ -42,6 +42,7 @@ export default {
},
},
xAxis: {
show: false,
type: 'category',
data: [],
},

View File

@ -1,8 +1,8 @@
<template>
<div ref="chartRef" style="width: 100%; height: 260px"></div>
<div ref="chartRef" style="width: 100%; height: 100%; min-height: 150px"></div>
</template>
<script>
import { ref, reactive, watch, watchEffect } from 'vue';
import { ref, reactive, watch, watchEffect, onMounted } from 'vue';
import { cloneDeep } from 'lodash';
import { useEcharts } from '@/hooks/useEcharts';
@ -58,6 +58,10 @@ export default {
props.chartData && initCharts();
});
onMounted(() => {
initCharts();
});
watch(
() => props.size,
() => {

View File

@ -74,10 +74,10 @@ const router = useRouter();
const keyword = ref('');
const meuns = ref([
// {
// label: '',
// path: '/sub-operation-service/dashboard',
// },
{
label: '综合看板',
path: '/sub-operation-service/dashboard',
},
{
label: '智慧种植',
path: '/sub-operation-service/smartFarm',

View File

@ -110,7 +110,7 @@ export const constantRoutes = [
path: '/sub-operation-service',
name: 'layout',
component: Layout,
redirect: '/sub-operation-service/smartFarm',
redirect: '/sub-operation-service/dashboard',
meta: { title: '运营服务' },
children: [
{
@ -119,11 +119,20 @@ export const constantRoutes = [
name: 'home',
meta: { title: '首页' },
},
],
},
{
path: '/sub-operation-service/dashboard',
component: () => import('@/views/dashboard/index.vue'),
component: Layout,
name: 'dashboard',
redirect: '/sub-operation-service/dashboard/home',
meta: { title: '综合看板' },
children: [
{
path: '/sub-operation-service/dashboard/home',
component: () => import('@/views/dashboard/breed/index.vue'),
name: 'dashboardHome',
meta: { title: '综合看板首页' },
},
],
},

View File

@ -11,10 +11,13 @@
<el-form label-width="120px" class="form">
<h1 style="margin: 20px 0 20px 50px">请选择溯源农产品申请</h1>
<el-form-item label="检查批次">
<el-select v-model="batch" placeholder="请选择农产品批次" :width="200">
<el-option label="批次A" value="A" />
<el-option label="批次B" value="B" />
<el-form-item label="溯源商品">
<el-select v-model="batch" placeholder="请选择商品" :width="200">
<el-option v-for="(item, index) in goodsList" :key="index" :label="item.goodName" :value="item.id">
<el-tooltip :content="item.goodName" placement="top">
<span>{{ item.goodNames }}</span>
</el-tooltip>
</el-option>
</el-select>
</el-form-item>
@ -52,22 +55,33 @@
<script setup>
import { useRouter, useRoute } from 'vue-router';
import { ref, onMounted } from 'vue';
import { ref, onMounted, reactive } from 'vue';
import { ElMessage } from 'element-plus';
import { getAssetsFile } from '@/utils/index.js';
import { goodList, saveRecords } from '@/apis/brand.js';
const router = useRouter();
const route = useRoute();
const productId = route.params.id;
const productId = route.query.id;
const product = ref({ name: '加载中...', id: productId });
const goodsList = reactive([]);
onMounted(() => {
//
product.value = {
id: productId,
name: productId == 1 ? '有机苹果' : '绿色蔬菜',
};
goodList().then((res) => {
if (res.code === 200) {
goodsList.splice(0, goodsList.length, ...res.data);
for (let i in goodsList) {
goodsList[i].goodNames = goodsList[i].goodName.length > 15 ? goodsList[i].goodName.substring(0, 15) + '...' : goodsList[i].goodName;
}
}
});
});
const batch = ref('');
@ -85,15 +99,24 @@ function uploadTraceCode() {
}
function submit() {
console.log('提交申请:', {
product: product.value,
batch: batch.value,
detectTime: detectTime.value,
station: station.value,
origin: origin.value,
});
// console.log('', {
// product: productId,
// batch: batch.value,
// detectTime: detectTime.value,
// station: station.value,
// origin: origin.value,
// });
let obj = {
goodsId: batch.value,
brandId: productId,
};
saveRecords(obj).then((res) => {
if (res.code === 200) {
// console.log(res);
ElMessage.success('提交成功!');
}
});
}
</script>
<style scoped lang="scss">

View File

@ -37,35 +37,42 @@
<!-- 产品列表 -->
<el-card shadow="hover" style="border-radius: 16px" class="product-card">
<!-- 状态筛选 -->
<el-tabs v-model="activeStatus" class="tabs-wrapper">
<el-tab-pane label="已授权" name="authorized" />
<el-tab-pane label="审批中" name="approving" />
<el-tab-pane label="已失效" name="expired" />
<el-tabs v-model="activeStatus" class="tabs-wrapper" @tab-change="changeStatus">
<el-tab-pane label="已授权" name="1" />
<el-tab-pane label="审批中" name="2" />
<el-tab-pane label="被驳回" name="3" />
<el-tab-pane label="已失效" name="4" />
</el-tabs>
<div class="product-list">
<div v-for="(product, index) in filteredProducts" :key="product.id" class="product-item" :class="{ 'border-top': index > 0 }">
<div v-for="(product, index) in products" :key="product.id" class="product-item" :class="{ 'border-top': index > 0 }">
<div class="product-info">
<img class="product-img" :src="product.img" alt="product" />
<img class="product-img" :src="product.goodsUrl" alt="product" />
<div class="product-text">
<span class="product-name">{{ product.name }}</span>
<span class="product-name">{{ product.productName }}</span>
<div class="detail-item">
<label>检测批次</label>
<span>{{ product.batch }}</span>
<span>2</span>
</div>
<div class="detail-item">
<label>授权期限</label>
<span>{{ product.duration }}</span>
<span
>{{ product.timeNum
}}{{ product.timeNumUnit === 1 ? '天' : product.timeNumUnit === 2 ? '月' : product.timeNumUnit === 3 ? '年' : '' }}</span
>
</div>
<div class="detail-item">
<label>到期时间</label>
<span class="text-expire">{{ product.expireDate }}</span>
<span class="text-expire">{{ product.endTime }}</span>
</div>
</div>
</div>
<div class="product-action">
<el-tag :class="statusClass(activeStatus)" :type="statusTypeMap[product.status]">{{ product.statusLabel }}</el-tag>
<el-tag v-if="product.status == 1" size="large" class="text-success status-tag" type="success">已授权</el-tag>
<el-tag v-if="product.status == 2" size="large" class="text-warning status-tag" type="warning">审批中</el-tag>
<el-tag v-if="product.status == 3" size="large" class="text-danger status-tag" type="danger">被驳回</el-tag>
<el-tag v-if="product.status == 4" size="large" class="text-info status-tag" type="info">已失效</el-tag>
<el-button
v-if="product.status === 'authorized'"
v-if="product.status == 1"
type="primary"
plain
:icon="Edit"
@ -95,18 +102,12 @@
</template>
<script setup>
import { ref, computed } from 'vue';
import { ref, computed, onMounted } from 'vue';
import { getAssetsFile } from '@/utils/index.js';
import { getProducts } from '@/apis/brand';
import { authList, getProducts } from '@/apis/brand';
import { Edit } from '@element-plus/icons-vue';
const activeStatus = ref('authorized');
const statusTypeMap = {
authorized: 'success',
approving: 'warning',
expired: 'danger',
};
const activeStatus = ref('1');
const products = ref([
{
@ -171,13 +172,7 @@ const products = ref([
},
]);
const statusClass = (tab) => {
if (tab === 'approving') return 'text-warning status-tag';
if (tab === 'expired') return 'text-danger status-tag';
return 'text-success status-tag';
};
const filteredProducts = computed(() => products.value.filter((p) => p.status === activeStatus.value));
// const filteredProducts = computed(() => products.value.filter((p) => p.status === activeStatus.value));
const certificateDialogVisible = ref(false);
const currentCertificateImg = ref('');
@ -187,6 +182,28 @@ const handleCertificate = (product) => {
currentCertificateImg.value = getAssetsFile('images/brand/sqzs.png'); // product.certificate
certificateDialogVisible.value = true;
};
const changeStatus = (tab) => {
getAuthList(tab);
};
const getAuthList = (status) => {
products.value = [];
authList({ status: status }).then((res) => {
if (res.code === 200) {
products.value = res.data.records;
for (let i in products.value) {
if (products.value[i].endTime) {
products.value[i].endTime = products.value[i].endTime.split(' ')[0];
}
}
}
});
};
onMounted(() => {
getAuthList(1);
});
</script>
<style lang="scss" scoped>
@ -348,9 +365,9 @@ const handleCertificate = (product) => {
}
.detail-item {
width: 100%;
font-size: 16px;
display: flex;
justify-content: space-between;
gap: 10px;
font-size: 16px;
font-weight: 400;
text-align: left;
color: #999999;

View File

@ -0,0 +1,162 @@
<template>
<div class="inventory-charts">
<custom-echart-line-line :chart-data="chartsData.valData" height="100%" :option="chartsData.option" />
</div>
</template>
<script setup>
import { ref, reactive, onMounted, computed } from 'vue';
const legendData = reactive(['分拣', '包装']);
let dataItem = reactive([100, 90, 200, 250, 240, 275, 120, 300, 320, 270, 290, 120]);
let colors = reactive({
分拣: '#3685fe',
包装: '#41b879',
});
let colorBg = reactive({
分拣: [
{ offset: 0, color: 'rgba(54,161,255,0.6)' },
{ offset: 1, color: 'rgba(25,104,255,0)' },
],
包装: [
{ offset: 0, color: 'rgba(0,255,0,0.6)' },
{ offset: 1, color: 'rgba(25,104,255,0)' },
],
});
const currentMonth = ref(new Date().getMonth() + 1);
const yAxisData = computed(() => {
let list = [];
for (let i = 1; i < 13; i++) {
let mouth = i < 10 ? i : i;
list.push(mouth + '月');
}
return list;
});
let seriesItem = reactive({
type: 'line',
stack: 'Total',
symbol: 'none',
smooth: true,
});
let seriesData = computed(() => {
let list = [];
if (legendData.length && legendData.length > 0) {
legendData.forEach((m) => {
let val = {
...seriesItem,
name: m,
areaStyle: {
color: {
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: colorBg[m],
global: false, // false
},
},
lineStyle: {
color: colors[m],
width: 1,
type: 'solid',
},
data: dataItem,
};
list.push(val);
});
}
return list;
});
const chartsData = reactive({
option: {
backgroundColor: 'transparent',
grid: {
left: '3%',
right: '15%',
bottom: '1%',
top: '3%',
containLabel: true,
},
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow',
},
textStyle: {
color: '#fff',
fontSize: 10,
},
confine: true, //
backgroundColor: 'rgba(17,95,182,0.5)', //
formatter: function (item) {
let params = [...item];
var res = params[0].name + '<br/>';
for (var i = 0, l = params.length; i < l; i++) {
res += params[i].value !== '-' ? params[i].marker + params[i].seriesName + ' : ' + params[i].value + ' <br/>' : '';
}
return res;
},
},
legend: {
left: '30%', // 10%
top: '0', //
itemWidth: 20, //
itemHeight: 20, //
show: true,
data: Array.from(legendData),
right: '0', // 10%
textStyle: {
fontSize: 10, //
color: '#fff', //
},
},
xAxis: {
type: 'category',
boundaryGap: true,
axisTick: {
show: false,
},
axisLine: {
lineStyle: {
color: '#94A7BD', //线
},
},
data: yAxisData,
},
yAxis: {
type: 'value',
name: ' ',
nameTextStyle: {
fontSize: 14,
color: '#94A7BD',
padding: [0, 0, 0, -45],
},
axisLine: {
lineStyle: {
color: '#94A7BD', //线
},
},
splitLine: {
show: true,
lineStyle: {
color: '#182D46',
type: [2, 3],
dashOffset: 2,
},
},
},
series: seriesData.value,
},
});
onMounted(() => {});
</script>
<style lang="scss" scoped>
.inventory-charts {
height: 100%;
width: 100%;
}
</style>

View File

@ -0,0 +1,403 @@
<template>
<div class="benefit-charts">
<custom-echart-mixin :chart-data="handelData" :option="chartsData.option" />
</div>
</template>
<script setup>
import { ref, reactive, onMounted, computed } from 'vue';
let itemStyle = reactive({
itemStyle: { borderRadius: [8, 8, 0, 0] },
});
let legendList = reactive(['成本', '收入', '繁殖率', '配种成功率']);
var { data, optionConfig } = {
data: [
{ name: '已使用', value: 15, itemStyle: { color: '#0096f9' }, startRatio: 0, endRatio: 0.15 },
{ name: '未使用', value: 25, itemStyle: { color: '#00e8ce' }, startRatio: 0.15, endRatio: 0.4 },
],
optionConfig: {},
};
const getPie3D = (pieData, internalDiameterRatio) => {
let series = [];
let sumValue = 0;
let startValue = 0;
let endValue = 0;
let legendData = [];
let k = typeof internalDiameterRatio !== 'undefined' ? (1 - internalDiameterRatio) / (1 + internalDiameterRatio) : 1 / 3;
// series-surface
for (let i = 0; i < pieData.length; i++) {
sumValue += pieData[i].value;
let seriesItem = {
name: typeof pieData[i].name === 'undefined' ? `series${i}` : pieData[i].name,
type: 'surface',
parametric: true,
wireframe: {
show: false,
},
pieData: pieData[i],
pieStatus: {
selected: false,
hovered: false,
k: k,
},
labelLine: {
show: false,
},
label: {
show: false,
// normal: {
// position: "inner",
// formatter: (params) => {
// return params;
// },
// },
},
itemStyle: {
opacity: 1,
},
};
if (typeof pieData[i].itemStyle != 'undefined') {
let itemStyle = {};
typeof pieData[i].itemStyle.color != 'undefined' ? (itemStyle.color = pieData[i].itemStyle.color) : null;
typeof pieData[i].itemStyle.opacity != 'undefined' ? (itemStyle.opacity = pieData[i].itemStyle.opacity) : null;
seriesItem.itemStyle = itemStyle;
}
series.push(seriesItem);
}
// 使 sumValue getParametricEquation
// series-surface series-surface.parametricEquation
for (let i = 0; i < series.length; i++) {
endValue = startValue + series[i].pieData.value;
// console.log(series[i]);
series[i].pieData.startRatio = startValue / sumValue;
series[i].pieData.endRatio = endValue / sumValue;
series[i].parametricEquation = getParametricEquation(
series[i].pieData.startRatio,
series[i].pieData.endRatio,
false,
false,
k,
series[i].pieData.value
);
startValue = endValue;
legendData.push(series[i].name);
}
// legendDataseries
let option = {
tooltip: {
// backgroundColor: '#053A8D',
formatter: (params) => {
if (params.seriesName !== 'mouseoutSeries') {
return `${
params.seriesName
}<br/><span style="display:inline-block;margin-right:5px;border-radius:10px;width:10px;height:10px;background-color:${
params.color
};"></span>${option.series[params.seriesIndex].pieData.value}`;
}
},
},
pie2dConfig: {
center: ['50%', '40%'],
label: {
show: true,
position: 'outside',
formatter: (params) => {
const total = 221.8 + 70.01; //
const percent = ((params.value / total) * 100).toFixed(0);
return `{name|${params.name}}\n{value|${params.value} 万吨\n${percent}%}`;
},
rich: {
name: {
fontSize: 16,
fontWeight: 'bold',
color: '#ffffff',
lineHeight: 20,
align: 'center',
},
value: {
fontSize: 16,
color: '#79F5AF',
lineHeight: 18,
align: 'center',
},
},
color: '#fff',
},
labelLine: {
show: true,
length: 40,
length2: 40,
lineStyle: { color: '#fff', width: 2 },
},
},
graphic: {
elements: [
{
type: 'text',
left: '50%',
top: '30%',
style: {
text: '40.1%',
fill: '#FFF',
fontSize: 18,
padding: [4, 8],
borderRadius: 4,
},
},
{
type: 'text',
left: '20%',
top: '60%',
style: {
text: '59.9%',
fill: '#FFF',
fontSize: 16,
padding: [4, 8],
borderRadius: 4,
},
},
],
},
labelLine: {
show: true,
},
label: {
show: true,
},
legend: {
orient: 'horizontal', //
top: 0,
data: legendData,
textStyle: {
color: '#fff',
fontSize: 15,
},
itemWidth: 10,
itemHeight: 10,
icon: 'roundRect',
formatter: function (name) {
let item = data.filter((item) => item.name == name)[0];
return `${item.name}`;
},
// top: '30%', //
},
xAxis3D: {
min: -1.3,
max: 1.3,
},
yAxis3D: {
min: -1.3,
max: 1.3,
},
zAxis3D: {
min: -1.3,
max: 1.3,
},
grid3D: {
show: false,
boxHeight: 4,
top: '0%',
left: '-2%',
// environment: "#021041",
viewControl: {
distance: 6000,
alpha: 60,
beta: 10,
},
},
series: series,
};
return option;
};
// series-surface.parametricEquation
const getParametricEquation = (startRatio, endRatio, isSelected, isHovered, k, height) => {
//
let midRatio = (startRatio + endRatio) / 2;
let startRadian = startRatio * Math.PI * 2;
let endRadian = endRatio * Math.PI * 2;
let midRadian = midRatio * Math.PI * 2;
//
if (startRatio === 0 && endRatio === 1) {
isSelected = false;
}
// / k 1/3
k = typeof k !== 'undefined' ? k : 1 / 3;
// x y 0
let offsetX = isSelected ? Math.cos(midRadian) * 0.1 : 0;
let offsetY = isSelected ? Math.sin(midRadian) * 0.1 : 0;
// 1
let hoverRate = isHovered ? 1.05 : 1;
//
return {
u: {
min: -Math.PI,
max: Math.PI * 3,
step: Math.PI / 32,
},
v: {
min: 0,
max: Math.PI * 2,
step: Math.PI / 20,
},
x: function (u, v) {
if (u < startRadian) {
return offsetX + Math.cos(startRadian) * (1 + Math.cos(v) * k) * hoverRate;
}
if (u > endRadian) {
return offsetX + Math.cos(endRadian) * (1 + Math.cos(v) * k) * hoverRate;
}
return offsetX + Math.cos(u) * (1 + Math.cos(v) * k) * hoverRate;
},
y: function (u, v) {
if (u < startRadian) {
return offsetY + Math.sin(startRadian) * (1 + Math.cos(v) * k) * hoverRate;
}
if (u > endRadian) {
return offsetY + Math.sin(endRadian) * (1 + Math.cos(v) * k) * hoverRate;
}
return offsetY + Math.sin(u) * (1 + Math.cos(v) * k) * hoverRate;
},
z: function (u, v) {
if (u < -Math.PI * 0.5) {
return Math.sin(u);
}
if (u > Math.PI * 2.5) {
return Math.sin(u);
}
return Math.sin(v) > 0 ? 1 * height : -1;
},
};
};
const chartsData = reactive({
option: {
// color: ['#3685fe', '#8dcbe9', '#ffd500', '#631f9f'],
// title: {
// text: ' ',
// textStyle: {
// color: '#333',
// },
// },
// legend: {
// show: true,
// data: legendList,
// left: '0', // 10%
// top: '0', //
// itemWidth: 15, //
// itemHeight: 8, //
// textStyle: {
// fontSize: 10, //
// color: '#fff', //
// },
// },
// barStyle: {
// barWidth: 10,
// },
// dataZoom: [
// // {
// // type: 'slider', //
// // startValue: 0, //
// // endValue: 2, //
// // },
// // {
// // type: 'inside', //
// // startValue: 0,
// // endValue: 2,
// // },
// ],
// yAxis: [
// {
// type: 'value',
// name: ' ',
// axisLabel: {
// formatter: '{value}',
// },
// splitLine: {
// show: true, // 线
// lineStyle: {
// type: 'dashed', // 线
// width: 0.5, // 线
// },
// },
// itemStyle: { fontSize: 8 },
// },
// ],
// grid: {
// x: '10%',
// x2: '10%',
// y: '20%',
// y2: '20%',
// },
},
valData: [],
});
chartsData.option = getPie3D(data, 0);
const randomVal = (num) => {
let list = [];
for (let i = 0; i < legendList.length; i++) {
let addNum = [10, 8, 2, 5];
let val = {
name: num + '月',
value: Number(Math.random() * 100 + addNum[i]).toFixed(2),
seriesType: i < legendList.length - 2 ? 'bar' : 'line',
type: legendList[i],
stack: num + '月',
};
if (val.seriesType == 'line') {
val.smooth = 30;
val.symbol = 'none';
}
let lastVal = {
...val,
...itemStyle,
};
list[i] = i < legendList.length - 3 ? val : lastVal;
}
return list;
};
let handelData = computed(() => {
let list = [];
let maxMouth = 12;
for (let i = 0; i < maxMouth; i++) {
let val = randomVal(i + 1);
list = [...list, ...val];
}
list.map((m, indexm) => {
return { ...m, value: Number(Number(m.value) + Math.random() + indexm).toFixed(0) };
});
// console.info('handelData', list);
return list;
});
onMounted(() => {});
</script>
<style lang="scss" scoped>
.benefit-charts {
height: 130%;
}
</style>

View File

@ -0,0 +1,397 @@
<template>
<div class="benefit-charts">
<custom-echart-mixin :chart-data="handelData" :option="chartsData.option" height="100%" />
</div>
</template>
<script setup>
import { ref, reactive, onMounted, computed } from 'vue';
let itemStyle = reactive({
itemStyle: { borderRadius: [8, 8, 0, 0] },
});
let legendList = reactive(['成本', '收入', '繁殖率', '配种成功率']);
var { data, optionConfig } = {
data: [
{ name: '豆菜', value: 15, itemStyle: { color: '#938df6' }, startRatio: 0, endRatio: 0.15 },
{ name: '茄科', value: 25, itemStyle: { color: '#0ce4d1' }, startRatio: 0.15, endRatio: 0.4 },
{ name: '根菜', value: 5, itemStyle: { color: '#2196f3' }, startRatio: 0.15, endRatio: 0.4 },
],
optionConfig: {},
};
const getPie3D = (pieData, internalDiameterRatio) => {
let series = [];
let sumValue = 0;
let startValue = 0;
let endValue = 0;
let legendData = [];
let k = typeof internalDiameterRatio !== 'undefined' ? (1 - internalDiameterRatio) / (1 + internalDiameterRatio) : 1 / 3;
// series-surface
for (let i = 0; i < pieData.length; i++) {
sumValue += pieData[i].value;
let seriesItem = {
name: typeof pieData[i].name === 'undefined' ? `series${i}` : pieData[i].name,
type: 'surface',
parametric: true,
wireframe: {
show: false,
},
pieData: pieData[i],
pieStatus: {
selected: false,
hovered: false,
k: k,
},
labelLine: {
show: false,
},
label: {
show: false,
// normal: {
// position: "inner",
// formatter: (params) => {
// return params;
// },
// },
},
itemStyle: {
opacity: 1,
},
};
if (typeof pieData[i].itemStyle != 'undefined') {
let itemStyle = {};
typeof pieData[i].itemStyle.color != 'undefined' ? (itemStyle.color = pieData[i].itemStyle.color) : null;
typeof pieData[i].itemStyle.opacity != 'undefined' ? (itemStyle.opacity = pieData[i].itemStyle.opacity) : null;
seriesItem.itemStyle = itemStyle;
}
series.push(seriesItem);
}
// 使 sumValue getParametricEquation
// series-surface series-surface.parametricEquation
for (let i = 0; i < series.length; i++) {
endValue = startValue + series[i].pieData.value;
// console.log(series[i]);
series[i].pieData.startRatio = startValue / sumValue;
series[i].pieData.endRatio = endValue / sumValue;
series[i].parametricEquation = getParametricEquation(
series[i].pieData.startRatio,
series[i].pieData.endRatio,
false,
false,
k,
series[i].pieData.value
);
startValue = endValue;
legendData.push(series[i].name);
}
// legendDataseries
let option = {
tooltip: {
backgroundColor: '#053A8D',
formatter: (params) => {
if (params.seriesName !== 'mouseoutSeries') {
return `${
params.seriesName
}<br/><span style="display:inline-block;margin-right:5px;border-radius:10px;width:10px;height:10px;background-color:${
params.color
};"></span>${option.series[params.seriesIndex].pieData.value}`;
}
},
},
graphic: {
elements: [
// {
// type: 'polyline',
// shape: {
// points: [
// [100, 150], //
// [150, 100], //
// [10, 200], //
// ],
// },
// style: { stroke: '#FF0000', lineWidth: 2 },
// },
// {
// type: 'line',
// shape: { x1: 80, y1: 150, x2: 0, y2: 200 },
// style: { stroke: '#fff', lineWidth: 2 },
// },
{
type: 'text',
left: '65%',
top: '30%',
style: {
text: '24500',
fill: '#FFF',
fontSize: 18,
padding: [4, 8],
borderRadius: 4,
},
},
{
type: 'text',
left: '60%',
top: '55%',
style: {
text: '32500',
fill: '#FFF',
fontSize: 16,
padding: [4, 8],
borderRadius: 4,
},
},
{
type: 'text',
left: '15%',
top: '50%',
style: {
text: '31100',
fill: '#FFF',
fontSize: 16,
padding: [4, 8],
borderRadius: 4,
},
},
],
},
labelLine: {
show: true,
},
label: {
show: true,
},
legend: {
orient: 'horizontal', //
left: 'left', //
top: 0,
data: legendData,
textStyle: {
color: '#fff',
fontSize: 15,
},
itemWidth: 10,
itemHeight: 10,
icon: 'roundRect',
formatter: function (name) {
let item = data.filter((item) => item.name == name)[0];
return `${item.name}`;
},
// top: '30%', //
},
xAxis3D: {
min: -1.3,
max: 1.3,
},
yAxis3D: {
min: -1.3,
max: 1.3,
},
zAxis3D: {
min: -1.3,
max: 1.3,
},
grid3D: {
show: false,
boxHeight: 4,
top: '0%',
left: '-2%',
// environment: "#021041",
viewControl: {
distance: 6000,
alpha: 60,
beta: 10,
},
},
series: series,
};
return option;
};
// series-surface.parametricEquation
const getParametricEquation = (startRatio, endRatio, isSelected, isHovered, k, height) => {
//
let midRatio = (startRatio + endRatio) / 2;
let startRadian = startRatio * Math.PI * 2;
let endRadian = endRatio * Math.PI * 2;
let midRadian = midRatio * Math.PI * 2;
//
if (startRatio === 0 && endRatio === 1) {
isSelected = false;
}
// / k 1/3
k = typeof k !== 'undefined' ? k : 1 / 3;
// x y 0
let offsetX = isSelected ? Math.cos(midRadian) * 0.1 : 0;
let offsetY = isSelected ? Math.sin(midRadian) * 0.1 : 0;
// 1
let hoverRate = isHovered ? 1.05 : 1;
//
return {
u: {
min: -Math.PI,
max: Math.PI * 3,
step: Math.PI / 32,
},
v: {
min: 0,
max: Math.PI * 2,
step: Math.PI / 20,
},
x: function (u, v) {
if (u < startRadian) {
return offsetX + Math.cos(startRadian) * (1 + Math.cos(v) * k) * hoverRate;
}
if (u > endRadian) {
return offsetX + Math.cos(endRadian) * (1 + Math.cos(v) * k) * hoverRate;
}
return offsetX + Math.cos(u) * (1 + Math.cos(v) * k) * hoverRate;
},
y: function (u, v) {
if (u < startRadian) {
return offsetY + Math.sin(startRadian) * (1 + Math.cos(v) * k) * hoverRate;
}
if (u > endRadian) {
return offsetY + Math.sin(endRadian) * (1 + Math.cos(v) * k) * hoverRate;
}
return offsetY + Math.sin(u) * (1 + Math.cos(v) * k) * hoverRate;
},
z: function (u, v) {
if (u < -Math.PI * 0.5) {
return Math.sin(u);
}
if (u > Math.PI * 2.5) {
return Math.sin(u);
}
return Math.sin(v) > 0 ? 1 * height : -1;
},
};
};
const chartsData = reactive({
option: {
// color: ['#3685fe', '#8dcbe9', '#ffd500', '#631f9f'],
// title: {
// text: ' ',
// textStyle: {
// color: '#333',
// },
// },
// legend: {
// show: true,
// data: legendList,
// left: '0', // 10%
// top: '0', //
// itemWidth: 15, //
// itemHeight: 8, //
// textStyle: {
// fontSize: 10, //
// color: '#fff', //
// },
// },
// barStyle: {
// barWidth: 10,
// },
// dataZoom: [
// // {
// // type: 'slider', //
// // startValue: 0, //
// // endValue: 2, //
// // },
// // {
// // type: 'inside', //
// // startValue: 0,
// // endValue: 2,
// // },
// ],
// yAxis: [
// {
// type: 'value',
// name: ' ',
// axisLabel: {
// formatter: '{value}',
// },
// splitLine: {
// show: true, // 线
// lineStyle: {
// type: 'dashed', // 线
// width: 0.5, // 线
// },
// },
// itemStyle: { fontSize: 8 },
// },
// ],
// grid: {
// x: '10%',
// x2: '10%',
// y: '20%',
// y2: '20%',
// },
},
valData: [],
});
chartsData.option = getPie3D(data, 0);
const randomVal = (num) => {
let list = [];
for (let i = 0; i < legendList.length; i++) {
let addNum = [10, 8, 2, 5];
let val = {
name: num + '月',
value: Number(Math.random() * 100 + addNum[i]).toFixed(2),
seriesType: i < legendList.length - 2 ? 'bar' : 'line',
type: legendList[i],
stack: num + '月',
};
if (val.seriesType == 'line') {
val.smooth = 30;
val.symbol = 'none';
}
let lastVal = {
...val,
...itemStyle,
};
list[i] = i < legendList.length - 3 ? val : lastVal;
}
return list;
};
let handelData = computed(() => {
let list = [];
let maxMouth = 12;
for (let i = 0; i < maxMouth; i++) {
let val = randomVal(i + 1);
list = [...list, ...val];
}
list.map((m, indexm) => {
return { ...m, value: Number(Number(m.value) + Math.random() + indexm).toFixed(0) };
});
// console.info('handelData', list);
return list;
});
onMounted(() => {});
</script>
<style lang="scss" scoped>
.benefit-charts {
height: 130%;
}
</style>

View File

@ -0,0 +1,231 @@
<template>
<div class="business">
<div style="display: flex; flex-direction: column; justify-content: flex-start; width: 60%">
<div class="business-left">
<custom-echart-water-droplet width="100%" height="100%" :option="state.option" />
</div>
<div class="business-title" style="z-index: 99; color: #fff">通过率</div>
</div>
<div>
<div class="business-right">
<div class="business-title">提交申请数量</div>
<ul class="business-info">
<li class="success">
<span>253</span>
</li>
</ul>
</div>
<div class="business-right">
<div class="business-title">审核通过数量</div>
<ul class="business-info">
<li class="success">
<span>101</span>
</li>
<!-- <li class="warning">
<b>临期</b>
<span>5</span>
</li>
<li class="danger">
<b>已过期</b>
<span>0</span>
</li> -->
</ul>
</div>
</div>
</div>
</template>
<script setup>
import { reactive, ref, watch } from 'vue';
import { isEmpty } from '@/utils';
const props = defineProps({
data: {
type: Object,
default: () => {},
},
});
const state = reactive({
option: {
backgroundColor: 'transparent', //
series: [
{
name: '',
type: 'liquidFill',
radius: '80%',
center: ['50%', '50%'],
backgroundStyle: {
color: 'transparent',
},
data: [],
amplitude: 12, //
label: {
position: ['50%', '50%'],
// formatter: 0.3998 * 100 + '%', //,
textStyle: {
fontSize: '20px', //,
color: '#fff',
},
},
outline: {
borderDistance: 2,
itemStyle: {
borderWidth: 2,
borderColor: {
type: 'linear',
x: 1,
y: 0,
x2: 0,
y2: 0,
colorStops: [
{
offset: 0,
color: 'rgba(71, 202, 219, 0.5)',
},
{
offset: 0.6,
color: 'rgba(45, 209, 185, 0.5)',
},
{
offset: 1,
color: 'rgba(13, 204, 163, 0.5)',
},
],
globalCoord: false,
},
},
},
itemStyle: {
color: {
type: 'linear', // 线
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [
{ offset: 0, color: 'rgba(13, 204, 163, 0.6)' },
{ offset: 1, color: 'rgba(71, 202, 219, 1)' },
],
global: false, // false
},
},
},
],
},
});
watch(
() => props.data,
(val) => {
if (!isEmpty(val)) {
state.option.series[0].data = [0, val.percent];
state.option.series[0].label.formatter = val.percent * 100 + '%';
}
},
{
deep: true,
immediate: true,
}
);
</script>
<style lang="scss" scoped>
.business-right {
margin-top: 20px;
}
.business-left {
width: 100%;
height: 80%;
}
.business {
width: 100%;
height: calc((100vh - 330px) / 3 - 50px);
display: flex;
justify-content: space-around;
align-items: center;
&-title {
width: 160px;
margin: 0 auto;
height: 32px;
line-height: 26px;
font-size: 16px;
font-weight: 400;
text-align: center;
color: #ffffff;
text-shadow: 2px 0px 10px 0px #01eeff;
background: url('@/assets/images/business/bg_title.png');
background-repeat: no-repeat;
background-size: contain;
text-shadow:
0 0 10px #01eeff,
0 0 20px #01eeff,
0 0 30px #01eeff,
0 0 40px #01eeff;
}
&-left,
&-right {
@include flex-column();
flex: 1;
}
&-info {
width: 100%;
@include flex-column();
text-align: center;
li {
@include flex-column();
font-size: 16px;
font-weight: 400;
color: #fff;
margin-top: 16px;
b {
margin-bottom: 10px;
&::before {
display: inline-block;
content: '';
width: 12px;
height: 12px;
border-radius: 6px;
margin-right: 10px;
}
}
&.success {
margin-top: 0 !important;
span {
color: #01faf9;
}
b {
&::before {
background-color: #01faf9;
}
}
}
&.warning {
span {
color: #fef906;
}
b {
&::before {
background-color: #fef906;
}
}
}
&.danger {
span {
color: #fc0003;
}
b {
&::before {
background-color: #fc0003;
}
}
}
}
}
}
</style>

View File

@ -0,0 +1,207 @@
<template>
<centerMap
:dialog-title="'经营主体'"
:marker-data="markerData"
:bg-image="'images/vsualized/mapopup1.png'"
:dialog-width="240"
@mapclick="doMapclick"
>
<template #header>
<div class="buiness-map-pop-header">
<div class="title">{{ currentRegion && currentRegion.name ? currentRegion.name : '经营主体' }}</div>
</div>
</template>
<template #dialogContent>
<div class="buiness-map-pop-content">
<div class="addr">
<el-icon :size="'18px'" :color="'#fff'">
<LocationFilled />
</el-icon>
{{ testInfo.addr || ' --' }}
</div>
<div class="tips-warp">
<div class="label">负责人</div>
<div class="val">{{ testInfo.user || '--' }}</div>
</div>
<div class="tips-warp">
<div class="label">联系方式</div>
<div class="val">{{ testInfo.tel || '--' }}</div>
</div>
<div class="tips-warp">
<div class="label">注册资本</div>
<div class="val">{{ testInfo.capital || '--' }}</div>
</div>
<div class="tips-warp">
<div class="label">成立时间</div>
<div class="val">{{ testInfo.time || '--' }}</div>
</div>
<div class="tips-warp">
<div class="label">信用等级</div>
<div class="val">{{ testInfo.credit || '--' }}</div>
</div>
<div class="img-list">
<div class="img-item">
<el-image
style="width: 80px; height: 60px; cursor: pointer"
:preview-src-list="
testInfo.imglist.map((m) => {
return getAssetsFile(m);
})
"
:src="getAssetsFile(testInfo.imglist[0])"
fit="cover"
lazy
/>
<div class="img-name">营业执照</div>
</div>
<div class="img-item">
<el-image
style="width: 80px; height: 60px; cursor: pointer"
:preview-src-list="
testInfo.imglist.map((m) => {
return getAssetsFile(m);
})
"
:src="getAssetsFile(testInfo.imglist[1])"
fit="cover"
lazy
/>
<div class="img-name">经营许可证</div>
</div>
<!-- <div class="img-item">
<el-image
style="width: 80px; height: 60px; cursor: pointer"
:preview-src-list="
testInfo.imglist.map((m) => {
return getAssetsFile(m);
})
"
:src="getAssetsFile(testInfo.imglist[2])"
fit="cover"
lazy
/>
<div class="img-name">其他证件</div>
</div> -->
</div>
</div>
</template>
</centerMap>
</template>
<script setup>
import { ref, reactive } from 'vue';
import { isEmpty, getAssetsFile } from '@/utils';
const list = reactive([
{ title: '年总产值', value: 3.49, color: '#01FEFD', unit: '亿元' },
{ title: '年人均收入', value: 6.98, color: '#FEF906', unit: '万元' },
]);
let testInfo = reactive({});
let currentRegion = ref(null);
const doMapclick = (data) => {
currentRegion.value = data;
if (data.name == '永星生产加工企业') {
testInfo = {
addr: '云南省临沧市耿马傣族佤族自治县孟定镇101号',
user: '张强',
tel: '15331683325',
capital: '500万',
time: '2018年12月1日',
credit: 'AA',
imglist: ['images/business/b1-1.png', 'images/business/b1-2.png', 'images/business/b1-3.png'],
};
}
if (data.name == '欣欣生产加工企业') {
testInfo = {
addr: '云南省临沧市耿马傣族佤族自治耿马镇102号',
user: '李欣',
tel: '13713575206',
capital: '600万',
time: '2020年10月1日',
credit: 'AA',
imglist: ['images/business/b2-1.png', 'images/business/b1-2.png', 'images/business/b1-2.png'],
};
}
};
let markerData = reactive([
//
{
name: '永星生产加工企业',
value: [99.081993, 23.524045, 150], // , ,
symbol: 'image://' + getAssetsFile('images/vsualized/marker.png'),
itemStyle: {
color: '#4bffb4', //
},
},
{
name: '欣欣生产加工企业',
value: [99.402267, 23.538889, 150], // , ,
symbol: 'image://' + getAssetsFile('images/vsualized/marker.png'),
itemStyle: {
color: '#4bffb4', //
},
},
]);
</script>
<style lang="scss" scoped>
.buiness-map-pop-header {
display: inline-flex;
justify-content: space-between;
width: 100%;
margin-top: 3px;
.title,
.value {
display: inline-block;
vertical-align: middle;
color: $color-white;
}
.title {
font-size: 18px;
}
.value {
font-size: 14px;
}
}
.buiness-map-pop-content {
width: 100%;
.addr {
width: 100%;
display: inline-flex;
color: #fff;
text-align: left;
}
.tips-warp {
width: 100%;
display: inline-flex;
justify-content: space-between;
text-align: left;
margin: 6px 0;
.label {
color: #fef906;
}
.val {
color: #fff;
}
}
.img-list {
width: 100%;
display: inline-flex;
justify-content: space-between;
gap: 10;
flex-wrap: wrap;
.img-item {
width: calc((100% - 10px) / 2);
margin-bottom: 8px;
.el-image {
background: transparent !important;
}
.img-name {
color: #fff;
padding: 6px 0;
}
}
}
}
</style>

View File

@ -0,0 +1,161 @@
<template>
<div class="demo device-charts" style="height: 90%">
<div class="list-item-header item-warp" :style="{ flex: listKeys.length }">
<template v-for="(h, indexh) in listKeys" :key="indexh">
<div class="item-td" :style="{ width: 'calc(100% / ' + listKeys.length + ')' }">{{ listKeysHeader[h] }}</div>
</template>
</div>
<vue3ScrollSeamless class="scroll-wrap" :class-options="classOptions" :data-list="datalist">
<div v-for="(item, index) in datalist" :key="index" class="list-item">
<div class="list-item-content">
<div class="list-item-boday item-warp" :style="{ flex: listKeys.length }">
<template v-for="(b, indexb) in listKeys" :key="indexb">
<div class="item-td" :class="item.status == 1 ? 'td-title' : 'td-warn'" :style="{ width: 'calc(100% / ' + listKeys.length + ')' }">
<span v-if="b == 'num'">
{{ item[b] }}
</span>
<span v-else-if="b == 'duration'" class="duration">
<span class="val">{{ item[b] + 'h' }}</span>
<div class="pro">
<customProgress height="5px" :percent="item.percent" inactive-bg="#081931"></customProgress>
</div>
</span>
<span v-else>
{{ item[b] == 0 ? '待机' : '运行' }}
</span>
</div>
</template>
</div>
</div>
</div>
</vue3ScrollSeamless>
</div>
<!-- </div> -->
</template>
<script setup>
import { ref, onMounted, onUnmounted, computed, reactive } from 'vue';
import { vue3ScrollSeamless } from 'vue3-scroll-seamless';
import customProgress from '@/components/customProgress.vue';
const props = defineProps({
// items: {
// type: Array,
// default: () => [],
// },
});
let list = reactive([
{ num: '投喂机', duration: '3.7', status: 1 },
{ num: '喂水机', duration: '10.0', status: 1 },
{ num: '投喂机', duration: '6.4', status: 1 },
{ num: '喂水机', duration: '3.9', status: 1 },
{ num: '投喂机', duration: '3.6', status: 0 },
{ num: '喂水机', duration: '4.5', status: 1 },
{ num: '投喂机', duration: '5.6', status: 1 },
]);
const listKeys = reactive(['num', 'status', 'duration']);
const listKeysHeader = reactive({
num: '设备编号',
status: '设备状态',
duration: '设备今日运行时长',
});
let datalist = computed(() => {
return list.map((m) => {
return {
...m,
percent: Number((Number(parseInt(m.duration) / max.value) * 100).toFixed(0)),
};
});
});
let max = computed(() => {
let valueList = new Set(list.map((item) => item.duration));
let sortValue = [...valueList].sort((a, b) => b - a) || [];
// console.info('valueList', sortValue);
return sortValue.length ? sortValue[0] : 0;
});
const classOptions = {
singleHeight: 48,
};
</script>
<style scoped lang="scss">
.device-charts {
margin-top: 8px;
.scroll-wrap {
height: 80%;
width: 100%;
margin: 4px auto;
overflow: hidden;
}
.list-item-header {
background: #144482;
font-size: 10px;
width: 100%;
.item-td {
padding: 8px 6px;
}
}
.list-item-boday {
background: transparent;
width: 100%;
.item-td {
padding: 4px 6px;
&.td-title {
color: #6beff9 !important;
}
&.td-warn {
color: red !important;
}
}
}
.item-warp {
display: inline-flex;
justify-content: space-around;
.item-td {
display: inline-block;
vertical-align: middle;
text-align: center;
color: #fff;
}
.duration {
width: 100%;
.val,
.pro {
display: inline-block;
vertical-align: middle;
box-sizing: border-box;
}
.val {
width: 50px;
padding-right: 10px;
}
.pro {
width: calc(100% - 50px);
}
}
}
.list-item {
// border-bottom: 1px dashed rgba(255, 255, 255, 0.2);
line-height: 18px;
.list-item-content {
display: inline-flex;
width: 100%;
justify-content: space-around;
position: relative;
}
}
}
.demo {
// display: flex;
// align-items: center;
// justify-content: center;
// margin-top: 10px;
}
</style>

View File

@ -0,0 +1,196 @@
<template>
<customEchartHyalineCake :chart-data="dataList" :option="option" />
</template>
<script lang="ts" setup>
import { reactive, ref } from 'vue';
/* --------------- 左中饼图 --------------- */
// #region
const dataList = ref([
{
name: '豆菜类作物 25万亩',
value: 60.8,
money: 100,
},
{
name: '根菜类作物 20万亩',
value: 44.4,
money: 88,
},
{
name: '叶菜类作物 10万亩',
value: 24.3,
money: 92,
},
{
name: '茄科类作物 20万亩',
value: 32.7,
money: 56,
},
{
name: '其他蔬菜作物 20万亩',
value: 32.9,
money: 18,
},
]);
const option = reactive({
k: 0.3,
opacity: 1,
itemGap: 0,
autoItemHeight: 2,
grid3D: {
show: false,
boxHeight: 4, //
top: '0', //
left: '-20%',
viewControl: {
//3d
alpha: 30, //( )
distance: 200, //zoom()
rotateSensitivity: 0, //0
zoomSensitivity: 0, //0
panSensitivity: 0, //0
autoRotate: false, //
autoRotateAfterStill: 2, //, autoRotate
},
},
// graphic: {
// elements: [
// // {
// // type: 'polyline',
// // shape: {
// // points: [
// // [100, 150], //
// // [150, 100], //
// // [10, 200], //
// // ],
// // },
// // style: { stroke: '#FF0000', lineWidth: 2 },
// // },
// // {
// // type: 'line',
// // shape: { x1: 80, y1: 150, x2: 0, y2: 200 },
// // style: { stroke: '#fff', lineWidth: 2 },
// // },
// {
// type: 'text',
// left: 0,
// top: 150,
// style: {
// text: ' 20',
// fill: '#FFF',
// fontSize: 14,
// padding: [4, 8],
// borderRadius: 4,
// },
// },
// {
// type: 'text',
// left: 120,
// top: 200,
// style: {
// text: ' 20',
// fill: '#FFF',
// fontSize: 14,
// padding: [4, 8],
// borderRadius: 4,
// },
// },
// {
// type: 'text',
// left: 200,
// top: 100,
// style: {
// text: ' 25',
// fill: '#FFF',
// fontSize: 14,
// padding: [4, 8],
// borderRadius: 4,
// },
// },
// {
// type: 'text',
// left: 20,
// top: 60,
// style: {
// text: ' 20',
// fill: '#FFF',
// fontSize: 14,
// padding: [4, 8],
// borderRadius: 4,
// },
// },
// {
// type: 'text',
// left: 0,
// top: 100,
// style: {
// text: ' 10',
// fill: '#FFF',
// fontSize: 14,
// padding: [4, 8],
// borderRadius: 4,
// },
// },
// // {
// // type: 'text',
// // left: 210,
// // top: 210,
// // style: {
// // text: '3.00',
// // fill: '#FFF',
// // fontSize: 14,
// // backgroundColor: 'rgba(0,0,0,0.7)',
// // padding: [4, 8],
// // borderRadius: 4,
// // },
// // },
// ],
// },
// series: [
// // 2D 线
// {
// type: 'pie',
// radius: ['30%', '70%'],
// center: ['40%', '50%'],
// startAngle: -40, // 3D
// clockwise: false,
// label: {
// show: true,
// position: 'outside',
// formatter: (params) => {
// console.log(params);
// return `{a|${params.data.name}}\n{b|${params.data.money}}`;
// },
// rich: {
// a: { color: '#ffffff' },
// b: { color: '#79F5AF' },
// },
// },
// labelLine: {
// show: true,
// length: 10,
// length2: 15,
// lineStyle: {
// color: '#ffffff',
// width: 1,
// },
// },
// data: dataList,
// itemStyle: {
// opacity: 1, // 线
// },
// },
// ],
});
// #endregion
/* --------------- methods --------------- */
// #region
// #endregion
</script>
<style lang="scss" scoped></style>

View File

@ -0,0 +1,174 @@
<template>
<div class="plant-environment-warp">
<div class="data-item-row">
<div
v-for="(n, index) in datalist"
:key="index"
:style="{
'background-image': 'url(' + getAssetsFile('images/plant/bg3.png') + ')',
width: 'calc((100% - 30px) /' + datalist.length + ')',
}"
class="data-item"
>
<div class="data-warp">
<div class="data-pos">
<div class="data-pos-center">
<div class="pos-center">
<span class="label">{{ n.label }}</span>
<div class="value">
<span>{{ n.value }}</span>
<span class="unit">{{ n.unit }}</span>
</div>
</div>
</div>
</div>
<div class="small-bg">
<img :src="getAssetsFile('images/plant/bg6.png')" />
<img :src="getAssetsFile('images/plant/' + n.icon)" class="img-icon" />
</div>
</div>
</div>
</div>
</div>
</template>
<script setup>
import { isEmpty, getAssetsFile } from '@/utils';
import { ref, reactive, onMounted, watch } from 'vue';
import { useRouter } from 'vue-router';
import { useApp } from '@/hooks';
const router = useRouter();
const props = defineProps({
title: {
type: String,
default: '统计分析',
},
postion: {
type: String,
default: 'left',
},
});
let topTitle = ref('');
let pos = ref('');
const datalist = reactive([
{ label: '空气温度', value: 28.6, unit: '℃', icon: 'icon4.png' },
{ label: '空气湿度', value: 30, unit: '%', icon: 'icon3.png' },
{ label: '光照强度', value: 1000, unit: 'lux', icon: 'icon1.png' },
{ label: '降水量', value: 100, unit: 'mm', icon: 'icon2.png' },
]);
onMounted(() => {
if (datalist.length) {
datalist.forEach((m, index) => {
let num = 0;
switch (index) {
case 0:
num = 20;
break;
case 1:
num = 30;
break;
case 2:
num = 1000;
break;
case 3:
num = 100;
break;
default:
num = 10;
break;
}
m.value = (Math.random() + num).toFixed(2);
});
}
});
watch(
() => (props.title, props.postion),
() => {
topTitle.value = props.title;
pos.value = props.postion;
},
{
deep: true,
immediate: true,
}
);
</script>
<style lang="scss" scoped>
.plant-environment-warp {
height: 100%;
width: 100%;
.data-item-row {
height: 100%;
width: 100%;
display: inline-flex;
justify-content: space-around;
flex-wrap: wrap;
gap: 10px;
}
.data-item {
height: 100%;
background-size: 100% 100%;
position: relative;
}
.data-warp {
padding: 8px 0;
text-align: center;
z-index: 1;
display: inline-flex;
justify-content: center;
.small-bg,
.data-pos {
display: inline-flex;
vertical-align: middle;
.data-pos-center {
display: inline-flex;
justify-content: space-around;
flex-direction: column;
height: 100%;
.pos-center {
}
}
}
.small-bg {
width: 38px;
height: 38px;
position: relative;
margin-top: 10%;
.img-icon {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
width: 38%;
height: 38%;
}
}
.data-pos {
width: calc(100% - 54px);
.label,
.value {
display: inline-block;
width: 100%;
}
.label {
color: #fff;
font-size: 13px;
}
.value {
color: #6beff9;
font-size: 16px;
font-weight: bold;
margin-top: 6px;
}
.unit {
font-size: 10px;
}
}
}
}
</style>

View File

@ -0,0 +1,226 @@
<template>
<div class="growth-indexes-charts">
<custom-echart-mixin :chart-data="handelData" :option="chartsData.option" height="100%" />
</div>
</template>
<script setup>
import { ref, reactive, onMounted, computed } from 'vue';
let itemStyle = reactive({
itemStyle: { borderRadius: [8, 8, 0, 0] },
});
let legendList = reactive(['猪', '牛', '羊', '鸡', '其他']);
const chartsData = reactive({
option: {
title: {
textStyle: {
color: '#fff',
},
},
tooltip: {
trigger: 'axis',
},
grid: {
left: '2%',
right: '2%',
bottom: '3%',
top: '18%',
containLabel: true,
},
legend: {
data: ['货款', '投保'],
left: '35%', // 10%
top: '0', //
itemWidth: 20, //
itemHeight: 20, //
textStyle: {
color: '#fff',
fontSize: '15',
},
},
calculable: true,
xAxis: [
{
type: 'value',
boundaryGap: [0, 0.01],
axisLabel: {
show: false,
},
axisLine: {
show: false,
},
axisTick: {
show: false,
},
splitLine: {
show: false,
},
},
],
yAxis: [
{
type: 'category',
name: '',
data: ['其他', '仓储', '生产加工', '种植'],
axisLabel: {
textStyle: {
fontSize: 15,
color: '#fff',
},
},
axisLine: {
show: false,
},
axisTick: {
show: false,
},
splitLine: {
show: false,
},
},
],
series: [
{
name: '货款',
type: 'bar',
barWidth: '10px',
itemStyle: {
normal: {
color: '#35d0c0',
barBorderRadius: 10,
},
},
label: {
//
show: true,
position: 'outside', // top / bottom / inside / outside
formatter: '{c}亿元',
color: '#fff', //
fontSize: 10,
},
data: [10, 15, 8.5, 5, 5, 16],
},
{
name: '投保',
type: 'bar',
barWidth: '10px',
itemStyle: {
normal: {
color: '#fef906',
barBorderRadius: 10,
},
},
label: {
//
show: true,
position: 'outside', // top / bottom / inside / outside
formatter: '{c}亿元',
color: '#fff', //
fontSize: 10,
},
data: [6, 6.5, 6, 3, 2, 10],
},
],
// color: ['#3685fe', '#41b879', '#ffd500', '#e57373'],
// title: {
// text: ' ',
// textStyle: {
// color: '#333',
// },
// },
// legend: {
// show: true,
// data: legendList,
// left: '0', // 10%
// top: '0', //
// itemWidth: 15, //
// itemHeight: 8, //
// textStyle: {
// fontSize: 10, //
// color: '#fff', //
// },
// },
// barStyle: {
// barWidth: 10,
// },
// dataZoom: [
// // {
// // type: 'slider', //
// // startValue: 0, //
// // endValue: 2, //
// // },
// // {
// // type: 'inside', //
// // startValue: 0,
// // endValue: 2,
// // },
// ],
// yAxis: [
// {
// type: 'value',
// name: ' ',
// axisLabel: {
// formatter: '{value}',
// },
// splitLine: {
// show: true, // 线
// lineStyle: {
// type: 'dashed', // 线
// width: 0.5, // 线
// },
// },
// itemStyle: { fontSize: 8 },
// },
// ],
// grid: {
// x: '10%',
// x2: '10%',
// y: '20%',
// y2: '20%',
// },
},
valData: [],
});
const randomVal = (num) => {
let list = [];
for (let i = 0; i < legendList.length; i++) {
let addNum = [10, 8, 2, 5];
let val = {
name: num + '月',
value: Number(Math.random() * 100 + addNum[i]).toFixed(2),
seriesType: 'bar',
type: legendList[i],
stack: num + '月',
};
let lastVal = {
...val,
...itemStyle,
};
list[i] = i < legendList.length - 1 ? val : lastVal;
}
return list;
};
let handelData = computed(() => {
let list = [];
let maxMouth = 12;
for (let i = 0; i < maxMouth; i++) {
let val = randomVal(i + 1);
list = [...list, ...val];
}
list.map((m, indexm) => {
return { ...m, value: Number(Number(m.value) + Math.random() + indexm).toFixed(0) };
});
// console.info('handelData', list);
return list;
});
onMounted(() => {});
</script>
<style lang="scss" scoped>
.growth-indexes-charts {
height: 100%;
}
</style>

View File

@ -0,0 +1,122 @@
<template>
<div class="demo health-status-charts" style="height: 90%">
<div class="list-item-header item-warp" :style="{ flex: listKeys.length }">
<template v-for="(h, indexh) in listKeys" :key="indexh">
<div class="item-td" :style="{ width: 'calc(100% / ' + listKeys.length + ')' }">{{ listKeysHeader[h] }}</div>
</template>
</div>
<vue3ScrollSeamless class="scroll-wrap" :class-options="classOptions" :data-list="list">
<div v-for="(item, index) in list" :key="index" class="list-item">
<div class="list-item-content">
<div class="list-item-boday item-warp" :style="{ flex: listKeys.length }">
<template v-for="(b, indexb) in listKeys" :key="indexb">
<div class="item-td" :class="item.status == 1 ? 'td-title' : 'td-warn'" :style="{ width: 'calc(100% / ' + listKeys.length + ')' }">
<span v-if="b != 'status'">
{{ item[b] }}
</span>
<el-icon v-else>
<Bell></Bell>
</el-icon>
</div>
</template>
</div>
</div>
</div>
</vue3ScrollSeamless>
</div>
<!-- </div> -->
</template>
<script setup>
import { ref, onMounted, onUnmounted, computed, reactive } from 'vue';
import { vue3ScrollSeamless } from 'vue3-scroll-seamless';
const props = defineProps({
// items: {
// type: Array,
// default: () => [],
// },
});
let list = reactive([
{ diseaseType: '瘟疫', incidenceRate: '23%', coverage: '84%', status: 1 },
{ diseaseType: '蓝耳病', incidenceRate: '19%', coverage: '88%', status: 1 },
{ diseaseType: '口蹄疫', incidenceRate: '45%', coverage: '68%', status: 1 },
{ diseaseType: '链球病菌', incidenceRate: '35%', coverage: '88%', status: 1 },
{ diseaseType: '炎症', incidenceRate: '8%', coverage: '98%', status: 1 },
{ diseaseType: '寄生虫', incidenceRate: '11%', coverage: '99%', status: 1 },
]);
const listKeys = reactive(['diseaseType', 'incidenceRate', 'coverage', 'status']);
const listKeysHeader = reactive({
diseaseType: '疾病种类',
incidenceRate: '发病率',
coverage: '疫苗接种率',
status: '预警',
});
const classOptions = {
singleHeight: 48,
};
</script>
<style scoped lang="scss">
.health-status-charts {
margin-top: 8px;
.scroll-wrap {
height: 80%;
width: 100%;
margin: 4px auto;
overflow: hidden;
}
.list-item-header {
background: #144482;
font-size: 10px;
width: 100%;
.item-td {
padding: 8px 6px;
}
}
.list-item-boday {
background: transparent;
width: 100%;
.item-td {
padding: 4px 6px;
&.td-title {
color: #6beff9 !important;
}
&.td-warn {
color: red !important;
}
}
}
.item-warp {
display: inline-flex;
justify-content: space-around;
.item-td {
display: inline-block;
vertical-align: middle;
text-align: center;
color: #fff;
}
}
.list-item {
// border-bottom: 1px dashed rgba(255, 255, 255, 0.2);
line-height: 18px;
.list-item-content {
display: inline-flex;
width: 100%;
justify-content: space-around;
position: relative;
}
}
}
.demo {
// display: flex;
// align-items: center;
// justify-content: center;
// margin-top: 10px;
}
</style>

View File

@ -0,0 +1,179 @@
<template>
<div class="irrigation-charts">
<div class="charts-content">
<div class="water-droplet-bg" :style="{ 'background-image': 'url(' + getAssetsFile('images/plant/bg5.png') + ')' }">
<div class="water-droplet">
<custom-echart-water-droplet height="100%" :option="option" />
</div>
</div>
<div class="water-droplet-warp">
<template v-for="(n, index) in itemlist" :key="index">
<div class="water-droplet-item" :style="{ height: 'calc((100% - 20px) / ' + itemlist.length + ')' }">
<div class="title" :style="{ 'background-image': 'url(' + getAssetsFile(n.bg1) + ')' }">
<div class="title-val" :style="{ color: n.color }">{{ n.title }}</div>
</div>
<div class="tips" :style="{ 'background-image': 'url(' + getAssetsFile(n.bg2) + ')' }">
<span class="tips-val">{{ n.tips }}</span>
</div>
</div>
</template>
</div>
</div>
</div>
</template>
<script setup>
import { ref, reactive, onMounted } from 'vue';
import { isEmpty, getAssetsFile } from '@/utils';
let percent = ref(0.6);
let itemlist = reactive([
{ title: '智能喂水', bg1: 'images/plant/bg8.png', bg2: 'images/plant/bg7.png', tips: '去喂水', color: '#4a90e2ff' },
{ title: '智能投喂', bg1: 'images/plant/bg9.png', bg2: 'images/plant/bg7.png', tips: '去投喂', color: '#50e3c2ff' },
]);
const option = reactive({
backgroundColor: 'transparent', //
series: [
{
name: '预估量',
type: 'liquidFill',
radius: '80%',
center: ['50%', '50%'],
backgroundStyle: {
color: 'transparent',
},
data: [percent.value, percent.value],
amplitude: 12, //
label: {
//
position: ['50%', '45%'],
formatter: percent.value * 100 + '%', //,
textStyle: {
fontSize: '20px', //,
color: '#fff',
},
},
outline: {
borderDistance: 3,
itemStyle: {
borderWidth: 1,
borderColor: {
type: 'linear',
x: 1,
y: 0,
x2: 0,
y2: 0,
colorStops: [
{
offset: 0,
color: 'rgba(255, 255, 255, 0.8)',
},
{
offset: 0.6,
color: 'rgba(255, 255, 255, 0.8)',
},
{
offset: 1,
color: 'rgba(255, 255, 255, 0.8)',
},
],
globalCoord: false,
},
},
},
itemStyle: {
color: {
type: 'linear', // 线
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [
{ offset: 0, color: '#45bfe9' },
{ offset: 1, color: '#01589c' },
],
global: false, // false
},
},
},
],
});
onMounted(() => {});
</script>
<style lang="scss" scoped>
.irrigation-charts {
height: 100%;
.charts-content {
display: inline-flex;
justify-content: space-between;
width: 100%;
height: 100%;
.water-droplet-bg {
display: inline-block;
width: 40%;
background-size: contain;
background-repeat: no-repeat;
background-position: center bottom;
position: relative;
.water-droplet {
position: absolute;
left: 50%;
top: 10%;
transform: translateX(-50%);
}
}
.water-droplet-warp {
width: 60%;
padding: 0 10px;
display: inline-flex;
vertical-align: middle;
flex-direction: column;
.water-droplet-item {
width: 100%;
}
.title,
.tips {
display: inline-block;
color: #fff;
vertical-align: top;
.tips-val {
display: inline-flex;
line-height: 42px;
text-align: center;
font-size: 14px;
font-weight: bold;
transform: skewX(-13deg) translateY(-50%);
background: linear-gradient(to bottom, '#ff7e5f', '#548fff');
-webkit-background-clip: text;
color: #fff;
letter-spacing: 2px;
text-shadow: -6px 0 0 1px #add8f1;
position: absolute;
left: 0;
top: 50%;
}
}
.title {
width: 40%;
height: 100%;
background-size: contain;
background-position: left bottom;
background-repeat: no-repeat;
.title-val {
width: 100%;
text-align: center;
line-height: 32px;
}
}
.tips {
width: 60%;
height: 100%;
background-size: 100% auto;
background-repeat: no-repeat;
background-position: left center;
position: relative;
}
}
}
}
</style>

View File

@ -0,0 +1,25 @@
<template>
<div class="monitoring-screen-warp">
<div class="monitoring-screen-content" :style="{ 'background-image': 'url(' + getAssetsFile('images/plant/bg2.png') + ')' }"></div>
</div>
</template>
<script setup>
import { isEmpty, getAssetsFile } from '@/utils';
</script>
<style lang="scss" scoped>
.monitoring-screen-warp {
height: 100%;
width: 100%;
box-sizing: border-box;
.monitoring-screen-content {
background-size: 100% 100%;
background-repeat: no-repeat;
width: 100%;
height: 100%;
padding: 10px 0;
div {
box-sizing: border-box;
}
}
}
</style>

View File

@ -0,0 +1,73 @@
<template>
<div class="notice-bar-warp" :style="{ height: height }">
<div class="notice-bar-pos">
<div class="notice-icon">
<img :src="getAssetsFile('images/plant/icon5.png')" />
</div>
<div class="notice-bar" :style="{ 'line-height': height }">
<div class="scrolling-text">
<span>{{ text }}</span>
</div>
</div>
</div>
</div>
</template>
<script setup>
import { isEmpty, getAssetsFile } from '@/utils';
import { ref, reactive, onMounted } from 'vue';
defineProps({
text: {
type: String,
required: true,
default: '这是一条滚动通知消息,请注意查看!',
},
height: {
type: String || Number,
default: '40px',
},
});
</script>
<style scoped lang="scss">
.notice-bar-warp {
width: 100%;
display: inline-flex;
flex-direction: column;
justify-content: center;
.notice-bar-pos {
display: inline-flex;
width: 100%;
}
.notice-icon {
display: inline-block;
vertical-align: middle;
width: 30px;
img {
width: 80%;
height: 80%;
margin: 10% 0;
}
}
}
.notice-bar {
display: inline-block;
overflow: hidden;
width: calc(100% - 30px);
}
.scrolling-text {
white-space: nowrap;
animation: scroll-left 10s linear infinite;
color: #fff;
}
@keyframes scroll-left {
0% {
transform: translateX(100%);
}
100% {
transform: translateX(-100%);
}
}
</style>

View File

@ -0,0 +1,116 @@
<template>
<div class="plant-gs-warp">
<div ref="viewwarp" class="plant-gs-content" :style="{ 'background-image': 'url(' + getAssetsFile('images/plant/bg1.png') + ')' }">
<vc-config-provider :cesium-path="vcConfig.cesiumPath" :access-token="vcConfig.accessToken">
<vc-viewer ref="viewerRef" @ready="onViewerReady">
<vc-layer-imagery :minimum-level="12" :maximum-level="18" :contrast="1.8" :saturation="1" :alpha="1">
<vc-imagery-provider-amap :key="'c843a50db7157faf295c6fa37c48719f'"></vc-imagery-provider-amap>
</vc-layer-imagery>
<vc-overlay-html ref="html" :position="pos" :show="show">
<div class="vc-name">耿马镇</div>
</vc-overlay-html>
<vc-entity description="Hello VueCesium">
<vc-graphics-rectangle
ref="rectangle2"
:coordinates="hierarchy4"
:material="[59, 199, 231, 80]"
:rotation="0.9"
:extruded-height="1000"
:height="0"
:outline="true"
:outline-width="0.1"
:clamp-to-ground="false"
:outline-color="[59, 199, 231, 150]"
></vc-graphics-rectangle>
</vc-entity>
</vc-viewer>
</vc-config-provider>
</div>
</div>
</template>
<script setup>
import { isEmpty, getAssetsFile } from '@/utils';
import { ref, reactive, onMounted, computed, nextTick, getCurrentInstance } from 'vue';
import {
VcViewer,
VcConfigProvider,
VcImageryProviderAmap,
VcLayerImagery,
VcGraphicsPlane,
VcEntity,
VcGraphicsPolygon,
VcGraphicsRectangle,
VcOverlayHtml,
} from 'vue-cesium';
import 'vue-cesium/dist/index.css';
const vcConfig = reactive({
cesiumPath: 'https://cdn.bootcdn.net/ajax/libs/cesium/1.80.0/Cesium.js',
accessToken:
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJiNjJjZTUxYi1lOTQ3LTQ3YjctOGI3ZS02ZGUzY2E4YWFkNDkiLCJpZCI6Mjg4MjAxLCJpYXQiOjE3NDMwNTY0MzN9.rjHQiqf7Y8bccaqsapqveULVAUH6M1QkeFp-AKG-frA',
});
const viewerRef = ref(null);
const viewwarp = ref(null);
const rectangle2 = ref(null);
onMounted(() => {
Promise.all([rectangle2.value.creatingPromise]).then((instances) => {
// console.info('aa', instances[0].viewer.entities);
instances[0].viewer.zoomTo(instances[0].viewer.entities);
});
});
const hierarchy4 = reactive([99.302267, 23.438899, 99.312267, 23.448889]);
const pos = reactive([99.302267, 23.438899]);
const onViewerReady = (readyObj) => {
console.info('readyObj', readyObj.Cesium); // Cesium namespace object
console.log(readyObj.viewer); // instanceof Cesium.Viewer
const { Cesium, viewer } = readyObj;
//
viewer.camera.setView({
destination: Cesium.Cartesian3.fromDegrees(99.516667, 23.640556, 4000), //
orientation: {
ading: Cesium.Math.toRadians(6), //
pitch: Cesium.Math.toRadians(-25), //
roll: Cesium.Math.toRadians(6), //
},
});
};
</script>
<style lang="scss" scoped>
.plant-gs-warp {
height: 100%;
padding: 10px 0;
width: 100%;
box-sizing: border-box;
.plant-gs-content {
background-size: 100% 100%;
background-repeat: no-repeat;
width: 100%;
height: 100%;
overflow: hidden;
.vc-name {
color: #fff;
font-size: 16px;
font-weight: bold;
}
::v-deep() {
.vc-viewer {
height: calc(100% - 30px) !important;
width: calc(100% - 20px) !important;
margin: 20px 10px 10px 10px !important;
}
canvas {
border-radius: 10px !important;
}
.cesium-viewer-bottom {
display: none !important;
}
}
}
}
</style>

View File

@ -0,0 +1,196 @@
<template>
<div class="water-intake-charts">
<custom-echart-mixin :chart-data="handelData" :option="chartsData.option" />
</div>
</template>
<script setup>
import { ref, reactive, onMounted, computed } from 'vue';
let itemStyle = reactive({
itemStyle: { borderRadius: [8, 8, 0, 0] },
});
let legendList = reactive(['种子', '番茄', '小麦']);
const chartsData = reactive({
option: {
color: ['#0AF2FE', '#2196f3', '#02fd94'],
series: [
{
type: 'pie', //
clockWise: false,
radius: [60, 40],
center: ['40%', '50%'],
hoverAnimation: false,
itemStyle: {
borderRadius: 5,
normal: {
label: {
position: 'outside',
formatter: function (params) {
if (params.name !== '') {
return '{name|' + params.name + '}' + '\n\n{value|' + params.value + '}吨';
} else {
return '';
}
},
align: 'left',
rich: {
name: {
fontSize: 14,
fontFamily: 'PingFang SC',
fontWeight: 500,
color: '#fff',
},
value: {
fontSize: 20,
fontFamily: 'D-DIN',
fontWeight: 400,
},
},
},
labelLine: {
width: 4,
show: true,
length: 30,
length2: 60,
color: '#fff',
},
},
},
tooltip: {
show: true,
},
data: [
{
value: 11325,
name: '种子',
itemStyle: {
normal: {
borderWidth: 5,
borderRadius: 20,
shadowBlur: 0,
borderColor: '#0AF2FE',
shadowColor: '#0AF2FE',
},
},
},
{
value: '3000',
name: '',
itemStyle: {
normal: {
label: {
show: false,
},
labelLine: {
show: false,
},
color: 'rgba(0, 0, 0, 0)',
borderColor: 'rgba(0, 0, 0, 0)',
borderWidth: 0,
},
},
},
{
value: 123000,
name: '化肥',
itemStyle: {
normal: {
borderWidth: 5,
borderRadius: 20,
shadowBlur: 0,
borderColor: '#2196f3',
shadowColor: '#2196f3',
},
},
},
{
value: '3000',
name: '',
itemStyle: {
normal: {
label: {
show: false,
},
labelLine: {
show: false,
},
color: 'rgba(0, 0, 0, 0)',
borderColor: 'rgba(0, 0, 0, 0)',
borderWidth: 0,
},
},
},
{
value: 601,
name: '农药',
itemStyle: {
normal: {
borderWidth: 5,
borderRadius: 20,
shadowBlur: 0,
borderColor: '#02fd94',
shadowColor: '#02fd94',
},
},
},
{
value: '3000',
name: '',
itemStyle: {
normal: {
label: {
show: false,
},
labelLine: {
show: false,
},
color: 'rgba(0, 0, 0, 0)',
borderColor: 'rgba(0, 0, 0, 0)',
borderWidth: 0,
},
},
},
],
},
],
},
valData: [],
});
const randomVal = (num) => {
let list = [];
for (let i = 0; i < legendList.length; i++) {
let addNum = [10, 8, 2, 5];
let val = {
name: num + '月',
value: Number(Math.random() * 100 + addNum[i]).toFixed(2),
seriesType: 'bar',
type: legendList[i],
...itemStyle,
};
list[i] = val;
}
return list;
};
let handelData = computed(() => {
let list = [];
let maxMouth = 6;
for (let i = 0; i < maxMouth; i++) {
let val = randomVal(i + 1);
list = [...list, ...val];
}
list.map((m) => {
return { ...m, value: Number(m.value + Math.random() + 10).toFixed(2) };
});
// console.info('handelData', list);
return list;
});
onMounted(() => {});
</script>
<style lang="scss" scoped>
.water-intake-charts {
height: 100%;
}
</style>

View File

@ -0,0 +1,200 @@
<template>
<div class="data-home-index" :style="{ backgroundImage: `url(${bgImageUrl})` }">
<el-row style="width: 100%; height: 100%">
<el-col :span="6" class="left-charts">
<div class="left-charts-item">
<customBack style="height: 100%" top-title="智慧种植数据统计" :top-postion="'left'">
<template #back>
<entitieslist></entitieslist>
</template>
</customBack>
</div>
<div class="left-charts-item">
<customBack style="height: 100%" top-title="电商数据统计" :top-postion="'left'">
<template #back>
<waterIntakeCharts></waterIntakeCharts>
</template>
</customBack>
</div>
<div class="left-charts-item">
<customBack style="height: 100%" top-title="涉农金融数据统计" :top-postion="'left'">
<template #back>
<growthIndexesCharts></growthIndexesCharts>
</template>
</customBack>
</div>
</el-col>
<el-col :span="12">
<businessMap></businessMap>
</el-col>
<el-col :span="6" class="right-charts">
<div class="right-charts-item">
<customBack top-title="分拣包装数据统计" :top-postion="'right'">
<template #back>
<InventoryCharts></InventoryCharts>
</template>
</customBack>
</div>
<div class="right-charts-item">
<customBack top-title="仓储物流数据统计" :top-postion="'right'">
<template #back>
<div style="display: flex; justify-content: space-around; align-items: center; height: 100%">
<div style="height: 100%; width: 100%">
<div class="left-title">仓储总面积()</div>
<div class="left-title-number">16266.23</div>
<div style="width: 100%; height: calc(100% - 60px)">
<benefitCharts></benefitCharts>
</div>
</div>
<div style="height: 100%; width: 100%">
<div class="right-title">本月物流量统计()</div>
<div class="right-title-number">88100</div>
<div style="width: 100%; height: calc(100% - 60px)">
<benefitChartsl></benefitChartsl>
</div>
</div>
</div>
</template>
</customBack>
</div>
<div class="right-charts-item">
<customBack top-title="公共品牌数据统计" :top-postion="'right'">
<template #back>
<businessFour :data="four" />
</template>
</customBack>
</div>
</el-col>
</el-row>
<img :src="getAssetsFile('images/basic/containerBotBG.png')" alt="" style="position: absolute; bottom: 0; width: 100%" />
</div>
</template>
<script setup>
import InventoryCharts from './components/InventoryCharts.vue';
import waterIntakeCharts from './components/waterIntakeCharts.vue';
import growthIndexesCharts from './components/growthIndexesCharts.vue';
import businessFour from './components/businessFour.vue';
import benefitCharts from './components/benefitCharts.vue';
import benefitChartsl from './components/benefitChartsl.vue';
import { reactive, ref, onMounted } from 'vue';
import entitieslist from './components/entitieslist.vue';
import businessMap from './components/businessMap.vue';
import { getAssetsFile } from '@/utils/index.js';
let four = reactive({
percent: 0.3998,
success: 253,
warning: 5,
danger: 0,
});
const bgImageUrl = ref('');
//
onMounted(() => {
getAssetsFile('images/basic/containerBG.png');
bgImageUrl.value = getAssetsFile('images/basic/containerBG.png');
});
</script>
<style lang="scss" scoped>
.data-home-index {
margin: 0 20px;
height: calc(100vh - 240px);
position: relative;
background-color: #000000;
background-size: cover; /* 填充整个容器 */
background-position: center; /* 图片居中 */
background-repeat: no-repeat;
.left-charts {
display: flex;
justify-content: space-around;
width: 95%;
height: calc(100vh - 240px);
flex-direction: column;
padding: 20px;
}
.left-charts-item {
width: 100%;
height: 33%;
}
.right-charts {
display: flex;
justify-content: space-around;
width: 100%;
height: calc(100vh - 240px);
padding: 20px;
flex-direction: column;
}
.right-charts-item {
width: 100%;
height: 33%;
.right-title {
line-height: 30px;
text-align: center;
font-size: 13px;
color: #fff;
width: 100%;
height: 30px;
background-image: url('@/assets/images/inputs/bg_title.png');
background-size: 100% 100%;
text-shadow:
0 0 10px #01eeff,
0 0 20px #01eeff,
0 0 30px #01eeff,
0 0 40px #01eeff;
}
.left-title {
line-height: 30px;
text-align: center;
font-size: 13px;
color: #fff;
width: 100%;
height: 30px;
background-image: url('@/assets/images/inputs/bg_title.png');
background-size: 100% 100%;
text-shadow:
0 0 10px #01eeff,
0 0 20px #01eeff,
0 0 30px #01eeff,
0 0 40px #01eeff;
}
.right-title-number {
line-height: 30px;
text-align: center;
font-size: 20px;
font-weight: bold;
color: #01faf9;
width: 100%;
height: 30px;
}
.left-title-number {
line-height: 30px;
text-align: center;
font-size: 20px;
font-weight: bold;
color: #01faf9;
width: 100%;
height: 30px;
}
}
.center-top {
padding: 16px;
.notice,
.top,
.map-gis {
display: inline-block;
width: 100%;
}
.notice {
height: 40px;
}
.top {
height: 80px;
}
.map-gis {
height: calc(100% - 140px);
}
}
}
</style>

View File

@ -0,0 +1,57 @@
<template>
<div class="ecommerce-common-warp">
<div class="ecommerce-common-content">
<div
class="common-content"
:style="{
background: 'url(' + getAssetsFile('images/vsualized/homeb.png') + ')',
}"
>
<slot v-if="$slots.main" name="main"></slot>
<template v-else></template>
</div>
</div>
</div>
</template>
<script setup>
import { ref, reactive, onMounted, watch } from 'vue';
import { getAssetsFile } from '#/utils/index.js';
const props = defineProps({
currentName: { type: String, default: 'agricultural' },
});
</script>
<style lang="scss" scoped>
.ecommerce-common-warp {
position: absolute;
width: 100%;
text-align: center;
height: 100%;
// height: calc(100vh - 230px);
text-align: center;
.ecommerce-common-content {
display: inline-flex;
justify-content: space-between;
margin: auto;
width: $width-main;
height: 100%;
.left-menu,
.common-content {
overflow-y: auto;
overflow-x: hidden;
padding: 8px;
// height: calc(100% - 16px);
border-radius: 8px;
}
.left-menu {
width: 240px;
background: $color-fff;
}
.common-content {
width: calc(100% - 20px);
}
}
}
</style>

View File

@ -1,138 +0,0 @@
<template>
<dev></dev>
</template>
<!-- <template>
<div class="data-home-index">
<el-row style="width: 100%; height: 100%">
<el-col :span="6" class="left-charts">
<div class="left-charts-item">
<customBack top-title="智慧种植数据统计" :top-postion="'left'">
<template #back>
<entitieslist></entitieslist>
</template>
</customBack>
</div>
<div class="left-charts-item">
<customBack top-title="电商数据统计" :top-postion="'left'">
<template #back>
<waterIntakeCharts></waterIntakeCharts>
</template>
</customBack>
</div>
<div class="left-charts-item">
<customBack top-title="涉农金融数据统计" :top-postion="'left'">
<template #back>
<growthIndexesCharts></growthIndexesCharts>
</template>
</customBack>
</div>
</el-col>
<el-col :span="12">
<businessMap></businessMap>
</el-col>
<el-col :span="6" class="right-charts">
<div class="right-charts-item">
<customBack top-title="分拣包装数据统计" :top-postion="'right'">
<template #back>
<InventoryCharts></InventoryCharts>
</template>
</customBack>
</div>
<div class="right-charts-item">
<customBack top-title="仓储物流数据统计" :top-postion="'right'">
<template #back>
<div style="display: flex; justify-content: space-evenly; align-items: center">
<div style="width: 200px; height: 200px">
<benefitCharts></benefitCharts>
</div>
<div style="width: 200px; height: 200px">
<benefitChartsl></benefitChartsl>
</div>
</div>
</template>
</customBack>
</div>
<div class="right-charts-item">
<customBack top-title="公共品牌数据统计" :top-postion="'right'">
<template #back>
<businessFour :data="four" />
</template>
</customBack>
</div>
</el-col>
</el-row>
</div>
</template>
<script setup>
import InventoryCharts from './components/InventoryCharts.vue';
import waterIntakeCharts from './components/waterIntakeCharts.vue';
import growthIndexesCharts from './components/growthIndexesCharts.vue';
import businessFour from './components/businessFour.vue';
import plantgs from './components/plantgs.vue';
import noticeBar from './components/noticeBar.vue';
import irrigationCharts from './components/irrigationCharts.vue';
// import healthStatusCharts from './components/healthStatusCharts.vue';
import monitoringScreen from './components/monitoringScreen.vue';
import benefitCharts from './components/benefitCharts.vue';
import benefitChartsl from './components/benefitChartsl.vue';
import { reactive } from 'vue';
import entitieslist from './components/entitieslist.vue';
import businessMap from './components/businessMap.vue';
// import deviceCharts from './components/deviceCharts.vue';
let four = reactive({
percent: 0.3998,
success: 253,
warning: 5,
danger: 0,
});
</script>
<style lang="scss" scoped>
.data-home-index {
background-color: black;
height: 75vh;
margin: 0 15%;
.left-charts {
display: flex;
justify-content: space-around;
width: 100%;
height: 100%;
flex-direction: column;
}
.left-charts-item {
width: 100%;
height: calc((100% - 30px) / 3);
}
.right-charts {
display: flex;
justify-content: space-around;
width: 100%;
height: 100%;
flex-direction: column;
}
.right-charts-item {
width: 100%;
height: calc((100% - 30px) / 3);
}
.center-top {
padding: 16px;
.notice,
.top,
.map-gis {
display: inline-block;
width: 100%;
}
.notice {
height: 40px;
}
.top {
height: 80px;
}
.map-gis {
height: calc(100% - 140px);
}
}
}
</style> -->

View File

@ -14,9 +14,10 @@
<el-row :gutter="16">
<el-col :span="12">
<banner
:key="currentIndex"
v-if="currentGood.goodUrls.length > 0"
name="landdetail"
:imglist="mockData[currentIndex].images"
:imglist="currentGood.goodUrls"
:is-montage="false"
indicator-pos="none"
arrow="always"
height="340px"
@ -25,27 +26,32 @@
</banner>
</el-col>
<el-col :span="12" class="top-info-txt">
<h1 class="title">{{ mockData[currentIndex].titleName }}</h1>
<h1 class="title">{{ currentGood.goodName }}</h1>
<div class="price-sold">
<span class="price">{{ mockData[currentIndex].price }}</span>
<span class="sold">{{ mockData[currentIndex].sold }}</span>
<span class="price">{{ currentPrice }}</span>
<span class="sold">{{ currentGood.salesVolume }}</span>
</div>
<div class="tips-list">
<el-row :gutter="16">
<el-col :span="24">发货地址{{ mockData[currentIndex].soldAddress }}</el-col>
<el-col :span="24">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{{ mockData[currentIndex].right }}</el-col>
<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 mockData[currentIndex].weight"
:key="currentIndex + '-' + index"
v-for="(item, index) in currentGood.netWeight"
:key="index"
class="spu-sku-item"
:class="[index === 0 ? 'act' : 'normal']"
:class="[index === currentWeight ? 'act' : 'normal']"
@click="currentWeight = index"
>
{{ item }}
{{ item.goodSpecs }}/{{ item.unit }}
</div>
</div>
<div class="goods-num">
@ -79,96 +85,18 @@
<div class="tab-content">
<div v-if="tabVal === 'detail'" class="content-detail">
<div v-if="showDetail">
<el-descriptions class="detail-des" title=" " :column="2" size="Large" border>
<el-descriptions-item>
<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">品牌</div>
<div class="cell-item">{{ item.value.name }}</div>
</template>
<span>童涵春堂</span>
<span>{{ item.value.value }}</span>
</el-descriptions-item>
<el-descriptions-item>
<template #label>
<div class="cell-item">系列</div>
</template>
<span>农用百货</span>
</el-descriptions-item>
<el-descriptions-item>
<template #label>
<div class="cell-item">型号</div>
</template>
<span>种子种苗</span>
</el-descriptions-item>
<el-descriptions-item>
<template #label>
<div class="cell-item">产地</div>
</template>
<span>耿马县</span>
</el-descriptions-item>
<el-descriptions-item>
<template #label>
<div class="cell-item">省份</div>
</template>
<span>云南省</span>
</el-descriptions-item>
<el-descriptions-item>
<template #label>
<div class="cell-item">城市</div>
</template>
<span>临沧市</span>
</el-descriptions-item>
<el-descriptions-item>
<template #label>
<div class="cell-item">储存条件</div>
</template>
<span>15~25避免高温或冷冻</span>
</el-descriptions-item>
<el-descriptions-item>
<template #label>
<div class="cell-item">包装方式</div>
</template>
<span>盒装</span>
</el-descriptions-item>
<el-descriptions-item>
<template #label>
<div class="cell-item">净含量</div>
</template>
<span>50g100g250g500g</span>
</el-descriptions-item>
<el-descriptions-item>
<template #label>
<div class="cell-item">使用方式</div>
</template>
<span>种植</span>
</el-descriptions-item>
<!-- <el-descriptions-item>-->
<!-- <template #label>-->
<!-- <div class="cell-item">厂名</div>-->
<!-- </template>-->
<!-- <span>遇合堂禽畜药品有限公司</span>-->
<!-- </el-descriptions-item>-->
<!-- <el-descriptions-item>-->
<!-- <template #label>-->
<!-- <div class="cell-item">厂址</div>-->
<!-- </template>-->
<!-- <span>云南省昆明市呈贡区彩云南路100号</span>-->
<!-- </el-descriptions-item>-->
<!-- <el-descriptions-item>-->
<!-- <template #label>-->
<!-- <div class="cell-item">保质期</div>-->
<!-- </template>-->
<!-- <span>7</span>-->
<!-- </el-descriptions-item>-->
</el-descriptions>
</div>
<div style="display: flex; justify-content: center; flex-wrap: wrap">
<el-image
v-for="(item, index) in mockData[currentIndex].bigImages"
:key="currentIndex + '-' + index"
:src="getAssetsFile('images/mockPic/' + item)?.href ?? ''"
style="width: 80%"
fit="contain"
/>
<el-image v-for="(item, index) in currentGood.detailUrl" :key="index" :src="item" style="width: 80%" fit="contain" />
</div>
</div>
<div v-if="tabVal == 'sourceCode'" class="content-source-code">
@ -207,16 +135,18 @@
<script setup name="ecommerce">
import common from './components/common.vue';
import banner from './components/banner.vue';
import { onMounted, reactive, ref } from '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([
@ -228,146 +158,156 @@ const tabList = reactive([
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 mockData = [
{
titleName: '甜糯玉米种子',
goodName: '甜糯玉米种子',
sold: 1200,
price: 25,
soldAddress: '河南信阳',
right: '七天保价',
sendAddress: '河南信阳',
safeguard: '七天保价',
weight: ['100g', '200g'],
images: ['images/mockPic/cornTop.png'],
bigImages: ['cornBottom1.png', 'cornBottom2.png', 'cornBottom3.png', 'cornBottom4.png'],
goodUrl: ['images/mockPic/cornTop.png'],
detailUrl: ['cornBottom1.png', 'cornBottom2.png', 'cornBottom3.png', 'cornBottom4.png'],
},
{
titleName: '张塘王豇豆种子种籽',
goodName: '张塘王豇豆种子种籽',
sold: 1200,
price: 4.35,
soldAddress: '山东潍坊',
right: '七天保价',
sendAddress: '山东潍坊',
safeguard: '七天保价',
weight: ['100粒', '200粒'],
images: ['images/mockPic/beanTop.png'],
bigImages: ['beanBottom1.png', 'beanBottom2.png', 'beanBottom3.png', 'beanBottom4.png'],
goodUrl: ['images/mockPic/beanTop.png'],
detailUrl: ['beanBottom1.png', 'beanBottom2.png', 'beanBottom3.png', 'beanBottom4.png'],
},
{
titleName: '茄子种子种籽',
goodName: '茄子种子种籽',
sold: 1200,
price: 3.92,
soldAddress: '山东潍坊',
right: '七天保价',
sendAddress: '山东潍坊',
safeguard: '七天保价',
weight: ['100粒', '200粒'],
images: ['images/mockPic/eggplantTop.png'],
bigImages: ['eggplantBottom1.png', 'eggplantBottom2.png', 'eggplantBottom3.png', 'eggplantBottom4.png'],
goodUrl: ['images/mockPic/eggplantTop.png'],
detailUrl: ['eggplantBottom1.png', 'eggplantBottom2.png', 'eggplantBottom3.png', 'eggplantBottom4.png'],
},
{
titleName: '正宗绿贝贝南瓜种籽',
goodName: '正宗绿贝贝南瓜种籽',
sold: 1200,
price: 6.8,
soldAddress: '安徽马鞍山',
right: '七天保价',
sendAddress: '安徽马鞍山',
safeguard: '七天保价',
weight: ['10粒', '20粒'],
images: ['images/mockPic/pumpkinTop.png'],
bigImages: ['pumpkinBottom1.png', 'pumpkinBottom2.png', 'pumpkinBottom3.png', 'pumpkinBottom4.png'],
goodUrl: ['images/mockPic/pumpkinTop.png'],
detailUrl: ['pumpkinBottom1.png', 'pumpkinBottom2.png', 'pumpkinBottom3.png', 'pumpkinBottom4.png'],
},
{
titleName: '复合肥料18-5-7',
goodName: '复合肥料18-5-7',
sold: 1200,
price: 154,
soldAddress: '浙江金华',
right: '七天保价',
sendAddress: '浙江金华',
safeguard: '七天保价',
weight: ['25kg', '50kg'],
images: ['images/mockPic/fertilizerTop.png'],
bigImages: ['fertilizerBottom1.png', 'fertilizerBottom2.png'],
goodUrl: ['images/mockPic/fertilizerTop.png'],
detailUrl: ['fertilizerBottom1.png', 'fertilizerBottom2.png'],
},
{
titleName: '正宗硫酸钾 农用钾肥',
goodName: '正宗硫酸钾 农用钾肥',
sold: 1200,
price: 13.5,
soldAddress: '内蒙古',
right: '七天保价',
sendAddress: '内蒙古',
safeguard: '七天保价',
weight: ['5斤', '10斤'],
images: ['images/mockPic/KSO4Top.png'],
bigImages: ['KSO4Bottom1.png', 'KSO4Bottom2.png', 'KSO4Bottom3.png', 'KSO4Bottom4.png'],
goodUrl: ['images/mockPic/KSO4Top.png'],
detailUrl: ['KSO4Bottom1.png', 'KSO4Bottom2.png', 'KSO4Bottom3.png', 'KSO4Bottom4.png'],
},
{
titleName: '噻虫嗪农药',
goodName: '噻虫嗪农药',
sold: 1200,
price: 8.6,
soldAddress: '内蒙古',
right: '七天保价',
sendAddress: '内蒙古',
safeguard: '七天保价',
weight: ['500g'],
images: ['images/mockPic/pesticideTop.png'],
bigImages: ['pesticideBottom1.png', 'pesticideBottom2.png', 'pesticideBottom3.png', 'pesticideBottom4.png', 'pesticideBottom5.png'],
goodUrl: ['images/mockPic/pesticideTop.png'],
detailUrl: ['pesticideBottom1.png', 'pesticideBottom2.png', 'pesticideBottom3.png', 'pesticideBottom4.png', 'pesticideBottom5.png'],
},
{
titleName: '11.6%甲维氯笨氣虫苯甲铣胺酰胺笨甲先胺水稻钻心虫农药杀虫剂',
goodName: '11.6%甲维氯笨氣虫苯甲铣胺酰胺笨甲先胺水稻钻心虫农药杀虫剂',
sold: 1200,
price: 35.6,
soldAddress: '山东烟台',
right: '七天保价',
sendAddress: '山东烟台',
safeguard: '七天保价',
weight: ['500g', '1000g'],
images: ['images/mockPic/nyTop.png'],
bigImages: ['nyBottom1.png', 'nyBottom2.png', 'nyBottom3.png', 'nyBottom4.png'],
goodUrl: ['images/mockPic/nyTop.png'],
detailUrl: ['nyBottom1.png', 'nyBottom2.png', 'nyBottom3.png', 'nyBottom4.png'],
},
{
titleName: '铁皮石斛种子',
goodName: '铁皮石斛种子',
sold: 13,
price: '80/g',
soldAddress: '耿马县',
right: '七天保价',
sendAddress: '耿马县',
safeguard: '七天保价',
weight: ['1g', '2g', '5g', '10g'],
images: ['images/mockPic/shihuTop.png'],
bigImages: ['shihuBottom0.png', 'shihuBottom1.png', 'shihuBottom2.png', 'shihuBottom3.png'],
goodUrl: ['images/mockPic/shihuTop.png'],
detailUrl: ['shihuBottom0.png', 'shihuBottom1.png', 'shihuBottom2.png', 'shihuBottom3.png'],
},
{
titleName: '黑皮甘蔗苗',
goodName: '黑皮甘蔗苗',
sold: 1400,
price: '0.7/株',
soldAddress: '耿马县',
right: '七天保价',
sendAddress: '耿马县',
safeguard: '七天保价',
weight: ['10株', '50株', '200株', '500株'],
images: ['images/mockPic/ganzheTop.png'],
bigImages: ['ganzheBottom0.png', 'ganzheBottom1.png', 'ganzheBottom2.png', 'ganzheBottom3.png'],
goodUrl: ['images/mockPic/ganzheTop.png'],
detailUrl: ['ganzheBottom0.png', 'ganzheBottom1.png', 'ganzheBottom2.png', 'ganzheBottom3.png'],
},
{
titleName: '美人椒种子 -辣椒种子',
goodName: '美人椒种子 -辣椒种子',
sold: 548,
price: '43/斤',
soldAddress: '耿马县',
right: '七天保价',
sendAddress: '耿马县',
safeguard: '七天保价',
weight: ['1斤', '2斤'],
images: ['images/mockPic/chiliTop.png'],
bigImages: ['chiliBottom0.png', 'chiliBottom1.png', 'chiliBottom2.png', 'chiliBottom3.png'],
goodUrl: ['images/mockPic/chiliTop.png'],
detailUrl: ['chiliBottom0.png', 'chiliBottom1.png', 'chiliBottom2.png', 'chiliBottom3.png'],
},
{
titleName: '四季青种子',
goodName: '四季青种子',
sold: 548,
price: '19.5/包',
soldAddress: '耿马县',
right: '七天保价',
sendAddress: '耿马县',
safeguard: '七天保价',
weight: ['1包500-2000粒', '2包', '4包'],
images: ['images/mockPic/leafyTop.png'],
bigImages: ['leafyBottom0.png', 'leafyBottom1.png', 'leafyBottom2.png'],
goodUrl: ['images/mockPic/leafyTop.png'],
detailUrl: ['leafyBottom0.png', 'leafyBottom1.png', 'leafyBottom2.png'],
},
{
titleName: '青花菜种子',
goodName: '青花菜种子',
sold: 548,
price: '10/包',
soldAddress: '耿马县',
right: '七天保价',
sendAddress: '耿马县',
safeguard: '七天保价',
weight: ['1包300-800粒', '2包', '4包'],
images: ['images/mockPic/broccoliTop.png'],
bigImages: ['broccoliBottom2.png', 'broccoliBottom1.png', 'broccoliBottom0.png'],
goodUrl: ['images/mockPic/broccoliTop.png'],
detailUrl: ['broccoliBottom2.png', 'broccoliBottom1.png', 'broccoliBottom0.png'],
},
{
titleName: '黑叶小白菜种子',
goodName: '黑叶小白菜种子',
sold: 82,
price: '60/公斤',
soldAddress: '耿马县',
right: '七天保价',
sendAddress: '耿马县',
safeguard: '七天保价',
weight: ['1公斤', '2公斤', '5公斤'],
images: ['images/mockPic/choyTop.png'],
bigImages: ['choyBottom0.png', 'choyBottom1.png', 'choyBottom2.png', 'choyBottom3.png'],
goodUrl: ['images/mockPic/choyTop.png'],
detailUrl: ['choyBottom0.png', 'choyBottom1.png', 'choyBottom2.png', 'choyBottom3.png'],
},
];
@ -376,48 +316,73 @@ let tabVal = ref('detail');
let saveInfo = reactive({
num: 0,
});
onMounted(() => {
showDetail.value = false;
const num = Number(pId);
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) {
currentIndex.value = 8;
// const num = Number(pId);
getGoodDetail(goodId).then(async (res) => {
currentGood.value = res.data;
//
await formattedData(res.data);
showDetail.value = true;
} 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;
}
});
// 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.replace(/'/g, '"');
currentGood.value.detailUrl = JSON.parse(currentGood.value.detailUrl);
}
currentGood.value.goodUrls = data.goodUrl.split(',');
console.log(currentGood.value);
};
const toCodeDetail = () => {
let id = '01';
@ -651,6 +616,7 @@ const toCopy = () => {};
.content-detail {
.detail-des {
margin-bottom: 24px;
width: 80%;
}
}
.content-source-code {

View File

@ -2,7 +2,13 @@
<div class="ecommerce-banner" :style="{ height: height }">
<el-carousel height="height" motion-blur :indicator-position="indicatorPos" :arrow="arrow">
<el-carousel-item v-for="(item, index) in list" :key="index">
<costomImg :url="item" :preview-list="srcList" :is-view="isViewVal" style="height: 100%; object-fit: fill"></costomImg>
<costomImg
:url="item"
:is-montage="isMontage"
:preview-list="srcList"
:is-view="isViewVal"
style="height: 100%; object-fit: fill"
></costomImg>
</el-carousel-item>
</el-carousel>
</div>
@ -33,6 +39,10 @@ const props = defineProps({
type: Boolean,
default: false,
},
isMontage: {
type: Boolean,
default: true,
},
});
let nameVal = ref(props.name);
@ -40,9 +50,15 @@ let list = ref([]);
let srcList = computed(() => {
let _list = [];
if (props.isMontage) {
_list = props.imglist.map((m) => {
return getAssetsFile(m)?.href ?? '';
});
} else {
_list = props.imglist.map((m) => {
return m ? m : '';
});
}
return _list;
});

View File

@ -23,8 +23,8 @@ const props = defineProps({
const leftMenu = reactive([
{ name: 'agricultural', title: '农资交易', icon: 'menu2.png', path: '/sub-operation-service/ecommerce-agricultural' },
{ name: 'supplier', title: '供应商服务', icon: 'menu1.png', path: '/sub-operation-service/ecommerce-supplier' },
{ name: 'purchaser', title: '采购商服务', icon: 'menu3.png', path: '/sub-operation-service/ecommerce-purchaser' },
{ name: 'supplier', title: '农产品交易', icon: 'menu1.png', path: '/sub-operation-service/ecommerce-supplier' },
// { name: 'purchaser', title: '', icon: 'menu3.png', path: '/sub-operation-service/ecommerce-purchaser' },
// { name: 'land', title: '', icon: 'menu4.png', path: '/sub-operation-service/ecommerce-land' },
]);

View File

@ -34,120 +34,7 @@ import filtertop from './components/filtertop.vue';
import goodsItem from './components/goodsItem.vue';
import { ref, reactive, onMounted, watch, computed } from 'vue';
import { agriculturalList, transaction } from '@/apis/supplier.js';
let treeList = reactive([
// {
// id: '2',
// name: '',
// children: [
// {
// id: '201',
// parentId: '2',
// name: '',
// children: [
// { parentId: '201', id: '20101', name: '' },
// { parentId: '201', id: '20102', name: '' },
// { parentId: '201', id: '20103', name: '' },
// ],
// },
// {
// id: '202',
// name: '',
// parentId: '2',
// children: [
// { parentId: '202', id: '20201', name: '' },
// { parentId: '202', id: '20202', name: '' },
// { parentId: '202', id: '20203', name: '' },
// { parentId: '202', id: '20204', name: '' },
// ],
// },
// {
// id: '203',
// name: '/',
// parentId: '2',
// children: [
// { parentId: '203', id: '20301', name: '' },
// { parentId: '203', id: '20302', name: '' },
// { parentId: '203', id: '20303', name: '' },
// ],
// },
// ],
// },
// {
// id: '1',
// name: '',
// children: [
// {
// id: '101',
// parentId: '1',
// name: '',
// children: [
// {
// parentId: '101',
// id: '10101',
// name: '',
// children: [],
// },
// ],
// },
// {
// id: '102',
// name: '',
// parentId: '1',
// children: [
// {
// parentId: '102',
// id: '10201',
// name: '',
// children: [],
// },
// ],
// },
// {
// id: '103',
// name: '',
// parentId: '1',
// children: [
// {
// parentId: '103',
// id: '10301',
// name: '',
// children: [],
// },
// {
// parentId: '103',
// id: '10302',
// name: '',
// children: [],
// },
// {
// parentId: '103',
// id: '10303',
// name: '',
// children: [],
// },
// {
// parentId: '103',
// id: '10304',
// name: '',
// children: [],
// },
// {
// parentId: '103',
// id: '10305',
// name: '',
// children: [],
// },
// {
// parentId: '103',
// id: '10306',
// name: '',
// children: [],
// },
// ],
// },
// ],
// },
]);
let treeList = reactive([]);
let list = reactive([
// {
@ -165,20 +52,6 @@ let list = reactive([
// title: ' 500g ',
// goodPrice: '25',
// },
// {
// goodId: '1020101',
// parentId: '103',
// goodUrl: 'http://gov-cloud.oss-cn-chengdu.aliyuncs.com/backend/815bc561d19f46a08ef357bb3df4c0d8.jpeg',
// title: '',
// goodPrice: '16',
// },
// {
// goodId: '1020102',
// parentId: '103',
// goodUrl: 'http://gov-cloud.oss-cn-chengdu.aliyuncs.com/backend/8819aebd5ae74c88bf7426bbf089acbb.jpeg',
// title: '绿',
// goodPrice: '25',
// },
]);
let params = reactive({
current: 1,