Compare commits
18 Commits
940a0320b3
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
37bc3f423c | ||
|
|
69d84c4706 | ||
| d84a3313e3 | |||
|
|
f786df1d9b | ||
|
|
40a1c2740d | ||
|
|
dae8e6d3a7 | ||
|
|
505a3e5101 | ||
|
|
a697185451 | ||
|
|
77c0a7d43f | ||
|
|
843db73d12 | ||
|
|
aed1321d88 | ||
|
|
aef25bc3dc | ||
|
|
711bba3e4b | ||
|
|
13b469d26f | ||
| 2635c22f27 | |||
| 8503ef4f3c | |||
|
|
fcfbd1fd96 | ||
|
|
001bba7cb1 |
1
.idea/compiler.xml
generated
1
.idea/compiler.xml
generated
@@ -2,6 +2,7 @@
|
||||
<project version="4">
|
||||
<component name="CompilerConfiguration">
|
||||
<annotationProcessing>
|
||||
<profile default="true" name="Default" enabled="true" />
|
||||
<profile name="Maven default annotation processors profile" enabled="true">
|
||||
<sourceOutputDir name="target/generated-sources/annotations" />
|
||||
<sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
|
||||
|
||||
4
.idea/dataSources.xml
generated
4
.idea/dataSources.xml
generated
@@ -1,13 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="DataSourceManagerImpl" format="xml" multifile-model="true">
|
||||
<data-source source="LOCAL" name="profile@leejk0523.com" uuid="48fe1c90-2c8b-4422-ab16-143a998890c0">
|
||||
<data-source source="LOCAL" name="pub@leejk0523.com" uuid="ba69e241-137d-4c9f-b047-5010d887b198">
|
||||
<driver-ref>mariadb</driver-ref>
|
||||
<synchronize>true</synchronize>
|
||||
<imported>true</imported>
|
||||
<remarks>$PROJECT_DIR$/java/src/main/resources/application.properties</remarks>
|
||||
<jdbc-driver>org.mariadb.jdbc.Driver</jdbc-driver>
|
||||
<jdbc-url>jdbc:mariadb://leejk0523.com:3306/profile</jdbc-url>
|
||||
<jdbc-url>jdbc:mariadb://leejk0523.com:3306/pub</jdbc-url>
|
||||
<jdbc-additional-properties>
|
||||
<property name="com.intellij.clouds.kubernetes.db.host.port" />
|
||||
<property name="com.intellij.clouds.kubernetes.db.enabled" value="false" />
|
||||
|
||||
1
.idea/encodings.xml
generated
1
.idea/encodings.xml
generated
@@ -2,5 +2,6 @@
|
||||
<project version="4">
|
||||
<component name="Encoding">
|
||||
<file url="file://$PROJECT_DIR$/java/src/main/java" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/java/target/generated-sources/java" charset="UTF-8" />
|
||||
</component>
|
||||
</project>
|
||||
1
.idea/modules.xml
generated
1
.idea/modules.xml
generated
@@ -3,6 +3,7 @@
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/java_vue.iml" filepath="$PROJECT_DIR$/.idea/java_vue.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/java/javavue.iml" filepath="$PROJECT_DIR$/java/javavue.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
124
.idea/uiDesigner.xml
generated
Normal file
124
.idea/uiDesigner.xml
generated
Normal file
@@ -0,0 +1,124 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Palette2">
|
||||
<group name="Swing">
|
||||
<item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
|
||||
</item>
|
||||
<item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
|
||||
</item>
|
||||
<item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
|
||||
</item>
|
||||
<item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.svg" removable="false" auto-create-binding="false" can-attach-label="true">
|
||||
<default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
|
||||
</item>
|
||||
<item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
|
||||
<initial-values>
|
||||
<property name="text" value="Button" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
|
||||
<initial-values>
|
||||
<property name="text" value="RadioButton" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
|
||||
<initial-values>
|
||||
<property name="text" value="CheckBox" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
|
||||
<initial-values>
|
||||
<property name="text" value="Label" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||
<preferred-size width="150" height="-1" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||
<preferred-size width="150" height="-1" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||
<preferred-size width="150" height="-1" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
|
||||
<preferred-size width="200" height="200" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
|
||||
<preferred-size width="200" height="200" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
|
||||
</item>
|
||||
<item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
|
||||
<preferred-size width="-1" height="20" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
|
||||
</item>
|
||||
</group>
|
||||
</component>
|
||||
</project>
|
||||
40
java/README.md
Normal file
40
java/README.md
Normal file
@@ -0,0 +1,40 @@
|
||||
### 기본 환경
|
||||
- Java 11
|
||||
- MyBatis 4.x
|
||||
- JPA 2.2
|
||||
- QueryDSL 5.0
|
||||
|
||||
### 개발 규약
|
||||
- 사용하지 않는 Parameter는 넣지 않는다.
|
||||
- Request, Response 호출은 EgovRequestUtils을 통해서만 한다.
|
||||
- 관리자 Session 정보는 EgovAdminSessionUtils로 호출한다.(MultipartRequest는 제외)
|
||||
- 사용자 Session 정보는 EgovUserSessionUtils로 호출한다.
|
||||
- Spring context에서 벗어나게 개발하지 않는다.
|
||||
|
||||
### 어노테이션
|
||||
- API Controller: @RestController
|
||||
- Page Controller: @Controller
|
||||
- Service: @Service
|
||||
- Mapper: @Mapper
|
||||
- DAO 또는 별도 컴포넌트들: @Component
|
||||
|
||||
### API URL 규약
|
||||
- 대국민포털(prefix): 없음
|
||||
- 참여기관/관리자포털(prefix): /admin
|
||||
- 페이지: /**
|
||||
- api: /api/**
|
||||
- 메뉴 등록 시 full url로 기재할 것!
|
||||
- 페이지 메뉴는 도메인으로 분기 처리되므로 동일 URL 사용 가능
|
||||
- id 조회의 경우 반드시 query 처리할 것!
|
||||
|
||||
|
||||
### DB 암호화
|
||||
- 환경변수 추가 필요(안하면 에러 남)
|
||||
- {project.baseDir}/main/resources/ksing/db 에 있는 모든 파일을 C:\SecureDBAgent 에 복사
|
||||
- 아래의 정보로 환경변수 세팅 진행
|
||||
- SDB_HOME / C:\SecureDBAgent
|
||||
- SDB_FIRST_PORT / 9909
|
||||
|
||||
### 비지니스 로직 로깅 관련
|
||||
- [필수] 비지니스 로직에 로깅할 경우 class 상단에 @Slf4j 어노테이션 선언
|
||||
- [필수] Service에서는 전자정부프레임워크에서 제공하는 egovLogger를 사용
|
||||
29
java/git.md
Normal file
29
java/git.md
Normal file
@@ -0,0 +1,29 @@
|
||||
### 임시 git 설정(SSH 터널링)
|
||||
```
|
||||
ssh -i KLAC_SYS_ADM.pem -o ServerAliveInterval=60 -L 8081:localhost:8081 -L 5000:localhost:3000 rocky@192.168.30.7 -p 6722
|
||||
```
|
||||
|
||||
### 브랜치 용도
|
||||
- master: 운영 서버 반영 브랜치
|
||||
- dev: 개발 서버 반영 브랜치
|
||||
- mix: 개발용 브랜치
|
||||
|
||||
### 신규 브랜치 작성 방법
|
||||
- feature/gitea아이디/번호
|
||||
- 예) feature/natoro/1
|
||||
- push 할 때마다 뒷 번호는 증가
|
||||
|
||||
### git 사용 방법
|
||||
1. 작업하기 전 반드시 mix 브랜치에서 new branch로 생성
|
||||
2. 작업이 완료될 경우 반드시 commit
|
||||
3. 새로운 내용을 받을 때 pull(예: mix 브랜치 pull)
|
||||
4. 작업한 내용을 서버에 올릴 때 push
|
||||
5. 개발자는 merge 작업하지 말 것!
|
||||
6. 작업 단위는 작게 진행(기능별로 분리해서 branch 작업)
|
||||
7. 커미터, 기능별 태그 관리 및 버전 관리할 것
|
||||
|
||||
### 소스 관리 및 반영 관리(수정)
|
||||
1. pull request 처리 주기
|
||||
2. 코드 리뷰 주기
|
||||
3. 반영 주기
|
||||
4. 예) 수요일 - 오후 4시 pull request 처리
|
||||
8
java/mapper.md
Normal file
8
java/mapper.md
Normal file
@@ -0,0 +1,8 @@
|
||||
Mapper 사용 시 아래와 같이 작성(중괄호는 치환되는 명칭)
|
||||
|
||||
```
|
||||
package: egovframework.com.lasp.{업무명}.mapper
|
||||
Mapper파일명: {Admin | User}{업무명}Mapper.xml
|
||||
annotation: org.egovframe.rte.psl.dataaccess.mapper.Mapper
|
||||
xml파일: \resources\egovframework\sqlmap\mappers\{Mapper명과 동일}.xml
|
||||
```
|
||||
64
java/pom.xml
64
java/pom.xml
@@ -1,36 +1,27 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>3.3.5</version>
|
||||
<relativePath/> <!-- lookup parent from repository -->
|
||||
</parent>
|
||||
|
||||
<groupId>com.leejk0523</groupId>
|
||||
<artifactId>javavue</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<packaging>war</packaging>
|
||||
<name>javavue</name>
|
||||
<description>javavue</description>
|
||||
<url/>
|
||||
<licenses>
|
||||
<license/>
|
||||
</licenses>
|
||||
<developers>
|
||||
<developer/>
|
||||
</developers>
|
||||
<scm>
|
||||
<connection/>
|
||||
<developerConnection/>
|
||||
<tag/>
|
||||
<url/>
|
||||
</scm>
|
||||
|
||||
<properties>
|
||||
<java.version>17</java.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<!-- Spring Boot Dependencies -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
||||
@@ -39,24 +30,48 @@
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web-services</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.mariadb.jdbc</groupId>
|
||||
<artifactId>mariadb-java-client</artifactId>
|
||||
<scope>runtime</scope>
|
||||
<!-- <version>3.1.2</version>-->
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-tomcat</artifactId>
|
||||
<groupId>jakarta.validation</groupId>
|
||||
<artifactId>jakarta.validation-api</artifactId>
|
||||
<!-- <version>3.1.0</version>-->
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<!-- <version>1.18.24</version>-->
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
|
||||
<dependency>
|
||||
<groupId>com.querydsl</groupId>
|
||||
<artifactId>querydsl-jpa</artifactId>
|
||||
<version>5.0.0</version>
|
||||
<classifier>jakarta</classifier>
|
||||
</dependency>
|
||||
<!-- QueryDSL Annotation Processor -->
|
||||
<dependency>
|
||||
<groupId>com.querydsl</groupId>
|
||||
<artifactId>querydsl-apt</artifactId>
|
||||
<version>5.0.0</version>
|
||||
<classifier>jakarta</classifier>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<defaultGoal>package</defaultGoal>
|
||||
<directory>${basedir}/target</directory>
|
||||
<finalName>javavue</finalName>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
@@ -64,5 +79,4 @@
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
</project>
|
||||
@@ -5,9 +5,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
public class JavavueApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(JavavueApplication.class, args);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.leejk0523.javavue.admin.contents.controller;
|
||||
|
||||
import com.leejk0523.javavue.admin.contents.service.AdminContentsService;
|
||||
import com.leejk0523.javavue.admin.contents.vo.ContentsListResult;
|
||||
import com.leejk0523.javavue.admin.contents.vo.ContentsPagingQuery;
|
||||
import com.leejk0523.javavue.model.AsaContent;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
public class AdminContentsController {
|
||||
private final AdminContentsService adminContentsService;
|
||||
|
||||
@GetMapping("/api/admin/contents/contentsList")
|
||||
public ResponseEntity<Page<ContentsListResult>> findContentsList(ContentsPagingQuery query) {
|
||||
final var results = adminContentsService.findContentsList(query);
|
||||
return ResponseEntity.ok(results);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
package com.leejk0523.javavue.admin.contents.dao;
|
||||
|
||||
import ch.qos.logback.core.util.StringUtil;
|
||||
import com.leejk0523.javavue.admin.contents.vo.ContentsListResult;
|
||||
import com.leejk0523.javavue.admin.contents.vo.ContentsPagingQuery;
|
||||
import com.leejk0523.javavue.common.QueryDSLUtils;
|
||||
import com.leejk0523.javavue.model.AsaContent;
|
||||
import com.leejk0523.javavue.model.QAsaContent;
|
||||
import com.querydsl.core.types.Projections;
|
||||
import com.querydsl.core.types.dsl.BooleanExpression;
|
||||
|
||||
import com.querydsl.core.types.dsl.Expressions;
|
||||
import io.micrometer.common.util.StringUtils;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageImpl;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.jpa.repository.support.QuerydslRepositorySupport;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Repository
|
||||
public class AdminContentsDao extends QuerydslRepositorySupport {
|
||||
|
||||
public AdminContentsDao() {
|
||||
super(AsaContent.class);
|
||||
}
|
||||
|
||||
public Page<ContentsListResult> findContentsList(ContentsPagingQuery query) {
|
||||
QAsaContent asaContent = QAsaContent.asaContent;
|
||||
|
||||
final var offset = QueryDSLUtils.getOffset(query);
|
||||
final var limit = QueryDSLUtils.getLimit(query);
|
||||
final var pageable = QueryDSLUtils.getPageable(query);
|
||||
|
||||
BooleanExpression expression = asaContent.delYn.eq("N");
|
||||
|
||||
if (StringUtils.isNotEmpty(query.getKeyword())) {
|
||||
switch (query.getType()) {
|
||||
case CONTENT: {
|
||||
expression = expression.and(asaContent.contents.contains(query.getKeyword()));
|
||||
break;
|
||||
}
|
||||
case TITLE : {
|
||||
expression = expression.and(asaContent.contentTitle.contains(query.getKeyword()));
|
||||
break;
|
||||
}
|
||||
case TOTAL: {
|
||||
expression = expression.and(asaContent.contents.contains(query.getKeyword())
|
||||
.or(asaContent.contentTitle.contains(query.getKeyword())));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (StringUtils.isNotEmpty(query.getOrgId())) {
|
||||
expression = expression.and(asaContent.orgId.eq(query.getOrgId()));
|
||||
}
|
||||
|
||||
final var list = from(asaContent)
|
||||
.select(
|
||||
Projections.bean(
|
||||
ContentsListResult.class,
|
||||
asaContent.contentId,
|
||||
asaContent.contentTitle,
|
||||
asaContent.orgId,
|
||||
asaContent.useYn,
|
||||
asaContent.frstRgtrId,
|
||||
asaContent.frstRegDt,
|
||||
asaContent.lastMdfrId,
|
||||
asaContent.lastMdfcnDt
|
||||
)
|
||||
)
|
||||
.where(expression)
|
||||
.limit(limit)
|
||||
.offset(offset)
|
||||
.orderBy(asaContent.contentId.desc())
|
||||
.fetch();
|
||||
|
||||
final var total = from(asaContent).where(expression).fetchCount();
|
||||
|
||||
return new PageImpl<>(list, pageable, total);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.leejk0523.javavue.admin.contents.service;
|
||||
|
||||
import com.leejk0523.javavue.admin.contents.vo.ContentsListResult;
|
||||
import com.leejk0523.javavue.admin.contents.vo.ContentsPagingQuery;
|
||||
import com.leejk0523.javavue.model.AsaContent;
|
||||
import org.springframework.data.domain.Page;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface AdminContentsService {
|
||||
Page<ContentsListResult> findContentsList(ContentsPagingQuery query);
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.leejk0523.javavue.admin.contents.service;
|
||||
|
||||
import com.leejk0523.javavue.admin.contents.dao.AdminContentsDao;
|
||||
import com.leejk0523.javavue.admin.contents.vo.ContentsListResult;
|
||||
import com.leejk0523.javavue.admin.contents.vo.ContentsPagingQuery;
|
||||
import com.leejk0523.javavue.model.AsaContent;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class AdminContentsServiceImpl implements AdminContentsService {
|
||||
private final AdminContentsDao adminContentsDao;
|
||||
|
||||
@Override
|
||||
public Page<ContentsListResult> findContentsList(ContentsPagingQuery query) {
|
||||
return adminContentsDao.findContentsList(query);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.leejk0523.javavue.admin.contents.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Data
|
||||
public class ContentsListResult {
|
||||
private Integer contentId;
|
||||
private String contentTitle;
|
||||
private String orgId;
|
||||
private String useYn;
|
||||
private String frstRgtrId;
|
||||
private LocalDateTime frstRegDt;
|
||||
private String lastMdfrId;
|
||||
private LocalDateTime lastMdfcnDt;
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.leejk0523.javavue.admin.contents.vo;
|
||||
|
||||
import com.leejk0523.javavue.common.PagingQuery;
|
||||
import lombok.Data;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
|
||||
@Data
|
||||
public class ContentsPagingQuery implements PagingQuery {
|
||||
|
||||
@NotNull
|
||||
private int page;
|
||||
|
||||
@NotNull
|
||||
private int size;
|
||||
|
||||
private String orgId;
|
||||
private String siteId;
|
||||
private String keyword;
|
||||
private Type type;
|
||||
|
||||
public enum Type {
|
||||
TITLE,
|
||||
CONTENT,
|
||||
TOTAL
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.leejk0523.javavue.admin.login.controller;
|
||||
|
||||
import com.leejk0523.javavue.admin.login.service.UserLoginService;
|
||||
import com.leejk0523.javavue.admin.login.vo.In;
|
||||
import com.leejk0523.javavue.admin.login.vo.Out;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
public class UserLoginController {
|
||||
private final UserLoginService userLoginService;
|
||||
|
||||
@PostMapping("/api/admin/login")
|
||||
private ResponseEntity<Out> login(@RequestBody In in) {
|
||||
final var authorization = userLoginService.login(in);
|
||||
|
||||
if (Objects.isNull(authorization)) {
|
||||
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
|
||||
}
|
||||
|
||||
return ResponseEntity.ok(authorization);
|
||||
}
|
||||
|
||||
@GetMapping("/api/test")
|
||||
public String test() {
|
||||
return "Hello World!";
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
package com.leejk0523.javavue.admin.login.dao;
|
||||
|
||||
import com.leejk0523.javavue.admin.login.vo.AdminMember;
|
||||
import com.leejk0523.javavue.admin.login.vo.In;
|
||||
import com.leejk0523.javavue.admin.login.vo.Member;
|
||||
import com.leejk0523.javavue.admin.login.vo.Out;
|
||||
import com.leejk0523.javavue.model.*;
|
||||
import com.querydsl.core.types.Projections;
|
||||
|
||||
import org.springframework.data.jpa.repository.support.QuerydslRepositorySupport;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
public class UserLoginDao extends QuerydslRepositorySupport {
|
||||
public UserLoginDao() {
|
||||
super(AsaAdminMember.class);
|
||||
}
|
||||
|
||||
public Member findByMemberId(In in) {
|
||||
QAsaAdminMember asaAdminMember = QAsaAdminMember.asaAdminMember;
|
||||
|
||||
return from(asaAdminMember)
|
||||
.select(Projections.bean(
|
||||
AdminMember.class,
|
||||
asaAdminMember.adminId.as("memberId"),
|
||||
asaAdminMember.adminName.as("memberName"),
|
||||
asaAdminMember.adminPassword.as("memberPassword"),
|
||||
asaAdminMember.adminActive.as("memberEnabled"),
|
||||
asaAdminMember.adminLoginFailCount.as("memberFailureCount"),
|
||||
asaAdminMember.adminLock.as("memberLocked"),
|
||||
asaAdminMember.orgId.as("orgzId")
|
||||
))
|
||||
.where(asaAdminMember.adminId.eq(in.getMemberId()))
|
||||
.fetchOne();
|
||||
}
|
||||
|
||||
public List<Out.Menu> findAllMenuByAdminId(String adminId) {
|
||||
final var menu = QAsaMenu.asaMenu;
|
||||
final var permission = QAsaPermission.asaPermission;
|
||||
final var adminSiteRoleRel = QAsaAdminSiteRoleRel.asaAdminSiteRoleRel;
|
||||
|
||||
return from(menu)
|
||||
.innerJoin(adminSiteRoleRel).on(
|
||||
menu.siteId.eq(adminSiteRoleRel.siteId)
|
||||
)
|
||||
.innerJoin(permission).on(
|
||||
adminSiteRoleRel.siteId.eq(permission.siteId)
|
||||
.and(adminSiteRoleRel.roleCode.eq(permission.roleCode))
|
||||
.and(menu.menuId.eq(permission.menuId))
|
||||
)
|
||||
.distinct()
|
||||
.select(Projections.bean(
|
||||
Out.Menu.class,
|
||||
menu.menuId,
|
||||
menu.upMenuId,
|
||||
menu.menuName,
|
||||
menu.menuType,
|
||||
menu.menuDepth,
|
||||
menu.menuOrder,
|
||||
menu.menuUrl
|
||||
))
|
||||
.where(
|
||||
adminSiteRoleRel.adminId.eq(adminId)
|
||||
.and(adminSiteRoleRel.siteId.eq("admin"))
|
||||
.and(menu.menuType.ne(AsaMenu.Type.API))
|
||||
.and(menu.menuStatus.eq(AsaMenu.Status.ENABLED))
|
||||
)
|
||||
.orderBy(menu.menuDepth.asc(), menu.menuOrder.asc())
|
||||
.fetch();
|
||||
}
|
||||
|
||||
public List<Out.PermitApi> findAllPermitApiByAdminId(String adminId) {
|
||||
final var menu = QAsaMenu.asaMenu;
|
||||
final var permission = QAsaPermission.asaPermission;
|
||||
final var adminSiteRoleRel = QAsaAdminSiteRoleRel.asaAdminSiteRoleRel;
|
||||
|
||||
return from(menu)
|
||||
.innerJoin(adminSiteRoleRel).on(
|
||||
menu.siteId.eq(adminSiteRoleRel.siteId)
|
||||
)
|
||||
.innerJoin(permission).on(
|
||||
adminSiteRoleRel.siteId.eq(permission.siteId)
|
||||
.and(adminSiteRoleRel.roleCode.eq(permission.roleCode))
|
||||
.and(menu.menuId.eq(permission.menuId))
|
||||
)
|
||||
.distinct()
|
||||
.select(Projections.bean(
|
||||
Out.PermitApi.class,
|
||||
menu.menuUrl
|
||||
))
|
||||
.where(
|
||||
adminSiteRoleRel.adminId.eq(adminId)
|
||||
.and(adminSiteRoleRel.siteId.eq("admin"))
|
||||
.and(menu.menuType.eq(AsaMenu.Type.API))
|
||||
)
|
||||
.fetch();
|
||||
}
|
||||
|
||||
public List<AsaRole> findRoleCodeByAdminId(String adminId) {
|
||||
final var adminSiteRole = QAsaAdminSiteRoleRel.asaAdminSiteRoleRel;
|
||||
final var role = QAsaRole.asaRole;
|
||||
|
||||
return from(adminSiteRole)
|
||||
.innerJoin(role).on(adminSiteRole.roleCode.eq(role.roleCode)
|
||||
.and(adminSiteRole.siteId.eq(role.siteId))
|
||||
)
|
||||
.select(role)
|
||||
.where(adminSiteRole.adminId.eq(adminId))
|
||||
.fetch();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package com.leejk0523.javavue.admin.login.service;
|
||||
|
||||
import com.leejk0523.javavue.admin.login.vo.In;
|
||||
import com.leejk0523.javavue.admin.login.vo.Out;
|
||||
|
||||
public interface UserLoginService {
|
||||
Out login(In in);
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package com.leejk0523.javavue.admin.login.service;
|
||||
|
||||
import com.leejk0523.javavue.admin.login.dao.UserLoginDao;
|
||||
import com.leejk0523.javavue.admin.login.vo.In;
|
||||
import com.leejk0523.javavue.admin.login.vo.Out;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class UserLoginServiceImpl implements UserLoginService {
|
||||
private final UserLoginDao userLoginDAO;
|
||||
|
||||
@Override
|
||||
public Out login(In in) {
|
||||
var member = userLoginDAO.findByMemberId(in);
|
||||
var menuList = getMenuList(member.getMemberId());
|
||||
var permitApiList = userLoginDAO.findAllPermitApiByAdminId(member.getMemberId());
|
||||
|
||||
return Out.builder()
|
||||
.memberNo(member.getMemberNo())
|
||||
.memberName(member.getMemberName())
|
||||
.menuList(menuList)
|
||||
.permitApiList(permitApiList)
|
||||
.authenticated(true)
|
||||
.build();
|
||||
}
|
||||
|
||||
private List<Out.Menu> getMenuList(String adminId) {
|
||||
final var menuList = userLoginDAO.findAllMenuByAdminId(adminId);
|
||||
final var root = menuList.stream()
|
||||
.filter(menu -> menu.getMenuDepth().equals(1))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
for (var parent : root) {
|
||||
nestedMenuList(menuList, parent);
|
||||
}
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
private void nestedMenuList(List<Out.Menu> list, Out.Menu parent) {
|
||||
final var children = list.stream()
|
||||
.filter(child -> Objects.nonNull(child.getUpMenuId())
|
||||
&& child.getUpMenuId().equals(parent.getMenuId()))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
parent.setChildren(children.isEmpty() ? null : children);
|
||||
|
||||
for (var child : children) {
|
||||
nestedMenuList(list, child);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.leejk0523.javavue.admin.login.vo;
|
||||
|
||||
import com.leejk0523.javavue.model.AsaAdminMember;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class AdminMember implements Member {
|
||||
private AsaAdminMember member;
|
||||
private Long memberNo;
|
||||
private String memberId;
|
||||
private String memberName;
|
||||
private String memberPassword;
|
||||
private String orgzId;
|
||||
private Type type;
|
||||
private Boolean memberEnabled;
|
||||
private Boolean memberLocked;
|
||||
private Integer memberFailureCount;
|
||||
private String plainPassword;
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.leejk0523.javavue.admin.login.vo;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class In implements Serializable {
|
||||
private String memberId;
|
||||
private String password;
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.leejk0523.javavue.admin.login.vo;
|
||||
|
||||
public interface Member {
|
||||
String getMemberName();
|
||||
Long getMemberNo();
|
||||
String getMemberId();
|
||||
String getMemberPassword();
|
||||
Type getType();
|
||||
Boolean getMemberEnabled();
|
||||
Boolean getMemberLocked();
|
||||
Integer getMemberFailureCount();
|
||||
void setPlainPassword(String plainPassword);
|
||||
String getPlainPassword();
|
||||
String getOrgzId();
|
||||
|
||||
enum Type {
|
||||
USER,
|
||||
ADMIN
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
package com.leejk0523.javavue.admin.login.vo;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.leejk0523.javavue.model.AsaMenu;
|
||||
import com.leejk0523.javavue.model.AsaRole;
|
||||
import lombok.*;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class Out implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@JsonIgnore
|
||||
private Long memberNo;
|
||||
|
||||
@JsonIgnore
|
||||
private String memberId;
|
||||
|
||||
@JsonIgnore
|
||||
private String orgzId;
|
||||
|
||||
@JsonIgnore
|
||||
private List<AsaRole> roles;
|
||||
|
||||
@JsonIgnore
|
||||
private List<String> orgList;
|
||||
|
||||
@JsonIgnore
|
||||
private String accessIpAddress;
|
||||
|
||||
private String memberName;
|
||||
|
||||
private List<Menu> menuList;
|
||||
private List<PermitApi> permitApiList;
|
||||
|
||||
private boolean authenticated;
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
public static class Menu implements Serializable{
|
||||
private static final long serialVersionUID = -6699279565175110630L;
|
||||
|
||||
private String menuId;
|
||||
private String upMenuId;
|
||||
private Integer menuDepth;
|
||||
private String menuName;
|
||||
private AsaMenu.Type menuType;
|
||||
private String menuUrl;
|
||||
|
||||
private List<Menu> children;
|
||||
}
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
public static class PermitApi implements Serializable{
|
||||
private static final long serialVersionUID = 385854228342672220L;
|
||||
private String menuUrl;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.leejk0523.javavue.admin.site.controller;
|
||||
|
||||
import com.leejk0523.javavue.model.AsaSite;
|
||||
import com.leejk0523.javavue.admin.site.service.AdminSiteService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
public class AdminSiteController {
|
||||
private final AdminSiteService adminSiteService;
|
||||
|
||||
@GetMapping("/api/admin/sys/site/siteList")
|
||||
public ResponseEntity<List<AsaSite>> siteAllList() {
|
||||
final var results = adminSiteService.SiteAllList();
|
||||
return ResponseEntity.ok(results);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.leejk0523.javavue.admin.site.dao;
|
||||
|
||||
import com.leejk0523.javavue.model.AsaSite;
|
||||
import com.leejk0523.javavue.model.QAsaSite;
|
||||
import org.springframework.data.jpa.repository.support.QuerydslRepositorySupport;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Repository
|
||||
public class AdminSiteDao extends QuerydslRepositorySupport {
|
||||
public AdminSiteDao() {
|
||||
super(AsaSite.class);
|
||||
}
|
||||
|
||||
public List<AsaSite> SiteAllList() {
|
||||
QAsaSite asaSite = QAsaSite.asaSite;
|
||||
|
||||
return from(asaSite)
|
||||
.fetch();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.leejk0523.javavue.admin.site.dao;
|
||||
|
||||
import com.leejk0523.javavue.model.AsaSite;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Repository
|
||||
public interface AdminSiteRepository extends JpaRepository<AsaSite, String> {
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.leejk0523.javavue.admin.site.service;
|
||||
|
||||
import com.leejk0523.javavue.model.AsaSite;
|
||||
import java.util.List;
|
||||
|
||||
public interface AdminSiteService {
|
||||
List<AsaSite> SiteAllList();
|
||||
List<AsaSite> findAll();
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.leejk0523.javavue.admin.site.service;
|
||||
|
||||
import com.leejk0523.javavue.admin.site.dao.AdminSiteRepository;
|
||||
import com.leejk0523.javavue.model.AsaSite;
|
||||
import com.leejk0523.javavue.admin.site.dao.AdminSiteDao;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class AdminSiteServiceImpl implements AdminSiteService {
|
||||
private final AdminSiteDao adminSiteDao;
|
||||
private final AdminSiteRepository adminSiteRepository;
|
||||
|
||||
@Override
|
||||
public List<AsaSite> SiteAllList() {
|
||||
return adminSiteDao.SiteAllList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AsaSite> findAll() {
|
||||
return adminSiteRepository.findAll();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package com.leejk0523.javavue.code.dao;
|
||||
|
||||
import com.leejk0523.javavue.common.GridCode;
|
||||
import com.leejk0523.javavue.model.ComCd;
|
||||
import com.leejk0523.javavue.model.QAsaSite;
|
||||
import com.leejk0523.javavue.model.QIstInst;
|
||||
import com.querydsl.core.types.Projections;
|
||||
import org.springframework.data.jpa.repository.support.QuerydslRepositorySupport;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
public class CodeDAO extends QuerydslRepositorySupport {
|
||||
public CodeDAO() {
|
||||
super(ComCd.class);
|
||||
}
|
||||
|
||||
public List<GridCode> findSiteCodeList() {
|
||||
final var site = QAsaSite.asaSite;
|
||||
|
||||
return from(site)
|
||||
.select(
|
||||
Projections.bean(
|
||||
GridCode.class,
|
||||
site.siteId.as("value"),
|
||||
site.siteName.as("text"),
|
||||
site.siteName.as("label")
|
||||
)
|
||||
)
|
||||
.fetch();
|
||||
}
|
||||
|
||||
public List<GridCode> findInstCodeList() {
|
||||
final var inst = QIstInst.istInst;
|
||||
|
||||
return from(inst)
|
||||
.select(
|
||||
Projections.bean(
|
||||
GridCode.class,
|
||||
inst.instNo.as("value"),
|
||||
inst.instNm.as("label"),
|
||||
inst.instNm.as("text")
|
||||
)
|
||||
)
|
||||
.fetch();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.leejk0523.javavue.code.service;
|
||||
|
||||
import com.leejk0523.javavue.common.GridCode;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface CodeService {
|
||||
List<GridCode> findSiteCodeList();
|
||||
List<GridCode> findInstCodeList();
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.leejk0523.javavue.code.service.impl;
|
||||
|
||||
import com.leejk0523.javavue.code.dao.CodeDAO;
|
||||
import com.leejk0523.javavue.code.service.CodeService;
|
||||
import com.leejk0523.javavue.common.GridCode;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Service("lasp.codeServiceImpl")
|
||||
@RequiredArgsConstructor
|
||||
public class CodeServiceImpl implements CodeService {
|
||||
private final CodeDAO codeDAO;
|
||||
|
||||
@Override
|
||||
public List<GridCode> findSiteCodeList() {
|
||||
return codeDAO.findSiteCodeList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<GridCode> findInstCodeList() {
|
||||
return codeDAO.findInstCodeList();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.leejk0523.javavue.code.web;
|
||||
|
||||
import com.leejk0523.javavue.code.service.CodeService;
|
||||
import com.leejk0523.javavue.common.GridCode;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
public class CodeController {
|
||||
|
||||
private final CodeService codeService;
|
||||
|
||||
@GetMapping("/api/admin/code/siteList")
|
||||
public ResponseEntity<List<GridCode>> siteCodeList() {
|
||||
final var results = codeService.findSiteCodeList();
|
||||
return ResponseEntity.ok(results);
|
||||
}
|
||||
|
||||
@GetMapping("/api/admin/code/instList")
|
||||
public ResponseEntity<List<GridCode>> instCodeList() {
|
||||
final var results = codeService.findInstCodeList();
|
||||
return ResponseEntity.ok(results);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.leejk0523.javavue.common;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class GridCode {
|
||||
private String label;
|
||||
private String text;
|
||||
private String value;
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package com.leejk0523.javavue.common;
|
||||
|
||||
public interface PagingQuery {
|
||||
int getPage();
|
||||
int getSize();
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.leejk0523.javavue.common;
|
||||
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
|
||||
public class QueryDSLUtils {
|
||||
public static Pageable getPageable(PagingQuery query) {
|
||||
return PageRequest.of(query.getPage() - 1, query.getSize());
|
||||
}
|
||||
|
||||
public static long getOffset(PagingQuery query) {
|
||||
return (long) (query.getPage() - 1) * query.getSize();
|
||||
}
|
||||
|
||||
public static long getLimit(PagingQuery query) {
|
||||
return query.getSize();
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
package com.leejk0523.javavue.config;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.web.servlet.config.annotation.CorsRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
|
||||
@Configuration
|
||||
public class WebConfig {
|
||||
// @Bean
|
||||
// public WebMvcConfigurer corsConfigurer() {
|
||||
// return new WebMvcConfigurer() {
|
||||
// @Override
|
||||
// public void addCorsMappings(@Nullable CorsRegistry registry) {
|
||||
// if (registry != null) {
|
||||
// registry.addMapping("/api/**")
|
||||
// .allowedOrigins("http://localhost:8080")
|
||||
// .allowedMethods("GET", "POST", "PUT", "DELETE")
|
||||
// .allowedHeaders("*")
|
||||
// .allowCredentials(true);
|
||||
// }
|
||||
// }
|
||||
// };
|
||||
// }
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
package com.leejk0523.javavue.controller;
|
||||
|
||||
import com.leejk0523.javavue.entity.UserProfile;
|
||||
import com.leejk0523.javavue.repository.UserProfileRepository;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api")
|
||||
public class UserProfileController {
|
||||
|
||||
@Autowired
|
||||
private UserProfileRepository userProfileRepository;
|
||||
|
||||
@GetMapping("")
|
||||
public String test() {
|
||||
return "Hello World!";
|
||||
}
|
||||
|
||||
@GetMapping("/all")
|
||||
public List<UserProfile> getAllUsers() {
|
||||
|
||||
return userProfileRepository.findAll();
|
||||
}
|
||||
|
||||
// 특정 ID로 사용자 조회
|
||||
@GetMapping("/{id}")
|
||||
public UserProfile getUserById(@PathVariable String id) {
|
||||
|
||||
return userProfileRepository.findById(id)
|
||||
.orElseThrow(() -> new RuntimeException("사용자를 찾을 수 없습니다."));
|
||||
}
|
||||
|
||||
// 이름으로 사용자 조회
|
||||
@GetMapping("/name/{name}")
|
||||
public List<UserProfile> getUsersByName(@PathVariable String name) {
|
||||
|
||||
return userProfileRepository.findByName(name);
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
public UserProfile createUser(@RequestBody UserProfile user) {
|
||||
|
||||
return userProfileRepository.save(user);
|
||||
}
|
||||
|
||||
@PutMapping("/{id}")
|
||||
public UserProfile updateUser(@PathVariable String id, @RequestBody UserProfile userDetails) {
|
||||
UserProfile userProfile = userProfileRepository.findById(id).orElseThrow();
|
||||
userProfile.setName(userDetails.getName());
|
||||
userProfile.setPhone(userDetails.getPhone());
|
||||
userProfile.setAddress(userDetails.getAddress());
|
||||
|
||||
return userProfileRepository.save(userProfile);
|
||||
}
|
||||
|
||||
@DeleteMapping("/{id}")
|
||||
public void deleteUser(@PathVariable String id) {
|
||||
|
||||
userProfileRepository.deleteById(id);
|
||||
}
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
package com.leejk0523.javavue.entity;
|
||||
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.Table;
|
||||
|
||||
@Entity
|
||||
@Table(name = "UserProfile") // 테이블 이름을 명시적으로 설정
|
||||
public class UserProfile {
|
||||
@Id
|
||||
@Column(name = "id", length = 100)
|
||||
private String id;
|
||||
|
||||
@Column(name = "name", length = 100)
|
||||
private String name;
|
||||
|
||||
@Column(name = "phone", length = 100)
|
||||
private String phone;
|
||||
|
||||
@Column(name = "address", length = 100)
|
||||
private String address;
|
||||
|
||||
@Column(name = "filepath", length = 100)
|
||||
private String filepath;
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getPhone() {
|
||||
return phone;
|
||||
}
|
||||
|
||||
public void setPhone(String phone) {
|
||||
this.phone = phone;
|
||||
}
|
||||
|
||||
public String getAddress() {
|
||||
return address;
|
||||
}
|
||||
|
||||
public void setAddress(String address) {
|
||||
this.address = address;
|
||||
}
|
||||
|
||||
public String getFilepath() {
|
||||
return filepath;
|
||||
}
|
||||
|
||||
public void setFilepath(String filepath) {
|
||||
this.filepath = filepath;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,170 @@
|
||||
package com.leejk0523.javavue.model;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import io.micrometer.common.util.StringUtils;
|
||||
import jakarta.persistence.*;
|
||||
import jakarta.validation.constraints.*;
|
||||
import lombok.*;
|
||||
import org.hibernate.annotations.ColumnTransformer;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Entity
|
||||
@Table(name = "asa_admin_member")
|
||||
public class AsaAdminMember {
|
||||
|
||||
@Id
|
||||
@Size(max = 50)
|
||||
@Column(name = "ADMIN_ID", nullable = false, length = 50)
|
||||
private String adminId;
|
||||
|
||||
@JsonIgnore
|
||||
@Size(max = 200)
|
||||
@NotNull
|
||||
@Column(name = "ADMIN_PASSWORD", nullable = false, length = 200)
|
||||
private String adminPassword;
|
||||
|
||||
@Size(max = 200)
|
||||
@Column(name = "ADMIN_NAME", length = 200)
|
||||
private String adminName;
|
||||
|
||||
@Size(max = 10)
|
||||
@Column(name = "ADMIN_SEX", length = 10)
|
||||
private String adminSex;
|
||||
|
||||
@Size(max = 200)
|
||||
@Column(name = "ADMIN_EMAIL", length = 200)
|
||||
private String adminEmail;
|
||||
|
||||
@Size(max = 100)
|
||||
@Column(name = "ADMIN_TEL1", length = 100)
|
||||
private String adminTel1;
|
||||
|
||||
@Size(max = 100)
|
||||
@Column(name = "ADMIN_TEL2", length = 100)
|
||||
private String adminTel2;
|
||||
|
||||
@Size(max = 100)
|
||||
@Column(name = "ADMIN_TEL3", length = 100)
|
||||
private String adminTel3;
|
||||
|
||||
@Size(max = 100)
|
||||
@Column(name = "ADMIN_MOBILE1", length = 100)
|
||||
private String adminMobile1;
|
||||
|
||||
@Size(max = 100)
|
||||
@Column(name = "ADMIN_MOBILE2", length = 100)
|
||||
private String adminMobile2;
|
||||
|
||||
@Size(max = 100)
|
||||
@Column(name = "ADMIN_MOBILE3", length = 100)
|
||||
private String adminMobile3;
|
||||
|
||||
@Size(max = 50)
|
||||
@Column(name = "ADMIN_FAX", length = 50)
|
||||
private String adminFax;
|
||||
|
||||
@Size(max = 100)
|
||||
@Column(name = "ADMIN_ZIPCODE", length = 100)
|
||||
private String adminZipcode;
|
||||
|
||||
@Size(max = 200)
|
||||
@Column(name = "ADMIN_ADDRESS", length = 200)
|
||||
private String adminAddress;
|
||||
|
||||
@Size(max = 200)
|
||||
@Column(name = "ADMIN_ADDRESS_DETAIL", length = 200)
|
||||
private String adminAddressDetail;
|
||||
|
||||
@Column(name = "ADMIN_REGDATE")
|
||||
private LocalDateTime adminRegdate;
|
||||
|
||||
@Column(name = "ADMIN_LOGIN_LAST_DATE")
|
||||
private LocalDateTime adminLoginLastDate;
|
||||
|
||||
@Column(name = "ADMIN_PW_LAST_UPDATE")
|
||||
private LocalDateTime adminPwLastUpdate;
|
||||
|
||||
@Size(max = 100)
|
||||
@Deprecated
|
||||
@Column(name = "ADMIN_ORGANIZATION", length = 100)
|
||||
private String adminOrganization;
|
||||
|
||||
@Size(max = 100)
|
||||
@Deprecated
|
||||
@Column(name = "ADMIN_DEPARTMENT", length = 100)
|
||||
private String adminDepartment;
|
||||
|
||||
@Size(max = 100)
|
||||
@Deprecated
|
||||
@Column(name = "ADMIN_TEAM", length = 100)
|
||||
private String adminTeam;
|
||||
|
||||
@Size(max = 100)
|
||||
@Deprecated
|
||||
@Column(name = "ADMIN_POSITION", length = 100)
|
||||
private String adminPosition;
|
||||
|
||||
@Size(max = 200)
|
||||
@Column(name = "ADMIN_ROLE", length = 200)
|
||||
private String adminRole;
|
||||
|
||||
@Size(max = 50)
|
||||
@Deprecated
|
||||
@Column(name = "ADMIN_MANAGEMENT_LEVEL", length = 50)
|
||||
private String adminManagementLevel;
|
||||
|
||||
@Column(name = "ADMIN_LOGIN_FAIL_COUNT")
|
||||
private Integer adminLoginFailCount;
|
||||
|
||||
@Column(name = "ADMIN_LOGIN_FAIL_DATE")
|
||||
private LocalDateTime adminLoginFailDate;
|
||||
|
||||
@NotNull
|
||||
@Column(name = "ADMIN_ACTIVE", nullable = false)
|
||||
private Boolean adminActive;
|
||||
|
||||
@Column(name = "ADMIN_LOCK")
|
||||
private Boolean adminLock;
|
||||
|
||||
@Column(name = "ADMIN_LONG_TERM")
|
||||
private Boolean adminLongTerm;
|
||||
|
||||
@Column(name = "SITE_ID", length = 20, nullable = false)
|
||||
private String siteId;
|
||||
|
||||
@Column(name = "ORG_ID", length = 36)
|
||||
private String orgId;
|
||||
|
||||
@Size(max = 100)
|
||||
@Column(name = "ADMIN_TEL", length = 100)
|
||||
private String adminTel;
|
||||
|
||||
@Size(max = 100)
|
||||
@Column(name = "ADMIN_MOBILE", length = 100)
|
||||
private String adminMobile;
|
||||
|
||||
public String getAdminTel() {
|
||||
if (StringUtils.isNotBlank(this.getAdminTel1())
|
||||
&& StringUtils.isNotBlank(this.getAdminTel2())
|
||||
&& StringUtils.isNotBlank(this.getAdminTel3())) {
|
||||
return this.getAdminTel1() + "-" + this.getAdminTel2() + "-" + this.getAdminTel3();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public String getAdminMobile() {
|
||||
if (StringUtils.isNotBlank(this.getAdminMobile1())
|
||||
&& StringUtils.isNotBlank(this.getAdminMobile2())
|
||||
&& StringUtils.isNotBlank(this.getAdminMobile3())) {
|
||||
return this.getAdminMobile1() + "-" + this.getAdminMobile2() + "-" + this.getAdminMobile3();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package com.leejk0523.javavue.model;
|
||||
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import java.io.Serializable;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Entity
|
||||
@Table(name = "asa_admin_site_role_rel")
|
||||
@IdClass(AsaAdminSiteRoleRel.Key.class)
|
||||
public class AsaAdminSiteRoleRel {
|
||||
|
||||
@Id
|
||||
@Size(max = 50)
|
||||
@NotNull
|
||||
@Column(name = "ADMIN_ID", nullable = false, length = 50)
|
||||
private String adminId;
|
||||
|
||||
@Id
|
||||
@Size(max = 20)
|
||||
@NotNull
|
||||
@Column(name = "SITE_ID", nullable = false, length = 20)
|
||||
private String siteId;
|
||||
|
||||
@Id
|
||||
@Size(max = 500)
|
||||
@Column(name = "ROLE_CODE", length = 100)
|
||||
private String roleCode;
|
||||
|
||||
@Data
|
||||
public static class Key implements Serializable {
|
||||
private String adminId;
|
||||
private String siteId;
|
||||
private String roleCode;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package com.leejk0523.javavue.model;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Entity
|
||||
@Table(name = "ASA_CONTENT")
|
||||
public class AsaContent {
|
||||
|
||||
@Id
|
||||
@SequenceGenerator(name = "SQ_ASA_CONTENT", sequenceName = "SQ_ASA_CONTENT", allocationSize = 1)
|
||||
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SQ_ASA_CONTENT")
|
||||
@Column(name = "CONTENT_ID", nullable = false)
|
||||
private Integer contentId;
|
||||
|
||||
@Column(name = "ORG_ID", length = 36)
|
||||
private String orgId;
|
||||
|
||||
@Size(max = 500)
|
||||
@Column(name = "CONTENT_TITLE", length = 500)
|
||||
private String contentTitle;
|
||||
|
||||
@Lob
|
||||
@Column(name = "CONTENTS")
|
||||
private String contents;
|
||||
|
||||
@Size(max = 4000)
|
||||
@Column(name = "CONTENT_PLAIN", length = 4000)
|
||||
private String contentPlain;
|
||||
|
||||
@Column(name = "USE_YN", length = 1, nullable = false)
|
||||
private String useYn;
|
||||
|
||||
@Column(name = "DEL_YN", length = 1, nullable = false)
|
||||
private String delYn;
|
||||
|
||||
@Column(name = "FRST_RGTR_ID", length = 50, nullable = false)
|
||||
private String frstRgtrId;
|
||||
|
||||
@Column(name = "FRST_REG_DT", nullable = false)
|
||||
private LocalDateTime frstRegDt;
|
||||
|
||||
@Column(name = "LAST_MDFR_ID", length = 50)
|
||||
private String lastMdfrId;
|
||||
|
||||
@Column(name = "LAST_MDFCN_DT")
|
||||
private LocalDateTime lastMdfcnDt;
|
||||
}
|
||||
126
java/src/main/java/com/leejk0523/javavue/model/AsaMenu.java
Normal file
126
java/src/main/java/com/leejk0523/javavue/model/AsaMenu.java
Normal file
@@ -0,0 +1,126 @@
|
||||
package com.leejk0523.javavue.model;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import lombok.*;
|
||||
import org.hibernate.annotations.GenericGenerator;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Entity
|
||||
@Table(name = "asa_menu")
|
||||
public class AsaMenu {
|
||||
|
||||
@Id
|
||||
@Size(max = 100)
|
||||
@GenericGenerator(name = "uuid", strategy = "org.hibernate.id.UUIDGenerator")
|
||||
@GeneratedValue(generator = "uuid")
|
||||
@Column(name = "menu_id", length = 100, nullable = false)
|
||||
private String menuId;
|
||||
|
||||
@Column(name = "site_id", length = 30, nullable = false)
|
||||
private String siteId;
|
||||
|
||||
@Size(max = 100)
|
||||
@Column(name = "up_menu_id", length = 100)
|
||||
private String upMenuId;
|
||||
|
||||
@Column(name = "menu_depth", nullable = false)
|
||||
private Integer menuDepth;
|
||||
|
||||
@Column(name = "menu_order", nullable = false)
|
||||
private Integer menuOrder;
|
||||
|
||||
@Size(max = 200)
|
||||
@Column(name = "menu_name", length = 200, nullable = false)
|
||||
private String menuName;
|
||||
|
||||
@Enumerated(EnumType.STRING)
|
||||
@Column(name = "menu_type", length = 20, nullable = false)
|
||||
private Type menuType;
|
||||
|
||||
@Enumerated(EnumType.STRING)
|
||||
@Column(name = "menu_feature", length = 20, nullable = false)
|
||||
private Feature menuFeature;
|
||||
|
||||
@Column(name = "menu_layout", length = 50)
|
||||
private String menuLayout;
|
||||
|
||||
@Column(name = "menu_url", length = 200)
|
||||
private String menuUrl;
|
||||
|
||||
@Column(name = "menu_method", length = 200)
|
||||
private String menuMethod;
|
||||
|
||||
@Column(name = "menu_description", length = 1000)
|
||||
private String menuDescription;
|
||||
|
||||
@Enumerated(EnumType.STRING)
|
||||
@Column(name = "menu_link_target", length = 20, nullable = false)
|
||||
private Target menuLinkTarget;
|
||||
|
||||
@Column(name = "menu_use_satisfaction", nullable = false)
|
||||
private Boolean menuUseSatisfaction;
|
||||
|
||||
@Column(name = "menu_use_mng_info", nullable = false)
|
||||
private Boolean menuUseMngInfo;
|
||||
|
||||
@Column(name = "menu_mng_id", length = 50)
|
||||
private String menuMngId;
|
||||
|
||||
@Enumerated(EnumType.STRING)
|
||||
@Column(name = "menu_status", length = 20, nullable = false)
|
||||
private Status menuStatus;
|
||||
|
||||
@Column(name = "menu_reg_date", nullable = false)
|
||||
private LocalDateTime menuRegDate;
|
||||
|
||||
@Column(name = "menu_reg_id", length = 50, nullable = false)
|
||||
private String menuRegId;
|
||||
|
||||
@Column(name = "menu_upd_date")
|
||||
private LocalDateTime menuUpdDate;
|
||||
|
||||
@Column(name = "menu_upd_id", length = 50)
|
||||
private String menuUpdId;
|
||||
|
||||
@Transient
|
||||
@JsonProperty("_children")
|
||||
private List<AsaMenu> children;
|
||||
|
||||
@Getter
|
||||
public enum Type {
|
||||
MENU,
|
||||
PAGE,
|
||||
API,
|
||||
TAB
|
||||
|
||||
}
|
||||
|
||||
@Getter
|
||||
public enum Feature {
|
||||
PAGE,
|
||||
LIST,
|
||||
DETAIL,
|
||||
CREATE,
|
||||
UPDATE,
|
||||
DELETE
|
||||
}
|
||||
|
||||
public enum Target {
|
||||
CURRENT,
|
||||
BLANK
|
||||
}
|
||||
|
||||
public enum Status {
|
||||
ENABLED,
|
||||
HIDDEN,
|
||||
DISABLED,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package com.leejk0523.javavue.model;
|
||||
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import java.io.Serializable;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Entity
|
||||
@Table(name = "ASA_PERMISSION")
|
||||
@IdClass(AsaPermission.Key.class)
|
||||
public class AsaPermission {
|
||||
|
||||
@Id
|
||||
@Size(max = 100)
|
||||
@NotNull
|
||||
@Column(name = "ROLE_CODE", nullable = false, length = 100)
|
||||
private String roleCode;
|
||||
|
||||
@Id
|
||||
@Size(max = 100)
|
||||
@Column(name = "MENU_ID", length = 100, nullable = false)
|
||||
private String menuId;
|
||||
|
||||
@Id
|
||||
@Size(max = 20)
|
||||
@NotNull
|
||||
@Column(name = "SITE_ID", nullable = false, length = 20)
|
||||
private String siteId;
|
||||
|
||||
@Data
|
||||
public static class Key implements Serializable {
|
||||
private String roleCode;
|
||||
private String menuId;
|
||||
private String siteId;
|
||||
}
|
||||
}
|
||||
61
java/src/main/java/com/leejk0523/javavue/model/AsaRole.java
Normal file
61
java/src/main/java/com/leejk0523/javavue/model/AsaRole.java
Normal file
@@ -0,0 +1,61 @@
|
||||
package com.leejk0523.javavue.model;
|
||||
|
||||
import jakarta.validation.constraints.Size;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
@Entity
|
||||
@Table(name = "asa_role")
|
||||
@IdClass(AsaRole.Key.class)
|
||||
public class AsaRole implements Serializable {
|
||||
private static final long serialVersionUID = 690922257948242364L;
|
||||
|
||||
@Id
|
||||
@Size(max = 100)
|
||||
@Column(name = "ROLE_CODE", nullable = false, length = 100)
|
||||
private String roleCode;
|
||||
|
||||
@Id
|
||||
@Size(max = 20)
|
||||
@Column(name = "SITE_ID", nullable = false, length = 20)
|
||||
private String siteId;
|
||||
|
||||
@Size(max = 100)
|
||||
@Column(name = "ROLE_NAME", length = 100)
|
||||
private String roleName;
|
||||
|
||||
@Size(max = 1000)
|
||||
@Column(name = "ROLE_DESCRIPTION", length = 1000)
|
||||
private String roleDescription;
|
||||
|
||||
@Column(name = "ROLE_REGDATE")
|
||||
private LocalDateTime roleRegdate;
|
||||
|
||||
@Column(name = "ROLE_DEFAULT")
|
||||
private Integer roleDefault;
|
||||
|
||||
@Column(name = "ROLE_ADMIN")
|
||||
private Integer roleAdmin;
|
||||
|
||||
@Column(name = "ROLE_JOIN")
|
||||
private Integer roleJoin;
|
||||
|
||||
@Data
|
||||
public static class Key implements Serializable {
|
||||
private static final long serialVersionUID = 1745833326981056763L;
|
||||
|
||||
private String roleCode;
|
||||
private String siteId;
|
||||
}
|
||||
|
||||
}
|
||||
72
java/src/main/java/com/leejk0523/javavue/model/AsaSite.java
Normal file
72
java/src/main/java/com/leejk0523/javavue/model/AsaSite.java
Normal file
@@ -0,0 +1,72 @@
|
||||
package com.leejk0523.javavue.model;
|
||||
|
||||
import lombok.*;
|
||||
import jakarta.persistence.*;
|
||||
import java.time.LocalDateTime;
|
||||
import jakarta.validation.constraints.*;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Entity
|
||||
@Table(name = "asa_site")
|
||||
public class AsaSite {
|
||||
|
||||
@Id
|
||||
@Size(max = 20)
|
||||
@Column(name = "SITE_ID", length = 20)
|
||||
private String siteId;
|
||||
|
||||
@Size(max = 200)
|
||||
@Column(name = "SITE_NAME", length = 200)
|
||||
private String siteName;
|
||||
|
||||
@Size(max = 1000)
|
||||
@Column(name = "SITE_DESCRIPTION", length = 1000)
|
||||
private String siteDescription;
|
||||
|
||||
@Size(max = 500)
|
||||
@Column(name = "SITE_DOMAIN", length = 500)
|
||||
private String siteDomain;
|
||||
|
||||
@Enumerated(EnumType.STRING)
|
||||
@Column(name = "SITE_TYPE", length = 50)
|
||||
private Type siteType;
|
||||
|
||||
@Size(max = 20)
|
||||
@Column(name = "site_prefix", length = 20)
|
||||
private String sitePrefix;
|
||||
|
||||
@Size(max = 11)
|
||||
@Column(name = "SITE_MAIN", length = 11)
|
||||
private long siteMain;
|
||||
|
||||
@Size(max = 20)
|
||||
@Column(name = "SITE_LOCALE", length = 20)
|
||||
private String siteLocale;
|
||||
|
||||
@Size(max = 11)
|
||||
@Column(name = "SITE_LOGO", length = 11)
|
||||
private Integer siteLogo;
|
||||
|
||||
@Column(name = "SITE_REGDATE")
|
||||
private LocalDateTime siteRegdate;
|
||||
|
||||
@Size(max = 50)
|
||||
@Column(name = "ORG_ID", length = 50)
|
||||
private String orgId;
|
||||
|
||||
@Size(max = 200)
|
||||
@Column(name = "BSC_URL", length = 200)
|
||||
private String bscUrl;
|
||||
|
||||
@Size(max = 200)
|
||||
@Column(name = "LGN_URL", length = 200)
|
||||
private String lgnUrl;
|
||||
|
||||
public enum Type {
|
||||
ADMIN,
|
||||
USER
|
||||
}
|
||||
}
|
||||
110
java/src/main/java/com/leejk0523/javavue/model/ComCd.java
Normal file
110
java/src/main/java/com/leejk0523/javavue/model/ComCd.java
Normal file
@@ -0,0 +1,110 @@
|
||||
package com.leejk0523.javavue.model;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
@Entity
|
||||
@Table(name = "com_cd")
|
||||
@IdClass(ComCd.Key.class)
|
||||
public class ComCd {
|
||||
@Id
|
||||
@NotNull
|
||||
@Size(max = 20)
|
||||
@Column(name = "CD_GROUP_ID", nullable = false, length = 20)
|
||||
private String cdGroupId;
|
||||
|
||||
@Id
|
||||
@Size(max = 6)
|
||||
@NotNull
|
||||
@Column(name = "COM_CD", nullable = false, length = 6)
|
||||
private String comCd;
|
||||
|
||||
@Size(max = 100)
|
||||
@Column(name = "COM_CD_NM", length = 100)
|
||||
private String comCdNm;
|
||||
|
||||
@Size(max = 2000)
|
||||
@Column(name = "COM_CD_EXPLN", length = 2000)
|
||||
private String comCdExpln;
|
||||
|
||||
@Column(name = "SORT_SEQ", nullable = false)
|
||||
private Integer sortSeq;
|
||||
|
||||
@Column(name = "USE_YN", length = 1, nullable = false)
|
||||
private String useYn;
|
||||
|
||||
@Column(name = "DEL_YN", length = 1, nullable = false)
|
||||
private String delYn;
|
||||
|
||||
@Size(max = 20)
|
||||
@Column(name = "ARTCL_NM1", length = 20)
|
||||
private String artclNm1;
|
||||
|
||||
@Size(max = 20)
|
||||
@Column(name = "ARTCL_NM2", length = 20)
|
||||
private String artclNm2;
|
||||
|
||||
@Size(max = 20)
|
||||
@Column(name = "ARTCL_NM3", length = 20)
|
||||
private String artclNm3;
|
||||
|
||||
@Size(max = 20)
|
||||
@Column(name = "ARTCL_NM4", length = 20)
|
||||
private String artclNm4;
|
||||
|
||||
@Size(max = 20)
|
||||
@Column(name = "ARTCL_NM5", length = 20)
|
||||
private String artclNm5;
|
||||
|
||||
@Size(max = 20)
|
||||
@Column(name = "ARTCL_NM6", length = 20)
|
||||
private String artclNm6;
|
||||
|
||||
@Size(max = 20)
|
||||
@Column(name = "ARTCL_NM7", length = 20)
|
||||
private String artclNm7;
|
||||
|
||||
@Size(max = 20)
|
||||
@Column(name = "ARTCL_NM8", length = 20)
|
||||
private String artclNm8;
|
||||
|
||||
@Size(max = 20)
|
||||
@Column(name = "ARTCL_NM9", length = 20)
|
||||
private String artclNm9;
|
||||
|
||||
@Size(max = 20)
|
||||
@Column(name = "ARTCL_NM10", length = 20)
|
||||
private String artclNm10;
|
||||
|
||||
@Column(name = "FRST_RGTR_ID", length = 50, nullable = false)
|
||||
private String frstRgtrId;
|
||||
|
||||
@Column(name = "FRST_REG_DT", nullable = false)
|
||||
private LocalDateTime frstRegDt;
|
||||
|
||||
@Column(name = "LAST_MDFR_ID", length = 50)
|
||||
private String lastMdfrId;
|
||||
|
||||
@Column(name = "LAST_MDFCN_DT")
|
||||
private LocalDateTime lastMdfcnDt;
|
||||
|
||||
@Data
|
||||
public static class Key implements Serializable {
|
||||
private static final long serialVersionUID = -3281903370957728656L;
|
||||
private String cdGroupId;
|
||||
private String comCd;
|
||||
}
|
||||
|
||||
}
|
||||
52
java/src/main/java/com/leejk0523/javavue/model/IstInst.java
Normal file
52
java/src/main/java/com/leejk0523/javavue/model/IstInst.java
Normal file
@@ -0,0 +1,52 @@
|
||||
package com.leejk0523.javavue.model;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
@Entity
|
||||
@Table(name = "IST_INST")
|
||||
public class IstInst {
|
||||
|
||||
@Id
|
||||
@Column(name = "INST_NO", length = 10, nullable = false)
|
||||
private String instNo;
|
||||
|
||||
@Column(name = "INST_CLSF_CD", length = 6, nullable = false)
|
||||
private String instClsfCd;
|
||||
|
||||
@Column(name = "INST_NM", length = 200, nullable = false)
|
||||
private String instNm;
|
||||
|
||||
@Column(name = "INST_SRVC_EXPLN", length = 50)
|
||||
private String instSrvcExpln;
|
||||
|
||||
@Column(name = "INST_CN")
|
||||
private String instCn;
|
||||
|
||||
@Column(name = "ATCH_FILE_ID", length = 20)
|
||||
private String atchFileId;
|
||||
|
||||
@Column(name = "USE_YN", length = 1, nullable = false)
|
||||
private String useYn;
|
||||
|
||||
@Column(name = "FRST_RGTR_ID", length = 50, nullable = false)
|
||||
private String frstRgtrId;
|
||||
|
||||
@Column(name = "FRST_REG_DT", nullable = false)
|
||||
private LocalDateTime frstRegDt;
|
||||
|
||||
@Column(name = "LAST_MDFR_ID", length = 50)
|
||||
private String lastMdfrId;
|
||||
|
||||
@Column(name = "LAST_MDFCN_DT")
|
||||
private LocalDateTime lastMdfcnDt;
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
package com.leejk0523.javavue.repository;
|
||||
|
||||
import com.leejk0523.javavue.entity.UserProfile;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Repository
|
||||
public interface UserProfileRepository extends JpaRepository<UserProfile, String> {
|
||||
|
||||
// 이름으로 검색
|
||||
List<UserProfile> findByName(String name);
|
||||
|
||||
// 전화번호로 검색
|
||||
List<UserProfile> findByPhone(String phone);
|
||||
|
||||
// 주소에 특정 키워드가 포함된 사용자 검색
|
||||
List<UserProfile> findByAddressContaining(String keyword);
|
||||
|
||||
// 파일 경로가 특정 값과 일치하는 사용자 검색
|
||||
UserProfile findByFilepath(String filepath);
|
||||
}
|
||||
@@ -1,28 +1,22 @@
|
||||
spring.application.name=javavue
|
||||
|
||||
spring.datasource.url=jdbc:mariadb://leejk0523.com:3306/profile
|
||||
spring.datasource.url=jdbc:mariadb://leejk0523.com:3306/pub
|
||||
spring.datasource.username=leejk0523
|
||||
spring.datasource.password=Ghtkssk0325
|
||||
|
||||
|
||||
# none: ???? ???? ??? (???? DB?? ?????)
|
||||
# create-drop: SessionFactory? ??? ? drop? ??? ????, SessionFactory? ??? ? drop? ???? (in-memory DB? ?? ?????)
|
||||
# create: SessionFactory? ??? ? ?????? drop? ???? ??? DDL? ????
|
||||
# update: ??? ???? ????
|
||||
# validate: ??? ???? ??? ???? ???? ??????? ????
|
||||
spring.jpa.hibernate.ddl-auto=none
|
||||
|
||||
# DB? ??? ?? ??? ????
|
||||
spring.jpa.hibernate.ddl-auto=update
|
||||
spring.jpa.properties.hibernate.show-sql=true
|
||||
# SQL 출력
|
||||
#spring.jpa.show-sql=true
|
||||
|
||||
# ???? ??? ??? ??? ???
|
||||
# SQL 포맷팅
|
||||
spring.jpa.properties.hibernate.format_sql=true
|
||||
spring.jpa.properties.hibernate.type=trace
|
||||
|
||||
# ?? ?? ???? ?? ????
|
||||
logging.level.org.hibernate.type.descriptor.sql=DEBUG
|
||||
# 바인딩 파라미터 값 로깅
|
||||
logging.level.org.hibernate.type.descriptor.sql=TRACE
|
||||
|
||||
# ?? ?? ??
|
||||
# SQL에 바인딩된 파라미터 값도 출력
|
||||
logging.level.org.hibernate.SQL=DEBUG
|
||||
|
||||
#UserProfile? ???? ????? ???? ??? ??
|
||||
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
|
||||
116
nuxt/README.md
116
nuxt/README.md
@@ -1,75 +1,71 @@
|
||||
# Nuxt Minimal Starter
|
||||
### 기본 환경
|
||||
- vue 3.x(5.0.8)
|
||||
- node (v20.17.0)
|
||||
- vue-router(최신)
|
||||
- pinia(최신) - store
|
||||
- Nuxt(최신) - 프레임워크
|
||||
- antd 4.x - UI/UX
|
||||
- yarn (1.22.22)
|
||||
- 추후 환경은 변경될 수 있음
|
||||
|
||||
Look at the [Nuxt documentation](https://nuxt.com/docs/getting-started/introduction) to learn more.
|
||||
## 최초 세팅
|
||||
- terminal(혹은 command창): yarn install
|
||||
- 실행 시 yarn dev
|
||||
|
||||
## Setup
|
||||
## 개발 시 중요 사항
|
||||
- 모든 파일은 업무 기준으로 작성됨(예: 사용자 > user)
|
||||
- 공통사항으로 적용되는 경우 utils 사용할 것!
|
||||
- 모든 네이밍은 명확한 단어로 사용할 것!
|
||||
- 반드시 저장할 경우 Eslint, Prettier 적용
|
||||
|
||||
Make sure to install dependencies:
|
||||
## 공통 단어 주의사항
|
||||
- 비즈니스 로직은 공통이 아님(불허)
|
||||
- 공통은 언제든지 사용할 수 있는 라이브러리성을 말하는 것임
|
||||
|
||||
```bash
|
||||
# npm
|
||||
npm install
|
||||
## Commit 금지 파일 및 디렉토리
|
||||
- /node_modules/
|
||||
- 기타 IDE 환경 파일(.classpath 등등)
|
||||
|
||||
# pnpm
|
||||
pnpm install
|
||||
### 페이지 작성
|
||||
- pages/도메인/index.vue
|
||||
- 페이지는 controller와 같은 역할을 함
|
||||
- useHead를 이용하여 html head 영역을 설정함
|
||||
|
||||
# yarn
|
||||
yarn install
|
||||
### 페이지 내 컴포넌트
|
||||
- /src/components/도메인/컴포넌트명.vue
|
||||
|
||||
# bun
|
||||
bun install
|
||||
### store 작성 위치
|
||||
- 디렉토리: /src/stores/도메인/index.ts
|
||||
|
||||
### api 작성 위치
|
||||
- 디렉토리: /src/apis/도메인/index.ts
|
||||
|
||||
### Type 지정
|
||||
- type 및 interface로 타입을 지정하는 경우가 많음
|
||||
- 법률구조공단은 type으로 모든 객체의 타입을 지정하는 것을 원칙으로 함
|
||||
- 최대한 undefined를 사용하지 않는 선으로 개발할 것
|
||||
- 예로 userId: string의 경우 빈값을 표현할 때 userId: '' 형식으로 사용할 것!
|
||||
- 타입 import 시 아래와 같이 type을 지정해야 함
|
||||
```
|
||||
import type {UserItemType} from 'types'
|
||||
```
|
||||
|
||||
## Development Server
|
||||
|
||||
Start the development server on `http://localhost:3000`:
|
||||
### Toast UI Calendar
|
||||
```
|
||||
// ES MODULE
|
||||
import Calendar from '@toast-ui/calendar';
|
||||
|
||||
```bash
|
||||
# npm
|
||||
npm run dev
|
||||
|
||||
# pnpm
|
||||
pnpm dev
|
||||
|
||||
# yarn
|
||||
yarn dev
|
||||
|
||||
# bun
|
||||
bun run dev
|
||||
// CSS 적용
|
||||
import '@toast-ui/calendar/dist/toastui-calendar.min.css';
|
||||
```
|
||||
|
||||
## Production
|
||||
|
||||
Build the application for production:
|
||||
|
||||
```bash
|
||||
# npm
|
||||
npm run build
|
||||
|
||||
# pnpm
|
||||
pnpm build
|
||||
|
||||
# yarn
|
||||
yarn build
|
||||
|
||||
# bun
|
||||
bun run build
|
||||
### Toast UI Grid
|
||||
```
|
||||
// ES MODULE
|
||||
import 'tui-grid/dist/tui-grid.css';
|
||||
import 'tui-date-picker/dist/tui-date-picker.min.css';
|
||||
|
||||
Locally preview production build:
|
||||
|
||||
```bash
|
||||
# npm
|
||||
npm run preview
|
||||
|
||||
# pnpm
|
||||
pnpm preview
|
||||
|
||||
# yarn
|
||||
yarn preview
|
||||
|
||||
# bun
|
||||
bun run preview
|
||||
```
|
||||
|
||||
Check out the [deployment documentation](https://nuxt.com/docs/getting-started/deployment) for more information.
|
||||
// CSS 적용
|
||||
import Grid from 'tui-grid';
|
||||
```
|
||||
@@ -1,8 +1,4 @@
|
||||
<script setup lang="ts">
|
||||
// import 'ant-design-vue/dist/reset.css';
|
||||
// import '~/assets/font/PretendardGOV/font.css';
|
||||
// import '~/assets/css/index.css';
|
||||
// import 'dayjs/locale/ko';
|
||||
import 'uno.css';
|
||||
</script>
|
||||
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
<!-- DateSearch.vue -->
|
||||
<template>
|
||||
<div>
|
||||
<label for="start-date">시작 날짜:</label>
|
||||
<input type="date" v-model="startDate" id="start-date" />
|
||||
|
||||
<label for="end-date">종료 날짜:</label>
|
||||
<input type="date" v-model="endDate" id="end-date" />
|
||||
|
||||
<button @click="searchData">검색</button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted, defineEmits } from 'vue';
|
||||
|
||||
const startDate = ref('');
|
||||
const endDate = ref('');
|
||||
const emit = defineEmits(['search']);
|
||||
const searchData = () => {
|
||||
emit('search', { startDate: startDate.value, endDate: endDate.value });
|
||||
};
|
||||
|
||||
const today = new Date();
|
||||
const tomorrow = new Date();
|
||||
tomorrow.setDate(today.getDate() + 1);
|
||||
startDate.value = formatDate(today);
|
||||
endDate.value = formatDate(tomorrow);
|
||||
|
||||
function formatDate(date) {
|
||||
return date.toISOString().split('T')[0];
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* 필요한 스타일 */
|
||||
</style>
|
||||
40
nuxt/components/common/DefaultSelectCode.vue
Normal file
40
nuxt/components/common/DefaultSelectCode.vue
Normal file
@@ -0,0 +1,40 @@
|
||||
<script setup lang="ts">
|
||||
import type { GridCodeType } from '~/types';
|
||||
|
||||
const value = defineModel<string>({ default: '' });
|
||||
|
||||
const props = defineProps<{
|
||||
options: GridCodeType[];
|
||||
className?: string;
|
||||
selectType?: 'SELECT' | 'ALL';
|
||||
isLoading?: boolean;
|
||||
}>();
|
||||
|
||||
const selectOptions = computed(() => {
|
||||
if (props.selectType === 'REQUIRED') {
|
||||
return [{ label: '선택', value: '' }, ...props.options];
|
||||
}
|
||||
|
||||
if (props.selectType === 'ALL') {
|
||||
return [{ label: '전체', value: '' }, ...props.options];
|
||||
}
|
||||
|
||||
return props.options;
|
||||
});
|
||||
|
||||
const emit = defineEmits(['change']);
|
||||
|
||||
const change = () => {
|
||||
emit('change');
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<a-select
|
||||
:class="className"
|
||||
:options="selectOptions"
|
||||
:loading="isLoading"
|
||||
v-model:value="value"
|
||||
@change="change"
|
||||
/>
|
||||
</template>
|
||||
29
nuxt/components/common/InstCodeSelect.vue
Normal file
29
nuxt/components/common/InstCodeSelect.vue
Normal file
@@ -0,0 +1,29 @@
|
||||
<script setup lang="ts">
|
||||
const props = defineProps<{
|
||||
className?: string;
|
||||
selectType?: 'SELECT' | 'ALL';
|
||||
}>();
|
||||
|
||||
const commonCodeStore = useCommonCodeStore();
|
||||
const value = defineModel<string>('');
|
||||
|
||||
const { data, isLoading } = useQuery({
|
||||
queryKey: ['INST_CODE_LIST'],
|
||||
queryFn: async () => {
|
||||
return await commonCodeStore.searchInstCodeList();
|
||||
},
|
||||
staleTime: 60 * 1000,
|
||||
refetchOnWindowFocus: false,
|
||||
refetchOnMount: false
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<common-default-select-code
|
||||
v-if="!isLoading"
|
||||
:class-name="className"
|
||||
:select-type="selectType"
|
||||
:options="data"
|
||||
v-model="value"
|
||||
/>
|
||||
</template>
|
||||
28
nuxt/components/common/PermitButton.vue
Normal file
28
nuxt/components/common/PermitButton.vue
Normal file
@@ -0,0 +1,28 @@
|
||||
<script setup lang="ts">
|
||||
import { useAuthStore } from '~/stores/login';
|
||||
import { some } from 'lodash-es';
|
||||
|
||||
const props = defineProps({
|
||||
api: {
|
||||
type: String,
|
||||
required: true
|
||||
}
|
||||
});
|
||||
|
||||
const authStore = useAuthStore();
|
||||
const { permitApiList } = storeToRefs(authStore);
|
||||
|
||||
const permit = computed(() => {
|
||||
return some(permitApiList.value, (value) => {
|
||||
return props.api === value.menuUrl;
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<template v-if="permit">
|
||||
<slot />
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
||||
32
nuxt/components/data/editor.vue
Normal file
32
nuxt/components/data/editor.vue
Normal file
@@ -0,0 +1,32 @@
|
||||
<script setup lang="ts">
|
||||
import { Editor } from '@toast-ui/editor';
|
||||
import '@toast-ui/editor/dist/toastui-editor.css';
|
||||
|
||||
const editorRef = ref();
|
||||
const instance = ref();
|
||||
const emit = defineEmits(['change']);
|
||||
const props = defineProps<{ initialValue: string }>();
|
||||
|
||||
onMounted(() => {
|
||||
instance.value = new Editor({
|
||||
el: editorRef.value,
|
||||
initialValue: props.initialValue ?? '',
|
||||
initialEditType: 'wysiwyg',
|
||||
hideModeSwitch: true,
|
||||
usageStatistics: false,
|
||||
events: {
|
||||
keyup: () => {
|
||||
if (instance.value) {
|
||||
emit('change', instance.value.getHTML());
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div ref="editorRef"></div>
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
||||
136
nuxt/components/data/grid.vue
Normal file
136
nuxt/components/data/grid.vue
Normal file
@@ -0,0 +1,136 @@
|
||||
<script setup lang="ts">
|
||||
import 'tui-grid/dist/tui-grid.css';
|
||||
import 'tui-date-picker/dist/tui-date-picker.min.css';
|
||||
import Grid, { type RowKey } from 'tui-grid';
|
||||
import { cloneDeep } from 'lodash-es';
|
||||
import type { DataGridType } from '~/types/data/grid';
|
||||
import type { GridEventName, OptRow } from 'tui-grid/types/options';
|
||||
import { TUI_GRID_THEME } from '~/constants/theme/grid';
|
||||
|
||||
Grid.setLanguage('ko', {
|
||||
display: {
|
||||
noData: '조회된 데이터가 존재하지 않습니다.'
|
||||
}
|
||||
});
|
||||
|
||||
Grid.applyTheme('default', TUI_GRID_THEME);
|
||||
|
||||
const gridRef = ref();
|
||||
const instance = ref<Grid>();
|
||||
|
||||
const props = defineProps<DataGridType>();
|
||||
|
||||
onMounted(() => {
|
||||
const gridOptions = {
|
||||
el: gridRef.value,
|
||||
columns: props.columns ?? [],
|
||||
data: cloneDeep(props.data) ?? [],
|
||||
bodyHeight: props.bodyHeight,
|
||||
columnOptions: props.columnOptions,
|
||||
keyColumnName: props.keyColumnName,
|
||||
width: props.width,
|
||||
heightResizable: props.heightResizable,
|
||||
minBodyHeight: props.minBodyHeight,
|
||||
rowHeight: props.rowHeight ?? 40,
|
||||
minRowHeight: props.minRowHeight,
|
||||
scrollX: props.scrollX,
|
||||
scrollY: props.scrollY,
|
||||
editingEvent: props.editingEvent,
|
||||
tabMode: props.tabMode,
|
||||
rowHeaders: props.rowHeaders,
|
||||
summary: props.summary,
|
||||
useClientSort: props.useClientSort,
|
||||
selectionUnit: props.selectionUnit,
|
||||
showDummyRows: props.showDummyRows,
|
||||
copyOptions: props.copyOptions,
|
||||
pageOptions: props.pageOptions,
|
||||
treeColumnOptions: props.treeColumnOptions,
|
||||
header: props.header,
|
||||
usageStatistics: false,
|
||||
disabled: props.disabled,
|
||||
draggable: props.draggable,
|
||||
contextMenu: props.contextMenu
|
||||
};
|
||||
|
||||
if (props.onGridMounted) {
|
||||
gridOptions['onGridMounted'] = props.onGridMounted;
|
||||
}
|
||||
if (props.onGridUpdated) {
|
||||
gridOptions['onGridUpdated'] = props.onGridUpdated;
|
||||
}
|
||||
if (props.onGridBeforeDestroy) {
|
||||
gridOptions['onGridBeforeDestroy'] = props.onGridBeforeDestroy;
|
||||
}
|
||||
|
||||
instance.value = new Grid(gridOptions);
|
||||
});
|
||||
|
||||
const appendRow = (value: OptRow) => {
|
||||
instance.value?.appendRow(value);
|
||||
};
|
||||
|
||||
const appendRows = (value: OptRow[]) => {
|
||||
instance.value?.appendRows(value);
|
||||
};
|
||||
|
||||
const prependRow = (value: OptRow) => {
|
||||
instance.value?.prependRow(value);
|
||||
};
|
||||
|
||||
const getCheckedRows = () => {
|
||||
return instance.value?.getCheckedRows();
|
||||
};
|
||||
|
||||
const getData = () => {
|
||||
return instance.value?.getData();
|
||||
};
|
||||
|
||||
const validate = () => {
|
||||
return instance.value?.validate();
|
||||
};
|
||||
|
||||
const resetData = (data: OptRow[]) => {
|
||||
instance.value?.resetData(data);
|
||||
};
|
||||
|
||||
const removeRow = (data: RowKey) => {
|
||||
instance.value?.removeRow(data);
|
||||
};
|
||||
|
||||
const removeRows = (data: RowKey[]) => {
|
||||
instance.value?.removeRows(data);
|
||||
};
|
||||
|
||||
const on = (eventName: GridEventName, eventFunction: (event) => void) => {
|
||||
instance.value?.on(eventName, eventFunction);
|
||||
};
|
||||
|
||||
const off = (eventName: GridEventName) => {
|
||||
instance.value?.off(eventName);
|
||||
};
|
||||
|
||||
defineExpose({
|
||||
appendRow,
|
||||
appendRows,
|
||||
prependRow,
|
||||
getCheckedRows,
|
||||
getData,
|
||||
validate,
|
||||
resetData,
|
||||
on,
|
||||
off,
|
||||
removeRow,
|
||||
removeRows
|
||||
});
|
||||
|
||||
watch(
|
||||
() => props.data,
|
||||
(newValue) => {
|
||||
resetData(newValue);
|
||||
}
|
||||
);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div ref="gridRef" />
|
||||
</template>
|
||||
163
nuxt/components/data/pagination.vue
Normal file
163
nuxt/components/data/pagination.vue
Normal file
@@ -0,0 +1,163 @@
|
||||
<script setup lang="ts">
|
||||
import 'tui-pagination/dist/tui-pagination.css';
|
||||
import type { PaginationType } from '~/types/data/pagination';
|
||||
import {
|
||||
DoubleLeftOutlined,
|
||||
DoubleRightOutlined,
|
||||
LeftOutlined,
|
||||
RightOutlined
|
||||
} from '@ant-design/icons-vue';
|
||||
|
||||
const props = defineProps<PaginationType>();
|
||||
const emit = defineEmits(['change']);
|
||||
|
||||
const totalPages = computed(() => Math.ceil(props.totalElements / props.size));
|
||||
const rangePages = computed(() =>
|
||||
Array.from({ length: totalPages.value }, (_, i) => i + 1)
|
||||
);
|
||||
|
||||
const ranges = computed(() => {
|
||||
const ranges: number[][] = [];
|
||||
do {
|
||||
ranges.push(rangePages.value.splice(0, props.showPaginationCount));
|
||||
} while (rangePages.value.length !== 0);
|
||||
|
||||
if (ranges[0].length === 0) {
|
||||
ranges[0][0] = 1;
|
||||
}
|
||||
|
||||
return ranges;
|
||||
});
|
||||
|
||||
const currentRange = computed(() => {
|
||||
for (const range of ranges.value) {
|
||||
if (range.some((i) => i === props.page)) {
|
||||
return range;
|
||||
}
|
||||
}
|
||||
|
||||
return [];
|
||||
});
|
||||
|
||||
const currentPeriod = computed(() => {
|
||||
for (let i = 0; i < ranges.value.length; ++i) {
|
||||
if (ranges.value[i].some((i) => i === props.page)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
});
|
||||
|
||||
const prevPageNumber = computed(() => {
|
||||
const range = ranges.value[currentPeriod.value - 1];
|
||||
if (range) {
|
||||
return range[range.length - 1];
|
||||
}
|
||||
|
||||
return props.page;
|
||||
});
|
||||
|
||||
const nextPageNumber = computed(() => {
|
||||
const range = ranges.value[currentPeriod.value + 1];
|
||||
if (range) {
|
||||
return range[0];
|
||||
}
|
||||
|
||||
return props.page;
|
||||
});
|
||||
|
||||
const firstPage = () => {
|
||||
submitPage(1);
|
||||
};
|
||||
|
||||
const prevPage = () => {
|
||||
submitPage(prevPageNumber.value);
|
||||
};
|
||||
|
||||
const nextPage = () => {
|
||||
submitPage(nextPageNumber.value);
|
||||
};
|
||||
|
||||
const lastPage = () => {
|
||||
submitPage(totalPages.value ? totalPages.value : 1);
|
||||
};
|
||||
|
||||
const change = (value) => {
|
||||
if (props.size !== value) {
|
||||
emit('change', props.page, value);
|
||||
}
|
||||
};
|
||||
|
||||
const movePage = (value) => {
|
||||
submitPage(value);
|
||||
};
|
||||
|
||||
const submitPage = (page: number) => {
|
||||
if (props.page !== page) {
|
||||
emit('change', page, props.size);
|
||||
}
|
||||
};
|
||||
|
||||
const options = [
|
||||
{ label: '15', value: 15 },
|
||||
{ label: '30', value: 30 },
|
||||
{ label: '50', value: 50 },
|
||||
{ label: '100', value: 100 }
|
||||
];
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<a-row justify="space-between" class="mt-5">
|
||||
<a-col>
|
||||
<a-space>
|
||||
<a-select :options="options" :value="size" @change="change" />
|
||||
<span>건/페이지 (총 {{ totalElements }}건)</span>
|
||||
</a-space>
|
||||
</a-col>
|
||||
<a-col
|
||||
><a-space>
|
||||
<a-button
|
||||
type="link"
|
||||
:icon="h(DoubleLeftOutlined)"
|
||||
size="small"
|
||||
class="pagination-icon-size text-black"
|
||||
@click="firstPage"
|
||||
/>
|
||||
<a-button
|
||||
type="link"
|
||||
:icon="h(LeftOutlined)"
|
||||
class="pagination-icon-size text-black"
|
||||
size="small"
|
||||
@click="prevPage"
|
||||
/>
|
||||
<a-space>
|
||||
<a-button
|
||||
size="small"
|
||||
:type="pageNo === page ? 'default' : `link`"
|
||||
class="text-black"
|
||||
v-for="pageNo in currentRange"
|
||||
:key="`pagination-${pageNo}`"
|
||||
@click="() => movePage(pageNo)"
|
||||
>{{ pageNo }}</a-button
|
||||
>
|
||||
</a-space>
|
||||
<a-button
|
||||
type="link"
|
||||
:icon="h(RightOutlined)"
|
||||
size="small"
|
||||
class="pagination-icon-size text-black"
|
||||
@click="nextPage"
|
||||
/>
|
||||
<a-button
|
||||
type="link"
|
||||
:icon="h(DoubleRightOutlined)"
|
||||
class="pagination-icon-size text-black"
|
||||
size="small"
|
||||
@click="lastPage"
|
||||
/>
|
||||
</a-space>
|
||||
</a-col>
|
||||
<a-col></a-col>
|
||||
</a-row>
|
||||
</template>
|
||||
@@ -1,9 +1,14 @@
|
||||
<script setup lang="ts">
|
||||
import { useAuthStore } from '~/stores/login';
|
||||
|
||||
const authStore = useAuthStore();
|
||||
const { loginResponse } = storeToRefs(authStore);
|
||||
|
||||
const selectedKeys = ref<string[]>([]);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<a-menu v-model:selected-keys="selectedKeys" mode="inline" theme="dark">
|
||||
<!-- <layout-left-menu-item :menu-list="authorization.menuList" />-->
|
||||
<layout-left-menu-item :menu-list="loginResponse.menuList" />
|
||||
</a-menu>
|
||||
</template>
|
||||
|
||||
@@ -1,26 +1,31 @@
|
||||
<script setup lang="ts">
|
||||
import type { AuthorizationMenuType } from '~/types/login';
|
||||
|
||||
defineProps<{
|
||||
menuList: AuthorizationMenuType[]
|
||||
}>();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<!-- <template v-for="menu in menuList" :key="menu.menuId">-->
|
||||
<!-- <a-menu-item :key="menu.menuId" v-if="!menu.children">-->
|
||||
<!-- <nuxt-link :to="menu.menuUrl">{{ menu.menuName }}</nuxt-link>-->
|
||||
<!-- </a-menu-item>-->
|
||||
<!-- <a-sub-menu :key="menu.menuId" v-if="menu.children">-->
|
||||
<!-- <template #title>{{ menu.menuName }}</template>-->
|
||||
<!-- <template v-for="child in menu.children">-->
|
||||
<!-- <template v-if="!child.children">-->
|
||||
<!-- <a-menu-item :key="child.menuId">-->
|
||||
<!-- <nuxt-link :to="child.menuUrl">{{ child.menuName }}</nuxt-link>-->
|
||||
<!-- </a-menu-item>-->
|
||||
<!-- </template>-->
|
||||
<!-- <template v-if="child.children">-->
|
||||
<!-- <a-sub-menu :key="child.menuId">-->
|
||||
<!-- <template #title>{{ child.menuName }}</template>-->
|
||||
<!-- <layout-left-menu-item :menu-list="child.children" />-->
|
||||
<!-- </a-sub-menu>-->
|
||||
<!-- </template>-->
|
||||
<!-- </template>-->
|
||||
<!-- </a-sub-menu>-->
|
||||
<!-- </template>-->
|
||||
<template v-for="menu in menuList" :key="menu.menuId">
|
||||
<a-menu-item :key="menu.menuId" v-if="!menu.children">
|
||||
<nuxt-link :to="menu.menuUrl">{{ menu.menuName }}</nuxt-link>
|
||||
</a-menu-item>
|
||||
<a-sub-menu :key="menu.menuId" v-if="menu.children">
|
||||
<template #title>{{ menu.menuName }}</template>
|
||||
<template v-for="child in menu.children">
|
||||
<template v-if="!child.children">
|
||||
<a-menu-item :key="child.menuId">
|
||||
<nuxt-link :to="child.menuUrl">{{ child.menuName }}</nuxt-link>
|
||||
</a-menu-item>
|
||||
</template>
|
||||
<template v-if="child.children">
|
||||
<a-sub-menu :key="child.menuId">
|
||||
<template #title>{{ child.menuName }}</template>
|
||||
<layout-left-menu-item :menu-list="child.children" />
|
||||
</a-sub-menu>
|
||||
</template>
|
||||
</template>
|
||||
</a-sub-menu>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
@@ -10,7 +10,7 @@ import { LogoutOutlined } from '@ant-design/icons-vue';
|
||||
</a-button>
|
||||
</a-col>
|
||||
|
||||
<router-link to="/login" style="color: #1890ff">
|
||||
<router-link to="/admin/login" style="color: #1890ff">
|
||||
로그아웃
|
||||
</router-link>
|
||||
|
||||
|
||||
41
nuxt/composables/useAxios.ts
Normal file
41
nuxt/composables/useAxios.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
import axios, { type AxiosError, type AxiosResponse } from 'axios';
|
||||
// import { useAuthStore } from '~/stores/login';
|
||||
// import { useDefaultStore, useLoadingStore } from '~/stores';
|
||||
|
||||
const baseURL = import.meta.env.VITE_API_URL as string;
|
||||
|
||||
export const useAxios = () => {
|
||||
// const loadingStore = useLoadingStore();
|
||||
// const defaultStore = useDefaultStore();
|
||||
// const { siteInfo } = storeToRefs(defaultStore);
|
||||
// const authStore = useAuthStore();
|
||||
const router = useRouter();
|
||||
|
||||
const instance = axios.create({
|
||||
baseURL,
|
||||
withCredentials: true
|
||||
});
|
||||
|
||||
instance.interceptors.request.use(
|
||||
(config) => {
|
||||
return Promise.resolve(config);
|
||||
},
|
||||
(error: AxiosError) => {
|
||||
return Promise.reject(error);
|
||||
}
|
||||
);
|
||||
|
||||
instance.interceptors.response.use(
|
||||
(response: AxiosResponse<any, any>) => {
|
||||
return Promise.resolve(response);
|
||||
},
|
||||
(error: AxiosError) => {
|
||||
if (error.status === 403) {
|
||||
return router.push('/');
|
||||
}
|
||||
return Promise.reject(error);
|
||||
}
|
||||
);
|
||||
|
||||
return instance;
|
||||
};
|
||||
20
nuxt/constants/grid/index.ts
Normal file
20
nuxt/constants/grid/index.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
export const BOOLEANS = [
|
||||
{ text: '사용', value: 'true' },
|
||||
{ text: '미사용', value: 'false' }
|
||||
];
|
||||
|
||||
export const YES_OR_NO_CODE_LIST = [
|
||||
{ text: '예', value: 'true' },
|
||||
{ text: '아니오', value: 'false' }
|
||||
];
|
||||
|
||||
export const LOCK_CODE_LIST = [
|
||||
{ text: '정상', value: 'false' },
|
||||
{ text: '잠김', value: 'true' }
|
||||
];
|
||||
|
||||
export const ADMIN_STATUS_CODE_LIST = [
|
||||
{ text: '미승인', value: 'NONE' },
|
||||
{ text: '승인', value: 'APRV' },
|
||||
{ text: '반려', value: 'RJCT' }
|
||||
];
|
||||
16
nuxt/constants/login/index.ts
Normal file
16
nuxt/constants/login/index.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import type { LoginRequestType, LoginResponseType } from '~/types/login';
|
||||
|
||||
export const DEFAULT_AUTHENTICATION_VALUE: LoginRequestType = {
|
||||
memberId: '',
|
||||
password: '',
|
||||
remember: false
|
||||
};
|
||||
|
||||
export const DEFAULT_AUTHORIZATION_VALUE: LoginResponseType = {
|
||||
memberName: '',
|
||||
deptNm: '',
|
||||
instNm: '',
|
||||
menuList: [],
|
||||
permitApiList: [],
|
||||
authenticated: false
|
||||
};
|
||||
36
nuxt/constants/theme/grid/ConditionButtonRenderer.ts
Normal file
36
nuxt/constants/theme/grid/ConditionButtonRenderer.ts
Normal file
@@ -0,0 +1,36 @@
|
||||
import type { CellRendererProps } from 'tui-grid/types/renderer';
|
||||
|
||||
export class ConditionButtonRenderer {
|
||||
el: HTMLElement;
|
||||
|
||||
constructor(props: CellRendererProps) {
|
||||
const { rowKey, grid } = props;
|
||||
const { options } = props.columnInfo.renderer;
|
||||
const data = grid.getRow(rowKey);
|
||||
|
||||
console.log(!data.baAnswerYn);
|
||||
if (!data.baAnswerYn) {
|
||||
const el = document.createElement('button');
|
||||
el.className = 'ant-btn ant-btn-primary';
|
||||
el.onclick = () => options?.onClick(data);
|
||||
el.innerHTML = `<span>${options?.buttonName}</span>`;
|
||||
this.el = el;
|
||||
} else {
|
||||
const el = document.createElement('span');
|
||||
el.innerHTML = options?.spanName;
|
||||
this.el = el;
|
||||
}
|
||||
}
|
||||
|
||||
beforeDestroy(): void {}
|
||||
|
||||
focused(): void {}
|
||||
|
||||
getElement(): Element {
|
||||
return this.el;
|
||||
}
|
||||
|
||||
mounted(parent: HTMLElement): void {}
|
||||
|
||||
render(props: CellRendererProps): void {}
|
||||
}
|
||||
39
nuxt/constants/theme/grid/ConditionIconButtonRenderer.ts
Normal file
39
nuxt/constants/theme/grid/ConditionIconButtonRenderer.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
import type { CellRendererProps } from 'tui-grid/types/renderer';
|
||||
|
||||
export class ConditionIconButtonRenderer {
|
||||
el: HTMLElement;
|
||||
|
||||
constructor(props: CellRendererProps) {
|
||||
const { options } = props.columnInfo.renderer;
|
||||
const data = props.grid.getRow(props.rowKey);
|
||||
|
||||
if (options?.condition(data)) {
|
||||
const el = document.createElement('a');
|
||||
// @ts-ignore
|
||||
const { icon } = options;
|
||||
el.innerHTML = `
|
||||
<svg focusable="false" data-icon="${icon.name}" width="1em" height="2em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896">
|
||||
<path d="${icon.icon.children[0].attrs.d}" />
|
||||
</svg>
|
||||
`;
|
||||
el.className = 'ant-btn ant-btn-primary';
|
||||
el.onclick = () => options?.onClick(data);
|
||||
|
||||
this.el = el;
|
||||
} else {
|
||||
this.el = document.createElement('span');
|
||||
}
|
||||
}
|
||||
|
||||
beforeDestroy(): void {}
|
||||
|
||||
focused(): void {}
|
||||
|
||||
getElement(): Element {
|
||||
return this.el;
|
||||
}
|
||||
|
||||
mounted(parent: HTMLElement): void {}
|
||||
|
||||
render(props: CellRendererProps): void {}
|
||||
}
|
||||
28
nuxt/constants/theme/grid/FunctionalButtonRenderer.ts
Normal file
28
nuxt/constants/theme/grid/FunctionalButtonRenderer.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import type { CellRendererProps } from 'tui-grid/types/renderer';
|
||||
|
||||
export class FunctionalButtonRenderer {
|
||||
el: HTMLElement;
|
||||
|
||||
constructor(props: CellRendererProps) {
|
||||
const el = document.createElement('button');
|
||||
const options = props.columnInfo.renderer.options;
|
||||
const data = props.grid.getRow(props.rowKey);
|
||||
el.className = 'ant-btn ant-btn-primary';
|
||||
el.onclick = () => options?.onClick(data);
|
||||
el.innerHTML = `<span>${options?.buttonName}</span>`;
|
||||
|
||||
this.el = el;
|
||||
}
|
||||
|
||||
beforeDestroy(): void {}
|
||||
|
||||
focused(): void {}
|
||||
|
||||
getElement(): Element {
|
||||
return this.el;
|
||||
}
|
||||
|
||||
mounted(parent: HTMLElement): void {}
|
||||
|
||||
render(props: CellRendererProps): void {}
|
||||
}
|
||||
27
nuxt/constants/theme/grid/MaxLengthTextEditor.ts
Normal file
27
nuxt/constants/theme/grid/MaxLengthTextEditor.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import type { CellEditorProps } from 'tui-grid/types/editor';
|
||||
|
||||
export class MaxLengthTextEditor {
|
||||
el: HTMLInputElement;
|
||||
|
||||
constructor(props: CellEditorProps) {
|
||||
const el = document.createElement('input');
|
||||
el.type = 'text';
|
||||
el.value = props.value as string;
|
||||
el.maxLength = props.columnInfo.editor?.options?.maxlength;
|
||||
el.placeholder = props.columnInfo.editor?.options?.placeholder;
|
||||
|
||||
this.el = el;
|
||||
}
|
||||
|
||||
getElement() {
|
||||
return this.el;
|
||||
}
|
||||
|
||||
getValue() {
|
||||
return this.el.value;
|
||||
}
|
||||
|
||||
mounted() {
|
||||
this.el.select();
|
||||
}
|
||||
}
|
||||
82
nuxt/constants/theme/grid/MenuSatisChargerRenderer.ts
Normal file
82
nuxt/constants/theme/grid/MenuSatisChargerRenderer.ts
Normal file
@@ -0,0 +1,82 @@
|
||||
import type { CellRendererProps } from 'tui-grid/types/renderer';
|
||||
import type { MenuType } from '~/types/sys/menu';
|
||||
|
||||
export class MenuSatisChargerRenderer {
|
||||
el: HTMLElement;
|
||||
|
||||
constructor(props: CellRendererProps) {
|
||||
const el = document.createElement('div');
|
||||
|
||||
el.style['gap'] = '8px';
|
||||
el.className = 'flex justify-center';
|
||||
|
||||
const { rowKey, grid } = props;
|
||||
const options = props.columnInfo.renderer.options as any;
|
||||
|
||||
const data = grid.getRow(rowKey) as unknown as MenuType;
|
||||
if (!data.menuType.endsWith('API')) {
|
||||
if (data?.menuMngId) {
|
||||
const { onView, onDelete } = options;
|
||||
const viewLink = document.createElement('a');
|
||||
const deleteLink = document.createElement('a');
|
||||
|
||||
viewLink.innerHTML = '보기';
|
||||
viewLink.onclick = () => onView(data);
|
||||
|
||||
deleteLink.innerHTML = '삭제';
|
||||
deleteLink.onclick = () => onDelete(data);
|
||||
|
||||
el.append(viewLink, deleteLink);
|
||||
} else {
|
||||
const { onEdit } = options;
|
||||
const link = document.createElement('a');
|
||||
link.innerHTML = '등록';
|
||||
link.onclick = () => onEdit(data);
|
||||
|
||||
el.append(link);
|
||||
}
|
||||
}
|
||||
|
||||
this.el = el;
|
||||
}
|
||||
|
||||
beforeDestroy(): void {}
|
||||
|
||||
focused(): void {}
|
||||
|
||||
getElement(): Element {
|
||||
return this.el;
|
||||
}
|
||||
|
||||
mounted(parent: HTMLElement): void {}
|
||||
|
||||
render(props: CellRendererProps): void {
|
||||
this.el.innerHTML = '';
|
||||
const { rowKey, grid } = props;
|
||||
const options = props.columnInfo.renderer.options as any;
|
||||
|
||||
const data = grid.getRow(rowKey) as unknown as MenuType;
|
||||
if (!data.menuType.endsWith('API')) {
|
||||
if (data?.menuMngId) {
|
||||
const { onView, onDelete } = options;
|
||||
const viewLink = document.createElement('a');
|
||||
const deleteLink = document.createElement('a');
|
||||
|
||||
viewLink.innerHTML = '보기';
|
||||
viewLink.onclick = () => onView(data);
|
||||
|
||||
deleteLink.innerHTML = '삭제';
|
||||
deleteLink.onclick = () => onDelete(data);
|
||||
|
||||
this.el.append(viewLink, deleteLink);
|
||||
} else {
|
||||
const { onEdit } = options;
|
||||
const link = document.createElement('a');
|
||||
link.innerHTML = '등록';
|
||||
link.onclick = () => onEdit(data);
|
||||
|
||||
this.el.append(link);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
32
nuxt/constants/theme/grid/RadioHeaderRenderer.ts
Normal file
32
nuxt/constants/theme/grid/RadioHeaderRenderer.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
import type { CellRendererProps } from 'tui-grid/types/renderer';
|
||||
|
||||
export class RadioHeaderRenderer {
|
||||
el: HTMLElement;
|
||||
|
||||
constructor(props: CellRendererProps) {
|
||||
const { rowKey, grid } = props;
|
||||
|
||||
const { options } = props.columnInfo.renderer;
|
||||
const data = grid.getRow(rowKey);
|
||||
|
||||
const el = document.createElement('input');
|
||||
el.name = 'gridRadio';
|
||||
el.type = 'radio';
|
||||
el.className = '';
|
||||
el.addEventListener('change', () => options?.onChange(data));
|
||||
|
||||
this.el = el;
|
||||
}
|
||||
|
||||
beforeDestroy(): void {}
|
||||
|
||||
focused(): void {}
|
||||
|
||||
getElement(): Element {
|
||||
return this.el;
|
||||
}
|
||||
|
||||
mounted(parent: HTMLElement): void {}
|
||||
|
||||
render(props: CellRendererProps): void {}
|
||||
}
|
||||
65
nuxt/constants/theme/grid/index.ts
Normal file
65
nuxt/constants/theme/grid/index.ts
Normal file
@@ -0,0 +1,65 @@
|
||||
import type { OptPreset } from 'tui-grid/types/options';
|
||||
|
||||
export const TUI_GRID_THEME: OptPreset = {
|
||||
selection: {
|
||||
background: '#4daaf9',
|
||||
border: '#004082'
|
||||
},
|
||||
scrollbar: {
|
||||
background: '#f5f5f5',
|
||||
thumb: '#d9d9d9',
|
||||
active: '#c1c1c1'
|
||||
},
|
||||
outline: {
|
||||
border: '#e1e2e5'
|
||||
},
|
||||
area: {
|
||||
header: {
|
||||
border: '#e1e2e5',
|
||||
background: '#f8f8f9'
|
||||
}
|
||||
},
|
||||
row: {
|
||||
even: {
|
||||
background: '#EFFAFF'
|
||||
}
|
||||
},
|
||||
cell: {
|
||||
normal: {
|
||||
background: 'white',
|
||||
border: '#eee',
|
||||
showVerticalBorder: true
|
||||
},
|
||||
header: {
|
||||
background: '#f8f8f9',
|
||||
showHorizontalBorder: true,
|
||||
showVerticalBorder: true
|
||||
},
|
||||
rowHeader: {
|
||||
border: '#e1e2e5',
|
||||
background: '#f8f8f9',
|
||||
showHorizontalBorder: false,
|
||||
showVerticalBorder: false
|
||||
},
|
||||
editable: {
|
||||
// 수정 가능 셀 색상은 아래에
|
||||
background: 'white'
|
||||
},
|
||||
selectedHeader: {
|
||||
background: '#e0e0e0'
|
||||
},
|
||||
focused: {
|
||||
border: '#418ed4'
|
||||
},
|
||||
disabled: {
|
||||
text: '#333',
|
||||
background: 'white'
|
||||
},
|
||||
invalid: {
|
||||
background: '#D60440'
|
||||
},
|
||||
required: {
|
||||
background: 'white'
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -21,12 +21,6 @@ export default defineNuxtConfig({
|
||||
autoImport: true
|
||||
},
|
||||
devtools: { enabled: true },
|
||||
// plugins: [
|
||||
// '~/plugins/ant-design-vue.ts'
|
||||
// ],
|
||||
// css: [
|
||||
// 'ant-design-vue/dist/reset.css'
|
||||
// ],
|
||||
modules: [
|
||||
'@pinia/nuxt',
|
||||
'@unocss/nuxt',
|
||||
@@ -35,11 +29,11 @@ export default defineNuxtConfig({
|
||||
],
|
||||
vite: {
|
||||
optimizeDeps: {
|
||||
include: ['tui-grid', '@ant-design', 'ant-design-vue']
|
||||
include: ['tui-grid', 'ant-design-vue']
|
||||
}
|
||||
},
|
||||
alias: {},
|
||||
experimental: {
|
||||
payloadExtraction: false
|
||||
payloadExtraction: true
|
||||
}
|
||||
});
|
||||
|
||||
126
nuxt/pages/admin/content/index.vue
Normal file
126
nuxt/pages/admin/content/index.vue
Normal file
@@ -0,0 +1,126 @@
|
||||
<script setup lang="ts">
|
||||
import { useContentStore } from '~/stores/contents';
|
||||
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
|
||||
const contentId = route.query.contentId;
|
||||
|
||||
const editorRef = ref();
|
||||
|
||||
const contentStore = useContentStore();
|
||||
const { contents, initialValue } = storeToRefs(contentStore);
|
||||
|
||||
onBeforeMount(() => {
|
||||
if (contentId) {
|
||||
contentStore.searchContents(Number(contentId));
|
||||
} else {
|
||||
contentStore.resetContents();
|
||||
}
|
||||
});
|
||||
|
||||
const save = () => {
|
||||
contents.value.contents = editorRef.value.getValue();
|
||||
|
||||
contentStore
|
||||
.updateContents()
|
||||
.then(() => {
|
||||
message.success('콘텐츠 정보가 저장이 되었습니다.');
|
||||
moveList();
|
||||
})
|
||||
.catch(() => {
|
||||
message.error('콘텐츠 저장에 실패하였습니다.');
|
||||
});
|
||||
};
|
||||
|
||||
const moveList = () => {
|
||||
router.push('/admin/content/list');
|
||||
};
|
||||
|
||||
const nonValid = computed(() => {
|
||||
return !contents.value.contentTitle;
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<client-only>
|
||||
<a-space direction="vertical" class="w-full">
|
||||
<a-card>
|
||||
<a-row>
|
||||
<a-col :span="24">
|
||||
<a-form-item
|
||||
label="제목"
|
||||
label-align="left"
|
||||
:colon="false"
|
||||
:label-col="{ span: 2 }"
|
||||
>
|
||||
<a-input
|
||||
title="제목"
|
||||
placeholder="콘텐츠 제목"
|
||||
v-model:value="contents.contentTitle"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
|
||||
<a-col :span="24">
|
||||
<a-form-item
|
||||
label="기관"
|
||||
label-align="left"
|
||||
:colon="false"
|
||||
:label-col="{ span: 2 }"
|
||||
>
|
||||
<common-inst-code-select v-model:value="contents.orgId" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
|
||||
<a-col :span="24">
|
||||
<a-form-item
|
||||
label="내용"
|
||||
label-align="left"
|
||||
:colon="false"
|
||||
:label-col="{ span: 2 }"
|
||||
:wrapper-col="{ span: 22 }"
|
||||
>
|
||||
<lazy-data-editor ref="editorRef" :initial-value="initialValue" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
|
||||
<a-col :span="24">
|
||||
<a-form-item
|
||||
label="사용여부"
|
||||
label-align="left"
|
||||
:colon="false"
|
||||
:label-col="{ span: 2 }"
|
||||
:wrapper-col="{ span: 22 }"
|
||||
>
|
||||
<a-switch v-model:checked="contents.useYn" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
|
||||
<a-col :span="24">
|
||||
<a-flex justify="space-between">
|
||||
<a-space>
|
||||
<common-permit-button api="/api/admin/contents/updateContents">
|
||||
<a-button
|
||||
type="primary"
|
||||
@click="save"
|
||||
:disabled="nonValid"
|
||||
v-if="!contentId"
|
||||
>저장</a-button
|
||||
>
|
||||
<a-button
|
||||
type="primary"
|
||||
@click="save"
|
||||
v-if="contentId != null"
|
||||
>수정</a-button
|
||||
>
|
||||
</common-permit-button>
|
||||
<a-button type="default" @click="moveList">목록</a-button>
|
||||
</a-space>
|
||||
</a-flex>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-card>
|
||||
</a-space>
|
||||
</client-only>
|
||||
</template>
|
||||
202
nuxt/pages/admin/content/list.vue
Normal file
202
nuxt/pages/admin/content/list.vue
Normal file
@@ -0,0 +1,202 @@
|
||||
<script setup lang="ts">
|
||||
import type { OptColumn, OptRowHeader } from 'tui-grid/types/options';
|
||||
import { useContentStore } from '~/stores/contents';
|
||||
import type { ContentType } from '~/types/contents';
|
||||
import { useCommonCodeStore } from '~/stores';
|
||||
|
||||
const router = useRouter();
|
||||
|
||||
const instCodeList = await useCommonCodeStore().searchInstCodeList();
|
||||
const contentStore = useContentStore();
|
||||
const { contentsList, contentsQuery } = storeToRefs(contentStore);
|
||||
const gridRef = ref();
|
||||
|
||||
const gridRowHeaders: OptRowHeader[] = ['checkbox', 'rowNum'];
|
||||
|
||||
const columns: OptColumn[] = [
|
||||
{
|
||||
name: 'contentId',
|
||||
hidden: true
|
||||
},
|
||||
{
|
||||
name: 'contentTitle',
|
||||
header: '콘텐츠제목'
|
||||
},
|
||||
{
|
||||
name: 'orgId',
|
||||
header: '관리기관',
|
||||
width: 100,
|
||||
disabled: true,
|
||||
formatter: 'listItemText',
|
||||
resizable: true,
|
||||
editor: {
|
||||
type: 'select',
|
||||
options: {
|
||||
listItems: instCodeList
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'useYn',
|
||||
header: '사용여부',
|
||||
width: 80,
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
name: 'frstRgtrId',
|
||||
header: '작성자',
|
||||
width: 100
|
||||
},
|
||||
{
|
||||
name: 'frstRegDt',
|
||||
header: '작성일',
|
||||
width: 130
|
||||
},
|
||||
{
|
||||
name: 'lastMdfrId',
|
||||
header: '수정자',
|
||||
width: 100
|
||||
},
|
||||
{
|
||||
name: 'lastMdfcnDt',
|
||||
header: '수정일',
|
||||
width: 130
|
||||
}
|
||||
];
|
||||
|
||||
const contentType = [
|
||||
{ label: '전체', value: 'TOTAL' },
|
||||
{ label: '제목', value: 'TITLE' },
|
||||
{ label: '내용', value: 'CONTENT' }
|
||||
];
|
||||
|
||||
onBeforeMount(() => {
|
||||
contentStore.searchContentList();
|
||||
});
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
// contentStore.resetContentListQuery();
|
||||
});
|
||||
|
||||
const search = () => {
|
||||
contentStore.searchContentList();
|
||||
};
|
||||
|
||||
const list = computed(() => {
|
||||
return contentsList.value.content;
|
||||
});
|
||||
|
||||
watch(list, (newValue) => {
|
||||
if (gridRef.value) {
|
||||
gridRef.value.off('dblclick');
|
||||
if (newValue.length > 0) {
|
||||
setTimeout(() => {
|
||||
gridRef.value.on('dblclick', ({ instance, rowKey }) => {
|
||||
const row = instance.getRow(rowKey);
|
||||
editPage(row.contentId);
|
||||
});
|
||||
}, 100);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const deleteContentList = async () => {
|
||||
const checkedRows = gridRef.value.getCheckedRows() as Array<ContentType>;
|
||||
|
||||
if (!checkedRows.length) {
|
||||
message.warn('삭제할 콘텐츠가 없습니다.');
|
||||
return;
|
||||
}
|
||||
Modal.confirm({
|
||||
type: 'warning',
|
||||
okText: '예',
|
||||
cancelText: '아니오',
|
||||
title: '컨텐츠 삭제',
|
||||
content: '선택한 컨텐츠를 삭제하시겠습니까?',
|
||||
onOk: async () => {
|
||||
const createdRows = checkedRows.filter((row) => row.contentId);
|
||||
await contentStore.deleteContents(createdRows);
|
||||
await contentStore.searchContentList();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const movePage = (page: number) => {
|
||||
contentsQuery.value.page = page;
|
||||
search();
|
||||
};
|
||||
|
||||
const editPage = (contentId: any) => {
|
||||
const query = typeof contentId === 'number' ? `?contentId=${contentId}` : '';
|
||||
router.push(`/admin/content${query}`);
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<client-only>
|
||||
<a-space direction="vertical" class="w-full">
|
||||
<a-card>
|
||||
<a-row :gutter="[16, 8]">
|
||||
<a-col>
|
||||
<a-space>
|
||||
<a-typography-text>관리기관</a-typography-text>
|
||||
<lazy-common-inst-code-select
|
||||
key="inst-code-select"
|
||||
v-model="contentsQuery.orgId"
|
||||
class-name="w-40"
|
||||
select-type="ALL"
|
||||
/>
|
||||
</a-space>
|
||||
</a-col>
|
||||
|
||||
<a-col>
|
||||
<a-space>
|
||||
<a-typography-text>검색어</a-typography-text>
|
||||
<a-select
|
||||
title="컨텐츠 구분"
|
||||
class="w-20"
|
||||
v-model:value="contentsQuery.type"
|
||||
:options="contentType"
|
||||
/>
|
||||
<a-input title="검색어" placeholder="Search" class="w-60"
|
||||
v-model:value="contentsQuery.keyword" allow-clear/>
|
||||
</a-space>
|
||||
</a-col>
|
||||
<a-col>
|
||||
<a-button type="primary" @click="search">검색</a-button>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-card>
|
||||
|
||||
<a-card>
|
||||
<a-space direction="vertical" class="w-full">
|
||||
<a-flex justify="space-between">
|
||||
<!-- <common-permit-button api="/api/admin/contents/deleteContents">-->
|
||||
<!-- <a-button type="primary" danger @click="deleteContentList"-->
|
||||
<!-- >삭제-->
|
||||
<!-- </a-button>-->
|
||||
<!-- </common-permit-button>-->
|
||||
<!-- <common-permit-button api="/api/admin/contents/updateContents">-->
|
||||
<!-- <a-button type="primary" @click="editPage">추가</a-button>-->
|
||||
<!-- </common-permit-button>-->
|
||||
</a-flex>
|
||||
<data-grid
|
||||
:key="`board-content-grid-${Math.random()}`"
|
||||
:row-headers="gridRowHeaders"
|
||||
:data="contentsList.content"
|
||||
:columns="columns"
|
||||
ref="gridRef"
|
||||
/>
|
||||
<data-pagination
|
||||
:key="`pagination-${Math.random()}`"
|
||||
:total-elements="contentsList.totalElements"
|
||||
:show-pagination-count="10"
|
||||
:size="contentsQuery.size"
|
||||
:page="contentsQuery.page"
|
||||
@change="movePage"
|
||||
/>
|
||||
</a-space>
|
||||
</a-card>
|
||||
</a-space>
|
||||
</client-only>
|
||||
</template>
|
||||
@@ -1,49 +1,28 @@
|
||||
<script setup lang="ts">
|
||||
const useAuthStore = ref('');
|
||||
const remember = ref(false);
|
||||
const memberId = ref('');
|
||||
const password = ref('');
|
||||
import { useAuthStore } from '~/stores/login';
|
||||
|
||||
definePageMeta({
|
||||
layout: 'empty'
|
||||
});
|
||||
|
||||
// const router = useRouter();
|
||||
// const store = useAuthStore();
|
||||
// const { authentication } = storeToRefs(store);
|
||||
//
|
||||
// onBeforeMount(() => {
|
||||
// store.loadRemember();
|
||||
// });
|
||||
//
|
||||
// onBeforeUnmount(() => {
|
||||
// authentication.value = {
|
||||
// ...authentication.value,
|
||||
// memberId: ''
|
||||
// };
|
||||
// });
|
||||
//
|
||||
// watch(authentication.value, (newValue) => {
|
||||
// if (newValue.remember) {
|
||||
// store.setRemember();
|
||||
// } else {
|
||||
// store.initRemember();
|
||||
// }
|
||||
// });
|
||||
const router = useRouter();
|
||||
const store = useAuthStore();
|
||||
const { loginRequest } = storeToRefs(store);
|
||||
|
||||
const login = async () => {
|
||||
// try {
|
||||
// const { data } = await store.authenticate();
|
||||
// store.authorize(data);
|
||||
//
|
||||
// await router.push('/');
|
||||
// } catch (e) {
|
||||
// message.error('아이디 또는 비밀번호를 확인해주세요.');
|
||||
// }
|
||||
try {
|
||||
const { data } = await store.LoginAPI();
|
||||
store.loginResponse = data;
|
||||
console.log(JSON.stringify(store.loginResponse));
|
||||
|
||||
await router.push('/');
|
||||
} catch (e) {
|
||||
message.error('아이디 또는 비밀번호를 확인해주세요.');
|
||||
}
|
||||
};
|
||||
|
||||
const validateLogin = computed(() => {
|
||||
return false;
|
||||
return loginRequest.value.memberId && loginRequest.value.password;
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -64,7 +43,7 @@ const validateLogin = computed(() => {
|
||||
<div style="height: 18px"></div>
|
||||
|
||||
<a-form-item>
|
||||
<a-checkbox v-model:checked="remember">
|
||||
<a-checkbox v-model:checked="loginRequest.remember">
|
||||
키보드보안 프로그램적용
|
||||
</a-checkbox>
|
||||
<div style="height: 10px"></div>
|
||||
@@ -78,7 +57,7 @@ const validateLogin = computed(() => {
|
||||
<a-form :colon="false" label-align="left">
|
||||
<a-form-item label="아이디" :label-col="{ span: 5 }">
|
||||
<a-input
|
||||
v-model:value="memberId"
|
||||
v-model:value="loginRequest.memberId"
|
||||
placeholder="아이디를 입력하세요"
|
||||
maxLength="20"
|
||||
/>
|
||||
@@ -86,10 +65,10 @@ const validateLogin = computed(() => {
|
||||
|
||||
<a-form-item label="비밀번호" :label-col="{ span: 5 }">
|
||||
<a-input-password
|
||||
v-model:value="password"
|
||||
v-model:value="loginRequest.password"
|
||||
placeholder="비밀번호를 입력하세요"
|
||||
maxLength="20"
|
||||
@keyup.enter="login"
|
||||
@keyup.enter="login()"
|
||||
/>
|
||||
</a-form-item>
|
||||
|
||||
@@ -97,7 +76,7 @@ const validateLogin = computed(() => {
|
||||
<a-button
|
||||
type="primary"
|
||||
block
|
||||
@click="login"
|
||||
@click="login()"
|
||||
:disabled="!validateLogin"
|
||||
style="font-weight: bold"
|
||||
>
|
||||
@@ -106,15 +85,15 @@ const validateLogin = computed(() => {
|
||||
</a-form-item>
|
||||
|
||||
<div style="display: flex; justify-content: center; margin-top: 16px">
|
||||
<router-link to="/login/id" style="color: #1890ff"
|
||||
<router-link to="#" style="color: #1890ff"
|
||||
>아이디 찾기</router-link
|
||||
>
|
||||
<span style="margin: 0 8px; color: #888">|</span>
|
||||
<router-link to="/login/pw" style="color: #1890ff"
|
||||
<router-link to="#" style="color: #1890ff"
|
||||
>비밀번호 찾기</router-link
|
||||
>
|
||||
<span style="margin: 0 8px; color: #888">|</span>
|
||||
<router-link to="/login/join" style="color: #1890ff"
|
||||
<router-link to="#" style="color: #1890ff"
|
||||
>회원가입</router-link
|
||||
>
|
||||
</div>
|
||||
192
nuxt/pages/admin/sys/site/index.vue
Normal file
192
nuxt/pages/admin/sys/site/index.vue
Normal file
@@ -0,0 +1,192 @@
|
||||
<script setup lang="ts">
|
||||
import type { OptColumn, OptRowHeader } from 'tui-grid/types/options';
|
||||
import { useSiteStore } from '~/stores/sys/site';
|
||||
import type { SiteType } from '~/types/sys/site';
|
||||
import { MaxLengthTextEditor } from '~/constants/theme/grid/MaxLengthTextEditor';
|
||||
|
||||
const siteStore = useSiteStore();
|
||||
const { siteList } = storeToRefs(siteStore);
|
||||
const gridRef = ref();
|
||||
|
||||
const gridRowHeaders: OptRowHeader[] = ['checkbox', 'rowNum'];
|
||||
|
||||
const columns: OptColumn[] = [
|
||||
{
|
||||
name: 'siteId',
|
||||
header: '사이트 ID',
|
||||
width: 80,
|
||||
editor: {
|
||||
type: 'text'
|
||||
},
|
||||
validation: {
|
||||
required: true
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'siteName',
|
||||
header: '사이트명',
|
||||
width: 120,
|
||||
editor: {
|
||||
type: 'text'
|
||||
},
|
||||
validation: {
|
||||
required: true
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'siteDescription',
|
||||
header: '사이트 설명',
|
||||
width: 200,
|
||||
editor: {
|
||||
type: 'text'
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'siteDomain',
|
||||
header: '사이트 도메인',
|
||||
width: 150,
|
||||
editor: {
|
||||
type: 'text'
|
||||
},
|
||||
validation: {
|
||||
required: true
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'siteType',
|
||||
header: '사이트 형식',
|
||||
width: 80,
|
||||
formatter: 'listItemText',
|
||||
editor: {
|
||||
type: 'select',
|
||||
options: {
|
||||
listItems: [
|
||||
{ text: '사용자', value: 'USER' },
|
||||
{ text: '관리자', value: 'ADMIN' }
|
||||
]
|
||||
}
|
||||
},
|
||||
validation: {
|
||||
required: true
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'sitePrefix',
|
||||
header: '사이트 구분',
|
||||
width: 120,
|
||||
editor: {
|
||||
type: 'select',
|
||||
options: {
|
||||
listItems: [
|
||||
{ text: '대국민포털', value: 'portal' },
|
||||
{ text: '참여기관포털', value: 'admin' }
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'lgnUrl',
|
||||
header: '로그인 URL',
|
||||
width: 120,
|
||||
editor: {
|
||||
type: MaxLengthTextEditor,
|
||||
options: {
|
||||
maxlength: 200,
|
||||
placeholder: '로그인 URL을 입력해주세요.'
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'bscUrl',
|
||||
header: '기본 URL',
|
||||
width: 120,
|
||||
editor: {
|
||||
type: MaxLengthTextEditor,
|
||||
options: {
|
||||
maxlength: 200,
|
||||
placeholder: '로그인 후 이동될 URL을 입력해주세요.'
|
||||
}
|
||||
}
|
||||
},
|
||||
{ name: 'siteRegdate', header: '등록일시', width: 140 }
|
||||
];
|
||||
|
||||
onBeforeMount(() => {
|
||||
siteStore.searchSiteList();
|
||||
});
|
||||
|
||||
const save = () => {
|
||||
if (gridRef.value.validate().length) {
|
||||
alert('len:::' + gridRef.value.validate().length);
|
||||
message.warn('입력된 사이트 정보를 확인해주세요.');
|
||||
return;
|
||||
}
|
||||
|
||||
Modal.confirm({
|
||||
type: 'info',
|
||||
title: '사이트 정보 저장',
|
||||
content: '선택한 사이트 정보를 저장하시겠습니까?',
|
||||
okText: '예',
|
||||
cancelText: '아니오',
|
||||
onOk: async () => {
|
||||
try {
|
||||
const data = gridRef.value.getData();
|
||||
siteStore.updateSiteList(data);
|
||||
} catch (e) {
|
||||
message.error('사이트 정보를 저장하는 도중 에러가 발생되었습니다.');
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const deleteSiteList = () => {
|
||||
const checkedRows = gridRef.value.getCheckedRows() as Array<SiteType>;
|
||||
|
||||
if (!checkedRows.length) {
|
||||
message.warn('삭제할 사이트가 없습니다.');
|
||||
return;
|
||||
}
|
||||
|
||||
const params = new URLSearchParams();
|
||||
checkedRows.forEach((value) => {
|
||||
params.append('siteId', value.siteId);
|
||||
});
|
||||
};
|
||||
|
||||
const addRow = () => {
|
||||
gridRef.value.appendRow({});
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<client-only>
|
||||
<a-space direction="vertical" style="width: 100%">
|
||||
<a-card>
|
||||
<a-space direction="vertical" style="width: 100%">
|
||||
<a-flex justify="space-between">
|
||||
<common-permit-button api="/api/admin/sys/site/deleteSiteList">
|
||||
<a-button type="primary" danger @click="deleteSiteList"
|
||||
>삭제</a-button
|
||||
>
|
||||
</common-permit-button>
|
||||
<common-permit-button api="/api/admin/sys/site/updateSiteList">
|
||||
<a-space>
|
||||
<a-button type="primary" @click="addRow">추가</a-button>
|
||||
<a-button type="primary" @click="save">저장</a-button>
|
||||
</a-space>
|
||||
</common-permit-button>
|
||||
</a-flex>
|
||||
<data-grid
|
||||
:key="`site-grid-${Math.random()}`"
|
||||
:row-headers="gridRowHeaders"
|
||||
:data="siteList"
|
||||
:columns="columns"
|
||||
ref="gridRef"
|
||||
/>
|
||||
</a-space>
|
||||
</a-card>
|
||||
</a-space>
|
||||
</client-only>
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
||||
@@ -1,133 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
|
||||
definePageMeta({
|
||||
layout: 'empty'
|
||||
});
|
||||
|
||||
const dummy = ref('phone');
|
||||
const domain = ref(''); // 도메인 선택 부분
|
||||
|
||||
const domains = [
|
||||
{ value: 'gmail.com', label: 'gmail.com' },
|
||||
{ value: 'naver.com', label: 'naver.com' },
|
||||
{ value: 'daum.net', label: 'daum.net' },
|
||||
{ value: '직접 입력', label: '직접 입력' }
|
||||
];
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<a-row justify="center" class="w-full h-full items-center">
|
||||
<a-col :span="12">
|
||||
<a-card
|
||||
bordered
|
||||
style="padding: 24px; background-color: #f9f9f9; border-radius: 8px"
|
||||
>
|
||||
<!-- 아이디 찾기 타이틀 -->
|
||||
<h2 style="text-align: center; font-weight: bold; font-size: 24px">
|
||||
아이디 찾기
|
||||
</h2>
|
||||
|
||||
<!-- 검색 방법 선택 -->
|
||||
<div style="display: flex; justify-content: center; margin: 16px 0">
|
||||
<a-radio-group v-model:value="dummy">
|
||||
<a-radio value="phone">휴대폰으로 찾기</a-radio>
|
||||
<a-radio value="email">이메일로 찾기</a-radio>
|
||||
</a-radio-group>
|
||||
</div>
|
||||
|
||||
<a-form :colon="false" label-align="left">
|
||||
<!-- 이름 -->
|
||||
<a-form-item
|
||||
label="이름"
|
||||
:label-col="{ span: 4 }"
|
||||
:wrapper-col="{ span: 20 }"
|
||||
>
|
||||
<a-input placeholder="이름을 입력하세요" />
|
||||
</a-form-item>
|
||||
|
||||
<!-- 자동입력방지문자 (라디오 값이 'phone'일 때만 표시) -->
|
||||
<a-form-item
|
||||
v-if="dummy === 'phone'"
|
||||
label="자동입력방지문자"
|
||||
:label-col="{ span: 6 }"
|
||||
:wrapper-col="{ span: 18 }"
|
||||
>
|
||||
<div style="display: flex; gap: 8px">
|
||||
<a-input
|
||||
disabled
|
||||
value="564866"
|
||||
style="width: 100px; text-align: center"
|
||||
/>
|
||||
<a-button>새로고침</a-button>
|
||||
<a-button>음성듣기</a-button>
|
||||
</div>
|
||||
<a-input
|
||||
placeholder="자동입력 방지문자를 입력하세요."
|
||||
style="margin-top: 8px"
|
||||
/>
|
||||
</a-form-item>
|
||||
|
||||
<!-- 휴대전화 (라디오 값이 'phone'일 때만 표시) -->
|
||||
<a-form-item
|
||||
v-if="dummy === 'phone'"
|
||||
label="휴대전화"
|
||||
:label-col="{ span: 4 }"
|
||||
:wrapper-col="{ span: 20 }"
|
||||
>
|
||||
<div style="display: flex; gap: 8px">
|
||||
<a-input style="width: 60px" maxlength="4" />
|
||||
<a-input style="width: 60px" maxlength="4" />
|
||||
<a-input style="width: 60px" maxlength="4" />
|
||||
<a-button>인증번호</a-button>
|
||||
</div>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item
|
||||
v-if="dummy === 'email'"
|
||||
label="이메일"
|
||||
:label-col="{ span: 4 }"
|
||||
:wrapper-col="{ span: 20 }"
|
||||
>
|
||||
<!-- 이메일 입력 필드 -->
|
||||
<a-input v-model="dummy" style="width: 120px" />
|
||||
<span> @ </span>
|
||||
<!-- 도메인 입력 필드 -->
|
||||
<a-input v-model="dummy" style="width: 150px; margin-right: 18px" />
|
||||
<!-- 직접 입력 드롭다운 -->
|
||||
<a-select
|
||||
v-model="domains"
|
||||
style="width: 150px"
|
||||
@change="handleDomainChange"
|
||||
>
|
||||
<a-select-option value="직접 입력">직접 입력</a-select-option>
|
||||
<a-select-option value="gmail.com">gmail.com</a-select-option>
|
||||
<a-select-option value="naver.com">naver.com</a-select-option>
|
||||
<a-select-option value="daum.net">daum.net</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
|
||||
<!-- 인증번호 (라디오 값이 'phone'일 때만 표시) -->
|
||||
<a-form-item
|
||||
v-if="dummy === 'phone'"
|
||||
label="인증번호"
|
||||
:label-col="{ span: 4 }"
|
||||
:wrapper-col="{ span: 20 }"
|
||||
>
|
||||
<a-input placeholder="인증번호를 입력하세요" />
|
||||
</a-form-item>
|
||||
|
||||
<!-- 아이디 찾기 버튼 -->
|
||||
<div style="text-align: center; margin-top: 16px">
|
||||
<a-button
|
||||
type="primary"
|
||||
style="background-color: #1e90ff; color: white; width: 100px"
|
||||
>
|
||||
아이디 찾기
|
||||
</a-button>
|
||||
</div>
|
||||
</a-form>
|
||||
</a-card>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</template>
|
||||
@@ -1,82 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
import locale from 'ant-design-vue/es/locale/ko_KR';
|
||||
import { DEFAULT_THEME } from '~/constants/theme/ui';
|
||||
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
const adminJoinStore = ref('');
|
||||
const member = ref('');
|
||||
|
||||
definePageMeta({
|
||||
layout: 'empty'
|
||||
});
|
||||
|
||||
const changeUrl = (activeKey: string) => {
|
||||
router.push(activeKey);
|
||||
};
|
||||
|
||||
function activeKey(key) {
|
||||
console.log('Active Tab:', key);
|
||||
}
|
||||
|
||||
const disabledInst = computed(() => {
|
||||
return false;
|
||||
});
|
||||
|
||||
const disabledCert = computed(() => {
|
||||
return false;
|
||||
});
|
||||
|
||||
const disabledForm = computed(() => {
|
||||
return false;
|
||||
});
|
||||
|
||||
const disabledCmptn = computed(() => {
|
||||
return false;
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<a-config-provider :locale="locale" :theme="DEFAULT_THEME">
|
||||
<a-row class="w-full h-full">
|
||||
<a-row justify="center" class="w-full h-full items-center">
|
||||
<a-col :span="15">
|
||||
<a-card bordered class="p-5">
|
||||
<a-typography-title :level="4" type="secondary" class="text-center">
|
||||
참여기관 회원가입
|
||||
</a-typography-title>
|
||||
|
||||
<a-tabs default-active-key="1" v-model:active-key="activeKey">
|
||||
<a-tab-pane key="/admin/login/join/trms" tab="01.약관동의" />
|
||||
<a-tab-pane
|
||||
key="/admin/login/join/inst"
|
||||
tab="02.기관선택"
|
||||
:disabled="disabledInst"
|
||||
/>
|
||||
<a-tab-pane
|
||||
key="/admin/login/join/cert"
|
||||
tab="03.본인인증"
|
||||
:disabled="disabledCert"
|
||||
/>
|
||||
<a-tab-pane
|
||||
key="/admin/login/join"
|
||||
tab="04.정보입력"
|
||||
:disabled="disabledForm"
|
||||
/>
|
||||
<a-tab-pane
|
||||
key="/admin/login/join/cmptn"
|
||||
tab="05.가입완료"
|
||||
:disabled="disabledCmptn"
|
||||
/>
|
||||
</a-tabs>
|
||||
|
||||
<slot />
|
||||
</a-card>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-row>
|
||||
</a-config-provider>
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
||||
@@ -1,124 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
|
||||
definePageMeta({
|
||||
layout: 'empty'
|
||||
});
|
||||
|
||||
const dummy = ref<string>('phone');
|
||||
const domain = ref(''); // 도메인 선택 부분
|
||||
|
||||
const domains = [
|
||||
{ value: 'gmail.com', label: 'gmail.com' },
|
||||
{ value: 'naver.com', label: 'naver.com' },
|
||||
{ value: 'daum.net', label: 'daum.net' },
|
||||
{ value: '직접 입력', label: '직접 입력' }
|
||||
];
|
||||
|
||||
const handleDomainChange = (value) => {
|
||||
if (value !== '직접 입력') {
|
||||
domain.value = value;
|
||||
} else {
|
||||
domain.value = '';
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<a-row justify="center" class="w-full h-full items-center">
|
||||
<a-col :span="12">
|
||||
<a-card
|
||||
bordered
|
||||
style="padding: 24px; background-color: #f9f9f9; border-radius: 8px"
|
||||
>
|
||||
<!-- 아이디 찾기 타이틀 -->
|
||||
<h2 style="text-align: center; font-weight: bold; font-size: 24px">
|
||||
비밀번호 재설정
|
||||
</h2>
|
||||
|
||||
<!-- 검색 방법 선택 -->
|
||||
<div style="display: flex; justify-content: center; margin: 16px 0">
|
||||
<a-radio-group v-model:value="dummy">
|
||||
<a-radio defaultValue="phone">휴대폰으로 찾기</a-radio>
|
||||
<a-radio value="email">이메일로 찾기</a-radio>
|
||||
</a-radio-group>
|
||||
</div>
|
||||
|
||||
<a-form :colon="false" label-align="left">
|
||||
<!-- 이름 -->
|
||||
<a-form-item
|
||||
label="이름"
|
||||
:label-col="{ span: 4 }"
|
||||
:wrapper-col="{ span: 20 }"
|
||||
>
|
||||
<a-input placeholder="이름을 입력하세요" />
|
||||
</a-form-item>
|
||||
<!-- 아이디 -->
|
||||
<a-form-item
|
||||
label="아이디"
|
||||
:label-col="{ span: 4 }"
|
||||
:wrapper-col="{ span: 20 }"
|
||||
>
|
||||
<a-input placeholder="아이디를 입력하세요" />
|
||||
</a-form-item>
|
||||
|
||||
<!-- 휴대전화 (라디오 값이 'phone'일 때만 표시) -->
|
||||
<a-form-item
|
||||
v-if="dummy === 'phone'"
|
||||
label="휴대전화"
|
||||
:label-col="{ span: 4 }"
|
||||
:wrapper-col="{ span: 20 }"
|
||||
>
|
||||
<div style="display: flex; gap: 8px">
|
||||
<a-input style="width: 90px" maxlength="4" />
|
||||
<a-input style="width: 90px" maxlength="4" />
|
||||
<a-input style="width: 90px" maxlength="4" />
|
||||
</div>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item
|
||||
v-if="dummy === 'email'"
|
||||
label="이메일"
|
||||
:label-col="{ span: 4 }"
|
||||
:wrapper-col="{ span: 20 }"
|
||||
>
|
||||
<!-- 이메일 입력 필드 -->
|
||||
<a-input v-model="dummy" style="width: 120px" />
|
||||
<span> @ </span>
|
||||
<!-- 도메인 입력 필드 -->
|
||||
<a-input v-model="dummy" style="width: 150px; margin-right: 18px" />
|
||||
<!-- 직접 입력 드롭다운 -->
|
||||
<a-select
|
||||
v-model="domains"
|
||||
style="width: 150px"
|
||||
@change="handleDomainChange"
|
||||
>
|
||||
<a-select-option value="직접 입력">직접 입력</a-select-option>
|
||||
<a-select-option value="gmail.com">gmail.com</a-select-option>
|
||||
<a-select-option value="naver.com">naver.com</a-select-option>
|
||||
<a-select-option value="daum.net">daum.net</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
|
||||
<!-- 암호 찾기 버튼 -->
|
||||
<div style="text-align: center; margin-top: 16px">
|
||||
<a-button
|
||||
v-if="dummy === 'phone'"
|
||||
type="primary"
|
||||
style="background-color: #1e90ff; color: white; width: 100px"
|
||||
>
|
||||
휴대폰 인증
|
||||
</a-button>
|
||||
<a-button
|
||||
v-else
|
||||
type="primary"
|
||||
style="background-color: #1e90ff; color: white; width: 100px"
|
||||
>
|
||||
이메일 인증
|
||||
</a-button>
|
||||
</div>
|
||||
</a-form>
|
||||
</a-card>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</template>
|
||||
140
nuxt/stores/contents/index.ts
Normal file
140
nuxt/stores/contents/index.ts
Normal file
@@ -0,0 +1,140 @@
|
||||
import type {
|
||||
ContentListQueryType,
|
||||
ContentListType,
|
||||
ContentType
|
||||
} from '~/types/contents';
|
||||
import { cloneDeep } from 'lodash-es';
|
||||
import type { Page } from '~/types/common';
|
||||
import { defineStore } from 'pinia';
|
||||
import { ref } from 'vue';
|
||||
import { useAxios } from '~/composables/useAxios';
|
||||
import { message } from 'ant-design-vue';
|
||||
|
||||
const DEFAULT_CONTENT_QUERY: ContentListQueryType = {
|
||||
keyword: '',
|
||||
orgId: '',
|
||||
page: 1,
|
||||
siteId: '',
|
||||
size: 10,
|
||||
type: 'TOTAL'
|
||||
};
|
||||
|
||||
const DEFAULT_CONTENTS_LIST: Page<ContentListType> = {
|
||||
content: [],
|
||||
totalElements: 0,
|
||||
totalPages: 0
|
||||
};
|
||||
|
||||
const DEFAULT_CONTENTS: ContentType = {
|
||||
contentTitle: '',
|
||||
contentPlain: '',
|
||||
contents: '',
|
||||
frstRegDt: '',
|
||||
frstRgtrId: '',
|
||||
lastMdfcnDt: '',
|
||||
lastMdfrId: '',
|
||||
orgId: '',
|
||||
siteId: '',
|
||||
useYn: true
|
||||
};
|
||||
|
||||
export const useContentStore = defineStore('useContentStore', () => {
|
||||
const contentsQuery = ref<ContentListQueryType>(
|
||||
cloneDeep(DEFAULT_CONTENT_QUERY)
|
||||
);
|
||||
|
||||
const contentsList = ref<Page<ContentListType>>(
|
||||
cloneDeep(DEFAULT_CONTENTS_LIST)
|
||||
);
|
||||
|
||||
const contents = ref<ContentType>(cloneDeep(DEFAULT_CONTENTS));
|
||||
const initialValue = ref<string>('');
|
||||
|
||||
const resetContentListQuery = () => {
|
||||
contentsQuery.value = cloneDeep(DEFAULT_CONTENT_QUERY);
|
||||
};
|
||||
|
||||
const resetContentList = () => {
|
||||
contentsList.value = cloneDeep(DEFAULT_CONTENTS_LIST);
|
||||
};
|
||||
|
||||
const resetContents = () => {
|
||||
contents.value = cloneDeep(DEFAULT_CONTENTS);
|
||||
initialValue.value = '';
|
||||
};
|
||||
|
||||
const initContentsQuery = () => {
|
||||
contentsQuery.value = cloneDeep(DEFAULT_CONTENT_QUERY);
|
||||
};
|
||||
|
||||
const searchContentList = async () => {
|
||||
try {
|
||||
const { data } = await useAxios().get(
|
||||
'/api/admin/contents/contentsList',
|
||||
{
|
||||
params: {
|
||||
...contentsQuery.value
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
contentsList.value = data;
|
||||
} catch (e) {
|
||||
message.error('사이트 리스트를 불러오는데 실패하였습니다.');
|
||||
}
|
||||
};
|
||||
|
||||
const searchContents = async (contentId: number) => {
|
||||
try {
|
||||
const { data } = await useAxios().get('/api/admin/contents/detail', {
|
||||
params: {
|
||||
contentId
|
||||
}
|
||||
});
|
||||
|
||||
contents.value = data;
|
||||
initialValue.value = data.contents;
|
||||
} catch (e) {
|
||||
message.error('컨텐츠 정보를 불러오는데 실패하였습니다.');
|
||||
}
|
||||
};
|
||||
|
||||
const updateContents = () => {
|
||||
console.log(contents.value);
|
||||
return useAxios().post(
|
||||
'/api/admin/contents/updateContents',
|
||||
contents.value
|
||||
);
|
||||
};
|
||||
|
||||
const deleteContents = async (data: ContentType[]) => {
|
||||
try {
|
||||
const params = new URLSearchParams();
|
||||
data.forEach((item) => {
|
||||
params.append('contentId', String(item.contentId));
|
||||
});
|
||||
|
||||
await useAxios().post('/api/admin/contents/deleteContents', null, {
|
||||
params
|
||||
});
|
||||
message.success('컨텐츠 정보가 삭제 되었습니다.');
|
||||
} catch (e) {
|
||||
message.error('컨텐츠 정보 삭제에 실패하였습니다.');
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
contentsQuery,
|
||||
contentsList,
|
||||
contents,
|
||||
initialValue,
|
||||
resetContentListQuery,
|
||||
searchContentList,
|
||||
searchContents,
|
||||
resetContentList,
|
||||
resetContents,
|
||||
initContentsQuery,
|
||||
deleteContents,
|
||||
updateContents
|
||||
};
|
||||
});
|
||||
80
nuxt/stores/index.ts
Normal file
80
nuxt/stores/index.ts
Normal file
@@ -0,0 +1,80 @@
|
||||
import type { SiteType } from '~/types/sys/site';
|
||||
import type { GridCodeType } from '~/types';
|
||||
import { defineStore } from 'pinia';
|
||||
import { computed, ref } from 'vue';
|
||||
import { useAxios } from '~/composables/useAxios';
|
||||
|
||||
export const useLoadingStore = defineStore('useLoadingStore', () => {
|
||||
const loadCount = ref<number>(0);
|
||||
|
||||
const incrementLoadCount = () => {
|
||||
loadCount.value++;
|
||||
};
|
||||
|
||||
const decrementLoadCount = () => {
|
||||
loadCount.value--;
|
||||
};
|
||||
|
||||
const resetLoadCount = () => {
|
||||
loadCount.value = 0;
|
||||
};
|
||||
|
||||
const isLoading = computed(() => {
|
||||
return loadCount.value > 0;
|
||||
});
|
||||
|
||||
return {
|
||||
isLoading,
|
||||
resetLoadCount,
|
||||
incrementLoadCount,
|
||||
decrementLoadCount
|
||||
};
|
||||
});
|
||||
|
||||
export const useDefaultStore = defineStore('useDefaultStore', () => {
|
||||
const siteInfo = ref<SiteType>({
|
||||
siteId: '',
|
||||
siteName: '',
|
||||
siteDescription: '',
|
||||
siteDomain: '',
|
||||
siteType: '',
|
||||
sitePrefix: '',
|
||||
siteLocale: '',
|
||||
siteLogo: '',
|
||||
bscUrl: '',
|
||||
lgnUrl: '',
|
||||
delYn: false,
|
||||
useYn: true,
|
||||
frstRgtrId: '',
|
||||
frstRegDt: '',
|
||||
lastMdfrId: '',
|
||||
lastMdfcnDt: ''
|
||||
});
|
||||
|
||||
const fetchSiteInfo = async () => {
|
||||
const { data } = await useAxios().get<SiteType>('/api/admin/siteInfo');
|
||||
siteInfo.value = data;
|
||||
};
|
||||
|
||||
return { siteInfo, fetchSiteInfo };
|
||||
});
|
||||
|
||||
export const useCommonCodeStore = defineStore('useCommonCodeStore', () => {
|
||||
|
||||
const searchSiteCodeList = async (): Promise<GridCodeType[]> => {
|
||||
const { data } = await useAxios().get('/api/admin/code/siteList');
|
||||
return data;
|
||||
};
|
||||
|
||||
const searchInstCodeList = async (): Promise<GridCodeType[]> => {
|
||||
const { data } = await useAxios().get<GridCodeType[]>(
|
||||
'/api/admin/code/instList'
|
||||
);
|
||||
return data;
|
||||
};
|
||||
|
||||
return {
|
||||
searchInstCodeList,
|
||||
searchSiteCodeList
|
||||
};
|
||||
});
|
||||
32
nuxt/stores/login/index.ts
Normal file
32
nuxt/stores/login/index.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
import {useAxios} from "~/composables/useAxios";
|
||||
import type {LoginRequestType, LoginResponseType} from "~/types/login";
|
||||
import { cloneDeep } from 'lodash-es';
|
||||
import {
|
||||
DEFAULT_AUTHENTICATION_VALUE,
|
||||
DEFAULT_AUTHORIZATION_VALUE
|
||||
} from '~/constants/login';
|
||||
|
||||
export const useAuthStore = defineStore('authStore', () => {
|
||||
const loginRequest = ref<LoginRequestType>(
|
||||
cloneDeep(DEFAULT_AUTHENTICATION_VALUE)
|
||||
);
|
||||
|
||||
const loginResponse = ref<LoginResponseType>(
|
||||
cloneDeep(DEFAULT_AUTHORIZATION_VALUE)
|
||||
);
|
||||
|
||||
const LoginAPI = async () => {
|
||||
return await useAxios().post(`/api/admin/login`, loginRequest.value);
|
||||
};
|
||||
|
||||
const permitApiList = computed(() => {
|
||||
return loginResponse.value.permitApiList;
|
||||
});
|
||||
|
||||
return {
|
||||
loginRequest,
|
||||
loginResponse,
|
||||
LoginAPI,
|
||||
permitApiList
|
||||
};
|
||||
});
|
||||
34
nuxt/stores/sys/site/index.ts
Normal file
34
nuxt/stores/sys/site/index.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
import type { SiteType } from '~/types/sys/site';
|
||||
|
||||
export const useSiteStore = defineStore('useSiteStore', () => {
|
||||
const siteList = ref<SiteType[]>([]);
|
||||
|
||||
const resetSiteList = () => {
|
||||
siteList.value = [];
|
||||
};
|
||||
|
||||
const searchSiteList = async () => {
|
||||
try {
|
||||
const { data } = await useAxios().get('/api/admin/sys/site/siteList');
|
||||
siteList.value = data;
|
||||
} catch (e) {
|
||||
message.error('사이트 리스트를 불러오는데 실패하였습니다.');
|
||||
}
|
||||
};
|
||||
|
||||
const updateSiteList = async (data: SiteType[]) => {
|
||||
try {
|
||||
await useAxios().post('/api/admin/sys/site/updateSiteList', data);
|
||||
message.success('사이트 정보가 저장이 되었습니다.');
|
||||
} catch (e) {
|
||||
message.error('사이트 저장에 실패하였습니다.');
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
siteList,
|
||||
resetSiteList,
|
||||
searchSiteList,
|
||||
updateSiteList
|
||||
};
|
||||
});
|
||||
10
nuxt/types/common/index.ts
Normal file
10
nuxt/types/common/index.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
export type Page<T> = {
|
||||
content: T[];
|
||||
totalElements: number;
|
||||
totalPages: number;
|
||||
};
|
||||
|
||||
export type PagingQuery = {
|
||||
page: number;
|
||||
size: number;
|
||||
};
|
||||
32
nuxt/types/contents/index.ts
Normal file
32
nuxt/types/contents/index.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
export type ContentListQueryType = {
|
||||
page: number;
|
||||
size: number;
|
||||
siteId: string;
|
||||
orgId: string;
|
||||
keyword: string;
|
||||
type: 'TOTAL' | 'TITLE' | 'CONTENT';
|
||||
};
|
||||
|
||||
export type ContentListType = {
|
||||
contentId: number;
|
||||
contentTitle: string;
|
||||
useYn: boolean;
|
||||
frstRgtrId: string;
|
||||
frstRegDt: string;
|
||||
lastMdfrId: string;
|
||||
lastMdfcnDt: string;
|
||||
};
|
||||
|
||||
export type ContentType = {
|
||||
contentId?: number;
|
||||
siteId: string;
|
||||
orgId: string;
|
||||
contentTitle: string;
|
||||
contents: string;
|
||||
contentPlain: string;
|
||||
useYn: boolean;
|
||||
frstRgtrId: string;
|
||||
frstRegDt: string;
|
||||
lastMdfrId: string;
|
||||
lastMdfcnDt: string;
|
||||
};
|
||||
50
nuxt/types/data/grid.ts
Normal file
50
nuxt/types/data/grid.ts
Normal file
@@ -0,0 +1,50 @@
|
||||
import type {
|
||||
GridEventListener,
|
||||
OptColumn,
|
||||
OptHeader,
|
||||
OptRow,
|
||||
OptRowHeader,
|
||||
OptSummaryData,
|
||||
OptTree
|
||||
} from 'tui-grid/types/options';
|
||||
import type { EditingEvent, TabMode } from 'tui-grid/types/store/focus';
|
||||
import type { SelectionUnit } from 'tui-grid/types/store/selection';
|
||||
import type {
|
||||
ClipboardCopyOptions,
|
||||
ColumnOptions
|
||||
} from 'tui-grid/types/store/column';
|
||||
import type { PageOptions } from 'tui-grid/types/store/data';
|
||||
import type { CreateMenuGroups } from 'tui-grid/types/store/contextMenu';
|
||||
|
||||
export type DataGridType = {
|
||||
data: OptRow[];
|
||||
columns: OptColumn[];
|
||||
bodyHeight?: number | 'fitToParent' | 'auto';
|
||||
columnOptions?: ColumnOptions;
|
||||
keyColumnName?: String;
|
||||
width?: number | 'auto';
|
||||
heightResizable?: Boolean;
|
||||
minBodyHeight?: Number;
|
||||
rowHeight?: number | 'auto';
|
||||
minRowHeight?: Number;
|
||||
scrollX?: Boolean;
|
||||
scrollY?: Boolean;
|
||||
editingEvent?: EditingEvent;
|
||||
tabMode?: TabMode;
|
||||
rowHeaders?: OptRowHeader[];
|
||||
summary?: OptSummaryData;
|
||||
useClientSort?: Boolean;
|
||||
selectionUnit?: SelectionUnit;
|
||||
showDummyRows?: Boolean;
|
||||
copyOptions?: ClipboardCopyOptions;
|
||||
pageOptions?: PageOptions;
|
||||
treeColumnOptions?: OptTree;
|
||||
header?: OptHeader;
|
||||
usageStatistics?: Boolean;
|
||||
disabled?: Boolean;
|
||||
onGridMounted?: GridEventListener;
|
||||
onGridUpdated?: GridEventListener;
|
||||
onGridBeforeDestroy?: GridEventListener;
|
||||
draggable?: Boolean;
|
||||
contextMenu?: CreateMenuGroups;
|
||||
};
|
||||
7
nuxt/types/data/pagination.ts
Normal file
7
nuxt/types/data/pagination.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
export type PaginationType = {
|
||||
page: number;
|
||||
size: number;
|
||||
totalElements: number;
|
||||
showPaginationCount: number;
|
||||
};
|
||||
|
||||
20
nuxt/types/index.ts
Normal file
20
nuxt/types/index.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
export type PagingQueryType = {
|
||||
page: number;
|
||||
size: number;
|
||||
};
|
||||
|
||||
export type GridCodeType = {
|
||||
label?: string;
|
||||
text?: string;
|
||||
value: string;
|
||||
};
|
||||
|
||||
export type FileInfoType = {
|
||||
fileId: number;
|
||||
fileOriginalName: string;
|
||||
filePath: string;
|
||||
fileMimeType: string;
|
||||
fileSize: number;
|
||||
fileAltText: string;
|
||||
fileDownloadCount: number;
|
||||
};
|
||||
33
nuxt/types/login/index.ts
Normal file
33
nuxt/types/login/index.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
import type { MenuType } from '../sys/menu';
|
||||
|
||||
export type LoginRequestType = {
|
||||
memberId: string;
|
||||
password: string;
|
||||
remember: boolean;
|
||||
};
|
||||
|
||||
export type LoginResponseType = {
|
||||
memberName: string;
|
||||
instNm: string;
|
||||
deptNm: string;
|
||||
menuList: AuthorizationMenuType[];
|
||||
permitApiList: PermitApiType[];
|
||||
authenticated: boolean;
|
||||
};
|
||||
|
||||
export type AuthorizationMenuType = {
|
||||
menuId: string;
|
||||
upMenuId: string;
|
||||
menuDepth: number;
|
||||
menuName: string;
|
||||
menuType: MenuType;
|
||||
menuUrl: string;
|
||||
bcId: string;
|
||||
contentId: string;
|
||||
|
||||
children: AuthorizationMenuType[];
|
||||
};
|
||||
|
||||
export type PermitApiType = {
|
||||
menuUrl: string;
|
||||
};
|
||||
25
nuxt/types/sys/menu/index.ts
Normal file
25
nuxt/types/sys/menu/index.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
export type MenuType = {
|
||||
menuId: string;
|
||||
siteId: string;
|
||||
upMenuId: string;
|
||||
menuDepth: number;
|
||||
menuOrder: number;
|
||||
menuName: string;
|
||||
menuType: 'MENU' | 'PAGE' | 'API' | 'TAB' | 'COMMON_MENU' | 'COMMON_API';
|
||||
menuFeature: 'PAGE' | 'LIST' | 'DETAIL' | 'CREATE' | 'UPDATE' | 'DELETE';
|
||||
menuLayout: string;
|
||||
menuUrl: string;
|
||||
menuMethod: string;
|
||||
menuDescription: string;
|
||||
menuLinkTarget: 'CURRENT' | 'BLANK';
|
||||
menuUseSatisfaction: boolean;
|
||||
menuUseMngInfo: boolean;
|
||||
menuMngId: string;
|
||||
menuStatus: 'ENABLED' | 'HIDDEN' | 'DISABLED';
|
||||
delYn: boolean;
|
||||
useYn: boolean;
|
||||
frstRgtrId: string;
|
||||
frstRegDt: string;
|
||||
lastMdfrId: string;
|
||||
lastMdfcnDt: string;
|
||||
};
|
||||
13
nuxt/types/sys/site/index.ts
Normal file
13
nuxt/types/sys/site/index.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
export type SiteType = {
|
||||
siteId: string;
|
||||
siteName: string;
|
||||
siteDescription: string;
|
||||
siteDomain: string;
|
||||
siteType: '' | 'ADMIN' | 'USER';
|
||||
sitePrefix: string;
|
||||
siteLocale: string;
|
||||
siteLogo: string;
|
||||
bscUrl: string;
|
||||
lgnUrl: string;
|
||||
siteRegdate: string;
|
||||
};
|
||||
Reference in New Issue
Block a user