From d1433e4b5be9df3e2d7817e1049f56aa792610a3 Mon Sep 17 00:00:00 2001 From: mubai <1609539827@qq.com> Date: Tue, 29 Oct 2024 22:30:01 +0800 Subject: [PATCH] add new features --- client/components.d.ts | 1 + client/package.json | 4 +- client/src/components/Manage/Sidebar.vue | 2 +- client/src/components/index/NewHeader.vue | 19 +- client/src/router/router.ts | 2 + client/src/style.css | 208 +++++++++--------- client/src/views/IndexHome.vue | 2 +- client/src/views/index/Home.vue | 4 +- .../views/manage/collect/CollectManage.vue | 83 ++++++- client/src/views/manage/system/Banners.vue | 79 +++++++ server/config/DataConfig.go | 6 +- server/controller/ManageController.go | 94 ++++++++ server/controller/SpiderController.go | 35 ++- server/logic/ManageLogic.go | 14 ++ server/logic/SpiderLogic.go | 5 + server/logic/UserLogic.go | 9 + server/main.go | 1 + server/model/system/Categories.go | 2 +- server/model/system/Manage.go | 44 ++++ server/model/system/Movies.go | 6 +- server/plugin/SystemInit/WebSiteInit.go | 10 + server/plugin/spider/Spider.go | 5 + server/router/router.go | 19 +- 23 files changed, 525 insertions(+), 129 deletions(-) create mode 100644 client/src/views/manage/system/Banners.vue diff --git a/client/components.d.ts b/client/components.d.ts index 0d5a98b..a3feeed 100644 --- a/client/components.d.ts +++ b/client/components.d.ts @@ -21,6 +21,7 @@ declare module '@vue/runtime-core' { ElContainer: typeof import('element-plus/es')['ElContainer'] ElDatePicker: typeof import('element-plus/es')['ElDatePicker'] ElDialog: typeof import('element-plus/es')['ElDialog'] + ElDrawer: typeof import('element-plus/es')['ElDrawer'] ElDropdown: typeof import('element-plus/es')['ElDropdown'] ElDropdownItem: typeof import('element-plus/es')['ElDropdownItem'] ElDropdownMenu: typeof import('element-plus/es')['ElDropdownMenu'] diff --git a/client/package.json b/client/package.json index a4d0cd3..cca106d 100644 --- a/client/package.json +++ b/client/package.json @@ -10,10 +10,10 @@ "preview": "vite preview" }, "dependencies": { - "@element-plus/icons-vue": "^2.1.0", + "@element-plus/icons-vue": "^2.3.1", "@videojs-player/vue": "^1.0.0", "axios": "^1.3.4", - "element-plus": "^2.4.4", + "element-plus": "^2.8.6", "video.js": "^8.0.4", "vue": "^3.4.31" }, diff --git a/client/src/components/Manage/Sidebar.vue b/client/src/components/Manage/Sidebar.vue index ce3349b..6be3614 100644 --- a/client/src/components/Manage/Sidebar.vue +++ b/client/src/components/Manage/Sidebar.vue @@ -14,7 +14,7 @@ 网站管理 站点管理 - + 海报管理 - @@ -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('') @@ -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 { diff --git a/client/src/router/router.ts b/client/src/router/router.ts index 9c22d26..d6acbe9 100644 --- a/client/src/router/router.ts +++ b/client/src/router/router.ts @@ -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}, diff --git a/client/src/style.css b/client/src/style.css index 4ee0eb7..4c2f1c6 100644 --- a/client/src/style.css +++ b/client/src/style.css @@ -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); } diff --git a/client/src/views/IndexHome.vue b/client/src/views/IndexHome.vue index a41784c..2608fdc 100644 --- a/client/src/views/IndexHome.vue +++ b/client/src/views/IndexHome.vue @@ -2,7 +2,7 @@ -
+ diff --git a/client/src/views/index/Home.vue b/client/src/views/index/Home.vue index 43ab9dd..9136904 100644 --- a/client/src/views/index/Home.vue +++ b/client/src/views/index/Home.vue @@ -1,6 +1,6 @@ + + + + + + + + + + + + + + + + + + + + @@ -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(() => { \ No newline at end of file diff --git a/server/config/DataConfig.go b/server/config/DataConfig.go index c1e8150..453ab6e 100644 --- a/server/config/DataConfig.go +++ b/server/config/DataConfig.go @@ -23,8 +23,8 @@ const ( // -------------------------redis key----------------------------------- const ( // CategoryTreeKey 分类树 key - CategoryTreeKey = "CategoryTree" - CategoryTreeExpired = time.Hour * 24 * 90 + CategoryTreeKey = "CategoryTree" + FilmExpired = time.Hour * 24 * 365 * 10 // MovieListInfoKey movies分类列表 key MovieListInfoKey = "MovieList:Cid%d" @@ -62,6 +62,8 @@ const ( ManageConfigExpired = time.Hour * 24 * 365 * 10 // SiteConfigBasic 网站参数配置 SiteConfigBasic = "SystemConfig:SiteConfig:Basic" + // BannersKey 轮播组件key 你 + BannersKey = "SystemConfig:Banners" // FilmCrontabKey 定时任务列表信息 FilmCrontabKey = "Cron:Task:Film" diff --git a/server/controller/ManageController.go b/server/controller/ManageController.go index 15fd96d..7906a3a 100644 --- a/server/controller/ManageController.go +++ b/server/controller/ManageController.go @@ -9,6 +9,7 @@ import ( "server/plugin/SystemInit" "server/plugin/common/util" "server/plugin/spider" + "strconv" ) func ManageIndex(c *gin.Context) { @@ -235,6 +236,99 @@ func ResetSiteBasic(c *gin.Context) { system.SuccessOnlyMsg("配置信息重置成功", c) } +// ------------------------------------------------------ 轮播数据配置 ------------------------------------------------------ + +// BannerList 获取轮播图数据 +func BannerList(c *gin.Context) { + bl := logic.ML.GetBanners() + system.Success(bl, "配置信息重置成功", c) +} + +// BannerFind 返回ID对应的横幅信息 +func BannerFind(c *gin.Context) { + idStr := c.Query("id") + if idStr == "" { + system.Failed("Banner信息获取失败, ID信息异常", c) + return + } + id, err := strconv.ParseInt(idStr, 10, 64) + if err != nil { + system.Failed("删除失败,参数类型异常", c) + return + } + bl := logic.ML.GetBanners() + for _, b := range bl { + if b.Id == id { + system.Success(b, "Banner信息获取成功", c) + return + } + } + system.Failed("Banner信息获取失败", c) +} + +// BannerAdd 添加海报数据 +func BannerAdd(c *gin.Context) { + var b system.Banner + if err := c.ShouldBindJSON(&b); err != nil { + system.Failed("Banner参数提交异常", c) + return + } + bl := logic.ML.GetBanners() + bl = append(bl, b) + if err := logic.ML.SaveBanners(bl); err != nil { + system.Failed(fmt.Sprintln("Banners信息添加失败,", err), c) + return + } + system.SuccessOnlyMsg("海报信息添加成功", c) +} + +// BannerUpdate 更新海报数据 +func BannerUpdate(c *gin.Context) { + var banner system.Banner + if err := c.ShouldBindJSON(&banner); err != nil { + system.Failed("Banner参数提交异常", c) + return + } + bl := logic.ML.GetBanners() + for i, b := range bl { + if b.Id == banner.Id { + bl[i] = banner + if err := logic.ML.SaveBanners(bl); err != nil { + system.Failed("海报信息更新失败", c) + } else { + system.SuccessOnlyMsg("海报信息更新成功", c) + return + } + + } + } + system.Failed("海报信息更新失败, 未匹配对应Banner信息", c) +} + +// BannerDel 删除海报数据 +func BannerDel(c *gin.Context) { + idStr := c.Query("id") + if idStr == "" { + system.Failed("Banner信息获取失败, ID信息异常", c) + return + } + id, err := strconv.ParseInt(idStr, 10, 64) + if err != nil { + system.Failed("删除失败,参数类型异常", c) + return + } + bl := logic.ML.GetBanners() + for i, b := range bl { + if b.Id == id { + bl = append(bl[:i], bl[i+1:]...) + _ = logic.ML.SaveBanners(bl) + system.SuccessOnlyMsg("海报信息删除成功", c) + return + } + } + system.Failed("海报信息删除失败", c) +} + // ------------------------------------------------------ 参数校验 ------------------------------------------------------ func validFilmSource(fs system.FilmSource) error { // 资源名称不能为空 且长度不能超过20 diff --git a/server/controller/SpiderController.go b/server/controller/SpiderController.go index 1e89867..5c51597 100644 --- a/server/controller/SpiderController.go +++ b/server/controller/SpiderController.go @@ -3,6 +3,7 @@ package controller import ( "fmt" "github.com/gin-gonic/gin" + "server/config" "server/logic" "server/model/system" "strconv" @@ -64,13 +65,27 @@ func StarSpider(c *gin.Context) { system.SuccessOnlyMsg("采集任务已成功开启!!!", c) } +// ClearAllFilm 删除所有film信息 +func ClearAllFilm(c *gin.Context) { + // 清空采集数据进行重新采集前校验输入的密码是否正确 + pwd := c.DefaultQuery("password", "") + // 如密码错误则不执行后续操作 + if !verifyPassword(c, pwd) { + system.Failed("重置失败, 密钥校验失败!!!", c) + return + } + // 删除已采集的所有影片信息 + logic.SL.ClearFilms() + system.SuccessOnlyMsg("影视数据已删除!!!", c) +} + // SpiderReset 重置影视数据, 清空库存, 从零开始 func SpiderReset(c *gin.Context) { // 清空采集数据进行重新采集前校验输入的密码是否正确 - key := c.DefaultQuery("accessKey", "") + pwd := c.DefaultQuery("password", "") // 如密码错误则不执行后续操作 - if len(key) <= 0 || key != "Re0" { - system.Failed("重置失败, 密钥校验失败!!!", c) + if !verifyPassword(c, pwd) { + system.Failed("重置失败, 密码校验失败!!!", c) return } // 前置校验通过则清空采集数据并对已启用站点进行 全量采集 @@ -87,3 +102,17 @@ func CoverFilmClass(c *gin.Context) { } system.SuccessOnlyMsg("影视分类信息重置成功, 请稍等片刻后刷新页面", c) } + +// 校验密码有效性 +func verifyPassword(c *gin.Context, password string) bool { + // 获取已登录的用户信息 + v, ok := c.Get(config.AuthUserClaims) + if !ok { + system.Failed("操作失败,登录信息异常!!!", c) + return false + } + // 从context中获取用户的登录信息 + uc := v.(*system.UserClaims) + // 校验密码 + return logic.UL.VerifyUserPassword(uc.UserID, password) +} diff --git a/server/logic/ManageLogic.go b/server/logic/ManageLogic.go index 906d145..f5c00ff 100644 --- a/server/logic/ManageLogic.go +++ b/server/logic/ManageLogic.go @@ -16,18 +16,22 @@ func (ml *ManageLogic) GetFilmSourceList() []system.FilmSource { return system.GetCollectSourceList() } +// GetFilmSource 获取ID对应的采集源信息 func (ml *ManageLogic) GetFilmSource(id string) *system.FilmSource { return system.FindCollectSourceById(id) } +// UpdateFilmSource 更新采集源信息 func (ml *ManageLogic) UpdateFilmSource(s system.FilmSource) error { return system.UpdateCollectSource(s) } +// SaveFilmSource 保存采集源信息 func (ml *ManageLogic) SaveFilmSource(s system.FilmSource) error { return system.AddCollectSource(s) } +// DelFilmSource 删除采集源信息 func (ml *ManageLogic) DelFilmSource(id string) error { // 先查找是否存在对应ID的站点信息 s := system.FindCollectSourceById(id) @@ -51,3 +55,13 @@ func (ml *ManageLogic) GetSiteBasicConfig() system.BasicConfig { func (ml *ManageLogic) UpdateSiteBasic(c system.BasicConfig) error { return system.SaveSiteBasic(c) } + +// GetBanners 获取轮播组件信息 +func (ml *ManageLogic) GetBanners() system.Banners { + return system.GetBanners() +} + +// SaveBanners 保存轮播信息 +func (ml *ManageLogic) SaveBanners(bl system.Banners) error { + return system.SaveBanners(bl) +} diff --git a/server/logic/SpiderLogic.go b/server/logic/SpiderLogic.go index dba6b81..ceab973 100644 --- a/server/logic/SpiderLogic.go +++ b/server/logic/SpiderLogic.go @@ -38,6 +38,11 @@ func (sl *SpiderLogic) AutoCollect(time int) { go spider.AutoCollect(time) } +// ClearFilms 删除采集的数据信息 +func (sl *SpiderLogic) ClearFilms() { + go spider.ClearSpider() +} + // ZeroCollect 数据清除从零开始采集 func (sl *SpiderLogic) ZeroCollect(time int) { go spider.StarZero(time) diff --git a/server/logic/UserLogic.go b/server/logic/UserLogic.go index 29cbaa4..05ad965 100644 --- a/server/logic/UserLogic.go +++ b/server/logic/UserLogic.go @@ -57,6 +57,7 @@ func (ul *UserLogic) ChangePassword(account, password, newPassword string) error return nil } +// GetUserInfo 获取用户基本信息 func (ul *UserLogic) GetUserInfo(id uint) system.UserInfoVo { // 通过用户ID查询对应的用户信息 u := system.GetUserById(id) @@ -64,3 +65,11 @@ func (ul *UserLogic) GetUserInfo(id uint) system.UserInfoVo { var vo = system.UserInfoVo{Id: u.ID, UserName: u.UserName, Email: u.Email, Gender: u.Gender, NickName: u.NickName, Avatar: u.Avatar, Status: u.Status} return vo } + +// VerifyUserPassword 校验密码 +func (ul *UserLogic) VerifyUserPassword(id uint, password string) bool { + // 获取当前登录的用户全部信息 + u := system.GetUserById(id) + // 校验密码是否正确 + return util.PasswordEncrypt(password, u.Salt) == u.Password +} diff --git a/server/main.go b/server/main.go index d18150a..491e15a 100644 --- a/server/main.go +++ b/server/main.go @@ -32,6 +32,7 @@ func start() { // 启动前先执行数据库内容的初始化工作 DefaultDataInit() + SystemInit.BannersInit() // 开启路由监听 r := router.SetupRouter() _ = r.Run(fmt.Sprintf(":%s", config.ListenerPort)) diff --git a/server/model/system/Categories.go b/server/model/system/Categories.go index 1b4e79f..5dadc08 100644 --- a/server/model/system/Categories.go +++ b/server/model/system/Categories.go @@ -26,7 +26,7 @@ type CategoryTree struct { // SaveCategoryTree 保存影片分类信息 func SaveCategoryTree(tree *CategoryTree) error { data, _ := json.Marshal(tree) - return db.Rdb.Set(db.Cxt, config.CategoryTreeKey, data, config.CategoryTreeExpired).Err() + return db.Rdb.Set(db.Cxt, config.CategoryTreeKey, data, config.FilmExpired).Err() } // GetCategoryTree 获取影片分类信息 diff --git a/server/model/system/Manage.go b/server/model/system/Manage.go index 00fead7..01a60e3 100644 --- a/server/model/system/Manage.go +++ b/server/model/system/Manage.go @@ -5,8 +5,10 @@ import ( "log" "server/config" "server/plugin/db" + "sort" ) +// BasicConfig 网站基本信息 type BasicConfig struct { SiteName string `json:"siteName"` // 网站名称 Domain string `json:"domain"` // 网站域名 @@ -17,6 +19,30 @@ type BasicConfig struct { Hint string `json:"hint"` // 网站关闭提示 } +// Banner 首页横幅信息 +type Banner struct { + Id int64 `json:"id"` // 绑定所属影片Id + Name string `json:"name"` // 影片名称 + Year int64 `json:"year"` // 上映年份 + CName string `json:"cName"` // 分类名称 + Poster string `json:"poster"` // 海报图片链接 + Picture string `json:"picture"` // 横幅大图链接 + Remark string `json:"remark"` // 更新状态描述信息 + Sort int64 `json:"sort"` // 排序分值 +} + +type Banners []Banner + +func (bl Banners) Len() int { + return len(bl) +} +func (bl Banners) Less(i, j int) bool { + return bl[i].Sort < bl[j].Sort +} +func (bl Banners) Swap(i, j int) { + bl[i], bl[j] = bl[j], bl[i] +} + // ------------------------------------------------------ Redis ------------------------------------------------------ // SaveSiteBasic 保存网站基本配置信息 @@ -34,3 +60,21 @@ func GetSiteBasic() BasicConfig { } return c } + +// GetBanners 获取轮播配置信息 +func GetBanners() Banners { + var bl Banners + data := db.Rdb.Get(db.Cxt, config.BannersKey).Val() + if err := json.Unmarshal([]byte(data), &bl); err != nil { + log.Println("Get Banners Error", err) + } + // 通过 sort 对banners进行排序 + sort.Sort(bl) + return bl +} + +// SaveBanners 保存轮播配置信息 +func SaveBanners(bl Banners) error { + data, _ := json.Marshal(bl) + return db.Rdb.Set(db.Cxt, config.BannersKey, data, config.ManageConfigExpired).Err() +} diff --git a/server/model/system/Movies.go b/server/model/system/Movies.go index 78c6694..526274b 100644 --- a/server/model/system/Movies.go +++ b/server/model/system/Movies.go @@ -99,7 +99,7 @@ func SaveDetails(list []MovieDetail) (err error) { data, _ := json.Marshal(detail) // 1. 原使用Zset存储, 但是不便于单个检索 db.Rdb.ZAdd(db.Cxt, fmt.Sprintf("%s:Cid%d", config.MovieDetailKey, detail.Cid), redis.Z{Score: float64(detail.Id), Member: member}).Err() // 改为普通 k v 存储, k-> id关键字, v json序列化的结果 - err = db.Rdb.Set(db.Cxt, fmt.Sprintf(config.MovieDetailKey, detail.Cid, detail.Id), data, config.CategoryTreeExpired).Err() + err = db.Rdb.Set(db.Cxt, fmt.Sprintf(config.MovieDetailKey, detail.Cid, detail.Id), data, config.FilmExpired).Err() // 2. 同步保存简略信息到redis中 SaveMovieBasicInfo(detail) // 3. 保存 Search tag redis中 @@ -121,7 +121,7 @@ func SaveDetail(detail MovieDetail) (err error) { // 序列化影片详情信息 data, _ := json.Marshal(detail) // 保存影片信息到Redis - err = db.Rdb.Set(db.Cxt, fmt.Sprintf(config.MovieDetailKey, detail.Cid, detail.Id), data, config.CategoryTreeExpired).Err() + err = db.Rdb.Set(db.Cxt, fmt.Sprintf(config.MovieDetailKey, detail.Cid, detail.Id), data, config.FilmExpired).Err() if err != nil { return err } @@ -156,7 +156,7 @@ func SaveMovieBasicInfo(detail MovieDetail) { Year: detail.Year, } data, _ := json.Marshal(basicInfo) - _ = db.Rdb.Set(db.Cxt, fmt.Sprintf(config.MovieBasicInfoKey, detail.Cid, detail.Id), data, config.CategoryTreeExpired).Err() + _ = db.Rdb.Set(db.Cxt, fmt.Sprintf(config.MovieBasicInfoKey, detail.Cid, detail.Id), data, config.FilmExpired).Err() } // SaveSitePlayList 仅保存播放url列表信息到当前站点 diff --git a/server/plugin/SystemInit/WebSiteInit.go b/server/plugin/SystemInit/WebSiteInit.go index d908160..a14110f 100644 --- a/server/plugin/SystemInit/WebSiteInit.go +++ b/server/plugin/SystemInit/WebSiteInit.go @@ -20,3 +20,13 @@ func BasicConfigInit() { } _ = system.SaveSiteBasic(bc) } + +func BannersInit() { + var bl = system.Banners{ + system.Banner{Name: "樱花庄的宠物女孩", Year: 2020, CName: "日韩动漫", Poster: "https://s2.loli.net/2024/02/21/Wt1QDhabdEI7HcL.jpg", Picture: "https://img.bfzypic.com/upload/vod/20230424-43/06e79232a4650aea00f7476356a49847.jpg", Remark: "已完结"}, + system.Banner{Name: "从零开始的异世界生活", Year: 2020, CName: "日韩动漫", Poster: "https://s2.loli.net/2024/02/21/Wt1QDhabdEI7HcL.jpg", Picture: "https://img.bfzypic.com/upload/vod/20230424-43/06e79232a4650aea00f7476356a49847.jpg", Remark: "已完结"}, + system.Banner{Name: "五等分的花嫁", Year: 2020, CName: "日韩动漫", Poster: "https://s2.loli.net/2024/02/21/Wt1QDhabdEI7HcL.jpg", Picture: "https://img.bfzypic.com/upload/vod/20230424-43/06e79232a4650aea00f7476356a49847.jpg", Remark: "已完结"}, + system.Banner{Name: "我的青春恋爱物语果然有问题", Year: 2020, CName: "日韩动漫", Poster: "https://s2.loli.net/2024/02/21/Wt1QDhabdEI7HcL.jpg", Picture: "https://img.bfzypic.com/upload/vod/20230424-43/06e79232a4650aea00f7476356a49847.jpg", Remark: "已完结"}, + } + _ = system.SaveBanners(bl) +} diff --git a/server/plugin/spider/Spider.go b/server/plugin/spider/Spider.go index 159127e..34b0d41 100644 --- a/server/plugin/spider/Spider.go +++ b/server/plugin/spider/Spider.go @@ -229,6 +229,11 @@ func AutoCollect(h int) { } } +// ClearSpider 删除已采集的影片信息 +func ClearSpider() { + system.FilmZero() +} + // StarZero 情况站点内所有影片信息 func StarZero(h int) { // 首先清除影视信息 diff --git a/server/router/router.go b/server/router/router.go index a11415d..2e346f4 100644 --- a/server/router/router.go +++ b/server/router/router.go @@ -34,14 +34,26 @@ func SetupRouter() *gin.Engine { manageRoute.Use(middleware.AuthToken()) { manageRoute.GET(`/index`, controller.ManageIndex) + // 系统相关 sysConfig := manageRoute.Group(`/config`) { - sysConfig.GET("/basic", controller.SiteBasicConfig) - sysConfig.POST("/basic/update", controller.UpdateSiteBasic) - sysConfig.GET("/basic/reset", controller.ResetSiteBasic) + sysConfig.GET(`/basic`, controller.SiteBasicConfig) + sysConfig.POST(`/basic/update`, controller.UpdateSiteBasic) + sysConfig.GET(`/basic/reset`, controller.ResetSiteBasic) } + // 轮播相关 + banner := manageRoute.Group(`banner`) + { + banner.GET(`/list`, controller.BannerList) + banner.GET(`/find`, controller.BannerFind) + banner.POST(`/add`, controller.BannerAdd) + banner.GET(`/update`, controller.BannerUpdate) + banner.GET(`/del`, controller.BannerDel) + } + + // 用户相关 userRoute := manageRoute.Group(`/user`) { userRoute.GET(`/info`, controller.UserInfo) @@ -77,6 +89,7 @@ func SetupRouter() *gin.Engine { { spiderRoute.POST(`/start`, controller.StarSpider) spiderRoute.GET(`/zero`, controller.SpiderReset) + spiderRoute.GET(`/clear`, controller.ClearAllFilm) spiderRoute.GET(`/class/cover`, controller.CoverFilmClass) } // filmManage 影视管理