Browse Source

feat: 导入功能,完善设备类别过滤。

main
betaqi 3 weeks ago
parent
commit
ceb5b84c45
  1. 5
      src/api/module/engineering/index.d.ts
  2. 16
      src/api/module/engineering/index.ts
  3. 117
      src/views/engineering/components/create-engineering-dlg.vue
  4. 2
      src/views/engineering/components/device-dlg.vue
  5. 55
      src/views/engineering/index.vue

5
src/api/module/engineering/index.d.ts vendored

@ -5,3 +5,8 @@ export interface IEngineeringOV { @@ -5,3 +5,8 @@ export interface IEngineeringOV {
isCreate: boolean
}
export interface IEngineeringImport {
projectName: string
description?: string
file: File
}

16
src/api/module/engineering/index.ts

@ -1,6 +1,6 @@ @@ -1,6 +1,6 @@
import { globalServer } from '../index'
import type { IEngineeringOV } from './index.d'
import type { IEngineeringImport, IEngineeringOV } from './index.d'
export const createEngineering = (params: IEngineeringOV) => {
return globalServer({
@ -33,6 +33,18 @@ export const deleteEngineeringBatch = (names: string[]) => { @@ -33,6 +33,18 @@ export const deleteEngineeringBatch = (names: string[]) => {
return globalServer({
url: 'project/delete-list',
method: 'delete',
params: names.join(','),
params: {
names: names.join(',')
},
})
}
export const importEngineering = (params: IEngineeringImport) => {
return globalServer({
url: '/project/import',
method: 'POST',
data: params,
headers: { 'Content-Type': 'multipart/form-data' },
timeout: 0,
})
}

117
src/views/engineering/components/create-engineering-dlg.vue

@ -17,6 +17,29 @@ @@ -17,6 +17,29 @@
clearable
/>
</el-row>
<el-row v-if="actionType === 'import'">
<div class="label">工程文件</div>
<el-upload
class="flex-1"
action=""
:auto-upload="false"
:limit="1"
:on-change="handleFileChange"
accept=".prj"
drag
:on-remove="handleRemove"
>
<el-icon class="el-icon--upload !text-3xl !mb-2 !text-gray-400">
<upload-filled />
</el-icon>
<div class="el-upload__text text-xs text-gray-500 mt-2">
拖拽文件或<em class="text-blue-500 not-italic cursor-pointer hover:underline"
>点击上传</em
>
<div class="mt-1 opacity-70">支持文件类型为.prj</div>
</div>
</el-upload>
</el-row>
<el-row>
<div class="label">工程描述</div>
<el-input
@ -34,23 +57,25 @@ @@ -34,23 +57,25 @@
<script setup lang="ts">
import { cloneDeep } from 'lodash-es'
import { useRouter } from 'vue-router'
import { UploadFilled } from '@element-plus/icons-vue'
import { useMessage } from '@/composables/useMessage'
import EdfsDialog from '@/components/Edfs-dialog.vue'
import type { IEngineeringOV } from '@/api/module/engineering/index.d'
import { createEngineering } from '@/api/module/engineering'
import { validateName } from '@/utils/validate'
import { createEngineering, importEngineering } from '@/api/module/engineering'
import type { UploadFile } from 'element-plus'
const message = useMessage()
const router = useRouter()
type ActionType = 'create' | 'import'
const actionType = ref<ActionType>('create')
const props = defineProps<{
existingNames?: string[]
}>()
const emit = defineEmits<{
'on-save': [name: string]
'on-save': [name: string, actionType: ActionType]
}>()
const fromData: IEngineeringOV = {
@ -59,33 +84,86 @@ const fromData: IEngineeringOV = { @@ -59,33 +84,86 @@ const fromData: IEngineeringOV = {
isCreate: true,
}
const file = ref<UploadFile | null>(null)
function handleRemove() {
file.value = null
}
async function handleFileChange(fileUpload: UploadFile) {
if (!fileUpload.raw) return
const isPrj = fileUpload.name.toLowerCase().endsWith('.prj')
// const isLt5M = fileUpload.size! / 1024 / 1024 < 5
if (!isPrj) {
message.warning('请上传 .prj 格式的文件')
file.value = null
return
}
// if (!isLt5M) {
// message.warning(' 5MB')
// file.value = null
// return
// }
file.value = fileUpload
}
const form = ref(cloneDeep(fromData))
const visible = ref(false)
const btnLoading = ref(false)
function open() {
function open(type: ActionType) {
actionType.value = type
visible.value = true
}
async function onSave() {
if (verifyData()) return
btnLoading.value = true
try {
await createEngineering(form.value)
message.success('创建成功')
emit('on-save', form.value.name)
close()
} catch (error) {
message.error('创建失败')
} finally {
btnLoading.value = false
if (actionType.value === 'create') {
await createdEngineering()
} else {
await importSave()
}
btnLoading.value = false
}
async function importSave() {
if (!file.value?.raw) return
const res = await importEngineering({
projectName: form.value.name,
description: form.value.description,
file: file.value?.raw,
})
if (res.code !== 0) {
message.error(res?.msg || '导入失败')
return
}
message.success('导入成功')
emit('on-save', form.value.name, actionType.value)
close()
}
async function createdEngineering() {
const res = await createEngineering(form.value)
if (res.code != 0) {
message.error(res?.msg || '创建失败')
return
}
message.success('创建成功')
emit('on-save', form.value.name, actionType.value)
close()
}
function close() {
visible.value = false
form.value = cloneDeep(fromData)
file.value = null
}
function verifyData() {
@ -99,6 +177,11 @@ function verifyData() { @@ -99,6 +177,11 @@ function verifyData() {
return true
}
if (actionType.value === 'import' && !file.value?.raw) {
message.warning('请上传工程文件')
return true
}
return false
}

2
src/views/engineering/components/device-dlg.vue

@ -110,7 +110,7 @@ const computedChannels = computed(() => { @@ -110,7 +110,7 @@ const computedChannels = computed(() => {
})
const computedCategories = computed(() => {
return props.categories[form.value.channel]
return props.categories[form.value.channel]?.filter(r => r.status) ?? []
})
const form = ref<IDeviceFormData>(cloneDeep(FormData))

55
src/views/engineering/index.vue

@ -1,19 +1,27 @@ @@ -1,19 +1,27 @@
<template>
<EdfsWrap class="wh-full" :title="'工程列表'" :use-scroll-bar="false">
<EdfsWrap :title="'工程列表'" :use-scroll-bar="false" class="wh-full">
<template #title-right>
<div v-if="!isBatchMode">
<el-button type="danger" plain @click="enterBatchMode"> 批量删除 </el-button>
<el-button plain type="danger" @click="enterBatchMode">批量删除</el-button>
</div>
<div v-else>
<el-button
type="danger"
:disabled="selectedItems.length === 0"
type="danger"
@click="handleBatchDelete"
>
确认删除
</el-button>
<el-button @click="exitBatchMode">取消</el-button>
</div>
<el-button
v-if="!isBatchMode"
plain
type="primary"
class="ml-2"
@click="importEngineering"
>导入工程</el-button
>
</template>
<div class="engineering-list-container">
<el-checkbox-group v-model="selectedItems" class="engineering-grid">
@ -30,21 +38,21 @@ @@ -30,21 +38,21 @@
<div class="card-header">
<div class="flex items-center gap-2 flex-1 overflow-hidden">
<el-checkbox v-if="isBatchMode" :value="item.name" @click.stop>
<span class="card-title" :title="item.name"
<span :title="item.name" class="card-title"
>工程名称{{ item.name }}</span
>
</el-checkbox>
<div v-else class="h-32 leading-32px">
<span class="card-title" :title="item.name"
<span :title="item.name" class="card-title"
>工程名称{{ item.name }}</span
>
</div>
</div>
<el-button
link
type="danger"
v-if="!isBatchMode"
:icon="Delete"
link
type="danger"
@click="handleDelete(item)"
/>
</div>
@ -52,12 +60,12 @@ @@ -52,12 +60,12 @@
<p class="card-desc">工程描述{{ item.description }}</p>
</div>
<div class="card-footer">
<el-button type="primary" text @click="handleDownload(item)"
>下载工程</el-button
>
<el-button type="primary" text @click="enterEngineering(item)"
>进入工程</el-button
>
<el-button text type="primary" @click="handleDownload(item)"
>下载工程
</el-button>
<el-button text type="primary" @click="enterEngineering(item)"
>进入工程
</el-button>
</div>
</div>
</el-checkbox-group>
@ -72,13 +80,13 @@ @@ -72,13 +80,13 @@
/>
</template>
<script setup lang="ts">
<script lang="ts" setup>
import { useRouter } from 'vue-router'
import { ElMessage, ElMessageBox } from 'element-plus'
import EdfsWrap from '@/components/Edfs-wrap.vue'
import type { IEngineeringOV } from '@/api/module/engineering/index.d'
import CreateEngineeringDlg from './components/create-engineering-dlg.vue'
import { Plus, Delete } from '@element-plus/icons-vue'
import { Delete, Plus } from '@element-plus/icons-vue'
import { useEngineeringStore } from '@/stores/engineering'
import { storeToRefs } from 'pinia'
import { deleteEngineering, deleteEngineeringBatch } from '@/api/module/engineering'
@ -102,10 +110,18 @@ onMounted(() => { @@ -102,10 +110,18 @@ onMounted(() => {
})
function addEngineering() {
createEngineeringDlgRef.value?.open()
createEngineeringDlgRef.value?.open('create')
}
function handleSave(name: string) {
function importEngineering() {
createEngineeringDlgRef.value?.open('import')
}
function handleSave(name: string, actionType: string) {
if (actionType === 'import') {
engineeringStore.fetchEngineeringList()
return
}
enterEngineering({ name, description: '', isCreate: true })
}
@ -193,7 +209,7 @@ function handleBatchDelete() { @@ -193,7 +209,7 @@ function handleBatchDelete() {
ElMessage.success('删除成功')
selectedItems.value = []
isBatchMode.value = false
engineeringStore.fetchEngineeringList()
await engineeringStore.fetchEngineeringList()
}
})
.catch(() => {})
@ -209,7 +225,7 @@ function exitBatchMode() { @@ -209,7 +225,7 @@ function exitBatchMode() {
}
</script>
<style scoped lang="scss">
<style lang="scss" scoped>
.engineering-list-container {
height: 100%;
overflow-y: auto;
@ -257,6 +273,7 @@ function exitBatchMode() { @@ -257,6 +273,7 @@ function exitBatchMode() {
.card-body {
flex: 1;
margin-bottom: 16px;
.card-desc {
font-size: 14px;
color: #606266;

Loading…
Cancel
Save