Skip to content

Commit

Permalink
✨ GM储存管理(#15)
Browse files Browse the repository at this point in the history
  • Loading branch information
CodFrm committed Dec 11, 2021
1 parent 606ac06 commit 6a13ff2
Show file tree
Hide file tree
Showing 6 changed files with 309 additions and 62 deletions.
63 changes: 45 additions & 18 deletions src/apps/script/controller.ts
Expand Up @@ -300,31 +300,58 @@ export class ScriptController {

// 第一次获取后在内存中维护
public async getScriptValue(script: Script): Promise<{ [key: string]: Value }> {
if (script.metadata['storagename']) {
return App.Cache.getOrSet("value:storagename:" + script.metadata['storagename'][0], () => {
return new Promise(async resolve => {
let list = <Value[]>await this.valueModel.list((table) => {
return table.where({ storageName: script.metadata['storagename'][0] });
});
let ret: { [key: string]: Value } = {};
list.forEach(val => {
ret[val.key] = val;
});
resolve(ret);
});
});
}
return App.Cache.getOrSet("value:" + script.id, () => {
return new Promise(async resolve => {
return App.Cache.getOrSet("value:storagename:" + script.metadata['storagename'][0], () => {
return this.getValues(script);
});
}

public async getValues(script: Script): Promise<{ [key: string]: Value }> {
return new Promise(async resolve => {
if (script.metadata['storagename']) {
let list = <Value[]>await this.valueModel.list((table) => {
return table.where({ scriptId: script.id });
return table.where({ storageName: script.metadata['storagename'][0] });
});
let ret: { [key: string]: Value } = {};
list.forEach(val => {
ret[val.key] = val;
});
resolve(ret);
return resolve(ret);
}
let list = <Value[]>await this.valueModel.list((table) => {
return table.where({ scriptId: script.id });
});
let ret: { [key: string]: Value } = {};
list.forEach(val => {
ret[val.key] = val;
});
resolve(ret);
});
}

public saveValue(script: Script, key: string, val: any): Promise<Value | undefined> {
return this.updateValue(key, val, script.id, (script.metadata['storagename'] && script.metadata['storagename'][0] || undefined));
}

public deleteValue(script: Script, key: string): Promise<void> {
return new Promise(async resolve => {
let model: Value | undefined;
let storageName = script.metadata['storagename'] && script.metadata['storagename'][0];
if (storageName) {
model = await this.valueModel.findOne({
storageName: storageName,
key: key,
});
} else {
model = await this.valueModel.findOne({
scriptId: script.id,
key: key,
});
}
if (model) {
this.valueModel.delete(model!.id);
MsgCenter.connect(ScriptValueChange, { model: model, tabid: undefined });
}
resolve(undefined);
});
}

Expand Down
18 changes: 2 additions & 16 deletions src/views/pages/Import/index.vue
Expand Up @@ -199,6 +199,7 @@ import {
import { SUBSCRIBE_STATUS_ENABLE } from "@App/model/do/subscribe";
import { base64ToStr, waitGroup } from "@App/pkg/utils/utils";
import { Component, Vue } from "vue-property-decorator";
import { parseStorageValue } from "../utils";
@Component({})
export default class Index extends Vue {
Expand Down Expand Up @@ -365,7 +366,7 @@ export default class Index extends Vue {
subWait.add(Object.keys(scriptInfo.storage.data).length);
for (const key in scriptInfo.storage.data) {
let importValue = async () => {
let val = this.parseValue(scriptInfo.storage.data[key]);
let val = parseStorageValue(scriptInfo.storage.data[key]);
await this.scriptCtrl.updateValue(
key,
val,
Expand Down Expand Up @@ -405,21 +406,6 @@ export default class Index extends Vue {
}
}
parseValue(str: string): any {
let t = str[0];
let s = str.substring(1);
switch (t) {
case "s":
return s;
case "b":
return s == "true";
case "n":
return parseFloat(s);
default:
return JSON.parse(s);
}
}
closeWindow() {
window.close();
}
Expand Down
213 changes: 208 additions & 5 deletions src/views/pages/Option/tabs/ScriptTab/Storage.vue
@@ -1,13 +1,216 @@
<template>
<div>GM_setValue GM_getValue</div>
<v-card>
<v-card-title>
<v-text-field
v-model="search"
:append-icon="icons.mdiMagnify"
label="搜索键"
single-line
hide-details
></v-text-field>
<v-spacer></v-spacer>
<v-dialog v-model="dialog" max-width="500px">
<template v-slot:activator="{ on, attrs }">
<v-btn color="primary" dark class="mb-2" v-bind="attrs" v-on="on">
添加新值
</v-btn>
</template>
<v-card>
<v-card-title>
<span class="text-h5">添加新值</span>
</v-card-title>
<v-card-text>
<v-container>
<v-row>
<v-col>
<v-text-field
v-model="editedItem.key"
label="储存键"
></v-text-field>
</v-col>
<v-col>
<v-text-field
v-model="editedItem.value"
label="储存值"
></v-text-field>
</v-col>
</v-row>
</v-container>
</v-card-text>

<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="blue darken-1" text @click="close"> 取消 </v-btn>
<v-btn color="blue darken-1" text @click="save"> 保存 </v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</v-card-title>
<v-data-table
:headers="headers"
:items="values"
:search="search"
:footer-props="{
itemsPerPageAllText: '显示全部',
itemsPerPageText: '每行页数',
}"
>
<template v-slot:top>
<v-toolbar flat>
<p>
储存空间:
{{
(script.metadata["storagename"] &&
script.metadata["storagename"][0]) ||
"匿名空间"
}}
</p>
<v-spacer></v-spacer>
<v-dialog v-model="dialogDelete" max-width="500px">
<v-card>
<v-card-title class="text-h5">请确定是否删除储存项?</v-card-title>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="blue darken-1" text @click="closeDelete"
>取消</v-btn
>
<v-btn color="blue darken-1" text @click="deleteItemConfirm"
>确定</v-btn
>
<v-spacer></v-spacer>
</v-card-actions>
</v-card>
</v-dialog>
</v-toolbar>
</template>
<template v-slot:[`item.value`]="{ item }">
{{ toStorageValueStr(item.value) }}
</template>
<template v-slot:[`item.actions`]="{ item }">
<v-icon small class="mr-2" @click="editItem(item)">
{{ icons.mdiPencil }}
</v-icon>
<v-icon small @click="deleteItem(item)">
{{ icons.mdiDelete }}
</v-icon>
</template>
<template v-slot:no-data> 没有储存数据 </template>
</v-data-table>
<v-card-subtitle>
值的第一个字符表示该值的类型,在编辑值时请也按照此规则进行编辑,否则默认识别为文本.
s:文本 n:数字 b:布尔值 o:对象
</v-card-subtitle>
</v-card>
</template>

<script lang="ts">
import { Component, Prop, Vue } from "vue-property-decorator";
import { ScriptController } from "@App/apps/script/controller";
import { Script } from "@App/model/do/script";
import { Value } from "@App/model/do/value";
import { parseStorageValue, toStorageValueStr } from "@App/views/pages/utils";
import { Component, Prop, Vue, Watch } from "vue-property-decorator";
import { mdiMagnify, mdiPencil, mdiDelete } from "@mdi/js";
@Component({})
export default class CloseButton extends Vue {}
export default class CloseButton extends Vue {
icons = {
mdiMagnify: mdiMagnify,
mdiPencil: mdiPencil,
mdiDelete: mdiDelete,
};
scriptCtrl = new ScriptController();
values: Array<Value> = new Array();
dialog = false;
dialogDelete = false;
editedIndex = -1;
editedItem = { key: "", value: "" };
@Prop() script!: Script;
async created() {
let values = await this.scriptCtrl.getValues(this.script);
console.log(this.script, values);
for (const key in values) {
this.values.push(values[key]);
}
}
data() {
return {
search: "",
headers: [
{ text: "储存键", value: "key" },
{ text: "储存值", value: "value" },
{ text: "操作", value: "actions" },
],
};
}
toStorageValueStr = toStorageValueStr;
@Watch("dialog")
watchDialog(val: any) {
val || this.close();
}
@Watch("dialogDelete")
watchDialogDelete(val: any) {
val || this.closeDelete();
}
close() {
this.dialog = false;
this.$nextTick(() => {
this.editedItem = { key: "", value: "" };
this.editedIndex = -1;
});
}
closeDelete() {
this.dialogDelete = false;
this.$nextTick(() => {
this.editedItem = { key: "", value: "" };
this.editedIndex = -1;
});
}
async save() {
let value = await this.scriptCtrl.saveValue(
this.script,
this.editedItem.key,
parseStorageValue(this.editedItem.value)
);
if (!value) {
alert("保存失败");
return;
}
if (this.editedIndex > -1) {
this.values[this.editedIndex].value = value.value;
} else {
this.values.unshift(value);
}
this.close();
}
editItem(item: Value) {
this.editedIndex = this.values.indexOf(item);
this.editedItem = Object.assign({}, item);
this.editedItem.value = toStorageValueStr(item.value);
this.dialog = true;
}
deleteItem(item: Value) {
this.editedIndex = this.values.indexOf(item);
this.editedItem = Object.assign({}, item);
this.editedItem.value = toStorageValueStr(item.value);
this.dialogDelete = true;
}
deleteItemConfirm() {
this.values.splice(this.editedIndex, 1);
this.scriptCtrl.deleteValue(this.script, this.editedItem.key);
this.closeDelete();
}
}
</script>

<style>
</style>
<style></style>
20 changes: 11 additions & 9 deletions src/views/pages/Option/tabs/ScriptTab/index.vue
Expand Up @@ -29,15 +29,15 @@
</TabPane>

<TabPane title="设置">
<Config />
<Config :script="script" />
</TabPane>

<TabPane title="存储">
<Storage />
<Storage :script="script" />
</TabPane>

<TabPane title="资源">
<Resource />
<Resource :script="script" />
</TabPane>
</Tab>
</div>
Expand Down Expand Up @@ -162,12 +162,14 @@ export default class ScriptTab extends Vue {
async handleSaveScript({ currentCode, debug }: ISaveScript) {
// todo 保存时候错误处理
let [newScript, oldScript] =
await this.scriptController.prepareScriptByCode(
currentCode,
this.script.origin || "",
this.script.uuid ? this.script.uuid : uuidv4()
);
let [
newScript,
oldScript,
] = await this.scriptController.prepareScriptByCode(
currentCode,
this.script.origin || "",
this.script.uuid ? this.script.uuid : uuidv4()
);
if (newScript == undefined) {
alert(oldScript);
Expand Down

0 comments on commit 6a13ff2

Please sign in to comment.