Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,4 @@ public class ContentDoc {

@Field(type = FieldType.Date, format = {}, pattern = "uuuu-MM-dd HH:mm:ss")
private LocalDateTime createdAt;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,4 @@ public class SearchContentDTO {
// 高亮片段映射(Key 为字段名,Value 为带 HTML 的高亮字符串)
// 例如:{"title": "如何学习<em>Java</em>"}
private Map<String, String> highlights;
}
}
84 changes: 68 additions & 16 deletions microlink-content/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,30 +8,36 @@
<version>3.2.0</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<groupId>org.microserviceteam</groupId>
<artifactId>microlink-content</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>microlink-content</name>
<description>Demo project for Spring Boot</description>
<url/>
<licenses>
<license/>
</licenses>
<developers>
<developer/>
</developers>
<scm>
<connection/>
<developerConnection/>
<tag/>
<url/>
</scm>
<description>MicroLink Content Service</description>

<properties>
<java.version>21</java.version>
<java.version>17</java.version>
<spring-cloud.version>2023.0.0</spring-cloud.version>
<spring-cloud-alibaba.version>2023.0.1.0</spring-cloud-alibaba.version>
<byte-buddy.version>1.15.10</byte-buddy.version>
<mockito.version>5.14.2</mockito.version>
</properties>

<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring-cloud-alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>bom</artifactId>
Expand Down Expand Up @@ -59,6 +65,16 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>

<!-- Nacos Discovery -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

<dependency>
<groupId>com.mysql</groupId>
Expand Down Expand Up @@ -116,6 +132,21 @@
<optional>true</optional>
</dependency>

<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>5.14.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>net.bytebuddy</groupId>
<artifactId>byte-buddy</artifactId>
</dependency>
<dependency>
<groupId>net.bytebuddy</groupId>
<artifactId>byte-buddy-agent</artifactId>
</dependency>

<!-- Metadata Extractor -->
<dependency>
<groupId>com.drewnoakes</groupId>
Expand All @@ -129,6 +160,27 @@
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.example.microlink_content.client;
package org.microserviceteam.microlink_content.client;

import lombok.Data;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.example.microlink_content.client;
package org.microserviceteam.microlink_content.client;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.client.RestTemplateBuilder;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package org.microserviceteam.microlink_content.client;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import java.util.Map;

@Component
public class WorkflowClient {

private final RestTemplate restTemplate;

@Value("${microlink.workflow-service.url:http://localhost:8083}")
private String workflowServiceUrl;

public WorkflowClient(RestTemplateBuilder builder) {
this.restTemplate = builder.build();
}

public void startProcess(String processKey, Map<String, Object> variables) {
try {
restTemplate.postForObject(
workflowServiceUrl + "/workflow/start/" + processKey,
variables,
Object.class
);
} catch (Exception e) {
e.printStackTrace();
// Handle error (log it, etc.)
}
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package com.example.microlink_content.controller;
package org.microserviceteam.microlink_content.controller;

import com.example.microlink_content.model.Content;
import com.example.microlink_content.model.ContentMedia;
import com.example.microlink_content.payload.request.PublishRequest;
import com.example.microlink_content.payload.response.ContentListResponse;
import com.example.microlink_content.service.ContentService;
import org.microserviceteam.microlink_content.model.Content;
import org.microserviceteam.microlink_content.model.ContentMedia;
import org.microserviceteam.microlink_content.payload.request.PublishRequest;
import org.microserviceteam.microlink_content.payload.response.ContentListResponse;
import org.microserviceteam.microlink_content.service.ContentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
Expand All @@ -30,7 +30,13 @@ public ResponseEntity<?> upload(@RequestParam("file") MultipartFile file) {

@PostMapping("/publish")
public ResponseEntity<?> publish(@RequestBody PublishRequest request) {
String authorId = (String) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
String authorId;
if (principal instanceof org.springframework.security.core.userdetails.UserDetails) {
authorId = ((org.springframework.security.core.userdetails.UserDetails) principal).getUsername();
} else {
authorId = principal.toString();
}
Content content = contentService.publishContent(request, authorId);
return ResponseEntity.status(HttpStatus.CREATED).body(content);
}
Expand Down Expand Up @@ -79,9 +85,32 @@ public ResponseEntity<?> update(@PathVariable Long id, @RequestBody PublishReque
return ResponseEntity.ok().build();
}

@PutMapping("/status/{id}")
public ResponseEntity<?> updateStatus(@PathVariable Long id, @RequestParam String status) {
try {
Content.ContentStatus contentStatus = Content.ContentStatus.valueOf(status.toUpperCase());
contentService.updateStatus(id, contentStatus);
return ResponseEntity.ok().build();
} catch (IllegalArgumentException e) {
return ResponseEntity.badRequest().body("Invalid status");
}
}

@PostMapping("/check/{id}")
public ResponseEntity<Boolean> checkContent(@PathVariable Long id) {
boolean result = contentService.checkContent(id);
return ResponseEntity.ok(result);
}

@DeleteMapping("/{id}")
public ResponseEntity<?> delete(@PathVariable Long id) {
String authorId = (String) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
String authorId;
if (principal instanceof org.springframework.security.core.userdetails.UserDetails) {
authorId = ((org.springframework.security.core.userdetails.UserDetails) principal).getUsername();
} else {
authorId = principal.toString();
}
contentService.deleteContent(id, authorId);
return ResponseEntity.noContent().build();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package com.example.microlink_content.controller;
package org.microserviceteam.microlink_content.controller;

import com.example.microlink_content.model.Content;
import com.example.microlink_content.service.ContentService;
import com.example.microlink_content.service.ProcessService;
import org.microserviceteam.microlink_content.model.Content;
import org.microserviceteam.microlink_content.service.ContentService;
import org.microserviceteam.microlink_content.service.ProcessService;
import org.flowable.task.api.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
Expand All @@ -25,7 +25,7 @@ public class ReviewController {
@GetMapping("/tasks")
public ResponseEntity<List<Map<String, Object>>> getReviewTasks() {
// In real world, we check if user is admin
List<Task> tasks = processService.getTasks("admin");
List<Task> tasks = processService.getTasksByProcessKey("admin", "content-publish-process-v2");

List<Map<String, Object>> response = new ArrayList<>();
for (Task task : tasks) {
Expand All @@ -50,24 +50,10 @@ public ResponseEntity<List<Map<String, Object>>> getReviewTasks() {
public ResponseEntity<?> completeReview(@PathVariable String taskId, @RequestBody Map<String, Boolean> body) {
boolean approved = body.getOrDefault("approved", false);

try {
Task task = processService.getTask(taskId);
if (task != null) {
Object contentIdObj = processService.getVariable(task.getProcessInstanceId(), "contentId");
if (contentIdObj != null) {
Long contentId = Long.valueOf(contentIdObj.toString());
if (approved) {
contentService.updateStatus(contentId, Content.ContentStatus.PUBLISHED);
} else {
contentService.updateStatus(contentId, Content.ContentStatus.REJECTED);
}
}
}
} catch (Exception e) {
// Log error but proceed to complete task
}
Map<String, Object> variables = new HashMap<>();
variables.put("approved", approved);

processService.completeTask(taskId);
processService.completeTask(taskId, variables);
return ResponseEntity.ok(Map.of("message", "Review completed"));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package org.microserviceteam.microlink_content.delegate;

import org.flowable.engine.delegate.DelegateExecution;
import org.flowable.engine.delegate.JavaDelegate;
import org.microserviceteam.microlink_content.client.UserDTO;
import org.microserviceteam.microlink_content.client.UserServiceClient;
import org.microserviceteam.microlink_content.service.EmailService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class ContentApprovalNotificationDelegate implements JavaDelegate {

@Autowired
private EmailService emailService;

@Autowired
private UserServiceClient userServiceClient;

@Override
public void execute(DelegateExecution execution) {
Boolean approved = (Boolean) execution.getVariable("approved");
String authorId = (String) execution.getVariable("authorId");
Long contentId = (Long) execution.getVariable("contentId");

UserDTO user = userServiceClient.getUser(authorId);
if (user == null || user.getEmail() == null) {
return;
}

if (approved != null && approved) {
emailService.sendSimpleMessage(user.getEmail(),
"内容审批通过",
"亲爱的 " + user.getUsername() + ",您的内容 (ID: " + contentId + ") 已通过审批并发布!");
} else {
emailService.sendSimpleMessage(user.getEmail(),
"内容审批拒绝",
"亲爱的 " + user.getUsername() + ",很抱歉,您的内容 (ID: " + contentId + ") 审批未通过。");
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package org.microserviceteam.microlink_content.delegate;

import org.flowable.engine.delegate.DelegateExecution;
import org.flowable.engine.delegate.JavaDelegate;
import org.microserviceteam.microlink_content.model.Content;
import org.microserviceteam.microlink_content.service.ContentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class ContentPublishDelegate implements JavaDelegate {

@Autowired
private ContentService contentService;

@Override
public void execute(DelegateExecution execution) {
Long contentId = (Long) execution.getVariable("contentId");
contentService.updateStatus(contentId, Content.ContentStatus.PUBLISHED);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package org.microserviceteam.microlink_content.delegate;

import org.flowable.engine.delegate.DelegateExecution;
import org.flowable.engine.delegate.JavaDelegate;
import org.microserviceteam.microlink_content.model.Content;
import org.microserviceteam.microlink_content.service.ContentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class ContentRejectDelegate implements JavaDelegate {

@Autowired
private ContentService contentService;

@Override
public void execute(DelegateExecution execution) {
Long contentId = (Long) execution.getVariable("contentId");
contentService.updateStatus(contentId, Content.ContentStatus.REJECTED);
}
}
Loading