Commit 0206c002e2e1a6eda0671ade974f621e3372b075
1 parent
5b5ab7e5
2024-04-15
Showing
42 changed files
with
1903 additions
and
1218 deletions
Show diff stats
prestige-vue-4.0.0/src/layout/AppFooter.vue
1 | 1 | <template> |
2 | 2 | <div class="layout-footer"> |
3 | 3 | <div class="grid"> |
4 | - <div class="col-12 md:col-6 lg:col-3"> | |
5 | - <span class="logo">Prestige</span> | |
6 | - <p>PrimeVue Premium Template</p> | |
7 | - </div> | |
8 | - <div class="col-12 md:col-6 lg:col-3"> | |
9 | - <span>LATEST TEMPLATES</span> | |
10 | - <div class="grid templates"> | |
11 | - <ul> | |
12 | - <li><a href="https://primefaces.org/prestige-vue/" target="_blank" rel="noopener noreferrer">Prestige</a></li> | |
13 | - <li><a href="https://primefaces.org/roma-vue/" target="_blank" rel="noopener noreferrer">Roma</a></li> | |
14 | - <li><a href="https://primefaces.org/babylon-vue/" target="_blank" rel="noopener noreferrer">Babylon</a></li> | |
15 | - <li><a href="https://primefaces.org/ultima-vue/" target="_blank" rel="noopener noreferrer">Ultima</a></li> | |
16 | - <li><a href="https://primefaces.org/diamond-vue/" target="_blank" rel="noopener noreferrer">Diamond</a></li> | |
17 | - </ul> | |
18 | - <ul> | |
19 | - <li><a href="https://primefaces.org/freya-vue/" target="_blank" rel="noopener noreferrer">Freya</a></li> | |
20 | - <li><a href="https://primefaces.org/apollo-vue/" target="_blank" rel="noopener noreferrer">Apollo</a></li> | |
21 | - <li><a href="https://primefaces.org/serenity-vue/" target="_blank" rel="noopener noreferrer">Serenity</a></li> | |
22 | - <li><a href="https://primefaces.org/avalon-vue/" target="_blank" rel="noopener noreferrer">Avalon</a></li> | |
23 | - <li><a href="https://primefaces.org/sapphire-vue/" target="_blank" rel="noopener noreferrer">Sapphire</a></li> | |
24 | - </ul> | |
25 | - </div> | |
26 | - </div> | |
27 | - <div class="col-12 md:col-6 lg:col-3"> | |
28 | - <span>DEMOS</span> | |
29 | - <div class="grid"> | |
30 | - <ul class="links"> | |
31 | - <li><a href="https://primefaces.org/primevue/" target="_blank" rel="noopener noreferrer">PrimeVue</a></li> | |
32 | - <li><a href="https://primefaces.org/primeng/" target="_blank" rel="noopener noreferrer">PrimeNG</a></li> | |
33 | - <li><a href="https://primefaces.org/primereact/" target="_blank" rel="noopener noreferrer">PrimeReact</a></li> | |
34 | - </ul> | |
35 | - </div> | |
4 | + <div class="col-12 md:col-12 lg:col-12"> | |
5 | + <span class="logo flex align-items-center justify-content-center">(주)대유씨엔에이</span> | |
6 | + <p class="flex align-items-center justify-content-center">서울특별시 성동구 성수일로 99 서울숲AK밸리 303호</p> | |
36 | 7 | </div> |
37 | 8 | </div> |
38 | 9 | </div> | ... | ... |
prestige-vue-4.0.0/src/layout/AppTopbar.vue
... | ... | @@ -24,24 +24,6 @@ |
24 | 24 | <div class="layout-quickmenu-tooltip-text">{{ sampleTitle }}</div> |
25 | 25 | </div> |
26 | 26 | </li> |
27 | - <li> | |
28 | - <a href="#" class="layout-topbar-icon"> | |
29 | - <i class="topbar-icon pi pi-chart-bar"></i> | |
30 | - </a> | |
31 | - <div class="layout-quickmenu-tooltip"> | |
32 | - <div class="layout-quickmenu-tooltip-arrow"></div> | |
33 | - <div class="layout-quickmenu-tooltip-text">Statistics</div> | |
34 | - </div> | |
35 | - </li> | |
36 | - <li> | |
37 | - <router-link to="/logout"> | |
38 | - <i class="topbar-icon pi pi-sign-out"></i> | |
39 | - </router-link> | |
40 | - <div class="layout-quickmenu-tooltip"> | |
41 | - <div class="layout-quickmenu-tooltip-arrow"></div> | |
42 | - <div class="layout-quickmenu-tooltip-text">Sign Out</div> | |
43 | - </div> | |
44 | - </li> | |
45 | 27 | </ul> |
46 | 28 | </transition> |
47 | 29 | </li> |
... | ... | @@ -72,24 +54,23 @@ |
72 | 54 | <li :class="[{ 'active-topmenuitem': activeTopbarItem === 'profile' }]" class="user-profile" @click="$emit('topbar-item-click', { originalEvent: $event, item: 'profile' })"> |
73 | 55 | <a href="#"> |
74 | 56 | <div class="user-profile-info profile-link"> |
75 | - <span class="user-profile-name">Ava Gregoraci</span> | |
76 | - <span class="user-profile-role">Design Ops</span> | |
57 | + <span class="user-profile-name">{{ store.getters.getLoginId }}</span> | |
58 | + <span class="user-profile-role">{{ store.getters.getCompanyName }}</span> | |
77 | 59 | </div> |
78 | - <img class="logo" src="/layout/images/avatar/avatar-ava.jpg" alt="prestige-layout" /> | |
60 | + <i class="pi pi-android" style="font-size: 3.5rem"></i> | |
79 | 61 | </a> |
80 | 62 | <transition name="layout-submenu-container"> |
81 | 63 | <ul class="fadeInDown" v-show="activeTopbarItem === 'profile'"> |
82 | - <li class="profile-detail"> | |
83 | - <div class="user-profile-info"> | |
84 | - <img class="logo" src="/layout/images/avatar/avatar-ava.jpg" alt="prestige-layout" /> | |
85 | - <div class="profile-info"> | |
86 | - <span class="user-profile-name">Ava Gregoraci</span> | |
87 | - <span class="user-profile-role">Design Ops</span> | |
88 | - </div> | |
64 | + <li> | |
65 | + <router-link to="/logout"> | |
89 | 66 | <a href="#" class="profile-detail-icon"> |
90 | 67 | <i class="pi pi-sign-out"></i> |
68 | + <div class="menu-text"> | |
69 | + <span class="menu-title">Logout</span> | |
70 | + <span class="menu-subtitle">Logout from current User</span> | |
71 | + </div> | |
91 | 72 | </a> |
92 | - </div> | |
73 | + </router-link> | |
93 | 74 | </li> |
94 | 75 | <li> |
95 | 76 | <a href="#"> |
... | ... | @@ -112,30 +93,6 @@ |
112 | 93 | <i class="right-icon pi pi-angle-right"></i> |
113 | 94 | </a> |
114 | 95 | </li> |
115 | - <li> | |
116 | - <a href="#"> | |
117 | - <i class="pi pi-inbox"></i> | |
118 | - <div class="menu-text"> | |
119 | - <span class="menu-title">Messages</span> | |
120 | - <span class="menu-subtitle" | |
121 | - >You have a | |
122 | - <div class="blue">3 new</div> | |
123 | - messages</span | |
124 | - > | |
125 | - </div> | |
126 | - <i class="right-icon pi pi-angle-right"></i> | |
127 | - </a> | |
128 | - </li> | |
129 | - <li> | |
130 | - <a href="#"> | |
131 | - <i class="pi pi-globe"></i> | |
132 | - <div class="menu-text"> | |
133 | - <span class="menu-title">Notification</span> | |
134 | - <span class="menu-subtitle">No new notification</span> | |
135 | - </div> | |
136 | - <i class="right-icon pi pi-angle-right"></i> | |
137 | - </a> | |
138 | - </li> | |
139 | 96 | </ul> |
140 | 97 | </transition> |
141 | 98 | </li> | ... | ... |
prestige-vue-4.0.0/src/main.js
... | ... | @@ -213,7 +213,8 @@ app.component('BlockViewer', BlockViewer); |
213 | 213 | |
214 | 214 | //ag-grid |
215 | 215 | import "ag-grid-community/styles//ag-grid.css"; |
216 | -import "ag-grid-community/styles//ag-theme-quartz.css"; | |
216 | +// import "ag-grid-community/styles//ag-theme-quartz.css"; | |
217 | +import "ag-grid-community/styles//ag-theme-balham.css"; | |
217 | 218 | import { AgGridVue } from "ag-grid-vue3"; |
218 | 219 | app.component('AgGridVue', AgGridVue); |
219 | 220 | ... | ... |
prestige-vue-4.0.0/src/router/index.js
... | ... | @@ -19,47 +19,6 @@ const routes = [ |
19 | 19 | }, |
20 | 20 | }, |
21 | 21 | { |
22 | - path: '/basic1', | |
23 | - name: 'basic1', | |
24 | - component: () => import('@/views/basic/Basic1.vue'), | |
25 | - meta: { | |
26 | - breadcrumb: [{ parent: 'Basic', label: 'Basic1' }], | |
27 | - }, | |
28 | - }, | |
29 | - { | |
30 | - path: '/basic2', | |
31 | - name: 'basic2', | |
32 | - component: () => import('@/views/basic/Basic2.vue'), | |
33 | - meta: { | |
34 | - breadcrumb: [{ parent: 'Basic', label: 'Basic2' }], | |
35 | - }, | |
36 | - }, | |
37 | - { | |
38 | - path: '/basic3', | |
39 | - name: 'basic3', | |
40 | - component: () => import('@/views/basic/Basic3.vue'), | |
41 | - meta: { | |
42 | - breadcrumb: [{ parent: 'Basic', label: 'Basic3' }], | |
43 | - }, | |
44 | - }, | |
45 | - { | |
46 | - path: '/basic4', | |
47 | - name: 'basic4', | |
48 | - component: () => import('@/views/basic/Basic4.vue'), | |
49 | - meta: { | |
50 | - breadcrumb: [{ parent: 'Basic', label: 'Basic4' }], | |
51 | - }, | |
52 | - }, | |
53 | - { | |
54 | - path: '/basic5', | |
55 | - name: 'basic5', | |
56 | - component: () => import('@/views/basic/Basic5.vue'), | |
57 | - meta: { | |
58 | - breadcrumb: [{ parent: 'Basic', label: 'Basic5' }], | |
59 | - }, | |
60 | - }, | |
61 | - | |
62 | - { | |
63 | 22 | path: '/systemCode', |
64 | 23 | name: 'systemCode', |
65 | 24 | component: () => import('@/views/system/SystemCode.vue'), |
... | ... | @@ -76,19 +35,11 @@ const routes = [ |
76 | 35 | }, |
77 | 36 | }, |
78 | 37 | { |
79 | - path: '/authority', | |
80 | - name: 'authority', | |
81 | - component: () => import('@/views/system/Authority.vue'), | |
82 | - meta: { | |
83 | - breadcrumb: [{ parent: 'System', label: 'Authority' }], | |
84 | - }, | |
85 | - }, | |
86 | - { | |
87 | - path: '/messages', | |
88 | - name: 'messages', | |
89 | - component: () => import('@/views/system/Messages.vue'), | |
38 | + path: '/userAuthority', | |
39 | + name: 'userAuthority', | |
40 | + component: () => import('@/views/system/UserAuthority.vue'), | |
90 | 41 | meta: { |
91 | - breadcrumb: [{ parent: 'System', label: 'Messages' }], | |
42 | + breadcrumb: [{ parent: 'System', label: 'User Authority' }], | |
92 | 43 | }, |
93 | 44 | }, |
94 | 45 | ], | ... | ... |
1 | +const agGridService = { | |
2 | + /** | |
3 | + * 그리드의 데이타를 전체/변경된 것을 가져온다 | |
4 | + * @param {*} pGridApi | |
5 | + * @param {*} pOnlyUpdated | |
6 | + */ | |
7 | + agGridGetData: (pGridApi, pOnlyUpdated) => { | |
8 | + console.log("agGridGetData"); | |
9 | + let updatedData = []; | |
10 | + let sRowStatus = "N,U,D"; | |
11 | + pGridApi.value.forEachNode(rec => { | |
12 | + if (pOnlyUpdated) { | |
13 | + if (sRowStatus.indexOf(rec.data.rowStatus) != -1) { | |
14 | + updatedData.push(rec.data); | |
15 | + } | |
16 | + } else { | |
17 | + updatedData.push(rec.data); | |
18 | + } | |
19 | + }); | |
20 | + return updatedData; | |
21 | + }, | |
22 | + | |
23 | + /** | |
24 | + * 새로운행울 추가하고 해당 결과에 대한 정보를 배열로 돌려준다 | |
25 | + * @param {*} pGridApi | |
26 | + * @returns | |
27 | + */ | |
28 | + agGridAddRow: (pGridApi, pRowCnt, pIdx) => { | |
29 | + console.log("agGridAddRow"); | |
30 | + let newRows = []; | |
31 | + for (let i=0; i<pRowCnt; i++) { | |
32 | + let newData = { | |
33 | + rowStatus: "N" | |
34 | + }; | |
35 | + newRows.push(newData); | |
36 | + } | |
37 | + const res = pGridApi.value.applyTransaction({ | |
38 | + addIndex: pIdx, | |
39 | + add: newRows | |
40 | + }); | |
41 | + return res; | |
42 | + }, | |
43 | + | |
44 | + /** | |
45 | + * 레코드를 삭제처리하고 결과를 돌려준다 | |
46 | + * @param {*} pGridApi | |
47 | + * @returns | |
48 | + */ | |
49 | + agGridDelRow: (pGridApi, pSelectedNodes) => { | |
50 | + console.log("agGridDelRow"); | |
51 | + | |
52 | + let removeNodes = []; | |
53 | + let updateNodes = []; | |
54 | + pSelectedNodes.map( | |
55 | + curNode => { | |
56 | + if (curNode.data.rowStatus === "N") { | |
57 | + removeNodes.push(curNode.data); | |
58 | + } else { | |
59 | + curNode.data.rowStatus = "D"; | |
60 | + updateNodes.push(curNode.data); | |
61 | + } | |
62 | + } | |
63 | + ) | |
64 | + | |
65 | + const res = pGridApi.value.applyTransaction({ | |
66 | + remove: removeNodes, | |
67 | + update: updateNodes | |
68 | + }); | |
69 | + return res; | |
70 | + }, | |
71 | + | |
72 | + /** | |
73 | + * 레코드의 변경상태를 초기화 한다(신규레코드는 제외) | |
74 | + * @param {*} pGridApi | |
75 | + * @returns | |
76 | + */ | |
77 | + agGridEraseStatusRow: (pGridApi) => { | |
78 | + console.log("agGridEraseStatusRow"); | |
79 | + const selectedRows = pGridApi.value.getSelectedRows(); | |
80 | + | |
81 | + if ("U,D".indexOf(selectedRows[0].rowStatus) > -1) { | |
82 | + selectedRows.map(curRec => curRec.rowStatus = ""); | |
83 | + const res = gridApi.value.applyTransaction({ | |
84 | + update: selectedRows | |
85 | + }); | |
86 | + return res; | |
87 | + } | |
88 | + | |
89 | + return res; | |
90 | + }, | |
91 | + | |
92 | + /** | |
93 | + * 셀변경시 상태 처리 | |
94 | + * @param {*} pGridApi | |
95 | + * @returns | |
96 | + */ | |
97 | + agGridChangeStatusRow: (pGridApi, pEvent) => { | |
98 | + console.log("onCellValueChanged"); | |
99 | + if ('N,D'.indexOf(pEvent.data.rowStatus) == -1) pEvent.data.rowStatus = "U"; | |
100 | + const res = pGridApi.value.applyTransaction({ | |
101 | + update: [pEvent.data] | |
102 | + }); | |
103 | + | |
104 | + return res; | |
105 | + } | |
106 | +} | |
107 | +export default agGridService; | |
0 | 108 | \ No newline at end of file | ... | ... |
prestige-vue-4.0.0/src/service/MenuDataService.js
... | ... | @@ -7,11 +7,6 @@ export let menu = |
7 | 7 | icon: 'pi pi-fw pi-wrench', |
8 | 8 | ord: 2, |
9 | 9 | items: [ |
10 | - { label: 'Basic1', icon: 'pi pi-fw pi-id-card', to: '/basic1', authrity: 'CURD', ord: 1}, | |
11 | - { label: 'Basic2', icon: 'pi pi-fw pi-check-square', to: '/basic2', authrity: 'CURD', ord: 2 }, | |
12 | - { label: 'Basic3', icon: 'pi pi-fw pi-bookmark', to: '/basic3', authrity: 'CURD', ord: 3 }, | |
13 | - { label: 'Basic4', icon: 'pi pi-fw pi-exclamation-circle', to: '/basic4', authrity: 'CURD', ord: 4 }, | |
14 | - { label: 'Basic5', icon: 'pi pi-fw pi-mobile', to: '/basic5', class: 'rotated-icon', authrity: 'CURD', ord: 5 }, | |
15 | 10 | ], |
16 | 11 | }, |
17 | 12 | { |
... | ... | @@ -22,8 +17,7 @@ export let menu = |
22 | 17 | items: [ |
23 | 18 | { label: 'System Code', icon: 'pi pi-fw pi-list', to: '/systemCode', authrity: 'CURD', ord: 1 }, |
24 | 19 | { label: 'User', icon: 'pi pi-fw pi-users', to: '/user', authrity: 'CURD', ord: 1 }, |
25 | - { label: 'Authority', icon: 'pi pi-fw pi-id-card', to: '/authority', authrity: 'CURD', ord: 1 }, | |
26 | - { label: 'Messages', icon: 'pi pi-fw pi-bars', to: '/messages', authrity: 'CURD', ord: 1 }, | |
20 | + { label: 'Authority', icon: 'pi pi-fw pi-id-card', to: '/userAuthority', authrity: 'CURD', ord: 1 }, | |
27 | 21 | ], |
28 | 22 | }, |
29 | 23 | ]; | ... | ... |
prestige-vue-4.0.0/src/service/axios.js
... | ... | @@ -27,7 +27,7 @@ axios.interceptors.response.use(function (response) { |
27 | 27 | // Do something with response error |
28 | 28 | console.log('에러일 경우', error.config); |
29 | 29 | const errorAPI = error.config; |
30 | - if((error.code != null || error.response.data.status===401) && errorAPI.retry===undefined){ | |
30 | + if((error.response.status===401 || error.response.status===405) && errorAPI.retry===undefined){ | |
31 | 31 | errorAPI.retry = true; |
32 | 32 | console.log('토큰이 이상한 오류일 경우'); |
33 | 33 | await refreshToken(); | ... | ... |
prestige-vue-4.0.0/src/service/login.js
... | ... | @@ -21,6 +21,8 @@ export async function loginForm(loginInfo, store){ |
21 | 21 | if (response.status == '200') { |
22 | 22 | console.log('store = ' + store); |
23 | 23 | store.commit("setLogined", true); |
24 | + store.commit("setCompanyName", "(주)대유씨엔에이"); | |
25 | + store.commit("setLoginId", loginInfo.username); | |
24 | 26 | } |
25 | 27 | return response.status; |
26 | 28 | }catch(err){ |
... | ... | @@ -47,6 +49,8 @@ export async function logoutForm(store){ |
47 | 49 | console.log("refresh_token=" + VueCookies.get('refresh_token')); |
48 | 50 | |
49 | 51 | store.commit("setLogined", false); |
52 | + store.commit("setCompanyName", null); | |
53 | + store.commit("setLoginId", null); | |
50 | 54 | |
51 | 55 | console.log("Logout Completed"); |
52 | 56 | } | ... | ... |
prestige-vue-4.0.0/src/store/index.js
... | ... | @@ -3,10 +3,18 @@ import createPersistedState from 'vuex-persistedstate' |
3 | 3 | |
4 | 4 | export default createStore({ |
5 | 5 | state: { |
6 | + companyName : null, | |
7 | + loginId : null, | |
6 | 8 | logined : false, |
7 | 9 | samplePages : false, |
8 | 10 | }, |
9 | 11 | getters: { |
12 | + getCompanyName(state){ | |
13 | + return state.companyName; | |
14 | + }, | |
15 | + getLoginId(state){ | |
16 | + return state.loginId; | |
17 | + }, | |
10 | 18 | getLogined(state){ |
11 | 19 | return state.logined; |
12 | 20 | }, |
... | ... | @@ -15,6 +23,12 @@ export default createStore({ |
15 | 23 | } |
16 | 24 | }, |
17 | 25 | mutations: { |
26 | + setCompanyName(state, companyName){ | |
27 | + state.companyName = companyName; | |
28 | + }, | |
29 | + setLoginId(state, loginId){ | |
30 | + state.loginId = loginId; | |
31 | + }, | |
18 | 32 | setLogined(state, logined){ |
19 | 33 | state.logined = logined; |
20 | 34 | }, | ... | ... |
prestige-vue-4.0.0/src/views/basic/Basic1.vue deleted
1 | -<script setup> | |
2 | -import { onMounted, ref } from 'vue'; | |
3 | - | |
4 | -class CustomTextEditor { | |
5 | - constructor(props) { | |
6 | - const el = document.createElement('input'); | |
7 | - const { maxLength } = props.columnInfo.editor.options; | |
8 | - | |
9 | - el.type = 'text'; | |
10 | - el.maxLength = maxLength; | |
11 | - el.value = String(props.value); | |
12 | - | |
13 | - this.el = el; | |
14 | - } | |
15 | - | |
16 | - getElement() { | |
17 | - return this.el; | |
18 | - } | |
19 | - | |
20 | - getValue() { | |
21 | - return this.el.value; | |
22 | - } | |
23 | - | |
24 | - mounted() { | |
25 | - this.el.select(); | |
26 | - } | |
27 | -} | |
28 | - | |
29 | -const data = ref([ | |
30 | - { | |
31 | - id: '10012', | |
32 | - city: 'Seoul', | |
33 | - country: 'South Korea', | |
34 | - }, | |
35 | - { | |
36 | - id: '10013', | |
37 | - city: 'Tokyo', | |
38 | - country: 'Japan', | |
39 | - }, | |
40 | - { | |
41 | - id: '10014', | |
42 | - city: 'London', | |
43 | - country: 'England', | |
44 | - }, | |
45 | - { | |
46 | - id: '10015', | |
47 | - city: 'Ljubljana', | |
48 | - country: 'Slovenia', | |
49 | - }, | |
50 | - { | |
51 | - id: '10016', | |
52 | - city: 'Reykjavik', | |
53 | - country: 'Iceland', | |
54 | - }, | |
55 | -]); | |
56 | - | |
57 | -const columns = ref([ | |
58 | - { | |
59 | - header: 'ID', | |
60 | - name: 'id', | |
61 | - editor: { | |
62 | - type: CustomTextEditor, | |
63 | - options: { | |
64 | - maxLength: 10, | |
65 | - }, | |
66 | - }, | |
67 | - }, | |
68 | - { | |
69 | - header: 'CITY', | |
70 | - name: 'city', | |
71 | - editor: 'text', | |
72 | - }, | |
73 | - { | |
74 | - header: 'COUNTRY', | |
75 | - name: 'country', | |
76 | - formatter: 'listItemText', | |
77 | - editor: { | |
78 | - type: 'select', | |
79 | - options: { | |
80 | - listItems: [ | |
81 | - { text: 'South Korea', value: 'South Korea' }, | |
82 | - { text: 'England', value: 'England' }, | |
83 | - { text: 'Japan', value: 'Japan' }, | |
84 | - { text: 'Slovenia', value: 'Slovenia' }, | |
85 | - ], | |
86 | - }, | |
87 | - }, | |
88 | - }, | |
89 | -]); | |
90 | - | |
91 | -const GridTable = ref(); | |
92 | - | |
93 | -onMounted(() => { | |
94 | - const grid = GridTable.value; | |
95 | - const optPreset = { | |
96 | - selection: { | |
97 | - background: '#4daaf9', | |
98 | - border: '#004082', | |
99 | - }, | |
100 | - scrollbar: { | |
101 | - background: '#f5f5f5', | |
102 | - thumb: '#d9d9d9', | |
103 | - active: '#c1c1c1', | |
104 | - }, | |
105 | - row: { | |
106 | - even: { | |
107 | - background: '#f3ffe3', | |
108 | - }, | |
109 | - hover: { | |
110 | - background: '#ccc', | |
111 | - }, | |
112 | - }, | |
113 | - cell: { | |
114 | - normal: { | |
115 | - background: '#fbfbfb', | |
116 | - border: '#e0e0e0', | |
117 | - showVerticalBorder: true, | |
118 | - }, | |
119 | - header: { | |
120 | - background: '#eee', | |
121 | - border: '#ccc', | |
122 | - showVerticalBorder: true, | |
123 | - }, | |
124 | - rowHeader: { | |
125 | - border: '#ccc', | |
126 | - showVerticalBorder: true, | |
127 | - }, | |
128 | - editable: { | |
129 | - background: '#fbfbfb', | |
130 | - }, | |
131 | - selectedHeader: { | |
132 | - background: '#d8d8d8', | |
133 | - }, | |
134 | - focused: { | |
135 | - border: '#418ed4', | |
136 | - }, | |
137 | - disabled: { | |
138 | - text: '#b0b0b0', | |
139 | - }, | |
140 | - }, | |
141 | - }; | |
142 | - grid?.applyTheme('striped', optPreset); | |
143 | - grid?.setLanguage('ko'); | |
144 | - // const instance = grid?.gridInstance; | |
145 | - // instance?.setWidth(500); | |
146 | - | |
147 | - //data Load | |
148 | - // const loginInfo = {}; | |
149 | - | |
150 | - // const response = getData(); | |
151 | -}); | |
152 | -</script> | |
153 | - | |
154 | -<template> | |
155 | - <div class="card"> | |
156 | - <Accordion :activeIndex="0"> | |
157 | - <AccordionTab header="Header I" class="w-full"> | |
158 | - <tui-grid ref="GridTable" :data="data" :columns="columns"> </tui-grid> | |
159 | - </AccordionTab> | |
160 | - <AccordionTab header="Header II"> | |
161 | - <p class="m-0"> | |
162 | - Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim | |
163 | - ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Consectetur, adipisci velit, sed quia non numquam eius modi. | |
164 | - </p> | |
165 | - </AccordionTab> | |
166 | - <AccordionTab header="Header III"> | |
167 | - <p class="m-0"> | |
168 | - At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa qui | |
169 | - officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus. | |
170 | - </p> | |
171 | - </AccordionTab> | |
172 | - </Accordion> | |
173 | - </div> | |
174 | -</template> |
prestige-vue-4.0.0/src/views/basic/Basic2.vue deleted
1 | -<template> | |
2 | - <div class="grid p-fluid"> | |
3 | - <div class="col-12 lg:col-6"> | |
4 | - <div class="card"> | |
5 | - <h5>Linear Chart</h5> | |
6 | - <Chart type="line" :data="lineData"></Chart> | |
7 | - </div> | |
8 | - <div class="card flex flex-column align-items-center"> | |
9 | - <h5 class="align-self-start">Pie Chart</h5> | |
10 | - <Chart type="pie" :data="pieData" style="position: relative; width: 50%"></Chart> | |
11 | - </div> | |
12 | - <div class="card flex flex-column align-items-center"> | |
13 | - <h5 class="align-self-start">Polar Area Chart</h5> | |
14 | - <Chart type="polarArea" :data="polarData" style="position: relative; width: 50%"></Chart> | |
15 | - </div> | |
16 | - </div> | |
17 | - <div class="col-12 lg:col-6"> | |
18 | - <div class="card"> | |
19 | - <h5>Bar Chart</h5> | |
20 | - <Chart type="bar" :data="barData"></Chart> | |
21 | - </div> | |
22 | - <div class="card flex flex-column align-items-center"> | |
23 | - <h5 class="align-self-start">Doughnut Chart</h5> | |
24 | - <Chart type="doughnut" :data="pieData" style="position: relative; width: 50%"></Chart> | |
25 | - </div> | |
26 | - <div class="card flex flex-column align-items-center"> | |
27 | - <h5 class="align-self-start">Radar Chart</h5> | |
28 | - <Chart type="radar" :data="radarData" style="position: relative; width: 50%"></Chart> | |
29 | - </div> | |
30 | - </div> | |
31 | - </div> | |
32 | -</template> | |
33 | - | |
34 | -<script> | |
35 | -export default { | |
36 | - data() { | |
37 | - return { | |
38 | - lineData: { | |
39 | - labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'], | |
40 | - datasets: [ | |
41 | - { | |
42 | - label: 'First Dataset', | |
43 | - data: [65, 59, 80, 81, 56, 55, 40], | |
44 | - fill: false, | |
45 | - borderColor: '#03A9F4', | |
46 | - tension: 0.4, | |
47 | - }, | |
48 | - { | |
49 | - label: 'Second Dataset', | |
50 | - data: [28, 48, 40, 19, 86, 27, 90], | |
51 | - fill: false, | |
52 | - borderColor: '#FFC107', | |
53 | - tension: 0.4, | |
54 | - }, | |
55 | - ], | |
56 | - }, | |
57 | - pieData: { | |
58 | - labels: ['A', 'B', 'C'], | |
59 | - datasets: [ | |
60 | - { | |
61 | - data: [540, 325, 702, 421], | |
62 | - backgroundColor: ['rgb(54, 162, 235)', 'rgb(255, 99, 132)', 'rgb(255, 205, 86)', 'rgb(75, 192, 192)'], | |
63 | - }, | |
64 | - ], | |
65 | - }, | |
66 | - polarData: { | |
67 | - datasets: [ | |
68 | - { | |
69 | - data: [11, 16, 7, 3], | |
70 | - backgroundColor: ['rgb(54, 162, 235)', 'rgb(255, 99, 132)', 'rgb(255, 205, 86)', 'rgb(75, 192, 192)'], | |
71 | - label: 'My dataset', | |
72 | - }, | |
73 | - ], | |
74 | - labels: ['Blue', 'Purple', 'Orange', 'Green'], | |
75 | - }, | |
76 | - barData: { | |
77 | - labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'], | |
78 | - datasets: [ | |
79 | - { | |
80 | - label: 'My First dataset', | |
81 | - backgroundColor: 'rgb(255, 99, 132)', | |
82 | - borderColor: 'rgb(255, 99, 132)', | |
83 | - data: [65, 59, 80, 81, 56, 55, 40], | |
84 | - }, | |
85 | - { | |
86 | - label: 'My Second dataset', | |
87 | - backgroundColor: 'rgb(54, 162, 235)', | |
88 | - borderColor: 'rgb(54, 162, 235)', | |
89 | - data: [28, 48, 40, 19, 86, 27, 90], | |
90 | - }, | |
91 | - ], | |
92 | - }, | |
93 | - doughnutData: { | |
94 | - labels: ['A', 'B', 'C'], | |
95 | - datasets: [ | |
96 | - { | |
97 | - data: [300, 50, 100], | |
98 | - backgroundColor: ['#FFC107', '#03A9F4', '#4CAF50'], | |
99 | - hoverBackgroundColor: ['#FFE082', '#81D4FA', '#A5D6A7'], | |
100 | - }, | |
101 | - ], | |
102 | - }, | |
103 | - radarData: { | |
104 | - labels: ['Eating', 'Drinking', 'Sleeping', 'Designing', 'Coding', 'Cycling', 'Running'], | |
105 | - datasets: [ | |
106 | - { | |
107 | - label: 'My First dataset', | |
108 | - backgroundColor: 'rgba(179,181,198,0.2)', | |
109 | - borderColor: 'rgba(179,181,198,1)', | |
110 | - pointBackgroundColor: 'rgba(179,181,198,1)', | |
111 | - pointBorderColor: '#fff', | |
112 | - pointHoverBackgroundColor: '#fff', | |
113 | - pointHoverBorderColor: 'rgba(179,181,198,1)', | |
114 | - data: [65, 59, 90, 81, 56, 55, 40], | |
115 | - }, | |
116 | - { | |
117 | - label: 'My Second dataset', | |
118 | - backgroundColor: 'rgba(255,99,132,0.2)', | |
119 | - borderColor: 'rgba(255,99,132,1)', | |
120 | - pointBackgroundColor: 'rgba(255,99,132,1)', | |
121 | - pointBorderColor: '#fff', | |
122 | - pointHoverBackgroundColor: '#fff', | |
123 | - pointHoverBorderColor: 'rgba(255,99,132,1)', | |
124 | - data: [28, 48, 40, 19, 96, 27, 100], | |
125 | - }, | |
126 | - ], | |
127 | - }, | |
128 | - }; | |
129 | - }, | |
130 | -}; | |
131 | -</script> | |
132 | - | |
133 | -<style scoped></style> |
prestige-vue-4.0.0/src/views/basic/Basic3.vue deleted
1 | -<template> | |
2 | - <div class="grid"> | |
3 | - <div class="col-12"> | |
4 | - <div class="card"> | |
5 | - <h5>Advanced</h5> | |
6 | - <FileUpload name="demo[]" @uploader="onUpload" :multiple="true" accept="image/*" :maxFileSize="1000000" customUpload /> | |
7 | - | |
8 | - <h5>Basic</h5> | |
9 | - <FileUpload mode="basic" name="demo[]" accept="image/*" :maxFileSize="1000000" @uploader="onUpload" customUpload /> | |
10 | - </div> | |
11 | - </div> | |
12 | - <Toast /> | |
13 | - </div> | |
14 | -</template> | |
15 | - | |
16 | -<script> | |
17 | -export default { | |
18 | - methods: { | |
19 | - onUpload() { | |
20 | - this.$toast.add({ severity: 'info', summary: 'Success', detail: 'File Uploaded', life: 3000 }); | |
21 | - }, | |
22 | - }, | |
23 | -}; | |
24 | -</script> | |
25 | - | |
26 | -<style scoped></style> |
prestige-vue-4.0.0/src/views/basic/Basic4.vue deleted
1 | -<template> | |
2 | - <div class="floatlabel-demo"> | |
3 | - <div class="card"> | |
4 | - <h5>Float Label</h5> | |
5 | - <p>All input text components support floating labels by adding (<mark>.p-float-label</mark>) to wrapper class.</p> | |
6 | - <div class="grid p-fluid"> | |
7 | - <div class="col-12 md:col-6"> | |
8 | - <div class="field"> | |
9 | - <span class="p-float-label"> | |
10 | - <InputText type="text" id="inputtext" v-model="value1" /> | |
11 | - <label for="inputtext">InputText</label> | |
12 | - </span> | |
13 | - </div> | |
14 | - <div class="field"> | |
15 | - <span class="p-float-label p-input-icon-left"> | |
16 | - <i class="pi pi-search" /> | |
17 | - <InputText type="text" id="lefticon" v-model="value3" /> | |
18 | - <label for="lefticon">Left Icon</label> | |
19 | - </span> | |
20 | - </div> | |
21 | - <div class="field"> | |
22 | - <span class="p-float-label p-input-icon-right"> | |
23 | - <i class="pi pi-spin pi-spinner" /> | |
24 | - <InputText type="text" id="righticon" v-model="value5" /> | |
25 | - <label for="righticon">Right Icon</label> | |
26 | - </span> | |
27 | - </div> | |
28 | - <div class="field"> | |
29 | - <span class="p-float-label"> | |
30 | - <InputMask id="inputmask" mask="99/99/9999" v-model="value7"></InputMask> | |
31 | - <label for="inputmask">InputMask</label> | |
32 | - </span> | |
33 | - </div> | |
34 | - <div class="field"> | |
35 | - <span class="p-float-label"> | |
36 | - <InputNumber id="inputnumber" v-model="value9"></InputNumber> | |
37 | - <label for="inputnumber">InputNumber</label> | |
38 | - </span> | |
39 | - </div> | |
40 | - <div class="field"> | |
41 | - <span class="p-float-label"> | |
42 | - <Chips inputId="chips" v-model="value11"></Chips> | |
43 | - <label for="chips">Chips</label> | |
44 | - </span> | |
45 | - </div> | |
46 | - </div> | |
47 | - | |
48 | - <div class="col-12 md:col-6"> | |
49 | - <div class="field"> | |
50 | - <div class="p-inputgroup"> | |
51 | - <span class="p-inputgroup-addon"> | |
52 | - <i class="pi pi-user"></i> | |
53 | - </span> | |
54 | - <span class="p-float-label"> | |
55 | - <InputText type="text" id="inputgroup" v-model="value2" /> | |
56 | - <label for="inputgroup">InputGroup</label> | |
57 | - </span> | |
58 | - </div> | |
59 | - </div> | |
60 | - <div class="field"> | |
61 | - <span class="p-float-label"> | |
62 | - <AutoComplete id="autocomplete" v-model="value4" :suggestions="filteredCountries" @complete="searchCountry($event)" field="name"></AutoComplete> | |
63 | - <label for="autocomplete">AutoComplete</label> | |
64 | - </span> | |
65 | - </div> | |
66 | - <div class="field"> | |
67 | - <span class="p-float-label"> | |
68 | - <Calendar inputId="calendar" v-model="value6"></Calendar> | |
69 | - <label for="calendar">Calendar</label> | |
70 | - </span> | |
71 | - </div> | |
72 | - <div class="field"> | |
73 | - <span class="p-float-label"> | |
74 | - <Dropdown id="dropdown" :options="cities" v-model="value8" optionLabel="name"></Dropdown> | |
75 | - <label for="dropdown">Dropdown</label> | |
76 | - </span> | |
77 | - </div> | |
78 | - <div class="field"> | |
79 | - <span class="p-float-label"> | |
80 | - <MultiSelect id="multiselect" :options="cities" v-model="value10" optionLabel="name" :filter="false"></MultiSelect> | |
81 | - <label for="multiselect">MultiSelect</label> | |
82 | - </span> | |
83 | - </div> | |
84 | - <div class="field"> | |
85 | - <span class="p-float-label"> | |
86 | - <Textarea inputId="textarea" rows="3" cols="30" v-model="value12"></Textarea> | |
87 | - <label for="textarea">Textarea</label> | |
88 | - </span> | |
89 | - </div> | |
90 | - </div> | |
91 | - </div> | |
92 | - </div> | |
93 | - </div> | |
94 | -</template> | |
95 | - | |
96 | -<script> | |
97 | -import CountryService from '@/service/CountryService'; | |
98 | -export default { | |
99 | - data() { | |
100 | - return { | |
101 | - countries: [], | |
102 | - filteredCountries: null, | |
103 | - cities: [ | |
104 | - { name: 'New York', code: 'NY' }, | |
105 | - { name: 'Rome', code: 'RM' }, | |
106 | - { name: 'London', code: 'LDN' }, | |
107 | - { name: 'Istanbul', code: 'IST' }, | |
108 | - { name: 'Paris', code: 'PRS' }, | |
109 | - ], | |
110 | - value1: null, | |
111 | - value2: null, | |
112 | - value3: null, | |
113 | - value4: null, | |
114 | - value5: null, | |
115 | - value6: null, | |
116 | - value7: null, | |
117 | - value8: null, | |
118 | - value9: null, | |
119 | - value10: null, | |
120 | - value11: null, | |
121 | - value12: null, | |
122 | - }; | |
123 | - }, | |
124 | - created() { | |
125 | - this.countryService = new CountryService(); | |
126 | - }, | |
127 | - mounted() { | |
128 | - this.countryService.getCountries().then((countries) => { | |
129 | - this.countries = countries; | |
130 | - }); | |
131 | - }, | |
132 | - methods: { | |
133 | - searchCountry(event) { | |
134 | - // in a real application, make a request to a remote url with the query and | |
135 | - // return filtered results, for demo we filter at client side | |
136 | - const filtered = []; | |
137 | - const query = event.query; | |
138 | - for (let i = 0; i < this.countries.length; i++) { | |
139 | - const country = this.countries[i]; | |
140 | - if (country.name.toLowerCase().indexOf(query.toLowerCase()) == 0) { | |
141 | - filtered.push(country); | |
142 | - } | |
143 | - } | |
144 | - this.filteredCountries = filtered; | |
145 | - }, | |
146 | - }, | |
147 | -}; | |
148 | -</script> | |
149 | - | |
150 | -<style lang="scss" scoped> | |
151 | -.floatlabel-demo { | |
152 | - .field { | |
153 | - margin-top: 2rem; | |
154 | - } | |
155 | -} | |
156 | -</style> |
prestige-vue-4.0.0/src/views/basic/Basic5.vue deleted
1 | -<template> | |
2 | - <div class="grid"> | |
3 | - <div class="col-12 md:col-6"> | |
4 | - <div class="card p-fluid"> | |
5 | - <h5>Vertical</h5> | |
6 | - <div class="field"> | |
7 | - <label for="name1">Name</label> | |
8 | - <InputText id="name1" type="text" /> | |
9 | - </div> | |
10 | - <div class="field"> | |
11 | - <label for="email1">Email</label> | |
12 | - <InputText id="email1" type="text" /> | |
13 | - </div> | |
14 | - <div class="field"> | |
15 | - <label for="age1">Age</label> | |
16 | - <InputText id="age1" type="text" /> | |
17 | - </div> | |
18 | - </div> | |
19 | - | |
20 | - <div class="card p-fluid"> | |
21 | - <h5>Vertical Grid</h5> | |
22 | - <div class="formgrid grid"> | |
23 | - <div class="field col"> | |
24 | - <label for="name2">Name</label> | |
25 | - <InputText id="name2" type="text" /> | |
26 | - </div> | |
27 | - <div class="field col"> | |
28 | - <label for="email2">Email</label> | |
29 | - <InputText id="email2" type="text" /> | |
30 | - </div> | |
31 | - </div> | |
32 | - </div> | |
33 | - </div> | |
34 | - | |
35 | - <div class="col-12 md:col-6"> | |
36 | - <div class="card p-fluid"> | |
37 | - <h5>Horizontal</h5> | |
38 | - <div class="field grid"> | |
39 | - <label for="name3" class="col-12 mb-2 md:col-2 md:mb-0">Name</label> | |
40 | - <div class="col-12 md:col-10"> | |
41 | - <InputText id="name3" type="text" /> | |
42 | - </div> | |
43 | - </div> | |
44 | - <div class="field grid"> | |
45 | - <label for="email3" class="col-12 mb-2 md:col-2 md:mb-0">Email</label> | |
46 | - <div class="col-12 md:col-10"> | |
47 | - <InputText id="email3" type="text" /> | |
48 | - </div> | |
49 | - </div> | |
50 | - </div> | |
51 | - | |
52 | - <div class="card"> | |
53 | - <h5>Inline</h5> | |
54 | - <div class="formgroup-inline"> | |
55 | - <div class="field"> | |
56 | - <label for="firstname1" class="p-sr-only">Firstname</label> | |
57 | - <InputText id="firstname1" type="text" placeholder="Firstname" /> | |
58 | - </div> | |
59 | - <div class="field"> | |
60 | - <label for="lastname1" class="p-sr-only">Lastname</label> | |
61 | - <InputText id="lastname1" type="text" placeholder="Lastname" /> | |
62 | - </div> | |
63 | - <Button label="Submit"></Button> | |
64 | - </div> | |
65 | - </div> | |
66 | - | |
67 | - <div class="card"> | |
68 | - <h5>Help Text</h5> | |
69 | - <div class="field p-fluid"> | |
70 | - <label for="username">Username</label> | |
71 | - <InputText id="username" type="text" /> | |
72 | - <small>Enter your username to reset your password.</small> | |
73 | - </div> | |
74 | - </div> | |
75 | - </div> | |
76 | - | |
77 | - <div class="col-12"> | |
78 | - <div class="card"> | |
79 | - <h5>Advanced</h5> | |
80 | - <div class="p-fluid formgrid grid"> | |
81 | - <div class="field col-12 md:col-6"> | |
82 | - <label for="firstname2">Firstname</label> | |
83 | - <InputText id="firstname2" type="text" /> | |
84 | - </div> | |
85 | - <div class="field col-12 md:col-6"> | |
86 | - <label for="lastname2">Lastname</label> | |
87 | - <InputText id="lastname2" type="text" /> | |
88 | - </div> | |
89 | - <div class="field col-12"> | |
90 | - <label for="address">Address</label> | |
91 | - <Textarea id="address" rows="4" /> | |
92 | - </div> | |
93 | - <div class="field col-12 md:col-6"> | |
94 | - <label for="city">City</label> | |
95 | - <InputText id="city" type="text" /> | |
96 | - </div> | |
97 | - <div class="field col-12 md:col-3"> | |
98 | - <label for="state">State</label> | |
99 | - <Dropdown id="state" v-model="dropdownItem" :options="dropdownItems" optionLabel="name" placeholder="Select One"></Dropdown> | |
100 | - </div> | |
101 | - <div class="field col-12 md:col-3"> | |
102 | - <label for="zip">Zip</label> | |
103 | - <InputText id="zip" type="text" /> | |
104 | - </div> | |
105 | - </div> | |
106 | - </div> | |
107 | - </div> | |
108 | - </div> | |
109 | -</template> | |
110 | -<script> | |
111 | -export default { | |
112 | - data() { | |
113 | - return { | |
114 | - dropdownItems: [ | |
115 | - { name: 'Option 1', code: 'Option 1' }, | |
116 | - { name: 'Option 2', code: 'Option 2' }, | |
117 | - { name: 'Option 3', code: 'Option 3' }, | |
118 | - ], | |
119 | - dropdownItem: null, | |
120 | - }; | |
121 | - }, | |
122 | -}; | |
123 | -</script> |
prestige-vue-4.0.0/src/views/system/Authority.vue deleted
1 | -<template> | |
2 | - <div class="grid"> | |
3 | - <div class="col-12"> | |
4 | - <div class="card"> | |
5 | - <h5>Calendar</h5> | |
6 | - <FullCalendar :events="events" :options="options" /> | |
7 | - | |
8 | - <Dialog v-model:visible="eventDialog" :style="{ width: '450px' }" header="Event Details" :modal="true" :closable="true"> | |
9 | - <div class="p-fluid"> | |
10 | - <div class="field"> | |
11 | - <label for="title">Title</label> | |
12 | - <InputText id="title" v-if="clickedEvent" v-model="changedEvent.title" required="true" autofocus /> | |
13 | - </div> | |
14 | - <div class="field"> | |
15 | - <label for="start">From</label> | |
16 | - <Calendar id="start" v-if="clickedEvent" v-model="changedEvent.start" :showTime="true" appendTo="body" /> | |
17 | - </div> | |
18 | - <div class="field"> | |
19 | - <label for="end">To</label> | |
20 | - <Calendar id="end" v-if="clickedEvent" v-model="changedEvent.end" :showTime="true" appendTo="body" /> | |
21 | - </div> | |
22 | - <div class="field-checkbox"> | |
23 | - <Checkbox id="allday" name="allday" value="All Day" v-model="changedEvent.allDay" /> | |
24 | - <label for="allday">All Day</label> | |
25 | - </div> | |
26 | - </div> | |
27 | - <template #footer> | |
28 | - <Button label="Save" icon="pi pi-check" class="p-button-text" @click="save" /> | |
29 | - <Button label="Reset" icon="pi pi-refresh" class="p-button-text" @click="reset" /> | |
30 | - </template> | |
31 | - </Dialog> | |
32 | - </div> | |
33 | - </div> | |
34 | - </div> | |
35 | -</template> | |
36 | - | |
37 | -<script> | |
38 | -import '@fullcalendar/core/vdom'; | |
39 | -import EventService from '@/service/EventService'; | |
40 | -import dayGridPlugin from '@fullcalendar/daygrid'; | |
41 | -import timeGridPlugin from '@fullcalendar/timegrid'; | |
42 | -import interactionPlugin from '@fullcalendar/interaction'; | |
43 | -import FullCalendar from 'primevue/fullcalendar'; | |
44 | -export default { | |
45 | - components: { | |
46 | - FullCalendar, | |
47 | - }, | |
48 | - data() { | |
49 | - return { | |
50 | - eventDialog: false, | |
51 | - clickedEvent: null, | |
52 | - changedEvent: { title: '', start: null, end: '', allDay: null }, | |
53 | - options: { | |
54 | - plugins: [dayGridPlugin, timeGridPlugin, interactionPlugin], | |
55 | - initialDate: '2023-01-01', | |
56 | - headerToolbar: { | |
57 | - left: 'prev,next', | |
58 | - center: 'title', | |
59 | - right: 'dayGridMonth,timeGridWeek,timeGridDay', | |
60 | - }, | |
61 | - editable: true, | |
62 | - selectable: true, | |
63 | - selectMirror: true, | |
64 | - dayMaxEvents: true, | |
65 | - eventClick: (e) => { | |
66 | - this.eventDialog = true; | |
67 | - this.clickedEvent = e.event; | |
68 | - this.changedEvent.title = this.clickedEvent.title; | |
69 | - this.changedEvent.start = this.clickedEvent.start; | |
70 | - this.changedEvent.end = this.clickedEvent.end; | |
71 | - }, | |
72 | - }, | |
73 | - events: null, | |
74 | - }; | |
75 | - }, | |
76 | - eventService: null, | |
77 | - created() { | |
78 | - this.eventService = new EventService(); | |
79 | - }, | |
80 | - mounted() { | |
81 | - this.eventService.getEvents().then((data) => (this.events = data)); | |
82 | - }, | |
83 | - methods: { | |
84 | - findIndexById(id) { | |
85 | - let index = -1; | |
86 | - for (let i = 0; i < this.events.length; i++) { | |
87 | - if (this.events[i].id === id) { | |
88 | - index = i; | |
89 | - break; | |
90 | - } | |
91 | - } | |
92 | - return index; | |
93 | - }, | |
94 | - save() { | |
95 | - this.eventDialog = false; | |
96 | - this.clickedEvent.setProp('title', this.changedEvent.title); | |
97 | - this.clickedEvent.setStart(this.changedEvent.start); | |
98 | - this.clickedEvent.setEnd(this.changedEvent.end); | |
99 | - this.clickedEvent.setAllDay(this.changedEvent.allDay); | |
100 | - this.changedEvent = { title: '', start: null, end: '', allDay: null }; | |
101 | - }, | |
102 | - reset() { | |
103 | - this.changedEvent.title = this.clickedEvent.title; | |
104 | - this.changedEvent.start = this.clickedEvent.start; | |
105 | - this.changedEvent.end = this.clickedEvent.end; | |
106 | - }, | |
107 | - }, | |
108 | -}; | |
109 | -</script> | |
110 | - | |
111 | -<style scoped> | |
112 | -::v-deep(.fc .fc-col-header-cell-cushion), | |
113 | -::v-deep(.fc-daygrid-dot-event .fc-event-time), | |
114 | -::v-deep(.fc-daygrid-dot-event .fc-event-title), | |
115 | -::v-deep(.fc .fc-daygrid-day-number), | |
116 | -::v-deep(.fc .fc-daygrid-more-link) { | |
117 | - color: var(--text-color); | |
118 | -} | |
119 | - | |
120 | -@media screen and (max-width: 960px) { | |
121 | - ::v-deep(.fc-header-toolbar) { | |
122 | - display: flex; | |
123 | - flex-wrap: wrap; | |
124 | - } | |
125 | -} | |
126 | -</style> |
prestige-vue-4.0.0/src/views/system/SystemCode.vue
1 | 1 | <template> |
2 | 2 | <div class="card"> |
3 | 3 | <Toast /> |
4 | - <div class="card formgrid grid"> | |
5 | - <div class="field col grid"> | |
6 | - <div class="field col-12 md:col-6"> | |
4 | + <div class="card formgrid grid" style="margin-bottom: 0px;"> | |
5 | + <div class="field col grid" style="margin-bottom: 0px;"> | |
6 | + <div class="field col-12 md:col-6" style="margin-bottom: 0px;"> | |
7 | 7 | <label for="codeType">코드유형</label> |
8 | 8 | <AutoComplete v-model="codeType" dropdown :suggestions="filteredItems" @complete="searchItems" class="w-full" /> |
9 | 9 | </div> |
10 | - <div class="field col-12 md:col-6"> | |
10 | + <div class="field col-12 md:col-6" style="margin-bottom: 0px;"> | |
11 | 11 | <label for="useAt">사용여부</label> |
12 | 12 | <SelectButton v-model="useAt" :options="options" aria-labelledby="basic" class="w-full" @click="setData(data)"/> |
13 | 13 | </div> |
14 | 14 | </div> |
15 | 15 | <SplitButton label="Search" icon="pi pi-plus" @click="search" :model="buttonItems" class="bg-primary" /> |
16 | 16 | </div> |
17 | - | |
17 | + <Toolbar style="background: #ffffff; border: 0px;"> | |
18 | + <template #end> | |
19 | + <Button icon="pi pi-refresh" aria-label="Filter" @click="refreshRow()"/> | |
20 | + <span style="width: 5px;"></span> | |
21 | + <Button icon="pi pi-plus" aria-label="Filter" @click="addRow()"/> | |
22 | + <span style="width: 5px;"></span> | |
23 | + <Button icon="pi pi-minus" aria-label="Filter" @click="delRow()"/> | |
24 | + </template> | |
25 | + </Toolbar> | |
18 | 26 | <div class="grid"> |
19 | 27 | <div class="col-12 md:col-4" style="padding: 0; padding-right: 10px;"> |
20 | 28 | <ag-grid-vue |
21 | 29 | style="width: 100%; height: 350px;" |
22 | - class="ag-theme-quartz" | |
30 | + class="ag-theme-balham" | |
23 | 31 | :columnDefs="columnsType" |
24 | 32 | :rowData="codeTypeItems" |
25 | 33 | @grid-ready="onGridReadyType" |
... | ... | @@ -32,7 +40,7 @@ |
32 | 40 | <div class="col-12 md:col-8" style="padding: 0"> |
33 | 41 | <ag-grid-vue |
34 | 42 | style="width: 100%; height: 350px;" |
35 | - class="ag-theme-quartz" | |
43 | + class="ag-theme-balham" | |
36 | 44 | :columnDefs="columns" |
37 | 45 | :rowData="codeItems" |
38 | 46 | :rowSelection="rowSelection" |
... | ... | @@ -56,6 +64,7 @@ import axios from '../../service/axios'; |
56 | 64 | import { onBeforeMount, ref } from 'vue'; |
57 | 65 | import { useI18n } from 'vue-i18n' |
58 | 66 | import RendererRowStatus from "../common/RendererRowStatus.vue"; |
67 | +import ags from '../../service/AgGridService'; | |
59 | 68 | |
60 | 69 | const toast = useToast(); |
61 | 70 | |
... | ... | @@ -103,6 +112,12 @@ const columns = [ |
103 | 112 | cellRenderer: RendererRowStatus |
104 | 113 | }, |
105 | 114 | { |
115 | + headerName: i18n.t('System.SystemCode.grid.CodeType'), | |
116 | + field: "codeTy", | |
117 | + editable: true, | |
118 | + pinned: 'left', | |
119 | + }, | |
120 | + { | |
106 | 121 | headerName: i18n.t('System.SystemCode.grid.Code'), |
107 | 122 | field: "cmmnCode", |
108 | 123 | editable: true, |
... | ... | @@ -181,6 +196,7 @@ const columns = [ |
181 | 196 | const rowSelection = ref(null); |
182 | 197 | const gridApiType = ref(); |
183 | 198 | const gridApi = ref(); |
199 | +let selectCodeTy = ""; | |
184 | 200 | |
185 | 201 | onBeforeMount(() => { |
186 | 202 | rowSelection.value = 'single'; |
... | ... | @@ -198,16 +214,14 @@ const onSelectionChanged = () => { |
198 | 214 | } |
199 | 215 | ); |
200 | 216 | } |
217 | + selectCodeTy = selectedRows[0].cmmnCode; | |
201 | 218 | }; |
202 | 219 | |
203 | 220 | const onCellValueChanged = (event) => { |
204 | - console.log("onCellValueChanged"); | |
205 | - event.data.rowStatus = "U"; | |
206 | - const res = gridApi.value.applyTransaction({ | |
207 | - update: [event.data] | |
208 | - }); | |
221 | + let res = ags.agGridChangeStatusRow(gridApi, event); | |
209 | 222 | console.log(res); |
210 | 223 | }; |
224 | + | |
211 | 225 | const onGridReadyType = (params) => { |
212 | 226 | gridApiType.value = params.api; |
213 | 227 | |
... | ... | @@ -269,6 +283,7 @@ const setData = (responseData) => { |
269 | 283 | defaultMinWidth: 50 |
270 | 284 | }); |
271 | 285 | codeItems.value = []; |
286 | + selectCodeTy = ""; | |
272 | 287 | } |
273 | 288 | |
274 | 289 | const buttonItems = [ |
... | ... | @@ -323,6 +338,24 @@ const saveData = async () => { |
323 | 338 | |
324 | 339 | }; |
325 | 340 | |
341 | +const addRow = () => { | |
342 | + const res = ags.agGridAddRow(gridApi, 1, false); | |
343 | + console.log(res); | |
344 | +} | |
345 | + | |
346 | +const delRow = () => { | |
347 | + const selectedNodes = gridApi.value.getSelectedNodes(); //[] | |
348 | + const res = ags.agGridDelRow(gridApi, selectedNodes); | |
349 | + console.log(res); | |
350 | +} | |
351 | + | |
352 | +const refreshRow = () => { | |
353 | + const selectedRows = gridApi.value.getSelectedRows(); | |
354 | + ags.agGridEraseStatusRow(gridApi, selectedRows); | |
355 | + console.log(res); | |
356 | +} | |
357 | + | |
358 | + | |
326 | 359 | //-------------------------------------------------------------------------------------------- |
327 | 360 | |
328 | 361 | </script> | ... | ... |
prestige-vue-4.0.0/src/views/system/User.vue
1 | 1 | <template> |
2 | - <div class="grid crud-demo"> | |
3 | - <div class="col-12"> | |
4 | - <div class="card"> | |
5 | - <Toast /> | |
6 | - <Toolbar class="mb-4"> | |
7 | - <template v-slot:start> | |
8 | - <div class="my-2"> | |
9 | - <Button label="New" icon="pi pi-plus" class="p-button-success mr-2" @click="openNew" /> | |
10 | - <Button label="Delete" icon="pi pi-trash" class="p-button-danger" @click="confirmDeleteSelected" :disabled="!selectedProducts || !selectedProducts.length" /> | |
11 | - </div> | |
12 | - </template> | |
13 | - | |
14 | - <template v-slot:end> | |
15 | - <FileUpload mode="basic" accept="image/*" :maxFileSize="1000000" label="Import" chooseLabel="Import" class="mr-2 inline-block" /> | |
16 | - <Button label="Export" icon="pi pi-upload" class="p-button-help" @click="exportCSV($event)" /> | |
17 | - </template> | |
18 | - </Toolbar> | |
19 | - | |
20 | - <DataTable | |
21 | - ref="dt" | |
22 | - :value="products" | |
23 | - v-model:selection="selectedProducts" | |
24 | - dataKey="id" | |
25 | - :paginator="true" | |
26 | - :rows="10" | |
27 | - :filters="filters" | |
28 | - paginatorTemplate="FirstPageLink PrevPageLink PageLinks NextPageLink LastPageLink CurrentPageReport RowsPerPageDropdown" | |
29 | - :rowsPerPageOptions="[5, 10, 25]" | |
30 | - currentPageReportTemplate="Showing {first} to {last} of {totalRecords} products" | |
31 | - responsiveLayout="scroll" | |
2 | + <div class="card"> | |
3 | + <Toast /> | |
4 | + <div class="card formgrid grid" style="margin-bottom: 0px;"> | |
5 | + <div class="field col grid" style="margin-bottom: 0px;"> | |
6 | + <div class="field col-12 md:col-6" style="margin-bottom: 0px;"> | |
7 | + <label for="userId">사용자Id</label> | |
8 | + <AutoComplete v-model="userId" dropdown :suggestions="filteredItems" @complete="searchItems" class="w-full" /> | |
9 | + </div> | |
10 | + <div class="field col-12 md:col-6" style="margin-bottom: 0px;"> | |
11 | + <label for="activated">사용여부</label> | |
12 | + <SelectButton v-model="activated" :options="options" aria-labelledby="basic" class="w-full" @click="setData(data)"/> | |
13 | + </div> | |
14 | + </div> | |
15 | + <SplitButton label="Search" icon="pi pi-plus" @click="search" :model="buttonItems" class="bg-primary" /> | |
16 | + </div> | |
17 | + <Toolbar style="background: #ffffff; border: 0px;"> | |
18 | + <template #end> | |
19 | + <Button icon="pi pi-refresh" aria-label="Filter" @click="refreshRow()"/> | |
20 | + <span style="width: 5px;"></span> | |
21 | + <Button icon="pi pi-plus" aria-label="Filter" @click="addRow()"/> | |
22 | + <span style="width: 5px;"></span> | |
23 | + <Button icon="pi pi-minus" aria-label="Filter" @click="delRow()"/> | |
24 | + </template> | |
25 | + </Toolbar> | |
26 | + <div class="grid"> | |
27 | + <div class="col-12 md:col-12" style="padding: 0; padding-right: 10px;"> | |
28 | + <ag-grid-vue | |
29 | + style="width: 100%; height: 350px;" | |
30 | + class="ag-theme-balham" | |
31 | + :columnDefs="columns" | |
32 | + :rowData="userItems" | |
33 | + @grid-ready="onGridReady" | |
34 | + :rowSelection="rowSelection" | |
35 | + @cell-value-changed ="onCellValueChanged" | |
36 | + :defaultColDef="defaultColDef" | |
32 | 37 | > |
33 | - <template #header> | |
34 | - <div class="flex flex-column md:flex-row md:justify-content-between md:align-items-center"> | |
35 | - <h5 class="m-0">Manage Products</h5> | |
36 | - <span class="block mt-2 md:mt-0 p-input-icon-left"> | |
37 | - <i class="pi pi-search" /> | |
38 | - <InputText v-model="filters['global'].value" placeholder="Search..." /> | |
39 | - </span> | |
40 | - </div> | |
41 | - </template> | |
42 | - | |
43 | - <Column selectionMode="multiple" headerStyle="width: 3rem"></Column> | |
44 | - <Column field="code" header="Code" :sortable="true" headerStyle="width:14%; min-width:10rem;"> | |
45 | - <template #body="slotProps"> | |
46 | - <span class="p-column-title">Code</span> | |
47 | - {{ slotProps.data.code }} | |
48 | - </template> | |
49 | - </Column> | |
50 | - <Column field="name" header="Name" :sortable="true" headerStyle="width:14%; min-width:10rem;"> | |
51 | - <template #body="slotProps"> | |
52 | - <span class="p-column-title">Name</span> | |
53 | - {{ slotProps.data.name }} | |
54 | - </template> | |
55 | - </Column> | |
56 | - <Column header="Image" headerStyle="width:14%; min-width:10rem;"> | |
57 | - <template #body="slotProps"> | |
58 | - <span class="p-column-title">Image</span> | |
59 | - <img :src="'/demo/images/product/' + slotProps.data.image" :alt="slotProps.data.image" class="shadow-2" width="100" /> | |
60 | - </template> | |
61 | - </Column> | |
62 | - <Column field="price" header="Price" :sortable="true" headerStyle="width:14%; min-width:8rem;"> | |
63 | - <template #body="slotProps"> | |
64 | - <span class="p-column-title">Price</span> | |
65 | - {{ formatCurrency(slotProps.data.price) }} | |
66 | - </template> | |
67 | - </Column> | |
68 | - <Column field="category" header="Category" :sortable="true" headerStyle="width:14%; min-width:10rem;"> | |
69 | - <template #body="slotProps"> | |
70 | - <span class="p-column-title">Category</span> | |
71 | - {{ formatCurrency(slotProps.data.category) }} | |
72 | - </template> | |
73 | - </Column> | |
74 | - <Column field="rating" header="Reviews" :sortable="true" headerStyle="width:14%; min-width:10rem;"> | |
75 | - <template #body="slotProps"> | |
76 | - <span class="p-column-title">Rating</span> | |
77 | - <Rating :modelValue="slotProps.data.rating" :readonly="true" :cancel="false" /> | |
78 | - </template> | |
79 | - </Column> | |
80 | - <Column field="inventoryStatus" header="Status" :sortable="true" headerStyle="width:14%; min-width:10rem;"> | |
81 | - <template #body="slotProps"> | |
82 | - <span class="p-column-title">Status</span> | |
83 | - <span :class="'product-badge status-' + (slotProps.data.inventoryStatus ? slotProps.data.inventoryStatus.toLowerCase() : '')">{{ slotProps.data.inventoryStatus }}</span> | |
84 | - </template> | |
85 | - </Column> | |
86 | - <Column headerStyle="width:14%; min-width:10rem;"> | |
87 | - <template #body="slotProps"> | |
88 | - <Button icon="pi pi-pencil" class="p-button-rounded p-button-success mr-2" @click="editProduct(slotProps.data)" /> | |
89 | - <Button icon="pi pi-trash" class="p-button-rounded p-button-warning" @click="confirmDeleteProduct(slotProps.data)" /> | |
90 | - </template> | |
91 | - </Column> | |
92 | - </DataTable> | |
93 | - | |
94 | - <Dialog v-model:visible="productDialog" :style="{ width: '450px' }" header="Product Details" :modal="true" class="p-fluid"> | |
95 | - <img :src="'/demo/images/product/' + product.image" :alt="product.image" v-if="product.image" width="150" class="mt-0 mx-auto mb-5 block shadow-2" /> | |
96 | - <div class="field"> | |
97 | - <label for="name">Name</label> | |
98 | - <InputText id="name" v-model.trim="product.name" required="true" autofocus :class="{ 'p-invalid': submitted && !product.name }" /> | |
99 | - <small class="p-invalid" v-if="submitted && !product.name">Name is required.</small> | |
100 | - </div> | |
101 | - <div class="field"> | |
102 | - <label for="description">Description</label> | |
103 | - <Textarea id="description" v-model="product.description" required="true" rows="3" cols="20" /> | |
104 | - </div> | |
105 | - | |
106 | - <div class="field"> | |
107 | - <label for="inventoryStatus" class="mb-3">Inventory Status</label> | |
108 | - <Dropdown id="inventoryStatus" v-model="product.inventoryStatus" :options="statuses" optionLabel="label" placeholder="Select a Status"> | |
109 | - <template #value="slotProps"> | |
110 | - <div v-if="slotProps.value && slotProps.value.value"> | |
111 | - <span :class="'product-badge status-' + slotProps.value.value">{{ slotProps.value.label }}</span> | |
112 | - </div> | |
113 | - <div v-else-if="slotProps.value && !slotProps.value.value"> | |
114 | - <span :class="'product-badge status-' + slotProps.value.toLowerCase()">{{ slotProps.value }}</span> | |
115 | - </div> | |
116 | - <span v-else> | |
117 | - {{ slotProps.placeholder }} | |
118 | - </span> | |
119 | - </template> | |
120 | - </Dropdown> | |
121 | - </div> | |
122 | - | |
123 | - <div class="field"> | |
124 | - <label class="mb-3">Category</label> | |
125 | - <div class="formgrid grid"> | |
126 | - <div class="field-radiobutton col-6"> | |
127 | - <RadioButton id="category1" name="category" value="Accessories" v-model="product.category" /> | |
128 | - <label for="category1">Accessories</label> | |
129 | - </div> | |
130 | - <div class="field-radiobutton col-6"> | |
131 | - <RadioButton id="category2" name="category" value="Clothing" v-model="product.category" /> | |
132 | - <label for="category2">Clothing</label> | |
133 | - </div> | |
134 | - <div class="field-radiobutton col-6"> | |
135 | - <RadioButton id="category3" name="category" value="Electronics" v-model="product.category" /> | |
136 | - <label for="category3">Electronics</label> | |
137 | - </div> | |
138 | - <div class="field-radiobutton col-6"> | |
139 | - <RadioButton id="category4" name="category" value="Fitness" v-model="product.category" /> | |
140 | - <label for="category4">Fitness</label> | |
141 | - </div> | |
142 | - </div> | |
143 | - </div> | |
144 | - | |
145 | - <div class="formgrid grid"> | |
146 | - <div class="field col"> | |
147 | - <label for="price">Price</label> | |
148 | - <InputNumber id="price" v-model="product.price" mode="currency" currency="USD" locale="en-US" /> | |
149 | - </div> | |
150 | - <div class="field col"> | |
151 | - <label for="quantity">Quantity</label> | |
152 | - <InputNumber id="quantity" v-model="product.quantity" integeronly /> | |
153 | - </div> | |
154 | - </div> | |
155 | - <template #footer> | |
156 | - <Button label="Cancel" icon="pi pi-times" class="p-button-text" @click="hideDialog" /> | |
157 | - <Button label="Save" icon="pi pi-check" class="p-button-text" @click="saveProduct" /> | |
158 | - </template> | |
159 | - </Dialog> | |
160 | - | |
161 | - <Dialog v-model:visible="deleteProductDialog" :style="{ width: '450px' }" header="Confirm" :modal="true"> | |
162 | - <div class="flex align-items-center justify-content-center"> | |
163 | - <i class="pi pi-exclamation-triangle mr-3" style="font-size: 2rem" /> | |
164 | - <span v-if="product" | |
165 | - >Are you sure you want to delete <b>{{ product.name }}</b | |
166 | - >?</span | |
167 | - > | |
168 | - </div> | |
169 | - <template #footer> | |
170 | - <Button label="No" icon="pi pi-times" class="p-button-text" @click="deleteProductDialog = false" /> | |
171 | - <Button label="Yes" icon="pi pi-check" class="p-button-text" @click="deleteProduct" /> | |
172 | - </template> | |
173 | - </Dialog> | |
174 | - | |
175 | - <Dialog v-model:visible="deleteProductsDialog" :style="{ width: '450px' }" header="Confirm" :modal="true"> | |
176 | - <div class="flex align-items-center justify-content-center"> | |
177 | - <i class="pi pi-exclamation-triangle mr-3" style="font-size: 2rem" /> | |
178 | - <span v-if="product">Are you sure you want to delete the selected products?</span> | |
179 | - </div> | |
180 | - <template #footer> | |
181 | - <Button label="No" icon="pi pi-times" class="p-button-text" @click="deleteProductsDialog = false" /> | |
182 | - <Button label="Yes" icon="pi pi-check" class="p-button-text" @click="deleteSelectedProducts" /> | |
183 | - </template> | |
184 | - </Dialog> | |
38 | + </ag-grid-vue> | |
185 | 39 | </div> |
40 | + | |
186 | 41 | </div> |
187 | 42 | </div> |
188 | 43 | </template> |
189 | 44 | |
190 | -<script> | |
191 | -import { FilterMatchMode } from 'primevue/api'; | |
192 | -import ProductService from '@/service/ProductService'; | |
193 | - | |
194 | -export default { | |
195 | - data() { | |
196 | - return { | |
197 | - products: null, | |
198 | - productDialog: false, | |
199 | - deleteProductDialog: false, | |
200 | - deleteProductsDialog: false, | |
201 | - product: {}, | |
202 | - selectedProducts: null, | |
203 | - filters: {}, | |
204 | - submitted: false, | |
205 | - statuses: [ | |
206 | - { label: 'INSTOCK', value: 'instock' }, | |
207 | - { label: 'LOWSTOCK', value: 'lowstock' }, | |
208 | - { label: 'OUTOFSTOCK', value: 'outofstock' }, | |
209 | - ], | |
210 | - }; | |
45 | +<script setup> | |
46 | +//-------------------------------------------------------------------------------------------- | |
47 | +// imprort | |
48 | +//-------------------------------------------------------------------------------------------- | |
49 | +import { useToast } from "primevue/usetoast"; | |
50 | +import axios from '../../service/axios'; | |
51 | +import { onBeforeMount, ref } from 'vue'; | |
52 | +import { useI18n } from 'vue-i18n' | |
53 | +import RendererRowStatus from "../common/RendererRowStatus.vue"; | |
54 | +import ags from '../../service/AgGridService'; | |
55 | + | |
56 | +const toast = useToast(); | |
57 | + | |
58 | +//-------------------------------------------------------------------------------------------- | |
59 | +// 변수선언 | |
60 | +//-------------------------------------------------------------------------------------------- | |
61 | +const userItems = ref(""); | |
62 | +const filteredItems = ref(); | |
63 | +const userId = ref(""); | |
64 | +const activated = ref("전체"); | |
65 | +const options = ref(['전체', '사용', '미사용']); | |
66 | + | |
67 | +let data = []; | |
68 | + | |
69 | +const i18n = useI18n() | |
70 | +//-------------------------------------------------------------------------------------------- | |
71 | + | |
72 | +//-------------------------------------------------------------------------------------------- | |
73 | +// ag-grid Header | |
74 | +//-------------------------------------------------------------------------------------------- | |
75 | + | |
76 | +const defaultColDef = { | |
77 | + filter: true, | |
78 | + enableCellChangeFlash: true, | |
79 | +}; | |
80 | + | |
81 | +const columns = [ | |
82 | + { | |
83 | + headerName: "", | |
84 | + field: "rowStatus", | |
85 | + editable: false, | |
86 | + pinned: 'left', | |
87 | + maxWidth: 45, | |
88 | + cellRenderer: RendererRowStatus | |
89 | + }, | |
90 | + { | |
91 | + headerName: "사용자ID", | |
92 | + field: "userId", | |
93 | + editable: false, | |
211 | 94 | }, |
212 | - productService: null, | |
213 | - created() { | |
214 | - this.productService = new ProductService(); | |
215 | - this.initFilters(); | |
95 | + { | |
96 | + headerName: "사용여부", | |
97 | + field: "activated", | |
98 | + maxWidth: 100, | |
99 | + editable: true, | |
216 | 100 | }, |
217 | - mounted() { | |
218 | - this.productService.getProducts().then((data) => (this.products = data)); | |
101 | + { | |
102 | + headerName: "사용자명", | |
103 | + field: "username", | |
104 | + editable: true, | |
219 | 105 | }, |
220 | - methods: { | |
221 | - formatCurrency(value) { | |
222 | - if (value) return value.toLocaleString('en-US', { style: 'currency', currency: 'USD' }); | |
223 | - return; | |
224 | - }, | |
225 | - openNew() { | |
226 | - this.product = {}; | |
227 | - this.submitted = false; | |
228 | - this.productDialog = true; | |
229 | - }, | |
230 | - hideDialog() { | |
231 | - this.productDialog = false; | |
232 | - this.submitted = false; | |
233 | - }, | |
234 | - saveProduct() { | |
235 | - this.submitted = true; | |
236 | - if (this.product.name.trim()) { | |
237 | - if (this.product.id) { | |
238 | - this.product.inventoryStatus = this.product.inventoryStatus.value ? this.product.inventoryStatus.value : this.product.inventoryStatus; | |
239 | - this.products[this.findIndexById(this.product.id)] = this.product; | |
240 | - this.$toast.add({ severity: 'success', summary: 'Successful', detail: 'Product Updated', life: 3000 }); | |
241 | - } else { | |
242 | - this.product.id = this.createId(); | |
243 | - this.product.code = this.createId(); | |
244 | - this.product.image = 'product-placeholder.svg'; | |
245 | - this.product.inventoryStatus = this.product.inventoryStatus ? this.product.inventoryStatus.value : 'INSTOCK'; | |
246 | - this.products.push(this.product); | |
247 | - this.$toast.add({ severity: 'success', summary: 'Successful', detail: 'Product Created', life: 3000 }); | |
248 | - } | |
249 | - this.productDialog = false; | |
250 | - this.product = {}; | |
251 | - } | |
252 | - }, | |
253 | - editProduct(product) { | |
254 | - this.product = { ...product }; | |
255 | - this.productDialog = true; | |
256 | - }, | |
257 | - confirmDeleteProduct(product) { | |
258 | - this.product = product; | |
259 | - this.deleteProductDialog = true; | |
260 | - }, | |
261 | - deleteProduct() { | |
262 | - this.products = this.products.filter((val) => val.id !== this.product.id); | |
263 | - this.deleteProductDialog = false; | |
264 | - this.product = {}; | |
265 | - this.$toast.add({ severity: 'success', summary: 'Successful', detail: 'Product Deleted', life: 3000 }); | |
266 | - }, | |
267 | - findIndexById(id) { | |
268 | - let index = -1; | |
269 | - for (let i = 0; i < this.products.length; i++) { | |
270 | - if (this.products[i].id === id) { | |
271 | - index = i; | |
272 | - break; | |
273 | - } | |
274 | - } | |
275 | - return index; | |
276 | - }, | |
277 | - createId() { | |
278 | - let id = ''; | |
279 | - var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; | |
280 | - for (var i = 0; i < 5; i++) { | |
281 | - id += chars.charAt(Math.floor(Math.random() * chars.length)); | |
282 | - } | |
283 | - return id; | |
284 | - }, | |
285 | - exportCSV() { | |
286 | - this.$refs.dt.exportCSV(); | |
287 | - }, | |
288 | - confirmDeleteSelected() { | |
289 | - this.deleteProductsDialog = true; | |
290 | - }, | |
291 | - deleteSelectedProducts() { | |
292 | - this.products = this.products.filter((val) => !this.selectedProducts.includes(val)); | |
293 | - this.deleteProductsDialog = false; | |
294 | - this.selectedProducts = null; | |
295 | - this.$toast.add({ severity: 'success', summary: 'Successful', detail: 'Products Deleted', life: 3000 }); | |
296 | - }, | |
297 | - initFilters() { | |
298 | - this.filters = { | |
299 | - global: { value: null, matchMode: FilterMatchMode.CONTAINS }, | |
300 | - }; | |
301 | - }, | |
106 | + { | |
107 | + headerName: "패스워드", | |
108 | + field: "password", | |
109 | + editable: true, | |
302 | 110 | }, |
111 | + { | |
112 | + headerName: "별명", | |
113 | + field: "nickname", | |
114 | + editable: true, | |
115 | + } | |
116 | +]; | |
117 | +//-------------------------------------------------------------------------------------------- | |
118 | + | |
119 | + | |
120 | + | |
121 | +//-------------------------------------------------------------------------------------------- | |
122 | +//ag-grid function | |
123 | +//-------------------------------------------------------------------------------------------- | |
124 | +const rowSelection = ref(null); | |
125 | +const gridApi = ref(); | |
126 | + | |
127 | +onBeforeMount(() => { | |
128 | + rowSelection.value = 'single'; | |
129 | +}); | |
130 | + | |
131 | +const onCellValueChanged = (event) => { | |
132 | + let res = ags.agGridChangeStatusRow(gridApi, event); | |
133 | + console.log(res); | |
303 | 134 | }; |
304 | -</script> | |
305 | 135 | |
306 | -<style scoped lang="scss"> | |
307 | -@import '@/assets/demo/styles/badges.scss'; | |
308 | -</style> | |
136 | +const onGridReady = (params) => { | |
137 | + gridApi.value = params.api; | |
138 | + | |
139 | + getData(); | |
140 | +}; | |
141 | + | |
142 | +const searchItems = (event) => { | |
143 | + let query = event.query; | |
144 | + let _filteredItems = []; | |
145 | + | |
146 | + for (let i = 0; i < userItems.value.length; i++) { | |
147 | + let item = userItems.value[i]; | |
148 | + | |
149 | + if (item.username.toLowerCase().indexOf(query.toLowerCase()) >= 0) { | |
150 | + _filteredItems.push(item.userId + " : " + item.username ); | |
151 | + } | |
152 | + } | |
153 | + | |
154 | + filteredItems.value = _filteredItems; | |
155 | +}; | |
156 | +//-------------------------------------------------------------------------------------------- | |
157 | + | |
158 | +//-------------------------------------------------------------------------------------------- | |
159 | +// 일반 Function | |
160 | +//-------------------------------------------------------------------------------------------- | |
161 | +const getData = async () => { | |
162 | + | |
163 | + try{ | |
164 | + const response = await axios.post('/api/user/users', {}); | |
165 | + console.log('response => '); | |
166 | + console.log(response); | |
167 | + | |
168 | + console.log('response.status = ' + response.status); | |
169 | + if (response.status == 200) { | |
170 | + console.log('Search Datas: ' + JSON.stringify(response.data)); | |
171 | + | |
172 | + setData(response.data); | |
173 | + | |
174 | + toast.add({ severity: 'success', summary: 'Success', detail: 'Search successfully', life: 3000 }); | |
175 | + } | |
176 | + return response.status; | |
177 | + }catch(err){ | |
178 | + toast.add({ severity: 'error', summary: 'Error', detail: err.message, life: 3000 }); | |
179 | + return err.message; | |
180 | + } | |
181 | + | |
182 | +}; | |
183 | + | |
184 | +const setData = (responseData) => { | |
185 | + data = responseData; //조회데이타 | |
186 | + //코드타입 데이타만 업데이트 | |
187 | + let sActivated = activated.value==="전체"?"true,false":activated.value==="사용"?"true":"false"; | |
188 | + userItems.value = data.filter(rec => sActivated.indexOf(rec.activated) > -1).sort((a, b) => a.userId - b.userId) ; | |
189 | + gridApi.value.sizeColumnsToFit({ | |
190 | + defaultMinWidth: 50 | |
191 | + }); | |
192 | +} | |
193 | + | |
194 | +const buttonItems = [ | |
195 | +{ | |
196 | + label: 'Save', | |
197 | + icon: 'pi pi-save', | |
198 | + command: () => { | |
199 | + saveData(); | |
200 | + } | |
201 | +}, | |
202 | +{ | |
203 | + label: 'Download', | |
204 | + icon: 'pi pi-file-excel', | |
205 | + command: () => { | |
206 | + window.location.href = 'https://vuejs.org/'; | |
207 | + } | |
208 | +} | |
209 | +]; | |
210 | + | |
211 | +const search = () => { | |
212 | + getData(); | |
213 | +}; | |
214 | + | |
215 | +const saveData = async () => { | |
216 | + | |
217 | + try{ | |
218 | + //rowStatus가 N,U,D인 것만 필터링 | |
219 | + let updatedData = ags.agGridGetData(gridApi, true); | |
220 | + const saveParams = { | |
221 | + //여기에 업데이트된 데이타 보내기 | |
222 | + searchCond: {}, | |
223 | + saveData: updatedData | |
224 | + }; | |
225 | + const response = await axios.post('/api/user/saveUsers', saveParams); | |
226 | + console.log('response => '); | |
227 | + console.log(response); | |
228 | + | |
229 | + console.log('response.status = ' + response.status); | |
230 | + if (response.status == 200) { | |
231 | + console.log('Search Datas: ' + JSON.stringify(response.data)); | |
232 | + | |
233 | + setData(response.data); | |
234 | + | |
235 | + toast.add({ severity: 'success', summary: 'Success', detail: 'Save successfully', life: 3000 }); | |
236 | + } | |
237 | + return response.status; | |
238 | + }catch(err){ | |
239 | + toast.add({ severity: 'error', summary: 'Error', detail: err.message, life: 3000 }); | |
240 | + return err.message; | |
241 | + } | |
242 | + | |
243 | +}; | |
244 | + | |
245 | +const addRow = () => { | |
246 | + const res = ags.agGridAddRow(gridApi, 1, false); | |
247 | + console.log(res); | |
248 | +} | |
249 | + | |
250 | +const delRow = () => { | |
251 | + const selectedNodes = gridApi.value.getSelectedNodes(); //[] | |
252 | + const res = ags.agGridDelRow(gridApi, selectedNodes); | |
253 | + console.log(res); | |
254 | +} | |
255 | + | |
256 | +const refreshRow = () => { | |
257 | + const selectedRows = gridApi.value.getSelectedRows(); | |
258 | + ags.agGridEraseStatusRow(gridApi, selectedRows); | |
259 | + console.log(res); | |
260 | +} | |
261 | + | |
262 | + | |
263 | +//-------------------------------------------------------------------------------------------- | |
264 | + | |
265 | +</script> | ... | ... |
prestige-vue-4.0.0/src/views/system/UserAuthority.vue
0 → 100644
1 | +<template> | |
2 | + <div class="card"> | |
3 | + <Toast /> | |
4 | + <div class="card formgrid grid" style="margin-bottom: 0px;"> | |
5 | + <div class="field col grid" style="margin-bottom: 0px;"> | |
6 | + <div class="field col-12 md:col-6" style="margin-bottom: 0px;"> | |
7 | + <label for="username">사용자명</label> | |
8 | + <AutoComplete v-model="username" dropdown :suggestions="filteredItems" @complete="searchItems" class="w-full" /> | |
9 | + </div> | |
10 | + </div> | |
11 | + <SplitButton label="Search" icon="pi pi-plus" @click="search" :model="buttonItems" class="bg-primary" /> | |
12 | + </div> | |
13 | + <Toolbar style="background: #ffffff; border: 0px;"> | |
14 | + <template #end> | |
15 | + <Button icon="pi pi-refresh" aria-label="Filter" @click="refreshRow()"/> | |
16 | + <span style="width: 5px;"></span> | |
17 | + <Button icon="pi pi-plus" aria-label="Filter" @click="addRow()"/> | |
18 | + <span style="width: 5px;"></span> | |
19 | + <Button icon="pi pi-minus" aria-label="Filter" @click="delRow()"/> | |
20 | + </template> | |
21 | + </Toolbar> | |
22 | + <div class="grid"> | |
23 | + <div class="col-12 md:col-12" style="padding: 0; padding-right: 10px;"> | |
24 | + <ag-grid-vue | |
25 | + style="width: 100%; height: 350px;" | |
26 | + class="ag-theme-balham" | |
27 | + :columnDefs="columns" | |
28 | + :rowData="userAuthorityItems" | |
29 | + @grid-ready="onGridReady" | |
30 | + :rowSelection="rowSelection" | |
31 | + @cell-value-changed ="onCellValueChanged" | |
32 | + :defaultColDef="defaultColDef" | |
33 | + > | |
34 | + </ag-grid-vue> | |
35 | + </div> | |
36 | + | |
37 | + </div> | |
38 | + </div> | |
39 | +</template> | |
40 | + | |
41 | +<script setup> | |
42 | +//-------------------------------------------------------------------------------------------- | |
43 | +// imprort | |
44 | +//-------------------------------------------------------------------------------------------- | |
45 | +import { useToast } from "primevue/usetoast"; | |
46 | +import axios from '../../service/axios'; | |
47 | +import { onBeforeMount, ref } from 'vue'; | |
48 | +import { useI18n } from 'vue-i18n' | |
49 | +import RendererRowStatus from "../common/RendererRowStatus.vue"; | |
50 | +import ags from '../../service/AgGridService'; | |
51 | + | |
52 | +const toast = useToast(); | |
53 | + | |
54 | +//-------------------------------------------------------------------------------------------- | |
55 | +// 변수선언 | |
56 | +//-------------------------------------------------------------------------------------------- | |
57 | +const userAuthorityItems = ref(""); | |
58 | +const filteredItems = ref(); | |
59 | +const username = ref(""); | |
60 | + | |
61 | +let data = []; | |
62 | + | |
63 | +const i18n = useI18n() | |
64 | +//-------------------------------------------------------------------------------------------- | |
65 | + | |
66 | +//-------------------------------------------------------------------------------------------- | |
67 | +// ag-grid Header | |
68 | +//-------------------------------------------------------------------------------------------- | |
69 | + | |
70 | +const defaultColDef = { | |
71 | + filter: true, | |
72 | + enableCellChangeFlash: true, | |
73 | +}; | |
74 | + | |
75 | +const userNames = ref([]); | |
76 | +const authorities = ref([]); | |
77 | + | |
78 | +const columns = [ | |
79 | + { | |
80 | + headerName: "", | |
81 | + field: "rowStatus", | |
82 | + editable: false, | |
83 | + pinned: 'left', | |
84 | + maxWidth: 45, | |
85 | + cellRenderer: RendererRowStatus | |
86 | + }, | |
87 | + { | |
88 | + headerName: "사용자ID", | |
89 | + field: "userId", | |
90 | + editable: false, | |
91 | + maxWidth: 150, | |
92 | + }, | |
93 | + { | |
94 | + headerName: "사용자명", | |
95 | + field: "username", | |
96 | + editable: true, | |
97 | + cellEditor: "agSelectCellEditor", | |
98 | + cellEditorParams: { values: userNames.value }, | |
99 | + }, | |
100 | + { | |
101 | + headerName: "권한명", | |
102 | + field: "authorityName", | |
103 | + editable: true, | |
104 | + cellEditor: "agSelectCellEditor", | |
105 | + cellEditorParams: { values: authorities.value }, | |
106 | + } | |
107 | +]; | |
108 | +//-------------------------------------------------------------------------------------------- | |
109 | + | |
110 | + | |
111 | + | |
112 | +//-------------------------------------------------------------------------------------------- | |
113 | +//ag-grid function | |
114 | +//-------------------------------------------------------------------------------------------- | |
115 | +const rowSelection = ref(null); | |
116 | +const gridApi = ref(); | |
117 | + | |
118 | +onBeforeMount(() => { | |
119 | + rowSelection.value = 'single'; | |
120 | +}); | |
121 | + | |
122 | +const onCellValueChanged = (event) => { | |
123 | + let res = ags.agGridChangeStatusRow(gridApi, event); | |
124 | + console.log(res); | |
125 | +}; | |
126 | + | |
127 | +const onGridReady = (params) => { | |
128 | + gridApi.value = params.api; | |
129 | + | |
130 | + getData(); | |
131 | +}; | |
132 | + | |
133 | +const searchItems = (event) => { | |
134 | + let query = event.query; | |
135 | + let _filteredItems = []; | |
136 | + | |
137 | + for (let i = 0; i < userAuthorityItems.value.length; i++) { | |
138 | + let item = userAuthorityItems.value[i]; | |
139 | + | |
140 | + if (item.username.toLowerCase().indexOf(query.toLowerCase()) >= 0) { | |
141 | + _filteredItems.push(item.username); | |
142 | + } | |
143 | + } | |
144 | + | |
145 | + filteredItems.value = _filteredItems; | |
146 | +}; | |
147 | +//-------------------------------------------------------------------------------------------- | |
148 | + | |
149 | +//-------------------------------------------------------------------------------------------- | |
150 | +// 일반 Function | |
151 | +//-------------------------------------------------------------------------------------------- | |
152 | +const getData = async () => { | |
153 | + | |
154 | + try{ | |
155 | + const response = await axios.post('/api/user/usersAuthority', { | |
156 | + username: username.value | |
157 | + }); | |
158 | + console.log('response => '); | |
159 | + console.log(response); | |
160 | + | |
161 | + console.log('response.status = ' + response.status); | |
162 | + if (response.status == 200) { | |
163 | + console.log('Search Datas: ' + JSON.stringify(response.data)); | |
164 | + | |
165 | + setData(response.data); | |
166 | + | |
167 | + toast.add({ severity: 'success', summary: 'Success', detail: 'Search successfully', life: 3000 }); | |
168 | + } | |
169 | + return response.status; | |
170 | + }catch(err){ | |
171 | + toast.add({ severity: 'error', summary: 'Error', detail: err.message, life: 3000 }); | |
172 | + return err.message; | |
173 | + } | |
174 | + | |
175 | +}; | |
176 | + | |
177 | +const setData = (responseData) => { | |
178 | + data = responseData; //조회데이타(userAuthority, userList, authorityList) | |
179 | + | |
180 | + //리스트에 새로운 배열을 셋팅해서 넣으면 컬럼의 값과 연결이 되지 않기 때문에 기존의 배열을 조작해서 넣어야 연결이 된다. | |
181 | + userNames.value.splice(0); | |
182 | + data.userList.map(rec => userNames.value.push(rec.username)); | |
183 | + authorities.value.splice(0); | |
184 | + data.authorityList.map(rec => authorities.value.push(rec.authority_name)); | |
185 | + | |
186 | + //데이타 셋팅 | |
187 | + userAuthorityItems.value = data.userAuthority.sort((a, b) => a.userId - b.userId) ; | |
188 | + | |
189 | + gridApi.value.sizeColumnsToFit({ | |
190 | + defaultMinWidth: 50 | |
191 | + }); | |
192 | + | |
193 | + | |
194 | +} | |
195 | + | |
196 | +const buttonItems = [ | |
197 | +{ | |
198 | + label: 'Save', | |
199 | + icon: 'pi pi-save', | |
200 | + command: () => { | |
201 | + saveData(); | |
202 | + } | |
203 | +}, | |
204 | +{ | |
205 | + label: 'Download', | |
206 | + icon: 'pi pi-file-excel', | |
207 | + command: () => { | |
208 | + window.location.href = 'https://vuejs.org/'; | |
209 | + } | |
210 | +} | |
211 | +]; | |
212 | + | |
213 | +const search = () => { | |
214 | + getData(); | |
215 | +}; | |
216 | + | |
217 | +const saveData = async () => { | |
218 | + | |
219 | + try{ | |
220 | + //rowStatus가 N,U,D인 것만 필터링 | |
221 | + let updatedData = ags.agGridGetData(gridApi, true); | |
222 | + const saveParams = { | |
223 | + //여기에 업데이트된 데이타 보내기 | |
224 | + searchCond: {"username": username}, | |
225 | + saveData: updatedData | |
226 | + }; | |
227 | + const response = await axios.post('/api/user/saveUsersAuthority', saveParams); | |
228 | + console.log('response => '); | |
229 | + console.log(response); | |
230 | + | |
231 | + console.log('response.status = ' + response.status); | |
232 | + if (response.status == 200) { | |
233 | + console.log('Search Datas: ' + JSON.stringify(response.data)); | |
234 | + | |
235 | + setData(response.data); | |
236 | + | |
237 | + toast.add({ severity: 'success', summary: 'Success', detail: 'Save successfully', life: 3000 }); | |
238 | + } | |
239 | + return response.status; | |
240 | + }catch(err){ | |
241 | + toast.add({ severity: 'error', summary: 'Error', detail: err.message, life: 3000 }); | |
242 | + return err.message; | |
243 | + } | |
244 | + | |
245 | +}; | |
246 | + | |
247 | +const addRow = () => { | |
248 | + const res = ags.agGridAddRow(gridApi, 1, false); | |
249 | + console.log(res); | |
250 | +} | |
251 | + | |
252 | +const delRow = () => { | |
253 | + const selectedNodes = gridApi.value.getSelectedNodes(); //[] | |
254 | + const res = ags.agGridDelRow(gridApi, selectedNodes); | |
255 | + console.log(res); | |
256 | +} | |
257 | + | |
258 | +const refreshRow = () => { | |
259 | + const selectedRows = gridApi.value.getSelectedRows(); | |
260 | + ags.agGridEraseStatusRow(gridApi, selectedRows); | |
261 | + console.log(res); | |
262 | +} | |
263 | + | |
264 | + | |
265 | +//-------------------------------------------------------------------------------------------- | |
266 | + | |
267 | +</script> | ... | ... |
src/main/java/daeucna/config/security/JwtSecurityConfig.java
... | ... | @@ -12,7 +12,7 @@ import lombok.RequiredArgsConstructor; |
12 | 12 | @RequiredArgsConstructor |
13 | 13 | public class JwtSecurityConfig extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity> { |
14 | 14 | private final JwtTokenProvider tokenProvider; |
15 | - | |
15 | + | |
16 | 16 | @Override |
17 | 17 | public void configure(HttpSecurity http) { |
18 | 18 | ... | ... |
src/main/java/daeucna/config/security/SecurityConfig.java
... | ... | @@ -10,8 +10,11 @@ import org.springframework.security.config.http.SessionCreationPolicy; |
10 | 10 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; |
11 | 11 | import org.springframework.security.crypto.password.PasswordEncoder; |
12 | 12 | import org.springframework.security.web.SecurityFilterChain; |
13 | +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; | |
13 | 14 | |
15 | +import daeucna.config.security.jwt.JwtAccessDeniedHandler; | |
14 | 16 | import daeucna.config.security.jwt.JwtAuthenticationEntryPoint; |
17 | +import daeucna.config.security.jwt.JwtFilter; | |
15 | 18 | import daeucna.config.security.jwt.JwtTokenProvider; |
16 | 19 | import lombok.RequiredArgsConstructor; |
17 | 20 | |
... | ... | @@ -22,6 +25,7 @@ public class SecurityConfig { |
22 | 25 | |
23 | 26 | private final JwtTokenProvider tokenProvider; |
24 | 27 | private final JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint; |
28 | + private final JwtAccessDeniedHandler jwtAccessDeniedHandler; | |
25 | 29 | |
26 | 30 | // PasswordEncoder는 BCryptPasswordEncoder를 사용 |
27 | 31 | @Bean |
... | ... | @@ -45,6 +49,11 @@ public class SecurityConfig { |
45 | 49 | // .anyRequest().permitAll() |
46 | 50 | .anyRequest().authenticated() // 그 외 인증 없이 접근X |
47 | 51 | ) |
52 | + .exceptionHandling(exceptionHandling -> exceptionHandling | |
53 | + .authenticationEntryPoint(jwtAuthenticationEntryPoint) | |
54 | + .accessDeniedPage("/api/exceptionDenied") | |
55 | + .accessDeniedHandler(jwtAccessDeniedHandler) | |
56 | + ) | |
48 | 57 | .formLogin(Customizer.withDefaults()) |
49 | 58 | .headers((headers) -> |
50 | 59 | headers |
... | ... | @@ -52,16 +61,13 @@ public class SecurityConfig { |
52 | 61 | .sameOrigin() |
53 | 62 | ) |
54 | 63 | ) |
55 | - .exceptionHandling(exceptionHandling -> exceptionHandling | |
56 | - .authenticationEntryPoint(jwtAuthenticationEntryPoint) | |
57 | - .accessDeniedPage("/api/exceptionDenied") | |
58 | - ) | |
59 | 64 | // 세션을 사용하지 않기 때문에 STATELESS로 설정 |
60 | 65 | .sessionManagement((sessionManagement) -> |
61 | 66 | sessionManagement |
62 | 67 | .sessionCreationPolicy(SessionCreationPolicy.STATELESS) |
63 | 68 | ) |
64 | - .apply(new JwtSecurityConfig(tokenProvider)); // JwtFilter를 addFilterBefore로 등록했던 JwtSecurityConfig class 적용 | |
69 | + .addFilterBefore(new JwtFilter(tokenProvider), UsernamePasswordAuthenticationFilter.class); | |
70 | +// .apply(new JwtSecurityConfig(tokenProvider)); // JwtFilter를 addFilterBefore로 등록했던 JwtSecurityConfig class 적용 | |
65 | 71 | |
66 | 72 | return httpSecurity.build(); |
67 | 73 | } | ... | ... |
src/main/java/daeucna/config/security/controller/ExceptionController.java
... | ... | @@ -16,7 +16,7 @@ public class ExceptionController { |
16 | 16 | @Operation(summary = "인가 거부", description = "인가에 따른 예외가 발생했습니다.") |
17 | 17 | @RequestMapping(value = "/exceptionDenied", method = {RequestMethod.GET, RequestMethod.POST}) |
18 | 18 | public void AccessDeniedException() { |
19 | - throw new AccessDeniedException(""); | |
19 | + throw new AccessDeniedException("인가거부"); | |
20 | 20 | } |
21 | 21 | |
22 | 22 | } | ... | ... |
src/main/java/daeucna/config/security/controller/UserController.java
... | ... | @@ -18,7 +18,7 @@ import jakarta.servlet.http.HttpServletResponse; |
18 | 18 | import jakarta.validation.Valid; |
19 | 19 | import lombok.RequiredArgsConstructor; |
20 | 20 | |
21 | -@RestController | |
21 | +@RestController(value = "SecurityUserController") | |
22 | 22 | @RequiredArgsConstructor |
23 | 23 | @RequestMapping("/api") |
24 | 24 | public class UserController { | ... | ... |
src/main/java/daeucna/config/security/jwt/JwtAccessDeniedHandler.java
0 → 100644
1 | +package daeucna.config.security.jwt; | |
2 | + | |
3 | +import java.io.IOException; | |
4 | + | |
5 | +import org.springframework.security.access.AccessDeniedException; | |
6 | +import org.springframework.security.web.access.AccessDeniedHandler; | |
7 | +import org.springframework.stereotype.Component; | |
8 | + | |
9 | +import jakarta.servlet.http.HttpServletRequest; | |
10 | +import jakarta.servlet.http.HttpServletResponse; | |
11 | + | |
12 | +@Component | |
13 | +public class JwtAccessDeniedHandler implements AccessDeniedHandler { | |
14 | + | |
15 | + @Override | |
16 | + public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException { | |
17 | + //필요한 권한이 없이 접근하려 할때 403 | |
18 | + response.sendError(HttpServletResponse.SC_FORBIDDEN); | |
19 | + } | |
20 | +} | ... | ... |
src/main/java/daeucna/config/security/jwt/JwtTokenProvider.java
... | ... | @@ -89,11 +89,16 @@ public class JwtTokenProvider implements InitializingBean { |
89 | 89 | .parseSignedClaims(token) |
90 | 90 | .getPayload(); |
91 | 91 | |
92 | - Collection<? extends GrantedAuthority> authorities = | |
93 | - Arrays.stream(claims.get(AUTHORITIES_KEY).toString().split(",")) | |
94 | - .map(SimpleGrantedAuthority::new) | |
95 | - .collect(Collectors.toList()); | |
92 | +// Collection<? extends GrantedAuthority> authorities = | |
93 | +// Arrays.stream(claims.get(AUTHORITIES_KEY).toString().split(",")) | |
94 | +// .map(SimpleGrantedAuthority::new) | |
95 | +// .collect(Collectors.toList()); | |
96 | 96 | |
97 | + Collection<? extends GrantedAuthority> authorities = | |
98 | + Arrays.stream(claims.get(AUTHORITIES_KEY).toString().split(",")) | |
99 | + .map(role -> new SimpleGrantedAuthority(role)) | |
100 | + .collect(Collectors.toList()); | |
101 | + | |
97 | 102 | User principal = new User(claims.getSubject(), "", authorities); |
98 | 103 | |
99 | 104 | return new UsernamePasswordAuthenticationToken(principal, token, authorities); | ... | ... |
src/main/java/daeucna/mapper/primary/system/UserMapper.java
0 → 100644
1 | +package daeucna.mapper.primary.system; | |
2 | + | |
3 | +import java.util.List; | |
4 | +import java.util.Map; | |
5 | + | |
6 | +import org.apache.ibatis.annotations.Mapper; | |
7 | + | |
8 | +import daeucna.system.user.UserAuthorityDto; | |
9 | +import daeucna.system.user.UserDto; | |
10 | + | |
11 | +@Mapper | |
12 | +public interface UserMapper { | |
13 | + List<UserDto> getUsers(UserDto param); | |
14 | + int saveUser(UserDto param); | |
15 | + void deleteUser(UserDto param); | |
16 | + | |
17 | + List<UserAuthorityDto> getUsersAuthority(UserAuthorityDto param); | |
18 | + int saveUserAuthority(UserAuthorityDto param); | |
19 | + void deleteUserAuthority(UserAuthorityDto param); | |
20 | + | |
21 | + List<Map> getUserList(Map param); | |
22 | + List<Map> getAuthorityList(Map param); | |
23 | + | |
24 | +} | |
0 | 25 | \ No newline at end of file | ... | ... |
src/main/java/daeucna/system/code/CodeServiceImpl.java
... | ... | @@ -42,7 +42,7 @@ public class CodeServiceImpl implements CodeService { |
42 | 42 | //삭제처리먼저 |
43 | 43 | for (CodeDto curRec : params.getSaveData()) { |
44 | 44 | String sRowStatus = curRec.getRowStatus(); |
45 | - if ("D".indexOf(sRowStatus) > 0) { | |
45 | + if ("D".indexOf(sRowStatus) > -1) { | |
46 | 46 | //코드 |
47 | 47 | codeMapper.deleteCmmnCode(curRec); |
48 | 48 | //코드Nls |
... | ... | @@ -52,7 +52,7 @@ public class CodeServiceImpl implements CodeService { |
52 | 52 | //신규및 업데이트 처리 |
53 | 53 | for (CodeDto curRec : params.getSaveData()) { |
54 | 54 | String sRowStatus = curRec.getRowStatus(); |
55 | - if ("N,U".indexOf(sRowStatus) > 0) { | |
55 | + if ("N,U".indexOf(sRowStatus) > -1) { | |
56 | 56 | //코드 |
57 | 57 | codeMapper.saveCmmnCode(curRec); |
58 | 58 | //코드Nls | ... | ... |
src/main/java/daeucna/system/user/UserAuthorityDto.java
0 → 100644
src/main/java/daeucna/system/user/UserAuthoritySaveDto.java
0 → 100644
src/main/java/daeucna/system/user/UserController.java
0 → 100644
1 | +package daeucna.system.user; | |
2 | + | |
3 | +import java.util.ArrayList; | |
4 | +import java.util.HashMap; | |
5 | +import java.util.List; | |
6 | +import java.util.Map; | |
7 | + | |
8 | +import org.springframework.beans.factory.annotation.Autowired; | |
9 | +import org.springframework.http.ResponseEntity; | |
10 | +import org.springframework.web.bind.annotation.PostMapping; | |
11 | +import org.springframework.web.bind.annotation.RequestBody; | |
12 | +import org.springframework.web.bind.annotation.RequestMapping; | |
13 | +import org.springframework.web.bind.annotation.RestController; | |
14 | + | |
15 | +import lombok.RequiredArgsConstructor; | |
16 | + | |
17 | +@RestController | |
18 | +@RequiredArgsConstructor | |
19 | +@RequestMapping("/api/user") | |
20 | +public class UserController { | |
21 | + @Autowired | |
22 | + private final UserService userService; | |
23 | + | |
24 | + @PostMapping("/users") | |
25 | + public ResponseEntity<List<UserDto>> getUsers(@RequestBody UserDto param) { | |
26 | + List<UserDto> rtnVal = new ArrayList<UserDto>(); | |
27 | + | |
28 | + rtnVal = userService.getUsers(param); | |
29 | + | |
30 | + return ResponseEntity.ok(rtnVal); | |
31 | + } | |
32 | + | |
33 | + @PostMapping("/saveUsers") | |
34 | + public ResponseEntity<List<UserDto>> saveUsers(@RequestBody UserSaveDto params) { | |
35 | + | |
36 | + List<UserDto> rtnVal = new ArrayList<UserDto>(); | |
37 | + | |
38 | + rtnVal = userService.saveUsers(params); | |
39 | + | |
40 | + return ResponseEntity.ok(rtnVal); | |
41 | + } | |
42 | + | |
43 | + | |
44 | + | |
45 | + @PostMapping("/usersAuthority") | |
46 | + public ResponseEntity<Map<String, Object>> usersAuthority(@RequestBody UserAuthorityDto param) { | |
47 | + Map<String, Object> rtnVal = new HashMap<String, Object>(); | |
48 | + | |
49 | + rtnVal = userService.getUsersAuthority(param); | |
50 | + | |
51 | + return ResponseEntity.ok(rtnVal); | |
52 | + } | |
53 | + | |
54 | + @PostMapping("/saveUsersAuthority") | |
55 | + public ResponseEntity<Map<String, Object>> saveUsersAuthority(@RequestBody UserAuthoritySaveDto params) { | |
56 | + | |
57 | + Map<String, Object> rtnVal = new HashMap<String, Object>(); | |
58 | + | |
59 | + rtnVal = userService.saveUsersAuthority(params); | |
60 | + | |
61 | + return ResponseEntity.ok(rtnVal); | |
62 | + } | |
63 | + | |
64 | +} | |
0 | 65 | \ No newline at end of file | ... | ... |
1 | +package daeucna.system.user; | |
2 | + | |
3 | +import java.util.List; | |
4 | +import java.util.Map; | |
5 | + | |
6 | +public interface UserService { | |
7 | + | |
8 | + @SuppressWarnings("rawtypes") | |
9 | + public List<UserDto> getUsers(UserDto param); | |
10 | + | |
11 | + @SuppressWarnings("rawtypes") | |
12 | + public List<UserDto> saveUsers(UserSaveDto params); | |
13 | + | |
14 | + | |
15 | + @SuppressWarnings("rawtypes") | |
16 | + public Map<String, Object> getUsersAuthority(UserAuthorityDto param); | |
17 | + | |
18 | + @SuppressWarnings("rawtypes") | |
19 | + public Map<String, Object> saveUsersAuthority(UserAuthoritySaveDto params); | |
20 | + | |
21 | +} | |
0 | 22 | \ No newline at end of file | ... | ... |
src/main/java/daeucna/system/user/UserServiceImpl.java
0 → 100644
1 | +package daeucna.system.user; | |
2 | + | |
3 | +import java.util.ArrayList; | |
4 | +import java.util.HashMap; | |
5 | +import java.util.List; | |
6 | +import java.util.Map; | |
7 | + | |
8 | +import org.springframework.beans.factory.annotation.Autowired; | |
9 | +import org.springframework.security.crypto.password.PasswordEncoder; | |
10 | +import org.springframework.stereotype.Repository; | |
11 | +import org.springframework.stereotype.Service; | |
12 | +import org.springframework.transaction.annotation.Propagation; | |
13 | +import org.springframework.transaction.annotation.Transactional; | |
14 | + | |
15 | +import daeucna.mapper.primary.system.UserMapper; | |
16 | +import daeucna.utils.StringUtil; | |
17 | +import lombok.RequiredArgsConstructor; | |
18 | +import lombok.extern.slf4j.Slf4j; | |
19 | + | |
20 | +@Service | |
21 | +@RequiredArgsConstructor | |
22 | +@Slf4j | |
23 | +@Repository | |
24 | +@Transactional(propagation = Propagation.REQUIRED, rollbackFor = { Exception.class }) | |
25 | +public class UserServiceImpl implements UserService { | |
26 | + @Autowired | |
27 | + private UserMapper userMapper; | |
28 | + private final PasswordEncoder passwordEncoder; | |
29 | + | |
30 | + @Override | |
31 | + public List<UserDto> getUsers(UserDto param) { | |
32 | + List<UserDto> lUserDto = new ArrayList<UserDto>(); | |
33 | + | |
34 | + lUserDto = userMapper.getUsers(param); | |
35 | + | |
36 | + log.info("getUsers"); | |
37 | + return lUserDto; | |
38 | + } | |
39 | + | |
40 | + @SuppressWarnings("unchecked") | |
41 | + @Override | |
42 | + public List<UserDto> saveUsers(UserSaveDto params) { | |
43 | + | |
44 | + // 삭제처리먼저 | |
45 | + for (UserDto curRec : params.getSaveData()) { | |
46 | + String sRowStatus = curRec.getRowStatus(); | |
47 | + if ("D".indexOf(sRowStatus) > -1) { | |
48 | + // 사용자 | |
49 | + userMapper.deleteUser(curRec); | |
50 | + } | |
51 | + } | |
52 | + // 신규및 업데이트 처리 | |
53 | + for (UserDto curRec : params.getSaveData()) { | |
54 | + String sRowStatus = curRec.getRowStatus(); | |
55 | + if ("N,U".indexOf(sRowStatus) > -1) { | |
56 | + // 사용자 | |
57 | + // 패스워드를 암호화 | |
58 | + String sEncodedPassword = null; | |
59 | + String sOrgPassword = StringUtil.defaultIfEmpty(curRec.getPassword(), null); | |
60 | + if (sOrgPassword != null) sEncodedPassword = passwordEncoder.encode(sOrgPassword); | |
61 | + curRec.setPassword(sEncodedPassword); | |
62 | + userMapper.saveUser(curRec); | |
63 | + } | |
64 | + } | |
65 | + | |
66 | + List<UserDto> lUserDto = userMapper.getUsers(params.getSearchCond()); | |
67 | + | |
68 | + log.info("saveUsers"); | |
69 | + return lUserDto; | |
70 | + } | |
71 | + | |
72 | + @Override | |
73 | + public Map<String, Object> getUsersAuthority(UserAuthorityDto param) { | |
74 | + Map<String, Object> rtnVal = new HashMap<String, Object>(); | |
75 | + | |
76 | + List<UserAuthorityDto> lUserAuthority = userMapper.getUsersAuthority(param); | |
77 | + rtnVal.put("userAuthority", lUserAuthority); | |
78 | + | |
79 | + List<Map> lmUserList = userMapper.getUserList(new HashMap<String, String>()); | |
80 | + rtnVal.put("userList", lmUserList); | |
81 | + | |
82 | + List<Map> lmAuthorityList = userMapper.getAuthorityList(new HashMap<String, String>()); | |
83 | + rtnVal.put("authorityList", lmAuthorityList); | |
84 | + | |
85 | + log.info("getUsersAuthority"); | |
86 | + return rtnVal; | |
87 | + } | |
88 | + | |
89 | + @Override | |
90 | + public Map<String, Object> saveUsersAuthority(UserAuthoritySaveDto params) { | |
91 | + | |
92 | + // 삭제처리먼저 | |
93 | + for (UserAuthorityDto curRec : params.getSaveData()) { | |
94 | + String sRowStatus = curRec.getRowStatus(); | |
95 | + if ("D".indexOf(sRowStatus) > -1) { | |
96 | + // 사용자 | |
97 | + userMapper.deleteUserAuthority(curRec); | |
98 | + } | |
99 | + } | |
100 | + // 신규및 업데이트 처리 | |
101 | + for (UserAuthorityDto curRec : params.getSaveData()) { | |
102 | + String sRowStatus = curRec.getRowStatus(); | |
103 | + if ("N,U".indexOf(sRowStatus) > -1) { | |
104 | + // 사용자 | |
105 | + userMapper.saveUserAuthority(curRec); | |
106 | + } | |
107 | + } | |
108 | + | |
109 | + Map<String, Object> rtnVal = getUsersAuthority(params.getSearchCond()); | |
110 | + | |
111 | + log.info("saveUsersAuthority"); | |
112 | + return rtnVal; | |
113 | + } | |
114 | + | |
115 | +} | |
0 | 116 | \ No newline at end of file | ... | ... |
1 | +package daeucna.utils; | |
2 | + | |
3 | +import java.sql.Timestamp; | |
4 | +import java.text.SimpleDateFormat; | |
5 | +import java.util.Locale; | |
6 | + | |
7 | +public class ConvertUtil { | |
8 | + | |
9 | + /** | |
10 | + * | |
11 | + * Timestamp 형식의 날짜를 입력한 Format 과 Locale 에 따라 Formatting 한다. | |
12 | + * | |
13 | + * <pre> | |
14 | + * | |
15 | + * [사용 예제] | |
16 | + * | |
17 | + * formatTimestamp("2004-02-25 15:45:31.156","yyyy년MM월dd일",Locale) ===> 2004년02월25일 | |
18 | + * | |
19 | + * </pre> | |
20 | + * | |
21 | + * @param timestamp Timestamp 형식의 날짜 | |
22 | + * @param format SimpleDateFormat 에 적용할 format | |
23 | + * @param locale 국가별 LOCALE | |
24 | + * @return java.lang.String | |
25 | + */ | |
26 | + public static String formatTimestamp(Timestamp timestamp, String format, Locale locale) { | |
27 | + | |
28 | + SimpleDateFormat formatter = new SimpleDateFormat(format, locale); | |
29 | + return formatter.format(timestamp); | |
30 | + | |
31 | + } | |
32 | + | |
33 | +} | |
0 | 34 | \ No newline at end of file | ... | ... |
1 | +package daeucna.utils; | |
2 | + | |
3 | +import java.sql.Timestamp; | |
4 | +import java.text.ParseException; | |
5 | +import java.util.Calendar; | |
6 | +import java.util.GregorianCalendar; | |
7 | +import java.util.Locale; | |
8 | + | |
9 | +public class DateUtil { | |
10 | + | |
11 | + public static java.util.Date formatValidDate(String date, String format, Locale lcal) throws Exception { | |
12 | + | |
13 | + if (date == null || format == null) | |
14 | + return null; | |
15 | + if (lcal == null) | |
16 | + lcal = java.util.Locale.KOREA; // 디폴트는 Korea | |
17 | + | |
18 | + java.text.SimpleDateFormat formatter = new java.text.SimpleDateFormat(format, lcal); | |
19 | + java.util.Date formattedDate = null; | |
20 | + | |
21 | + formattedDate = formatter.parse(date); | |
22 | + | |
23 | + return formattedDate; | |
24 | + } | |
25 | + | |
26 | + /** | |
27 | + * | |
28 | + * yyyyMMdd Format으로 입력된 날짜에 addDay 만큼 더한 날짜(yyyyMMdd)를 Return한다. | |
29 | + * | |
30 | + * <pre> | |
31 | + * | |
32 | + * [사용 예제] | |
33 | + * | |
34 | + * addDays("20040225", 1) ===> 20040226 | |
35 | + * | |
36 | + * </pre> | |
37 | + * | |
38 | + * @param date | |
39 | + * @param addDay | |
40 | + * @return String | |
41 | + * @throws ChainedException | |
42 | + */ | |
43 | + public static String addDays(String date, int addDay) throws Exception { | |
44 | + return addDays(date, "yyyyMMdd", addDay, null); | |
45 | + } | |
46 | + | |
47 | + /** | |
48 | + * | |
49 | + * 입력한 날짜를 입력한 Format으로 해석하여 addDay 만큼 더한 날짜를 Return한다. | |
50 | + * | |
51 | + * @param date | |
52 | + * @param addDay 더할 일수 | |
53 | + * @param format | |
54 | + * @return String | |
55 | + * @throws ChainedException | |
56 | + */ | |
57 | + public static String addDays(String date, String format, int addDay, Locale lcal) throws Exception { | |
58 | + if (lcal == null) | |
59 | + lcal = java.util.Locale.KOREA; // 디폴트는 Korea | |
60 | + | |
61 | + java.text.SimpleDateFormat formatter = new java.text.SimpleDateFormat(format, lcal); | |
62 | + java.util.Date formattedDate = formatValidDate(date, format, lcal); | |
63 | + formattedDate.setTime(formattedDate.getTime() + ((long) addDay * 1000 * 60 * 60 * 24)); | |
64 | + return formatter.format(formattedDate); | |
65 | + } | |
66 | + | |
67 | + /** | |
68 | + * | |
69 | + * yyyyMMdd Format으로 입력된 날짜에 addMonth 만큼 더한 날짜를 Return한다. | |
70 | + * | |
71 | + * @param date | |
72 | + * @param addMonth 더할 월수 | |
73 | + * @return String | |
74 | + * @throws ChainedException | |
75 | + */ | |
76 | + public static String addMonths(String date, int addMonth) throws Exception { | |
77 | + return addMonths(date, "yyyyMMdd", addMonth, null); | |
78 | + } | |
79 | + | |
80 | + /** | |
81 | + * | |
82 | + * 입력한 날짜를 입력한 Format으로 해석하여 addMonth 만큼 더한 날짜를 Return한다. | |
83 | + * | |
84 | + * @param date | |
85 | + * @param addMonth 더할 월수 | |
86 | + * @param format | |
87 | + * @return String | |
88 | + * @throws ChainedException | |
89 | + */ | |
90 | + public static String addMonths(String date, String format, int addMonth, Locale lcal) throws Exception { | |
91 | + if (lcal == null) | |
92 | + lcal = java.util.Locale.KOREA; // 디폴트는 Korea | |
93 | + java.text.SimpleDateFormat formatter = new java.text.SimpleDateFormat(format, lcal); | |
94 | + java.util.Date formattedDate = formatValidDate(date, format, lcal); | |
95 | + | |
96 | + java.text.SimpleDateFormat yearFormat = new java.text.SimpleDateFormat("yyyy", lcal); | |
97 | + java.text.SimpleDateFormat monthFormat = new java.text.SimpleDateFormat("MM", lcal); | |
98 | + java.text.SimpleDateFormat dayFormat = new java.text.SimpleDateFormat("dd", lcal); | |
99 | + | |
100 | + int year = Integer.parseInt(yearFormat.format(formattedDate)); | |
101 | + int month = Integer.parseInt(monthFormat.format(formattedDate)); | |
102 | + int day = Integer.parseInt(dayFormat.format(formattedDate)); | |
103 | + month += addMonth; | |
104 | + if (addMonth > 0) { | |
105 | + while (month > 12) { | |
106 | + month -= 12; | |
107 | + year += 1; | |
108 | + } | |
109 | + } else { | |
110 | + while (month <= 0) { | |
111 | + month += 12; | |
112 | + year -= 1; | |
113 | + } | |
114 | + } | |
115 | + java.text.DecimalFormat fourDf = new java.text.DecimalFormat("0000"); | |
116 | + java.text.DecimalFormat twoDf = new java.text.DecimalFormat("00"); | |
117 | + String tempDate = String.valueOf(fourDf.format(year)) + String.valueOf(twoDf.format(month)) | |
118 | + + String.valueOf(twoDf.format(day)); | |
119 | + java.util.Date targetDate = null; | |
120 | + try { | |
121 | + targetDate = formatValidDate(tempDate, "yyyyMMdd", lcal); | |
122 | + } catch (Exception e) { | |
123 | + day = getLastDay(year, month); | |
124 | + tempDate = String.valueOf(fourDf.format(year)) + String.valueOf(twoDf.format(month)) | |
125 | + + String.valueOf(twoDf.format(day)); | |
126 | + targetDate = formatValidDate(tempDate, "yyyyMMdd", lcal); | |
127 | + } | |
128 | + return formatter.format(targetDate); | |
129 | + } | |
130 | + | |
131 | + /** | |
132 | + * | |
133 | + * yyyyMMdd Format으로 입력된 날짜에 addYear 만큼 더한 날짜를 Return한다. | |
134 | + * | |
135 | + * @param date | |
136 | + * @param addYear 더할 년수 | |
137 | + * @return String | |
138 | + * @throws ChainedException | |
139 | + */ | |
140 | + public static String addYears(String date, int addYear) throws Exception { | |
141 | + return addYears(date, addYear, "yyyyMMdd", null); | |
142 | + } | |
143 | + | |
144 | + /** | |
145 | + * | |
146 | + * 입력한 날짜를 입력한 Format으로 해석하여 addYear 만큼 더한 날짜를 Return한다. | |
147 | + * | |
148 | + * @param date | |
149 | + * @param addYear 더할 년수 | |
150 | + * @param format | |
151 | + * @return String | |
152 | + * @throws ChainedException | |
153 | + */ | |
154 | + public static String addYears(String date, int addYear, String format, Locale lcal) throws Exception { | |
155 | + if (lcal == null) | |
156 | + lcal = java.util.Locale.KOREA; // 디폴트는 Korea | |
157 | + | |
158 | + java.text.SimpleDateFormat formatter = new java.text.SimpleDateFormat(format, lcal); | |
159 | + java.util.Date formattedDate = formatValidDate(date, format, lcal); | |
160 | + | |
161 | + Calendar calendar = new GregorianCalendar(); | |
162 | + calendar.setTime(formattedDate); | |
163 | + calendar.add(Calendar.YEAR, addYear); | |
164 | + formattedDate = calendar.getTime(); | |
165 | + | |
166 | + return formatter.format(formattedDate); | |
167 | + | |
168 | + } | |
169 | + | |
170 | + /** | |
171 | + * | |
172 | + * 현재 시각을 HHmmss Format 의 String 으로 Return한다. | |
173 | + * | |
174 | + * @return java.lang.String | |
175 | + */ | |
176 | + public static String getCurrentTimeString() { | |
177 | + return getCurrentDateString("HHmmss", null); | |
178 | + } | |
179 | + | |
180 | + /** | |
181 | + * | |
182 | + * 현재 날짜와 시각을 yyyy-MM-dd hh:mm:ss.fffffffff Format의 Timestamp 로 Return한다. | |
183 | + * | |
184 | + * @return Timestamp | |
185 | + */ | |
186 | + public static Timestamp getCurrentTimeStamp() { | |
187 | + return new Timestamp(new GregorianCalendar().getTime().getTime()); | |
188 | + } | |
189 | + | |
190 | + /** | |
191 | + * | |
192 | + * 현재 날짜를 yyyyMMdd Format 의 String 으로 Return한다. | |
193 | + * | |
194 | + * @return java.lang.String | |
195 | + */ | |
196 | + public static String getCurrentDateString() { | |
197 | + return getCurrentDateString("yyyyMMdd", null); | |
198 | + } | |
199 | + | |
200 | + /** | |
201 | + * | |
202 | + * 현재 날짜를 주어진 Format 의 String 으로 Return한다. | |
203 | + * | |
204 | + * <pre> | |
205 | + * | |
206 | + * [사용 예제] | |
207 | + * | |
208 | + * CDateUtil.getCurrentDateString("yyyy/MM/dd") ===> 2004/02/24 | |
209 | + * CDateUtil.getCurrentDateString("HH:mm:ss")); ===> 13:40:05 | |
210 | + * CDateUtil.getCurrentDateString("hh:mm:ss")); ===> 01:40:05 | |
211 | + * | |
212 | + * format : h hour in am/pm (1~12) | |
213 | + * format : H hour in day (0~23) | |
214 | + * | |
215 | + * </pre> | |
216 | + * | |
217 | + * @param format | |
218 | + * @return java.lang.String | |
219 | + */ | |
220 | + public static String getCurrentDateString(String format, Locale lcal) { | |
221 | + if (lcal == null) lcal = java.util.Locale.KOREA; | |
222 | + return ConvertUtil.formatTimestamp(getCurrentTimeStamp(), format, lcal); | |
223 | + } | |
224 | + | |
225 | + /** | |
226 | + * | |
227 | + * yyyyMMdd Format으로 입력된 날짜가 유효한 날짜인지 확인한다. | |
228 | + * | |
229 | + * <pre> | |
230 | + * | |
231 | + * [사용 예제] | |
232 | + * | |
233 | + * CDateUtil.isValidDate("20050225") ===> true | |
234 | + * | |
235 | + * </pre> | |
236 | + * | |
237 | + * @param date | |
238 | + * @return boolean | |
239 | + * @throws ChainedException | |
240 | + */ | |
241 | + public static boolean isValidDate(String date) throws Exception { | |
242 | + return DateUtil.isValidDate(date, "yyyyMMdd", null); | |
243 | + } | |
244 | + | |
245 | + /** | |
246 | + * | |
247 | + * 입력된 날짜와 입력된 Format 으로 해석하여 입력된 날짜가 유효한 날짜인지 확인한다. | |
248 | + * | |
249 | + * <pre> | |
250 | + * | |
251 | + * [사용 예제] | |
252 | + * | |
253 | + * CDateUtil.isValidDate("2004-02-99","yyyy-MM-dd") ===> false | |
254 | + * | |
255 | + * </pre> | |
256 | + * | |
257 | + * @param date | |
258 | + * @return boolean | |
259 | + * @throws ChainedException | |
260 | + */ | |
261 | + public static boolean isValidDate(String date, String format, Locale lcal) throws Exception { | |
262 | + if (lcal == null) | |
263 | + lcal = java.util.Locale.KOREA; | |
264 | + try { | |
265 | + java.text.SimpleDateFormat formatter = new java.text.SimpleDateFormat(format, lcal); | |
266 | + java.util.Date formattedDate = null; | |
267 | + | |
268 | + try { | |
269 | + | |
270 | + formattedDate = formatter.parse(date); | |
271 | + | |
272 | + } catch (java.text.ParseException e) { | |
273 | + return false; | |
274 | + } | |
275 | + | |
276 | + if (!formatter.format(formattedDate).equals(date)) | |
277 | + return false; | |
278 | + | |
279 | + return true; | |
280 | + } catch (Exception e) { | |
281 | + return false; | |
282 | + } | |
283 | + } | |
284 | + | |
285 | + /** | |
286 | + * | |
287 | + * yyyyMMdd Format으로 입력된 from 날짜와 to 날짜 사이의 일수를 Return한다. | |
288 | + * | |
289 | + * <pre> | |
290 | + * | |
291 | + * [사용 예제] | |
292 | + * | |
293 | + * daysBetween("20040225", "20040301") ===> 5 | |
294 | + * | |
295 | + * </pre> | |
296 | + * | |
297 | + * @param from | |
298 | + * @param to | |
299 | + * @return int | |
300 | + * @throws ChainedException | |
301 | + */ | |
302 | + public static int getDaysBetween(String from, String to) throws Exception { | |
303 | + return getDaysBetween(from, to, "yyyyMMdd", null); | |
304 | + } | |
305 | + | |
306 | + /** | |
307 | + * | |
308 | + * 입력된 from 날짜와 to 날짜를 입력된 Format으로 해석하여 날짜 사이의 일수를 Return한다. | |
309 | + * | |
310 | + * <pre> | |
311 | + * | |
312 | + * [사용 예제] | |
313 | + * | |
314 | + * daysBetween("2004-02-25", "2004-03-01", "yyyy-MM-dd") ===> 5 | |
315 | + * | |
316 | + * </pre> | |
317 | + * | |
318 | + * @param from | |
319 | + * @param to | |
320 | + * @param format | |
321 | + * @return int | |
322 | + * @throws ChainedException | |
323 | + */ | |
324 | + public static int getDaysBetween(String from, String to, String format, Locale lcal) throws Exception { | |
325 | + if (lcal == null) | |
326 | + lcal = java.util.Locale.KOREA; | |
327 | + java.util.Date d1 = formatValidDate(from, format, lcal); | |
328 | + java.util.Date d2 = formatValidDate(to, format, lcal); | |
329 | + long duration = d2.getTime() - d1.getTime(); | |
330 | + return (int) (duration / (1000 * 60 * 60 * 24)); | |
331 | + } | |
332 | + | |
333 | + /** | |
334 | + * | |
335 | + * yyyyMMdd Format으로 입력된 from 날짜와 to 날짜 사이의 월수를 Return한다. | |
336 | + * | |
337 | + * <pre> | |
338 | + * | |
339 | + * [사용 예제] | |
340 | + * | |
341 | + * monthsBetween("20040225", "20041001") ===> 8 | |
342 | + * | |
343 | + * </pre> | |
344 | + * | |
345 | + * @param from | |
346 | + * @param to | |
347 | + * @return int | |
348 | + * @throws ChainedException | |
349 | + */ | |
350 | + public static int getMonthsBetween(String from, String to) throws Exception { | |
351 | + return getMonthsBetween(from, to, "yyyyMMdd", null); | |
352 | + } | |
353 | + | |
354 | + /** | |
355 | + * | |
356 | + * 입력된 from 날짜와 to 날짜를 입력된 Format으로 해석하여 날짜 사이의 월수를 Return한다. | |
357 | + * | |
358 | + * <pre> | |
359 | + * | |
360 | + * [사용 예제] | |
361 | + * | |
362 | + * monthsBetween("2004-02-25", "2004-10-01", "yyyy-MM-dd") ===> 8 | |
363 | + * | |
364 | + * </pre> | |
365 | + * | |
366 | + * @param from | |
367 | + * @param to | |
368 | + * @param format | |
369 | + * @return int | |
370 | + * @throws ChainedException | |
371 | + */ | |
372 | + public static int getMonthsBetween(String from, String to, String format, Locale lcal) throws Exception { | |
373 | + if (lcal == null) | |
374 | + lcal = java.util.Locale.KOREA; | |
375 | + java.util.Date fromDate = formatValidDate(from, format, lcal); | |
376 | + java.util.Date toDate = formatValidDate(to, format, lcal); | |
377 | + // if two date are same, return 0. | |
378 | + if (fromDate.compareTo(toDate) == 0) | |
379 | + return 0; | |
380 | + java.text.SimpleDateFormat yearFormat = new java.text.SimpleDateFormat("yyyy", lcal); | |
381 | + java.text.SimpleDateFormat monthFormat = new java.text.SimpleDateFormat("MM", lcal); | |
382 | + java.text.SimpleDateFormat dayFormat = new java.text.SimpleDateFormat("dd", lcal); | |
383 | + int fromYear = Integer.parseInt(yearFormat.format(fromDate)); | |
384 | + int toYear = Integer.parseInt(yearFormat.format(toDate)); | |
385 | + int fromMonth = Integer.parseInt(monthFormat.format(fromDate)); | |
386 | + int toMonth = Integer.parseInt(monthFormat.format(toDate)); | |
387 | + int fromDay = Integer.parseInt(dayFormat.format(fromDate)); | |
388 | + int toDay = Integer.parseInt(dayFormat.format(toDate)); | |
389 | + int result = 0; | |
390 | + result += ((toYear - fromYear) * 12); | |
391 | + result += (toMonth - fromMonth); | |
392 | + // if (((toDay - fromDay) < 0) ) result += fromDate.compareTo(toDate); | |
393 | + // ceil과 floor의 효과 | |
394 | + if (((toDay - fromDay) > 0)) | |
395 | + result += toDate.compareTo(fromDate); | |
396 | + return result; | |
397 | + } | |
398 | + | |
399 | + /** | |
400 | + * | |
401 | + * yyyyMMdd Format으로 입력된 from 날짜와 to 날짜 사이의 년수를 Return한다. | |
402 | + * | |
403 | + * <pre> | |
404 | + * | |
405 | + * [사용 예제] | |
406 | + * yearsBetween("20040225", "20071001") ===> 3 | |
407 | + * | |
408 | + * </pre> | |
409 | + * | |
410 | + * @param from | |
411 | + * @param to | |
412 | + * @return int | |
413 | + * @throws ChainedException | |
414 | + */ | |
415 | + public static int getYearsBetween(String from, String to) throws Exception { | |
416 | + return getYearsBetween(from, to, "yyyyMMdd", null); | |
417 | + } | |
418 | + | |
419 | + /** | |
420 | + * | |
421 | + * 입력된 from 날짜와 to 날짜를 입력된 Format으로 해석하여 날짜 사이의 년수를 Return한다. | |
422 | + * | |
423 | + * <pre> | |
424 | + * | |
425 | + * [사용 예제] | |
426 | + * | |
427 | + * yearsBetween("2004-02-25", "2007-10-01", "yyyy-MM-dd") ===> 3 | |
428 | + * | |
429 | + * </pre> | |
430 | + * | |
431 | + * @param from | |
432 | + * @param to | |
433 | + * @param format | |
434 | + * @return int | |
435 | + * @throws ChainedException | |
436 | + */ | |
437 | + public static int getYearsBetween(String from, String to, String format, Locale lcal) throws Exception { | |
438 | + if (lcal == null) | |
439 | + lcal = java.util.Locale.KOREA; | |
440 | + return (int) (getDaysBetween(from, to, format, lcal) / 365); | |
441 | + } | |
442 | + | |
443 | + /** | |
444 | + * | |
445 | + * yyyyMMdd Format으로 입력된 날짜에서 해당 년월의 마지막 날짜를 Return한다. | |
446 | + * | |
447 | + * <pre> | |
448 | + * | |
449 | + * [사용 예제] | |
450 | + * | |
451 | + * lastDayOfMonth("20040202") ===> 20040229 | |
452 | + * | |
453 | + * </pre> | |
454 | + * | |
455 | + * @param date | |
456 | + * @return String | |
457 | + * @throws ChainedException | |
458 | + */ | |
459 | + public static String getLastDayOfMonth(String date) throws Exception { | |
460 | + return getLastDayOfMonth(date, "yyyyMMdd", null); | |
461 | + } | |
462 | + | |
463 | + /** | |
464 | + * | |
465 | + * 입력된 날짜을 입력된 Format 으로 해석하여 그 날짜에서 해당 년월의 마지막 날짜를 Return한다. | |
466 | + * | |
467 | + * <pre> | |
468 | + * | |
469 | + * [사용 예제] | |
470 | + * | |
471 | + * lastDayOfMonth("20040202", "yyyyMMdd") ===> 20040429 | |
472 | + * | |
473 | + * </pre> | |
474 | + * | |
475 | + * @param date | |
476 | + * @param format | |
477 | + * @return String | |
478 | + * @throws ChainedException | |
479 | + */ | |
480 | + public static String getLastDayOfMonth(String date, String format, Locale lcal) throws Exception { | |
481 | + if (lcal == null) | |
482 | + lcal = java.util.Locale.KOREA; | |
483 | + java.text.SimpleDateFormat formatter = new java.text.SimpleDateFormat(format, lcal); | |
484 | + java.util.Date formattedDate = formatValidDate(date, format, lcal); | |
485 | + java.text.SimpleDateFormat yearFormat = new java.text.SimpleDateFormat("yyyy", lcal); | |
486 | + java.text.SimpleDateFormat monthFormat = new java.text.SimpleDateFormat("MM", lcal); | |
487 | + int year = Integer.parseInt(yearFormat.format(formattedDate)); | |
488 | + int month = Integer.parseInt(monthFormat.format(formattedDate)); | |
489 | + int day = getLastDay(year, month); | |
490 | + java.text.DecimalFormat fourDf = new java.text.DecimalFormat("0000"); | |
491 | + java.text.DecimalFormat twoDf = new java.text.DecimalFormat("00"); | |
492 | + String tempDate = String.valueOf(fourDf.format(year)) + String.valueOf(twoDf.format(month)) | |
493 | + + String.valueOf(twoDf.format(day)); | |
494 | + java.util.Date targetDate = formatValidDate(tempDate, "yyyyMMdd", lcal); | |
495 | + return formatter.format(targetDate); | |
496 | + } | |
497 | + | |
498 | + /** | |
499 | + * | |
500 | + * 입력된 년도와 입력된 월의 마지막 일를 Return한다. | |
501 | + * | |
502 | + * <pre> | |
503 | + * | |
504 | + * [사용 예제] | |
505 | + * | |
506 | + * lastDay(2004,02) ===> 29 | |
507 | + * | |
508 | + * </pre> | |
509 | + * | |
510 | + * @param year | |
511 | + * @param month | |
512 | + * @return int | |
513 | + * @throws ParseException | |
514 | + */ | |
515 | + public static int getLastDay(int year, int month) throws java.text.ParseException { | |
516 | + int day = 0; | |
517 | + switch (month) { | |
518 | + case 1: | |
519 | + case 3: | |
520 | + case 5: | |
521 | + case 7: | |
522 | + case 8: | |
523 | + case 10: | |
524 | + case 12: | |
525 | + day = 31; | |
526 | + break; | |
527 | + case 2: | |
528 | + if ((year % 4) == 0) { | |
529 | + if ((year % 100) == 0 && (year % 400) != 0) { | |
530 | + day = 28; | |
531 | + } else { | |
532 | + day = 29; | |
533 | + } | |
534 | + } else { | |
535 | + day = 28; | |
536 | + } | |
537 | + break; | |
538 | + default: | |
539 | + day = 30; | |
540 | + } | |
541 | + return day; | |
542 | + } | |
543 | + | |
544 | + /** | |
545 | + * | |
546 | + * 현재 시간을 Long Type 으로 Return한다. (워크플로우 작업이력저장 용도) | |
547 | + * | |
548 | + * <pre> | |
549 | + * | |
550 | + * [사용 예제] | |
551 | + * | |
552 | + * DateUtil.getCurrentTime() | |
553 | + * | |
554 | + * </pre> | |
555 | + * | |
556 | + * @return Long | |
557 | + * @throws Exception | |
558 | + */ | |
559 | + public static Long getCurrentTime() throws Exception { | |
560 | + java.util.Date date = new java.util.Date(); | |
561 | + | |
562 | + long ltime1 = date.getTime(); // 현재시간 | |
563 | + | |
564 | + Calendar cal = Calendar.getInstance(); | |
565 | + cal.set(1970, 0, 1, 9, 0, 0);// 파일넷 기준시간 | |
566 | + | |
567 | + long ltime2 = cal.getTimeInMillis(); | |
568 | + | |
569 | + long curTime = ltime1 - ltime2; | |
570 | + | |
571 | + return new Long(curTime / 1000); | |
572 | + } | |
573 | + | |
574 | +} | |
0 | 575 | \ No newline at end of file | ... | ... |
1 | +package daeucna.utils; | |
2 | + | |
3 | +import daeucna.config.security.utils.CommonJson; | |
4 | + | |
5 | +public class JsonUtil { | |
6 | + | |
7 | + public static String objectToString(Object object) { | |
8 | + return CommonJson.objectToString(object); | |
9 | + } | |
10 | + | |
11 | + public static Object stringToObject(String sJson, Class<?> objClass) { | |
12 | + return CommonJson.stringToObject(sJson, objClass); | |
13 | + } | |
14 | + | |
15 | + public static Object objectToObject(Object object, Class<?> objClass) { | |
16 | + return CommonJson.objectToObject(object, objClass); | |
17 | + } | |
18 | + | |
19 | +} | |
0 | 20 | \ No newline at end of file | ... | ... |
1 | +package daeucna.utils; | |
2 | + | |
3 | +import java.io.UnsupportedEncodingException; | |
4 | +import java.net.URLDecoder; | |
5 | +import java.net.URLEncoder; | |
6 | +import java.util.HashMap; | |
7 | +import java.util.Iterator; | |
8 | +import java.util.List; | |
9 | +import java.util.Map; | |
10 | +import java.util.StringTokenizer; | |
11 | +import java.util.Vector; | |
12 | + | |
13 | +import org.apache.commons.lang3.StringUtils; | |
14 | + | |
15 | +/** | |
16 | + * <p> | |
17 | + * <code>StringUtil</code> 은 String의 handling과 관련된 class이다. | |
18 | + * <p> | |
19 | + */ | |
20 | + | |
21 | +public class StringUtil { | |
22 | + /** | |
23 | + * lPad(inStr, iSize, sPadStr) | |
24 | + * | |
25 | + * @param inStr | |
26 | + * @param iSize | |
27 | + * @param sPadStr | |
28 | + * @return | |
29 | + */ | |
30 | + public static String leftPad(String inStr, int iSize, String sPadStr) { | |
31 | + return StringUtils.leftPad(inStr, iSize, sPadStr); | |
32 | + } | |
33 | + | |
34 | + /** | |
35 | + * rPad(inStr, iSize, sPadStr) | |
36 | + * | |
37 | + * @param inStr | |
38 | + * @param iSize | |
39 | + * @param sPadStr | |
40 | + * @return | |
41 | + */ | |
42 | + public static String rightPad(String inStr, int iSize, String sPadStr) { | |
43 | + return StringUtils.rightPad(inStr, iSize, sPadStr); | |
44 | + } | |
45 | + | |
46 | + /** | |
47 | + * inStr이 null/""/"공백문자" 이면 default | |
48 | + * | |
49 | + * @param inStr | |
50 | + * @param sDefault | |
51 | + * @return | |
52 | + */ | |
53 | + public static String defaultIfBlank(String inStr, String sDefault) { | |
54 | + return StringUtils.defaultIfBlank(inStr, sDefault); | |
55 | + } | |
56 | + | |
57 | + /** | |
58 | + * inStr이 null/"" 이면 default | |
59 | + * | |
60 | + * @param inStr | |
61 | + * @param sDefault | |
62 | + * @return | |
63 | + */ | |
64 | + public static String defaultIfEmpty(String inStr, String sDefault) { | |
65 | + return StringUtils.defaultIfEmpty(inStr, sDefault); | |
66 | + } | |
67 | + | |
68 | + /** | |
69 | + * Strip 결과가 Null이나 ""이면 "" | |
70 | + * | |
71 | + * @param inStr | |
72 | + * @param sDefault | |
73 | + * @return | |
74 | + */ | |
75 | + public static String stripToEmpty(String inStr) { | |
76 | + return StringUtils.stripToEmpty(inStr); | |
77 | + } | |
78 | + | |
79 | + /** | |
80 | + * Strip 결과가 "" 이면 NULL | |
81 | + * | |
82 | + * @param inStr | |
83 | + * @param sDefault | |
84 | + * @return | |
85 | + */ | |
86 | + public static String stripToNull(String inStr) { | |
87 | + return StringUtils.stripToNull(inStr); | |
88 | + } | |
89 | + | |
90 | + public static String remove(String inStr, String sRemoveStr) { | |
91 | + return StringUtils.remove(inStr, sRemoveStr); | |
92 | + } | |
93 | + | |
94 | + public static String replace(String inStr, String sTargetStr, String sReplaceStr) { | |
95 | + return StringUtils.replace(sTargetStr, inStr, sReplaceStr); | |
96 | + } | |
97 | + | |
98 | + public static String trimToEmpty(String inStr) { | |
99 | + return StringUtils.trimToEmpty(inStr); | |
100 | + } | |
101 | + | |
102 | + public static String trimToNull(String inStr) { | |
103 | + return StringUtils.trimToNull(inStr); | |
104 | + } | |
105 | + | |
106 | +} | |
0 | 107 | \ No newline at end of file | ... | ... |
src/main/resources/application.properties
... | ... | @@ -17,9 +17,9 @@ spring.jpa.defer-datasource-initialization=true |
17 | 17 | ## Datasource |
18 | 18 | # primary |
19 | 19 | spring.datasource.hikari.primary.driver-class-name=org.postgresql.Driver |
20 | -spring.datasource.hikari.primary.jdbc-url=jdbc:postgresql://daeuserver.iptime.org:20430/account | |
21 | -spring.datasource.hikari.primary.username=account | |
22 | -spring.datasource.hikari.primary.password=daeucna10! | |
20 | +spring.datasource.hikari.primary.jdbc-url=jdbc:postgresql://localhost:5432/sangkiham | |
21 | +spring.datasource.hikari.primary.username=sangkiham | |
22 | +spring.datasource.hikari.primary.password=sangkiham | |
23 | 23 | |
24 | 24 | # secondary |
25 | 25 | #spring.datasource.hikari.secondary.driver-class-name=oracle.jdbc.driver.OracleDriver | ... | ... |
src/main/resources/data.sql
... | ... | @@ -21,21 +21,25 @@ WHEN NOT MATCHED THEN |
21 | 21 | MERGE INTO users m |
22 | 22 | USING ( |
23 | 23 | SELECT |
24 | - 1 as user_id, | |
25 | 24 | true as activated, |
26 | 25 | 'sangkiham' as nickname, |
27 | 26 | '$2a$10$nyHQj.Nj2tID4UzIkd1/SuMeYwlKaaHT8Gi3Wgg2x/h9K9qLQciLO' as password, |
28 | 27 | 'sangkiham' as username |
29 | 28 | ) s |
30 | 29 | ON |
31 | - m.user_id = s.user_id | |
30 | + m.username = s.username | |
31 | +WHEN MATCHED THEN | |
32 | + UPDATE SET | |
33 | + nickname = s.nickname | |
34 | + , activated = s.activated | |
35 | + , password = s.password | |
32 | 36 | WHEN NOT MATCHED THEN |
33 | - INSERT (user_id, activated, nickname, password, username) VALUES (s.user_id, s.activated, s.nickname, s.password, s.username); | |
37 | + INSERT (activated, nickname, password, username) VALUES (s.activated, s.nickname, s.password, s.username); | |
34 | 38 | |
35 | 39 | MERGE INTO user_authority m |
36 | 40 | USING ( |
37 | 41 | SELECT |
38 | - 1 as user_id, | |
42 | + (SELECT user_id FROM users WHERE username = 'sangkiham') as user_id, | |
39 | 43 | 'ROLE_ADMIN' as authority_name |
40 | 44 | ) s |
41 | 45 | ON | ... | ... |
src/main/resources/mybatis/mybatis-config.xml
... | ... | @@ -22,6 +22,8 @@ |
22 | 22 | <!-- 별칭 --> |
23 | 23 | <typeAliases> |
24 | 24 | <typeAlias type="daeucna.system.code.CodeDto" alias="CodeDto"/> |
25 | + <typeAlias type="daeucna.system.user.UserDto" alias="UserDto"/> | |
26 | + <typeAlias type="daeucna.system.user.UserAuthorityDto" alias="UserAuthorityDto"/> | |
25 | 27 | </typeAliases> |
26 | 28 | |
27 | 29 | </configuration> |
28 | 30 | \ No newline at end of file | ... | ... |
src/main/resources/mybatis/primary/system/UserMapper.xml
0 → 100644
1 | +<?xml version="1.0" encoding="UTF-8"?> | |
2 | +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> | |
3 | +<mapper namespace="daeucna.mapper.primary.system.UserMapper"> | |
4 | + | |
5 | + <select id="getUsers" parameterType="UserDto" resultType="UserDto"> | |
6 | + SELECT | |
7 | + m.user_id | |
8 | + , m.activated | |
9 | + , m.nickname | |
10 | + , null as password | |
11 | + , m.username | |
12 | + FROM public.users m | |
13 | + ORDER BY | |
14 | + m.username | |
15 | + </select> | |
16 | + | |
17 | + <update id="saveUser" parameterType="UserDto"> | |
18 | + MERGE INTO public.users m | |
19 | + USING ( | |
20 | + SELECT | |
21 | + #{activated} as activated | |
22 | + , #{nickname} as nickname | |
23 | + , #{username} as username | |
24 | + <if test='password != null and !password.equals("")'> | |
25 | + , #{password} as password | |
26 | + </if> | |
27 | + ) s | |
28 | + ON ( | |
29 | + m.username = s.username | |
30 | + ) | |
31 | + WHEN MATCHED THEN | |
32 | + UPDATE SET | |
33 | + activated = s.activated | |
34 | + , nickname = s.nickname | |
35 | + , username = s.username | |
36 | + <if test='password != null and !password.equals("")'> | |
37 | + , password = s.password | |
38 | + </if> | |
39 | + WHEN NOT MATCHED THEN | |
40 | + INSERT ( | |
41 | + activated | |
42 | + , nickname | |
43 | + , username | |
44 | + <if test='password != null and !password.equals("")'> | |
45 | + , password | |
46 | + </if> | |
47 | + ) VALUES ( | |
48 | + s.activated | |
49 | + , s.nickname | |
50 | + , s.username | |
51 | + <if test='password != null and !password.equals("")'> | |
52 | + , s.password | |
53 | + </if> | |
54 | + ) | |
55 | + </update> | |
56 | + | |
57 | + <delete id="deleteUser" parameterType="UserDto"> | |
58 | + DELETE FROM public.users m | |
59 | + WHERE | |
60 | + user_id = #{userId} | |
61 | + </delete> | |
62 | + | |
63 | + | |
64 | + <select id="getUsersAuthority" parameterType="UserAuthorityDto" resultType="UserAuthorityDto"> | |
65 | + SELECT | |
66 | + m.user_id | |
67 | + , s1.username | |
68 | + , s2.authority_name | |
69 | + FROM public.user_authority m | |
70 | + inner join public.users s1 | |
71 | + on s1.user_id = m.user_id | |
72 | + inner join public.authority s2 | |
73 | + on s2.authority_name = m.authority_name | |
74 | + WHERE 1=1 | |
75 | + <if test='username != null and !username.equals("")'> | |
76 | + and s1.username like ('%' || #{username} || '%') | |
77 | + </if> | |
78 | + ORDER BY m.user_id ASC | |
79 | + </select> | |
80 | + | |
81 | + <update id="saveUserAuthority" parameterType="UserAuthorityDto"> | |
82 | + MERGE INTO public.user_authority m | |
83 | + USING ( | |
84 | + SELECT | |
85 | + (SELECT user_id FROM public.users WHERE username=#{username}) as user_id | |
86 | + , #{authorityName} as authority_name | |
87 | + ) s | |
88 | + ON ( | |
89 | + m.user_id = s.user_id | |
90 | + ) | |
91 | + WHEN MATCHED THEN | |
92 | + UPDATE SET | |
93 | + authority_name = s.authority_name | |
94 | + WHEN NOT MATCHED THEN | |
95 | + INSERT ( | |
96 | + user_id | |
97 | + , authority_name | |
98 | + ) VALUES ( | |
99 | + s.user_id | |
100 | + , s.authority_name | |
101 | + ) | |
102 | + </update> | |
103 | + | |
104 | + <delete id="deleteUserAuthority" parameterType="UserAuthorityDto"> | |
105 | + DELETE FROM public.user_authority m | |
106 | + WHERE | |
107 | + user_id = #{userId} | |
108 | + </delete> | |
109 | + | |
110 | + <select id="getUserList" parameterType="Map" resultType="Map"> | |
111 | + SELECT | |
112 | + user_id | |
113 | + , username | |
114 | + FROM public.users | |
115 | + WHERE | |
116 | + activated = true | |
117 | + ORDER BY username ASC | |
118 | + </select> | |
119 | + | |
120 | + <select id="getAuthorityList" parameterType="Map" resultType="Map"> | |
121 | + SELECT | |
122 | + authority_name | |
123 | + FROM public.authority | |
124 | + ORDER BY authority_name ASC | |
125 | + </select> | |
126 | + | |
127 | +</mapper> | |
0 | 128 | \ No newline at end of file | ... | ... |
src/main/resources/schema.sql
... | ... | @@ -223,7 +223,6 @@ CREATE TABLE IF NOT EXISTS batch_user_job_status |
223 | 223 | exit_code character varying(10) COLLATE pg_catalog."default", |
224 | 224 | exit_message character varying(2000) COLLATE pg_catalog."default", |
225 | 225 | CONSTRAINT batch_user_job_status_pkey PRIMARY KEY (user_job_id) |
226 | - USING INDEX TABLESPACE account | |
227 | 226 | ); |
228 | 227 | |
229 | 228 | COMMENT ON TABLE batch_user_job_status |
... | ... | @@ -267,12 +266,12 @@ CREATE TABLE IF NOT EXISTS user_authority |
267 | 266 | CONSTRAINT user_authority_pkey PRIMARY KEY (user_id, authority_name), |
268 | 267 | CONSTRAINT fk6ktglpl5mjosa283rvken2py5 FOREIGN KEY (authority_name) |
269 | 268 | REFERENCES authority (authority_name) MATCH SIMPLE |
270 | - ON UPDATE NO ACTION | |
271 | - ON DELETE NO ACTION, | |
269 | + ON UPDATE CASCADE | |
270 | + ON DELETE CASCADE, | |
272 | 271 | CONSTRAINT fkhi46vu7680y1hwvmnnuh4cybx FOREIGN KEY (user_id) |
273 | 272 | REFERENCES users (user_id) MATCH SIMPLE |
274 | - ON UPDATE NO ACTION | |
275 | - ON DELETE NO ACTION | |
273 | + ON UPDATE CASCADE | |
274 | + ON DELETE CASCADE | |
276 | 275 | ); |
277 | 276 | |
278 | 277 | -- Table: sy_cmmn_code_mng | ... | ... |