mirror of
https://github.com/ProudMuBai/GoFilm.git
synced 2026-04-10 00:17:30 +08:00
New version trial
This commit is contained in:
32
README.md
32
README.md
@@ -4,7 +4,7 @@
|
||||
|
||||
效果展示: <a href="https://m.mubai.link/" target="_blank">点击访问演示站点</a>
|
||||
|
||||
新版本测试访问站点: [测试内容站点](https://m.mubai.us.ci/)
|
||||
新版本测试访问站点: [新版本站点](https://www.mubai.us.ci/)
|
||||
|
||||
## 简介
|
||||
|
||||
@@ -21,14 +21,15 @@
|
||||
**部署方式**
|
||||
|
||||
- [Docker部署](https://github.com/ProudMuBai/GoFilm/blob/main/film/README.md)
|
||||
- [1Panel部署(可视化面板操作)](https://blog.mubai.link/2024/04/21/Docs/gofilm/)
|
||||
- [1Panel部署(可视化面板操作)](https://blog.mubai.link/procedure/application/github/GoFilm/)
|
||||
|
||||
**使用指南**
|
||||
|
||||
- 程序使用文档: 提供项目安装部署以及相应的初始化使用步骤说明 [GoFilm 部署文档](https://blog.mubai.link/procedure/application/github/GoFilm/)
|
||||
|
||||
- 后端项目路径 `GoFilm/server`, 包含 项目结构说明, 后端程序源码, API接口说明, 本地启动注意事项 [查看](https://github.com/ProudMuBai/GoFilm/tree/main/server)
|
||||
- 前端项目路径 `GoFilm/client`, 包含 项目结构说明, 前端项目源码, 配置文件说明, 本地启动方式 [查看](https://github.com/ProudMuBai/GoFilm/tree/main/client)
|
||||
- 部署文件 `GoFilm/film`, 包含项目部署所需的所有文件以及相应的说明文件 [查看](https://github.com/ProudMuBai/GoFilm/tree/main/film)
|
||||
- 程序使用文档: 提供项目安装部署以及相应的初始化使用步骤说明 [点击前往](https://blog.mubai.link/2024/04/21/Docs/gofilm/)
|
||||
|
||||
|
||||
|
||||
@@ -52,25 +53,26 @@
|
||||
**更新说明**
|
||||
|
||||
- 更换主体数据存储方式, 精简部分无意义字段, 节省服务器内存
|
||||
- 使用中出现问题可在项目 Issues 中进行描述, 有需要添加的新功能和好的建议也可以提供
|
||||
- 更换视频播放器, 优化部分功能键,新增播放列表和下一集控键
|
||||
- 新版本安装方法以及使用说明请查看本项目 film 文件夹下的说明文件
|
||||
|
||||
>新增内容:
|
||||
>更新内容:
|
||||
>
|
||||
>- 新增移动端观看历史
|
||||
>- 新增采集失败记录功能 && 基于失败的采集进行重新采集处理
|
||||
>- 默认定时任务新增定期处理失败采集功能
|
||||
>- 修复Banner首页轮播横幅参数修改提交异常问题
|
||||
>- 修复首页一级分类导航无数据问题
|
||||
>- 修复首页界面影片信息卡片异常显示问题
|
||||
>- 优化影片详情以及播放页的组件背景显示问题
|
||||
>- 采集优化, 采集逻辑大幅度改动, 主站点采集前进行分类设置(将不需要的分类设置为不展示), 可精简采集内容
|
||||
>- 数据存储方式变更, 主附站点数据存储转为MySQL存储, 减少Redis内存消耗
|
||||
>- 更新采集内容缓存, 通过定时任务(每周日凌晨四点)统一同步到MySQL, 降低MySQL数据更新频率
|
||||
>- 资源匹配逻辑修改, 变更对不同站点的影片匹配逻辑
|
||||
>- DockerFile 更新, 由于golang版本以及相关依赖升级导致旧文件无法正常构建镜像.
|
||||
>- UI 不分列表展示区域数据重复问题
|
||||
>- 播放页逻辑变更, 更换播放器为 `xgplayer`
|
||||
>
|
||||
>后续计划:
|
||||
>
|
||||
>- 新增功能测试 && buf修复
|
||||
>- 完善历史观看界面功能 && 优化相应UI组件
|
||||
>- 针对播放器进行优化 OR 更换播放器组件
|
||||
>- 采集方式细节化, 实现定向采集以及单一影片的实时手动更新功能
|
||||
>- 优化UI组件
|
||||
>- 针对播放器进行BUG测试优化以及功能完善
|
||||
>- 采集方式细节化, 实现采集数据的精简
|
||||
>- 聚合采集, 实现通过影片名称搜索动态添加数据到站点中
|
||||
|
||||
## 目录结构
|
||||
|
||||
|
||||
@@ -118,7 +118,7 @@ server: {
|
||||
|
||||
4. 执行 `npm run build` 将项目进行打包构建
|
||||
5. 将打包后生成的 dist目录中的所有文件复制到 nginx的 html文件夹下
|
||||
6. 使用浏览器访问 nginx 的服务地址, 例: IP:Port, http://localhost:3600
|
||||
6. 使用浏览器访问 nginx 的服务地址, 例: IP:Port, http://localhost:3600 或 http://127.0.0.1:3600
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -160,3 +160,4 @@
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -56,6 +56,7 @@ onMounted(() => {
|
||||
width: "",
|
||||
height: "",
|
||||
autoplay: data.options.autoplay,
|
||||
miniprogress: true,
|
||||
lang: 'zh-cn', // 设置语言为中文
|
||||
volume: 0.7, // 初始音量
|
||||
playbackRate:[3, 2, 1.5, 1, 0.75, 0.5],
|
||||
@@ -82,6 +83,7 @@ onMounted(() => {
|
||||
hideDefaultControls: true,
|
||||
pressRate: 3,//长按倍速
|
||||
disablePress: false,
|
||||
miniprogress: true,
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<template>
|
||||
<div class="player_area" v-show="data.loading">
|
||||
<div ref="playerContainer" class="player_p"/>
|
||||
<div id="player-full" />
|
||||
<div ref="playerContainer" class="player_p" @touchmove.prevent @wheel.prevent />
|
||||
<div class="current_play_info">
|
||||
<div class="play_info_left">
|
||||
<h3 class="current_play_title"><a
|
||||
@@ -207,7 +208,6 @@ const saveFilmHistory = () => {
|
||||
// 在浏览器关闭前或页面刷新前将当前影片的观看信息存入历史记录中
|
||||
window.addEventListener('beforeunload', saveFilmHistory)
|
||||
|
||||
|
||||
// 初始化页面数据
|
||||
onBeforeMount(() => {
|
||||
let query = router.currentRoute.value.query
|
||||
@@ -240,6 +240,7 @@ onBeforeMount(() => {
|
||||
poster: posterImg,
|
||||
width: "",
|
||||
height: "",
|
||||
fluid: true,
|
||||
autoplay: data.options.autoplay,
|
||||
lang: 'zh-cn', // 设置语言为中文
|
||||
volume: 0.7, // 初始音量
|
||||
@@ -248,9 +249,7 @@ onBeforeMount(() => {
|
||||
urlList: data.options.urls,
|
||||
},
|
||||
playsinline: true,
|
||||
// "x5-playsinline": true, // 针对腾讯 X5 内核(微信、QQ、部分安卓)
|
||||
// "x5-video-player-type": "h5-page", // 关键:使用同层播放器
|
||||
// "webapp-role": "foo", // 某些特定环境下的 hack
|
||||
miniprogress: true,
|
||||
"x5-video-orientation": "landscape",
|
||||
"x5-video-player-fullscreen": "true",
|
||||
plugins: [HlsPlugin, playListPlugin],
|
||||
@@ -270,13 +269,10 @@ onBeforeMount(() => {
|
||||
},
|
||||
keyboard: {playbackRate: 3},
|
||||
mobile: {
|
||||
disableGesture: true,
|
||||
// controls: true,
|
||||
rotateFullScreen: true,
|
||||
rotateFullscreen: true,
|
||||
hideDefaultControls: true,
|
||||
gestureX: true,
|
||||
gestureYL: true,
|
||||
disableVolume: true,
|
||||
gestureY: true,
|
||||
scopeR: 0.15,
|
||||
pressRate: 3,//长按倍速
|
||||
disablePress: false,
|
||||
@@ -318,10 +314,8 @@ watch(data.options, (newVal) => {
|
||||
mPlayer.play()
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
// 自定义播放列表插件
|
||||
const {POSITIONS} = Plugin
|
||||
|
||||
class playListPlugin extends Plugin {
|
||||
// 插件的名称,将作为插件实例的唯一key值
|
||||
static get pluginName() {
|
||||
@@ -374,7 +368,7 @@ class playListPlugin extends Plugin {
|
||||
}
|
||||
el.addEventListener('wheel', (e:any)=> {
|
||||
e.preventDefault()
|
||||
this.listContainer && (this.listContainer.scrollTop += e.deltaY+50)
|
||||
this.listContainer && (this.listContainer.scrollTop += e.deltaY)
|
||||
});
|
||||
this.listContainer && this.listContainer.appendChild(el);
|
||||
})
|
||||
@@ -438,20 +432,50 @@ class playListPlugin extends Plugin {
|
||||
</script>
|
||||
|
||||
<style>
|
||||
/*xgplayer 样式修改*/
|
||||
.xg-right-grid .icon-dianying1 {
|
||||
display: block;
|
||||
color: #ffffff;
|
||||
padding: 0;
|
||||
font-size: 25px;
|
||||
font-size: 16px;
|
||||
line-height: 40px;
|
||||
}
|
||||
|
||||
.xgplayer-playlist-wrapper {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
}
|
||||
.xgplayer-playnext .xgplayer-icon svg {
|
||||
width: 15px;
|
||||
}
|
||||
.xgplayer xg-icon:not(.xgplayer-playnext) svg {
|
||||
width: 20px;
|
||||
}
|
||||
.xgplayer .xgplayer-progress-btn{
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
border-radius: 10px;
|
||||
}
|
||||
.xgplayer .xgplayer-progress-btn:before{
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border-radius: 8px;
|
||||
}
|
||||
.xgplayer .flex-controls .xg-inner-controls{
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
@media only screen and (orientation: landscape) {
|
||||
.xgplayer-mobile.xgplayer-is-fullscreen .xg-top-bar, .xgplayer-mobile.xgplayer-is-fullscreen .xg-pos{
|
||||
left: 3%;
|
||||
right: 3%;
|
||||
}
|
||||
.xgplayer .xgplayer-playnext svg{
|
||||
width: 16px !important;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.playListContainer {
|
||||
display: none;
|
||||
@@ -488,12 +512,10 @@ class playListPlugin extends Plugin {
|
||||
|
||||
</style>
|
||||
|
||||
<!--公共样式-->
|
||||
<style scoped>
|
||||
@import "/src/assets/css/film.css";
|
||||
/*vue3-video-play 相关设置*/
|
||||
/*//播放器控件区域大小*/
|
||||
|
||||
|
||||
/*公共样式区域*/
|
||||
/*当前播放的影片信息展示*/
|
||||
.current_play_info {
|
||||
width: 100%;
|
||||
@@ -542,52 +564,6 @@ class playListPlugin extends Plugin {
|
||||
min-height: 100%;
|
||||
}
|
||||
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.player_area {
|
||||
padding: 10px 6%;
|
||||
}
|
||||
|
||||
.tags a {
|
||||
padding: 5px 10px;
|
||||
/* background-color: rgba(155, 73, 231, 0.72);*/
|
||||
background: linear-gradient(#9B49E7B8, #9B49E799);
|
||||
color: #c4c2c2;
|
||||
font-size: 13px;
|
||||
border-radius: 6px;
|
||||
margin-right: 15px;
|
||||
}
|
||||
|
||||
.tags span {
|
||||
padding: 6px 12px;
|
||||
/*background-color: #404042;*/
|
||||
background: linear-gradient(#fff2, #ffffff1a);
|
||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||
color: #b5b2b2;
|
||||
border-radius: 5px;
|
||||
margin: 0 8px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.play_content a {
|
||||
white-space: nowrap;
|
||||
font-size: 12px;
|
||||
min-width: calc(10% - 24px);
|
||||
padding: 6px 10px;
|
||||
color: #ffffff;
|
||||
border-radius: 6px;
|
||||
margin: 8px 12px;
|
||||
background: #888888;
|
||||
}
|
||||
|
||||
.play_info_right a:hover {
|
||||
color: #FFBB5C;
|
||||
background: rgb(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
.player_p {
|
||||
width: 100%;
|
||||
aspect-ratio: 16 / 9;
|
||||
@@ -630,11 +606,15 @@ class playListPlugin extends Plugin {
|
||||
|
||||
</style>
|
||||
|
||||
<!--移动端-->
|
||||
<!--移动端 && pc端-->
|
||||
<style scoped>
|
||||
|
||||
/*适应小尺寸*/
|
||||
@media (max-width: 768px) {
|
||||
:deep(.xgplayer xg-start-inner){
|
||||
border-radius: 50%!important;
|
||||
background: rgba(0, 0, 0, .38)!important;
|
||||
}
|
||||
.player_area {
|
||||
padding: 5px 10px;
|
||||
}
|
||||
@@ -696,6 +676,51 @@ class playListPlugin extends Plugin {
|
||||
background: rgb(0, 0, 0, 0.2);
|
||||
}
|
||||
}
|
||||
|
||||
/*pc端样式*/
|
||||
@media (min-width: 768px) {
|
||||
.player_area {
|
||||
padding: 10px 6%;
|
||||
}
|
||||
|
||||
.tags a {
|
||||
padding: 5px 10px;
|
||||
/* background-color: rgba(155, 73, 231, 0.72);*/
|
||||
background: linear-gradient(#9B49E7B8, #9B49E799);
|
||||
color: #c4c2c2;
|
||||
font-size: 13px;
|
||||
border-radius: 6px;
|
||||
margin-right: 15px;
|
||||
}
|
||||
|
||||
.tags span {
|
||||
padding: 6px 12px;
|
||||
/*background-color: #404042;*/
|
||||
background: linear-gradient(#fff2, #ffffff1a);
|
||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||
color: #b5b2b2;
|
||||
border-radius: 5px;
|
||||
margin: 0 8px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.play_content a {
|
||||
white-space: nowrap;
|
||||
font-size: 12px;
|
||||
min-width: calc(10% - 24px);
|
||||
padding: 6px 10px;
|
||||
color: #ffffff;
|
||||
border-radius: 6px;
|
||||
margin: 8px 12px;
|
||||
background: #888888;
|
||||
}
|
||||
|
||||
.play_info_right a:hover {
|
||||
color: #FFBB5C;
|
||||
background: rgb(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
|
||||
@@ -1,17 +1,27 @@
|
||||
FROM golang:latest
|
||||
FROM golang:tip-alpine3.23 AS builder
|
||||
|
||||
ENV GO111MODULE=auto \
|
||||
CGO_ENABLED=0 \
|
||||
GOOS=linux \
|
||||
GOARCH=amd64 \
|
||||
GOPROXY=https://goproxy.cn,direct
|
||||
RUN apk add --no-cache ca-certificates git build-base
|
||||
|
||||
MAINTAINER "bai"
|
||||
|
||||
WORKDIR /opt/server
|
||||
|
||||
ADD ./server /opt/server
|
||||
|
||||
RUN go build main.go
|
||||
|
||||
EXPOSE 3061
|
||||
|
||||
|
||||
WORKDIR /build
|
||||
|
||||
COPY ./server/go.mod ./server/go.sum ./
|
||||
RUN --mount=type=cache,target=/go/pkg/mod \
|
||||
go mod download
|
||||
|
||||
|
||||
COPY ./server .
|
||||
|
||||
|
||||
RUN --mount=type=cache,target=/root/.cache/go-build \
|
||||
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 \
|
||||
go build -ldflags="-s -w" -o /build/gofilm ./main.go
|
||||
|
||||
|
||||
FROM scratch
|
||||
|
||||
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
|
||||
COPY --from=builder /build/gofilm /gofilm
|
||||
|
||||
ENTRYPOINT ["/gofilm"]
|
||||
|
||||
@@ -136,7 +136,9 @@ mysql:
|
||||
|
||||
### 5. 管理后台基本使用说明
|
||||
|
||||
- 访问 http://xxx.xxx.xxx/manage 进行登录, 用户名 密码: `admin admin` , 登录成功后自行修改
|
||||
- 详情使用说明前往: [MuBaiBoat](https://blog.mubai.link/procedure/application/github/GoFilm/)个人博客观看
|
||||
|
||||
- 访问 http://xxx.xxx.xxx/manage 进行登录, 初始用户名/密码: `admin admin` , 登录成功后自行修改
|
||||
- 使用 `采集管理 -> 影视采集` 功能进行采集站信息的添加和更新, 系统初始化时有预留站点信息, 自行斟酌选择
|
||||
- 首先选择一个站点为主站点, 然后选择 采集一周, 一天, 或 全部, 进行主站点的数据采集, (前台数据全来自于主站点, 因此主站点只需要存在一个, 否则会冲突)
|
||||
- 主站点信息采集完成后则可在 影片管理 -> 影视分类 中进行主页分类展示信息的设置, 选择需要展示的分类信息, 以及分类的名称管理 (自行摸索如何使用)
|
||||
@@ -144,4 +146,6 @@ mysql:
|
||||
- 定时任务:
|
||||
- 系统默认添加一条规则, 但未启用, 该规则为每20分钟更新一次所有已开启的采集站的近3小时内更新的数据, 开启后则基本满足资源更新需求
|
||||
- 可自定义定时任务, 使用相关功能可自主选择对某些站点进行定时更新功能
|
||||
- 每周日对采集失败的记录进行二次采集处理
|
||||
- 每周日对近期采集数据进行同步入库
|
||||
|
||||
|
||||
290
film/data/nginx/html/assets/index-C7tICDmk.js
Normal file
290
film/data/nginx/html/assets/index-C7tICDmk.js
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
1
film/data/nginx/html/assets/index-DYf3Lkog.css
Normal file
1
film/data/nginx/html/assets/index-DYf3Lkog.css
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -11,8 +11,8 @@
|
||||
<meta charset="UTF-8"/>
|
||||
<title>(╥﹏╥)</title>
|
||||
<link rel="stylesheet" href="//at.alicdn.com/t/c/font_3992367_d9xdu8zk04f.css">
|
||||
<script type="module" crossorigin src="/assets/index-ChHS3BBc.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-b0J83Qwy.css">
|
||||
<script type="module" crossorigin src="/assets/index-C7tICDmk.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-DYf3Lkog.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
|
||||
@@ -102,7 +102,6 @@ const (
|
||||
FailureRecordTableName = "failure_records"
|
||||
|
||||
//mysql服务配置信息 root:root 设置mysql账户的用户名和密码
|
||||
|
||||
MysqlDsn = "root:root@(mysql:3306)/FilmSite?charset=utf8mb4&parseTime=True&loc=Local"
|
||||
|
||||
// Redis连接信息
|
||||
|
||||
@@ -177,6 +177,7 @@ func DelSlaveMovieInfos(id string) {
|
||||
//}
|
||||
}
|
||||
|
||||
// AddMovieDetailIndex 添加详情表索引
|
||||
func AddMovieDetailIndex() {
|
||||
var m MovieDetail
|
||||
tableName := m.TableName()
|
||||
@@ -184,14 +185,16 @@ func AddMovieDetailIndex() {
|
||||
db.Mdb.Exec(fmt.Sprintf("CREATE UNIQUE INDEX idx_mid ON %s (mid)", tableName))
|
||||
}
|
||||
|
||||
// AddSlaveMovieInfoIndex 添加附属站点信息表索引
|
||||
func AddSlaveMovieInfoIndex() {
|
||||
var s SlaveMovieInfo
|
||||
tableName := s.TableName()
|
||||
// 如果不存在索引则创建对应索引
|
||||
if !db.Mdb.Migrator().HasIndex(&s, "idx_mid") {
|
||||
// 添加索引
|
||||
db.Mdb.Exec(fmt.Sprintf("CREATE INDEX idx_mid ON %s (mid)", tableName))
|
||||
db.Mdb.Exec(fmt.Sprintf("CREATE INDEX idx_dbId ON %s (db_id)", tableName))
|
||||
db.Mdb.Exec(fmt.Sprintf("CREATE INDEX idx_sid ON %s (sid DESC)", tableName))
|
||||
db.Mdb.Exec(fmt.Sprintf("CREATE INDEX idx_mid ON %s (mid DESC)", tableName))
|
||||
db.Mdb.Exec(fmt.Sprintf("CREATE INDEX idx_dbId ON %s (db_id DESC", tableName))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -312,7 +315,7 @@ func BatchUpdateDetails(ml []MovieDetail) (err error) {
|
||||
// ExistMovieDetailByMid 通过mid判断是否存在对应信息
|
||||
func ExistMovieDetailByMid(mid int64) bool {
|
||||
var count int64
|
||||
db.Mdb.Model(&SearchInfo{}).Where("mid", mid).Count(&count)
|
||||
db.Mdb.Model(&MovieDetail{}).Where("mid", mid).Count(&count)
|
||||
return count > 0
|
||||
}
|
||||
|
||||
@@ -440,12 +443,32 @@ func SlaveDetailCache(id string, ml []MovieDetail) error {
|
||||
// 只执行保存操作, 不考虑更新情况
|
||||
s := SlaveMovieInfo{Sid: id, Mid: GenerateHashKey(m.Name), DbId: m.DbId, PlayList: m.PlayList}
|
||||
r, _ := json.Marshal(s)
|
||||
data[s.Mid] = string(r)
|
||||
// redis中的存储key优先db_id
|
||||
if s.DbId > 0 {
|
||||
data[fmt.Sprintf("%d", s.DbId)] = string(r)
|
||||
} else {
|
||||
data[s.Mid] = string(r)
|
||||
}
|
||||
}
|
||||
// 使用 Sid:Mid为key, 用以区分不同站点数据
|
||||
return db.Rdb.HSet(db.Cxt, fmt.Sprintf(config.MultipleSiteDetailKey, id), data).Err()
|
||||
}
|
||||
|
||||
// GetSlaveDetailInCache 从redis缓存中获取播放信息
|
||||
func GetSlaveDetailInCache(sid, mid string) SlaveMovieInfo {
|
||||
// 初始化返回值
|
||||
var s SlaveMovieInfo
|
||||
v, err := db.Rdb.HGet(db.Cxt, fmt.Sprintf(config.MultipleSiteDetailKey, sid), mid).Result()
|
||||
if err != nil {
|
||||
// 如果没有获取到对应值, 则直接continue
|
||||
//log.Println("Get MultipleSiteDetail Failed: ", err)
|
||||
return s
|
||||
}
|
||||
// 如果获取到数据则直接退出本次循环
|
||||
_ = json.Unmarshal([]byte(v), &s)
|
||||
return s
|
||||
}
|
||||
|
||||
// SyncMovieDetail 同步redis中的影片数据到mysql中
|
||||
func SyncMovieDetail(sid string, grade SourceGrade, mode int) {
|
||||
// 初始化游标
|
||||
@@ -554,8 +577,7 @@ func GetDetailByMid(mid int64) MovieDetail {
|
||||
if err != nil {
|
||||
// 如果没有获取到对应值, 则去mysql中进行查找
|
||||
if errors.Is(err, redis.Nil) {
|
||||
if err := db.Mdb.Model(&MovieDetail{}).Select("id, mid, cid, pid, name, sub_title, c_name, state, picture, actor, director,"+
|
||||
" content, remarks, area, year").Where("mid = ?", mid).Find(&m).Error; err != nil {
|
||||
if err := db.Mdb.Where("mid = ?", mid).Find(&m).Error; err != nil {
|
||||
log.Println("Find BasicInfo Failed: ", err)
|
||||
return m
|
||||
}
|
||||
@@ -631,7 +653,7 @@ func GetBasicInfoByIds(ids []int64) []MovieBasicInfo {
|
||||
// 如果存在nil值,则去mysql进行补全
|
||||
if len(newIds) > 0 {
|
||||
if err := db.Mdb.Model(&MovieDetail{}).Select("id, mid, cid, pid, name, sub_title, c_name, state, picture, actor, director,"+
|
||||
" content, remarks, area, year").Where("mid IN (?)", ids).Find(&ml).Error; err != nil {
|
||||
" content, remarks, area, year").Where("mid IN (?)", newIds).Find(&ml).Error; err != nil {
|
||||
log.Println("BatchFind BasicInfo Failed: ", err)
|
||||
return nil
|
||||
}
|
||||
@@ -747,17 +769,26 @@ func GetMultiplePlay(mIds []string, dbId int64) []SlaveMovieInfo {
|
||||
continue
|
||||
}
|
||||
var s SlaveMovieInfo
|
||||
// 优先使用dbID为key去redis中获取
|
||||
if s = GetSlaveDetailInCache(c.Id, fmt.Sprintf("%d", dbId)); s.Mid != "" {
|
||||
l = append(l, s)
|
||||
continue
|
||||
}
|
||||
for _, mid := range mIds {
|
||||
// 初始化临时变量 SlaveMovieInfo
|
||||
v, err := db.Rdb.HGet(db.Cxt, fmt.Sprintf(config.MultipleSiteDetailKey, c.Id), mid).Result()
|
||||
if err != nil {
|
||||
// 如果没有获取到对应值, 则直接continue
|
||||
continue
|
||||
if s = GetSlaveDetailInCache(c.Id, mid); s.Mid != "" {
|
||||
l = append(l, s)
|
||||
break
|
||||
}
|
||||
// 如果获取到数据则直接退出本次循环
|
||||
_ = json.Unmarshal([]byte(v), &s)
|
||||
l = append(l, s)
|
||||
break
|
||||
//v, err := db.Rdb.HGet(db.Cxt, fmt.Sprintf(config.MultipleSiteDetailKey, c.Id), mid).Result()
|
||||
//if err != nil {
|
||||
// // 如果没有获取到对应值, 则直接continue
|
||||
// continue
|
||||
//}
|
||||
//// 如果获取到数据则直接退出本次循环
|
||||
//_ = json.Unmarshal([]byte(v), &s)
|
||||
//l = append(l, s)
|
||||
//break
|
||||
}
|
||||
// 如果迭代完s依旧为空,则去mysql中进行匹配
|
||||
if s.Mid == "" {
|
||||
|
||||
@@ -27,8 +27,8 @@ func InitMysql() (err error) {
|
||||
//NameReplacer: strings.NewReplacer("spider_", ""), // 替表名和字段中的 Me 为 空
|
||||
},
|
||||
//Logger: logger.Default.LogMode(logger.Warn), //设置日志级别为Info
|
||||
Logger: logger.Default.LogMode(logger.Info), //设置日志级别为Info
|
||||
//Logger: logger.Default.LogMode(logger.Error), //设置日志级别为Info
|
||||
//Logger: logger.Default.LogMode(logger.Info), //设置日志级别为Info
|
||||
Logger: logger.Default.LogMode(logger.Error), //设置日志级别为Info
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
@@ -84,10 +84,20 @@ server
|
||||
|
||||
### 本地运行
|
||||
|
||||
1. 修改 /server/plugin/db 目录下的 mysql.go 和 redis.go 中的连接地址和用户名密码
|
||||
2. 在 server 目录下执行 `go run main.go`
|
||||
1. 数据库初始化, 本地需要有 MySQL 和 Redis 数据库, MySQL中需手动创建名为 `FilmSite` 的数据库
|
||||
2. 修改 `server/config/DataConfig.go` 目录下的 mysql.go 和 redis.go 中的连接地址和用户名密码
|
||||
|
||||
```go
|
||||
|
||||
// mysql连接配置信息
|
||||
MysqlDsn = "root:root@(192.168.20.5:3601)/FilmSite?charset=utf8mb4&parseTime=True&loc=Local"
|
||||
// redis连接配置信息
|
||||
RedisAddr = `192.168.20.5:3602`
|
||||
RedisPassword = `root`
|
||||
RedisDBNo = 0
|
||||
```
|
||||
|
||||
3. 在 server 目录下执行 `go run main.go`
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -315,7 +315,7 @@ func BatchUpdateDetails(ml []MovieDetail) (err error) {
|
||||
// ExistMovieDetailByMid 通过mid判断是否存在对应信息
|
||||
func ExistMovieDetailByMid(mid int64) bool {
|
||||
var count int64
|
||||
db.Mdb.Model(&SearchInfo{}).Where("mid", mid).Count(&count)
|
||||
db.Mdb.Model(&MovieDetail{}).Where("mid", mid).Count(&count)
|
||||
return count > 0
|
||||
}
|
||||
|
||||
@@ -443,12 +443,32 @@ func SlaveDetailCache(id string, ml []MovieDetail) error {
|
||||
// 只执行保存操作, 不考虑更新情况
|
||||
s := SlaveMovieInfo{Sid: id, Mid: GenerateHashKey(m.Name), DbId: m.DbId, PlayList: m.PlayList}
|
||||
r, _ := json.Marshal(s)
|
||||
data[s.Mid] = string(r)
|
||||
// redis中的存储key优先db_id
|
||||
if s.DbId > 0 {
|
||||
data[fmt.Sprintf("%d", s.DbId)] = string(r)
|
||||
} else {
|
||||
data[s.Mid] = string(r)
|
||||
}
|
||||
}
|
||||
// 使用 Sid:Mid为key, 用以区分不同站点数据
|
||||
return db.Rdb.HSet(db.Cxt, fmt.Sprintf(config.MultipleSiteDetailKey, id), data).Err()
|
||||
}
|
||||
|
||||
// GetSlaveDetailInCache 从redis缓存中获取播放信息
|
||||
func GetSlaveDetailInCache(sid, mid string) SlaveMovieInfo {
|
||||
// 初始化返回值
|
||||
var s SlaveMovieInfo
|
||||
v, err := db.Rdb.HGet(db.Cxt, fmt.Sprintf(config.MultipleSiteDetailKey, sid), mid).Result()
|
||||
if err != nil {
|
||||
// 如果没有获取到对应值, 则直接continue
|
||||
//log.Println("Get MultipleSiteDetail Failed: ", err)
|
||||
return s
|
||||
}
|
||||
// 如果获取到数据则直接退出本次循环
|
||||
_ = json.Unmarshal([]byte(v), &s)
|
||||
return s
|
||||
}
|
||||
|
||||
// SyncMovieDetail 同步redis中的影片数据到mysql中
|
||||
func SyncMovieDetail(sid string, grade SourceGrade, mode int) {
|
||||
// 初始化游标
|
||||
@@ -749,17 +769,26 @@ func GetMultiplePlay(mIds []string, dbId int64) []SlaveMovieInfo {
|
||||
continue
|
||||
}
|
||||
var s SlaveMovieInfo
|
||||
// 优先使用dbID为key去redis中获取
|
||||
if s = GetSlaveDetailInCache(c.Id, fmt.Sprintf("%d", dbId)); s.Mid != "" {
|
||||
l = append(l, s)
|
||||
continue
|
||||
}
|
||||
for _, mid := range mIds {
|
||||
// 初始化临时变量 SlaveMovieInfo
|
||||
v, err := db.Rdb.HGet(db.Cxt, fmt.Sprintf(config.MultipleSiteDetailKey, c.Id), mid).Result()
|
||||
if err != nil {
|
||||
// 如果没有获取到对应值, 则直接continue
|
||||
continue
|
||||
if s = GetSlaveDetailInCache(c.Id, mid); s.Mid != "" {
|
||||
l = append(l, s)
|
||||
break
|
||||
}
|
||||
// 如果获取到数据则直接退出本次循环
|
||||
_ = json.Unmarshal([]byte(v), &s)
|
||||
l = append(l, s)
|
||||
break
|
||||
//v, err := db.Rdb.HGet(db.Cxt, fmt.Sprintf(config.MultipleSiteDetailKey, c.Id), mid).Result()
|
||||
//if err != nil {
|
||||
// // 如果没有获取到对应值, 则直接continue
|
||||
// continue
|
||||
//}
|
||||
//// 如果获取到数据则直接退出本次循环
|
||||
//_ = json.Unmarshal([]byte(v), &s)
|
||||
//l = append(l, s)
|
||||
//break
|
||||
}
|
||||
// 如果迭代完s依旧为空,则去mysql中进行匹配
|
||||
if s.Mid == "" {
|
||||
|
||||
@@ -27,8 +27,8 @@ func InitMysql() (err error) {
|
||||
//NameReplacer: strings.NewReplacer("spider_", ""), // 替表名和字段中的 Me 为 空
|
||||
},
|
||||
//Logger: logger.Default.LogMode(logger.Warn), //设置日志级别为Info
|
||||
Logger: logger.Default.LogMode(logger.Info), //设置日志级别为Info
|
||||
//Logger: logger.Default.LogMode(logger.Error), //设置日志级别为Info
|
||||
//Logger: logger.Default.LogMode(logger.Info), //设置日志级别为Info
|
||||
Logger: logger.Default.LogMode(logger.Error), //设置日志级别为Info
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user