mirror of
https://github.com/fofolee/uTools-quickcommand.git
synced 2025-12-19 18:25:44 +08:00
重构ubrowser
This commit is contained in:
@@ -33,7 +33,8 @@
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<q-select
|
||||
v-model="selectedUA"
|
||||
:model-value="selectedUA"
|
||||
@update:model-value="handleUAChange"
|
||||
:options="userAgentOptions"
|
||||
label="常用 UA"
|
||||
dense
|
||||
@@ -66,11 +67,11 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { defineComponent } from "vue";
|
||||
import { defaultUBrowserConfigs } from "js/composer/ubrowserConfig";
|
||||
import { defineComponent, ref, computed } from "vue";
|
||||
import { userAgent } from "js/options/httpOptions";
|
||||
import VariableInput from "components/composer/ui/VariableInput.vue";
|
||||
import NumberInput from "components/composer/ui/NumberInput.vue";
|
||||
|
||||
export default defineComponent({
|
||||
name: "UBrowserBasic",
|
||||
components: {
|
||||
@@ -83,37 +84,47 @@ export default defineComponent({
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
selectedUA: null,
|
||||
localConfigs: defaultUBrowserConfigs.goto,
|
||||
userAgentOptions: userAgent,
|
||||
};
|
||||
},
|
||||
created() {
|
||||
// 初始化本地配置
|
||||
this.localConfigs = window.lodashM.cloneDeep(this.configs);
|
||||
},
|
||||
methods: {
|
||||
updateConfigs() {
|
||||
this.$emit("update:configs", window.lodashM.cloneDeep(this.localConfigs));
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
configs: {
|
||||
deep: true,
|
||||
handler(newConfigs) {
|
||||
this.localConfigs = window.lodashM.cloneDeep(newConfigs);
|
||||
emits: ["update:configs"],
|
||||
setup(props, { emit }) {
|
||||
const selectedUA = ref(null);
|
||||
|
||||
// 使用 computed 处理配置
|
||||
const localConfigs = computed({
|
||||
get: () => props.configs,
|
||||
set: (val) => {
|
||||
emit("update:configs", val);
|
||||
},
|
||||
},
|
||||
selectedUA(value) {
|
||||
if (value) {
|
||||
this.localConfigs.goto.headers.userAgent.value = value;
|
||||
this.localConfigs.goto.headers.userAgent.isString = true;
|
||||
this.updateConfigs();
|
||||
this.selectedUA = null;
|
||||
});
|
||||
|
||||
// 更新配置
|
||||
const updateConfigs = () => {
|
||||
emit("update:configs", localConfigs.value);
|
||||
};
|
||||
|
||||
// 处理 UA 选择
|
||||
const handleUAChange = (val) => {
|
||||
if (!val) return;
|
||||
|
||||
const newConfigs = window.lodashM.cloneDeep(props.configs);
|
||||
if (!newConfigs.goto.headers) {
|
||||
newConfigs.goto.headers = {};
|
||||
}
|
||||
},
|
||||
newConfigs.goto.headers.userAgent = {
|
||||
value: val,
|
||||
isString: true,
|
||||
__varInputVal__: true,
|
||||
};
|
||||
emit("update:configs", newConfigs);
|
||||
selectedUA.value = null;
|
||||
};
|
||||
|
||||
return {
|
||||
selectedUA,
|
||||
localConfigs,
|
||||
userAgentOptions: userAgent,
|
||||
updateConfigs,
|
||||
handleUAChange,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
</q-tabs>
|
||||
|
||||
<!-- 内容区域 -->
|
||||
<q-tab-panels v-model="step" animated swipeable class="ubrowser-panels">
|
||||
<q-tab-panels v-model="step" class="ubrowser-panels">
|
||||
<q-tab-panel name="1" class="panel-content">
|
||||
<UBrowserBasic :configs="configs" @update:configs="updateConfigs" />
|
||||
</q-tab-panel>
|
||||
@@ -23,8 +23,9 @@
|
||||
<q-tab-panel name="2" class="panel-content">
|
||||
<UBrowserOperations
|
||||
:configs="configs"
|
||||
:selected-actions="selectedActions"
|
||||
@update:configs="updateConfigs"
|
||||
v-model:selected-actions="selectedActions"
|
||||
@update:selected-actions="(val) => (selectedActions = val)"
|
||||
@remove-action="removeAction"
|
||||
/>
|
||||
</q-tab-panel>
|
||||
@@ -37,7 +38,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { defineComponent } from "vue";
|
||||
import { defineComponent, ref, computed } from "vue";
|
||||
import UBrowserBasic from "./UBrowserBasic.vue";
|
||||
import UBrowserOperations from "./UBrowserOperations.vue";
|
||||
import UBrowserRun from "./UBrowserRun.vue";
|
||||
@@ -53,117 +54,115 @@ export default defineComponent({
|
||||
},
|
||||
props: {
|
||||
modelValue: {
|
||||
type: String,
|
||||
default: "",
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
emits: ["update:modelValue"],
|
||||
data() {
|
||||
return {
|
||||
step: "1",
|
||||
selectedActions: [],
|
||||
configs: window.lodashM.cloneDeep(defaultUBrowserConfigs),
|
||||
setup(props, { emit }) {
|
||||
// 基础状态
|
||||
const step = ref("1");
|
||||
const selectedActions = ref([]);
|
||||
|
||||
// 初始化配置,确保包含 run 参数
|
||||
const localConfigs = ref(window.lodashM.cloneDeep(defaultUBrowserConfigs));
|
||||
if (props.modelValue?.argvs) {
|
||||
// 合并配置,保留默认的 run 参数
|
||||
localConfigs.value = {
|
||||
...localConfigs.value,
|
||||
...props.modelValue.argvs,
|
||||
run: {
|
||||
...localConfigs.value.run,
|
||||
...props.modelValue.argvs.run,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
// 计算 argvs
|
||||
const argvs = computed({
|
||||
get: () => localConfigs.value,
|
||||
set: (val) => {
|
||||
// 确保保留 run 参数
|
||||
const newConfigs = {
|
||||
...val,
|
||||
run: {
|
||||
...localConfigs.value.run,
|
||||
...val.run,
|
||||
},
|
||||
};
|
||||
localConfigs.value = newConfigs;
|
||||
emit("update:modelValue", {
|
||||
...props.modelValue,
|
||||
argvs: newConfigs,
|
||||
code: generateUBrowserCode(newConfigs, selectedActions.value),
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
// 更新配置
|
||||
const updateConfigs = (newConfigs) => {
|
||||
argvs.value = window.lodashM.cloneDeep(newConfigs);
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
updateConfigs(newConfigs) {
|
||||
this.configs = newConfigs;
|
||||
},
|
||||
removeAction(action) {
|
||||
const newActions = this.selectedActions.filter((a) => a.id !== action.id);
|
||||
this.selectedActions = newActions;
|
||||
const newConfigs = { ...this.configs };
|
||||
|
||||
// 移除操作
|
||||
const removeAction = (action) => {
|
||||
selectedActions.value = selectedActions.value.filter(
|
||||
(a) => a.id !== action.id
|
||||
);
|
||||
const newConfigs = { ...argvs.value };
|
||||
delete newConfigs[action.value];
|
||||
this.configs = newConfigs;
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
configs: {
|
||||
deep: true,
|
||||
handler() {
|
||||
this.$emit(
|
||||
"update:modelValue",
|
||||
generateUBrowserCode(this.configs, this.selectedActions)
|
||||
);
|
||||
},
|
||||
},
|
||||
selectedActions: {
|
||||
handler() {
|
||||
this.$emit(
|
||||
"update:modelValue",
|
||||
generateUBrowserCode(this.configs, this.selectedActions)
|
||||
);
|
||||
},
|
||||
},
|
||||
step: {
|
||||
handler() {
|
||||
this.$emit(
|
||||
"update:modelValue",
|
||||
generateUBrowserCode(this.configs, this.selectedActions)
|
||||
);
|
||||
},
|
||||
},
|
||||
argvs.value = newConfigs;
|
||||
};
|
||||
|
||||
return {
|
||||
step,
|
||||
selectedActions,
|
||||
configs: argvs,
|
||||
updateConfigs,
|
||||
removeAction,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
<style>
|
||||
.ubrowser-editor {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
min-height: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.ubrowser-tabs {
|
||||
background: rgba(255, 255, 255, 0.8);
|
||||
border-radius: 4px 4px 0 0;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.ubrowser-panels {
|
||||
background: rgba(255, 255, 255, 0.8);
|
||||
border-radius: 0 0 4px 4px;
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
|
||||
/* 调整面板内边距和布局 */
|
||||
.ubrowser-panels :deep(.q-tab-panel) {
|
||||
padding: 8px;
|
||||
height: 100%;
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
/* 面板内容区域 */
|
||||
.panel-content {
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
/* 调整标签页样式 */
|
||||
.panel-content {
|
||||
padding: 16px;
|
||||
min-height: 200px;
|
||||
}
|
||||
|
||||
.ubrowser-panels :deep(.q-tab-panel) {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.ubrowser-tabs :deep(.q-tab) {
|
||||
min-height: 36px;
|
||||
padding: 0 12px;
|
||||
}
|
||||
|
||||
.ubrowser-tabs :deep(.q-tab__content) {
|
||||
min-width: 0;
|
||||
flex-direction: row;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.ubrowser-tabs :deep(.q-tab__label) {
|
||||
font-size: 12px;
|
||||
line-height: 1;
|
||||
min-height: 40px;
|
||||
padding: 0 16px;
|
||||
}
|
||||
|
||||
.ubrowser-tabs :deep(.q-tab__icon) {
|
||||
font-size: 16px;
|
||||
margin: 0;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.ubrowser-tabs :deep(.q-tab__label) {
|
||||
font-size: 14px;
|
||||
line-height: 1.2;
|
||||
margin-left: 8px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -106,20 +106,21 @@ export default defineComponent({
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
emits: ["remove-action", "update:selectedActions", "update:configs"],
|
||||
setup() {
|
||||
return {
|
||||
ubrowserOperationConfigs: ubrowserOperationConfigs,
|
||||
ubrowserOperationConfigs,
|
||||
};
|
||||
},
|
||||
emits: ["remove-action", "update:selectedActions", "update:configs"],
|
||||
methods: {
|
||||
moveAction(index, direction) {
|
||||
const newIndex = index + direction;
|
||||
if (newIndex >= 0 && newIndex < this.selectedActions.length) {
|
||||
const actions = [...this.selectedActions];
|
||||
const temp = actions[index];
|
||||
actions[index] = actions[newIndex];
|
||||
actions[newIndex] = temp;
|
||||
[actions[index], actions[newIndex]] = [
|
||||
actions[newIndex],
|
||||
actions[index],
|
||||
];
|
||||
this.$emit("update:selectedActions", actions);
|
||||
}
|
||||
},
|
||||
@@ -127,19 +128,22 @@ export default defineComponent({
|
||||
const index = this.selectedActions.findIndex(
|
||||
(a) => a.value === action.value
|
||||
);
|
||||
|
||||
if (index === -1) {
|
||||
// 添加操作
|
||||
const newAction = {
|
||||
...action,
|
||||
id: this.$root.getUniqueId(),
|
||||
argv: "",
|
||||
saveOutput: false,
|
||||
useOutput: null,
|
||||
cmd: action.value || action.cmd,
|
||||
value: action.value || action.cmd,
|
||||
};
|
||||
|
||||
this.$emit("update:selectedActions", [
|
||||
...this.selectedActions,
|
||||
{
|
||||
...action,
|
||||
id: this.$root.getUniqueId(),
|
||||
argv: "",
|
||||
saveOutput: false,
|
||||
useOutput: null,
|
||||
cmd: action.value || action.cmd,
|
||||
value: action.value || action.cmd,
|
||||
},
|
||||
newAction,
|
||||
]);
|
||||
|
||||
// 初始化配置对象
|
||||
@@ -148,14 +152,14 @@ export default defineComponent({
|
||||
const newConfigs = { ...this.configs };
|
||||
if (!newConfigs[action.value]) {
|
||||
newConfigs[action.value] = {};
|
||||
// 设置默认值
|
||||
config.forEach((field) => {
|
||||
if (field.defaultValue !== undefined) {
|
||||
newConfigs[action.value][field.key] = field.defaultValue;
|
||||
}
|
||||
});
|
||||
this.$emit("update:configs", newConfigs);
|
||||
}
|
||||
// 设置默认值
|
||||
config.forEach((field) => {
|
||||
if (field.defaultValue !== undefined) {
|
||||
newConfigs[action.value][field.key] = field.defaultValue;
|
||||
}
|
||||
});
|
||||
this.$emit("update:configs", newConfigs);
|
||||
}
|
||||
} else {
|
||||
// 移除操作
|
||||
@@ -167,7 +171,7 @@ export default defineComponent({
|
||||
getActionProps(action, key) {
|
||||
return this.ubrowserOperationConfigs.find(
|
||||
(a) => a.value === action.value
|
||||
)[key];
|
||||
)?.[key];
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@@ -155,7 +155,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { defineComponent } from "vue";
|
||||
import { defineComponent, ref, computed } from "vue";
|
||||
import NumberInput from "components/composer/ui/NumberInput.vue";
|
||||
|
||||
export default defineComponent({
|
||||
@@ -170,24 +170,24 @@ export default defineComponent({
|
||||
},
|
||||
},
|
||||
emits: ["update:configs"],
|
||||
data() {
|
||||
return {
|
||||
localConfigs: window.lodashM.cloneDeep(this.configs),
|
||||
setup(props, { emit }) {
|
||||
const localConfigs = ref(window.lodashM.cloneDeep(props.configs));
|
||||
|
||||
// 监听 configs 变化
|
||||
const watchConfigs = computed(() => props.configs);
|
||||
watchConfigs.value &&
|
||||
(localConfigs.value = window.lodashM.cloneDeep(props.configs));
|
||||
|
||||
// 更新配置
|
||||
const updateConfig = (key, value) => {
|
||||
localConfigs.value.run[key] = value;
|
||||
emit("update:configs", window.lodashM.cloneDeep(localConfigs.value));
|
||||
};
|
||||
|
||||
return {
|
||||
localConfigs,
|
||||
updateConfig,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
updateConfig(key, value) {
|
||||
this.localConfigs.run[key] = value;
|
||||
this.$emit("update:configs", window.lodashM.cloneDeep(this.localConfigs));
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
configs: {
|
||||
deep: true,
|
||||
handler(newConfigs) {
|
||||
this.localConfigs = window.lodashM.cloneDeep(newConfigs);
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
<template>
|
||||
<div class="row items-center no-wrap">
|
||||
<q-badge class="q-pa-xs">{{ label }}</q-badge>
|
||||
<q-btn-toggle
|
||||
:model-value="modelValue"
|
||||
:options="options"
|
||||
dense
|
||||
flat
|
||||
no-caps
|
||||
spread
|
||||
class="button-group"
|
||||
@update:model-value="$emit('update:modelValue', $event)"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { defineComponent } from "vue";
|
||||
|
||||
export default defineComponent({
|
||||
name: "UBrowserButtonToggle",
|
||||
props: {
|
||||
modelValue: {
|
||||
type: [String, Number, Boolean],
|
||||
required: true,
|
||||
},
|
||||
label: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
options: {
|
||||
type: Array,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
emits: ["update:modelValue"],
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.button-group {
|
||||
flex: 1;
|
||||
padding: 0 10px;
|
||||
}
|
||||
|
||||
.button-group :deep(.q-btn) {
|
||||
min-height: 24px;
|
||||
font-size: 12px;
|
||||
}
|
||||
</style>
|
||||
@@ -1,37 +0,0 @@
|
||||
<template>
|
||||
<div class="row items-center no-wrap">
|
||||
<q-badge class="q-pa-xs">{{ label }}</q-badge>
|
||||
<q-btn-toggle
|
||||
:model-value="modelValue ? 'true' : 'false'"
|
||||
:options="[
|
||||
{ label: '是', value: 'true' },
|
||||
{ label: '否', value: 'false' },
|
||||
]"
|
||||
dense
|
||||
flat
|
||||
no-caps
|
||||
spread
|
||||
class="button-group"
|
||||
@update:model-value="$emit('update:modelValue', $event === 'true')"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { defineComponent } from "vue";
|
||||
|
||||
export default defineComponent({
|
||||
name: "UBrowserCheckbox",
|
||||
props: {
|
||||
modelValue: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
label: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
emits: ["update:modelValue"],
|
||||
});
|
||||
</script>
|
||||
@@ -1,31 +0,0 @@
|
||||
<template>
|
||||
<div class="row items-center">
|
||||
<q-option-group
|
||||
:model-value="modelValue"
|
||||
:options="options"
|
||||
type="checkbox"
|
||||
inline
|
||||
dense
|
||||
@update:model-value="$emit('update:modelValue', $event)"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { defineComponent } from "vue";
|
||||
|
||||
export default defineComponent({
|
||||
name: "UBrowserCheckboxGroup",
|
||||
props: {
|
||||
modelValue: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
options: {
|
||||
type: Array,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
emits: ["update:modelValue"],
|
||||
});
|
||||
</script>
|
||||
@@ -11,7 +11,7 @@
|
||||
<VariableInput
|
||||
:model-value="cookie.name"
|
||||
label="名称"
|
||||
:command="{ icon: 'label' }"
|
||||
icon="label"
|
||||
@update:model-value="
|
||||
(value) => handleUpdate(index, 'name', value)
|
||||
"
|
||||
@@ -21,7 +21,7 @@
|
||||
<VariableInput
|
||||
:model-value="cookie.value"
|
||||
label="值"
|
||||
:command="{ icon: 'edit' }"
|
||||
icon="edit"
|
||||
@update:model-value="
|
||||
(value) => handleUpdate(index, 'value', value)
|
||||
"
|
||||
@@ -64,20 +64,58 @@ export default defineComponent({
|
||||
props: {
|
||||
modelValue: {
|
||||
type: Array,
|
||||
default: () => [{ name: "", value: "" }],
|
||||
default: () => [
|
||||
{
|
||||
name: {
|
||||
value: "",
|
||||
isString: true,
|
||||
__varInputVal__: true,
|
||||
},
|
||||
value: {
|
||||
value: "",
|
||||
isString: true,
|
||||
__varInputVal__: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
emits: ["update:modelValue"],
|
||||
methods: {
|
||||
addCookie() {
|
||||
const newValue = [...this.modelValue, { name: "", value: "" }];
|
||||
const newValue = [
|
||||
...this.modelValue,
|
||||
{
|
||||
name: {
|
||||
value: "",
|
||||
isString: true,
|
||||
__varInputVal__: true,
|
||||
},
|
||||
value: {
|
||||
value: "",
|
||||
isString: true,
|
||||
__varInputVal__: true,
|
||||
},
|
||||
},
|
||||
];
|
||||
this.$emit("update:modelValue", newValue);
|
||||
},
|
||||
removeCookie(index) {
|
||||
const newValue = [...this.modelValue];
|
||||
newValue.splice(index, 1);
|
||||
if (newValue.length === 0) {
|
||||
newValue.push({ name: "", value: "" });
|
||||
newValue.push({
|
||||
name: {
|
||||
value: "",
|
||||
isString: true,
|
||||
__varInputVal__: true,
|
||||
},
|
||||
value: {
|
||||
value: "",
|
||||
isString: true,
|
||||
__varInputVal__: true,
|
||||
},
|
||||
});
|
||||
}
|
||||
this.$emit("update:modelValue", newValue);
|
||||
},
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<div class="row q-col-gutter-sm">
|
||||
<div class="col">
|
||||
<VariableInput
|
||||
:command="{ icon: icon }"
|
||||
icon="label"
|
||||
:model-value="modelValue"
|
||||
:label="label"
|
||||
@update:model-value="$emit('update:modelValue', $event)"
|
||||
@@ -41,8 +41,12 @@ export default defineComponent({
|
||||
},
|
||||
props: {
|
||||
modelValue: {
|
||||
type: String,
|
||||
default: "",
|
||||
type: Object,
|
||||
default: () => ({
|
||||
value: "",
|
||||
isString: true,
|
||||
__varInputVal__: true,
|
||||
}),
|
||||
},
|
||||
label: {
|
||||
type: String,
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
<template>
|
||||
<div class="row q-col-gutter-sm">
|
||||
<div class="col-6">
|
||||
<VariableInput
|
||||
v-model.number="size.width"
|
||||
label="宽度"
|
||||
:command="{ icon: 'width', inputType: 'number' }"
|
||||
@update:model-value="handleUpdate"
|
||||
/>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<VariableInput
|
||||
v-model.number="size.height"
|
||||
label="高度"
|
||||
:command="{ icon: 'height', inputType: 'number' }"
|
||||
@update:model-value="handleUpdate"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { defineComponent } from "vue";
|
||||
import VariableInput from "components/composer/ui/VariableInput.vue";
|
||||
|
||||
export default defineComponent({
|
||||
name: "UBrowserDeviceSize",
|
||||
components: {
|
||||
VariableInput,
|
||||
},
|
||||
props: {
|
||||
modelValue: {
|
||||
type: Object,
|
||||
default: () => ({ width: 0, height: 0 }),
|
||||
},
|
||||
},
|
||||
emits: ["update:modelValue"],
|
||||
data() {
|
||||
return {
|
||||
size: {
|
||||
width: this.modelValue.width,
|
||||
height: this.modelValue.height,
|
||||
},
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
handleUpdate() {
|
||||
this.$emit("update:modelValue", { ...this.size });
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
modelValue: {
|
||||
deep: true,
|
||||
handler(newValue) {
|
||||
this.size = { ...newValue };
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
</script>
|
||||
@@ -58,7 +58,14 @@ export default defineComponent({
|
||||
emits: ["update:modelValue"],
|
||||
methods: {
|
||||
addFile() {
|
||||
const newValue = [...(this.modelValue || []), ""];
|
||||
const newValue = [
|
||||
...(this.modelValue || []),
|
||||
{
|
||||
value: "",
|
||||
isString: true,
|
||||
__varInputVal__: true,
|
||||
},
|
||||
];
|
||||
this.$emit("update:modelValue", newValue);
|
||||
},
|
||||
removeFile(index) {
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<VariableInput
|
||||
:model-value="param.name"
|
||||
label="参数名"
|
||||
:command="{ icon: 'label' }"
|
||||
icon="label"
|
||||
@update:model-value="(value) => handleUpdate(index, 'name', value)"
|
||||
/>
|
||||
</div>
|
||||
@@ -18,7 +18,7 @@
|
||||
<VariableInput
|
||||
:model-value="param.value"
|
||||
label="传递给参数的值"
|
||||
:command="{ icon: 'edit' }"
|
||||
icon="edit"
|
||||
@update:model-value="(value) => handleUpdate(index, 'value', value)"
|
||||
/>
|
||||
</div>
|
||||
@@ -56,14 +56,41 @@ export default defineComponent({
|
||||
props: {
|
||||
modelValue: {
|
||||
type: Array,
|
||||
default: () => [{ name: "", value: "" }],
|
||||
default: () => [
|
||||
{
|
||||
name: {
|
||||
value: "",
|
||||
isString: true,
|
||||
__varInputVal__: true,
|
||||
},
|
||||
value: {
|
||||
value: "",
|
||||
isString: true,
|
||||
__varInputVal__: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
label: String,
|
||||
},
|
||||
emits: ["update:modelValue"],
|
||||
methods: {
|
||||
addParam() {
|
||||
const newValue = [...(this.modelValue || []), { name: "", value: "" }];
|
||||
const newValue = [
|
||||
...(this.modelValue || []),
|
||||
{
|
||||
name: {
|
||||
value: "",
|
||||
isString: true,
|
||||
__varInputVal__: true,
|
||||
},
|
||||
value: {
|
||||
value: "",
|
||||
isString: true,
|
||||
__varInputVal__: true,
|
||||
},
|
||||
},
|
||||
];
|
||||
this.$emit("update:modelValue", newValue);
|
||||
},
|
||||
removeParam(index) {
|
||||
|
||||
@@ -7,20 +7,37 @@
|
||||
>
|
||||
<!-- 复选框组 -->
|
||||
<template v-if="field.type === 'checkbox-group'">
|
||||
<UBrowserCheckboxGroup
|
||||
v-model="fieldValue[field.key]"
|
||||
<q-option-group
|
||||
:model-value="
|
||||
Array.isArray(fieldValue[field.key]) ? fieldValue[field.key] : []
|
||||
"
|
||||
:options="field.options"
|
||||
type="checkbox"
|
||||
class="row items-center"
|
||||
inline
|
||||
dense
|
||||
@update:model-value="updateValue(field.key, $event)"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<!-- 单个复选框 -->
|
||||
<template v-else-if="field.type === 'checkbox'">
|
||||
<UBrowserCheckbox
|
||||
v-model="fieldValue[field.key]"
|
||||
:label="field.label"
|
||||
@update:model-value="updateValue(field.key, $event)"
|
||||
/>
|
||||
<!-- 是/否选择 -->
|
||||
<template v-else-if="field.type === 'boolean-toggle'">
|
||||
<div class="row items-center no-wrap">
|
||||
<q-badge class="q-pa-xs">{{ field.label }}</q-badge>
|
||||
<q-btn-toggle
|
||||
:model-value="fieldValue[field.key] ? 'true' : 'false'"
|
||||
:options="[
|
||||
{ label: '是', value: 'true' },
|
||||
{ label: '否', value: 'false' },
|
||||
]"
|
||||
dense
|
||||
flat
|
||||
no-caps
|
||||
spread
|
||||
class="button-group"
|
||||
@update:model-value="updateValue(field.key, $event === 'true')"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- 基本输入类型的处理 -->
|
||||
@@ -37,12 +54,9 @@
|
||||
<!-- 普通输入框 -->
|
||||
<template v-else>
|
||||
<VariableInput
|
||||
v-model="fieldValue[field.key]"
|
||||
:model-value="fieldValue[field.key]"
|
||||
:label="field.label"
|
||||
:command="{
|
||||
icon: field.icon,
|
||||
inputType: field.inputType,
|
||||
}"
|
||||
:icon="field.icon"
|
||||
@update:model-value="updateValue(field.key, $event)"
|
||||
/>
|
||||
</template>
|
||||
@@ -51,16 +65,6 @@
|
||||
<!-- 数字输入框 -->
|
||||
<template v-else-if="field.type === 'numInput'">
|
||||
<NumberInput
|
||||
v-model="fieldValue[field.key]"
|
||||
:label="field.label"
|
||||
:command="{ icon: field.icon }"
|
||||
@update:model-value="updateValue(field.key, $event)"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<!-- 文本区域 -->
|
||||
<template v-else-if="field.type === 'textarea'">
|
||||
<UBrowserTextarea
|
||||
v-model="fieldValue[field.key]"
|
||||
:label="field.label"
|
||||
:icon="field.icon"
|
||||
@@ -70,13 +74,20 @@
|
||||
|
||||
<!-- 选择框 -->
|
||||
<template v-else-if="field.type === 'select'">
|
||||
<UBrowserSelect
|
||||
v-model="fieldValue[field.key]"
|
||||
<q-select
|
||||
:model-value="fieldValue[field.key]"
|
||||
:label="field.label"
|
||||
:icon="field.icon"
|
||||
:options="field.options"
|
||||
dense
|
||||
filled
|
||||
emit-value
|
||||
map-options
|
||||
@update:model-value="updateValue(field.key, $event)"
|
||||
/>
|
||||
>
|
||||
<template v-slot:prepend>
|
||||
<q-icon :name="field.icon" />
|
||||
</template>
|
||||
</q-select>
|
||||
</template>
|
||||
|
||||
<!-- Cookie列表 -->
|
||||
@@ -106,20 +117,39 @@
|
||||
|
||||
<!-- 按钮组 -->
|
||||
<template v-else-if="field.type === 'button-toggle'">
|
||||
<UBrowserButtonToggle
|
||||
v-model="fieldValue[field.key]"
|
||||
:label="field.label"
|
||||
:options="field.options"
|
||||
@update:model-value="updateValue(field.key, $event)"
|
||||
/>
|
||||
<div class="row items-center no-wrap">
|
||||
<q-badge class="q-pa-xs">{{ field.label }}</q-badge>
|
||||
<q-btn-toggle
|
||||
:model-value="fieldValue[field.key]"
|
||||
:options="field.options"
|
||||
dense
|
||||
flat
|
||||
no-caps
|
||||
spread
|
||||
class="button-group"
|
||||
@update:model-value="updateValue(field.key, $event)"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- 设备尺寸 -->
|
||||
<template v-else-if="field.type === 'device-size'">
|
||||
<UBrowserDeviceSize
|
||||
v-model="fieldValue.size"
|
||||
@update:model-value="updateValue(field.key, $event)"
|
||||
/>
|
||||
<div class="row q-col-gutter-sm">
|
||||
<VariableInput
|
||||
v-model.number="fieldValue.size[key]"
|
||||
class="col-6"
|
||||
v-for="key in ['width', 'height']"
|
||||
:key="key"
|
||||
label="宽度"
|
||||
icon="width"
|
||||
@update:model-value="
|
||||
updateValue(field.key, {
|
||||
...fieldValue.size,
|
||||
[key]: $event,
|
||||
})
|
||||
"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- 带参数的函数输入 -->
|
||||
@@ -139,36 +169,25 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { defineComponent } from "vue";
|
||||
import { defineComponent, computed, ref, onMounted } from "vue";
|
||||
import { get, set } from "lodash";
|
||||
import UBrowserFunctionInput from "./UBrowserFunctionInput.vue";
|
||||
import UBrowserCheckbox from "./UBrowserCheckbox.vue";
|
||||
import UBrowserFileList from "./UBrowserFileList.vue";
|
||||
import UBrowserCookieList from "./UBrowserCookieList.vue";
|
||||
import UBrowserButtonToggle from "./UBrowserButtonToggle.vue";
|
||||
import UBrowserDeviceSize from "./UBrowserDeviceSize.vue";
|
||||
import UBrowserNamedParamList from "./UBrowserNamedParamList.vue";
|
||||
import UBrowserSelect from "./UBrowserSelect.vue";
|
||||
import UBrowserDeviceName from "./UBrowserDeviceName.vue";
|
||||
import UBrowserTextarea from "./UBrowserTextarea.vue";
|
||||
import VariableInput from "components/composer/ui/VariableInput.vue";
|
||||
import UBrowserCheckboxGroup from "./UBrowserCheckboxGroup.vue";
|
||||
import NumberInput from "components/composer/ui/NumberInput.vue";
|
||||
|
||||
export default defineComponent({
|
||||
name: "UBrowserOperation",
|
||||
components: {
|
||||
UBrowserFunctionInput,
|
||||
UBrowserCheckbox,
|
||||
UBrowserFileList,
|
||||
UBrowserCookieList,
|
||||
UBrowserButtonToggle,
|
||||
UBrowserDeviceSize,
|
||||
UBrowserNamedParamList,
|
||||
UBrowserSelect,
|
||||
UBrowserDeviceName,
|
||||
UBrowserTextarea,
|
||||
VariableInput,
|
||||
UBrowserCheckboxGroup,
|
||||
NumberInput,
|
||||
},
|
||||
props: {
|
||||
@@ -186,70 +205,62 @@ export default defineComponent({
|
||||
},
|
||||
},
|
||||
emits: ["update:configs"],
|
||||
data() {
|
||||
return {
|
||||
fieldValue: {},
|
||||
};
|
||||
},
|
||||
created() {
|
||||
// 初始化字段值,确保有默认值
|
||||
this.fields.forEach((field) => {
|
||||
const value = get(this.configs[this.action], field.key);
|
||||
// 根据字段类型设置适当的默认值
|
||||
let defaultValue;
|
||||
if (field.type === "checkbox-group") {
|
||||
defaultValue = field.defaultValue || [];
|
||||
} else if (field.type === "checkbox") {
|
||||
defaultValue = field.defaultValue || false;
|
||||
} else if (field.type === "function-with-params") {
|
||||
// 为function-with-params类型设置特殊的默认值结构
|
||||
this.fieldValue.function = value?.function || "";
|
||||
this.fieldValue.args = value?.args || [];
|
||||
return; // 跳过后续的赋值
|
||||
} else {
|
||||
defaultValue = field.defaultValue;
|
||||
}
|
||||
this.fieldValue[field.key] = value !== undefined ? value : defaultValue;
|
||||
setup(props, { emit }) {
|
||||
const fieldValue = ref({});
|
||||
|
||||
// 初始化字段值
|
||||
onMounted(() => {
|
||||
props.fields.forEach((field) => {
|
||||
const value = get(props.configs[props.action], field.key);
|
||||
// 根据字段类型设置适当的默认值
|
||||
if (field.type === "function-with-params") {
|
||||
fieldValue.value.function = value?.function || "";
|
||||
fieldValue.value.args = value?.args || [];
|
||||
return;
|
||||
}
|
||||
|
||||
const defaultValue =
|
||||
field.type === "checkbox-group"
|
||||
? []
|
||||
: field.type === "checkbox"
|
||||
? field.defaultValue || false
|
||||
: field.defaultValue;
|
||||
|
||||
fieldValue.value[field.key] = Array.isArray(value)
|
||||
? value
|
||||
: defaultValue;
|
||||
});
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
updateValue(key, value) {
|
||||
// 更新本地值
|
||||
this.fieldValue[key] = value;
|
||||
|
||||
// 创建新的配置对
|
||||
const newConfigs = { ...this.configs };
|
||||
if (!newConfigs[this.action]) {
|
||||
newConfigs[this.action] = {};
|
||||
// 更新值的方法
|
||||
const updateValue = (key, value) => {
|
||||
fieldValue.value[key] = value;
|
||||
|
||||
const newConfigs = { ...props.configs };
|
||||
if (!newConfigs[props.action]) {
|
||||
newConfigs[props.action] = {};
|
||||
}
|
||||
|
||||
// 使用 lodash 的 set 来处理嵌套路径
|
||||
set(newConfigs[this.action], key, value);
|
||||
set(newConfigs[props.action], key, value);
|
||||
emit("update:configs", newConfigs);
|
||||
};
|
||||
|
||||
// 发出更新事件
|
||||
this.$emit("update:configs", newConfigs);
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
// 监听配置变化
|
||||
configs: {
|
||||
deep: true,
|
||||
handler() {
|
||||
this.fields.forEach((field) => {
|
||||
const value = get(this.configs[this.action], field.key);
|
||||
if (field.type === "function-with-params") {
|
||||
// 为function-with-params类型设置特殊的更新逻辑
|
||||
this.fieldValue.function =
|
||||
value?.function || this.fieldValue.function || "";
|
||||
this.fieldValue.args = value?.args || this.fieldValue.args || [];
|
||||
return;
|
||||
}
|
||||
if (value !== undefined) {
|
||||
this.fieldValue[field.key] = value;
|
||||
}
|
||||
});
|
||||
},
|
||||
},
|
||||
return {
|
||||
fieldValue,
|
||||
updateValue,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.button-group {
|
||||
flex: 1;
|
||||
padding: 0 10px;
|
||||
}
|
||||
|
||||
.button-group :deep(.q-btn) {
|
||||
min-height: 24px;
|
||||
font-size: 12px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
<template>
|
||||
<q-select
|
||||
:model-value="modelValue"
|
||||
:label="label"
|
||||
:options="options"
|
||||
dense
|
||||
filled
|
||||
emit-value
|
||||
map-options
|
||||
@update:model-value="$emit('update:modelValue', $event)"
|
||||
>
|
||||
<template v-slot:prepend>
|
||||
<q-icon :name="icon" />
|
||||
</template>
|
||||
</q-select>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { defineComponent } from "vue";
|
||||
|
||||
export default defineComponent({
|
||||
name: "UBrowserSelect",
|
||||
props: {
|
||||
modelValue: {
|
||||
type: [String, Number],
|
||||
default: "",
|
||||
},
|
||||
label: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
options: {
|
||||
type: Array,
|
||||
required: true,
|
||||
},
|
||||
icon: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
},
|
||||
emits: ["update:modelValue"],
|
||||
});
|
||||
</script>
|
||||
@@ -1,38 +0,0 @@
|
||||
<template>
|
||||
<q-input
|
||||
:model-value="modelValue"
|
||||
:label="label"
|
||||
type="textarea"
|
||||
dense
|
||||
filled
|
||||
autogrow
|
||||
@update:model-value="$emit('update:modelValue', $event)"
|
||||
>
|
||||
<template v-slot:prepend>
|
||||
<q-icon :name="icon" />
|
||||
</template>
|
||||
</q-input>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { defineComponent } from "vue";
|
||||
|
||||
export default defineComponent({
|
||||
name: "UBrowserTextarea",
|
||||
props: {
|
||||
modelValue: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
label: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
icon: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
},
|
||||
emits: ["update:modelValue"],
|
||||
});
|
||||
</script>
|
||||
Reference in New Issue
Block a user