Browse Source

Merge remote-tracking branch 'origin/master'

yusm 1 month ago
parent
commit
85e17eba00
14 changed files with 193 additions and 19 deletions
  1. 1 1
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/login.vue
  2. 30 3
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/analysis/api.ts
  3. 59 7
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/analysis/components/AIChat.vue
  4. 14 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/controller/AIQuestionController.java
  5. 8 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/entity/AIQuestion.java
  6. 4 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/AIQuestionService.java
  7. 47 1
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/AIQuestionServiceImpl.java
  8. 2 2
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/ProjectController.java
  9. 2 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/mapper/ProjectDeptRelateMapper.java
  10. 1 1
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/ProjectService.java
  11. 16 1
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ProjectServiceImpl.java
  12. 2 2
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/WxCorpInfoServiceImpl.java
  13. 6 0
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/ProjectDeptRelateMapper.xml
  14. 1 1
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/UserCorpwxTimeMapper.xml

+ 1 - 1
fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/login.vue

@@ -69,7 +69,7 @@ function verifyLoginEnvironment() {
     loginByUserId(loginUserId);
   } else {
     // 判断是否为企业微信授权
-    if (isCorpWX.value) {
+    if (isCorpWX.value || isWX.value) {
       // 判断企业微信,是否存在授权
       if (href.includes("com/?code")) {
         bindIfNessary()

+ 30 - 3
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/analysis/api.ts

@@ -102,10 +102,26 @@ export type AIQuestionParams = {
   url?: string;
 };
 
-export type AIQuestionResponse = {
+export interface ChatContent {
+  type: 0 | 1;
+  content: string;
+  questionId?: number;
+}
+
+export interface LatestQuestionResponse {
   code: string;
-  data: string;
-};
+  data: {
+    contents: ChatContent[];
+  };
+}
+
+export interface AIQuestionResponse {
+  code: string;
+  data: {
+    queryRes: string;
+    questionId: number;
+  };
+}
 
 export async function askAIQuestion(
   payload: AIQuestionParams
@@ -124,3 +140,14 @@ export async function uploadFileApi(file: File): Promise<UploadFileResponse> {
   
   return await requestUploadFile('/common/uploadFile', formData);
 }
+
+export interface ChatContent {
+  type: 0 | 1;
+  content: string;
+  createTime: string;
+  questionId?: number;
+}
+
+export async function getLatestQuestionList(): Promise<LatestQuestionResponse> {
+  return await post('/aiQuestion/getLatestQuestionList');
+}

+ 59 - 7
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/analysis/components/AIChat.vue

@@ -111,12 +111,22 @@
 </template>
 
 <script lang="ts" setup>
-import { ref, reactive, nextTick, computed } from 'vue';
+import { ref, reactive, nextTick, computed, onMounted } from 'vue';
 import { marked } from 'marked';
 import { ChatLineRound, User, Download } from '@element-plus/icons-vue';
 import { Document, Paragraph, TextRun, Packer } from 'docx';
-import { askAIQuestion, uploadFileApi, type AIQuestionParams, type UploadFileResponse } from '../api';
+import { 
+  askAIQuestion,
+  uploadFileApi, 
+  getLatestQuestionList,
+  type AIQuestionParams,
+  type UploadFileResponse,
+  type ChatContent,
+  type LatestQuestionResponse,
+  type AIQuestionResponse
+} from '../api';
 import { ElMessage } from 'element-plus/es'
+import * as internal from 'stream';
 const renderMarkdown = (content: string): string => {
   // Configure marked with options
   marked.setOptions({
@@ -300,9 +310,45 @@ const dateRange = ref([getFirstDayOfMonth(), new Date()]);
 // Chat functionality
 const inputMessage = ref('请进行数据分析,给一个总结报告,不超过300字');
 const loading = ref(false);
-const messages = reactive<ChatMessage[]>([
-  { role: 'assistant', content: '你好,需要分析查询哪些数据,请交给我' },
-]);
+const messages = reactive<ChatMessage[]>([]);
+const questionId = ref<number | null>(null);
+
+const isSameDay = (dateString: string, compareDate: Date) => {
+  // Parse yyyy-MM-dd hh:mm:ss format
+  const [datePart] = dateString.split(' ');
+  const [year, month, day] = datePart.split('-').map(Number);
+  
+  return year === compareDate.getFullYear() &&
+         month - 1 === compareDate.getMonth() && // Months are 0-indexed in JS
+         day === compareDate.getDate();
+};
+
+onMounted(async () => {
+  try {
+    const result = await getLatestQuestionList();
+    if (result.code === 'ok' && result.data.contents) {
+      result.data.contents.forEach(content => {
+        messages.push({
+          role: content.type === 0 ? 'assistant' : 'user',
+          content: content.content
+        });
+
+        // Check if createTime is today and set questionId
+        if (content.createTime && content.questionId) {
+          if (isSameDay(content.createTime, new Date())) {
+            questionId.value = content.questionId;
+          }
+        }
+      });
+    } else {
+      // Default message if no history
+      messages.push({ role: 'assistant', content: '你好,需要分析查询哪些数据,请交给我' });
+    }
+  } catch (error) {
+    console.error('Failed to load chat history:', error);
+    messages.push({ role: 'assistant', content: '你好,需要分析查询哪些数据,请交给我' });
+  }
+});
 
 const sendMessage = async () => {
   if (!inputMessage.value.trim() || loading.value) return;
@@ -322,7 +368,7 @@ const sendMessage = async () => {
       'free': 4
     };
 
-    const params: AIQuestionParams = {
+    const params: AIQuestionParams & { questionId?: number } = {
       questionDataSource: dataSourceMap[dataSource.value],
       sourceContent: dataSource.value === 'system' ? systemTable.value : '',
       content: inputMessage.value,
@@ -331,12 +377,18 @@ const sendMessage = async () => {
       url: dataSource.value === 'upload' ? uploadedFilePath.value : ''
     };
 
+    // Only include questionId if we have one from today's conversation
+    if (questionId.value) {
+      params.questionId = questionId.value;
+    }
+
     const result = await askAIQuestion(params);
     messages[thinkingIndex] = {
       role: 'assistant',
-      content: result.data || '根据您的请求,我已分析了相关数据。分析结果显示...',
+      content: result.data.queryRes || '根据您的请求,我已分析了相关数据。分析结果显示...',
       loading: false
     };
+    questionId.value = result.data.questionId;
   } catch (error) {
     console.error('API error:', error);
     messages[thinkingIndex] = {

+ 14 - 0
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/controller/AIQuestionController.java

@@ -34,4 +34,18 @@ public class AIQuestionController {
         return responseEntity;
     }
 
+    @PostMapping("/getLatestQuestionList")
+    public HttpRespMsg getLatestQuestion(HttpServletRequest request){
+        HttpRespMsg msg = new HttpRespMsg();
+        msg = aiQuestionService.getLatestQuestionList(request);
+        return msg;
+    }
+
+    @PostMapping("/getHisQuestion")
+    public HttpRespMsg getHisQuestion(HttpServletRequest request){
+        HttpRespMsg msg = new HttpRespMsg();
+        msg = aiQuestionService.getHisQuestion(request);
+        return msg;
+    }
+
 }

+ 8 - 0
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/entity/AIQuestion.java

@@ -39,4 +39,12 @@ public class AIQuestion extends Model<AIQuestion> {
      */
     @TableField("creator_id")
     private String creatorId;
+
+    /**
+     * 会话名称
+     */
+    @TableField("name")
+    private String name;
+
+
 }

+ 4 - 0
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/AIQuestionService.java

@@ -12,4 +12,8 @@ public interface AIQuestionService extends IService<AIQuestion> {
     HttpRespMsg ask(QuestionBO questionBO, HttpServletRequest request);
 
     ResponseEntity<byte[]> downloadContent(Integer questionId, HttpServletRequest request);
+
+    HttpRespMsg getLatestQuestionList(HttpServletRequest request);
+
+    HttpRespMsg getHisQuestion(HttpServletRequest request);
 }

+ 47 - 1
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/AIQuestionServiceImpl.java

@@ -343,11 +343,14 @@ public class AIQuestionServiceImpl extends ServiceImpl<AIQuestionMapper, AIQuest
             }
         }
 
+        Map<String,Object> resMap = new HashMap<>();
+
         if(null == questionBO.getQuestionId()){
             //提问获取回答,再插入
             AIQuestion aiQuestion = new AIQuestion();
             aiQuestion.setCompanyId(user.getCompanyId());
             aiQuestion.setCreatorId(user.getId());
+            aiQuestion.setName(questionBO.getContent());
             aiQuestionMapper.insert(aiQuestion);
 
             Integer questionId = aiQuestion.getQuestionId();
@@ -376,6 +379,8 @@ public class AIQuestionServiceImpl extends ServiceImpl<AIQuestionMapper, AIQuest
             aiAnswer.setStartDate(questionBO.getStartDate());
             aiAnswer.setEndDate(questionBO.getEndDate());
             aiQuestionDetailMapper.insert(aiAnswer);
+
+            resMap.put("questionId",questionId);
         } else {
             Integer questionId = questionBO.getQuestionId();
             AIQuestionDetail lastOne = aiQuestionDetailMapper.selectOne(new LambdaQueryWrapper<AIQuestionDetail>()
@@ -414,9 +419,12 @@ public class AIQuestionServiceImpl extends ServiceImpl<AIQuestionMapper, AIQuest
             aiAnswer.setEndDate(questionBO.getEndDate());
             aiQuestionDetailMapper.insert(aiAnswer);
 
+            resMap.put("questionId",questionId);
         }
 
-        httpRespMsg.setData(queryRes);
+
+        resMap.put("queryRes",queryRes);
+        httpRespMsg.setData(resMap);
         return httpRespMsg;
     }
 
@@ -476,6 +484,44 @@ public class AIQuestionServiceImpl extends ServiceImpl<AIQuestionMapper, AIQuest
                 .body(out.toByteArray());
     }
 
+    @Override
+    public HttpRespMsg getLatestQuestionList(HttpServletRequest request) {
+        HttpRespMsg httpRespMsg = new HttpRespMsg();
+        User user = userMapper.selectById(request.getHeader("token"));
+        AIQuestion aiQuestion = aiQuestionMapper.selectOne(new LambdaQueryWrapper<AIQuestion>()
+                .eq(AIQuestion::getCreatorId, user.getId())
+                .orderByDesc(AIQuestion::getCreateTime)
+                .last(" limit 1")
+        );
+        Map<String,Object> resMap = new HashMap<>();
+        if(null != aiQuestion){
+            List<AIQuestionDetail> aiQuestionDetails = aiQuestionDetailMapper.selectList(new LambdaQueryWrapper<AIQuestionDetail>()
+                    .select(AIQuestionDetail::getQuestionId, AIQuestionDetail::getSeq
+                            , AIQuestionDetail::getType, AIQuestionDetail::getContent)
+                    .eq(AIQuestionDetail::getQuestionId, aiQuestion.getQuestionId())
+                    .orderByAsc(AIQuestionDetail::getSeq)
+            );
+
+
+            resMap.put("latestQuestionId",aiQuestion.getQuestionId());
+            resMap.put("contents",aiQuestionDetails);
+            httpRespMsg.setData(resMap);
+        }
+        return httpRespMsg;
+    }
+
+    @Override
+    public HttpRespMsg getHisQuestion(HttpServletRequest request) {
+        HttpRespMsg httpRespMsg = new HttpRespMsg();
+        User user = userMapper.selectById(request.getHeader("token"));
+        List<AIQuestion> aiQuestions = aiQuestionMapper.selectList(new LambdaQueryWrapper<AIQuestion>()
+                .eq(AIQuestion::getCreatorId, user.getId())
+                .orderByDesc(AIQuestion::getCreateTime)
+        );
+        httpRespMsg.setData(aiQuestions);
+        return httpRespMsg;
+    }
+
     public static List<Map<String, Object>> convertListWithAlias(ResultSet rs) {
         List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
         try {

+ 2 - 2
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/ProjectController.java

@@ -743,8 +743,8 @@ public class ProjectController {
         return projectService.exportWaitingReviewList(request,stateKey,userId,startDate,endDate);
     }
     @RequestMapping("/batchSetParticipation")
-    public HttpRespMsg batchSetParticipation(HttpServletRequest request,String projectIdArray,String userIds){
-        return projectService.batchSetParticipation(request,projectIdArray,userIds);
+    public HttpRespMsg batchSetParticipation(HttpServletRequest request,String projectIdArray,String userIds,String deptIds){
+        return projectService.batchSetParticipation(request,projectIdArray,userIds,deptIds);
     }
     @RequestMapping("/changeCurrentStage")
     public HttpRespMsg changeCurrentStage(Integer projectId,Integer currentStageId,String currentStageName){

+ 2 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/mapper/ProjectDeptRelateMapper.java

@@ -8,4 +8,6 @@ import java.util.List;
 
 public interface ProjectDeptRelateMapper  extends BaseMapper<ProjectDeptRelate> {
     void insertBatch(@Param("projectId") Integer projectId,@Param("deptList") List<String> deptList);
+
+    void insertBatchList(@Param("toAddList") List<ProjectDeptRelate> toAddList);
 }

+ 1 - 1
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/ProjectService.java

@@ -176,7 +176,7 @@ public interface ProjectService extends IService<Project> {
 
     HttpRespMsg exportWaitingReviewList(HttpServletRequest request, Integer stateKey, String userId,String startDate,String endDate);
 
-    HttpRespMsg batchSetParticipation(HttpServletRequest request,String projectIdArray , String userIds);
+    HttpRespMsg batchSetParticipation(HttpServletRequest request,String projectIdArray , String userIds,String deptIds);
 
     HttpRespMsg suspendProject(Integer id);
 

+ 16 - 1
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ProjectServiceImpl.java

@@ -10234,11 +10234,14 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
     }
 
     @Override
-    public HttpRespMsg batchSetParticipation(HttpServletRequest request,String  projectIdArray,String userIds) {
+    public HttpRespMsg batchSetParticipation(HttpServletRequest request,String  projectIdArray,String userIds,String deptIds) {
         HttpRespMsg msg=new HttpRespMsg();
         User user = userMapper.selectById(request.getHeader("token"));
         List<Integer> array = JSONArray.parseArray(projectIdArray, Integer.class);
         List<String> userIdList = JSONArray.parseArray(userIds, String.class);
+        List<Integer> deptArray = JSONArray.parseArray(deptIds, Integer.class);
+        List<ProjectDeptRelate> toAddList = new ArrayList<>();
+
         List<Project> projectList = projectMapper.selectList(new QueryWrapper<Project>().eq("company_id", user.getCompanyId()).in("id",array));
         List<Participation> list=new ArrayList<>();
         for (Project project : projectList) {
@@ -10261,6 +10264,18 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
                     .setOperationTime(LocalDateTime.now())
                     .setContent("批量添加项目参与人");
             operationRecordService.save(operationRecord);
+            if(CollectionUtils.isNotEmpty(deptArray)){
+                for (Integer deptId : deptArray) {
+                    ProjectDeptRelate tmpRelate = new ProjectDeptRelate();
+                    tmpRelate.setProjectId(project.getId());
+                    tmpRelate.setDepartmentId(deptId);
+                    toAddList.add(tmpRelate);
+                }
+            }
+
+        }
+        if(CollectionUtils.isNotEmpty(toAddList)){
+            projectDeptRelateMapper.insertBatchList(toAddList);
         }
         participationService.saveBatch(list);
         return msg;

+ 2 - 2
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/WxCorpInfoServiceImpl.java

@@ -1752,8 +1752,8 @@ public class WxCorpInfoServiceImpl extends ServiceImpl<WxCorpInfoMapper, WxCorpI
                         }
                         if (showLog) System.out.println("工作时长==" + workHours);
 
-                        if (corpInfo.getCompanyId() == 481) {
-                            //给盛立安元0.5单位进位
+                        if (corpInfo.getCompanyId() == 481 || corpInfo.getCompanyId() == 469) {
+                            //给盛立安元和赛元微电子0.5单位进位
                             ct.setWorkHours(DateTimeUtil.getHalfHoursFromDouble(workHours));
                         } else {
                             ct.setWorkHours(DateTimeUtil.getHoursFromDouble(workHours));

+ 6 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/ProjectDeptRelateMapper.xml

@@ -9,4 +9,10 @@
             (#{projectId},#{deptId})
         </foreach>
     </insert>
+    <insert id="insertBatchList">
+        insert into project_dept_relate(project_id, department_id) VALUES
+        <foreach collection="toAddList" item="item" separator=",">
+            (#{item.projectId},#{item.departmentId})
+        </foreach>
+    </insert>
 </mapper>

+ 1 - 1
fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/UserCorpwxTimeMapper.xml

@@ -31,7 +31,7 @@
     <select id="getUserDataList" resultType="java.util.HashMap" >
         SELECT user.id as userId, department.department_name as departmentName, DATE_FORMAT(a.create_date, '%Y/%m/%d') as createDate,a.start_time as startTime, a.end_time as endTime, a.work_hours as workHours, user.name as username,user.corpwx_userid as corpwxUserid,a.week_day as weekDay,
         week_day_txt as weekDayTxt,card_time as cardTime, outdoor_time as outdoorTime, ask_leave_time as askLeaveTime FROM user_corpwx_time a
-        LEFT JOIN user ON  user.name = a.name AND a.`company_id` = user.`company_id`
+        LEFT JOIN user ON  (user.name = a.name OR user.`corpwx_userid` = a.`corpwx_userid`) AND a.`company_id` = user.`company_id`
         left join department on department.department_id = user.department_id
         WHERE a.create_date BETWEEN #{startDate} AND #{endDate}
         AND a.company_id = #{companyId}