728x90
반응형
구현
- 기본 프로젝트 목록 Project List 구현 -
- Project Management System의 이용자가 참여중인 프로젝트와 사내 전체 프로젝트목록을 띄움
- 참여중인 프로젝트의 제목 클릭 시 해당 프로젝트의 대시보드 화면으로 이동(구현 예정)
- 사내 전체 프로젝트 목록은 검색이 가능함(검색조건: 프로젝트명, 팀명)
- 참여중인 프로젝트는 '참여중'을 띄우고, 그 외의 프로젝트는 '보기'버튼 활성화 및 완료된 프로젝트 표시
(추후 권한에 따라 '보기'버튼 비활성화/활성화 예정)
Key Point
@click="함수명()" : 클릭하면 해당 함수 호출
@keyup.enter="함수명()" : 엔터를 누르면 해당 함수 호출 (검색창에 사용하면 유용)
Back 단
DAO / Mapper(SQL) / Service / Controller
- DAO (Interface)
import java.util.List;
import org.springframework.stereotype.Repository;
import pms.vo.ProjectVO;
/**
* 프로젝트 DAO
*
* */
@Repository
public interface ProjectDAO {
// 참여중인 프로젝트 정보
public List<ProjectVO> projList(int userSn);
// 모든 프로젝트 정보
public List<ProjectVO> allProjList(ProjectVO project);
// 모든 프로젝트 개수
public int allProjCnt(ProjectVO project);
}
- Mapper (SQL)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="pms.dao.ProjectDAO">
<!-- 참여중인 프로젝트 -->
<resultMap type="project" id="projList"/>
<select id="projList" parameterType="int" resultMap="projList">
SELECT
p.project_sn AS projectSn,
p.TEAM_SN AS teamSn,
p.PROJECT_NM AS projectNm,
p.PROJECT_CTN AS projectCtn,
to_char(p.PROJECT_BEG_DT, 'yyyy-mm-dd') AS projectBegDt,
to_char(p.PROJECT_END_DT, 'yyyy-mm-dd') AS projectEndDt,
p.PROJECT_COMPLETE_YN AS projectCompleteYn,
(
SELECT count(*)
FROM PROJECT p1, TEAM t1, "USER" u1
WHERE 1=1
AND p1.TEAM_SN = t1.TEAM_SN
AND t1.TEAM_SN = u1.TEAM_SN
AND p.PROJECT_SN = p1.PROJECT_SN
) AS personCnt,
(
SELECT u2.USER_NM
FROM PROJECT p2, TEAM t2, "USER" u2, GRADE g
WHERE 1=1
AND p2.TEAM_SN = t2.TEAM_SN
AND t2.TEAM_SN = u2.TEAM_SN
AND u2.GRADE_SN = g.GRADE_SN
AND p2.PROJECT_SN = p.PROJECT_SN
AND g.GRADE_SN = 666
) AS pmNm
FROM PROJECT p, "USER" u
WHERE 1=1
AND p.TEAM_SN = u.TEAM_SN
AND p.PROJECT_COMPLETE_YN = 'N'
AND u.USER_SN = #{userSn}
</select>
<!-- 전체 프로젝트 -->
<resultMap type="project" id="allProjList"/>
<select id="allProjList" parameterType="project" resultMap="allProjList">
SELECT
p.project_sn AS projectSn,
p.TEAM_SN AS teamSn,
p.PROJECT_NM AS projectNm,
p.PROJECT_CTN AS projectCtn,
to_char(p.PROJECT_BEG_DT, 'yyyy-mm-dd') AS projectBegDt,
to_char(p.PROJECT_END_DT, 'yyyy-mm-dd') AS projectEndDt,
p.PROJECT_COMPLETE_YN AS projectCompleteYn,
(
SELECT count(*)
FROM PROJECT p1, TEAM t1, "USER" u1
WHERE 1=1
AND p1.TEAM_SN = t1.TEAM_SN
AND t1.TEAM_SN = u1.TEAM_SN
AND p.PROJECT_SN = p1.PROJECT_SN
) AS personCnt,
(
SELECT u2.USER_NM
FROM PROJECT p2, TEAM t2, "USER" u2, GRADE g
WHERE 1=1
AND p2.TEAM_SN = t2.TEAM_SN
AND t2.TEAM_SN = u2.TEAM_SN
AND u2.GRADE_SN = g.GRADE_SN
AND p2.PROJECT_SN = p.PROJECT_SN
AND g.GRADE_SN = 666
) AS pmNm
FROM PROJECT p, TEAM t
WHERE 1=1
<if test="srhKeywordType != '' and srhKeywordType != null">
<choose>
<when test='srhKeywordType == "projectNm"'>
AND p.PROJECT_NM LIKE '%'||#{srhKeyword}||'%'
</when>
<when test='srhKeywordType == "teamNm"'>
AND t.TEAM_NM LIKE '%'||#{srhKeyword}||'%'
</when>
</choose>
</if>
AND p.TEAM_SN = t.TEAM_SN
</select>
<!-- 전체 프로젝트 개수 -->
<select id="allProjCnt" parameterType="project" resultType="int">
SELECT
COUNT(*) as totCount
FROM PROJECT p, TEAM t
WHERE 1=1
<if test="srhKeywordType != '' and srhKeywordType != null">
<choose>
<when test='srhKeywordType == "projectNm"'>
AND p.PROJECT_NM LIKE '%'||#{srhKeyword}||'%'
</when>
<when test='srhKeywordType == "teamNm"'>
AND t.TEAM_NM LIKE '%'||#{srhKeyword}||'%'
</when>
</choose>
</if>
AND p.TEAM_SN = t.TEAM_SN
</select>
</mapper>
서브쿼리 결과 변수인 personCnt, pmNm 등은 DB에 저장된 컬럼이 아니다.
객체에 담을 수 있게 VO에만 선언.
ERD 설계 는 아래 글 참고(작성시점 이후로 수정되었으나 글은 수정되지 않음. 전반적인 개요정도만 확인)
https://heisely93.tistory.com/entry/PMS-ERD-%EC%84%A4%EA%B3%84
[PMS] ERD 설계
1. 하나의 팀에 여러 명의 사용자 > 팀1 : 사용자多 1-1. 한 명의 사람이 한 팀만 가질 수 있어서 헷갈릴 수 있으나, 사용자 일련번호가 pk이므로 각각의 사용자별로 팀을 설정해 주면 됨 1-2.
heisely93.tistory.com
- Service
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import pms.dao.ProjectDAO;
import pms.vo.ProjectVO;
@Service
public class ProjectService {
@Autowired(required = false)
private ProjectDAO dao;
// 참여중인 프로젝트 정보
public Object projList(int userSn) {
List<ProjectVO> list = dao.projList(userSn);
Map<String, Object> result = new HashMap<String, Object>();
result.put("list", list);
return result;
}
// 모든 프로젝트 정보
public Object allProjList(ProjectVO project) {
List<ProjectVO> allList = dao.allProjList(project);
int totCount = dao.allProjCnt(project);
Map<String, Object> result = new HashMap<String, Object>();
result.put("allList", allList);
result.put("totCount", totCount);
return result;
}
}
- Controller
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import pms.dao.ProjectDAO;
import pms.vo.ProjectVO;
@Service
public class ProjectService {
@Autowired(required = false)
private ProjectDAO dao;
// 참여중인 프로젝트 정보
public Object projList(int userSn) {
List<ProjectVO> list = dao.projList(userSn);
Map<String, Object> result = new HashMap<String, Object>();
result.put("list", list);
return result;
}
// 모든 프로젝트 정보
public Object allProjList(ProjectVO project) {
List<ProjectVO> allList = dao.allProjList(project);
int totCount = dao.allProjCnt(project);
Map<String, Object> result = new HashMap<String, Object>();
result.put("allList", allList);
result.put("totCount", totCount);
return result;
}
}
Front 단
instance / components / jsp
- projectInfo.js (Vue Instance) - el 설정 및 components들의 초기화 함수 호출
/**
* project info instance vue
*/
var app = window.app || {};
app.components = app.components || {};
// instance
$(document).ready(function(){
app.components.projectInfo = new Vue({
el : '.projectInfo',
data : {
},
// components : { // 굳이 명시 안 해줘도 됨!
// 'project-list' : app.components.projList,
// 'all-project-list' : app.components.allProjList
// },
mounted() {
this.init();
},
methods : {
init() {
this.$refs.projList.init();
this.$refs.allProjList.init();
},
show() {
$(this.$el).show();
},
hide() {
$(this.$el).hide();
}
}
})
});
- project_info.jsp - 가장 바깥 껍데기
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" import="java.util.*"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>pmsPrj</title>
<%@include file="/WEB-INF/pmsPrj/jsp/main/template/common_lib.jsp" %>
<!-- 이 부분이 중요! -->
<script type="text/javascript" src="/pmsProject/pms/js/project/proj/components/allProjList.js"></script>
<script type="text/javascript" src="/pmsProject/pms/js/project/proj/components/projList.js"></script>
<script type="module" src="/pmsProject/pms/js/project/proj/projectInfo.js"></script><!-- vue instance -->
</head>
<body class="hold-transition sidebar-mini layout-fixed">
<!-- header와 footer는 지우고 업로드함 -->
<div class="wrapper">
<!-- Content Body -->
<section class="content">
<div class="container-fluid">
<div class="row">
<div class="col-12">
<div class="card projectInfo">
<div class="card-header">
<h2>Project Info</h2>
</div>
<div class="card-body">
<!-- 참여중인 프로젝트 정보 -->
<%@include file="/WEB-INF/pmsPrj/jsp/proj/proj/components/proj_list.jsp" %>
<!-- 모든 프로젝트 리스트 // 페이징 필요 -->
<%@include file="/WEB-INF/pmsPrj/jsp/proj/proj/components/all_proj_list.jsp" %>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- /.Content Body -->
</div>
</body>
</html>
- projList.js (Vue Components 1)
/**
* projcet list components (참여중인 프로젝트)
*/
var app = window.app || {};
app.components = app.components || {};
$(document).ready(function(){
app.components.projList = Vue.component('project-list', {
props : [],
data : function(){
return {
list : [],
userSn : ''
}
},
methods : {
init() {
this.list = [];
this.userSn = '999';
this.getList();
},
getList(){
const self = this;
const formData = new FormData();
formData.append('userSn', self.userSn);
// 서버통신
axios.post('/pmsProject/project/getProjList.do', formData).then(function(result){
self.list = result.data.list;
});
},
goDashboard(list) {
alert('대시보드 이동 준비중\n' + list.projectSn);
},
show() {
$(this.$el).show();
},
hide() {
$(this.$el).hide();
}
}
});
});
- proj_list.jsp - components명으로 감싸고(inline-template 및 refs 선언), div로 한 번 더 감싼 상태에서 작성
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" import="java.util.*"%>
<project-list inline-template ref='projList'>
<div>
<div class="card-header">
<h2 style="color:blue;">참여중인 프로젝트</h2>
</div>
<div class="card-body">
<div v-for="list in list">
<table class="table table-bordered table-hover">
<tr>
<th colspan="2" @click="goDashboard(list)">{{list.projectNm}} (클릭 시 대시보드로 이동하게 수정예정)</th>
</tr>
<tr>
<td colspan="2">{{list.projectCtn}}</td>
</tr>
<tr>
<td>프로젝트 참여기간</td>
<td>{{list.projectBegDt}} <span>~</span> {{list.projectEndDt}}</td>
</tr>
<tr>
<td>PM : {{list.pmNm}} </td>
<td>참여인원 : {{list.personCnt}}명</td>
</tr>
</table>
</div>
</div>
</div>
</project-list>
- allProjList.js (Vue Components 2)
/**
* all project list components (모든 프로젝트 리스트)
*/
var app = window.app || {};
app.components = app.components || {};
$(document).ready(function(){
app.components.allProjList = Vue.component('all-project-list', {
props : [],
data : function(){
return {
allList : [],
srhKeyword : '',
srhKeywordType : 'projectNm',
totCount : 0
}
},
methods : {
init() {
this.totCount = 0;
this.allList = [];
this.srhKeyword = '';
this.srhKeywordType = 'projectNm';
this.getAllProject();
},
getAllProject(){
const self = this;
const formData = new FormData();
formData.append('srhKeyword', self.srhKeyword);
formData.append('srhKeywordType', self.srhKeywordType);
// 서버통신
axios.post('/pmsProject/project/getAllProj.do', formData).then(function(result){
self.allList = result.data.allList;
self.totCount = result.data.totCount;
});
},
show() {
$(this.$el).show();
},
hide() {
$(this.$el).hide();
}
}
});
});
- all_proj_list.jsp - components명으로 감싸고(inline-template 및 refs 선언), div로 한 번 더 감싼 상태에서 작성
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" import="java.util.*"%>
<all-project-list inline-template ref='allProjList'>
<div>
<div class="card-header">
<h2 style="color:blue;">전체 프로젝트<span>(전체 {{totCount}}건)</span></h2>
<!-- 검색조건 -->
<select v-model="srhKeywordType" id="srhKeywordType">
<option value='projectNm'>프로젝트명</option>
<option value='teamNm'>팀명</option>
</select>
<input type="text" v-model="srhKeyword" id="srhKeyword" @keyup.enter="getAllProject()">
<button @click="getAllProject()">검색</button>
<button @click="init()">초기화</button>
</div>
<div class="card-body">
<div v-for="list in allList">
<table class="table table-bordered table-hover">
<tr>
<th colspan="3">{{list.projectNm}}</th>
</tr>
<tr>
<td colspan="3">{{list.projectCtn}}</td>
</tr>
<tr>
<td>프로젝트 참여기간</td>
<td colspan="2">{{list.projectBegDt}} <span>~</span> {{list.projectEndDt}}</td>
</tr>
<tr>
<td>PM : {{list.pmNm}} </td>
<td>참여인원 : {{list.personCnt}}명</td>
<td>
<button v-if="list.projectCompleteYn == 'Y'" class="fr">완료된 프로젝트</button>
<button class="fr" @click="$parent.$refs.projList.goDashboard(list)">{{$parent.$refs.projList.list[0].projectSn == list.projectSn ? '참여중' : '보기'}}</button>
</td>
</tr>
</table>
</div>
</div>
</div>
</all-project-list>
실행화면
css 미적용. 단순 기능 확인
End.
heisely's 괴발개발 개발일지
728x90
반응형
'Programming > 구현' 카테고리의 다른 글
[구현] projectSn 세션처리 (0) | 2022.04.19 |
---|---|
[구현] 사용자 정보(feat. session) (0) | 2022.04.07 |
[구현] 로그인 화면 구현 (0) | 2022.04.07 |
[구현] ERD 설계 (0) | 2022.02.04 |
[구현] 분석단계 - 준비 (0) | 2022.01.24 |