Compare commits
2 Commits
adaf7c1110
...
6cebfdf962
Author | SHA1 | Date | |
---|---|---|---|
6cebfdf962 | |||
487c07c85c |
@ -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', {
|
||||
|
@ -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,
|
||||
});
|
||||
}
|
||||
|
BIN
sub-operation-service/src/assets/images/inputs/1.png
Normal file
After Width: | Height: | Size: 4.2 KiB |
BIN
sub-operation-service/src/assets/images/inputs/2.png
Normal file
After Width: | Height: | Size: 4.2 KiB |
BIN
sub-operation-service/src/assets/images/inputs/3.png
Normal file
After Width: | Height: | Size: 4.0 KiB |
BIN
sub-operation-service/src/assets/images/inputs/4.png
Normal file
After Width: | Height: | Size: 3.9 KiB |
BIN
sub-operation-service/src/assets/images/inputs/5.png
Normal file
After Width: | Height: | Size: 4.0 KiB |
BIN
sub-operation-service/src/assets/images/inputs/6.png
Normal file
After Width: | Height: | Size: 4.3 KiB |
BIN
sub-operation-service/src/assets/images/inputs/bg_label.png
Normal file
After Width: | Height: | Size: 4.4 KiB |
BIN
sub-operation-service/src/assets/images/inputs/bg_title.png
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
sub-operation-service/src/assets/images/inputs/bg_value.png
Normal file
After Width: | Height: | Size: 38 KiB |
BIN
sub-operation-service/src/assets/images/inputs/order.webp
Normal file
After Width: | Height: | Size: 34 KiB |
BIN
sub-operation-service/src/assets/images/inputs/order2x.webp
Normal file
After Width: | Height: | Size: 93 KiB |
@ -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,
|
||||
|
@ -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';
|
||||
|
@ -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: [],
|
||||
},
|
||||
|
@ -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,
|
||||
() => {
|
||||
|
@ -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',
|
||||
|
@ -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: Layout,
|
||||
name: 'dashboard',
|
||||
redirect: '/sub-operation-service/dashboard/home',
|
||||
meta: { title: '综合看板' },
|
||||
children: [
|
||||
{
|
||||
path: '/sub-operation-service/dashboard',
|
||||
component: () => import('@/views/dashboard/index.vue'),
|
||||
name: 'dashboard',
|
||||
meta: { title: '综合看板' },
|
||||
path: '/sub-operation-service/dashboard/home',
|
||||
component: () => import('@/views/dashboard/breed/index.vue'),
|
||||
name: 'dashboardHome',
|
||||
meta: { title: '综合看板首页' },
|
||||
},
|
||||
],
|
||||
},
|
||||
|
@ -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,14 +99,23 @@ 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('提交成功!');
|
||||
}
|
||||
});
|
||||
ElMessage.success('提交成功!');
|
||||
}
|
||||
</script>
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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>
|
@ -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);
|
||||
}
|
||||
|
||||
// 准备待返回的配置项,把准备好的 legendData、series 传入。
|
||||
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>
|
@ -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);
|
||||
}
|
||||
|
||||
// 准备待返回的配置项,把准备好的 legendData、series 传入。
|
||||
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>
|
@ -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>
|
@ -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>
|
@ -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>
|
@ -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>
|
@ -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>
|
@ -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>
|
@ -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>
|
@ -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>
|
@ -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>
|
@ -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>
|
@ -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>
|
@ -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>
|
200
sub-operation-service/src/views/dashboard/breed/index.vue
Normal 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">仓储总面积(m²)</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>
|
@ -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>
|
@ -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> -->
|
@ -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">保 障:{{ mockData[currentIndex].right }}</el-col>
|
||||
<el-col :span="24">发货地址:{{ currentGood.detailAddress }}</el-col>
|
||||
<el-col :span="24"
|
||||
>保 障:{{
|
||||
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>50g、100g、250g、500g</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,49 +316,74 @@ 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';
|
||||
router.push('/sub-operation-service/ecommerce-sourceCodeDetail?id=' + id);
|
||||
@ -651,6 +616,7 @@ const toCopy = () => {};
|
||||
.content-detail {
|
||||
.detail-des {
|
||||
margin-bottom: 24px;
|
||||
width: 80%;
|
||||
}
|
||||
}
|
||||
.content-source-code {
|
||||
|
@ -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 = [];
|
||||
_list = props.imglist.map((m) => {
|
||||
return getAssetsFile(m)?.href ?? '';
|
||||
});
|
||||
if (props.isMontage) {
|
||||
_list = props.imglist.map((m) => {
|
||||
return getAssetsFile(m)?.href ?? '';
|
||||
});
|
||||
} else {
|
||||
_list = props.imglist.map((m) => {
|
||||
return m ? m : '';
|
||||
});
|
||||
}
|
||||
return _list;
|
||||
});
|
||||
|
||||
|
@ -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' },
|
||||
]);
|
||||
|
||||
|
@ -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,
|
||||
|