|
|
@@ -0,0 +1,342 @@
|
|
|
+<template>
|
|
|
+ <div class="now-year-container">
|
|
|
+ <div class="now-year-title">
|
|
|
+ <i class="iconfont icon-bar-chart"></i>
|
|
|
+ 实施服务(今年数据)
|
|
|
+ </div>
|
|
|
+ <div class="chart-container">
|
|
|
+ <div id="nowYearChart" class="chart"></div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script>
|
|
|
+ import { mapState } from "vuex"
|
|
|
+ import { api } from "@/api"
|
|
|
+ import * as echarts from "echarts"
|
|
|
+
|
|
|
+ export default {
|
|
|
+ name: "NowYearServices",
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ chartInstance: null,
|
|
|
+ chartData: {
|
|
|
+ categories: [
|
|
|
+ "履约城市",
|
|
|
+ "服务企业",
|
|
|
+ "服务项目",
|
|
|
+ "合同数",
|
|
|
+ "签约户数",
|
|
|
+ ],
|
|
|
+ ongoing: [88888, 88888, 88888, 88888, 88888], // 进行中
|
|
|
+ lastMonthCompleted: [88888, 88888, 88888, 88888, 88888], // 上月完成
|
|
|
+ yearTotal: [88888, 88888, 888888, 88888, 88888], // 今年累计
|
|
|
+ totalNumbers: [8888, 8888, 8888, 8888, 8888], // 左侧显示的总数
|
|
|
+ },
|
|
|
+ timer: null,
|
|
|
+ }
|
|
|
+ },
|
|
|
+ computed: {
|
|
|
+ ...mapState(["entCode", "communityId"]),
|
|
|
+ },
|
|
|
+ mounted() {
|
|
|
+ this.init()
|
|
|
+ window.addEventListener("resize", this.handleResize)
|
|
|
+
|
|
|
+ // 设置定时刷新
|
|
|
+ this.timer = setInterval(() => {
|
|
|
+ this.loadData()
|
|
|
+ }, 30000) // 每30秒刷新一次
|
|
|
+ },
|
|
|
+ beforeDestroy() {
|
|
|
+ if (this.chartInstance) {
|
|
|
+ this.chartInstance.dispose()
|
|
|
+ }
|
|
|
+ window.removeEventListener("resize", this.handleResize)
|
|
|
+ if (this.timer) {
|
|
|
+ clearInterval(this.timer)
|
|
|
+ }
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ // 初始化组件
|
|
|
+ init() {
|
|
|
+ this.initChart()
|
|
|
+ this.loadData()
|
|
|
+ },
|
|
|
+
|
|
|
+ // 初始化图表
|
|
|
+ initChart() {
|
|
|
+ this.chartInstance = echarts.init(
|
|
|
+ document.getElementById("nowYearChart")
|
|
|
+ )
|
|
|
+
|
|
|
+ const option = {
|
|
|
+ tooltip: {
|
|
|
+ trigger: "axis",
|
|
|
+ axisPointer: {
|
|
|
+ type: "shadow",
|
|
|
+ },
|
|
|
+ backgroundColor: "rgba(17, 28, 49, 0.9)",
|
|
|
+ borderColor: "rgba(64, 158, 255, 0.2)",
|
|
|
+ textStyle: {
|
|
|
+ color: "#ffffff",
|
|
|
+ },
|
|
|
+ },
|
|
|
+ legend: {
|
|
|
+ data: ["进行中", "上月完成", "今年累计"],
|
|
|
+ textStyle: {
|
|
|
+ color: "#a0b3d6",
|
|
|
+ },
|
|
|
+ itemWidth: 16,
|
|
|
+ itemHeight: 8,
|
|
|
+ top: 10,
|
|
|
+ },
|
|
|
+ grid: {
|
|
|
+ left: "3%",
|
|
|
+ right: "4%",
|
|
|
+ bottom: "3%",
|
|
|
+ top: 50,
|
|
|
+ containLabel: true,
|
|
|
+ },
|
|
|
+ xAxis: {
|
|
|
+ type: "value",
|
|
|
+ show: false, // 隐藏x轴
|
|
|
+ axisLine: {
|
|
|
+ show: false,
|
|
|
+ },
|
|
|
+ axisTick: {
|
|
|
+ show: false,
|
|
|
+ },
|
|
|
+ axisLabel: {
|
|
|
+ show: false,
|
|
|
+ },
|
|
|
+ splitLine: {
|
|
|
+ show: false,
|
|
|
+ },
|
|
|
+ },
|
|
|
+ yAxis: {
|
|
|
+ type: "category",
|
|
|
+ data: this.chartData.categories,
|
|
|
+ show: true, // 隐藏y轴
|
|
|
+ axisLine: {
|
|
|
+ show: false,
|
|
|
+ },
|
|
|
+ axisTick: {
|
|
|
+ show: false,
|
|
|
+ },
|
|
|
+ axisLabel: {
|
|
|
+ show: true,
|
|
|
+ color: "#a1a1a1",
|
|
|
+ fontSize: 14,
|
|
|
+ },
|
|
|
+ },
|
|
|
+ series: [
|
|
|
+ {
|
|
|
+ name: "进行中",
|
|
|
+ type: "bar",
|
|
|
+ stack: "total",
|
|
|
+ emphasis: {
|
|
|
+ focus: "series",
|
|
|
+ },
|
|
|
+ itemStyle: {
|
|
|
+ color: new echarts.graphic.LinearGradient(0, 0, 1, 0, [
|
|
|
+ { offset: 0, color: "#1620D4" },
|
|
|
+ { offset: 0.8, color: "#3AB3E3" },
|
|
|
+ ]),
|
|
|
+ borderRadius: [20, 0, 0, 20],
|
|
|
+ },
|
|
|
+ label: {
|
|
|
+ show: true,
|
|
|
+ color: '#fff'
|
|
|
+ },
|
|
|
+ barWidth: 30,
|
|
|
+ barGap: "0%",
|
|
|
+ barCategoryGap: "20%",
|
|
|
+ data: this.chartData.ongoing,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: "上月完成",
|
|
|
+ type: "bar",
|
|
|
+ stack: "total",
|
|
|
+ emphasis: {
|
|
|
+ focus: "series",
|
|
|
+ },
|
|
|
+ itemStyle: {
|
|
|
+ color: new echarts.graphic.LinearGradient(0, 0, 1, 0, [
|
|
|
+ { offset: 0, color: "#192FC9" },
|
|
|
+ { offset: 0.8, color: "#6D44BC" },
|
|
|
+ ]),
|
|
|
+ borderRadius: [0, 0, 0, 0],
|
|
|
+ },
|
|
|
+ label: {
|
|
|
+ show: true,
|
|
|
+ color: '#fff'
|
|
|
+ },
|
|
|
+ barWidth: 30,
|
|
|
+ barGap: "0%",
|
|
|
+ data: this.chartData.lastMonthCompleted,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: "今年累计",
|
|
|
+ type: "bar",
|
|
|
+ stack: "total",
|
|
|
+ emphasis: {
|
|
|
+ focus: "series",
|
|
|
+ },
|
|
|
+ label: {
|
|
|
+ show: true,
|
|
|
+ color: '#fff'
|
|
|
+ },
|
|
|
+ itemStyle: {
|
|
|
+ color: new echarts.graphic.LinearGradient(0, 0, 1, 0, [
|
|
|
+ { offset: 0, color: "#F7897D" },
|
|
|
+ { offset: 0.8, color: "#F66C89" },
|
|
|
+ ]),
|
|
|
+ borderRadius: [0, 20, 20, 0],
|
|
|
+ },
|
|
|
+ barWidth: 30,
|
|
|
+ barGap: "0%",
|
|
|
+ data: this.chartData.yearTotal,
|
|
|
+ },
|
|
|
+ ],
|
|
|
+ }
|
|
|
+
|
|
|
+ this.chartInstance.setOption(option)
|
|
|
+ },
|
|
|
+
|
|
|
+ // 加载数据
|
|
|
+ async loadData() {
|
|
|
+ try {
|
|
|
+ const params = {
|
|
|
+ entCode: this.entCode,
|
|
|
+ communityId: this.communityId,
|
|
|
+ }
|
|
|
+ // 这里应该调用实际的API获取数据
|
|
|
+ // const res = await api.getNowYearServices(params)
|
|
|
+ // this.chartData = res.data || this.chartData
|
|
|
+
|
|
|
+ // 暂时使用模拟数据
|
|
|
+ this.updateChart()
|
|
|
+ } catch (error) {
|
|
|
+ console.error("获取今年实施服务数据失败:", error)
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ // 更新图表
|
|
|
+ updateChart() {
|
|
|
+ if (this.chartInstance) {
|
|
|
+ this.chartInstance.setOption({
|
|
|
+ yAxis: {
|
|
|
+ data: this.chartData.categories,
|
|
|
+ },
|
|
|
+ series: [
|
|
|
+ {
|
|
|
+ data: this.chartData.ongoing,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ data: this.chartData.lastMonthCompleted,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ data: this.chartData.yearTotal,
|
|
|
+ },
|
|
|
+ ],
|
|
|
+ })
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ // 处理窗口大小变化
|
|
|
+ handleResize() {
|
|
|
+ if (this.chartInstance) {
|
|
|
+ this.chartInstance.resize()
|
|
|
+ }
|
|
|
+ },
|
|
|
+ },
|
|
|
+ }
|
|
|
+</script>
|
|
|
+
|
|
|
+<style lang="scss" scoped>
|
|
|
+ @import "@/assets/css/theme.scss";
|
|
|
+
|
|
|
+ .now-year-container {
|
|
|
+ background: var(--title-bg);
|
|
|
+ border-radius: 4px;
|
|
|
+ padding: 20px;
|
|
|
+ height: 100%;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ }
|
|
|
+
|
|
|
+ .now-year-title {
|
|
|
+ font-size: 18px;
|
|
|
+ font-weight: 500;
|
|
|
+ color: var(--title-primary);
|
|
|
+ margin-bottom: 20px;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+
|
|
|
+ .iconfont {
|
|
|
+ margin-right: 8px;
|
|
|
+ font-size: 20px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .chart-container {
|
|
|
+ flex: 1;
|
|
|
+ min-height: 0;
|
|
|
+ position: relative;
|
|
|
+ // 添加自定义内容显示
|
|
|
+ &::before {
|
|
|
+ content: "";
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ justify-content: space-around;
|
|
|
+ position: absolute;
|
|
|
+ left: 20px;
|
|
|
+ top: 20px;
|
|
|
+ bottom: 20px;
|
|
|
+ width: 120px;
|
|
|
+ z-index: 1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .chart {
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ min-height: 400px;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 添加自定义标签显示
|
|
|
+ .chart-container::before {
|
|
|
+ content: "";
|
|
|
+ }
|
|
|
+
|
|
|
+ // 响应式设计
|
|
|
+ @media (max-width: 1200px) {
|
|
|
+ .now-year-container {
|
|
|
+ padding: 16px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .now-year-title {
|
|
|
+ font-size: 16px;
|
|
|
+ margin-bottom: 16px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .chart {
|
|
|
+ min-height: 350px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @media (max-width: 768px) {
|
|
|
+ .now-year-container {
|
|
|
+ padding: 12px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .now-year-title {
|
|
|
+ font-size: 14px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .chart {
|
|
|
+ min-height: 300px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+</style>
|