This commit is contained in:
王子琦
2026-01-14 14:27:39 +08:00
parent f567e733d3
commit 2343001168
29 changed files with 262 additions and 30 deletions

View File

@@ -39,7 +39,7 @@ public class SecurityConfig {
.sessionManagement(sm -> sm.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.authorizeHttpRequests(auth -> auth
.requestMatchers(HttpMethod.OPTIONS, "/**").permitAll()
.requestMatchers("/api/auth/**", "/api/public/**", "/error").permitAll()
.requestMatchers("/api/auth/**", "/api/public/**", "/files/**", "/error").permitAll()
.anyRequest().authenticated()
)
.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);

View File

@@ -1,4 +1,4 @@
package com.toyshop.config;
package com.toyshop.config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;

View File

@@ -81,7 +81,14 @@ public class AdminController {
@GetMapping("/products")
public ApiResponse<List<Product>> products() {
return ApiResponse.ok(productRepository.findAll());
List<Product> products = productRepository.findAll();
for (Product product : products) {
var img = productService.getFirstImage(product);
if (img != null) {
product.setImageUrl(img.getUrl());
}
}
return ApiResponse.ok(products);
}
@PostMapping("/products")
@@ -148,6 +155,16 @@ public class AdminController {
return ApiResponse.ok("删除成功", null);
}
@PutMapping("/products/{id}/image")
public ApiResponse<?> replaceProductImage(@PathVariable Long id, @RequestBody ProductImage body) {
Product product = productRepository.findById(id).orElseThrow();
if (body.getUrl() == null || body.getUrl().isBlank()) {
return ApiResponse.fail("图片地址不能为空");
}
productService.replaceProductImage(product, body.getUrl());
return ApiResponse.ok("更新成功", null);
}
@GetMapping("/orders")
public ApiResponse<List<Order>> orders() {
return ApiResponse.ok(orderRepository.findAll());

View File

@@ -1,4 +1,4 @@
package com.toyshop.controller.admin;
package com.toyshop.controller.admin;
import com.toyshop.dto.ApiResponse;
import org.springframework.beans.factory.annotation.Value;

View File

@@ -1,5 +1,6 @@
package com.toyshop.entity;
import com.fasterxml.jackson.annotation.JsonIgnore;
import jakarta.persistence.*;
import java.time.LocalDateTime;
@@ -12,6 +13,7 @@ public class Address {
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id", nullable = false)
@JsonIgnore
private User user;
@Column(nullable = false, length = 50)

View File

@@ -1,5 +1,7 @@
package com.toyshop.entity;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import jakarta.persistence.*;
@Entity
@@ -11,10 +13,12 @@ public class CartItem {
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id", nullable = false)
@JsonIgnore
private User user;
@ManyToOne(fetch = FetchType.LAZY)
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "product_id", nullable = false)
@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
private Product product;
@Column(nullable = false)

View File

@@ -1,5 +1,6 @@
package com.toyshop.entity;
import com.fasterxml.jackson.annotation.JsonIgnore;
import jakarta.persistence.*;
import java.math.BigDecimal;
import java.time.LocalDateTime;
@@ -16,6 +17,7 @@ public class Order {
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id", nullable = false)
@JsonIgnore
private User user;
@Enumerated(EnumType.STRING)

View File

@@ -1,5 +1,7 @@
package com.toyshop.entity;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import jakarta.persistence.*;
import java.math.BigDecimal;
@@ -12,10 +14,12 @@ public class OrderItem {
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "order_id", nullable = false)
@JsonIgnore
private Order order;
@ManyToOne(fetch = FetchType.LAZY)
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "product_id", nullable = false)
@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
private Product product;
@Column(nullable = false)

View File

@@ -47,6 +47,9 @@ public class Product {
@Column(nullable = false)
private LocalDateTime updatedAt;
@Transient
private String imageUrl;
@PrePersist
public void prePersist() {
LocalDateTime now = LocalDateTime.now();
@@ -81,4 +84,6 @@ public class Product {
public void setOnSale(boolean onSale) { this.onSale = onSale; }
public LocalDateTime getCreatedAt() { return createdAt; }
public LocalDateTime getUpdatedAt() { return updatedAt; }
public String getImageUrl() { return imageUrl; }
public void setImageUrl(String imageUrl) { this.imageUrl = imageUrl; }
}

View File

@@ -1,5 +1,6 @@
package com.toyshop.entity;
import com.fasterxml.jackson.annotation.JsonIgnore;
import jakarta.persistence.*;
@Entity
@@ -11,6 +12,7 @@ public class ProductImage {
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "product_id", nullable = false)
@JsonIgnore
private Product product;
@Column(nullable = false, length = 255)

View File

@@ -4,7 +4,10 @@ import com.toyshop.entity.ProductImage;
import com.toyshop.entity.Product;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.List;
import java.util.Optional;
public interface ProductImageRepository extends JpaRepository<ProductImage, Long> {
List<ProductImage> findByProduct(Product product);
Optional<ProductImage> findTopByProductOrderBySortOrderAsc(Product product);
void deleteByProduct(Product product);
}

View File

@@ -3,6 +3,7 @@ package com.toyshop.service;
import com.toyshop.entity.*;
import com.toyshop.repository.*;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.util.List;
@@ -23,6 +24,7 @@ public class OrderService {
this.addressRepository = addressRepository;
}
@Transactional
public Order createOrder(User user, Long addressId) {
Address address = addressRepository.findById(addressId).orElseThrow();
if (!address.getUser().getId().equals(user.getId())) {

View File

@@ -5,6 +5,7 @@ import com.toyshop.repository.*;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import jakarta.persistence.criteria.Predicate;
import java.util.ArrayList;
@@ -59,4 +60,18 @@ public class ProductService {
public List<Category> allCategories() {
return categoryRepository.findAll();
}
public ProductImage getFirstImage(Product product) {
return productImageRepository.findTopByProductOrderBySortOrderAsc(product).orElse(null);
}
@Transactional
public void replaceProductImage(Product product, String url) {
productImageRepository.deleteByProduct(product);
ProductImage image = new ProductImage();
image.setProduct(product);
image.setUrl(url);
image.setSortOrder(0);
productImageRepository.save(image);
}
}