MrShi
8 天以前 cb94ff4f0a46eb74c21dd7b34b8d958ef9a9f11c
Merge branch 'master' of http://139.186.142.91:10010/r/productDev/zbom_dianjiang
已添加6个文件
已修改31个文件
1447 ■■■■ 文件已修改
admin/.env 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/.env.development 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/.env.test 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/package.json 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/public/favicon.ico 补丁 | 查看 | 原始文档 | blame | 历史
admin/public/template/casees.xlsx 补丁 | 查看 | 原始文档 | blame | 历史
admin/public/template/member.xlsx 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/components/business/OperaCasesImportWindow.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/components/business/OperaCasesListWindow.vue 182 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/components/business/OperaCasesWindow.vue 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/components/business/OperaMemberListWindow.vue 288 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/components/common/GlobalWindow.vue 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/views/business/cases.vue 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/views/business/importRecord.vue 30 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/views/business/member.vue 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/admin/src/main/java/com/doumee/init/InitService.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/admin/src/main/resources/application.yml 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/pom.xml 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/java/com/doumee/core/annotation/excel/ExcelImporter.java 143 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/java/com/doumee/core/annotation/excel/ExcelPictureUtil.java 81 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/java/com/doumee/core/constants/Constants.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/java/com/doumee/core/dingTalk/DingTalk.java 128 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/java/com/doumee/core/dingTalk/DingTalkStream.java 71 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/java/com/doumee/dao/business/dto/CasesImport.java 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/java/com/doumee/dao/business/dto/MemberImport.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/java/com/doumee/dao/business/model/Cases.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/java/com/doumee/dao/business/model/ImportRecord.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/java/com/doumee/dao/business/model/Member.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/java/com/doumee/dao/system/dto/DingLoginDTO.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/java/com/doumee/dao/vo/WebLoginUserVO.java 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/java/com/doumee/service/business/ImportRecordService.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/java/com/doumee/service/business/impl/CasesServiceImpl.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/java/com/doumee/service/business/impl/CategoryServiceImpl.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/java/com/doumee/service/business/impl/ImportRecordServiceImpl.java 220 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/java/com/doumee/service/business/impl/MemberServiceImpl.java 64 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/resources/application-dev.yml 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/web/src/main/java/com/doumee/api/web/LoginController.java 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/.env
@@ -10,4 +10,4 @@
VUE_APP_CONTEXT_PATH = './'
# æŽ¥å£å‰ç¼€
VUE_APP_API_PREFIX = '/jinkuai_admin'
VUE_APP_API_PREFIX = '/dianjiang_admin_api'
admin/.env.development
@@ -1,3 +1,3 @@
# å¼€å‘环境配置
NODE_ENV = 'development'
VUE_APP_API_URL = 'http://localhost:10010'
VUE_APP_API_URL = 'http://localhost:11010'
admin/.env.test
@@ -1,7 +1,3 @@
# ç”Ÿäº§çŽ¯å¢ƒé…ç½®
NODE_ENV = 'production'
# å…³é—­DEBUG
VUE_APP_DEBUG = 'off'
VUE_APP_API_URL  = 'https://test.doumee.cn/lianhelihua_interface'
# å¼€å‘环境配置
NODE_ENV = 'development'
VUE_APP_API_URL = 'http://192.168.0.7:10010/dianjiang_admin_interface'
admin/package.json
@@ -1,5 +1,5 @@
{
  "name": "jinkuai",
  "name": "zbom_dianjiang",
  "version": "1.0.0",
  "private": true,
  "scripts": {
admin/public/favicon.ico

admin/public/template/casees.xlsx
Binary files differ
admin/public/template/member.xlsx
Binary files differ
admin/src/components/business/OperaCasesImportWindow.vue
@@ -48,7 +48,7 @@
      this.title = title
      this.fileName = ''
      this.visible = true
      this.type = 0
      this.type = 1
    },
    // å¯¼å‡ºæ¨¡æ¿
    exportTemplate () {
admin/src/components/business/OperaCasesListWindow.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,182 @@
<template>
  <GlobalWindow
    :title="title"
    :visible.sync="visible"
    width="100%"
  >
    <TableLayout :permissions="['business:cases:query']">
      <!-- æœç´¢è¡¨å• -->
      <el-form ref="searchForm" slot="search-form" :model="searchForm" id="curSearchForm"  label-width="100px" inline>
        <el-form-item label="标题" prop="name">
          <el-input v-model="searchForm.name"  style="width: 150px" placeholder="请输入标题" @keypress.enter.native="search"></el-input>
        </el-form-item>
        <el-form-item label="状态" prop="status">
          <el-select
              v-model="searchForm.status"
              placeholder="状态"
              clearable
              style="width: 150px"
              @change="search"
          >
            <el-option :key="0" :value="0" label="启用"></el-option>
            <el-option :key="1" :value="1" label="禁用"></el-option>
          </el-select>
        </el-form-item>
        <section>
          <el-button type="primary" @click="search">搜索</el-button>
          <el-button @click="reset">重置</el-button>
        </section>
      </el-form>
      <!-- è¡¨æ ¼å’Œåˆ†é¡µ -->
      <template v-slot:table-wrap>
<!--        <ul class="toolbar" v-permissions="['business:cases:create', 'business:cases:delete']">
          <li><el-button type="primary" @click="$refs.operaCasesWindow.open('新建案例',null)" icon="el-icon-plus" v-permissions="['business:cases:create']">新建</el-button></li>
          <li><el-button type="primary" icon="el-icon-refresh" v-permissions="['business:cases:create']" @click="$refs.OperaCasesImportWindow.open('案例导入')">批量导入</el-button></li>
          <li><el-button type="danger" @click="deleteByIdInBatch" icon="el-icon-delete" v-permissions="['business:cases:delete']">删除</el-button></li>
        </ul>-->
        <el-table
            :height="tableHeight"
            v-loading="isWorking.search"
            :data="tableData.list"
            :cell-class-name="setRowClassName"
            border
            stripe
            @selection-change="handleSelectionChange"
        >
          <el-table-column prop="name" label="案例标题" min-width="200px"></el-table-column>
          <el-table-column  prop="icon" label="排行榜图集" min-width="220px">
            <template slot-scope="{row}">
              <div style="display: flex; flex-wrap: wrap;width: 200px;"  v-if="row.fileList && row.fileList.length">
                <div v-for="item in row.fileList" :key="row.id+'_img'+item.id" style=" box-sizing: border-box;  margin-right: 10px; " >
                  <el-image  style="width: 50px; height: 50px;" :src="item.url"
                             :preview-src-list="[item.url]">
                  </el-image>
                </div>
              </div>
            </template>
          </el-table-column>
          <el-table-column prop="memberName" label="老师" min-width="220px">
            <template slot-scope="{row}">
              <span class="orange" style="margin-right: 10px"> {{row.memberCode}}</span> <span>{{row.memberName||''}}</span>
            </template>
          </el-table-column>
          <el-table-column prop="startDate" label="开始日期" min-width="140px"></el-table-column>
          <el-table-column prop="endDate" label="结束日期" min-width="140px"></el-table-column>
          <el-table-column prop="detail" label="案例描述" min-width="230px" ></el-table-column>
          <el-table-column label="状态"  >
            <template slot-scope="{row}">
              <span class="orange" v-if="row.status==0"  >启用</span>
              <span class="red"  v-if="row.status==1">禁用</span>
            </template>
          </el-table-column>
          <el-table-column label="是否删除"  >
            <template slot-scope="{row}">
              <span class="red" v-if="row.deleted==1"  >已删除</span>
              <span class="green"  v-else>未删除</span>
            </template>
          </el-table-column>
        </el-table>
        <pagination
            @size-change="handleSizeChange"
            @current-change="handlePageChange"
            :pagination="tableData.pagination"
        >
        </pagination>
      </template>
    </TableLayout>
    <template  v-slot:footer>
      <el-button @click="visible=false">返回</el-button>
    </template>
  </GlobalWindow>
</template>
<script>
import BaseTable from '@/components/base/BaseTable'
import TableLayout from '@/layouts/TableLayout'
import Pagination from '@/components/common/Pagination'
import GlobalWindow from '@/components/common/GlobalWindow'
import { findAll as memberList } from '@/api/business/member'
import {findAll as cateList} from "@/api/business/category";
export default {
  name: 'OperaCasesListWindow',
  extends: BaseTable,
  components: { GlobalWindow, TableLayout, Pagination },
  data () {
    return {
      title: '',
      visible: false,
      tableHeight: null,
      searchForm: {
        containDeleted: 1,
        name: '',
        importId: '',
        status: null
      },
      memberList: []
    }
  },
  created () {
    this.config({
      api: '/business/cases',
      'field.id': 'id'
    })
    window.addEventListener('resize', () => {
       this.getTableHeight()
    })
    cateList({
    }).then(res => {
      this.cateList = res
    })
  },
  methods: {
    setRowClassName({row, rowIndex}) {
      if (row.deleted == 1) {
        return 'warning-row'
      }
      return '' // å¦‚果不需要任何特殊样式,返回空字符串或 null
    },
    getTableHeight(){
      this.$nextTick(() => {
        this.tableHeight = window.innerHeight - 180- document.getElementById('curSearchForm').clientHeight
      })
    },
    open (title, memberId, importId) {
      this.title = title
      this.visible = true
      this.getTableHeight()
      this.tableData = {
        // å·²é€‰ä¸­çš„æ•°æ®
        selectedRows: [],
        // æŽ’序的字段
        sorts: [],
        // å½“前页数据
        list: [],
        // åˆ†é¡µ
        pagination: {
          pageIndex: 1,
          pageSize: 10,
          total: 0
        }
      }
      this.searchForm.importId = importId
      this.search()
    }
  }
}
</script>
<style scoped lang="scss">
/deep/ .window__body {
  overflow-y: hidden !important;
}
.table-content .table-wrap .el-table{
  overflow-y: hidden !important;
}
</style>
<style  >
.success-row {
  background: #f0f9eb; /* æµ…绿色背景 */
}
.warning-row {
  background: rgba(161, 14, 14, 0.35); /* æµ…红色背景 */
}
</style>
admin/src/components/business/OperaCasesWindow.vue
@@ -16,7 +16,7 @@
              v-for="item in memberList"
              :key="item.id"
              :value="item.id"
              :label="item.name"
              :label="item.name+' ã€'+item.code+'】'"
          ></el-option>
        </el-select>
      </el-form-item>
@@ -74,7 +74,7 @@
    return {
      isUploading: false,
      uploadData: {
        folder: 'dianjiang/category'
        folder: 'dianjiang/cases'
      },
      // è¡¨å•数据
      form: {
admin/src/components/business/OperaMemberListWindow.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,288 @@
<template>
  <GlobalWindow
    :title="title"
    :visible.sync="visible"
    width="100%"
  >
    <TableLayout :permissions="['business:cases:query']">
      <!-- æœç´¢è¡¨å• -->
      <el-form class="table-search-formCur" ref="searchForm" id="curSearchForm" slot="search-form" :model="searchForm" label-width="100px" inline>
        <el-form-item label="名称" prop="name">
          <el-input v-model="searchForm.name"  style="width: 150px" placeholder="请输入名称" @keypress.enter.native="search"></el-input>
        </el-form-item>
        <el-form-item label="工号" prop="code">
          <el-input v-model="searchForm.code" style="width: 150px" placeholder="请输入工号" @keypress.enter.native="search"></el-input>
        </el-form-item>
        <el-form-item label="战区" prop="zhanquIds">
          <el-select
              v-model="searchForm.zhanquIds"
              style="width: 150px"
              placeholder="战区"
              clearable
              @change="search"
          >
            <el-option
                v-for="item in cateList.filter(item=>{return item.type==0})"
                :key="item.id"
                :value="item.id"
                :label="item.name"
            ></el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="商业化类型" prop="bustypeIds">
          <el-select
              v-model="searchForm.bustypeIds"
              style="width: 150px"
              placeholder="商业化类型"
              clearable
              @change="search"
          >
            <el-option
                v-for="item in cateList.filter(item=>{return item.type==1})"
                :key="item.id"
                :value="item.id"
                :label="item.name"
            ></el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="擅长领域" prop="fieldIdList">
          <el-select
              v-model="searchForm.fieldIdList"
              style="width: 150px"
              placeholder="擅长领域"
              clearable
              multiple
              @change="search"
          >
            <el-option
                v-for="item in cateList.filter(item=>{return item.type==2})"
                :key="item.id"
                :value="item.id"
                :label="item.name"
            ></el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="老师等级" prop="levelId">
          <el-select
              v-model="searchForm.levelId"
              style="width: 150px"
              placeholder="老师等级"
              clearable
              @change="search"
          >
            <el-option
                v-for="item in cateList.filter(item=>{return item.type==3})"
                :key="item.id"
                :value="item.id"
                :label="item.name"
            ></el-option>
          </el-select>
        </el-form-item>
          <el-form-item label="状态" prop="status">
            <el-select
                v-model="searchForm.status"
                placeholder="状态"
                clearable
                style="width: 150px"
                @change="search"
            >
              <el-option :key="0" :value="0" label="启用"></el-option>
              <el-option :key="1" :value="1" label="禁用"></el-option>
            </el-select>
          </el-form-item>
        <section>
          <el-button type="primary" @click="search">搜索</el-button>
          <el-button @click="reset">重置</el-button>
        </section>
      </el-form>
      <!-- è¡¨æ ¼å’Œåˆ†é¡µ -->
      <template v-slot:table-wrap>
<!--        <ul class="toolbar" v-permissions="['business:cases:create', 'business:cases:delete']">
          <li><el-button type="primary" @click="$refs.operaCasesWindow.open('新建案例',null)" icon="el-icon-plus" v-permissions="['business:cases:create']">新建</el-button></li>
          <li><el-button type="primary" icon="el-icon-refresh" v-permissions="['business:cases:create']" @click="$refs.OperaCasesImportWindow.open('案例导入')">批量导入</el-button></li>
          <li><el-button type="danger" @click="deleteByIdInBatch" icon="el-icon-delete" v-permissions="['business:cases:delete']">删除</el-button></li>
        </ul>-->
        <el-table
            :height="tableHeight"
            v-loading="isWorking.search"
            :data="tableData.list"
            border
            :cell-class-name="setRowClassName"
            stripe
            @selection-change="handleSelectionChange"
        >
          <el-table-column  prop="imgurl" label="图片" min-width="100px">
            <template slot-scope="{row}">
              <el-image v-if="row.fullImgurl" style="width: 50px; height: 50px; margin-right: 10px" :src="row.fullImgurl"
                        :preview-src-list="[row.fullImgurl]">
              </el-image>
            </template>
          </el-table-column>
          <el-table-column prop="code" label="工号" min-width="100px"></el-table-column>
          <el-table-column prop="name" label="姓名" min-width="100px"></el-table-column>
          <el-table-column prop="sex" label="性别" min-width="100px">
            <template slot-scope="{row}">
              <span v-if="row.sex ==0">男</span>
              <span v-if="row.sex ==1">女</span>
            </template>
          </el-table-column>
          <el-table-column prop="positon" label="岗位" min-width="120px"></el-table-column>
          <el-table-column prop="levelName" label="等级" min-width="100px"></el-table-column>
          <el-table-column prop="jobYear" label="从业年份" min-width="100px"></el-table-column>
          <el-table-column prop="serveNum" label="服务商场" min-width="100px">
            <template slot-scope="{row}">
              <span v-if="row.serveNum">{{row.serveNum}}个</span>
            </template>
          </el-table-column>
          <el-table-column prop="caseNum" label="标杆案例" min-width="100px">
            <template slot-scope="{row}">
              <span >{{row.caseNum || 0}}个</span>
            </template>
          </el-table-column>
          <el-table-column prop="busTypeNames" label="商业化类型" min-width="200px">
            <template slot-scope="{row}">
              <div v-if="row.typeList && row.typeList.length">
                <div style="display:inline-block;" v-for="(item,index) in row.typeList">{{item.name||''}} <span v-if="index < row.typeList.length-1" style="display:inline-block;padding: 0px 3px;">/</span></div>
              </div>
            </template>
          </el-table-column>
          <el-table-column prop="areaNames" label="服务战区" min-width="200px">
            <template slot-scope="{row}">
              <div v-if="row.zqList && row.zqList.length">
                <div style="display:inline-block;" v-for="(item,index) in row.zqList">{{item.name||''}} <span v-if="index < row.zqList.length-1" style="display:inline-block;padding: 0px 3px;">/</span></div>
              </div>
            </template>
          </el-table-column>
          <el-table-column prop="fieldNames" label="擅长领域" min-width="200px">
            <template slot-scope="{row}">
              <div v-if="row.fieldList && row.fieldList.length">
                <div style="display:inline-block;" v-for="(item,index) in row.fieldList">{{item.name||''}} <span v-if="index < row.fieldList.length-1" style="display:inline-block;padding: 0px 3px;">/</span></div>
              </div>
            </template>
          </el-table-column>
          <el-table-column prop="fee" label="费用标准(元/周)" min-width="130px"></el-table-column>
          <el-table-column label="状态"  >
            <template slot-scope="{row}">
              <span class="orange" v-if="row.status==0"  >启用</span>
              <span class="red"  v-if="row.status==1">禁用</span>
            </template>
          </el-table-column>
          <el-table-column label="是否删除"  >
            <template slot-scope="{row}">
              <span class="red" v-if="row.deleted==1"  >已删除</span>
              <span class="green"  v-else>未删除</span>
            </template>
          </el-table-column>
        </el-table>
        <pagination
            @size-change="handleSizeChange"
            @current-change="handlePageChange"
            :pagination="tableData.pagination"
        >
        </pagination>
      </template>
    </TableLayout>
    <template  v-slot:footer>
      <el-button @click="visible=false">返回</el-button>
    </template>
  </GlobalWindow>
</template>
<script>
import BaseTable from '@/components/base/BaseTable'
import TableLayout from '@/layouts/TableLayout'
import Pagination from '@/components/common/Pagination'
import GlobalWindow from '@/components/common/GlobalWindow'
import { findAll as memberList } from '@/api/business/member'
export default {
  name: 'OperaMemberListWindow',
  extends: BaseTable,
  components: { GlobalWindow, TableLayout, Pagination },
  data () {
    return {
      title: '',
      visible: false,
      tableHeight: null,
      searchForm: {
        name: '',
        containDeleted: 1,
        queryFlag: 1,
        code: '',
        status: null,
        levelId: null,
        fieldIdList: [],
        zhanquIds: null,
        bustypeIds: null,
        type: 0
      },
      cateList: []
    }
  },
  created () {
    this.config({
      api: '/business/member',
      'field.id': 'id'
    })
    window.addEventListener('resize', () => {
      this.getTableHeight()
    })
  },
  methods: {
    getTableHeight () {
      this.$nextTick(() => {
        this.tableHeight = window.innerHeight - 180- document.getElementById('curSearchForm').clientHeight
      })
    },
    loadMemberList () {
      memberList({
      }).then(res => {
        this.memberList = res
      })
    },
    setRowClassName({row, rowIndex}) {
      if (row.deleted == 1) {
        return 'warning-row'
      }
      return '' // å¦‚果不需要任何特殊样式,返回空字符串或 null
    },
    open (title, importId) {
      this.title = title
      this.visible = true
      this.getTableHeight()
      this.tableData = {
        // å·²é€‰ä¸­çš„æ•°æ®
        selectedRows: [],
        // æŽ’序的字段
        sorts: [],
        // å½“前页数据
        list: [],
        // åˆ†é¡µ
        pagination: {
          pageIndex: 1,
          pageSize: 10,
          total: 0
        }
      }
      this.searchForm.importId = importId
      this.search()
    }
  }
}
</script>
<style scoped lang="scss">
/deep/ .window__body {
  overflow-y: hidden !important;
}
.table-content .table-wrap .el-table{
  overflow-y: hidden !important;
}
</style>
<style  >
.success-row {
  background: #f0f9eb; /* æµ…绿色背景 */
}
.warning-row {
  background: rgba(161, 14, 14, 0.35); /* æµ…红色背景 */
}
</style>
admin/src/components/common/GlobalWindow.vue
@@ -85,6 +85,7 @@
$input-height: 32px;
.global-window {
  // å¤´éƒ¨æ ‡é¢˜
  left: 218px !important;
  /deep/ .el-drawer__header {
    padding: 0 10px 0 0;
    line-height: 40px;
admin/src/views/business/cases.vue
@@ -18,7 +18,7 @@
              v-for="item in memberList"
              :key="item.id"
              :value="item.id"
              :label="item.name"
              :label="item.name+' ã€'+item.code+'】'"
          ></el-option>
        </el-select>
      </el-form-item>
@@ -54,7 +54,7 @@
        @selection-change="handleSelectionChange"
      >
        <el-table-column type="selection" width="55"></el-table-column>
        <el-table-column prop="name" label="案例标题" min-width="100px"></el-table-column>
        <el-table-column prop="name" label="案例标题" min-width="200px"></el-table-column>
        <el-table-column  prop="icon" label="排行榜图集" min-width="220px">
          <template slot-scope="{row}">
            <div style="display: flex; flex-wrap: wrap;width: 200px;"  v-if="row.fileList && row.fileList.length">
@@ -66,10 +66,14 @@
            </div>
          </template>
        </el-table-column>
        <el-table-column prop="memberName" label="老师" min-width="120px"></el-table-column>
        <el-table-column prop="memberName" label="老师" min-width="220px">
          <template slot-scope="{row}">
            <span class="orange" style="margin-right: 10px"> {{row.memberCode}}</span> <span>{{row.memberName||''}}</span>
          </template>
        </el-table-column>
        <el-table-column prop="startDate" label="开始日期" min-width="140px"></el-table-column>
        <el-table-column prop="endDate" label="结束日期" min-width="140px"></el-table-column>
        <el-table-column prop="detail" label="案例描述" min-width="230px" show-overflow-tooltip></el-table-column>
        <el-table-column prop="detail" label="案例描述" min-width="230px" ></el-table-column>
        <el-table-column prop="updateUserName" label="操作人" min-width="100px"></el-table-column>
        <el-table-column prop="updateTime" label="最近操作时间" min-width="150px"></el-table-column>
        <el-table-column label="状态" fixed="right">
admin/src/views/business/importRecord.vue
@@ -56,8 +56,8 @@
        <el-table-column prop="title" label="内容" min-width="200px" show-overflow-tooltip></el-table-column>
        <el-table-column label="业务类型">
          <template slot-scope="{row}">
            <span v-if="row.type ==0 " >老师导入</span>
            <span v-if="row.type == 1"  >案例导入</span>
            <span v-if="row.type ==0 "  class="green">老师导入</span>
            <span v-if="row.type == 1"   class="orange" >案例导入</span>
          </template>
        </el-table-column>
        <el-table-column label="状态">
@@ -68,10 +68,26 @@
          </template>
        </el-table-column>
        <el-table-column prop="totalNum" label="总记录数" min-width="100px"></el-table-column>
        <el-table-column prop="doneNum" label="成功录入数量" min-width="100px"></el-table-column>
        <el-table-column prop="doneNum" label="成功录入数量" min-width="100px">
          <template slot-scope="{row}">
            <span v-if="row.status == 1" class="red">{{row.ingNum}}</span>
            <span v-else>{{ row.doneNum }}</span>
          </template>
        </el-table-column>
        <el-table-column prop="errorNum" label="录入失败数量" min-width="100px"></el-table-column>
        <el-table-column prop="updateUserName" label="操作人" min-width="100px"></el-table-column>
        <el-table-column prop="createTime" label="导入时间" min-width="150px"></el-table-column>
        <el-table-column prop="updateTime" label="最近操作时间" min-width="150px"></el-table-column>
        <el-table-column
            label="操作"
            min-width="120"
            fixed="right"
        >
          <template slot-scope="{row}">
            <el-button type="text"  v-if="row.type ==1"  style="color: orange" @click="$refs.OperaCasesListWindow.open('查看导入案例【'+row.title+'】',null, row.id)" icon="el-icon-open">查看导入案例</el-button>
            <el-button type="text"  v-if="row.type ==0" style="color: green"   @click="$refs.OperaMemberListWindow.open('查看导入案例【'+row.title+'】', row.id)" icon="el-icon-open">查看导入老师</el-button>
          </template>
        </el-table-column>
      </el-table>
      <pagination
        @size-change="handleSizeChange"
@@ -81,7 +97,8 @@
      </pagination>
    </template>
    <!-- æ–°å»º/修改 -->
    <OperaCategoryWindow ref="operaCategoryWindow" @success="handlePageChange"/>
    <OperaMemberListWindow ref="OperaMemberListWindow" @success="handlePageChange"/>
    <OperaCasesListWindow ref="OperaCasesListWindow" @success="handlePageChange"/>
  </TableLayout>
</template>
@@ -89,11 +106,12 @@
import BaseTable from '@/components/base/BaseTable'
import TableLayout from '@/layouts/TableLayout'
import Pagination from '@/components/common/Pagination'
import OperaCategoryWindow from '@/components/business/OperaCategoryWindow'
import OperaMemberListWindow from '@/components/business/OperaMemberListWindow'
import OperaCasesListWindow from '@/components/business/OperaCasesListWindow'
export default {
  name: 'Category',
  extends: BaseTable,
  components: { TableLayout, Pagination, OperaCategoryWindow },
  components: { TableLayout, Pagination, OperaCasesListWindow,OperaMemberListWindow},
  data () {
    return {
      // æœç´¢
admin/src/views/business/member.vue
@@ -72,6 +72,7 @@
              :label="item.name"
          ></el-option>
        </el-select>
      </el-form-item>
        <el-form-item label="状态" prop="status">
          <el-select
              v-model="searchForm.status"
@@ -84,7 +85,6 @@
            <el-option :key="1" :value="1" label="禁用"></el-option>
          </el-select>
        </el-form-item>
      </el-form-item>
      <section>
        <el-button type="primary" @click="search">搜索</el-button>
        <el-button @click="reset">重置</el-button>
@@ -167,11 +167,12 @@
        <el-table-column
          v-if="containPermissions(['business:member:update', 'business:member:delete'])"
          label="操作"
          min-width="120"
          min-width="180"
          fixed="right"
        >
          <template slot-scope="{row}">
            <el-button type="text" @click="$refs.operaMemberWindow.open('编辑老师', row,searchForm.type)" icon="el-icon-edit" v-permissions="['business:member:update']">编辑</el-button>
            <el-button type="text"   @click="$refs.OperaCasesListWindow.open('查看老师案例【'+row.name+'】', row.id)" icon="el-icon-open">案例</el-button>
            <el-button type="text" style="color: red" @click="deleteById(row)" icon="el-icon-delete" v-permissions="['business:member:delete']">删除</el-button>
          </template>
        </el-table-column>
@@ -186,6 +187,7 @@
    <!-- æ–°å»º/修改 -->
    <OperaMemberWindow ref="operaMemberWindow" @success="handlePageChange"/>
    <OperaMemberImportWindow ref="OperaMemberImportWindow" @success="handlePageChange" />
    <OperaCasesListWindow ref="OperaCasesListWindow" @success="handlePageChange" />
  </TableLayout>
</template>
@@ -195,11 +197,12 @@
import Pagination from '@/components/common/Pagination'
import OperaMemberWindow from '@/components/business/OperaMemberWindow'
import OperaMemberImportWindow from '@/components/business/OperaMemberImportWindow'
import OperaCasesListWindow from '@/components/business/OperaCasesListWindow'
import { findAll as cateList } from '@/api/business/category'
export default {
  name: 'Category',
  extends: BaseTable,
  components: { TableLayout, Pagination, OperaMemberWindow ,OperaMemberImportWindow},
  components: { TableLayout, Pagination, OperaMemberWindow ,OperaMemberImportWindow,OperaCasesListWindow},
  data () {
    return {
      // æœç´¢
server/admin/src/main/java/com/doumee/init/InitService.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,20 @@
package com.doumee.init;
import com.doumee.service.business.ImportRecordService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
@Service
@Slf4j
public class InitService  {
    @Autowired
    private ImportRecordService importRecordService;
    @PostConstruct
    public void initImportTaskStatus() {
        importRecordService.clearImporTask();
    }
}
server/admin/src/main/resources/application.yml
@@ -1,6 +1,6 @@
# ç«¯å£å™¨é…ç½®
server:
  port: 10010
  port: 11010
# é¡¹ç›®ä¿¡æ¯é…ç½®
project:
  name: å¿—邦-点将
server/services/pom.xml
@@ -24,6 +24,21 @@
      <artifactId>hutool-all</artifactId>
      <version>5.8.40</version>
    </dependency>
    <dependency>
      <groupId>com.aliyun</groupId>
      <artifactId>dingtalk</artifactId>
      <version>2.2.25</version>
    </dependency>
    <dependency>
      <groupId>com.dingtalk.open</groupId>
      <artifactId>app-stream-client</artifactId>
      <version>1.3.7</version>
    </dependency>
    <dependency>
      <groupId>com.aliyun</groupId>
      <artifactId>alibaba-dingtalk-service-sdk</artifactId>
      <version>2.0.0</version>
    </dependency>
  </dependencies>
  <properties>
    <maven.compiler.source>8</maven.compiler.source>
server/services/src/main/java/com/doumee/core/annotation/excel/ExcelImporter.java
@@ -4,6 +4,7 @@
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFPicture;
import org.apache.poi.xssf.usermodel.XSSFPictureData;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.slf4j.Logger;
@@ -329,64 +330,102 @@
            }
            StringBuilder sb = new StringBuilder();
            for (Object[] os : annotationList){
                Object val = this.getCellValue(row, column++);
                if (val != null){
                    ExcelColumn ef = (ExcelColumn)os[0];
                    // Get param type and type cast
                    Class<?> valType = Class.class;
                    if (os[1] instanceof Field){
                        valType = ((Field)os[1]).getType();
                    }else if(os[1] instanceof Method){
                        Method method = ((Method)os[1]);
                        if ("get".equals(method.getName().substring(0, 3))){
                            valType = method.getReturnType();
                        }else if("set".equals(method.getName().substring(0, 3))){
                            valType = ((Method)os[1]).getParameterTypes()[0];
                        }
                int tcolumn = column++;
                Object val = this.getCellValue(row, tcolumn);;
                ExcelColumn ef = (ExcelColumn)os[0];
                // Get param type and type cast
                Class<?> valType = Class.class;
                if (os[1] instanceof Field){
                    valType = ((Field)os[1]).getType();
                }else if(os[1] instanceof Method){
                    Method method = ((Method)os[1]);
                    if ("get".equals(method.getName().substring(0, 3))){
                        valType = method.getReturnType();
                    }else if("set".equals(method.getName().substring(0, 3))){
                        valType = ((Method)os[1]).getParameterTypes()[0];
                    }
                    //log.debug("Import value type: ["+i+","+column+"] " + valType);
                    try {
                        if (valType == String.class){
                            String s = String.valueOf(val.toString());
                            if(StringUtils.endsWith(s, ".0")){
                                val = StringUtils.substringBefore(s, ".0");
                            }else{
                                val = String.valueOf(val.toString()).trim();
                }
                if(ef.fieldType()== XSSFPictureData.class){
                    XSSFPictureData qrData = null;
                    if(val !=null){
                        String tid = String.valueOf(val.toString()).trim();
                        int start = tid.indexOf("(\"")+2;
                        int end = tid.indexOf("\",");
                        if(start>=0&& end>=1 && end>start){
                            String picId = tid.substring(start,end);
                            XSSFPictureData data = this.pictureList.get(picId);
                            if(data!= null && data.getData() != null){
                                qrData =data;
                            }
                        }
                        else if (valType == Integer.class){
                            val = Double.valueOf(val.toString()).intValue();
                        }else if (valType == Long.class){
                            val = Double.valueOf(val.toString()).longValue();
                        }else if (valType == Double.class){
                            val = Double.valueOf(val.toString());
                        }else if (valType == Float.class){
                            val = Float.valueOf(val.toString());
                        }else if (valType == Date.class){
                            val = DateUtil.getJavaDate((Double)val);
                        }else{
                            if (ef.fieldType() != Class.class){
                                val = ef.fieldType().getMethod("getValue", String.class).invoke(null, val.toString());
                            }else{
                                val = Class.forName(this.getClass().getName().replaceAll(this.getClass().getSimpleName(),
                                    "fieldtype."+valType.getSimpleName()+"Type")).getMethod("getValue", String.class).invoke(null, val.toString());
                    }
                    val = null;
                    //悬浮图片
                    List<XSSFPictureData> xfData = ExcelPictureUtil.getPicturesFromCell(this.sheet,row.getCell(tcolumn));
                    List<XSSFPictureData> valList =new ArrayList<>();
                    if(qrData!=null){
                        valList.add(qrData);
                    }
                    if(xfData!=null){
                        valList.addAll(xfData);
                    }
                    if (valType==List.class){
                        val =valList;
                    } else if ( valType==XSSFPictureData.class){
                        val = (valList!=null && valList.size()>0)?valList.get(0):null;
                    }
                }else{
                    if (val != null){
                        try {
                            if (valType == String.class){
                                String s = String.valueOf(val.toString());
                                if(StringUtils.endsWith(s, ".0")){
                                    val = StringUtils.substringBefore(s, ".0");
                                }else{
                                    val = String.valueOf(val.toString()).trim();
                                }
                            }
                            else if (valType == Integer.class){
                                val = Double.valueOf(val.toString()).intValue();
                            }else if (valType == Long.class){
                                val = Double.valueOf(val.toString()).longValue();
                            }else if (valType == Double.class){
                                val = Double.valueOf(val.toString());
                            }else if (valType == Float.class){
                                val = Float.valueOf(val.toString());
                            }else if (valType == Date.class){
                                val = DateUtil.getJavaDate((Double)val);
                            }else if (valType == XSSFPictureData.class){
                            }else{
                                if (ef.fieldType() != Class.class){
                                    val = ef.fieldType().getMethod("getValue", String.class).invoke(null, val.toString());
                                }else{
                                    val = Class.forName(this.getClass().getName().replaceAll(this.getClass().getSimpleName(),
                                            "fieldtype."+valType.getSimpleName()+"Type")).getMethod("getValue", String.class).invoke(null, val.toString());
                                }
                            }
                        } catch (Exception ex) {
                            log.info("Get cell value ["+i+","+column+"] error: " + ex.toString());
                            val = null;
                        }
                    } catch (Exception ex) {
                        log.info("Get cell value ["+i+","+column+"] error: " + ex.toString());
                        val = null;
                    }
                    // set entity value
                    if (os[1] instanceof Field){
                        Reflections.invokeSetter(e, ((Field)os[1]).getName(), val);
                    }else if (os[1] instanceof Method){
                        String mthodName = ((Method)os[1]).getName();
                        if ("get".equals(mthodName.substring(0, 3))){
                            mthodName = "set"+StringUtils.substringAfter(mthodName, "get");
                        }
                        Reflections.invokeMethod(e, mthodName, new Class[] {valType}, new Object[] {val});
                    }
                }
                 if (val != null){
                     try {
                         // set entity value
                         if (os[1] instanceof Field){
                             Reflections.invokeSetter(e, ((Field)os[1]).getName(), val);
                         }else if (os[1] instanceof Method){
                             String mthodName = ((Method)os[1]).getName();
                             if ("get".equals(mthodName.substring(0, 3))){
                                 mthodName = "set"+StringUtils.substringAfter(mthodName, "get");
                             }
                             Reflections.invokeMethod(e, mthodName, new Class[] {valType}, new Object[] {val});
                         }
                     }catch (Exception e1){
                         val =null;
                     }
                }else{
                }
                sb.append(val+", ");
            }
server/services/src/main/java/com/doumee/core/annotation/excel/ExcelPictureUtil.java
@@ -7,17 +7,13 @@
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.openxml4j.opc.PackagePartName;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.*;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
@@ -315,4 +311,75 @@
        }
    }
    /**
     * èŽ·å–å•å…ƒæ ¼ä¸­çš„å›¾ç‰‡
     */
    public static List<XSSFPictureData> getPicturesFromCell(Sheet sheet, Cell cell) {
        try {
            List<XSSFPictureData> cellPictures = new ArrayList<>();
            XSSFDrawing drawing = ((XSSFSheet) sheet).createDrawingPatriarch();
            if (drawing != null) {
                List<XSSFPicture> pictures = drawing.getShapes().stream()
                        .filter(shape -> shape instanceof XSSFPicture)
                        .map(shape -> (XSSFPicture) shape).collect(Collectors.toList());
                for (XSSFPicture picture : pictures) {
                    int rowIndex = picture.getPreferredSize().getRow1();
                    int colIndex = picture.getPreferredSize().getCol1();
                    if (colIndex == cell.getColumnIndex() && rowIndex == cell.getRowIndex()) {
                        cellPictures.add(picture.getPictureData());
                    }
                }
            }
            return cellPictures;
        }catch (Exception e){
            e.printStackTrace();
        }
         return  null;
    }
    private static Map<String, List<XSSFPicture>> getImgPathMap(Sheet sheet) {
        Map<String, List<XSSFPicture>> imgPathMap = new HashMap<>();
        XSSFDrawing drawing = ((XSSFSheet) sheet).createDrawingPatriarch();
        if (drawing != null) {
            List<XSSFPicture> pictures = drawing.getShapes().stream()
                    .filter(shape -> shape instanceof XSSFPicture)
                    .map(shape -> (XSSFPicture) shape).collect(Collectors.toList());
            for (XSSFPicture picture : pictures) {
                int rowIndex = picture.getPreferredSize().getRow1();
                int colIndex = picture.getPreferredSize().getCol1();
                String key = colIndex + "-" + rowIndex;
                List<XSSFPicture> list = null;
                if (imgPathMap.containsKey(key)) {
                    list = imgPathMap.get(key);
                } else {
                    list = new ArrayList<>();
                    imgPathMap.put(key, list);
                }
                list.add(picture);
            }
        }
        return imgPathMap;
    }
    /**
     * èŽ·å–å›¾ç‰‡çš„æ‰©å±•å
     */
    private static String getImageExtension(PictureData picture) {
        String mimeType = picture.getMimeType();
        switch (mimeType) {
            case "image/jpeg":
                return "jpg";
            case "image/png":
                return "png";
            default:
                return "";
        }
    }
}
server/services/src/main/java/com/doumee/core/constants/Constants.java
@@ -76,6 +76,8 @@
    public static final Integer FOUR = 4;
    public static final Integer SIX = 6;
    public static final Integer FIVE = 5;
    public static final Integer DD_STATUS_SUCCESS_CODE = 200 ;
    public static final Long DD_ERR_CODE = 0L ;
    public static final String INENTITY_FILES = "INENTITY_FILES";
    public static final String MEMBER_FILES = "MEMBER_FILES";
    public static final String CATEGORY_FILES = "CATEGORY_FILES";
@@ -85,6 +87,10 @@
    public static final String ZBOM_TICKET_LOGIN_URL ="ZBOM_TICKET_LOGIN_URL" ;
    public static final String OBJCET_STORAGE = "OBJCET_STORAGE";
    public static final Object OBJECT_TYPE_CASES = "OBJECT_TYPE_CASES";
    public static final String DD_TALK = "DD_TALK" ;
    public static final String APP_KEY = "APP_KEY";
    public static final String APP_SECRET = "APP_SECRET";
    public static final String DD_USER_TYPE = "DD_USER";
    public static boolean WORKORDER_SHE_EMAIL_SENDING = false;
    public static  boolean DEALING_COMPANY_SYNC = false ;
    public static  boolean DEALING_MEMBER_SYNC = false ;
server/services/src/main/java/com/doumee/core/dingTalk/DingTalk.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,128 @@
package com.doumee.core.dingTalk;
import com.alibaba.fastjson.JSONObject;
import com.aliyun.dingtalkoauth2_1_0.Client;
import com.aliyun.dingtalkoauth2_1_0.models.GetAccessTokenRequest;
import com.aliyun.dingtalkoauth2_1_0.models.GetAccessTokenResponse;
import com.aliyun.dingtalkoauth2_1_0.models.GetTokenResponse;
import com.aliyun.dingtalktodo_1_0.models.*;
import com.aliyun.tea.TeaException;
import com.aliyun.teautil.models.RuntimeOptions;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.dingtalk.api.DefaultDingTalkClient;
import com.dingtalk.api.DingTalkClient;
import com.dingtalk.api.request.*;
import com.dingtalk.api.response.*;
import com.doumee.biz.system.SystemDictDataBiz;
import com.doumee.core.constants.Constants;
import com.doumee.core.constants.ResponseStatus;
import com.doumee.core.exception.BusinessException;
import com.doumee.dao.system.dto.DingLoginDTO;
import com.doumee.dao.system.model.SystemDictData;
import com.taobao.api.ApiException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.util.*;
import java.util.stream.Collectors;
/**
 * Created by IntelliJ IDEA.
 *
 * @Author : Rk
 * @create 2025/9/24 16:25
 */
@Slf4j
@Service
public class DingTalk {
    @Autowired
    private SystemDictDataBiz systemDictDataBiz;
    @Value("${dingtalk.clientId}")
    private String clientId;
    @Value("${dingtalk.clientSecret}")
    private String clientSecret;
    /**
     * ä½¿ç”¨ Token åˆå§‹åŒ–账号Client æ•°æ®åŒæ­¥ç±»
     * @return Client com.aliyun.dingtalkoauth2_1_0.
     * @throws Exception
     */
    public static Client createClient() throws Exception {
        com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config();
        config.protocol = "https";
        config.regionId = "central";
        return new Client(config);
    }
    /**
     * å¾…办通知类 é“¾æŽ¥æ± 
     * @return
     * @throws Exception
     */
    public static com.aliyun.dingtalktodo_1_0.Client createV1Client() throws Exception {
        com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config();
        config.protocol = "https";
        config.regionId = "central";
        return new com.aliyun.dingtalktodo_1_0.Client(config);
    }
    /**
     * èŽ·å–é’‰é’‰Token
     * @return
     */
    public String getToken(){
        String accessToken  =  systemDictDataBiz.queryByCode(Constants.DD_TALK,Constants.ACCESS_TOKEN).getCode();
        return accessToken;
    }
    private String getAccessToken(String corpId) {
        com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config();
        config.protocol = "https";
        config.regionId = "central";
        try {
            com.aliyun.dingtalkoauth2_1_0.Client client = new com.aliyun.dingtalkoauth2_1_0.Client(config);
            com.aliyun.dingtalkoauth2_1_0.models.GetTokenRequest getTokenRequest = new com.aliyun.dingtalkoauth2_1_0.models.GetTokenRequest()
                    .setClientId(clientId)
                    .setClientSecret(clientSecret)
                    .setGrantType("client_credentials");
            GetTokenResponse response = client.getToken(corpId, getTokenRequest);
            return response.getBody().accessToken;
        } catch (TeaException err) {
            if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) {
                // err ä¸­å«æœ‰ code å’Œ message å±žæ€§ï¼Œå¯å¸®åŠ©å¼€å‘å®šä½é—®é¢˜
                log.error("Error getting access token: {}", err.getMessage());
            }
        } catch (Exception _err) {
            TeaException err = new TeaException(_err.getMessage(), _err);
            if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) {
                // err ä¸­å«æœ‰ code å’Œ message å±žæ€§ï¼Œå¯å¸®åŠ©å¼€å‘å®šä½é—®é¢˜
                log.error("Error getting access token: {}", err.getMessage());
            }
        }
        return null;
    }
    public OapiV2UserGetuserinfoResponse.UserGetByCodeResponse  getDDUserByCode(DingLoginDTO dto) throws ApiException {
        DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/v2/user/getuserinfo");
        OapiV2UserGetuserinfoRequest req = new OapiV2UserGetuserinfoRequest();
        req.setCode(dto.getCode());
        OapiV2UserGetuserinfoResponse rsp = client.execute(req, getAccessToken(dto.getCorpId()));
        if(rsp.getErrcode().equals(Constants.DD_ERR_CODE)){
           return  rsp.getResult();
        }else{
            throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(),rsp.getMessage());
        }
    }
}
server/services/src/main/java/com/doumee/core/dingTalk/DingTalkStream.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,71 @@
package com.doumee.core.dingTalk;
import com.dingtalk.open.app.api.GenericEventListener;
import com.dingtalk.open.app.api.OpenDingTalkStreamClientBuilder;
import com.dingtalk.open.app.api.message.GenericOpenDingTalkEvent;
import com.dingtalk.open.app.api.security.AuthClientCredential;
import com.dingtalk.open.app.stream.protocol.event.EventAckStatus;
import com.doumee.biz.system.SystemDictDataBiz;
import com.doumee.core.constants.Constants;
import com.doumee.service.business.MemberService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import shade.com.alibaba.fastjson2.JSONObject;
/**
 * é’‰é’‰ è®¢é˜…事件通知
 *
 * @Author : Rk
 * @create 2025/9/24 17:14
 */
@Slf4j
@Configuration
public class DingTalkStream {
    @Autowired
    private SystemDictDataBiz systemDictDataBiz;
    @Bean
    public void DingTalkStreamRun()  throws Exception {
        String appKey  =  systemDictDataBiz.queryByCode(Constants.DD_TALK,Constants.APP_KEY).getCode();
        String appSecret  = systemDictDataBiz.queryByCode(Constants.DD_TALK,Constants.APP_SECRET).getCode();
        OpenDingTalkStreamClientBuilder
                .custom()
                .credential(new AuthClientCredential(appKey, appSecret))
                //注册事件监听
                .registerAllEventListener(new GenericEventListener() {
                    @Override
                    public EventAckStatus onEvent(GenericOpenDingTalkEvent event) {
                        try {
                            //事件唯一Id
                            String eventId = event.getEventId();
                            log.error("钉钉推送事件Id:{}"+eventId);
                            //事件类型
                            String eventType = event.getEventType();
                            log.error("钉钉推送事件类型:{}"+eventType);
                            //事件产生时间
                            Long bornTime = event.getEventBornTime();
                            log.error("钉钉推送事件产生时间:{}"+bornTime);
                            //获取事件体
                            JSONObject bizData = event.getData();
                            log.error("钉钉推送事件详情:{}"+bizData);
                            //处理事件
//                            process(bizData);
                            //消费成功
                            return EventAckStatus.SUCCESS;
                        } catch (Exception e) {
                            //消费失败
                            return EventAckStatus.LATER;
                        }
                    }
                })
                .build().start();
    }
}
server/services/src/main/java/com/doumee/dao/business/dto/CasesImport.java
@@ -3,6 +3,11 @@
import com.doumee.core.annotation.excel.ExcelColumn;
import io.swagger.annotations.ApiModel;
import lombok.Data;
import org.apache.poi.xssf.usermodel.XSSFPicture;
import org.apache.poi.xssf.usermodel.XSSFPictureData;
import java.util.Date;
import java.util.List;
/**
 * å‘˜å·¥ä¿¡æ¯å¯¼å…¥è¡¨
@@ -13,24 +18,31 @@
@ApiModel("员工信息导入")
public class CasesImport {
//    @ExcelColumn(name="序号",value = "sn")
    private Integer sn;
    @ExcelColumn(name="姓名",value = "name",index = 1)
    @ExcelColumn(name="案例主题",value = "name",index = 1)
    private String name;
    @ExcelColumn(name="手机号",value = "phone",index = 2)
    private String phone;
    @ExcelColumn(name="开始日期",value = "startDate",index = 2)
    private String startDate;
    @ExcelColumn(name="身份证号",value = "idcardNo",index = 3)
    private String idcardNo;
    @ExcelColumn(name="结束日期",value = "endDate",index = 3)
    private String endDate;
    @ExcelColumn(name="组织名称" , value = "companyName" ,index = 4)
    private String companyName;
    @ExcelColumn(name="服务老师" , value = "memberCode" ,index = 4)
    private String memberCode;
    @ExcelColumn(name="服务老师姓名" , value = "memberName" ,index = 5)
    private String memberName;
    @ExcelColumn(name="工号" , value = "code")
    private String code;
    @ExcelColumn(name="岗位" , value = "code")
    private String positionName;
    @ExcelColumn(name="案例说明" , value = "detail",index = 6)
    private String detail;
    @ExcelColumn(name="案例图1" , value = "imageList",fieldType = XSSFPictureData.class,index = 7)
    private List<XSSFPictureData> imageList;
    @ExcelColumn(name="案例图2" , value = "imageList1",fieldType = XSSFPictureData.class,index = 8)
    private List<XSSFPictureData> imageList1;
    @ExcelColumn(name="案例图3" , value = "imageList2",fieldType = XSSFPictureData.class,index = 9)
    private List<XSSFPictureData> imageList2;
    @ExcelColumn(name="案例图4" , value = "imageList3",fieldType = XSSFPictureData.class,index = 10)
    private List<XSSFPictureData> imageList3;
    @ExcelColumn(name="案例图5" , value = "imageList4",fieldType = XSSFPictureData.class,index = 11)
    private List<XSSFPictureData> imageList4;
    @ExcelColumn(name="案例图6" , value = "imageList5",fieldType = XSSFPictureData.class,index = 12)
    private List<XSSFPictureData> imageList5;
}
server/services/src/main/java/com/doumee/dao/business/dto/MemberImport.java
@@ -5,6 +5,7 @@
import com.doumee.dao.business.model.Category;
import io.swagger.annotations.ApiModel;
import lombok.Data;
import org.apache.poi.xssf.usermodel.XSSFPictureData;
import java.util.List;
@@ -20,8 +21,8 @@
    private String code;
    @ExcelColumn(name="姓名",value = "name",index = 2)
    private String name;
    @ExcelColumn(name="职业照",value = "imgurl",index = 3)
    private String imgurl;
    @ExcelColumn(name="职业照",value = "imgurl",index = 3,fieldType = XSSFPictureData.class)
    private XSSFPictureData imgurl;
    @ExcelColumn(name="等级",value = "levelName",index = 4)
    private String levelName;
    @ExcelColumn(name="性别" , value = "sex" ,index = 5)
server/services/src/main/java/com/doumee/dao/business/model/Cases.java
@@ -86,10 +86,22 @@
    @ApiModelProperty(value = "老师姓名", example = "1")
    @TableField(exist = false)
    private String memberName  ;
    @ApiModelProperty(value = "老师工号", example = "1")
    @TableField(exist = false)
    private String memberCode  ;
    @ApiModelProperty(value = "图集附件集合", example = "1")
    @TableField(exist = false)
    private List<Multifile> fileList;
    @ApiModelProperty(value = "最后操作人员;", example = "1")
    @TableField(exist = false)
    private String updateUserName;
    @ApiModelProperty(value = "图片集数据;", example = "1")
    @TableField(exist = false)
    private List<byte[]> imgdataList;
    @ApiModelProperty(value = "是否包含已删除 0不包含 1包含;", example = "1")
    @TableField(exist = false)
    private int containDeleted;
}
server/services/src/main/java/com/doumee/dao/business/model/ImportRecord.java
@@ -98,4 +98,7 @@
    @ApiModelProperty(value = "结束时间;", example = "1")
    @TableField(exist = false)
    private Date endtime;
    @ApiModelProperty(value = "进行中已处理的数量;", example = "1")
    @TableField(exist = false)
    private Integer ingNum;
}
server/services/src/main/java/com/doumee/dao/business/model/Member.java
@@ -181,4 +181,7 @@
    @ApiModelProperty(value = "最后操作人员;", example = "1")
    @TableField(exist = false)
    private String updateUserName;
    @ApiModelProperty(value = "是否包含已删除 0不包含 1包含;", example = "1")
    @TableField(exist = false)
    private int containDeleted;
}
server/services/src/main/java/com/doumee/dao/system/dto/DingLoginDTO.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,26 @@
package com.doumee.dao.system.dto;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import java.io.Serializable;
/**
 * @author  dm
 * @since 2025/03/31 16:44
 */
@Data
@ApiModel("登录参数")
public class DingLoginDTO implements Serializable {
    @NotBlank(message = "code不能为空")
    @ApiModelProperty(value = "code")
    private String code;
    @NotBlank(message = "corpId不能为空")
    @ApiModelProperty(value = "corpId")
    private String corpId;
}
server/services/src/main/java/com/doumee/dao/vo/WebLoginUserVO.java
@@ -19,10 +19,12 @@
    @ApiModelProperty(value = "用户主键")
    private String id;
    @ApiModelProperty(value = "用户角色:")
    @ApiModelProperty(value = "用户角色:   (dUser:标记为钉钉用户)")
    private String roleType;
    @ApiModelProperty(value = "战区编码")
    private String zhanqu;
    @ApiModelProperty(value = "token")
    private String token;
}
server/services/src/main/java/com/doumee/service/business/ImportRecordService.java
@@ -99,4 +99,5 @@
    ImportRecord importBatch(MultipartFile file, int type );
    void dealImporTask(ImportRecord importRecord);
    void clearImporTask();
}
server/services/src/main/java/com/doumee/service/business/impl/CasesServiceImpl.java
@@ -179,12 +179,13 @@
        MPJLambdaWrapper<Cases> queryWrapper = new MPJLambdaWrapper<>();
        queryWrapper.selectAll(Cases.class)
                .selectAs(Member::getName,Cases::getMemberName)
                .selectAs(Member::getCode,Cases::getMemberCode)
                .selectAs(SystemUser::getRealname, Member::getUpdateUserName)
                .leftJoin(SystemUser.class,SystemUser::getId,Cases::getUpdateUser)
                 .leftJoin(Member.class,Member::getId,Cases::getMemberId);
        Utils.MP.blankToNull(pageWrap.getModel());
        queryWrapper.eq(pageWrap.getModel().getContainDeleted()!=1,Cases::getDeleted, Constants.ZERO);
        queryWrapper.eq(pageWrap.getModel().getId() != null,Cases::getId, pageWrap.getModel().getId());
        queryWrapper.eq(pageWrap.getModel().getDeleted() != null,Cases::getDeleted, pageWrap.getModel().getDeleted());
        queryWrapper.eq(pageWrap.getModel().getCreateUser() != null,Cases::getCreateUser, pageWrap.getModel().getCreateUser());
        queryWrapper.eq(pageWrap.getModel().getUpdateUser() != null,Cases::getUpdateUser, pageWrap.getModel().getUpdateUser());
        queryWrapper.eq(pageWrap.getModel().getRemark() != null,Cases::getRemark, pageWrap.getModel().getRemark());
@@ -209,7 +210,7 @@
    }
    private void initMultifileList(Cases cate) {
        String path = systemDictDataBiz.queryByCode(Constants.OBJCET_STORAGE, Constants.RESOURCE_PATH).getCode()
                + systemDictDataBiz.queryByCode(Constants.OBJCET_STORAGE, Constants.CATEGORY_FILES).getCode();
                + systemDictDataBiz.queryByCode(Constants.OBJCET_STORAGE, Constants.CASES_FILES).getCode();
        Multifile find = new Multifile();
        find.setObjId(cate.getId());
server/services/src/main/java/com/doumee/service/business/impl/CategoryServiceImpl.java
@@ -283,8 +283,8 @@
                .orderByAsc(Category::getSortnum)
        );
        if(com.github.xiaoymin.knife4j.core.util.CollectionUtils.isNotEmpty(categoryList)){
            String path  = systemDictDataBiz.queryByCode(Constants.SYSTEM,Constants.RESOURCE_PATH).getCode()
                    +systemDictDataBiz.queryByCode(Constants.SYSTEM,Constants.CATEGORY_FILES).getCode();
            String path  = systemDictDataBiz.queryByCode(Constants.OBJCET_STORAGE,Constants.RESOURCE_PATH).getCode()
                    +systemDictDataBiz.queryByCode(Constants.OBJCET_STORAGE,Constants.CATEGORY_FILES).getCode();
            for (Category category:categoryList) {
                if(StringUtils.isNotBlank(category.getIcon())){
                    category.setIconFull(path + category.getIcon());
server/services/src/main/java/com/doumee/service/business/impl/ImportRecordServiceImpl.java
@@ -10,17 +10,11 @@
import com.doumee.core.model.PageWrap;
import com.doumee.core.utils.DateUtil;
import com.doumee.core.utils.tyyun.TyyZosUtil;
import com.doumee.dao.business.CasesMapper;
import com.doumee.dao.business.CategoryMapper;
import com.doumee.dao.business.MemberMapper;
import com.doumee.dao.business.*;
import com.doumee.dao.business.dto.CasesImport;
import com.doumee.dao.business.dto.MemberImport;
import com.doumee.dao.business.model.Cases;
import com.doumee.dao.business.model.Category;
import com.doumee.dao.business.model.ImportRecord;
import com.doumee.dao.business.model.*;
import com.doumee.core.utils.Utils;
import com.doumee.dao.business.ImportRecordMapper;
import com.doumee.dao.business.model.Member;
import com.doumee.dao.system.model.SystemUser;
import com.doumee.service.business.ImportRecordService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
@@ -44,6 +38,7 @@
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.io.ByteArrayInputStream;
import java.math.BigDecimal;
@@ -67,6 +62,8 @@
    private MemberMapper memberMapper;
    @Autowired
    private CasesMapper casesMapper;
    @Autowired
    private MultifileMapper multifileMapper;
    @Resource
    private RedisTemplate<String, Object> redisTemplate;
    @Resource
@@ -145,7 +142,8 @@
        MPJLambdaWrapper<ImportRecord> queryWrapper = new MPJLambdaWrapper<>();
        Utils.MP.blankToNull(pageWrap.getModel());
        queryWrapper.selectAll(ImportRecord.class )
        .selectAs(SystemUser::getRealname,ImportRecord::getUpdateUserName)
                .select( "(select count(c.id) from cases c where c.import_id= t.id)",ImportRecord::getIngNum)
                .selectAs(SystemUser::getRealname,ImportRecord::getUpdateUserName)
                .leftJoin(SystemUser.class,SystemUser::getId,ImportRecord::getUpdateUser);
       queryWrapper.eq(pageWrap.getModel().getId() != null,ImportRecord::getId, pageWrap.getModel().getId());
       queryWrapper.eq(pageWrap.getModel().getDeleted() != null,ImportRecord::getDeleted, pageWrap.getModel().getDeleted());
@@ -203,9 +201,7 @@
            Map<String, XSSFPictureData> pics = ie.getExcelPictures();
            if(type == 1) {
              List<CasesImport> importList =  (ie.getDataList(CasesImport.class,null));
              if(importList==null || importList.size()==0){
                  throw new BusinessException(ResponseStatus.DATA_EMPTY.getCode(),"导入文件案例信息内容为空!");
              }
              model.setCaseList(isvalidImpartCasesParam(loginUserInfo,pics,importList));
              model.setTotalNum(model.getCaseList().size());
            }else{
               List<MemberImport> importList = (ie.getDataList(MemberImport.class,null));
@@ -242,19 +238,21 @@
        int index = 1;
         for(MemberImport param :memberList){
             index ++;
             if(StringUtils.isBlank(param.getImgurl())
             ||StringUtils.isBlank(param.getFee())
             ||StringUtils.isBlank(param.getName())
             ||StringUtils.isBlank(param.getInfo())
             ||StringUtils.isBlank(param.getJobYear())
             ||StringUtils.isBlank(param.getPosition())
             ||StringUtils.isBlank(param.getFieldNames())
             ||StringUtils.isBlank(param.getSex())
             ||StringUtils.isBlank(param.getCode())
             ||StringUtils.isBlank(param.getZqNames())
             ||StringUtils.isBlank(param.getLevelName())
             ||StringUtils.isBlank(param.getServeNum())
             ||StringUtils.isBlank(param.getTypeNames())){
             if(( param.getImgurl() == null
                 ||param.getImgurl().getData() == null
                 ||param.getImgurl().getData().length == 0)
                     &&StringUtils.isBlank(param.getFee())
                     &&StringUtils.isBlank(param.getName())
                     &&StringUtils.isBlank(param.getInfo())
                     &&StringUtils.isBlank(param.getJobYear())
                     &&StringUtils.isBlank(param.getPosition())
                     &&StringUtils.isBlank(param.getFieldNames())
                     &&StringUtils.isBlank(param.getSex())
                     &&StringUtils.isBlank(param.getCode())
                     &&StringUtils.isBlank(param.getZqNames())
                     &&StringUtils.isBlank(param.getLevelName())
                     &&StringUtils.isBlank(param.getServeNum())
                     &&StringUtils.isBlank(param.getTypeNames())){
                 continue;
             }
             Member member = new Member();
@@ -295,7 +293,7 @@
             if(StringUtils.isBlank(param.getFee())){
                 throw  new BusinessException(ResponseStatus.BAD_REQUEST.getCode(),"对不起,第"+index+"行数据, è´¹ç”¨æ ‡å‡†ä¿¡æ¯ä¸èƒ½ä¸ºç©º");
             }
             if(pics!=null && StringUtils.isNotBlank(param.getImgurl())){
          /*   if(pics!=null && StringUtils.isNotBlank(param.getImgurl())){
                log.info("===================="+param.getImgurl());
                int start = param.getImgurl().indexOf("(\"")+2;
                int end = param.getImgurl().indexOf("\",");
@@ -307,7 +305,11 @@
                        member.setImgurlData(data.getData());
                    }
                }
            }
            }*/
             if(param.getImgurl() ==null ){
                 throw  new BusinessException(ResponseStatus.BAD_REQUEST.getCode(),"对不起,第"+index+"行【"+param.getName()+"】数据, æœªè¯»å–到任何职业照图片数据");
             }
             member.setImgurlData(param.getImgurl().getData());
             if(member.getImgurlData() ==null || member.getImgurlData().length==0){
                 throw  new BusinessException(ResponseStatus.BAD_REQUEST.getCode(),"对不起,第"+index+"行【"+param.getName()+"】数据, æœªè¯»å–到任何职业照图片数据");
             }
@@ -350,6 +352,91 @@
            throw  new BusinessException(ResponseStatus.BAD_REQUEST.getCode(),"对不起,未读取到有效数据");
        }
         return insertMember;
    }
    private  List<Cases> isvalidImpartCasesParam(LoginUserInfo user,  Map<String, XSSFPictureData> pics, List<CasesImport> casesImportList) {
        if(casesImportList ==null || casesImportList.size()==0){
            throw  new BusinessException(ResponseStatus.BAD_REQUEST.getCode(),"对不起,未读取到有效数据");
        }
        if(pics ==null || pics.size()==0){
            throw  new BusinessException(ResponseStatus.BAD_REQUEST.getCode(),"对不起,未读取到任何职业照图片数据");
        }
        List<Cases> insertList = new ArrayList<>();
        List<Member> allList = memberMapper.selectList(new QueryWrapper<Member>().lambda()
                .eq(Member::getDeleted,Constants.ZERO));
        allList=allList==null?new ArrayList<>():allList;
        if(allList == null || allList.size()==0){
            throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(),"对不起, è¯»å–老师数据异常,请先维护老师数据信息!");
        }
        Date date = new Date();
        int index = 1;
         for(CasesImport param :casesImportList){
             index ++;
             if(  StringUtils.isBlank(param.getName())
                     &&StringUtils.isBlank(param.getMemberCode())
                     &&StringUtils.isBlank(param.getStartDate())
                     &&StringUtils.isBlank(param.getEndDate())
                     &&StringUtils.isBlank(param.getDetail())){
                 continue;
             }
             Cases cases = new Cases();
             cases.setStartDate(DateUtil.fromStringToDate("yyyy-MM-dd",param.getStartDate()));
             cases.setEndDate(DateUtil.fromStringToDate("yyyy-MM-dd",param.getEndDate()));
             if(StringUtils.isBlank(param.getName())){
                 throw  new BusinessException(ResponseStatus.BAD_REQUEST.getCode(),"对不起,第"+index+"行数据, æ¡ˆä¾‹ä¸»é¢˜ä¸èƒ½ä¸ºç©º");
             }
             Member member =null;
             for(Member m : allList){
                 if(StringUtils.equals(param.getMemberCode(),m.getCode())){
                    member = m;
                 }
             }
             if(member == null){
                 throw  new BusinessException(ResponseStatus.BAD_REQUEST.getCode(),"对不起,第"+index+"行数据, è€å¸ˆå·¥å·ã€"+param.getMemberCode()+"】信息不存在,请确认不要重复录入");
             }
             if(StringUtils.isBlank(param.getDetail())){
                 throw  new BusinessException(ResponseStatus.BAD_REQUEST.getCode(),"对不起,第"+index+"行数据, æ¡ˆä¾‹è¯´æ˜Žä¸èƒ½ä¸ºç©º");
             }
             if(param.getImageList() == null){
                 param.setImageList(new ArrayList<>());
             }
             param.getImageList().addAll(param.getImageList1()!=null?param.getImageList1():new ArrayList<>());
             param.getImageList().addAll(param.getImageList2()!=null?param.getImageList2():new ArrayList<>());
             param.getImageList().addAll(param.getImageList3()!=null?param.getImageList3():new ArrayList<>());
             param.getImageList().addAll(param.getImageList4()!=null?param.getImageList4():new ArrayList<>());
             param.getImageList().addAll(param.getImageList5()!=null?param.getImageList5():new ArrayList<>());
         /*    if(param.getImageList() == null
                     ||param.getImageList().size() == 0 ){
                 throw  new BusinessException(ResponseStatus.BAD_REQUEST.getCode(),"对不起,第"+index+"行数据, æ¡ˆä¾‹å›¾ä¿¡æ¯ä¸èƒ½ä¸ºç©º");
             }*/
             if(cases.getStartDate()==null){
                 throw  new BusinessException(ResponseStatus.BAD_REQUEST.getCode(),"对不起,第"+index+"行数据, å¼€å§‹æ—¥æœŸè¯»å–失败");
             }
             if(cases.getEndDate()==null){
                 throw  new BusinessException(ResponseStatus.BAD_REQUEST.getCode(),"对不起,第"+index+"行数据, ç»“束日期读取失败");
             }
             cases.setImgdataList(new ArrayList<>());
             for(XSSFPictureData d : param.getImageList()){
                 cases.getImgdataList().add(d.getData());
             }
             cases.setCreateTime(date);
             cases.setUpdateTime(date);
             cases.setCreateUser(user.getId());
             cases.setUpdateUser(user.getId());
             cases.setAddType(Constants.ONE);
             cases.setDeleted(Constants.ZERO);
             cases.setStatus(Constants.ZERO);
             cases.setName(param.getName());
             cases.setDetail(param.getDetail());
             cases.setMemberId(member.getId());
             insertList.add(cases);
         }
        if(insertList ==null || insertList.size()==0){
            throw  new BusinessException(ResponseStatus.BAD_REQUEST.getCode(),"对不起,未读取到有效数据");
        }
         return insertList;
    }
@@ -414,22 +501,66 @@
    }
    /**
     * å¼‚步执行文件任务
     */
    @Override
    public  void clearImporTask(){
        try {
            List<ImportRecord> records = importRecordMapper.selectList(new QueryWrapper<ImportRecord>()
                    .select("id,total_num,(select count(c.id) from cases c where c.import_id= import_record.id) as doneNum")
                    .lambda()
                    .eq(ImportRecord::getDetail,Constants.ZERO)
                    .ne(ImportRecord::getStatus,Constants.TWO)
            );
            for(ImportRecord importRecord : records){
                importRecord.setErrorNum(Constants.formatIntegerNum(importRecord.getTotalNum()- Constants.formatIntegerNum(importRecord.getDoneNum())));
                importRecord.setStatus(Constants.TWO);
                importRecord.setUpdateTime(new Date());
                importRecord.setRemark("任务执行中断,强制设置任务状态");
                importRecordMapper.updateById(importRecord);
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            redisTemplate.delete(Constants.RedisKeys.IMPORTING_RECORD);
        }
    }
    /**
     * å¤„理案例导入任务
     * @param importRecord
     */
    private int dealCaseImportBiz(ImportRecord importRecord) {
        int success=0;
        String msg ="";
        String msg = "";
        String nowDate =DateUtil.getNowShortDate();
        try {
            for(Cases param:importRecord.getCaseList()){
            String bucket =systemDictDataBiz.queryByCode(Constants.OBJCET_STORAGE,Constants.BUCKETNAME).getCode();
            String folder =systemDictDataBiz.queryByCode(Constants.OBJCET_STORAGE,Constants.CASES_FILES).getCode();
            TyyZosUtil obs = new TyyZosUtil(systemDictDataBiz.queryByCode(Constants.OBJCET_STORAGE,Constants.ENDPOINT).getCode(),
                    systemDictDataBiz.queryByCode(Constants.OBJCET_STORAGE,Constants.ACCESS_ID).getCode(),
                    systemDictDataBiz.queryByCode(Constants.OBJCET_STORAGE,Constants.ACCESS_KEY).getCode());
            for(Cases param: importRecord.getCaseList()){
                int ts =0;
                try {
                    param.setImportId(importRecord.getId());
                    param.setAddType(Constants.ONE);
                    ts =  dealCasesInsert(obs,param,folder,nowDate,bucket);
                }catch (Exception e){
                    log.error("处理人员信息发生异常{}",e.getMessage());
                    ts =0;
                }
                success += ts;
            }
            obs.shutDown();
        }catch (Exception e){
        }
        importRecord.setDoneNum(success);
        importRecord.setErrorNum(importRecord.getTotalNum() - success);
        importRecord.setDetail(msg);
        redisTemplate.delete(Constants.RedisKeys.IMPORTING_RECORD);
        return success;
    }
@@ -464,6 +595,35 @@
    }
    @Transactional
    private int dealCasesInsert( TyyZosUtil obs,Cases param,String folder,String nowDate,String bucketName) {
        int success = casesMapper.insert(param);
        if(param.getImgdataList()!=null && param.getImgdataList().size()>0){
            List<Multifile> multifileList = new ArrayList<>();
            for(byte[] d : param.getImgdataList()){
                String fileName = UUID.randomUUID() + ".png";
                String tempFileName = nowDate + "/" + fileName;
                String key = folder + tempFileName;// æ–‡ä»¶å
                if (obs.uploadInputstreamObjectNoShutdown(new ByteArrayInputStream(d ) ,bucketName,  key)) {
                    Multifile s = new Multifile();
                    s.setIsdeleted(Constants.ZERO);
                    s.setCreator(param.getCreateUser());
                    s.setCreateDate(param.getCreateTime());
                    s.setObjId(param.getId());
                    s.setType(Constants.ZERO);
                    s.setFileurl(tempFileName);
                    s.setObjType(Constants.ONE);
                    multifileList.add(s);
                    param.setImgurl(tempFileName);//证件照地址
                }else{
                    throw  new BusinessException(ResponseStatus.SERVER_ERROR.getCode(),"图集上传失败!");
                }
            }
            multifileMapper.insert(multifileList);
        }
        return success;
}
    private int dealMemberInsert( TyyZosUtil obs,Member param,String folder,String nowDate,String bucketName) {
        int success =0;
        try {
server/services/src/main/java/com/doumee/service/business/impl/MemberServiceImpl.java
@@ -221,8 +221,9 @@
                .apply(Objects.nonNull(model.getBustypeIds())," find_in_set( '["+model.getBustypeIds()+"]', t.BUSTYPE_IDS ) ")
                .apply(Objects.nonNull(model.getZhanquIds())," find_in_set( '["+model.getZhanquIds()+"]', t.ZHANQU_IDS ) ")
                .like(StringUtils.isNotBlank(model.getName()),Member::getName, model.getName())
                .eq(Objects.nonNull(model.getImportId()),Member::getImportId, model.getImportId())
                .eq(Objects.nonNull(model.getStatus()),Member::getStatus, model.getStatus())
                .eq(Member::getDeleted, Constants.ZERO)
                .eq(model.getContainDeleted()!=1,Member::getDeleted, Constants.ZERO)
                .in(Objects.nonNull(model.getLevelId()),Category::getId, model.getLevelId())
                .eq(Objects.nonNull(model.getCode()),Member::getCode, model.getCode())
                .orderByDesc(Objects.nonNull(model.getOrderByType())&&Constants.equalsInteger(model.getOrderByType(), Constants.ZERO),Member::getFee)
@@ -235,11 +236,13 @@
        if(Constants.equalsInteger(pageWrap.getModel().getQueryFlag(),Constants.ONE)){
            queryWrapper.select("(select count(c.id) from cases c where c.deleted=0 and c.member_id=t.id)",Member::getCaseNum);
        }
        if(StringUtils.isNotBlank(model.getFieldIds())){
            String [] fieldIds = model.getFieldIds().split(",");
            for (String s:fieldIds) {
                queryWrapper.apply("find_in_set( '["+s+"]' , t.FIELD_IDS )");
        if(CollectionUtils.isNotEmpty(model.getFieldIdList())){
            String sql = "";
            for (Integer s:model.getFieldIdList()
                 ) {
                sql = sql + (StringUtils.isNotBlank(sql)?" or ":"") + " find_in_set( '["+s+"]' , t.FIELD_IDS ) ";
            }
            queryWrapper.apply(sql);
        }
        if (StringUtils.isNotBlank(model.getQueryZQCode())) {
            Category zhanqu = categoryMapper.selectOne(new QueryWrapper<Category>().lambda()
@@ -261,19 +264,12 @@
            );
            String path = systemDictDataBiz.queryByCode(Constants.OBJCET_STORAGE, Constants.RESOURCE_PATH).getCode() +
                    systemDictDataBiz.queryByCode(Constants.OBJCET_STORAGE, Constants.MEMBER_FILES).getCode();
            String roleConfig = systemDictDataBiz.queryByCode(Constants.SYSTEM, Constants.ROLE_CONFIG).getCode();
            for (Member member:memberIPage.getRecords()) {
                if(CollectionUtils.isNotEmpty(categoryList)){
                    dealMemberField(member,categoryList);
                    if(Constants.equalsInteger(pageWrap.getModel().getQueryFlag(),Constants.ONE)) {
                        dealMemberCategoryList(member, categoryList);
                    }
                    dealMemberCategoryList(member, categoryList,pageWrap.getModel().getQueryFlag());
                }
                member.setFullImgurl(StringUtils.isNotBlank(member.getImgurl())?(path + member.getImgurl()):"");
                if(!Constants.equalsInteger(pageWrap.getModel().getQueryFlag(),Constants.ONE) && (StringUtils.isBlank(roleConfig)||StringUtils.isBlank(model.getQueryUserRole())
                        || !roleConfig.contains(model.getQueryUserRole()))){
                    member.setFee(null);
                }
               if(member.getJobYear()!=null){
                    member.setWorkYears(DateUtil.getCurrentYear( ) - member.getJobYear()+1);
                }
@@ -282,36 +278,38 @@
        return PageData.from(memberIPage);
    }
    private void dealMemberCategoryList(Member member, List<Category> categoryList) {
        member.setFieldIdList(new ArrayList<>());
        member.setBustypeIdList(new ArrayList<>());
        member.setZhanquIdList(new ArrayList<>());
    private void dealMemberCategoryList(Member member, List<Category> categoryList, Integer queryFlag) {
        member.setFieldList(new ArrayList<>());
        member.setTypeList(new ArrayList<>());
        member.setZqList(new ArrayList<>());
        member.setBustypeIdList(new ArrayList<>());
        member.setZhanquIdList(new ArrayList<>());
        for(Category c:categoryList){
//            0=战区;1=商业化;2=擅长领域;
            if(Constants.equalsInteger(c.getType(),Constants.ZERO)&& StringUtils.contains(member.getZhanquIds(),"["+c.getId()+"]")){
                //战区
                member.getZqList().add(c);
                member.getZhanquIdList().add(c.getId());
            }
            if(Constants.equalsInteger(c.getType(),Constants.ONE)&& StringUtils.contains(member.getBustypeIds(),"["+c.getId()+"]")){
                //商业化
                member.getTypeList().add(c);
                member.getBustypeIdList().add(c.getId());
            }
            if(Constants.equalsInteger(c.getType(),Constants.TWO) && StringUtils.contains(member.getFieldIds(),"["+c.getId()+"]")){
                //擅长领域
                member.getFieldList().add(c);
                member.getFieldIdList().add(c.getId());
            if(Constants.equalsInteger(queryFlag,Constants.ONE)) {
                //            0=战区;1=商业化;2=擅长领域;
                if(Constants.equalsInteger(c.getType(),Constants.ZERO)&& StringUtils.contains(member.getZhanquIds(),"["+c.getId()+"]")){
                    //战区
                    member.getZqList().add(c);
                    member.getZhanquIdList().add(c.getId());
                }
                if(Constants.equalsInteger(c.getType(),Constants.TWO) && StringUtils.contains(member.getFieldIds(),"["+c.getId()+"]")){
                    //擅长领域
                    member.getFieldList().add(c);
                    member.getFieldIdList().add(c.getId());
                }
            }
        }
    }
    @Override
    public Member findDetailById(Integer id,String queryUserRole) {
    public Member findDetailById(Integer id,String userRole) {
        Member member = memberMapper.selectJoinOne(Member.class, new MPJLambdaWrapper<Member>()
                .selectAll(Member.class)
                .select(" c1.NAME ", Member::getPromotionName)
@@ -336,7 +334,7 @@
       }
        String resourcePath = systemDictDataBiz.queryByCode(Constants.OBJCET_STORAGE, Constants.RESOURCE_PATH).getCode();
        String path =  systemDictDataBiz.queryByCode(Constants.OBJCET_STORAGE, Constants.CATEGORY_FILES).getCode();
        String path =  systemDictDataBiz.queryByCode(Constants.OBJCET_STORAGE, Constants.MEMBER_FILES).getCode();
        String roleConfig = systemDictDataBiz.queryByCode(Constants.SYSTEM, Constants.ROLE_CONFIG).getCode();
        member.setFullImgurl(StringUtils.isNotBlank(member.getImgurl())?(resourcePath  + path + member.getImgurl()):"");
        List<Cases> casesList = casesMapper.selectList(new QueryWrapper<Cases>().lambda()
@@ -345,7 +343,7 @@
                .orderByDesc(Cases::getId)
        );
        if(CollectionUtils.isNotEmpty(casesList)){
            String casePath =  systemDictDataBiz.queryByCode(Constants.OBJCET_STORAGE, Constants.CASES_FILES).getCode();
            String casePath =  systemDictDataBiz.queryByCode(Constants.OBJCET_STORAGE, Constants.CATEGORY_FILES).getCode();
            for (Cases cases:casesList) {
                List<Multifile> multifileList = multifileMapper.selectList(new QueryWrapper<Multifile>().lambda()
                        .eq(Multifile::getObjId,cases.getId())
@@ -356,11 +354,12 @@
                multifileList.forEach(multifile -> {
                    multifile.setUrl(StringUtils.isNotBlank(multifile.getFileurl())?(resourcePath  + casePath + multifile.getFileurl()):"");
                });
                cases.setFileList(multifileList);
            }
            member.setCasesList(casesList);
        }
        if(StringUtils.isBlank(roleConfig)||StringUtils.isBlank(queryUserRole)
                || !roleConfig.contains(queryUserRole)){
        if(StringUtils.isBlank(roleConfig)||StringUtils.isBlank(userRole)
                || !(roleConfig.contains(userRole)||userRole.equals(Constants.DD_USER_TYPE) )){
            member.setFee(null);
        }
        return member;
@@ -390,4 +389,5 @@
    }
}
server/services/src/main/resources/application-dev.yml
@@ -86,4 +86,9 @@
  # æ¨¡å¼ï¼Œtesting测试模式
  mode: testing
dingtalk:
  clientId: dingulzemj5bynjciapg
  clientSecret: tLnWtSmmTuqjX9a1MvJzYxI1iXVJxEwtyZZYYFQ5cLg57pzzCZ4J8VsVwvmRNtkK
server/web/src/main/java/com/doumee/api/web/LoginController.java
@@ -2,6 +2,7 @@
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.dingtalk.api.response.OapiV2UserGetuserinfoResponse;
import com.doumee.api.BaseController;
import com.doumee.biz.system.SystemDictDataBiz;
import com.doumee.config.annotation.LoginRequired;
@@ -10,6 +11,7 @@
import com.doumee.core.annotation.pr.PreventRepeat;
import com.doumee.core.annotation.trace.Trace;
import com.doumee.core.constants.Constants;
import com.doumee.core.dingTalk.DingTalk;
import com.doumee.core.model.ApiResponse;
import com.doumee.core.model.LoginUserInfo;
import com.doumee.core.model.PageData;
@@ -18,16 +20,19 @@
import com.doumee.dao.business.dto.LoginRequestNewParam;
import com.doumee.dao.business.model.Category;
import com.doumee.dao.business.model.Member;
import com.doumee.dao.system.dto.DingLoginDTO;
import com.doumee.dao.system.model.SystemJob;
import com.doumee.dao.vo.WebLoginUserVO;
import com.doumee.service.business.CategoryService;
import com.doumee.service.business.MemberService;
import com.sun.deploy.net.HttpUtils;
import com.taobao.api.ApiException;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
@@ -42,6 +47,7 @@
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.UUID;
/**
@@ -67,14 +73,17 @@
    @Autowired
    private MemberService memberService;
    @Autowired
    private DingTalk dingTalk;
    @ApiOperation("UK单点登录")
    @GetMapping("/ukLogin")
    public void ukLogin(String tick, Object obj, HttpServletRequest request, HttpServletResponse response) throws Exception  {
        LoginRequestNewParam requestParam = new LoginRequestNewParam();
        /*// UK_ERROR_URL = "http://u.zhibang.com/sso/web/token/error";
        // UK_ERROR_URL = "http://u.zhibang.com/sso/web/token/error";
        String errorUrl =systemDictDataBiz.queryByCode(Constants.ZBOM_PARAM,Constants.ZBOM_UK_ERROR_URL).getCode();
        try {
       /* try {
            log.error("请求参数TICK最原始===========:" + tick);
            JSONObject urlParams = new JSONObject();
            log.info("请求参数:" + JSON.toJSONString(urlParams));
@@ -106,6 +115,19 @@
        response.sendRedirect(requestParam.getRediUrl()+"?token="+token);
    }
    @ApiOperation("钉钉登录")
    @PostMapping("/ddLogin")
    public ApiResponse<WebLoginUserVO> ddLogin(@Validated @RequestBody DingLoginDTO dingLoginDTO)  throws ApiException {
        WebLoginUserVO loginUserVO = new WebLoginUserVO();
        OapiV2UserGetuserinfoResponse.UserGetByCodeResponse response = dingTalk.getDDUserByCode(dingLoginDTO);
        if(Objects.nonNull(response)){
            loginUserVO.setId(response.getUserid());
            loginUserVO.setRoleType(Constants.DD_USER_TYPE);
        }
        loginUserVO.setToken(jwtTokenUtil.generateToken(loginUserVO));
        return ApiResponse.success(loginUserVO);
    }
    private String enCode(String string) {
        // TODO Auto-generated method stub
@@ -129,7 +151,17 @@
        WebLoginUserVO loginUserVO = this.getMemberResponse();
        pageWrap.getModel().setQueryUserRole(loginUserVO.getRoleType());
        pageWrap.getModel().setQueryZQCode(loginUserVO.getZhanqu());
        return ApiResponse.success(memberService.findPage(pageWrap));
        PageData<Member> pageData = memberService.findPage(pageWrap);
        if(CollectionUtils.isNotEmpty(pageData.getRecords())){
            String roleConfig = systemDictDataBiz.queryByCode(Constants.SYSTEM, Constants.ROLE_CONFIG).getCode();
            if(StringUtils.isBlank(roleConfig)||StringUtils.isBlank(pageWrap.getModel().getQueryUserRole())
                    || ! (roleConfig.contains(pageWrap.getModel().getQueryUserRole()) || pageWrap.getModel().getQueryUserRole().equals(Constants.DD_USER_TYPE) )){
                pageData.getRecords().forEach(i->{
                    i.setFee(null);
                });
            }
        }
        return ApiResponse.success(pageData);
    }
@@ -158,4 +190,7 @@
}