Compare commits
No commits in common. "40a1c2740d6b9e961d542a6c189b8179291dfb6a" and "77c0a7d43fe1e7d195d116db1a9f53f345e9a756" have entirely different histories.
40a1c2740d
...
77c0a7d43f
|
|
@ -1,11 +1,8 @@
|
||||||
package com.leejk0523.javavue.admin.contents.controller;
|
package com.leejk0523.javavue.admin.contents.controller;
|
||||||
|
|
||||||
import com.leejk0523.javavue.admin.contents.service.AdminContentsService;
|
import com.leejk0523.javavue.admin.contents.service.AdminContentsService;
|
||||||
import com.leejk0523.javavue.admin.contents.vo.ContentsListResult;
|
|
||||||
import com.leejk0523.javavue.admin.contents.vo.ContentsPagingQuery;
|
|
||||||
import com.leejk0523.javavue.model.AsaContent;
|
import com.leejk0523.javavue.model.AsaContent;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.data.domain.Page;
|
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
@ -18,8 +15,8 @@ public class AdminContentsController {
|
||||||
private final AdminContentsService adminContentsService;
|
private final AdminContentsService adminContentsService;
|
||||||
|
|
||||||
@GetMapping("/api/admin/contents/contentsList")
|
@GetMapping("/api/admin/contents/contentsList")
|
||||||
public ResponseEntity<Page<ContentsListResult>> findContentsList(ContentsPagingQuery query) {
|
public ResponseEntity<List<AsaContent>> siteAllList() {
|
||||||
final var results = adminContentsService.findContentsList(query);
|
final var results = adminContentsService.SiteAllList();
|
||||||
return ResponseEntity.ok(results);
|
return ResponseEntity.ok(results);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,7 @@
|
||||||
package com.leejk0523.javavue.admin.contents.dao;
|
package com.leejk0523.javavue.admin.contents.dao;
|
||||||
|
|
||||||
import com.leejk0523.javavue.admin.contents.vo.ContentsListResult;
|
|
||||||
import com.leejk0523.javavue.admin.contents.vo.ContentsPagingQuery;
|
|
||||||
import com.leejk0523.javavue.model.AsaContent;
|
import com.leejk0523.javavue.model.AsaContent;
|
||||||
import com.leejk0523.javavue.model.QAsaContent;
|
import com.leejk0523.javavue.model.QAsaContent;
|
||||||
import com.querydsl.core.types.Projections;
|
|
||||||
import com.querydsl.core.types.dsl.BooleanExpression;
|
|
||||||
|
|
||||||
import org.springframework.data.domain.Page;
|
|
||||||
import org.springframework.data.domain.PageImpl;
|
|
||||||
import org.springframework.data.domain.PageRequest;
|
|
||||||
import org.springframework.data.domain.Pageable;
|
|
||||||
import org.springframework.data.jpa.repository.support.QuerydslRepositorySupport;
|
import org.springframework.data.jpa.repository.support.QuerydslRepositorySupport;
|
||||||
import org.springframework.stereotype.Repository;
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
|
|
@ -22,50 +13,11 @@ public class AdminContentsDao extends QuerydslRepositorySupport {
|
||||||
super(AsaContent.class);
|
super(AsaContent.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Page<ContentsListResult> findContentsList(ContentsPagingQuery query) {
|
public List<AsaContent> SiteAllList() {
|
||||||
QAsaContent asaContent = QAsaContent.asaContent;
|
QAsaContent asaContent = QAsaContent.asaContent;
|
||||||
|
|
||||||
final var offset = getOffset(query);
|
return from(asaContent)
|
||||||
final var limit = getLimit(query);
|
|
||||||
final var pageable = getPageable(query);
|
|
||||||
|
|
||||||
BooleanExpression expression = asaContent.delYn.eq("N");
|
|
||||||
|
|
||||||
final var list = from(asaContent)
|
|
||||||
.select(
|
|
||||||
Projections.bean(
|
|
||||||
ContentsListResult.class,
|
|
||||||
asaContent.contentId,
|
|
||||||
asaContent.contentTitle,
|
|
||||||
asaContent.orgId,
|
|
||||||
asaContent.useYn,
|
|
||||||
asaContent.frstRgtrId,
|
|
||||||
asaContent.frstRegDt,
|
|
||||||
asaContent.lastMdfrId,
|
|
||||||
asaContent.lastMdfcnDt
|
|
||||||
)
|
|
||||||
)
|
|
||||||
.where(expression)
|
|
||||||
.limit(limit)
|
|
||||||
.offset(offset)
|
|
||||||
.orderBy(asaContent.contentId.desc())
|
|
||||||
.fetch();
|
.fetch();
|
||||||
|
|
||||||
final var total = from(asaContent).where(expression).fetchCount();
|
|
||||||
|
|
||||||
return new PageImpl<>(list, pageable, total);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Pageable getPageable(ContentsPagingQuery query) {
|
|
||||||
return PageRequest.of(query.getPage() - 1, query.getSize());
|
|
||||||
}
|
|
||||||
|
|
||||||
private long getOffset(ContentsPagingQuery query) {
|
|
||||||
return (long) (query.getPage() - 1) * query.getSize();
|
|
||||||
}
|
|
||||||
|
|
||||||
private long getLimit(ContentsPagingQuery query) {
|
|
||||||
return query.getSize();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,9 @@
|
||||||
package com.leejk0523.javavue.admin.contents.service;
|
package com.leejk0523.javavue.admin.contents.service;
|
||||||
|
|
||||||
import com.leejk0523.javavue.admin.contents.vo.ContentsListResult;
|
|
||||||
import com.leejk0523.javavue.admin.contents.vo.ContentsPagingQuery;
|
|
||||||
import com.leejk0523.javavue.model.AsaContent;
|
import com.leejk0523.javavue.model.AsaContent;
|
||||||
import org.springframework.data.domain.Page;
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public interface AdminContentsService {
|
public interface AdminContentsService {
|
||||||
Page<ContentsListResult> findContentsList(ContentsPagingQuery query);
|
List<AsaContent> SiteAllList();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,8 @@
|
||||||
package com.leejk0523.javavue.admin.contents.service;
|
package com.leejk0523.javavue.admin.contents.service;
|
||||||
|
|
||||||
import com.leejk0523.javavue.admin.contents.dao.AdminContentsDao;
|
import com.leejk0523.javavue.admin.contents.dao.AdminContentsDao;
|
||||||
import com.leejk0523.javavue.admin.contents.vo.ContentsListResult;
|
|
||||||
import com.leejk0523.javavue.admin.contents.vo.ContentsPagingQuery;
|
|
||||||
import com.leejk0523.javavue.model.AsaContent;
|
import com.leejk0523.javavue.model.AsaContent;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.data.domain.Page;
|
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
@ -16,7 +13,7 @@ public class AdminContentsServiceImpl implements AdminContentsService {
|
||||||
private final AdminContentsDao adminContentsDao;
|
private final AdminContentsDao adminContentsDao;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Page<ContentsListResult> findContentsList(ContentsPagingQuery query) {
|
public List<AsaContent> SiteAllList() {
|
||||||
return adminContentsDao.findContentsList(query);
|
return adminContentsDao.SiteAllList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,17 +0,0 @@
|
||||||
package com.leejk0523.javavue.admin.contents.vo;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
public class ContentsListResult {
|
|
||||||
private Integer contentId;
|
|
||||||
private String contentTitle;
|
|
||||||
private String orgId;
|
|
||||||
private String useYn;
|
|
||||||
private String frstRgtrId;
|
|
||||||
private LocalDateTime frstRegDt;
|
|
||||||
private String lastMdfrId;
|
|
||||||
private LocalDateTime lastMdfcnDt;
|
|
||||||
}
|
|
||||||
|
|
@ -1,24 +0,0 @@
|
||||||
package com.leejk0523.javavue.admin.contents.vo;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
import jakarta.validation.constraints.NotNull;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
public class ContentsPagingQuery {
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private int page;
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private int size;
|
|
||||||
|
|
||||||
private String orgId;
|
|
||||||
private String siteId;
|
|
||||||
private String keyword;
|
|
||||||
private Type type;
|
|
||||||
|
|
||||||
public enum Type {
|
|
||||||
TITLE,
|
|
||||||
CONTENT
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -10,15 +10,18 @@ import java.time.LocalDateTime;
|
||||||
@Getter
|
@Getter
|
||||||
@Setter
|
@Setter
|
||||||
@Entity
|
@Entity
|
||||||
@Table(name = "ASA_CONTENT")
|
@Table(name = "asa_content")
|
||||||
public class AsaContent {
|
public class AsaContent {
|
||||||
|
|
||||||
@Id
|
@Id
|
||||||
@SequenceGenerator(name = "SQ_ASA_CONTENT", sequenceName = "SQ_ASA_CONTENT", allocationSize = 1)
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SQ_ASA_CONTENT")
|
|
||||||
@Column(name = "CONTENT_ID", nullable = false)
|
@Column(name = "CONTENT_ID", nullable = false)
|
||||||
private Integer contentId;
|
private Integer contentId;
|
||||||
|
|
||||||
|
@Size(max = 20)
|
||||||
|
@Column(name = "SITE_ID", length = 20)
|
||||||
|
private String siteId;
|
||||||
|
|
||||||
@Column(name = "ORG_ID", length = 36)
|
@Column(name = "ORG_ID", length = 36)
|
||||||
private String orgId;
|
private String orgId;
|
||||||
|
|
||||||
|
|
@ -35,10 +38,10 @@ public class AsaContent {
|
||||||
private String contentPlain;
|
private String contentPlain;
|
||||||
|
|
||||||
@Column(name = "USE_YN", length = 1, nullable = false)
|
@Column(name = "USE_YN", length = 1, nullable = false)
|
||||||
private String useYn;
|
private Boolean useYn;
|
||||||
|
|
||||||
@Column(name = "DEL_YN", length = 1, nullable = false)
|
@Column(name = "DEL_YN", length = 1, nullable = false)
|
||||||
private String delYn;
|
private Boolean delYn;
|
||||||
|
|
||||||
@Column(name = "FRST_RGTR_ID", length = 50, nullable = false)
|
@Column(name = "FRST_RGTR_ID", length = 50, nullable = false)
|
||||||
private String frstRgtrId;
|
private String frstRgtrId;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import 'tui-pagination/dist/tui-pagination.css';
|
||||||
|
import Pagination from 'tui-pagination/dist/tui-pagination';
|
||||||
|
import type { PaginationType } from '~/types/data/pagination';
|
||||||
|
|
||||||
|
const instance = ref();
|
||||||
|
const paginationRef = ref();
|
||||||
|
const props = defineProps<PaginationType>();
|
||||||
|
const emit = defineEmits(['change']);
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
instance.value = new Pagination(paginationRef.value, {
|
||||||
|
totalItems: props.totalItems,
|
||||||
|
itemPerPage: props.itemsPerPage,
|
||||||
|
visiblePages: props.visiblePages ?? 10,
|
||||||
|
centerAlign: props.centerAlign ?? false,
|
||||||
|
usageStatistics: false
|
||||||
|
});
|
||||||
|
|
||||||
|
instance.value.on('beforeMove', (data: any) => {
|
||||||
|
emit('change', data.page);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props,
|
||||||
|
(newValue) => {
|
||||||
|
instance.value.setItemsPerPage(newValue.itemsPerPage);
|
||||||
|
instance.value.setTotalItems(newValue.itemsPerPage);
|
||||||
|
},
|
||||||
|
{
|
||||||
|
deep: true
|
||||||
|
}
|
||||||
|
);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div ref="paginationRef" class="tui-pagination"></div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped></style>
|
||||||
|
|
@ -1,163 +0,0 @@
|
||||||
<script setup lang="ts">
|
|
||||||
import 'tui-pagination/dist/tui-pagination.css';
|
|
||||||
import type { PaginationType } from '~/types/data/pagination';
|
|
||||||
import {
|
|
||||||
DoubleLeftOutlined,
|
|
||||||
DoubleRightOutlined,
|
|
||||||
LeftOutlined,
|
|
||||||
RightOutlined
|
|
||||||
} from '@ant-design/icons-vue';
|
|
||||||
|
|
||||||
const props = defineProps<PaginationType>();
|
|
||||||
const emit = defineEmits(['change']);
|
|
||||||
|
|
||||||
const totalPages = computed(() => Math.ceil(props.totalElements / props.size));
|
|
||||||
const rangePages = computed(() =>
|
|
||||||
Array.from({ length: totalPages.value }, (_, i) => i + 1)
|
|
||||||
);
|
|
||||||
|
|
||||||
const ranges = computed(() => {
|
|
||||||
const ranges: number[][] = [];
|
|
||||||
do {
|
|
||||||
ranges.push(rangePages.value.splice(0, props.showPaginationCount));
|
|
||||||
} while (rangePages.value.length !== 0);
|
|
||||||
|
|
||||||
if (ranges[0].length === 0) {
|
|
||||||
ranges[0][0] = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ranges;
|
|
||||||
});
|
|
||||||
|
|
||||||
const currentRange = computed(() => {
|
|
||||||
for (const range of ranges.value) {
|
|
||||||
if (range.some((i) => i === props.page)) {
|
|
||||||
return range;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return [];
|
|
||||||
});
|
|
||||||
|
|
||||||
const currentPeriod = computed(() => {
|
|
||||||
for (let i = 0; i < ranges.value.length; ++i) {
|
|
||||||
if (ranges.value[i].some((i) => i === props.page)) {
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
});
|
|
||||||
|
|
||||||
const prevPageNumber = computed(() => {
|
|
||||||
const range = ranges.value[currentPeriod.value - 1];
|
|
||||||
if (range) {
|
|
||||||
return range[range.length - 1];
|
|
||||||
}
|
|
||||||
|
|
||||||
return props.page;
|
|
||||||
});
|
|
||||||
|
|
||||||
const nextPageNumber = computed(() => {
|
|
||||||
const range = ranges.value[currentPeriod.value + 1];
|
|
||||||
if (range) {
|
|
||||||
return range[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
return props.page;
|
|
||||||
});
|
|
||||||
|
|
||||||
const firstPage = () => {
|
|
||||||
submitPage(1);
|
|
||||||
};
|
|
||||||
|
|
||||||
const prevPage = () => {
|
|
||||||
submitPage(prevPageNumber.value);
|
|
||||||
};
|
|
||||||
|
|
||||||
const nextPage = () => {
|
|
||||||
submitPage(nextPageNumber.value);
|
|
||||||
};
|
|
||||||
|
|
||||||
const lastPage = () => {
|
|
||||||
submitPage(totalPages.value ? totalPages.value : 1);
|
|
||||||
};
|
|
||||||
|
|
||||||
const change = (value) => {
|
|
||||||
if (props.size !== value) {
|
|
||||||
emit('change', props.page, value);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const movePage = (value) => {
|
|
||||||
submitPage(value);
|
|
||||||
};
|
|
||||||
|
|
||||||
const submitPage = (page: number) => {
|
|
||||||
if (props.page !== page) {
|
|
||||||
emit('change', page, props.size);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const options = [
|
|
||||||
{ label: '15', value: 15 },
|
|
||||||
{ label: '30', value: 30 },
|
|
||||||
{ label: '50', value: 50 },
|
|
||||||
{ label: '100', value: 100 }
|
|
||||||
];
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<a-row justify="space-between" class="mt-5">
|
|
||||||
<a-col>
|
|
||||||
<a-space>
|
|
||||||
<a-select :options="options" :value="size" @change="change" />
|
|
||||||
<span>건/페이지 (총 {{ totalElements }}건)</span>
|
|
||||||
</a-space>
|
|
||||||
</a-col>
|
|
||||||
<a-col
|
|
||||||
><a-space>
|
|
||||||
<a-button
|
|
||||||
type="link"
|
|
||||||
:icon="h(DoubleLeftOutlined)"
|
|
||||||
size="small"
|
|
||||||
class="pagination-icon-size text-black"
|
|
||||||
@click="firstPage"
|
|
||||||
/>
|
|
||||||
<a-button
|
|
||||||
type="link"
|
|
||||||
:icon="h(LeftOutlined)"
|
|
||||||
class="pagination-icon-size text-black"
|
|
||||||
size="small"
|
|
||||||
@click="prevPage"
|
|
||||||
/>
|
|
||||||
<a-space>
|
|
||||||
<a-button
|
|
||||||
size="small"
|
|
||||||
:type="pageNo === page ? 'default' : `link`"
|
|
||||||
class="text-black"
|
|
||||||
v-for="pageNo in currentRange"
|
|
||||||
:key="`pagination-${pageNo}`"
|
|
||||||
@click="() => movePage(pageNo)"
|
|
||||||
>{{ pageNo }}</a-button
|
|
||||||
>
|
|
||||||
</a-space>
|
|
||||||
<a-button
|
|
||||||
type="link"
|
|
||||||
:icon="h(RightOutlined)"
|
|
||||||
size="small"
|
|
||||||
class="pagination-icon-size text-black"
|
|
||||||
@click="nextPage"
|
|
||||||
/>
|
|
||||||
<a-button
|
|
||||||
type="link"
|
|
||||||
:icon="h(DoubleRightOutlined)"
|
|
||||||
class="pagination-icon-size text-black"
|
|
||||||
size="small"
|
|
||||||
@click="lastPage"
|
|
||||||
/>
|
|
||||||
</a-space>
|
|
||||||
</a-col>
|
|
||||||
<a-col></a-col>
|
|
||||||
</a-row>
|
|
||||||
</template>
|
|
||||||
|
|
@ -1,20 +0,0 @@
|
||||||
export const BOOLEANS = [
|
|
||||||
{ text: '사용', value: 'true' },
|
|
||||||
{ text: '미사용', value: 'false' }
|
|
||||||
];
|
|
||||||
|
|
||||||
export const YES_OR_NO_CODE_LIST = [
|
|
||||||
{ text: '예', value: 'true' },
|
|
||||||
{ text: '아니오', value: 'false' }
|
|
||||||
];
|
|
||||||
|
|
||||||
export const LOCK_CODE_LIST = [
|
|
||||||
{ text: '정상', value: 'false' },
|
|
||||||
{ text: '잠김', value: 'true' }
|
|
||||||
];
|
|
||||||
|
|
||||||
export const ADMIN_STATUS_CODE_LIST = [
|
|
||||||
{ text: '미승인', value: 'NONE' },
|
|
||||||
{ text: '승인', value: 'APRV' },
|
|
||||||
{ text: '반려', value: 'RJCT' }
|
|
||||||
];
|
|
||||||
|
|
@ -21,6 +21,12 @@ export default defineNuxtConfig({
|
||||||
autoImport: true
|
autoImport: true
|
||||||
},
|
},
|
||||||
devtools: { enabled: true },
|
devtools: { enabled: true },
|
||||||
|
// plugins: [
|
||||||
|
// '~/plugins/ant-design-vue.ts'
|
||||||
|
// ],
|
||||||
|
// css: [
|
||||||
|
// 'ant-design-vue/dist/reset.css'
|
||||||
|
// ],
|
||||||
modules: [
|
modules: [
|
||||||
'@pinia/nuxt',
|
'@pinia/nuxt',
|
||||||
'@unocss/nuxt',
|
'@unocss/nuxt',
|
||||||
|
|
@ -29,11 +35,11 @@ export default defineNuxtConfig({
|
||||||
],
|
],
|
||||||
vite: {
|
vite: {
|
||||||
optimizeDeps: {
|
optimizeDeps: {
|
||||||
include: ['tui-grid', 'ant-design-vue']
|
include: ['tui-grid', '@ant-design', 'ant-design-vue']
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
alias: {},
|
alias: {},
|
||||||
experimental: {
|
experimental: {
|
||||||
payloadExtraction: true
|
payloadExtraction: false
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,126 +0,0 @@
|
||||||
<script setup lang="ts">
|
|
||||||
import { useContentStore } from '~/stores/contents';
|
|
||||||
|
|
||||||
const route = useRoute();
|
|
||||||
const router = useRouter();
|
|
||||||
|
|
||||||
const contentId = route.query.contentId;
|
|
||||||
|
|
||||||
const editorRef = ref();
|
|
||||||
|
|
||||||
const contentStore = useContentStore();
|
|
||||||
const { contents, initialValue } = storeToRefs(contentStore);
|
|
||||||
|
|
||||||
onBeforeMount(() => {
|
|
||||||
if (contentId) {
|
|
||||||
contentStore.searchContents(Number(contentId));
|
|
||||||
} else {
|
|
||||||
contentStore.resetContents();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const save = () => {
|
|
||||||
contents.value.contents = editorRef.value.getValue();
|
|
||||||
|
|
||||||
contentStore
|
|
||||||
.updateContents()
|
|
||||||
.then(() => {
|
|
||||||
message.success('콘텐츠 정보가 저장이 되었습니다.');
|
|
||||||
moveList();
|
|
||||||
})
|
|
||||||
.catch(() => {
|
|
||||||
message.error('콘텐츠 저장에 실패하였습니다.');
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const moveList = () => {
|
|
||||||
router.push('/admin/content/list');
|
|
||||||
};
|
|
||||||
|
|
||||||
const nonValid = computed(() => {
|
|
||||||
return !contents.value.contentTitle;
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<client-only>
|
|
||||||
<a-space direction="vertical" class="w-full">
|
|
||||||
<a-card>
|
|
||||||
<a-row>
|
|
||||||
<a-col :span="24">
|
|
||||||
<a-form-item
|
|
||||||
label="제목"
|
|
||||||
label-align="left"
|
|
||||||
:colon="false"
|
|
||||||
:label-col="{ span: 2 }"
|
|
||||||
>
|
|
||||||
<a-input
|
|
||||||
title="제목"
|
|
||||||
placeholder="콘텐츠 제목"
|
|
||||||
v-model:value="contents.contentTitle"
|
|
||||||
/>
|
|
||||||
</a-form-item>
|
|
||||||
</a-col>
|
|
||||||
|
|
||||||
<a-col :span="24">
|
|
||||||
<a-form-item
|
|
||||||
label="기관"
|
|
||||||
label-align="left"
|
|
||||||
:colon="false"
|
|
||||||
:label-col="{ span: 2 }"
|
|
||||||
>
|
|
||||||
<!-- <common-inst-code-select v-model:value="contents.orgId" />-->
|
|
||||||
</a-form-item>
|
|
||||||
</a-col>
|
|
||||||
|
|
||||||
<a-col :span="24">
|
|
||||||
<a-form-item
|
|
||||||
label="내용"
|
|
||||||
label-align="left"
|
|
||||||
:colon="false"
|
|
||||||
:label-col="{ span: 2 }"
|
|
||||||
:wrapper-col="{ span: 22 }"
|
|
||||||
>
|
|
||||||
<lazy-data-editor ref="editorRef" :initial-value="initialValue" />
|
|
||||||
</a-form-item>
|
|
||||||
</a-col>
|
|
||||||
|
|
||||||
<a-col :span="24">
|
|
||||||
<a-form-item
|
|
||||||
label="사용여부"
|
|
||||||
label-align="left"
|
|
||||||
:colon="false"
|
|
||||||
:label-col="{ span: 2 }"
|
|
||||||
:wrapper-col="{ span: 22 }"
|
|
||||||
>
|
|
||||||
<a-switch v-model:checked="contents.useYn" />
|
|
||||||
</a-form-item>
|
|
||||||
</a-col>
|
|
||||||
|
|
||||||
<a-col :span="24">
|
|
||||||
<a-flex justify="space-between">
|
|
||||||
<a-space>
|
|
||||||
<common-permit-button api="/api/admin/contents/updateContents">
|
|
||||||
<a-button
|
|
||||||
type="primary"
|
|
||||||
@click="save"
|
|
||||||
:disabled="nonValid"
|
|
||||||
v-if="!contentId"
|
|
||||||
>저장</a-button
|
|
||||||
>
|
|
||||||
<a-button
|
|
||||||
type="primary"
|
|
||||||
@click="save"
|
|
||||||
v-if="contentId != null"
|
|
||||||
>수정</a-button
|
|
||||||
>
|
|
||||||
</common-permit-button>
|
|
||||||
<a-button type="default" @click="moveList">목록</a-button>
|
|
||||||
</a-space>
|
|
||||||
</a-flex>
|
|
||||||
</a-col>
|
|
||||||
</a-row>
|
|
||||||
</a-card>
|
|
||||||
</a-space>
|
|
||||||
</client-only>
|
|
||||||
</template>
|
|
||||||
|
|
@ -1,194 +0,0 @@
|
||||||
<script setup lang="ts">
|
|
||||||
import type { OptColumn, OptRowHeader } from 'tui-grid/types/options';
|
|
||||||
import { useContentStore } from '~/stores/contents';
|
|
||||||
import type { ContentType } from '~/types/contents';
|
|
||||||
import { BOOLEANS } from '~/constants/grid';
|
|
||||||
// import { useCommonCodeStore } from '~/stores';
|
|
||||||
|
|
||||||
const router = useRouter();
|
|
||||||
|
|
||||||
// const siteCodeList = await useCommonCodeStore().searchSiteCodeList();
|
|
||||||
// const instCodeList = await useCommonCodeStore().searchInstCodeList();
|
|
||||||
const contentStore = useContentStore();
|
|
||||||
const { contentsList, contentsQuery } = storeToRefs(contentStore);
|
|
||||||
const gridRef = ref();
|
|
||||||
|
|
||||||
const gridRowHeaders: OptRowHeader[] = ['checkbox', 'rowNum'];
|
|
||||||
|
|
||||||
const columns: OptColumn[] = [
|
|
||||||
{
|
|
||||||
name: 'contentId',
|
|
||||||
hidden: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'contentTitle',
|
|
||||||
header: '콘텐츠제목'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'orgId',
|
|
||||||
header: '관리기관',
|
|
||||||
width: 100,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'useYn',
|
|
||||||
header: '사용여부',
|
|
||||||
width: 80,
|
|
||||||
align: 'center',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'frstRgtrId',
|
|
||||||
header: '작성자',
|
|
||||||
width: 100
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'frstRegDt',
|
|
||||||
header: '작성일',
|
|
||||||
width: 130
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'lastMdfrId',
|
|
||||||
header: '수정자',
|
|
||||||
width: 100
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'lastMdfcnDt',
|
|
||||||
header: '수정일',
|
|
||||||
width: 130
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
const contentType = [
|
|
||||||
{ label: '전체', value: '' },
|
|
||||||
{ label: '제목', value: 'TITLE' },
|
|
||||||
{ label: '내용', value: 'CONTENT' }
|
|
||||||
];
|
|
||||||
|
|
||||||
onBeforeMount(() => {
|
|
||||||
contentStore.searchContentList();
|
|
||||||
});
|
|
||||||
|
|
||||||
onBeforeUnmount(() => {
|
|
||||||
// contentStore.resetContentListQuery();
|
|
||||||
});
|
|
||||||
|
|
||||||
const search = () => {
|
|
||||||
// contentStore.searchContentList();
|
|
||||||
};
|
|
||||||
|
|
||||||
const list = computed(() => {
|
|
||||||
return contentsList.value.content;
|
|
||||||
});
|
|
||||||
|
|
||||||
watch(list, (newValue) => {
|
|
||||||
if (gridRef.value) {
|
|
||||||
gridRef.value.off('dblclick');
|
|
||||||
if (newValue.length > 0) {
|
|
||||||
setTimeout(() => {
|
|
||||||
gridRef.value.on('dblclick', ({ instance, rowKey }) => {
|
|
||||||
const row = instance.getRow(rowKey);
|
|
||||||
editPage(row.contentId);
|
|
||||||
});
|
|
||||||
}, 100);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const deleteContentList = async () => {
|
|
||||||
const checkedRows = gridRef.value.getCheckedRows() as Array<ContentType>;
|
|
||||||
|
|
||||||
if (!checkedRows.length) {
|
|
||||||
message.warn('삭제할 콘텐츠가 없습니다.');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Modal.confirm({
|
|
||||||
type: 'warning',
|
|
||||||
okText: '예',
|
|
||||||
cancelText: '아니오',
|
|
||||||
title: '컨텐츠 삭제',
|
|
||||||
content: '선택한 컨텐츠를 삭제하시겠습니까?',
|
|
||||||
onOk: async () => {
|
|
||||||
const createdRows = checkedRows.filter((row) => row.contentId);
|
|
||||||
await contentStore.deleteContents(createdRows);
|
|
||||||
await contentStore.searchContentList();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const movePage = (page: number) => {
|
|
||||||
contentsQuery.value.page = page;
|
|
||||||
search();
|
|
||||||
};
|
|
||||||
|
|
||||||
const editPage = (contentId: any) => {
|
|
||||||
const query = typeof contentId === 'number' ? `?contentId=${contentId}` : '';
|
|
||||||
router.push(`/admin/content${query}`);
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<client-only>
|
|
||||||
<a-space direction="vertical" class="w-full">
|
|
||||||
<a-card>
|
|
||||||
<a-row :gutter="[16, 8]">
|
|
||||||
<a-col>
|
|
||||||
<a-space>
|
|
||||||
<a-typography-text>관리기관</a-typography-text>
|
|
||||||
<!-- <lazy-common-inst-code-select-->
|
|
||||||
<!-- key="inst-code-select"-->
|
|
||||||
<!-- v-model="contentsQuery.orgId"-->
|
|
||||||
<!-- class-name="w-40"-->
|
|
||||||
<!-- select-type="ALL"-->
|
|
||||||
<!-- />-->
|
|
||||||
</a-space>
|
|
||||||
</a-col>
|
|
||||||
|
|
||||||
<a-col>
|
|
||||||
<a-space>
|
|
||||||
<a-typography-text>검색어</a-typography-text>
|
|
||||||
<a-select
|
|
||||||
title="컨텐츠 구분"
|
|
||||||
class="w-20"
|
|
||||||
v-model:value="contentsQuery.type"
|
|
||||||
:options="contentType"
|
|
||||||
/>
|
|
||||||
<a-input title="검색어" placeholder="Search" class="w-60" />
|
|
||||||
</a-space>
|
|
||||||
</a-col>
|
|
||||||
<a-col>
|
|
||||||
<a-button type="primary" @click="search">검색</a-button>
|
|
||||||
</a-col>
|
|
||||||
</a-row>
|
|
||||||
</a-card>
|
|
||||||
|
|
||||||
<a-card>
|
|
||||||
<a-space direction="vertical" class="w-full">
|
|
||||||
<a-flex justify="space-between">
|
|
||||||
<!-- <common-permit-button api="/api/admin/contents/deleteContents">-->
|
|
||||||
<!-- <a-button type="primary" danger @click="deleteContentList"-->
|
|
||||||
<!-- >삭제-->
|
|
||||||
<!-- </a-button>-->
|
|
||||||
<!-- </common-permit-button>-->
|
|
||||||
<!-- <common-permit-button api="/api/admin/contents/updateContents">-->
|
|
||||||
<!-- <a-button type="primary" @click="editPage">추가</a-button>-->
|
|
||||||
<!-- </common-permit-button>-->
|
|
||||||
</a-flex>
|
|
||||||
<data-grid
|
|
||||||
:key="`board-content-grid-${Math.random()}`"
|
|
||||||
:row-headers="gridRowHeaders"
|
|
||||||
:data="contentsList.content"
|
|
||||||
:columns="columns"
|
|
||||||
ref="gridRef"
|
|
||||||
/>
|
|
||||||
<data-pagination
|
|
||||||
:key="`pagination-${Math.random()}`"
|
|
||||||
:total-elements="contentsList.totalElements"
|
|
||||||
:show-pagination-count="10"
|
|
||||||
:size="contentsQuery.size"
|
|
||||||
:page="contentsQuery.page"
|
|
||||||
@change="movePage"
|
|
||||||
/>
|
|
||||||
</a-space>
|
|
||||||
</a-card>
|
|
||||||
</a-space>
|
|
||||||
</client-only>
|
|
||||||
</template>
|
|
||||||
|
|
@ -1,140 +0,0 @@
|
||||||
import type {
|
|
||||||
ContentListQueryType,
|
|
||||||
ContentListType,
|
|
||||||
ContentType
|
|
||||||
} from '~/types/contents';
|
|
||||||
import { cloneDeep } from 'lodash-es';
|
|
||||||
import type { Page } from '~/types/common';
|
|
||||||
import { defineStore } from 'pinia';
|
|
||||||
import { ref } from 'vue';
|
|
||||||
import { useAxios } from '~/composables/useAxios';
|
|
||||||
import { message } from 'ant-design-vue';
|
|
||||||
|
|
||||||
const DEFAULT_CONTENT_QUERY: ContentListQueryType = {
|
|
||||||
keyword: '',
|
|
||||||
orgId: '',
|
|
||||||
page: 1,
|
|
||||||
siteId: '',
|
|
||||||
size: 10,
|
|
||||||
type: ''
|
|
||||||
};
|
|
||||||
|
|
||||||
const DEFAULT_CONTENTS_LIST: Page<ContentListType> = {
|
|
||||||
content: [],
|
|
||||||
totalElements: 0,
|
|
||||||
totalPages: 0
|
|
||||||
};
|
|
||||||
|
|
||||||
const DEFAULT_CONTENTS: ContentType = {
|
|
||||||
contentTitle: '',
|
|
||||||
contentPlain: '',
|
|
||||||
contents: '',
|
|
||||||
frstRegDt: '',
|
|
||||||
frstRgtrId: '',
|
|
||||||
lastMdfcnDt: '',
|
|
||||||
lastMdfrId: '',
|
|
||||||
orgId: '',
|
|
||||||
siteId: '',
|
|
||||||
useYn: true
|
|
||||||
};
|
|
||||||
|
|
||||||
export const useContentStore = defineStore('useContentStore', () => {
|
|
||||||
const contentsQuery = ref<ContentListQueryType>(
|
|
||||||
cloneDeep(DEFAULT_CONTENT_QUERY)
|
|
||||||
);
|
|
||||||
|
|
||||||
const contentsList = ref<Page<ContentListType>>(
|
|
||||||
cloneDeep(DEFAULT_CONTENTS_LIST)
|
|
||||||
);
|
|
||||||
|
|
||||||
const contents = ref<ContentType>(cloneDeep(DEFAULT_CONTENTS));
|
|
||||||
const initialValue = ref<string>('');
|
|
||||||
|
|
||||||
const resetContentListQuery = () => {
|
|
||||||
contentsQuery.value = cloneDeep(DEFAULT_CONTENT_QUERY);
|
|
||||||
};
|
|
||||||
|
|
||||||
const resetContentList = () => {
|
|
||||||
contentsList.value = cloneDeep(DEFAULT_CONTENTS_LIST);
|
|
||||||
};
|
|
||||||
|
|
||||||
const resetContents = () => {
|
|
||||||
contents.value = cloneDeep(DEFAULT_CONTENTS);
|
|
||||||
initialValue.value = '';
|
|
||||||
};
|
|
||||||
|
|
||||||
const initContentsQuery = () => {
|
|
||||||
contentsQuery.value = cloneDeep(DEFAULT_CONTENT_QUERY);
|
|
||||||
};
|
|
||||||
|
|
||||||
const searchContentList = async () => {
|
|
||||||
try {
|
|
||||||
const { data } = await useAxios().get(
|
|
||||||
'/api/admin/contents/contentsList',
|
|
||||||
{
|
|
||||||
params: {
|
|
||||||
...contentsQuery.value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
contentsList.value = data;
|
|
||||||
} catch (e) {
|
|
||||||
message.error('사이트 리스트를 불러오는데 실패하였습니다.');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const searchContents = async (contentId: number) => {
|
|
||||||
try {
|
|
||||||
const { data } = await useAxios().get('/api/admin/contents/detail', {
|
|
||||||
params: {
|
|
||||||
contentId
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
contents.value = data;
|
|
||||||
initialValue.value = data.contents;
|
|
||||||
} catch (e) {
|
|
||||||
message.error('컨텐츠 정보를 불러오는데 실패하였습니다.');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const updateContents = () => {
|
|
||||||
console.log(contents.value);
|
|
||||||
return useAxios().post(
|
|
||||||
'/api/admin/contents/updateContents',
|
|
||||||
contents.value
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const deleteContents = async (data: ContentType[]) => {
|
|
||||||
try {
|
|
||||||
const params = new URLSearchParams();
|
|
||||||
data.forEach((item) => {
|
|
||||||
params.append('contentId', String(item.contentId));
|
|
||||||
});
|
|
||||||
|
|
||||||
await useAxios().post('/api/admin/contents/deleteContents', null, {
|
|
||||||
params
|
|
||||||
});
|
|
||||||
message.success('컨텐츠 정보가 삭제 되었습니다.');
|
|
||||||
} catch (e) {
|
|
||||||
message.error('컨텐츠 정보 삭제에 실패하였습니다.');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return {
|
|
||||||
contentsQuery,
|
|
||||||
contentsList,
|
|
||||||
contents,
|
|
||||||
initialValue,
|
|
||||||
resetContentListQuery,
|
|
||||||
searchContentList,
|
|
||||||
searchContents,
|
|
||||||
resetContentList,
|
|
||||||
resetContents,
|
|
||||||
initContentsQuery,
|
|
||||||
deleteContents,
|
|
||||||
updateContents
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
@ -1,99 +0,0 @@
|
||||||
import type { SiteType } from '~/types/sys/site';
|
|
||||||
import type { GridCodeType } from '~/types';
|
|
||||||
import { defineStore } from 'pinia';
|
|
||||||
import { computed, ref } from 'vue';
|
|
||||||
import { useAxios } from '~/composables/useAxios';
|
|
||||||
|
|
||||||
export const useLoadingStore = defineStore('useLoadingStore', () => {
|
|
||||||
const loadCount = ref<number>(0);
|
|
||||||
|
|
||||||
const incrementLoadCount = () => {
|
|
||||||
loadCount.value++;
|
|
||||||
};
|
|
||||||
|
|
||||||
const decrementLoadCount = () => {
|
|
||||||
loadCount.value--;
|
|
||||||
};
|
|
||||||
|
|
||||||
const resetLoadCount = () => {
|
|
||||||
loadCount.value = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
const isLoading = computed(() => {
|
|
||||||
return loadCount.value > 0;
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
isLoading,
|
|
||||||
resetLoadCount,
|
|
||||||
incrementLoadCount,
|
|
||||||
decrementLoadCount
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
export const useDefaultStore = defineStore('useDefaultStore', () => {
|
|
||||||
const siteInfo = ref<SiteType>({
|
|
||||||
siteId: '',
|
|
||||||
siteName: '',
|
|
||||||
siteDescription: '',
|
|
||||||
siteDomain: '',
|
|
||||||
siteType: '',
|
|
||||||
sitePrefix: '',
|
|
||||||
siteLocale: '',
|
|
||||||
siteLogo: '',
|
|
||||||
bscUrl: '',
|
|
||||||
lgnUrl: '',
|
|
||||||
delYn: false,
|
|
||||||
useYn: true,
|
|
||||||
frstRgtrId: '',
|
|
||||||
frstRegDt: '',
|
|
||||||
lastMdfrId: '',
|
|
||||||
lastMdfcnDt: ''
|
|
||||||
});
|
|
||||||
|
|
||||||
const fetchSiteInfo = async () => {
|
|
||||||
const { data } = await useAxios().get<SiteType>('/api/admin/siteInfo');
|
|
||||||
siteInfo.value = data;
|
|
||||||
};
|
|
||||||
|
|
||||||
return { siteInfo, fetchSiteInfo };
|
|
||||||
});
|
|
||||||
|
|
||||||
export const useCommonCodeStore = defineStore('useCommonCodeStore', () => {
|
|
||||||
const searchCommonCodeList = async (
|
|
||||||
codeGroupId: string
|
|
||||||
): Promise<GridCodeType[]> => {
|
|
||||||
const { data } = await useAxios().get('/api/admin/code/codeList', {
|
|
||||||
params: {
|
|
||||||
codeGroupId
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return data;
|
|
||||||
};
|
|
||||||
|
|
||||||
const searchSiteCodeList = async (): Promise<GridCodeType[]> => {
|
|
||||||
const { data } = await useAxios().get('/api/admin/code/siteList');
|
|
||||||
return data;
|
|
||||||
};
|
|
||||||
|
|
||||||
const searchInstCodeList = async (): Promise<GridCodeType[]> => {
|
|
||||||
const { data } = await useAxios().get<GridCodeType[]>(
|
|
||||||
'/api/admin/code/instList'
|
|
||||||
);
|
|
||||||
return data;
|
|
||||||
};
|
|
||||||
|
|
||||||
const searchRoleCodeList = async (): Promise<GridCodeType[]> => {
|
|
||||||
const { data } = await useAxios().get<GridCodeType[]>(
|
|
||||||
'/api/admin/code/roleList'
|
|
||||||
);
|
|
||||||
return data;
|
|
||||||
};
|
|
||||||
|
|
||||||
return {
|
|
||||||
searchInstCodeList,
|
|
||||||
searchSiteCodeList,
|
|
||||||
searchCommonCodeList,
|
|
||||||
searchRoleCodeList
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
@ -1,10 +0,0 @@
|
||||||
export type Page<T> = {
|
|
||||||
content: T[];
|
|
||||||
totalElements: number;
|
|
||||||
totalPages: number;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type PagingQuery = {
|
|
||||||
page: number;
|
|
||||||
size: number;
|
|
||||||
};
|
|
||||||
|
|
@ -1,32 +0,0 @@
|
||||||
export type ContentListQueryType = {
|
|
||||||
page: number;
|
|
||||||
size: number;
|
|
||||||
siteId: string;
|
|
||||||
orgId: string;
|
|
||||||
keyword: string;
|
|
||||||
type: '' | 'TITLE' | 'CONTENT';
|
|
||||||
};
|
|
||||||
|
|
||||||
export type ContentListType = {
|
|
||||||
contentId: number;
|
|
||||||
contentTitle: string;
|
|
||||||
useYn: boolean;
|
|
||||||
frstRgtrId: string;
|
|
||||||
frstRegDt: string;
|
|
||||||
lastMdfrId: string;
|
|
||||||
lastMdfcnDt: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type ContentType = {
|
|
||||||
contentId?: number;
|
|
||||||
siteId: string;
|
|
||||||
orgId: string;
|
|
||||||
contentTitle: string;
|
|
||||||
contents: string;
|
|
||||||
contentPlain: string;
|
|
||||||
useYn: boolean;
|
|
||||||
frstRgtrId: string;
|
|
||||||
frstRegDt: string;
|
|
||||||
lastMdfrId: string;
|
|
||||||
lastMdfcnDt: string;
|
|
||||||
};
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
export type PaginationType = {
|
export type PaginationType = {
|
||||||
page: number;
|
totalItems: number;
|
||||||
size: number;
|
itemsPerPage: number;
|
||||||
totalElements: number;
|
visiblePages: number;
|
||||||
showPaginationCount: number;
|
centerAlign?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,20 +0,0 @@
|
||||||
export type PagingQueryType = {
|
|
||||||
page: number;
|
|
||||||
size: number;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type GridCodeType = {
|
|
||||||
label?: string;
|
|
||||||
text?: string;
|
|
||||||
value: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type FileInfoType = {
|
|
||||||
fileId: number;
|
|
||||||
fileOriginalName: string;
|
|
||||||
filePath: string;
|
|
||||||
fileMimeType: string;
|
|
||||||
fileSize: number;
|
|
||||||
fileAltText: string;
|
|
||||||
fileDownloadCount: number;
|
|
||||||
};
|
|
||||||
Loading…
Reference in New Issue