吉安感知网项目-前端
罗广辉
2026-01-07 74b20b23a36ca26d3288ffb7b798903b1afd46c3
feat: 设备出入库管理
3 files added
1 files deleted
378 ■■■■■ changed files
applications/drone-command/src/api/fwDevice/index.js 43 ●●●●● patch | view | raw | blame | history
applications/drone-command/src/views/basicManage/deviceStock.vue 19 ●●●●● patch | view | raw | blame | history
applications/drone-command/src/views/basicManage/deviceStock/DeviceStockFormDialog.vue 208 ●●●●● patch | view | raw | blame | history
applications/drone-command/src/views/basicManage/deviceStock/deviceStock.vue 108 ●●●●● patch | view | raw | blame | history
applications/drone-command/src/api/fwDevice/index.js
New file
@@ -0,0 +1,43 @@
import request from '@/axios'
// 查
export const fwDeviceListApi = params => {
    return request({
        url: `/drone-fw/fwDevice/fwDevice/list`,
        method: 'get',
        params,
    })
}
// 增
export const fwDeviceSaveApi = data => {
    return request({
        url: `/drone-fw/fwDevice/fwDevice/save`,
        method: 'post',
        data,
    })
}
// 改
export const fwDeviceUpdateApi = data => {
    return request({
        url: `/drone-fw/fwDevice/fwDevice/update`,
        method: 'post',
        data,
    })
}
//删除
export const fwDeviceRemoveApi = data => {
    return request({
        url: `/drone-fw/fwDevice/fwDevice/remove`,
        method: 'post',
        data,
    })
}
//详情
export const fwDeviceDetailApi = params => {
    return request({
        url: `/drone-fw/fwDevice/fwDevice/detail`,
        method: 'get',
        params,
    })
}
applications/drone-command/src/views/basicManage/deviceStock.vue
File was deleted
applications/drone-command/src/views/basicManage/deviceStock/DeviceStockFormDialog.vue
New file
@@ -0,0 +1,208 @@
<template>
    <el-dialog v-model="visible" :title="dialogTitle" @closed="handleClosed" destroy-on-close>
        <el-form ref="formRef" :model="formData" :rules="rules" :disabled="dialogReadonly" label-width="100px">
            <el-row>
                <el-col :span="12">
                    <el-form-item label="设备名称" prop="deviceName">
                        <el-input v-model="formData.deviceName" maxlength="50" placeholder="请输入" />
                    </el-form-item>
                </el-col>
                <el-col :span="12">
                    <el-form-item label="设备类型" prop="deviceType">
                        <el-input v-model="formData.deviceType" maxlength="50" placeholder="请输入" />
                    </el-form-item>
                </el-col>
            </el-row>
            <el-row>
                <el-col :span="12">
                    <el-form-item label="型号" prop="deviceModel">
                        <el-input v-model="formData.deviceModel" maxlength="50" placeholder="请输入" />
                    </el-form-item>
                </el-col>
                <el-col :span="12">
                    <el-form-item label="规格" prop="deviceSpecification">
                        <el-input v-model="formData.deviceSpecification" maxlength="50" placeholder="请输入" />
                    </el-form-item>
                </el-col>
            </el-row>
            <el-row>
                <el-col :span="12">
                    <el-form-item label="生产厂商" prop="manufacturer">
                        <el-input v-model="formData.manufacturer" maxlength="50" placeholder="请输入" />
                    </el-form-item>
                </el-col>
                <el-col :span="12">
                    <el-form-item label="出库去向" prop="stockOutDestination">
                        <el-input v-model="formData.stockOutDestination" maxlength="50" placeholder="请输入" />
                    </el-form-item>
                </el-col>
            </el-row>
            <el-row>
                <el-col :span="12">
                    <el-form-item label="来源" prop="source">
                        <el-input v-model="formData.source" maxlength="50" placeholder="请输入" />
                    </el-form-item>
                </el-col>
                <el-col :span="12">
                    <el-form-item label="用途" prop="purpose">
                        <el-input v-model="formData.purpose" maxlength="50" placeholder="请输入" />
                    </el-form-item>
                </el-col>
            </el-row>
            <el-row>
                <el-col :span="12">
                    <el-form-item label="所属部门" prop="ownerDept">
                        <el-input v-model="formData.ownerDept" maxlength="50" placeholder="请输入" />
                    </el-form-item>
                </el-col>
                <el-col :span="12">
                    <el-form-item label="负责人" prop="ownerUser">
                        <el-input v-model="formData.ownerUser" maxlength="50" placeholder="请输入" />
                    </el-form-item>
                </el-col>
            </el-row>
        </el-form>
        <template #footer>
            <el-button @click="handleCancel">{{ dialogShowSubmit ? '取消' : '关闭' }}</el-button>
            <el-button v-if="dialogShowSubmit" type="primary" @click="handleSubmit">确定</el-button>
        </template>
    </el-dialog>
</template>
<script setup>
import { computed, ref } from 'vue'
import { ElMessage } from 'element-plus'
import { fwDeviceDetailApi, fwDeviceSaveApi, fwDeviceUpdateApi } from '@/api/fwDevice'
const createEmptyForm = () => ({
    deviceModel: '',
    deviceName: '',
    deviceSpecification: '',
    deviceType: '',
    manufacturer: '',
    ownerDept: '',
    ownerUser: '',
    purpose: '',
    source: '',
    stockOutDestination: '',
})
const emit = defineEmits(['success'])
const formRef = ref(null)
const formData = ref(createEmptyForm())
const visible = ref(false)
const dialogMode = ref('add')
const dialogRowId = ref(null)
const dialogTitle = computed(() => {
    if (dialogMode.value === 'edit') {
        return '编辑'
    }
    if (dialogMode.value === 'view') {
        return '查看'
    }
    return '新增'
})
const dialogShowSubmit = computed(() => dialogMode.value !== 'view')
const dialogReadonly = computed(() => dialogMode.value === 'view')
const rules = {
    deviceName: [
        { required: true, message: '请输入设备名称', trigger: 'blur' },
        { max: 50, message: '长度不超过50', trigger: 'blur' },
    ],
    deviceType: [
        { required: true, message: '请输入设备类型', trigger: 'blur' },
        { max: 50, message: '长度不超过50', trigger: 'blur' },
    ],
    deviceModel: [
        { required: true, message: '请输入型号', trigger: 'blur' },
        { max: 50, message: '长度不超过50', trigger: 'blur' },
    ],
    deviceSpecification: [
        { required: true, message: '请输入规格', trigger: 'blur' },
        { max: 50, message: '长度不超过50', trigger: 'blur' },
    ],
    manufacturer: [
        { required: true, message: '请输入生产厂商', trigger: 'blur' },
        { max: 50, message: '长度不超过50', trigger: 'blur' },
    ],
    stockOutDestination: [
        { required: true, message: '请输入出库去向', trigger: 'blur' },
        { max: 50, message: '长度不超过50', trigger: 'blur' },
    ],
    source: [
        { required: true, message: '请输入来源', trigger: 'blur' },
        { max: 50, message: '长度不超过50', trigger: 'blur' },
    ],
    purpose: [
        { required: true, message: '请输入用途', trigger: 'blur' },
        { max: 50, message: '长度不超过50', trigger: 'blur' },
    ],
    ownerDept: [
        { required: true, message: '请输入所属部门', trigger: 'blur' },
        { max: 50, message: '长度不超过50', trigger: 'blur' },
    ],
    ownerUser: [
        { required: true, message: '请输入负责人', trigger: 'blur' },
        { max: 50, message: '长度不超过50', trigger: 'blur' },
    ],
}
// 关闭弹框
function handleCancel() {
    visible.value = false
}
// 提交新增/编辑
async function handleSubmit() {
    if (dialogMode.value === 'view') {
        return
    }
    const isValid = await formRef.value?.validate().catch(() => false)
    if (!isValid) {
        return
    }
    if (dialogMode.value === 'add') {
        await fwDeviceSaveApi({ ...formData.value })
        ElMessage.success('新增成功')
    }
    if (dialogMode.value === 'edit') {
        await fwDeviceUpdateApi({ ...formData.value })
        ElMessage.success('更新成功')
    }
    visible.value = false
    emit('success')
}
// 加载详情
async function loadDetail() {
    if (!dialogRowId.value) return
    const res = await fwDeviceDetailApi({ id: dialogRowId.value })
    const data = res?.data?.data ?? {}
    formData.value = { ...createEmptyForm(), ...data }
}
// 重置表单
function resetFormData() {
    formData.value = createEmptyForm()
}
// 关闭后重置
function handleClosed() {
    resetFormData()
}
// 打开弹框
async function open({ mode, id } = {}) {
    dialogMode.value = mode || 'add'
    dialogRowId.value = id ?? null
    visible.value = true
    if (dialogMode.value === 'add') {
        resetFormData()
    } else {
        await loadDetail()
    }
}
defineExpose({ open })
</script>
applications/drone-command/src/views/basicManage/deviceStock/deviceStock.vue
New file
@@ -0,0 +1,108 @@
<template>
    <basic-container>
        <el-form ref="queryParamsRef" :inline="true" :model="searchParams">
            <el-form-item label="名称" prop="deviceName">
                <el-input v-model="searchParams.deviceName" />
            </el-form-item>
            <el-form-item label="类型" prop="deviceType">
                <el-input v-model="searchParams.deviceType" />
            </el-form-item>
            <el-form-item>
                <el-button type="primary" @click="handleSearch">查询</el-button>
                <el-button @click="resetForm">重置</el-button>
            </el-form-item>
        </el-form>
        <div>
            <el-button type="primary" @click="handleAdd">新增</el-button>
        </div>
        <el-table :data="list">
            <el-table-column type="index" width="60" label="序号" />
            <el-table-column prop="deviceName" label="名称" />
            <el-table-column prop="deviceType" label="类型" />
            <el-table-column prop="deviceModel" label="设备型号" />
            <el-table-column prop="deviceSpecification" label="规格" />
            <el-table-column label="操作">
                <template v-slot="{ row }">
                    <el-link @click="handleView(row)" type="primary">查看</el-link>
                    <el-link @click="handleEdit(row)" type="warning">编辑</el-link>
                    <el-link @click="handleDelete(row)" type="danger">删除</el-link>
                </template>
            </el-table-column>
        </el-table>
        <el-pagination
            v-model:current-page="searchParams.current"
            v-model:page-size="searchParams.size"
            :total="total"
            @change="getList"
        />
        <DeviceStockFormDialog ref="dialogRef" @success="getList" />
    </basic-container>
</template>
<script setup>
import { onMounted, reactive, ref } from 'vue'
import { ElMessageBox } from 'element-plus'
import { fwDeviceListApi, fwDeviceRemoveApi } from '@/api/fwDevice'
import DeviceStockFormDialog from './DeviceStockFormDialog.vue'
const searchParams = reactive({
    deviceName: '',
    deviceType: '',
    current: 1,
    size: 10,
})
const total = ref(0)
const list = ref([])
const queryParamsRef = ref(null)
const dialogRef = ref(null)
// 获取列表
async function getList() {
    const res = await fwDeviceListApi({ ...searchParams })
    list.value = res?.data?.data?.records ?? []
    total.value = res?.data?.data?.total ?? 0
}
// 查询
function handleSearch() {
    searchParams.current = 1
    getList()
}
// 重置查询
function resetForm() {
    queryParamsRef.value?.resetFields()
    searchParams.current = 1
    getList()
}
// 查看
function handleView(row) {
    dialogRef.value?.open({ mode: 'view', id: row.id })
}
// 编辑
function handleEdit(row) {
    dialogRef.value?.open({ mode: 'edit', id: row.id })
}
// 删除
async function handleDelete(row) {
    await ElMessageBox.confirm('确认删除该设备吗?', '提示', { type: 'warning' })
    await fwDeviceRemoveApi({ ids: [row.id] })
    getList()
}
// 新增
function handleAdd() {
    dialogRef.value?.open({ mode: 'add' })
}
onMounted(() => {
    getList()
})
</script>
<style scoped lang="scss"></style>