|
@@ -1,6 +1,9 @@
|
|
|
<template>
|
|
<template>
|
|
|
<div class="total-container">
|
|
<div class="total-container">
|
|
|
- <div class="total-title">实施服务(汇总数据)</div>
|
|
|
|
|
|
|
+ <div class="total-title">
|
|
|
|
|
+ <img src="@/assets/images/tj.png" class="title-icon" />
|
|
|
|
|
+ 实施服务(汇总数据
|
|
|
|
|
+ </div>
|
|
|
<div class="total-grid">
|
|
<div class="total-grid">
|
|
|
<div class="total-item">
|
|
<div class="total-item">
|
|
|
<div class="total-label">城市总数</div>
|
|
<div class="total-label">城市总数</div>
|
|
@@ -39,183 +42,181 @@
|
|
|
</template>
|
|
</template>
|
|
|
|
|
|
|
|
<script>
|
|
<script>
|
|
|
-import { mapState } from 'vuex'
|
|
|
|
|
-import { api } from '@/api'
|
|
|
|
|
-
|
|
|
|
|
-export default {
|
|
|
|
|
- name: 'ImplementationTotal',
|
|
|
|
|
- data () {
|
|
|
|
|
- return {
|
|
|
|
|
- cityCount: 99,
|
|
|
|
|
- enterpriseCount: 99,
|
|
|
|
|
- contractCount: 99,
|
|
|
|
|
- performanceCount: 99,
|
|
|
|
|
- serviceHours: 99,
|
|
|
|
|
- projectCount: 99,
|
|
|
|
|
- signedUserCount: 99,
|
|
|
|
|
- implementationUserCount: 99,
|
|
|
|
|
- timer: null
|
|
|
|
|
- }
|
|
|
|
|
- },
|
|
|
|
|
- computed: {
|
|
|
|
|
- ...mapState([
|
|
|
|
|
- 'entCode',
|
|
|
|
|
- 'communityId'
|
|
|
|
|
- ])
|
|
|
|
|
- },
|
|
|
|
|
- mounted () {
|
|
|
|
|
- this.init()
|
|
|
|
|
- // 设置定时刷新
|
|
|
|
|
- this.timer = setInterval(() => {
|
|
|
|
|
- this.init()
|
|
|
|
|
- }, 60000) // 每分钟刷新一次
|
|
|
|
|
- },
|
|
|
|
|
- beforeDestroy () {
|
|
|
|
|
- if (this.timer) {
|
|
|
|
|
- clearInterval(this.timer)
|
|
|
|
|
- }
|
|
|
|
|
- },
|
|
|
|
|
- methods: {
|
|
|
|
|
- // 初始化数据
|
|
|
|
|
- async init () {
|
|
|
|
|
- try {
|
|
|
|
|
- const params = {
|
|
|
|
|
- entCode: this.entCode,
|
|
|
|
|
- communityId: this.communityId
|
|
|
|
|
- }
|
|
|
|
|
- // 这里应该调用实际的API获取数据
|
|
|
|
|
- // const res = await api.getImplementationTotal(params)
|
|
|
|
|
- // 暂时使用模拟数据
|
|
|
|
|
- this.updateData()
|
|
|
|
|
- } catch (error) {
|
|
|
|
|
- console.error('获取实施服务汇总数据失败:', error)
|
|
|
|
|
|
|
+ import { mapState } from "vuex"
|
|
|
|
|
+ import { api } from "@/api"
|
|
|
|
|
+
|
|
|
|
|
+ export default {
|
|
|
|
|
+ name: "ImplementationTotal",
|
|
|
|
|
+ data() {
|
|
|
|
|
+ return {
|
|
|
|
|
+ cityCount: 99,
|
|
|
|
|
+ enterpriseCount: 99,
|
|
|
|
|
+ contractCount: 99,
|
|
|
|
|
+ performanceCount: 99,
|
|
|
|
|
+ serviceHours: 99,
|
|
|
|
|
+ projectCount: 99,
|
|
|
|
|
+ signedUserCount: 99,
|
|
|
|
|
+ implementationUserCount: 99,
|
|
|
|
|
+ timer: null,
|
|
|
}
|
|
}
|
|
|
},
|
|
},
|
|
|
- // 更新数据
|
|
|
|
|
- updateData () {
|
|
|
|
|
- // 这里可以根据实际API返回的数据进行更新
|
|
|
|
|
- // 目前使用固定值展示
|
|
|
|
|
- this.cityCount = 99
|
|
|
|
|
- this.enterpriseCount = 99
|
|
|
|
|
- this.contractCount = 99
|
|
|
|
|
- this.performanceCount = 99
|
|
|
|
|
- this.serviceHours = 99
|
|
|
|
|
- this.projectCount = 99
|
|
|
|
|
- this.signedUserCount = 99
|
|
|
|
|
- this.implementationUserCount = 99
|
|
|
|
|
|
|
+ computed: {
|
|
|
|
|
+ ...mapState(["entCode", "communityId"]),
|
|
|
},
|
|
},
|
|
|
- // 格式化数字显示
|
|
|
|
|
- formatNumber (num) {
|
|
|
|
|
- if (num >= 10000) {
|
|
|
|
|
- return (num / 10000).toFixed(1) + '万'
|
|
|
|
|
|
|
+ mounted() {
|
|
|
|
|
+ this.init()
|
|
|
|
|
+ // 设置定时刷新
|
|
|
|
|
+ this.timer = setInterval(() => {
|
|
|
|
|
+ this.init()
|
|
|
|
|
+ }, 60000) // 每分钟刷新一次
|
|
|
|
|
+ },
|
|
|
|
|
+ beforeDestroy() {
|
|
|
|
|
+ if (this.timer) {
|
|
|
|
|
+ clearInterval(this.timer)
|
|
|
}
|
|
}
|
|
|
- return num.toString()
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ },
|
|
|
|
|
+ methods: {
|
|
|
|
|
+ // 初始化数据
|
|
|
|
|
+ async init() {
|
|
|
|
|
+ try {
|
|
|
|
|
+ const params = {
|
|
|
|
|
+ entCode: this.entCode,
|
|
|
|
|
+ communityId: this.communityId,
|
|
|
|
|
+ }
|
|
|
|
|
+ // 这里应该调用实际的API获取数据
|
|
|
|
|
+ // const res = await api.getImplementationTotal(params)
|
|
|
|
|
+ // 暂时使用模拟数据
|
|
|
|
|
+ this.updateData()
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ console.error("获取实施服务汇总数据失败:", error)
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ // 更新数据
|
|
|
|
|
+ updateData() {
|
|
|
|
|
+ // 这里可以根据实际API返回的数据进行更新
|
|
|
|
|
+ // 目前使用固定值展示
|
|
|
|
|
+ this.cityCount = 99
|
|
|
|
|
+ this.enterpriseCount = 99
|
|
|
|
|
+ this.contractCount = 99
|
|
|
|
|
+ this.performanceCount = 99
|
|
|
|
|
+ this.serviceHours = 99
|
|
|
|
|
+ this.projectCount = 99
|
|
|
|
|
+ this.signedUserCount = 99
|
|
|
|
|
+ this.implementationUserCount = 99
|
|
|
|
|
+ },
|
|
|
|
|
+ // 格式化数字显示
|
|
|
|
|
+ formatNumber(num) {
|
|
|
|
|
+ if (num >= 10000) {
|
|
|
|
|
+ return (num / 10000).toFixed(1) + "万"
|
|
|
|
|
+ }
|
|
|
|
|
+ return num.toString()
|
|
|
|
|
+ },
|
|
|
|
|
+ },
|
|
|
}
|
|
}
|
|
|
-}
|
|
|
|
|
</script>
|
|
</script>
|
|
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
<style lang="scss" scoped>
|
|
|
-@import "@/assets/css/theme.scss";
|
|
|
|
|
-
|
|
|
|
|
-.total-container {
|
|
|
|
|
- background: var(--title-bg);
|
|
|
|
|
- border-radius: 4px;
|
|
|
|
|
- padding: 20px;
|
|
|
|
|
- position: relative;
|
|
|
|
|
- overflow: hidden;
|
|
|
|
|
-
|
|
|
|
|
- &::before {
|
|
|
|
|
- content: '';
|
|
|
|
|
- position: absolute;
|
|
|
|
|
- top: 0;
|
|
|
|
|
- left: 0;
|
|
|
|
|
- right: 0;
|
|
|
|
|
- height: 2px;
|
|
|
|
|
- background: linear-gradient(90deg, transparent, #409eff, transparent);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- .total-title {
|
|
|
|
|
- font-size: 18px;
|
|
|
|
|
- font-weight: 500;
|
|
|
|
|
- color: var(--title-primary);
|
|
|
|
|
- margin-bottom: 20px;
|
|
|
|
|
- text-align: center;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- .total-grid {
|
|
|
|
|
- display: grid;
|
|
|
|
|
- grid-template-columns: repeat(2, 1fr);
|
|
|
|
|
- grid-template-rows: repeat(4, 1fr);
|
|
|
|
|
- gap: 16px;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- .total-item {
|
|
|
|
|
- background: var(--content-bg);
|
|
|
|
|
- border-radius: 6px;
|
|
|
|
|
- padding: 16px;
|
|
|
|
|
- text-align: center;
|
|
|
|
|
- transition: all 0.3s ease;
|
|
|
|
|
- border: 1px solid rgba(64, 158, 255, 0.1);
|
|
|
|
|
-
|
|
|
|
|
- &:hover {
|
|
|
|
|
- transform: translateY(-2px);
|
|
|
|
|
- box-shadow: 0 4px 12px rgba(64, 158, 255, 0.2);
|
|
|
|
|
- border-color: rgba(64, 158, 255, 0.3);
|
|
|
|
|
|
|
+ @import "@/assets/css/theme.scss";
|
|
|
|
|
+
|
|
|
|
|
+ .total-container {
|
|
|
|
|
+ background: var(--title-bg);
|
|
|
|
|
+ border-radius: 4px;
|
|
|
|
|
+ padding: 20px;
|
|
|
|
|
+ position: relative;
|
|
|
|
|
+ overflow: hidden;
|
|
|
|
|
+
|
|
|
|
|
+ &::before {
|
|
|
|
|
+ content: "";
|
|
|
|
|
+ position: absolute;
|
|
|
|
|
+ top: 0;
|
|
|
|
|
+ left: 0;
|
|
|
|
|
+ right: 0;
|
|
|
|
|
+ height: 2px;
|
|
|
|
|
+ background: linear-gradient(90deg, transparent, #409eff, transparent);
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
- .total-label {
|
|
|
|
|
- font-size: 14px;
|
|
|
|
|
- color: #a0b3d6;
|
|
|
|
|
- margin-bottom: 8px;
|
|
|
|
|
|
|
+
|
|
|
|
|
+ .total-title {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ font-size: 18px;
|
|
|
|
|
+ font-weight: 500;
|
|
|
|
|
+ color: var(--title-primary);
|
|
|
|
|
+ margin-bottom: 20px;
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
- .total-value {
|
|
|
|
|
- font-size: 28px;
|
|
|
|
|
- font-weight: bold;
|
|
|
|
|
- color: #ffffff;
|
|
|
|
|
- line-height: 1.2;
|
|
|
|
|
- // 添加数字闪烁动画
|
|
|
|
|
- animation: pulse 2s infinite;
|
|
|
|
|
|
|
+
|
|
|
|
|
+ .total-grid {
|
|
|
|
|
+ display: grid;
|
|
|
|
|
+ grid-template-columns: repeat(2, 1fr);
|
|
|
|
|
+ grid-template-rows: repeat(4, 1fr);
|
|
|
|
|
+ gap: 16px;
|
|
|
}
|
|
}
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
|
|
|
|
|
-@keyframes pulse {
|
|
|
|
|
- 0% {
|
|
|
|
|
- opacity: 1;
|
|
|
|
|
- transform: scale(1);
|
|
|
|
|
- }
|
|
|
|
|
- 50% {
|
|
|
|
|
- opacity: 0.9;
|
|
|
|
|
- transform: scale(1.02);
|
|
|
|
|
- }
|
|
|
|
|
- 100% {
|
|
|
|
|
- opacity: 1;
|
|
|
|
|
- transform: scale(1);
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
|
|
+ .total-item {
|
|
|
|
|
+ background: var(--content-bg);
|
|
|
|
|
+ border-radius: 6px;
|
|
|
|
|
+ padding: 16px;
|
|
|
|
|
+ text-align: center;
|
|
|
|
|
+ transition: all 0.3s ease;
|
|
|
|
|
+ border: 1px solid rgba(64, 158, 255, 0.1);
|
|
|
|
|
|
|
|
-// 响应式设计
|
|
|
|
|
-@media (max-width: 1200px) {
|
|
|
|
|
- .total-grid {
|
|
|
|
|
- grid-template-columns: repeat(3, 1fr);
|
|
|
|
|
- grid-template-rows: repeat(3, 1fr);
|
|
|
|
|
|
|
+ &:hover {
|
|
|
|
|
+ transform: translateY(-2px);
|
|
|
|
|
+ box-shadow: 0 4px 12px rgba(64, 158, 255, 0.2);
|
|
|
|
|
+ border-color: rgba(64, 158, 255, 0.3);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .total-label {
|
|
|
|
|
+ font-size: 14px;
|
|
|
|
|
+ color: #a0b3d6;
|
|
|
|
|
+ margin-bottom: 8px;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .total-value {
|
|
|
|
|
+ font-size: 28px;
|
|
|
|
|
+ font-weight: bold;
|
|
|
|
|
+ color: #ffffff;
|
|
|
|
|
+ line-height: 1.2;
|
|
|
|
|
+ // 添加数字闪烁动画
|
|
|
|
|
+ animation: pulse 2s infinite;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
- .total-value {
|
|
|
|
|
- font-size: 24px !important;
|
|
|
|
|
|
|
+
|
|
|
|
|
+ @keyframes pulse {
|
|
|
|
|
+ 0% {
|
|
|
|
|
+ opacity: 1;
|
|
|
|
|
+ transform: scale(1);
|
|
|
|
|
+ }
|
|
|
|
|
+ 50% {
|
|
|
|
|
+ opacity: 0.9;
|
|
|
|
|
+ transform: scale(1.02);
|
|
|
|
|
+ }
|
|
|
|
|
+ 100% {
|
|
|
|
|
+ opacity: 1;
|
|
|
|
|
+ transform: scale(1);
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
-}
|
|
|
|
|
|
|
|
|
|
-@media (max-width: 768px) {
|
|
|
|
|
- .total-grid {
|
|
|
|
|
- grid-template-columns: repeat(2, 1fr);
|
|
|
|
|
- grid-template-rows: repeat(4, 1fr);
|
|
|
|
|
|
|
+ // 响应式设计
|
|
|
|
|
+ @media (max-width: 1200px) {
|
|
|
|
|
+ .total-grid {
|
|
|
|
|
+ grid-template-columns: repeat(3, 1fr);
|
|
|
|
|
+ grid-template-rows: repeat(3, 1fr);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .total-value {
|
|
|
|
|
+ font-size: 24px !important;
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
- .total-value {
|
|
|
|
|
- font-size: 20px !important;
|
|
|
|
|
|
|
+
|
|
|
|
|
+ @media (max-width: 768px) {
|
|
|
|
|
+ .total-grid {
|
|
|
|
|
+ grid-template-columns: repeat(2, 1fr);
|
|
|
|
|
+ grid-template-rows: repeat(4, 1fr);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .total-value {
|
|
|
|
|
+ font-size: 20px !important;
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
-}
|
|
|
|
|
-</style>
|
|
|
|
|
|
|
+</style>
|