Compare commits

..

No commits in common. "2ad995d565ed96884e3c69ea8acdef1dcd1767d6" and "c1a5340a73f77bd95284476d78da2b1d5a003af2" have entirely different histories.

3 changed files with 328 additions and 372 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

View File

@ -1,420 +1,376 @@
<template> <template>
<doc-alert title="上传下载" url="https://doc.iocoder.cn/file/" /> <doc-alert title="上传下载" url="https://doc.iocoder.cn/file/" />
<div class="flex-container"> <div class="flex-container">
<!-- 菜单区域 --> <!-- 菜单区域 -->
<div class="menu-area"> <div class="menu-area">
<el-button type="primary" plain @click="createType" style="width: 90;font-size: 12px;"> <el-button type="primary" plain @click="createType" style="width: 90;font-size: 12px;">
<Icon icon="ep:plus" class="mr-5px" /> 新增分类 <Icon icon="ep:plus" class="mr-5px" /> 新增分类
</el-button> </el-button>
<el-menu :default-active="targetMenuId" style="width:182px"> <el-menu :default-active="targetMenuId" style="width:182px">
<el-menu-item :index="targetMenuId" :key="targetMenuId" @click="clickMenu(targetMenuId)"> <el-menu-item :index="targetMenuId" :key="targetMenuId" @click="clickMenu(targetMenuId)">
全部类型 全部类型
</el-menu-item> </el-menu-item>
<el-menu-item v-for="item in typeMenu" :index="item.value" :key="item.value" <el-menu-item v-for="item in typeMenu" :index="item.value" :key="item.value"
@click="clickMenu(item.value)"> @click="clickMenu(item.value)">
{{ item.label }} {{ item.label }}
<el-icon style="margin-left: 60px;width: 10px;" @mouseover="showActions = item.value" <el-icon style="margin-left: 60px;width: 10px;" @mouseover="showActions = item.value"
@mouseleave="showActions = null"> @mouseleave="showActions = null">
<MoreFilled /> <MoreFilled />
<div v-if="showActions === item.value" class="action-buttons"> <div v-if="showActions === item.value" class="action-buttons">
<el-button size="small" @click.stop="editItem(item.id,item.label)">编辑</el-button> <el-button size="small" @click.stop="editItem(item.id,item.label)">编辑</el-button>
<br /> <br />
<el-button size="small" @click.stop="deleteItem(item.id)">删除</el-button> <el-button size="small" @click.stop="deleteItem(item.id)">删除</el-button>
</div> </div>
</el-icon> </el-icon>
</el-menu-item> </el-menu-item>
</el-menu> </el-menu>
</div> </div>
<!-- 内容区域 --> <!-- 内容区域 -->
<div class="content-wrap"> <div class="content-wrap">
<ContentWrap> <ContentWrap>
<el-form class="-mb-15px" :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px"> <el-form class="-mb-15px" :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px">
<el-form-item label="文件类型" prop="type" width="80"> <!-- <el-form-item label="文件路径" prop="path">
<el-input v-model="queryParams.type" placeholder="请输入文件类型" clearable <el-input
@keyup.enter="handleQuery" /> v-model="queryParams.path"
</el-form-item> placeholder="请输入文件路径"
clearable
@keyup.enter="handleQuery"
/>
</el-form-item> -->
<el-form-item label="文件类型" prop="type" width="80">
<el-input v-model="queryParams.type" placeholder="请输入文件类型" clearable
@keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="创建时间" prop="createTime"> <el-form-item label="创建时间" prop="createTime">
<el-date-picker v-model="queryParams.createTime" value-format="YYYY-MM-DD HH:mm:ss" <el-date-picker v-model="queryParams.createTime" value-format="YYYY-MM-DD HH:mm:ss"
type="daterange" start-placeholder="开始日期" end-placeholder="结束日期" type="daterange" start-placeholder="开始日期" end-placeholder="结束日期"
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]" /> :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]" />
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button @click="handleQuery"> <el-button @click="handleQuery">
<Icon icon="ep:search" class="mr-5px" /> 搜索 <Icon icon="ep:search" class="mr-5px" /> 搜索
</el-button> </el-button>
<el-button @click="resetQuery"> <el-button @click="resetQuery">
<Icon icon="ep:refresh" class="mr-5px" /> 重置 <Icon icon="ep:refresh" class="mr-5px" /> 重置
</el-button> </el-button>
<el-button type="primary" plain @click="openForm"> <el-button type="primary" plain @click="openForm">
<Icon icon="ep:upload" class="mr-5px" /> 上传文件 <Icon icon="ep:upload" class="mr-5px" /> 上传文件
</el-button> </el-button>
</el-form-item> </el-form-item>
<span><img @click="liebiao" style="cursor: pointer;" class="mr-10px h-30px w-30px" src="@/assets/imgs/liebiao.png" /></span> </el-form>
<span><img @click="tubiao" style="cursor: pointer;" class="mr-10px h-30px w-30px" src="@/assets/imgs/tubiao.png" /></span> </ContentWrap>
</el-form>
</ContentWrap>
<ContentWrap>
<el-table v-loading="loading" :data="list">
<el-table-column label="文件内容" align="center" prop="url" width="110px">
<template #default="{ row }">
<el-image v-if="row.type.includes('image')" class="h-80px w-80px" lazy :src="row.url"
:preview-src-list="[row.url]" preview-teleported fit="cover" />
<el-link v-else-if="row.type.includes('pdf')" type="primary" :href="row.url"
:underline="false" target="_blank">预览</el-link>
<el-link v-else type="primary" download :href="row.url" :underline="false"
target="_blank">下载</el-link>
</template>
</el-table-column>
<el-table-column label="文件名" align="center" prop="name" :show-overflow-tooltip="true" />
<!-- <el-table-column label="文件路径" align="center" prop="path" :show-overflow-tooltip="true" /> -->
<el-table-column label="URL" align="center" prop="url" :show-overflow-tooltip="true" />
<!-- <el-table-column label="文件大小" align="center" prop="size" width="120"
:formatter="fileSizeFormatter" /> -->
<!-- <el-table-column label="文件类型" align="center" prop="type" width="180px" />
<el-table-column label="图片分类" align="center" prop="picType">
<template #default="scope">
<dict-tag :type="DICT_TYPE.INFRA_FILE_TYPE" :value="scope.row.picType" />
</template>
</el-table-column> -->
<el-table v-loading="loading" :data="list" v-show="panduan == '1'"> <el-table-column label="上传时间" align="center" prop="createTime" width="180"
<el-table-column label="文件内容" align="center" prop="url" width="110px"> :formatter="dateFormatter" />
<template #default="{ row }"> <el-table-column label="操作" align="center">
<el-image v-if="row.type.includes('image')" class="h-80px w-80px" lazy :src="row.url" <template #default="scope">
:preview-src-list="[row.url]" preview-teleported fit="cover" /> <el-button link type="primary"
<el-link v-else-if="row.type.includes('pdf')" type="primary" :href="row.url" @click="updateForm('update', scope.row.id , scope.row.picType)">
:underline="false" target="_blank">预览</el-link> 更改类型
<el-link v-else type="primary" download :href="row.url" :underline="false" </el-button>
target="_blank">下载</el-link> <el-button link type="danger" @click="handleDelete(scope.row.id)"
</template> v-hasPermi="['infra:file:delete']">
</el-table-column> 删除
<el-table-column label="文件名" align="center" prop="name" :show-overflow-tooltip="true" /> </el-button>
<!-- <el-table-column label="文件路径" align="center" prop="path" :show-overflow-tooltip="true" /> --> </template>
<el-table-column label="URL" align="center" prop="url" :show-overflow-tooltip="true" /> </el-table-column>
</el-table>
</ContentWrap>
<!-- 分页 -->
<Pagination :total="total" v-model:page="queryParams.pageNo" v-model:limit="queryParams.pageSize"
@pagination="getList" />
<el-table-column label="上传时间" align="center" prop="createTime" width="180" </div>
:formatter="dateFormatter" /> </div>
<el-table-column label="操作" align="center"> <!-- 表单弹窗添加/修改 -->
<template #default="scope"> <FileForm ref="formRef" @success="getList" />
<el-button link type="primary"
@click="updateForm('update', scope.row.id , scope.row.picType)">
更改类型
</el-button>
<el-button link type="danger" @click="handleDelete(scope.row.id)"
v-hasPermi="['infra:file:delete']">
删除
</el-button>
</template>
</el-table-column>
</el-table>
<div v-show="panduan == '2'"> <UpdateForm ref="forRef" @success="getList" />
<!-- 图片展示区域 -->
<div class="image-container">
<div v-for="item in tubiaoData" :key="item.id" class="image-item">
<img :src="item.url" alt="图表" />
</div>
</div>
</div>
<Dialog v-model="dialogVisibles" :title="dialogTitles">
<el-form ref="formRef" v-loading="formLoading" :model="formData" :rules="formRules" label-width="80px">
<el-form-item label="数据标签" prop="label">
<el-input v-model="formData.label" placeholder="请输入数据标签" />
</el-form-item>
<el-form-item label="显示排序" prop="sort">
<el-input-number v-model="formData.sort" :min="0" controls-position="right" />
</el-form-item>
<!-- 分页 --> </el-form>
<Pagination :total="total" v-model:page="queryParams.pageNo" v-model:limit="queryParams.pageSize" <template #footer>
@pagination="getList" /> <el-button :disabled="formLoading" type="primary" @click="submitForm"> </el-button>
<el-button @click="dialogVisibles = false"> </el-button>
</template>
</Dialog>
</div> <Dialog v-model="dialogVisible" :title="dialogTitle">
</div> <el-form ref="formRef" v-loading="formLoading" :model="formData" label-width="80px">
<!-- 表单弹窗添加/修改 --> <el-form-item label="数据标签" prop="label">
<FileForm ref="formRef" @success="getList" /> <el-input v-model="updateLabel" placeholder="请输入数据标签" />
</el-form-item>
<UpdateForm ref="forRef" @success="getList" /> </el-form>
<template #footer>
<Dialog v-model="dialogVisibles" :title="dialogTitles"> <el-button :disabled="formLoading" type="primary" @click="submitForms"> </el-button>
<el-form ref="formRef" v-loading="formLoading" :model="formData" :rules="formRules" label-width="80px"> <el-button @click="dialogVisible = false"> </el-button>
</template>
<el-form-item label="数据标签" prop="label"> </Dialog>
<el-input v-model="formData.label" placeholder="请输入数据标签" />
</el-form-item>
<el-form-item label="显示排序" prop="sort">
<el-input-number v-model="formData.sort" :min="0" controls-position="right" />
</el-form-item>
</el-form>
<template #footer>
<el-button :disabled="formLoading" type="primary" @click="submitForm"> </el-button>
<el-button @click="dialogVisibles = false"> </el-button>
</template>
</Dialog>
<Dialog v-model="dialogVisible" :title="dialogTitle">
<el-form ref="formRef" v-loading="formLoading" :model="formData" label-width="80px">
<el-form-item label="数据标签" prop="label">
<el-input v-model="updateLabel" placeholder="请输入数据标签" />
</el-form-item>
</el-form>
<template #footer>
<el-button :disabled="formLoading" type="primary" @click="submitForms"> </el-button>
<el-button @click="dialogVisible = false"> </el-button>
</template>
</Dialog>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { getIntDictOptions, DICT_TYPE } from '@/utils/dict' import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
import { fileSizeFormatter } from '@/utils' import { fileSizeFormatter } from '@/utils'
import { Search, MoreFilled } from '@element-plus/icons-vue'; import { Search, MoreFilled } from '@element-plus/icons-vue';
import { dateFormatter } from '@/utils/formatTime' import { dateFormatter } from '@/utils/formatTime'
// import * as ElementPlusIconsVue from '@element-plus/icons-vue' // import * as ElementPlusIconsVue from '@element-plus/icons-vue'
import * as FileApi from '@/api/infra/file' import * as FileApi from '@/api/infra/file'
import FileForm from './FileForm.vue' import FileForm from './FileForm.vue'
import UpdateForm from './updateForm.vue' import UpdateForm from './updateForm.vue'
import * as DictDataApi from '@/api/system/dict/dict.data' import * as DictDataApi from '@/api/system/dict/dict.data'
const typeMenu = ref<DictDataApi.DictDataVO[]>([]) // const typeMenu = ref<DictDataApi.DictDataVO[]>([]) //
const targetMenuId = ref('0') const targetMenuId = ref('0')
defineOptions({ name: 'InfraFile' }) defineOptions({ name: 'InfraFile' })
const showActions = ref(null); const showActions = ref(null);
const dialogVisible = ref(false) // const dialogVisible = ref(false) //
const dialogTitle = ref('') // const dialogTitle = ref('') //
const dialogVisibles = ref(false) // const dialogVisibles = ref(false) //
const dialogTitles = ref('') // const dialogTitles = ref('') //
const formLoading = ref(false) // 12 const formLoading = ref(false) // 12
const panduan = ref('1') const formData = ref({
const tubiaoData = ref<FileDataVO[]>([]); id: undefined,
const formData = ref({ sort: undefined,
id: undefined, label: '',
sort: undefined, value: '',
label: '', dictType: '',
value: '', // status: CommonStatusEnum.ENABLE,
dictType: '', colorType: '',
// status: CommonStatusEnum.ENABLE, cssClass: '',
colorType: '', remark: ''
cssClass: '', })
remark: '' const formRules = reactive({
}) label: [{ required: true, message: '数据标签不能为空', trigger: 'blur' }],
const formRules = reactive({ sort: [{ required: true, message: '数据顺序不能为空', trigger: 'blur' }],
label: [{ required: true, message: '数据标签不能为空', trigger: 'blur' }], })
sort: [{ required: true, message: '数据顺序不能为空', trigger: 'blur' }], const updateLabel = ref('')
}) const message = useMessage() //
const updateLabel = ref('') const { t } = useI18n() //
const message = useMessage() //
const { t } = useI18n() //
const loading = ref(true) // const loading = ref(true) //
const total = ref(0) // const total = ref(0) //
const list = ref([]) // const list = ref([]) //
const menuId = ref() const menuId = ref()
const queryParams = reactive({ const queryParams = reactive({
pageNo: 1, pageNo: 1,
pageSize: 10, pageSize: 10,
name: undefined, name: undefined,
type: undefined, type: undefined,
picType: '', picType: '',
path: undefined, path: undefined,
createTime: [], createTime: [],
}) })
const queryFormRef = ref() // const queryFormRef = ref() //
/** 查询列表 */ /** 查询列表 */
const getList = async () => { const getList = async () => {
loading.value = true loading.value = true
try { try {
const data = await FileApi.getFilePage(queryParams) const data = await FileApi.getFilePage(queryParams)
list.value = data.list list.value = data.list
tubiaoData.value = data.list total.value = data.total
console.log('111111',tubiaoData) } finally {
total.value = data.total loading.value = false
} finally { }
loading.value = false }
}
}
interface FileDataVO {
id: string
configId: string
path: string
name: string
url: string
type: string
picType: string
size: string
createTime: Date
}
const tubiao = () => { //
panduan.value = '2' const createType = () => {
} dialogVisibles.value = true
dialogTitles.value = '新增分类'
const liebiao = () => { }
panduan.value = '1'
}
// /** 添加分类菜单 */
const createType = () => { const emit = defineEmits(['success']) // success
dialogVisibles.value = true const submitForm = async () => {
dialogTitles.value = '新增分类' //
} if (!formRef) return
const valid = await formRef.value.validate()
if (!valid) return
//
formLoading.value = true
try {
const data = formData.value as DictDataApi.DictDataVO
await DictDataApi.createPicType(data)
message.success(t('common.createSuccess'))
dialogVisibles.value = false
//
emit('success')
getTypeList()
/** 添加分类菜单 */ } finally {
const emit = defineEmits(['success']) // success formLoading.value = false
const submitForm = async () => { }
// }
if (!formRef) return
const valid = await formRef.value.validate()
if (!valid) return
//
formLoading.value = true
try {
const data = formData.value as DictDataApi.DictDataVO
await DictDataApi.createPicType(data)
message.success(t('common.createSuccess'))
dialogVisibles.value = false
//
emit('success')
getTypeList()
} finally { //
formLoading.value = false const submitForms = async () => {
} //
} if (!formRef) return
const valid = await formRef.value.validate()
if (!valid) return
//
formLoading.value = true
try {
// await DictDataApi.updateMenu(menuId.value, updateLabel.value)
const submitForms = async () => { message.success(t('common.createSuccess'))
// dialogVisible.value = false
if (!formRef) return //
const valid = await formRef.value.validate() emit('success')
if (!valid) return getTypeList()
//
formLoading.value = true
try {
await DictDataApi.updateMenu(menuId.value, updateLabel.value) } finally {
message.success(t('common.createSuccess')) formLoading.value = false
dialogVisible.value = false }
// }
emit('success')
getTypeList()
} finally { //
formLoading.value = false const editItem = (id : number | undefined, lable : string) => {
} dialogVisible.value = true
} dialogTitle.value = '菜单编辑'
menuId.value = id
updateLabel.value = lable
//
console.log('编辑:',);
};
//
const deleteItem = async (id : number | undefined) => {
//
//
await message.delConfirm()
await DictDataApi.deleteMenu(id)
message.success(t('common.delSuccess'))
getTypeList()
// };
const editItem = (id : number | undefined, lable : string) => { //
dialogVisible.value = true const getTypeList = async () => {
dialogTitle.value = '菜单编辑' const data = await DictDataApi.getTypeList()
menuId.value = id typeMenu.value = data
updateLabel.value = lable console.log('1111111111', typeMenu)
// }
console.log('编辑:',);
};
//
const deleteItem = async (id : number | undefined) => {
//
//
await message.delConfirm()
await DictDataApi.deleteMenu(id)
message.success(t('common.delSuccess'))
getTypeList()
};
//
const getTypeList = async () => {
const data = await DictDataApi.getTypeList()
typeMenu.value = data
}
/** */ /** */
const clickMenu = (id : string) => { const clickMenu = (id : string) => {
queryParams.picType = id queryParams.picType = id
queryParams.pageNo = 1 queryParams.pageNo = 1
getList() getList()
} }
/** 搜索按钮操作 */ /** 搜索按钮操作 */
const handleQuery = () => { const handleQuery = () => {
queryParams.pageNo = 1 queryParams.pageNo = 1
getList() getList()
} }
/** 重置按钮操作 */ /** 重置按钮操作 */
const resetQuery = () => { const resetQuery = () => {
queryFormRef.value.resetFields() queryFormRef.value.resetFields()
handleQuery() handleQuery()
} }
const formRef = ref() const formRef = ref()
const openForm = () => { const openForm = () => {
formRef.value.open() formRef.value.open()
} }
const forRef = ref() const forRef = ref()
/** 修改操作 */ /** 修改操作 */
const updateForm = (type : string, id : number, picType : number) => { const updateForm = (type : string, id : number, picType : number) => {
forRef.value.open(type, id, picType) forRef.value.open(type, id, picType)
} }
/** 删除按钮操作 */ /** 删除按钮操作 */
const handleDelete = async (id : number) => { const handleDelete = async (id : number) => {
try { try {
// //
await message.delConfirm() await message.delConfirm()
// //
await FileApi.deleteFile(id) await FileApi.deleteFile(id)
message.success(t('common.delSuccess')) message.success(t('common.delSuccess'))
// //
await getList() await getList()
} catch { } } catch { }
} }
/** 初始化 **/ /** 初始化 **/
onMounted(() => { onMounted(() => {
queryParams.picType = targetMenuId.value queryParams.picType = targetMenuId.value
getTypeList() getTypeList()
getList() getList()
}) })
</script> </script>
<style scoped> <style scoped>
.flex-container { .flex-container {
height: 100vh; height: 100vh;
/* 使容器填满视口高度 */ /* 使容器填满视口高度 */
display: flex; display: flex;
} }
.menu-area { .menu-area {
padding: 25px; padding: 25px;
background-color: white; background-color: white;
width: 180px; width: 180px;
height: 1000px; height: 1000px;
/* 固定高度 */ /* 固定高度 */
overflow-y: hidden; overflow-y: hidden;
/* 禁止滚动 */ /* 禁止滚动 */
border-right: 1px solid #e0e0e0; border-right: 1px solid #e0e0e0;
/* 可选:添加分隔线 */ /* 可选:添加分隔线 */
} }
.content-wrap { .content-wrap {
flex-grow: 1; flex-grow: 1;
/* 使内容区域占据剩余空间 */ /* 使内容区域占据剩余空间 */
overflow-y: auto; overflow-y: auto;
/* 允许内容区域滚动 */ /* 允许内容区域滚动 */
} }
</style>
/* 图片容器样式 */
.image-container {
display: flex;
flex-wrap: wrap;
gap: 10px; /* 设置图片之间的间距 */
justify-content: flex-start; /* 如果图片少于5张会平均分布 */
max-width: 1000px; /* 设置外部容器的最大宽度 */
margin: 0 auto; /* 居中显示 */
}
/* 每张图片占用的宽度使每行显示5张 */
.image-item {
width: calc(20% - 8px); /* 宽度设为容器的20%,减去间距 */
}
/* 设置图片的最大宽度 */
.image-item img {
width: 100%;
height: auto;
border-radius: 8px; /* 图片边缘圆角(可选) */
}
</style>