优化素材中心

This commit is contained in:
xiangheng
2024-02-21 19:27:18 +08:00
parent 1dc7f7542a
commit aa2ecf115b
13 changed files with 215 additions and 249 deletions

View File

@@ -1,66 +1,124 @@
<!DOCTYPE html>
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>后台管理系统</title>
<style>
* {
margin: 0;
padding: 0;
}
.preload {
display: flex;
align-items: center;
justify-content: center;
height: 100vh;
width: 100vw;
}
.circular {
height: 42px;
width: 42px;
animation: loading-rotate 2s linear infinite;
}
.circular .path {
animation: loading-dash 1.5s ease-in-out infinite;
stroke-dasharray: 90, 150;
stroke-dashoffset: 0;
stroke-width: 2;
stroke: #4073fa;
stroke-linecap: round;
}
@keyframes loading-rotate {
100% {
transform: rotate(1turn);
}
}
@keyframes loading-dash {
0% {
stroke-dasharray: 90, 150;
stroke-dashoffset: -40px;
}
100% {
stroke-dasharray: 90, 150;
stroke-dashoffset: -120px;
}
}
</style>
</head>
<body>
<div id="app">
<div class="preload">
<svg viewBox="25 25 50 50" class="circular">
<circle cx="50" cy="50" r="20" fill="none" class="path"></circle>
</svg>
</div>
</div>
<script type="module" src="/src/main.ts"></script>
</body>
<head>
<meta charset="UTF-8" />
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>x_admin管理系统</title>
<meta name="description" content="后台管理系统" />
<meta name="keywords" content="x_admin,后台管理系统" />
<style>
* {
margin: 0;
padding: 0;
}
.preload {
display: flex;
align-items: center;
justify-content: center;
height: 100vh;
width: 100vw;
}
.circular {
height: 42px;
width: 42px;
animation: loading-rotate 2s linear infinite;
}
.circular .path {
animation: loading-dash 1.5s ease-in-out infinite;
stroke-dasharray: 90, 150;
stroke-dashoffset: 0;
stroke-width: 2;
stroke: #4073fa;
stroke-linecap: round;
}
@keyframes loading-rotate {
100% {
transform: rotate(1turn);
}
}
@keyframes loading-dash {
0% {
stroke-dasharray: 90, 150;
stroke-dashoffset: -40px;
}
100% {
stroke-dasharray: 90, 150;
stroke-dashoffset: -120px;
}
}
</style>
</head>
<body>
<div id="app">
<div class="preload">
<svg viewBox="25 25 50 50" class="circular">
<circle cx="50" cy="50" r="20" fill="none" class="path"></circle>
</svg>
</div>
</div>
<!-- 异常收集 -->
<script>
!(function (c, i, e, b) {
var h = i.createElement('script')
var f = i.getElementsByTagName('script')[0]
h.type = 'text/javascript'
h.crossorigin = true
h.onload = function () {
new c[b]['Monitor']().init({
id: '3HYtHZVKJQxGvKyR',
sendSuspicious: true,
sendSpaPv: true
})
}
f.parentNode.insertBefore(h, f)
h.src = e
})(window, document, 'https://sdk.51.la/perf/js-sdk-perf.min.js', 'LingQue')
</script>
<!-- 网站统计 -->
<script>
!(function (p) {
'use strict'
!(function (t) {
var s = window,
e = document,
i = p,
c = ''.concat(
'https:' === e.location.protocol ? 'https://' : 'http://',
'sdk.51.la/js-sdk-pro.min.js'
),
n = e.createElement('script'),
r = e.getElementsByTagName('script')[0]
;(n.type = 'text/javascript'),
n.setAttribute('charset', 'UTF-8'),
(n.async = !0),
(n.src = c),
(n.id = 'LA_COLLECT'),
(i.d = n)
var o = function () {
s.LA.ids.push(i)
}
s.LA ? s.LA.ids && o() : ((s.LA = p), (s.LA.ids = []), o()),
r.parentNode.insertBefore(n, r)
})()
})({ id: '3HYtjw7cm3a6D52W', ck: '3HYtjw7cm3a6D52W', autoTrack: true, hashMode: true })
</script>
<script type="module" src="/src/main.ts"></script>
<!-- 百度统计 -->
<!-- <script>
var _hmt = _hmt || []
;(function () {
var hm = document.createElement('script')
hm.src = 'https://hm.baidu.com/hm.js?9ce7f08804f25b8da927f382b23cf456'
var s = document.getElementsByTagName('script')[0]
s.parentNode.insertBefore(hm, s)
})()
</script> -->
</body>
</html>

View File

@@ -1,7 +1,13 @@
<template>
<div>
<div class="file-item relative" :style="{ height: fileSize, width: fileSize }">
<el-image class="image" v-if="type == 'image'" fit="contain" :src="uri"></el-image>
<el-image
class="image"
v-if="type == 'image'"
fit="contain"
loading="lazy"
:src="uri"
></el-image>
<video class="video" v-else-if="type == 'video'" :src="uri"></video>
<div
v-if="type == 'video'"

View File

@@ -20,7 +20,7 @@ export function useCate(type: number) {
const cateLists = ref<any[]>([])
// 选中的分组id
const cateId = ref<number | string>('')
const cateId = ref<number | string>(0)
// 获取分组列表
const getCateLists = async () => {
@@ -28,10 +28,10 @@ export function useCate(type: number) {
type
})
const item: any[] = [
// {
// name: '全部',
// id: ''
// },
{
name: '全部',
id: 0
}
// {
// name: '未分组',
// id: 0
@@ -96,7 +96,6 @@ export function useFile(
size: number
) {
const tableRef = shallowRef()
const listShowType = ref('normal')
const moveId = ref(0)
const select = ref<any[]>([])
const isCheckAll = ref(false)
@@ -120,10 +119,6 @@ export function useFile(
resetPage()
}
const isSelect = (id: number) => {
return !!select.value.find((item: any) => item.id == id)
}
const batchFileDelete = async (id?: number[]) => {
await feedback.confirm(
'确认删除后,本地或云存储文件也将同步删除,如文件已被使用,请谨慎操作!'
@@ -167,7 +162,9 @@ export function useFile(
const cancelSelete = (id: number) => {
select.value = select.value.filter((item: any) => item.id != id)
}
const selectItems = (items: any[]) => {
select.value = items
}
const selectAll = (value: CheckboxValueType) => {
isIndeterminate.value = false
tableRef.value?.toggleAllSelection()
@@ -186,7 +183,6 @@ export function useFile(
getFileList()
}
return {
listShowType,
tableRef,
moveId,
pager,
@@ -199,10 +195,10 @@ export function useFile(
batchFileDelete,
batchFileMove,
selectFile,
isSelect,
clearSelect,
cancelSelete,
selectAll,
selectItems,
handleFileRename
}
}

View File

@@ -106,40 +106,6 @@
>
<el-button type="primary">本地上传</el-button>
</upload>
<el-button
v-perms="['admin:common:album:albumDel']"
v-if="mode == 'page'"
:disabled="!select.length"
@click.stop="batchFileDelete()"
>
删除
</el-button>
<popup
v-perms="['admin:common:album:albumMove']"
v-if="mode == 'page'"
class="ml-3"
@confirm="batchFileMove"
:disabled="!select.length"
title="移动文件"
>
<template #trigger>
<el-button :disabled="!select.length">移动</el-button>
</template>
<div>
<span class="mr-5">移动文件至</span>
<el-select v-model="moveId" placeholder="请选择">
<template v-for="item in cateLists" :key="item.id">
<el-option
v-if="item.id !== ''"
:label="item.name"
:value="item.id"
></el-option>
</template>
</el-select>
</div>
</popup>
</div>
<el-input
class="w-60"
@@ -155,100 +121,19 @@
</el-button>
</template>
</el-input>
<div class="flex items-center ml-2">
<el-tooltip content="列表视图" placement="top">
<div
class="list-icon"
:class="{
select: listShowType == 'table'
}"
@click="listShowType = 'table'"
>
<icon name="local-icon-list-2" :size="18" />
</div>
</el-tooltip>
<el-tooltip content="平铺视图" placement="top">
<div
class="list-icon"
:class="{
select: listShowType == 'normal'
}"
@click="listShowType = 'normal'"
>
<icon name="el-icon-Menu" :size="18" />
</div>
</el-tooltip>
</div>
</div>
<div class="mt-3" v-if="mode == 'page'">
<el-checkbox
:disabled="!pager.lists.length"
v-model="isCheckAll"
@change="selectAll"
:indeterminate="isIndeterminate"
>
当页全选
</el-checkbox>
</div>
<div class="material-center__content flex flex-col flex-1 mb-1 min-h-0">
<el-scrollbar v-if="pager.lists.length" v-show="listShowType == 'normal'">
<ul class="file-list flex flex-wrap mt-4">
<li
class="file-item-wrap"
v-for="item in pager.lists"
:key="item.id"
:style="{ width: fileSize }"
>
<del-wrap @close="batchFileDelete([item.id])">
<file-item
:uri="item.uri"
:file-size="fileSize"
:type="type"
@click="selectFile(item)"
>
<div class="item-selected" v-if="isSelect(item.id)">
<icon :size="24" name="el-icon-Check" color="#fff" />
</div>
</file-item>
</del-wrap>
<overflow-tooltip class="mt-1" :content="item.name" />
<div class="operation-btns flex items-center">
<popover-input
v-perms="['admin:common:album:albumRename']"
@confirm="handleFileRename($event, item.id)"
size="default"
:value="item.name"
width="400px"
:limit="50"
show-limit
teleported
>
<el-button type="primary" link> 重命名 </el-button>
</popover-input>
<el-button type="primary" link @click="handlePreview(item.uri)">
查看
</el-button>
</div>
</li>
</ul>
</el-scrollbar>
<el-table
ref="tableRef"
class="mt-4"
v-show="listShowType == 'table'"
:data="pager.lists"
width="100%"
height="100%"
size="large"
@row-click="selectFile"
@selection-change="handleSelectionChange"
>
<el-table-column width="55">
<template #default="{ row }">
<el-checkbox :modelValue="isSelect(row.id)" @change="selectFile(row)" />
</template>
</el-table-column>
<el-table-column type="selection" width="55" />
<el-table-column label="图片" width="100">
<template #default="{ row }">
<file-item :uri="row.uri" file-size="50px" :type="type"></file-item>
@@ -305,7 +190,7 @@
<div class="material-center__footer flex justify-between items-center mt-2">
<div class="flex">
<template v-if="mode == 'page'">
<span class="mr-3">
<!-- <span class="mr-3">
<el-checkbox
:disabled="!pager.lists.length"
v-model="isCheckAll"
@@ -314,7 +199,7 @@
>
当页全选
</el-checkbox>
</span>
</span> -->
<el-button
v-perms="['admin:common:album:albumDel']"
:disabled="!select.length"
@@ -333,18 +218,15 @@
<el-button :disabled="!select.length">移动</el-button>
</template>
<div>
<span class="mr-5">移动文件至</span>
<el-select v-model="moveId" placeholder="请选择">
<template v-for="item in cateLists" :key="item.id">
<el-option
v-if="item.id !== ''"
:label="item.name"
:value="item.id"
></el-option>
</template>
</el-select>
</div>
<el-select v-model="moveId" placeholder="请选择">
<template v-for="item in cateLists" :key="item.id">
<el-option
v-if="item.id !== ''"
:label="item.name"
:value="item.id"
></el-option>
</template>
</el-select>
</popup>
</template>
</div>
@@ -389,7 +271,6 @@
import { useCate, useFile } from './hook'
import FileItem from './file.vue'
import Preview from './preview.vue'
import type { Ref } from 'vue'
const props = defineProps({
fileSize: {
type: String,
@@ -442,7 +323,6 @@ const {
const {
tableRef,
listShowType,
moveId,
pager,
fileParams,
@@ -453,14 +333,18 @@ const {
refresh,
batchFileDelete,
batchFileMove,
selectFile,
isSelect,
clearSelect,
cancelSelete,
selectAll,
selectItems,
handleFileRename
} = useFile(cateId, typeValue, limit, props.pageSize)
function handleSelectionChange(val: any[]) {
console.log('handleSelectionChange', val)
selectItems(val)
// multipleSelection.value = val
}
const getData = async () => {
await getCateLists()
treeRef.value?.setCurrentKey(cateId.value)
@@ -519,9 +403,16 @@ defineExpose({
<style scoped lang="scss">
.material {
@apply h-full min-h-0 flex flex-1;
height: 100%;
min-height: 0px;
display: flex;
flex: 1 1 0%;
&__left {
@apply border-r border-br flex flex-col w-[200px];
border-right-width: 1px;
border-color: var(--el-border-color);
display: flex;
flex-direction: column;
width: 200px;
:deep(.el-tree-node__content) {
height: 36px;
}
@@ -537,7 +428,8 @@ defineExpose({
padding: 5px;
cursor: pointer;
&.select {
@apply text-primary bg-primary-light-8;
color: var(--el-color-primary);
background-color: var(--el-color-primary-light-8);
}
}
.file-list {
@@ -569,7 +461,10 @@ defineExpose({
}
}
&__right {
@apply border-l border-br flex flex-col;
border-left-width: 1px;
border-color: var(--el-border-color);
display: flex;
flex-direction: column;
width: 130px;
.select-lists {
padding: 10px;

View File

@@ -10,6 +10,7 @@
:center="center"
:append-to-body="true"
:width="width"
draggable
:close-on-click-modal="clickModalClose"
@closed="close"
>

View File

@@ -64,6 +64,7 @@ export class Feedback {
// 确认窗体
confirm(msg: string) {
return ElMessageBox.confirm(msg, '温馨提示', {
draggable: true,
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
@@ -72,6 +73,7 @@ export class Feedback {
// 提交内容
prompt(content: string, title: string, options?: ElMessageBoxOptions) {
return ElMessageBox.prompt(content, title, {
draggable: true,
confirmButtonText: '确定',
cancelButtonText: '取消',
...options

View File

@@ -8,13 +8,13 @@
<!-- <el-form-item label="申请人id" prop="applyUserId">
<el-input v-model="queryParams.applyUserId" />
</el-form-item> -->
<el-form-item label="申请人" prop="applyUserNickname">
<el-form-item label="申请人" prop="applyUserNickname" class="w-[280px]">
<el-input v-model="queryParams.applyUserNickname" />
</el-form-item>
<el-form-item label="流程名称" prop="flowName">
<el-form-item label="流程名称" prop="flowName" class="w-[280px]">
<el-input v-model="queryParams.flowName" />
</el-form-item>
<el-form-item label="流程分类" prop="flowGroup">
<el-form-item label="流程分类" prop="flowGroup" class="w-[280px]">
<el-select v-model="queryParams.flowGroup" clearable>
<el-option label="全部" value="" />
<el-option

View File

@@ -11,10 +11,10 @@
<el-form-item label="申请人昵称" prop="applyUserNickname">
<el-input v-model="queryParams.applyUserNickname" />
</el-form-item> -->
<el-form-item label="流程名称" prop="flowName">
<el-form-item label="流程名称" prop="flowName" class="w-[280px]">
<el-input v-model="queryParams.flowName" />
</el-form-item>
<el-form-item label="流程分类" prop="flowGroup">
<el-form-item label="流程分类" prop="flowGroup" class="w-[280px]">
<el-select v-model="queryParams.flowGroup" clearable>
<el-option label="全部" value="" />
<el-option
@@ -28,7 +28,7 @@
<!-- <el-form-item label="流程描述" prop="flowRemark">
<el-input v-model="queryParams.flowRemark" />
</el-form-item> -->
<el-form-item label="状态" prop="status">
<el-form-item label="状态" prop="status" class="w-[280px]">
<el-select v-model="queryParams.status" clearable>
<el-option label="全部" value="" />
<el-option

View File

@@ -6,7 +6,15 @@
<el-input v-model="queryParams.flowName" />
</el-form-item>
<el-form-item class="w-[280px]" label="流程分类" prop="flowGroup">
<el-input v-model="queryParams.flowGroup" />
<el-select v-model="queryParams.flowGroup" clearable>
<el-option label="全部" value="" />
<el-option
v-for="(item, index) in dictData.flow_group"
:key="index"
:label="item.name"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item class="w-[280px]" label="流程描述" prop="flowRemark">
<el-input v-model="queryParams.flowRemark" />

View File

@@ -15,7 +15,7 @@
mode="page"
file-size="120px"
:limit="-1"
:page-size="20"
:page-size="10"
/>
</el-tab-pane>
</el-tabs>
@@ -24,6 +24,7 @@
</template>
<script lang="ts" setup>
import material from '@/components/material/index.vue'
defineOptions({
name: 'materialCenter'
})

View File

@@ -1,7 +1,6 @@
<!-- 系统日志 -->
<template>
<div class="journal">
{{ formData }}
<el-card class="!border-none" shadow="never">
<el-form class="ls-form" :model="formData" inline>
<el-form-item label="管理员" class="w-[360px]">

View File

@@ -8,15 +8,15 @@ type CommonUploadImageReq struct {
//CommonAlbumListReq 相册文件列表参数
type CommonAlbumListReq struct {
Cid int `form:"cid,default=-1"` // 类目ID
Type int `form:"type" binding:"omitempty,oneof=10 20"` // 文件类型: [10=图片, 20=视频]
Name string `form:"keyword"` // 文件名称
Cid int `form:"cid,default=-1"` // 类目ID
Type int `form:"type" binding:"omitempty,oneof=10 20 30"` // 文件类型: [10=图片, 20=视频]
Name string `form:"name"` // 文件名称
}
//CommonAlbumRenameReq 相册文件重命名参数
type CommonAlbumRenameReq struct {
ID uint `form:"id" binding:"required,gt=0"` // 主键
Name string `form:"keyword" binding:"required,min=1,max=30"` // 文件名称
ID uint `form:"id" binding:"required,gt=0"` // 主键
Name string `form:"name" binding:"required,min=1,max=30"` // 文件名称
}
//CommonAlbumMoveReq 相册文件移动参数
@@ -27,14 +27,14 @@ type CommonAlbumMoveReq struct {
//CommonAlbumAddReq 相册文件新增参数
type CommonAlbumAddReq struct {
Cid uint `form:"cid" binding:"gte=0"` // 类目ID
Aid uint `form:"aid" binding:"gte=0"` // 管理ID
Uid uint `form:"uid" binding:"gte=0"` // 用户ID
Type int `form:"type" binding:"oneof=10 20"` // 文件类型: [10=图片, 20=视频]
Name string `form:"name"` // 文件名称
Uri string `form:"uri"` // 文件路径
Ext string `form:"ext"` // 文件扩展
Size int64 `form:"size"` // 文件大小
Cid uint `form:"cid" binding:"gte=0"` // 类目ID
Aid uint `form:"aid" binding:"gte=0"` // 管理ID
Uid uint `form:"uid" binding:"gte=0"` // 用户ID
Type int `form:"type" binding:"oneof=10 20 30"` // 文件类型: [10=图片, 20=视频,30文件]
Name string `form:"name"` // 文件名称
Uri string `form:"uri"` // 文件路径
Ext string `form:"ext"` // 文件扩展
Size int64 `form:"size"` // 文件大小
}
//CommonAlbumDelReq 相册文件删除参数
@@ -44,21 +44,21 @@ type CommonAlbumDelReq struct {
//CommonCateListReq 相册分类列表参数
type CommonCateListReq struct {
Type int `form:"type" binding:"omitempty,oneof=10 20 30"` // 分类类型: [10=图片,20=视频]
Name string `form:"keyword"` // 分类名称
Type int `form:"type" binding:"omitempty,oneof=10 20 30"` // 分类类型: [10=图片,20=视频,30文件]
Name string `form:"name"` // 分类名称
}
//CommonCateAddReq 相册分类新增参数
type CommonCateAddReq struct {
Pid uint `form:"pid" binding:"gte=0"` // 父级ID
Type int `form:"type" binding:"required,oneof=10 20 30"` // 分类类型: [10=图片,20=视频]
Type int `form:"type" binding:"required,oneof=10 20 30"` // 分类类型: [10=图片,20=视频,30文件]
Name string `form:"name" binding:"required,min=1,max=30"` // 分类名称
}
//CommonCateRenameReq 相册分类重命名参数
type CommonCateRenameReq struct {
ID uint `form:"id" binding:"required,gt=0"` // 主键
Name string `form:"keyword" binding:"required,min=1,max=30"` // 分类名称
ID uint `form:"id" binding:"required,gt=0"` // 主键
Name string `form:"name" binding:"required,min=1,max=30"` // 分类名称
}
//CommonCateDelReq 相册分类删除参数

View File

@@ -78,10 +78,10 @@ func initServer(router *gin.Engine) *http.Server {
// @title x_admin文档
// @version 0.0.1
// @description x_admin是一个完整的后台管理系统
// @termsOfService http://likeadmin.adtk.cn
// @termsOfService http://x.adtk.cn
// @contact.name API Support
// @contact.url http://likeadmin.adtk.cn
// @contact.url http://x.adtk.cn
// @contact.email 11675084@qq.com
// @license.name MIT License