From 5241598544bda95a4f28be80de0f479ed3201680 Mon Sep 17 00:00:00 2001 From: jonghyun0429p Date: Fri, 16 Aug 2024 23:11:32 +0900 Subject: [PATCH 1/2] feature : develop extract product --- logic/build.gradle.kts | 1 + .../com/spring_greens/logic/LogicApplication.java | 2 ++ .../logic/extraction/dto/RedisProduct.java | 13 +++++++++++++ .../logic/extraction/dto/RedisShop.java | 11 +++++++++++ 4 files changed, 27 insertions(+) create mode 100644 logic/src/main/java/com/spring_greens/logic/extraction/dto/RedisProduct.java create mode 100644 logic/src/main/java/com/spring_greens/logic/extraction/dto/RedisShop.java diff --git a/logic/build.gradle.kts b/logic/build.gradle.kts index 29878c8..91d10de 100644 --- a/logic/build.gradle.kts +++ b/logic/build.gradle.kts @@ -35,6 +35,7 @@ dependencies { testImplementation("io.projectreactor:reactor-test") testImplementation("org.springframework.security:spring-security-test") testRuntimeOnly("org.junit.platform:junit-platform-launcher") + implementation("org.springframework.boot:spring-boot-starter-logging") } tasks.withType { diff --git a/logic/src/main/java/com/spring_greens/logic/LogicApplication.java b/logic/src/main/java/com/spring_greens/logic/LogicApplication.java index dd29026..af58189 100644 --- a/logic/src/main/java/com/spring_greens/logic/LogicApplication.java +++ b/logic/src/main/java/com/spring_greens/logic/LogicApplication.java @@ -2,7 +2,9 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.scheduling.annotation.EnableScheduling; +@EnableScheduling @SpringBootApplication public class LogicApplication { diff --git a/logic/src/main/java/com/spring_greens/logic/extraction/dto/RedisProduct.java b/logic/src/main/java/com/spring_greens/logic/extraction/dto/RedisProduct.java new file mode 100644 index 0000000..b220c15 --- /dev/null +++ b/logic/src/main/java/com/spring_greens/logic/extraction/dto/RedisProduct.java @@ -0,0 +1,13 @@ +package com.spring_greens.logic.extraction.dto; + +public class RedisProduct { + public String product_id; + public String product_name; + public String product_unit; + public String product_price; + public String product_view_count; +// public String product_image_url; +// public String major_category; +// public String sub_category; +} + diff --git a/logic/src/main/java/com/spring_greens/logic/extraction/dto/RedisShop.java b/logic/src/main/java/com/spring_greens/logic/extraction/dto/RedisShop.java new file mode 100644 index 0000000..0826b3b --- /dev/null +++ b/logic/src/main/java/com/spring_greens/logic/extraction/dto/RedisShop.java @@ -0,0 +1,11 @@ +package com.spring_greens.logic.extraction.dto; + +import java.util.List; + +public class RedisShop { + public Long shop_id; + public String shop_name; + public String shop_contact; + public String shop_address_details; + public List product; +} From b0757912f1f9cfae47f0690739d21a82a3cd6f44 Mon Sep 17 00:00:00 2001 From: jonghyun0429p Date: Fri, 16 Aug 2024 23:13:43 +0900 Subject: [PATCH 2/2] feature : develop extract product --- .../controller/ExtractionConroller.java | 13 + .../converter/ExtrationConverterImpl.java | 49 +++ .../converter/ifs/ExtractionConverter.java | 14 + .../logic/extraction/dto/RedisDTO.java | 18 + .../schduler/ExtractionScheduler.java | 22 ++ .../service/ExtractionServiceImpl.java | 195 +++++++++++ .../service/ifs/ExtractionService.java | 17 + .../controller/AbstractBaseController.java | 33 ++ .../logic/global/dto/MallDTO.java | 21 ++ .../logic/global/dto/ProductDTO.java | 37 ++ .../logic/global/dto/ShopDTO.java | 19 ++ .../logic/global/entity/Mall.java | 56 +++ .../logic/global/entity/Product.java | 63 ++++ .../logic/global/entity/Shop.java | 50 +++ .../logic/global/enums/Mall.java | 14 + .../converter/ConverterFactoryImpl.java | 33 ++ .../converter/ifs/ConverterFactory.java | 7 + .../repository/RepositoryFactoryImpl.java | 35 ++ .../repository/ifs/RepositoryFactory.java | 13 + .../factory/service/ServiceFactoryImpl.java | 34 ++ .../factory/service/ifs/ServiceFactory.java | 12 + .../global/repository/MallRepository.java | 17 + .../global/repository/ProductRepository.java | 28 ++ .../global/repository/ShopRepository.java | 22 ++ .../main/resources/application-dev.properties | 39 +++ .../src/main/resources/logback-spring-dev.xml | 50 +++ .../main/resources/static/fcmMessagePush.html | 124 +++++++ .../resources/static/fcmMessagePushStyle.css | 322 ++++++++++++++++++ 28 files changed, 1357 insertions(+) create mode 100644 logic/src/main/java/com/spring_greens/logic/extraction/controller/ExtractionConroller.java create mode 100644 logic/src/main/java/com/spring_greens/logic/extraction/converter/ExtrationConverterImpl.java create mode 100644 logic/src/main/java/com/spring_greens/logic/extraction/converter/ifs/ExtractionConverter.java create mode 100644 logic/src/main/java/com/spring_greens/logic/extraction/dto/RedisDTO.java create mode 100644 logic/src/main/java/com/spring_greens/logic/extraction/schduler/ExtractionScheduler.java create mode 100644 logic/src/main/java/com/spring_greens/logic/extraction/service/ExtractionServiceImpl.java create mode 100644 logic/src/main/java/com/spring_greens/logic/extraction/service/ifs/ExtractionService.java create mode 100644 logic/src/main/java/com/spring_greens/logic/global/controller/AbstractBaseController.java create mode 100644 logic/src/main/java/com/spring_greens/logic/global/dto/MallDTO.java create mode 100644 logic/src/main/java/com/spring_greens/logic/global/dto/ProductDTO.java create mode 100644 logic/src/main/java/com/spring_greens/logic/global/dto/ShopDTO.java create mode 100644 logic/src/main/java/com/spring_greens/logic/global/entity/Mall.java create mode 100644 logic/src/main/java/com/spring_greens/logic/global/entity/Product.java create mode 100644 logic/src/main/java/com/spring_greens/logic/global/entity/Shop.java create mode 100644 logic/src/main/java/com/spring_greens/logic/global/enums/Mall.java create mode 100644 logic/src/main/java/com/spring_greens/logic/global/factory/converter/ConverterFactoryImpl.java create mode 100644 logic/src/main/java/com/spring_greens/logic/global/factory/converter/ifs/ConverterFactory.java create mode 100644 logic/src/main/java/com/spring_greens/logic/global/factory/repository/RepositoryFactoryImpl.java create mode 100644 logic/src/main/java/com/spring_greens/logic/global/factory/repository/ifs/RepositoryFactory.java create mode 100644 logic/src/main/java/com/spring_greens/logic/global/factory/service/ServiceFactoryImpl.java create mode 100644 logic/src/main/java/com/spring_greens/logic/global/factory/service/ifs/ServiceFactory.java create mode 100644 logic/src/main/java/com/spring_greens/logic/global/repository/MallRepository.java create mode 100644 logic/src/main/java/com/spring_greens/logic/global/repository/ProductRepository.java create mode 100644 logic/src/main/java/com/spring_greens/logic/global/repository/ShopRepository.java create mode 100644 logic/src/main/resources/application-dev.properties create mode 100644 logic/src/main/resources/logback-spring-dev.xml create mode 100644 logic/src/main/resources/static/fcmMessagePush.html create mode 100644 logic/src/main/resources/static/fcmMessagePushStyle.css diff --git a/logic/src/main/java/com/spring_greens/logic/extraction/controller/ExtractionConroller.java b/logic/src/main/java/com/spring_greens/logic/extraction/controller/ExtractionConroller.java new file mode 100644 index 0000000..0e9c0d1 --- /dev/null +++ b/logic/src/main/java/com/spring_greens/logic/extraction/controller/ExtractionConroller.java @@ -0,0 +1,13 @@ +package com.spring_greens.logic.extraction.controller; + +import com.spring_greens.logic.global.controller.AbstractBaseController; +import com.spring_greens.logic.global.factory.converter.ifs.ConverterFactory; +import com.spring_greens.logic.global.factory.service.ifs.ServiceFactory; + +public class ExtractionConroller extends AbstractBaseController{ + + public ExtractionConroller(ConverterFactory converterFactory, ServiceFactory serviceFactory) { + super(converterFactory, serviceFactory); + } + +} diff --git a/logic/src/main/java/com/spring_greens/logic/extraction/converter/ExtrationConverterImpl.java b/logic/src/main/java/com/spring_greens/logic/extraction/converter/ExtrationConverterImpl.java new file mode 100644 index 0000000..2ae84dc --- /dev/null +++ b/logic/src/main/java/com/spring_greens/logic/extraction/converter/ExtrationConverterImpl.java @@ -0,0 +1,49 @@ +package com.spring_greens.logic.extraction.converter; + +import com.spring_greens.logic.extraction.converter.ifs.ExtractionConverter; +import com.spring_greens.logic.global.dto.MallDTO; +import com.spring_greens.logic.global.dto.ProductDTO; +import com.spring_greens.logic.global.dto.ShopDTO; +import com.spring_greens.logic.global.entity.Mall; +import com.spring_greens.logic.global.entity.Product; +import com.spring_greens.logic.global.entity.Shop; + +public class ExtrationConverterImpl implements ExtractionConverter{ + + @Override + public MallDTO craeteMallDTO(Mall mall) { + return MallDTO.builder() + .id(mall.getId()) + .name(mall.getName()) + .build(); + } + + @Override + public ProductDTO createProductDTO(Product product) { + return ProductDTO.builder() + .id(product.getId()) + .name(product.getName()) + .unit(product.getUnit()) + .price(product.getPrice()) + .totalViewers(product.getTotalViewers()) + // .productImageUrl(product.get) + // .majorCategory(product.getMajorCategory()) + // .subCategory(product.getSubCategory()) + .detailsProductClickCount(product.getDetailsProductClickCount()) + .dailyAdImpressions(product.getDailyAdImpressions()) + .age(product.getAge()) + .build(); + } + + @Override + public ShopDTO createShopDTO(Shop shop) { + return ShopDTO.builder() + .id(shop.getId()) + .name(shop.getName()) + .contact(shop.getContact()) + .addressDetails(shop.getAddressDetails()) + .build(); + } + + +} diff --git a/logic/src/main/java/com/spring_greens/logic/extraction/converter/ifs/ExtractionConverter.java b/logic/src/main/java/com/spring_greens/logic/extraction/converter/ifs/ExtractionConverter.java new file mode 100644 index 0000000..ff366a2 --- /dev/null +++ b/logic/src/main/java/com/spring_greens/logic/extraction/converter/ifs/ExtractionConverter.java @@ -0,0 +1,14 @@ +package com.spring_greens.logic.extraction.converter.ifs; + +import com.spring_greens.logic.global.dto.MallDTO; +import com.spring_greens.logic.global.dto.ProductDTO; +import com.spring_greens.logic.global.dto.ShopDTO; +import com.spring_greens.logic.global.entity.Mall; +import com.spring_greens.logic.global.entity.Product; +import com.spring_greens.logic.global.entity.Shop; + +public interface ExtractionConverter { + MallDTO craeteMallDTO(Mall mall); + ProductDTO createProductDTO(Product product); + ShopDTO createShopDTO(Shop shop); +} diff --git a/logic/src/main/java/com/spring_greens/logic/extraction/dto/RedisDTO.java b/logic/src/main/java/com/spring_greens/logic/extraction/dto/RedisDTO.java new file mode 100644 index 0000000..7bb4600 --- /dev/null +++ b/logic/src/main/java/com/spring_greens/logic/extraction/dto/RedisDTO.java @@ -0,0 +1,18 @@ +package com.spring_greens.logic.extraction.dto; + +import java.util.List; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.spring_greens.logic.global.dto.ShopDTO; + +import lombok.Builder; +import lombok.Getter; + +@Getter +@Builder +@JsonInclude(JsonInclude.Include.NON_NULL) +public class RedisDTO { + private Long mall_id; + private String mall_name; + private List shop_list; +} diff --git a/logic/src/main/java/com/spring_greens/logic/extraction/schduler/ExtractionScheduler.java b/logic/src/main/java/com/spring_greens/logic/extraction/schduler/ExtractionScheduler.java new file mode 100644 index 0000000..2522b77 --- /dev/null +++ b/logic/src/main/java/com/spring_greens/logic/extraction/schduler/ExtractionScheduler.java @@ -0,0 +1,22 @@ +package com.spring_greens.logic.extraction.schduler; + +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import com.spring_greens.logic.global.factory.service.ifs.ServiceFactory; + +import lombok.RequiredArgsConstructor; + +@Component +@RequiredArgsConstructor +public class ExtractionScheduler { + private final ServiceFactory serviceFactory; + + @Scheduled + public void extractionProductScheduler(){ + + serviceFactory.getExtractionService().ExtractionProductService(); + } + +} diff --git a/logic/src/main/java/com/spring_greens/logic/extraction/service/ExtractionServiceImpl.java b/logic/src/main/java/com/spring_greens/logic/extraction/service/ExtractionServiceImpl.java new file mode 100644 index 0000000..ca21b34 --- /dev/null +++ b/logic/src/main/java/com/spring_greens/logic/extraction/service/ExtractionServiceImpl.java @@ -0,0 +1,195 @@ +package com.spring_greens.logic.extraction.service; + +import java.util.*; + +import com.spring_greens.logic.extraction.dto.RedisProduct; +import com.spring_greens.logic.extraction.dto.RedisShop; +import com.spring_greens.logic.global.dto.ShopDTO; +import com.spring_greens.logic.global.enums.Mall; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + +import com.spring_greens.logic.extraction.dto.RedisDTO; +import com.spring_greens.logic.extraction.service.ifs.ExtractionService; +import com.spring_greens.logic.global.dto.ProductDTO; +import com.spring_greens.logic.global.factory.converter.ifs.ConverterFactory; +import com.spring_greens.logic.global.factory.repository.ifs.RepositoryFactory; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Service +@RequiredArgsConstructor +public class ExtractionServiceImpl implements ExtractionService{ + + private final static Logger logger = LoggerFactory.getLogger(ExtractionServiceImpl.class); + + private final ConverterFactory converterFactory; + private final RepositoryFactory repositoryFactory; + private final Double[] weights = {0.2, 0.3, 0.5}; + private double sum = 0.0; + private double max = 0.0; + + + public RedisDTO ExtractionProductService(){ + + // 상품을추출 + List products = createProducts(); + + // 확률 + List Probabilities = createAgeScores(products); + + // 10개의 상품으을추출한다. + List tenIndexs = rouletteAlgorithm(products, Probabilities); + + // age -= 1 + ageManagement(products); + + // age를 부여한다. + ageGrant(tenIndexs, Probabilities, products); + + // DTO를 만들어서 보낸다. + return createRedisDTO(tenIndexs, products); + } + + public List createAgeScores(List products){ + List ageScores = new ArrayList(); + + //각각의 가중치와 해당 값들을 구하여 더한 것이 ageScore + for(ProductDTO p : products){ + double ageScore = weights[0]*p.getDailyAdImpressions() + + weights[1]*p.getDetailsProductClickCount() + + weights[2]*p.getTotalViewers(); + ageScores.add(ageScore); + sum += ageScore; + } + + //룰렛 휠 알고리즘을 위해 필요한 확률로 만들어준다. + for(int i = 0; i < ageScores.size(); i++){ + ageScores.set(i, ageScores.get(i)/sum); + // maximum + if(ageScores.get(i) > max){ + max = ageScores.get(i); + } + } + + return ageScores; + } + + public List rouletteAlgorithm(List products, List ageScores){ + //확률들을 누적시켜 더한 값을 리스트로 저장해둔다. + List tenIndexs = new ArrayList<>(); + List cumulativeProbabilities = new ArrayList<>(); + double cumulativeSum = 0; + + for (double probability : ageScores) { + cumulativeSum += probability; + cumulativeProbabilities.add(probability); + } + + //상품 선택 + Random random = new Random(); + while(tenIndexs.size() < 10){ + double r = random.nextDouble(); + //0에서 1사이의 랜덤한 실수를 정하고, 그 실수보다 큰 한가지를 골라서 저장. + for(int i = 0; i < cumulativeProbabilities.size(); i++){ + if (r <= cumulativeProbabilities.get(i)){ + tenIndexs.add(i); + break; + } + } + } + + return tenIndexs; + } + + public void ageManagement(List products){ + for(ProductDTO p : products){ + Integer age = p.getAge(); + if(age>0){ + p.changeAge(age-1); + } + } + } + + + // 에이지 부여 + public void ageGrant(List tenIndexs, List probabilities, List products){ + //최댓값을 5로 두고, 20%씩 낮추면서 4,3,2,1 이런식으로 부여할 예정 + for(Integer i : tenIndexs){ + double ratio = probabilities.get(i)/max; + + if(ratio > 0.8){ + products.get(i).changeAge(5); + } else if (ratio > 0.6) { + products.get(i).changeAge(4); + } else if (ratio > 0.4) { + products.get(i).changeAge(3); + } else if (ratio > 0.2) { + products.get(i).changeAge(2); + } else { + products.get(i).changeAge(1); + } + + } + } + + + + public RedisDTO createRedisDTO(List tenIndexs, List products){ + List productIds = new ArrayList<>(); + List productDtos = new ArrayList<>(); + List redisProducts = new ArrayList<>(); + List redisShops = new ArrayList<>(); + List redisDTO = new ArrayList<>(); + + public class RedisDTO { + private Long mall_id; + private String mall_name; + private List shop_list; + } + + //shop을 가져오기 위한 productID를 가져오는 반복문, 10개의 product를 저장하는 코드 + for(Integer i : tenIndexs){ + ProductDTO p = products.get(i); + productIds.add(p.getId()); + productDtos.add(p); + } + + // shop 정보가지고오기 + List shops = createShopDTO(productIds); + + for(int i = 0; i < Mall.values().length ; i++){ + // return 1 + // return 2 + } + + + + } + + public List createProducts(){ + + Optional> products = repositoryFactory.getProductRepository().findAllAge(); + + if(products.isPresent()){ + return products.get(); + }else{ + log.info("DB Product 데이터 추출 실패"); + throw new NoSuchElementException("No products found"); + } + + } + + public List createShopDTO(List productId){ + Optional> shops = repositoryFactory.getShopRepository().findByProduct(productId); + if(shops.isPresent()){ + return shops.get(); + }else{ + log.info("DB Shop 데이터 추출 실패"); + throw new NoSuchElementException("No products found"); + } + } +} diff --git a/logic/src/main/java/com/spring_greens/logic/extraction/service/ifs/ExtractionService.java b/logic/src/main/java/com/spring_greens/logic/extraction/service/ifs/ExtractionService.java new file mode 100644 index 0000000..0fbff4e --- /dev/null +++ b/logic/src/main/java/com/spring_greens/logic/extraction/service/ifs/ExtractionService.java @@ -0,0 +1,17 @@ +package com.spring_greens.logic.extraction.service.ifs; + +import java.util.List; + +import com.spring_greens.logic.extraction.dto.RedisDTO; +import com.spring_greens.logic.global.dto.ProductDTO; +import com.spring_greens.logic.global.dto.ShopDTO; + +public interface ExtractionService { + public RedisDTO ExtractionProductService(); + public List createAgeScores(List product); + public List rouletteAlgorithm(List products, List ageScores); + public void ageManagement(List products); + public void ageGrant(List tenIndexs, List probabilities, List Products); + public RedisDTO createRedisDTO(List tenIndexs, List products); + public List createShopDTO(List productId); +} diff --git a/logic/src/main/java/com/spring_greens/logic/global/controller/AbstractBaseController.java b/logic/src/main/java/com/spring_greens/logic/global/controller/AbstractBaseController.java new file mode 100644 index 0000000..a8143de --- /dev/null +++ b/logic/src/main/java/com/spring_greens/logic/global/controller/AbstractBaseController.java @@ -0,0 +1,33 @@ +package com.spring_greens.logic.global.controller; + +import com.spring_greens.logic.global.factory.converter.ifs.ConverterFactory; +import com.spring_greens.logic.global.factory.service.ifs.ServiceFactory; +// import io.swagger.v3.oas.annotations.Operation; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.RestController; + +/** + * This is abstract class for MapController and MainController.
+ * because Let's make one assumption that client want to get redis products so send to server HTTP GET request.
+ * then server response it.
+ * + * but we need to consider how to handle common request. ( get product )
+ * currently, client send request to server on map and main page.
+ * + * if we define interface for map and main if so abstract method have to implement each. + * but, it's way was not good solution. because of only get products to redis server and then convert to specific type response that's it
+ * so, I thought that implement a common processing logic by the abstract class.
+ * @author itstime0809 + */ + +@Slf4j +@RequiredArgsConstructor +@RestController +public abstract class AbstractBaseController { + protected final ConverterFactory converterFactory; + protected final ServiceFactory serviceFactory; +} + + + diff --git a/logic/src/main/java/com/spring_greens/logic/global/dto/MallDTO.java b/logic/src/main/java/com/spring_greens/logic/global/dto/MallDTO.java new file mode 100644 index 0000000..21acb18 --- /dev/null +++ b/logic/src/main/java/com/spring_greens/logic/global/dto/MallDTO.java @@ -0,0 +1,21 @@ +package com.spring_greens.logic.global.dto; + +import jakarta.persistence.Entity; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import jdk.jfr.Description; + +@Getter +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class MallDTO { + + private Long id; + @Description("상가이름") + private String name; + +} diff --git a/logic/src/main/java/com/spring_greens/logic/global/dto/ProductDTO.java b/logic/src/main/java/com/spring_greens/logic/global/dto/ProductDTO.java new file mode 100644 index 0000000..315454c --- /dev/null +++ b/logic/src/main/java/com/spring_greens/logic/global/dto/ProductDTO.java @@ -0,0 +1,37 @@ +package com.spring_greens.logic.global.dto; + +import java.time.LocalDate; + +import org.springframework.context.annotation.Description; + +import com.fasterxml.jackson.annotation.JsonInclude; + +import jakarta.persistence.Column; +import lombok.Getter; +import lombok.experimental.SuperBuilder; + +@Getter +@SuperBuilder(toBuilder = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public class ProductDTO { + private Long id; + private Long shop_id; + private String name; + private String unit; + private Integer price; + private Integer totalViewers; + /* + private String productImageUrl; + private String majorCategory; + private String subCategory; + */ + private Integer age; + private Integer detailsProductClickCount; + private Integer dailyAdImpressions; + private Boolean extractableStatus; + private LocalDate lastExtractDate; + + public void changeAge(Integer age){ + this.age = age; + } +} diff --git a/logic/src/main/java/com/spring_greens/logic/global/dto/ShopDTO.java b/logic/src/main/java/com/spring_greens/logic/global/dto/ShopDTO.java new file mode 100644 index 0000000..77047f0 --- /dev/null +++ b/logic/src/main/java/com/spring_greens/logic/global/dto/ShopDTO.java @@ -0,0 +1,19 @@ +package com.spring_greens.logic.global.dto; + +import java.util.List; + +import com.fasterxml.jackson.annotation.JsonInclude; + +import lombok.Getter; +import lombok.experimental.SuperBuilder; + +@SuperBuilder(toBuilder = true) +@Getter +@JsonInclude(JsonInclude.Include.NON_NULL) +public class ShopDTO { + private Long id; + private Long mallId; + private String name; + private String contact; + private String addressDetails; +} diff --git a/logic/src/main/java/com/spring_greens/logic/global/entity/Mall.java b/logic/src/main/java/com/spring_greens/logic/global/entity/Mall.java new file mode 100644 index 0000000..55c88ba --- /dev/null +++ b/logic/src/main/java/com/spring_greens/logic/global/entity/Mall.java @@ -0,0 +1,56 @@ +package com.spring_greens.logic.global.entity; + +import jakarta.persistence.*; +import jdk.jfr.Description; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import java.time.LocalDateTime; +import java.time.LocalTime; + +@Entity +@Getter +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class Mall { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Description("상가이름") + private String name; + + @Description("상가전화번호") + private String contact; + + @Description("위도") + private Double latitude; + + @Description("경도") + private Double longitude; + + @Description("상가너비") + private Integer width; + + @Column(name = "start_time") + @Description("영업시작시간") + private LocalTime startTime; + + @Column(name = "end_time") + @Description("영업종료시간") + private LocalTime endTime; + + @Column(name = "road_address") + @Description("도로명주소") + private String roadAddress; + + @Column(name = "address_details") + @Description("상세주소") + private String addressDetails; + + @Column(name = "registration_date") + @Description("상가등록일") + private LocalDateTime registrationDate; +} diff --git a/logic/src/main/java/com/spring_greens/logic/global/entity/Product.java b/logic/src/main/java/com/spring_greens/logic/global/entity/Product.java new file mode 100644 index 0000000..39adb13 --- /dev/null +++ b/logic/src/main/java/com/spring_greens/logic/global/entity/Product.java @@ -0,0 +1,63 @@ +package com.spring_greens.logic.global.entity; + + +import jakarta.persistence.*; +import jdk.jfr.Description; +import lombok.Builder; +import lombok.Getter; + +import java.time.LocalDate; +import java.time.LocalDateTime; + +@Builder +@Getter +@Entity +public class Product { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + private Long shop_id; + private Integer price; + private String name; + + @Description("단위") + private String unit; + private String content; + + @Column(name = "stock_status") + @Description("상품 재고 상태") + private Boolean stockStatus; + + @Description("평점수") + private Byte rating; + + @Column(name = "registration_date_time") + @Description("등록일") + private LocalDateTime registrationDateTime; + + @Column(name = "last_change_date_time") + @Description("마지막변경일") + private LocalDateTime lastChangeDateTime; + + @Column(name = "total_viewers") + @Description("누적뷰어수") + private Integer totalViewers; + + @Description("주기") + private Integer age; + + @Column(name = "details_product_click_count") + @Description("상품상세클릭수") + private Integer detailsProductClickCount; + @Column(name = "daily_ad_impressions") + @Description("하루광고노출수") + private Integer dailyAdImpressions; + + @Column(name = "extractable_status") + @Description("마지막 추출 상태") + private Boolean extractableStatus; + + @Column(name = "last_extract_date") + @Description("마지막 추출 날짜") + private LocalDate lastExtractDate; +} diff --git a/logic/src/main/java/com/spring_greens/logic/global/entity/Shop.java b/logic/src/main/java/com/spring_greens/logic/global/entity/Shop.java new file mode 100644 index 0000000..17cd1d2 --- /dev/null +++ b/logic/src/main/java/com/spring_greens/logic/global/entity/Shop.java @@ -0,0 +1,50 @@ +package com.spring_greens.logic.global.entity; + +import jakarta.persistence.*; +import jdk.jfr.Description; +import lombok.Builder; +import lombok.Getter; + +import java.time.LocalDateTime; +import java.time.LocalTime; + + +// @TODO 리팩토링 +@Getter +@Builder +@Entity +public class Shop { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + @Column(name = "user_id") + private Long userId; + @Column(name = "mall_id") + private Long mallId; + private String contact; + private String name; + private String intro; + @Column(name = "profile_type") + @Description("프로필 설정 여부") + private Boolean profileType; + @Column(name = "road_address") + @Description("도로명주소") + private String roadAddress; + + @Column(name = "address_details") + @Description("상세주소") + private String addressDetails; + + @Column(name = "start_time") + @Description("영업시작시간") + private LocalTime startTime; + + @Column(name = "end_time") + @Description("영업종료시간") + private LocalTime endTime; + + @Column(name = "registration_date") + @Description("가게등록일") + private LocalDateTime registrationDateTime; + +} diff --git a/logic/src/main/java/com/spring_greens/logic/global/enums/Mall.java b/logic/src/main/java/com/spring_greens/logic/global/enums/Mall.java new file mode 100644 index 0000000..172ac01 --- /dev/null +++ b/logic/src/main/java/com/spring_greens/logic/global/enums/Mall.java @@ -0,0 +1,14 @@ +package com.spring_greens.logic.global.enums; + +import lombok.Getter; + +@Getter +public enum Mall { + APM( "apm"), + DONGPYEONGHWA("동평화시장"), + CHEONGPYEONGHWA("청평화시장"); + private final String mallName; + Mall(String mallName) { + this.mallName = mallName; + } +} diff --git a/logic/src/main/java/com/spring_greens/logic/global/factory/converter/ConverterFactoryImpl.java b/logic/src/main/java/com/spring_greens/logic/global/factory/converter/ConverterFactoryImpl.java new file mode 100644 index 0000000..9229c62 --- /dev/null +++ b/logic/src/main/java/com/spring_greens/logic/global/factory/converter/ConverterFactoryImpl.java @@ -0,0 +1,33 @@ +package com.spring_greens.logic.global.factory.converter; + +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Component; + +import com.spring_greens.logic.extraction.converter.ifs.ExtractionConverter; +import com.spring_greens.logic.global.factory.converter.ifs.ConverterFactory; + +/** + * ConverterFactory purpose is to break dependency of controller.
+ * if converterFactory is not exist, AbstractBaseController has many of service bean and converter etc.
+ * each of controller need to initialize bean by using constructor.
+ * in this case, each controller increases the number of parameters to constructor.
+ *
+ * let's assume one situation, we have so many controller that contained many services.
+ * if controller is changed or deleted, we have to change each of controller.
+ * + * In order to prevent this, I create converter factory
+ * as a result, this way reduces the dependence between controller and each bean.
+ * @author itstime0809 + */ + +@Component +@RequiredArgsConstructor +public class ConverterFactoryImpl implements ConverterFactory { + private final ExtractionConverter extractionConverter; + + @Override + public ExtractionConverter getExtractionConverter(){ + return extractionConverter; + } +} diff --git a/logic/src/main/java/com/spring_greens/logic/global/factory/converter/ifs/ConverterFactory.java b/logic/src/main/java/com/spring_greens/logic/global/factory/converter/ifs/ConverterFactory.java new file mode 100644 index 0000000..68b160b --- /dev/null +++ b/logic/src/main/java/com/spring_greens/logic/global/factory/converter/ifs/ConverterFactory.java @@ -0,0 +1,7 @@ +package com.spring_greens.logic.global.factory.converter.ifs; + +import com.spring_greens.logic.extraction.converter.ifs.ExtractionConverter; + +public interface ConverterFactory { + ExtractionConverter getExtractionConverter(); +} diff --git a/logic/src/main/java/com/spring_greens/logic/global/factory/repository/RepositoryFactoryImpl.java b/logic/src/main/java/com/spring_greens/logic/global/factory/repository/RepositoryFactoryImpl.java new file mode 100644 index 0000000..949c016 --- /dev/null +++ b/logic/src/main/java/com/spring_greens/logic/global/factory/repository/RepositoryFactoryImpl.java @@ -0,0 +1,35 @@ +package com.spring_greens.logic.global.factory.repository; + +import org.springframework.stereotype.Component; + +import com.spring_greens.logic.global.factory.repository.ifs.RepositoryFactory; +import com.spring_greens.logic.global.repository.MallRepository; +import com.spring_greens.logic.global.repository.ProductRepository; +import com.spring_greens.logic.global.repository.ShopRepository; + +import lombok.RequiredArgsConstructor; + +@Component +@RequiredArgsConstructor +public class RepositoryFactoryImpl implements RepositoryFactory{ + + private final MallRepository mallrepository; + private final ProductRepository productRepository; + private final ShopRepository shopRepository; + + @Override + public MallRepository getMallRepository() { + return mallrepository; + } + + @Override + public ProductRepository getProductRepository() { + return productRepository; + } + + @Override + public ShopRepository getShopRepository() { + return shopRepository; + } + +} diff --git a/logic/src/main/java/com/spring_greens/logic/global/factory/repository/ifs/RepositoryFactory.java b/logic/src/main/java/com/spring_greens/logic/global/factory/repository/ifs/RepositoryFactory.java new file mode 100644 index 0000000..94fc4f8 --- /dev/null +++ b/logic/src/main/java/com/spring_greens/logic/global/factory/repository/ifs/RepositoryFactory.java @@ -0,0 +1,13 @@ +package com.spring_greens.logic.global.factory.repository.ifs; + +import com.spring_greens.logic.global.repository.MallRepository; +import com.spring_greens.logic.global.repository.ProductRepository; +import com.spring_greens.logic.global.repository.ShopRepository; + +public interface RepositoryFactory { + MallRepository getMallRepository(); + + ProductRepository getProductRepository(); + + ShopRepository getShopRepository(); +} diff --git a/logic/src/main/java/com/spring_greens/logic/global/factory/service/ServiceFactoryImpl.java b/logic/src/main/java/com/spring_greens/logic/global/factory/service/ServiceFactoryImpl.java new file mode 100644 index 0000000..09a26de --- /dev/null +++ b/logic/src/main/java/com/spring_greens/logic/global/factory/service/ServiceFactoryImpl.java @@ -0,0 +1,34 @@ +package com.spring_greens.logic.global.factory.service; + +import com.spring_greens.logic.extraction.service.ExtractionServiceImpl; +// import com.spring_greens.logic.auth.service.UserService; +// import com.spring_greens.logic.fcm.service.FcmService; +import com.spring_greens.logic.global.factory.service.ifs.ServiceFactory; +// import com.spring_greens.logic.global.redis.service.RedisService; +// import com.spring_greens.logic.mall.service.ifs.MallService; +// import com.spring_greens.logic.shop.service.ShopService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; + +/** + * ConverterFactory purpose is to break dependency of controller.
+ * if converterFactory is not exist, AbstractBaseController has many of service bean and converter etc.
+ * each of controller need to initialize bean by using constructor.
+ * in this case, each controller increases the number of parameters to constructor.
+ *
+ * let's assume one situation, we have so many controller that contained many services.
+ * if controller is changed or deleted, we have to change each of controller.
+ * + * In order to prevent this, I create converter factory
+ * as a result, this way reduces the dependence between controller and each bean.
+ * @author itstime0809 + */ +@Component +@RequiredArgsConstructor +public class ServiceFactoryImpl implements ServiceFactory { + private final ExtractionServiceImpl extractionService; + @Override + public ExtractionServiceImpl getExtractionService() { + return extractionService; + } +} diff --git a/logic/src/main/java/com/spring_greens/logic/global/factory/service/ifs/ServiceFactory.java b/logic/src/main/java/com/spring_greens/logic/global/factory/service/ifs/ServiceFactory.java new file mode 100644 index 0000000..5684176 --- /dev/null +++ b/logic/src/main/java/com/spring_greens/logic/global/factory/service/ifs/ServiceFactory.java @@ -0,0 +1,12 @@ +package com.spring_greens.logic.global.factory.service.ifs; + +// import com.spring_greens.logic.auth.service.UserService; +import com.spring_greens.logic.extraction.service.ExtractionServiceImpl; +// import com.spring_greens.logic.fcm.service.FcmService; +// import com.spring_greens.logic.global.redis.service.RedisService; +// import com.spring_greens.logic.mall.service.ifs.MallService; +// import com.spring_greens.logic.shop.service.ShopService; + +public interface ServiceFactory { + ExtractionServiceImpl getExtractionService(); +} diff --git a/logic/src/main/java/com/spring_greens/logic/global/repository/MallRepository.java b/logic/src/main/java/com/spring_greens/logic/global/repository/MallRepository.java new file mode 100644 index 0000000..815e7d9 --- /dev/null +++ b/logic/src/main/java/com/spring_greens/logic/global/repository/MallRepository.java @@ -0,0 +1,17 @@ +package com.spring_greens.logic.global.repository; + +import java.util.List; +import java.util.Optional; + +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.CrudRepository; +import org.springframework.stereotype.Repository; + +import com.spring_greens.logic.global.dto.MallDTO; +import com.spring_greens.logic.global.entity.Mall; + +@Repository +public interface MallRepository extends CrudRepository{ + @Query() + Optional> findByShop(); +} diff --git a/logic/src/main/java/com/spring_greens/logic/global/repository/ProductRepository.java b/logic/src/main/java/com/spring_greens/logic/global/repository/ProductRepository.java new file mode 100644 index 0000000..b90f27c --- /dev/null +++ b/logic/src/main/java/com/spring_greens/logic/global/repository/ProductRepository.java @@ -0,0 +1,28 @@ +package com.spring_greens.logic.global.repository; + +import java.util.List; +import java.util.Optional; + +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.CrudRepository; +import org.springframework.stereotype.Repository; + +import com.spring_greens.logic.global.dto.ProductDTO; +import com.spring_greens.logic.global.entity.Product; + +@Repository +public interface ProductRepository extends CrudRepository{ + @Query(value = "select p.id, " + + "p.shop_id, " + + "p.name, " + + "p.unit, " + + "p.price, " + + "p.total_viewers, " + + "p.age, " + + "p.detail_product_click_count, " + + "p.daily_ad_impressions, "+ + "p.extractable_status, " + + "p.last_extract_date " + + "from product as p where p.stock_status = 1 and p.extractable_status = 1", nativeQuery = true) + Optional> findAllAge(); +} diff --git a/logic/src/main/java/com/spring_greens/logic/global/repository/ShopRepository.java b/logic/src/main/java/com/spring_greens/logic/global/repository/ShopRepository.java new file mode 100644 index 0000000..3da9b83 --- /dev/null +++ b/logic/src/main/java/com/spring_greens/logic/global/repository/ShopRepository.java @@ -0,0 +1,22 @@ +package com.spring_greens.logic.global.repository; + +import java.util.List; +import java.util.Optional; + +import com.spring_greens.logic.global.entity.Product; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.CrudRepository; +import org.springframework.data.repository.query.Param; +import org.springframework.stereotype.Repository; + +import com.spring_greens.logic.global.dto.ShopDTO; +import com.spring_greens.logic.global.entity.Shop; + +@Repository +public interface ShopRepository extends CrudRepository { + @Query(value = "SELECT s.id, s.mall_id, s.name, " + + "s.contact, s.address_details " + + "FROM shop as s INNER JOIN product as p ON p.id = s.product_id " + + "WHERE p.id IN :productIds") + Optional> findByProduct(@Param("productIds") List ProductId); +} diff --git a/logic/src/main/resources/application-dev.properties b/logic/src/main/resources/application-dev.properties new file mode 100644 index 0000000..d897433 --- /dev/null +++ b/logic/src/main/resources/application-dev.properties @@ -0,0 +1,39 @@ +spring.application.name=presentation +# DB dataSource URL +spring.datasource.url=${DB_ENDPOINT} + +# DB username should change your localhost +spring.datasource.username=${DB_USERNAME} + +# DB password should change your password +spring.datasource.password=${DB_PASSWORD} + +# Hibernate do not convert logical naming to physical name. +# ex ) if you write member_id, that may apply member_id. +spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.CamelCaseToUnderscoresNamingStrategy + +# Lazy datasource initialization for docker environment. +spring.jpa.defer-datasource-initialization=true + +# show sql query, when execute jpa query method +spring.jpa.show-sql=true +spring.jpa.hibernate.ddl-auto=none +spring.jpa.properties.hibernate.format_sql=true + +# redis configuration +spring.data.redis.host=${REDIS_HOST} +spring.data.redis.port=${REDIS_PORT} +# Server port configuration +spring.data.redis.password=${REDIS_PASSWORD} +server.port=${SERVER_PORT} + +# Logging configuration for dev environment +logging.config=classpath:logback-spring-dev.xml + +# fcm key path +fcm.sdk.key.path=${FCM_SDK_KEY_PATH} + +# fileSystem path +file.upload-absolute-path=${FILE_UPLOAD_ABSOLUTE_PATH} + +spring.datasource.driver-class-name=org.mariadb.jdbc.Driver \ No newline at end of file diff --git a/logic/src/main/resources/logback-spring-dev.xml b/logic/src/main/resources/logback-spring-dev.xml new file mode 100644 index 0000000..75875b1 --- /dev/null +++ b/logic/src/main/resources/logback-spring-dev.xml @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + ${CONSOLE_PATTERN} + + + + + + + ${ROLLING_PATTERN} + + ${FILE_NAME} + + + + ${LOG_NAME_PATTERN} + + ${MAX_HISTORY} + + ${MAX_FILE_SIZE} + + ${TOTAL_SIZE} + + + + + + + + + \ No newline at end of file diff --git a/logic/src/main/resources/static/fcmMessagePush.html b/logic/src/main/resources/static/fcmMessagePush.html new file mode 100644 index 0000000..adb4f7e --- /dev/null +++ b/logic/src/main/resources/static/fcmMessagePush.html @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + +
+
+
가게관리
+ lroenimson님 +
+ 로그아웃 +
+
+
+
+
상품예약
+ + +
+
+
상품발송내역
+ + +
+
+
+
+
+ + +
이미지를 업로드 해주세요
+
+
+
+
+
+
제목을 입력해주세요
+
+
+
+
+
시간설정
+
+
+
+
+
시간설정
+
+
+
+
+
시간설정
+
+
+
+
+
예약하기
+
+
+
+
+
예약하기
+
+
+
+
+
예약하기
+
+
+
+
+
내용을 입력해주세요
+
+
+
+
내용을 입력해주세요
+
+
+
내용을 입력해주세요
+
+
+
+
제목을 입력해주세요
+
+
+
+
+
제목을 입력해주세요
+
+
+
+
+
+ + +
이미지를 업로드 해주세요
+
+
+
+
+
+
+ + +
이미지를 업로드 해주세요
+
+
+
+
+ + + + + + \ No newline at end of file diff --git a/logic/src/main/resources/static/fcmMessagePushStyle.css b/logic/src/main/resources/static/fcmMessagePushStyle.css new file mode 100644 index 0000000..2ae06f5 --- /dev/null +++ b/logic/src/main/resources/static/fcmMessagePushStyle.css @@ -0,0 +1,322 @@ +body { + margin: 0; + line-height: normal; +} + +.div { + position: absolute; + top: calc(50% - 11px); + left: 22px; +} +.lroenimson { + position: absolute; + top: calc(50% - 10px); + left: 1453px; + font-size: 16px; +} +.b { + position: relative; +} +.wrapper { + position: absolute; + top: calc(50% - 13px); + left: 1622px; + border-radius: 4px; + background-color: #222; + display: flex; + flex-direction: row; + align-items: center; + justify-content: center; + padding: 5px 8px; + font-size: 14px; +} +.parent { + position: absolute; + top: 0px; + left: 0px; + background-color: #304ffe; + width: 1920px; + height: 54px; + overflow: hidden; + font-size: 20px; + color: #fff; +} +.div1 { + position: absolute; + top: calc(50% - 9.5px); + left: calc(50% - 71px); +} +.mingcuteright-line-icon { + position: absolute; + top: 18px; + left: 132px; + width: 14px; + height: 14px; + overflow: hidden; + object-fit: contain; +} +.group { + position: absolute; + top: 29px; + left: 19px; + border-bottom: 1px solid #999; + box-sizing: border-box; + width: 150px; + height: 45px; + overflow: hidden; +} +.container { + position: absolute; + top: 74px; + left: 19px; + border-bottom: 1px solid #999; + box-sizing: border-box; + width: 150px; + height: 45px; + overflow: hidden; +} +.frame-parent { + position: absolute; + top: 54px; + left: 0px; + box-shadow: 0px 4px 4px rgba(0, 0, 0, 0.25); + background-color: #fff; + border: 1px solid #b1b1b1; + box-sizing: border-box; + width: 179px; + height: 1153px; + overflow: hidden; + font-size: 16px; + color: #222; +} +.group-child { + position: absolute; + top: 0px; + left: 18px; + width: 204px; + height: 204px; +} +.div3 { + position: absolute; + top: 214px; + left: 0px; +} +.group-parent { + position: absolute; + top: 207px; + left: 96px; + width: 255px; + height: 242px; +} +.group-wrapper { + position: absolute; + top: 0px; + left: 0px; + box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.25); + border-radius: 6px; + background-color: #fff; + width: 447px; + height: 600px; + overflow: hidden; +} +.desktop-6-inner { + position: absolute; + top: 129px; + left: 250px; + width: 447px; + height: 600px; +} +.div4 { + position: absolute; + top: 17px; + left: 27px; + display: inline-block; + width: 346px; + height: 28px; +} +.frame { + position: absolute; + top: 0px; + left: 0px; + box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.25); + border-radius: 6px; + background-color: #fff; + width: 447px; + height: 62px; + overflow: hidden; +} +.desktop-6-child { + position: absolute; + top: 766px; + left: 250px; + width: 447px; + height: 62px; +} +.div5 { + position: absolute; + top: 17px; + left: 24px; + display: inline-block; + width: 91px; + height: 28px; + font-size: large; + text-align: center; + justify-content: center; +} +.frame-div { + position: absolute; + top: 0px; + left: 0px; + box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.25); + border-radius: 6px; + background-color: #fff; + width: 139px; + height: 62px; + overflow: hidden; +} +.group-div { + position: absolute; + top: 1029px; + left: 395px; + width: 139px; + height: 62px; +} +.desktop-6-inner1 { + position: absolute; + top: 1029px; + left: 932px; + width: 139px; + height: 62px; +} +.desktop-6-inner2 { + position: absolute; + top: 1029px; + left: 1460px; + width: 139px; + height: 62px; +} +.div8 { + position: absolute; + top: 17px; + left: 178px; + display: inline-block; + width: 91px; + font-size: large; + text-align: center; + justify-content: center; +} +.wrapper3 { + position: absolute; + top: 0px; + left: 0px; + box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.25); + border-radius: 6px; + background-color: #304ffe; + width: 447px; + height: 62px; + overflow: hidden; +} +.desktop-6-inner3 { + position: absolute; + top: 1116px; + left: 250px; + width: 447px; + height: 62px; + color: #fff; +} +.desktop-6-inner4 { + position: absolute; + top: 1116px; + left: 778px; + width: 447px; + height: 62px; + color: #fff; +} +.desktop-6-inner5 { + position: absolute; + top: 1116px; + left: 1306px; + width: 447px; + height: 62px; + color: #fff; +} +.wrapper6 { + position: absolute; + top: 0px; + left: 0px; + box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.25); + border-radius: 6px; + background-color: #fff; + width: 447px; + height: 148px; + overflow: hidden; +} +.desktop-6-inner6 { + position: absolute; + top: 856px; + left: 250px; + width: 447px; + height: 148px; +} +.wrapper7 { + position: absolute; + top: 856px; + left: 778px; + box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.25); + border-radius: 6px; + background-color: #fff; + width: 447px; + height: 148px; + overflow: hidden; +} +.wrapper8 { + position: absolute; + top: 856px; + left: 1306px; + box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.25); + border-radius: 6px; + background-color: #fff; + width: 447px; + height: 148px; + overflow: hidden; +} +.desktop-6-inner7 { + position: absolute; + top: 774px; + left: 778px; + width: 447px; + height: 62px; +} +.desktop-6-inner8 { + position: absolute; + top: 774px; + left: 1306px; + width: 447px; + height: 62px; +} +.desktop-6-inner9 { + position: absolute; + top: 129px; + left: 778px; + width: 447px; + height: 600px; +} +.desktop-6-inner10 { + position: absolute; + top: 129px; + left: 1306px; + width: 447px; + height: 600px; +} +.desktop-6 { + width: 100%; + position: relative; + background-color: #fff; + height: 1207px; + overflow: hidden; + text-align: left; + font-size: 24px; + color: #999; + font-family: Roboto; +} +