fix: merge
This commit is contained in:
commit
c2d571802e
|
@ -1,6 +1,25 @@
|
|||
import { BASE_API_PATH } from "@/utils/variable";
|
||||
import server from '@/utils/request'
|
||||
import { SearchHistoryList } from 'components/Search/types'
|
||||
|
||||
export const FILE_UPLOAD = `${BASE_API_PATH}/file/static`;
|
||||
|
||||
/**
|
||||
* 上传文件
|
||||
* 保存查询记录
|
||||
* @param data
|
||||
* @param target
|
||||
*/
|
||||
export const FILE_UPLOAD = `${BASE_API_PATH}/file/static`;
|
||||
export const saveSearchHistory = (data: any, target:string) => server.post(`/user/settings/${target}`, data)
|
||||
|
||||
/**
|
||||
* 获取查询记录
|
||||
* @param target
|
||||
*/
|
||||
export const getSearchHistory = (target:string) => server.get<SearchHistoryList[]>(`/user/settings/${target}`)
|
||||
|
||||
/**
|
||||
* 删除指定查询记录
|
||||
* @param id
|
||||
* @param target
|
||||
*/
|
||||
export const deleteSearchHistory = (target:string, id:string) => server.remove<SearchHistoryList[]>(`/user/settings/${target}/${id}`)
|
||||
|
|
|
@ -6,11 +6,11 @@ export const detail = (id: string) => server.get(`/gateway/device/${id}`);
|
|||
|
||||
export const getNetworkList = (
|
||||
networkType: string,
|
||||
include: string,
|
||||
data: Object,
|
||||
params: Object,
|
||||
) =>
|
||||
server.get(
|
||||
`/network/config/${networkType}/_alive?include=${params.include}`,
|
||||
`/network/config/${networkType}/_alive?include=${include}`,
|
||||
data,
|
||||
);
|
||||
|
||||
|
|
|
@ -3,4 +3,4 @@ import server from '@/utils/request';
|
|||
// 保存
|
||||
export const save_api = (data: any) => server.post(`/system/config/scope/_save`, data)
|
||||
// 获取详情
|
||||
export const getDetails_api = (data: any) => server.post(`/system/config/scopes`, data)
|
||||
export const getDetails_api = (data: any) => server.post(`/system/config/scopes`, data)
|
||||
|
|
|
@ -0,0 +1,125 @@
|
|||
<template>
|
||||
<a-dropdown-button
|
||||
type='primary'
|
||||
@click='click'
|
||||
placement='bottomLeft'
|
||||
:visible='historyVisible'
|
||||
@visibleChange='visibleChange'
|
||||
>
|
||||
搜索
|
||||
<template #overlay>
|
||||
<a-menu>
|
||||
<template v-if='!showEmpty'>
|
||||
<a-menu-item v-for='item in historyList' :key='item.id'>
|
||||
<div class='history-item'>
|
||||
<span @click.stop='itemClick(item.content)'>{{ item.name }}</span>
|
||||
<a-popconfirm
|
||||
title='确认删除吗?'
|
||||
placement='top'
|
||||
@confirm.stop='deleteHistory(item.id)'
|
||||
:okButtonProps='{
|
||||
loading: deleteLoading
|
||||
}'
|
||||
>
|
||||
<span class='delete'>
|
||||
<DeleteOutlined />
|
||||
</span>
|
||||
</a-popconfirm>
|
||||
</div>
|
||||
</a-menu-item>
|
||||
</template>
|
||||
<template v-else>
|
||||
<div class='history-empty'>
|
||||
<a-empty />
|
||||
</div>
|
||||
</template>
|
||||
</a-menu>
|
||||
</template>
|
||||
<template #icon>
|
||||
<SearchOutlined />
|
||||
</template>
|
||||
</a-dropdown-button>
|
||||
</template>
|
||||
|
||||
<script setup lang='ts' name='SearchHistory'>
|
||||
import { SearchOutlined, DeleteOutlined } from '@ant-design/icons-vue'
|
||||
import { deleteSearchHistory, getSearchHistory } from '@/api/comm'
|
||||
import type { SearchHistoryList } from 'components/Search/types'
|
||||
|
||||
type Emit = {
|
||||
(event: 'click'): void
|
||||
(event: 'itemClick', data: string): void
|
||||
}
|
||||
const emit = defineEmits<Emit>()
|
||||
|
||||
const props = defineProps({
|
||||
target: {
|
||||
type: String,
|
||||
default: '',
|
||||
required: true
|
||||
}
|
||||
})
|
||||
|
||||
const historyList = ref<SearchHistoryList[]>([])
|
||||
const historyVisible = ref(false)
|
||||
const deleteLoading = ref(false)
|
||||
const showEmpty = ref(false)
|
||||
|
||||
const visibleChange = async (visible: boolean) => {
|
||||
historyVisible.value = visible
|
||||
if (visible) {
|
||||
const resp = await getSearchHistory(props.target)
|
||||
if (resp.success && resp.result.length) {
|
||||
historyList.value = resp.result.filter(item => item.content)
|
||||
showEmpty.value = false
|
||||
} else {
|
||||
showEmpty.value = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const click = () => {
|
||||
emit('click')
|
||||
}
|
||||
|
||||
const itemClick = (content: string) => {
|
||||
historyVisible.value = false
|
||||
emit('itemClick', content)
|
||||
}
|
||||
|
||||
const deleteHistory = async (id: string) => {
|
||||
deleteLoading.value = true
|
||||
const resp = await deleteSearchHistory(props.target, id)
|
||||
deleteLoading.value = false
|
||||
if (resp.success) {
|
||||
historyVisible.value = false
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped lang='less'>
|
||||
.history-empty {
|
||||
width: 200px;
|
||||
background-color: #fff;
|
||||
box-shadow: @box-shadow-base;
|
||||
border-radius: 2px;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
max-height: 200px;
|
||||
}
|
||||
|
||||
.history-item {
|
||||
width: 200px;
|
||||
display: flex;
|
||||
|
||||
> span {
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
|
||||
.delete {
|
||||
padding: 0 6px;
|
||||
flex: 0 0 28px;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,100 @@
|
|||
<template>
|
||||
<a-popover
|
||||
title='搜索名称'
|
||||
trigger='click'
|
||||
v-model:visible='visible'
|
||||
@visibleChange='visibleChange'
|
||||
>
|
||||
<template #content>
|
||||
<div style='width: 240px'>
|
||||
<a-form ref='formRef' :model='modelRef'>
|
||||
<a-form-item
|
||||
name='name'
|
||||
:rules='[
|
||||
{ required: true, message: "请输入名称"}
|
||||
]'
|
||||
>
|
||||
<a-textarea
|
||||
v-model:value='modelRef.name'
|
||||
:rows='3'
|
||||
:maxlength='200'
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
<a-button
|
||||
:loading='saveHistoryLoading'
|
||||
type='primary'
|
||||
class='save-btn'
|
||||
@click='saveHistory'
|
||||
>
|
||||
保存
|
||||
</a-button>
|
||||
</div>
|
||||
</template>
|
||||
<a-button>
|
||||
<template #icon>
|
||||
<SaveOutlined />
|
||||
</template>
|
||||
保存
|
||||
</a-button>
|
||||
</a-popover>
|
||||
</template>
|
||||
|
||||
<script setup lang='ts' name='SaveHistory'>
|
||||
import type { Terms } from './types'
|
||||
import { PropType } from 'vue'
|
||||
import { saveSearchHistory } from '@/api/comm'
|
||||
import { SaveOutlined } from '@ant-design/icons-vue';
|
||||
|
||||
const props = defineProps({
|
||||
terms: {
|
||||
type: Object as PropType<Terms>,
|
||||
default: () => ({})
|
||||
},
|
||||
target: {
|
||||
type: String,
|
||||
default: '',
|
||||
required: true
|
||||
}
|
||||
})
|
||||
|
||||
const searchName = ref('')
|
||||
|
||||
const saveHistoryLoading = ref(false)
|
||||
|
||||
const visible = ref(false)
|
||||
|
||||
const formRef = ref()
|
||||
|
||||
const modelRef = reactive({
|
||||
name: undefined
|
||||
})
|
||||
|
||||
/**
|
||||
* 保存当前查询条件
|
||||
*/
|
||||
const saveHistory = async () => {
|
||||
// 获取当前查询条件并转化为字符串
|
||||
const formData = await formRef.value.validate()
|
||||
if (formData) {
|
||||
formData.content = JSON.stringify(props.terms)
|
||||
saveHistoryLoading.value = true
|
||||
const resp = await saveSearchHistory(formData, props.target)
|
||||
saveHistoryLoading.value = false
|
||||
if (resp.success) {
|
||||
visible.value = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const visibleChange = (e: boolean) => {
|
||||
visible.value = e
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped lang='less'>
|
||||
.save-btn {
|
||||
width: 100%
|
||||
}
|
||||
</style>
|
|
@ -23,24 +23,10 @@
|
|||
</div>
|
||||
<div :class='["JSearch-footer", expand ? "expand" : ""]'>
|
||||
<div class='JSearch-footer--btns'>
|
||||
<a-dropdown-button type="primary" @click='searchSubmit'>
|
||||
搜索
|
||||
<template #overlay>
|
||||
<a-menu v-if='!!historyList.length'>
|
||||
<a-menu-item>
|
||||
|
||||
</a-menu-item>
|
||||
</a-menu>
|
||||
<a-empty v-else />
|
||||
</template>
|
||||
<template #icon><SearchOutlined /></template>
|
||||
</a-dropdown-button>
|
||||
<a-button>
|
||||
<template #icon><PoweroffOutlined /></template>
|
||||
保存
|
||||
</a-button>
|
||||
<History :target='target' @click='searchSubmit' @itemClick='historyItemClick' />
|
||||
<SaveHistory :terms='terms' :target='target'/>
|
||||
<a-button @click='reset'>
|
||||
<template #icon><PoweroffOutlined /></template>
|
||||
<template #icon><RedoOutlined /></template>
|
||||
重置
|
||||
</a-button>
|
||||
</div>
|
||||
|
@ -64,7 +50,7 @@
|
|||
搜索
|
||||
</a-button>
|
||||
<a-button @click='reset'>
|
||||
<template #icon><PoweroffOutlined /></template>
|
||||
<template #icon><RedoOutlined /></template>
|
||||
重置
|
||||
</a-button>
|
||||
</div>
|
||||
|
@ -77,10 +63,12 @@
|
|||
import SearchItem from './Item.vue'
|
||||
import { typeOptions } from './util'
|
||||
import { useElementSize, useUrlSearchParams } from '@vueuse/core'
|
||||
import { cloneDeep, isFunction, set } from 'lodash-es'
|
||||
import { SearchOutlined, DownOutlined } from '@ant-design/icons-vue';
|
||||
import { cloneDeep, isFunction, isString, set } from 'lodash-es'
|
||||
import { SearchOutlined, DownOutlined, RedoOutlined } from '@ant-design/icons-vue';
|
||||
import { PropType } from 'vue'
|
||||
import { JColumnsProps } from 'components/Table/types'
|
||||
import SaveHistory from './SaveHistory.vue'
|
||||
import History from './History.vue'
|
||||
import type { SearchItemData, SearchProps, Terms } from './types'
|
||||
|
||||
type UrlParam = {
|
||||
|
@ -177,16 +165,18 @@ const addUrlParams = () => {
|
|||
* @param v
|
||||
*/
|
||||
const handleLikeValue = (v: string) => {
|
||||
let _v = v
|
||||
return _v.split('').reduce((pre: string, next: string) => {
|
||||
let _next = next
|
||||
if (next === '\\') {
|
||||
_next = '\\\\'
|
||||
} else if (next === '%') {
|
||||
_next = '\\%'
|
||||
}
|
||||
return pre + _next
|
||||
}, '')
|
||||
if (isString(v)) {
|
||||
return v.split('').reduce((pre: string, next: string) => {
|
||||
let _next = next
|
||||
if (next === '\\') {
|
||||
_next = '\\\\'
|
||||
} else if (next === '%') {
|
||||
_next = '\\%'
|
||||
}
|
||||
return pre + _next
|
||||
}, '')
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -207,7 +197,7 @@ const handleParamsFormat = () => {
|
|||
}
|
||||
|
||||
if (_item.handleValue && isFunction(_item.handleValue)) {
|
||||
iItem.value = _item.handleValue(iItem.value, iItem)
|
||||
iItem.value = _item.handleValue(iItem.value)
|
||||
}
|
||||
|
||||
if (['like','nlike'].includes(iItem.termType) && !!iItem.value) {
|
||||
|
@ -226,7 +216,9 @@ const handleParamsFormat = () => {
|
|||
*/
|
||||
const searchSubmit = () => {
|
||||
emit('search', handleParamsFormat())
|
||||
addUrlParams()
|
||||
if (props.type === 'advanced') {
|
||||
addUrlParams()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -235,8 +227,10 @@ const searchSubmit = () => {
|
|||
const reset = () => {
|
||||
terms.terms = []
|
||||
expand.value = false
|
||||
urlParams.q = null
|
||||
urlParams.target = null
|
||||
if (props.type === 'advanced') {
|
||||
urlParams.q = null
|
||||
urlParams.target = null
|
||||
}
|
||||
}
|
||||
|
||||
watch(width, (value) => {
|
||||
|
@ -249,6 +243,18 @@ watch(width, (value) => {
|
|||
}
|
||||
})
|
||||
|
||||
const historyItemClick = (content: string) => {
|
||||
try {
|
||||
terms.terms = JSON.parse(content)?.terms || []
|
||||
if (terms.terms.length === 2) {
|
||||
expand.value = true
|
||||
}
|
||||
addUrlParams()
|
||||
} catch (e) {
|
||||
console.warn(`Search组件中handleUrlParams处理JSON时异常:【${e}】`)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理URL中的查询参数
|
||||
* @param _params
|
||||
|
@ -258,7 +264,6 @@ const handleUrlParams = (_params: UrlParam) => {
|
|||
if (_params.target === props.target && _params.q) {
|
||||
try {
|
||||
terms.terms = JSON.parse(_params.q)?.terms || []
|
||||
console.log(terms)
|
||||
if (terms.terms.length === 2) {
|
||||
expand.value = true
|
||||
}
|
||||
|
@ -372,4 +377,5 @@ handleItems()
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
|
@ -37,9 +37,11 @@ export interface SortItem {
|
|||
value?: any
|
||||
}
|
||||
|
||||
export interface Params {
|
||||
sorts: SortItem[]
|
||||
terms: Terms['terms']
|
||||
export interface SearchHistoryList {
|
||||
content?: string
|
||||
name: string
|
||||
id: string
|
||||
key: string
|
||||
}
|
||||
|
||||
export interface SearchProps extends SearchBaseProps, SearchItemProps {
|
||||
|
|
|
@ -45,7 +45,7 @@
|
|||
<template #addonAfter>
|
||||
<a-upload
|
||||
name="file"
|
||||
:action="action"
|
||||
:action="FILE_UPLOAD"
|
||||
:headers="headers"
|
||||
:showUploadList="false"
|
||||
@change="handleFileChange"
|
||||
|
@ -89,6 +89,7 @@ import GeoComponent from '@/components/GeoComponent/index.vue';
|
|||
import { BASE_API_PATH, TOKEN_KEY } from '@/utils/variable';
|
||||
import { LocalStore } from '@/utils/comm';
|
||||
import { ItemData, ITypes } from './types';
|
||||
import { FILE_UPLOAD } from '@/api/comm';
|
||||
|
||||
type Emits = {
|
||||
(e: 'update:modelValue', data: string | number | boolean): void;
|
||||
|
@ -161,7 +162,6 @@ const handleItemModalSubmit = () => {
|
|||
};
|
||||
|
||||
// 文件上传
|
||||
const action = ref<string>(`${BASE_API_PATH}/file/static`);
|
||||
const headers = ref({ [TOKEN_KEY]: LocalStore.get(TOKEN_KEY) });
|
||||
const handleFileChange = (info: UploadChangeParam<UploadFile<any>>) => {
|
||||
if (info.file.status === 'done') {
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<div class='search'>
|
||||
<Search
|
||||
:columns='columns'
|
||||
target='device'
|
||||
target='device-instance-search'
|
||||
@search='search'
|
||||
/>
|
||||
<Search
|
||||
|
|
|
@ -12,10 +12,10 @@
|
|||
<div>
|
||||
<a-form
|
||||
:model="formState"
|
||||
ref="formRef1"
|
||||
name="basic"
|
||||
autocomplete="off"
|
||||
layout="vertical"
|
||||
@finish="onFinish"
|
||||
>
|
||||
<a-row :gutter="[24, 24]">
|
||||
<a-col :span="12">
|
||||
|
@ -25,7 +25,11 @@
|
|||
:rules="[
|
||||
{
|
||||
required: true,
|
||||
message: '请输入SIP 域!',
|
||||
message: '请输入SIP 域',
|
||||
},
|
||||
{
|
||||
max: 64,
|
||||
message: '最大可输入64个字符',
|
||||
},
|
||||
]"
|
||||
>
|
||||
|
@ -42,7 +46,11 @@
|
|||
:rules="[
|
||||
{
|
||||
required: true,
|
||||
message: '请输入SIP ID!',
|
||||
message: '请输入SIP ID',
|
||||
},
|
||||
{
|
||||
max: 64,
|
||||
message: '最大可输入64个字符',
|
||||
},
|
||||
]"
|
||||
>
|
||||
|
@ -59,7 +67,7 @@
|
|||
:rules="[
|
||||
{
|
||||
required: true,
|
||||
message: '请选择集群!',
|
||||
message: '请选择集群',
|
||||
},
|
||||
]"
|
||||
>
|
||||
|
@ -88,65 +96,104 @@
|
|||
<a-radio :value="false">独立配置</a-radio>
|
||||
</a-radio-group>
|
||||
</a-form-item>
|
||||
<div v-if="formState.shareCluster">
|
||||
<div v-if="formState.shareCluster" class="form-item1">
|
||||
<a-row :gutter="[24, 24]">
|
||||
<a-col :span="12">
|
||||
<a-col :span="6">
|
||||
<a-form-item
|
||||
label="SIP 地址"
|
||||
name="sip"
|
||||
:name="['hostPort', 'host']"
|
||||
:rules="[
|
||||
{
|
||||
required: true,
|
||||
message: '请选择端口!',
|
||||
message: '请选择SIP地址',
|
||||
},
|
||||
]"
|
||||
>
|
||||
<a-input-group compact>
|
||||
<a-select
|
||||
v-model:value="formState.sip1"
|
||||
style="width: 50%"
|
||||
:disabled="true"
|
||||
<a-select
|
||||
v-model:value="
|
||||
formState.hostPort.host
|
||||
"
|
||||
style="width: 105%"
|
||||
:disabled="true"
|
||||
show-search
|
||||
:filter-option="filterOption"
|
||||
>
|
||||
<a-select-option value="0.0.0.0"
|
||||
>0.0.0.0</a-select-option
|
||||
>
|
||||
<a-select-option value="0.0.0.0"
|
||||
>0.0.0.0</a-select-option
|
||||
>
|
||||
</a-select>
|
||||
<a-select
|
||||
v-model:value="formState.sip"
|
||||
:options="sipList"
|
||||
style="width: 50%"
|
||||
placeholder="请选择端口"
|
||||
/>
|
||||
</a-input-group>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-col :span="6">
|
||||
<a-form-item
|
||||
label="公网 Host"
|
||||
name="public"
|
||||
:name="['hostPort', 'port']"
|
||||
:rules="[
|
||||
{
|
||||
required: true,
|
||||
message: '请选择端口!',
|
||||
message: '请选择端口',
|
||||
},
|
||||
]"
|
||||
>
|
||||
<a-input-group compact>
|
||||
<a-input
|
||||
style="width: 50%"
|
||||
v-model:value="
|
||||
formState.public1
|
||||
"
|
||||
placeholder="请输入IP地址"
|
||||
/>
|
||||
<a-input-number
|
||||
style="width: 50%"
|
||||
placeholder="请输入端口"
|
||||
v-model:value="formState.public"
|
||||
:min="1"
|
||||
:max="65535"
|
||||
/>
|
||||
</a-input-group>
|
||||
<div class="form-label"></div>
|
||||
|
||||
<a-select
|
||||
v-model:value="
|
||||
formState.hostPort.port
|
||||
"
|
||||
:options="sipList"
|
||||
placeholder="请选择端口"
|
||||
allowClear
|
||||
show-search
|
||||
:filter-option="filterOption"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="6">
|
||||
<a-form-item
|
||||
label="公网 Host"
|
||||
:name="['hostPort', 'publicHost']"
|
||||
:rules="[
|
||||
{
|
||||
required: true,
|
||||
message: '请输入IP地址',
|
||||
},
|
||||
{
|
||||
pattern:
|
||||
/^([0-9]|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.([0-9]|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.([0-9]|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.([0-9]|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])$/,
|
||||
message: '请输入正确的IP地址',
|
||||
},
|
||||
]"
|
||||
>
|
||||
<a-input
|
||||
style="width: 105%"
|
||||
v-model:value="
|
||||
formState.hostPort.publicHost
|
||||
"
|
||||
placeholder="请输入IP地址"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="6">
|
||||
<a-form-item
|
||||
:name="['hostPort', 'publicPort']"
|
||||
:rules="[
|
||||
{
|
||||
required: true,
|
||||
message: '输入端口',
|
||||
},
|
||||
]"
|
||||
>
|
||||
<div class="form-label"></div>
|
||||
|
||||
<a-input-number
|
||||
style="width: 100%"
|
||||
placeholder="请输入端口"
|
||||
v-model:value="
|
||||
formState.hostPort.publicPort
|
||||
"
|
||||
:min="1"
|
||||
:max="65535"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
@ -158,50 +205,56 @@
|
|||
layout="vertical"
|
||||
name="dynamic_form_nest_item"
|
||||
:model="dynamicValidateForm"
|
||||
@finish="onFinish2"
|
||||
>
|
||||
<div
|
||||
v-for="(
|
||||
user, index
|
||||
) in dynamicValidateForm.users"
|
||||
:key="user.id"
|
||||
cluster, index
|
||||
) in dynamicValidateForm.cluster"
|
||||
:key="cluster.id"
|
||||
>
|
||||
<a-collapse v-model:activeKey="activeKey">
|
||||
<a-collapse-panel
|
||||
:key="user.id"
|
||||
:key="cluster.id"
|
||||
:header="`#${index + 1}.节点`"
|
||||
>
|
||||
|
||||
<template #extra>
|
||||
<delete-outlined
|
||||
@click="removeUser(user)"
|
||||
@click="removeCluster(cluster)"
|
||||
/>
|
||||
</template>
|
||||
<a-row :gutter="[24, 24]">
|
||||
<a-col :span="8">
|
||||
<a-form-item
|
||||
label="节点名称"
|
||||
:name="[
|
||||
'users',
|
||||
'cluster',
|
||||
index,
|
||||
'first',
|
||||
'clusterNodeId',
|
||||
]"
|
||||
>
|
||||
<div class="form-label">
|
||||
节点名称
|
||||
</div>
|
||||
<a-select
|
||||
v-model:value="
|
||||
user.first
|
||||
cluster.clusterNodeId
|
||||
"
|
||||
:options="clustersList"
|
||||
placeholder="请选择节点名称"
|
||||
allowClear
|
||||
show-search
|
||||
:filter-option="
|
||||
filterOption
|
||||
"
|
||||
>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="7">
|
||||
<a-col :span="4">
|
||||
<a-form-item
|
||||
:name="[
|
||||
'users',
|
||||
'cluster',
|
||||
index,
|
||||
'last',
|
||||
'host',
|
||||
]"
|
||||
:rules="{
|
||||
required: true,
|
||||
|
@ -209,13 +262,10 @@
|
|||
'请选择SIP 地址',
|
||||
}"
|
||||
>
|
||||
<div>
|
||||
<div class="form-label">
|
||||
SIP 地址
|
||||
<span
|
||||
style="
|
||||
color: red;
|
||||
margin: 0 4px 0 -2px;
|
||||
"
|
||||
class="form-label-required"
|
||||
>*</span
|
||||
>
|
||||
<a-tooltip>
|
||||
|
@ -227,46 +277,84 @@
|
|||
<question-circle-outlined />
|
||||
</a-tooltip>
|
||||
</div>
|
||||
<a-input-group compact>
|
||||
<a-select
|
||||
v-model:value="
|
||||
user.last
|
||||
"
|
||||
style="width: 50%"
|
||||
:options="sipList"
|
||||
>
|
||||
</a-select>
|
||||
<a-select
|
||||
v-model:value="
|
||||
user.last1
|
||||
"
|
||||
:options="sipList"
|
||||
style="width: 50%"
|
||||
placeholder="请选择端口"
|
||||
/>
|
||||
</a-input-group>
|
||||
|
||||
<a-select
|
||||
v-model:value="
|
||||
cluster.host
|
||||
"
|
||||
:options="sipListOption"
|
||||
placeholder="请选择IP地址"
|
||||
allowClear
|
||||
show-search
|
||||
:filter-option="
|
||||
filterOption
|
||||
"
|
||||
style="width: 110%"
|
||||
@change="
|
||||
handleChangeForm2Sip(
|
||||
index,
|
||||
)
|
||||
"
|
||||
>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="8">
|
||||
<a-col :span="4">
|
||||
<a-form-item
|
||||
:name="[
|
||||
'users',
|
||||
'cluster',
|
||||
index,
|
||||
'last2',
|
||||
'port',
|
||||
]"
|
||||
:rules="{
|
||||
required: true,
|
||||
message:
|
||||
'请输入公网 Host',
|
||||
message: '请选择端口',
|
||||
}"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
class="form-label"
|
||||
></div>
|
||||
<a-select
|
||||
v-model:value="
|
||||
cluster.port
|
||||
"
|
||||
:options="
|
||||
sipListIndex[index]
|
||||
"
|
||||
placeholder="请选择端口"
|
||||
allowClear
|
||||
show-search
|
||||
:filter-option="
|
||||
filterOption
|
||||
"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="4">
|
||||
<a-form-item
|
||||
:name="[
|
||||
'cluster',
|
||||
index,
|
||||
'publicHost',
|
||||
]"
|
||||
:rules="[
|
||||
{
|
||||
required: true,
|
||||
message:
|
||||
'请输入公网 Host',
|
||||
},
|
||||
{
|
||||
pattern:
|
||||
/^([0-9]|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.([0-9]|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.([0-9]|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.([0-9]|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])$/,
|
||||
message:
|
||||
'请输入正确的IP地址',
|
||||
},
|
||||
]"
|
||||
>
|
||||
<div class="form-label">
|
||||
公网 Host
|
||||
<span
|
||||
style="
|
||||
color: red;
|
||||
margin: 0 4px 0 -2px;
|
||||
"
|
||||
class="form-label-required"
|
||||
>*</span
|
||||
>
|
||||
<a-tooltip>
|
||||
|
@ -278,24 +366,44 @@
|
|||
<question-circle-outlined />
|
||||
</a-tooltip>
|
||||
</div>
|
||||
<a-input-group compact>
|
||||
<a-input
|
||||
style="width: 50%"
|
||||
v-model:value="
|
||||
user.last2
|
||||
"
|
||||
placeholder="请输入IP地址"
|
||||
/>
|
||||
<a-input-number
|
||||
style="width: 50%"
|
||||
placeholder="请输入端口"
|
||||
v-model:value="
|
||||
user.last3
|
||||
"
|
||||
:min="1"
|
||||
:max="65535"
|
||||
/>
|
||||
</a-input-group>
|
||||
<a-input
|
||||
style="width: 110%"
|
||||
v-model:value="
|
||||
cluster.publicHost
|
||||
"
|
||||
placeholder="请输入IP地址"
|
||||
allowClear
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="4">
|
||||
<a-form-item
|
||||
:name="[
|
||||
'cluster',
|
||||
index,
|
||||
'publicPort',
|
||||
]"
|
||||
:rules="[
|
||||
{
|
||||
required: true,
|
||||
message:
|
||||
'请输入端口',
|
||||
},
|
||||
]"
|
||||
>
|
||||
<div
|
||||
class="form-label"
|
||||
></div>
|
||||
|
||||
<a-input-number
|
||||
style="width: 100%"
|
||||
placeholder="请输入端口"
|
||||
v-model:value="
|
||||
cluster.publicPort
|
||||
"
|
||||
:min="1"
|
||||
:max="65535"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
@ -307,17 +415,12 @@
|
|||
style="margin-top: 10px"
|
||||
type="dashed"
|
||||
block
|
||||
@click="addUser"
|
||||
@click="addCluster"
|
||||
>
|
||||
<PlusOutlined />
|
||||
新增
|
||||
</a-button>
|
||||
</a-form-item>
|
||||
<a-form-item>
|
||||
<a-button type="primary" html-type="submit"
|
||||
>Submit</a-button
|
||||
>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -333,11 +436,7 @@
|
|||
<a-col :span="12">
|
||||
<title-component data="基本信息" />
|
||||
<div>
|
||||
<a-form
|
||||
ref="formRef"
|
||||
:model="form"
|
||||
layout="vertical"
|
||||
>
|
||||
<a-form :model="form" layout="vertical">
|
||||
<a-form-item
|
||||
label="名称"
|
||||
v-bind="validateInfos.name"
|
||||
|
@ -380,110 +479,13 @@
|
|||
<div class="config-right-item-title">
|
||||
消息协议
|
||||
</div>
|
||||
<div class="config-right-item-context">
|
||||
<div>
|
||||
{{
|
||||
procotolList.find(
|
||||
(i) => i.id === procotolCurrent,
|
||||
).name
|
||||
provider?.id === 'fixed-media'
|
||||
? 'URL'
|
||||
: 'SIP'
|
||||
}}
|
||||
</div>
|
||||
<div
|
||||
class="config-right-item-context"
|
||||
v-if="config.document"
|
||||
>
|
||||
<Markdown :source="config.document" />
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="config-right-item"
|
||||
v-if="
|
||||
networkList.find(
|
||||
(i) => i.id === networkCurrent,
|
||||
) &&
|
||||
(
|
||||
networkList.find(
|
||||
(i) => i.id === networkCurrent,
|
||||
).addresses || []
|
||||
).length > 0
|
||||
"
|
||||
>
|
||||
<div class="config-right-item-title">
|
||||
网络组件
|
||||
</div>
|
||||
<div
|
||||
v-for="i in (networkList.find(
|
||||
(i) => i.id === networkCurrent,
|
||||
) &&
|
||||
networkList.find(
|
||||
(i) => i.id === networkCurrent,
|
||||
).addresses) ||
|
||||
[]"
|
||||
:key="i.address"
|
||||
>
|
||||
<a-badge
|
||||
:color="
|
||||
i.health === -1
|
||||
? 'red'
|
||||
: 'green'
|
||||
"
|
||||
:text="i.address"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="config-right-item"
|
||||
v-if="
|
||||
config.routes &&
|
||||
config.routes.length > 0
|
||||
"
|
||||
>
|
||||
<div class="config-right-item-title">
|
||||
{{
|
||||
data.provider ===
|
||||
'mqtt-server-gateway' ||
|
||||
data.provider ===
|
||||
'mqtt-client-gateway'
|
||||
? 'topic'
|
||||
: 'URL信息'
|
||||
}}
|
||||
</div>
|
||||
<a-table
|
||||
:pagination="false"
|
||||
:rowKey="generateUUID()"
|
||||
:data-source="config.routes || []"
|
||||
bordered
|
||||
:columns="columnsMQTT"
|
||||
:scroll="{ y: 300 }"
|
||||
>
|
||||
<template
|
||||
#bodyCell="{ column, text, record }"
|
||||
>
|
||||
<template
|
||||
v-if="
|
||||
column.dataIndex ===
|
||||
'stream'
|
||||
"
|
||||
>
|
||||
<span
|
||||
v-if="
|
||||
record.upstream &&
|
||||
record.downstream
|
||||
"
|
||||
>上行、下行</span
|
||||
>
|
||||
<span
|
||||
v-else-if="record.upstream"
|
||||
>上行</span
|
||||
>
|
||||
<span
|
||||
v-else-if="
|
||||
record.downstream
|
||||
"
|
||||
>下行</span
|
||||
>
|
||||
</template>
|
||||
</template>
|
||||
</a-table>
|
||||
</div>
|
||||
</div>
|
||||
</a-col>
|
||||
|
@ -492,14 +494,10 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="steps-action">
|
||||
<a-button
|
||||
v-if="[0, 1].includes(current)"
|
||||
type="primary"
|
||||
@click="next"
|
||||
>
|
||||
<a-button v-if="[0].includes(current)" @click="next">
|
||||
下一步
|
||||
</a-button>
|
||||
<a-button v-if="current === 2" type="primary" @click="saveData">
|
||||
<a-button v-if="current === 1" type="primary" @click="saveData">
|
||||
保存
|
||||
</a-button>
|
||||
<a-button v-if="current > 0" style="margin-left: 8px" @click="prev">
|
||||
|
@ -512,47 +510,29 @@
|
|||
<script lang="ts" setup name="AccessNetwork">
|
||||
import { message, Form } from 'ant-design-vue';
|
||||
import type { FormInstance } from 'ant-design-vue';
|
||||
import Markdown from 'vue3-markdown-it';
|
||||
import { QuestionCircleOutlined } from '@ant-design/icons-vue';
|
||||
import { getResourcesCurrent, getClusters } from '@/api/link/accessConfig';
|
||||
|
||||
import { DeleteOutlined, PlusOutlined } from '@ant-design/icons-vue';
|
||||
import { update, save } from '@/api/link/accessConfig';
|
||||
|
||||
interface User {
|
||||
first: string;
|
||||
last1: string;
|
||||
last: string;
|
||||
last2: string;
|
||||
last3: string;
|
||||
interface Form2 {
|
||||
clusterNodeId: string;
|
||||
port: string;
|
||||
host: string;
|
||||
publicPort: string;
|
||||
publicHost: string;
|
||||
id: number;
|
||||
}
|
||||
|
||||
const activeKey = ref([]);
|
||||
|
||||
const formRef2 = ref<FormInstance>();
|
||||
const dynamicValidateForm = reactive<{ users: User[] }>({
|
||||
users: [],
|
||||
});
|
||||
const removeUser = (item: User) => {
|
||||
let index = dynamicValidateForm.users.indexOf(item);
|
||||
if (index !== -1) {
|
||||
dynamicValidateForm.users.splice(index, 1);
|
||||
}
|
||||
};
|
||||
const addUser = () => {
|
||||
dynamicValidateForm.users.push({
|
||||
first: '',
|
||||
last1: '',
|
||||
last: '',
|
||||
last2: '',
|
||||
last3: '',
|
||||
id: Date.now(),
|
||||
});
|
||||
};
|
||||
const onFinish2 = (values) => {
|
||||
console.log('Received values of form:', values);
|
||||
console.log('dynamicValidateForm.users:', dynamicValidateForm.users);
|
||||
};
|
||||
interface FormState {
|
||||
domain: string;
|
||||
sipId: string;
|
||||
shareCluster: boolean;
|
||||
hostPort: {
|
||||
port: string;
|
||||
host: string;
|
||||
publicPort: string;
|
||||
publicHost: string;
|
||||
};
|
||||
}
|
||||
|
||||
const props = defineProps({
|
||||
provider: {
|
||||
|
@ -565,9 +545,14 @@ const props = defineProps({
|
|||
},
|
||||
});
|
||||
|
||||
const route = useRoute();
|
||||
const id = route.query.id;
|
||||
|
||||
const activeKey: any = ref([]);
|
||||
const clientHeight = document.body.clientHeight;
|
||||
|
||||
const formRef = ref<FormInstance>();
|
||||
const formRef1 = ref<FormInstance>();
|
||||
const formRef2 = ref<FormInstance>();
|
||||
const useForm = Form.useForm;
|
||||
|
||||
const current = ref(0);
|
||||
|
@ -577,10 +562,70 @@ const form = reactive({
|
|||
name: '',
|
||||
description: '',
|
||||
});
|
||||
|
||||
const formState = reactive<FormState>({
|
||||
domain: '',
|
||||
sipId: '',
|
||||
shareCluster: true,
|
||||
hostPort: {
|
||||
port: '',
|
||||
host: '0.0.0.0',
|
||||
publicPort: '',
|
||||
publicHost: '',
|
||||
},
|
||||
});
|
||||
let params = {
|
||||
configuration: {},
|
||||
};
|
||||
let sipListConst: any = [];
|
||||
const sipListOption = ref([]);
|
||||
const sipList = ref([]);
|
||||
const sipListIndex: any = ref([]);
|
||||
const clustersList = ref([]);
|
||||
|
||||
const dynamicValidateForm = reactive<{ cluster: Form2[] }>({
|
||||
cluster: [],
|
||||
});
|
||||
|
||||
const removeCluster = (item: Form2) => {
|
||||
let index = dynamicValidateForm.cluster.indexOf(item);
|
||||
if (index !== -1) {
|
||||
dynamicValidateForm.cluster.splice(index, 1);
|
||||
}
|
||||
};
|
||||
|
||||
const addCluster = () => {
|
||||
const id = Date.now();
|
||||
dynamicValidateForm.cluster.push({
|
||||
clusterNodeId: '',
|
||||
port: '',
|
||||
host: '',
|
||||
publicPort: '',
|
||||
publicHost: '',
|
||||
id,
|
||||
});
|
||||
activeKey.value = [...activeKey.value, id.toString()];
|
||||
};
|
||||
|
||||
const filterOption = (input: string, option: any) => {
|
||||
return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0;
|
||||
};
|
||||
|
||||
const handleChangeForm2Sip = (index: number) => {
|
||||
dynamicValidateForm.cluster[index].port = '';
|
||||
const value = dynamicValidateForm.cluster[index].host;
|
||||
sipListIndex.value[index] = sipListConst
|
||||
.find((i: any) => i.host === value)
|
||||
?.portList.map((i: any) => {
|
||||
return {
|
||||
value: JSON.stringify({
|
||||
host: value,
|
||||
port: i.port,
|
||||
}),
|
||||
label: `${i.transports.join('/')} (${i.port})`,
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
const { resetFields, validate, validateInfos } = useForm(
|
||||
form,
|
||||
reactive({
|
||||
|
@ -592,61 +637,81 @@ const { resetFields, validate, validateInfos } = useForm(
|
|||
);
|
||||
|
||||
const saveData = () => {
|
||||
validate()
|
||||
.then(async (values) => {
|
||||
console.log(333, values);
|
||||
})
|
||||
.catch((err) => {});
|
||||
validate().then(async (values) => {
|
||||
params = {
|
||||
...params,
|
||||
...values,
|
||||
provider: 'gb28181-2016',
|
||||
transport: 'SIP',
|
||||
channel: 'gb28181',
|
||||
};
|
||||
const resp = !!id
|
||||
? await update({ ...params, id })
|
||||
: await save(params);
|
||||
if (resp.status === 200) {
|
||||
message.success('操作成功!');
|
||||
// if (params.get('save')) {
|
||||
// if ((window as any).onTabSaveSuccess) {
|
||||
// if (resp.result) {
|
||||
// (window as any).onTabSaveSuccess(resp.result);
|
||||
// setTimeout(() => window.close(), 300);
|
||||
// }
|
||||
// }
|
||||
// } else {
|
||||
history.back();
|
||||
// }
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const next = async () => {
|
||||
console.log(22, current.value);
|
||||
let data1: any = await formRef1.value?.validate();
|
||||
if (data1.hostPort?.port) {
|
||||
const port = JSON.parse(data1.hostPort.port).port;
|
||||
data1.hostPort.port = port;
|
||||
}
|
||||
if (!data1?.shareCluster) {
|
||||
let data2 = await formRef2.value?.validate();
|
||||
if (data2 && data2?.cluster) {
|
||||
data2.cluster.forEach((i: any) => {
|
||||
i.enabled = true;
|
||||
i.port = JSON.parse(i.port).port;
|
||||
});
|
||||
data1 = {
|
||||
...data1,
|
||||
...data2,
|
||||
};
|
||||
}
|
||||
}
|
||||
current.value = current.value + 1;
|
||||
params.configuration = data1;
|
||||
};
|
||||
const prev = () => {
|
||||
current.value = current.value - 1;
|
||||
};
|
||||
|
||||
interface FormState {
|
||||
domain: string;
|
||||
sipId: string;
|
||||
shareCluster: boolean;
|
||||
sip1: string;
|
||||
sip: string;
|
||||
public1: string;
|
||||
public: string;
|
||||
}
|
||||
const formState = reactive<FormState>({
|
||||
domain: '',
|
||||
sipId: '',
|
||||
shareCluster: true,
|
||||
sip1: '0.0.0.0',
|
||||
sip: '',
|
||||
public1: '',
|
||||
public: '',
|
||||
});
|
||||
const onFinish = (values: any) => {
|
||||
console.log('Success:', values);
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
getResourcesCurrent().then((resp) => {
|
||||
if (resp.status === 200) {
|
||||
const data: any = resp.result.find((i) => i.host === '0.0.0.0');
|
||||
const list = data.portList.map((i) => {
|
||||
const label = `${i.transports.join('/')} (${i.port})`;
|
||||
const value = {
|
||||
host: '0.0.0.0',
|
||||
port: i.port,
|
||||
};
|
||||
return {
|
||||
value: JSON.stringify(value),
|
||||
label,
|
||||
};
|
||||
});
|
||||
sipList.value = list;
|
||||
sipListConst = resp.result;
|
||||
sipListOption.value = sipListConst.map((i) => ({
|
||||
value: i.host,
|
||||
label: i.host,
|
||||
}));
|
||||
|
||||
sipList.value = sipListConst
|
||||
.find((i) => i.host === '0.0.0.0')
|
||||
?.portList.map((i) => {
|
||||
return {
|
||||
value: JSON.stringify({
|
||||
host: '0.0.0.0',
|
||||
port: i.port,
|
||||
}),
|
||||
label: `${i.transports.join('/')} (${i.port})`,
|
||||
};
|
||||
});
|
||||
}
|
||||
});
|
||||
console.log(1);
|
||||
|
||||
getClusters().then((resp) => {
|
||||
if (resp.status === 200) {
|
||||
|
@ -662,11 +727,7 @@ onMounted(() => {
|
|||
watch(
|
||||
current,
|
||||
(v) => {
|
||||
// if (props.provider.channel !== 'child-device') {
|
||||
// stepCurrent.value = v;
|
||||
// } else {
|
||||
// stepCurrent.value = v - 1;
|
||||
// }
|
||||
stepCurrent.value = v;
|
||||
},
|
||||
{
|
||||
deep: true,
|
||||
|
@ -745,4 +806,17 @@ watch(
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
.form-item1 {
|
||||
background-color: #f6f6f6;
|
||||
padding: 10px;
|
||||
}
|
||||
.form-label {
|
||||
height: 30px;
|
||||
padding-bottom: 8px;
|
||||
.form-label-required {
|
||||
color: red;
|
||||
margin: 0 4px 0 -2px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -78,11 +78,14 @@
|
|||
import { message, Form } from 'ant-design-vue';
|
||||
import type { FormInstance } from 'ant-design-vue';
|
||||
import GB28181 from './GB28181.vue';
|
||||
import { update, save } from '@/api/link/accessConfig';
|
||||
|
||||
interface FormState {
|
||||
name: string;
|
||||
description: string;
|
||||
}
|
||||
const route = useRoute();
|
||||
const id = route.query.id;
|
||||
|
||||
const props = defineProps({
|
||||
provider: {
|
||||
|
@ -96,14 +99,32 @@ const props = defineProps({
|
|||
});
|
||||
|
||||
const channel = ref(props.provider.channel);
|
||||
console.log(211, channel.value, props);
|
||||
|
||||
const formState = reactive<FormState>({
|
||||
name: '',
|
||||
description: '',
|
||||
});
|
||||
const onFinish = (values: any) => {
|
||||
console.log('Success:', values);
|
||||
const onFinish = async (values: any) => {
|
||||
const params = {
|
||||
...values,
|
||||
provider: 'fixed-media',
|
||||
transport: 'URL',
|
||||
channel: 'fixed-media',
|
||||
};
|
||||
const resp = !!id ? await update({ ...params, id }) : await save(params);
|
||||
if (resp.status === 200) {
|
||||
message.success('操作成功!');
|
||||
// if (params.get('save')) {
|
||||
// if ((window as any).onTabSaveSuccess) {
|
||||
// if (resp.result) {
|
||||
// (window as any).onTabSaveSuccess(resp.result);
|
||||
// setTimeout(() => window.close(), 300);
|
||||
// }
|
||||
// }
|
||||
// } else {
|
||||
history.back();
|
||||
// }
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
|
|
|
@ -295,11 +295,7 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="steps-action">
|
||||
<a-button
|
||||
v-if="[0, 1].includes(current)"
|
||||
type="primary"
|
||||
@click="next"
|
||||
>
|
||||
<a-button v-if="[0, 1].includes(current)" @click="next">
|
||||
下一步
|
||||
</a-button>
|
||||
<a-button v-if="current === 2" type="primary" @click="saveData">
|
||||
|
@ -588,8 +584,12 @@ const { resetFields, validate, validateInfos } = useForm(
|
|||
}),
|
||||
);
|
||||
|
||||
const queryNetworkList = async (id: string, params: object, data = {}) => {
|
||||
const resp = await getNetworkList(NetworkTypeMapping.get(id), data, params);
|
||||
const queryNetworkList = async (id: string, include: string, data = {}) => {
|
||||
const resp = await getNetworkList(
|
||||
NetworkTypeMapping.get(id),
|
||||
include,
|
||||
data,
|
||||
);
|
||||
if (resp.status === 200) {
|
||||
networkList.value = resp.result;
|
||||
}
|
||||
|
@ -623,9 +623,7 @@ const addNetwork = () => {
|
|||
tab.onTabSaveSuccess = (value) => {
|
||||
if (value.success) {
|
||||
networkCurrent.value = value.result.id;
|
||||
queryNetworkList(props.provider?.id, {
|
||||
include: networkCurrent.value || '',
|
||||
});
|
||||
queryNetworkList(props.provider?.id, networkCurrent.value || '');
|
||||
}
|
||||
};
|
||||
};
|
||||
|
@ -648,20 +646,14 @@ const checkedChange = (id: string) => {
|
|||
};
|
||||
|
||||
const networkSearch = (value: string) => {
|
||||
queryNetworkList(
|
||||
props.provider.id,
|
||||
{
|
||||
include: networkCurrent.value || '',
|
||||
},
|
||||
{
|
||||
terms: [
|
||||
{
|
||||
column: 'name$LIKE',
|
||||
value: `%${value}%`,
|
||||
},
|
||||
],
|
||||
},
|
||||
);
|
||||
queryNetworkList(props.provider.id, networkCurrent.value || '', {
|
||||
terms: [
|
||||
{
|
||||
column: 'name$LIKE',
|
||||
value: `%${value}%`,
|
||||
},
|
||||
],
|
||||
});
|
||||
};
|
||||
const procotolChange = (id: string) => {
|
||||
if (!props.data.id) {
|
||||
|
@ -862,9 +854,7 @@ onMounted(() => {
|
|||
procotolCurrent.value = props.data.protocol;
|
||||
current.value = 0;
|
||||
networkCurrent.value = props.data.channelId;
|
||||
queryNetworkList(props.provider.id, {
|
||||
include: networkCurrent.value,
|
||||
});
|
||||
queryNetworkList(props.provider.id, networkCurrent.value);
|
||||
procotolCurrent.value = props.data.protocol;
|
||||
steps.value = ['网络组件', '消息协议', '完成'];
|
||||
} else {
|
||||
|
@ -875,9 +865,7 @@ onMounted(() => {
|
|||
} else {
|
||||
if (props.provider?.id) {
|
||||
if (props.provider.channel !== 'child-device') {
|
||||
queryNetworkList(props.provider.id, {
|
||||
include: '',
|
||||
});
|
||||
queryNetworkList(props.provider.id, '');
|
||||
steps.value = ['网络组件', '消息协议', '完成'];
|
||||
current.value = 0;
|
||||
} else {
|
||||
|
|
|
@ -0,0 +1,105 @@
|
|||
<!-- webhook请求头可编辑表格 -->
|
||||
<template>
|
||||
<div class="attachment-wrapper">
|
||||
<div
|
||||
class="attachment-item"
|
||||
v-for="(item, index) in fileList"
|
||||
:key="index"
|
||||
>
|
||||
<a-input v-model:value="item.name">
|
||||
<template #addonAfter>
|
||||
<a-upload
|
||||
name="file"
|
||||
:action="FILE_UPLOAD"
|
||||
:headers="{
|
||||
[TOKEN_KEY]: LocalStore.get(TOKEN_KEY),
|
||||
}"
|
||||
:showUploadList="false"
|
||||
@change="handleChange"
|
||||
>
|
||||
<upload-outlined />
|
||||
</a-upload>
|
||||
</template>
|
||||
</a-input>
|
||||
<delete-outlined @click="handleDelete" style="cursor: pointer" />
|
||||
</div>
|
||||
|
||||
<a-button
|
||||
type="dashed"
|
||||
@click="handleAdd"
|
||||
style="width: 100%; margin-top: 5px"
|
||||
>
|
||||
<template #icon>
|
||||
<plus-outlined />
|
||||
</template>
|
||||
添加
|
||||
</a-button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts" name="Attachments">
|
||||
import {
|
||||
PlusOutlined,
|
||||
DeleteOutlined,
|
||||
UploadOutlined,
|
||||
} from '@ant-design/icons-vue';
|
||||
import { PropType } from 'vue';
|
||||
import { IAttachments } from '../../types';
|
||||
import { FILE_UPLOAD } from '@/api/comm';
|
||||
import { LocalStore } from '@/utils/comm';
|
||||
import { TOKEN_KEY } from '@/utils/variable';
|
||||
import { UploadChangeParam } from 'ant-design-vue';
|
||||
|
||||
type Emits = {
|
||||
(e: 'update:attachments', data: IAttachments[]): void;
|
||||
};
|
||||
const emit = defineEmits<Emits>();
|
||||
|
||||
const props = defineProps({
|
||||
attachments: {
|
||||
type: Array as PropType<IAttachments[]>,
|
||||
default: () => [],
|
||||
},
|
||||
});
|
||||
|
||||
const handleChange = (info: UploadChangeParam) => {
|
||||
if (info.file.status === 'done') {
|
||||
const result = info.file.response?.result;
|
||||
console.log('result: ', result);
|
||||
}
|
||||
};
|
||||
|
||||
const fileList = ref<IAttachments[]>([]);
|
||||
watch(
|
||||
() => props.attachments,
|
||||
(val) => {
|
||||
fileList.value = val;
|
||||
},
|
||||
{ deep: true },
|
||||
);
|
||||
|
||||
const handleDelete = (id: number) => {
|
||||
const idx = fileList.value.findIndex((f) => f.id === id);
|
||||
fileList.value.splice(idx, 1);
|
||||
emit('update:attachments', fileList.value);
|
||||
};
|
||||
const handleAdd = () => {
|
||||
fileList.value.push({
|
||||
id: fileList.value.length,
|
||||
name: '',
|
||||
location: '',
|
||||
});
|
||||
emit('update:attachments', fileList.value);
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.attachment-wrapper {
|
||||
.attachment-item {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
align-items: center;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -259,10 +259,11 @@
|
|||
</a-select>
|
||||
</a-form-item>
|
||||
<a-form-item label="附件信息">
|
||||
<!-- <a-input
|
||||
v-model:value="formData.template.attachments"
|
||||
placeholder="请上传文件或输入文件名称"
|
||||
/> -->
|
||||
<Attachments
|
||||
v-model:attachments="
|
||||
formData.template.attachments
|
||||
"
|
||||
/>
|
||||
</a-form-item>
|
||||
</template>
|
||||
<!-- 语音 -->
|
||||
|
@ -461,6 +462,7 @@ import {
|
|||
import templateApi from '@/api/notice/template';
|
||||
import Doc from './doc/index';
|
||||
import MonacoEditor from '@/components/MonacoEditor/index.vue';
|
||||
import Attachments from './components/Attachments.vue'
|
||||
|
||||
const router = useRouter();
|
||||
const route = useRoute();
|
||||
|
|
|
@ -7,6 +7,7 @@ export interface IHeaders {
|
|||
interface IAttachments {
|
||||
location: string;
|
||||
name: string;
|
||||
id?: number;
|
||||
}
|
||||
interface IVariableDefinitions {
|
||||
id: string;
|
||||
|
|
Loading…
Reference in New Issue