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

This commit is contained in:
JiangQiming 2023-03-20 15:53:24 +08:00
commit 5d27993d0f
16 changed files with 89 additions and 437 deletions

View File

@ -4,7 +4,13 @@ const color = {
'error': '229, 0, 18',
'success': '36, 178, 118',
'warning': '255, 144, 0',
'default': '102, 102, 102'
'default': '102, 102, 102',
//告警颜色
'level1': '229, 0, 18',
'level2': '255, 148, 87',
'level3': '250, 189, 71',
'level4': '153, 153, 153',
'level5': '196, 196, 196'
}
export const getHexColor = (code: string, pe: number = 0.1) => {
const _color = color[code] || color.default

View File

@ -28,6 +28,7 @@
</j-form-item>
</j-col>
<j-col
class="inputs"
:span="
modelRef.messageType === 'READ_PROPERTY' ||
actionType === 'latestData'
@ -68,6 +69,7 @@
</j-col>
<j-col
:span="12"
class="inputs"
v-if="
modelRef.messageType === 'WRITE_PROPERTY' &&
actionType === 'command'
@ -84,11 +86,11 @@
<ValueItem
v-model:modelValue="modelRef.message.value"
:itemType="
property.type || property.valueType?.type || 'int'
property.valueType?.type || property.type || 'int'
"
:options="
property.valueType?.type === 'enum'
? (property?.dataType?.elements || []).map(
? (property?.valueType?.elements || []).map(
(item) => {
return {
label: item?.text,
@ -190,9 +192,21 @@ const modelRef = reactive({
properties: undefined,
functionId: undefined,
inputs: [],
value: undefined
},
});
const property = ref<any>({});
const onPropertyChange = (val: string) => {
if (val) {
const _item = props.metadata?.properties.find(
(item: any) => item.id === val,
);
property.value = _item || {};
}
};
watch(
() => props.modelValue,
(newVal) => {
@ -208,8 +222,6 @@ watch(
},
);
const property = ref<any>({});
const funcChange = (val: string) => {
if (val) {
const arr =
@ -227,15 +239,6 @@ const funcChange = (val: string) => {
}
};
const onPropertyChange = (val: string) => {
if (val) {
const _item = props.metadata?.properties.find(
(item: any) => item.id === val,
);
property.value = _item?.[0] || {};
}
};
const saveBtn = () =>
new Promise((resolve) => {
formRef.value

View File

@ -571,6 +571,7 @@ const getTypes = async () => {
};
const getDuerOSProperties = (val: string) => {
console.log(val)
const arr = modelRef.propertyMappings.map((item) => item?.source) || [];
const checked = _.cloneDeep(arr);
const _index = checked.findIndex((i) => i === val);
@ -672,6 +673,7 @@ watch(
_data.applianceType = _data?.applianceType?.value;
}
Object.assign(modelRef, _data);
console.log(modelRef.propertyMappings)
}
},
{ immediate: true, deep: true },

View File

@ -119,6 +119,7 @@ const Status = defineComponent({
<span>
<PermissionButton
type="link"
style="padding: 0"
hasPermission="link/Type:action"
popConfirm={{
title: '确认启用',
@ -288,6 +289,8 @@ const Status = defineComponent({
text={<span>
<PermissionButton
hasPermission="link/Type:action"
type="link"
style="padding: 0"
popConfirm={{
title: '确认启用',
onConfirm: async () => {
@ -416,6 +419,8 @@ const Status = defineComponent({
<PermissionButton
hasPermission="link/AccessConfig:action"
type="link"
style="padding: 0"
popConfirm={{
title: '确认启用',
onConfirm: async () => {
@ -528,6 +533,8 @@ const Status = defineComponent({
<PermissionButton
hasPermission="device/Product:action"
type="link"
style="padding: 0"
popConfirm={{
title: '确认启用',
onConfirm: async () => {
@ -636,6 +643,8 @@ const Status = defineComponent({
<PermissionButton
hasPermission="device/Product:action"
type="link"
style="padding: 0"
popConfirm={{
title: '确认启用',
onConfirm: async () => {
@ -712,6 +721,8 @@ const Status = defineComponent({
<PermissionButton
hasPermission="device/Instance:action"
type="link"
style="padding: 0"
popConfirm={{
title: '确认启用',
onConfirm: async () => {
@ -1720,6 +1731,8 @@ const Status = defineComponent({
<PermissionButton
hasPermission="device/Product:action"
type="link"
style="padding: 0"
popConfirm={{
title: '确认启用',
onConfirm: async () => {

View File

@ -1,15 +1,14 @@
<template>
<page-container
:tabList="list"
@back="onBack"
:tabActiveKey="instanceStore.tabActiveKey"
@tabChange="onTabChange"
>
<template #title>
<div>
<div style="display: flex; align-items: center">
<j-button @click="onBack" size="small">返回</j-button>
<div style="margin-left: 20px; font-size: 24px">
<!-- <j-button @click="onBack" size="small">返回</j-button> -->
<div style="font-size: 24px">
{{ instanceStore.current.name }}
</div>
<j-divider type="vertical" />
@ -207,9 +206,9 @@ onMounted(() => {
instanceStore.tabActiveKey = history.state?.params?.tab || 'Info';
});
const onBack = () => {
menuStory.jumpPage('device/Instance');
};
// const onBack = () => {
// menuStory.jumpPage('device/Instance');
// };
const onTabChange = (e: string) => {
instanceStore.tabActiveKey = e;

View File

@ -335,6 +335,7 @@ const columns = [
key: 'productName',
search: {
type: 'select',
rename: 'productId',
options: () =>
new Promise((resolve) => {
queryNoPagingPost({ paging: false }).then((resp: any) => {

View File

@ -317,7 +317,7 @@
:status="slotProps.state.value"
:statusText="slotProps.state.text"
:statusNames="{
enabled: 'success',
enabled: 'processing',
disabled: 'error',
}"
>
@ -1009,6 +1009,7 @@ const submitDevice = async () => {
});
if (resp.status === 200) {
message.success('操作成功!');
productStore.current!.storePolicy = storePolicy
if ((window as any).onTabSaveSuccess) {
if (resp.result) {
(window as any).onTabSaveSuccess(resp);

View File

@ -266,7 +266,7 @@ onMounted(() => {
cursor: not-allowed;
}
.productDetailHead {
width: 50%;
max-width: 50%;
overflow: hidden;
white-space: nowrap;
overflow: hidden;

View File

@ -48,7 +48,7 @@
:status="slotProps.state"
:statusText="slotProps.state === 1 ? '正常' : '禁用'"
:statusNames="{
1: 'success',
1: 'processing',
0: 'error',
}"
>
@ -118,9 +118,13 @@
</CardBox>
</template>
<template #state="slotProps">
<j-badge
<BadgeStatus
:text="slotProps.state === 1 ? '正常' : '禁用'"
:status="statusMap.get(slotProps.state)"
:status="slotProps.state"
:statusNames="{
1: 'processing',
0: 'error',
}"
/>
</template>
<template #action="slotProps">
@ -189,9 +193,6 @@ const menuStory = useMenuStore();
const isAdd = ref<number>(0);
const title = ref<string>('');
const params = ref<Record<string, any>>({});
const statusMap = new Map();
statusMap.set(1, 'success');
statusMap.set(0, 'error');
const columns = [
{
title: 'ID',

View File

@ -44,7 +44,7 @@
</j-radio-group>
</j-form-item>
<j-form-item label="说明" name="description">
<j-textarea v-model:value="form.description"></j-textarea>
<j-textarea v-model:value="form.description" showCount :maxlength="200"></j-textarea>
</j-form-item>
<PermissionButton type="primary" @click="handleSave" :hasPermission="['rule-engine/Alarm/Configuration:add','rule-engine/Alarm/Configuration:update']">保存</PermissionButton>
</j-form>

View File

@ -37,7 +37,7 @@
:active="_selectedRowKeys.includes(slotProps.id)"
@click="handleClick"
:statusNames="{
started: 'success',
started: 'processing',
disable: 'error',
}"
>

View File

@ -39,7 +39,7 @@
:status="slotProps.state?.value"
:statusText="slotProps.state?.text"
:statusNames="{
enabled: 'success',
enabled: 'processing',
disabled: 'error',
}"
>
@ -122,17 +122,17 @@
>
</template>
<template #state="slotProps">
<j-badge
<BadgeStatus
:text="
slotProps.state?.value === 'enabled'
? '正常'
: '禁用'
"
:status="
slotProps.state?.value === 'enabled'
? 'success'
: 'error'
"
:status="slotProps.state?.value"
:statusNames="{
enabled: 'processing',
disabled: 'error',
}"
/>
</template>
<template #action="slotProps">
@ -196,6 +196,8 @@ const columns = [
search: {
type: 'string',
},
width: 220,
ellipsis: true,
},
{
title: '类型',
@ -223,6 +225,7 @@ const columns = [
},
],
},
width: 100,
},
{
title: '告警级别',
@ -244,6 +247,8 @@ const columns = [
return [];
},
},
width: 200,
ellipsis: true,
},
{
title: '关联场景联动',
@ -267,6 +272,8 @@ const columns = [
return [];
},
},
width: 220,
ellipsis: true,
},
{
title: '状态',
@ -286,6 +293,7 @@ const columns = [
},
],
},
width: 90,
},
{
title: '说明',
@ -294,6 +302,7 @@ const columns = [
search: {
type: 'string',
},
ellipsis: true,
},
{
title: '操作',

View File

@ -43,6 +43,14 @@
(i) => i.level === slotProps.level,
)?.title || slotProps.level
"
:status="slotProps.level"
:statusNames="{
1: 'level1',
2: 'level2',
3: 'level3',
4: 'level4',
5: 'level5',
}"
>
<template #img>
<img :src="imgMap.get(slotProps.targetType)" alt="" />
@ -80,14 +88,14 @@
</j-col>
<j-col :span="8">
<div class="content-des-title">状态</div>
<j-badge
:status="
slotProps.state.value === 'warning'
? 'error'
: 'default'
"
<BadgeStatus
:status="slotProps.state.value"
:statusName="{
warning: 'warning',
normal: 'default',
}"
>
</j-badge
</BadgeStatus
><span
:style="
slotProps.state.value === 'warning'
@ -184,14 +192,6 @@ titleMap.set('product', '产品');
titleMap.set('device', '设备');
titleMap.set('other', '其他');
titleMap.set('org', '组织');
const colorMap = new Map();
colorMap.set(1, '#E50012');
colorMap.set(2, '#FF9457');
colorMap.set(3, '#FABD47');
colorMap.set(4, '#999999');
colorMap.set(5, '#C4C4C4');
const columns = [
{
title: '名称',

View File

@ -1,370 +0,0 @@
<template>
<div class="card">
<div
class="card-warp"
:class="{ active: active ? 'active' : '' }"
@click="handleClick"
>
<div class="card-type">
<div class="card-type-text"><slot name="type"></slot></div>
</div>
<div class="card-content">
<div style="display: flex">
<!-- 图片 -->
<div class="card-item-avatar">
<slot name="img"> </slot>
</div>
<!-- 内容 -->
<div class="card-item-body">
<slot name="title"></slot>
<span class="subTitle">
<slot name="subTitle"></slot>
</span>
</div>
</div>
<!-- 勾选 -->
<div v-if="active" class="checked-icon">
<div>
<AIcon type="CheckOutlined" />
</div>
</div>
<!-- 状态 -->
<div
v-if="showStatus"
class="card-state"
:class="statusNames ? statusNames[status] : ''"
>
<div class="card-state-content">
<BadgeStatus
:status="status"
:text="statusText"
:statusNames="statusNames"
></BadgeStatus>
</div>
</div>
</div>
</div>
<!-- 按钮 -->
<slot name="bottom-tool">
<div
v-if="showTool && actions && actions.length"
class="card-tools"
>
<div
v-for="item in actions"
:key="item.key"
class="card-button"
:class="{
delete: item.key === 'delete',
}"
>
<slot name="actions" v-bind="item"></slot>
</div>
</div>
</slot>
</div>
</template>
<script setup lang="ts">
import BadgeStatus from '@/components/BadgeStatus/index.vue';
import { StatusColorEnum } from '@/utils/consts.ts';
import type { ActionsType } from '@/components/Table/index.vue';
import { PropType } from 'vue';
type EmitProps = {
(e: 'click', data: Record<string, any>): void;
};
type TableActionsType = Partial<ActionsType>;
const emit = defineEmits<EmitProps>();
const props = defineProps({
value: {
type: Object as PropType<Record<string, any>>,
default: () => {},
},
showStatus: {
type: Boolean,
default: true,
},
showTool: {
type: Boolean,
default: true,
},
statusText: {
type: String,
default: '正常',
},
status: {
type: [String, Number],
default: 'default',
},
statusNames: {
type: Object,
},
actions: {
type: Array as PropType<TableActionsType[]>,
default: () => [],
},
active: {
type: Boolean,
default: false,
},
});
const handleClick = () => {
emit('click', props.value);
};
</script>
<style lang="less" scoped>
.card {
width: 100%;
background-color: #fff;
.checked-icon {
position: absolute;
right: -22px;
bottom: -22px;
z-index: 2;
width: 44px;
height: 44px;
color: #fff;
background-color: red;
background-color: #2f54eb;
transform: rotate(-45deg);
> div {
position: relative;
height: 100%;
transform: rotate(45deg);
> span {
position: absolute;
top: 6px;
left: 6px;
font-size: 12px;
}
}
}
.card-warp {
position: relative;
border: 1px solid #e6e6e6;
overflow: hidden;
&:hover {
cursor: pointer;
box-shadow: 0 0 24px rgba(#000, 0.1);
.card-mask {
visibility: visible;
}
}
&.active {
position: relative;
border: 1px solid #2f54eb;
}
.card-type {
position: absolute;
top: 0;
left: -14px;
height: 32px;
padding: 0 30px;
color: rgba(0, 0, 0, 0.65);
line-height: 32px;
background-color: rgba(0, 0, 0, 0.06);
transform: skewX(-45deg);
.card-type-text {
display: flex;
align-items: center;
justify-content: center;
transform: skewX(45deg);
}
}
.card-content {
position: relative;
padding: 43px 12px 19px 30px;
overflow: hidden;
.card-item-avatar {
margin-right: 16px;
}
.card-item-body {
display: flex;
flex-direction: column;
flex-grow: 1;
width: 0;
.subTitle {
color: rgba(0, 0, 0, 0.65);
font-size: 14px;
margin-top: 10px;
}
}
.card-state {
position: absolute;
top: 40px;
right: -12px;
display: flex;
justify-content: center;
width: 100px;
padding: 2px 0;
background-color: rgba(#5995f5, 0.15);
transform: skewX(45deg);
&.success {
background-color: @success-color-deprecated-bg;
}
&.warning {
background-color: rgba(#ff9000, 0.1);
}
&.error {
background-color: rgba(#e50012, 0.1);
}
.card-state-content {
transform: skewX(-45deg);
}
}
:deep(.card-item-content-title) {
cursor: pointer;
font-size: 16px;
font-weight: 700;
color: @primary-color;
width: calc(100% - 100px);
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
:deep(.card-item-heard-name) {
font-weight: 700;
font-size: 16px;
margin-bottom: 12px;
}
:deep(.card-item-content-text) {
color: rgba(0, 0, 0, 0.75);
font-size: 12px;
}
}
}
&.item-active {
position: relative;
color: #2f54eb;
.checked-icon {
display: block;
}
.card-warp {
border: 1px solid #2f54eb;
}
}
.card-tools {
display: flex;
margin-top: 8px;
.card-button {
display: flex;
flex-grow: 1;
& > :deep(span, button) {
width: 100%;
border-radius: 0;
}
:deep(button) {
width: 100%;
border-radius: 0;
background: #f6f6f6;
border: 1px solid #e6e6e6;
color: #2f54eb;
&:hover {
background-color: @primary-color-hover;
border-color: @primary-color-hover;
span {
color: #fff !important;
}
}
&:active {
background-color: @primary-color-active;
border-color: @primary-color-active;
span {
color: #fff !important;
}
}
}
&:not(:last-child) {
margin-right: 8px;
}
&.delete {
flex-basis: 60px;
flex-grow: 0;
:deep(button) {
background: @error-color-deprecated-bg;
border: 1px solid @error-color-outline;
span {
color: @error-color !important;
}
&:hover {
background-color: @error-color-hover;
span {
color: #fff !important;
}
}
&:active {
background-color: @error-color-active;
span {
color: #fff !important;
}
}
}
}
:deep(button[disabled]) {
background: @disabled-bg;
border-color: @disabled-color;
span {
color: @disabled-color !important;
}
&:hover {
background-color: @disabled-active-bg;
}
&:active {
background-color: @disabled-active-bg;
}
}
}
}
}
</style>

View File

@ -132,7 +132,6 @@ import { query, _delete, _action, _execute } from '@/api/rule-engine/scene';
import { message } from 'ant-design-vue';
import type { ActionsType } from '@/components/Table';
import { getImage } from '@/utils/comm';
import SceneCard from './SceneCard.vue';
import BadgeStatus from '@/components/BadgeStatus/index.vue';
const menuStory = useMenuStore();

View File

@ -3698,26 +3698,14 @@ jetlinks-store@^0.0.3:
resolved "https://registry.npmjs.org/jetlinks-store/-/jetlinks-store-0.0.3.tgz"
integrity sha512-AZf/soh1hmmwjBZ00fr1emuMEydeReaI6IBTGByQYhTmK1Zd5pQAxC7WLek2snRAn/HHDgJfVz2hjditKThl6Q==
jetlinks-ui-components@^1.0.4:
version "1.0.4"
resolved "http://47.108.170.157:9013/jetlinks-ui-components/-/jetlinks-ui-components-1.0.4.tgz#cd080b2d8320c7a03ed20f4c4c22e9a5c920a3c8"
integrity sha512-8xzDFH6jSGNrkbCMb+/FL/g9vB0c2GdsDq6QPUzgKFwzPiS+cPbpSxL0RNHez9MF7/NSSuY8wL4VaujiVXTpfg==
dependencies:
"@vueuse/core" "^9.12.0"
ant-design-vue "^3.2.15"
colorpicker-v3 "^2.10.2"
lodash-es "^4.17.21"
monaco-editor "^0.35.0"
jetlinks-ui-components@^1.0.5:
version "1.0.5"
resolved "http://47.108.170.157:9013/jetlinks-ui-components/-/jetlinks-ui-components-1.0.5.tgz#0c4999d28c96c11ce266c5c9706cc895010450dc"
integrity sha512-buCf4mWJ8cUyn+12nRRLIr25MwG60nxqWH4pZidKy/npNKt5WQXLV8PmHmf04z0xpJUnW5yY3C7QBkYoAkSgVw==
resolved "http://47.108.170.157:9013/jetlinks-ui-components/-/jetlinks-ui-components-1.0.5.tgz#682711e0f69c141fff2c256db61a060c82539611"
integrity sha512-rQxD/YlE+XSAG7BWIcFTtKrCQJXk5o+TUgejyuUT/baBThJB6xYt1k2dQEdXyiwpukYen5FzaoLpelSD9SUegw==
dependencies:
"@vueuse/core" "^9.12.0"
ant-design-vue "^3.2.15"
colorpicker-v3 "^2.10.2"
jetlinks-ui-components "^1.0.4"
lodash-es "^4.17.21"
monaco-editor "^0.35.0"