From 6d9fa5112e81ce278f16a8248c3f9dfe3fed8e13 Mon Sep 17 00:00:00 2001 From: enncy <877526278@qq.com> Date: Mon, 30 May 2022 23:51:47 +0800 Subject: [PATCH] =?UTF-8?q?fix(core):=20=E5=9B=A0=E5=85=A8=E5=B1=80?= =?UTF-8?q?=E5=8F=98=E9=87=8F=E5=88=A0=E9=99=A4=EF=BC=8C=E4=B8=94=E9=9C=80?= =?UTF-8?q?=E8=A6=81=E5=B0=81=E8=A3=85=20store=20=E4=B8=AD=E5=A4=9A?= =?UTF-8?q?=E4=B8=AA=E5=8F=98=E9=87=8F=E7=9A=84=E5=A4=84=E7=90=86=EF=BC=8C?= =?UTF-8?q?=E4=BB=A5=E5=8F=8A=E9=98=B2=E6=AD=A2=E5=8F=98=E9=87=8F=E6=B1=A1?= =?UTF-8?q?=E6=9F=93=EF=BC=8C=E6=96=B0=E5=A2=9E=E4=BA=86=20useContext=20?= =?UTF-8?q?=E5=92=8C=20useSettings=20=E7=9A=84API=EF=BC=8C=E7=9B=B8?= =?UTF-8?q?=E5=BA=94=E6=B6=89=E5=8F=8A=E4=BB=A3=E7=A0=81=E5=90=8C=E6=AD=A5?= =?UTF-8?q?=E6=9B=B4=E6=96=B0=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/core/src/App.vue | 26 +-- packages/core/src/components/Alert.tsx | 5 +- packages/core/src/components/Terminal.tsx | 8 +- .../components/cx/CommonWorkSettingPanel.tsx | 167 ++++++++---------- .../src/components/cx/ExamSettingPanel.tsx | 8 +- .../src/components/cx/StudySettingPanel.tsx | 20 ++- .../src/components/cx/WorkSettingPanel.tsx | 20 ++- packages/core/src/components/index.tsx | 141 ++++++++------- packages/core/src/components/utils.ts | 11 +- .../components/zhs/CommonWorkSettingPanel.tsx | 103 +++++------ .../components/zhs/CreditWorkSettingPanel.tsx | 31 ++-- .../src/components/zhs/ExamSettingPanel.tsx | 37 ++-- .../src/components/zhs/StudySettingPanel.tsx | 9 +- .../src/components/zhs/WorkSettingPanel.tsx | 21 ++- packages/core/src/core/types.ts | 52 ++++-- packages/core/src/logger.ts | 5 +- packages/core/src/main.ts | 4 +- packages/core/src/script/cx/recognize.ts | 18 +- packages/core/src/start.ts | 35 +--- packages/core/src/store.ts | 84 ++++++++- 20 files changed, 444 insertions(+), 361 deletions(-) diff --git a/packages/core/src/App.vue b/packages/core/src/App.vue index cbd2b7bf..fd4b89e2 100644 --- a/packages/core/src/App.vue +++ b/packages/core/src/App.vue @@ -6,11 +6,11 @@ >
@@ -93,11 +93,15 @@ import { Alert } from './components/alert'; import { Tooltip } from './components/Tooltip'; import { addFunctionEventListener, dragElement, getCurrentPanels } from './core/utils'; import { definedScripts } from './main'; -import { store } from './store'; +import { useContext, useStore } from './store'; + +const ctx = useContext(); + +const local = useStore('localStorage'); const panels = ref(getCurrentPanels(definedScripts)); -const hide = ref(store.localStorage.hide); +const hide = ref(local.hide); /** * 对面板进行处理 @@ -137,7 +141,7 @@ watch(currentPanels, () => { }); watch(hide, () => { - store.localStorage.hide = hide.value; + local.hide = hide.value; nextTick(() => { enablePanelDrag(); }); @@ -148,7 +152,7 @@ onMounted(() => { listenResetEvent(); enablePanelDrag(); listenHistoryChange(); - let { x, y } = store.localStorage.position; + let { x, y } = local.position; // 设置初始位置 if (panel.value && x && y) { // 判断移动后的坐标是否超出了屏幕,如果超出则重置为初始位置 @@ -178,7 +182,7 @@ onMounted(() => { * 启用面板拖拽 */ function enablePanelDrag() { - if (panel.value && store.startOptions?.draggable) { + if (panel.value && ctx.common.startOptions?.draggable) { if (logo.value) { dragElement(logo.value, panel.value, onMove); } @@ -190,8 +194,8 @@ function enablePanelDrag() { } function onMove(x: number, y: number) { - store.localStorage.position.x = x; - store.localStorage.position.y = y; + local.position.x = x; + local.position.y = y; } /** diff --git a/packages/core/src/components/Alert.tsx b/packages/core/src/components/Alert.tsx index 74e15736..5e720d55 100644 --- a/packages/core/src/components/Alert.tsx +++ b/packages/core/src/components/Alert.tsx @@ -1,5 +1,5 @@ import { defineComponent, PropType, toRefs } from 'vue'; -import { store } from '../main'; +import { useContext } from '../store'; export interface AlertType { key: any; @@ -24,6 +24,7 @@ export const Alert = defineComponent({ }, setup(props) { const { type, text, index } = toRefs(props); + const { common } = useContext(); return () => (
@@ -31,7 +32,7 @@ export const Alert = defineComponent({
(store.alerts.splice(index.value, 1))}> + onClick={() => (common.alerts.splice(index.value, 1))}> × { text.value } diff --git a/packages/core/src/components/Terminal.tsx b/packages/core/src/components/Terminal.tsx index 6e251bf7..71ff3289 100644 --- a/packages/core/src/components/Terminal.tsx +++ b/packages/core/src/components/Terminal.tsx @@ -1,16 +1,18 @@ import { defineComponent, nextTick, onMounted, watch } from 'vue'; import { domSearch } from '../core/utils'; -import { store } from '../store'; +import { useStore } from '../store'; export const Terminal = defineComponent({ setup () { + const local = useStore('localStorage'); + onMounted(() => { // 控制台元素 const { terminal } = domSearch({ terminal: '.terminal' }); // 监听改变,并且滚动到最下方 watch( - () => store.localStorage.logs, + () => local.logs, // eslint-disable-next-line vue/valid-next-tick () => nextTick(() => scroll()) ); @@ -29,7 +31,7 @@ export const Terminal = defineComponent({ return () => (
- {store.localStorage.logs.map((log: any) => ( + {local.logs.map((log: any) => (
{new Date(log.time).toLocaleTimeString('zh-CN')} diff --git a/packages/core/src/components/cx/CommonWorkSettingPanel.tsx b/packages/core/src/components/cx/CommonWorkSettingPanel.tsx index 89b7d6c9..04c74920 100644 --- a/packages/core/src/components/cx/CommonWorkSettingPanel.tsx +++ b/packages/core/src/components/cx/CommonWorkSettingPanel.tsx @@ -1,7 +1,7 @@ import { defineComponent, PropType, toRefs } from 'vue'; -import { createWorkerSetting } from '..'; -import { store } from '../../main'; + import { CommonWorkSetting } from '../../scripts'; +import { useSettings } from '../../store'; import { Tooltip } from '../Tooltip'; export const CommonWorkSettingPanel = defineComponent({ @@ -9,109 +9,92 @@ export const CommonWorkSettingPanel = defineComponent({ settings: { default: () => {}, type: Object as PropType - }, - upload: { - default: () => 'close', - type: String as PropType } }, + setup (props, { slots }) { - const { settings, upload } = toRefs(props); + const { settings } = toRefs(props); + + const commonSettings = useSettings().cx.common; return () => ( <> - {slots.upload - ? slots.upload() - : ( - createWorkerSetting( - '自动答题', + + {slots.upload?.()} + + +
+ + + +
- { - upload.value === 'close' - ? null - : ( - <> - -
- - - -
+ +
+ (settings.value.period = e.target.valueAsNumber)} + onInput={(e: any) => (settings.value.period = e.target.valueAsNumber)} + /> +
- -
- (settings.value.period = e.target.valueAsNumber)} - onInput={(e: any) => (settings.value.period = e.target.valueAsNumber)} - /> -
+ +
+ + (settings.value.timeout = e.target.valueAsNumber)} + onInput={(e: any) => (settings.value.timeout = e.target.valueAsNumber)} + /> + +
- -
- - (settings.value.timeout = e.target.valueAsNumber)} - onInput={(e: any) => (settings.value.timeout = e.target.valueAsNumber)} - /> - -
+ +
+ (settings.value.retry = e.target.valueAsNumber)} + onInput={(e: any) => (settings.value.retry = e.target.valueAsNumber)} + /> +
- -
- (settings.value.retry = e.target.valueAsNumber)} - onInput={(e: any) => (settings.value.retry = e.target.valueAsNumber)} - /> -
- -
- - (settings.value.waitForCheck = e.target.valueAsNumber)} - onInput={(e: any) => (settings.value.waitForCheck = e.target.valueAsNumber)} - /> - -
+ {slots.extra?.()} - {slots.extra?.()} - - ) - } + +
+ + (settings.value.waitForCheck = e.target.valueAsNumber)} + onInput={(e: any) => (settings.value.waitForCheck = e.target.valueAsNumber)} + /> + +
diff --git a/packages/core/src/components/cx/ExamSettingPanel.tsx b/packages/core/src/components/cx/ExamSettingPanel.tsx index b144d2a6..dbf23aa1 100644 --- a/packages/core/src/components/cx/ExamSettingPanel.tsx +++ b/packages/core/src/components/cx/ExamSettingPanel.tsx @@ -1,18 +1,18 @@ import { defineComponent } from 'vue'; import { createWorkerSetting } from '..'; -import { store } from '../../store'; +import { useSettings } from '../../store'; + import { CommonWorkSettingPanel } from './CommonWorkSettingPanel'; export const ExamSettingPanel = defineComponent({ setup () { - const settings = store.setting.cx.exam; + const settings = useSettings().cx.exam; return () => (
(
@@ -23,8 +26,8 @@ export const StudySettingPanel = defineComponent({ step="1" onInput={(e: any) => { settings.playbackRate = e.target.valueAsNumber; - if (store.currentMedia) { - store.currentMedia.playbackRate = e.target.valueAsNumber; + if (ctx.common.currentMedia) { + ctx.common.currentMedia.playbackRate = e.target.valueAsNumber; } }} > @@ -42,7 +45,7 @@ export const StudySettingPanel = defineComponent({ value={settings.volume} onInput={(e: any) => { settings.volume = e.target.valueAsNumber; - if (store.currentMedia) store.currentMedia.volume = e.target.valueAsNumber; + if (ctx.common.currentMedia) ctx.common.currentMedia.volume = e.target.valueAsNumber; }} /> {Math.round(settings.volume * 100)}% @@ -56,8 +59,8 @@ export const StudySettingPanel = defineComponent({ value={settings.line || '默认路线'} onChange={(e: any) => { settings.line = e.target.value; - if (store.videojs && store.currentMedia) { - switchPlayLine(settings, store.videojs, store.currentMedia, e.target.value); + if (ctx.cx.videojs && ctx.common.currentMedia) { + switchPlayLine(settings, ctx.cx.videojs, ctx.common.currentMedia, e.target.value); } }} > @@ -99,8 +102,7 @@ export const StudySettingPanel = defineComponent({
(
- + (settings.upload = e.target.value) + ) + }} + > +
); diff --git a/packages/core/src/components/index.tsx b/packages/core/src/components/index.tsx index 9dae6a78..5fff2547 100644 --- a/packages/core/src/components/index.tsx +++ b/packages/core/src/components/index.tsx @@ -2,7 +2,7 @@ import { defineComponent, VNodeProps } from 'vue'; import { ScriptPanelChild } from '../core/define.script'; import { AnswererWrapper } from '../core/worker/answer.wrapper.handler'; -import { store } from '../store'; +import { useSettings } from '../store'; import { SearchResults } from './SearchResults'; import { Terminal } from './Terminal'; import { Tooltip } from './Tooltip'; @@ -92,12 +92,17 @@ export function createWorkerSetting ( return option; }); + const { common } = useSettings(); + return ( <>
- { + changeHandler(e); + }}> {options.map((option) => (
- { - config.selected === 'close' - ? null - : ( - <> - -
- - { - const text = e.clipboardData?.getData('text') || await navigator.clipboard.readText() || ''; - store.setting.answererWrappers = parseAnswererWrappers(text); - }} - > - - - - {store.setting.answererWrappers.length - ? ( - ( - <> - 解析成功, 一共有 {store.setting.answererWrappers.length} 个题库 -
    - {store.setting.answererWrappers.map((aw) => ( -
  1. {aw.name}
  2. - ))} -
- - ) - }} - > - -
- ) - : ( - - - - )} -
- - - { - window.open('https://docs.ocsjs.com/docs/work'); - }}> + +
+ + { + const text = e.clipboardData?.getData('text') || await navigator.clipboard.readText() || ''; + common.answererWrappers = parseAnswererWrappers(text); + console.log('common', { common }); + }} + > + + + + { common.answererWrappers.length + ? ( + ( + <> + 解析成功, 一共有 { common.answererWrappers.length} 个题库 +
    + { common.answererWrappers.map((aw) => ( +
  1. {aw.name}
  2. + ))} +
+ + ) + }} + > + +
+ ) + : ( + + + + )} +
+ + + { + window.open('https://docs.ocsjs.com/docs/work'); + }}> ❓ - - - -
- - ) - } +
+
+
+
); @@ -176,19 +174,28 @@ export function createWorkerSetting ( function parseAnswererWrappers (value: string): AnswererWrapper[] { try { - const aw = JSON.parse(value); + const aw: AnswererWrapper[] = JSON.parse(value); if (aw && Array.isArray(aw)) { - message('success', '题库配置成功!'); + if (aw.length) { + if (aw.every((item) => item.url && item.handler)) { + message('success', '题库配置成功!'); + return aw; + } else { + message('error', '题库缺少必要参数: `url` 或 `handler` '); + } + } else { + message('error', '题库为空!'); + } return aw; } else { message('error', '题库配置格式错误!'); - return []; } } catch (e) { console.log(e); message('error', '题库配置格式错误!'); - return []; } + + return []; } /** diff --git a/packages/core/src/components/utils.ts b/packages/core/src/components/utils.ts index f27b76df..5b5e2853 100644 --- a/packages/core/src/components/utils.ts +++ b/packages/core/src/components/utils.ts @@ -1,10 +1,11 @@ -import { store } from '../main'; + +import { useContext } from '../store'; import { AlertType } from './alert'; export function message(type: AlertType['type'], text: string) { - if (store.alerts.length > 3) { - store.alerts.shift(); + const { common } = useContext(); + if (common.alerts.length > 3) { + common.alerts.shift(); } - - store.alerts.push({ type, text, key: store.alerts.length }); + common.alerts.push({ type, text, key: common.alerts.length }); } diff --git a/packages/core/src/components/zhs/CommonWorkSettingPanel.tsx b/packages/core/src/components/zhs/CommonWorkSettingPanel.tsx index 5b6aabd3..3fde3e64 100644 --- a/packages/core/src/components/zhs/CommonWorkSettingPanel.tsx +++ b/packages/core/src/components/zhs/CommonWorkSettingPanel.tsx @@ -1,5 +1,4 @@ import { defineComponent, PropType, toRefs } from 'vue'; -import { createWorkerSetting } from '..'; import { CommonWorkSetting } from '../../scripts'; import { Tooltip } from '../Tooltip'; @@ -8,75 +7,55 @@ export const CommonWorkSettingPanel = defineComponent({ settings: { default: () => {}, type: Object as PropType - }, - upload: { - default: () => 'close', - type: String as PropType } }, - setup (props, { slots }) { - const { settings, upload } = toRefs(props); + emits: ['updateUpload'], + setup (props, { slots, emit }) { + const { settings } = toRefs(props); return () => ( <> - {slots.upload - ? slots.upload() - : ( - createWorkerSetting( - '自动答题', - { - selected: upload.value - }, - (e: any) => (upload.value = e.target.value) - ) - )} - { - upload.value === 'close' - ? null - : ( - <> - -
- (settings.value.period = e.target.valueAsNumber)} - onInput={(e: any) => (settings.value.period = e.target.valueAsNumber)} - /> -
+ { slots.upload?.()} - -
- - (settings.value.timeout = e.target.valueAsNumber)} - onInput={(e: any) => (settings.value.timeout = e.target.valueAsNumber)} - /> - -
+ +
+ (settings.value.period = e.target.valueAsNumber)} + onInput={(e: any) => (settings.value.period = e.target.valueAsNumber)} + /> +
- -
- (settings.value.retry = e.target.valueAsNumber)} - onInput={(e: any) => (settings.value.retry = e.target.valueAsNumber)} - /> -
- - ) - } + +
+ + (settings.value.timeout = e.target.valueAsNumber)} + onInput={(e: any) => (settings.value.timeout = e.target.valueAsNumber)} + /> + +
+ + +
+ (settings.value.retry = e.target.valueAsNumber)} + onInput={(e: any) => (settings.value.retry = e.target.valueAsNumber)} + /> +
diff --git a/packages/core/src/components/zhs/CreditWorkSettingPanel.tsx b/packages/core/src/components/zhs/CreditWorkSettingPanel.tsx index d6a8957e..b2b62933 100644 --- a/packages/core/src/components/zhs/CreditWorkSettingPanel.tsx +++ b/packages/core/src/components/zhs/CreditWorkSettingPanel.tsx @@ -1,28 +1,31 @@ import { defineComponent } from 'vue'; import { createWorkerSetting } from '..'; -import { store } from '../../store'; +import { useSettings } from '../../store'; + import { CommonWorkSettingPanel } from './CommonWorkSettingPanel'; export const CreditWorkSettingPanel = defineComponent({ setup () { - const settings = store.setting.zhs.work; + const settings = useSettings().zhs.work; return () => (
- (settings.upload = e.target.value) - ) - }}> + (settings.upload = e.target.value) + ) + }}>
diff --git a/packages/core/src/components/zhs/ExamSettingPanel.tsx b/packages/core/src/components/zhs/ExamSettingPanel.tsx index 4a3132a1..f7061c7a 100644 --- a/packages/core/src/components/zhs/ExamSettingPanel.tsx +++ b/packages/core/src/components/zhs/ExamSettingPanel.tsx @@ -1,30 +1,33 @@ import { defineComponent } from 'vue'; import { createWorkerSetting } from '..'; -import { store } from '../../store'; +import { useSettings } from '../../store'; + import { CommonWorkSettingPanel } from './CommonWorkSettingPanel'; export const ExamSettingPanel = defineComponent({ setup () { - const settings = store.setting.zhs.exam; + const settings = useSettings().zhs.exam; return () => (
- (settings.upload = e.target.value) - ) - }}> + (settings.upload = e.target.value) + ) + }}>
diff --git a/packages/core/src/components/zhs/StudySettingPanel.tsx b/packages/core/src/components/zhs/StudySettingPanel.tsx index 7e22d9d5..d0b0af34 100644 --- a/packages/core/src/components/zhs/StudySettingPanel.tsx +++ b/packages/core/src/components/zhs/StudySettingPanel.tsx @@ -1,11 +1,14 @@ import { defineComponent, ref } from 'vue'; + import { autoClose, fixedVideoProgress, switchPlaybackRate } from '../../script/zhs/study'; -import { store } from '../../store'; +import { useContext, useSettings } from '../../store'; import { Tooltip } from '../Tooltip'; export const StudySettingPanel = defineComponent({ setup () { - const settings = store.setting.zhs.video; + const settings = useSettings().zhs.video; + const ctx = useContext(); + showCloseDate(); /** 显示关闭时间 */ @@ -103,7 +106,7 @@ export const StudySettingPanel = defineComponent({ value={settings.volume} onInput={(e: any) => { settings.volume = e.target.valueAsNumber; - if (store.currentMedia) store.currentMedia.volume = e.target.valueAsNumber; + if (ctx.common.currentMedia) ctx.common.currentMedia.volume = e.target.valueAsNumber; }} > {Math.round(settings.volume * 100)}% diff --git a/packages/core/src/components/zhs/WorkSettingPanel.tsx b/packages/core/src/components/zhs/WorkSettingPanel.tsx index 0dcec14c..b31a7500 100644 --- a/packages/core/src/components/zhs/WorkSettingPanel.tsx +++ b/packages/core/src/components/zhs/WorkSettingPanel.tsx @@ -1,16 +1,31 @@ import { defineComponent } from 'vue'; -import { store } from '../../store'; +import { createWorkerSetting } from '..'; +import { useSettings } from '../../store'; + import { CommonWorkSettingPanel } from './CommonWorkSettingPanel'; export const WorkSettingPanel = defineComponent({ setup (props, { slots }) { - const settings = store.setting.zhs.work; + const settings = useSettings().zhs.work; return () => (
- + + (settings.upload = e.target.value) + ) + }}> +
diff --git a/packages/core/src/core/types.ts b/packages/core/src/core/types.ts index 4c6b3c0c..9350d37e 100644 --- a/packages/core/src/core/types.ts +++ b/packages/core/src/core/types.ts @@ -27,26 +27,40 @@ export interface OCSLocalStorage { } export interface OCSStore { + localStorage: OCSLocalStorage /** 版本号 */ VERSION: string setting: ScriptSettings - localStorage: OCSLocalStorage - /** 当前视频 */ - currentMedia: HTMLMediaElement | null - /** 超星 videojs 元素 */ - videojs: HTMLElement | null - /** 搜索结果存储 */ - workResults: WorkResult[] - /** 是否正在识别文字 */ - isRecognizing: boolean - /** 启动参数 */ - startOptions: StartOptions | undefined - /** 消息 */ - alerts: AlertType[] - /** - * 字体字典库 用于繁体字识别 - * author wyn665817 - * @see https://bbs.tampermonkey.net.cn/thread-2303-1-1.html - */ - fontMap: any + context: { + common: { + /** 当前视频 */ + currentMedia: HTMLMediaElement | null + /** 搜索结果存储 */ + workResults: WorkResult[] + /** 启动参数 */ + startOptions: StartOptions | undefined + /** 消息 */ + alerts: AlertType[] + }, + /** + * 各脚本预留存储字段 + */ + cx: { + /** 超星 videojs 元素 */ + videojs: HTMLElement | null + /** 是否正在识别文字 */ + isRecognizing: boolean + /** + * 字体字典库 用于繁体字识别 + * author wyn665817 + * @see https://bbs.tampermonkey.net.cn/thread-2303-1-1.html + */ + fontMap: any + }, + zhs: { + /** 是否正在识别文字 */ + isRecognizing: boolean + } + + } } diff --git a/packages/core/src/logger.ts b/packages/core/src/logger.ts index 550263b3..2ca4ddb1 100644 --- a/packages/core/src/logger.ts +++ b/packages/core/src/logger.ts @@ -1,4 +1,4 @@ -import { store } from './store'; +import { useStore } from './store'; export function loggerPrefix(level: 'info' | 'error' | 'warn' | 'debug') { const extra = level === 'error' ? '[错误]' : level === 'warn' ? '[警告]' : undefined; @@ -40,7 +40,8 @@ export function logger(level: 'info' | 'error' | 'warn' | 'debug', ...msg: any[] const type = typeof s; return type === 'function' ? '[Function]' : type === 'object' ? '[Object]' : type === 'undefined' ? '无' : s; }); - const logs = store.localStorage.logs; + const logs = useStore('localStorage').logs; + if (logs.length > 50) { logs.shift(); } diff --git a/packages/core/src/main.ts b/packages/core/src/main.ts index 492af98a..dad8dd3b 100644 --- a/packages/core/src/main.ts +++ b/packages/core/src/main.ts @@ -3,13 +3,13 @@ import { CommonScript } from './script/common'; import { CXScript } from './script/cx'; import { ZHSScript } from './script/zhs'; import { app, loaded, panel, start } from './start'; -import { store } from './store'; +import { getStore } from './store'; export * from './core/index'; /** * ocsjs */ -export { store, start, app, panel, loaded, message }; +export { getStore, start, app, panel, loaded, message }; // @ts-ignore vite.define export const VERSION = process.env._VERSION_; diff --git a/packages/core/src/script/cx/recognize.ts b/packages/core/src/script/cx/recognize.ts index 7a514f4f..968e55b2 100644 --- a/packages/core/src/script/cx/recognize.ts +++ b/packages/core/src/script/cx/recognize.ts @@ -1,18 +1,20 @@ import md5 from 'md5'; import { request } from '../../core/utils'; -import { logger, OCR, store } from '../../main'; +import { logger, OCR } from '../../main'; import CXAnalyses from './utils'; // @ts-ignore import Typr from 'typr.js'; +import { useContext } from '../../store'; /** * 繁体字识别-字典匹配 * @see 参考 https://bbs.tampermonkey.net.cn/thread-2303-1-1.html */ export async function mapRecognize() { + const { cx } = useContext(); // 顶层初始化 if (window === top) { - store.isRecognizing = false; + cx.isRecognizing = false; logger('debug', '正在加载字典库...'); // 预加载字体库 const res = await request('https://cdn.ocs.enncy.cn/resources/font/table.json', { @@ -20,12 +22,12 @@ export async function mapRecognize() { method: 'get', contentType: 'json' }); - store.fontMap = res; + cx.fontMap = res; logger('info', '字典库加载成功'); } else { /** 判断是否有繁体字 */ const fontFaceEl = Array.from(document.head.querySelectorAll('style')).find((style) => style.textContent?.includes('font-cxsecret')); - const fontMap = store.fontMap; + const fontMap = cx.fontMap; if (fontFaceEl) { // 解析font-cxsecret字体 const font = fontFaceEl.textContent?.match(/base64,([\w\W]+?)'/)?.[1]; @@ -70,9 +72,11 @@ export async function ocrRecognize() { workerPath: 'https://cdn.ocs.enncy.cn/resources/tesseract/worker.min.js' }); + const { cx } = useContext(); + // 顶层初始化 if (window === top) { - store.isRecognizing = false; + cx.isRecognizing = false; logger('debug', '加载文字识别功能, 如果是初始化请耐心等待..., 大约需要下载20mb的数据文件'); // 预加载 await ocr.load(); @@ -82,7 +86,7 @@ export async function ocrRecognize() { const fonts = CXAnalyses.getSecretFont(); if (fonts.length) { logger('info', '文字识别功能启动'); - store.isRecognizing = true; + cx.isRecognizing = true; // 加载 await ocr.load(); for (let i = 0; i < fonts.length; i++) { @@ -99,7 +103,7 @@ export async function ocrRecognize() { } } - store.isRecognizing = false; + cx.isRecognizing = false; logger('info', '文字识别完成'); } } diff --git a/packages/core/src/start.ts b/packages/core/src/start.ts index 7c4e8ca5..e23c7225 100644 --- a/packages/core/src/start.ts +++ b/packages/core/src/start.ts @@ -1,11 +1,10 @@ import { App as VueApp, createApp } from 'vue'; import App from './App.vue'; import { DefineScript } from './core/define.script'; -import { getCurrentRoutes, isInBrowser, onComplete, onInteractive } from './core/utils'; +import { getCurrentRoutes, onComplete, onInteractive } from './core/utils'; import { logger } from './logger'; import { definedScripts } from './main'; -import { createStore, setStore, store } from './store'; - +import { useContext, useStore } from './store'; export interface StartOptions { /** * 面板样式 url | string @@ -30,12 +29,13 @@ export let loaded = false; * 显示面板,检测是否存在需要运行的脚本,并执行 */ export function start(options?: StartOptions) { - // 初始化 store 变量 - initStore(); + // 执行脚本 + executeScripts(options?.scripts || definedScripts); // 加载面板 if (top === window) { - store.startOptions = options; + const ctx = useContext(); + ctx.common.startOptions = options; /** 绑定元素 */ app = createApp(App); @@ -63,29 +63,8 @@ export function start(options?: StartOptions) { shadowRoot.appendChild(panel!); document.body.appendChild(div); app.mount(panel); - logger('info', `OCS ${store.VERSION} 加载成功`); + logger('info', `OCS ${useStore('VERSION')} 加载成功`); } - } - - // 执行脚本 - executeScripts(options?.scripts || definedScripts); -} - -function initStore() { - // 环境检测 - if (isInBrowser()) { - if (typeof unsafeWindow !== 'undefined') { - setStore(createStore()); - } - - onComplete(() => { - if (typeof unsafeWindow !== 'undefined') { - // 统一转向顶层对象 - // eslint-disable-next-line no-undef - setStore(unsafeWindow.top?.OCS.store || store); - } else { - logger('warn', '为了确保功能正常使用, 请在油猴环境下运行 https://www.tampermonkey.net/'); - } }); } } diff --git a/packages/core/src/store.ts b/packages/core/src/store.ts index b886a093..d951b972 100644 --- a/packages/core/src/store.ts +++ b/packages/core/src/store.ts @@ -1,13 +1,25 @@ import defaultsDeep from 'lodash/defaultsDeep'; import { reactive, watch } from 'vue'; import { OCSLocalStorage, OCSStore } from './core/types'; -import { isInBrowser } from './core/utils'; +import { isInBrowser, onComplete } from './core/utils'; +import { logger } from './logger'; import { defaultOCSSetting } from './scripts'; /** * OCS 响应式存储对象, 在除油猴环境下的其他环境为 `{}` */ -export let store: OCSStore = {} as OCSStore; +let store: OCSStore = {} as OCSStore; + +// 环境检测 +if (isInBrowser()) { + if (typeof unsafeWindow !== 'undefined') { + setStore(createStore()); + } +} + +export function getStore() { + return store; +} export function setStore(val: OCSStore) { store = val; @@ -40,12 +52,22 @@ export function createStore() { // @ts-ignore VERSION: process.env._VERSION_, setting: _localStorage.setting, - currentMedia: null, - videojs: null, - workResults: [], - isRecognizing: false, - alerts: [], - fontMap: {} + context: { + common: { + startOptions: {}, + currentMedia: null, + workResults: [], + alerts: [] + }, + cx: { + videojs: null, + isRecognizing: false, + fontMap: {} + }, + zhs: { + isRecognizing: false + } + } }); /** 监听,并保存到本地 */ @@ -56,3 +78,49 @@ export function createStore() { return _store; } + +export function initStore(original: OCSStore) { + onComplete(() => { + if (typeof unsafeWindow !== 'undefined') { + try { + // 统一转向顶层对象 + // eslint-disable-next-line no-undef + setStore(original || store); + } catch (e) { + // @ts-ignore + console.log('store init error', e.message); + } + } else { + logger('warn', '为了确保功能正常使用, 请在油猴环境下运行 https://www.tampermonkey.net/'); + } + }); +} + +export function useStore(name: T): OCSStore[T] { + return store[name]; +} + +/** + * 获取公共上下文 + */ +export function useContext() { + return store.context; +} + +/** + * 获取设置 + */ +export function useSettings() { + // 历史遗留字段处理 + if (store.setting.answererWrappers.length && store.setting.common.answererWrappers.length === 0) { + store.setting.common.answererWrappers = store.setting.answererWrappers; + store.setting.answererWrappers = []; + } + // 历史遗留字段处理 + if (store.setting.cx.video && store.setting.cx.study === undefined) { + store.setting.cx.study = store.setting.cx.video; + store.setting.cx.video = undefined; + } + + return store.setting; +}