zuypeng 1 rok temu
rodzic
commit
e64c929b93
23 zmienionych plików z 0 dodań i 3965 usunięć
  1. 0 30
      admin-web/src/router/route.ts
  2. 0 107
      admin-web/src/views/admin/basic/index.vue
  3. 0 342
      admin-web/src/views/admin/invoice/dialog.vue
  4. 0 416
      admin-web/src/views/admin/invoice/index.vue
  5. 0 703
      admin-web/src/views/admin/kanban/index.vue
  6. 0 301
      admin-web/src/views/admin/refund/index.vue
  7. 0 245
      admin-web/src/views/admin/station/stat/dialog.vue
  8. 0 270
      admin-web/src/views/admin/station/stat/index.vue
  9. 0 334
      admin-web/src/views/admin/station/statment/dialog.vue
  10. 0 288
      admin-web/src/views/admin/station/statment/index.vue
  11. 0 55
      car-wash-admin/src/main/java/com/kym/admin/controller/ConnectorInfoController.java
  12. 0 69
      car-wash-admin/src/main/java/com/kym/admin/controller/CouponController.java
  13. 0 18
      car-wash-admin/src/main/java/com/kym/admin/controller/EquipmentInfoController.java
  14. 0 18
      car-wash-admin/src/main/java/com/kym/admin/controller/EquipmentRelationController.java
  15. 0 146
      car-wash-admin/src/main/java/com/kym/admin/controller/FinanceController.java
  16. 0 18
      car-wash-admin/src/main/java/com/kym/admin/controller/MonitorLogController.java
  17. 0 61
      car-wash-admin/src/main/java/com/kym/admin/controller/StatementsController.java
  18. 0 18
      car-wash-admin/src/main/java/com/kym/admin/controller/StationNoticeController.java
  19. 0 171
      car-wash-admin/src/main/java/com/kym/admin/jobs/ActivityDelayJob.java
  20. 0 63
      car-wash-admin/src/main/java/com/kym/admin/jobs/InvoiceStatusJob.java
  21. 0 65
      car-wash-admin/src/main/java/com/kym/admin/jobs/OfflineNotifyJob.java
  22. 0 173
      car-wash-admin/src/main/java/com/kym/admin/jobs/StationStatJob.java
  23. 0 54
      car-wash-admin/src/main/java/com/kym/admin/mq/consumer/UserCouponConsumer.java

+ 0 - 30
admin-web/src/router/route.ts

@@ -270,36 +270,6 @@ export const adminRoutes: Array<RouteRecordRaw> = [
                     perm:"recharge.list",
                 },
             },
-            {
-                path: '/refund',
-                name: 'adminRefund',
-                component: () => import('/@/views/admin/refund/index.vue'),
-                meta: {
-                    title: '退款记录',
-                    isLink: '',
-                    isHide: false,
-                    isKeepAlive: true,
-                    isAffix: false,
-                    isIframe: false,
-                    icon: 'ele-Cloudy',
-                    perm:"refund.list",
-                },
-            },
-            {
-                path: '/invoice',
-                name: 'adminInvoice',
-                component: () => import('/@/views/admin/invoice/index.vue'),
-                meta: {
-                    title: '发票管理',
-                    isLink: '',
-                    isHide: false,
-                    isKeepAlive: true,
-                    isAffix: false,
-                    isIframe: false,
-                    icon: 'ele-Tickets',
-                    perm:"invoice.list",
-                },
-            },
             {
                 path: '/org',
                 name: 'adminOrg',

+ 0 - 107
admin-web/src/views/admin/basic/index.vue

@@ -1,107 +0,0 @@
-<template>
-	<div class="fun-tagsview layout-pd">
-		<NoticeBar
-			text="已删除非当前页 tagsView 演示,后续有时间可以再加回来!,tagsview 支持多标签(参数不同)、单标签共用(参数不同)"
-			background="#ecf5ff"
-			color="#409eff"
-		/>
-		<el-card shadow="hover" header="tagsView 当前页演示" class="mt15">
-			<div class="flex-warp">
-				<div class="flex-warp-item">
-					<div class="flex-warp-item-box">
-						<el-button type="primary" size="default" @click="refreshCurrentTagsView">
-							<el-icon>
-								<ele-RefreshRight />
-							</el-icon>
-							刷新当前页
-						</el-button>
-					</div>
-				</div>
-				<div class="flex-warp-item">
-					<div class="flex-warp-item-box">
-						<el-button type="info" size="default" @click="closeCurrentTagsView">
-							<el-icon>
-								<ele-Close />
-							</el-icon>
-							关闭当前页
-						</el-button>
-					</div>
-				</div>
-				<div class="flex-warp-item">
-					<div class="flex-warp-item-box">
-						<el-button type="warning" size="default" @click="closeOtherTagsView">
-							<el-icon>
-								<ele-CircleClose />
-							</el-icon>
-							关闭其它
-						</el-button>
-					</div>
-				</div>
-				<div class="flex-warp-item">
-					<div class="flex-warp-item-box">
-						<el-button type="danger" size="default" @click="closeAllTagsView">
-							<el-icon>
-								<ele-FolderDelete />
-							</el-icon>
-							全部关闭
-						</el-button>
-					</div>
-				</div>
-				<div class="flex-warp-item">
-					<div class="flex-warp-item-box">
-						<el-button type="success" size="default" @click="openCurrenFullscreen">
-							<el-icon>
-								<ele-FullScreen />
-							</el-icon>
-							当前页全屏
-						</el-button>
-					</div>
-				</div>
-			</div>
-		</el-card>
-	</div>
-</template>
-
-<script setup lang="ts" name="funTagsView">
-import { defineAsyncComponent } from 'vue';
-import { useRoute } from 'vue-router';
-import mittBus from '/@/utils/mitt';
-
-// 引入组件
-const NoticeBar = defineAsyncComponent(() => import('/@/components/noticeBar/index.vue'));
-
-// 定义变量内容
-const route = useRoute();
-
-// 0 刷新当前,1 关闭当前,2 关闭其它,3 关闭全部 4 当前页全屏
-// 1、刷新当前 tagsView
-const refreshCurrentTagsView = () => {
-	mittBus.emit('onCurrentContextmenuClick', Object.assign({}, { contextMenuClickId: 0, ...route }));
-};
-// 2、关闭当前 tagsView
-const closeCurrentTagsView = () => {
-	mittBus.emit('onCurrentContextmenuClick', Object.assign({}, { contextMenuClickId: 1, ...route }));
-};
-// 3、关闭其它 tagsView
-const closeOtherTagsView = () => {
-	mittBus.emit('onCurrentContextmenuClick', Object.assign({}, { contextMenuClickId: 2, ...route }));
-};
-// 4、关闭全部 tagsView
-const closeAllTagsView = () => {
-	mittBus.emit('onCurrentContextmenuClick', Object.assign({}, { contextMenuClickId: 3, ...route }));
-};
-// 5、开启当前页面全屏
-const openCurrenFullscreen = () => {
-	mittBus.emit('onCurrentContextmenuClick', Object.assign({}, { contextMenuClickId: 4, ...route }));
-};
-</script>
-
-<style scoped lang="scss">
-.fun-tagsview {
-	.fun-tagsview-from-item {
-		:deep(.el-form-item__content) {
-			margin-left: 0 !important;
-		}
-	}
-}
-</style>

+ 0 - 342
admin-web/src/views/admin/invoice/dialog.vue

@@ -1,342 +0,0 @@
-<style scoped lang="scss">
-
-</style>
-<template>
-  <div class="system-dialog-container">
-    <el-dialog
-        :title="state.dialog.title"
-        v-model="state.dialog.isShowDialog"
-        width="920px"
-        draggable
-        destroy-on-close
-        :close-on-click-modal="false"
-        @close="onClose"
-        align-center>
-      <el-form
-          inline
-          :model="state.ruleForm"
-          :rules="state.rules"
-          ref="formRef"
-          size="default"
-          label-width="125px"
-          class="mt5">
-<!--        <el-form-item label="微信发票申请id" prop="applyId">
-          <el-input
-              v-model.trim="state.ruleForm.applyId"
-              placeholder="微信发票申请号"
-              readonly
-              class="wd200">
-          </el-input>
-        </el-form-item>-->
-        <el-form-item label="开票日期" prop="fapiaoTime">
-          <el-input
-              v-model.trim="state.ruleForm.fapiaoTime"
-              readonly
-              class="wd200">
-          </el-input>
-        </el-form-item>
-        <el-form-item label="发票状态" prop="status">
-          <ext-d-label    class="wd200" type="Invoice.status" :model-value="state.ruleForm.status"> </ext-d-label>
-        </el-form-item>
-        <el-form-item label="开票人" prop="biller">
-          <el-input
-              v-model.trim="state.ruleForm.sellerInformation.name"
-              placeholder="开票人"
-              readonly
-              class="wd200">
-          </el-input>
-        </el-form-item>
-<!--        <el-form-item label="用户id" prop="userId">
-          <el-input
-              v-model.trim="state.ruleForm.userId"
-              placeholder="用户id"
-              readonly
-              class="wd200">
-          </el-input>
-        </el-form-item>-->
-        <el-form-item label="累积充电量(度)" prop="totalPower">
-          <el-input
-              v-model.trim="state.detail.totalPower"
-              placeholder="累积充电量(度)"
-              readonly
-              class="wd200">
-          </el-input>
-        </el-form-item>
-        <el-form-item label="累积总金额(元)" prop="totalMoney">
-          <el-input
-              :model-value="u.fmt.fmtMoney(state.ruleForm.totalMoney)"
-              placeholder="累积总金额(元)"
-              readonly
-              class="wd200">
-          </el-input>
-        </el-form-item>
-        <el-form-item label="累积电费(元)" prop="elecMoney">
-          <el-input
-              :model-value="u.fmt.fmtMoney(state.detail.elecMoney)"
-              placeholder="累积电费(元)"
-              readonly
-              class="wd200">
-          </el-input>
-        </el-form-item>
-        <el-form-item label="累积服务费(元)" prop="serviceMoney">
-          <el-input
-              :model-value="u.fmt.fmtMoney(state.detail.serviceMoney)"
-              placeholder="累积服务费(元)"
-              readonly
-              class="wd200">
-          </el-input>
-        </el-form-item>
-        <el-form-item label="服务费优惠金额(元)" prop="serviceMoneyDiscount">
-          <el-input
-              :model-value="u.fmt.fmtMoney(state.detail.serviceMoneyDiscount)"
-              placeholder="服务费优惠金额(元)"
-              readonly
-              class="wd200">
-          </el-input>
-        </el-form-item>
-
-        <el-card header="开票人" shadow="hover" class="mt20">
-          <el-form-item label="开票企业名称" prop="invoiceTitle">
-            <el-input
-                v-model.trim="state.ruleForm.sellerInformation.name"
-                placeholder="开票企业名称"
-                readonly
-                class="wd200">
-            </el-input>
-          </el-form-item>
-          <el-form-item label="公司税号" prop="taxId">
-            <el-input
-                v-model.trim="state.ruleForm.sellerInformation.taxpayer_id"
-                placeholder="公司税号"
-                readonly
-                class="wd200">
-            </el-input>
-          </el-form-item>
-          <el-form-item label="公司地址" prop="address">
-            <el-input
-                v-model.trim="state.ruleForm.sellerInformation.address"
-                placeholder="公司地址"
-                readonly
-                class="wd200">
-            </el-input>
-          </el-form-item>
-          <el-form-item label="开户银行" prop="bankName">
-            <el-input
-                v-model.trim="state.ruleForm.sellerInformation.bank_name"
-                placeholder="开户银行"
-                readonly
-                class="wd200">
-            </el-input>
-          </el-form-item>
-          <el-form-item label="联系电话" prop="bankAccount">
-            <el-input
-                v-model.trim="state.ruleForm.sellerInformation.telephone"
-                placeholder="联系电话"
-                readonly
-                class="wd200">
-            </el-input>
-          </el-form-item>
-        </el-card>
-
-        <el-card header="发票信息" shadow="hover" class="mt20">
-          <el-form-item label="发票类型" prop="invoiceType">
-            <ext-d-label   class="wd200"  type="Invoice.type" :model-value="state.ruleForm.buyerInformation.type"></ext-d-label>
-          </el-form-item>
-          <el-form-item label="发票抬头名称" prop="invoiceTitle">
-            <el-input
-                v-model.trim="state.ruleForm.buyerInformation.name"
-                placeholder="发票抬头名称"
-                readonly
-                class="wd200">
-            </el-input>
-          </el-form-item>
-          <el-form-item label="公司税号" prop="taxId">
-            <el-input
-                v-model.trim="state.ruleForm.buyerInformation.taxpayer_id"
-                placeholder="公司税号"
-                readonly
-                class="wd200">
-            </el-input>
-          </el-form-item>
-          <el-form-item label="公司地址" prop="address">
-            <el-input
-                v-model.trim="state.ruleForm.buyerInformation.address"
-                placeholder="公司地址"
-                readonly
-                class="wd200">
-            </el-input>
-          </el-form-item>
-          <el-form-item label="开户银行" prop="bankName">
-            <el-input
-                v-model.trim="state.ruleForm.buyerInformation.bank_name"
-                placeholder="开户银行"
-                readonly
-                class="wd200">
-            </el-input>
-          </el-form-item>
-          <el-form-item label="银行账户" prop="bankAccount">
-            <el-input
-                v-model.trim="state.ruleForm.buyerInformation.bank_account"
-                placeholder="银行账户"
-                readonly
-                class="wd200">
-            </el-input>
-          </el-form-item>
-          <el-form-item label="发票金额(单位:分)" prop="invoiceAmount">
-            <el-input
-                :model-value="u.fmt.fmtMoney(state.ruleForm.totalAmount)"
-                placeholder="发票金额(单位:分)"
-                readonly
-                class="wd200">
-            </el-input>
-          </el-form-item>
-          <el-form-item label="税额" prop="taxInfo">
-            <el-input
-                :model-value="u.fmt.fmtMoney(state.ruleForm.taxAmount)"
-                placeholder="税额"
-                readonly
-                class="wd200">
-            </el-input>
-          </el-form-item>
-
-          <el-form-item label="接收发票邮箱" prop="email">
-            <el-input
-                v-model.trim="state.ruleForm.email"
-                placeholder="接收发票邮箱"
-                readonly
-                class="wd200">
-            </el-input>
-          </el-form-item>
-          <el-form-item label="电话" prop="phone">
-            <el-input
-                v-model.trim="state.ruleForm.phone"
-                placeholder="电话"
-                readonly
-                class="wd200">
-            </el-input>
-          </el-form-item>
-        </el-card>
-
-
-
-<!--        <el-form-item label="备注" prop="remark">
-          <el-input
-              v-model.trim="state.ruleForm.remark"
-              placeholder="备注"
-              readonly
-              class="wd200">
-          </el-input>
-        </el-form-item>-->
-      </el-form>
-
-      <template #footer>
-        <div class="dialog-footer">
-          <el-button @click="onCancel" size="default">取 消</el-button>
-          <el-button :loading="state.btnLoading" type="primary" @click="onSubmit" size="default">{{ state.dialog.submitTxt }}</el-button>
-        </div>
-      </template>
-    </el-dialog>
-  </div>
-</template>
-
-<script setup lang="ts" name="InvoiceDialog">
-import {defineAsyncComponent, reactive, onMounted, ref} from 'vue';
-import {Msg} from "/@/utils/message";
-import {$body, $get} from "/@/utils/request";
-import u from '/@/utils/u'
-import ExtDLabel from "/@/components/form/ExtDLabel.vue";
-
-
-// 定义子组件向父组件传值/事件
-const emit = defineEmits(['refresh']);
-const formRef = ref();
-//定义初始变量,重置使用
-const initState = () => ({
-  ruleForm: {
-    id: 0,
-    buyerInformation:{},
-    blueFapiao:{},
-    cardInformation:{},
-    extraInformationd:{},
-    sellerInformation:{},
-  },
-  detail:{
-    orderDetails:{}
-  },
-  btnLoading: false,
-  dialog: {
-    isShowDialog: false,
-    type: '',
-    title: '',
-    submitTxt: '',
-  },
-  rules: {},
-})
-
-// 定义变量内容
-const state = reactive(initState());
-
-
-// 打开弹窗
-const open = (action: string = 'add', row: any) => {
-  state.dialog.title = u.dialog.actions[action].title + "『发票』"
-  state.dialog.submitTxt = u.dialog.actions[action].btn
-  state.dialog.isShowDialog = true;
-  state.detail = row;
-  if (action !== 'add') {
-    loadData(row.applyId);
-  } else {
-    state.ruleForm = Object.assign(state.ruleForm, row);
-  }
-};
-// 关闭弹窗
-const onClose = () => {
-  state.dialog.isShowDialog = false;
-  Object.assign(state, initState())
-};
-// 取消
-const onCancel = () => {
-  onClose();
-};
-// 提交
-const onSubmit = () => {
-  formRef.value.validate((valid: boolean) => {
-    if (valid) {
-      state.btnLoading = true;
-      const url = state.ruleForm.id > 0 ? "invoice/modify" : "invoice/add"
-      $body(url, state.ruleForm).then(() => {
-        state.btnLoading = false;
-        Msg.message('操作成功');
-        //console.log('submit!')
-        onClose();
-        emit('refresh');
-      })
-    }
-  }).catch(() => {
-    state.btnLoading = false;
-    Msg.message('请先完整填写表单', 'error');
-  })
-};
-
-const handleFormChange = (formData: any) => {
-  //console.log(formData)
-}
-
-// 初始化表格数据
-const loadData = (applyId: String) => {
-  $get(`finance/listInvoiceDetail`, {applyId}).then((res: any) => {
-    if (res.list && res.list.length > 0) {
-      state.ruleForm = res.list[0];
-      //console.log(state.ruleForm)
-      //console.log(state.detail)
-    }
-  })
-}
-
-// 暴露变量
-defineExpose({
-  open
-});
-
-
-</script>

+ 0 - 416
admin-web/src/views/admin/invoice/index.vue

@@ -1,416 +0,0 @@
- <style scoped lang="scss">
-.system-container {
-
-  :deep(.el-card__body) {
-    display: flex;
-    flex-direction: column;
-    justify-content: space-between;
-    flex: 1;
-    overflow: auto;
-
-    .el-table {
-      flex: 1;
-    }
-
-  }
-}
-
-.page-content {
-  margin-bottom: 20px;
-}
-
-.page-pager {
-  background-color: #fff;
-  height: 24px;
-}
-</style>
-<template>
-  <div class="system-container layout-padding">
-    <el-card shadow="hover" class="layout-padding-auto">
-
-
-      <el-form
-          :model="state.formQuery"
-          ref="queryRef"
-          size="default" label-width="0px" class="mt5 mb5">
-        <el-input
-            v-model="state.formQuery.phone"
-            placeholder="用户手机号"
-            clearable
-            @blur="loadData(true)"
-            class="wd150 mr10">
-        </el-input>
-        <ext-d-select
-            v-model="state.formQuery.status"
-            placeholder="发票状态"
-            type="Invoice.status"
-            clearable
-            @blur="loadData(true)"
-            class="wd150 mr10">
-        </ext-d-select>
-        <ext-d-select
-            v-model="state.formQuery.invoiceType"
-            placeholder="发票类型"
-            type="Invoice.type"
-            clearable
-            @blur="loadData(true)"
-            class="wd150 mr10">
-        </ext-d-select>
-        <el-input
-            v-model="state.formQuery.email"
-            placeholder="接收发票邮箱"
-            clearable
-            @blur="loadData(true)"
-            class="wd150 mr10">
-        </el-input>
-
-        <el-input
-            v-model="state.formQuery.invoiceTitle"
-            placeholder="发票抬头名称"
-            clearable
-            @blur="loadData(true)"
-            class="wd150 mr10">
-        </el-input>
-        <el-input
-            v-model="state.formQuery.taxId"
-            placeholder="公司税号"
-            clearable
-            @blur="loadData(true)"
-            class="wd150 mr10">
-        </el-input>
-        <el-input
-            v-model="state.formQuery.biller"
-            placeholder="开票人"
-            clearable
-            @blur="loadData(true)"
-            class="wd150 mr10">
-        </el-input>
-
-
-        <el-button class="ml10" plain size="default" type="success" @click="loadData(true)">
-          <SvgIcon name="ele-Search"/>
-          查询
-        </el-button>
-
-        <el-button class="ml10" plain size="default" type="warning" @click="handleDownloadExcel">
-          <SvgIcon name="ele-Download"/>
-          下载
-        </el-button>
-      </el-form>
-
-      <el-table
-          border
-          stripe="stripe"
-          :height="state.tableData.height"
-          highlight-current-row
-          current-row-key="id"
-          row-key="id"
-          :data="state.tableData.data"
-          v-loading="state.tableData.loading"
-          @selection-change="handleTableSelectionChange"
-          @sort-change="handleTableSortChange">
-        <template #empty>
-          <el-empty></el-empty>
-        </template>
-        <el-table-column
-            v-for="field in state.tableData.columns"
-            :key="field.prop"
-            :type="field.type"
-            :label="field.label"
-            :column-key="field.prop"
-            :width="field.width"
-            :min-width="field.minWidth"
-            :fixed="field.fixed"
-            :sortable="field.sortable"
-            :show-overflow-tooltip="!field.fixed&&field.width>150"
-        >
-          <template #default="{row}">
-            <template v-if="field.prop==='expand'">
-              <el-row class="pd10">
-                <el-col :span="12">
-                  <h4 class="pd5">关联订单明细</h4>
-                  <el-table :data="row.orderDetails" width="400" border>
-                    <el-table-column label="充电订单" prop="startChargeSeq"/>
-                    <el-table-column label="订单总金额" prop="totalMoney">
-                      <template #default="{row}">{{ u.fmt.fmtMoney(row.totalMoney) }}</template>
-                    </el-table-column>
-                    <el-table-column label="总电量/度" prop="totalPower"/>
-                    <el-table-column label="电费" prop="elecMoney">
-                      <template #default="{row}">{{ u.fmt.fmtMoney(row.elecMoney) }}</template>
-                    </el-table-column>
-                    <el-table-column label="服务费" prop="serviceMoney">
-                      <template #default="{row}">{{ u.fmt.fmtMoney(row.serviceMoney) }}</template>
-                    </el-table-column>
-                    <el-table-column label="服务费优惠" prop="serviceMoneyDiscount">
-                      <template #default="{row}">{{ u.fmt.fmtMoney(row.serviceMoneyDiscount) }}</template>
-                    </el-table-column>
-                  </el-table>
-                </el-col>
-              </el-row>
-
-            </template>
-            <template v-else-if="field.prop==='status'">
-              <ext-d-label type="Invoice.status" :model-value="row[field.prop]"></ext-d-label>
-              <!--              <p style="padding-left: 2em;" v-html="row[field.prop]"></p>-->
-            </template>
-            <template v-else-if="field.prop==='invoiceType'">
-              <ext-d-label type="Invoice.type" :model-value="row[field.prop]"></ext-d-label>
-              <!--              <p style="padding-left: 2em;" v-html="row[field.prop]"></p>-->
-            </template>
-            <template v-else-if="field.prop==='totalMoney'">
-              {{ u.fmt.fmtMoney(row[field.prop]) }}
-            </template>
-            <template v-else-if="field.prop==='invoiceAmount'">
-              {{ u.fmt.fmtMoney(row[field.prop]) }}
-            </template>
-            <template v-else-if="field.prop==='elecMoney'">
-              {{ u.fmt.fmtMoney(row[field.prop]) }}
-            </template>
-            <template v-else-if="field.prop==='serviceMoney'">
-              {{ u.fmt.fmtMoney(row[field.prop]) }}
-            </template>
-            <template v-else-if="field.prop==='serviceMoneyDiscount'">
-              {{ u.fmt.fmtMoney(row[field.prop]) }}
-            </template>
-            <template v-else-if="field.prop==='action'">
-              <el-button v-if="row.status===0" v-auth="'invoice.modify'" size="small" plain type="warning" @click="handleInvice(row)">开票</el-button>
-              <el-button v-if="row.status===0" v-auth="'invoice.modify'" size="small" plain type="danger" @click="handleCancelInvoice(row)">取消开票</el-button>
-              <el-button v-if="row.status===1" v-auth="'invoice.modify'" size="small" plain type="success" @click="previewInvoice(row)">下载</el-button>
-              <el-button   size="small" plain type="success" @click="handleInfo(row)">详情</el-button>
-            </template>
-            <template v-else>
-              <div>{{ row[field.prop] }}</div>
-            </template>
-
-          </template>
-        </el-table-column>
-      </el-table>
-
-      <ext-page class="page-pager" v-model:value="state.pageQuery" @change="loadData(false)"/>
-    </el-card>
-  </div>
-  <InvoiceDialog ref="invoiceDialogRef" @refresh="loadData(true)"/>
-
-  <canvas ref="pdfViewer"></canvas>
-</template>
-
-<script setup lang="ts" name="InvoiceList">
-import {defineAsyncComponent, reactive, onMounted, onBeforeMount, ref, getCurrentInstance, nextTick, onBeforeUnmount} from 'vue';
-import {$body, $get, $post} from "/@/utils/request";
-import {Msg} from "/@/utils/message";
-import u from "/@/utils/u"
-
-
-import ExtPage from '/@/components/form/ExtPage.vue'
-
-import mittBus from '/@/utils/mitt';
-import ExtDSelect from "/@/components/form/ExtDSelect.vue";
-import ExtDLabel from "/@/components/form/ExtDLabel.vue";
-
-const InvoiceDialog = defineAsyncComponent(() => import("/@/views/admin/invoice/dialog.vue"));
-
-// import pdfjsLib from 'pdfjs-dist'
-
-//定义引用
-const queryRef = ref();
-const invoiceDialogRef = ref();
-
-const pdfViewer = ref()
-
-//定义变量
-const state = reactive({
-  formQuery: {
-    status:0
-  },
-  pageQuery: {
-    pageNum: 1,
-    pageSize: 10,
-    total: 0
-  },
-  tableData: {
-    height: 500,
-    data: [] as Array<any>,
-    loading: false,
-    columns: [
-      {type: 'expand', prop: 'expand', width: 30, fixed: 'left'},
-      {label: '用户手机号', prop: 'mobilePhone', align: 'center', fixed: 'left', width: 120},
-      {label: '发票ID', prop: 'id', align: 'center', fixed: 'left', width: 110},
-      {label: '发票申请单号', prop: 'applyId', align: 'center', fixed: 'left', width: 130},
-      {label: '发票状态', prop: 'status', align: 'center', fixed: 'left', width: 100},
-      {label: '发票金额', prop: 'invoiceAmount', resizable: true, width: 90},
-      {label: '订单总额', prop: 'totalMoney', resizable: true, width: 90},
-      {label: '总服务费', prop: 'serviceMoney', resizable: true, width: 90},
-      {label: '总服务费', prop: 'elecMoney', resizable: true, width: 90},
-      {label: '服务费优惠', prop: 'serviceMoneyDiscount', resizable: true, width: 105},
-      {label: '公司税号', prop: 'taxId', resizable: true, width: 115},
-      {label: '发票类型', prop: 'invoiceType', resizable: true, width: 90},
-      {label: '发票抬头', prop: 'invoiceTitle', resizable: true, width: 110},
-      {label: '开票人', prop: 'biller', resizable: true, width: 80},
-      {label: '开票时间', prop: 'fapiaoTime', resizable: true, width: 170},
-      {label: '接收发票邮箱', prop: 'email', resizable: true, width: 120},
-      {label: '电话', prop: 'phone', resizable: true, width: 90},
-      /*
-
-            {label: '公司地址', prop: 'address', resizable: true, width: 130},
-            {label: '开户银行', prop: 'bankName', resizable: true, width: 130},
-            {label: '银行账户', prop: 'bankAccount', resizable: true},
-
-            {label: '税额详情信息', prop: 'taxInfo', resizable: true, width: 150},
-
-      */
-
-      {label: '备注', prop: 'remark', resizable: true},
-      {label: '创建时间', prop: 'createTime', sortable: 'custom', resizable: true, width: 170},
-      {label: '更新时间', prop: 'updateTime', sortable: 'custom', resizable: true, width: 170},
-      {
-        label: '操作', prop: 'action', width: 240, align: 'center', fixed: 'right',
-      }
-    ],
-  },
-})
-
-
-// 监听双向绑定 modelValue 的变化
-// watch(
-//         () => state.pageNum,
-//         () => {
-//
-//         }
-// );
-
-//生命周期钩子
-onBeforeMount(() => {
-})
-
-onMounted(() => {
-  loadData();
-
-  nextTick(() => {
-    let bodyHeight = document.body.clientHeight;
-    let queryHeight = queryRef.value.$el.clientHeight;
-    state.tableData.height = bodyHeight - queryHeight - 320
-  })
-
-  mittBus.on("invoice.refresh", () => {
-    loadData();
-  })
-});
-
-onBeforeUnmount(() => {
-  mittBus.off("invoice.refresh")
-})
-
-
-//region 方法区
-// 初始化表格数据
-const loadData = (refresh: boolean = false) => {
-  if (refresh) {
-    state.pageQuery.pageNum = 1;
-  }
-  state.tableData.loading = true;
-  $body(`/finance/listInvoice`, {...state.formQuery, ...state.pageQuery}).then((res: any) => {
-    let {list, total} = res;
-    state.tableData.data = list;
-    state.pageQuery.total = total;
-    state.tableData.loading = false;
-  }).catch(e => {
-    //console.error(e)
-    state.tableData.loading = false;
-  })
-};
-
-const handleInvice = (row: any) => {
-  Msg.confirm("请确认是否开票?").then(()=>{
-    $get(`/finance/handleInvoice/${row.id}`).then((res: any) => {
-      Msg.message("开票成功")
-      loadData(true)
-    }).catch(e => {
-      //console.error(e)
-    })
-  })
-
-}
-
-const handleDownloadExcel = () => {
-  let url = import.meta.env.VITE_API_URL;
-  if (!url) {
-    url = `${location.origin}/admin/`;
-  }
-  // $get(`/finance/export/invoiceList`,{...state.formQuery, ...state.pageQuery})
-  let params =   Object.keys(state.formQuery).map(key=>`${key}=${state.formQuery[key]}`).join("&")
-
-  window.open(`${url}/finance/export/invoiceList?t=${new Date().getTime()}&${params}`, "_blank")
-}
-
-const handleInfo = (row:any) => {
-  invoiceDialogRef.value.open('view', row);
-}
-
-
-const previewInvoice =   (row: any) => {
-  $get(`/finance/downloadInvoice/${row.id}`).then((res: any) => {
-    //console.log(res)
-    let {downloadUrl} = res;
-    if (downloadUrl) {
-      window.open(downloadUrl, "_blank")
-
-      // doPriview(downloadUrl)
-
-    }
-  }).catch(e => {
-    //console.error(e)
-  })
-}
-/*
-const doPriview=async  (url:string) =>{
-  const canvas = pdfViewer.value;
-  const loadingTask = pdfjsLib.getDocument(url)
-  const pdf = await loadingTask.promise
-  const page = await pdf.getPage(1)
-  const viewport = page.getViewport({ scale: 1.0 })
-  const context = canvas.getContext('2d')
-  canvas.height = viewport.height
-  canvas.width = viewport.width
-  const renderTask = page.render({
-    canvasContext: context,
-    viewport: viewport
-  })
-  await renderTask.promise
-}*/
-
-// 打开修改用户弹窗
-const onRowClick = (type: string, row: any) => {
-  invoiceDialogRef.value.open(type, row);
-};
-
-const handleTableSelectionChange = (selection: any) => {
-  //console.log("handleTableSelectionChange>>", selection)
-  // emit("on-check-change", selection)
-}
-
-const handleTableSortChange = (column, prop, order) => {
-  //console.log("handleTableSortChange>>", column, prop, order)
-  // emit("on-sort-change", column)
-}
-
-const handleCancelInvoice = (row:any) => {
-  Msg.confirm("请确认是否取消开票?").then(()=>{
-    $get(`/finance/cancelApplyInvoice/${row.id}`).then((res: any) => {
-      Msg.message("取消成功")
-      loadData(true)
-    }).catch(e => {
-      //console.error(e)
-    })
-  })
-
-}
-
-
-//endregion
-
-
-// 暴露变量
-// defineExpose({
-//     loadData,
-// });
-</script>

+ 0 - 703
admin-web/src/views/admin/kanban/index.vue

@@ -1,703 +0,0 @@
-<style scoped lang="scss">
-.system-container {
-
-  :deep(.el-card__body) {
-    display: flex;
-    flex-direction: column;
-    justify-content: space-between;
-    flex: 1;
-    overflow: auto;
-
-    .el-table {
-      flex: 1;
-    }
-
-  }
-}
-
-.page-content {
-  margin-bottom: 20px;
-}
-
-.page-pager {
-  background-color: #fff;
-  height: 24px;
-}
-</style>
-<template>
-  <div class="system-container1 layout-padding">
-
-    <el-form
-        inline
-        :model="state.formQuery"
-        ref="queryRef"
-        size="default" label-width="0px" class="mt5 mb5">
-      <el-form-item>
-        <ext-select
-            v-model="state.formQuery.stationIdList"
-            placeholder="站点"
-            value-key="stationId"
-            label-key="stationName"
-            clearable
-            multiple
-            @on-change="loadData"
-            :data-list="state.stationList"
-            style="min-width: 150px;"
-            class=" mr10">
-        </ext-select>
-      </el-form-item>
-
-      <el-form-item>
-        <el-radio-group v-model="state.formQuery.type" size="default" @change="handleQueryTypeChange">
-          <el-radio-button label="day">天</el-radio-button>
-          <el-radio-button label="month">月</el-radio-button>
-        </el-radio-group>
-        <el-date-picker
-            :value-format="state.dateFormat"
-            v-model="state.formQuery.dateRange"
-            :type="state.dateType"
-            @change="loadData"
-            unlink-panels
-            range-separator="至"
-            start-placeholder="开始时间"
-            end-placeholder="结束时间"
-            :shortcuts="shortcuts"
-        />
-      </el-form-item>
-
-      <el-form-item>
-        <el-button class="ml10" plain size="default" type="success" @click="loadData()">
-          <SvgIcon name="ele-Search"/>
-          查询
-        </el-button>
-      </el-form-item>
-    </el-form>
-
-    <el-scrollbar>
-      <el-card>
-        <el-card shadow="hover" class="layout-padding-auto">
-          <template #header>充电用户及有效订单数</template>
-          <template #default>
-            <div style="min-height: 500px;padding: 20px;" ref="chartOneRef"></div>
-          </template>
-        </el-card>
-
-        <el-card shadow="hover" class="layout-padding-auto mt10">
-          <template #header>电费/服务费</template>
-          <template #default>
-            <div style="min-height: 500px;padding: 20px;" ref="chartTwoRef"></div>
-          </template>
-        </el-card>
-
-        <el-card shadow="hover" class="layout-padding-auto mt10">
-          <template #header>电量/平均电量</template>
-          <template #default>
-            <div style="min-height: 500px;padding: 20px;" ref="chartThreeRef"></div>
-          </template>
-        </el-card>
-
-
-      </el-card>
-
-    </el-scrollbar>
-  </div>
-</template>
-
-<script setup lang="ts" name="KanbanList">
-import {defineAsyncComponent, reactive, onMounted, onBeforeMount, ref, getCurrentInstance, nextTick, onUnmounted, markRaw} from 'vue';
-import {$body, $get} from "/@/utils/request";
-import {Msg} from "/@/utils/message";
-import * as echarts from 'echarts';
-
-import mittBus from '/@/utils/mitt';
-import ExtSelect from "/@/components/form/ExtSelect.vue";
-import u from "/@/utils/u";
-
-//定义引用
-const queryRef = ref();
-const chartOneRef = ref();
-const chartTwoRef = ref();
-const chartThreeRef = ref();
-
-const end = new Date()
-const start = new Date()
-start.setTime(start.getTime() - 3600 * 1000 * 24 * 30)
-
-
-//定义变量
-const state = reactive({
-  formQuery: {
-    stationIdList: [],
-    dateRange: [u.date.format(start, "YYYY-MM-DD"), u.date.format(end, "YYYY-MM-DD")],
-    type: 'day'
-  },
-  stationList: [],
-  chartOne: null as any,
-  chartTwo: null as any,
-  chartThree: null as any,
-  chartData: {},
-  theme: '',
-  dateType: 'daterange',
-  dateFormat: 'YYYY-MM-DD'
-})
-
-
-const shortcuts = [
-  {
-    text: '近7天',
-    value: () => {
-      const end = new Date()
-      const start = new Date()
-      start.setTime(start.getTime() - 3600 * 1000 * 24 * 7)
-      return [start, end]
-    },
-  },
-  {
-    text: '近30天',
-    value: () => {
-      const end = new Date()
-      const start = new Date()
-      start.setTime(start.getTime() - 3600 * 1000 * 24 * 30)
-      return [start, end]
-    },
-  },
-  {
-    text: '近90天',
-    value: () => {
-      const end = new Date()
-      const start = new Date()
-      start.setTime(start.getTime() - 3600 * 1000 * 24 * 90)
-      return [start, end]
-    },
-  },
-]
-
-
-// 监听双向绑定 modelValue 的变化
-// watch(
-//         () => state.pageNum,
-//         () => {
-//
-//         }
-// );
-
-//生命周期钩子
-onBeforeMount(() => {
-  loadStationList()
-})
-
-onMounted(() => {
-  loadData();
-});
-
-onUnmounted(() => {
-  state.chartOne?.dispose();
-  state.chartTwo?.dispose();
-  state.chartThree?.dispose();
-})
-
-window.onresize = function () {
-  //自适应大小
-  state.chartOne.resize();
-  state.chartTwo.resize();
-  state.chartThree.resize();
-};
-
-//region 方法区
-
-const handleQueryTypeChange = (type: string) => {
-  //console.log(type)
-  if (type === 'day') {
-    state.dateType = 'daterange'
-    state.dateFormat = 'YYYY-MM-DD'
-  } else {
-    state.dateType = 'monthrange'
-    state.dateFormat = 'YYYY-MM-DD'
-  }
-}
-
-const loadStationList = () => {
-  $get(`/station/listStation`, {pageNum: 1024}).then((res: any) => {
-    state.stationList = res;
-    state.formQuery.stationIdList = res.map(k=>k.stationId);
-    //console.log(res)
-    setTimeout(()=>{
-      loadData();
-    },200)
-  }).catch(e => {
-    //console.error(e)
-  })
-}
-
-// 初始化表格数据
-const loadData = () => {
-  //console.log(state.formQuery)
-  let params = {
-    stationIds: state.formQuery.stationIdList,
-    startTime: state.formQuery.dateRange[0],
-    endTime: state.formQuery.dateRange[1],
-    type: state.formQuery.type
-  }
-  for (let i = 0; i < Object.keys(params).length; i++) {
-    if (u.isEmptyOrNull(params[Object.keys(params)[i]])) {
-      return;
-    }
-  }
-  $get(`/stat/stationStatDetail`, params).then(res => {
-    //console.log(res)
-    state.chartData = res;
-    buildOrderChart()
-    buildMoneyChart()
-    buildElectricChart()
-  })
-};
-
-/**
- * 充电人数、有限订单数散点图
- */
-const buildOrderChart = () => {
-
-  if (state.chartOne) {
-    state.chartOne.dispose();
-  }
-  state.chartOne = markRaw(echarts.init(chartOneRef.value, state.theme));
-  let {type} = state.formQuery
-  let stationIdList = Object.keys(state.chartData);
-  if (u.isEmptyOrNull(stationIdList)) {
-    Msg.message('未查询到统计数据', 'error')
-    return;
-  }
-  let xAxis = state.chartData[`${stationIdList[0]}`].map((k: any) => type==='day'?k.statDay:k.statMonth);
-  let legends:Array<string> =[];
-  state.stationList.filter((k: any) => stationIdList.includes(k.stationId)).forEach(item=>{
-    legends.push(item.stationName)
-    // legends.push(item.stationName+'-平均订单电量')
-    // legends.push(item.stationName+'-平均充电电量')
-  })
-
-  const itemStyle = {
-    opacity: 0.8,
-    shadowBlur: 10,
-    shadowOffsetX: 0,
-    shadowOffsetY: 0,
-    shadowColor: 'rgba(0,0,0,0.3)'
-  };
-
-
-  let y1Max = 0,y2Max=0;
-  let series: Array<any> = [];
-  stationIdList.forEach((stationId: string) => {
-    let tmpUserMax = Math.max(...state.chartData[`${stationId}`].map((k: any) => k.chargeUsers))
-    y1Max = Math.max(y1Max, tmpUserMax)
-
-    let tmpOrderMax = Math.max(...state.chartData[`${stationId}`].map((k: any) => k.validOrders))
-    y2Max = Math.max(y2Max, tmpOrderMax)
-
-    let station = state.stationList.find((k: any) => k.stationId == stationId);
-    let {stationName} = station;
-
-    series.push({
-      name: stationName,
-      type: 'scatter',
-      itemStyle:itemStyle,
-      data: state.chartData[stationId].map((k: any) =>  {
-        return [type==='day'?k.statDay:k.statMonth,k.chargeUsers,k.validOrders]
-      })
-    })
-  });
-
-
-
-
-  const schema = [
-    { name: 'date', index: 0, text: '日' },
-    { name: '充电人次', index: 1, text: '充电人次' },
-    { name: '有效订单', index: 2, text: '有效订单' },
-  ];
-
-  let option = {
-    color: ['#dd4444', '#fec42c', '#80F1BE','#353EE9'],
-    legend: {
-      top: 10,
-      data: legends,
-      textStyle: {
-        fontSize: 16
-      }
-    },
-    grid: {
-      left: '10%',
-      right: 150,
-      top: '18%',
-      bottom: '10%'
-    },
-    tooltip: {
-      backgroundColor: 'rgba(255,255,255,0.7)',
-      formatter: function (param) {
-        var value = param.value;
-        // prettier-ignore
-        return '<div style="border-bottom: 1px solid rgba(255,255,255,.3); font-size: 18px;padding-bottom: 7px;margin-bottom: 7px">'
-            + value[0] + '</br> ' +  param.seriesName + ''
-            + '</div>'
-            + schema[1].text + ':' + value[1] + '人<br>'
-            + schema[2].text + ':' + value[2] + '笔<br>'
-      }
-    },
-    xAxis: {
-      type: 'category',
-      data: xAxis,
-    },
-    yAxis: {
-      type: 'value',
-      name: '数量',
-      nameLocation: 'end',
-      nameGap: 20,
-      nameTextStyle: {
-        fontSize: 16
-      },
-    },
-    visualMap: [
-      {
-        left: 'right',
-        top: '10%',
-        dimension: 1,
-        min: 0,
-        max: y1Max,
-        itemWidth: 30,
-        itemHeight: 120,
-        calculable: true,
-        precision: 0.1,
-        text: ['圆形大小:充电人次'],
-        textGap: 30,
-        inRange: {
-          symbolSize: [10, 70]
-        },
-        outOfRange: {
-          symbolSize: [10, 70],
-          color: ['rgba(255,255,255,0.4)']
-        },
-        controller: {
-          inRange: {
-            color: ['#c23531']
-          },
-          outOfRange: {
-            color: ['#999']
-          }
-        }
-      },
-      {
-        left: 'right',
-        bottom: '5%',
-        dimension: 2,
-        min: 0,
-        max: y2Max,
-        itemHeight: 120,
-        text: ['明暗:有效订单数'],
-        textGap: 30,
-        inRange: {
-          colorLightness: [0.9, 0.5]
-        },
-        outOfRange: {
-          color: ['rgba(255,255,255,0.4)']
-        },
-        controller: {
-          inRange: {
-            color: ['#c23531']
-          },
-          outOfRange: {
-            color: ['#999']
-          }
-        }
-      }
-    ],
-    series: series
-  };
-
-  //console.log(option)
-  state.chartOne.setOption(option)
-}
-
-
-/**
- * 充电量,柱状、折线图
- */
-const buildElectricChart = () => {
-
-  if (state.chartThree) {
-    state.chartThree.dispose();
-  }
-  state.chartThree = markRaw(echarts.init(chartThreeRef.value, state.theme));
-  let {type} = state.formQuery
-  let stationIdList = Object.keys(state.chartData);
-  if (u.isEmptyOrNull(stationIdList)) {
-    Msg.message('未查询到统计数据', 'error')
-    return;
-  }
-  let xAxis = state.chartData[`${stationIdList[0]}`].map((k: any) => type==='day'?k.statDay:k.statMonth);
-  let legends:Array<string> =[];
-  state.stationList.filter((k: any) => stationIdList.includes(k.stationId)).forEach(item=>{
-    legends.push(item.stationName+'-总电量')
-    legends.push(item.stationName+'-平均充电电量')
-    legends.push(item.stationName+'-平均订单电量')
-  })
-
-  let y1Max = 0, y2Max = 0;
-  let series: Array<any> = [];
-  stationIdList.forEach((stationId: string) => {
-    let tmpUserMax = Math.max(...state.chartData[`${stationId}`].map((k: any) => k.totalPower))
-    y1Max = Math.max(y1Max, tmpUserMax)
-
-    let tmpOrderMax = Math.max(...state.chartData[`${stationId}`].map((k: any) => k.avgOrderElec))
-    y2Max = Math.max(y2Max, tmpOrderMax)
-
-    let station = state.stationList.find((k: any) => k.stationId == stationId);
-    let {stationName} = station;
-    series.push({
-      name: stationName+'-总电量',
-      type: 'bar',
-      barMaxWidth:20,
-      symbolSize: 6,
-      symbol: 'circle',
-      smooth: true,
-      itemStyle: { barBorderRadius: 5},
-      // tooltip: {
-      //   trigger:'axis',
-      //   formatter: ' {a0}  {b}<br />{a} :  {c}人 '
-      // },
-      data: state.chartData[stationId].map((k: any) => k.totalPower)
-    })
-
-
-    series.push({
-      name: stationName+'-平均充电电量',
-      type: 'line',
-      smooth: true,
-      yAxisIndex: 1,
-      data: state.chartData[stationId].map((k: any) => k.avgConnectorElec)
-    })
-
-
-    series.push({
-      name: stationName+'-平均订单电量',
-      type: 'line',
-      smooth: true,
-      yAxisIndex: 1,
-      data: state.chartData[stationId].map((k: any) => k.avgOrderElec)
-    })
-
-
-  });
-
-
-
-  y1Max = Math.max(y1Max, 80)
-  y2Max  =Math.ceil(y2Max +10)
-
-  let y1Interval = Math.ceil(y1Max / 5)
-  let y2Interval =  Math.ceil(y2Max / 5)
-
-
-  let option = {
-    tooltip: {
-      show:true,
-      trigger: 'axis',
-      axisPointer: {
-        type: 'cross',
-        crossStyle: {
-          color: '#999'
-        }
-      }
-    },
-    toolbox: {
-      feature: {
-        // dataView: {show: true, readOnly: false},
-        // magicType: {show: true, type: ['line', 'bar']},
-        // restore: {show: true},
-        // saveAsImage: {show: true}
-      }
-    },
-    legend: {
-      data: legends
-    },
-    xAxis: [
-      {
-        type: 'category',
-        data: xAxis,
-        axisPointer: {
-          type: 'shadow'
-        }
-      }
-    ],
-    yAxis: [
-      {
-        type: 'value',
-        name: '电量',
-        min: 0,
-        max: y1Max,
-        interval: y1Interval,
-        axisLabel: {
-          formatter: '{value} 度'
-        }
-      },
-      {
-        type: 'value',
-        name: '平均电量',
-        min: 0,
-        max: y2Max,
-        interval: y2Interval,
-        axisLabel: {
-          formatter: '{value} 度'
-        }
-      }
-    ],
-    series: series
-  };
-  // //console.log(option)
-  state.chartThree.setOption(option)
-
-
-
-}
-
-
-/**
- * 充电金额  电费+服务费=总费用
- */
-const buildMoneyChart = () => {
-  if (state.chartTwo) {
-    state.chartTwo.dispose();
-  }
-  state.chartTwo = markRaw(echarts.init(chartTwoRef.value, state.theme));
-  let {type} = state.formQuery
-  let stationIdList = Object.keys(state.chartData);
-  if (u.isEmptyOrNull(stationIdList)) {
-    Msg.message('未查询到统计数据', 'error')
-    return;
-  }
-  let xAxis = state.chartData[`${stationIdList[0]}`].map((k: any) => type==='day'?k.statDay:k.statMonth);
-  let legends:Array<string> =[];
-  state.stationList.filter((k: any) => stationIdList.includes(k.stationId)).forEach(item=>{
-    legends.push(item.stationName+'-总费用')
-    legends.push(item.stationName+'-电费')
-    legends.push(item.stationName+'-服务费')
-  })
-
-  let y1Max = 0;
-  let series: Array<any> = [];
-  stationIdList.forEach((stationId: string) => {
-    let tmpUserMax = Math.max(...state.chartData[`${stationId}`].map((k: any) => Math.ceil((k.totalMoney/100))))
-    y1Max = Math.max(y1Max, tmpUserMax)
-
-    let station = state.stationList.find((k: any) => k.stationId == stationId);
-    let {stationName} = station;
-
-    series.push({
-      name: stationName+'-总费用',
-      type: 'bar',
-      barMaxWidth:20,
-      symbolSize: 10,
-      symbol: 'circle',
-      smooth: true,
-      itemStyle: { barBorderRadius: 5},
-      emphasis: {
-        focus: 'series'
-      },
-      tooltip: {
-        formatter: ' {a0}  {b}<br />{a} :  {c}元 '
-      },
-      markPoint: {
-        data: [
-          { type: 'max', name: 'Max' },
-          { type: 'min', name: 'Min' }
-        ]
-      },
-      markLine: {
-        data: [{ type: 'average', name: 'Avg' }]
-      },
-      data: state.chartData[stationId].map((k: any) => (k.totalMoney/100).toFixed(2))
-    })
-
-
-    series.push({
-      name: stationName+'-电费',
-      type: 'bar',
-      barMaxWidth:20,
-      smooth: true,
-      stack: 'Fee'+stationId,
-      markPoint: {
-        data: [
-          { type: 'max', name: 'Max' },
-          { type: 'min', name: 'Min' }
-        ]
-      },
-      data: state.chartData[stationId].map((k: any) =>  (k.elecMoney/100).toFixed(2))
-    })
-
-
-    series.push({
-      name: stationName+'-服务费',
-      type: 'bar',
-      barMaxWidth:20,
-      smooth: true,
-      stack:'Fee'+stationId,
-      markPoint: {
-        data: [
-          { type: 'max', name: 'Max' },
-          { type: 'min', name: 'Min' }
-        ]
-      },
-      data: state.chartData[stationId].map((k: any) => (k.serviceMoney/100).toFixed(2))
-    })
-
-  });
-
-  y1Max = Math.max(y1Max, 1000)+100
-
-  let y1Interval = Math.ceil(y1Max / 5)
-
-
-  let option = {
-    tooltip: {
-      show:true,
-      trigger: 'axis',
-      axisPointer: {
-        type: 'cross',
-        crossStyle: {
-          color: '#999'
-        }
-      }
-    },
-    legend: {
-      data: legends,
-      top:-5
-    },
-    xAxis: [
-      {
-        type: 'category',
-        data: xAxis,
-        axisPointer: {
-          type: 'shadow'
-        }
-      }
-    ],
-    yAxis: [
-      {
-        type: 'value',
-        name: '金额(元)',
-        min: 0,
-        max: y1Max,
-        interval: y1Interval,
-        axisLabel: {
-          formatter: '{value} '
-        }
-      },
-    ],
-    series: series
-  };
-  // //console.log(option)
-  state.chartTwo.setOption(option)
-
-}
-
-//endregion
-
-</script>

+ 0 - 301
admin-web/src/views/admin/refund/index.vue

@@ -1,301 +0,0 @@
-<style scoped lang="scss">
-.system-container {
-
-  :deep(.el-card__body) {
-    display: flex;
-    flex-direction: column;
-    justify-content: space-between;
-    flex: 1;
-    overflow: auto;
-
-    .el-table {
-      flex: 1;
-    }
-
-  }
-}
-
-.page-content {
-  margin-bottom: 20px;
-}
-
-.page-pager {
-  background-color: #fff;
-  height: 24px;
-}
-</style>
-<template>
-  <div class="system-container layout-padding">
-    <el-card shadow="hover" class="layout-padding-auto">
-
-
-      <el-form
-          :model="state.formQuery"
-          ref="queryRef"
-          size="default" label-width="0px" class="mt5 mb5">
-        <ext-d-select
-            v-model="state.formQuery.status"
-            placeholder="退款状态"
-            clearable
-            type="Refund.status"
-            @on-change="loadData(true)"
-            class="wd150 mr10">
-        </ext-d-select>
-<!--       <ext-d-select
-            v-model="state.formQuery.fundsAccount"
-            placeholder="资金账户"
-            clearable
-            type="Refund.account"
-            @on-change="loadData(true)"
-            class="wd150 mr10">
-        </ext-d-select>-->
-        <el-input
-            v-model="state.formQuery.mobilePhone"
-            placeholder="手机号"
-            clearable
-            @blur="loadData(true)"
-            class="wd150 mr10">
-        </el-input>
-<!--        <el-input
-            v-model="state.formQuery.outRefundNo"
-            placeholder="商户退款单号"
-            clearable
-            @blur="loadData(true)"
-            class="wd150 mr10">
-        </el-input>-->
-        <el-input
-            v-model="state.formQuery.outTradeNo"
-            placeholder="商户订单号"
-            clearable
-            @blur="loadData(true)"
-            class="wd150 mr10">
-        </el-input>
-<!--        <el-input
-            v-model="state.formQuery.refundId"
-            placeholder="微信支付退款单号"
-            clearable
-            @blur="loadData(true)"
-            class="wd150 mr10">
-        </el-input>-->
-        <el-input
-            v-model="state.formQuery.transactionId"
-            placeholder="微信支付订单号"
-            clearable
-            @blur="loadData(true)"
-            class="wd150 mr10">
-        </el-input>
-
-        <el-button class="ml10" plain size="default" type="success" @click="loadData(true)">
-          <SvgIcon name="ele-Search"/>
-          查询
-        </el-button>
-      </el-form>
-
-      <el-table
-          border
-          stripe="stripe"
-          :height="state.tableData.height"
-          highlight-current-row
-          current-row-key="id"
-          row-key="id"
-          :data="state.tableData.data"
-          v-loading="state.tableData.loading"
-          @selection-change="handleTableSelectionChange"
-          @sort-change="handleTableSortChange">
-        <template #empty>
-          <el-empty></el-empty>
-        </template>
-        <el-table-column
-            v-for="field in state.tableData.columns"
-            :key="field.prop"
-            :label="field.label"
-            :column-key="field.prop"
-            :width="field.width"
-            :min-width="field.minWidth"
-            :fixed="field.fixed"
-            :sortable="field.sortable"
-            :show-overflow-tooltip="!field.fixed&&field.width>150"
-        >
-          <template #default="{row}">
-            <template v-if="field.prop==='expand'">
-              <p style="padding-left: 2em;" v-html="row[field.prop]"></p>
-            </template>
-            <template v-else-if="'total'===field.prop">
-              {{u.fmt.fmtMoney(row[field.prop])}}
-            </template>
-            <template v-else-if="'refund'===field.prop">
-              {{u.fmt.fmtMoney(row[field.prop])}}
-            </template>
-            <template v-else-if="'discountAmount'===field.prop">
-              {{u.fmt.fmtMoney(row[field.prop])}}
-            </template>
-            <template v-else-if="'status'===field.prop">
-              <ext-d-label type="Refund.status" v-model="row[field.prop]"/>
-            </template>
-            <template v-else-if="'action'===field.prop">
-              <el-button v-if="row.status==='NEW'"  size="small" plain  type="warning" @click="onRefundClick(row)">退款</el-button>
-            </template>
-            <template v-else>
-              <div>{{ row[field.prop] }}</div>
-            </template>
-          </template>
-        </el-table-column>
-      </el-table>
-
-      <ext-page class="page-pager" v-model:value="state.pageQuery" @change="loadData(false)"/>
-    </el-card>
-  </div>
-</template>
-
-<script setup lang="ts" name="RefundLogList">
-import {defineAsyncComponent, reactive, onMounted, onBeforeMount, ref, getCurrentInstance, nextTick, onBeforeUnmount} from 'vue';
-import {$body, $get} from "/@/utils/request";
-import {Msg} from "/@/utils/message";
-import u from "/@/utils/u"
-
-
-import {useRoute} from "vue-router";
-
-const route = useRoute();
-import ExtPage from '/@/components/form/ExtPage.vue'
-
-import mittBus from '/@/utils/mitt';
-import ExtDSelect from "/@/components/form/ExtDSelect.vue";
-import ExtDLabel from "/@/components/form/ExtDLabel.vue";
-
-
-//定义引用
-const queryRef = ref();
-
-//定义变量
-const state = reactive({
-  formQuery: {
-    status:'NEW'
-  },
-  pageQuery: {
-    pageNum: 1,
-    pageSize: 10,
-    total: 0
-  },
-  tableData: {
-    height: 500,
-    data: [] as Array<any>,
-    loading: false,
-    columns: [
-      {label: '退款记录ID', prop: 'refundLogId', width: 105, resizable: true,fixed:'left'},
-      {label: '商户退款单号', prop: 'outRefundNo', width: 130, resizable: true,fixed:'left'},
-      {label: '商户订单号', prop: 'outTradeNo', width: 130, resizable: true,fixed:'left'},
-      {label: '手机号', prop: 'mobilePhone', width: 120, resizable: true,fixed:'left'},
-      // {label: '退款渠道', prop: 'channel', width: 150,resizable: true},
-      {label: '退款状态', prop: 'status', resizable: true, width: 120},
-      {label: '申请时间', prop: 'createTime', sortable: 'custom', resizable: true, width: 160},
-      {label: '退款成功时间', prop: 'successTime', sortable: 'custom', resizable: true, width: 160},
-      {label: '原充值订单金额', prop: 'total', resizable: true, width: 140},
-      {label: '退款申请金额', prop: 'refund', resizable: true, width: 120},
-      {label: '优惠金额', prop: 'discountAmount', resizable: true, width: 90},
-      // {label: '用户支付币种', prop: 'currency', resizable: true, width: 120},
-      // {label: '资金账户', prop: 'fundsAccount', resizable: true, width: 120},
-      {label: '退款原因', prop: 'reason', resizable: true, width: 120},
-      // {label: '微信支付退款单号', prop: 'outRefundNo', resizable: true, width: 150},
-      // {label: '微信支付订单号', prop: 'outTradeNo', resizable: true, width: 150},
-      {label: '退款入账账户', prop: 'userReceivedAccount', resizable: true, width: 120},
-      {label: '操作人', prop: 'adminUsername', resizable: true, width: 120},
-      {
-        label: '操作', prop: 'action', width: 110, align: 'center', fixed: 'right',
-      }
-    ],
-  },
-})
-
-
-// 监听双向绑定 modelValue 的变化
-// watch(
-//         () => state.pageNum,
-//         () => {
-//
-//         }
-// );
-
-//生命周期钩子
-onBeforeMount(() => {
-})
-
-onMounted(() => {
-  let query = route.query;
-  //console.log(route.params, route.query)
-  if (query.mobilePhone) {
-    state.formQuery.mobilePhone = query.mobilePhone;
-  }
-
-
-  loadData();
-
-  nextTick(() => {
-    let bodyHeight = document.body.clientHeight;
-    let queryHeight = queryRef.value.$el.clientHeight;
-    state.tableData.height = bodyHeight - queryHeight - 320
-  })
-
-  mittBus.on("refundLog.refresh", () => {
-    loadData();
-  })
-});
-
-onBeforeUnmount(() => {
-  mittBus.off("refundLog.refresh")
-})
-
-
-//region 方法区
-// 初始化表格数据
-const loadData = (refresh: boolean = false) => {
-  if (refresh) {
-    state.pageQuery.pageNum = 1;
-  }
-  state.tableData.loading = true;
-  $get(`/finance/listRefundLog`, {...state.formQuery, ...state.pageQuery}).then((res: any) => {
-    let {list, total} = res;
-    state.tableData.data = list;
-    state.pageQuery.total = total;
-    state.tableData.loading = false;
-  }).catch(e => {
-    //console.error(e)
-    state.tableData.loading = false;
-  })
-};
-
-// 打开修改用户弹窗
-const onRefundClick = ( row: any) => {
-  // if(row.status){
-  //   return;
-  // }
-  Msg.confirm("请确认是否执行退款操作?").then(()=>{
-    $get(`/finance/customWxRefund/${row.refundLogId}`).then((res: any) => {
-      Msg.message(`操作已提交`)
-      loadData(true)
-    }).catch(e => {
-      //console.error(e)
-    })
-  })
-};
-
-
-const handleTableSelectionChange = (selection: any) => {
-  //console.log("handleTableSelectionChange>>", selection)
-  // emit("on-check-change", selection)
-}
-
-const handleTableSortChange = (column, prop, order) => {
-  //console.log("handleTableSortChange>>", column, prop, order)
-  // emit("on-sort-change", column)
-}
-
-
-//endregion
-
-
-// 暴露变量
-// defineExpose({
-//     loadData,
-// });
-</script>

+ 0 - 245
admin-web/src/views/admin/station/stat/dialog.vue

@@ -1,245 +0,0 @@
-<style scoped lang="scss">
-
-</style>
-<template>
-  <div class="system-dialog-container">
-    <el-drawer
-        :title="state.dialog.title"
-        v-model="state.dialog.isShowDialog"
-        size="620px"
-        class="pd8"
-        append-to-body
-        destroy-on-close
-        :close-on-click-modal="false"
-    >
-      <el-form
-          :model="state.ruleForm"
-          :rules="state.rules"
-          label-position="right"
-          ref="formRef"
-          size="default"
-          label-width="180px"
-          class="mt5">
-        <el-form-item label="统计时间" prop="statMonth">
-          <el-input
-              v-model="state.ruleForm.statMonth"
-              placeholder="统计时间"
-              clearable
-              disabled
-              class="wd200">
-          </el-input>
-        </el-form-item>
-        <el-form-item label="站点" prop="stationId">
-<!--          <el-input
-              v-model="state.ruleForm.stationId"
-              placeholder="站点id"
-              clearable
-              class="wd200">
-          </el-input>-->
-          <ext-select
-              v-model="state.ruleForm.stationId"
-              placeholder="站点"
-              clearable
-              disabled
-              url="station/listStation"
-              urlMethod="get"
-              data-key=""
-              label-key="stationName"
-              value-key="stationId"
-              @on-change="loadData(true)"
-              class="wd200 mr10">
-          </ext-select>
-        </el-form-item>
-
-
-
-<!--        <el-form-item label="总电量" prop="totalPower">-->
-<!--          <ext-input-number v-model="state.ruleForm.totalPower"  class="wd200"></ext-input-number>-->
-<!--        </el-form-item>-->
-
-<!--        <el-form-item label="总充电费用" prop="totalMoney">-->
-<!--          <ext-input-number v-model="state.ruleForm.totalMoney"  class="wd200"></ext-input-number>-->
-<!--        </el-form-item>-->
-
-<!--        <el-form-item label="总电费" prop="elecMoney">-->
-<!--          <ext-input-number v-model="state.ruleForm.elecMoney"  class="wd200"></ext-input-number>-->
-<!--        </el-form-item>-->
-
-        <el-form-item label="实际抄表电费" prop="actualElecMoney">
-          <ext-input-number v-model="state.ruleForm.actualElecMoney"  class="wd200"></ext-input-number>
-        </el-form-item>
-        <el-form-item label="实际抄表电量" prop="actualPower">
-          <ext-input-number v-model="state.ruleForm.actualPower"  class="wd200"></ext-input-number>
-        </el-form-item>
-
-
-<!--        <el-form-item label="总服务费" prop="serviceMoney">-->
-<!--          <ext-input-number v-model="state.ruleForm.serviceMoney"  class="wd200"></ext-input-number>-->
-<!--        </el-form-item>-->
-
-
-<!--        <el-form-item label="服务费优惠金额" prop="serviceMoneyDiscount">-->
-<!--          <ext-input-number v-model="state.ruleForm.serviceMoneyDiscount"  class="wd200"></ext-input-number>-->
-<!--        </el-form-item>-->
-
-
-<!--        <el-form-item label="总优惠金额" prop="discountAmount">-->
-<!--          <ext-input-number v-model="state.ruleForm.discountAmount"  class="wd200"></ext-input-number>-->
-<!--        </el-form-item>-->
-
-<!--        <el-form-item label="单枪平均日充电量" prop="avgConnectorElec">-->
-<!--          <ext-input-number v-model="state.ruleForm.avgConnectorElec"  class="wd200"></ext-input-number>-->
-<!--        </el-form-item>-->
-<!--        <el-form-item label="订单平均充电量" prop="avgOrderElec">-->
-<!--          <ext-input-number v-model="state.ruleForm.avgOrderElec"  class="wd200"></ext-input-number>-->
-<!--        </el-form-item>-->
-<!--        <el-form-item label="订单平均充电费用" prop="avgOrderMoney">-->
-<!--          <ext-input-number v-model="state.ruleForm.avgOrderMoney"  class="wd200"></ext-input-number>-->
-<!--        </el-form-item>-->
-
-
-<!--        <el-form-item label="充电人数" prop="chargeUsers">-->
-<!--          <el-input-->
-<!--              type="number"-->
-<!--              v-model="state.ruleForm.chargeUsers"-->
-<!--              placeholder="充电人数"-->
-<!--              clearable-->
-<!--              class="wd200">-->
-<!--          </el-input>-->
-<!--        </el-form-item>-->
-
-
-
-<!--        <el-form-item label="充电有效订单数" prop="validOrders">-->
-<!--          <el-input-->
-<!--              type="number"-->
-<!--              v-model="state.ruleForm.validOrders"-->
-<!--              placeholder="充电有效订单数"-->
-<!--              clearable-->
-<!--              class="wd200">-->
-<!--          </el-input>-->
-<!--        </el-form-item>-->
-
-<!--        <el-form-item label="设备使用率" prop="connectorUsageRate">-->
-<!--          <el-input-->
-<!--              type="number"-->
-<!--              v-model="state.ruleForm.connectorUsageRate"-->
-<!--              placeholder="设备使用率"-->
-<!--              clearable-->
-<!--              class="wd200">-->
-<!--          </el-input>-->
-<!--        </el-form-item>-->
-      </el-form>
-
-      <template #footer>
-        <div class="dialog-footer">
-          <el-button @click="onCancel" size="default">关  闭</el-button>
-          <el-button v-if="state.action==='edit'"  :loading="state.btnLoading" type="primary" @click="onSubmit" size="default">{{ state.dialog.submitTxt }}</el-button>
-        </div>
-      </template>
-    </el-drawer>
-  </div>
-</template>
-
-<script setup lang="ts" name="StationStatMonthDialog">
-import {defineAsyncComponent, reactive, onMounted, ref} from 'vue';
-import {Msg} from "/@/utils/message";
-import {$body, $get} from "/@/utils/request";
-import u from '/@/utils/u'
-
-import ExtSelect from "/@/components/form/ExtSelect.vue";
-import ExtInputNumber from "/@/components/form/ExtInputNumber.vue";
-
-// 定义子组件向父组件传值/事件
-const emit = defineEmits(['refresh']);
-const formRef = ref();
-//定义初始变量,重置使用
-const initState = () => ({
-  ruleForm: {
-    id: 0
-  },
-  btnLoading: false,
-  dialog: {
-    isShowDialog: false,
-    type: '',
-    title: '',
-    submitTxt: '',
-  },
-  rules: {},
-  action:''
-})
-
-// 定义变量内容
-const state = reactive(initState());
-
-
-// 打开弹窗
-const open = (action: string = 'add', row: any) => {
-  state.action = action;
-  state.dialog.title = u.dialog.actions[action].title + "『站点统计表-月』"
-  state.dialog.submitTxt = u.dialog.actions[action].btn + "『站点统计表-月』"
-  state.dialog.isShowDialog = true;
-  if (action !== 'add') {
-    loadData(row.id);
-  }
-};
-// 关闭弹窗
-const onClose = () => {
-  state.dialog.isShowDialog = false;
-  Object.assign(state, initState())
-};
-// 取消
-const onCancel = () => {
-  onClose();
-};
-// 提交
-const onSubmit = () => {
-  formRef.value.validate((valid, fields) => {
-    // //console.log('basic checkForm!', valid,fields)
-    //console.log(state.ruleForm)
-    if (valid) {
-      state.btnLoading = true;
-      const url = state.ruleForm.id > 0 ? "/stat/modifyStationStatMonth" : "stationStatMonth/add"
-      $body(url, state.ruleForm).then(() => {
-        state.btnLoading = false;
-        Msg.message('操作成功');
-        //console.log('submit!')
-        onClose();
-        emit('refresh');
-      })
-    } else {
-      state.btnLoading = false;
-      Msg.message('表单校验失败', 'error');
-    }
-  })
-
-};
-
-const handleFormChange = (formData: any) => {
-  //console.log(formData)
-}
-
-// 初始化表格数据
-const loadData = (id: any) => {
-  $get(`/stat/getStationStatMonth/${id}`).then((res: any) => {
-    state.ruleForm = res;
-  })
-}
-
-
-const formatMoney = (value:string|number) => {
-  return u.fmt.fmtMoney(Number(value))
-}
-
-const parserMoney = (value:string) => {
-  return (Number(value)*100)+""
-}
-
-
-// 暴露变量
-defineExpose({
-  open
-});
-
-
-</script>

+ 0 - 270
admin-web/src/views/admin/station/stat/index.vue

@@ -1,270 +0,0 @@
-<style scoped lang="scss">
-.system-container {
-
-  :deep(.el-card__body) {
-    display: flex;
-    flex-direction: column;
-    justify-content: space-between;
-    flex: 1;
-    overflow: auto;
-
-    .el-table {
-      flex: 1;
-    }
-
-  }
-}
-
-.page-content {
-  margin-bottom: 20px;
-}
-
-.page-pager {
-  background-color: #fff;
-  height: 24px;
-}
-</style>
-<template>
-  <div class="system-container layout-padding">
-    <el-card shadow="hover" class="layout-padding-auto">
-
-
-      <el-form
-          :model="state.formQuery"
-          ref="queryRef"
-          size="default" label-width="0px" class="mt5 mb5">
-<!--        <el-input-->
-<!--            v-model="state.formQuery.statMonth"-->
-<!--            placeholder="统计时间"-->
-<!--            clearable-->
-<!--            @blur="loadData(true)"-->
-<!--            class="wd150 mr10">-->
-<!--        </el-input>-->
-
-        <el-date-picker
-            placeholder="统计时间(月)"
-            @change="loadData(true)"
-            value-format="YYYY-MM"
-            v-model="state.formQuery.statMonth"
-            type="month"
-            class="wd150 mr10"
-        />
-
-        <ext-select
-            v-model="state.formQuery.stationId"
-            placeholder="站点"
-            clearable
-            url="station/listStation"
-            urlMethod="get"
-            data-key=""
-            label-key="stationName"
-            value-key="stationId"
-            @on-change="loadData(true)"
-            class="wd150 mr10">
-        </ext-select>
-
-        <el-button class="ml10"  plain size="default" type="success" @click="loadData(true)">
-          <SvgIcon name="ele-Search"/>
-          查询
-        </el-button>
-      </el-form>
-
-      <el-table
-          border
-          stripe="stripe"
-          :height="state.tableData.height"
-          highlight-current-row
-          current-row-key="id"
-          row-key="id"
-          :data="state.tableData.data"
-          v-loading="state.tableData.loading"
-          @selection-change="handleTableSelectionChange"
-          @sort-change="handleTableSortChange">
-        <template #empty>
-          <el-empty></el-empty>
-        </template>
-        <el-table-column
-            v-for="field in state.tableData.columns"
-            :key="field.prop"
-            :label="field.label"
-            :column-key="field.prop"
-            :width="field.width"
-            :min-width="field.minWidth"
-            :fixed="field.fixed"
-            :sortable="field.sortable"
-            :show-overflow-tooltip="!field.fixed&&field.width>150"
-        >
-          <template #default="{row}">
-            <template v-if="field.prop==='action'">
-              <el-button v-auth="'stationStatMonth.modify'" size="small" plain type="warning" @click="onRowClick('edit',row)">编辑</el-button>
-              <el-button v-auth="'stationStatMonth.list'" size="small" plain type="primary" @click="onRowClick('view',row)">查看</el-button>
-              <el-button v-auth="'statement.add'" size="small" plain type="success" @click="handleCreateStatements(row)">生成对账单</el-button>
-            </template>
-            <template v-else-if="field.prop==='stationId'">
-              <div class="text-align-center">
-                {{row.stationId}}
-                <hr>
-                {{row.stationName}}
-              </div>
-            </template>
-            <template v-else-if="['totalMoney','elecMoney','actualElecMoney','serviceMoney','serviceMoneyDiscount','discountAmount','avgOrderMoney','actualPower'].includes(field.prop)">
-              {{ u.fmt.fmtMoney(row[field.prop]) }}
-            </template>
-            <template v-else>
-              <div>{{row[field.prop]}}</div>
-            </template>
-
-          </template>
-        </el-table-column>
-      </el-table>
-
-      <ext-page class="page-pager" v-model:value="state.pageQuery" @change="loadData(false)"/>
-    </el-card>
-  </div>
-  <StationStatMonthDialog ref="stationStatMonthDialogRef" @refresh="loadData(true)"/>
-</template>
-
-<script setup lang="ts" name="StationStatMonthList">
-import {defineAsyncComponent, reactive, onMounted, onBeforeMount, ref, getCurrentInstance, nextTick, onBeforeUnmount} from 'vue';
-import {$body,$get} from "/@/utils/request";
-import {Msg} from "/@/utils/message";
-import u from "/@/utils/u";
-
-import ExtPage from '/@/components/form/ExtPage.vue'
-
-import mittBus from '/@/utils/mitt';
-import ExtSelect from "/@/components/form/ExtSelect.vue";
-
-const StationStatMonthDialog = defineAsyncComponent(() => import("/@/views/admin/station/stat/dialog.vue"));
-
-//定义引用
-const queryRef = ref();
-const stationStatMonthDialogRef = ref();
-
-//定义变量
-const state = reactive({
-  formQuery: {},
-  pageQuery: {
-    pageNum: 1,
-    pageSize: 10,
-    total: 0
-  },
-  tableData: {
-    height: 500,
-    data: [] as Array < any >,
-    loading: false,
-    columns: [
-      {label: '站点', prop: 'stationId', resizable: true,width:140,fixed:'left'},
-      {label: '统计时间', prop: 'statMonth', resizable: true,width:90},
-      {label: '订单电量', prop: 'totalPower', resizable: true,width:100},
-      {label: '订单金额', prop: 'totalMoney', resizable: true,width:100},
-      {label: '订单电费', prop: 'elecMoney', resizable: true,width:100},
-      {label: '实际抄表电费', prop: 'actualElecMoney', resizable: true,width:120},
-      {label: '实际抄表电量', prop: 'actualPower', resizable: true,width:120},
-      {label: '订单服务费', prop: 'serviceMoney', resizable: true,width:110},
-      {label: '服务费优惠金额', prop: 'serviceMoneyDiscount', resizable: true,width:135},
-      {label: '总优惠金额', prop: 'discountAmount', resizable: true,width:110},
-      {label: '充电人数', prop: 'chargeUsers', resizable: true,width:100},
-      {label: '充电有效订单数', prop: 'validOrders', resizable: true,width:135},
-      {label: '订单平均充电量', prop: 'avgOrderElec', resizable: true,width:145},
-      {label: '订单平均充电费用', prop: 'avgOrderMoney', resizable: true,width:145},
-      {label: '单枪平均日充电量', prop: 'avgConnectorElec', resizable: true,width:145},
-      // {label: '创建时间', prop: 'createTime', sortable: 'custom', resizable: true,width:200,fixed: 'right',},
-      {
-        label: '操作', prop: 'action', width: 180, align: 'center', fixed: 'right',
-      }
-    ],
-  },
-})
-
-
-// 监听双向绑定 modelValue 的变化
-// watch(
-//         () => state.pageNum,
-//         () => {
-//
-//         }
-// );
-
-//生命周期钩子
-onBeforeMount(() => {
-})
-
-onMounted(() => {
-  loadData();
-
-  nextTick(() => {
-    let bodyHeight = document.body.clientHeight;
-    let queryHeight = queryRef.value.$el.clientHeight;
-    state.tableData.height = bodyHeight - queryHeight - 320
-  })
-
-  mittBus.on("stationStatMonth.refresh", () => {
-    loadData();
-  })
-});
-
-onBeforeUnmount(() => {
-  mittBus.off("stationStatMonth.refresh")
-})
-
-
-//region 方法区
-// 初始化表格数据
-const handleCreateStatements = (statMonth) => {
-  $get(`statements/create/${statMonth.id}`).then(()=>{
-    Msg.message(`生成对账单成功`)
-  })
-}
-
-const loadData = (refresh: boolean = false) => {
-  if (refresh) {
-    state.pageQuery.pageNum = 1;
-  }
-  state.tableData.loading = true;
-  $get(`/stat/listStatMonth`, {...state.formQuery, ...state.pageQuery}).then((res: any) => {
-    let {list, total} = res;
-    state.tableData.data = list;
-    state.pageQuery.total = total;
-    state.tableData.loading = false;
-  }).catch(e => {
-    //console.error(e)
-    state.tableData.loading = false;
-  })
-};
-
-// 打开修改站点统计表-月弹窗
-const onRowClick = (type: string, row: any) => {
-  stationStatMonthDialogRef.value.open(type, row);
-};
-
-// 删除站点统计表-月
-const onRowDel = (row: any) => {
-  Msg.confirm(`此操作将永久删除:『${row.name}』,是否继续?`).then(() => {
-    $get(`/stationStatMonth/delete/${row.id}`).then(() => {
-      Msg.message("删除成功", 'success')
-    }).catch(() => {
-      Msg.message("删除失败", 'error')
-    })
-  });
-};
-
-const handleTableSelectionChange = (selection: any) => {
-  //console.log("handleTableSelectionChange>>", selection)
-  // emit("on-check-change", selection)
-}
-
-const handleTableSortChange = (column, prop, order) => {
-  //console.log("handleTableSortChange>>", column, prop, order)
-  // emit("on-sort-change", column)
-}
-
-
-//endregion
-
-
-// 暴露变量
-// defineExpose({
-//     loadData,
-// });
-</script>

+ 0 - 334
admin-web/src/views/admin/station/statment/dialog.vue

@@ -1,334 +0,0 @@
-<style scoped lang="scss">
-/*  td{
-    height: 42px;
-    padding-left: 3px;
-  }*/
-
-table {
-  border-collapse: separate;
-  border-top: 1px solid #000;
-  border-left: 1px solid #000;
-}
-
-thead tr th {
-  background-color: #f8f8f9;
-  padding: 6px;
-  text-align: center;
-  border-bottom: 1px solid #000;
-  border-right: 1px solid #000;
-}
-
-tbody tr td {
-  padding: 6px;
-  height: 34px; //设置单元格最小高度
-  border-bottom: 1px solid #000;
-  border-right: 1px solid #000;
-}
-</style>
-<template>
-  <div class="system-dialog-container">
-    <el-dialog
-        :title="state.ruleForm.roleName+'对账单'"
-        v-model="state.dialog.isShowDialog"
-        width="1000px"
-        draggable
-        destroy-on-close
-        :close-on-click-modal="false"
-        @close="onClose"
-        align-center>
-
-      <template v-if="state.ruleForm.roleName==='投资者'">
-        <table border="0" cellspacing="0" :id="'settle-table-'+state.ruleForm.roleDesc" class="w100">
-          <tr style="background-color: lightsteelblue;font-weight: bold">
-            <td colspan="9" style="height: 34px;text-align: center;">深圳市快与慢充电桩服务有限公司—{{ state.ruleForm.stationName }}对账单</td>
-          </tr>
-          <tbody>
-          <tr class="text-align-center">
-            <td>客户名称</td>
-            <td :colspan="8">{{ state.ruleForm.adminUserName }}</td>
-          </tr>
-          <tr class="text-align-center">
-            <td>所属期间</td>
-            <td :colspan="8">{{ state.ruleForm.statMonth }}</td>
-          </tr>
-
-          <tr style="background-color: lightsteelblue;">
-            <td colspan="9" style="padding-left: 15px;">一、APP后台数据(含税,订单总金额为电费金额,实际电费为快与慢代收代付)(电量单位为“度”,电费和服务费以及金额单位为“元”)</td>
-          </tr>
-          <tr style="text-align: center">
-            <td>站点名称</td>
-            <td>订单电量</td>
-            <td>①订单电费</td>
-            <td>电表电量</td>
-            <td>②电表电费</td>
-            <td>电损金额=②-①</td>
-            <td>实收对账服务费</td>
-            <td>订单实收总金额</td>
-          </tr>
-          <tr style="text-align: center">
-            <td>{{ state.ruleForm.stationName }}</td>
-            <td>{{ state.ruleForm.totalPower }}</td>
-            <td>{{ u.fmt.fmtMoney(state.ruleForm.elecMoney) }}</td>
-            <td>{{ u.fmt.fmtMoney(state.ruleForm.actualPower) }}</td>
-            <td>{{ u.fmt.fmtMoney(state.ruleForm.actualElecMoney) }}</td>
-            <td>{{ u.fmt.fmtMoney(state.ruleForm.elecLossMoney) }}</td>
-            <td>{{ u.fmt.fmtMoney(state.ruleForm.serviceMoney - state.ruleForm.discountAmount) }}</td>
-            <td>{{ u.fmt.fmtMoney(state.ruleForm.totalMoney - state.ruleForm.discountAmount) }}</td>
-          </tr>
-          <tr style="background-color: lightsteelblue">
-            <td colspan="9" style="padding-left: 15px;">二、客户结算数据(含税)(电费和服务费以及金额单位为“元”)</td>
-          </tr>
-          <tr style="text-align: center">
-            <td>站点名称</td>
-            <td>①对账服务费</td>
-            <td>②服务费分成比例</td>
-            <td>③服务费分成</td>
-            <td>④电损金额</td>
-            <td>⑤电损承担比例</td>
-            <td>⑥电损承担金额</td>
-            <td>⑦分成金额=③-⑥</td>
-          </tr>
-          <tr style="text-align: center">
-            <td>{{ state.ruleForm.stationName }}</td>
-            <td>{{ u.fmt.fmtMoney(state.ruleForm.actualServiceMoney) }}</td>
-            <td>{{ (state.ruleForm.splittingProportion * 100).toFixed(2) }}%</td>
-            <td>{{ u.fmt.fmtMoney(state.ruleForm.actualServiceMoney * state.ruleForm.splittingProportion) }}</td>
-            <td>{{ u.fmt.fmtMoney(state.ruleForm.elecLossMoney) }}</td>
-            <td>{{ (state.ruleForm.elecLossProportion * 100).toFixed(2) }}%</td>
-            <td>{{ u.fmt.fmtMoney(state.ruleForm.elecLossAmount) }}</td>
-            <td>{{ u.fmt.fmtMoney(state.ruleForm.actualServiceMoney * state.ruleForm.splittingProportion - state.ruleForm.elecLossAmount) }}</td>
-          </tr>
-          <tr style="background-color: lightsteelblue">
-            <td colspan="9" style="padding-left: 15px;">三、客户结算数据(不含税)(税额和金额单位为“元”)</td>
-          </tr>
-          <tr style="text-align: center">
-            <td colspan="2">①分成金额</td>
-            <td colspan="2"> 增值税率</td>
-            <td colspan="2">②应纳增值税额</td>
-            <td colspan="3">应付金额=①-②</td>
-          </tr>
-          <tr style="text-align: center">
-            <td colspan="2">{{ u.fmt.fmtMoney(state.ruleForm.actualServiceMoney * state.ruleForm.splittingProportion - state.ruleForm.elecLossAmount) }}</td>
-            <td colspan="2">{{ (state.ruleForm.vatRate * 100).toFixed(2) }}%</td>
-            <td colspan="2">{{ u.fmt.fmtMoney(state.ruleForm.vatAmount) }}</td>
-            <td colspan="2">{{ u.fmt.fmtMoney(state.ruleForm.actualSplittingAmount) }}</td>
-          </tr>
-          <tr style="background-color: lightsteelblue">
-            <td colspan="9" style="padding-left: 15px;">备注:</td>
-          </tr>
-          <tr>
-            <td colspan="9" style="padding-left: 15px;">
-              分成金额=实际服务费收入*分成比例<br>
-
-              注意:乙方通过运营平台收取扣除相应费用以后的“实际收取的充电服务费收益”*甲方分成比例,甲方收益分成比例为{{ (state.ruleForm.splittingProportion * 100).toFixed(2) }}%。<br>
-
-              结算账户:{{ state.ruleForm.accountName }} &nbsp;&nbsp; 联系电话:{{ state.ruleForm.telephone }} <br>
-
-              开户行:{{ state.ruleForm.bankName }} &nbsp;&nbsp; 银行账号:{{ state.ruleForm.bankCardNo }} <br>
-            </td>
-          </tr>
-          </tbody>
-        </table>
-      </template>
-
-
-      <template v-else>
-        <table border="0" cellspacing="0" :id="'settle-table-'+state.ruleForm.roleDesc"  class="w100">
-          <tr style="background-color: lightsteelblue;font-weight: bold">
-            <td colspan="8" style="height: 34px;text-align: center;">深圳市快与慢充电桩服务有限公司—{{ state.ruleForm.stationName }}对账单</td>
-          </tr>
-          <tbody>
-          <tr class="text-align-center">
-            <td>客户名称</td>
-            <td :colspan="7">{{ state.ruleForm.adminUserName }}</td>
-          </tr>
-          <tr class="text-align-center">
-            <td>所属期间</td>
-            <td :colspan="7">{{ state.ruleForm.statMonth }}</td>
-          </tr>
-
-          <tr style="background-color: lightsteelblue;">
-            <td colspan="8" style="padding-left: 15px;">一、APP后台数据(含税,订单总金额为电费金额,实际电费为快与慢代收代付)(电量单位为“度”,电费和服务费以及金额单位为“元”)</td>
-          </tr>
-          <tr style="text-align: center">
-            <td  colspan="2">站点名称</td>
-            <td colspan="2">充电电量(度)</td>
-            <td colspan="2">订单电费(元)</td>
-            <td >实收服务费(元)</td>
-            <td>订单实收总金额(元)</td>
-          </tr>
-          <tr style="text-align: center">
-            <td colspan="2">{{ state.ruleForm.stationName }}</td>
-            <td colspan="2">{{ state.ruleForm.totalPower }}</td>
-            <td colspan="2">{{ u.fmt.fmtMoney(state.ruleForm.elecMoney) }}</td>
-            <td>{{ u.fmt.fmtMoney(state.ruleForm.serviceMoney - state.ruleForm.discountAmount) }}</td>
-            <td>{{ u.fmt.fmtMoney(state.ruleForm.totalMoney - state.ruleForm.discountAmount) }}</td>
-          </tr>
-          <tr style="background-color: lightsteelblue">
-            <td colspan="8" style="padding-left: 15px;">二、物业结算数据(含税)</td>
-          </tr>
-          <tr style="text-align: center">
-            <td colspan="2">站点名称</td>
-            <td colspan="2">实付服务费(元)</td>
-            <td colspan="2">物业/场地方分成比例</td>
-            <td colspan="2">物业/场地方分成金额(元)</td>
-          </tr>
-          <tr style="text-align: center">
-            <td colspan="2">{{ state.ruleForm.stationName }}</td>
-            <td colspan="2">{{ u.fmt.fmtMoney(state.ruleForm.actualServiceMoney) }}</td>
-            <td colspan="2">{{ (state.ruleForm.splittingProportion * 100).toFixed(2) }}%</td>
-            <td colspan="2">{{ u.fmt.fmtMoney(state.ruleForm.splittingAmount) }}</td>
-          </tr>
-
-          <tr style="background-color: lightsteelblue">
-            <td colspan="8" style="padding-left: 15px;">备注:</td>
-          </tr>
-          <tr>
-            <td colspan="4" style="padding-left: 15px;">
-              甲方账户信息:<br>
-
-              结算账户:{{ state.ruleForm.accountName }} &nbsp;&nbsp;<br>
-              纳税人识别号:{{ state.ruleForm.taxNo }} <br>
-              开户行:{{ state.ruleForm.bankName }} &nbsp;&nbsp; <br>
-              银行账号:{{ state.ruleForm.bankCardNo }} <br>
-
-              物业确认(盖公章或财务章):
-            </td>
-            <td colspan="3" style="padding-left: 15px;">
-              乙方账户信息:<br>
-
-              结算账户:深圳市快与慢充电桩服务有限公司&nbsp;&nbsp;<br>
-              纳税人识别号:91440300MA5HJNDG14<br>
-              开户行:平安银行深圳深大支行&nbsp;&nbsp; <br>
-              银行账号:15419629160031<br>
-
-              乙方确认(盖公章或财务章):
-            </td>
-            <td  style="padding-left: 15px;">
-              应付账款:{{ u.fmt.fmtMoney(state.ruleForm.splittingAmount) }}元
-            </td>
-          </tr>
-          </tbody>
-        </table>
-      </template>
-
-      <template #footer>
-        <div class="dialog-footer">
-          <el-button @click="onCancel" size="default">关 闭</el-button>
-          <el-button :loading="state.btnLoading" type="primary" @click="onSubmit" size="default">下 载PDF</el-button>
-        </div>
-      </template>
-    </el-dialog>
-  </div>
-</template>
-
-<script setup lang="ts" name="StationDialog">
-import {defineAsyncComponent, reactive, onMounted, ref} from 'vue';
-import {$body, $get} from "/@/utils/request";
-import u from "/@/utils/u";
-
-import html2canvas from 'html2canvas';
-import jsPDF from 'jspdf'
-// 引入组件
-
-// 定义子组件向父组件传值/事件
-const emit = defineEmits(['refresh']);
-const formRef = ref();
-//定义初始变量,重置使用
-const initState = () => ({
-  ruleForm: {
-    id: 0,
-    roleName: '投资者',
-    roleDesc:'investor'
-  },
-  btnLoading: false,
-  dialog: {
-    isShowDialog: false,
-    type: '',
-    title: '',
-    submitTxt: '',
-  },
-  form: {}
-})
-
-// 定义变量内容
-const state = reactive(initState());
-
-
-// 打开弹窗
-const open = (action: string = 'add', row: any) => {
-  state.dialog.isShowDialog = true;
-  loadData(row.id);
-};
-// 关闭弹窗
-const onClose = () => {
-  state.dialog.isShowDialog = false;
-  Object.assign(state, initState())
-};
-// 取消
-const onCancel = () => {
-  onClose();
-};
-
-const loadData = (id: number) => {
-  $get(`statements/preview/${id}`).then(res => {
-    state.ruleForm = res;
-  })
-}
-
-
-const onSubmit = () => {
-  htmlToPDF(`settle-table-${state.ruleForm.roleDesc}`)
-}
-
-const htmlToPDF = async (htmlId: string, title: string = "对账单", bgColor = "#fff") => {
-  let pdfDom: HTMLElement | null = document.getElementById(htmlId) as HTMLElement
-  pdfDom.style.padding = '0 10px !important'
-  //纵向打印
-  // const A4Width = 595.28;
-  // const A4Height = 841.89;
-  const A4Width = 841.89;
-  const A4Height = 595.28;
-  let canvas = await html2canvas(pdfDom, {
-    scale: 2,
-    useCORS: true,
-    backgroundColor: bgColor,
-  });
-  let pageHeight = (canvas.width / A4Width) * A4Height;
-  let leftHeight = canvas.height;
-  let position = 0;
-  let imgWidth = A4Width;
-  let imgHeight = (A4Width / canvas.width) * canvas.height;
-  /*
-   根据自身业务需求  是否在此处键入下方水印代码
-  */
-  let pageData = canvas.toDataURL("image/jpeg", 1.0);
-  let PDF = new jsPDF("l", 'pt', 'a4');
-  if (leftHeight < pageHeight) {
-    PDF.addImage(pageData, "JPEG", 0, 0, imgWidth, imgHeight);
-  } else {
-    while (leftHeight > 0) {
-      PDF.addImage(pageData, "JPEG", 0, position, imgWidth, imgHeight);
-      leftHeight -= pageHeight;
-      position -= A4Height;
-      if (leftHeight > 0) PDF.addPage();
-    }
-  }
-  PDF.save(title + ".pdf");
-}
-
-
-// 初始化表格数据
-/*const loadData = (id: number) => {
-  $get(`station/detail/${id}`).then((res: any) => {
-    state.ruleForm = res;
-  })
-}*/
-
-// 暴露变量
-defineExpose({
-  open
-});
-
-
-</script>

+ 0 - 288
admin-web/src/views/admin/station/statment/index.vue

@@ -1,288 +0,0 @@
-<style scoped lang="scss">
-.system-container {
-
-  :deep(.el-card__body) {
-    display: flex;
-    flex-direction: column;
-    justify-content: space-between;
-    flex: 1;
-    overflow: auto;
-
-    .el-table {
-      flex: 1;
-    }
-
-  }
-}
-
-.page-content {
-  margin-bottom: 20px;
-}
-
-.page-pager {
-  background-color: #fff;
-  height: 24px;
-}
-</style>
-<template>
-  <div class="system-container layout-padding">
-    <el-card shadow="hover" class="layout-padding-auto">
-
-
-      <el-form
-          :model="state.formQuery"
-          ref="queryRef"
-          size="default" label-width="0px" class="mt5 mb5">
-        <el-input
-            v-model="state.formQuery.adminUserName"
-            placeholder="客户姓名"
-            clearable
-            @blur="loadData(true)"
-            class="wd150 mr10">
-        </el-input>
-
-        <el-date-picker
-            placeholder="统计时间(月)"
-            @change="loadData(true)"
-            value-format="YYYY-MM"
-            v-model="state.formQuery.statMonth"
-            type="month"
-            class="wd150 mr10"
-        />
-
-<!--        <el-input
-            v-model="state.formQuery.statMonth"
-            placeholder="统计时间(月)"
-            clearable
-            @blur="loadData(true)"
-            class="wd150 mr10">
-        </el-input>-->
-
-        <ext-select
-            v-model="state.formQuery.stationId"
-            placeholder="站点"
-            clearable
-            url="station/listStation"
-            urlMethod="get"
-            data-key=""
-            label-key="stationName"
-            value-key="stationId"
-            @on-change="loadData(true)"
-            class="wd150 mr10">
-        </ext-select>
-
-        <ext-d-select
-            type="Statement.status"
-            v-model="state.formQuery.status"
-            placeholder="状态"
-            clearable
-            @blur="loadData(true)"
-            class="wd150 mr10">
-        </ext-d-select>
-
-        <el-button class="ml10" plain size="default" type="success" @click="loadData(true)">
-          <SvgIcon name="ele-Search"/>
-          查询
-        </el-button>
-      </el-form>
-
-      <el-table
-          border
-          stripe="stripe"
-          :height="state.tableData.height"
-          highlight-current-row
-          current-row-key="id"
-          row-key="id"
-          :data="state.tableData.data"
-          v-loading="state.tableData.loading"
-          @selection-change="handleTableSelectionChange"
-          @sort-change="handleTableSortChange">
-        <template #empty>
-          <el-empty></el-empty>
-        </template>
-        <el-table-column
-            v-for="field in state.tableData.columns"
-            :key="field.prop"
-            :label="field.label"
-            :column-key="field.prop"
-            :width="field.width"
-            :min-width="field.minWidth"
-            :fixed="field.fixed"
-            :sortable="field.sortable"
-            :show-overflow-tooltip="!field.fixed&&field.width>150"
-        >
-          <template #default="{row}">
-            <template v-if="field.prop==='action'">
-              <el-button v-auth="'statement.list'" size="small" plain type="primary" @click="onRowClick('view',row)">查看</el-button>
-            </template>
-            <template v-else-if="field.prop==='stationId'">
-              <div class="text-align-center">
-                {{ row.stationId }}
-                <hr>
-                {{ row.stationName }}
-              </div>
-            </template>
-            <template v-else-if="field.prop==='status'">
-              <ext-d-label type="Statement.status" v-model="row.status"/>
-            </template>
-            <template v-else-if="['actualElecMoney','actualServiceMoney','actualSplittingAmount','discountAmount','elecLossMoney','elecMoney','serviceMoney','serviceMoneyDiscount','splittingAmount','totalMoney','vatAmount'].includes(field.prop)">
-              {{ u.fmt.fmtMoney(row[field.prop]) }}
-            </template>
-            <template v-else>
-              <div>{{ row[field.prop] }}</div>
-            </template>
-
-          </template>
-        </el-table-column>
-      </el-table>
-
-      <ext-page class="page-pager" v-model:value="state.pageQuery" @change="loadData(false)"/>
-    </el-card>
-  </div>
-  <StatementsDialog ref="statementsDialogRef" @refresh="loadData(true)"/>
-</template>
-
-<script setup lang="ts" name="StatementsList">
-import {defineAsyncComponent, reactive, onMounted, onBeforeMount, ref, getCurrentInstance, nextTick, onBeforeUnmount} from 'vue';
-import {$body, $get} from "/@/utils/request";
-import {Msg} from "/@/utils/message";
-import u from "/@/utils/u";
-
-
-import ExtPage from '/@/components/form/ExtPage.vue'
-
-import mittBus from '/@/utils/mitt';
-import ExtDLabel from "/@/components/form/ExtDLabel.vue";
-import ExtDSelect from "/@/components/form/ExtDSelect.vue";
-import ExtSelect from "/@/components/form/ExtSelect.vue";
-
-const StatementsDialog = defineAsyncComponent(() => import("/@/views/admin/station/statment/dialog.vue"));
-
-//定义引用
-const queryRef = ref();
-const statementsDialogRef = ref();
-
-//定义变量
-const state = reactive({
-  formQuery: {},
-  pageQuery: {
-    pageNum: 1,
-    pageSize: 10,
-    total: 0
-  },
-  tableData: {
-    height: 500,
-    data: [] as Array<any>,
-    loading: false,
-    columns: [
-      {label: '客户姓名', prop: 'adminUserName', resizable: true, fixed: 'left', width: 150},
-      {label: '站点', prop: 'stationId', resizable: true, width: 130},
-      {label: '统计时间(月)', prop: 'statMonth', resizable: true, width: 135},
-      // {label: '状态', prop: 'status', sortable: 'custom', align: 'center', width: 130},
-      {label: '实际抄表电费金额', prop: 'actualElecMoney', resizable: true, width: 150},
-      {label: '实际参与分成的服务费', prop: 'actualServiceMoney', resizable: true, width: 180},
-      {label: '实际分成金额', prop: 'actualSplittingAmount', resizable: true, width: 140},
-
-      {label: '优惠金额', prop: 'discountAmount', resizable: true, width: 100},
-      {label: '电损电费金额', prop: 'elecLossMoney', resizable: true, width: 120},
-      {label: '订单电费金额', prop: 'elecMoney', resizable: true, width: 120},
-
-      {label: '服务费金额', prop: 'serviceMoney', resizable: true, width: 120},
-      {label: '服务费优惠金额', prop: 'serviceMoneyDiscount', resizable: true, width: 130},
-      {label: '分成金额', prop: 'splittingAmount', resizable: true, width: 100},
-
-      {label: '订单金额', prop: 'totalMoney', resizable: true, width: 100},
-      {label: '增值税额', prop: 'vatAmount', resizable: true, width: 100},
-      {label: '创建时间', prop: 'createTime', sortable: 'custom', resizable: true, width: 200, fixed: 'right'},
-      {
-        label: '操作', prop: 'action', width: 100, align: 'center', fixed: 'right',
-      }
-    ],
-  },
-})
-
-
-// 监听双向绑定 modelValue 的变化
-// watch(
-//         () => state.pageNum,
-//         () => {
-//
-//         }
-// );
-
-//生命周期钩子
-onBeforeMount(() => {
-})
-
-onMounted(() => {
-  loadData();
-
-  nextTick(() => {
-    let bodyHeight = document.body.clientHeight;
-    let queryHeight = queryRef.value.$el.clientHeight;
-    state.tableData.height = bodyHeight - queryHeight - 320
-  })
-
-  mittBus.on("statements.refresh", () => {
-    loadData();
-  })
-});
-
-onBeforeUnmount(() => {
-  mittBus.off("statements.refresh")
-})
-
-
-//region 方法区
-// 初始化表格数据
-const loadData = (refresh: boolean = false) => {
-  if (refresh) {
-    state.pageQuery.pageNum = 1;
-  }
-  state.tableData.loading = true;
-  $get(`/statements/listStatements`, {...state.formQuery, ...state.pageQuery}).then((res: any) => {
-    let {list, total} = res;
-    state.tableData.data = list;
-    state.pageQuery.total = total;
-    state.tableData.loading = false;
-  }).catch(e => {
-    //console.error(e)
-    state.tableData.loading = false;
-  })
-};
-
-// 打开修改客户对账单弹窗
-const onRowClick = (type: string, row: any) => {
-  statementsDialogRef.value.open(type, row);
-};
-
-// 删除客户对账单
-const onRowDel = (row: any) => {
-  Msg.confirm(`此操作将永久删除:『${row.name}』,是否继续?`).then(() => {
-    $get(`/statements/delete/${row.id}`).then(() => {
-      Msg.message("删除成功", 'success')
-    }).catch(() => {
-      Msg.message("删除失败", 'error')
-    })
-  });
-};
-
-const handleTableSelectionChange = (selection: any) => {
-  //console.log("handleTableSelectionChange>>", selection)
-  // emit("on-check-change", selection)
-}
-
-const handleTableSortChange = (column, prop, order) => {
-  //console.log("handleTableSortChange>>", column, prop, order)
-  // emit("on-sort-change", column)
-}
-
-
-//endregion
-
-
-// 暴露变量
-// defineExpose({
-//     loadData,
-// });
-</script>

+ 0 - 55
car-wash-admin/src/main/java/com/kym/admin/controller/ConnectorInfoController.java

@@ -1,55 +0,0 @@
-package com.kym.admin.controller;
-
-import com.kym.common.R;
-import com.kym.entity.admin.queryParams.EquipmentQueryParam;
-import com.kym.entity.admin.vo.ConnectorInfoVo;
-import com.kym.entity.common.PageBean;
-import com.kym.service.admin.ConnectorInfoService;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.ModelAttribute;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
-
-/**
- * <p>
- * 充电桩桩体设备 前端控制器
- * </p>
- *
- * @author skyline
- * @since 2023-08-05
- */
-@RestController
-@RequestMapping("/connector")
-public class ConnectorInfoController {
-
-    private final ConnectorInfoService connectorInfoService;
-
-    public ConnectorInfoController(ConnectorInfoService connectorInfoService) {
-        this.connectorInfoService = connectorInfoService;
-    }
-
-
-    /**
-     * 充电桩列表
-     *
-     * @param params
-     * @return
-     */
-    @GetMapping("/listConnectors")
-    R<?> listEquipment(@ModelAttribute EquipmentQueryParam params) {
-        PageBean<ConnectorInfoVo> res = connectorInfoService.listConnectors(params);
-        return R.success(res);
-    }
-
-    /**
-     * 统计充电桩状态
-     *
-     * @return
-     */
-    @GetMapping("/statConnectorStatus")
-    R<?> statEquipment(String stationId) {
-        return R.success(connectorInfoService.statConnectorStatus(stationId));
-    }
-
-
-}

+ 0 - 69
car-wash-admin/src/main/java/com/kym/admin/controller/CouponController.java

@@ -1,69 +0,0 @@
-package com.kym.admin.controller;
-
-import com.kym.common.R;
-import com.kym.entity.admin.Coupon;
-import com.kym.entity.admin.queryParams.CouponQueryParam;
-import com.kym.entity.admin.vo.CouponVo;
-import com.kym.entity.admin.vo.UserCouponsIssueVo;
-import com.kym.service.admin.CouponService;
-import com.kym.service.miniapp.UserCouponService;
-import org.springframework.web.bind.annotation.*;
-
-/**
- * <p>
- * 优惠券表 前端控制器
- * </p>
- *
- * @author skyline
- * @since 2024-04-25
- */
-@RestController
-@RequestMapping("/coupon")
-public class CouponController {
-
-    private final CouponService couponService;
-
-    private final UserCouponService couponUserCouponService;
-
-    public CouponController(CouponService couponService, UserCouponService couponUserCouponService) {
-        this.couponService = couponService;
-        this.couponUserCouponService = couponUserCouponService;
-    }
-
-
-    /**
-     * 优惠券列表查询
-     *
-     * @param
-     * @return
-     */
-    @GetMapping("list")
-    public R<?> listCoupon(@ModelAttribute CouponQueryParam params) {
-        return R.success(couponService.listCoupon(params));
-    }
-
-
-    /**
-     * 发放优惠券
-     *
-     * @param userCouponsIssue
-     * @return
-     */
-    @PostMapping("issueCoupons")
-    R<?> issueCoupons(@RequestBody UserCouponsIssueVo userCouponsIssue) {
-        couponService.issueCoupons(userCouponsIssue);
-        return R.success();
-    }
-
-
-    /**
-     * 用户优惠券列表
-     * @param params
-     * @return
-     */
-    @GetMapping("listUserCoupons")
-    R<?> listUserCoupons(@ModelAttribute CouponQueryParam params){
-        return R.success(couponUserCouponService.listUserCoupons(params));
-    }
-
-}

+ 0 - 18
car-wash-admin/src/main/java/com/kym/admin/controller/EquipmentInfoController.java

@@ -1,18 +0,0 @@
-package com.kym.admin.controller;
-
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
-
-/**
- * <p>
- * 充电桩桩体设备 前端控制器
- * </p>
- *
- * @author skyline
- * @since 2023-08-05
- */
-@RestController
-@RequestMapping("/equipment")
-public class EquipmentInfoController {
-
-}

+ 0 - 18
car-wash-admin/src/main/java/com/kym/admin/controller/EquipmentRelationController.java

@@ -1,18 +0,0 @@
-package com.kym.admin.controller;
-
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
-
-/**
- * <p>
- *  前端控制器
- * </p>
- *
- * @author skyline
- * @since 2023-08-07
- */
-@RestController
-@RequestMapping("/equipment-relation")
-public class EquipmentRelationController {
-
-}

+ 0 - 146
car-wash-admin/src/main/java/com/kym/admin/controller/FinanceController.java

@@ -1,146 +0,0 @@
-package com.kym.admin.controller;
-
-import cn.hutool.core.io.IoUtil;
-import cn.hutool.poi.excel.ExcelWriter;
-import com.kym.common.R;
-import com.kym.common.annotation.SysLog;
-import com.kym.entity.admin.queryParams.CommonQueryParam;
-import com.kym.entity.admin.queryParams.InvoiceDetailQueryParam;
-import com.kym.entity.admin.queryParams.InvoiceQueryParam;
-import com.kym.service.admin.InvoiceDetailService;
-import com.kym.service.miniapp.InvoiceService;
-import com.kym.service.miniapp.RefundLogService;
-import com.kym.service.wechat.WxPayService;
-import jakarta.servlet.ServletOutputStream;
-import jakarta.servlet.http.HttpServletRequest;
-import jakarta.servlet.http.HttpServletResponse;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.web.bind.annotation.*;
-
-import java.net.URLEncoder;
-import java.nio.charset.StandardCharsets;
-
-
-/**
- * @author skyline
- * @description 财务
- * @date 2023-09-14 16:21
- */
-@RestController
-@RequestMapping("/finance")
-public class FinanceController {
-
-    private final Logger logger = LoggerFactory.getLogger(FinanceController.class);
-
-    private final WxPayService wxPayService;
-
-    private final RefundLogService refundLogService;
-
-    private final InvoiceService invoiceService;
-    private final InvoiceDetailService invoiceDetailService;
-
-    public FinanceController(WxPayService wxPayService, RefundLogService refundLogService, InvoiceService invoiceService, InvoiceDetailService invoiceDetailService) {
-        this.wxPayService = wxPayService;
-        this.refundLogService = refundLogService;
-        this.invoiceService = invoiceService;
-        this.invoiceDetailService = invoiceDetailService;
-    }
-
-    @SysLog("退款申请列表")
-    @GetMapping("/listRefundLog")
-    R<?> listRefundLog(@ModelAttribute CommonQueryParam params) {
-        return R.success(refundLogService.listRefundLog(params));
-    }
-
-    @SysLog("处理用户微信退款")
-    @GetMapping("/customWxRefund/{refundLogId}")
-    R<?> customWxRefund(@PathVariable("refundLogId") long refundLogId) {
-        wxPayService.wxRefund(refundLogId);
-        return R.success();
-    }
-
-    @GetMapping("/getUserTitle/{applyId}")
-    Object getUserTitle(@PathVariable String applyId) {
-        return wxPayService.userTitle(applyId);
-    }
-
-    @SysLog("开具发票")
-    @GetMapping("/handleInvoice/{invoiceId}")
-    R<?> handleInvoice(@PathVariable("invoiceId") String invoiceId) {
-        wxPayService.fapiaoApplication(invoiceId);
-        return R.success();
-    }
-
-    @SysLog("下载发票")
-    @GetMapping("/downloadInvoice/{invoiceId}")
-    R<?> downloadInvoice(@PathVariable("invoiceId") String invoiceId) {
-        return R.success(wxPayService.downloadInvoice(invoiceId));
-    }
-
-    /**
-     * 发票列表
-     *
-     * @param params
-     * @return 发票列表
-     */
-    @PostMapping("/listInvoice")
-    R<?> list(@RequestBody InvoiceQueryParam params) {
-        return R.success(invoiceService.listInvoice(params));
-    }
-
-    /**
-     * 取消申请发票,发票抬头填写页关闭事件调用
-     *
-     * @return
-     */
-    @GetMapping("/cancelApplyInvoice/{invoiceId}")
-    R<?> cancelApplyInvoice(@PathVariable String invoiceId) {
-        invoiceService.cancelApplyInvoice(invoiceId);
-        return R.success();
-    }
-
-    /**
-     * 查询发票
-     */
-    @GetMapping("/getInvoice/{applyId}")
-    R<?> getInvoice(@PathVariable String applyId) {
-        return R.success(wxPayService.queryFapiao(applyId));
-    }
-
-
-    /**
-     * 发票详情
-     */
-    @GetMapping("/listInvoiceDetail")
-    R<?> listInvoiceDetail(@ModelAttribute InvoiceDetailQueryParam params) {
-        return R.success(invoiceDetailService.listInvoiceDetail(params));
-    }
-
-
-    /**
-     * 导出发票列表
-     *
-     * @param params
-     * @return 导出发票列表
-     */
-    @GetMapping("/export/invoiceList")
-    void exportInvoiceList(@ModelAttribute InvoiceDetailQueryParam params, HttpServletRequest request, HttpServletResponse response) {
-        ExcelWriter writer = invoiceDetailService.exportInvoiceDetail(params);
-        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
-        response.setHeader("Content-disposition", "attachment;filename=" + URLEncoder.encode("发票详情列表", StandardCharsets.UTF_8) + ".xlsx");
-        ServletOutputStream excelOut = null;
-        try {
-            excelOut = response.getOutputStream();
-            writer.flush(excelOut, true);
-        } catch (Exception e) {
-            logger.error("exportInvoiceList error", e);
-        } finally {
-            writer.close();
-        }
-        IoUtil.close(excelOut);
-    }
-
-}
-
-

+ 0 - 18
car-wash-admin/src/main/java/com/kym/admin/controller/MonitorLogController.java

@@ -1,18 +0,0 @@
-package com.kym.admin.controller;
-
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
-
-/**
- * <p>
- * 设备监控日志表 前端控制器
- * </p>
- *
- * @author skyline
- * @since 2023-08-29
- */
-@RestController
-@RequestMapping("/monitor-log")
-public class MonitorLogController {
-
-}

+ 0 - 61
car-wash-admin/src/main/java/com/kym/admin/controller/StatementsController.java

@@ -1,61 +0,0 @@
-package com.kym.admin.controller;
-
-import com.kym.common.R;
-import com.kym.entity.admin.queryParams.StatementsQueryParam;
-import com.kym.service.admin.StatementsService;
-import org.springframework.web.bind.annotation.*;
-
-/**
- * <p>
- * 客户对账单 前端控制器
- * </p>
- *
- * @author skyline
- * @since 2023-12-27
- */
-@RestController
-@RequestMapping("/statements")
-public class StatementsController {
-
-    private final StatementsService statementsService;
-
-    public StatementsController(StatementsService statementsService) {
-        this.statementsService = statementsService;
-    }
-
-    /**
-     * 生成对账单(创建前先录入抄表电量和电费金额)
-     * 一次性生成对应站点投资者和物业的对账单
-     *
-     * @param statMonthId 月统计记录id
-     * @return
-     */
-    @GetMapping("/create/{statMonthId}")
-    R<?> create(@PathVariable("statMonthId") String statMonthId) {
-        statementsService.createStatements(statMonthId);
-        return R.success();
-    }
-
-    /**
-     * 预览
-     *
-     * @param statId
-     * @return
-     */
-    @GetMapping("/preview/{statId}")
-    R<?> preview(@PathVariable("statId") String statId) {
-        return R.success(statementsService.preview(statId));
-    }
-
-    /**
-     * 对账单列表
-     *
-     * @param params
-     * @return
-     */
-    @GetMapping("/listStatements")
-    R<?> list(@ModelAttribute StatementsQueryParam params) {
-        return R.success(statementsService.listStatements(params));
-    }
-
-}

+ 0 - 18
car-wash-admin/src/main/java/com/kym/admin/controller/StationNoticeController.java

@@ -1,18 +0,0 @@
-package com.kym.admin.controller;
-
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
-
-/**
- * <p>
- * 系统公告通知站点关联表 前端控制器
- * </p>
- *
- * @author skyline
- * @since 2024-08-20
- */
-@RestController
-@RequestMapping("/station-notice")
-public class StationNoticeController {
-
-}

+ 0 - 171
car-wash-admin/src/main/java/com/kym/admin/jobs/ActivityDelayJob.java

@@ -1,171 +0,0 @@
-package com.kym.admin.jobs;
-
-
-import com.kym.common.utils.CommUtil;
-import com.kym.entity.admin.*;
-import com.kym.entity.admin.delay.DelayActivity;
-import com.kym.service.admin.*;
-import com.kym.service.jobs.DelayService;
-import com.kym.service.jobs.DelayedItem;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.config.ConfigurableBeanFactory;
-import org.springframework.context.annotation.Scope;
-import org.springframework.context.event.ContextRefreshedEvent;
-import org.springframework.context.event.EventListener;
-import org.springframework.stereotype.Service;
-
-import java.util.concurrent.DelayQueue;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-
-/**
- * @author skyline
- * @description 活动启闭延迟任务
- * @date 2023-10-08 22:11
- */
-@Service
-@Slf4j
-@Scope(ConfigurableBeanFactory.SCOPE_SINGLETON) // 设置成单例
-public class ActivityDelayJob implements DelayService<DelayActivity> {
-
-    /**
-     * 活动队列
-     */
-    private final static DelayQueue<DelayedItem<DelayActivity>> DELAY_QUEUE = new DelayQueue<>();
-
-    private final ActivityService activityService;
-    private final ActivityStationService activityStationService;
-    private final RechargeRightsService rechargeRightsService;
-
-    private final CouponService couponService;
-    private final BannerService bannerService;
-    /**
-     * 线程池
-     */
-    private final ExecutorService executor = Executors.newFixedThreadPool(1);
-
-    public ActivityDelayJob(ActivityService activityService, ActivityStationService activityStationService, RechargeRightsService rechargeRightsService, CouponService couponService, BannerService bannerService) {
-        this.activityService = activityService;
-        this.activityStationService = activityStationService;
-        this.rechargeRightsService = rechargeRightsService;
-        this.couponService = couponService;
-        this.bannerService = bannerService;
-    }
-
-    // 这里不能使用@PostConstruct,在初始化完成后, bean 进入增强阶段, 所以这个阶段的任何AOP都是无效的,https://www.cnblogs.com/eternityz/p/15330069.html
-    @EventListener
-    @Override
-    public void init(ContextRefreshedEvent event) {
-        // 队列加载所有进行中和未开始的活动
-        var activity = activityService.lambdaQuery().in(Activity::getStatus, Activity.STATUS_进行中, Activity.STATUS_未开始).list();
-
-        // 启动队列
-        var delayStartActivityList = activity.stream().filter(a -> a.getStatus().equals(Activity.STATUS_未开始)).map(act -> new DelayActivity()
-                        .setId(act.getId())
-                        .setName(act.getName())
-                        .setExecuteTime(act.getStartTime())
-                        .setDiscountType(act.getDiscountType())
-                        .setType(DelayActivity.TYPE_启动))
-                .toList();
-
-        // 结束队列
-        var delayEndActivityList = activity.stream().map(act -> new DelayActivity()
-                        .setId(act.getId())
-                        .setName(act.getName())
-                        .setExecuteTime(act.getEndTime())
-                        .setDiscountType(act.getDiscountType())
-                        .setType(DelayActivity.TYPE_结束))
-                .toList();
-
-        delayStartActivityList.stream().map(delay -> new DelayedItem<>(delay, delay.getExecuteTime())).toList().forEach(this::addToDelayQueue);
-        delayEndActivityList.stream().map(delay -> new DelayedItem<>(delay, delay.getExecuteTime())).toList().forEach(this::addToDelayQueue);
-
-        // 开启线程处理队列消息
-        executor.execute(() -> {
-            ThreadLocal<Long> threadLocal = new ThreadLocal<>();
-            log.info("活动延迟启闭处理线程:{}", Thread.currentThread().getName());
-            DelayedItem<DelayActivity> delayedItem;
-            while (true) {
-                try {
-                    delayedItem = DELAY_QUEUE.take();
-                    var delayActivity = delayedItem.data;
-                    threadLocal.set(delayActivity.getId());
-                    if (delayActivity.getType().equals(DelayActivity.TYPE_启动)) {
-                        log.info("活动id:{},活动名:{}启动中...", delayActivity.getId(), delayActivity.getName());
-                        // 开始活动
-                        // 修改活动状态为进行中
-                        activityService.lambdaUpdate().set(Activity::getStatus, Activity.STATUS_进行中).eq(Activity::getId, delayActivity.getId()).update();
-                        // 修改活动站点关联表状态为进行中
-                        activityStationService.lambdaUpdate().set(ActivityStation::getStatus, Activity.STATUS_进行中).eq(ActivityStation::getActivityId, delayActivity.getId()).update();
-
-                        // 判断活动优惠类型,分别处理活动启动逻辑
-                        if (delayActivity.getDiscountType().equals(Activity.DISCOUNT_TYPE_服务费折扣权益)) {
-                            // 修改充值权益为进行中
-                            rechargeRightsService.lambdaUpdate().set(RechargeRights::getStatus, RechargeRights.STATUS_进行中).eq(RechargeRights::getActivityId, delayActivity.getId()).update();
-                        }
-                        if (delayActivity.getDiscountType().equals(Activity.DISCOUNT_TYPE_优惠券)) {
-                            // 修改优惠券状态为进行中
-                            couponService.lambdaUpdate().set(Coupon::getStatus, Coupon.STATUS_进行中).eq(Coupon::getActivityId, delayActivity.getId()).update();
-                        }
-
-                        // 修改banner状态为有效
-                        bannerService.lambdaUpdate().set(Banner::getStatus, Banner.STATUS_有效).eq(Banner::getActivityId, delayActivity.getId()).update();
-                        log.info("活动id:{},活动名:{}已开始...", delayActivity.getId(), delayActivity.getName());
-                    } else {
-                        log.info("活动id:{},活动名:{}停止中...", delayActivity.getId(), delayActivity.getName());
-                        // 停止活动
-                        // 修改活动状态为已结束
-                        activityService.lambdaUpdate().set(Activity::getStatus, Activity.STATUS_已结束).eq(Activity::getId, delayActivity.getId()).update();
-                        // 修改活动站点关联表状态为已结束
-                        activityStationService.lambdaUpdate().set(ActivityStation::getStatus, Activity.STATUS_已结束).eq(ActivityStation::getActivityId, delayActivity.getId()).update();
-
-                        // 判断活动优惠类型,分别处理活动结束逻辑
-                        if (delayActivity.getDiscountType().equals(Activity.DISCOUNT_TYPE_服务费折扣权益)) {
-                            // 修改充值权益为已结束
-                            rechargeRightsService.lambdaUpdate().set(RechargeRights::getStatus, RechargeRights.STATUS_已结束).eq(RechargeRights::getActivityId, delayActivity.getId()).update();
-                        }
-                        if (delayActivity.getDiscountType().equals(Activity.DISCOUNT_TYPE_优惠券)) {
-                            // 修改优惠券状态为已结束
-                            couponService.lambdaUpdate().set(Coupon::getStatus, Coupon.STATUS_已结束).eq(Coupon::getActivityId, delayActivity.getId()).update();
-                        }
-
-                        // 修改banner状态为失效
-                        bannerService.lambdaUpdate().set(Banner::getStatus, Banner.STATUS_无效).eq(Banner::getActivityId, delayActivity.getId()).update();
-                        log.info("活动id:{},活动名:{}已结束...", delayActivity.getId(), delayActivity.getName());
-                    }
-                    // 线程休眠100ms
-                    Thread.sleep(100);
-                } catch (Exception e) {
-                    if (e instanceof InterruptedException) {
-                        log.error("活动到期停止队列take异常", e);
-                    } else {
-                        log.info("活动到期停止,主活动id:{}", threadLocal.get(), e);
-                    }
-                } finally {
-                    threadLocal.remove();
-                }
-            }
-        });
-
-    }
-
-    @Override
-    public boolean addToDelayQueue(DelayedItem<DelayActivity> delayedItem) {
-        return DELAY_QUEUE.add(delayedItem);
-    }
-
-    @Override
-    public boolean addToDelayQueue(DelayActivity activity) {
-        DelayedItem<DelayActivity> orderDelayed = new DelayedItem<>(activity, activity.getExecuteTime());
-        return DELAY_QUEUE.add(orderDelayed);
-    }
-
-
-    @Override
-    public boolean removeFromDelayQueue(Object activityId) {
-        if (CommUtil.isEmptyOrNull(activityId)) {
-            return false;
-        }
-        return DELAY_QUEUE.removeIf(queue -> queue.data.getId().equals(activityId));
-    }
-}

+ 0 - 63
car-wash-admin/src/main/java/com/kym/admin/jobs/InvoiceStatusJob.java

@@ -1,63 +0,0 @@
-package com.kym.admin.jobs;
-
-
-import com.kym.entity.miniapp.ChargeOrder;
-import com.kym.entity.miniapp.Invoice;
-import com.kym.entity.wechat.InvoiceNotification;
-import com.kym.entity.wechat.InvoiceOrderDetail;
-import com.kym.service.admin.InvoiceDetailService;
-import com.kym.service.miniapp.ChargeOrderService;
-import com.kym.service.miniapp.InvoiceService;
-import com.kym.service.wechat.WxPayService;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.scheduling.annotation.Scheduled;
-import org.springframework.stereotype.Component;
-
-/**
- * @author skyline
- * @description 发票状态更新
- */
-@Component
-@Slf4j
-public class InvoiceStatusJob {
-
-    private final InvoiceService invoiceService;
-
-    private final InvoiceDetailService invoiceDetailService;
-
-    private final ChargeOrderService chargeOrderService;
-
-    private final WxPayService wxPayService;
-
-
-    public InvoiceStatusJob(InvoiceService invoiceService, InvoiceDetailService invoiceDetailService, ChargeOrderService chargeOrderService, WxPayService wxPayService) {
-        this.invoiceService = invoiceService;
-        this.invoiceDetailService = invoiceDetailService;
-        this.chargeOrderService = chargeOrderService;
-        this.wxPayService = wxPayService;
-    }
-
-    /**
-     * 每天18:00执行,处理微信发票开票结果通知不到的情况,主动查询发票信息更新数据
-     */
-//    @Scheduled(cron = "0 0 18 * * ?")
-    public void execute() {
-        log.info("执行发票状态处理定时任务...开始");
-        // 所有开票中状态的发票
-        var invoiceList = invoiceService.lambdaQuery().eq(Invoice::getStatus, Invoice.STATUS_开票中).list();
-        invoiceList.forEach(invoice -> {
-            var fapiaoApplications = wxPayService.queryFapiao(invoice.getApplyId());
-            // 更新发票详情
-            invoiceDetailService.updateInvoiceDetail(invoice.getApplyId(), fapiaoApplications);
-            // 更新订单开票状态
-            if (InvoiceNotification.FapiaoStatus.ISSUED.name().equals(fapiaoApplications.getFapiao_information().get(0).getStatus())) {
-                var startChargeSeqs = invoice.getOrderDetails().stream().map(InvoiceOrderDetail::getStartChargeSeq).toList();
-                chargeOrderService.lambdaUpdate().in(ChargeOrder::getStartChargeSeq, startChargeSeqs).set(ChargeOrder::getInvoiceStatus, ChargeOrder.INVOICE_STATUS_已开票).update();
-                // 修改发票状态
-                invoiceService.lambdaUpdate().eq(Invoice::getApplyId, invoice.getApplyId()).set(Invoice::getStatus, Invoice.STATUS_已开票).update();
-            }
-        });
-        log.info("执行发票状态处理定时任务...结束");
-    }
-
-}

+ 0 - 65
car-wash-admin/src/main/java/com/kym/admin/jobs/OfflineNotifyJob.java

@@ -1,65 +0,0 @@
-package com.kym.admin.jobs;
-
-import cn.hutool.extra.mail.MailUtil;
-import com.kym.common.utils.CommUtil;
-import com.kym.entity.common.RedisKeys;
-import com.kym.service.cache.KymCache;
-import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.lang3.StringUtils;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.data.redis.core.StringRedisTemplate;
-import org.springframework.scheduling.annotation.Scheduled;
-import org.springframework.stereotype.Component;
-
-import java.util.ArrayList;
-import java.util.Comparator;
-import java.util.Map;
-import java.util.Set;
-import java.util.stream.Collectors;
-
-/**
- * @author skyline
- * @description 设备离线通知
- * @date 2023-09-30 16:15
- */
-@Component
-@Slf4j
-public class OfflineNotifyJob {
-
-    private final StringRedisTemplate redisTemplate;
-
-    @Value("${kym.notify-email}")
-    private String notifyEmail;
-
-    public OfflineNotifyJob(StringRedisTemplate redisTemplate) {
-        this.redisTemplate = redisTemplate;
-    }
-
-    // 每小时的第30分钟执行一次
-//    @Scheduled(cron = "0 30 0/1 * * ? ")
-    public void execute() {
-        // 查询redis离线设备消息队列,存在且超过1小时的消息则发送邮件提醒
-        Set<String> offlineList = redisTemplate.opsForZSet().rangeByScore(RedisKeys.OFFLINE, System.currentTimeMillis() - 60 * 60 * 1000, System.currentTimeMillis() + 60 * 60 * 1000);
-        if (!CommUtil.isEmptyOrNull(offlineList)) {
-            /*
-             * 格式:
-             * 【设备离线通知】
-             * 【阳光科创中心】:001001,001002,001003
-             * 【阳光粤海家园】:002001,002002,002003
-             */
-            var temp = "【%s】:%s\n";
-            var map = new ArrayList<String>(offlineList).stream()
-                    .collect(Collectors.toMap(KymCache.INSTANCE::getShortIdByEquipmentIdOrConnectorId, KymCache.INSTANCE::getStationNameByConnectorId));
-            // 以站点名称分组
-            var list = map.entrySet().stream().collect(Collectors.groupingBy(Map.Entry::getValue));
-            StringBuilder sb = new StringBuilder();
-            list.forEach((k, v) -> sb.append(temp.formatted(k, StringUtils.join(v.stream().map(Map.Entry::getKey).sorted(Comparator.comparingInt(Integer::parseInt)).toList(), ","))));
-            log.warn(sb.toString());
-            // 格式化信息,发送邮件
-            MailUtil.send(notifyEmail, "【设备离线通知】", sb.toString(), false);
-            redisTemplate.opsForZSet().remove(RedisKeys.OFFLINE, offlineList.toArray(Object[]::new));
-            redisTemplate.opsForSet().add(RedisKeys.OFFLINE_EXPIRED, offlineList.toArray(String[]::new));
-        }
-
-    }
-}

+ 0 - 173
car-wash-admin/src/main/java/com/kym/admin/jobs/StationStatJob.java

@@ -1,173 +0,0 @@
-package com.kym.admin.jobs;
-
-import cn.hutool.core.date.DateUtil;
-
-import com.kym.common.utils.CommUtil;
-import com.kym.entity.admin.ConnectorInfo;
-import com.kym.entity.admin.StationStatDay;
-import com.kym.entity.admin.StationStatMonth;
-import com.kym.entity.miniapp.ChargeOrder;
-import com.kym.service.admin.ConnectorInfoService;
-import com.kym.service.admin.StationStatDayService;
-import com.kym.service.admin.StationStatMonthService;
-import com.kym.service.miniapp.ChargeOrderService;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.scheduling.annotation.Scheduled;
-import org.springframework.stereotype.Component;
-
-import java.time.LocalDate;
-import java.time.LocalDateTime;
-import java.time.LocalTime;
-import java.time.temporal.TemporalAdjusters;
-import java.util.*;
-import java.util.stream.Collectors;
-
-/**
- * 站点统计定时任务
- *
- * @author skyline
- */
-@Component
-@Slf4j
-public class StationStatJob {
-
-    private final ChargeOrderService chargeOrderService;
-
-    private final StationStatDayService dayService;
-    private final StationStatMonthService monthService;
-
-    private final ConnectorInfoService connectorInfoService;
-
-    public StationStatJob(ChargeOrderService chargeOrderService, StationStatDayService stationStatDayService, StationStatMonthService stationStatMonthService, ConnectorInfoService connectorInfoService) {
-        this.chargeOrderService = chargeOrderService;
-        this.dayService = stationStatDayService;
-        this.monthService = stationStatMonthService;
-        this.connectorInfoService = connectorInfoService;
-    }
-
-
-    // 每天14:30执行一次,通过charge_app.t_charge_order表统计start_time为前一天且充电金额大于100的充电订单,分别统计充电人数、订单数、充电总费用、充电总电量、平均充电电量、平均充电费用、平均订单费用、平均订单电量
-
-    /**
-     * 日统计,每日下午14:30启动,统计上日数据
-     */
-//    @Scheduled(cron = "0 30 14 * * ?")
-    // 定时每日下午14:30
-    private void dayStat() {
-        log.info("执行站点日统计定时任务-开始");
-        var statDay = LocalDateTime.now().minusDays(1);
-        var startTime = LocalDateTime.of(statDay.toLocalDate(), LocalTime.MIN);
-        var endTime = LocalDateTime.of(statDay.toLocalDate(), LocalTime.MAX);
-        var chargeOrderList = getChargeOrders(startTime, endTime);
-        dayService.saveBatch((Collection<StationStatDay>) getStationStat(chargeOrderList, true));
-        log.info("执行站点日统计定时任务-结束");
-    }
-
-
-    /**
-     * 月统计,每月第一天下午15:00启动,统计上月数据
-     */
-//    @Scheduled(cron = "0 0 15 1 * ?")
-    private void monthStat() {
-        log.info("执行站点月统计定时任务-开始");
-        var statMonth = LocalDateTime.now().minusMonths(1);
-        var startTime = statMonth.with(TemporalAdjusters.firstDayOfMonth()).with(LocalTime.MIN);
-        var endTime = statMonth.with(TemporalAdjusters.lastDayOfMonth()).with(LocalTime.MAX);
-        var chargeOrderList = getChargeOrders(startTime, endTime);
-        monthService.saveBatch((Collection<StationStatMonth>) getStationStat(chargeOrderList, false));
-        log.info("执行站点月统计定时任务-结束");
-    }
-
-    // 只执行一次
-//    @PostConstruct
-    private void init() {
-        log.info("执行站点初始化定时任务-开始");
-        // 2023-08-01 00:00:00
-//        var statMonth = LocalDateTime.of(2023, 12, 1, 0, 0);
-//        var endMonth = LocalDateTime.of(2023, 12, 1, 0, 0);
-//        var startTime = statMonth.with(TemporalAdjusters.firstDayOfMonth()).with(LocalTime.MIN);
-//        var endTime = endMonth.with(TemporalAdjusters.lastDayOfMonth()).with(LocalTime.MAX);
-//        var chargeOrderList = getChargeOrders(startTime, endTime);
-//        monthService.saveBatch((Collection<StationStatMonth>) getStationStat(chargeOrderList, false));
-//
-//        // 将订单按照日为单位分组
-//        var chargeOrderMap = chargeOrderList.stream().collect(Collectors.groupingBy(order ->
-//                order.getStartTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"))
-//        ));
-//        // chargeOrderMap按照key升序排序
-//        var chargeOrderMapSort = chargeOrderMap.entrySet().stream().sorted(Map.Entry.comparingByKey()).collect(
-//                Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (oldValue, newValue) -> oldValue, LinkedHashMap::new));
-//
-//        chargeOrderMapSort.forEach((k, v) -> dayService.saveBatch(((Collection<StationStatDay>) getStationStat(v, true))));
-
-        log.info("执行站点初始化定时任务-结束");
-    }
-
-    private List<ChargeOrder> getChargeOrders(LocalDateTime startTime, LocalDateTime endTime) {
-        // 通过charge_app.t_charge_order表统计start_time为前一天且充电金额大于0的有效充电订单
-        var res = chargeOrderService.lambdaQuery()
-                .ge(ChargeOrder::getStartTime, startTime)
-                .le(ChargeOrder::getStartTime, endTime)
-                .gt(ChargeOrder::getTotalMoney, 0)
-                .list();
-        return res;
-    }
-
-    private Collection<?> getStationStat(List<ChargeOrder> chargeOrderList, boolean isDayStat) {
-        // 统计每个站点的connector_id数量
-        var stationConnectorCountMap = connectorInfoService.list().stream().collect(Collectors.groupingBy(ConnectorInfo::getStationId, Collectors.counting()));
-        // 将chargeOrderList按照stationId分组
-        var chargeOrderMap = chargeOrderList.stream().collect(Collectors.groupingBy(ChargeOrder::getStationId));
-        // 根据分组计算每个站点的充电人数、订单数、充电总费用、充电总电量、平均充电电量、平均充电费用、平均订单费用、平均订单电量
-        return chargeOrderMap.entrySet().stream().collect(Collectors.toMap(
-                Map.Entry::getKey,
-                entry -> {
-                    var chargeOrders = entry.getValue();
-                    var chargeUsers = chargeOrders.stream().collect(Collectors.collectingAndThen(
-                            Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(ChargeOrder::getUserId))), ArrayList<ChargeOrder>::new)).size();
-                    var totalMoney = chargeOrders.stream().mapToInt(ChargeOrder::getTotalMoney).sum();
-                    var elecMoney = chargeOrders.stream().mapToInt(ChargeOrder::getElecMoney).sum();
-                    var serviceMoney = chargeOrders.stream().mapToInt(ChargeOrder::getServiceMoney).sum();
-                    var serviceMoneyDiscount = chargeOrders.stream().mapToInt(ChargeOrder::getServiceMoneyDiscount).sum();
-                    var discountAmount = chargeOrders.stream().mapToInt(ChargeOrder::getDiscountAmount).sum();
-                    var totalPower = chargeOrders.stream().mapToDouble(ChargeOrder::getTotalPower).sum();
-                    var avgPower = chargeOrders.stream().mapToDouble(ChargeOrder::getTotalPower).average().orElse(0.0);
-                    var avgOrderMoney = chargeOrders.stream().mapToInt(ChargeOrder::getTotalMoney).average().orElse(0);
-                    // 充电桩使用率 = 有订单的充电桩数量 / 总充电桩数
-                    var connectorUsageRate = (double) chargeOrders.stream().filter(CommUtil.distinctByKey(ChargeOrder::getConnectorId)).count() / stationConnectorCountMap.get(entry.getKey());
-                    ;
-                    return isDayStat
-                            ? new StationStatDay()
-                            .setStationId(entry.getKey())
-                            .setStatDay(DateUtil.format(LocalDateTime.now().minusDays(1), "yyyy-MM-dd"))
-                            .setChargeUsers(chargeUsers)
-                            .setValidOrders(chargeOrders.size())
-                            .setTotalMoney(totalMoney)
-                            .setElecMoney(elecMoney)
-                            .setServiceMoney(serviceMoney)
-                            .setServiceMoneyDiscount(serviceMoneyDiscount)
-                            .setDiscountAmount(discountAmount)
-
-                            .setTotalPower(totalPower)
-                            .setAvgOrderElec(avgPower)
-                            .setAvgOrderMoney((int) avgOrderMoney)
-                            .setAvgConnectorElec(totalPower / (stationConnectorCountMap.get(entry.getKey())))
-                            .setConnectorUsageRate(connectorUsageRate)
-
-                            : new StationStatMonth()
-                            .setStationId(entry.getKey())
-                            .setStatMonth(DateUtil.format(LocalDateTime.now().minusMonths(1), "yyyy-MM"))
-                            .setChargeUsers(chargeUsers)
-                            .setValidOrders(chargeOrders.size())
-                            .setTotalMoney(totalMoney)
-                            .setElecMoney(elecMoney)
-                            .setServiceMoney(serviceMoney)
-                            .setServiceMoneyDiscount(serviceMoneyDiscount)
-                            .setDiscountAmount(discountAmount)
-                            .setTotalPower(totalPower)
-                            .setAvgOrderElec(avgPower)
-                            .setAvgOrderMoney((int) avgOrderMoney)
-                            .setAvgConnectorElec(totalPower / (stationConnectorCountMap.get(entry.getKey()) * (LocalDate.now().minusMonths(1).lengthOfMonth())));
-                })).values();
-    }
-}

+ 0 - 54
car-wash-admin/src/main/java/com/kym/admin/mq/consumer/UserCouponConsumer.java

@@ -1,54 +0,0 @@
-package com.kym.admin.mq.consumer;
-
-import com.alibaba.fastjson2.JSONObject;
-
-import com.kym.entity.common.Queues;
-import com.kym.entity.miniapp.UserCoupon;
-import com.kym.service.miniapp.UserCouponService;
-import com.rabbitmq.client.Channel;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.amqp.core.Message;
-import org.springframework.amqp.rabbit.annotation.RabbitHandler;
-import org.springframework.amqp.rabbit.annotation.RabbitListener;
-import org.springframework.stereotype.Component;
-
-import java.io.IOException;
-import java.util.List;
-
-
-/**
- * 用户优惠券消费者
- *
- * @author skyline
- */
-@Slf4j
-@Component
-public class UserCouponConsumer {
-
-    private final UserCouponService userCouponService;
-
-    public UserCouponConsumer(UserCouponService userCouponService) {
-        this.userCouponService = userCouponService;
-    }
-
-    @RabbitHandler
-    @RabbitListener(queues = Queues.DELAY_USER_COUPON_QUEUE)
-    public void userCouponHandler(List<Message> messages, Channel channel) {
-        try {
-            List<UserCoupon> userCouponList = messages.stream()
-                    .map(item -> JSONObject.parseObject(new String(item.getBody()), UserCoupon.class)).toList();
-
-            // 存入 t_user_coupon
-            userCouponService.saveBatch(userCouponList);
-
-            // todo 推送用户收到优惠券
-
-            // 消息逐个ack
-            for (Message message : messages) {
-                channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
-            }
-        } catch (IOException e) {
-            e.printStackTrace();
-        }
-    }
-}