Skip to content

Commit

Permalink
量表附加操作
Browse files Browse the repository at this point in the history
  • Loading branch information
zzlb0224 committed Sep 19, 2024
1 parent b2d0f29 commit a992d9d
Show file tree
Hide file tree
Showing 4 changed files with 153 additions and 56 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,9 @@

### 第七个功能 添加量表操作

把量表的固定操作添加进来。
目前做的是comment记录的方式。
应该要改成双链的方式。
![量表操作](doc/7量表操作.png)

### 建议的固定标签配置
Expand Down
114 changes: 60 additions & 54 deletions src/component/PopupRoot.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ export function PopupRoot({
// item.isCollection
const _annotationManager = reader._annotationManager;
const _keyboardManager = reader._keyboardManager;
const annotations = item.getAnnotations();

//定义状态
// ztoolkit.log("params", params);
Expand Down Expand Up @@ -133,6 +134,7 @@ export function PopupRoot({
const [selectionPopupSize, setSelectionPopupSize] = useState({ width: 0, height: 0 });
const [configName, setConfigName] = useState(getPref("configName"));
const [bScale, setBScale] = useState(getPref("bScale") as boolean)
const [exAction, setExAction] = useState(getPref("exAction") as string)
const [sScale, setSScale] = useState(getPref("sScale"))
const [sScaleType, setSScaleType] = useState(getPref("sScaleType") as string)
const [sScaleItem, setSScaleItem] = useState("")
Expand Down Expand Up @@ -405,6 +407,7 @@ export function PopupRoot({
const clickMeButtonRef = React.useRef<HTMLElement | null>(null);

const vars = [
exAction,
bScale,
sScale,
sScaleType,
Expand Down Expand Up @@ -1085,63 +1088,66 @@ export function PopupRoot({
}}
>
{!params.ids && (<>
{/* {item.getAnnotations().map(a => a.getTags().map(b => b.tag).join(","))} */}
{item.getAnnotations().some(s => s.hasTag("量表")) && (<div>
<div style={{ display: "flex", flexWrap: "wrap" }}> <button className='toolbar-button' style={{ width: "unset", margin: "2px" }} onClick={() => {
const nbScale = !bScale;
setBScale(nbScale)
setPref("bScale", nbScale)
}
}>量表操作</button>
<button className='toolbar-button' style={{ width: "unset", margin: "2px" }} onClick={() => {
const nbScale = !bScale;
setBScale(nbScale)
setPref("bScale", nbScale)

<div style={{ display: "flex", flexWrap: "wrap" }}>
{["量表", "元"].filter(f => annotations.some(s => s.hasTag(f))).map(action => (<button className='toolbar-button' style={{ width: "unset", margin: "2px" }} onClick={() => {
if (exAction == action) {
setExAction("")
setPref("exAction", "")
}
else {
setExAction(action)
setPref("exAction", action)
}
}>元操作</button></div>
{bScale && (<>
<div style={{ display: "flex", flexWrap: "wrap" }}>
{sScaleType ? (
<button className='toolbar-button' style={{ width: "unset" }} onClick={() => {
setSScaleType("")
}}>类型:{sScaleType}</button>
) : (["item", "CR", "CA", "AVE", "factorLoading", "reference", "description"].map(a => (<button className='toolbar-button' style={{ width: "unset", margin: "2px" }} onClick={() => {
setSScaleType(a)
}
}>{exAction == action ? `【${action}操作】` : action}</button>))}

</div>

{exAction == "量表" && (<>
<div style={{ display: "flex", flexWrap: "wrap" }}>
{sScaleType ? (
<button className='toolbar-button' style={{ width: "unset" }} onClick={() => {
setSScaleType("")
}}>类型:{sScaleType}</button>
) : (["item", "CR", "CA", "AVE", "factorLoading", "reference", "description"].map(a => (<button className='toolbar-button' style={{ width: "unset", margin: "2px" }} onClick={() => {
setSScaleType(a)
setPref("sScaleType", a)
}}>{a}</button>)))}
</div>
<div>
{sScaleType && (sScale ? (<button className='toolbar-button' style={{ width: "unset" }} onClick={() => {
setSScale("")
}}>量表:{sScale}</button>) : (item.getAnnotations().filter(f => f.hasTag("量表")).map(a =>
(<button className='toolbar-button' style={{ width: "unset" }} onClick={() => {
setSScale(a.annotationText);
setPref("sScale", a.annotationText)
}}>{a.annotationText}</button>)
)
))}
</div>
<div>
{sScaleType == "factorLoading" && sScale && (sScaleItem ? (<button className='toolbar-button' style={{ width: "unset" }} onClick={() => {
setSScaleItem("")
}}>量表item:{sScaleItem}</button>) : (item.getAnnotations().filter(f => f.hasTag("量表item") && f.annotationComment.includes(`*${sScale}*`)).map(a =>
(<button className='toolbar-button' style={{ width: "unset" }} onClick={() => {
setSScaleItem(a.annotationText);
}}>{a.annotationText}</button>)
)
))}
</div>
<div>{sScaleType != "" && sScale != "" && (sScaleType != "factor loading" || sScaleItem != "") && (<div style={{ display: "flex", flexWrap: "wrap" }}>
{["item", "CR", "CA", "AVE", "factorLoading", "reference", "description"]//.filter(f => f != sScaleType)
.map(a => (<button className='toolbar-button' style={{ width: "unset", margin: "2px" }} onClick={() => {
scaleAddAnnotation();
setPref("sScaleType", a)
}}>{a}</button>)))}
</div>
<div>
{sScaleType && (sScale ? (<button className='toolbar-button' style={{ width: "unset" }} onClick={() => {
setSScale("")
}}>量表:{sScale}</button>) : (item.getAnnotations().filter(f => f.hasTag("量表")).map(a =>
(<button className='toolbar-button' style={{ width: "unset" }} onClick={() => {
setSScale(a.annotationText);
setPref("sScale", a.annotationText)
}}>{a.annotationText}</button>)
)
))}
</div>
<div>
{sScaleType == "factorLoading" && sScale && (sScaleItem ? (<button className='toolbar-button' style={{ width: "unset" }} onClick={() => {
setSScaleItem("")
}}>量表item:{sScaleItem}</button>) : (item.getAnnotations().filter(f => f.hasTag("量表item") && f.annotationComment.includes(`*${sScale}*`)).map(a =>
(<button className='toolbar-button' style={{ width: "unset" }} onClick={() => {
setSScaleItem(a.annotationText);
}}>{a.annotationText}</button>)
)
))}
</div>
<div>{sScaleType != "" && sScale != "" && (sScaleType != "factor loading" || sScaleItem != "") && (<div style={{ display: "flex", flexWrap: "wrap" }}>
{["item", "CR", "CA", "AVE", "factorLoading", "reference", "description"]//.filter(f => f != sScaleType)
.map(a => (<button className='toolbar-button' style={{ width: "unset", margin: "2px" }} onClick={() => {
scaleAddAnnotation();
setPref("sScaleType", a)
}}>{sScaleType == a ? `【${a}】` : a}</button>))}
</div>)}</div>
}}>{sScaleType == a ? `【${a}】` : a}</button>))}
</div>)}</div>


</>)}


</>)}
</div>)}
</>)}
<div
style={{
Expand Down Expand Up @@ -1552,7 +1558,7 @@ export function PopupRoot({
</span>
</div>
</div>
</div >
</div>
),
vars,
);
Expand Down
81 changes: 81 additions & 0 deletions src/modules/AnnotationsToNote.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -940,6 +940,87 @@ export async function exportNoteByType(type: _ZoteroTypes.Annotations.Annotation
},
});
}
export async function exportScaleCsv(collectionOrItem: "collection" | "item") {

const pw = new ztoolkit.ProgressWindow("")
// const ans2 = await convertHtml(ans, note, pw)

const sData = await getScaleData(collectionOrItem);
const data = sData.map(a => [a.authorYear ? `${a.authorYear?.author || " "}(${a.authorYear?.year || " "})` : " ", `${a.authorYear?.title || " "}`, `${a.variable?.text || " "}`, `${a.scaleItem?.text || " "}`, `${a.scaleItem?.comment || " "}`, `${a.factorLoading?.text || " "}`, `${a.reference?.text || " "}`, `${a.CR?.text || " "}`, `${a.CA?.text || " "}`, `${a.AVE?.text || " "}`, `${a.description?.text || " "}`, `${a.description?.comment || " "}`]);

const csv = [];
const separator = ",";
for (let i = 0; i < data.length; i++) {
const row = [], cols = data[i];
for (let j = 0; j < cols.length; j++) {
let data = cols[j]?.replace(/(\r\n|\n|\r)/gm, '').replace(/(\s\s)/gm, ' ') || ""
data = data.replace(/"/g, '""');
row.push('"' + data + '"');
}
csv.push(row.join(separator));
}
const csv_string = csv.join('\n');
const classes = Components.classes as any
const nsIFilePicker = Components.interfaces.nsIFilePicker;
const fp = classes["@mozilla.org/filepicker;1"].createInstance(nsIFilePicker);

fp.defaultString = "EX - " + ZoteroPane.getSelectedCollection()?.name + ".csv";
fp.init(window, "Save to file", nsIFilePicker.modeSave);
fp.appendFilter("CSV (*.csv; *.txt)", "*.csv; *.txt");
fp.defaultExtension = "csv";

fp.open(function () {
const outputStream = classes["@mozilla.org/network/file-output-stream;1"].createInstance(Components.interfaces.nsIFileOutputStream);
outputStream.init(fp.file, 0x04 | 0x08 | 0x20, 420, 0);
const converter = classes["@mozilla.org/intl/converter-output-stream;1"].createInstance(Components.interfaces.nsIConverterOutputStream);
converter.init(outputStream, "gb2312", 0, 0);
converter.writeString(csv_string);
converter.close();
outputStream.close();
});

}
async function getScaleData(collectionOrItem: "collection" | "item") {
const items = await getSelectedItems(collectionOrItem);
const ans = getAllAnnotations(items).filter(f => f.annotationTags.includes("量表"));
const pw = new ztoolkit.ProgressWindow("")
const ans2group = groupBy(ans, a => a.item.key)
const title = `量表来自${ans2group.length}个条目`;

const authorYear = "authorYear";
const variable = "variable";
const AVE = "AVE";
const CA = "CA";
const CR = "CR";
const reference = "reference";
const scaleItem = "item";
const factorLoading = "factorLoading";
const description = "description";
const data = []
// data.push({ authorYear, variable, factorLoading, scaleItem, reference, CR, CA, AVE, description });
for (const item of ans2group) {
const vars = item.values.filter(f => f.tags.some(s => s.tag == "量表"))
const authorYear = item.values[0]
const getAns = (type: "AVE" | "CR" | "CA" | "reference" | "item" | "factorLoading" | "description" | "itemDescription", text: string = "**") => item.values.filter(f => f.tags.some(s => s.tag == "量表" + type) && f.comment.includes(`*${text}*`))
for (const scale of vars) {
const variable = scale;
const description = getAns("description", scale.text)?.[0]
const AVE = getAns("AVE", scale.text)?.[0];
const CA = getAns("CA", scale.text)?.[0]
const CR = getAns("CR", scale.text)?.[0]
const reference = getAns("reference", scale.text)?.[0]
data.push({ authorYear, variable, reference, CR, CA, AVE, description });
const scaleItems = item.values.filter(f => f.tags.some(s => s.tag == "量表item") && f.comment.includes(`*${scale.text}*`))
for (const scaleItem1 of scaleItems) {
const scaleItem = scaleItem1;
const description = getAns("itemDescription", scaleItem1.text)?.[0];
const factorLoading = getAns("factorLoading", scaleItem1.text)?.[0];
data.push({ factorLoading, scaleItem, description });
}
}
}
return data
}
export async function exportScaleNote(collectionOrItem: "collection" | "item") {
const items = await getSelectedItems(collectionOrItem);
const ans = getAllAnnotations(items).filter(f => f.annotationTags.includes("量表"));
Expand Down
11 changes: 9 additions & 2 deletions src/modules/menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { sortBy, sortValuesLengthKeyAsc } from "../utils/sort";
import { Tab } from "../utils/tab";
import { uniqueBy } from "../utils/uniqueBy";
import { ReTest, clearChild, createDialog, getChildCollections, isDebug, memFixedColor, stopPropagation } from "../utils/zzlb";
import { createAnnotationMatrix, createChooseTagsDiv, createSearchAnnContent, exportNote, exportScaleNote, getAllAnnotations } from "./AnnotationsToNote";
import { createAnnotationMatrix, createChooseTagsDiv, createSearchAnnContent, exportNote, exportScaleCsv, exportScaleNote, getAllAnnotations } from "./AnnotationsToNote";
import { copyAnnotations, mergePdfs, pasteAnnotations } from "./BackupAnnotation";
import { DDDTagClear, DDDTagRemove, DDDTagSet } from "./DDD";
import { getCiteItemHtml } from "./getCitationItem";
Expand Down Expand Up @@ -317,11 +317,18 @@ function buildMenu(collectionOrItem: "collection" | "item") {
tag: "menuseparator",
}, {
tag: "menuitem",
label: "导出量表格式(测试中)",
label: "导出量表格式Note(测试中)",
icon: iconBaseUrl + "favicon.png",
commandListener: async (ev: Event) => {
exportScaleNote(collectionOrItem);
},
}, {
tag: "menuitem",
label: "导出量表格式CSV(测试中)",
icon: iconBaseUrl + "favicon.png",
commandListener: async (ev: Event) => {
exportScaleCsv(collectionOrItem);
},
},
{
tag: "menuseparator",
Expand Down

0 comments on commit a992d9d

Please sign in to comment.