diff --git a/cc-inspector/src/scripts/inject-view/app.vue b/cc-inspector/src/scripts/inject-view/app.vue new file mode 100644 index 0000000..9ed276a --- /dev/null +++ b/cc-inspector/src/scripts/inject-view/app.vue @@ -0,0 +1,210 @@ + + + + diff --git a/cc-inspector/src/scripts/inject-view/banner.vue b/cc-inspector/src/scripts/inject-view/banner.vue new file mode 100644 index 0000000..f28fc8a --- /dev/null +++ b/cc-inspector/src/scripts/inject-view/banner.vue @@ -0,0 +1,92 @@ + + + + diff --git a/cc-inspector/src/scripts/inject-view/const.ts b/cc-inspector/src/scripts/inject-view/const.ts new file mode 100644 index 0000000..bec0b9e --- /dev/null +++ b/cc-inspector/src/scripts/inject-view/const.ts @@ -0,0 +1,5 @@ +import { TinyEmitter } from "tiny-emitter"; +export const Msg = { + ChangeAd: "ChangeAd", +}; +export const emitter = new TinyEmitter(); diff --git a/cc-inspector/src/scripts/inject-view/github.ts b/cc-inspector/src/scripts/inject-view/github.ts new file mode 100644 index 0000000..9cd0e6e --- /dev/null +++ b/cc-inspector/src/scripts/inject-view/github.ts @@ -0,0 +1,146 @@ +export interface MirrorInfo { + /** + * 请求的url + */ + name: string; + /** + * 上次请求成功的时间 + */ + time: number; +} +class Config { + private key = "cc-inspector-ad-config"; + private data: MirrorInfo[] = []; + constructor() { + const cfg = localStorage.getItem(this.key); + if (cfg) { + try { + const ret = JSON.parse(cfg) as MirrorInfo[]; + if (ret) { + ret.forEach((el) => { + this.data.push({ name: el.name, time: el.time }); + }); + } + } catch {} + } + } + save(name: string, time: number) { + const ret = this.data.find((el) => el.name === name); + if (ret) { + ret.time = time; + } else { + this.data.push({ name: name, time: time } as MirrorInfo); + } + localStorage.setItem(this.key, JSON.stringify(this.data)); + } + getTime(url: string) { + const ret = this.data.find((el) => el.name === url); + if (ret) { + return ret.time; + } + return 0; + } +} +export class GithubMirror { + owner: string = "tidys"; + repo: string = "cc-inspector-ad"; + branch: string = "main"; + /** + * 上次请求成功的时间 + */ + time: number = 0; + /** + * 镜像的名字 + */ + name: string = ""; + private calcUrl: Function; + constructor(name: string, cb) { + this.name = name; + this.time = cfg.getTime(name); + this.calcUrl = cb; + } + private getUrl(file: string) { + if (this.calcUrl) { + return this.calcUrl(this.owner, this.repo, this.branch, file); + } else { + return ""; + } + } + public async getData(file: string) { + const url = this.getUrl(file); + if (url) { + const data = await this.reqFecth(url); + return data; + } + return null; + } + private reqFecth(url: string): Promise { + return new Promise((resolve, reject) => { + console.log(`req ad: ${url}`); + fetch(url) + .then((res) => { + return res.json(); + }) + .then((data) => { + resolve(data); + }) + .catch((e) => { + resolve(null); + }); + }); + } +} +const cfg = new Config(); +export class GithubMirrorMgr { + mirrors: GithubMirror[] = []; + constructor() { + // 使用国内gitub镜像来达到下载远程配置文件的目的 + this.mirrors.push( + new GithubMirror("github", (owner: string, repo: string, branch: string, file: string) => { + return `https://raw.githubusercontent.com/${owner}/${repo}/refs/heads/${branch}/${file}`; + }) + ); + this.mirrors.push( + new GithubMirror("bgithub", (owner: string, repo: string, branch: string, file: string) => { + return `https://raw.bgithub.xyz/${owner}/${repo}/refs/heads/${branch}/${file}`; + }) + ); + this.mirrors.push( + new GithubMirror("kkgithub", (owner: string, repo: string, branch: string, file: string) => { + return `https://raw.kkgithub.com/${owner}/${repo}/refs/heads/${branch}/${file}`; + }) + ); + + this.mirrors.push( + new GithubMirror("xiaohei", (owner: string, repo: string, branch: string, file: string) => { + return `https://raw-githubusercontent.xiaohei.me/${owner}/${repo}/refs/heads/${branch}/${file}`; + }) + ); + + this.mirrors.push( + new GithubMirror("gh-proxy", (owner: string, repo: string, branch: string, file: string) => { + return `https://gh-proxy.com/raw.githubusercontent.com/${owner}/${repo}/refs/heads/${branch}/${file}`; + }) + ); + this.mirrors.push( + new GithubMirror("ghproxy", (owner: string, repo: string, branch: string, file: string) => { + return `https://ghproxy.net/https://raw.githubusercontent.com/${owner}/${repo}/refs/heads/${branch}/${file}`; + }) + ); + } + async getData(file: string): Promise { + this.mirrors.sort((a, b) => b.time - a.time); + for (let i = 0; i < this.mirrors.length; i++) { + const mirror = this.mirrors[i]; + const data = await mirror.getData(file); + if (data) { + const time = new Date().getTime(); + mirror.time = time; + cfg.save(mirror.name, time); + return data; + } + } + return null; + } +} +export const githubMirrorMgr = new GithubMirrorMgr(); diff --git a/cc-inspector/src/scripts/inject-view/loader.ts b/cc-inspector/src/scripts/inject-view/loader.ts new file mode 100644 index 0000000..6c29fa6 --- /dev/null +++ b/cc-inspector/src/scripts/inject-view/loader.ts @@ -0,0 +1,90 @@ +import { githubMirrorMgr } from "./github"; + +export class AdItem { + /** + * 广告的名字 + */ + name: string = ""; + /** + * 鼠标悬浮提示 + */ + tip: string = ""; + /** + * 插件的试用地址 + */ + try: string = ""; + /** + * 广告的store购买链接 + */ + store: string = ""; + /** + * 广告的展示时间,单位s + */ + duration: number = 0; + /** + * 广告的有效性 + */ + valid: boolean = true; + /** + * 背景图 + */ + img: string = ""; + parse(data: AdItem) { + this.name = data.name; + this.store = data.store || ""; + this.try = data.try || ""; + this.tip = data.tip || ""; + this.duration = data.duration || 0; + this.valid = !!data.valid; + this.img = data.img || ""; + return this; + } +} +export class AdData { + desc: string = ""; + version: string = ""; + /** + * 是否启用广告 + */ + valid: boolean = false; + /** + * 多少分钟不再展示,单位分钟,默认10分钟 + */ + showDuration: number = 10; + /** + * 底部广告多少秒滚动一次 + */ + scrollDuration: number = 3; + data: Array = []; + parse(data: AdData) { + this.desc = data.desc; + this.version = data.version; + this.valid = !!data.valid; + this.showDuration = data.showDuration || 10; + this.scrollDuration = data.scrollDuration || 3; + if (data.data) { + data.data.forEach((el) => { + const item = new AdItem().parse(el); + if (!item.duration) { + console.warn(`add failed, ad.duration is ${item.duration}, ${JSON.stringify(item)}`); + return; + } + if (!item.valid) { + console.warn(`add failed, ad is invalid, ${JSON.stringify(item)}`); + return; + } + this.data.push(item); + }); + } + } +} + +export async function getAdData(): Promise { + const data = await githubMirrorMgr.getData("ad.json"); + if (data) { + const ad = new AdData(); + ad.parse(data as AdData); + return ad; + } + return null; +} diff --git a/cc-inspector/src/scripts/inject-view/web-test.ts b/cc-inspector/src/scripts/inject-view/web-test.ts new file mode 100644 index 0000000..4a49816 --- /dev/null +++ b/cc-inspector/src/scripts/inject-view/web-test.ts @@ -0,0 +1,18 @@ +/** + * 这个是web测试inject_view的入口,实际chrome插件不应该走这个界面 + */ +import ccui from "@xuyanfeng/cc-ui"; +import "@xuyanfeng/cc-ui/dist/ccui.css"; +import "@xuyanfeng/cc-ui/iconfont/iconfont.css"; +import CCP from "cc-plugin/src/ccp/entry-render"; +import { createApp } from "vue"; +import pluginConfig from "../../../cc-plugin.config"; +import App from "./app.vue"; + +export default CCP.init(pluginConfig, { + ready: function (rootElement: any, args: any) { + const app = createApp(App); + app.use(ccui); + app.mount(rootElement); + }, +});