1、博主签名字符串长度限制
2、仅下载图片时-一直重复下载BUG修复 3、cookie授权界面优化
This commit is contained in:
@@ -29,16 +29,13 @@ columns.value = [
|
|||||||
{ title: '收藏路径', dataIndex: 'savePath' },
|
{ title: '收藏路径', dataIndex: 'savePath' },
|
||||||
{ title: '喜欢路径', dataIndex: 'favSavePath' },
|
{ title: '喜欢路径', dataIndex: 'favSavePath' },
|
||||||
{ title: '博主路径', dataIndex: 'upSavePath' },
|
{ title: '博主路径', dataIndex: 'upSavePath' },
|
||||||
// { title: '图文视频', dataIndex: 'imgSavePath' },
|
|
||||||
// { title: 'Cookie', dataIndex: 'cookies' },
|
|
||||||
{ title: '状态', dataIndex: 'status', width: 180 },
|
{ title: '状态', dataIndex: 'status', width: 180 },
|
||||||
{ title: '操作', dataIndex: 'edit', width: 200 }, // 加宽操作列宽度
|
{ title: '操作', dataIndex: 'edit', width: 200 },
|
||||||
];
|
];
|
||||||
|
|
||||||
// 定义数组中单个对象的类型:包含uper和uid字段(可选字符串类型,根据实际需求调整是否可选)
|
|
||||||
interface UpSecUserIdItem {
|
interface UpSecUserIdItem {
|
||||||
uper?: string; // 若要求必填,可去掉问号 `uper: string;`
|
uper?: string;
|
||||||
uid?: string; // 同上,必填则去掉问号
|
uid?: string;
|
||||||
syncAll: boolean;
|
syncAll: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,8 +51,6 @@ type DataItem = {
|
|||||||
upSecUserIdsJson?: UpSecUserIdItem[];
|
upSecUserIdsJson?: UpSecUserIdItem[];
|
||||||
upSecUserIds?: string;
|
upSecUserIds?: string;
|
||||||
upSavePath?: string;
|
upSavePath?: string;
|
||||||
// imgSavePath?: string;
|
|
||||||
// useSinglePath?: boolean; // 新增:是否全部用一个地址
|
|
||||||
useCollectFolder?: boolean;
|
useCollectFolder?: boolean;
|
||||||
downMix?: boolean;
|
downMix?: boolean;
|
||||||
downSeries?: boolean;
|
downSeries?: boolean;
|
||||||
@@ -118,17 +113,15 @@ const newCookie = (cookie?: DataItem) => {
|
|||||||
cookie.savePath = undefined;
|
cookie.savePath = undefined;
|
||||||
cookie.favSavePath = undefined;
|
cookie.favSavePath = undefined;
|
||||||
cookie.secUserId = undefined;
|
cookie.secUserId = undefined;
|
||||||
cookie.status = 0; // 0=关闭,1=开启
|
cookie.status = 0;
|
||||||
cookie.id = '0';
|
cookie.id = '0';
|
||||||
cookie.upSecUserIdsJson = undefined;
|
cookie.upSecUserIdsJson = undefined;
|
||||||
cookie.upSavePath = undefined;
|
cookie.upSavePath = undefined;
|
||||||
// cookie.imgSavePath = undefined;
|
cookie.useCollectFolder = false;
|
||||||
// cookie.useSinglePath = false; // 新增:默认不使用单一路径
|
cookie.downMix = false;
|
||||||
cookie.useCollectFolder = false; //是否按收藏夹来下载。
|
cookie.downSeries = false;
|
||||||
cookie.downMix = false; //是否下载收藏夹的合集
|
cookie.mixPath = undefined;
|
||||||
cookie.downSeries = false; //是否下载短剧
|
cookie.seriesPath = undefined;
|
||||||
cookie.mixPath = undefined; //合集存储路径
|
|
||||||
cookie.seriesPath = undefined; //短剧存储路径
|
|
||||||
cookie.downCollect = false;
|
cookie.downCollect = false;
|
||||||
cookie.downFavorite = false;
|
cookie.downFavorite = false;
|
||||||
cookie.downFollowd = false;
|
cookie.downFollowd = false;
|
||||||
@@ -144,19 +137,6 @@ const copyObject = (target: any, source?: any) => {
|
|||||||
|
|
||||||
const form = reactive<DataItem>(newCookie());
|
const form = reactive<DataItem>(newCookie());
|
||||||
|
|
||||||
// 新增:监听收藏路径变化,当启用单一路径时同步到其他路径
|
|
||||||
// watch(
|
|
||||||
// [() => form.savePath, () => form.useSinglePath],
|
|
||||||
// ([newSavePath, useSinglePath]) => {
|
|
||||||
// // if (useSinglePath && newSavePath) {
|
|
||||||
// // form.favSavePath = newSavePath;
|
|
||||||
// // form.upSavePath = newSavePath;
|
|
||||||
// // // form.imgSavePath = newSavePath;
|
|
||||||
// // }
|
|
||||||
// },
|
|
||||||
// { immediate: true }
|
|
||||||
// );
|
|
||||||
|
|
||||||
function reset() {
|
function reset() {
|
||||||
return newCookie(form);
|
return newCookie(form);
|
||||||
}
|
}
|
||||||
@@ -177,7 +157,6 @@ function submit() {
|
|||||||
?.validateFields()
|
?.validateFields()
|
||||||
.then((resData: DataItem) => {
|
.then((resData: DataItem) => {
|
||||||
if (form._isNew) {
|
if (form._isNew) {
|
||||||
// authors.push({ ...res });
|
|
||||||
} else {
|
} else {
|
||||||
copyObject(editRecord.value, resData);
|
copyObject(editRecord.value, resData);
|
||||||
}
|
}
|
||||||
@@ -236,17 +215,10 @@ function edit(record: DataItem) {
|
|||||||
editRecord.value = record;
|
editRecord.value = record;
|
||||||
console.log(record);
|
console.log(record);
|
||||||
copyObject(form, record);
|
copyObject(form, record);
|
||||||
// 确保useSinglePath有默认值
|
|
||||||
// if (form.useSinglePath === undefined) {
|
|
||||||
// form.useSinglePath = false;
|
|
||||||
// }
|
|
||||||
showModal.value = true;
|
showModal.value = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 新增:切换同步状态方法
|
|
||||||
|
|
||||||
const switchSyncStatus = (record: DataItem) => {
|
const switchSyncStatus = (record: DataItem) => {
|
||||||
// 保存原始状态,用于弹窗取消后还原
|
|
||||||
const statusText = record.status === 1 ? '开启' : '停止';
|
const statusText = record.status === 1 ? '开启' : '停止';
|
||||||
const title = `确认${statusText}同步`;
|
const title = `确认${statusText}同步`;
|
||||||
const content = `确定要${statusText}【${record.userName || '该'}】Cookie的同步任务吗?`;
|
const content = `确定要${statusText}【${record.userName || '该'}】Cookie的同步任务吗?`;
|
||||||
@@ -267,7 +239,7 @@ const switchSyncStatus = (record: DataItem) => {
|
|||||||
loading.value = false;
|
loading.value = false;
|
||||||
if (res.code === 0) {
|
if (res.code === 0) {
|
||||||
message.success(`${statusText}同步成功`);
|
message.success(`${statusText}同步成功`);
|
||||||
GetRecords(); // 刷新列表,更新 switch 状态
|
GetRecords();
|
||||||
} else {
|
} else {
|
||||||
message.error(`${statusText}同步失败:${res.message || '未知错误'}`);
|
message.error(`${statusText}同步失败:${res.message || '未知错误'}`);
|
||||||
record.status = record.status === 1 ? 0 : 1;
|
record.status = record.status === 1 ? 0 : 1;
|
||||||
@@ -292,19 +264,6 @@ const StatusDict = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const dataSource = ref(datas);
|
const dataSource = ref(datas);
|
||||||
const showCookiesModal = ref(false);
|
|
||||||
let showCookiesData = '';
|
|
||||||
const showCookies = (recode: DataItem) => {
|
|
||||||
showCookiesModal.value = true;
|
|
||||||
showCookiesData = recode.cookies;
|
|
||||||
};
|
|
||||||
|
|
||||||
const showUpersModal = ref(false);
|
|
||||||
let showUpersData = '';
|
|
||||||
const showUpers = (recode: DataItem) => {
|
|
||||||
showUpersModal.value = true;
|
|
||||||
showUpersData = recode.upSecUserIds;
|
|
||||||
};
|
|
||||||
|
|
||||||
const addRow = () => {
|
const addRow = () => {
|
||||||
if (!form.upSecUserIdsJson) {
|
if (!form.upSecUserIdsJson) {
|
||||||
@@ -319,47 +278,38 @@ const removeRow = (index: number) => {
|
|||||||
};
|
};
|
||||||
const rowCount = 10;
|
const rowCount = 10;
|
||||||
|
|
||||||
// 组件挂载时获取配置
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
GetRecords();
|
GetRecords();
|
||||||
});
|
});
|
||||||
|
|
||||||
// ========== 抽屉相关响应式数据 ==========
|
|
||||||
// 抽屉显示状态
|
|
||||||
const showDrawer = ref(false);
|
const showDrawer = ref(false);
|
||||||
// 抽屉类型(区分收藏夹/合集/短剧)
|
|
||||||
type DrawerType = 'collect' | 'mix' | 'series';
|
type DrawerType = 'collect' | 'mix' | 'series';
|
||||||
|
|
||||||
const cookieId = ref('');
|
const cookieId = ref('');
|
||||||
const cateType = ref(5);
|
const cateType = ref(5);
|
||||||
|
|
||||||
const drawerType = ref<DrawerType>('collect');
|
const drawerType = ref<DrawerType>('collect');
|
||||||
// 抽屉滚动容器引用(用于监听触底分页)
|
|
||||||
const drawerScrollRef = ref<HTMLDivElement | null>(null);
|
const drawerScrollRef = ref<HTMLDivElement | null>(null);
|
||||||
// 抽屉数据列表
|
|
||||||
const drawerDataList = ref<DrawerItem[]>([]);
|
const drawerDataList = ref<DrawerItem[]>([]);
|
||||||
// 抽屉分页配置
|
|
||||||
const drawerPagination = reactive({
|
const drawerPagination = reactive({
|
||||||
current: 1,
|
current: 1,
|
||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
total: 0,
|
total: 0,
|
||||||
loading: false,
|
loading: false,
|
||||||
hasMore: true, // 是否还有更多数据
|
hasMore: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
// ========== 定义抽屉数据项接口 ==========
|
|
||||||
interface DrawerItem {
|
interface DrawerItem {
|
||||||
id: string; // 不显示
|
id: string;
|
||||||
name: string; // 名称
|
name: string;
|
||||||
saveFolder: string; // 保存文件夹
|
saveFolder: string;
|
||||||
sync: boolean; // 是否同步
|
sync: boolean;
|
||||||
coverUrl: string; // 封面
|
coverUrl: string;
|
||||||
cookieId: string; // 不显示
|
cookieId: string;
|
||||||
xId: string; // 不显示
|
xId: string;
|
||||||
total: number;
|
total: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ========== 3个打开抽屉的方法 ==========
|
|
||||||
const openCollectFolderSetModal = () => {
|
const openCollectFolderSetModal = () => {
|
||||||
drawerType.value = 'collect';
|
drawerType.value = 'collect';
|
||||||
cateType.value = 5;
|
cateType.value = 5;
|
||||||
@@ -378,16 +328,13 @@ const openSeriesDownSetModal = () => {
|
|||||||
openCommonDrawer();
|
openCommonDrawer();
|
||||||
};
|
};
|
||||||
|
|
||||||
// ========== 公用抽屉打开逻辑(替换原来的) ==========
|
|
||||||
const openCommonDrawer = () => {
|
const openCommonDrawer = () => {
|
||||||
// 重置抽屉状态
|
|
||||||
drawerDataList.value = [];
|
drawerDataList.value = [];
|
||||||
drawerPagination.current = 1;
|
drawerPagination.current = 1;
|
||||||
drawerPagination.total = 0;
|
drawerPagination.total = 0;
|
||||||
drawerPagination.hasMore = true;
|
drawerPagination.hasMore = true;
|
||||||
showDrawer.value = true;
|
showDrawer.value = true;
|
||||||
|
|
||||||
// 确保DOM渲染后再加载 + 绑定事件
|
|
||||||
nextTick()
|
nextTick()
|
||||||
.then(() => {
|
.then(() => {
|
||||||
loadDrawerData();
|
loadDrawerData();
|
||||||
@@ -395,54 +342,24 @@ const openCommonDrawer = () => {
|
|||||||
})
|
})
|
||||||
.catch(() => {});
|
.catch(() => {});
|
||||||
};
|
};
|
||||||
// ========== 绑定抽屉滚动触底事件 ==========
|
|
||||||
// const bindDrawerScrollEvent = () => {
|
|
||||||
// const scrollContainer = drawerScrollRef.value;
|
|
||||||
// if (!scrollContainer) return;
|
|
||||||
|
|
||||||
// // 先移除原有事件,避免重复绑定
|
|
||||||
// scrollContainer.removeEventListener('scroll', handleDrawerScroll);
|
|
||||||
// // 添加滚动事件
|
|
||||||
// scrollContainer.addEventListener('scroll', handleDrawerScroll);
|
|
||||||
// };
|
|
||||||
// ========== 绑定抽屉滚动触底事件(替换原来的) ==========
|
|
||||||
const bindDrawerScrollEvent = () => {
|
const bindDrawerScrollEvent = () => {
|
||||||
const scrollContainer = drawerScrollRef.value;
|
const scrollContainer = drawerScrollRef.value;
|
||||||
if (!scrollContainer) {
|
if (!scrollContainer) {
|
||||||
// 延迟重试绑定,确保DOM渲染完成
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
bindDrawerScrollEvent();
|
bindDrawerScrollEvent();
|
||||||
}, 100);
|
}, 100);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 先清除所有旧事件
|
|
||||||
scrollContainer.removeEventListener('scroll', handleDrawerScroll);
|
scrollContainer.removeEventListener('scroll', handleDrawerScroll);
|
||||||
// 重新绑定
|
|
||||||
scrollContainer.addEventListener('scroll', handleDrawerScroll);
|
scrollContainer.addEventListener('scroll', handleDrawerScroll);
|
||||||
|
|
||||||
// 额外:首次加载如果内容不足一屏,自动加载下一页
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
handleDrawerScroll();
|
handleDrawerScroll();
|
||||||
}, 200);
|
}, 200);
|
||||||
};
|
};
|
||||||
// ========== 滚动触底处理逻辑 ==========
|
|
||||||
// const handleDrawerScroll = () => {
|
|
||||||
// const scrollContainer = drawerScrollRef.value;
|
|
||||||
// if (!scrollContainer || drawerPagination.loading || !drawerPagination.hasMore) return;
|
|
||||||
|
|
||||||
// // 计算滚动位置(触底阈值20px,避免精准触底才触发)
|
|
||||||
// const { scrollTop, clientHeight, scrollHeight } = scrollContainer;
|
|
||||||
// const isBottom = scrollTop + clientHeight >= scrollHeight - 20;
|
|
||||||
|
|
||||||
// if (isBottom) {
|
|
||||||
// // 加载下一页
|
|
||||||
// drawerPagination.current += 1;
|
|
||||||
// loadDrawerData();
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
|
|
||||||
// 防抖函数(防止滚动触发太频繁)
|
|
||||||
const debounce = (func: Function, delay = 100) => {
|
const debounce = (func: Function, delay = 100) => {
|
||||||
let timeoutId: any;
|
let timeoutId: any;
|
||||||
return (...args: any[]) => {
|
return (...args: any[]) => {
|
||||||
@@ -450,14 +367,13 @@ const debounce = (func: Function, delay = 100) => {
|
|||||||
timeoutId = setTimeout(() => func.apply(this, args), delay);
|
timeoutId = setTimeout(() => func.apply(this, args), delay);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
// ========== 滚动触底处理逻辑(替换原来的) ==========
|
|
||||||
const handleDrawerScroll = debounce(() => {
|
const handleDrawerScroll = debounce(() => {
|
||||||
const scrollContainer = drawerScrollRef.value;
|
const scrollContainer = drawerScrollRef.value;
|
||||||
if (!scrollContainer) return;
|
if (!scrollContainer) return;
|
||||||
if (drawerPagination.loading || !drawerPagination.hasMore) return;
|
if (drawerPagination.loading || !drawerPagination.hasMore) return;
|
||||||
|
|
||||||
const { scrollTop, scrollHeight, clientHeight } = scrollContainer;
|
const { scrollTop, scrollHeight, clientHeight } = scrollContainer;
|
||||||
// 兼容所有设备的触底判断(距离底部 50px 就触发)
|
|
||||||
const isBottom = scrollTop + clientHeight + 50 >= scrollHeight;
|
const isBottom = scrollTop + clientHeight + 50 >= scrollHeight;
|
||||||
|
|
||||||
if (isBottom) {
|
if (isBottom) {
|
||||||
@@ -465,9 +381,8 @@ const handleDrawerScroll = debounce(() => {
|
|||||||
drawerPagination.current += 1;
|
drawerPagination.current += 1;
|
||||||
loadDrawerData();
|
loadDrawerData();
|
||||||
}
|
}
|
||||||
}, 100); // 100ms 防抖
|
}, 100);
|
||||||
|
|
||||||
// ========== 加载抽屉数据(替换原来的) ==========
|
|
||||||
const loadDrawerData = () => {
|
const loadDrawerData = () => {
|
||||||
if (drawerPagination.loading || !drawerPagination.hasMore) {
|
if (drawerPagination.loading || !drawerPagination.hasMore) {
|
||||||
console.log('🚫 阻止重复加载');
|
console.log('🚫 阻止重复加载');
|
||||||
@@ -488,10 +403,8 @@ const loadDrawerData = () => {
|
|||||||
drawerDataList.value = [...drawerDataList.value, ...newData];
|
drawerDataList.value = [...drawerDataList.value, ...newData];
|
||||||
|
|
||||||
drawerPagination.total = res.data.total || 0;
|
drawerPagination.total = res.data.total || 0;
|
||||||
// 判断是否还有更多
|
|
||||||
drawerPagination.hasMore = drawerDataList.value.length < drawerPagination.total;
|
drawerPagination.hasMore = drawerDataList.value.length < drawerPagination.total;
|
||||||
|
|
||||||
// 加载完成后立刻检查是否需要继续加载(适配大屏)
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
handleDrawerScroll();
|
handleDrawerScroll();
|
||||||
}, 100);
|
}, 100);
|
||||||
@@ -507,7 +420,6 @@ const loadDrawerData = () => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// ========== 获取抽屉类型名称(用于页面展示) ==========
|
|
||||||
const getDrawerTypeName = () => {
|
const getDrawerTypeName = () => {
|
||||||
switch (drawerType.value) {
|
switch (drawerType.value) {
|
||||||
case 'collect':
|
case 'collect':
|
||||||
@@ -521,24 +433,21 @@ const getDrawerTypeName = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// ========== 切换同步状态(可根据需求对接真实接口) ==========
|
|
||||||
const toggleDrawerItemSync = (item: DrawerItem, index: number) => {
|
const toggleDrawerItemSync = (item: DrawerItem, index: number) => {
|
||||||
if (drawerDataList.value[index]) {
|
if (drawerDataList.value[index]) {
|
||||||
drawerDataList.value[index].sync = !item.sync;
|
drawerDataList.value[index].sync = !item.sync;
|
||||||
console.log(`切换${getDrawerTypeName()}【${item.name}】的同步状态为:${!item.sync}`);
|
console.log(`切换${getDrawerTypeName()}【${item.name}】的同步状态为:${!item.sync}`);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
// ========== 关闭抽屉清理资源 ==========
|
|
||||||
const closeDrawer = () => {
|
const closeDrawer = () => {
|
||||||
showDrawer.value = false;
|
showDrawer.value = false;
|
||||||
// 移除滚动事件监听
|
|
||||||
const scrollContainer = drawerScrollRef.value;
|
const scrollContainer = drawerScrollRef.value;
|
||||||
if (scrollContainer) {
|
if (scrollContainer) {
|
||||||
scrollContainer.removeEventListener('scroll', handleDrawerScroll);
|
scrollContainer.removeEventListener('scroll', handleDrawerScroll);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 2. 新增:抽屉右上角保存按钮的点击方法(仅抽屉相关,不影响其他逻辑)
|
|
||||||
const saveDrawerData = () => {
|
const saveDrawerData = () => {
|
||||||
if (drawerDataList.value.length === 0) {
|
if (drawerDataList.value.length === 0) {
|
||||||
message.info('暂无需要保存的配置数据');
|
message.info('暂无需要保存的配置数据');
|
||||||
@@ -587,12 +496,10 @@ const switchdownCollect = (e: any) => {
|
|||||||
</div>
|
</div>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|
||||||
<!-- 修复:下载收藏视频 - 拆分Form.Item,用a-form-item-rest包裹非收集字段 -->
|
|
||||||
<a-form-item label="下载收藏视频" name="downCollect">
|
<a-form-item label="下载收藏视频" name="downCollect">
|
||||||
<div style="display: flex; align-items: center; gap: 12px;">
|
<div style="display: flex; align-items: center; gap: 12px;">
|
||||||
<div class="form-item-div">
|
<div class="form-item-div">
|
||||||
<a-switch v-model:checked="form.downCollect" @change="switchdownCollect" :checked-value="true" :un-checked-value="false" size="default" />
|
<a-switch v-model:checked="form.downCollect" @change="switchdownCollect" :checked-value="true" :un-checked-value="false" size="default" />
|
||||||
<!-- 非收集字段用a-form-item-rest包裹 -->
|
|
||||||
<a-form-item-rest v-if="form.downCollect">
|
<a-form-item-rest v-if="form.downCollect">
|
||||||
<a-form-item name="savePath" noStyle>
|
<a-form-item name="savePath" noStyle>
|
||||||
<a-input v-model:value="form.savePath" placeholder='请输入容器路径' class="form-item-div-input" />
|
<a-input v-model:value="form.savePath" placeholder='请输入容器路径' class="form-item-div-input" />
|
||||||
@@ -603,7 +510,6 @@ const switchdownCollect = (e: any) => {
|
|||||||
</div>
|
</div>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|
||||||
<!-- 修复:自定义收藏夹 - 拆分Form.Item -->
|
|
||||||
<a-form-item v-if="form.savePath && form.savePath.length>0" label="自定义收藏夹" name="useCollectFolder">
|
<a-form-item v-if="form.savePath && form.savePath.length>0" label="自定义收藏夹" name="useCollectFolder">
|
||||||
<div style="display: flex; align-items: center; gap: 12px;">
|
<div style="display: flex; align-items: center; gap: 12px;">
|
||||||
<div class="form-item-div">
|
<div class="form-item-div">
|
||||||
@@ -619,7 +525,6 @@ const switchdownCollect = (e: any) => {
|
|||||||
</div>
|
</div>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|
||||||
<!-- 修复:下载喜欢视频 - 拆分Form.Item -->
|
|
||||||
<a-form-item label="下载喜欢视频" name="downFavorite">
|
<a-form-item label="下载喜欢视频" name="downFavorite">
|
||||||
<div style="display: flex; align-items: center; gap: 12px;">
|
<div style="display: flex; align-items: center; gap: 12px;">
|
||||||
<div class="form-item-div">
|
<div class="form-item-div">
|
||||||
@@ -637,7 +542,6 @@ const switchdownCollect = (e: any) => {
|
|||||||
</div>
|
</div>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|
||||||
<!-- 修复:下载关注视频 - 拆分Form.Item -->
|
|
||||||
<a-form-item label="下载关注视频" name="downFollowd">
|
<a-form-item label="下载关注视频" name="downFollowd">
|
||||||
<div style="display: flex; align-items: center; gap: 12px;">
|
<div style="display: flex; align-items: center; gap: 12px;">
|
||||||
<div class="form-item-div">
|
<div class="form-item-div">
|
||||||
@@ -655,7 +559,6 @@ const switchdownCollect = (e: any) => {
|
|||||||
</div>
|
</div>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|
||||||
<!-- 修复:下载合集视频 - 拆分Form.Item -->
|
|
||||||
<a-form-item label="下载合集视频" name="downMix">
|
<a-form-item label="下载合集视频" name="downMix">
|
||||||
<div style="display: flex; align-items: center; gap: 12px;">
|
<div style="display: flex; align-items: center; gap: 12px;">
|
||||||
<div class="form-item-div">
|
<div class="form-item-div">
|
||||||
@@ -673,7 +576,6 @@ const switchdownCollect = (e: any) => {
|
|||||||
</div>
|
</div>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|
||||||
<!-- 修复:下载短剧视频 - 拆分Form.Item -->
|
|
||||||
<a-form-item label="下载短剧视频" name="downSeries">
|
<a-form-item label="下载短剧视频" name="downSeries">
|
||||||
<div style="display: flex; align-items: center; gap: 12px;">
|
<div style="display: flex; align-items: center; gap: 12px;">
|
||||||
<div class="form-item-div">
|
<div class="form-item-div">
|
||||||
@@ -687,12 +589,10 @@ const switchdownCollect = (e: any) => {
|
|||||||
</a-button>
|
</a-button>
|
||||||
</a-form-item-rest>
|
</a-form-item-rest>
|
||||||
</div>
|
</div>
|
||||||
<a-alert message="开启后自动下载收藏的短剧视频(还需要开启短剧同步开关,不填目录径默认存储到收藏目录,设置后记得docker里面加映射,注意:付费视频下载后无法播放)
|
<a-alert message="开启后自动下载收藏的短剧视频(还需要开启短剧同步开关,不填目录径默认存储到收藏目录,设置后记得docker里面加映射,注意:付费视频下载后无法播放)" :type="form.downSeries?'error':'info'" size="small" style="flex: 1; margin-bottom: 0;" />
|
||||||
" :type="form.downSeries?'error':'info'" size="small" style="flex: 1; margin-bottom: 0;" />
|
|
||||||
</div>
|
</div>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|
||||||
<!-- 任务同步状态 - 保持原有结构(仅一个Switch,无警告) -->
|
|
||||||
<a-form-item label="任务同步状态" name="status">
|
<a-form-item label="任务同步状态" name="status">
|
||||||
<div style="display: flex; align-items: center; gap: 8px;">
|
<div style="display: flex; align-items: center; gap: 8px;">
|
||||||
<a-switch v-model:checked="form.status" :checked-value="1" :un-checked-value="0" size="default" />
|
<a-switch v-model:checked="form.status" :checked-value="1" :un-checked-value="0" size="default" />
|
||||||
@@ -702,9 +602,7 @@ const switchdownCollect = (e: any) => {
|
|||||||
</a-form>
|
</a-form>
|
||||||
</a-modal>
|
</a-modal>
|
||||||
|
|
||||||
<!-- 公用抽屉组件(层级高于原有弹窗)- 优化后 -->
|
|
||||||
<a-drawer :title="getDrawerTypeName()+'配置'" v-model:visible="showDrawer" placement="right" width="800px" :z-index="10010" :mask-z-index="10009" @close="closeDrawer" class="common-drawer">
|
<a-drawer :title="getDrawerTypeName()+'配置'" v-model:visible="showDrawer" placement="right" width="800px" :z-index="10010" :mask-z-index="10009" @close="closeDrawer" class="common-drawer">
|
||||||
<!-- 抽屉右上角:添加保存按钮(利用 extra 插槽,不改动其他模板) -->
|
|
||||||
<template #extra>
|
<template #extra>
|
||||||
<a-button type="primary" :loading="drawerPagination.loading" @click="saveDrawerData" class="drawer-save-btn">
|
<a-button type="primary" :loading="drawerPagination.loading" @click="saveDrawerData" class="drawer-save-btn">
|
||||||
<template #icon>
|
<template #icon>
|
||||||
@@ -714,28 +612,22 @@ const switchdownCollect = (e: any) => {
|
|||||||
</a-button>
|
</a-button>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<!-- 抽屉滚动容器(绑定ref和滚动样式) -->
|
|
||||||
<div ref="drawerScrollRef" class="drawer-scroll-container">
|
<div ref="drawerScrollRef" class="drawer-scroll-container">
|
||||||
<!-- 加载中状态 -->
|
|
||||||
<div v-if="drawerPagination.loading && drawerDataList.length === 0" class="drawer-loading">
|
<div v-if="drawerPagination.loading && drawerDataList.length === 0" class="drawer-loading">
|
||||||
<Spin size="large" />
|
<Spin size="large" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 卡片网格展示 - 优化布局(横向一行展示名称、保存路径) -->
|
|
||||||
<a-card v-else :bordered="false" class="drawer-card-container grid-container">
|
<a-card v-else :bordered="false" class="drawer-card-container grid-container">
|
||||||
<a-card-grid v-for="(item, index) in drawerDataList" :key="item.id" class="drawer-card-grid">
|
<a-card-grid v-for="(item, index) in drawerDataList" :key="item.id" class="drawer-card-grid">
|
||||||
<!-- 竖向封面(移除预览功能,仅保留基础展示) -->
|
|
||||||
<div class="grid-cover vertical-cover" v-if="drawerType!='collect'">
|
<div class="grid-cover vertical-cover" v-if="drawerType!='collect'">
|
||||||
<a-image :preview="false" :src="item.coverUrl" fit="cover" />
|
<a-image :preview="false" :src="item.coverUrl" fit="cover" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 名称:横向一行展示(标签 + 内容 在同一行) -->
|
|
||||||
<div class="grid-item horizontal-item name">
|
<div class="grid-item horizontal-item name">
|
||||||
<label class="drawer-label">名称:</label>
|
<label class="drawer-label">名称:</label>
|
||||||
<span>{{ item.name || '未命名' }}</span>
|
<span>{{ item.name || '未命名' }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 保存文件夹:横向一行展示(标签 + 输入框 在同一行) -->
|
|
||||||
<div class="grid-item horizontal-item save-folder">
|
<div class="grid-item horizontal-item save-folder">
|
||||||
<label class="drawer-label">保存:</label>
|
<label class="drawer-label">保存:</label>
|
||||||
<a-input v-model:value="item.saveFolder" size="small" placeholder="默认用名称作文件夹" class="save-path-input" />
|
<a-input v-model:value="item.saveFolder" size="small" placeholder="默认用名称作文件夹" class="save-path-input" />
|
||||||
@@ -745,7 +637,6 @@ const switchdownCollect = (e: any) => {
|
|||||||
<span>{{ item.total || '0' }}</span>
|
<span>{{ item.total || '0' }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 同步开关(保持原有逻辑,横向对齐) -->
|
|
||||||
<div class="grid-item horizontal-item sync-switch">
|
<div class="grid-item horizontal-item sync-switch">
|
||||||
<label class="drawer-label">同步:</label>
|
<label class="drawer-label">同步:</label>
|
||||||
<a-switch :checked="item.sync" @change="() => toggleDrawerItemSync(item, index)" size="small" />
|
<a-switch :checked="item.sync" @change="() => toggleDrawerItemSync(item, index)" size="small" />
|
||||||
@@ -753,19 +644,16 @@ const switchdownCollect = (e: any) => {
|
|||||||
</a-card-grid>
|
</a-card-grid>
|
||||||
</a-card>
|
</a-card>
|
||||||
|
|
||||||
<!-- 无更多数据提示 -->
|
|
||||||
<div v-if="!drawerPagination.hasMore && drawerDataList.length > 0" class="no-more-data">
|
<div v-if="!drawerPagination.hasMore && drawerDataList.length > 0" class="no-more-data">
|
||||||
<!-- 已加载全部{{ getDrawerTypeName() }}数据 -->
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 加载下一页中 -->
|
|
||||||
<div v-if="drawerPagination.loading && drawerDataList.length > 0" class="loading-more">
|
<div v-if="drawerPagination.loading && drawerDataList.length > 0" class="loading-more">
|
||||||
<Spin size="small" />
|
<Spin size="small" />
|
||||||
<span>加载中...</span>
|
<span>加载中...</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</a-drawer>
|
</a-drawer>
|
||||||
<!-- 成员表格 -->
|
|
||||||
<a-table v-bind="$attrs" :columns="columns" :dataSource="dataSource" :pagination="false">
|
<a-table v-bind="$attrs" :columns="columns" :dataSource="dataSource" :pagination="false">
|
||||||
<template #title>
|
<template #title>
|
||||||
<div class="flex justify-end pr-4">
|
<div class="flex justify-end pr-4">
|
||||||
@@ -786,7 +674,6 @@ const switchdownCollect = (e: any) => {
|
|||||||
</template>
|
</template>
|
||||||
<template #bodyCell="{ column, text, record }">
|
<template #bodyCell="{ column, text, record }">
|
||||||
<template v-if="column.dataIndex === 'status'">
|
<template v-if="column.dataIndex === 'status'">
|
||||||
<!-- 新:a-switch 显示状态,绑定切换逻辑 -->
|
|
||||||
<div style="display: flex; align-items: center; gap: 8px;">
|
<div style="display: flex; align-items: center; gap: 8px;">
|
||||||
<a-switch v-model:checked="record.status" :checked-value="1" :un-checked-value="0" size="small" :disabled="loading" @change="() => switchSyncStatus(record)" />
|
<a-switch v-model:checked="record.status" :checked-value="1" :un-checked-value="0" size="small" :disabled="loading" @change="() => switchSyncStatus(record)" />
|
||||||
<span :style="{
|
<span :style="{
|
||||||
@@ -797,14 +684,7 @@ const switchdownCollect = (e: any) => {
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template v-else-if="column.dataIndex === 'cookies'">
|
|
||||||
<a-button @click="showCookies(record)">查看</a-button>
|
|
||||||
</template>
|
|
||||||
<template v-else-if="column.dataIndex === 'upSecUserIds'">
|
|
||||||
<a-button @click="showUpers(record)">查看</a-button>
|
|
||||||
</template>
|
|
||||||
<template v-else-if="column.dataIndex === 'edit'">
|
<template v-else-if="column.dataIndex === 'edit'">
|
||||||
<!-- 已删除「开启/停止」按钮,仅保留编辑和删除 -->
|
|
||||||
<a-button :disabled="showModal || loading" type="link" @click="edit(record)">
|
<a-button :disabled="showModal || loading" type="link" @click="edit(record)">
|
||||||
<template #icon>
|
<template #icon>
|
||||||
<EditFilled />
|
<EditFilled />
|
||||||
@@ -824,51 +704,12 @@ const switchdownCollect = (e: any) => {
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</a-table>
|
</a-table>
|
||||||
|
|
||||||
<!-- Cookie详情弹窗 -->
|
|
||||||
<a-modal title="Cookie 详情" :visible="showCookiesModal" style="width:1200px;" @cancel="showCookiesModal = false" @ok="showCookiesModal = false">
|
|
||||||
<div class="cookie-content">
|
|
||||||
{{ showCookiesData || '无Cookie数据' }}
|
|
||||||
</div>
|
|
||||||
</a-modal>
|
|
||||||
|
|
||||||
<!-- 博主信息弹窗 -->
|
|
||||||
<a-modal title="要同步的博主信息" :visible="showUpersModal" style="width:1200px;" @cancel="showUpersModal = false" @ok="showUpersModal = false">
|
|
||||||
<div class="cookie-content">
|
|
||||||
{{ showUpersData || '未设置' }}
|
|
||||||
</div>
|
|
||||||
</a-modal>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped lang="less">
|
<style scoped lang="less">
|
||||||
// 原有非抽屉样式(保留,不改动)
|
|
||||||
.cookie-content {
|
|
||||||
white-space: pre-wrap;
|
|
||||||
word-break: break-all;
|
|
||||||
max-height: 400px;
|
|
||||||
overflow-y: auto;
|
|
||||||
padding: 10px;
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
|
||||||
.ant-form-item {
|
.ant-form-item {
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
}
|
}
|
||||||
/* 透明滚动条样式 - WebKit内核浏览器 */
|
|
||||||
.cookie-content::-webkit-scrollbar {
|
|
||||||
width: 6px; /* 更细的滚动条 */
|
|
||||||
}
|
|
||||||
.cookie-content::-webkit-scrollbar-track {
|
|
||||||
background: transparent;
|
|
||||||
}
|
|
||||||
.cookie-content::-webkit-scrollbar-thumb {
|
|
||||||
background: rgba(150, 150, 150, 0.2); /* 浅灰透明 */
|
|
||||||
border-radius: 3px;
|
|
||||||
}
|
|
||||||
.cookie-content::-webkit-scrollbar-thumb:hover {
|
|
||||||
background: rgba(150, 150, 150, 0.4); /* 略深一点的透明 */
|
|
||||||
}
|
|
||||||
.cookie-content::-webkit-scrollbar-corner {
|
|
||||||
background: transparent;
|
|
||||||
}
|
|
||||||
.form-item-div {
|
.form-item-div {
|
||||||
width: 300px;
|
width: 300px;
|
||||||
}
|
}
|
||||||
@@ -876,13 +717,7 @@ const switchdownCollect = (e: any) => {
|
|||||||
width: 180px;
|
width: 180px;
|
||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
}
|
}
|
||||||
/* Firefox 透明滚动条适配 */
|
|
||||||
.cookie-content {
|
|
||||||
scrollbar-width: thin;
|
|
||||||
scrollbar-color: rgba(150, 150, 150, 0.2) transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* a-textarea 透明滚动条 */
|
|
||||||
:deep(.ant-input-textarea-input) {
|
:deep(.ant-input-textarea-input) {
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
scrollbar-width: thin;
|
scrollbar-width: thin;
|
||||||
@@ -906,102 +741,81 @@ const switchdownCollect = (e: any) => {
|
|||||||
background: transparent;
|
background: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 禁用状态的输入框样式优化 */
|
|
||||||
:deep(.ant-input-disabled) {
|
:deep(.ant-input-disabled) {
|
||||||
background-color: #f5f5f5 !important;
|
background-color: #f5f5f5 !important;
|
||||||
color: #666 !important;
|
color: #666 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 修复:移除对alert的自定义样式修改,还原官方默认样式 */
|
|
||||||
.alert-wrapper {
|
.alert-wrapper {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
margin-bottom: 0 !important;
|
margin-bottom: 0 !important;
|
||||||
}
|
}
|
||||||
// ========== 精准匹配模板:a-card-grid 样式优化 ==========
|
|
||||||
/* 父容器:解决卡片间隙,避免换行(不改动模板,仅样式控制) */
|
|
||||||
.drawer-card-container.grid-container {
|
.drawer-card-container.grid-container {
|
||||||
// 清除 a-card 自带内边距,避免与卡片间隙冲突
|
|
||||||
:deep(.ant-card-body) {
|
:deep(.ant-card-body) {
|
||||||
padding: 16px;
|
padding: 16px;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
// 启用 Flex 布局,实现卡片均匀间隙(核心:gap 不与组件自带样式冲突)
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
gap: 20px; /* 卡片之间的横向/纵向间隙(可自定义,不会换行) */
|
gap: 20px;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
/* 固定左对齐:单元素/多元素都保持从左往右排列 */
|
|
||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
/* 新增:兜底最小高度,避免空容器塌陷 */
|
|
||||||
min-height: 200px;
|
min-height: 200px;
|
||||||
/* 新增:左内边距,让单元素和多元素视觉对齐一致 */
|
|
||||||
padding-left: 5px;
|
padding-left: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 新增:单元素样式修复 - 关键修复(仅防变形,不居中) */
|
|
||||||
.drawer-card-container.grid-container:has(:only-child) :deep(.drawer-card-grid) {
|
.drawer-card-container.grid-container:has(:only-child) :deep(.drawer-card-grid) {
|
||||||
/* 单元素时保持3列布局的宽度,不拉伸,防止变形 */
|
|
||||||
width: calc(33.333% - 10.333px) !important;
|
width: calc(33.333% - 10.333px) !important;
|
||||||
/* 可选:如果觉得单元素太窄,可取消下面注释,设置固定宽度 */
|
min-width: 200px;
|
||||||
/* width: 300px !important; */
|
|
||||||
min-width: 200px; /* 强制最小宽度,防止压缩变形 */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* a-card-grid 核心样式:圆角 + 固定宽度 + 内边距 */
|
|
||||||
:deep(.drawer-card-grid) {
|
:deep(.drawer-card-grid) {
|
||||||
// 精确宽度计算:3列均分,减去 gap 分摊值,避免换行
|
width: calc(33.333% - 10.333px) !important;
|
||||||
width: calc(33.333% - 10.333px) !important; /* 20px gap 分摊到3列,每列减 ~13.333px */
|
|
||||||
/* 新增:最小宽度限制,防止变形(核心) */
|
|
||||||
min-width: 200px;
|
min-width: 200px;
|
||||||
margin: 5px !important; /* 清除组件自带 margin,避免间隙重复 */
|
margin: 5px !important;
|
||||||
border-radius: 12px !important; /* 卡片圆角(可自定义大小) */
|
border-radius: 12px !important;
|
||||||
padding: 16px !important; /* 卡片内部整体内边距 */
|
padding: 16px !important;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
border: 1px solid #f0f0f0; /* 卡片边框,增强圆角视觉感 */
|
border: 1px solid #f0f0f0;
|
||||||
// 卡片内部竖向排列,确保每个内容块独占一行
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 12px; /* 卡片内部元素之间的间距(可自定义) */
|
gap: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 图片容器:横向铺满卡片 + 自带内边距 */
|
|
||||||
:deep(.drawer-card-grid .grid-cover.vertical-cover) {
|
:deep(.drawer-card-grid .grid-cover.vertical-cover) {
|
||||||
width: 100% !important; /* 横向铺满卡片 */
|
width: 100% !important;
|
||||||
padding: 4px; /* 图片内部内边距(可自定义,实现图片与卡片边框的间距) */
|
padding: 4px;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
border-radius: 8px; /* 图片容器轻微圆角,与卡片圆角呼应 */
|
border-radius: 8px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 图片:强制铺满容器,不拉伸 */
|
|
||||||
:deep(.drawer-card-grid .vertical-cover .ant-image) {
|
:deep(.drawer-card-grid .vertical-cover .ant-image) {
|
||||||
width: 100% !important;
|
width: 100% !important;
|
||||||
height: auto !important; /* 高度自适应,保持图片比例 */
|
height: auto !important;
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
:deep(.drawer-card-grid .vertical-cover .ant-image-img) {
|
:deep(.drawer-card-grid .vertical-cover .ant-image-img) {
|
||||||
width: 100% !important;
|
width: 100% !important;
|
||||||
height: 100% !important;
|
height: 100% !important;
|
||||||
object-fit: cover !important; /* 保持图片比例,裁剪多余部分 */
|
object-fit: cover !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 名称、保存路径、同步开关:独占一行样式 */
|
|
||||||
:deep(.drawer-card-grid .grid-item.horizontal-item) {
|
:deep(.drawer-card-grid .grid-item.horizontal-item) {
|
||||||
width: 100% !important; /* 独占一行,横向铺满卡片 */
|
width: 100% !important;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center; /* 标签与内容垂直居中 */
|
align-items: center;
|
||||||
margin: 0 !important; /* 清除多余间距,确保独占一行 */
|
margin: 0 !important;
|
||||||
padding: 4px 0; /* 上下轻微内边距,增强可读性 */
|
padding: 4px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 亮色模式(保留)
|
|
||||||
:deep(.drawer-label) {
|
:deep(.drawer-label) {
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
color: rgba(0, 0, 0, 0.6);
|
color: rgba(0, 0, 0, 0.6);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 名称内容、输入框:占满剩余宽度 */
|
|
||||||
:deep(.drawer-card-grid .horizontal-item span) {
|
:deep(.drawer-card-grid .horizontal-item span) {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
@@ -1016,20 +830,16 @@ const switchdownCollect = (e: any) => {
|
|||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 同步开关:两端对齐,保持独占一行 */
|
|
||||||
:deep(.drawer-card-grid .sync-switch) {
|
:deep(.drawer-card-grid .sync-switch) {
|
||||||
justify-content: space-between; /* 标签左对齐,开关右对齐 */
|
justify-content: space-between;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 响应式适配:小屏幕自动调整列数,保持间隙不换行 */
|
|
||||||
@media (max-width: 768px) {
|
@media (max-width: 768px) {
|
||||||
:deep(.drawer-card-grid) {
|
:deep(.drawer-card-grid) {
|
||||||
width: calc(50% - 10px) !important; /* 2列均分,20px gap 每列减10px */
|
width: calc(50% - 10px) !important;
|
||||||
/* 新增:响应式最小宽度 */
|
|
||||||
min-width: 180px;
|
min-width: 180px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 响应式下单元素适配(保持左对齐) */
|
|
||||||
.drawer-card-container.grid-container:has(:only-child) :deep(.drawer-card-grid) {
|
.drawer-card-container.grid-container:has(:only-child) :deep(.drawer-card-grid) {
|
||||||
width: calc(50% - 10px) !important;
|
width: calc(50% - 10px) !important;
|
||||||
min-width: 180px;
|
min-width: 180px;
|
||||||
@@ -1037,51 +847,38 @@ const switchdownCollect = (e: any) => {
|
|||||||
}
|
}
|
||||||
@media (max-width: 480px) {
|
@media (max-width: 480px) {
|
||||||
:deep(.drawer-card-grid) {
|
:deep(.drawer-card-grid) {
|
||||||
width: 100% !important; /* 1列铺满,无间距分摊 */
|
width: 100% !important;
|
||||||
/* 新增:移动端最小宽度铺满 */
|
|
||||||
min-width: 100%;
|
min-width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 移动端单元素适配(1列铺满) */
|
|
||||||
.drawer-card-container.grid-container:has(:only-child) :deep(.drawer-card-grid) {
|
.drawer-card-container.grid-container:has(:only-child) :deep(.drawer-card-grid) {
|
||||||
width: 100% !important;
|
width: 100% !important;
|
||||||
min-width: 100%;
|
min-width: 100%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ========== 黑暗模式样式(html.dark-mode + 链式类名,光效增强 + hover 效果) ==========
|
|
||||||
/* 卡片:深色背景 + 隐式边框 + 增强光效(默认状态) */
|
|
||||||
html.dark-mode .drawer-card-container.grid-container .drawer-card-grid {
|
html.dark-mode .drawer-card-container.grid-container .drawer-card-grid {
|
||||||
border-color: rgba(142, 140, 140, 0.1) !important; /* 边框透明化(隐掉) */
|
border-color: rgba(142, 140, 140, 0.1) !important;
|
||||||
background-color: #1a1a2e !important;
|
background-color: #1a1a2e !important;
|
||||||
/* 增强光效:双层阴影+浅蓝紫微光,更醒目且不刺眼(核心修改) */
|
box-shadow: 0 6px 16px rgba(0, 20, 60, 0.4), 0 2px 6px rgba(100, 120, 255, 0.2),
|
||||||
box-shadow: 0 6px 16px rgba(0, 20, 60, 0.4),
|
inset 0 1px 0 rgba(255, 255, 255, 0.05) !important;
|
||||||
/* 主阴影:加深蓝紫调,增大模糊半径,光效更明显 */ 0 2px 6px rgba(100, 120, 255, 0.2),
|
transition: all 0.3s ease-in-out !important;
|
||||||
/* 辅阴影:新增浅蓝紫微光,光效更突出 */ inset 0 1px 0 rgba(255, 255, 255, 0.05) !important; /* 内阴影:轻微高光,增强卡片质感 */
|
|
||||||
/* 可选:完全隐藏边框 */
|
|
||||||
/* border: none !important; */
|
|
||||||
transition: all 0.3s ease-in-out !important; /* 过渡动画:hover 效果平滑切换,不生硬 */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 卡片 hover 效果:悬浮时光效更突出,层次感拉满 */
|
|
||||||
html.dark-mode .drawer-card-container.grid-container .drawer-card-grid:hover {
|
html.dark-mode .drawer-card-container.grid-container .drawer-card-grid:hover {
|
||||||
box-shadow: 0 8px 24px rgba(0, 30, 80, 0.5),
|
box-shadow: 0 8px 24px rgba(0, 30, 80, 0.5), 0 4px 12px rgba(120, 140, 255, 0.35),
|
||||||
/* 主阴影:进一步加深、扩大,立体感更强 */ 0 4px 12px rgba(120, 140, 255, 0.35),
|
inset 0 1px 0 rgba(255, 255, 255, 0.08) !important;
|
||||||
/* 辅阴影:蓝紫微光更亮,光效更醒目 */ inset 0 1px 0 rgba(255, 255, 255, 0.08) !important; /* 内阴影:高光增强,质感更优 */
|
transform: translateY(-2px) !important;
|
||||||
transform: translateY(-2px) !important; /* 可选:轻微上浮,增强交互感(可删除) */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* label:强制纯白色(核心需求,格式不变) */
|
|
||||||
html.dark-mode .drawer-card-container.grid-container .drawer-card-grid .horizontal-item label {
|
html.dark-mode .drawer-card-container.grid-container .drawer-card-grid .horizontal-item label {
|
||||||
color: #ffffff !important;
|
color: #ffffff !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 名称内容:浅白色(格式不变) */
|
|
||||||
html.dark-mode .drawer-card-container.grid-container .drawer-card-grid .horizontal-item span {
|
html.dark-mode .drawer-card-container.grid-container .drawer-card-grid .horizontal-item span {
|
||||||
color: rgba(255, 255, 255, 0.88) !important;
|
color: rgba(255, 255, 255, 0.88) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 输入框:深色适配(格式不变) */
|
|
||||||
html.dark-mode .drawer-card-container.grid-container .drawer-card-grid .ant-input {
|
html.dark-mode .drawer-card-container.grid-container .drawer-card-grid .ant-input {
|
||||||
background-color: #2f2f2f !important;
|
background-color: #2f2f2f !important;
|
||||||
border-color: #404040 !important;
|
border-color: #404040 !important;
|
||||||
@@ -1089,7 +886,6 @@ html.dark-mode .drawer-card-container.grid-container .drawer-card-grid .ant-inpu
|
|||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<!-- 新增全局样式块,确保alert样式不受scoped影响(仅针对alert还原默认) -->
|
|
||||||
<style lang="less">
|
<style lang="less">
|
||||||
.full-modal {
|
.full-modal {
|
||||||
.ant-modal {
|
.ant-modal {
|
||||||
@@ -1108,11 +904,9 @@ html.dark-mode .drawer-card-container.grid-container .drawer-card-grid .ant-inpu
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 还原Ant Design Vue alert官方默认样式,消除scoped样式的间接影响 */
|
|
||||||
.ant-alert {
|
.ant-alert {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
/* padding: 16px 16px; */
|
|
||||||
color: rgba(0, 0, 0, 0.88);
|
color: rgba(0, 0, 0, 0.88);
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
line-height: 1.5714285714;
|
line-height: 1.5714285714;
|
||||||
@@ -1127,7 +921,6 @@ html.dark-mode .drawer-card-container.grid-container .drawer-card-grid .ant-inpu
|
|||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
}
|
}
|
||||||
/* 还原alert不同类型的官方默认颜色 */
|
|
||||||
.ant-alert-info {
|
.ant-alert-info {
|
||||||
background-color: #e6f4ff;
|
background-color: #e6f4ff;
|
||||||
border: 1px solid #91caff;
|
border: 1px solid #91caff;
|
||||||
@@ -1135,7 +928,6 @@ html.dark-mode .drawer-card-container.grid-container .drawer-card-grid .ant-inpu
|
|||||||
.ant-alert-info .ant-alert-message {
|
.ant-alert-info .ant-alert-message {
|
||||||
color: #1677ff;
|
color: #1677ff;
|
||||||
}
|
}
|
||||||
/* 还原alert不同类型的官方默认颜色 */
|
|
||||||
.ant-alert-success {
|
.ant-alert-success {
|
||||||
background-color: #daf1d3;
|
background-color: #daf1d3;
|
||||||
border: 1px solid #5bbc51;
|
border: 1px solid #5bbc51;
|
||||||
@@ -1144,14 +936,12 @@ html.dark-mode .drawer-card-container.grid-container .drawer-card-grid .ant-inpu
|
|||||||
color: #228b22;
|
color: #228b22;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 还原 Alert 各类型的官方默认颜色 */
|
|
||||||
/* 错误(error)类型 - 红色系 */
|
|
||||||
.ant-alert-error {
|
.ant-alert-error {
|
||||||
background-color: #fff1f0; /* 错误类型背景色 */
|
background-color: #fff1f0;
|
||||||
border: 1px solid #ff4d4f; /* 错误类型边框色 */
|
border: 1px solid #ff4d4f;
|
||||||
}
|
}
|
||||||
.ant-alert-error .ant-alert-message {
|
.ant-alert-error .ant-alert-message {
|
||||||
color: #f5222d; /* 错误类型文字主色 */
|
color: #f5222d;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ant-alert-warning {
|
.ant-alert-warning {
|
||||||
@@ -1161,7 +951,6 @@ html.dark-mode .drawer-card-container.grid-container .drawer-card-grid .ant-inpu
|
|||||||
.ant-alert-warning .ant-alert-message {
|
.ant-alert-warning .ant-alert-message {
|
||||||
color: #faad14;
|
color: #faad14;
|
||||||
}
|
}
|
||||||
/* 确保alert图标颜色同步官方样式 */
|
|
||||||
.ant-alert-info .ant-alert-icon {
|
.ant-alert-info .ant-alert-icon {
|
||||||
color: #1677ff;
|
color: #1677ff;
|
||||||
}
|
}
|
||||||
@@ -1169,10 +958,8 @@ html.dark-mode .drawer-card-container.grid-container .drawer-card-grid .ant-inpu
|
|||||||
color: #faad14;
|
color: #faad14;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 抽屉滚动容器样式(核心修复)
|
|
||||||
.drawer-scroll-container {
|
.drawer-scroll-container {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
/* 固定抽屉内部高度,强制出现滚动区域 */
|
|
||||||
height: calc(100vh - 130px) !important;
|
height: calc(100vh - 130px) !important;
|
||||||
min-height: 300px !important;
|
min-height: 300px !important;
|
||||||
overflow-y: auto !important;
|
overflow-y: auto !important;
|
||||||
@@ -1182,7 +969,6 @@ html.dark-mode .drawer-card-container.grid-container .drawer-card-grid .ant-inpu
|
|||||||
position: relative;
|
position: relative;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
|
|
||||||
/* 优化滚动条 */
|
|
||||||
&::-webkit-scrollbar {
|
&::-webkit-scrollbar {
|
||||||
width: 6px;
|
width: 6px;
|
||||||
}
|
}
|
||||||
@@ -1198,7 +984,6 @@ html.dark-mode .drawer-card-container.grid-container .drawer-card-grid .ant-inpu
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 加载中样式
|
|
||||||
.drawer-loading {
|
.drawer-loading {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
|||||||
+3
-1
@@ -22,7 +22,9 @@ const prodRollupOptions = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
// vite 配置
|
// vite 配置
|
||||||
|
// net stop winnat
|
||||||
|
// net start winnat
|
||||||
export default ({ command, mode }) => {
|
export default ({ command, mode }) => {
|
||||||
// 获取环境变量
|
// 获取环境变量
|
||||||
const env = loadEnv(mode, process.cwd());
|
const env = loadEnv(mode, process.cwd());
|
||||||
|
|||||||
@@ -646,6 +646,12 @@ namespace dy.net.job
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
//2026-06-16 21:56:40 bug修复 ,之前会一直重复下载这个图片
|
||||||
|
//判断如果文件路径="/" 说明是仅下载图片的记录,不处理,直接跳过也不用删除记录
|
||||||
|
if(exitVideo.VideoUrl=="/"&& exitVideo.IsMergeVideo == 1)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
//文件不存在,直接删掉原始记录
|
//文件不存在,直接删掉原始记录
|
||||||
await douyinVideoService.DeleteById(exitVideo.Id);
|
await douyinVideoService.DeleteById(exitVideo.Id);
|
||||||
}
|
}
|
||||||
@@ -1212,6 +1218,7 @@ namespace dy.net.job
|
|||||||
VideoHeight = height > 0 ? height : 1920, // 视频高度
|
VideoHeight = height > 0 ? height : 1920, // 视频高度
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// 执行图片合成视频操作
|
// 执行图片合成视频操作
|
||||||
var mergeResult = await douyinMergeVideoService.MergeToVideo(cookie.Cookies, AppContext.BaseDirectory, reqParams, savePath, fileNamefolder, config.DownImageVideo, config.DownImage, config.DownMp3);
|
var mergeResult = await douyinMergeVideoService.MergeToVideo(cookie.Cookies, AppContext.BaseDirectory, reqParams, savePath, fileNamefolder, config.DownImageVideo, config.DownImage, config.DownMp3);
|
||||||
if (!mergeResult)
|
if (!mergeResult)
|
||||||
@@ -1220,7 +1227,6 @@ namespace dy.net.job
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// 获取不带扩展名的完整路径
|
// 获取不带扩展名的完整路径
|
||||||
//string fullPathWithoutExtension = Path.Combine(Path.GetDirectoryName(savePath),Path.GetFileNameWithoutExtension(savePath) );
|
//string fullPathWithoutExtension = Path.Combine(Path.GetDirectoryName(savePath),Path.GetFileNameWithoutExtension(savePath) );
|
||||||
if (config.DownImageVideo)
|
if (config.DownImageVideo)
|
||||||
|
|||||||
@@ -111,6 +111,17 @@ namespace dy.net.repository
|
|||||||
return (0, 0, false);
|
return (0, 0, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//处理list里面 Signature 字段 可能存在一些导致SQL无法执行的特殊字符,需要清洗一下
|
||||||
|
// ========== 新增:清洗 Signature 字段特殊字符 ==========
|
||||||
|
foreach (var item in followInfos)
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrWhiteSpace(item.Signature))
|
||||||
|
{
|
||||||
|
item.Signature = CleanSignature(item.Signature);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// 2. 开启SqlSugar事务
|
// 2. 开启SqlSugar事务
|
||||||
@@ -268,5 +279,42 @@ namespace dy.net.repository
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 清洗签名字段,移除会导致SQL执行异常的特殊字符
|
||||||
|
/// </summary>
|
||||||
|
private string CleanSignature(string input,int maxLength=100)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(input))
|
||||||
|
return string.Empty;
|
||||||
|
|
||||||
|
// 1. 移除所有不可见控制字符(ASCII 0-31、127):空字符、换行、制表符、响铃等
|
||||||
|
// 如需保留换行/制表符,可放开注释里的判断条件
|
||||||
|
char[] validChars = input.Where(c =>
|
||||||
|
{
|
||||||
|
// if (c == '\n' || c == '\r' || c == '\t') return true; // 保留换行、回车、制表符
|
||||||
|
return !char.IsControl(c);
|
||||||
|
}).ToArray();
|
||||||
|
|
||||||
|
string result = new string(validChars);
|
||||||
|
|
||||||
|
// 2. 转义SQL单引号(SQL语法标准:单引号用双单引号转义,避免语句截断)
|
||||||
|
result = result.Replace("'", "''");
|
||||||
|
|
||||||
|
// 3. 去除首尾空白
|
||||||
|
result = result.Trim();
|
||||||
|
|
||||||
|
// 4. 可选:过滤反斜杠、空字节等其他高危字符(按需开启)
|
||||||
|
result = result.Replace("\\", string.Empty);
|
||||||
|
result = result.Replace("\0", string.Empty);
|
||||||
|
|
||||||
|
if (result.Length > maxLength)
|
||||||
|
{
|
||||||
|
result = result.Substring(0, maxLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user