add new features

This commit is contained in:
mubai
2024-10-29 22:30:01 +08:00
parent 7ceb125746
commit d1433e4b5b
23 changed files with 525 additions and 129 deletions

View File

@@ -14,7 +14,7 @@
<span>网站管理</span>
</template>
<el-menu-item index="/manage/system/webSite">站点管理</el-menu-item>
<!--<el-menu-item index="">预留配置</el-menu-item>-->
<el-menu-item index="/manage/system/banners">海报管理</el-menu-item>
</el-sub-menu>
<el-sub-menu index="/manage/collect">
<template #title>

View File

@@ -50,8 +50,8 @@
</a>
<!-- wrap 导航-->
<a @click="visible = true" class="iconfont icon-caidan" style="font-size: 26px"/>
<el-drawer v-model="visible" append-to-body :show-close="false" size="45%" class="warp-drawer">
<a @click="handleDrawer" class="iconfont icon-caidan" style="font-size: 26px"/>
<el-drawer v-model="visible" append-to-body :show-close="false" size="45%" class="warp-drawer" @closed="handleDrawer" >
<template #header="{ close, titleId, titleClass }">
<h2 class="menu-title" :id="titleId" :class="titleClass">{{ data.site.siteName }}</h2>
</template>
@@ -62,7 +62,6 @@
</template>
</div>
</el-drawer>
</div>
<!--弹窗模块,显示按钮对应信息-->
</div>
@@ -78,6 +77,15 @@ import {cookieUtil, COOKIE_KEY_MAP} from "../../utils/cookie";
const visible = ref(false)
const handleDrawer = ()=>{
visible.value = !visible.value
if(visible.value) {
document.body.style.position = 'fixed'
} else {
document.body.style.position = ''
}
}
// 搜索关键字
const keyword = ref<string>('')
@@ -160,9 +168,12 @@ onMounted(() => {
.el-drawer__body {
--el-drawer-padding-primary: 20px;
}
.el-overlay {
max-height: 100vh;
}
.warp-drawer {
background-color: var(--bg-dark) !important;
max-height: 100vh;
}
.el-drawer__header {

View File

@@ -25,6 +25,7 @@ import Film from "../views/manage/film/Film.vue";
import FileUpload from "../views/manage/file/FileUpload.vue";
import FilmAdd from "../views/manage/film/FilmAdd.vue";
import CustomPlay from "../views/index/CustomPlay.vue";
import Banners from "../views/manage/system/Banners.vue";
// 2. 定义一个路由
@@ -52,6 +53,7 @@ const routes = [
{path: 'index', component: ManageIndex},
{path: 'collect/index', component: CollectManage},
{path: 'system/webSite', component: SiteConfig},
{path: 'system/banners', component: Banners},
{path: 'cron/index', component: CronManage},
{path: 'file/upload', component: FileUpload},
{path: 'file/gallery', component: Temp},

View File

@@ -1,169 +1,181 @@
:root {
font-family: Inter, Avenir, Helvetica, Arial, system-ui, sans-serif;
line-height: 1.5;
font-weight: 400;
font-family: Inter, Avenir, Helvetica, Arial, system-ui, sans-serif;
line-height: 1.5;
font-weight: 400;
color-scheme: light dark;
color: rgba(255, 255, 255, 0.87);
background-color: #242424;
color-scheme: light dark;
color: rgba(255, 255, 255, 0.87);
background-color: #242424;
font-synthesis: none;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
-webkit-text-size-adjust: 100%;
font-synthesis: none;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
-webkit-text-size-adjust: 100%;
/*公共颜色*/
--bg-light: #ffffff;
/*公共颜色*/
--bg-light: #ffffff;
--bg-dark: #21252b;
--bg-dark: #21252b;
--text-color-primary: #ffffff;
--content-text-color: #888888;
--text-color-primary: #ffffff;
--content-text-color: #888888;
--paging-parmary-color: #9b49e7d6;
--paging-parmary-color-hover: #a574b7;
--paging-parmary-color: #9b49e7d6;
--paging-parmary-color-hover: #a574b7;
--border-gray-color: #0000001f;
--border-gray-color: #0000001f;
--btn-primary-color: #8636cc;
--btn-pink-color: #d942bf;
--btn-bg-linght: #fff;
--btn-primary-color: #8636cc;
--btn-pink-color: #d942bf;
--btn-bg-linght: #fff;
--bg-fill-light: #8d00fb1a;
--bg-fill-light: #8d00fb1a;
}
a {
font-weight: 500;
color: #646cff;
text-decoration: inherit;
outline: none;
font-weight: 500;
color: #646cff;
text-decoration: inherit;
outline: none;
}
a:hover {
color: #535bf2;
color: #535bf2;
}
body {
margin: 0;
display: flex;
place-items: center;
min-width: 320px;
min-height: 100vh;
margin: 0;
display: flex;
place-items: center;
min-width: 320px;
min-height: 100vh;
}
h1 {
font-size: 3.2em;
line-height: 1.1;
font-size: 3.2em;
line-height: 1.1;
}
button {
border-radius: 8px;
border: 1px solid transparent;
padding: 0.6em 1.2em;
font-size: 1em;
font-weight: 500;
font-family: inherit;
background-color: #1a1a1a;
cursor: pointer;
transition: border-color 0.25s;
border-radius: 8px;
border: 1px solid transparent;
padding: 0.6em 1.2em;
font-size: 1em;
font-weight: 500;
font-family: inherit;
background-color: #1a1a1a;
cursor: pointer;
transition: border-color 0.25s;
}
button:hover {
border-color: #646cff;
border-color: #646cff;
}
button:focus,
button:focus-visible {
outline: none;
outline: none;
}
.card {
padding: 2em;
padding: 2em;
}
#app {
max-width: 1280px;
margin: 0 auto;
padding: 2rem;
text-align: center;
max-width: 1280px;
margin: 0 auto;
padding: 2rem;
text-align: center;
}
@media (prefers-color-scheme: light) {
:root {
color: #213547;
background-color: #ffffff;
}
a:hover {
color: #747bff;
}
button {
background-color: #f9f9f9;
}
:root {
color: #213547;
background-color: #ffffff;
}
a:hover {
color: #747bff;
}
button {
background-color: #f9f9f9;
}
}
/*通用样式*/
.primary{
color: #99DBF5;
.primary {
color: #99DBF5;
}
.dark {
color: rgba(0,0,0,0.68);
color: rgba(0, 0, 0, 0.68);
}
.light {
color: rgba(255,255,255,0.68);
color: rgba(255, 255, 255, 0.68);
}
.silver{
color: rgba(255,255,255,0.75);
.silver {
color: rgba(255, 255, 255, 0.75);
}
/*滚动条样式*/
@media (min-width: 768px) {
::-webkit-scrollbar {
width: 3px;
}
::-webkit-scrollbar-thumb {
border-radius: 5px;
height: 10px;
background: rgba(255,255,255,0.25);
}
::-webkit-scrollbar {
width: 3px;
}
::-webkit-scrollbar-thumb {
border-radius: 5px;
height: 10px;
background: rgba(255, 255, 255, 0.25);
}
}
/*el-dialog样式*/
@media (min-width: 768px){
.el-dialog__body{
padding: 45px!important;
}
@media (min-width: 768px) {
.el-dialog__body {
padding: 45px !important;
}
}
@media (max-width: 768px){
.el-dialog__body{
padding: 20px!important;
}
.el-dialog__header{
padding: 12px 0 8px 0 !important;
}
@media (max-width: 768px) {
.el-dialog__body {
padding: 20px !important;
}
.el-dialog__header {
padding: 12px 0 8px 0 !important;
}
}
.el-dialog{
border-radius: 8px !important;
background-image: linear-gradient( 135deg, #81FFEF 10%, #F067B4 100%) !important;
}
.el-dialog__header{
border-bottom: 1px solid rgba(0,0,0,0.1);
margin-right: 0!important;
.el-dialog {
border-radius: 8px !important;
background-image: linear-gradient(135deg, #81FFEF 10%, #F067B4 100%) !important;
--el-text-color-primary: #5e1e99b8;
}
.el-dialog__headerbtn{
outline: none!important;
border: none;
.el-dialog__header {
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
margin-right: 0 !important;
}
.el-dialog__headerbtn {
outline: none !important;
border: none;
}
/*分页插件颜色*/
.el-popper {
--el-color-primary: var(--paging-parmary-color);
--el-color-primary: var(--paging-parmary-color);
}

View File

@@ -2,7 +2,7 @@
<el-container>
<el-header>
<!--<Header/>-->
<Header />
<NewHeader />
</el-header>
<el-main>
<router-view></router-view>

View File

@@ -1,6 +1,6 @@
<template>
<div class="container">
<div v-if="false" class="hidden-sm-and-up banner_wrap" @touchstart="touchS" @touchend="touchE" >
<div v-if="true" class="hidden-sm-and-up banner_wrap" @touchstart="touchS" @touchend="touchE" >
<el-carousel v-model="data.banner.current" ref="wrap" :pause-on-hover="false" :interval="5000" trigger="hover" height="200px" arrow="never" >
<el-carousel-item v-for="item in banners" :key="item" >
<el-image style="width: 100%; height: 100%;" :src="item.picture" fit="fill"/>
@@ -8,7 +8,7 @@
</el-carousel-item>
</el-carousel>
</div>
<div v-if="false" class="banner hidden-sm-and-down"
<div v-if="true" class="banner hidden-sm-and-down"
:style="{background:`url(${data.banner.current.picture})`, backgroundRepeat: 'no-repeat', backgroundSize: 'cover'}">
<div class="preview">
<el-carousel @change="carousel" :interval="5000" height="240px" arrow="always">

View File

@@ -67,7 +67,8 @@
<div class="cus_util">
<el-button color="#9b49e7" :icon="CirclePlus" @click="dialogV.addV = true">添加采集站</el-button>
<el-button color="#d942bf" @click="openBatchCollect" :icon="Promotion">一键采集</el-button>
<el-button type="danger" :icon="BellFilled">ReZero</el-button>
<el-button type="danger" :icon="DeleteFilled" @click="dialogV.clear = true" >RemoveAll</el-button>
<el-button type="primary" :icon="BellFilled" @click="dialogV.reCollect = true" >AutoCollect</el-button>
</div>
<!--站点添加弹窗-->
<el-dialog v-model="dialogV.addV" title="添加采集站点">
@@ -191,6 +192,36 @@
</span>
</template>
</el-dialog>
<!--影片删除提示弹窗-->
<el-dialog v-model="dialogV.clear" title="是否清除所有影视数据 ?" width="500">
<el-form :model="form">
<el-form-item label="确认密码" >
<el-input v-model="data.password" type="password" placeholder="请输入账户密码并开确认执行" autocomplete="off" />
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button @click="dialogV.clear = false">取消</el-button>
<el-button type="primary" @click="clearFilms">确认执行</el-button>
</div>
</template>
</el-dialog>
<!--Re0 从零开始的自动全量采集-->
<el-dialog v-model="dialogV.reCollect" title="是否清除影片数据并重新采集 ?" width="500">
<el-form :model="form">
<el-form-item label="确认密码" >
<el-input v-model="data.password" type="password" placeholder="请输入账户密码并开确认执行" autocomplete="off" />
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button @click="dialogV.reCollect = false">取消</el-button>
<el-button type="primary" @click="reCollectFilm">确认执行</el-button>
</div>
</template>
</el-dialog>
</div>
</template>
@@ -200,7 +231,7 @@
import {onMounted, reactive} from "vue";
import {ApiGet, ApiPost} from "../../../utils/request";
import {ElMessage} from "element-plus";
import {Delete, Edit, SwitchButton, CirclePlus, Promotion, BellFilled} from "@element-plus/icons-vue";
import {Delete, Edit, SwitchButton, CirclePlus, Promotion, BellFilled, DeleteFilled} from "@element-plus/icons-vue";
const data = reactive({
siteList: [],
@@ -208,13 +239,16 @@ const data = reactive({
{time: 24, label: '采集今日'},
{time: 24 * 7, label: '采集本周'},
{time: -1, label: '采集全部'},
]
],
password: '',
})
const dialogV = reactive({
addV: false,
editV: false,
batchV:false,
clear: false,
reCollect: false,
})
interface FilmSource {
@@ -271,9 +305,6 @@ const startTask = (row:any)=>{
})
}
// 弹窗图片同步开关限制
const restrict = (t:number)=>{
// t 弹窗类型 0 - add | 1 - edit
@@ -327,7 +358,6 @@ const openEditDialog = (id:string)=>{
dialogV.editV = true
}
// switch 开关
const changeSourceState = (s:any)=>{
ApiPost(`/manage/collect/change`, {id:s.id, state: s.state, syncPictures: s.syncPictures}).then((resp: any) => {
@@ -373,6 +403,7 @@ const cancelDialog = ()=>{
form.add = {name: '', uri: '', resultModel: 0, grade: 1, collectType: 0, syncPictures: false, state: false, interval: 0}
}
// 获取采集列表信息
const getCollectList = ()=>{
ApiGet(`/manage/collect/list`).then((resp: any) => {
if (resp.code === 0) {
@@ -402,6 +433,41 @@ const getCollectList = ()=>{
}
})
}
// 清除影片信息
const clearFilms = ()=>{
if (data.password.length <= 0) {
ElMessage.error({message: '操作失败, 密钥信息缺失'})
return
}
ApiGet(`/manage/spider/clear`, {password: data.password}).then((resp:any)=>{
if (resp.code === 0) {
ElMessage.success({message: resp.msg})
} else {
ElMessage.error({message: resp.msg})
}
dialogV.clear = false
data.password = ''
})
}
// 从零开始重新采集
const reCollectFilm = ()=>{
if (data.password.length <= 0) {
ElMessage.error({message: '操作失败, 密钥信息缺失'})
return
}
ApiGet(`/manage/spider/zero`, {password: data.password}).then((resp:any)=>{
if (resp.code === 0) {
ElMessage.success({message: resp.msg})
} else {
ElMessage.error({message: resp.msg})
}
dialogV.reCollect = false
data.password = ''
})
}
onMounted(() => {
getCollectList()
})
@@ -409,8 +475,7 @@ onMounted(() => {
</script>
<style scoped>
.container {
}
.cus_util {
display: flex;

View File

@@ -0,0 +1,79 @@
<template>
<h2 style="color: #8e48b4">首页横幅管理界面</h2>
<el-table
:data="data.banners" style="width: 100%" border size="default"
:row-class-name="'cus-tr'" table-layout="auto">
<el-table-column prop="name" label="影片名称"/>
<el-table-column prop="collectType" align="center" label="影片类型">
<template #default="scope">
<el-tag type="warning">{{ scope.row.cName }}</el-tag>
</template>
</el-table-column>
<el-table-column prop="collectType" align="center" label="上映年份">
<template #default="scope">
<el-tag type="warning">{{ scope.row.year }}</el-tag>
</template>
</el-table-column>
<el-table-column prop="collectType" align="center" label="影片海报">
<template #default="scope">
<el-image style="width: 120px; height: 80px" :src="scope.row.poster" :preview-src-list="[scope.row.poster]" preview-teleported fit="contain" />
</template>
</el-table-column>
<el-table-column prop="collectType" align="center" label="影片封面">
<template #default="scope">
<el-image style="width: 60px; height: 80px" :src="scope.row.picture" :preview-src-list="[scope.row.picture]" preview-teleported fit="cover" />
</template>
</el-table-column>
<el-table-column prop="collectType" align="center" label="排序">
<template #default="scope">
<el-tag disable-transitions>{{ scope.row.sort }}</el-tag>
</template>
</el-table-column>
<el-table-column prop="resultModel" align="center" label="连载状态">
<template #default="scope">
<el-tag v-if="(scope.row.remarks+'').search('更新') == -1" type="success" >{{ scope.row.remark}}</el-tag>
<el-tag v-else type="primary" >{{ scope.row.remark}}</el-tag>
</template>
</el-table-column>
<el-table-column label="操作" align="center">
<template #default="scope">
<el-button type="success" :icon="SwitchButton" plain circle @click="" />
<el-button type="primary" :icon="Edit" plain circle @click="" />
<el-button type="danger" :icon="Delete" plain circle @click="" />
</template>
</el-table-column>
</el-table>
</template>
<script setup lang="ts">
import {Delete, Edit, SwitchButton} from "@element-plus/icons-vue";
import {onMounted, reactive} from "vue";
import {ApiGet} from "../../../utils/request";
import {ElMessage} from "element-plus";
const data = reactive({
banners: [],
})
const getBanners = ()=>{
ApiGet(`/manage/banner/list`).then((resp:any)=>{
if(resp.code === 0){
data.banners = resp.data
} else {
ElMessage.error({message: resp.msg})
}
})
}
onMounted(()=>{
// 初始化banners数据
getBanners()
})
</script>
<style scoped>
</style>