合并
@ -5,7 +5,7 @@ VITE_APP_TITLE = 煤科建管平台
|
|||||||
VITE_APP_ENV = 'development'
|
VITE_APP_ENV = 'development'
|
||||||
|
|
||||||
# 开发环境
|
# 开发环境
|
||||||
VITE_APP_BASE_API = 'http://192.168.110.209:8899'
|
VITE_APP_BASE_API = 'http://192.168.110.180:8899'
|
||||||
|
|
||||||
# 无人机接口地址
|
# 无人机接口地址
|
||||||
|
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
"diagram-js": "12.3.0",
|
"diagram-js": "12.3.0",
|
||||||
"didi": "9.0.2",
|
"didi": "9.0.2",
|
||||||
"echarts": "5.5.0",
|
"echarts": "5.5.0",
|
||||||
|
"echarts-gl": "^2.0.9",
|
||||||
"element-plus": "2.8.8",
|
"element-plus": "2.8.8",
|
||||||
"esbuild": "^0.25.0",
|
"esbuild": "^0.25.0",
|
||||||
"ezuikit-js": "^8.1.10",
|
"ezuikit-js": "^8.1.10",
|
||||||
|
93
src/api/tender/index.ts
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
import request from '@/utils/request';
|
||||||
|
import { AxiosPromise } from 'axios';
|
||||||
|
|
||||||
|
//获取版本
|
||||||
|
export const obtainAllVersionNumbers = (query: any): AxiosPromise<any> => {
|
||||||
|
return request({
|
||||||
|
url: '/tender/tenderPlanLimitList/obtainAllVersionNumbers',
|
||||||
|
method: 'get',
|
||||||
|
params: query
|
||||||
|
});
|
||||||
|
};
|
||||||
|
//获取sheet
|
||||||
|
export const sheetList = (query: any): AxiosPromise<any> => {
|
||||||
|
return request({
|
||||||
|
url: '/tender/tenderPlanLimitList/sheetList',
|
||||||
|
method: 'get',
|
||||||
|
params: query
|
||||||
|
});
|
||||||
|
};
|
||||||
|
//获取表格数据
|
||||||
|
export const getTableList = (query: any): AxiosPromise<any> => {
|
||||||
|
return request({
|
||||||
|
url: '/tender/tenderPlanLimitList/list',
|
||||||
|
method: 'get',
|
||||||
|
params: query
|
||||||
|
});
|
||||||
|
};
|
||||||
|
//修改单价数据
|
||||||
|
export const updatePrice = (query: any): AxiosPromise<any> => {
|
||||||
|
return request({
|
||||||
|
url: '/tender/tenderPlanLimitList',
|
||||||
|
method: 'put',
|
||||||
|
data: query
|
||||||
|
});
|
||||||
|
};
|
||||||
|
//导入
|
||||||
|
export const importExcelFile = (query: any, data: any): AxiosPromise<any> => {
|
||||||
|
return request({
|
||||||
|
url: '/tender/tenderPlanLimitList/importExcelFile',
|
||||||
|
method: 'post',
|
||||||
|
params: query,
|
||||||
|
data
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
//招标计划列表
|
||||||
|
|
||||||
|
export const tenderPlanList = (query: any): AxiosPromise<any> => {
|
||||||
|
return request({
|
||||||
|
url: '/tender/biddingPlan/list',
|
||||||
|
method: 'get',
|
||||||
|
params: query
|
||||||
|
});
|
||||||
|
};
|
||||||
|
//新增招标计划
|
||||||
|
export const addTenderPlan = (query: any): AxiosPromise<any> => {
|
||||||
|
return request({
|
||||||
|
url: '/tender/biddingPlan',
|
||||||
|
method: 'post',
|
||||||
|
data: query
|
||||||
|
});
|
||||||
|
};
|
||||||
|
//删除招标计划
|
||||||
|
export const delTenderPlan = (query: any): AxiosPromise<any> => {
|
||||||
|
return request({
|
||||||
|
url: '/tender/biddingPlan/' + query.ids,
|
||||||
|
method: 'delete'
|
||||||
|
});
|
||||||
|
};
|
||||||
|
//修改招标计划
|
||||||
|
export const updateTenderPlan = (query: any): AxiosPromise<any> => {
|
||||||
|
return request({
|
||||||
|
url: '/tender/biddingPlan',
|
||||||
|
method: 'put',
|
||||||
|
data: query
|
||||||
|
});
|
||||||
|
};
|
||||||
|
//弹窗数据
|
||||||
|
export const treeList = (query: any): AxiosPromise<any> => {
|
||||||
|
return request({
|
||||||
|
url: '/tender/tenderPlanLimitList/getTree',
|
||||||
|
method: 'get',
|
||||||
|
params: query
|
||||||
|
});
|
||||||
|
};
|
||||||
|
//获取招标计划详情
|
||||||
|
export const getTenderPlanDetail = (query: any): AxiosPromise<any> => {
|
||||||
|
return request({
|
||||||
|
url: '/tender/biddingPlan/getMore',
|
||||||
|
method: 'get',
|
||||||
|
params: query
|
||||||
|
});
|
||||||
|
};
|
BIN
src/assets/large/down.png
Normal file
After Width: | Height: | Size: 438 B |
BIN
src/assets/large/title_bottom.png
Normal file
After Width: | Height: | Size: 323 B |
BIN
src/assets/large/title_icon.png
Normal file
After Width: | Height: | Size: 731 B |
BIN
src/assets/large/top1.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
src/assets/large/top2.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
src/assets/large/top3.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
BIN
src/assets/large/top4.png
Normal file
After Width: | Height: | Size: 2.0 KiB |
BIN
src/assets/large/up.png
Normal file
After Width: | Height: | Size: 386 B |
169
src/components/EchartBox/index.vue
Normal file
@ -0,0 +1,169 @@
|
|||||||
|
<template>
|
||||||
|
<div ref="echartBox" class="echarts"></div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import china from '@/assets/china.json';
|
||||||
|
import cq from '@/assets/cq.json';
|
||||||
|
import { ref, onMounted, watchEffect, onBeforeUnmount } from 'vue';
|
||||||
|
import * as echarts from 'echarts/core';
|
||||||
|
import {
|
||||||
|
BarChart, // 柱状图
|
||||||
|
// 系列类型的定义后缀都为 SeriesOption
|
||||||
|
BarSeriesOption,
|
||||||
|
LineChart, // 折线图
|
||||||
|
LineSeriesOption,
|
||||||
|
PieChart, // 饼图
|
||||||
|
PieSeriesOption,
|
||||||
|
PictorialBarChart,
|
||||||
|
MapChart,
|
||||||
|
ScatterChart,
|
||||||
|
EffectScatterChart,
|
||||||
|
LinesChart
|
||||||
|
} from 'echarts/charts';
|
||||||
|
import {
|
||||||
|
// 组件类型的定义后缀都为 ComponentOption
|
||||||
|
// 标题
|
||||||
|
TitleComponent,
|
||||||
|
TitleComponentOption,
|
||||||
|
// 提示框
|
||||||
|
TooltipComponent,
|
||||||
|
TooltipComponentOption,
|
||||||
|
// 直角坐标系
|
||||||
|
GridComponent,
|
||||||
|
GridComponentOption,
|
||||||
|
// 图例
|
||||||
|
LegendComponent,
|
||||||
|
LegendComponentOption,
|
||||||
|
// 数据集组件
|
||||||
|
DatasetComponent,
|
||||||
|
DatasetComponentOption,
|
||||||
|
// 内置数据转换器组件 (filter, sort)
|
||||||
|
TransformComponent,
|
||||||
|
DataZoomComponent,
|
||||||
|
DataZoomComponentOption,
|
||||||
|
// 极坐标
|
||||||
|
PolarComponent,
|
||||||
|
PolarComponentOption,
|
||||||
|
MarkLineComponentOption,
|
||||||
|
MarkLineComponent,
|
||||||
|
// MarkPoint
|
||||||
|
MarkPointComponent,
|
||||||
|
MarkPointComponentOption,
|
||||||
|
// VisualMap
|
||||||
|
VisualMapComponent,
|
||||||
|
VisualMapComponentOption,
|
||||||
|
// GeoComponent
|
||||||
|
GeoComponent,
|
||||||
|
GeoComponentOption
|
||||||
|
} from 'echarts/components';
|
||||||
|
import { LabelLayout, UniversalTransition } from 'echarts/features';
|
||||||
|
import { CanvasRenderer } from 'echarts/renderers';
|
||||||
|
import 'echarts-gl';
|
||||||
|
|
||||||
|
// 通过 ComposeOption 来组合出一个只有必须组件和图表的 Option 类型
|
||||||
|
type ECOption = echarts.ComposeOption<
|
||||||
|
| BarSeriesOption
|
||||||
|
| LineSeriesOption
|
||||||
|
| PieSeriesOption
|
||||||
|
| TitleComponentOption
|
||||||
|
| TooltipComponentOption
|
||||||
|
| GridComponentOption
|
||||||
|
| DatasetComponentOption
|
||||||
|
| LegendComponentOption
|
||||||
|
| DataZoomComponentOption
|
||||||
|
| PolarComponentOption
|
||||||
|
| MarkLineComponentOption
|
||||||
|
| MarkPointComponentOption
|
||||||
|
| VisualMapComponentOption
|
||||||
|
| GeoComponentOption
|
||||||
|
>;
|
||||||
|
|
||||||
|
// 注册必须的组件
|
||||||
|
echarts.use([
|
||||||
|
TitleComponent,
|
||||||
|
TooltipComponent,
|
||||||
|
GridComponent,
|
||||||
|
DatasetComponent,
|
||||||
|
TransformComponent,
|
||||||
|
LegendComponent,
|
||||||
|
DataZoomComponent,
|
||||||
|
PolarComponent,
|
||||||
|
MarkLineComponent,
|
||||||
|
MarkPointComponent,
|
||||||
|
LabelLayout,
|
||||||
|
UniversalTransition,
|
||||||
|
CanvasRenderer,
|
||||||
|
BarChart,
|
||||||
|
LineChart,
|
||||||
|
PieChart,
|
||||||
|
VisualMapComponent,
|
||||||
|
PictorialBarChart,
|
||||||
|
GeoComponent,
|
||||||
|
MapChart,
|
||||||
|
ScatterChart,
|
||||||
|
EffectScatterChart,
|
||||||
|
LinesChart
|
||||||
|
]);
|
||||||
|
const props = defineProps({
|
||||||
|
option: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const emit = defineEmits(['echartsEvent']);
|
||||||
|
const echartBox = ref(null);
|
||||||
|
let chart!: echarts.ECharts;
|
||||||
|
|
||||||
|
const setChart = (option: ECOption): void => {
|
||||||
|
if (!props.option || !echartBox.value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
chart.resize();
|
||||||
|
chart.setOption(option);
|
||||||
|
};
|
||||||
|
|
||||||
|
const resetChart = (): void => {
|
||||||
|
const option = chart.getOption();
|
||||||
|
if (!option || !echartBox.value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
chart.resize();
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
(echarts as any).registerMap('china', { geoJSON: china });
|
||||||
|
(echarts as any).registerMap('cq', { geoJSON: cq });
|
||||||
|
chart = echarts.init(echartBox.value as any);
|
||||||
|
|
||||||
|
emit('echartsEvent', chart);
|
||||||
|
setChart(props.option);
|
||||||
|
// 界面拉伸后重设
|
||||||
|
window.addEventListener('resize', () => {
|
||||||
|
resetChart();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
watchEffect(() => {
|
||||||
|
if (chart) {
|
||||||
|
chart.clear();
|
||||||
|
}
|
||||||
|
setChart(props.option);
|
||||||
|
});
|
||||||
|
|
||||||
|
onBeforeUnmount(() => {
|
||||||
|
if (chart) {
|
||||||
|
chart.dispose();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.echarts {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
pointer-events: all;
|
||||||
|
}
|
||||||
|
</style>
|
@ -463,7 +463,16 @@ const getDetails = (row: any) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
//监听项目id刷新数据
|
||||||
|
const listeningProject = watch(
|
||||||
|
() => currentProject.value?.id,
|
||||||
|
(nid, oid) => {
|
||||||
|
getTabsList();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
onUnmounted(() => {
|
||||||
|
listeningProject();
|
||||||
|
});
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
getTabsList();
|
getTabsList();
|
||||||
});
|
});
|
||||||
|
@ -3,11 +3,11 @@
|
|||||||
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
||||||
<el-card shadow="always">
|
<el-card shadow="always">
|
||||||
<el-form :model="queryForm" :inline="true">
|
<el-form :model="queryForm" :inline="true">
|
||||||
<!-- <el-form-item label="版本号" prop="versions">
|
<el-form-item label="版本号" prop="versions">
|
||||||
<el-select v-model="queryForm.versions" placeholder="选择版本号" @change="changeVersions">
|
<el-select v-model="queryForm.versions" placeholder="选择版本号" @change="changeVersions">
|
||||||
<el-option v-for="item in options" :key="item" :label="item" :value="item" />
|
<el-option v-for="item in options" :key="item" :label="item" :value="item" />
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item> -->
|
</el-form-item>
|
||||||
<el-form-item label="表名" prop="sheet">
|
<el-form-item label="表名" prop="sheet">
|
||||||
<el-select v-model="queryForm.sheet" placeholder="选择表名" @change="changeSheet">
|
<el-select v-model="queryForm.sheet" placeholder="选择表名" @change="changeSheet">
|
||||||
<el-option v-for="item in sheets" :key="item" :label="item" :value="item" />
|
<el-option v-for="item in sheets" :key="item" :label="item" :value="item" />
|
||||||
@ -100,6 +100,7 @@ const getVersionNums = async () => {
|
|||||||
try {
|
try {
|
||||||
const params = {
|
const params = {
|
||||||
projectId: currentProject.value?.id,
|
projectId: currentProject.value?.id,
|
||||||
|
workOrderType: '1',
|
||||||
pageSize: 1000,
|
pageSize: 1000,
|
||||||
pageNum: 1
|
pageNum: 1
|
||||||
};
|
};
|
||||||
@ -140,8 +141,8 @@ const changeSheet = () => {
|
|||||||
const getSheetName = async () => {
|
const getSheetName = async () => {
|
||||||
try {
|
try {
|
||||||
const params = {
|
const params = {
|
||||||
projectId: currentProject.value?.id
|
projectId: currentProject.value?.id,
|
||||||
// versions: queryForm.value.versions
|
versions: queryForm.value.versions
|
||||||
};
|
};
|
||||||
const res = await sheetList(params);
|
const res = await sheetList(params);
|
||||||
if (res.code == 200) {
|
if (res.code == 200) {
|
||||||
@ -268,8 +269,8 @@ onUnmounted(() => {
|
|||||||
listeningProject();
|
listeningProject();
|
||||||
});
|
});
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
// getVersionNums();
|
getVersionNums();
|
||||||
getSheetName();
|
// getSheetName();
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
121
src/views/largeScreen/components/ProgressComponent.vue
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
<template>
|
||||||
|
<div class="progress_component">
|
||||||
|
<div class="title">
|
||||||
|
<span class="progress_title">{{ title }}</span>
|
||||||
|
<span :class="percentageClass" class="roboto">{{ percentageChange }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="roboto" v-if="isShowPrice">
|
||||||
|
<span>{{ value }}</span>
|
||||||
|
<span>{{ unit }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="my_el_progress">
|
||||||
|
<el-progress :percentage="progressPercentage" :color="progressColor" :show-text="false" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { defineProps, computed } from 'vue';
|
||||||
|
|
||||||
|
// 定义组件属性
|
||||||
|
const props = defineProps({
|
||||||
|
// 标题文本
|
||||||
|
title: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
default: '指标名称'
|
||||||
|
},
|
||||||
|
// 数值
|
||||||
|
value: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
default: '0.00'
|
||||||
|
},
|
||||||
|
// 单位
|
||||||
|
unit: {
|
||||||
|
type: String,
|
||||||
|
default: '万元'
|
||||||
|
},
|
||||||
|
// 百分比变化值(如:-327.55%)
|
||||||
|
percentageChange: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
default: '0.00%'
|
||||||
|
},
|
||||||
|
// 进度条百分比
|
||||||
|
progressPercentage: {
|
||||||
|
type: Number,
|
||||||
|
required: true,
|
||||||
|
default: 0
|
||||||
|
},
|
||||||
|
// 进度条颜色,默认红色
|
||||||
|
progressColor: {
|
||||||
|
type: String,
|
||||||
|
default: 'rgba(255, 77, 79, 1)'
|
||||||
|
},
|
||||||
|
// 是否显示价格
|
||||||
|
isShowPrice: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 计算百分比变化的样式类(红色或绿色)
|
||||||
|
const percentageClass = computed(() => {
|
||||||
|
// 检查变化值是否为正数
|
||||||
|
const isPositive = props.percentageChange.startsWith('+') ||
|
||||||
|
(!props.percentageChange.startsWith('-') && props.percentageChange !== '0.00%');
|
||||||
|
return isPositive ? 'green' : 'red';
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.progress_component {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
|
||||||
|
:deep(.el-progress-bar__outer) {
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.el-progress-bar__inner),
|
||||||
|
:deep(.el-progress-bar__outer) {
|
||||||
|
border-radius: unset;
|
||||||
|
}
|
||||||
|
|
||||||
|
.my_el_progress {
|
||||||
|
margin-top: 15px;
|
||||||
|
padding: 10px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.progress_title {
|
||||||
|
color: rgba(143, 171, 191, 1);
|
||||||
|
font-size: 12px;
|
||||||
|
font-family: SourceHanSansCN-Regular;
|
||||||
|
font-weight: 400;
|
||||||
|
}
|
||||||
|
|
||||||
|
.roboto {
|
||||||
|
font-family: Roboto-Regular;
|
||||||
|
font-weight: 400;
|
||||||
|
}
|
||||||
|
|
||||||
|
.red {
|
||||||
|
color: rgba(255, 77, 79, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.green {
|
||||||
|
color: rgba(0, 227, 150, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
167
src/views/largeScreen/components/RevenueContractCard.vue
Normal file
@ -0,0 +1,167 @@
|
|||||||
|
<template>
|
||||||
|
<div class="stat-card" :style="customStyles">
|
||||||
|
<!-- 标题区域 -->
|
||||||
|
<div class="stat-card__title">{{ title }}</div>
|
||||||
|
|
||||||
|
<!-- 数值区域 -->
|
||||||
|
<div class="stat-card__value-container">
|
||||||
|
<span class="stat-card__value">{{ formattedValue }}</span>
|
||||||
|
<span class="stat-card__unit">{{ unit }}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 底部信息区域 -->
|
||||||
|
<div class="stat-card__footer">
|
||||||
|
<div class="stat-card__trend">
|
||||||
|
<img
|
||||||
|
class="stat-card__trend-icon"
|
||||||
|
:src="'/src/assets/large/' + trendIcon+'.png'"
|
||||||
|
:alt="trendDirection === 'up' ? '上升' : '下降'"
|
||||||
|
>
|
||||||
|
<span class="stat-card__trend-text">{{ trendText }}</span>
|
||||||
|
</div>
|
||||||
|
<img
|
||||||
|
class="stat-card__badge"
|
||||||
|
:src="'/src/assets/large/'+badgeIcon+'.png'"
|
||||||
|
alt="徽章图标"
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { computed } from 'vue';
|
||||||
|
|
||||||
|
// 定义组件属性
|
||||||
|
const props = defineProps({
|
||||||
|
// 卡片标题
|
||||||
|
title: {
|
||||||
|
type: String,
|
||||||
|
default: '收入合同'
|
||||||
|
},
|
||||||
|
// 数值
|
||||||
|
value: {
|
||||||
|
type: Number,
|
||||||
|
default: 205805.17
|
||||||
|
},
|
||||||
|
// 单位
|
||||||
|
unit: {
|
||||||
|
type: String,
|
||||||
|
default: '万元'
|
||||||
|
},
|
||||||
|
// 增长率
|
||||||
|
growthRate: {
|
||||||
|
type: Number,
|
||||||
|
default: 3.2
|
||||||
|
},
|
||||||
|
// 增长对比周期
|
||||||
|
period: {
|
||||||
|
type: String,
|
||||||
|
default: '较上月'
|
||||||
|
},
|
||||||
|
// 趋势方向 (up/down)
|
||||||
|
trendDirection: {
|
||||||
|
type: String,
|
||||||
|
default: 'up',
|
||||||
|
validator: (value) => ['up', 'down'].includes(value)
|
||||||
|
},
|
||||||
|
// 趋势图标
|
||||||
|
trendIcon: {
|
||||||
|
type: String,
|
||||||
|
default: 'up'
|
||||||
|
},
|
||||||
|
// 徽章图标
|
||||||
|
badgeIcon: {
|
||||||
|
type: String,
|
||||||
|
default: 'top1'
|
||||||
|
},
|
||||||
|
// 卡片自定义样式
|
||||||
|
customStyles: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({})
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 格式化数值为带千分位的字符串
|
||||||
|
const formattedValue = computed(() => {
|
||||||
|
return props.value.toLocaleString('zh-CN', {
|
||||||
|
minimumFractionDigits: 2,
|
||||||
|
maximumFractionDigits: 2
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// 生成趋势文本
|
||||||
|
const trendText = computed(() => {
|
||||||
|
return `${props.growthRate}% ${props.period}`;
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.stat-card {
|
||||||
|
width: 225px;
|
||||||
|
height: 147px;
|
||||||
|
background-color: rgba(29, 214, 255, 0.1);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 20px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
border: 1px solid rgba(29, 214, 255, 0.1);
|
||||||
|
border-radius: 4px; // 增加轻微圆角,提升视觉效果
|
||||||
|
|
||||||
|
&__title {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #8FABBF;
|
||||||
|
line-height: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__value-container {
|
||||||
|
display: flex;
|
||||||
|
align-items: baseline;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__value {
|
||||||
|
font-size: 24px;
|
||||||
|
color: #fff;
|
||||||
|
line-height: 30px;
|
||||||
|
margin-right: 5px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__unit {
|
||||||
|
color: #8FABBF;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__footer {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__trend {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__trend-icon {
|
||||||
|
width: 12px;
|
||||||
|
height: 12px;
|
||||||
|
margin-right: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__trend-text {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #8FABBF;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__badge {
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 为下降趋势添加不同颜色
|
||||||
|
:deep(.stat-card__trend-text) {
|
||||||
|
color: v-bind('trendDirection === "up" ? "#8FABBF" : "#ff4d4f"');
|
||||||
|
}
|
||||||
|
</style>
|
56
src/views/largeScreen/components/TitleComponent.vue
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
<template>
|
||||||
|
<div class="large_title">
|
||||||
|
<div class="title">
|
||||||
|
<img class="title_icon" src="@/assets/large/title_icon.png" alt=""></img>
|
||||||
|
<div class="title_text">{{ title }}</div>
|
||||||
|
</div>
|
||||||
|
<img class="title_bottom" src="@/assets/large/title_bottom.png" alt="">
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { defineProps } from 'vue';
|
||||||
|
|
||||||
|
// 定义组件属性,使组件可配置
|
||||||
|
const props = defineProps({
|
||||||
|
// 标题文本
|
||||||
|
title: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
default: '标题'
|
||||||
|
},
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.large_title {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
.title {
|
||||||
|
display: flex;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title_icon {
|
||||||
|
width: 10px;
|
||||||
|
height: 24px;
|
||||||
|
margin-right: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title_text {
|
||||||
|
font-size: 24px;
|
||||||
|
font-family: Rang_men_zheng_title;
|
||||||
|
font-weight: 400;
|
||||||
|
color: rgba(226, 235, 241, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.title_bottom {
|
||||||
|
width: 100%;
|
||||||
|
height: 5px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
45
src/views/largeScreen/components/bottomboxconpoent.vue
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
<template>
|
||||||
|
<div class="bottom_box">
|
||||||
|
<div class="bottom_box_title">收入合同</div>
|
||||||
|
<div>
|
||||||
|
<span class="bottom_box_number">205,805.17</span>
|
||||||
|
<span>万元</span>
|
||||||
|
</div>
|
||||||
|
<div class="bottom_box_bottom">
|
||||||
|
<el-progress :percentage="50" color="rgba(255, 147, 42, 1)" />
|
||||||
|
</div>
|
||||||
|
<div class="bottom_box_text">
|
||||||
|
成本率
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.bottom_box {
|
||||||
|
width: 225px;
|
||||||
|
height: 147px;
|
||||||
|
height: 100%;
|
||||||
|
padding: 10px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: space-around;
|
||||||
|
|
||||||
|
.bottom_box_title,
|
||||||
|
.bottom_box_text {
|
||||||
|
color: rgba(143, 171, 191, 1);
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bottom_box_number {
|
||||||
|
font-size: 24px;
|
||||||
|
color: #fff;
|
||||||
|
line-height: 30px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
@ -1,8 +1,55 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="centerPage">
|
<div class="centerPage">
|
||||||
|
<div>
|
||||||
|
<div style="height: 147px;width: 100%;display: flex;justify-content: space-between;">
|
||||||
|
<!-- <div class="top_box">
|
||||||
|
<div class="top_box_title">收入合同</div>
|
||||||
|
<div>
|
||||||
|
<span class="top_box_number">205,805.17</span>
|
||||||
|
<span>万元</span>
|
||||||
|
</div>
|
||||||
|
<div class="top_box_bottom">
|
||||||
|
<div>
|
||||||
|
<img class="up_img" src="@/assets/large/up.png" alt=""></img>
|
||||||
|
<span class="top_box_title"> 3.2% 较上月</span>
|
||||||
|
</div>
|
||||||
|
<img class="top_img" src="@/assets/large/top1.png" alt=""></img>
|
||||||
|
</div>
|
||||||
|
</div> -->
|
||||||
|
<RevenueContractCard title="收入合同" :value="156234.89" :growthRate="-1.5" trendDirection="up" trendIcon="up"
|
||||||
|
badgeIcon="top1" period="较上月" />
|
||||||
|
<RevenueContractCard title="支出合同" :value="156234.89" :growthRate="-1.5" trendDirection="up" trendIcon="up"
|
||||||
|
badgeIcon="top2" period="较上月" />
|
||||||
|
<RevenueContractCard title="合同利润" :value="156234.89" :growthRate="-1.5" trendDirection="up" trendIcon="down"
|
||||||
|
badgeIcon="top3" period="较上月" />
|
||||||
|
<RevenueContractCard title="工程变更" :value="156234.89" :growthRate="-1.5" trendDirection="up" trendIcon="up"
|
||||||
|
badgeIcon="top4" period="较上月" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="centerPage_map">
|
<div class="centerPage_map">
|
||||||
<div ref="mapRef" class="map-container" style="width: 100%; height: 100%" />
|
<div ref="mapRef" class="map-container" style="width: 100%; height: 100%" />
|
||||||
</div>
|
</div>
|
||||||
|
<div>
|
||||||
|
<div style="height: 147px;width: 100%;display: flex;justify-content: space-between;">
|
||||||
|
<!-- <div class="bottom_box">
|
||||||
|
<div class="bottom_box_title">收入合同</div>
|
||||||
|
<div>
|
||||||
|
<span class="bottom_box_number">205,805.17</span>
|
||||||
|
<span>万元</span>
|
||||||
|
</div>
|
||||||
|
<div class="bottom_box_bottom">
|
||||||
|
<el-progress :percentage="50" color="rgba(255, 147, 42, 1)" />
|
||||||
|
</div>
|
||||||
|
<div class="bottom_box_text">
|
||||||
|
成本率
|
||||||
|
</div>
|
||||||
|
</div> -->
|
||||||
|
<bottomboxconpoent> </bottomboxconpoent>
|
||||||
|
<bottomboxconpoent> </bottomboxconpoent>
|
||||||
|
<bottomboxconpoent> </bottomboxconpoent>
|
||||||
|
<bottomboxconpoent> </bottomboxconpoent>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -10,6 +57,8 @@
|
|||||||
// import { getPowerStationOverview } from '@/api/large';
|
// import { getPowerStationOverview } from '@/api/large';
|
||||||
import * as echarts from 'echarts';
|
import * as echarts from 'echarts';
|
||||||
import china from '@/assets/china.json';
|
import china from '@/assets/china.json';
|
||||||
|
import RevenueContractCard from './RevenueContractCard.vue';
|
||||||
|
import bottomboxconpoent from './bottomboxconpoent.vue';
|
||||||
const data = ref<any>({});
|
const data = ref<any>({});
|
||||||
|
|
||||||
// 地图容器引用
|
// 地图容器引用
|
||||||
@ -168,9 +217,12 @@ onUnmounted(() => {
|
|||||||
padding: 0 10px 10px 10px;
|
padding: 0 10px 10px 10px;
|
||||||
|
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
|
|
||||||
.centerPage_map {
|
.centerPage_map {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 60%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,13 +1,73 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="leftPage">左边</div>
|
<div class="leftPage">
|
||||||
|
<!-- -->
|
||||||
|
<div class="kpi_box">
|
||||||
|
<TitleComponent :title="'支付KPI'" style="margin-bottom: 20px;"/>
|
||||||
|
<ProgressComponent
|
||||||
|
title="应收账款"
|
||||||
|
value="123,456.78"
|
||||||
|
percentageChange="+25.30%"
|
||||||
|
progressPercentage="75"
|
||||||
|
progressColor="rgba(255, 77, 79, 1)"
|
||||||
|
/>
|
||||||
|
<ProgressComponent
|
||||||
|
title="应付账款"
|
||||||
|
value="123,456.78"
|
||||||
|
percentageChange="+25.30%"
|
||||||
|
progressPercentage="25"
|
||||||
|
progressColor="rgba(29, 214, 255, 1)"
|
||||||
|
/>
|
||||||
|
<ProgressComponent
|
||||||
|
title="本月付款"
|
||||||
|
value="123,456.78"
|
||||||
|
percentageChange="+25.30%"
|
||||||
|
progressPercentage="45"
|
||||||
|
progressColor="rgba(0, 227, 150, 1)"
|
||||||
|
/>
|
||||||
|
<ProgressComponent
|
||||||
|
title="本月收款"
|
||||||
|
value="123,456.78"
|
||||||
|
percentageChange="+25.30%"
|
||||||
|
progressPercentage="10"
|
||||||
|
progressColor="rgba(255, 147, 42, 1)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="contract_box">
|
||||||
|
<EchartBox :option="barOption" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts"></script>
|
<script setup>
|
||||||
|
import { ref, reactive, onMounted, computed, toRefs, getCurrentInstance, nextTick } from 'vue';
|
||||||
|
// import echarts from 'echarts';
|
||||||
|
import TitleComponent from './TitleComponent.vue';
|
||||||
|
import ProgressComponent from './ProgressComponent.vue';
|
||||||
|
import EchartBox from '@/components/EchartBox/index.vue';
|
||||||
|
import { getBarOptions2 } from './optionList';
|
||||||
|
const barOption = ref();
|
||||||
|
const getCapitalData = (data) => {
|
||||||
|
barOption.value = getBarOptions2();
|
||||||
|
};
|
||||||
|
onMounted(() => {
|
||||||
|
getCapitalData();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style lang="scss">
|
||||||
.leftPage {
|
.leftPage {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
background: #0c1e35;
|
.kpi_box{
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
.contract_box{
|
||||||
|
height: 35vh;
|
||||||
|
}
|
||||||
|
.kpi_box,.contract_box {
|
||||||
|
padding: 10px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
border: 1px solid rgba(29, 214, 255, 0.3);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import * as echarts from 'echarts/core';
|
import * as echarts from 'echarts/core';
|
||||||
|
import { text } from 'stream/consumers';
|
||||||
// import { PictorialBarChart } from 'echarts/charts'
|
// import { PictorialBarChart } from 'echarts/charts'
|
||||||
// 客流量图
|
// 客流量图
|
||||||
export const getOption = (xData: any, yData: any) => {
|
export const getOption = (xData: any, yData: any) => {
|
||||||
@ -249,9 +250,10 @@ export const getOption2 = (data: any) => {
|
|||||||
};
|
};
|
||||||
return option;
|
return option;
|
||||||
};
|
};
|
||||||
//食堂周报图
|
//z折线
|
||||||
export const getLineOption = (lineData: any) => {
|
export const getLineOption = (lineData: any) => {
|
||||||
const maxData = Math.ceil(Math.max(...lineData.line1));
|
const maxData = Math.max(...lineData.line1.flat());
|
||||||
|
|
||||||
const option = {
|
const option = {
|
||||||
backgroundColor: '',
|
backgroundColor: '',
|
||||||
tooltip: {
|
tooltip: {
|
||||||
@ -263,42 +265,49 @@ export const getLineOption = (lineData: any) => {
|
|||||||
},
|
},
|
||||||
borderColor: '#7ec7ff'
|
borderColor: '#7ec7ff'
|
||||||
},
|
},
|
||||||
// legend: {
|
legend: {
|
||||||
// align: 'left',
|
align: 'left',
|
||||||
// right: '5%',
|
right: '5%',
|
||||||
// top: '1%',
|
top: '1%',
|
||||||
// type: 'plain',
|
type: 'plain',
|
||||||
// textStyle: {
|
textStyle: {
|
||||||
// color: '#fff',
|
color: '#fff',
|
||||||
// fontSize: 12
|
fontSize: 12
|
||||||
// },
|
},
|
||||||
// // icon:'rect',
|
// icon:'rect',
|
||||||
// itemGap: 15,
|
itemGap: 15,
|
||||||
// itemWidth: 18,
|
itemWidth: 18,
|
||||||
// data: [
|
data: [
|
||||||
// {
|
{
|
||||||
// name: '上周销售量'
|
name: '收款金额'
|
||||||
// },
|
},
|
||||||
// {
|
{
|
||||||
// name: '本周销售量'
|
name: '付款金额'
|
||||||
// }
|
},
|
||||||
// ]
|
{
|
||||||
// },
|
name: '净现金流'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
grid: {
|
grid: {
|
||||||
top: '12%',
|
top: '12%',
|
||||||
left: '1%',
|
left: '1%',
|
||||||
right: '3%',
|
right: '3%',
|
||||||
bottom: '12%',
|
bottom: '5%',
|
||||||
containLabel: true
|
containLabel: true
|
||||||
},
|
},
|
||||||
xAxis: {
|
xAxis: {
|
||||||
type: 'category',
|
type: 'category',
|
||||||
data: lineData.xLabel,
|
data: lineData.xLabel,
|
||||||
|
boundaryGap: false,
|
||||||
axisLine: {
|
axisLine: {
|
||||||
show: false
|
show: false
|
||||||
},
|
},
|
||||||
axisTick: {
|
axisTick: {
|
||||||
show: true
|
show: false
|
||||||
|
},
|
||||||
|
splitLine: {
|
||||||
|
show: false
|
||||||
},
|
},
|
||||||
axisLabel: {
|
axisLabel: {
|
||||||
textStyle: {
|
textStyle: {
|
||||||
@ -311,28 +320,28 @@ export const getLineOption = (lineData: any) => {
|
|||||||
type: 'value',
|
type: 'value',
|
||||||
max: maxData,
|
max: maxData,
|
||||||
splitLine: {
|
splitLine: {
|
||||||
show: true,
|
show: false,
|
||||||
lineStyle: {
|
lineStyle: {
|
||||||
type: 'solid',
|
type: 'solid',
|
||||||
color: 'rgba(73, 169, 191, 0.2)'
|
color: 'rgba(73, 169, 191, 0.2)'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
dataZoom: [
|
// dataZoom: [
|
||||||
{
|
// {
|
||||||
// show: true,
|
// // show: true,
|
||||||
start: 0,
|
// start: 0,
|
||||||
end: 30,
|
// end: 30,
|
||||||
bottom: 2, // 下滑块距离x轴底部的距离
|
// bottom: 2, // 下滑块距离x轴底部的距离
|
||||||
height: 23
|
// height: 23
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
type: 'inside'
|
// type: 'inside'
|
||||||
}
|
// }
|
||||||
],
|
// ],
|
||||||
series: [
|
series: [
|
||||||
{
|
{
|
||||||
name: '逆变器功率',
|
name: '收款金额',
|
||||||
type: 'line',
|
type: 'line',
|
||||||
symbol: 'circle', // 默认是空心圆(中间是白色的),改成实心圆
|
symbol: 'circle', // 默认是空心圆(中间是白色的),改成实心圆
|
||||||
showAllSymbol: false,
|
showAllSymbol: false,
|
||||||
@ -373,7 +382,95 @@ export const getLineOption = (lineData: any) => {
|
|||||||
shadowColor: 'rgba(25,163,223, 0.5)', //阴影颜色
|
shadowColor: 'rgba(25,163,223, 0.5)', //阴影颜色
|
||||||
shadowBlur: 20 //shadowBlur设图形阴影的模糊大小。配合shadowColor,shadowOffsetX/Y, 设置图形的阴影效果。
|
shadowBlur: 20 //shadowBlur设图形阴影的模糊大小。配合shadowColor,shadowOffsetX/Y, 设置图形的阴影效果。
|
||||||
},
|
},
|
||||||
data: lineData.line1
|
data: lineData.line1[0]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '付款金额',
|
||||||
|
type: 'line',
|
||||||
|
symbol: 'none', // 默认是空心圆(中间是白色的),改成实心圆
|
||||||
|
showAllSymbol: false,
|
||||||
|
symbolSize: 0,
|
||||||
|
smooth: true,
|
||||||
|
lineStyle: {
|
||||||
|
width: 1,
|
||||||
|
color: 'rgba(255, 224, 179, 1)', // 线条颜色
|
||||||
|
borderColor: 'rgba(0,0,0,.4)'
|
||||||
|
},
|
||||||
|
itemStyle: {
|
||||||
|
color: 'rgba(255, 224, 179, 1)',
|
||||||
|
borderWidth: 2,
|
||||||
|
show: true
|
||||||
|
},
|
||||||
|
tooltip: {
|
||||||
|
show: true
|
||||||
|
},
|
||||||
|
areaStyle: {
|
||||||
|
//线性渐变,前4个参数分别是x0,y0,x2,y2(范围0~1);相当于图形包围盒中的百分比。如果最后一个参数是‘true’,则该四个值是绝对像素位置。
|
||||||
|
color: new echarts.graphic.LinearGradient(
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
[
|
||||||
|
{
|
||||||
|
offset: 0,
|
||||||
|
color: 'rgba(255, 224, 179, 0.4)'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
offset: 1,
|
||||||
|
color: 'rgba(255, 224, 179, 0)'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
false
|
||||||
|
),
|
||||||
|
shadowColor: 'rgba(255, 224, 179, 0.6)', //阴影颜色
|
||||||
|
shadowBlur: 20 //shadowBlur设图形阴影的模糊大小。配合shadowColor,shadowOffsetX/Y, 设置图形的阴影效果。
|
||||||
|
},
|
||||||
|
data: lineData.line1[1]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '净现金流',
|
||||||
|
type: 'line',
|
||||||
|
symbol: 'none', // 默认是空心圆(中间是白色的),改成实心圆
|
||||||
|
showAllSymbol: false,
|
||||||
|
symbolSize: 0,
|
||||||
|
smooth: true,
|
||||||
|
lineStyle: {
|
||||||
|
width: 1,
|
||||||
|
color: 'rgba(39, 255, 252, 1)', // 线条颜色
|
||||||
|
borderColor: 'rgba(0,0,0,.4)'
|
||||||
|
},
|
||||||
|
itemStyle: {
|
||||||
|
color: 'rgba(39, 255, 252, 1)',
|
||||||
|
borderWidth: 2,
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
tooltip: {
|
||||||
|
show: true
|
||||||
|
},
|
||||||
|
areaStyle: {
|
||||||
|
//线性渐变,前4个参数分别是x0,y0,x2,y2(范围0~1);相当于图形包围盒中的百分比。如果最后一个参数是‘true’,则该四个值是绝对像素位置。
|
||||||
|
color: new echarts.graphic.LinearGradient(
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
[
|
||||||
|
{
|
||||||
|
offset: 0,
|
||||||
|
color: 'rgba(39, 255, 252, 0.4)'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
offset: 1,
|
||||||
|
color: 'rgba(39, 255, 252, 0)'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
false
|
||||||
|
),
|
||||||
|
shadowColor: 'rgba(39, 255, 252, 0.5)', //阴影颜色
|
||||||
|
shadowBlur: 20 //shadowBlur设图形阴影的模糊大小。配合shadowColor,shadowOffsetX/Y, 设置图形的阴影效果。
|
||||||
|
},
|
||||||
|
data: lineData.line1[2]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
@ -600,16 +697,16 @@ export const getBarOptions = (data: any) => {
|
|||||||
const option = {
|
const option = {
|
||||||
backgroundColor: '',
|
backgroundColor: '',
|
||||||
grid: {
|
grid: {
|
||||||
left: '7%',
|
left: '8%',
|
||||||
top: '4%',
|
top: '4%',
|
||||||
bottom: '25%',
|
bottom: '8%',
|
||||||
right: '2%'
|
right: '2%'
|
||||||
},
|
},
|
||||||
tooltip: {
|
tooltip: {
|
||||||
show: true,
|
show: true,
|
||||||
backgroundColor: '',
|
backgroundColor: '',
|
||||||
trigger: 'axis',
|
trigger: 'axis',
|
||||||
formatter: '{b0}:{c0}元',
|
formatter: '{b0}:{c0}万元',
|
||||||
textStyle: {
|
textStyle: {
|
||||||
color: '#fff'
|
color: '#fff'
|
||||||
}
|
}
|
||||||
@ -634,7 +731,7 @@ export const getBarOptions = (data: any) => {
|
|||||||
// show: true,
|
// show: true,
|
||||||
},
|
},
|
||||||
splitLine: {
|
splitLine: {
|
||||||
show: true,
|
show: false,
|
||||||
lineStyle: {
|
lineStyle: {
|
||||||
color: 'rgba(108, 128, 151, 0.3)',
|
color: 'rgba(108, 128, 151, 0.3)',
|
||||||
type: 'dashed'
|
type: 'dashed'
|
||||||
@ -646,9 +743,7 @@ export const getBarOptions = (data: any) => {
|
|||||||
{
|
{
|
||||||
axisLabel: {
|
axisLabel: {
|
||||||
formatter: function (value) {
|
formatter: function (value) {
|
||||||
if (value >= 1000) {
|
value = value + '万';
|
||||||
value = (value / 1000).toFixed(1) + 'k'; // 大于等于1000的数字显示为1k、2.5k等
|
|
||||||
}
|
|
||||||
return value;
|
return value;
|
||||||
},
|
},
|
||||||
color: 'rgba(255, 255, 255, 0.8)'
|
color: 'rgba(255, 255, 255, 0.8)'
|
||||||
@ -662,7 +757,7 @@ export const getBarOptions = (data: any) => {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
splitLine: {
|
splitLine: {
|
||||||
show: true,
|
show: false,
|
||||||
lineStyle: {
|
lineStyle: {
|
||||||
color: 'rgba(108, 128, 151, 0.3)',
|
color: 'rgba(108, 128, 151, 0.3)',
|
||||||
type: 'dashed'
|
type: 'dashed'
|
||||||
@ -670,24 +765,25 @@ export const getBarOptions = (data: any) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
dataZoom: [
|
// dataZoom: [
|
||||||
{
|
// {
|
||||||
// show: true,
|
// // show: true,
|
||||||
start: 0,
|
// start: 0,
|
||||||
end: 30,
|
// end: 30,
|
||||||
bottom: 2, // 下滑块距离x轴底部的距离
|
// bottom: 2, // 下滑块距离x轴底部的距离
|
||||||
height: 23
|
// height: 23
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
type: 'inside'
|
// type: 'inside'
|
||||||
}
|
// }
|
||||||
],
|
// ],
|
||||||
series: [
|
series: [
|
||||||
{
|
{
|
||||||
type: 'bar',
|
type: 'bar',
|
||||||
data: data.value,
|
data: data.value[0],
|
||||||
stack: '合并',
|
// stack: '合并',
|
||||||
barWidth: '15',
|
barWidth: '5',
|
||||||
|
barGap: '100%',
|
||||||
itemStyle: {
|
itemStyle: {
|
||||||
color: new echarts.graphic.LinearGradient(
|
color: new echarts.graphic.LinearGradient(
|
||||||
0,
|
0,
|
||||||
@ -697,22 +793,60 @@ export const getBarOptions = (data: any) => {
|
|||||||
[
|
[
|
||||||
{
|
{
|
||||||
offset: 0,
|
offset: 0,
|
||||||
color: 'rgba(0, 111, 255, 0)' // 0% 处的颜色
|
color: ' rgba(29, 214, 255, 1)' // 0% 处的颜色
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
offset: 0.7,
|
offset: 0.7,
|
||||||
color: 'rgba(0, 111, 255, 0.5)' // 0% 处的颜色
|
color: ' rgba(29, 214, 255, 0.5)' // 0% 处的颜色
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
offset: 1,
|
offset: 1,
|
||||||
color: 'rgba(0, 111, 255, 1)' // 100% 处的颜色
|
color: ' rgba(29, 214, 255, 0.1)' // 100% 处的颜色
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
false
|
false
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
label: {
|
label: {
|
||||||
show: true,
|
show: false,
|
||||||
|
formatter: '{c}',
|
||||||
|
position: 'top',
|
||||||
|
color: '#fff',
|
||||||
|
fontSize: 10
|
||||||
|
// padding: 5
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'bar',
|
||||||
|
data: data.value[1],
|
||||||
|
// stack: '合并',
|
||||||
|
barWidth: '5',
|
||||||
|
barGap: '100%',
|
||||||
|
itemStyle: {
|
||||||
|
color: new echarts.graphic.LinearGradient(
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
[
|
||||||
|
{
|
||||||
|
offset: 0,
|
||||||
|
color: ' rgba(255, 77, 79, 1)' // 0% 处的颜色
|
||||||
|
},
|
||||||
|
{
|
||||||
|
offset: 0.7,
|
||||||
|
color: ' rgba(255, 77, 79, 0.5)' // 0% 处的颜色
|
||||||
|
},
|
||||||
|
{
|
||||||
|
offset: 1,
|
||||||
|
color: ' rgba(255, 77, 79, 0.1)' // 100% 处的颜色
|
||||||
|
}
|
||||||
|
],
|
||||||
|
false
|
||||||
|
)
|
||||||
|
},
|
||||||
|
label: {
|
||||||
|
show: false,
|
||||||
formatter: '{c}',
|
formatter: '{c}',
|
||||||
position: 'top',
|
position: 'top',
|
||||||
color: '#fff',
|
color: '#fff',
|
||||||
@ -720,16 +854,66 @@ export const getBarOptions = (data: any) => {
|
|||||||
// padding: 5
|
// padding: 5
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// {
|
|
||||||
// type: 'bar',
|
|
||||||
// stack: '合并',
|
|
||||||
// data: topData,
|
|
||||||
// barWidth: '15',
|
|
||||||
// itemStyle: {
|
|
||||||
// color: 'rgba(252, 217, 18, 1)'
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
return option;
|
return option;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 收支合同分析
|
||||||
|
export const getBarOptions2 = (data: any) => {
|
||||||
|
const option = {
|
||||||
|
color:['#FF932A', '#678FE6', '#1DD6FF', '#00E396'],
|
||||||
|
title: {
|
||||||
|
text: '数量(个)',
|
||||||
|
subtext: '16',
|
||||||
|
bottom: 'center',
|
||||||
|
left: 'center',
|
||||||
|
textStyle: {
|
||||||
|
color: '#9DADB7',
|
||||||
|
fontSize: 16
|
||||||
|
},
|
||||||
|
subtextStyle:{
|
||||||
|
color: '#707070',
|
||||||
|
fontSize: 32,
|
||||||
|
fontWeight: 'bold'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'item'
|
||||||
|
},
|
||||||
|
legend: {
|
||||||
|
top: '5%',
|
||||||
|
left: 'center'
|
||||||
|
},
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
name: 'Access From',
|
||||||
|
type: 'pie',
|
||||||
|
radius: ['50%', '60%'],
|
||||||
|
avoidLabelOverlap: false,
|
||||||
|
padAngle: 5,
|
||||||
|
label: {
|
||||||
|
show: false,
|
||||||
|
position: 'center'
|
||||||
|
},
|
||||||
|
emphasis: {
|
||||||
|
label: {
|
||||||
|
show: false,
|
||||||
|
fontSize: 40,
|
||||||
|
fontWeight: 'bold'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
labelLine: {
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
data: [
|
||||||
|
{ value: 3, name: '100万一下' },
|
||||||
|
{ value: 4, name: '100-500万' },
|
||||||
|
{ value: 5, name: '500-1000万' },
|
||||||
|
{ value: 4, name: '1000万以上' },
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
return option;
|
||||||
|
}
|
@ -1,13 +1,183 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="rightPage">右边</div>
|
<div class="rightPage">
|
||||||
|
<div class="funds">
|
||||||
|
<TitleComponent :title="'资金KPI'" />
|
||||||
|
<div class="funds_echarts">
|
||||||
|
<EchartBox :option="lineOption" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="cashFlow">
|
||||||
|
<TitleComponent :title="'现金流概述'" />
|
||||||
|
<div class="inflowData">
|
||||||
|
<div class="inflow">
|
||||||
|
<div class="title">现金流入</div>
|
||||||
|
<div class="number">1000000</div>
|
||||||
|
<div class="unit">万元</div>
|
||||||
|
</div>
|
||||||
|
<div class="inflow">
|
||||||
|
<div class="title">现金流出</div>
|
||||||
|
<div class="number">1000000</div>
|
||||||
|
<div class="unit">万元</div>
|
||||||
|
</div>
|
||||||
|
<div class="inflow">
|
||||||
|
<div class="title">净现金流</div>
|
||||||
|
<div class="number">1000000</div>
|
||||||
|
<div class="unit">万元</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="inflow_echarts">
|
||||||
|
<EchartBox :option="barOption" />
|
||||||
|
</div>
|
||||||
|
<div class="progress">
|
||||||
|
<!-- <div class="progress_item">
|
||||||
|
<div class="title">项目进度</div>
|
||||||
|
<div class="number">100%</div>
|
||||||
|
</div> -->
|
||||||
|
<ProgressComponent title="现金比率" value="123,456.78" percentageChange="3479.61%" :progressPercentage="100"
|
||||||
|
progressColor="rgba(29, 214, 255, 1)" :isShowPrice="false" class="progress_text" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts"></script>
|
<script setup lang="ts">
|
||||||
|
import TitleComponent from './TitleComponent.vue';
|
||||||
|
import EchartBox from '@/components/EchartBox/index.vue';
|
||||||
|
import { getLineOption, getBarOptions } from './optionList';
|
||||||
|
import ProgressComponent from './ProgressComponent.vue';
|
||||||
|
|
||||||
|
const lineOption = ref();
|
||||||
|
const barOption = ref();
|
||||||
|
|
||||||
|
const getCapitalData = (data?: any) => {
|
||||||
|
// const xData = data.map((item) => item.time);
|
||||||
|
// const yData = data.map((item) => item.content);
|
||||||
|
const lineData = {
|
||||||
|
xLabel: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'],
|
||||||
|
line1: [
|
||||||
|
[100, 200, 150, 300, 250, 350, 400, 350, 450, 500, 400, 550],
|
||||||
|
[220, 250, 230, 280, 270, 300, 350, 320, 380, 400, 450, 500],
|
||||||
|
[300, 350, 320, 380, 400, 450, 500, 480, 520, 550, 600, 650]
|
||||||
|
]
|
||||||
|
|
||||||
|
// line2: ['20', '50', '12', '65', '30', '60']
|
||||||
|
};
|
||||||
|
lineOption.value = getLineOption(lineData);
|
||||||
|
};
|
||||||
|
const getTurnoverList = (data?: any) => {
|
||||||
|
// const xData = data.map((item) => item.time);
|
||||||
|
// const yData = data.map((item) => {
|
||||||
|
// // 先将content转换为数字,再调用toFixed
|
||||||
|
// const num = Number(item.content);
|
||||||
|
// return isNaN(num) ? 0 : Number(num.toFixed(2));
|
||||||
|
// });
|
||||||
|
|
||||||
|
const barData = {
|
||||||
|
name: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'],
|
||||||
|
value: [
|
||||||
|
[2, 5, 15, 30, 25, 35, 40, 35, 45, 50, 40, 55],
|
||||||
|
[4, 3, 6, 11, 15, 22, 30, 14, 48, 22, 25, 60]
|
||||||
|
]
|
||||||
|
};
|
||||||
|
barOption.value = getBarOptions(barData);
|
||||||
|
};
|
||||||
|
onMounted(() => {
|
||||||
|
getCapitalData();
|
||||||
|
getTurnoverList();
|
||||||
|
});
|
||||||
|
|
||||||
|
//资金KPI
|
||||||
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
.rightPage {
|
.rightPage {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
background: #0c1e35;
|
box-sizing: border-box;
|
||||||
|
// padding: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.funds {
|
||||||
|
width: 100%;
|
||||||
|
// height: 40%;
|
||||||
|
border: 1px solid rgba(29, 214, 255, 0.3);
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding: 10px 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.funds_echarts {
|
||||||
|
width: 100%;
|
||||||
|
height: 25vh;
|
||||||
|
padding: 10px 0 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cashFlow {
|
||||||
|
width: 100%;
|
||||||
|
// height: 50%;
|
||||||
|
border: 1px solid rgba(29, 214, 255, 0.3);
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding: 10px 5px;
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inflowData {
|
||||||
|
width: 100%;
|
||||||
|
height: 12vh;
|
||||||
|
// background: #fff;
|
||||||
|
padding-top: 20px;
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(3, 1fr);
|
||||||
|
grid-gap: 10px;
|
||||||
|
|
||||||
|
.inflow {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
// background: #f5f5f5;
|
||||||
|
padding: 10px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
background: rgba(29, 214, 255, 0.1);
|
||||||
|
border-left: 1px solid rgba(29, 214, 255, 1);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.title {
|
||||||
|
font-size: 14px;
|
||||||
|
// font-weight: 500;
|
||||||
|
color: #fff;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.number {
|
||||||
|
font-size: 24px;
|
||||||
|
// font-weight: 500;
|
||||||
|
color: #fff;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.unit {
|
||||||
|
font-size: 12px;
|
||||||
|
// font-weight: 500;
|
||||||
|
color: rgba(255, 255, 255, 0.5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.inflow_echarts {
|
||||||
|
width: 100%;
|
||||||
|
height: 25vh;
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.progress {
|
||||||
|
width: 100%;
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.progress_text) {
|
||||||
|
.roboto {
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
279
src/views/tender/bidd/index.vue
Normal file
@ -0,0 +1,279 @@
|
|||||||
|
<template>
|
||||||
|
<div class="p-2">
|
||||||
|
<el-tabs type="border-card" @tab-change="handleTabChange" v-model="activeTab">
|
||||||
|
<el-tab-pane v-for="(item, index) in tabList" :key="index" :label="item.label" :name="item.value">
|
||||||
|
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
||||||
|
<el-card shadow="always">
|
||||||
|
<el-form :model="queryForm" :inline="true">
|
||||||
|
<el-form-item label="版本号" prop="versions">
|
||||||
|
<el-select v-model="queryForm.versions" placeholder="选择版本号" @change="changeVersions">
|
||||||
|
<el-option v-for="item in options" :key="item.versions" :label="item.versions" :value="item.versions" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="表名" prop="sheet">
|
||||||
|
<el-select v-model="queryForm.sheet" placeholder="选择表名" @change="changeSheet">
|
||||||
|
<el-option v-for="item in sheets" :key="item" :label="item" :value="item" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button type="primary" @click="toggleExpandAll(true)">一键展开</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button type="primary" @click="toggleExpandAll(false)">一键收起</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-upload
|
||||||
|
ref="uploadRef"
|
||||||
|
class="upload-demo"
|
||||||
|
:http-request="importExcel"
|
||||||
|
:show-file-list="false"
|
||||||
|
v-hasPermi="['tender:billofquantitiesLimitList:importExcelFile']"
|
||||||
|
>
|
||||||
|
<template #trigger>
|
||||||
|
<el-button type="primary">导入excel</el-button>
|
||||||
|
</template>
|
||||||
|
</el-upload>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button type="primary" @click="handleExport()" v-hasPermi="['tender:billofquantitiesLimitList:export']">导出excel</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</el-card>
|
||||||
|
</transition>
|
||||||
|
<el-card shadow="never" class="mb8">
|
||||||
|
<el-table ref="tableRef" v-loading="loading" :data="tableData" row-key="id" border lazy default-expand-all>
|
||||||
|
<el-table-column prop="num" label="编号" />
|
||||||
|
<el-table-column prop="name" label="工程或费用名称" />
|
||||||
|
<el-table-column prop="unit" label="单位" />
|
||||||
|
<el-table-column prop="quantity" label="数量" />
|
||||||
|
<el-table-column prop="remark" label="单价" align="center">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-input-number
|
||||||
|
:model-value="scope.row.unitPrice"
|
||||||
|
@change="(val) => (scope.row.unitPrice = val)"
|
||||||
|
:precision="2"
|
||||||
|
:step="0.1"
|
||||||
|
:controls="false"
|
||||||
|
v-if="scope.row.quantity && scope.row.quantity != 0"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="price" label="总价" align="center">
|
||||||
|
<template #default="scope">
|
||||||
|
{{ scope.row.price }}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="price" label="操作" align="center">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
size="small"
|
||||||
|
@click="handleSave(scope.row)"
|
||||||
|
v-if="scope.row.quantity && scope.row.quantity != 0"
|
||||||
|
v-hasPermi="['tender:billofquantitiesLimitList:edit']"
|
||||||
|
>确定</el-button
|
||||||
|
>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</el-card>
|
||||||
|
</el-tab-pane>
|
||||||
|
</el-tabs>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { useUserStoreHook } from '@/store/modules/user';
|
||||||
|
import { obtainAllVersionNumbers, sheetList, getTableList, updatePrice, importExcelFile } from '@/api/tender/index';
|
||||||
|
|
||||||
|
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||||
|
const userStore = useUserStoreHook();
|
||||||
|
const currentProject = computed(() => userStore.selectedProject);
|
||||||
|
const tabList = [
|
||||||
|
{
|
||||||
|
label: '招采工程量清单',
|
||||||
|
value: '2'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '物资设备清单',
|
||||||
|
value: '3'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
const queryForm = ref({
|
||||||
|
versions: '',
|
||||||
|
sheet: ''
|
||||||
|
});
|
||||||
|
|
||||||
|
const activeTab = ref('2');
|
||||||
|
const sheets = ref([]);
|
||||||
|
const options = ref([]);
|
||||||
|
const tableData = ref([]);
|
||||||
|
const tableRef = ref();
|
||||||
|
const isExpandAll = ref(false);
|
||||||
|
const loading = ref(false);
|
||||||
|
|
||||||
|
// 切换tab
|
||||||
|
const handleTabChange = (tab: string) => {
|
||||||
|
activeTab.value = tab;
|
||||||
|
getVersionNums();
|
||||||
|
};
|
||||||
|
//切换版本
|
||||||
|
const changeVersions = () => {
|
||||||
|
getSheetName();
|
||||||
|
};
|
||||||
|
//切换表格
|
||||||
|
const changeSheet = (val: any) => {
|
||||||
|
getTableData();
|
||||||
|
};
|
||||||
|
//展开树
|
||||||
|
const toggleExpandAll = (isExpand: boolean) => {
|
||||||
|
tableData.value.forEach((row) => {
|
||||||
|
tableRef.value.toggleRowExpansion(row, isExpand);
|
||||||
|
});
|
||||||
|
isExpandAll.value = isExpand;
|
||||||
|
};
|
||||||
|
|
||||||
|
//获取版本号
|
||||||
|
const getVersionNums = async () => {
|
||||||
|
try {
|
||||||
|
const params = {
|
||||||
|
projectId: currentProject.value?.id,
|
||||||
|
workOrderType: activeTab.value,
|
||||||
|
pageSize: 1000,
|
||||||
|
pageNum: 1
|
||||||
|
};
|
||||||
|
|
||||||
|
const res = await obtainAllVersionNumbers(params);
|
||||||
|
if (res.code == 200) {
|
||||||
|
options.value = res.data;
|
||||||
|
if (res.data.length > 0) {
|
||||||
|
queryForm.value.versions = res.data[0].versions;
|
||||||
|
getSheetName();
|
||||||
|
} else {
|
||||||
|
queryForm.value.versions = '';
|
||||||
|
getSheetName();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
//获取表名
|
||||||
|
const getSheetName = async () => {
|
||||||
|
try {
|
||||||
|
const params = {
|
||||||
|
projectId: currentProject.value?.id,
|
||||||
|
versions: queryForm.value.versions
|
||||||
|
};
|
||||||
|
const res = await sheetList(params);
|
||||||
|
if (res.code == 200) {
|
||||||
|
sheets.value = res.data;
|
||||||
|
if (res.data.length > 0) {
|
||||||
|
queryForm.value.sheet = res.data[0];
|
||||||
|
} else {
|
||||||
|
queryForm.value.sheet = '';
|
||||||
|
}
|
||||||
|
getTableData();
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
//获取表格数据
|
||||||
|
const getTableData = async () => {
|
||||||
|
try {
|
||||||
|
const params = {
|
||||||
|
projectId: currentProject.value?.id,
|
||||||
|
versions: queryForm.value.versions,
|
||||||
|
sheet: queryForm.value.sheet,
|
||||||
|
type: activeTab.value
|
||||||
|
};
|
||||||
|
const res = await getTableList(params);
|
||||||
|
if (res.code == 200) {
|
||||||
|
tableData.value = res.data;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
//导入
|
||||||
|
const importExcel = (options: any): any => {
|
||||||
|
let formData = new FormData();
|
||||||
|
formData.append('file', options.file);
|
||||||
|
loading.value = true;
|
||||||
|
importExcelFile(
|
||||||
|
{ projectId: currentProject.value?.id, sheet: queryForm.value.sheet, versions: queryForm.value.versions, type: activeTab.value },
|
||||||
|
formData
|
||||||
|
)
|
||||||
|
.then((res) => {
|
||||||
|
const { code } = res;
|
||||||
|
if (code == 200) {
|
||||||
|
proxy.$modal.msgSuccess(res.msg || '导入成功');
|
||||||
|
getTableData();
|
||||||
|
} else {
|
||||||
|
proxy.$modal.msgError(res.msg || '导入失败');
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
proxy.$modal.msgError(err.msg || '导入失败');
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
loading.value = false;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
//导出
|
||||||
|
const handleExport = () => {
|
||||||
|
proxy?.download(
|
||||||
|
'/tender/tenderPlanLimitList/export',
|
||||||
|
{
|
||||||
|
projectId: currentProject.value?.id,
|
||||||
|
sheet: queryForm.value.sheet,
|
||||||
|
versions: queryForm.value.versions,
|
||||||
|
type: activeTab.value
|
||||||
|
},
|
||||||
|
`招标一览表${queryForm.value.sheet}.xlsx`
|
||||||
|
);
|
||||||
|
};
|
||||||
|
//确认修改
|
||||||
|
const handleSave = (row: any) => {
|
||||||
|
try {
|
||||||
|
if (!row.unitPrice) {
|
||||||
|
ElMessage({
|
||||||
|
message: '请输入单价',
|
||||||
|
type: 'warning'
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
loading.value = true;
|
||||||
|
updatePrice(row).then((res) => {
|
||||||
|
if (res.code == 200) {
|
||||||
|
ElMessage({
|
||||||
|
message: '修改成功',
|
||||||
|
type: 'success'
|
||||||
|
});
|
||||||
|
getTableData();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
loading.value = false;
|
||||||
|
} finally {
|
||||||
|
loading.value = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
//监听项目id刷新数据
|
||||||
|
const listeningProject = watch(
|
||||||
|
() => currentProject.value?.id,
|
||||||
|
(nid, oid) => {
|
||||||
|
getVersionNums();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
onUnmounted(() => {
|
||||||
|
listeningProject();
|
||||||
|
});
|
||||||
|
onMounted(() => {
|
||||||
|
getVersionNums();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss"></style>
|