Merge branch 'dev-dictionary' of github.com:jetlinks/jetlinks-ui-vue into dev-dictionary
This commit is contained in:
commit
03db286aab
|
@ -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 updateMepsd_api = (data:object) => server.put(`/user/passwd`,data);
|
||||||
// 第三方账号解绑
|
// 第三方账号解绑
|
||||||
export const unBind_api = (appId: string) => server.post(`/application/sso/${appId}/unbind/me`);
|
export const unBind_api = (appId: string) => server.post(`/application/sso/${appId}/unbind/me`,[]);
|
||||||
/**
|
/**
|
||||||
* 校验字段合法性
|
* 校验字段合法性
|
||||||
* @param type 类型
|
* @param type 类型
|
||||||
|
|
|
@ -36,4 +36,6 @@ export const systemVersion = () => server.get<{edition?: string}>('/system/versi
|
||||||
*/
|
*/
|
||||||
export const queryDashboard = (data: Record<string, any>) => server.post(`/dashboard/_multi`, data)
|
export const queryDashboard = (data: Record<string, any>) => server.post(`/dashboard/_multi`, data)
|
||||||
|
|
||||||
export const fileUpload = (data: any) => server.post('/file/static', data)
|
export const fileUpload = (data: any) => server.post('/file/static', data)
|
||||||
|
|
||||||
|
export const lowCodeUrl = () => server.get('/system/config/low-code')
|
|
@ -270,6 +270,11 @@ export const queryDeviceMapping = (deviceId: string, data?: any) => server.post(
|
||||||
*/
|
*/
|
||||||
export const saveDeviceMapping = (deviceId: string, data: any) => server.post(`/edge/operations/${deviceId}/device-mapping-save-batch/invoke`, data)
|
export const saveDeviceMapping = (deviceId: string, data: any) => server.post(`/edge/operations/${deviceId}/device-mapping-save-batch/invoke`, data)
|
||||||
|
|
||||||
|
/**
|
||||||
|
*批量删除云端映射设备
|
||||||
|
*/
|
||||||
|
export const deleteDeviceMapping = (deviceId: string, data:any) => server.post(`/edge/operations/${deviceId}/device-mapping-delete/invoke`, data)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取产品列表
|
* 获取产品列表
|
||||||
* @param data
|
* @param data
|
||||||
|
@ -279,7 +284,7 @@ export const getProductListNoPage = (data: any) => server.post('/device/product/
|
||||||
/**
|
/**
|
||||||
* 修改设备
|
* 修改设备
|
||||||
*/
|
*/
|
||||||
export const editDevice = (parmas: any) => server.patch('/device-instance', parmas)
|
export const editDevice = (params: any) => server.patch('/device-instance', params)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 新增设备
|
* 新增设备
|
||||||
|
|
|
@ -0,0 +1,129 @@
|
||||||
|
<template>
|
||||||
|
<j-pro-layout
|
||||||
|
v-model:collapsed="basicLayout.collapsed"
|
||||||
|
v-model:openKeys="basicLayout.openKeys"
|
||||||
|
:breadcrumb="{ routes: breadcrumbs }"
|
||||||
|
:headerHeight='layout.headerHeight'
|
||||||
|
:pure="basicLayout.pure"
|
||||||
|
:selectedKeys="basicLayout.selectedKeys"
|
||||||
|
v-bind="layoutConf"
|
||||||
|
@backClick='routerBack'
|
||||||
|
>
|
||||||
|
<template #breadcrumbRender="slotProps">
|
||||||
|
<a
|
||||||
|
v-if="slotProps.route.index !== 0 && !slotProps.route.isLast"
|
||||||
|
@click='jump(slotProps.route)'
|
||||||
|
>
|
||||||
|
{{ slotProps.route.breadcrumbName }}
|
||||||
|
</a>
|
||||||
|
<span v-else style='cursor: default' >{{ slotProps.route.breadcrumbName }}</span>
|
||||||
|
</template>
|
||||||
|
<template #rightContentRender>
|
||||||
|
<div class="right-content">
|
||||||
|
<AIcon type="QuestionCircleOutlined" @click="toDoc" />
|
||||||
|
<Notice style="margin: 0 24px" />
|
||||||
|
<UserInfo />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<Iframe />
|
||||||
|
</j-pro-layout>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" name="SinglePage" setup>
|
||||||
|
import UserInfo from './components/UserInfo.vue';
|
||||||
|
import Notice from './components/Notice.vue';
|
||||||
|
import DefaultSetting from '../../../config/config';
|
||||||
|
import { useMenuStore } from '@/store/menu';
|
||||||
|
import { clearMenuItem } from 'jetlinks-ui-components/es/ProLayout/util';
|
||||||
|
import { AccountMenu } from '@/router/menu'
|
||||||
|
import { useSystem } from '@/store/system';
|
||||||
|
import { storeToRefs } from 'pinia';
|
||||||
|
import Iframe from '@/views/iframe/index.vue'
|
||||||
|
|
||||||
|
type StateType = {
|
||||||
|
collapsed: boolean;
|
||||||
|
openKeys: string[];
|
||||||
|
selectedKeys: string[];
|
||||||
|
pure: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
const router = useRouter();
|
||||||
|
const route = useRoute();
|
||||||
|
|
||||||
|
const menu = useMenuStore();
|
||||||
|
|
||||||
|
const system = useSystem();
|
||||||
|
const {configInfo,layout, basicLayout} = storeToRefs(system);
|
||||||
|
|
||||||
|
const layoutConf = reactive({
|
||||||
|
theme: DefaultSetting.layout.theme,
|
||||||
|
siderWidth: layout.value.siderWidth,
|
||||||
|
logo: DefaultSetting.layout.logo,
|
||||||
|
title: DefaultSetting.layout.title,
|
||||||
|
menuData: menu.siderMenus,
|
||||||
|
// menuData: menu.siderMenus,
|
||||||
|
splitMenus: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
watchEffect(() => {
|
||||||
|
layoutConf.theme = configInfo.value.front?.headerTheme || DefaultSetting.layout.theme;
|
||||||
|
layoutConf.title = configInfo.value.front?.title || DefaultSetting.layout.title;
|
||||||
|
layoutConf.logo = configInfo.value.front?.logo || DefaultSetting.layout.logo;
|
||||||
|
})
|
||||||
|
|
||||||
|
const components = computed(() => {
|
||||||
|
const componentName = route.matched[route.matched.length - 1]?.components?.default?.name
|
||||||
|
if (componentName !== 'BasicLayoutPage') {
|
||||||
|
return route.matched[route.matched.length - 1]?.components?.default
|
||||||
|
}
|
||||||
|
return undefined
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 面包屑
|
||||||
|
*/
|
||||||
|
const breadcrumbs = computed(() =>
|
||||||
|
{
|
||||||
|
const paths = router.currentRoute.value.matched
|
||||||
|
|
||||||
|
return paths.map((item, index) => {
|
||||||
|
return {
|
||||||
|
index,
|
||||||
|
isLast: index === (paths.length -1),
|
||||||
|
path: item.path,
|
||||||
|
breadcrumbName: (item.meta as any).title || '',
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const routerBack = () => {
|
||||||
|
router.go(-1)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const jump = (item: any) => {
|
||||||
|
router.push(item.path)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
watchEffect(() => {
|
||||||
|
if (router.currentRoute) {
|
||||||
|
const paths = router.currentRoute.value.matched
|
||||||
|
basicLayout.value.selectedKeys = paths.map(item => item.path)
|
||||||
|
basicLayout.value.openKeys = paths.map(item => item.path)
|
||||||
|
console.log(paths) //
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const toDoc = () => window.open('http://doc.v2.jetlinks.cn/');
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.right-content {
|
||||||
|
margin-right: 24px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -1,3 +1,4 @@
|
||||||
export { default as BasicLayoutPage } from './BasicLayoutPage.vue'
|
export { default as BasicLayoutPage } from './BasicLayoutPage.vue'
|
||||||
export { default as BlankLayoutPage } from './BlankLayoutPage.vue'
|
export { default as BlankLayoutPage } from './BlankLayoutPage.vue'
|
||||||
export { default as FullPage } from './FullPage.vue'
|
export { default as FullPage } from './FullPage.vue'
|
||||||
|
export { default as SinglePage } from './SinglePage.vue'
|
|
@ -1,6 +1,7 @@
|
||||||
import { BlankLayoutPage, BasicLayoutPage } from 'components/Layout'
|
import { BlankLayoutPage, BasicLayoutPage, SinglePage } from 'components/Layout'
|
||||||
import { isNoCommunity } from '@/utils/utils'
|
import { isNoCommunity } from '@/utils/utils'
|
||||||
import Iframe from '../views/iframe/index.vue'
|
import Iframe from '../views/iframe/index.vue'
|
||||||
|
import { h } from 'vue'
|
||||||
|
|
||||||
const pagesComponent = import.meta.glob('../views/**/*.vue');
|
const pagesComponent = import.meta.glob('../views/**/*.vue');
|
||||||
|
|
||||||
|
@ -343,10 +344,12 @@ import { shallowRef } from 'vue'
|
||||||
|
|
||||||
type Buttons = Array<{ id: string }>
|
type Buttons = Array<{ id: string }>
|
||||||
|
|
||||||
const hasAppID = (item: { appId?: string, url?: string }): { isApp: boolean, appUrl: string } => {
|
const hasAppID = (item: any): { isApp: boolean, appUrl: string } => {
|
||||||
|
const isApp = !!item.appId
|
||||||
|
const isLowCode = !!item.options?.LowCode
|
||||||
return {
|
return {
|
||||||
isApp: !!item.appId,
|
isApp: isApp || isLowCode,
|
||||||
appUrl: `/${item.appId}${item.url}`
|
appUrl: isApp ? `/${item.appId}${item.url}` : item.url
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -453,6 +456,10 @@ export const handleMenus = (menuData: any[], components: any, level: number = 1)
|
||||||
route.children = route.children ? [...route.children, ...extraRoute] : extraRoute
|
route.children = route.children ? [...route.children, ...extraRoute] : extraRoute
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (item.options?.LowCode && level === 1) {
|
||||||
|
route.component = () => SinglePage
|
||||||
|
}
|
||||||
|
|
||||||
if (detail_components.length) {
|
if (detail_components.length) {
|
||||||
route.children = route.children ? route.children.concat(detail_components) : detail_components
|
route.children = route.children ? route.children.concat(detail_components) : detail_components
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
visible
|
visible
|
||||||
@ok="handleClick"
|
@ok="handleClick"
|
||||||
@cancel="handleClose"
|
@cancel="handleClose"
|
||||||
|
:confirmLoading="confirmLoading"
|
||||||
>
|
>
|
||||||
<div class="map-tree">
|
<div class="map-tree">
|
||||||
<div class="map-tree-top">
|
<div class="map-tree-top">
|
||||||
|
@ -99,6 +100,7 @@ const rightList = ref<any[]>([]);
|
||||||
const dataSource = ref<any[]>([]);
|
const dataSource = ref<any[]>([]);
|
||||||
const loading = ref<boolean>(false);
|
const loading = ref<boolean>(false);
|
||||||
|
|
||||||
|
const confirmLoading = ref(false)
|
||||||
const handleData = (data: any[], type: string) => {
|
const handleData = (data: any[], type: string) => {
|
||||||
data.forEach((item) => {
|
data.forEach((item) => {
|
||||||
item.key = item.id;
|
item.key = item.id;
|
||||||
|
@ -212,6 +214,7 @@ const _delete = (_key: string) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleClick = async () => {
|
const handleClick = async () => {
|
||||||
|
confirmLoading.value = true
|
||||||
if (!rightList.value.length) {
|
if (!rightList.value.length) {
|
||||||
onlyMessage('请选择采集器', 'warning');
|
onlyMessage('请选择采集器', 'warning');
|
||||||
} else {
|
} else {
|
||||||
|
@ -271,6 +274,7 @@ const handleClick = async () => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
confirmLoading.value = false
|
||||||
};
|
};
|
||||||
const handleClose = () => {
|
const handleClose = () => {
|
||||||
_emits('close');
|
_emits('close');
|
||||||
|
|
|
@ -280,7 +280,9 @@ const onSave = async () => {
|
||||||
{ deviceId: resq.result?.id, deviceName: formData.name }
|
{ deviceId: resq.result?.id, deviceName: formData.name }
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
const res = await saveDeviceMapping(instanceStore.current.id, params)
|
if(!instanceStore.current.parentId){
|
||||||
|
const res = await saveDeviceMapping(instanceStore.current.id, params)
|
||||||
|
}
|
||||||
const submitData = {
|
const submitData = {
|
||||||
deviceId: instanceStore.current.parentId
|
deviceId: instanceStore.current.parentId
|
||||||
? instanceStore.current.parentId
|
? instanceStore.current.parentId
|
||||||
|
|
|
@ -113,7 +113,7 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import type { ActionsType } from '@/components/Table';
|
import type { ActionsType } from '@/components/Table';
|
||||||
import {query, unbindDevice, unbindBatchDevice, queryByParent} from '@/api/device/instance';
|
import {query, unbindDevice, unbindBatchDevice, queryByParent , deleteDeviceMapping} from '@/api/device/instance';
|
||||||
import { useInstanceStore } from '@/store/instance';
|
import { useInstanceStore } from '@/store/instance';
|
||||||
import { storeToRefs } from 'pinia';
|
import { storeToRefs } from 'pinia';
|
||||||
import BindChildDevice from './BindChildDevice/index.vue';
|
import BindChildDevice from './BindChildDevice/index.vue';
|
||||||
|
@ -241,6 +241,10 @@ const getActions = (data: Partial<Record<string, any>>): ActionsType[] => {
|
||||||
data.id,
|
data.id,
|
||||||
{},
|
{},
|
||||||
);
|
);
|
||||||
|
const res = await deleteDeviceMapping(
|
||||||
|
detail.value.id,
|
||||||
|
{ids:[data.id]}
|
||||||
|
)
|
||||||
if (resp.status === 200) {
|
if (resp.status === 200) {
|
||||||
childDeviceRef.value?.reload();
|
childDeviceRef.value?.reload();
|
||||||
onlyMessage('操作成功!');
|
onlyMessage('操作成功!');
|
||||||
|
@ -282,6 +286,10 @@ const handleUnBind = async () => {
|
||||||
_selectedRowKeys.value,
|
_selectedRowKeys.value,
|
||||||
);
|
);
|
||||||
if (resp.status === 200) {
|
if (resp.status === 200) {
|
||||||
|
const res = await deleteDeviceMapping(
|
||||||
|
detail.value.id,
|
||||||
|
{ids:[_selectedRowKeys.value]}
|
||||||
|
)
|
||||||
onlyMessage('操作成功!');
|
onlyMessage('操作成功!');
|
||||||
cancelSelect();
|
cancelSelect();
|
||||||
childDeviceRef.value?.reload();
|
childDeviceRef.value?.reload();
|
||||||
|
|
|
@ -210,7 +210,6 @@ import PatchMapping from './PatchMapping.vue';
|
||||||
import { onlyMessage } from '@/utils/comm';
|
import { onlyMessage } from '@/utils/comm';
|
||||||
import { cloneDeep } from 'lodash-es';
|
import { cloneDeep } from 'lodash-es';
|
||||||
import { usePermissionStore } from '@/store/permission';
|
import { usePermissionStore } from '@/store/permission';
|
||||||
|
|
||||||
const columns = [
|
const columns = [
|
||||||
{
|
{
|
||||||
title: '名称',
|
title: '名称',
|
||||||
|
@ -313,6 +312,14 @@ const handleSearch = async (_array: any[]) => {
|
||||||
Object.assign(item, metadataId);
|
Object.assign(item, metadataId);
|
||||||
return item
|
return item
|
||||||
})
|
})
|
||||||
|
resp.result?.[0].forEach((item:any)=>{
|
||||||
|
const differ = array.every((i:any)=>{
|
||||||
|
return item.metadataId !== i.metadataId
|
||||||
|
})
|
||||||
|
if(!differ){
|
||||||
|
array.push(item)
|
||||||
|
}
|
||||||
|
})
|
||||||
// const array = resp.result?.[0].reduce((x: any, y: any) => {
|
// const array = resp.result?.[0].reduce((x: any, y: any) => {
|
||||||
// const metadataId = _metadata.find(
|
// const metadataId = _metadata.find(
|
||||||
// (item: any) => item.metadataId === y.metadataId,
|
// (item: any) => item.metadataId === y.metadataId,
|
||||||
|
@ -324,6 +331,7 @@ const handleSearch = async (_array: any[]) => {
|
||||||
// }
|
// }
|
||||||
// return x;
|
// return x;
|
||||||
// }, _metadata);
|
// }, _metadata);
|
||||||
|
console.log(array)
|
||||||
modelRef.dataSource = array;
|
modelRef.dataSource = array;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,7 +37,7 @@
|
||||||
<AIcon type="EditOutlined" />
|
<AIcon type="EditOutlined" />
|
||||||
</j-button>
|
</j-button>
|
||||||
</j-popconfirm-modal>
|
</j-popconfirm-modal>
|
||||||
<j-dropdown v-if="myValue === 'rule' && target === 'device' && showReset" :getPopupContainer="(triggerNode) => triggerNode.parentNode">
|
<j-dropdown v-if="myValue === 'rule' && target === 'device' && showReset" :getPopupContainer="(node) => fullRef || node" placement="bottom">
|
||||||
<span style="width: 20px;" @click.prevent>
|
<span style="width: 20px;" @click.prevent>
|
||||||
<AIcon type="MoreOutlined" />
|
<AIcon type="MoreOutlined" />
|
||||||
</span>
|
</span>
|
||||||
|
@ -100,7 +100,13 @@ import { resetRule } from '@/api/device/instance';
|
||||||
import { updata } from '@/api/rule-engine/configuration';
|
import { updata } from '@/api/rule-engine/configuration';
|
||||||
import { onlyMessage } from '@/utils/comm';
|
import { onlyMessage } from '@/utils/comm';
|
||||||
import { provide } from 'vue';
|
import { provide } from 'vue';
|
||||||
|
import { queryDeviceVirtualProperty } from '@/api/device/instance';
|
||||||
|
import {
|
||||||
|
queryProductVirtualProperty
|
||||||
|
} from '@/api/device/product';
|
||||||
|
import { useProductStore } from '@/store/product';
|
||||||
const instanceStore = useInstanceStore();
|
const instanceStore = useInstanceStore();
|
||||||
|
const productStore = useProductStore();
|
||||||
const PropertySource: { label: string; value: string }[] = isNoCommunity
|
const PropertySource: { label: string; value: string }[] = isNoCommunity
|
||||||
? [
|
? [
|
||||||
{
|
{
|
||||||
|
@ -133,6 +139,7 @@ type Emit = {
|
||||||
(e: 'update:value', data: Record<string, any>): void;
|
(e: 'update:value', data: Record<string, any>): void;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
const fullRef = inject(FULL_CODE);
|
const fullRef = inject(FULL_CODE);
|
||||||
const showReset = ref(false);
|
const showReset = ref(false);
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
|
@ -243,6 +250,32 @@ const cancel = () => {
|
||||||
type.value = props.value?.expands?.type || [];
|
type.value = props.value?.expands?.type || [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handleSearch = async () => {
|
||||||
|
let resp: any = undefined;
|
||||||
|
if (props.target === 'product') {
|
||||||
|
resp = await queryProductVirtualProperty(
|
||||||
|
productStore.current?.id,
|
||||||
|
props.value?.id,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
resp = await queryDeviceVirtualProperty(
|
||||||
|
instanceStore.current?.productId,
|
||||||
|
instanceStore.current?.id,
|
||||||
|
props.value?.id,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (resp && resp.status === 200 && resp.result) {
|
||||||
|
const _triggerProperties = props.value?.expands?.virtualRule?.triggerProperties?.length ? props.value?.expands?.virtualRule?.triggerProperties : resp.result.triggerProperties
|
||||||
|
updateValue({
|
||||||
|
source: myValue.value,
|
||||||
|
virtualRule:{
|
||||||
|
triggerProperties: _triggerProperties?.length ? _triggerProperties : ['*'],
|
||||||
|
...resp.result.rule
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => props.value,
|
() => props.value,
|
||||||
() => {
|
() => {
|
||||||
|
@ -261,6 +294,7 @@ onMounted(()=>{
|
||||||
item === props.value?.id ? showReset.value = true : ''
|
item === props.value?.id ? showReset.value = true : ''
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
handleSearch()
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -43,6 +43,7 @@
|
||||||
:actions="getActions(slotProps, 'card')"
|
:actions="getActions(slotProps, 'card')"
|
||||||
:status="slotProps.state?.value"
|
:status="slotProps.state?.value"
|
||||||
:statusText="slotProps.state?.text"
|
:statusText="slotProps.state?.text"
|
||||||
|
@click="handleView(slotProps.id)"
|
||||||
:statusNames="{
|
:statusNames="{
|
||||||
online: 'processing',
|
online: 'processing',
|
||||||
offline: 'error',
|
offline: 'error',
|
||||||
|
@ -63,7 +64,6 @@
|
||||||
<Ellipsis style="width: calc(100% - 100px)">
|
<Ellipsis style="width: calc(100% - 100px)">
|
||||||
<span
|
<span
|
||||||
style="font-size: 16px; font-weight: 600"
|
style="font-size: 16px; font-weight: 600"
|
||||||
@click.stop="handleView(slotProps.id)"
|
|
||||||
>
|
>
|
||||||
{{ slotProps.name }}
|
{{ slotProps.name }}
|
||||||
</span>
|
</span>
|
||||||
|
@ -101,7 +101,7 @@
|
||||||
:key="i"
|
:key="i"
|
||||||
>
|
>
|
||||||
<PermissionButton
|
<PermissionButton
|
||||||
:disabled="o.disabled"
|
:disabled="o.disabled || item.state !== 'online'"
|
||||||
:popConfirm="o.popConfirm"
|
:popConfirm="o.popConfirm"
|
||||||
:tooltip="{
|
:tooltip="{
|
||||||
...o.tooltip,
|
...o.tooltip,
|
||||||
|
@ -470,7 +470,7 @@ const getActions = (
|
||||||
},
|
},
|
||||||
icon: 'RedoOutlined',
|
icon: 'RedoOutlined',
|
||||||
popConfirm: {
|
popConfirm: {
|
||||||
title: '确认重置密码为P@ssw0rd?',
|
title: '确认重置密码为Jetlinks123?',
|
||||||
onConfirm: async () => {
|
onConfirm: async () => {
|
||||||
restPassword(data.id).then((resp: any) => {
|
restPassword(data.id).then((resp: any) => {
|
||||||
if (resp.status === 200) {
|
if (resp.status === 200) {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
<template>
|
<template>
|
||||||
<page-container>
|
<page-container>
|
||||||
<iframe
|
<iframe
|
||||||
|
v-if="loading"
|
||||||
:src="iframeUrl"
|
:src="iframeUrl"
|
||||||
frameBorder="0"
|
frameBorder="0"
|
||||||
style="width: 100%; height: calc(100vh - 140px)"
|
style="width: 100%; height: calc(100vh - 140px)"
|
||||||
|
@ -10,12 +11,13 @@
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { TOKEN_KEY } from '@/utils/variable';
|
import { TOKEN_KEY } from '@/utils/variable';
|
||||||
import { LocalStore } from '@/utils/comm';
|
import { LocalStore, getToken } from '@/utils/comm';
|
||||||
import { getAppInfo_api } from '@/api/system/apply';
|
import { getAppInfo_api } from '@/api/system/apply';
|
||||||
|
import { lowCodeUrl } from '@/api/comm'
|
||||||
|
|
||||||
const iframeUrl = ref<string>('');
|
const iframeUrl = ref<string>('');
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
|
const loading = ref(false)
|
||||||
const handle = async (appId: string, url: string) => {
|
const handle = async (appId: string, url: string) => {
|
||||||
const res = await getAppInfo_api(appId);
|
const res = await getAppInfo_api(appId);
|
||||||
let menuUrl: any = url;
|
let menuUrl: any = url;
|
||||||
|
@ -38,13 +40,26 @@ const handle = async (appId: string, url: string) => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const lowCode = () => {
|
||||||
|
lowCodeUrl().then(res => {
|
||||||
|
if (res.success && res.result) {
|
||||||
|
const url = res.result['ui-addr']
|
||||||
|
iframeUrl.value = url + '/#' + route.path + '?&token=' + getToken()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
watchEffect(() => {
|
watchEffect(() => {
|
||||||
const matchedItem: any = route.matched?.[0]
|
const matchedItem: any = route.matched?.[0]
|
||||||
if (matchedItem?.meta?.isApp) {
|
if (matchedItem?.meta?.isApp) {
|
||||||
const params = route.path.split('/')?.[1];
|
const params = route.path.split('/')?.[1];
|
||||||
const url = route.path.split('/').slice(2).join('/');
|
if (params === 'preview') {
|
||||||
handle(params, url);
|
lowCode()
|
||||||
|
} else {
|
||||||
|
loading.value = true
|
||||||
|
const url = route.path.split('/').slice(2).join('/');
|
||||||
|
handle(params, url);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -283,6 +283,11 @@
|
||||||
cluster
|
cluster
|
||||||
.configuration
|
.configuration
|
||||||
.port
|
.port
|
||||||
|
"
|
||||||
|
:options="
|
||||||
|
portOptionsIndex[
|
||||||
|
index
|
||||||
|
]
|
||||||
"
|
"
|
||||||
placeholder="请选择本地端口"
|
placeholder="请选择本地端口"
|
||||||
allowClear
|
allowClear
|
||||||
|
@ -291,7 +296,7 @@
|
||||||
filterPortOption
|
filterPortOption
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<j-select-option
|
<!-- <j-select-option
|
||||||
v-for="i in getPortList( portOptionsIndex[
|
v-for="i in getPortList( portOptionsIndex[
|
||||||
index
|
index
|
||||||
], cluster
|
], cluster
|
||||||
|
@ -300,7 +305,7 @@
|
||||||
:value="i.value"
|
:value="i.value"
|
||||||
>
|
>
|
||||||
{{ i.label }}
|
{{ i.label }}
|
||||||
</j-select-option>
|
</j-select-option> -->
|
||||||
</j-select>
|
</j-select>
|
||||||
</j-form-item>
|
</j-form-item>
|
||||||
</j-col>
|
</j-col>
|
||||||
|
@ -1231,11 +1236,11 @@ const filterPortOption = (input: string, option: any) => {
|
||||||
return JSON.stringify(option.label).indexOf(input) >= 0;
|
return JSON.stringify(option.label).indexOf(input) >= 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
const getPortList = (list: any[], id: string) => {
|
// const getPortList = (list: any[], id: string) => {
|
||||||
const keys = dynamicValidateForm?.cluster?.map?.(item => item.configuration?.port) || []
|
// const keys = dynamicValidateForm?.cluster?.map?.(item => item.configuration?.port) || []
|
||||||
// console.log(dynamicValidateForm?.cluster, id, keys)
|
// // console.log(dynamicValidateForm?.cluster, id, keys)
|
||||||
return (list || []).filter(item => item.value === id || !keys.includes(item.value) )
|
// return (list || []).filter(item => item.value === id || !keys.includes(item.value) )
|
||||||
}
|
// }
|
||||||
|
|
||||||
const filterConfigByType = (data: any[], type: string) => {
|
const filterConfigByType = (data: any[], type: string) => {
|
||||||
let _temp = type;
|
let _temp = type;
|
||||||
|
|
|
@ -130,7 +130,7 @@
|
||||||
</template>
|
</template>
|
||||||
</MediaTool>
|
</MediaTool>
|
||||||
</div>
|
</div>
|
||||||
<Preset :data="data" @refresh="onRefresh" />
|
<Preset v-if='data.ptzType.value ===0 || data.ptzType.value === 1' :data="data" @refresh="onRefresh" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
|
|
|
@ -1,176 +1,180 @@
|
||||||
<template>
|
<template>
|
||||||
<page-container>
|
<page-container>
|
||||||
<div class="manager-container">
|
<FullPage>
|
||||||
<div class="left">
|
<div class="manager-container">
|
||||||
<j-input-search
|
<div class="left">
|
||||||
v-model:value="leftData.searchValue"
|
<j-input-search
|
||||||
placeholder="请输入"
|
v-model:value="leftData.searchValue"
|
||||||
style="margin-bottom: 24px"
|
placeholder="请输入"
|
||||||
/>
|
style="margin-bottom: 24px"
|
||||||
<!-- 使用v-if用于解决异步加载数据后不展开的问题 -->
|
/>
|
||||||
<j-tree
|
<!-- 使用v-if用于解决异步加载数据后不展开的问题 -->
|
||||||
v-if="leftData.treeData.length > 0"
|
<j-tree
|
||||||
defaultExpandAll
|
v-if="leftData.treeData.length > 0"
|
||||||
:tree-data="leftData.treeData"
|
defaultExpandAll
|
||||||
v-model:selectedKeys="leftData.selectedKeys"
|
:tree-data="leftData.treeData"
|
||||||
@select="onSelect"
|
v-model:selectedKeys="leftData.selectedKeys"
|
||||||
:showLine="{ showLeafIcon: false }"
|
@select="onSelect"
|
||||||
:show-icon="true"
|
:showLine="{ showLeafIcon: false }"
|
||||||
>
|
:show-icon="true"
|
||||||
<template #title="{ dataRef }">
|
|
||||||
<div
|
|
||||||
v-if="dataRef.root"
|
|
||||||
style="
|
|
||||||
justify-content: space-between;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
width: 200px;
|
|
||||||
"
|
|
||||||
>
|
|
||||||
<span>
|
|
||||||
{{ dataRef.title }}
|
|
||||||
</span>
|
|
||||||
<AIcon
|
|
||||||
type="PlusOutlined"
|
|
||||||
style="color: #1d39c4"
|
|
||||||
@click="addTable"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<span v-else>
|
|
||||||
{{ dataRef.title }}
|
|
||||||
</span>
|
|
||||||
</template>
|
|
||||||
</j-tree>
|
|
||||||
</div>
|
|
||||||
<div class="right">
|
|
||||||
<div class="btns">
|
|
||||||
<j-button type="primary" @click="clickSave">保存</j-button>
|
|
||||||
</div>
|
|
||||||
<j-form ref="formRef" :model="table">
|
|
||||||
<j-table
|
|
||||||
:columns="columns"
|
|
||||||
:dataSource="table.data"
|
|
||||||
:pagination="false"
|
|
||||||
:scroll="{ y: 500 }"
|
|
||||||
>
|
>
|
||||||
<template #bodyCell="{ column, record, index }">
|
<template #title="{ dataRef }">
|
||||||
<template v-if="column.key === 'name'">
|
<Ellipsis>
|
||||||
<j-form-item
|
<div
|
||||||
:name="['data', index, 'name']"
|
v-if="dataRef.root"
|
||||||
:rules="[
|
style="
|
||||||
{
|
justify-content: space-between;
|
||||||
max: 64,
|
display: flex;
|
||||||
message: '最多可输入64个字符',
|
align-items: center;
|
||||||
},
|
width: 200px;
|
||||||
{
|
"
|
||||||
required: true,
|
|
||||||
message: '请输入名称',
|
|
||||||
},
|
|
||||||
]"
|
|
||||||
>
|
>
|
||||||
<j-input
|
<span>
|
||||||
:disabled="record.old_id"
|
{{ dataRef.title }}
|
||||||
v-model:value="record.name"
|
</span>
|
||||||
placeholder="请输入名称"
|
<AIcon
|
||||||
|
type="PlusOutlined"
|
||||||
|
style="color: #1d39c4"
|
||||||
|
@click="addTable"
|
||||||
/>
|
/>
|
||||||
</j-form-item>
|
</div>
|
||||||
</template>
|
<span v-else>
|
||||||
<template v-else-if="column.key === 'type'">
|
{{ dataRef.title }}
|
||||||
<j-form-item
|
</span>
|
||||||
:name="['data', index, 'type']"
|
</Ellipsis>
|
||||||
:rules="[
|
|
||||||
{
|
|
||||||
max: 64,
|
|
||||||
message: '最多可输入64个字符',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
message: '请输入类型',
|
|
||||||
},
|
|
||||||
]"
|
|
||||||
>
|
|
||||||
<j-input
|
|
||||||
v-model:value="record.type"
|
|
||||||
placeholder="请输入类型"
|
|
||||||
/>
|
|
||||||
</j-form-item>
|
|
||||||
</template>
|
|
||||||
<template v-else-if="column.key === 'length'">
|
|
||||||
<j-form-item :name="['data', index, 'length']">
|
|
||||||
<j-input-number
|
|
||||||
v-model:value="record.length"
|
|
||||||
:min="0"
|
|
||||||
:max="99999"
|
|
||||||
style="width: 100%"
|
|
||||||
/>
|
|
||||||
</j-form-item>
|
|
||||||
</template>
|
|
||||||
<template v-else-if="column.key === 'scale'">
|
|
||||||
<j-form-item :name="['data', index, 'scale']">
|
|
||||||
<j-input-number
|
|
||||||
v-model:value="record.scale"
|
|
||||||
:min="0"
|
|
||||||
:max="99999"
|
|
||||||
style="width: 100%"
|
|
||||||
/>
|
|
||||||
</j-form-item>
|
|
||||||
</template>
|
|
||||||
<template v-else-if="column.key === 'notnull'">
|
|
||||||
<j-form-item
|
|
||||||
:name="['data', index, 'notnull']"
|
|
||||||
:rules="[
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
message: '请选择是否不能为空',
|
|
||||||
},
|
|
||||||
]"
|
|
||||||
>
|
|
||||||
<j-radio-group
|
|
||||||
v-model:value="record.notnull"
|
|
||||||
button-style="solid"
|
|
||||||
>
|
|
||||||
<j-radio-button :value="true"
|
|
||||||
>是</j-radio-button
|
|
||||||
>
|
|
||||||
<j-radio-button :value="false"
|
|
||||||
>否</j-radio-button
|
|
||||||
>
|
|
||||||
</j-radio-group>
|
|
||||||
</j-form-item>
|
|
||||||
</template>
|
|
||||||
<template v-else-if="column.key === 'comment'">
|
|
||||||
<j-form-item :name="['data', index, 'comment']">
|
|
||||||
<j-input
|
|
||||||
v-model:value="record.comment"
|
|
||||||
placeholder="请输入说明"
|
|
||||||
/>
|
|
||||||
</j-form-item>
|
|
||||||
</template>
|
|
||||||
<template v-else-if="column.key === 'action'">
|
|
||||||
<PermissionButton
|
|
||||||
hasPermission="system/DataSource:delete"
|
|
||||||
type="link"
|
|
||||||
:tooltip="{ title: '删除' }"
|
|
||||||
:danger="true"
|
|
||||||
:popConfirm="{
|
|
||||||
title: `确认删除`,
|
|
||||||
onConfirm: () =>
|
|
||||||
clickDel(record, index),
|
|
||||||
}"
|
|
||||||
:disabled="record.status"
|
|
||||||
>
|
|
||||||
<AIcon type="DeleteOutlined" />
|
|
||||||
</PermissionButton>
|
|
||||||
</template>
|
|
||||||
</template>
|
</template>
|
||||||
</j-table>
|
</j-tree>
|
||||||
</j-form>
|
</div>
|
||||||
|
<div class="right">
|
||||||
|
<div class="btns">
|
||||||
|
<j-button type="primary" @click="clickSave">保存</j-button>
|
||||||
|
</div>
|
||||||
|
<j-form ref="formRef" :model="table">
|
||||||
|
<j-table
|
||||||
|
:columns="columns"
|
||||||
|
:dataSource="table.data"
|
||||||
|
:pagination="false"
|
||||||
|
:scroll="{ y: 500 }"
|
||||||
|
>
|
||||||
|
<template #bodyCell="{ column, record, index }">
|
||||||
|
<template v-if="column.key === 'name'">
|
||||||
|
<j-form-item
|
||||||
|
:name="['data', index, 'name']"
|
||||||
|
:rules="[
|
||||||
|
{
|
||||||
|
max: 64,
|
||||||
|
message: '最多可输入64个字符',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: '请输入名称',
|
||||||
|
},
|
||||||
|
]"
|
||||||
|
>
|
||||||
|
<j-input
|
||||||
|
:disabled="record.old_id"
|
||||||
|
v-model:value="record.name"
|
||||||
|
placeholder="请输入名称"
|
||||||
|
/>
|
||||||
|
</j-form-item>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="column.key === 'type'">
|
||||||
|
<j-form-item
|
||||||
|
:name="['data', index, 'type']"
|
||||||
|
:rules="[
|
||||||
|
{
|
||||||
|
max: 64,
|
||||||
|
message: '最多可输入64个字符',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: '请输入类型',
|
||||||
|
},
|
||||||
|
]"
|
||||||
|
>
|
||||||
|
<j-input
|
||||||
|
v-model:value="record.type"
|
||||||
|
placeholder="请输入类型"
|
||||||
|
/>
|
||||||
|
</j-form-item>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="column.key === 'length'">
|
||||||
|
<j-form-item :name="['data', index, 'length']">
|
||||||
|
<j-input-number
|
||||||
|
v-model:value="record.length"
|
||||||
|
:min="0"
|
||||||
|
:max="99999"
|
||||||
|
style="width: 100%"
|
||||||
|
/>
|
||||||
|
</j-form-item>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="column.key === 'scale'">
|
||||||
|
<j-form-item :name="['data', index, 'scale']">
|
||||||
|
<j-input-number
|
||||||
|
v-model:value="record.scale"
|
||||||
|
:min="0"
|
||||||
|
:max="99999"
|
||||||
|
style="width: 100%"
|
||||||
|
/>
|
||||||
|
</j-form-item>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="column.key === 'notnull'">
|
||||||
|
<j-form-item
|
||||||
|
:name="['data', index, 'notnull']"
|
||||||
|
:rules="[
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: '请选择是否不能为空',
|
||||||
|
},
|
||||||
|
]"
|
||||||
|
>
|
||||||
|
<j-radio-group
|
||||||
|
v-model:value="record.notnull"
|
||||||
|
button-style="solid"
|
||||||
|
>
|
||||||
|
<j-radio-button :value="true"
|
||||||
|
>是</j-radio-button
|
||||||
|
>
|
||||||
|
<j-radio-button :value="false"
|
||||||
|
>否</j-radio-button
|
||||||
|
>
|
||||||
|
</j-radio-group>
|
||||||
|
</j-form-item>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="column.key === 'comment'">
|
||||||
|
<j-form-item :name="['data', index, 'comment']">
|
||||||
|
<j-input
|
||||||
|
v-model:value="record.comment"
|
||||||
|
placeholder="请输入说明"
|
||||||
|
/>
|
||||||
|
</j-form-item>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="column.key === 'action'">
|
||||||
|
<PermissionButton
|
||||||
|
hasPermission="system/DataSource:delete"
|
||||||
|
type="link"
|
||||||
|
:tooltip="{ title: '删除' }"
|
||||||
|
:danger="true"
|
||||||
|
:popConfirm="{
|
||||||
|
title: `确认删除`,
|
||||||
|
onConfirm: () =>
|
||||||
|
clickDel(record, index),
|
||||||
|
}"
|
||||||
|
:disabled="record.status"
|
||||||
|
>
|
||||||
|
<AIcon type="DeleteOutlined" />
|
||||||
|
</PermissionButton>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
</j-table>
|
||||||
|
</j-form>
|
||||||
|
|
||||||
<j-button class="add-row" @click="addRow">
|
<j-button class="add-row" @click="addRow">
|
||||||
<AIcon type="PlusOutlined" /> 新增行
|
<AIcon type="PlusOutlined" /> 新增行
|
||||||
</j-button>
|
</j-button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</FullPage>
|
||||||
<j-modal
|
<j-modal
|
||||||
:visible="true"
|
:visible="true"
|
||||||
v-if="dialog.visible"
|
v-if="dialog.visible"
|
||||||
|
@ -495,12 +499,15 @@ const checkName = (_: any, value: any) =>
|
||||||
padding: 24px;
|
padding: 24px;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
display: flex;
|
display: flex;
|
||||||
min-height: 500px;
|
height: 100%;
|
||||||
|
|
||||||
.left {
|
.left {
|
||||||
flex-basis: 280px;
|
flex-basis: 280px;
|
||||||
padding: 0 24px;
|
padding: 0 24px;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
|
width:300px;
|
||||||
|
height:100%;
|
||||||
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
.right {
|
.right {
|
||||||
width: calc(100% - 280px);
|
width: calc(100% - 280px);
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
>
|
>
|
||||||
<div class="alert">
|
<div class="alert">
|
||||||
<AIcon type="InfoCircleOutlined" />
|
<AIcon type="InfoCircleOutlined" />
|
||||||
通过角色控制【{{ name }}】的所有的通知方式可被哪些用户订阅。
|
通过角色控制哪些用户可以订阅【{{ name }}】下所有的通知方式。
|
||||||
</div>
|
</div>
|
||||||
<Role v-model="_selectedRowKeys" :gridColumn="2" />
|
<Role v-model="_selectedRowKeys" :gridColumn="2" />
|
||||||
</j-modal>
|
</j-modal>
|
||||||
|
|
|
@ -63,7 +63,7 @@
|
||||||
<template v-if="current === 4">
|
<template v-if="current === 4">
|
||||||
<div class="alert">
|
<div class="alert">
|
||||||
<AIcon type="InfoCircleOutlined" />
|
<AIcon type="InfoCircleOutlined" />
|
||||||
已规定固定收信人的模板在当前页面将被过滤
|
通过角色控制哪些用户可以订阅从【{{ name }}】接收到【{{ showName }}】通知
|
||||||
</div>
|
</div>
|
||||||
<Role type="add" v-model="formModel.grant.role.idList" />
|
<Role type="add" v-model="formModel.grant.role.idList" />
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -109,7 +109,7 @@
|
||||||
</j-button>
|
</j-button>
|
||||||
</j-form-item>
|
</j-form-item>
|
||||||
</j-form>
|
</j-form>
|
||||||
<div class="other">
|
<div class="other" v-if="bindings.length">
|
||||||
<j-divider plain>
|
<j-divider plain>
|
||||||
<div class="other-text">
|
<div class="other-text">
|
||||||
其他登录方式
|
其他登录方式
|
||||||
|
@ -245,7 +245,7 @@ const codeUrl = ref('');
|
||||||
const codeConfig = ref(false);
|
const codeConfig = ref(false);
|
||||||
|
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
const bindings = ref<any[]>();
|
const bindings = ref<any[]>([]);
|
||||||
// const basis = ref<any>({});
|
// const basis = ref<any>({});
|
||||||
|
|
||||||
const defaultImg = getImage('/apply/internal-standalone.png');
|
const defaultImg = getImage('/apply/internal-standalone.png');
|
||||||
|
|
Loading…
Reference in New Issue