mirror of
https://github.com/fofolee/uTools-quickcommand.git
synced 2025-06-09 06:54:11 +08:00
重构ubrowser
This commit is contained in:
parent
827c702e50
commit
e082304c56
@ -33,7 +33,8 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="col-auto">
|
<div class="col-auto">
|
||||||
<q-select
|
<q-select
|
||||||
v-model="selectedUA"
|
:model-value="selectedUA"
|
||||||
|
@update:model-value="handleUAChange"
|
||||||
:options="userAgentOptions"
|
:options="userAgentOptions"
|
||||||
label="常用 UA"
|
label="常用 UA"
|
||||||
dense
|
dense
|
||||||
@ -66,11 +67,11 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { defineComponent } from "vue";
|
import { defineComponent, ref, computed } from "vue";
|
||||||
import { defaultUBrowserConfigs } from "js/composer/ubrowserConfig";
|
|
||||||
import { userAgent } from "js/options/httpOptions";
|
import { userAgent } from "js/options/httpOptions";
|
||||||
import VariableInput from "components/composer/ui/VariableInput.vue";
|
import VariableInput from "components/composer/ui/VariableInput.vue";
|
||||||
import NumberInput from "components/composer/ui/NumberInput.vue";
|
import NumberInput from "components/composer/ui/NumberInput.vue";
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: "UBrowserBasic",
|
name: "UBrowserBasic",
|
||||||
components: {
|
components: {
|
||||||
@ -83,37 +84,47 @@ export default defineComponent({
|
|||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
data() {
|
emits: ["update:configs"],
|
||||||
return {
|
setup(props, { emit }) {
|
||||||
selectedUA: null,
|
const selectedUA = ref(null);
|
||||||
localConfigs: defaultUBrowserConfigs.goto,
|
|
||||||
userAgentOptions: userAgent,
|
// 使用 computed 处理配置
|
||||||
|
const localConfigs = computed({
|
||||||
|
get: () => props.configs,
|
||||||
|
set: (val) => {
|
||||||
|
emit("update:configs", val);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// 更新配置
|
||||||
|
const updateConfigs = () => {
|
||||||
|
emit("update:configs", localConfigs.value);
|
||||||
};
|
};
|
||||||
},
|
|
||||||
created() {
|
// 处理 UA 选择
|
||||||
// 初始化本地配置
|
const handleUAChange = (val) => {
|
||||||
this.localConfigs = window.lodashM.cloneDeep(this.configs);
|
if (!val) return;
|
||||||
},
|
|
||||||
methods: {
|
const newConfigs = window.lodashM.cloneDeep(props.configs);
|
||||||
updateConfigs() {
|
if (!newConfigs.goto.headers) {
|
||||||
this.$emit("update:configs", window.lodashM.cloneDeep(this.localConfigs));
|
newConfigs.goto.headers = {};
|
||||||
},
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
configs: {
|
|
||||||
deep: true,
|
|
||||||
handler(newConfigs) {
|
|
||||||
this.localConfigs = window.lodashM.cloneDeep(newConfigs);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
selectedUA(value) {
|
|
||||||
if (value) {
|
|
||||||
this.localConfigs.goto.headers.userAgent.value = value;
|
|
||||||
this.localConfigs.goto.headers.userAgent.isString = true;
|
|
||||||
this.updateConfigs();
|
|
||||||
this.selectedUA = null;
|
|
||||||
}
|
}
|
||||||
},
|
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>
|
</script>
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
</q-tabs>
|
</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">
|
<q-tab-panel name="1" class="panel-content">
|
||||||
<UBrowserBasic :configs="configs" @update:configs="updateConfigs" />
|
<UBrowserBasic :configs="configs" @update:configs="updateConfigs" />
|
||||||
</q-tab-panel>
|
</q-tab-panel>
|
||||||
@ -23,8 +23,9 @@
|
|||||||
<q-tab-panel name="2" class="panel-content">
|
<q-tab-panel name="2" class="panel-content">
|
||||||
<UBrowserOperations
|
<UBrowserOperations
|
||||||
:configs="configs"
|
:configs="configs"
|
||||||
|
:selected-actions="selectedActions"
|
||||||
@update:configs="updateConfigs"
|
@update:configs="updateConfigs"
|
||||||
v-model:selected-actions="selectedActions"
|
@update:selected-actions="(val) => (selectedActions = val)"
|
||||||
@remove-action="removeAction"
|
@remove-action="removeAction"
|
||||||
/>
|
/>
|
||||||
</q-tab-panel>
|
</q-tab-panel>
|
||||||
@ -37,7 +38,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { defineComponent } from "vue";
|
import { defineComponent, ref, computed } from "vue";
|
||||||
import UBrowserBasic from "./UBrowserBasic.vue";
|
import UBrowserBasic from "./UBrowserBasic.vue";
|
||||||
import UBrowserOperations from "./UBrowserOperations.vue";
|
import UBrowserOperations from "./UBrowserOperations.vue";
|
||||||
import UBrowserRun from "./UBrowserRun.vue";
|
import UBrowserRun from "./UBrowserRun.vue";
|
||||||
@ -53,117 +54,115 @@ export default defineComponent({
|
|||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
modelValue: {
|
modelValue: {
|
||||||
type: String,
|
type: Object,
|
||||||
default: "",
|
required: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
emits: ["update:modelValue"],
|
emits: ["update:modelValue"],
|
||||||
data() {
|
setup(props, { emit }) {
|
||||||
return {
|
// 基础状态
|
||||||
step: "1",
|
const step = ref("1");
|
||||||
selectedActions: [],
|
const selectedActions = ref([]);
|
||||||
configs: window.lodashM.cloneDeep(defaultUBrowserConfigs),
|
|
||||||
|
// 初始化配置,确保包含 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,
|
||||||
},
|
},
|
||||||
methods: {
|
};
|
||||||
updateConfigs(newConfigs) {
|
localConfigs.value = newConfigs;
|
||||||
this.configs = newConfigs;
|
emit("update:modelValue", {
|
||||||
|
...props.modelValue,
|
||||||
|
argvs: newConfigs,
|
||||||
|
code: generateUBrowserCode(newConfigs, selectedActions.value),
|
||||||
|
});
|
||||||
},
|
},
|
||||||
removeAction(action) {
|
});
|
||||||
const newActions = this.selectedActions.filter((a) => a.id !== action.id);
|
|
||||||
this.selectedActions = newActions;
|
// 更新配置
|
||||||
const newConfigs = { ...this.configs };
|
const updateConfigs = (newConfigs) => {
|
||||||
|
argvs.value = window.lodashM.cloneDeep(newConfigs);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 移除操作
|
||||||
|
const removeAction = (action) => {
|
||||||
|
selectedActions.value = selectedActions.value.filter(
|
||||||
|
(a) => a.id !== action.id
|
||||||
|
);
|
||||||
|
const newConfigs = { ...argvs.value };
|
||||||
delete newConfigs[action.value];
|
delete newConfigs[action.value];
|
||||||
this.configs = newConfigs;
|
argvs.value = newConfigs;
|
||||||
},
|
};
|
||||||
},
|
|
||||||
watch: {
|
return {
|
||||||
configs: {
|
step,
|
||||||
deep: true,
|
selectedActions,
|
||||||
handler() {
|
configs: argvs,
|
||||||
this.$emit(
|
updateConfigs,
|
||||||
"update:modelValue",
|
removeAction,
|
||||||
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)
|
|
||||||
);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style>
|
||||||
.ubrowser-editor {
|
.ubrowser-editor {
|
||||||
width: 100%;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
min-height: 0;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ubrowser-tabs {
|
.ubrowser-tabs {
|
||||||
background: rgba(255, 255, 255, 0.8);
|
|
||||||
border-radius: 4px 4px 0 0;
|
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ubrowser-panels {
|
.ubrowser-panels {
|
||||||
background: rgba(255, 255, 255, 0.8);
|
|
||||||
border-radius: 0 0 4px 4px;
|
|
||||||
flex: 1;
|
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;
|
overflow: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 调整标签页样式 */
|
.panel-content {
|
||||||
|
padding: 16px;
|
||||||
|
min-height: 200px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ubrowser-panels :deep(.q-tab-panel) {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.ubrowser-tabs :deep(.q-tab) {
|
.ubrowser-tabs :deep(.q-tab) {
|
||||||
min-height: 36px;
|
min-height: 40px;
|
||||||
padding: 0 12px;
|
padding: 0 16px;
|
||||||
}
|
|
||||||
|
|
||||||
.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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.ubrowser-tabs :deep(.q-tab__icon) {
|
.ubrowser-tabs :deep(.q-tab__icon) {
|
||||||
font-size: 16px;
|
font-size: 20px;
|
||||||
margin: 0;
|
}
|
||||||
|
|
||||||
|
.ubrowser-tabs :deep(.q-tab__label) {
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 1.2;
|
||||||
|
margin-left: 8px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -106,20 +106,21 @@ export default defineComponent({
|
|||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
data() {
|
emits: ["remove-action", "update:selectedActions", "update:configs"],
|
||||||
|
setup() {
|
||||||
return {
|
return {
|
||||||
ubrowserOperationConfigs: ubrowserOperationConfigs,
|
ubrowserOperationConfigs,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
emits: ["remove-action", "update:selectedActions", "update:configs"],
|
|
||||||
methods: {
|
methods: {
|
||||||
moveAction(index, direction) {
|
moveAction(index, direction) {
|
||||||
const newIndex = index + direction;
|
const newIndex = index + direction;
|
||||||
if (newIndex >= 0 && newIndex < this.selectedActions.length) {
|
if (newIndex >= 0 && newIndex < this.selectedActions.length) {
|
||||||
const actions = [...this.selectedActions];
|
const actions = [...this.selectedActions];
|
||||||
const temp = actions[index];
|
[actions[index], actions[newIndex]] = [
|
||||||
actions[index] = actions[newIndex];
|
actions[newIndex],
|
||||||
actions[newIndex] = temp;
|
actions[index],
|
||||||
|
];
|
||||||
this.$emit("update:selectedActions", actions);
|
this.$emit("update:selectedActions", actions);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -127,11 +128,10 @@ export default defineComponent({
|
|||||||
const index = this.selectedActions.findIndex(
|
const index = this.selectedActions.findIndex(
|
||||||
(a) => a.value === action.value
|
(a) => a.value === action.value
|
||||||
);
|
);
|
||||||
|
|
||||||
if (index === -1) {
|
if (index === -1) {
|
||||||
// 添加操作
|
// 添加操作
|
||||||
this.$emit("update:selectedActions", [
|
const newAction = {
|
||||||
...this.selectedActions,
|
|
||||||
{
|
|
||||||
...action,
|
...action,
|
||||||
id: this.$root.getUniqueId(),
|
id: this.$root.getUniqueId(),
|
||||||
argv: "",
|
argv: "",
|
||||||
@ -139,7 +139,11 @@ export default defineComponent({
|
|||||||
useOutput: null,
|
useOutput: null,
|
||||||
cmd: action.value || action.cmd,
|
cmd: action.value || action.cmd,
|
||||||
value: action.value || action.cmd,
|
value: action.value || action.cmd,
|
||||||
},
|
};
|
||||||
|
|
||||||
|
this.$emit("update:selectedActions", [
|
||||||
|
...this.selectedActions,
|
||||||
|
newAction,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// 初始化配置对象
|
// 初始化配置对象
|
||||||
@ -148,7 +152,6 @@ export default defineComponent({
|
|||||||
const newConfigs = { ...this.configs };
|
const newConfigs = { ...this.configs };
|
||||||
if (!newConfigs[action.value]) {
|
if (!newConfigs[action.value]) {
|
||||||
newConfigs[action.value] = {};
|
newConfigs[action.value] = {};
|
||||||
}
|
|
||||||
// 设置默认值
|
// 设置默认值
|
||||||
config.forEach((field) => {
|
config.forEach((field) => {
|
||||||
if (field.defaultValue !== undefined) {
|
if (field.defaultValue !== undefined) {
|
||||||
@ -157,6 +160,7 @@ export default defineComponent({
|
|||||||
});
|
});
|
||||||
this.$emit("update:configs", newConfigs);
|
this.$emit("update:configs", newConfigs);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// 移除操作
|
// 移除操作
|
||||||
const newActions = [...this.selectedActions];
|
const newActions = [...this.selectedActions];
|
||||||
@ -167,7 +171,7 @@ export default defineComponent({
|
|||||||
getActionProps(action, key) {
|
getActionProps(action, key) {
|
||||||
return this.ubrowserOperationConfigs.find(
|
return this.ubrowserOperationConfigs.find(
|
||||||
(a) => a.value === action.value
|
(a) => a.value === action.value
|
||||||
)[key];
|
)?.[key];
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -155,7 +155,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { defineComponent } from "vue";
|
import { defineComponent, ref, computed } from "vue";
|
||||||
import NumberInput from "components/composer/ui/NumberInput.vue";
|
import NumberInput from "components/composer/ui/NumberInput.vue";
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
@ -170,24 +170,24 @@ export default defineComponent({
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
emits: ["update:configs"],
|
emits: ["update:configs"],
|
||||||
data() {
|
setup(props, { emit }) {
|
||||||
return {
|
const localConfigs = ref(window.lodashM.cloneDeep(props.configs));
|
||||||
localConfigs: window.lodashM.cloneDeep(this.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>
|
</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
|
<VariableInput
|
||||||
:model-value="cookie.name"
|
:model-value="cookie.name"
|
||||||
label="名称"
|
label="名称"
|
||||||
:command="{ icon: 'label' }"
|
icon="label"
|
||||||
@update:model-value="
|
@update:model-value="
|
||||||
(value) => handleUpdate(index, 'name', value)
|
(value) => handleUpdate(index, 'name', value)
|
||||||
"
|
"
|
||||||
@ -21,7 +21,7 @@
|
|||||||
<VariableInput
|
<VariableInput
|
||||||
:model-value="cookie.value"
|
:model-value="cookie.value"
|
||||||
label="值"
|
label="值"
|
||||||
:command="{ icon: 'edit' }"
|
icon="edit"
|
||||||
@update:model-value="
|
@update:model-value="
|
||||||
(value) => handleUpdate(index, 'value', value)
|
(value) => handleUpdate(index, 'value', value)
|
||||||
"
|
"
|
||||||
@ -64,20 +64,58 @@ export default defineComponent({
|
|||||||
props: {
|
props: {
|
||||||
modelValue: {
|
modelValue: {
|
||||||
type: Array,
|
type: Array,
|
||||||
default: () => [{ name: "", value: "" }],
|
default: () => [
|
||||||
|
{
|
||||||
|
name: {
|
||||||
|
value: "",
|
||||||
|
isString: true,
|
||||||
|
__varInputVal__: true,
|
||||||
|
},
|
||||||
|
value: {
|
||||||
|
value: "",
|
||||||
|
isString: true,
|
||||||
|
__varInputVal__: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
emits: ["update:modelValue"],
|
emits: ["update:modelValue"],
|
||||||
methods: {
|
methods: {
|
||||||
addCookie() {
|
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);
|
this.$emit("update:modelValue", newValue);
|
||||||
},
|
},
|
||||||
removeCookie(index) {
|
removeCookie(index) {
|
||||||
const newValue = [...this.modelValue];
|
const newValue = [...this.modelValue];
|
||||||
newValue.splice(index, 1);
|
newValue.splice(index, 1);
|
||||||
if (newValue.length === 0) {
|
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);
|
this.$emit("update:modelValue", newValue);
|
||||||
},
|
},
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
<div class="row q-col-gutter-sm">
|
<div class="row q-col-gutter-sm">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<VariableInput
|
<VariableInput
|
||||||
:command="{ icon: icon }"
|
icon="label"
|
||||||
:model-value="modelValue"
|
:model-value="modelValue"
|
||||||
:label="label"
|
:label="label"
|
||||||
@update:model-value="$emit('update:modelValue', $event)"
|
@update:model-value="$emit('update:modelValue', $event)"
|
||||||
@ -41,8 +41,12 @@ export default defineComponent({
|
|||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
modelValue: {
|
modelValue: {
|
||||||
type: String,
|
type: Object,
|
||||||
default: "",
|
default: () => ({
|
||||||
|
value: "",
|
||||||
|
isString: true,
|
||||||
|
__varInputVal__: true,
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
label: {
|
label: {
|
||||||
type: String,
|
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"],
|
emits: ["update:modelValue"],
|
||||||
methods: {
|
methods: {
|
||||||
addFile() {
|
addFile() {
|
||||||
const newValue = [...(this.modelValue || []), ""];
|
const newValue = [
|
||||||
|
...(this.modelValue || []),
|
||||||
|
{
|
||||||
|
value: "",
|
||||||
|
isString: true,
|
||||||
|
__varInputVal__: true,
|
||||||
|
},
|
||||||
|
];
|
||||||
this.$emit("update:modelValue", newValue);
|
this.$emit("update:modelValue", newValue);
|
||||||
},
|
},
|
||||||
removeFile(index) {
|
removeFile(index) {
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
<VariableInput
|
<VariableInput
|
||||||
:model-value="param.name"
|
:model-value="param.name"
|
||||||
label="参数名"
|
label="参数名"
|
||||||
:command="{ icon: 'label' }"
|
icon="label"
|
||||||
@update:model-value="(value) => handleUpdate(index, 'name', value)"
|
@update:model-value="(value) => handleUpdate(index, 'name', value)"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@ -18,7 +18,7 @@
|
|||||||
<VariableInput
|
<VariableInput
|
||||||
:model-value="param.value"
|
:model-value="param.value"
|
||||||
label="传递给参数的值"
|
label="传递给参数的值"
|
||||||
:command="{ icon: 'edit' }"
|
icon="edit"
|
||||||
@update:model-value="(value) => handleUpdate(index, 'value', value)"
|
@update:model-value="(value) => handleUpdate(index, 'value', value)"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@ -56,14 +56,41 @@ export default defineComponent({
|
|||||||
props: {
|
props: {
|
||||||
modelValue: {
|
modelValue: {
|
||||||
type: Array,
|
type: Array,
|
||||||
default: () => [{ name: "", value: "" }],
|
default: () => [
|
||||||
|
{
|
||||||
|
name: {
|
||||||
|
value: "",
|
||||||
|
isString: true,
|
||||||
|
__varInputVal__: true,
|
||||||
|
},
|
||||||
|
value: {
|
||||||
|
value: "",
|
||||||
|
isString: true,
|
||||||
|
__varInputVal__: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
label: String,
|
label: String,
|
||||||
},
|
},
|
||||||
emits: ["update:modelValue"],
|
emits: ["update:modelValue"],
|
||||||
methods: {
|
methods: {
|
||||||
addParam() {
|
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);
|
this.$emit("update:modelValue", newValue);
|
||||||
},
|
},
|
||||||
removeParam(index) {
|
removeParam(index) {
|
||||||
|
@ -7,20 +7,37 @@
|
|||||||
>
|
>
|
||||||
<!-- 复选框组 -->
|
<!-- 复选框组 -->
|
||||||
<template v-if="field.type === 'checkbox-group'">
|
<template v-if="field.type === 'checkbox-group'">
|
||||||
<UBrowserCheckboxGroup
|
<q-option-group
|
||||||
v-model="fieldValue[field.key]"
|
:model-value="
|
||||||
|
Array.isArray(fieldValue[field.key]) ? fieldValue[field.key] : []
|
||||||
|
"
|
||||||
:options="field.options"
|
:options="field.options"
|
||||||
|
type="checkbox"
|
||||||
|
class="row items-center"
|
||||||
|
inline
|
||||||
|
dense
|
||||||
@update:model-value="updateValue(field.key, $event)"
|
@update:model-value="updateValue(field.key, $event)"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<!-- 单个复选框 -->
|
<!-- 是/否选择 -->
|
||||||
<template v-else-if="field.type === 'checkbox'">
|
<template v-else-if="field.type === 'boolean-toggle'">
|
||||||
<UBrowserCheckbox
|
<div class="row items-center no-wrap">
|
||||||
v-model="fieldValue[field.key]"
|
<q-badge class="q-pa-xs">{{ field.label }}</q-badge>
|
||||||
:label="field.label"
|
<q-btn-toggle
|
||||||
@update:model-value="updateValue(field.key, $event)"
|
: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>
|
</template>
|
||||||
|
|
||||||
<!-- 基本输入类型的处理 -->
|
<!-- 基本输入类型的处理 -->
|
||||||
@ -37,12 +54,9 @@
|
|||||||
<!-- 普通输入框 -->
|
<!-- 普通输入框 -->
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<VariableInput
|
<VariableInput
|
||||||
v-model="fieldValue[field.key]"
|
:model-value="fieldValue[field.key]"
|
||||||
:label="field.label"
|
:label="field.label"
|
||||||
:command="{
|
:icon="field.icon"
|
||||||
icon: field.icon,
|
|
||||||
inputType: field.inputType,
|
|
||||||
}"
|
|
||||||
@update:model-value="updateValue(field.key, $event)"
|
@update:model-value="updateValue(field.key, $event)"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
@ -51,16 +65,6 @@
|
|||||||
<!-- 数字输入框 -->
|
<!-- 数字输入框 -->
|
||||||
<template v-else-if="field.type === 'numInput'">
|
<template v-else-if="field.type === 'numInput'">
|
||||||
<NumberInput
|
<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]"
|
v-model="fieldValue[field.key]"
|
||||||
:label="field.label"
|
:label="field.label"
|
||||||
:icon="field.icon"
|
:icon="field.icon"
|
||||||
@ -70,13 +74,20 @@
|
|||||||
|
|
||||||
<!-- 选择框 -->
|
<!-- 选择框 -->
|
||||||
<template v-else-if="field.type === 'select'">
|
<template v-else-if="field.type === 'select'">
|
||||||
<UBrowserSelect
|
<q-select
|
||||||
v-model="fieldValue[field.key]"
|
:model-value="fieldValue[field.key]"
|
||||||
:label="field.label"
|
:label="field.label"
|
||||||
:icon="field.icon"
|
|
||||||
:options="field.options"
|
:options="field.options"
|
||||||
|
dense
|
||||||
|
filled
|
||||||
|
emit-value
|
||||||
|
map-options
|
||||||
@update:model-value="updateValue(field.key, $event)"
|
@update:model-value="updateValue(field.key, $event)"
|
||||||
/>
|
>
|
||||||
|
<template v-slot:prepend>
|
||||||
|
<q-icon :name="field.icon" />
|
||||||
|
</template>
|
||||||
|
</q-select>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<!-- Cookie列表 -->
|
<!-- Cookie列表 -->
|
||||||
@ -106,20 +117,39 @@
|
|||||||
|
|
||||||
<!-- 按钮组 -->
|
<!-- 按钮组 -->
|
||||||
<template v-else-if="field.type === 'button-toggle'">
|
<template v-else-if="field.type === 'button-toggle'">
|
||||||
<UBrowserButtonToggle
|
<div class="row items-center no-wrap">
|
||||||
v-model="fieldValue[field.key]"
|
<q-badge class="q-pa-xs">{{ field.label }}</q-badge>
|
||||||
:label="field.label"
|
<q-btn-toggle
|
||||||
|
:model-value="fieldValue[field.key]"
|
||||||
:options="field.options"
|
:options="field.options"
|
||||||
|
dense
|
||||||
|
flat
|
||||||
|
no-caps
|
||||||
|
spread
|
||||||
|
class="button-group"
|
||||||
@update:model-value="updateValue(field.key, $event)"
|
@update:model-value="updateValue(field.key, $event)"
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<!-- 设备尺寸 -->
|
<!-- 设备尺寸 -->
|
||||||
<template v-else-if="field.type === 'device-size'">
|
<template v-else-if="field.type === 'device-size'">
|
||||||
<UBrowserDeviceSize
|
<div class="row q-col-gutter-sm">
|
||||||
v-model="fieldValue.size"
|
<VariableInput
|
||||||
@update:model-value="updateValue(field.key, $event)"
|
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>
|
</template>
|
||||||
|
|
||||||
<!-- 带参数的函数输入 -->
|
<!-- 带参数的函数输入 -->
|
||||||
@ -139,36 +169,25 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { defineComponent } from "vue";
|
import { defineComponent, computed, ref, onMounted } from "vue";
|
||||||
import { get, set } from "lodash";
|
import { get, set } from "lodash";
|
||||||
import UBrowserFunctionInput from "./UBrowserFunctionInput.vue";
|
import UBrowserFunctionInput from "./UBrowserFunctionInput.vue";
|
||||||
import UBrowserCheckbox from "./UBrowserCheckbox.vue";
|
|
||||||
import UBrowserFileList from "./UBrowserFileList.vue";
|
import UBrowserFileList from "./UBrowserFileList.vue";
|
||||||
import UBrowserCookieList from "./UBrowserCookieList.vue";
|
import UBrowserCookieList from "./UBrowserCookieList.vue";
|
||||||
import UBrowserButtonToggle from "./UBrowserButtonToggle.vue";
|
|
||||||
import UBrowserDeviceSize from "./UBrowserDeviceSize.vue";
|
|
||||||
import UBrowserNamedParamList from "./UBrowserNamedParamList.vue";
|
import UBrowserNamedParamList from "./UBrowserNamedParamList.vue";
|
||||||
import UBrowserSelect from "./UBrowserSelect.vue";
|
|
||||||
import UBrowserDeviceName from "./UBrowserDeviceName.vue";
|
import UBrowserDeviceName from "./UBrowserDeviceName.vue";
|
||||||
import UBrowserTextarea from "./UBrowserTextarea.vue";
|
|
||||||
import VariableInput from "components/composer/ui/VariableInput.vue";
|
import VariableInput from "components/composer/ui/VariableInput.vue";
|
||||||
import UBrowserCheckboxGroup from "./UBrowserCheckboxGroup.vue";
|
|
||||||
import NumberInput from "components/composer/ui/NumberInput.vue";
|
import NumberInput from "components/composer/ui/NumberInput.vue";
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: "UBrowserOperation",
|
name: "UBrowserOperation",
|
||||||
components: {
|
components: {
|
||||||
UBrowserFunctionInput,
|
UBrowserFunctionInput,
|
||||||
UBrowserCheckbox,
|
|
||||||
UBrowserFileList,
|
UBrowserFileList,
|
||||||
UBrowserCookieList,
|
UBrowserCookieList,
|
||||||
UBrowserButtonToggle,
|
|
||||||
UBrowserDeviceSize,
|
|
||||||
UBrowserNamedParamList,
|
UBrowserNamedParamList,
|
||||||
UBrowserSelect,
|
|
||||||
UBrowserDeviceName,
|
UBrowserDeviceName,
|
||||||
UBrowserTextarea,
|
|
||||||
VariableInput,
|
VariableInput,
|
||||||
UBrowserCheckboxGroup,
|
|
||||||
NumberInput,
|
NumberInput,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
@ -186,70 +205,62 @@ export default defineComponent({
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
emits: ["update:configs"],
|
emits: ["update:configs"],
|
||||||
data() {
|
setup(props, { emit }) {
|
||||||
return {
|
const fieldValue = ref({});
|
||||||
fieldValue: {},
|
|
||||||
};
|
// 初始化字段值
|
||||||
},
|
onMounted(() => {
|
||||||
created() {
|
props.fields.forEach((field) => {
|
||||||
// 初始化字段值,确保有默认值
|
const value = get(props.configs[props.action], field.key);
|
||||||
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;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
updateValue(key, value) {
|
|
||||||
// 更新本地值
|
|
||||||
this.fieldValue[key] = value;
|
|
||||||
|
|
||||||
// 创建新的配置对
|
|
||||||
const newConfigs = { ...this.configs };
|
|
||||||
if (!newConfigs[this.action]) {
|
|
||||||
newConfigs[this.action] = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
// 使用 lodash 的 set 来处理嵌套路径
|
|
||||||
set(newConfigs[this.action], key, value);
|
|
||||||
|
|
||||||
// 发出更新事件
|
|
||||||
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") {
|
if (field.type === "function-with-params") {
|
||||||
// 为function-with-params类型设置特殊的更新逻辑
|
fieldValue.value.function = value?.function || "";
|
||||||
this.fieldValue.function =
|
fieldValue.value.args = value?.args || [];
|
||||||
value?.function || this.fieldValue.function || "";
|
|
||||||
this.fieldValue.args = value?.args || this.fieldValue.args || [];
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (value !== undefined) {
|
|
||||||
this.fieldValue[field.key] = value;
|
const defaultValue =
|
||||||
}
|
field.type === "checkbox-group"
|
||||||
|
? []
|
||||||
|
: field.type === "checkbox"
|
||||||
|
? field.defaultValue || false
|
||||||
|
: field.defaultValue;
|
||||||
|
|
||||||
|
fieldValue.value[field.key] = Array.isArray(value)
|
||||||
|
? value
|
||||||
|
: defaultValue;
|
||||||
});
|
});
|
||||||
},
|
});
|
||||||
},
|
|
||||||
|
// 更新值的方法
|
||||||
|
const updateValue = (key, value) => {
|
||||||
|
fieldValue.value[key] = value;
|
||||||
|
|
||||||
|
const newConfigs = { ...props.configs };
|
||||||
|
if (!newConfigs[props.action]) {
|
||||||
|
newConfigs[props.action] = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
set(newConfigs[props.action], key, value);
|
||||||
|
emit("update:configs", newConfigs);
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
fieldValue,
|
||||||
|
updateValue,
|
||||||
|
};
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
</script>
|
</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>
|
|
@ -4,6 +4,7 @@
|
|||||||
*/
|
*/
|
||||||
const customComponentGuide = {
|
const customComponentGuide = {
|
||||||
description: "创建自定义命令组件的完整流程",
|
description: "创建自定义命令组件的完整流程",
|
||||||
|
important: "创建过程中严禁删除、修改任何已有的函数或对象",
|
||||||
steps: {
|
steps: {
|
||||||
"1. Backend Interface": {
|
"1. Backend Interface": {
|
||||||
location: "plugin/lib/quickcomposer/xxx/yyy.js",
|
location: "plugin/lib/quickcomposer/xxx/yyy.js",
|
||||||
|
@ -4,285 +4,358 @@
|
|||||||
* @param {Array} selectedActions 已选择的操作列表
|
* @param {Array} selectedActions 已选择的操作列表
|
||||||
* @returns {string} 生成的代码
|
* @returns {string} 生成的代码
|
||||||
*/
|
*/
|
||||||
import { defaultUBrowserConfigs } from "js/composer/ubrowserConfig";
|
import { stringifyObject, stringifyWithType } from "./formatString";
|
||||||
|
|
||||||
export function generateUBrowserCode(configs, selectedActions) {
|
// 生成 goto 参数字符串
|
||||||
let code = "utools.ubrowser";
|
function generateGotoArgs(goto) {
|
||||||
|
const args = [];
|
||||||
|
|
||||||
// 基础参数
|
// URL
|
||||||
// if (configs.useragent.value) {
|
const urlStr = stringifyWithType(goto.url);
|
||||||
// code += `\n .useragent('${configs.useragent.value}')`;
|
args.push(urlStr);
|
||||||
// }
|
|
||||||
|
|
||||||
if (configs.goto.url) {
|
// Headers
|
||||||
let gotoOptionsStr = `\n .goto(\n`;
|
if (goto.headers?.Referer?.value || goto.headers?.userAgent?.value) {
|
||||||
gotoOptionsStr += `${configs.goto.url}`;
|
const headers = {};
|
||||||
|
if (goto.headers.Referer?.value) {
|
||||||
if (configs.goto.headers.Referer || configs.goto.headers.userAgent) {
|
headers.Referer = goto.headers.Referer;
|
||||||
gotoOptionsStr += ",\n{";
|
|
||||||
if (configs.goto.headers.Referer) {
|
|
||||||
gotoOptionsStr += `\nReferer: ${configs.goto.headers.Referer}`;
|
|
||||||
}
|
}
|
||||||
if (configs.goto.headers.userAgent) {
|
if (goto.headers.userAgent?.value) {
|
||||||
gotoOptionsStr += `${
|
headers.userAgent = goto.headers.userAgent;
|
||||||
configs.goto.headers.Referer ? "," : ""
|
|
||||||
}\nuserAgent: ${configs.goto.headers.userAgent}`;
|
|
||||||
}
|
}
|
||||||
gotoOptionsStr += "\n}";
|
console.log("Headers:", JSON.stringify(headers, null, 2));
|
||||||
|
args.push(stringifyObject(headers, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (configs.goto.timeout !== 60000) {
|
// Timeout
|
||||||
gotoOptionsStr += `,\n${configs.goto.timeout}`;
|
if (goto.timeout !== 60000) {
|
||||||
|
args.push(goto.timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
gotoOptionsStr += "\n)";
|
return args.join(", ");
|
||||||
code += gotoOptionsStr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 浏览器操作
|
// 生成 run 参数字符串
|
||||||
selectedActions.forEach((action) => {
|
function generateRunArgs(run) {
|
||||||
const config = configs[action.value];
|
const options = {};
|
||||||
switch (action.value) {
|
const defaultValues = {
|
||||||
|
show: true,
|
||||||
|
center: true,
|
||||||
|
alwaysOnTop: false,
|
||||||
|
fullscreen: false,
|
||||||
|
fullscreenable: true,
|
||||||
|
resizable: true,
|
||||||
|
movable: true,
|
||||||
|
minimizable: true,
|
||||||
|
maximizable: true,
|
||||||
|
enableLargerThanScreen: false,
|
||||||
|
opacity: 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
// 窗口显示控制
|
||||||
|
if (run.show !== undefined && run.show !== defaultValues.show)
|
||||||
|
options.show = run.show;
|
||||||
|
if (run.center !== undefined && run.center !== defaultValues.center)
|
||||||
|
options.center = run.center;
|
||||||
|
if (
|
||||||
|
run.alwaysOnTop !== undefined &&
|
||||||
|
run.alwaysOnTop !== defaultValues.alwaysOnTop
|
||||||
|
)
|
||||||
|
options.alwaysOnTop = run.alwaysOnTop;
|
||||||
|
if (
|
||||||
|
run.fullscreen !== undefined &&
|
||||||
|
run.fullscreen !== defaultValues.fullscreen
|
||||||
|
)
|
||||||
|
options.fullscreen = run.fullscreen;
|
||||||
|
if (
|
||||||
|
run.fullscreenable !== undefined &&
|
||||||
|
run.fullscreenable !== defaultValues.fullscreenable
|
||||||
|
)
|
||||||
|
options.fullscreenable = run.fullscreenable;
|
||||||
|
|
||||||
|
// 窗口尺寸和位置 - 只有设置了值才添加
|
||||||
|
if (run.width !== undefined && run.width > 0) options.width = run.width;
|
||||||
|
if (run.height !== undefined && run.height > 0) options.height = run.height;
|
||||||
|
if (run.x !== undefined && run.x !== 0) options.x = run.x;
|
||||||
|
if (run.y !== undefined && run.y !== 0) options.y = run.y;
|
||||||
|
|
||||||
|
// 最大最小尺寸 - 只有设置了值才添加
|
||||||
|
if (run.minWidth !== undefined && run.minWidth > 0)
|
||||||
|
options.minWidth = run.minWidth;
|
||||||
|
if (run.minHeight !== undefined && run.minHeight > 0)
|
||||||
|
options.minHeight = run.minHeight;
|
||||||
|
if (run.maxWidth !== undefined && run.maxWidth > 0)
|
||||||
|
options.maxWidth = run.maxWidth;
|
||||||
|
if (run.maxHeight !== undefined && run.maxHeight > 0)
|
||||||
|
options.maxHeight = run.maxHeight;
|
||||||
|
|
||||||
|
// 窗口行为控制
|
||||||
|
if (run.resizable !== undefined && run.resizable !== defaultValues.resizable)
|
||||||
|
options.resizable = run.resizable;
|
||||||
|
if (run.movable !== undefined && run.movable !== defaultValues.movable)
|
||||||
|
options.movable = run.movable;
|
||||||
|
if (
|
||||||
|
run.minimizable !== undefined &&
|
||||||
|
run.minimizable !== defaultValues.minimizable
|
||||||
|
)
|
||||||
|
options.minimizable = run.minimizable;
|
||||||
|
if (
|
||||||
|
run.maximizable !== undefined &&
|
||||||
|
run.maximizable !== defaultValues.maximizable
|
||||||
|
)
|
||||||
|
options.maximizable = run.maximizable;
|
||||||
|
if (
|
||||||
|
run.enableLargerThanScreen !== undefined &&
|
||||||
|
run.enableLargerThanScreen !== defaultValues.enableLargerThanScreen
|
||||||
|
)
|
||||||
|
options.enableLargerThanScreen = run.enableLargerThanScreen;
|
||||||
|
|
||||||
|
// 透明度 - 只有不是1时才添加
|
||||||
|
if (run.opacity !== undefined && run.opacity !== defaultValues.opacity)
|
||||||
|
options.opacity = run.opacity;
|
||||||
|
|
||||||
|
// 其他参数 - 只有设置了值才添加
|
||||||
|
if (run.headless) options.headless = run.headless;
|
||||||
|
if (run.devtools) options.devtools = run.devtools;
|
||||||
|
if (run.timeout && run.timeout !== 60000) options.timeout = run.timeout;
|
||||||
|
if (run.proxy) options.proxy = run.proxy;
|
||||||
|
if (run.viewport) options.viewport = run.viewport;
|
||||||
|
|
||||||
|
return Object.keys(options).length ? stringifyObject(options) : "";
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生成操作参数字符串
|
||||||
|
function generateActionArgs(action, config) {
|
||||||
|
console.log(
|
||||||
|
"Generating args for action:",
|
||||||
|
action,
|
||||||
|
"config:",
|
||||||
|
JSON.stringify(config, null, 2)
|
||||||
|
);
|
||||||
|
if (!config) return "";
|
||||||
|
|
||||||
|
let result;
|
||||||
|
switch (action) {
|
||||||
case "wait":
|
case "wait":
|
||||||
if (config.type === "time" && config.time) {
|
result = generateWaitArgs(config);
|
||||||
code += `\n .wait(${config.time})`;
|
|
||||||
} else if (config.type === "selector" && config.selector) {
|
|
||||||
code += `\n .wait(${config.selector}${
|
|
||||||
config.timeout !== 60000 ? `, ${config.timeout}` : ""
|
|
||||||
})`;
|
|
||||||
} else if (config.type === "function" && config.function) {
|
|
||||||
const functionBody = config.function.trim();
|
|
||||||
if (config.args?.length) {
|
|
||||||
const params = config.args.map((arg) => arg.name).join(", ");
|
|
||||||
const functionCode = `(${params}) => {\n ${functionBody} \n}`;
|
|
||||||
const args = `, ${config.timeout || 60000}, ${config.args
|
|
||||||
.map((arg) => JSON.stringify(arg.value))
|
|
||||||
.join(", ")}`;
|
|
||||||
code += `\n .wait(${functionCode}${args})`;
|
|
||||||
} else {
|
|
||||||
const functionCode = `() => {\n ${functionBody} \n}`;
|
|
||||||
code += `\n .wait(${functionCode}${
|
|
||||||
config.timeout !== 60000 ? `, ${config.timeout}` : ""
|
|
||||||
})`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "click":
|
case "click":
|
||||||
if (config.selector) {
|
|
||||||
code += `\n .click(${config.selector})`;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "css":
|
|
||||||
if (config.value) {
|
|
||||||
code += `\n .css(${config.value})`;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "press":
|
|
||||||
if (config.key) {
|
|
||||||
const modifiers = config.modifiers.length
|
|
||||||
? `, ${JSON.stringify(config.modifiers)}`
|
|
||||||
: "";
|
|
||||||
code += `\n .press(${config.key}${modifiers})`;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "paste":
|
|
||||||
if (config.text) {
|
|
||||||
code += `\n .paste(${config.text})`;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "screenshot":
|
|
||||||
if (config.selector) {
|
|
||||||
code += `\n .screenshot(${config.selector}${
|
|
||||||
config.savePath ? `, '${config.savePath}'` : ""
|
|
||||||
})`;
|
|
||||||
} else if (config.rect) {
|
|
||||||
code += `\n .screenshot(${JSON.stringify(config.rect)}${
|
|
||||||
config.savePath ? `, ${config.savePath}` : ""
|
|
||||||
})`;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "pdf":
|
|
||||||
if (config.savePath) {
|
|
||||||
code += `\n .pdf(${config.savePath}${
|
|
||||||
config.options ? `, ${JSON.stringify(config.options)}` : ""
|
|
||||||
})`;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "device":
|
|
||||||
if (config.type === "preset" && config.deviceName) {
|
|
||||||
code += `\n .device(${config.deviceName})`;
|
|
||||||
} else if (config.type === "custom") {
|
|
||||||
let deviceOptionsStr = `\n .device(\n{`;
|
|
||||||
if (config.size) {
|
|
||||||
deviceOptionsStr += `\nsize: ${JSON.stringify(config.size)}`;
|
|
||||||
}
|
|
||||||
if (config.useragent) {
|
|
||||||
deviceOptionsStr += `${config.size ? "," : ""}\nuserAgent: ${
|
|
||||||
config.useragent
|
|
||||||
}`;
|
|
||||||
}
|
|
||||||
deviceOptionsStr += "\n}";
|
|
||||||
code += deviceOptionsStr + "\n)";
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "cookies":
|
|
||||||
if (config.name) {
|
|
||||||
code += `\n .cookies(${config.name})`;
|
|
||||||
} else {
|
|
||||||
code += `\n .cookies()`;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "setCookies":
|
|
||||||
if (config.items?.length) {
|
|
||||||
let cookiesStr = `\n .setCookies([\n`;
|
|
||||||
config.items.forEach((item, index) => {
|
|
||||||
cookiesStr += " {";
|
|
||||||
if (item.name) cookiesStr += `\n name: ${item.name}`;
|
|
||||||
if (item.value)
|
|
||||||
cookiesStr += `${item.name ? "," : ""}\n value: ${
|
|
||||||
item.value
|
|
||||||
}}`;
|
|
||||||
if (index < config.items.length - 1) cookiesStr += ",";
|
|
||||||
cookiesStr += "\n";
|
|
||||||
});
|
|
||||||
cookiesStr += " ])";
|
|
||||||
code += cookiesStr;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "removeCookies":
|
|
||||||
if (config.name) {
|
|
||||||
code += `\n .removeCookies(${config.name})`;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "clearCookies":
|
|
||||||
code += `\n .clearCookies(${config.url || ""})`;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "evaluate":
|
|
||||||
if (config.function) {
|
|
||||||
const functionBody = config.function.trim();
|
|
||||||
if (config.args?.length) {
|
|
||||||
const params = config.args.map((arg) => arg.name).join(", ");
|
|
||||||
const functionCode = `(${params}) => {\n ${functionBody} \n}`;
|
|
||||||
const args = `, ${config.args
|
|
||||||
.map((arg) => JSON.stringify(arg.value))
|
|
||||||
.join(", ")}`;
|
|
||||||
code += `\n .evaluate(${functionCode}${args})`;
|
|
||||||
} else {
|
|
||||||
const functionCode = `() => {\n ${functionBody} \n}`;
|
|
||||||
code += `\n .evaluate(${functionCode})`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "when":
|
|
||||||
if (config.condition) {
|
|
||||||
code += `\n .when(${config.condition})`;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "mousedown":
|
case "mousedown":
|
||||||
case "mouseup":
|
case "mouseup":
|
||||||
if (config.selector) {
|
|
||||||
code += `\n .${action.value}(${config.selector})`;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "file":
|
|
||||||
if (config.selector && config.files?.length) {
|
|
||||||
let filesStr = `\n .file(${config.selector}, [\n`;
|
|
||||||
config.files.forEach((file, index) => {
|
|
||||||
filesStr += ` ${file}`;
|
|
||||||
if (index < config.files.length - 1) filesStr += ",\n";
|
|
||||||
});
|
|
||||||
filesStr += "\n ])";
|
|
||||||
code += filesStr;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "value":
|
|
||||||
if (config.selector) {
|
|
||||||
code += `\n .value(${config.selector}, ${config.value})`;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "check":
|
|
||||||
if (config.selector) {
|
|
||||||
code += `\n .check(${config.selector}${
|
|
||||||
config.checked !== undefined ? `, ${config.checked}` : ""
|
|
||||||
})`;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "focus":
|
case "focus":
|
||||||
if (config.selector) {
|
result = stringifyWithType(config.selector);
|
||||||
code += `\n .focus(${config.selector})`;
|
break;
|
||||||
}
|
case "css":
|
||||||
|
case "paste":
|
||||||
|
result = stringifyWithType(config.value);
|
||||||
|
break;
|
||||||
|
case "press":
|
||||||
|
result = generatePressArgs(config);
|
||||||
|
break;
|
||||||
|
case "screenshot":
|
||||||
|
result = generateScreenshotArgs(config);
|
||||||
|
break;
|
||||||
|
case "pdf":
|
||||||
|
result = generatePdfArgs(config);
|
||||||
|
break;
|
||||||
|
case "device":
|
||||||
|
result = generateDeviceArgs(config);
|
||||||
|
break;
|
||||||
|
case "cookies":
|
||||||
|
case "removeCookies":
|
||||||
|
result = stringifyWithType(config.name);
|
||||||
|
break;
|
||||||
|
case "setCookies":
|
||||||
|
result = generateSetCookiesArgs(config);
|
||||||
|
break;
|
||||||
|
case "evaluate":
|
||||||
|
result = generateEvaluateArgs(config);
|
||||||
|
break;
|
||||||
|
case "when":
|
||||||
|
result = generateWhenArgs(config);
|
||||||
|
break;
|
||||||
|
case "file":
|
||||||
|
result = generateFileArgs(config);
|
||||||
|
break;
|
||||||
|
case "value":
|
||||||
|
result = generateValueArgs(config);
|
||||||
|
break;
|
||||||
|
case "check":
|
||||||
|
result = generateCheckArgs(config);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "scroll":
|
case "scroll":
|
||||||
if (config.type === "element" && config.selector) {
|
result = generateScrollArgs(config);
|
||||||
code += `\n .scroll(${config.selector})`;
|
|
||||||
} else if (config.type === "position") {
|
|
||||||
if (config.x !== undefined && config.y !== undefined) {
|
|
||||||
code += `\n .scroll(${config.x}, ${config.y})`;
|
|
||||||
} else if (config.y !== undefined) {
|
|
||||||
code += `\n .scroll(${config.y})`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "download":
|
case "download":
|
||||||
if (config.url) {
|
result = generateDownloadArgs(config);
|
||||||
code += `\n .download(${config.url}${
|
|
||||||
config.savePath ? `, ${config.savePath}` : ""
|
|
||||||
})`;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "hide":
|
|
||||||
case "show":
|
|
||||||
code += `\n .${action.value}()`;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "devTools":
|
case "devTools":
|
||||||
if (config.mode) {
|
result = stringifyWithType(config.mode);
|
||||||
code += `\n .devTools(${config.mode})`;
|
|
||||||
} else {
|
|
||||||
code += `\n .devTools()`;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
result = "";
|
||||||
}
|
}
|
||||||
|
console.log(
|
||||||
|
"Generated args for action:",
|
||||||
|
action,
|
||||||
|
"result:",
|
||||||
|
JSON.stringify(result)
|
||||||
|
);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生成 wait 参数字符串
|
||||||
|
function generateWaitArgs(config) {
|
||||||
|
switch (config.type) {
|
||||||
|
case "selector":
|
||||||
|
return stringifyWithType(config.selector);
|
||||||
|
case "function":
|
||||||
|
return config.function;
|
||||||
|
case "time":
|
||||||
|
return config.time;
|
||||||
|
default:
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生成 press 参数字符串
|
||||||
|
function generatePressArgs(config) {
|
||||||
|
const args = [stringifyWithType(config.key)];
|
||||||
|
if (config.modifiers?.length) {
|
||||||
|
args.push(JSON.stringify(config.modifiers));
|
||||||
|
}
|
||||||
|
return args.join(", ");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生成 screenshot 参数字符串
|
||||||
|
function generateScreenshotArgs(config) {
|
||||||
|
const args = [];
|
||||||
|
if (config.rect) {
|
||||||
|
args.push(stringifyObject(config.rect));
|
||||||
|
} else if (config.selector) {
|
||||||
|
args.push(stringifyWithType(config.selector));
|
||||||
|
}
|
||||||
|
if (config.savePath) {
|
||||||
|
args.push(stringifyWithType(config.savePath));
|
||||||
|
}
|
||||||
|
return args.join(", ");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生成 pdf 参数字符串
|
||||||
|
function generatePdfArgs(config) {
|
||||||
|
const args = [];
|
||||||
|
if (config.savePath) {
|
||||||
|
args.push(stringifyWithType(config.savePath));
|
||||||
|
}
|
||||||
|
if (config.options) {
|
||||||
|
args.push(stringifyObject(config.options));
|
||||||
|
}
|
||||||
|
return args.join(", ");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生成 device 参数字符串
|
||||||
|
function generateDeviceArgs(config) {
|
||||||
|
if (config.type === "preset") {
|
||||||
|
return stringifyWithType(config.deviceName);
|
||||||
|
} else {
|
||||||
|
const options = {};
|
||||||
|
if (config.size) options.size = config.size;
|
||||||
|
if (config.useragent) options.userAgent = config.useragent;
|
||||||
|
return stringifyObject(options);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生成 setCookies 参数字符串
|
||||||
|
function generateSetCookiesArgs(config) {
|
||||||
|
if (!config.items?.length) return "[]";
|
||||||
|
return stringifyObject(config.items);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生成 evaluate 参数字符串
|
||||||
|
function generateEvaluateArgs(config) {
|
||||||
|
const args = [config.function];
|
||||||
|
if (config.args?.length) {
|
||||||
|
args.push(...config.args.map(stringifyWithType));
|
||||||
|
}
|
||||||
|
return args.join(", ");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生成 when 参数字符串
|
||||||
|
function generateWhenArgs(config) {
|
||||||
|
if (config.type === "function") {
|
||||||
|
return config.function;
|
||||||
|
} else {
|
||||||
|
return stringifyWithType(config.selector);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生成 file 参数字符串
|
||||||
|
function generateFileArgs(config) {
|
||||||
|
const args = [stringifyWithType(config.selector)];
|
||||||
|
if (config.files) {
|
||||||
|
args.push(stringifyObject(config.files));
|
||||||
|
}
|
||||||
|
return args.join(", ");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生成 value 参数字符串
|
||||||
|
function generateValueArgs(config) {
|
||||||
|
return `${stringifyWithType(config.selector)}, ${stringifyWithType(
|
||||||
|
config.value
|
||||||
|
)}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生成 check 参数字符串
|
||||||
|
function generateCheckArgs(config) {
|
||||||
|
return `${stringifyWithType(config.selector)}, ${config.checked}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生成 scroll 参数字符串
|
||||||
|
function generateScrollArgs(config) {
|
||||||
|
if (config.type === "element") {
|
||||||
|
return stringifyWithType(config.selector);
|
||||||
|
} else {
|
||||||
|
if (config.x !== undefined) {
|
||||||
|
return `${config.x}, ${config.y}`;
|
||||||
|
} else {
|
||||||
|
return String(config.y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生成 download 参数字符串
|
||||||
|
function generateDownloadArgs(config) {
|
||||||
|
const args = [stringifyWithType(config.url)];
|
||||||
|
if (config.savePath) {
|
||||||
|
args.push(stringifyWithType(config.savePath));
|
||||||
|
}
|
||||||
|
return args.join(", ");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生成完整的 ubrowser 代码
|
||||||
|
export function generateUBrowserCode(configs, selectedActions) {
|
||||||
|
const lines = [];
|
||||||
|
const indent = " ";
|
||||||
|
|
||||||
|
// 添加 goto 参数
|
||||||
|
if (configs.goto) {
|
||||||
|
const gotoArgs = generateGotoArgs(configs.goto);
|
||||||
|
lines.push(`${indent}goto(${gotoArgs}),`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加选中的操作
|
||||||
|
if (selectedActions?.length) {
|
||||||
|
selectedActions.forEach((action) => {
|
||||||
|
const args = generateActionArgs(action.value, configs[action.value]);
|
||||||
|
lines.push(`${indent}${action.value}(${args}),`);
|
||||||
});
|
});
|
||||||
|
|
||||||
// 运行参数
|
|
||||||
const runOptions = {};
|
|
||||||
Object.entries(configs.run).forEach(([key, value]) => {
|
|
||||||
if (
|
|
||||||
value !== undefined &&
|
|
||||||
value !== null &&
|
|
||||||
value !== defaultUBrowserConfigs.run[key]
|
|
||||||
) {
|
|
||||||
runOptions[key] = value;
|
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
|
||||||
code += `\n .run(${
|
// 添加 run 参数
|
||||||
Object.keys(runOptions).length
|
const runArgs = generateRunArgs(configs.run || {});
|
||||||
? `\n${JSON.stringify(runOptions, null, 2).replace(/\n/g, "\n ")}`
|
const runLine = runArgs ? `${indent}run(${runArgs})` : `${indent}run()`;
|
||||||
: ""
|
lines.push(runLine);
|
||||||
})`;
|
|
||||||
|
|
||||||
return code;
|
// 生成最终代码
|
||||||
|
return `utools.ubrowser\n${lines.join("\n")}`;
|
||||||
}
|
}
|
||||||
|
@ -76,7 +76,7 @@ export const ubrowserOperationConfigs = [
|
|||||||
key: "value",
|
key: "value",
|
||||||
label: "注入的CSS样式",
|
label: "注入的CSS样式",
|
||||||
icon: "style",
|
icon: "style",
|
||||||
type: "textarea",
|
type: "varInput",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
icon: "style",
|
icon: "style",
|
||||||
@ -424,7 +424,7 @@ export const ubrowserOperationConfigs = [
|
|||||||
{
|
{
|
||||||
key: "checked",
|
key: "checked",
|
||||||
label: "选中状态",
|
label: "选中状态",
|
||||||
type: "checkbox",
|
type: "boolean-toggle",
|
||||||
defaultValue: false,
|
defaultValue: false,
|
||||||
width: 4,
|
width: 4,
|
||||||
},
|
},
|
||||||
@ -564,9 +564,6 @@ const defaultUBrowserRunConfigs = {
|
|||||||
// ubrowser 默认配置 基础参数-浏览器操作-运行参数
|
// ubrowser 默认配置 基础参数-浏览器操作-运行参数
|
||||||
export const defaultUBrowserConfigs = {
|
export const defaultUBrowserConfigs = {
|
||||||
// 基础参数
|
// 基础参数
|
||||||
useragent: {
|
|
||||||
value: "",
|
|
||||||
},
|
|
||||||
goto: {
|
goto: {
|
||||||
url: {
|
url: {
|
||||||
value: "",
|
value: "",
|
||||||
@ -593,82 +590,183 @@ export const defaultUBrowserConfigs = {
|
|||||||
timeout: 60000,
|
timeout: 60000,
|
||||||
},
|
},
|
||||||
click: {
|
click: {
|
||||||
selector: "",
|
selector: {
|
||||||
|
value: "",
|
||||||
|
isString: true,
|
||||||
|
__varInputVal__: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
css: {
|
css: {
|
||||||
|
value: {
|
||||||
value: "",
|
value: "",
|
||||||
|
isString: true,
|
||||||
|
__varInputVal__: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
press: {
|
press: {
|
||||||
key: "",
|
key: {
|
||||||
|
value: "",
|
||||||
|
isString: true,
|
||||||
|
__varInputVal__: true,
|
||||||
|
},
|
||||||
modifiers: [],
|
modifiers: [],
|
||||||
},
|
},
|
||||||
paste: {
|
paste: {
|
||||||
text: "",
|
text: {
|
||||||
|
value: "",
|
||||||
|
isString: true,
|
||||||
|
__varInputVal__: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
screenshot: {
|
screenshot: {
|
||||||
selector: "",
|
selector: {
|
||||||
|
value: "",
|
||||||
|
isString: true,
|
||||||
|
__varInputVal__: true,
|
||||||
|
},
|
||||||
rect: { x: 0, y: 0, width: 0, height: 0 },
|
rect: { x: 0, y: 0, width: 0, height: 0 },
|
||||||
savePath: "",
|
savePath: {
|
||||||
|
value: "",
|
||||||
|
isString: true,
|
||||||
|
__varInputVal__: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
pdf: {
|
pdf: {
|
||||||
options: {
|
options: {
|
||||||
marginsType: 0,
|
marginsType: 0,
|
||||||
pageSize: "A4",
|
pageSize: "A4",
|
||||||
},
|
},
|
||||||
savePath: "",
|
savePath: {
|
||||||
|
value: "",
|
||||||
|
isString: true,
|
||||||
|
__varInputVal__: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
device: {
|
device: {
|
||||||
size: { width: 1280, height: 800 },
|
size: { width: 1280, height: 800 },
|
||||||
useragent: "",
|
useragent: {
|
||||||
|
value: "",
|
||||||
|
isString: true,
|
||||||
|
__varInputVal__: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
cookies: {
|
cookies: {
|
||||||
name: "",
|
name: {
|
||||||
|
value: "",
|
||||||
|
isString: true,
|
||||||
|
__varInputVal__: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
setCookies: {
|
setCookies: {
|
||||||
items: [{ name: "", value: "" }],
|
items: [
|
||||||
|
{
|
||||||
|
name: {
|
||||||
|
value: "",
|
||||||
|
isString: true,
|
||||||
|
__varInputVal__: true,
|
||||||
|
},
|
||||||
|
value: {
|
||||||
|
value: "",
|
||||||
|
isString: true,
|
||||||
|
__varInputVal__: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
removeCookies: {
|
removeCookies: {
|
||||||
name: "",
|
name: {
|
||||||
|
value: "",
|
||||||
|
isString: true,
|
||||||
|
__varInputVal__: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
clearCookies: {
|
clearCookies: {
|
||||||
url: "",
|
url: {
|
||||||
|
value: "",
|
||||||
|
isString: true,
|
||||||
|
__varInputVal__: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
evaluate: {
|
evaluate: {
|
||||||
function: "",
|
function: "",
|
||||||
params: [],
|
params: [],
|
||||||
},
|
},
|
||||||
when: {
|
when: {
|
||||||
condition: "",
|
condition: {
|
||||||
|
value: "",
|
||||||
|
isString: false,
|
||||||
|
__varInputVal__: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
mousedown: {
|
mousedown: {
|
||||||
selector: "",
|
selector: {
|
||||||
|
value: "",
|
||||||
|
isString: true,
|
||||||
|
__varInputVal__: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
mouseup: {
|
mouseup: {
|
||||||
selector: "",
|
selector: {
|
||||||
|
value: "",
|
||||||
|
isString: true,
|
||||||
|
__varInputVal__: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
file: {
|
file: {
|
||||||
selector: "",
|
selector: {
|
||||||
|
value: "",
|
||||||
|
isString: true,
|
||||||
|
__varInputVal__: true,
|
||||||
|
},
|
||||||
files: [],
|
files: [],
|
||||||
},
|
},
|
||||||
value: {
|
value: {
|
||||||
selector: "",
|
selector: {
|
||||||
value: "",
|
value: "",
|
||||||
|
isString: true,
|
||||||
|
__varInputVal__: true,
|
||||||
|
},
|
||||||
|
value: {
|
||||||
|
value: "",
|
||||||
|
isString: true,
|
||||||
|
__varInputVal__: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
check: {
|
check: {
|
||||||
selector: "",
|
selector: {
|
||||||
|
value: "",
|
||||||
|
isString: true,
|
||||||
|
__varInputVal__: true,
|
||||||
|
},
|
||||||
checked: false,
|
checked: false,
|
||||||
},
|
},
|
||||||
focus: {
|
focus: {
|
||||||
selector: "",
|
selector: {
|
||||||
|
value: "",
|
||||||
|
isString: true,
|
||||||
|
__varInputVal__: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
scroll: {
|
scroll: {
|
||||||
target: "",
|
target: {
|
||||||
|
value: "",
|
||||||
|
isString: true,
|
||||||
|
__varInputVal__: true,
|
||||||
|
},
|
||||||
x: 0,
|
x: 0,
|
||||||
y: 0,
|
y: 0,
|
||||||
},
|
},
|
||||||
download: {
|
download: {
|
||||||
url: "",
|
url: {
|
||||||
savePath: "",
|
value: "",
|
||||||
|
isString: true,
|
||||||
|
__varInputVal__: true,
|
||||||
|
},
|
||||||
|
savePath: {
|
||||||
|
value: "",
|
||||||
|
isString: true,
|
||||||
|
__varInputVal__: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
// 运行参数
|
// 运行参数
|
||||||
run: defaultUBrowserRunConfigs,
|
run: defaultUBrowserRunConfigs,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user