mirror of
https://gitee.com/yudaocode/yudao-ui-admin-vue3.git
synced 2025-12-30 09:32:26 +00:00
feat: 优化HTTP任务请求头输入,改为键值对单独编辑框
This commit is contained in:
@@ -0,0 +1,178 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
v-model="dialogVisible"
|
||||
title="编辑请求头"
|
||||
width="600px"
|
||||
:close-on-click-modal="false"
|
||||
@close="handleClose"
|
||||
>
|
||||
<div class="header-editor">
|
||||
<div class="header-list">
|
||||
<div v-for="(item, index) in headerList" :key="index" class="header-item">
|
||||
<el-input v-model="item.key" placeholder="请输入参数名" class="header-key" clearable />
|
||||
<span class="separator">:</span>
|
||||
<el-input
|
||||
v-model="item.value"
|
||||
placeholder="请输入参数值 (支持表达式 ${变量名})"
|
||||
class="header-value"
|
||||
clearable
|
||||
/>
|
||||
<el-button
|
||||
type="danger"
|
||||
:icon="Delete"
|
||||
circle
|
||||
size="small"
|
||||
@click="removeHeader(index)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<el-button type="primary" :icon="Plus" class="add-btn" @click="addHeader">
|
||||
添加请求头
|
||||
</el-button>
|
||||
</div>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="handleClose">取消</el-button>
|
||||
<el-button type="primary" @click="handleSave">保存</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { Delete, Plus } from '@element-plus/icons-vue'
|
||||
|
||||
defineOptions({ name: 'HttpHeaderEditor' })
|
||||
|
||||
const props = defineProps({
|
||||
modelValue: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
headers: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
})
|
||||
|
||||
const emit = defineEmits(['update:modelValue', 'save'])
|
||||
|
||||
interface HeaderItem {
|
||||
key: string
|
||||
value: string
|
||||
}
|
||||
|
||||
const dialogVisible = computed({
|
||||
get: () => props.modelValue,
|
||||
set: (val) => emit('update:modelValue', val)
|
||||
})
|
||||
|
||||
const headerList = ref<HeaderItem[]>([])
|
||||
|
||||
// 解析请求头字符串为列表
|
||||
const parseHeaders = (headersStr: string): HeaderItem[] => {
|
||||
if (!headersStr || !headersStr.trim()) {
|
||||
return [{ key: '', value: '' }]
|
||||
}
|
||||
|
||||
const lines = headersStr.split('\n').filter((line) => line.trim())
|
||||
const parsed = lines.map((line) => {
|
||||
const colonIndex = line.indexOf(':')
|
||||
if (colonIndex > 0) {
|
||||
return {
|
||||
key: line.substring(0, colonIndex).trim(),
|
||||
value: line.substring(colonIndex + 1).trim()
|
||||
}
|
||||
}
|
||||
return { key: line.trim(), value: '' }
|
||||
})
|
||||
|
||||
return parsed.length > 0 ? parsed : [{ key: '', value: '' }]
|
||||
}
|
||||
|
||||
// 将列表转换为请求头字符串
|
||||
const stringifyHeaders = (headers: HeaderItem[]): string => {
|
||||
return headers
|
||||
.filter((item) => item.key.trim())
|
||||
.map((item) => `${item.key}: ${item.value}`)
|
||||
.join('\n')
|
||||
}
|
||||
|
||||
// 添加请求头
|
||||
const addHeader = () => {
|
||||
headerList.value.push({ key: '', value: '' })
|
||||
}
|
||||
|
||||
// 移除请求头
|
||||
const removeHeader = (index: number) => {
|
||||
if (headerList.value.length === 1) {
|
||||
// 至少保留一行
|
||||
headerList.value = [{ key: '', value: '' }]
|
||||
} else {
|
||||
headerList.value.splice(index, 1)
|
||||
}
|
||||
}
|
||||
|
||||
// 保存
|
||||
const handleSave = () => {
|
||||
const headersStr = stringifyHeaders(headerList.value)
|
||||
emit('save', headersStr)
|
||||
dialogVisible.value = false
|
||||
}
|
||||
|
||||
// 关闭
|
||||
const handleClose = () => {
|
||||
dialogVisible.value = false
|
||||
}
|
||||
|
||||
// 监听对话框打开,初始化数据
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
(val) => {
|
||||
if (val) {
|
||||
headerList.value = parseHeaders(props.headers)
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
)
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.header-editor {
|
||||
.header-list {
|
||||
max-height: 400px;
|
||||
overflow-y: auto;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.header-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
margin-bottom: 12px;
|
||||
|
||||
.header-key {
|
||||
flex: 0 0 180px;
|
||||
}
|
||||
|
||||
.separator {
|
||||
color: #606266;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.header-value {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.add-btn {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.dialog-footer {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 10px;
|
||||
}
|
||||
</style>
|
||||
@@ -43,22 +43,34 @@
|
||||
<el-option label="POST" value="POST" />
|
||||
<el-option label="PUT" value="PUT" />
|
||||
<el-option label="DELETE" value="DELETE" />
|
||||
<el-option label="PATCH" value="PATCH" />
|
||||
<el-option label="HEAD" value="HEAD" />
|
||||
<el-option label="OPTIONS" value="OPTIONS" />
|
||||
<!-- <el-option label="PATCH" value="PATCH" />-->
|
||||
<!-- <el-option label="HEAD" value="HEAD" />-->
|
||||
<!-- <el-option label="OPTIONS" value="OPTIONS" />-->
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="请求地址" key="http-url" prop="requestUrl">
|
||||
<el-input v-model="httpTaskForm.requestUrl" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="请求头" key="http-headers">
|
||||
<el-input
|
||||
v-model="httpTaskForm.requestHeaders"
|
||||
type="textarea"
|
||||
resize="vertical"
|
||||
:autosize="{ minRows: 2, maxRows: 4 }"
|
||||
clearable
|
||||
/>
|
||||
<div style="display: flex; gap: 8px; align-items: flex-start; width: 100%">
|
||||
<el-input
|
||||
v-model="httpTaskForm.requestHeaders"
|
||||
type="textarea"
|
||||
resize="vertical"
|
||||
:autosize="{ minRows: 4, maxRows: 8 }"
|
||||
readonly
|
||||
placeholder="点击右侧编辑按钮添加请求头"
|
||||
style="flex: 1; min-width: 0"
|
||||
/>
|
||||
<el-button
|
||||
type="primary"
|
||||
:icon="Edit"
|
||||
@click="showHeaderEditor = true"
|
||||
style="flex-shrink: 0"
|
||||
>
|
||||
编辑
|
||||
</el-button>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="禁止重定向" key="http-disallow-redirects">
|
||||
<el-switch v-model="httpTaskForm.disallowRedirects" />
|
||||
@@ -66,24 +78,34 @@
|
||||
<el-form-item label="忽略异常" key="http-ignore-exception">
|
||||
<el-switch v-model="httpTaskForm.ignoreException" />
|
||||
</el-form-item>
|
||||
<el-form-item label="保存响应参数" key="http-save-response">
|
||||
<el-form-item label="保存返回变量" key="http-save-response">
|
||||
<el-switch v-model="httpTaskForm.saveResponseParameters" />
|
||||
</el-form-item>
|
||||
<el-form-item label="瞬态保存响应参数" key="http-save-transient">
|
||||
<el-form-item label="是否瞬间变量" key="http-save-transient">
|
||||
<el-switch v-model="httpTaskForm.saveResponseParametersTransient" />
|
||||
</el-form-item>
|
||||
<el-form-item label="保存响应参数" key="http-result-variable-prefix">
|
||||
<el-form-item label="返回变量前缀" key="http-result-variable-prefix">
|
||||
<el-input v-model="httpTaskForm.resultVariablePrefix" />
|
||||
</el-form-item>
|
||||
<el-form-item label="JSON 保存响应变量" key="http-save-json">
|
||||
<el-form-item label="格式化返回为JSON" key="http-save-json">
|
||||
<el-switch v-model="httpTaskForm.saveResponseVariableAsJson" />
|
||||
</el-form-item>
|
||||
</template>
|
||||
|
||||
<!-- 请求头编辑器 -->
|
||||
<HttpHeaderEditor
|
||||
v-model="showHeaderEditor"
|
||||
:headers="httpTaskForm.requestHeaders"
|
||||
@save="handleHeadersSave"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { Edit } from '@element-plus/icons-vue'
|
||||
import { updateElementExtensions } from '@/components/bpmnProcessDesigner/package/utils'
|
||||
import HttpHeaderEditor from './HttpHeaderEditor.vue'
|
||||
|
||||
defineOptions({ name: 'ServiceTask' })
|
||||
const props = defineProps({
|
||||
id: String,
|
||||
@@ -136,6 +158,7 @@ const serviceTaskForm = ref({ ...DEFAULT_TASK_FORM })
|
||||
const httpTaskForm = ref({ ...DEFAULT_HTTP_FORM })
|
||||
const bpmnElement = ref()
|
||||
const httpInitializing = ref(false)
|
||||
const showHeaderEditor = ref(false)
|
||||
|
||||
const bpmnInstances = () => (window as any)?.bpmnInstances
|
||||
|
||||
@@ -341,6 +364,10 @@ const handleExecuteTypeChange = (value: string) => {
|
||||
updateElementTask()
|
||||
}
|
||||
|
||||
const handleHeadersSave = (headersStr: string) => {
|
||||
httpTaskForm.value.requestHeaders = headersStr
|
||||
}
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
bpmnElement.value = null
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user