update: 首页-设备接入视图组件替换、弹窗优化
This commit is contained in:
parent
418c0e823e
commit
57e481d949
|
@ -26,7 +26,6 @@ import { useMenuStore } from '@/store/menu';
|
|||
|
||||
const { jumpPage } = useMenuStore();
|
||||
|
||||
const router = useRouter();
|
||||
const props = defineProps({
|
||||
cardData: Array<bootConfig>,
|
||||
cardTitle: String,
|
||||
|
|
|
@ -74,7 +74,7 @@ const deviceStepDetails: recommendList[] = [
|
|||
details:
|
||||
'产品是设备的集合,通常指一组具有相同功能的设备。物联设备必须通过产品进行接入方式配置。',
|
||||
iconUrl: '/images/home/bottom-4.png',
|
||||
linkUrl: 'iot/device/Product',
|
||||
linkUrl: 'device/Product',
|
||||
auth: productPermission('add'),
|
||||
params: {
|
||||
type: 'add',
|
||||
|
@ -85,7 +85,7 @@ const deviceStepDetails: recommendList[] = [
|
|||
details:
|
||||
'通过产品对同一类型的设备进行统一的接入方式配置。请参照设备铭牌说明选择匹配的接入方式。',
|
||||
iconUrl: '/images/home/bottom-1.png',
|
||||
linkUrl: 'iot/device/Product/detail',
|
||||
linkUrl: 'device/Product/Detail',
|
||||
auth: productPermission('update'),
|
||||
dialogTag: 'accessMethod',
|
||||
},
|
||||
|
@ -93,7 +93,7 @@ const deviceStepDetails: recommendList[] = [
|
|||
title: '添加测试设备',
|
||||
details: '添加单个设备,用于验证产品模型是否配置正确。',
|
||||
iconUrl: '/images/home/bottom-5.png',
|
||||
linkUrl: 'iot/device/Instance',
|
||||
linkUrl: 'device/Instance',
|
||||
auth: devicePermission('add'),
|
||||
params: {
|
||||
type: 'add',
|
||||
|
@ -104,8 +104,7 @@ const deviceStepDetails: recommendList[] = [
|
|||
details:
|
||||
'对添加的测试设备进行功能调试,验证能否连接到平台,设备功能是否配置正确。',
|
||||
iconUrl: '/images/home/bottom-2.png',
|
||||
linkUrl: 'iot/device/Instance/detail',
|
||||
// auth: devicePermission('update'),
|
||||
linkUrl: 'device/Instance/Detail',
|
||||
auth: true,
|
||||
dialogTag: 'funcTest',
|
||||
},
|
||||
|
@ -113,7 +112,7 @@ const deviceStepDetails: recommendList[] = [
|
|||
title: '批量添加设备',
|
||||
details: '批量添加同一产品下的设备',
|
||||
iconUrl: '/images/home/bottom-3.png',
|
||||
linkUrl: 'iot/device/Instance',
|
||||
linkUrl: 'device/Instance',
|
||||
auth: devicePermission('import'),
|
||||
params: {
|
||||
import: true,
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
<template>
|
||||
<a-card class="step-container">
|
||||
<dic class="step-container">
|
||||
<h5 class="title">
|
||||
<span style="margin-right: 12px">{{ cardTitle }}</span>
|
||||
<a-tooltip placement="top">
|
||||
<span style="margin-right: 12px">{{ props.cardTitle }}</span>
|
||||
<j-tooltip placement="top">
|
||||
<template #title>
|
||||
<span>{{ tooltip }}</span>
|
||||
<span>{{ props.tooltip }}</span>
|
||||
</template>
|
||||
<question-circle-outlined style="padding-top: 5px" />
|
||||
</a-tooltip>
|
||||
<AIcon type="QuestionCircleOutlined" style="padding-top: 5px" />
|
||||
</j-tooltip>
|
||||
</h5>
|
||||
|
||||
<div class="box-list">
|
||||
<div class="list-item" v-for="item in dataList">
|
||||
<div class="list-item" v-for="item in props.dataList">
|
||||
<div class="box-top" @click="jumpPage(item)">
|
||||
<span class="top-title">{{ item.title }}</span>
|
||||
<img :src="item.iconUrl" alt="" />
|
||||
|
@ -22,42 +22,35 @@
|
|||
|
||||
<div class="dialogs">
|
||||
<ProductChooseDialog
|
||||
:open-number="openAccess"
|
||||
v-if="productDialogVisible"
|
||||
v-model:visible="productDialogVisible"
|
||||
@confirm="againJumpPage"
|
||||
/>
|
||||
<DeviceChooseDialog
|
||||
:open-number="openFunc"
|
||||
v-if="deviceDialogVisible"
|
||||
v-model:visible="deviceDialogVisible"
|
||||
@confirm="againJumpPage"
|
||||
/>
|
||||
</div>
|
||||
</a-card>
|
||||
</dic>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { PropType } from 'vue';
|
||||
import { QuestionCircleOutlined } from '@ant-design/icons-vue';
|
||||
import { message } from 'ant-design-vue';
|
||||
|
||||
import ProductChooseDialog from './dialogs/ProductChooseDialog.vue';
|
||||
import DeviceChooseDialog from './dialogs/DeviceChooseDialog.vue';
|
||||
|
||||
import { recommendList } from '../typing';
|
||||
import { useMenuStore } from '@/store/menu';
|
||||
|
||||
type rowType = {
|
||||
params: object;
|
||||
linkUrl: string;
|
||||
};
|
||||
const { jumpPage: _jumpPage } = useMenuStore();
|
||||
|
||||
const props = defineProps({
|
||||
cardTitle: String,
|
||||
tooltip: String,
|
||||
dataList: Array as PropType<recommendList[]>,
|
||||
});
|
||||
const router = useRouter();
|
||||
|
||||
const { cardTitle, tooltip, dataList } = toRefs(props);
|
||||
const openAccess = ref<number>(0);
|
||||
const openFunc = ref<number>(0);
|
||||
let selectRow: recommendList | rowType = {
|
||||
params: {},
|
||||
linkUrl: '',
|
||||
|
@ -66,34 +59,33 @@ let selectRow: recommendList | rowType = {
|
|||
const jumpPage = (row: recommendList) => {
|
||||
if (!row.auth) return message.warning('暂无权限,请联系管理员');
|
||||
selectRow = row; // 二次跳转需要使用
|
||||
if (row.dialogTag == 'accessMethod') return (openAccess.value += 1);
|
||||
else if (row.dialogTag === 'funcTest') return (openFunc.value += 1);
|
||||
if (row.dialogTag == 'accessMethod')
|
||||
return (productDialogVisible.value = true);
|
||||
else if (row.dialogTag === 'funcTest')
|
||||
return (deviceDialogVisible.value = true);
|
||||
else if (row.linkUrl) {
|
||||
router.push(`${row.linkUrl}${objToParams(row.params || {})}`);
|
||||
_jumpPage(row.linkUrl, row.params);
|
||||
}
|
||||
};
|
||||
// 弹窗返回后的二次跳转
|
||||
const againJumpPage = (params: string) => {
|
||||
router.push(`${selectRow.linkUrl}/${params}`);
|
||||
const againJumpPage = (id: string) => {
|
||||
_jumpPage(selectRow.linkUrl, { id });
|
||||
};
|
||||
|
||||
const objToParams = (source: object): string => {
|
||||
if (Object.prototype.toString.call(source) === '[object Object]') {
|
||||
const paramsArr = <any>[];
|
||||
// 直接使用for in遍历对象ts会报错
|
||||
Object.entries(source).forEach(([prop, value]) => {
|
||||
if (typeof value === 'object') value = JSON.stringify(value);
|
||||
paramsArr.push(`${prop}=${value}`);
|
||||
});
|
||||
if (paramsArr.length > 0) return '?' + paramsArr.join('&');
|
||||
}
|
||||
return '';
|
||||
const productDialogVisible = ref(false);
|
||||
const deviceDialogVisible = ref(false);
|
||||
|
||||
type rowType = {
|
||||
params: object;
|
||||
linkUrl: string;
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.step-container {
|
||||
width: 100%;
|
||||
padding: 24px 14px;
|
||||
background-color: #fff;
|
||||
.title {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
|
|
|
@ -1,23 +1,26 @@
|
|||
<template>
|
||||
<div ref="modal" class="func-test-dialog-container"></div>
|
||||
<a-modal
|
||||
v-model:visible="visible"
|
||||
title="选择产品"
|
||||
<j-modal
|
||||
visible
|
||||
title="选择设备"
|
||||
style="width: 1000px"
|
||||
@ok="handleOk"
|
||||
:getContainer="getContainer"
|
||||
@ok="confirm"
|
||||
@cancel="emits('update:visible', false)"
|
||||
:maskClosable="false"
|
||||
>
|
||||
<Search type="simple" :columns="query.columns" @search="query.search" />
|
||||
<JTable
|
||||
<j-advanced-search
|
||||
type="simple"
|
||||
:columns="columns"
|
||||
@search="(params:any)=>queryParams = {...params}"
|
||||
/>
|
||||
<j-pro-table
|
||||
model="TABLE"
|
||||
:request="getDeviceList_api"
|
||||
:columns="table.columns"
|
||||
:params="query.params"
|
||||
:columns="columns"
|
||||
:params="queryParams"
|
||||
:defaultParams="{ sorts: [{ name: 'createTime', order: 'desc' }] }"
|
||||
:rowSelection="{
|
||||
selectedRowKeys: table.selectedKeys,
|
||||
onChange: table.onSelect,
|
||||
selectedRowKeys: selectedKeys,
|
||||
onChange: (keys:string[])=>selectedKeys = keys,
|
||||
type: 'radio',
|
||||
}"
|
||||
>
|
||||
|
@ -32,152 +35,90 @@
|
|||
:status-label="slotProps.state.text"
|
||||
/>
|
||||
</template>
|
||||
</JTable>
|
||||
|
||||
<template #footer>
|
||||
<a-button key="back" @click="visible = false">取消</a-button>
|
||||
<a-button key="submit" type="primary" @click="handleOk"
|
||||
>确认</a-button
|
||||
>
|
||||
</template>
|
||||
</a-modal>
|
||||
</j-pro-table>
|
||||
</j-modal>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import StatusLabel from '../StatusLabel.vue';
|
||||
|
||||
import { ComponentInternalInstance } from 'vue';
|
||||
import { getDeviceList_api } from '@/api/home';
|
||||
import { message } from 'ant-design-vue';
|
||||
import moment from 'moment';
|
||||
|
||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||
const emits = defineEmits(['confirm']);
|
||||
const props = defineProps({
|
||||
openNumber: Number,
|
||||
});
|
||||
const emits = defineEmits(['confirm', 'update:visible']);
|
||||
const props = defineProps<{
|
||||
visible: boolean;
|
||||
}>();
|
||||
|
||||
// 弹窗控制
|
||||
const visible = ref<boolean>(false);
|
||||
const getContainer = () => proxy?.$refs.modal as HTMLElement;
|
||||
const handleOk = () => {
|
||||
if (table.selectedKeys.length < 1) return message.warn('请选择设备');
|
||||
emits('confirm', table.selectedKeys[0]);
|
||||
visible.value = false;
|
||||
const confirm = () => {
|
||||
if (selectedKeys.value.length < 1) return message.warn('请选择设备');
|
||||
emits('confirm', selectedKeys.value[0]);
|
||||
emits('update:visible', false);
|
||||
};
|
||||
watch(
|
||||
() => props.openNumber,
|
||||
() => {
|
||||
visible.value = true;
|
||||
},
|
||||
);
|
||||
|
||||
const query = reactive({
|
||||
params: {},
|
||||
columns: [
|
||||
{
|
||||
title: '设备ID',
|
||||
dataIndex: 'id',
|
||||
key: 'id',
|
||||
ellipsis: true,
|
||||
search: {
|
||||
type: 'string',
|
||||
},
|
||||
const columns = [
|
||||
{
|
||||
title: '设备ID',
|
||||
dataIndex: 'id',
|
||||
key: 'id',
|
||||
ellipsis: true,
|
||||
search: {
|
||||
type: 'string',
|
||||
},
|
||||
{
|
||||
title: '设备名称',
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
ellipsis: true,
|
||||
search: {
|
||||
type: 'string',
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '产品名称',
|
||||
dataIndex: 'productName',
|
||||
key: 'productName',
|
||||
ellipsis: true,
|
||||
search: {
|
||||
type: 'string',
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '注册时间',
|
||||
dataIndex: 'modifyTime',
|
||||
key: 'modifyTime',
|
||||
ellipsis: true,
|
||||
search: {
|
||||
type: 'date',
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '状态',
|
||||
dataIndex: 'state',
|
||||
key: 'state',
|
||||
ellipsis: true,
|
||||
search: {
|
||||
rename: 'state',
|
||||
type: 'select',
|
||||
options: [
|
||||
{
|
||||
label: '在线',
|
||||
value: 'online',
|
||||
},
|
||||
{
|
||||
label: '离线',
|
||||
value: 'offline',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
search: (params: object) => {
|
||||
query.params = params;
|
||||
},
|
||||
});
|
||||
{
|
||||
title: '设备名称',
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
ellipsis: true,
|
||||
search: {
|
||||
type: 'string',
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '产品名称',
|
||||
dataIndex: 'productName',
|
||||
key: 'productName',
|
||||
ellipsis: true,
|
||||
search: {
|
||||
type: 'string',
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '注册时间',
|
||||
dataIndex: 'modifyTime',
|
||||
key: 'modifyTime',
|
||||
ellipsis: true,
|
||||
search: {
|
||||
type: 'date',
|
||||
},
|
||||
scopedSlots: true,
|
||||
},
|
||||
{
|
||||
title: '状态',
|
||||
dataIndex: 'state',
|
||||
key: 'state',
|
||||
ellipsis: true,
|
||||
search: {
|
||||
rename: 'state',
|
||||
type: 'select',
|
||||
options: [
|
||||
{
|
||||
label: '在线',
|
||||
value: 'online',
|
||||
},
|
||||
{
|
||||
label: '离线',
|
||||
value: 'offline',
|
||||
},
|
||||
],
|
||||
},
|
||||
scopedSlots: true,
|
||||
},
|
||||
];
|
||||
|
||||
const table = reactive({
|
||||
columns: [
|
||||
{
|
||||
title: '设备Id',
|
||||
dataIndex: 'id',
|
||||
key: 'id',
|
||||
},
|
||||
{
|
||||
title: '设备名称',
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
},
|
||||
{
|
||||
title: '产品名称',
|
||||
dataIndex: 'productName',
|
||||
key: 'productName',
|
||||
},
|
||||
{
|
||||
title: '注册时间',
|
||||
dataIndex: 'modifyTime',
|
||||
key: 'modifyTime',
|
||||
scopedSlots: true,
|
||||
},
|
||||
{
|
||||
title: '状态',
|
||||
dataIndex: 'state',
|
||||
key: 'state',
|
||||
scopedSlots: true,
|
||||
},
|
||||
],
|
||||
selectedKeys: [] as string[],
|
||||
onSelect: (keys: string[]) => {
|
||||
table.selectedKeys = [...keys];
|
||||
},
|
||||
});
|
||||
const queryParams = ref({});
|
||||
|
||||
const selectedKeys = ref<string[]>([]);
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.func-test-dialog-container {
|
||||
.search {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -1,59 +1,52 @@
|
|||
<template>
|
||||
<div ref="modal" class="access-method-dialog-container"></div>
|
||||
<a-modal
|
||||
v-model:visible="visible"
|
||||
<j-modal
|
||||
visible
|
||||
title="选择产品"
|
||||
style="width: 700px"
|
||||
@ok="handleOk"
|
||||
show-search
|
||||
width="700px"
|
||||
@ok="confirm"
|
||||
@cancel="emits('update:visible', false)"
|
||||
:filter-option="filterOption"
|
||||
:getContainer="getContainer"
|
||||
:maskClosable="false"
|
||||
class="access-method-dialog-container"
|
||||
>
|
||||
<a-form :model="form" name="basic" autocomplete="off" layout="vertical">
|
||||
<a-form-item
|
||||
<j-form :model="form" name="basic" autocomplete="off" layout="vertical">
|
||||
<j-form-item
|
||||
label="产品"
|
||||
name="productId"
|
||||
:rules="[{ required: true, message: '该字段是必填字段' }]"
|
||||
>
|
||||
<a-select
|
||||
<j-select
|
||||
v-model:value="form.productId"
|
||||
style="width: 100%"
|
||||
:options="productList"
|
||||
>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
|
||||
<template #footer>
|
||||
<a-button key="back" @click="visible = false">取消</a-button>
|
||||
<a-button key="submit" type="primary" @click="handleOk"
|
||||
>确认</a-button
|
||||
>
|
||||
</template>
|
||||
</a-modal>
|
||||
</j-select>
|
||||
</j-form-item>
|
||||
</j-form>
|
||||
</j-modal>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ComponentInternalInstance } from 'vue';
|
||||
|
||||
import { getProductList_api } from '@/api/home';
|
||||
import { productItem } from '../../typing';
|
||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||
const props = defineProps({
|
||||
openNumber: Number,
|
||||
});
|
||||
const emits = defineEmits(['confirm']);
|
||||
const visible = ref<boolean>(false);
|
||||
|
||||
const emits = defineEmits(['confirm', 'update:visible']);
|
||||
const props = defineProps<{
|
||||
visible: boolean;
|
||||
}>();
|
||||
|
||||
const confirm = () => {
|
||||
emits('confirm', form.value.productId);
|
||||
emits('update:visible', false);
|
||||
};
|
||||
|
||||
const form = ref({
|
||||
productId: '',
|
||||
});
|
||||
|
||||
const productList = ref<[productItem] | []>([]);
|
||||
|
||||
const getContainer = () => proxy?.$refs.modal as HTMLElement;
|
||||
const getOptions = () => {
|
||||
getProductList_api().then((resp:any) => {
|
||||
getProductList_api().then((resp: any) => {
|
||||
productList.value = resp.result
|
||||
.filter((i: any) => !i?.accessId)
|
||||
.map((item: { name: any; id: any }) => ({
|
||||
|
@ -62,21 +55,11 @@ const getOptions = () => {
|
|||
})) as [productItem];
|
||||
});
|
||||
};
|
||||
const handleOk = () => {
|
||||
emits('confirm', form.value.productId);
|
||||
visible.value = false;
|
||||
};
|
||||
|
||||
const filterOption = (input: string, option: any) => {
|
||||
return option.value.toLowerCase().indexOf(input.toLowerCase()) >= 0;
|
||||
};
|
||||
watch(
|
||||
() => props.openNumber,
|
||||
() => {
|
||||
visible.value = true;
|
||||
form.value.productId = '';
|
||||
getOptions();
|
||||
},
|
||||
);
|
||||
getOptions();
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
|
|
Loading…
Reference in New Issue