Appearance
setup
setupDynamicComponent.ts
메뉴 클릭시 로딩될 컴포넌트를 등록해준다.
Smart-erp-lite에서 메뉴 선택시 열린 프로그램은 상단에 탭으로 추가되는데, vue의 <component>
를 이용해서 메뉴의 programUrl에 해당하는 컴포넌트가 동적 로딩되도록 한다.
- 프로그램 작성순서
- 프로그램관리 테이블
SYS_PROGRAM
의PROGRAM_URL
컬럼에 각 프로그램의 메인이 되는 대표 컴포넌트의 경로를 등록한다.
PROGRAM_NM | PROGRAM_URL |
---|---|
경비승인관리 | /views/fim/expense-approval-management/ExpenseApprovalManagement.vue |
program_url은 /view/
경로로 시작하고, 최종 경로의 폴더명은 컴포넌트 이름을 snake-case
로 하고, 파일명은 컴포넌트이름과 vue 확장명으로 작성한다.
- 컴포넌트 등록 스크립트
import { App } from "vue"
import _ from 'lodash'
import { usePopupSettingMap } from '@/core'
export default function setupDynamicComponent(app: App) {
// https://vitejs-kr.github.io/guide/features.html#glob-import
let componentsCore = import.meta.globEager('../core/components/**/*.vue')
let componentsViews = import.meta.globEager('../views/**/*.vue')
let componentsSample = import.meta.globEager('../views-sample/**/*.vue')
let components = {
...componentsCore,
...componentsViews
}
if (import.meta.env.DEV) {
components = {
...components,
...componentsSample
}
}
const popupSettingMap = new Map<string, PopupSetting>()
usePopupSettingMap(popupSettingMap)
Object.entries(components).forEach(([path, definition]) => {
// Get name of component, based on filename
// "./components/Fruits.vue" will become "Fruits"
if (path.includes('xxx')) {
return
}
if (path.includes('/directive/')) {
console.warn(path)
return
}
const splitPath = path?.split('/')
const componentName = splitPath.pop()?.replace(/\.\w+$/, '')!
const parentPath = _.upperFirst(_.camelCase(splitPath.pop()))
// console.log(path, componentName)
// 샘플은 '프로그램명폴더/프로그램명컴포넌트' 규칙 제외
if (splitPath.includes('views-sample') || splitPath.includes('core')) {
app.component(componentName, definition.default)
} else {
// Register component on this Vue instance
// console.log(componentName , parentPath);
// 프로그램경로명과 컴포넌트이름이 같은 규칙이면 등록
// 팝업도 등록
if (componentName === parentPath || componentName.endsWith('Popup')) {
app.component(componentName, definition.default)
}
}
if (!componentName.startsWith('Vm') && componentName.endsWith('Popup')) {
// console.log(componentName, definition.default);
if (definition.default.popupSetting) definition.default.popupSetting.popupName = componentName
popupSettingMap.set(componentName, definition.default.popupSetting || {
popupName: componentName,
path
})
}
})
}
setupDynamicSvg.ts
프로젝트에서 모든 이미지는 svg를 사용한다. vue 프로젝트에서 이미지와 같은 static resource는 'src/asset'에 위치한다.
scss에서 background-image: url(@/assets/icon/xxx.svg)
로 사용하거나
<VmIcon name="아이콘 이름"/>
컴포넌트에 전체 경로 대신 이름만 입력해서 사용한다.
import { App } from "vue"
import _ from 'lodash'
const icons: {[index: string]: any} = {}
export default function setupDynamicSvg(app: App) {
// https://vitejs-kr.github.io/guide/features.html#glob-import
let svgs = import.meta.globEager('../assets/**/**/*.svg')
Object.entries(svgs).forEach(([path, definition]) => {
// console.log(path, definition)
// Get name of component, based on filename
// "./components/Fruits.vue" will become "Fruits"
const splitPath = path?.split('/')
const svgName = splitPath.pop()?.split('.').shift()!
// console.log(svgName)
if (icons[svgName]) {
throw `svg 파일이름 중복 ${path} ${icons[svgName]}`
}
icons[svgName] = definition.default
})
// console.log('setup icon', icons);
}
export function useIcon(name?: string) {
return name ? icons[name] : icons
}
setupInputmaskExtends.ts
<VmSearch>
컴포넌트에서 사용할 입력마스킹(Inputmask)을 정의한다. setupInputmaskExtends.ts
에 규칙을 추가하면 @/core/types/Mask.ts
에도 alias를 선언하여 마스크 사용시 타입체크를 할 수 있게 한다.
volar-components
<template>
에서 import하지 않고 사용하는 Global Components는 vscode의 volar에서 타입지원을 하기위해 volar-components.ts
에 Type
을 등록한다.
volar 사용시 Global Components의 타입-체킹을 가능하게 해준다. Global Components는 setupDynamicComponent.ts
에서 등록 하고 있으므로 타입만 선언한다.
volar Define Global Components
// https://github.com/johnsoncodehk/volar/tree/master/extensions/vscode-vue-language-features
declare module '@vue/runtime-core' {
export interface GlobalComponents {
// layout
//VmScroll: typeof import('@/core/components/layout/VmScroll.vue')['default']
// button
VmButton: typeof import('@/core/components/button/VmButton.vue')['default']
VmButtonPrimary: typeof import('@/core/components/button/VmButtonPrimary.vue')['default']
VmButtonApply: typeof import('@/core/components/button/VmButtonApply.vue')['default']
VmButtonClose: typeof import('@/core/components/button/VmButtonClose.vue')['default']
VmButtonQuery: typeof import('@/core/components/button/VmButtonQuery.vue')['default']
VmButtonPrint: typeof import('@/core/components/button/VmButtonPrint.vue')['default']
VmButtonSave: typeof import('@/core/components/button/VmButtonSave.vue')['default']
// container, row, cell
VmContainer: typeof import('@/core/components/container/VmContainer.vue')['default']
VmContainerToggle: typeof import('@/core/components/container/VmContainerToggle.vue')['default']
VmRow: typeof import('@/core/components/container/VmRow.vue')['default']
VmCell: typeof import('@/core/components/container/VmCell.vue')['default']
VmCellLine: typeof import('@/core/components/container/VmVertLine.vue')['default']
VmLabel: typeof import('@/core/components/container/VmLabel.vue')['default']
VmLineBreak: typeof import('@/core/components/layout/VmLineBreak.vue')['default']
VmVertLine: typeof import('@/core/components/layout/VmVertLine.vue')['default']
//
VmProgramTopArea: typeof import('@/core/components/container/VmProgramTopArea.vue')['default']
// flex
VmFlexCol: typeof import('@/core/components/container/VmFlexCol.vue')['default']
VmFlexRow: typeof import('@/core/components/container/VmFlexRow.vue')['default']
VmFlexBreak: typeof import('@/core/components/container/VmFlexBreak.vue')['default']
// form
VmAddrSearch: typeof import('@/core/components/form/VmAddrSearch.vue')['default']
VmCheckbox: typeof import('@/core/components/form/VmCheckbox.vue')['default']
VmDate: typeof import('@/core/components/form/VmDate.vue')['default']
VmMonth: typeof import('@/core/components/form/VmMonth.vue')['default']
VmYear: typeof import('@/core/components/form/VmYear.vue')['default']
VmDateRange: typeof import('@/core/components/form/VmDateRange.vue')['default']
VmMonthRange: typeof import('@/core/components/form/VmMonthRange.vue')['default']
// VmDateTime: typeof import('@/core/components/form/VmDateTime.vue')['default']
VmIcon: typeof import('@/core/components/form/VmIcon.vue')['default']
VmPopup: typeof import('@/core/components/form/VmPopup.vue')['default']
VmRadio: typeof import('@/core/components/form/VmRadio.vue')['default']
VmSearch: typeof import('@/core/components/form/VmSearch.vue')['default']
VmSelect: typeof import('@/core/components/form/VmSelect.vue')['default']
VmTextarea: typeof import('@/core/components/form/VmTextarea.vue')['default']
VmFile: typeof import('@/core/components/form/VmFile.vue')['default']
// modal
VmModal: typeof import('@/core/components/modal/VmModal.vue')['default']
VmModalComp: typeof import('@/core/components/modal/VmModalComp.vue')['default']
// grid
VmGrid: typeof import('@/core/components/grid/VmGrid.vue')['default']
// tab
VmTabs: typeof import('@/core/components/tab/VmTabs.vue')['default']
VmTab: typeof import('@/core/components/tab/VmTab.vue')['default']
// tree
VmTree: typeof import('@/core/components/tree/VmTree.vue')['default']
}
}
export { }