샘플 메뉴 추가

This commit is contained in:
keymasroy
2021-12-22 00:47:03 +09:00
parent d0af34d3bf
commit 950b2421c2
6 changed files with 594 additions and 15 deletions

View File

@@ -0,0 +1,195 @@
<template>
<div>
<u-field-set ref="fieldSet">
<u-field-row>
<u-field label="코드">
<dx-text-box ref="codeInput" v-model="inputData.dtlCd" :disabled="inputMode === 'update'">
<dx-validator>
<dx-required-rule />
<dx-async-rule message="이미 사용 중인 코드입니다." :validation-callback="validateCode" />
</dx-validator>
</dx-text-box>
</u-field>
</u-field-row>
<u-field-row>
<u-field label="코드명">
<dx-text-box v-model="inputData.cdNm">
<dx-validator>
<dx-required-rule />
</dx-validator>
</dx-text-box>
</u-field>
</u-field-row>
<u-field-row>
<u-field label="설명">
<dx-text-area v-model="inputData.cdDesc"></dx-text-area>
</u-field>
</u-field-row>
<u-field-row>
<u-field label="사용여부">
<dx-radio-group v-model="inputData.useYn" :items="useYnList" display-expr="name" value-expr="code"></dx-radio-group>
</u-field>
</u-field-row>
</u-field-set>
<u-button-bar position="bottom">
<dx-button text="신규" icon="plus" :disabled="inputMode === 'new'" @click="newForm"></dx-button>
<dx-button text="저장" class="right" icon="floppy" type="default" @click="save" />
<dx-button text="삭제" icon="close" :disabled="inputMode === 'new'" @click="remove" />
</u-button-bar>
</div>
</template>
<script lang="ts">
import { Component, Ref, Emit } from 'vue-property-decorator'
import { UstraBoComponent } from '@ustra/nuxt-mng-bo/src/components/ustra-bo-component'
import { Validatable } from '@ustra/nuxt-dx/src/components/dx/dx-validation-group'
import { DxTextBox } from '@ustra/nuxt-dx/src/components/dx/dx-text-box'
import { CodeInfo } from '@ustra/nuxt-mng/src/system/models/ustra-code-model'
import { UseYnDataList } from '@ustra/nuxt-mng/src/data'
import { FormMode } from '@ustra/data/src/models/base-models'
import { OnError } from '@ustra/nuxt/src/vue/decorators'
import { REMOVE_QUESTION } from '@ustra/data/src/data/common-messages'
import { SampleCrudModel, sampleCrudService } from '~/services/sample-crud-service'
type InputType = 'groupCode' | 'detailCode'
@Component
/**
* @vuese
* @group component group
* component description
*/
export default class extends UstraBoComponent {
// #region variables
inputData: SampleCrudModel = null
inputMode: FormMode = null
inputType: InputType = null
groupCode: SampleCrudModel = {
useYn: 'Y',
}
useYnList = UseYnDataList
@Ref() readonly fieldSet: Validatable
@Ref() readonly codeInput: DxTextBox
// #endregion
// #region hooks
created() {
this.init('groupCode')
}
// #endregion
// #region methods
async init(inputType: InputType = 'detailCode', groupCode?: CodeInfo) {
if (this.fieldSet) {
await this.fieldSet.reset()
}
this.inputData = {
grpCd: null,
dtlCd: null,
cdNm: null,
cdDesc: null,
useYn: 'Y',
}
this.inputType = inputType
this.groupCode = null
this.inputMode = 'new'
if (inputType === 'detailCode' && !groupCode) {
throw new Error('groupCode 값이 없음.')
}
this.groupCode = groupCode
this.focus()
}
async detail(code?: CodeInfo) {
const detail = await sampleCrudService.getCode(code.grpCd, code.dtlCd)
if (detail === null) {
throw new Error('코드 정보가 없습니다.')
}
if (detail.dtlCd === '*') {
detail.dtlCd = detail.grpCd
}
await this.fieldSet.reset()
this.inputData = detail
this.inputMode = 'update'
this.focus()
}
@OnError()
async save() {
const saveData = this.$ustra.utils.core.deepMerge({}, this.inputData)
if (this.inputType === 'groupCode') {
saveData.grpCd = saveData.dtlCd
saveData.dtlCd = '*'
} else {
saveData.grpCd = this.groupCode.grpCd
}
const validateResult = await this.fieldSet.validate(true)
if (!validateResult || !validateResult.isValid) {
// alert('입력 값을 확인해주세요.')
return
}
if (this.inputMode === 'new') {
await sampleCrudService.add(saveData)
} else {
await sampleCrudService.edit(saveData)
}
this.saved(this.groupCode)
}
@OnError()
async remove() {
if (await confirm(REMOVE_QUESTION)) {
await sampleCrudService.remove(this.inputData.grpCd, this.inputData.dtlCd)
this.saved(this.groupCode)
}
}
newForm() {
this.init('detailCode', this.groupCode)
this.reset()
}
focus() {
try {
this.codeInput.instance.focus()
} catch (e) {}
}
// #region validation
async validateCode(e) {
const code = await sampleCrudService.getCode(e.value, '*')
return code === null
}
// #endregion
// #region event method
@Emit()
saved(groupCode: CodeInfo) {
return groupCode
}
@Emit()
reset() {}
// #endregion
// #endregion
// #region watches
// #endregion
}
</script>
<style lang="scss"></style>

View File

@@ -0,0 +1,121 @@
<template>
<dx-box direction="col">
<dx-item :ratio="1">
<template #default>
<dx-box direction="col">
<dx-item :ratio="1">
<template #default>
<dx-data-grid ref="grid" :data-source="codes" @selection-changed="rowSelected">
<dx-column data-field="grpCd" caption="코드" />
<dx-column data-field="cdNm" caption="코드명" />
<dx-column />
</dx-data-grid>
</template>
</dx-item>
<dx-item base-size="auto">
<template #default>
<div>
<u-help-box :is-grid-total="false" :show-icon="false">
검색 건수 : <span class="emphasis-text">{{ codes.length }}</span>
</u-help-box>
</div>
</template>
</dx-item>
</dx-box>
</template>
</dx-item>
<dx-item :ratio="0" base-size="auto">
<template #default>
<u-button-bar>
<dx-button text="신규" class="right" icon="plus" @click="newGroupCode"></dx-button>
<dx-button text="수정" icon="edit" :visible="hasSelectedRow" @click="editGroupCode"></dx-button>
<dx-popup :width="500" :height="400" :visible.sync="isOpenedInputForm" title="마스터 코드 등록" @shown="inputForm.focus()">
<dx-box direction="col" height="100%">
<dx-item :ratio="1">
<template #default>
<input-form ref="inputForm" @saved="onSaved" />
</template>
</dx-item>
</dx-box>
</dx-popup>
</u-button-bar>
</template>
</dx-item>
</dx-box>
</template>
<script lang="ts">
import { Component, Ref, Emit } from 'vue-property-decorator'
import { DxDataGrid } from '@ustra/nuxt-dx/src/components'
import { UstraBoComponent } from '@ustra/nuxt-mng-bo/src/components/ustra-bo-component'
import InputForm from './input-form.vue'
import { SampleCrudModel, sampleCrudService } from '~/services/sample-crud-service'
@Component({
components: { InputForm },
})
/**
* @vuese
* @group component group
* component description
*/
export default class extends UstraBoComponent {
// #region variables
codes: SampleCrudModel[] = []
isOpenedInputForm: boolean = false
hasSelectedRow: boolean = false
@Ref() readonly inputForm: InputForm
@Ref() readonly grid: DxDataGrid
// #endregion
// #region hooks
created() {
this.loadCode()
}
// #endregion
// #region methods
@Emit()
codeSelected(code: SampleCrudModel) {
return code
}
@Emit()
codeLoaded() {}
newGroupCode() {
this.isOpenedInputForm = true
this.inputForm.init('groupCode')
}
editGroupCode() {
this.newGroupCode()
this.inputForm.detail(this.grid.instance.getSelectedRowsData()[0])
}
async loadCode() {
this.codes = await sampleCrudService.getGroups()
this.codeLoaded()
}
rowSelected(e) {
this.hasSelectedRow = e.selectedRowsData.length > 0
if (e.selectedRowsData.length < 1) {
return
}
this.codeSelected(e.selectedRowsData[0] as SampleCrudModel)
}
onSaved() {
this.isOpenedInputForm = false
this.loadCode()
}
// #endregion
// #region watches
// #endregion
}
</script>
<style lang="scss"></style>

View File

@@ -0,0 +1,58 @@
<template>
<dx-data-grid ref="grid" height="100%" :data-source="codes" @selection-changed="rowSelected">
<dx-column data-field="dtlCd" caption="코드" />
<dx-column data-field="cdNm" caption="코드명" />
</dx-data-grid>
</template>
<script lang="ts">
import { Component, Ref, Emit } from 'vue-property-decorator'
import { UstraBoComponent } from '@ustra/nuxt-mng-bo/src/components/ustra-bo-component'
import { OnError } from '@ustra/nuxt/src/vue/decorators'
import { DxDataGrid } from '@ustra/nuxt-dx/src/components/dx/dx-data-grid'
import { SampleCrudModel, sampleCrudService } from '~/services/sample-crud-service'
@Component
/**
* @vuese
* @group component group
* component description
*/
export default class extends UstraBoComponent {
// #region variables
codes: SampleCrudModel[] = null
@Ref() readonly grid: DxDataGrid
// #endregion
// #region hooks
// #endregion
// #region methods
@OnError({ message: '코드 목록 조회 중 오류가 발생하였습니다.' })
async loadData(groupCode: SampleCrudModel) {
this.codes = (await sampleCrudService.getCodes(null, groupCode.grpCd)).body.filter(code => code.dtlCd !== '*')
}
@Emit()
codeSelected(code: SampleCrudModel) {
return code
}
rowSelected(e) {
if (e.selectedRowsData.length < 1) {
return
}
this.codeSelected(e.selectedRowsData[0] as SampleCrudModel)
}
clearSelection() {
this.grid.instance.clearSelection()
}
clear() {
this.codes = []
}
// #endregion
// #region watches
// #endregion
}
</script>
<style lang="scss"></style>

View File

@@ -1,15 +0,0 @@
<template>
<div style="display: flex; align-items: stretch; flex: 1; flex-grow: 1; flex-direction: column"></div>
</template>
<script lang="ts">
import { Component } from 'vue-property-decorator'
import { UstraBoComponent } from '@ustra/nuxt-mng-bo/src/components/ustra-bo-component'
@Component({})
/**
* @vuese
* @group component group
* component description
*/
export default class extends UstraBoComponent {}
</script>

View File

@@ -0,0 +1,81 @@
<template>
<dx-box direction="row" height="100%" width="100%">
<template #default>
<dx-item :ratio="1">
<template #default>
<master-grid ref="masterGrid" @code-selected="masterCodeSelected" @code-loaded="onMasterCodeLoaded" />
</template>
</dx-item>
<dx-item :ratio="1" :disabled="subFormDisabled">
<template #default>
<dx-box direction="col" width="100%">
<template #default>
<dx-item :ratio="1">
<template #default>
<sub-grid ref="subGrid" @code-selected="subCodeSelected" />
</template>
</dx-item>
<dx-item :ratio="0" :base-size="250">
<template #default>
<input-form ref="inputForm" @saved="onSaved" @reset="onReset" />
</template>
</dx-item>
</template>
</dx-box>
</template>
</dx-item>
</template>
</dx-box>
</template>
<script lang="ts">
import { Component, Ref } from 'vue-property-decorator'
import { UstraBoComponent } from '@ustra/nuxt-mng-bo/src/components/ustra-bo-component'
import MasterGrid from '~/components/sample-menu/code-crud/master-grid.vue'
import SubGrid from '~/components/sample-menu/code-crud/sub-grid.vue'
import InputForm from '~/components/sample-menu/code-crud/input-form.vue'
import { SampleCrudModel } from '~/services/sample-crud-service'
@Component({
components: { MasterGrid, SubGrid, InputForm },
})
export default class extends UstraBoComponent {
// #region variables
@Ref() readonly masterGrid: MasterGrid
@Ref() readonly subGrid: SubGrid
@Ref() readonly inputForm: InputForm
subFormDisabled: boolean = true
masterCodes: SampleCrudModel[]
// #endregion
// #region hooks
// #endregion
// #region methods
async masterCodeSelected(code: SampleCrudModel) {
await this.subGrid.loadData(code)
await this.inputForm.init('detailCode', code)
this.subFormDisabled = false
}
subCodeSelected(code: SampleCrudModel) {
this.inputForm.detail(code)
}
onMasterCodeLoaded() {
this.subGrid.clear()
this.subFormDisabled = true
}
onSaved(code: SampleCrudModel) {
this.masterCodeSelected(code)
}
onReset() {
this.subGrid.clearSelection()
}
// #endregion
// #region watches
// #endregion
}
</script>
<style lang="scss"></style>

View File

@@ -0,0 +1,139 @@
import { BaseModel } from '@ustra/data/src/models/base-models'
import { ApiResponse } from '@ustra/data/src/models/api-model'
import { PaginationRequest } from '@ustra/data/src/models/pagination-model'
import { UtraService } from '@ustra/nuxt/src/services/ustra-service'
import { HttpMethod } from '@ustra/core/src/server/http/const'
/**
* crud sample 모델
*/
export interface SampleCrudModel extends BaseModel {
/**
* 그룹 코드
*/
grpCd?: string
/**
* 상세 코드
*/
dtlCd?: string
/**
* 코드 명
*/
cdNm?: string
/**
* 코드 상세
*/
cdDesc?: string
/**
* 사용 여부
*/
useYn?: string
/**
* 비고
*/
rmk?: string
}
export class SampleCrudService extends UtraService {
/**
* 코드 그룹 목록 조회
*/
async getGroups() {
return (
await this.$ustra.api.call<ApiResponse<SampleCrudModel[]>>({
url: '/api/sample/crud-code/groups',
method: HttpMethod.GET,
})
).data.body
}
/**
* 코드 목록 조회
* @param pagination 페이징 요청 정보
* @param grpCd 그룹 코드
*/
async getCodes(pagination: PaginationRequest, grpCd: string = null) {
const url = this.$ustra.api
.urlBuilder('/api/sample/crud-code')
.add('criteria', {
paginationRequest: pagination,
grpCd,
})
.build()
return (
await this.$ustra.api.call<ApiResponse<SampleCrudModel[]>>({
url,
method: HttpMethod.GET,
})
).data
}
/**
* 코드 상세 정보 조회
* @param grpCd 그룹 코드
* @param dtlCd 상세 코드
*/
async getCode(grpCd: string, dtlCd: string) {
return (
await this.$ustra.api.call<ApiResponse<SampleCrudModel>>({
url: `/api/sample/crud-code/${grpCd}/${dtlCd}`,
method: HttpMethod.GET,
})
).data.body
}
/**
* 코드 추가
* @param data 입력 데이터
*/
async add(data: SampleCrudModel) {
return (
await this.$ustra.api.call<ApiResponse<SampleCrudModel>>({
url: '/api/sample/crud-code',
method: HttpMethod.POST,
data,
})
).data.body
}
/**
* 코드 수정
* @param data 수정 데이터
*/
async edit(data: SampleCrudModel) {
return (
await this.$ustra.api.call<ApiResponse<SampleCrudModel>>({
url: '/api/sample/crud-code',
method: HttpMethod.PUT,
data,
})
).data.body
}
/**
* 코드 삭제
* @param grpCd 그룹 코드
* @param dtlCd 상세 코드
*/
async remove(grpCd: string, dtlCd: string) {
return (
await this.$ustra.api.call<ApiResponse<SampleCrudModel>>({
url: '/api/sample/crud-code',
method: HttpMethod.DELETE,
data: {
grpCd,
dtlCd,
},
})
).data.body
}
}
export const sampleCrudService = new SampleCrudService()
export default sampleCrudService