Merge branch 'dev' of github.com:jetlinks/jetlinks-ui-vue into dev
This commit is contained in:
commit
14d2a782ce
|
@ -24,7 +24,7 @@
|
|||
"event-source-polyfill": "^1.0.31",
|
||||
"global": "^4.4.0",
|
||||
"jetlinks-store": "^0.0.3",
|
||||
"jetlinks-ui-components": "^1.0.1",
|
||||
"jetlinks-ui-components": "^1.0.3",
|
||||
"js-cookie": "^3.0.1",
|
||||
"less": "^4.1.3",
|
||||
"less-loader": "^11.1.0",
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
import server from '@/utils/request';
|
||||
|
||||
export const query = (data: any) =>
|
||||
server.post(`/data-collect/channel/_query`, data);
|
||||
|
||||
export const remove = (id: string) =>
|
||||
server.remove(`/data-collect/channel/${id}`);
|
||||
|
||||
export const save = (data: any) => server.post(`/data-collect/channel`, data);
|
||||
|
||||
export const update = (id: string, data: any) =>
|
||||
server.put(`/data-collect/channel/${id}`, data);
|
||||
|
||||
export const getProviders = () => server.get(`/gateway/device/providers`);
|
||||
|
||||
export const queryOptionsList = (type: strimg) =>
|
||||
server.get(`/data-collect/opc/${type}`);
|
||||
|
||||
export const validateField = (data: any) =>
|
||||
server.post(`/data-collect/opc/endpoint/_validate`, data, null, {
|
||||
headers: {
|
||||
'Content-Type': 'text/plain;charset=UTF-8',
|
||||
},
|
||||
});
|
||||
|
||||
export const queryCertificateList = () =>
|
||||
server.get(`/network/certificate/_query/no-paging?paging=false`, {});
|
|
@ -0,0 +1,6 @@
|
|||
import server from '@/utils/request';
|
||||
|
||||
export const queryCount = (type: string, data: any) =>
|
||||
server.post(`/data-collect/${type}/_count`, data);
|
||||
|
||||
export const dashboard = (data: any) => server.post(`/dashboard/_multi`, data);
|
|
@ -51,4 +51,9 @@ export const settingDetail = (scopes: string) => server.get(`/system/config/${sc
|
|||
/**
|
||||
* 获取当前登录用户信息
|
||||
*/
|
||||
export const userDetail = () => server.get<any>('/user/detail')
|
||||
export const userDetail = () => server.get<any>('/user/detail')
|
||||
|
||||
/**
|
||||
* 退出登录
|
||||
*/
|
||||
export const loginout_api = () => server.get<any>('/user-token/reset')
|
||||
|
|
|
@ -35,8 +35,12 @@ export default {
|
|||
// 更改国标ID
|
||||
updateGbChannelId: (id: string, data: any): any => server.put(`/media/gb28181-cascade/binding/${id}`, data),
|
||||
// 查询通道分页列表
|
||||
queryChannelList: (data: any): any => server.post(`media/channel/_query`, data),
|
||||
queryChannelList: (data: any): any => server.post(`/media/channel/_query`, data),
|
||||
// 推送
|
||||
publish: (id: string, params: any) => server.get(`/media/gb28181-cascade/${id}/bindings/publish`, params)
|
||||
publish: (id: string, params: any) => server.get(`/media/gb28181-cascade/${id}/bindings/publish`, params),
|
||||
|
||||
// 分屏展示接口
|
||||
// 设备树
|
||||
getMediaTree: (data?: any) => server.post<any>(`/media/device/_query/no-paging`, data),
|
||||
|
||||
}
|
|
@ -70,6 +70,10 @@ const iconKeys = [
|
|||
'CaretDownOutlined',
|
||||
'MinusOutlined',
|
||||
'AudioOutlined',
|
||||
'BellOutlined',
|
||||
'UserOutlined',
|
||||
'LogoutOutlined',
|
||||
'ReadIconOutlined'
|
||||
]
|
||||
|
||||
const Icon = (props: {type: string}) => {
|
||||
|
|
|
@ -1,84 +1,102 @@
|
|||
<template>
|
||||
<j-pro-layout
|
||||
v-bind='layoutConf'
|
||||
v-model:openKeys="state.openKeys"
|
||||
v-model:collapsed="state.collapsed"
|
||||
v-model:selectedKeys="state.selectedKeys"
|
||||
:pure='state.pure'
|
||||
:breadcrumb='{ routes: breadcrumb }'
|
||||
>
|
||||
<template #breadcrumbRender='slotProps'>
|
||||
<a v-if='slotProps.route.index !== 0'>{{slotProps.route.breadcrumbName}}</a>
|
||||
<span v-else>{{slotProps.route.breadcrumbName}}</span>
|
||||
</template>
|
||||
<router-view v-slot='{ Component}'>
|
||||
<component :is='Component' />
|
||||
</router-view>
|
||||
</j-pro-layout>
|
||||
<j-pro-layout
|
||||
v-bind="layoutConf"
|
||||
v-model:openKeys="state.openKeys"
|
||||
v-model:collapsed="state.collapsed"
|
||||
v-model:selectedKeys="state.selectedKeys"
|
||||
:pure="state.pure"
|
||||
:breadcrumb="{ routes: breadcrumb }"
|
||||
>
|
||||
<template #breadcrumbRender="slotProps">
|
||||
<a v-if="slotProps.route.index !== 0">{{
|
||||
slotProps.route.breadcrumbName
|
||||
}}</a>
|
||||
<span v-else>{{ slotProps.route.breadcrumbName }}</span>
|
||||
</template>
|
||||
<template #rightContentRender>
|
||||
<div style="margin-right: 24px;display: flex;align-items: center;">
|
||||
<AIcon type="QuestionCircleOutlined" @click="toDoc" />
|
||||
<Notice style="margin: 0 24px;" />
|
||||
<UserInfo />
|
||||
</div>
|
||||
</template>
|
||||
<router-view v-slot="{ Component }">
|
||||
<component :is="Component" />
|
||||
</router-view>
|
||||
</j-pro-layout>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts" name='BasicLayoutPage'>
|
||||
import DefaultSetting from '../../../config/config'
|
||||
import { useMenuStore } from '@/store/menu'
|
||||
import { clearMenuItem } from 'jetlinks-ui-components/es/ProLayout/util'
|
||||
<script setup lang="ts" name="BasicLayoutPage">
|
||||
import UserInfo from './components/UserInfo.vue';
|
||||
import Notice from './components/Notice.vue'
|
||||
import DefaultSetting from '../../../config/config';
|
||||
import { useMenuStore } from '@/store/menu';
|
||||
import { clearMenuItem } from 'jetlinks-ui-components/es/ProLayout/util';
|
||||
|
||||
type StateType = {
|
||||
collapsed: boolean
|
||||
openKeys: string[]
|
||||
selectedKeys: string[]
|
||||
pure: boolean
|
||||
}
|
||||
collapsed: boolean;
|
||||
openKeys: string[];
|
||||
selectedKeys: string[];
|
||||
pure: boolean;
|
||||
};
|
||||
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
const router = useRouter();
|
||||
const route = useRoute();
|
||||
|
||||
const menu = useMenuStore()
|
||||
const menu = useMenuStore();
|
||||
|
||||
const layoutConf = reactive({
|
||||
theme: DefaultSetting.layout.theme,
|
||||
siderWidth: DefaultSetting.layout.siderWidth,
|
||||
logo: DefaultSetting.layout.logo,
|
||||
title: DefaultSetting.layout.title,
|
||||
menuData: clearMenuItem(menu.siderMenus),
|
||||
splitMenus: true
|
||||
theme: DefaultSetting.layout.theme,
|
||||
siderWidth: DefaultSetting.layout.siderWidth,
|
||||
logo: DefaultSetting.layout.logo,
|
||||
title: DefaultSetting.layout.title,
|
||||
menuData: clearMenuItem(menu.siderMenus),
|
||||
splitMenus: true,
|
||||
});
|
||||
|
||||
const state = reactive<StateType>({
|
||||
pure: false,
|
||||
collapsed: false, // default value
|
||||
openKeys: [],
|
||||
selectedKeys: [],
|
||||
pure: false,
|
||||
collapsed: false, // default value
|
||||
openKeys: [],
|
||||
selectedKeys: [],
|
||||
});
|
||||
|
||||
const breadcrumb = computed(() =>
|
||||
router.currentRoute.value.matched.concat().map((item, index) => {
|
||||
return {
|
||||
index,
|
||||
path: item.path,
|
||||
breadcrumbName: item.meta.title || ''
|
||||
router.currentRoute.value.matched.concat().map((item, index) => {
|
||||
return {
|
||||
index,
|
||||
path: item.path,
|
||||
breadcrumbName: item.meta.title || '',
|
||||
};
|
||||
}),
|
||||
);
|
||||
|
||||
watchEffect(() => {
|
||||
if (router.currentRoute) {
|
||||
const matched = router.currentRoute.value.matched.concat();
|
||||
state.selectedKeys = matched.map((r) => r.path);
|
||||
state.openKeys = matched
|
||||
.filter((r) => r.path !== router.currentRoute.value.path)
|
||||
.map((r) => r.path);
|
||||
console.log(state.selectedKeys);
|
||||
}
|
||||
})
|
||||
)
|
||||
// TODO 获取当前路由中参数,用于控制pure
|
||||
});
|
||||
|
||||
watchEffect(() => {
|
||||
if (router.currentRoute) {
|
||||
const matched = router.currentRoute.value.matched.concat()
|
||||
state.selectedKeys = matched.map(r => r.path)
|
||||
state.openKeys = matched.filter((r) => r.path !== router.currentRoute.value.path).map(r => r.path)
|
||||
console.log(state.selectedKeys)
|
||||
}
|
||||
// TODO 获取当前路由中参数,用于控制pure
|
||||
})
|
||||
if (
|
||||
route.query &&
|
||||
'layout' in route.query &&
|
||||
route.query.layout === 'false'
|
||||
) {
|
||||
state.pure = true;
|
||||
} else {
|
||||
state.pure = false;
|
||||
}
|
||||
});
|
||||
|
||||
watchEffect(() => {
|
||||
if (route.query && 'layout' in route.query && route.query.layout === 'false') {
|
||||
state.pure = true
|
||||
} else {
|
||||
state.pure = false
|
||||
}
|
||||
})
|
||||
|
||||
const toDoc = ()=>window.open('http://doc.v2.jetlinks.cn/')
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
</style>
|
||||
<style scoped></style>
|
||||
|
|
|
@ -0,0 +1,99 @@
|
|||
<template>
|
||||
<div class="notice-container">
|
||||
<a-dropdown :trigger="['click']" @visible-change="visibleChange">
|
||||
<div class="icon-content">
|
||||
<AIcon
|
||||
type="BellOutlined"
|
||||
@click.prevent
|
||||
style="font-size: 16px"
|
||||
/>
|
||||
<span class="unread" v-show="total > 0">{{ total }}</span>
|
||||
</div>
|
||||
<template #overlay>
|
||||
<div>
|
||||
<NoticeInfo :data="list" @on-action="getList" />
|
||||
</div>
|
||||
</template>
|
||||
</a-dropdown>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { getList_api } from '@/api/account/notificationRecord';
|
||||
import NoticeInfo from './NoticeInfo.vue';
|
||||
import { getWebSocket } from '@/utils/websocket';
|
||||
import { notification } from 'ant-design-vue';
|
||||
import { changeStatus_api } from '@/api/account/notificationRecord';
|
||||
import { useUserInfo } from '@/store/userInfo';
|
||||
|
||||
const updateCount = computed(()=>useUserInfo().$state.alarmUpdateCount);
|
||||
|
||||
const total = ref(0);
|
||||
const list = ref<any[]>([]);
|
||||
const loading = ref(false);
|
||||
|
||||
const subscribeNotice = () => {
|
||||
getWebSocket('notification', '/notifications', {})
|
||||
?.pipe()
|
||||
.subscribe((resp: any) => {
|
||||
total.value += 1;
|
||||
notification.open({
|
||||
message: 'Notification Title',
|
||||
description:
|
||||
'This is the content of the notification. This is the content of the notification. This is the content of the notification.',
|
||||
onClick: () => {
|
||||
changeStatus_api('_read', [resp.id]);
|
||||
},
|
||||
});
|
||||
});
|
||||
};
|
||||
const getList = () => {
|
||||
loading.value = true;
|
||||
const params = {
|
||||
'terms[0].column': 'state',
|
||||
'terms[0].value': 'unread',
|
||||
'sorts[0].name': 'notifyTime',
|
||||
'sorts[0].order': 'desc',
|
||||
};
|
||||
getList_api(params)
|
||||
.then((resp: any) => {
|
||||
list.value = resp.result.data;
|
||||
total.value = resp.result.total;
|
||||
})
|
||||
.finally(() => (loading.value = false));
|
||||
};
|
||||
subscribeNotice();
|
||||
getList();
|
||||
watch(updateCount, () => getList());
|
||||
const visibleChange = (bool: boolean) => {
|
||||
bool && getList();
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.notice-container {
|
||||
.icon-content {
|
||||
height: 48px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
|
||||
.unread {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: -12px;
|
||||
min-width: 20px;
|
||||
height: 20px;
|
||||
padding: 0 6px;
|
||||
color: #fff;
|
||||
font-weight: normal;
|
||||
font-size: 12px;
|
||||
line-height: 20px;
|
||||
white-space: nowrap;
|
||||
text-align: center;
|
||||
background: #ff4d4f;
|
||||
border-radius: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,122 @@
|
|||
<template>
|
||||
<div class="notice-info-container">
|
||||
<a-tabs :activeKey="'default'">
|
||||
<a-tab-pane key="default" tab="未读消息">
|
||||
<div class="no-data" v-if="props.data.length === 0">
|
||||
<img src="https://gw.alipayobjects.com/zos/rmsportal/sAuJeJzSKbUmHfBQRzmZ.svg" alt="" />
|
||||
</div>
|
||||
|
||||
<div v-else class="content">
|
||||
<ul class="list">
|
||||
<li
|
||||
class="list-item"
|
||||
v-for="item in props.data"
|
||||
@click="read(item.id)"
|
||||
>
|
||||
<h5>{{ item.topicName }}</h5>
|
||||
<p>{{ item.message }}</p>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="btns">
|
||||
<span @click="read()">当前标记为已读</span>
|
||||
<span @click="jumpPage('account/NotificationRecord')"
|
||||
>查看更多</span
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</a-tab-pane>
|
||||
</a-tabs>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { changeStatus_api } from '@/api/account/notificationRecord';
|
||||
import { useMenuStore } from '@/store/menu';
|
||||
|
||||
const emits = defineEmits(['onAction']);
|
||||
const props = defineProps<{
|
||||
data: any[];
|
||||
}>();
|
||||
const { jumpPage } = useMenuStore();
|
||||
|
||||
const read = (id?: string) => {
|
||||
const ids = id ? [id] : props.data.map((item) => item.id);
|
||||
changeStatus_api('_read', ids).then((resp:any) => {
|
||||
if (resp.status === 200) emits('onAction');
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.notice-info-container {
|
||||
width: 336px;
|
||||
background-color: #fff;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 6px 16px -8px rgb(0 0 0 / 8%), 0 9px 28px 0 rgb(0 0 0 / 5%),
|
||||
0 12px 48px 16px rgb(0 0 0 / 3%);
|
||||
|
||||
:deep(.ant-tabs-nav-wrap) {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.no-data {
|
||||
width: 100%;
|
||||
padding: 73px 0 88px;
|
||||
color: rgba(0, 0, 0, 0.45);
|
||||
text-align: center;
|
||||
|
||||
img {
|
||||
height: 76px;
|
||||
}
|
||||
}
|
||||
|
||||
.content {
|
||||
.list {
|
||||
max-height: 400px;
|
||||
overflow: auto;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
&::-webkit-scrollbar {
|
||||
//隐藏或取消滚动条
|
||||
display: none;
|
||||
}
|
||||
|
||||
.list-item {
|
||||
padding: 12px 24px;
|
||||
list-style: none;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
cursor: pointer;
|
||||
h5 {
|
||||
color: rgba(0, 0, 0, 0.85);
|
||||
font-size: 14px;
|
||||
font-weight: normal;
|
||||
}
|
||||
p {
|
||||
font-size: 12px;
|
||||
color: rgba(0, 0, 0, 0.45);
|
||||
}
|
||||
|
||||
&:hover{
|
||||
background: #f0f5ff;
|
||||
}
|
||||
}
|
||||
}
|
||||
.btns {
|
||||
display: flex;
|
||||
height: 46px;
|
||||
line-height: 46px;
|
||||
span {
|
||||
display: block;
|
||||
width: 50%;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
|
||||
&:first-child {
|
||||
border-right: 1px solid #f0f0f0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,45 @@
|
|||
<template>
|
||||
<div>
|
||||
<a-dropdown placement="bottomRight">
|
||||
<div style="cursor: pointer;height: 100%;">
|
||||
<img
|
||||
:src="userInfo.avatar"
|
||||
alt=""
|
||||
style="width: 24px; margin-right: 12px"
|
||||
/>
|
||||
<span>{{ userInfo.name }}</span>
|
||||
</div>
|
||||
<template #overlay>
|
||||
<a-menu>
|
||||
<a-menu-item @click="push('/account/center')" style="width: 160px;">
|
||||
<AIcon type="UserOutlined" style="margin-right: 8px;" />
|
||||
<span>个人中心</span>
|
||||
</a-menu-item>
|
||||
<a-menu-item @click="logOut">
|
||||
<AIcon type="LogoutOutlined" style="margin-right: 8px;" />
|
||||
<span>退出登录</span>
|
||||
</a-menu-item>
|
||||
</a-menu>
|
||||
</template>
|
||||
</a-dropdown>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { loginout_api } from '@/api/login';
|
||||
import { useUserInfo } from '@/store/userInfo';
|
||||
|
||||
const {push} = useRouter();
|
||||
|
||||
const userInfo = useUserInfo().$state.userInfos as any;
|
||||
|
||||
|
||||
const logOut = () => {
|
||||
loginout_api().then(() => {
|
||||
localStorage.clear();
|
||||
push('/user/login');
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
|
@ -0,0 +1,36 @@
|
|||
<svg width="58" height="50" viewBox="0 0 58 50" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M29 49.5794C45.0163 49.5794 58 46.8079 58 43.3891C58 39.9702 45.0163 37.1987 29 37.1987C12.9837 37.1987 0 39.9702 0 43.3891C0 46.8079 12.9837 49.5794 29 49.5794Z" fill="#FAFAFA"/>
|
||||
<path d="M33.2639 9.99902L9.93594 16.3635C9.47351 16.4896 9.43643 17.1312 9.88123 17.3098L26.5406 23.999L49.1273 18.1035C49.5839 17.9843 49.6364 17.3571 49.206 17.1637L33.2639 9.99902Z" fill="#FAFAFA" stroke="#E0E0E0"/>
|
||||
<path d="M24.2975 4.69484C25.7779 5.25264 26.8448 8.08321 25.7779 9.45134L22.4067 10.9999C21.6665 10.2491 20.7123 8.2462 21.0824 6.52395C21.2746 5.62954 21.4884 5.19123 22.1983 4.7653C22.8554 4.37107 23.7889 4.5032 24.2975 4.69484Z" fill="white" stroke="#E0E0E0"/>
|
||||
<path d="M35.2162 3.78468C33.7358 4.34248 32.6689 7.17306 33.7358 8.54119L37.107 10.0897C37.8472 9.33897 38.8014 7.33604 38.4313 5.61379C38.2391 4.71939 38.0253 4.28107 37.3153 3.85514C36.6583 3.46091 35.7248 3.59304 35.2162 3.78468Z" fill="white" stroke="#E0E0E0"/>
|
||||
<mask id="path-5-inside-1_990_11491" fill="white">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M42.5449 17.5308C42.5432 17.4907 42.5411 17.4504 42.5387 17.4099C42.3461 14.2156 40.8848 9.80379 37.5252 7.09156C35.6005 5.42908 33.0395 4.3785 29.6986 4.65434C26.3456 4.78127 23.9278 6.13333 22.2162 8.01686C19.2086 11.1131 18.2885 15.6671 18.4811 18.8607C18.4835 18.9011 18.4863 18.9414 18.4894 18.9814C18.515 19.5938 18.6444 20.1629 18.8655 20.688C20.262 24.3125 25.1708 25.5541 30.934 25.2065C30.9736 25.2042 31.0131 25.2017 31.0526 25.1991C36.7632 24.8346 41.4308 23.0119 42.3762 19.2717C42.533 18.7234 42.5931 18.1424 42.5449 17.5308Z"/>
|
||||
</mask>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M42.5449 17.5308C42.5432 17.4907 42.5411 17.4504 42.5387 17.4099C42.3461 14.2156 40.8848 9.80379 37.5252 7.09156C35.6005 5.42908 33.0395 4.3785 29.6986 4.65434C26.3456 4.78127 23.9278 6.13333 22.2162 8.01686C19.2086 11.1131 18.2885 15.6671 18.4811 18.8607C18.4835 18.9011 18.4863 18.9414 18.4894 18.9814C18.515 19.5938 18.6444 20.1629 18.8655 20.688C20.262 24.3125 25.1708 25.5541 30.934 25.2065C30.9736 25.2042 31.0131 25.2017 31.0526 25.1991C36.7632 24.8346 41.4308 23.0119 42.3762 19.2717C42.533 18.7234 42.5931 18.1424 42.5449 17.5308Z" fill="white"/>
|
||||
<path d="M42.5387 17.4099L43.5369 17.3497L43.5369 17.3497L42.5387 17.4099ZM42.5449 17.5308L41.5459 17.5738L41.5466 17.5916L41.548 17.6094L42.5449 17.5308ZM37.5252 7.09156L36.8715 7.84832L36.8841 7.8592L36.897 7.86964L37.5252 7.09156ZM29.6986 4.65434L29.7364 5.65362L29.7587 5.65278L29.7809 5.65095L29.6986 4.65434ZM22.2162 8.01686L22.9335 8.71363L22.9451 8.7017L22.9563 8.68938L22.2162 8.01686ZM18.4811 18.8607L17.4829 18.9209L18.4811 18.8607ZM18.4894 18.9814L19.4885 18.9396L19.4878 18.9217L19.4864 18.904L18.4894 18.9814ZM18.8655 20.688L19.7987 20.3284L19.7931 20.3141L19.7871 20.2999L18.8655 20.688ZM31.0526 25.1991L30.9889 24.2011L30.9878 24.2012L31.0526 25.1991ZM42.3762 19.2717L41.4148 18.9968L41.4105 19.0117L41.4067 19.0266L42.3762 19.2717ZM41.5405 17.4701C41.5426 17.5049 41.5444 17.5394 41.5459 17.5738L43.544 17.4879C43.5421 17.442 43.5397 17.3959 43.5369 17.3497L41.5405 17.4701ZM36.897 7.86964C39.9727 10.3527 41.359 14.4604 41.5405 17.4701L43.5369 17.3497C43.3331 13.9708 41.7968 9.2549 38.1533 6.31347L36.897 7.86964ZM38.1788 6.33479C36.0609 4.50532 33.2375 3.35875 29.6163 3.65773L29.7809 5.65095C32.8416 5.39825 35.1402 6.35285 36.8715 7.84832L38.1788 6.33479ZM22.9563 8.68938C24.496 6.99503 26.6647 5.76991 29.7364 5.65362L29.6608 3.65505C26.0266 3.79264 23.3597 5.27163 21.4761 7.34434L22.9563 8.68938ZM21.4989 7.3201C18.2372 10.6779 17.2792 15.5428 17.4829 18.9209L19.4793 18.8005C19.2978 15.7915 20.18 11.5483 22.9335 8.71363L21.4989 7.3201ZM17.4829 18.9209C17.4857 18.967 17.4888 19.013 17.4924 19.0588L19.4864 18.904C19.4837 18.8697 19.4814 18.8352 19.4793 18.8005L17.4829 18.9209ZM19.7871 20.2999C19.6131 19.8867 19.5093 19.435 19.4885 18.9396L17.4903 19.0232C17.5208 19.7525 17.6756 20.439 17.9439 21.0761L19.7871 20.2999ZM17.9324 21.0475C18.7723 23.2274 20.6451 24.6048 22.941 25.3838C25.2296 26.1603 28.0393 26.3829 30.9942 26.2047L30.8738 24.2084C28.0655 24.3777 25.5393 24.1534 23.5835 23.4898C21.6351 22.8288 20.3553 21.7731 19.7987 20.3284L17.9324 21.0475ZM30.9942 26.2047C31.0353 26.2023 31.0763 26.1997 31.1174 26.197L30.9878 24.2012C30.9499 24.2037 30.9119 24.2061 30.8738 24.2084L30.9942 26.2047ZM41.4067 19.0266C41.0298 20.5176 39.8986 21.7128 38.0652 22.6014C36.2245 23.4935 33.7708 24.0236 30.9889 24.2011L31.1163 26.1971C34.045 26.0101 36.7804 25.4466 38.9375 24.4012C41.1019 23.3522 42.7772 21.766 43.3457 19.5167L41.4067 19.0266ZM43.3377 19.5465C43.5279 18.8813 43.5992 18.1806 43.5419 17.4523L41.548 17.6094C41.587 18.1042 41.5381 18.5654 41.4148 18.9968L43.3377 19.5465Z" fill="#E0E0E0" mask="url(#path-5-inside-1_990_11491)"/>
|
||||
<ellipse cx="21.5982" cy="19.5977" rx="2.27602" ry="1.30058" transform="rotate(-3.45082 21.5982 19.5977)" fill="#F4F4F4"/>
|
||||
<ellipse cx="2.27602" cy="1.30058" rx="2.27602" ry="1.30058" transform="matrix(-0.974459 0.224564 0.224564 0.974459 43.8887 15.7603)" fill="#F4F4F4"/>
|
||||
<circle cx="26.0809" cy="15.0666" r="1.84249" transform="rotate(-3.45082 26.0809 15.0666)" fill="#E0E0E0"/>
|
||||
<circle cx="26.6121" cy="14.6075" r="0.650291" transform="rotate(-3.45082 26.6121 14.6075)" fill="white"/>
|
||||
<circle cx="25.4848" cy="15.971" r="0.325146" transform="rotate(-3.45082 25.4848 15.971)" fill="white"/>
|
||||
<circle cx="37.7645" cy="14.362" r="1.84249" transform="rotate(-3.45082 37.7645 14.362)" fill="#E0E0E0"/>
|
||||
<circle cx="38.2937" cy="13.9029" r="0.650291" transform="rotate(-3.45082 38.2937 13.9029)" fill="white"/>
|
||||
<circle cx="37.1683" cy="15.2669" r="0.325146" transform="rotate(-3.45082 37.1683 15.2669)" fill="white"/>
|
||||
<ellipse cx="32.3087" cy="16.6698" rx="1.51282" ry="1.23036" transform="rotate(-3.45082 32.3087 16.6698)" fill="#E0E0E0"/>
|
||||
<mask id="mask0_990_11491" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="28" y="19" width="8" height="4">
|
||||
<path d="M28.8401 21.0038C29.1929 20.5749 29.549 20.2953 30.0249 20.0923C30.5162 19.8826 31.1577 19.7447 32.1 19.6404C33.021 19.5386 33.5501 19.5974 33.9102 19.7125C34.2573 19.8235 34.4861 19.9957 34.8185 20.246C34.8296 20.2544 34.8408 20.2628 34.8521 20.2713C35.02 20.3977 35.1717 20.6012 35.2384 20.787C35.2708 20.8773 35.274 20.938 35.2703 20.9682C35.2681 20.9866 35.2652 20.9882 35.2637 20.989C35.2635 20.9891 35.2633 20.9892 35.2632 20.9893C34.8844 21.3249 34.6341 21.5424 34.2159 21.7233C33.7851 21.9096 33.148 22.067 32.0018 22.1938C30.8548 22.3207 30.2398 22.3016 29.8387 22.2257C29.513 22.164 29.319 22.0665 29.0343 21.9233C28.9772 21.8947 28.9166 21.8642 28.8504 21.8317C28.7416 21.7784 28.657 21.6792 28.6311 21.5668C28.609 21.4712 28.6107 21.2826 28.8401 21.0038Z" fill="#FD7477" stroke="#666666"/>
|
||||
</mask>
|
||||
<g mask="url(#mask0_990_11491)">
|
||||
<path d="M31.2438 19.4706L31.0537 18.6566C31.0373 18.5863 31.1139 18.545 31.1837 18.5631C31.3003 18.5935 31.4791 18.5924 31.6924 18.4731C32.0018 18.3001 32.1775 17.9936 32.2267 17.862L32.3581 20.041L32.0351 20.0605C31.6628 20.083 31.3286 19.8338 31.2438 19.4706Z" fill="white" stroke="#E0E0E0" stroke-width="0.5"/>
|
||||
<path d="M33.4522 19.3375L33.543 18.5065C33.5509 18.4348 33.4699 18.403 33.4028 18.4294C33.2906 18.4735 33.113 18.4939 32.887 18.4012C32.559 18.2666 32.3477 17.9835 32.2831 17.8587L32.4145 20.0378L32.7374 20.0183C33.1097 19.9958 33.4116 19.7083 33.4522 19.3375Z" fill="white" stroke="#E0E0E0" stroke-width="0.5"/>
|
||||
</g>
|
||||
<path d="M31.421 18.7266C30.2561 19.2905 29.7431 20.4957 29.7177 20.5566C29.7081 20.5796 29.7032 20.6044 29.7031 20.6293C29.7031 20.6543 29.708 20.679 29.7175 20.7021C29.727 20.7252 29.741 20.7462 29.7587 20.7639C29.7763 20.7815 29.7972 20.7956 29.8203 20.8052C29.8434 20.8147 29.8681 20.8197 29.893 20.8197C29.918 20.8198 29.9428 20.8149 29.9658 20.8053C29.9889 20.7958 30.0099 20.7818 30.0276 20.7642C30.0453 20.7466 30.0593 20.7256 30.0689 20.7026C30.0756 20.6866 30.6789 19.416 32.19 19.1705C33.6941 18.926 34.9386 20.104 34.9503 20.119C34.9812 20.1584 35.0264 20.184 35.076 20.1903C35.1257 20.1966 35.1758 20.183 35.2155 20.1526C35.2553 20.1222 35.2814 20.0773 35.2882 20.0277C35.2951 19.9781 35.2821 19.9278 35.2522 19.8878C35.0034 19.5814 34.7147 19.3099 34.3937 19.0805C33.6826 18.5696 32.926 18.3613 32.2053 18.4785C31.9332 18.5227 31.669 18.6063 31.421 18.7266Z" fill="#E0E0E0" stroke="#E0E0E0" stroke-width="0.1"/>
|
||||
<line x1="23.7287" y1="18.1659" x2="23.5991" y2="18.5272" stroke="#E0E0E0" stroke-width="0.7" stroke-linecap="round"/>
|
||||
<line x1="24.9494" y1="18.31" x2="24.893" y2="18.4672" stroke="#E0E0E0" stroke-width="0.7" stroke-linecap="round"/>
|
||||
<line x1="0.35" y1="-0.35" x2="0.733819" y2="-0.35" transform="matrix(0.44853 0.893768 0.893768 -0.44853 40.4297 15.9731)" stroke="#E0E0E0" stroke-width="0.7" stroke-linecap="round"/>
|
||||
<line x1="0.35" y1="-0.35" x2="0.517055" y2="-0.35" transform="matrix(0.448552 0.893757 0.893757 -0.448552 39.2363 16.2622)" stroke="#E0E0E0" stroke-width="0.7" stroke-linecap="round"/>
|
||||
<path d="M9 17.5027C9 17.1455 9.36388 16.9035 9.69336 17.0416L25 23.4605V46.2127L9 38.7176V17.5027Z" fill="#FBFBFB" stroke="#E0E0E0"/>
|
||||
<path d="M8.74631 16.66L24.8561 23.8265L22.245 30.3166L6.15202 22.5625L8.74631 16.66Z" fill="white" stroke="#E0E0E0"/>
|
||||
<path d="M50 18.2859C50 17.9597 49.6926 17.7208 49.3765 17.8014L25.5 23.8878V45.8708C25.5 46.2033 25.8185 46.4432 26.1381 46.3513L50 39.4934V18.2859Z" fill="#F4F4F4" stroke="#E0E0E0"/>
|
||||
<path d="M50.0635 18.0495C49.9823 17.7978 49.719 17.6529 49.4628 17.719L26.1262 23.7393L28.0893 30.3834L51.865 23.6308L50.0635 18.0495Z" fill="white" stroke="#E0E0E0"/>
|
||||
</svg>
|
After Width: | Height: | Size: 9.4 KiB |
|
@ -0,0 +1,466 @@
|
|||
<!-- 分屏组件 -->
|
||||
<template>
|
||||
<div class="live-player-warp">
|
||||
<div class="live-player-content">
|
||||
<!-- 工具栏 -->
|
||||
<div class="player-screen-tool" v-if="showScreen">
|
||||
<a-radio-group
|
||||
v-model:value="screen"
|
||||
button-style="solid"
|
||||
@change="handleScreenChange"
|
||||
>
|
||||
<a-radio-button :value="1">单屏</a-radio-button>
|
||||
<a-radio-button :value="4">四分屏</a-radio-button>
|
||||
<a-radio-button :value="9">九分屏</a-radio-button>
|
||||
<a-radio-button :value="0">全屏</a-radio-button>
|
||||
</a-radio-group>
|
||||
<div class="screen-tool-save">
|
||||
<a-tooltip title="可保存分屏配置记录">
|
||||
<AIcon type="QuestionCircleOutlined" />
|
||||
</a-tooltip>
|
||||
<a-popover
|
||||
v-model:visible="visible"
|
||||
trigger="click"
|
||||
title="分屏名称"
|
||||
>
|
||||
<template #content>
|
||||
<a-form
|
||||
ref="formRef"
|
||||
:model="formData"
|
||||
layout="vertical"
|
||||
>
|
||||
<a-form-item
|
||||
name="name"
|
||||
:rules="[
|
||||
{
|
||||
required: true,
|
||||
message: '请输入名称',
|
||||
},
|
||||
{
|
||||
max: 64,
|
||||
message: '最多可输入64个字符',
|
||||
},
|
||||
]"
|
||||
>
|
||||
<a-textarea v-model:value="formData.name" />
|
||||
</a-form-item>
|
||||
<a-button
|
||||
type="primary"
|
||||
@click="saveHistory"
|
||||
:loading="loading"
|
||||
style="width: 100%; margin-top: 16px"
|
||||
>
|
||||
保存
|
||||
</a-button>
|
||||
</a-form>
|
||||
</template>
|
||||
<a-dropdown-button
|
||||
type="primary"
|
||||
@click="visible = true"
|
||||
>
|
||||
保存
|
||||
<template #overlay>
|
||||
<a-menu>
|
||||
<a-empty
|
||||
v-if="!historyList.length"
|
||||
description="暂无数据"
|
||||
/>
|
||||
<a-menu-item
|
||||
v-for="(item, index) in historyList"
|
||||
:key="`his${index}`"
|
||||
@click="handleHistory(item)"
|
||||
>
|
||||
<a-space>
|
||||
<span>{{ item.name }}</span>
|
||||
<a-popconfirm
|
||||
title="确认删除?"
|
||||
ok-text="确认"
|
||||
cancel-text="取消"
|
||||
@confirm="(e: any) => {
|
||||
e?.stopPropagation();
|
||||
deleteHistory(item.key);
|
||||
}
|
||||
"
|
||||
>
|
||||
<AIcon
|
||||
type="DeleteOutlined"
|
||||
@click="
|
||||
(e:any) =>
|
||||
e?.stopPropagation()
|
||||
"
|
||||
/>
|
||||
</a-popconfirm>
|
||||
</a-space>
|
||||
</a-menu-item>
|
||||
</a-menu>
|
||||
</template>
|
||||
</a-dropdown-button>
|
||||
</a-popover>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 播放器 -->
|
||||
<div class="player-body">
|
||||
<div
|
||||
ref="fullscreenRef"
|
||||
class="player-screen"
|
||||
:class="`screen-${screen}`"
|
||||
>
|
||||
<template v-for="(item, index) in players" :key="item.key">
|
||||
<div
|
||||
class="player-screen-item"
|
||||
:class="{
|
||||
active:
|
||||
showScreen &&
|
||||
playerActive === index &&
|
||||
!isFullscreen,
|
||||
'full-screen': isFullscreen,
|
||||
}"
|
||||
:style="{ display: item.show ? 'block' : 'none' }"
|
||||
@click="playerActive = index"
|
||||
>
|
||||
<div
|
||||
class="media-btn-refresh"
|
||||
:style="{
|
||||
display: item.url ? 'block' : 'none',
|
||||
}"
|
||||
@click="handleRefresh($event, item, index)"
|
||||
>
|
||||
刷新
|
||||
</div>
|
||||
<LivePlayer
|
||||
:src="item.url"
|
||||
:width="screenWidth"
|
||||
:height="screenHeight"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 控制器 -->
|
||||
</div>
|
||||
<MediaTool @onMouseDown="handleMouseDown" @onMouseUp="handleMouseUp" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useFullscreen } from '@vueuse/core';
|
||||
import {
|
||||
deleteSearchHistory,
|
||||
getSearchHistory,
|
||||
saveSearchHistory,
|
||||
} from '@/api/comm';
|
||||
import { message } from 'ant-design-vue';
|
||||
import LivePlayer from '@/components/Player/index.vue';
|
||||
import MediaTool from '@/components/Player/mediaTool.vue';
|
||||
|
||||
type Player = {
|
||||
id?: string;
|
||||
url?: string;
|
||||
channelId?: string;
|
||||
key: string;
|
||||
show: boolean;
|
||||
};
|
||||
|
||||
interface ScreenProps {
|
||||
url?: string;
|
||||
id?: string;
|
||||
channelId: string;
|
||||
className?: string;
|
||||
historyHandle?: (deviceId: string, channelId: string) => string;
|
||||
/**
|
||||
*
|
||||
* @param id 当前选中播发视频ID
|
||||
* @param type 当前操作动作
|
||||
*/
|
||||
onMouseDown?: (deviceId: string, channelId: string, type: string) => void;
|
||||
/**
|
||||
*
|
||||
* @param id 当前选中播发视频ID
|
||||
* @param type 当前操作动作
|
||||
*/
|
||||
onMouseUp?: (deviceId: string, channelId: string, type: string) => void;
|
||||
showScreen?: boolean;
|
||||
}
|
||||
|
||||
const props = defineProps<ScreenProps>();
|
||||
|
||||
const DEFAULT_SAVE_CODE = 'screen-save';
|
||||
|
||||
// 分屏数量 1/4/9/0
|
||||
const screen = ref(1);
|
||||
// 视频窗口
|
||||
const players = ref<Player[]>([]);
|
||||
// 当前选中的窗口
|
||||
const playerActive = ref(0);
|
||||
// 单个播放窗口宽高
|
||||
const screenWidth = ref('');
|
||||
const screenHeight = ref('');
|
||||
// 历史记录
|
||||
const historyList = ref<any[]>([]);
|
||||
// 展示保存浮窗
|
||||
const visible = ref(false);
|
||||
const loading = ref(false);
|
||||
// 保存表单
|
||||
const formRef = ref();
|
||||
const formData = ref({
|
||||
name: '',
|
||||
});
|
||||
|
||||
// 全屏元素
|
||||
const fullscreenRef = ref(null);
|
||||
const { isFullscreen, enter, exit, toggle } = useFullscreen(
|
||||
fullscreenRef.value,
|
||||
);
|
||||
|
||||
/**
|
||||
* 刷新视频
|
||||
* @param id
|
||||
* @param channelId
|
||||
* @param url
|
||||
* @param index
|
||||
*/
|
||||
const reloadPlayer = (
|
||||
id: string,
|
||||
channelId: string,
|
||||
url: string,
|
||||
index: number,
|
||||
) => {
|
||||
const olPlayers = [...players.value];
|
||||
olPlayers[index] = {
|
||||
id: '',
|
||||
channelId: '',
|
||||
url: '',
|
||||
key: olPlayers[index].key,
|
||||
show: true,
|
||||
};
|
||||
const newPlayer = {
|
||||
id,
|
||||
url,
|
||||
channelId,
|
||||
key: olPlayers[index].key,
|
||||
show: true,
|
||||
};
|
||||
players.value = [...olPlayers];
|
||||
setTimeout(() => {
|
||||
olPlayers[index] = newPlayer;
|
||||
players.value = [...olPlayers];
|
||||
}, 1000);
|
||||
};
|
||||
|
||||
/**
|
||||
* 视频链接变化, 更新播放内容
|
||||
* @param id
|
||||
* @param channelId
|
||||
* @param url
|
||||
*/
|
||||
const replaceVideo = (id: string, channelId: string, url: string) => {
|
||||
const olPlayers = [...players.value];
|
||||
const newPlayer = {
|
||||
id,
|
||||
url,
|
||||
channelId,
|
||||
key: olPlayers[playerActive.value].key,
|
||||
show: true,
|
||||
};
|
||||
|
||||
if (olPlayers[playerActive.value].url === url) {
|
||||
// 刷新视频
|
||||
reloadPlayer(id, channelId, url, playerActive.value);
|
||||
} else {
|
||||
olPlayers[playerActive.value] = newPlayer;
|
||||
players.value = olPlayers;
|
||||
}
|
||||
if (playerActive.value === screen.value - 1) {
|
||||
// 当前位置为分屏最后一位
|
||||
playerActive.value = 0;
|
||||
} else {
|
||||
playerActive.value += 1;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 点击分屏历史记录
|
||||
* @param item
|
||||
*/
|
||||
const handleHistory = (item: any) => {
|
||||
if (props.historyHandle) {
|
||||
const log = JSON.parse(item.content || '{}');
|
||||
screen.value = log.screen;
|
||||
const oldPlayers = [...players.value];
|
||||
|
||||
players.value = oldPlayers.map((oldPlayer, index) => {
|
||||
oldPlayer.show = false;
|
||||
if (index < log.screen) {
|
||||
const { deviceId, channelId } = log.players[index];
|
||||
return {
|
||||
...oldPlayer,
|
||||
id: deviceId,
|
||||
channelId: deviceId,
|
||||
url: deviceId
|
||||
? props.historyHandle!(deviceId, channelId)
|
||||
: '',
|
||||
show: true,
|
||||
};
|
||||
}
|
||||
return oldPlayer;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取历史分屏
|
||||
*/
|
||||
const getHistory = async () => {
|
||||
const res = await getSearchHistory(DEFAULT_SAVE_CODE);
|
||||
if (res.success) {
|
||||
historyList.value = res.result;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 删除历史分屏
|
||||
* @param id
|
||||
*/
|
||||
const deleteHistory = async (id: string) => {
|
||||
const res = await deleteSearchHistory(DEFAULT_SAVE_CODE, id);
|
||||
if (res.success) {
|
||||
getHistory();
|
||||
visible.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 保存分屏
|
||||
*/
|
||||
const saveHistory = async () => {
|
||||
formRef.value
|
||||
.validate()
|
||||
.then(async () => {
|
||||
const param = {
|
||||
name: formData.value.name,
|
||||
content: JSON.stringify({
|
||||
screen: screen.value,
|
||||
players: players.value.map((item: any) => ({
|
||||
deviceId: item.id,
|
||||
channelId: item.channelId,
|
||||
})),
|
||||
}),
|
||||
};
|
||||
loading.value = true;
|
||||
const res = await saveSearchHistory(param, DEFAULT_SAVE_CODE);
|
||||
loading.value = false;
|
||||
if (res.success) {
|
||||
visible.value = false;
|
||||
getHistory();
|
||||
message.success('保存成功');
|
||||
formRef.value.resetFields();
|
||||
} else {
|
||||
message.error('保存失败');
|
||||
}
|
||||
})
|
||||
.catch((err: any) => {
|
||||
console.log(err);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 初始化
|
||||
*/
|
||||
const mediaInit = () => {
|
||||
const newArr = [];
|
||||
for (let i = 0; i < 9; i++) {
|
||||
newArr.push({
|
||||
id: '',
|
||||
channelId: '',
|
||||
url: '',
|
||||
key: 'time_' + new Date().getTime() + i,
|
||||
show: i === 0,
|
||||
});
|
||||
}
|
||||
players.value = newArr;
|
||||
};
|
||||
|
||||
/**
|
||||
* 改变分屏数量
|
||||
* @param e
|
||||
*/
|
||||
const handleScreenChange = (e: any) => {
|
||||
if (e.target.value) {
|
||||
screenChange(e.target.value);
|
||||
} else {
|
||||
// 全屏操作
|
||||
toggle();
|
||||
}
|
||||
};
|
||||
const screenChange = (index: number) => {
|
||||
players.value = players.value.map((m: any, i: number) => ({
|
||||
id: '',
|
||||
channelId: '',
|
||||
url: '',
|
||||
updateTime: 0,
|
||||
key: m.key,
|
||||
show: i < index,
|
||||
}));
|
||||
playerActive.value = 0;
|
||||
screen.value = index;
|
||||
|
||||
// if (screen.value === 4) {
|
||||
// screenWidth.value = '350px';
|
||||
// screenHeight.value = '2000px';
|
||||
// }
|
||||
};
|
||||
|
||||
/**
|
||||
* 刷新
|
||||
* @param e
|
||||
* @param item
|
||||
* @param index
|
||||
*/
|
||||
const handleRefresh = (e: any, item: any, index: number) => {
|
||||
e.stopPropagation();
|
||||
if (item.url) {
|
||||
reloadPlayer(item.id!, item.channelId!, item.url!, index);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 点击控制按钮
|
||||
* @param type 控制类型
|
||||
*/
|
||||
const handleMouseDown = (type: string) => {
|
||||
const { id, channelId } = players.value[playerActive.value];
|
||||
if (id && channelId && props.onMouseDown) {
|
||||
props.onMouseDown(id, channelId, type);
|
||||
}
|
||||
};
|
||||
const handleMouseUp = (type: string) => {
|
||||
const { id, channelId } = players.value[playerActive.value];
|
||||
if (id && channelId && props.onMouseUp) {
|
||||
props.onMouseUp(id, channelId, type);
|
||||
}
|
||||
};
|
||||
|
||||
watch(
|
||||
() => props.url,
|
||||
(val) => {
|
||||
if (val && props.id) {
|
||||
replaceVideo(props.id, props.channelId, val);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
watchEffect(() => {
|
||||
if (props.showScreen !== false) {
|
||||
getHistory();
|
||||
}
|
||||
mediaInit();
|
||||
});
|
||||
|
||||
defineExpose({
|
||||
replaceVideo,
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
@import './index.less';
|
||||
</style>
|
|
@ -0,0 +1,82 @@
|
|||
.live-player-warp {
|
||||
display: flex;
|
||||
|
||||
.live-player-content {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
|
||||
.player-screen-tool {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 20px;
|
||||
|
||||
.ant-radio-button-wrapper {
|
||||
height: auto;
|
||||
padding: 4px 20px;
|
||||
}
|
||||
}
|
||||
|
||||
.player-body {
|
||||
flex: 1;
|
||||
|
||||
.player-screen {
|
||||
position: relative;
|
||||
display: grid;
|
||||
box-sizing: border-box;
|
||||
|
||||
&.screen-1 {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
&.screen-4 {
|
||||
grid-template-rows: 1fr 1fr;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
}
|
||||
|
||||
&.screen-9 {
|
||||
grid-template-rows: 1fr 1fr 1fr;
|
||||
grid-template-columns: 1fr 1fr 1fr;
|
||||
}
|
||||
|
||||
&.screen-4,
|
||||
&.screen-9 {
|
||||
grid-gap: 12px;
|
||||
}
|
||||
|
||||
.active {
|
||||
border: 2px solid red;
|
||||
}
|
||||
|
||||
.full-screen {
|
||||
border: 1px solid #fff;
|
||||
}
|
||||
|
||||
.player-screen-item {
|
||||
position: relative;
|
||||
|
||||
.media-btn-refresh {
|
||||
position: absolute;
|
||||
top: 4px;
|
||||
right: 4px;
|
||||
z-index: 2;
|
||||
padding: 2px 4px;
|
||||
font-size: 12px;
|
||||
background-color: #f0f0f0;
|
||||
border-radius: 2px;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
background-color: #d9d9d9;
|
||||
}
|
||||
|
||||
&:active {
|
||||
background-color: #bfbfbf;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -10,6 +10,8 @@ import vue3videoPlay from 'vue3-video-play';
|
|||
const props = defineProps({
|
||||
src: { type: String, default: '' },
|
||||
type: { type: String, default: 'mp4' },
|
||||
width: { type: String, default: '500px' },
|
||||
height: { type: String, default: '280px' },
|
||||
});
|
||||
|
||||
watch(
|
||||
|
@ -21,8 +23,6 @@ watch(
|
|||
|
||||
const options = reactive({
|
||||
...props,
|
||||
width: '500px', //播放器高度
|
||||
height: '280px', //播放器高度
|
||||
color: '#409eff', //主题色
|
||||
title: '', //视频名称
|
||||
// src: props.src,
|
||||
|
|
|
@ -1,5 +1,49 @@
|
|||
export const LoginPath = '/login'
|
||||
|
||||
export const AccountMenu = {
|
||||
path: '/account',
|
||||
component: () => import('@/components/Layout/BasicLayoutPage.vue'),
|
||||
redirect: '/account/center',
|
||||
name: 'account',
|
||||
meta: {
|
||||
title: '个人中心',
|
||||
icon: '',
|
||||
hideInMenu: true
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: '/account/center',
|
||||
name: 'account/center',
|
||||
meta: {
|
||||
title: '基本设置',
|
||||
icon: '',
|
||||
hideInMenu: false
|
||||
},
|
||||
component: () => import('@/views/account/Center/index.vue')
|
||||
},
|
||||
{
|
||||
path: '/account/NotificationSubscription',
|
||||
name: 'account/NotificationSubscription',
|
||||
meta: {
|
||||
title: '通知订阅',
|
||||
icon: '',
|
||||
hideInMenu: false
|
||||
},
|
||||
component: () => import('@/views/account/NotificationSubscription/index.vue')
|
||||
},
|
||||
{
|
||||
path: '/account/NotificationRecord',
|
||||
name: 'account/NotificationRecord',
|
||||
meta: {
|
||||
title: '通知记录',
|
||||
icon: '',
|
||||
hideInMenu: false
|
||||
},
|
||||
component: () => import('@/views/account/NotificationRecord/index.vue')
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
export default [
|
||||
{ path: '/*', redirect: '/'},
|
||||
// start: 测试用, 可删除
|
||||
|
@ -27,18 +71,6 @@ export default [
|
|||
path: '/system/Api',
|
||||
component: () => import('@/views/system/Platforms/index.vue')
|
||||
},
|
||||
{
|
||||
path: '/account/center',
|
||||
component: () => import('@/views/account/Center/index.vue')
|
||||
},
|
||||
{
|
||||
path: '/account/NotificationSubscription',
|
||||
component: () => import('@/views/account/NotificationSubscription/index.vue')
|
||||
},
|
||||
{
|
||||
path: '/account/NotificationRecord',
|
||||
component: () => import('@/views/account/NotificationRecord/index.vue')
|
||||
},
|
||||
// end: 测试用, 可删除
|
||||
|
||||
// 初始化
|
||||
|
|
|
@ -4,8 +4,8 @@ import { filterAsnycRouter, MenuItem } from '@/utils/menu'
|
|||
import { isArray } from 'lodash-es'
|
||||
import { usePermissionStore } from './permission'
|
||||
import router from '@/router'
|
||||
import { message } from 'ant-design-vue'
|
||||
import { onlyMessage } from '@/utils/comm'
|
||||
import { AccountMenu } from '@/router/menu'
|
||||
|
||||
const defaultOwnParams = [
|
||||
{
|
||||
|
@ -115,8 +115,11 @@ export const useMenuStore = defineStore({
|
|||
hideInMenu: true
|
||||
}
|
||||
})
|
||||
menusData.push(AccountMenu)
|
||||
silderMenus.push(AccountMenu)
|
||||
this.siderMenus = silderMenus
|
||||
console.log('menusData', menusData)
|
||||
console.log('silderMenus', silderMenus)
|
||||
res(menusData)
|
||||
}
|
||||
})
|
||||
|
|
|
@ -20,7 +20,9 @@ export const useUserInfo = defineStore('userInfo', {
|
|||
token: '',
|
||||
user: {},
|
||||
},
|
||||
alarmUpdateCount: 0
|
||||
}),
|
||||
|
||||
actions: {
|
||||
login(userInfo: any) {
|
||||
const username = userInfo.userName.trim();
|
||||
|
@ -49,6 +51,9 @@ export const useUserInfo = defineStore('userInfo', {
|
|||
}
|
||||
}).catch(() => rej())
|
||||
})
|
||||
},
|
||||
updateAlarm(){
|
||||
this.alarmUpdateCount += 1
|
||||
}
|
||||
},
|
||||
});
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import type { Slots } from 'vue'
|
||||
import { TOKEN_KEY } from '@/utils/variable'
|
||||
import { message } from 'ant-design-vue'
|
||||
import { message } from 'jetlinks-ui-components';
|
||||
|
||||
/**
|
||||
* 静态图片资源处理
|
||||
|
|
|
@ -24,12 +24,17 @@ export const request = axios.create({
|
|||
* @param {String} url
|
||||
* @param {Object} [data]
|
||||
* @param {String} responseType 如果接口是需要导出文件流,那么responseType = 'blob'
|
||||
* @param {Object|String} [ext] 扩展参数,如果是配置headers,ext对象内包含headers对象,如下
|
||||
* {
|
||||
headers: {'Content-Type': 'text/plain;charset=UTF-8'},
|
||||
}
|
||||
* @returns {AxiosInstance}
|
||||
*/
|
||||
export const post = function<T>(url: string, data = {}, params = {}) {
|
||||
params = typeof params === 'string' ? { responseType: params } : params
|
||||
export const post = function<T>(url: string, data = {}, params = {}, ext={}) {
|
||||
ext = typeof ext === 'string' ? { responseType: ext } : ext
|
||||
return request<any, AxiosResponseRewrite<T>>({
|
||||
...params,
|
||||
...ext,
|
||||
params,
|
||||
method: 'POST',
|
||||
url,
|
||||
data
|
||||
|
|
|
@ -0,0 +1,315 @@
|
|||
<template lang="">
|
||||
<a-modal
|
||||
:title="data.id ? '编辑' : '新增'"
|
||||
:visible="true"
|
||||
width="700px"
|
||||
@cancel="handleCancel"
|
||||
>
|
||||
<a-form
|
||||
class="form"
|
||||
layout="vertical"
|
||||
:model="formData"
|
||||
name="basic"
|
||||
autocomplete="off"
|
||||
:rules="FormValidate"
|
||||
ref="formRef"
|
||||
>
|
||||
<a-form-item label="通道名称" name="name">
|
||||
<a-input
|
||||
placeholder="请输入通道名称"
|
||||
v-model:value="formData.name"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="通讯协议" name="provider">
|
||||
<a-select
|
||||
style="width: 100%"
|
||||
v-model:value="formData.provider"
|
||||
:options="providersList"
|
||||
placeholder="请选择通讯协议"
|
||||
allowClear
|
||||
show-search
|
||||
:filter-option="filterOption"
|
||||
:disabled="!!id"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
v-if="formData.provider === 'MODBUS_TCP'"
|
||||
:name="['configuration', 'host']"
|
||||
:rules="FormValidate.host"
|
||||
>
|
||||
<div class="form-label">
|
||||
Modbus主机IP
|
||||
<span class="form-label-required">*</span>
|
||||
<a-tooltip>
|
||||
<template #title>
|
||||
<p>支持ipv4、ipv6、域名</p>
|
||||
</template>
|
||||
<AIcon type="QuestionCircleOutlined" />
|
||||
</a-tooltip>
|
||||
</div>
|
||||
<a-input
|
||||
placeholder="请输入Modbus主机IP"
|
||||
v-model:value="formData.configuration.host"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
v-if="formData.provider === 'MODBUS_TCP'"
|
||||
label="端口"
|
||||
:name="['configuration', 'port']"
|
||||
:rules="FormValidate.port"
|
||||
>
|
||||
<a-input-number
|
||||
style="width: 100%"
|
||||
placeholder="请输入端口"
|
||||
v-model:value="formData.configuration.port"
|
||||
:min="1"
|
||||
:max="65535"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
v-if="formData.provider === 'OPC_UA'"
|
||||
label="端点url"
|
||||
:name="['configuration', 'endpoint']"
|
||||
:rules="FormValidate.endpoint"
|
||||
>
|
||||
<a-input
|
||||
placeholder="请输入端点url"
|
||||
v-model:value="formData.configuration.endpoint"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
v-if="formData.provider === 'OPC_UA'"
|
||||
label="安全策略"
|
||||
:name="['configuration.securityPolicy']"
|
||||
:rules="FormValidate.securityPolicy"
|
||||
>
|
||||
<a-select
|
||||
style="width: 100%"
|
||||
v-model:value="formData.configuration.securityPolicy"
|
||||
:options="Options['security-policies']"
|
||||
placeholder="请选择安全策略"
|
||||
allowClear
|
||||
show-search
|
||||
:filter-option="filterOption"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
v-if="formData.provider === 'OPC_UA'"
|
||||
label="安全模式"
|
||||
:name="['configuration.securityMode']"
|
||||
:rules="FormValidate.securityMode"
|
||||
>
|
||||
<a-select
|
||||
style="width: 100%"
|
||||
v-model:value="formData.configuration.securityMode"
|
||||
:options="Options['security-modes']"
|
||||
placeholder="请选择安全模式"
|
||||
allowClear
|
||||
show-search
|
||||
:filter-option="filterOption"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
v-if="
|
||||
formData.configuration.securityMode === 'SignAndEncrypt' ||
|
||||
formData.configuration.securityMode === 'Sign'
|
||||
"
|
||||
label="证书"
|
||||
:name="['configuration.certificate']"
|
||||
:rules="FormValidate.certificate"
|
||||
>
|
||||
<a-select
|
||||
style="width: 100%"
|
||||
v-model:value="formData.configuration.certificate"
|
||||
:options="certificateList"
|
||||
placeholder="请选择证书"
|
||||
allowClear
|
||||
show-search
|
||||
:filter-option="filterOption"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
v-if="formData.provider === 'OPC_UA'"
|
||||
label="权限认证"
|
||||
:name="['configuration.authType']"
|
||||
:rules="FormValidate.authType"
|
||||
>
|
||||
<RadioCard
|
||||
layout="horizontal"
|
||||
:checkStyle="true"
|
||||
:options="Options['auth-types']"
|
||||
v-model="formData.configuration.authType"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
v-if="formData.configuration.authType === 'username'"
|
||||
label="用户名"
|
||||
:name="['configuration.username']"
|
||||
:rules="FormValidate.username"
|
||||
>
|
||||
<a-input
|
||||
placeholder="请输入用户名"
|
||||
v-model:value="formData.configuration.username"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
v-if="formData.configuration.authType === 'username'"
|
||||
label="密码"
|
||||
:name="['configuration.password']"
|
||||
:rules="FormValidate.password"
|
||||
>
|
||||
<a-input-password
|
||||
placeholder="请输入密码"
|
||||
v-model:value="formData.configuration.password"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="说明" name="description">
|
||||
<a-textarea
|
||||
placeholder="请输入说明"
|
||||
v-model:value="formData.description"
|
||||
:maxlength="200"
|
||||
:rows="3"
|
||||
showCount
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
<template #footer>
|
||||
<a-button key="back" @click="handleCancel">取消</a-button>
|
||||
<PermissionButton
|
||||
key="submit"
|
||||
type="primary"
|
||||
:loading="loading"
|
||||
@click="handleOk"
|
||||
style="margin-left: 8px"
|
||||
:hasPermission="`DataCollect/Channel:${id ? 'update' : 'add'}`"
|
||||
>
|
||||
确认
|
||||
</PermissionButton>
|
||||
</template>
|
||||
</a-modal>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import {
|
||||
save,
|
||||
update,
|
||||
queryOptionsList,
|
||||
queryCertificateList,
|
||||
getProviders,
|
||||
} from '@/api/data-collect/channel';
|
||||
import { FormValidate, FormState } from '../data';
|
||||
import type { FormInstance } from 'ant-design-vue';
|
||||
import type { FormDataType } from '../type.d';
|
||||
|
||||
const props = defineProps({
|
||||
data: {
|
||||
type: Object,
|
||||
default: () => {},
|
||||
},
|
||||
});
|
||||
|
||||
const emit = defineEmits(['change']);
|
||||
const loading = ref(false);
|
||||
const id = props.data.id;
|
||||
const formRef = ref<FormInstance>();
|
||||
|
||||
const certificateList = ref([]);
|
||||
const providersList = ref([]);
|
||||
const Options = ref({
|
||||
'auth-types': [],
|
||||
'security-modes': [],
|
||||
'security-policies': [],
|
||||
});
|
||||
|
||||
const formData = ref<FormDataType>(FormState);
|
||||
|
||||
const handleOk = async () => {
|
||||
const params = await formRef.value?.validate();
|
||||
loading.value = true;
|
||||
const response = !id
|
||||
? await save(params)
|
||||
: await update(id, { ...props.data, ...params });
|
||||
if (response.status === 200) {
|
||||
emit('change', true);
|
||||
}
|
||||
loading.value = false;
|
||||
formRef.value?.resetFields();
|
||||
};
|
||||
|
||||
const handleCancel = () => {
|
||||
emit('change', false);
|
||||
formRef.value?.resetFields();
|
||||
};
|
||||
|
||||
const filterOption = (input: string, option: any) => {
|
||||
return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0;
|
||||
};
|
||||
|
||||
const getOptionsList = async () => {
|
||||
for (let key in Options.value) {
|
||||
const res = await queryOptionsList(key);
|
||||
Options.value[key] = res.result.map((item) => ({
|
||||
label: item?.text || item,
|
||||
value: item?.value || item,
|
||||
}));
|
||||
}
|
||||
};
|
||||
const getCertificateList = async () => {
|
||||
const res = await queryCertificateList();
|
||||
certificateList.value = res.result.map((item) => ({
|
||||
value: item.id,
|
||||
label: item.name,
|
||||
}));
|
||||
};
|
||||
|
||||
const getProvidersList = async () => {
|
||||
const resp = await getProviders();
|
||||
if (resp.status === 200) {
|
||||
const list = [
|
||||
{ label: 'OPC UA', value: 'OPC_UA' },
|
||||
{ label: 'Modbus TCP', value: 'MODBUS_TCP' },
|
||||
];
|
||||
const arr = resp.result
|
||||
.filter(
|
||||
(item: any) => item.id === 'modbus-tcp' || item.id === 'opc-ua',
|
||||
)
|
||||
.map((it: any) => (it?.id === 'opc-ua' ? 'OPC_UA' : 'MODBUS_TCP'));
|
||||
const providers = list.filter((item: any) => arr.includes(item.value));
|
||||
providersList.value = providers;
|
||||
if (arr.includes('OPC_UA')) {
|
||||
getOptionsList();
|
||||
}
|
||||
}
|
||||
};
|
||||
getProvidersList();
|
||||
getCertificateList();
|
||||
|
||||
watch(
|
||||
() => props.data,
|
||||
(value) => {
|
||||
if (value.id) formData.value = value;
|
||||
},
|
||||
{ immediate: true, deep: true },
|
||||
);
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.form {
|
||||
.form-radio-button {
|
||||
width: 148px;
|
||||
height: 80px;
|
||||
padding: 0;
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
.form-label {
|
||||
height: 30px;
|
||||
padding-bottom: 8px;
|
||||
.form-label-required {
|
||||
color: red;
|
||||
margin: 0 4px 0 -2px;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,141 @@
|
|||
import { validateField } from '@/api/data-collect/channel';
|
||||
import { FormDataType } from './type.d';
|
||||
|
||||
export const FormState: FormDataType = {
|
||||
name: '',
|
||||
provider: undefined,
|
||||
configuration: {
|
||||
host: '',
|
||||
port: '502',
|
||||
endpoint: '',
|
||||
securityPolicy: undefined,
|
||||
securityMode: undefined,
|
||||
certificate: undefined,
|
||||
authType: undefined,
|
||||
username: '',
|
||||
password: '',
|
||||
},
|
||||
description: '',
|
||||
};
|
||||
|
||||
export const StatusColorEnum = {
|
||||
running: 'success',
|
||||
disabled: 'error',
|
||||
partialError: 'processing',
|
||||
failed: 'warning',
|
||||
stopped: 'default',
|
||||
};
|
||||
export const updateStatus = {
|
||||
disabled: {
|
||||
state: 'enabled',
|
||||
runningState: 'running',
|
||||
},
|
||||
enabled: {
|
||||
state: 'disabled',
|
||||
runningState: 'stopped',
|
||||
},
|
||||
};
|
||||
|
||||
export const TiTlePermissionButtonStyle = {
|
||||
padding: 0,
|
||||
color: ' #1890ff !important',
|
||||
'font-weight': 700,
|
||||
'font-size': '16px',
|
||||
overflow: 'hidden',
|
||||
'text-overflow': 'ellipsis',
|
||||
'white-space': 'nowrap',
|
||||
width: 'calc(100%-100px)',
|
||||
// width: '60%',
|
||||
};
|
||||
|
||||
export const regOnlyNumber = new RegExp(/^\d+$/);
|
||||
|
||||
export const regIP = new RegExp(
|
||||
/^([0-9]|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.([0-9]|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.([0-9]|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.([0-9]|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])$/,
|
||||
);
|
||||
export const regIPv6 = new RegExp(
|
||||
/^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$/,
|
||||
);
|
||||
export const regDomain = new RegExp(
|
||||
/([0-9a-z-]{2,}\.[0-9a-z-]{2,3}\.[0-9a-z-]{2,3}|[0-9a-z-]{2,}\.[0-9a-z-]{2,3})$/i,
|
||||
);
|
||||
export const checkEndpoint = (_rule: Rule, value: string): Promise<any> =>
|
||||
new Promise(async (resolve, reject) => {
|
||||
if (value) {
|
||||
const res = await validateField(value);
|
||||
return res.result.passed ? resolve('') : reject(res.result.reason);
|
||||
}
|
||||
});
|
||||
export const FormValidate = {
|
||||
name: [
|
||||
{ required: true, message: '请输入名称', trigger: 'blur' },
|
||||
{ max: 64, message: '最多可输入64个字符' },
|
||||
],
|
||||
provider: [{ required: true, message: '请选择通讯协议' }],
|
||||
host: [
|
||||
{
|
||||
required: true,
|
||||
message: '请输入Modbus主机IP',
|
||||
},
|
||||
{
|
||||
pattern: regIP || regIPv6 || regDomain,
|
||||
message: '请输入正确格式的Modbus主机IP地址',
|
||||
},
|
||||
],
|
||||
port: [
|
||||
{
|
||||
required: true,
|
||||
message: '请输入端口',
|
||||
},
|
||||
{
|
||||
pattern: regOnlyNumber,
|
||||
message: '请输入1-65535之间的正整数',
|
||||
},
|
||||
],
|
||||
|
||||
endpoint: [
|
||||
{
|
||||
required: true,
|
||||
message: '请输入端点url',
|
||||
},
|
||||
{
|
||||
validator: checkEndpoint,
|
||||
trigger: 'blur',
|
||||
},
|
||||
],
|
||||
|
||||
securityPolicy: [
|
||||
{
|
||||
required: true,
|
||||
message: '请选择安全策略',
|
||||
},
|
||||
],
|
||||
securityMode: [
|
||||
{
|
||||
required: true,
|
||||
message: '请选择安全模式',
|
||||
},
|
||||
],
|
||||
certificate: [
|
||||
{
|
||||
required: true,
|
||||
message: '请选择证书',
|
||||
},
|
||||
],
|
||||
authType: [
|
||||
{
|
||||
required: true,
|
||||
message: '请选择权限认证',
|
||||
},
|
||||
],
|
||||
username: [
|
||||
{ required: true, message: '请输入用户名', trigger: 'blur' },
|
||||
{ max: 64, message: '最多可输入64个字符' },
|
||||
],
|
||||
password: [
|
||||
{ required: true, message: '请输入密码', trigger: 'blur' },
|
||||
{ max: 64, message: '最多可输入64个字符' },
|
||||
],
|
||||
|
||||
description: [{ max: 200, message: '最多可输入200个字符' }],
|
||||
};
|
|
@ -0,0 +1,341 @@
|
|||
<template>
|
||||
<page-container>
|
||||
<div>
|
||||
<Search :columns="columns" target="search" @search="handleSearch" />
|
||||
|
||||
<j-pro-table
|
||||
ref="tableRef"
|
||||
:columns="columns"
|
||||
model="CARD"
|
||||
:gridColumn="3"
|
||||
:request="query"
|
||||
:defaultParams="{
|
||||
sorts: [{ name: 'createTime', order: 'desc' }],
|
||||
}"
|
||||
:params="params"
|
||||
>
|
||||
<template #headerTitle>
|
||||
<PermissionButton
|
||||
type="primary"
|
||||
@click="handlAdd"
|
||||
hasPermission="DataCollect/Channel:add"
|
||||
>
|
||||
<template #icon><AIcon type="PlusOutlined" /></template>
|
||||
新增通道
|
||||
</PermissionButton>
|
||||
</template>
|
||||
<template #card="slotProps">
|
||||
<CardBox
|
||||
:showStatus="true"
|
||||
:value="slotProps"
|
||||
:actions="getActions(slotProps, 'card')"
|
||||
v-bind="slotProps"
|
||||
:status="getState(slotProps).value"
|
||||
:statusText="getState(slotProps).text"
|
||||
:statusNames="StatusColorEnum"
|
||||
>
|
||||
<template #img>
|
||||
<slot name="img">
|
||||
<img :src="getImage('/network.png')" />
|
||||
</slot>
|
||||
</template>
|
||||
<template #content>
|
||||
<div class="card-item-content">
|
||||
<PermissionButton
|
||||
type="link"
|
||||
@click="handlEye(slotProps.id)"
|
||||
hasPermission="DataCollect/Collector:view"
|
||||
:style="TiTlePermissionButtonStyle"
|
||||
>
|
||||
{{ slotProps.name }}
|
||||
</PermissionButton>
|
||||
|
||||
<a-row class="card-item-content-box">
|
||||
<a-col :span="12">
|
||||
<div class="card-item-content-text">
|
||||
协议
|
||||
</div>
|
||||
<div class="card-item-content-text">
|
||||
<a-tooltip>
|
||||
<template #title>{{
|
||||
slotProps.provider
|
||||
}}</template>
|
||||
{{ slotProps.provider }}
|
||||
</a-tooltip>
|
||||
</div>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<div class="card-item-content-text">
|
||||
地址
|
||||
</div>
|
||||
<div class="card-item-content-text">
|
||||
<a-tooltip>
|
||||
<template #title>{{
|
||||
slotProps.configuration
|
||||
.host ||
|
||||
slotProps.configuration
|
||||
.endpoint
|
||||
}}</template>
|
||||
<span class="details-text">{{
|
||||
slotProps.configuration
|
||||
.host ||
|
||||
slotProps.configuration
|
||||
.endpoint
|
||||
}}</span>
|
||||
</a-tooltip>
|
||||
</div>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</div>
|
||||
</template>
|
||||
<template #actions="item">
|
||||
<PermissionButton
|
||||
:disabled="item.disabled"
|
||||
:popConfirm="item.popConfirm"
|
||||
:tooltip="{
|
||||
...item.tooltip,
|
||||
}"
|
||||
@click="item.onClick"
|
||||
:hasPermission="
|
||||
'DataCollect/Channel:' + item.key
|
||||
"
|
||||
>
|
||||
<AIcon
|
||||
type="DeleteOutlined"
|
||||
v-if="item.key === 'delete'"
|
||||
/>
|
||||
<template v-else>
|
||||
<AIcon :type="item.icon" />
|
||||
<span>{{ item?.text }}</span>
|
||||
</template>
|
||||
</PermissionButton>
|
||||
</template>
|
||||
</CardBox>
|
||||
</template>
|
||||
</j-pro-table>
|
||||
<Save v-if="visible" :data="current" @change="saveChange" />
|
||||
</div>
|
||||
</page-container>
|
||||
</template>
|
||||
<script lang="ts" setup name="TypePage">
|
||||
import type { ActionsType } from '@/components/Table/index';
|
||||
import { getImage } from '@/utils/comm';
|
||||
import { query, remove, update } from '@/api/data-collect/channel';
|
||||
import { message } from 'ant-design-vue';
|
||||
import {
|
||||
TiTlePermissionButtonStyle,
|
||||
StatusColorEnum,
|
||||
updateStatus,
|
||||
} from './data';
|
||||
import { useMenuStore } from 'store/menu';
|
||||
import Save from './Save/index.vue';
|
||||
import _ from 'lodash';
|
||||
|
||||
const menuStory = useMenuStore();
|
||||
const tableRef = ref<Record<string, any>>({});
|
||||
const params = ref<Record<string, any>>({});
|
||||
const options = ref([]);
|
||||
const visible = ref(false);
|
||||
const current = ref({});
|
||||
|
||||
const columns = [
|
||||
{
|
||||
title: '通道名称',
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
ellipsis: true,
|
||||
fixed: 'left',
|
||||
search: {
|
||||
type: 'string',
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '通讯协议',
|
||||
dataIndex: 'provider',
|
||||
key: 'provider',
|
||||
ellipsis: true,
|
||||
search: {
|
||||
type: 'select',
|
||||
options: [
|
||||
{ label: 'OPC_UA', value: 'OPC_UA' },
|
||||
{ label: 'MODBUS_TCP', value: 'MODBUS_TCP' },
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '状态',
|
||||
dataIndex: 'state',
|
||||
key: 'state',
|
||||
ellipsis: true,
|
||||
scopedSlots: true,
|
||||
search: {
|
||||
type: 'select',
|
||||
options: [
|
||||
{ label: '正常', value: 'enabled' },
|
||||
{ label: '禁用', value: 'disabled' },
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '运行状态',
|
||||
dataIndex: 'runningState',
|
||||
key: 'runningState',
|
||||
ellipsis: true,
|
||||
scopedSlots: true,
|
||||
search: {
|
||||
type: 'select',
|
||||
options: [
|
||||
{ label: '运行中', value: 'running' },
|
||||
{ label: '部分错误', value: 'partialError' },
|
||||
{ label: '错误', value: 'failed' },
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '说明',
|
||||
dataIndex: 'description',
|
||||
key: 'description',
|
||||
ellipsis: true,
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
key: 'action',
|
||||
fixed: 'right',
|
||||
width: 200,
|
||||
scopedSlots: true,
|
||||
},
|
||||
];
|
||||
|
||||
const getActions = (
|
||||
data: Partial<Record<string, any>>,
|
||||
type: 'card' | 'table',
|
||||
): ActionsType[] => {
|
||||
if (!data) return [];
|
||||
const state = data.state.value;
|
||||
const stateText = state === 'enabled' ? '禁用' : '启用';
|
||||
const actions = [
|
||||
{
|
||||
key: 'update',
|
||||
text: '编辑',
|
||||
tooltip: {
|
||||
title: '编辑',
|
||||
},
|
||||
icon: 'EditOutlined',
|
||||
onClick: () => {
|
||||
handlEdit(data);
|
||||
},
|
||||
},
|
||||
{
|
||||
key: 'action',
|
||||
text: stateText,
|
||||
tooltip: {
|
||||
title: stateText,
|
||||
},
|
||||
icon: state === 'enabled' ? 'StopOutlined' : 'CheckCircleOutlined',
|
||||
popConfirm: {
|
||||
title: `确认${stateText}?`,
|
||||
onConfirm: async () => {
|
||||
const res = await update(data.id, updateStatus[state]);
|
||||
if (res.success) {
|
||||
message.success('操作成功');
|
||||
tableRef.value?.reload();
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
key: 'delete',
|
||||
text: '删除',
|
||||
disabled: state === 'enabled',
|
||||
tooltip: {
|
||||
title:
|
||||
state === 'enabled' ? '请先禁用该组件,再删除。' : '删除',
|
||||
},
|
||||
popConfirm: {
|
||||
title: '确认删除?',
|
||||
onConfirm: async () => {
|
||||
const res = await remove(data.id);
|
||||
if (res.success) {
|
||||
message.success('操作成功');
|
||||
tableRef.value.reload();
|
||||
}
|
||||
},
|
||||
},
|
||||
icon: 'DeleteOutlined',
|
||||
},
|
||||
];
|
||||
return actions;
|
||||
};
|
||||
|
||||
const handlAdd = () => {
|
||||
current.value = {};
|
||||
visible.value = true;
|
||||
};
|
||||
|
||||
const handlEdit = (data: object) => {
|
||||
current.value = _.cloneDeep(data);
|
||||
visible.value = true;
|
||||
};
|
||||
const handlEye = (id: string) => {
|
||||
console.log(id);
|
||||
};
|
||||
const saveChange = (value: object) => {
|
||||
visible.value = false;
|
||||
current.value = {};
|
||||
if (value) {
|
||||
message.success('操作成功');
|
||||
tableRef.value.reload();
|
||||
}
|
||||
};
|
||||
const getState = (record: Partial<Record<string, any>>) => {
|
||||
if (record) {
|
||||
if (record?.state?.value === 'enabled') {
|
||||
return { ...record?.runningState };
|
||||
} else {
|
||||
return {
|
||||
text: '禁用',
|
||||
value: 'disabled',
|
||||
};
|
||||
}
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 搜索
|
||||
* @param params
|
||||
*/
|
||||
const handleSearch = (e: any) => {
|
||||
params.value = e;
|
||||
};
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.card-item-content {
|
||||
min-height: 100px;
|
||||
|
||||
.card-item-content-title-a {
|
||||
// color: #000 !important;
|
||||
font-weight: 700;
|
||||
font-size: 16px;
|
||||
overflow: hidden; //超出的文本隐藏
|
||||
text-overflow: ellipsis; //溢出用省略号显示
|
||||
white-space: nowrap; //溢出不换行
|
||||
}
|
||||
.card-item-content-box {
|
||||
min-height: 50px;
|
||||
}
|
||||
.card-item-content-text {
|
||||
margin-top: 10px;
|
||||
color: rgba(0, 0, 0, 0.75);
|
||||
font-size: 12px;
|
||||
overflow: hidden; //超出的文本隐藏
|
||||
text-overflow: ellipsis; //溢出用省略号显示
|
||||
white-space: nowrap; //溢出不换行
|
||||
}
|
||||
}
|
||||
.details-text {
|
||||
font-weight: 700;
|
||||
font-size: 14px;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,19 @@
|
|||
export interface ConfigurationType {
|
||||
port: string | undefined;
|
||||
host: string | undefined;;
|
||||
username: string;
|
||||
password: string;
|
||||
endpoint: string,
|
||||
securityPolicy: string | undefined,
|
||||
securityMode: string | undefined,
|
||||
certificate: string | undefined,
|
||||
authType: string | undefined,
|
||||
|
||||
}
|
||||
|
||||
export interface FormDataType {
|
||||
name: string;
|
||||
provider: string | undefined,
|
||||
configuration: ConfigurationType;
|
||||
description?: string;
|
||||
}
|
|
@ -0,0 +1,165 @@
|
|||
<template>
|
||||
<a-spin :spinning="loading">
|
||||
<div class="dash-board">
|
||||
<div class="header">
|
||||
<div class="left">
|
||||
<h3 style="width: 100px">点位数据量</h3>
|
||||
</div>
|
||||
<div class="right">
|
||||
<a-radio-group
|
||||
default-value="a"
|
||||
button-style="solid"
|
||||
style="margin-right: 10px"
|
||||
v-model:value="data.time.type"
|
||||
>
|
||||
<a-radio-button value="hour">
|
||||
最近1小时
|
||||
</a-radio-button>
|
||||
<a-radio-button value="today"> 今日 </a-radio-button>
|
||||
<a-radio-button value="week"> 近一周 </a-radio-button>
|
||||
</a-radio-group>
|
||||
<a-range-picker
|
||||
:allowClear="false"
|
||||
:show-time="{ format: 'HH:mm:ss' }"
|
||||
format="YYYY-MM-DD HH:mm:ss"
|
||||
v-model="data.time"
|
||||
@change="pickerTimeChange"
|
||||
>
|
||||
<template #suffixIcon
|
||||
><AIcon type="CalendarOutlined"
|
||||
/></template>
|
||||
</a-range-picker>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div ref="chartRef" style="width: 100%; height: 350px"></div>
|
||||
</div>
|
||||
</div>
|
||||
</a-spin>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { dashboard } from '@/api/data-collect/dashboard';
|
||||
import { getTimeByType, pointParams, pointOptionsSeries } from '../tool.ts';
|
||||
import * as echarts from 'echarts';
|
||||
import { Dayjs } from 'dayjs';
|
||||
|
||||
const chartRef = ref<Record<string, any>>({});
|
||||
const loading = ref(false);
|
||||
const data = ref({
|
||||
time: {
|
||||
type: 'hour',
|
||||
end: 0,
|
||||
start: 0,
|
||||
},
|
||||
});
|
||||
|
||||
const pickerTimeChange = (
|
||||
value: [Dayjs, Dayjs],
|
||||
dateString: [string, string],
|
||||
) => {
|
||||
data.value.time.start = Date.parse(dateString[0]);
|
||||
data.value.time.end = Date.parse(dateString[1]);
|
||||
data.value.time.type = undefined;
|
||||
};
|
||||
|
||||
const getEcharts = async (val) => {
|
||||
loading.value = true;
|
||||
const resp = await dashboard(pointParams(val));
|
||||
if (resp.success) {
|
||||
const x = resp.result
|
||||
.map((item: any) => item.data.timeString)
|
||||
.reverse();
|
||||
const y = resp.result.map((item: any) => item.data.value).reverse();
|
||||
handleOptions(x, y);
|
||||
}
|
||||
setTimeout(() => {
|
||||
loading.value = false;
|
||||
}, 300);
|
||||
};
|
||||
|
||||
const handleOptions = (x = [], y = []) => {
|
||||
const chart = chartRef.value;
|
||||
if (chart) {
|
||||
const myChart = echarts.init(chart);
|
||||
const options = {
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
boundaryGap: false,
|
||||
data: x,
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value',
|
||||
},
|
||||
grid: {
|
||||
left: '80px',
|
||||
right: '50px',
|
||||
},
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
},
|
||||
color: ['#979AFF'],
|
||||
series: [
|
||||
{
|
||||
name: '消息量',
|
||||
data: y,
|
||||
...pointOptionsSeries,
|
||||
},
|
||||
],
|
||||
};
|
||||
myChart.setOption(options);
|
||||
window.addEventListener('resize', function () {
|
||||
myChart.resize();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
watch(
|
||||
() => data.value.time.type,
|
||||
(value) => {
|
||||
data.value.time.end = Date.parse(new Date());
|
||||
data.value.time.start = Date.parse(getTimeByType(value));
|
||||
},
|
||||
{ immediate: true, deep: true },
|
||||
);
|
||||
watch(
|
||||
() => data.value,
|
||||
(value) => {
|
||||
const { time } = value;
|
||||
if (time.type || (time.end && time.start)) {
|
||||
getEcharts(value);
|
||||
}
|
||||
},
|
||||
{ immediate: true, deep: true },
|
||||
);
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.dash-board {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
padding: 24px;
|
||||
background-color: #fff;
|
||||
box-shadow: 0px 2.73036px 5.46071px rgba(31, 89, 245, 0.2);
|
||||
border-radius: 2px;
|
||||
margin-top: 24px;
|
||||
}
|
||||
.header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
.left h3 {
|
||||
width: 200px;
|
||||
margin-top: 8px;
|
||||
}
|
||||
}
|
||||
.left,
|
||||
.right {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.empty {
|
||||
height: 300px;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,98 @@
|
|||
<template>
|
||||
<div class="top-card">
|
||||
<div class="top-card-content">
|
||||
<div class="content-left">
|
||||
<div class="content-left-title">
|
||||
<span>{{ title }}</span>
|
||||
<a-tooltip placement="top" v-if="tooltip">
|
||||
<template #title>
|
||||
<span>{{ tooltip }}</span>
|
||||
</template>
|
||||
<AIcon type="QuestionCircleOutlined" />
|
||||
</a-tooltip>
|
||||
</div>
|
||||
<div class="content-left-value">{{ value }}</div>
|
||||
</div>
|
||||
<div class="content-right">
|
||||
<img :src="img" alt="" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="top-card-footer">
|
||||
<template v-for="(item, index) in footer" :key="index">
|
||||
<span v-if="!item.status">{{ item.title }}</span>
|
||||
<a-badge v-else :text="item.title" :status="item.status" />
|
||||
<div class="footer-item-value">{{ item.value }}</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { PropType } from 'vue';
|
||||
import type { Footer } from '../typings.d';
|
||||
|
||||
const props = defineProps({
|
||||
title: { type: String, default: '' },
|
||||
tooltip: { type: String, default: '' },
|
||||
img: { type: String, default: '' },
|
||||
footer: { type: Array as PropType<Footer[]>, default: '' },
|
||||
value: { type: Number, default: 0 },
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.top-card {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
// height: 200px;
|
||||
padding: 24px;
|
||||
background-color: #fff;
|
||||
border: 1px solid #e0e4e8;
|
||||
border-radius: 2px;
|
||||
max-height: 215px;
|
||||
.top-card-content {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-grow: 1;
|
||||
.content-left {
|
||||
height: 100%;
|
||||
width: 50%;
|
||||
&-title {
|
||||
color: rgba(0, 0, 0, 0.64);
|
||||
}
|
||||
&-value {
|
||||
padding: 12px 0;
|
||||
color: #323130;
|
||||
font-weight: 700;
|
||||
font-size: 36px;
|
||||
}
|
||||
}
|
||||
.content-right {
|
||||
width: 0;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-grow: 1;
|
||||
align-items: flex-end;
|
||||
justify-content: flex-end;
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
max-height: 123px;
|
||||
max-width: 140px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.top-card-footer {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding-top: 16px;
|
||||
border-top: 1px solid #f0f0f0;
|
||||
.footer-item-value {
|
||||
color: #323130;
|
||||
font-weight: 700;
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,38 @@
|
|||
.media-dash-board {
|
||||
.top-card-items {
|
||||
margin-bottom: 12px;
|
||||
height: 100px;
|
||||
.top-card-item {
|
||||
width: 25%;
|
||||
padding: 6px 24px;
|
||||
border: 1px solid #e3e3e3;
|
||||
|
||||
.top-card-top {
|
||||
display: flex;
|
||||
padding: 12px 0;
|
||||
|
||||
.top-card-top-left {
|
||||
width: 80px;
|
||||
}
|
||||
|
||||
.top-card-top-right {
|
||||
.top-card-total {
|
||||
font-weight: bold;
|
||||
font-size: 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.top-card-bottom {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 12px 0;
|
||||
border-top: 1px solid #e3e3e3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.media-dash-board-body {
|
||||
border: 1px solid #f0f0f0;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
<template>
|
||||
<page-container>
|
||||
<a-row :gutter="24">
|
||||
<a-col :span="8" v-for="item in statusData" :key="item[0].type">
|
||||
<TopCard
|
||||
:title="item[0].label"
|
||||
:img="
|
||||
getImage(`/DataCollect/dashboard/${item[0].type}.png`)
|
||||
"
|
||||
:footer="item"
|
||||
:value="item[0].total"
|
||||
/>
|
||||
</a-col>
|
||||
</a-row>
|
||||
<a-row :gutter="24">
|
||||
<a-col :span="24">
|
||||
<Card />
|
||||
</a-col>
|
||||
</a-row>
|
||||
</page-container>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import TopCard from './components/TopCard.vue';
|
||||
import Card from './components/Card.vue';
|
||||
import { getImage } from '@/utils/comm';
|
||||
import { queryCount } from '@/api/data-collect/dashboard';
|
||||
import { defaultParams, statusData } from './tool';
|
||||
|
||||
const getNumberData = () => {
|
||||
statusData.value.forEach(async (item) => {
|
||||
const res = await queryCount(item[0].type, {});
|
||||
const resp = await queryCount(item[0].type, defaultParams);
|
||||
item[0].total = res.result || 0;
|
||||
item[0].value = resp.result || 0;
|
||||
});
|
||||
};
|
||||
getNumberData();
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped></style>
|
|
@ -0,0 +1,155 @@
|
|||
import moment from 'moment';
|
||||
import * as echarts from 'echarts';
|
||||
|
||||
const getParams = (dt: any) => {
|
||||
switch (dt.type) {
|
||||
case 'today':
|
||||
return {
|
||||
limit: 24,
|
||||
interval: '1h',
|
||||
format: 'HH:mm',
|
||||
};
|
||||
case 'week':
|
||||
return {
|
||||
limit: 7,
|
||||
interval: '1d',
|
||||
format: 'MM-dd',
|
||||
};
|
||||
case 'hour':
|
||||
return {
|
||||
limit: 60,
|
||||
interval: '1m',
|
||||
format: 'HH:mm',
|
||||
};
|
||||
default:
|
||||
const time = dt.end - dt.start;
|
||||
const hour = 60 * 60 * 1000;
|
||||
const days = hour * 24;
|
||||
const year = days * 365;
|
||||
if (time <= hour) {
|
||||
return {
|
||||
limit: Math.abs(Math.ceil(time / (60 * 60))),
|
||||
interval: '1m',
|
||||
format: 'HH:mm',
|
||||
};
|
||||
} else if (time > hour && time <= days) {
|
||||
return {
|
||||
limit: Math.abs(Math.ceil(time / hour)),
|
||||
interval: '1h',
|
||||
format: 'HH:mm',
|
||||
};
|
||||
} else if (time >= year) {
|
||||
return {
|
||||
limit: Math.abs(Math.ceil(time / days / 31)) + 1,
|
||||
interval: '1M',
|
||||
format: 'yyyy年-M月',
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
limit: Math.abs(Math.ceil(time / days)) + 1,
|
||||
interval: '1d',
|
||||
format: 'MM-dd',
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const getTimeByType = (type) => {
|
||||
switch (type) {
|
||||
case 'hour':
|
||||
return moment().subtract(1, 'hours');
|
||||
case 'week':
|
||||
return moment().subtract(6, 'days');
|
||||
case 'month':
|
||||
return moment().subtract(29, 'days');
|
||||
case 'year':
|
||||
return moment().subtract(365, 'days');
|
||||
default:
|
||||
return moment().startOf('day');
|
||||
}
|
||||
};
|
||||
|
||||
export const pointParams = (data) => [
|
||||
{
|
||||
dashboard: 'collector',
|
||||
object: 'pointData',
|
||||
measurement: 'quantity',
|
||||
dimension: 'agg',
|
||||
params: {
|
||||
limit: getParams(data.time).limit,
|
||||
from: data.time.start,
|
||||
to: data.time.end,
|
||||
interval: getParams(data.time).interval,
|
||||
format: getParams(data.time).format,
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
export const pointOptionsSeries = {
|
||||
type: 'line',
|
||||
smooth: true,
|
||||
color: '#60DFC7',
|
||||
areaStyle: {
|
||||
color: {
|
||||
type: 'linear',
|
||||
x: 0,
|
||||
y: 0,
|
||||
x2: 0,
|
||||
y2: 1,
|
||||
colorStops: [
|
||||
{
|
||||
offset: 0,
|
||||
color: '#60DFC7', // 100% 处的颜色
|
||||
},
|
||||
{
|
||||
offset: 1,
|
||||
color: '#FFFFFF', // 0% 处的颜色
|
||||
},
|
||||
],
|
||||
global: false, // 缺省为 false
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export const defaultParams = {
|
||||
terms: [
|
||||
{
|
||||
column: 'runningState',
|
||||
termType: 'not',
|
||||
value: 'running',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export const statusData = ref([
|
||||
[
|
||||
{
|
||||
type: 'channel',
|
||||
title: '异常通道',
|
||||
status: 'error',
|
||||
label: '通道数量',
|
||||
value: 0,
|
||||
total: 0,
|
||||
},
|
||||
],
|
||||
[
|
||||
{
|
||||
type: 'collector',
|
||||
title: '异常采集器',
|
||||
status: 'error',
|
||||
label: '采集器数量',
|
||||
value: 0,
|
||||
total: 0,
|
||||
},
|
||||
],
|
||||
[
|
||||
{
|
||||
type: 'point',
|
||||
title: '异常点位',
|
||||
status: 'error',
|
||||
label: '采集点位',
|
||||
value: 0,
|
||||
total: 0,
|
||||
},
|
||||
],
|
||||
]);
|
|
@ -0,0 +1,18 @@
|
|||
export type Agg = {
|
||||
duration: number;
|
||||
total: number;
|
||||
};
|
||||
|
||||
export type AggPlaying = {
|
||||
playerTotal: number;
|
||||
playingTotal: number;
|
||||
};
|
||||
|
||||
export type Footer = {
|
||||
title: string;
|
||||
value: number | string;
|
||||
total: number | string;
|
||||
status?: 'default' | 'error' | 'success' | 'warning' | 'processing' | '';
|
||||
type: string;
|
||||
label: string;
|
||||
};
|
|
@ -5,50 +5,55 @@
|
|||
width="1000px"
|
||||
@ok="emits('update:visible', false)"
|
||||
@cancel="emits('update:visible', false)"
|
||||
class="view-dialog-container"
|
||||
>
|
||||
<a-row v-if="data?.targetType === 'device'">
|
||||
<a-col :span="6" class="label">告警设备</a-col>
|
||||
<a-col :span="6" class="value">
|
||||
<a-col :span="4" class="label">告警设备</a-col>
|
||||
<a-col :span="8" class="value">
|
||||
{{ data?.targetName || '' }}
|
||||
</a-col>
|
||||
<a-col :span="6" class="label">设备ID</a-col>
|
||||
<a-col :span="6" class="value">
|
||||
<a-col :span="4" class="label">设备ID</a-col>
|
||||
<a-col :span="8" class="value">
|
||||
{{ data?.targetId || '' }}
|
||||
</a-col>
|
||||
</a-row>
|
||||
<a-row>
|
||||
<a-col :span="6" class="label">告警名称</a-col>
|
||||
<a-col :span="6" class="value">
|
||||
<a-col :span="4" class="label">告警名称</a-col>
|
||||
<a-col :span="8" class="value">
|
||||
{{ data?.alarmName || data?.alarmConfigName || '' }}
|
||||
</a-col>
|
||||
<a-col :span="6" class="label">告警时间</a-col>
|
||||
<a-col :span="6" class="value">
|
||||
<a-col :span="4" class="label">告警时间</a-col>
|
||||
<a-col :span="8" class="value">
|
||||
{{ moment(data?.alarmTime).format('YYYY-MM-DD HH:mm:ss') }}
|
||||
</a-col>
|
||||
|
||||
<a-col :span="6" class="label">告警级别</a-col>
|
||||
<a-col :span="6" class="value">
|
||||
<a-col :span="4" class="label">告警级别</a-col>
|
||||
<a-col :span="8" class="value">
|
||||
{{ (levelList.length > 0 && getLevelLabel(data.level)) || '' }}
|
||||
</a-col>
|
||||
<a-col :span="6" class="label">告警说明</a-col>
|
||||
<a-col :span="6" class="value">{{ data?.description || '' }}</a-col>
|
||||
<a-col :span="4" class="label">告警说明</a-col>
|
||||
<a-col :span="8" class="value">{{ data?.description || '' }}</a-col>
|
||||
|
||||
<a-col :span="6" class="label">告警流水</a-col>
|
||||
<a-col :span="18" class="value">
|
||||
<!-- <MonacoEditor
|
||||
style="width: 100%; height: 370px"
|
||||
theme="vs"
|
||||
v-model="jsonData"
|
||||
/> -->
|
||||
<JsonViewer :value="jsonData" copyable boxed sort />
|
||||
<a-col
|
||||
:span="4"
|
||||
class="label"
|
||||
style="display: flex; height: 440px; align-items: center"
|
||||
>告警流水</a-col
|
||||
>
|
||||
<a-col
|
||||
:span="20"
|
||||
class="value"
|
||||
style="max-height: 440px; overflow: auto"
|
||||
>
|
||||
<JsonViewer :value="JSON.parse(data?.alarmInfo || '{}')" />
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-modal>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import MonacoEditor from '@/components/MonacoEditor/index.vue';
|
||||
import {JsonViewer} from 'vue3-json-viewer';
|
||||
import { JsonViewer } from 'vue3-json-viewer';
|
||||
import 'vue3-json-viewer/dist/index.css';
|
||||
import { queryLevel as queryLevel_api } from '@/api/rule-engine/config';
|
||||
import moment from 'moment';
|
||||
|
||||
|
@ -69,18 +74,25 @@ const getLevel = () => {
|
|||
});
|
||||
};
|
||||
getLevel();
|
||||
const getLevelLabel = (id: string) => {
|
||||
const getLevelLabel = (id: number) => {
|
||||
if (levelList.value.length < 1 || !id) return '';
|
||||
const obj = levelList.value.find((item) => item.id === id);
|
||||
return obj.title;
|
||||
const obj = levelList.value.find((item) => item.level === id);
|
||||
return obj?.title;
|
||||
};
|
||||
|
||||
const jsonData = JSON.stringify({
|
||||
name: 'qiu',
|
||||
age: 18,
|
||||
isMan: false,
|
||||
arr: [1, 2, 5],
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
<style lang="less" scoped>
|
||||
.view-dialog-container {
|
||||
.ant-row {
|
||||
.ant-col {
|
||||
padding: 16px 24px;
|
||||
border-right: 1px solid #f0f0f0;
|
||||
}
|
||||
.label {
|
||||
background-color: #fafafa;
|
||||
}
|
||||
.value {
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<div class="notification-record-container">
|
||||
<Search :columns="columns" @search="query.search" />
|
||||
|
||||
<JTable
|
||||
<j-pro-table
|
||||
ref="tableRef"
|
||||
:columns="columns"
|
||||
:request="getList_api"
|
||||
|
@ -54,18 +54,6 @@
|
|||
}"
|
||||
>
|
||||
<AIcon type="ReadIconOutlined" />
|
||||
<!-- <svg
|
||||
width="1em"
|
||||
height="1em"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M12 18H6L2 22V2C2 2 2.9 2 4 2H20C21.1 2 22 2 22 2V11H20V4H4V16H12V18ZM23 14.34L21.59 12.93L17.35 17.17L15.23 15.05L13.82 16.46L17.34 20L23 14.34Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg> -->
|
||||
</PermissionButton>
|
||||
<PermissionButton
|
||||
type="link"
|
||||
|
@ -78,9 +66,13 @@
|
|||
</PermissionButton>
|
||||
</a-space>
|
||||
</template>
|
||||
</JTable>
|
||||
</j-pro-table>
|
||||
|
||||
<ViewDialog v-if="viewVisible" v-model:visible="viewVisible" :data="viewItem" />
|
||||
<ViewDialog
|
||||
v-if="viewVisible"
|
||||
v-model:visible="viewVisible"
|
||||
:data="viewItem"
|
||||
/>
|
||||
</div>
|
||||
</page-container>
|
||||
</template>
|
||||
|
@ -97,7 +89,10 @@ import { optionItem } from '@/views/rule-engine/Scene/typings';
|
|||
import { dictItemType } from '@/views/system/DataSource/typing';
|
||||
import moment from 'moment';
|
||||
import { message } from 'ant-design-vue';
|
||||
import NoticeCp from '@/components/Layout/components/Notice.vue';
|
||||
import { useUserInfo } from '@/store/userInfo';
|
||||
|
||||
const { updateAlarm } = useUserInfo();
|
||||
const columns = [
|
||||
{
|
||||
title: '类型',
|
||||
|
@ -181,6 +176,7 @@ const table = {
|
|||
if (resp.status === 200) {
|
||||
message.success('操作成功!');
|
||||
table.refresh();
|
||||
updateAlarm();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<page-container>
|
||||
<div class="notification-subscription-container">
|
||||
<Search :columns="columns" @search="query.search" />
|
||||
<JTable
|
||||
<j-pro-table
|
||||
ref="tableRef"
|
||||
:columns="columns"
|
||||
:request="getNoticeList_api"
|
||||
|
@ -87,7 +87,7 @@
|
|||
</PermissionButton>
|
||||
</a-space>
|
||||
</template>
|
||||
</JTable>
|
||||
</j-pro-table>
|
||||
|
||||
<EditDialog
|
||||
v-if="dialogVisible"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
|
||||
<template>
|
||||
<a-card>
|
||||
<j-card>
|
||||
<div>
|
||||
<div class="top">
|
||||
<div class="top-left">
|
||||
|
@ -25,9 +25,9 @@
|
|||
</div>
|
||||
<div>
|
||||
脚本语言:
|
||||
<a-select :defaultValue="'JavaScript'" style="width: 200;margin-left: 5px;">
|
||||
<a-select-option value="JavaScript">JavaScript(ECMAScript 5)</a-select-option>
|
||||
</a-select>
|
||||
<j-select :defaultValue="'JavaScript'" style="width: 200;margin-left: 5px;">
|
||||
<j-select-option value="JavaScript">JavaScript(ECMAScript 5)</j-select-option>
|
||||
</j-select>
|
||||
<AIcon type="ExpandOutlined" style="margin-left: 20px;" @click="toggle" />
|
||||
</div>
|
||||
</div>
|
||||
|
@ -42,7 +42,7 @@
|
|||
|
||||
})
|
||||
}"></div>
|
||||
<MonacoEditor language="javascript" style="height: 100%;" theme="vs" v-model:modelValue="editorValue" />
|
||||
<j-monaco-editor language="javascript" style="height: 100%;" theme="vs" v-model:modelValue="editorValue" />
|
||||
</div>
|
||||
<div class="bottom">
|
||||
<div style="width: 49.5%;">
|
||||
|
@ -51,25 +51,25 @@
|
|||
<div class="bottom-title-topic">
|
||||
<template v-if="instanceStore.current.transport === 'MQTT'">
|
||||
<div style="margin-right: 5px;">Topic:</div>
|
||||
<a-auto-complete placeholder="请输入Topic" style="width: 300px" :options="topicList"
|
||||
<j-auto-complete placeholder="请输入Topic" style="width: 300px" :options="topicList"
|
||||
:allowClear="true" :filterOption="(inputValue: any, option: any) =>
|
||||
option!.value.indexOf(inputValue) !== -1" v-model:value="topic" />
|
||||
</template>
|
||||
<template v-else>
|
||||
<div style="margin-right: 5px;">URL:</div>
|
||||
<a-input placeholder="请输入URL" v-model:value="url" style="width: 300px"></a-input>
|
||||
<j-input placeholder="请输入URL" v-model:value="url" style="width: 300px"></j-input>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<a-textarea :rows="5" placeholder="// 二进制数据以0x开头的十六进制输入,字符串数据输入原始字符串" style="margin-top: 10px;"
|
||||
<j-textarea :rows="5" placeholder="// 二进制数据以0x开头的十六进制输入,字符串数据输入原始字符串" style="margin-top: 10px;"
|
||||
v-model:value="simulation" />
|
||||
</div>
|
||||
<div style="width: 49.5%;">
|
||||
<div class="bottom-title">
|
||||
<div class="bottom-title-text">运行结果</div>
|
||||
</div>
|
||||
<a-textarea :autoSize="{ minRows: 5 }" :style="resStyle" v-model:value="result" />
|
||||
<j-textarea :autoSize="{ minRows: 5 }" :style="resStyle" v-model:value="result" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -87,13 +87,13 @@
|
|||
保存
|
||||
</PermissionButton>
|
||||
</div>
|
||||
</a-card>
|
||||
</j-card>
|
||||
</template>
|
||||
|
||||
<script setup lang='ts' name="Parsing">
|
||||
import AIcon from '@/components/AIcon'
|
||||
import PermissionButton from '@/components/PermissionButton/index.vue'
|
||||
import MonacoEditor from '@/components/MonacoEditor/index.vue';
|
||||
// import MonacoEditor from '@/components/MonacoEditor/index.vue';
|
||||
import { useFullscreen } from '@vueuse/core'
|
||||
import { useInstanceStore } from '@/store/instance';
|
||||
import {
|
||||
|
@ -103,7 +103,7 @@ import {
|
|||
saveDeviceCode,
|
||||
delDeviceCode
|
||||
} from '@/api/device/instance'
|
||||
import { message } from 'ant-design-vue';
|
||||
import { message } from 'jetlinks-ui-components';
|
||||
import { isBoolean } from 'lodash';
|
||||
|
||||
const defaultValue =
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
|
||||
<template>
|
||||
<a-card>
|
||||
<j-card>
|
||||
<div>
|
||||
<div class="top">
|
||||
<div>
|
||||
脚本语言:
|
||||
<a-select :defaultValue="'JavaScript'" style="width: 200;margin-left: 5px;">
|
||||
<a-select-option value="JavaScript">JavaScript(ECMAScript 5)</a-select-option>
|
||||
</a-select>
|
||||
<j-select :defaultValue="'JavaScript'" style="width: 200;margin-left: 5px;">
|
||||
<j-select-option value="JavaScript">JavaScript(ECMAScript 5)</j-select-option>
|
||||
</j-select>
|
||||
<AIcon type="ExpandOutlined" style="margin-left: 20px;" @click="toggle" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="edit" ref="el">
|
||||
<MonacoEditor language="javascript" style="height: 100%;" theme="vs" v-model:modelValue="editorValue" />
|
||||
<j-monaco-editor language="javascript" style="height: 100%;" theme="vs" v-model:modelValue="editorValue" />
|
||||
</div>
|
||||
<div class="bottom">
|
||||
<div style="width: 49.5%;">
|
||||
|
@ -21,25 +21,25 @@
|
|||
<div class="bottom-title-topic">
|
||||
<template v-if="productStore.current.transportProtocol === 'MQTT'">
|
||||
<div style="margin-right: 5px;">Topic:</div>
|
||||
<a-auto-complete placeholder="请输入Topic" style="width: 300px" :options="topicList"
|
||||
<j-auto-complete placeholder="请输入Topic" style="width: 300px" :options="topicList"
|
||||
:allowClear="true" :filterOption="(inputValue: any, option: any) =>
|
||||
option!.value.indexOf(inputValue) !== -1" v-model:value="topic" />
|
||||
</template>
|
||||
<template v-else>
|
||||
<div style="margin-right: 5px;">URL:</div>
|
||||
<a-input placeholder="请输入URL" v-model:value="url" style="width: 300px"></a-input>
|
||||
<j-input placeholder="请输入URL" v-model:value="url" style="width: 300px"></j-input>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<a-textarea :rows="5" placeholder="// 二进制数据以0x开头的十六进制输入,字符串数据输入原始字符串" style="margin-top: 10px;"
|
||||
<j-textarea :rows="5" placeholder="// 二进制数据以0x开头的十六进制输入,字符串数据输入原始字符串" style="margin-top: 10px;"
|
||||
v-model:value="simulation" />
|
||||
</div>
|
||||
<div style="width: 49.5%;">
|
||||
<div class="bottom-title">
|
||||
<div class="bottom-title-text">运行结果</div>
|
||||
</div>
|
||||
<a-textarea :autoSize="{ minRows: 5 }" :style="resStyle" v-model:value="result" />
|
||||
<j-textarea :autoSize="{ minRows: 5 }" :style="resStyle" v-model:value="result" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -57,13 +57,13 @@
|
|||
保存
|
||||
</PermissionButton>
|
||||
</div>
|
||||
</a-card>
|
||||
</j-card>
|
||||
</template>
|
||||
|
||||
<script setup lang='ts' name="DataAnalysis">
|
||||
import AIcon from '@/components/AIcon'
|
||||
import PermissionButton from '@/components/PermissionButton/index.vue'
|
||||
import MonacoEditor from '@/components/MonacoEditor/index.vue';
|
||||
// import MonacoEditor from '@/components/MonacoEditor/index.vue';
|
||||
import { useFullscreen } from '@vueuse/core'
|
||||
import { useProductStore } from '@/store/product';
|
||||
import {
|
||||
|
@ -72,7 +72,7 @@ import {
|
|||
testCode,
|
||||
saveProductCode,
|
||||
} from '@/api/device/instance'
|
||||
import { message } from 'ant-design-vue';
|
||||
import { message } from 'jetlinks-ui-components';
|
||||
import { isBoolean } from 'lodash';
|
||||
|
||||
const defaultValue =
|
||||
|
|
|
@ -1,63 +1,37 @@
|
|||
<!-- 绑定设备 -->
|
||||
<template>
|
||||
<a-modal
|
||||
:maskClosable="false"
|
||||
width="1100px"
|
||||
:visible="true"
|
||||
title="选择设备"
|
||||
okText="确定"
|
||||
cancelText="取消"
|
||||
@ok="handleOk"
|
||||
@cancel="handleCancel"
|
||||
:confirmLoading="btnLoading"
|
||||
>
|
||||
<j-modal :maskClosable="false" width="1100px" :visible="true" title="选择设备" okText="确定" cancelText="取消" @ok="handleOk"
|
||||
@cancel="handleCancel" :confirmLoading="btnLoading">
|
||||
<div style="margin-top: 10px">
|
||||
<Search
|
||||
:columns="columns"
|
||||
target="iot-card-bind-device"
|
||||
@search="handleSearch"
|
||||
type="simple"
|
||||
/>
|
||||
<JTable
|
||||
ref="bindDeviceRef"
|
||||
:columns="columns"
|
||||
:request="queryUnbounded"
|
||||
model="TABLE"
|
||||
:defaultParams="{
|
||||
sorts: [{ name: 'createTime', order: 'desc' }],
|
||||
}"
|
||||
:rowSelection="{
|
||||
type: 'radio',
|
||||
selectedRowKeys: _selectedRowKeys,
|
||||
onSelect: onSelectChange,
|
||||
}"
|
||||
@cancelSelect="cancelSelect"
|
||||
:params="params"
|
||||
>
|
||||
<Search :columns="columns" target="iot-card-bind-device" @search="handleSearch" type="simple" />
|
||||
<j-pro-table ref="bindDeviceRef" :columns="columns" :request="queryUnbounded" model="TABLE" :defaultParams="{
|
||||
sorts: [{ name: 'createTime', order: 'desc' }],
|
||||
}" :rowSelection="{
|
||||
type: 'radio',
|
||||
selectedRowKeys: _selectedRowKeys,
|
||||
onSelect: onSelectChange,
|
||||
}" @cancelSelect="cancelSelect" :params="params">
|
||||
<template #registryTime="slotProps">
|
||||
{{
|
||||
slotProps.registryTime
|
||||
? moment(slotProps.registryTime).format(
|
||||
'YYYY-MM-DD HH:mm:ss',
|
||||
)
|
||||
: ''
|
||||
? moment(slotProps.registryTime).format(
|
||||
'YYYY-MM-DD HH:mm:ss',
|
||||
)
|
||||
: ''
|
||||
}}
|
||||
</template>
|
||||
<template #state="slotProps">
|
||||
<a-badge
|
||||
:text="slotProps.state.text"
|
||||
:status="statusMap.get(slotProps.state.value)"
|
||||
/>
|
||||
<j-badge :text="slotProps.state.text" :status="statusMap.get(slotProps.state.value)" />
|
||||
</template>
|
||||
</JTable>
|
||||
</j-pro-table>
|
||||
</div>
|
||||
</a-modal>
|
||||
</j-modal>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { queryUnbounded, bind } from '@/api/iot-card/cardManagement';
|
||||
import moment from 'moment';
|
||||
import { message } from 'ant-design-vue';
|
||||
import { message } from 'jetlinks-ui-components';
|
||||
|
||||
const emit = defineEmits(['change']);
|
||||
|
||||
|
@ -141,7 +115,7 @@ const handleOk = () => {
|
|||
bind(props.cardId, _selectedRowKeys.value[0])
|
||||
.then((resp: any) => {
|
||||
if (resp.status === 200) {
|
||||
message.success('操作成功');
|
||||
message.success('操作成功')
|
||||
emit('change', true);
|
||||
}
|
||||
})
|
||||
|
|
|
@ -8,15 +8,15 @@
|
|||
:data="current"
|
||||
@change="saveChange"
|
||||
/>
|
||||
<a-row :gutter="[24, 24]">
|
||||
<a-col :span="24">
|
||||
<a-card>
|
||||
<a-descriptions size="small" :column="3" bordered>
|
||||
<j-row :gutter="[24, 24]">
|
||||
<j-col :span="24">
|
||||
<j-card>
|
||||
<j-descriptions size="small" :column="3" bordered>
|
||||
<template #title>
|
||||
<Guide>
|
||||
<template #title>
|
||||
<span>基本信息</span>
|
||||
<a-button
|
||||
<j-button
|
||||
type="link"
|
||||
@click="
|
||||
() => {
|
||||
|
@ -28,74 +28,74 @@
|
|||
>
|
||||
<AIcon type="EditOutlined"></AIcon>
|
||||
编辑
|
||||
</a-button>
|
||||
</j-button>
|
||||
</template>
|
||||
</Guide>
|
||||
</template>
|
||||
|
||||
<a-descriptions-item label="卡号">{{
|
||||
<j-descriptions-item label="卡号">{{
|
||||
detail.id
|
||||
}}</a-descriptions-item>
|
||||
<a-descriptions-item label="ICCID">{{
|
||||
}}</j-descriptions-item>
|
||||
<j-descriptions-item label="ICCID">{{
|
||||
detail.iccId
|
||||
}}</a-descriptions-item>
|
||||
<a-descriptions-item label="绑定设备">{{
|
||||
}}</j-descriptions-item>
|
||||
<j-descriptions-item label="绑定设备">{{
|
||||
detail.deviceName
|
||||
}}</a-descriptions-item>
|
||||
<a-descriptions-item label="平台类型">{{
|
||||
}}</j-descriptions-item>
|
||||
<j-descriptions-item label="平台类型">{{
|
||||
detail.operatorPlatformType?.text
|
||||
}}</a-descriptions-item>
|
||||
<a-descriptions-item label="平台名称">{{
|
||||
}}</j-descriptions-item>
|
||||
<j-descriptions-item label="平台名称">{{
|
||||
detail.platformConfigName
|
||||
}}</a-descriptions-item>
|
||||
<a-descriptions-item label="运营商">{{
|
||||
}}</j-descriptions-item>
|
||||
<j-descriptions-item label="运营商">{{
|
||||
detail.operatorName
|
||||
}}</a-descriptions-item>
|
||||
<a-descriptions-item label="类型">{{
|
||||
}}</j-descriptions-item>
|
||||
<j-descriptions-item label="类型">{{
|
||||
detail.cardType?.text
|
||||
}}</a-descriptions-item>
|
||||
<a-descriptions-item label="激活日期">{{
|
||||
}}</j-descriptions-item>
|
||||
<j-descriptions-item label="激活日期">{{
|
||||
detail.activationDate
|
||||
? moment(detail.activationDate).format(
|
||||
'YYYY-MM-DD HH:mm:ss',
|
||||
)
|
||||
: ''
|
||||
}}</a-descriptions-item>
|
||||
<a-descriptions-item label="更新时间">{{
|
||||
}}</j-descriptions-item>
|
||||
<j-descriptions-item label="更新时间">{{
|
||||
detail.updateTime
|
||||
? moment(detail.updateTime).format(
|
||||
'YYYY-MM-DD HH:mm:ss',
|
||||
)
|
||||
: ''
|
||||
}}</a-descriptions-item>
|
||||
<a-descriptions-item label="总流量">{{
|
||||
}}</j-descriptions-item>
|
||||
<j-descriptions-item label="总流量">{{
|
||||
detail.totalFlow
|
||||
? detail.totalFlow.toFixed(2) + ' M'
|
||||
: ''
|
||||
}}</a-descriptions-item>
|
||||
<a-descriptions-item label="使用流量">{{
|
||||
}}</j-descriptions-item>
|
||||
<j-descriptions-item label="使用流量">{{
|
||||
detail.usedFlow
|
||||
? detail.usedFlow.toFixed(2) + ' M'
|
||||
: ''
|
||||
}}</a-descriptions-item>
|
||||
<a-descriptions-item label="剩余流量">{{
|
||||
}}</j-descriptions-item>
|
||||
<j-descriptions-item label="剩余流量">{{
|
||||
detail.residualFlow
|
||||
? detail.residualFlow.toFixed(2) + ' M'
|
||||
: ''
|
||||
}}</a-descriptions-item>
|
||||
<a-descriptions-item label="状态">{{
|
||||
}}</j-descriptions-item>
|
||||
<j-descriptions-item label="状态">{{
|
||||
detail?.cardState?.text
|
||||
}}</a-descriptions-item>
|
||||
<a-descriptions-item label="说明">{{
|
||||
}}</j-descriptions-item>
|
||||
<j-descriptions-item label="说明">{{
|
||||
detail?.describe
|
||||
}}</a-descriptions-item>
|
||||
</a-descriptions>
|
||||
</a-card>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
}}</j-descriptions-item>
|
||||
</j-descriptions>
|
||||
</j-card>
|
||||
</j-col>
|
||||
<j-col :span="24">
|
||||
<!-- 流量统计 -->
|
||||
<a-row :gutter="24">
|
||||
<a-col :span="16">
|
||||
<j-row :gutter="24">
|
||||
<j-col :span="16">
|
||||
<div class="card">
|
||||
<Guide title="流量统计">
|
||||
<template #extra>
|
||||
|
@ -113,15 +113,15 @@
|
|||
:chartData="flowData"
|
||||
/>
|
||||
</div>
|
||||
</a-col>
|
||||
<a-col :span="8">
|
||||
</j-col>
|
||||
<j-col :span="8">
|
||||
<div class="card">
|
||||
<Guide title="数据统计" />
|
||||
<div class="static-info" style="min-height: 490px">
|
||||
<div class="data-statistics-item">
|
||||
<div class="flow-info" style="width: 100%">
|
||||
<div class="label">昨日流量消耗</div>
|
||||
<a-tooltip placement="bottomLeft">
|
||||
<j-tooltip placement="bottomLeft">
|
||||
<template #title>
|
||||
<span>{{ dayTotal }} M</span>
|
||||
</template>
|
||||
|
@ -129,7 +129,7 @@
|
|||
{{ dayTotal }}
|
||||
<span class="unit">M</span>
|
||||
</div>
|
||||
</a-tooltip>
|
||||
</j-tooltip>
|
||||
</div>
|
||||
<LineChart
|
||||
color="#FBA500"
|
||||
|
@ -139,7 +139,7 @@
|
|||
<div class="data-statistics-item">
|
||||
<div class="flow-info" style="width: 100%">
|
||||
<div class="label">当月流量消耗</div>
|
||||
<a-tooltip placement="bottomLeft">
|
||||
<j-tooltip placement="bottomLeft">
|
||||
<template #title>
|
||||
<span>{{ monthTotal }} M</span>
|
||||
</template>
|
||||
|
@ -147,14 +147,14 @@
|
|||
{{ monthTotal }}
|
||||
<span class="unit">M</span>
|
||||
</div>
|
||||
</a-tooltip>
|
||||
</j-tooltip>
|
||||
</div>
|
||||
<LineChart :chartData="monthOptions" />
|
||||
</div>
|
||||
<div class="data-statistics-item">
|
||||
<div class="flow-info" style="width: 100%">
|
||||
<div class="label">本年流量消耗</div>
|
||||
<a-tooltip placement="bottomLeft">
|
||||
<j-tooltip placement="bottomLeft">
|
||||
<template #title>
|
||||
<span>{{ yearTotal }} M</span>
|
||||
</template>
|
||||
|
@ -162,7 +162,7 @@
|
|||
{{ yearTotal }}
|
||||
<span class="unit">M</span>
|
||||
</div>
|
||||
</a-tooltip>
|
||||
</j-tooltip>
|
||||
</div>
|
||||
<LineChart
|
||||
color="#58E1D3"
|
||||
|
@ -171,10 +171,10 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</j-col>
|
||||
</j-row>
|
||||
</j-col>
|
||||
</j-row>
|
||||
</page-container>
|
||||
</template>
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<!-- 导入 -->
|
||||
<a-modal
|
||||
<j-modal
|
||||
:maskClosable="false"
|
||||
:visible="true"
|
||||
title="导出"
|
||||
|
@ -10,19 +10,19 @@
|
|||
@cancel="handleCancel"
|
||||
>
|
||||
<div style="margin-top: 10px">
|
||||
<a-space>
|
||||
<j-space>
|
||||
<span>文件格式:</span>
|
||||
<a-radio-group
|
||||
<j-radio-group
|
||||
v-model:value="type"
|
||||
placeholder="请选择文件格式"
|
||||
button-style="solid"
|
||||
>
|
||||
<a-radio-button value="xlsx">xlsx</a-radio-button>
|
||||
<a-radio-button value="csv">csv</a-radio-button>
|
||||
</a-radio-group>
|
||||
</a-space>
|
||||
<j-radio-button value="xlsx">xlsx</j-radio-button>
|
||||
<j-radio-button value="csv">csv</j-radio-button>
|
||||
</j-radio-group>
|
||||
</j-space>
|
||||
</div>
|
||||
</a-modal>
|
||||
</j-modal>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<!-- 导入 -->
|
||||
<a-modal
|
||||
<j-modal
|
||||
:maskClosable="false"
|
||||
:visible="true"
|
||||
title="导入"
|
||||
|
@ -10,30 +10,30 @@
|
|||
@cancel="handleCancel"
|
||||
>
|
||||
<div style="margin-top: 10px">
|
||||
<a-form :layout="'vertical'">
|
||||
<a-form-item label="平台对接" required>
|
||||
<a-select
|
||||
<j-form :layout="'vertical'">
|
||||
<j-form-item label="平台对接" required>
|
||||
<j-select
|
||||
showSearch
|
||||
v-model:value="modelRef.configId"
|
||||
:options="configList"
|
||||
placeholder="请选择平台对接"
|
||||
>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</j-select>
|
||||
</j-form-item>
|
||||
|
||||
<a-form-item v-if="modelRef.configId" label="文件格式">
|
||||
<a-radio-group
|
||||
<j-form-item v-if="modelRef.configId" label="文件格式">
|
||||
<j-radio-group
|
||||
button-style="solid"
|
||||
v-model:value="modelRef.fileType"
|
||||
placeholder="请选择文件格式"
|
||||
>
|
||||
<a-radio-button value="xlsx">xlsx</a-radio-button>
|
||||
<a-radio-button value="csv">csv</a-radio-button>
|
||||
</a-radio-group>
|
||||
</a-form-item>
|
||||
<j-radio-button value="xlsx">xlsx</j-radio-button>
|
||||
<j-radio-button value="csv">csv</j-radio-button>
|
||||
</j-radio-group>
|
||||
</j-form-item>
|
||||
|
||||
<a-form-item label="文件上传" v-if="modelRef.configId">
|
||||
<a-upload
|
||||
<j-form-item label="文件上传" v-if="modelRef.configId">
|
||||
<j-upload
|
||||
v-model:fileList="modelRef.upload"
|
||||
name="file"
|
||||
:action="FILE_UPLOAD"
|
||||
|
@ -44,24 +44,24 @@
|
|||
:showUploadList="false"
|
||||
@change="fileChange"
|
||||
>
|
||||
<a-button :loading="loading">
|
||||
<j-button :loading="loading">
|
||||
<template #icon>
|
||||
<AIcon type="UploadOutlined" />
|
||||
</template>
|
||||
文件上传
|
||||
</a-button>
|
||||
</a-upload>
|
||||
</a-form-item>
|
||||
<a-form-item v-if="modelRef.configId" label="下载模板">
|
||||
<a-space>
|
||||
<a-button icon="file" @click="downFileFn('xlsx')">
|
||||
</j-button>
|
||||
</j-upload>
|
||||
</j-form-item>
|
||||
<j-form-item v-if="modelRef.configId" label="下载模板">
|
||||
<j-space>
|
||||
<j-button icon="file" @click="downFileFn('xlsx')">
|
||||
.xlsx
|
||||
</a-button>
|
||||
<a-button icon="file" @click="downFileFn('csv')">
|
||||
</j-button>
|
||||
<j-button icon="file" @click="downFileFn('csv')">
|
||||
.csv
|
||||
</a-button>
|
||||
</a-space>
|
||||
</a-form-item>
|
||||
</j-button>
|
||||
</j-space>
|
||||
</j-form-item>
|
||||
<div v-if="totalCount">
|
||||
<a-icon class="check-num" type="check" /> 已完成 总数量
|
||||
<span class="check-num">{{ totalCount }}</span>
|
||||
|
@ -71,9 +71,9 @@
|
|||
失败 总数量
|
||||
<span class="check-num">{{ errCount }}</span>
|
||||
</div>
|
||||
</a-form>
|
||||
</j-form>
|
||||
</div>
|
||||
</a-modal>
|
||||
</j-modal>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
|
@ -82,7 +82,9 @@ import { BASE_API_PATH, TOKEN_KEY } from '@/utils/variable';
|
|||
import { LocalStore } from '@/utils/comm';
|
||||
import { downloadFile, downloadFileByUrl } from '@/utils/utils';
|
||||
import { queryPlatformNoPage, _import ,exportCard} from '@/api/iot-card/cardManagement';
|
||||
import { message } from 'ant-design-vue';
|
||||
// import { message } from 'ant-design-vue';
|
||||
import { message } from 'jetlinks-ui-components';
|
||||
|
||||
|
||||
const emit = defineEmits(['close']);
|
||||
|
||||
|
@ -125,10 +127,10 @@ const fileChange = (info: any) => {
|
|||
_import(modelRef.configId, { fileUrl: r.result })
|
||||
.then((resp: any) => {
|
||||
totalCount.value = resp.result.total;
|
||||
message.success('导入成功');
|
||||
message.success('导入成功')
|
||||
})
|
||||
.catch((err) => {
|
||||
message.error(err.response.data.message || '导入失败');
|
||||
message.error(err.response.data.message || '导入失败')
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<a-modal
|
||||
<j-modal
|
||||
:maskClosable="false"
|
||||
width="600px"
|
||||
:visible="true"
|
||||
|
@ -11,39 +11,39 @@
|
|||
:confirmLoading="btnLoading"
|
||||
>
|
||||
<div style="margin-top: 10px">
|
||||
<a-form
|
||||
<j-form
|
||||
:layout="'vertical'"
|
||||
ref="formRef"
|
||||
:rules="rules"
|
||||
:model="modelRef"
|
||||
>
|
||||
<a-form-item label="卡号" name="id">
|
||||
<a-input
|
||||
<j-form-item label="卡号" name="id">
|
||||
<j-input
|
||||
v-model:value="modelRef.id"
|
||||
placeholder="请输入卡号"
|
||||
:disabled="type === 'edit'"
|
||||
></a-input>
|
||||
</a-form-item>
|
||||
<a-form-item name="iccId">
|
||||
></j-input>
|
||||
</j-form-item>
|
||||
<j-form-item name="iccId">
|
||||
<template #label>
|
||||
<span>
|
||||
ICCID
|
||||
<a-tooltip title="IC卡的唯一识别号码">
|
||||
<j-tooltip title="IC卡的唯一识别号码">
|
||||
<AIcon
|
||||
type="QuestionCircleOutlined"
|
||||
style="margin-left: 2px"
|
||||
/>
|
||||
</a-tooltip>
|
||||
</j-tooltip>
|
||||
</span>
|
||||
</template>
|
||||
<a-input
|
||||
<j-input
|
||||
v-model:value="modelRef.iccId"
|
||||
placeholder="请输入ICCID"
|
||||
:disabled="type === 'edit'"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="平台对接" name="platformConfigId">
|
||||
<a-select
|
||||
</j-form-item>
|
||||
<j-form-item label="平台对接" name="platformConfigId">
|
||||
<j-select
|
||||
showSearch
|
||||
:filter-option="filterOption"
|
||||
:disabled="type === 'edit'"
|
||||
|
@ -52,11 +52,11 @@
|
|||
v-model:value="modelRef.platformConfigId"
|
||||
placeholder="请选择平台对接"
|
||||
>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</j-select>
|
||||
</j-form-item>
|
||||
|
||||
<a-form-item label="运营商" name="operatorName">
|
||||
<a-select
|
||||
<j-form-item label="运营商" name="operatorName">
|
||||
<j-select
|
||||
allowClear
|
||||
showSearch
|
||||
:filter-option="filterOption"
|
||||
|
@ -64,10 +64,10 @@
|
|||
v-model:value="modelRef.operatorName"
|
||||
placeholder="请选择运营商"
|
||||
>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
<a-form-item label="类型" name="cardType">
|
||||
<a-select
|
||||
</j-select>
|
||||
</j-form-item>
|
||||
<j-form-item label="类型" name="cardType">
|
||||
<j-select
|
||||
allowClear
|
||||
showSearch
|
||||
:disabled="type === 'edit'"
|
||||
|
@ -76,19 +76,19 @@
|
|||
v-model:value="modelRef.cardType"
|
||||
placeholder="请选择类型"
|
||||
>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
<a-form-item label="说明" name="describe">
|
||||
<a-textarea
|
||||
</j-select>
|
||||
</j-form-item>
|
||||
<j-form-item label="说明" name="describe">
|
||||
<j-textarea
|
||||
v-model:value="modelRef.describe"
|
||||
placeholder="请输入说明"
|
||||
showCount
|
||||
:maxlength="200"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</j-form-item>
|
||||
</j-form>
|
||||
</div>
|
||||
</a-modal>
|
||||
</j-modal>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
@ -98,7 +98,7 @@ import {
|
|||
add,
|
||||
edit,
|
||||
} from '@/api/iot-card/cardManagement';
|
||||
import { message } from 'ant-design-vue';
|
||||
import { message } from 'jetlinks-ui-components';
|
||||
import { OperatorList, TypeList } from '@/views/iot-card/data';
|
||||
|
||||
const emit = defineEmits(['change']);
|
||||
|
@ -236,7 +236,7 @@ const handleOk = () => {
|
|||
: await edit(toRaw(modelRef));
|
||||
btnLoading.value = false;
|
||||
if (resp.status === 200) {
|
||||
message.success('操作成功!');
|
||||
message.success('操作成功')
|
||||
emit('change', true);
|
||||
formRef.value.resetFields();
|
||||
}
|
||||
|
|
|
@ -2,37 +2,40 @@
|
|||
<template>
|
||||
<page-container>
|
||||
<Search :columns="columns" target="iot-card-management-search" @search="handleSearch" />
|
||||
<JTable ref="cardManageRef" :columns="columns" :request="query"
|
||||
<j-pro-table ref="cardManageRef" :columns="columns" :request="query"
|
||||
:defaultParams="{ sorts: [{ name: 'createTime', order: 'desc' }] }" :rowSelection="{
|
||||
selectedRowKeys: _selectedRowKeys,
|
||||
onChange: onSelectChange,
|
||||
}" @cancelSelect="cancelSelect" :params="params" :gridColumn="3">
|
||||
<template #headerTitle>
|
||||
<a-space>
|
||||
<a-button type="primary" @click="handleAdd">
|
||||
<j-space>
|
||||
<!-- <a-button type="primary" @click="handleAdd">
|
||||
<AIcon type="PlusOutlined" />新增
|
||||
</a-button>
|
||||
<a-dropdown>
|
||||
<a-button>
|
||||
</a-button> -->
|
||||
<PermissionButton @click="handleAdd" :hasPermission="'iot-card/CardManagement:add'" type="primary">
|
||||
<AIcon type="PlusOutlined" />新增
|
||||
</PermissionButton>
|
||||
<j-dropdown>
|
||||
<j-button>
|
||||
批量操作
|
||||
<AIcon type="DownOutlined" />
|
||||
</a-button>
|
||||
</j-button>
|
||||
<template #overlay>
|
||||
<a-menu>
|
||||
<a-menu-item>
|
||||
<j-menu>
|
||||
<j-menu-item>
|
||||
<PermissionButton @click="exportVisible = true"
|
||||
:hasPermission="'iot-card/CardManagement:export'">
|
||||
<AIcon type="ExportOutlined" />
|
||||
批量导出
|
||||
</PermissionButton>
|
||||
</a-menu-item>
|
||||
<a-menu-item>
|
||||
</j-menu-item>
|
||||
<j-menu-item>
|
||||
<PermissionButton @click="importVisible = true"
|
||||
:hasPermission="'iot-card/CardManagement:import'">
|
||||
<AIcon type="ImportOutlined" />批量导入
|
||||
</PermissionButton>
|
||||
</a-menu-item>
|
||||
<a-menu-item>
|
||||
</j-menu-item>
|
||||
<j-menu-item>
|
||||
<PermissionButton :popConfirm="{
|
||||
title: '确认激活吗?',
|
||||
onConfirm: handleActive,
|
||||
|
@ -40,47 +43,47 @@
|
|||
<AIcon type="CheckCircleOutlined" />
|
||||
批量激活
|
||||
</PermissionButton>
|
||||
</a-menu-item>
|
||||
<a-menu-item>
|
||||
</j-menu-item>
|
||||
<j-menu-item>
|
||||
<PermissionButton :popConfirm="{
|
||||
title: '确认停用吗?',
|
||||
onConfirm: handleStop,
|
||||
}" ghost type="primary" :hasPermission="'iot-card/CardManagement:action'">
|
||||
<AIcon type="StopOutlined" />
|
||||
批量停用
|
||||
批量停用
|
||||
</PermissionButton>
|
||||
</a-menu-item>
|
||||
<a-menu-item>
|
||||
</j-menu-item>
|
||||
<j-menu-item>
|
||||
<PermissionButton :popConfirm="{
|
||||
title: '确认复机吗?',
|
||||
onConfirm: handleResumption,
|
||||
}" ghost type="primary" :hasPermission="'iot-card/CardManagement:action'">
|
||||
<AIcon type="PoweroffOutlined" />
|
||||
批量复机
|
||||
<AIcon type="PoweroffOutlined" />
|
||||
批量复机
|
||||
</PermissionButton>
|
||||
</a-menu-item>
|
||||
<a-menu-item>
|
||||
</j-menu-item>
|
||||
<j-menu-item>
|
||||
<PermissionButton :popConfirm="{
|
||||
title: '确认同步状态吗?',
|
||||
onConfirm: handleSync,
|
||||
}" ghost type="primary" :hasPermission="'iot-card/CardManagement:sync'">
|
||||
<AIcon type="SwapOutlined" />
|
||||
同步状态
|
||||
<AIcon type="SwapOutlined" />
|
||||
同步状态
|
||||
</PermissionButton>
|
||||
</a-menu-item>
|
||||
<a-menu-item v-if="_selectedRowKeys.length > 0">
|
||||
</j-menu-item>
|
||||
<j-menu-item v-if="_selectedRowKeys.length > 0">
|
||||
<PermissionButton :popConfirm="{
|
||||
title: '确认删除吗?',
|
||||
onConfirm: handelRemove,
|
||||
}" ghost type="primary" :hasPermission="'iot-card/CardManagement:delete'">
|
||||
<AIcon type="SwapOutlined" />
|
||||
批量删除
|
||||
}" ghost type="primary" :hasPermission="'iot-card/CardManagement:delete'">
|
||||
<AIcon type="SwapOutlined" />
|
||||
批量删除
|
||||
</PermissionButton>
|
||||
</a-menu-item>
|
||||
</a-menu>
|
||||
</j-menu-item>
|
||||
</j-menu>
|
||||
</template>
|
||||
</a-dropdown>
|
||||
</a-space>
|
||||
</j-dropdown>
|
||||
</j-space>
|
||||
</template>
|
||||
<template #card="slotProps">
|
||||
<CardBox :value="slotProps" @click="handleClick" :actions="getActions(slotProps, 'card')" v-bind="slotProps"
|
||||
|
@ -99,23 +102,23 @@
|
|||
<h3 class="card-item-content-title">
|
||||
{{ slotProps.id }}
|
||||
</h3>
|
||||
<a-row>
|
||||
<a-col :span="8">
|
||||
<j-row>
|
||||
<j-col :span="8">
|
||||
<div class="card-item-content-text">
|
||||
平台对接
|
||||
</div>
|
||||
<div>{{ slotProps.platformConfigName }}</div>
|
||||
</a-col>
|
||||
<a-col :span="6">
|
||||
</j-col>
|
||||
<j-col :span="6">
|
||||
<div class="card-item-content-text">类型</div>
|
||||
<div>{{ slotProps.cardType.text }}</div>
|
||||
</a-col>
|
||||
<a-col :span="6">
|
||||
</j-col>
|
||||
<j-col :span="6">
|
||||
<div class="card-item-content-text">提醒</div>
|
||||
<!-- <div>{{ slotProps.cardType.text }}</div> -->
|
||||
</a-col>
|
||||
</a-row>
|
||||
<a-divider style="margin: 12px 0" />
|
||||
</j-col>
|
||||
</j-row>
|
||||
<j-divider style="margin: 12px 0" />
|
||||
<div v-if="slotProps.usedFlow === 0">
|
||||
<span class="flow-text">
|
||||
{{ slotProps.totalFlow }}
|
||||
|
@ -135,7 +138,7 @@
|
|||
总共 {{ slotProps.totalFlow }} M
|
||||
</div>
|
||||
</div>
|
||||
<a-progress :strokeColor="'#ADC6FF'" :showInfo="false" :percent="
|
||||
<j-progress :strokeColor="'#ADC6FF'" :showInfo="false" :percent="
|
||||
slotProps.totalFlow - slotProps.usedFlow
|
||||
" />
|
||||
</div>
|
||||
|
@ -185,7 +188,7 @@
|
|||
</template>
|
||||
</a-button>
|
||||
</template>
|
||||
</a-tooltip> -->
|
||||
</j-tooltip> -->
|
||||
</template>
|
||||
</CardBox>
|
||||
</template>
|
||||
|
@ -244,28 +247,20 @@
|
|||
}}
|
||||
</template>
|
||||
<template #action="slotProps">
|
||||
<a-space :size="16">
|
||||
<template
|
||||
v-for="i in getActions(slotProps,'table')"
|
||||
:key="i.key"
|
||||
>
|
||||
<PermissionButton
|
||||
:disabled="i.disabled"
|
||||
:popConfirm="i.popConfirm"
|
||||
:tooltip="{
|
||||
...i.tooltip,
|
||||
}"
|
||||
@click="i.onClick"
|
||||
type="link"
|
||||
style="padding: 0px"
|
||||
:hasPermission="'iot-card/CardManagement:' + i.key"
|
||||
>
|
||||
<template #icon><AIcon :type="i.icon" /></template>
|
||||
<j-space :size="16">
|
||||
<template v-for="i in getActions(slotProps, 'table')" :key="i.key">
|
||||
<PermissionButton :disabled="i.disabled" :popConfirm="i.popConfirm" :tooltip="{
|
||||
...i.tooltip,
|
||||
}" @click="i.onClick" type="link" style="padding: 0px"
|
||||
:hasPermission="'iot-card/CardManagement:' + i.key">
|
||||
<template #icon>
|
||||
<AIcon :type="i.icon" />
|
||||
</template>
|
||||
</PermissionButton>
|
||||
</template>
|
||||
</a-space>
|
||||
</j-space>
|
||||
</template>
|
||||
</JTable>
|
||||
</j-pro-table>
|
||||
<!-- 批量导入 -->
|
||||
<Import v-if="importVisible" @close="importVisible = false" />
|
||||
<!-- 批量导出 -->
|
||||
|
@ -294,7 +289,7 @@ import {
|
|||
removeCards,
|
||||
unbind,
|
||||
} from '@/api/iot-card/cardManagement';
|
||||
import { message } from 'ant-design-vue';
|
||||
import { message } from 'jetlinks-ui-components';
|
||||
import type { CardManagement } from './typing';
|
||||
import { getImage } from '@/utils/comm';
|
||||
import BindDevice from './BindDevice.vue';
|
||||
|
@ -510,7 +505,7 @@ const getActions = (
|
|||
onConfirm: async () => {
|
||||
unbind(data.id).then((resp: any) => {
|
||||
if (resp.status === 200) {
|
||||
message.success('操作成功');
|
||||
message.success('操作成功')
|
||||
cardManageRef.value?.reload();
|
||||
}
|
||||
});
|
||||
|
@ -559,21 +554,21 @@ const getActions = (
|
|||
if (data.cardStateType?.value === 'toBeActivated') {
|
||||
changeDeploy(data.id).then((resp) => {
|
||||
if (resp.status === 200) {
|
||||
message.success('操作成功');
|
||||
message.success('操作成功')
|
||||
cardManageRef.value?.reload();
|
||||
}
|
||||
});
|
||||
} else if (data.cardStateType?.value === 'deactivate') {
|
||||
resumption(data.id).then((resp) => {
|
||||
if (resp.status === 200) {
|
||||
message.success('操作成功');
|
||||
message.success('操作成功')
|
||||
cardManageRef.value?.reload();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
unDeploy(data.id).then((resp) => {
|
||||
if (resp.status === 200) {
|
||||
message.success('操作成功');
|
||||
message.success('操作成功')
|
||||
cardManageRef.value?.reload();
|
||||
}
|
||||
});
|
||||
|
@ -594,7 +589,7 @@ const getActions = (
|
|||
onConfirm: async () => {
|
||||
const resp: any = await del(data.id);
|
||||
if (resp.status === 200) {
|
||||
message.success('操作成功!');
|
||||
message.success('操作成功')
|
||||
cardManageRef.value?.reload();
|
||||
} else {
|
||||
message.error('操作失败!');
|
||||
|
@ -689,7 +684,7 @@ const handleStop = () => {
|
|||
) {
|
||||
unDeployBatch(_selectedRowKeys.value).then((res: any) => {
|
||||
if (res.status === 200) {
|
||||
message.success('操作成功');
|
||||
message.success('操作成功')
|
||||
}
|
||||
});
|
||||
} else {
|
||||
|
@ -707,7 +702,7 @@ const handleResumption = () => {
|
|||
) {
|
||||
resumptionBatch(_selectedRowKeys.value).then((res: any) => {
|
||||
if (res.status === 200) {
|
||||
message.success('操作成功');
|
||||
message.success('操作成功')
|
||||
}
|
||||
});
|
||||
} else {
|
||||
|
@ -733,7 +728,7 @@ const handleSync = () => {
|
|||
const handelRemove = async () => {
|
||||
const resp = await removeCards(_selectedRow.value);
|
||||
if (resp.status === 200) {
|
||||
message.success('操作成功!');
|
||||
message.success('操作成功')
|
||||
_selectedRowKeys.value = [];
|
||||
_selectedRow.value = [];
|
||||
cardManageRef.value?.reload();
|
||||
|
|
|
@ -2,14 +2,14 @@
|
|||
<template>
|
||||
<page-container>
|
||||
<div class="card-dashboard-container">
|
||||
<a-card style="margin-bottom: 24px">
|
||||
<a-row :gutter="24">
|
||||
<a-col :span="24"><Guide title="数据统计" /></a-col>
|
||||
<a-col :span="8">
|
||||
<j-card style="margin-bottom: 24px">
|
||||
<j-row :gutter="24">
|
||||
<j-col :span="24"><Guide title="数据统计" /></j-col>
|
||||
<j-col :span="8">
|
||||
<div class="data-statistics-item">
|
||||
<div class="flow-info" style="width: 100%">
|
||||
<div class="label">昨日流量消耗</div>
|
||||
<a-tooltip placement="bottomLeft">
|
||||
<j-tooltip placement="bottomLeft">
|
||||
<template #title>
|
||||
<span>{{ dayTotal }} M</span>
|
||||
</template>
|
||||
|
@ -17,19 +17,19 @@
|
|||
{{ dayTotal }}
|
||||
<span class="unit">M</span>
|
||||
</div>
|
||||
</a-tooltip>
|
||||
</j-tooltip>
|
||||
</div>
|
||||
<LineChart
|
||||
color="#FBA500"
|
||||
:chartData="dayOptions"
|
||||
/>
|
||||
</div>
|
||||
</a-col>
|
||||
<a-col :span="8">
|
||||
</j-col>
|
||||
<j-col :span="8">
|
||||
<div class="data-statistics-item">
|
||||
<div class="flow-info" style="width: 100%">
|
||||
<div class="label">当月流量消耗</div>
|
||||
<a-tooltip placement="bottomLeft">
|
||||
<j-tooltip placement="bottomLeft">
|
||||
<template #title>
|
||||
<span>{{ monthTotal }} M</span>
|
||||
</template>
|
||||
|
@ -37,16 +37,16 @@
|
|||
{{ monthTotal }}
|
||||
<span class="unit">M</span>
|
||||
</div>
|
||||
</a-tooltip>
|
||||
</j-tooltip>
|
||||
</div>
|
||||
<LineChart :chartData="monthOptions" />
|
||||
</div>
|
||||
</a-col>
|
||||
<a-col :span="8">
|
||||
</j-col>
|
||||
<j-col :span="8">
|
||||
<div class="data-statistics-item">
|
||||
<div class="flow-info" style="width: 100%">
|
||||
<div class="label">本年流量消耗</div>
|
||||
<a-tooltip placement="bottomLeft">
|
||||
<j-tooltip placement="bottomLeft">
|
||||
<template #title>
|
||||
<span>{{ yearTotal }} M</span>
|
||||
</template>
|
||||
|
@ -54,18 +54,18 @@
|
|||
{{ yearTotal }}
|
||||
<span class="unit">M</span>
|
||||
</div>
|
||||
</a-tooltip>
|
||||
</j-tooltip>
|
||||
</div>
|
||||
<LineChart
|
||||
color="#58E1D3"
|
||||
:chartData="yearOptions"
|
||||
/>
|
||||
</div>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-card>
|
||||
<a-row :gutter="24">
|
||||
<a-col :span="16">
|
||||
</j-col>
|
||||
</j-row>
|
||||
</j-card>
|
||||
<j-row :gutter="24">
|
||||
<j-col :span="16">
|
||||
<div class="static-card">
|
||||
<Guide title="流量统计">
|
||||
<template #extra>
|
||||
|
@ -85,11 +85,11 @@
|
|||
:chartData="flowData"
|
||||
/>
|
||||
<div class="empty-body" v-else>
|
||||
<a-empty :image="Empty.PRESENTED_IMAGE_SIMPLE" />
|
||||
<j-empty :image="Empty.PRESENTED_IMAGE_SIMPLE" />
|
||||
</div>
|
||||
</div>
|
||||
</a-col>
|
||||
<a-col :span="8">
|
||||
</j-col>
|
||||
<j-col :span="8">
|
||||
<div class="static-card">
|
||||
<Guide title="流量使用TOP10">
|
||||
<template #extra>
|
||||
|
@ -118,7 +118,7 @@
|
|||
</div>
|
||||
<div class="cardNum">{{ item.cardNum }}</div>
|
||||
<div class="progress">
|
||||
<a-progress
|
||||
<j-progress
|
||||
:strokeColor="'#ADC6FF'"
|
||||
:trailColor="'#E0E4E8'"
|
||||
:strokeLinecap="'butt'"
|
||||
|
@ -128,7 +128,7 @@
|
|||
(item.value / topTotal) * 100,
|
||||
)
|
||||
"
|
||||
></a-progress>
|
||||
></j-progress>
|
||||
</div>
|
||||
<div class="total">
|
||||
{{ item?.value?.toFixed(2) }} M
|
||||
|
@ -136,11 +136,11 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="empty-body" v-else>
|
||||
<a-empty :image="Empty.PRESENTED_IMAGE_SIMPLE" />
|
||||
<j-empty :image="Empty.PRESENTED_IMAGE_SIMPLE" />
|
||||
</div>
|
||||
</div>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</j-col>
|
||||
</j-row>
|
||||
</div>
|
||||
</page-container>
|
||||
</template>
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
<!-- 物联卡-首页 -->
|
||||
<template>
|
||||
<page-container>
|
||||
<a-row :gutter="24">
|
||||
<a-col :span="14">
|
||||
<j-row :gutter="24">
|
||||
<j-col :span="14">
|
||||
<div class="home-guide">
|
||||
<Guide title="物联卡引导"></Guide>
|
||||
<div
|
||||
|
@ -25,8 +25,8 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</a-col>
|
||||
<a-col :span="10">
|
||||
</j-col>
|
||||
<j-col :span="10">
|
||||
<div class="home-statistics">
|
||||
<Guide title="基础统计">
|
||||
<template #extra>
|
||||
|
@ -71,8 +71,8 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</a-col>
|
||||
<a-col :span="24" style="min-height: 580px">
|
||||
</j-col>
|
||||
<j-col :span="24" style="min-height: 580px">
|
||||
<div class="home-body">
|
||||
<Guide
|
||||
title="平台架构图"
|
||||
|
@ -82,22 +82,20 @@
|
|||
<img :src="getImage('/iot-card/iotcard-home.png')" />
|
||||
</div>
|
||||
</div>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</j-col>
|
||||
</j-row>
|
||||
</page-container>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { getImage } from '@/utils/comm';
|
||||
import Guide from '../components/Guide.vue';
|
||||
import { message } from 'ant-design-vue';
|
||||
import moment from 'moment';
|
||||
import { queryFlow, list } from '@/api/iot-card/home';
|
||||
import * as echarts from 'echarts';
|
||||
import { useMenuStore } from '@/store/menu';
|
||||
import { usePermissionStore } from '@/store/permission';
|
||||
|
||||
const router = useRouter();
|
||||
const { proxy } = <any>getCurrentInstance();
|
||||
|
||||
interface GuideItemProps {
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
<template>
|
||||
<page-container>
|
||||
<a-card>
|
||||
<a-row :gutter="24">
|
||||
<a-col :span="14">
|
||||
<j-card>
|
||||
<j-row :gutter="24">
|
||||
<j-col :span="14">
|
||||
<TitleComponent data="详情" />
|
||||
<a-form
|
||||
<j-form
|
||||
:layout="'vertical'"
|
||||
ref="formRef"
|
||||
:rules="rules"
|
||||
:model="form"
|
||||
>
|
||||
<a-form-item
|
||||
<j-form-item
|
||||
label="平台类型"
|
||||
name="operatorName"
|
||||
required
|
||||
|
@ -28,104 +28,104 @@
|
|||
v-model:value="form.operatorName"
|
||||
@change="typeChange"
|
||||
></PlatformType
|
||||
></a-form-item>
|
||||
<a-form-item label="名称" name="name">
|
||||
<a-input
|
||||
></j-form-item>
|
||||
<j-form-item label="名称" name="name">
|
||||
<j-input
|
||||
v-model:value="form.name"
|
||||
placeholder="请输入名称"
|
||||
/>
|
||||
</a-form-item>
|
||||
</j-form-item>
|
||||
|
||||
<!-- onelink -->
|
||||
<div v-if="form.operatorName === 'onelink'">
|
||||
<a-form-item label="App ID" name="appId">
|
||||
<a-input
|
||||
<j-form-item label="App ID" name="appId">
|
||||
<j-input
|
||||
v-model:value="form.appId"
|
||||
placeholder="请输入App ID"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="Password" name="passWord">
|
||||
<a-input-password
|
||||
</j-form-item>
|
||||
<j-form-item label="Password" name="passWord">
|
||||
<j-input-password
|
||||
v-model:value="form.passWord"
|
||||
placeholder="请输入密码"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="接口地址" name="apiAddr">
|
||||
<a-input
|
||||
</j-form-item>
|
||||
<j-form-item label="接口地址" name="apiAddr">
|
||||
<j-input
|
||||
v-model:value="form.apiAddr"
|
||||
placeholder="请输入接口地址"
|
||||
/>
|
||||
</a-form-item>
|
||||
</j-form-item>
|
||||
</div>
|
||||
<!-- ctwing -->
|
||||
<div v-if="form.operatorName === 'ctwing'">
|
||||
<a-form-item label="用户id" name="userId">
|
||||
<a-input
|
||||
<j-form-item label="用户id" name="userId">
|
||||
<j-input
|
||||
v-model:value="form.userId"
|
||||
placeholder="请输入用户id"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="密码" name="passWord">
|
||||
<a-input-password
|
||||
</j-form-item>
|
||||
<j-form-item label="密码" name="passWord">
|
||||
<j-input-password
|
||||
v-model:value="form.passWord"
|
||||
placeholder="请输入密码"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="secretKey" name="secretKey">
|
||||
<a-input
|
||||
</j-form-item>
|
||||
<j-form-item label="secretKey" name="secretKey">
|
||||
<j-input
|
||||
v-model:value="form.secretKey"
|
||||
placeholder="请输入secretKey"
|
||||
/>
|
||||
</a-form-item>
|
||||
</j-form-item>
|
||||
</div>
|
||||
<!-- unicom -->
|
||||
<div v-if="form.operatorName === 'unicom'">
|
||||
<a-form-item label="App ID" name="appId">
|
||||
<a-input
|
||||
<j-form-item label="App ID" name="appId">
|
||||
<j-input
|
||||
v-model:value="form.appId"
|
||||
placeholder="请输入App ID"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="App Secret" name="appSecret">
|
||||
<a-input
|
||||
</j-form-item>
|
||||
<j-form-item label="App Secret" name="appSecret">
|
||||
<j-input
|
||||
v-model:value="form.appSecret"
|
||||
placeholder="请输入App Secret"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="创建者ID" name="openId">
|
||||
<a-input
|
||||
</j-form-item>
|
||||
<j-form-item label="创建者ID" name="openId">
|
||||
<j-input
|
||||
v-model:value="form.openId"
|
||||
placeholder="请输入创建者ID"
|
||||
/>
|
||||
</a-form-item>
|
||||
</j-form-item>
|
||||
</div>
|
||||
|
||||
<a-form-item label="说明" name="explain">
|
||||
<a-textarea
|
||||
<j-form-item label="说明" name="explain">
|
||||
<j-textarea
|
||||
v-model:value="form.explain"
|
||||
placeholder="请输入说明"
|
||||
showCount
|
||||
:rows="3"
|
||||
:maxlength="200"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item>
|
||||
<a-divider />
|
||||
<a-button
|
||||
</j-form-item>
|
||||
<j-form-item>
|
||||
<j-divider />
|
||||
<j-button
|
||||
:loading="saveBtnLoading"
|
||||
type="primary"
|
||||
@click="handleSave"
|
||||
>
|
||||
保存
|
||||
</a-button>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-col>
|
||||
<a-col :span="10">
|
||||
</j-button>
|
||||
</j-form-item>
|
||||
</j-form>
|
||||
</j-col>
|
||||
<j-col :span="10">
|
||||
<Doc :type="form.operatorName" />
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-card>
|
||||
</j-col>
|
||||
</j-row>
|
||||
</j-card>
|
||||
</page-container>
|
||||
</template>
|
||||
|
||||
|
@ -133,7 +133,7 @@
|
|||
import { getImage } from '@/utils/comm';
|
||||
import PlatformType from '@/views/iot-card/components/PlatformType.vue';
|
||||
import { queryById, save, update } from '@/api/iot-card/platform';
|
||||
import { message } from 'ant-design-vue';
|
||||
import { message } from 'jetlinks-ui-components';
|
||||
import Doc from '../doc/index.vue';
|
||||
|
||||
const router = useRouter();
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
获取路径:“中移物联卡能力开放平台”--“个人中心”--“客户信息”--“接入信息”
|
||||
</p>
|
||||
<div class="image">
|
||||
<a-image
|
||||
<j-image
|
||||
width="100%"
|
||||
:src="getImage('/iot-card/onelink-appid.png')"
|
||||
/>
|
||||
|
@ -37,7 +37,7 @@
|
|||
获取路径:“中移物联卡能力开放平台”--“个人中心”--“客户信息”--“接入信息”
|
||||
</p>
|
||||
<div class="image">
|
||||
<a-image
|
||||
<j-image
|
||||
width="100%"
|
||||
:src="getImage('/iot-card/onelink-pass.png')"
|
||||
/>
|
||||
|
@ -77,7 +77,7 @@
|
|||
获取路径:“5G连接管理平台”--“能力开放”--“API网关账号管理”
|
||||
</p>
|
||||
<div class="image">
|
||||
<a-image
|
||||
<j-image
|
||||
width="100%"
|
||||
:src="getImage('/iot-card/ctwing-id.png')"
|
||||
/>
|
||||
|
@ -90,7 +90,7 @@
|
|||
获取路径:“5G连接管理平台”--“能力开放”--“API网关账号管理”
|
||||
</p>
|
||||
<div class="image">
|
||||
<a-image
|
||||
<j-image
|
||||
width="100%"
|
||||
:src="getImage('/iot-card/ctwing-pass.png')"
|
||||
/>
|
||||
|
@ -103,7 +103,7 @@
|
|||
获取路径:“5G连接管理平台”--“能力开放”--“API网关账号管理”
|
||||
</p>
|
||||
<div class="image">
|
||||
<a-image
|
||||
<j-image
|
||||
width="100%"
|
||||
:src="getImage('/iot-card/ctwing-secret.png')"
|
||||
/>
|
||||
|
@ -137,7 +137,7 @@
|
|||
获取路径:“雁飞智连CMP平台”--“我的应用”--“应用列表”
|
||||
</p>
|
||||
<div class="image">
|
||||
<a-image
|
||||
<j-image
|
||||
width="100%"
|
||||
:src="getImage('/iot-card/unicom-id.png')"
|
||||
/>
|
||||
|
@ -150,7 +150,7 @@
|
|||
获取路径:“雁飞智连CMP平台”--“我的应用”--“应用列表”
|
||||
</p>
|
||||
<div class="image">
|
||||
<a-image
|
||||
<j-image
|
||||
width="100%"
|
||||
:src="getImage('/iot-card/unicom-secret.png')"
|
||||
/>
|
||||
|
@ -164,7 +164,7 @@
|
|||
<br />
|
||||
</p>
|
||||
<div class="image">
|
||||
<a-image
|
||||
<j-image
|
||||
width="100%"
|
||||
:src="getImage('/iot-card/unicom-openid.png')"
|
||||
/>
|
||||
|
|
|
@ -1,38 +1,25 @@
|
|||
<!-- 平台对接 -->
|
||||
<template>
|
||||
<page-container>
|
||||
<Search
|
||||
:columns="columns"
|
||||
target="platform-search"
|
||||
@search="handleSearch"
|
||||
/>
|
||||
<JTable
|
||||
ref="platformRef"
|
||||
:columns="columns"
|
||||
:request="queryList"
|
||||
:defaultParams="{ sorts: [{ name: 'createTime', order: 'desc' }] }"
|
||||
:params="params"
|
||||
:gridColumn="3"
|
||||
>
|
||||
<Search :columns="columns" target="platform-search" @search="handleSearch" />
|
||||
<j-pro-table ref="platformRef" :columns="columns" :request="queryList"
|
||||
:defaultParams="{ sorts: [{ name: 'createTime', order: 'desc' }] }" :params="params" :gridColumn="3">
|
||||
<template #headerTitle>
|
||||
<a-space>
|
||||
<a-button type="primary" @click="handleAdd">
|
||||
<j-space>
|
||||
<!-- <j-button type="primary" @click="handleAdd">
|
||||
<AIcon type="PlusOutlined" />新增
|
||||
</a-button>
|
||||
</a-space>
|
||||
</j-button> -->
|
||||
<PermissionButton @click="handleAdd" :hasPermission="'iot-card/Platform:add'" type="primary">
|
||||
<AIcon type="PlusOutlined" />新增
|
||||
</PermissionButton>
|
||||
</j-space>
|
||||
</template>
|
||||
<template #card="slotProps">
|
||||
<CardBox
|
||||
:value="slotProps"
|
||||
:actions="getActions(slotProps, 'card')"
|
||||
v-bind="slotProps"
|
||||
:status="slotProps.state.value"
|
||||
:statusText="slotProps.state.text"
|
||||
:statusNames="{
|
||||
<CardBox :value="slotProps" :actions="getActions(slotProps, 'card')" v-bind="slotProps"
|
||||
:status="slotProps.state.value" :statusText="slotProps.state.text" :statusNames="{
|
||||
enabled: 'success',
|
||||
disabled: 'error',
|
||||
}"
|
||||
>
|
||||
}">
|
||||
<template #img>
|
||||
<slot name="img">
|
||||
<img :src="getImage('/iot-card/iot-card-bg.png')" />
|
||||
|
@ -42,18 +29,18 @@
|
|||
<h3 class="card-item-content-title">
|
||||
{{ slotProps.name }}
|
||||
</h3>
|
||||
<a-row>
|
||||
<a-col :span="12">
|
||||
<j-row>
|
||||
<j-col :span="12">
|
||||
<div class="card-item-content-text">
|
||||
平台类型
|
||||
</div>
|
||||
<div>{{ slotProps.operatorName }}</div>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
</j-col>
|
||||
<j-col :span="12">
|
||||
<div class="card-item-content-text">说明</div>
|
||||
<div>{{ slotProps.explain }}</div>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</j-col>
|
||||
</j-row>
|
||||
</template>
|
||||
<template #actions="item">
|
||||
<PermissionButton :disabled="item.disabled" :popConfirm="item.popConfirm" :tooltip="{
|
||||
|
@ -69,45 +56,34 @@
|
|||
</CardBox>
|
||||
</template>
|
||||
<template #state="slotProps">
|
||||
<a-badge
|
||||
:text="slotProps.state.text"
|
||||
:status="
|
||||
slotProps.state.value === 'disabled'
|
||||
? 'error'
|
||||
: 'success'
|
||||
"
|
||||
/>
|
||||
<j-badge :text="slotProps.state.text" :status="
|
||||
slotProps.state.value === 'disabled'
|
||||
? 'error'
|
||||
: 'success'
|
||||
" />
|
||||
</template>
|
||||
<template #action="slotProps">
|
||||
<a-space :size="16">
|
||||
<template
|
||||
v-for="i in getActions(slotProps,'table')"
|
||||
:key="i.key"
|
||||
>
|
||||
<PermissionButton
|
||||
:disabled="i.disabled"
|
||||
:popConfirm="i.popConfirm"
|
||||
:tooltip="{
|
||||
...i.tooltip,
|
||||
}"
|
||||
@click="i.onClick"
|
||||
type="link"
|
||||
style="padding: 0px"
|
||||
:hasPermission="'iot-card/Platform:' + i.key"
|
||||
>
|
||||
<template #icon><AIcon :type="i.icon" /></template>
|
||||
<j-space :size="16">
|
||||
<template v-for="i in getActions(slotProps, 'table')" :key="i.key">
|
||||
<PermissionButton :disabled="i.disabled" :popConfirm="i.popConfirm" :tooltip="{
|
||||
...i.tooltip,
|
||||
}" @click="i.onClick" type="link" style="padding: 0px"
|
||||
:hasPermission="'iot-card/Platform:' + i.key">
|
||||
<template #icon>
|
||||
<AIcon :type="i.icon" />
|
||||
</template>
|
||||
</PermissionButton>
|
||||
</template>
|
||||
</a-space>
|
||||
</j-space>
|
||||
</template>
|
||||
</JTable>
|
||||
</j-pro-table>
|
||||
</page-container>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { getImage } from '@/utils/comm';
|
||||
import type { ActionsType } from '@/components/Table';
|
||||
import { message } from 'ant-design-vue';
|
||||
import { message } from 'jetlinks-ui-components';
|
||||
import { queryList, update, del } from '@/api/iot-card/platform';
|
||||
import { useMenuStore } from 'store/menu'
|
||||
const menuStory = useMenuStore()
|
||||
|
@ -189,8 +165,8 @@ const getActions = (
|
|||
},
|
||||
icon: 'EditOutlined',
|
||||
onClick: () => {
|
||||
// router.push(`/iot-card/Platform/detail/${data.id}`);
|
||||
menuStory.jumpPage('iot-card/Platform/Detail',{id:data.id});
|
||||
// router.push(`/iot-card/Platform/detail/${data.id}`);
|
||||
menuStory.jumpPage('iot-card/Platform/Detail', { id: data.id });
|
||||
},
|
||||
},
|
||||
{
|
||||
|
@ -204,9 +180,8 @@ const getActions = (
|
|||
? 'StopOutlined'
|
||||
: 'PlayCircleOutlined',
|
||||
popConfirm: {
|
||||
title: `确认${
|
||||
data.state.value === 'enabled' ? '禁用' : '启用'
|
||||
}?`,
|
||||
title: `确认${data.state.value === 'enabled' ? '禁用' : '启用'
|
||||
}?`,
|
||||
okText: ' 确定',
|
||||
cancelText: '取消',
|
||||
onConfirm: () => {
|
||||
|
@ -263,7 +238,7 @@ const handleSearch = (e: any) => {
|
|||
* 新增
|
||||
*/
|
||||
const handleAdd = () => {
|
||||
menuStory.jumpPage('iot-card/Platform/Detail',{id:'add'})
|
||||
menuStory.jumpPage('iot-card/Platform/Detail', { id: 'add' })
|
||||
};
|
||||
</script>
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<a-modal
|
||||
<j-modal
|
||||
:maskClosable="false"
|
||||
width="1000px"
|
||||
:visible="true"
|
||||
|
@ -10,40 +10,40 @@
|
|||
@cancel="handleCancel"
|
||||
>
|
||||
<div style="margin-top: 10px">
|
||||
<a-descriptions
|
||||
<j-descriptions
|
||||
:column="2"
|
||||
bordered
|
||||
:contentStyle="{ minWidth: '300px' }"
|
||||
:labelStyle="{ minWidth: '120px' }"
|
||||
>
|
||||
<a-descriptions-item label="充值金额">{{
|
||||
<j-descriptions-item label="充值金额">{{
|
||||
data.chargeMoney
|
||||
}}</a-descriptions-item>
|
||||
<a-descriptions-item label="账户id">{{
|
||||
}}</j-descriptions-item>
|
||||
<j-descriptions-item label="账户id">{{
|
||||
data?.rechargeId
|
||||
}}</a-descriptions-item>
|
||||
<a-descriptions-item label="平台对接">{{
|
||||
}}</j-descriptions-item>
|
||||
<j-descriptions-item label="平台对接">{{
|
||||
data.configName
|
||||
}}</a-descriptions-item>
|
||||
<a-descriptions-item label="订单号">{{
|
||||
}}</j-descriptions-item>
|
||||
<j-descriptions-item label="订单号">{{
|
||||
data.orderNumber
|
||||
}}</a-descriptions-item>
|
||||
<a-descriptions-item label="支付方式">{{
|
||||
}}</j-descriptions-item>
|
||||
<j-descriptions-item label="支付方式">{{
|
||||
data.paymentType
|
||||
}}</a-descriptions-item>
|
||||
<a-descriptions-item label="支付URL">
|
||||
}}</j-descriptions-item>
|
||||
<j-descriptions-item label="支付URL">
|
||||
<div style="height: 100px; overflow: auto">
|
||||
{{ data.url ? data.url : '' }}
|
||||
</div>
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="订单时间">{{
|
||||
</j-descriptions-item>
|
||||
<j-descriptions-item label="订单时间">{{
|
||||
data.createTime
|
||||
? moment(data.createTime).format('YYYY-MM-DD HH:mm:ss')
|
||||
: '-'
|
||||
}}</a-descriptions-item>
|
||||
</a-descriptions>
|
||||
}}</j-descriptions-item>
|
||||
</j-descriptions>
|
||||
</div>
|
||||
</a-modal>
|
||||
</j-modal>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<a-modal
|
||||
<j-modal
|
||||
:maskClosable="false"
|
||||
width="600px"
|
||||
:visible="true"
|
||||
|
@ -17,14 +17,14 @@
|
|||
style="margin-right: 6px"
|
||||
/>暂只支持移动OneLink平台
|
||||
</div>
|
||||
<a-form
|
||||
<j-form
|
||||
layout="vertical"
|
||||
ref="formRef"
|
||||
:rules="rules"
|
||||
:model="modelRef"
|
||||
>
|
||||
<a-form-item label="平台对接" name="configId">
|
||||
<a-select
|
||||
<j-form-item label="平台对接" name="configId">
|
||||
<j-select
|
||||
v-model:value="modelRef.configId"
|
||||
:options="configList"
|
||||
allowClear
|
||||
|
@ -32,16 +32,16 @@
|
|||
style="width: 100%"
|
||||
placeholder="请选择平台对接"
|
||||
>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
<a-form-item label="账户id" name="rechargeId">
|
||||
<a-input
|
||||
</j-select>
|
||||
</j-form-item>
|
||||
<j-form-item label="账户id" name="rechargeId">
|
||||
<j-input
|
||||
v-model:value="modelRef.rechargeId"
|
||||
placeholder="请输入账户id"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="充值金额" name="chargeMoney">
|
||||
<a-input-number
|
||||
</j-form-item>
|
||||
<j-form-item label="充值金额" name="chargeMoney">
|
||||
<j-input-number
|
||||
allowClear
|
||||
:precision="2"
|
||||
style="width: 100%"
|
||||
|
@ -50,25 +50,25 @@
|
|||
:max="500"
|
||||
placeholder="请输入1~500之间的金额"
|
||||
/>
|
||||
</a-form-item>
|
||||
</j-form-item>
|
||||
|
||||
<a-form-item label="支付方式" name="paymentType">
|
||||
<a-select
|
||||
<j-form-item label="支付方式" name="paymentType">
|
||||
<j-select
|
||||
allowClear
|
||||
:options="PaymentMethod"
|
||||
v-model:value="modelRef.paymentType"
|
||||
placeholder="请选择支付方式"
|
||||
>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</j-select>
|
||||
</j-form-item>
|
||||
</j-form>
|
||||
</div>
|
||||
</a-modal>
|
||||
</j-modal>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { queryPlatformNoPage, recharge } from '@/api/iot-card/cardManagement';
|
||||
import { message } from 'ant-design-vue';
|
||||
import { message } from 'jetlinks-ui-components';
|
||||
import { PaymentMethod } from '@/views/iot-card/data';
|
||||
|
||||
const emit = defineEmits(['change']);
|
||||
|
@ -167,7 +167,7 @@ const handleOk = () => {
|
|||
btnLoading.value = false;
|
||||
if (resp.status === 200) {
|
||||
if (resp.result === '失败') {
|
||||
message.error('缴费失败');
|
||||
message.error('缴费失败')
|
||||
} else {
|
||||
window.open(resp.result);
|
||||
}
|
||||
|
@ -176,6 +176,7 @@ const handleOk = () => {
|
|||
}
|
||||
})
|
||||
.catch((err: any) => {
|
||||
btnLoading.value=false
|
||||
console.log('error', err);
|
||||
});
|
||||
};
|
||||
|
|
|
@ -2,10 +2,10 @@
|
|||
<template>
|
||||
<page-container>
|
||||
<Search :columns="columns" target="recharge-search" @search="handleSearch" />
|
||||
<JTable ref="rechargeRef" :columns="columns" :request="queryRechargeList" model="TABLE"
|
||||
<j-pro-table ref="rechargeRef" :columns="columns" :request="queryRechargeList" model="TABLE"
|
||||
:defaultParams="{ sorts: [{ name: 'createTime', order: 'desc' }] }" :params="params">
|
||||
<template #headerTitle>
|
||||
<a-space>
|
||||
<j-space>
|
||||
<PermissionButton @click="visible = true" :hasPermission="'iot-card/Recharge:pay'" type="primary">
|
||||
充值
|
||||
</PermissionButton>
|
||||
|
@ -15,7 +15,7 @@
|
|||
</span>
|
||||
本平台仅提供充值入口,具体充值结果需以运营商的充值结果为准
|
||||
</div>
|
||||
</a-space>
|
||||
</j-space>
|
||||
</template>
|
||||
<template #createTime="slotProps">
|
||||
{{
|
||||
|
@ -27,7 +27,7 @@
|
|||
}}
|
||||
</template>
|
||||
<template #action="slotProps">
|
||||
<a-space :size="16">
|
||||
<j-space :size="16">
|
||||
<template
|
||||
v-for="i in getActions(slotProps)"
|
||||
:key="i.key"
|
||||
|
@ -46,9 +46,9 @@
|
|||
<template #icon><AIcon :type="i.icon" /></template>
|
||||
</PermissionButton>
|
||||
</template>
|
||||
</a-space>
|
||||
</j-space>
|
||||
</template>
|
||||
</JTable>
|
||||
</j-pro-table>
|
||||
<!-- 充值 -->
|
||||
<Save v-if="visible" @change="saveChange" />
|
||||
<Detail v-if="detailVisible" :data="current" @close="close" />
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
target="record-search"
|
||||
@search="handleSearch"
|
||||
/>
|
||||
<JTable
|
||||
<j-pro-table
|
||||
ref="RecordRef"
|
||||
:columns="columns"
|
||||
:request="queryList"
|
||||
|
@ -21,7 +21,7 @@
|
|||
: ''
|
||||
}}
|
||||
</template>
|
||||
</JTable>
|
||||
</j-pro-table>
|
||||
</page-container>
|
||||
</template>
|
||||
|
||||
|
|
|
@ -1,21 +1,21 @@
|
|||
<template>
|
||||
<div>
|
||||
<a-radio-group
|
||||
<j-radio-group
|
||||
v-if="quickBtn"
|
||||
default-value="today"
|
||||
button-style="solid"
|
||||
v-model:value="radioValue"
|
||||
@change="(e) => handleBtnChange(e.target.value)"
|
||||
>
|
||||
<a-radio-button
|
||||
<j-radio-button
|
||||
v-for="item in quickBtnList"
|
||||
:key="item.value"
|
||||
:value="item.value"
|
||||
>
|
||||
{{ item.label }}
|
||||
</a-radio-button>
|
||||
</a-radio-group>
|
||||
<a-range-picker
|
||||
</j-radio-button>
|
||||
</j-radio-group>
|
||||
<j-range-picker
|
||||
format="YYYY-MM-DD"
|
||||
valueFormat="YYYY-MM-DD"
|
||||
style="margin-left: 12px"
|
||||
|
@ -23,7 +23,7 @@
|
|||
v-model:value="rangeVal"
|
||||
:allowClear="false"
|
||||
>
|
||||
</a-range-picker>
|
||||
</j-range-picker>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
|
@ -316,7 +316,7 @@ const getActions = (data: Partial<Record<string, any>>): ActionsType[] => {
|
|||
|
||||
const getProvidersList = async () => {
|
||||
const res = await getProviders();
|
||||
providersList = res.result;
|
||||
providersList.value = res.result;
|
||||
};
|
||||
getProvidersList();
|
||||
|
||||
|
@ -337,7 +337,7 @@ const handlEye = (id: string) => {
|
|||
const getDescription = (slotProps: Record<string, any>) =>
|
||||
slotProps.description
|
||||
? slotProps.description
|
||||
: providersList?.find(
|
||||
: providersList.value?.find(
|
||||
(item: Record<string, any>) => item.id === slotProps.provider,
|
||||
)?.description;
|
||||
|
||||
|
|
|
@ -33,8 +33,7 @@
|
|||
>
|
||||
</a-range-picker>
|
||||
</div>
|
||||
<a-empty v-if="empty" class="empty" />
|
||||
<div v-else ref="chartRef" style="width: 100%; height: 300px"></div>
|
||||
<div ref="chartRef" style="width: 100%; height: 300px"></div>
|
||||
</div>
|
||||
</a-spin>
|
||||
</template>
|
||||
|
@ -54,7 +53,6 @@ import {
|
|||
|
||||
const chartRef = ref<Record<string, any>>({});
|
||||
const loading = ref(false);
|
||||
const empty = ref(false);
|
||||
const data = ref({
|
||||
type: 'hour',
|
||||
time: [null, null],
|
||||
|
@ -108,7 +106,6 @@ const handleCpuOptions = (optionsData, xAxis) => {
|
|||
if (chart) {
|
||||
const myChart = echarts.init(chart);
|
||||
const dataKeys = Object.keys(optionsData);
|
||||
|
||||
const options = {
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
|
@ -143,7 +140,6 @@ const handleCpuOptions = (optionsData, xAxis) => {
|
|||
: typeDataLine,
|
||||
};
|
||||
myChart.setOption(options);
|
||||
xAxis.length === 0 && (empty.value = true);
|
||||
window.addEventListener('resize', function () {
|
||||
myChart.resize();
|
||||
});
|
||||
|
@ -190,7 +186,4 @@ watch(
|
|||
margin-top: 8px;
|
||||
}
|
||||
}
|
||||
.empty {
|
||||
height: 300px;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -33,8 +33,7 @@
|
|||
>
|
||||
</a-range-picker>
|
||||
</div>
|
||||
<a-empty v-if="empty" class="empty" />
|
||||
<div v-else ref="chartRef" style="width: 100%; height: 300px"></div>
|
||||
<div ref="chartRef" style="width: 100%; height: 300px"></div>
|
||||
</div>
|
||||
</a-spin>
|
||||
</template>
|
||||
|
@ -53,7 +52,6 @@ import {
|
|||
} from './tool.ts';
|
||||
|
||||
const chartRef = ref<Record<string, any>>({});
|
||||
const empty = ref(false);
|
||||
const loading = ref(false);
|
||||
const data = ref({
|
||||
type: 'hour',
|
||||
|
@ -147,7 +145,6 @@ const handleJVMOptions = (optionsData, xAxis) => {
|
|||
: typeDataLine,
|
||||
};
|
||||
myChart.setOption(options);
|
||||
xAxis.length === 0 && (empty.value = true);
|
||||
window.addEventListener('resize', function () {
|
||||
myChart.resize();
|
||||
});
|
||||
|
@ -194,7 +191,4 @@ watch(
|
|||
margin-top: 8px;
|
||||
}
|
||||
}
|
||||
.empty {
|
||||
height: 300px;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -37,18 +37,13 @@
|
|||
@change="pickerTimeChange"
|
||||
>
|
||||
<template #suffixIcon
|
||||
><a-icon type="calendar"
|
||||
><AIcon type="CalendarOutlined"
|
||||
/></template>
|
||||
</a-range-picker>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<a-empty v-if="empty" class="empty" />
|
||||
<div
|
||||
v-else
|
||||
ref="chartRef"
|
||||
style="width: 100%; height: 350px"
|
||||
></div>
|
||||
<div ref="chartRef" style="width: 100%; height: 350px"></div>
|
||||
</div>
|
||||
</div>
|
||||
</a-spin>
|
||||
|
@ -61,13 +56,11 @@ import {
|
|||
typeDataLine,
|
||||
areaStyle,
|
||||
networkParams,
|
||||
arrayReverse,
|
||||
} from './tool.ts';
|
||||
import moment from 'moment';
|
||||
import * as echarts from 'echarts';
|
||||
|
||||
const chartRef = ref<Record<string, any>>({});
|
||||
const empty = ref(false);
|
||||
const loading = ref(false);
|
||||
const data = ref({
|
||||
type: 'bytesRead',
|
||||
|
@ -134,7 +127,6 @@ const setOptions = (data, key) => ({
|
|||
|
||||
const handleNetworkOptions = (optionsData, xAxis) => {
|
||||
const chart = chartRef.value;
|
||||
|
||||
if (chart) {
|
||||
const myChart = echarts.init(chart);
|
||||
const dataKeys = Object.keys(optionsData);
|
||||
|
@ -148,7 +140,7 @@ const handleNetworkOptions = (optionsData, xAxis) => {
|
|||
type: 'value',
|
||||
},
|
||||
grid: {
|
||||
left: '80px',
|
||||
left: '100px',
|
||||
right: '50px',
|
||||
},
|
||||
tooltip: {
|
||||
|
@ -161,7 +153,6 @@ const handleNetworkOptions = (optionsData, xAxis) => {
|
|||
: typeDataLine,
|
||||
};
|
||||
myChart.setOption(options);
|
||||
// xAxis.length === 0 && (empty.value = true);
|
||||
window.addEventListener('resize', function () {
|
||||
myChart.resize();
|
||||
});
|
||||
|
@ -215,7 +206,4 @@ watch(
|
|||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.empty {
|
||||
height: 300px;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -0,0 +1,91 @@
|
|||
@padding: 20px;
|
||||
|
||||
.split-screen {
|
||||
display: flex;
|
||||
|
||||
.left-content {
|
||||
width: 300px;
|
||||
padding-right: @padding;
|
||||
border-right: 1px solid #f0f0f0;
|
||||
|
||||
.online {
|
||||
color: rgba(82, 196, 26, 1);
|
||||
.anticon {
|
||||
color: rgba(82, 196, 26, 1);
|
||||
}
|
||||
}
|
||||
|
||||
.offline {
|
||||
color: rgba(0, 0, 0, 0.25);
|
||||
.anticon {
|
||||
color: rgba(0, 0, 0, 0.25);
|
||||
}
|
||||
}
|
||||
|
||||
.left-search {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
.right-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-grow: 1;
|
||||
padding-left: @padding;
|
||||
|
||||
.top {
|
||||
display: flex;
|
||||
flex-basis: 30px;
|
||||
justify-content: center;
|
||||
padding-bottom: 12px;
|
||||
}
|
||||
|
||||
.live-player {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
|
||||
.live-player-content {
|
||||
position: relative;
|
||||
flex-grow: 1;
|
||||
|
||||
.player-screen {
|
||||
display: grid;
|
||||
|
||||
&.screen-1 {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
&.screen-4 {
|
||||
grid-template-rows: 1fr 1fr;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
}
|
||||
|
||||
&.screen-9 {
|
||||
grid-template-rows: 1fr 1fr 1fr;
|
||||
grid-template-columns: 1fr 1fr 1fr;
|
||||
}
|
||||
|
||||
&.screen-4,
|
||||
&.screen-9 {
|
||||
grid-gap: 12px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.player-tools {
|
||||
flex-basis: 280px;
|
||||
padding: 50px 12px 0 12px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media screen {
|
||||
@media (min-width: 1300px) {
|
||||
.split-screen {
|
||||
.left-content {
|
||||
width: 200px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
<template>
|
||||
<page-container>
|
||||
<a-card class="splitScreen">
|
||||
<div class="split-screen">
|
||||
<LeftTree @onSelect="mediaStart" />
|
||||
<div class="right-content">
|
||||
<ScreenPlayer
|
||||
ref="player"
|
||||
:id="deviceId"
|
||||
:channelId="channelId"
|
||||
:onMouseUp="(id, cId) => channelApi.ptzStop(id, cId)"
|
||||
:onMouseDown="
|
||||
(id, cId, type) => channelApi.ptzTool(id, cId, type)
|
||||
"
|
||||
:historyHandle="(dId, cId) => getMediaUrl(dId, cId)"
|
||||
showScreen
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</a-card>
|
||||
</page-container>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import LeftTree from './tree.vue';
|
||||
import channelApi from '@/api/media/channel';
|
||||
import ScreenPlayer from '@/components/Player/ScreenPlayer.vue';
|
||||
|
||||
const deviceId = ref('');
|
||||
const channelId = ref('');
|
||||
const player = ref();
|
||||
|
||||
/**
|
||||
* 获取视频链接
|
||||
* @param dId
|
||||
* @param cId
|
||||
*/
|
||||
const getMediaUrl = (dId: string, cId: string): string => {
|
||||
return channelApi.ptzStart(dId, cId, 'mp4');
|
||||
};
|
||||
|
||||
/**
|
||||
* 点击左侧摄像头, 播放对应视频
|
||||
* @param e
|
||||
*/
|
||||
const mediaStart = (e: { cId: string; dId: string }) => {
|
||||
channelId.value = e.cId;
|
||||
deviceId.value = e.dId;
|
||||
player.value?.replaceVideo(e.dId, e.cId, getMediaUrl(e.dId, e.cId));
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
@import './index.less';
|
||||
</style>
|
|
@ -0,0 +1,174 @@
|
|||
<template>
|
||||
<div class="left-content">
|
||||
<a-tree
|
||||
:height="700"
|
||||
:show-line="{ showLeafIcon: false }"
|
||||
:show-icon="true"
|
||||
:tree-data="treeData"
|
||||
:loadData="onLoadData"
|
||||
:fieldNames="{ title: 'name', key: 'id' }"
|
||||
@select="onSelect"
|
||||
>
|
||||
<template #icon="{ id, selected }">
|
||||
<AIcon
|
||||
type="VideoCameraOutlined"
|
||||
v-if="!treeData.find((f: any) => f.id === id)"
|
||||
/>
|
||||
</template>
|
||||
</a-tree>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import cascadeApi from '@/api/media/cascade';
|
||||
|
||||
type Emits = {
|
||||
(e: 'onSelect', data: { dId: string; cId: string }): void;
|
||||
};
|
||||
|
||||
const emit = defineEmits<Emits>();
|
||||
|
||||
interface DataNode {
|
||||
name: string;
|
||||
id: string;
|
||||
isLeaf?: boolean;
|
||||
channelNumber?: number;
|
||||
icon?: any;
|
||||
status: {
|
||||
text: string;
|
||||
value: string;
|
||||
};
|
||||
children?: DataNode[];
|
||||
}
|
||||
|
||||
/**
|
||||
* 点击节点
|
||||
* @param _
|
||||
* @param param1
|
||||
*/
|
||||
const onSelect = (_: any, { node }: any) => {
|
||||
emit('onSelect', { dId: node.deviceId, cId: node.channelId });
|
||||
};
|
||||
|
||||
/**
|
||||
* 是否为子节点
|
||||
* @param node
|
||||
*/
|
||||
const isLeaf = (node: any): boolean => {
|
||||
if (node.channelNumber) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取设备列表
|
||||
*/
|
||||
const treeData = ref<any[]>([]);
|
||||
const getDeviceList = async () => {
|
||||
const res = await cascadeApi.getMediaTree({ paging: false });
|
||||
if (res.success) {
|
||||
treeData.value = res.result.map((m: any) => {
|
||||
const extra: any = {};
|
||||
extra.isLeaf = isLeaf(m);
|
||||
return {
|
||||
...m,
|
||||
...extra,
|
||||
};
|
||||
});
|
||||
}
|
||||
};
|
||||
getDeviceList();
|
||||
|
||||
/**
|
||||
* 更新数据
|
||||
* @param list
|
||||
* @param key
|
||||
* @param children
|
||||
*/
|
||||
const updateTreeData = (
|
||||
list: DataNode[],
|
||||
key: any,
|
||||
children: DataNode[],
|
||||
): DataNode[] => {
|
||||
return list.map((node) => {
|
||||
if (node.id === key) {
|
||||
return {
|
||||
...node,
|
||||
children: node.children
|
||||
? [...node.children, ...children]
|
||||
: children,
|
||||
};
|
||||
}
|
||||
|
||||
if (node.children) {
|
||||
return {
|
||||
...node,
|
||||
children: updateTreeData(node.children, key, children),
|
||||
};
|
||||
}
|
||||
return node;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取子节点
|
||||
* @param key
|
||||
* @param params
|
||||
*/
|
||||
const getChildren = (key: any, params: any): Promise<any> => {
|
||||
return new Promise(async (resolve) => {
|
||||
const res = await cascadeApi.queryChannelList(params);
|
||||
if (res.status === 200) {
|
||||
const { total, pageIndex, pageSize } = res.result;
|
||||
treeData.value = updateTreeData(
|
||||
treeData.value,
|
||||
key,
|
||||
res.result.data.map((item: DataNode) => ({
|
||||
...item,
|
||||
class: item.status.value,
|
||||
isLeaf: isLeaf(item),
|
||||
})),
|
||||
);
|
||||
|
||||
if (total > (pageIndex + 1) * pageSize) {
|
||||
setTimeout(() => {
|
||||
getChildren(key, {
|
||||
...params,
|
||||
pageIndex: params.pageIndex + 1,
|
||||
});
|
||||
}, 50);
|
||||
}
|
||||
resolve(res.result);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 异步加载子节点数据
|
||||
* @param param0
|
||||
*/
|
||||
const onLoadData = ({ key, children }: any): Promise<void> => {
|
||||
return new Promise(async (resolve) => {
|
||||
if (children) {
|
||||
resolve();
|
||||
return;
|
||||
}
|
||||
await getChildren(key, {
|
||||
pageIndex: 0,
|
||||
pageSize: 100,
|
||||
terms: [
|
||||
{
|
||||
column: 'deviceId',
|
||||
value: key,
|
||||
},
|
||||
],
|
||||
});
|
||||
resolve();
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
@import './index.less';
|
||||
</style>
|
|
@ -19,7 +19,12 @@
|
|||
</a-steps>
|
||||
<a-divider style='margin-bottom: 0px' />
|
||||
<div class='steps-content'>
|
||||
<Product v-if='addModel.stepNumber === 0' v-model:rowKey='addModel.productId' v-model:detail='addModel.productDetail' />
|
||||
<Product
|
||||
v-if='addModel.stepNumber === 0'
|
||||
v-model:rowKey='addModel.productId'
|
||||
v-model:detail='addModel.productDetail'
|
||||
@change='productChange'
|
||||
/>
|
||||
<DeviceSelect
|
||||
v-else-if='addModel.stepNumber === 1'
|
||||
:productId='addModel.productId'
|
||||
|
@ -32,6 +37,7 @@
|
|||
ref='typeRef'
|
||||
v-else-if='addModel.stepNumber === 2'
|
||||
:metadata='addModel.metadata'
|
||||
:operator='addModel.operator'
|
||||
/>
|
||||
</div>
|
||||
<template #footer>
|
||||
|
@ -53,11 +59,11 @@ import { detail as deviceDetail } from '@/api/device/instance'
|
|||
import Product from './Product.vue'
|
||||
import DeviceSelect from './DeviceSelect.vue'
|
||||
import Type from './Type.vue'
|
||||
import { continuousValue, timeUnitEnum } from '@/views/rule-engine/Scene/Save/components/Timer/util'
|
||||
|
||||
type Emit = {
|
||||
(e: 'cancel'): void
|
||||
(e: 'update:value', data: TriggerDevice): void
|
||||
(e: 'update:options', data: any): void
|
||||
(e: 'save', data: TriggerDevice, options: Record<string, any>): void
|
||||
}
|
||||
|
||||
interface AddModelType extends Omit<TriggerDevice, 'selectorValues'> {
|
||||
|
@ -65,8 +71,9 @@ interface AddModelType extends Omit<TriggerDevice, 'selectorValues'> {
|
|||
deviceKeys: Array<{ label: string, value: string }>
|
||||
orgId: Array<{ label: string, value: string }>
|
||||
productDetail: any
|
||||
selectorValues: Array<{ label: string, value: string }>
|
||||
metadata: metadataType
|
||||
selectorValues: Array<Record<string, any>>
|
||||
metadata: metadataType,
|
||||
operator: TriggerDeviceOptions
|
||||
}
|
||||
|
||||
const emit = defineEmits<Emit>()
|
||||
|
@ -82,7 +89,7 @@ const props = defineProps({
|
|||
})
|
||||
},
|
||||
options: {
|
||||
type: Object as PropType<any>,
|
||||
type: Object as PropType<Record<string, any>>,
|
||||
default: () => ({})
|
||||
}
|
||||
})
|
||||
|
@ -95,13 +102,106 @@ const addModel = reactive<AddModelType>({
|
|||
deviceKeys: [],
|
||||
orgId: [],
|
||||
productDetail: {},
|
||||
metadata: {}
|
||||
metadata: {},
|
||||
operator: {
|
||||
operator: 'online'
|
||||
}
|
||||
})
|
||||
|
||||
const optionsCache = ref(props.options)
|
||||
|
||||
Object.assign(addModel, props.value)
|
||||
|
||||
const handleOptions = (data: TriggerDeviceOptions) => {
|
||||
const typeIconMap = {
|
||||
writeProperty: 'icon-bianji1',
|
||||
invokeFunction: 'icon-widgets',
|
||||
reportEvent: 'icon-shijian',
|
||||
readProperty: 'icon-Group',
|
||||
};
|
||||
|
||||
const _options: any = {
|
||||
name: '', // 名称
|
||||
extraName: '', // 拓展参数
|
||||
onlyName: false,
|
||||
type: '', // 触发类型
|
||||
typeIcon: typeIconMap[data.operator],
|
||||
productName: '',
|
||||
selectorIcon: '',
|
||||
time: undefined,
|
||||
when: undefined,
|
||||
extraTime: undefined,
|
||||
action: optionsCache.value?.action,
|
||||
};
|
||||
|
||||
if (addModel.selector === 'fixed') {
|
||||
let isLimit = false;
|
||||
let indexOf = 0;
|
||||
const nameStr = addModel.selectorValues!.reduce((_prev, next, index) => {
|
||||
if (_prev.length <= 30) {
|
||||
indexOf = index;
|
||||
return index === 0 ? next.name : _prev + '、' + next.name;
|
||||
} else {
|
||||
isLimit = true;
|
||||
}
|
||||
return _prev;
|
||||
}, '');
|
||||
// _options.name = TriggerDeviceModel.selectorValues?.map((item) => item.name).join('、');
|
||||
_options.name = nameStr;
|
||||
if (isLimit && addModel.selectorValues!.length > indexOf) {
|
||||
_options.extraName = `等${addModel.selectorValues!.length}台设备`;
|
||||
}
|
||||
_options.selectorIcon = 'icon-shebei1';
|
||||
} else if (addModel.selector === 'org') {
|
||||
_options.name = addModel.selectorValues?.[0].name + '的';
|
||||
_options.productName = addModel.productDetail.name; // 产品名称
|
||||
_options.selectorIcon = 'icon-zuzhi';
|
||||
} else {
|
||||
_options.name = '所有的' + addModel.productDetail.name;
|
||||
}
|
||||
|
||||
if (data.timer) {
|
||||
const _timer = data.timer;
|
||||
if (_timer.trigger === 'cron') {
|
||||
_options.time = _timer.cron;
|
||||
} else {
|
||||
// console.log('continuousValue', continuousValue(_timer.when! || [], _timer!.trigger))
|
||||
let whenStr = '每天';
|
||||
if (_timer.when!.length) {
|
||||
whenStr = _timer!.trigger === 'week' ? '每周' : '每月';
|
||||
const whenStrArr = continuousValue(_timer.when! || [], _timer!.trigger);
|
||||
const whenStrArr3 = whenStrArr.splice(0, 3);
|
||||
whenStr += whenStrArr3.join('、');
|
||||
whenStr += `等${_timer.when!.length}天`;
|
||||
}
|
||||
_options.when = whenStr;
|
||||
if (_timer.once) {
|
||||
_options.time = _timer.once.time + ' 执行1次';
|
||||
} else if (_timer.period) {
|
||||
_options.time = _timer.period.from + '-' + _timer.period.to;
|
||||
_options.extraTime = `每${_timer.period.every}${timeUnitEnum[_timer.period.unit]}执行1次`;
|
||||
}
|
||||
}
|
||||
|
||||
if (data.operator === 'online') {
|
||||
_options.type = '上线';
|
||||
_options.action = '';
|
||||
_options.typeIcon = 'icon-a-Group4713';
|
||||
}
|
||||
|
||||
if (data.operator === 'offline') {
|
||||
_options.type = '离线';
|
||||
_options.action = '';
|
||||
_options.typeIcon = 'icon-a-Group4892';
|
||||
}
|
||||
|
||||
if (data.operator === 'reportProperty') {
|
||||
_options.type = '属性上报';
|
||||
_options.action = '';
|
||||
_options.typeIcon = 'icon-file-upload-outline';
|
||||
}
|
||||
return _options;
|
||||
}
|
||||
}
|
||||
|
||||
const prev = () => {
|
||||
|
@ -120,6 +220,16 @@ const handleMetadata = (metadata?: string) => {
|
|||
}
|
||||
}
|
||||
|
||||
const productChange = () => {
|
||||
addModel.deviceKeys = []
|
||||
addModel.orgId = []
|
||||
addModel.selector = 'fixed'
|
||||
addModel.operator = {
|
||||
operator: 'online'
|
||||
}
|
||||
addModel.selectorValues = []
|
||||
}
|
||||
|
||||
const save = async (step?: number) => {
|
||||
let _step = step !== undefined ? step : addModel.stepNumber
|
||||
if (_step === 0) {
|
||||
|
@ -139,9 +249,16 @@ const save = async (step?: number) => {
|
|||
addModel.stepNumber = 2
|
||||
} else {
|
||||
const typeData = await typeRef.value.vail()
|
||||
console.log(typeData)
|
||||
if (typeData) {
|
||||
const _options = handleOptions(typeData);
|
||||
optionsCache.value.action = typeData.action
|
||||
const _options = handleOptions(typeData.data);
|
||||
const data = {
|
||||
operator: typeData.data,
|
||||
selector: addModel.selector,
|
||||
selectorValues: addModel.selectorValues,
|
||||
productId: addModel.productId
|
||||
}
|
||||
emit('save', data, _options)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -66,6 +66,7 @@ import { getImage } from '@/utils/comm'
|
|||
type Emit = {
|
||||
(e: 'update:rowKey', data: string): void
|
||||
(e: 'update:detail', data: string): void
|
||||
(e: 'change', data: string): void
|
||||
}
|
||||
|
||||
const actionRef = ref()
|
||||
|
@ -246,6 +247,7 @@ const productQuery = (p: any) => {
|
|||
const handleClick = (detail: any) => {
|
||||
emit('update:rowKey', detail.id)
|
||||
emit('update:detail', detail)
|
||||
emit('change', detail)
|
||||
}
|
||||
|
||||
</script>
|
||||
|
|
|
@ -57,7 +57,7 @@
|
|||
import { filterSelectNode } from '@/utils/comm'
|
||||
import { TopCard, Timer } from '@/views/rule-engine/Scene/Save/components'
|
||||
import { getImage } from '@/utils/comm'
|
||||
import { metadataType } from '@/views/rule-engine/Scene/typings'
|
||||
import type { metadataType, TriggerDeviceOptions } from '@/views/rule-engine/Scene/typings'
|
||||
import type { PropType } from 'vue'
|
||||
import { TypeEnum } from '@/views/rule-engine/Scene/Save/Device/util'
|
||||
import ReadProperties from './ReadProperties.vue'
|
||||
|
@ -70,6 +70,10 @@ const props = defineProps({
|
|||
metadata: {
|
||||
type: Object as PropType<metadataType>,
|
||||
default: () => ({})
|
||||
},
|
||||
operator: {
|
||||
type: Object as PropType<TriggerDeviceOptions>,
|
||||
default: () => ({})
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -83,6 +87,8 @@ const formModel = reactive({
|
|||
functionParameters: []
|
||||
})
|
||||
|
||||
Object.assign(formModel, props.operator)
|
||||
|
||||
const optionCache = reactive({
|
||||
action: ''
|
||||
})
|
||||
|
@ -222,7 +228,7 @@ defineExpose({
|
|||
filterKey.push('writeProperties')
|
||||
}
|
||||
|
||||
resolve(omit(cloneModel, filterKey))
|
||||
resolve({ data: omit(cloneModel, filterKey), action: optionCache.action })
|
||||
})
|
||||
}
|
||||
})
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
</AddButton>
|
||||
</a-form-item>
|
||||
<Action />
|
||||
<AddModel v-if='visible' @cancel='visible = false' v-model='data.device' v-model:options='data.options.trigger' />
|
||||
<AddModel v-if='visible' @cancel='visible = false' @save='save' :value='data.trigger.device' :options='data.options.trigger' />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -26,9 +26,10 @@ import AddModel from './AddModal.vue'
|
|||
import AddButton from '../components/AddButton.vue'
|
||||
import Title from '../components/Title.vue'
|
||||
import Action from '../action/index.vue'
|
||||
import type { TriggerDevice } from '@/views/rule-engine/Scene/typings'
|
||||
|
||||
const sceneStore = useSceneStore()
|
||||
const { data } = storeToRefs<any>(sceneStore)
|
||||
const { data } = storeToRefs(sceneStore)
|
||||
|
||||
const visible = ref(false)
|
||||
|
||||
|
@ -41,6 +42,11 @@ const rules = [{
|
|||
},
|
||||
}]
|
||||
|
||||
const save = (device: TriggerDevice, options: Record<string, any>) => {
|
||||
data.value.trigger!.device = device
|
||||
data.value.options!.trigger = options
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped lang='less'>
|
||||
|
|
|
@ -0,0 +1,261 @@
|
|||
<template>
|
||||
<Search
|
||||
:columns="columns"
|
||||
type='simple'
|
||||
@search="handleSearch"
|
||||
class='search'
|
||||
target="scene-triggrt-device-device"
|
||||
/>
|
||||
<a-divider style='margin: 0' />
|
||||
<j-pro-table
|
||||
ref='actionRef'
|
||||
model='CARD'
|
||||
:columns='columns'
|
||||
:params='params'
|
||||
:request='productQuery'
|
||||
:gridColumn='2'
|
||||
:gridColumns='[2,2,2]'
|
||||
:bodyStyle='{
|
||||
paddingRight: 0,
|
||||
paddingLeft: 0
|
||||
}'
|
||||
>
|
||||
<template #card="slotProps">
|
||||
<CardBox
|
||||
:value='slotProps'
|
||||
:active="rowKey === slotProps.id"
|
||||
:status="slotProps.state"
|
||||
:statusText="slotProps.state === 1 ? '正常' : '禁用'"
|
||||
:statusNames="{ 1: 'success', 0: 'error', }"
|
||||
@click="handleClick"
|
||||
>
|
||||
<template #img>
|
||||
<slot name="img">
|
||||
<img width='88' height='88' :src="slotProps.photoUrl || getImage('/device-product.png')" />
|
||||
</slot>
|
||||
</template>
|
||||
<template #content>
|
||||
<div style='width: calc(100% - 100px)'>
|
||||
<Ellipsis>
|
||||
<span style="font-size: 16px;font-weight: 600" >
|
||||
{{ slotProps.name }}
|
||||
</span>
|
||||
</Ellipsis>
|
||||
</div>
|
||||
<a-row>
|
||||
<a-col :span="12">
|
||||
<div class="card-item-content-text">
|
||||
设备类型
|
||||
</div>
|
||||
<div>直连设备</div>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</template>
|
||||
</CardBox>
|
||||
</template>
|
||||
</j-pro-table>
|
||||
</template>
|
||||
|
||||
<script setup lang='ts' name='Product'>
|
||||
import { getProviders, queryGatewayList, queryProductList } from '@/api/device/product'
|
||||
import { queryTree } from '@/api/device/category'
|
||||
import { getTreeData_api } from '@/api/system/department'
|
||||
import { isNoCommunity } from '@/utils/utils'
|
||||
import { getImage } from '@/utils/comm'
|
||||
|
||||
type Emit = {
|
||||
(e: 'update:rowKey', data: string): void
|
||||
(e: 'update:detail', data: string): void
|
||||
(e: 'change', data: string): void
|
||||
}
|
||||
|
||||
const actionRef = ref()
|
||||
const params = ref({})
|
||||
const props = defineProps({
|
||||
rowKey: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
detail: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
}
|
||||
})
|
||||
|
||||
const emit = defineEmits<Emit>()
|
||||
|
||||
const columns = [
|
||||
{
|
||||
title: 'ID',
|
||||
dataIndex: 'id',
|
||||
width: 300,
|
||||
ellipsis: true,
|
||||
fixed: 'left',
|
||||
search: {
|
||||
type: 'string',
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '名称',
|
||||
dataIndex: 'name',
|
||||
width: 200,
|
||||
ellipsis: true,
|
||||
search: {
|
||||
type: 'string',
|
||||
first: true
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '网关类型',
|
||||
dataIndex: 'accessProvider',
|
||||
width: 150,
|
||||
ellipsis: true,
|
||||
hideInTable: true,
|
||||
search: {
|
||||
type: 'select',
|
||||
options: () => getProviders().then((resp: any) => {
|
||||
if (isNoCommunity) {
|
||||
return (resp?.result || []).map((item: any) => ({
|
||||
label: item.name,
|
||||
value: item.id
|
||||
}))
|
||||
} else {
|
||||
return (resp?.result || []).filter((item: any) => [
|
||||
'mqtt-server-gateway',
|
||||
'http-server-gateway',
|
||||
'mqtt-client-gateway',
|
||||
'tcp-server-gateway',
|
||||
].includes(item.id))
|
||||
.map((item: any) => ({
|
||||
label: item.name,
|
||||
value: item.id,
|
||||
}))
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '接入方式',
|
||||
dataIndex: 'accessName',
|
||||
width: 150,
|
||||
ellipsis: true,
|
||||
search: {
|
||||
type: 'select',
|
||||
options: () => queryGatewayList().then((resp: any) =>
|
||||
resp.result.map((item: any) => ({
|
||||
label: item.name, value: item.id
|
||||
}))
|
||||
)
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '设备类型',
|
||||
dataIndex: 'deviceType',
|
||||
width: 150,
|
||||
search: {
|
||||
type: 'select',
|
||||
options: [
|
||||
{ label: '直连设备', value: 'device' },
|
||||
{ label: '网关子设备', value: 'childrenDevice' },
|
||||
{ label: '网关设备', value: 'gateway' },
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '状态',
|
||||
dataIndex: 'state',
|
||||
width: '90px',
|
||||
search: {
|
||||
type: 'select',
|
||||
options: [
|
||||
{ label: '禁用', value: 0 },
|
||||
{ label: '正常', value: 1 },
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '说明',
|
||||
dataIndex: 'describe',
|
||||
ellipsis: true,
|
||||
width: 300,
|
||||
},
|
||||
{
|
||||
dataIndex: 'classifiedId',
|
||||
title: '分类',
|
||||
hideInTable: true,
|
||||
search: {
|
||||
type: 'treeSelect',
|
||||
options: queryTree({ paging: false }).then(resp => resp.result),
|
||||
componentProps: {
|
||||
fieldNames: {
|
||||
label: 'name',
|
||||
value: 'id',
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
dataIndex: 'id$dim-assets',
|
||||
title: '所属组织',
|
||||
hideInTable: true,
|
||||
search: {
|
||||
type: 'treeSelect',
|
||||
options: getTreeData_api({ paging: false }).then((resp: any) => {
|
||||
const formatValue = (list: any[]) => {
|
||||
return list.map((item: any) => {
|
||||
if (item.children) {
|
||||
item.children = formatValue(item.children);
|
||||
}
|
||||
return {
|
||||
...item,
|
||||
value: JSON.stringify({
|
||||
assetType: 'product',
|
||||
targets: [
|
||||
{
|
||||
type: 'org',
|
||||
id: item.id,
|
||||
},
|
||||
],
|
||||
}),
|
||||
}
|
||||
})
|
||||
}
|
||||
return formatValue(resp.result)
|
||||
}),
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
const handleSearch = (p: any) => {
|
||||
params.value = p
|
||||
}
|
||||
|
||||
const productQuery = (p: any) => {
|
||||
const sorts: any = [];
|
||||
|
||||
if (props.rowKey) {
|
||||
sorts.push({
|
||||
name: 'id',
|
||||
value: props.rowKey,
|
||||
});
|
||||
}
|
||||
sorts.push({ name: 'createTime', order: 'desc' });
|
||||
p.sorts = sorts
|
||||
return queryProductList(p)
|
||||
}
|
||||
|
||||
const handleClick = (detail: any) => {
|
||||
emit('update:rowKey', detail.id)
|
||||
emit('update:detail', detail)
|
||||
emit('change', detail)
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped lang='less'>
|
||||
.search {
|
||||
margin-bottom: 0;
|
||||
padding-right: 0px;
|
||||
padding-left: 0px;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,14 @@
|
|||
|
||||
<template>
|
||||
<div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang='ts' name="Device">
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped lang='less'>
|
||||
|
||||
</style>
|
|
@ -1,22 +1,104 @@
|
|||
<template>
|
||||
<j-modal
|
||||
title="执行动作"
|
||||
visible
|
||||
:width="860"
|
||||
@cancel="onCancel"
|
||||
@ok="onOk"
|
||||
:maskClosable="false"
|
||||
>
|
||||
device
|
||||
<j-modal title="执行动作" visible :width="860" @cancel="onCancel" @ok="save" :maskClosable="false">
|
||||
<j-steps :current='DeviceModel.current' @change='stepChange'>
|
||||
<j-step>
|
||||
<template #title>选择产品</template>
|
||||
</j-step>
|
||||
<j-step>
|
||||
<template #title>选择设备</template>
|
||||
</j-step>
|
||||
<j-step>
|
||||
<template #title>执行动作</template>
|
||||
</j-step>
|
||||
</j-steps>
|
||||
<j-divider style='margin-bottom: 10px;' />
|
||||
<div class='steps-content'>
|
||||
<Product v-if='DeviceModel.current === 0' v-model:rowKey='DeviceModel.productId'
|
||||
v-model:detail='DeviceModel.productDetail' />
|
||||
</div>
|
||||
<template #footer>
|
||||
<div class='steps-action'>
|
||||
<j-button v-if='DeviceModel.current === 0' @click='cancel'>取消</j-button>
|
||||
<j-button v-else @click='prev'>上一步</j-button>
|
||||
<j-button type='primary' v-if='DeviceModel.current < 2' @click='saveClick'>下一步</j-button>
|
||||
<j-button type='primary' v-else @click='saveClick'>确定</j-button>
|
||||
</div>
|
||||
</template>
|
||||
</j-modal>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
const emit = defineEmits(['cancel', 'save']);
|
||||
const onCancel = () => {
|
||||
import { DeviceModelType } from './typings';
|
||||
import Product from './Product.vue';
|
||||
import { onlyMessage } from '@/utils/comm';
|
||||
|
||||
type Emit = {
|
||||
(e: 'cancel'): void
|
||||
(e: 'save', data: any, options: Record<string, any>): void
|
||||
}
|
||||
|
||||
|
||||
const DeviceModel = reactive<DeviceModelType>({
|
||||
steps: [],
|
||||
current: 0,
|
||||
productId: '',
|
||||
deviceId: '',
|
||||
productDetail: {},
|
||||
device: {},
|
||||
deviceDetail: {},
|
||||
options: {},
|
||||
selector: 'fixed',
|
||||
selectorValues: [],
|
||||
upperKey: '',
|
||||
source: 'fixed',
|
||||
relationName: '',
|
||||
message: {},
|
||||
propertiesName: '',
|
||||
propertiesValue: '',
|
||||
columns: [],
|
||||
actionName: '',
|
||||
tagList: [],
|
||||
})
|
||||
|
||||
const emit = defineEmits<Emit>()
|
||||
const cancel = () => {
|
||||
emit('cancel');
|
||||
};
|
||||
const onOk = () => {
|
||||
emit('save');
|
||||
const save = async(step?: number) => {
|
||||
let _step = step !== undefined ? step : DeviceModel.current
|
||||
if (_step === 0) {
|
||||
DeviceModel.productId ? DeviceModel.current = 1 : onlyMessage('请选择产品', 'error')
|
||||
} else if (_step === 1) {
|
||||
|
||||
} else {
|
||||
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
const stepChange = (step: number) => {
|
||||
if (step !== 0) {
|
||||
save(step - 1)
|
||||
} else {
|
||||
DeviceModel.current = 0
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const prev = () => {
|
||||
DeviceModel.current = DeviceModel.current - 1
|
||||
}
|
||||
const saveClick = () => save()
|
||||
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.steps-steps {
|
||||
width: 100%;
|
||||
margin-bottom: 17px;
|
||||
padding-bottom: 17px;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
}
|
||||
|
||||
.steps-content {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,28 @@
|
|||
import { ProductItem } from '@/views/device/Product/typings';
|
||||
import { ActionsDeviceProps } from '../../../typings';
|
||||
|
||||
type DeviceModelType = {
|
||||
steps: {
|
||||
key: string;
|
||||
title: string;
|
||||
content: React.ReactNode;
|
||||
}[];
|
||||
current: number;
|
||||
productId: string;
|
||||
deviceId: string;
|
||||
productDetail: ProductItem | any;
|
||||
device: Partial<ActionsDeviceProps>;
|
||||
deviceDetail: any;
|
||||
options: any;
|
||||
selector: string;
|
||||
selectorValues: any;
|
||||
upperKey: string;
|
||||
source: string;
|
||||
relationName: string;
|
||||
message: any;
|
||||
propertiesName: string;
|
||||
propertiesValue: string | any;
|
||||
columns: string[];
|
||||
actionName: string;
|
||||
tagList: any[];
|
||||
}
|
|
@ -1,3 +1,4 @@
|
|||
import { isArray } from 'lodash-es'
|
||||
export const numberToString = {
|
||||
1: '星期一',
|
||||
2: '星期二',
|
||||
|
@ -6,4 +7,46 @@ export const numberToString = {
|
|||
5: '星期五',
|
||||
6: '星期六',
|
||||
7: '星期日',
|
||||
};
|
||||
|
||||
export const timeUnitEnum = {
|
||||
seconds: '秒',
|
||||
minutes: '分',
|
||||
hours: '小时',
|
||||
};
|
||||
|
||||
type continuousValueFn = (data: (string | number)[], type: string) => (number | string)[];
|
||||
|
||||
export const continuousValue: continuousValueFn = (data, type) => {
|
||||
let start = 0;
|
||||
const newArray: (number | string)[] = [];
|
||||
const isWeek = type === 'week';
|
||||
if (isArray(data)) {
|
||||
data.forEach((item, index) => {
|
||||
const _item = Number(item);
|
||||
const nextValue = data[index + 1];
|
||||
const previousValue = data[index - 1];
|
||||
const nextItemValue = _item + 1;
|
||||
const previousItemValue = _item - 1;
|
||||
if (nextItemValue === nextValue && previousItemValue !== previousValue) {
|
||||
start = _item;
|
||||
} else if (previousItemValue === previousValue && nextItemValue !== nextValue) {
|
||||
// 表示前start和item连续,并且item与nextValue不连续
|
||||
if (_item - start >= 2) {
|
||||
// 至少三位连续
|
||||
newArray.push(
|
||||
isWeek
|
||||
? `${numberToString[start]} - ${numberToString[_item]}`
|
||||
: `${start} - ${_item}号`,
|
||||
);
|
||||
} else {
|
||||
newArray.push(isWeek ? numberToString[start] : `${start}号`);
|
||||
newArray.push(isWeek ? numberToString[_item] : `${_item}号`);
|
||||
}
|
||||
} else if (previousItemValue !== previousValue && nextItemValue !== nextValue) {
|
||||
newArray.push(isWeek ? numberToString[_item] : `${_item}号`);
|
||||
}
|
||||
});
|
||||
}
|
||||
return newArray;
|
||||
};
|
|
@ -5,13 +5,13 @@
|
|||
<div class='center-item'>
|
||||
<AIcon v-if='options.selectorIcon' :type='options.selectorIcon' class='icon-padding-right' />
|
||||
<span class='trigger-options-name'>
|
||||
<Ellipsis style='width: 310px'>
|
||||
<Ellipsis style='max-width: 310px'>
|
||||
{{ options.name }}
|
||||
</Ellipsis>
|
||||
</span>
|
||||
</span>
|
||||
<span v-if='options.extraName'>{{ options.extraName }}</span>
|
||||
</div>
|
||||
<template v-if='options.onlyName'>
|
||||
<template v-if='!options.onlyName'>
|
||||
<div v-if='options.productName' class='center-item'>
|
||||
<AIcon type='icon-chanpin1' class='icon-padding-right' />
|
||||
<span className='trigger-options-type'>{{ options.productName }}</span>
|
||||
|
@ -28,7 +28,7 @@
|
|||
</div>
|
||||
<div v-if='options.action' class='center-item'>
|
||||
<AIcon :type='options.typeIcon' class='icon-padding-right' />
|
||||
<span className='trigger-options-action'>{{ options.productName }}</span>
|
||||
<span className='trigger-options-action'>{{ options.action }}</span>
|
||||
</div>
|
||||
<div v-if='options.type' class='center-item'>
|
||||
<AIcon :type='options.typeIcon' class='icon-padding-right' />
|
||||
|
@ -57,6 +57,8 @@ const isAdd = computed(() => {
|
|||
|
||||
<style scoped lang='less'>
|
||||
.trigger-options-content {
|
||||
display: inline-flex;
|
||||
gap: 16px;
|
||||
|
||||
.center-item {
|
||||
display: flex;
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<div class="apply-container">
|
||||
<Search :columns="columns" @search="search" />
|
||||
|
||||
<JTable
|
||||
<j-pro-table
|
||||
ref="tableRef"
|
||||
:columns="columns"
|
||||
:request="getApplyList_api"
|
||||
|
@ -158,7 +158,7 @@
|
|||
</PermissionButton>
|
||||
</a-space>
|
||||
</template>
|
||||
</JTable>
|
||||
</j-pro-table>
|
||||
</div>
|
||||
<div class="dialogs">
|
||||
<MenuDialog ref="dialogRef" mode="edit" />
|
||||
|
|
|
@ -45,7 +45,7 @@
|
|||
>保存</a-button
|
||||
>
|
||||
</div>
|
||||
<JTable
|
||||
<j-pro-table
|
||||
ref="tableRef"
|
||||
:columns="table.columns"
|
||||
model="TABLE"
|
||||
|
@ -109,7 +109,7 @@
|
|||
<AIcon type="DeleteOutlined" />
|
||||
</PermissionButton>
|
||||
</template>
|
||||
</JTable>
|
||||
</j-pro-table>
|
||||
<a-botton class="add-row" @click="table.addRow">
|
||||
<AIcon type="PlusOutlined" /> 新增行
|
||||
</a-botton>
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<div class="data-source-container">
|
||||
<Search :columns="query.columns" @search="query.search" />
|
||||
|
||||
<JTable
|
||||
<j-pro-table
|
||||
ref="tableRef"
|
||||
:columns="table.columns"
|
||||
:request="getDataSourceList_api"
|
||||
|
@ -122,7 +122,7 @@
|
|||
</PermissionButton>
|
||||
</a-space>
|
||||
</template>
|
||||
</JTable>
|
||||
</j-pro-table>
|
||||
|
||||
<div class="dialogs">
|
||||
<EditDialog ref="editDialogRef" @confirm="table.refresh" />
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
|
||||
<Search :columns="props.queryColumns" @search="query.search" />
|
||||
|
||||
<JTable
|
||||
<j-pro-table
|
||||
ref="tableRef"
|
||||
:request="table.requestFun"
|
||||
:gridColumn="2"
|
||||
|
@ -101,7 +101,7 @@
|
|||
</template>
|
||||
</CardBox>
|
||||
</template>
|
||||
</JTable>
|
||||
</j-pro-table>
|
||||
</a-modal>
|
||||
</template>
|
||||
|
||||
|
@ -115,6 +115,7 @@ import {
|
|||
bindDeviceOrProductList_api,
|
||||
} from '@/api/system/department';
|
||||
import { message } from 'ant-design-vue';
|
||||
import { dictType } from '../typing';
|
||||
|
||||
const emits = defineEmits(['confirm']);
|
||||
const props = defineProps<{
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<template>
|
||||
<div class="product-container">
|
||||
<Search :columns="query.columns" @search="query.search" />
|
||||
<JTable
|
||||
<j-pro-table
|
||||
ref="tableRef"
|
||||
:request="table.requestFun"
|
||||
:gridColumn="2"
|
||||
|
@ -130,7 +130,7 @@
|
|||
</template>
|
||||
</CardBox>
|
||||
</template>
|
||||
</JTable>
|
||||
</j-pro-table>
|
||||
|
||||
<div class="dialogs">
|
||||
<AddDeviceOrProductDialog
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<template>
|
||||
<div class="product-container">
|
||||
<Search :columns="query.columns" @search="query.search" />
|
||||
<JTable
|
||||
<j-pro-table
|
||||
ref="tableRef"
|
||||
:request="table.requestFun"
|
||||
:gridColumn="2"
|
||||
|
@ -130,7 +130,7 @@
|
|||
</template>
|
||||
</CardBox>
|
||||
</template>
|
||||
</JTable>
|
||||
</j-pro-table>
|
||||
|
||||
<div class="dialogs">
|
||||
<AddDeviceOrProductDialog
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
>
|
||||
<Search :columns="query.columns" @search="query.search" />
|
||||
<div class="table">
|
||||
<JTable
|
||||
<j-pro-table
|
||||
ref="tableRef"
|
||||
:columns="table.columns"
|
||||
:request="table.requestFun"
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<div>
|
||||
<Search :columns="query.columns" @search="query.search" />
|
||||
|
||||
<JTable
|
||||
<j-pro-table
|
||||
ref="tableRef"
|
||||
:columns="table.columns"
|
||||
:request="table.requestFun"
|
||||
|
@ -58,7 +58,7 @@
|
|||
</PermissionButton>
|
||||
</a-space>
|
||||
</template>
|
||||
</JTable>
|
||||
</j-pro-table>
|
||||
|
||||
<div class="dialogs">
|
||||
<AddBindUserDialog
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<div class="button-mange-container">
|
||||
<JTable
|
||||
<j-pro-table
|
||||
ref="tableRef"
|
||||
:columns="table.columns"
|
||||
model="TABLE"
|
||||
|
@ -47,7 +47,7 @@
|
|||
</PermissionButton>
|
||||
</a-space>
|
||||
</template>
|
||||
</JTable>
|
||||
</j-pro-table>
|
||||
|
||||
<div class="dialog">
|
||||
<ButtonAddDialog
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<div class="menu-container">
|
||||
<Search :columns="query.columns" @search="query.search" />
|
||||
|
||||
<JTable
|
||||
<j-pro-table
|
||||
ref="tableRef"
|
||||
:columns="table.columns"
|
||||
:request="table.getList"
|
||||
|
@ -71,7 +71,7 @@
|
|||
</PermissionButton>
|
||||
</a-space>
|
||||
</template>
|
||||
</JTable>
|
||||
</j-pro-table>
|
||||
</div>
|
||||
</page-container>
|
||||
</template>
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<div class="permission-container">
|
||||
<Search :columns="query.columns" @search="query.search" />
|
||||
|
||||
<JTable
|
||||
<j-pro-table
|
||||
ref="tableRef"
|
||||
:columns="table.columns"
|
||||
:request="getPermission_api"
|
||||
|
@ -115,7 +115,7 @@
|
|||
</PermissionButton>
|
||||
</a-space>
|
||||
</template>
|
||||
</JTable>
|
||||
</j-pro-table>
|
||||
|
||||
<div class="dialogs">
|
||||
<EditDialog ref="editDialogRef" @refresh="table.refresh" />
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
<div class="api-card">
|
||||
<h5>请求参数</h5>
|
||||
<div class="content">
|
||||
<JTable
|
||||
<j-pro-table
|
||||
:columns="requestCard.columns"
|
||||
:dataSource="requestCard.tableData"
|
||||
noPagination
|
||||
|
@ -33,19 +33,19 @@
|
|||
<template #type="slotProps">
|
||||
<span>{{ slotProps.schema.type }}</span>
|
||||
</template>
|
||||
</JTable>
|
||||
</j-pro-table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="api-card">
|
||||
<h5>响应状态</h5>
|
||||
<div class="content">
|
||||
<JTable
|
||||
<j-pro-table
|
||||
:columns="responseStatusCard.columns"
|
||||
:dataSource="responseStatusCard.tableData"
|
||||
noPagination
|
||||
model="TABLE"
|
||||
>
|
||||
</JTable>
|
||||
</j-pro-table>
|
||||
|
||||
<a-tabs v-model:activeKey="responseStatusCard.activeKey">
|
||||
<a-tab-pane
|
||||
|
@ -60,13 +60,13 @@
|
|||
<div class="api-card">
|
||||
<h5>响应参数</h5>
|
||||
<div class="content">
|
||||
<JTable
|
||||
<j-pro-table
|
||||
:columns="respParamsCard.columns"
|
||||
:dataSource="respParamsCard.tableData"
|
||||
noPagination
|
||||
model="TABLE"
|
||||
>
|
||||
</JTable>
|
||||
</j-pro-table>
|
||||
</div>
|
||||
|
||||
<MonacoEditor
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<div class="choose-api-container">
|
||||
<JTable
|
||||
<j-pro-table
|
||||
:columns="columns"
|
||||
:dataSource="props.tableData"
|
||||
:rowSelection="props.mode !== 'home' ? rowSelection : undefined"
|
||||
|
@ -14,7 +14,7 @@
|
|||
>{{ slotProps.url }}</span
|
||||
>
|
||||
</template>
|
||||
</JTable>
|
||||
</j-pro-table>
|
||||
|
||||
<a-button type="primary" @click="save" v-if="props.mode !== 'home'"
|
||||
>保存</a-button
|
||||
|
|
|
@ -60,7 +60,7 @@
|
|||
<div style="width: 50%">
|
||||
<h3>示例数据</h3>
|
||||
<div>
|
||||
<JTable
|
||||
<j-pro-table
|
||||
:dataSource="data"
|
||||
model="TABLE"
|
||||
noPagination
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<div class="relationship-container">
|
||||
<Search :columns="query.columns" @search="query.search" />
|
||||
|
||||
<JTable
|
||||
<j-pro-table
|
||||
ref="tableRef"
|
||||
:columns="table.columns"
|
||||
:request="getRelationshipList_api"
|
||||
|
@ -49,7 +49,7 @@
|
|||
</PermissionButton>
|
||||
</a-space>
|
||||
</template>
|
||||
</JTable>
|
||||
</j-pro-table>
|
||||
|
||||
<EditDialog ref="editDialogRef" @refresh="table.refresh" />
|
||||
</div>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<a-card class="role-user-container">
|
||||
<Search :columns="query.columns" />
|
||||
|
||||
<JTable
|
||||
<j-pro-table
|
||||
ref="tableRef"
|
||||
:columns="table.columns"
|
||||
:request="getUserByRole_api"
|
||||
|
@ -37,7 +37,7 @@
|
|||
</a-popconfirm>
|
||||
</a-space>
|
||||
</template>
|
||||
</JTable>
|
||||
</j-pro-table>
|
||||
|
||||
<div class="dialogs">
|
||||
<AddUserDialog :open="dialog.openAdd" @refresh="table.refresh" />
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
>
|
||||
<Search :columns="query.columns" type="simple" />
|
||||
|
||||
<JTable
|
||||
<j-pro-table
|
||||
ref="tableRef"
|
||||
:columns="table.columns"
|
||||
:request="getUserByRole_api"
|
||||
|
@ -19,7 +19,7 @@
|
|||
}"
|
||||
@cancelSelect="table.cancelSelect"
|
||||
>
|
||||
</JTable>
|
||||
</j-pro-table>
|
||||
|
||||
<template #footer>
|
||||
<a-button key="back" @click="dialog.visible = false">取消</a-button>
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<a-card class="role-container">
|
||||
<Search :columns="query.columns" />
|
||||
|
||||
<JTable
|
||||
<j-pro-table
|
||||
ref="tableRef"
|
||||
:columns="table.columns"
|
||||
:request="getRoleList_api"
|
||||
|
@ -45,7 +45,7 @@
|
|||
</PermissionButton>
|
||||
</a-space>
|
||||
</template>
|
||||
</JTable>
|
||||
</j-pro-table>
|
||||
|
||||
<div class="dialogs">
|
||||
<AddDialog ref="addDialogRef" />
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<div class="user-container">
|
||||
<Search :columns="query.columns" @search="query.search" />
|
||||
|
||||
<JTable
|
||||
<j-pro-table
|
||||
ref="tableRef"
|
||||
:columns="table.columns"
|
||||
:request="getUserList_api"
|
||||
|
@ -43,62 +43,6 @@
|
|||
</template>
|
||||
<template #action="slotProps">
|
||||
<a-space :size="16">
|
||||
<!-- <a-tooltip>
|
||||
<template #title>编辑</template>
|
||||
<a-button
|
||||
style="padding: 0"
|
||||
type="link"
|
||||
@click="table.openDialog('edit', slotProps)"
|
||||
>
|
||||
<AIcon type="EditOutlined" />
|
||||
</a-button>
|
||||
</a-tooltip> -->
|
||||
<!-- <a-popconfirm
|
||||
:title="`确定${slotProps.status ? '禁用' : '启用'}吗?`"
|
||||
ok-text="确定"
|
||||
cancel-text="取消"
|
||||
@confirm="table.changeStatus(slotProps)"
|
||||
>
|
||||
<a-tooltip>
|
||||
<template #title>{{
|
||||
slotProps.status ? '禁用' : '启用'
|
||||
}}</template>
|
||||
<a-button style="padding: 0" type="link">
|
||||
<stop-outlined v-if="slotProps.status" />
|
||||
<play-circle-outlined v-else />
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
</a-popconfirm> -->
|
||||
<!-- <a-tooltip>
|
||||
<template #title>重置密码</template>
|
||||
<a-button
|
||||
style="padding: 0"
|
||||
type="link"
|
||||
@click="table.openDialog('reset', slotProps)"
|
||||
>
|
||||
<AIcon type="icon-zhongzhimima" />
|
||||
</a-button>
|
||||
</a-tooltip> -->
|
||||
<!-- <a-popconfirm
|
||||
title="确认删除"
|
||||
ok-text="确定"
|
||||
cancel-text="取消"
|
||||
@confirm="table.clickDel(slotProps)"
|
||||
:disabled="slotProps.status"
|
||||
>
|
||||
<a-tooltip>
|
||||
<template #title>{{
|
||||
slotProps.status ? '请先禁用,再删除' : '删除'
|
||||
}}</template>
|
||||
<a-button
|
||||
style="padding: 0"
|
||||
type="link"
|
||||
:disabled="slotProps.status"
|
||||
>
|
||||
<AIcon type="DeleteOutlined" />
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
</a-popconfirm> -->
|
||||
|
||||
<PermissionButton
|
||||
:uhasPermission="`${permission}:update`"
|
||||
|
@ -154,7 +98,7 @@
|
|||
</PermissionButton>
|
||||
</a-space>
|
||||
</template>
|
||||
</JTable>
|
||||
</j-pro-table>
|
||||
|
||||
<div class="dialogs">
|
||||
<EditUserDialog ref="editDialogRef" @confirm="table.refresh" />
|
||||
|
|
423
yarn.lock
423
yarn.lock
|
@ -36,19 +36,19 @@
|
|||
|
||||
"@ant-design/colors@^6.0.0":
|
||||
version "6.0.0"
|
||||
resolved "https://registry.npmjs.org/@ant-design/colors/-/colors-6.0.0.tgz"
|
||||
resolved "https://registry.jetlinks.cn/@ant-design%2fcolors/-/colors-6.0.0.tgz#9b9366257cffcc47db42b9d0203bb592c13c0298"
|
||||
integrity sha512-qAZRvPzfdWHtfameEGP2Qvuf838NhergR35o+EuVyB5XvSA98xod5r4utvi4TJ3ywmevm290g9nsCG5MryrdWQ==
|
||||
dependencies:
|
||||
"@ctrl/tinycolor" "^3.4.0"
|
||||
|
||||
"@ant-design/icons-svg@^4.2.1":
|
||||
version "4.2.1"
|
||||
resolved "https://registry.npmjs.org/@ant-design/icons-svg/-/icons-svg-4.2.1.tgz"
|
||||
resolved "https://registry.jetlinks.cn/@ant-design%2ficons-svg/-/icons-svg-4.2.1.tgz#8630da8eb4471a4aabdaed7d1ff6a97dcb2cf05a"
|
||||
integrity sha512-EB0iwlKDGpG93hW8f85CTJTs4SvMX7tt5ceupvhALp1IF44SeUFOMhKUOYqpsoYWQKAOuTRDMqn75rEaKDp0Xw==
|
||||
|
||||
"@ant-design/icons-vue@^6.1.0":
|
||||
version "6.1.0"
|
||||
resolved "https://registry.npmjs.org/@ant-design/icons-vue/-/icons-vue-6.1.0.tgz"
|
||||
resolved "https://registry.jetlinks.cn/@ant-design%2ficons-vue/-/icons-vue-6.1.0.tgz#f9324fdc0eb4cea943cf626d2bf3db9a4ff4c074"
|
||||
integrity sha512-EX6bYm56V+ZrKN7+3MT/ubDkvJ5rK/O2t380WFRflDcVFgsvl3NLH7Wxeau6R8DbrO5jWR6DSTC3B6gYFp77AA==
|
||||
dependencies:
|
||||
"@ant-design/colors" "^6.0.0"
|
||||
|
@ -288,9 +288,9 @@
|
|||
"@babel/plugin-syntax-typescript" "^7.20.0"
|
||||
|
||||
"@babel/runtime@^7.10.5":
|
||||
version "7.20.7"
|
||||
resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.20.7.tgz"
|
||||
integrity sha512-UF0tvkUtxwAgZ5W/KrkHf0Rn0fdnLDU9ScxBrEVNUprE/MzirjK4MJUX1/BVDv00Sv8cljtukVK1aky++X1SjQ==
|
||||
version "7.21.0"
|
||||
resolved "https://registry.jetlinks.cn/@babel%2fruntime/-/runtime-7.21.0.tgz#5b55c9d394e5fcf304909a8b00c07dc217b56673"
|
||||
integrity sha512-xwII0//EObnq89Ji5AKYQaRYiW/nZ3llSv29d49IuxPhKbtJoLP+9QUUZ4nVragQVtaVGeZrpB+ZtG/Pdy/POw==
|
||||
dependencies:
|
||||
regenerator-runtime "^0.13.11"
|
||||
|
||||
|
@ -502,9 +502,9 @@
|
|||
"@jridgewell/trace-mapping" "0.3.9"
|
||||
|
||||
"@ctrl/tinycolor@^3.4.0":
|
||||
version "3.5.0"
|
||||
resolved "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-3.5.0.tgz"
|
||||
integrity sha512-tlJpwF40DEQcfR/QF+wNMVyGMaO9FQp6Z1Wahj4Gk3CJQYHwA2xVG7iKDFdW6zuxZY9XWOpGcfNCTsX4McOsOg==
|
||||
version "3.6.0"
|
||||
resolved "https://registry.jetlinks.cn/@ctrl%2ftinycolor/-/tinycolor-3.6.0.tgz#53fa5fe9c34faee89469e48f91d51a3766108bc8"
|
||||
integrity sha512-/Z3l6pXthq0JvMYdUFyX9j0MaCltlIn6mfh9jLyQwg5aPKxkyNa0PTHtU1AlFXLNk55ZuAeJRcpvq+tmLfKmaQ==
|
||||
|
||||
"@esbuild/android-arm64@0.16.12":
|
||||
version "0.16.12"
|
||||
|
@ -855,6 +855,107 @@
|
|||
node-gyp "^7.1.0"
|
||||
read-package-json-fast "^2.0.1"
|
||||
|
||||
"@octokit/auth-token@^2.4.4":
|
||||
version "2.5.0"
|
||||
resolved "https://registry.npmmirror.com/@octokit/auth-token/-/auth-token-2.5.0.tgz#27c37ea26c205f28443402477ffd261311f21e36"
|
||||
integrity sha512-r5FVUJCOLl19AxiuZD2VRZ/ORjp/4IN98Of6YJoJOkY75CIBuYfmiNHGrDwXr+aLGG55igl9QrxX3hbiXlLb+g==
|
||||
dependencies:
|
||||
"@octokit/types" "^6.0.3"
|
||||
|
||||
"@octokit/core@^3.5.1":
|
||||
version "3.6.0"
|
||||
resolved "https://registry.npmmirror.com/@octokit/core/-/core-3.6.0.tgz#3376cb9f3008d9b3d110370d90e0a1fcd5fe6085"
|
||||
integrity sha512-7RKRKuA4xTjMhY+eG3jthb3hlZCsOwg3rztWh75Xc+ShDWOfDDATWbeZpAHBNRpm4Tv9WgBMOy1zEJYXG6NJ7Q==
|
||||
dependencies:
|
||||
"@octokit/auth-token" "^2.4.4"
|
||||
"@octokit/graphql" "^4.5.8"
|
||||
"@octokit/request" "^5.6.3"
|
||||
"@octokit/request-error" "^2.0.5"
|
||||
"@octokit/types" "^6.0.3"
|
||||
before-after-hook "^2.2.0"
|
||||
universal-user-agent "^6.0.0"
|
||||
|
||||
"@octokit/endpoint@^6.0.1":
|
||||
version "6.0.12"
|
||||
resolved "https://registry.npmmirror.com/@octokit/endpoint/-/endpoint-6.0.12.tgz#3b4d47a4b0e79b1027fb8d75d4221928b2d05658"
|
||||
integrity sha512-lF3puPwkQWGfkMClXb4k/eUT/nZKQfxinRWJrdZaJO85Dqwo/G0yOC434Jr2ojwafWJMYqFGFa5ms4jJUgujdA==
|
||||
dependencies:
|
||||
"@octokit/types" "^6.0.3"
|
||||
is-plain-object "^5.0.0"
|
||||
universal-user-agent "^6.0.0"
|
||||
|
||||
"@octokit/graphql@^4.5.8":
|
||||
version "4.8.0"
|
||||
resolved "https://registry.npmmirror.com/@octokit/graphql/-/graphql-4.8.0.tgz#664d9b11c0e12112cbf78e10f49a05959aa22cc3"
|
||||
integrity sha512-0gv+qLSBLKF0z8TKaSKTsS39scVKF9dbMxJpj3U0vC7wjNWFuIpL/z76Qe2fiuCbDRcJSavkXsVtMS6/dtQQsg==
|
||||
dependencies:
|
||||
"@octokit/request" "^5.6.0"
|
||||
"@octokit/types" "^6.0.3"
|
||||
universal-user-agent "^6.0.0"
|
||||
|
||||
"@octokit/openapi-types@^12.11.0":
|
||||
version "12.11.0"
|
||||
resolved "https://registry.npmmirror.com/@octokit/openapi-types/-/openapi-types-12.11.0.tgz#da5638d64f2b919bca89ce6602d059f1b52d3ef0"
|
||||
integrity sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ==
|
||||
|
||||
"@octokit/plugin-paginate-rest@^2.16.8":
|
||||
version "2.21.3"
|
||||
resolved "https://registry.npmmirror.com/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.21.3.tgz#7f12532797775640dbb8224da577da7dc210c87e"
|
||||
integrity sha512-aCZTEf0y2h3OLbrgKkrfFdjRL6eSOo8komneVQJnYecAxIej7Bafor2xhuDJOIFau4pk0i/P28/XgtbyPF0ZHw==
|
||||
dependencies:
|
||||
"@octokit/types" "^6.40.0"
|
||||
|
||||
"@octokit/plugin-request-log@^1.0.4":
|
||||
version "1.0.4"
|
||||
resolved "https://registry.npmmirror.com/@octokit/plugin-request-log/-/plugin-request-log-1.0.4.tgz#5e50ed7083a613816b1e4a28aeec5fb7f1462e85"
|
||||
integrity sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA==
|
||||
|
||||
"@octokit/plugin-rest-endpoint-methods@^5.12.0":
|
||||
version "5.16.2"
|
||||
resolved "https://registry.npmmirror.com/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.16.2.tgz#7ee8bf586df97dd6868cf68f641354e908c25342"
|
||||
integrity sha512-8QFz29Fg5jDuTPXVtey05BLm7OB+M8fnvE64RNegzX7U+5NUXcOcnpTIK0YfSHBg8gYd0oxIq3IZTe9SfPZiRw==
|
||||
dependencies:
|
||||
"@octokit/types" "^6.39.0"
|
||||
deprecation "^2.3.1"
|
||||
|
||||
"@octokit/request-error@^2.0.5", "@octokit/request-error@^2.1.0":
|
||||
version "2.1.0"
|
||||
resolved "https://registry.npmmirror.com/@octokit/request-error/-/request-error-2.1.0.tgz#9e150357831bfc788d13a4fd4b1913d60c74d677"
|
||||
integrity sha512-1VIvgXxs9WHSjicsRwq8PlR2LR2x6DwsJAaFgzdi0JfJoGSO8mYI/cHJQ+9FbN21aa+DrgNLnwObmyeSC8Rmpg==
|
||||
dependencies:
|
||||
"@octokit/types" "^6.0.3"
|
||||
deprecation "^2.0.0"
|
||||
once "^1.4.0"
|
||||
|
||||
"@octokit/request@^5.6.0", "@octokit/request@^5.6.3":
|
||||
version "5.6.3"
|
||||
resolved "https://registry.npmmirror.com/@octokit/request/-/request-5.6.3.tgz#19a022515a5bba965ac06c9d1334514eb50c48b0"
|
||||
integrity sha512-bFJl0I1KVc9jYTe9tdGGpAMPy32dLBXXo1dS/YwSCTL/2nd9XeHsY616RE3HPXDVk+a+dBuzyz5YdlXwcDTr2A==
|
||||
dependencies:
|
||||
"@octokit/endpoint" "^6.0.1"
|
||||
"@octokit/request-error" "^2.1.0"
|
||||
"@octokit/types" "^6.16.1"
|
||||
is-plain-object "^5.0.0"
|
||||
node-fetch "^2.6.7"
|
||||
universal-user-agent "^6.0.0"
|
||||
|
||||
"@octokit/rest@^18":
|
||||
version "18.12.0"
|
||||
resolved "https://registry.npmmirror.com/@octokit/rest/-/rest-18.12.0.tgz#f06bc4952fc87130308d810ca9d00e79f6988881"
|
||||
integrity sha512-gDPiOHlyGavxr72y0guQEhLsemgVjwRePayJ+FcKc2SJqKUbxbkvf5kAZEWA/MKvsfYlQAMVzNJE3ezQcxMJ2Q==
|
||||
dependencies:
|
||||
"@octokit/core" "^3.5.1"
|
||||
"@octokit/plugin-paginate-rest" "^2.16.8"
|
||||
"@octokit/plugin-request-log" "^1.0.4"
|
||||
"@octokit/plugin-rest-endpoint-methods" "^5.12.0"
|
||||
|
||||
"@octokit/types@^6.0.3", "@octokit/types@^6.16.1", "@octokit/types@^6.39.0", "@octokit/types@^6.40.0":
|
||||
version "6.41.0"
|
||||
resolved "https://registry.npmmirror.com/@octokit/types/-/types-6.41.0.tgz#e58ef78d78596d2fb7df9c6259802464b5f84a04"
|
||||
integrity sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==
|
||||
dependencies:
|
||||
"@octokit/openapi-types" "^12.11.0"
|
||||
|
||||
"@rollup/pluginutils@^4.1.2", "@rollup/pluginutils@^4.2.0":
|
||||
version "4.2.1"
|
||||
resolved "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-4.2.1.tgz"
|
||||
|
@ -874,7 +975,7 @@
|
|||
|
||||
"@simonwep/pickr@~1.8.0":
|
||||
version "1.8.2"
|
||||
resolved "https://registry.npmjs.org/@simonwep/pickr/-/pickr-1.8.2.tgz"
|
||||
resolved "https://registry.jetlinks.cn/@simonwep%2fpickr/-/pickr-1.8.2.tgz#96dc86675940d7cad63d69c22083dd1cbb9797cb"
|
||||
integrity sha512-/l5w8BIkrpP6n1xsetx9MWPWlU6OblN5YgZZphxan0Tq4BByTCETL6lyIeY8lagalS2Nbt4F2W034KHLIiunKA==
|
||||
dependencies:
|
||||
core-js "^3.15.1"
|
||||
|
@ -927,6 +1028,14 @@
|
|||
resolved "https://registry.npmjs.org/@types/estree/-/estree-1.0.0.tgz"
|
||||
integrity sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ==
|
||||
|
||||
"@types/glob@*":
|
||||
version "8.1.0"
|
||||
resolved "https://registry.npmmirror.com/@types/glob/-/glob-8.1.0.tgz#b63e70155391b0584dce44e7ea25190bbc38f2fc"
|
||||
integrity sha512-IO+MJPVhoqz+28h1qLAcBEH2+xHMK6MTyHJc7MTnnYb6wsoLR29POVGJ7LycmVXIqyy/4/2ShP5sUwTXuOwb/w==
|
||||
dependencies:
|
||||
"@types/minimatch" "^5.1.2"
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/lodash-es@^4.17.6":
|
||||
version "4.17.6"
|
||||
resolved "https://registry.npmjs.org/@types/lodash-es/-/lodash-es-4.17.6.tgz"
|
||||
|
@ -944,6 +1053,11 @@
|
|||
resolved "https://registry.npmjs.org/@types/marked/-/marked-4.0.8.tgz"
|
||||
integrity sha512-HVNzMT5QlWCOdeuBsgXP8EZzKUf0+AXzN+sLmjvaB3ZlLqO+e4u0uXrdw9ub69wBKFs+c6/pA4r9sy6cCDvImw==
|
||||
|
||||
"@types/minimatch@^5.1.2":
|
||||
version "5.1.2"
|
||||
resolved "https://registry.npmmirror.com/@types/minimatch/-/minimatch-5.1.2.tgz#07508b45797cb81ec3f273011b054cd0755eddca"
|
||||
integrity sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==
|
||||
|
||||
"@types/minimist@^1.2.0":
|
||||
version "1.2.2"
|
||||
resolved "https://registry.npmmirror.com/@types/minimist/-/minimist-1.2.2.tgz"
|
||||
|
@ -966,6 +1080,14 @@
|
|||
resolved "https://registry.npmmirror.com/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz"
|
||||
integrity sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==
|
||||
|
||||
"@types/shelljs@^0.8.11":
|
||||
version "0.8.11"
|
||||
resolved "https://registry.npmmirror.com/@types/shelljs/-/shelljs-0.8.11.tgz#17a5696c825974e96828e96e89585d685646fcb8"
|
||||
integrity sha512-x9yaMvEh5BEaZKeVQC4vp3l+QoFj3BXcd4aYfuKSzIIyihjdVARAadYy3SMNIz0WCCdS2vB9JL/U6GQk5PaxQw==
|
||||
dependencies:
|
||||
"@types/glob" "*"
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/three@0.143.0":
|
||||
version "0.143.0"
|
||||
resolved "https://registry.npmjs.org/@types/three/-/three-0.143.0.tgz"
|
||||
|
@ -1072,6 +1194,16 @@
|
|||
estree-walker "^2.0.2"
|
||||
source-map "^0.6.1"
|
||||
|
||||
"@vue/compiler-core@3.2.47":
|
||||
version "3.2.47"
|
||||
resolved "https://registry.jetlinks.cn/@vue%2fcompiler-core/-/compiler-core-3.2.47.tgz#3e07c684d74897ac9aa5922c520741f3029267f8"
|
||||
integrity sha512-p4D7FDnQb7+YJmO2iPEv0SQNeNzcbHdGByJDsT4lynf63AFkOTFN07HsiRSvjGo0QrxR/o3d0hUyNCUnBU2Tig==
|
||||
dependencies:
|
||||
"@babel/parser" "^7.16.4"
|
||||
"@vue/shared" "3.2.47"
|
||||
estree-walker "^2.0.2"
|
||||
source-map "^0.6.1"
|
||||
|
||||
"@vue/compiler-dom@3.2.45", "@vue/compiler-dom@^3.2.45":
|
||||
version "3.2.45"
|
||||
resolved "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.2.45.tgz"
|
||||
|
@ -1080,6 +1212,14 @@
|
|||
"@vue/compiler-core" "3.2.45"
|
||||
"@vue/shared" "3.2.45"
|
||||
|
||||
"@vue/compiler-dom@3.2.47":
|
||||
version "3.2.47"
|
||||
resolved "https://registry.jetlinks.cn/@vue%2fcompiler-dom/-/compiler-dom-3.2.47.tgz#a0b06caf7ef7056939e563dcaa9cbde30794f305"
|
||||
integrity sha512-dBBnEHEPoftUiS03a4ggEig74J2YBZ2UIeyfpcRM2tavgMWo4bsEfgCGsu+uJIL/vax9S+JztH8NmQerUo7shQ==
|
||||
dependencies:
|
||||
"@vue/compiler-core" "3.2.47"
|
||||
"@vue/shared" "3.2.47"
|
||||
|
||||
"@vue/compiler-sfc@3.2.45", "@vue/compiler-sfc@^3.2.29", "@vue/compiler-sfc@^3.2.45":
|
||||
version "3.2.45"
|
||||
resolved "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.2.45.tgz"
|
||||
|
@ -1096,6 +1236,22 @@
|
|||
postcss "^8.1.10"
|
||||
source-map "^0.6.1"
|
||||
|
||||
"@vue/compiler-sfc@3.2.47":
|
||||
version "3.2.47"
|
||||
resolved "https://registry.jetlinks.cn/@vue%2fcompiler-sfc/-/compiler-sfc-3.2.47.tgz#1bdc36f6cdc1643f72e2c397eb1a398f5004ad3d"
|
||||
integrity sha512-rog05W+2IFfxjMcFw10tM9+f7i/+FFpZJJ5XHX72NP9eC2uRD+42M3pYcQqDXVYoj74kHMSEdQ/WmCjt8JFksQ==
|
||||
dependencies:
|
||||
"@babel/parser" "^7.16.4"
|
||||
"@vue/compiler-core" "3.2.47"
|
||||
"@vue/compiler-dom" "3.2.47"
|
||||
"@vue/compiler-ssr" "3.2.47"
|
||||
"@vue/reactivity-transform" "3.2.47"
|
||||
"@vue/shared" "3.2.47"
|
||||
estree-walker "^2.0.2"
|
||||
magic-string "^0.25.7"
|
||||
postcss "^8.1.10"
|
||||
source-map "^0.6.1"
|
||||
|
||||
"@vue/compiler-ssr@3.2.45":
|
||||
version "3.2.45"
|
||||
resolved "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.2.45.tgz"
|
||||
|
@ -1104,6 +1260,14 @@
|
|||
"@vue/compiler-dom" "3.2.45"
|
||||
"@vue/shared" "3.2.45"
|
||||
|
||||
"@vue/compiler-ssr@3.2.47":
|
||||
version "3.2.47"
|
||||
resolved "https://registry.jetlinks.cn/@vue%2fcompiler-ssr/-/compiler-ssr-3.2.47.tgz#35872c01a273aac4d6070ab9d8da918ab13057ee"
|
||||
integrity sha512-wVXC+gszhulcMD8wpxMsqSOpvDZ6xKXSVWkf50Guf/S+28hTAXPDYRTbLQ3EDkOP5Xz/+SY37YiwDquKbJOgZw==
|
||||
dependencies:
|
||||
"@vue/compiler-dom" "3.2.47"
|
||||
"@vue/shared" "3.2.47"
|
||||
|
||||
"@vue/devtools-api@^6.4.5":
|
||||
version "6.4.5"
|
||||
resolved "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.4.5.tgz"
|
||||
|
@ -1120,6 +1284,17 @@
|
|||
estree-walker "^2.0.2"
|
||||
magic-string "^0.25.7"
|
||||
|
||||
"@vue/reactivity-transform@3.2.47":
|
||||
version "3.2.47"
|
||||
resolved "https://registry.jetlinks.cn/@vue%2freactivity-transform/-/reactivity-transform-3.2.47.tgz#e45df4d06370f8abf29081a16afd25cffba6d84e"
|
||||
integrity sha512-m8lGXw8rdnPVVIdIFhf0LeQ/ixyHkH5plYuS83yop5n7ggVJU+z5v0zecwEnX7fa7HNLBhh2qngJJkxpwEEmYA==
|
||||
dependencies:
|
||||
"@babel/parser" "^7.16.4"
|
||||
"@vue/compiler-core" "3.2.47"
|
||||
"@vue/shared" "3.2.47"
|
||||
estree-walker "^2.0.2"
|
||||
magic-string "^0.25.7"
|
||||
|
||||
"@vue/reactivity@3.2.45", "@vue/reactivity@^3.2.45":
|
||||
version "3.2.45"
|
||||
resolved "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.2.45.tgz"
|
||||
|
@ -1127,6 +1302,13 @@
|
|||
dependencies:
|
||||
"@vue/shared" "3.2.45"
|
||||
|
||||
"@vue/reactivity@3.2.47":
|
||||
version "3.2.47"
|
||||
resolved "https://registry.jetlinks.cn/@vue%2freactivity/-/reactivity-3.2.47.tgz#1d6399074eadfc3ed35c727e2fd707d6881140b6"
|
||||
integrity sha512-7khqQ/75oyyg+N/e+iwV6lpy1f5wq759NdlS1fpAhFXa8VeAIKGgk2E/C4VF59lx5b+Ezs5fpp/5WsRYXQiKxQ==
|
||||
dependencies:
|
||||
"@vue/shared" "3.2.47"
|
||||
|
||||
"@vue/runtime-core@3.2.45":
|
||||
version "3.2.45"
|
||||
resolved "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.2.45.tgz"
|
||||
|
@ -1135,6 +1317,14 @@
|
|||
"@vue/reactivity" "3.2.45"
|
||||
"@vue/shared" "3.2.45"
|
||||
|
||||
"@vue/runtime-core@3.2.47":
|
||||
version "3.2.47"
|
||||
resolved "https://registry.jetlinks.cn/@vue%2fruntime-core/-/runtime-core-3.2.47.tgz#406ebade3d5551c00fc6409bbc1eeb10f32e121d"
|
||||
integrity sha512-RZxbLQIRB/K0ev0K9FXhNbBzT32H9iRtYbaXb0ZIz2usLms/D55dJR2t6cIEUn6vyhS3ALNvNthI+Q95C+NOpA==
|
||||
dependencies:
|
||||
"@vue/reactivity" "3.2.47"
|
||||
"@vue/shared" "3.2.47"
|
||||
|
||||
"@vue/runtime-dom@3.2.45":
|
||||
version "3.2.45"
|
||||
resolved "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.2.45.tgz"
|
||||
|
@ -1144,6 +1334,15 @@
|
|||
"@vue/shared" "3.2.45"
|
||||
csstype "^2.6.8"
|
||||
|
||||
"@vue/runtime-dom@3.2.47":
|
||||
version "3.2.47"
|
||||
resolved "https://registry.jetlinks.cn/@vue%2fruntime-dom/-/runtime-dom-3.2.47.tgz#93e760eeaeab84dedfb7c3eaf3ed58d776299382"
|
||||
integrity sha512-ArXrFTjS6TsDei4qwNvgrdmHtD930KgSKGhS5M+j8QxXrDJYLqYw4RRcDy1bz1m1wMmb6j+zGLifdVHtkXA7gA==
|
||||
dependencies:
|
||||
"@vue/runtime-core" "3.2.47"
|
||||
"@vue/shared" "3.2.47"
|
||||
csstype "^2.6.8"
|
||||
|
||||
"@vue/server-renderer@3.2.45":
|
||||
version "3.2.45"
|
||||
resolved "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.2.45.tgz"
|
||||
|
@ -1152,11 +1351,24 @@
|
|||
"@vue/compiler-ssr" "3.2.45"
|
||||
"@vue/shared" "3.2.45"
|
||||
|
||||
"@vue/server-renderer@3.2.47":
|
||||
version "3.2.47"
|
||||
resolved "https://registry.jetlinks.cn/@vue%2fserver-renderer/-/server-renderer-3.2.47.tgz#8aa1d1871fc4eb5a7851aa7f741f8f700e6de3c0"
|
||||
integrity sha512-dN9gc1i8EvmP9RCzvneONXsKfBRgqFeFZLurmHOveL7oH6HiFXJw5OGu294n1nHc/HMgTy6LulU/tv5/A7f/LA==
|
||||
dependencies:
|
||||
"@vue/compiler-ssr" "3.2.47"
|
||||
"@vue/shared" "3.2.47"
|
||||
|
||||
"@vue/shared@3.2.45", "@vue/shared@^3.2.45":
|
||||
version "3.2.45"
|
||||
resolved "https://registry.npmjs.org/@vue/shared/-/shared-3.2.45.tgz"
|
||||
integrity sha512-Ewzq5Yhimg7pSztDV+RH1UDKBzmtqieXQlpTVm2AwraoRL/Rks96mvd8Vgi7Lj+h+TH8dv7mXD3FRZR3TUvbSg==
|
||||
|
||||
"@vue/shared@3.2.47":
|
||||
version "3.2.47"
|
||||
resolved "https://registry.jetlinks.cn/@vue%2fshared/-/shared-3.2.47.tgz#e597ef75086c6e896ff5478a6bfc0a7aa4bbd14c"
|
||||
integrity sha512-BHGyyGN3Q97EZx0taMQ+OLNuZcW3d37ZEVmEAyeoA9ERdGvm9Irc/0Fua8SNyOtV1w6BS4q25wbMzJujO9HIfQ==
|
||||
|
||||
"@vuemap/layer-3dtiles@^0.0.3":
|
||||
version "0.0.3"
|
||||
resolved "https://registry.npmjs.org/@vuemap/layer-3dtiles/-/layer-3dtiles-0.0.3.tgz"
|
||||
|
@ -1187,13 +1399,13 @@
|
|||
|
||||
"@vueuse/core@^7.5.5":
|
||||
version "7.7.1"
|
||||
resolved "https://registry.jetlinks.cn/@vueuse%2fcore/-/core-7.7.1.tgz"
|
||||
resolved "https://registry.jetlinks.cn/@vueuse%2fcore/-/core-7.7.1.tgz#fc284f4103de73c7fb79bc06579d8066790db511"
|
||||
integrity sha512-PRRgbATMpoeUmkCEBtUeJgOwtew8s+4UsEd+Pm7MhkjL2ihCNrSqxNVtM6NFE4uP2sWnkGcZpCjPuNSxowJ1Ow==
|
||||
dependencies:
|
||||
"@vueuse/shared" "7.7.1"
|
||||
vue-demi "*"
|
||||
|
||||
"@vueuse/core@^9.10.0", "@vueuse/core@^9.12.0":
|
||||
"@vueuse/core@^9.10.0":
|
||||
version "9.12.0"
|
||||
resolved "https://registry.npmmirror.com/@vueuse/core/-/core-9.12.0.tgz"
|
||||
integrity sha512-h/Di8Bvf6xRcvS/PvUVheiMYYz3U0tH3X25YxONSaAUBa841ayMwxkuzx/DGUMCW/wHWzD8tRy2zYmOC36r4sg==
|
||||
|
@ -1203,14 +1415,29 @@
|
|||
"@vueuse/shared" "9.12.0"
|
||||
vue-demi "*"
|
||||
|
||||
"@vueuse/core@^9.12.0":
|
||||
version "9.13.0"
|
||||
resolved "https://registry.jetlinks.cn/@vueuse%2fcore/-/core-9.13.0.tgz#2f69e66d1905c1e4eebc249a01759cf88ea00cf4"
|
||||
integrity sha512-pujnclbeHWxxPRqXWmdkKV5OX4Wk4YeK7wusHqRwU0Q7EFusHoqNA/aPhB6KCh9hEqJkLAJo7bb0Lh9b+OIVzw==
|
||||
dependencies:
|
||||
"@types/web-bluetooth" "^0.0.16"
|
||||
"@vueuse/metadata" "9.13.0"
|
||||
"@vueuse/shared" "9.13.0"
|
||||
vue-demi "*"
|
||||
|
||||
"@vueuse/metadata@9.12.0":
|
||||
version "9.12.0"
|
||||
resolved "https://registry.npmmirror.com/@vueuse/metadata/-/metadata-9.12.0.tgz"
|
||||
integrity sha512-9oJ9MM9lFLlmvxXUqsR1wLt1uF7EVbP5iYaHJYqk+G2PbMjY6EXvZeTjbdO89HgoF5cI6z49o2zT/jD9SVoNpQ==
|
||||
|
||||
"@vueuse/metadata@9.13.0":
|
||||
version "9.13.0"
|
||||
resolved "https://registry.jetlinks.cn/@vueuse%2fmetadata/-/metadata-9.13.0.tgz#bc25a6cdad1b1a93c36ce30191124da6520539ff"
|
||||
integrity sha512-gdU7TKNAUVlXXLbaF+ZCfte8BjRJQWPCa2J55+7/h+yDtzw3vOoGQDRXzI6pyKyo6bXFT5/QoPE4hAknExjRLQ==
|
||||
|
||||
"@vueuse/shared@7.7.1":
|
||||
version "7.7.1"
|
||||
resolved "https://registry.jetlinks.cn/@vueuse%2fshared/-/shared-7.7.1.tgz"
|
||||
resolved "https://registry.jetlinks.cn/@vueuse%2fshared/-/shared-7.7.1.tgz#77e312de7275380efce86b0079bd7938791a076b"
|
||||
integrity sha512-rN2qd22AUl7VdBxihagWyhUNHCyVk9IpvBTTfHoLH9G7rGE552X1f+zeCfehuno0zXif13jPw+icW/wn2a0rnQ==
|
||||
dependencies:
|
||||
vue-demi "*"
|
||||
|
@ -1222,6 +1449,13 @@
|
|||
dependencies:
|
||||
vue-demi "*"
|
||||
|
||||
"@vueuse/shared@9.13.0":
|
||||
version "9.13.0"
|
||||
resolved "https://registry.jetlinks.cn/@vueuse%2fshared/-/shared-9.13.0.tgz#089ff4cc4e2e7a4015e57a8f32e4b39d096353b9"
|
||||
integrity sha512-UrnhU+Cnufu4S6JLCPZnkWh0WwZGUp72ktOF2DFptMlOs3TOdVv8xJN53zhHGARmVOsz5KqOls09+J1NR6sBKw==
|
||||
dependencies:
|
||||
vue-demi "*"
|
||||
|
||||
JSONStream@^1.0.4:
|
||||
version "1.3.5"
|
||||
resolved "https://registry.npmmirror.com/JSONStream/-/JSONStream-1.3.5.tgz"
|
||||
|
@ -1371,7 +1605,7 @@ ansistyles@~0.1.3:
|
|||
|
||||
ant-design-vue@^3.2.15:
|
||||
version "3.2.15"
|
||||
resolved "https://registry.npmjs.org/ant-design-vue/-/ant-design-vue-3.2.15.tgz"
|
||||
resolved "https://registry.jetlinks.cn/ant-design-vue/-/ant-design-vue-3.2.15.tgz#eab52877fa08a9e4c8cb311ea479a90203dcb302"
|
||||
integrity sha512-sJfE7LWimSdAPe4dzNyQBrmVMnOTNQTkG9oOyr+7W8qIYrX8sYWyC68Nn1uum4KBJUSZUa/BU6dohvTG0urBhA==
|
||||
dependencies:
|
||||
"@ant-design/colors" "^6.0.0"
|
||||
|
@ -1448,7 +1682,7 @@ array-ify@^1.0.0:
|
|||
|
||||
array-tree-filter@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.npmjs.org/array-tree-filter/-/array-tree-filter-2.1.0.tgz"
|
||||
resolved "https://registry.jetlinks.cn/array-tree-filter/-/array-tree-filter-2.1.0.tgz#873ac00fec83749f255ac8dd083814b4f6329190"
|
||||
integrity sha512-4ROwICNlNw/Hqa9v+rk5h22KjmzB1JGTMVKP2AKJBOCgb0yL0ASf0+YvCcLNNwquOHNX48jkeZIJ3a+oOQqKcw==
|
||||
|
||||
arrify@^1.0.1:
|
||||
|
@ -1480,7 +1714,7 @@ astral-regex@^2.0.0:
|
|||
|
||||
async-validator@^4.0.0:
|
||||
version "4.2.5"
|
||||
resolved "https://registry.npmjs.org/async-validator/-/async-validator-4.2.5.tgz"
|
||||
resolved "https://registry.jetlinks.cn/async-validator/-/async-validator-4.2.5.tgz#c96ea3332a521699d0afaaceed510a54656c6339"
|
||||
integrity sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg==
|
||||
|
||||
async@^1.5.2:
|
||||
|
@ -1550,6 +1784,11 @@ bcrypt-pbkdf@^1.0.0:
|
|||
dependencies:
|
||||
tweetnacl "^0.14.3"
|
||||
|
||||
before-after-hook@^2.2.0:
|
||||
version "2.2.3"
|
||||
resolved "https://registry.npmmirror.com/before-after-hook/-/before-after-hook-2.2.3.tgz#c51e809c81a4e354084422b9b26bad88249c517c"
|
||||
integrity sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==
|
||||
|
||||
bin-links@^2.2.1:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.jetlinks.cn/bin-links/-/bin-links-2.3.0.tgz#1ff241c86d2c29b24ae52f49544db5d78a4eb967"
|
||||
|
@ -1774,7 +2013,7 @@ chalk@^3.0.0:
|
|||
|
||||
chalk@^4.0.0, chalk@^4.0.2, chalk@^4.1.0, chalk@^4.1.2:
|
||||
version "4.1.2"
|
||||
resolved "https://registry.jetlinks.cn/chalk/-/chalk-4.1.2.tgz"
|
||||
resolved "https://registry.jetlinks.cn/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01"
|
||||
integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==
|
||||
dependencies:
|
||||
ansi-styles "^4.1.0"
|
||||
|
@ -2010,7 +2249,7 @@ colorette@^2.0.16, colorette@^2.0.19:
|
|||
|
||||
colorpicker-v3@^2.10.2:
|
||||
version "2.10.2"
|
||||
resolved "https://registry.jetlinks.cn/colorpicker-v3/-/colorpicker-v3-2.10.2.tgz"
|
||||
resolved "https://registry.jetlinks.cn/colorpicker-v3/-/colorpicker-v3-2.10.2.tgz#f5e2f9ea603eee4d227ba10fa436d86963aa2bd0"
|
||||
integrity sha512-ZWPq5wcugS3NcL7DwYqVSP5mE/x45FK31olGpig+Tko5jUXk0danfEYi1Aei3lgYs+Z0zAfhbhqVuDgOdUs5Mw==
|
||||
dependencies:
|
||||
"@vueuse/core" "^7.5.5"
|
||||
|
@ -2033,7 +2272,7 @@ combined-stream@^1.0.6, combined-stream@^1.0.8, combined-stream@~1.0.6:
|
|||
|
||||
commander@^2.19.0, commander@^2.20.0, commander@^2.9.0:
|
||||
version "2.20.3"
|
||||
resolved "https://registry.jetlinks.cn/commander/-/commander-2.20.3.tgz"
|
||||
resolved "https://registry.npmmirror.com/commander/-/commander-2.20.3.tgz"
|
||||
integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==
|
||||
|
||||
commander@^8.3.0:
|
||||
|
@ -2041,7 +2280,7 @@ commander@^8.3.0:
|
|||
resolved "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz"
|
||||
integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==
|
||||
|
||||
commander@^9.4.1:
|
||||
commander@^9, commander@^9.4.1:
|
||||
version "9.5.0"
|
||||
resolved "https://registry.npmmirror.com/commander/-/commander-9.5.0.tgz"
|
||||
integrity sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==
|
||||
|
@ -2079,7 +2318,7 @@ compare-func@^2.0.0:
|
|||
|
||||
compute-scroll-into-view@^1.0.20:
|
||||
version "1.0.20"
|
||||
resolved "https://registry.npmjs.org/compute-scroll-into-view/-/compute-scroll-into-view-1.0.20.tgz"
|
||||
resolved "https://registry.jetlinks.cn/compute-scroll-into-view/-/compute-scroll-into-view-1.0.20.tgz#1768b5522d1172754f5d0c9b02de3af6be506a43"
|
||||
integrity sha512-UCB0ioiyj8CRjtrvaceBLqqhZCVP+1B8+NWQhmdsm0VXOJtobBCf1dBQmebCCo34qZmUwZfIH2MZLqNHazrfjg==
|
||||
|
||||
concat-map@0.0.1:
|
||||
|
@ -2182,9 +2421,9 @@ copy-anything@^2.0.1:
|
|||
is-what "^3.14.1"
|
||||
|
||||
core-js@^3.15.1:
|
||||
version "3.27.0"
|
||||
resolved "https://registry.npmjs.org/core-js/-/core-js-3.27.0.tgz"
|
||||
integrity sha512-wY6cKosevs430KRkHUIsvepDXHGjlXOZO3hYXNyqpD6JvB0X28aXyv0t1Y1vZMwE7SoKmtfa6IASHCPN52FwBQ==
|
||||
version "3.29.0"
|
||||
resolved "https://registry.jetlinks.cn/core-js/-/core-js-3.29.0.tgz#0273e142b67761058bcde5615c503c7406b572d6"
|
||||
integrity sha512-VG23vuEisJNkGl6XQmFJd3rEG/so/CNatqeE+7uZAwTSwFeB/qaO0be8xZYUNWprJ/GIwL8aMt9cj1kvbpTZhg==
|
||||
|
||||
core-util-is@1.0.2:
|
||||
version "1.0.2"
|
||||
|
@ -2286,7 +2525,7 @@ dashdash@^1.12.0:
|
|||
|
||||
dayjs@^1.10.5:
|
||||
version "1.11.7"
|
||||
resolved "https://registry.npmjs.org/dayjs/-/dayjs-1.11.7.tgz"
|
||||
resolved "https://registry.jetlinks.cn/dayjs/-/dayjs-1.11.7.tgz#4b296922642f70999544d1144a2c25730fce63e2"
|
||||
integrity sha512-+Yw9U6YO5TQohxLcIkrXBeY73WP3ejHWVvx8XCk3gxvQDCTEmS48ZrSZCKciI7Bhl/uCMyxYtE9UqRILmFphkQ==
|
||||
|
||||
de-indent@^1.0.2:
|
||||
|
@ -2375,6 +2614,11 @@ depd@^1.1.2:
|
|||
resolved "https://registry.jetlinks.cn/depd/-/depd-1.1.2.tgz"
|
||||
integrity sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==
|
||||
|
||||
deprecation@^2.0.0, deprecation@^2.3.1:
|
||||
version "2.3.1"
|
||||
resolved "https://registry.npmmirror.com/deprecation/-/deprecation-2.3.1.tgz#6368cbdb40abf3373b525ac87e4a260c3a700919"
|
||||
integrity sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==
|
||||
|
||||
detect-indent@^6.0.0:
|
||||
version "6.1.0"
|
||||
resolved "https://registry.npmmirror.com/detect-indent/-/detect-indent-6.1.0.tgz"
|
||||
|
@ -2400,12 +2644,12 @@ diff@^5.0.0:
|
|||
|
||||
dom-align@^1.12.1:
|
||||
version "1.12.4"
|
||||
resolved "https://registry.npmjs.org/dom-align/-/dom-align-1.12.4.tgz"
|
||||
resolved "https://registry.jetlinks.cn/dom-align/-/dom-align-1.12.4.tgz#3503992eb2a7cfcb2ed3b2a6d21e0b9c00d54511"
|
||||
integrity sha512-R8LUSEay/68zE5c8/3BDxiTEvgb4xZTF0RKmAHfiEVN3klfIpXfi2/QCoiWPccVQ0J/ZGdz9OjzL4uJEP/MRAw==
|
||||
|
||||
dom-scroll-into-view@^2.0.0:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.npmjs.org/dom-scroll-into-view/-/dom-scroll-into-view-2.0.1.tgz"
|
||||
resolved "https://registry.jetlinks.cn/dom-scroll-into-view/-/dom-scroll-into-view-2.0.1.tgz#0decc8522801fd8d3f1c6ba355a74d382c5f989b"
|
||||
integrity sha512-bvVTQe1lfaUr1oFzZX80ce9KLDlZ3iU+XGNE/bz9HnGdklTieqsbmsLHe+rT2XWqopvL0PckkYqN7ksmm5pe3w==
|
||||
|
||||
dom-serializer@^1.0.1:
|
||||
|
@ -2644,6 +2888,11 @@ escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5:
|
|||
resolved "https://registry.npmmirror.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz"
|
||||
integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==
|
||||
|
||||
escape-string-regexp@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.npmmirror.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34"
|
||||
integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==
|
||||
|
||||
escape-string-regexp@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz"
|
||||
|
@ -3007,7 +3256,7 @@ glob-parent@^5.1.2, glob-parent@~5.1.2:
|
|||
dependencies:
|
||||
is-glob "^4.0.1"
|
||||
|
||||
glob@^7.1.1, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6, glob@^7.2.0:
|
||||
glob@^7.0.0, glob@^7.1.1, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6, glob@^7.2.0:
|
||||
version "7.2.3"
|
||||
resolved "https://registry.npmmirror.com/glob/-/glob-7.2.3.tgz"
|
||||
integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==
|
||||
|
@ -3386,6 +3635,11 @@ inquirer@^7.0.4:
|
|||
strip-ansi "^6.0.0"
|
||||
through "^2.3.6"
|
||||
|
||||
interpret@^1.0.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.npmmirror.com/interpret/-/interpret-1.4.0.tgz#665ab8bc4da27a774a40584e812e3e0fa45b1a1e"
|
||||
integrity sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==
|
||||
|
||||
ip-regex@^4.1.0:
|
||||
version "4.3.0"
|
||||
resolved "https://registry.jetlinks.cn/ip-regex/-/ip-regex-4.3.0.tgz#687275ab0f57fa76978ff8f4dddc8a23d5990db5"
|
||||
|
@ -3555,9 +3809,14 @@ is-plain-obj@^1.1.0:
|
|||
|
||||
is-plain-object@3.0.1:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.npmjs.org/is-plain-object/-/is-plain-object-3.0.1.tgz"
|
||||
resolved "https://registry.jetlinks.cn/is-plain-object/-/is-plain-object-3.0.1.tgz#662d92d24c0aa4302407b0d45d21f2251c85f85b"
|
||||
integrity sha512-Xnpx182SBMrr/aBik8y+GuR4U1L9FqMSojwDQwPMmxyC6bvEqly9UBCxhauBF5vNh2gwWJNX6oDV7O+OM4z34g==
|
||||
|
||||
is-plain-object@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.npmmirror.com/is-plain-object/-/is-plain-object-5.0.0.tgz#4427f50ab3429e9025ea7d52e9043a9ef4159344"
|
||||
integrity sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==
|
||||
|
||||
is-redirect@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.npmmirror.com/is-redirect/-/is-redirect-1.0.0.tgz"
|
||||
|
@ -3642,10 +3901,10 @@ 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.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.jetlinks.cn/jetlinks-ui-components/-/jetlinks-ui-components-1.0.1.tgz#12fe9a193af14b859e1baf02fbd706a2be5b31cf"
|
||||
integrity sha512-4hdEJUaKNMSIcmbn4qKcG8oK7h6VSYP3X3fCNndBm6WhHh+9ONf8f+3OSrUy1PvxdenmqO0VN2QdWV0KupByKQ==
|
||||
jetlinks-ui-components@^1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.jetlinks.cn/jetlinks-ui-components/-/jetlinks-ui-components-1.0.3.tgz#303ca83cf6096721e49e72d1a3a73b054b0aa7fa"
|
||||
integrity sha512-Jm7tP/CtnK2GIRSPTjd/UOw8emZ3C7/i9af8m+XCM8wi/J1SZh4cZGc487vR1DPxyWZfJjG87Zdy45DZ5EMw2w==
|
||||
dependencies:
|
||||
"@vueuse/core" "^9.12.0"
|
||||
ant-design-vue "^3.2.15"
|
||||
|
@ -4119,7 +4378,7 @@ longest@^2.0.1:
|
|||
|
||||
loose-envify@^1.0.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz"
|
||||
resolved "https://registry.jetlinks.cn/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
|
||||
integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==
|
||||
dependencies:
|
||||
js-tokens "^3.0.0 || ^4.0.0"
|
||||
|
@ -4315,6 +4574,13 @@ marked@^4.2.12:
|
|||
resolved "https://registry.npmjs.org/marked/-/marked-4.2.12.tgz"
|
||||
integrity sha512-yr8hSKa3Fv4D3jdZmtMMPghgVt6TWbk86WQaWhDloQjRSQhMMYCAro7jP7VDJrjjdV8pxVxMssXS8B8Y5DZ5aw==
|
||||
|
||||
matcher@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.npmmirror.com/matcher/-/matcher-4.0.0.tgz#a42a05a09aaed92e2d241eb91fddac689461ea51"
|
||||
integrity sha512-S6x5wmcDmsDRRU/c2dkccDwQPXoFczc5+HpQ2lON8pnvHlnvHAHj5WlLVvw6n6vNyHuVugYrFohYxbS+pvFpKQ==
|
||||
dependencies:
|
||||
escape-string-regexp "^4.0.0"
|
||||
|
||||
mdurl@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.npmmirror.com/mdurl/-/mdurl-1.0.1.tgz"
|
||||
|
@ -4532,13 +4798,17 @@ moment@*, moment@^2.29.4:
|
|||
|
||||
monaco-editor@^0.35.0:
|
||||
version "0.35.0"
|
||||
resolved "https://registry.jetlinks.cn/monaco-editor/-/monaco-editor-0.35.0.tgz"
|
||||
resolved "https://registry.jetlinks.cn/monaco-editor/-/monaco-editor-0.35.0.tgz#49c4220c815262a900dacf0ae8a59bef66efab8b"
|
||||
integrity sha512-BJfkAZ0EJ7JgrgWzqjfBNP9hPSS8NlfECEDMEIIiozV2UaPq22yeuOjgbd3TwMh3anH0krWZirXZfn8KUSxiOA==
|
||||
|
||||
monaco-editor@^0.36.0:
|
||||
version "0.36.1"
|
||||
resolved "https://registry.jetlinks.cn/monaco-editor/-/monaco-editor-0.36.1.tgz"
|
||||
integrity sha512-/CaclMHKQ3A6rnzBzOADfwdSJ25BFoFT0Emxsc4zYVyav5SkK9iA6lEtIeuN/oRYbwPgviJT+t3l+sjFa28jYg==
|
||||
version "0.36.0"
|
||||
resolved "https://registry.npmmirror.com/monaco-editor/-/monaco-editor-0.36.0.tgz#8e7dba92f8110b369fdbc2312366184216419fc7"
|
||||
integrity sha512-1Pn3AatfK88flUigyBozA4mt8+SB5xlgloQDu1RqivARw9yKaml/jceIvndae7Z2Nq8T7xZccFlmH+n6rkFg6g==
|
||||
dependencies:
|
||||
"@types/shelljs" "^0.8.11"
|
||||
pin-github-action "^1.8.0"
|
||||
shelljs "^0.8.5"
|
||||
|
||||
mrm-core@^7.1.13:
|
||||
version "7.1.13"
|
||||
|
@ -4616,7 +4886,7 @@ nanoid@^3.3.4:
|
|||
|
||||
nanopop@^2.1.0:
|
||||
version "2.2.0"
|
||||
resolved "https://registry.npmjs.org/nanopop/-/nanopop-2.2.0.tgz"
|
||||
resolved "https://registry.jetlinks.cn/nanopop/-/nanopop-2.2.0.tgz#bd1c25588a7beaf68865bc2df19db4c58c77dcc9"
|
||||
integrity sha512-E9JaHcxh3ere8/BEZHAcnuD10RluTSPyTToBvoFWS9/7DcCx6gyKjbn7M7Bx7E1veCxCuY1iO6h4+gdAf1j73Q==
|
||||
|
||||
needle@^3.1.0:
|
||||
|
@ -4641,6 +4911,13 @@ no-case@^3.0.4:
|
|||
lower-case "^2.0.2"
|
||||
tslib "^2.0.3"
|
||||
|
||||
node-fetch@^2.6.7:
|
||||
version "2.6.9"
|
||||
resolved "https://registry.npmmirror.com/node-fetch/-/node-fetch-2.6.9.tgz#7c7f744b5cc6eb5fd404e0c7a9fec630a55657e6"
|
||||
integrity sha512-DJm/CJkZkRjKKj4Zi4BsKVZh3ValV5IR5s7LVZnW+6YMh0W1BfNA8XSs6DLMGYlId5F3KnA70uu2qepcR08Qqg==
|
||||
dependencies:
|
||||
whatwg-url "^5.0.0"
|
||||
|
||||
node-gyp@^7.1.0, node-gyp@^7.1.2:
|
||||
version "7.1.2"
|
||||
resolved "https://registry.jetlinks.cn/node-gyp/-/node-gyp-7.1.2.tgz"
|
||||
|
@ -5280,6 +5557,17 @@ pify@^4.0.1:
|
|||
resolved "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz"
|
||||
integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==
|
||||
|
||||
pin-github-action@^1.8.0:
|
||||
version "1.8.0"
|
||||
resolved "https://registry.npmmirror.com/pin-github-action/-/pin-github-action-1.8.0.tgz#50f0833e6af5bbba2bbfc978ca5e498b5670b9d8"
|
||||
integrity sha512-8QMKGbDUmMLFSyeV7hDIVmlI8B3ThJed1uFYuhcCBLi/w8xHPbrPhnCvJndYdugNc8aj1FrijrOMDLQ93ATc7A==
|
||||
dependencies:
|
||||
"@octokit/rest" "^18"
|
||||
commander "^9"
|
||||
debug "^4.3.4"
|
||||
matcher "^4.0.0"
|
||||
yaml "^2.1.3"
|
||||
|
||||
pinia@^2.0.28:
|
||||
version "2.0.28"
|
||||
resolved "https://registry.npmjs.org/pinia/-/pinia-2.0.28.tgz"
|
||||
|
@ -5548,6 +5836,13 @@ readme-badger@^0.3.0:
|
|||
dependencies:
|
||||
balanced-match "^1.0.0"
|
||||
|
||||
rechoir@^0.6.2:
|
||||
version "0.6.2"
|
||||
resolved "https://registry.npmmirror.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384"
|
||||
integrity sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==
|
||||
dependencies:
|
||||
resolve "^1.1.6"
|
||||
|
||||
redent@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.npmmirror.com/redent/-/redent-3.0.0.tgz"
|
||||
|
@ -5558,7 +5853,7 @@ redent@^3.0.0:
|
|||
|
||||
regenerator-runtime@^0.13.11:
|
||||
version "0.13.11"
|
||||
resolved "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz"
|
||||
resolved "https://registry.jetlinks.cn/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz#f6dca3e7ceec20590d07ada785636a90cdca17f9"
|
||||
integrity sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==
|
||||
|
||||
registry-auth-token@^3.0.1:
|
||||
|
@ -5650,7 +5945,7 @@ require-main-filename@^2.0.0:
|
|||
|
||||
resize-observer-polyfill@^1.5.1:
|
||||
version "1.5.1"
|
||||
resolved "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz"
|
||||
resolved "https://registry.jetlinks.cn/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz#0e9020dd3d21024458d4ebd27e23e40269810464"
|
||||
integrity sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==
|
||||
|
||||
resolve-from@5.0.0, resolve-from@^5.0.0:
|
||||
|
@ -5670,7 +5965,7 @@ resolve-global@1.0.0, resolve-global@^1.0.0:
|
|||
dependencies:
|
||||
global-dirs "^0.1.1"
|
||||
|
||||
resolve@^1.10.0, resolve@^1.22.1:
|
||||
resolve@^1.1.6, resolve@^1.10.0, resolve@^1.22.1:
|
||||
version "1.22.1"
|
||||
resolved "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz"
|
||||
integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==
|
||||
|
@ -5778,7 +6073,7 @@ sax@^1.2.4:
|
|||
|
||||
scroll-into-view-if-needed@^2.2.25:
|
||||
version "2.2.31"
|
||||
resolved "https://registry.npmjs.org/scroll-into-view-if-needed/-/scroll-into-view-if-needed-2.2.31.tgz"
|
||||
resolved "https://registry.jetlinks.cn/scroll-into-view-if-needed/-/scroll-into-view-if-needed-2.2.31.tgz#d3c482959dc483e37962d1521254e3295d0d1587"
|
||||
integrity sha512-dGCXy99wZQivjmjIqihaBQNjryrz5rueJY7eHfTdyWEiR4ttYpsajb14rn9s5d4DY4EcY6+4+U/maARBXJedkA==
|
||||
dependencies:
|
||||
compute-scroll-into-view "^1.0.20"
|
||||
|
@ -5845,7 +6140,7 @@ set-blocking@^2.0.0, set-blocking@~2.0.0:
|
|||
|
||||
shallow-equal@^1.0.0:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.npmjs.org/shallow-equal/-/shallow-equal-1.2.1.tgz"
|
||||
resolved "https://registry.jetlinks.cn/shallow-equal/-/shallow-equal-1.2.1.tgz#4c16abfa56043aa20d050324efa68940b0da79da"
|
||||
integrity sha512-S4vJDjHHMBaiZuT9NPb616CSmLf618jawtv3sufLl6ivK8WocjAo58cXwbRV1cgqxH0Qbv+iUt6m05eqEa2IRA==
|
||||
|
||||
shebang-command@^1.2.0:
|
||||
|
@ -5872,6 +6167,15 @@ shebang-regex@^3.0.0:
|
|||
resolved "https://registry.npmmirror.com/shebang-regex/-/shebang-regex-3.0.0.tgz"
|
||||
integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==
|
||||
|
||||
shelljs@^0.8.5:
|
||||
version "0.8.5"
|
||||
resolved "https://registry.npmmirror.com/shelljs/-/shelljs-0.8.5.tgz#de055408d8361bed66c669d2f000538ced8ee20c"
|
||||
integrity sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==
|
||||
dependencies:
|
||||
glob "^7.0.0"
|
||||
interpret "^1.0.0"
|
||||
rechoir "^0.6.2"
|
||||
|
||||
sigmund@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.npmmirror.com/sigmund/-/sigmund-1.0.1.tgz"
|
||||
|
@ -6319,6 +6623,11 @@ tough-cookie@~2.5.0:
|
|||
psl "^1.1.28"
|
||||
punycode "^2.1.1"
|
||||
|
||||
tr46@~0.0.3:
|
||||
version "0.0.3"
|
||||
resolved "https://registry.npmmirror.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a"
|
||||
integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==
|
||||
|
||||
treeverse@^1.0.4:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.jetlinks.cn/treeverse/-/treeverse-1.0.4.tgz#a6b0ebf98a1bca6846ddc7ecbc900df08cb9cd5f"
|
||||
|
@ -6474,6 +6783,11 @@ unique-string@^2.0.0:
|
|||
dependencies:
|
||||
crypto-random-string "^2.0.0"
|
||||
|
||||
universal-user-agent@^6.0.0:
|
||||
version "6.0.0"
|
||||
resolved "https://registry.npmmirror.com/universal-user-agent/-/universal-user-agent-6.0.0.tgz#3381f8503b251c0d9cd21bc1de939ec9df5480ee"
|
||||
integrity sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==
|
||||
|
||||
universalify@^0.1.0:
|
||||
version "0.1.2"
|
||||
resolved "https://registry.npmmirror.com/universalify/-/universalify-0.1.2.tgz"
|
||||
|
@ -6628,7 +6942,7 @@ user-meta@^1.0.0:
|
|||
|
||||
util-deprecate@^1.0.1, util-deprecate@~1.0.1:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.jetlinks.cn/util-deprecate/-/util-deprecate-1.0.2.tgz"
|
||||
resolved "https://registry.jetlinks.cn/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
|
||||
integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==
|
||||
|
||||
uuid@^3.3.2:
|
||||
|
@ -6695,7 +7009,7 @@ vite-plugin-html@^3.2.0:
|
|||
|
||||
vite-plugin-monaco-editor@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.jetlinks.cn/vite-plugin-monaco-editor/-/vite-plugin-monaco-editor-1.1.0.tgz"
|
||||
resolved "https://registry.jetlinks.cn/vite-plugin-monaco-editor/-/vite-plugin-monaco-editor-1.1.0.tgz#a6238c2e13d5e98dd54a1bc51f6f189325219de3"
|
||||
integrity sha512-IvtUqZotrRoVqwT0PBBDIZPNraya3BxN/bfcNfnxZ5rkJiGcNtO5eAOWWSgT7zullIAEqQwxMU83yL9J5k7gww==
|
||||
|
||||
vite-plugin-style-import@^2.0.0:
|
||||
|
@ -6768,7 +7082,7 @@ vue-tsc@^1.0.11:
|
|||
|
||||
vue-types@^3.0.0:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.npmjs.org/vue-types/-/vue-types-3.0.2.tgz"
|
||||
resolved "https://registry.jetlinks.cn/vue-types/-/vue-types-3.0.2.tgz#ec16e05d412c038262fc1efa4ceb9647e7fb601d"
|
||||
integrity sha512-IwUC0Aq2zwaXqy74h4WCvFCUtoV0iSWr0snWnE9TnU18S66GAQyqQbRf2qfJtUuiFsBf6qp0MEwdonlwznlcrw==
|
||||
dependencies:
|
||||
is-plain-object "3.0.1"
|
||||
|
@ -6845,7 +7159,7 @@ walk-up-path@^1.0.0:
|
|||
|
||||
warning@^4.0.0:
|
||||
version "4.0.3"
|
||||
resolved "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz"
|
||||
resolved "https://registry.jetlinks.cn/warning/-/warning-4.0.3.tgz#16e9e077eb8a86d6af7d64aa1e05fd85b4678ca3"
|
||||
integrity sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==
|
||||
dependencies:
|
||||
loose-envify "^1.0.0"
|
||||
|
@ -6857,6 +7171,11 @@ wcwidth@^1.0.0:
|
|||
dependencies:
|
||||
defaults "^1.0.3"
|
||||
|
||||
webidl-conversions@^3.0.0:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.npmmirror.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871"
|
||||
integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==
|
||||
|
||||
webpack-merge@^4.2.2:
|
||||
version "4.2.2"
|
||||
resolved "https://registry.npmmirror.com/webpack-merge/-/webpack-merge-4.2.2.tgz"
|
||||
|
@ -6874,6 +7193,14 @@ webpack-virtual-modules@^0.5.0:
|
|||
resolved "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.5.0.tgz"
|
||||
integrity sha512-kyDivFZ7ZM0BVOUteVbDFhlRt7Ah/CSPwJdi8hBpkK7QLumUqdLtVfm/PX/hkcnrvr0i77fO5+TjZ94Pe+C9iw==
|
||||
|
||||
whatwg-url@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.npmmirror.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d"
|
||||
integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==
|
||||
dependencies:
|
||||
tr46 "~0.0.3"
|
||||
webidl-conversions "^3.0.0"
|
||||
|
||||
which-module@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.npmmirror.com/which-module/-/which-module-2.0.0.tgz"
|
||||
|
|
Loading…
Reference in New Issue