Skip to content

Commit

Permalink
feat(core): 新增 Script.methods 方法可自定义对外暴露函数,优化搜索结果的显示。
Browse files Browse the repository at this point in the history
  • Loading branch information
enncy committed Apr 3, 2023
1 parent 0074f73 commit 53043d1
Show file tree
Hide file tree
Showing 5 changed files with 103 additions and 46 deletions.
2 changes: 1 addition & 1 deletion packages/core/src/core/worker/worker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,7 @@ export class OCSWorker<E extends RawElements = RawElements> extends CommonEventE

/** 如果存在答题处理 */
if (resolver) {
this.resolverIndex++;
try {
const result = await resolver.func();
/** 修改答题结果 */
Expand All @@ -255,7 +256,6 @@ export class OCSWorker<E extends RawElements = RawElements> extends CommonEventE
results[resolver.index].resolving = false;
results[resolver.index].error = (e as any)?.message || e;
}
this.resolverIndex++;
loop();
} else {
/** 继续等待,直到处理数量等于题目数量 */
Expand Down
55 changes: 37 additions & 18 deletions packages/core/src/interfaces/script.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,18 @@ import EventEmitter from 'events';

export type ScriptConfigsProvider<T extends Record<string, Config>> = T | { (): T };

export interface ScriptOptions<T extends Record<string, Config>> {
export interface ScriptOptions<C extends Record<string, Config>> {
name: string;
/** 运行的链接,如果是 string 类型,可以提供用户跳转功能 [链接的解释,链接/正则表达式][] */
url: [string, string | RegExp][];
/** 排除的链接 [链接的解释,链接/正则表达式][] */
excludes?: [string, string | RegExp][];
level?: number;
/** 脚本唯一命名空间 */
namespace?: string;
/** 脚本提示 */
notes?: string[];
configs?: ScriptConfigsProvider<T>;
/** 脚本配置 */
configs?: ScriptConfigsProvider<C>;
/** 不显示脚本页 */
hideInPanel?: boolean;
}
Expand All @@ -31,6 +33,8 @@ export type ScriptConfigs = {
};
} & Record<string, Config>;

export type ScriptMethods = Record<string, (...args: any[]) => any>;

type ScriptEvent = {
/** 在脚本加载时立即运行的事件 */
start: (...args: any[]) => any;
Expand Down Expand Up @@ -68,11 +72,14 @@ export class BaseScript<E extends ScriptEvent = ScriptEvent> extends CommonEvent
/**
* 脚本
*/
export class Script<T extends ScriptConfigs = ScriptConfigs> extends BaseScript<ScriptEvent> {
export class Script<
C extends ScriptConfigs = ScriptConfigs,
M extends ScriptMethods = ScriptMethods
> extends BaseScript<ScriptEvent> {
/** 未经处理的 configs 原对象 */
private _configs?: ScriptConfigsProvider<T>;
private _configs?: ScriptConfigsProvider<C>;
/** 存储已经处理过的 configs 对象,避免重复调用方法 */
private _resolvedConfigs?: T;
private _resolvedConfigs?: C;

/** 名字 */
name: string;
Expand All @@ -87,12 +94,13 @@ export class Script<T extends ScriptConfigs = ScriptConfigs> extends BaseScript<
/** 后台脚本(不提供管理页面) */
hideInPanel?: boolean;
/** 通过 configs 映射并经过解析后的配置对象 */
cfg: { [K in keyof T]: T[K]['defaultValue'] } & { notes?: string } = {} as any;
cfg: { [K in keyof C]: C[K]['defaultValue'] } & { notes?: string } = {} as any;
/** 经过初始化页面脚本注入的页面元素,如果初始化脚本未运行,则此元素为空 */
panel?: ScriptPanelElement;
/** 操作面板头部元素 */
header?: HeaderElement;

/** 脚本暴露给外部调用的方法 */
methods: M = Object.create({});
/** 自定义事件触发器,避免使用 script.emit , script.on 导致与原有的事件冲突,使用 script.event.emit 和 script.event.on */
event: EventEmitter = new EventEmitter();

Expand All @@ -119,14 +127,16 @@ export class Script<T extends ScriptConfigs = ScriptConfigs> extends BaseScript<
oncomplete,
onbeforeunload,
onrender,
onhistorychange
}: ScriptOptions<T> & {
onstart?: (this: Script<T>, ...args: any) => any;
onactive?: (this: Script<T>, ...args: any) => any;
oncomplete?: (this: Script<T>, ...args: any) => any;
onbeforeunload?: (this: Script<T>, ...args: any) => any;
onrender?: (this: Script<T>, elements: { panel: ScriptPanelElement; header: HeaderElement }) => any;
onhistorychange?: (this: Script<T>, type: 'push' | 'replace', ...args: any[]) => any;
onhistorychange,
methods
}: ScriptOptions<C> & {
onstart?: (this: Script<C, M>, ...args: any) => any;
onactive?: (this: Script<C, M>, ...args: any) => any;
oncomplete?: (this: Script<C, M>, ...args: any) => any;
onbeforeunload?: (this: Script<C, M>, ...args: any) => any;
onrender?: (this: Script<C, M>, elements: { panel: ScriptPanelElement; header: HeaderElement }) => any;
onhistorychange?: (this: Script<C, M>, type: 'push' | 'replace', ...args: any[]) => any;
methods?: (this: Script<C>) => M;
}) {
super();
this.name = name;
Expand All @@ -141,11 +151,20 @@ export class Script<T extends ScriptConfigs = ScriptConfigs> extends BaseScript<
this.onbeforeunload = this.errorHandler(onbeforeunload);
this.onrender = this.errorHandler(onrender);
this.onhistorychange = this.errorHandler(onhistorychange);
this.methods = methods?.bind(this)() || Object.create({});

if (this.methods) {
for (const key in methods) {
if (Reflect.has(this.methods, key) && typeof this.methods[key] !== 'function') {
Reflect.set(this.methods, key, this.errorHandler(this.methods[key]));
}
}
}
}

onConfigChange<K extends keyof T>(
onConfigChange<K extends keyof C>(
key: K,
handler: (curr: T[K]['defaultValue'], pre: T[K]['defaultValue'], remote: boolean) => any
handler: (curr: C[K]['defaultValue'], pre: C[K]['defaultValue'], remote: boolean) => any
) {
const _key = $.namespaceKey(this.namespace, key.toString());

Expand Down
49 changes: 42 additions & 7 deletions packages/scripts/src/projects/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,16 @@ import {
SimplifyWorkResult,
$script,
RenderScript,
$
$,
WorkUploadType
} from '@ocsjs/core';

import type { ScriptPanelElement, HeaderElement, AnswererWrapper } from '@ocsjs/core';
import { definedProjects } from '../index';
import { markdown } from '../utils/markdown';
import { workConfigs } from '../utils/configs';

export const TAB_WORK_RESULTS_KEY = 'common.work-results.results';
const TAB_WORK_RESULTS_KEY = 'common.work-results.results';

export const CommonProject = Project.create({
name: '通用',
Expand Down Expand Up @@ -342,6 +343,38 @@ export const CommonProject = Project.create({
defaultValue: 0
}
},
methods() {
return {
/**
* 更新状态
*/
updateWorkState: (state: { totalQuestionCount: number; requestIndex: number; resolverIndex: number }) => {
this.cfg.totalQuestionCount = state.totalQuestionCount;
this.cfg.requestIndex = state.requestIndex;
this.cfg.resolverIndex = state.resolverIndex;
},
/**
* 刷新状态
*/
refreshState: () => {
this.cfg.totalQuestionCount = 0;
this.cfg.requestIndex = 0;
this.cfg.resolverIndex = 0;
},
/**
* 清空搜索结果
*/
clearResults: () => {
$store.setTab(TAB_WORK_RESULTS_KEY, []);
},
getResults(): Promise<SimplifyWorkResult[]> | undefined {
return $store.getTab(TAB_WORK_RESULTS_KEY) || undefined;
},
setResults(results: SimplifyWorkResult[]) {
$store.setTab(TAB_WORK_RESULTS_KEY, results);
}
};
},
onrender({ panel }) {
/** 记录滚动高度 */
let scrollPercent = 0;
Expand Down Expand Up @@ -370,8 +403,8 @@ export const CommonProject = Project.create({
};

/** 渲染结果面板 */
const render = async () => {
const results: SimplifyWorkResult[] | undefined = await $store.getTab(TAB_WORK_RESULTS_KEY);
const render = debounce(async () => {
const results: SimplifyWorkResult[] | undefined = await this.methods.getResults();

if (results?.length) {
// 如果序号指向的结果为空,则代表已经被清空,则重新让index变成0
Expand Down Expand Up @@ -534,11 +567,12 @@ export const CommonProject = Project.create({
el(
'div',
[
`当前搜题: ${this.cfg.requestIndex + 1}/${this.cfg.totalQuestionCount}`,
`当前搜题: ${this.cfg.requestIndex}/${this.cfg.totalQuestionCount}`,
' , ',
`当前答题: ${this.cfg.resolverIndex + 1}/${this.cfg.totalQuestionCount}`,
`当前答题: ${this.cfg.resolverIndex}/${this.cfg.totalQuestionCount}`,
' , ',
el('a', '查看提示', (btn) => {
btn.style.cursor = 'pointer';
btn.addEventListener('click', () => {
$model('confirm', {
content: tip
Expand All @@ -553,7 +587,7 @@ export const CommonProject = Project.create({

el('hr')
);
};
}, 100);

/** 渲染结果列表 */
const createResult = (result: SimplifyWorkResult | undefined) => {
Expand Down Expand Up @@ -587,6 +621,7 @@ export const CommonProject = Project.create({

render();
this.onConfigChange('type', render);
this.onConfigChange('requestIndex', render);
this.onConfigChange('resolverIndex', render);
$store.addChangeListener(TAB_WORK_RESULTS_KEY, render);
}
Expand Down
23 changes: 13 additions & 10 deletions packages/scripts/src/projects/cx.ts
Original file line number Diff line number Diff line change
Expand Up @@ -495,8 +495,10 @@ export function workOrExam(
) {
$message('info', { content: `开始${type === 'work' ? '作业' : '考试'}` });

// 刷新搜索结果状态
CommonProject.scripts.workResults.methods.refreshState();
// 清空搜索结果
$store.setTab(TAB_WORK_RESULTS_KEY, []);
CommonProject.scripts.workResults.methods.clearResults();
// 置顶搜索结果面板
$script.pin(CommonProject.scripts.workResults);

Expand Down Expand Up @@ -616,12 +618,11 @@ export function workOrExam(

/** 完成答题后 */
onResultsUpdate(res) {
$store.setTab(TAB_WORK_RESULTS_KEY, simplifyWorkResult(res));
CommonProject.scripts.workResults.methods.setResults(simplifyWorkResult(res, workOrExamQuestionTitleTransform));
},
/** 监听答题结果 */
onResolveUpdate(res) {
CommonProject.scripts.workResults.cfg.totalQuestionCount = worker.totalQuestionCount;
CommonProject.scripts.workResults.cfg.requestIndex = worker.requestIndex;
CommonProject.scripts.workResults.cfg.resolverIndex = worker.resolverIndex;
CommonProject.scripts.workResults.methods.updateWorkState(worker);
},
async onElementSearched(elements) {
if (uncheckAllChoice) {
Expand Down Expand Up @@ -1242,8 +1243,10 @@ async function chapterTestTask(
const frameWindow = frame.contentWindow;
const { TiMu } = domSearchAll({ TiMu: '.TiMu' }, frameWindow!.document);

// 刷新搜索结果状态
CommonProject.scripts.workResults.methods.refreshState();
// 清空搜索结果
$store.setTab(TAB_WORK_RESULTS_KEY, []);
CommonProject.scripts.workResults.methods.clearResults();
// 置顶搜索结果面板
$script.pin(CommonProject.scripts.workResults);

Expand Down Expand Up @@ -1350,7 +1353,9 @@ async function chapterTestTask(

/** 完成答题后 */
async onResultsUpdate(res, curr) {
await $store.setTab(TAB_WORK_RESULTS_KEY, simplifyWorkResult(res));
CommonProject.scripts.workResults.methods.setResults(
simplifyWorkResult(res, chapterTestTaskQuestionTitleTransform)
);

// 没有完成时随机作答
if (!curr.result?.finish && curr.resolving === false) {
Expand Down Expand Up @@ -1394,9 +1399,7 @@ async function chapterTestTask(
}
},
onResolveUpdate(res) {
CommonProject.scripts.workResults.cfg.totalQuestionCount = worker.totalQuestionCount;
CommonProject.scripts.workResults.cfg.requestIndex = worker.requestIndex;
CommonProject.scripts.workResults.cfg.resolverIndex = worker.resolverIndex;
CommonProject.scripts.workResults.methods.updateWorkState(worker);
},
async onElementSearched(elements) {
const typeInput = elements.type[0] as HTMLInputElement;
Expand Down
20 changes: 10 additions & 10 deletions packages/scripts/src/projects/zhs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -830,8 +830,10 @@ function gxkWorkOrExam(
) {
$message('info', { content: `开始${type === 'work' ? '作业' : '考试'}` });

// 刷新搜索结果状态
CommonProject.scripts.workResults.methods.refreshState();
// 清空搜索结果
$store.setTab(TAB_WORK_RESULTS_KEY, []);
CommonProject.scripts.workResults.methods.clearResults();
// 置顶搜索结果面板
$script.pin(CommonProject.scripts.workResults);

Expand Down Expand Up @@ -873,12 +875,10 @@ function gxkWorkOrExam(
},
/** 完成答题后 */
onResultsUpdate(res) {
$store.setTab(TAB_WORK_RESULTS_KEY, simplifyWorkResult(res));
CommonProject.scripts.workResults.methods.setResults(simplifyWorkResult(res, titleTransform));
},
onResolveUpdate(res) {
CommonProject.scripts.workResults.cfg.totalQuestionCount = worker.totalQuestionCount;
CommonProject.scripts.workResults.cfg.requestIndex = worker.requestIndex;
CommonProject.scripts.workResults.cfg.resolverIndex = worker.resolverIndex;
CommonProject.scripts.workResults.methods.updateWorkState(worker);
}
});

Expand Down Expand Up @@ -957,8 +957,10 @@ function gxkWorkOrExam(
function xnkWork({ answererWrappers, period, thread }: CommonWorkOptions) {
$message('info', { content: '开始作业' });

// 刷新搜索结果状态
CommonProject.scripts.workResults.methods.refreshState();
// 清空搜索结果
$store.setTab(TAB_WORK_RESULTS_KEY, []);
CommonProject.scripts.workResults.methods.clearResults();
// 置顶搜索结果面板
$script.pin(CommonProject.scripts.workResults);

Expand Down Expand Up @@ -999,12 +1001,10 @@ function xnkWork({ answererWrappers, period, thread }: CommonWorkOptions) {
},

onResultsUpdate(res) {
$store.setTab(TAB_WORK_RESULTS_KEY, simplifyWorkResult(res));
CommonProject.scripts.workResults.methods.setResults(simplifyWorkResult(res, titleTransform));
},
onResolveUpdate(res) {
CommonProject.scripts.workResults.cfg.totalQuestionCount = worker.totalQuestionCount;
CommonProject.scripts.workResults.cfg.requestIndex = worker.requestIndex;
CommonProject.scripts.workResults.cfg.resolverIndex = worker.resolverIndex;
CommonProject.scripts.workResults.methods.updateWorkState(worker);
}
});

Expand Down

0 comments on commit 53043d1

Please sign in to comment.