| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import request from '../../utils/request' |
| | | |
| | | const base = '/visitsAdmin/cloudService/business/ywCustomerRecharge' |
| | | |
| | | export function merchantPage (data) { |
| | | return request.post(base + '/merchantPage', data, { trim: true }) |
| | | } |
| | | |
| | | export function getDetail (customerId) { |
| | | return request.get(base + '/' + customerId + '/detail') |
| | | } |
| | | |
| | | export function electricalPage (customerId, data) { |
| | | return request.post(base + '/electrical/page?customerId=' + customerId, data, { trim: true }) |
| | | } |
| | | |
| | | export function selectableElectricalPage (customerId, data) { |
| | | return request.post(base + '/electrical/selectablePage?customerId=' + customerId, data, { trim: true }) |
| | | } |
| | | |
| | | export function saveElectrical (data) { |
| | | return request.post(base + '/electrical/save', data) |
| | | } |
| | | |
| | | export function deleteElectrical (customerId, electricalId) { |
| | | return request.get(base + '/electrical/delete?customerId=' + customerId + '&electricalId=' + electricalId) |
| | | } |
| | | |
| | | export function conditionerPage (customerId, data) { |
| | | return request.post(base + '/conditioner/page?customerId=' + customerId, data, { trim: true }) |
| | | } |
| | | |
| | | export function getGsConfig (customerId) { |
| | | return request.get(base + '/conditioner/gsConfig?customerId=' + customerId) |
| | | } |
| | | |
| | | export function saveGsConfig (data) { |
| | | return request.post(base + '/conditioner/saveGsConfig', data) |
| | | } |
| | | |
| | | export function rechargeElectrical (data) { |
| | | return request.post(base + '/recharge/electrical', data) |
| | | } |
| | | |
| | | export function resetElectrical (data) { |
| | | return request.post(base + '/reset/electrical', data) |
| | | } |
| | | |
| | | export function readMeter (customerId, electricalId) { |
| | | return request.get(base + '/readMeter?customerId=' + customerId + '&electricalId=' + electricalId) |
| | | } |
| | | |
| | | export function getElectricalRemoteInfo (electricalId) { |
| | | return request.get(base + '/electrical/remoteInfo?electricalId=' + electricalId) |
| | | } |
| | | |
| | | export function getConditionerRechargeInfo (customerId) { |
| | | return request.get(base + '/recharge/conditioner/info?customerId=' + customerId) |
| | | } |
| | | |
| | | export function rechargeConditioner (data) { |
| | | return request.post(base + '/recharge/conditioner', data) |
| | | } |
| | | |
| | | export function cleanConditioner (customerId) { |
| | | return request.post(base + '/clean/conditioner?customerId=' + customerId) |
| | | } |
| | | |
| | | export function rechargeRecordPage (data) { |
| | | return request.post(base + '/rechargeRecord/page', data, { trim: true }) |
| | | } |
| | | |
| | | export function retryRecharge (id) { |
| | | return request.post(base + '/rechargeRecord/retry/' + id) |
| | | } |
| | | |
| | | export function syncRechargeStatus (id) { |
| | | return request.post(base + '/rechargeRecord/sync/' + id) |
| | | } |
| | | |
| | | export function exportRechargeRecord (data) { |
| | | return request.post(base + '/rechargeRecord/exportExcel', data, { responseType: 'blob', trim: true }) |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div v-loading="loading"> |
| | | <div class="info-block"> |
| | | <p>客æ·åç§°ï¼{{ customer.name }}</p> |
| | | <p>å©ä½éé¢(å
)ï¼{{ leftMoney }}</p> |
| | | <p>ä½é¢åæ¥æ¶é´ï¼{{ syncDate || '-' }}</p> |
| | | <p v-if="platformInfo">æ»çµéï¼{{ platformInfo.left_money_y != null ? platformInfo.left_money_y : '-' }}</p> |
| | | </div> |
| | | <el-form label-width="120px" size="small"> |
| | | <el-form-item label="å
å¼éé¢"> |
| | | <el-input-number v-model="form.money" :min="0" :precision="2" style="width: 200px"/> |
| | | </el-form-item> |
| | | <el-form-item label="å
å¼å¤æ³¨"> |
| | | <el-input v-model="form.remark" maxlength="300" style="width: 400px"/> |
| | | </el-form-item> |
| | | </el-form> |
| | | <div class="footer-btns"> |
| | | <el-button type="primary" :loading="isOperating" v-permissions="['business:ywcustomerrecharge:recharge']" @click="confirmRecharge">确认å
å¼</el-button> |
| | | <el-button type="warning" plain :loading="isOperating" v-permissions="['business:ywcustomerrecharge:recharge']" @click="confirmClean">è´¦æ·æ¸
é¶</el-button> |
| | | <el-button @click="loadInfo">å·æ°ä½é¢</el-button> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import * as api from '@/api/business/ywcustomerrecharge' |
| | | |
| | | export default { |
| | | name: 'YwCustomerConditionerRechargePanel', |
| | | props: { |
| | | customer: { type: Object, default: () => ({}) } |
| | | }, |
| | | data () { |
| | | return { |
| | | loading: false, |
| | | isOperating: false, |
| | | gsConfig: null, |
| | | platformInfo: null, |
| | | form: { money: 0, remark: '' } |
| | | } |
| | | }, |
| | | computed: { |
| | | leftMoney () { |
| | | if (this.gsConfig && this.gsConfig.leftMoney != null) return this.gsConfig.leftMoney |
| | | return '-' |
| | | }, |
| | | syncDate () { |
| | | return this.gsConfig && this.gsConfig.syncDate |
| | | } |
| | | }, |
| | | mounted () { |
| | | this.loadInfo() |
| | | }, |
| | | methods: { |
| | | loadInfo () { |
| | | this.loading = true |
| | | api.getConditionerRechargeInfo(this.customer.id) |
| | | .then(res => { |
| | | this.gsConfig = res.gsConfig || null |
| | | this.platformInfo = res.platformInfo || null |
| | | }) |
| | | .catch(e => this.$tip.apiFailed(e)) |
| | | .finally(() => { this.loading = false }) |
| | | }, |
| | | confirmRecharge () { |
| | | this.$dialog.actionConfirm('确认å
å¼åï¼', 'æä½ç¡®è®¤') |
| | | .then(() => { |
| | | this.isOperating = true |
| | | return api.rechargeConditioner({ |
| | | customerId: this.customer.id, |
| | | money: this.form.money, |
| | | remark: this.form.remark |
| | | }) |
| | | }) |
| | | .then(msg => { |
| | | this.$tip.success(msg || 'å
弿å') |
| | | this.form.money = 0 |
| | | this.loadInfo() |
| | | this.$emit('success') |
| | | }) |
| | | .catch(e => { if (e !== 'cancel') this.$tip.apiFailed(e) }) |
| | | .finally(() => { this.isOperating = false }) |
| | | }, |
| | | confirmClean () { |
| | | this.$dialog.actionConfirm('确认æ¸
é¶ç©ºè°è´¦æ·åï¼', 'æä½ç¡®è®¤') |
| | | .then(() => { |
| | | this.isOperating = true |
| | | return api.cleanConditioner(this.customer.id) |
| | | }) |
| | | .then(msg => { |
| | | this.$tip.success(msg || 'æ¸
é¶æå') |
| | | this.loadInfo() |
| | | this.$emit('success') |
| | | }) |
| | | .catch(e => { if (e !== 'cancel') this.$tip.apiFailed(e) }) |
| | | .finally(() => { this.isOperating = false }) |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .info-block p { margin: 4px 0; line-height: 26px; } |
| | | .footer-btns { text-align: right; margin-top: 16px; } |
| | | .footer-btns .el-button { margin-left: 8px; } |
| | | </style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div v-loading="loading" class="conditioner-tab"> |
| | | <section class="config-section"> |
| | | <div class="section-title">计费é
ç½®</div> |
| | | <el-form label-width="150px" size="small" class="config-form"> |
| | | <el-row :gutter="24"> |
| | | <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> |
| | | </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> |
| | | </el-col> |
| | | </el-row> |
| | | <el-form-item label="夿³¨" class="remark-item"> |
| | | <el-input |
| | | v-model="form.gsBz" |
| | | type="textarea" |
| | | :rows="2" |
| | | maxlength="500" |
| | | show-word-limit |
| | | placeholder="请è¾å
¥å¤æ³¨ï¼éå¡«ï¼" |
| | | /> |
| | | </el-form-item> |
| | | </el-form> |
| | | </section> |
| | | |
| | | <section class="config-section"> |
| | | <div class="section-header"> |
| | | <span class="section-title">å
³èå
æº</span> |
| | | <el-button type="primary" size="small" icon="el-icon-plus" @click="openSelector">æ·»å å
æº</el-button> |
| | | </div> |
| | | <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 prop="platformDevId" label="å¹³å°è®¾å¤ID" min-width="110" align="center"/> |
| | | <el-table-column label="å¨çº¿" min-width="80" align="center"> |
| | | <template slot-scope="{ row }"> |
| | | <span :class="row.online === 'å¨çº¿' ? 'green' : 'red'">{{ row.online || '-' }}</span> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="çµè´¹å æ¯%" min-width="130" align="center"> |
| | | <template slot-scope="{ row }"> |
| | | <el-input-number v-model="row.devRatio" :min="1" :max="100" size="small" controls-position="right"/> |
| | | </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> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </section> |
| | | |
| | | <div class="footer-btns"> |
| | | <el-button type="primary" :loading="saving" v-permissions="['business:ywcustomerrecharge:bindDevice']" @click="save">ä¿åé
ç½®</el-button> |
| | | </div> |
| | | |
| | | <GlobalWindow title="éæ©ç©ºè°å
æº" :visible.sync="selectorVisible" width="780px" @confirm="confirmSelect"> |
| | | <el-form inline @submit.native.prevent class="selector-form"> |
| | | <el-form-item label="å
³é®å"> |
| | | <el-input v-model="selectorKeyword" placeholder="åç§°/ç¼å·" clearable @keypress.enter.native="searchDevices"/> |
| | | </el-form-item> |
| | | <el-button type="primary" @click="searchDevices">æ¥è¯¢</el-button> |
| | | </el-form> |
| | | <el-table ref="devTable" v-loading="selectorLoading" :data="selectorList" stripe size="small" @selection-change="rows => selectedRows = rows"> |
| | | <el-table-column type="selection" width="45"/> |
| | | <el-table-column label="设å¤" min-width="180" align="left" show-overflow-tooltip> |
| | | <template slot-scope="{ row }">{{ deviceLabel(row) }}</template> |
| | | </el-table-column> |
| | | <el-table-column prop="platformDevId" label="å¹³å°è®¾å¤ID" min-width="110" align="center"/> |
| | | <el-table-column prop="online" label="å¨çº¿" min-width="80" align="center"/> |
| | | </el-table> |
| | | <pagination @current-change="p => { selectorPagination.pageIndex = p; loadDevices() }" :pagination="selectorPagination"/> |
| | | </GlobalWindow> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import GlobalWindow from '@/components/common/GlobalWindow' |
| | | import Pagination from '@/components/common/Pagination' |
| | | import * as rechargeApi from '@/api/business/ywcustomerrecharge' |
| | | import * as conditionerApi from '@/api/business/ywconditioner' |
| | | |
| | | export default { |
| | | name: 'YwCustomerConditionerTab', |
| | | components: { GlobalWindow, Pagination }, |
| | | props: { |
| | | customerId: Number, |
| | | active: Boolean |
| | | }, |
| | | data () { |
| | | return { |
| | | loading: false, |
| | | saving: false, |
| | | form: { |
| | | isPwr: 1, |
| | | isRestStop: 0, |
| | | stopMoney: 0, |
| | | gsBz: '', |
| | | conditioners: [] |
| | | }, |
| | | selectorVisible: false, |
| | | selectorLoading: false, |
| | | selectorKeyword: '', |
| | | selectorList: [], |
| | | selectorPagination: { pageIndex: 1, pageSize: 10, total: 0 }, |
| | | selectedRows: [] |
| | | } |
| | | }, |
| | | watch: { |
| | | active (val) { |
| | | if (val) this.loadConfig() |
| | | }, |
| | | customerId () { |
| | | if (this.active) this.loadConfig() |
| | | } |
| | | }, |
| | | mounted () { |
| | | if (this.active) this.loadConfig() |
| | | }, |
| | | methods: { |
| | | deviceLabel (row) { |
| | | const parts = [row.floorName, row.roomName, row.name].filter(Boolean) |
| | | return parts.length ? parts.join('/') : (row.name || row.code || '-') |
| | | }, |
| | | loadConfig () { |
| | | if (!this.customerId) return |
| | | this.loading = true |
| | | Promise.all([ |
| | | rechargeApi.getGsConfig(this.customerId), |
| | | 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.gsBz = gs.gsBz || '' |
| | | } else { |
| | | this.form.isPwr = 1 |
| | | this.form.isRestStop = 0 |
| | | this.form.stopMoney = 0 |
| | | this.form.gsBz = '' |
| | | } |
| | | this.form.conditioners = (page.records || []).map(c => ({ |
| | | conditionerId: c.id, |
| | | platformDevId: c.platformDevId, |
| | | name: c.name, |
| | | floorName: c.floorName, |
| | | roomName: c.roomName, |
| | | online: c.online, |
| | | devRatio: c.devRatio != null ? c.devRatio : 100 |
| | | })) |
| | | }).catch(e => this.$tip.apiFailed(e)).finally(() => { this.loading = false }) |
| | | }, |
| | | save () { |
| | | if (!this.form.conditioners.length) { |
| | | this.$tip.warning('请è³å°å
³èä¸å°å
æº') |
| | | return |
| | | } |
| | | this.saving = true |
| | | rechargeApi.saveGsConfig({ |
| | | customerId: this.customerId, |
| | | isPwr: this.form.isPwr, |
| | | isRestStop: this.form.isRestStop, |
| | | stopMoney: this.form.stopMoney, |
| | | gsBz: this.form.gsBz, |
| | | conditioners: this.form.conditioners.map(c => ({ |
| | | conditionerId: c.conditionerId, |
| | | devRatio: c.devRatio |
| | | })) |
| | | }).then(() => { |
| | | this.$tip.success('ä¿åæå') |
| | | this.loadConfig() |
| | | this.$emit('success') |
| | | }).catch(e => this.$tip.apiFailed(e)).finally(() => { this.saving = false }) |
| | | }, |
| | | openSelector () { |
| | | this.selectorVisible = true |
| | | this.selectorKeyword = '' |
| | | this.selectedRows = [] |
| | | this.selectorPagination.pageIndex = 1 |
| | | this.loadDevices() |
| | | }, |
| | | loadDevices () { |
| | | this.selectorLoading = true |
| | | conditionerApi.fetchList({ |
| | | page: this.selectorPagination.pageIndex, |
| | | capacity: this.selectorPagination.pageSize, |
| | | model: this.selectorKeyword ? { devKeyword: this.selectorKeyword } : {} |
| | | }).then(data => { |
| | | const boundIds = new Set(this.form.conditioners.map(c => c.conditionerId)) |
| | | this.selectorList = (data.records || []).filter(r => !boundIds.has(r.id)) |
| | | this.selectorPagination.total = data.total || 0 |
| | | }).catch(e => this.$tip.apiFailed(e)).finally(() => { this.selectorLoading = false }) |
| | | }, |
| | | searchDevices () { |
| | | this.selectorPagination.pageIndex = 1 |
| | | this.loadDevices() |
| | | }, |
| | | confirmSelect () { |
| | | if (!this.selectedRows.length) { |
| | | this.$tip.warning('è¯·éæ©å
æº') |
| | | return |
| | | } |
| | | this.selectedRows.forEach(r => { |
| | | this.form.conditioners.push({ |
| | | conditionerId: r.id, |
| | | platformDevId: r.platformDevId, |
| | | name: r.name, |
| | | floorName: r.floorName, |
| | | roomName: r.roomName, |
| | | online: r.online, |
| | | devRatio: 100 |
| | | }) |
| | | }) |
| | | this.selectorVisible = false |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .conditioner-tab { |
| | | padding-top: 4px; |
| | | } |
| | | .config-section { |
| | | margin-bottom: 16px; |
| | | padding: 16px; |
| | | background: #fff; |
| | | border: 1px solid #ebeef5; |
| | | border-radius: 4px; |
| | | } |
| | | .section-header { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | margin-bottom: 12px; |
| | | } |
| | | .section-title { |
| | | font-size: 14px; |
| | | font-weight: 600; |
| | | color: #303133; |
| | | line-height: 22px; |
| | | } |
| | | .section-header .section-title { |
| | | margin-bottom: 0; |
| | | } |
| | | .config-section > .section-title { |
| | | margin-bottom: 12px; |
| | | padding-bottom: 8px; |
| | | border-bottom: 1px solid #ebeef5; |
| | | } |
| | | .config-form { |
| | | margin-bottom: 0; |
| | | } |
| | | .config-form ::v-deep .el-form-item { |
| | | margin-bottom: 12px; |
| | | } |
| | | .config-form ::v-deep .remark-item { |
| | | margin-bottom: 0; |
| | | } |
| | | .config-form ::v-deep .remark-item .el-textarea { |
| | | max-width: 100%; |
| | | } |
| | | .config-form ::v-deep .el-switch { |
| | | width: auto; |
| | | } |
| | | .device-table { |
| | | width: 100%; |
| | | } |
| | | .footer-btns { |
| | | text-align: right; |
| | | padding-top: 4px; |
| | | } |
| | | .selector-form { |
| | | margin-bottom: 12px; |
| | | } |
| | | .green { color: #67c23a; } |
| | | .red { color: #f56c6c; } |
| | | </style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <GlobalWindow title="å
³è设å¤" :visible.sync="visible" width="920px" :show-confirm="false"> |
| | | <div class="merchant-info"> |
| | | <div class="merchant-info__item"> |
| | | <span class="merchant-info__label">客æ·ç±»å</span> |
| | | <span class="merchant-info__value">{{ customerTypeText }}</span> |
| | | </div> |
| | | <div class="merchant-info__item"> |
| | | <span class="merchant-info__label">客æ·åç§°</span> |
| | | <span class="merchant-info__value">{{ customer.name || '-' }}</span> |
| | | </div> |
| | | <div class="merchant-info__item"> |
| | | <span class="merchant-info__label">è系人</span> |
| | | <span class="merchant-info__value">{{ customer.memberName || '-' }}</span> |
| | | </div> |
| | | <div class="merchant-info__item"> |
| | | <span class="merchant-info__label">èç³»æ¹å¼</span> |
| | | <span class="merchant-info__value">{{ customer.memberPhone || '-' }}</span> |
| | | </div> |
| | | </div> |
| | | <el-tabs v-model="activeTab" class="device-tabs"> |
| | | <el-tab-pane label="å
³èçµè¡¨" name="electrical"> |
| | | <YwCustomerElectricalTab :customer-id="customer.id" :active="activeTab === 'electrical'" @success="$emit('success')"/> |
| | | </el-tab-pane> |
| | | <el-tab-pane label="å
³è空è°" name="conditioner"> |
| | | <YwCustomerConditionerTab :customer-id="customer.id" :active="activeTab === 'conditioner'" @success="$emit('success')"/> |
| | | </el-tab-pane> |
| | | </el-tabs> |
| | | </GlobalWindow> |
| | | </template> |
| | | |
| | | <script> |
| | | import GlobalWindow from '@/components/common/GlobalWindow' |
| | | import YwCustomerElectricalTab from './YwCustomerElectricalTab' |
| | | import YwCustomerConditionerTab from './YwCustomerConditionerTab' |
| | | |
| | | export default { |
| | | name: 'YwCustomerDeviceWindow', |
| | | components: { GlobalWindow, YwCustomerElectricalTab, YwCustomerConditionerTab }, |
| | | data () { |
| | | return { |
| | | visible: false, |
| | | activeTab: 'electrical', |
| | | customer: {} |
| | | } |
| | | }, |
| | | computed: { |
| | | customerTypeText () { |
| | | const t = this.customer.type |
| | | return t === 0 || t === '0' ? '个人' : 'ä¼ä¸' |
| | | } |
| | | }, |
| | | methods: { |
| | | open (row, tab) { |
| | | this.customer = { |
| | | id: row.id, |
| | | type: row.type, |
| | | name: row.name, |
| | | memberName: row.memberName, |
| | | memberPhone: row.memberPhone |
| | | } |
| | | this.activeTab = tab || 'electrical' |
| | | this.visible = true |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .merchant-info { |
| | | display: flex; |
| | | flex-wrap: wrap; |
| | | gap: 12px 24px; |
| | | margin-bottom: 16px; |
| | | padding: 30px 16px 30px 16px; |
| | | background: #f5f7fa; |
| | | border-radius: 4px; |
| | | } |
| | | .merchant-info__item { |
| | | min-width: 180px; |
| | | line-height: 22px; |
| | | } |
| | | .merchant-info__label { |
| | | color: #909399; |
| | | margin-right: 8px; |
| | | } |
| | | .merchant-info__label::after { |
| | | content: 'ï¼'; |
| | | } |
| | | .merchant-info__value { |
| | | color: #303133; |
| | | font-weight: 500; |
| | | } |
| | | .device-tabs { |
| | | margin-top: 4px; |
| | | } |
| | | </style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div v-loading="loading"> |
| | | <el-form label-width="120px" size="small"> |
| | | <el-form-item label="éæ©çµè¡¨"> |
| | | <el-select v-model="electricalId" placeholder="è¯·éæ©çµè¡¨" filterable style="width: 360px" @change="loadRemoteInfo"> |
| | | <el-option v-for="item in electricalList" :key="item.id" :label="item.name + ' (' + item.address + ')'" :value="item.id"/> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-form> |
| | | <account-recharge-panel |
| | | v-if="electricalId" |
| | | :info="info" |
| | | :latest="latest" |
| | | :form="form" |
| | | :is-operating="isOperating" |
| | | :purchase-count="purchaseCount" |
| | | mode="recharge" |
| | | @read="readMeter" |
| | | @confirm="confirmRecharge" |
| | | /> |
| | | <!-- <div v-if="electricalId" class="extra-btns"> |
| | | <el-button type="warning" plain :loading="isOperating" v-permissions="['business:ywcustomerrecharge:recharge']" @click="resetAccount('resetPrepay')">æ¸
é¶(é¢ä»è´¹)</el-button> |
| | | <el-button type="warning" plain :loading="isOperating" v-permissions="['business:ywcustomerrecharge:recharge']" @click="resetAccount('resetPostpay')">æ¸
é¶(åä»è´¹)</el-button> |
| | | </div> |
| | | --> |
| | | <div v-if="!electricalList.length && !loading" class="empty-tip">è¯¥åæ·å°æªå
³èçµè¡¨ï¼è¯·å
å¨å
³è设å¤ä¸æ·»å </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import AccountRechargePanel from './AccountRechargePanel' |
| | | import * as api from '@/api/business/ywcustomerrecharge' |
| | | |
| | | export default { |
| | | name: 'YwCustomerElectricalRechargePanel', |
| | | components: { AccountRechargePanel }, |
| | | props: { |
| | | customer: { type: Object, default: () => ({}) } |
| | | }, |
| | | data () { |
| | | return { |
| | | loading: false, |
| | | electricalList: [], |
| | | electricalId: null, |
| | | info: {}, |
| | | latest: null, |
| | | purchaseCount: '0', |
| | | form: { money: 0, remark: '' }, |
| | | isOperating: false |
| | | } |
| | | }, |
| | | mounted () { |
| | | this.loadElectricalList() |
| | | }, |
| | | methods: { |
| | | loadElectricalList () { |
| | | this.loading = true |
| | | api.electricalPage(this.customer.id, { page: 1, capacity: 500, model: {} }) |
| | | .then(data => { |
| | | this.electricalList = data.records || [] |
| | | if (this.electricalList.length) { |
| | | this.electricalId = this.electricalList[0].id |
| | | this.loadRemoteInfo() |
| | | } |
| | | }) |
| | | .catch(e => this.$tip.apiFailed(e)) |
| | | .finally(() => { this.loading = false }) |
| | | }, |
| | | loadRemoteInfo () { |
| | | if (!this.electricalId) return |
| | | api.getElectricalRemoteInfo(this.electricalId).then(res => { |
| | | this.info = res.electrical || {} |
| | | this.latest = res.latestData |
| | | this.purchaseCount = res.purchaseCount || '0' |
| | | }).catch(e => this.$tip.apiFailed(e)) |
| | | }, |
| | | readMeter () { |
| | | if (!this.electricalId) return |
| | | this.isOperating = true |
| | | api.readMeter(this.customer.id, this.electricalId) |
| | | .then(res => { |
| | | this.info = res.electrical || this.info |
| | | this.latest = res.latestData |
| | | this.$tip.success(res.message || 'æè¡¨å®æ') |
| | | }) |
| | | .catch(e => this.$tip.apiFailed(e)) |
| | | .finally(() => { this.isOperating = false }) |
| | | }, |
| | | confirmRecharge () { |
| | | this.$dialog.actionConfirm('确认å
å¼åï¼', 'æä½ç¡®è®¤') |
| | | .then(() => { |
| | | this.isOperating = true |
| | | return api.rechargeElectrical({ |
| | | customerId: this.customer.id, |
| | | electricalId: this.electricalId, |
| | | money: this.form.money, |
| | | remark: this.form.remark |
| | | }) |
| | | }) |
| | | .then(msg => { |
| | | this.$tip.success(msg || 'æäº¤æåï¼è¯·å¨å
å¼è®°å½ä¸æ¥çç»æ') |
| | | this.loadRemoteInfo() |
| | | this.$emit('success') |
| | | }) |
| | | .catch(e => { if (e !== 'cancel') this.$tip.apiFailed(e) }) |
| | | .finally(() => { this.isOperating = false }) |
| | | }, |
| | | resetAccount (resetAction) { |
| | | const label = resetAction === 'resetPrepay' ? 'é¢ä»è´¹' : 'åä»è´¹' |
| | | this.$dialog.actionConfirm('确认æ¸
é¶å¹¶åæ¢å°' + label + '模å¼åï¼', 'æä½ç¡®è®¤') |
| | | .then(() => { |
| | | this.isOperating = true |
| | | return api.resetElectrical({ |
| | | customerId: this.customer.id, |
| | | electricalId: this.electricalId, |
| | | resetAction |
| | | }) |
| | | }) |
| | | .then(msg => { |
| | | this.$tip.success(msg || 'æäº¤æå') |
| | | this.loadRemoteInfo() |
| | | this.$emit('success') |
| | | }) |
| | | .catch(e => { if (e !== 'cancel') this.$tip.apiFailed(e) }) |
| | | .finally(() => { this.isOperating = false }) |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .extra-btns { margin-top: 12px; } |
| | | .empty-tip { padding: 24px; color: #909399; text-align: center; } |
| | | </style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div> |
| | | <div class="toolbar-row"> |
| | | <el-button type="primary" size="small" v-permissions="['business:ywcustomerrecharge:bindDevice']" @click="openSelector">å»éæ©çµè¡¨</el-button> |
| | | </div> |
| | | <el-table v-loading="loading" :data="list" stripe size="small"> |
| | | <el-table-column prop="name" label="åç§°" min-width="120" align="center" show-overflow-tooltip/> |
| | | <el-table-column prop="address" label="表å°å" min-width="130" align="center" show-overflow-tooltip/> |
| | | <el-table-column prop="accountId" label="弿·å·" min-width="100" align="center"/> |
| | | <el-table-column prop="roomNames" label="æ¿é´" min-width="120" align="center" show-overflow-tooltip/> |
| | | <el-table-column label="å¨çº¿" min-width="80" align="center"> |
| | | <template slot-scope="{ row }"> |
| | | <span :class="row.online === 1 ? 'green' : 'red'">{{ row.online === 1 ? 'å¨çº¿' : '离线' }}</span> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="ç»§çµå¨" min-width="80" align="center"> |
| | | <template slot-scope="{ row }">{{ relayText(row.relayStatus) }}</template> |
| | | </el-table-column> |
| | | <el-table-column label="æä½" min-width="80" align="center"> |
| | | <template slot-scope="{ row }"> |
| | | <el-button type="text" class="red" v-permissions="['business:ywcustomerrecharge:bindDevice']" @click="remove(row)">ç§»é¤</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | <pagination small @size-change="onSizeChange" @current-change="onPageChange" :pagination="pagination"/> |
| | | |
| | | <GlobalWindow title="éæ©çµè¡¨" :visible.sync="selectorVisible" width="780px" @confirm="confirmSelect"> |
| | | <el-form inline @submit.native.prevent> |
| | | <el-form-item label="å
³é®å"> |
| | | <el-input v-model="selectorKeyword" placeholder="åç§°/å°å" clearable @keypress.enter.native="searchSelectable"/> |
| | | </el-form-item> |
| | | <el-button type="primary" @click="searchSelectable">æ¥è¯¢</el-button> |
| | | </el-form> |
| | | <el-table ref="selectTable" v-loading="selectorLoading" :data="selectorList" stripe size="small" @selection-change="onSelectionChange"> |
| | | <el-table-column type="selection" width="45"/> |
| | | <el-table-column prop="name" label="åç§°" min-width="120" align="center"/> |
| | | <el-table-column prop="address" label="表å°å" min-width="130" align="center"/> |
| | | <el-table-column prop="roomNames" label="æ¿é´" min-width="120" align="center" show-overflow-tooltip/> |
| | | <el-table-column label="å¨çº¿" min-width="80" align="center"> |
| | | <template slot-scope="{ row }"> |
| | | <span :class="row.online === 1 ? 'green' : 'red'">{{ row.online === 1 ? 'å¨çº¿' : '离线' }}</span> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | <pagination small @current-change="onSelectorPageChange" :pagination="selectorPagination"/> |
| | | </GlobalWindow> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import GlobalWindow from '@/components/common/GlobalWindow' |
| | | import Pagination from '@/components/common/Pagination' |
| | | import * as api from '@/api/business/ywcustomerrecharge' |
| | | |
| | | export default { |
| | | name: 'YwCustomerElectricalTab', |
| | | components: { GlobalWindow, Pagination }, |
| | | props: { |
| | | customerId: Number, |
| | | active: Boolean |
| | | }, |
| | | data () { |
| | | return { |
| | | loading: false, |
| | | list: [], |
| | | pagination: { pageIndex: 1, pageSize: 10, total: 0 }, |
| | | selectorVisible: false, |
| | | selectorLoading: false, |
| | | selectorList: [], |
| | | selectorKeyword: '', |
| | | selectorPagination: { pageIndex: 1, pageSize: 10, total: 0 }, |
| | | selectedRows: [] |
| | | } |
| | | }, |
| | | watch: { |
| | | active (val) { |
| | | if (val) this.loadList() |
| | | }, |
| | | customerId () { |
| | | if (this.active) this.loadList() |
| | | } |
| | | }, |
| | | mounted () { |
| | | if (this.active) this.loadList() |
| | | }, |
| | | methods: { |
| | | relayText (v) { |
| | | if (v === '0' || v === 0) return 'æé¸' |
| | | if (v === '1' || v === 1) return 'åé¸' |
| | | return v || '-' |
| | | }, |
| | | loadList () { |
| | | if (!this.customerId) return |
| | | this.loading = true |
| | | api.electricalPage(this.customerId, { |
| | | page: this.pagination.pageIndex, |
| | | capacity: this.pagination.pageSize, |
| | | model: {} |
| | | }).then(data => { |
| | | this.list = data.records || [] |
| | | this.pagination.total = data.total || 0 |
| | | }).catch(e => this.$tip.apiFailed(e)).finally(() => { this.loading = false }) |
| | | }, |
| | | onPageChange (p) { |
| | | this.pagination.pageIndex = p |
| | | this.loadList() |
| | | }, |
| | | onSizeChange (s) { |
| | | this.pagination.pageSize = s |
| | | this.pagination.pageIndex = 1 |
| | | this.loadList() |
| | | }, |
| | | remove (row) { |
| | | this.$dialog.actionConfirm('确认移é¤è¯¥çµè¡¨å
³èåï¼', 'æä½ç¡®è®¤') |
| | | .then(() => api.deleteElectrical(this.customerId, row.id)) |
| | | .then(() => { |
| | | this.$tip.success('已移é¤') |
| | | this.loadList() |
| | | this.$emit('success') |
| | | }) |
| | | .catch(e => { if (e !== 'cancel') this.$tip.apiFailed(e) }) |
| | | }, |
| | | openSelector () { |
| | | this.selectorVisible = true |
| | | this.selectorKeyword = '' |
| | | this.selectedRows = [] |
| | | this.selectorPagination.pageIndex = 1 |
| | | this.loadSelectable() |
| | | }, |
| | | loadSelectable () { |
| | | this.selectorLoading = true |
| | | api.selectableElectricalPage(this.customerId, { |
| | | page: this.selectorPagination.pageIndex, |
| | | capacity: this.selectorPagination.pageSize, |
| | | model: this.selectorKeyword ? { name: this.selectorKeyword } : {} |
| | | }).then(data => { |
| | | this.selectorList = data.records || [] |
| | | this.selectorPagination.total = data.total || 0 |
| | | }).catch(e => this.$tip.apiFailed(e)).finally(() => { this.selectorLoading = false }) |
| | | }, |
| | | searchSelectable () { |
| | | this.selectorPagination.pageIndex = 1 |
| | | this.loadSelectable() |
| | | }, |
| | | onSelectorPageChange (p) { |
| | | this.selectorPagination.pageIndex = p |
| | | this.loadSelectable() |
| | | }, |
| | | onSelectionChange (rows) { |
| | | this.selectedRows = rows |
| | | }, |
| | | confirmSelect () { |
| | | if (!this.selectedRows.length) { |
| | | this.$tip.warning('è¯·éæ©çµè¡¨') |
| | | return |
| | | } |
| | | api.saveElectrical({ |
| | | customerId: this.customerId, |
| | | electricalIds: this.selectedRows.map(r => r.id) |
| | | }).then(() => { |
| | | this.$tip.success('ä¿åæå') |
| | | this.selectorVisible = false |
| | | this.loadList() |
| | | this.$emit('success') |
| | | }).catch(e => this.$tip.apiFailed(e)) |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .toolbar-row { margin-bottom: 12px; } |
| | | .green { color: #67c23a; } |
| | | .red { color: #f56c6c; } |
| | | </style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <GlobalWindow :title="'å
å¼ - ' + (customer.name || '')" :visible.sync="visible" width="820px" :show-confirm="false"> |
| | | <el-tabs v-model="activeTab"> |
| | | <el-tab-pane label="çµè¡¨å
å¼" name="electrical"> |
| | | <YwCustomerElectricalRechargePanel |
| | | v-if="activeTab === 'electrical'" |
| | | :customer="customer" |
| | | @success="onSuccess" |
| | | /> |
| | | </el-tab-pane> |
| | | <el-tab-pane label="空è°å
å¼" name="conditioner"> |
| | | <YwCustomerConditionerRechargePanel |
| | | v-if="activeTab === 'conditioner'" |
| | | :customer="customer" |
| | | @success="onSuccess" |
| | | /> |
| | | </el-tab-pane> |
| | | </el-tabs> |
| | | </GlobalWindow> |
| | | </template> |
| | | |
| | | <script> |
| | | import GlobalWindow from '@/components/common/GlobalWindow' |
| | | import YwCustomerElectricalRechargePanel from './YwCustomerElectricalRechargePanel' |
| | | import YwCustomerConditionerRechargePanel from './YwCustomerConditionerRechargePanel' |
| | | |
| | | export default { |
| | | name: 'YwCustomerRechargeWindow', |
| | | components: { GlobalWindow, YwCustomerElectricalRechargePanel, YwCustomerConditionerRechargePanel }, |
| | | data () { |
| | | return { |
| | | visible: false, |
| | | activeTab: 'electrical', |
| | | customer: {} |
| | | } |
| | | }, |
| | | methods: { |
| | | open (row, tab) { |
| | | this.customer = { id: row.id, name: row.name } |
| | | this.activeTab = tab || 'electrical' |
| | | this.visible = true |
| | | }, |
| | | onSuccess () { |
| | | this.$emit('success') |
| | | } |
| | | } |
| | | } |
| | | </script> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <TableLayout :permissions="['business:ywcustomerrecharge:query']"> |
| | | <el-form ref="searchForm" slot="search-form" :model="searchForm" label-width="100px" inline> |
| | | <el-form-item label="客æ·åç§°" prop="nameKeyword"> |
| | | <el-input v-model="searchForm.nameKeyword" placeholder="客æ·åç§°" clearable @keypress.enter.native="search"/> |
| | | </el-form-item> |
| | | <el-form-item label="çµè¡¨ç¶æ" prop="electricalStatusFilter"> |
| | | <el-select v-model="searchForm.electricalStatusFilter" clearable placeholder="å
¨é¨" style="min-width: 120px"> |
| | | <el-option label="å
¨å¨çº¿" :value="1"/> |
| | | <el-option label="åå¨ç¦»çº¿" :value="2"/> |
| | | <el-option label="æ 设å¤" :value="3"/> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="空è°ç¶æ" prop="conditionerStatusFilter"> |
| | | <el-select v-model="searchForm.conditionerStatusFilter" clearable placeholder="å
¨é¨" style="min-width: 120px"> |
| | | <el-option label="å
¨å¨çº¿" :value="1"/> |
| | | <el-option label="åå¨ç¦»çº¿" :value="2"/> |
| | | <el-option label="æ 设å¤" :value="3"/> |
| | | </el-select> |
| | | </el-form-item> |
| | | <section> |
| | | <el-button type="primary" icon="el-icon-search" @click="search">æ¥è¯¢</el-button> |
| | | <el-button icon="el-icon-refresh" @click="reset">éç½®</el-button> |
| | | </section> |
| | | </el-form> |
| | | <template v-slot:table-wrap> |
| | | <el-table v-loading="isWorking.search" :data="tableData.list" stripe> |
| | | <el-table-column prop="type" label="客æ·ç±»å" min-width="80" align="center"> |
| | | <template slot-scope="{ row }"> |
| | | <span>{{ row.type == 0 || row.type === '0' ? '个人' : 'ä¼ä¸' }}</span> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="name" label="客æ·åç§°" min-width="140" align="center" show-overflow-tooltip/> |
| | | <el-table-column prop="memberName" label="è系人" min-width="120" align="center" show-overflow-tooltip> |
| | | <template slot-scope="{ row }">{{ row.memberName || '-' }}</template> |
| | | </el-table-column> |
| | | <el-table-column prop="memberPhone" label="èç³»çµè¯" min-width="130" align="center"> |
| | | <template slot-scope="{ row }">{{ row.memberPhone || '-' }}</template> |
| | | </el-table-column> |
| | | <el-table-column prop="electricalCount" label="å
³èçµè¡¨æ°" min-width="100" align="center"/> |
| | | <el-table-column label="çµè¡¨ä½é¢" min-width="140" align="center"> |
| | | <template slot-scope="{ row }"> |
| | | <span v-if="!row.electricalBalances || !row.electricalBalances.length" class="balance-text">-</span> |
| | | <el-tooltip v-else placement="top" effect="dark"> |
| | | <div slot="content" class="balance-tooltip"> |
| | | <div v-for="(item, idx) in row.electricalBalances" :key="idx" class="balance-tooltip-line"> |
| | | {{ item.name }}ï¼{{ item.address }}ï¼ï¼{{ formatBalance(item.balance) }} |
| | | </div> |
| | | </div> |
| | | <span class="balance-text balance-summary"> |
| | | <template v-for="(item, idx) in row.electricalBalances"> |
| | | <span :key="'b-' + idx" :class="{ red: isAmountLow(item.balance) }">{{ formatBalance(item.balance) }}</span><span v-if="idx < row.electricalBalances.length - 1" :key="'s-' + idx">/</span> |
| | | </template> |
| | | </span> |
| | | </el-tooltip> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="conditionerCount" label="空è°å
æºæ°" min-width="100" align="center"/> |
| | | <el-table-column label="空è°ä½é¢" min-width="110" align="center"> |
| | | <template slot-scope="{ row }"> |
| | | <span v-if="row.acBalance == null" class="balance-text">-</span> |
| | | <span v-else class="balance-text" :class="{ red: isAmountLow(row.acBalance) }">{{ row.acBalance }}</span> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="createDate" label="å建æ¶é´" min-width="160" align="center"/> |
| | | <el-table-column label="æä½" min-width="180" align="center" fixed="right"> |
| | | <template slot-scope="{ row }"> |
| | | <el-button type="text" v-permissions="['business:ywcustomerrecharge:bindDevice']" @click="openDevice(row)">å
³è设å¤</el-button> |
| | | <el-button type="text" v-permissions="['business:ywcustomerrecharge:recharge']" @click="openRecharge(row)">å
å¼</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | <pagination @size-change="handleSizeChange" @current-change="handlePageChange" :pagination="tableData.pagination"/> |
| | | </template> |
| | | <YwCustomerDeviceWindow ref="deviceWindow" @success="search"/> |
| | | <YwCustomerRechargeWindow ref="rechargeWindow" @success="search"/> |
| | | </TableLayout> |
| | | </template> |
| | | |
| | | <script> |
| | | import BaseTable from '@/components/base/BaseTable' |
| | | import TableLayout from '@/layouts/TableLayout' |
| | | import Pagination from '@/components/common/Pagination' |
| | | import * as api from '@/api/business/ywcustomerrecharge' |
| | | import YwCustomerDeviceWindow from './components/YwCustomerDeviceWindow' |
| | | import YwCustomerRechargeWindow from './components/YwCustomerRechargeWindow' |
| | | |
| | | export default { |
| | | name: 'YwCustomerRecharge', |
| | | extends: BaseTable, |
| | | components: { TableLayout, Pagination, YwCustomerDeviceWindow, YwCustomerRechargeWindow }, |
| | | data () { |
| | | return { |
| | | searchForm: { |
| | | nameKeyword: '', |
| | | electricalStatusFilter: null, |
| | | conditionerStatusFilter: null |
| | | } |
| | | } |
| | | }, |
| | | created () { |
| | | this.search() |
| | | }, |
| | | methods: { |
| | | handlePageChange (pageIndex) { |
| | | this.tableData.pagination.pageIndex = pageIndex || this.tableData.pagination.pageIndex |
| | | this.loadList() |
| | | }, |
| | | loadList () { |
| | | this.isWorking.search = true |
| | | api.merchantPage({ |
| | | page: this.tableData.pagination.pageIndex, |
| | | 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 }) |
| | | }, |
| | | search () { |
| | | this.tableData.pagination.pageIndex = 1 |
| | | this.loadList() |
| | | }, |
| | | buildSearchModel () { |
| | | const model = {} |
| | | if (this.searchForm.nameKeyword) model.nameKeyword = this.searchForm.nameKeyword |
| | | if (this.searchForm.electricalStatusFilter != null) model.electricalStatusFilter = this.searchForm.electricalStatusFilter |
| | | if (this.searchForm.conditionerStatusFilter != null) model.conditionerStatusFilter = this.searchForm.conditionerStatusFilter |
| | | return model |
| | | }, |
| | | reset () { |
| | | this.searchForm = { nameKeyword: '', electricalStatusFilter: null, conditionerStatusFilter: null } |
| | | this.search() |
| | | }, |
| | | openDevice (row) { |
| | | this.$refs.deviceWindow.open(row) |
| | | }, |
| | | openRecharge (row) { |
| | | this.$refs.rechargeWindow.open(row) |
| | | }, |
| | | formatBalance (val) { |
| | | if (val == null || val === '') return '0' |
| | | const n = parseFloat(val) |
| | | return isNaN(n) ? val : String(val) |
| | | }, |
| | | isAmountLow (val) { |
| | | if (val == null || val === '' || val === '-') return false |
| | | const n = parseFloat(val) |
| | | return !isNaN(n) && n <= 0 |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .red { color: #f56c6c; } |
| | | .balance-text { white-space: nowrap; } |
| | | .balance-summary { |
| | | cursor: default; |
| | | } |
| | | </style> |
| | | |
| | | <style> |
| | | .balance-tooltip { |
| | | line-height: 22px; |
| | | } |
| | | .balance-tooltip-line { |
| | | white-space: nowrap; |
| | | } |
| | | </style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <TableLayout :permissions="['business:ywcustomerrechargerecord:query']"> |
| | | <el-form ref="searchForm" slot="search-form" :model="searchForm" label-width="100px" inline> |
| | | <el-form-item label="客æ·åç§°" prop="customerName"> |
| | | <el-input v-model="searchForm.customerName" placeholder="客æ·åç§°" clearable @keypress.enter.native="search"/> |
| | | </el-form-item> |
| | | <el-form-item label="ä¸å¡ç±»å" prop="type"> |
| | | <el-select v-model="searchForm.type" clearable placeholder="å
¨é¨" style="min-width: 120px"> |
| | | <el-option label="çµè¡¨" :value="0"/> |
| | | <el-option label="空è°" :value="1"/> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="å
å¼ç¶æ" prop="status"> |
| | | <el-select v-model="searchForm.status" clearable placeholder="å
¨é¨" style="min-width: 120px"> |
| | | <el-option label="å
å¼ä¸" :value="0"/> |
| | | <el-option label="å
弿å" :value="1"/> |
| | | <el-option label="å
å¼å¤±è´¥" :value="2"/> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="æäº¤æ¶é´"> |
| | | <el-date-picker |
| | | v-model="searchForm.dateRange" |
| | | type="datetimerange" |
| | | value-format="yyyy-MM-dd HH:mm:ss" |
| | | start-placeholder="å¼å§" |
| | | end-placeholder="ç»æ" |
| | | style="width: 360px" |
| | | /> |
| | | </el-form-item> |
| | | <section> |
| | | <el-button type="primary" icon="el-icon-search" @click="search">æ¥è¯¢</el-button> |
| | | <el-button icon="el-icon-refresh" @click="reset">éç½®</el-button> |
| | | </section> |
| | | </el-form> |
| | | <template v-slot:table-wrap> |
| | | <ul class="toolbar"> |
| | | <li> |
| | | <el-button @click="exportExcel" :loading="isWorking.export" v-permissions="['business:ywcustomerrechargerecord:exportExcel']">导åº</el-button> |
| | | </li> |
| | | </ul> |
| | | <el-table v-loading="isWorking.search" :data="tableData.list" stripe> |
| | | <el-table-column prop="customerName" label="客æ·åç§°" min-width="130" align="center" show-overflow-tooltip/> |
| | | <el-table-column label="ä¸å¡ç±»å" min-width="90" align="center"> |
| | | <template slot-scope="{ row }">{{ row.type === 1 ? '空è°' : 'çµè¡¨' }}</template> |
| | | </el-table-column> |
| | | <el-table-column prop="deviceInfo" label="设å¤ä¿¡æ¯" min-width="180" align="center" show-overflow-tooltip/> |
| | | <el-table-column prop="money" label="å
å¼éé¢(å
)" min-width="110" align="center"/> |
| | | <el-table-column prop="banlance" label="å
å¼åä½é¢" min-width="110" align="center"/> |
| | | <el-table-column prop="balanceAfter" label="å
å¼åä½é¢" min-width="110" align="center"/> |
| | | <el-table-column label="ç¶æ" min-width="100" align="center"> |
| | | <template slot-scope="{ row }"> |
| | | <span v-if="row.status === 0" class="orange">å
å¼ä¸</span> |
| | | <span v-else-if="row.status === 1" class="green">å
弿å</span> |
| | | <span v-else-if="row.status === 2" class="red">å
å¼å¤±è´¥</span> |
| | | <span v-else>-</span> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="oprId" label="ä»»å¡ID" min-width="180" align="center" show-overflow-tooltip/> |
| | | <el-table-column prop="remark" label="夿³¨" min-width="120" align="center" show-overflow-tooltip/> |
| | | <el-table-column prop="statusInfo" label="ç¶æè¯´æ" min-width="140" align="center" show-overflow-tooltip/> |
| | | <el-table-column prop="createDate" label="æäº¤æ¶é´" min-width="160" align="center"/> |
| | | <el-table-column prop="statusTime" label="ç¶ææ´æ°æ¶é´" min-width="160" align="center"/> |
| | | <el-table-column label="æä½" min-width="160" align="center" fixed="right"> |
| | | <template slot-scope="{ row }"> |
| | | <el-button v-if="row.status === 2" type="text" v-permissions="['business:ywcustomerrechargerecord:retry']" @click="handleRetry(row)">忬¡æäº¤</el-button> |
| | | <el-button v-if="row.status === 0" type="text" v-permissions="['business:ywcustomerrechargerecord:syncStatus']" @click="handleSync(row)">æå¨åæ¥</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | <pagination @size-change="handleSizeChange" @current-change="handlePageChange" :pagination="tableData.pagination"/> |
| | | </template> |
| | | </TableLayout> |
| | | </template> |
| | | |
| | | <script> |
| | | import BaseTable from '@/components/base/BaseTable' |
| | | import TableLayout from '@/layouts/TableLayout' |
| | | import Pagination from '@/components/common/Pagination' |
| | | import * as api from '@/api/business/ywcustomerrecharge' |
| | | |
| | | export default { |
| | | name: 'YwCustomerRechargeRecord', |
| | | extends: BaseTable, |
| | | components: { TableLayout, Pagination }, |
| | | data () { |
| | | return { |
| | | searchForm: { |
| | | customerName: '', |
| | | type: null, |
| | | status: null, |
| | | dateRange: null |
| | | } |
| | | } |
| | | }, |
| | | created () { |
| | | this.search() |
| | | }, |
| | | methods: { |
| | | handlePageChange (pageIndex) { |
| | | this.tableData.pagination.pageIndex = pageIndex || this.tableData.pagination.pageIndex |
| | | this.loadList() |
| | | }, |
| | | loadList () { |
| | | this.isWorking.search = true |
| | | api.rechargeRecordPage({ |
| | | page: this.tableData.pagination.pageIndex, |
| | | 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 }) |
| | | }, |
| | | search () { |
| | | this.tableData.pagination.pageIndex = 1 |
| | | this.loadList() |
| | | }, |
| | | buildSearchModel () { |
| | | const model = {} |
| | | if (this.searchForm.customerName) model.customerName = this.searchForm.customerName |
| | | if (this.searchForm.type !== '' && this.searchForm.type !== null) model.type = this.searchForm.type |
| | | if (this.searchForm.status !== '' && this.searchForm.status !== null) model.status = this.searchForm.status |
| | | if (this.searchForm.dateRange && this.searchForm.dateRange.length === 2) { |
| | | model.createTimeBegin = this.searchForm.dateRange[0] |
| | | model.createTimeEnd = this.searchForm.dateRange[1] |
| | | } |
| | | return model |
| | | }, |
| | | reset () { |
| | | this.searchForm = { customerName: '', type: null, status: null, dateRange: null } |
| | | this.search() |
| | | }, |
| | | exportExcel () { |
| | | this.$dialog.exportConfirm('确认导åºåï¼') |
| | | .then(() => { |
| | | this.isWorking.export = true |
| | | api.exportRechargeRecord({ page: 1, capacity: 1000000, model: this.buildSearchModel() }) |
| | | .then(response => { this.download(response) }) |
| | | .catch(e => this.$tip.apiFailed(e)) |
| | | .finally(() => { this.isWorking.export = false }) |
| | | }) |
| | | .catch(() => {}) |
| | | }, |
| | | handleRetry (row) { |
| | | this.$dialog.actionConfirm('ç¡®è®¤åæ¬¡æäº¤è¯¥å
å¼åï¼', 'æä½ç¡®è®¤') |
| | | .then(() => api.retryRecharge(row.id)) |
| | | .then(msg => { |
| | | this.$tip.success(msg || 'å·²æäº¤') |
| | | this.loadList() |
| | | }) |
| | | .catch(e => { if (e !== 'cancel') this.$tip.apiFailed(e) }) |
| | | }, |
| | | handleSync (row) { |
| | | api.syncRechargeStatus(row.id) |
| | | .then(msg => { |
| | | this.$tip.success(msg || '忥宿') |
| | | this.loadList() |
| | | }) |
| | | .catch(e => this.$tip.apiFailed(e)) |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .green { color: #67c23a; } |
| | | .red { color: #f56c6c; } |
| | | .orange { color: #e6a23c; } |
| | | </style> |