diff --git a/client/src/views/manage/collect/CollectManage.vue b/client/src/views/manage/collect/CollectManage.vue
index 0d51c40..c4add39 100644
--- a/client/src/views/manage/collect/CollectManage.vue
+++ b/client/src/views/manage/collect/CollectManage.vue
@@ -67,7 +67,8 @@
添加采集站
一键采集
- ReZero
+ RemoveAll
+ AutoCollect
@@ -191,6 +192,36 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -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 影视管理