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

This commit is contained in:
jackhoo_98 2023-03-28 14:37:55 +08:00
commit 551863ba2f
21 changed files with 199 additions and 92 deletions

View File

@ -1,5 +1,11 @@
<template> <template>
<pro-search class="device-search" type="simple" :columns="columns" target="device-instance-running-events" @search="handleSearch" /> <pro-search
class="device-search"
type="simple"
:columns="columns"
target="device-instance-running-events"
@search="handleSearch"
/>
<JProTable <JProTable
ref="eventsRef" ref="eventsRef"
:columns="columns" :columns="columns"
@ -17,13 +23,18 @@
</j-button> </j-button>
</template> </template>
</JProTable> </JProTable>
<j-modal :width="600" v-model:visible="visible" title="详情" class="device-running-event-modal">
<JsonViewer :value="info" />
<template #footer>
<j-button type="primary" @click="visible = false">关闭</j-button>
</template>
</j-modal>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import { getEventList } from '@/api/device/instance'; import { getEventList } from '@/api/device/instance';
import { useInstanceStore } from '@/store/instance'; import { useInstanceStore } from '@/store/instance';
import { Modal } from 'jetlinks-ui-components';
import JsonViewer from 'vue-json-viewer'; import JsonViewer from 'vue-json-viewer';
const events = defineProps({ const events = defineProps({
@ -52,13 +63,11 @@ const columns = ref<Record<string, any>>([
}, },
]); ]);
const params = ref<Record<string, any>>({}); const params = ref<Record<string, any>>({});
const visible = ref<boolean>(false);
const info = ref<Record<string, any>>({});
const _getEventList = (_params: any) => const _getEventList = (_params: any) =>
getEventList( getEventList(instanceStore.current.id || '', events.data.id || '', _params);
instanceStore.current.id || '',
events.data.id || '',
_params
);
watchEffect(() => { watchEffect(() => {
if (events.data?.valueType?.type === 'object') { if (events.data?.valueType?.type === 'object') {
@ -69,7 +78,7 @@ watchEffect(() => {
dataIndex: `${i.id}_format`, dataIndex: `${i.id}_format`,
search: { search: {
type: i?.valueType?.type || 'string', type: i?.valueType?.type || 'string',
} },
}); });
}); });
} else { } else {
@ -85,20 +94,28 @@ const handleSearch = (_params: any) => {
}; };
const detail = (_info: any) => { const detail = (_info: any) => {
Modal.info({ info.value = _info
title: () => '详情', visible.value = true
width: 850, // Modal.info({
content: () => h('JsonViewer', { // title: () => '',
'expand-depth': 5, // width: 850,
value: _info // content: () => h('JsonViewer', {
}), // 'expand-depth': 5,
okText: '关闭', // value: _info
}); // }),
// okText: '',
// });
}; };
</script> </script>
<style lang="less"> <style lang="less">
.device-search { .device-search {
margin: 0 0 24px 0 ; margin: 0 0 24px 0;
}
.device-running-event-modal {
.ant-modal-body {
padding: 0 20px;
}
} }
</style> </style>

View File

@ -13,7 +13,7 @@
<j-row type="flex"> <j-row type="flex">
<j-col flex="180px"> <j-col flex="180px">
<j-form-item name="photoUrl"> <j-form-item name="photoUrl">
<JProUpload v-model="modelRef.photoUrl" /> <JProUpload accept="image/*" v-model="modelRef.photoUrl" />
</j-form-item> </j-form-item>
</j-col> </j-col>
<j-col flex="auto"> <j-col flex="auto">

View File

@ -5,9 +5,16 @@
<template #title> <template #title>
<div style="display: flex"> <div style="display: flex">
<h3>配置信息</h3> <h3>配置信息</h3>
<div style="margin: 0 0px 0 15px; color: #1d39c4"> <!-- <div style="margin: 0 0px 0 15px; color: #1d39c4">
<AIcon type="EditOutlined" @click="editConfig"/> <AIcon type="EditOutlined" @click="editConfig" />
</div> </div> -->
<PermissionButton
type="link"
@click="editConfig"
hasPermission="device/Product:update"
>
<template #icon><AIcon type="EditOutlined" /></template>
</PermissionButton>
</div> </div>
</template> </template>

View File

@ -13,7 +13,7 @@
<j-row type="flex"> <j-row type="flex">
<j-col flex="180px"> <j-col flex="180px">
<j-form-item name="photoUrl"> <j-form-item name="photoUrl">
<JProUpload v-model="modelRef.photoUrl" /> <JProUpload accept="image/*" v-model="modelRef.photoUrl" />
</j-form-item> </j-form-item>
</j-col> </j-col>
<j-col flex="auto"> <j-col flex="auto">

View File

@ -245,12 +245,6 @@ export default {
url: '/iot/link/protocol', url: '/iot/link/protocol',
buttons: [ buttons: [
{ id: 'view', name: '查看', enabled: true, granted: true }, { id: 'view', name: '查看', enabled: true, granted: true },
{
id: 'action',
name: '启/禁用',
enabled: true,
granted: true,
},
{ id: 'delete', name: '删除', enabled: true, granted: true }, { id: 'delete', name: '删除', enabled: true, granted: true },
{ {
id: 'update', id: 'update',
@ -651,12 +645,6 @@ export default {
url: '/iot/link/protocol', url: '/iot/link/protocol',
buttons: [ buttons: [
{ id: 'view', name: '查看', enabled: true, granted: true }, { id: 'view', name: '查看', enabled: true, granted: true },
{
id: 'action',
name: '启/禁用',
enabled: true,
granted: true,
},
{ id: 'delete', name: '删除', enabled: true, granted: true }, { id: 'delete', name: '删除', enabled: true, granted: true },
{ {
id: 'update', id: 'update',

View File

@ -1364,6 +1364,16 @@ export default [
}, },
], ],
}, },
{
id: 'action',
name: '启/禁用',
permissions: [
{
permission: 'firmware-upgrade-task-manager',
actions: ['save'],
}
],
},
], ],
accessSupport: { text: "不支持", value: "unsupported" }, accessSupport: { text: "不支持", value: "unsupported" },
supportDataAccess: false supportDataAccess: false

View File

@ -2,8 +2,21 @@
<template> <template>
<page-container> <page-container>
<pro-search :columns="columns" target="recharge-search" @search="handleSearch" /> <pro-search :columns="columns" target="recharge-search" @search="handleSearch" />
<j-pro-table ref="rechargeRef" :columns="columns" :request="queryRechargeList" model="TABLE" <j-pro-table
:defaultParams="{ sorts: [{ name: 'createTime', order: 'desc' }] }" :params="params"> ref="rechargeRef"
:columns="columns"
:request="queryRechargeList"
model="TABLE"
:defaultParams="{
pageSize: 10,
sorts: [{ name: 'createTime', order: 'desc' }],
}"
:pagination="{
showSizeChanger: true,
pageSizeOptions: ['10', '20', '50', '100'],
}"
:params="params"
>
<template #headerTitle> <template #headerTitle>
<j-space> <j-space>
<PermissionButton @click="visible = true" :hasPermission="'iot-card/Recharge:pay'" type="primary"> <PermissionButton @click="visible = true" :hasPermission="'iot-card/Recharge:pay'" type="primary">

View File

@ -44,15 +44,33 @@
</j-radio-group> </j-radio-group>
</j-form-item> </j-form-item>
<j-form-item label="说明" name="description"> <j-form-item label="说明" name="description">
<j-textarea v-model:value="form.description" showCount :maxlength="200"></j-textarea> <j-textarea
v-model:value="form.description"
showCount
:maxlength="200"
></j-textarea>
</j-form-item> </j-form-item>
<PermissionButton type="primary" :loading="loading" @click="handleSave" :hasPermission="['rule-engine/Alarm/Configuration:add','rule-engine/Alarm/Configuration:update']">保存</PermissionButton> <PermissionButton
type="primary"
:loading="loading"
@click="handleSave"
:hasPermission="[
'rule-engine/Alarm/Configuration:add',
'rule-engine/Alarm/Configuration:update',
]"
>保存</PermissionButton
>
</j-form> </j-form>
</div> </div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { getTargetTypes, save, detail , updata} from '@/api/rule-engine/configuration'; import {
getTargetTypes,
save,
detail,
updata,
} from '@/api/rule-engine/configuration';
import { queryLevel } from '@/api/rule-engine/config'; import { queryLevel } from '@/api/rule-engine/config';
import { query } from '@/api/rule-engine/scene'; import { query } from '@/api/rule-engine/scene';
import { getImage } from '@/utils/comm'; import { getImage } from '@/utils/comm';
@ -63,15 +81,14 @@ import { useAlarmConfigurationStore } from '@/store/alarm';
import { storeToRefs } from 'pinia'; import { storeToRefs } from 'pinia';
import { usePermissionStore } from '@/store/permission'; import { usePermissionStore } from '@/store/permission';
const route = useRoute(); const route = useRoute();
const id = route.query?.id;
let selectDisable = ref(false); let selectDisable = ref(false);
const alarmConfigurationStore = useAlarmConfigurationStore(); const alarmConfigurationStore = useAlarmConfigurationStore();
let { configurationData } = storeToRefs(alarmConfigurationStore); let { configurationData } = storeToRefs(alarmConfigurationStore);
const queryData = () => { const queryData = () => {
if (id) { if (route.query?.id) {
detail(id).then((res) => { detail(route.query?.id).then((res) => {
if (res.status === 200) { if (res.status === 200) {
form.value = res?.result form.value = res?.result;
// form.level = res?.result?.level; // form.level = res?.result?.level;
// form.name = res?.result?.name; // form.name = res?.result?.name;
// form.targetType = res?.result?.targetType; // form.targetType = res?.result?.targetType;
@ -84,7 +101,7 @@ const queryData = () => {
{ {
column: 'id', column: 'id',
termType: 'alarm-bind-rule', termType: 'alarm-bind-rule',
value: id, value: route.query?.id,
}, },
], ],
type: 'and', type: 'and',
@ -176,18 +193,22 @@ const handleSave = async () => {
formRef.value formRef.value
.validate() .validate()
.then(async () => { .then(async () => {
const res = id ? await updata(form.value) : await save(form.value); const res = route.query?.id
? await updata(form.value)
: await save(form.value);
if (res.status === 200) { if (res.status === 200) {
message.success('操作成功,请配置关联的场景联动'); message.success('操作成功,请配置关联的场景联动');
loading.value = false; loading.value = false;
menuStory.jumpPage( if (res.result?.id) {
'rule-engine/Alarm/Configuration/Save', menuStory.jumpPage(
{}, 'rule-engine/Alarm/Configuration/Save',
{ id: res.result?.id }, {},
); { id: res.result?.id },
if (!id) { );
}
if (!route.query?.id) {
configurationData.value.current = res.result; configurationData.value.current = res.result;
} }
} }
}) })
.catch((error) => { .catch((error) => {
@ -196,6 +217,12 @@ const handleSave = async () => {
}); });
}; };
queryData(); queryData();
watch(
() => route.query?.id,
() => {
queryData();
},
);
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
.ant-radio-button-wrapper { .ant-radio-button-wrapper {
@ -203,7 +230,7 @@ queryData();
width: 20%; width: 20%;
height: 100%; height: 100%;
} }
.levelSelect{ .levelSelect {
display: flex; display: flex;
width: 100%; width: 100%;
} }

View File

@ -40,12 +40,13 @@
</j-space> </j-space>
</template> </template>
</JProTable> </JProTable>
<Info v-if="visiable" :data="current" @close="close"/> <Info v-if="visiable" :data="current" @close="close" :description="description"/>
</page-container> </page-container>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { detail, queryHistoryList } from '@/api/rule-engine/log'; import { detail, queryHistoryList } from '@/api/rule-engine/log';
import { detail as configurationDetail} from '@/api/rule-engine/configuration'
import { useRoute } from 'vue-router'; import { useRoute } from 'vue-router';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import type { ActionsType } from '@/components/Table/index.vue'; import type { ActionsType } from '@/components/Table/index.vue';
@ -58,6 +59,7 @@ const route = useRoute();
const id = route.params?.id; const id = route.params?.id;
const { params: routerParams } = useRouterParams() const { params: routerParams } = useRouterParams()
let visiable = ref(false); let visiable = ref(false);
let description = ref<string>();
const columns = [ const columns = [
{ {
title: '告警时间', title: '告警时间',
@ -168,6 +170,11 @@ watchEffect(async () => {
key: 'targetName', key: 'targetName',
}); });
} }
configurationDetail(res.result?.alarmConfigId).then((res:any)=>{
if(res.status === 200){
description.value = res.result?.description;
}
})
} }
}); });
const handleSearch = (_params: any) => { const handleSearch = (_params: any) => {

View File

@ -1,8 +1,26 @@
<template> <template>
<j-modal visible title="详情" okText="确定" cancelText="取消" :width="1000" @ok="closeModal" @cancel="closeModal"> <j-modal
visible
title="详情"
okText="确定"
cancelText="取消"
:width="1000"
@ok="closeModal"
@cancel="closeModal"
>
<j-descriptions bordered :column="2"> <j-descriptions bordered :column="2">
<j-descriptions-item v-if="props.data.targetType==='device'" label="告警设备" :span="1">{{props.data?.targetName || ''}}</j-descriptions-item> <j-descriptions-item
<j-descriptions-item v-if="props.data.targetType==='device'" label="设备ID" :span="1">{{props.data?.targetId || ''}}</j-descriptions-item> v-if="props.data.targetType === 'device'"
label="告警设备"
:span="1"
>{{ props.data?.targetName || '' }}</j-descriptions-item
>
<j-descriptions-item
v-if="props.data.targetType === 'device'"
label="设备ID"
:span="1"
>{{ props.data?.targetId || '' }}</j-descriptions-item
>
<j-descriptions-item label="告警名称" :span="1">{{ <j-descriptions-item label="告警名称" :span="1">{{
props.data?.alarmConfigName props.data?.alarmConfigName
}}</j-descriptions-item> }}</j-descriptions-item>
@ -23,22 +41,20 @@
</Ellipsis> </Ellipsis>
</j-tooltip> </j-tooltip>
</j-descriptions-item> </j-descriptions-item>
<j-descriptions-item label="告警说明" :span="1" <j-descriptions-item label="告警说明" :span="1">
><j-tooltip <Ellipsis style="width: calc(100% - 20px)">
placement="topLeft" <span>
:title="data?.description || ''" {{ description || '' }}
> </span>
<Ellipsis> </Ellipsis>
<span> </j-descriptions-item>
{{ data?.description || '' }} <j-descriptions-item label="告警流水" :span="2"
</span> </Ellipsis ><div style="max-height: 500px; overflow-y: auto">
> <JsonViewer
</j-tooltip></j-descriptions-item :value="JSON.parse(data?.alarmInfo || '{}')"
> :expand-depth="5"
<j-descriptions-item ></JsonViewer></div
label="告警流水" ></j-descriptions-item>
:span="2"
><div style="max-height: 500px; overflow-y: auto;"><JsonViewer :value="JSON.parse(data?.alarmInfo || '{}')" :expand-depth="5"></JsonViewer></div></j-descriptions-item>
</j-descriptions> </j-descriptions>
</j-modal> </j-modal>
</template> </template>
@ -49,11 +65,12 @@ import { Store } from 'jetlinks-store';
import JsonViewer from 'vue-json-viewer'; import JsonViewer from 'vue-json-viewer';
const props = defineProps({ const props = defineProps({
data: Object, data: Object,
description: String,
}); });
const emit = defineEmits(['close']) const emit = defineEmits(['close']);
const closeModal = () => { const closeModal = () => {
emit('close'); emit('close');
} };
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
</style> </style>

View File

@ -13,7 +13,7 @@
v-model:value="_value" v-model:value="_value"
:precision="3" :precision="3"
:min="0" :min="0"
:max="6535" :max="65535"
> >
<template #addonAfter> <template #addonAfter>
<j-select <j-select

View File

@ -7,6 +7,7 @@
v-model:value="_value" v-model:value="_value"
v-model:source="_source" v-model:source="_source"
@select="onChange" @select="onChange"
valueName="id"
> >
<template v-slot="{ label }"> <template v-slot="{ label }">
<j-input :value="label" readonly /> <j-input :value="label" readonly />
@ -15,6 +16,7 @@
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { cloneDeep } from 'lodash-es';
import ParamsDropdown from '../../../components/ParamsDropdown'; import ParamsDropdown from '../../../components/ParamsDropdown';
import { handleParamsData } from './index'; import { handleParamsData } from './index';
@ -101,7 +103,7 @@ const filterParamsData = (type?: string, data?: any[]): any[] => {
}; };
const upperOptions = computed(() => { const upperOptions = computed(() => {
return filterParamsData(props.data.valueType?.type, props?.builtInList); return filterParamsData(props.data.valueType?.type, cloneDeep(props?.builtInList));
}); });
const onChange = () => { const onChange = () => {

View File

@ -39,6 +39,7 @@
v-model:value="propertyModelRef.propertiesValue" v-model:value="propertyModelRef.propertiesValue"
v-model:source="propertyModelRef.source" v-model:source="propertyModelRef.source"
@select="onValueChange" @select="onValueChange"
valueName="id"
> >
<template v-slot="{ label }"> <template v-slot="{ label }">
<j-input readonly :value="label" placeholder="请选择" /> <j-input readonly :value="label" placeholder="请选择" />
@ -51,6 +52,7 @@
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { cloneDeep } from 'lodash-es';
import ParamsDropdown from '../../../components/ParamsDropdown'; import ParamsDropdown from '../../../components/ParamsDropdown';
import { handleParamsData } from './index'; import { handleParamsData } from './index';
const props = defineProps({ const props = defineProps({
@ -122,7 +124,8 @@ const filterParamsData = (type?: string, data?: any[]): any[] => {
}; };
const upperOptions = computed(() => { const upperOptions = computed(() => {
return filterParamsData(getType.value?.valueType?.type, props?.builtInList); const _data = filterParamsData(getType.value?.valueType?.type, cloneDeep(props?.builtInList))
return _data
}); });
const handleOptions = computed(() => { const handleOptions = computed(() => {
@ -162,7 +165,7 @@ const onChange = () => {
}); });
}; };
const onValueChange = () => { const onValueChange = (val: any) => {
const obj = { const obj = {
[`${propertyModelRef.properties}`]: { [`${propertyModelRef.properties}`]: {
value: propertyModelRef?.propertiesValue, value: propertyModelRef?.propertiesValue,
@ -170,7 +173,7 @@ const onValueChange = () => {
}, },
}; };
emit('update:value', obj); emit('update:value', obj);
emit('change', propertyModelRef?.propertiesValue) emit('change', val?.name || val)
}; };
watch( watch(

View File

@ -183,7 +183,7 @@ watch(
<style lang="less"> <style lang="less">
.action-search { .action-search {
padding: 0 0 24px 0; padding: 0;
} }
.logo { .logo {

View File

@ -183,7 +183,7 @@ watch(
<style lang="less"> <style lang="less">
.action-search { .action-search {
padding: 0 0 24px 0; padding: 0;
} }
.logo { .logo {

View File

@ -79,6 +79,7 @@ const formRef = ref();
const modelRef = reactive({}); const modelRef = reactive({});
watchEffect(() => { watchEffect(() => {
console.log(props?.value)
Object.assign(modelRef, props?.value); Object.assign(modelRef, props?.value);
}); });

View File

@ -91,7 +91,7 @@ const source = computed(() => {
}); });
const builtInList = ref<any[]>([]); const builtInList = ref<any[]>([]);
const upperKey = ref(); const upperKey = ref(props.value?.upperKey);
const sourceChange = (val: any) => { const sourceChange = (val: any) => {
emit('update:value', { emit('update:value', {
@ -160,6 +160,14 @@ watch(
}, },
{ deep: true, immediate: true }, { deep: true, immediate: true },
); );
watch(
() => props.value.upperKey,
(newVal) => {
upperKey.value = newVal
},
{ immediate: true },
);
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>

View File

@ -176,10 +176,10 @@
name="name" name="name"
:required="true" :required="true"
:rules="[ :rules="[
// { {
// required: true, required: true,
// message: '', message: '请输入名称',
// }, },
{ {
max: 64, max: 64,
message: '最多可输入64个字符', message: '最多可输入64个字符',
@ -467,7 +467,7 @@ const checkName = (_: any, value: any) =>
resolve(''); resolve('');
} }
} else { } else {
reject('请输入名称'); resolve('');
} }
}); });
</script> </script>

View File

@ -232,7 +232,7 @@ const table: any = {
// allPermissions, // allPermissions,
// ); // );
// item.selectPermissions = newPermission; // item.selectPermissions = newPermission;
// fix: bug#10756 // fix: bug#10756
item.selectPermissions = n[1]; item.selectPermissions = n[1];
// //
@ -264,6 +264,12 @@ const table: any = {
removedItem.selectPermissions = ['read']; removedItem.selectPermissions = ['read'];
}); });
} }
if (!nValue.length) {
//
table.tableData.forEach((item: any) => {
item.selectPermissions = ['read'];
});
}
}, },
{ deep: true }, { deep: true },
); );

View File

@ -548,6 +548,7 @@ watch(
() => props.parentId, () => props.parentId,
() => { () => {
tableData._selectedRowKeys = []; tableData._selectedRowKeys = [];
tableData.selectedRows = [];
}, },
); );
</script> </script>

View File

@ -3700,8 +3700,8 @@ jetlinks-store@^0.0.3:
jetlinks-ui-components@^1.0.5: jetlinks-ui-components@^1.0.5:
version "1.0.5" version "1.0.5"
resolved "http://47.108.170.157:9013/jetlinks-ui-components/-/jetlinks-ui-components-1.0.5.tgz#c93a8863ed93b90f620d3c011ec79ada218625dd" resolved "http://47.108.170.157:9013/jetlinks-ui-components/-/jetlinks-ui-components-1.0.5.tgz#531a7cd5cc4069dc299f0efcc92411a4eee369e7"
integrity sha512-ESpadoDCZHkedS0oFgQmuSUvoMLUk2OrCXwB6x4ED4crfKynLJtqjBYeY/f8Eb2TuRTLxElL/qv6dr+MTaJSeQ== integrity sha512-7VHsz5lVG9PlFkHoJvEown4QARuVuasR+jDa9NNQ+pJSHAtHAeiIO1bpVTQKfE5WCyhCKPnN8yIerJLLzmQ1fA==
dependencies: dependencies:
"@vueuse/core" "^9.12.0" "@vueuse/core" "^9.12.0"
ant-design-vue "^3.2.15" ant-design-vue "^3.2.15"