feat: 优化素材页面

master
绝弹 2024-01-09 22:34:36 +08:00
parent 40eeb6899a
commit 9b15be521e
9 changed files with 229 additions and 124 deletions

View File

@ -4,10 +4,19 @@
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="./favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>%VITE_TITLE% - %VITE_SUBTITLE%</title>
<title>%VITE_TITLE% | %VITE_SUBTITLE%</title>
</head>
<body>
<div id="app" class="dark:bg-slate-900 dark:text-slate-200">
<div class="loading">
<img
src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz48c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHN0eWxlPSJtYXJnaW46IGF1dG87IGJhY2tncm91bmQ6IHJnYigyNTUsIDI1NSwgMjU1KTsgZGlzcGxheTogYmxvY2s7IHNoYXBlLXJlbmRlcmluZzogYXV0bzsiIHdpZHRoPSIyMDBweCIgaGVpZ2h0PSIyMDBweCIgdmlld0JveD0iMCAwIDEwMCAxMDAiIHByZXNlcnZlQXNwZWN0UmF0aW89InhNaWRZTWlkIj48ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSg1MCA1MCkiPjxnPjxhbmltYXRlVHJhbnNmb3JtIGF0dHJpYnV0ZU5hbWU9InRyYW5zZm9ybSIgdHlwZT0icm90YXRlIiB2YWx1ZXM9IjA7NDUiIGtleVRpbWVzPSIwOzEiIGR1cj0iMC4ycyIgcmVwZWF0Q291bnQ9ImluZGVmaW5pdGUiPjwvYW5pbWF0ZVRyYW5zZm9ybT48cGF0aCBkPSJNMjkuNDkxNTI0MjA2MTE3MjU1IC01LjUgTDM3LjQ5MTUyNDIwNjExNzI1NSAtNS41IEwzNy40OTE1MjQyMDYxMTcyNTUgNS41IEwyOS40OTE1MjQyMDYxMTcyNTUgNS41IEEzMCAzMCAwIDAgMSAyNC43NDI3NDQwNTAxOTg3MzggMTYuOTY0NTY5NDU3MTQ2NzEyIEwyNC43NDI3NDQwNTAxOTg3MzggMTYuOTY0NTY5NDU3MTQ2NzEyIEwzMC4zOTk1OTgyOTk2OTExMTcgMjIuNjIxNDIzNzA2NjM5MDkyIEwyMi42MjE0MjM3MDY2MzkwOTYgMzAuMzk5NTk4Mjk5NjkxMTE0IEwxNi45NjQ1Njk0NTcxNDY3MTYgMjQuNzQyNzQ0MDUwMTk4NzM0IEEzMCAzMCAwIDAgMSA1LjUgMjkuNDkxNTI0MjA2MTE3MjU1IEw1LjUgMjkuNDkxNTI0MjA2MTE3MjU1IEw1LjUgMzcuNDkxNTI0MjA2MTE3MjU1IEwtNS40OTk5OTk5OTk5OTk5OTcgMzcuNDkxNTI0MjA2MTE3MjU1IEwtNS40OTk5OTk5OTk5OTk5OTcgMjkuNDkxNTI0MjA2MTE3MjU1IEEzMCAzMCAwIDAgMSAtMTYuOTY0NTY5NDU3MTQ2NzA1IDI0Ljc0Mjc0NDA1MDE5ODczOCBMLTE2Ljk2NDU2OTQ1NzE0NjcwNSAyNC43NDI3NDQwNTAxOTg3MzggTC0yMi42MjE0MjM3MDY2MzkwODUgMzAuMzk5NTk4Mjk5NjkxMTE3IEwtMzAuMzk5NTk4Mjk5NjkxMTE3IDIyLjYyMTQyMzcwNjYzOTA5MiBMLTI0Ljc0Mjc0NDA1MDE5ODczOCAxNi45NjQ1Njk0NTcxNDY3MTIgQTMwIDMwIDAgMCAxIC0yOS40OTE1MjQyMDYxMTcyNTUgNS41MDAwMDAwMDAwMDAwMDkgTC0yOS40OTE1MjQyMDYxMTcyNTUgNS41MDAwMDAwMDAwMDAwMDkgTC0zNy40OTE1MjQyMDYxMTcyNTUgNS41MDAwMDAwMDAwMDAwMSBMLTM3LjQ5MTUyNDIwNjExNzI1NSAtNS41MDAwMDAwMDAwMDAwMDEgTC0yOS40OTE1MjQyMDYxMTcyNTUgLTUuNTAwMDAwMDAwMDAwMDAyIEEzMCAzMCAwIDAgMSAtMjQuNzQyNzQ0MDUwMTk4NzM4IC0xNi45NjQ1Njk0NTcxNDY3MDUgTC0yNC43NDI3NDQwNTAxOTg3MzggLTE2Ljk2NDU2OTQ1NzE0NjcwNSBMLTMwLjM5OTU5ODI5OTY5MTExNyAtMjIuNjIxNDIzNzA2NjM5MDg1IEwtMjIuNjIxNDIzNzA2NjM5MDkyIC0zMC4zOTk1OTgyOTk2OTExMTcgTC0xNi45NjQ1Njk0NTcxNDY3MTIgLTI0Ljc0Mjc0NDA1MDE5ODczOCBBMzAgMzAgMCAwIDEgLTUuNTAwMDAwMDAwMDAwMDExIC0yOS40OTE1MjQyMDYxMTcyNTUgTC01LjUwMDAwMDAwMDAwMDAxMSAtMjkuNDkxNTI0MjA2MTE3MjU1IEwtNS41MDAwMDAwMDAwMDAwMTIgLTM3LjQ5MTUyNDIwNjExNzI1NSBMNS40OTk5OTk5OTk5OTk5OTggLTM3LjQ5MTUyNDIwNjExNzI1NSBMNS41IC0yOS40OTE1MjQyMDYxMTcyNTUgQTMwIDMwIDAgMCAxIDE2Ljk2NDU2OTQ1NzE0NjcwMiAtMjQuNzQyNzQ0MDUwMTk4NzQgTDE2Ljk2NDU2OTQ1NzE0NjcwMiAtMjQuNzQyNzQ0MDUwMTk4NzQgTDIyLjYyMTQyMzcwNjYzOTA4IC0zMC4zOTk1OTgyOTk2OTExMiBMMzAuMzk5NTk4Mjk5NjkxMTE3IC0yMi42MjE0MjM3MDY2MzkxIEwyNC43NDI3NDQwNTAxOTg3MzggLTE2Ljk2NDU2OTQ1NzE0NjcxNiBBMzAgMzAgMCAwIDEgMjkuNDkxNTI0MjA2MTE3MjU1IC01LjUwMDAwMDAwMDAwMDAxMyBNMCAtMjBBMjAgMjAgMCAxIDAgMCAyMCBBMjAgMjAgMCAxIDAgMCAtMjAiIGZpbGw9IiMwOWYiPjwvcGF0aD48L2c+PC9nPjwvc3ZnPgo="
alt="loading"
class="loading-image"
/>
<h1 class="loading-title">欢迎访问%VITE_TITLE%</h1>
<div class="loading-tip">资源加载中, 请稍等...</div>
</div>
<style>
html,
body {
@ -17,8 +26,8 @@
height: 100%;
overflow: hidden;
font-size: 14px;
font-family: Inter, "-apple-system", BlinkMacSystemFont, "PingFang SC", "Hiragino Sans GB", "noto sans",
"Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif;
font-family: Inter, '-apple-system', BlinkMacSystemFont, 'PingFang SC', 'Hiragino Sans GB', 'noto sans',
'Microsoft YaHei', 'Helvetica Neue', Helvetica, Arial, sans-serif;
}
#app {
width: 100%;
@ -47,18 +56,9 @@
.loading-tip {
margin-top: 12px;
line-height: 1;
color: #888;
color: #889;
}
</style>
<div class="loading">
<img
src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz48c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHN0eWxlPSJtYXJnaW46IGF1dG87IGJhY2tncm91bmQ6IHJnYigyNTUsIDI1NSwgMjU1KTsgZGlzcGxheTogYmxvY2s7IHNoYXBlLXJlbmRlcmluZzogYXV0bzsiIHdpZHRoPSIyMDBweCIgaGVpZ2h0PSIyMDBweCIgdmlld0JveD0iMCAwIDEwMCAxMDAiIHByZXNlcnZlQXNwZWN0UmF0aW89InhNaWRZTWlkIj48ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSg1MCA1MCkiPjxnPjxhbmltYXRlVHJhbnNmb3JtIGF0dHJpYnV0ZU5hbWU9InRyYW5zZm9ybSIgdHlwZT0icm90YXRlIiB2YWx1ZXM9IjA7NDUiIGtleVRpbWVzPSIwOzEiIGR1cj0iMC4ycyIgcmVwZWF0Q291bnQ9ImluZGVmaW5pdGUiPjwvYW5pbWF0ZVRyYW5zZm9ybT48cGF0aCBkPSJNMjkuNDkxNTI0MjA2MTE3MjU1IC01LjUgTDM3LjQ5MTUyNDIwNjExNzI1NSAtNS41IEwzNy40OTE1MjQyMDYxMTcyNTUgNS41IEwyOS40OTE1MjQyMDYxMTcyNTUgNS41IEEzMCAzMCAwIDAgMSAyNC43NDI3NDQwNTAxOTg3MzggMTYuOTY0NTY5NDU3MTQ2NzEyIEwyNC43NDI3NDQwNTAxOTg3MzggMTYuOTY0NTY5NDU3MTQ2NzEyIEwzMC4zOTk1OTgyOTk2OTExMTcgMjIuNjIxNDIzNzA2NjM5MDkyIEwyMi42MjE0MjM3MDY2MzkwOTYgMzAuMzk5NTk4Mjk5NjkxMTE0IEwxNi45NjQ1Njk0NTcxNDY3MTYgMjQuNzQyNzQ0MDUwMTk4NzM0IEEzMCAzMCAwIDAgMSA1LjUgMjkuNDkxNTI0MjA2MTE3MjU1IEw1LjUgMjkuNDkxNTI0MjA2MTE3MjU1IEw1LjUgMzcuNDkxNTI0MjA2MTE3MjU1IEwtNS40OTk5OTk5OTk5OTk5OTcgMzcuNDkxNTI0MjA2MTE3MjU1IEwtNS40OTk5OTk5OTk5OTk5OTcgMjkuNDkxNTI0MjA2MTE3MjU1IEEzMCAzMCAwIDAgMSAtMTYuOTY0NTY5NDU3MTQ2NzA1IDI0Ljc0Mjc0NDA1MDE5ODczOCBMLTE2Ljk2NDU2OTQ1NzE0NjcwNSAyNC43NDI3NDQwNTAxOTg3MzggTC0yMi42MjE0MjM3MDY2MzkwODUgMzAuMzk5NTk4Mjk5NjkxMTE3IEwtMzAuMzk5NTk4Mjk5NjkxMTE3IDIyLjYyMTQyMzcwNjYzOTA5MiBMLTI0Ljc0Mjc0NDA1MDE5ODczOCAxNi45NjQ1Njk0NTcxNDY3MTIgQTMwIDMwIDAgMCAxIC0yOS40OTE1MjQyMDYxMTcyNTUgNS41MDAwMDAwMDAwMDAwMDkgTC0yOS40OTE1MjQyMDYxMTcyNTUgNS41MDAwMDAwMDAwMDAwMDkgTC0zNy40OTE1MjQyMDYxMTcyNTUgNS41MDAwMDAwMDAwMDAwMSBMLTM3LjQ5MTUyNDIwNjExNzI1NSAtNS41MDAwMDAwMDAwMDAwMDEgTC0yOS40OTE1MjQyMDYxMTcyNTUgLTUuNTAwMDAwMDAwMDAwMDAyIEEzMCAzMCAwIDAgMSAtMjQuNzQyNzQ0MDUwMTk4NzM4IC0xNi45NjQ1Njk0NTcxNDY3MDUgTC0yNC43NDI3NDQwNTAxOTg3MzggLTE2Ljk2NDU2OTQ1NzE0NjcwNSBMLTMwLjM5OTU5ODI5OTY5MTExNyAtMjIuNjIxNDIzNzA2NjM5MDg1IEwtMjIuNjIxNDIzNzA2NjM5MDkyIC0zMC4zOTk1OTgyOTk2OTExMTcgTC0xNi45NjQ1Njk0NTcxNDY3MTIgLTI0Ljc0Mjc0NDA1MDE5ODczOCBBMzAgMzAgMCAwIDEgLTUuNTAwMDAwMDAwMDAwMDExIC0yOS40OTE1MjQyMDYxMTcyNTUgTC01LjUwMDAwMDAwMDAwMDAxMSAtMjkuNDkxNTI0MjA2MTE3MjU1IEwtNS41MDAwMDAwMDAwMDAwMTIgLTM3LjQ5MTUyNDIwNjExNzI1NSBMNS40OTk5OTk5OTk5OTk5OTggLTM3LjQ5MTUyNDIwNjExNzI1NSBMNS41IC0yOS40OTE1MjQyMDYxMTcyNTUgQTMwIDMwIDAgMCAxIDE2Ljk2NDU2OTQ1NzE0NjcwMiAtMjQuNzQyNzQ0MDUwMTk4NzQgTDE2Ljk2NDU2OTQ1NzE0NjcwMiAtMjQuNzQyNzQ0MDUwMTk4NzQgTDIyLjYyMTQyMzcwNjYzOTA4IC0zMC4zOTk1OTgyOTk2OTExMiBMMzAuMzk5NTk4Mjk5NjkxMTE3IC0yMi42MjE0MjM3MDY2MzkxIEwyNC43NDI3NDQwNTAxOTg3MzggLTE2Ljk2NDU2OTQ1NzE0NjcxNiBBMzAgMzAgMCAwIDEgMjkuNDkxNTI0MjA2MTE3MjU1IC01LjUwMDAwMDAwMDAwMDAxMyBNMCAtMjBBMjAgMjAgMCAxIDAgMCAyMCBBMjAgMjAgMCAxIDAgMCAtMjAiIGZpbGw9IiMwOWYiPjwvcGF0aD48L2c+PC9nPjwvc3ZnPgo="
alt="loading"
class="loading-image"
/>
<h1 class="loading-title">欢迎访问%VITE_TITLE%</h1>
<div class="loading-tip">资源加载中, 请稍等...</div>
</div>
</div>
<script type="module" src="/src/main.ts"></script>
</body>

View File

@ -9,8 +9,6 @@
title="上传文件"
title-align="start"
v-model:visible="visible"
mask-animation-name=""
modal-animation-name=""
:width="960"
:mask-closable="false"
:on-before-cancel="onBeforeCancel"
@ -45,11 +43,11 @@
</div>
</div>
<div class="h-[424px] border-t border-b border-zinc-100 mt-4">
<ul v-if="fileList.length" class="overflow-hidden p-0 m-0">
<div class="h-[424px] border-t border-b border-zinc-100 mt-2">
<ul v-if="fileList.length" class="h-full overflow-hidden p-0 m-0">
<a-scrollbar outer-class="h-full overflow-hidden" class="h-full overflow-auto pr-[20px] divide-y">
<li v-for="item in fileList" :key="item.uid" class="flex items-center gap-4 py-3">
<div class="text-4xl rounded pr-0.5 flex justify-center">
<li v-for="item in fileList" :key="item.uid" class="flex items-center gap-3 py-3">
<div class="text-3xl rounded pr-0.5 flex justify-center">
<i :class="getIcon(item.file?.type ?? 'video')"></i>
</div>
<div class="flex-1 overflow-hidden">
@ -59,10 +57,10 @@
<span class="text-xs text-gray-400 ml-2">{{ numeral(item.file?.size).format('0 b') }}</span>
</div>
<div v-show="item.status !== 'done'">
<a-link v-show="item.status === 'uploading'" @click="pauseItem(item)"></a-link>
<a-link v-show="item.status === 'error'" @click="retryItem(item)"></a-link>
<a-link v-show="item.status === 'uploading'" @click="pauseItem(item)"> </a-link>
<a-link v-show="item.status === 'error'" @click="retryItem(item)"> </a-link>
<a-link v-show="item.status === 'init' || item.status === 'error'" @click="removeItem(item)">
</a-link>
</div>
</div>
@ -70,19 +68,19 @@
<div class="flex items-center justify-between gap-2 text-gray-400 mt-1.5 text-xs">
<span class="text-xs">
<span v-if="item.status === 'init'">
<i class="icon-park-outline-hourglass-full"></i>
<i class="icon-park-outline-lightning"></i>
等待上传
</span>
<span v-else-if="item.status === 'uploading'" class="text-[rgb(var(--primary-6))]">
<i class="icon-park-outline-upload-one"></i>
<span v-else-if="item.status === 'uploading'">
<i class="icon-park-outline-upload-one text-blue-500"></i>
正在上传
</span>
<span v-else-if="item.status === 'done'" class="text-[rgb(var(--success-6))]">
<i class="icon-park-outline-check"></i>
<span v-else-if="item.status === 'done'">
<i class="icon-park-outline-check-one text-green-500"></i>
上传成功
</span>
<span v-else="item.status === 'error'" class="text-red-500">
<i class="icon-park-outline-close"></i>
<span v-else="item.status === 'error'" class="">
<i class="icon-park-outline-close-one text-red-500"></i>
上传失败
</span>
</span>
@ -135,22 +133,19 @@ const emit = defineEmits<{
(event: 'close', count: number): void;
}>();
interface FileInfo {
lastTime: number;
lastLoaded: number;
speed: number;
aspeed: number;
cost: number;
error: string;
}
const visible = ref(false);
const uploadRef = ref<UploadInstance | null>(null);
const fileList = ref<FileItem[]>([]);
const fileMap = reactive<
Map<
string,
{
lastTime: number;
lastLoaded: number;
speed: number;
aspeed: number;
cost: number;
error: string;
} | null
>
>(new Map());
const fileMap = reactive<Map<string, FileInfo | null>>(new Map());
const formatProgress = (item: FileItem, small?: boolean) => {
let percent = Math.floor((item.percent || 0) * 100);
@ -239,7 +234,6 @@ const onClose = () => {
const upload = (option: RequestOption) => {
const { fileItem, onError, onProgress, onSuccess } = option;
const source = axios.CancelToken.source();
if (!fileMap.has(fileItem.uid)) {
fileMap.set(fileItem.uid, {
lastTime: Date.now(),
@ -250,6 +244,7 @@ const upload = (option: RequestOption) => {
error: '网络异常',
});
}
const source = axios.CancelToken.source();
const item = fileMap.get(fileItem.uid)!;
const startTime = Date.now();
const data = { file: fileItem.file as any };

View File

@ -1,43 +1,39 @@
<template>
<BreadPage>
<template #content>
<a-tabs class="tabs-page">
<a-tab-pane key="1" title="全部素材">
<div class="overflow-hidden grid grid-cols-[auto_1fr] gap-2 m-4 mt-1">
<!-- <AnGroup class="bg-white p-4 w-[242px]" :current="current" @change="onCategoryChange"></AnGroup> -->
<div class="bg-white p-4">
<MaterialTable>
<template #action>
<AnUpload @success="() => tableRef?.refresh()"></AnUpload>
</template>
</MaterialTable>
<AnPreview v-model:visible="viewer.visible" :type="viewer.type" :url="viewer.url"></AnPreview>
</div>
</div>
</a-tab-pane>
<a-tab-pane key="2" title="分类管理">
<div class="overflow-hidden grid grid-cols-[auto_1fr] gap-2 m-4 mt-1">
<div class="bg-white p-4">
<AnCategory></AnCategory>
</div>
</div>
</a-tab-pane>
<a-tab-pane key="3" title="显示设置"></a-tab-pane>
</a-tabs>
</template>
</BreadPage>
<a-tabs class="tabs-page">
<a-tab-pane key="1" title="全部素材">
<div class="overflow-hidden grid grid-cols-[auto_1fr] gap-2 m-4 mt-0">
<!-- <AnGroup class="bg-white p-4 w-[242px]" :current="current" @change="onCategoryChange"></AnGroup> -->
<div class="bg-white p-4">
<MaterialTable>
<template #action>
<AnUpload @success="() => tableRef?.refresh()"></AnUpload>
</template>
</MaterialTable>
<AnPreview v-model:visible="viewer.visible" :type="viewer.type" :url="viewer.url"></AnPreview>
</div>
</div>
</a-tab-pane>
<a-tab-pane key="2" title="分类管理">
<div class="overflow-hidden grid grid-cols-[auto_1fr] gap-2 m-4 mt-0">
<div class="bg-white p-4">
<AnCategory></AnCategory>
</div>
</div>
</a-tab-pane>
<a-tab-pane key="3" title="素材设置"> </a-tab-pane>
</a-tabs>
</template>
<script setup lang="tsx">
import { FileCategory, api } from '@/api';
import { useCreateColumn, useTable, useTableDelete, useUpdateColumn } from '@/components/AnTable';
import { FileTypes } from '@/constants/file';
import { Message } from '@arco-design/web-vue';
import numeral from 'numeral';
import AnCategory from './components/AnCategory.vue';
import AnPreview from './components/AnPreview.vue';
import AnUpload from './components/AnUpload.vue';
import { getIcon } from './components/util';
import { FileTypes } from '@/constants/file';
const current = ref<FileCategory>();
const viewer = reactive({ visible: false, url: undefined, type: undefined });
@ -74,7 +70,7 @@ const {
dataIndex: 'name',
render: ({ record }) => {
return (
<div class="group flex items-center gap-4">
<div class="group flex items-center gap-3">
<div class="w-8 flex justify-center">
{record.mimetype.startsWith('image1') ? (
<a-avatar size={32} shape="square">
@ -92,30 +88,33 @@ const {
>
{record.name}
</span>
<span
{/* <span
class="inline-block w-5 text-xs text-gray-400 ml-0"
title="复制地址"
onClick={() => copyLink(record)}
>
<i class="hidden! group-hover:inline-block! icon-park-outline-copy hover:text-gray-700 cursor-pointer"></i>
</span>
</span> */}
</span>
<div class="h-5 inline-flex items-center text-xs text-gray-400 space-x-4">
{/* <div class="h-5 inline-flex items-center text-xs text-gray-400 space-x-4 ">
<span>
<i class="icon-park-outline-folder-close mr-1"></i>
{record.category?.name ?? '默认分类'}
</span>
</div>
</div> */}
</div>
</div>
);
},
},
{
title: '分类',
width: 150,
render: ({ record }) => record.category?.name ?? '默认分类',
},
{
title: '文件大小',
width: 100,
align: 'right',
render: ({ record }) => <span class="text-gray-500">{numeral(record.size).format('0 b')}</span>,
width: 150,
render: ({ record }) => numeral(record.size).format('0 b'),
},
useCreateColumn(),
useUpdateColumn(),
@ -206,7 +205,16 @@ const {
});
</script>
<style scoped></style>
<style lang="less" scoped>
.tabs-page {
display: grid;
grid-template-rows: auto 1fr;
height: 100%;
:deep(.arco-tabs-content) {
overflow: auto;
}
}
</style>
<route lang="json">
{

View File

@ -10,11 +10,11 @@
</div> -->
<div>
<div class="text-gray-500">
{{ item.title }}
</div>
<div class="text-lg mt-1.5">
{{ item.count }}
</div>
{{ item.title }}
</div>
<div class="text-lg mt-1.5">
{{ item.count }}
</div>
</div>
</div>
</div>
@ -30,9 +30,11 @@
<i class="icon-park-outline-delete text-xs"></i>
</div>
</div>
<div class="py-3 px-3 border border-dashed rounded-sm border-gray-400 text-gray-500 hover:bg-gray-100 cursor-pointer">
<div
class="py-3 px-3 border border-dashed rounded-sm border-gray-400 text-gray-500 hover:bg-gray-100 cursor-pointer"
>
<i class="icon-park-outline-add ml-2"></i>
添加服务
添加服务1
</div>
</div>
</div>
@ -47,7 +49,7 @@
</div>
</div>
</div>
<div class="bg-white py-4 px-5 mt-4">
<div class="bg-white py-4 px-5 mt-4">
<div class="flex items-center justify-between">
<span>公告</span>
<a-link>更多</a-link>
@ -55,7 +57,9 @@
<div class="flex justify-between gap-4 mt-4">
<ul class="list-none w-full m-0 p-0">
<li v-for="i in 8" class="w-full h-6 items-center overflow-hidden justify-between flex gap-2 mb-2">
<span class="flex-1 truncate hover:underline underline-offset-2 cursor-pointer">但是预测已加载的数据不足以</span>
<span class="flex-1 truncate hover:underline underline-offset-2 cursor-pointer"
>但是预测已加载的数据不足以</span
>
<span class="text-gray-400">3天前</span>
</li>
</ul>
@ -74,29 +78,39 @@ const stat = {
post: {
title: '文章',
count: 22,
icon: 'icon-park-outline-folder-close'
icon: 'icon-park-outline-folder-close',
},
material: {
title: '素材',
count: 119,
icon: 'icon-park-outline-folder-close'
icon: 'icon-park-outline-folder-close',
},
comment: {
title: '评论',
count: 1802,
icon: 'icon-park-outline-user'
icon: 'icon-park-outline-user',
},
user: {
title: '用户',
count: 98,
icon: 'icon-park-outline-user'
icon: 'icon-park-outline-user',
},
category: {
title: '分类',
count: 26,
icon: 'icon-park-outline-tag'
icon: 'icon-park-outline-tag',
},
};
</script>
<style scoped></style>
<route lang="json">
{
"meta": {
"sort": 1000,
"title": "概览",
"icon": "icon-park-outline-home"
}
}
</route>

View File

@ -8,7 +8,7 @@
<ani-group :current="current" @change="onTypeChange"></ani-group>
</div>
<div class="bg-white p-4">
<div :show-icon="false" class="rounded mb-3 bg-gray-100 px-4 py-3">
<div :show-icon="false" class="rounded mb-3 bg-gray-200 px-4 py-3">
<span class="text-base">
<i class="icon-park-outline-folder-close"></i>
{{ current?.name }}

View File

@ -41,24 +41,30 @@ const { component: MenuTable, tableRef } = useTable({
id = ` => ${record.code}`;
}
return (
<div class="flex items-center gap-1">
<a-tag bordered color={MenuTypes.fmt(record.type, 'color')}>
{{
default: () => MenuTypes.fmt(record.type),
}}
</a-tag>
<div class="flex-1 flex overflow-hidden ml-1">
<div class="flex-1">
<i class={`${record.icon} mr-1`}></i>
<span>{record.name ?? '无'}</span>
<span class="text-gray-400 text-xs truncate">{id}</span>
</div>
<a-switch checked-color="#3c9" size="small"></a-switch>
</div>
<div class="flex-1">
<i class={`${record.icon} mr-1`}></i>
<span>{record.name ?? '无'}</span>
<span class="text-gray-400 text-xs truncate">{id}</span>
</div>
);
},
},
{
title: '标识',
width: 200,
dataIndex: 'code',
},
{
title: '类型',
width: 200,
render: ({ record }) => (
<a-tag bordered color={MenuTypes.fmt(record.type, 'color')}>
{{
default: () => MenuTypes.fmt(record.type),
}}
</a-tag>
),
},
useCreateColumn(),
useUpdateColumn(),
{
@ -135,7 +141,7 @@ const { component: MenuTable, tableRef } = useTable({
field: 'type',
value: 1,
label: '类型',
setter: 'input',
setter: 'select',
options: MenuTypes.raw,
},
{

View File

@ -2,6 +2,24 @@
<BreadPage :content-padding="false">
<template #content>
<section class="my-page m-4 bg-white rounded px-4">
<div class="bg-white py-4 px-5 mb-4">
<div v-for="t1 in types" :key="t1.label" class="flex items-center">
{{ t1.label }}
<div class="flex gap-2">
<a-tag
v-for="t2 in t1.children"
:key="t2.value"
:checked="search.bk === t2.value"
color="blue"
:bordered="true"
checkable
@check="search.bk = t2.value"
>
{{ t2.label }}
</a-tag>
</div>
</div>
</div>
<a-tabs size="large" class="h-full">
<a-tab-pane key="8" title="常规设置">
<a-form
@ -39,17 +57,10 @@
:max-length="140"
:show-word-limit="true"
></a-textarea>
<template #help>
启用后消息通知将在左上角进行提示.
</template>
<template #help> 启用后消息通知将在左上角进行提示. </template>
</a-form-item>
<a-form-item label="站点URL">
<a-input
v-model="appStore.title"
placeholder="请输入"
class="!w-[432px]"
allow-clear
></a-input>
<a-input v-model="appStore.title" placeholder="请输入" class="!w-[432px]" allow-clear></a-input>
<template #help> 示例https://www.juetan.cn </template>
</a-form-item>
<a-form-item>
@ -83,7 +94,8 @@
<a-input v-model="mail.smtpHost" allow-clear placeholder="请输入" class="!w-[314px]"></a-input>
<span class="inline-block px-2">:</span>
<a-input-number v-model="mail.smtpPort" :min="0" :max="65535" class="w-24!"></a-input-number>
<template #help> 示例: smtp.163.com:25国内常见有
<template #help>
示例: smtp.163.com:25国内常见有
<a target="_blank" class="mr-2" href="https://mail.163.com">网易邮箱</a>
<a target="_blank" class="mr-2" href="http://mail.aliyun.com/">阿里邮箱</a>
<a target="_blank" class="mr-2" href="https://mail.qq.com">QQ邮箱</a>默认 25 端口
@ -164,6 +176,79 @@
import { useAppStore } from '@/store';
import { reactive } from 'vue';
const search = reactive({ bk: undefined });
const types = [
{
label: '板块',
children: [
{
label: '全部',
value: undefined,
},
{
label: '电影',
value: 'fild',
},
{
label: '电视剧',
value: 'vs',
},
{
label: '综艺',
value: 'zy',
},
{
label: '动漫',
value: 'dm',
},
{
label: '短剧',
value: 'dj',
},
{
label: '体育',
value: 'ty',
},
{
label: '纪录片',
value: 'jlp',
},
{
label: '游戏',
value: 'yx',
},
{
label: '新闻',
value: 'xw',
},
{
label: '娱乐',
value: 'yl',
},
{
label: '生活',
value: 'sh',
},
{
label: '音乐',
value: 'yinyue',
},
{
label: '时尚',
value: 'shishang',
},
{
label: '科技',
value: 'keji',
},
{
label: '发现',
value: 'faxian',
},
],
},
];
const appStore = useAppStore();
const mail = reactive({

View File

@ -49,7 +49,6 @@ declare module '@vue/runtime-core' {
ARadioGroup: typeof import('@arco-design/web-vue')['RadioGroup']
AScrollbar: typeof import('@arco-design/web-vue')['Scrollbar']
ASelect: typeof import('@arco-design/web-vue')['Select']
ASlider: typeof import('@arco-design/web-vue')['Slider']
ASpace: typeof import('@arco-design/web-vue')['Space']
ASpin: typeof import('@arco-design/web-vue')['Spin']
ASwitch: typeof import('@arco-design/web-vue')['Switch']

View File

@ -4,8 +4,6 @@ import { merge } from 'lodash-es';
export type DelOptions = string | Partial<Omit<ModalConfig, 'onOk' | 'onCancel'>>;
export const delOptions: ModalConfig = {
maskAnimationName: '',
modalAnimationName: '',
title: '提示',
titleAlign: 'start',
width: 432,