初始化admin pc端

This commit is contained in:
Mrtangl 2022-04-08 14:46:31 +08:00
parent 19665b64fb
commit 41ed86604f
6 changed files with 147 additions and 110 deletions

View File

@ -81,6 +81,7 @@ const tiny = reactive({
], //false
paste_data_images: true, //
file_picker_types: "file image media",
convert_urls : false, // false-
//
file_picker_callback: (callback: any, value: any, meta: any) => {
if (meta.filetype == "image") {

View File

@ -1,40 +1,54 @@
<template>
<div>
<del-wrap @close="$emit('close')">
<div class="file-item" :style="{ height: fileSize, width: fileSize }">
<el-image v-if="type == 'image'" class="image" fit="contain" :src="uri"></el-image>
<video v-else-if="type == 'video'" class="video" :src="uri"></video>
<div
class="file-item"
:style="{ height: fileSize, width: fileSize }"
>
<el-image
class="image"
v-if="type.type == 'image'"
fit="contain"
:src="uri"
></el-image>
<video
class="video"
v-else-if="type.type == 'video'"
:src="uri"
></video>
<slot></slot>
</div>
</del-wrap>
</div>
</template>
<script lang="ts">
import DelWrap from '@/components/del-wrap/index.vue'
import { defineComponent, inject } from 'vue'
export default defineComponent({
components: {
DelWrap
DelWrap,
},
props: {
//
uri: {
type: String
type: String,
},
//
fileSize: {
type: String,
default: '100px'
}
default: '100px',
},
},
emits: ['close'],
setup() {
const type = inject('type')
const type = inject<any>('type')
return {
type
}
}
},
})
</script>

View File

@ -5,24 +5,26 @@ import {
apiFileCateLists,
apiFileDelete,
apiFileList,
apiFileMove
} from '@/api/app'
import { usePages } from '@/core/hooks/pages'
import { ElMessage } from 'element-plus'
import { computed, inject, reactive, ref, Ref } from 'vue'
apiFileMove,
} from "@/api/app"
import { usePages } from "@/core/hooks/pages"
import { ElMessage } from "element-plus"
import { computed, inject, reactive, ref, Ref } from "vue"
// 左侧分组的钩子函数
export function useCate(typeValue: Ref<any>) {
// 分组列表
const cateLists: Ref<any[]> = ref([])
// 选中的分组id
const cateId = ref('')
const cateId = ref("")
// 添加分组
const handleAddCate = (val: string) => {
apiFileCateAdd({
type: typeValue.value,
pid: 0,
name: val
name: val,
}).then(() => {
getCateLists()
})
@ -31,7 +33,7 @@ export function useCate(typeValue: Ref<any>) {
const handleEditCate = (val: string, id: number) => {
apiFileCateEdit({
id,
name: val
name: val,
}).then(() => {
getCateLists()
})
@ -39,7 +41,7 @@ export function useCate(typeValue: Ref<any>) {
// 删除分组
const handleDeleteCate = (id: number) => {
apiFileCateDelete({
id
id,
}).then(() => {
getCateLists()
})
@ -49,17 +51,17 @@ export function useCate(typeValue: Ref<any>) {
return new Promise((resolve, reject) => {
apiFileCateLists({
type: typeValue.value,
page_type: 1
page_type: 1,
}).then((res: any) => {
const item: any[] = [
{
name: '全部',
id: ''
name: "全部",
id: "",
},
{
name: '未分组',
id: 0
}
name: "未分组",
id: 0,
},
]
cateLists.value = res?.lists
cateLists.value.unshift(...item)
@ -73,23 +75,25 @@ export function useCate(typeValue: Ref<any>) {
handleAddCate,
handleEditCate,
handleDeleteCate,
getCateLists
getCateLists,
}
}
// 处理文件的钩子函数
export function useFile(cateId: Ref<string>, type: Ref<any>, limit: Ref<number>) {
const moveId = ref(0)
const select: Ref<any[]> = ref([])
const fileParams = reactive({
name: '',
name: "",
type: type,
cid: cateId
cid: cateId,
})
const { pager, requestApi, resetPage } = usePages({
callback: apiFileList,
params: fileParams
})
const selectStatus = computed(
() => (id: number) => select.value.find((item: any) => item.id == id)
@ -102,20 +106,20 @@ export function useFile(cateId: Ref<string>, type: Ref<any>, limit: Ref<number>)
resetPage()
}
const batchFileDelete = (id?: number[]) => {
const ids = id ? id : select.value.map((item: any) => item.id)
let ids = id ? id : select.value.map((item: any) => item.id)
apiFileDelete({
ids
}).then(res => {
ids,
}).then((res) => {
getFileList()
clearSelect()
})
}
const batchFileMove = () => {
const ids = select.value.map((item: any) => item.id)
let ids = select.value.map((item: any) => item.id)
apiFileMove({
ids,
cid: moveId.value
}).then(res => {
cid: moveId.value,
}).then((res) => {
moveId.value = 0
getFileList()
clearSelect()
@ -123,7 +127,7 @@ export function useFile(cateId: Ref<string>, type: Ref<any>, limit: Ref<number>)
}
const selectFile = (item: any) => {
const index = select.value.findIndex((items: any) => items.id == item.id)
let index = select.value.findIndex((items: any) => items.id == item.id)
if (index != -1) {
select.value.splice(index, 1)
return
@ -134,7 +138,7 @@ export function useFile(cateId: Ref<string>, type: Ref<any>, limit: Ref<number>)
select.value.push(item)
return
}
ElMessage.warning('已达到选择上限')
ElMessage.warning("已达到选择上限")
return
}
select.value.push(item)
@ -143,7 +147,7 @@ export function useFile(cateId: Ref<string>, type: Ref<any>, limit: Ref<number>)
select.value = []
}
const cancelSelete = (id: number) => {
select.value = select.value.filter(item => item.id != id)
select.value = select.value.filter((item) => item.id != id)
}
return {
moveId,

View File

@ -1,3 +1,4 @@
<template>
<div class="material-select">
<popup
@ -7,41 +8,42 @@
:title="`选择${tipsText}`"
@confirm="handleConfirm"
>
<template #trigger>
<template v-if="!hiddenUpload" #trigger>
<div class="material-select__trigger clearfix" @click.stop>
<draggable v-model="fileList" class="draggable" animation="300" item-key="id">
<template #item="{ element, index }">
<draggable
class="draggable"
v-model="fileList"
animation="300"
item-key="id"
>
<template v-slot:item="{ element, index }">
<div
class="material-preview"
:class="{
'is-disabled': disabled,
'is-one': limit == 1
'is-one': limit == 1,
}"
@click="showPopup(index)"
>
<file-item
:uri="element"
:file-size="size"
@close="deleteImg(index)"
/>
<file-item :uri="element" :file-size="size" @close="deleteImg(index)" />
</div>
</template>
</draggable>
<div
v-show="showUpload"
class="material-upload"
@click="showPopup(-1)"
v-show="showUpload"
:class="{
'is-disabled': disabled,
'is-one': limit == 1
'is-one': limit == 1,
}"
@click="showPopup(-1)"
>
<slot name="upload">
<div
class="upload-btn flex flex-col flex-center"
:style="{
width: size,
height: size
height: size,
}"
>
<el-icon :size="25"><plus /></el-icon>
@ -63,6 +65,7 @@
</div>
</template>
<script lang="ts">
import {
provide,
@ -74,7 +77,7 @@ import {
toRef,
toRefs,
watch,
nextTick
nextTick,
} from 'vue'
import Draggable from 'vuedraggable'
import Popup from '@/components/popup/index.vue'
@ -85,37 +88,42 @@ export default defineComponent({
Popup,
Draggable,
FileItem,
Material
Material,
},
props: {
modelValue: {
type: [String, Array],
default: () => []
default: () => [],
},
//
type: {
type: String,
default: 'image'
default: 'image',
},
//
size: {
type: String,
default: '100px'
default: '100px',
},
//
fileSize: {
type: String,
default: '100px'
default: '100px',
},
//
limit: {
type: Number,
default: 1
// type: Number,
default: 1,
},
//
disabled: {
type: Boolean,
default: false
default: false,
},
// *(使)
hiddenUpload: {
type: Boolean,
default: false,
}
},
@ -149,28 +157,24 @@ export default defineComponent({
const showUpload = computed(() => {
return props.limit - fileList.value.length > 0
})
const meterialLimit = computed(() => {
const meterialLimit: any = computed(() => {
if (!isAdd.value) {
return 1
}
if (!limit.value) {
return null
}
if (!limit.value) return null
return limit.value - fileList.value.length
})
const handleConfirm = () => {
const selectUri = select.value.map(item => item.uri)
const selectUri = select.value.map((item) => item.uri)
if (!isAdd.value) {
fileList.value.splice(currentIndex.value, 1, selectUri.shift())
} else {
fileList.value = [...fileList.value, ...selectUri]
fileList.value = [...fileList.value,...selectUri]
}
handleChange()
}
const showPopup = (index: number) => {
if (disabled.value) {
return
}
if (disabled.value) return
if (index >= 0) {
isAdd.value = false
currentIndex.value = index
@ -184,7 +188,8 @@ export default defineComponent({
select.value = val
}
const handleChange = () => {
const valueImg = limit.value != 1 ? fileList.value : fileList.value[0] || ''
const valueImg =
limit.value != 1 ? fileList.value : fileList.value[0] || ''
emit('update:modelValue', valueImg)
emit('change', valueImg)
nextTick(() => {
@ -198,13 +203,13 @@ export default defineComponent({
}
watch(modelValue, (val: any[] | string) => {
console.log(val)
fileList.value = Array.isArray(val) ? val : val == '' ? [] : [val]
})
provide('type', props.type)
provide('type', props)
provide('fileSize', props.fileSize)
provide('limit', props.limit)
provide('typeValue', typeValue)
provide('hiddenUpload', props.hiddenUpload)
return {
popupRef,
materialRefs,
@ -217,7 +222,7 @@ export default defineComponent({
selectChange,
deleteImg
}
}
},
})
</script>

View File

@ -1,5 +1,6 @@
<template>
<div v-loading="pager.loading" class="material flex col-stretch">
<div class="material flex col-stretch" v-loading="pager.loading">
<div class="material__left">
<el-scrollbar class="ls-scrollbar" style="height: calc(100% - 40px)">
<div class="material-left__content p-t-16 p-b-16">
@ -14,16 +15,17 @@
:current-node-key="cateId"
@node-click="currentChange"
>
<template #default="{ data }">
<template v-slot="{ data }">
<div class="flex flex-1 flex-center" style="min-width: 0">
<img
style="width: 20px; height: 16px"
src="@/assets/images/icon_folder.png"
alt
class="m-r-10"
/>
<span class="flex-1 line-1 m-r-10">
{{ data.name }}
{{
data.name
}}
</span>
<el-dropdown v-if="data.id > 0" :hide-on-click="false">
<span class="muted m-r-10">···</span>
@ -33,12 +35,21 @@
<popover-input
type="text"
tips="分类名称"
@confirm="handleEditCate($event, data.id)"
@confirm="
handleEditCate(
$event,
data.id
)
"
>
<el-dropdown-item>命名分组</el-dropdown-item>
</popover-input>
</div>
<div @click="handleDeleteCate(data.id)">
<div
@click="
handleDeleteCate(data.id)
"
>
<el-dropdown-item>删除分组</el-dropdown-item>
</div>
</el-dropdown-menu>
@ -61,7 +72,7 @@
<upload
class="m-r-10"
:data="{ cid: cateId }"
:type="type"
:type="type.type"
:show-progress="true"
@change="refresh"
>
@ -79,9 +90,9 @@
</popup>
<popup
class="m-r-10 inline"
@confirm="batchFileMove"
:disabled="!select.length"
title="移动文件"
@confirm="batchFileMove"
>
<template #trigger>
<el-button size="small" :disabled="!select.length">移动</el-button>
@ -102,10 +113,10 @@
</popup>
</div>
<el-input
v-model="fileParams.name"
size="small"
placeholder="请输入名字"
style="width: 280px"
v-model="fileParams.name"
@keyup.enter="refresh"
>
<template #append>
@ -116,9 +127,9 @@
<div class="material-center__content flex flex-col flex-1">
<ul class="file-list flex flex-wrap m-t-14">
<li
class="file-item-wrap"
v-for="item in pager.lists"
:key="item.id"
class="file-item-wrap"
:style="{ width: fileSize }"
@click="selectFile(item)"
>
@ -127,7 +138,7 @@
:file-size="fileSize"
@close="batchFileDelete([item.id])"
>
<div v-if="selectStatus(item.id)" class="item-selected">
<div class="item-selected" v-if="selectStatus(item.id)">
<el-icon color="#fff" size="24">
<check />
</el-icon>
@ -138,17 +149,15 @@
</li>
</ul>
<div
v-if="!pager.loading && !pager.lists.length"
class="flex flex-1 row-center col-center"
>
暂无数据~
</div>
v-if="!pager.loading && !pager.lists.length"
>暂无数据~</div>
</div>
<div class="material-center__footer flex row-right">
<pagination
v-model="pager"
layout="total, prev, pager, next, jumper"
@change="getFileList"
layout="total, prev, pager, next, jumper"
/>
</div>
</div>
@ -163,13 +172,9 @@
<el-scrollbar class="ls-scrollbar" style="height: calc(100% - 32px)">
<ul class="select-lists flex-col p-t-10">
<li v-for="item in select" :key="item.id" class="m-b-16">
<li class="m-b-16" v-for="item in select" :key="item.id">
<div class="select-item">
<file-item
:uri="item.uri"
file-size="100px"
@close="cancelSelete(item.id)"
></file-item>
<file-item :uri="item.uri" file-size="100px" @close="cancelSelete(item.id)"></file-item>
</div>
</li>
</ul>
@ -178,6 +183,7 @@
</div>
</template>
<script lang="ts">
import { defineComponent, inject, Ref, ref, toRefs, watch } from 'vue'
import { useCate, useFile } from './hook'
@ -194,27 +200,33 @@ export default defineComponent({
Pagination,
Popup,
Upload,
FileItem
FileItem,
},
props: {
fileSize: {
type: String,
default: '100px'
default: '100px',
},
limit: {
type: Number,
default: 1
}
default: 1,
},
},
emits: ['change'],
setup(props, { emit }) {
const treeRefs: Ref<typeof ElTree | null> = ref(null)
const type = inject('type') as Ref<string>
const type = inject('type') as Ref<any>
const { limit } = toRefs(props)
const typeValue = inject('typeValue') as Ref<10 | 20 | 30>
const visible = inject('visible') as Ref<boolean>
const { cateId, cateLists, handleAddCate, handleEditCate, handleDeleteCate, getCateLists } =
useCate(typeValue)
const {
cateId,
cateLists,
handleAddCate,
handleEditCate,
handleDeleteCate,
getCateLists,
} = useCate(typeValue)
const {
moveId,
pager,
@ -227,7 +239,7 @@ export default defineComponent({
selectFile,
selectStatus,
clearSelect,
cancelSelete
cancelSelete,
} = useFile(cateId, typeValue, limit)
const currentChange = (item: any) => {
@ -244,7 +256,7 @@ export default defineComponent({
}
},
{
immediate: true
immediate: true,
}
)
watch(cateId, (val: string) => {
@ -282,9 +294,9 @@ export default defineComponent({
selectFile,
selectStatus,
clearSelect,
cancelSelete
cancelSelete,
}
}
},
})
</script>

View File

@ -56,12 +56,13 @@
<div
v-for="item in workbenchData.menu"
:key="item"
class="nav-item flex flex-col flex-center m-t-10"
class="nav-item flex-col m-t-10"
>
<router-link :to="item.url">
<el-image style="width: 48px; height: 48px" :src="item.image">
</el-image>
<div class="m-t-8 normal">{{ item.name }}</div>
<view class="flex flex-center">
<el-image style="width: 48px; height: 48px" :src="item?.image"></el-image>
</view>
<div class="m-t-8 normal text-center">{{ item.name }}</div>
</router-link>
</div>
</div>
@ -233,10 +234,10 @@ export default defineComponent({
.function {
.nav-lists {
display: flex;
flex-wrap: wrap;
// flex-wrap: wrap;
.nav-item {
min-width: 120px;
min-width: 210px;
}
}
}