Compare commits

..

3 Commits

Author SHA1 Message Date
2090205686@qq.com
bea334086a 产出品管理页面调整(未完);小模块title和顶部菜单样式调整全局样式; 2025-05-14 17:28:42 +08:00
2090205686@qq.com
3330fed4e9 新版大屏调整,首页完,产出品管理未完 2025-05-12 23:39:08 +08:00
2090205686@qq.com
7c135ca70b 初始化项目配置 2025-05-12 11:28:09 +08:00
30 changed files with 23740 additions and 7095 deletions

View File

@ -1,19 +1,6 @@
# 开发环境 # 开发环境
# VITE_PORT = 9530 VITE_PORT = 9000
# VITE_APP_NAME = 'new-digital-agriculture-screen' VITE_APP_NAME = 'digital-agriculture-screen'
# VITE_APP_TITLE = '政务云数字农业智慧大屏'
# VITE_APP_BASE_API = '/apis'
# VITE_APP_BASE_URL = 'http://192.168.18.99:8080'
# 开发环境
VITE_PORT = 9530
VITE_MODE = 'DEV'
VITE_APP_TITLE = '政务云数字农业智慧大屏' VITE_APP_TITLE = '政务云数字农业智慧大屏'
VITE_APP_MIAN = 'daimp-front-main'
VITE_APP_MIAN_URL = 'http://localhost:9530'
VITE_APP_NAME = 'new-digital-agriculture-screen'
VITE_APP_BASE_API = '/apis' VITE_APP_BASE_API = '/apis'
VITE_APP_BASE_URL = 'http://192.168.18.99:8080' 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

@ -1,14 +1,5 @@
# 生产环境 # 生产环境
# VITE_APP_NAME = 'new-digital-agriculture-screen' VITE_APP_NAME = 'digital-agriculture-screen'
# VITE_APP_TITLE = '政务云数字农业智慧大屏' VITE_APP_TITLE = '政务云数字农业智慧大屏'
# VITE_APP_BASE_API = '/apis'
# VITE_APP_BASE_URL = ''
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_BASE_API = '/apis' VITE_APP_BASE_API = '/apis'
VITE_APP_BASE_URL = '' VITE_APP_BASE_URL = ''
VITE_APP_UPLOAD_API = '/uploadApis'
VITE_APP_UPLOAD_URL = ''

5
.env.test Normal file
View File

@ -0,0 +1,5 @@
# 测试环境
VITE_APP_NAME = 'digital-agriculture-screen'
VITE_APP_TITLE = '政务云数字农业智慧大屏'
VITE_APP_BASE_API = '/apis'
VITE_APP_BASE_URL = ''

2
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,2 @@
{
}

1
.yarnrc.yml Normal file
View File

@ -0,0 +1 @@
nodeLinker: node-modules

13213
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -17,6 +17,8 @@
"dependencies": { "dependencies": {
"@element-plus/icons-vue": "^2.3.1", "@element-plus/icons-vue": "^2.3.1",
"@smallwei/avue": "^3.6.2", "@smallwei/avue": "^3.6.2",
"@vuemap/vue-amap": "^2.0",
"@vuemap/vue-amap-loca": "^2.0",
"@wangeditor/editor": "^5.1.23", "@wangeditor/editor": "^5.1.23",
"@wangeditor/editor-for-vue": "^5.1.12", "@wangeditor/editor-for-vue": "^5.1.12",
"animate.css": "^4.1.1", "animate.css": "^4.1.1",
@ -25,8 +27,6 @@
"echarts-gl": "^2.0.9", "echarts-gl": "^2.0.9",
"echarts-liquidfill": "^3.1.0", "echarts-liquidfill": "^3.1.0",
"echarts-wordcloud": "^2.1.0", "echarts-wordcloud": "^2.1.0",
"@vuemap/vue-amap": "^2.0",
"@vuemap/vue-amap-loca": "^2.0",
"element-plus": "^2.7.2", "element-plus": "^2.7.2",
"js-base64": "^3.7.6", "js-base64": "^3.7.6",
"lodash": "^4.17.21", "lodash": "^4.17.21",

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

View File

@ -36,10 +36,10 @@ export default {
const { setOptions, getInstance, resize, startAutoPlay } = useEcharts(chartRef); const { setOptions, getInstance, resize, startAutoPlay } = useEcharts(chartRef);
const option = reactive({ const option = reactive({
tooltip: { tooltip: {
// trigger: 'axis', trigger: 'axis',
// axisPointer: { axisPointer: {
// type: 'shadow', type: 'shadow',
// }, },
backgroundColor: 'rgba(18, 55, 85, 0.8);', backgroundColor: 'rgba(18, 55, 85, 0.8);',
borderColor: '#35d0c0', borderColor: '#35d0c0',
formatter: (data) => { formatter: (data) => {
@ -62,7 +62,7 @@ export default {
gap: 0, gap: 0,
label: { label: {
show: true, show: true,
position: 'right', position: 'outside',
width: '200px', width: '200px',
align: 'right', align: 'right',
formatter: function (params) { formatter: function (params) {
@ -74,9 +74,29 @@ export default {
a: { color: '#fff', fontSize: '16px' }, a: { color: '#fff', fontSize: '16px' },
b: { color: '#05FCC6', fontSize: '16px' }, b: { color: '#05FCC6', fontSize: '16px' },
}, },
verticalAlign: 'middle',
padding: [5, 10], //
}, },
labelLine: { labelLine: {
show: false, show: true,
length: 20,
length2: 30,
smooth: true,
lineStyle: {
width: 2,
color: '#ffffff',
opacity: 1,
type: 'solid',
},
// 线
// idx-, params-
// formatter: function (idx, params) {
// return [
// [params.labelRect.x, params.labelRect.y], //
// [params.labelRect.x + 20, params.labelRect.y], // 线
// [params.labelRect.x + 20, params.dataCoord[1]] // 线
// ];
// },
}, },
itemStyle: { itemStyle: {
show: false, show: false,

View File

@ -54,14 +54,14 @@ const props = defineProps({
type: Array, type: Array,
default() { default() {
return [ return [
{ label: '首页', value: '/new-digital-agriculture-screen/v2/home' }, { label: '首页', value: '/v2/home' },
{ label: '土地资源', value: '/new-digital-agriculture-screen/v2/land' }, { label: '土地资源', value: '/v2/land' },
{ label: '投入品监管', value: '/new-digital-agriculture-screen/v2/inputs' }, { label: '投入品监管', value: '/v2/inputs' },
{ label: '产出品管理', value: '/new-digital-agriculture-screen/v2/entities' }, { label: '产出品管理', value: '/v2/entities' },
// { label: '', value: 'plant' }, // { label: '', value: 'plant' },
// { label: '', value: 'breed' }, // { label: '', value: 'breed' },
{ label: '生产经营主体', value: '/new-digital-agriculture-screen/v2/business' }, { label: '生产经营主体', value: '/v2/business' },
{ label: '农产品溯源', value: '/new-digital-agriculture-screen/v2/trace' }, { label: '农产品溯源', value: '/v2/trace' },
// { label: '', value: 'early' }, // { label: '', value: 'early' },
]; ];
}, },
@ -69,7 +69,7 @@ const props = defineProps({
}); });
const titleContentW = ref('0'); const titleContentW = ref('0');
const itemW = ref('1'); const itemW = ref('1');
const gap = ref(24); const gap = ref(1);
const leftNum = ref(0); const leftNum = ref(0);
const position = ref(0); const position = ref(0);
const right = ref(null); const right = ref(null);
@ -133,7 +133,7 @@ function handleTitleClick(val) {
.header_title { .header_title {
background-color: #000; background-color: #000;
position: relative; position: relative;
padding: 0 68px; padding: 0 40px;
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
width: 100vw; width: 100vw;
@ -174,7 +174,7 @@ function handleTitleClick(val) {
.left_titles_container, .left_titles_container,
.right_titles_container { .right_titles_container {
position: relative; position: relative;
width: 30%; width: 31%;
height: 100%; height: 100%;
overflow: hidden; overflow: hidden;
line-height: 90px; line-height: 90px;
@ -182,10 +182,10 @@ function handleTitleClick(val) {
position: absolute; position: absolute;
top: 10px; top: 10px;
width: var(--titleContentW); width: var(--titleContentW);
height: 40px; height: 56px;
transition: all 0.4s ease; transition: all 0.4s ease;
font-size: 20px; font-size: 24px;
font-weight: bold; // font-weight: bold;
.active { .active {
color: #fff; color: #fff;
opacity: 1 !important; opacity: 1 !important;
@ -194,9 +194,9 @@ function handleTitleClick(val) {
.title_item { .title_item {
margin-right: var(--gap); margin-right: var(--gap);
display: inline-block; display: inline-block;
width: var(--itemW); min-width: var(--itemW);
height: 40px; height: 56px;
line-height: 40px; line-height: 56px;
text-align: center; text-align: center;
color: #f5fffe; color: #f5fffe;
cursor: pointer; cursor: pointer;

View File

@ -9,7 +9,7 @@
></div> ></div>
<span class="title-top-content" :style="{ 'text-align': props.left }">{{ topTitle || '--' }}</span> <span class="title-top-content" :style="{ 'text-align': props.left }">{{ topTitle || '--' }}</span>
<div v-if="isDown" class="down-list" :style="{ width: downWidth }"> <div v-if="isDown" class="down-list" :style="{ width: downWidth }">
<el-dropdown :hide-on-click="true" :style="{ width: '90%' }" trigger="click" @command="handleCommand"> <el-dropdown :hide-on-click="true" trigger="click" @command="handleCommand">
<span class="el-dropdown-link"> <span class="el-dropdown-link">
{{ currentVal && currentVal[labelField] ? currentVal[labelField] : downTitle }}<el-icon class="el-icon--right"><arrow-down /></el-icon> {{ currentVal && currentVal[labelField] ? currentVal[labelField] : downTitle }}<el-icon class="el-icon--right"><arrow-down /></el-icon>
</span> </span>
@ -147,8 +147,8 @@ const handleCommand = (data) => {
} }
.title-top-content { .title-top-content {
line-height: 38px; line-height: 38px;
font-size: 14px; font-size: 20px;
font-weight: bold; // font-weight: bold;
display: inline-block; display: inline-block;
transform: skewX(-13deg); transform: skewX(-13deg);
background: linear-gradient(to bottom, '#ff7e5f', '#548fff'); background: linear-gradient(to bottom, '#ff7e5f', '#548fff');
@ -167,7 +167,7 @@ const handleCommand = (data) => {
.down-list { .down-list {
display: inline-block; display: inline-block;
position: absolute; position: absolute;
right: 32px; right: 0;
top: 50%; top: 50%;
transform: translateY(-50%); transform: translateY(-50%);
z-index: 2; z-index: 2;
@ -178,6 +178,8 @@ const handleCommand = (data) => {
border: 1px solid $color-custom-main; border: 1px solid $color-custom-main;
padding: 6px; padding: 6px;
border-radius: 4px; border-radius: 4px;
padding-left: 10px;
padding-right: 10px;
} }
} }
} }

View File

@ -74,6 +74,7 @@ onMounted(() => {
} }
.base-laytout-header { .base-laytout-header {
height: 90px; height: 90px;
margin-bottom: 50px;
} }
} }
</style> </style>

View File

@ -1,10 +1,3 @@
/**
* @Description:
* @Author: zenghua.wang
* @Date: 2024-01-24 17:14:41
* @LastEditors: zenghua.wang
* @LastEditTime: 2024-03-22 10:11:34
*/
import 'virtual:svg-icons-register'; import 'virtual:svg-icons-register';
import { createApp, nextTick } from 'vue'; import { createApp, nextTick } from 'vue';
import App from './App.vue'; import App from './App.vue';
@ -12,23 +5,30 @@ import router from './router';
import pinia from './store'; import pinia from './store';
import ElementPlus from 'element-plus'; import ElementPlus from 'element-plus';
import 'element-plus/dist/index.css'; import 'element-plus/dist/index.css';
import Avue from '@smallwei/avue'; import 'animate.css';
import '@smallwei/avue/lib/index.css';
import './utils/permission'; import './utils/permission';
import VueAMap, { initAMapApiLoader } from '@vuemap/vue-amap';
import { registerDirective } from './directives'; import { registerDirective } from './directives';
import { registerGlobalComponents } from './plugins/globalComponents';
import { registerElIcons } from './plugins/icon'; import { registerElIcons } from './plugins/icon';
import { registerMicroApps } from './plugins/micro'; import VueAMap, { initAMapApiLoader } from '@vuemap/vue-amap';
import '@vuemap/vue-amap/dist/style.css';
// 初始化高德地图 API
initAMapApiLoader({
key: 'c843a50db7157faf295c6fa37c48719f',
securityJsCode: 'f09302d3ed65110614bdb26e44717ddf', // 新版key需要配合安全密钥使用
version: '2.0',
Loca: {
version: '2.0',
},
AMapUI: {
plugins: ['misc/PathSimplifier'],
},
plugins: ['AMap.MapType'],
});
const app = createApp(App); const app = createApp(App);
// 注册 Vue3 Scroll Seamless 组件
// app.component('Vue3ScrollSeamless', vue3ScrollSeamless);
// app.use(pinia).use(router).use(ElementPlus).use(Avue);
app.use(pinia).use(router).use(ElementPlus).use(Avue).use(VueAMap);
nextTick(() => { nextTick(() => {
registerGlobalComponents(app);
registerElIcons(app); registerElIcons(app);
registerDirective(app); registerDirective(app);
registerMicroApps(app);
}); });
app.use(pinia).use(router).use(ElementPlus).use(VueAMap).mount('#app');

View File

@ -1,8 +0,0 @@
import * as components from '../../../main/src/components';
// 全局注册组件
export const registerGlobalComponents = (app) => {
Object.keys(components).forEach((key) => {
app.component(key, components[key]);
});
};

View File

@ -1,26 +0,0 @@
import { renderWithQiankun, qiankunWindow } from 'vite-plugin-qiankun/dist/helper';
export const registerMicroApps = async (app) => {
const initQiankun = () => {
renderWithQiankun({
bootstrap() {
console.log('bootstrap');
},
mount(props) {
console.log('mount', props);
render(props);
},
update(props) {
console.log('update', props);
},
unmount(props) {
console.log('unmount', props);
},
});
};
const render = async ({ container }) => {
await new Promise((resolve) => setTimeout(resolve, 1000));
app.mount(container ? container.querySelector('#app') : '#app');
};
qiankunWindow.__POWERED_BY_QIANKUN__ ? initQiankun() : render({});
};

View File

@ -1,7 +0,0 @@
import { Splitpanes, Pane } from 'splitpanes';
import 'splitpanes/dist/splitpanes.css';
export const registerSplitpanes = (app) => {
app.component('Splitpanes', Splitpanes);
app.component('Pane', Pane);
};

View File

@ -11,26 +11,18 @@ export const constantRoutes = [
// component: () => import('@/views/error/404.vue'), // component: () => import('@/views/error/404.vue'),
// hidden: true, // hidden: true,
// }, // },
// {
// path: '/403',
// name: '403',
// component: () => import('@/views/error/403.vue'),
// hidden: true,
// },
{ {
path: '/new-digital-agriculture-screen/403', path: '/',
name: '403',
component: () => import('@/views/error/403.vue'),
hidden: true,
},
{
path: '/new-digital-agriculture-screen',
name: 'layout', name: 'layout',
component: Layout, component: Layout,
redirect: '/new-digital-agriculture-screen/v2/home', redirect: '/v2/land',
meta: { title: '首页', icon: 'House' }, meta: { title: '首页', icon: 'House' },
children: [
{
path: '/new-digital-agriculture-screen/v2/home',
component: () => import('@/views/home/index.vue'),
name: 'home',
meta: { title: '首页', icon: '' },
},
],
}, },
// ...demoRouters, // ...demoRouters,
v2, v2,
@ -46,9 +38,9 @@ export const constantRoutes = [
* @Title notFoundRouter(找不到路由) * @Title notFoundRouter(找不到路由)
*/ */
export const notFoundRouter = { export const notFoundRouter = {
path: '/new-digital-agriculture-screen/:pathMatch(.*)', path: '/:pathMatch(.*)',
name: 'notFound', name: 'notFound',
redirect: '/new-digital-agriculture-screen/404', redirect: '/404',
}; };
const router = createRouter({ const router = createRouter({

View File

@ -2,20 +2,20 @@ import Layout from '@/layouts/index.vue';
export default [ export default [
{ {
path: '/new-digital-agriculture-screen/demo', path: '/demo',
name: 'demo', name: 'demo',
component: Layout, component: Layout,
redirect: '/new-digital-agriculture-screen/scrollBoard', redirect: '/scrollBoard',
meta: { title: '案例', icon: 'document' }, meta: { title: '案例', icon: 'document' },
children: [ children: [
{ {
path: '/new-digital-agriculture-screen/demo/scrollBoard', path: '/demo/scrollBoard',
name: 'scrollBoard', name: 'scrollBoard',
component: () => import('@/views/demo/scrollBoard.vue'), component: () => import('@/views/demo/scrollBoard.vue'),
meta: { title: '轮播列表', icon: 'document' }, meta: { title: '轮播列表', icon: 'document' },
}, },
{ {
path: '/new-digital-agriculture-screen/demo/rank', path: '/demo/rank',
name: 'rank', name: 'rank',
component: () => import('@/views/demo/rank.vue'), component: () => import('@/views/demo/rank.vue'),
meta: { title: '滚动排名列表', icon: 'document' }, meta: { title: '滚动排名列表', icon: 'document' },

View File

@ -1,32 +1,32 @@
import Layout from '@/layouts/index.vue'; import Layout from '@/layouts/index.vue';
export default { export default {
path: '/new-digital-agriculture-screen', path: '/v2',
name: 'layout', name: 'v2',
component: Layout, component: Layout,
redirect: '/new-digital-agriculture-screen/v2/home', redirect: '/v2/home',
meta: { title: '首页', icon: '' }, meta: { title: '首页', icon: '' },
children: [ children: [
{ {
path: '/new-digital-agriculture-screen/v2/home', path: '/v2/home',
component: () => import('@/views/home/index.vue'), component: () => import('@/views/home/index.vue'),
name: 'home', name: 'home',
meta: { title: '首页', icon: '' }, meta: { title: '首页', icon: '' },
}, },
{ {
path: '/new-digital-agriculture-screen/v2/land', path: '/v2/land',
component: () => import('@/views/land/index.vue'), component: () => import('@/views/land/index.vue'),
name: 'land', name: 'land',
meta: { title: '土地资源', icon: '' }, meta: { title: '土地资源', icon: '' },
}, },
{ {
path: '/new-digital-agriculture-screen/v2/inputs', path: '/v2/inputs',
name: 'inputs', name: 'inputs',
component: () => import('@/views/inputs/index.vue'), component: () => import('@/views/inputs/index.vue'),
meta: { title: '投入品监管', icon: '' }, meta: { title: '投入品监管', icon: '' },
}, },
{ {
path: '/new-digital-agriculture-screen/v2/entities', path: '/v2/entities',
name: 'entities', name: 'entities',
component: () => import('@/views/entities/index.vue'), component: () => import('@/views/entities/index.vue'),
meta: { title: '产出品管理', icon: '' }, meta: { title: '产出品管理', icon: '' },
@ -44,13 +44,13 @@ export default {
// meta: { title: '', icon: '' }, // meta: { title: '', icon: '' },
// }, // },
{ {
path: '/new-digital-agriculture-screen/v2/business', path: '/v2/business',
name: 'business', name: 'business',
component: () => import('@/views/business/index.vue'), component: () => import('@/views/business/index.vue'),
meta: { title: '生产经营主体', icon: '' }, meta: { title: '生产经营主体', icon: '' },
}, },
{ {
path: '/new-digital-agriculture-screen/trace', path: 'trace',
name: 'trace', name: 'trace',
component: () => import('@/views/trace/index.vue'), component: () => import('@/views/trace/index.vue'),
meta: { title: '农产品溯源', icon: '' }, meta: { title: '农产品溯源', icon: '' },

View File

@ -35,11 +35,6 @@ router.beforeEach(async (to, from, next) => {
accessRoutes.forEach((item) => router.addRoute(item)); accessRoutes.forEach((item) => router.addRoute(item));
return next({ ...to, replace: true }); return next({ ...to, replace: true });
} else { } else {
if (from.path.includes('/new') && to.path.includes('/platform')) {
window.location.reload();
return;
}
next();
next(); next();
} }
} catch (error) { } catch (error) {

View File

@ -145,6 +145,7 @@ function handleChange(n) {
top: 8px; top: 8px;
width: 24px; width: 24px;
height: 24px; height: 24px;
text-shadow: 2px 0px 10px 0px #01eeff;
} }
.left_btn { .left_btn {
left: 6px; left: 6px;

View File

@ -1,39 +1,60 @@
<template> <template>
<customEchartHyalineCake :chart-data="data" height="100%" :option="option" /> <customEchartHyalineCake ref="chartRef" :chart-data="data" height="100%" :option="option" />
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { reactive, ref } from 'vue'; import { reactive, ref, onMounted } from 'vue';
const chartRef = ref(null);
/* --------------- data --------------- */ /* --------------- data右上侧饼图 --------------- */
// #region // #region
const data = ref([ const data = ref([
{ {
name: ' 企业', name: ' 企业',
value: 10.8, value: 10.8,
itemStyle: { color: '#3c5fc4', opacity: 0.8 },
}, },
{ {
name: ' 合作社', name: ' 合作社',
value: 8.4, value: 18.4,
itemStyle: { color: '#8fd8ff', opacity: 0.8 },
}, },
{ {
name: ' 村集体', name: ' 村集体',
value: 4.3, value: 14.3,
itemStyle: { color: '#55d9a4', opacity: 0.8 },
}, },
{ {
name: ' 个体', name: ' 个体',
value: 3.7, value: 23.7,
itemStyle: { color: '#d2a823', opacity: 0.8 },
}, },
]); ]);
let itemGapWith = ref(0);
const getChartrefWith = () => {
let len = data.value.length * 2;
return chartRef.value.$refs.chartRef.offsetWidth / len + 8;
};
const option = reactive({ const option = reactive({
k: 0.2, k: 0.2,
opacity: 0.6, opacity: 0.4,
itemGap: 0, itemGap: 0,
autoItemHeight: 3, autoItemHeight: 3,
legend: { legend: {
type: 'plain',
orient: 'horizontal', orient: 'horizontal',
width: '100%',
bottom: 10, bottom: 10,
left: 'center', left: 'center',
itemWidth: 16,
itemHeight: 16,
itemGap: itemGapWith.value ? itemGapWith.value : 50,
textStyle: {
color: '#fff',
fontSize: '16px',
},
}, },
title: { title: {
text: '23亿元', text: '23亿元',
@ -47,18 +68,18 @@ const option = reactive({
color: '#02FD94', color: '#02FD94',
fontSize: '18px', fontSize: '18px',
}, },
top: 'center', top: '26%',
left: 'center', left: 'center',
}, },
grid3D: { grid3D: {
show: false, show: false,
boxHeight: 5, boxHeight: 3,
top: 'center', top: '-15%', //0
left: 'center', left: 'center',
viewControl: { viewControl: {
//3d //3d
alpha: 30, //( ) alpha: 36, //( )
distance: 160, //zoom() distance: 130, //zoom()
rotateSensitivity: 10, //0 rotateSensitivity: 10, //0
zoomSensitivity: 10, //0 zoomSensitivity: 10, //0
panSensitivity: 10, //0 panSensitivity: 10, //0
@ -73,6 +94,10 @@ const option = reactive({
// #region // #region
// #endregion // #endregion
onMounted(() => {
itemGapWith.value = getChartrefWith();
option.legend.itemGap = itemGapWith.value ? itemGapWith.value : 50;
});
</script> </script>
<style lang="scss" scoped></style> <style lang="scss" scoped></style>

View File

@ -1,34 +1,21 @@
<template> <template>
<custom-echart-line :chart-data="dataList" height="100%" :option="state.option" /> <custom-echart-line :chart-data="state.data" height="100%" :option="state.option" />
</template> </template>
<script setup> <script setup>
import { reactive } from 'vue'; import { reactive, watch } from 'vue';
let dataList = reactive([ import { isEmpty, sleep } from '@/utils';
{
value: 10, const props = defineProps({
name: '2020', data: {
type: Array,
default: () => [],
}, },
{ query: {
value: 66, type: String,
name: '2021', default: '',
}, },
{ });
value: 100,
name: '2022',
},
{
value: 120,
name: '2023',
},
{
value: 150,
name: '2024',
},
{
value: 80,
name: '2025',
},
]);
const state = reactive({ const state = reactive({
option: { option: {
color: ['#35D0C0'], color: ['#35D0C0'],
@ -76,12 +63,12 @@ const state = reactive({
// name: '', // name: '',
}, },
}, },
data: dataList, data: [],
}); });
const refresData = () => { const refresData = () => {
console.info('landPatrol********************refresData'); // console.info('landPatrol********************refresData');
state.data = dataList = reactive([ state.data = reactive([
{ {
value: 20, value: 20,
name: '2020', name: '2020',
@ -108,7 +95,53 @@ const refresData = () => {
}, },
]); ]);
}; };
const loadData = async (code = '') => {
state.loading = true;
// GetInputsInfo()
// .then((res) => {
// if (res.code === 200) {
// state.data = res.data;
// }
// })
// .catch((err) => {
// app.$message.error(err.msg);
// });
await sleep(500);
state.data = [
{ value: 5, name: '2020' },
{ value: 36, name: '2021' },
{ value: 70, name: '2022' },
{ value: 56, name: '2023' },
{ value: 70, name: '2024' },
{ value: 20, name: '2025' },
];
};
watch(
() => props.data,
(val) => {
if (!isEmpty(val)) {
state.data = val;
}
},
{
deep: true,
immediate: true,
}
);
watch(
() => props.query,
(val) => {
if (!isEmpty(val)) {
loadData(val);
}
},
{
deep: true,
immediate: true,
}
);
defineExpose({ defineExpose({
refresData, refresData,
}); });

View File

@ -2,21 +2,23 @@
<custom-echart-column-line :chart-data="state.data" height="100%" :option="state.option" /> <custom-echart-column-line :chart-data="state.data" height="100%" :option="state.option" />
</template> </template>
<script setup> <script setup>
import { reactive } from 'vue'; import { reactive, watch } from 'vue';
import { isEmpty, sleep } from '@/utils';
import * as echarts from 'echarts'; import * as echarts from 'echarts';
const props = defineProps({
data: {
type: Array,
default: () => [],
},
query: {
type: String,
default: '',
},
});
const state = reactive({ const state = reactive({
data: [ data: [],
{ value: 103, value1: 208, name: '耿马镇' },
{ value: 72, value1: 157, name: '勐撒镇' },
{ value: 50, value1: 125, name: '勐永镇' },
{ value: 60, value1: 146, name: '孟定镇' },
{ value: 40, value1: 86, name: '勐简乡' },
{ value: 111, value1: 172, name: '贺派乡' },
{ value: 81, value1: 180, name: '四排山乡' },
{ value: 55, value1: 99, name: '芒洪乡' },
{ value: 68, value1: 84, name: '大兴乡' },
],
option: { option: {
grid: { grid: {
left: '3%', left: '3%',
@ -26,6 +28,7 @@ const state = reactive({
containLabel: true, containLabel: true,
}, },
tooltip: { tooltip: {
show: true,
trigger: 'axis', trigger: 'axis',
axisPointer: { axisPointer: {
type: 'shadow', type: 'shadow',
@ -37,8 +40,8 @@ const state = reactive({
const params = data[0]; const params = data[0];
let str = `<div class="custom-echarts-tips"> let str = `<div class="custom-echarts-tips">
<span>${params.name}</span><br/> <span>${params.name}</span><br/>
<span>${params.marker} ${params.data} </span><br /> <span>${params.marker} ${params.data} </span><br />
<span>${data[1].marker} ${data[1].data} </span> <span>${data[1].marker} ${data[1].data} </span>
</div>`; </div>`;
return str; return str;
}, },
@ -199,4 +202,55 @@ const state = reactive({
], ],
}, },
}); });
const loadData = async (code = '') => {
state.loading = true;
// GetInputsInfo()
// .then((res) => {
// if (res.code === 200) {
// state.data = res.data;
// }
// })
// .catch((err) => {
// app.$message.error(err.msg);
// });
await sleep(500);
state.data = [
{ value: 103, value1: 208, name: '耿马镇' },
{ value: 72, value1: 157, name: '勐撒镇' },
{ value: 50, value1: 125, name: '勐永镇' },
{ value: 60, value1: 146, name: '孟定镇' },
{ value: 40, value1: 86, name: '勐简乡' },
{ value: 111, value1: 172, name: '贺派乡' },
{ value: 81, value1: 180, name: '四排山乡' },
{ value: 55, value1: 99, name: '芒洪乡' },
{ value: 68, value1: 84, name: '大兴乡' },
];
};
watch(
() => props.data,
(val) => {
if (!isEmpty(val)) {
state.data = val;
}
},
{
deep: true,
immediate: true,
}
);
watch(
() => props.query,
(val) => {
if (!isEmpty(val)) {
loadData(val);
}
},
{
deep: true,
immediate: true,
}
);
</script> </script>

View File

@ -1,34 +1,40 @@
<template> <template>
<customEchartHyalineCake :chart-data="data" height="100%" :option="option" /> <customEchartHyalineCake :chart-data="dataList" height="100%" :option="option" />
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { reactive, ref } from 'vue'; import { reactive, ref } from 'vue';
/* --------------- data --------------- */ /* --------------- 左中饼图 --------------- */
// #region // #region
const data = ref([ const dataList = ref([
{ {
name: '烟草', name: '烟草',
value: 60.8, value: 60.8,
money: 100,
}, },
{ {
name: '甘蔗', name: '甘蔗',
value: 44.4, value: 44.4,
money: 88,
}, },
{ {
name: '核桃', name: '核桃',
value: 24.3, value: 24.3,
money: 92,
}, },
{ {
name: '蔬菜', name: '蔬菜',
value: 32.7, value: 32.7,
money: 56,
}, },
{ {
name: '其他', name: '其他',
value: 32.9, value: 32.9,
money: 18,
}, },
]); ]);
const option = reactive({ const option = reactive({
k: 0.3, k: 0.3,
opacity: 1, opacity: 1,
@ -36,13 +42,13 @@ const option = reactive({
autoItemHeight: 2, autoItemHeight: 2,
grid3D: { grid3D: {
show: false, show: false,
boxHeight: 5, boxHeight: 4, //
top: '0', top: '0', //
left: '-20%', left: '-20%',
viewControl: { viewControl: {
//3d //3d
alpha: 30, //( ) alpha: 30, //( )
distance: 160, //zoom() distance: 200, //zoom()
rotateSensitivity: 10, //0 rotateSensitivity: 10, //0
zoomSensitivity: 10, //0 zoomSensitivity: 10, //0
panSensitivity: 10, //0 panSensitivity: 10, //0
@ -50,6 +56,41 @@ const option = reactive({
autoRotateAfterStill: 2, //, autoRotate autoRotateAfterStill: 2, //, autoRotate
}, },
}, },
// 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 // #endregion

View File

@ -1,5 +1,10 @@
<template> <template>
<div ref="chartsWarp" class="hot-charts"> <div ref="chartsWarp" class="hot-charts">
<section class="_top_btns">
<span class="left_btn" @click="handleChange(-1)"></span>
<span class="right_btn" @click="handleChange(1)"></span>
{{ current.info.name }}
</section>
<custom-echart-triangle :chart-data="data" height="100%" :option="option" /> <custom-echart-triangle :chart-data="data" height="100%" :option="option" />
</div> </div>
</template> </template>
@ -13,9 +18,72 @@ const data = ref([
]); ]);
const option = reactive({}); const option = reactive({});
onMounted(() => {}); onMounted(() => {});
const list = ref([
{
name: '茶叶',
value: '1',
},
{
name: '核桃',
value: '2',
},
{
name: '玉米',
value: '3',
},
]);
const current = reactive({
index: 0,
length: list.value.length - 1,
info: {
name: '茶叶',
value: '20',
},
});
function handleChange(n) {
if (current.index == 0 && n == -1) {
current.index = current.length;
} else if (current.index == current.length && n == 1) {
current.index = 0;
} else {
current.index += n;
}
current.info = list.value[current.index];
}
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.hot-charts { .hot-charts {
width: 100%;
height: 100%; height: 100%;
display: flex;
flex-direction: column;
align-items: center;
._top_btns {
position: relative;
height: 40px;
width: 30%;
font-size: 20px;
text-align: center;
color: #fff;
line-height: 40px;
background: url('../../../assets/images/basic/tagBG-small.png') no-repeat center center / cover;
span {
display: block;
position: absolute;
top: 8px;
width: 24px;
height: 24px;
text-shadow: 2px 0px 10px 0px #01eeff;
}
.left_btn {
left: -10px;
background: url('../../../assets/images/basic/leftArrowIcon.png') no-repeat center center / cover;
}
.right_btn {
right: -10px;
background: url('../../../assets/images/basic/rightArrowIcon.png') no-repeat center center / cover;
}
}
} }
</style> </style>

View File

@ -2,9 +2,29 @@
<el-row class="data-home-index"> <el-row class="data-home-index">
<el-col :span="6" class="left-charts"> <el-col :span="6" class="left-charts">
<div class="left-charts-item"> <div class="left-charts-item">
<customBack top-title="全县历年产值对比" :top-postion="'left'"> <customBack
top-title="全县历年产值对比"
:top-postion="'left'"
:down-title="'全县'"
:label-field="'label'"
:value-field="'value'"
:down-width="''"
:options="[
{ label: '全县', value: '530926' },
{ label: '耿马镇', value: '42611' },
{ label: '勐撒镇', value: '9259' },
{ label: '勐永镇', value: '17787' },
{ label: '孟定镇', value: '42610' },
{ label: '勐简乡', value: '17788' },
{ label: '贺派乡', value: '40161' },
{ label: '四排山乡', value: '40163' },
{ label: '大兴乡', value: '40159' },
]"
:is-down="true"
@command="handleCommand"
>
<template #back> <template #back>
<entitiesCategoryCharts></entitiesCategoryCharts> <entitiesCategoryCharts ref="oneRef" :data="state.data.one" :query="state.queryCode"></entitiesCategoryCharts>
</template> </template>
</customBack> </customBack>
</div> </div>
@ -16,9 +36,25 @@
</customBack> </customBack>
</div> </div>
<div class="left-charts-item"> <div class="left-charts-item">
<customBack top-title="全县作物产量对比" :top-postion="'left'"> <customBack
top-title="全县作物产量对比"
:top-postion="'left'"
:down-title="'烟草'"
:label-field="'label'"
:value-field="'value'"
:down-width="''"
:options="[
{ label: '烟草', value: 1 },
{ label: '甘蔗', value: 2 },
{ label: '核桃', value: 3 },
{ label: '蔬菜', value: 4 },
{ label: '其他', value: 5 },
]"
:is-down="true"
@command="handleContrast"
>
<template #back> <template #back>
<entitiesStatistics></entitiesStatistics> <entitiesStatistics ref="thirdRef" :data="state.data.third" :query="state.contrastCode"></entitiesStatistics>
</template> </template>
</customBack> </customBack>
</div> </div>
@ -52,6 +88,7 @@
</el-row> </el-row>
</template> </template>
<script setup> <script setup>
import { nextTick, reactive, ref } from 'vue';
import centerMap from '@/components/centerMap.vue'; import centerMap from '@/components/centerMap.vue';
import categoryCharts from './components/categoryCharts.vue'; import categoryCharts from './components/categoryCharts.vue';
import entitieslist from './components/entitieslist.vue'; import entitieslist from './components/entitieslist.vue';
@ -60,6 +97,58 @@ import benefitCharts from './components/benefitCharts.vue';
import entitiesStatistics from './components/entitiesStatistics.vue'; import entitiesStatistics from './components/entitiesStatistics.vue';
import entitiesCategoryCharts from './components/entitiesCategoryCharts.vue'; import entitiesCategoryCharts from './components/entitiesCategoryCharts.vue';
import entitiesMap from './components/entitiesMap.vue'; import entitiesMap from './components/entitiesMap.vue';
import { sleep } from '@/utils';
const oneRef = ref(null);
const thirdRef = ref(null);
const state = reactive({
loading: false,
data: {},
queryCode: '',
contrastCode: '',
});
const loadData = async () => {
state.loading = true;
await sleep(500);
state.data = {
one: [
{ value: 5, name: '2020' },
{ value: 36, name: '2021' },
{ value: 70, name: '2022' },
{ value: 56, name: '2023' },
{ value: 70, name: '2024' },
{ value: 20, name: '2025' },
],
third: [
{ value: 78, value1: 128, name: '耿马镇' },
{ value: 55, value1: 117, name: '勐撒镇' },
{ value: 65, value1: 145, name: '勐永镇' },
{ value: 60, value1: 126, name: '孟定镇' },
{ value: 40, value1: 86, name: '勐简乡' },
{ value: 81, value1: 152, name: '贺派乡' },
{ value: 41, value1: 130, name: '四排山乡' },
{ value: 63, value1: 109, name: '芒洪乡' },
{ value: 79, value1: 184, name: '大兴乡' },
],
};
};
loadData();
const handleCommand = (data) => {
state.queryCode = data.value;
// console.info('data=', data);
// nextTick(() => {
// oneRef.value && oneRef.value.refresData();
// });
};
const handleContrast = (data) => {
state.contrastCode = data.value;
// console.info('data=', data);
nextTick(() => {
thirdRef.value && thirdRef.value.refresData();
});
};
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.data-home-index { .data-home-index {

View File

@ -2,8 +2,8 @@
<div class="data-home-index"> <div class="data-home-index">
<template v-for="(n, index) in homeList" :key="n.name"> <template v-for="(n, index) in homeList" :key="n.name">
<div class="home-enter-item" :style="n.style" @click="itemClick(index)"> <div class="home-enter-item" :style="n.style" @click="itemClick(index)">
<div class="name"> <div class="name" :style="n.nameStyle">
<span>{{ n.title || '--' }}</span> <span :style="n.spanStyle">{{ n.title || '--' }}</span>
</div> </div>
<div class="img-icon" :style="n.imgstyle"><img :src="getAssetsFile(n.img)" /></div> <div class="img-icon" :style="n.imgstyle"><img :src="getAssetsFile(n.img)" /></div>
</div> </div>
@ -32,35 +32,43 @@ let homeList = reactive([
linkType: 0, linkType: 0,
url: '', url: '',
img: 'images/vsualized/home1.png', img: 'images/vsualized/home1.png',
style: 'left: 20%;bottom:320px;', style: 'left: 21%;bottom:300px;',
imgstyle: 'width:100px;height:100px', imgstyle: 'width:100px;height:100px',
nameStyle: 'padding: 0 16px;margin: 16px 0;',
spanStyle: 'font-size: 20px;',
}, },
{ {
title: '农业产业运营服务平台', title: '产业运营平台',
name: 'operation', name: 'operation',
linkType: 0, linkType: 0,
url: '', url: '',
img: 'images/vsualized/home2.png', img: 'images/vsualized/home2.png',
style: 'left: 20%;bottom: 64px;', style: 'left: 22%;bottom: 24px;',
imgstyle: 'width:160px;height:160px', imgstyle: 'width:160px;height:160px',
nameStyle: 'padding: 0 22px;margin: 24px 0;border-radius: 16px;',
spanStyle: 'font-size: 28px;line-height: 66px',
}, },
{ {
title: '数字大屏', title: '数字大屏',
name: 'dataV', name: 'dataV',
linkType: 1, linkType: 1,
url: '/new-digital-agriculture-screen/v2/land', url: '/v2/land',
img: 'images/vsualized/home3.png', img: 'images/vsualized/home3.png',
style: 'right: 20%;bottom:320px;', style: 'right: 23%;bottom:300px;',
imgstyle: 'width:100px;height:100px', imgstyle: 'width:100px;height:100px',
nameStyle: 'padding: 0 16px;margin: 16px 0;',
spanStyle: 'font-size: 20px;',
}, },
{ {
title: '农业产业政务服务平台', title: '政务云平台',
name: 'gov', name: 'gov',
linkType: 0, linkType: 0,
url: '', url: '',
img: 'images/vsualized/home4.png', img: 'images/vsualized/home4.png',
style: 'right: 20%;bottom: 64px;', style: 'right: 24%;bottom: 24px;',
imgstyle: 'width:160px;height:160px', imgstyle: 'width:160px;height:160px',
nameStyle: 'padding: 0 22px;margin: 24px 0;border-radius: 16px;',
spanStyle: 'font-size: 28px;line-height: 66px',
}, },
// ... // ...
]); ]);
@ -70,7 +78,6 @@ const itemClick = (index) => {
let val = homeList[index] || null; let val = homeList[index] || null;
if (val && val.url != '') { if (val && val.url != '') {
if (val.linkType == 1) { if (val.linkType == 1) {
// router.push({ name: val.url });
router.push({ path: val.url }); router.push({ path: val.url });
} }
} }
@ -107,17 +114,24 @@ const itemClick = (index) => {
.name { .name {
color: #fff; color: #fff;
font-family: 'JinBuTi'; font-family: 'JinBuTi';
margin: 24px 0;
background: linear-gradient(180deg, #01fefd, rgba(1, 254, 253, 0));
border: 2px solid #01fefd; border: 2px solid #01fefd;
border-radius: 8px; border-radius: 8px;
padding: 0 24px;
span {
backdrop-filter: blur(8px); backdrop-filter: blur(8px);
&::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: linear-gradient(180deg, #01fefd, rgba(1, 254, 253, 0));
opacity: 0.16; //
z-index: -1; //
border-radius: 6px; //
}
span {
line-height: 40px; line-height: 40px;
text-shadow: 0px 4px 8px 0px #01fefd; text-shadow: 0px 4px 8px 0px #01fefd;
font-size: 28px;
} }
} }
.img-icon { .img-icon {

View File

@ -3,12 +3,12 @@
* @Author: zenghua.wang * @Author: zenghua.wang
* @Date: 2022-09-18 21:24:29 * @Date: 2022-09-18 21:24:29
* @LastEditors: zenghua.wang * @LastEditors: zenghua.wang
* @LastEditTime: 2025-02-28 11:04:41 * @LastEditTime: 2025-04-18 15:41:11
*/ */
import { defineConfig, loadEnv } from 'vite'; import { defineConfig, loadEnv } from 'vite';
import vue from '@vitejs/plugin-vue'; import vue from '@vitejs/plugin-vue';
import qiankun from 'vite-plugin-qiankun'; // import qiankun from 'vite-plugin-qiankun';
import eslintPlugin from 'vite-plugin-eslint'; import eslintPlugin from 'vite-plugin-eslint';
import vueSetupExtend from 'vite-plugin-vue-setup-extend'; import vueSetupExtend from 'vite-plugin-vue-setup-extend';
import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'; import { createSvgIconsPlugin } from 'vite-plugin-svg-icons';
@ -23,9 +23,9 @@ import { resolve } from 'path';
const useDevMode = true; const useDevMode = true;
export default defineConfig(({ command, mode }) => { export default defineConfig(({ command, mode }) => {
const { VITE_APP_MIAN_URL, VITE_PORT, VITE_APP_NAME, VITE_APP_BASE_API, VITE_APP_BASE_URL, VITE_APP_UPLOAD_API, VITE_APP_UPLOAD_URL } = loadEnv(mode, process.cwd()); const { VITE_PORT, VITE_APP_NAME, VITE_APP_BASE_API, VITE_APP_BASE_URL } = loadEnv(mode, process.cwd());
const config = { const config = {
base: '/new-digital-agriculture-screen/', base: '/',
build: { build: {
target: 'ESNext', target: 'ESNext',
outDir: 'dist', outDir: 'dist',
@ -36,7 +36,6 @@ export default defineConfig(({ command, mode }) => {
port: VITE_PORT, port: VITE_PORT,
open: true, open: true,
https: false, https: false,
origin: VITE_APP_MIAN_URL,
headers: { headers: {
'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Origin': '*',
}, },
@ -46,17 +45,11 @@ export default defineConfig(({ command, mode }) => {
changeOrigin: true, changeOrigin: true,
rewrite: (path) => path.replace(/^\/apis/, ''), rewrite: (path) => path.replace(/^\/apis/, ''),
}, },
[VITE_APP_UPLOAD_API]: {
target: VITE_APP_UPLOAD_URL,
changeOrigin: true,
rewrite: (path) => path.replace(/^\/uploadApis/, ''),
},
}, },
}, },
resolve: { resolve: {
alias: { alias: {
'@': resolve(__dirname, 'src'), '@': resolve(__dirname, 'src'),
'#': resolve(__dirname, '../main/src'),
}, },
extensions: ['.js', '.vue', '.json', '.ts'], extensions: ['.js', '.vue', '.json', '.ts'],
}, },
@ -78,7 +71,7 @@ export default defineConfig(({ command, mode }) => {
}, },
plugins: [ plugins: [
vue(), vue(),
qiankun(VITE_APP_NAME, { useDevMode }), // qiankun(VITE_APP_NAME, { useDevMode }),
vueSetupExtend(), vueSetupExtend(),
eslintPlugin({ eslintPlugin({
include: ['src/**/*.ts', 'src/**/*.vue', 'src/*.ts', 'src/*.vue'], include: ['src/**/*.ts', 'src/**/*.vue', 'src/*.ts', 'src/*.vue'],

16857
yarn.lock

File diff suppressed because it is too large Load Diff