This commit is contained in:
李想 2025-03-21 16:15:58 +08:00
commit 1700a7ab42
40 changed files with 1419 additions and 456 deletions

View File

@ -23,6 +23,7 @@
"axios": "^1.6.5", "axios": "^1.6.5",
"dayjs": "^1.11.11", "dayjs": "^1.11.11",
"echarts": "^5.6.0", "echarts": "^5.6.0",
"echarts-gl": "^2.0.9",
"element-plus": "^2.7.3", "element-plus": "^2.7.3",
"file-saver": "^2.0.5", "file-saver": "^2.0.5",
"js-base64": "^3.7.7", "js-base64": "^3.7.7",

View File

@ -35,23 +35,7 @@ export default {
const chartRef = ref(null); const chartRef = ref(null);
const { setOptions, getInstance, resize } = useEcharts(chartRef); const { setOptions, getInstance, resize } = useEcharts(chartRef);
const option = reactive({ const option = reactive({
tooltip: { series: [],
formatter: '{b} ({c})',
},
series: [
{
type: 'pie',
radius: '72%',
center: ['50%', '55%'],
data: [],
labelLine: { show: true },
label: {
show: true,
formatter: '{b} \n ({d}%)',
color: '#B1B9D3',
},
},
],
}); });
watchEffect(() => { watchEffect(() => {
@ -72,8 +56,7 @@ export default {
if (props.option) { if (props.option) {
Object.assign(option, cloneDeep(props.option)); Object.assign(option, cloneDeep(props.option));
} }
// option.series[0].data = props.chartData; option.series = props.chartData;
option.series[0].data = props.chartData;
setOptions(option); setOptions(option);
resize(); resize();
getInstance()?.off('click', onClick); getInstance()?.off('click', onClick);

View File

@ -0,0 +1,39 @@
<template>
<iframe v-if="state.url" :src="state.url" frameborder="0" width="100%" height="100%" @load="onLoad"></iframe>
</template>
<script setup name="custom-iframe">
import { reactive, watch } from 'vue';
import { isExternal } from '@/utils/validate';
const props = defineProps({
url: {
type: String,
required: true,
},
});
const emit = defineEmits(['on-load']);
const state = reactive({
url: '',
loaded: false,
});
watch(
() => props.url,
(val) => {
if (isExternal(val)) {
state.url = val;
}
},
{
immediate: true,
}
);
const onLoad = () => {
state.loaded = true;
emit('on-load', state.loaded);
};
</script>

View File

@ -2,14 +2,18 @@
<div :class="`custom-table-tree ${shadow ? 'custom-table-tree__shadow' : ''}`"> <div :class="`custom-table-tree ${shadow ? 'custom-table-tree__shadow' : ''}`">
<div v-if="title" class="title">{{ title }}</div> <div v-if="title" class="title">{{ title }}</div>
<el-tree <el-tree
node-key="id"
:data="data" :data="data"
:node-key="option.nodeKey"
:show-checkbox="option.showCheckbox" :show-checkbox="option.showCheckbox"
:default-expanded-keys="option.defaultExpandedKeys" :default-expanded-keys="option.defaultExpandedKeys"
:default-checked-keys="option.defaultCheckedKeys" :default-checked-keys="option.defaultCheckedKeys"
:props="option.defaultProps" :props="option.props ?? option.defaultProps"
@node-click="handleNodeClick" @node-click="handleNodeClick"
/> >
<template #default="{ data: rows }">
<slot :data="rows"></slot>
</template>
</el-tree>
</div> </div>
</template> </template>
<script setup name="custom-table-tree"> <script setup name="custom-table-tree">
@ -21,7 +25,9 @@ const props = defineProps({
type: Object, type: Object,
default: () => { default: () => {
return { return {
nodeKey: 'id',
showCheckbox: false, showCheckbox: false,
props: {},
defaultProps: { defaultProps: {
children: 'children', children: 'children',
label: 'label', label: 'label',
@ -34,8 +40,8 @@ const props = defineProps({
}); });
const emit = defineEmits(['node-click']); const emit = defineEmits(['node-click']);
const handleNodeClick = (data) => { const handleNodeClick = (data, node) => {
emit('node-click', data); emit('node-click', data, node);
}; };
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

@ -1,4 +1,5 @@
import SvgIcon from './svg-icon'; import SvgIcon from './svg-icon';
import CustomIframe from './custom-iframe';
import CustomTableOperate from './custom-table-operate'; import CustomTableOperate from './custom-table-operate';
import CustomTableTree from './custom-table-tree'; import CustomTableTree from './custom-table-tree';
import CustomCarouselPicture from './custom-carousel-picture'; import CustomCarouselPicture from './custom-carousel-picture';
@ -16,6 +17,7 @@ import CustomEchartPie3d from './custom-echart-pie-3d';
export { export {
SvgIcon, SvgIcon,
CustomIframe,
CustomTableOperate, CustomTableOperate,
CustomTableTree, CustomTableTree,
CustomCarouselPicture, CustomCarouselPicture,

View File

@ -1,7 +1,7 @@
import * as echarts from 'echarts/core'; import * as echarts from 'echarts/core';
import { BarChart, LineChart, PieChart, MapChart, PictorialBarChart, RadarChart, GraphChart } from 'echarts/charts'; import { BarChart, LineChart, PieChart, MapChart, PictorialBarChart, RadarChart, GraphChart } from 'echarts/charts';
import 'echarts-gl';
import { import {
TitleComponent, TitleComponent,
TooltipComponent, TooltipComponent,

View File

@ -45,7 +45,7 @@ export function isHttp(url) {
* @returns {Boolean} * @returns {Boolean}
*/ */
export function isExternal(path) { export function isExternal(path) {
return /^(https?:|mailto:|tel:)/.test(path); return /^(http?:|https?:|mailto:|tel:)/.test(path);
} }
/** /**

View File

@ -1628,6 +1628,11 @@ class-utils@^0.3.5:
isobject "^3.0.0" isobject "^3.0.0"
static-extend "^0.1.1" static-extend "^0.1.1"
claygl@^1.2.1:
version "1.3.0"
resolved "https://registry.npmmirror.com/claygl/-/claygl-1.3.0.tgz#7a6e2903210519ac358848f5d78070ed211685f3"
integrity sha512-+gGtJjT6SSHD2l2yC3MCubW/sCV40tZuSs5opdtn79vFSGUgp/lH139RNEQ6Jy078/L0aV8odCw8RSrUcMfLaQ==
clean-css@^5.2.2: clean-css@^5.2.2:
version "5.3.3" version "5.3.3"
resolved "https://registry.npmmirror.com/clean-css/-/clean-css-5.3.3.tgz#b330653cd3bd6b75009cc25c714cae7b93351ccd" resolved "https://registry.npmmirror.com/clean-css/-/clean-css-5.3.3.tgz#b330653cd3bd6b75009cc25c714cae7b93351ccd"
@ -2177,6 +2182,14 @@ dunder-proto@^1.0.0, dunder-proto@^1.0.1:
es-errors "^1.3.0" es-errors "^1.3.0"
gopd "^1.2.0" gopd "^1.2.0"
echarts-gl@^2.0.9:
version "2.0.9"
resolved "https://registry.npmmirror.com/echarts-gl/-/echarts-gl-2.0.9.tgz#ee228a6c7520a6fb7bbb71ea94394f3637ade033"
integrity sha512-oKeMdkkkpJGWOzjgZUsF41DOh6cMsyrGGXimbjK2l6Xeq/dBQu4ShG2w2Dzrs/1bD27b2pLTGSaUzouY191gzA==
dependencies:
claygl "^1.2.1"
zrender "^5.1.1"
echarts@^5.6.0: echarts@^5.6.0:
version "5.6.0" version "5.6.0"
resolved "https://registry.npmmirror.com/echarts/-/echarts-5.6.0.tgz#2377874dca9fb50f104051c3553544752da3c9d6" resolved "https://registry.npmmirror.com/echarts/-/echarts-5.6.0.tgz#2377874dca9fb50f104051c3553544752da3c9d6"
@ -7095,7 +7108,7 @@ yocto-queue@^0.1.0:
resolved "https://registry.npmmirror.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" resolved "https://registry.npmmirror.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"
integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==
zrender@5.6.1: zrender@5.6.1, zrender@^5.1.1:
version "5.6.1" version "5.6.1"
resolved "https://registry.npmmirror.com/zrender/-/zrender-5.6.1.tgz#e08d57ecf4acac708c4fcb7481eb201df7f10a6b" resolved "https://registry.npmmirror.com/zrender/-/zrender-5.6.1.tgz#e08d57ecf4acac708c4fcb7481eb201df7f10a6b"
integrity sha512-OFXkDJKcrlx5su2XbzJvj/34Q3m6PvyCZkVPHGYpcCJ52ek4U/ymZyfuV1nKE23AyBJ51E/6Yr0mhZ7xGTO4ag== integrity sha512-OFXkDJKcrlx5su2XbzJvj/34Q3m6PvyCZkVPHGYpcCJ52ek4U/ymZyfuV1nKE23AyBJ51E/6Yr0mhZ7xGTO4ag==

View File

@ -1,4 +1,4 @@
import request from '@/utils/request'; import request from '@/utils/request'
// 登录方法 // 登录方法
export function login(username, password, code, uuid) { export function login(username, password, code, uuid) {
@ -10,7 +10,7 @@ export function login(username, password, code, uuid) {
}, },
method: 'post', method: 'post',
data: { username, password, code, uuid }, data: { username, password, code, uuid },
}); })
} }
// 注册方法 // 注册方法
@ -22,7 +22,7 @@ export function register(data) {
}, },
method: 'post', method: 'post',
data: data, data: data,
}); })
} }
// 刷新方法 // 刷新方法
@ -30,7 +30,7 @@ export function refreshToken() {
return request({ return request({
url: '/auth/refresh', url: '/auth/refresh',
method: 'post', method: 'post',
}); })
} }
// 获取用户详细信息 // 获取用户详细信息
@ -38,7 +38,7 @@ export function getInfo() {
return request({ return request({
url: '/system/user/getInfo', url: '/system/user/getInfo',
method: 'get', method: 'get',
}); })
} }
// 退出方法 // 退出方法
@ -46,7 +46,7 @@ export function logout() {
return request({ return request({
url: '/auth/logout', url: '/auth/logout',
method: 'delete', method: 'delete',
}); })
} }
// 获取验证码 // 获取验证码
@ -58,5 +58,5 @@ export function getCodeImg() {
}, },
method: 'get', method: 'get',
timeout: 20000, timeout: 20000,
}); })
} }

View File

@ -7,14 +7,13 @@ const TokenKey = 'Admin-Token';
const ExpiresInKey = 'Admin-Expires-In'; const ExpiresInKey = 'Admin-Expires-In';
export function getToken() { export function getToken() {
return true let token = Cookies.get(TokenKey);
// let token = Cookies.get(TokenKey); if (undefined === token || null == token || 'null' === token) {
// if (undefined === token || null == token || 'null' === token) { token = getQueryString('Authorization');
// token = getQueryString('Authorization'); if (null != token || 'null' !== token) Cookies.set(TokenKey, token);
// if (null != token || 'null' !== token) Cookies.set(TokenKey, token); }
// } if (undefined === token || null == token || 'null' === token) token = false;
// if (undefined === token || null == token || 'null' === token) token = false; return token;
// return token;
} }
export function setToken(token) { export function setToken(token) {

View File

@ -28,7 +28,7 @@ service.interceptors.request.use(
// 是否需要防止数据重复提交 // 是否需要防止数据重复提交
const isRepeatSubmit = (config.headers || {}).repeatSubmit === false; const isRepeatSubmit = (config.headers || {}).repeatSubmit === false;
if (getToken() && !isToken) { if (getToken() && !isToken) {
config.headers['Authorization'] = 'Bearer ' + getToken(); // 让每个请求携带自定义token 请根据实际情况自行修改 config.headers['Authorization'] = getToken(); // 让每个请求携带自定义token 请根据实际情况自行修改
} }
// get请求映射params参数 // get请求映射params参数
if (config.method === 'get' && config.params) { if (config.method === 'get' && config.params) {

View File

@ -18,7 +18,7 @@ module.exports = {
// 部署生产环境和开发环境下的URL。 // 部署生产环境和开发环境下的URL。
// 默认情况下Vue CLI 会假设你的应用是被部署在一个域名的根路径上 // 默认情况下Vue CLI 会假设你的应用是被部署在一个域名的根路径上
// 例如 https://www.ruoyi.vip/。如果应用被部署在一个子路径上,你就需要用这个选项指定这个子路径。例如,如果你的应用被部署在 https://www.ruoyi.vip/admin/,则设置 baseUrl 为 /admin/。 // 例如 https://www.ruoyi.vip/。如果应用被部署在一个子路径上,你就需要用这个选项指定这个子路径。例如,如果你的应用被部署在 https://www.ruoyi.vip/admin/,则设置 baseUrl 为 /admin/。
publicPath: `/sub-admin/`, publicPath: './',
// 在npm run build 或 yarn build 时 生成文件的目录名称要和baseUrl的生产环境路径一致默认dist // 在npm run build 或 yarn build 时 生成文件的目录名称要和baseUrl的生产环境路径一致默认dist
outputDir: 'dist', outputDir: 'dist',
// 用于放置生成的静态资源 (js、css、img、fonts) 的;(项目打包之后,静态资源会放在这个文件夹下) // 用于放置生成的静态资源 (js、css、img、fonts) 的;(项目打包之后,静态资源会放在这个文件夹下)
@ -68,7 +68,7 @@ module.exports = {
libraryTarget: 'umd', // 把微应用打包成 umd 库格式 libraryTarget: 'umd', // 把微应用打包成 umd 库格式
jsonpFunction: `${name}`, jsonpFunction: `${name}`,
filename: `[name].[hash].js`, filename: `[name].[hash].js`,
chunkFilename: `[name].[hash].js` chunkFilename: `[name].[hash].js`,
}, },
plugins: [ plugins: [
new CompressionPlugin({ new CompressionPlugin({

View File

@ -44,35 +44,25 @@ export function delPlanCrop(params) {
//种植产物对应的种植阶段相关 //种植产物对应的种植阶段相关
// #region // #region
// export function getPlanStage(params = {}) { export function getPlanStage(params = {}) {
// return request('land-resource/baseInfo/planTypePage', { return request('land-resource/baseInfo/stageTypePage', {
// method: 'GET', method: 'GET',
// params, params,
// }); });
// } }
// export function upPlanStage(data = {}) { export function upPlanStage(data = {}) {
// return request('land-resource/baseInfo/planTypeEdit', { return request('land-resource/baseInfo/stageTypeEdit', {
// method: 'PUT', method: 'PUT',
// data, data,
// }); });
// } }
// export function exportPlanStage(params = {}) { export function delPlanStage(params) {
// return request('/land-resource/baseInfo/planTypeExport', { return request('land-resource/baseInfo/stageTypeDelete/' + params.id, {
// method: 'GET', method: 'DELETE',
// params, });
// responseType: 'blob', }
// });
// }
// export function delPlanStage(params) {
// return request('land-resource/baseInfo/planTypeDelete/' + params.id, {
// method: 'DELETE',
// });
// }
// #endregion
export function savePlanStage(data) { export function savePlanStage(data) {
return request('land-resource/baseInfo/stageTypeSave', { return request('land-resource/baseInfo/stageTypeSave', {
@ -81,6 +71,14 @@ export function savePlanStage(data) {
}); });
} }
export function getWorkPage(params = {}) {
return request('land-resource/planManage/workPage', {
method: 'GET',
params,
});
}
// #endregion
/* ------ 土壤类型 ------ */ /* ------ 土壤类型 ------ */
// #region // #region

View File

@ -99,6 +99,13 @@ export function delPlan(params) {
}); });
} }
export function getPlanHistory(params = {}) {
return request('land-resource/planManage/historyPlanPage', {
method: 'GET',
params,
});
}
//种植阶段相关 //种植阶段相关
export function getPlantingStage(params = {}) { export function getPlantingStage(params = {}) {
return request('land-resource/planManage/pageStage', { return request('land-resource/planManage/pageStage', {

View File

@ -3,14 +3,14 @@
* @Author: zenghua.wang * @Author: zenghua.wang
* @Date: 2023-06-20 14:29:45 * @Date: 2023-06-20 14:29:45
* @LastEditors: zenghua.wang * @LastEditors: zenghua.wang
* @LastEditTime: 2025-02-13 16:02:18 * @LastEditTime: 2025-03-20 14:04:09
--> -->
<template> <template>
<el-breadcrumb class="layout-breadcrumb" separator="/"> <el-breadcrumb class="layout-breadcrumb" separator="/">
<transition-group name="breadcrumb"> <transition-group name="breadcrumb">
<el-breadcrumb-item v-if="matched[0].meta.title !== '首页'" key="home" :to="{ path: '/' }"> <el-breadcrumb-item v-if="matched[0].meta.title !== '政务服务'" key="home" :to="{ path: '/' }">
<div class="layout-breadcrumb-item"> <div class="layout-breadcrumb-item">
<span class="layout-breadcrumb-title">首页</span> <span class="layout-breadcrumb-title">政务服务</span>
</div> </div>
</el-breadcrumb-item> </el-breadcrumb-item>
<el-breadcrumb-item v-for="(item, index) in matched" :key="item.name"> <el-breadcrumb-item v-for="(item, index) in matched" :key="item.name">

View File

@ -3,7 +3,7 @@
* @Author: zenghua.wang * @Author: zenghua.wang
* @Date: 2023-06-20 11:48:41 * @Date: 2023-06-20 11:48:41
* @LastEditors: zenghua.wang * @LastEditors: zenghua.wang
* @LastEditTime: 2025-03-12 11:10:12 * @LastEditTime: 2025-03-20 14:40:44
*/ */
import { createRouter, createWebHistory } from 'vue-router'; import { createRouter, createWebHistory } from 'vue-router';
import Layout from '@/layouts/index.vue'; import Layout from '@/layouts/index.vue';

View File

@ -0,0 +1,326 @@
<template>
<div style="margin-top: 16px">
<!-- <el-dialog v-model="isShowVal" title="种植阶段详情" width="1000" center @closed="stageClose"> -->
<el-text class="mx-1" size="large">种植阶段详情</el-text>
<div style="margin-top: 16px">
<avue-crud
ref="stateCrudRef"
v-model="stageState.form"
v-model:search="stageState.query"
v-model:page="stageState.pageData"
:table-loading="stageState.loading"
:data="stageState.data"
:option="stageState.options"
@refresh-change="stageRefresh"
@search-reset="stageSearch"
@search-change="stageSearch"
@selection-change="stageSelection"
@current-change="stageCurrent"
@size-change="stageSize"
@row-del="stageRowDel"
@row-save="stageRowSave"
@row-update="stageRowUpdate"
>
<template #menu-left>
<el-button type="primary" icon="Plus" @click="onStateAdd">新增</el-button>
</template>
<template #stage="{ row }">
<el-tag size="small">{{ stageObj[row.stage] }}</el-tag>
</template>
<template #cropId="{ row }">
{{ row.cropName }}
</template>
<template #menu="scope">
<custom-table-operate :actions="stageState.options.actions" :data="scope" />
</template>
</avue-crud>
<!-- </el-dialog> -->
</div>
</div>
</template>
<script setup>
import { onMounted, reactive, ref, watch } from 'vue';
import { useApp } from '@/hooks';
import { CRUD_OPTIONS } from '@/config';
import { useUserStore } from '@/store/modules/user';
import { getPlanStage, savePlanStage, upPlanStage, delPlanStage } from '@/apis/baseInfo.js';
import { isEmpty, imageToBase64, getAssetsFile, downloadFile } from '@/utils';
const props = defineProps({
isShow: {
type: Boolean,
default: true,
},
rowOriginal: {
type: Object,
default: () => {
return {};
},
},
});
const emit = defineEmits(['close']);
const { VITE_APP_BASE_API } = import.meta.env;
const app = useApp();
const UserStore = useUserStore();
const stateCrudRef = ref(null);
const stageOptions = reactive([
{ value: '0', label: '苗期' },
{ value: '1', label: '花果期' },
{ value: '2', label: '采收期' },
]);
const workOptions = reactive([
{ label: '作业计划1', value: '000001' },
{ label: '作业计划2', value: '000002' },
]);
const stageObj = reactive({
0: '苗期',
1: '花果期',
2: '采收期',
});
const isShowVal = ref(false);
let currentRow = reactive({});
const loadList = () => {
if (isShowVal.value) {
console.info('loadList', props);
getStageList();
}
};
onMounted(() => {
isShowVal.value = props.isShow;
currentRow = props.rowOriginal;
loadList();
// console.info('onMounted', props);
});
watch(
() => (props.isShow, props.rowOriginal),
() => {
isShowVal.value = props.isShow;
currentRow = props.rowOriginal;
console.info('watch', props);
loadList();
},
{ deep: true, immediate: true }
);
let stageState = reactive({
loading: false,
query: {
current: 1,
size: 10,
stage: null,
},
form: {},
options: {
...CRUD_OPTIONS,
addBtn: false,
selection: false,
column: [
{
label: '种植产物',
prop: 'cropId',
type: 'select',
remote: false,
width: '160px',
showOverflowTooltip: true,
props: {
label: 'crop',
value: 'id',
},
dicHeaders: {
authorization: UserStore.token,
},
dicUrl: `${VITE_APP_BASE_API}/land-resource/baseInfo/planTypePage?current=1&size=999`,
dicFormatter: (res) => res.data.records ?? [],
rules: [
{
required: true,
message: '请选择',
trigger: 'blur',
},
],
},
{
label: '所属阶段',
prop: 'stage',
type: 'select',
search: true,
dicData: stageOptions,
rules: {
required: true,
message: '请选择',
trigger: 'blur',
},
},
{
label: '作业类型',
prop: 'workType',
// type: 'select',
search: false,
// dicData: workOptions,
rules: { required: true, message: '请选择', trigger: 'blur' },
},
{
label: '作业时间(多少天后)',
prop: 'workTime',
rules: { required: true, message: '请输入', trigger: 'blur' },
props: {
type: 'Number',
},
addDisplay: true,
editDisplay: true,
},
],
actions: [
{
name: '编辑',
icon: 'edit',
event: ({ row }) => stageRowEdit(row),
},
{
type: 'danger',
name: '删除',
icon: 'delete',
event: ({ row }) => stageRowDel(row),
},
],
},
pageData: {
total: 0,
currentPage: 1,
pageSize: 10,
},
data: [],
currentRow: {},
});
async function getStageList() {
if (!currentRow.id) {
return app.$message.success('请选择种植产物');
}
stageState.loading = true;
getPlanStage({ ...stageState.query, cropId: currentRow.id })
.then((res) => {
if (res.code === 200) {
const { current, size, total, records } = res.data;
stageState.data = records || [];
stageState.pageData = {
currentPage: current || 1,
pageSize: size || 10,
total: total,
};
}
})
.catch((err) => {
app.$message.error(err.msg);
stageState.data = [];
})
.finally(() => {
stageState.loading = false;
});
}
const stageSearch = (params, done) => {
if (done) done();
stageState.query = params;
stageState.query.current = 1;
getStageList();
};
const stageSelection = (rows) => {
stageState.selection = rows;
};
const stageCurrent = (current) => {
stageState.query.current = current;
getStageList();
};
const stageSize = (size) => {
stageState.query.size = size;
getStageList();
};
const stageRowDel = (row, index, done) => {
if (isEmpty(row)) return;
app
.$confirm(`删除后信息将不可查看,确认要删除吗?`, '确定删除', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
})
.then(() => {
console.info('删除');
delPlanStage({ id: row.id })
.then((res) => {
if (res.code === 200) {
app.$message.success('删除成功!');
getStageList();
done();
}
})
.catch((err) => {
app.$message.error(err.msg);
});
})
.catch(() => {});
};
const stageRowEdit = (row) => {
stateCrudRef.value.rowEdit(row);
};
const onStateAdd = () => {
if (!currentRow.id) {
app.$message.error('请选择种植产物');
return;
}
stateCrudRef.value.rowAdd();
};
const stageRowSave = (row, done, loading) => {
console.info('stageRowSave', row);
savePlanStage({ ...row })
.then((res) => {
if (res.code === 200) {
app.$message.success('添加成功!');
done();
getStageList();
}
})
.catch((err) => {
app.$message.error(err.msg);
})
.finally(() => {
loading();
});
};
const stageRowUpdate = (row, index, done, loading) => {
console.info('stageRowUpdate');
upPlanStage(row)
.then((res) => {
if (res.code === 200) {
app.$message.success('更新成功!');
done();
getStageList();
}
})
.catch((err) => {
app.$message.error(err.msg);
})
.finally(() => {
loading();
});
};
const stageClose = () => {
isShowVal.value = false;
emit('close');
};
</script>

View File

@ -33,39 +33,8 @@
</template> </template>
</avue-crud> </avue-crud>
<stageList :is-show="stageShow" :row-original="state.currentRow" @close="stageHide"></stageList>
<el-text class="mx-1" size="large">种植阶段详情</el-text> <el-text class="mx-1" size="large">种植阶段详情</el-text>
<div style="margin-top: 16px">
<avue-crud
ref="stateCrudRef"
v-model="stageState.form"
v-model:search="stageState.query"
v-model:page="stageState.pageData"
:table-loading="stageState.loading"
:data="stageState.data"
:option="stageState.options"
@refresh-change="stageRefresh"
@search-reset="stageSearch"
@search-change="stageSearch"
@selection-change="stageSelection"
@current-change="stageCurrent"
@size-change="stageSize"
@row-del="stageRowDel"
@row-save="stageRowSave"
@row-update="stageRowUpdate"
>
<template #menu-left>
<el-button type="primary" icon="Plus" @click="onStateAdd">新增</el-button>
</template>
<template #stage="{ row }">
<el-tag size="small">{{ stageObj[row.stage] }}</el-tag>
</template>
<template #menu="scope">
<custom-table-operate :actions="stageState.options.actions" :data="scope" />
</template>
</avue-crud>
</div>
</div> </div>
</template> </template>
<script setup> <script setup>
@ -75,7 +44,8 @@ import { CRUD_OPTIONS } from '@/config';
import { isEmpty, downloadFile } from '@/utils'; import { isEmpty, downloadFile } from '@/utils';
import { useUserStore } from '@/store/modules/user'; import { useUserStore } from '@/store/modules/user';
import { compact } from 'lodash'; import { compact } from 'lodash';
import { getPlanCrop, savePlanCrop, upPlanCrop, exportPlanCrop, delPlanCrop } from '@/apis/baseInfo'; import { getPlanCrop, savePlanCrop, upPlanCrop, exportPlanCrop, delPlanCrop, getPlanStage } from '@/apis/baseInfo';
import stageList from '../dictCrop/component/stage.vue';
const { VITE_APP_BASE_API } = import.meta.env; const { VITE_APP_BASE_API } = import.meta.env;
const app = useApp(); const app = useApp();
@ -83,21 +53,7 @@ const UserStore = useUserStore();
const crudRef = ref(null); const crudRef = ref(null);
const stateCrudRef = ref(null); const stateCrudRef = ref(null);
const stageOptions = reactive([ let stageShow = ref(false);
{ value: '0', label: '苗期' },
{ value: '1', label: '花果期' },
{ value: '2', label: '采收期' },
]);
const stageObj = reactive({
0: '苗期',
1: '花果期',
2: '采收期',
});
const workOptions = reactive([
{ planName: '作业计划1', id: '000001' },
{ planName: '作业计划2', id: '000002' },
]);
const state = reactive({ const state = reactive({
loading: false, loading: false,
query: { query: {
@ -134,19 +90,19 @@ const state = reactive({
trigger: 'blur', trigger: 'blur',
}, },
}, },
{ // {
label: '种植时间', // label: '',
prop: 'planDate', // prop: 'planDate',
type: 'date', // type: 'date',
format: 'YYYY-MM-DD', // format: 'YYYY-MM-DD',
valueFormat: 'YYYY-MM-DD', // valueFormat: 'YYYY-MM-DD',
width: 160, // width: 160,
rules: { // rules: {
required: true, // required: true,
message: '请选择作业日期', // message: '',
trigger: 'blur', // trigger: 'blur',
}, // },
}, // },
{ {
label: '状态', label: '状态',
prop: 'status', prop: 'status',
@ -191,68 +147,6 @@ const state = reactive({
currentRow: {}, currentRow: {},
}); });
const stageState = reactive({
loading: false,
query: {
current: 1,
size: 10,
},
form: {},
options: {
...CRUD_OPTIONS,
addBtn: false,
selection: false,
column: [
{
label: '所属阶段',
prop: 'stage',
type: 'select',
search: true,
dicData: stageOptions,
rules: {
required: true,
message: '请选择',
trigger: 'blur',
},
},
{
label: '作业计划',
prop: 'workId',
type: 'select',
search: true,
dicData: workOptions,
rules: {
required: true,
message: '请选择',
trigger: 'blur',
},
},
{ label: '作业时间', prop: 'coordinate', disabled: true, addDisplay: false, editDisplay: false },
{ label: '结束时间', prop: 'createTime', disabled: true, addDisplay: false, editDisplay: false },
],
actions: [
{
name: '编辑',
icon: 'edit',
event: ({ row }) => stageRowEdit(row),
},
{
type: 'danger',
name: '删除',
icon: 'delete',
event: ({ row }) => stageRowDel(row),
},
],
},
pageData: {
total: 0,
currentPage: 1,
pageSize: 10,
},
data: [],
currentRow: {},
});
// //
const loadData = () => { const loadData = () => {
state.loading = true; state.loading = true;
@ -380,13 +274,6 @@ const rowUpdate = (row, index, done, loading) => {
}); });
}; };
//
//
const stageRefresh = () => {
// loadData();
app.$message.success('刷新成功');
};
const rowStatus = (row) => { const rowStatus = (row) => {
console.info('操作状态'); console.info('操作状态');
let parmer = { let parmer = {
@ -433,126 +320,10 @@ const rowDel = (row, index, done) => {
const rowClick = (row) => { const rowClick = (row) => {
state.currentRow = { ...row }; state.currentRow = { ...row };
stageShow.value = true;
console.info('rowClick', state.currentRow); console.info('rowClick', state.currentRow);
getStageList();
}; };
async function getStageList() { const stageHide = () => {
// stageState.loading = true; stageShow.value = false;
// getPlantingStage({ ...stageState.query, planId: state.currentRow.id })
// .then((res) => {
// if (res.code === 200) {
// const { current, size, total, records } = res.data;
// stageState.data = records || [];
// stageState.pageData = {
// currentPage: current || 1,
// pageSize: size || 10,
// total: total,
// };
// }
// })
// .catch((err) => {
// app.$message.error(err.msg);
// stageState.data = [];
// })
// .finally(() => {
// stageState.loading = false;
// });
}
const stageSearch = (params, done) => {
if (done) done();
stageState.query = params;
stageState.query.current = 1;
getStageList();
};
const stageSelection = (rows) => {
stageState.selection = rows;
};
const stageCurrent = (current) => {
stageState.query.current = current;
getStageList();
};
const stageSize = (size) => {
stageState.query.size = size;
getStageList();
};
const stageRowDel = (row, index, done) => {
if (isEmpty(row)) return;
app
.$confirm(`删除后信息将不可查看,确认要删除吗?`, '确定删除', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
})
.then(() => {
console.info('删除');
// delPlantingStage({ id: row.id })
// .then((res) => {
// if (res.code === 200) {
// app.$message.success('');
// getStageList();
// done();
// }
// })
// .catch((err) => {
// app.$message.error(err.msg);
// });
})
.catch(() => {});
};
const stageRowEdit = (row) => {
stateCrudRef.value.rowEdit(row);
};
const onStateAdd = () => {
if (!state.currentRow.id) {
app.$message.error('请选择种植产物');
return;
}
// stageInfoData.landName = state.currentRow.landName || '';
// stageInfoData.crop = state.currentRow.crop || '';
// stageInfoVisible.value = true;
stateCrudRef.value.rowAdd();
};
const stageRowSave = (row, done, loading) => {
row.planId = state.currentRow.planId;
console.info('stageRowSave', row);
// savePlantingStage({ ...row })
// .then((res) => {
// if (res.code === 200) {
// app.$message.success('');
// done();
// getStageList();
// }
// })
// .catch((err) => {
// app.$message.error(err.msg);
// })
// .finally(() => {
// loading();
// });
};
const stageRowUpdate = (row, index, done, loading) => {
console.info('stageRowUpdate');
// editPlantingStage(row)
// .then((res) => {
// if (res.code === 200) {
// app.$message.success('');
// done();
// getStageList();
// }
// })
// .catch((err) => {
// app.$message.error(err.msg);
// })
// .finally(() => {
// loading();
// });
}; };
</script> </script>

View File

@ -3,13 +3,14 @@
<div> <div>
<el-row :gutter="20"> <el-row :gutter="20">
<el-col :span="4"> <el-col :span="4">
<el-tree <!-- <el-tree
style="max-width: 600px" style="max-width: 600px"
:data="typeTree" :data="typeTree"
node-key="areaCode" node-key="areaCode"
:props="{ children: 'areaChildVOS', label: 'areaName' }" :props="{ children: 'areaChildVOS', label: 'areaName' }"
@node-click="handleNodeClick" @node-click="handleNodeClick"
/> /> -->
<custom-table-tree title="行政区域" :data="typeTree" :option="treeOption" @node-click="handleNodeClick" />
</el-col> </el-col>
<el-col :span="20"> <el-col :span="20">
<avue-crud <avue-crud
@ -126,35 +127,13 @@ const state = reactive({
currentRow: {}, currentRow: {},
}); });
let typeTree = ref([ const typeTree = ref([]);
// { const treeOption = ref({
// label: '', nodeKey: 'areaCode',
// id: '0', props: { children: 'areaChildVOS', label: 'areaName' },
// level: '0', });
// children: [ const townOptions = reactive([]);
// { const infoData = reactive({
// label: '1',
// level: '1',
// id: '01',
// children: [
// { label: '1', children: [], id: '0101', pId: '01', level: '2' },
// { label: '2', children: [], id: '0102', pId: '01', level: '2' },
// ],
// pId: '0',
// },
// { label: '2', level: '1', children: [], id: '02', pId: '0' },
// ],
// },
// {
// label: '1',
// id: '1',
// level: '0',
// children: [{ label: '1', children: [], id: '11', pId: '10', level: '1' }],
// },
]);
let townOptions = reactive([]);
let infoData = reactive({
countyId: '', countyId: '',
townId: '', townId: '',
name: '', name: '',

View File

@ -1,3 +0,0 @@
<template>
<div>开发中</div>
</template>

View File

@ -0,0 +1,259 @@
<template>
<div style="margin-top: 16px">
<el-dialog v-model="isShowVal" title="规划记录" width="1000" center @closed="stageClose">
<avue-crud
ref="listRef"
v-model="stageState.form"
v-model:search="stageState.query"
v-model:page="stageState.pageData"
:table-loading="stageState.loading"
:data="stageState.data"
:option="stageState.options"
@refresh-change="stageRefresh"
@search-reset="stageSearch"
@search-change="stageSearch"
@selection-change="stageSelection"
@current-change="stageCurrent"
@size-change="stageSize"
@row-del="stageRowDel"
@row-save="stageRowSave"
@row-update="stageRowUpdate"
>
<template #menu-left>
<!-- <el-button type="primary" icon="Plus" @click="onStateAdd">新增</el-button> -->
</template>
<template #planId="{ row }">
{{ row.planName }}
</template>
<template #menu="scope">
<custom-table-operate :actions="stageState.options.actions" :data="scope" />
</template>
</avue-crud>
</el-dialog>
</div>
</template>
<script setup>
import { onMounted, reactive, ref, watch } from 'vue';
import { useApp } from '@/hooks';
import { CRUD_OPTIONS } from '@/config';
import { useUserStore } from '@/store/modules/user';
import { getPlantingStage, savePlantingStage, editPlantingStage, delPlantingStage, getPlanHistory } from '@/apis/land.js';
import { isEmpty, imageToBase64, getAssetsFile, downloadFile } from '@/utils';
const props = defineProps({
isShow: {
type: Boolean,
default: false,
},
rowOriginal: {
type: Object,
default: () => {
return {};
},
},
});
const emit = defineEmits(['close']);
const { VITE_APP_BASE_API } = import.meta.env;
const app = useApp();
const UserStore = useUserStore();
const listRef = ref(null);
const stageOptions = reactive([
{ value: '0', label: '苗期' },
{ value: '1', label: '花果期' },
{ value: '2', label: '采收期' },
]);
const workOptions = reactive([
{ label: '作业计划1', value: '000001' },
{ label: '作业计划2', value: '000002' },
]);
const stageObj = reactive({
0: '苗期',
1: '花果期',
2: '采收期',
});
const isShowVal = ref(false);
let currentRow = reactive({});
const loadList = () => {
if (isShowVal.value) {
console.info('loadList', props);
getList();
}
};
onMounted(() => {
isShowVal.value = props.isShow;
currentRow = props.rowOriginal;
loadList();
// console.info('onMounted', props);
});
watch(
() => (props.isShow, props.rowOriginal),
() => {
isShowVal.value = props.isShow;
currentRow = props.rowOriginal;
console.info('watch', props);
loadList();
},
{ deep: true, immediate: true }
);
const stageState = reactive({
loading: false,
query: {
current: 1,
size: 10,
},
form: {},
options: {
...CRUD_OPTIONS,
addBtn: false,
selection: false,
column: [
{
label: '年度计划',
prop: 'planId',
type: 'select',
remote: false,
width: '160px',
showOverflowTooltip: true,
props: {
label: 'planName',
value: 'id',
},
dicHeaders: {
authorization: UserStore.token,
},
dicUrl: `${VITE_APP_BASE_API}/land-resource/annualManage/page`,
dicFormatter: (res) => res.data.records ?? [],
rules: [
{
required: true,
message: '请选择',
trigger: 'blur',
},
],
},
{ label: '供应商', prop: 'seedSupplier', addDisplay: false, editDisplay: true },
{ label: '种植日期', prop: 'planDate', addDisplay: true, editDisplay: true },
{ label: '种植产物', prop: 'crop', addDisplay: false, editDisplay: false },
],
actions: [
{
name: '编辑',
icon: 'edit',
event: ({ row }) => stageRowEdit(row),
},
],
},
pageData: {
total: 0,
currentPage: 1,
pageSize: 10,
},
data: [],
currentRow: {},
});
async function getList() {
stageState.loading = true;
getPlanHistory({ ...stageState.query, landId: currentRow.landId })
.then((res) => {
if (res.code === 200) {
const { current, size, total, records } = res.data;
stageState.data = records || [];
stageState.pageData = {
currentPage: current || 1,
pageSize: size || 10,
total: total,
};
}
})
.catch((err) => {
app.$message.error(err.msg);
stageState.data = [];
})
.finally(() => {
stageState.loading = false;
});
}
const stageSearch = (params, done) => {
if (done) done();
stageState.query = params;
stageState.query.current = 1;
getList();
};
const stageSelection = (rows) => {
stageState.selection = rows;
};
const stageCurrent = (current) => {
stageState.query.current = current;
getList();
};
const stageSize = (size) => {
stageState.query.size = size;
getList();
};
const stageRowEdit = (row) => {
listRef.value.rowEdit(row);
};
const onStateAdd = () => {
if (!currentRow.landId) {
app.$message.error('请选择种植规划');
return;
}
listRef.value.rowAdd();
};
const stageRowSave = (row, done, loading) => {
row.landId = currentRow.landId;
console.info('stageRowSave', row);
savePlantingStage({ ...row })
.then((res) => {
if (res.code === 200) {
app.$message.success('添加成功!');
done();
getList();
}
})
.catch((err) => {
app.$message.error(err.msg);
})
.finally(() => {
loading();
});
};
const stageRowUpdate = (row, index, done, loading) => {
console.info('stageRowUpdate');
editPlantingStage(row)
.then((res) => {
if (res.code === 200) {
app.$message.success('更新成功!');
done();
getList();
}
})
.catch((err) => {
app.$message.error(err.msg);
})
.finally(() => {
loading();
});
};
const stageClose = () => {
isShowVal.value = false;
emit('close');
};
</script>

View File

@ -78,12 +78,17 @@ const stageObj = reactive({
2: '采收期', 2: '采收期',
}); });
const handleWorkChange = async (value, form, done) => {
stageState.form.workTime = value.item?.workTime || '';
};
const isShowVal = ref(false); const isShowVal = ref(false);
let currentRow = reactive({}); let currentRow = reactive({});
const loadList = () => { const loadList = () => {
if (isShowVal.value) { if (isShowVal.value) {
console.info('loadList', props); console.info('loadList', props);
getStageList();
} }
}; };
onMounted(() => { onMounted(() => {
@ -107,13 +112,37 @@ const stageState = reactive({
query: { query: {
current: 1, current: 1,
size: 10, size: 10,
stage: null,
}, },
form: {}, form: {},
options: { options: {
...CRUD_OPTIONS, ...CRUD_OPTIONS,
addBtn: false, addBtn: false,
selection: false, selection: false,
group: [
{ label: '所属阶段', prop: 'stage' },
{ label: '作业类型', prop: 'workType' },
{ label: '作业时间', prop: 'operationDate' },
],
column: [ column: [
// {
// label: '',
// prop: 'cropId',
// type: 'select',
// remote: false,
// width: '160px',
// showOverflowTooltip: true,
// props: {
// label: 'crop',
// value: 'id',
// },
// dicHeaders: {
// authorization: UserStore.token,
// },
// dicUrl: `${VITE_APP_BASE_API}/land-resource/baseInfo/planTypePage?current=1&size=999`,
// dicFormatter: (res) => res.data.records ?? [],
// rules: [{ required: true, message: '', trigger: 'blur' }],
// },
{ {
label: '所属阶段', label: '所属阶段',
prop: 'stage', prop: 'stage',
@ -127,19 +156,42 @@ const stageState = reactive({
}, },
}, },
{ {
label: '作业计划', label: '作业类型',
prop: 'workId', prop: 'workId',
type: 'select', type: 'select',
search: true, search: false,
dicData: workOptions, remote: false,
rules: { width: '160px',
required: true, showOverflowTooltip: true,
message: '请选择', props: {
trigger: 'blur', label: 'workType',
value: 'id',
}, },
dicHeaders: {
authorization: UserStore.token,
},
dicUrl: `${VITE_APP_BASE_API}/land-resource/planManage/workPage?current=1&size=999`,
dicFormatter: (res) => res.data.records ?? [],
rules: { required: true, message: '请选择', trigger: 'blur' },
change: handleWorkChange,
},
{
label: '作业时间(多少天后)',
prop: 'workTime',
rules: { required: true, message: '请输入', trigger: 'blur' },
props: {
type: 'Number',
},
addDisabled: true,
editDisplay: false,
viewDisplay: false,
},
{
label: '作业时间',
prop: 'operationDate',
editDisplay: false,
addDisplay: false,
}, },
{ label: '作业时间', prop: 'coordinate', addDisplay: false, editDisplay: false },
{ label: '结束时间', prop: 'createTime', addDisplay: false, editDisplay: false },
], ],
actions: [ actions: [
{ {
@ -166,7 +218,7 @@ const stageState = reactive({
async function getStageList() { async function getStageList() {
stageState.loading = true; stageState.loading = true;
getPlantingStage({ ...stageState.query, planId: currentRow.currentRow.id }) getPlantingStage({ ...stageState.query, planId: currentRow.id })
.then((res) => { .then((res) => {
if (res.code === 200) { if (res.code === 200) {
const { current, size, total, records } = res.data; const { current, size, total, records } = res.data;
@ -245,7 +297,7 @@ const onStateAdd = () => {
}; };
const stageRowSave = (row, done, loading) => { const stageRowSave = (row, done, loading) => {
row.planId = currentRow.planId; row.planId = currentRow.id;
console.info('stageRowSave', row); console.info('stageRowSave', row);
savePlantingStage({ ...row }) savePlantingStage({ ...row })
.then((res) => { .then((res) => {

View File

@ -51,7 +51,8 @@
</template> </template>
</avue-crud> </avue-crud>
<stageList :is-show="stageShow" :row-original="stageRowVal" @close="stageHide"></stageList> <stageList :is-show="stageShow" :row-original="currentRowVal" @close="stageHide"></stageList>
<historyList :is-show="historyShow" :row-original="currentRowVal" @close="historyHide"></historyList>
</div> </div>
</template> </template>
<script setup> <script setup>
@ -71,7 +72,8 @@ import {
delPlantingStage, delPlantingStage,
} from '@/apis/land.js'; } from '@/apis/land.js';
import { isEmpty, imageToBase64, getAssetsFile, downloadFile } from '@/utils'; import { isEmpty, imageToBase64, getAssetsFile, downloadFile } from '@/utils';
import stageList from '../../component/plantPlan/compoent/stage.vue'; import stageList from '../../component/plantPlan/component/stage.vue';
import historyList from '../../component/plantPlan/component/history.vue';
const { VITE_APP_BASE_API } = import.meta.env; const { VITE_APP_BASE_API } = import.meta.env;
const app = useApp(); const app = useApp();
@ -90,7 +92,8 @@ const workOptions = reactive([
]); ]);
let stageShow = ref(false); let stageShow = ref(false);
let stageRowVal = reactive({}); let currentRowVal = reactive({});
let historyShow = ref(false);
const state = reactive({ const state = reactive({
loading: false, loading: false,
@ -229,6 +232,11 @@ const state = reactive({
icon: 'edit', icon: 'edit',
event: ({ row }) => toStage(row), event: ({ row }) => toStage(row),
}, },
{
name: '规划记录',
icon: 'Memo',
event: ({ row }) => toHistory(row),
},
{ {
type: 'danger', type: 'danger',
name: '删除', name: '删除',
@ -409,9 +417,9 @@ const rowDel = (row, index, done) => {
}; };
const toStage = (row) => { const toStage = (row) => {
stageRowVal = row; currentRowVal = row;
stageShow.value = true; stageShow.value = true;
console.info('toStage', stageRowVal); console.info('toStage', currentRowVal);
}; };
// //
@ -467,4 +475,12 @@ const rowClick = (row) => {
const stageHide = () => { const stageHide = () => {
stageShow.value = false; stageShow.value = false;
}; };
const toHistory = (row) => {
currentRowVal = row;
historyShow.value = true;
};
const historyHide = () => {
historyShow.value = false;
};
</script> </script>

View File

@ -91,31 +91,61 @@ const state = reactive({
overHidden: true, overHidden: true,
}, },
{ {
label: '地块名', label: '基地分类',
prop: 'p2', prop: 'type',
width: 200, type: 'select',
type: 'cascader', dicData: [
// hide: true, {
// addDisplay: true, label: '种植基地',
// editDisplay: true, value: 1,
// viewDisplay: false, },
// props: { {
// label: 'areaName', label: '养殖基地',
// value: 'areaCode', value: 2,
// children: 'areaChildVOS', },
// }, ],
// dicUrl: `${VITE_APP_BASE_API}/system/area/region?areaCode=530000`,
// dicHeaders: {
// authorization: UserStore.token,
// },
// dicFormatter: (res) => res.data ?? [],
rules: { rules: {
required: true, required: true,
message: '请选择', message: '请输入',
trigger: 'blur', trigger: 'blur',
}, },
overHidden: true,
}, },
{
label: '地块名',
prop: 'landName',
width: 200,
formslot: true,
rules: {
required: true,
message: '请输入',
trigger: 'blur',
},
},
// {
// label: '',
// prop: 'p2',
// width: 200,
// type: 'select',
// // addDisplay: true,
// // editDisplay: true,
// // viewDisplay: false,
// // props: {
// // label: 'areaName',
// // value: 'areaCode',
// // children: 'areaChildVOS',
// // },
// // dicUrl: `${VITE_APP_BASE_API}/system/area/region?areaCode=530000`,
// // dicHeaders: {
// // authorization: UserStore.token,
// // },
// // dicFormatter: (res) => res.data ?? [],
// rules: {
// required: true,
// message: '',
// trigger: 'blur',
// },
// overHidden: true,
// },
{ {
label: '区域位置', label: '区域位置',
prop: 'p3', prop: 'p3',
@ -136,26 +166,6 @@ const state = reactive({
trigger: 'blur', trigger: 'blur',
}, },
}, },
{
label: '基地分类',
prop: 'type',
type: 'select',
dicData: [
{
label: '种植基地',
value: 1,
},
{
label: '养殖基地',
value: 2,
},
],
rules: {
required: true,
message: '请输入',
trigger: 'blur',
},
},
{ {
label: '状态', label: '状态',
prop: 'status', prop: 'status',
@ -273,8 +283,8 @@ const loadData = async () => {
await sleep(500); await sleep(500);
state.data = mockData( state.data = mockData(
{ {
p1: '202501基地', p1: '耿马镇一号基地',
p2: '耿马镇1号地块', p2: '耿马镇2025001号地块',
p3: '耿马傣族佤族自治县/耿马镇', p3: '耿马傣族佤族自治县/耿马镇',
p4: '1000', p4: '1000',
p5: '张三', p5: '张三',

View File

@ -3,7 +3,7 @@
* @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-03-20 14:24:31
*/ */
import { defineConfig, loadEnv } from 'vite'; import { defineConfig, loadEnv } from 'vite';

View File

@ -21,6 +21,7 @@
"@wangeditor/editor-for-vue": "^5.1.12", "@wangeditor/editor-for-vue": "^5.1.12",
"axios": "^1.6.5", "axios": "^1.6.5",
"echarts": "^5.6.0", "echarts": "^5.6.0",
"echarts-gl": "^2.0.9",
"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: 75 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 865 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -80,7 +80,7 @@ const chartsData = reactive({
}, },
// //
grid: { grid: {
x: '10%', x: '16%',
x2: '5%', x2: '5%',
y: '15%', y: '15%',
y2: '15%', y2: '15%',

View File

@ -6,16 +6,17 @@
<script setup> <script setup>
import { ref, reactive, onMounted } from 'vue'; import { ref, reactive, onMounted } from 'vue';
const dataList = reactive([ const dataList = reactive([
{ name: '打车费', val: 1230, itemStyle: { color: 'rgba(56, 136, 235, 1)' } }, { name: '肉类', val: 1230, itemStyle: { color: 'rgba(56, 136, 235, 1)' } },
{ name: '住宿费', val: 300, itemStyle: { color: 'rgba(113, 70, 159, 1)' } }, { name: '水果', val: 300, itemStyle: { color: 'rgba(113, 70, 159, 1)' } },
{ name: '办公费', val: 800, itemStyle: { color: 'rgba(237, 171, 87, 1)' } }, { name: '蔬菜', val: 800, itemStyle: { color: 'rgba(237, 171, 87, 1)' } },
{ name: '差旅费', val: 500, itemStyle: { color: 'rgba(231, 89, 77, 1)' } }, { name: '水产', val: 500, itemStyle: { color: 'rgba(231, 89, 77, 1)' } },
{ name: '谷物', val: 600, itemStyle: { color: 'rgba(231, 89, 77, 1)' } },
]); ]);
const heightProportion = ref(0.3); // const heightProportion = ref(0.3); //
// series-surface.parametricEquation // series-surface.parametricEquation
// #region // #region
const getParametricEquation = (startRatio, endRatio, isSelected, isHovered, k, height) => { const getParametricEquation = (startRatio, endRatio, isSelected, isHovered, k, height, radiusScale) => {
// //
let midRatio = (startRatio + endRatio) / 3; let midRatio = (startRatio + endRatio) / 3;
@ -54,22 +55,22 @@ const getParametricEquation = (startRatio, endRatio, isSelected, isHovered, k, h
x: function (u, v) { x: function (u, v) {
if (u < startRadian) { if (u < startRadian) {
return offsetX + Math.cos(startRadian) * (1 + Math.cos(v) * k) * hoverRate; return offsetX + Math.cos(startRadian) * (1 + Math.cos(v) * k) * hoverRate * radiusScale;
} }
if (u > endRadian) { if (u > endRadian) {
return offsetX + Math.cos(endRadian) * (1 + Math.cos(v) * k) * hoverRate; return offsetX + Math.cos(endRadian) * (1 + Math.cos(v) * k) * hoverRate * radiusScale;
} }
return offsetX + Math.cos(u) * (1 + Math.cos(v) * k) * hoverRate; return offsetX + Math.cos(u) * (1 + Math.cos(v) * k) * hoverRate * radiusScale;
}, },
y: function (u, v) { y: function (u, v) {
if (u < startRadian) { if (u < startRadian) {
return offsetY + Math.sin(startRadian) * (1 + Math.cos(v) * k) * hoverRate; return offsetY + Math.sin(startRadian) * (1 + Math.cos(v) * k) * hoverRate * radiusScale;
} }
if (u > endRadian) { if (u > endRadian) {
return offsetY + Math.sin(endRadian) * (1 + Math.cos(v) * k) * hoverRate; return offsetY + Math.sin(endRadian) * (1 + Math.cos(v) * k) * hoverRate * radiusScale;
} }
return offsetY + Math.sin(u) * (1 + Math.cos(v) * k) * hoverRate; return offsetY + Math.sin(u) * (1 + Math.cos(v) * k) * hoverRate * radiusScale;
}, },
z: function (u, v) { z: function (u, v) {
@ -86,7 +87,7 @@ const getParametricEquation = (startRatio, endRatio, isSelected, isHovered, k, h
// #endregion // #endregion
// 3D // 3D
const getPie3D = (pieData, internalDiameterRatio) => { const getPie3D = (pieData, internalDiameterRatio, radiusScale = 1.8) => {
let series = []; let series = [];
let sumValue = 0; let sumValue = 0;
let startValue = 0; let startValue = 0;
@ -138,7 +139,8 @@ const getPie3D = (pieData, internalDiameterRatio) => {
false, false,
false, false,
k, k,
series[i].pieData.value series[i].pieData.value,
radiusScale
); );
startValue = endValue; startValue = endValue;
@ -148,8 +150,8 @@ const getPie3D = (pieData, internalDiameterRatio) => {
const midRadian = (series[i].pieData.startRatio + series[i].pieData.endRatio) * Math.PI; const midRadian = (series[i].pieData.startRatio + series[i].pieData.endRatio) * Math.PI;
// v=0 // v=0
const radius = 1 + k; // const radius = 1 + k; //
const posX = Math.cos(midRadian) * radius; const posX = Math.cos(midRadian) * radius * radiusScale;
const posY = Math.sin(midRadian) * radius; const posY = Math.sin(midRadian) * radius * radiusScale;
// //
const posZ = heightProportion.value * series[i].pieData.value; const posZ = heightProportion.value * series[i].pieData.value;
let flag = (midRadian >= 0 && midRadian <= Math.PI / 2) || (midRadian >= (3 * Math.PI) / 2 && midRadian <= Math.PI * 2) ? 1 : -1; let flag = (midRadian >= 0 && midRadian <= Math.PI / 2) || (midRadian >= (3 * Math.PI) / 2 && midRadian <= Math.PI * 2) ? 1 : -1;
@ -169,15 +171,15 @@ const getPie3D = (pieData, internalDiameterRatio) => {
{ {
type: 'scatter3D', type: 'scatter3D',
label: { label: {
show: true, show: true, //label
distance: 0, distance: 0,
position: 'center', position: 'center',
textStyle: { textStyle: {
color: '#ffffff', color: '#ffffff',
backgroundColor: color, backgroundColor: color,
borderWidth: 2, borderWidth: 2,
fontSize: 14, fontSize: 8,
padding: 10, padding: 4,
borderRadius: 4, borderRadius: 4,
}, },
formatter: '{b}', formatter: '{b}',
@ -241,8 +243,8 @@ const getPie3D = (pieData, internalDiameterRatio) => {
}, },
parametricEquation: { parametricEquation: {
u: { u: {
min: 0.74, // 92% min: 0.94, // 92%
max: 0.75, // 100% max: 0.95, // 100%
step: 0.0001, step: 0.0001,
}, },
v: { v: {
@ -277,8 +279,8 @@ const getPie3D = (pieData, internalDiameterRatio) => {
}, },
parametricEquation: { parametricEquation: {
u: { u: {
min: 0.54, // 92% min: 0.94, // 92%
max: 0.55, // 100% max: 0.95, // 100%
step: 0.0001, step: 0.0001,
}, },
v: { v: {
@ -309,7 +311,6 @@ dataList.forEach((item) => {
const chartsData = reactive({ const chartsData = reactive({
option: { option: {
backgroundColor: '#2d58e4',
xAxis3D: { xAxis3D: {
min: -1.5, min: -1.5,
max: 1.5, max: 1.5,
@ -325,7 +326,7 @@ const chartsData = reactive({
grid3D: { grid3D: {
show: false, show: false,
boxHeight: 4, boxHeight: 4,
bottom: '50%', top: '10%',
viewControl: { viewControl: {
distance: 380, distance: 380,
alpha: 25, alpha: 25,

View File

@ -7,7 +7,7 @@
<div class="left-charts-item"> <div class="left-charts-item">
<customBack top-title="生产经营主体类别统计" :top-postion="'left'"> <customBack top-title="生产经营主体类别统计" :top-postion="'left'">
<template #back> <template #back>
<!-- <entitiesCategoryCharts></entitiesCategoryCharts> --> <entitiesCategoryCharts></entitiesCategoryCharts>
</template> </template>
</customBack> </customBack>
</div> </div>

View File

@ -0,0 +1,131 @@
<template>
<div class="cases-alerts-warp">
<div class="cases-alerts" :style="{ 'background-image': 'url(' + getAssetsFile('images/inputs/partbg1.png') + ')' }">
<div class="cases-alerts-content">
<div class="cases-alerts-item-pos">
<template v-for="(n, index) in datalist" :key="index">
<div class="cases-alerts-item">
<div class="header" :style="{ 'background-image': 'url(' + getAssetsFile('images/inputs/partbg2.png') + ')' }">
<div class="title">{{ n.title }}</div>
</div>
<div class="content">
<template v-for="(m, mindex) in n.valStr" :key="mindex">
<div class="content-item" :style="{ 'background-image': 'url(' + getAssetsFile('images/inputs/partbg3.png') + ')' }">
<div class="num">{{ m }}</div>
</div>
</template>
</div>
</div>
</template>
</div>
</div>
</div>
</div>
</template>
<script setup>
import { ref, reactive, onMounted } from 'vue';
import { isEmpty, getAssetsFile } from '@/utils';
const datalist = reactive([
{ title: '案件次数', val: 100 },
{ title: '预警次数', val: 236 },
]);
onMounted(() => {
if (datalist.length && datalist.length > 0) {
datalist.forEach((m) => {
let valStr = '';
if (m.val < 1000 && m.val >= 100) {
valStr = '0' + m.val;
} else if (m.val < 100 && m.val >= 10) {
valStr = '00' + m.val;
} else if (m.val < 10) {
valStr = '000' + m.val;
} else {
valStr = m.val.toFixed(0);
}
m.valStr = [...valStr];
// console.info('valStr', m.valStr);
});
}
});
</script>
<style lang="scss" scoped>
div {
box-sizing: border-box;
}
.cases-alerts-warp {
height: 100%;
padding: 8px;
.cases-alerts {
width: 100%;
height: 100%;
background-size: 100% 100%;
background-repeat: no-repeat;
.cases-alerts-content {
width: 100%;
height: 100%;
padding: 0 20px;
display: inline-flex;
justify-content: center;
flex-direction: column;
.cases-alerts-item-pos {
width: 100%;
display: inline-flex;
justify-content: space-around;
}
.cases-alerts-item {
display: inline-block;
width: calc((100% - 20px) / 2);
.header,
.content {
display: inline-flex;
width: 100%;
}
.header {
background-size: 100% 100%;
background-repeat: no-repeat;
line-height: 32px;
height: 32px;
display: inline-block;
width: 100%;
.title {
text-align: center;
font-size: 16px;
font-weight: bold;
transform: skewX(-8deg);
background: linear-gradient(to bottom, '#ff7e5f', '#548fff');
-webkit-background-clip: text;
color: #fff;
letter-spacing: 8px;
text-shadow: -6px 0 0 1px #add8f1;
}
}
.content {
justify-content: space-around;
margin-top: 50%;
.content-item {
height: 36px;
display: inline-block;
width: calc((100% - 20px) / 4);
background-size: 100% 100%;
background-repeat: no-repeat;
line-height: 36px;
text-align: center;
.num {
text-align: center;
font-size: 20px;
font-weight: bold;
transform: skewX(-8deg);
background: linear-gradient(to bottom, '#ff7e5f', '#548fff');
-webkit-background-clip: text;
color: #fff;
text-shadow: -6px 0 0 1px #add8f1;
}
}
}
}
}
}
}
</style>

View File

@ -0,0 +1,171 @@
<template>
<div class="demo roll-list-land-plan" 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 }">
<div class="item-content">
<div class="label">{{ item.title }}</div>
<div class="val">
<!-- <el-progress :percentage="50" :show-text="false" :indeterminate="false" :stroke-width="12" color="#6cd1f9" :duration="8" /> -->
<div class="progress-warp" :style="{ width: item.percent + 'px' }">
<div class="progress"></div>
</div>
</div>
</div>
</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([
{ title: '农药', value: 357 },
{ title: '肥料', value: 159 },
{ title: '种源', value: 516 },
{ title: '兽药', value: 82 },
{ title: '农机', value: 45 },
]);
let datalist = computed(() => {
return list.map((m) => {
return { ...m, percent: parseInt(Number(m.value / max.value) * 200) };
});
});
let max = computed(() => {
let valueList = new Set(list.map((item) => item.value));
let sortValue = [...valueList].sort((a, b) => b - a) || [];
// console.info('valueList', sortValue);
return sortValue.length ? sortValue[0] : 0;
});
const listKeys = reactive(['title', 'value']);
const listKeysHeader = reactive({
title: '分类',
value: '数量',
});
const classOptions = {
singleHeight: 48,
};
onMounted(() => {});
</script>
<style scoped lang="scss">
.roll-list-land-plan {
margin-top: 8px;
::v-deep() {
.el-progress-bar__outer {
background: transparent;
}
}
.scroll-wrap {
height: 90%;
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: #6cd1f9 !important;
}
&.zebra-b {
background: #051225 !important;
}
}
}
.item-warp {
display: inline-flex;
justify-content: space-around;
.item-td {
display: inline-block;
vertical-align: middle;
text-align: center;
color: #fff;
}
.item-content {
width: 100%;
display: inline-flex;
justify-content: flex-start;
margin: 8px 0;
.label,
.val {
display: inline-block;
vertical-align: middle;
}
.label {
width: 50px;
color: #fff;
}
.val {
width: calc(100% - 50px);
.progress-warp {
.progress {
height: 10px;
border-radius: 6px;
background: linear-gradient(90deg, #45bfe9 0%, #01589c 100%);
animation: expandWidth 1s ease-in-out forwards;
}
@keyframes expandWidth {
from {
width: 0;
}
to {
width: 100%;
}
}
}
}
}
}
.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

@ -6,7 +6,9 @@
<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'">
<template #back> </template> <template #back>
<inputsType></inputsType>
</template>
</customBack> </customBack>
</div> </div>
<div class="left-charts-item"> <div class="left-charts-item">
@ -30,7 +32,9 @@
<el-col :span="6" class="right-charts"> <el-col :span="6" class="right-charts">
<div class="right-charts-item"> <div class="right-charts-item">
<customBack top-title="案件次数" :top-postion="'right'"> <customBack top-title="案件次数" :top-postion="'right'">
<template #back> </template> <template #back>
<casesAlerts></casesAlerts>
</template>
</customBack> </customBack>
</div> </div>
<div class="right-charts-item"> <div class="right-charts-item">
@ -61,6 +65,8 @@ import inputsGmp from './components/inputsGmp.vue';
import landbreedCharts from './components/landbreedCharts.vue'; import landbreedCharts from './components/landbreedCharts.vue';
import monthlyuseCharts from './components/monthlyuseCharts.vue'; import monthlyuseCharts from './components/monthlyuseCharts.vue';
import dealerDistributionCharts from './components/dealerDistributionCharts.vue'; import dealerDistributionCharts from './components/dealerDistributionCharts.vue';
import casesAlerts from './components/casesAlerts.vue';
import inputsType from './components/inputsType.vue';
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.data-home-index { .data-home-index {

View File

@ -1,12 +1,12 @@
<template> <template>
<div class="distribution-charts"> <div class="distribution-charts">
<custom-echart-pie :chart-data="plantBreed.valData" height="100%" :option="plantBreed.option" /> <custom-echart-pie :chart-data="chartsData.valData" height="100%" :option="chartsData.option" />
</div> </div>
</template> </template>
<script setup> <script setup>
import { ref, reactive, onMounted } from 'vue'; import { ref, reactive, onMounted } from 'vue';
const plantBreed = reactive({ const chartsData = reactive({
option: { option: {
color: ['#3685fe', '#41b879', '#ffd500'], color: ['#3685fe', '#41b879', '#ffd500'],
title: { title: {
@ -42,6 +42,9 @@ const plantBreed = reactive({
itemStyle: { itemStyle: {
borderRadius: 5, borderRadius: 5,
}, },
// animationDuration: 15000,
// //
// animationEasing: 'elasticOut',
}, },
], ],
}, },

View File

@ -0,0 +1,65 @@
<template>
<div class="insect-pests-charts">
<custom-echart-bar :chart-data="chartsData.valData" height="100%" :option="chartsData.option" />
</div>
</template>
<script setup>
import { ref, reactive, onMounted } from 'vue';
const chartsData = reactive({
option: {
grid: {
left: '3%',
right: '4%',
bottom: '2%',
top: '18%',
containLabel: true,
},
title: {
text: ' ',
textStyle: {
color: '#333',
},
},
label: {
color: '#333',
},
barStyle: {
barWidth: 15,
itemStyle: {
borderRadius: [8, 8, 0, 0], //
},
color: {
type: 'linear', // 线
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [
{ offset: 0, color: '#45bfe9' },
{ offset: 1, color: '#01589c' },
],
global: false, // false
},
},
legend: {
show: false,
},
},
valData: [
{ value: 80, type: '经销商', name: '耿马镇' },
{ value: 105, type: '经销商', name: '勐撒镇' },
{ value: 100, type: '经销商', name: '勐永镇' },
{ value: 125, type: '经销商', name: '孟定镇' },
{ value: 217, type: '经销商', name: '勐简乡' },
{ value: 200, type: '经销商', name: '贺派乡' },
{ value: 155, type: '经销商', name: '四排山乡' },
{ value: 80, type: '经销商', name: '芒洪乡' },
{ value: 105, type: '经销商', name: '大兴乡' },
],
});
</script>
<style lang="scss" scoped>
.insect-pests-charts {
height: 100%;
}
</style>

View File

@ -0,0 +1,74 @@
<template>
<div class="plant-type-charts">
<custom-echart-pie :chart-data="chartsData.valData" height="100%" :option="chartsData.option" />
</div>
</template>
<script setup>
import { ref, reactive, onMounted } from 'vue';
const chartsData = reactive({
option: {
color: ['#3685fe', '#41b879', '#ffd500'],
title: {
text: ' ',
textStyle: {
color: '#333',
},
},
legend: {
data: ['甘蔗', '菠萝', '土豆', '番茄', '白菜', '其他'],
right: '0', // 10%
top: 'middle', //
orient: 'vertical', //
itemWidth: 15, //
itemHeight: 8, //
textStyle: {
fontSize: 10, //
color: '#fff', //
},
},
label: {
color: '#333',
},
series: [
{
type: 'pie',
radius: [20, 80],
roseType: 'area',
center: ['40%', '50%'],
label: {
show: false,
},
itemStyle: {
borderRadius: 5,
},
// animationDuration: 15000,
// //
// animationEasing: 'elasticOut',
},
],
},
valData: [
{ value: 205.6, name: '甘蔗' },
{ value: 308.7, name: '菠萝' },
{ value: 359.6, name: '土豆' },
{ value: 452.6, name: '番茄' },
{ value: 388.9, name: '白菜' },
{ value: 512.5, name: '其他' },
],
});
onMounted(() => {
if (chartsData.valData && chartsData.valData.length) {
chartsData.valData.forEach((m, index) => {
let num = 100;
m.value = (Number(m.value) + Math.random() + num).toFixed(2);
});
}
});
</script>
<style lang="scss" scoped>
.plant-type-charts {
height: 100%;
}
</style>

View File

@ -4,15 +4,53 @@
<template #center> <template #center>
<el-row style="width: 100%; height: 100%"> <el-row style="width: 100%; height: 100%">
<el-col :span="6" class="left-charts"> <el-col :span="6" class="left-charts">
<div class="left-charts-item"></div> <div class="left-charts-item">
<div class="left-charts-item"></div> <customBack top-title="智慧种植种类分析" :top-postion="'left'">
<div class="left-charts-item"></div> <template #back>
<plantTypeCharts></plantTypeCharts>
</template>
</customBack>
</div>
<div class="left-charts-item">
<customBack top-title="昆虫害监测" :top-postion="'left'">
<template #back></template>
</customBack>
</div>
<div class="left-charts-item">
<customBack top-title="病理害监测" :top-postion="'left'">
<template #back></template>
</customBack>
</div>
</el-col>
<el-col :span="12">
<el-row style="height: 60%">
<el-col :span="24"> 1-1</el-col>
</el-row>
<el-row style="height: 40%">
<el-col :span="12">
<customBack top-title="水肥检测分析" :top-postion="'left'"> <template #back></template> </customBack>
</el-col>
<el-col :span="12">
<customBack top-title="智慧水肥灌溉" :top-postion="'right'"> <template #back></template> </customBack>
</el-col>
</el-row>
</el-col> </el-col>
<el-col :span="12"></el-col>
<el-col :span="6" class="right-charts"> <el-col :span="6" class="right-charts">
<div class="right-charts-item"></div> <div class="right-charts-item">
<div class="right-charts-item"></div> <customBack top-title="智慧监控 A区 QQI" :top-postion="'right'">
<div class="right-charts-item"></div> <template #back></template>
</customBack>
</div>
<div class="right-charts-item">
<customBack top-title="种植产量分析" :top-postion="'right'">
<template #back></template>
</customBack>
</div>
<div class="right-charts-item">
<customBack top-title="水质检测分析" :top-postion="'right'">
<template #back></template>
</customBack>
</div>
</el-col> </el-col>
</el-row> </el-row>
</template> </template>
@ -21,6 +59,8 @@
</template> </template>
<script setup> <script setup>
import baseBg from '@/components/baseBg.vue'; import baseBg from '@/components/baseBg.vue';
import customBack from '@/components/customBack.vue';
import plantTypeCharts from './components/plantTypeCharts.vue';
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.data-home-index { .data-home-index {

View File

@ -1601,6 +1601,11 @@ class-utils@^0.3.5:
isobject "^3.0.0" isobject "^3.0.0"
static-extend "^0.1.1" static-extend "^0.1.1"
claygl@^1.2.1:
version "1.3.0"
resolved "https://registry.npmmirror.com/claygl/-/claygl-1.3.0.tgz#7a6e2903210519ac358848f5d78070ed211685f3"
integrity sha512-+gGtJjT6SSHD2l2yC3MCubW/sCV40tZuSs5opdtn79vFSGUgp/lH139RNEQ6Jy078/L0aV8odCw8RSrUcMfLaQ==
clone-regexp@^1.0.0: clone-regexp@^1.0.0:
version "1.0.1" version "1.0.1"
resolved "https://registry.npmmirror.com/clone-regexp/-/clone-regexp-1.0.1.tgz#051805cd33173375d82118fc0918606da39fd60f" resolved "https://registry.npmmirror.com/clone-regexp/-/clone-regexp-1.0.1.tgz#051805cd33173375d82118fc0918606da39fd60f"
@ -2086,6 +2091,14 @@ dunder-proto@^1.0.0, dunder-proto@^1.0.1:
es-errors "^1.3.0" es-errors "^1.3.0"
gopd "^1.2.0" gopd "^1.2.0"
echarts-gl@^2.0.9:
version "2.0.9"
resolved "https://registry.npmmirror.com/echarts-gl/-/echarts-gl-2.0.9.tgz#ee228a6c7520a6fb7bbb71ea94394f3637ade033"
integrity sha512-oKeMdkkkpJGWOzjgZUsF41DOh6cMsyrGGXimbjK2l6Xeq/dBQu4ShG2w2Dzrs/1bD27b2pLTGSaUzouY191gzA==
dependencies:
claygl "^1.2.1"
zrender "^5.1.1"
echarts@^5.6.0: echarts@^5.6.0:
version "5.6.0" version "5.6.0"
resolved "https://registry.npmmirror.com/echarts/-/echarts-5.6.0.tgz#2377874dca9fb50f104051c3553544752da3c9d6" resolved "https://registry.npmmirror.com/echarts/-/echarts-5.6.0.tgz#2377874dca9fb50f104051c3553544752da3c9d6"
@ -6686,7 +6699,7 @@ yocto-queue@^0.1.0:
resolved "https://registry.npmmirror.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" resolved "https://registry.npmmirror.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"
integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==
zrender@5.6.1: zrender@5.6.1, zrender@^5.1.1:
version "5.6.1" version "5.6.1"
resolved "https://registry.npmmirror.com/zrender/-/zrender-5.6.1.tgz#e08d57ecf4acac708c4fcb7481eb201df7f10a6b" resolved "https://registry.npmmirror.com/zrender/-/zrender-5.6.1.tgz#e08d57ecf4acac708c4fcb7481eb201df7f10a6b"
integrity sha512-OFXkDJKcrlx5su2XbzJvj/34Q3m6PvyCZkVPHGYpcCJ52ek4U/ymZyfuV1nKE23AyBJ51E/6Yr0mhZ7xGTO4ag== integrity sha512-OFXkDJKcrlx5su2XbzJvj/34Q3m6PvyCZkVPHGYpcCJ52ek4U/ymZyfuV1nKE23AyBJ51E/6Yr0mhZ7xGTO4ag==