Kaynağa Gözat

Merge remote-tracking branch 'origin/master'

liao-sea 1 yıl önce
ebeveyn
işleme
65fb07f547

+ 13 - 1
src/main/java/com/hz/employmentsite/controller/baseSettings/SiteUserController.java

@@ -1,6 +1,7 @@
 package com.hz.employmentsite.controller.baseSettings;
 
 import com.github.pagehelper.PageInfo;
+import com.hz.employmentsite.filter.exception.BaseErrorEnum;
 import com.hz.employmentsite.filter.exception.BaseResponse;
 import com.hz.employmentsite.filter.exception.RespGenerstor;
 import com.hz.employmentsite.model.SelectProps;
@@ -100,9 +101,20 @@ public class SiteUserController {
 
     @ResponseBody
     @PostMapping("/delete")
-    public BaseResponse<Integer> delete(@RequestBody List<String> idList){
+    public BaseResponse<Integer> delete(@RequestBody List<String> idList) {
         return RespGenerstor.success(userInfoService.delete(idList));
     }
 
+    @PostMapping("/importSiteUser")
+    public BaseResponse<Object> importSiteUser(@RequestBody List<SiteUserVo> dataList) {
+        List<SiteUserVo> result = userInfoService.importSiteUser(dataList, accountService.getLoginUserID());
+
+        if (result != null && result.size() > 0) {
+            return RespGenerstor.fail(BaseErrorEnum.IMPORT_DATA_ERROR, result);
+        } else {
+            return RespGenerstor.success(true);
+        }
+    }
+
 
 }

+ 107 - 5
src/main/java/com/hz/employmentsite/services/impl/baseSettings/SiteUserImpl.java

@@ -3,13 +3,11 @@ package com.hz.employmentsite.services.impl.baseSettings;
 import com.github.pagehelper.PageHelper;
 import com.github.pagehelper.PageInfo;
 import com.hz.employmentsite.filter.exception.BaseException;
-import com.hz.employmentsite.mapper.PcSiteUserMapper;
-import com.hz.employmentsite.mapper.SysRoleMapper;
-import com.hz.employmentsite.mapper.SysUserMapper;
-import com.hz.employmentsite.mapper.SysUserSysRoleMapper;
+import com.hz.employmentsite.mapper.*;
 import com.hz.employmentsite.mapper.cquery.UserInfoCQuery;
 import com.hz.employmentsite.model.*;
 import com.hz.employmentsite.services.service.baseSettings.SiteUserService;
+import com.hz.employmentsite.services.service.system.DictionaryService;
 import com.hz.employmentsite.util.StringUtils;
 import com.hz.employmentsite.vo.baseSettings.SiteUserVo;
 import net.sourceforge.pinyin4j.PinyinHelper;
@@ -25,6 +23,7 @@ import java.util.ArrayList;
 import java.util.Date;
 import java.util.List;
 import java.util.UUID;
+import java.util.stream.Collectors;
 
 @Service("SiteUserService")
 public class SiteUserImpl implements SiteUserService {
@@ -47,6 +46,12 @@ public class SiteUserImpl implements SiteUserService {
     @Autowired
     private SysUserSysRoleMapper sysUserSysRoleMapper;
 
+    @Autowired
+    private PcSiteMapper siteMapper;
+
+    @Autowired
+    private DictionaryService dictionaryService;
+
     @Override
     public PageInfo<SiteUserVo> getList(int pageIndex, int pageSize, List<String> siteUserIDList, String siteUserName, String siteID, String roleName, String regionCode, String userNo) {
         PageHelper.startPage(pageIndex, pageSize);
@@ -193,7 +198,104 @@ public class SiteUserImpl implements SiteUserService {
         return result;
     }
 
-    public String StrToPinYin(String chinese){
+    /**
+     * 数据导入
+     *
+     * @param dataList    excel数据
+     * @param loginUserId 当前登录用户ID
+     * @return 导入结果
+     */
+    @Override
+    public List<SiteUserVo> importSiteUser(List<SiteUserVo> dataList, String loginUserId) {
+        if (dataList.size() <= 0)
+            throw new BaseException("", "请添加导入数据!");
+        // 所属驿站
+        List<PcSite> siteList = siteMapper.selectByExample(null);
+        // 已存在的驿站工作人员
+        List<PcSiteUser> pcSiteUsers = pcSiteUserMapper.selectByExample(null);
+        // 用户类型字典数据
+        List<SysDictionaryItem> userTypeList = dictionaryService.getDictionaryItemList("UserType");
+        // 性别字典数据
+        List<SysDictionaryItem> genderList = dictionaryService.getDictionaryItemList("Gender");
+
+        // 最终结果
+        List<SiteUserVo> resultList = new ArrayList<>();
+
+        dataList.forEach(item -> {
+            String errorInfo = "";
+
+            // 数据内容为空判断
+            if (stringUtils.IsNullOrEmpty(item.siteUserName)) {
+                errorInfo += "请填写姓名!";
+            }
+            if (stringUtils.IsNullOrEmpty(item.userNo)) {
+                errorInfo += "请填写工号!";
+            } else {
+                String siteUserID = pcSiteUsers.stream().filter(it -> it.getUserNo() != null && it.getUserNo().equals(item.getUserNo().trim())).findFirst().orElse(new PcSiteUser()).getSiteUserID();
+                if (!stringUtils.IsNullOrEmpty(siteUserID)) {
+                    errorInfo += "工号重复!";
+                }
+            }
+            if (stringUtils.IsNullOrEmpty(item.genderName)) {
+                errorInfo += "请填写性别!";
+            } else {
+                item.gender = genderList.stream().filter(it -> it.getName().equals(item.getGenderName().trim()))
+                        .findFirst().orElse(new SysDictionaryItem()).getValue();
+                if (item.gender == null) {
+                    errorInfo += "性别不存在!";
+                }
+            }
+            if (stringUtils.IsNullOrEmpty(item.mobile)) {
+                errorInfo += "请填写联系电话!";
+            } else {
+                String siteUserID = pcSiteUsers.stream().filter(it -> it.getMobile() != null && it.getMobile().equals(item.getMobile().trim())).findFirst().orElse(new PcSiteUser()).getSiteUserID();
+                if (!stringUtils.IsNullOrEmpty(siteUserID)) {
+                    errorInfo += "联系电话重复!";
+                }
+            }
+            if (stringUtils.IsNullOrEmpty(item.idCard)) {
+                errorInfo += "请填写身份证号码!";
+            }
+            if (stringUtils.IsNullOrEmpty(item.roleName)) {
+                errorInfo += "请填写用户类型!";
+            } else {
+                item.roleID = userTypeList.stream().filter(it -> it.getName().equals(item.getRoleName().trim()))
+                        .findFirst().orElse(new SysDictionaryItem()).getValue();
+                if (item.roleID == null) {
+                    errorInfo += "用户类型不存在!";
+                }
+            }
+            if (stringUtils.IsNullOrEmpty(item.siteName)) {
+                errorInfo += "请填写所属驿站!";
+            } else {
+                item.siteID = siteList.stream().filter(it -> it.getSiteName().equals(item.getSiteName().trim()))
+                        .findFirst().orElse(new PcSite()).getSiteID();
+                if (stringUtils.IsNullOrEmpty(item.siteID)) {
+                    errorInfo += "驿站不存在!";
+                }
+            }
+
+            // 检查结果填充
+            if (stringUtils.IsNullOrEmpty(errorInfo)) {
+                item.setSiteUserID(UUID.randomUUID().toString());
+                resultList.add(item);
+            } else {
+                item.setErrorMessage(errorInfo);
+            }
+        });
+
+        // 返回结果
+        if (dataList.stream().filter(it -> !stringUtils.IsNullOrEmpty(it.errorMessage)).collect(Collectors.toList()).size() > 0)
+            return dataList;
+
+        // 保存到数据
+        resultList.forEach(item -> {
+            save(item, loginUserId);
+        });
+        return null;
+    }
+
+    public String StrToPinYin(String chinese) {
         String pinyinStr = "";
         char[] newChar = chinese.toCharArray();
         HanyuPinyinOutputFormat defaultFormat = new HanyuPinyinOutputFormat();

+ 9 - 0
src/main/java/com/hz/employmentsite/services/service/baseSettings/SiteUserService.java

@@ -19,4 +19,13 @@ public interface SiteUserService {
     Integer save(SiteUserVo data, String userId);
 
     Integer delete(List<String> idList);
+
+    /**
+     * 数据导入
+     *
+     * @param dataList    excel数据
+     * @param loginUserId 当前登录用户ID
+     * @return 导入结果
+     */
+    List<SiteUserVo> importSiteUser(List<SiteUserVo> dataList, String loginUserId);
 }

+ 3 - 0
src/main/java/com/hz/employmentsite/vo/baseSettings/SiteUserVo.java

@@ -39,4 +39,7 @@ public class SiteUserVo {
     @RegionID
     public String regionCode;
 
+    // 导入时的报错信息
+    public String errorMessage;
+
 }

BIN
src/main/resources/static/doc/template/驿站站点人员导入模板.xlsx


+ 2 - 0
vue/src/router/asyncModules/basesettings.ts

@@ -5,7 +5,9 @@ export default {
   'baseSettings/site/index': () => import('@/views/baseSettings/siteInfo/index.vue'),
   'baseSettings/site/add': () => import('@/views/baseSettings/siteInfo/edit.vue'),
   'baseSettings/site/edit': () => import('@/views/baseSettings/siteInfo/edit.vue'),
+  'baseSettings/site/detail': () => import('@/views/baseSettings/siteInfo/detail.vue'),
   'baseSettings/user/index': () => import('@/views/baseSettings/siteUser/index.vue'),
   'baseSettings/user/add': () => import('@/views/baseSettings/siteUser/edit.vue'),
   'baseSettings/user/edit': () => import('@/views/baseSettings/siteUser/edit.vue'),
+  'baseSettings/user/detail': () => import('@/views/baseSettings/siteUser/detail.vue'),
 };

+ 60 - 0
vue/src/views/baseSettings/siteInfo/detail.vue

@@ -0,0 +1,60 @@
+<template>
+  <div class="card-edit">
+    <a-divider orientation="left">驿站站点基本信息</a-divider>
+    <a-descriptions bordered>
+      <a-descriptions-item label="驿站编号">{{ siteInfo.siteCode }}</a-descriptions-item>
+      <a-descriptions-item label="站点名称">{{ siteInfo.siteName }}</a-descriptions-item>
+      <a-descriptions-item label="所属机构">{{ siteInfo.institutionName }}</a-descriptions-item>
+      <a-descriptions-item label="所属县区">{{ siteInfo.regionName }}</a-descriptions-item>
+      <a-descriptions-item label="所属街道">{{ siteInfo.streetName }}</a-descriptions-item>
+      <a-descriptions-item label="详细地址">{{ siteInfo.detailAddress }}</a-descriptions-item>
+      <a-descriptions-item label="站点负责人">{{ siteInfo.fzrName }}</a-descriptions-item>
+      <a-descriptions-item label="联系电话">{{ siteInfo.fzrMobile }}</a-descriptions-item>
+      <a-descriptions-item label="经度">{{ siteInfo.siteLongitude }}</a-descriptions-item>
+      <a-descriptions-item label="纬度">{{ siteInfo.siteLatitude }}</a-descriptions-item>
+    </a-descriptions>
+    <a-divider orientation="left">其他信息</a-divider>
+    <a-descriptions bordered>
+      <a-descriptions-item label="备注">{{ siteInfo.remark }}</a-descriptions-item>
+    </a-descriptions>
+  </div>
+</template>
+
+<script setup lang="ts">
+import {onMounted, reactive} from "vue";
+import {getSiteByID} from "@/api/baseSettings/siteInfo";
+
+// 站点信息
+const siteInfo = reactive({
+  siteCode: "",
+  siteName: "",
+  institutionName: "",
+  regionName: "",
+  streetName: "",
+  detailAddress: "",
+  fzrName: "",
+  fzrMobile: "",
+  siteLongitude: "",
+  siteLatitude: "",
+  remark: "",
+})
+
+// 站点数据加载
+function loadData(siteID: any) {
+  getSiteByID(siteID).then((result: any) => {
+    Object.keys(siteInfo).forEach(key => {
+      siteInfo[key] = result[key];
+    })
+  });
+}
+
+// 页面初始化
+onMounted(() => {
+  const id = history.state.params?.id;
+  loadData(id);
+})
+</script>
+
+<style scoped>
+
+</style>

+ 13 - 6
vue/src/views/baseSettings/siteInfo/index.vue

@@ -94,6 +94,8 @@
         <template #bodyCell="{ column, text, record }">
           <template v-if="column.key === 'operation'">
             <div class="table-operation">
+              <a-button type="link" size="small" functioncode="T01010201" @click='onDetail(record.siteID)'>查看
+              </a-button>
               <a-button type="link" size="small"  functioncode="T01010203" @click='onEdit(record.siteID)' >编辑</a-button>
               <a-button type="link" size="small"  functioncode="T01010204" @click="onDel(record)" >删除</a-button>
             </div>
@@ -105,15 +107,15 @@
 </template>
 
 <script lang="ts">
-import {reactive, ref, computed, defineComponent, createVNode} from 'vue';
+import {computed, createVNode, defineComponent, reactive, ref} from 'vue';
 import {useTabsViewStore} from "@/store/modules/tabsView";
 import {DownOutlined, ExclamationCircleOutlined, UpOutlined} from '@ant-design/icons-vue';
-import type {FormInstance,TableColumnsType, TableProps} from 'ant-design-vue';
-import {getSiteList,delSite} from '@/api/baseSettings/siteInfo';
+import type {FormInstance, TableColumnsType, TableProps} from 'ant-design-vue';
+import {message, Modal, SelectProps} from "ant-design-vue";
+import {delSite, getSiteList} from '@/api/baseSettings/siteInfo';
 import {getRegionCodeList, getStreetCodeList} from "@/api/system/area/index";
 import BExportExcel from "@/components/basic/excel/exportExcel/exportExcel.vue";
 import {getPaginationTotalTitle} from "@/utils/common";
-import {message, Modal, SelectProps} from "ant-design-vue";
 import {getInstitutionDataList} from "@/api/baseSettings/institution";
 
 export default defineComponent({
@@ -148,7 +150,7 @@ export default defineComponent({
       {title: '详细地址', dataIndex: 'detailAddress', key: 'detailAddress', align: "center"},
       {title: '所属机构', dataIndex: 'institutionName', key: 'institutionName', align: "center"},
       {title: '驿站人员',  dataIndex: 'siteUsers',key: 'siteUsers', fixed: 'right',width:170, align: "center"},
-      {title: '操作', key: 'operation', fixed: 'right',width:100, align: "center"},
+      {title: '操作', key: 'operation', fixed: 'right', width: 150, align: "center"},
     ];
     const pagination = computed(() => ({
       total: formState.total,
@@ -235,6 +237,10 @@ export default defineComponent({
       tabsViewStore.addTabByPath('/baseSettings/site/edit', {id:id});
     };
 
+    const onDetail = (id: string) => {
+      tabsViewStore.addTabByPath('/baseSettings/site/detail', {id: id});
+    };
+
     const loadData = async function () {
       formState.loading = true;
       await getAllInstitutions();
@@ -263,7 +269,8 @@ export default defineComponent({
       onEdit,
       onDel,
       loadData,
-      changeRegion
+      changeRegion,
+      onDetail
     };
   },
   created() {

+ 49 - 0
vue/src/views/baseSettings/siteUser/detail.vue

@@ -0,0 +1,49 @@
+<template>
+  <div class="card-edit">
+    <a-divider orientation="left">站点人员基本信息</a-divider>
+    <a-descriptions bordered>
+      <a-descriptions-item label="姓名">{{ siteUserInfo.siteUserName }}</a-descriptions-item>
+      <a-descriptions-item label="性别">{{ siteUserInfo.genderName }}</a-descriptions-item>
+      <a-descriptions-item label="联系电话">{{ siteUserInfo.mobile }}</a-descriptions-item>
+      <a-descriptions-item label="工号">{{ siteUserInfo.userNo }}</a-descriptions-item>
+      <a-descriptions-item label="身份证">{{ siteUserInfo.idCard }}</a-descriptions-item>
+      <a-descriptions-item label="用户类型">{{ siteUserInfo.roleName }}</a-descriptions-item>
+      <a-descriptions-item label="所属驿站">{{ siteUserInfo.siteName }}</a-descriptions-item>
+    </a-descriptions>
+  </div>
+</template>
+
+<script setup lang="ts">
+import {onMounted, reactive} from "vue";
+import {getSiteUserByID} from "@/api/baseSettings/userInfo";
+
+// 站点人员信息
+const siteUserInfo = reactive({
+  siteUserName: "",
+  genderName: "",
+  mobile: "",
+  userNo: "",
+  idCard: "",
+  roleName: "",
+  siteName: "",
+})
+
+// 站点人员数据加载
+function loadData(siteUserID: string) {
+  getSiteUserByID(siteUserID).then((result: any) => {
+    Object.keys(siteUserInfo).forEach(key => {
+      siteUserInfo[key] = result[key];
+    })
+  });
+}
+
+// 页面初始化
+onMounted(() => {
+  const id = history.state.params?.id;
+  loadData(id);
+})
+</script>
+
+<style scoped>
+
+</style>

+ 2 - 2
vue/src/views/baseSettings/siteUser/edit.vue

@@ -25,14 +25,14 @@
       </a-row>
       <a-row type="flex">
         <a-col :span="7">
-          <a-form-item label="工号" name="roleID" :label-col="{span:7}"
+          <a-form-item label="工号" name="userNo" :label-col="{span:7}"
                        :rules="[{ required: true, message: '请输入工号!' }]">
             <label v-if="opCategory==3">{{ dataModel.userNo }}</label>
             <a-input v-model:value="dataModel.userNo" placeholder=""/>
           </a-form-item>
         </a-col>
         <a-col :span="8">
-          <a-form-item label="身份证" name="roleID" :label-col="{span:7}"
+          <a-form-item label="身份证" name="idCard" :label-col="{span:7}"
                        :rules="[{ required: true, message: '请输入身份证!' }]">
             <label v-if="opCategory==3">{{ dataModel.idCard }}</label>
             <a-input v-model:value="dataModel.idCard" placeholder=""/>

+ 35 - 3
vue/src/views/baseSettings/siteUser/index.vue

@@ -41,6 +41,10 @@
       <a-row class="edit-operation">
         <a-col :span="24" style="text-align: right">
           <a-button type="primary" html-type="submit" functioncode="T01010302" @click='onAdd' >新增</a-button>
+          <BImportExcel functioncode="T01010306"
+                        :options="importOptions"
+                        @success="loadData"
+          ></BImportExcel>
           <BExportExcel :title="'导出'" :filename="'驿站人员信息'" :url="'userInfo/export'" :params="{...searchParams, rows:100000,siteUserIDList:formState.selectedRowKeys.join(',')}"></BExportExcel>
         </a-col>
       </a-row>
@@ -55,6 +59,8 @@
         <template #bodyCell="{ column, text, record }">
           <template v-if="column.key === 'operation'">
             <div class="table-operation">
+              <a-button type="link" size="small" functioncode="T01010301" @click='onDetail(record.siteUserID)'>查看
+              </a-button>
               <a-button type="link" size="small"  functioncode="T01010303"  @click='onEdit(record.siteUserID)' >编辑</a-button>
               <a-button type="link" size="small"  functioncode="T01010304"  @click="onDel(record)" >删除</a-button>
             </div>
@@ -75,10 +81,12 @@ import {delSiteUser, getSiteUserList} from '@/api/baseSettings/userInfo';
 import BExportExcel from "@/components/basic/excel/exportExcel/exportExcel.vue";
 import {getPaginationTotalTitle} from "@/utils/common";
 import {getSiteList} from "@/api/baseSettings/siteInfo";
+import BImportExcel from "@/components/basic/excel/importExcel/importExcel.vue";
+import type {ImportProps} from "@/components/basic/excel/importExcel/ImportProps";
 
 export default defineComponent({
   name: 'UserInfoList',
-  components: {DownOutlined, UpOutlined, BExportExcel},
+  components: {BImportExcel, DownOutlined, UpOutlined, BExportExcel},
   setup() {
     const formRef = ref<FormInstance>();
     const tabsViewStore = useTabsViewStore();
@@ -104,8 +112,26 @@ export default defineComponent({
       {title: '联系电话', dataIndex: 'mobile', key: 'mobile', align: "center"},
       {title: '身份证号', dataIndex: 'idCard', key: 'idCard', align: "center"},
       {title: '所属驿站', dataIndex: 'siteName', key: 'siteName', align: "center"},
-      {title: '操作', key: 'operation', fixed: 'right',width:100, align: "center"},
+      {title: '操作', key: 'operation', fixed: 'right', width: 150, align: "center"},
     ];
+    const importOptions = ref<ImportProps>({
+      title: '导入',
+      url: 'userInfo/importSiteUser',
+      columns: [
+        {cnName: '姓名', enName: 'siteUserName', width: 100},
+        {cnName: '工号', enName: 'userNo', width: 100},
+        {cnName: '性别', enName: 'genderName', width: 100},
+        {cnName: '联系电话', enName: 'mobile', width: 100},
+        {cnName: '身份证号码', enName: 'idCard', width: 140},
+        {cnName: '用户类型', enName: 'roleName', width: 100},
+        {cnName: '所属驿站', enName: 'siteName', width: 100},
+      ],
+      template: {
+        tempFileName: '站点人员信息导入模板.xlsx',
+        url: '',
+        params: null,
+      },
+    });
     const pagination = computed(() => ({
       total: formState.total,
       current: searchParams.pageIndex,
@@ -183,6 +209,10 @@ export default defineComponent({
       tabsViewStore.addTabByPath('/baseSettings/user/edit', {id:id,op:2});
     };
 
+    const onDetail = (id: string) => {
+      tabsViewStore.addTabByPath('/baseSettings/user/detail', {id: id, op: 2});
+    };
+
     return {
       formRef,
       allSites,
@@ -197,7 +227,9 @@ export default defineComponent({
       onAdd,
       onEdit,
       onDel,
-      loadData
+      loadData,
+      onDetail,
+      importOptions
     };
   },
   created() {