fix: bug#19215、19214、19213、19183、19060、19090、19167、19090
* fix: 优化物模型配置按钮样式 * fix: bug#18263 * fix: 优化iframe中hash地址 * fix: bug#19132 * fix: bug#19071 * Dev bug (#217) * fix: bug#19215、19214、19213、19183 * fix: bug#19060、19090 * fix: bug#19167 * fix: bug#19080 * fix: bug#19181 * fix: bug#19060、19090 * fix: bug#19181 * fix: iframe组件优化没有参数时,url格式
This commit is contained in:
parent
2c891e7f49
commit
f473124ce8
2
.npmrc
2
.npmrc
|
@ -1,2 +1,2 @@
|
||||||
always-auth=true
|
always-auth=true
|
||||||
registry=http://registry.jetlinks.cn/
|
registry=https://registry.npmjs.org/
|
||||||
|
|
12
README.md
12
README.md
|
@ -48,6 +48,18 @@ yarn dev:force
|
||||||
|
|
||||||
此处可以更改系统名称、主题色、系统logo、浏览器页签等
|
此处可以更改系统名称、主题色、系统logo、浏览器页签等
|
||||||
|
|
||||||
|
#### 主题色
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// src/App.vue
|
||||||
|
|
||||||
|
ConfigProvider.config({
|
||||||
|
theme: {
|
||||||
|
primaryColor: "#315efb"
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
#### 2.默认配置
|
#### 2.默认配置
|
||||||
|
|
||||||
在代码根目录找到`config\config.ts`文件
|
在代码根目录找到`config\config.ts`文件
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
"event-source-polyfill": "^1.0.31",
|
"event-source-polyfill": "^1.0.31",
|
||||||
"global": "^4.4.0",
|
"global": "^4.4.0",
|
||||||
"jetlinks-store": "^0.0.3",
|
"jetlinks-store": "^0.0.3",
|
||||||
"jetlinks-ui-components": "^1.0.33",
|
"jetlinks-ui-components": "^1.0.34-4",
|
||||||
"js-cookie": "^3.0.1",
|
"js-cookie": "^3.0.1",
|
||||||
"jsencrypt": "^3.3.2",
|
"jsencrypt": "^3.3.2",
|
||||||
"less": "^4.1.3",
|
"less": "^4.1.3",
|
||||||
|
|
|
@ -15,7 +15,11 @@ const system = useSystem();
|
||||||
const {configInfo} = storeToRefs(system);
|
const {configInfo} = storeToRefs(system);
|
||||||
|
|
||||||
system.setDocumentTitle()
|
system.setDocumentTitle()
|
||||||
|
ConfigProvider.config({
|
||||||
|
theme: {
|
||||||
|
primaryColor: "#315efb"
|
||||||
|
}
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="editor">
|
<div class="editor">
|
||||||
<j-monaco-editor v-if="loading" v-model:model-value="_value" theme="vs" ref="editor" language="javascript" :registrationTypescript="typescriptTip"
|
<j-monaco-editor v-if="loading" v-model:model-value="_value" theme="vs" ref="editor" language="javascript" :registrationTypescript="typescriptTip" :registrationTips="registrationTips"
|
||||||
:init="editorInit"/>
|
:init="editorInit"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -41,11 +41,13 @@ import {
|
||||||
} from '@/api/device/instance';
|
} from '@/api/device/instance';
|
||||||
import { useInstanceStore } from '@/store/instance';
|
import { useInstanceStore } from '@/store/instance';
|
||||||
import { useProductStore } from '@/store/product';
|
import { useProductStore } from '@/store/product';
|
||||||
|
import { cloneDeep } from 'lodash-es';
|
||||||
import { inject } from 'vue'
|
import { inject } from 'vue'
|
||||||
interface Props {
|
interface Props {
|
||||||
mode?: 'advance' | 'simple';
|
mode?: 'advance' | 'simple';
|
||||||
id?: string;
|
id?: string;
|
||||||
value?: string;
|
value?: string;
|
||||||
|
tips?: Array<any>
|
||||||
}
|
}
|
||||||
const props = defineProps<Props>()
|
const props = defineProps<Props>()
|
||||||
const target = inject('target')
|
const target = inject('target')
|
||||||
|
@ -71,28 +73,9 @@ type SymbolType = {
|
||||||
const typescriptTip = reactive({
|
const typescriptTip = reactive({
|
||||||
typescript: ''
|
typescript: ''
|
||||||
})
|
})
|
||||||
|
const registrationTips = ref<any>({
|
||||||
const queryCode = () => {
|
name: 'javascript'
|
||||||
let id = ''
|
})
|
||||||
if(target==='device'){
|
|
||||||
id = instanceStore.current.id
|
|
||||||
queryTypescript(id).then(res => {
|
|
||||||
if (res.status===200) {
|
|
||||||
typescriptTip.typescript = res.result
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}else if(target ==='product'){
|
|
||||||
id = productStore.current.id
|
|
||||||
queryProductTs(id).then(res => {
|
|
||||||
if (res.status===200) {
|
|
||||||
typescriptTip.typescript = res.result
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
queryCode()
|
|
||||||
|
|
||||||
const editorInit = (editor: any, monaco: any) => {
|
const editorInit = (editor: any, monaco: any) => {
|
||||||
monaco.languages.typescript.javascriptDefaults.setDiagnosticsOptions({
|
monaco.languages.typescript.javascriptDefaults.setDiagnosticsOptions({
|
||||||
noSemanticValidation: true,
|
noSemanticValidation: true,
|
||||||
|
@ -200,11 +183,27 @@ const _value = computed({
|
||||||
})
|
})
|
||||||
|
|
||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
onMounted(() => {
|
const queryCode = () => {
|
||||||
setTimeout(() => {
|
registrationTips.value.suggestions = cloneDeep(props.tips)
|
||||||
loading.value = true;
|
let id = ''
|
||||||
}, 100);
|
if(target==='device'){
|
||||||
})
|
id = instanceStore.current.id
|
||||||
|
queryTypescript(id).then(res => {
|
||||||
|
if (res.status===200) {
|
||||||
|
typescriptTip.typescript = res.result
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}else if(target ==='product'){
|
||||||
|
id = productStore.current.id
|
||||||
|
queryProductTs(id).then(res => {
|
||||||
|
if (res.status===200) {
|
||||||
|
typescriptTip.typescript = res.result
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const addOperatorValue = (val: string) => {
|
const addOperatorValue = (val: string) => {
|
||||||
editor.value?.insert(val)
|
editor.value?.insert(val)
|
||||||
|
@ -220,6 +219,13 @@ defineExpose({
|
||||||
addOperatorValue
|
addOperatorValue
|
||||||
})
|
})
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
setTimeout(() => {
|
||||||
|
loading.value = true;
|
||||||
|
}, 100);
|
||||||
|
})
|
||||||
|
|
||||||
|
queryCode()
|
||||||
</script>
|
</script>
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
.editor-box {
|
.editor-box {
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
mode="advance"
|
mode="advance"
|
||||||
key="advance"
|
key="advance"
|
||||||
v-model:value="_value"
|
v-model:value="_value"
|
||||||
|
:tips="tips"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -49,7 +50,7 @@
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<j-space>
|
<j-space>
|
||||||
<j-button @click="handleCancel">取消</j-button>
|
<j-button @click="handleCancel">取消</j-button>
|
||||||
<j-button :disabled="_disabled" @click="handleOk" type="primary">确定</j-button>
|
<j-button @click="handleOk" type="primary">确定</j-button>
|
||||||
</j-space>
|
</j-space>
|
||||||
</template>
|
</template>
|
||||||
</j-modal>
|
</j-modal>
|
||||||
|
@ -59,7 +60,8 @@ import Editor from './Editor/index.vue';
|
||||||
import Debug from './Debug/index.vue';
|
import Debug from './Debug/index.vue';
|
||||||
import Operator from './Operator/index.vue';
|
import Operator from './Operator/index.vue';
|
||||||
import { FULL_CODE } from 'jetlinks-ui-components/es/DataTable'
|
import { FULL_CODE } from 'jetlinks-ui-components/es/DataTable'
|
||||||
|
import { cloneDeep } from 'lodash-es';
|
||||||
|
import { PropertyMetadata } from '@/views/device/Product/typings';
|
||||||
interface Emits {
|
interface Emits {
|
||||||
(e: 'save', data: string | undefined): void;
|
(e: 'save', data: string | undefined): void;
|
||||||
(e: 'close'): void;
|
(e: 'close'): void;
|
||||||
|
@ -77,7 +79,7 @@ const props = defineProps({
|
||||||
const _value = ref<string | undefined>(props.value);
|
const _value = ref<string | undefined>(props.value);
|
||||||
const _disabled = ref<boolean>(true);
|
const _disabled = ref<boolean>(true);
|
||||||
const fullRef = inject(FULL_CODE);
|
const fullRef = inject(FULL_CODE);
|
||||||
|
const tips = ref<any[]>([])
|
||||||
const handleCancel = () => {
|
const handleCancel = () => {
|
||||||
emit('close');
|
emit('close');
|
||||||
};
|
};
|
||||||
|
@ -98,13 +100,38 @@ const addOperatorValue = (val: string) => {
|
||||||
editor.value.addOperatorValue(val);
|
editor.value.addOperatorValue(val);
|
||||||
};
|
};
|
||||||
|
|
||||||
watch(() => _value.value, () => {
|
const getAllCrud = () => {
|
||||||
_disabled.value = true
|
const list = cloneDeep(props.propertiesOptions)?.filter((i:any)=>
|
||||||
})
|
props?.id !== i.id
|
||||||
|
)
|
||||||
const onSuccess = (bool: boolean) => {
|
console.log(list,'list')
|
||||||
_disabled.value = bool;
|
// 转化为语法提示
|
||||||
|
list.forEach(item => {
|
||||||
|
console.log(item)
|
||||||
|
const config = item
|
||||||
|
tips.value.push({
|
||||||
|
label: `${config.name}$recent实时值`,
|
||||||
|
insertText:`$recent ("${config.id}")`,
|
||||||
|
kind: 18,
|
||||||
|
})
|
||||||
|
tips.value.push({
|
||||||
|
label: `${config.name}上一值`,
|
||||||
|
insertText: `$lastState("${config.id}"))`,
|
||||||
|
kind: 18
|
||||||
|
})
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// watch(() => _value.value, () => {
|
||||||
|
// console.log(_value.value)
|
||||||
|
// _disabled.value = true
|
||||||
|
// })
|
||||||
|
|
||||||
|
// const onSuccess = (bool: boolean) => {
|
||||||
|
// _disabled.value = bool;
|
||||||
|
// }
|
||||||
|
getAllCrud()
|
||||||
</script>
|
</script>
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
.header {
|
.header {
|
||||||
|
|
|
@ -25,9 +25,11 @@
|
||||||
<UserInfo />
|
<UserInfo />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<router-view v-slot="{ Component }">
|
<slot>
|
||||||
<component :is="components || Component" />
|
<router-view v-slot="{ Component }">
|
||||||
</router-view>
|
<component :is="components || Component" />
|
||||||
|
</router-view>
|
||||||
|
</slot>
|
||||||
</j-pro-layout>
|
</j-pro-layout>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -40,6 +42,7 @@ import { clearMenuItem } from 'jetlinks-ui-components/es/ProLayout/util';
|
||||||
import { AccountMenu } from '@/router/menu'
|
import { AccountMenu } from '@/router/menu'
|
||||||
import { useSystem } from '@/store/system';
|
import { useSystem } from '@/store/system';
|
||||||
import { storeToRefs } from 'pinia';
|
import { storeToRefs } from 'pinia';
|
||||||
|
import { useSlots } from 'vue'
|
||||||
|
|
||||||
type StateType = {
|
type StateType = {
|
||||||
collapsed: boolean;
|
collapsed: boolean;
|
||||||
|
@ -55,7 +58,7 @@ const menu = useMenuStore();
|
||||||
|
|
||||||
const system = useSystem();
|
const system = useSystem();
|
||||||
const {configInfo,layout, basicLayout} = storeToRefs(system);
|
const {configInfo,layout, basicLayout} = storeToRefs(system);
|
||||||
|
const slots = useSlots()
|
||||||
const layoutConf = reactive({
|
const layoutConf = reactive({
|
||||||
theme: DefaultSetting.layout.theme,
|
theme: DefaultSetting.layout.theme,
|
||||||
siderWidth: layout.value.siderWidth,
|
siderWidth: layout.value.siderWidth,
|
||||||
|
@ -107,8 +110,6 @@ const jump = (item: any) => {
|
||||||
router.push(item.path)
|
router.push(item.path)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
watchEffect(() => {
|
watchEffect(() => {
|
||||||
if (router.currentRoute) {
|
if (router.currentRoute) {
|
||||||
const paths = router.currentRoute.value.matched
|
const paths = router.currentRoute.value.matched
|
||||||
|
@ -116,6 +117,10 @@ watchEffect(() => {
|
||||||
basicLayout.value.openKeys = paths.map(item => item.path)
|
basicLayout.value.openKeys = paths.map(item => item.path)
|
||||||
console.log(paths) //
|
console.log(paths) //
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (route.query?.layout === 'false') {
|
||||||
|
basicLayout.value.pure = true
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const toDoc = () => window.open('http://doc.v2.jetlinks.cn/');
|
const toDoc = () => window.open('http://doc.v2.jetlinks.cn/');
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<template>
|
<template>
|
||||||
<template v-if="isPermission">
|
<template v-if="isPermission">
|
||||||
<template v-if="popConfirm">
|
<template v-if="popConfirm">
|
||||||
<j-popconfirm :overlayStyle='{width: "220px"}' v-bind="popConfirm" :disabled="!isPermission || props.disabled">
|
<j-popconfirm :disabled="!isPermission || props.disabled" :overlayStyle='{width: "220px", zIndex: 1075 }' v-bind="popConfirm">
|
||||||
<j-tooltip v-if="tooltip" v-bind="tooltip">
|
<j-tooltip v-if="tooltip" v-bind="tooltip">
|
||||||
<slot v-if="noButton"></slot>
|
<slot v-if="noButton"></slot>
|
||||||
<j-button v-else v-bind="props" :disabled="_isPermission" :style="props.style">
|
<j-button v-else v-bind="props" :disabled="_isPermission" :style="props.style">
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
export * from './useRequest'
|
|
@ -0,0 +1,92 @@
|
||||||
|
import {onUnmounted, ref} from 'vue'
|
||||||
|
import type { Ref } from 'vue'
|
||||||
|
import {isFunction, get, isArray} from 'lodash-es'
|
||||||
|
import type { AxiosResponseRewrite } from '@/utils/request'
|
||||||
|
|
||||||
|
interface RequestOptions<T, S> {
|
||||||
|
immediate: boolean
|
||||||
|
/**
|
||||||
|
* 成功回调
|
||||||
|
* @param data
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
onSuccess: (data: AxiosResponseRewrite<S>) => S | void
|
||||||
|
/**
|
||||||
|
* 返回参数处理
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
formatName: string | [string]
|
||||||
|
onError: (e: any) => void
|
||||||
|
|
||||||
|
defaultParams: S | any | any[]
|
||||||
|
|
||||||
|
handleResponse: (data: any) => any
|
||||||
|
}
|
||||||
|
|
||||||
|
const defaultOptions: any = {
|
||||||
|
immediate: true,
|
||||||
|
formatName: 'result'
|
||||||
|
}
|
||||||
|
|
||||||
|
type Run = (...args: any[]) => void
|
||||||
|
|
||||||
|
export const useRequest = <T = any, S = any>(
|
||||||
|
request: (...args: any[]) => Promise<AxiosResponseRewrite<T>>,
|
||||||
|
options: Partial<RequestOptions<T, S>> = defaultOptions,
|
||||||
|
): {
|
||||||
|
data: Ref<S | undefined>,
|
||||||
|
loading: Ref<boolean>,
|
||||||
|
run: Run
|
||||||
|
} => {
|
||||||
|
const data = ref<S>()
|
||||||
|
const loading = ref(false)
|
||||||
|
const _options = {
|
||||||
|
...defaultOptions,
|
||||||
|
...options
|
||||||
|
}
|
||||||
|
|
||||||
|
async function run(...arg: any[]) {
|
||||||
|
if (request && isFunction(request)) {
|
||||||
|
loading.value = true
|
||||||
|
try {
|
||||||
|
// @ts-ignore
|
||||||
|
const resp = await request.apply(this, arg)
|
||||||
|
|
||||||
|
loading.value = false
|
||||||
|
|
||||||
|
if (resp?.success) {
|
||||||
|
const successData = await _options.onSuccess?.(resp)
|
||||||
|
data.value = successData || get(resp, _options.formatName!)
|
||||||
|
// console.log(data.value)
|
||||||
|
} else {
|
||||||
|
_options.onError?.(resp)
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
loading.value = false
|
||||||
|
_options.onError?.(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_options.immediate) { // 主动触发
|
||||||
|
if (_options.defaultParams) {
|
||||||
|
isArray(_options.defaultParams) ? run(..._options.defaultParams) : run(_options.defaultParams)
|
||||||
|
} else {
|
||||||
|
run()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onUnmounted(() => {
|
||||||
|
// 销毁时,撤销该请求
|
||||||
|
if (request && isFunction(request)) {
|
||||||
|
|
||||||
|
}
|
||||||
|
// request()
|
||||||
|
})
|
||||||
|
|
||||||
|
return {
|
||||||
|
data,
|
||||||
|
loading,
|
||||||
|
run
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,7 +4,7 @@ import store from './store'
|
||||||
import components from './components'
|
import components from './components'
|
||||||
import router from './router'
|
import router from './router'
|
||||||
import './style.less'
|
import './style.less'
|
||||||
|
import 'ant-design-vue/dist/antd.variable.min.css'
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
import 'dayjs/locale/zh-cn';
|
import 'dayjs/locale/zh-cn';
|
||||||
dayjs.locale('zh-cn');
|
dayjs.locale('zh-cn');
|
||||||
|
|
|
@ -24,12 +24,12 @@ const defaultOwnParams = [
|
||||||
termType: 'eq',
|
termType: 'eq',
|
||||||
value: 'iot'
|
value: 'iot'
|
||||||
},
|
},
|
||||||
{
|
// {
|
||||||
column: 'owner',
|
// column: 'owner',
|
||||||
termType: 'isnull',
|
// termType: 'isnull',
|
||||||
value: '1',
|
// value: '1',
|
||||||
type: 'or'
|
// type: 'or'
|
||||||
}
|
// }
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -30,9 +30,9 @@ body {
|
||||||
|
|
||||||
.ant-pro-top-nav-header {
|
.ant-pro-top-nav-header {
|
||||||
.ant-menu-item {
|
.ant-menu-item {
|
||||||
padding: 0 10px !important;
|
padding: 0 14px !important;
|
||||||
&:not(:first-child) {
|
&:first-child {
|
||||||
margin-left: 8px !important;
|
padding: 0 10px !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { BlankLayoutPage, BasicLayoutPage } from 'components/Layout'
|
import { BlankLayoutPage, BasicLayoutPage } 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 { shallowRef, defineAsyncComponent } from 'vue'
|
||||||
|
|
||||||
const pagesComponent = import.meta.glob('../views/**/*.vue');
|
const pagesComponent = import.meta.glob('../views/**/*.vue');
|
||||||
|
|
||||||
|
@ -155,192 +156,6 @@ const extraRouteObj = {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
//
|
|
||||||
// const resolveComponent = (name: any) => {
|
|
||||||
// const importPage = pagesComponent[`../views/${name}/index.vue`];
|
|
||||||
// console.log(importPage)
|
|
||||||
// if (!importPage) {
|
|
||||||
// return undefined
|
|
||||||
// } else {
|
|
||||||
// const res = () => importPage()
|
|
||||||
// return res
|
|
||||||
// }
|
|
||||||
// //@ts-ignore
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// const findChildrenRoute = (code: string, url: string, routes: any[] = []): MenuItem[] => {
|
|
||||||
// if (extraRouteObj[code]) {
|
|
||||||
// const extraRoutes = extraRouteObj[code].children.map((route: MenuItem) => {
|
|
||||||
// return {
|
|
||||||
// url: `${url}/${route.code}`,
|
|
||||||
// code: `${code}/${route.code}`,
|
|
||||||
// name: route.name,
|
|
||||||
// isShow: false
|
|
||||||
// }
|
|
||||||
// })
|
|
||||||
// return [...routes, ...extraRoutes]
|
|
||||||
// }
|
|
||||||
// return routes
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// const findDetailRouteItem = (code: string, url: string): Partial<MenuItem> | null => {
|
|
||||||
// const detailComponent = resolveComponent(`${code}/Detail`)
|
|
||||||
// if (detailComponent) {
|
|
||||||
// return {
|
|
||||||
// url: `${url}/detail/:id`,
|
|
||||||
// code: `${code}/Detail`,
|
|
||||||
// component: detailComponent,
|
|
||||||
// name: '详情信息',
|
|
||||||
// isShow: false
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// return null
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// const findDetailRoutes = (routes: any[]): any[] => {
|
|
||||||
// const newRoutes: any[] = []
|
|
||||||
// routes.forEach((route: any) => {
|
|
||||||
// newRoutes.push(route)
|
|
||||||
// const detail = findDetailRouteItem(route.code, route.url)
|
|
||||||
// if (detail) {
|
|
||||||
// newRoutes.push(detail)
|
|
||||||
// }
|
|
||||||
// })
|
|
||||||
// return newRoutes
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// const filterMenus = ['device/DashBoard']
|
|
||||||
// export const filterCommunityMenus = (menuData: any[]) => {
|
|
||||||
// return menuData.filter(item => {
|
|
||||||
// if (item.children) {
|
|
||||||
// item.children = filterCommunityMenus(item.children)
|
|
||||||
// }
|
|
||||||
// return !filterMenus.includes(item.code)
|
|
||||||
// })
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// export const findCodeRoute = (asyncRouterMap: any[]) => {
|
|
||||||
// const routeMeta = {}
|
|
||||||
//
|
|
||||||
// function getDetail(code: string, url: string) {
|
|
||||||
// const detail = findDetailRouteItem(code, url)
|
|
||||||
// if (!detail) return
|
|
||||||
//
|
|
||||||
// routeMeta[(detail as MenuItem).code] = {
|
|
||||||
// path: detail.url,
|
|
||||||
// title: detail.name,
|
|
||||||
// parentName: code,
|
|
||||||
// buttons: detail.buttons?.map((b: any) => b.id) || []
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// function findChildren(data: any[], code: string = '') {
|
|
||||||
// data.forEach(route => {
|
|
||||||
// routeMeta[route.code] = {
|
|
||||||
// path: route.url || route.path,
|
|
||||||
// title: route.meta?.title || route.name,
|
|
||||||
// parentName: code,
|
|
||||||
// buttons: route.buttons?.map((b: any) => b.id) || []
|
|
||||||
// }
|
|
||||||
// const otherRoutes = extraRouteObj[route.code]
|
|
||||||
//
|
|
||||||
// if (otherRoutes) {
|
|
||||||
// otherRoutes.children.map((item: any) => {
|
|
||||||
// const _code = `${route.code}/${item.code}`
|
|
||||||
// const url = `${route.url}/${item.code}`
|
|
||||||
// routeMeta[_code] = {
|
|
||||||
// path: `${route.url}/${item.code}`,
|
|
||||||
// title: item.name,
|
|
||||||
// parentName: route.code,
|
|
||||||
// buttons: item.buttons?.map((b: any) => b.id) || []
|
|
||||||
// }
|
|
||||||
// getDetail(_code, url)
|
|
||||||
// })
|
|
||||||
// }
|
|
||||||
// const _code = route.appId ? `/${route.appId}${route.url}` : route.code
|
|
||||||
// if (!route.appId) {
|
|
||||||
// getDetail(_code, route.url)
|
|
||||||
// } else {
|
|
||||||
// routeMeta[_code] = {
|
|
||||||
// path: `/${route.appId}${route.url}`,
|
|
||||||
// title: route.name,
|
|
||||||
// parentName: code,
|
|
||||||
// buttons: []
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// if (route.children) {
|
|
||||||
// findChildren(route.children, _code)
|
|
||||||
// }
|
|
||||||
// })
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// findChildren(asyncRouterMap)
|
|
||||||
//
|
|
||||||
// return routeMeta
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// export function filterAsyncRouter(asyncRouterMap: any, parentCode = '', level = 1): { menusData: any, silderMenus: any } {
|
|
||||||
// const _asyncRouterMap = cloneDeep(asyncRouterMap)
|
|
||||||
// const menusData: any[] = []
|
|
||||||
// const silderMenus: any[] = []
|
|
||||||
// _asyncRouterMap.forEach((route: any) => {
|
|
||||||
// const hasAppId = route.appId
|
|
||||||
// const _route: any = {
|
|
||||||
// path: hasAppId ? `/${route.appId}${route.url}` : `${route.url}`,
|
|
||||||
// name: hasAppId ? `/${route.appId}${route.url}` : route.code,
|
|
||||||
// url: hasAppId ? `/${route.appId}${route.url}` : route.url,
|
|
||||||
// meta: {
|
|
||||||
// icon: route.icon,
|
|
||||||
// title: route.name,
|
|
||||||
// hideInMenu: route.isShow === false,
|
|
||||||
// buttons: route.buttons?.map((b: any) => b.id) || [],
|
|
||||||
// isApp: hasAppId,
|
|
||||||
// },
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// const silder = { ..._route }
|
|
||||||
// // 查看是否有隐藏子路由
|
|
||||||
// route.children = findChildrenRoute(route.code, route.url, route.children)
|
|
||||||
// route.children = findDetailRoutes(route.children)
|
|
||||||
// if (route.children && route.children.length) {
|
|
||||||
// // TODO 查看是否具有详情页
|
|
||||||
// const { menusData: _menusData, silderMenus: _silderMenus } = filterAsyncRouter(route.children, `${parentCode}/${route.code}`, level + 1)
|
|
||||||
// _route.children = _menusData
|
|
||||||
// silder.children = _silderMenus
|
|
||||||
// const showChildren = _route.children.some((r: any) => !r.meta.hideInMenu)
|
|
||||||
//
|
|
||||||
// if (showChildren && _route.children.length) {
|
|
||||||
// _route.component = level === 1 ? BasicLayoutPage : BlankLayoutPage
|
|
||||||
// _route.redirect = _route.children[0].url
|
|
||||||
// } else {
|
|
||||||
// const myComponent = resolveComponent(route.code)
|
|
||||||
// // _route.component = myComponent ? myComponent : BlankLayoutPage;
|
|
||||||
// if (!!myComponent) {
|
|
||||||
// _route.component = myComponent;
|
|
||||||
// _route.children.map((r: any) => menusData.push(r))
|
|
||||||
// delete _route.children
|
|
||||||
// } else {
|
|
||||||
// _route.component = BlankLayoutPage
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// if (hasAppId) {
|
|
||||||
// _route.component = route.component || resolveComponent('iframe')
|
|
||||||
// } else {
|
|
||||||
// _route.component = route.component || resolveComponent(route.code) || BlankLayoutPage
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// menusData.push(_route)
|
|
||||||
// silderMenus.push(silder)
|
|
||||||
// })
|
|
||||||
// return {
|
|
||||||
// menusData,
|
|
||||||
// silderMenus,
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
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: { appId?: string, url?: string }): { isApp: boolean, appUrl: string } => {
|
||||||
|
@ -367,6 +182,12 @@ const handleMeta = (item: MenuItem, isApp: boolean) => {
|
||||||
const findComponents = (code: string, level: number, isApp: boolean, components: any) => {
|
const findComponents = (code: string, level: number, isApp: boolean, components: any) => {
|
||||||
const myComponents = components[code]
|
const myComponents = components[code]
|
||||||
if (level === 1) { // BasicLayoutPage
|
if (level === 1) { // BasicLayoutPage
|
||||||
|
if (myComponents) {
|
||||||
|
return h(BasicLayoutPage, {}, () => [h(defineAsyncComponent(() => myComponents()), {})])
|
||||||
|
}
|
||||||
|
if (isApp) {
|
||||||
|
return h(BasicLayoutPage, {}, () => [h(Iframe, {})])
|
||||||
|
}
|
||||||
return myComponents ? () => myComponents() : BasicLayoutPage
|
return myComponents ? () => myComponents() : BasicLayoutPage
|
||||||
} else if (isApp){ // iframe
|
} else if (isApp){ // iframe
|
||||||
return Iframe
|
return Iframe
|
||||||
|
|
|
@ -6,7 +6,7 @@ import { LoginPath } from '@/router/menu'
|
||||||
import { cleanToken, getToken, LocalStore } from '@/utils/comm'
|
import { cleanToken, getToken, LocalStore } from '@/utils/comm'
|
||||||
import type { AxiosInstance, AxiosResponse } from 'axios'
|
import type { AxiosInstance, AxiosResponse } from 'axios'
|
||||||
|
|
||||||
interface AxiosResponseRewrite<T = any[]> extends AxiosResponse<T, any> {
|
export interface AxiosResponseRewrite<T = any[]> extends AxiosResponse<T, any> {
|
||||||
result: T
|
result: T
|
||||||
success: boolean
|
success: boolean
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
:dataSource="modelRef.dataSource"
|
:dataSource="modelRef.dataSource"
|
||||||
:columns="FormTableColumns"
|
:columns="FormTableColumns"
|
||||||
:scroll="{ y: 580 }"
|
:scroll="{ y: 580 }"
|
||||||
|
:pagination="false"
|
||||||
>
|
>
|
||||||
<template #headerCell="{ column }">
|
<template #headerCell="{ column }">
|
||||||
<template
|
<template
|
||||||
|
@ -308,7 +309,6 @@ watch(
|
||||||
() => props.data,
|
() => props.data,
|
||||||
(value, preValue) => {
|
(value, preValue) => {
|
||||||
modelRef.dataSource = value;
|
modelRef.dataSource = value;
|
||||||
|
|
||||||
// 有新增时同上数据
|
// 有新增时同上数据
|
||||||
const vlength = value.length,
|
const vlength = value.length,
|
||||||
plength = preValue.length;
|
plength = preValue.length;
|
||||||
|
|
|
@ -133,13 +133,13 @@
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<j-form-item
|
<j-form-item
|
||||||
:name="['configuration', 'requsetTimeout']"
|
:name="['configuration', 'requestTimeout']"
|
||||||
:rules="LeftTreeRules.requsetTimeout"
|
:rules="LeftTreeRules.requestTimeout"
|
||||||
>
|
>
|
||||||
<j-input-number
|
<j-input-number
|
||||||
style="width: 100%"
|
style="width: 100%"
|
||||||
placeholder="请输入请求超时时间配置"
|
placeholder="请输入请求超时时间配置"
|
||||||
v-model:value="formData.configuration.requsetTimeout"
|
v-model:value="formData.configuration.requestTimeout"
|
||||||
addon-after="ms"
|
addon-after="ms"
|
||||||
:max="60000"
|
:max="60000"
|
||||||
:min="2000"
|
:min="2000"
|
||||||
|
@ -257,7 +257,7 @@ const formData = ref({
|
||||||
type: 'LowerFrequency',
|
type: 'LowerFrequency',
|
||||||
endian: 'BIG',
|
endian: 'BIG',
|
||||||
endianIn: 'BIG',
|
endianIn: 'BIG',
|
||||||
requsetTimeout: 2000,
|
requestTimeout: 2000,
|
||||||
inheritBreakerSpec: {
|
inheritBreakerSpec: {
|
||||||
type: 'LowerFrequency',
|
type: 'LowerFrequency',
|
||||||
}
|
}
|
||||||
|
|
|
@ -170,7 +170,7 @@ export const LeftTreeRules = {
|
||||||
endianIn: [
|
endianIn: [
|
||||||
{ required: true, message: '请选择单字高低位切换', trigger: 'blur' },
|
{ required: true, message: '请选择单字高低位切换', trigger: 'blur' },
|
||||||
],
|
],
|
||||||
requsetTimeout:[
|
requestTimeout:[
|
||||||
{ pattern: /^\d+$/, message:'请输入2000-60000的正整数',trigger: 'change'}
|
{ pattern: /^\d+$/, message:'请输入2000-60000的正整数',trigger: 'change'}
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
|
|
@ -90,6 +90,7 @@ import {
|
||||||
} from '@/utils/consts';
|
} from '@/utils/consts';
|
||||||
import { usePermissionStore } from '@/store/permission';
|
import { usePermissionStore } from '@/store/permission';
|
||||||
import RoleShow from './components/RoleShow/index.vue';
|
import RoleShow from './components/RoleShow/index.vue';
|
||||||
|
import {isNoCommunity} from "@/utils/utils";
|
||||||
|
|
||||||
const imageTypes = reactive([
|
const imageTypes = reactive([
|
||||||
'image/jpeg',
|
'image/jpeg',
|
||||||
|
@ -103,7 +104,8 @@ const imageTypes = reactive([
|
||||||
const user = useUserInfo();
|
const user = useUserInfo();
|
||||||
|
|
||||||
type KeyType = 'HomeView' | 'BindThirdAccount' | 'Subscribe' | 'StationMessage';
|
type KeyType = 'HomeView' | 'BindThirdAccount' | 'Subscribe' | 'StationMessage';
|
||||||
const list: { key: KeyType; title: string }[] = [
|
console.log(isNoCommunity)
|
||||||
|
const list: { key: KeyType; title: string }[] = isNoCommunity ? [
|
||||||
{
|
{
|
||||||
key: 'HomeView',
|
key: 'HomeView',
|
||||||
title: '首页视图',
|
title: '首页视图',
|
||||||
|
@ -120,6 +122,19 @@ const list: { key: KeyType; title: string }[] = [
|
||||||
key: 'StationMessage',
|
key: 'StationMessage',
|
||||||
title: '站内信',
|
title: '站内信',
|
||||||
},
|
},
|
||||||
|
] : [
|
||||||
|
{
|
||||||
|
key: 'HomeView',
|
||||||
|
title: '首页视图',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'Subscribe',
|
||||||
|
title: '我的订阅',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'StationMessage',
|
||||||
|
title: '站内信',
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const tabs = {
|
const tabs = {
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
></j-col>
|
></j-col>
|
||||||
<j-col :span="6"
|
<j-col :span="6"
|
||||||
><TopCard
|
><TopCard
|
||||||
title="今日设备信息量"
|
title="今日设备消息量"
|
||||||
:footer="messageFooter"
|
:footer="messageFooter"
|
||||||
:value="dayMessage"
|
:value="dayMessage"
|
||||||
>
|
>
|
||||||
|
@ -395,6 +395,7 @@ const setDevMesChartOption = (
|
||||||
y: Array<number>,
|
y: Array<number>,
|
||||||
maxY: number,
|
maxY: number,
|
||||||
): void => {
|
): void => {
|
||||||
|
const yLen = String(Math.ceil(maxY)).length
|
||||||
devMegOptions.value = {
|
devMegOptions.value = {
|
||||||
xAxis: {
|
xAxis: {
|
||||||
type: 'category',
|
type: 'category',
|
||||||
|
@ -412,7 +413,7 @@ const setDevMesChartOption = (
|
||||||
grid: {
|
grid: {
|
||||||
top: '2%',
|
top: '2%',
|
||||||
bottom: '5%',
|
bottom: '5%',
|
||||||
left: maxY > 100000 ? '50px' : '70px',
|
left: maxY < 900000 ? '60px' : (yLen * 7.5 + Math.floor(yLen/3) * 1.2 + 10) + 'px',
|
||||||
right: '50px',
|
right: '50px',
|
||||||
},
|
},
|
||||||
series: [
|
series: [
|
||||||
|
@ -596,8 +597,9 @@ const getEcharts = (data: any) => {
|
||||||
const y = res.result.map((item: any) => item.data.value).reverse();
|
const y = res.result.map((item: any) => item.data.value).reverse();
|
||||||
const maxY = Math.max.apply(
|
const maxY = Math.max.apply(
|
||||||
null,
|
null,
|
||||||
messageChartYData.value.length ? messageChartYData.value : [0],
|
y.length ? y : [0],
|
||||||
);
|
);
|
||||||
|
|
||||||
setDevMesChartOption(x, y, maxY);
|
setDevMesChartOption(x, y, maxY);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,106 +1,60 @@
|
||||||
<template>
|
<template>
|
||||||
<SaveChild
|
<SaveChild v-if="childVisible" @close-child-save="closeChildSave" :childData="_current" />
|
||||||
v-if="childVisible"
|
|
||||||
@close-child-save="closeChildSave"
|
|
||||||
:childData="_current"
|
|
||||||
/>
|
|
||||||
<div v-else>
|
<div v-else>
|
||||||
<pro-search
|
<pro-search :columns="columns" target="child-device" @search="handleSearch" class="device-child-device-search" />
|
||||||
:columns="columns"
|
|
||||||
target="child-device"
|
|
||||||
@search="handleSearch"
|
|
||||||
class="device-child-device-search"
|
|
||||||
/>
|
|
||||||
<!-- <j-divider /> -->
|
<!-- <j-divider /> -->
|
||||||
<JProTable
|
<JProTable ref="childDeviceRef" :columns="columns" :request="query" :bodyStyle="{
|
||||||
ref="childDeviceRef"
|
padding: 0
|
||||||
:columns="columns"
|
}" :defaultParams="{
|
||||||
:request="query"
|
terms: [
|
||||||
:bodyStyle="{
|
{
|
||||||
padding: 0
|
column: 'parentId',
|
||||||
}"
|
value: detail?.id || '',
|
||||||
:defaultParams="{
|
termType: 'eq',
|
||||||
terms: [
|
},
|
||||||
{
|
],
|
||||||
column: 'parentId',
|
}" :rowSelection="{
|
||||||
value: detail?.id || '',
|
selectedRowKeys: _selectedRowKeys,
|
||||||
termType: 'eq',
|
onChange: onSelectChange,
|
||||||
},
|
}" :params="params" :model="'TABLE'">
|
||||||
],
|
|
||||||
}"
|
|
||||||
:rowSelection="{
|
|
||||||
selectedRowKeys: _selectedRowKeys,
|
|
||||||
onChange: onSelectChange,
|
|
||||||
}"
|
|
||||||
:params="params"
|
|
||||||
:model="'TABLE'"
|
|
||||||
>
|
|
||||||
<template #rightExtraRender>
|
<template #rightExtraRender>
|
||||||
<j-space>
|
<j-space>
|
||||||
<PermissionButton
|
<PermissionButton type="primary" v-if="detail?.accessProvider === 'official-edge-gateway'
|
||||||
type="primary"
|
" hasPermission="device/Instance:update" @click="
|
||||||
v-if="
|
_current = {};
|
||||||
detail?.accessProvider === 'official-edge-gateway'
|
childVisible = true;
|
||||||
"
|
">新增并绑定</PermissionButton>
|
||||||
hasPermission="device/Instance:update"
|
<PermissionButton type="primary" @click="visible = true" hasPermission="device/Instance:update">
|
||||||
@click="
|
绑定</PermissionButton>
|
||||||
_current = {};
|
<PermissionButton type="primary" hasPermission="device/Instance:update" :popConfirm="{
|
||||||
childVisible = true;
|
title: '确定解绑吗?',
|
||||||
"
|
onConfirm: handleUnBind,
|
||||||
>新增并绑定</PermissionButton
|
}">批量解除</PermissionButton>
|
||||||
>
|
|
||||||
<PermissionButton
|
|
||||||
type="primary"
|
|
||||||
@click="visible = true"
|
|
||||||
hasPermission="device/Instance:update"
|
|
||||||
>
|
|
||||||
绑定</PermissionButton
|
|
||||||
>
|
|
||||||
<PermissionButton
|
|
||||||
type="primary"
|
|
||||||
hasPermission="device/Instance:update"
|
|
||||||
:popConfirm="{
|
|
||||||
title: '确定解绑吗?',
|
|
||||||
onConfirm: handleUnBind,
|
|
||||||
}"
|
|
||||||
>批量解除</PermissionButton
|
|
||||||
>
|
|
||||||
</j-space>
|
</j-space>
|
||||||
</template>
|
</template>
|
||||||
<template #registryTime="slotProps">
|
<template #registryTime="slotProps">
|
||||||
{{
|
{{
|
||||||
slotProps.registryTime
|
slotProps.registryTime
|
||||||
? moment(slotProps.registryTime).format(
|
? moment(slotProps.registryTime).format(
|
||||||
'YYYY-MM-DD HH:mm:ss',
|
'YYYY-MM-DD HH:mm:ss',
|
||||||
)
|
)
|
||||||
: ''
|
: ''
|
||||||
}}
|
}}
|
||||||
</template>
|
</template>
|
||||||
<template #state="slotProps">
|
<template #state="slotProps">
|
||||||
<j-badge
|
<j-badge :text="slotProps.state.text" :status="statusMap.get(slotProps.state.value)" />
|
||||||
:text="slotProps.state.text"
|
|
||||||
:status="statusMap.get(slotProps.state.value)"
|
|
||||||
/>
|
|
||||||
</template>
|
</template>
|
||||||
<template #action="slotProps">
|
<template #action="slotProps">
|
||||||
<j-space :size="16">
|
<j-space :size="16">
|
||||||
<template
|
<template v-for="i in getActions(slotProps, 'table')" :key="i.key">
|
||||||
v-for="i in getActions(slotProps, 'table')"
|
<PermissionButton v-if="i.key !== 'update' || detail.accessProvider === 'official-edge-gateway'"
|
||||||
:key="i.key"
|
:disabled="i.disabled" :popConfirm="i.popConfirm" :tooltip="{
|
||||||
>
|
|
||||||
<PermissionButton
|
|
||||||
v-if="i.key !== 'update' || detail.accessProvider === 'official-edge-gateway'"
|
|
||||||
:disabled="i.disabled"
|
|
||||||
:popConfirm="i.popConfirm"
|
|
||||||
:tooltip="{
|
|
||||||
...i.tooltip,
|
...i.tooltip,
|
||||||
}"
|
}" @click="i.onClick" type="link" style="padding: 0px"
|
||||||
@click="i.onClick"
|
:hasPermission="'device/Instance:' + i.key">
|
||||||
type="link"
|
<template #icon>
|
||||||
style="padding: 0px"
|
<AIcon :type="i.icon" />
|
||||||
:hasPermission="'device/Instance:' + i.key"
|
</template>
|
||||||
>
|
|
||||||
<template #icon><AIcon :type="i.icon" /></template>
|
|
||||||
</PermissionButton>
|
</PermissionButton>
|
||||||
</template>
|
</template>
|
||||||
</j-space>
|
</j-space>
|
||||||
|
@ -113,7 +67,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 , deleteDeviceMapping} 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,10 +195,12 @@ const getActions = (data: Partial<Record<string, any>>): ActionsType[] => {
|
||||||
data.id,
|
data.id,
|
||||||
{},
|
{},
|
||||||
);
|
);
|
||||||
const res = await deleteDeviceMapping(
|
if (instanceStore.current.accessProvider === 'official-edge-gateway') {
|
||||||
detail.value.id,
|
const res = await deleteDeviceMapping(
|
||||||
{ids:[data.id]}
|
detail.value.id,
|
||||||
)
|
{ ids: [data.id] }
|
||||||
|
)
|
||||||
|
}
|
||||||
if (resp.status === 200) {
|
if (resp.status === 200) {
|
||||||
childDeviceRef.value?.reload();
|
childDeviceRef.value?.reload();
|
||||||
onlyMessage('操作成功!');
|
onlyMessage('操作成功!');
|
||||||
|
@ -285,11 +241,13 @@ const handleUnBind = async () => {
|
||||||
detail.value.id,
|
detail.value.id,
|
||||||
_selectedRowKeys.value,
|
_selectedRowKeys.value,
|
||||||
);
|
);
|
||||||
if (resp.status === 200) {
|
if (instanceStore.current.accessProvider === 'official-edge-gateway') {
|
||||||
const res = await deleteDeviceMapping(
|
const res = await deleteDeviceMapping(
|
||||||
detail.value.id,
|
detail.value.id,
|
||||||
{ids:[_selectedRowKeys.value]}
|
{ ids: [_selectedRowKeys.value] }
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
if (resp.status === 200) {
|
||||||
onlyMessage('操作成功!');
|
onlyMessage('操作成功!');
|
||||||
cancelSelect();
|
cancelSelect();
|
||||||
childDeviceRef.value?.reload();
|
childDeviceRef.value?.reload();
|
||||||
|
@ -316,7 +274,7 @@ const closeBindDevice = (val: boolean) => {
|
||||||
const closeChildSave = () => {
|
const closeChildSave = () => {
|
||||||
childVisible.value = false;
|
childVisible.value = false;
|
||||||
};
|
};
|
||||||
onMounted(()=>{
|
onMounted(() => {
|
||||||
console.log(detail.value.accessProvider)
|
console.log(detail.value.accessProvider)
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -1380,7 +1380,7 @@ const Status = defineComponent({
|
||||||
>
|
>
|
||||||
设备接入配置
|
设备接入配置
|
||||||
</Button>
|
</Button>
|
||||||
中${urlMap.get(unref(device)?.accessProvider) || ''}信息,任意上报一条数据
|
中{urlMap.get(unref(device)?.accessProvider) || ''}信息,任意上报一条数据
|
||||||
</span>
|
</span>
|
||||||
}
|
}
|
||||||
/>,
|
/>,
|
||||||
|
@ -1391,7 +1391,7 @@ const Status = defineComponent({
|
||||||
status="default"
|
status="default"
|
||||||
text={
|
text={
|
||||||
<span>
|
<span>
|
||||||
请联系管理员提供${urlMap.get(unref(device)?.accessProvider) || ''}
|
请联系管理员提供{urlMap.get(unref(device)?.accessProvider) || ''}
|
||||||
信息,并根据URL信息任意上报一条数据
|
信息,并根据URL信息任意上报一条数据
|
||||||
</span>
|
</span>
|
||||||
}
|
}
|
||||||
|
|
|
@ -197,7 +197,7 @@ const handleExecute = async (func: any) => {
|
||||||
.then(async () => {
|
.then(async () => {
|
||||||
const obj = {};
|
const obj = {};
|
||||||
func.table.forEach((item: any) => {
|
func.table.forEach((item: any) => {
|
||||||
if (item.type === 'object') {
|
if (item.type === 'object' && item.value) {
|
||||||
obj[item.id] = JSON.parse(item.value);
|
obj[item.id] = JSON.parse(item.value);
|
||||||
} else {
|
} else {
|
||||||
obj[item.id] = item.value;
|
obj[item.id] = item.value;
|
||||||
|
|
|
@ -185,7 +185,8 @@ const getOptions = (arr: any[]) => {
|
||||||
tooltip: {
|
tooltip: {
|
||||||
trigger: 'axis',
|
trigger: 'axis',
|
||||||
position: function (pt: any) {
|
position: function (pt: any) {
|
||||||
return [pt[0], '10%'];
|
const left = pt[0] - 80
|
||||||
|
return [left, '10%'];
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
series: [
|
series: [
|
||||||
|
|
|
@ -155,7 +155,7 @@ const handleOk = () => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
btnLoading.value = true;
|
btnLoading.value = true;
|
||||||
bindDevice(_selectedRowKeys.value[0], props.data.id, )
|
bindDevice(_selectedRowKeys.value[0], [props.data.id] )
|
||||||
.then((resp) => {
|
.then((resp) => {
|
||||||
if(resp.status === 200){
|
if(resp.status === 200){
|
||||||
emit('ok', _selectedRowKeys.value[0]);
|
emit('ok', _selectedRowKeys.value[0]);
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
</j-space>
|
</j-space>
|
||||||
</template>
|
</template>
|
||||||
<j-form ref="formRef" :model="modelRef">
|
<j-form ref="formRef" :model="modelRef">
|
||||||
<j-table :dataSource="modelRef.dataSource" :columns="columns">
|
<j-table :columns="columns" :dataSource="modelRef.dataSource" @change="tableChange">
|
||||||
<template #headerCell="{ column }">
|
<template #headerCell="{ column }">
|
||||||
<template v-if="column.key === 'collectorId'">
|
<template v-if="column.key === 'collectorId'">
|
||||||
采集器
|
采集器
|
||||||
|
@ -20,13 +20,14 @@
|
||||||
<template #bodyCell="{ column, record, index }">
|
<template #bodyCell="{ column, record, index }">
|
||||||
<template v-if="column.dataIndex === 'channelId'">
|
<template v-if="column.dataIndex === 'channelId'">
|
||||||
<j-form-item
|
<j-form-item
|
||||||
:name="['dataSource', index, 'channelId']"
|
:name="['dataSource', myCurrent * 10 + index, 'channelId']"
|
||||||
>
|
>
|
||||||
<j-select
|
<j-select
|
||||||
style="width: 100%"
|
style="width: 100%"
|
||||||
v-model:value="record[column.dataIndex]"
|
v-model:value="record[column.dataIndex]"
|
||||||
placeholder="请选择"
|
placeholder="请选择"
|
||||||
allowClear
|
allowClear
|
||||||
|
show-search
|
||||||
:filter-option="filterOption"
|
:filter-option="filterOption"
|
||||||
:options="channelList"
|
:options="channelList"
|
||||||
@select="(_, option) => { record.provider = option.provider }"
|
@select="(_, option) => { record.provider = option.provider }"
|
||||||
|
@ -36,7 +37,7 @@
|
||||||
</template>
|
</template>
|
||||||
<template v-if="column.dataIndex === 'collectorId'">
|
<template v-if="column.dataIndex === 'collectorId'">
|
||||||
<j-form-item
|
<j-form-item
|
||||||
:name="['dataSource', index, 'collectorId']"
|
:name="['dataSource', myCurrent * 10 + index, 'collectorId']"
|
||||||
:rules="[
|
:rules="[
|
||||||
{
|
{
|
||||||
required: !!record.channelId,
|
required: !!record.channelId,
|
||||||
|
@ -53,7 +54,7 @@
|
||||||
</template>
|
</template>
|
||||||
<template v-if="column.dataIndex === 'pointId'">
|
<template v-if="column.dataIndex === 'pointId'">
|
||||||
<j-form-item
|
<j-form-item
|
||||||
:name="['dataSource', index, 'pointId']"
|
:name="['dataSource', myCurrent * 10 + index, 'pointId']"
|
||||||
:rules="[
|
:rules="[
|
||||||
{
|
{
|
||||||
required: !!record.channelId,
|
required: !!record.channelId,
|
||||||
|
@ -157,6 +158,8 @@ const columns = [
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const myCurrent = ref(0)
|
||||||
|
|
||||||
const filterOption = (input: string, option: any) => {
|
const filterOption = (input: string, option: any) => {
|
||||||
return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0;
|
return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0;
|
||||||
};
|
};
|
||||||
|
@ -235,6 +238,10 @@ const handleSearch = async () => {
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const tableChange = (pagination: { current: number }) => {
|
||||||
|
myCurrent.value = pagination.current - 1
|
||||||
|
}
|
||||||
|
|
||||||
const unbind = async (id: string) => {
|
const unbind = async (id: string) => {
|
||||||
if (id) {
|
if (id) {
|
||||||
const resp = await removeMapping('device', instanceStore.current.id, [
|
const resp = await removeMapping('device', instanceStore.current.id, [
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
<template>
|
<template>
|
||||||
<j-select allowClear v-model:value="_value" @change="onChange" placeholder="请选择" style="width: 100%">
|
<j-select allowClear v-model:value="_value" @change="onChange" placeholder="请选择" style="width: 100%" show-search :filter-option="filterOption">
|
||||||
<j-select-option
|
<j-select-option
|
||||||
v-for="item in list"
|
v-for="item in list"
|
||||||
:key="item.id"
|
:key="item.id"
|
||||||
:value="item.id"
|
:value="item.id"
|
||||||
:label="item.name"
|
:label="item.name"
|
||||||
:filter-option="filterOption"
|
|
||||||
>{{ item.name }}</j-select-option
|
>{{ item.name }}</j-select-option
|
||||||
>
|
>
|
||||||
</j-select>
|
</j-select>
|
||||||
|
|
|
@ -243,11 +243,11 @@ const columns = [
|
||||||
options: [
|
options: [
|
||||||
{
|
{
|
||||||
label: '正常',
|
label: '正常',
|
||||||
value: 'started',
|
value: 'enabled',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '禁用',
|
label: '禁用',
|
||||||
value: 'disable',
|
value: 'disabled',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
|
@ -313,8 +313,9 @@ const submitData = () => {
|
||||||
if (form.id === '') {
|
if (form.id === '') {
|
||||||
form.id = undefined;
|
form.id = undefined;
|
||||||
}
|
}
|
||||||
const res = await addProduct(form);
|
const res = await addProduct(form).finally(()=>{
|
||||||
loading.value = false
|
loading.value = false
|
||||||
|
});
|
||||||
if (res.status === 200) {
|
if (res.status === 200) {
|
||||||
onlyMessage('保存成功!');
|
onlyMessage('保存成功!');
|
||||||
visible.value = false;
|
visible.value = false;
|
||||||
|
|
|
@ -389,8 +389,7 @@ const beforeUpload = (file: any) => {
|
||||||
reader.readAsText(file);
|
reader.readAsText(file);
|
||||||
reader.onload = async (result) => {
|
reader.onload = async (result) => {
|
||||||
const text = result.target?.result;
|
const text = result.target?.result;
|
||||||
// console.log('text: ', text);
|
console.log(text);
|
||||||
// console.log(file);
|
|
||||||
if (!file.type.includes('json')) {
|
if (!file.type.includes('json')) {
|
||||||
onlyMessage('请上传json格式文件', 'error');
|
onlyMessage('请上传json格式文件', 'error');
|
||||||
return false;
|
return false;
|
||||||
|
@ -410,6 +409,10 @@ const beforeUpload = (file: any) => {
|
||||||
if(!data?.name){
|
if(!data?.name){
|
||||||
data.name = "产品" + Date.now();
|
data.name = "产品" + Date.now();
|
||||||
}
|
}
|
||||||
|
if(!data?.deviceType || JSON.stringify(data?.deviceType) === '{}' ){
|
||||||
|
onlyMessage('缺少deviceType字段或对应的值','error')
|
||||||
|
return false
|
||||||
|
}
|
||||||
const res = await updateDevice(data);
|
const res = await updateDevice(data);
|
||||||
if (res.status === 200) {
|
if (res.status === 200) {
|
||||||
onlyMessage('操作成功');
|
onlyMessage('操作成功');
|
||||||
|
|
|
@ -61,19 +61,17 @@
|
||||||
title="继承自产品物模型的数据不支持修改"
|
title="继承自产品物模型的数据不支持修改"
|
||||||
>
|
>
|
||||||
<!-- <ModelButton :disabled="true"/>-->
|
<!-- <ModelButton :disabled="true"/>-->
|
||||||
<j-button :disabled="true" type="link" style="padding-left: 0;">
|
<j-button :disabled="true" type="link" >
|
||||||
<AIcon type="SettingOutlined" />
|
<AIcon type="SettingOutlined" />
|
||||||
配置
|
配置
|
||||||
</j-button>
|
</j-button>
|
||||||
|
|
||||||
</j-tooltip>
|
</j-tooltip>
|
||||||
<PermissionButton
|
<InputParams
|
||||||
v-else
|
v-else
|
||||||
:has-permission="`${permission}:update`"
|
v-model:value="data.record.inputs"
|
||||||
type="link"
|
:has-permission="`${permission}:update`"
|
||||||
key="inputs"
|
/>
|
||||||
>
|
|
||||||
<InputParams v-model:value="data.record.inputs" />
|
|
||||||
</PermissionButton>
|
|
||||||
</template>
|
</template>
|
||||||
<template #output="{ data }">
|
<template #output="{ data }">
|
||||||
{{ data.record.output?.type }}
|
{{ data.record.output?.type }}
|
||||||
|
@ -93,19 +91,16 @@
|
||||||
title="继承自产品物模型的数据不支持修改"
|
title="继承自产品物模型的数据不支持修改"
|
||||||
>
|
>
|
||||||
<!-- <ModelButton :disabled="true"/>-->
|
<!-- <ModelButton :disabled="true"/>-->
|
||||||
<j-button :disabled="true" type="link" style="padding-left: 0;">
|
<j-button :disabled="true" type="link">
|
||||||
<AIcon type="SettingOutlined" />
|
<AIcon type="SettingOutlined" />
|
||||||
配置
|
配置
|
||||||
</j-button>
|
</j-button>
|
||||||
</j-tooltip>
|
</j-tooltip>
|
||||||
<PermissionButton
|
<ConfigParams
|
||||||
v-else
|
v-else
|
||||||
:has-permission="`${permission}:update`"
|
v-model:value="data.record.valueType"
|
||||||
type="link"
|
:has-permission="`${permission}:update`"
|
||||||
key="properties"
|
/>
|
||||||
>
|
|
||||||
<ConfigParams v-model:value="data.record.valueType" />
|
|
||||||
</PermissionButton>
|
|
||||||
</template>
|
</template>
|
||||||
<template #outInput>
|
<template #outInput>
|
||||||
object
|
object
|
||||||
|
@ -116,33 +111,27 @@
|
||||||
</j-tag>
|
</j-tag>
|
||||||
</template>
|
</template>
|
||||||
<template #other="{ data }">
|
<template #other="{ data }">
|
||||||
<j-tooltip
|
<!-- <j-tooltip
|
||||||
v-if="target === 'device' && productNoEdit.id?.includes?.(data.record.id)"
|
v-if="target === 'device' && productNoEdit.id?.includes?.(data.record.id)"
|
||||||
title="继承自产品物模型的数据不支持修改"
|
title="继承自产品物模型的数据不支持修改"
|
||||||
>
|
> -->
|
||||||
<!-- <ModelButton :disabled="true"/>-->
|
<!-- <ModelButton :disabled="true"/>-->
|
||||||
<j-button :disabled="true" type="link" style="padding-left: 0;">
|
<!-- <j-button :disabled="true" type="link" style="padding-left: 0;">
|
||||||
<AIcon type="SettingOutlined" />
|
<AIcon type="SettingOutlined" />
|
||||||
配置
|
配置
|
||||||
</j-button>
|
</j-button> -->
|
||||||
</j-tooltip>
|
<!-- </j-tooltip> -->
|
||||||
<PermissionButton
|
<OtherSetting
|
||||||
v-else
|
|
||||||
:has-permission="`${permission}:update`"
|
|
||||||
type="link"
|
|
||||||
key="setting"
|
|
||||||
>
|
|
||||||
<OtherSetting
|
|
||||||
v-model:value="data.record.expands"
|
v-model:value="data.record.expands"
|
||||||
:id="data.record.id"
|
:id="data.record.id"
|
||||||
:disabled="target === 'device' && productNoEdit.id?.includes?.(data.record.id)"
|
:disabled="target === 'device' && productNoEdit.id?.includes?.(data.record.id)"
|
||||||
:record="data.record"
|
:record="data.record"
|
||||||
|
:type="data.record.valueType.type"
|
||||||
|
:has-permission="`${permission}:update`"
|
||||||
:tooltip="target === 'device' && productNoEdit.id?.includes?.(data.record.id) ? {
|
:tooltip="target === 'device' && productNoEdit.id?.includes?.(data.record.id) ? {
|
||||||
title: '继承自产品物模型的数据不支持删除',
|
title: '继承自产品物模型的数据不支持删除',
|
||||||
} : undefined"
|
} : undefined"
|
||||||
:type="data.record.valueType.type"
|
|
||||||
/>
|
/>
|
||||||
</PermissionButton>
|
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
<template #action="{data}">
|
<template #action="{data}">
|
||||||
|
|
|
@ -6,10 +6,9 @@ import { EventLevel } from "@/views/device/data";
|
||||||
import {MetadataType} from "@/views/device/Product/typings";
|
import {MetadataType} from "@/views/device/Product/typings";
|
||||||
import { getUnit } from '@/api/device/instance';
|
import { getUnit } from '@/api/device/instance';
|
||||||
import {Ref} from "vue";
|
import {Ref} from "vue";
|
||||||
import {omit, pick} from "lodash-es";
|
import {omit, pick, isObject, cloneDeep} from "lodash-es";
|
||||||
import { message } from 'jetlinks-ui-components'
|
import { message } from 'jetlinks-ui-components'
|
||||||
import { onlyMessage } from "@/utils/comm";
|
import { onlyMessage } from "@/utils/comm";
|
||||||
import {cloneDeep} from "lodash";
|
|
||||||
interface DataTableColumnProps extends ColumnProps {
|
interface DataTableColumnProps extends ColumnProps {
|
||||||
type?: string,
|
type?: string,
|
||||||
components?: {
|
components?: {
|
||||||
|
@ -37,9 +36,7 @@ const type = {
|
||||||
report: '上报',
|
report: '上报',
|
||||||
};
|
};
|
||||||
|
|
||||||
export const validatorConfig = (value: any, isObject: boolean = false) => {
|
export const validatorConfig = (value: any, _isObject: boolean = false) => {
|
||||||
|
|
||||||
console.log(value)
|
|
||||||
|
|
||||||
if (!value) {
|
if (!value) {
|
||||||
return Promise.resolve()
|
return Promise.resolve()
|
||||||
|
@ -52,11 +49,11 @@ export const validatorConfig = (value: any, isObject: boolean = false) => {
|
||||||
return Promise.reject('请选择元素类型')
|
return Promise.reject('请选择元素类型')
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isObject && value.type === 'object' && !value.properties?.length) {
|
if (_isObject && value.type === 'object' && !value.properties?.length) {
|
||||||
return Promise.reject('请添加参数')
|
return Promise.reject('请添加参数')
|
||||||
}
|
}
|
||||||
|
|
||||||
if (value.type === 'file' && (!value.fileType || !Object.keys(value.fileType).length)) {
|
if (value.type === 'file' && (!value.fileType || (isObject(value.fileType) && !Object.keys(value.fileType).length))) {
|
||||||
return Promise.reject('请选择文件类型')
|
return Promise.reject('请选择文件类型')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,6 @@
|
||||||
{{ TypeStringMap[data.record.valueType?.type] }}
|
{{ TypeStringMap[data.record.valueType?.type] }}
|
||||||
</template>
|
</template>
|
||||||
<template #config="{ data }">
|
<template #config="{ data }">
|
||||||
<!-- <OtherConfigInfo :value="data.record.valueType"></OtherConfigInfo>-->
|
|
||||||
<ConfigModal v-model:value="data.record.valueType" :showOther="false" />
|
<ConfigModal v-model:value="data.record.valueType" :showOther="false" />
|
||||||
</template>
|
</template>
|
||||||
</DataTableObject>
|
</DataTableObject>
|
||||||
|
@ -54,7 +53,7 @@
|
||||||
|
|
||||||
<script setup lang="ts" name="MetadataDataType">
|
<script setup lang="ts" name="MetadataDataType">
|
||||||
import { getUnit } from '@/api/device/instance';
|
import { getUnit } from '@/api/device/instance';
|
||||||
import { ValueObject } from '../components'
|
import {DataType, ValueObject} from '../components'
|
||||||
import {
|
import {
|
||||||
DataTableTypeSelect,
|
DataTableTypeSelect,
|
||||||
DataTableArray,
|
DataTableArray,
|
||||||
|
@ -68,7 +67,7 @@ import {
|
||||||
DataTableObject,
|
DataTableObject,
|
||||||
} from 'jetlinks-ui-components';
|
} from 'jetlinks-ui-components';
|
||||||
import { cloneDeep } from 'lodash-es';
|
import { cloneDeep } from 'lodash-es';
|
||||||
import {handleTypeValue, typeSelectChange, TypeStringMap, useUnit} from '../columns'
|
import {handleTypeValue, typeSelectChange, TypeStringMap, useUnit, validatorConfig} from '../columns'
|
||||||
import ConfigModal from './ConfigModal.vue'
|
import ConfigModal from './ConfigModal.vue'
|
||||||
import { Form } from 'jetlinks-ui-components'
|
import { Form } from 'jetlinks-ui-components'
|
||||||
|
|
||||||
|
@ -137,7 +136,6 @@ const columns = [{
|
||||||
required: true,
|
required: true,
|
||||||
rules: [{
|
rules: [{
|
||||||
validator(_: any, value: any) {
|
validator(_: any, value: any) {
|
||||||
console.log('validator',value)
|
|
||||||
if (!value?.type) {
|
if (!value?.type) {
|
||||||
return Promise.reject('请选择数据类型')
|
return Promise.reject('请选择数据类型')
|
||||||
}
|
}
|
||||||
|
@ -150,7 +148,23 @@ const columns = [{
|
||||||
{
|
{
|
||||||
title: '其他配置',
|
title: '其他配置',
|
||||||
dataIndex: 'config',
|
dataIndex: 'config',
|
||||||
width: 100
|
width: 100,
|
||||||
|
// components: {
|
||||||
|
// name: ConfigModal,
|
||||||
|
// props: {
|
||||||
|
// showOther: false
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
form: {
|
||||||
|
rules: [{
|
||||||
|
callback(rule: any, value: any, dataSource: any[]) {
|
||||||
|
const field = rule.field.split('.')
|
||||||
|
const fieldIndex = Number(field[1])
|
||||||
|
const values = dataSource.find((item, index) => index === fieldIndex)
|
||||||
|
return validatorConfig(values?.valueType)
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '操作',
|
title: '操作',
|
||||||
|
|
|
@ -6,7 +6,15 @@
|
||||||
<template #config="{ data }">
|
<template #config="{ data }">
|
||||||
<ConfigModal v-model:value="data.record.valueType" :showOther="false" />
|
<ConfigModal v-model:value="data.record.valueType" :showOther="false" />
|
||||||
</template>
|
</template>
|
||||||
<ModelButton />
|
<PermissionButton
|
||||||
|
key="properties"
|
||||||
|
:has-permission="hasPermission"
|
||||||
|
style="padding-left: 0;"
|
||||||
|
type="link"
|
||||||
|
>
|
||||||
|
<AIcon type="SettingOutlined" />
|
||||||
|
配置
|
||||||
|
</PermissionButton>
|
||||||
</DataTableObject>
|
</DataTableObject>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -139,6 +147,7 @@ const props = defineProps({
|
||||||
type: Array as PropType<{ label: string; value: string }[]>,
|
type: Array as PropType<{ label: string; value: string }[]>,
|
||||||
default: () => [],
|
default: () => [],
|
||||||
},
|
},
|
||||||
|
hasPermission: String,
|
||||||
});
|
});
|
||||||
|
|
||||||
const value = ref(props.value.properties);
|
const value = ref(props.value.properties);
|
||||||
|
|
|
@ -9,7 +9,14 @@
|
||||||
<template #config="{ data }">
|
<template #config="{ data }">
|
||||||
<ConfigModal v-model:value="data.record.valueType" :showOther="false" />
|
<ConfigModal v-model:value="data.record.valueType" :showOther="false" />
|
||||||
</template>
|
</template>
|
||||||
<ModelButton />
|
<PermissionButton
|
||||||
|
key="properties"
|
||||||
|
:has-permission="hasPermission"
|
||||||
|
type="link"
|
||||||
|
>
|
||||||
|
<AIcon type="SettingOutlined" />
|
||||||
|
配置
|
||||||
|
</PermissionButton>
|
||||||
</DataTableObject>
|
</DataTableObject>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -43,6 +50,7 @@ const props = defineProps({
|
||||||
type: Array as PropType<{ label: string; value: string }[]>,
|
type: Array as PropType<{ label: string; value: string }[]>,
|
||||||
default: () => [],
|
default: () => [],
|
||||||
},
|
},
|
||||||
|
hasPermission: String,
|
||||||
});
|
});
|
||||||
const formItemContext = Form.useInjectFormItemContext();
|
const formItemContext = Form.useInjectFormItemContext();
|
||||||
|
|
||||||
|
|
|
@ -55,15 +55,15 @@
|
||||||
import { getUnit } from '@/api/device/instance';
|
import { getUnit } from '@/api/device/instance';
|
||||||
import {
|
import {
|
||||||
DataTableTypeSelect,
|
DataTableTypeSelect,
|
||||||
DataTableArray,
|
DataTableArray,
|
||||||
DataTableString,
|
DataTableString,
|
||||||
DataTableInteger,
|
DataTableInteger,
|
||||||
DataTableDouble,
|
DataTableDouble,
|
||||||
DataTableBoolean,
|
DataTableBoolean,
|
||||||
DataTableEnum,
|
DataTableEnum,
|
||||||
DataTableFile,
|
DataTableFile,
|
||||||
DataTableDate,
|
DataTableDate,
|
||||||
DataTableObject,
|
DataTableObject, Form,
|
||||||
} from 'jetlinks-ui-components';
|
} from 'jetlinks-ui-components';
|
||||||
|
|
||||||
import ConfigModal from '@/views/device/components/Metadata/Base/components/ConfigModal.vue'
|
import ConfigModal from '@/views/device/components/Metadata/Base/components/ConfigModal.vue'
|
||||||
|
@ -83,7 +83,7 @@ const props = defineProps({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const formItemContext = Form.useInjectFormItemContext();
|
||||||
const options = ref<{ label: string; value: string }[]>([]);
|
const options = ref<{ label: string; value: string }[]>([]);
|
||||||
const emit = defineEmits(['update:value']);
|
const emit = defineEmits(['update:value']);
|
||||||
|
|
||||||
|
@ -235,6 +235,7 @@ const valueChange = () => {
|
||||||
...props.value,
|
...props.value,
|
||||||
output: {...data.value, type: type.value},
|
output: {...data.value, type: type.value},
|
||||||
});
|
});
|
||||||
|
formItemContext.onFieldChange()
|
||||||
}
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -120,7 +120,7 @@ const validator = (_: any, value: any) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const typeValidator = (_: any, value: any) => {
|
const typeValidator = (_: any, value: any) => {
|
||||||
if (value === undefined) {
|
if (value === undefined || value === null) {
|
||||||
return Promise.reject(validatorTip())
|
return Promise.reject(validatorTip())
|
||||||
}
|
}
|
||||||
if (type === 'string' && value?.length > 64) {
|
if (type === 'string' && value?.length > 64) {
|
||||||
|
@ -146,7 +146,7 @@ const handleValueByType = (value: any, isRange: boolean = false) => {
|
||||||
|
|
||||||
const confirm = () => {
|
const confirm = () => {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
formRef.value.validate().then(() => {
|
formRef.value.validate().then((res) => {
|
||||||
let value = props.value.range === true ? formData.rangeValue : formData.value
|
let value = props.value.range === true ? formData.rangeValue : formData.value
|
||||||
|
|
||||||
if (['int', 'long'].includes(type)) {
|
if (['int', 'long'].includes(type)) {
|
||||||
|
|
|
@ -51,8 +51,17 @@
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
<PermissionButton
|
||||||
<ModelButton :disabled="disabled"/>
|
key="setting"
|
||||||
|
:disabled="disabled"
|
||||||
|
:has-permission="hasPermission"
|
||||||
|
:tooltip="tooltip"
|
||||||
|
style="padding-left: 0;"
|
||||||
|
type="link"
|
||||||
|
>
|
||||||
|
<AIcon type="SettingOutlined" />
|
||||||
|
配置
|
||||||
|
</PermissionButton>
|
||||||
</j-popconfirm-modal>
|
</j-popconfirm-modal>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -88,6 +97,8 @@ const props = defineProps({
|
||||||
type: Object,
|
type: Object,
|
||||||
default: () => ({})
|
default: () => ({})
|
||||||
},
|
},
|
||||||
|
hasPermission: String,
|
||||||
|
tooltip: Object
|
||||||
})
|
})
|
||||||
|
|
||||||
const fullRef = inject(FULL_CODE);
|
const fullRef = inject(FULL_CODE);
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
v-if="myValue != 'manual' && !showReset"
|
v-if="myValue != 'manual' && !showReset"
|
||||||
:bodyStyle="{
|
:bodyStyle="{
|
||||||
width: '450px',
|
width: '450px',
|
||||||
height: myValue === 'rule' ? '300px' : '80px',
|
height: myValue === 'rule' ? '300px' : '90px',
|
||||||
}"
|
}"
|
||||||
:get-popup-container="(node) => fullRef || node"
|
:get-popup-container="(node) => fullRef || node"
|
||||||
placement="bottomRight"
|
placement="bottomRight"
|
||||||
|
@ -294,7 +294,9 @@ onMounted(()=>{
|
||||||
item === props.value?.id ? showReset.value = true : ''
|
item === props.value?.id ? showReset.value = true : ''
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
handleSearch()
|
if(isNoCommunity && myValue.value === 'rule'){
|
||||||
|
handleSearch()
|
||||||
|
}
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -112,7 +112,7 @@ const codecs = ref<{ id: string; name: string }[]>()
|
||||||
const routeChange = async (id: string) => {
|
const routeChange = async (id: string) => {
|
||||||
const res = await getCodecs()
|
const res = await getCodecs()
|
||||||
if (res.status === 200) {
|
if (res.status === 200) {
|
||||||
codecs.value = [{ id: 'jetlinks', name: 'jetlinks' }].concat(res.result)
|
codecs.value = [{ id: 'jetlinks', name: '标准物模型' }].concat(res.result)
|
||||||
}
|
}
|
||||||
if (props.type === 'device' && id) {
|
if (props.type === 'device' && id) {
|
||||||
detail(id as string).then((resp) => {
|
detail(id as string).then((resp) => {
|
||||||
|
|
|
@ -158,7 +158,7 @@
|
||||||
<template #label>
|
<template #label>
|
||||||
<j-space>
|
<j-space>
|
||||||
物模型
|
物模型
|
||||||
<j-tooltip title="在线编辑器中编写物模型脚本">
|
<j-tooltip title="在编辑器中编写物模型脚本">
|
||||||
<AIcon
|
<AIcon
|
||||||
type="QuestionCircleOutlined"
|
type="QuestionCircleOutlined"
|
||||||
style="color: rgb(136, 136, 136)"
|
style="color: rgb(136, 136, 136)"
|
||||||
|
@ -637,7 +637,7 @@ const handleImport = async () => {
|
||||||
data[data?.type === 'copy' ? 'copy' : 'import'] ||
|
data[data?.type === 'copy' ? 'copy' : 'import'] ||
|
||||||
'{}',
|
'{}',
|
||||||
);
|
);
|
||||||
if(data?.type === 'import'){
|
if(data?.type !== 'copy'){
|
||||||
Object.keys(_object).forEach((i:any)=>{
|
Object.keys(_object).forEach((i:any)=>{
|
||||||
const map = new Map()
|
const map = new Map()
|
||||||
_object[i].forEach((item:any)=>(
|
_object[i].forEach((item:any)=>(
|
||||||
|
|
|
@ -20,19 +20,34 @@ 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;
|
||||||
if (res.status === 200) {
|
if (res.status === 200) {
|
||||||
if (res.result.page.routeType === 'hash') {
|
const result = res.result
|
||||||
menuUrl = `${url}`;
|
if (result.page.routeType === 'hash') {
|
||||||
|
menuUrl = url.startsWith('/') ? `#${url}` : `#/${url}`;
|
||||||
}
|
}
|
||||||
if (res.result.provider === 'internal-standalone') {
|
|
||||||
const urlStandalone = `${res.result.page.baseUrl}/api/application/sso/${appId}/login?redirect=${menuUrl}?layout=false`;
|
if (result.page.parameters) {
|
||||||
|
const params = new URLSearchParams()
|
||||||
|
result.page.parameters.forEach((item: any) => {
|
||||||
|
if (item?.key) {
|
||||||
|
params.set(item.key,item.value)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
const urlParams = params.toString()
|
||||||
|
if (urlParams) {
|
||||||
|
menuUrl += `?${urlParams}`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.provider === 'internal-standalone') {
|
||||||
|
const urlStandalone = `${result.page.baseUrl}/api/application/sso/${appId}/login?redirect=${menuUrl}?layout=false`;
|
||||||
iframeUrl.value = urlStandalone;
|
iframeUrl.value = urlStandalone;
|
||||||
} else if (res.result.provider === 'internal-integrated') {
|
} else if (result.provider === 'internal-integrated') {
|
||||||
const tokenUrl = `${
|
const tokenUrl = `${
|
||||||
res.result.page.baseUrl
|
result.page.baseUrl
|
||||||
}?X-Access-Token=${LocalStore.get(TOKEN_KEY)}`;
|
}/${menuUrl}?layout=false&X-Access-Token=${LocalStore.get(TOKEN_KEY)}`;
|
||||||
iframeUrl.value = tokenUrl;
|
iframeUrl.value = tokenUrl;
|
||||||
} else {
|
} else {
|
||||||
const urlOther = `${res.result.page.baseUrl}/${menuUrl}`;
|
const urlOther = `${result.page.baseUrl}/${menuUrl}`;
|
||||||
iframeUrl.value = urlOther;
|
iframeUrl.value = urlOther;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -145,7 +145,10 @@ const visible = ref<boolean>(false);
|
||||||
const modalForm = reactive<modalState>({
|
const modalForm = reactive<modalState>({
|
||||||
host: '0.0.0.0',
|
host: '0.0.0.0',
|
||||||
});
|
});
|
||||||
|
const regDomain = new RegExp(
|
||||||
|
// /^https?:\/\/(([a-zA-Z0-9_-])+(\.)?)*(:\d+)?(\/((\.)?(\?)?=?&?[a-zA-Z0-9_-](\?)?)*)*$/i,
|
||||||
|
/^[a-zA-Z0-9]+([\-\.]{1}[a-zA-Z0-9]+)*\.[a-zA-Z]{2,}$/
|
||||||
|
)
|
||||||
/**
|
/**
|
||||||
* 校验官网地址
|
* 校验官网地址
|
||||||
*/
|
*/
|
||||||
|
@ -153,7 +156,7 @@ const validateUrl = async (_rule: Rule, value: string) => {
|
||||||
if (!value) {
|
if (!value) {
|
||||||
return Promise.reject('请输入公网地址');
|
return Promise.reject('请输入公网地址');
|
||||||
} else {
|
} else {
|
||||||
if (!testIpv4_6(value)) {
|
if (!testIpv4_6(value) && !regDomain.test(value)) {
|
||||||
return Promise.reject('请输入正确的公网地址');
|
return Promise.reject('请输入正确的公网地址');
|
||||||
}
|
}
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
|
|
|
@ -4,91 +4,56 @@
|
||||||
<j-card>
|
<j-card>
|
||||||
<j-row :gutter="[24, 24]" style="padding: 24px">
|
<j-row :gutter="[24, 24]" style="padding: 24px">
|
||||||
<j-col :span="12">
|
<j-col :span="12">
|
||||||
<j-form
|
<j-form class="form" layout="vertical" :model="formData" name="basic" :label-col="{ span: 8 }"
|
||||||
class="form"
|
:wrapper-col="{ span: 24 }" autocomplete="off" ref="formRef">
|
||||||
layout="vertical"
|
<j-form-item label="证书标准" name="type"
|
||||||
:model="formData"
|
:rules="[{ required: true, message: '请选择证书标准', trigger: 'blur' }]">
|
||||||
name="basic"
|
|
||||||
:label-col="{ span: 8 }"
|
|
||||||
:wrapper-col="{ span: 24 }"
|
|
||||||
autocomplete="off"
|
|
||||||
>
|
|
||||||
<j-form-item
|
|
||||||
label="证书标准"
|
|
||||||
v-bind="validateInfos.type"
|
|
||||||
>
|
|
||||||
<j-radio-group v-model:value="formData.type">
|
<j-radio-group v-model:value="formData.type">
|
||||||
<j-radio-button
|
<j-radio-button class="form-radio-button" value="common">
|
||||||
class="form-radio-button"
|
<img :src="getImage('/certificate.png')" />
|
||||||
value="common"
|
|
||||||
>
|
|
||||||
<img
|
|
||||||
:src="getImage('/certificate.png')"
|
|
||||||
/>
|
|
||||||
</j-radio-button>
|
</j-radio-button>
|
||||||
</j-radio-group>
|
</j-radio-group>
|
||||||
</j-form-item>
|
</j-form-item>
|
||||||
<j-form-item
|
<j-form-item label="证书名称" name="name" :rules="[
|
||||||
label="证书名称"
|
{ required: true, message: '请输入证书名称', trigger: 'blur' },
|
||||||
v-bind="validateInfos.name"
|
{ max: 64, message: '最多可输入64个字符' },
|
||||||
>
|
]">
|
||||||
<j-input
|
<j-input placeholder="请输入证书名称" v-model:value="formData.name" />
|
||||||
placeholder="请输入证书名称"
|
|
||||||
v-model:value="formData.name"
|
|
||||||
/>
|
|
||||||
</j-form-item>
|
</j-form-item>
|
||||||
<j-form-item
|
<j-form-item label="证书文件" :name="['configs','cert']" :rules="[
|
||||||
label="证书文件"
|
{ required: true, message: '请输入或上传文件', trigger: 'blur' },
|
||||||
v-bind="validateInfos['configs.cert']"
|
]">
|
||||||
>
|
<CertificateFile name="cert" v-model:modelValue="formData.configs.cert"
|
||||||
<CertificateFile
|
placeholder="请输入证书文件" />
|
||||||
name="cert"
|
|
||||||
v-model:modelValue="formData.configs.cert"
|
|
||||||
placeholder="请输入证书文件"
|
|
||||||
/>
|
|
||||||
</j-form-item>
|
</j-form-item>
|
||||||
<j-form-item label="证书类型" v-bind="validateInfos.mode">
|
<j-form-item label="证书类型" name="mode"
|
||||||
|
:rules="[{ required: true, message: '请选择证书类型', trigger: 'blur' }]">
|
||||||
<j-radio-group v-model:value="formData.mode" button-style="solid">
|
<j-radio-group v-model:value="formData.mode" button-style="solid">
|
||||||
<j-radio-button value="client" style="margin-right: 30px;" size="large">客户端</j-radio-button>
|
<j-radio-button value="client" style="margin-right: 30px;"
|
||||||
|
size="large">客户端</j-radio-button>
|
||||||
<j-radio-button value="server" size="large">服务端</j-radio-button>
|
<j-radio-button value="server" size="large">服务端</j-radio-button>
|
||||||
</j-radio-group>
|
</j-radio-group>
|
||||||
</j-form-item>
|
</j-form-item>
|
||||||
<j-form-item label="认证方式" v-if="formData.mode === 'client'" v-bind="validateInfos.authenticationMethod">
|
<!-- <j-form-item label="认证方式" v-if="formData.mode === 'client'" v-bind="validateInfos.authenticationMethod">
|
||||||
<j-radio-group button-style="solid" v-model:value="formData.authenticationMethod">
|
<j-radio-group button-style="solid" v-model:value="formData.authenticationMethod">
|
||||||
<j-radio-button value="single" style="margin-right: 30px;" size="large">单向认证</j-radio-button>
|
<j-radio-button value="single" style="margin-right: 30px;" size="large">单向认证</j-radio-button>
|
||||||
<j-radio-button value="binomial" size="large">双向认证</j-radio-button>
|
<j-radio-button value="binomial" size="large">双向认证</j-radio-button>
|
||||||
</j-radio-group>
|
</j-radio-group>
|
||||||
|
</j-form-item> -->
|
||||||
|
<j-form-item label="证书私钥" v-if="formData.mode !== 'client'" :name="['configs','key']" :rules="[
|
||||||
|
{ required: true, message: '请输入或上传文件', trigger: 'blur' },
|
||||||
|
]">
|
||||||
|
<CertificateFile name="key" v-model:modelValue="formData.configs.key"
|
||||||
|
placeholder="请输入证书私钥" />
|
||||||
</j-form-item>
|
</j-form-item>
|
||||||
<j-form-item
|
<j-form-item label="说明" name="description" :rules="[{ max: 200, message: '最多可输入200个字符' }]">
|
||||||
label="证书私钥"
|
<j-textarea placeholder="请输入说明" v-model:value="formData.description" :maxlength="200"
|
||||||
v-bind="validateInfos['configs.key']"
|
:rows="3" showCount />
|
||||||
>
|
|
||||||
<CertificateFile
|
|
||||||
name="key"
|
|
||||||
v-model:modelValue="formData.configs.key"
|
|
||||||
placeholder="请输入证书私钥"
|
|
||||||
/>
|
|
||||||
</j-form-item>
|
|
||||||
<j-form-item label="说明" name="description">
|
|
||||||
<j-textarea
|
|
||||||
placeholder="请输入说明"
|
|
||||||
v-model:value="formData.description"
|
|
||||||
:maxlength="200"
|
|
||||||
:rows="3"
|
|
||||||
showCount
|
|
||||||
/>
|
|
||||||
</j-form-item>
|
</j-form-item>
|
||||||
|
|
||||||
<j-form-item>
|
<j-form-item>
|
||||||
<j-button
|
<j-button v-if="view === 'false'" class="form-submit" html-type="submit" type="primary"
|
||||||
v-if="view === 'false'"
|
@click.prevent="onSubmit" :loading="loading">保存</j-button>
|
||||||
class="form-submit"
|
|
||||||
html-type="submit"
|
|
||||||
type="primary"
|
|
||||||
@click.prevent="onSubmit"
|
|
||||||
:loading="loading"
|
|
||||||
>保存</j-button
|
|
||||||
>
|
|
||||||
</j-form-item>
|
</j-form-item>
|
||||||
</j-form>
|
</j-form>
|
||||||
</j-col>
|
</j-col>
|
||||||
|
@ -131,8 +96,9 @@ const route = useRoute();
|
||||||
const view = route.query.view as string;
|
const view = route.query.view as string;
|
||||||
const id = route.params.id as string;
|
const id = route.params.id as string;
|
||||||
|
|
||||||
const useForm = Form.useForm;
|
// const useForm = Form.useForm;
|
||||||
|
|
||||||
|
const formRef = ref()
|
||||||
const fileLoading = ref(false);
|
const fileLoading = ref(false);
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
|
|
||||||
|
@ -144,49 +110,46 @@ const formData = ref<FormDataType>({
|
||||||
key: '',
|
key: '',
|
||||||
},
|
},
|
||||||
description: '',
|
description: '',
|
||||||
mode:'server',
|
mode: 'server',
|
||||||
authenticationMethod:'single'
|
authenticationMethod: 'single'
|
||||||
});
|
});
|
||||||
|
|
||||||
const { resetFields, validate, validateInfos } = useForm(
|
// const rules = {
|
||||||
formData,
|
// type: [{ required: true, message: '请选择证书标准', trigger: 'blur' }],
|
||||||
reactive({
|
// name: [
|
||||||
type: [{ required: true, message: '请选择证书标准', trigger: 'blur' }],
|
// { required: true, message: '请输入证书名称', trigger: 'blur' },
|
||||||
name: [
|
// { max: 64, message: '最多可输入64个字符' },
|
||||||
{ required: true, message: '请输入证书名称', trigger: 'blur' },
|
// ],
|
||||||
{ max: 64, message: '最多可输入64个字符' },
|
// 'configs.cert': [
|
||||||
],
|
// { required: true, message: '请输入或上传文件', trigger: 'blur' },
|
||||||
'configs.cert': [
|
// ],
|
||||||
{ required: true, message: '请输入或上传文件', trigger: 'blur' },
|
// 'configs.key': [
|
||||||
],
|
// { required: true, message: '请输入或上传文件', trigger: 'blur' },
|
||||||
'configs.key': [
|
// ],
|
||||||
{ required: true, message: '请输入或上传文件', trigger: 'blur' },
|
// description: [{ max: 200, message: '最多可输入200个字符' }],
|
||||||
],
|
// mode:[{ required: true, message: '请选择证书类型', trigger: 'blur' }],
|
||||||
description: [{ max: 200, message: '最多可输入200个字符' }],
|
// authenticationMethod:[{ required: true, message: '请选择认证方式', trigger: 'blur' }]
|
||||||
mode:[{ required: true, message: '请选择证书类型', trigger: 'blur' }],
|
// );
|
||||||
authenticationMethod:[{ required: true, message: '请选择认证方式', trigger: 'blur' }]
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
|
|
||||||
const onSubmit = () => {
|
const onSubmit = () => {
|
||||||
validate()
|
formRef.value.validate()
|
||||||
.then(async (res) => {
|
.then(async (res) => {
|
||||||
let params:any = toRaw(formData.value);
|
let params: any = toRaw(formData.value);
|
||||||
if(formData.value.mode === 'client'){
|
if (formData.value.mode === 'client') {
|
||||||
if(formData.value.authenticationMethod === 'binomial'){
|
if (formData.value.authenticationMethod === 'binomial') {
|
||||||
params.configs.trust = params.configs.cert
|
params.configs.trust = params.configs.cert
|
||||||
}else{
|
} else {
|
||||||
params.configs = {
|
params.configs = {
|
||||||
key:formData.value.configs.key,
|
// key:formData.value.configs.key,
|
||||||
trust:formData.value.configs.cert
|
trust: formData.value.configs.cert
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
const response =
|
const response =
|
||||||
id === ':id'
|
id === ':id'
|
||||||
? await save(params).catch(() => {})
|
? await save(params).catch(() => { })
|
||||||
: await update({ ...params, id }).catch(() => {});
|
: await update({ ...params, id }).catch(() => { });
|
||||||
if (response?.status === 200) {
|
if (response?.status === 200) {
|
||||||
onlyMessage('操作成功', 'success');
|
onlyMessage('操作成功', 'success');
|
||||||
router.push('/iot/link/certificate');
|
router.push('/iot/link/certificate');
|
||||||
|
@ -217,9 +180,9 @@ const detail = async (id: string) => {
|
||||||
const type = result.type.value as TypeObjType;
|
const type = result.type.value as TypeObjType;
|
||||||
formData.value = {
|
formData.value = {
|
||||||
...result,
|
...result,
|
||||||
configs:{
|
configs: {
|
||||||
key:result.configs.key,
|
key: result.configs.key,
|
||||||
cert:result.configs?.cert ? result.configs?.cert : result.configs?.trust
|
cert: result.configs?.cert ? result.configs?.cert : result.configs?.trust
|
||||||
},
|
},
|
||||||
mode: result.mode.value,
|
mode: result.mode.value,
|
||||||
authenticationMethod: result.authenticationMethod.value,
|
authenticationMethod: result.authenticationMethod.value,
|
||||||
|
@ -239,6 +202,7 @@ detail(id);
|
||||||
width: 148px;
|
width: 148px;
|
||||||
height: 80px;
|
height: 80px;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
|
||||||
img {
|
img {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|
|
@ -149,10 +149,16 @@ const getNetworkEcharts = async (val: any) => {
|
||||||
|
|
||||||
const formatterData = (value: any) => {
|
const formatterData = (value: any) => {
|
||||||
let _data = '';
|
let _data = '';
|
||||||
if (value >= 1024 && value < 1024 * 1024) {
|
const kb = 1024
|
||||||
_data = `${Number((value / 1024).toFixed(2))}KB`;
|
const mb = kb**2
|
||||||
} else if (value >= 1024 * 1024) {
|
const gb = kb**3
|
||||||
_data = `${Number((value / 1024 / 1024).toFixed(2))}M`;
|
|
||||||
|
if (value >= kb && value < mb) {
|
||||||
|
_data = `${Number((value / kb).toFixed(2))}KB`;
|
||||||
|
} else if (value >= mb && value < gb) {
|
||||||
|
_data = `${Number((value / mb).toFixed(2))}M`;
|
||||||
|
} else if (value >= gb) {
|
||||||
|
_data = `${Number((value / gb).toFixed(2))}G`;
|
||||||
} else {
|
} else {
|
||||||
_data = `${value}B`;
|
_data = `${value}B`;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1285,7 +1285,7 @@ const changeType = (value: string) => {
|
||||||
if (value !== 'MQTT_CLIENT') {
|
if (value !== 'MQTT_CLIENT') {
|
||||||
const { configuration } = dynamicValidateForm.cluster[0];
|
const { configuration } = dynamicValidateForm.cluster[0];
|
||||||
value && (configuration.host = '0.0.0.0');
|
value && (configuration.host = '0.0.0.0');
|
||||||
}else{
|
}else if(isNoCommunity){
|
||||||
formData.value.shareCluster = false
|
formData.value.shareCluster = false
|
||||||
changeShareCluster(formData.value.shareCluster)
|
changeShareCluster(formData.value.shareCluster)
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,12 +5,12 @@ const Webhook = () => {
|
||||||
<div class={'doc'}>
|
<div class={'doc'}>
|
||||||
<h1>1. 概述</h1>
|
<h1>1. 概述</h1>
|
||||||
<div>
|
<div>
|
||||||
webhook是一个接收HTTP请求的URL(本平台默认只支持HTTP
|
WebHook是一个接收HTTP请求的URL(本平台默认只支持HTTP
|
||||||
POST请求),实现了Webhook的第三方系统可以基于该URL订阅本平台系统信息,本平台按配置把特定的事件结果推送到指定的地址,便于系统做后续处理。
|
POST请求),实现了WebHook的第三方系统可以基于该URL订阅本平台系统信息,本平台按配置把特定的事件结果推送到指定的地址,便于系统做后续处理。
|
||||||
</div>
|
</div>
|
||||||
<h1>2.通知配置说明</h1>
|
<h1>2.通知配置说明</h1>
|
||||||
<h2>1、Webhook</h2>
|
<h2>1、WebHook</h2>
|
||||||
<div>Webhook地址。</div>
|
<div>WebHook地址。</div>
|
||||||
|
|
||||||
<h2>2、请求头</h2>
|
<h2>2、请求头</h2>
|
||||||
<div>
|
<div>
|
||||||
|
|
|
@ -80,7 +80,7 @@
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<j-form-item
|
<j-form-item
|
||||||
label="webHook"
|
label="WebHook"
|
||||||
v-bind="validateInfos['configuration.url']"
|
v-bind="validateInfos['configuration.url']"
|
||||||
:rules='[{ max: 64, message: "最多可输入64个字符" }]'
|
:rules='[{ max: 64, message: "最多可输入64个字符" }]'
|
||||||
>
|
>
|
||||||
|
@ -88,7 +88,7 @@
|
||||||
v-model:value="
|
v-model:value="
|
||||||
formData.configuration.url
|
formData.configuration.url
|
||||||
"
|
"
|
||||||
placeholder="请输入webHook"
|
placeholder="请输入WebHook"
|
||||||
/>
|
/>
|
||||||
</j-form-item>
|
</j-form-item>
|
||||||
</template>
|
</template>
|
||||||
|
@ -278,12 +278,12 @@
|
||||||
<!-- webhook -->
|
<!-- webhook -->
|
||||||
<template v-if="formData.type === 'webhook'">
|
<template v-if="formData.type === 'webhook'">
|
||||||
<j-form-item
|
<j-form-item
|
||||||
label="Webhook"
|
label="WebHook"
|
||||||
v-bind="validateInfos['configuration.url']"
|
v-bind="validateInfos['configuration.url']"
|
||||||
>
|
>
|
||||||
<j-input
|
<j-input
|
||||||
v-model:value="formData.configuration.url"
|
v-model:value="formData.configuration.url"
|
||||||
placeholder="请输入Webhook"
|
placeholder="请输入WebHook"
|
||||||
/>
|
/>
|
||||||
</j-form-item>
|
</j-form-item>
|
||||||
<j-form-item label="请求头">
|
<j-form-item label="请求头">
|
||||||
|
@ -447,7 +447,7 @@ const formRules = ref({
|
||||||
],
|
],
|
||||||
// webhook
|
// webhook
|
||||||
'configuration.url': [
|
'configuration.url': [
|
||||||
{ required: true, message: '请输入Webhook', trigger: 'blur' },
|
{ required: true, message: '请输入WebHook', trigger: 'blur' },
|
||||||
// {
|
// {
|
||||||
// pattern:
|
// pattern:
|
||||||
// /^(((ht|f)tps?):\/\/)?([^!@#$%^&*?.\s-]([^!@#$%^&*?.\s]{0,63}[^!@#$%^&*?.\s])?\.)+[j-z]{2,6}\/?/,
|
// /^(((ht|f)tps?):\/\/)?([^!@#$%^&*?.\s-]([^!@#$%^&*?.\s]{0,63}[^!@#$%^&*?.\s])?\.)+[j-z]{2,6}\/?/,
|
||||||
|
|
|
@ -28,7 +28,7 @@ export const NOTICE_METHOD: INoticeMethod[] = [
|
||||||
value: 'sms',
|
value: 'sms',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'webhook',
|
label: 'WebHook',
|
||||||
value: 'webhook',
|
value: 'webhook',
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
@ -75,7 +75,7 @@ export const MSG_TYPE = {
|
||||||
],
|
],
|
||||||
webhook: [
|
webhook: [
|
||||||
{
|
{
|
||||||
label: 'webhook',
|
label: 'WebHook',
|
||||||
value: 'http',
|
value: 'http',
|
||||||
logo: getImage('/notice/webhook.png'),
|
logo: getImage('/notice/webhook.png'),
|
||||||
},
|
},
|
||||||
|
|
|
@ -141,7 +141,7 @@
|
||||||
<div>
|
<div>
|
||||||
1、平台支持将告警数据输出到kafka,第三方系统可订阅kafka中的告警数据,进行业务处理。
|
1、平台支持将告警数据输出到kafka,第三方系统可订阅kafka中的告警数据,进行业务处理。
|
||||||
</div>
|
</div>
|
||||||
<h2>输出参数</h2>
|
<h2>推送参数</h2>
|
||||||
<div>
|
<div>
|
||||||
<j-table
|
<j-table
|
||||||
:dataSource="outputData"
|
:dataSource="outputData"
|
||||||
|
|
|
@ -192,6 +192,12 @@ const columns = [
|
||||||
hideInTable: true,
|
hideInTable: true,
|
||||||
search: {
|
search: {
|
||||||
type: 'treeSelect',
|
type: 'treeSelect',
|
||||||
|
componentProps: {
|
||||||
|
fieldNames: {
|
||||||
|
label: 'name',
|
||||||
|
value: 'value',
|
||||||
|
},
|
||||||
|
},
|
||||||
options: () => new Promise((resolve) => {
|
options: () => new Promise((resolve) => {
|
||||||
getTreeData_api({ paging: false }).then((resp: any) => {
|
getTreeData_api({ paging: false }).then((resp: any) => {
|
||||||
const formatValue = (list: any[]) => {
|
const formatValue = (list: any[]) => {
|
||||||
|
|
|
@ -208,10 +208,17 @@ const columns = [
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
dataIndex: 'id$dim-assets',
|
dataIndex: 'id$dim-assets',
|
||||||
|
key: 'id$dim-assets',
|
||||||
title: '所属组织',
|
title: '所属组织',
|
||||||
hideInTable: true,
|
hideInTable: true,
|
||||||
search: {
|
search: {
|
||||||
type: 'treeSelect',
|
type: 'treeSelect',
|
||||||
|
componentProps: {
|
||||||
|
fieldNames: {
|
||||||
|
label: 'name',
|
||||||
|
value: 'value',
|
||||||
|
},
|
||||||
|
},
|
||||||
options: () =>
|
options: () =>
|
||||||
new Promise((resolve) => {
|
new Promise((resolve) => {
|
||||||
getTreeData_api({ paging: false }).then((resp: any) => {
|
getTreeData_api({ paging: false }).then((resp: any) => {
|
||||||
|
|
|
@ -109,9 +109,13 @@ const upperOptions = computed(() => {
|
||||||
});
|
});
|
||||||
|
|
||||||
const onChange = () => {
|
const onChange = () => {
|
||||||
|
const objValue: any = { source: _source.value, value: _value.value }
|
||||||
|
if (_source.value === 'upper') {
|
||||||
|
objValue.upperKey = _value.value
|
||||||
|
}
|
||||||
emit('update:value', _value.value);
|
emit('update:value', _value.value);
|
||||||
emit('update:source', _source.value);
|
emit('update:source', _source.value);
|
||||||
emit('change', { source: _source.value, value: _value.value });
|
emit('change', objValue);
|
||||||
};
|
};
|
||||||
|
|
||||||
watchEffect(() => {
|
watchEffect(() => {
|
||||||
|
|
|
@ -173,11 +173,18 @@ const onChange = () => {
|
||||||
|
|
||||||
const onValueChange = (val: any, label: string) => {
|
const onValueChange = (val: any, label: string) => {
|
||||||
const optionColumn = isObject(val) && (val as any).metadata ? [(val as any).column] : []
|
const optionColumn = isObject(val) && (val as any).metadata ? [(val as any).column] : []
|
||||||
|
|
||||||
|
const objectValue: any = {
|
||||||
|
value: propertyModelRef?.propertiesValue,
|
||||||
|
source: propertyModelRef?.source,
|
||||||
|
}
|
||||||
|
|
||||||
|
if (propertyModelRef?.source === 'upper') {
|
||||||
|
objectValue.upperKey = propertyModelRef?.propertiesValue
|
||||||
|
}
|
||||||
|
|
||||||
const obj = {
|
const obj = {
|
||||||
[`${propertyModelRef.properties}`]: {
|
[`${propertyModelRef.properties}`]: objectValue
|
||||||
value: propertyModelRef?.propertiesValue,
|
|
||||||
source: propertyModelRef?.source,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
emit('update:value', obj);
|
emit('update:value', obj);
|
||||||
emit('change', label || val, optionColumn)
|
emit('change', label || val, optionColumn)
|
||||||
|
|
|
@ -220,7 +220,7 @@
|
||||||
)
|
)
|
||||||
"
|
"
|
||||||
/>
|
/>
|
||||||
webhook
|
WebHook
|
||||||
</span>
|
</span>
|
||||||
发送
|
发送
|
||||||
<span>{{
|
<span>{{
|
||||||
|
|
|
@ -144,12 +144,7 @@
|
||||||
|
|
||||||
<RequestTable
|
<RequestTable
|
||||||
v-model:value="form.data.page.parameters"
|
v-model:value="form.data.page.parameters"
|
||||||
value-type="select"
|
value-type="input"
|
||||||
:value-options="[
|
|
||||||
{ label: '用户ID', value: '用户ID' },
|
|
||||||
{ label: '用户名', value: '用户名' },
|
|
||||||
{ label: 'token', value: 'token' },
|
|
||||||
]"
|
|
||||||
/>
|
/>
|
||||||
</j-form-item>
|
</j-form-item>
|
||||||
</template>
|
</template>
|
||||||
|
@ -1397,12 +1392,20 @@
|
||||||
|
|
||||||
<div class="dialog">
|
<div class="dialog">
|
||||||
<MenuDialog
|
<MenuDialog
|
||||||
v-if="dialog.visible"
|
v-if="dialog.visible && dialog.current.provider !== 'third-party'"
|
||||||
v-model:visible="dialog.visible"
|
v-model:visible="dialog.visible"
|
||||||
:data="dialog.current"
|
:data="dialog.current"
|
||||||
:mode="routeQuery.id ? 'edit' : 'add'"
|
:mode="routeQuery.id ? 'edit' : 'add'"
|
||||||
@refresh="menuStory.jumpPage('system/Apply')"
|
@refresh="menuStory.jumpPage('system/Apply')"
|
||||||
/>
|
/>
|
||||||
|
<ThirdMenu
|
||||||
|
v-if="dialog.visible && dialog.current.provider === 'third-party'"
|
||||||
|
:data="dialog.current"
|
||||||
|
:mode="routeQuery.id ? 'edit' : 'add'"
|
||||||
|
mode="add"
|
||||||
|
@cancel="dialog.visible = false"
|
||||||
|
@ok="menuStory.jumpPage('system/Apply')"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -1420,6 +1423,7 @@ import {
|
||||||
import FormLabel from './FormLabel.vue';
|
import FormLabel from './FormLabel.vue';
|
||||||
import RequestTable from './RequestTable.vue';
|
import RequestTable from './RequestTable.vue';
|
||||||
import MenuDialog from '../../componenets/MenuDialog.vue';
|
import MenuDialog from '../../componenets/MenuDialog.vue';
|
||||||
|
import ThirdMenu from '../../componenets/ThirdMenu.vue';
|
||||||
import { getImage, onlyMessage } from '@/utils/comm';
|
import { getImage, onlyMessage } from '@/utils/comm';
|
||||||
import type { formType, dictType, optionsType, applyType } from '../typing';
|
import type { formType, dictType, optionsType, applyType } from '../typing';
|
||||||
import { getRoleList_api } from '@/api/system/user';
|
import { getRoleList_api } from '@/api/system/user';
|
||||||
|
|
|
@ -0,0 +1,150 @@
|
||||||
|
<template>
|
||||||
|
<j-modal
|
||||||
|
:confirmLoading="loading"
|
||||||
|
class="edit-dialog-container"
|
||||||
|
title="集成菜单"
|
||||||
|
visible
|
||||||
|
width="600px"
|
||||||
|
@cancel="cancel"
|
||||||
|
@ok="handleOk"
|
||||||
|
>
|
||||||
|
<p>
|
||||||
|
当前集成菜单
|
||||||
|
</p>
|
||||||
|
<j-tree
|
||||||
|
v-if="menuTree.length"
|
||||||
|
v-model:checkedKeys="menuState.checkedMenu"
|
||||||
|
v-model:expandedKeys="menuState.expandedKeys"
|
||||||
|
:fieldNames="{ key: 'code', title: 'name' }"
|
||||||
|
:height="300"
|
||||||
|
:tree-data="menuTree"
|
||||||
|
checkable
|
||||||
|
/>
|
||||||
|
<j-empty
|
||||||
|
v-else
|
||||||
|
/>
|
||||||
|
</j-modal>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script name="ThirdMenu" setup>
|
||||||
|
import {getMenuTree_api, queryOwnThree} from '@/api/system/menu';
|
||||||
|
import { onlyMessage } from '@/utils/comm';
|
||||||
|
import { useMenuStore } from '@/store/menu';
|
||||||
|
import { useRequest } from '@/hook'
|
||||||
|
import {filterTree, getCheckByTree} from "@/views/system/Apply/componenets/util";
|
||||||
|
import {
|
||||||
|
saveOwnerMenu_api,
|
||||||
|
updateApp_api,
|
||||||
|
} from '@/api/system/apply';
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
mode: {
|
||||||
|
type: String,
|
||||||
|
default: 'add'
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const menuStory = useMenuStore();
|
||||||
|
const loading = ref(false)
|
||||||
|
const emit = defineEmits(['ok', 'cancel']);
|
||||||
|
const menuState = reactive({
|
||||||
|
checkedMenu: [],
|
||||||
|
expandedKeys: [],
|
||||||
|
menuTree: ''
|
||||||
|
})
|
||||||
|
|
||||||
|
const menuTree = computed(() => {
|
||||||
|
try {
|
||||||
|
return JSON.parse(menuState.menuTree || '[]')
|
||||||
|
} catch (e) {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
useRequest(queryOwnThree,
|
||||||
|
{
|
||||||
|
defaultParams: { terms: [{ column: 'owner', termType: 'isnull', value: 0 }]},
|
||||||
|
onSuccess(res) {
|
||||||
|
menuState.menuTree = JSON.stringify(res.result)
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
const { run } = useRequest(getMenuTree_api, {
|
||||||
|
immediate: false,
|
||||||
|
onSuccess(res) {
|
||||||
|
menuState.checkedMenu = getCheckByTree(res.result)
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
}) // 获取应用绑定的菜单
|
||||||
|
|
||||||
|
const cancel = () => {
|
||||||
|
if (props.mode === 'add') {
|
||||||
|
menuStory.jumpPage('system/Apply/Save', {}, { id: props.data?.id })
|
||||||
|
}
|
||||||
|
emit('cancel')
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleOk = async () => {
|
||||||
|
if (!menuState.checkedMenu.length) {
|
||||||
|
onlyMessage('请勾选配置菜单', 'warning')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const id = props.data.id
|
||||||
|
const cloneData = JSON.parse(menuState.menuTree)
|
||||||
|
const filterData = filterTree(cloneData, menuState.checkedMenu)
|
||||||
|
|
||||||
|
loading.value = true
|
||||||
|
|
||||||
|
try {
|
||||||
|
const resp = await saveOwnerMenu_api('iot', id, filterData)
|
||||||
|
await updateApp_api(id, {
|
||||||
|
...props.data,
|
||||||
|
integrationModes: props.data?.integrationModes?.map((item) => item?.value || item),
|
||||||
|
page: {
|
||||||
|
...props.data?.page,
|
||||||
|
configuration: {
|
||||||
|
checkedSystem: props.data?.page?.configuration?.checkedSystem
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if (resp.success) {
|
||||||
|
// 保存集成菜单
|
||||||
|
onlyMessage('操作成功');
|
||||||
|
emit('ok')
|
||||||
|
}
|
||||||
|
loading.value = false
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e)
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const getBindMenuData = () => {
|
||||||
|
const id = props.data.id
|
||||||
|
|
||||||
|
run({
|
||||||
|
terms: [
|
||||||
|
{
|
||||||
|
column: 'appId',
|
||||||
|
value: id,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if (props.data?.id) {
|
||||||
|
getBindMenuData()
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
|
@ -0,0 +1,27 @@
|
||||||
|
export const getCheckByTree = (data: any[]): string[] => {
|
||||||
|
let keys: string[] = []
|
||||||
|
if (data.length) {
|
||||||
|
data.forEach(item => {
|
||||||
|
if (item.children) {
|
||||||
|
keys = [...getCheckByTree(item.children), ...keys]
|
||||||
|
} else {
|
||||||
|
keys.push(item.code)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return keys
|
||||||
|
}
|
||||||
|
|
||||||
|
export const filterTree = (data: any[], ids: string[]) => {
|
||||||
|
return data?.filter(item => {
|
||||||
|
delete item.id
|
||||||
|
item.options = {show: true}
|
||||||
|
if (ids.includes(item.code)) {
|
||||||
|
return true
|
||||||
|
} else if (item.children) {
|
||||||
|
item.children = filterTree(item.children, ids)
|
||||||
|
return item.children.length >0
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}) || []
|
||||||
|
}
|
|
@ -183,12 +183,19 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="dialogs">
|
<div class="dialogs">
|
||||||
<MenuDialog
|
<MenuDialog
|
||||||
v-if="dialogVisible"
|
v-if="dialogVisible && current.provider !== 'third-party'"
|
||||||
v-model:visible="dialogVisible"
|
v-model:visible="dialogVisible"
|
||||||
mode="edit"
|
mode="edit"
|
||||||
:data="current"
|
:data="current"
|
||||||
@refresh="table.refresh"
|
@refresh="table.refresh"
|
||||||
/>
|
/>
|
||||||
|
<ThirdMenu
|
||||||
|
v-if="dialogVisible && current.provider === 'third-party'"
|
||||||
|
:data="current"
|
||||||
|
mode="edit"
|
||||||
|
@cancel="dialogVisible = false"
|
||||||
|
@ok="() => { dialogVisible = false; table.refresh}"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<Add v-if="visible" @close="visible = false" />
|
<Add v-if="visible" @close="visible = false" />
|
||||||
</page-container>
|
</page-container>
|
||||||
|
@ -197,6 +204,7 @@
|
||||||
<script setup lang="ts" name="Apply">
|
<script setup lang="ts" name="Apply">
|
||||||
import PermissionButton from '@/components/PermissionButton/index.vue';
|
import PermissionButton from '@/components/PermissionButton/index.vue';
|
||||||
import MenuDialog from './componenets/MenuDialog.vue';
|
import MenuDialog from './componenets/MenuDialog.vue';
|
||||||
|
import ThirdMenu from './componenets/ThirdMenu.vue'
|
||||||
import {
|
import {
|
||||||
getApplyList_api,
|
getApplyList_api,
|
||||||
changeApplyStatus_api,
|
changeApplyStatus_api,
|
||||||
|
|
|
@ -129,6 +129,20 @@
|
||||||
/>
|
/>
|
||||||
</j-form-item>
|
</j-form-item>
|
||||||
</j-col>
|
</j-col>
|
||||||
|
<j-col :span="12">
|
||||||
|
<j-form-item
|
||||||
|
label="所属应用"
|
||||||
|
name="owner"
|
||||||
|
>
|
||||||
|
<j-select
|
||||||
|
v-model:value="form.data.owner"
|
||||||
|
:options="[{ label: 'Iot', value: 'iot' }]"
|
||||||
|
allowClear
|
||||||
|
placeholder="请选择所属应用"
|
||||||
|
style="width: 100%"
|
||||||
|
/>
|
||||||
|
</j-form-item>
|
||||||
|
</j-col>
|
||||||
</j-row>
|
</j-row>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -362,6 +376,8 @@ const form = reactive({
|
||||||
const accessSupportValue = form.data.accessSupport;
|
const accessSupportValue = form.data.accessSupport;
|
||||||
const params = {
|
const params = {
|
||||||
...form.data,
|
...form.data,
|
||||||
|
owner: form.data?.owner ?? null,
|
||||||
|
options: { show: true },
|
||||||
accessSupport: {
|
accessSupport: {
|
||||||
value: accessSupportValue,
|
value: accessSupportValue,
|
||||||
label:
|
label:
|
||||||
|
@ -371,7 +387,6 @@ const form = reactive({
|
||||||
? '支持'
|
? '支持'
|
||||||
: '间接控制',
|
: '间接控制',
|
||||||
},
|
},
|
||||||
owner: 'iot',
|
|
||||||
};
|
};
|
||||||
api(params)
|
api(params)
|
||||||
.then((resp: any) => {
|
.then((resp: any) => {
|
||||||
|
@ -442,7 +457,7 @@ type assetType = {
|
||||||
|
|
||||||
&::before {
|
&::before {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 5px px;
|
top: 5px;
|
||||||
left: 0;
|
left: 0;
|
||||||
width: 4px;
|
width: 4px;
|
||||||
height: calc(100% - 10px);
|
height: calc(100% - 10px);
|
||||||
|
|
|
@ -229,7 +229,7 @@ onMounted(() => {
|
||||||
))
|
))
|
||||||
console.log(AllMenu);
|
console.log(AllMenu);
|
||||||
// 处理排序
|
// 处理排序
|
||||||
treeData.value = handleSortsArr(systemMenu.value);
|
treeData.value = handleSortsArr(AllMenu);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -179,21 +179,17 @@ const table = reactive({
|
||||||
//过滤非集成的菜单
|
//过滤非集成的菜单
|
||||||
const item = {
|
const item = {
|
||||||
terms: [
|
terms: [
|
||||||
{
|
{
|
||||||
terms: [
|
column: 'owner',
|
||||||
{
|
termType: 'eq',
|
||||||
column: 'owner',
|
value: 'iot',
|
||||||
termType: 'eq',
|
},
|
||||||
value: 'iot',
|
{
|
||||||
},
|
column: 'owner',
|
||||||
{
|
termType: 'isnull',
|
||||||
column: 'owner',
|
value: '1',
|
||||||
termType: 'isnull',
|
type: 'or',
|
||||||
value: '1',
|
},
|
||||||
type: 'or',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
const params = {
|
const params = {
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
<div
|
<div
|
||||||
class="child-item-left-auth"
|
class="child-item-left-auth"
|
||||||
:class="{ disabled: !checked }"
|
:class="{ disabled: !checked }"
|
||||||
|
v-if="isNoCommunity"
|
||||||
>
|
>
|
||||||
<j-tooltip>
|
<j-tooltip>
|
||||||
<template #title>
|
<template #title>
|
||||||
|
@ -163,6 +164,7 @@ import { Modal, Checkbox } from 'jetlinks-ui-components';
|
||||||
import { usePermissionStore } from '@/store/permission';
|
import { usePermissionStore } from '@/store/permission';
|
||||||
import { LocalStore } from '@/utils/comm';
|
import { LocalStore } from '@/utils/comm';
|
||||||
import { useUserInfo } from '@/store/userInfo';
|
import { useUserInfo } from '@/store/userInfo';
|
||||||
|
import { isNoCommunity } from '@/utils/utils';
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
data: {
|
data: {
|
||||||
|
|
|
@ -191,7 +191,7 @@ const form = reactive({
|
||||||
else {
|
else {
|
||||||
const resp: any = await checkId_api({ id });
|
const resp: any = await checkId_api({ id });
|
||||||
if (resp.result.passed) return Promise.resolve();
|
if (resp.result.passed) return Promise.resolve();
|
||||||
else return Promise.reject(resp.result.reason);
|
else return Promise.reject("标识重复");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -117,7 +117,7 @@
|
||||||
v-if="refStr"
|
v-if="refStr"
|
||||||
ref="editorRef"
|
ref="editorRef"
|
||||||
language="json"
|
language="json"
|
||||||
style="height: 100%"
|
style="height: 100% ; min-height: 200px;"
|
||||||
theme="vs"
|
theme="vs"
|
||||||
v-model:modelValue="requestBody.code"
|
v-model:modelValue="requestBody.code"
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -96,7 +96,7 @@ export default defineConfig(({ mode}) => {
|
||||||
// target: 'http://192.168.32.244:8881',
|
// target: 'http://192.168.32.244:8881',
|
||||||
// target: 'http://192.168.32.163:8844', //张季本地
|
// target: 'http://192.168.32.163:8844', //张季本地
|
||||||
// target: 'http://120.77.179.54:8844', // 120测试
|
// target: 'http://120.77.179.54:8844', // 120测试
|
||||||
target: 'http://192.168.33.46:8844', // 本地开发环境
|
target: 'http://192.168.33.46:8844', // 本地开发环境
|
||||||
// target: 'http://192.168.32.5:8848', // 刘本地
|
// target: 'http://192.168.32.5:8848', // 刘本地
|
||||||
ws: 'ws://192.168.33.46:8844',
|
ws: 'ws://192.168.33.46:8844',
|
||||||
changeOrigin: true,
|
changeOrigin: true,
|
||||||
|
|
|
@ -3738,10 +3738,10 @@ jetlinks-store@^0.0.3:
|
||||||
resolved "https://registry.npmjs.org/jetlinks-store/-/jetlinks-store-0.0.3.tgz"
|
resolved "https://registry.npmjs.org/jetlinks-store/-/jetlinks-store-0.0.3.tgz"
|
||||||
integrity sha512-AZf/soh1hmmwjBZ00fr1emuMEydeReaI6IBTGByQYhTmK1Zd5pQAxC7WLek2snRAn/HHDgJfVz2hjditKThl6Q==
|
integrity sha512-AZf/soh1hmmwjBZ00fr1emuMEydeReaI6IBTGByQYhTmK1Zd5pQAxC7WLek2snRAn/HHDgJfVz2hjditKThl6Q==
|
||||||
|
|
||||||
jetlinks-ui-components@^1.0.33:
|
jetlinks-ui-components@^1.0.34-4:
|
||||||
version "1.0.33"
|
version "1.0.34-4"
|
||||||
resolved "http://registry.jetlinks.cn/jetlinks-ui-components/-/jetlinks-ui-components-1.0.33.tgz#49ce2b8c1e7be66272864728d5df82f834ec4490"
|
resolved "https://registry.npmjs.org/jetlinks-ui-components/-/jetlinks-ui-components-1.0.34-4.tgz#92cfc6be685988385a489f3e924383c4831f3ed5"
|
||||||
integrity sha512-vYUP4MhzO6r0golmKqO8lHk8w5ldhAkgXWZfFII1Zoa7JtUwveqpSywTU23iSmCN+4muPaSLvHw713k6OdzLmg==
|
integrity sha512-td+RgaBC5lQxRuDsHkCg9UEzCcSy4XikufnabVGz5IxU+UmXu+PJUjz2wo9vDe8sPSctyk/5jQU+N6GBPlp8JA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@vueuse/core" "^9.12.0"
|
"@vueuse/core" "^9.12.0"
|
||||||
"@vueuse/router" "^9.13.0"
|
"@vueuse/router" "^9.13.0"
|
||||||
|
|
Loading…
Reference in New Issue