skyline 2 лет назад
Родитель
Сommit
03c3f9e442

+ 4 - 4
admin-web/src/views/admin/station/endpoint/index.vue

@@ -69,10 +69,10 @@
           查询
         </el-button>
 
-        <el-button class="ml10" plain size="default" type="success" @click="handleUploadVisible">
-          <SvgIcon name="ele-Upload"/>
-          上传
-        </el-button>
+<!--        <el-button class="ml10" plain size="default" type="success" @click="handleUploadVisible">-->
+<!--          <SvgIcon name="ele-Upload"/>-->
+<!--          上传-->
+<!--        </el-button>-->
       </el-form>
 
       <el-table

+ 1 - 1
admin-web/src/views/admin/station/endpoint/upload.vue

@@ -271,7 +271,7 @@ let  fields=state.excelForm.importFields.filter(k => !!k);
     dataList
   }
 
-  $body(`station/importData`, params).then(() => {
+  $body(`station/importStation`, params).then(() => {
     Msg.message(`导入成功`)
     state.importLoading = false;
     emit('on-import-finish')

+ 16 - 3
admin-web/src/views/admin/station/list/index.vue

@@ -47,9 +47,14 @@
           查询
         </el-button>
 
-        <el-button  v-auth="'station.add'"   size="default" plain  type="success" class="ml10" @click="onRowClick('add',null)">
-          <SvgIcon name="ele-FolderAdd"/>
-          新增
+<!--        <el-button  v-auth="'station.add'"   size="default" plain  type="success" class="ml10" @click="onRowClick('add',null)">-->
+<!--          <SvgIcon name="ele-FolderAdd"/>-->
+<!--          新增-->
+<!--        </el-button>-->
+
+        <el-button class="ml10" plain size="default" type="success" @click="handleUploadVisible">
+          <SvgIcon name="ele-Upload"/>
+          导入站点
         </el-button>
 
       </el-form>
@@ -119,6 +124,7 @@
   </div>
   <StationDialog ref="stationDialogRef" @refresh="loadData(true)"/>
   <SettleDialog ref="settleDialogRef" />
+  <upload ref="upload_ref"></upload>
 </template>
 
 <script setup lang="ts" name="StationList">
@@ -134,11 +140,14 @@ import {useRouter} from "vue-router";
 import ExtImage from "/@/components/form/ExtImage.vue";
 const router = useRouter();
 const StationDialog = defineAsyncComponent(() => import("/@/views/admin/station/list/dialog.vue"));
+const Upload = defineAsyncComponent(() => import("/@/views/admin/station/list/upload.vue"));
+
 
 //定义引用
 const queryRef = ref();
 const stationDialogRef = ref();
 const settleDialogRef = ref();
+const upload_ref = ref();
 
 //定义变量
 const state = reactive({
@@ -284,6 +293,10 @@ const handleSettleShow = () => {
   settleDialogRef.value?.open();
 }
 
+const handleUploadVisible = () => {
+  upload_ref.value.open();
+}
+
 
 //endregion
 

+ 476 - 0
admin-web/src/views/admin/station/list/upload.vue

@@ -0,0 +1,476 @@
+<template>
+  <el-dialog
+      :title="'导入『电桩信息』'"
+      v-model="state.dialog.isShowDialog"
+      width="75%"
+      destroy-on-close
+      :close-on-click-modal="false"
+      :close-on-press-escape="false"
+      draggable
+      class="pd0 dialog-padding-none"
+  >
+
+    <el-tabs class="demo-tabs">
+      <el-tab-pane>
+        <template #label>
+        <span class="custom-tabs-label">
+          <SvgIcon name="ele-Grid"></SvgIcon>
+          <span>Excel导入</span>
+        </span>
+        </template>
+
+        <el-button @click="handleOpenFile" plain type="success" class="mt5"> 请选择excel文件上传导入</el-button>
+        <el-text type="primary" class="ml5">{{ state.uploadFileName }} <SvgIcon v-if="state.uploadFileName" name="ele-Remove" @click="reset" color="var(--el-color-danger)"></SvgIcon></el-text>
+
+        <!--        <ext-upload
+                    v-model="state.excelForm.file"
+                    placeholder="请选择上传文件"
+                    tips="请选择excel文件上传导入"
+                    style="width: 100%"
+                    :limit="1"
+                    mime="excel"
+                    @on-success="handleUploadFileSuccess">
+                </ext-upload>-->
+
+      </el-tab-pane>
+
+    </el-tabs>
+
+
+
+    <div class="w100 mt5">
+      <div class="w100">
+        <el-scrollbar @scroll="handleFieldHeaderScroll" ref="fieldHeaderScrollRef" :min-size="0">
+          <div class="model-field-select-wrapper">
+            <div class="model-field-select-header" v-for="(field,idx) in state.excelForm.columns"
+                 :key="'select_'+idx">
+              <template v-if="idx===0">
+                <div style="width: 135px;height: 32px;line-height:32px;border:1px solid #eee;text-align: center;">导入列选择</div>
+              </template>
+              <el-select-v2 v-else
+                            v-model="state.excelForm.importFields[idx]"
+                            :options="state.excelForm.selectFields"
+                            style="width: 135px;height: 36px;border:none;display: inline-block;flex-shrink: 0;margin-right: 10px;"
+                            filterable
+                            clearable>
+              </el-select-v2>
+            </div>
+          </div>
+        </el-scrollbar>
+      </div>
+
+      <vxe-table
+          ref="excelRef"
+          border="full"
+          show-header-overflow
+          :show-footer="false"
+          :max-height="state.tableHeight"
+          :loading="false"
+          header-cell-class-name="task-list-header"
+          header-align="left"
+          empty-text=" "
+          @cell-click="handleCellClick"
+          :data="state.excelForm.data"
+          @scroll="handleDataTableScroll"
+          :row-config="{isHover:true,isCurrent:true}"
+          :tooltip-config="{zIndex:9999}"
+          :scroll-x="{enabled: true, gt: 100}"
+          :scroll-y="{enabled: true, gt: 100}">
+
+        <vxe-column
+            v-for="(field,idx) in state.excelForm.columns"
+            :key="idx"
+            :field="field.field"
+            :width="135"
+            :title="field.name"
+            show-overflow="title">
+          <template v-if="field.field==='idx'" #default="{row,rowIndex}">
+            <div class="w100  flex flex-align-items-center flex-justify-center  hover-parent">
+
+              <el-dropdown @command="handleRow($event,row,rowIndex)">
+                <el-text type="primary" class="hover-child ml5 cursor-pointer font12">        <span>{{ rowIndex+1}}</span></el-text>
+                <template #dropdown>
+                  <el-dropdown-item command="setHeader" style="color:var(--el-color-success)" class="font12">设为表头</el-dropdown-item>
+                  <el-dropdown-item command="delete" style="color:var(--el-color-danger)" class="font12">删除本行</el-dropdown-item>
+                </template>
+              </el-dropdown>
+            </div>
+          </template>
+        </vxe-column>
+      </vxe-table>
+
+    </div>
+
+    <template #footer>
+				<span class="dialog-footer">
+					<el-button @click="onClose" size="default">取 消</el-button>
+					<el-button type="primary" @click="handleConfirm" :loading="state.importLoading" size="default">导入</el-button>
+				</span>
+    </template>
+  </el-dialog>
+</template>
+
+<script setup lang="ts" name="EndpointImportDialog">
+import {reactive, onMounted, nextTick, ref, toRaw, unref} from 'vue';
+
+//定义初始变量,重置使用
+import {useFileDialog} from '@vueuse/core'
+
+import {$body, $post} from "/@/utils/request";
+import {Msg} from "/@/utils/message";
+import {VxeTable, VxeColumn, VxeTableInstance} from "vxe-table";
+import 'vxe-table/lib/style.css'
+import {useDebounceFn, useThrottleFn} from '@vueuse/core'
+
+import {ElScrollbar} from 'element-plus'
+import * as XLSX from 'xlsx'
+
+const fieldHeaderScrollRef = ref<InstanceType<typeof ElScrollbar>>();
+const excelRef = ref<VxeTableInstance>();
+
+
+const {files, open: handleOpenFile, reset, onChange:handleFileChange} = useFileDialog(
+    {
+      multiple: false,
+      accept: '.xls,.xlsx, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/vnd.ms-excel'
+    })
+
+
+handleFileChange((files)=>{
+  parseExcel()
+})
+
+const initState = () => ({
+  dialog: {
+    isShowDialog: false,
+    type: '',
+    title: '',
+    submitTxt: '',
+  },
+  initColumnList: [{field: 'idx', name: '#', fixed: 'left'}],
+  excelForm: {
+    file: '',
+    rowHeaderIndex: 0,
+    rowContentIndex: 1,
+    columns: [] as any[],
+    sheet: '',
+    sheets: [] as string[],
+    data: [],
+    loading: false,
+    importFields: [] as string[],
+    selectFields: []
+  },
+  uploadFileName: '' as String | null,
+  importLoading: false,
+  tableHeight: 400,
+  fieldList:[
+    {label:'序号ID',value:'id'},
+    {label:'站点ID',value:'stationId'},
+    {label:'站点名称',value:'stationName'},
+    {label:'设备短编号',value:'shortId'},
+    {label:'充电桩SN',value:'equipmentId'},
+    {label:'充电口SN',value:'connectorId'},
+    {label:'车位编号',value:'parkingNo'},
+  ]
+})
+
+// 定义变量内容
+const state = reactive(initState());
+
+const emit = defineEmits(['on-import-finish']);
+
+
+onMounted(() => {
+
+})
+
+const open = () => {
+  state.dialog.isShowDialog = true;
+
+  nextTick(() => {
+    let clientHeight = document.body.clientHeight;
+    let th = clientHeight - 60 - 120 - 300
+    state.tableHeight = th;
+  })
+  state.excelForm.selectFields = state.fieldList.map((k: any) => {
+    return {
+      value: k.value,
+      label: k.label
+    }
+  })
+}
+
+// 关闭弹窗
+const onClose = () => {
+  state.dialog.isShowDialog = false;
+  Object.assign(state, initState())
+  reset();
+};
+
+
+const handleCellClick = (e: any) => {
+  let {row, rowIndex, $rowIndex, column, columnIndex, $columnIndex} = e;
+  if (columnIndex === 0) {
+    return;
+  }
+  let val = state.excelForm.data[rowIndex][column.property]
+  Msg.prompt(`修改导入的数据`, '修改',
+      {
+        draggable: true,
+        type: 'primary',
+        value: val
+      }
+  ).then((res: any) => {
+    let {value, action} = res;
+    if (action === 'confirm') {
+      state.excelForm.data[rowIndex][column.property] = value
+    }
+  })
+}
+
+const handleConfirm = () => {
+  let checks: Array<string> = [];
+  let checkPass= true;
+  state.excelForm.importFields.forEach(key => {
+    if (key) {
+      if (checks.includes(key)) {
+        checkPass = false;
+        Msg.message('表头不可重复', 'error')
+        return false;
+      } else {
+        checks.push(key)
+      }
+    }
+  })
+  if(!checkPass)return;
+  debounceImport();
+}
+
+const debounceImport = useThrottleFn(() => {
+  state.importLoading = true;
+  let fieldIndexes: Array<number> = []
+  state.excelForm.importFields.forEach((key, idx) => {
+    if (key) {
+      fieldIndexes.push(idx - 1);
+    }
+  })
+let  fields=state.excelForm.importFields.filter(k => !!k);
+  let dataList : Array<any> = [];
+  state.excelForm.data.forEach(data => {
+    let item ={}
+    let arr: Array<any> = []
+    fieldIndexes.forEach((idx, i) => {
+      item[fields[i]] = data[`f${idx}`] || ""
+    })
+    dataList.push(item)
+  })
+
+  let params = {
+    fields: state.excelForm.importFields.filter(k => !!k),
+    fieldIndexes,
+    dataList
+  }
+
+  $body(`station/importStation`, params).then(() => {
+    Msg.message(`导入成功`)
+    state.importLoading = false;
+    emit('on-import-finish')
+    state.dialog.isShowDialog = false;
+  }).catch(() => {
+    state.importLoading = false;
+  })
+}, 1500)
+
+//表头选择器滚动
+const handleFieldHeaderScroll = (ev: any) => {
+  let {scrollLeft, scrollTop} = ev;
+  // console.log(scrollLeft, scrollTop, ev)
+  if (scrollLeft >= 0) {
+    let st = excelRef.value.getScroll();
+    const el = excelRef.value?.$el.querySelector('.vxe-table--body-wrapper')
+    if (el) {
+      el.scrollLeft = scrollLeft
+    }
+  }
+}
+
+//数据表格滚动
+const handleDataTableScroll = (ev: any) => {
+  let {scrollLeft} = ev;
+  // console.log(type, scrollLeft, scrollHeight)
+  if (scrollLeft >= 0) {
+    fieldHeaderScrollRef.value?.setScrollLeft(scrollLeft);
+  }
+}
+
+const handleRow = (command: string, row: any, rowIndex: number) => {
+  if (command === 'setHeader') {
+    let tmpHeaders: any[] = []
+    let tmpHeader = state.excelForm.data[rowIndex]
+    Object.keys(tmpHeader).forEach((key, i) => {
+      if (key.startsWith("f")) {
+        let header = tmpHeader[key]
+        let find = state.fieldList.find((k: any) => k.name == header);
+        if (find) {
+          state.excelForm.importFields[i + 1] = find.label;
+        } else {
+          state.excelForm.importFields[i + 1] = "";
+        }
+        tmpHeaders.push({
+          field: `f${i}`,
+          name: header
+        });
+      }
+    })
+    state.excelForm.columns = state.initColumnList.concat(tmpHeaders)
+    state.excelForm.data.splice(rowIndex, 1)
+    excelRef.value?.reloadData(state.excelForm.data);
+  } else if (command === 'delete') {
+    state.excelForm.data.splice(rowIndex, 1)
+    excelRef.value?.reloadData(state.excelForm.data);
+  }
+}
+
+const parseExcel = (sheetName: string = "") => {
+  // console.log(sheetName, state.excelForm.sheet,files)
+  // if(sheetName==state.excelForm.sheet&&state.excelForm.sheet){
+  //   return;
+  // }
+  if (!files || !files.value || !files.value[0]) {
+    state.excelForm.columns = []
+    excelRef.value?.reloadData([])
+    state.uploadFileName = null;
+    state.excelForm.sheets = []
+    return;
+  }
+  // console.log(files)
+  Msg.showLoading('解析中...')
+  state.uploadFileName = files.value[0].name;
+  let reader = new FileReader();
+  reader.onload = function () {
+    // console.log(reader)
+
+    let fileData = reader.result;
+    let wb = XLSX.read(fileData, {type: 'binary', cellDates: true});
+    state.excelForm.sheets = wb.SheetNames;
+    // {header:1} 取消标题列.
+    // console.log(wb.SheetNames)
+    let sheet = sheetName || wb.SheetNames[0];
+    state.excelForm.sheet = sheet;
+    let rowList: (any) = XLSX.utils.sheet_to_json(wb.Sheets[sheet], {header: 1});
+    // console.log(rowList)
+    let maxColumnLength = 1;
+    rowList.forEach((row: any, idx: number) => {
+      // console.log(row)
+      if (idx < 10) {
+        maxColumnLength = Math.max(maxColumnLength, row.length);
+      }
+    })
+
+    // console.log(maxColumnLength, rowList)
+    let tmpHeaders: Array<any> = []
+    let headers = rowList[state.excelForm.rowHeaderIndex];
+    for (let i = 0; i < maxColumnLength; i++) {
+      let header = i >= headers.length ? '' : headers[i];
+      let find = state.fieldList.find((k: any) => k.name == header);
+      if (find) {
+        state.excelForm.importFields[i + 1] = find.cname;
+      } else {
+        state.excelForm.importFields[i + 1] = "";
+      }
+      tmpHeaders.push({
+        field: `f${i}`,
+        name: header
+      });
+
+    }
+    state.excelForm.columns = state.initColumnList.concat(tmpHeaders)
+    // console.log(state.excelForm.columns)
+
+    let tmpContents: any[] = []
+    for (let i = state.excelForm.rowContentIndex; i < rowList.length; i++) {
+      let dl = rowList[i];
+      let rowItem = {}
+      dl.forEach((rowValue: any, columnIdx: number) => {
+        rowItem[`f${columnIdx}`] = rowValue
+      })
+      tmpContents.push(rowItem)
+    }
+    state.excelForm.data = tmpContents;
+    state.excelForm.loading = false;
+    excelRef.value?.reloadData(state.excelForm.data)
+    // data.exportTableData = rowObj;
+    Msg.hideLoading();
+  };
+  // 已二进制的形式读取文件
+  reader.readAsBinaryString(unref(files)[0]);
+  // 导入标识改为true
+  // data.exportSign = true;
+}
+
+const handleClick = (sheet: string) => {
+  parseExcel(sheet)
+  // handleRow("setHeader",state.excelForm.data[0],0)
+}
+
+/*
+onChange = ((files) => {
+  parseExcel();
+})
+*/
+
+
+defineExpose({
+  open
+})
+</script>
+
+<style scoped lang="scss">
+.custom-tabs-label {
+  display: inline-flex;
+  align-items: center;
+  align-content: center;
+  justify-content: space-between;
+}
+
+.model-field-select-wrapper {
+  width: 100%;
+  display: inline-flex;
+}
+
+.sheet-item {
+  width: 135px;
+  border-right: 2px solid #ddd;
+  border-bottom: 2px solid #ddd;
+  text-align: center;
+  cursor: pointer;
+}
+
+.model-field-select-header {
+  width: 135px;
+  height: 36px;
+  //overflow-x: auto;
+  //display: inline-flex;
+  //flex-wrap: wrap;
+
+  :deep(.el-select-v2__wrapper) {
+    border: 1px solid #eee !important;
+    border-radius: 0px !important;
+  }
+}
+
+:deep(.vxe-loading) {
+  display: none !important;
+}
+
+.pd0 {
+  :deep(.el-dialog__body) {
+    padding: 0 !important;
+  }
+}
+
+.vxe-table--tooltip-wrapper{
+  z-index: 10000 !important;
+}
+
+</style>

+ 3 - 11
admin/src/main/java/com/kym/admin/controller/StationController.java

@@ -75,17 +75,9 @@ public class StationController {
         return R.success();
     }
 
-    // 新增站点
-    @SysLog("初始化新站点信息")
-    @PostMapping("/addStation")
-    R<?> addStation(@RequestBody List<ConnectorVo> stationInfo) {
-        stationService.addStation(stationInfo);
-        return R.success();
-    }
-
-    @PostMapping("/importData")
-    R<?> importData(@RequestBody JSONObject data){
-        stationService.importData(data);
+    @PostMapping("/importStation")
+    R<?> importStation(@RequestBody JSONObject data){
+        stationService.importStation(data);
         return R.success(data);
     }
 

+ 5 - 12
service/src/main/java/com/kym/service/admin/StationService.java

@@ -4,13 +4,10 @@ import com.alibaba.fastjson2.JSONObject;
 import com.fasterxml.jackson.core.JsonProcessingException;
 import com.github.yulichang.base.MPJBaseService;
 import com.kym.entity.admin.Station;
-import com.kym.entity.admin.vo.ConnectorVo;
 import com.kym.entity.admin.vo.StationVo;
 import com.kym.entity.enplus.EnStationStatsInfo;
 import com.kym.entity.enplus.EnStationStatusInfo;
-import org.springframework.transaction.annotation.Transactional;
 
-import java.util.Collection;
 import java.util.List;
 
 /**
@@ -23,19 +20,15 @@ import java.util.List;
  */
 public interface StationService extends MPJBaseService<Station> {
 
-    public List<StationVo> queryStationInfo(int pageNum, int pageSize) throws JsonProcessingException;
+    List<StationVo> queryStationInfo(int pageNum, int pageSize) throws JsonProcessingException;
 
-    public List<EnStationStatusInfo> stationStatus(String[] ids);
+    List<EnStationStatusInfo> stationStatus(String[] ids);
 
-    public EnStationStatsInfo stationStats(String stationId, String startTime, String endTime);
+    EnStationStatsInfo stationStats(String stationId, String startTime, String endTime);
 
-    public void pullEnStationInfos(String stationId);
-
-    @Transactional(rollbackFor = Exception.class)
+    void pullEnStationInfos(String stationId);
 
     void modifyStation(Station station);
 
-    void addStation(List<ConnectorVo> connectorVos);
-
-    void importData(JSONObject data);
+    void importStation(JSONObject data);
 }

+ 1 - 2
service/src/main/java/com/kym/service/admin/impl/ActivityServiceImpl.java

@@ -21,7 +21,6 @@ import com.kym.service.jobs.DelayService;
 import com.kym.service.miniapp.UserCouponService;
 import com.kym.service.miniapp.UserRechargeRightsService;
 import com.kym.service.miniapp.UserService;
-import com.kym.service.queue.sender.MessageSender;
 import com.kym.service.queue.sender.UserCouponSender;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.BeanUtils;
@@ -70,7 +69,7 @@ public class ActivityServiceImpl extends MPJBaseServiceImpl<ActivityMapper, Acti
 
     public ActivityServiceImpl(ActivityStationService activityStationService, RechargeRightsService rechargeRightsService, CouponService couponService,
                                UserRechargeRightsService userRechargeRightsService, StationService stationService,
-                               @Lazy DelayService<DelayActivity> activityDelayService, BannerService bannerService, UserService userService, UserCouponService userCouponService,  UserCouponSender userCouponSender) {
+                               @Lazy DelayService<DelayActivity> activityDelayService, BannerService bannerService, UserService userService, UserCouponService userCouponService, UserCouponSender userCouponSender) {
         this.activityStationService = activityStationService;
         this.rechargeRightsService = rechargeRightsService;
         this.couponService = couponService;

+ 0 - 8
service/src/main/java/com/kym/service/admin/impl/EquipmentInfoServiceImpl.java

@@ -24,12 +24,4 @@ import java.util.stream.Collectors;
 @DS("db-admin")
 public class EquipmentInfoServiceImpl extends MyBaseServiceImpl<EquipmentInfoMapper, EquipmentInfo> implements EquipmentInfoService {
 
-    @PostConstruct
-    private void init() {
-        // 手动切换数据源
-        DynamicDataSourceContextHolder.push("db-admin");
-        KymCache.INSTANCE.putConnectorId2ParkingNo(list().stream().collect(Collectors.toMap(equipmentInfo -> equipmentInfo.getEquipmentId().concat("1"), EquipmentInfo::getParkingNo)));
-        DynamicDataSourceContextHolder.poll();
-    }
-
 }

+ 13 - 51
service/src/main/java/com/kym/service/admin/impl/StationServiceImpl.java

@@ -11,7 +11,6 @@ import com.kym.common.exception.BusinessException;
 import com.kym.common.utils.AESUtil;
 import com.kym.common.utils.CommUtil;
 import com.kym.entity.admin.*;
-import com.kym.entity.admin.vo.ConnectorVo;
 import com.kym.entity.admin.vo.StationVo;
 import com.kym.entity.enplus.EnEquipmentInfo;
 import com.kym.entity.enplus.EnStationStatsInfo;
@@ -21,7 +20,6 @@ import com.kym.service.MyBaseServiceImpl;
 import com.kym.service.admin.*;
 import com.kym.service.cache.KymCache;
 import com.kym.service.enplus.EnPlusService;
-import jakarta.annotation.PostConstruct;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.BeanUtils;
 import org.springframework.context.annotation.Lazy;
@@ -62,14 +60,6 @@ public class StationServiceImpl extends MyBaseServiceImpl<StationMapper, Station
         this.activityService = activityService;
     }
 
-    @PostConstruct
-    private void init() {
-        // 手动切换数据源
-        DynamicDataSourceContextHolder.push("db-admin");
-        KymCache.INSTANCE.putStationId2Name(list().stream().collect(Collectors.toMap(Station::getStationId, Station::getStationName)));
-        DynamicDataSourceContextHolder.poll();
-    }
-
     @Override
     @DynamicCache // 方法的返回结果加一层方法缓存,5分钟内不变
     public List<StationVo> queryStationInfo(int pageNum, int pageSize) {
@@ -205,10 +195,9 @@ public class StationServiceImpl extends MyBaseServiceImpl<StationMapper, Station
 
         DynamicDataSourceContextHolder.poll();
 
-        // 将充电站相关数据写入KymCache
+        // 缓存更新,其他数据在站点导入时更新 com.kym.service.admin.impl.StationServiceImpl.importStation
         KymCache.INSTANCE.putStationId2Name(Map.of(stationVo.getStationId(), stationVo.getStationName()));
 
-
     }
 
 
@@ -219,59 +208,26 @@ public class StationServiceImpl extends MyBaseServiceImpl<StationMapper, Station
                 .eq(Station::getStationId, station.getStationId()).update();
     }
 
-    @Override
-    @Transactional
-    public void addStation(List<ConnectorVo> connectorVos) {
-        // 1、组装t_station数据
-
-        // 2、组装t_equipment_info数据
-        var equipmentInfos = connectorVos.stream().map(item -> {
-            var equipmentInfo = new EquipmentInfo();
-            BeanUtils.copyProperties(item, equipmentInfo);
-            return equipmentInfo;
-        }).toList();
-        equipmentInfoService.saveBatch(equipmentInfos);
-
-        // 3、组装t_connector_info数据
-        var connectorInfos = connectorVos.stream().map(item -> {
-            var connectorInfo = new ConnectorInfo();
-            BeanUtils.copyProperties(item, connectorInfo);
-            return connectorInfo;
-        }).toList();
-        connectorInfoService.saveBatch(connectorInfos);
-
-        // 4、组装t_equipment_relation数据
-        var equipmentRelations = connectorVos.stream().map(item -> {
-            var equipmentRelation = new EquipmentRelation();
-            BeanUtils.copyProperties(item, equipmentRelation);
-            return equipmentRelation;
-        }).toList();
-        equipmentRelationService.saveBatch(equipmentRelations);
-
-        // 5、更新KymCache数据
-        // TODO redis发布订阅?
-    }
 
     @Override
     @Transactional
-    public void importData(JSONObject data) {
-        log.debug("导入数据:{}", data.toString());
+    public void importStation(JSONObject data) {
         var fieldIndexes = data.getJSONArray("fieldIndexes");
         if (fieldIndexes.size() != 7) {
             throw new BusinessException("导入数据格式错误,请正确匹配对应数据列");
         }
 
         String dataList = data.getString("dataList");
-        var list = JSON.parseArray(dataList, EquipmentRelation.class);
+        var equipmentRelations = JSON.parseArray(dataList, EquipmentRelation.class);
 
         // t_station
-        var stations = list.stream().filter(CommUtil.distinctByKey(EquipmentRelation::getStationId))
+        var stations = equipmentRelations.stream().filter(CommUtil.distinctByKey(EquipmentRelation::getStationId))
                 .map(item -> Map.of("stationId", item.getStationId(), "stationName", item.getStationName())).toList();
         var stationList = stations.stream().map(map -> new Station().setStationId(map.get("stationId")).setStationName(map.get("stationName"))).toList();
         saveBatch(stationList);
 
         // t_equipment_info
-        var equipmentInfoList = list.stream().map(item -> {
+        var equipmentInfoList = equipmentRelations.stream().map(item -> {
             var equipmentInfo = new EquipmentInfo();
             BeanUtils.copyProperties(item, equipmentInfo, "id");
             return equipmentInfo;
@@ -279,7 +235,7 @@ public class StationServiceImpl extends MyBaseServiceImpl<StationMapper, Station
         equipmentInfoService.saveBatch(equipmentInfoList);
 
         // t_connector_info
-        var connectorInfoList = list.stream().map(item -> {
+        var connectorInfoList = equipmentRelations.stream().map(item -> {
             var connectorInfo = new ConnectorInfo();
             BeanUtils.copyProperties(item, connectorInfo, "id");
             return connectorInfo;
@@ -287,7 +243,13 @@ public class StationServiceImpl extends MyBaseServiceImpl<StationMapper, Station
         connectorInfoService.saveBatch(connectorInfoList);
 
         // t_equipment_relation
-        equipmentRelationService.saveBatch(list);
+        equipmentRelationService.saveBatch(equipmentRelations);
+
+        // 缓存更新
+        KymCache.INSTANCE.putStationId2Name(stations.stream().collect(Collectors.toMap(map -> map.get("stationId"), map -> map.get("stationName"))));
+        KymCache.INSTANCE.putConnectorId2ShortId(equipmentRelations.stream().collect(Collectors.toMap(EquipmentRelation::getConnectorId, EquipmentRelation::getShortId)));
+        KymCache.INSTANCE.putConnectorId2StationId(equipmentRelations.stream().collect(Collectors.toMap(EquipmentRelation::getConnectorId, EquipmentRelation::getStationId)));
+        KymCache.INSTANCE.putConnectorId2ParkingNo(equipmentRelations.stream().collect(Collectors.toMap(EquipmentRelation::getConnectorId, EquipmentRelation::getParkingNo)));
     }
 
 }

+ 0 - 5
service/src/main/java/com/kym/service/cache/KymCache.java

@@ -26,7 +26,6 @@ public enum KymCache {
 
 
     private static ConcurrentHashMap<String, String> CONNECTOR_ID_SHORT_ID_MAPPING = new ConcurrentHashMap<>();
-    private static ConcurrentHashMap<Long, List<String>> ADMIN_USER_STATIONS = new ConcurrentHashMap<>();
 
 
     public void putConnectorId2ShortId(Map<String, String> map) {
@@ -149,19 +148,15 @@ public enum KymCache {
 
             var connectorId2ShortId = equipmentRelations.stream().collect(Collectors.toMap(EquipmentRelation::getConnectorId, EquipmentRelation::getShortId));
             KymCache.INSTANCE.putConnectorId2ShortId(connectorId2ShortId);
-            connectorId2ShortId.forEach((k, v) -> redisTemplate.opsForValue().set(RedisKeys.CONNECTOR_ID_TO_SHORT_ID + k, v));
 
             var connector2Station = equipmentRelations.stream().collect(Collectors.toMap(EquipmentRelation::getConnectorId, EquipmentRelation::getStationId));
             KymCache.INSTANCE.putConnectorId2StationId(connector2Station);
-            connector2Station.forEach((k, v) -> redisTemplate.opsForValue().set(RedisKeys.CONNECTOR_ID_TO_STATION_ID + k, v));
 
             var stationId2Name = stationService.list().stream().collect(Collectors.toMap(Station::getStationId, Station::getStationName));
             KymCache.INSTANCE.putStationId2Name(stationId2Name);
-            stationId2Name.forEach((k, v) -> redisTemplate.opsForValue().set(RedisKeys.STATION_ID_TO_NAME + k, v));
 
             var connectorId2ParkingNo = equipmentRelations.stream().collect(Collectors.toMap(EquipmentRelation::getConnectorId, EquipmentRelation::getParkingNo));
             KymCache.INSTANCE.putConnectorId2ParkingNo(connectorId2ParkingNo);
-            connectorId2ParkingNo.forEach((k, v) -> redisTemplate.opsForValue().set(RedisKeys.CONNECTOR_ID_TO_PARKING_NO + k, v));
         }
     }
 }