feat(product): 添加商品管理功能模块
- 新增商品控制器ProductController,提供商品创建、查询、图片上传接口 - 实现商品详情页URL生成逻辑 - 添加商品图片单文件及批量上传功能,支持多种图片格式校验 - 集成OSS服务实现文件存储 - 新增商品响应DTO,包含商品基本信息、SKU列表及状态信息 - 定义商品服务接口及实现类,封装商品核心业务逻辑 - 添加商品状态枚举及SKU状态枚举定义 - 实现商品数据访问层基础结构
This commit is contained in:
144
logs/mt-pay-error.2025-12-19.log
Normal file
144
logs/mt-pay-error.2025-12-19.log
Normal file
@@ -0,0 +1,144 @@
|
||||
2025-12-19 18:34:38.656 [restartedMain] ERROR org.springframework.boot.SpringApplication - Application run failed
|
||||
java.lang.IllegalArgumentException: Invalid value type for attribute 'factoryBeanObjectType': java.lang.String
|
||||
at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.getTypeForFactoryBeanFromAttributes(FactoryBeanRegistrySupport.java:86)
|
||||
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.getTypeForFactoryBean(AbstractAutowireCapableBeanFactory.java:838)
|
||||
at org.springframework.beans.factory.support.AbstractBeanFactory.isTypeMatch(AbstractBeanFactory.java:620)
|
||||
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doGetBeanNamesForType(DefaultListableBeanFactory.java:573)
|
||||
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanNamesForType(DefaultListableBeanFactory.java:532)
|
||||
at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:138)
|
||||
at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:775)
|
||||
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:597)
|
||||
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146)
|
||||
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:753)
|
||||
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:455)
|
||||
at org.springframework.boot.SpringApplication.run(SpringApplication.java:323)
|
||||
at com.mtkj.mtpay.MtPayApplication.main(MtPayApplication.java:24)
|
||||
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
|
||||
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
|
||||
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
|
||||
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
|
||||
at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:50)
|
||||
2025-12-19 18:34:38.658 [restartedMain] ERROR com.mtkj.mtpay.MtPayApplication -
|
||||
╔══════════════════════════════════════════════════════════╗
|
||||
║ ║
|
||||
║ ❌ MTKJ PAY 支付系统启动失败! ❌ ║
|
||||
║ ║
|
||||
╚══════════════════════════════════════════════════════════╝
|
||||
|
||||
java.lang.IllegalArgumentException: Invalid value type for attribute 'factoryBeanObjectType': java.lang.String
|
||||
at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.getTypeForFactoryBeanFromAttributes(FactoryBeanRegistrySupport.java:86)
|
||||
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.getTypeForFactoryBean(AbstractAutowireCapableBeanFactory.java:838)
|
||||
at org.springframework.beans.factory.support.AbstractBeanFactory.isTypeMatch(AbstractBeanFactory.java:620)
|
||||
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doGetBeanNamesForType(DefaultListableBeanFactory.java:573)
|
||||
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanNamesForType(DefaultListableBeanFactory.java:532)
|
||||
at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:138)
|
||||
at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:775)
|
||||
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:597)
|
||||
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146)
|
||||
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:753)
|
||||
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:455)
|
||||
at org.springframework.boot.SpringApplication.run(SpringApplication.java:323)
|
||||
at com.mtkj.mtpay.MtPayApplication.main(MtPayApplication.java:24)
|
||||
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
|
||||
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
|
||||
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
|
||||
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
|
||||
at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:50)
|
||||
2025-12-19 18:34:38.661 [main] ERROR com.mtkj.mtpay.MtPayApplication -
|
||||
╔══════════════════════════════════════════════════════════╗
|
||||
║ ║
|
||||
║ ❌ MTKJ PAY 支付系统启动失败! ❌ ║
|
||||
║ ║
|
||||
╚══════════════════════════════════════════════════════════╝
|
||||
|
||||
org.springframework.boot.devtools.restart.SilentExitExceptionHandler$SilentExitException: null
|
||||
at org.springframework.boot.devtools.restart.SilentExitExceptionHandler.exitCurrentThread(SilentExitExceptionHandler.java:92)
|
||||
at org.springframework.boot.devtools.restart.Restarter.immediateRestart(Restarter.java:179)
|
||||
at org.springframework.boot.devtools.restart.Restarter.initialize(Restarter.java:163)
|
||||
at org.springframework.boot.devtools.restart.Restarter.initialize(Restarter.java:532)
|
||||
at org.springframework.boot.devtools.restart.RestartApplicationListener.onApplicationStartingEvent(RestartApplicationListener.java:98)
|
||||
at org.springframework.boot.devtools.restart.RestartApplicationListener.onApplicationEvent(RestartApplicationListener.java:51)
|
||||
at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:178)
|
||||
at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:171)
|
||||
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:149)
|
||||
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:137)
|
||||
at org.springframework.boot.context.event.EventPublishingRunListener.multicastInitialEvent(EventPublishingRunListener.java:136)
|
||||
at org.springframework.boot.context.event.EventPublishingRunListener.starting(EventPublishingRunListener.java:75)
|
||||
at org.springframework.boot.SpringApplicationRunListeners.lambda$starting$0(SpringApplicationRunListeners.java:54)
|
||||
at java.base/java.lang.Iterable.forEach(Iterable.java:75)
|
||||
at org.springframework.boot.SpringApplicationRunListeners.doWithListeners(SpringApplicationRunListeners.java:118)
|
||||
at org.springframework.boot.SpringApplicationRunListeners.starting(SpringApplicationRunListeners.java:54)
|
||||
at org.springframework.boot.SpringApplication.run(SpringApplication.java:315)
|
||||
at com.mtkj.mtpay.MtPayApplication.main(MtPayApplication.java:24)
|
||||
2025-12-19 18:34:49.156 [restartedMain] ERROR org.springframework.boot.SpringApplication - Application run failed
|
||||
java.lang.IllegalArgumentException: Invalid value type for attribute 'factoryBeanObjectType': java.lang.String
|
||||
at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.getTypeForFactoryBeanFromAttributes(FactoryBeanRegistrySupport.java:86)
|
||||
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.getTypeForFactoryBean(AbstractAutowireCapableBeanFactory.java:838)
|
||||
at org.springframework.beans.factory.support.AbstractBeanFactory.isTypeMatch(AbstractBeanFactory.java:620)
|
||||
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doGetBeanNamesForType(DefaultListableBeanFactory.java:573)
|
||||
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanNamesForType(DefaultListableBeanFactory.java:532)
|
||||
at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:138)
|
||||
at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:775)
|
||||
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:597)
|
||||
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146)
|
||||
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:753)
|
||||
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:455)
|
||||
at org.springframework.boot.SpringApplication.run(SpringApplication.java:323)
|
||||
at com.mtkj.mtpay.MtPayApplication.main(MtPayApplication.java:24)
|
||||
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
|
||||
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
|
||||
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
|
||||
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
|
||||
at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:50)
|
||||
2025-12-19 18:34:49.158 [restartedMain] ERROR com.mtkj.mtpay.MtPayApplication -
|
||||
╔══════════════════════════════════════════════════════════╗
|
||||
║ ║
|
||||
║ ❌ MTKJ PAY 支付系统启动失败! ❌ ║
|
||||
║ ║
|
||||
╚══════════════════════════════════════════════════════════╝
|
||||
|
||||
java.lang.IllegalArgumentException: Invalid value type for attribute 'factoryBeanObjectType': java.lang.String
|
||||
at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.getTypeForFactoryBeanFromAttributes(FactoryBeanRegistrySupport.java:86)
|
||||
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.getTypeForFactoryBean(AbstractAutowireCapableBeanFactory.java:838)
|
||||
at org.springframework.beans.factory.support.AbstractBeanFactory.isTypeMatch(AbstractBeanFactory.java:620)
|
||||
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doGetBeanNamesForType(DefaultListableBeanFactory.java:573)
|
||||
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanNamesForType(DefaultListableBeanFactory.java:532)
|
||||
at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:138)
|
||||
at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:775)
|
||||
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:597)
|
||||
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146)
|
||||
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:753)
|
||||
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:455)
|
||||
at org.springframework.boot.SpringApplication.run(SpringApplication.java:323)
|
||||
at com.mtkj.mtpay.MtPayApplication.main(MtPayApplication.java:24)
|
||||
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
|
||||
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
|
||||
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
|
||||
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
|
||||
at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:50)
|
||||
2025-12-19 18:34:49.161 [main] ERROR com.mtkj.mtpay.MtPayApplication -
|
||||
╔══════════════════════════════════════════════════════════╗
|
||||
║ ║
|
||||
║ ❌ MTKJ PAY 支付系统启动失败! ❌ ║
|
||||
║ ║
|
||||
╚══════════════════════════════════════════════════════════╝
|
||||
|
||||
org.springframework.boot.devtools.restart.SilentExitExceptionHandler$SilentExitException: null
|
||||
at org.springframework.boot.devtools.restart.SilentExitExceptionHandler.exitCurrentThread(SilentExitExceptionHandler.java:92)
|
||||
at org.springframework.boot.devtools.restart.Restarter.immediateRestart(Restarter.java:179)
|
||||
at org.springframework.boot.devtools.restart.Restarter.initialize(Restarter.java:163)
|
||||
at org.springframework.boot.devtools.restart.Restarter.initialize(Restarter.java:532)
|
||||
at org.springframework.boot.devtools.restart.RestartApplicationListener.onApplicationStartingEvent(RestartApplicationListener.java:98)
|
||||
at org.springframework.boot.devtools.restart.RestartApplicationListener.onApplicationEvent(RestartApplicationListener.java:51)
|
||||
at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:178)
|
||||
at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:171)
|
||||
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:149)
|
||||
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:137)
|
||||
at org.springframework.boot.context.event.EventPublishingRunListener.multicastInitialEvent(EventPublishingRunListener.java:136)
|
||||
at org.springframework.boot.context.event.EventPublishingRunListener.starting(EventPublishingRunListener.java:75)
|
||||
at org.springframework.boot.SpringApplicationRunListeners.lambda$starting$0(SpringApplicationRunListeners.java:54)
|
||||
at java.base/java.lang.Iterable.forEach(Iterable.java:75)
|
||||
at org.springframework.boot.SpringApplicationRunListeners.doWithListeners(SpringApplicationRunListeners.java:118)
|
||||
at org.springframework.boot.SpringApplicationRunListeners.starting(SpringApplicationRunListeners.java:54)
|
||||
at org.springframework.boot.SpringApplication.run(SpringApplication.java:315)
|
||||
at com.mtkj.mtpay.MtPayApplication.main(MtPayApplication.java:24)
|
||||
72
logs/mt-pay-error.2025-12-22.log
Normal file
72
logs/mt-pay-error.2025-12-22.log
Normal file
@@ -0,0 +1,72 @@
|
||||
2025-12-22 09:18:35.818 [restartedMain] ERROR org.springframework.boot.SpringApplication - Application run failed
|
||||
java.lang.IllegalArgumentException: Invalid value type for attribute 'factoryBeanObjectType': java.lang.String
|
||||
at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.getTypeForFactoryBeanFromAttributes(FactoryBeanRegistrySupport.java:86)
|
||||
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.getTypeForFactoryBean(AbstractAutowireCapableBeanFactory.java:838)
|
||||
at org.springframework.beans.factory.support.AbstractBeanFactory.isTypeMatch(AbstractBeanFactory.java:620)
|
||||
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doGetBeanNamesForType(DefaultListableBeanFactory.java:573)
|
||||
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanNamesForType(DefaultListableBeanFactory.java:532)
|
||||
at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:138)
|
||||
at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:775)
|
||||
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:597)
|
||||
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146)
|
||||
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:753)
|
||||
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:455)
|
||||
at org.springframework.boot.SpringApplication.run(SpringApplication.java:323)
|
||||
at com.mtkj.mtpay.MtPayApplication.main(MtPayApplication.java:24)
|
||||
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
|
||||
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
|
||||
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
|
||||
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
|
||||
at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:50)
|
||||
2025-12-22 09:18:35.820 [restartedMain] ERROR com.mtkj.mtpay.MtPayApplication -
|
||||
╔══════════════════════════════════════════════════════════╗
|
||||
║ ║
|
||||
║ ❌ MTKJ PAY 支付系统启动失败! ❌ ║
|
||||
║ ║
|
||||
╚══════════════════════════════════════════════════════════╝
|
||||
|
||||
java.lang.IllegalArgumentException: Invalid value type for attribute 'factoryBeanObjectType': java.lang.String
|
||||
at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.getTypeForFactoryBeanFromAttributes(FactoryBeanRegistrySupport.java:86)
|
||||
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.getTypeForFactoryBean(AbstractAutowireCapableBeanFactory.java:838)
|
||||
at org.springframework.beans.factory.support.AbstractBeanFactory.isTypeMatch(AbstractBeanFactory.java:620)
|
||||
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doGetBeanNamesForType(DefaultListableBeanFactory.java:573)
|
||||
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanNamesForType(DefaultListableBeanFactory.java:532)
|
||||
at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:138)
|
||||
at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:775)
|
||||
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:597)
|
||||
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146)
|
||||
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:753)
|
||||
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:455)
|
||||
at org.springframework.boot.SpringApplication.run(SpringApplication.java:323)
|
||||
at com.mtkj.mtpay.MtPayApplication.main(MtPayApplication.java:24)
|
||||
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
|
||||
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
|
||||
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
|
||||
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
|
||||
at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:50)
|
||||
2025-12-22 09:18:35.825 [main] ERROR com.mtkj.mtpay.MtPayApplication -
|
||||
╔══════════════════════════════════════════════════════════╗
|
||||
║ ║
|
||||
║ ❌ MTKJ PAY 支付系统启动失败! ❌ ║
|
||||
║ ║
|
||||
╚══════════════════════════════════════════════════════════╝
|
||||
|
||||
org.springframework.boot.devtools.restart.SilentExitExceptionHandler$SilentExitException: null
|
||||
at org.springframework.boot.devtools.restart.SilentExitExceptionHandler.exitCurrentThread(SilentExitExceptionHandler.java:92)
|
||||
at org.springframework.boot.devtools.restart.Restarter.immediateRestart(Restarter.java:179)
|
||||
at org.springframework.boot.devtools.restart.Restarter.initialize(Restarter.java:163)
|
||||
at org.springframework.boot.devtools.restart.Restarter.initialize(Restarter.java:532)
|
||||
at org.springframework.boot.devtools.restart.RestartApplicationListener.onApplicationStartingEvent(RestartApplicationListener.java:98)
|
||||
at org.springframework.boot.devtools.restart.RestartApplicationListener.onApplicationEvent(RestartApplicationListener.java:51)
|
||||
at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:178)
|
||||
at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:171)
|
||||
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:149)
|
||||
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:137)
|
||||
at org.springframework.boot.context.event.EventPublishingRunListener.multicastInitialEvent(EventPublishingRunListener.java:136)
|
||||
at org.springframework.boot.context.event.EventPublishingRunListener.starting(EventPublishingRunListener.java:75)
|
||||
at org.springframework.boot.SpringApplicationRunListeners.lambda$starting$0(SpringApplicationRunListeners.java:54)
|
||||
at java.base/java.lang.Iterable.forEach(Iterable.java:75)
|
||||
at org.springframework.boot.SpringApplicationRunListeners.doWithListeners(SpringApplicationRunListeners.java:118)
|
||||
at org.springframework.boot.SpringApplicationRunListeners.starting(SpringApplicationRunListeners.java:54)
|
||||
at org.springframework.boot.SpringApplication.run(SpringApplication.java:315)
|
||||
at com.mtkj.mtpay.MtPayApplication.main(MtPayApplication.java:24)
|
||||
76
logs/mt-pay.2025-12-22.log
Normal file
76
logs/mt-pay.2025-12-22.log
Normal file
@@ -0,0 +1,76 @@
|
||||
2025-12-22 09:18:34.910 [background-preinit] INFO org.hibernate.validator.internal.util.Version - HV000001: Hibernate Validator 8.0.1.Final
|
||||
2025-12-22 09:18:34.954 [restartedMain] INFO com.mtkj.mtpay.MtPayApplication - Starting MtPayApplication using Java 17.0.12 with PID 19392 (E:\MTKJPAY\mt-pay\target\classes started by 18969 in E:\MTKJPAY)
|
||||
2025-12-22 09:18:34.955 [restartedMain] INFO com.mtkj.mtpay.MtPayApplication - No active profile set, falling back to 1 default profile: "default"
|
||||
2025-12-22 09:18:35.783 [restartedMain] WARN o.s.b.w.s.c.AnnotationConfigServletWebServerApplicationContext - Exception encountered during context initialization - cancelling refresh attempt: java.lang.IllegalArgumentException: Invalid value type for attribute 'factoryBeanObjectType': java.lang.String
|
||||
2025-12-22 09:18:35.818 [restartedMain] ERROR org.springframework.boot.SpringApplication - Application run failed
|
||||
java.lang.IllegalArgumentException: Invalid value type for attribute 'factoryBeanObjectType': java.lang.String
|
||||
at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.getTypeForFactoryBeanFromAttributes(FactoryBeanRegistrySupport.java:86)
|
||||
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.getTypeForFactoryBean(AbstractAutowireCapableBeanFactory.java:838)
|
||||
at org.springframework.beans.factory.support.AbstractBeanFactory.isTypeMatch(AbstractBeanFactory.java:620)
|
||||
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doGetBeanNamesForType(DefaultListableBeanFactory.java:573)
|
||||
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanNamesForType(DefaultListableBeanFactory.java:532)
|
||||
at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:138)
|
||||
at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:775)
|
||||
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:597)
|
||||
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146)
|
||||
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:753)
|
||||
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:455)
|
||||
at org.springframework.boot.SpringApplication.run(SpringApplication.java:323)
|
||||
at com.mtkj.mtpay.MtPayApplication.main(MtPayApplication.java:24)
|
||||
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
|
||||
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
|
||||
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
|
||||
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
|
||||
at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:50)
|
||||
2025-12-22 09:18:35.820 [restartedMain] ERROR com.mtkj.mtpay.MtPayApplication -
|
||||
╔══════════════════════════════════════════════════════════╗
|
||||
║ ║
|
||||
║ ❌ MTKJ PAY 支付系统启动失败! ❌ ║
|
||||
║ ║
|
||||
╚══════════════════════════════════════════════════════════╝
|
||||
|
||||
java.lang.IllegalArgumentException: Invalid value type for attribute 'factoryBeanObjectType': java.lang.String
|
||||
at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.getTypeForFactoryBeanFromAttributes(FactoryBeanRegistrySupport.java:86)
|
||||
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.getTypeForFactoryBean(AbstractAutowireCapableBeanFactory.java:838)
|
||||
at org.springframework.beans.factory.support.AbstractBeanFactory.isTypeMatch(AbstractBeanFactory.java:620)
|
||||
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doGetBeanNamesForType(DefaultListableBeanFactory.java:573)
|
||||
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanNamesForType(DefaultListableBeanFactory.java:532)
|
||||
at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:138)
|
||||
at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:775)
|
||||
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:597)
|
||||
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146)
|
||||
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:753)
|
||||
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:455)
|
||||
at org.springframework.boot.SpringApplication.run(SpringApplication.java:323)
|
||||
at com.mtkj.mtpay.MtPayApplication.main(MtPayApplication.java:24)
|
||||
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
|
||||
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
|
||||
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
|
||||
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
|
||||
at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:50)
|
||||
2025-12-22 09:18:35.825 [main] ERROR com.mtkj.mtpay.MtPayApplication -
|
||||
╔══════════════════════════════════════════════════════════╗
|
||||
║ ║
|
||||
║ ❌ MTKJ PAY 支付系统启动失败! ❌ ║
|
||||
║ ║
|
||||
╚══════════════════════════════════════════════════════════╝
|
||||
|
||||
org.springframework.boot.devtools.restart.SilentExitExceptionHandler$SilentExitException: null
|
||||
at org.springframework.boot.devtools.restart.SilentExitExceptionHandler.exitCurrentThread(SilentExitExceptionHandler.java:92)
|
||||
at org.springframework.boot.devtools.restart.Restarter.immediateRestart(Restarter.java:179)
|
||||
at org.springframework.boot.devtools.restart.Restarter.initialize(Restarter.java:163)
|
||||
at org.springframework.boot.devtools.restart.Restarter.initialize(Restarter.java:532)
|
||||
at org.springframework.boot.devtools.restart.RestartApplicationListener.onApplicationStartingEvent(RestartApplicationListener.java:98)
|
||||
at org.springframework.boot.devtools.restart.RestartApplicationListener.onApplicationEvent(RestartApplicationListener.java:51)
|
||||
at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:178)
|
||||
at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:171)
|
||||
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:149)
|
||||
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:137)
|
||||
at org.springframework.boot.context.event.EventPublishingRunListener.multicastInitialEvent(EventPublishingRunListener.java:136)
|
||||
at org.springframework.boot.context.event.EventPublishingRunListener.starting(EventPublishingRunListener.java:75)
|
||||
at org.springframework.boot.SpringApplicationRunListeners.lambda$starting$0(SpringApplicationRunListeners.java:54)
|
||||
at java.base/java.lang.Iterable.forEach(Iterable.java:75)
|
||||
at org.springframework.boot.SpringApplicationRunListeners.doWithListeners(SpringApplicationRunListeners.java:118)
|
||||
at org.springframework.boot.SpringApplicationRunListeners.starting(SpringApplicationRunListeners.java:54)
|
||||
at org.springframework.boot.SpringApplication.run(SpringApplication.java:315)
|
||||
at com.mtkj.mtpay.MtPayApplication.main(MtPayApplication.java:24)
|
||||
@@ -0,0 +1,48 @@
|
||||
package com.mtkj.mtpay.common.enums;
|
||||
|
||||
/**
|
||||
* 商品状态枚举
|
||||
*/
|
||||
public enum ProductStatus {
|
||||
|
||||
/**
|
||||
* 上架
|
||||
*/
|
||||
ACTIVE("ACTIVE", "上架"),
|
||||
|
||||
/**
|
||||
* 下架
|
||||
*/
|
||||
INACTIVE("INACTIVE", "下架"),
|
||||
|
||||
/**
|
||||
* 已删除
|
||||
*/
|
||||
DELETED("DELETED", "已删除");
|
||||
|
||||
private final String code;
|
||||
private final String description;
|
||||
|
||||
ProductStatus(String code, String description) {
|
||||
this.code = code;
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public static ProductStatus fromCode(String code) {
|
||||
for (ProductStatus status : values()) {
|
||||
if (status.code.equals(code)) {
|
||||
return status;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,206 @@
|
||||
package com.mtkj.mtpay.controller;
|
||||
|
||||
import com.mtkj.mtpay.common.Result;
|
||||
import com.mtkj.mtpay.dto.request.CreateProductRequestDTO;
|
||||
import com.mtkj.mtpay.dto.response.ProductResponseDTO;
|
||||
import com.mtkj.mtpay.service.ProductService;
|
||||
import jakarta.validation.Valid;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 商品管理控制器
|
||||
*/
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping("/api/product")
|
||||
public class ProductController {
|
||||
|
||||
@Autowired
|
||||
private ProductService productService;
|
||||
|
||||
@Autowired
|
||||
private com.mtkj.mtpay.service.OssService ossService;
|
||||
|
||||
/**
|
||||
* 创建商品
|
||||
*/
|
||||
@PostMapping
|
||||
public Result<ProductResponseDTO> createProduct(@Valid @RequestBody CreateProductRequestDTO request) {
|
||||
log.info("创建商品请求:{}", request);
|
||||
ProductResponseDTO product = productService.createProduct(request);
|
||||
return Result.success("商品创建成功", product);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取商品详情
|
||||
*/
|
||||
@GetMapping("/{id}")
|
||||
public Result<ProductResponseDTO> getProduct(@PathVariable Long id) {
|
||||
log.info("获取商品详情,商品ID:{}", id);
|
||||
ProductResponseDTO product = productService.getProductById(id);
|
||||
return Result.success(product);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取商品详情页URL
|
||||
*/
|
||||
@GetMapping("/{id}/url")
|
||||
public Result<Map<String, String>> getProductUrl(@PathVariable Long id) {
|
||||
log.info("获取商品URL,商品ID:{}", id);
|
||||
String url = productService.getProductUrl(id);
|
||||
Map<String, String> result = new HashMap<>();
|
||||
result.put("url", url);
|
||||
return Result.success(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传商品图片(单文件上传,参考mt-admin的CommonController实现)
|
||||
*/
|
||||
@PostMapping("/upload/image")
|
||||
public Result<Map<String, Object>> uploadImage(@RequestParam("file") MultipartFile file) {
|
||||
try {
|
||||
if (file == null || file.isEmpty()) {
|
||||
return Result.fail("文件不能为空");
|
||||
}
|
||||
|
||||
String originalFilename = file.getOriginalFilename();
|
||||
if (originalFilename == null) {
|
||||
return Result.fail("文件名不能为空");
|
||||
}
|
||||
|
||||
// 验证文件类型
|
||||
String extension = originalFilename.substring(originalFilename.lastIndexOf(".") + 1).toLowerCase();
|
||||
if (!isImageFile(extension)) {
|
||||
return Result.fail("只支持图片文件(jpg、jpeg、png、gif、webp、bmp)");
|
||||
}
|
||||
|
||||
// 验证文件大小(最大10MB)
|
||||
if (file.getSize() > 10 * 1024 * 1024) {
|
||||
return Result.fail("文件大小不能超过10MB");
|
||||
}
|
||||
|
||||
// 上传到OSS(参考mt-admin实现)
|
||||
byte[] content = file.getBytes();
|
||||
String imageUrl = ossService.upload(content, originalFilename);
|
||||
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
result.put("url", imageUrl);
|
||||
result.put("fileName", imageUrl);
|
||||
result.put("originalFilename", originalFilename);
|
||||
|
||||
log.info("图片上传成功,文件名: {}, URL: {}", originalFilename, imageUrl);
|
||||
return Result.success("图片上传成功", result);
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("图片上传失败", e);
|
||||
return Result.fail("图片上传失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量上传商品图片(多文件上传)
|
||||
*/
|
||||
@PostMapping("/upload/images")
|
||||
public Result<Map<String, Object>> uploadImages(@RequestParam("file") MultipartFile[] files) {
|
||||
if (files == null || files.length == 0) {
|
||||
return Result.fail("文件不能为空");
|
||||
}
|
||||
|
||||
try {
|
||||
List<Map<String, String>> uploadedFiles = new ArrayList<>();
|
||||
List<String> errors = new ArrayList<>();
|
||||
|
||||
for (int i = 0; i < files.length; i++) {
|
||||
MultipartFile uploadFile = files[i];
|
||||
|
||||
if (uploadFile == null || uploadFile.isEmpty()) {
|
||||
errors.add("第" + (i + 1) + "个文件为空");
|
||||
continue;
|
||||
}
|
||||
|
||||
// 验证文件类型
|
||||
String originalFilename = uploadFile.getOriginalFilename();
|
||||
if (originalFilename == null) {
|
||||
errors.add("第" + (i + 1) + "个文件名不能为空");
|
||||
continue;
|
||||
}
|
||||
|
||||
String extension = originalFilename.substring(originalFilename.lastIndexOf(".") + 1).toLowerCase();
|
||||
if (!isImageFile(extension)) {
|
||||
errors.add("第" + (i + 1) + "个文件不是图片格式(" + originalFilename + ")");
|
||||
continue;
|
||||
}
|
||||
|
||||
// 验证文件大小(最大10MB)
|
||||
if (uploadFile.getSize() > 10 * 1024 * 1024) {
|
||||
errors.add("第" + (i + 1) + "个文件大小超过10MB(" + originalFilename + ")");
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
// 上传到OSS
|
||||
byte[] content = uploadFile.getBytes();
|
||||
String imageUrl = ossService.upload(content, originalFilename);
|
||||
|
||||
Map<String, String> fileInfo = new HashMap<>();
|
||||
fileInfo.put("url", imageUrl);
|
||||
fileInfo.put("originalFilename", originalFilename);
|
||||
fileInfo.put("size", String.valueOf(uploadFile.getSize()));
|
||||
uploadedFiles.add(fileInfo);
|
||||
|
||||
log.info("图片上传成功,文件名: {}, URL: {}", originalFilename, imageUrl);
|
||||
} catch (Exception e) {
|
||||
log.error("上传第{}个文件失败: {}", i + 1, originalFilename, e);
|
||||
errors.add("第" + (i + 1) + "个文件上传失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
result.put("files", uploadedFiles);
|
||||
result.put("successCount", uploadedFiles.size());
|
||||
result.put("totalCount", files.length);
|
||||
|
||||
if (!errors.isEmpty()) {
|
||||
result.put("errors", errors);
|
||||
}
|
||||
|
||||
if (uploadedFiles.isEmpty()) {
|
||||
return Result.fail("所有文件上传失败: " + String.join("; ", errors));
|
||||
}
|
||||
|
||||
String message = String.format("成功上传%d/%d个文件", uploadedFiles.size(), files.length);
|
||||
if (!errors.isEmpty()) {
|
||||
message += ",部分文件上传失败";
|
||||
}
|
||||
|
||||
log.info("批量图片上传完成,成功: {}/{}, 失败: {}", uploadedFiles.size(), files.length, errors.size());
|
||||
return Result.success(message, result);
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("批量图片上传失败", e);
|
||||
return Result.fail("图片上传失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否为图片文件
|
||||
*/
|
||||
private boolean isImageFile(String extension) {
|
||||
String[] imageExtensions = {"jpg", "jpeg", "png", "gif", "webp", "bmp"};
|
||||
for (String ext : imageExtensions) {
|
||||
if (ext.equalsIgnoreCase(extension)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,143 @@
|
||||
package com.mtkj.mtpay.dto.response;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 商品响应DTO
|
||||
*/
|
||||
@Data
|
||||
public class ProductResponseDTO implements Serializable {
|
||||
|
||||
/**
|
||||
* 商品ID
|
||||
*/
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 商品名称
|
||||
*/
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 商品价格(基础价格)
|
||||
*/
|
||||
private BigDecimal price;
|
||||
|
||||
/**
|
||||
* 主图URL(单个,兼容旧版本,取mainImages的第一个)
|
||||
*/
|
||||
private String mainImage;
|
||||
|
||||
/**
|
||||
* 主图URL列表(支持多张主图)
|
||||
*/
|
||||
private List<String> mainImages;
|
||||
|
||||
/**
|
||||
* 商品状态
|
||||
*/
|
||||
private String status;
|
||||
|
||||
/**
|
||||
* 店铺ID
|
||||
*/
|
||||
private Long shopId;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private LocalDateTime createTime;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
/**
|
||||
* SKU列表
|
||||
*/
|
||||
private List<ProductSkuResponseDTO> skus;
|
||||
|
||||
/**
|
||||
* SKU响应DTO
|
||||
*/
|
||||
@Data
|
||||
public static class ProductSkuResponseDTO implements Serializable {
|
||||
|
||||
/**
|
||||
* SKU ID
|
||||
*/
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 商品ID
|
||||
*/
|
||||
private Long productId;
|
||||
|
||||
/**
|
||||
* SKU编码
|
||||
*/
|
||||
private String sku;
|
||||
|
||||
/**
|
||||
* 价格
|
||||
*/
|
||||
private BigDecimal price;
|
||||
|
||||
/**
|
||||
* 货币
|
||||
*/
|
||||
private String currency;
|
||||
|
||||
/**
|
||||
* 库存数量
|
||||
*/
|
||||
private Integer stock;
|
||||
|
||||
/**
|
||||
* 销售属性(JSON格式)
|
||||
*/
|
||||
private String salesAttrs;
|
||||
|
||||
/**
|
||||
* SKU图片URL
|
||||
*/
|
||||
private String skuImage;
|
||||
|
||||
/**
|
||||
* 重量
|
||||
*/
|
||||
private BigDecimal weight;
|
||||
|
||||
/**
|
||||
* 大小/尺寸(JSON格式)
|
||||
*/
|
||||
private String size;
|
||||
|
||||
/**
|
||||
* 规格
|
||||
*/
|
||||
private String specification;
|
||||
|
||||
/**
|
||||
* SKU状态
|
||||
*/
|
||||
private String status;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private LocalDateTime createTime;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
private LocalDateTime updateTime;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.mtkj.mtpay.service;
|
||||
|
||||
import com.mtkj.mtpay.dto.request.CreateProductRequestDTO;
|
||||
import com.mtkj.mtpay.dto.response.ProductResponseDTO;
|
||||
|
||||
/**
|
||||
* 商品服务接口
|
||||
*/
|
||||
public interface ProductService {
|
||||
|
||||
/**
|
||||
* 创建商品
|
||||
* @param request 创建商品请求
|
||||
* @return 商品响应
|
||||
*/
|
||||
ProductResponseDTO createProduct(CreateProductRequestDTO request);
|
||||
|
||||
/**
|
||||
* 根据ID获取商品详情
|
||||
* @param id 商品ID
|
||||
* @return 商品响应
|
||||
*/
|
||||
ProductResponseDTO getProductById(Long id);
|
||||
|
||||
/**
|
||||
* 获取商品详情页URL
|
||||
* @param id 商品ID
|
||||
* @return 商品详情页URL
|
||||
*/
|
||||
String getProductUrl(Long id);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,215 @@
|
||||
package com.mtkj.mtpay.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.mtkj.mtpay.common.ResultCode;
|
||||
import com.mtkj.mtpay.common.enums.ProductStatus;
|
||||
import com.mtkj.mtpay.common.enums.SkuStatus;
|
||||
import com.mtkj.mtpay.dto.request.CreateProductRequestDTO;
|
||||
import com.mtkj.mtpay.dto.response.ProductResponseDTO;
|
||||
import com.mtkj.mtpay.entity.MtProduct;
|
||||
import com.mtkj.mtpay.entity.MtProductSku;
|
||||
import com.mtkj.mtpay.exception.BusinessException;
|
||||
import com.mtkj.mtpay.mapper.MtProductMapper;
|
||||
import com.mtkj.mtpay.mapper.MtProductSkuMapper;
|
||||
import com.mtkj.mtpay.service.ProductService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 商品服务实现类
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class ProductServiceImpl implements ProductService {
|
||||
|
||||
@Autowired
|
||||
private MtProductMapper productMapper;
|
||||
|
||||
@Autowired
|
||||
private MtProductSkuMapper productSkuMapper;
|
||||
|
||||
@Autowired
|
||||
private ObjectMapper objectMapper;
|
||||
|
||||
@Value("${server.port:8082}")
|
||||
private String serverPort;
|
||||
|
||||
@Value("${server.servlet.context-path:}")
|
||||
private String contextPath;
|
||||
|
||||
/**
|
||||
* 前端访问地址(用于生成商品详情页URL)
|
||||
*/
|
||||
@Value("${app.frontend.url:http://localhost:3000}")
|
||||
private String frontendUrl;
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public ProductResponseDTO createProduct(CreateProductRequestDTO request) {
|
||||
log.info("开始创建商品,商品名称: {}, 店铺ID: {}, SKU数量: {}",
|
||||
request.getName(), request.getShopId(),
|
||||
request.getSkus() != null ? request.getSkus().size() : 0);
|
||||
|
||||
// 创建商品
|
||||
MtProduct product = new MtProduct();
|
||||
product.setName(request.getName());
|
||||
product.setPrice(request.getPrice());
|
||||
|
||||
// 处理主图:优先使用mainImages(多图),如果没有则使用mainImage(单图,兼容旧版本)
|
||||
String mainImageValue = null;
|
||||
if (request.getMainImages() != null && !request.getMainImages().isEmpty()) {
|
||||
// 多个主图,转换为JSON数组存储
|
||||
try {
|
||||
mainImageValue = objectMapper.writeValueAsString(request.getMainImages());
|
||||
log.debug("商品主图(多图): {}", mainImageValue);
|
||||
} catch (Exception e) {
|
||||
log.error("转换主图列表为JSON失败", e);
|
||||
throw new BusinessException(ResultCode.SYSTEM_ERROR, "主图数据格式错误");
|
||||
}
|
||||
} else if (StringUtils.hasText(request.getMainImage())) {
|
||||
// 单个主图,兼容旧版本
|
||||
mainImageValue = request.getMainImage();
|
||||
log.debug("商品主图(单图): {}", mainImageValue);
|
||||
}
|
||||
product.setMainImage(mainImageValue);
|
||||
|
||||
product.setStatus(request.getStatus() != null ? request.getStatus() : ProductStatus.ACTIVE.getCode());
|
||||
product.setShopId(request.getShopId());
|
||||
|
||||
int result = productMapper.insert(product);
|
||||
if (result <= 0) {
|
||||
log.error("创建商品失败,商品名称: {}", request.getName());
|
||||
throw new BusinessException(ResultCode.SYSTEM_ERROR, "创建商品失败");
|
||||
}
|
||||
log.debug("商品基础信息插入成功,商品ID: {}", product.getId());
|
||||
|
||||
// 创建SKU
|
||||
if (request.getSkus() != null && !request.getSkus().isEmpty()) {
|
||||
log.debug("开始创建SKU,数量: {}", request.getSkus().size());
|
||||
for (CreateProductRequestDTO.CreateProductSkuDTO skuDTO : request.getSkus()) {
|
||||
MtProductSku sku = new MtProductSku();
|
||||
sku.setProductId(product.getId());
|
||||
sku.setSku(skuDTO.getSku());
|
||||
sku.setPrice(skuDTO.getPrice());
|
||||
sku.setCurrency(skuDTO.getCurrency());
|
||||
sku.setStock(skuDTO.getStock());
|
||||
sku.setSalesAttrs(skuDTO.getSalesAttrs());
|
||||
sku.setSkuImage(skuDTO.getSkuImage());
|
||||
sku.setWeight(skuDTO.getWeight());
|
||||
sku.setSize(skuDTO.getSize());
|
||||
sku.setSpecification(skuDTO.getSpecification());
|
||||
sku.setStatus(skuDTO.getStatus() != null ? skuDTO.getStatus() : SkuStatus.ACTIVE.getCode());
|
||||
|
||||
int skuResult = productSkuMapper.insert(sku);
|
||||
if (skuResult <= 0) {
|
||||
log.error("创建SKU失败,商品ID: {}, SKU编码: {}", product.getId(), skuDTO.getSku());
|
||||
throw new BusinessException(ResultCode.SYSTEM_ERROR, "创建SKU失败");
|
||||
}
|
||||
log.debug("SKU创建成功,商品ID: {}, SKU编码: {}, SKU ID: {}",
|
||||
product.getId(), skuDTO.getSku(), sku.getId());
|
||||
}
|
||||
}
|
||||
|
||||
log.info("商品创建成功,商品ID: {}, 商品名称: {}, SKU数量: {}",
|
||||
product.getId(), product.getName(),
|
||||
request.getSkus() != null ? request.getSkus().size() : 0);
|
||||
|
||||
// 返回商品详情
|
||||
return getProductById(product.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProductResponseDTO getProductById(Long id) {
|
||||
log.debug("查询商品详情,商品ID: {}", id);
|
||||
MtProduct product = productMapper.selectById(id);
|
||||
if (product == null) {
|
||||
log.warn("商品不存在,商品ID: {}", id);
|
||||
throw new BusinessException(ResultCode.DATA_NOT_FOUND, "商品不存在");
|
||||
}
|
||||
|
||||
// 查询SKU列表
|
||||
LambdaQueryWrapper<MtProductSku> skuWrapper = new LambdaQueryWrapper<>();
|
||||
skuWrapper.eq(MtProductSku::getProductId, id);
|
||||
skuWrapper.eq(MtProductSku::getStatus, SkuStatus.ACTIVE.getCode());
|
||||
List<MtProductSku> skus = productSkuMapper.selectList(skuWrapper);
|
||||
log.debug("查询到商品SKU数量: {}, 商品ID: {}", skus.size(), id);
|
||||
|
||||
// 转换为响应DTO
|
||||
ProductResponseDTO response = new ProductResponseDTO();
|
||||
BeanUtils.copyProperties(product, response);
|
||||
|
||||
// 处理主图:解析JSON数组或使用单个URL
|
||||
if (StringUtils.hasText(product.getMainImage())) {
|
||||
try {
|
||||
// 尝试解析为JSON数组
|
||||
if (product.getMainImage().trim().startsWith("[")) {
|
||||
List<String> mainImages = objectMapper.readValue(
|
||||
product.getMainImage(),
|
||||
new TypeReference<List<String>>() {}
|
||||
);
|
||||
response.setMainImages(mainImages);
|
||||
// 兼容:第一个作为mainImage
|
||||
if (!mainImages.isEmpty()) {
|
||||
response.setMainImage(mainImages.get(0));
|
||||
}
|
||||
log.debug("解析商品主图(多图),数量: {}", mainImages.size());
|
||||
} else {
|
||||
// 单个URL
|
||||
response.setMainImage(product.getMainImage());
|
||||
List<String> singleImageList = new ArrayList<>();
|
||||
singleImageList.add(product.getMainImage());
|
||||
response.setMainImages(singleImageList);
|
||||
log.debug("解析商品主图(单图)");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.warn("解析商品主图失败,使用原始值,商品ID: {}", id, e);
|
||||
response.setMainImage(product.getMainImage());
|
||||
List<String> singleImageList = new ArrayList<>();
|
||||
singleImageList.add(product.getMainImage());
|
||||
response.setMainImages(singleImageList);
|
||||
}
|
||||
}
|
||||
|
||||
List<ProductResponseDTO.ProductSkuResponseDTO> skuDTOs = skus.stream().map(sku -> {
|
||||
ProductResponseDTO.ProductSkuResponseDTO skuDTO = new ProductResponseDTO.ProductSkuResponseDTO();
|
||||
BeanUtils.copyProperties(sku, skuDTO);
|
||||
return skuDTO;
|
||||
}).collect(Collectors.toList());
|
||||
|
||||
response.setSkus(skuDTOs);
|
||||
|
||||
log.info("获取商品详情成功,商品ID: {}, 商品名称: {}, SKU数量: {}, 主图数量: {}",
|
||||
id, product.getName(), skuDTOs.size(),
|
||||
response.getMainImages() != null ? response.getMainImages().size() : 0);
|
||||
return response;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getProductUrl(Long id) {
|
||||
log.debug("获取商品URL,商品ID: {}", id);
|
||||
// 检查商品是否存在
|
||||
MtProduct product = productMapper.selectById(id);
|
||||
if (product == null) {
|
||||
log.warn("商品不存在,无法生成URL,商品ID: {}", id);
|
||||
throw new BusinessException(ResultCode.DATA_NOT_FOUND, "商品不存在");
|
||||
}
|
||||
|
||||
// 构建商品详情页URL(使用前端地址)
|
||||
// 格式:http://前端地址/product/{id}
|
||||
String productUrl = frontendUrl + "/product/" + id;
|
||||
log.info("生成商品URL成功,商品ID: {}, URL: {}", id, productUrl);
|
||||
return productUrl;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user