Skip to content

Commit

Permalink
关系图谱
Browse files Browse the repository at this point in the history
  • Loading branch information
MuiseDestiny committed Mar 14, 2023
1 parent 4fd2c58 commit ef01c0b
Show file tree
Hide file tree
Showing 14 changed files with 321 additions and 37 deletions.
1 change: 1 addition & 0 deletions addon/chrome/content/dist/assets/index.css

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions addon/chrome/content/dist/assets/index.js

Large diffs are not rendered by default.

8 changes: 8 additions & 0 deletions addon/chrome/content/dist/assets/pixi.js

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions addon/chrome/content/dist/assets/sim.js

Large diffs are not rendered by default.

34 changes: 34 additions & 0 deletions addon/chrome/content/dist/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<!DOCTYPE html>
<html lang="en" style="background-color: #ffffff;">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<script rel="text/javascript" async src="./assets/pixi.js"></script>
<script rel="text/javascript" async src="./assets/sim.js"></script>
<script rel="text/javascript" async src="./assets/index.js"></script>
<title>Graph View</title>
<link rel="stylesheet" href="./assets/index.css">
</head>
<body>
<div id="app">
</div>
</body>
<style>
#app{
width: 100%;
height: 100%;
padding: 0;
overflow: hidden;
}
* {
margin: 0;
padding: 0;
}
.graph-view-container {
height: 100%;
}
#graph-view {
max-height: 400px;
}
</style>
</html>
1 change: 1 addition & 0 deletions addon/chrome/content/icons/graph-view.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 4 additions & 2 deletions addon/prefs.js
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,12 @@ pref("extensions.zotero.__addonRef__.nestedTags.sortord", "0");

pref("extensions.zotero.__addonRef__.GPT.secretKey", "");


pref("extensions.zotero.__addonRef__.storage.in", "note");
pref("extensions.zotero.__addonRef__.storage.filename", "");

pref("extensions.zotero.__addonRef__.easyscholar.username", "");
pref("extensions.zotero.__addonRef__.easyscholar.password", "");
// pref("extensions.zotero.__addonRef__.easyscholar.username", "");
// pref("extensions.zotero.__addonRef__.easyscholar.password", "");



Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "zotero-style",
"version": "2.4.3",
"version": "2.4.4",
"description": "让你的Zotero看起来更有趣",
"config": {
"addonName": "Zotero Style",
Expand Down
15 changes: 10 additions & 5 deletions src/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import Events from "./modules/events";
import AddonItem from "./modules/item";
import { registerPrefsScripts, registerPrefs } from "./modules/prefs";
import LocalStorage from "./modules/localStorage";
import GraphView from "./modules/graphView";

async function onStartup() {
registerPrefs();
Expand Down Expand Up @@ -32,7 +33,7 @@ async function onStartup() {
Zotero.uiReadyPromise,
]);
initLocale();

// 不争不抢先加载
await Zotero.Promise.delay(1000)

Expand All @@ -52,18 +53,20 @@ async function onStartup() {
Zotero.Prefs.get(`${config.addonRef}.storage.filename`) as string
)
await storage.lock;
} else {
return
}
console.log(storage)
ztoolkit.log(storage)

const events = new Events(storage)
events.onInit()

const views = new Views(storage)
Zotero.ZoteroStyle.data.views = views

await (new GraphView()).init()
const tasks = [
views.initTags(),
views.createGraphView(),
// views.createGraphView(),
views.renderTitleColumn(),
views.createTagsColumn(),
views.createTextTagsColumn(),
Expand All @@ -78,14 +81,16 @@ async function onStartup() {
try {
await Promise.all(tasks);
} catch (e) {
console.log("ERROR", e)
ztoolkit.log("ERROR", e)
}
await views.registerSwitchColumnsViewUI();
try {
ZoteroPane.itemsView.tree._columns._updateVirtualizedTable()
ztoolkit.ItemTree.refresh()
} catch { }
await views.registerCommands()


}

function onShutdown(): void {
Expand Down
209 changes: 209 additions & 0 deletions src/modules/graphView.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,209 @@
import { config } from "../../package.json";

import Views from "./views";
const d3 = require("./d3")

export default class GraphView {
private popupWin: any;
private frame!: HTMLIFrameElement;
private container?: HTMLDivElement;
constructor() {
}

public async init() {
await this.createContainer()
this.registerButton()
}

private registerButton() {
console.log("registerButton is called")
const node = document.querySelector("#zotero-tb-advanced-search")
console.log(node)
let newNode = node?.cloneNode(true) as XUL.ToolBarButton
newNode.setAttribute("id", "zotero-style-show-hide-graph-view")
newNode.setAttribute("tooltiptext", "Hi, I am your Style.")
newNode.setAttribute("command", "")
newNode.setAttribute("oncommand", "")
newNode.addEventListener("click", () => {
let node = this.container
if (!node) { return }
if (node.style.display == "none") {
node.style.display = ""
Zotero.Prefs.set(`${config.addonRef}.graphView.enable`, true)
} else {
node.style.display = "none"
Zotero.Prefs.set(`${config.addonRef}.graphView.enable`, false)
}
})
newNode.style.listStyleImage = `url(chrome:https://${config.addonRef}/content/icons/favicon.png)`
document.querySelector("#zotero-items-toolbar")?.insertBefore(newNode, node?.nextElementSibling!)
console.log(document.querySelector("#zotero-items-toolbar"))
}

public async buildGraphData(item: Zotero.Item) {
}

private async createContainer() {
document.querySelectorAll("#graph").forEach(e => e.remove());
document.querySelectorAll(".resizer").forEach(e => e.remove())
while (!document.querySelector("#item-tree-main-default")) {
await Zotero.Promise.delay(100)
}
const mainNode = document.querySelector("#item-tree-main-default")!
// 图形容器
const container = ztoolkit.UI.createElement(document, "div", {
id: "graph-view",
styles: {
width: "100%",
// height: "50%",
minHeight: "400px",
borderTop: "2px solid #cecece",
// display: Zotero.Prefs.get(`${config.addonRef}.graphView.enable`) ? "" : "none"
// display: ""
}
})
ztoolkit.UI.appendElement({
tag: "div",
id: "app",
children: [
{
tag: "div",
id: "graph-view"
}
]
}, container)
const frame = this.frame = ztoolkit.UI.createElement(document, "iframe", { namespace: "html" }) as HTMLIFrameElement
frame.setAttribute("src", `chrome:https://${config.addonRef}/content/dist/index.html`)
frame.style.height = "500px"
frame.style.border = "none"
frame.style.outline = "none"
frame.style.width = "100%"
frame.style.height = "100%"
frame.style.overflow = "hidden"
frame.style.backgroundColor = "#ffffff"
container.append(frame)
mainNode.append(container)
this.container = container
await this.initIFrame(frame)
}

private getItemDisplayText(item: _ZoteroItem) {
let authors = item.getCreators()
if (authors.length == 0) { return item.getField("title") }
let author
if (/[A-Za-z]/.test(authors[0].lastName)) {
author = item.firstCreator.replace("和", "and").replace("等", "et al.")
} else {
author = item.firstCreator.replace("and", "和").replace("et al.", "等")
}
const year = item.getField("year")
return `${author}, ${year}`
}

private getGraph(items: _ZoteroItem[]) {
let nodes: { [key: string]: any } = {}
let graph: { [key: string]: any } = { nodes }
items.forEach((item, i) => {
let id = item.id
nodes[id] = { links: {}, type: "item"}
const relatedKeys = item.relatedItems
items
.forEach((_item, _i) => {
if (_i == i) { return }
if (relatedKeys.indexOf(_item.key) != -1) {
nodes[id].links[_item.id] = true
}
})
})
return graph
}

private async initIFrame(frame: HTMLIFrameElement) {
// 等待js执行结束
// @ts-ignore
while (!frame.contentWindow!.renderer) {
await Zotero.Promise.delay(100)
}
// @ts-ignore
const renderer = frame.contentWindow!.renderer
/**
* 点击文献直接定位
*/
let userSelect = true
ZoteroPane.itemsView.onSelect.addListener(() => {
if (!userSelect) { userSelect = true; return }
let items = ZoteroPane.getSelectedItems()
if (items.length == 1) {
const item = items[0]
const itemID = item.id
console.log(itemID, renderer.nodes)
const node = renderer.nodes.find((node: any) => Number(node.id) == itemID)
renderer.highlightNode = node
if (!node) { return }
const f = window.devicePixelRatio
const scale = 2
const canvas = renderer.interactiveEl
const X = (f * canvas.width / 2 - node.x * scale);
const Y = (f * canvas.height / 2 - node.y * scale);
renderer.zoomTo(scale / 2);
renderer.setPan(X, Y);
renderer.setScale(scale);
renderer.changed()
}
})
/**
* 点击节点定位文献
*/
renderer.onNodeClick = (e: any, id: string, type: number) => {
userSelect = false
ZoteroPane.itemsView.selectItem(Number(id))
}
/**
* 双击关系图谱空白分析当前图谱
*/
frame.addEventListener("dblclick", () => {
// 分析链接
this.setData(renderer, this.getGraph(ZoteroPane.getSortedItems()))
})

/**
* 窗口调整canvas调整
*/
frame.addEventListener("resize", () => {
// renderer.interactiveEl.style.height = window.getComputedStyle(container).height
renderer.onResize()
})

/**
* 加载一个默认图谱
*/
const graph = {
nodes: {
Sun: { links: { Earth: true, Moon: true } },
Earth: { links: { Sun: true, Moon: true, Zotero: true } },
Moon: { links: { Earth: true, Moon: true } },
Zotero: { links: { You: true } },
You: { links: {} },
"我一直在等你": { links: {} }
}
}
this.setData(renderer, graph)
}

private setData(renderer: any, graph: any) {
renderer.setData(graph)
const that = this
renderer.nodes.forEach((node: any) => {
if (node._getDisplayText) { return }
node._getDisplayText = node.getDisplayText
node.getDisplayText = function () {
if (this.type == "item") {
return that.getItemDisplayText(Zotero.Items.get(Number(this.id)))
}
return this.id
}
})
renderer.changed()
renderer.onResize()
}
}
43 changes: 28 additions & 15 deletions src/modules/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,25 +17,38 @@ const utils = {
}
if (data) { return data }
// 开启一个异步更新影响因子
// 下面代码对es官方影响较大
// window.setTimeout(async () => {
// const username = Zotero.Prefs.get(`${config.addonRef}.easyscholar.username`) as string
// const password = Zotero.Prefs.get(`${config.addonRef}.easyscholar.password`) as string
// if (username.length && password.length) {
// await this.requests.get(
// `https://easyscholar.cc/login?userName=${username}&password=${password}`
// )
// }
// const response = await this.requests.post(
// "https://easyscholar.cc/extension/listPublicationRank4",
// {
// publicationName: { "0": publicationTitle }
// }
// )
// ztoolkit.log(response)
// if (response && response.data) {
// let data = response.data.publicationRankList[0]
// if (data) {
// delete data.tempID
// await this.localStorage.set(item, key, data)
// }
// }
// })
window.setTimeout(async () => {
const username = Zotero.Prefs.get(`${config.addonRef}.easyscholar.username`) as string
const password = Zotero.Prefs.get(`${config.addonRef}.easyscholar.password`) as string
if (username.length && password.length) {
await this.requests.get(
`https://easyscholar.cc/login?userName=${username}&password=${password}`
)
}
const response = await this.requests.post(
"https://easyscholar.cc/extension/listPublicationRank4",
{
publicationName: { "0": publicationTitle }
}
const response = await this.requests.get(
`https://easyscholar.cc/homeController/getQueryTable.ajax?sourceName=${publicationTitle}`,
)
console.log(response)
ztoolkit.log(response)
if (response && response.data) {
let data = response.data.publicationRankList[0]
let data = response.data[0]
if (data) {
delete data.tempID
await this.localStorage.set(item, key, data)
}
}
Expand Down
Loading

0 comments on commit ef01c0b

Please sign in to comment.