Merge branch 'dev' of github.com:jetlinks/jetlinks-ui-vue into dev

This commit is contained in:
leiqiaochu 2023-07-15 16:24:49 +08:00
commit ae12ae34ec
11 changed files with 200 additions and 73 deletions

View File

@ -74,6 +74,7 @@
<div class="header">
<div class="title">
<div>运行结果</div>
<div v-if="virtualRule?.script && !isBeginning">正在运行......</div>
</div>
<div class="action">
<div v-if="virtualRule?.script">
@ -127,6 +128,7 @@ type propertyType = {
last?: string;
};
const property = ref<propertyType[]>([]);
// virtualRule?.rule?.windowType === 'undefined' ? moment(item.time).format('HH:mm:ss')
const columns = [
{

View File

@ -613,6 +613,7 @@ const onPlatError = (val: any) => {
_errorSet.value.add(val)
}
};
const _validator = (_rule: any, value: string): Promise<any> =>
new Promise((resolve, reject) => {
const _item = productList.value.find((item) => item.id === value);
@ -657,7 +658,7 @@ watch(
async (newId) => {
if (newId) {
queryRegionsList();
getProduct();
await getProduct();
if (newId === ':id' || !newId) return;
const resp = await detail(newId as string);
const _data: any = resp.result;

View File

@ -17,60 +17,66 @@
</template>
<script lang="ts" setup>
import { PropType } from "vue";
import { PropType } from 'vue';
import { Form } from 'jetlinks-ui-components';
const props = defineProps({
disabled: {
type: Boolean,
default: false
default: false,
},
options: {
type: Array as PropType<any[]>,
default: () => []
default: () => [],
},
value: {
type: String,
default: undefined
default: undefined,
},
type: {
type: String,
default: 'product'
}
})
default: 'product',
},
});
const emits = defineEmits(['update:value', 'change', 'error']);
const formItemContext = Form.useInjectFormItemContext()
const formItemContext = Form.useInjectFormItemContext();
const _value = ref<any>(undefined)
const _value = ref<any>(undefined);
const formTouchOff = () => {
formItemContext.onFieldChange()
}
formItemContext.onFieldChange();
};
const _options = computed(() => {
if(props.type === 'product') {
return props.options.filter(i => i?.state || i.id === props.value)
if (props.type === 'product') {
return props.options.filter((i) => i?.state || i.id === props.value);
} else {
return props.options
return props.options;
}
})
});
watchEffect(() => {
_value.value = props.value
if(props.type !== 'product') {
formTouchOff()
} else {
if(props.value){
formTouchOff()
watch(
() => props.value,
() => {
_value.value = props.value;
if (props.type !== 'product') {
formTouchOff();
} else {
if (props.value) {
formTouchOff();
}
emits('error', props.value);
}
emits('error', props.value)
},
{
immediate: true
}
})
);
const productChange = (val: any) => {
emits('update:value', val)
emits('change', val)
}
emits('update:value', val);
emits('change', val);
};
</script>

View File

@ -210,6 +210,7 @@ import { PropertiesModal, FunctionModal, EventModal, TagsModal } from './DetailM
import { Modal } from 'jetlinks-ui-components'
import {EventEmitter} from "@/utils/utils";
import {watch} from "vue";
import {cloneDeep} from "lodash";
const props = defineProps({
target: {
@ -361,7 +362,7 @@ const handleAddClick = async (_data?: any, index?: number) => {
};
const copyItem = (record: any, index: number) => {
const copyData = omit(record, ['_uuid', '_sortIndex'])
const copyData = cloneDeep(omit(record, ['_uuid', '_sortIndex']))
copyData.id = `copy_${copyData.id}`.slice(0,64)
handleAddClick(copyData, index)
}

View File

@ -235,7 +235,7 @@ const columns = [
type: 'select',
options: () =>
new Promise((resolve) => {
queryNoPagingPost({
query({
paging: false,
sorts: [
{
@ -246,8 +246,8 @@ const columns = [
}).then((resp: any) => {
resolve(
resp.result.map((item: any) => ({
label: item.name,
value: item.id,
label: item.sourceName,
value: item.sourceId,
})),
);
});

View File

@ -151,6 +151,14 @@
/^([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地址',
},
{
max: 65535,
message: '请输入1~65535之间的正整数'
},
{
min: 1,
message: '请输入1~65535之间的正整数'
},
]"
>
<j-input-number
@ -185,6 +193,7 @@
"
:min="1"
:max="65535"
:precision="0"
/>
</j-form-item>
</j-col>
@ -238,7 +247,6 @@
v-model:value="
cluster.clusterNodeId
"
:options="clustersList"
placeholder="请选择节点名称"
allowClear
show-search
@ -246,6 +254,9 @@
filterOption
"
>
<j-select-option v-for="i in getClusterNodeIds(cluster.clusterNodeId)" :value="i.value">
{{ i.label}}
</j-select-option>
</j-select>
</j-form-item>
</j-col>
@ -309,16 +320,20 @@
<div class="form-label"></div>
<j-select
v-model:value="cluster.port"
:options="
sipListIndex[index]
"
placeholder="请选择端口"
allowClear
show-search
:filter-option="
filterOption
"
/>
>
<j-select-option
v-for="i in getSipListOption(sipListIndex[index], cluster.port)"
:value="i.value"
>
{{ i.label }}
</j-select-option>
</j-select>
</j-form-item>
</j-col>
<j-col :span="4">
@ -389,6 +404,7 @@
"
:min="1"
:max="65535"
:precision="0"
/>
</j-form-item>
</j-col>
@ -450,23 +466,26 @@
</div>
</j-col>
<j-col :span="12">
<div class="doc" style="height: 400px">
<h1>接入方式</h1>
<p>
{{ provider.name }}
</p>
<p>
{{ provider.description }}
</p>
<h1>消息协议</h1>
<p>
{{
provider?.id === 'fixed-media'
? 'URL'
: 'SIP'
}}
</p>
</div>
<div style="height: 400px">
<title-component data="配置概览" />
<j-descriptions :column="1" :labelStyle="{ width: '80px'}">
<j-descriptions-item label="接入方式">{{ provider.name }}</j-descriptions-item>
<j-descriptions-item>
<span style="color: #a3a3a3">{{ provider.description }}</span>
</j-descriptions-item>
<j-descriptions-item label="SIP 域">{{ formState.domain }}</j-descriptions-item>
<j-descriptions-item label="SIP ID">{{ formState.sipId }}</j-descriptions-item>
<j-descriptions-item>
<!-- 共享配置 -->
<template v-if="formState.shareCluster">
<a-badge :text="`${formState.hostPort.publicHost}:${formState.hostPort.publicPort}`" status="processing" />
</template>
<template v-else>
<a-badge v-for="i in dynamicValidateForm.cluster" :text="`${i.publicHost}:${i.publicPort}`" status="processing" />
</template>
</j-descriptions-item>
</j-descriptions>
</div>
</j-col>
</j-row>
</div>
@ -667,8 +686,9 @@ const saveData = () => {
};
const next = async () => {
let data1: any = await formRef1.value?.validate();
if (!isNumber(data1.hostPort.port)) {
if (data1.hostPort?.port && !isNumber(data1.hostPort.port) && data1.shareCluster) {
data1.hostPort.port = JSON.parse(data1.hostPort.port).port;
}
if (!data1?.shareCluster) {
@ -721,6 +741,16 @@ const develop = () => {
}
};
const getClusterNodeIds = (id?: string) => {
const keys = dynamicValidateForm?.cluster?.map?.(item => item.clusterNodeId) || []
return clustersList.value.filter(item => item.value === id || !keys.includes(item.value) )
}
const getSipListOption = (list: any[], id: string) => {
const keys = dynamicValidateForm?.cluster?.map?.(item => item.port) || []
return (list || []).filter(item => item.value === id || !keys.includes(item.value) )
}
onMounted(() => {
getResourcesCurrent().then((resp) => {
if (resp.status === 200) {

View File

@ -284,18 +284,24 @@
.configuration
.port
"
:options="
portOptionsIndex[
index
]
"
placeholder="请选择本地端口"
allowClear
show-search
:filter-option="
filterPortOption
"
/>
>
<j-select-option
v-for="i in getPortList( portOptionsIndex[
index
], cluster
.configuration
.port)"
:value="i.value"
>
{{ i.label }}
</j-select-option>
</j-select>
</j-form-item>
</j-col>
<j-col
@ -1190,6 +1196,12 @@ const filterPortOption = (input: string, option: any) => {
return JSON.stringify(option.label).indexOf(input) >= 0;
};
const getPortList = (list: any[], id: string) => {
const keys = dynamicValidateForm?.cluster?.map?.(item => item.configuration?.port) || []
console.log(dynamicValidateForm?.cluster, id, keys)
return (list || []).filter(item => item.value === id || !keys.includes(item.value) )
}
const filterConfigByType = (data: any[], type: string) => {
let _temp = type;
if (TCPList.includes(type)) {

View File

@ -12,8 +12,9 @@
:request="(e) => handleData(e)"
model="CARD"
:bodyStyle="{
padding: 0
padding: 0,
}"
ref="tableRef"
:params="params"
:gridColumn="2"
:noPagination="true"
@ -83,6 +84,10 @@ const props = defineProps({
type: String,
default: '',
},
notifyType: {
type: String,
default: '',
},
});
const emit = defineEmits(['update:value', 'change', 'update:detail']);
@ -97,6 +102,7 @@ const getMethodTxt = (type: string) => {
const params = ref<Record<string, any>>({});
const _selectedRowKeys = ref<string[]>([]);
const tableRef = ref<any>();
const columns = [
{
@ -129,19 +135,70 @@ const handleSearch = (_params: any) => {
params.value = _params;
};
const handleClick = (dt: any) => {
const typeObj = {
weixin: 'wechat',
dingTalk: 'dingtalk',
};
const queryUserList = async (id: string) => {
if (!(props.notifyType && props.notifierId)) return '';
const resp = await TemplateApi.getUser(
typeObj[props.notifyType],
props.notifierId,
);
if (resp.status === 200) {
return resp.result?.find((item: any) => item.id === id)?.name;
} else {
return '';
}
};
const queryOrgList = async (id: string) => {
if (!(props.notifyType && props.notifierId)) return '';
const resp = await TemplateApi.getDept(
typeObj[props.notifyType],
props.notifierId,
);
if (resp.status === 200) {
return resp.result?.find((item: any) => item.id === id)?.name;
} else {
return '';
}
};
const getOptions = async (dt: any) => {
const obj = {};
//
if (props.notifyType === 'weixin') {
if (dt?.template?.toParty) {
obj['orgName'] = await queryOrgList(dt?.template?.toParty);
}
if (dt?.template?.toUser) {
obj['sendTo'] = await queryUserList(dt?.template?.toUser);
}
}
if (props.notifyType === 'dingTalk') {
if (dt?.template?.departmentIdList) {
obj['orgName'] = await queryOrgList(dt?.template?.departmentIdList);
}
if (dt?.template?.userIdList) {
obj['sendTo'] = await queryUserList(dt?.template?.userIdList);
}
}
return obj;
};
const handleClick = async (dt: any) => {
if (_selectedRowKeys.value.includes(dt.id)) {
_selectedRowKeys.value = [];
emit('update:value', undefined);
// emit('change', { templateName: undefined, orgName: undefined, sendTo: undefined });
emit('change', { templateName: undefined });
emit('change', { templateName: undefined, orgName: undefined, sendTo: undefined });
emit('update:detail', undefined);
} else {
// console.log(dt)
const obj = await getOptions(dt)
_selectedRowKeys.value = [dt.id];
emit('change', { templateName: dt?.name, ...obj });
emit('update:value', dt.id);
// emit('change', { templateName: dt?.name, orgName: dt.template?.departmentIdList, sendTo: dt.template?.userIdList });
emit('change', { templateName: dt?.name });
emit('update:detail', dt);
}
};
@ -176,6 +233,7 @@ watch(
(newValue) => {
if (newValue) {
_selectedRowKeys.value = [newValue];
// (tableRef.value?._dataSource || []).find()
} else {
_selectedRowKeys.value = [];
}

View File

@ -48,6 +48,7 @@
<NotifyTemplate
v-model:value="formModel.templateId"
v-model:detail="template"
:notifyType="formModel.notifyType"
:notifierId="formModel.notifierId"
@change="(val) => onValChange(val, 'templateId')"
/>

View File

@ -104,7 +104,7 @@
mode="multiple"
style="width: calc(100% - 40px)"
placeholder="请选择角色"
:options="form.roleOptions"
:options="_roleOptions"
:disabled="form.data.username === 'admin'"
></j-select>
@ -123,7 +123,7 @@
show-search
style="width: calc(100% - 40px)"
placeholder="请选择组织"
:tree-data="form.departmentOptions"
:tree-data="_departmentOptions"
:fieldNames="{ label: 'name', value: 'id' }"
multiple
:filterTreeNode="
@ -205,6 +205,7 @@ import { DefaultOptionType } from 'ant-design-vue/es/vc-tree-select/TreeSelect';
import { AxiosResponse } from 'axios';
import { passwordRegEx } from '@/utils/validate';
import { filterSelectNode, onlyMessage } from '@/utils/comm';
import { uniqBy } from 'lodash-es';
const deptPermission = 'system/Department';
const rolePermission = 'system/Role';
@ -279,6 +280,9 @@ const form = reactive({
roleOptions: [] as optionType[],
departmentOptions: [] as DefaultOptionType[],
_roleOptions: [] as optionType[],
_departmentOptions: [] as DefaultOptionType[],
init: () => {
form.getDepartmentList();
form.getRoleList();
@ -286,7 +290,6 @@ const form = reactive({
},
getUserInfo: () => {
const id = props.data.id || '';
console.log(111);
if (props.type === 'add') form.data = {} as formType;
else if (props.type === 'reset') form.data = { id } as formType;
@ -301,6 +304,10 @@ const form = reactive({
(item: dictType) => item.id,
),
};
form._roleOptions = resp.result?.roleList?.map((i: any) => {
return {label: i.name, value: i.id}
});
form._departmentOptions = resp.result?.orgList
nextTick(() => {
formRef.value?.clearValidate();
});
@ -358,6 +365,15 @@ const form = reactive({
};
},
});
const _roleOptions = computed(() => {
return uniqBy([...form.roleOptions, ...form._roleOptions], 'value')
})
const _departmentOptions = computed(() => {
return uniqBy([...form.departmentOptions, ...form._departmentOptions], 'id')
})
form.init();
interface AxiosResponseRewrite<T = any[]> extends AxiosResponse<T, any> {

View File

@ -3837,8 +3837,8 @@ jetlinks-ui-components@^1.0.23:
jetlinks-ui-components@^1.0.24:
version "1.0.24"
resolved "http://registry.jetlinks.cn/jetlinks-ui-components/-/jetlinks-ui-components-1.0.24.tgz#0bd3caf482367d46974244558519dfa7919baf1f"
integrity sha512-bXJZUWU27kDpnvhR+zKtUZQjrq+S130abBD2D37PnbHeUtT8g/i1CRV8Qnp1SMzk7aRDH9glVSjbzIQxem3YMQ==
resolved "http://registry.jetlinks.cn/jetlinks-ui-components/-/jetlinks-ui-components-1.0.24.tgz#a1262b3a735a01cd1fd9801406d16291b5070367"
integrity sha512-P4aolPQb1/wq4edN0AZ6WSavVAvQ+KEOEFzAarL/0dy6Oz3tTVemZmtgu20TsGbrNnEe/LheMu0QpvmkOq+3dg==
dependencies:
"@vueuse/core" "^9.12.0"
"@vueuse/router" "^9.13.0"