mirror of
https://github.com/EstrellaXD/Auto_Bangumi.git
synced 2026-04-24 10:31:09 +08:00
Merge pull request #422 from Rewrite0/3.1-dev
webui: Code refactoring optimization
This commit is contained in:
@@ -1 +1,3 @@
|
||||
public-hoist-pattern[]=@vue/runtime-core
|
||||
public-hoist-pattern[]=*eslint*
|
||||
public-hoist-pattern[]=*prettier*
|
||||
|
||||
@@ -32,9 +32,11 @@ export const apiBangumi = {
|
||||
* @returns axios 请求返回的数据
|
||||
*/
|
||||
async updateRule(bangumiId: number, bangumiRule: BangumiRule) {
|
||||
const rule = omit(bangumiRule, ['id']);
|
||||
|
||||
const { data } = await axios.patch<ApiSuccess>(
|
||||
`api/v1/bangumi/update/${bangumiId}`,
|
||||
bangumiRule
|
||||
rule
|
||||
);
|
||||
return data;
|
||||
},
|
||||
|
||||
@@ -4,35 +4,25 @@ interface Status {
|
||||
status: 'Success';
|
||||
}
|
||||
|
||||
interface AnalysisError {
|
||||
status: 'Failed to parse link';
|
||||
}
|
||||
|
||||
export const apiDownload = {
|
||||
/**
|
||||
* 解析 RSS 链接
|
||||
* @param rss_link - RSS 链接
|
||||
*/
|
||||
async analysis(rss_link: string) {
|
||||
const fetchResult = createEventHook<BangumiRule>();
|
||||
const fetchError = createEventHook<AnalysisError>();
|
||||
|
||||
axios
|
||||
.post<any>('api/v1/download/analysis', {
|
||||
const { data } = await axios.post<BangumiRule & { status?: string }>(
|
||||
'api/v1/download/analysis',
|
||||
{
|
||||
rss_link,
|
||||
})
|
||||
.then(({ data }) => {
|
||||
if (data.status) {
|
||||
fetchError.trigger(data as AnalysisError);
|
||||
} else {
|
||||
fetchResult.trigger(data as BangumiRule);
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
return {
|
||||
onResult: fetchResult.on,
|
||||
onError: fetchError.on,
|
||||
};
|
||||
// 解析失败抛出错误
|
||||
if (data.status) {
|
||||
throw data;
|
||||
}
|
||||
|
||||
return data;
|
||||
},
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,38 +1,21 @@
|
||||
<script lang="ts" setup>
|
||||
import { useMessage } from 'naive-ui';
|
||||
import type { BangumiRule } from '#/bangumi';
|
||||
import { ruleTemplate } from '#/bangumi';
|
||||
|
||||
const { getAll } = useBangumiStore();
|
||||
/** v-model show */
|
||||
const show = defineModel('show', { default: false });
|
||||
|
||||
const rss = ref('');
|
||||
const message = useMessage();
|
||||
const rule = ref<BangumiRule>({
|
||||
added: false,
|
||||
deleted: false,
|
||||
dpi: '',
|
||||
eps_collect: false,
|
||||
filter: [],
|
||||
group_name: '',
|
||||
id: 0,
|
||||
official_title: '',
|
||||
offset: 0,
|
||||
poster_link: '',
|
||||
rss_link: [],
|
||||
rule_name: '',
|
||||
save_path: '',
|
||||
season: 1,
|
||||
season_raw: '',
|
||||
source: null,
|
||||
subtitle: '',
|
||||
title_raw: '',
|
||||
year: null,
|
||||
});
|
||||
const { getAll } = useBangumiStore();
|
||||
|
||||
const rss = ref('');
|
||||
const rule = ref<BangumiRule>(ruleTemplate);
|
||||
|
||||
const analysis = reactive({
|
||||
loading: false,
|
||||
next: false,
|
||||
});
|
||||
|
||||
const loading = reactive({
|
||||
collect: false,
|
||||
subscribe: false,
|
||||
@@ -47,27 +30,22 @@ watch(show, (val) => {
|
||||
}
|
||||
});
|
||||
|
||||
async function analyser() {
|
||||
async function analysisRss() {
|
||||
if (rss.value === '') {
|
||||
message.error('Please enter the RSS link!');
|
||||
} else {
|
||||
try {
|
||||
analysis.loading = true;
|
||||
const { onError, onResult } = await apiDownload.analysis(rss.value);
|
||||
onResult((data) => {
|
||||
rule.value = data;
|
||||
analysis.loading = false;
|
||||
analysis.next = true;
|
||||
console.log('rule', data);
|
||||
});
|
||||
const data = await apiDownload.analysis(rss.value);
|
||||
analysis.loading = false;
|
||||
|
||||
onError((err) => {
|
||||
message.error(err.status);
|
||||
analysis.loading = false;
|
||||
console.log('error', err);
|
||||
});
|
||||
rule.value = data;
|
||||
analysis.next = true;
|
||||
console.log('rule', data);
|
||||
} catch (error) {
|
||||
message.error('Failed to analyser!');
|
||||
const err = error as { status: string };
|
||||
message.error(err.status);
|
||||
console.log('error', err);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -78,6 +56,7 @@ async function collect() {
|
||||
loading.collect = true;
|
||||
const res = await apiDownload.collection(rule.value);
|
||||
loading.collect = false;
|
||||
|
||||
if (res) {
|
||||
message.success('Collect Success!');
|
||||
getAll();
|
||||
@@ -90,6 +69,7 @@ async function collect() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function subscribe() {
|
||||
if (rule.value) {
|
||||
try {
|
||||
@@ -124,9 +104,12 @@ async function subscribe() {
|
||||
></ab-setting>
|
||||
|
||||
<div flex="~ justify-end">
|
||||
<ab-button size="small" :loading="analysis.loading" @click="analyser">{{
|
||||
$t('topbar.add.analyse')
|
||||
}}</ab-button>
|
||||
<ab-button
|
||||
size="small"
|
||||
:loading="analysis.loading"
|
||||
@click="analysisRss"
|
||||
>{{ $t('topbar.add.analyse') }}</ab-button
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ export function useApi<
|
||||
|
||||
const fetchResult = createEventHook<TData>();
|
||||
const fetchError = createEventHook<TError>();
|
||||
const fetchFinally = createEventHook();
|
||||
const message = useMessage();
|
||||
|
||||
function execute(...params: Parameters<TApi>) {
|
||||
@@ -43,6 +44,7 @@ export function useApi<
|
||||
})
|
||||
.finally(() => {
|
||||
isLoading.value = false;
|
||||
fetchFinally.trigger('');
|
||||
});
|
||||
}
|
||||
|
||||
@@ -53,5 +55,6 @@ export function useApi<
|
||||
execute,
|
||||
onResult: fetchResult.on,
|
||||
onError: fetchError.on,
|
||||
onFinally: fetchFinally.on,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,92 +1,12 @@
|
||||
<script lang="ts" setup>
|
||||
import type { BangumiRule } from '#/bangumi';
|
||||
|
||||
const { data } = storeToRefs(useBangumiStore());
|
||||
const { getAll, useUpdateRule, useDisableRule, useEnableRule, useDeleteRule } =
|
||||
const { bangumi, editRule } = storeToRefs(useBangumiStore());
|
||||
const { getAll, updateRule, enableRule, openEditPopup, ruleManage } =
|
||||
useBangumiStore();
|
||||
|
||||
const editRule = reactive<{
|
||||
show: boolean;
|
||||
item: BangumiRule;
|
||||
}>({
|
||||
show: false,
|
||||
item: {
|
||||
added: false,
|
||||
deleted: false,
|
||||
dpi: '',
|
||||
eps_collect: false,
|
||||
filter: [],
|
||||
group_name: '',
|
||||
id: 0,
|
||||
official_title: '',
|
||||
offset: 0,
|
||||
poster_link: '',
|
||||
rss_link: [],
|
||||
rule_name: '',
|
||||
save_path: '',
|
||||
season: 1,
|
||||
season_raw: '',
|
||||
source: null,
|
||||
subtitle: '',
|
||||
title_raw: '',
|
||||
year: null,
|
||||
},
|
||||
});
|
||||
|
||||
function open(data: BangumiRule) {
|
||||
editRule.show = true;
|
||||
editRule.item = data;
|
||||
}
|
||||
|
||||
function refresh() {
|
||||
editRule.show = false;
|
||||
getAll();
|
||||
}
|
||||
|
||||
const { execute: updateRule, onResult: onUpdateRuleResult } = useUpdateRule();
|
||||
const { execute: enableRule, onResult: onEnableRuleResult } = useEnableRule();
|
||||
const { execute: disableRule, onResult: onDisableRuleResult } =
|
||||
useDisableRule();
|
||||
const { execute: deleteRule, onResult: onDeleteRuleResult } = useDeleteRule();
|
||||
const message = useMessage();
|
||||
|
||||
onUpdateRuleResult(({ msg }) => {
|
||||
message.success(msg);
|
||||
refresh();
|
||||
});
|
||||
|
||||
onDisableRuleResult(({ msg }) => {
|
||||
message.success(msg);
|
||||
refresh();
|
||||
});
|
||||
|
||||
onEnableRuleResult(({ msg }) => {
|
||||
message.success(msg);
|
||||
refresh();
|
||||
});
|
||||
|
||||
onDeleteRuleResult(({ msg }) => {
|
||||
message.success(msg);
|
||||
refresh();
|
||||
});
|
||||
|
||||
onActivated(() => {
|
||||
getAll();
|
||||
});
|
||||
|
||||
function ruleManage(
|
||||
type: 'disable' | 'delete',
|
||||
id: number,
|
||||
deleteFile: boolean
|
||||
) {
|
||||
if (type === 'disable') {
|
||||
disableRule(id, deleteFile);
|
||||
}
|
||||
if (type === 'delete') {
|
||||
deleteRule(id, deleteFile);
|
||||
}
|
||||
}
|
||||
|
||||
definePage({
|
||||
name: 'Bangumi List',
|
||||
});
|
||||
@@ -96,13 +16,13 @@ definePage({
|
||||
<div overflow-auto mt-12px flex-grow>
|
||||
<div flex="~ wrap" gap-y-12px gap-x-50px>
|
||||
<ab-bangumi-card
|
||||
v-for="i in data"
|
||||
v-for="i in bangumi"
|
||||
:key="i.id"
|
||||
:class="[i.deleted && 'grayscale']"
|
||||
:poster="i.poster_link ?? ''"
|
||||
:name="i.official_title"
|
||||
:season="i.season"
|
||||
@click="() => open(i)"
|
||||
@click="() => openEditPopup(i)"
|
||||
></ab-bangumi-card>
|
||||
|
||||
<ab-edit-rule
|
||||
|
||||
@@ -1,67 +1,87 @@
|
||||
import type { BangumiRule } from '#/bangumi';
|
||||
import { ruleTemplate } from '#/bangumi';
|
||||
|
||||
export const useBangumiStore = defineStore('bangumi', () => {
|
||||
const data = ref<BangumiRule[]>();
|
||||
const message = useMessage();
|
||||
|
||||
function getAll() {
|
||||
const { execute, onResult } = useApi(apiBangumi.getAll);
|
||||
const bangumi = ref<BangumiRule[]>();
|
||||
const editRule = reactive<{
|
||||
show: boolean;
|
||||
item: BangumiRule;
|
||||
}>({
|
||||
show: false,
|
||||
item: ruleTemplate,
|
||||
});
|
||||
|
||||
const { execute: getAll, onResult: onBangumiResult } = useApi(
|
||||
apiBangumi.getAll
|
||||
);
|
||||
const { execute: updateRule, onResult: onUpdateRuleResult } = useApi(
|
||||
apiBangumi.updateRule
|
||||
);
|
||||
const { execute: enableRule, onResult: onEnableRuleResult } = useApi(
|
||||
apiBangumi.enableRule
|
||||
);
|
||||
const { execute: disableRule, onResult: onDisableRuleResult } = useApi(
|
||||
apiBangumi.disableRule
|
||||
);
|
||||
const { execute: deleteRule, onResult: onDeleteRuleResult } = useApi(
|
||||
apiBangumi.deleteRule
|
||||
);
|
||||
|
||||
onBangumiResult((res) => {
|
||||
function sort(arr: BangumiRule[]) {
|
||||
return arr.sort((a, b) => b.id - a.id);
|
||||
}
|
||||
|
||||
onResult((res) => {
|
||||
const enabled = sort(res.filter((e) => !e.deleted));
|
||||
const disabled = sort(res.filter((e) => e.deleted));
|
||||
const enabled = sort(res.filter((e) => !e.deleted));
|
||||
const disabled = sort(res.filter((e) => e.deleted));
|
||||
|
||||
data.value = [...enabled, ...disabled];
|
||||
});
|
||||
bangumi.value = [...enabled, ...disabled];
|
||||
});
|
||||
|
||||
execute();
|
||||
function refresh() {
|
||||
editRule.show = false;
|
||||
getAll();
|
||||
}
|
||||
|
||||
function useUpdateRule() {
|
||||
const { execute, onResult } = useApi(apiBangumi.updateRule);
|
||||
function actionSuccess({ msg }) {
|
||||
message.success(msg);
|
||||
refresh();
|
||||
}
|
||||
onUpdateRuleResult(actionSuccess);
|
||||
onDisableRuleResult(actionSuccess);
|
||||
onEnableRuleResult(actionSuccess);
|
||||
onDeleteRuleResult(actionSuccess);
|
||||
|
||||
return {
|
||||
execute,
|
||||
onResult,
|
||||
};
|
||||
function openEditPopup(data: BangumiRule) {
|
||||
editRule.show = true;
|
||||
editRule.item = data;
|
||||
}
|
||||
|
||||
function useDisableRule() {
|
||||
const { execute, onResult } = useApi(apiBangumi.disableRule);
|
||||
|
||||
return {
|
||||
execute,
|
||||
onResult,
|
||||
};
|
||||
}
|
||||
|
||||
function useEnableRule() {
|
||||
const { execute, onResult } = useApi(apiBangumi.enableRule);
|
||||
|
||||
return {
|
||||
execute,
|
||||
onResult,
|
||||
};
|
||||
}
|
||||
|
||||
function useDeleteRule() {
|
||||
const { execute, onResult } = useApi(apiBangumi.deleteRule);
|
||||
|
||||
return {
|
||||
execute,
|
||||
onResult,
|
||||
};
|
||||
function ruleManage(
|
||||
type: 'disable' | 'delete',
|
||||
id: number,
|
||||
deleteFile: boolean
|
||||
) {
|
||||
if (type === 'disable') {
|
||||
disableRule(id, deleteFile);
|
||||
}
|
||||
if (type === 'delete') {
|
||||
deleteRule(id, deleteFile);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
data,
|
||||
bangumi,
|
||||
editRule,
|
||||
|
||||
getAll,
|
||||
useUpdateRule,
|
||||
useDisableRule,
|
||||
useEnableRule,
|
||||
useDeleteRule,
|
||||
updateRule,
|
||||
enableRule,
|
||||
disableRule,
|
||||
deleteRule,
|
||||
openEditPopup,
|
||||
ruleManage,
|
||||
};
|
||||
});
|
||||
|
||||
22
webui/src/utils/omit.test.ts
Normal file
22
webui/src/utils/omit.test.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import { expect, it } from 'vitest';
|
||||
import { omit } from './omit';
|
||||
|
||||
it('test omit', () => {
|
||||
const obj = {
|
||||
a: 1,
|
||||
b: 2,
|
||||
c: 3,
|
||||
d: 4,
|
||||
};
|
||||
|
||||
expect(omit(obj, ['a'])).toStrictEqual({
|
||||
b: 2,
|
||||
c: 3,
|
||||
d: 4,
|
||||
});
|
||||
|
||||
expect(omit(obj, ['b', 'c'])).toStrictEqual({
|
||||
a: 1,
|
||||
d: 4,
|
||||
});
|
||||
});
|
||||
12
webui/src/utils/omit.ts
Normal file
12
webui/src/utils/omit.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
export function omit<T extends { [k: string]: any }>(
|
||||
obj: T,
|
||||
omitKeys: Array<keyof T>
|
||||
) {
|
||||
return Object.keys(obj).reduce((acc, key) => {
|
||||
if (omitKeys.includes(key)) {
|
||||
return acc;
|
||||
} else {
|
||||
return { ...acc, [key]: obj[key] };
|
||||
}
|
||||
}, {});
|
||||
}
|
||||
@@ -20,23 +20,26 @@ export interface BangumiRule {
|
||||
year: string | null;
|
||||
}
|
||||
|
||||
export interface BangumiUpdate {
|
||||
added: boolean;
|
||||
deleted: boolean;
|
||||
dpi: string;
|
||||
eps_collect: boolean;
|
||||
filter: string;
|
||||
group_name: string;
|
||||
official_title: string;
|
||||
offset: number;
|
||||
poster_link: string | null;
|
||||
rss_link: string;
|
||||
rule_name: string;
|
||||
save_path: string;
|
||||
season: number;
|
||||
season_raw: string;
|
||||
source: string | null;
|
||||
subtitle: string;
|
||||
title_raw: string;
|
||||
year: string | null;
|
||||
}
|
||||
export type BangumiUpdate = Omit<BangumiRule, 'id'>;
|
||||
|
||||
export const ruleTemplate: BangumiRule = {
|
||||
added: false,
|
||||
deleted: false,
|
||||
dpi: '',
|
||||
eps_collect: false,
|
||||
filter: [],
|
||||
group_name: '',
|
||||
id: 0,
|
||||
official_title: '',
|
||||
offset: 0,
|
||||
poster_link: '',
|
||||
rss_link: [],
|
||||
rule_name: '',
|
||||
save_path: '',
|
||||
season: 1,
|
||||
season_raw: '',
|
||||
source: null,
|
||||
subtitle: '',
|
||||
title_raw: '',
|
||||
year: null,
|
||||
};
|
||||
|
||||
1
webui/types/dts/auto-imports.d.ts
vendored
1
webui/types/dts/auto-imports.d.ts
vendored
@@ -70,6 +70,7 @@ declare global {
|
||||
const mapWritableState: typeof import('pinia')['mapWritableState']
|
||||
const markRaw: typeof import('vue')['markRaw']
|
||||
const nextTick: typeof import('vue')['nextTick']
|
||||
const omit: typeof import('../../src/utils/omit')['omit']
|
||||
const onActivated: typeof import('vue')['onActivated']
|
||||
const onBeforeMount: typeof import('vue')['onBeforeMount']
|
||||
const onBeforeRouteLeave: typeof import('vue-router/auto')['onBeforeRouteLeave']
|
||||
|
||||
Reference in New Issue
Block a user