mirror of
https://github.com/daief/gm-response-proxy.git
synced 2026-03-15 02:33:17 +08:00
wip: easy ui
This commit is contained in:
@@ -1,30 +1,62 @@
|
||||
<template>
|
||||
<div v-show="show" :class="cls" @click.self="close">
|
||||
<div :class="`${cls}--container`">
|
||||
<Button type="primary" :onClick="handleAdd">+</Button>
|
||||
<Button type="primary" @click="handleAddSet"> + 新增规则集合 </Button>
|
||||
<br />
|
||||
<div
|
||||
v-for="(it, idx) in state.matchedSetList"
|
||||
:key="idx"
|
||||
:key="it.id"
|
||||
:class="`${cls}--set-wrap`"
|
||||
>
|
||||
<div>
|
||||
<label>domainTest:</label>
|
||||
<input :value="it.domainTest" />
|
||||
<Button type="primary" :onClick="() => handleAddRule(idx)">
|
||||
Add rule
|
||||
<Button
|
||||
:class="`${cls}--set-del`"
|
||||
size="small"
|
||||
shape="circle"
|
||||
@click="handleDelSet(it, i)"
|
||||
>
|
||||
X
|
||||
</Button>
|
||||
<div :class="`${cls}--set-domain-head`">
|
||||
<label>域名匹配规则(支持正则):</label>
|
||||
<input :value="it.domainTest" :class="`${cls}--set-domain-input`" />
|
||||
<Button type="primary" @click="() => handleAddRule(idx)" size="small">
|
||||
添加 Api 规则
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div v-for="(rule, idx2) in it.rules" :key="idx2">
|
||||
<div
|
||||
v-for="(rule, idx2) in it.rules"
|
||||
:key="rule.id"
|
||||
style="padding: 0 10px; margin-bottom: 10px"
|
||||
>
|
||||
<div>
|
||||
<label>rule-{{ idx2 }}:</label>
|
||||
<label>
|
||||
Rule {{ idx2 + 1 }} ----
|
||||
<Button
|
||||
:class="`${cls}--set-del-rule`"
|
||||
size="small"
|
||||
shape="circle"
|
||||
@click="handleDelRule(rule, idx, idx2)"
|
||||
>
|
||||
X
|
||||
</Button>
|
||||
</label>
|
||||
<div>
|
||||
apiTest: <input v-model="rule.apiTest" style="width: 300px" />
|
||||
Api 匹配规则(仅字符串子串):
|
||||
<br />
|
||||
<input v-model="rule.apiTest" style="width: 100%; padding: 8px" />
|
||||
</div>
|
||||
<div>
|
||||
Mock Response(仅 JSON):
|
||||
<br />
|
||||
<textarea
|
||||
v-model="rule.response"
|
||||
rows="6"
|
||||
style="width: 100%; max-width: 100%; padding: 8px"
|
||||
/>
|
||||
</div>
|
||||
<div>response: <textarea v-model="rule.response" /></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -72,7 +104,7 @@ export default defineComponent({
|
||||
close: () => {
|
||||
show.value = false;
|
||||
},
|
||||
handleAdd: () => {
|
||||
handleAddSet: () => {
|
||||
state.matchedSetList.unshift({
|
||||
domainTest: location.hostname,
|
||||
rules: [],
|
||||
@@ -87,6 +119,17 @@ export default defineComponent({
|
||||
disabled: false,
|
||||
});
|
||||
},
|
||||
handleDelSet: (item: ISet) => {
|
||||
if (confirm('是否删除该集合,包括其下所有 Api 配置?')) {
|
||||
Store.deleteSets([item.id]);
|
||||
state.matchedSetList = state.matchedSetList.filter(it => it !== item);
|
||||
}
|
||||
},
|
||||
handleDelRule: (item: any, setIdx: number, _ruleIdx: number) => {
|
||||
state.matchedSetList[setIdx].rules = state.matchedSetList[
|
||||
setIdx
|
||||
].rules.filter(it => it !== item);
|
||||
},
|
||||
};
|
||||
},
|
||||
});
|
||||
@@ -114,20 +157,37 @@ export default defineComponent({
|
||||
background: #fff;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 0 24px 0 rgba(102, 102, 102, 0.08);
|
||||
min-height: 360px;
|
||||
height: 640px;
|
||||
max-height: 100%;
|
||||
max-width: 100%;
|
||||
width: 720px;
|
||||
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
&--set-wrap {
|
||||
border: @color5 1px solid;
|
||||
border-radius: 4px;
|
||||
margin: 10px;
|
||||
margin: 15px 30px;
|
||||
padding: 16px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
& + & {
|
||||
margin-top: 10px;
|
||||
}
|
||||
&--set-del {
|
||||
position: absolute;
|
||||
top: -12px;
|
||||
right: -12px;
|
||||
}
|
||||
|
||||
&--set-domain-input {
|
||||
width: 300px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
&--set-domain-head {
|
||||
height: 40px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
<template>
|
||||
<button :class="[cls, `${cls}--${type}`]" @click="handleClick">
|
||||
<button
|
||||
:class="[
|
||||
cls,
|
||||
`${cls}--${type}`,
|
||||
`${cls}--size-${size}`,
|
||||
`${cls}--shape-${shape}`,
|
||||
]"
|
||||
@click="handleClick"
|
||||
>
|
||||
<slot />
|
||||
</button>
|
||||
</template>
|
||||
@@ -8,27 +16,45 @@
|
||||
import { ns } from '@/common';
|
||||
import { defineComponent, ref } from 'vue';
|
||||
|
||||
import type { PropType } from 'vue';
|
||||
|
||||
export interface IButtonProps {
|
||||
type?: PropType<'primary' | 'secondary'>;
|
||||
size?: PropType<'default' | 'small'>;
|
||||
shape?: PropType<'default' | 'circle' | 'round'>;
|
||||
}
|
||||
|
||||
export default defineComponent({
|
||||
name: 'RPButton',
|
||||
props: {
|
||||
type: {
|
||||
type: String,
|
||||
type: String as IButtonProps['type'],
|
||||
default: 'secondary',
|
||||
},
|
||||
size: {
|
||||
type: String as IButtonProps['size'],
|
||||
default: 'default',
|
||||
},
|
||||
shape: {
|
||||
type: String as IButtonProps['shape'],
|
||||
default: 'default',
|
||||
},
|
||||
onClick: {
|
||||
type: Function,
|
||||
default: () => null,
|
||||
},
|
||||
},
|
||||
setup(props) {
|
||||
setup(props, _ctx) {
|
||||
const innerLoading = ref(false);
|
||||
|
||||
const handleClick = async (e: any) => {
|
||||
// ctx.emit('click', e);
|
||||
|
||||
if (innerLoading.value) return;
|
||||
|
||||
try {
|
||||
innerLoading.value = true;
|
||||
await props.onClick(e);
|
||||
await props.onClick(e); // ? 能触发 @click
|
||||
} catch (_) {
|
||||
} finally {
|
||||
innerLoading.value = false;
|
||||
@@ -47,15 +73,16 @@ export default defineComponent({
|
||||
.@{prefix}__button {
|
||||
text-transform: none;
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
display: inline-flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
white-space: nowrap;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
|
||||
user-select: none;
|
||||
touch-action: manipulation;
|
||||
height: 32px;
|
||||
padding: 4px 15px;
|
||||
padding: 0 15px;
|
||||
font-size: 14px;
|
||||
border-radius: 2px;
|
||||
border: 1px solid #d9d9d9;
|
||||
@@ -94,5 +121,26 @@ export default defineComponent({
|
||||
color: @color8;
|
||||
}
|
||||
}
|
||||
|
||||
&--size {
|
||||
&-default {
|
||||
min-width: 32px;
|
||||
}
|
||||
&-small {
|
||||
height: 24px;
|
||||
min-width: 24px;
|
||||
padding: 0 12px;
|
||||
}
|
||||
}
|
||||
|
||||
&--shape {
|
||||
&-circle {
|
||||
border-radius: 50%;
|
||||
padding: 0;
|
||||
}
|
||||
&-round {
|
||||
border-radius: 32px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -53,4 +53,11 @@ export const Store = {
|
||||
});
|
||||
GM_setValue(KEY_SET, store);
|
||||
},
|
||||
deleteSets(ids: string[]) {
|
||||
const store = Store.getStoreObject();
|
||||
ids.forEach(id => {
|
||||
delete store[id];
|
||||
});
|
||||
GM_setValue(KEY_SET, store);
|
||||
},
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user