Skip to content

Commit

Permalink
feat(core): 新增 通用-搜索结果 显示
Browse files Browse the repository at this point in the history
  • Loading branch information
enncy committed Jan 1, 2023
1 parent 345fbcc commit 9d9ead8
Showing 1 changed file with 235 additions and 29 deletions.
264 changes: 235 additions & 29 deletions packages/core/src/projects/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,18 @@ import { getAllRawConfigs } from '../utils/common';
import cloneDeep from 'lodash/cloneDeep';
import { $message, $model } from './init';
import { el } from '../utils/dom';
import { getValue, notification, setValue } from '../utils/tampermonkey';
import { notification } from '../utils/tampermonkey';
import { parseAnswererWrappers } from '../core/utils/common';
import { AnswererWrapper, defaultAnswerWrapperHandler } from '../core/worker/answer.wrapper.handler';
import debounce from 'lodash/debounce';
import { WorkResult } from '../core/worker/interface';
import { $creator } from '../utils/creator';

export const CommonProject: Project = {
export const CommonProject = Project.create({
name: '通用',
domains: [],
scripts: [
new Script({
scripts: {
onlineSearch: new Script({
name: '在线搜题',
url: [/.*/],
namespace: 'common.online-search',
Expand All @@ -35,8 +37,8 @@ export const CommonProject: Project = {
if (this.cfg.selectSearch) {
document.addEventListener(
'selectionchange',
debounce(function () {
setValue('common.online-search.selection', document.getSelection()?.toString() || '');
debounce(() => {
this.cfg.selection = document.getSelection()?.toString() || '';
}, 500)
);
}
Expand All @@ -55,7 +57,7 @@ export const CommonProject: Project = {

if (value) {
const t = Date.now();
const results = await defaultAnswerWrapperHandler(getValue('common.settings.answererWrappers'), {
const results = await defaultAnswerWrapperHandler(CommonProject.scripts.settings.cfg.answererWrappers, {
title: value
});
// 耗时计算
Expand Down Expand Up @@ -103,7 +105,208 @@ export const CommonProject: Project = {
);
}
}),
new Script({
workResults: new Script({
name: '搜索结果',
url: [/.*/],
namespace: 'common.work-results',
configs: {
notes: {
defaultValue: '点击题目序号,查看搜索结果<br>每次自动答题开始前,都会清空上一次的搜索结果。'
},
/**
* 显示类型
* list: 显示为题目列表
* numbers: 显示为序号列表
*/
type: {
label: '显示类型',
tag: 'select',
defaultValue: 'numbers' as 'questions' | 'numbers',
onload() {
this.append(
...$creator.selectOptions(this.getAttribute('value'), [
['numbers', '序号列表'],
['questions', '题目列表']
])
);
}
},
results: {
defaultValue: [] as WorkResult<any>[]
},
currentResultIndex: {
defaultValue: 0
}
},
onrender({ panel }) {
/** 渲染结果面板 */
const render = () => {
if (this.cfg.results.length) {
// 如果序号指向的结果为空,则代表已经被清空,则重新让index变成0
if (this.cfg.results[this.cfg.currentResultIndex] === undefined) {
this.cfg.currentResultIndex = 0;
}

// 渲染序号或者题目列表
if (this.cfg.type === 'numbers') {
const resultContainer = el('div', {}, (res) => {
res.style.width = '400px';
});
const list = el('div', {}, (list) => {
list.style.maxWidth = '400px';
list.style.marginBottom = '12px';
});
/** 渲染序号 */
const nums = this.cfg.results.map((result, index) => {
return el('span', { className: 'search-results-num', innerText: (index + 1).toString() }, (num) => {
if (result.error) {
num.classList.add('error');
} else if (index === this.cfg.currentResultIndex) {
num.classList.add('active');
}

num.onclick = () => {
for (const n of nums) {
n.classList.remove('active');
}
num.classList.add('active');
// 更新显示序号
this.cfg.currentResultIndex = index;
// 重新渲染结果列表
resultContainer.replaceChildren(createResult(result));
};
});
});

list.replaceChildren(...nums);
// 初始显示指定序号的结果
resultContainer.replaceChildren(createResult(this.cfg.results[this.cfg.currentResultIndex]));

panel.body.replaceChildren(el('hr'), list, resultContainer);
} else {
const resultContainer = el('div', {}, (res) => {
res.style.width = '50%';
});
const list = el('div', {}, (list) => {
list.style.width = '50%';

const resize = () => {
if (list.parentElement === null) {
window.removeEventListener('reset', resize);
} else {
list.style.maxHeight = window.innerHeight / 2 + 'px';
}
};
resize();
window.addEventListener('resize', resize);
});

/** 渲染题目列表 */
const questions = this.cfg.results.map((result, index) => {
return el(
'span',

[
el('span', { innerHTML: (index + 1 < 10 ? index + 1 + '&nbsp;' : index + 1).toString() }, (num) => {
num.style.marginRight = '12px';
num.style.display = 'inline-block';
}),
result.ctx?.elements.title?.map((t) => t.innerText || '题目为空').join(',') || '题目为空'
],
(question) => {
question.className = 'search-results-question';

if (result.error) {
question.classList.add('error');
} else if (index === this.cfg.currentResultIndex) {
question.classList.add('active');
}

question.onmouseover = () => {
question.classList.add('hover');
// 重新渲染结果列表
resultContainer.replaceChildren(createResult(result));
};

question.onmouseleave = () => {
question.classList.remove('hover');
// 重新显示指定序号的结果
resultContainer.replaceChildren(createResult(this.cfg.results[this.cfg.currentResultIndex]));
};

question.onclick = () => {
for (const q of questions) {
q.classList.remove('active');
}
question.classList.add('active');
// 更新显示序号
this.cfg.currentResultIndex = index;
// 重新渲染结果列表
resultContainer.replaceChildren(createResult(result));
};
}
);
});

list.replaceChildren(...questions);
// 初始显示指定序号的结果
resultContainer.replaceChildren(createResult(this.cfg.results[this.cfg.currentResultIndex]));

panel.body.replaceChildren(
el('hr'),
el(
'div',
[
list,
el('div', {}, (border) => {
border.style.borderRight = '1px solid #63636346';
border.style.margin = '0px 8px';
}),
resultContainer
],
(div) => {
div.style.maxWidth = '800px';
div.style.display = 'flex';
}
)
);
}
} else {
panel.body.replaceChildren('暂无任何搜索结果');
}
};

/** 渲染结果列表 */
const createResult = (result: WorkResult<any>) => {
if (result.error) {
return el(
'div',
result.error.message
? result.error.message
: result.result?.finish === false
? '此题未完成, 可能是没有匹配的选项。'
: result.ctx?.searchResults?.length === 0
? '此题未搜索到答案'
: '未知的错误',
(el) => {
el.style.textAlign = 'center';
el.style.color = 'red';
}
);
} else {
return el('search-results-element', {
results: result.ctx?.searchResults || [],
question: result.ctx?.elements.title?.map((t) => t.innerText).join(',')
});
}
};

render();
this.onConfigChange('type', render);
this.onConfigChange('results', render);
}
}),
settings: new Script({
name: '全局设置',
url: [/.*/],
namespace: 'common.settings',
Expand All @@ -118,7 +321,7 @@ export const CommonProject: Project = {
}
},
answererWrappers: {
defaultValue: []
defaultValue: [] as AnswererWrapper[]
},

answererWrappersButton: {
Expand All @@ -128,37 +331,40 @@ export const CommonProject: Project = {
type: 'button'
},
onload() {
const aws: any[] = getValue('common.settings.answererWrappers');
const aws: any[] = CommonProject.scripts.settings.cfg.answererWrappers;
this.value = `点击重新配置${aws.length ? ',当前有' + aws.length + '个可用题库' : ''}`;

this.onclick = () => {
const aw: any[] = getValue('common.settings.answererWrappers');
const aw: any[] = CommonProject.scripts.settings.cfg.answererWrappers;
const copy = $creator.copy('复制题库配置', JSON.stringify(aw));

const list = el('div', [
el('div', aw.length ? '以下是已经解析过的题库配置:' : ''),
el('div', aw.length ? ['以下是已经解析过的题库配置:', copy] : ''),
...createAnswererWrapperList(aw)
]);

const model = $model('prompt', {
content: el('div', {
innerHTML:
'具体配置教程,请查看官网的 <a href="https://docs.ocsjs.com/docs/work" target="_blank">"自动答题教程"</a>' +
list.innerHTML
}).innerHTML,
content: el('div', [
'具体配置教程,请查看官网:',
el('a', { href: 'https://docs.ocsjs.com/docs/work' }, '自动答题教程'),
list
]),
placeholder: aw.length ? '重新输入' : '输入题库配置',
cancelButton: el('button', {
className: 'model-cancel-button',
innerText: '清空题库配置',
onclick() {
$message('success', { content: '已清空,在答题前请记得重新配置。' });
model?.remove();
setValue('common.settings.answererWrappers', []);
CommonProject.scripts.settings.cfg.answererWrappers = [];
}
}),
async onConfirm(value) {
if (value) {
try {
const aw = await parseAnswererWrappers(value);
setValue('common.settings.answererWrappers', aw);
CommonProject.scripts.settings.cfg.answererWrappers = aw;

$model('alert', {
content: el('div', [
el('div', '配置成功,打开具有答题脚本的页面后即可自动答题,解析到的题库如下所示:'),
Expand Down Expand Up @@ -206,7 +412,7 @@ export const CommonProject: Project = {
});
}
}),
new Script({
guide: new Script({
name: '使用教程',
url: [/.*/],
namespace: 'common.guide',
Expand Down Expand Up @@ -235,17 +441,17 @@ export const CommonProject: Project = {
el('summary', project.name),
el(
'ul',
project.scripts.map((script) =>
Object.keys(project.scripts).map((key) =>
el('li', [
el(
'span',
{
title: [
'隐藏操作页面:\t' + (script.hideInPanel ? '是' : '否'),
'在以下页面中运行:\t' + script.url.join(',')
'隐藏操作页面:\t' + (project.scripts[key].hideInPanel ? '是' : '否'),
'在以下页面中运行:\t' + project.scripts[key].url.join(',')
].join('\n')
},
script.name
project.scripts[key].name
)
])
),
Expand Down Expand Up @@ -287,7 +493,7 @@ export const CommonProject: Project = {
}
}
}),
new Script({
dev: new Script({
name: '开发者调试页面',
// 使用时从打包中的代码修改此处为 true
hideInPanel: true,
Expand All @@ -296,7 +502,7 @@ export const CommonProject: Project = {
const configs = cloneDeep(
getAllRawConfigs(
getDefinedProjects()
.map((p) => p.scripts)
.map((p) => Object.keys(p.scripts).map((key) => p.scripts[key]))
.flat()
.filter((s) => s.name !== '开发者调试页面')
)
Expand All @@ -313,7 +519,7 @@ export const CommonProject: Project = {
return configs;
}
}),
new Script({
hack: new Script({
name: '页面复制粘贴限制解除脚本',
url: [/.*/],
hideInPanel: true,
Expand All @@ -325,8 +531,8 @@ export const CommonProject: Project = {
setTimeout(() => enableCopy(), 3000);
}
})
]
};
}
});

function enableCopy() {
try {
Expand Down

0 comments on commit 9d9ead8

Please sign in to comment.