}
},
+
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 (
<>
-
- {
- 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) => (
- - {aw.name}
- ))}
-
- >
- )
- }}
- >
- ✅
-
- )
- : (
-
- ❌
-
- )}
-
-
-
- {
- 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) => (
+ - {aw.name}
+ ))}
+
+ >
+ )
+ }}
+ >
+ ✅
+
+ )
+ : (
+
+ ❌
+
+ )}
+
+
+
+ {
+ 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;
+}