parent
d95ad35903
commit
8c5129f63a
|
|
@ -12,11 +12,14 @@ module.exports = {
|
|||
extends: ['plugin:vue/recommended', 'eslint:recommended'],
|
||||
rules: {
|
||||
'vue/no-v-model-argument': 0,
|
||||
'vue/max-attributes-per-line': 2,
|
||||
'vue/max-attributes-per-line': 0,
|
||||
'vue/first-attribute-linebreak': 'off',
|
||||
'vue/singleline-html-element-content-newline': 'off',
|
||||
'vue/multiline-html-element-content-newline': 'off',
|
||||
'vue/multi-word-component-names': 'off',
|
||||
'vue/html-closing-bracket-newline': 'off',
|
||||
'vue/no-v-html': 'off',
|
||||
'vue/html-indent': 'off',
|
||||
'accessor-pairs': 2,
|
||||
'arrow-spacing': [
|
||||
2,
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import service from '@/utils/request'
|
|||
|
||||
export const findFile = (params) => {
|
||||
return service({
|
||||
url: '/fileUploadAndDownload/findFile',
|
||||
url: '/mediaFile/findFile',
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
|
|
@ -17,7 +17,7 @@ export const findFile = (params) => {
|
|||
|
||||
export const breakpointContinue = (data) => {
|
||||
return service({
|
||||
url: '/fileUploadAndDownload/breakpointContinue',
|
||||
url: '/mediaFile/breakpointContinue',
|
||||
method: 'post',
|
||||
donNotShowLoading: true,
|
||||
headers: { 'Content-Type': 'multipart/form-data' },
|
||||
|
|
@ -27,7 +27,7 @@ export const breakpointContinue = (data) => {
|
|||
|
||||
export const breakpointContinueFinish = (params) => {
|
||||
return service({
|
||||
url: '/fileUploadAndDownload/breakpointContinueFinish',
|
||||
url: '/mediaFile/breakpointContinueFinish',
|
||||
method: 'post',
|
||||
params
|
||||
})
|
||||
|
|
@ -35,7 +35,7 @@ export const breakpointContinueFinish = (params) => {
|
|||
|
||||
export const removeChunk = (data, params) => {
|
||||
return service({
|
||||
url: '/fileUploadAndDownload/removeChunk',
|
||||
url: '/mediaFile/removeChunk',
|
||||
method: 'post',
|
||||
data,
|
||||
params
|
||||
|
|
|
|||
|
|
@ -0,0 +1,63 @@
|
|||
import service from '@/utils/request'
|
||||
|
||||
// @Summary 获取栏目树
|
||||
// @Produce application/json
|
||||
// @Router /channel/getChannelTree [post]
|
||||
export const getChannelTree = () => {
|
||||
return service({
|
||||
url: '/channel/getChannelTree',
|
||||
method: 'post',
|
||||
})
|
||||
}
|
||||
|
||||
// @Summary 新增栏目
|
||||
// @Produce application/json
|
||||
// @Param menu Object
|
||||
// @Router /channel/addChannel [post]
|
||||
export const addChannel = (data) => {
|
||||
return service({
|
||||
url: '/channel/addChannel',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// @Summary 删除栏目
|
||||
// @Produce application/json
|
||||
// @Param ID int
|
||||
// @Router /channel/deleteChannel [post]
|
||||
export const deleteChannel = (data) => {
|
||||
return service({
|
||||
url: '/channel/deleteChannel',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// @Summary 修改栏目
|
||||
// @Produce application/json
|
||||
// @Param menu Object
|
||||
// @Router /channel/updateChannel [post]
|
||||
export const updateChannel = (data) => {
|
||||
return service({
|
||||
url: '/channel/updateChannel',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// @Tags 文章栏目
|
||||
// @Summary 根据id获取栏目
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body api.GetById true "根据id获取栏目"
|
||||
// @Success 200 {string} json "{"success":true,"data":{},"msg":"获取成功"}"
|
||||
// @Router /channel/getChannelById [post]
|
||||
export const getChannelById = (data) => {
|
||||
return service({
|
||||
url: '/channel/getChannelById',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
import service from '@/utils/request'
|
||||
// @Tags MediaFile
|
||||
// @Summary 分页文件列表
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body modelInterface.PageInfo true "分页获取文件户列表"
|
||||
// @Success 200 {string} json "{"success":true,"data":{},"msg":"获取成功"}"
|
||||
// @Router /mediaFile/getFileList [post]
|
||||
export const getFileList = (data) => {
|
||||
return service({
|
||||
url: '/mediaFile/getFileList',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// @Tags MediaFile
|
||||
// @Summary 删除文件
|
||||
// @Security ApiKeyAuth
|
||||
// @Produce application/json
|
||||
// @Param data body dbModel.MediaFile true "传入文件里面id即可"
|
||||
// @Success 200 {string} json "{"success":true,"data":{},"msg":"返回成功"}"
|
||||
// @Router /mediaFile/deleteFile [post]
|
||||
export const deleteFile = (data) => {
|
||||
return service({
|
||||
url: '/mediaFile/deleteFile',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑文件名或者备注
|
||||
* @param data
|
||||
* @returns {*}
|
||||
*/
|
||||
export const editFileName = (data) => {
|
||||
return service({
|
||||
url: '/mediaFile/editFileName',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
|
@ -1,59 +1,24 @@
|
|||
<template>
|
||||
<el-drawer
|
||||
v-model="drawer"
|
||||
title="媒体库"
|
||||
size="650px"
|
||||
>
|
||||
<warning-bar
|
||||
title="点击“文件名/备注”可以编辑文件名或者备注内容。"
|
||||
/>
|
||||
<el-drawer v-model="drawer" title="媒体库" size="650px">
|
||||
<warning-bar title="点击“文件名/备注”可以编辑文件名或者备注内容。" />
|
||||
<div class="gva-btn-list">
|
||||
<upload-common
|
||||
:image-common="imageCommon"
|
||||
class="upload-btn-media-library"
|
||||
@on-success="open"
|
||||
/>
|
||||
<upload-image
|
||||
:image-url="imageUrl"
|
||||
:file-size="512"
|
||||
:max-w-h="1080"
|
||||
class="upload-btn-media-library"
|
||||
@on-success="open"
|
||||
/>
|
||||
<el-form
|
||||
ref="searchForm"
|
||||
:inline="true"
|
||||
:model="search"
|
||||
>
|
||||
<upload-common :image-common="imageCommon" class="upload-btn-media-library" @on-success="open" />
|
||||
<upload-image :image-url="imageUrl" :file-size="512" :max-w-h="1080" class="upload-btn-media-library"
|
||||
@on-success="open" />
|
||||
<el-form ref="searchForm" :inline="true" :model="search">
|
||||
<el-form-item label="">
|
||||
<el-input
|
||||
v-model="search.keyword"
|
||||
class="keyword"
|
||||
placeholder="请输入文件名或备注"
|
||||
/>
|
||||
<el-input v-model="search.keyword" class="keyword" placeholder="请输入文件名或备注" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item>
|
||||
<el-button
|
||||
type="primary"
|
||||
icon="search"
|
||||
@click="open"
|
||||
>查询</el-button>
|
||||
<el-button type="primary" icon="search" @click="open">查询</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<div class="media">
|
||||
<div
|
||||
v-for="(item,key) in picList"
|
||||
:key="key"
|
||||
class="media-box"
|
||||
>
|
||||
<div v-for="(item, key) in picList" :key="key" class="media-box">
|
||||
<div class="header-img-box-list">
|
||||
<el-image
|
||||
:key="key"
|
||||
:src="getUrl(item.url)"
|
||||
@click="chooseImg(item.url,target,targetKey)"
|
||||
>
|
||||
<el-image :key="key" :src="getUrl(item.url)" @click="chooseImg(item.url, target, targetKey)">
|
||||
<template #error>
|
||||
<div class="header-img-box-list">
|
||||
<el-icon>
|
||||
|
|
@ -63,28 +28,18 @@
|
|||
</template>
|
||||
</el-image>
|
||||
</div>
|
||||
<div
|
||||
class="img-title"
|
||||
@click="editFileNameFunc(item)"
|
||||
>{{ item.name }}</div>
|
||||
<div class="img-title" @click="editFileNameFunc(item)">{{ item.name }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<el-pagination
|
||||
:current-page="page"
|
||||
:page-size="pageSize"
|
||||
:total="total"
|
||||
:style="{'justify-content':'center'}"
|
||||
layout="total, prev, pager, next, jumper"
|
||||
@current-change="handleCurrentChange"
|
||||
@size-change="handleSizeChange"
|
||||
/>
|
||||
<el-pagination :current-page="page" :page-size="pageSize" :total="total" :style="{ 'justify-content': 'center' }"
|
||||
layout="total, prev, pager, next, jumper" @current-change="handleCurrentChange" @size-change="handleSizeChange" />
|
||||
</el-drawer>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { getUrl } from '@/utils/image'
|
||||
import { ref } from 'vue'
|
||||
import { getFileList, editFileName } from '@/api/fileUploadAndDownload'
|
||||
import { getFileList, editFileName } from '@/api/mediaFile'
|
||||
import UploadImage from '@/components/upload/image.vue'
|
||||
import UploadCommon from '@/components/upload/common.vue'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
|
|
@ -208,6 +163,7 @@ defineExpose({ open })
|
|||
line-height: 120px;
|
||||
cursor: pointer;
|
||||
overflow: hidden;
|
||||
|
||||
.el-image__inner {
|
||||
max-width: 120px;
|
||||
max-height: 120px;
|
||||
|
|
@ -218,5 +174,4 @@ defineExpose({ open })
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,19 +1,8 @@
|
|||
<template>
|
||||
<div class="border border-solid border-gray-100 h-full">
|
||||
<Toolbar
|
||||
:editor="editorRef"
|
||||
:default-config="toolbarConfig"
|
||||
mode="default"
|
||||
/>
|
||||
<Editor
|
||||
v-model="valueHtml"
|
||||
class="overflow-y-hidden mt-0.5"
|
||||
style="height: 18rem;"
|
||||
:default-config="editorConfig"
|
||||
mode="default"
|
||||
@onCreated="handleCreated"
|
||||
@onChange="change"
|
||||
/>
|
||||
<Toolbar :editor="editorRef" :default-config="toolbarConfig" mode="default" />
|
||||
<Editor v-model="valueHtml" class="overflow-y-hidden mt-0.5" style="height: 18rem;" :default-config="editorConfig"
|
||||
mode="default" @onCreated="handleCreated" @onChange="change" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
@ -56,7 +45,7 @@ const editorConfig = {
|
|||
}
|
||||
editorConfig.MENU_CONF['uploadImage'] = {
|
||||
fieldName: 'file',
|
||||
server: basePath + '/fileUploadAndDownload/upload?noSave=1',
|
||||
server: basePath + '/mediaFile/upload?noSave=1',
|
||||
customInsert(res, insertFn) {
|
||||
if (res.code === 0) {
|
||||
const urlPath = getUrl(res.data.file.url)
|
||||
|
|
@ -85,6 +74,4 @@ watch(() => props.modelValue, () => {
|
|||
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
</style>
|
||||
<style scoped lang="scss"></style>
|
||||
|
|
|
|||
|
|
@ -1,16 +1,8 @@
|
|||
<template>
|
||||
<div>
|
||||
<el-upload
|
||||
multiple
|
||||
:action="`${path}/fileUploadAndDownload/upload?noSave=1`"
|
||||
:on-error="uploadError"
|
||||
:on-success="uploadSuccess"
|
||||
:show-file-list="true"
|
||||
:file-list="fileList"
|
||||
:limit="limit"
|
||||
:accept="accept"
|
||||
class="upload-btn"
|
||||
>
|
||||
<el-upload multiple :action="`${path}/mediaFile/upload?noSave=1`" :on-error="uploadError"
|
||||
:on-success="uploadSuccess" :show-file-list="true" :file-list="fileList" :limit="limit" :accept="accept"
|
||||
class="upload-btn">
|
||||
<el-button type="primary">上传文件</el-button>
|
||||
</el-upload>
|
||||
</div>
|
||||
|
|
@ -82,4 +74,3 @@ const uploadError = () => {
|
|||
}
|
||||
|
||||
</script>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,184 +1,85 @@
|
|||
<template>
|
||||
<div>
|
||||
<div
|
||||
v-if="!multiple"
|
||||
class="update-image"
|
||||
:style="{
|
||||
<div v-if="!multiple" class="update-image" :style="{
|
||||
'background-image': `url(${getUrl(model)})`,
|
||||
'position': 'relative',
|
||||
}"
|
||||
>
|
||||
<el-icon
|
||||
v-if="isVideoExt(model || '')"
|
||||
:size="32"
|
||||
class="video video-icon"
|
||||
style=""
|
||||
>
|
||||
}">
|
||||
<el-icon v-if="isVideoExt(model || '')" :size="32" class="video video-icon" style="">
|
||||
<VideoPlay />
|
||||
</el-icon>
|
||||
<video
|
||||
v-if="isVideoExt(model || '')"
|
||||
class="avatar video-avatar video"
|
||||
muted
|
||||
preload="metadata"
|
||||
style=""
|
||||
@click="openChooseImg"
|
||||
>
|
||||
<video v-if="isVideoExt(model || '')" class="avatar video-avatar video" muted preload="metadata" style=""
|
||||
@click="openChooseImg">
|
||||
<source :src="getUrl(model) + '#t=1'">
|
||||
</video>
|
||||
<span
|
||||
v-if="model"
|
||||
class="update"
|
||||
style="position: absolute;"
|
||||
@click="openChooseImg"
|
||||
>
|
||||
<span v-if="model" class="update" style="position: absolute;" @click="openChooseImg">
|
||||
<el-icon>
|
||||
<delete />
|
||||
</el-icon>
|
||||
删除</span>
|
||||
<span
|
||||
v-else
|
||||
class="update text-gray-600"
|
||||
@click="openChooseImg"
|
||||
>
|
||||
<span v-else class="update text-gray-600" @click="openChooseImg">
|
||||
<el-icon>
|
||||
<plus />
|
||||
</el-icon>
|
||||
上传</span>
|
||||
</div>
|
||||
<div
|
||||
v-else
|
||||
class="multiple-img"
|
||||
>
|
||||
<div
|
||||
v-for="(item, index) in multipleValue"
|
||||
:key="index"
|
||||
class="update-image"
|
||||
:style="{
|
||||
<div v-else class="multiple-img">
|
||||
<div v-for="(item, index) in multipleValue" :key="index" class="update-image" :style="{
|
||||
'background-image': `url(${getUrl(item)})`,
|
||||
'position': 'relative',
|
||||
}"
|
||||
>
|
||||
<el-icon
|
||||
v-if="isVideoExt(item || '')"
|
||||
:size="32"
|
||||
class="video video-icon"
|
||||
>
|
||||
}">
|
||||
<el-icon v-if="isVideoExt(item || '')" :size="32" class="video video-icon">
|
||||
<VideoPlay />
|
||||
</el-icon>
|
||||
<video
|
||||
v-if="isVideoExt(item || '')"
|
||||
class="avatar video-avatar video"
|
||||
muted
|
||||
preload="metadata"
|
||||
@click="deleteImg(index)"
|
||||
>
|
||||
<video v-if="isVideoExt(item || '')" class="avatar video-avatar video" muted preload="metadata"
|
||||
@click="deleteImg(index)">
|
||||
<source :src="getUrl(item) + '#t=1'">
|
||||
</video>
|
||||
<span
|
||||
class="update"
|
||||
style="position: absolute;"
|
||||
@click="deleteImg(index)"
|
||||
>
|
||||
<span class="update" style="position: absolute;" @click="deleteImg(index)">
|
||||
<el-icon>
|
||||
<delete />
|
||||
</el-icon>
|
||||
删除</span>
|
||||
</div>
|
||||
<div
|
||||
v-if="!maxUpdateCount || maxUpdateCount>multipleValue.length"
|
||||
class="add-image"
|
||||
>
|
||||
<span
|
||||
class="update text-gray-600"
|
||||
@click="openChooseImg"
|
||||
>
|
||||
<div v-if="!maxUpdateCount || maxUpdateCount > multipleValue.length" class="add-image">
|
||||
<span class="update text-gray-600" @click="openChooseImg">
|
||||
<el-icon>
|
||||
<Plus />
|
||||
</el-icon>
|
||||
上传</span>
|
||||
</div>
|
||||
</div>
|
||||
<el-drawer
|
||||
v-model="drawer"
|
||||
title="媒体库"
|
||||
size="650px"
|
||||
>
|
||||
<warning-bar
|
||||
title="点击“文件名/备注”可以编辑文件名或者备注内容。"
|
||||
/>
|
||||
<el-drawer v-model="drawer" title="媒体库" size="650px">
|
||||
<warning-bar title="点击“文件名/备注”可以编辑文件名或者备注内容。" />
|
||||
<div class="gva-btn-list">
|
||||
<upload-common
|
||||
:image-common="imageCommon"
|
||||
class="upload-btn-media-library"
|
||||
@on-success="getImageList"
|
||||
/>
|
||||
<upload-image
|
||||
:image-url="imageUrl"
|
||||
:file-size="512"
|
||||
:max-w-h="1080"
|
||||
class="upload-btn-media-library"
|
||||
@on-success="getImageList"
|
||||
/>
|
||||
<el-form
|
||||
ref="searchForm"
|
||||
:inline="true"
|
||||
:model="search"
|
||||
>
|
||||
<upload-common :image-common="imageCommon" class="upload-btn-media-library" @on-success="getImageList" />
|
||||
<upload-image :image-url="imageUrl" :file-size="512" :max-w-h="1080" class="upload-btn-media-library"
|
||||
@on-success="getImageList" />
|
||||
<el-form ref="searchForm" :inline="true" :model="search">
|
||||
<el-form-item label="">
|
||||
<el-input
|
||||
v-model="search.keyword"
|
||||
class="keyword"
|
||||
placeholder="请输入文件名或备注"
|
||||
/>
|
||||
<el-input v-model="search.keyword" class="keyword" placeholder="请输入文件名或备注" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item>
|
||||
<el-button
|
||||
type="primary"
|
||||
icon="search"
|
||||
@click="getImageList"
|
||||
>查询
|
||||
<el-button type="primary" icon="search" @click="getImageList">查询
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<div class="media">
|
||||
<div
|
||||
v-for="(item,key) in picList"
|
||||
:key="key"
|
||||
class="media-box"
|
||||
>
|
||||
<div v-for="(item, key) in picList" :key="key" class="media-box">
|
||||
<div class="header-img-box-list">
|
||||
<el-image
|
||||
:key="key"
|
||||
:src="getUrl(item.url)"
|
||||
fit="cover"
|
||||
style="width: 100%;height: 100%;"
|
||||
@click="chooseImg(item.url)"
|
||||
>
|
||||
<el-image :key="key" :src="getUrl(item.url)" fit="cover" style="width: 100%;height: 100%;"
|
||||
@click="chooseImg(item.url)">
|
||||
<template #error>
|
||||
<el-icon
|
||||
v-if="isVideoExt(item.url || '')"
|
||||
:size="32"
|
||||
class="video video-icon"
|
||||
>
|
||||
<el-icon v-if="isVideoExt(item.url || '')" :size="32" class="video video-icon">
|
||||
<VideoPlay />
|
||||
</el-icon>
|
||||
<video
|
||||
v-if="isVideoExt(item.url || '')"
|
||||
class="avatar video-avatar video"
|
||||
muted
|
||||
preload="metadata"
|
||||
@click="chooseImg(item.url)"
|
||||
>
|
||||
<video v-if="isVideoExt(item.url || '')" class="avatar video-avatar video" muted preload="metadata"
|
||||
@click="chooseImg(item.url)">
|
||||
<source :src="getUrl(item.url) + '#t=1'">
|
||||
您的浏览器不支持视频播放
|
||||
</video>
|
||||
<div
|
||||
v-else
|
||||
class="header-img-box-list"
|
||||
>
|
||||
<div v-else class="header-img-box-list">
|
||||
<el-icon class="lost-image">
|
||||
<icon-picture />
|
||||
</el-icon>
|
||||
|
|
@ -186,22 +87,13 @@
|
|||
</template>
|
||||
</el-image>
|
||||
</div>
|
||||
<div
|
||||
class="img-title"
|
||||
@click="editFileNameFunc(item)"
|
||||
>{{ item.name }}
|
||||
<div class="img-title" @click="editFileNameFunc(item)">{{ item.name }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<el-pagination
|
||||
:current-page="page"
|
||||
:page-size="pageSize"
|
||||
:total="total"
|
||||
:style="{'justify-content':'center'}"
|
||||
layout="total, prev, pager, next, jumper"
|
||||
@current-change="handleCurrentChange"
|
||||
@size-change="handleSizeChange"
|
||||
/>
|
||||
<el-pagination :current-page="page" :page-size="pageSize" :total="total" :style="{ 'justify-content': 'center' }"
|
||||
layout="total, prev, pager, next, jumper" @current-change="handleCurrentChange"
|
||||
@size-change="handleSizeChange" />
|
||||
</el-drawer>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -210,7 +102,7 @@
|
|||
|
||||
import { getUrl, isVideoExt } from '@/utils/image'
|
||||
import { onMounted, ref } from 'vue'
|
||||
import { getFileList, editFileName } from '@/api/fileUploadAndDownload'
|
||||
import { getFileList, editFileName } from '@/api/mediaFile'
|
||||
import UploadImage from '@/components/upload/image.vue'
|
||||
import UploadCommon from '@/components/upload/common.vue'
|
||||
import WarningBar from '@/components/warningBar/warningBar.vue'
|
||||
|
|
@ -346,7 +238,6 @@ const getImageList = async() => {
|
|||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
.multiple-img {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
|
|
@ -381,16 +272,12 @@ const getImageList = async() => {
|
|||
|
||||
&:hover {
|
||||
color: #fff;
|
||||
background: linear-gradient(
|
||||
to bottom,
|
||||
background: linear-gradient(to bottom,
|
||||
rgba(255, 255, 255, 0.15) 0%,
|
||||
rgba(0, 0, 0, 0.15) 100%
|
||||
),
|
||||
radial-gradient(
|
||||
at top center,
|
||||
rgba(0, 0, 0, 0.15) 100%),
|
||||
radial-gradient(at top center,
|
||||
rgba(255, 255, 255, 0.4) 0%,
|
||||
rgba(0, 0, 0, 0.4) 120%
|
||||
) #989898;
|
||||
rgba(0, 0, 0, 0.4) 120%) #989898;
|
||||
background-blend-mode: multiply, multiply;
|
||||
background-size: cover;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,13 +1,7 @@
|
|||
<template>
|
||||
<div>
|
||||
<el-upload
|
||||
:action="`${path}/fileUploadAndDownload/upload`"
|
||||
:before-upload="checkFile"
|
||||
:on-error="uploadError"
|
||||
:on-success="uploadSuccess"
|
||||
:show-file-list="false"
|
||||
class="upload-btn"
|
||||
>
|
||||
<el-upload :action="`${path}/mediaFile/upload`" :before-upload="checkFile" :on-error="uploadError"
|
||||
:on-success="uploadSuccess" :show-file-list="false" class="upload-btn">
|
||||
<el-button type="primary">普通上传</el-button>
|
||||
</el-upload>
|
||||
</div>
|
||||
|
|
@ -23,43 +17,37 @@ defineOptions({
|
|||
name: 'UploadCommon',
|
||||
})
|
||||
|
||||
const emit = defineEmits(['on-success'])
|
||||
const emit = defineEmits(['on-success', 'on-failure', 'on-before-upload'])
|
||||
const path = ref(import.meta.env.VITE_BASE_API)
|
||||
|
||||
const fullscreenLoading = ref(false)
|
||||
|
||||
const checkFile = (file) => {
|
||||
fullscreenLoading.value = true
|
||||
const isLt500K = file.size / 1024 / 1024 < 0.5 // 500K, @todo 应支持在项目中设置
|
||||
const isLt5M = file.size / 1024 / 1024 < 5 // 5MB, @todo 应支持项目中设置
|
||||
const isVideo = isVideoMime(file.type)
|
||||
const isImage = isImageMime(file.type)
|
||||
let pass = true
|
||||
|
||||
if (!isVideo && !isImage) {
|
||||
ElMessage.error('上传图片只能是 jpg,png,svg,webp 格式, 上传视频只能是 mp4,webm 格式!')
|
||||
fullscreenLoading.value = false
|
||||
pass = false
|
||||
return false
|
||||
}
|
||||
if (!isLt5M && isVideo) {
|
||||
ElMessage.error('上传视频大小不能超过 5MB')
|
||||
fullscreenLoading.value = false
|
||||
pass = false
|
||||
return false
|
||||
}
|
||||
if (!isLt500K && isImage) {
|
||||
ElMessage.error('未压缩的上传图片大小不能超过 500KB,请使用压缩上传')
|
||||
fullscreenLoading.value = false
|
||||
pass = false
|
||||
return false
|
||||
}
|
||||
|
||||
console.log('upload file check result: ', pass)
|
||||
emit('on-before-upload', file)
|
||||
|
||||
return pass
|
||||
return true
|
||||
}
|
||||
|
||||
const uploadSuccess = (res) => {
|
||||
const { data } = res
|
||||
if (data.file) {
|
||||
emit('on-success', data.file.url)
|
||||
if (data.mediaFile) {
|
||||
emit('on-success', data.mediaFile.url)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -68,8 +56,7 @@ const uploadError = () => {
|
|||
type: 'error',
|
||||
message: '上传失败'
|
||||
})
|
||||
fullscreenLoading.value = false
|
||||
emit('on-failure')
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,14 +1,8 @@
|
|||
|
||||
<template>
|
||||
<div>
|
||||
<el-upload
|
||||
:action="`${path}/fileUploadAndDownload/upload`"
|
||||
:show-file-list="false"
|
||||
:on-success="handleImageSuccess"
|
||||
:before-upload="beforeImageUpload"
|
||||
:multiple="false"
|
||||
>
|
||||
<el-button type="primary">压缩上传</el-button>
|
||||
<el-upload :action="`${path}/mediaFile/upload`" :show-file-list="false" :on-success="handleImageSuccess"
|
||||
:on-error="handleImageFailure" :before-upload="beforeImageUpload" :multiple="false">
|
||||
<el-button type="primary">图片自动压缩上传</el-button>
|
||||
</el-upload>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -17,13 +11,12 @@
|
|||
import ImageCompress from '@/utils/image'
|
||||
import { ref } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { useUserStore } from '@/pinia/modules/user'
|
||||
|
||||
defineOptions({
|
||||
name: 'UploadImage',
|
||||
})
|
||||
|
||||
const emit = defineEmits(['on-success'])
|
||||
const emit = defineEmits(['on-success', 'on-failure', 'on-before-upload'])
|
||||
const props = defineProps({
|
||||
imageUrl: {
|
||||
type: String,
|
||||
|
|
@ -41,8 +34,6 @@ const props = defineProps({
|
|||
|
||||
const path = ref(import.meta.env.VITE_BASE_API)
|
||||
|
||||
const userStore = useUserStore()
|
||||
|
||||
const beforeImageUpload = (file) => {
|
||||
const isJPG = file.type === 'image/jpeg'
|
||||
const isPng = file.type === 'image/png'
|
||||
|
|
@ -51,19 +42,26 @@ const beforeImageUpload = (file) => {
|
|||
return false
|
||||
}
|
||||
|
||||
emit('on-before-upload')
|
||||
|
||||
const isRightSize = file.size / 1024 < props.fileSize
|
||||
if (!isRightSize) {
|
||||
// 压缩
|
||||
const compress = new ImageCompress(file, props.fileSize, props.maxWH)
|
||||
return compress.compress()
|
||||
}
|
||||
|
||||
return isRightSize
|
||||
}
|
||||
|
||||
const handleImageFailure = (res) => {
|
||||
emit('on-failure')
|
||||
}
|
||||
|
||||
const handleImageSuccess = (res) => {
|
||||
const { data } = res
|
||||
if (data.file) {
|
||||
emit('on-success', data.file.url)
|
||||
if (data.mediaFile) {
|
||||
emit('on-success', data.mediaFile.url)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -78,9 +76,11 @@ const handleImageSuccess = (res) => {
|
|||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.image-uploader {
|
||||
border-color: #409eff;
|
||||
}
|
||||
|
||||
.image-uploader-icon {
|
||||
font-size: 28px;
|
||||
color: #8c939d;
|
||||
|
|
@ -89,6 +89,7 @@ const handleImageSuccess = (res) => {
|
|||
line-height: 178px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.image {
|
||||
width: 178px;
|
||||
height: 178px;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,266 @@
|
|||
<template>
|
||||
<div>
|
||||
<div class="gva-table-box">
|
||||
<div class="gva-btn-list">
|
||||
<el-button type="primary" icon="plus" @click="clickAdd('0')">新增根栏目</el-button>
|
||||
</div>
|
||||
|
||||
<!-- 由于此处菜单跟左侧列表一一对应所以不需要分页 pageSize默认999 -->
|
||||
<el-table :data="tableData" row-key="ID">
|
||||
<el-table-column align="left" label="ID" min-width="80" prop="ID" />
|
||||
<el-table-column align="left" label="名称" min-width="100" prop="name" />
|
||||
<el-table-column align="left" label="标题" min-width="120" prop="title" />
|
||||
<el-table-column align="left" label="摘要" min-width="260" prop="description" />
|
||||
<el-table-column align="left" label="关键词" min-width="260" prop="keyword" />
|
||||
<el-table-column align="left" label="介绍" min-width="260" prop="introduce" />
|
||||
<el-table-column align="left" label="模板ID" min-width="80" prop="templateId" />
|
||||
<el-table-column align="left" label="文章页模板ID" min-width="140" prop="templateArticleId" />
|
||||
<el-table-column align="left" label="默认显示文章数" min-width="140" prop="pageNum" />
|
||||
<el-table-column align="left" label="父节点" min-width="90" prop="parentId" />
|
||||
<el-table-column align="left" fixed="right" label="操作" width="300">
|
||||
<template #default="scope">
|
||||
<el-button type="primary" link icon="plus" @click="clickAdd(scope.row.ID)">添加子栏目</el-button>
|
||||
<el-button type="primary" link icon="edit" @click="clickEdit(scope.row.ID)">编辑</el-button>
|
||||
<el-button type="primary" link icon="delete" @click="clickDelete(scope.row.ID)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
|
||||
<el-dialog v-model="dialogFormVisible" :before-close="handleClose" :title="dialogTitle">
|
||||
<el-form v-if="dialogFormVisible" ref="channelForm" label-position="top" label-width="85px" :inline="true"
|
||||
:model="form" :rules="rules">
|
||||
<el-form-item label="名称(导航用)" prop="name" style="width:45%">
|
||||
<el-input v-model="form.name" autocomplete="off" />
|
||||
</el-form-item>
|
||||
<el-form-item label="标题(栏目页使用)" prop="title" style="width:45%">
|
||||
<el-input v-model="form.title" autocomplete="off" />
|
||||
</el-form-item>
|
||||
<el-form-item label="摘要" prop="description" style="width:94%">
|
||||
<el-input v-model="form.description" autocomplete="off" />
|
||||
</el-form-item>
|
||||
<el-form-item label="关键词" prop="keyword" style="width:94%">
|
||||
<el-input v-model="form.keyword" autocomplete="off" />
|
||||
</el-form-item>
|
||||
<el-form-item label="介绍" prop="introduce" style="width:94%">
|
||||
<el-input v-model="form.introduce" autocomplete="off" />
|
||||
</el-form-item>
|
||||
<el-form-item label="模板ID" prop="templateId" style="width:45%">
|
||||
<el-input v-model="form.templateId" autocomplete="off" />
|
||||
</el-form-item>
|
||||
<el-form-item label="文章页模板ID" prop="templateArticleId" style="width:45%">
|
||||
<el-input v-model="form.templateArticleId" autocomplete="off" />
|
||||
</el-form-item>
|
||||
<el-form-item label="默认显示文章条数" prop="pageNum" style="width:45%">
|
||||
<el-input-number v-model="form.pageNum" autocomplete="off" style="width:100%" />
|
||||
</el-form-item>
|
||||
<el-form-item label="父节点ID" style="width:45%">
|
||||
<el-cascader v-model="form.parentId" style="width:100%" :disabled="!isEdit" :options="channelOption"
|
||||
:props="{ checkStrictly: true, label: 'title', value: 'ID', disabled: 'disabled', emitPath: false }"
|
||||
:show-all-levels="false" filterable />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button @click="closeDialog">取 消</el-button>
|
||||
<el-button type="primary" @click="enterDialog">确 定</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { reactive, ref } from 'vue'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
|
||||
import {
|
||||
getChannelTree,
|
||||
addChannel,
|
||||
updateChannel,
|
||||
deleteChannel,
|
||||
getChannelById
|
||||
} from '@/api/channel'
|
||||
|
||||
const rules = reactive({
|
||||
name: [
|
||||
{ required: true, message: '请输入栏目名称', trigger: 'blur' }
|
||||
],
|
||||
title: [
|
||||
{ required: true, message: '请输入栏目标题', trigger: 'blur' }
|
||||
],
|
||||
pageNum: [
|
||||
{ required: true, type: 'number', message: '默认显示文章条数必须为大于0的整数', trigger: 'blur' }
|
||||
],
|
||||
})
|
||||
|
||||
const tableData = ref([])
|
||||
|
||||
// 查询
|
||||
const getTableData = async () => {
|
||||
const res = await getChannelTree()
|
||||
if (res.code === 0) {
|
||||
tableData.value = res.data.channelTree
|
||||
}
|
||||
}
|
||||
|
||||
getTableData()
|
||||
|
||||
const channelOption = ref([
|
||||
{
|
||||
ID: '0',
|
||||
name: '根栏目'
|
||||
}
|
||||
])
|
||||
const setOptions = () => {
|
||||
channelOption.value = [
|
||||
{
|
||||
ID: '0',
|
||||
name: '根栏目'
|
||||
}
|
||||
]
|
||||
setChannelOptions(tableData.value, channelOption.value, false)
|
||||
}
|
||||
const setChannelOptions = (channelData, optionsData, disabled) => {
|
||||
channelData &&
|
||||
channelData.forEach(item => {
|
||||
if (item.children && item.children.length) {
|
||||
const option = {
|
||||
title: item.name,
|
||||
ID: String(item.ID),
|
||||
disabled: disabled || item.ID === form.value.ID,
|
||||
children: []
|
||||
}
|
||||
setChannelOptions(
|
||||
item.children,
|
||||
option.children,
|
||||
disabled || item.ID === form.value.ID
|
||||
)
|
||||
optionsData.push(option)
|
||||
} else {
|
||||
const option = {
|
||||
title: item.name,
|
||||
ID: String(item.ID),
|
||||
disabled: disabled || item.ID === form.value.ID
|
||||
}
|
||||
optionsData.push(option)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const form = ref({
|
||||
ID: 0,
|
||||
parentId: 0,
|
||||
name: '',
|
||||
title: '',
|
||||
description: '',
|
||||
keyword: '',
|
||||
introduce: '',
|
||||
templateId: 0,
|
||||
templateArticleId: 0,
|
||||
pageNum: 10,
|
||||
})
|
||||
|
||||
// 添加栏目
|
||||
const enterDialog = async () => {
|
||||
channelForm.value.validate(async valid => {
|
||||
if (valid) {
|
||||
let res
|
||||
if (isEdit.value) {
|
||||
res = await updateChannel(form.value)
|
||||
} else {
|
||||
res = await addChannel(form.value)
|
||||
}
|
||||
if (res.code === 0) {
|
||||
ElMessage({
|
||||
type: 'success',
|
||||
message: isEdit.value ? '编辑成功' : '添加成功!'
|
||||
})
|
||||
getTableData()
|
||||
}
|
||||
initForm()
|
||||
dialogFormVisible.value = false
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 初始化弹窗内表格方法
|
||||
const channelForm = ref(null)
|
||||
const checkFlag = ref(false)
|
||||
const initForm = () => {
|
||||
checkFlag.value = false
|
||||
channelForm.value.resetFields()
|
||||
form.value = {
|
||||
ID: 0,
|
||||
parentId: 0,
|
||||
name: '',
|
||||
title: '',
|
||||
description: '',
|
||||
keyword: '',
|
||||
introduce: '',
|
||||
templateId: 0,
|
||||
templateArticleId: 0,
|
||||
pageNum: 10,
|
||||
}
|
||||
}
|
||||
const handleClose = (done) => {
|
||||
initForm()
|
||||
done()
|
||||
}
|
||||
|
||||
// 关闭弹窗
|
||||
const dialogFormVisible = ref(false)
|
||||
const closeDialog = () => {
|
||||
initForm()
|
||||
dialogFormVisible.value = false
|
||||
}
|
||||
|
||||
// 删除菜单
|
||||
const clickDelete = (ID) => {
|
||||
ElMessageBox.confirm('此操作将永久删除栏目, 是否继续?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
})
|
||||
.then(async () => {
|
||||
const res = await deleteChannel({ ID })
|
||||
if (res.code === 0) {
|
||||
ElMessage({
|
||||
type: 'success',
|
||||
message: '删除成功!'
|
||||
})
|
||||
if (tableData.value.length === 1 && page.value > 1) {
|
||||
page.value--
|
||||
}
|
||||
getTableData()
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
ElMessage({
|
||||
type: 'info',
|
||||
message: '已取消删除'
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// 添加栏目方法,id为 0则为添加根栏目
|
||||
const isEdit = ref(false)
|
||||
const dialogTitle = ref('新增栏目')
|
||||
const clickAdd = (id) => {
|
||||
dialogTitle.value = '新增栏目'
|
||||
form.value.parentId = String(id)
|
||||
isEdit.value = false
|
||||
setOptions()
|
||||
dialogFormVisible.value = true
|
||||
}
|
||||
// 修改菜单方法
|
||||
const clickEdit = async (id) => {
|
||||
dialogTitle.value = '编辑栏目'
|
||||
const res = await getChannelById({ id })
|
||||
form.value = res.data.channel
|
||||
isEdit.value = true
|
||||
setOptions()
|
||||
dialogFormVisible.value = true
|
||||
}
|
||||
|
||||
</script>
|
||||
|
|
@ -0,0 +1,279 @@
|
|||
<template>
|
||||
<div class="break-point">
|
||||
<div class="gva-table-box">
|
||||
<el-divider content-position="left">大文件上传</el-divider>
|
||||
<form id="fromCont" method="post">
|
||||
<div class="fileUpload" @click="inputChange">
|
||||
选择文件
|
||||
<input v-show="false" id="file" ref="FileInput" multiple="multiple" type="file" @change="choseFile">
|
||||
</div>
|
||||
</form>
|
||||
<el-button :disabled="limitFileSize" type="primary" class="uploadBtn" @click="getFile">上传文件</el-button>
|
||||
<div class="el-upload__tip">请上传不超过5MB的文件</div>
|
||||
<div class="list">
|
||||
<transition name="list" tag="p">
|
||||
<div v-if="file" class="list-item">
|
||||
<el-icon>
|
||||
<document />
|
||||
</el-icon>
|
||||
<span>{{ file.name }}</span>
|
||||
<span class="percentage">{{ percentage }}%</span>
|
||||
<el-progress :show-text="false" :text-inside="false" :stroke-width="2" :percentage="percentage" />
|
||||
</div>
|
||||
</transition>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import SparkMD5 from 'spark-md5'
|
||||
import {
|
||||
findFile,
|
||||
breakpointContinueFinish,
|
||||
removeChunk,
|
||||
breakpointContinue
|
||||
} from '@/api/breakpoint'
|
||||
import { ref, watch } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
|
||||
defineOptions({
|
||||
name: 'BreakPoint'
|
||||
})
|
||||
|
||||
const file = ref(null)
|
||||
const fileMd5 = ref('')
|
||||
const formDataList = ref([])
|
||||
const waitUpLoad = ref([])
|
||||
const waitNum = ref(NaN)
|
||||
const limitFileSize = ref(false)
|
||||
const percentage = ref(0)
|
||||
const percentageFlage = ref(true)
|
||||
|
||||
// 选中文件的函数
|
||||
const choseFile = async (e) => {
|
||||
const fileR = new FileReader() // 创建一个reader用来读取文件流
|
||||
const fileInput = e.target.files[0] // 获取当前文件
|
||||
const maxSize = 5 * 1024 * 1024
|
||||
file.value = fileInput // file 丢全局方便后面用 可以改进为func传参形式
|
||||
percentage.value = 0
|
||||
if (file.value.size < maxSize) {
|
||||
fileR.readAsArrayBuffer(file.value) // 把文件读成ArrayBuffer 主要为了保持跟后端的流一致
|
||||
fileR.onload = async e => {
|
||||
// 读成arrayBuffer的回调 e 为方法自带参数 相当于 dom的e 流存在e.target.result 中
|
||||
const blob = e.target.result
|
||||
const spark = new SparkMD5.ArrayBuffer() // 创建md5制造工具 (md5用于检测文件一致性 这里不懂就打电话问我)
|
||||
spark.append(blob) // 文件流丢进工具
|
||||
fileMd5.value = spark.end() // 工具结束 产生一个a 总文件的md5
|
||||
const FileSliceCap = 1 * 1024 * 1024 // 分片字节数
|
||||
let start = 0 // 定义分片开始切的地方
|
||||
let end = 0 // 每片结束切的地方a
|
||||
let i = 0 // 第几片
|
||||
formDataList.value = [] // 分片存储的一个池子 丢全局
|
||||
while (end < file.value.size) {
|
||||
// 当结尾数字大于文件总size的时候 结束切片
|
||||
start = i * FileSliceCap // 计算每片开始位置
|
||||
end = (i + 1) * FileSliceCap // 计算每片结束位置
|
||||
var fileSlice = file.value.slice(start, end) // 开始切 file.slice 为 h5方法 对文件切片 参数为 起止字节数
|
||||
const formData = new window.FormData() // 创建FormData用于存储传给后端的信息
|
||||
formData.append('fileMd5', fileMd5.value) // 存储总文件的Md5 让后端知道自己是谁的切片
|
||||
formData.append('file', fileSlice) // 当前的切片
|
||||
formData.append('chunkNumber', i) // 当前是第几片
|
||||
formData.append('fileName', file.value.name) // 当前文件的文件名 用于后端文件切片的命名 formData.appen 为 formData对象添加参数的方法
|
||||
formDataList.value.push({ key: i, formData }) // 把当前切片信息 自己是第几片 存入我们方才准备好的池子
|
||||
i++
|
||||
}
|
||||
const params = {
|
||||
fileName: file.value.name,
|
||||
fileMd5: fileMd5.value,
|
||||
chunkTotal: formDataList.value.length
|
||||
}
|
||||
const res = await findFile(params)
|
||||
// 全部切完以后 发一个请求给后端 拉当前文件后台存储的切片信息 用于检测有多少上传成功的切片
|
||||
const finishList = res.data.file.ExaFileChunk // 上传成功的切片
|
||||
const IsFinish = res.data.file.IsFinish // 是否是同文件不同命 (文件md5相同 文件名不同 则默认是同一个文件但是不同文件名 此时后台数据库只需要拷贝一下数据库文件即可 不需要上传文件 即秒传功能)
|
||||
if (!IsFinish) {
|
||||
// 当是断点续传时候
|
||||
waitUpLoad.value = formDataList.value.filter(all => {
|
||||
return !(
|
||||
finishList &&
|
||||
finishList.some(fi => fi.FileChunkNumber === all.key)
|
||||
) // 找出需要上传的切片
|
||||
})
|
||||
} else {
|
||||
waitUpLoad.value = [] // 秒传则没有需要上传的切片
|
||||
ElMessage.success('文件已秒传')
|
||||
}
|
||||
waitNum.value = waitUpLoad.value.length // 记录长度用于百分比展示
|
||||
}
|
||||
} else {
|
||||
limitFileSize.value = true
|
||||
ElMessage('请上传小于5M文件')
|
||||
}
|
||||
}
|
||||
|
||||
const getFile = () => {
|
||||
// 确定按钮
|
||||
if (file.value === null) {
|
||||
ElMessage('请先上传文件')
|
||||
return
|
||||
}
|
||||
if (percentage.value === 100) {
|
||||
percentageFlage.value = false
|
||||
}
|
||||
sliceFile() // 上传切片
|
||||
}
|
||||
|
||||
const sliceFile = () => {
|
||||
waitUpLoad.value &&
|
||||
waitUpLoad.value.forEach(item => {
|
||||
// 需要上传的切片
|
||||
item.formData.append('chunkTotal', formDataList.value.length) // 切片总数携带给后台 总有用的
|
||||
const fileR = new FileReader() // 功能同上
|
||||
const fileF = item.formData.get('file')
|
||||
fileR.readAsArrayBuffer(fileF)
|
||||
fileR.onload = e => {
|
||||
const spark = new SparkMD5.ArrayBuffer()
|
||||
spark.append(e.target.result)
|
||||
item.formData.append('chunkMd5', spark.end()) // 获取当前切片md5 后端用于验证切片完整性
|
||||
upLoadFileSlice(item)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
watch(() => waitNum.value, () => { percentage.value = Math.floor(((formDataList.value.length - waitNum.value) / formDataList.value.length) * 100) })
|
||||
|
||||
const upLoadFileSlice = async (item) => {
|
||||
// 切片上传
|
||||
const fileRe = await breakpointContinue(item.formData)
|
||||
if (fileRe.code !== 0) {
|
||||
return
|
||||
}
|
||||
waitNum.value-- // 百分数增加
|
||||
if (waitNum.value === 0) {
|
||||
// 切片传完以后 合成文件
|
||||
const params = {
|
||||
fileName: file.value.name,
|
||||
fileMd5: fileMd5.value
|
||||
}
|
||||
const res = await breakpointContinueFinish(params)
|
||||
if (res.code === 0) {
|
||||
// 合成文件过后 删除缓存切片
|
||||
const params = {
|
||||
fileName: file.value.name,
|
||||
fileMd5: fileMd5.value,
|
||||
filePath: res.data.filePath,
|
||||
}
|
||||
ElMessage.success('上传成功')
|
||||
await removeChunk(params)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const FileInput = ref(null)
|
||||
const inputChange = () => {
|
||||
FileInput.value.dispatchEvent(new MouseEvent('click'))
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang='scss' scoped>
|
||||
h3 {
|
||||
margin: 40px 0 0;
|
||||
}
|
||||
|
||||
ul {
|
||||
list-style-type: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
li {
|
||||
display: inline-block;
|
||||
margin: 0 10px;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #42b983;
|
||||
}
|
||||
|
||||
#fromCont {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.fileUpload {
|
||||
padding: 3px 10px;
|
||||
font-size: 12px;
|
||||
height: 20px;
|
||||
line-height: 20px;
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
color: #000;
|
||||
border: 1px solid #c1c1c1;
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
display: inline-block;
|
||||
|
||||
input {
|
||||
position: absolute;
|
||||
font-size: 100px;
|
||||
right: 0;
|
||||
top: 0;
|
||||
opacity: 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.fileName {
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
margin: 6px 15px 0 15px;
|
||||
}
|
||||
|
||||
.uploadBtn {
|
||||
position: relative;
|
||||
top: -10px;
|
||||
margin-left: 15px;
|
||||
}
|
||||
|
||||
.tips {
|
||||
margin-top: 30px;
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
color: #606266;
|
||||
}
|
||||
|
||||
.el-divider {
|
||||
margin: 0 0 30px 0;
|
||||
}
|
||||
|
||||
.list {
|
||||
margin-top: 15px;
|
||||
}
|
||||
|
||||
.list-item {
|
||||
display: block;
|
||||
margin-right: 10px;
|
||||
color: #606266;
|
||||
line-height: 25px;
|
||||
margin-bottom: 5px;
|
||||
width: 40%;
|
||||
|
||||
.percentage {
|
||||
float: right;
|
||||
}
|
||||
}
|
||||
|
||||
.list-enter-active,
|
||||
.list-leave-active {
|
||||
transition: all 1s;
|
||||
}
|
||||
|
||||
.list-enter,
|
||||
.list-leave-to
|
||||
|
||||
/* .list-leave-active for below version 2.1.8 */
|
||||
{
|
||||
opacity: 0;
|
||||
transform: translateY(-30px);
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,192 @@
|
|||
<template>
|
||||
<div v-loading.fullscreen.lock="fullscreenLoading">
|
||||
<div class="gva-table-box">
|
||||
<warning-bar title="点击“文件名/备注”可以编辑文件名或者备注内容。" />
|
||||
<div class="gva-btn-list">
|
||||
<upload-common :image-common="imageCommon" @on-success="uploadSuccess" @on-failure="uploadFailure"
|
||||
@on-before-upload="beforeUpload" />
|
||||
<upload-image :image-url="imageUrl" :file-size="512" :max-w-h="1080" @on-success="uploadSuccess"
|
||||
@on-failure="uploadFailure" @on-before-upload="beforeUpload" />
|
||||
<el-input v-model="search.keyword" class="keyword" placeholder="请输入文件名或备注" />
|
||||
<el-button type="primary" icon="search" @click="getTableData">查询</el-button>
|
||||
</div>
|
||||
|
||||
<el-table :data="tableData">
|
||||
<el-table-column align="left" label="预览" width="100">
|
||||
<template #default="scope">
|
||||
<CustomPic pic-type="file" :pic-src="scope.row.url" preview />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="left" label="日期" prop="UpdatedAt" width="180">
|
||||
<template #default="scope">
|
||||
<div>{{ formatDate(scope.row.UpdatedAt) }}</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="left" label="文件名/备注" prop="name" width="180">
|
||||
<template #default="scope">
|
||||
<div class="name" @click="editFileNameFunc(scope.row)">{{ scope.row.name }}</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="left" label="链接" prop="url" min-width="300" />
|
||||
<el-table-column align="left" label="标签" prop="tag" width="100">
|
||||
<template #default="scope">
|
||||
<el-tag :type="scope.row.tag === 'jpg' ? 'info' : 'success'" disable-transitions>{{ scope.row.tag }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="left" label="操作" width="160">
|
||||
<template #default="scope">
|
||||
<el-button icon="download" type="primary" link @click="downloadFile(scope.row)">下载</el-button>
|
||||
<el-button icon="delete" type="primary" link @click="deleteFileFunc(scope.row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div class="gva-pagination">
|
||||
<el-pagination :current-page="page" :page-size="pageSize" :page-sizes="[10, 30, 50, 100]"
|
||||
:style="{ float: 'right', padding: '20px' }" :total="total" layout="total, sizes, prev, pager, next, jumper"
|
||||
@current-change="handleCurrentChange" @size-change="handleSizeChange" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { getFileList, deleteFile, editFileName } from '@/api/mediaFile'
|
||||
import { downloadImage } from '@/utils/downloadImg'
|
||||
import CustomPic from '@/components/customPic/index.vue'
|
||||
import UploadImage from '@/components/upload/image.vue'
|
||||
import UploadCommon from '@/components/upload/common.vue'
|
||||
import { formatDate } from '@/utils/format'
|
||||
import WarningBar from '@/components/warningBar/warningBar.vue'
|
||||
|
||||
import { ref } from 'vue'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
|
||||
defineOptions({
|
||||
name: 'Upload',
|
||||
})
|
||||
|
||||
const path = ref(import.meta.env.VITE_BASE_API)
|
||||
|
||||
const imageUrl = ref('')
|
||||
const imageCommon = ref('')
|
||||
|
||||
const page = ref(1)
|
||||
const total = ref(0)
|
||||
const pageSize = ref(10)
|
||||
const search = ref({})
|
||||
const tableData = ref([])
|
||||
const fullscreenLoading = ref(false)
|
||||
|
||||
// 分页
|
||||
const handleSizeChange = (val) => {
|
||||
pageSize.value = val
|
||||
getTableData()
|
||||
}
|
||||
|
||||
const handleCurrentChange = (val) => {
|
||||
page.value = val
|
||||
getTableData()
|
||||
}
|
||||
|
||||
const beforeUpload = () => {
|
||||
console.log('beforeUpload')
|
||||
fullscreenLoading.value = true
|
||||
}
|
||||
|
||||
const uploadSuccess = () => {
|
||||
console.log('uploadSuccess')
|
||||
fullscreenLoading.value = false
|
||||
getTableData()
|
||||
}
|
||||
|
||||
const uploadFailure = () => {
|
||||
console.log('uploadFailure')
|
||||
fullscreenLoading.value = false
|
||||
}
|
||||
|
||||
// 查询
|
||||
const getTableData = async () => {
|
||||
const table = await getFileList({ page: page.value, pageSize: pageSize.value, ...search.value })
|
||||
if (table.code === 0) {
|
||||
tableData.value = table.data.list
|
||||
total.value = table.data.total
|
||||
page.value = table.data.page
|
||||
pageSize.value = table.data.pageSize
|
||||
}
|
||||
}
|
||||
getTableData()
|
||||
|
||||
const deleteFileFunc = async (row) => {
|
||||
ElMessageBox.confirm('此操作将永久删除文件, 是否继续?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
})
|
||||
.then(async () => {
|
||||
const res = await deleteFile(row)
|
||||
if (res.code === 0) {
|
||||
ElMessage({
|
||||
type: 'success',
|
||||
message: '删除成功!',
|
||||
})
|
||||
if (tableData.value.length === 1 && page.value > 1) {
|
||||
page.value--
|
||||
}
|
||||
getTableData()
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
ElMessage({
|
||||
type: 'info',
|
||||
message: '已取消删除',
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
const downloadFile = (row) => {
|
||||
if (row.url.indexOf('http://') > -1 || row.url.indexOf('https://') > -1) {
|
||||
downloadImage(row.url, row.name)
|
||||
} else {
|
||||
debugger
|
||||
downloadImage(path.value + '/' + row.url, row.name)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑文件名或者备注
|
||||
* @param row
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
const editFileNameFunc = async (row) => {
|
||||
ElMessageBox.prompt('请输入文件名或者备注', '编辑', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
inputPattern: /\S/,
|
||||
inputErrorMessage: '不能为空',
|
||||
inputValue: row.name
|
||||
}).then(async ({ value }) => {
|
||||
row.name = value
|
||||
// console.log(row)
|
||||
const res = await editFileName(row)
|
||||
if (res.code === 0) {
|
||||
ElMessage({
|
||||
type: 'success',
|
||||
message: '编辑成功!',
|
||||
})
|
||||
getTableData()
|
||||
}
|
||||
}).catch(() => {
|
||||
ElMessage({
|
||||
type: 'info',
|
||||
message: '取消修改'
|
||||
})
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.name {
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,100 +1,46 @@
|
|||
<template>
|
||||
<div id="userLayout" class="w-full h-full relative">
|
||||
<div
|
||||
id="userLayout"
|
||||
class="w-full h-full relative"
|
||||
>
|
||||
<div
|
||||
class="rounded-lg flex items-center justify-evenly w-full h-full bg-white md:w-screen md:h-screen md:bg-[#194bfb]"
|
||||
>
|
||||
class="rounded-lg flex items-center justify-evenly w-full h-full bg-white md:w-screen md:h-screen md:bg-[#194bfb]">
|
||||
<div class="md:w-3/5 w-10/12 h-full flex items-center justify-evenly">
|
||||
<div class="oblique h-[130%] w-3/5 bg-white transform -rotate-12 absolute -ml-52" />
|
||||
<!-- 分割斜块 -->
|
||||
<div class="z-[999] pt-12 pb-10 md:w-96 w-full rounded-lg flex flex-col justify-between box-border">
|
||||
<div>
|
||||
<div class="flex items-center justify-center">
|
||||
<img
|
||||
class="w-24"
|
||||
src="@/assets/logo.png"
|
||||
alt
|
||||
style="margin-bottom: 15px;"
|
||||
>
|
||||
<img class="w-24" src="@/assets/logo.png" alt style="margin-bottom: 15px;">
|
||||
</div>
|
||||
<div class="mb-9">
|
||||
<p class="text-center text-4xl font-bold">{{ $GIN_VUE_ADMIN.appName }}</p>
|
||||
<!-- <p class="text-center text-sm font-normal text-gray-500 mt-2.5">A management platform using Golang and Vue</p> -->
|
||||
</div>
|
||||
<el-form
|
||||
ref="loginForm"
|
||||
:model="loginFormData"
|
||||
:rules="rules"
|
||||
:validate-on-rule-change="false"
|
||||
@keyup.enter="submitForm"
|
||||
>
|
||||
<el-form-item
|
||||
prop="username"
|
||||
class="mb-6"
|
||||
>
|
||||
<el-input
|
||||
v-model="loginFormData.username"
|
||||
size="large"
|
||||
placeholder="请输入用户名"
|
||||
suffix-icon="user"
|
||||
/>
|
||||
<el-form ref="loginForm" :model="loginFormData" :rules="rules" :validate-on-rule-change="false"
|
||||
@keyup.enter="submitForm">
|
||||
<el-form-item prop="username" class="mb-6">
|
||||
<el-input v-model="loginFormData.username" size="large" placeholder="请输入用户名" suffix-icon="user" />
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
prop="password"
|
||||
class="mb-6"
|
||||
>
|
||||
<el-input
|
||||
v-model="loginFormData.password"
|
||||
show-password
|
||||
size="large"
|
||||
type="password"
|
||||
placeholder="请输入密码"
|
||||
/>
|
||||
<el-form-item prop="password" class="mb-6">
|
||||
<el-input v-model="loginFormData.password" show-password size="large" type="password"
|
||||
placeholder="请输入密码" />
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
v-if="loginFormData.openCaptcha"
|
||||
prop="captcha"
|
||||
class="mb-6"
|
||||
>
|
||||
<el-form-item v-if="loginFormData.openCaptcha" prop="captcha" class="mb-6">
|
||||
<div class="flex w-full justify-between">
|
||||
<el-input
|
||||
v-model="loginFormData.captcha"
|
||||
placeholder="请输入验证码"
|
||||
size="large"
|
||||
class="flex-1 mr-5"
|
||||
/>
|
||||
<el-input v-model="loginFormData.captcha" placeholder="请输入验证码" size="large" class="flex-1 mr-5" />
|
||||
<div class="w-1/3 h-11 bg-[#c3d4f2] rounded">
|
||||
<img
|
||||
v-if="picPath"
|
||||
class="w-full h-full"
|
||||
:src="picPath"
|
||||
alt="请输入验证码"
|
||||
@click="loginVerify()"
|
||||
>
|
||||
<img v-if="picPath" class="w-full h-full" :src="picPath" alt="请输入验证码" @click="loginVerify()">
|
||||
</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item class="mb-6">
|
||||
<el-button
|
||||
class="shadow shadow-blue-600 h-11 w-full"
|
||||
type="primary"
|
||||
size="large"
|
||||
@click="submitForm"
|
||||
>登 录</el-button>
|
||||
<el-button class="shadow shadow-blue-600 h-11 w-full" type="primary" size="large" @click="submitForm">登
|
||||
录</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="hidden md:block w-1/2 h-full float-right bg-[#194bfb]">
|
||||
<img
|
||||
class="h-full"
|
||||
style="width: 90%"
|
||||
src="@/assets/login_left.svg"
|
||||
alt="banner"
|
||||
>
|
||||
<img class="h-full" style="width: 90%" src="@/assets/login_left.svg" alt="banner">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -5,42 +5,21 @@
|
|||
<div class="w-full h-full bg-white px-4 py-8 rounded-lg shadow-lg box-border">
|
||||
<div class="user-card px-6 text-center bg-white shrink-0">
|
||||
<div class="flex justify-center">
|
||||
<SelectImage
|
||||
v-model="userStore.userInfo.headerImg"
|
||||
file-type="image"
|
||||
/>
|
||||
<SelectImage v-model="userStore.userInfo.headerImg" file-type="image" />
|
||||
</div>
|
||||
<div class="py-6 text-center">
|
||||
<p
|
||||
v-if="!editFlag"
|
||||
class="text-3xl flex justify-center items-center gap-4"
|
||||
>
|
||||
<p v-if="!editFlag" class="text-3xl flex justify-center items-center gap-4">
|
||||
{{ userStore.userInfo.nickName }}
|
||||
<el-icon
|
||||
class="cursor-pointer text-sm"
|
||||
color="#66b1ff"
|
||||
@click="openEdit"
|
||||
>
|
||||
<el-icon class="cursor-pointer text-sm" color="#66b1ff" @click="openEdit">
|
||||
<edit />
|
||||
</el-icon>
|
||||
</p>
|
||||
<p
|
||||
v-if="editFlag"
|
||||
class="flex justify-center items-center gap-4"
|
||||
>
|
||||
<p v-if="editFlag" class="flex justify-center items-center gap-4">
|
||||
<el-input v-model="nickName" />
|
||||
<el-icon
|
||||
class="cursor-pointer"
|
||||
color="#67c23a"
|
||||
@click="enterEdit"
|
||||
>
|
||||
<el-icon class="cursor-pointer" color="#67c23a" @click="enterEdit">
|
||||
<check />
|
||||
</el-icon>
|
||||
<el-icon
|
||||
class="cursor-pointer"
|
||||
color="#f23c3c"
|
||||
@click="closeEdit"
|
||||
>
|
||||
<el-icon class="cursor-pointer" color="#f23c3c" @click="closeEdit">
|
||||
<close />
|
||||
</el-icon>
|
||||
</p>
|
||||
|
|
@ -61,14 +40,8 @@
|
|||
</div>
|
||||
<div class="col-span-9 ">
|
||||
<div class="bg-white h-full px-4 py-8 rounded-lg shadow-lg box-border">
|
||||
<el-tabs
|
||||
v-model="activeName"
|
||||
@tab-click="handleClick"
|
||||
>
|
||||
<el-tab-pane
|
||||
label="账号绑定"
|
||||
name="second"
|
||||
>
|
||||
<el-tabs v-model="activeName" @tab-click="handleClick">
|
||||
<el-tab-pane label="账号绑定" name="second">
|
||||
<ul>
|
||||
<li class="borderd">
|
||||
<p class="pb-2.5 text-xl text-gray-600">手机</p>
|
||||
|
|
@ -96,11 +69,7 @@
|
|||
<p class="pb-2.5 text-xl text-gray-600">修改密码</p>
|
||||
<p class="pb-2.5 text-lg text-gray-400">
|
||||
修改个人密码
|
||||
<a
|
||||
href="javascript:void(0)"
|
||||
class="float-right text-blue-400"
|
||||
@click="showPassword = true"
|
||||
>修改密码</a>
|
||||
<a href="javascript:void(0)" class="float-right text-blue-400" @click="showPassword = true">修改密码</a>
|
||||
</p>
|
||||
</li>
|
||||
</ul>
|
||||
|
|
@ -110,162 +79,66 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<el-dialog
|
||||
v-model="showPassword"
|
||||
title="修改密码"
|
||||
width="360px"
|
||||
@close="clearPassword"
|
||||
>
|
||||
<el-form
|
||||
ref="modifyPwdForm"
|
||||
:model="pwdModify"
|
||||
:rules="rules"
|
||||
label-width="80px"
|
||||
>
|
||||
<el-form-item
|
||||
:minlength="6"
|
||||
label="原密码"
|
||||
prop="password"
|
||||
>
|
||||
<el-input
|
||||
v-model="pwdModify.password"
|
||||
show-password
|
||||
/>
|
||||
<el-dialog v-model="showPassword" title="修改密码" width="360px" @close="clearPassword">
|
||||
<el-form ref="modifyPwdForm" :model="pwdModify" :rules="rules" label-width="80px">
|
||||
<el-form-item :minlength="6" label="原密码" prop="password">
|
||||
<el-input v-model="pwdModify.password" show-password />
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
:minlength="6"
|
||||
label="新密码"
|
||||
prop="newPassword"
|
||||
>
|
||||
<el-input
|
||||
v-model="pwdModify.newPassword"
|
||||
show-password
|
||||
/>
|
||||
<el-form-item :minlength="6" label="新密码" prop="newPassword">
|
||||
<el-input v-model="pwdModify.newPassword" show-password />
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
:minlength="6"
|
||||
label="确认密码"
|
||||
prop="confirmPassword"
|
||||
>
|
||||
<el-input
|
||||
v-model="pwdModify.confirmPassword"
|
||||
show-password
|
||||
/>
|
||||
<el-form-item :minlength="6" label="确认密码" prop="confirmPassword">
|
||||
<el-input v-model="pwdModify.confirmPassword" show-password />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button
|
||||
|
||||
@click="showPassword = false"
|
||||
>取 消</el-button>
|
||||
<el-button
|
||||
|
||||
type="primary"
|
||||
@click="savePassword"
|
||||
>确 定</el-button>
|
||||
<el-button @click="showPassword = false">取 消</el-button>
|
||||
<el-button type="primary" @click="savePassword">确 定</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<el-dialog
|
||||
v-model="changePhoneFlag"
|
||||
title="绑定手机"
|
||||
width="600px"
|
||||
>
|
||||
<el-dialog v-model="changePhoneFlag" title="绑定手机" width="600px">
|
||||
<el-form :model="phoneForm">
|
||||
<el-form-item
|
||||
label="手机号"
|
||||
label-width="120px"
|
||||
>
|
||||
<el-input
|
||||
v-model="phoneForm.phone"
|
||||
placeholder="请输入手机号"
|
||||
autocomplete="off"
|
||||
/>
|
||||
<el-form-item label="手机号" label-width="120px">
|
||||
<el-input v-model="phoneForm.phone" placeholder="请输入手机号" autocomplete="off" />
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
label="验证码"
|
||||
label-width="120px"
|
||||
>
|
||||
<el-form-item label="验证码" label-width="120px">
|
||||
<div class="flex w-full gap-4">
|
||||
<el-input
|
||||
v-model="phoneForm.code"
|
||||
class="flex-1"
|
||||
autocomplete="off"
|
||||
placeholder="请自行设计短信服务,此处为模拟随便写"
|
||||
style="width:300px"
|
||||
/>
|
||||
<el-button
|
||||
type="primary"
|
||||
:disabled="time>0"
|
||||
@click="getCode"
|
||||
>{{ time>0?`(${time}s)后重新获取`:'获取验证码' }}</el-button>
|
||||
<el-input v-model="phoneForm.code" class="flex-1" autocomplete="off" placeholder="请自行设计短信服务,此处为模拟随便写"
|
||||
style="width:300px" />
|
||||
<el-button type="primary" :disabled="time > 0" @click="getCode">{{ time > 0 ? `(${time}s)后重新获取` : '获取验证码'
|
||||
}}</el-button>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button
|
||||
|
||||
@click="closeChangePhone"
|
||||
>取消</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
|
||||
@click="changePhone"
|
||||
>更改</el-button>
|
||||
<el-button @click="closeChangePhone">取消</el-button>
|
||||
<el-button type="primary" @click="changePhone">更改</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<el-dialog
|
||||
v-model="changeEmailFlag"
|
||||
title="绑定邮箱"
|
||||
width="600px"
|
||||
>
|
||||
<el-dialog v-model="changeEmailFlag" title="绑定邮箱" width="600px">
|
||||
<el-form :model="emailForm">
|
||||
<el-form-item
|
||||
label="邮箱"
|
||||
label-width="120px"
|
||||
>
|
||||
<el-input
|
||||
v-model="emailForm.email"
|
||||
placeholder="请输入邮箱"
|
||||
autocomplete="off"
|
||||
/>
|
||||
<el-form-item label="邮箱" label-width="120px">
|
||||
<el-input v-model="emailForm.email" placeholder="请输入邮箱" autocomplete="off" />
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
label="验证码"
|
||||
label-width="120px"
|
||||
>
|
||||
<el-form-item label="验证码" label-width="120px">
|
||||
<div class="flex w-full gap-4">
|
||||
<el-input
|
||||
v-model="emailForm.code"
|
||||
class="flex-1"
|
||||
placeholder="请自行设计邮件服务,此处为模拟随便写"
|
||||
autocomplete="off"
|
||||
style="width:300px"
|
||||
/>
|
||||
<el-button
|
||||
type="primary"
|
||||
:disabled="emailTime>0"
|
||||
@click="getEmailCode"
|
||||
>{{ emailTime>0?`(${emailTime}s)后重新获取`:'获取验证码' }}</el-button>
|
||||
<el-input v-model="emailForm.code" class="flex-1" placeholder="请自行设计邮件服务,此处为模拟随便写" autocomplete="off"
|
||||
style="width:300px" />
|
||||
<el-button type="primary" :disabled="emailTime > 0" @click="getEmailCode">{{
|
||||
emailTime > 0 ? `(${emailTime}s)后重新获取` : '获取验证码' }}</el-button>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button
|
||||
|
||||
@click="closeChangeEmail"
|
||||
>取消</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
|
||||
@click="changeEmail"
|
||||
>更改</el-button>
|
||||
<el-button @click="closeChangeEmail">取消</el-button>
|
||||
<el-button type="primary" @click="changeEmail">更改</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
|
@ -453,6 +326,7 @@ const changeEmail = async() => {
|
|||
<style lang="scss">
|
||||
.borderd {
|
||||
@apply border-b-2 border-solid border-gray-100 border-t-0 border-r-0 border-l-0;
|
||||
|
||||
&:last-child {
|
||||
@apply border-b-0;
|
||||
}
|
||||
|
|
@ -461,5 +335,4 @@ const changeEmail = async() => {
|
|||
.info-list {
|
||||
@apply w-full whitespace-nowrap overflow-hidden text-ellipsis py-3 text-lg text-gray-700
|
||||
}
|
||||
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,28 +1,14 @@
|
|||
<template>
|
||||
<div>
|
||||
<el-select
|
||||
v-model="metaData.icon"
|
||||
clearable
|
||||
filterable
|
||||
placeholder="请选择"
|
||||
>
|
||||
<el-select v-model="metaData.icon" clearable filterable placeholder="请选择">
|
||||
<template #prefix>
|
||||
<el-icon>
|
||||
<component :is="metaData.icon" />
|
||||
</el-icon>
|
||||
</template>
|
||||
<el-option
|
||||
v-for="item in options"
|
||||
:key="item.key"
|
||||
class="select__option_item"
|
||||
:label="item.key"
|
||||
:value="item.key"
|
||||
>
|
||||
<span
|
||||
class="gva-icon"
|
||||
style=" padding: 3px 0 0; "
|
||||
:class="item.label"
|
||||
>
|
||||
<el-option v-for="item in options" :key="item.key" class="select__option_item" :label="item.key"
|
||||
:value="item.key">
|
||||
<span class="gva-icon" style=" padding: 3px 0 0; " :class="item.label">
|
||||
<el-icon>
|
||||
<component :is="item.label" />
|
||||
</el-icon>
|
||||
|
|
|
|||
|
|
@ -2,45 +2,20 @@
|
|||
<div>
|
||||
<div class="gva-table-box">
|
||||
<div class="gva-btn-list">
|
||||
<el-button
|
||||
type="primary"
|
||||
icon="plus"
|
||||
@click="addMenu('0')"
|
||||
>新增根菜单</el-button>
|
||||
<el-button type="primary" icon="plus" @click="addMenu('0')">新增根菜单</el-button>
|
||||
</div>
|
||||
|
||||
<!-- 由于此处菜单跟左侧列表一一对应所以不需要分页 pageSize默认999 -->
|
||||
<el-table
|
||||
:data="tableData"
|
||||
row-key="ID"
|
||||
>
|
||||
<el-table-column
|
||||
align="left"
|
||||
label="ID"
|
||||
min-width="100"
|
||||
prop="ID"
|
||||
/>
|
||||
<el-table-column
|
||||
align="left"
|
||||
label="展示名称"
|
||||
min-width="120"
|
||||
prop="authorityName"
|
||||
>
|
||||
<el-table :data="tableData" row-key="ID">
|
||||
<el-table-column align="left" label="ID" min-width="100" prop="ID" />
|
||||
<el-table-column align="left" label="展示名称" min-width="180" prop="authorityName">
|
||||
<template #default="scope">
|
||||
<span>{{ scope.row.meta.title }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
align="left"
|
||||
label="图标"
|
||||
min-width="140"
|
||||
prop="authorityName"
|
||||
>
|
||||
<el-table-column align="left" label="图标" min-width="180" prop="authorityName">
|
||||
<template #default="scope">
|
||||
<div
|
||||
v-if="scope.row.meta.icon"
|
||||
class="icon-column"
|
||||
>
|
||||
<div v-if="scope.row.meta.icon" class="icon-column">
|
||||
<el-icon>
|
||||
<component :is="scope.row.meta.icon" />
|
||||
</el-icon>
|
||||
|
|
@ -48,353 +23,136 @@
|
|||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
align="left"
|
||||
label="路由Name"
|
||||
show-overflow-tooltip
|
||||
min-width="160"
|
||||
prop="name"
|
||||
/>
|
||||
<el-table-column
|
||||
align="left"
|
||||
label="路由Path"
|
||||
show-overflow-tooltip
|
||||
min-width="160"
|
||||
prop="path"
|
||||
/>
|
||||
<el-table-column
|
||||
align="left"
|
||||
label="是否隐藏"
|
||||
min-width="100"
|
||||
prop="hidden"
|
||||
>
|
||||
<el-table-column align="left" label="路由Name" show-overflow-tooltip min-width="160" prop="name" />
|
||||
<el-table-column align="left" label="路由Path" show-overflow-tooltip min-width="160" prop="path" />
|
||||
<el-table-column align="left" label="是否隐藏" min-width="100" prop="hidden">
|
||||
<template #default="scope">
|
||||
<span>{{ scope.row.hidden ? "隐藏" : "显示" }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
align="left"
|
||||
label="父节点"
|
||||
min-width="90"
|
||||
prop="parentId"
|
||||
/>
|
||||
<el-table-column
|
||||
align="left"
|
||||
label="排序"
|
||||
min-width="70"
|
||||
prop="sort"
|
||||
/>
|
||||
<el-table-column
|
||||
align="left"
|
||||
label="文件路径"
|
||||
min-width="360"
|
||||
prop="component"
|
||||
/>
|
||||
<el-table-column
|
||||
align="left"
|
||||
fixed="right"
|
||||
label="操作"
|
||||
width="300"
|
||||
>
|
||||
<el-table-column align="left" label="父节点" min-width="90" prop="parentId" />
|
||||
<el-table-column align="left" label="排序" min-width="70" prop="sort" />
|
||||
<el-table-column align="left" label="文件路径" min-width="360" prop="component" />
|
||||
<el-table-column align="left" fixed="right" label="操作" width="300">
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
type="primary"
|
||||
link
|
||||
icon="plus"
|
||||
@click="addMenu(scope.row.ID)"
|
||||
>添加子菜单</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
link
|
||||
icon="edit"
|
||||
@click="editMenu(scope.row.ID)"
|
||||
>编辑</el-button>
|
||||
<el-button
|
||||
|
||||
type="primary"
|
||||
link
|
||||
icon="delete"
|
||||
@click="deleteMenu(scope.row.ID)"
|
||||
>删除</el-button>
|
||||
<el-button type="primary" link icon="plus" @click="addMenu(scope.row.ID)">添加子菜单</el-button>
|
||||
<el-button type="primary" link icon="edit" @click="editMenu(scope.row.ID)">编辑</el-button>
|
||||
<el-button type="primary" link icon="delete" @click="deleteMenu(scope.row.ID)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
<el-dialog
|
||||
v-model="dialogFormVisible"
|
||||
:before-close="handleClose"
|
||||
:title="dialogTitle"
|
||||
>
|
||||
<el-dialog v-model="dialogFormVisible" :before-close="handleClose" :title="dialogTitle">
|
||||
<warning-bar title="新增菜单,需要在角色管理内配置权限才可使用" />
|
||||
<el-form
|
||||
v-if="dialogFormVisible"
|
||||
ref="menuForm"
|
||||
:inline="true"
|
||||
:model="form"
|
||||
:rules="rules"
|
||||
label-position="top"
|
||||
label-width="85px"
|
||||
>
|
||||
<el-form-item
|
||||
label="路由Name"
|
||||
prop="path"
|
||||
style="width:30%"
|
||||
>
|
||||
<el-input
|
||||
v-model="form.name"
|
||||
autocomplete="off"
|
||||
placeholder="唯一英文字符串"
|
||||
@change="changeName"
|
||||
/>
|
||||
<el-form v-if="dialogFormVisible" ref="menuForm" :inline="true" :model="form" :rules="rules" label-position="top"
|
||||
label-width="85px">
|
||||
<el-form-item label="路由Name" prop="path" style="width:30%">
|
||||
<el-input v-model="form.name" autocomplete="off" placeholder="唯一英文字符串" @change="changeName" />
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
prop="path"
|
||||
style="width:30%"
|
||||
>
|
||||
<el-form-item prop="path" style="width:30%">
|
||||
<template #label>
|
||||
<span style="display: inline-flex;align-items: center;">
|
||||
<span>路由Path</span>
|
||||
<el-checkbox
|
||||
v-model="checkFlag"
|
||||
style="margin-left:12px;height: auto"
|
||||
>添加参数</el-checkbox>
|
||||
<el-checkbox v-model="checkFlag" style="margin-left:12px;height: auto">添加参数</el-checkbox>
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<el-input
|
||||
v-model="form.path"
|
||||
:disabled="!checkFlag"
|
||||
autocomplete="off"
|
||||
placeholder="建议只在后方拼接参数"
|
||||
/>
|
||||
<el-input v-model="form.path" :disabled="!checkFlag" autocomplete="off" placeholder="建议只在后方拼接参数" />
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
label="是否隐藏"
|
||||
style="width:30%"
|
||||
>
|
||||
<el-select
|
||||
v-model="form.hidden"
|
||||
placeholder="是否在列表隐藏"
|
||||
>
|
||||
<el-option
|
||||
:value="false"
|
||||
label="否"
|
||||
/>
|
||||
<el-option
|
||||
:value="true"
|
||||
label="是"
|
||||
/>
|
||||
<el-form-item label="是否隐藏" style="width:30%">
|
||||
<el-select v-model="form.hidden" placeholder="是否在列表隐藏">
|
||||
<el-option :value="false" label="否" />
|
||||
<el-option :value="true" label="是" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
label="父节点ID"
|
||||
style="width:30%"
|
||||
>
|
||||
<el-cascader
|
||||
v-model="form.parentId"
|
||||
style="width:100%"
|
||||
:disabled="!isEdit"
|
||||
:options="menuOption"
|
||||
<el-form-item label="父节点ID" style="width:30%">
|
||||
<el-cascader v-model="form.parentId" style="width:100%" :disabled="!isEdit" :options="menuOption"
|
||||
:props="{ checkStrictly: true, label: 'title', value: 'ID', disabled: 'disabled', emitPath: false }"
|
||||
:show-all-levels="false"
|
||||
filterable
|
||||
/>
|
||||
:show-all-levels="false" filterable />
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
label="文件路径"
|
||||
prop="component"
|
||||
style="width:60%"
|
||||
>
|
||||
<el-input
|
||||
v-model="form.component"
|
||||
autocomplete="off"
|
||||
placeholder="页面:view/xxx/xx.vue 插件:plugin/xx/xx.vue"
|
||||
@blur="fmtComponent"
|
||||
/>
|
||||
<el-form-item label="文件路径" prop="component" style="width:60%">
|
||||
<el-input v-model="form.component" autocomplete="off" placeholder="页面:view/xxx/xx.vue 插件:plugin/xx/xx.vue"
|
||||
@blur="fmtComponent" />
|
||||
<span style="font-size:12px;margin-right:12px;">如果菜单包含子菜单,请创建router-view二级路由页面或者</span><el-button
|
||||
style="margin-top:4px"
|
||||
@click="form.component = 'view/routerHolder.vue'"
|
||||
>点我设置</el-button>
|
||||
style="margin-top:4px" @click="form.component = 'view/routerHolder.vue'">点我设置</el-button>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
label="展示名称"
|
||||
prop="meta.title"
|
||||
style="width:30%"
|
||||
>
|
||||
<el-input
|
||||
v-model="form.meta.title"
|
||||
autocomplete="off"
|
||||
/>
|
||||
<el-form-item label="展示名称" prop="meta.title" style="width:30%">
|
||||
<el-input v-model="form.meta.title" autocomplete="off" />
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
label="图标"
|
||||
prop="meta.icon"
|
||||
style="width:30%"
|
||||
>
|
||||
<icon
|
||||
:meta="form.meta"
|
||||
style="width:100%"
|
||||
/>
|
||||
<el-form-item label="图标" prop="meta.icon" style="width:30%">
|
||||
<icon :meta="form.meta" style="width:100%" />
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
label="排序标记"
|
||||
prop="sort"
|
||||
style="width:30%"
|
||||
>
|
||||
<el-input
|
||||
v-model.number="form.sort"
|
||||
autocomplete="off"
|
||||
/>
|
||||
<el-form-item label="排序标记" prop="sort" style="width:30%">
|
||||
<el-input v-model.number="form.sort" autocomplete="off" />
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
prop="meta.activeName"
|
||||
style="width:30%"
|
||||
>
|
||||
<el-form-item prop="meta.activeName" style="width:30%">
|
||||
<template #label>
|
||||
<div>
|
||||
<span> 高亮菜单 </span>
|
||||
<el-tooltip
|
||||
content="注:当到达此路由时候,指定左侧菜单指定name会处于活跃状态(亮起),可为空,为空则为本路由Name。"
|
||||
placement="top"
|
||||
effect="light"
|
||||
>
|
||||
<el-icon><QuestionFilled /></el-icon>
|
||||
<el-tooltip content="注:当到达此路由时候,指定左侧菜单指定name会处于活跃状态(亮起),可为空,为空则为本路由Name。" placement="top" effect="light">
|
||||
<el-icon>
|
||||
<QuestionFilled />
|
||||
</el-icon>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</template>
|
||||
<el-input
|
||||
v-model="form.meta.activeName"
|
||||
:placeholder="form.name"
|
||||
autocomplete="off"
|
||||
/>
|
||||
<el-input v-model="form.meta.activeName" :placeholder="form.name" autocomplete="off" />
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
label="KeepAlive"
|
||||
prop="meta.keepAlive"
|
||||
style="width:30%"
|
||||
>
|
||||
<el-select
|
||||
v-model="form.meta.keepAlive"
|
||||
style="width:100%"
|
||||
placeholder="是否keepAlive缓存页面"
|
||||
>
|
||||
<el-option
|
||||
:value="false"
|
||||
label="否"
|
||||
/>
|
||||
<el-option
|
||||
:value="true"
|
||||
label="是"
|
||||
/>
|
||||
<el-form-item label="KeepAlive" prop="meta.keepAlive" style="width:30%">
|
||||
<el-select v-model="form.meta.keepAlive" style="width:100%" placeholder="是否keepAlive缓存页面">
|
||||
<el-option :value="false" label="否" />
|
||||
<el-option :value="true" label="是" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
label="CloseTab"
|
||||
prop="meta.closeTab"
|
||||
style="width:30%"
|
||||
>
|
||||
<el-select
|
||||
v-model="form.meta.closeTab"
|
||||
style="width:100%"
|
||||
placeholder="是否自动关闭tab"
|
||||
>
|
||||
<el-option
|
||||
:value="false"
|
||||
label="否"
|
||||
/>
|
||||
<el-option
|
||||
:value="true"
|
||||
label="是"
|
||||
/>
|
||||
<el-form-item label="CloseTab" prop="meta.closeTab" style="width:30%">
|
||||
<el-select v-model="form.meta.closeTab" style="width:100%" placeholder="是否自动关闭tab">
|
||||
<el-option :value="false" label="否" />
|
||||
<el-option :value="true" label="是" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item style="width:30%">
|
||||
<template #label>
|
||||
<div>
|
||||
<span> 是否为基础页面 </span>
|
||||
<el-tooltip
|
||||
content="此项选择为是,则不会展示左侧菜单以及顶部信息。"
|
||||
placement="top"
|
||||
effect="light"
|
||||
>
|
||||
<el-icon><QuestionFilled /></el-icon>
|
||||
<el-tooltip content="此项选择为是,则不会展示左侧菜单以及顶部信息。" placement="top" effect="light">
|
||||
<el-icon>
|
||||
<QuestionFilled />
|
||||
</el-icon>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<el-select
|
||||
v-model="form.meta.defaultMenu"
|
||||
style="width:100%"
|
||||
placeholder="是否为基础页面"
|
||||
>
|
||||
<el-option
|
||||
:value="false"
|
||||
label="否"
|
||||
/>
|
||||
<el-option
|
||||
:value="true"
|
||||
label="是"
|
||||
/>
|
||||
<el-select v-model="form.meta.defaultMenu" style="width:100%" placeholder="是否为基础页面">
|
||||
<el-option :value="false" label="否" />
|
||||
<el-option :value="true" label="是" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div>
|
||||
<div class="flex items-center gap-2">
|
||||
<el-button
|
||||
type="primary"
|
||||
icon="edit"
|
||||
@click="addParameter(form)"
|
||||
>新增菜单参数</el-button>
|
||||
<el-icon
|
||||
class="cursor-pointer"
|
||||
@click="toDoc('https://www.bilibili.com/video/BV1kv4y1g7nT?p=9&vd_source=f2640257c21e3b547a790461ed94875e')"
|
||||
><VideoCameraFilled /></el-icon>
|
||||
<el-button type="primary" icon="edit" @click="addParameter(form)">新增菜单参数</el-button>
|
||||
<el-icon class="cursor-pointer"
|
||||
@click="toDoc('https://www.bilibili.com/video/BV1kv4y1g7nT?p=9&vd_source=f2640257c21e3b547a790461ed94875e')">
|
||||
<VideoCameraFilled />
|
||||
</el-icon>
|
||||
</div>
|
||||
<el-table
|
||||
:data="form.parameters"
|
||||
style="width: 100%;margin-top: 12px;"
|
||||
>
|
||||
<el-table-column
|
||||
align="left"
|
||||
prop="type"
|
||||
label="参数类型"
|
||||
width="180"
|
||||
>
|
||||
<el-table :data="form.parameters" style="width: 100%;margin-top: 12px;">
|
||||
<el-table-column align="left" prop="type" label="参数类型" width="180">
|
||||
<template #default="scope">
|
||||
<el-select
|
||||
v-model="scope.row.type"
|
||||
placeholder="请选择"
|
||||
>
|
||||
<el-option
|
||||
key="query"
|
||||
value="query"
|
||||
label="query"
|
||||
/>
|
||||
<el-option
|
||||
key="params"
|
||||
value="params"
|
||||
label="params"
|
||||
/>
|
||||
<el-select v-model="scope.row.type" placeholder="请选择">
|
||||
<el-option key="query" value="query" label="query" />
|
||||
<el-option key="params" value="params" label="params" />
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
align="left"
|
||||
prop="key"
|
||||
label="参数key"
|
||||
width="180"
|
||||
>
|
||||
<el-table-column align="left" prop="key" label="参数key" width="180">
|
||||
<template #default="scope">
|
||||
<div>
|
||||
<el-input v-model="scope.row.key" />
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
align="left"
|
||||
prop="value"
|
||||
label="参数值"
|
||||
>
|
||||
<el-table-column align="left" prop="value" label="参数值">
|
||||
<template #default="scope">
|
||||
<div>
|
||||
<el-input v-model="scope.row.value" />
|
||||
|
|
@ -404,52 +162,31 @@
|
|||
<el-table-column align="left">
|
||||
<template #default="scope">
|
||||
<div>
|
||||
<el-button
|
||||
type="danger"
|
||||
|
||||
icon="delete"
|
||||
@click="deleteParameter(form.parameters,scope.$index)"
|
||||
>删除</el-button>
|
||||
<el-button type="danger" icon="delete"
|
||||
@click="deleteParameter(form.parameters, scope.$index)">删除</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<div class="flex items-center gap-2 mt-3">
|
||||
<el-button
|
||||
type="primary"
|
||||
icon="edit"
|
||||
@click="addBtn(form)"
|
||||
>新增可控按钮
|
||||
<el-button type="primary" icon="edit" @click="addBtn(form)">新增可控按钮
|
||||
</el-button>
|
||||
<el-icon
|
||||
class="cursor-pointer"
|
||||
@click="toDoc('https://www.bilibili.com/video/BV1kv4y1g7nT?p=11&vd_source=f2640257c21e3b547a790461ed94875e')"
|
||||
><VideoCameraFilled /></el-icon>
|
||||
<el-icon class="cursor-pointer"
|
||||
@click="toDoc('https://www.bilibili.com/video/BV1kv4y1g7nT?p=11&vd_source=f2640257c21e3b547a790461ed94875e')">
|
||||
<VideoCameraFilled />
|
||||
</el-icon>
|
||||
</div>
|
||||
|
||||
<el-table
|
||||
:data="form.menuBtn"
|
||||
style="width: 100%;margin-top: 12px;"
|
||||
>
|
||||
<el-table-column
|
||||
align="left"
|
||||
prop="name"
|
||||
label="按钮名称"
|
||||
width="180"
|
||||
>
|
||||
<el-table :data="form.menuBtn" style="width: 100%;margin-top: 12px;">
|
||||
<el-table-column align="left" prop="name" label="按钮名称" width="180">
|
||||
<template #default="scope">
|
||||
<div>
|
||||
<el-input v-model="scope.row.name" />
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
align="left"
|
||||
prop="name"
|
||||
label="备注"
|
||||
width="180"
|
||||
>
|
||||
<el-table-column align="left" prop="name" label="备注" width="180">
|
||||
<template #default="scope">
|
||||
<div>
|
||||
<el-input v-model="scope.row.desc" />
|
||||
|
|
@ -459,12 +196,7 @@
|
|||
<el-table-column align="left">
|
||||
<template #default="scope">
|
||||
<div>
|
||||
<el-button
|
||||
type="danger"
|
||||
|
||||
icon="delete"
|
||||
@click="deleteBtn(form.menuBtn,scope.$index)"
|
||||
>删除</el-button>
|
||||
<el-button type="danger" icon="delete" @click="deleteBtn(form.menuBtn, scope.$index)">删除</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
|
@ -473,10 +205,7 @@
|
|||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button @click="closeDialog">取 消</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="enterDialog"
|
||||
>确 定</el-button>
|
||||
<el-button type="primary" @click="enterDialog">确 定</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
|
@ -749,9 +478,11 @@ const editMenu = async(id) => {
|
|||
.warning {
|
||||
color: #dc143c;
|
||||
}
|
||||
|
||||
.icon-column {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.el-icon {
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -102,14 +102,16 @@ export default ({
|
|||
fullImportPlugin()
|
||||
)
|
||||
} else {
|
||||
config.plugins.push(AutoImport({
|
||||
config.plugins.push(
|
||||
AutoImport({
|
||||
resolvers: [ElementPlusResolver()]
|
||||
}),
|
||||
Components({
|
||||
resolvers: [ElementPlusResolver({
|
||||
importStyle: 'sass'
|
||||
})]
|
||||
}))
|
||||
})
|
||||
)
|
||||
}
|
||||
return config
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue