fix: 优化物联卡详情仪表盘显示异常;修改菜单拖拽排序
* fix: 修改菜单拖拽排序 * fix: 优化物联卡详情仪表盘显示异常
This commit is contained in:
parent
acf2c006db
commit
bc0c4fa55b
|
@ -8848,11 +8848,8 @@
|
||||||
"version": "2.0.5",
|
"version": "2.0.5",
|
||||||
"resolved": "http://registry.jetlinks.cn/init-package-json/-/init-package-json-2.0.5.tgz",
|
"resolved": "http://registry.jetlinks.cn/init-package-json/-/init-package-json-2.0.5.tgz",
|
||||||
"integrity": "sha512-u1uGAtEFu3VA6HNl/yUWw57jmKEMx8SKOxHhxjGnOFUiIlFnohKDFg4ZrPpv9wWqk44nDxGJAtqjdQFm+9XXQA==",
|
"integrity": "sha512-u1uGAtEFu3VA6HNl/yUWw57jmKEMx8SKOxHhxjGnOFUiIlFnohKDFg4ZrPpv9wWqk44nDxGJAtqjdQFm+9XXQA==",
|
||||||
<<<<<<< HEAD
|
|
||||||
=======
|
|
||||||
"resolved": "http://registry.jetlinks.cn/init-package-json/-/init-package-json-2.0.5.tgz",
|
"resolved": "http://registry.jetlinks.cn/init-package-json/-/init-package-json-2.0.5.tgz",
|
||||||
"integrity": "sha512-u1uGAtEFu3VA6HNl/yUWw57jmKEMx8SKOxHhxjGnOFUiIlFnohKDFg4ZrPpv9wWqk44nDxGJAtqjdQFm+9XXQA==",
|
"integrity": "sha512-u1uGAtEFu3VA6HNl/yUWw57jmKEMx8SKOxHhxjGnOFUiIlFnohKDFg4ZrPpv9wWqk44nDxGJAtqjdQFm+9XXQA==",
|
||||||
>>>>>>> dev-bug
|
|
||||||
"inBundle": true,
|
"inBundle": true,
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -1,75 +0,0 @@
|
||||||
<template>
|
|
||||||
<j-modal :mask-closable="false" visible width="70vw" title="设置属性规则" @cancel="handleCancel" @ok="handleOk">
|
|
||||||
<div class="advance-box">
|
|
||||||
<div class="left">
|
|
||||||
<Editor
|
|
||||||
ref="editor"
|
|
||||||
mode="advance"
|
|
||||||
key="advance"
|
|
||||||
v-model:value="_value"
|
|
||||||
/>
|
|
||||||
<Debug
|
|
||||||
:virtualRule="{
|
|
||||||
...virtualRule,
|
|
||||||
script: _value,
|
|
||||||
}"
|
|
||||||
:id="id"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div class="right">
|
|
||||||
<Operator :id="id" @add-operator-value="addOperatorValue"/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</j-modal>
|
|
||||||
</template>
|
|
||||||
<script setup lang="ts" name="Advance">
|
|
||||||
import Editor from '../Editor/index.vue'
|
|
||||||
import Debug from '../Debug/index.vue'
|
|
||||||
import Operator from '../Operator/index.vue'
|
|
||||||
|
|
||||||
interface Emits {
|
|
||||||
(e: 'update:value', data: string | undefined): void;
|
|
||||||
(e: 'change', data: string): void;
|
|
||||||
}
|
|
||||||
const emit = defineEmits<Emits>();
|
|
||||||
|
|
||||||
const props = defineProps({
|
|
||||||
value: String,
|
|
||||||
id: String,
|
|
||||||
virtualRule: Object
|
|
||||||
})
|
|
||||||
|
|
||||||
const _value = ref<string | undefined>(props.value)
|
|
||||||
|
|
||||||
const handleCancel = () => {
|
|
||||||
emit('change', 'simple')
|
|
||||||
}
|
|
||||||
const handleOk = () => {
|
|
||||||
emit('update:value', _value.value)
|
|
||||||
emit('change', 'simple')
|
|
||||||
}
|
|
||||||
|
|
||||||
const editor = ref()
|
|
||||||
const addOperatorValue = (val: string) => {
|
|
||||||
editor.value.addOperatorValue(val)
|
|
||||||
}
|
|
||||||
|
|
||||||
</script>
|
|
||||||
<style lang="less" scoped>
|
|
||||||
.advance-box {
|
|
||||||
display: flex;
|
|
||||||
justify-content: flex-start;
|
|
||||||
width: 100%;
|
|
||||||
|
|
||||||
.left {
|
|
||||||
width: 70%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.right {
|
|
||||||
width: 30%;
|
|
||||||
margin-left: 10px;
|
|
||||||
padding-left: 10px;
|
|
||||||
border-left: 1px solid lightgray;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -1,302 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="debug-container">
|
|
||||||
<div class="left">
|
|
||||||
<div class="header">
|
|
||||||
<div>
|
|
||||||
<div class="title">
|
|
||||||
属性赋值
|
|
||||||
<div class="description">请对上方规则使用的属性进行赋值</div>
|
|
||||||
</div>
|
|
||||||
<div v-if="!isBeginning && virtualRule?.type === 'window'" class="action" @click="runScriptAgain">
|
|
||||||
<a style="margin-left: 75px;">发送数据</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<j-table :columns="columns" :data-source="property" :pagination="false" bordered size="small">
|
|
||||||
<template #bodyCell="{ column, record, index }">
|
|
||||||
<template v-if="column.key === 'id'">
|
|
||||||
<j-auto-complete :options="options" v-model:value="record.id" size="small" style="width: 130px" />
|
|
||||||
</template>
|
|
||||||
<template v-if="column.key === 'current'">
|
|
||||||
<j-input v-model:value="record.current" size="small"></j-input>
|
|
||||||
</template>
|
|
||||||
<template v-if="column.key === 'last'">
|
|
||||||
<j-input v-model:value="record.last" size="small"></j-input>
|
|
||||||
</template>
|
|
||||||
<template v-if="column.key === 'action'">
|
|
||||||
<AIcon type="DeleteOutlined" @click="deleteItem(index)" />
|
|
||||||
</template>
|
|
||||||
</template>
|
|
||||||
</j-table>
|
|
||||||
<j-button type="dashed" block style="margin-top: 5px" @click="addItem">
|
|
||||||
<template #icon>
|
|
||||||
<AIcon type="PlusOutlined" />
|
|
||||||
</template>
|
|
||||||
添加条目
|
|
||||||
</j-button>
|
|
||||||
</div>
|
|
||||||
<div class="right">
|
|
||||||
<div class="header">
|
|
||||||
<div class="title">
|
|
||||||
<div>运行结果</div>
|
|
||||||
</div>
|
|
||||||
<div class="action">
|
|
||||||
<div>
|
|
||||||
<a v-if="isBeginning" @click="beginAction">
|
|
||||||
开始运行
|
|
||||||
</a>
|
|
||||||
<a v-else @click="stopAction">
|
|
||||||
停止运行
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<a @click="clearAction">
|
|
||||||
清空
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="log">
|
|
||||||
<j-descriptions>
|
|
||||||
<j-descriptions-item v-for="item in ruleEditorStore.state.log" :label="moment(item.time).format('HH:mm:ss')"
|
|
||||||
:key="item.time" :span="3">
|
|
||||||
<j-tooltip placement="top" :title="item.content">
|
|
||||||
{{ item.content }}
|
|
||||||
</j-tooltip>
|
|
||||||
</j-descriptions-item>
|
|
||||||
</j-descriptions>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<script setup lang="ts" name="Debug">
|
|
||||||
import { PropType } from 'vue';
|
|
||||||
import { useProductStore } from '@/store/product';
|
|
||||||
import { useRuleEditorStore } from '@/store/ruleEditor';
|
|
||||||
import moment from 'moment';
|
|
||||||
import { getWebSocket } from '@/utils/websocket';
|
|
||||||
import { PropertyMetadata } from '@/views/device/Product/typings';
|
|
||||||
import { onlyMessage } from '@/utils/comm';
|
|
||||||
|
|
||||||
|
|
||||||
const props = defineProps({
|
|
||||||
virtualRule: Object as PropType<Record<any, any>>,
|
|
||||||
id: String,
|
|
||||||
})
|
|
||||||
|
|
||||||
const isBeginning = ref(true)
|
|
||||||
|
|
||||||
type propertyType = {
|
|
||||||
id?: string,
|
|
||||||
current?: string,
|
|
||||||
last?: string
|
|
||||||
}
|
|
||||||
const property = ref<propertyType[]>([])
|
|
||||||
|
|
||||||
const columns = [{
|
|
||||||
title: '属性ID',
|
|
||||||
dataIndex: 'id',
|
|
||||||
key: 'id'
|
|
||||||
}, {
|
|
||||||
title: '当前值',
|
|
||||||
dataIndex: 'current',
|
|
||||||
key: 'current'
|
|
||||||
}, {
|
|
||||||
title: '上一值',
|
|
||||||
dataIndex: 'last',
|
|
||||||
key: 'last'
|
|
||||||
}, {
|
|
||||||
title: '',
|
|
||||||
key: 'action'
|
|
||||||
}]
|
|
||||||
|
|
||||||
const addItem = () => {
|
|
||||||
property.value.push({})
|
|
||||||
}
|
|
||||||
const deleteItem = (index: number) => {
|
|
||||||
property.value.splice(index, 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
const ws = ref()
|
|
||||||
|
|
||||||
const virtualIdRef = ref(new Date().getTime());
|
|
||||||
|
|
||||||
const productStore = useProductStore()
|
|
||||||
const ruleEditorStore = useRuleEditorStore()
|
|
||||||
const runScript = () => {
|
|
||||||
const metadata = productStore.current.metadata || '{}';
|
|
||||||
const propertiesList = JSON.parse(metadata).properties || [];
|
|
||||||
const _properties = property.value.map((item: any) => {
|
|
||||||
const _item = propertiesList.find((i: any) => i.id === item.id);
|
|
||||||
return { ...item, type: _item?.valueType?.type };
|
|
||||||
});
|
|
||||||
|
|
||||||
if (ws.value) {
|
|
||||||
ws.value.unsubscribe?.();
|
|
||||||
}
|
|
||||||
if (!props.virtualRule?.script) {
|
|
||||||
isBeginning.value = true;
|
|
||||||
onlyMessage('请编辑规则', 'warning');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ws.value = getWebSocket(`virtual-property-debug-${props.id}-${new Date().getTime()}`,
|
|
||||||
'/virtual-property-debug',
|
|
||||||
{
|
|
||||||
virtualId: `${virtualIdRef.value}-virtual-id`,
|
|
||||||
property: props.id,
|
|
||||||
virtualRule: {
|
|
||||||
...props.virtualRule,
|
|
||||||
},
|
|
||||||
properties: _properties || [],
|
|
||||||
}).subscribe((data: any) => {
|
|
||||||
ruleEditorStore.state.log.push({ time: new Date().getTime(), content: JSON.stringify(data.payload) });
|
|
||||||
if (props.virtualRule?.type !== 'window') {
|
|
||||||
stopAction()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const wsAgain = ref<any>();
|
|
||||||
const runScriptAgain = async () => {
|
|
||||||
if (wsAgain.value) {
|
|
||||||
wsAgain.value.unsubscribe?.();
|
|
||||||
}
|
|
||||||
const metadata = productStore.current.metadata || '{}';
|
|
||||||
const propertiesList = JSON.parse(metadata).properties || [];
|
|
||||||
const _properties = property.value.map((item: any) => {
|
|
||||||
const _item = propertiesList.find((i: any) => i.id === item.id);
|
|
||||||
return { ...item, type: _item?.valueType?.type };
|
|
||||||
});
|
|
||||||
|
|
||||||
wsAgain.value = getWebSocket(`virtual-property-debug-${props.id}-${new Date().getTime()}`,
|
|
||||||
'/virtual-property-debug',
|
|
||||||
{
|
|
||||||
virtualId: `${virtualIdRef.value}-virtual-id`,
|
|
||||||
property: props.id,
|
|
||||||
virtualRule: {
|
|
||||||
...props.virtualRule,
|
|
||||||
},
|
|
||||||
properties: _properties || [],
|
|
||||||
}).subscribe((data: any) => { })
|
|
||||||
}
|
|
||||||
|
|
||||||
const beginAction = () => {
|
|
||||||
isBeginning.value = false;
|
|
||||||
runScript();
|
|
||||||
}
|
|
||||||
const stopAction = () => {
|
|
||||||
isBeginning.value = true;
|
|
||||||
if (ws.value) {
|
|
||||||
ws.value.unsubscribe?.();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const clearAction = () => {
|
|
||||||
ruleEditorStore.set('log', []);
|
|
||||||
}
|
|
||||||
|
|
||||||
onUnmounted(() => {
|
|
||||||
if (ws.value) {
|
|
||||||
ws.value.unsubscribe?.();
|
|
||||||
}
|
|
||||||
clearAction()
|
|
||||||
})
|
|
||||||
|
|
||||||
const options = ref<{ label: string, value: string }[]>()
|
|
||||||
const getProperty = () => {
|
|
||||||
const metadata = productStore.current.metadata || '{}';
|
|
||||||
const _p: PropertyMetadata[] = JSON.parse(metadata).properties || [];
|
|
||||||
options.value = _p.filter((p) => p.id !== props.id).map((item) => ({
|
|
||||||
label: item.name,
|
|
||||||
value: item.id,
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
getProperty()
|
|
||||||
</script>
|
|
||||||
<style lang="less" scoped>
|
|
||||||
.debug-container {
|
|
||||||
display: flex;
|
|
||||||
width: 100%;
|
|
||||||
height: 340px;
|
|
||||||
margin-top: 20px;
|
|
||||||
|
|
||||||
.left {
|
|
||||||
flex: 1;
|
|
||||||
min-width: 0;
|
|
||||||
max-width: 550px;
|
|
||||||
overflow-y: auto;
|
|
||||||
border: 1px solid lightgray;
|
|
||||||
|
|
||||||
.header {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
width: 100%;
|
|
||||||
height: 40px;
|
|
||||||
border-bottom: 1px solid lightgray;
|
|
||||||
//justify-content: space-around;
|
|
||||||
|
|
||||||
div {
|
|
||||||
display: flex;
|
|
||||||
//width: 100%;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: flex-start;
|
|
||||||
height: 100%;
|
|
||||||
|
|
||||||
.title {
|
|
||||||
margin: 0 10px;
|
|
||||||
font-weight: 600;
|
|
||||||
font-size: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.description {
|
|
||||||
margin-left: 10px;
|
|
||||||
color: lightgray;
|
|
||||||
font-size: 12px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.action {
|
|
||||||
width: 150px;
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.right {
|
|
||||||
flex: 1;
|
|
||||||
min-width: 0;
|
|
||||||
border: 1px solid lightgray;
|
|
||||||
border-left: none;
|
|
||||||
|
|
||||||
.header {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: space-between;
|
|
||||||
width: 100%;
|
|
||||||
height: 40px;
|
|
||||||
border-bottom: 1px solid lightgray;
|
|
||||||
|
|
||||||
.title {
|
|
||||||
display: flex;
|
|
||||||
|
|
||||||
div {
|
|
||||||
margin: 0 10px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.action {
|
|
||||||
display: flex;
|
|
||||||
|
|
||||||
div {
|
|
||||||
margin: 0 10px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.log {
|
|
||||||
height: 290px;
|
|
||||||
padding: 5px;
|
|
||||||
overflow: auto;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -1,213 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="editor-box">
|
|
||||||
<div class="top">
|
|
||||||
<div class="left">
|
|
||||||
<span v-for="item in symbolList.filter((t: SymbolType, i: number) => i <= 3)" :key="item.key"
|
|
||||||
@click="addOperatorValue(item.value)">
|
|
||||||
{{ item.value }}
|
|
||||||
</span>
|
|
||||||
<span>
|
|
||||||
<j-dropdown>
|
|
||||||
<AIcon type="MoreOutlined" />
|
|
||||||
<template #overlay>
|
|
||||||
<j-menu>
|
|
||||||
<j-menu-item v-for="item in symbolList.filter((t: SymbolType, i: number) => i > 6)" :key="item.key"
|
|
||||||
@click="addOperatorValue(item.value)">
|
|
||||||
{{ item.value }}
|
|
||||||
</j-menu-item>
|
|
||||||
</j-menu>
|
|
||||||
</template>
|
|
||||||
</j-dropdown>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div class="right">
|
|
||||||
<span v-if="mode !== 'advance'">
|
|
||||||
<j-tooltip :title="!id ? '请先输入标识' : '设置属性规则'">
|
|
||||||
<AIcon type="FullscreenOutlined" :class="!id ? 'disabled' : ''" @click="fullscreenClick" />
|
|
||||||
</j-tooltip>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="editor">
|
|
||||||
<j-monaco-editor v-if="loading" v-model:model-value="_value" theme="vs" ref="editor" language="javascript"/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<script setup lang="ts" name="Editor">
|
|
||||||
|
|
||||||
interface Props {
|
|
||||||
mode?: 'advance' | 'simple';
|
|
||||||
id?: string;
|
|
||||||
value?: string;
|
|
||||||
}
|
|
||||||
const props = defineProps<Props>()
|
|
||||||
|
|
||||||
interface Emits {
|
|
||||||
(e: 'change', data: string): void;
|
|
||||||
(e: 'update:value', data: string): void;
|
|
||||||
}
|
|
||||||
|
|
||||||
const emit = defineEmits<Emits>()
|
|
||||||
|
|
||||||
type editorType = {
|
|
||||||
insert(val: string): void
|
|
||||||
}
|
|
||||||
const editor = ref<editorType>()
|
|
||||||
|
|
||||||
type SymbolType = {
|
|
||||||
key: string,
|
|
||||||
value: string
|
|
||||||
}
|
|
||||||
const symbolList = [
|
|
||||||
{
|
|
||||||
key: 'add',
|
|
||||||
value: '+',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'subtract',
|
|
||||||
value: '-',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'multiply',
|
|
||||||
value: '*',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'divide',
|
|
||||||
value: '/',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'parentheses',
|
|
||||||
value: '()',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'cubic',
|
|
||||||
value: '^',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'dayu',
|
|
||||||
value: '>',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'dayudengyu',
|
|
||||||
value: '>=',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'dengyudengyu',
|
|
||||||
value: '==',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'xiaoyudengyu',
|
|
||||||
value: '<=',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'xiaoyu',
|
|
||||||
value: '<',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'jiankuohao',
|
|
||||||
value: '<>',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'andand',
|
|
||||||
value: '&&',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'huohuo',
|
|
||||||
value: '||',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'fei',
|
|
||||||
value: '!',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'and',
|
|
||||||
value: '&',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'huo',
|
|
||||||
value: '|',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'bolang',
|
|
||||||
value: '~',
|
|
||||||
},
|
|
||||||
] as SymbolType[];
|
|
||||||
|
|
||||||
const _value = computed({
|
|
||||||
get: () => props.value || '',
|
|
||||||
set: (data: string) => {
|
|
||||||
emit('update:value', data);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const loading = ref(false)
|
|
||||||
onMounted(() => {
|
|
||||||
setTimeout(() => {
|
|
||||||
loading.value = true;
|
|
||||||
}, 100);
|
|
||||||
})
|
|
||||||
|
|
||||||
const addOperatorValue = (val: string) => {
|
|
||||||
editor.value?.insert(val)
|
|
||||||
}
|
|
||||||
|
|
||||||
const fullscreenClick = () => {
|
|
||||||
if (props.id) {
|
|
||||||
emit('change', 'advance');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
defineExpose({
|
|
||||||
addOperatorValue
|
|
||||||
})
|
|
||||||
|
|
||||||
</script>
|
|
||||||
<style lang="less" scoped>
|
|
||||||
.editor-box {
|
|
||||||
margin-bottom: 10px;
|
|
||||||
border: 1px solid lightgray;
|
|
||||||
|
|
||||||
.top {
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
justify-content: space-between;
|
|
||||||
width: 100%;
|
|
||||||
border-bottom: 1px solid lightgray;
|
|
||||||
|
|
||||||
.left {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
width: 60%;
|
|
||||||
margin: 0 5px;
|
|
||||||
|
|
||||||
span {
|
|
||||||
display: inline-block;
|
|
||||||
height: 40px;
|
|
||||||
margin: 0 10px;
|
|
||||||
line-height: 40px;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.right {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
width: 10%;
|
|
||||||
margin: 0 5px;
|
|
||||||
|
|
||||||
span {
|
|
||||||
margin: 0 5px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.disabled {
|
|
||||||
color: rgba(#000, 0.5);
|
|
||||||
cursor: not-allowed;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.editor {
|
|
||||||
height: 300px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -1,10 +0,0 @@
|
||||||
import type { TreeNode } from '@/utils/tree';
|
|
||||||
|
|
||||||
interface OperatorItem extends TreeNode {
|
|
||||||
id: string;
|
|
||||||
name: string;
|
|
||||||
key: string;
|
|
||||||
description: string;
|
|
||||||
code: string;
|
|
||||||
children: OperatorItem[];
|
|
||||||
}
|
|
|
@ -1,44 +0,0 @@
|
||||||
<template>
|
|
||||||
<Editor key="simple" @change="change" v-model:value="_value" :id="id" />
|
|
||||||
<Advance v-if="ruleEditorStore.state.model === 'advance'" v-model:value="_value" :model="ruleEditorStore.state.model"
|
|
||||||
:virtualRule="virtualRule" :id="id" @change="change" />
|
|
||||||
</template>
|
|
||||||
<script setup lang="ts">
|
|
||||||
import { useRuleEditorStore } from '@/store/ruleEditor'
|
|
||||||
import Editor from './Editor/index.vue'
|
|
||||||
import Advance from './Advance/index.vue'
|
|
||||||
|
|
||||||
interface Props {
|
|
||||||
value: string;
|
|
||||||
property?: string;
|
|
||||||
virtualRule?: any;
|
|
||||||
id?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
const props = defineProps<Props>()
|
|
||||||
|
|
||||||
interface Emits {
|
|
||||||
(e: 'update:value', data: string): void;
|
|
||||||
}
|
|
||||||
|
|
||||||
const emit = defineEmits<Emits>()
|
|
||||||
|
|
||||||
const _value = computed({
|
|
||||||
get: () => props.value,
|
|
||||||
set: (val: string) => {
|
|
||||||
emit('update:value', val)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const ruleEditorStore = useRuleEditorStore()
|
|
||||||
|
|
||||||
const change = (v: string) => {
|
|
||||||
ruleEditorStore.set('model', v);
|
|
||||||
}
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
ruleEditorStore.set('property', props.property)
|
|
||||||
ruleEditorStore.set('code', props.value);
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
<style lang="less" scoped></style>
|
|
|
@ -360,6 +360,13 @@ const runScript = () => {
|
||||||
if (props.virtualRule?.type !== 'window') {
|
if (props.virtualRule?.type !== 'window') {
|
||||||
stopAction();
|
stopAction();
|
||||||
}
|
}
|
||||||
|
}, () => {}, () => {
|
||||||
|
ruleEditorStore.state.log.push({
|
||||||
|
time: new Date().getTime(),
|
||||||
|
content: '运行结束',
|
||||||
|
_time: unref(time.value),
|
||||||
|
});
|
||||||
|
stopAction()
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -83,7 +83,6 @@ export default {
|
||||||
.use(MarkdownItAbbr)
|
.use(MarkdownItAbbr)
|
||||||
.use(MarkdownItAnchor, props.anchor)
|
.use(MarkdownItAnchor, props.anchor)
|
||||||
.use(MarkdownItDeflist)
|
.use(MarkdownItDeflist)
|
||||||
.use(emoji, props.emoji)
|
|
||||||
.use(MarkdownItFootnote)
|
.use(MarkdownItFootnote)
|
||||||
.use(MarkdownItHighlightjs, props.highlight)
|
.use(MarkdownItHighlightjs, props.highlight)
|
||||||
.use(MarkdownItIns)
|
.use(MarkdownItIns)
|
||||||
|
|
|
@ -84,40 +84,48 @@ watch(
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
{ immediate: true, deep: true },
|
{ immediate: true, deep: true },
|
||||||
|
|
||||||
|
|
||||||
);
|
);
|
||||||
|
|
||||||
const productName = computed(() => {
|
const productName = computed(() => {
|
||||||
console.log(modelRef.product);
|
console.log(modelRef.product);
|
||||||
return productList.value.find(item => item.id === modelRef.product)?.name || ''
|
return productList.value.find(item => item.id === modelRef.product)?.name || ''
|
||||||
// console.log(item.id);
|
// console.log(item.id);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const handleOk = async () => {
|
const handleOk = async () => {
|
||||||
const params = paramsEncodeQuery(props.data);
|
const _params = paramsEncodeQuery(props.data);
|
||||||
// downloadFile(
|
// downloadFile(
|
||||||
// deviceExport(modelRef.product || '', modelRef.fileType),
|
// deviceExport(modelRef.product || '', modelRef.fileType),
|
||||||
// params,
|
// params,
|
||||||
// );
|
// );
|
||||||
const res: any = await deviceExport(
|
// const res: any = await deviceExport(
|
||||||
modelRef.product || '',
|
// modelRef.product || '',
|
||||||
modelRef.fileType,
|
// modelRef.fileType,
|
||||||
params
|
// params
|
||||||
|
//
|
||||||
|
//
|
||||||
);
|
// );
|
||||||
if (res) {
|
// if (res) {
|
||||||
// const blob = new Blob([res], { type: modelRef.fileType });
|
// // const blob = new Blob([res], { type: modelRef.fileType });
|
||||||
// const url = URL.createObjectURL(blob);
|
// // const url = URL.createObjectURL(blob);
|
||||||
// downloadFileByUrl(url, `${productName.value ? (productName.value + '下设备') : '设备实例'}`, modelRef.fileType);
|
// // downloadFileByUrl(url, `${productName.value ? (productName.value + '下设备') : '设备实例'}`, modelRef.fileType);
|
||||||
window.open(`${origin}/api/device-instance/${modelRef.product}/export.xlsx?:X_Access_Token=${LocalStore.get(TOKEN_KEY)}`)
|
//
|
||||||
emit('close');
|
// }
|
||||||
}
|
const urlParams = new URLSearchParams()
|
||||||
|
|
||||||
|
Object.keys(_params).forEach(key => {
|
||||||
|
if (_params[key]) {
|
||||||
|
urlParams.append(key, _params[key])
|
||||||
|
}
|
||||||
|
})
|
||||||
|
window.open(`${origin}/api/device-instance/${modelRef.product}/export.xlsx?:X_Access_Token=${LocalStore.get(TOKEN_KEY)}&${urlParams}`)
|
||||||
|
emit('close');
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleCancel = () => {
|
const handleCancel = () => {
|
||||||
|
|
|
@ -327,7 +327,7 @@ const handleClick = (data: any) => {
|
||||||
const add = () => {
|
const add = () => {
|
||||||
const url = menuStore.hasMenu('link/AccessConfig/Detail');
|
const url = menuStore.hasMenu('link/AccessConfig/Detail');
|
||||||
if (url) {
|
if (url) {
|
||||||
const tab: any = window.open(`${origin}/#${url}?view=false&save=true`);
|
const tab: any = window.open(`${window.location.origin + window.location.pathname}#${url}?view=false`);
|
||||||
tab.onTabSaveSuccess = (value: any) => {
|
tab.onTabSaveSuccess = (value: any) => {
|
||||||
if (value.status === 200) {
|
if (value.status === 200) {
|
||||||
tableRef.value.reload();
|
tableRef.value.reload();
|
||||||
|
|
|
@ -180,8 +180,8 @@ export const useColumns = (type?: MetadataType, target?: 'device' | 'product', n
|
||||||
},
|
},
|
||||||
{ max: 64, message: '最多可输入64个字符' },
|
{ max: 64, message: '最多可输入64个字符' },
|
||||||
{
|
{
|
||||||
pattern: /^[a-zA-Z0-9_\-]+$/,
|
pattern: /^[a-zA-Z0-9_]+$/,
|
||||||
message: '标识只能由数字、字母、下划线、中划线组成',
|
message: '标识只能由数字、字母、下划线组成',
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,238 +1,295 @@
|
||||||
<template>
|
<template>
|
||||||
<j-popconfirm-modal
|
<j-popconfirm-modal
|
||||||
body-style="padding-top:4px;width:600px;"
|
v-if="!disabled"
|
||||||
placement="bottomRight"
|
body-style="padding-top:4px;width:600px;"
|
||||||
:disabled="disabled"
|
placement="bottomRight"
|
||||||
:get-popup-container="(node) => fullRef || node"
|
:disabled="disabled"
|
||||||
@confirm="confirm"
|
:get-popup-container="(node) => fullRef || node"
|
||||||
@cancel="cancel"
|
@confirm="confirm"
|
||||||
@visibleChange="visibleChange"
|
@cancel="cancel"
|
||||||
>
|
@visibleChange="visibleChange"
|
||||||
<template v-if="visible" #content>
|
>
|
||||||
<j-scrollbar height="350" v-if="showMetrics || config.length > 0">
|
<template v-if="visible" #content>
|
||||||
<j-collapse v-model:activeKey="activeKey">
|
<j-scrollbar height="350" v-if="showMetrics || config.length > 0">
|
||||||
<j-collapse-panel v-for="(item, index) in config" :key="'store_'+index" :header="item.name">
|
<j-collapse v-model:activeKey="activeKey">
|
||||||
<j-table
|
<j-collapse-panel
|
||||||
:columns="columns"
|
v-for="(item, index) in config"
|
||||||
:data-source="item.properties"
|
:key="'store_' + index"
|
||||||
:pagination="false"
|
:header="item.name"
|
||||||
rowKey="id"
|
>
|
||||||
>
|
<j-table
|
||||||
<template #bodyCell="{ column, record, index }">
|
:columns="columns"
|
||||||
<template v-if="column.dataIndex === 'type'">{{ record.type?.name }}</template>
|
:data-source="item.properties"
|
||||||
<value-item
|
:pagination="false"
|
||||||
v-else-if="column.dataIndex === 'value'"
|
rowKey="id"
|
||||||
v-model:modelValue="configValue[record.property]"
|
>
|
||||||
:itemType="item.properties[index].type?.type"
|
<template #bodyCell="{ column, record, index }">
|
||||||
:options="(item.properties[index].type?.elements || []).map((a:any) => ({
|
<template v-if="column.dataIndex === 'type'">{{
|
||||||
|
record.type?.name
|
||||||
|
}}</template>
|
||||||
|
<value-item
|
||||||
|
v-else-if="column.dataIndex === 'value'"
|
||||||
|
v-model:modelValue="
|
||||||
|
configValue[record.property]
|
||||||
|
"
|
||||||
|
:itemType="
|
||||||
|
item.properties[index].type?.type
|
||||||
|
"
|
||||||
|
:options="(item.properties[index].type?.elements || []).map((a:any) => ({
|
||||||
label: a.text,
|
label: a.text,
|
||||||
value: a.value,
|
value: a.value,
|
||||||
}))"
|
}))"
|
||||||
:get-popup-container="(node) => fullRef || node"
|
:get-popup-container="
|
||||||
/>
|
(node) => fullRef || node
|
||||||
</template>
|
"
|
||||||
</j-table>
|
/>
|
||||||
</j-collapse-panel>
|
</template>
|
||||||
<j-collapse-panel key="metrics" v-if="showMetrics">
|
</j-table>
|
||||||
<template #header>
|
</j-collapse-panel>
|
||||||
指标配置
|
<j-collapse-panel key="metrics" v-if="showMetrics">
|
||||||
<j-tooltip title="场景联动页面可引用指标配置作为触发条件">
|
<template #header>
|
||||||
<AIcon type="ExclamationCircleOutlined" style="padding-left: 12px;padding-top: 4px;" />
|
指标配置
|
||||||
</j-tooltip>
|
<j-tooltip
|
||||||
</template>
|
title="场景联动页面可引用指标配置作为触发条件"
|
||||||
<Metrics ref="metricsRef" :options="booleanOptions" :type="props.type" :value="myValue.metrics"/>
|
>
|
||||||
</j-collapse-panel>
|
<AIcon
|
||||||
</j-collapse>
|
type="ExclamationCircleOutlined"
|
||||||
|
style="padding-left: 12px; padding-top: 4px"
|
||||||
</j-scrollbar>
|
/>
|
||||||
<div v-else style="padding-top: 24px">
|
</j-tooltip>
|
||||||
<j-empty
|
</template>
|
||||||
description="没有动态配置项"
|
<Metrics
|
||||||
/>
|
ref="metricsRef"
|
||||||
</div>
|
:options="booleanOptions"
|
||||||
</template>
|
:type="props.type"
|
||||||
|
:value="myValue.metrics"
|
||||||
|
/>
|
||||||
|
</j-collapse-panel>
|
||||||
|
</j-collapse>
|
||||||
|
</j-scrollbar>
|
||||||
|
<div v-else style="padding-top: 24px">
|
||||||
|
<j-empty description="没有动态配置项" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<PermissionButton
|
||||||
|
key="setting"
|
||||||
|
:disabled="disabled"
|
||||||
|
:has-permission="hasPermission"
|
||||||
|
:tooltip="tooltip"
|
||||||
|
style="padding-left: 0"
|
||||||
|
type="link"
|
||||||
|
>
|
||||||
|
<AIcon type="SettingOutlined" />
|
||||||
|
配置
|
||||||
|
</PermissionButton>
|
||||||
|
</j-popconfirm-modal>
|
||||||
<PermissionButton
|
<PermissionButton
|
||||||
|
v-else
|
||||||
key="setting"
|
key="setting"
|
||||||
:disabled="disabled"
|
:disabled="disabled"
|
||||||
:has-permission="hasPermission"
|
:has-permission="hasPermission"
|
||||||
:tooltip="tooltip"
|
:tooltip="tooltip"
|
||||||
style="padding-left: 0;"
|
style="padding-left: 0"
|
||||||
type="link"
|
type="link"
|
||||||
>
|
>
|
||||||
<AIcon type="SettingOutlined" />
|
<AIcon type="SettingOutlined" />
|
||||||
配置
|
配置
|
||||||
</PermissionButton>
|
</PermissionButton>
|
||||||
</j-popconfirm-modal>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts" name="OtherSetting">
|
<script setup lang="ts" name="OtherSetting">
|
||||||
import Metrics from './Metrics/Metrics.vue'
|
import Metrics from './Metrics/Metrics.vue';
|
||||||
import {watch} from "vue";
|
import { watch } from 'vue';
|
||||||
import {useProductStore} from "store/product";
|
import { useProductStore } from 'store/product';
|
||||||
import {useInstanceStore} from "store/instance";
|
import { useInstanceStore } from 'store/instance';
|
||||||
import {getMetadataConfig, getMetadataDeviceConfig} from "@/api/device/product";
|
import {
|
||||||
import ModelButton from '@/views/device/components/Metadata/Base/components/ModelButton.vue'
|
getMetadataConfig,
|
||||||
import { omit , cloneDeep} from "lodash-es";
|
getMetadataDeviceConfig,
|
||||||
import { FULL_CODE } from 'jetlinks-ui-components/es/DataTable'
|
} from '@/api/device/product';
|
||||||
|
import ModelButton from '@/views/device/components/Metadata/Base/components/ModelButton.vue';
|
||||||
|
import { omit, cloneDeep } from 'lodash-es';
|
||||||
|
import { FULL_CODE } from 'jetlinks-ui-components/es/DataTable';
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
value: {
|
value: {
|
||||||
type: Object,
|
type: Object,
|
||||||
default: () => ({})
|
default: () => ({}),
|
||||||
},
|
},
|
||||||
type: {
|
type: {
|
||||||
type: String,
|
type: String,
|
||||||
default: undefined
|
default: undefined,
|
||||||
},
|
},
|
||||||
disabled: {
|
disabled: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false
|
default: false,
|
||||||
},
|
},
|
||||||
id: {
|
id: {
|
||||||
type: String,
|
type: String,
|
||||||
default: undefined
|
default: undefined,
|
||||||
},
|
},
|
||||||
record: {
|
record: {
|
||||||
type: Object,
|
type: Object,
|
||||||
default: () => ({})
|
default: () => ({}),
|
||||||
},
|
},
|
||||||
hasPermission: String,
|
hasPermission: String,
|
||||||
tooltip: Object
|
tooltip: Object,
|
||||||
})
|
});
|
||||||
|
|
||||||
const fullRef = inject(FULL_CODE);
|
const fullRef = inject(FULL_CODE);
|
||||||
|
|
||||||
const type = inject('_metadataType')
|
const type = inject('_metadataType');
|
||||||
|
|
||||||
const productStore = useProductStore()
|
const productStore = useProductStore();
|
||||||
const deviceStore = useInstanceStore()
|
const deviceStore = useInstanceStore();
|
||||||
|
|
||||||
const emit = defineEmits(['update:value'])
|
const emit = defineEmits(['update:value']);
|
||||||
|
|
||||||
const activeKey = ref()
|
const activeKey = ref();
|
||||||
const storageRef = ref()
|
const storageRef = ref();
|
||||||
const metricsRef = ref()
|
const metricsRef = ref();
|
||||||
|
|
||||||
const myValue = ref(props.value)
|
const myValue = ref(props.value);
|
||||||
const visible = ref(false)
|
const visible = ref(false);
|
||||||
|
|
||||||
const config = ref<any>([])
|
const config = ref<any>([]);
|
||||||
const configValue = ref(props.value?.expands)
|
const configValue = ref(props.value?.expands);
|
||||||
|
|
||||||
const showMetrics = computed(() => {
|
const showMetrics = computed(() => {
|
||||||
return ['int', 'long', 'float', 'double', 'string', 'boolean', 'date'].includes(props.type as any)
|
return [
|
||||||
})
|
'int',
|
||||||
|
'long',
|
||||||
|
'float',
|
||||||
|
'double',
|
||||||
|
'string',
|
||||||
|
'boolean',
|
||||||
|
'date',
|
||||||
|
].includes(props.type as any);
|
||||||
|
});
|
||||||
|
|
||||||
const booleanOptions = ref([
|
const booleanOptions = ref([
|
||||||
{ label: '否', value: 'false'},
|
{ label: '否', value: 'false' },
|
||||||
{ label: '是', value: 'true'},
|
{ label: '是', value: 'true' },
|
||||||
])
|
]);
|
||||||
|
|
||||||
const columns = ref([
|
const columns = ref([
|
||||||
{
|
{
|
||||||
title: '参数名称',
|
title: '参数名称',
|
||||||
dataIndex: 'name',
|
dataIndex: 'name',
|
||||||
width: 150,
|
width: 150,
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '输入类型',
|
title: '输入类型',
|
||||||
dataIndex: 'type',
|
dataIndex: 'type',
|
||||||
width: 150,
|
width: 150,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '值',
|
title: '值',
|
||||||
dataIndex: 'value',
|
dataIndex: 'value',
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const getConfig = async () => {
|
const getConfig = async () => {
|
||||||
const id = type === 'product' ? productStore.current?.id : deviceStore.current.id
|
const id =
|
||||||
console.log(props.id, id, props)
|
type === 'product' ? productStore.current?.id : deviceStore.current.id;
|
||||||
|
console.log(props.id, id, props);
|
||||||
|
|
||||||
if(!props.id || !id || !props.type) return
|
if (!props.id || !id || !props.type) return;
|
||||||
|
|
||||||
if (props.type === 'boolean') {
|
if (props.type === 'boolean') {
|
||||||
const booleanValue = props.record.valueType
|
const booleanValue = props.record.valueType;
|
||||||
booleanOptions.value[0] = { label: booleanValue.falseText || '否', value: booleanValue.falseValue || 'false'}
|
booleanOptions.value[0] = {
|
||||||
booleanOptions.value[1] = { label: booleanValue.trueText || '是', value: booleanValue.trueValue || 'true'}
|
label: booleanValue.falseText || '否',
|
||||||
}
|
value: booleanValue.falseValue || 'false',
|
||||||
|
};
|
||||||
const params: any = {
|
booleanOptions.value[1] = {
|
||||||
deviceId: id,
|
label: booleanValue.trueText || '是',
|
||||||
metadata: {
|
value: booleanValue.trueValue || 'true',
|
||||||
id: props.id,
|
};
|
||||||
type: 'property',
|
|
||||||
dataType: props.type,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
const resp = type === 'product' ? await getMetadataConfig(params) : await getMetadataDeviceConfig(params)
|
|
||||||
if (resp.status === 200) {
|
|
||||||
|
|
||||||
config.value = resp.result
|
|
||||||
if (resp.result.length) {
|
|
||||||
activeKey.value = ['store_0']
|
|
||||||
} else if (showMetrics.value) {
|
|
||||||
activeKey.value = ['metrics']
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (resp.result.length && !configValue.value) {
|
const params: any = {
|
||||||
resp.result.forEach(a => {
|
deviceId: id,
|
||||||
if (a.properties) {
|
metadata: {
|
||||||
a.properties.forEach(b => {
|
id: props.id,
|
||||||
configValue.value[b.property] = undefined
|
type: 'property',
|
||||||
})
|
dataType: props.type,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const resp =
|
||||||
|
type === 'product'
|
||||||
|
? await getMetadataConfig(params)
|
||||||
|
: await getMetadataDeviceConfig(params);
|
||||||
|
if (resp.status === 200) {
|
||||||
|
config.value = resp.result;
|
||||||
|
if (resp.result.length) {
|
||||||
|
activeKey.value = ['store_0'];
|
||||||
|
} else if (showMetrics.value) {
|
||||||
|
activeKey.value = ['metrics'];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (resp.result.length && !configValue.value) {
|
||||||
|
resp.result.forEach((a) => {
|
||||||
|
if (a.properties) {
|
||||||
|
a.properties.forEach((b) => {
|
||||||
|
configValue.value[b.property] = undefined;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
}
|
|
||||||
|
|
||||||
const confirm = () => {
|
const confirm = () => {
|
||||||
|
return new Promise(async (resolve, reject) => {
|
||||||
|
try {
|
||||||
|
let metrics: any;
|
||||||
|
metrics = await metricsRef.value?.getData();
|
||||||
|
|
||||||
return new Promise(async (resolve, reject) => {
|
const expands = {
|
||||||
try {
|
...(configValue.value || {}),
|
||||||
let metrics: any
|
};
|
||||||
metrics = await metricsRef.value?.getData()
|
|
||||||
|
|
||||||
const expands = {
|
if (metrics) {
|
||||||
...(configValue.value || {}),
|
expands.metrics = metrics;
|
||||||
}
|
}
|
||||||
|
emit('update:value', {
|
||||||
if (metrics) {
|
...props.value,
|
||||||
expands.metrics = metrics
|
...expands,
|
||||||
}
|
});
|
||||||
emit('update:value', {
|
resolve(true);
|
||||||
...props.value,
|
} catch (err) {
|
||||||
...expands
|
reject(false);
|
||||||
})
|
}
|
||||||
resolve(true)
|
});
|
||||||
} catch (err) {
|
};
|
||||||
reject(false)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const visibleChange = (e: boolean) => {
|
const visibleChange = (e: boolean) => {
|
||||||
visible.value = e
|
visible.value = e;
|
||||||
if (e) {
|
if (e) {
|
||||||
configValue.value = omit(props.value, ['source', 'type', 'metrics', 'required'])
|
configValue.value = omit(props.value, [
|
||||||
getConfig()
|
'source',
|
||||||
}
|
'type',
|
||||||
}
|
'metrics',
|
||||||
|
'required',
|
||||||
|
]);
|
||||||
|
getConfig();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const cancel = () => {
|
const cancel = () => {
|
||||||
myValue.value = cloneDeep(props.value)
|
myValue.value = cloneDeep(props.value);
|
||||||
}
|
};
|
||||||
|
|
||||||
watch(() => props.value, () => {
|
|
||||||
console.log(props.value)
|
|
||||||
myValue.value = cloneDeep(props.value)
|
|
||||||
}, {immediate: true, deep: true})
|
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.value,
|
||||||
|
() => {
|
||||||
|
console.log(props.value);
|
||||||
|
myValue.value = cloneDeep(props.value);
|
||||||
|
},
|
||||||
|
{ immediate: true, deep: true },
|
||||||
|
);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped></style>
|
||||||
|
|
||||||
</style>
|
|
||||||
|
|
|
@ -313,7 +313,7 @@ const getDataTotal = () => {
|
||||||
yearTotal.value = resp.sortArray
|
yearTotal.value = resp.sortArray
|
||||||
.reduce((r, n) => r + Number(n.value), 0)
|
.reduce((r, n) => r + Number(n.value), 0)
|
||||||
.toFixed(2);
|
.toFixed(2);
|
||||||
yearOptions.value = monthOptions.value;
|
yearOptions.value = resp.sortArray;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -164,8 +164,13 @@ const onDelete = () => {
|
||||||
|
|
||||||
const onDeleteAll = () => {
|
const onDeleteAll = () => {
|
||||||
if (FormModel.value.branches) {
|
if (FormModel.value.branches) {
|
||||||
|
// FormModel.value.branches.length = props.name
|
||||||
|
// FormModel.value.branches.push(null as any)
|
||||||
FormModel.value.branches[props.name].when = []
|
FormModel.value.branches[props.name].when = []
|
||||||
FormModel.value.options.when[props.branches_Index].terms = []
|
FormModel.value.options.when[props.branches_Index].terms = []
|
||||||
|
if(FormModel.value.branches[props.name + 1] === null){
|
||||||
|
FormModel.value.branches.splice(props.name + 1 , 1)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -199,7 +204,9 @@ const addWhen = () => {
|
||||||
key: `terms_${randomString()}`
|
key: `terms_${randomString()}`
|
||||||
}
|
}
|
||||||
FormModel.value.branches?.[props.name].when?.push(terms)
|
FormModel.value.branches?.[props.name].when?.push(terms)
|
||||||
FormModel.value.branches?.splice(props.groupLen, 0, null)
|
if(FormModel.value.branches?.length <= props.name + 1){
|
||||||
|
FormModel.value.branches?.splice(props.groupLen, 0, null)
|
||||||
|
}
|
||||||
FormModel.value.options!.when[props.branches_Index]?.terms.push({ termType: '并且', terms: [['','eq','','and']]})
|
FormModel.value.options!.when[props.branches_Index]?.terms.push({ termType: '并且', terms: [['','eq','','and']]})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="button-mange-container">
|
<div class="button-mange-container">
|
||||||
<j-pro-table
|
<j-pro-table
|
||||||
ref="tableRef"
|
ref="tableRef"
|
||||||
:columns="table.columns"
|
:columns="table.columns"
|
||||||
model="TABLE"
|
model="TABLE"
|
||||||
|
@ -46,7 +46,7 @@
|
||||||
</PermissionButton>
|
</PermissionButton>
|
||||||
</j-space>
|
</j-space>
|
||||||
</template>
|
</template>
|
||||||
</j-pro-table>
|
</j-pro-table>
|
||||||
|
|
||||||
<div class="dialog">
|
<div class="dialog">
|
||||||
<ButtonAddDialog
|
<ButtonAddDialog
|
||||||
|
@ -110,6 +110,7 @@ const table = reactive({
|
||||||
title: '说明',
|
title: '说明',
|
||||||
dataIndex: 'description',
|
dataIndex: 'description',
|
||||||
key: 'description',
|
key: 'description',
|
||||||
|
ellipsis: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '操作',
|
title: '操作',
|
||||||
|
|
|
@ -328,7 +328,7 @@ export const handleSorts = (node: any[]) => {
|
||||||
if (!node) return []
|
if (!node) return []
|
||||||
return node.map((item, index) => {
|
return node.map((item, index) => {
|
||||||
if (item.index !== index) {
|
if (item.index !== index) {
|
||||||
item.sortIndex = index
|
item.sortIndex = index + 1
|
||||||
if (item.children) {
|
if (item.children) {
|
||||||
item.children = handleSorts(item.children).sort((a, b) => a.sortIndex - b.sortIndex)
|
item.children = handleSorts(item.children).sort((a, b) => a.sortIndex - b.sortIndex)
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,7 +63,10 @@
|
||||||
:btnId="form.data.id"
|
:btnId="form.data.id"
|
||||||
/>
|
/>
|
||||||
</j-form-item>
|
</j-form-item>
|
||||||
<j-form-item label="说明" name="description">
|
<j-form-item label="说明" name="description"
|
||||||
|
:rules="[
|
||||||
|
{ max: 200, message: '最多可输入200个字符' },
|
||||||
|
]">
|
||||||
<j-textarea
|
<j-textarea
|
||||||
v-model:value="form.data.description"
|
v-model:value="form.data.description"
|
||||||
:rows="4"
|
:rows="4"
|
||||||
|
@ -147,7 +150,7 @@ const codeOptions = [
|
||||||
{ label: 'update', value: 'update', message: '更新' },
|
{ label: 'update', value: 'update', message: '更新' },
|
||||||
];
|
];
|
||||||
const validateIdRepeat = (rule: any, val: any) => {
|
const validateIdRepeat = (rule: any, val: any) => {
|
||||||
if (props.mode === '编辑') {
|
if (props.mode === '编辑'|| props.mode === '查看') {
|
||||||
return Promise.resolve('');
|
return Promise.resolve('');
|
||||||
}
|
}
|
||||||
const isRepeat = props.menuData.find((i: any) => {
|
const isRepeat = props.menuData.find((i: any) => {
|
||||||
|
|
|
@ -14,7 +14,9 @@
|
||||||
:params="queryParams"
|
:params="queryParams"
|
||||||
:rowSelection="{
|
:rowSelection="{
|
||||||
selectedRowKeys: selectedRowKeys,
|
selectedRowKeys: selectedRowKeys,
|
||||||
onChange: (keys:string[])=>selectedRowKeys = keys,
|
onSelect: onSelectChange,
|
||||||
|
onSelectAll: selectAll,
|
||||||
|
onSelectNone: () => (selectedRowKeys = []),
|
||||||
}"
|
}"
|
||||||
size="small"
|
size="small"
|
||||||
>
|
>
|
||||||
|
@ -26,6 +28,7 @@
|
||||||
<PermissionButton
|
<PermissionButton
|
||||||
:popConfirm="{
|
:popConfirm="{
|
||||||
title: `是否批量解除绑定`,
|
title: `是否批量解除绑定`,
|
||||||
|
placement: 'topRight',
|
||||||
onConfirm: () => table.unbind(),
|
onConfirm: () => table.unbind(),
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
|
@ -181,9 +184,37 @@ const table = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const onSelectChange = (item: any, state: boolean) => {
|
||||||
|
const arr = new Set(selectedRowKeys.value);
|
||||||
|
if (state) {
|
||||||
|
arr.add(item.id);
|
||||||
|
} else {
|
||||||
|
arr.delete(item.id);
|
||||||
|
}
|
||||||
|
selectedRowKeys.value = [...arr.values()];
|
||||||
|
};
|
||||||
|
|
||||||
|
const selectAll = (selected: Boolean, selectedRows: any, changeRows: any) => {
|
||||||
|
if (selected) {
|
||||||
|
changeRows.map((i: any) => {
|
||||||
|
if (!selectedRowKeys.value.includes(i.id)) {
|
||||||
|
selectedRowKeys.value.push(i.id);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
const arr = changeRows.map((item: any) => item.id);
|
||||||
|
const _ids: string[] = [];
|
||||||
|
selectedRowKeys.value.map((i: any) => {
|
||||||
|
if (!arr.includes(i)) {
|
||||||
|
_ids.push(i);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
selectedRowKeys.value = _ids;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// 弹窗相关
|
// 弹窗相关
|
||||||
const dialogVisible = ref(false);
|
const dialogVisible = ref(false);
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
|
|
@ -53,10 +53,11 @@ import { FormInstance } from 'ant-design-vue';
|
||||||
import { saveRole_api , queryRoleGroup , updateRole_api} from '@/api/system/role';
|
import { saveRole_api , queryRoleGroup , updateRole_api} from '@/api/system/role';
|
||||||
import { useMenuStore } from '@/store/menu';
|
import { useMenuStore } from '@/store/menu';
|
||||||
import { onlyMessage } from '@/utils/comm';
|
import { onlyMessage } from '@/utils/comm';
|
||||||
|
import { cloneDeep } from 'lodash-es'
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const { jumpPage } = useMenuStore();
|
const { jumpPage } = useMenuStore();
|
||||||
|
|
||||||
const emits = defineEmits(['update:visible']);
|
const emits = defineEmits(['update:visible','refresh']);
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
visible: {
|
visible: {
|
||||||
type:Boolean,
|
type:Boolean,
|
||||||
|
@ -107,6 +108,7 @@ const confirm = async() => {
|
||||||
updateRole_api(form.value).then((resp:any)=>{
|
updateRole_api(form.value).then((resp:any)=>{
|
||||||
if (resp.status === 200) {
|
if (resp.status === 200) {
|
||||||
onlyMessage('操作成功');
|
onlyMessage('操作成功');
|
||||||
|
emits('refresh');
|
||||||
emits('update:visible', false);
|
emits('update:visible', false);
|
||||||
}
|
}
|
||||||
}).catch(() => (loading.value = false));
|
}).catch(() => (loading.value = false));
|
||||||
|
@ -131,7 +133,8 @@ onMounted(()=>{
|
||||||
getGroupOptions()
|
getGroupOptions()
|
||||||
form.value.groupId = props.groupId
|
form.value.groupId = props.groupId
|
||||||
if(props.modalType === 'edit'){
|
if(props.modalType === 'edit'){
|
||||||
form.value = props.current
|
// Object.assign(form.value,props.current)
|
||||||
|
form.value=cloneDeep(props.current)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -34,8 +34,10 @@
|
||||||
</j-pro-table>
|
</j-pro-table>
|
||||||
</FullPage>
|
</FullPage>
|
||||||
|
|
||||||
<AddDialog v-if="dialogVisible" v-model:visible="dialogVisible" :groupId="groupId" :modalType="modalType"
|
<AddDialog v-if="dialogVisible" v-model:visible="dialogVisible" :groupId="groupId" :modalType="modalType"
|
||||||
:current="current" />
|
:current="current"
|
||||||
|
@refresh="tableRef?.reload()"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
|
@ -140,6 +142,7 @@ const getActions = (
|
||||||
},
|
},
|
||||||
popConfirm: {
|
popConfirm: {
|
||||||
title: '确认删除?',
|
title: '确认删除?',
|
||||||
|
placement:'topRight',
|
||||||
onConfirm: async () => {
|
onConfirm: async () => {
|
||||||
const res = await delRole_api(data.id)
|
const res = await delRole_api(data.id)
|
||||||
if (res.status === 200) {
|
if (res.status === 200) {
|
||||||
|
|
|
@ -186,11 +186,11 @@ const columns = [
|
||||||
key: 'roleList',
|
key: 'roleList',
|
||||||
search:{
|
search:{
|
||||||
type:'select',
|
type:'select',
|
||||||
rename:'id$in-dimension$role',
|
// rename:'id$in-dimension$role',
|
||||||
options:() =>
|
options:() =>
|
||||||
new Promise((resolve)=>{
|
new Promise((resolve)=>{
|
||||||
queryRole_api(
|
queryRole_api(
|
||||||
{
|
{
|
||||||
paging:false,
|
paging:false,
|
||||||
sorts: [
|
sorts: [
|
||||||
{ name: 'createTime', order: 'desc' },
|
{ name: 'createTime', order: 'desc' },
|
||||||
|
@ -303,37 +303,60 @@ type dictType = {
|
||||||
type modalType = '' | 'add' | 'edit' | 'reset';
|
type modalType = '' | 'add' | 'edit' | 'reset';
|
||||||
|
|
||||||
const handleParams = (params: any) => {
|
const handleParams = (params: any) => {
|
||||||
const newParams = (params?.terms as any[])?.map((item1) => {
|
const newParams = (params?.terms as any[])?.map((termsGroupA) => {
|
||||||
let arr: any[] = []
|
let arr: any[] = []
|
||||||
item1.terms = item1.terms.map((item2: any) => {
|
termsGroupA.terms = termsGroupA.terms.map((termsItem: any) => {
|
||||||
if (['telephone', 'email'].includes(item2.column)) {
|
|
||||||
|
if (termsItem.column === 'id$in-dimension$role') {
|
||||||
|
let _termType = termsItem.termType === 'nin' ? 'not$in' : termsItem.termType
|
||||||
|
termsItem.column = `${termsItem.column}$${_termType}`
|
||||||
|
delete termsItem.termType
|
||||||
|
}
|
||||||
|
if (['telephone', 'email'].includes(termsItem.column)) {
|
||||||
return {
|
return {
|
||||||
column: 'id$user-detail',
|
column: 'id$user-detail',
|
||||||
value: [item2],
|
value: [termsItem],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
if (['type'].includes(item2.column) && item2.value === 'other') {
|
if (['type'].includes(termsItem.column) && termsItem.value === 'other') {
|
||||||
arr = [
|
arr = [
|
||||||
{
|
{
|
||||||
...item2,
|
...termsItem,
|
||||||
type: 'or',
|
type: 'or',
|
||||||
termType: 'isnull',
|
termType: 'isnull',
|
||||||
value: 1,
|
value: 1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
...item2,
|
...termsItem,
|
||||||
type: 'or',
|
type: 'or',
|
||||||
termType: 'empty',
|
termType: 'empty',
|
||||||
value: 1,
|
value: 1,
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
return item2;
|
if(termsItem.column === 'roleList'){
|
||||||
|
if(termsItem.termType === 'eq' || termsItem.termType === 'in'){
|
||||||
|
return {
|
||||||
|
column: 'id$in-dimension$role',
|
||||||
|
type: termsItem.type,
|
||||||
|
value: termsItem.value
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
return {
|
||||||
|
column: 'id$in-dimension$role$not',
|
||||||
|
type: termsItem.type,
|
||||||
|
value: termsItem.value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return termsItem;
|
||||||
});
|
});
|
||||||
|
|
||||||
if(arr.length){
|
if(arr.length){
|
||||||
item1.terms = [...item1.terms, ...arr]
|
termsGroupA.terms = [...termsGroupA.terms, ...arr]
|
||||||
}
|
}
|
||||||
return item1;
|
|
||||||
|
return termsGroupA;
|
||||||
});
|
});
|
||||||
queryParams.value = { terms: newParams || [] };
|
queryParams.value = { terms: newParams || [] };
|
||||||
};
|
};
|
||||||
|
|
|
@ -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.32.66:8800', // 本地开发环境
|
target: 'http://192.168.33.46:8844', // 本地开发环境
|
||||||
// target: 'http://192.168.32.167:8844', // 本地开发环境1
|
// target: 'http://192.168.32.167:8844', // 本地开发环境1
|
||||||
// target: 'http://192.168.33.1:8848', // 社区版开发环境
|
// target: 'http://192.168.33.1:8848', // 社区版开发环境
|
||||||
// target: 'http://192.168.32.207:8844', // 刘本地
|
// target: 'http://192.168.32.207:8844', // 刘本地
|
||||||
|
|
Loading…
Reference in New Issue