一大波修改 #1

Merged
shenhong merged 6 commits from 一大波修改 into dev 2025-06-09 17:55:45 +08:00
150 changed files with 23228 additions and 763 deletions
Showing only changes of commit 1f6f4206dd - Show all commits

2
.gitignore vendored
View File

@ -12,6 +12,8 @@ dist
dist-ssr
.history
*.local
*.zip
*.rar
# Editor directories and files
.vscode/*

View File

@ -6,6 +6,7 @@ VITE_APP_SUB_OA = '//localhost:8090/sub-operation-admin/'
VITE_APP_SUB_GAS = '//localhost:8090/sub-government-affairs-service/'
VITE_APP_SUB_GAA = '//localhost:8090/sub-government-admin/'
VITE_APP_SUB_GSS = '//localhost:8090/sub-government-screen-service/'
VITE_APP_VIST_URL = 'http://localhost'
# 接口
VITE_APP_BASE_API = '/apis'
VITE_APP_BASE_URL = ''

View File

@ -12,4 +12,5 @@ VITE_APP_BASE_API = '/apis'
VITE_APP_BASE_URL = ''
VITE_APP_UPLOAD_API = '/uploadApis'
VITE_APP_UPLOAD_URL = ''
VITE_APP_VIST_URL = 'http://47.109.205.240'

View File

@ -12,3 +12,4 @@ VITE_APP_BASE_API = '/apis'
VITE_APP_BASE_URL = ''
VITE_APP_UPLOAD_API = '/uploadApis'
VITE_APP_UPLOAD_URL = ''
VITE_APP_VIST_URL = 'http://192.168.18.99'

2
main/.gitignore vendored
View File

@ -23,3 +23,5 @@ dist-ssr
*.njsproj
*.sln
*.sw?
*.zip
*.rar

View File

@ -1,6 +1,6 @@
import actions from './actions';
const { VITE_APP_SUB_OS, VITE_APP_SUB_OA, VITE_APP_SUB_ADMIN, VITE_APP_SUB_GAS, VITE_APP_SUB_GSS, VITE_APP_SUB_GSR } = import.meta.env;
const { VITE_APP_SUB_OS, VITE_APP_SUB_OA, VITE_APP_SUB_ADMIN, VITE_APP_SUB_GAS, VITE_APP_SUB_GSS, VITE_APP_SUB_GSR, VITE_APP_VIST_URL } = import.meta.env;
export const leftApps = [
{
@ -13,7 +13,7 @@ export const leftApps = [
{
name: 'sub-operation-admin',
entry: VITE_APP_SUB_OA,
activeRule: '/sub-operation-admin',
activeRule: `${VITE_APP_VIST_URL}:82/login`,
title: '管理后台',
icon: 'images/platform/icon-admin.png',
},
@ -44,7 +44,7 @@ export const rightApps = [
{
name: 'sub-government-admin',
entry: VITE_APP_SUB_GAS,
activeRule: '/sub-government-affairs-service',
activeRule: `${VITE_APP_VIST_URL}:81/login`,
title: '管理后台',
icon: 'images/platform/icon-admin.png',
},

View File

@ -7,6 +7,7 @@
VITE_APP_MIAN = 'daimp-front-main'
VITE_APP_MIAN_URL = 'http://47.109.205.240:88'
VITE_APP_NAME = 'new-digital-agriculture-screen'
VITE_APP_TITLE = '政务云数字农业智慧大屏'
# 接口
VITE_APP_BASE_API = '/apis'
VITE_APP_BASE_URL = ''

View File

@ -64,6 +64,8 @@ web_modules/
# Output of 'npm pack'
*.tgz
*.zip
*.rar
# Yarn Integrity file
.yarn-integrity

View File

@ -4,6 +4,7 @@ VITE_APP_MIAN = 'daimp-front-main'
VITE_APP_MIAN_URL = 'http://localhost:9000'
VITE_APP_NAME = 'sub-operation-service'
VITE_APP_BASE_API = '/apis'
VITE_APP_BASE_URL = 'http://192.168.18.99:88'
# VITE_APP_BASE_URL = 'http://192.168.18.99:88'
VITE_APP_BASE_URL = 'http://192.168.18.99:8080'
VITE_APP_UPLOAD_API = '/uploadApis'
VITE_APP_UPLOAD_URL = 'http://192.168.18.99:9300'

View File

@ -4,7 +4,7 @@ import request from '@/utils/axios';
//获取农资分类查询数据
export function transaction(params = {}) {
return request('goods/business/category/transactionType?type=1', {
return request('goods/goodInfoManage/transactionType?type=1', {
method: 'GET',
params,
});
@ -12,7 +12,15 @@ export function transaction(params = {}) {
//获取农资列表数据
export function agriculturalList(params) {
return request('goods/business/category/transactionGoodInfo', {
return request('goods/goodInfoManage/transactionGoodInfo?type=1', {
method: 'GET',
params,
});
}
// 获取商品详情接口
export function getGoodDetail(id, params) {
return request(`goods/goodInfoManage/getGoodInfo/${id}`, {
method: 'GET',
params,
});
@ -20,7 +28,7 @@ export function agriculturalList(params) {
// 获取用户评价列表
export function agriculturalContent(params) {
return request('goods/business/category/contentPage', {
return request('goods/goodInfoManage/contentPage', {
method: 'POST',
params,
});

View File

@ -1,5 +1,6 @@
// src/apis/brand.js
import axios from '@/utils/axios';
import request from '@/utils/axios.js';
export const getProducts = (params) => {
return axios.get('/api/brand/products', {
@ -19,3 +20,29 @@ export const getMonitorList = () => {
apisType: 'mock',
});
};
export function brandList(params) {
return request('brand/brandbase/page?status=1&auditStatus=2', {
method: 'GET',
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,
});
}

View File

@ -0,0 +1,19 @@
import request from '@/utils/axios';
//农资
//获取农资分类查询数据
export function transaction(params = {}) {
return request('goods/goodInfoManage/transactionType?type=2', {
method: 'GET',
params,
});
}
//获取农资列表数据
export function agriculturalList(params) {
return request('goods/goodInfoManage/transactionGoodInfo?type=2', {
method: 'GET',
params,
});
}

View File

@ -0,0 +1,106 @@
import request from '@/utils/axios';
//购物车列表
export function shoppingCart(params = {}) {
return request('user-center/shoppingCart/page', {
method: 'GET',
params,
});
}
//删除购物车
export function deleteChooseGoods(params = {}) {
return request('user-center/shoppingCart/deleteChooseGoods', {
method: 'GET',
params,
});
}
//商品添加数量
export function addToCart(params = {}) {
return request('user-center/shoppingCart/addToCart', {
method: 'GET',
params,
});
}
//商品减数量
export function delCartGood(params = {}) {
return request('user-center/shoppingCart/delCartGood', {
method: 'GET',
params,
});
}
//获取地址列表
export function userPostAddress(params = {}) {
return request('user-center/userPostAddress/page', {
method: 'GET',
params,
});
}
//修改购物车数量
export function setGoodsCount(params = {}) {
return request('user-center/shoppingCart/setGoodsCount', {
method: 'GET',
params,
});
}
//新增地址
export function addUserPostAddress(params = {}) {
return request('user-center/userPostAddress/add', {
method: 'POST',
data: params,
});
}
//删除地址
export function deleteAddress(params = {}) {
return request(`user-center/userPostAddress/delete/${params}`, {
method: 'DELETE',
});
}
//修改地址信息
export function userPostAddressed(params = {}) {
return request('user-center/userPostAddress/edit', {
method: 'PUT',
data: params,
});
}
//提交订单
export function commitOrder(params = {}) {
return request('user-center/shoppingCart/commitOrder', {
method: 'POST',
data: params,
});
}
//获取订单列表
export function upOrderInfoList(params = {}) {
return request('user-center/orderInfo/getById', {
method: 'GET',
params,
});
}
//确认订单
export function confirmOrder(params = {}) {
return request('user-center/orderInfo/confirmOrder', {
method: 'POST',
data: params,
});
}
//获取订单列表
export function orderInfo(params = {}) {
return request('/user-center/orderInfo/page', {
method: 'GET',
params,
});
}
//取消订单
export function cancelOrder(params = {}) {
return request(`/user-center/orderInfo/cancelOrder/${params.id}`, {
method: 'PUT',
// data: params,
});
}
//品牌列表
export function mainPage(params = {}) {
return request('/brand/applicationrecord/mainPage', {
method: 'GET',
params,
});
}

View File

@ -0,0 +1,39 @@
import request from '@/utils/axios';
// 获取仓储查询数据
export function warehouseList(params = {}) {
return request('logistics/logisticwarehouse/page?status=1', {
method: 'GET',
params,
});
}
// 获取仓储查询数据
export function logisticList(params = {}) {
return request('logistics/logisticlogistic/page?', {
method: 'GET',
params,
});
}
// 获取仓储详情
export function warehouseDetail(id, params = {}) {
return request(`logistics/logisticwarehouse/detail/${id}`, {
method: 'GET',
params,
});
}
// 获取物流详情
export function logisticDetail(id, params = {}) {
return request(`logistics/logisticlogistic/detail/${id}`, {
method: 'GET',
params,
});
}
// 获取仓储详情
export function getWarehouseInfo(data = {}) {
return request(`logistics/getwarehouseinfo/save`, {
method: 'POST',
data,
});
}

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 76 KiB

After

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.4 KiB

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 93 KiB

After

Width:  |  Height:  |  Size: 93 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 906 KiB

After

Width:  |  Height:  |  Size: 906 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 350 KiB

After

Width:  |  Height:  |  Size: 350 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 679 KiB

After

Width:  |  Height:  |  Size: 679 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 735 KiB

After

Width:  |  Height:  |  Size: 735 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 352 KiB

After

Width:  |  Height:  |  Size: 352 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 393 KiB

After

Width:  |  Height:  |  Size: 393 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 131 KiB

After

Width:  |  Height:  |  Size: 131 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 760 KiB

After

Width:  |  Height:  |  Size: 760 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 620 KiB

After

Width:  |  Height:  |  Size: 620 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 381 KiB

After

Width:  |  Height:  |  Size: 381 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 378 KiB

After

Width:  |  Height:  |  Size: 378 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 522 KiB

After

Width:  |  Height:  |  Size: 522 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 98 KiB

After

Width:  |  Height:  |  Size: 98 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 141 KiB

After

Width:  |  Height:  |  Size: 141 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 896 KiB

After

Width:  |  Height:  |  Size: 896 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 MiB

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 551 KiB

After

Width:  |  Height:  |  Size: 551 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 506 KiB

After

Width:  |  Height:  |  Size: 506 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 918 KiB

After

Width:  |  Height:  |  Size: 918 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 644 KiB

After

Width:  |  Height:  |  Size: 644 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1016 KiB

After

Width:  |  Height:  |  Size: 1016 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 580 KiB

After

Width:  |  Height:  |  Size: 580 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 186 KiB

After

Width:  |  Height:  |  Size: 186 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 195 KiB

After

Width:  |  Height:  |  Size: 195 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.1 KiB

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.4 KiB

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.5 KiB

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.1 KiB

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.8 KiB

After

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.3 KiB

After

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

After

Width:  |  Height:  |  Size: 39 KiB

View File

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

View File

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

View File

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

View File

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

View File

@ -3,7 +3,7 @@
<div class="layout-header">
<div class="layout-header-top">
<div class="layout-header-top-left">
<span class="welcome-msg">您好欢迎来到农业产业服务平台</span>
<span class="welcome-msg">您好欢迎来到农业产业运营平台</span>
<div class="left-link">
<div class="iconfont icon-bigScreen"></div>
<span>数据大屏</span>
@ -74,10 +74,10 @@ const router = useRouter();
const keyword = ref('');
const meuns = ref([
// {
// label: '',
// path: '/sub-operation-service/dashboard',
// },
{
label: '综合看板',
path: '/sub-operation-service/dashboard',
},
{
label: '智慧种植',
path: '/sub-operation-service/smartFarm',

View File

@ -49,6 +49,12 @@ export const constantRoutes = [
name: 'sureOrder',
meta: { title: '结算' },
},
{
path: '/sub-operation-service/addressList',
component: () => import('@/views/userCenter/addressList.vue'),
name: 'addressList',
meta: { title: '我的地址' },
},
{
path: '/sub-operation-service/orderSuccess',
component: () => import('@/views/userCenter/orderSuccess.vue'),
@ -67,6 +73,12 @@ export const constantRoutes = [
name: 'userOrders',
meta: { title: '我的订单' },
},
{
path: '/sub-operation-service/orderDetails',
component: () => import('@/views/userCenter/orderDetails.vue'),
name: 'orderDetails',
meta: { title: '订单详情' },
},
{
path: '/sub-operation-service/userLands',
component: () => import('@/views/userCenter/userLands.vue'),
@ -85,6 +97,12 @@ export const constantRoutes = [
name: 'myFinance',
meta: { title: '我的金融' },
},
{
path: '/sub-operation-service/myBrand',
component: () => import('@/views/userCenter/myBrand.vue'),
name: 'myBrand',
meta: { title: '我的品牌' },
},
],
},
@ -92,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: [
{
@ -101,11 +119,20 @@ export const constantRoutes = [
name: 'home',
meta: { title: '首页' },
},
],
},
{
path: '/sub-operation-service/dashboard',
component: () => import('@/views/dashboard/index.vue'),
component: Layout,
name: 'dashboard',
redirect: '/sub-operation-service/dashboard/home',
meta: { title: '综合看板' },
children: [
{
path: '/sub-operation-service/dashboard/home',
component: () => import('@/views/dashboard/breed/index.vue'),
name: 'dashboardHome',
meta: { title: '综合看板首页' },
},
],
},
@ -230,6 +257,12 @@ export const constantRoutes = [
name: 'packagingMain',
meta: { title: '包装首页' },
},
{
path: '/sub-operation-service/packaging/details',
component: () => import('@/views/packaging/details.vue'),
name: 'detailsMain',
meta: { title: '详情页' },
},
],
},
{
@ -245,12 +278,24 @@ export const constantRoutes = [
name: 'warehouseMain',
meta: { title: '仓储首页' },
},
{
path: '/sub-operation-service/warehouse-detail',
component: () => import('@/views/warehouseLogistics/warehouse/detail.vue'),
name: 'warehouse-detail',
meta: { title: '仓储详情' },
},
{
path: '/sub-operation-service/logistics',
component: () => import('@/views/warehouseLogistics/logistics/index.vue'),
name: 'logistics-list',
meta: { title: '物流首页' },
},
{
path: '/sub-operation-service/logistics-detail',
component: () => import('@/views/warehouseLogistics/logistics/detail.vue'),
name: 'logistics-detail',
meta: { title: '物流详情' },
},
],
},
{

View File

@ -0,0 +1,24 @@
import { defineStore } from 'pinia';
import { constantRoutes, notFoundRouter } from '@/router';
import { createAsyncRoutes, filterAsyncRoutes, filterKeepAlive } from '@/utils/router';
import { orderInfo } from '../../apis/user';
import { getTree } from '@/utils';
export const useGetUserOrder = defineStore('userOrder', {
state: () => ({
data: {},
}),
actions: {
//订单
getData(params) {
return Promise.resolve(
orderInfo(params).then((res) => {
console.log(res);
useGetUserOrder().$state.data = res.data;
return useGetUserOrder().$state.data;
})
);
},
},
getters: {},
});

View File

@ -1,7 +1,9 @@
<template>
<div class="container">
<el-breadcrumb separator="·">
<el-breadcrumb-item style="cursor: pointer" @click="backToList">使用申请</el-breadcrumb-item>
<el-breadcrumb-item style="cursor: pointer" @click="backToList"
><el-icon><ArrowLeftBold /></el-icon>使用申请</el-breadcrumb-item
>
<el-breadcrumb-item><a href="#">我要申请</a></el-breadcrumb-item>
</el-breadcrumb>
@ -9,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>
@ -50,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('');
@ -83,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('提交成功!');
}
});
}
</script>

View File

@ -3,9 +3,9 @@
<el-col v-for="product in products" :key="product.id" :span="6">
<el-card class="box-card" :body-style="{ padding: '8px', height: '100%' }">
<div class="flex-column">
<img :src="getAssetsFile(product.imageUrl)" alt="商品图" class="img" />
<img :src="getAssetsFile(product.imgPath)" alt="商品图" class="img" />
<div class="flex-1 flex-around">
<p>{{ product.name }}</p>
<p>{{ product.title }}</p>
<el-button type="success" class="button" @click="gotoApplication(product.id)">我要申请</el-button>
</div>
</div>
@ -16,9 +16,10 @@
<script setup>
import { ref, onMounted } from 'vue';
import { getApplyList } from '@/apis/brand';
import { getApplyList, brandList } from '@/apis/brand';
import { getAssetsFile } from '@/utils/index.js';
import { useRouter } from 'vue-router';
import { ElMessage } from 'element-plus';
const router = useRouter();
const products = ref([]);
@ -29,18 +30,12 @@ const products = ref([]);
// });
const applyData = [
{ id: 1, name: '耿马绿色蔬菜', imageUrl: 'images/brand/11.png' },
{ id: 2, name: '云南高山茶', imageUrl: 'images/brand/12.png' },
{ id: 3, name: '新疆大枣', imageUrl: 'images/brand/13.png' },
{ id: 4, name: '东北大米', imageUrl: 'images/brand/14.png' },
{ id: 5, name: '山东苹果', imageUrl: 'images/brand/15.png' },
{ id: 6, name: '四川泡菜', imageUrl: 'images/brand/16.png' },
{ id: 7, name: '江苏阳澄湖大闸蟹', imageUrl: 'images/brand/11.png' },
{ id: 8, name: '海南椰子', imageUrl: 'images/brand/12.png' },
{ id: 9, name: '广东早茶', imageUrl: 'images/brand/13.png' },
{ id: 10, name: '北京烤鸭', imageUrl: 'images/brand/14.png' },
{ id: 11, name: '西藏青稞酒', imageUrl: 'images/brand/15.png' },
{ id: 12, name: '青海牦牛肉', imageUrl: 'images/brand/16.png' },
{ id: 1, title: '耿马绿色蔬菜', imgPath: 'images/brand/11.png' },
{ id: 2, title: '耿马云斛石斛', imgPath: 'images/brand/12.png' },
{ id: 3, title: '耿马蒸酶茶', imgPath: 'images/brand/15.png' },
{ id: 4, title: '孟定蔬菜', imgPath: 'images/brand/14.png' },
{ id: 5, title: '耿马芒抗金丝凤梨', imgPath: 'images/brand/16.png' },
// { id: 6, name: '', imgPath: 'images/brand/16.png' },
];
function gotoApplication(id) {
@ -52,9 +47,20 @@ function data() {
products.value = applyData;
}
function getApplyData() {
brandList().then((res) => {
console.log(res);
if (res.code === 200) {
products.value = res.data.records;
} else {
ElMessage.error(res.errmsg);
}
});
}
//
onMounted(() => {
// getApplyList;
// getApplyData();
data();
});
</script>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

Some files were not shown because too many files have changed in this diff Show More