feat: 设备管理批量操作
This commit is contained in:
parent
063602078a
commit
5e5087602c
|
|
@ -1,3 +1,6 @@
|
|||
import { BASE_API_PATH } from "@/utils/variable";
|
||||
|
||||
export const FILE_UPLOAD = `${BASE_API_PATH}/file/static`;
|
||||
/**
|
||||
* 上传文件
|
||||
*/
|
||||
export const FILE_UPLOAD = `${BASE_API_PATH}/file/static`;
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
import server from '@/utils/request'
|
||||
import { BASE_API_PATH } from '@/utils/variable'
|
||||
import { DeviceInstance } from '@/views/device/instance/typings'
|
||||
|
||||
/**
|
||||
|
|
@ -73,3 +74,28 @@ export const batchUndeployDevice = (data: string[]) => server.put(`/device-insta
|
|||
* @returns
|
||||
*/
|
||||
export const batchDeleteDevice = (data: string[]) => server.put(`/device-instance/batch/_delete`, data)
|
||||
|
||||
/**
|
||||
* 下载设备模板
|
||||
* @param productId 产品id
|
||||
* @param type 文件类型
|
||||
* @returns
|
||||
*/
|
||||
export const deviceTemplateDownload = (productId: string, type: string) => `${BASE_API_PATH}/device-instance/${productId}/template.${type}`
|
||||
|
||||
/**
|
||||
* 设备导入
|
||||
* @param productId 产品id
|
||||
* @param type 文件类型
|
||||
* @returns
|
||||
*/
|
||||
export const deviceImport = (productId: string, fileUrl: string, autoDeploy: boolean) => `${BASE_API_PATH}/device-instance/${productId}/import?fileUrl=${fileUrl}&autoDeploy=${autoDeploy}&:X_Access_Token=${LocalStore.get(TOKEN_KEY)}`
|
||||
|
||||
/**
|
||||
* 设备导出
|
||||
* @param productId 产品id
|
||||
* @param type 文件类型
|
||||
* @returns
|
||||
*/
|
||||
export const deviceExport = (productId: string, type: string) => `${BASE_API_PATH}/device-instance${!!productId ? '/' + productId : ''}/export.${type}`
|
||||
|
||||
|
|
|
|||
|
|
@ -25,7 +25,8 @@ const iconKeys = [
|
|||
'ImportOutlined',
|
||||
'ExportOutlined',
|
||||
'SyncOutlined',
|
||||
'ExclamationCircleOutlined'
|
||||
'ExclamationCircleOutlined',
|
||||
'UploadOutlined'
|
||||
]
|
||||
|
||||
const Icon = (props: {type: string}) => {
|
||||
|
|
|
|||
|
|
@ -228,6 +228,10 @@ const handleClick = () => {
|
|||
transform: skewX(-45deg);
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.card-item-content-title) {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.card-mask {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,36 @@
|
|||
<template>
|
||||
<a-space align="end">
|
||||
<a-radio-group button-style="solid" v-model:value="modelValue.fileType" placeholder="请选择文件格式">
|
||||
<a-radio-button value="xlsx">xlsx</a-radio-button>
|
||||
<a-radio-button value="csv">csv</a-radio-button>
|
||||
</a-radio-group>
|
||||
<a-checkbox v-model:checked="modelValue.autoDeploy">自动启用</a-checkbox>
|
||||
</a-space>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { PropType } from 'vue'
|
||||
|
||||
type Props = {
|
||||
autoDeploy: boolean,
|
||||
fileType: 'xlsx' | 'csv'
|
||||
}
|
||||
type Emits = {
|
||||
(e: 'update:modelValue', data: Partial<Props>): void;
|
||||
};
|
||||
const emit = defineEmits<Emits>();
|
||||
|
||||
const props = defineProps({
|
||||
// 组件双向绑定的值
|
||||
modelValue: {
|
||||
type: Object as PropType<Props>,
|
||||
default: () => {
|
||||
return {
|
||||
fileType: 'xlsx',
|
||||
autoDeploy: false
|
||||
}
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
</script>
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
<template>
|
||||
<a-upload
|
||||
v-model:file-list="fileList"
|
||||
name="avatar"
|
||||
list-type="picture-card"
|
||||
class="avatar-uploader"
|
||||
:show-upload-list="false"
|
||||
action="https://www.mocky.io/v2/5cc8019d300000980a055e76"
|
||||
:before-upload="beforeUpload"
|
||||
@change="handleChange"
|
||||
>
|
||||
<img v-if="imageUrl" :src="imageUrl" alt="avatar" />
|
||||
<div v-else>
|
||||
<loading-outlined v-if="loading"></loading-outlined>
|
||||
<plus-outlined v-else></plus-outlined>
|
||||
<div class="ant-upload-text">Upload</div>
|
||||
</div>
|
||||
</a-upload>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { message, UploadChangeParam, UploadProps } from 'ant-design-vue';
|
||||
|
||||
const handleChange = (info: UploadChangeParam) => {
|
||||
// if (info.file.status === 'uploading') {
|
||||
// loading.value = true;
|
||||
// return;
|
||||
// }
|
||||
// if (info.file.status === 'done') {
|
||||
// // Get this url from response in real world.
|
||||
// getBase64(info.file.originFileObj, (base64Url: string) => {
|
||||
// imageUrl.value = base64Url;
|
||||
// loading.value = false;
|
||||
// });
|
||||
// }
|
||||
// if (info.file.status === 'error') {
|
||||
// loading.value = false;
|
||||
// message.error('upload error');
|
||||
// }
|
||||
};
|
||||
|
||||
const beforeUpload = (file: UploadProps['fileList'][number]) => {
|
||||
// const isJpgOrPng = file.type === 'image/jpeg' || file.type === 'image/png';
|
||||
// if (!isJpgOrPng) {
|
||||
// message.error('You can only upload JPG file!');
|
||||
// }
|
||||
// const isLt2M = file.size / 1024 / 1024 < 2;
|
||||
// if (!isLt2M) {
|
||||
// message.error('Image must smaller than 2MB!');
|
||||
// }
|
||||
// return isJpgOrPng && isLt2M;
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.avatar-uploader {
|
||||
width: 160px;
|
||||
height: 160px;
|
||||
padding: 8px;
|
||||
background-color: rgba(0,0,0,.06);
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
:deep(.ant-upload.ant-upload-select-picture-card) {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,116 @@
|
|||
<template>
|
||||
<a-space align="end">
|
||||
<a-upload
|
||||
v-model:fileList="modelValue.upload"
|
||||
name="file"
|
||||
:action="FILE_UPLOAD"
|
||||
:headers="{
|
||||
'X-Access-Token': LocalStore.get(TOKEN_KEY)
|
||||
}"
|
||||
accept=".xlsx,.csv"
|
||||
:maxCount="1"
|
||||
:showUploadList="false"
|
||||
@change="uploadChange"
|
||||
>
|
||||
<a-button>
|
||||
<template #icon><AIcon type="UploadOutlined" /></template>
|
||||
文件上传
|
||||
</a-button>
|
||||
</a-upload>
|
||||
<div style="margin-left: 20px">
|
||||
<a-space>
|
||||
<a @click="downFile('xlsx')">.xlsx</a>
|
||||
<a @click="downFile('csv')">.csv</a>
|
||||
</a-space>
|
||||
</div>
|
||||
</a-space>
|
||||
<div style="margin-top: 20px" v-if="importLoading">
|
||||
<a-badge v-if="flag" status="processing" text="进行中" />
|
||||
<a-badge v-else status="success" text="已完成" />
|
||||
<span>总数量:{{count}}</span>
|
||||
<p style="color: red">{{errMessage}}</p>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { FILE_UPLOAD } from '@/api/comm'
|
||||
import { TOKEN_KEY } from '@/utils/variable';
|
||||
import { LocalStore } from '@/utils/comm';
|
||||
import { downloadFile } from '@/utils/utils';
|
||||
import { deviceImport, deviceTemplateDownload } from '@/api/device/instance'
|
||||
import { EventSourcePolyfill } from 'event-source-polyfill'
|
||||
import { message } from 'ant-design-vue';
|
||||
|
||||
type Emits = {
|
||||
(e: 'update:modelValue', data: string[]): void;
|
||||
};
|
||||
const emit = defineEmits<Emits>();
|
||||
|
||||
const props = defineProps({
|
||||
// 组件双向绑定的值
|
||||
modelValue: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
product: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
file: {
|
||||
type: Object,
|
||||
default: () => {
|
||||
return {
|
||||
fileType: 'xlsx',
|
||||
autoDeploy: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
const importLoading = ref<boolean>(false)
|
||||
const flag = ref<boolean>(false)
|
||||
const count = ref<number>(0)
|
||||
const errMessage = ref<string>('')
|
||||
|
||||
const downFile = (type: string) => {
|
||||
downloadFile(deviceTemplateDownload(props.product, type));
|
||||
}
|
||||
|
||||
const submitData = async (fileUrl: string) => {
|
||||
if (!!fileUrl) {
|
||||
count.value = 0
|
||||
errMessage.value = ''
|
||||
flag.value = true
|
||||
const autoDeploy = !!props?.file?.autoDeploy || false;
|
||||
importLoading.value = true
|
||||
let dt = 0;
|
||||
const source = new EventSourcePolyfill(deviceImport(props.product, fileUrl, autoDeploy));
|
||||
source.onmessage = (e: any) => {
|
||||
const res = JSON.parse(e.data);
|
||||
if (res.success) {
|
||||
const temp = res.result.total;
|
||||
dt += temp;
|
||||
count.value = dt
|
||||
} else {
|
||||
errMessage.value = res.message || '失败'
|
||||
}
|
||||
};
|
||||
source.onerror = (e: { status: number; }) => {
|
||||
if (e.status === 403) errMessage.value = '暂无权限,请联系管理员'
|
||||
flag.value = false
|
||||
source.close();
|
||||
};
|
||||
source.onopen = () => {};
|
||||
} else {
|
||||
message.error('请先上传文件')
|
||||
}
|
||||
}
|
||||
|
||||
const uploadChange = async (info: Record<string, any>) => {
|
||||
if (info.file.status === 'done') {
|
||||
const resp: any = info.file.response || { result: '' };
|
||||
await submitData(resp?.result || '');
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
|
@ -174,8 +174,14 @@ const JTable = defineComponent<JTableProps>({
|
|||
loading.value = true
|
||||
if(props.request) {
|
||||
const resp = await props.request({
|
||||
pageIndex: 0,
|
||||
pageSize: 12,
|
||||
...props.defaultParams,
|
||||
..._params
|
||||
..._params,
|
||||
terms: [
|
||||
...(props.defaultParams?.terms || []),
|
||||
...(_params?.terms || [])
|
||||
]
|
||||
})
|
||||
if(resp.status === 200){
|
||||
if(props.type === 'PAGE'){
|
||||
|
|
|
|||
|
|
@ -6,6 +6,9 @@ import TitleComponent from "./TitleComponent/index.vue";
|
|||
import Form from './Form';
|
||||
import CardBox from './CardBox/index.vue';
|
||||
import Search from './Search'
|
||||
import NormalUpload from './NormalUpload/index.vue'
|
||||
import FileFormat from './FileFormat/index.vue'
|
||||
import JUpload from './JUpload/index.vue'
|
||||
|
||||
export default {
|
||||
install(app: App) {
|
||||
|
|
@ -16,5 +19,8 @@ export default {
|
|||
.component('Form', Form)
|
||||
.component('CardBox', CardBox)
|
||||
.component('Search', Search)
|
||||
.component('NormalUpload', NormalUpload)
|
||||
.component('FileFormat', FileFormat)
|
||||
.component('JUpload', JUpload)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ import { queryNoPagingPost } from '@/api/device/product'
|
|||
import { downloadFile } from '@/utils/utils'
|
||||
import encodeQuery from '@/utils/encodeQuery'
|
||||
import { BASE_API_PATH } from '@/utils/variable'
|
||||
import { deviceExport } from '@/api/device/instance'
|
||||
|
||||
const emit = defineEmits(['close'])
|
||||
const props = defineProps({
|
||||
|
|
@ -58,15 +59,8 @@ watch(
|
|||
|
||||
const handleOk = () => {
|
||||
const params = encodeQuery(props.data);
|
||||
if(modelRef.product){
|
||||
downloadFile(
|
||||
`${BASE_API_PATH}/device/instance/${modelRef.product}/export.${modelRef.fileType}`,
|
||||
params
|
||||
);
|
||||
} else {
|
||||
downloadFile(`${BASE_API_PATH}/device/instance/export.${modelRef.fileType}`, params);
|
||||
}
|
||||
emit('close')
|
||||
downloadFile(deviceExport(modelRef.product || "", modelRef.fileType),params);
|
||||
emit('close')
|
||||
}
|
||||
|
||||
const handleCancel = () => {
|
||||
|
|
|
|||
|
|
@ -1,14 +1,67 @@
|
|||
<template>
|
||||
<a-modal :maskClosable="false" width="800px" :visible="true" title="导入" @ok="handleOk" @cancel="handleCancel">
|
||||
123
|
||||
<a-modal :maskClosable="false" width="800px" :visible="true" title="导入" @ok="handleCancel" @cancel="handleCancel">
|
||||
<div style="margin-top: 10px">
|
||||
<a-form :layout="'vertical'">
|
||||
<a-row>
|
||||
<a-col span="24">
|
||||
<a-form-item label="产品" required>
|
||||
<a-select showSearch v-model:value="modelRef.product" placeholder="请选择产品">
|
||||
<a-select-option :value="item.id" v-for="item in productList" :key="item.id" :title="item.name"></a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col span="24">
|
||||
<a-form-item label="文件格式" v-if="modelRef.product">
|
||||
<FileFormat v-model="modelRef.file" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col span="12">
|
||||
<a-form-item label="文件上传" v-if="modelRef.product">
|
||||
<NormalUpload :product="modelRef.product" v-model="modelRef.upload" :file="modelRef.file" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-form>
|
||||
</div>
|
||||
</a-modal>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
const handleOk = () => {
|
||||
import { queryNoPagingPost } from '@/api/device/product'
|
||||
import { Form } from 'ant-design-vue';
|
||||
|
||||
const emit = defineEmits(['close'])
|
||||
const props = defineProps({
|
||||
data: {
|
||||
type: Object,
|
||||
default: undefined
|
||||
}
|
||||
})
|
||||
const productList = ref<Record<string, any>[]>([])
|
||||
const useForm = Form.useForm;
|
||||
|
||||
const modelRef = reactive({
|
||||
product: undefined,
|
||||
upload: [],
|
||||
file: {
|
||||
fileType: 'xlsx',
|
||||
autoDeploy: false,
|
||||
}
|
||||
});
|
||||
|
||||
watch(
|
||||
() => props.data,
|
||||
() => {
|
||||
queryNoPagingPost({paging: false}).then(resp => {
|
||||
if(resp.status === 200){
|
||||
productList.value = resp.result as Record<string, any>[]
|
||||
}
|
||||
})
|
||||
},
|
||||
{immediate: true, deep: true}
|
||||
)
|
||||
|
||||
}
|
||||
const handleCancel = () => {
|
||||
|
||||
emit('close')
|
||||
}
|
||||
</script>
|
||||
|
|
@ -1,16 +1,16 @@
|
|||
<template>
|
||||
<a-modal :maskClosable="false" width="800px" :visible="true" title="当前进度" @ok="handleOk" @cancel="handleCancel">
|
||||
<a-modal :maskClosable="false" width="800px" :visible="true" title="当前进度" @ok="handleCancel" @cancel="handleCancel">
|
||||
<div>
|
||||
<a-badge v-if="flag" status="processing" text="进行中" />
|
||||
<a-badge v-else status="success" text="已完成" />
|
||||
</div>
|
||||
<p>总数量:{{count}}</p>
|
||||
<a></a>
|
||||
<a style="color: red">{{errMessage}}</a>
|
||||
</a-modal>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { downloadFile } from '@/utils/utils'
|
||||
import { EventSourcePolyfill } from 'event-source-polyfill'
|
||||
|
||||
const emit = defineEmits(['close'])
|
||||
const props = defineProps({
|
||||
|
|
@ -29,22 +29,63 @@ const flag = ref<boolean>(false)
|
|||
const errMessage = ref<string>('')
|
||||
const isSource = ref<boolean>(false)
|
||||
const id = ref<string>('')
|
||||
|
||||
const handleOk = () => {
|
||||
emit('close')
|
||||
}
|
||||
const source = ref<Record<string, any>>({})
|
||||
|
||||
const handleCancel = () => {
|
||||
emit('close')
|
||||
}
|
||||
|
||||
const getData = () => {
|
||||
|
||||
const getData = (api: string) => {
|
||||
let dt = 0
|
||||
const _source = new EventSourcePolyfill(api)
|
||||
source.value = _source
|
||||
_source.onmessage = (e: any) => {
|
||||
const res = JSON.parse(e.data);
|
||||
switch (props.type) {
|
||||
case 'active':
|
||||
if (res.success) {
|
||||
dt += res.total;
|
||||
count.value = dt
|
||||
} else {
|
||||
if (res.source) {
|
||||
const msg = `${res.source.name}: ${res.message}`;
|
||||
errMessage.value = msg
|
||||
id.value = res.source.id
|
||||
isSource.value = true
|
||||
} else {
|
||||
errMessage.value = res.message
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'sync':
|
||||
dt += res;
|
||||
count.value = dt
|
||||
break;
|
||||
case 'import':
|
||||
if (res.success) {
|
||||
const temp = res.result.total;
|
||||
dt += temp;
|
||||
count.value = dt
|
||||
} else {
|
||||
errMessage.value = res.message
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
};
|
||||
_source.onerror = () => {
|
||||
flag.value = false
|
||||
_source.close();
|
||||
};
|
||||
_source.onopen = () => {};
|
||||
}
|
||||
|
||||
watch(() => props.api,
|
||||
() => {
|
||||
getData()
|
||||
(newValue) => {
|
||||
if(newValue) {
|
||||
getData(newValue)
|
||||
}
|
||||
},
|
||||
{deep: true, immediate: true}
|
||||
)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,70 @@
|
|||
<template>
|
||||
<a-modal :maskClosable="false" width="650px" :visible="true" title="新增" @ok="handleCancel" @cancel="handleCancel">
|
||||
<div style="margin-top: 10px">
|
||||
<a-form :layout="'vertical'">
|
||||
<a-row type="flex">
|
||||
<a-col flex="180px">
|
||||
<a-form-item required>
|
||||
<JUpload />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col flex="auto">
|
||||
<a-form-item label="ID">
|
||||
<a-input v-model:value="modelRef.id" placeholder="请输入ID" />
|
||||
</a-form-item>
|
||||
<a-form-item label="名称" required>
|
||||
<a-input v-model:value="modelRef.name" placeholder="请输入名称" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
<a-form-item label="产品" required>
|
||||
<a-select showSearch v-model:value="modelRef.productId" placeholder="请选择产品">
|
||||
<a-select-option :value="item.id" v-for="item in productList" :key="item.id" :title="item.name"></a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
<a-form-item label="说明">
|
||||
<a-textarea v-model:value="modelRef.describe" placeholder="请输入说明" />
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</div>
|
||||
</a-modal>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { queryNoPagingPost } from '@/api/device/product'
|
||||
import { Form } from 'ant-design-vue';
|
||||
|
||||
const emit = defineEmits(['close', 'save'])
|
||||
const props = defineProps({
|
||||
data: {
|
||||
type: Object,
|
||||
default: undefined
|
||||
}
|
||||
})
|
||||
const productList = ref<Record<string, any>[]>([])
|
||||
const useForm = Form.useForm;
|
||||
|
||||
const modelRef = reactive({
|
||||
productId: undefined,
|
||||
id: '',
|
||||
name: '',
|
||||
describe: '',
|
||||
photoUrl: ''
|
||||
});
|
||||
|
||||
watch(
|
||||
() => props.data,
|
||||
() => {
|
||||
queryNoPagingPost({paging: false}).then(resp => {
|
||||
if(resp.status === 200){
|
||||
productList.value = resp.result as Record<string, any>[]
|
||||
}
|
||||
})
|
||||
},
|
||||
{immediate: true, deep: true}
|
||||
)
|
||||
|
||||
const handleCancel = () => {
|
||||
emit('close')
|
||||
}
|
||||
</script>
|
||||
|
|
@ -73,7 +73,7 @@
|
|||
</slot>
|
||||
</template>
|
||||
<template #content>
|
||||
<h3 @click="handleView(slotProps.id)">{{ slotProps.name }}</h3>
|
||||
<h3 class="card-item-content-title" @click.stop="handleView(slotProps.id)">{{ slotProps.name }}</h3>
|
||||
<a-row>
|
||||
<a-col :span="12">
|
||||
<div class="card-item-content-text">设备类型</div>
|
||||
|
|
@ -151,6 +151,7 @@
|
|||
<Import v-if="importVisible" @close="importVisible = false" />
|
||||
<Export v-if="exportVisible" @close="exportVisible = false" :data="params" />
|
||||
<Process v-if="operationVisible" @close="operationVisible = false" :api="api" :type="type" />
|
||||
<Save v-if="visible" :data="current" />
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
|
|
@ -161,13 +162,15 @@ import { message } from "ant-design-vue";
|
|||
import Import from './Import/index.vue'
|
||||
import Export from './Export/index.vue'
|
||||
import Process from './Process/index.vue'
|
||||
import Save from './Save/index.vue'
|
||||
import { BASE_API_PATH, TOKEN_KEY } from '@/utils/variable';
|
||||
|
||||
const instanceRef = ref<Record<string, any>>({});
|
||||
const params = ref<Record<string, any>>({pageIndex: 0, pageSize: 12})
|
||||
const params = ref<Record<string, any>>({})
|
||||
const _selectedRowKeys = ref<string[]>([])
|
||||
const importVisible = ref<boolean>(false)
|
||||
const exportVisible = ref<boolean>(false)
|
||||
const visible = ref<boolean>(false)
|
||||
const current = ref<Record<string, any>>({})
|
||||
const operationVisible = ref<boolean>(false)
|
||||
const api = ref<string>('')
|
||||
|
|
@ -220,9 +223,9 @@ const columns = [
|
|||
}
|
||||
]
|
||||
|
||||
const paramsFormat = (config: any, _terms: any, name?: string) => {
|
||||
const paramsFormat = (config: Record<string, any>, _terms: Record<string, any>, name?: string) => {
|
||||
if (config?.terms && Array.isArray(config.terms) && config?.terms.length > 0) {
|
||||
(config?.terms || []).map((item: any, index: number) => {
|
||||
(config?.terms || []).map((item: Record<string, any>, index: number) => {
|
||||
if (item?.type) {
|
||||
_terms[`${name ? `${name}.` : ''}terms[${index}].type`] = item.type;
|
||||
}
|
||||
|
|
@ -237,28 +240,33 @@ const paramsFormat = (config: any, _terms: any, name?: string) => {
|
|||
}
|
||||
}
|
||||
|
||||
const handleParams = (config: any) => {
|
||||
const _terms: any = {};
|
||||
const handleParams = (config: Record<string, any>) => {
|
||||
const _terms: Record<string, any> = {};
|
||||
paramsFormat(config, _terms);
|
||||
const url = new URLSearchParams();
|
||||
Object.keys(_terms).forEach((key) => {
|
||||
url.append(key, _terms[key]);
|
||||
});
|
||||
return url.toString();
|
||||
if(Object.keys(_terms._value).length && Object.keys(_terms).length) {
|
||||
const url = new URLSearchParams();
|
||||
Object.keys(_terms).forEach((key) => {
|
||||
url.append(key, _terms[key]);
|
||||
});
|
||||
return url.toString();
|
||||
} else {
|
||||
return ''
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增
|
||||
*/
|
||||
const handleAdd = () => {
|
||||
message.warn('新增')
|
||||
visible.value = true
|
||||
current.value = {}
|
||||
}
|
||||
|
||||
/**
|
||||
* 查看
|
||||
*/
|
||||
const handleView = (dt: any) => {
|
||||
// message.warn('查看')
|
||||
const handleView = (id: string) => {
|
||||
message.warn(id + '暂未开发')
|
||||
}
|
||||
|
||||
const getActions = (data: Partial<Record<string, any>>, type: 'card' | 'table'): ActionsType[] => {
|
||||
|
|
@ -272,7 +280,7 @@ const getActions = (data: Partial<Record<string, any>>, type: 'card' | 'table'):
|
|||
},
|
||||
icon: 'EyeOutlined',
|
||||
onClick: () => {
|
||||
handleView(data)
|
||||
handleView(data.id)
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
@ -283,7 +291,8 @@ const getActions = (data: Partial<Record<string, any>>, type: 'card' | 'table'):
|
|||
},
|
||||
icon: 'EditOutlined',
|
||||
onClick: () => {
|
||||
message.warn('edit')
|
||||
visible.value = true
|
||||
current.value = data
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
@ -356,14 +365,14 @@ const handleClick = (dt: any) => {
|
|||
|
||||
const activeAllDevice = () => {
|
||||
type.value = 'active'
|
||||
const activeAPI = `/${BASE_API_PATH}/device-instance/deploy?:X_Access_Token=${LocalStore.get(TOKEN_KEY)}&${handleParams(params)}`;
|
||||
const activeAPI = `${BASE_API_PATH}/device-instance/deploy?:X_Access_Token=${LocalStore.get(TOKEN_KEY)}&${handleParams(params)}`;
|
||||
api.value = activeAPI
|
||||
operationVisible.value = true
|
||||
}
|
||||
|
||||
const syncDeviceStatus = () => {
|
||||
type.value = 'sync'
|
||||
const syncAPI = `/${BASE_API_PATH}/device-instance/state/_sync?:X_Access_Token=${LocalStore.get(TOKEN_KEY)}&${handleParams(params)}`;
|
||||
const syncAPI = `${BASE_API_PATH}/device-instance/state/_sync?:X_Access_Token=${LocalStore.get(TOKEN_KEY)}&${handleParams(params)}`;
|
||||
api.value = syncAPI
|
||||
operationVisible.value = true
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue