Merge branch 'dev' into dev-edge

# Conflicts:
#	yarn.lock
This commit is contained in:
XieYongHong 2023-07-28 12:29:09 +08:00
commit 7ba89d6b69
45 changed files with 320 additions and 177 deletions

View File

@ -10,7 +10,7 @@ export const updateMeInfo_api = (data:object) => server.put(`/user/detail`,data)
// 修改登录用户密码
export const updateMepsd_api = (data:object) => server.put(`/user/passwd`,data);
// 第三方账号解绑
export const unBind_api = (appId: string) => server.request.post(`/application/sso/${appId}/unbind/me`);
export const unBind_api = (appId: string) => server.post(`/application/sso/${appId}/unbind/me`);
/**
*
* @param type

View File

@ -5,6 +5,7 @@
visible
width="70vw"
title="编辑规则"
:getContainer="(node) => fullRef || node"
@cancel="handleCancel"
:destroyOnClose="true"
>
@ -57,6 +58,7 @@
import Editor from './Editor/index.vue';
import Debug from './Debug/index.vue';
import Operator from './Operator/index.vue';
import { FULL_CODE } from 'jetlinks-ui-components/es/DataTable'
interface Emits {
(e: 'save', data: string | undefined): void;
@ -73,6 +75,7 @@ const props = defineProps({
const _value = ref<string | undefined>(props.value);
const _disabled = ref<boolean>(true);
const fullRef = inject(FULL_CODE);
const handleCancel = () => {
emit('close');

View File

@ -61,7 +61,7 @@ const layoutConf = reactive({
siderWidth: layout.value.siderWidth,
logo: DefaultSetting.layout.logo,
title: DefaultSetting.layout.title,
menuData: [...menu.siderMenus, AccountMenu],
menuData: menu.siderMenus,
// menuData: menu.siderMenus,
splitMenus: true,
});

View File

@ -8,6 +8,7 @@
:options="options"
allowClear
style="width: 100%"
:getPopupContainer="getPopupContainer"
@change='selectChange'
/>
<j-time-picker
@ -16,6 +17,7 @@
allowClear
valueFormat="HH:mm:ss"
style="width: 100%"
:getPopupContainer="getPopupContainer"
@change='timeChange'
/>
<j-date-picker
@ -25,6 +27,7 @@
showTime
valueFormat="YYYY-MM-DD HH:mm:ss"
style="width: 100%"
:getPopupContainer="getPopupContainer"
@change='dateChange'
/>
<j-input-number
@ -93,6 +96,7 @@
cancel-text="取消"
v-model:visible="modalVis"
width="700px"
:getPopupContainer="getPopupContainer"
@cancel="modalVis = false"
@ok="handleItemModalSubmit"
:zIndex='1100'
@ -149,6 +153,10 @@ const props = defineProps({
placeholder: {
type: String,
default: () => '',
},
getPopupContainer: {
type: Function,
default: undefined
}
});
// type Props = {

View File

@ -123,7 +123,7 @@ export const useMenuStore = defineStore({
})
// console.log(menusData)
// menusData.push(AccountMenu)
this.siderMenus = silderMenus.filter((item: { name: string }) => ![USER_CENTER_MENU_CODE, NotificationRecordCode, NotificationSubscriptionCode].includes(item.name))
this.siderMenus = silderMenus
res(menusData)
}
})

View File

@ -487,7 +487,7 @@ export const handleMenusMap = (menuData: any[], cb: (data: any) => void) => {
}
const hideInMenu = (code: string) => {
return ['account-center', 'message-subscribe'].includes(code)
return ['account-center', 'account-center', 'message-subscribe'].includes(code)
}
export const handleSiderMenu = (menuData: any[]) => {

View File

@ -83,6 +83,9 @@ const handleOptions = (x = [], y = []) => {
const chart: any = chartRef.value;
if (chart) {
const myChart = echarts.init(chart);
const maxY: number = y.sort((a,b)=>{
return b-a
})?.[0]
const options = {
xAxis: {
type: 'category',
@ -93,8 +96,8 @@ const handleOptions = (x = [], y = []) => {
type: 'value',
},
grid: {
left: '80px',
right: '50px',
left: maxY < 1000 ? 60 : maxY.toString().length * 10,
right: '60px',
},
tooltip: {
trigger: 'axis',

View File

@ -12,7 +12,7 @@
/>
</j-col>
</j-row>
<j-row :gutter="24">
<j-row :gutter="24" style="margin-top: 24px;">
<j-col :span="24">
<Card />
</j-col>
@ -26,14 +26,19 @@ import Card from './components/Card.vue';
import { getImage } from '@/utils/comm';
import { queryCount } from '@/api/data-collect/dashboard';
import { defaultParams, statusData } from './tool';
import { useMenuStore } from '@/store/menu';
const menuPermission = useMenuStore().hasMenu;
const StatusData = ref(statusData);
const getNumberData = () => {
StatusData.value.forEach(async (item: any) => {
const res = await queryCount(item[0].type, {});
const resp = await queryCount(item[0].type, defaultParams);
item[0].total = res?.result;
item[0].value = resp?.result;
if(menuPermission(item[0]?.permission)) {
const res = await queryCount(item[0].type, {});
const resp = await queryCount(item[0].type, defaultParams);
item[0].total = res?.result;
item[0].value = resp?.result;
}
});
};
onMounted(() => {

View File

@ -39,13 +39,13 @@ const getParams = (dt: any) => {
};
} else if (time > days && time <= days * 7) {
return {
limit: Math.abs(Math.ceil(time / days / 7)) + 1,
limit: Math.abs(Math.ceil(time / days)) + 1,
interval: '1d',
format: 'YYYY-MM-dd HH:mm',
};
} else if (time >= year) {
} else if (time > days*90) {
return {
limit: Math.abs(Math.ceil(time / days / 31)) + 1,
limit: Math.abs(Math.ceil(time / days / 30)) + 1,
interval: '1M',
format: 'YYYY-MM-dd HH:mm',
};
@ -137,6 +137,7 @@ export const statusData = [
label: '通道数量',
value: 0,
total: 0,
permission: 'DataCollect/Channel'
},
],
[
@ -147,6 +148,7 @@ export const statusData = [
label: '采集器数量',
value: 0,
total: 0,
permission: 'DataCollect/Collector'
},
],
[
@ -157,6 +159,7 @@ export const statusData = [
label: '采集点位',
value: 0,
total: 0,
permission: 'DataCollect/Collector'
},
],
];

View File

@ -6,6 +6,8 @@
width="770px"
@cancel="emits('close')"
:confirmLoading="loading"
:zIndex="1100"
:maskClosable='false'
>
<j-form :model="form" layout="vertical" ref="formRef">
<j-row :gutter="24">
@ -66,7 +68,7 @@
:rules="[
{
pattern: /^1[3456789]\d{9}$/,
message: '请输入正确手机号',
message: '请输入正确手机号',
},
]"
>

View File

@ -1,5 +1,5 @@
<template>
<j-modal :width="'900px'" visible @cancel="emit('close')" :zIndex="1100">
<j-modal :maskClosable='false' :width="'900px'" visible @cancel="emit('close')" :zIndex="1100">
<template v-if="getType === 'notifier-weixin'">
<j-spin :spinning="loading">
<div class="code" style="height: 450px">

View File

@ -28,11 +28,14 @@
<template v-else>
<Detail
@unsubscribe="onUnSubscribe"
@save="onSave"
v-if="current?.channelProvider !== 'inside-mail' && popoverVisible"
v-if="
current?.channelProvider !== 'inside-mail' &&
popoverVisible
"
:current="current"
:data="props.data"
@close="popoverVisible = false"
:data="data"
@bindChange="onChange('bind')"
@infoChange="onChange('info')"
/>
<PermissionButton
v-else
@ -51,12 +54,28 @@
{{ current?.name }}
</j-ellipsis>
</div>
<EditInfo
v-if="editInfoVisible"
:data="user.userInfos"
@close="editInfoVisible = false"
@save="onSave"
/>
<Bind
@close="visible = false"
v-if="visible"
:data="data"
:current="current"
@save="onBindSave"
/>
</div>
</template>
<script lang="ts" setup>
import { getImage } from '@/utils/comm';
import Detail from './Detail.vue';
import { useUserInfo } from '@/store/userInfo';
import EditInfo from '../../EditInfo/index.vue';
import Bind from './Bind.vue';
const iconMap = new Map();
iconMap.set('notifier-dingTalk', getImage('/notice-rule/dingtalk.png'));
@ -81,19 +100,44 @@ const props = defineProps({
},
notifyChannels: {
type: Array,
default: () => []
}
default: () => [],
},
});
const user = useUserInfo();
const popoverVisible = ref<boolean>(false);
const editInfoVisible = ref<boolean>(false);
const visible = ref<boolean>(false);
const onChange = (type: 'bind' | 'info') => {
if(type === 'bind'){
editInfoVisible.value = true
} else {
visible.value = true
}
}
const onSave = () => {
editInfoVisible.value = false;
user.getUserInfo();
emit('save', props.current);
popoverVisible.value = false;
};
const onBindSave = () => {
visible.value = false
emit('save', props.current);
popoverVisible.value = false;
}
const onUnSubscribe = (dt: any) => {
emit('unsubscribe', dt);
popoverVisible.value = false
popoverVisible.value = false;
};
const onCheckChange = (dt: any) => {
emit('save', dt)
popoverVisible.value = false
emit('save', dt);
popoverVisible.value = false;
};
</script>

View File

@ -21,29 +21,14 @@
>
</div>
</div>
<EditInfo
v-if="editInfoVisible"
:data="user.userInfos"
@close="editInfoVisible = false"
@save="onSave"
/>
<Bind
@close="visible = false"
v-if="visible"
:data="props.data"
:current="current"
@save="onBindSave"
/>
</template>
<script lang="ts" setup>
import { getIsBindThird } from '@/api/account/notificationSubscription';
import { useUserInfo } from '@/store/userInfo';
import EditInfo from '../../EditInfo/index.vue';
import Bind from './Bind.vue';
const user = useUserInfo();
const emit = defineEmits(['save', 'unsubscribe', 'close']);
const emit = defineEmits(['infoChange', 'unsubscribe', 'bindChange']);
const info = ref<any>(null);
const props = defineProps({
data: {
@ -58,39 +43,23 @@ const props = defineProps({
},
});
const editInfoVisible = ref<boolean>(false);
const visible = ref<boolean>(false);
const getType = computed(() => {
return props.current?.channelProvider;
});
const onBind = () => {
if (
['notifier-voice', 'notifier-sms', 'notifier-email'].includes(
!['notifier-voice', 'notifier-sms', 'notifier-email'].includes(
props.current?.channelProvider,
)
) {
editInfoVisible.value = true;
emit('infoChange')
} else {
visible.value = true
emit('bindChange')
}
};
const onSave = () => {
editInfoVisible.value = false;
user.getUserInfo();
emit('save', props.current);
emit('close')
};
const onBindSave = () => {
visible.value = false
emit('save', props.current);
emit('close')
}
const handleSearch = async () => {
if (
!['notifier-voice', 'notifier-sms', 'notifier-email'].includes(
@ -114,16 +83,6 @@ onMounted(() => {
handleSearch()
})
// watch(
// () => props.current,
// () => {
// handleSearch();
// },
// {
// immediate: true,
// deep: true,
// },
// );
</script>
<style lang="less" scoped>

View File

@ -1,5 +1,5 @@
<template>
<j-modal :width="'384px'" visible @cancel="emit('close')" :footer="null">
<j-modal :maskClosable='false' :width="'384px'" visible @cancel="emit('close')" :footer="null">
<template v-if="getType === 'notifier-dingTalk'">
<div class="tip">请先绑定钉钉账号</div>
</template>

View File

@ -164,7 +164,16 @@ import { isBoolean } from 'lodash';
import { onlyMessage } from '@/utils/comm';
const defaultValue =
'//解码函数\r\nfunction decode(context) {\r\n //原始报文\r\n var buffer = context.payload();\r\n // 转为json\r\n // var json = context.json();\r\n //mqtt 时通过此方法获取topic\r\n // var topic = context.topic();\r\n\r\n // 提取变量\r\n // var topicVars = context.pathVars("/{deviceId}/**",topic)\r\n //温度属性\r\n var temperature = buffer.getShort(3) * 10;\r\n //湿度属性\r\n var humidity = buffer.getShort(6) * 10;\r\n return {\r\n "temperature": temperature,\r\n "humidity": humidity\r\n };\r\n}\r\n';
`//注册设备下行数据监听器,当平台下发指令给设备时,回调将被调用,用于构造下发给设备的报文
codec.onDownstream(function(ctx){
});
//,,,.
codec.onUpstream(function(ctx){
});
`;
const el = ref<HTMLElement | null>(null);
const { toggle } = useFullscreen(el);

View File

@ -123,7 +123,16 @@ import { isBoolean } from 'lodash';
import { onlyMessage } from '@/utils/comm';
const defaultValue =
'//解码函数\r\nfunction decode(context) {\r\n //原始报文\r\n var buffer = context.payload();\r\n // 转为json\r\n // var json = context.json();\r\n //mqtt 时通过此方法获取topic\r\n // var topic = context.topic();\r\n\r\n // 提取变量\r\n // var topicVars = context.pathVars("/{deviceId}/**",topic)\r\n //温度属性\r\n var temperature = buffer.getShort(3) * 10;\r\n //湿度属性\r\n var humidity = buffer.getShort(6) * 10;\r\n return {\r\n "temperature": temperature,\r\n "humidity": humidity\r\n };\r\n}\r\n';
`//注册设备下行数据监听器,当平台下发指令给设备时,回调将被调用,用于构造下发给设备的报文
codec.onDownstream(function(ctx){
});
//,,,.
codec.onUpstream(function(ctx){
});
`;
const el = ref<HTMLElement | null>(null);
const { toggle } = useFullscreen(el);

View File

@ -164,7 +164,7 @@ const deviceList = ref([
label: '网关子设备',
value: 'childrenDevice',
iconUrl: getImage('/device-type-2.png'),
tooltip: '作为网关的子设备,网关代理连接到物联网平台',
tooltip: '作为网关的子设备,网关代理连接到物联网平台',
},
{
label: '网关设备',

View File

@ -341,7 +341,6 @@ export const useColumns = (type?: MetadataType, target?: 'device' | 'product', n
const fieldIndex = Number(field[1])
const values = dataSource.find((item, index) => index === fieldIndex)
return validatorConfig(values.output)
}
}]

View File

@ -12,6 +12,7 @@
<script setup name="ConstraintSelect">
import { set, get } from 'lodash-es'
import {FULL_CODE} from "jetlinks-ui-components/es/DataTable";
const props = defineProps({
value: {
@ -25,6 +26,7 @@ const props = defineProps({
})
const emit = defineEmits(['update:value'])
const fullRef = inject(FULL_CODE);
const myValue = ref()

View File

@ -3,6 +3,7 @@
v-model:value="value"
:options="options"
:placeholder="placeholder"
:getPopupContainer="(node) => fullRef || node"
@change="change"
/>
</template>
@ -10,7 +11,7 @@
<script setup lang="ts" name="SelectColumnn">
import type { PropType } from 'vue';
import { ref, watch } from 'vue';
import { FULL_CODE } from 'jetlinks-ui-components/es/DataTable'
type Emits = {
(e: 'update:value', data: Record<string, any>): void;
@ -18,6 +19,8 @@ type Emits = {
};
type SizeType = 'small' | 'middle' | 'large' | undefined;
const fullRef = inject(FULL_CODE);
const emit = defineEmits<Emits>();
const props = defineProps({
value: {

View File

@ -3,6 +3,7 @@
v-model:value="value"
:options="options"
:placeholder="placeholder"
:get-popup-container="(node) => fullRef || node"
@change="change"
/>
</template>
@ -10,8 +11,8 @@
<script setup lang="ts" name="SelectColumnn">
import type { PropType } from 'vue';
import { ref, watch } from 'vue';
import { FULL_CODE } from 'jetlinks-ui-components/es/DataTable'
type Emits = {
(e: 'update:value', data: Record<string, any>): void;
(e: 'change', data: string): void;
@ -36,7 +37,7 @@
});
const value = ref(props.value.async);
const fullRef = inject(FULL_CODE);
const change = (v: string) => {
emit('update:value', {...props.value, async: value.value});
emit('change', v);

View File

@ -5,11 +5,13 @@
{ label: '固定值', value: 'false' },
{ label: '范围值', value: 'true' },
]"
:get-popup-container="(node) => fullRef || node"
@select="select"
/>
</template>
<script name="BooleanSelect" setup>
import { FULL_CODE } from 'jetlinks-ui-components/es/DataTable'
const props = defineProps({
value: {
@ -17,8 +19,10 @@ const props = defineProps({
default: () => ({})
}
})
const emit = defineEmits(['update:value'])
const fullRef = inject(FULL_CODE);
const myValue = ref()
const select = (e) => {
emit('update:value', {

View File

@ -90,6 +90,14 @@ const columns: any = [
form: {
required: true,
rules: [
{
callback(rule:any,value: any) {
if (!value) {
return Promise.reject('请输入指标名称')
}
return Promise.resolve()
}
},
{ max: 64, message: '最多可输入64个字符' },
]
},
@ -107,11 +115,11 @@ const columns: any = [
required: true,
rules: [
{
validator(_: any, value: any) {
callback(rule:any,value: any) {
if (!value) {
return Promise.reject('请配置指标')
}
return validatorConfig(value, true)
return Promise.resolve()
}
},
]
@ -148,7 +156,7 @@ const addItem = () => {
const data = {
id: undefined,
name: undefined,
range: 'false',
range: false,
value: undefined,
}

View File

@ -6,6 +6,7 @@
<j-popconfirm-modal
:show-cancel="false"
body-style="width: 300px"
:get-popup-container="(node) => fullRef || node"
@confirm="confirm"
>
<template #content>
@ -39,6 +40,7 @@ import type { PropType } from 'vue';
import Item from './item.vue'
import {Form} from "jetlinks-ui-components";
import {cloneDeep} from "lodash";
import { FULL_CODE } from 'jetlinks-ui-components/es/DataTable'
type ValueType = number | Array<number | undefined> | undefined;
@ -55,7 +57,7 @@ const props = defineProps({
const emit = defineEmits<Emit>();
const formItemContext = Form.useInjectFormItemContext();
const fullRef = inject(FULL_CODE);
const formData = reactive<{
@ -89,6 +91,7 @@ const confirm = () => {
return new Promise((resolve, reject) => {
formRef.value.validate().then(() => {
const value = props.value.range === true ? formData.rangeValue : formData.value
console.log('confirm',value, props.value)
emit('update:value', {
...props.value,
value: value

View File

@ -7,7 +7,7 @@
@change="change"
/>
<j-input-number
v-else-if="['int', 'long', 'float', 'double'].includes(type)"
v-else-if="type === 'int'"
v-model:value="myValue"
:precision="0"
:max="2147483647"
@ -16,6 +16,25 @@
placeholder="请输入"
@change="change"
/>
<j-input-number
v-else-if="type === 'long'"
v-model:value="myValue"
:max="9223372036854775807"
:min="-9223372036854775808"
:precision="0"
placeholder="请输入"
style="width: 100%"
@change="change"
/>
<j-input-number
v-else-if="['float', 'double'].includes(type)"
v-model:value="myValue"
:max="9999999999999999"
:min="-9999999999999999"
placeholder="请输入"
style="width: 100%"
@change="change"
/>
<j-select
v-else-if="type === 'boolean'"
placeholder="请选择"
@ -23,17 +42,20 @@
{ label: '否', value: 'false'},
{ label: '是', value: 'true'},
]"
:get-popup-container="(node) => fullRef || node"
/>
<j-date-picker
v-else-if="type === 'date' "
v-model:value="myValue"
show-time
placeholder="请选择"
:get-popup-container="(node) => fullRef || node"
@change="change"
/>
</template>
<script setup name="MetricValueItem">
import { Form } from 'jetlinks-ui-components'
import {FULL_CODE} from "jetlinks-ui-components/es/DataTable";
const props = defineProps({
value: {
@ -47,6 +69,7 @@ const formItemContext = Form.useInjectFormItemContext();
const type = inject('metricsType')
const myValue = ref(props.value)
const fullRef = inject(FULL_CODE);
const change = () => {
// formItemContext.onFieldChange()

View File

@ -3,6 +3,7 @@
body-style="padding-top:4px;width:600px;"
placement="topRight"
:disabled="disabled"
:get-popup-container="(node) => fullRef || node"
@confirm="confirm"
@cancel="cancel"
@visibleChange="visibleChange"
@ -27,6 +28,7 @@
label: a.text,
value: a.value,
}))"
:get-popup-container="(node) => fullRef || node"
/>
</template>
</j-table>
@ -63,6 +65,7 @@ import {useInstanceStore} from "store/instance";
import {getMetadataConfig, getMetadataDeviceConfig} from "@/api/device/product";
import ModelButton from '@/views/device/components/Metadata/Base/components/ModelButton.vue'
import {omit} from "lodash-es";
import { FULL_CODE } from 'jetlinks-ui-components/es/DataTable'
const props = defineProps({
value: {
@ -83,6 +86,8 @@ const props = defineProps({
},
})
const fullRef = inject(FULL_CODE);
const type = inject('_metadataType')
const productStore = useProductStore()

View File

@ -16,6 +16,7 @@
label: a.text,
value: a.value,
}))"
:get-popup-container="(node) => fullRef || node"
/>
</template>
</j-table>
@ -29,6 +30,7 @@ import type { PropType } from "vue";
import { defineExpose } from 'vue'
import {getMetadataConfig, getMetadataDeviceConfig} from "@/api/device/product";
import { omit } from 'lodash-es'
import { FULL_CODE } from 'jetlinks-ui-components/es/DataTable'
const props = defineProps({
type: {
@ -47,7 +49,7 @@ const props = defineProps({
const productStore = useProductStore()
const deviceStore = useInstanceStore()
const fullRef = inject(FULL_CODE);
const config = ref<any>([])
const configValue = ref(props.record?.expands)

View File

@ -4,17 +4,20 @@
v-model:value="myValue"
:options="PropertySource"
placeholder="请选择来源"
@change="onChange"
:disabled="disabled"
:get-popup-container="(node) => fullRef || node"
@change="onChange"
>
</j-select>
<j-popconfirm-modal
v-if="myValue != 'manual'"
@confirm="confirm"
:bodyStyle="{
width: '450px',
height: myValue === 'rule' ? '300px' : '80px',
}"
:get-popup-container="(node) => fullRef || node"
placement="topLeft"
@confirm="confirm"
>
<template #content>
<j-scrollbar v-if="myValue">
@ -39,6 +42,7 @@
import { isNoCommunity } from '@/utils/utils';
import VirtualRule from './VirtualRule/index.vue';
import { Form } from 'jetlinks-ui-components';
import { FULL_CODE } from 'jetlinks-ui-components/es/DataTable'
const PropertySource: { label: string; value: string }[] = isNoCommunity
? [
@ -72,6 +76,8 @@ type Emit = {
(e: 'update:value', data: Record<string, any>): void;
};
const fullRef = inject(FULL_CODE);
const props = defineProps({
value: {
type: Object,

View File

@ -7,6 +7,7 @@
{ label: '写', value: 'write'},
{ label: '上报', value: 'report'},
]"
:get-popup-container="(node) => fullRef || node"
placeholder="请选择读写类型"
@change="onChange"
/>
@ -15,6 +16,7 @@
<script setup lang="ts">
import type {PropType} from "vue";
import { FULL_CODE } from 'jetlinks-ui-components/es/DataTable'
type Emit = {
(e: 'update:value', data: any): void
@ -28,7 +30,7 @@ const props = defineProps({
})
const emit = defineEmits<Emit>()
const fullRef = inject(FULL_CODE);
const myValue = ref<Array<string>>([])
const onChange = () =>{

View File

@ -26,7 +26,7 @@ const { jumpPage } = useMenuStore();
const projectNum = ref(0);
const deviceNum = ref(0);
const menuPermission = useMenuStore().hasPermission;
const menuPermission = useMenuStore().hasMenu;
const getData = () => {
//
menuPermission('device/Product') &&

View File

@ -193,11 +193,11 @@
<div class="progress-text">
<div>
{{
(
(slotProps.usedFlow /
slotProps.totalFlow ? (
(slotProps.usedFlow /
slotProps.totalFlow) *
100
).toFixed(2)
).toFixed(2) : '0.00'
}}
%
</div>
@ -209,9 +209,9 @@
:strokeColor="'#ADC6FF'"
:showInfo="false"
:percent="
(slotProps.usedFlow /
slotProps.totalFlow ? (slotProps.usedFlow /
slotProps.totalFlow) *
100
100 : 0
"
/>
</div>

View File

@ -45,7 +45,7 @@
v-if="serverOptions.length > 1"
v-model:value="serverActive"
:options="serverOptions"
color="#2CB6E0"
:color="colorCpu"
/>
</template>
</div>
@ -59,9 +59,10 @@ import dayjs from 'dayjs';
import {
getTimeByType,
arrayReverse,
defulteParamsData,
defaultParamsData,
areaStyleCpu,
typeDataLine,
colorCpu
} from './tool.ts';
import { DataType } from '../typings';
import ServerList from './ServerList.vue'
@ -97,6 +98,7 @@ const pickerTimeChange = () => {
};
const echartsOptions = computed(() => {
console.log(serverActive.value)
const series = serverActive.value.length
? serverActive.value.map((key) => setOptions(serverData.data, key))
: typeDataLine
@ -128,17 +130,18 @@ const echartsOptions = computed(() => {
end: data.value.type !== 'hour' ? 5 : 100,
},
],
color: ['#2CB6E0'],
color: colorCpu,
series: series
};
})
const getCPUEcharts = async (val: any) => {
loading.value = true;
const res: any = await dashboard(defulteParamsData('cpu', val));
const res: any = await dashboard(defaultParamsData('cpu', val));
if (res.success) {
const _cpuOptions = {};
const _cpuXAxis = new Set();
if (res.result?.length) {
isEmpty.value = false;
//
// const filterArray = props.isNoCommunity ? res.result.filter((item : any) => item.data?.clusterNodeId === props.serviceId) : res.result
const filterArray = res.result
@ -173,7 +176,7 @@ const setOptions = (optionsData: any, key: string) => ({
type: 'line',
smooth: true,
symbol: 'none',
areaStyle: areaStyleCpu,
// areaStyle: areaStyleCpu(index),
});
const handleCpuOptions = (optionsData: any, xAxis: any) => {

View File

@ -45,7 +45,7 @@
v-if="serverOptions.length > 1"
v-model:value="serverActive"
:options="serverOptions"
color="#60DFC7"
:color="colorJvm"
/>
</template>
</div>
@ -61,7 +61,8 @@ import {
arrayReverse,
typeDataLine,
areaStyleJvm,
defulteParamsData,
colorJvm,
defaultParamsData
} from './tool.ts';
import { DataType } from '../typings';
import ServerList from './ServerList.vue'
@ -98,11 +99,12 @@ const pickerTimeChange = () => {
const getJVMEcharts = async (val: any) => {
loading.value = true;
const res: any = await dashboard(defulteParamsData('jvm', val));
const res: any = await dashboard(defaultParamsData('jvm', val));
if (res.success) {
const _jvmOptions = {};
const _jvmXAxis = new Set();
if (res.result?.length) {
isEmpty.value = false;
// const filterArray = props.isNoCommunity ? res.result.filter((item : any) => item.data?.clusterNodeId === props.serviceId) : res.result
const filterArray = res.result
filterArray.forEach((item: any) => {
@ -141,7 +143,7 @@ const setOptions = (optionsData: any, key: string) => ({
type: 'line',
smooth: true,
symbol: 'none',
areaStyle: areaStyleJvm,
// areaStyle: areaStyleJvm(_index),
});
const handleJVMOptions = (optionsData: any, xAxis: any) => {
const dataKeys = Object.keys(optionsData);
@ -183,7 +185,7 @@ const echartsOptions = computed(() => {
end: data.value.type !== 'hour' ? 10 : 100,
},
],
color: ['#60DFC7'],
color: colorJvm,
series: series
}
})

View File

@ -7,6 +7,7 @@
<j-radio-group
button-style="solid"
v-model:value="data.type"
@change="() => { getNetworkEcharts(data) }"
>
<j-radio-button value="bytesRead">
上行
@ -72,6 +73,7 @@ import {
getTimeByType,
typeDataLine,
areaStyle,
colorNetwork,
networkParams, arrayReverse,
} from './tool.ts';
import dayjs from 'dayjs';
@ -105,6 +107,7 @@ const serverData = reactive({
const pickerTimeChange = (value: any) => {
data.value.time.type = undefined;
getNetworkEcharts(data.value);
};
const getNetworkEcharts = async (val: any) => {
@ -114,6 +117,7 @@ const getNetworkEcharts = async (val: any) => {
const _networkOptions = {};
const _networkXAxis = new Set();
if (resp.result.length) {
isEmpty.value = false;
const filterArray = resp.result
// const filterArray = resp.result.filter((item : any) => item.data?.clusterNodeId === props.serviceId)
filterArray.forEach((item: any) => {
@ -165,7 +169,7 @@ const setOptions = (data: any, key: string) => ({
name: key,
type: 'line',
smooth: true,
areaStyle,
// areaStyle,
});
const handleNetworkOptions = (optionsData: any, xAxis: any) => {
@ -202,7 +206,7 @@ const echartsOptions = computed(() => {
trigger: 'axis',
formatter: (_value: any) => networkValueRender(_value[0]),
},
color: ['#979AFF'],
color: colorNetwork,
series: series
};
})
@ -219,13 +223,6 @@ watch(
{ immediate: true, deep: true },
);
// watchEffect(() => {
// const time = data.value.time.time
// if (time && Array.isArray(time) && time.length === 2 && time[0] && props.serviceId) {
//
// }
// })
</script>
<style lang="less" scoped>

View File

@ -4,10 +4,10 @@
<j-scrollbar>
<div class="server-list-items">
<div
v-for="item in options" :class="['server-item', myValue.includes(item) ? 'active' : '']"
v-for="(item, index) in options" :key="item" :class="['server-item', myValue.includes(item) ? 'active' : '']"
@click="() => change(item)"
>
<j-badge :color=" myValue.includes(item) ? color : '#a3a3a3'" :text="item" />
<j-badge :color="myValue.includes(item) ? (Array.isArray(color) ? color[index % 5] : color) : '#a3a3a3'" :text="item" />
</div>
</div>
</j-scrollbar>
@ -26,7 +26,7 @@ const props = defineProps({
default: () => []
},
color: {
type: String,
type: [String, Array],
default: '#979AFF'
}
})

View File

@ -44,7 +44,7 @@ watch(() => props.options, () => {
echartsRender()
})
}
}, { deep: true })
}, { immediate: true, deep: true })
</script>

View File

@ -104,7 +104,7 @@ export const networkParams = (val: any) => {
},
];
};
export const defulteParamsData = (group: any, val: any) => [
export const defaultParamsData = (group: any, val: any) => [
{
dashboard: 'systemMonitor',
object: 'stats',
@ -119,6 +119,10 @@ export const defulteParamsData = (group: any, val: any) => [
},
];
export const colorNetwork = ['#FF7D00', '#FFC300', '#37E2E2', '#165DFF', '#722ED1']
export const colorCpu = ['#313CA9', '#21CCFF', '#249EFF', '#86DF6C', '#979AFF']
export const colorJvm = ['#246EFF', '#00B2FF', '#81E2FF', '#2CAB40', '#8D4EDA']
export const areaStyle = {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{

View File

@ -6,6 +6,10 @@
@cancel="emit('close')"
@ok="onSave"
>
<div class="alert">
<AIcon type="InfoCircleOutlined" />
通过角色控制{{ name }}的所有的通知方式可被哪些用户订阅
</div>
<Role v-model="_selectedRowKeys" :gridColumn="2" />
</j-modal>
</template>
@ -20,6 +24,10 @@ const props = defineProps({
type: Array as PropType<string[]>,
default: () => [],
},
name: {
type: String,
default: ''
}
});
const _selectedRowKeys = ref<string[]>([]);
@ -31,4 +39,15 @@ watchEffect(() => {
const onSave = () => {
emit('save', _selectedRowKeys.value);
};
</script>
</script>
<style lang="less" scoped>
.alert {
height: 40px;
padding: 0 20px 0 10px;
margin-bottom: 10px;
color: rgba(0, 0, 0, 0.55);
line-height: 40px;
background-color: #f6f6f6;
}
</style>

View File

@ -22,7 +22,7 @@
<template #title>
<span v-if="!update">暂无权限请联系管理员</span>
<div v-else>
用于配制外层权限<br />未配置外层权限将执行通知方式中配置的权限<br />配置外层权限后将覆盖所有通知方式中配置的权限
通过角色控制{{ data.name }}的所有的通知方式可被哪些用户订阅
</div>
</template>
<j-button
@ -129,6 +129,7 @@
@save="onSave"
:loading="loading"
:provider="provider"
:name="data.name"
/>
<Detail
:data="current"
@ -140,6 +141,7 @@
:data="data?.grant?.role?.idList"
@close="authVisible = false"
@save="onAuthSave"
:name="data.name"
/>
</template>
@ -346,49 +348,53 @@ const onSwitchChange = (e: boolean) => {
if (_checked) {
onAction(e);
} else {
Modal.confirm({
title: e
? '开启后默认平台所有用户都能接收到该通知'
: '关闭后平台所有用户都不能接收到该通知',
cancelText: '取消',
okText: e ? '确认开启' : '确认关闭',
content: h(
'div',
{
style: {
display: 'flex',
justifyContent: 'flex-end',
marginTop: '20px',
},
},
[
h(
Checkbox,
{
onChange: (_e: any) => {
LocalStore.set(
user.userInfos?.username,
e
? {
..._value,
open: _e.target?.checked,
}
: {
..._value,
close: _e.target?.checked,
},
);
},
if (e) {
onAction(e);
} else {
Modal.confirm({
title: e
? '开启后默认平台所有用户都能接收到该通知'
: '关闭后平台所有用户都不能接收到该通知',
cancelText: '取消',
okText: e ? '确认开启' : '确认关闭',
content: h(
'div',
{
style: {
display: 'flex',
justifyContent: 'flex-end',
marginTop: '20px',
},
'不再提示',
),
],
),
onOk() {
onAction(e);
},
onCancel() {},
});
},
[
h(
Checkbox,
{
onChange: (_e: any) => {
LocalStore.set(
user.userInfos?.username,
e
? {
..._value,
open: _e.target?.checked,
}
: {
..._value,
close: _e.target?.checked,
},
);
},
},
'不再提示',
),
],
),
onOk() {
onAction(e);
},
onCancel() {},
});
}
}
};
@ -489,7 +495,7 @@ const onSave = (_data: any) => {
.box-item-add {
cursor: pointer;
background-color: #F7F8FA;
background-color: #f7f8fa;
width: 54px;
height: 54px;
display: flex;

View File

@ -70,7 +70,7 @@
</j-alert>
</div>
</template>
<j-scrollbar height="400px">
<j-scrollbar :height="gridColumn <= 2 ? '320px' : '250px'">
<j-pro-table
ref="tableRef"
:columns="columns"

View File

@ -20,7 +20,7 @@
<AIcon type="InfoCircleOutlined" />
钉钉群机器人类型的配置在当前页面将被过滤
</div>
<div style="height: 400px; overflow-y: auto">
<div style="max-height: 400px; overflow-y: auto">
<JProTable
:columns="columns"
:request="query"

View File

@ -19,7 +19,7 @@
<AIcon type="InfoCircleOutlined" />
已规定固定收信人的模板在当前页面将被过滤
</div>
<div style="height: 400px; overflow-y: auto">
<div style="max-height: 400px; overflow-y: auto">
<JProTable
:columns="columns"
:request="(e) => handleData(e)"

View File

@ -69,10 +69,12 @@ onMounted(() => {
iconUrl: iconMap.get(item.id),
};
});
emit('update:value', options.value?.[0]?.value);
emit('update:name', options.value?.[0]?.label);
emit('change', {label: options.value?.[0]?.label, value: options.value?.[0]?.value});
}
loading.value = false;
});
notifyType.value = props.value;
});
</script>

View File

@ -11,11 +11,12 @@
<j-step v-for="(item, index) in stepList" :key="item">
<template #title>
{{ item
}}<j-tooltip
v-if="index === 4"
>
}}<j-tooltip v-if="index === 4">
<template #title>
<span>内层权限配置<br />外层权限已配置的情况下将取外层权限与当前页面分配权限的交集向对应角色发送通知<br />外层权限未配置的情况下将按此处配置的权限发送通知</span>
<span>
通过角色控制{{ name }}下的{{ showName }}通知可被哪些用户订阅<br />
注意当前配置会被外层{{ name }}中的权限控制覆盖
</span>
</template>
<AIcon type="QuestionCircleOutlined"
/></j-tooltip>
@ -32,6 +33,7 @@
<template v-if="current === 0">
<NotifyWay
:value="formModel.channelProvider"
v-model:name="showName"
@change="onWayChange"
/>
</template>
@ -161,6 +163,10 @@ const props = defineProps({
type: String,
default: '',
},
name: {
type: String,
default: '',
},
});
const stepList = [
@ -190,14 +196,15 @@ const formModel = reactive<{
});
const variableRef = ref();
const formRef = ref();
const showName = ref<string>('钉钉')
const _getType = computed(() => {
if(['notifier-dingTalk'].includes(props.data?.channelProvider)) {
return ['user', 'tag']
if (['notifier-dingTalk'].includes(props.data?.channelProvider)) {
return ['user', 'tag'];
} else {
return ['user', 'org', 'tag']
return ['user', 'org', 'tag'];
}
})
});
const _variableDefinitions = computed(() => {
return variable.value.filter((item: any) => {

View File

@ -3755,8 +3755,8 @@ jetlinks-ui-components@^1.0.23:
jetlinks-ui-components@^1.0.27:
version "1.0.27"
resolved "http://registry.jetlinks.cn/jetlinks-ui-components/-/jetlinks-ui-components-1.0.27.tgz#97f04cb18906ad603de2bcbc62fa4b6673a7a3d0"
integrity sha512-R9dPrRMwV5imqV0JTkHeTMT8LeCnv7+Vb1IqKNIqc9I7joFZ9hLtEAE0EXO5GxTthPUiMZlQ+BDsd9ehCArO3Q==
resolved "http://registry.jetlinks.cn/jetlinks-ui-components/-/jetlinks-ui-components-1.0.27.tgz#03a2a9ba49d669c6d63e6c5d5b144f31a27253df"
integrity sha512-I9A05UXUtjRsSWU/jgRDfDNeCv2ZV21/PV4FEV3UG5bQOYa1/CvL7Lr7F7iB1m4Hjn9mnXTqAQ2pU11b6T2U8Q==
dependencies:
"@vueuse/core" "^9.12.0"
"@vueuse/router" "^9.13.0"