1、去重

2、分享
3、视频播放
4、批量删除,重新下载
5、自定义标题(仅博主视频)
6、授权页面去掉博主添加,新增关注列表
7、图文视频合成优化
8、其他优化
This commit is contained in:
jianzhichu
2025-11-30 00:42:25 +08:00
parent 63b51d211e
commit e6e9ff3cc3
94 changed files with 8155 additions and 1544 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 128 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 168 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<movie>
<title>打工人必备3个邪修办公工具,早用早下班!!#办公技巧 #干货分享 #文员 #找工作 #vlog日常</title>
<author>丸子不是圆子</author>
<releasedate>2025-11-14</releasedate>
<genre>个人管理</genre>
<genre>职场技能</genre>
<genre>办公效率</genre>
<actors>
<actor>
<name>丸子不是圆子</name>
<role>主演</role>
<thumb>app/coll2\author\3833318009221843.jpg</thumb>
</actor>
</actors>
<thumb aspect="poster">poster.jpg</thumb>
<fanart>
<thumb>poster.jpg</thumb>
</fanart>
</movie>
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<movie>
<title>冬天穿羽绒服就扎这三款丸子头 #简单盘发教程 #扎发教程 #简单好看发型 #日常编发 #盘发</title>
<author>爱编发的小童</author>
<releasedate>2025-11-19</releasedate>
<genre>时尚</genre>
<genre>彩妆</genre>
<genre>发型</genre>
<actors>
<actor>
<name>爱编发的小童</name>
<role>主演</role>
<thumb>app/coll2\author\2253324655537024.jpg</thumb>
</actor>
</actors>
<thumb aspect="poster">poster.jpg</thumb>
<fanart>
<thumb>poster.jpg</thumb>
</fanart>
</movie>
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<movie>
<title>“最好的医生”其实就在你身边,医生眼里的“最好”:白开水、阳光、徒步……</title>
<author>新华社</author>
<releasedate>2025-11-07</releasedate>
<genre>时政社会</genre>
<genre>社会新闻</genre>
<genre>民生</genre>
<actors>
<actor>
<name>新华社</name>
<role>主演</role>
<thumb>app/coll2\author\93288642596.jpg</thumb>
</actor>
</actors>
<thumb aspect="poster">poster.jpg</thumb>
<fanart>
<thumb>poster.jpg</thumb>
</fanart>
</movie>
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<movie>
<title>披星戴月的日子值吗?男孩分享爸爸送给自己的一段话,自律的苦轻如鸿毛,后悔的痛重过千斤。</title>
<author>新华社</author>
<releasedate>2025-11-22</releasedate>
<genre>时政社会</genre>
<genre>社会新闻</genre>
<genre>民生</genre>
<actors>
<actor>
<name>新华社</name>
<role>主演</role>
<thumb>app/coll2\author\93288642596.jpg</thumb>
</actor>
</actors>
<thumb aspect="poster">poster.jpg</thumb>
<fanart>
<thumb>poster.jpg</thumb>
</fanart>
</movie>
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<movie>
<title>每天练一题,让孩子爱上数学!小学数学奥数竖式谜口诀解题技巧 #小学数学 #小学奥数 #小学数学解题技巧 #小学数学思维 #小学数学题讲解视频</title>
<author>懒熊数学思维(小学奥数)</author>
<releasedate>2025-11-25</releasedate>
<genre>校园教育</genre>
<genre>K12教育</genre>
<genre>学科教育</genre>
<actors>
<actor>
<name>懒熊数学思维(小学奥数)</name>
<role>主演</role>
<thumb>app/coll2\author\3432007521806423.jpg</thumb>
</actor>
</actors>
<thumb aspect="poster">poster.jpg</thumb>
<fanart>
<thumb>poster.jpg</thumb>
</fanart>
</movie>
Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<movie>
<title>万万没想到,文件传输助手竟如此全能 #文件传输助手 #冷知识</title>
<author>主持人阿喆</author>
<releasedate>2025-08-01</releasedate>
<genre>科普</genre>
<genre>冷知识</genre>
<actors>
<actor>
<name>主持人阿喆</name>
<role>主演</role>
<thumb>app/fav2\author\75856936333.jpg</thumb>
</actor>
</actors>
<thumb aspect="poster">poster.jpg</thumb>
<fanart>
<thumb>poster.jpg</thumb>
</fanart>
</movie>
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<movie>
<title>幸福的愿望 想念变成空气在叹息</title>
<author>小思宇</author>
<releasedate>2025-06-19</releasedate>
<genre>随拍</genre>
<genre>人物随拍</genre>
<genre>人物图片轮播</genre>
<actors>
<actor>
<name>小思宇</name>
<role>主演</role>
<thumb>app/fav2\author\2664814926116075.jpg</thumb>
</actor>
</actors>
<thumb aspect="poster">poster.jpg</thumb>
<fanart>
<thumb>poster.jpg</thumb>
</fanart>
</movie>
Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<movie>
<title>放假领她去帮我哥打包,体验生活的不容易。#生产车间现场 #拼命努力的挣钱 #工作实拍</title>
<author>郭小胖</author>
<releasedate>2024-07-20</releasedate>
<genre>随拍</genre>
<genre>生活记录</genre>
<genre>日常vlog</genre>
<actors>
<actor>
<name>郭小胖</name>
<role>主演</role>
<thumb>app/fav2\author\66899755406.jpg</thumb>
</actor>
</actors>
<thumb aspect="poster">poster.jpg</thumb>
<fanart>
<thumb>poster.jpg</thumb>
</fanart>
</movie>
+1 -1
View File
@@ -51,7 +51,7 @@
"babel-preset-es2015": "^6.24.1",
"babel-register": "^6.26.0",
"body-parser": "^1.20.1",
"crypto-js": "^4.1.1",
"crypto-js": "^4.2.0",
"gh-pages": "^3.1.0",
"gulp": "^4.0.2",
"gulp-clean": "^0.4.0",
+1 -2
View File
@@ -1,12 +1,11 @@
<script lang="ts" setup>
import { getBase64 } from '@/utils/file';
import { FormInstance } from 'ant-design-vue';
import { reactive, ref, onMounted } from 'vue';
import { reactive, ref, onMounted, UnwrapRef } from 'vue';
import dayjs from 'dayjs';
import { Dayjs } from 'dayjs';
import { EditFilled } from '@ant-design/icons-vue';
import { useApiStore } from '@/store';
import type { UnwrapRef } from 'vue';
import { message } from 'ant-design-vue';
import { StarOutlined, StarFilled, StarTwoTone } from '@ant-design/icons-vue';
+893
View File
@@ -0,0 +1,893 @@
<template>
<div class="dept-user-card-container">
<!-- 搜索框 + Tab导航 同一行布局 -->
<div class="search-tab-container">
<div class="tab-wrapper">
<a-tabs v-model:value="activeTabKey" type="line" class="custom-tabs" @change="handleTabChange">
<a-tab-pane v-for="tab in tabList" :key="tab.key" :tab="`${tab.name}(${tab.total || 0})`" />
</a-tabs>
</div>
<div class="search-area">
<!-- 搜索按钮 -->
<a-button type="default" class="search-btn" @click="toggleSearchInput">
<CloseOutlined v-if="searchInputVisible" />
<SearchOutlined v-else />
</a-button>
<transition name="search-input-fade">
<div v-if="searchInputVisible" class="search-input-wrapper">
<a-input v-model:value="quaryData.followUserName" placeholder="输入关注的用户名,按回车" allow-clear @pressEnter="handleSearch" class="search-input" ref="searchInputRef" />
</div>
</transition>
<!-- 同步按钮请求期间禁用 -->
<!-- <a-button type="primary" class="sync-btn" @click="handleSyncAll" :disabled="isSyncDisabled">
<SyncOutlined />
<span class="sync-btn-text">同步</span>
</a-button> -->
</div>
</div>
<!-- 卡片列表区域 -->
<div class="card-list-container" @scroll="handleScroll">
<a-card v-for="(item, index) in currentTabData" :key="item.id" :data-key="item.id" class="custom-card" :bordered="true" :hoverable="true">
<div class="card-inner">
<div class="card-switch">
<a-switch v-model:checked="item.openSync" @change="(checked) => handleSwitchChange(item, checked)" checked-children="" un-checked-children="" />
</div>
<div class="card-main-content">
<div class="avatar-wrapper">
<a-avatar shape="circle" size="large" :src="item.uperAvatar" v-if="item.uperAvatar" />
<a-avatar shape="circle" size="large" v-else class="avatar-placeholder">
{{ item.uperName.charAt(0) }}
</a-avatar>
</div>
<div class="card-content">
<div class="card-name">{{ item.uperName }}</div>
<!-- 签名多行显示高度控制 + 溢出截断 + Tooltip气泡 -->
<div class="card-desc">
<a-tooltip placement="top" :title="item.signature || '无签名'">
<span class="signature-text">
{{ item.signature || '无签名' }}
</span>
</a-tooltip>
</div>
<div class="card-path-sync-container">
<template v-if="!item.openSync">
<span class="path-placeholder"></span>
</template>
<template v-else>
<div class="path-area">
<template v-if="item.isEditing">
<div class="edit-input-group">
<!-- 输入框禁用item.isSaving true -->
<a-input v-model:value="item.savePath" placeholder="请输入文件夹名称" @keypress.enter="() => handleSavePath(item)" maxlength="10" :disabled="item.isSaving" />
<!-- 保存按钮禁用item.isSaving true -->
<a-button type="text" class="edit-btn" @click="() => handleSavePath(item)" :disabled="item.isSaving">
<SaveOutlined />
</a-button>
</div>
</template>
<template v-else>
<span class="path-text" :class="{ 'path-empty': !item.savePath }">
{{ item.savePath || '未设置存储文件夹名称' }}
</span>
<!-- 编辑按钮禁用item.isSaving true -->
<a-button type="text" class="edit-btn" @click="() => handleEditPath(item)" title="编辑文件夹名称" :disabled="item.isSaving">
<EditOutlined />
</a-button>
</template>
</div>
<div class="sync-switch-wrapper">
<span class="sync-label">全量同步</span>
<a-switch v-model:checked="item.fullSync" size="small" @change="(checked) => handleSyncChange(item, checked)" />
</div>
</template>
</div>
</div>
</div>
</div>
</a-card>
<!-- 加载状态 -->
<div v-if="loading" class="loading-container">
<a-spin size="middle" />
<span class="loading-text">加载中...</span>
</div>
<!-- 无更多数据 -->
<div v-if="noMoreData && followData.length > 0" class="no-more-container">暂无更多数据</div>
<!-- 空状态 -->
<div v-if="followData.length === 0 && !loading" class="empty-container">
<Empty description="暂无关注用户" />
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import { ref, computed, onMounted, onUnmounted, UnwrapRef, reactive, nextTick } from 'vue';
import { message, Spin, Empty, Tooltip } from 'ant-design-vue';
import { useApiStore } from '@/store';
import { SyncOutlined, CloseOutlined, SearchOutlined, SaveOutlined, EditOutlined } from '@ant-design/icons-vue';
// Tab列表数据
const tabList = ref<Array<{ key: string; name: string; total?: number }>>([]);
const activeTabKey = ref('');
// 关注用户列表数据:新增 isSaving 状态(控制保存期间按钮禁用)
const followData = ref<
Array<{
id: string;
mySelfId: string;
uperName: string;
enterprise: string;
signature: string;
uperAvatar: string;
fullSync: boolean;
openSync: boolean;
savePath?: string;
isEditing: boolean;
isSaving?: boolean; // 新增:保存中状态(true=禁用按钮)
}>
>([]);
// 状态变量
const loading = ref(false);
const noMoreData = ref(false);
const hasMore = ref(true);
const searchInputVisible = ref(false);
const searchInputRef = ref<HTMLInputElement | null>(null);
const isSyncDisabled = ref(false); // 同步按钮禁用状态
// 搜索参数
interface QuaryParam {
pageIndex: number;
pageSize: number;
followUserName: string | null;
mySelfId?: string;
}
const quaryData: UnwrapRef<QuaryParam> = reactive({
pageIndex: 0,
pageSize: 20,
followUserName: null,
mySelfId: '',
});
// 生命周期 - 挂载时初始化
onMounted(() => {
quaryData.pageIndex = 0;
GetCookies();
});
// 生命周期 - 卸载时移除滚动监听
onUnmounted(() => {
const cardContainer = document.querySelector('.dept-user-card-container .card-list-container');
if (cardContainer) {
cardContainer.removeEventListener('scroll', handleScroll);
}
});
// 获取Cookie列表(Tab数据)
const GetCookies = () => {
useApiStore()
.CookieList()
.then((res) => {
if (res.code === 0) {
const tabs = (res.data || [{ key: 'tab1', name: '部门一' }]).map((tab) => ({
...tab,
total: 0,
}));
tabList.value = tabs;
activeTabKey.value = tabList.value[0]?.key || '';
quaryData.mySelfId = activeTabKey.value;
GetFollows(true);
handleTabChange(activeTabKey.value);
}
});
};
// 获取关注用户列表
const GetFollows = (isReset = false) => {
if (loading.value || (noMoreData.value && !isReset)) return;
loading.value = true;
useApiStore()
.FollowList(quaryData)
.then((res) => {
if (res.code === 0) {
const newData = res.data.data || [];
const total = res.data.total || 0;
// 给新数据初始化 isSaving: false(避免未定义导致的禁用异常)
const formattedData = newData.map((item) => ({
...item,
isSaving: false, // 初始化保存中状态为false
isEditing: item.isEditing ?? false, // 兼容后端未返回isEditing的情况
}));
// 更新当前Tab的总数
if (isReset) {
const tabIndex = tabList.value.findIndex((tab) => tab.key === activeTabKey.value);
if (tabIndex !== -1) {
tabList.value[tabIndex].total = total;
}
}
// 判断是否还有更多数据
if (formattedData.length < quaryData.pageSize) {
noMoreData.value = true;
hasMore.value = false;
} else {
noMoreData.value = false;
hasMore.value = true;
}
// 合并数据(避免重复)
if (isReset) {
followData.value = formattedData;
} else {
const existingKeys = followData.value.map((item) => item.id);
const uniqueNewData = formattedData.filter((item) => !existingKeys.includes(item.id));
followData.value = [...followData.value, ...uniqueNewData];
}
quaryData.pageIndex += 1;
} else {
message.error('获取关注用户列表失败');
noMoreData.value = true;
hasMore.value = false;
}
})
.catch((err) => {
console.error('获取关注用户列表异常:', err);
message.error('网络异常,请重试');
noMoreData.value = true;
hasMore.value = false;
})
.finally(() => {
loading.value = false;
});
};
// 切换搜索框显示/隐藏
const toggleSearchInput = () => {
searchInputVisible.value = !searchInputVisible.value;
if (searchInputVisible.value) {
nextTick(() => {
searchInputRef.value?.focus();
});
} else {
// 隐藏时清空搜索条件并重新加载
if (quaryData.followUserName) {
quaryData.followUserName = null;
quaryData.pageIndex = 0;
GetFollows(true);
}
}
};
// 执行搜索
const handleSearch = () => {
quaryData.pageIndex = 0;
noMoreData.value = false;
hasMore.value = true;
GetFollows(true);
};
// Tab切换
const handleTabChange = (key: string) => {
activeTabKey.value = key;
quaryData.mySelfId = key;
quaryData.pageIndex = 0;
noMoreData.value = false;
hasMore.value = true;
searchInputVisible.value = false;
quaryData.followUserName = null;
GetFollows(true);
};
// 计算当前Tab的用户数据
const currentTabData = computed(() => {
return followData.value.filter((item) => item.mySelfId === activeTabKey.value);
});
// 滚动加载更多
const handleScroll = () => {
const cardContainer = document.querySelector('.dept-user-card-container .card-list-container');
if (!cardContainer || loading.value || !hasMore.value || noMoreData.value) return;
const { scrollTop, scrollHeight, clientHeight } = cardContainer as HTMLDivElement;
// 滚动到底部100px内时加载更多
if (scrollTop + clientHeight >= scrollHeight - 100) {
GetFollows(false);
}
};
// 开关状态变更(启用/禁用用户)
const handleSwitchChange = (item, checked) => {
item.openSync = checked;
if (!checked) item.isEditing = false; // 禁用时关闭编辑状态
if (!checked) {
uploadSyncStatus(item);
} else {
if (item.savePath.length > 0) {
uploadSyncStatus(item);
}
}
};
// 全量同步开关变更
const handleSyncChange = (item, checked) => {
item.fullSync = checked;
uploadFullSyncStatus(item);
};
// 编辑存储路径:增加防重复编辑(保存中不可编辑)
const handleEditPath = (item) => {
if (item.isSaving) return; // 正在保存时,禁止点击编辑
item.isEditing = true;
// 延迟聚焦输入框(确保DOM已更新)
setTimeout(() => {
const input = document.querySelector(
`.dept-user-card-container .custom-card[data-key="${item.id}"] .edit-input-group .ant-input`
) as HTMLInputElement | null;
input?.focus();
}, 100);
};
// 保存存储路径:增加按钮禁用逻辑
const handleSavePath = (item) => {
// 防止重复提交:正在保存时直接返回
if (item.isSaving) return;
uploadSyncStatus(item);
};
const uploadSyncStatus = (item) => {
item.isSaving = true;
useApiStore()
.OpenOrCloseSync({
Id: item.id,
OpenSync: item.openSync,
FullSync: item.fullSync,
SavePath: item.savePath, // 保持原有逻辑:提交 savePath
})
.then((res) => {
if (res.code === 0) {
message.success(`保存成功,将在下次任务执行时生效`);
item.isEditing = false; // 保存成功后关闭编辑状态
} else {
message.error('保存失败' + (res.msg || '未知错误'));
}
})
.catch((err) => {
console.error('保存失败', err);
message.error('保存失败,请重试');
})
.finally(() => {
// 接口响应结束:解除禁用(无论成功失败)
item.isSaving = false;
});
};
//全量同步开关
const uploadFullSyncStatus = (item) => {
item.isSaving = true;
useApiStore()
.OpenOrCloseFullSync({
Id: item.id,
OpenSync: item.openSync,
FullSync: item.fullSync,
SavePath: item.savePath, // 保持原有逻辑:提交 savePath
})
.then((res) => {
if (res.code === 0) {
message.success(`保存成功,将在下次任务执行时生效`);
item.isEditing = false; // 保存成功后关闭编辑状态
} else {
message.error('保存失败' + (res.msg || '未知错误'));
}
})
.catch((err) => {
console.error('保存失败', err);
message.error('保存失败,请重试');
})
.finally(() => {
// 接口响应结束:解除禁用(无论成功失败)
item.isSaving = false;
});
};
// 批量同步所有用户
const handleSyncAll = () => {
if (isSyncDisabled.value) return;
// 请求开始:禁用按钮+显示加载
isSyncDisabled.value = true;
loading.value = true;
useApiStore()
.SyncFollow()
.then((res) => {
if (res.code === 0) {
message.success('后台开始同步...根据您关注的数量,需要的时间不一定...请耐心等待');
} else {
message.error('同步失败:' + (res.msg || '未知错误'));
}
})
.catch((err) => {
console.error('同步异常:', err);
message.error('同步失败,请重试');
})
.finally(() => {
// 请求完成:解禁按钮+关闭加载
isSyncDisabled.value = false;
loading.value = false;
});
};
</script>
<style scoped>
/* 原有样式保持不变,无需修改 */
.dept-user-card-container {
max-width: 1500px;
margin: 0 auto;
padding: 10px;
min-height: 100vh;
}
/* 搜索+Tab容器 */
.search-tab-container {
display: flex;
justify-content: space-between;
align-items: center;
gap: 16px;
margin-bottom: 24px;
flex-wrap: wrap;
}
.tab-wrapper {
flex: 1;
min-width: 200px;
}
.search-area {
display: flex;
align-items: center;
gap: 8px;
transition: all 0.3s ease;
}
/* 同步按钮样式 */
.sync-btn {
height: 40px !important;
padding: 0 16px !important;
white-space: nowrap;
display: flex;
align-items: center;
gap: 6px;
transition: all 0.3s ease;
}
.sync-btn-text {
font-size: 14px;
}
/* 同步按钮禁用样式(浅色模式) */
.sync-btn:disabled {
background-color: #f5f5f5 !important;
border-color: #d9d9d9 !important;
color: #bfbfbf !important;
cursor: not-allowed !important;
opacity: 0.8;
}
/* 搜索按钮样式 */
.search-btn {
height: 40px !important;
padding: 0 16px !important;
white-space: nowrap;
}
.search-input-wrapper {
width: 280px;
transition: all 0.3s ease;
}
.search-input {
width: 100% !important;
height: 40px !important;
}
/* 搜索框过渡动画 */
.search-input-fade-enter-from,
.search-input-fade-leave-to {
width: 0 !important;
opacity: 0;
overflow: hidden;
}
.search-input-fade-enter-active,
.search-input-fade-leave-active {
transition: all 0.3s ease;
}
/* Tab样式 */
.custom-tabs {
border-radius: 12px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
overflow: hidden;
}
.ant-tabs-nav-list .ant-tabs-tab:first-child {
padding-left: 24px !important;
}
.ant-tabs-nav-list .ant-tabs-tab {
padding-left: 16px !important;
padding-right: 16px !important;
}
/* 卡片列表容器 */
.card-list-container {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(360px, 1fr));
gap: 28px !important;
max-height: calc(100vh - 140px);
overflow-y: auto;
padding-bottom: 40px;
}
/* 卡片样式 */
.custom-card {
border-radius: 12px !important;
box-shadow: none !important;
border: 1px solid #e5e7eb !important;
transition: all 0.3s ease !important;
overflow: hidden !important;
display: flex !important;
flex-direction: column !important;
background: transparent !important;
}
.custom-card:hover {
border-color: #c7d2fe !important;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08) !important;
}
.card-inner {
position: relative;
padding: 5px !important;
flex: 1 !important;
display: flex !important;
flex-direction: column !important;
}
/* 卡片开关位置 */
.card-switch {
position: absolute !important;
top: 12px;
right: 16px;
z-index: 10;
}
/* 卡片主要内容 */
.card-main-content {
display: flex;
align-items: flex-start; /* 改为顶部对齐,避免多行签名导致头像居中错位 */
gap: 20px;
margin-top: 8px !important;
flex: 1 !important;
}
/* 头像样式 */
.avatar-wrapper {
width: 64px;
height: 64px;
flex-shrink: 0;
margin-top: 4px; /* 微调头像位置,与多行签名对齐 */
}
.ant-avatar-lg {
width: 64px !important;
height: 64px !important;
}
.avatar-placeholder {
background: linear-gradient(135deg, #4096ff, #69b1ff);
color: #fff;
font-size: 24px;
font-weight: 600;
}
/* 卡片内容区域 */
.card-content {
flex: 1;
display: flex;
flex-direction: column;
gap: 4px; /* 缩小行间距,适配多行签名 */
margin: 4px 0;
}
.card-name {
font-size: 16px !important;
font-weight: 600;
color: #1d2129;
line-height: 1.4;
}
/* 核心修改:签名多行显示(高度控制) */
.card-desc {
font-size: 12px !important;
color: #86909c;
line-height: 1.5; /* 行高适配多行 */
width: 100%;
/* 保持原有宽度,不影响布局 */
}
.signature-text {
display: -webkit-box; /* 关键:启用弹性盒模型 */
width: 250px; /* 固定宽度(原300px不变) */
max-height: 54px; /* 控制显示行数:12px字体+1.5行高 → 2行=36px3行=54px */
line-height: 1.5; /* 行高,需与font-size配合计算高度 */
overflow: hidden; /* 隐藏溢出内容 */
text-overflow: ellipsis; /* 溢出显示省略号 */
-webkit-line-clamp: 3; /* 关键:限制显示2行(可改为3行) */
-webkit-box-orient: vertical; /* 垂直排列 */
cursor: pointer; /* 提示可悬停查看完整内容 */
word-break: break-all; /* 长单词/URL自动换行,避免横向溢出 */
}
/* 路径+同步开关容器 */
.card-path-sync-container {
display: flex;
align-items: center;
width: 100%;
height: 34px !important;
margin-top: 8px !important; /* 微调与签名的间距,适配多行 */
gap: 8px;
}
.path-area {
display: flex;
align-items: center;
gap: 8px;
flex: 1;
max-width: calc(100% - 120px);
overflow: hidden;
}
.path-placeholder {
width: 100%;
height: 100%;
}
.path-text {
font-size: 13px !important;
color: #4e5969;
flex: 1;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
height: 100%;
line-height: 34px !important;
}
.path-empty {
color: #c9cdd4;
font-style: italic;
}
/* 全量同步开关区域 */
.sync-switch-wrapper {
display: flex;
align-items: center;
gap: 8px;
white-space: nowrap;
width: 120px !important;
justify-content: flex-end;
}
.sync-label {
font-size: 12px !important;
color: #6b7280;
font-weight: 500;
}
/* 编辑按钮样式 */
.edit-btn {
width: 32px !important;
height: 32px !important;
padding: 0 !important;
margin: 0 !important;
border-radius: 50% !important;
display: flex !important;
align-items: center !important;
justify-content: center !important;
background: transparent !important;
color: #4096ff !important;
border: none !important;
}
.edit-btn .anticon {
font-size: 18px !important;
}
.edit-btn:hover {
background: transparent !important;
color: #2563eb !important;
}
.edit-input-group {
display: flex;
align-items: center;
gap: 8px;
width: 100%;
height: 100%;
}
.ant-input {
flex: 1;
height: 100% !important;
font-size: 13px !important;
}
:deep(.ant-card-body) {
padding: 0 !important;
height: 100% !important;
display: flex !important;
flex-direction: column !important;
padding: 1px !important;
}
.ant-card-bordered {
border-width: 1px !important;
}
/* 加载状态 */
.loading-container {
grid-column: 1 / -1;
display: flex;
align-items: center;
justify-content: center;
gap: 12px;
padding: 20px 0;
color: #6b7280;
}
.loading-text {
font-size: 14px;
}
/* 无更多数据 */
.no-more-container {
grid-column: 1 / -1;
display: flex;
align-items: center;
justify-content: center;
padding: 20px 0;
color: #9ca3af;
font-size: 14px;
}
/* 空状态 */
.empty-container {
grid-column: 1 / -1;
display: flex;
align-items: center;
justify-content: center;
padding: 40px 0;
}
/* 移动端适配 */
@media (max-width: 768px) {
.card-list-container {
grid-template-columns: 1fr !important;
gap: 20px !important;
max-height: calc(100vh - 180px);
}
.search-tab-container {
flex-direction: column;
align-items: flex-start;
}
.search-input-wrapper {
width: 100% !important;
}
.card-inner {
padding: 14px !important;
}
.custom-card {
height: auto !important; /* 移动端卡片高度自适应,避免多行签名溢出 */
}
.path-area {
max-width: calc(100% - 110px);
}
.sync-switch-wrapper {
width: 110px !important;
}
.sync-label {
font-size: 11px !important;
}
.sync-btn-text {
display: none;
}
.sync-btn {
padding: 0 12px !important;
}
.sync-btn:disabled {
padding: 0 12px !important;
}
/* 移动端签名样式调整 */
.signature-text {
width: 250px; /* 移动端宽度缩减 */
max-height: 30px; /* 移动端显示2行(12px字体+1.25行高) */
line-height: 1.25;
-webkit-line-clamp: 2; /* 保持2行显示 */
}
}
/* ====================================== */
/* 黑暗模式样式(html.dark-mode 强制生效) */
/* ====================================== */
html.dark-mode .dept-user-card-container .custom-card {
border-color: #374151 !important;
}
html.dark-mode .dept-user-card-container .custom-card:hover {
border-color: #6366f1 !important;
}
html.dark-mode .dept-user-card-container .ant-card-bordered {
border-color: #374151 !important;
}
html.dark-mode .dept-user-card-container .ant-card-bordered:hover {
border-color: #6366f1 !important;
}
html.dark-mode .dept-user-card-container .card-name {
color: #f3f4f6 !important;
}
html.dark-mode .dept-user-card-container .card-desc {
color: #9ca3af !important;
}
html.dark-mode .dept-user-card-container .path-text {
color: #d1d5db !important;
}
html.dark-mode .dept-user-card-container .path-empty {
color: #6b7280 !important;
}
html.dark-mode .dept-user-card-container .sync-label {
color: #9ca3af !important;
}
html.dark-mode .dept-user-card-container .loading-text,
html.dark-mode .dept-user-card-container .no-more-container span {
color: #9ca3af !important;
}
/* 黑暗模式下同步按钮样式 */
html.dark-mode .dept-user-card-container .sync-btn {
color: #d1d5db !important;
border-color: #4b5563 !important;
}
html.dark-mode .dept-user-card-container .sync-btn:hover {
color: #f3f4f6 !important;
border-color: #6b7280 !important;
background-color: rgba(255, 255, 255, 0.04) !important;
}
</style>
+205 -83
View File
@@ -6,26 +6,63 @@
<h3 class="section-title">任务调度</h3>
<a-form-item has-feedback label="同步周期(分钟)" name="Cron" :wrapper-col="{ span: 6}" style="margin-left:30px">
<!-- <a-input v-model:value="formState.Cron" placeholder="请输入数字" /> -->
<a-input-number v-model:value="formState.Cron" placeholder="请输入数字" :min="1" />
<a-input-number v-model:value="formState.Cron" placeholder="请输入数字" :min="15" />
<div class="flex items-start mt-1 text-sm text-gray-500">
<InfoCircleOutlined class="text-blue-400 mr-1 mt-0.5" />
<span>同步任务的执行间隔最小15分钟建议使用默认值</span>
</div>
</a-form-item>
<a-form-item has-feedback label="每次同步(条数)" name="BatchCount" :wrapper-col="{ span:6}" style="margin-left:30px">
<a-input-number v-model:value="formState.BatchCount" placeholder="请输入查询条数(最大30)" :min="10" :max="30" />
<div class="flex items-start mt-1 text-sm text-gray-500">
<InfoCircleOutlined class="text-blue-400 mr-1 mt-0.5" />
<span>每次同步获取的条数范围10-30建议使用默认值</span>
</div>
</a-form-item>
</div>
<!-- 文件保存配置 -->
<div class="form-section">
<h3 class="section-title">博主视频</h3>
<h3 class="section-title">博主视频仅关注有效</h3>
<a-form-item has-feedback label="标题当文件名" name="UperUseViedoTitle" :wrapper-col="{ span: 6 }">
<a-form-item has-feedback label="标题当文件名" name="UperUseViedoTitle" :wrapper-col="{ span: 20 }">
<a-switch v-model:checked="formState.UperUseViedoTitle" />
<div class="flex items-start mt-1 text-sm text-gray-500">
<InfoCircleOutlined class="text-blue-400 mr-1 mt-0.5" />
<span>启用后关注的视频文件名将直接使用原视频标题否则使用模板生成,如果既没有模板也没有开启则系统默认使用视频Id作为文件名</span>
</div>
</a-form-item>
<a-form-item has-feedback label="不创建子目录" name="UperSaveTogether" :wrapper-col="{ span: 6 }">
<a-form-item has-feedback label="不创建子目录" name="UperSaveTogether" :wrapper-col="{ span: 20 }">
<a-switch v-model:checked="formState.UperSaveTogether" />
<div class="flex items-start mt-1 text-sm text-gray-500">
<InfoCircleOutlined class="text-blue-400 mr-1 mt-0.5" />
<span>默认是按博主名字创建文件夹存储启用后关注的视频直接存放在根目录</span>
</div>
</a-form-item>
<!-- 模板相关配置只有关闭"标题当文件名"时才显示 -->
<a-form-item has-feedback label="定义标题模板" name="FollowedTitleTemplate" :wrapper-col="{ span: 12 }" v-if="!formState.UperUseViedoTitle">
<a-select v-model:value="formState.FollowedTitleTemplate" :options="template_options" mode="multiple" size="middle" placeholder="请选择"></a-select>
<div class="flex items-start mt-1 text-sm text-gray-500">
<InfoCircleOutlined class="text-blue-400 mr-1 mt-0.5" />
<span>选择生成文件名的占位符顺序即为文件名顺序需配合分隔符使用</span>
</div>
</a-form-item>
<a-form-item has-feedback label="模板分隔符" name="FollowedTitleSeparator" :wrapper-col="{ span: 12 }" v-if="!formState.UperUseViedoTitle">
<a-input v-model:value="formState.FollowedTitleSeparator" placeholder="请输入分隔符(如 - _ 或空)" style="width: 200px" />
<div class="flex items-start mt-1 text-sm text-gray-500">
<InfoCircleOutlined class="text-blue-400 mr-1 mt-0.5" />
<span>占位符之间的连接符-_为空则直接拼接</span>
</div>
</a-form-item>
<!-- 完整模板预览只有关闭"标题当文件名"时才显示 -->
<a-form-item label="完整模板预览" :wrapper-col="{ span: 12 }" v-if="!formState.UperUseViedoTitle">
<a-input v-model:value="formState.FullFollowedTitleTemplate" placeholder="最终的模板" disabled style="background: #f5f5f5" />
</a-form-item>
</div>
<div class="form-section" v-if="downImgVideo">
@@ -33,24 +70,62 @@
<a-form-item has-feedback label="图文视频合成" name="DownImageVideo" :wrapper-col="{ span: 6 }">
<a-switch v-model:checked="formState.DownImageVideo" />
<div class="flex items-start mt-1 text-sm text-gray-500">
<InfoCircleOutlined class="text-blue-400 mr-1 mt-0.5" />
<span>启用后图文视频将合成为视频文件下载</span>
</div>
</a-form-item>
<a-form-item has-feedback label="单独下载音频" name="DownMp3" :wrapper-col="{ span: 6 }">
<a-form-item has-feedback label="额外下载音频" name="DownMp3" :wrapper-col="{ span: 6 }">
<a-switch v-model:checked="formState.DownMp3" />
<div class="flex items-start mt-1 text-sm text-gray-500">
<InfoCircleOutlined class="text-blue-400 mr-1 mt-0.5" />
<span>启用后将额外下载音频文件</span>
</div>
</a-form-item>
<a-form-item has-feedback label="单独下载图片" name="DownImage" :wrapper-col="{ span: 6 }">
<a-form-item has-feedback label="额外下载图片" name="DownImage" :wrapper-col="{ span: 6 }">
<a-switch v-model:checked="formState.DownImage" />
<div class="flex items-start mt-1 text-sm text-gray-500">
<InfoCircleOutlined class="text-blue-400 mr-1 mt-0.5" />
<span>启用后将额外下载所有图片文件</span>
</div>
</a-form-item>
<a-form-item has-feedback label="是否统一存储" name="ImageViedoSaveAlone" :wrapper-col="{ span: 10 }">
<a-switch v-model:checked="formState.ImageViedoSaveAlone" />
<div class="flex items-start mt-1 text-sm text-gray-500">
<InfoCircleOutlined class="text-blue-400 mr-1 mt-0.5" />
<span>
启用后所有图文视频统一存储到 Cookie(抖音授权) 设置的目录<br />否则按类型存储到对应文件夹比如视频属于收藏的视频则存储到收藏视频的目录
</span>
</div>
</a-form-item>
</div>
<!-- 系统配置 -->
<div class="form-section">
<h3 class="section-title">其他配置</h3>
<a-form-item has-feedback label="日志保留(天数)" name="LogKeepDay" :wrapper-col="{ span: 6 }" style="margin-left:30px">
<a-input-number v-model:value="formState.LogKeepDay" placeholder="请输入保留天数" :min="1" :max="90" />
<div class="flex items-start mt-1 text-sm text-gray-500">
<InfoCircleOutlined class="text-blue-400 mr-1 mt-0.5" />
<span>系统运行日志的保留天数范围1-90过期自动清理</span>
</div>
</a-form-item>
<a-form-item has-feedback label="是否统一存储" name="AutoDistinct" :wrapper-col="{ span: 10 }">
<a-switch v-model:checked="formState.AutoDistinct" />
<div class="flex items-start mt-1 text-sm text-gray-500">
<InfoCircleOutlined class="text-blue-400 mr-1 mt-0.5" />
<span>
启用后同一个视频,只会下载一次
</span>
</div>
</a-form-item>
</div>
<!-- 操作按钮 -->
<a-form-item :wrapper-col="{ span: 12, offset: 5 }" class="form-actions">
<a-space size="middle">
@@ -64,22 +139,34 @@
</template>
<script lang="ts" setup>
import { reactive, toRaw, ref, watch, onMounted } from 'vue';
import { reactive, toRaw, ref, watch, onMounted, computed } from 'vue';
import type { UnwrapRef } from 'vue';
import { Form } from 'ant-design-vue';
import type { Rule } from 'ant-design-vue/es/form';
import type { FormInstance } from 'ant-design-vue';
import { useApiStore } from '@/store';
import { message } from 'ant-design-vue';
import { InfoCircleOutlined } from '@ant-design/icons-vue';
// 表单引用
const formRef = ref<FormInstance>();
// 模板字段:结构化数组
const template_options = [
{ label: '{Id}', value: '{Id}' },
{ label: '{VideoTitle}', value: '{VideoTitle}' },
{ label: '{FileHash}', value: '{FileHash}' },
// { label: '{FileSize}', value: '{FileSize}' },
{ label: '{Resolution}', value: '{Resolution}' },
// { label: '{SyncTime}', value: '{SyncTime}' },
{ label: '{ReleaseTime}', value: '{ReleaseTime}' },
];
// 状态定义
const componentDisabled = ref(true);
const downImgVideo = ref(false);
// 表单数据结构
// 表单数据结构(新增 FullFollowedTitleTemplate 字段)
interface FormState {
Cron: number;
Id: string;
@@ -91,6 +178,11 @@ interface FormState {
LogKeepDay: number;
DownImage: boolean;
DownMp3: boolean;
ImageViedoSaveAlone: boolean;
FollowedTitleTemplate: string[]; // 占位符数组
FollowedTitleSeparator: string; // 分隔符
FullFollowedTitleTemplate: string; // 新增:完整模板字符串(自动生成)
AutoDistinct: boolean;
}
// 表单初始数据
@@ -105,44 +197,70 @@ const formState: UnwrapRef<FormState> = reactive({
DownImageVideoFromEnv: false,
DownMp3: false,
DownImage: false,
ImageViedoSaveAlone: true,
FollowedTitleTemplate: [],
FollowedTitleSeparator: '',
FullFollowedTitleTemplate: '', // 初始为空
AutoDistinct: false,
});
// 表单校验规则
// 实时计算完整模板(可选:让用户实时预览,提交时无需重复计算)
const computeFullTemplate = computed(() => {
return formState.FollowedTitleTemplate.join(formState.FollowedTitleSeparator);
});
// 监听占位符/分隔符变化,实时更新预览(可选)
watch(
[() => [...formState.FollowedTitleTemplate], () => formState.FollowedTitleSeparator],
() => {
if (!formState.UperUseViedoTitle) {
// 只有关闭标题当文件名时才更新预览
formState.FullFollowedTitleTemplate = computeFullTemplate.value;
}
},
{ immediate: true, deep: true }
);
// 监听"标题当文件名"开关变化
watch(
() => formState.UperUseViedoTitle,
(isEnabled) => {
if (isEnabled) {
// 开启时清空模板相关数据,避免数据残留
formState.FollowedTitleTemplate = [];
formState.FollowedTitleSeparator = '';
formState.FullFollowedTitleTemplate = '';
// 清空相关表单项的校验状态
formRef.value?.clearValidate(['FollowedTitleTemplate', 'FollowedTitleSeparator', 'FullFollowedTitleTemplate']);
} else {
// 关闭时重新计算完整模板
formState.FullFollowedTitleTemplate = computeFullTemplate.value;
}
},
{ immediate: true }
);
// 表单校验规则(新增 FullFollowedTitleTemplate 校验)
const rules: Record<string, Rule[]> = {
// Cron: [
// { required: true, message: '请输入任务调度周期', trigger: 'change' },
// {
// validator: (rule, value) => {
// // 验证数字或cron表达式
// if (/^\d+$/.test(value) || /^(\d+\s*){5,6}$/.test(value)) {
// return Promise.resolve();
// }
// return Promise.reject(new Error('请输入有效的数字或Cron表达式'));
// },
// trigger: 'change',
// },
// ],
// BatchCount: [
// { required: true, message: '请输入每次查询条数', trigger: 'change' },
// { type: 'number', min: 1, max: 100, message: '查询条数应在1-100之间', trigger: 'change' },
// ],
// LogKeepDay: [
// { required: true, message: '请输入日志保留天数', trigger: 'change' },
// { type: 'number', min: 1, max: 90, message: '保留天数应在1-90之间', trigger: 'change' },
// ],
FollowedTitleSeparator: [{ max: 5, message: '分隔符长度不能超过5个字符', trigger: 'change' }],
FullFollowedTitleTemplate: [{ max: 200, message: '完整模板字符串长度不能超过200个字符', trigger: 'change' }],
};
// 布局配置
const labelCol = { style: { width: '150px', textAlign: 'right' } };
const wrapperCol = { span: 12 };
// 获取配置数据
// 获取配置数据(适配 FullFollowedTitleTemplate 字段)
const getConfig = () => {
useApiStore()
.apiGetConfig()
.then((res) => {
if (res.code === 0) {
// 使用Object.assign避免重复赋值
// 优先从 FullFollowedTitleTemplate 解析占位符数组(确保数据一致)
const fullTemplate = res.data.FullFollowedTitleTemplate || res.data.followedTitleTemplate || '';
const parsedTemplateArr = parseTemplateToArr(fullTemplate);
// 赋值所有字段(包含新增的 FullFollowedTitleTemplate
Object.assign(formState, {
Cron: res.data.cron,
Id: res.data.id,
@@ -154,9 +272,13 @@ const getConfig = () => {
LogKeepDay: res.data.logKeepDay,
DownImage: res.data.downImage,
DownMp3: res.data.downMp3,
FollowedTitleTemplate: parsedTemplateArr,
FollowedTitleSeparator: res.data.followedTitleSeparator || '',
FullFollowedTitleTemplate: fullTemplate, // 回显完整模板
ImageViedoSaveAlone: res.data.imageViedoSaveAlone,
AutoDistinct: res.data.autoDistinct,
});
// 监听环境变量配置,控制是否显示图片视频下载选项
downImgVideo.value = res.data.downImageVideoFromEnv;
} else {
message.error(res.erro || '获取配置失败', 8);
@@ -168,26 +290,46 @@ const getConfig = () => {
});
};
// 模板字符串 → 占位符数组(原有逻辑不变)
const parseTemplateToArr = (templateStr: string | null | undefined) => {
if (!templateStr || typeof templateStr !== 'string' || templateStr.trim() === '') {
return [];
}
const placeholderReg = /\{[a-zA-Z0-9]+\}/g;
const matchedPlaceholders = templateStr.match(placeholderReg) || [];
const validPlaceholderValues = template_options.map((item) => item.value);
const validPlaceholders = matchedPlaceholders.filter((placeholder) => validPlaceholderValues.includes(placeholder));
return Array.from(new Set(validPlaceholders));
};
// 组件挂载时获取配置
onMounted(() => {
getConfig();
});
// // 监听环境变量变化
// watch(
// () => formState.DownImageVideoFromEnv,
// (value) => {
// downImgVideo.value = value;
// }
// );
// 提交表单
// 提交表单(核心:自动生成完整模板字符串)
const onSubmit = () => {
formRef.value
.validate()
.then(() => {
// 1. 如果开启了标题当文件名,清空模板相关字段
let fullTemplate = '';
let templateTitle = '';
if (!formState.UperUseViedoTitle) {
// 自动拼接完整模板字符串(数组 + 分隔符)
fullTemplate = formState.FollowedTitleTemplate.join(formState.FollowedTitleSeparator);
}
// 2. 构造提交数据(包含三个模板相关字段)
const submitData = {
...toRaw(formState),
FullFollowedTitleTemplate: fullTemplate, // 确保提交最新拼接结果
FollowedTitleTemplate: formState.FollowedTitleTemplate.join(''),
};
// 3. 提交接口
useApiStore()
.apiUpdateConfig(toRaw(formState))
.apiUpdateConfig(submitData)
.then((res) => {
if (res.code === 0) {
message.success('修改成功,同步任务将在5-10秒按新配置运行...');
@@ -215,8 +357,11 @@ const onUpdate = () => {
// 取消编辑
const onCancel = () => {
componentDisabled.value = true;
// 可以考虑添加重置表单的逻辑
formRef.value?.clearValidate();
// 取消时恢复完整模板预览(只有关闭标题当文件名时)
if (!formState.UperUseViedoTitle) {
formState.FullFollowedTitleTemplate = computeFullTemplate.value;
}
};
</script>
@@ -229,6 +374,9 @@ const onCancel = () => {
&:last-child {
border-bottom: none;
}
margin-bottom: 20px;
padding-bottom: 15px;
border-bottom: 1px solid #f0f0f0;
}
.section-title {
@@ -240,44 +388,6 @@ const onCancel = () => {
border-left: 3px solid @primary-color;
}
// // 关键改动:强制标签靠左并添加100px左侧间距
// .ant-form-item-label {
// text-align: left !important; /* 强制靠左对齐,覆盖默认右对齐 */
// padding-right: 0 !important; /* 清除默认右侧内边距 */
// margin-left: 100px !important; /* 标签左侧间距100px */
// }
// 保持配置项内容区域与标签对齐(可选,根据实际布局调整)
// .ant-form-item-control {
// margin-left: 0 !important; /* 清除之前可能添加的左侧间距,避免双重缩进 */
// }
.help-text {
margin-top: 8px;
font-size: 12px;
color: #666;
line-height: 1.5;
p {
margin: 4px 0;
}
}
.cron-link {
color: @primary-color;
text-decoration: underline;
transition: all 0.3s;
&:hover {
color: #096dd9;
}
}
.form-actions {
margin-top: 30px;
text-align: center;
}
.ant-form-item {
margin-bottom: 18px;
}
@@ -286,7 +396,19 @@ const onCancel = () => {
color: rgb(164 158 158) !important;
background-color: #e6e6e6 !important;
}
.ant-form-item-label {
text-align: left !important;
}
// 统一提醒文字样式
:deep(.flex.items-start.mt-1.text-sm.text-gray-500) {
line-height: 1.6;
white-space: normal;
}
// 禁用输入框样式优化
:deep(.ant-input-disabled) {
color: #666 !important;
}
</style>
File diff suppressed because it is too large Load Diff
+13
View File
@@ -107,6 +107,18 @@ const routes: RouteRecordRaw[] = [
},
component: () => import('@/pages/workplace/Workplace.vue'),
},
{
path: '/follow',
name: '关注列表',
meta: {
icon: 'HeartOutlined',
view: 'self',
target: '_self',
renderMenu: true,
cacheable: false,
},
component: () => import('@/pages/followd/index.vue'),
},
{
path: '/cok',
name: '抖音授权',
@@ -119,6 +131,7 @@ const routes: RouteRecordRaw[] = [
},
component: () => import('@/pages/cok/Table.vue'),
},
{
path: '/set',
name: '系统配置',
+53 -8
View File
@@ -146,6 +146,14 @@ export const useApiStore = defineStore('coreapi', () => {
});
}
async function CookieList() {
return http.request<any, Response<any>>('/api/config/list', 'get').then(r => {
return r.data;
}).finally(() => {
});
}
async function UpdateConfig(param: object) {
return http.request<any, Response<any>>('/api/config/update', 'post_json', param).then(r => {
@@ -162,16 +170,47 @@ export const useApiStore = defineStore('coreapi', () => {
});
}
// async function playViedo(id: string) {
// return http.request<any, Response<any>>('/api/video/play/' + id, 'get').then(r => {
// return r.data;
// }).finally(() => {
//follows
async function FollowList(param: object) {
return http.request<any, Response<any>>('/api/follow/paged', 'post_json', param).then(r => {
return r.data;
}).finally(() => {
// });
// }
});
}
//同步关注列表
async function SyncFollow() {
return http.request<any, Response<any>>('/api/follow/sync', 'get').then(r => {
return r.data;
}).finally(() => {
});
}
//更新同步关注者状态
async function OpenOrCloseSync(param: object) {
return http.request<any, Response<any>>('/api/follow/openOrCloseSync', 'post_json', param).then(r => {
return r.data;
}).finally(() => {
});
}
//更新同步关注者状态
async function OpenOrCloseFullSync(param: object) {
return http.request<any, Response<any>>('/api/follow/openOrCloseFullSync', 'post_json', param).then(r => {
return r.data;
}).finally(() => {
});
}
//重新下载
async function ReDownViedos(param: object) {
return http.request<any, Response<any>>('/api/video/redown', 'post_json', param).then(r => {
return r.data;
}).finally(() => {
});
}
return {
// playViedo,
deleteCookie,
UpdateConfig,
apiCheckInitStatus,
@@ -184,6 +223,12 @@ export const useApiStore = defineStore('coreapi', () => {
StartJobNow,
VideoStatics,
VideoPageList,
CookiePageList
CookiePageList,
CookieList,
FollowList,
SyncFollow,
OpenOrCloseSync,
OpenOrCloseFullSync,
ReDownViedos
};
});