User:Saimmx/SATG.js
外观
注意:保存之后,你必须清除浏览器缓存才能看到做出的更改。Google Chrome、Firefox、Microsoft Edge及Safari:按住⇧ Shift键并单击工具栏的“刷新”按钮。参阅Help:绕过浏览器缓存以获取更多帮助。
//Written by Saimmx
//Date: 2026-03-09
//<nowiki>
mw.util.addPortlet( 'p-codex', 'Codex小工具', '#p-interaction' );
const dialogTrigger = mw.util.addPortletLink( 'p-tb', '#', '可靠來源評估產生器', 'p-codex-dialog' );
mw.loader.using( '@wikimedia/codex' ).then( function( require ) {
const Vue = require( 'vue' );
const Codex = require( '@wikimedia/codex' );
const mountPoint = document.body.appendChild( document.createElement( 'div' ) );
/*
* https://vuejs.org/api/options-misc#components
* https://doc.wikimedia.org/codex/latest/components/overview.html
* cdx-accordion => CdxAccordion
* cdx-combobox => CdxCombobox
* 寫起來有點北爛就是了
*/
const VueComponentComponents = {
CdxButton: Codex.CdxButton,
CdxDialog: Codex.CdxDialog,
CdxLabel: Codex.CdxLabel,
CdxTextInput: Codex.CdxTextInput,
CdxSelect: Codex.CdxSelect,
}
/*
* Because "No .vue single-file component support; you must define components in plain .js files", sooo...
* @see: [https://www.mediawiki.org/wiki/Codex/en#Using_Codex_in_userscripts Codex]
*/
const VueComponentTemplate = `<cdx-dialog
v-model:open="showDialog"
title="可靠來源評估產生器"
close-button-label="關閉"
:use-close-button="true"
:default-action="defaultAction"
@default="open = false"
>
<div class="satg-app">
<p>
以下程式為評估<a :href="anchorLink.GNG" target="_blank">{{ anchorTitle.GNG }}</a>來源的產生程式。
靈感取自<a :href="anchorLink.EGardnerCodex" target="_blank">{{ anchorTitle.EGardnerCodex }}</a>
與<a :href="anchorLink.DannyS712SATG" target="_blank">{{ anchorTitle.DannyS712SATG }}</a>。
</p>
<hr />
<div class="satg-app-source">
<cdx-label>這個來源是哪裡?</cdx-label>
<cdx-text-input v-model="sourceAccess.source" aria-label="來源說明"></cdx-text-input>
</div>
<div class="satg-app-reliable">
<cdx-label>來源是否可靠?</cdx-label>
<cdx-select v-model:selected="sourceAccess.rel" :menu-items="accessOptions" aria-label="來源可靠評價" default-label="請評價" />
<cdx-label>為什麼?</cdx-label>
<cdx-text-input v-model="sourceAccess.rel_just" aria-label="來源可靠理由"></cdx-text-input>
</div>
<div class="satg-app-coverage">
<cdx-label>來源是否有效介绍?</cdx-label>
<cdx-select v-model:selected="sourceAccess.sig" :menu-items="accessOptions" aria-label="有效介绍評價" default-label="請評價" />
<cdx-label>為什麼?</cdx-label>
<cdx-text-input v-model="sourceAccess.sig_just" aria-label="有效介绍理由"></cdx-text-input>
</div>
<div class="satg-app-independent">
<cdx-label>來源是否獨立於主題實體?</cdx-label>
<cdx-select v-model:selected="sourceAccess.ind" :menu-items="accessOptions" aria-label="獨立於主題實體評價" default-label="請評價" />
<cdx-label>為什麼?</cdx-label>
<cdx-text-input v-model="sourceAccess.ind_just" aria-label="獨立於主題實體理由"></cdx-text-input>
</div>
<hr />
<div class="satg-app-control">
<cdx-button action="progressive" @click="addSource(sourceAccess)">新增此來源</cdx-button>
<cdx-button action="destructive" @click="resetSource">重設來源</cdx-button>
</div>
<hr />
<div class="satg-app-sources-preview">
<cdx-label>簡易來源檢查</cdx-label>
<ol v-show="sourcesPreview.length > 0">
<li v-for="(item, index) in sources" :key="index">
{{ item.source }}
<cdx-button action="destructive" @click="deleteSource(index)">Delete source</cdx-button>
</li>
</ol>
</div>
<hr />
<div class="satg-app-result">
<cdx-label>檢查結果</cdx-label>
{{ sourceAccessResult }}
</div>
</div>
</cdx-dialog>`;
// components:
// .component( 'cdx-button', Codex.CdxButton )
// .component( 'cdx-dialog', Codex.CdxDialog )
Vue.createMwApp( {
components: VueComponentComponents,
template: VueComponentTemplate,
data: function() {
return {
showDialog: false,
showResult: false,
sources: [],
links: {
GNG: {
href: "WP:GNG",
title: "通用收錄標準"
},
EGardnerCodex: {
href: "en:User:EGardner (WMF)/codex-hello-world.js",
title: "User:EGardner (WMF)/codex-hello-world.js"
},
DannyS712SATG: {
href: "en:User:DannyS712/SATG.js",
title: "User:DannyS712/SATG.js"
},
},
GNGConditions: [
{
id: "reliable",
summary: "可靠来源",
},
{
id: "coverage" ,
summary: "有效介绍",
},
{
id: "independent" ,
summary: "獨立於主題實體",
},
],
sourceAccess: {
source: "",
rel: null,
sig: null,
ind: null,
rel_just: "",
sig_just: "",
ind_just: "",
},
accessOptions: [
{ value: "y", label: "是" },
{ value: "n", label: "否" },
{ value: "-", label: "部份" },
{ value: "?", label: "不知道" },
],
};
},
computed: {
anchorLink() {
const getLink = (link = { href: "WP:5P", title: "五大支柱" }) => `https://zh.wikipedia.org/wiki/${link.href}`;
return {
GNG: getLink(this.links.GNG),
EGardnerCodex: getLink(this.links.EGardnerCodex),
DannyS712SATG: getLink(this.links.DannyS712SATG),
};
},
anchorTitle() {
const getLink = (link = { href: "WP:5P", title: "五大支柱" }) => link.title;
return {
GNG: getLink(this.links.GNG),
EGardnerCodex: getLink(this.links.EGardnerCodex),
DannyS712SATG: getLink(this.links.DannyS712SATG),
};
},
sourcesPreview() {
const inited_source = { source: "", rel: "", sig: "", ind: "", rel_just: "", sig_just: "", ind_just: "", };
return this.sources.map( (item = inited_source, index = 0) => ({ index, ...item }) );
},
sourceAccessTemplate() {
const inited_source = { source: "", rel: "", sig: "", ind: "", rel_just: "", sig_just: "", ind_just: "", };
return this.sources.map( (item = inited_source, index = 0) => `
{{ source assess
|source=${item.source}
|rel=${item.rel}
|sig=${item.sig}
|ind=${item.ind}
|rel_just=${item.rel_just}
|sig_just=${item.sig_just}
|ind_just=${item.ind_just}
}} \n
`);
},
sourceAccessResult() {
return `{{ source assess table | user=Example |
${ this.sourceAccessTemplate }
}}`;
}
},
methods: {
openDialog () {
this.showDialog = true;
},
addSource(sourceAccess = { source: "", rel: "", sig: "", ind: "", rel_just: "", sig_just: "", ind_just: "", }) {
this.sources.push( sourceAccess );
this.resetSource();
},
resetSource() {
this.sourceAccess = {
source: "",
rel: "",
sig: "",
ind: "",
rel_just: "",
sig_just: "",
ind_just: "",
};
},
deleteItemFromIndex(ary, index) {
if (index < 0 || index >= ary.length) {
return ary;
}
ary.splice(index, 1);
return ary;
},
deleteSource(index = 0) {
this.sources = this.deleteItemFromIndex(this.sources, index);
},
toggleShowResult() {
this.showResult = !this.showResult;
},
},
mounted() {
dialogTrigger.addEventListener( 'click', this.openDialog );
},
unMounted() {
dialogTrigger.removeEventListener( this.openDialog );
}
} )
.mount( mountPoint );
} );
//</nowiki>