mirror of
https://git.hmsn.ink/kospo/svcm/oa.git
synced 2026-03-20 13:03:34 +09:00
com : app.vue - breadcrumb 주석
com : navbar.vue - 테마기능 삭제 func : VFlexTable 커스텀추가 fix : 계약관리, 결재함 스타일수정
This commit is contained in:
595
src/components/app-vuero/VFlexTableCustomize.vue
Normal file
595
src/components/app-vuero/VFlexTableCustomize.vue
Normal file
@@ -0,0 +1,595 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { type VNode } from 'vue'
|
||||||
|
import { flewTableWrapperSymbol } from '../base/VFlexTableWrapper.vue'
|
||||||
|
|
||||||
|
export interface VFlexTableColumn {
|
||||||
|
key: string
|
||||||
|
label: string
|
||||||
|
format: (value: any, row: any, index: number) => any
|
||||||
|
renderHeader?: () => VNode
|
||||||
|
renderRow?: (row: any, column: VFlexTableColumn, index: number) => VNode
|
||||||
|
align?: 'start' | 'center' | 'end'
|
||||||
|
bold?: boolean
|
||||||
|
inverted?: boolean
|
||||||
|
scrollX?: boolean
|
||||||
|
scrollY?: boolean
|
||||||
|
grow?: boolean | 'lg' | 'xl'
|
||||||
|
media?: boolean
|
||||||
|
cellClass?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface VFlexTableProps {
|
||||||
|
data?: any[]
|
||||||
|
columns?: Record<string, string | Partial<VFlexTableColumn>>
|
||||||
|
printObjects?: boolean
|
||||||
|
reactive?: boolean
|
||||||
|
compact?: boolean
|
||||||
|
rounded?: boolean
|
||||||
|
separators?: boolean
|
||||||
|
clickable?: boolean
|
||||||
|
subtable?: boolean
|
||||||
|
noHeader?: boolean
|
||||||
|
usePaymentHeader?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
const emits = defineEmits<{
|
||||||
|
(e: 'rowClick', row: any, index: number): void
|
||||||
|
}>()
|
||||||
|
const props = withDefaults(defineProps<VFlexTableProps>(), {
|
||||||
|
columns: undefined,
|
||||||
|
usePaymentHeader: false,
|
||||||
|
data: () => [],
|
||||||
|
})
|
||||||
|
|
||||||
|
const wrapper = inject(flewTableWrapperSymbol, null)
|
||||||
|
|
||||||
|
const data = computed(() => {
|
||||||
|
if (wrapper?.data) return wrapper.data
|
||||||
|
|
||||||
|
if (props.reactive) {
|
||||||
|
if (isReactive(props.data)) {
|
||||||
|
return props.data
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return reactive(props.data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return toRaw(props.data)
|
||||||
|
})
|
||||||
|
|
||||||
|
const defaultFormatter = (value: any) => value
|
||||||
|
const columns = computed(() => {
|
||||||
|
const columnsSrc = wrapper?.columns ?? props.columns
|
||||||
|
let columns: VFlexTableColumn[] = []
|
||||||
|
|
||||||
|
if (columnsSrc) {
|
||||||
|
for (const [key, label] of Object.entries(columnsSrc)) {
|
||||||
|
if (typeof label === 'string') {
|
||||||
|
columns.push({
|
||||||
|
format: defaultFormatter,
|
||||||
|
label,
|
||||||
|
key,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
columns.push({
|
||||||
|
format: defaultFormatter,
|
||||||
|
label: key,
|
||||||
|
key,
|
||||||
|
...(label as any),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (data.value.length > 0) {
|
||||||
|
for (const [key] of Object.entries(data.value[0])) {
|
||||||
|
columns.push({
|
||||||
|
format: defaultFormatter,
|
||||||
|
label: key,
|
||||||
|
key,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return columns
|
||||||
|
})
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div
|
||||||
|
class="flex-table"
|
||||||
|
:class="[
|
||||||
|
props.compact && 'is-compact',
|
||||||
|
props.rounded && 'is-rounded',
|
||||||
|
props.separators && 'with-separators',
|
||||||
|
props.noHeader && 'no-header',
|
||||||
|
props.clickable && 'is-table-clickable',
|
||||||
|
props.subtable && 'sub-table',
|
||||||
|
]"
|
||||||
|
>
|
||||||
|
<slot v-if="props.usePaymentHeader" name="payment-header">
|
||||||
|
<div
|
||||||
|
v-if="!props.noHeader"
|
||||||
|
class="flex-table-header"
|
||||||
|
>
|
||||||
|
<template
|
||||||
|
v-for="column in columns"
|
||||||
|
:key="'col' + column.key"
|
||||||
|
>
|
||||||
|
<slot
|
||||||
|
name="header-column"
|
||||||
|
:column="column"
|
||||||
|
>
|
||||||
|
<component
|
||||||
|
:is="{ render: column.renderHeader } as any"
|
||||||
|
v-if="column.renderHeader"
|
||||||
|
:class="[
|
||||||
|
column.grow === true && 'is-grow',
|
||||||
|
column.grow === 'lg' && 'is-grow-lg',
|
||||||
|
column.grow === 'xl' && 'is-grow-xl',
|
||||||
|
column.align === 'end' && 'cell-end',
|
||||||
|
column.align === 'center' && 'cell-center',
|
||||||
|
]"
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
v-else
|
||||||
|
:class="[
|
||||||
|
column.grow === true && 'is-grow',
|
||||||
|
column.grow === 'lg' && 'is-grow-lg',
|
||||||
|
column.grow === 'xl' && 'is-grow-xl',
|
||||||
|
column.align === 'end' && 'cell-end',
|
||||||
|
column.align === 'center' && 'cell-center',
|
||||||
|
]"
|
||||||
|
>{{ column.label }}</span>
|
||||||
|
</slot>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</slot>
|
||||||
|
<slot v-else name="header">
|
||||||
|
<div
|
||||||
|
v-if="!props.noHeader"
|
||||||
|
class="flex-table-header"
|
||||||
|
>
|
||||||
|
<template
|
||||||
|
v-for="column in columns"
|
||||||
|
:key="'col' + column.key"
|
||||||
|
>
|
||||||
|
<slot
|
||||||
|
name="header-column"
|
||||||
|
:column="column"
|
||||||
|
>
|
||||||
|
<component
|
||||||
|
:is="{ render: column.renderHeader } as any"
|
||||||
|
v-if="column.renderHeader"
|
||||||
|
:class="[
|
||||||
|
column.grow === true && 'is-grow',
|
||||||
|
column.grow === 'lg' && 'is-grow-lg',
|
||||||
|
column.grow === 'xl' && 'is-grow-xl',
|
||||||
|
column.align === 'end' && 'cell-end',
|
||||||
|
column.align === 'center' && 'cell-center',
|
||||||
|
]"
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
v-else
|
||||||
|
:class="[
|
||||||
|
column.grow === true && 'is-grow',
|
||||||
|
column.grow === 'lg' && 'is-grow-lg',
|
||||||
|
column.grow === 'xl' && 'is-grow-xl',
|
||||||
|
column.align === 'end' && 'cell-end',
|
||||||
|
column.align === 'center' && 'cell-center',
|
||||||
|
]"
|
||||||
|
>{{ column.label }}</span>
|
||||||
|
</slot>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</slot>
|
||||||
|
<slot name="body">
|
||||||
|
<template
|
||||||
|
v-for="(row, index) in data"
|
||||||
|
:key="index"
|
||||||
|
>
|
||||||
|
<slot
|
||||||
|
name="body-row-pre"
|
||||||
|
:row="row"
|
||||||
|
:columns="columns"
|
||||||
|
:index="index"
|
||||||
|
/>
|
||||||
|
<!-- eslint-disable-next-line vuejs-accessibility/no-static-element-interactions -->
|
||||||
|
<div
|
||||||
|
class="flex-table-item"
|
||||||
|
:class="[props.clickable && 'is-clickable']"
|
||||||
|
:tabindex="props.clickable ? 0 : undefined"
|
||||||
|
:role="props.clickable ? 'button' : undefined"
|
||||||
|
@keydown.enter.prevent="
|
||||||
|
() => {
|
||||||
|
props.clickable && emits('rowClick', row, index)
|
||||||
|
}
|
||||||
|
"
|
||||||
|
@click="
|
||||||
|
() => {
|
||||||
|
props.clickable && emits('rowClick', row, index)
|
||||||
|
}
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<slot
|
||||||
|
name="body-row"
|
||||||
|
:row="row"
|
||||||
|
:columns="columns"
|
||||||
|
:index="index"
|
||||||
|
>
|
||||||
|
<template
|
||||||
|
v-for="column in columns"
|
||||||
|
:key="'row' + column.key"
|
||||||
|
>
|
||||||
|
<VFlexTableCell :column="column">
|
||||||
|
<slot
|
||||||
|
:name="`body-cell-${column.key}`"
|
||||||
|
:row="row"
|
||||||
|
:column="column"
|
||||||
|
:index="index"
|
||||||
|
:value="column.format(row[column.key], row, index)"
|
||||||
|
>
|
||||||
|
<component
|
||||||
|
:is="
|
||||||
|
{
|
||||||
|
render: () => column.renderRow?.(row, column, index),
|
||||||
|
} as any
|
||||||
|
"
|
||||||
|
v-if="column.renderRow"
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
v-else-if="
|
||||||
|
typeof column.format(row[column.key], row, index) === 'object'
|
||||||
|
"
|
||||||
|
:class="[
|
||||||
|
column.cellClass,
|
||||||
|
column.inverted && 'dark-inverted',
|
||||||
|
// !column.inverted && (column.bold ? 'dark-text' : 'light-text'),
|
||||||
|
]"
|
||||||
|
>
|
||||||
|
<details v-if="printObjects">
|
||||||
|
<div class="language-json py-4">
|
||||||
|
<pre><code>{{ column.format(row[column.key], row, index) }}</code></pre>
|
||||||
|
</div>
|
||||||
|
</details>
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
v-else
|
||||||
|
:class="[
|
||||||
|
column.cellClass,
|
||||||
|
column.inverted && 'dark-inverted',
|
||||||
|
// !column.inverted && (column.bold ? 'dark-text' : 'light-text'),
|
||||||
|
]"
|
||||||
|
>
|
||||||
|
{{ column.format(row[column.key], row, index) }}
|
||||||
|
</span>
|
||||||
|
</slot>
|
||||||
|
</VFlexTableCell>
|
||||||
|
</template>
|
||||||
|
</slot>
|
||||||
|
</div>
|
||||||
|
<slot
|
||||||
|
name="body-row-post"
|
||||||
|
:row="row"
|
||||||
|
:columns="columns"
|
||||||
|
:index="index"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</slot>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.flex-table {
|
||||||
|
.flex-table-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 20px 10px;
|
||||||
|
background-color: var(--primary);
|
||||||
|
|
||||||
|
> span,
|
||||||
|
.text {
|
||||||
|
flex: 1 1 0;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 1.0rem;
|
||||||
|
font-weight: 600;
|
||||||
|
color: var(--smoke-white);
|
||||||
|
text-transform: uppercase;
|
||||||
|
padding: 0 10px;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
&.is-checkbox {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
width: 30px;
|
||||||
|
max-width: 30px;
|
||||||
|
|
||||||
|
.checkbox {
|
||||||
|
padding: 0;
|
||||||
|
|
||||||
|
> span {
|
||||||
|
height: 22px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.cell-center {
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.cell-end {
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.is-grow {
|
||||||
|
flex-grow: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.is-grow-lg {
|
||||||
|
flex-grow: 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.is-grow-xl {
|
||||||
|
flex-grow: 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: var(--muted-grey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.checkbox {
|
||||||
|
padding-bottom: 10px;
|
||||||
|
padding-top: 0;
|
||||||
|
|
||||||
|
> span {
|
||||||
|
min-height: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.flex-table-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: stretch;
|
||||||
|
width: 100%;
|
||||||
|
min-height: 60px;
|
||||||
|
background: var(--white);
|
||||||
|
border: 1px solid color-mix(in oklab, var(--fade-grey), black 3%);
|
||||||
|
padding: 8px;
|
||||||
|
margin-bottom: 6px;
|
||||||
|
|
||||||
|
&.is-row {
|
||||||
|
border: none;
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.sub-table {
|
||||||
|
.flex-table-item {
|
||||||
|
padding-top: 0;
|
||||||
|
padding-bottom: 0;
|
||||||
|
margin-bottom: 0;
|
||||||
|
min-height: 40px;
|
||||||
|
border: none;
|
||||||
|
background: transparent;
|
||||||
|
|
||||||
|
.table-label {
|
||||||
|
font-family: var(--font);
|
||||||
|
text-transform: uppercase;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
color: var(--light-text);
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-total {
|
||||||
|
font-family: var(--font);
|
||||||
|
color: var(--dark-text);
|
||||||
|
font-weight: 500;
|
||||||
|
|
||||||
|
&.is-bigger {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.is-compact {
|
||||||
|
.flex-table-item {
|
||||||
|
margin-bottom: 0;
|
||||||
|
border-radius: 0;
|
||||||
|
|
||||||
|
&:not(:last-child) {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.is-rounded {
|
||||||
|
&:not(.no-header) {
|
||||||
|
.flex-table-item {
|
||||||
|
&:nth-of-type(2) {
|
||||||
|
border-radius: 8px 8px 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
margin-bottom: 6px;
|
||||||
|
border-radius: 0 0 8px 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.no-header {
|
||||||
|
.flex-table-item {
|
||||||
|
&:first-child {
|
||||||
|
border-radius: 8px 8px 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
margin-bottom: 6px;
|
||||||
|
border-radius: 0 0 8px 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:not(.is-compact) {
|
||||||
|
&.is-rounded {
|
||||||
|
.flex-table-item {
|
||||||
|
border-radius: 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.is-table-clickable {
|
||||||
|
.flex-table-item {
|
||||||
|
&:hover,
|
||||||
|
&:focus-within {
|
||||||
|
background: var(--widget-grey) !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.with-separators {
|
||||||
|
.flex-table-item {
|
||||||
|
.flex-table-cell {
|
||||||
|
&:not(:first-of-type) {
|
||||||
|
border-inline-start: solid 1px color-mix(in oklab, var(--fade-grey), black 3%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ==========================================================================
|
||||||
|
2. Flex Table Dark mode
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
.is-dark {
|
||||||
|
.flex-table {
|
||||||
|
&:not(.sub-table) {
|
||||||
|
.flex-table-item {
|
||||||
|
background: color-mix(in oklab, var(--dark-sidebar), white 6%);
|
||||||
|
border-color: color-mix(in oklab, var(--dark-sidebar), white 12%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.with-separators {
|
||||||
|
.flex-table-item {
|
||||||
|
.flex-table-cell {
|
||||||
|
&:not(:first-of-type) {
|
||||||
|
border-inline-start: dashed 1px color-mix(in oklab, var(--dark-sidebar), white 12%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.is-table-clickable {
|
||||||
|
.flex-table-item {
|
||||||
|
&:hover,
|
||||||
|
&:focus-within {
|
||||||
|
background: color-mix(in oklab, var(--dark-sidebar), white 12%) !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ==========================================================================
|
||||||
|
3. Media Queries
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
@media (width <= 767px) {
|
||||||
|
.flex-table {
|
||||||
|
.flex-table-header {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flex-table-item {
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
width: 100% !important;
|
||||||
|
padding: 20px;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
> div {
|
||||||
|
border: none !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:not(.sub-table) {
|
||||||
|
.flex-table-item {
|
||||||
|
.flex-table-cell {
|
||||||
|
> span,
|
||||||
|
> small,
|
||||||
|
> strong,
|
||||||
|
> p,
|
||||||
|
> div,
|
||||||
|
> .is-pushed-mobile,
|
||||||
|
> .text {
|
||||||
|
margin-inline-start: auto;
|
||||||
|
|
||||||
|
&.no-push {
|
||||||
|
margin-inline-start: 0 !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:not(:first-child) {
|
||||||
|
.flex-table-cell {
|
||||||
|
&[data-th] {
|
||||||
|
&::before {
|
||||||
|
content: attr(data-th);
|
||||||
|
font-size: 0.9rem;
|
||||||
|
text-transform: uppercase;
|
||||||
|
font-weight: 500;
|
||||||
|
color: var(--muted-grey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media only screen and (width <= 767px) {
|
||||||
|
.flex-table {
|
||||||
|
&.sub-table {
|
||||||
|
padding-top: 16px;
|
||||||
|
|
||||||
|
.is-vhidden {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flex-table-item:not(.is-vhidden) {
|
||||||
|
flex-direction: revert !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.paymentColumn1 {
|
||||||
|
min-width: 20%;
|
||||||
|
}
|
||||||
|
.paymentColumn2 {
|
||||||
|
min-width: 40%;
|
||||||
|
}
|
||||||
|
.paymentColumn3 {
|
||||||
|
min-width: 10%;
|
||||||
|
}
|
||||||
|
.paymentColumn4 {
|
||||||
|
min-width: 20%;
|
||||||
|
}
|
||||||
|
.paymentColumn5 {
|
||||||
|
min-width: 10%;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -62,11 +62,6 @@ const links = ref<NavbarItem[]>([
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template #toolbar>
|
<template #toolbar>
|
||||||
<!-- <LayoutSwitcher class="is-hidden-mobile" />-->
|
|
||||||
<!-- <ToolbarNotification />-->
|
|
||||||
<!-- <ToolbarActivity />-->
|
|
||||||
<ToolbarThemeToggle />
|
|
||||||
<!-- <ToolbarLanguage />-->
|
|
||||||
<ToolbarUserProfile right class="ml-2 is-hidden-mobile" />
|
<ToolbarUserProfile right class="ml-2 is-hidden-mobile" />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
@@ -7,24 +7,24 @@ definePage({
|
|||||||
requiresAuth: true,
|
requiresAuth: true,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
const breadcrumb = [
|
// const breadcrumb = [
|
||||||
{
|
// {
|
||||||
label: '가격조사',
|
// label: '가격조사',
|
||||||
hideLabel: true,
|
// hideLabel: true,
|
||||||
// use external links
|
// // use external links
|
||||||
link: 'https://vuero.cssninja.io/',
|
// link: 'https://vuero.cssninja.io/',
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
label: '가격조사',
|
// label: '가격조사',
|
||||||
// or generate a router link with 'to' props
|
// // or generate a router link with 'to' props
|
||||||
to: '/components/',
|
// to: '/components/',
|
||||||
}
|
// }
|
||||||
]
|
// ]
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<Navbar>
|
<Navbar>
|
||||||
<VBreadcrumb :items="breadcrumb" separator="succeeds" />
|
<!-- <VBreadcrumb :items="breadcrumb" separator="succeeds" />-->
|
||||||
<RouterView />
|
<RouterView />
|
||||||
</Navbar>
|
</Navbar>
|
||||||
</template>
|
</template>
|
||||||
@@ -4,6 +4,9 @@ import type { VFlexTableWrapperSortFunction, VFlexTableWrapperFilterFunction } f
|
|||||||
import { users } from '/src/data/layouts/card-grid-v1'
|
import { users } from '/src/data/layouts/card-grid-v1'
|
||||||
import PriceDetail from "/@src/pages/app/priceDetail.vue";
|
import PriceDetail from "/@src/pages/app/priceDetail.vue";
|
||||||
import {conveterNo, updateApprovalStatus} from "/@src/service/approvalApi.ts";
|
import {conveterNo, updateApprovalStatus} from "/@src/service/approvalApi.ts";
|
||||||
|
import {formatDatefromString} from "/@src/utils/common/comfunc.ts";
|
||||||
|
import {getPriceList} from "/@src/service/priceApi.ts";
|
||||||
|
import {getContractList} from "/@src/service/contractApi.ts";
|
||||||
|
|
||||||
|
|
||||||
onBeforeMount(async () => {
|
onBeforeMount(async () => {
|
||||||
@@ -13,6 +16,45 @@ const isModalOpen = ref(false)
|
|||||||
const selectedRow = ref<any>(null)
|
const selectedRow = ref<any>(null)
|
||||||
const prcsNo = ref<string>('')
|
const prcsNo = ref<string>('')
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
const totalItems = ref(0) // 전체 아이템 수
|
||||||
|
const currentPage = ref<number>(1) // 현재 페이지
|
||||||
|
const itemsPerPage = 8
|
||||||
|
const totalPages = ref(1)
|
||||||
|
|
||||||
|
async function getApprovalListData(){
|
||||||
|
const today = new Date()
|
||||||
|
searchParamsList.regSdt = new Date().setDate(today.getDate() - 30)
|
||||||
|
searchParamsList.regEdt = new Date().setDate(today.getDate())
|
||||||
|
|
||||||
|
const priceBase = {
|
||||||
|
params:{
|
||||||
|
regSdt: formatDatefromString(searchParamsList.regSdt),
|
||||||
|
regEdt: formatDatefromString(searchParamsList.regEdt),
|
||||||
|
page: 1,
|
||||||
|
row: itemsPerPage
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const result = await getPriceList(priceBase)
|
||||||
|
params.priceData = result.content
|
||||||
|
//페이지 관련 값 설정
|
||||||
|
totalItems.value = result.totalElements
|
||||||
|
totalPages.value = result.totalPages
|
||||||
|
}
|
||||||
|
|
||||||
|
const searchApprovalDoc = async (item) => {
|
||||||
|
const searchParams = {
|
||||||
|
params: {
|
||||||
|
title : searchParamsList.title, //제목
|
||||||
|
regSdt: formatDatefromString(searchParamsList.regSdt),//등록시작일
|
||||||
|
regEdt: formatDatefromString(searchParamsList.regEdt),//등록종료일
|
||||||
|
page: item,//페이지
|
||||||
|
row: itemsPerPage //아이템갯수
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const result = await getContractList(searchParams)
|
||||||
|
params.priceData = result.content
|
||||||
|
totalItems.value = result.totalElements
|
||||||
|
}
|
||||||
|
|
||||||
const masks = ref({
|
const masks = ref({
|
||||||
modelValue: 'YYYY-MM-DD',
|
modelValue: 'YYYY-MM-DD',
|
||||||
@@ -34,14 +76,7 @@ const params = reactive({
|
|||||||
},
|
},
|
||||||
{ key: 'process', label: '구분', cellClass: 'paymentColumn5' },
|
{ key: 'process', label: '구분', cellClass: 'paymentColumn5' },
|
||||||
],
|
],
|
||||||
flexWrapperColumn: {
|
approvalParams: [],
|
||||||
apprNo: { label: '결재번호', cellClass: 'paymentColumn1', searchable: true, sortable: true },
|
|
||||||
title: { label: '제목', cellClass: 'paymentColumn2', searchable: true, sortable: true },
|
|
||||||
name: { label: '작성자', cellClass: 'paymentColumn3', searchable: true, sortable: true },
|
|
||||||
regDt: { label: '등록일', cellClass: 'paymentColumn4', searchable: true, sortable: true },
|
|
||||||
process: { label: '구분', cellClass: 'paymentColumn5', searchable: true, sortable: true },
|
|
||||||
},
|
|
||||||
paymentParams: [],
|
|
||||||
rowData: [],
|
rowData: [],
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -57,10 +92,13 @@ async function getIntegratedPaymentList() {
|
|||||||
sabun: '17131303', // 김진형 17131303, 손원창 17131304
|
sabun: '17131303', // 김진형 17131303, 손원창 17131304
|
||||||
}
|
}
|
||||||
const result = await getIntegratedApproval(paymentParams)
|
const result = await getIntegratedApproval(paymentParams)
|
||||||
params.paymentParams = result.content.map(item => ({
|
params.approvalParams = result.content.map(item => ({
|
||||||
...item,
|
...item,
|
||||||
process: gubunMap[item.gubun] || '',
|
process: gubunMap[item.gubun] || '',
|
||||||
}))
|
}))
|
||||||
|
//페이지 관련 값 설정
|
||||||
|
totalItems.value = result.totalElements
|
||||||
|
totalPages.value = result.totalPages
|
||||||
}
|
}
|
||||||
|
|
||||||
async function updateIntegratedPaymentApprovalFunc() {
|
async function updateIntegratedPaymentApprovalFunc() {
|
||||||
@@ -95,16 +133,16 @@ const gubunMap = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const searchApproval = async () => {
|
const searchApproval = async () => {
|
||||||
const paymentParams = {
|
const searchParams = {
|
||||||
params: {
|
params: {
|
||||||
title: params.title,
|
title: params.title,
|
||||||
page: '1',
|
page: '1',
|
||||||
row: '10',
|
row: '10',
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
const result = await getIntegratedApproval(paymentParams)
|
const result = await getIntegratedApproval(searchParams)
|
||||||
params.paymentParams = result.content
|
params.approvalParams = result.content
|
||||||
console.log(params.paymentParams)
|
console.log(params.approvalParams)
|
||||||
}
|
}
|
||||||
|
|
||||||
type User = (typeof users)[0]
|
type User = (typeof users)[0]
|
||||||
@@ -271,7 +309,7 @@ const onRowClick2 = (row: any) => {
|
|||||||
</div>
|
</div>
|
||||||
<div class="datatable-wrapper">
|
<div class="datatable-wrapper">
|
||||||
<ComVFlexTable
|
<ComVFlexTable
|
||||||
:data="params.paymentParams"
|
:data="params.approvalParams"
|
||||||
:columns="params.flexColumn"
|
:columns="params.flexColumn"
|
||||||
:separators="true"
|
:separators="true"
|
||||||
:clickable="true"
|
:clickable="true"
|
||||||
@@ -308,119 +346,32 @@ const onRowClick2 = (row: any) => {
|
|||||||
<VButton type="submit" color="primary" raised @click="updateIntegratedPaymentApprovalFunc">승인</VButton>
|
<VButton type="submit" color="primary" raised @click="updateIntegratedPaymentApprovalFunc">승인</VButton>
|
||||||
</template>
|
</template>
|
||||||
</VModal>
|
</VModal>
|
||||||
<!-- <VFlexTableWrapper :columns="params.flexWrapperColumn" :data="params.paymentParams">-->
|
|
||||||
<!--<!–-->
|
|
||||||
<!-- Here we retrieve the internal wrapperState.-->
|
|
||||||
<!-- Note that we can not destructure it-->
|
|
||||||
<!-- –>-->
|
|
||||||
<!-- <template #default="wrapperState">-->
|
|
||||||
<!-- <pre>data: {{ data }}</pre>-->
|
|
||||||
<!-- <!– We can place any content inside the default slot–>-->
|
|
||||||
<!-- <VFlexTableToolbar>-->
|
|
||||||
<!-- <template #left>-->
|
|
||||||
<!-- <!– We can bind wrapperState.searchInput to any input –>-->
|
|
||||||
<!-- <VField>-->
|
|
||||||
<!-- <VControl icon="lucide:search">-->
|
|
||||||
<!-- <input-->
|
|
||||||
<!-- v-model="wrapperState.searchInput"-->
|
|
||||||
<!-- type="text"-->
|
|
||||||
<!-- class="input is-rounded"-->
|
|
||||||
<!-- placeholder="Filter..."-->
|
|
||||||
<!-- >-->
|
|
||||||
<!-- </VControl>-->
|
|
||||||
<!-- </VField>-->
|
|
||||||
<!-- </template>-->
|
|
||||||
|
|
||||||
<!-- <template #right>-->
|
<VFlexPagination
|
||||||
<!-- <!– We can also bind wrapperState.limit –>-->
|
:item-per-page="itemsPerPage"
|
||||||
<!-- <VField>-->
|
:total-items="totalItems"
|
||||||
<!-- <VControl>-->
|
v-model:current-page="currentPage"
|
||||||
<!-- <div class="select is-rounded">-->
|
/>
|
||||||
<!-- <select v-model="wrapperState.limit">-->
|
|
||||||
<!-- <option :value="1">-->
|
|
||||||
<!-- 1 results per page-->
|
|
||||||
<!-- </option>-->
|
|
||||||
<!-- <option :value="10">-->
|
|
||||||
<!-- 10 results per page-->
|
|
||||||
<!-- </option>-->
|
|
||||||
<!-- <option :value="15">-->
|
|
||||||
<!-- 15 results per page-->
|
|
||||||
<!-- </option>-->
|
|
||||||
<!-- <option :value="25">-->
|
|
||||||
<!-- 25 results per page-->
|
|
||||||
<!-- </option>-->
|
|
||||||
<!-- <option :value="50">-->
|
|
||||||
<!-- 50 results per page-->
|
|
||||||
<!-- </option>-->
|
|
||||||
<!-- </select>-->
|
|
||||||
<!-- </div>-->
|
|
||||||
<!-- </VControl>-->
|
|
||||||
<!-- </VField>-->
|
|
||||||
<!-- </template>-->
|
|
||||||
<!-- </VFlexTableToolbar>-->
|
|
||||||
|
|
||||||
<!-- <!–-->
|
|
||||||
<!-- The VFlexTable "data" and "columns" props-->
|
|
||||||
<!-- will be inherited from parent VFlexTableWrapper-->
|
|
||||||
<!-- –>-->
|
|
||||||
<!-- <VFlexTable rounded>-->
|
|
||||||
<!-- <!– Custom "name" cell content –>-->
|
|
||||||
<!-- <template #body-cell="{ row, column }">-->
|
|
||||||
<!-- <template v-if="column.key === 'name'">-->
|
|
||||||
<!-- <VAvatar-->
|
|
||||||
<!-- size="medium"-->
|
|
||||||
<!-- :picture="row.medias.avatar"-->
|
|
||||||
<!-- :badge="row.medias.badge"-->
|
|
||||||
<!-- :initials="row.initials"-->
|
|
||||||
<!-- />-->
|
|
||||||
<!-- <div>-->
|
|
||||||
<!-- <span class="dark-text" :title="row.name">-->
|
|
||||||
<!-- {{ row?.shortname }}-->
|
|
||||||
<!-- </span>-->
|
|
||||||
<!-- <VTextEllipsis-->
|
|
||||||
<!-- width="280px"-->
|
|
||||||
<!-- class="light-text"-->
|
|
||||||
<!-- :title="row.bio"-->
|
|
||||||
<!-- >-->
|
|
||||||
<!-- <small>{{ row?.bio }}</small>-->
|
|
||||||
<!-- </VTextEllipsis>-->
|
|
||||||
<!-- </div>-->
|
|
||||||
<!-- </template>-->
|
|
||||||
<!-- </template>-->
|
|
||||||
<!-- </VFlexTable>-->
|
|
||||||
|
|
||||||
<!-- <!– Table Pagination with wrapperState.page binded–>-->
|
|
||||||
<!-- <VFlexPagination-->
|
|
||||||
<!-- v-model:current-page="wrapperState.page"-->
|
|
||||||
<!-- class="mt-6"-->
|
|
||||||
<!-- :item-per-page="wrapperState.limit"-->
|
|
||||||
<!-- :total-items="wrapperState.total"-->
|
|
||||||
<!-- :max-links-displayed="5"-->
|
|
||||||
<!-- no-router-->
|
|
||||||
<!-- />-->
|
|
||||||
<!-- </template>-->
|
|
||||||
<!-- </VFlexTableWrapper>-->
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- <VButtons class="v-buttons-right-align">-->
|
|
||||||
<!-- <VButton-->
|
|
||||||
<!-- color="primary"-->
|
|
||||||
<!-- icon="fas fa-plus"-->
|
|
||||||
<!-- elevated-->
|
|
||||||
<!-- to="/app/PriceInsert"-->
|
|
||||||
<!-- >-->
|
|
||||||
<!-- 등록-->
|
|
||||||
<!-- </VButton>-->
|
|
||||||
<!-- </VButtons>-->
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
|
.datatable-toolbar {
|
||||||
|
padding: 1rem 1.5rem;
|
||||||
|
margin: 0 0 2rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flex-table .flex-table-item {
|
||||||
|
min-height: 3rem;
|
||||||
|
}
|
||||||
|
|
||||||
input[readonly] {
|
input[readonly] {
|
||||||
background-color: #f5f5f5; /* 살짝 회색 배경 */
|
background-color: #f5f5f5;
|
||||||
color: #888; /* 글자색 연하게 */
|
color: #888;
|
||||||
cursor: not-allowed; /* 마우스 커서 변경 */
|
cursor: not-allowed;
|
||||||
border-color: #e0e0e0; /* 테두리 연하게 */
|
border-color: #e0e0e0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.v-buttons-right-align {
|
.v-buttons-right-align {
|
||||||
|
|||||||
@@ -207,3 +207,15 @@ function getContractDetail(){
|
|||||||
</VButtons>
|
</VButtons>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.datatable-toolbar {
|
||||||
|
padding: 1rem 1.5rem;
|
||||||
|
margin: 0 0 2rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flex-table .flex-table-item {
|
||||||
|
min-height: 3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
|
|||||||
@@ -326,7 +326,7 @@ const onPrcsFileDownload = async (prcsNo: string, fileOrd: number, logiFnm: stri
|
|||||||
<td>견적서확인</td>
|
<td>견적서확인</td>
|
||||||
<td colspan="9">
|
<td colspan="9">
|
||||||
<slot name="status"
|
<slot name="status"
|
||||||
v-if="!params.svyYn"
|
v-if="params.stCd == '0100'"
|
||||||
>
|
>
|
||||||
<div style="display: flex; justify-content: flex-end; gap: 8px;">
|
<div style="display: flex; justify-content: flex-end; gap: 8px;">
|
||||||
<VButton
|
<VButton
|
||||||
@@ -340,7 +340,7 @@ const onPrcsFileDownload = async (prcsNo: string, fileOrd: number, logiFnm: stri
|
|||||||
</div>
|
</div>
|
||||||
</slot>
|
</slot>
|
||||||
<div class="mt-2">
|
<div class="mt-2">
|
||||||
<ComVFlexTable
|
<VFlexTableCustomize
|
||||||
:key="params.prcsBizs.length"
|
:key="params.prcsBizs.length"
|
||||||
:data="params.prcsBizs"
|
:data="params.prcsBizs"
|
||||||
:columns="params.prcsBizsColumn"
|
:columns="params.prcsBizsColumn"
|
||||||
@@ -373,13 +373,12 @@ const onPrcsFileDownload = async (prcsNo: string, fileOrd: number, logiFnm: stri
|
|||||||
</template>
|
</template>
|
||||||
<!-- 나머지 컬럼만 이 슬롯 사용 -->
|
<!-- 나머지 컬럼만 이 슬롯 사용 -->
|
||||||
<template #body-cell="{ column, index, value, row }">
|
<template #body-cell="{ column, index, value, row }">
|
||||||
<pre>{{ row.sendYn }}</pre>
|
|
||||||
<div>
|
<div>
|
||||||
<span v-if="column.key=='num'">{{index + 1}}</span>
|
<span v-if="column.key=='num'">{{index + 1}}</span>
|
||||||
<span v-else>{{ value }}</span>
|
<span v-else>{{ value }}</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</ComVFlexTable>
|
</VFlexTableCustomize>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|||||||
Reference in New Issue
Block a user