| | |
| | | export function getDeviceCateData (data) { |
| | | return request.post('/visitsAdmin/cloudService/business/ywDevice/getDeviceCateData', data) |
| | | } |
| | | |
| | | // æ¹é导å
¥ |
| | | export function importExcel (data) { |
| | | return request.post('/visitsAdmin/cloudService/business/ywDevice/importExcel', data) |
| | | } |
| | |
| | | export function workDeskData () { |
| | | return request.get('/visitsAdmin/cloudService/business/ywWorkDesk/workDeskData') |
| | | } |
| | | |
| | | // çµè¡¨æ¥è¦ç±»åç»è®¡ |
| | | export function electricalWarningStats () { |
| | | return request.get('/visitsAdmin/cloudService/business/ywWorkDesk/electricalWarningStats') |
| | | } |
| | | |
| | | // çµè¡¨æ¥è¦å页 |
| | | export function electricalWarningPage (data) { |
| | | return request.post('/visitsAdmin/cloudService/business/ywWorkDesk/electricalWarningPage', data, { |
| | | trim: true |
| | | }) |
| | | } |
| | | |
| | | // è¿30天æºè½çµè¡¨æ¯æ¥çµé/çµè´¹ |
| | | export function electricalDailyEnergyStats () { |
| | | return request.get('/visitsAdmin/cloudService/business/ywWorkDesk/electricalDailyEnergyStats') |
| | | } |
| | | |
| | | // è¿30天空è°å¤èæºæ¯æ¥çµé/çµè´¹ |
| | | export function conditionerDailyEnergyStats () { |
| | | return request.get('/visitsAdmin/cloudService/business/ywWorkDesk/conditionerDailyEnergyStats') |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div class="daily-energy-panel"> |
| | | <div class="panel-header"> |
| | | <h3 class="panel-header__title">{{ title }}</h3> |
| | | </div> |
| | | <div class="panel_body" v-loading="loading"> |
| | | <div class="chart_box"> |
| | | <div ref="mixChart" class="chart_item"></div> |
| | | <div v-if="!loading && !hasData" class="chart_empty">ææ æ°æ®</div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import * as echarts from 'echarts' |
| | | |
| | | export default { |
| | | name: 'DailyEnergyTrendPanel', |
| | | props: { |
| | | title: { |
| | | type: String, |
| | | required: true |
| | | }, |
| | | loadData: { |
| | | type: Function, |
| | | required: true |
| | | } |
| | | }, |
| | | data () { |
| | | return { |
| | | loading: false, |
| | | statList: [], |
| | | chartInstance: null |
| | | } |
| | | }, |
| | | computed: { |
| | | hasData () { |
| | | return this.statList.some(item => Number(item.totalKwh) > 0 || Number(item.totalFee) > 0) |
| | | } |
| | | }, |
| | | mounted () { |
| | | this.fetchStats() |
| | | window.addEventListener('resize', this.handleResize) |
| | | }, |
| | | beforeDestroy () { |
| | | window.removeEventListener('resize', this.handleResize) |
| | | this.disposeChart() |
| | | }, |
| | | methods: { |
| | | fetchStats () { |
| | | this.loading = true |
| | | this.loadData() |
| | | .then(res => { |
| | | this.statList = res || [] |
| | | this.$nextTick(() => { |
| | | this.renderChart() |
| | | }) |
| | | }) |
| | | .finally(() => { |
| | | this.loading = false |
| | | }) |
| | | }, |
| | | disposeChart () { |
| | | if (this.chartInstance) { |
| | | this.chartInstance.dispose() |
| | | this.chartInstance = null |
| | | } |
| | | }, |
| | | renderChart () { |
| | | const chartDom = this.$refs.mixChart |
| | | if (!chartDom) { |
| | | return |
| | | } |
| | | if (!this.chartInstance) { |
| | | this.chartInstance = echarts.init(chartDom) |
| | | } |
| | | const dates = this.statList.map(item => item.statDate.substring(5)) |
| | | const kwhData = this.statList.map(item => Number(item.totalKwh || 0)) |
| | | const feeData = this.statList.map(item => Number(item.totalFee || 0)) |
| | | this.chartInstance.setOption({ |
| | | tooltip: { |
| | | trigger: 'axis', |
| | | axisPointer: { type: 'cross' }, |
| | | backgroundColor: 'rgba(255,255,255,0.96)', |
| | | borderColor: '#EEF2F8', |
| | | borderWidth: 1, |
| | | textStyle: { color: '#333', fontSize: 12 }, |
| | | extraCssText: 'border-radius: 6px;' |
| | | }, |
| | | legend: { |
| | | data: ['æ»çµé(kWh)', 'æ»çµè´¹(å
)'], |
| | | top: 0, |
| | | right: 0, |
| | | textStyle: { fontSize: 12, color: '#666' } |
| | | }, |
| | | grid: { |
| | | left: 50, |
| | | right: 50, |
| | | top: 36, |
| | | bottom: 28 |
| | | }, |
| | | xAxis: { |
| | | type: 'category', |
| | | data: dates, |
| | | axisLabel: { |
| | | fontSize: 11, |
| | | color: '#999', |
| | | interval: 4 |
| | | }, |
| | | axisLine: { lineStyle: { color: '#E8E8E8' } } |
| | | }, |
| | | yAxis: [ |
| | | { |
| | | type: 'value', |
| | | name: 'kWh', |
| | | nameTextStyle: { color: '#999', fontSize: 11 }, |
| | | axisLabel: { fontSize: 11, color: '#999' }, |
| | | splitLine: { lineStyle: { color: '#F0F0F0' } } |
| | | }, |
| | | { |
| | | type: 'value', |
| | | name: 'å
', |
| | | nameTextStyle: { color: '#999', fontSize: 11 }, |
| | | axisLabel: { fontSize: 11, color: '#999' }, |
| | | splitLine: { show: false } |
| | | } |
| | | ], |
| | | series: [ |
| | | { |
| | | name: 'æ»çµé(kWh)', |
| | | type: 'bar', |
| | | barMaxWidth: 24, |
| | | itemStyle: { |
| | | color: { |
| | | type: 'linear', |
| | | x: 0, |
| | | y: 0, |
| | | x2: 0, |
| | | y2: 1, |
| | | colorStops: [ |
| | | { offset: 0, color: '#5B9CF5' }, |
| | | { offset: 1, color: '#3E80EF' } |
| | | ] |
| | | }, |
| | | borderRadius: [3, 3, 0, 0] |
| | | }, |
| | | data: kwhData |
| | | }, |
| | | { |
| | | name: 'æ»çµè´¹(å
)', |
| | | type: 'line', |
| | | smooth: true, |
| | | yAxisIndex: 1, |
| | | symbol: 'circle', |
| | | symbolSize: 5, |
| | | itemStyle: { color: '#FFB020' }, |
| | | lineStyle: { width: 2, color: '#FFB020' }, |
| | | areaStyle: { |
| | | color: { |
| | | type: 'linear', |
| | | x: 0, |
| | | y: 0, |
| | | x2: 0, |
| | | y2: 1, |
| | | colorStops: [ |
| | | { offset: 0, color: 'rgba(255, 176, 32, 0.25)' }, |
| | | { offset: 1, color: 'rgba(255, 176, 32, 0.02)' } |
| | | ] |
| | | } |
| | | }, |
| | | data: feeData |
| | | } |
| | | ] |
| | | }, true) |
| | | }, |
| | | handleResize () { |
| | | if (this.chartInstance) { |
| | | this.chartInstance.resize() |
| | | } |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .daily-energy-panel { |
| | | flex: 1; |
| | | min-width: 0; |
| | | background: #FFFFFF; |
| | | border-radius: 10px; |
| | | padding: 20px; |
| | | box-sizing: border-box; |
| | | |
| | | .panel-header { |
| | | margin-bottom: 16px; |
| | | |
| | | &__title { |
| | | margin: 0; |
| | | padding-left: 10px; |
| | | font-weight: 600; |
| | | font-size: 18px; |
| | | color: #222222; |
| | | line-height: 1.4; |
| | | border-left: 3px solid #3E80EF; |
| | | } |
| | | } |
| | | |
| | | .panel_body { |
| | | min-height: 280px; |
| | | } |
| | | |
| | | .chart_box { |
| | | position: relative; |
| | | width: 100%; |
| | | padding: 12px; |
| | | background: #FAFBFE; |
| | | border-radius: 8px; |
| | | border: 1px solid #EEF2F8; |
| | | box-sizing: border-box; |
| | | |
| | | .chart_item { |
| | | width: 100%; |
| | | height: 280px; |
| | | } |
| | | |
| | | .chart_empty { |
| | | position: absolute; |
| | | inset: 12px; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | color: #999; |
| | | font-size: 14px; |
| | | background: #FAFBFE; |
| | | border-radius: 6px; |
| | | } |
| | | } |
| | | } |
| | | </style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div class="electrical-warning-panel"> |
| | | <div class="panel-header"> |
| | | <h3 class="panel-header__title">æ¥å¸¸çµéç®¡çæ¥è¦ä¿¡æ¯</h3> |
| | | </div> |
| | | <div class="panel_body"> |
| | | <div class="chart_box" v-loading="chartLoading"> |
| | | <div ref="warningChart" class="warning_chart"></div> |
| | | <div v-if="!chartLoading && !chartData.length" class="chart_empty">ææ æ¥è¦æ°æ®</div> |
| | | </div> |
| | | <div class="list_box"> |
| | | <el-table |
| | | v-loading="listLoading" |
| | | :data="warningList" |
| | | stripe |
| | | highlight-current-row |
| | | class="warning_table" |
| | | @row-click="handleRowClick" |
| | | > |
| | | <el-table-column label="åºå·" width="60" align="center"> |
| | | <template slot-scope="{ $index }"> |
| | | {{ (pagination.page - 1) * pagination.pageSize + $index + 1 }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="electricalName" label="çµè¡¨åç§°" min-width="120" align="center" show-overflow-tooltip /> |
| | | <el-table-column prop="deviceAddress" label="çµè¡¨å°å" min-width="120" align="center" show-overflow-tooltip /> |
| | | <el-table-column label="æ¥è¦é¡¹" min-width="160" align="center"> |
| | | <template slot-scope="{ row }"> |
| | | <span v-if="row.warningName" class="warn-tag">{{ row.warningName }}</span> |
| | | <span v-else>-</span> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="æ¥è¦æ¶é´" min-width="150" align="center"> |
| | | <template slot-scope="{ row }"> |
| | | {{ formatDateTime(row.startTime) }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="msg" label="æ¥è¦è¯¦æ
" min-width="160" align="center" show-overflow-tooltip /> |
| | | </el-table> |
| | | <div class="pagination_wrap"> |
| | | <Pagination |
| | | @size-change="handleSizeChange" |
| | | @current-change="loadWarningList" |
| | | :pagination="pagination" |
| | | /> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <YwElectricalRemote ref="remoteWindow" /> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import * as echarts from 'echarts' |
| | | import dayjs from 'dayjs' |
| | | import Pagination from '@/components/common/Pagination' |
| | | import { electricalWarningStats, electricalWarningPage } from '@/api/ywWorkDesk' |
| | | import YwElectricalRemote from '@/views/business/components/YwElectricalRemote' |
| | | |
| | | const CHART_COLORS = ['#8EC5FF', '#FF8C69', '#6B5BFF', '#52C41A', '#FFB020', '#9254DE', '#36CFC9', '#F759AB'] |
| | | |
| | | export default { |
| | | name: 'ElectricalWarningWorkbench', |
| | | components: { Pagination, YwElectricalRemote }, |
| | | data () { |
| | | return { |
| | | chartLoading: false, |
| | | listLoading: false, |
| | | chartData: [], |
| | | warningList: [], |
| | | chartInstance: null, |
| | | pagination: { |
| | | page: 1, |
| | | pageSize: 10, |
| | | total: 0 |
| | | } |
| | | } |
| | | }, |
| | | mounted () { |
| | | this.loadStats() |
| | | this.loadWarningList(1) |
| | | window.addEventListener('resize', this.handleResize) |
| | | }, |
| | | beforeDestroy () { |
| | | window.removeEventListener('resize', this.handleResize) |
| | | if (this.chartInstance) { |
| | | this.chartInstance.dispose() |
| | | this.chartInstance = null |
| | | } |
| | | }, |
| | | methods: { |
| | | loadStats () { |
| | | this.chartLoading = true |
| | | electricalWarningStats() |
| | | .then(res => { |
| | | this.chartData = (res || []).map((item, index) => ({ |
| | | name: `ãçµè½è¡¨ã${item.warningName}(${item.count})`, |
| | | value: item.count, |
| | | itemStyle: { color: CHART_COLORS[index % CHART_COLORS.length] } |
| | | })) |
| | | this.$nextTick(() => { |
| | | this.renderChart() |
| | | }) |
| | | }) |
| | | .finally(() => { |
| | | this.chartLoading = false |
| | | }) |
| | | }, |
| | | loadWarningList (page) { |
| | | this.listLoading = true |
| | | if (page) { |
| | | this.pagination.page = page |
| | | } |
| | | electricalWarningPage({ |
| | | page: this.pagination.page, |
| | | capacity: this.pagination.pageSize, |
| | | model: {} |
| | | }) |
| | | .then(res => { |
| | | this.warningList = res.records || [] |
| | | this.pagination.total = res.total || 0 |
| | | }) |
| | | .finally(() => { |
| | | this.listLoading = false |
| | | }) |
| | | }, |
| | | handleSizeChange (size) { |
| | | this.pagination.pageSize = size |
| | | this.loadWarningList(1) |
| | | }, |
| | | renderChart () { |
| | | const chartDom = this.$refs.warningChart |
| | | if (!chartDom) { |
| | | return |
| | | } |
| | | if (!this.chartInstance) { |
| | | this.chartInstance = echarts.init(chartDom) |
| | | } |
| | | this.chartInstance.setOption({ |
| | | tooltip: { |
| | | trigger: 'item', |
| | | formatter: '{b}: {c} ({d}%)', |
| | | backgroundColor: 'rgba(255,255,255,0.96)', |
| | | borderColor: '#EEF2F8', |
| | | borderWidth: 1, |
| | | textStyle: { color: '#333', fontSize: 12 } |
| | | }, |
| | | legend: { |
| | | type: 'scroll', |
| | | orient: 'vertical', |
| | | bottom: 8, |
| | | left: 'center', |
| | | height: 80, |
| | | pageButtonItemGap: 6, |
| | | pageIconSize: 10, |
| | | itemWidth: 12, |
| | | itemHeight: 12, |
| | | itemGap: 8, |
| | | textStyle: { |
| | | fontSize: 12, |
| | | color: '#666' |
| | | } |
| | | }, |
| | | series: [ |
| | | { |
| | | type: 'pie', |
| | | radius: ['45%', '62%'], |
| | | center: ['50%', '38%'], |
| | | avoidLabelOverlap: true, |
| | | label: { |
| | | show: false |
| | | }, |
| | | labelLine: { |
| | | show: false |
| | | }, |
| | | data: this.chartData |
| | | } |
| | | ] |
| | | }, true) |
| | | }, |
| | | handleResize () { |
| | | if (this.chartInstance) { |
| | | this.chartInstance.resize() |
| | | } |
| | | }, |
| | | handleRowClick (row) { |
| | | if (!row.electricalId) { |
| | | this.$message.warning('该æ¥è¦æªå
³èçµè¡¨ï¼æ æ³æå¼è¿ç¨æ§å¶') |
| | | return |
| | | } |
| | | this.$refs.remoteWindow.open({ id: row.electricalId }, 'basic') |
| | | }, |
| | | formatDateTime (value) { |
| | | if (!value) { |
| | | return '-' |
| | | } |
| | | return dayjs(value).format('YYYY-MM-DD HH:mm:ss') |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .electrical-warning-panel { |
| | | width: 100%; |
| | | background: #FFFFFF; |
| | | border-radius: 10px; |
| | | padding: 20px; |
| | | box-sizing: border-box; |
| | | |
| | | .panel-header { |
| | | margin-bottom: 16px; |
| | | |
| | | &__title { |
| | | margin: 0; |
| | | padding-left: 10px; |
| | | font-weight: 600; |
| | | font-size: 18px; |
| | | color: #222222; |
| | | line-height: 1.4; |
| | | border-left: 3px solid #3E80EF; |
| | | } |
| | | } |
| | | |
| | | .panel_body { |
| | | display: flex; |
| | | align-items: stretch; |
| | | gap: 20px; |
| | | } |
| | | |
| | | .chart_box { |
| | | position: relative; |
| | | width: 400px; |
| | | flex-shrink: 0; |
| | | min-height: 340px; |
| | | padding: 12px; |
| | | background: #FAFBFE; |
| | | border-radius: 8px; |
| | | border: 1px solid #EEF2F8; |
| | | box-sizing: border-box; |
| | | |
| | | .warning_chart { |
| | | width: 100%; |
| | | height: 316px; |
| | | } |
| | | |
| | | .chart_empty { |
| | | position: absolute; |
| | | inset: 0; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | color: #999; |
| | | font-size: 14px; |
| | | } |
| | | } |
| | | |
| | | .list_box { |
| | | flex: 1; |
| | | min-width: 0; |
| | | display: flex; |
| | | flex-direction: column; |
| | | padding-left: 4px; |
| | | border-left: 1px solid #EEF2F8; |
| | | } |
| | | |
| | | .warning_table { |
| | | width: 100%; |
| | | |
| | | ::v-deep tbody tr { |
| | | cursor: pointer; |
| | | } |
| | | } |
| | | |
| | | .pagination_wrap { |
| | | margin-top: 12px; |
| | | } |
| | | |
| | | .warn-tag { |
| | | display: inline-block; |
| | | color: #f56c6c; |
| | | border: 1px solid #f56c6c; |
| | | border-radius: 4px; |
| | | padding: 0 6px; |
| | | margin: 2px; |
| | | font-size: 12px; |
| | | line-height: 20px; |
| | | white-space: nowrap; |
| | | } |
| | | } |
| | | |
| | | @media (max-width: 1200px) { |
| | | .electrical-warning-panel { |
| | | .panel_body { |
| | | flex-direction: column; |
| | | } |
| | | |
| | | .chart_box { |
| | | width: 100%; |
| | | } |
| | | |
| | | .list_box { |
| | | padding-left: 0; |
| | | border-left: none; |
| | | padding-top: 4px; |
| | | border-top: 1px solid #EEF2F8; |
| | | } |
| | | } |
| | | } |
| | | </style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <el-dialog |
| | | class="center-title" |
| | | :title="title" |
| | | width="500px" |
| | | top="30vh" |
| | | :visible.sync="visible" |
| | | :confirm-working="isWorking" |
| | | @confirm="confirm" |
| | | > |
| | | <p class="tip-warn"><i class="el-icon-warning"></i>导å
¥è¯´æï¼<br> |
| | | 1.请å
ä¸è½½æä»¶æ¨¡æ¿ï¼å¹¶æç
§æ¨¡æ¿è¦æ±å¡«åè¡¨æ ¼å
容;<br> |
| | | 2.带*为å¿
填项ï¼å
³èæ¿æºæ ¼å¼ä¸ºï¼æ¥¼å®/楼å±/æ¿æº;<br> |
| | | 3.设å¤åç±»æ ¼å¼ä¸ºï¼ä¸çº§åç±»/äºçº§åç±»;<br> |
| | | </p> |
| | | <el-form class="demo-form-inline"> |
| | | <el-form-item label="设å¤åå" required> |
| | | <div style="width: 100%;display: flex;align-items: center;"> |
| | | <el-button type="primary" @click="clickRef">ç¹å»ä¸ä¼ </el-button> |
| | | <el-button type="text" @click="exportTemplate">ç¹å»ä¸è½½æ¨¡ç.EXCEL</el-button> |
| | | </div> |
| | | <div style="font-size: 14px; color: black;" v-if="fileName">{{ fileName }}</div> |
| | | </el-form-item> |
| | | </el-form> |
| | | <input type="file" style="position: fixed; left: 0; top: -50px;" accept=".xlsx" ref="fileExcel" @change="result" /> |
| | | <template v-slot:footer> |
| | | <el-button @click="visible=false">è¿å</el-button> |
| | | </template> |
| | | </el-dialog> |
| | | </template> |
| | | |
| | | <script> |
| | | import BaseOpera from '@/components/base/BaseOpera' |
| | | import GlobalWindow from '@/components/common/GlobalWindow' |
| | | import { importExcel } from '@/api/Inspection/device' |
| | | export default { |
| | | name: 'OperaDeviceImportWindow', |
| | | extends: BaseOpera, |
| | | // eslint-disable-next-line vue/no-unused-components |
| | | components: { GlobalWindow }, |
| | | data () { |
| | | return { |
| | | importing: false, |
| | | fileName: '' |
| | | } |
| | | }, |
| | | methods: { |
| | | open (title) { |
| | | this.title = title |
| | | this.fileName = '' |
| | | this.visible = true |
| | | }, |
| | | exportTemplate () { |
| | | window.open('/template/yw_device.xlsx') |
| | | }, |
| | | clickRef () { |
| | | this.$refs.fileExcel.click() |
| | | }, |
| | | result (e) { |
| | | const file = e.target.files[0] |
| | | if (!file) { |
| | | return |
| | | } |
| | | this.fileName = file.name |
| | | const data = new FormData() |
| | | data.append('file', file) |
| | | importExcel(data) |
| | | .then(res => { |
| | | this.$message.success(res || 'æä½æå') |
| | | this.$emit('success') |
| | | this.visible = false |
| | | }) |
| | | .catch(() => { |
| | | this.fileName = '' |
| | | }) |
| | | .finally(() => { |
| | | this.$refs.fileExcel.value = null |
| | | }) |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | |
| | | </style> |
| | |
| | | <span>è¯·æ ¹æ®ä½¿ç¨ä¹ æ¯èªå®ä¹å¸¸ç¨åè½ï¼æ¯ææå¨æ</span> |
| | | <draggable v-model="filterList" chosenClass="chosen" forceFallback="true" group="people" animation="1000"> |
| | | <transition-group class="dra"> |
| | | <div class="list" v-for="(item, index) in filterList" :key="index"> |
| | | <div class="list" v-for="item in filterList" :key="item.path || item.id"> |
| | | <div class="list_checkbox"> |
| | | <el-checkbox v-model="item.checked"> </el-checkbox> |
| | | </div> |
| | |
| | | <script> |
| | | import BaseOpera from '@/components/base/BaseOpera' |
| | | import GlobalWindow from '@/components/common/GlobalWindow' |
| | | import { updMyYwQuickModel, getDefaultYwQuickList } from '@/api/ywWorkDesk' |
| | | import { updMyYwQuickModel, getDefaultYwQuickList, getYwQuickList } from '@/api/ywWorkDesk' |
| | | import draggable from 'vuedraggable' |
| | | export default { |
| | | name: 'commonFunctions', |
| | |
| | | methods: { |
| | | open (title) { |
| | | this.title = title |
| | | getDefaultYwQuickList({}) |
| | | .then(res => { |
| | | res.forEach(item => { |
| | | item.checked = false |
| | | Promise.all([getDefaultYwQuickList(), getYwQuickList()]) |
| | | .then(([allList, myList]) => { |
| | | const selectedPaths = (myList || []).map(item => item.path) |
| | | const pathOrder = new Map(selectedPaths.map((path, index) => [path, index])) |
| | | const selected = [] |
| | | const unselected = [] |
| | | ;(allList || []).forEach(item => { |
| | | const entry = { ...item, checked: selectedPaths.includes(item.path) } |
| | | if (entry.checked) { |
| | | selected.push(entry) |
| | | } else { |
| | | unselected.push(entry) |
| | | } |
| | | }) |
| | | this.filterList = res |
| | | selected.sort((a, b) => (pathOrder.get(a.path) || 0) - (pathOrder.get(b.path) || 0)) |
| | | this.filterList = [...selected, ...unselected] |
| | | this.visible = true |
| | | }) |
| | | .catch(e => this.$tip.apiFailed(e)) |
| | | }, |
| | | confirm () { |
| | | this.isWorking = true |
| | |
| | | import { mapState } from 'vuex' |
| | | import MenuItems from './MenuItems' |
| | | import Scrollbar from './Scrollbar' |
| | | import { findMenuByUrl, getOpenMenuIndexes } from '@/utils/menu' |
| | | export default { |
| | | name: 'Menu', |
| | | components: { Scrollbar, MenuItems }, |
| | |
| | | ...mapState(['menuData']), |
| | | // éä¸çèåindex |
| | | activeIndex() { |
| | | let path = this.$route.path |
| | | if (path.endsWith('/')) { |
| | | path = path.substring(0, path.length - 1) |
| | | } |
| | | const menuConfig = this.__getMenuConfig(path, 'index', this.menuData.list) |
| | | if (menuConfig == null) { |
| | | return null |
| | | } else { |
| | | this.$store.commit('pushtags', menuConfig) |
| | | } |
| | | return menuConfig.index |
| | | const menuConfig = findMenuByUrl(this.$route.path, this.menuData.list) |
| | | return menuConfig ? menuConfig.index : null |
| | | }, |
| | | // é»è®¤å±å¼çèåindex |
| | | defaultOpeneds() { |
| | | // return this.menuData.list.map(menu => menu.index) |
| | | |
| | | return [this.menuData.list[0].index] |
| | | const openeds = getOpenMenuIndexes(this.$route.path, this.menuData.list) |
| | | if (openeds.length > 0) { |
| | | return openeds |
| | | } |
| | | return this.menuData.list.length > 0 ? [this.menuData.list[0].index] : [] |
| | | } |
| | | }, |
| | | watch: { |
| | | '$route': { |
| | | handler () { |
| | | this.syncMenuState() |
| | | }, |
| | | immediate: true |
| | | } |
| | | }, |
| | | methods: { |
| | | syncMenuState () { |
| | | const menuConfig = findMenuByUrl(this.$route.path, this.menuData.list) |
| | | if (menuConfig) { |
| | | this.$store.commit('pushtags', menuConfig) |
| | | } |
| | | this.$nextTick(() => { |
| | | const menuRef = this.$refs.menu |
| | | if (!menuRef) { |
| | | return |
| | | } |
| | | getOpenMenuIndexes(this.$route.path, this.menuData.list).forEach(index => { |
| | | menuRef.open(index) |
| | | }) |
| | | }) |
| | | }, |
| | | // å¤çèåéä¸ |
| | | handleSelect(menuIndex) { |
| | | const menuConfig = this.__getMenuConfig(menuIndex, 'index', this.menuData.list) |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | function normalizePath (path) { |
| | | if (!path) { |
| | | return '' |
| | | } |
| | | let normalized = path |
| | | if (normalized.endsWith('/')) { |
| | | normalized = normalized.substring(0, normalized.length - 1) |
| | | } |
| | | return normalized |
| | | } |
| | | |
| | | export function findMenuByUrl (url, menus) { |
| | | const target = normalizePath(url) |
| | | for (const menu of menus || []) { |
| | | if (menu.url && normalizePath(menu.url) === target) { |
| | | return menu |
| | | } |
| | | if (menu.children && menu.children.length > 0) { |
| | | const child = findMenuByUrl(target, menu.children) |
| | | if (child) { |
| | | return child |
| | | } |
| | | } |
| | | } |
| | | return null |
| | | } |
| | | |
| | | export function findMenuPathByUrl (url, menus, ancestors = []) { |
| | | const target = normalizePath(url) |
| | | for (const menu of menus || []) { |
| | | const chain = [...ancestors, menu] |
| | | if (menu.url && normalizePath(menu.url) === target) { |
| | | return chain |
| | | } |
| | | if (menu.children && menu.children.length > 0) { |
| | | const childChain = findMenuPathByUrl(target, menu.children, chain) |
| | | if (childChain) { |
| | | return childChain |
| | | } |
| | | } |
| | | } |
| | | return null |
| | | } |
| | | |
| | | export function getOpenMenuIndexes (url, menus) { |
| | | const chain = findMenuPathByUrl(url, menus) |
| | | if (!chain || chain.length <= 1) { |
| | | return [] |
| | | } |
| | | return chain.slice(0, -1).map(menu => menu.index) |
| | | } |
| | | |
| | | export function navigateByMenu (router, store, path, menus) { |
| | | const menuConfig = findMenuByUrl(path, menus) |
| | | if (menuConfig) { |
| | | if (menuConfig.params) { |
| | | router.push({ |
| | | path: menuConfig.url, |
| | | query: { index: menuConfig.index, param: menuConfig.params } |
| | | }) |
| | | } else { |
| | | router.push(menuConfig.url) |
| | | } |
| | | store.commit('pushtags', menuConfig) |
| | | return |
| | | } |
| | | router.push({ path }) |
| | | } |
| | |
| | | <template> |
| | | <div v-loading="loading" class="conditioner-tab"> |
| | | <el-form ref="configForm" :model="form" :rules="rules" label-width="150px" size="small" class="config-form"> |
| | | <section class="config-section"> |
| | | <div class="section-title">计费é
ç½®</div> |
| | | <el-form label-width="150px" size="small" class="config-form"> |
| | | <el-row :gutter="24"> |
| | | <el-row :gutter="24" class="config-first-row"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="计费å¼å
³"> |
| | | <el-switch v-model="form.isPwr" :active-value="1" :inactive-value="0" active-text="å¼å¯" inactive-text="å
³é"/> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="18:00-09:00 ä¸åæº"> |
| | | <el-switch v-model="form.isRestStop" :active-value="1" :inactive-value="0" active-text="æ¯" inactive-text="å¦"/> |
| | | <el-form-item label="æ¬ è´¹é¢åº¦" prop="stopMoney" class="stop-money-item"> |
| | | <div class="el-input-group stop-money-group"> |
| | | <el-input-number |
| | | v-model="form.stopMoney" |
| | | :min="0" |
| | | :precision="2" |
| | | :step="10" |
| | | controls-position="right" |
| | | class="stop-money-input" |
| | | /> |
| | | <div class="el-input-group__append">å
</div> |
| | | </div> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="24"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="æ¬ è´¹é¢åº¦ï¼å
ï¼"> |
| | | <el-input-number v-model="form.stopMoney" :min="0" :precision="2" :step="10" controls-position="right" style="width: 100%"/> |
| | | <el-form-item label="计费å¼å
³" prop="isPwr"> |
| | | <el-switch v-model="form.isPwr" :active-value="1" :inactive-value="0" active-text="å¼å¯" inactive-text="å
³é"/> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="18:00-09:00 ä¸åæº" prop="isRestStop"> |
| | | <el-switch v-model="form.isRestStop" :active-value="1" :inactive-value="0" active-text="æ¯" inactive-text="å¦"/> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | |
| | | placeholder="请è¾å
¥å¤æ³¨ï¼éå¡«ï¼" |
| | | /> |
| | | </el-form-item> |
| | | </el-form> |
| | | </section> |
| | | |
| | | <section class="config-section"> |
| | | <div class="section-header"> |
| | | <span class="section-title">å
³èå
æº</span> |
| | | <span class="section-title required-title">å
³èå
æº</span> |
| | | <el-button type="primary" size="small" icon="el-icon-plus" @click="openSelector">æ·»å å
æº</el-button> |
| | | </div> |
| | | <el-form-item prop="conditioners" label-width="0" class="conditioners-form-item"> |
| | | <el-table :data="form.conditioners" stripe size="small" class="device-table" empty-text="ææªå
³èå
æºï¼è¯·ç¹å»æ·»å "> |
| | | <el-table-column label="设å¤" min-width="200" align="left" show-overflow-tooltip> |
| | | <template slot-scope="{ row }">{{ deviceLabel(row) }}</template> |
| | |
| | | </el-table-column> |
| | | <el-table-column label="æä½" width="80" align="center" fixed="right"> |
| | | <template slot-scope="{ $index }"> |
| | | <el-button type="text" class="red" @click="form.conditioners.splice($index, 1)">ç§»é¤</el-button> |
| | | <el-button type="text" class="red" @click="removeConditioner($index)">ç§»é¤</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </el-form-item> |
| | | </section> |
| | | </el-form> |
| | | |
| | | <div class="footer-btns"> |
| | | <el-button type="primary" :loading="saving" v-permissions="['business:ywcustomerrecharge:bindDevice']" @click="save">ä¿åé
ç½®</el-button> |
| | |
| | | loading: false, |
| | | saving: false, |
| | | form: { |
| | | isPwr: 1, |
| | | isRestStop: 0, |
| | | stopMoney: 0, |
| | | isPwr: null, |
| | | isRestStop: null, |
| | | stopMoney: undefined, |
| | | gsBz: '', |
| | | conditioners: [] |
| | | }, |
| | | rules: { |
| | | stopMoney: [{ |
| | | validator: (rule, value, callback) => { |
| | | if (value === null || value === undefined || value === '') { |
| | | callback(new Error('请è¾å
¥æ¬ è´¹é¢åº¦')) |
| | | } else if (Number(value) < 0) { |
| | | callback(new Error('æ¬ è´¹é¢åº¦ä¸è½å°äº0')) |
| | | } else { |
| | | callback() |
| | | } |
| | | }, |
| | | trigger: 'blur' |
| | | }], |
| | | isPwr: [{ |
| | | validator: (rule, value, callback) => { |
| | | if (value === 0 || value === 1) callback() |
| | | else callback(new Error('è¯·éæ©è®¡è´¹å¼å
³')) |
| | | }, |
| | | trigger: 'change' |
| | | }], |
| | | isRestStop: [{ |
| | | validator: (rule, value, callback) => { |
| | | if (value === 0 || value === 1) callback() |
| | | else callback(new Error('è¯·éæ©æ¯å¦åæº')) |
| | | }, |
| | | trigger: 'change' |
| | | }], |
| | | conditioners: [{ |
| | | validator: (rule, value, callback) => { |
| | | if (value && value.length) callback() |
| | | else callback(new Error('请è³å°å
³èä¸å°å
æº')) |
| | | }, |
| | | trigger: 'change' |
| | | }] |
| | | }, |
| | | selectorVisible: false, |
| | | selectorLoading: false, |
| | |
| | | rechargeApi.conditionerPage(this.customerId, { page: 1, capacity: 500, model: {} }) |
| | | ]).then(([gs, page]) => { |
| | | if (gs) { |
| | | this.form.isPwr = gs.isPwr != null ? gs.isPwr : 1 |
| | | this.form.isRestStop = gs.isRestStop != null ? gs.isRestStop : 0 |
| | | this.form.stopMoney = gs.stopMoney != null ? gs.stopMoney : 0 |
| | | this.form.isPwr = gs.isPwr != null ? gs.isPwr : null |
| | | this.form.isRestStop = gs.isRestStop != null ? gs.isRestStop : null |
| | | this.form.stopMoney = gs.stopMoney != null ? gs.stopMoney : undefined |
| | | this.form.gsBz = gs.gsBz || '' |
| | | } else { |
| | | this.form.isPwr = 1 |
| | | this.form.isRestStop = 0 |
| | | this.form.stopMoney = 0 |
| | | this.form.isPwr = null |
| | | this.form.isRestStop = null |
| | | this.form.stopMoney = undefined |
| | | this.form.gsBz = '' |
| | | } |
| | | this.form.conditioners = (page.records || []).map(c => ({ |
| | |
| | | online: c.online, |
| | | devRatio: c.devRatio != null ? c.devRatio : 100 |
| | | })) |
| | | this.$nextTick(() => { |
| | | if (this.$refs.configForm) { |
| | | this.$refs.configForm.clearValidate() |
| | | } |
| | | }) |
| | | }).catch(e => this.$tip.apiFailed(e)).finally(() => { this.loading = false }) |
| | | }, |
| | | save () { |
| | | if (!this.form.conditioners.length) { |
| | | this.$tip.warning('请è³å°å
³èä¸å°å
æº') |
| | | return |
| | | } |
| | | this.$refs.configForm.validate(valid => { |
| | | if (!valid) return |
| | | this.saving = true |
| | | rechargeApi.saveGsConfig({ |
| | | customerId: this.customerId, |
| | |
| | | this.loadConfig() |
| | | this.$emit('success') |
| | | }).catch(e => this.$tip.apiFailed(e)).finally(() => { this.saving = false }) |
| | | }) |
| | | }, |
| | | removeConditioner (index) { |
| | | this.form.conditioners.splice(index, 1) |
| | | this.$nextTick(() => { |
| | | if (this.$refs.configForm) { |
| | | this.$refs.configForm.validateField('conditioners') |
| | | } |
| | | }) |
| | | }, |
| | | openSelector () { |
| | | this.selectorVisible = true |
| | |
| | | }) |
| | | }) |
| | | this.selectorVisible = false |
| | | this.$nextTick(() => { |
| | | if (this.$refs.configForm) { |
| | | this.$refs.configForm.validateField('conditioners') |
| | | } |
| | | }) |
| | | } |
| | | } |
| | | } |
| | |
| | | .config-form { |
| | | margin-bottom: 0; |
| | | } |
| | | .config-first-row { |
| | | margin-bottom: 4px; |
| | | padding-bottom: 4px; |
| | | border-bottom: 1px dashed #ebeef5; |
| | | } |
| | | .config-form ::v-deep .stop-money-item { |
| | | margin-bottom: 8px; |
| | | } |
| | | .stop-money-group { |
| | | display: inline-flex; |
| | | width: 100%; |
| | | max-width: 280px; |
| | | vertical-align: middle; |
| | | } |
| | | .stop-money-group ::v-deep .stop-money-input { |
| | | flex: 1; |
| | | width: auto; |
| | | } |
| | | .stop-money-group ::v-deep .el-input-number { |
| | | width: 100%; |
| | | } |
| | | .stop-money-group ::v-deep .el-input__inner { |
| | | border-top-right-radius: 0; |
| | | border-bottom-right-radius: 0; |
| | | } |
| | | .config-form ::v-deep .el-form-item { |
| | | margin-bottom: 12px; |
| | | } |
| | |
| | | .config-form ::v-deep .el-switch { |
| | | width: auto; |
| | | } |
| | | .required-title::before { |
| | | content: '*'; |
| | | color: #f56c6c; |
| | | margin-right: 4px; |
| | | } |
| | | .conditioners-form-item { |
| | | margin-bottom: 0; |
| | | } |
| | | .conditioners-form-item ::v-deep .el-form-item__content { |
| | | margin-left: 0 !important; |
| | | } |
| | | .conditioners-form-item ::v-deep .el-form-item__error { |
| | | padding-top: 4px; |
| | | } |
| | | .device-table { |
| | | width: 100%; |
| | | } |
| | |
| | | <template> |
| | | <GlobalWindow title="çµè¡¨è¿ç¨æ§å¶" :visible.sync="visible" width="780px" :show-confirm="false"> |
| | | <el-tabs v-model="activeTab"> |
| | | <el-tabs v-model="activeTab" @tab-click="onTabClick"> |
| | | <el-tab-pane label="åºæ¬æä½" name="basic"> |
| | | <div class="info-block"> |
| | | <p>ééå¨å·ï¼{{ info.collectorId }} <span :class="info.online === 1 ? 'green' : 'red'">{{ info.online === 1 ? 'å¨çº¿' : '离线' }}</span></p> |
| | |
| | | <p>çµè¡¨ç±»åï¼{{ info.type }}</p> |
| | | <p>å
³èæ¿é´ï¼{{ info.roomNames }}</p> |
| | | </div> |
| | | <div class="meter-data-block" v-loading="infoLoading"> |
| | | <div class="meter-data-block__title">ææ°æè¡¨æ°æ®</div> |
| | | <p>å½åæ»çµéï¼{{ totalPower }}</p> |
| | | <p>çµé忥æ¶é´ï¼{{ latest && latest.addTime ? latest.addTime : '-' }}</p> |
| | | <p>å½åå©ä½éé¢(å
)ï¼{{ latest && latest.ye != null ? latest.ye : (info.balance != null ? info.balance : '0.0000') }}</p> |
| | | <p>ä½é¢åæ¥æ¶é´ï¼{{ balanceSyncTime }}</p> |
| | | </div> |
| | | <div class="btn-row"> |
| | | <el-button type="primary" :loading="isOperating" @click="doOperate('resetPrepay', '确认æ¸
é¶å¹¶åæ¢å°é¢ä»è´¹æ¨¡å¼åï¼')">æ¸
é¶å¹¶åæ¢å°é¢ä»è´¹æ¨¡å¼</el-button> |
| | | <el-button type="primary" :loading="isOperating" @click="doOperate('resetPostpay', '确认æ¸
é¶å¹¶åæ¢å°åä»è´¹æ¨¡å¼åï¼')">æ¸
é¶å¹¶åæ¢å°åä»è´¹æ¨¡å¼</el-button> |
| | | <el-button type="primary" :loading="isOperating" @click="doOperate('trip', '确认æé¸åï¼')">æé¸</el-button> |
| | | <el-button type="primary" :loading="isOperating" @click="doOperate('close', '确认åé¸åï¼')">åé¸</el-button> |
| | | </div> |
| | | <div class="btn-row btn-row--relay"> |
| | | <span class="btn-row__label">æå鏿ä½</span> |
| | | <el-button type="danger" :loading="isOperating" @click="doRelayOperate('trip')">æé¸</el-button> |
| | | <el-button type="primary" :loading="isOperating" @click="doRelayOperate('close')">åé¸</el-button> |
| | | <el-button type="warning" :loading="isOperating" @click="doRelayOperate('powerProtect')">ä¿çµ</el-button> |
| | | <el-button type="danger" plain :loading="isOperating" @click="doRelayOperate('powerProtectRelease')">è§£é¤ä¿çµ</el-button> |
| | | </div> |
| | | </el-tab-pane> |
| | | <el-tab-pane label="弿·" name="open"> |
| | |
| | | @confirm="doOperate('recharge', '确认å
å¼åï¼')" |
| | | /> |
| | | </el-tab-pane> |
| | | <el-tab-pane label="æ§å¶è®°å½" name="records"> |
| | | <el-table v-loading="recordsLoading" :data="recordsList" stripe size="small" class="records-table"> |
| | | <el-table-column label="æä½ç±»å" min-width="100" align="center"> |
| | | <template slot-scope="{ row }">{{ formatActionType(row.actionType) }}</template> |
| | | </el-table-column> |
| | | <el-table-column prop="oprId" label="æä½ID" min-width="150" align="center" show-overflow-tooltip /> |
| | | <el-table-column label="ç¶æ" min-width="80" align="center"> |
| | | <template slot-scope="{ row }"> |
| | | <span :class="statusClass(row.status)">{{ formatStatus(row.status) }}</span> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="resultMsg" label="æ§è¡ç»æ" min-width="140" align="center" show-overflow-tooltip> |
| | | <template slot-scope="{ row }">{{ row.resultMsg || '-' }}</template> |
| | | </el-table-column> |
| | | <el-table-column prop="createDate" label="æä½æ¶é´" min-width="150" align="center" /> |
| | | <el-table-column label="æ¥æ" min-width="120" align="center"> |
| | | <template slot-scope="{ row }"> |
| | | <el-button type="text" :disabled="!row.requestBody" @click="openJson('è¯·æ±æ¥æ', row.requestBody)">请æ±</el-button> |
| | | <el-button type="text" :disabled="!row.responseBody" @click="openJson('ååºæ¥æ', row.responseBody)">ååº</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="æä½" min-width="100" align="center" fixed="right"> |
| | | <template slot-scope="{ row }"> |
| | | <el-button |
| | | v-if="row.status === 0 && row.oprId" |
| | | type="text" |
| | | :loading="queryLoadingId === row.id" |
| | | v-permissions="['business:ywelectricalactions:queryResult']" |
| | | @click="handleQueryResult(row)" |
| | | >æ¥è¯¢ç»æ</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | <pagination |
| | | small |
| | | @size-change="handleRecordsSizeChange" |
| | | @current-change="loadActionRecords" |
| | | :pagination="recordsPagination" |
| | | /> |
| | | </el-tab-pane> |
| | | </el-tabs> |
| | | <OperaInterfaceLogWindow ref="jsonWindow" /> |
| | | <template slot="footer"> |
| | | <el-button type="primary" icon="el-icon-refresh" :loading="isRefreshing" @click="refreshMeterData">å·æ°çµè¡¨æ°æ®</el-button> |
| | | <el-button @click="visible = false">è¿å</el-button> |
| | | </template> |
| | | </GlobalWindow> |
| | | </template> |
| | | |
| | | <script> |
| | | import GlobalWindow from '@/components/common/GlobalWindow' |
| | | import Pagination from '@/components/common/Pagination' |
| | | import OperaInterfaceLogWindow from '@/components/business/OperaInterfaceLogWindow' |
| | | import { getRemoteInfo, operate } from '@/api/business/ywelectrical' |
| | | import * as actionsApi from '@/api/business/ywelectricalactions' |
| | | import AccountRechargePanel from './AccountRechargePanel' |
| | | |
| | | const RELAY_ACTIONS = { |
| | | trip: { label: 'æé¸', message: '确认对该çµè¡¨æ§è¡æé¸æä½åï¼' }, |
| | | close: { label: 'åé¸', message: '确认对该çµè¡¨æ§è¡å鏿ä½åï¼' }, |
| | | powerProtect: { label: 'ä¿çµ', message: '确认对该çµè¡¨æ§è¡ä¿çµæä½åï¼' }, |
| | | powerProtectRelease: { label: 'è§£é¤ä¿çµ', message: '确认对该çµè¡¨æ§è¡è§£é¤ä¿çµæä½åï¼' } |
| | | } |
| | | |
| | | const ACTION_TYPE_MAP = { |
| | | 1: 'é¢ä»è´¹æ¸
é¶', |
| | | 2: 'åä»è´¹æ¸
é¶', |
| | | 3: 'è¿ç¨éæ·', |
| | | 4: 'æé¸', |
| | | 5: 'åé¸', |
| | | 6: '弿·', |
| | | 7: 'å
å¼', |
| | | 8: 'æè¡¨', |
| | | 9: 'ä¿çµ', |
| | | 10: 'è§£é¤ä¿çµ' |
| | | } |
| | | |
| | | export default { |
| | | name: 'YwElectricalRemote', |
| | | components: { GlobalWindow, AccountRechargePanel }, |
| | | components: { GlobalWindow, AccountRechargePanel, Pagination, OperaInterfaceLogWindow }, |
| | | data () { |
| | | return { |
| | | visible: false, |
| | |
| | | latest: null, |
| | | purchaseCount: '0', |
| | | form: { money: 0, remark: '' }, |
| | | isOperating: false |
| | | isOperating: false, |
| | | isRefreshing: false, |
| | | infoLoading: false, |
| | | recordsLoading: false, |
| | | recordsList: [], |
| | | recordsPagination: { pageIndex: 1, pageSize: 10, total: 0 }, |
| | | queryLoadingId: null |
| | | } |
| | | }, |
| | | computed: { |
| | | totalPower () { |
| | | if (!this.latest) return '0.00kWh' |
| | | const v = this.latest.zhygzdl || '0' |
| | | return String(v).toLowerCase().indexOf('kwh') >= 0 ? v : v + 'kWh' |
| | | }, |
| | | balanceSyncTime () { |
| | | return (this.latest && this.latest.addTime) ? this.latest.addTime : (this.info.balanceTime || '-') |
| | | } |
| | | }, |
| | | methods: { |
| | |
| | | this.electricalId = row.id |
| | | this.activeTab = tab || 'basic' |
| | | this.form = { money: 0, remark: '' } |
| | | this.recordsPagination.pageIndex = 1 |
| | | this.recordsList = [] |
| | | this.visible = true |
| | | this.loadInfo() |
| | | if (this.activeTab === 'records') { |
| | | this.loadActionRecords(1) |
| | | } |
| | | }, |
| | | onTabClick (tab) { |
| | | if (tab.name === 'records' && this.recordsList.length === 0) { |
| | | this.loadActionRecords(1) |
| | | } |
| | | }, |
| | | loadInfo () { |
| | | if (!this.electricalId) return |
| | | this.infoLoading = true |
| | | getRemoteInfo(this.electricalId).then(res => { |
| | | this.info = res.electrical || {} |
| | | this.latest = res.latestData |
| | | this.purchaseCount = res.purchaseCount || '0' |
| | | }).catch(e => this.$tip.apiFailed(e)) |
| | | }).catch(e => this.$tip.apiFailed(e)).finally(() => { this.infoLoading = false }) |
| | | }, |
| | | refreshMeterData () { |
| | | if (!this.electricalId) return |
| | | this.isRefreshing = true |
| | | operate({ |
| | | electricalId: this.electricalId, |
| | | action: 'readMeter' |
| | | }) |
| | | .then(res => { |
| | | this.$tip.apiSuccess(res || 'æè¡¨è¯·æ±å·²æäº¤ï¼æ£å¨å·æ°æ°æ®') |
| | | this.loadInfo() |
| | | this.$emit('success') |
| | | if (this.activeTab === 'records') { |
| | | this.loadActionRecords(this.recordsPagination.pageIndex) |
| | | } |
| | | }) |
| | | .catch(e => this.$tip.apiFailed(e)) |
| | | .finally(() => { this.isRefreshing = false }) |
| | | }, |
| | | loadActionRecords (page) { |
| | | if (!this.electricalId) return |
| | | if (page) { |
| | | this.recordsPagination.pageIndex = page |
| | | } |
| | | this.recordsLoading = true |
| | | actionsApi.fetchList({ |
| | | page: this.recordsPagination.pageIndex, |
| | | capacity: this.recordsPagination.pageSize, |
| | | model: { electricalId: this.electricalId } |
| | | }) |
| | | .then(data => { |
| | | this.recordsList = data.records || [] |
| | | this.recordsPagination.total = data.total || 0 |
| | | }) |
| | | .catch(e => this.$tip.apiFailed(e)) |
| | | .finally(() => { this.recordsLoading = false }) |
| | | }, |
| | | handleRecordsSizeChange (size) { |
| | | this.recordsPagination.pageSize = size |
| | | this.loadActionRecords(1) |
| | | }, |
| | | readMeter () { |
| | | this.submitOperate('readMeter', true) |
| | | }, |
| | | doOperate (action, msg) { |
| | | this.$dialog.actionConfirm(msg, 'æä½ç¡®è®¤') |
| | | .then(() => this.submitOperate(action, false)) |
| | | .catch(() => {}) |
| | | }, |
| | | relayMeterTip () { |
| | | const name = this.info.name || '-' |
| | | const address = this.info.address || '-' |
| | | return `表åç§°ï¼${name}ï¼è¡¨å°åï¼${address}` |
| | | }, |
| | | doRelayOperate (action) { |
| | | const cfg = RELAY_ACTIONS[action] |
| | | if (!cfg) return |
| | | const meterTip = this.relayMeterTip() |
| | | this.$dialog.actionConfirm(`${cfg.message}ï¼${meterTip}ï¼`, 'æä½ç¡®è®¤') |
| | | .then(() => this.submitOperate(action, false)) |
| | | .catch(() => {}) |
| | | }, |
| | |
| | | this.$tip.apiSuccess(res || (silent ? 'æè¡¨è¯·æ±å·²æäº¤' : 'æäº¤æåï¼è¯·å¨ãæ¥å¸¸ç¨çµç®¡ç-å
å¼è®°å½ã䏿¥çå
å¼ç»æ')) |
| | | this.loadInfo() |
| | | this.$emit('success') |
| | | if (this.activeTab === 'records') { |
| | | this.loadActionRecords(this.recordsPagination.pageIndex) |
| | | } |
| | | }) |
| | | .catch(e => this.$tip.apiFailed(e)) |
| | | .finally(() => { this.isOperating = false }) |
| | | }, |
| | | formatActionType (val) { |
| | | return ACTION_TYPE_MAP[val] || val || '-' |
| | | }, |
| | | formatStatus (val) { |
| | | if (val === 0 || val === '0') return 'å¤çä¸' |
| | | if (val === 1 || val === '1') return 'æå' |
| | | if (val === 2 || val === '2') return '失败' |
| | | return val == null || val === '' ? '-' : String(val) |
| | | }, |
| | | statusClass (val) { |
| | | if (val === 1 || val === '1') return 'green' |
| | | if (val === 2 || val === '2') return 'red' |
| | | if (val === 0 || val === '0') return 'orange' |
| | | return '' |
| | | }, |
| | | openJson (title, content) { |
| | | if (!content) return |
| | | this.$refs.jsonWindow.open(title, { content }) |
| | | }, |
| | | handleQueryResult (row) { |
| | | this.queryLoadingId = row.id |
| | | actionsApi.queryResult(row.id) |
| | | .then(msg => { |
| | | this.$tip.success(msg || 'æ¥è¯¢å®æ') |
| | | this.loadActionRecords(this.recordsPagination.pageIndex) |
| | | }) |
| | | .catch(e => this.$tip.apiFailed(e)) |
| | | .finally(() => { this.queryLoadingId = null }) |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .info-block { margin-bottom: 16px; line-height: 28px; color: #303133; } |
| | | .info-block { margin-bottom: 12px; line-height: 28px; color: #303133; } |
| | | .meter-data-block { |
| | | margin-bottom: 16px; |
| | | padding: 12px 14px; |
| | | background: #fafbfe; |
| | | border: 1px solid #eef2f8; |
| | | border-radius: 8px; |
| | | line-height: 26px; |
| | | color: #303133; |
| | | } |
| | | .meter-data-block__title { |
| | | font-weight: 600; |
| | | font-size: 14px; |
| | | margin-bottom: 6px; |
| | | color: #222; |
| | | } |
| | | .meter-data-block p { margin: 0; } |
| | | .btn-row .el-button { margin: 0 8px 8px 0; } |
| | | .btn-row--relay { |
| | | margin-top: 4px; |
| | | padding-top: 12px; |
| | | border-top: 1px dashed #ebeef5; |
| | | } |
| | | .btn-row__label { |
| | | display: block; |
| | | width: 100%; |
| | | margin-bottom: 8px; |
| | | font-size: 13px; |
| | | color: #909399; |
| | | } |
| | | .records-table { width: 100%; margin-top: 4px; } |
| | | .green { color: #67c23a; } |
| | | .red { color: #f56c6c; } |
| | | .orange { color: #e6a23c; } |
| | | </style> |
| | |
| | | capacity: this.tableData.pagination.pageSize, |
| | | model: this.buildSearchModel() |
| | | }).then(data => { |
| | | this.tableData.list = data.records |
| | | this.tableData.pagination.total = data.total |
| | | }).catch(() => {}).finally(() => { this.isWorking.search = false }) |
| | | this.tableData.list = (data && data.records) || [] |
| | | this.tableData.pagination.total = (data && data.total) || 0 |
| | | }).catch(e => { |
| | | this.$tip.apiFailed(e) |
| | | }).finally(() => { this.isWorking.search = false }) |
| | | }, |
| | | search () { |
| | | this.tableData.pagination.pageIndex = 1 |
| | | this.loadList() |
| | | }, |
| | | handleSizeChange (size) { |
| | | this.tableData.pagination.pageSize = size |
| | | this.loadList() |
| | | }, |
| | | buildSearchModel () { |
| | | const model = {} |
| | | if (this.searchForm.nameKeyword) model.nameKeyword = this.searchForm.nameKeyword |
| | |
| | | 5: 'åé¸', |
| | | 6: '弿·', |
| | | 7: 'å
å¼', |
| | | 8: 'æè¡¨' |
| | | 8: 'æè¡¨', |
| | | 9: 'ä¿çµ', |
| | | 10: 'è§£é¤ä¿çµ' |
| | | } |
| | | |
| | | export default { |
| | |
| | | <template> |
| | | <div class="main"> |
| | | <div class="main_left"> |
| | | <div class="main_left_head"> |
| | | <div class="head_item"> |
| | | <div class="head_item_left"> |
| | | <span>å¾
åå·¥å</span> |
| | | <span>{{obj.waitDealWorkOrderSize || 0}}</span> |
| | | <span @click="jump(1)">æ¥çæ´å¤</span> |
| | | <div class="dashboard"> |
| | | <section class="dashboard-top"> |
| | | <div class="dashboard-top__left"> |
| | | <div class="stat-cards card"> |
| | | <div class="stat-cards__item head_item--workorder" @click="jump(1)"> |
| | | <div class="stat-cards__content"> |
| | | <span class="stat-cards__label">å¾
åå·¥å</span> |
| | | <span class="stat-cards__value">{{ obj.waitDealWorkOrderSize || 0 }}</span> |
| | | <span class="stat-cards__link">æ¥çæ´å¤</span> |
| | | </div> |
| | | <img class="head_item_icon" src="@/assets/indexIcon/ic_daibangongdan@2x.png" /> |
| | | <img class="stat-cards__icon" src="@/assets/indexIcon/ic_daibangongdan@2x.png" alt="" /> |
| | | </div> |
| | | <div class="head_item"> |
| | | <div class="head_item_left"> |
| | | <span>å¾
å·¡æ£</span> |
| | | <span>{{obj.waitTaskSize || 0}}</span> |
| | | <span @click="jump(2)">æ¥çæ´å¤</span> |
| | | <div class="stat-cards__item head_item--inspect" @click="jump(2)"> |
| | | <div class="stat-cards__content"> |
| | | <span class="stat-cards__label">å¾
å·¡æ£</span> |
| | | <span class="stat-cards__value">{{ obj.waitTaskSize || 0 }}</span> |
| | | <span class="stat-cards__link">æ¥çæ´å¤</span> |
| | | </div> |
| | | <img class="head_item_icon" src="@/assets/indexIcon/ic_daixuncha@2x.png" /> |
| | | <img class="stat-cards__icon" src="@/assets/indexIcon/ic_daixuncha@2x.png" alt="" /> |
| | | </div> |
| | | <div class="head_item"> |
| | | <div class="head_item_left"> |
| | | <span>å¾
çç¹</span> |
| | | <span>{{obj.stocktakingSize || 0}}</span> |
| | | <span @click="jump(3)">æ¥çæ´å¤</span> |
| | | <div class="stat-cards__item head_item--stock" @click="jump(3)"> |
| | | <div class="stat-cards__content"> |
| | | <span class="stat-cards__label">å¾
çç¹</span> |
| | | <span class="stat-cards__value">{{ obj.stocktakingSize || 0 }}</span> |
| | | <span class="stat-cards__link">æ¥çæ´å¤</span> |
| | | </div> |
| | | <img class="head_item_icon" src="@/assets/indexIcon/ic_daipandian@2x.png" /> |
| | | <img class="stat-cards__icon" src="@/assets/indexIcon/ic_daipandian@2x.png" alt="" /> |
| | | </div> |
| | | </div> |
| | | <div class="main_left_menu"> |
| | | <div class="main_left_menu_title"> |
| | | <span>常ç¨åè½</span> |
| | | <div class="main_left_menu_title_edit" @click="$refs.commonFunctions.open('常ç¨åè½ç®¡ç')"> |
| | | <img src="@/assets/indexIcon/ic_daibangongdan@2x.png" /> |
| | | |
| | | <div class="quick-menu card"> |
| | | <div class="section-header"> |
| | | <h3 class="section-header__title">常ç¨åè½</h3> |
| | | <div class="section-header__action" @click="$refs.commonFunctions.open('常ç¨åè½ç®¡ç')"> |
| | | <i class="el-icon-setting"></i> |
| | | <span>èªå®ä¹åè½</span> |
| | | </div> |
| | | </div> |
| | | <div class="main_left_menu_list"> |
| | | <div class="list_item" v-for="(item, index) in list" :key="index" @click="jump1(item.path)"> |
| | | <div class="list_item_left"> |
| | | <img :src="item.icoPath" /> |
| | | <div class="quick-menu__grid"> |
| | | <div |
| | | class="quick-menu__item" |
| | | v-for="(item, index) in list" |
| | | :key="index" |
| | | @click="jump1(item.path)" |
| | | > |
| | | <div class="quick-menu__item-left"> |
| | | <img :src="item.icoPath" alt="" /> |
| | | <span>{{item.name}}</span> |
| | | </div> |
| | | <i class="el-icon-arrow-right"></i> |
| | | </div> |
| | | <div class="list_item1"></div> |
| | | <div class="list_item1"></div> |
| | | <div class="list_item1"></div> |
| | | <i class="el-icon-arrow-right quick-menu__arrow"></i> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div class="main_right"> |
| | | <div class="main_right_title">æ¥ç¨</div> |
| | | <div class="main_right_search"> |
| | | <el-select v-model="nian" style="width: 150px; margin-right: 15px;" @change="getMonthNoticess" placeholder="è¯·éæ©"> |
| | | </div> |
| | | |
| | | <aside class="schedule-panel card"> |
| | | <div class="section-header"> |
| | | <h3 class="section-header__title">æ¥ç¨</h3> |
| | | </div> |
| | | <div class="schedule-panel__filters"> |
| | | <el-select v-model="nian" class="schedule-panel__select" @change="getMonthNoticess" placeholder="è¯·éæ©"> |
| | | <el-option |
| | | v-for="item in yearList" |
| | | :key="item.val" |
| | | :label="item.name" |
| | | :value="item.val"> |
| | | </el-option> |
| | | :value="item.val" |
| | | /> |
| | | </el-select> |
| | | <el-select v-model="yue" style="width: 150px;" @change="getMonthNoticess" placeholder="è¯·éæ©"> |
| | | <el-select v-model="yue" class="schedule-panel__select" @change="getMonthNoticess" placeholder="è¯·éæ©"> |
| | | <el-option |
| | | v-for="(item, index) in 12" |
| | | :key="index" |
| | | :label="item + 'æ'" |
| | | :value="item > 9 ? item : `0${item}`"> |
| | | </el-option> |
| | | :value="item > 9 ? item : `0${item}`" |
| | | /> |
| | | </el-select> |
| | | </div> |
| | | <div class="main_right_date"> |
| | | <div class="schedule-panel__calendar"> |
| | | <Calendar |
| | | ref="Calendar" |
| | | v-on:choseDay="clickDay" |
| | | :markDateMore="markDateMore" |
| | | ></Calendar> |
| | | /> |
| | | </div> |
| | | <div class="main_right_rc"> |
| | | <div class="main_right_rc_title">彿¥æ¥ç¨ï¼{{dataList.length}}ï¼</div> |
| | | <div class="main_right_rc_list" v-loading="loading"> |
| | | <div class="main_right_rc_list_row" v-for="(item, index) in dataList" :key="index"> |
| | | <div class="top"> |
| | | <div class="top_left"> |
| | | <div class="top_left_dian"></div> |
| | | <div class="top_left_title">{{item.title}}</div> |
| | | <div class="schedule-panel__list-wrap"> |
| | | <div class="schedule-panel__list-title">彿¥æ¥ç¨ï¼{{ dataList.length }}ï¼</div> |
| | | <div class="schedule-panel__list" v-loading="loading"> |
| | | <template v-if="dataList.length"> |
| | | <div class="schedule-item" v-for="(item, index) in dataList" :key="index"> |
| | | <div class="schedule-item__top"> |
| | | <div class="schedule-item__title-wrap"> |
| | | <div class="schedule-item__dot"></div> |
| | | <div class="schedule-item__title">{{ item.title }}</div> |
| | | </div> |
| | | <div class="top_date">{{item.param1}}</div> |
| | | <div class="schedule-item__time">{{ item.param1 }}</div> |
| | | </div> |
| | | <div class="bottom"> |
| | | {{item.content}} |
| | | <div class="schedule-item__content">{{ item.content }}</div> |
| | | </div> |
| | | </template> |
| | | <div v-else class="schedule-empty">彿¥ææ æ¥ç¨</div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </aside> |
| | | </section> |
| | | |
| | | <section class="dashboard-warning"> |
| | | <ElectricalWarningWorkbench /> |
| | | </section> |
| | | |
| | | <section class="dashboard-energy"> |
| | | <DailyEnergyTrendPanel |
| | | title="è¿30天æºè½çµè¡¨æ¯æ¥æ»çµé/æ»çµè´¹" |
| | | :load-data="electricalDailyEnergyStats" |
| | | /> |
| | | <DailyEnergyTrendPanel |
| | | title="è¿30天空è°å¤èæºæ¯æ¥æ»çµé/æ»çµè´¹" |
| | | :load-data="conditionerDailyEnergyStats" |
| | | /> |
| | | </section> |
| | | |
| | | <CommonFunctions ref="commonFunctions" @success="getYwQuickLists" /> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import CommonFunctions from '@/components/business/commonFunctions' |
| | | import { getYwQuickList, getMonthNotices, workDeskData } from '@/api/ywWorkDesk' |
| | | import ElectricalWarningWorkbench from '@/components/business/ElectricalWarningWorkbench' |
| | | import DailyEnergyTrendPanel from '@/components/business/DailyEnergyTrendPanel' |
| | | import { getYwQuickList, getMonthNotices, workDeskData, electricalDailyEnergyStats, conditionerDailyEnergyStats } from '@/api/ywWorkDesk' |
| | | import { navigateByMenu } from '@/utils/menu' |
| | | import { mapState } from 'vuex' |
| | | import Calendar from 'vue-calendar-component' |
| | | |
| | | export default { |
| | | data() { |
| | | return { |
| | |
| | | loading: false |
| | | } |
| | | }, |
| | | components: { CommonFunctions, Calendar }, |
| | | components: { CommonFunctions, Calendar, ElectricalWarningWorkbench, DailyEnergyTrendPanel }, |
| | | computed: { |
| | | ...mapState(['menuData']) |
| | | }, |
| | | created () { |
| | | this.getWorkDeskData() |
| | | this.getYwQuickLists() |
| | | this.getYear() |
| | | }, |
| | | methods: { |
| | | electricalDailyEnergyStats, |
| | | conditionerDailyEnergyStats, |
| | | getYear() { |
| | | let currentYear = new Date().getFullYear(); |
| | | let currentMonth = new Date().getMonth() + 1; |
| | | const currentYear = new Date().getFullYear() |
| | | const currentMonth = new Date().getMonth() + 1 |
| | | this.nian = currentYear |
| | | this.yue = currentMonth > 9 ? currentMonth : `0${currentMonth}` |
| | | for (let i = currentYear - 10; i <= currentYear; i++) { |
| | |
| | | } |
| | | this.getMonthNoticess() |
| | | }, |
| | | // è·å代å |
| | | getWorkDeskData() { |
| | | workDeskData({}) |
| | | .then(res => { |
| | | workDeskData({}).then(res => { |
| | | this.obj = res |
| | | }) |
| | | }, |
| | | clickDay(e) { |
| | | this.loading = true |
| | | let date = e.replace("/\\//g", "-") |
| | | let arr = this.markDateMore.filter(item => { |
| | | if (item.date === date) { |
| | | return item |
| | | } |
| | | }) |
| | | if (arr.length > 0) { |
| | | this.dataList = arr[0].noticeList |
| | | } else { |
| | | this.dataList = [] |
| | | } |
| | | const date = e.replace('/\\//g', '-') |
| | | const arr = this.markDateMore.filter(item => item.date === date) |
| | | this.dataList = arr.length > 0 ? arr[0].noticeList : [] |
| | | this.loading = false |
| | | }, |
| | | // è·åæ¥ç¨ |
| | | getMonthNoticess() { |
| | | getMonthNotices(this.nian + '-' + this.yue).then(res => { |
| | | let arr = res.filter(item => { |
| | | if (item.noticeList && item.noticeList.length > 0) { |
| | | return item |
| | | } |
| | | }) |
| | | this.markDateMore = arr.map(item => { |
| | | return { date: item.monthDate.replace("/-0/g", "-"), className: 'markRed', noticeList: item.noticeList } |
| | | }) |
| | | let toDay = this.getDay() |
| | | const arr = res.filter(item => item.noticeList && item.noticeList.length > 0) |
| | | this.markDateMore = arr.map(item => ({ |
| | | date: item.monthDate.replace('/-0/g', '-'), |
| | | className: 'markRed', |
| | | noticeList: item.noticeList |
| | | })) |
| | | const toDay = this.getDay() |
| | | this.markDateMore.forEach(item => { |
| | | if (item.date === toDay) { |
| | | this.dataList = item.noticeList |
| | |
| | | }) |
| | | }, |
| | | getYwQuickLists() { |
| | | getYwQuickList({}) |
| | | .then(res => { |
| | | getYwQuickList({}).then(res => { |
| | | this.list = res |
| | | }) |
| | | }, |
| | | getDay() { |
| | | let date = new Date(); |
| | | let year = date.getFullYear(); // è·å年份 |
| | | let month = String(date.getMonth() + 1).padStart(2, '0'); // è·åæä»½ï¼å¹¶è¡¥é¶ |
| | | let day = String(date.getDate()).padStart(2, '0'); // è·åæ¥æï¼å¹¶è¡¥é¶ |
| | | |
| | | return `${year}-${month}-${day}`; |
| | | const date = new Date() |
| | | const year = date.getFullYear() |
| | | const month = String(date.getMonth() + 1).padStart(2, '0') |
| | | const day = String(date.getDate()).padStart(2, '0') |
| | | return `${year}-${month}-${day}` |
| | | }, |
| | | jump(type) { |
| | | if (type === 1) { |
| | | this.$router.push({ path: '/workorder/workorderList' }) |
| | | } else if (type === 2) { |
| | | this.$router.push({ path: '/Inspection/task' }) |
| | | } else if (type === 3) { |
| | | this.$router.push({ path: '/stock/check' }) |
| | | const pathMap = { |
| | | 1: '/workorder/workorderList', |
| | | 2: '/Inspection/task', |
| | | 3: '/stock/check' |
| | | } |
| | | this.navigateToMenu(pathMap[type]) |
| | | }, |
| | | jump1(path) { |
| | | this.$router.push({ path }) |
| | | this.navigateToMenu(path) |
| | | }, |
| | | navigateToMenu (path) { |
| | | navigateByMenu(this.$router, this.$store, path, this.menuData.list) |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .main { |
| | | .dashboard { |
| | | --dash-primary: #3E80EF; |
| | | --dash-primary-light: rgba(62, 128, 239, 0.08); |
| | | --dash-text: #222222; |
| | | --dash-text-secondary: #666666; |
| | | --dash-text-muted: #999999; |
| | | --dash-bg: #F4F7FC; |
| | | --dash-card-bg: #FFFFFF; |
| | | --dash-border: #EEF2F8; |
| | | --dash-radius: 10px; |
| | | --dash-shadow: 0 1px 4px rgba(0, 0, 0, 0.06); |
| | | --dash-gap: 16px; |
| | | |
| | | width: 100%; |
| | | padding: 15px; |
| | | min-height: 100%; |
| | | padding: var(--dash-gap); |
| | | box-sizing: border-box; |
| | | background: #F4F7FC; |
| | | display: flex; |
| | | align-items: self-start; |
| | | justify-content: space-between; |
| | | .main_left { |
| | | flex: 1; |
| | | height: 100%; |
| | | background: var(--dash-bg); |
| | | display: flex; |
| | | flex-direction: column; |
| | | .main_left_head { |
| | | width: 100%; |
| | | height: 199px; |
| | | background: #FFFFFF; |
| | | border-radius: 8px; |
| | | display: flex; |
| | | align-items: center; |
| | | padding: 20px; |
| | | box-sizing: border-box; |
| | | .head_item { |
| | | flex: 1; |
| | | height: 100%; |
| | | gap: var(--dash-gap); |
| | | } |
| | | |
| | | .card { |
| | | background: var(--dash-card-bg); |
| | | border-radius: var(--dash-radius); |
| | | border: 1px solid var(--dash-border); |
| | | box-shadow: var(--dash-shadow); |
| | | } |
| | | |
| | | .section-header { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | background: #F1F5FF; |
| | | border-radius: 8px; |
| | | margin-right: 15px; |
| | | padding: 28px 20px; |
| | | box-sizing: border-box; |
| | | &:last-child { |
| | | margin: 0 !important; |
| | | } |
| | | .head_item_left { |
| | | flex: 1; |
| | | display: flex; |
| | | flex-direction: column; |
| | | span { |
| | | &:nth-child(1) { |
| | | font-weight: 600; |
| | | font-size: 17px; |
| | | color: #222222; |
| | | } |
| | | &:nth-child(2) { |
| | | font-weight: 600; |
| | | font-size: 30px; |
| | | color: #111111; |
| | | margin-top: 6px; |
| | | margin-bottom: 14px; |
| | | } |
| | | &:nth-child(3) { |
| | | font-weight: 400; |
| | | font-size: 13px; |
| | | color: #999999; |
| | | cursor: pointer; |
| | | } |
| | | } |
| | | } |
| | | .head_item_icon { |
| | | width: 60px; |
| | | height: 60px; |
| | | } |
| | | } |
| | | } |
| | | .main_left_menu { |
| | | width: 100%; |
| | | height: calc(100% - 214px); |
| | | background: #FFFFFF; |
| | | border-radius: 8px; |
| | | margin-top: 15px; |
| | | padding: 20px; |
| | | box-sizing: border-box; |
| | | .main_left_menu_title { |
| | | width: 100%; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | span { |
| | | margin-bottom: 16px; |
| | | |
| | | &__title { |
| | | margin: 0; |
| | | padding-left: 10px; |
| | | font-weight: 600; |
| | | font-size: 18px; |
| | | color: #222222; |
| | | color: var(--dash-text); |
| | | line-height: 1.4; |
| | | border-left: 3px solid var(--dash-primary); |
| | | } |
| | | .main_left_menu_title_edit { |
| | | |
| | | &__action { |
| | | cursor: pointer; |
| | | display: flex; |
| | | align-items: center; |
| | | img { |
| | | width: 15px; |
| | | height: 15px; |
| | | } |
| | | span { |
| | | font-weight: 400; |
| | | gap: 4px; |
| | | font-size: 14px; |
| | | color: #3E80EF; |
| | | margin-left: 5px; |
| | | color: var(--dash-primary); |
| | | transition: opacity 0.2s; |
| | | |
| | | &:hover { |
| | | opacity: 0.8; |
| | | } |
| | | |
| | | i { |
| | | font-size: 15px; |
| | | } |
| | | } |
| | | } |
| | | .main_left_menu_list { |
| | | width: 100%; |
| | | margin-top: 20px; |
| | | |
| | | .dashboard-top { |
| | | display: flex; |
| | | align-items: flex-start; |
| | | gap: var(--dash-gap); |
| | | |
| | | &__left { |
| | | flex: 1; |
| | | min-width: 0; |
| | | display: flex; |
| | | flex-direction: column; |
| | | gap: var(--dash-gap); |
| | | } |
| | | } |
| | | |
| | | .stat-cards { |
| | | display: flex; |
| | | align-items: stretch; |
| | | gap: 12px; |
| | | padding: 20px; |
| | | |
| | | &__item { |
| | | flex: 1; |
| | | display: flex; |
| | | align-items: center; |
| | | flex-wrap: wrap; |
| | | justify-content: space-between; |
| | | .list_item1 { |
| | | width: 24%; |
| | | height: 0; |
| | | } |
| | | .list_item { |
| | | padding: 24px 20px; |
| | | border-radius: 8px; |
| | | cursor: pointer; |
| | | width: 24%; |
| | | height: 70px; |
| | | background: #FFFFFF; |
| | | transition: transform 0.2s, box-shadow 0.2s; |
| | | |
| | | &:hover { |
| | | transform: translateY(-2px); |
| | | box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08); |
| | | |
| | | .stat-cards__icon { |
| | | transform: scale(1.05); |
| | | } |
| | | } |
| | | |
| | | &.head_item--workorder { |
| | | background: linear-gradient(135deg, #EEF4FF 0%, #F5F8FF 100%); |
| | | |
| | | .stat-cards__value { |
| | | color: #3E80EF; |
| | | } |
| | | |
| | | .stat-cards__link:hover { |
| | | color: #3E80EF; |
| | | } |
| | | } |
| | | |
| | | &.head_item--inspect { |
| | | background: linear-gradient(135deg, #E8FAF0 0%, #F2FBF6 100%); |
| | | |
| | | .stat-cards__value { |
| | | color: #36B37E; |
| | | } |
| | | |
| | | .stat-cards__link:hover { |
| | | color: #36B37E; |
| | | } |
| | | } |
| | | |
| | | &.head_item--stock { |
| | | background: linear-gradient(135deg, #FFF6E8 0%, #FFFAF2 100%); |
| | | |
| | | .stat-cards__value { |
| | | color: #FF9E00; |
| | | } |
| | | |
| | | .stat-cards__link:hover { |
| | | color: #FF9E00; |
| | | } |
| | | } |
| | | } |
| | | |
| | | &__content { |
| | | display: flex; |
| | | flex-direction: column; |
| | | } |
| | | |
| | | &__label { |
| | | font-weight: 600; |
| | | font-size: 16px; |
| | | color: var(--dash-text); |
| | | } |
| | | |
| | | &__value { |
| | | font-weight: 700; |
| | | font-size: 32px; |
| | | line-height: 1.2; |
| | | margin: 6px 0 12px; |
| | | } |
| | | |
| | | &__link { |
| | | font-size: 13px; |
| | | color: var(--dash-text-muted); |
| | | transition: color 0.2s; |
| | | } |
| | | |
| | | &__icon { |
| | | width: 56px; |
| | | height: 56px; |
| | | flex-shrink: 0; |
| | | transition: transform 0.2s; |
| | | } |
| | | } |
| | | |
| | | .quick-menu { |
| | | padding: 20px; |
| | | |
| | | &__grid { |
| | | display: grid; |
| | | grid-template-columns: repeat(4, 1fr); |
| | | gap: 12px; |
| | | } |
| | | |
| | | &__item { |
| | | cursor: pointer; |
| | | height: 72px; |
| | | background: var(--dash-card-bg); |
| | | border-radius: 8px; |
| | | border: 1px solid #EEEEEE; |
| | | padding: 0 16px; |
| | | box-sizing: border-box; |
| | | margin-bottom: 15px; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | .list_item_left { |
| | | transition: border-color 0.2s, box-shadow 0.2s, transform 0.2s; |
| | | |
| | | &:hover { |
| | | border-color: var(--dash-primary); |
| | | box-shadow: 0 2px 8px rgba(62, 128, 239, 0.12); |
| | | transform: translateY(-1px); |
| | | |
| | | .quick-menu__arrow { |
| | | color: var(--dash-primary); |
| | | } |
| | | } |
| | | } |
| | | |
| | | &__item-left { |
| | | display: flex; |
| | | align-items: center; |
| | | min-width: 0; |
| | | |
| | | img { |
| | | width: 40px; |
| | | height: 40px; |
| | | margin-right: 5px; |
| | | margin-right: 8px; |
| | | flex-shrink: 0; |
| | | } |
| | | |
| | | span { |
| | | font-weight: 500; |
| | | font-size: 15px; |
| | | color: #222222; |
| | | font-size: 14px; |
| | | color: var(--dash-text); |
| | | overflow: hidden; |
| | | text-overflow: ellipsis; |
| | | white-space: nowrap; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | .main_right { |
| | | |
| | | &__arrow { |
| | | color: #C0C4CC; |
| | | font-size: 14px; |
| | | flex-shrink: 0; |
| | | width: 500px; |
| | | height: 100%; |
| | | margin-left: 15px; |
| | | background: #FEFEFF; |
| | | border-radius: 8px; |
| | | transition: color 0.2s; |
| | | } |
| | | } |
| | | |
| | | .schedule-panel { |
| | | flex-shrink: 0; |
| | | width: 480px; |
| | | padding: 20px; |
| | | box-sizing: border-box; |
| | | .main_right_title { |
| | | font-weight: 600; |
| | | font-size: 18px; |
| | | color: #222222; |
| | | |
| | | &__filters { |
| | | display: flex; |
| | | gap: 12px; |
| | | margin-bottom: 12px; |
| | | } |
| | | .main_right_rc { |
| | | width: 100%; |
| | | display: flex; |
| | | flex-direction: column; |
| | | .main_right_rc_title { |
| | | font-weight: 500; |
| | | font-size: 16px; |
| | | color: #222222; |
| | | margin-bottom: 15px; |
| | | |
| | | &__select { |
| | | width: 140px; |
| | | } |
| | | .main_right_rc_list { |
| | | width: 100%; |
| | | height: 300px; |
| | | overflow-y: scroll; |
| | | .main_right_rc_list_row { |
| | | width: 100%; |
| | | padding: 15px; |
| | | box-sizing: border-box; |
| | | background: #F4F7FC; |
| | | border-radius: 2px; |
| | | |
| | | &__calendar { |
| | | padding: 12px; |
| | | background: #FAFBFE; |
| | | border-radius: 8px; |
| | | border: 1px solid var(--dash-border); |
| | | } |
| | | |
| | | &__list-wrap { |
| | | margin-top: 16px; |
| | | } |
| | | |
| | | &__list-title { |
| | | font-weight: 500; |
| | | font-size: 15px; |
| | | color: var(--dash-text); |
| | | margin-bottom: 12px; |
| | | } |
| | | |
| | | &__list { |
| | | height: 280px; |
| | | overflow-y: auto; |
| | | padding-right: 4px; |
| | | |
| | | &::-webkit-scrollbar { |
| | | width: 5px; |
| | | } |
| | | |
| | | &::-webkit-scrollbar-thumb { |
| | | background: #D8DCE6; |
| | | border-radius: 3px; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .schedule-item { |
| | | padding: 14px 14px 14px 12px; |
| | | background: #FAFBFE; |
| | | border-radius: 8px; |
| | | border: 1px solid var(--dash-border); |
| | | border-left: 3px solid #FF9E00; |
| | | margin-bottom: 10px; |
| | | .top { |
| | | width: 100%; |
| | | |
| | | &__top { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | .top_left { |
| | | gap: 8px; |
| | | } |
| | | |
| | | &__title-wrap { |
| | | display: flex; |
| | | align-items: center; |
| | | .top_left_dian { |
| | | width: 10px; |
| | | height: 10px; |
| | | min-width: 0; |
| | | } |
| | | |
| | | &__dot { |
| | | width: 8px; |
| | | height: 8px; |
| | | border-radius: 50%; |
| | | background: #FF9E00; |
| | | margin-right: 10px; |
| | | margin-right: 8px; |
| | | flex-shrink: 0; |
| | | } |
| | | .top_left_title { |
| | | |
| | | &__title { |
| | | font-weight: 500; |
| | | font-size: 15px; |
| | | color: #222222; |
| | | font-size: 14px; |
| | | color: var(--dash-text); |
| | | overflow: hidden; |
| | | text-overflow: ellipsis; |
| | | white-space: nowrap; |
| | | } |
| | | } |
| | | .top_date { |
| | | font-weight: 400; |
| | | |
| | | &__time { |
| | | font-size: 12px; |
| | | color: #999999; |
| | | color: var(--dash-text-muted); |
| | | flex-shrink: 0; |
| | | } |
| | | } |
| | | .bottom { |
| | | font-weight: 400; |
| | | |
| | | &__content { |
| | | font-size: 13px; |
| | | color: #666666; |
| | | color: var(--dash-text-secondary); |
| | | margin-top: 8px; |
| | | line-height: 1.5; |
| | | } |
| | | } |
| | | |
| | | .schedule-empty { |
| | | height: 120px; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | color: var(--dash-text-muted); |
| | | font-size: 14px; |
| | | } |
| | | |
| | | .dashboard-warning, |
| | | .dashboard-energy { |
| | | display: flex; |
| | | flex-direction: column; |
| | | gap: var(--dash-gap); |
| | | } |
| | | .main_right_date { |
| | | width: 100%; |
| | | padding-top: 15px; |
| | | box-sizing: border-box; |
| | | |
| | | ::v-deep .electrical-warning-panel, |
| | | ::v-deep .daily-energy-panel { |
| | | margin-top: 0 !important; |
| | | border: 1px solid var(--dash-border); |
| | | box-shadow: var(--dash-shadow); |
| | | border-radius: var(--dash-radius); |
| | | } |
| | | |
| | | .schedule-panel__calendar { |
| | | ::v-deep .wh_content_item { |
| | | height: 50px; |
| | | color: #222222; |
| | | font-weight: 400; |
| | | font-size: 15px; |
| | | color: var(--dash-text); |
| | | font-size: 14px; |
| | | } |
| | | |
| | | ::v-deep .wh_item_date { |
| | | width: 30px; |
| | | height: 30px; |
| | | font-size: 15px; |
| | | font-size: 14px; |
| | | } |
| | | |
| | | ::v-deep .wh_content_all { |
| | | background-color: #ffffff; |
| | | background-color: transparent; |
| | | } |
| | | |
| | | ::v-deep .wh_top_changge { |
| | | display: none; |
| | | } |
| | | |
| | | ::v-deep .wh_container { |
| | | max-width: 100%; |
| | | } |
| | | |
| | | ::v-deep .wh_content_item .wh_isToday { |
| | | background-color: rgba(62, 128, 239, 0.47); |
| | | color: #ffffff; |
| | | } |
| | | |
| | | ::v-deep .wh_item_date:hover { |
| | | background-color: #3E80EF; |
| | | background-color: var(--dash-primary); |
| | | border-radius: 50%; |
| | | color: #ffffff; |
| | | } |
| | | |
| | | ::v-deep .wh_content_item .wh_chose_day { |
| | | background: #3E80EF; |
| | | background: var(--dash-primary); |
| | | color: #fff; |
| | | } |
| | | |
| | | ::v-deep .markRed { |
| | | position: relative; |
| | | } |
| | | |
| | | ::v-deep .markRed::after { |
| | | content: 'â'; |
| | | color: #FF9E00; |
| | |
| | | transform: translate(-50%, 0); |
| | | } |
| | | } |
| | | |
| | | @media (max-width: 1400px) { |
| | | .dashboard-top { |
| | | flex-direction: column; |
| | | } |
| | | |
| | | .schedule-panel { |
| | | width: 100%; |
| | | } |
| | | } |
| | | |
| | | @media (max-width: 1200px) { |
| | | .quick-menu__grid { |
| | | grid-template-columns: repeat(3, 1fr); |
| | | } |
| | | |
| | | .stat-cards { |
| | | flex-direction: column; |
| | | } |
| | | } |
| | | |
| | | @media (max-width: 768px) { |
| | | .quick-menu__grid { |
| | | grid-template-columns: repeat(2, 1fr); |
| | | } |
| | | } |
| | | </style> |
| | |
| | | <div class="mt20"> |
| | | <el-button type="primary" @click="handleEdit()" icon="el-icon-plus" |
| | | v-permissions="['business:ywpatrolline:create']">æ°å»º</el-button> |
| | | <el-button type="primary" v-permissions="['business:ywdevice:importExcel']" |
| | | @click="$refs.deviceImport.open('è®¾å¤æ¹é导å
¥')">æ¹é导å
¥</el-button> |
| | | </div> |
| | | <el-table v-loading="loading" :data="list" stripe> |
| | | <el-table-column prop="code" label="设å¤ç¼å·" min-width="100" show-overflow-tooltip /> |
| | |
| | | </div> |
| | | <Edit v-if="showEdit" ref="EditRef" @success="getList" @close="showEdit = false" /> |
| | | <Detail ref="DetailRef" /> |
| | | <OperaDeviceImportWindow ref="deviceImport" @success="getList(1)" /> |
| | | </div> |
| | | </template> |
| | | |
| | |
| | | import QueryForm from '@/components/common/QueryForm' |
| | | import Edit from './components/deviceEdit' |
| | | import Detail from './components/deviceDetail' |
| | | import OperaDeviceImportWindow from '@/components/business/OperaDeviceImportWindow' |
| | | import { fetchList, deleteById } from '@/api/Inspection/device' |
| | | export default { |
| | | components: { |
| | | Pagination, |
| | | QueryForm, |
| | | Edit, |
| | | Detail |
| | | Detail, |
| | | OperaDeviceImportWindow |
| | | }, |
| | | data() { |
| | | return { |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | -- 设å¤ç®¡çæ¹é导å
¥ï¼ä¸ºè¶
级管çåè§è²è¡¥å
¨ importExcel æéï¼å¯é夿§è¡ï¼ |
| | | -- æ§è¡åè¯·éæ°ç»å½ä»¥å·æ° Redis ä¸çæéç¼å |
| | | |
| | | INSERT INTO `SYSTEM_ROLE_PERMISSION` (`ROLE_ID`, `PERMISSION_ID`, `CREATE_TIME`, `UPDATE_TIME`, `CREATE_USER`, `UPDATE_USER`, `DELETED`) |
| | | SELECT r.`ID`, p.`ID`, CURRENT_TIMESTAMP, NULL, 1, NULL, 0 |
| | | FROM `SYSTEM_ROLE` r |
| | | INNER JOIN `SYSTEM_PERMISSION` p ON p.`CODE` = 'business:ywdevice:importExcel' AND p.`DELETED` = 0 |
| | | WHERE r.`DELETED` = 0 AND (r.`CODE` = 'admin' OR r.`NAME` IN ('è¶
级管çå', '管çå')) |
| | | AND NOT EXISTS ( |
| | | SELECT 1 FROM `SYSTEM_ROLE_PERMISSION` rp |
| | | WHERE rp.`ROLE_ID` = r.`ID` AND rp.`PERMISSION_ID` = p.`ID` AND rp.`DELETED` = 0 |
| | | ); |
| | |
| | | INSERT INTO `SYSTEM_PERMISSION`(`CODE`, `NAME`, `REMARK`, `FIXED`, `CREATE_USER`, `CREATE_TIME`, `UPDATE_USER`, `UPDATE_TIME`, `DELETED`) VALUES ('business:ywdevice:update', 'ä¿®æ¹è¿ç»´è®¾å¤ä¿¡æ¯è¡¨', '', 0, 1, CURRENT_TIMESTAMP, NULL, NULL, 0); |
| | | INSERT INTO `SYSTEM_PERMISSION`(`CODE`, `NAME`, `REMARK`, `FIXED`, `CREATE_USER`, `CREATE_TIME`, `UPDATE_USER`, `UPDATE_TIME`, `DELETED`) VALUES ('business:ywdevice:query', 'æ¥è¯¢è¿ç»´è®¾å¤ä¿¡æ¯è¡¨', '', 0, 1, CURRENT_TIMESTAMP, NULL, NULL, 0); |
| | | INSERT INTO `SYSTEM_PERMISSION`(`CODE`, `NAME`, `REMARK`, `FIXED`, `CREATE_USER`, `CREATE_TIME`, `UPDATE_USER`, `UPDATE_TIME`, `DELETED`) VALUES ('business:ywdevice:exportExcel', '导åºè¿ç»´è®¾å¤ä¿¡æ¯è¡¨(Excel)', '', 0, 1, CURRENT_TIMESTAMP, NULL, NULL, 0); |
| | | INSERT INTO `SYSTEM_PERMISSION`(`CODE`, `NAME`, `REMARK`, `FIXED`, `CREATE_USER`, `CREATE_TIME`, `UPDATE_USER`, `UPDATE_TIME`, `DELETED`) VALUES ('business:ywdevice:importExcel', '导å
¥è¿ç»´è®¾å¤ä¿¡æ¯è¡¨(Excel)', '', 0, 1, CURRENT_TIMESTAMP, NULL, NULL, 0); |
| | | |
| | |
| | | public ApiResponse<PageData<YwCustomerRechargeMerchantVO>> merchantPage( |
| | | @RequestBody PageWrap<YwCustomerRechargeQueryDTO> pageWrap, |
| | | @RequestHeader(Constants.HEADER_USER_TOKEN) String token) { |
| | | if (pageWrap == null) { |
| | | pageWrap = new PageWrap<>(); |
| | | } |
| | | return ApiResponse.success(ywCustomerRechargeBizService.findMerchantPage(pageWrap)); |
| | | } |
| | | |
| | |
| | | import com.doumee.dao.business.vo.YwDeviceStatusDataVO; |
| | | import com.doumee.service.business.YwDeviceService; |
| | | import io.swagger.annotations.Api; |
| | | import io.swagger.annotations.ApiImplicitParam; |
| | | import io.swagger.annotations.ApiImplicitParams; |
| | | import io.swagger.annotations.ApiOperation; |
| | | import io.swagger.annotations.ApiParam; |
| | | import com.doumee.config.annotation.CloudRequiredPermission; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.web.bind.annotation.*; |
| | | import org.springframework.web.multipart.MultipartFile; |
| | | |
| | | import javax.servlet.http.HttpServletResponse; |
| | | import java.io.File; |
| | | import java.util.ArrayList; |
| | | import java.util.List; |
| | | import java.util.Set; |
| | |
| | | ExcelExporter.build(YwDevice.class).export(ywDeviceService.findPage(pageWrap).getRecords(), "è¿ç»´è®¾å¤ä¿¡æ¯è¡¨", response); |
| | | } |
| | | |
| | | @ApiOperation("è®¾å¤æ¹é导å
¥") |
| | | @PostMapping("/importExcel") |
| | | @ApiImplicitParams({ |
| | | @ApiImplicitParam(name = "file", value = "file", required = true, paramType = "query", dataType = "file", dataTypeClass = File.class), |
| | | }) |
| | | @CloudRequiredPermission("business:ywdevice:importExcel") |
| | | public ApiResponse<String> importExcel(@ApiParam(value = "file") MultipartFile file, @RequestHeader(Constants.HEADER_USER_TOKEN) String token) { |
| | | return ApiResponse.success(ywDeviceService.importBatch(file, this.getLoginUser(token))); |
| | | } |
| | | |
| | | @ApiOperation("æ ¹æ®IDæ¥è¯¢") |
| | | @GetMapping("/{id}") |
| | | @CloudRequiredPermission("business:ywdevice:query") |
| | |
| | | import com.doumee.core.utils.Constants; |
| | | import com.doumee.dao.business.model.YwPatrolTaskRecord; |
| | | import com.doumee.dao.business.model.YwQuickModel; |
| | | import com.doumee.dao.business.model.YwElectricalWarning; |
| | | import com.doumee.dao.business.vo.DailyEnergyStatVO; |
| | | import com.doumee.dao.business.vo.MonthDataResponse; |
| | | import com.doumee.dao.business.vo.WarningTypeStatVO; |
| | | import com.doumee.dao.business.vo.WorkDeskDataResponse; |
| | | import com.doumee.dao.system.model.Notices; |
| | | import com.doumee.service.business.WorkbenchesService; |
| | | import com.doumee.service.business.YwElectricalWarningService; |
| | | import com.doumee.service.business.YwWorkDeskEnergyService; |
| | | import com.doumee.service.business.YwPatrolTaskRecordService; |
| | | import io.swagger.annotations.Api; |
| | | import io.swagger.annotations.ApiOperation; |
| | |
| | | |
| | | @Autowired |
| | | private WorkbenchesService workbenchesService; |
| | | |
| | | @Autowired |
| | | private YwElectricalWarningService ywElectricalWarningService; |
| | | |
| | | @Autowired |
| | | private YwWorkDeskEnergyService ywWorkDeskEnergyService; |
| | | |
| | | @ApiOperation("è·åå¿«æ·è忍¡åä¿¡æ¯") |
| | | @GetMapping("/getYwQuickList") |
| | |
| | | return ApiResponse.success(workbenchesService.getMyNotices(pageWrap,getLoginUser(token))); |
| | | } |
| | | |
| | | @ApiOperation("å·¥ä½å°-çµè¡¨æ¥è¦ç±»åç»è®¡") |
| | | @GetMapping("/electricalWarningStats") |
| | | public ApiResponse<List<WarningTypeStatVO>> electricalWarningStats(@RequestHeader(Constants.HEADER_USER_TOKEN) String token) { |
| | | return ApiResponse.success(ywElectricalWarningService.warningTypeStats()); |
| | | } |
| | | |
| | | @ApiOperation("å·¥ä½å°-çµè¡¨æ¥è¦å页") |
| | | @PostMapping("/electricalWarningPage") |
| | | public ApiResponse<PageData<YwElectricalWarning>> electricalWarningPage(@RequestBody PageWrap<YwElectricalWarning> pageWrap, |
| | | @RequestHeader(Constants.HEADER_USER_TOKEN) String token) { |
| | | return ApiResponse.success(ywElectricalWarningService.findPage(pageWrap)); |
| | | } |
| | | |
| | | @ApiOperation("å·¥ä½å°-è¿30天æºè½çµè¡¨æ¯æ¥çµé/çµè´¹") |
| | | @GetMapping("/electricalDailyEnergyStats") |
| | | public ApiResponse<List<DailyEnergyStatVO>> electricalDailyEnergyStats(@RequestHeader(Constants.HEADER_USER_TOKEN) String token) { |
| | | return ApiResponse.success(ywWorkDeskEnergyService.electricalDailyStats()); |
| | | } |
| | | |
| | | @ApiOperation("å·¥ä½å°-è¿30天空è°å¤èæºæ¯æ¥çµé/çµè´¹") |
| | | @GetMapping("/conditionerDailyEnergyStats") |
| | | public ApiResponse<List<DailyEnergyStatVO>> conditionerDailyEnergyStats(@RequestHeader(Constants.HEADER_USER_TOKEN) String token) { |
| | | return ApiResponse.success(ywWorkDeskEnergyService.conditionerDailyStats()); |
| | | } |
| | | |
| | | } |
| | |
| | | |
| | | import java.net.URLEncoder; |
| | | import java.nio.charset.StandardCharsets; |
| | | import java.math.BigDecimal; |
| | | import java.util.Collections; |
| | | import java.util.LinkedHashMap; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | |
| | | JSONObject body = new JSONObject(true); |
| | | putSessionFields(body, req); |
| | | body.put("is_pwr", req.getIs_pwr() != null ? req.getIs_pwr() : 1); |
| | | if (req.getLi_dev() != null && !req.getLi_dev().isEmpty()) { |
| | | body.put("li_dev", req.getLi_dev()); |
| | | } |
| | | if (req.getD_dev() != null && !req.getD_dev().isEmpty()) { |
| | | body.put("d_dev", req.getD_dev()); |
| | | } |
| | | body.put("li_dev", req.getLi_dev() != null ? req.getLi_dev() : Collections.emptyList()); |
| | | body.put("d_dev", req.getD_dev() != null ? req.getD_dev() : Collections.emptyMap()); |
| | | body.put("gs_name", req.getGs_name()); |
| | | body.put("is_rest_stop", req.getIs_rest_stop() != null ? req.getIs_rest_stop() : 0); |
| | | body.put("gs_bz", StringUtils.defaultString(req.getGs_bz())); |
| | |
| | | } |
| | | req.fillSessionDefaults(); |
| | | JSONObject body = new JSONObject(true); |
| | | putSessionFields(body, req); |
| | | body.put("id", req.getId()); |
| | | body.put("is_pwr", req.getIs_pwr() != null ? req.getIs_pwr() : 1); |
| | | body.put("is_rest_stop", req.getIs_rest_stop() != null ? req.getIs_rest_stop() : 0); |
| | |
| | | body.put("left_money", req.getLeft_money()); |
| | | } |
| | | body.put("is_stop", req.getIs_stop() != null ? req.getIs_stop() : 0); |
| | | body.put("li_dev", req.getLi_dev()); |
| | | body.put("d_dev", req.getD_dev()); |
| | | body.put("li_dev", req.getLi_dev() != null ? req.getLi_dev() : Collections.emptyList()); |
| | | body.put("d_dev", req.getD_dev() != null ? req.getD_dev() : Collections.emptyMap()); |
| | | body.put("gs_bz", StringUtils.defaultString(req.getGs_bz())); |
| | | putStopMoney(body, req.getStop_money()); |
| | | return postJsonBody("/changeGs", body, Object.class); |
| | | } |
| | | |
| | | private static void putStopMoney(JSONObject body, Object stopMoney) { |
| | | if (stopMoney != null) { |
| | | body.put("stop_money", stopMoney); |
| | | if (stopMoney == null) { |
| | | body.put("stop_money", "0"); |
| | | return; |
| | | } |
| | | if (stopMoney instanceof BigDecimal) { |
| | | body.put("stop_money", ((BigDecimal) stopMoney).toPlainString()); |
| | | } else { |
| | | body.put("stop_money", String.valueOf(stopMoney)); |
| | | } |
| | | } |
| | | |
| | |
| | | @EqualsAndHashCode(callSuper = true) |
| | | public class EleControlApiRequest extends OpenAccountRequest { |
| | | |
| | | @ApiModelProperty("10æé¸ 11åé¸") |
| | | @ApiModelProperty("10æé¸ 11åé¸ 63ä¿çµ 220è§£é¤ä¿çµ") |
| | | private int type; |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.doumee.dao.admin.request; |
| | | |
| | | import com.doumee.core.annotation.excel.ExcelColumn; |
| | | import io.swagger.annotations.ApiModel; |
| | | import lombok.Data; |
| | | |
| | | /** |
| | | * è¿ç»´è®¾å¤æ¹é导å
¥ |
| | | */ |
| | | @Data |
| | | @ApiModel("è¿ç»´è®¾å¤å¯¼å
¥") |
| | | public class DeviceImport { |
| | | |
| | | @ExcelColumn(name = "*设å¤ç¼å·", value = "code", index = 0) |
| | | private String code; |
| | | |
| | | @ExcelColumn(name = "*设å¤åç§°", value = "name", index = 1) |
| | | private String name; |
| | | |
| | | @ExcelColumn(name = "*设å¤åç±»", value = "categoryPath", index = 2) |
| | | private String categoryPath; |
| | | |
| | | @ExcelColumn(name = "设å¤åå·", value = "modelNo", index = 3) |
| | | private String modelNo; |
| | | |
| | | @ExcelColumn(name = "设å¤ç®¡çå", value = "adminUserName", index = 4) |
| | | private String adminUserName; |
| | | |
| | | @ExcelColumn(name = "æå¨ä½ç½®", value = "addr", index = 5) |
| | | private String addr; |
| | | |
| | | @ExcelColumn(name = "*æå±é¡¹ç®", value = "projectName", index = 6) |
| | | private String projectName; |
| | | |
| | | @ExcelColumn(name = "*å
³èæ¿æº", value = "roomPath", index = 7) |
| | | private String roomPath; |
| | | |
| | | @ExcelColumn(name = "è´å
¥æ¶é´", value = "buyDate", index = 8) |
| | | private String buyDate; |
| | | |
| | | @ExcelColumn(name = "设å¤ç¶æ", value = "statusText", index = 9) |
| | | private String statusText; |
| | | |
| | | @ExcelColumn(name = "è¿ç»´å
容", value = "content", index = 10) |
| | | private String content; |
| | | |
| | | @ExcelColumn(name = "设å¤ä¾åºå", value = "supplier", index = 11) |
| | | private String supplier; |
| | | |
| | | @ExcelColumn(name = "ä¾åºåè系人", value = "supplierLinker", index = 12) |
| | | private String supplierLinker; |
| | | |
| | | @ExcelColumn(name = "ä¾åºåèç³»æ¹å¼", value = "supplierPhone", index = 13) |
| | | private String supplierPhone; |
| | | |
| | | @ExcelColumn(name = "ç»´ä¿è´è´£äºº", value = "maintenanceUserName", index = 14) |
| | | private String maintenanceUserName; |
| | | |
| | | @ExcelColumn(name = "ç»´ä¿å°ææ¥", value = "maintenanceOverDate", index = 15) |
| | | private String maintenanceOverDate; |
| | | |
| | | @ExcelColumn(name = "ç»´ä¿è¯´æ", value = "maintenanceContent", index = 16) |
| | | private String maintenanceContent; |
| | | } |
| | |
| | | private String remark; |
| | | @ApiModelProperty("çµè¡¨ID") |
| | | private Integer electricalId; |
| | | @ApiModelProperty("æä½ç±»å 1é¢ä»è´¹æ¸
é¶ 2åä»è´¹æ¸
é¶ 3è¿ç¨éæ· 4æé¸ 5åé¸ 6弿· 7å
å¼ 8æè¡¨") |
| | | @ApiModelProperty("æä½ç±»å 1é¢ä»è´¹æ¸
é¶ 2åä»è´¹æ¸
é¶ 3è¿ç¨éæ· 4æé¸ 5åé¸ 6弿· 7å
å¼ 8æè¡¨ 9ä¿çµ 10è§£é¤ä¿çµ") |
| | | private Integer actionType; |
| | | private String oprId; |
| | | private String requestBody; |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.doumee.dao.business.vo; |
| | | |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | |
| | | import java.math.BigDecimal; |
| | | |
| | | /** |
| | | * ææ¥æ±æ»çµé/çµè´¹ |
| | | */ |
| | | @Data |
| | | @ApiModel("ææ¥æ±æ»çµé/çµè´¹") |
| | | public class DailyEnergyStatVO { |
| | | |
| | | @ApiModelProperty("æ¥æ yyyy-MM-dd") |
| | | private String statDate; |
| | | |
| | | @ApiModelProperty("æ»çµé kWh") |
| | | private BigDecimal totalKwh; |
| | | |
| | | @ApiModelProperty("æ»çµè´¹ å
") |
| | | private BigDecimal totalFee; |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.doumee.dao.business.vo; |
| | | |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | |
| | | /** |
| | | * çµè¡¨æ¥è¦ç±»åç»è®¡ |
| | | */ |
| | | @Data |
| | | @ApiModel("çµè¡¨æ¥è¦ç±»åç»è®¡") |
| | | public class WarningTypeStatVO { |
| | | |
| | | @ApiModelProperty("æ¥è¦äºä»¶id") |
| | | private Integer warningDefId; |
| | | |
| | | @ApiModelProperty("æ¥è¦é¡¹åç§°") |
| | | private String warningName; |
| | | |
| | | @ApiModelProperty("æ°é") |
| | | private Long count; |
| | | } |
| | |
| | | import com.doumee.dao.business.vo.YwDeviceDataVO; |
| | | import com.doumee.dao.business.vo.YwDeviceParentCateDataVO; |
| | | import com.doumee.dao.business.vo.YwDeviceStatusDataVO; |
| | | import org.springframework.web.multipart.MultipartFile; |
| | | |
| | | import java.util.List; |
| | | import java.util.Set; |
| | |
| | | Set<YwDeviceParentCateDataVO> getDeviceCateData(YwDevice model); |
| | | |
| | | YwDeviceStatusDataVO getDeviceStatus(YwDevice model); |
| | | |
| | | /** |
| | | * æ¹é导å
¥è®¾å¤ |
| | | */ |
| | | String importBatch(MultipartFile file, LoginUserInfo user); |
| | | } |
| | |
| | | import com.doumee.core.model.PageWrap; |
| | | import com.doumee.dao.business.dto.WarningDefOptionDTO; |
| | | import com.doumee.dao.business.model.YwElectricalWarning; |
| | | import com.doumee.dao.business.vo.WarningTypeStatVO; |
| | | |
| | | import java.util.List; |
| | | |
| | |
| | | String syncFromPlatform(); |
| | | |
| | | List<WarningDefOptionDTO> listWarningDefOptions(); |
| | | |
| | | List<WarningTypeStatVO> warningTypeStats(); |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.doumee.service.business; |
| | | |
| | | import com.doumee.dao.business.vo.DailyEnergyStatVO; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * å·¥ä½å°çµé/çµè´¹ç»è®¡ |
| | | */ |
| | | public interface YwWorkDeskEnergyService { |
| | | |
| | | List<DailyEnergyStatVO> electricalDailyStats(); |
| | | |
| | | List<DailyEnergyStatVO> conditionerDailyStats(); |
| | | } |
| | |
| | | import com.doumee.service.business.YwCustomerRechargeBizService; |
| | | import com.doumee.service.business.YwElectricalBizService; |
| | | import com.github.yulichang.wrapper.MPJLambdaWrapper; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.apache.commons.lang3.StringUtils; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.stereotype.Service; |
| | |
| | | import java.util.stream.Collectors; |
| | | |
| | | @Service |
| | | @Slf4j |
| | | public class YwCustomerRechargeBizServiceImpl implements YwCustomerRechargeBizService { |
| | | |
| | | private static final String ONLINE_TEXT = "å¨çº¿"; |
| | | |
| | | @Autowired |
| | | private YwCustomerMapper ywCustomerMapper; |
| | | @Autowired |
| | | private MemberMapper memberMapper; |
| | | @Autowired |
| | | private YwCustomerGsMapper ywCustomerGsMapper; |
| | | @Autowired |
| | |
| | | |
| | | @Override |
| | | public PageData<YwCustomerRechargeMerchantVO> findMerchantPage(PageWrap<YwCustomerRechargeQueryDTO> pageWrap) { |
| | | if (pageWrap == null) { |
| | | pageWrap = new PageWrap<>(); |
| | | } |
| | | YwCustomerRechargeQueryDTO query = pageWrap.getModel() != null ? pageWrap.getModel() : new YwCustomerRechargeQueryDTO(); |
| | | boolean hasDeviceFilter = query.getElectricalStatusFilter() != null || query.getConditionerStatusFilter() != null; |
| | | |
| | | if (hasDeviceFilter) { |
| | | List<YwCustomer> all = ywCustomerMapper.selectList(new QueryWrapper<YwCustomer>().lambda() |
| | | .eq(YwCustomer::getIsdeleted, Constants.ZERO) |
| | | .like(StringUtils.isNotBlank(query.getNameKeyword()), YwCustomer::getName, query.getNameKeyword()) |
| | | .orderByDesc(YwCustomer::getCreateDate)); |
| | | List<YwCustomer> all = ywCustomerMapper.selectJoinList(YwCustomer.class, buildMerchantCustomerWrapper(query)); |
| | | List<YwCustomerRechargeMerchantVO> enriched = enrichMerchantList(all); |
| | | List<YwCustomerRechargeMerchantVO> filtered = enriched.stream() |
| | | .filter(vo -> matchDeviceFilter(vo, query)) |
| | |
| | | } |
| | | |
| | | IPage<YwCustomer> page = new Page<>(pageWrap.getPage(), pageWrap.getCapacity()); |
| | | IPage<YwCustomer> result = ywCustomerMapper.selectPage(page, new QueryWrapper<YwCustomer>().lambda() |
| | | .eq(YwCustomer::getIsdeleted, Constants.ZERO) |
| | | .like(StringUtils.isNotBlank(query.getNameKeyword()), YwCustomer::getName, query.getNameKeyword()) |
| | | .orderByDesc(YwCustomer::getCreateDate)); |
| | | IPage<YwCustomer> result = ywCustomerMapper.selectJoinPage(page, YwCustomer.class, buildMerchantCustomerWrapper(query)); |
| | | List<YwCustomerRechargeMerchantVO> list = enrichMerchantList(result.getRecords()); |
| | | PageData<YwCustomerRechargeMerchantVO> data = new PageData<>(); |
| | | data.setRecords(list); |
| | |
| | | data.setPage(result.getCurrent()); |
| | | data.setCapacity(result.getSize()); |
| | | return data; |
| | | } |
| | | |
| | | private MPJLambdaWrapper<YwCustomer> buildMerchantCustomerWrapper(YwCustomerRechargeQueryDTO query) { |
| | | return new MPJLambdaWrapper<YwCustomer>() |
| | | .selectAll(YwCustomer.class) |
| | | .selectAs(Member::getName, YwCustomer::getMemberName) |
| | | .selectAs(Member::getPhone, YwCustomer::getMemberPhone) |
| | | .leftJoin(Member.class, Member::getId, YwCustomer::getMemberId) |
| | | .eq(YwCustomer::getIsdeleted, Constants.ZERO) |
| | | .like(StringUtils.isNotBlank(query.getNameKeyword()), YwCustomer::getName, query.getNameKeyword()) |
| | | .orderByDesc(YwCustomer::getCreateDate); |
| | | } |
| | | |
| | | private PageData<YwCustomerRechargeMerchantVO> manualPage(List<YwCustomerRechargeMerchantVO> list, long page, long capacity) { |
| | |
| | | } |
| | | List<Integer> customerIds = customers.stream().map(YwCustomer::getId).collect(Collectors.toList()); |
| | | |
| | | Map<Integer, YwCustomerGs> gsMap = ywCustomerGsMapper.selectList(new QueryWrapper<YwCustomerGs>().lambda() |
| | | .eq(YwCustomerGs::getIsdeleted, Constants.ZERO) |
| | | .in(YwCustomerGs::getCustomerId, customerIds)) |
| | | .stream().collect(Collectors.toMap(YwCustomerGs::getCustomerId, g -> g, (a, b) -> a)); |
| | | Map<Integer, YwCustomerGs> gsMap = loadGsMap(customerIds); |
| | | |
| | | List<YwCustomerElectrical> relE = ywCustomerElectricalMapper.selectList(new QueryWrapper<YwCustomerElectrical>().lambda() |
| | | .eq(YwCustomerElectrical::getIsdeleted, Constants.ZERO) |
| | | .in(YwCustomerElectrical::getCustomerId, customerIds)); |
| | | List<YwCustomerElectrical> relE = loadCustomerElectricalRels(customerIds); |
| | | Map<Integer, List<Integer>> customerElectricalIds = relE.stream() |
| | | .collect(Collectors.groupingBy(YwCustomerElectrical::getCustomerId, |
| | | Collectors.mapping(YwCustomerElectrical::getElectricalId, Collectors.toList()))); |
| | | |
| | | List<YwCustomerConditioner> relC = ywCustomerConditionerMapper.selectList(new QueryWrapper<YwCustomerConditioner>().lambda() |
| | | .eq(YwCustomerConditioner::getIsdeleted, Constants.ZERO) |
| | | .in(YwCustomerConditioner::getCustomerId, customerIds)); |
| | | List<YwCustomerConditioner> relC = loadCustomerConditionerRels(customerIds); |
| | | Map<Integer, List<Integer>> customerConditionerIds = relC.stream() |
| | | .collect(Collectors.groupingBy(YwCustomerConditioner::getCustomerId, |
| | | Collectors.mapping(YwCustomerConditioner::getConditionerId, Collectors.toList()))); |
| | | |
| | | Set<Integer> allElectricalIds = relE.stream().map(YwCustomerElectrical::getElectricalId).collect(Collectors.toSet()); |
| | | Map<Integer, YwElectrical> electricalMap = allElectricalIds.isEmpty() ? Collections.emptyMap() |
| | | : ywElectricalMapper.selectBatchIds(allElectricalIds).stream() |
| | | .filter(e -> !Objects.equals(e.getIsdeleted(), Constants.ONE)) |
| | | .collect(Collectors.toMap(YwElectrical::getId, e -> e, (a, b) -> a)); |
| | | Map<Integer, YwElectrical> electricalMap = loadElectricalMap(allElectricalIds); |
| | | |
| | | Set<Integer> allConditionerIds = relC.stream().map(YwCustomerConditioner::getConditionerId).collect(Collectors.toSet()); |
| | | Map<Integer, YwConditioner> conditionerMap = allConditionerIds.isEmpty() ? Collections.emptyMap() |
| | | : ywConditionerMapper.selectBatchIds(allConditionerIds).stream() |
| | | .filter(c -> !Objects.equals(c.getIsdeleted(), Constants.ONE)) |
| | | .collect(Collectors.toMap(YwConditioner::getId, c -> c, (a, b) -> a)); |
| | | |
| | | Set<Integer> memberIds = customers.stream() |
| | | .map(YwCustomer::getMemberId) |
| | | .filter(Objects::nonNull) |
| | | .collect(Collectors.toSet()); |
| | | Map<Integer, Member> memberMap = memberIds.isEmpty() ? Collections.emptyMap() |
| | | : memberMapper.selectBatchIds(memberIds).stream() |
| | | .filter(m -> !Objects.equals(m.getIsdeleted(), Constants.ONE)) |
| | | .collect(Collectors.toMap(Member::getId, m -> m, (a, b) -> a)); |
| | | Map<Integer, YwConditioner> conditionerMap = loadConditionerMap(allConditionerIds); |
| | | |
| | | List<YwCustomerRechargeMerchantVO> list = new ArrayList<>(); |
| | | for (YwCustomer c : customers) { |
| | |
| | | vo.setName(c.getName()); |
| | | vo.setPhone(c.getPhone()); |
| | | vo.setCreateDate(c.getCreateDate()); |
| | | Member member = c.getMemberId() != null ? memberMap.get(c.getMemberId()) : null; |
| | | if (member != null) { |
| | | vo.setMemberName(member.getName()); |
| | | vo.setMemberPhone(member.getPhone()); |
| | | } |
| | | vo.setMemberName(c.getMemberName()); |
| | | vo.setMemberPhone(StringUtils.defaultIfBlank(c.getMemberPhone(), c.getPhone())); |
| | | |
| | | List<Integer> eIds = customerElectricalIds.getOrDefault(c.getId(), Collections.emptyList()); |
| | | vo.setElectricalCount(eIds.size()); |
| | |
| | | list.add(vo); |
| | | } |
| | | return list; |
| | | } |
| | | |
| | | private Map<Integer, YwCustomerGs> loadGsMap(List<Integer> customerIds) { |
| | | if (CollectionUtils.isEmpty(customerIds)) { |
| | | return Collections.emptyMap(); |
| | | } |
| | | try { |
| | | return ywCustomerGsMapper.selectList(new QueryWrapper<YwCustomerGs>().lambda() |
| | | .select(YwCustomerGs::getId, YwCustomerGs::getCustomerId, |
| | | YwCustomerGs::getLeftMoney, YwCustomerGs::getSyncDate, YwCustomerGs::getPlatformGsId) |
| | | .eq(YwCustomerGs::getIsdeleted, Constants.ZERO) |
| | | .in(YwCustomerGs::getCustomerId, customerIds)) |
| | | .stream().collect(Collectors.toMap(YwCustomerGs::getCustomerId, g -> g, (a, b) -> a)); |
| | | } catch (Exception e) { |
| | | log.warn("load yw_customer_gs failed, skip gs stats: {}", e.getMessage()); |
| | | return Collections.emptyMap(); |
| | | } |
| | | } |
| | | |
| | | private List<YwCustomerElectrical> loadCustomerElectricalRels(List<Integer> customerIds) { |
| | | if (CollectionUtils.isEmpty(customerIds)) { |
| | | return Collections.emptyList(); |
| | | } |
| | | try { |
| | | return ywCustomerElectricalMapper.selectList(new QueryWrapper<YwCustomerElectrical>().lambda() |
| | | .select(YwCustomerElectrical::getCustomerId, YwCustomerElectrical::getElectricalId) |
| | | .eq(YwCustomerElectrical::getIsdeleted, Constants.ZERO) |
| | | .in(YwCustomerElectrical::getCustomerId, customerIds)); |
| | | } catch (Exception e) { |
| | | log.warn("load yw_customer_electrical failed, skip electrical stats: {}", e.getMessage()); |
| | | return Collections.emptyList(); |
| | | } |
| | | } |
| | | |
| | | private List<YwCustomerConditioner> loadCustomerConditionerRels(List<Integer> customerIds) { |
| | | if (CollectionUtils.isEmpty(customerIds)) { |
| | | return Collections.emptyList(); |
| | | } |
| | | try { |
| | | return ywCustomerConditionerMapper.selectList(new QueryWrapper<YwCustomerConditioner>().lambda() |
| | | .select(YwCustomerConditioner::getCustomerId, YwCustomerConditioner::getConditionerId) |
| | | .eq(YwCustomerConditioner::getIsdeleted, Constants.ZERO) |
| | | .in(YwCustomerConditioner::getCustomerId, customerIds)); |
| | | } catch (Exception e) { |
| | | log.warn("load yw_customer_conditioner failed, skip conditioner stats: {}", e.getMessage()); |
| | | return Collections.emptyList(); |
| | | } |
| | | } |
| | | |
| | | private Map<Integer, YwElectrical> loadElectricalMap(Set<Integer> electricalIds) { |
| | | if (CollectionUtils.isEmpty(electricalIds)) { |
| | | return Collections.emptyMap(); |
| | | } |
| | | try { |
| | | return ywElectricalMapper.selectList(new QueryWrapper<YwElectrical>().lambda() |
| | | .select(YwElectrical::getId, YwElectrical::getName, YwElectrical::getAddress, |
| | | YwElectrical::getBalance, YwElectrical::getOnline, YwElectrical::getIsdeleted) |
| | | .in(YwElectrical::getId, electricalIds) |
| | | .eq(YwElectrical::getIsdeleted, Constants.ZERO)) |
| | | .stream().collect(Collectors.toMap(YwElectrical::getId, e -> e, (a, b) -> a)); |
| | | } catch (Exception e) { |
| | | log.warn("load electrical for merchant page failed: {}", e.getMessage()); |
| | | return Collections.emptyMap(); |
| | | } |
| | | } |
| | | |
| | | private Map<Integer, YwConditioner> loadConditionerMap(Set<Integer> conditionerIds) { |
| | | if (CollectionUtils.isEmpty(conditionerIds)) { |
| | | return Collections.emptyMap(); |
| | | } |
| | | try { |
| | | return ywConditionerMapper.selectList(new QueryWrapper<YwConditioner>().lambda() |
| | | .select(YwConditioner::getId, YwConditioner::getOnline, YwConditioner::getIsdeleted) |
| | | .in(YwConditioner::getId, conditionerIds) |
| | | .eq(YwConditioner::getIsdeleted, Constants.ZERO)) |
| | | .stream().collect(Collectors.toMap(YwConditioner::getId, c -> c, (a, b) -> a)); |
| | | } catch (Exception e) { |
| | | log.warn("load conditioner for merchant page failed: {}", e.getMessage()); |
| | | return Collections.emptyMap(); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | |
| | | |
| | | @Override |
| | | public YwCustomerGs getCustomerGsConfig(Integer customerId) { |
| | | try { |
| | | return ywCustomerGsMapper.selectOne(new QueryWrapper<YwCustomerGs>().lambda() |
| | | .eq(YwCustomerGs::getCustomerId, customerId) |
| | | .eq(YwCustomerGs::getIsdeleted, Constants.ZERO) |
| | | .last("limit 1")); |
| | | } catch (Exception e) { |
| | | log.warn("load yw_customer_gs failed, retry without stop_money: {}", e.getMessage()); |
| | | return ywCustomerGsMapper.selectOne(new QueryWrapper<YwCustomerGs>().lambda() |
| | | .select(YwCustomerGs::getId, YwCustomerGs::getCustomerId, YwCustomerGs::getPlatformGsId, |
| | | YwCustomerGs::getIsPwr, YwCustomerGs::getIsRestStop, YwCustomerGs::getGsBz, |
| | | YwCustomerGs::getLeftMoney, YwCustomerGs::getSyncDate, |
| | | YwCustomerGs::getCreator, YwCustomerGs::getCreateDate, |
| | | YwCustomerGs::getEditor, YwCustomerGs::getEditDate, YwCustomerGs::getIsdeleted) |
| | | .eq(YwCustomerGs::getCustomerId, customerId) |
| | | .eq(YwCustomerGs::getIsdeleted, Constants.ZERO) |
| | | .last("limit 1")); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void saveCustomerGsConfig(YwCustomerGsConfigDTO dto, LoginUserInfo user) { |
| | | YwCustomer customer = requireCustomer(dto.getCustomerId()); |
| | | if (CollectionUtils.isEmpty(dto.getConditioners())) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "请è³å°å
³èä¸å°ç©ºè°å
æº"); |
| | | } |
| | | validateGsConfigRequired(dto); |
| | | conditionerBizService.ensureLogin(); |
| | | |
| | | List<Integer> conditionerIds = dto.getConditioners().stream() |
| | |
| | | } |
| | | gs.setEditor(user.getId()); |
| | | gs.setEditDate(new Date()); |
| | | gs.setIsPwr(dto.getIsPwr() != null ? dto.getIsPwr() : Constants.ONE); |
| | | gs.setIsRestStop(dto.getIsRestStop() != null ? dto.getIsRestStop() : Constants.ZERO); |
| | | gs.setIsPwr(dto.getIsPwr()); |
| | | gs.setIsRestStop(dto.getIsRestStop()); |
| | | gs.setGsBz(StringUtils.defaultString(dto.getGsBz())); |
| | | gs.setStopMoney(dto.getStopMoney() != null ? dto.getStopMoney() : BigDecimal.ZERO); |
| | | gs.setStopMoney(dto.getStopMoney()); |
| | | |
| | | if (StringUtils.isBlank(customer.getName())) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "客æ·åç§°ä¸è½ä¸ºç©º"); |
| | |
| | | companyReq.setIs_rest_stop(gs.getIsRestStop()); |
| | | companyReq.setGs_bz(gs.getGsBz()); |
| | | companyReq.setStop_money(gs.getStopMoney()); |
| | | companyReq.setLi_dev(liDev); |
| | | companyReq.setD_dev(dDev); |
| | | |
| | | if (gs.getPlatformGsId() == null) { |
| | | ConditionerBaseResponse<Object> addResp = ConditionerUtil.addGs(companyReq); |
| | |
| | | |
| | | refreshGsLeftMoney(gs); |
| | | if (gs.getId() == null) { |
| | | try { |
| | | ywCustomerGsMapper.insert(gs); |
| | | } catch (Exception e) { |
| | | if (gs.getStopMoney() != null) { |
| | | log.warn("insert yw_customer_gs with stop_money failed, retry without stop_money: {}", e.getMessage()); |
| | | gs.setStopMoney(null); |
| | | ywCustomerGsMapper.insert(gs); |
| | | } else { |
| | | throw e; |
| | | } |
| | | } |
| | | } else { |
| | | try { |
| | | ywCustomerGsMapper.updateById(gs); |
| | | } catch (Exception e) { |
| | | if (gs.getStopMoney() != null) { |
| | | log.warn("update yw_customer_gs with stop_money failed, retry without stop_money: {}", e.getMessage()); |
| | | BigDecimal stopMoney = gs.getStopMoney(); |
| | | gs.setStopMoney(null); |
| | | ywCustomerGsMapper.updateById(gs); |
| | | gs.setStopMoney(stopMoney); |
| | | } else { |
| | | throw e; |
| | | } |
| | | } |
| | | } |
| | | |
| | | saveCustomerConditionerRels(dto, user); |
| | | } |
| | | |
| | | /** |
| | | * å
³èå
æº upsertï¼è¡¨ä¸æ uk(customer_id, conditioner_id)ï¼ä¸è½è½¯å åéå¤ insertã |
| | | */ |
| | | private void saveCustomerConditionerRels(YwCustomerGsConfigDTO dto, LoginUserInfo user) { |
| | | List<YwCustomerConditioner> existingRels = ywCustomerConditionerMapper.selectList( |
| | | new QueryWrapper<YwCustomerConditioner>().lambda() |
| | | .eq(YwCustomerConditioner::getCustomerId, dto.getCustomerId())); |
| | | Map<Integer, YwCustomerConditioner> relByCondId = existingRels.stream() |
| | | .collect(Collectors.toMap(YwCustomerConditioner::getConditionerId, r -> r, (a, b) -> a)); |
| | | |
| | | Set<Integer> targetIds = dto.getConditioners().stream() |
| | | .map(YwCustomerGsConfigDTO.ConditionerItem::getConditionerId) |
| | | .filter(Objects::nonNull) |
| | | .collect(Collectors.toSet()); |
| | | |
| | | Date now = new Date(); |
| | | for (YwCustomerConditioner rel : existingRels) { |
| | | if (!targetIds.contains(rel.getConditionerId()) |
| | | && Objects.equals(rel.getIsdeleted(), Constants.ZERO)) { |
| | | ywCustomerConditionerMapper.update(null, new UpdateWrapper<YwCustomerConditioner>().lambda() |
| | | .set(YwCustomerConditioner::getIsdeleted, Constants.ONE) |
| | | .set(YwCustomerConditioner::getEditDate, new Date()) |
| | | .set(YwCustomerConditioner::getEditDate, now) |
| | | .set(YwCustomerConditioner::getEditor, user.getId()) |
| | | .eq(YwCustomerConditioner::getCustomerId, dto.getCustomerId()) |
| | | .eq(YwCustomerConditioner::getIsdeleted, Constants.ZERO)); |
| | | .eq(YwCustomerConditioner::getId, rel.getId())); |
| | | } |
| | | } |
| | | |
| | | for (YwCustomerGsConfigDTO.ConditionerItem item : dto.getConditioners()) { |
| | | YwCustomerConditioner rel = new YwCustomerConditioner(); |
| | | rel.setCreator(user.getId()); |
| | | rel.setCreateDate(new Date()); |
| | | rel.setEditor(user.getId()); |
| | | rel.setEditDate(new Date()); |
| | | if (item.getConditionerId() == null) { |
| | | continue; |
| | | } |
| | | int ratio = item.getDevRatio() != null ? item.getDevRatio() : 100; |
| | | YwCustomerConditioner rel = relByCondId.get(item.getConditionerId()); |
| | | if (rel != null) { |
| | | rel.setIsdeleted(Constants.ZERO); |
| | | rel.setCustomerId(dto.getCustomerId()); |
| | | rel.setConditionerId(item.getConditionerId()); |
| | | rel.setDevRatio(item.getDevRatio() != null ? item.getDevRatio() : 100); |
| | | ywCustomerConditionerMapper.insert(rel); |
| | | rel.setDevRatio(ratio); |
| | | rel.setEditor(user.getId()); |
| | | rel.setEditDate(now); |
| | | ywCustomerConditionerMapper.updateById(rel); |
| | | } else { |
| | | YwCustomerConditioner created = new YwCustomerConditioner(); |
| | | created.setCreator(user.getId()); |
| | | created.setCreateDate(now); |
| | | created.setEditor(user.getId()); |
| | | created.setEditDate(now); |
| | | created.setIsdeleted(Constants.ZERO); |
| | | created.setCustomerId(dto.getCustomerId()); |
| | | created.setConditionerId(item.getConditionerId()); |
| | | created.setDevRatio(ratio); |
| | | ywCustomerConditionerMapper.insert(created); |
| | | relByCondId.put(item.getConditionerId(), created); |
| | | } |
| | | } |
| | | } |
| | | |
| | |
| | | } |
| | | } |
| | | |
| | | private void validateGsConfigRequired(YwCustomerGsConfigDTO dto) { |
| | | if (dto.getStopMoney() == null) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "æ¬ è´¹é¢åº¦ä¸è½ä¸ºç©º"); |
| | | } |
| | | if (dto.getStopMoney().compareTo(BigDecimal.ZERO) < 0) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "æ¬ è´¹é¢åº¦ä¸è½å°äº0"); |
| | | } |
| | | if (dto.getIsPwr() == null) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "计费å¼å
³ä¸è½ä¸ºç©º"); |
| | | } |
| | | if (dto.getIsRestStop() == null) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "æ¯å¦åæºä¸è½ä¸ºç©º"); |
| | | } |
| | | if (CollectionUtils.isEmpty(dto.getConditioners())) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "请è³å°å
³èä¸å°ç©ºè°å
æº"); |
| | | } |
| | | } |
| | | |
| | | private String apiMsg(ConditionerBaseResponse<?> resp, String def) { |
| | | return resp != null && StringUtils.isNotBlank(resp.getMessage()) ? resp.getMessage() : def; |
| | | } |
| | |
| | | import com.doumee.core.utils.Constants; |
| | | import com.doumee.core.utils.DateUtil; |
| | | import com.doumee.core.utils.Utils; |
| | | import com.doumee.core.annotation.excel.ExcelImporter; |
| | | import com.doumee.dao.admin.request.DeviceImport; |
| | | import com.doumee.dao.business.*; |
| | | import com.doumee.dao.business.YwDeviceMapper; |
| | | import com.doumee.dao.business.YwDeviceRecordMapper; |
| | | import com.doumee.dao.business.join.MemberJoinMapper; |
| | | import com.doumee.dao.business.model.*; |
| | | import com.doumee.dao.business.vo.YwDeviceCateDataVO; |
| | | import com.doumee.dao.business.vo.YwDeviceDataVO; |
| | | import com.doumee.dao.business.vo.YwDeviceParentCateDataVO; |
| | | import com.doumee.dao.business.vo.YwDeviceStatusDataVO; |
| | | import com.doumee.dao.system.MultifileMapper; |
| | | import com.doumee.dao.system.SystemUserMapper; |
| | | import com.doumee.dao.system.model.Multifile; |
| | | import com.doumee.dao.system.model.SystemUser; |
| | | import com.doumee.service.business.YwDeviceRecordService; |
| | |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.data.redis.core.RedisTemplate; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | import org.springframework.util.CollectionUtils; |
| | | import org.springframework.web.multipart.MultipartFile; |
| | | |
| | | import java.text.SimpleDateFormat; |
| | | import java.util.*; |
| | | import java.util.stream.Collectors; |
| | | |
| | |
| | | @Autowired |
| | | private RedisTemplate<String,Object> redisTemplate; |
| | | |
| | | @Autowired |
| | | private CategoryMapper categoryMapper; |
| | | @Autowired |
| | | private YwProjectMapper ywProjectMapper; |
| | | @Autowired |
| | | private YwBuildingMapper ywBuildingMapper; |
| | | @Autowired |
| | | private YwFloorMapper ywFloorMapper; |
| | | @Autowired |
| | | private YwRoomMapper ywRoomMapper; |
| | | @Autowired |
| | | private MemberJoinMapper memberJoinMapper; |
| | | @Autowired |
| | | private SystemUserMapper systemUserMapper; |
| | | |
| | | private static final int IMPORT_EXCEL_ROW_OFFSET = 3; |
| | | |
| | | @Override |
| | | public Integer create(YwDevice ywDevice) { |
| | |
| | | |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = {BusinessException.class, Exception.class}) |
| | | public String importBatch(MultipartFile file, LoginUserInfo loginUserInfo) { |
| | | List<DeviceImport> dataList; |
| | | try { |
| | | ExcelImporter ie = new ExcelImporter(file, 1, 0); |
| | | dataList = ie.getDataList(DeviceImport.class, null); |
| | | } catch (Exception e) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "对ä¸èµ·ï¼å¯¼å
¥æä»¶è§£æå¤±è´¥ï¼è¯·æ£æ¥è¡¨æ ¼æ ¼å¼ï¼"); |
| | | } |
| | | if (CollectionUtils.isEmpty(dataList)) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "对ä¸èµ·ï¼å½å
¥æ°æ®ä¸ºç©ºï¼"); |
| | | } |
| | | DeviceImportCache cache = buildImportCache(); |
| | | List<YwDevice> insertList = new ArrayList<>(); |
| | | List<YwDevice> updateList = new ArrayList<>(); |
| | | Set<String> fileCodes = new HashSet<>(); |
| | | Date now = new Date(); |
| | | for (int i = 0; i < dataList.size(); i++) { |
| | | DeviceImport row = dataList.get(i); |
| | | if (isImportBlankRow(row)) { |
| | | continue; |
| | | } |
| | | YwDevice device = checkImportRow(row, i, cache, fileCodes, loginUserInfo, now); |
| | | if (device.getId() != null) { |
| | | updateList.add(device); |
| | | } else { |
| | | insertList.add(device); |
| | | } |
| | | } |
| | | if (CollectionUtils.isEmpty(insertList) && CollectionUtils.isEmpty(updateList)) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "对ä¸èµ·ï¼å½å
¥æææ°æ®ä¸ºç©ºï¼"); |
| | | } |
| | | if (!CollectionUtils.isEmpty(insertList)) { |
| | | ywDeviceMapper.insert(insertList); |
| | | } |
| | | for (YwDevice device : updateList) { |
| | | ywDeviceMapper.updateById(device); |
| | | } |
| | | return String.format("æä½æåï¼æ¬æ¬¡å¯¼å
¥ æ°å¢%d个设å¤ï¼æ´æ°%d个设å¤", insertList.size(), updateList.size()); |
| | | } |
| | | |
| | | private boolean isImportBlankRow(DeviceImport row) { |
| | | return StringUtils.isBlank(row.getCode()) |
| | | && StringUtils.isBlank(row.getName()) |
| | | && StringUtils.isBlank(row.getProjectName()) |
| | | && StringUtils.isBlank(row.getRoomPath()); |
| | | } |
| | | |
| | | private DeviceImportCache buildImportCache() { |
| | | DeviceImportCache cache = new DeviceImportCache(); |
| | | List<Category> categories = categoryMapper.selectList(new QueryWrapper<Category>().lambda() |
| | | .eq(Category::getIsdeleted, Constants.ZERO) |
| | | .eq(Category::getType, Constants.FIVE)); |
| | | Map<Integer, Category> categoryById = categories.stream() |
| | | .collect(Collectors.toMap(Category::getId, c -> c, (a, b) -> a)); |
| | | for (Category category : categories) { |
| | | if (category.getParentId() == null || category.getParentId() <= 0) { |
| | | continue; |
| | | } |
| | | Category parent = categoryById.get(category.getParentId()); |
| | | if (parent == null || StringUtils.isBlank(parent.getName()) || StringUtils.isBlank(category.getName())) { |
| | | continue; |
| | | } |
| | | cache.categoryPathMap.put(parent.getName() + "/" + category.getName(), category.getId()); |
| | | } |
| | | List<YwProject> projects = ywProjectMapper.selectList(new QueryWrapper<YwProject>().lambda() |
| | | .eq(YwProject::getIsdeleted, Constants.ZERO)); |
| | | for (YwProject project : projects) { |
| | | if (StringUtils.isNotBlank(project.getName())) { |
| | | cache.projectNameMap.put(project.getName(), project.getId()); |
| | | } |
| | | } |
| | | List<YwBuilding> buildings = ywBuildingMapper.selectList(new QueryWrapper<YwBuilding>().lambda() |
| | | .eq(YwBuilding::getIsdeleted, Constants.ZERO)); |
| | | for (YwBuilding building : buildings) { |
| | | if (building.getProjectId() != null && StringUtils.isNotBlank(building.getName())) { |
| | | cache.buildingMap.put(building.getProjectId() + "|" + building.getName(), building.getId()); |
| | | } |
| | | } |
| | | List<YwFloor> floors = ywFloorMapper.selectList(new QueryWrapper<YwFloor>().lambda() |
| | | .eq(YwFloor::getIsdeleted, Constants.ZERO)); |
| | | for (YwFloor floor : floors) { |
| | | if (floor.getBuildingId() != null && StringUtils.isNotBlank(floor.getName())) { |
| | | cache.floorMap.put(floor.getBuildingId() + "|" + floor.getName(), floor.getId()); |
| | | } |
| | | } |
| | | List<YwRoom> rooms = ywRoomMapper.selectList(new QueryWrapper<YwRoom>().lambda() |
| | | .eq(YwRoom::getIsdeleted, Constants.ZERO)); |
| | | for (YwRoom room : rooms) { |
| | | if (room.getProjectId() == null || room.getBuildingId() == null || room.getFloor() == null) { |
| | | continue; |
| | | } |
| | | if (StringUtils.isNotBlank(room.getCode())) { |
| | | cache.roomMap.put(roomKey(room.getProjectId(), room.getBuildingId(), room.getFloor(), room.getCode()), room.getId()); |
| | | } |
| | | if (StringUtils.isNotBlank(room.getRoomNum())) { |
| | | cache.roomMap.put(roomKey(room.getProjectId(), room.getBuildingId(), room.getFloor(), room.getRoomNum()), room.getId()); |
| | | } |
| | | } |
| | | List<YwDevice> devices = ywDeviceMapper.selectList(new QueryWrapper<YwDevice>().lambda() |
| | | .eq(YwDevice::getIsdeleted, Constants.ZERO) |
| | | .select(YwDevice::getId, YwDevice::getCode)); |
| | | for (YwDevice device : devices) { |
| | | if (StringUtils.isNotBlank(device.getCode())) { |
| | | cache.existingCodeIdMap.put(device.getCode(), device.getId()); |
| | | } |
| | | } |
| | | List<Member> members = memberJoinMapper.selectJoinList(Member.class, new MPJLambdaWrapper<Member>() |
| | | .select(Member::getId, Member::getName) |
| | | .leftJoin(Company.class, Company::getId, Member::getCompanyId) |
| | | .eq(Member::getIsdeleted, Constants.ZERO) |
| | | .eq(Company::getType, Constants.ONE)); |
| | | if (!CollectionUtils.isEmpty(members)) { |
| | | List<Integer> memberIds = members.stream().map(Member::getId).filter(Objects::nonNull).collect(Collectors.toList()); |
| | | if (!CollectionUtils.isEmpty(memberIds)) { |
| | | List<SystemUser> systemUsers = systemUserMapper.selectList(new QueryWrapper<SystemUser>().lambda() |
| | | .eq(SystemUser::getDeleted, Boolean.FALSE) |
| | | .in(SystemUser::getMemberId, memberIds)); |
| | | Map<Integer, Integer> memberUserMap = systemUsers.stream() |
| | | .filter(u -> u.getMemberId() != null) |
| | | .collect(Collectors.toMap(SystemUser::getMemberId, SystemUser::getId, (a, b) -> a)); |
| | | for (Member member : members) { |
| | | if (StringUtils.isBlank(member.getName())) { |
| | | continue; |
| | | } |
| | | Integer userId = memberUserMap.get(member.getId()); |
| | | if (userId == null) { |
| | | continue; |
| | | } |
| | | if (cache.internalUserNameMap.containsKey(member.getName())) { |
| | | cache.duplicateInternalUserNames.add(member.getName()); |
| | | } |
| | | cache.internalUserNameMap.put(member.getName(), userId); |
| | | } |
| | | } |
| | | } |
| | | return cache; |
| | | } |
| | | |
| | | private String roomKey(Integer projectId, Integer buildingId, Integer floorId, String roomName) { |
| | | return projectId + "|" + buildingId + "|" + floorId + "|" + roomName; |
| | | } |
| | | |
| | | private YwDevice checkImportRow(DeviceImport row, int index, DeviceImportCache cache, Set<String> fileCodes, |
| | | LoginUserInfo loginUserInfo, Date now) { |
| | | int rowNum = index + IMPORT_EXCEL_ROW_OFFSET; |
| | | if (StringUtils.isBlank(row.getCode())) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "对ä¸èµ·ï¼ç¬¬" + rowNum + "è¡è®¾å¤ç¼å·ä¸è½ä¸ºç©ºï¼è¯·æ£æ¥è¡¨æ ¼å
容ï¼"); |
| | | } |
| | | if (StringUtils.isBlank(row.getName())) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "对ä¸èµ·ï¼ç¬¬" + rowNum + "è¡è®¾å¤åç§°ä¸è½ä¸ºç©ºï¼è¯·æ£æ¥è¡¨æ ¼å
容ï¼"); |
| | | } |
| | | if (StringUtils.isBlank(row.getProjectName())) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "对ä¸èµ·ï¼ç¬¬" + rowNum + "è¡æå±é¡¹ç®ä¸è½ä¸ºç©ºï¼è¯·æ£æ¥è¡¨æ ¼å
容ï¼"); |
| | | } |
| | | if (StringUtils.isBlank(row.getRoomPath())) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "对ä¸èµ·ï¼ç¬¬" + rowNum + "è¡å
³èæ¿æºä¸è½ä¸ºç©ºï¼è¯·æ£æ¥è¡¨æ ¼å
容ï¼"); |
| | | } |
| | | String code = row.getCode().trim(); |
| | | if (fileCodes.contains(code)) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "对ä¸èµ·ï¼ç¬¬" + rowNum + "è¡è®¾å¤ç¼å·ã" + code + "ãéå¤ï¼è¯·æ£æ¥è¡¨æ ¼å
容ï¼"); |
| | | } |
| | | fileCodes.add(code); |
| | | Integer existingId = cache.existingCodeIdMap.get(code); |
| | | |
| | | Integer cateId = null; |
| | | if (StringUtils.isNotBlank(row.getCategoryPath())) { |
| | | String categoryPath = row.getCategoryPath().trim(); |
| | | String[] cateParts = categoryPath.split("/"); |
| | | if (cateParts.length < 2 || StringUtils.isBlank(cateParts[1])) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "对ä¸èµ·ï¼ç¬¬" + rowNum + "è¡è®¾å¤åç±»ã" + categoryPath + "ãæ ¼å¼ä¸æ£ç¡®ï¼è¯·ä½¿ç¨ä¸çº§/äºçº§æ ¼å¼ï¼"); |
| | | } |
| | | cateId = cache.categoryPathMap.get(categoryPath); |
| | | if (cateId == null) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "对ä¸èµ·ï¼ç¬¬" + rowNum + "è¡è®¾å¤åç±»ã" + categoryPath + "ãæªæ¾å°ï¼è¯·æ£æ¥è¡¨æ ¼å
容ï¼"); |
| | | } |
| | | } |
| | | |
| | | Integer projectId = cache.projectNameMap.get(row.getProjectName().trim()); |
| | | if (projectId == null) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "对ä¸èµ·ï¼ç¬¬" + rowNum + "è¡æå±é¡¹ç®ã" + row.getProjectName() + "ãæªæ¾å°ï¼è¯·æ£æ¥è¡¨æ ¼å
容ï¼"); |
| | | } |
| | | |
| | | String[] roomParts = row.getRoomPath().trim().split("/"); |
| | | if (roomParts.length < 3 || StringUtils.isAnyBlank(roomParts[0], roomParts[1], roomParts[2])) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "对ä¸èµ·ï¼ç¬¬" + rowNum + "è¡å
³èæ¿æºã" + row.getRoomPath() + "ãæ ¼å¼ä¸æ£ç¡®ï¼è¯·ä½¿ç¨æ¥¼å®/楼å±/æ¿æºæ ¼å¼ï¼"); |
| | | } |
| | | Integer buildingId = cache.buildingMap.get(projectId + "|" + roomParts[0].trim()); |
| | | if (buildingId == null) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "对ä¸èµ·ï¼ç¬¬" + rowNum + "è¡å
³èæ¿æºã" + row.getRoomPath() + "ãæªæ¾å°ï¼è¯·æ£æ¥è¡¨æ ¼å
容ï¼"); |
| | | } |
| | | Integer floorId = cache.floorMap.get(buildingId + "|" + roomParts[1].trim()); |
| | | if (floorId == null) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "对ä¸èµ·ï¼ç¬¬" + rowNum + "è¡å
³èæ¿æºã" + row.getRoomPath() + "ãæªæ¾å°ï¼è¯·æ£æ¥è¡¨æ ¼å
容ï¼"); |
| | | } |
| | | Integer roomId = cache.roomMap.get(roomKey(projectId, buildingId, floorId, roomParts[2].trim())); |
| | | if (roomId == null) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "对ä¸èµ·ï¼ç¬¬" + rowNum + "è¡å
³èæ¿æºã" + row.getRoomPath() + "ãæªæ¾å°ï¼è¯·æ£æ¥è¡¨æ ¼å
容ï¼"); |
| | | } |
| | | |
| | | Integer status = parseImportStatus(row.getStatusText(), rowNum); |
| | | |
| | | Integer userId = resolveInternalUserId(row.getAdminUserName(), rowNum, "设å¤ç®¡çå", cache); |
| | | Integer maintenanceUserId = resolveInternalUserId(row.getMaintenanceUserName(), rowNum, "ç»´ä¿è´è´£äºº", cache); |
| | | |
| | | YwDevice device = new YwDevice(); |
| | | device.setCode(code); |
| | | device.setName(row.getName().trim()); |
| | | device.setCateId(cateId); |
| | | device.setModelNo(StringUtils.trimToNull(row.getModelNo())); |
| | | device.setUserId(userId); |
| | | device.setAddr(StringUtils.trimToNull(row.getAddr())); |
| | | device.setProjectId(projectId); |
| | | device.setBuildingId(buildingId); |
| | | device.setFloorId(floorId); |
| | | device.setRoomId(roomId); |
| | | device.setBuyDate(parseImportDate(row.getBuyDate(), rowNum, "è´å
¥æ¶é´")); |
| | | device.setStatus(status); |
| | | device.setContent(StringUtils.trimToNull(row.getContent())); |
| | | device.setSupplier(StringUtils.trimToNull(row.getSupplier())); |
| | | device.setSupplierLinker(StringUtils.trimToNull(row.getSupplierLinker())); |
| | | device.setSupplierPhone(StringUtils.trimToNull(row.getSupplierPhone())); |
| | | device.setMaintenanceUserId(maintenanceUserId); |
| | | device.setMaintenanceOverDate(parseImportDate(row.getMaintenanceOverDate(), rowNum, "ç»´ä¿å°ææ¥")); |
| | | device.setMaintenanceContent(StringUtils.trimToNull(row.getMaintenanceContent())); |
| | | if (existingId != null) { |
| | | device.setId(existingId); |
| | | device.setEditor(loginUserInfo.getId()); |
| | | device.setEditDate(now); |
| | | } else { |
| | | device.setCreator(loginUserInfo.getId()); |
| | | device.setCreateDate(now); |
| | | device.setIsdeleted(Constants.ZERO); |
| | | } |
| | | return device; |
| | | } |
| | | |
| | | private Integer resolveInternalUserId(String userName, int rowNum, String fieldLabel, DeviceImportCache cache) { |
| | | if (StringUtils.isBlank(userName)) { |
| | | return null; |
| | | } |
| | | String name = userName.trim(); |
| | | if (cache.duplicateInternalUserNames.contains(name)) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "对ä¸èµ·ï¼ç¬¬" + rowNum + "è¡" + fieldLabel + "ã" + name + "ãåå¨éåï¼è¯·æ£æ¥è¡¨æ ¼å
容ï¼"); |
| | | } |
| | | Integer userId = cache.internalUserNameMap.get(name); |
| | | if (userId == null) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "对ä¸èµ·ï¼ç¬¬" + rowNum + "è¡" + fieldLabel + "ã" + name + "ãæªæ¾å°ï¼è¯·æ£æ¥è¡¨æ ¼å
容ï¼"); |
| | | } |
| | | return userId; |
| | | } |
| | | |
| | | private Integer parseImportStatus(String statusText, int rowNum) { |
| | | if (StringUtils.isBlank(statusText)) { |
| | | return Constants.ZERO; |
| | | } |
| | | String text = statusText.trim(); |
| | | if ("æ£å¸¸".equals(text)) { |
| | | return Constants.ZERO; |
| | | } |
| | | if ("æå".equals(text)) { |
| | | return Constants.ONE; |
| | | } |
| | | if ("æ¥åº".equals(text)) { |
| | | return Constants.TWO; |
| | | } |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "对ä¸èµ·ï¼ç¬¬" + rowNum + "è¡è®¾å¤ç¶æã" + statusText + "ã䏿£ç¡®ï¼ä»
æ¯ææ£å¸¸/æå/æ¥åºï¼"); |
| | | } |
| | | |
| | | private Date parseImportDate(String dateText, int rowNum, String fieldLabel) { |
| | | if (StringUtils.isBlank(dateText)) { |
| | | return null; |
| | | } |
| | | String text = dateText.trim(); |
| | | if (StringUtils.endsWith(text, ".0")) { |
| | | text = StringUtils.substringBefore(text, ".0"); |
| | | } |
| | | Date date = DateUtil.parseFromFormats(text); |
| | | if (date != null) { |
| | | return date; |
| | | } |
| | | try { |
| | | return new SimpleDateFormat("yyyy-MM-dd").parse(text); |
| | | } catch (Exception ignored) { |
| | | // try excel serial number below |
| | | } |
| | | try { |
| | | return org.apache.poi.ss.usermodel.DateUtil.getJavaDate(Double.parseDouble(text)); |
| | | } catch (Exception ignored) { |
| | | // fall through to error |
| | | } |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), |
| | | "对ä¸èµ·ï¼ç¬¬" + rowNum + "è¡" + fieldLabel + "ã" + dateText + "ãæ ¼å¼ä¸æ£ç¡®ï¼è¯·ä½¿ç¨yyyy-MM-ddæ ¼å¼ï¼"); |
| | | } |
| | | |
| | | private static class DeviceImportCache { |
| | | private final Map<String, Integer> categoryPathMap = new HashMap<>(); |
| | | private final Map<String, Integer> projectNameMap = new HashMap<>(); |
| | | private final Map<String, Integer> buildingMap = new HashMap<>(); |
| | | private final Map<String, Integer> floorMap = new HashMap<>(); |
| | | private final Map<String, Integer> roomMap = new HashMap<>(); |
| | | private final Map<String, Integer> existingCodeIdMap = new HashMap<>(); |
| | | private final Map<String, Integer> internalUserNameMap = new HashMap<>(); |
| | | private final Set<String> duplicateInternalUserNames = new HashSet<>(); |
| | | } |
| | | |
| | | } |
| | | |
| | |
| | | if (model.getActionType() != null) { |
| | | queryWrapper.eq(YwElectricalActions::getActionType, model.getActionType()); |
| | | } |
| | | if (model.getElectricalId() != null) { |
| | | queryWrapper.eq(YwElectricalActions::getElectricalId, model.getElectricalId()); |
| | | } |
| | | if (model.getOperateTimeBegin() != null) { |
| | | queryWrapper.ge(YwElectricalActions::getCreateDate, Utils.Date.getStart(model.getOperateTimeBegin())); |
| | | } |
| | |
| | | public static final int ACTION_OPEN = 6; |
| | | public static final int ACTION_RECHARGE = 7; |
| | | public static final int ACTION_READ = 8; |
| | | public static final int ACTION_POWER_PROTECT = 9; |
| | | public static final int ACTION_POWER_PROTECT_RELEASE = 10; |
| | | |
| | | private static final long FIRST_STATUS_QUERY_DELAY_MS = 30_000L; |
| | | private static final long STATUS_QUERY_MIN_INTERVAL_MS = 3_600_000L; |
| | |
| | | return doEleControl(e, 10, ACTION_TRIP, user); |
| | | case "close": |
| | | return doEleControl(e, 11, ACTION_CLOSE, user); |
| | | case "powerProtect": |
| | | return doEleControl(e, 63, ACTION_POWER_PROTECT, user); |
| | | case "powerProtectRelease": |
| | | return doEleControl(e, 220, ACTION_POWER_PROTECT_RELEASE, user); |
| | | case "openAccount": |
| | | return doOpenAccount(e, dto, user); |
| | | case "recharge": |
| | |
| | | List<OpenAccountRequest> list = new ArrayList<>(); |
| | | list.add(req); |
| | | ElectronicBaseResponse resp = ElectronicToolUtil.eleControl(list); |
| | | return finishAsync(e, actionType, oprId, "/Api_v2/ele_security/ele_control", reqJson, resp, user); |
| | | return finishAsync(e, actionType, oprId, "/Api_v2/ele_control", reqJson, resp, user); |
| | | } |
| | | |
| | | private String doOpenAccount(YwElectrical e, YwElectricalOperateDTO dto, LoginUserInfo user) { |
| | |
| | | import com.doumee.dao.business.model.YwElectricalRoom; |
| | | import com.doumee.dao.business.model.YwElectricalWarning; |
| | | import com.doumee.dao.business.model.YwRoom; |
| | | import com.doumee.dao.business.vo.WarningTypeStatVO; |
| | | import com.doumee.service.business.YwElectricalWarningService; |
| | | import com.github.yulichang.wrapper.MPJLambdaWrapper; |
| | | import org.apache.commons.lang3.StringUtils; |
| | |
| | | return list; |
| | | } |
| | | |
| | | @Override |
| | | public List<WarningTypeStatVO> warningTypeStats() { |
| | | QueryWrapper<YwElectricalWarning> wrapper = new QueryWrapper<>(); |
| | | wrapper.select("warning_def_id", "count(1) as cnt") |
| | | .eq("isdeleted", Constants.ZERO) |
| | | .eq("device_type", ELECTRICAL_DEVICE_TYPE) |
| | | .isNotNull("warning_def_id") |
| | | .groupBy("warning_def_id") |
| | | .orderByDesc("cnt"); |
| | | List<Map<String, Object>> rows = ywElectricalWarningMapper.selectMaps(wrapper); |
| | | List<WarningTypeStatVO> list = new ArrayList<>(); |
| | | if (CollectionUtils.isEmpty(rows)) { |
| | | return list; |
| | | } |
| | | for (Map<String, Object> row : rows) { |
| | | Object defIdObj = row.get("warning_def_id"); |
| | | if (defIdObj == null) { |
| | | continue; |
| | | } |
| | | Integer warningDefId = Integer.parseInt(String.valueOf(defIdObj)); |
| | | Object cntObj = row.get("cnt"); |
| | | long count = cntObj == null ? 0L : Long.parseLong(String.valueOf(cntObj)); |
| | | WarningTypeStatVO stat = new WarningTypeStatVO(); |
| | | stat.setWarningDefId(warningDefId); |
| | | stat.setCount(count); |
| | | ElectronicConstant.warningDefId def = ElectronicConstant.warningDefId.getByKey(warningDefId); |
| | | stat.setWarningName(def != null ? def.getName() : "æªç¥æ¥è¦"); |
| | | list.add(stat); |
| | | } |
| | | return list; |
| | | } |
| | | |
| | | private MPJLambdaWrapper<YwElectricalWarning> buildPageQuery(PageWrap<YwElectricalWarning> pageWrap) { |
| | | MPJLambdaWrapper<YwElectricalWarning> queryWrapper = new MPJLambdaWrapper<>(); |
| | | YwElectricalWarning model = pageWrap.getModel() == null ? new YwElectricalWarning() : pageWrap.getModel(); |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.doumee.service.business.impl; |
| | | |
| | | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
| | | import com.doumee.core.utils.Constants; |
| | | import com.doumee.dao.business.YwConditionerUsageMapper; |
| | | import com.doumee.dao.business.YwElectricalDataMapper; |
| | | import com.doumee.dao.business.model.YwConditionerUsage; |
| | | import com.doumee.dao.business.model.YwElectricalData; |
| | | import com.doumee.dao.business.vo.DailyEnergyStatVO; |
| | | import com.doumee.service.business.YwWorkDeskEnergyService; |
| | | import org.apache.commons.lang3.StringUtils; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.math.RoundingMode; |
| | | import java.text.ParseException; |
| | | import java.text.SimpleDateFormat; |
| | | import java.time.LocalDate; |
| | | import java.time.format.DateTimeFormatter; |
| | | import java.util.ArrayList; |
| | | import java.util.Date; |
| | | import java.util.HashMap; |
| | | import java.util.LinkedHashMap; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | | @Service |
| | | public class YwWorkDeskEnergyServiceImpl implements YwWorkDeskEnergyService { |
| | | |
| | | private static final int DAYS = 30; |
| | | private static final DateTimeFormatter DATE_FMT = DateTimeFormatter.ofPattern("yyyy-MM-dd"); |
| | | private static final String READ_TIME_PATTERN = "yyyy-MM-dd HH:mm:ss"; |
| | | |
| | | @Autowired |
| | | private YwElectricalDataMapper ywElectricalDataMapper; |
| | | |
| | | @Autowired |
| | | private YwConditionerUsageMapper ywConditionerUsageMapper; |
| | | |
| | | @Override |
| | | public List<DailyEnergyStatVO> electricalDailyStats() { |
| | | LocalDate end = LocalDate.now(); |
| | | LocalDate start = end.minusDays(DAYS - 1L); |
| | | LocalDate queryStart = start.minusDays(1L); |
| | | Map<String, DailyEnergyStatVO> bucket = initDailyBucket(start, end); |
| | | |
| | | List<YwElectricalData> rows = ywElectricalDataMapper.selectList(new QueryWrapper<YwElectricalData>().lambda() |
| | | .eq(YwElectricalData::getIsdeleted, Constants.ZERO) |
| | | .ge(YwElectricalData::getCreateDate, java.sql.Date.valueOf(queryStart)) |
| | | .le(YwElectricalData::getCreateDate, java.sql.Date.valueOf(end.plusDays(1)))); |
| | | |
| | | SimpleDateFormat dayFmt = new SimpleDateFormat("yyyy-MM-dd"); |
| | | SimpleDateFormat readTimeFmt = new SimpleDateFormat(READ_TIME_PATTERN); |
| | | Map<String, Map<String, MeterDayReading>> meterDayLatest = new HashMap<>(); |
| | | |
| | | for (YwElectricalData row : rows) { |
| | | String meterKey = resolveMeterKey(row); |
| | | if (StringUtils.isBlank(meterKey)) { |
| | | continue; |
| | | } |
| | | String dayKey = resolveElectricalDayKey(row, dayFmt); |
| | | if (StringUtils.isBlank(dayKey)) { |
| | | continue; |
| | | } |
| | | BigDecimal totalEnergy = resolveTotalEnergy(row); |
| | | if (totalEnergy.compareTo(BigDecimal.ZERO) < 0) { |
| | | continue; |
| | | } |
| | | long readingTime = resolveReadingTime(row, readTimeFmt); |
| | | MeterDayReading snapshot = new MeterDayReading(totalEnergy, parseDecimal(row.getDqdj()), readingTime); |
| | | upsertLatestReading(meterDayLatest, meterKey, dayKey, snapshot); |
| | | } |
| | | |
| | | for (LocalDate day = start; !day.isAfter(end); day = day.plusDays(1)) { |
| | | String todayKey = day.format(DATE_FMT); |
| | | String yesterdayKey = day.minusDays(1).format(DATE_FMT); |
| | | DailyEnergyStatVO stat = bucket.get(todayKey); |
| | | for (Map<String, MeterDayReading> dayReadings : meterDayLatest.values()) { |
| | | MeterDayReading todayReading = dayReadings.get(todayKey); |
| | | MeterDayReading yesterdayReading = dayReadings.get(yesterdayKey); |
| | | if (todayReading == null || yesterdayReading == null) { |
| | | continue; |
| | | } |
| | | BigDecimal usage = todayReading.totalEnergy.subtract(yesterdayReading.totalEnergy); |
| | | if (usage.compareTo(BigDecimal.ZERO) <= 0) { |
| | | continue; |
| | | } |
| | | stat.setTotalKwh(stat.getTotalKwh().add(usage)); |
| | | stat.setTotalFee(stat.getTotalFee().add(usage.multiply(todayReading.price))); |
| | | } |
| | | } |
| | | return normalizeBucket(bucket); |
| | | } |
| | | |
| | | @Override |
| | | public List<DailyEnergyStatVO> conditionerDailyStats() { |
| | | LocalDate end = LocalDate.now(); |
| | | LocalDate start = end.minusDays(DAYS - 1L); |
| | | Map<String, DailyEnergyStatVO> bucket = initDailyBucket(start, end); |
| | | |
| | | List<YwConditionerUsage> rows = ywConditionerUsageMapper.selectList(new QueryWrapper<YwConditionerUsage>().lambda() |
| | | .eq(YwConditionerUsage::getIsdeleted, Constants.ZERO) |
| | | .ge(YwConditionerUsage::getUsageDate, java.sql.Date.valueOf(start)) |
| | | .le(YwConditionerUsage::getUsageDate, java.sql.Date.valueOf(end))); |
| | | |
| | | SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); |
| | | for (YwConditionerUsage row : rows) { |
| | | if (row.getUsageDate() == null) { |
| | | continue; |
| | | } |
| | | String dayKey = sdf.format(row.getUsageDate()); |
| | | if (!bucket.containsKey(dayKey)) { |
| | | continue; |
| | | } |
| | | DailyEnergyStatVO stat = bucket.get(dayKey); |
| | | stat.setTotalKwh(stat.getTotalKwh().add(nullToZero(row.getSumDl()))); |
| | | stat.setTotalFee(stat.getTotalFee().add(nullToZero(row.getSumDf()))); |
| | | } |
| | | return normalizeBucket(bucket); |
| | | } |
| | | |
| | | private static void upsertLatestReading(Map<String, Map<String, MeterDayReading>> meterDayLatest, |
| | | String meterKey, |
| | | String dayKey, |
| | | MeterDayReading snapshot) { |
| | | Map<String, MeterDayReading> dayMap = meterDayLatest.computeIfAbsent(meterKey, key -> new HashMap<>()); |
| | | MeterDayReading existing = dayMap.get(dayKey); |
| | | if (existing == null || snapshot.readingTime >= existing.readingTime) { |
| | | dayMap.put(dayKey, snapshot); |
| | | } |
| | | } |
| | | |
| | | private static String resolveMeterKey(YwElectricalData row) { |
| | | if (StringUtils.isNotBlank(row.getAddress())) { |
| | | return row.getAddress().trim(); |
| | | } |
| | | if (StringUtils.isNotBlank(row.getDeviceId())) { |
| | | return "dev:" + row.getDeviceId().trim(); |
| | | } |
| | | if (StringUtils.isNotBlank(row.getMid())) { |
| | | return "mid:" + row.getMid().trim(); |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | private static BigDecimal resolveTotalEnergy(YwElectricalData row) { |
| | | BigDecimal total = parseDecimal(row.getZhygzdl()); |
| | | if (total.compareTo(BigDecimal.ZERO) <= 0) { |
| | | total = parseDecimal(row.getZyje()); |
| | | } |
| | | return total; |
| | | } |
| | | |
| | | private static long resolveReadingTime(YwElectricalData row, SimpleDateFormat readTimeFmt) { |
| | | if (StringUtils.isNotBlank(row.getAddTime())) { |
| | | String addTime = row.getAddTime().trim(); |
| | | if (addTime.matches("\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}")) { |
| | | try { |
| | | return readTimeFmt.parse(addTime).getTime(); |
| | | } catch (ParseException ignored) { |
| | | // fallback to createDate |
| | | } |
| | | } |
| | | } |
| | | Date createDate = row.getCreateDate(); |
| | | return createDate == null ? 0L : createDate.getTime(); |
| | | } |
| | | |
| | | private static List<DailyEnergyStatVO> normalizeBucket(Map<String, DailyEnergyStatVO> bucket) { |
| | | List<DailyEnergyStatVO> list = new ArrayList<>(bucket.values()); |
| | | for (DailyEnergyStatVO stat : list) { |
| | | stat.setTotalKwh(stat.getTotalKwh().setScale(2, RoundingMode.HALF_UP)); |
| | | stat.setTotalFee(stat.getTotalFee().setScale(2, RoundingMode.HALF_UP)); |
| | | } |
| | | return list; |
| | | } |
| | | |
| | | private static Map<String, DailyEnergyStatVO> initDailyBucket(LocalDate start, LocalDate end) { |
| | | Map<String, DailyEnergyStatVO> bucket = new LinkedHashMap<>(); |
| | | for (LocalDate d = start; !d.isAfter(end); d = d.plusDays(1)) { |
| | | DailyEnergyStatVO vo = new DailyEnergyStatVO(); |
| | | vo.setStatDate(d.format(DATE_FMT)); |
| | | vo.setTotalKwh(BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP)); |
| | | vo.setTotalFee(BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP)); |
| | | bucket.put(vo.getStatDate(), vo); |
| | | } |
| | | return bucket; |
| | | } |
| | | |
| | | private static String resolveElectricalDayKey(YwElectricalData row, SimpleDateFormat sdf) { |
| | | if (StringUtils.isNotBlank(row.getAddTime())) { |
| | | String addTime = row.getAddTime().trim(); |
| | | if (addTime.length() >= 10) { |
| | | return addTime.substring(0, 10); |
| | | } |
| | | } |
| | | Date createDate = row.getCreateDate(); |
| | | return createDate == null ? null : sdf.format(createDate); |
| | | } |
| | | |
| | | private static BigDecimal parseDecimal(String val) { |
| | | if (StringUtils.isBlank(val)) { |
| | | return BigDecimal.ZERO; |
| | | } |
| | | try { |
| | | return new BigDecimal(val.trim()); |
| | | } catch (NumberFormatException e) { |
| | | return BigDecimal.ZERO; |
| | | } |
| | | } |
| | | |
| | | private static BigDecimal nullToZero(BigDecimal val) { |
| | | return val == null ? BigDecimal.ZERO : val; |
| | | } |
| | | |
| | | private static class MeterDayReading { |
| | | private final BigDecimal totalEnergy; |
| | | private final BigDecimal price; |
| | | private final long readingTime; |
| | | |
| | | private MeterDayReading(BigDecimal totalEnergy, BigDecimal price, long readingTime) { |
| | | this.totalEnergy = totalEnergy; |
| | | this.price = price; |
| | | this.readingTime = readingTime; |
| | | } |
| | | } |
| | | } |