1107 lines
35 KiB
Vue
1107 lines
35 KiB
Vue
<template>
|
||
<a-modal
|
||
:visible="visible"
|
||
:title="getModalTitle()"
|
||
width="1200px"
|
||
:confirm-loading="loading"
|
||
:ok-button-props="{ disabled: !isFormValid || isView }"
|
||
@cancel="handleCancel"
|
||
@ok="handleSubmit"
|
||
>
|
||
<a-form
|
||
ref="formRef"
|
||
:model="formData"
|
||
:rules="rules"
|
||
:label-col="{ span: 6 }"
|
||
:wrapper-col="{ span: 16 }"
|
||
auto-label-width
|
||
>
|
||
<!-- 标签页导航 -->
|
||
<div class="tab-navigation">
|
||
<div
|
||
v-for="tab in tabs"
|
||
:key="tab.key"
|
||
class="tab-item" :class="[{ active: activeTab === tab.key }]"
|
||
@click="activeTab = tab.key"
|
||
>
|
||
{{ tab.label }}
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 标签页内容 -->
|
||
<div class="tab-content">
|
||
<!-- 基本信息 -->
|
||
<div v-show="activeTab === 'basic'">
|
||
<!-- 测试数据按钮 -->
|
||
<div v-if="!isView" class="test-data-section">
|
||
<div class="test-data-header">
|
||
<span class="test-data-title">🧪 测试数据</span>
|
||
<span class="test-data-desc">点击按钮快速填入测试数据,方便功能测试</span>
|
||
</div>
|
||
<a-button
|
||
type="primary"
|
||
size="small"
|
||
@click="fillTestData"
|
||
>
|
||
📝 填入测试数据
|
||
</a-button>
|
||
</div>
|
||
|
||
<a-row :gutter="16">
|
||
<a-col :span="12">
|
||
<a-form-item label="设备名称" field="equipmentName">
|
||
<a-input
|
||
v-model="formData.equipmentName"
|
||
placeholder="请输入设备名称"
|
||
:disabled="isView"
|
||
show-word-limit
|
||
:max-length="200"
|
||
/>
|
||
</a-form-item>
|
||
</a-col>
|
||
<a-col :span="12">
|
||
<a-form-item label="设备类型" field="equipmentType">
|
||
<a-select
|
||
v-model="formData.equipmentType"
|
||
:options="equipmentTypeOptions"
|
||
placeholder="请选择设备类型"
|
||
:disabled="isView"
|
||
/>
|
||
</a-form-item>
|
||
</a-col>
|
||
</a-row>
|
||
|
||
<a-row :gutter="16">
|
||
<a-col :span="12">
|
||
<a-form-item label="设备型号" field="equipmentModel">
|
||
<a-input
|
||
v-model="formData.equipmentModel"
|
||
placeholder="请输入设备型号"
|
||
:disabled="isView"
|
||
show-word-limit
|
||
:max-length="200"
|
||
/>
|
||
</a-form-item>
|
||
</a-col>
|
||
<a-col :span="12">
|
||
<a-form-item label="序列号" field="equipmentSn">
|
||
<a-input
|
||
v-model="formData.equipmentSn"
|
||
placeholder="选择设备类型后自动生成"
|
||
:disabled="true"
|
||
show-word-limit
|
||
:max-length="100"
|
||
/>
|
||
<div class="field-tip">
|
||
<IconInfoCircle style="color: #1890ff; margin-right: 4px;" />
|
||
选择设备类型后自动生成,格式:设备类型+顺序号+日期
|
||
</div>
|
||
</a-form-item>
|
||
</a-col>
|
||
</a-row>
|
||
|
||
<a-row :gutter="16">
|
||
<a-col :span="12">
|
||
<a-form-item label="品牌" field="brand">
|
||
<a-input
|
||
v-model="formData.brand"
|
||
placeholder="请输入品牌"
|
||
:disabled="isView"
|
||
show-word-limit
|
||
:max-length="100"
|
||
/>
|
||
</a-form-item>
|
||
</a-col>
|
||
<a-col :span="12">
|
||
<a-form-item label="资产编号" field="assetCode">
|
||
<a-input
|
||
v-model="formData.assetCode"
|
||
placeholder="请输入资产编号"
|
||
:disabled="isView"
|
||
show-word-limit
|
||
:max-length="50"
|
||
/>
|
||
</a-form-item>
|
||
</a-col>
|
||
</a-row>
|
||
|
||
<a-form-item label="配置规格" field="specification">
|
||
<a-textarea
|
||
v-model="formData.specification"
|
||
placeholder="请输入配置规格参数"
|
||
:disabled="isView"
|
||
:rows="3"
|
||
show-word-limit
|
||
:max-length="500"
|
||
/>
|
||
</a-form-item>
|
||
</div>
|
||
|
||
<!-- 采购信息 -->
|
||
<div v-show="activeTab === 'procurement'">
|
||
<a-row :gutter="16">
|
||
<a-col :span="12">
|
||
<a-form-item label="采购订单" field="purchaseOrder">
|
||
<a-input
|
||
v-model="formData.purchaseOrder"
|
||
placeholder="请输入采购订单号"
|
||
:disabled="isView"
|
||
show-word-limit
|
||
:max-length="100"
|
||
/>
|
||
</a-form-item>
|
||
</a-col>
|
||
<a-col :span="12">
|
||
<a-form-item label="供应商" field="supplierName">
|
||
<a-input
|
||
v-model="formData.supplierName"
|
||
placeholder="请输入供应商名称"
|
||
:disabled="isView"
|
||
show-word-limit
|
||
:max-length="200"
|
||
/>
|
||
</a-form-item>
|
||
</a-col>
|
||
</a-row>
|
||
|
||
<a-row :gutter="16">
|
||
<a-col :span="8">
|
||
<a-form-item label="数量" field="quantity">
|
||
<a-input-number
|
||
v-model="formData.quantity"
|
||
placeholder="请输入数量"
|
||
:min="1"
|
||
:disabled="isView"
|
||
style="width: 100%"
|
||
/>
|
||
</a-form-item>
|
||
</a-col>
|
||
<a-col :span="8">
|
||
<a-form-item label="单价" field="unitPrice">
|
||
<a-input-number
|
||
v-model="formData.unitPrice"
|
||
placeholder="请输入单价"
|
||
:precision="2"
|
||
:min="0"
|
||
:disabled="isView"
|
||
style="width: 100%"
|
||
/>
|
||
</a-form-item>
|
||
</a-col>
|
||
<a-col :span="8">
|
||
<a-form-item label="总价" field="totalPrice">
|
||
<a-input-number
|
||
v-model="formData.totalPrice"
|
||
placeholder="自动计算"
|
||
:precision="2"
|
||
:min="0"
|
||
:disabled="true"
|
||
style="width: 100%"
|
||
/>
|
||
</a-form-item>
|
||
</a-col>
|
||
</a-row>
|
||
|
||
<a-row :gutter="16">
|
||
<a-col :span="12">
|
||
<a-form-item label="采购价格" field="purchasePrice">
|
||
<a-input-number
|
||
v-model="formData.purchasePrice"
|
||
placeholder="请输入采购价格"
|
||
:precision="2"
|
||
:min="0"
|
||
:disabled="isView"
|
||
style="width: 100%"
|
||
/>
|
||
</a-form-item>
|
||
</a-col>
|
||
<a-col :span="12">
|
||
<a-form-item label="当前净值" field="currentNetValue">
|
||
<a-input-number
|
||
v-model="formData.currentNetValue"
|
||
placeholder="请输入当前净值"
|
||
:precision="2"
|
||
:min="0"
|
||
:disabled="isView"
|
||
style="width: 100%"
|
||
/>
|
||
</a-form-item>
|
||
</a-col>
|
||
</a-row>
|
||
|
||
<a-row :gutter="16">
|
||
<a-col :span="12">
|
||
<a-form-item label="采购时间" field="purchaseTime">
|
||
<a-date-picker
|
||
v-model="formData.purchaseTime"
|
||
placeholder="请选择采购时间"
|
||
:disabled="isView"
|
||
show-time
|
||
style="width: 100%"
|
||
format="YYYY-MM-DD HH:mm:ss"
|
||
value-format="YYYY-MM-DD HH:mm:ss"
|
||
/>
|
||
</a-form-item>
|
||
</a-col>
|
||
<a-col :span="12">
|
||
<a-form-item label="入库时间" field="inStockTime">
|
||
<a-date-picker
|
||
v-model="formData.inStockTime"
|
||
placeholder="请选择入库时间"
|
||
:disabled="isView"
|
||
show-time
|
||
style="width: 100%"
|
||
format="YYYY-MM-DD HH:mm:ss"
|
||
value-format="YYYY-MM-DD HH:mm:ss"
|
||
/>
|
||
</a-form-item>
|
||
</a-col>
|
||
</a-row>
|
||
|
||
<a-row :gutter="16">
|
||
<a-col :span="12">
|
||
<a-form-item label="启用时间" field="activationTime">
|
||
<a-date-picker
|
||
v-model="formData.activationTime"
|
||
placeholder="请选择启用时间"
|
||
:disabled="isView"
|
||
show-time
|
||
style="width: 100%"
|
||
format="YYYY-MM-DD HH:mm:ss"
|
||
value-format="YYYY-MM-DD HH:mm:ss"
|
||
/>
|
||
</a-form-item>
|
||
</a-col>
|
||
<a-col :span="12">
|
||
<a-form-item label="预计报废时间" field="expectedScrapTime">
|
||
<a-date-picker
|
||
v-model="formData.expectedScrapTime"
|
||
placeholder="请选择预计报废时间"
|
||
:disabled="isView"
|
||
show-time
|
||
style="width: 100%"
|
||
format="YYYY-MM-DD HH:mm:ss"
|
||
value-format="YYYY-MM-DD HH:mm:ss"
|
||
/>
|
||
</a-form-item>
|
||
</a-col>
|
||
</a-row>
|
||
|
||
<a-row :gutter="16">
|
||
<a-col :span="12">
|
||
<a-form-item label="折旧方法" field="depreciationMethod">
|
||
<a-select
|
||
v-model="formData.depreciationMethod"
|
||
placeholder="请选择折旧方法"
|
||
:disabled="isView"
|
||
>
|
||
<a-option value="straight_line">直线折旧</a-option>
|
||
<a-option value="declining_balance">余额递减</a-option>
|
||
<a-option value="sum_of_years">年数总和</a-option>
|
||
</a-select>
|
||
</a-form-item>
|
||
</a-col>
|
||
<a-col :span="12">
|
||
<a-form-item label="折旧年限" field="depreciationYears">
|
||
<a-input-number
|
||
v-model="formData.depreciationYears"
|
||
placeholder="请输入折旧年限"
|
||
:min="1"
|
||
:max="50"
|
||
:disabled="isView"
|
||
style="width: 100%"
|
||
/>
|
||
</a-form-item>
|
||
</a-col>
|
||
</a-row>
|
||
|
||
<a-row :gutter="16">
|
||
<a-col :span="12">
|
||
<a-form-item label="残值" field="salvageValue">
|
||
<a-input-number
|
||
v-model="formData.salvageValue"
|
||
placeholder="请输入残值"
|
||
:precision="2"
|
||
:min="0"
|
||
:disabled="isView"
|
||
style="width: 100%"
|
||
/>
|
||
</a-form-item>
|
||
</a-col>
|
||
<a-col :span="12">
|
||
<a-form-item label="保修截止日期" field="warrantyExpireDate">
|
||
<a-date-picker
|
||
v-model="formData.warrantyExpireDate"
|
||
placeholder="请选择保修截止日期"
|
||
:disabled="isView"
|
||
show-time
|
||
style="width: 100%"
|
||
format="YYYY-MM-DD HH:mm:ss"
|
||
value-format="YYYY-MM-DD HH:mm:ss"
|
||
/>
|
||
</a-form-item>
|
||
</a-col>
|
||
</a-row>
|
||
</div>
|
||
|
||
<!-- 状态信息 -->
|
||
<div v-show="activeTab === 'status'">
|
||
<a-row :gutter="16">
|
||
<a-col :span="12">
|
||
<a-form-item label="设备状态" field="equipmentStatus">
|
||
<a-select
|
||
v-model="formData.equipmentStatus"
|
||
:options="equipmentStatusOptions"
|
||
placeholder="请选择设备状态"
|
||
:disabled="isView"
|
||
/>
|
||
</a-form-item>
|
||
</a-col>
|
||
<a-col :span="12">
|
||
<a-form-item label="使用状态" field="useStatus">
|
||
<a-select
|
||
v-model="formData.useStatus"
|
||
:options="useStatusOptions"
|
||
placeholder="请选择使用状态"
|
||
:disabled="isView"
|
||
/>
|
||
</a-form-item>
|
||
</a-col>
|
||
</a-row>
|
||
|
||
<a-row :gutter="16">
|
||
<a-col :span="12">
|
||
<a-form-item label="位置状态" field="locationStatus">
|
||
<a-select
|
||
v-model="formData.locationStatus"
|
||
:options="locationStatusOptions"
|
||
placeholder="请选择位置状态"
|
||
:disabled="isView"
|
||
/>
|
||
</a-form-item>
|
||
</a-col>
|
||
<a-col :span="12">
|
||
<a-form-item label="健康状态" field="healthStatus">
|
||
<a-select
|
||
v-model="formData.healthStatus"
|
||
:options="healthStatusOptions"
|
||
placeholder="请选择健康状态"
|
||
:disabled="isView"
|
||
/>
|
||
</a-form-item>
|
||
</a-col>
|
||
</a-row>
|
||
|
||
<a-row :gutter="16">
|
||
<a-col :span="12">
|
||
<a-form-item label="负责人" field="responsiblePerson">
|
||
<a-input
|
||
v-model="formData.responsiblePerson"
|
||
placeholder="请输入负责人"
|
||
:disabled="isView"
|
||
show-word-limit
|
||
:max-length="100"
|
||
/>
|
||
</a-form-item>
|
||
</a-col>
|
||
<a-col :span="12">
|
||
<a-form-item label="维护人员" field="maintenancePerson">
|
||
<a-input
|
||
v-model="formData.maintenancePerson"
|
||
placeholder="请输入维护人员"
|
||
:disabled="isView"
|
||
show-word-limit
|
||
:max-length="100"
|
||
/>
|
||
</a-form-item>
|
||
</a-col>
|
||
</a-row>
|
||
|
||
<a-row :gutter="16">
|
||
<a-col :span="12">
|
||
<a-form-item label="物理位置" field="physicalLocation">
|
||
<a-input
|
||
v-model="formData.physicalLocation"
|
||
placeholder="请输入物理位置"
|
||
:disabled="isView"
|
||
show-word-limit
|
||
:max-length="200"
|
||
/>
|
||
</a-form-item>
|
||
</a-col>
|
||
<a-col :span="12">
|
||
<a-form-item label="库存条码" field="inventoryBarcode">
|
||
<a-input
|
||
v-model="formData.inventoryBarcode"
|
||
placeholder="请输入库存条码"
|
||
:disabled="isView"
|
||
show-word-limit
|
||
:max-length="100"
|
||
/>
|
||
</a-form-item>
|
||
</a-col>
|
||
</a-row>
|
||
|
||
<a-row :gutter="16">
|
||
<a-col :span="12">
|
||
<a-form-item label="上次维护日期" field="lastMaintenanceDate">
|
||
<a-date-picker
|
||
v-model="formData.lastMaintenanceDate"
|
||
placeholder="请选择上次维护日期"
|
||
:disabled="isView"
|
||
show-time
|
||
style="width: 100%"
|
||
format="YYYY-MM-DD HH:mm:ss"
|
||
value-format="YYYY-MM-DD HH:mm:ss"
|
||
/>
|
||
</a-form-item>
|
||
</a-col>
|
||
<a-col :span="12">
|
||
<a-form-item label="下次维护日期" field="nextMaintenanceDate">
|
||
<a-date-picker
|
||
v-model="formData.nextMaintenanceDate"
|
||
placeholder="请选择下次维护日期"
|
||
:disabled="isView"
|
||
show-time
|
||
style="width: 100%"
|
||
format="YYYY-MM-DD HH:mm:ss"
|
||
value-format="YYYY-MM-DD HH:mm:ss"
|
||
/>
|
||
</a-form-item>
|
||
</a-col>
|
||
</a-row>
|
||
</div>
|
||
|
||
<!-- 其他信息 -->
|
||
<div v-show="activeTab === 'other'">
|
||
<a-row :gutter="16">
|
||
<a-col :span="12">
|
||
<a-form-item label="次户号" field="accountNumber">
|
||
<a-input
|
||
v-model="formData.accountNumber"
|
||
placeholder="请输入次户号"
|
||
:disabled="isView"
|
||
show-word-limit
|
||
:max-length="100"
|
||
/>
|
||
</a-form-item>
|
||
</a-col>
|
||
<a-col :span="12">
|
||
<a-form-item label="盘点依据" field="inventoryBasis">
|
||
<a-input
|
||
v-model="formData.inventoryBasis"
|
||
placeholder="请输入盘点依据"
|
||
:disabled="isView"
|
||
show-word-limit
|
||
:max-length="200"
|
||
/>
|
||
</a-form-item>
|
||
</a-col>
|
||
</a-row>
|
||
|
||
<a-form-item label="动态记录" field="dynamicRecord">
|
||
<a-textarea
|
||
v-model="formData.dynamicRecord"
|
||
placeholder="请输入动态记录"
|
||
:disabled="isView"
|
||
:rows="4"
|
||
show-word-limit
|
||
:max-length="1000"
|
||
/>
|
||
</a-form-item>
|
||
|
||
<a-form-item label="资产备注" field="assetRemark">
|
||
<a-textarea
|
||
v-model="formData.assetRemark"
|
||
placeholder="请输入资产备注"
|
||
:disabled="isView"
|
||
:rows="3"
|
||
show-word-limit
|
||
:max-length="500"
|
||
/>
|
||
</a-form-item>
|
||
</div>
|
||
</div>
|
||
</a-form>
|
||
</a-modal>
|
||
</template>
|
||
|
||
<script setup lang="ts">
|
||
import { ref, reactive, computed, watch } from 'vue'
|
||
import { Message } from '@arco-design/web-vue'
|
||
import type { FormInstance } from '@arco-design/web-vue'
|
||
import { equipmentProcurementApi } from '@/apis/equipment/procurement'
|
||
import type { EquipmentResp, EquipmentReq } from '@/apis/equipment/type'
|
||
import { IconInfoCircle } from '@arco-design/web-vue/es/icon'
|
||
|
||
interface Props {
|
||
visible: boolean
|
||
procurementData?: EquipmentResp | null
|
||
mode: 'add' | 'edit' | 'view'
|
||
}
|
||
|
||
interface Emits {
|
||
(e: 'update:visible', value: boolean): void
|
||
(e: 'success'): void
|
||
}
|
||
|
||
const props = withDefaults(defineProps<Props>(), {
|
||
visible: false,
|
||
procurementData: null,
|
||
mode: 'add',
|
||
})
|
||
|
||
const emit = defineEmits<Emits>()
|
||
|
||
const formRef = ref<FormInstance>()
|
||
const loading = ref(false)
|
||
const activeTab = ref('basic')
|
||
|
||
// 标签页配置
|
||
const tabs = [
|
||
{ key: 'basic', label: '基本信息' },
|
||
{ key: 'procurement', label: '采购信息' },
|
||
{ key: 'status', label: '状态信息' },
|
||
{ key: 'other', label: '其他信息' },
|
||
]
|
||
|
||
// 表单数据
|
||
const formData = reactive<EquipmentReq>({
|
||
equipmentName: '',
|
||
equipmentModel: '',
|
||
equipmentType: '',
|
||
equipmentStatus: '',
|
||
useStatus: '',
|
||
equipmentSn: '',
|
||
assetCode: '',
|
||
brand: '',
|
||
specification: '',
|
||
locationStatus: '',
|
||
physicalLocation: '',
|
||
responsiblePerson: '',
|
||
healthStatus: '',
|
||
purchaseTime: '',
|
||
inStockTime: '',
|
||
activationTime: '',
|
||
expectedScrapTime: '',
|
||
actualScrapTime: '',
|
||
purchaseOrder: '',
|
||
supplierName: '',
|
||
purchasePrice: undefined,
|
||
currentNetValue: undefined,
|
||
depreciationMethod: '',
|
||
depreciationYears: undefined,
|
||
salvageValue: undefined,
|
||
warrantyExpireDate: '',
|
||
lastMaintenanceDate: '',
|
||
nextMaintenanceDate: '',
|
||
maintenancePerson: '',
|
||
inventoryBarcode: '',
|
||
assetRemark: '',
|
||
accountNumber: '',
|
||
quantity: 1,
|
||
unitPrice: undefined,
|
||
totalPrice: undefined,
|
||
inventoryBasis: '',
|
||
dynamicRecord: '',
|
||
})
|
||
|
||
// 表单验证规则
|
||
const rules = {
|
||
equipmentName: [{ required: true, message: '请输入设备名称' }],
|
||
equipmentModel: [{ required: true, message: '请输入设备型号' }],
|
||
equipmentType: [{ required: true, message: '请选择设备类型' }],
|
||
equipmentSn: [{ required: true, message: '请输入设备序列号' }],
|
||
equipmentStatus: [{ required: true, message: '请选择设备状态' }],
|
||
useStatus: [{ required: true, message: '请选择使用状态' }],
|
||
purchaseOrder: [{ required: true, message: '请输入采购订单号' }],
|
||
supplierName: [{ required: true, message: '请输入供应商名称' }],
|
||
purchasePrice: [{ required: true, message: '请输入采购价格' }],
|
||
quantity: [{ required: true, message: '请输入数量' }],
|
||
unitPrice: [{ required: true, message: '请输入单价' }],
|
||
totalPrice: [{ required: true, message: '请输入总价' }],
|
||
}
|
||
|
||
// 选项配置
|
||
const equipmentTypeOptions = [
|
||
{ label: '检测设备', value: 'detection' },
|
||
{ label: '安防设备', value: 'security' },
|
||
{ label: '办公设备', value: 'office' },
|
||
{ label: '车辆', value: 'car' },
|
||
{ label: '其他设备', value: 'other' },
|
||
]
|
||
|
||
const equipmentStatusOptions = [
|
||
{ label: '正常', value: 'normal' },
|
||
{ label: '维修中', value: 'repair' },
|
||
{ label: '保养中', value: 'maintain' },
|
||
{ label: '报废', value: 'scrap' },
|
||
]
|
||
|
||
const useStatusOptions = [
|
||
{ label: '空闲中', value: '0' },
|
||
{ label: '使用中', value: '1' },
|
||
]
|
||
|
||
const locationStatusOptions = [
|
||
{ label: '未入库', value: 'not_in_stock' },
|
||
{ label: '库存中', value: 'in_stock' },
|
||
{ label: '已分配', value: 'allocated' },
|
||
{ label: '维修中', value: 'repair' },
|
||
{ label: '待报废', value: 'scrap' },
|
||
{ label: '已报废', value: 'scrapped' },
|
||
{ label: '外借中', value: 'borrowed' },
|
||
{ label: '丢失', value: 'lost' },
|
||
]
|
||
|
||
const healthStatusOptions = [
|
||
{ label: '优秀', value: 'excellent' },
|
||
{ label: '良好', value: 'good' },
|
||
{ label: '一般', value: 'normal' },
|
||
{ label: '较差', value: 'poor' },
|
||
{ label: '危险', value: 'critical' },
|
||
]
|
||
|
||
// 计算属性
|
||
const isView = computed(() => props.mode === 'view')
|
||
const isFormValid = computed(() => {
|
||
return formData.equipmentName &&
|
||
formData.equipmentModel &&
|
||
formData.equipmentType &&
|
||
formData.equipmentSn
|
||
})
|
||
|
||
// 获取弹窗标题
|
||
const getModalTitle = () => {
|
||
const titles = {
|
||
add: '新增采购记录',
|
||
edit: '编辑采购记录',
|
||
view: '查看采购记录',
|
||
}
|
||
return titles[props.mode]
|
||
}
|
||
|
||
// 监听弹窗显示状态
|
||
watch(() => props.visible, (newVal) => {
|
||
if (newVal && props.procurementData) {
|
||
initFormData()
|
||
}
|
||
})
|
||
|
||
// 监听单价和数量变化,自动计算总价
|
||
watch([() => formData.unitPrice, () => formData.quantity], ([newUnitPrice, newQuantity]) => {
|
||
if (newUnitPrice && newQuantity) {
|
||
formData.totalPrice = Number((newUnitPrice * newQuantity).toFixed(2))
|
||
} else {
|
||
formData.totalPrice = undefined
|
||
}
|
||
})
|
||
|
||
// 生成设备序列号
|
||
const generateEquipmentSn = (equipmentType: string) => {
|
||
// 获取当前时间戳作为顺序号
|
||
const timestamp = Date.now()
|
||
const orderNumber = timestamp.toString().slice(-6) // 取后6位作为顺序号
|
||
|
||
// 获取设备类型简称
|
||
const typeMap: Record<string, string> = {
|
||
'detection': 'DET',
|
||
'security': 'SEC',
|
||
'office': 'OFF',
|
||
'car': 'CAR',
|
||
'other': 'OTH'
|
||
}
|
||
const typeCode = typeMap[equipmentType] || 'OTH'
|
||
|
||
// 格式化当前时间(年月日)
|
||
const now = new Date()
|
||
const dateStr = now.getFullYear().toString().slice(-2) +
|
||
(now.getMonth() + 1).toString().padStart(2, '0') +
|
||
now.getDate().toString().padStart(2, '0')
|
||
|
||
// 生成序列号:设备类型+顺序号+当前时间
|
||
return `${typeCode}${orderNumber}${dateStr}`
|
||
}
|
||
|
||
// 监听设备类型变化,自动生成序列号
|
||
watch(() => formData.equipmentType, (newType) => {
|
||
if (newType && !formData.equipmentSn) {
|
||
// 只有在序列号为空时才自动生成
|
||
formData.equipmentSn = generateEquipmentSn(newType)
|
||
}
|
||
})
|
||
|
||
// 初始化表单数据
|
||
const initFormData = () => {
|
||
if (props.procurementData) {
|
||
Object.assign(formData, {
|
||
equipmentName: props.procurementData.equipmentName || '',
|
||
equipmentModel: props.procurementData.equipmentModel || '',
|
||
equipmentType: props.procurementData.equipmentType || '',
|
||
equipmentStatus: props.procurementData.equipmentStatus || '',
|
||
useStatus: props.procurementData.useStatus || '',
|
||
equipmentSn: props.procurementData.equipmentSn || '',
|
||
assetCode: props.procurementData.assetCode || '',
|
||
brand: props.procurementData.brand || '',
|
||
specification: props.procurementData.specification || '',
|
||
locationStatus: props.procurementData.locationStatus || '',
|
||
physicalLocation: props.procurementData.physicalLocation || '',
|
||
responsiblePerson: props.procurementData.responsiblePerson || '',
|
||
healthStatus: props.procurementData.healthStatus || '',
|
||
purchaseTime: props.procurementData.purchaseTime || '',
|
||
inStockTime: props.procurementData.inStockTime || '',
|
||
activationTime: props.procurementData.activationTime || '',
|
||
expectedScrapTime: props.procurementData.expectedScrapTime || '',
|
||
actualScrapTime: props.procurementData.actualScrapTime || '',
|
||
purchaseOrder: props.procurementData.purchaseOrder || '',
|
||
supplierName: props.procurementData.supplierName || '',
|
||
purchasePrice: props.procurementData.purchasePrice,
|
||
currentNetValue: props.procurementData.currentNetValue,
|
||
depreciationMethod: props.procurementData.depreciationMethod || '',
|
||
depreciationYears: props.procurementData.depreciationYears,
|
||
salvageValue: props.procurementData.salvageValue,
|
||
warrantyExpireDate: props.procurementData.warrantyExpireDate || '',
|
||
lastMaintenanceDate: props.procurementData.lastMaintenanceDate || '',
|
||
nextMaintenanceDate: props.procurementData.nextMaintenanceDate || '',
|
||
maintenancePerson: props.procurementData.maintenancePerson || '',
|
||
inventoryBarcode: props.procurementData.inventoryBarcode || '',
|
||
assetRemark: props.procurementData.assetRemark || '',
|
||
accountNumber: props.procurementData.accountNumber || '',
|
||
quantity: props.procurementData.quantity || 1,
|
||
unitPrice: props.procurementData.unitPrice,
|
||
totalPrice: props.procurementData.totalPrice,
|
||
inventoryBasis: props.procurementData.inventoryBasis || '',
|
||
dynamicRecord: props.procurementData.dynamicRecord || '',
|
||
})
|
||
} else {
|
||
resetForm()
|
||
}
|
||
}
|
||
|
||
// 重置表单
|
||
const resetForm = () => {
|
||
Object.assign(formData, {
|
||
equipmentName: '',
|
||
equipmentModel: '',
|
||
equipmentType: '',
|
||
equipmentStatus: '',
|
||
useStatus: '',
|
||
equipmentSn: '',
|
||
assetCode: '',
|
||
brand: '',
|
||
specification: '',
|
||
locationStatus: 'not_in_stock', // 设置默认位置状态为"未入库"
|
||
physicalLocation: '',
|
||
responsiblePerson: '',
|
||
healthStatus: '',
|
||
purchaseTime: '',
|
||
inStockTime: '',
|
||
activationTime: '',
|
||
expectedScrapTime: '',
|
||
actualScrapTime: '',
|
||
purchaseOrder: '',
|
||
supplierName: '',
|
||
purchasePrice: undefined,
|
||
currentNetValue: undefined,
|
||
depreciationMethod: '',
|
||
depreciationYears: undefined,
|
||
salvageValue: undefined,
|
||
warrantyExpireDate: '',
|
||
lastMaintenanceDate: '',
|
||
nextMaintenanceDate: '',
|
||
maintenancePerson: '',
|
||
inventoryBarcode: '',
|
||
assetRemark: '',
|
||
accountNumber: '',
|
||
quantity: 1,
|
||
unitPrice: undefined,
|
||
totalPrice: undefined,
|
||
inventoryBasis: '',
|
||
dynamicRecord: '',
|
||
})
|
||
formRef.value?.resetFields()
|
||
}
|
||
|
||
// 提交表单
|
||
const handleSubmit = async () => {
|
||
try {
|
||
await formRef.value?.validate()
|
||
|
||
loading.value = true
|
||
|
||
if (props.mode === 'edit' && props.procurementData) {
|
||
await equipmentProcurementApi.update(props.procurementData.equipmentId, formData)
|
||
Message.success('更新成功')
|
||
} else {
|
||
await equipmentProcurementApi.add(formData)
|
||
Message.success('新增成功')
|
||
}
|
||
|
||
emit('success')
|
||
} catch (error: any) {
|
||
console.error('操作失败:', error)
|
||
Message.error(error?.message || '操作失败')
|
||
} finally {
|
||
loading.value = false
|
||
}
|
||
}
|
||
|
||
// 填入测试数据
|
||
const fillTestData = () => {
|
||
// 生成当前时间
|
||
const now = new Date()
|
||
const currentTime = now.toISOString().slice(0, 19).replace('T', ' ')
|
||
|
||
// 生成未来时间(预计报废时间)
|
||
const futureDate = new Date(now.getTime() + 365 * 24 * 60 * 60 * 1000) // 一年后
|
||
const futureTime = futureDate.toISOString().slice(0, 19).replace('T', ' ')
|
||
|
||
// 生成过去时间(采购时间等)
|
||
const pastDate = new Date(now.getTime() - 30 * 24 * 60 * 60 * 1000) // 30天前
|
||
const pastTime = pastDate.toISOString().slice(0, 19).replace('T', ' ')
|
||
|
||
// 生成入库时间(采购后7天)
|
||
const inStockDate = new Date(pastDate.getTime() + 7 * 24 * 60 * 60 * 1000)
|
||
const inStockTime = inStockDate.toISOString().slice(0, 19).replace('T', ' ')
|
||
|
||
// 生成启用时间(入库后3天)
|
||
const activationDate = new Date(inStockDate.getTime() + 3 * 24 * 60 * 60 * 1000)
|
||
const activationTime = activationDate.toISOString().slice(0, 19).replace('T', ' ')
|
||
|
||
// 生成保修截止时间(采购后2年)
|
||
const warrantyDate = new Date(pastDate.getTime() + 2 * 365 * 24 * 60 * 60 * 1000)
|
||
const warrantyTime = warrantyDate.toISOString().slice(0, 19).replace('T', ' ')
|
||
|
||
// 生成维护时间
|
||
const lastMaintenanceDate = new Date(now.getTime() - 15 * 24 * 60 * 60 * 1000) // 15天前
|
||
const lastMaintenanceTime = lastMaintenanceDate.toISOString().slice(0, 19).replace('T', ' ')
|
||
|
||
const nextMaintenanceDate = new Date(now.getTime() + 15 * 24 * 60 * 60 * 1000) // 15天后
|
||
const nextMaintenanceTime = nextMaintenanceDate.toISOString().slice(0, 19).replace('T', ' ')
|
||
|
||
// 生成随机序列号
|
||
const randomSn = generateEquipmentSn('detection')
|
||
|
||
// 生成随机资产编号
|
||
const randomAssetCode = 'ZC' + Math.random().toString(36).substr(2, 6).toUpperCase()
|
||
|
||
// 生成随机采购订单号
|
||
const randomPurchaseOrder = 'PO' + Math.random().toString(36).substr(2, 8).toUpperCase()
|
||
|
||
// 生成随机库存条码
|
||
const randomBarcode = 'BC' + Math.random().toString(36).substr(2, 10).toUpperCase()
|
||
|
||
// 生成随机次户号
|
||
const randomAccountNumber = 'AC' + Math.random().toString(36).substr(2, 6).toUpperCase()
|
||
|
||
// 先设置单价和数量,让监听器自动计算总价
|
||
formData.unitPrice = 8999.00
|
||
formData.quantity = 2
|
||
|
||
Object.assign(formData, {
|
||
// 基本信息
|
||
equipmentName: '高清工业相机系统',
|
||
equipmentModel: 'IC-2000Pro',
|
||
equipmentType: 'detection',
|
||
equipmentSn: randomSn,
|
||
brand: '海康威视',
|
||
assetCode: randomAssetCode,
|
||
specification: '分辨率:4K,帧率:60fps,接口:USB3.0,支持AI识别,防水等级IP67',
|
||
|
||
// 采购信息
|
||
purchaseOrder: randomPurchaseOrder,
|
||
supplierName: '海康威视官方旗舰店',
|
||
// quantity 和 unitPrice 已在上方设置,totalPrice 将由监听器自动计算
|
||
purchasePrice: 17998.00,
|
||
currentNetValue: 17998.00,
|
||
depreciationMethod: 'straight_line',
|
||
depreciationYears: 5,
|
||
salvageValue: 899.90,
|
||
|
||
// 时间信息
|
||
purchaseTime: pastTime,
|
||
inStockTime: inStockTime,
|
||
activationTime: activationTime,
|
||
expectedScrapTime: futureTime,
|
||
warrantyExpireDate: warrantyTime,
|
||
lastMaintenanceDate: lastMaintenanceTime,
|
||
nextMaintenanceDate: nextMaintenanceTime,
|
||
|
||
// 状态信息
|
||
equipmentStatus: 'normal',
|
||
useStatus: '1',
|
||
locationStatus: 'in_stock',
|
||
healthStatus: 'excellent',
|
||
responsiblePerson: '张工程师',
|
||
maintenancePerson: '李维护员',
|
||
physicalLocation: 'A区-3楼-设备间-01号柜',
|
||
inventoryBarcode: randomBarcode,
|
||
|
||
// 其他信息
|
||
accountNumber: randomAccountNumber,
|
||
inventoryBasis: '月度盘点',
|
||
dynamicRecord: '设备运行正常,定期维护保养,性能稳定,满足生产需求。',
|
||
assetRemark: '重要检测设备,需定期校准,专人负责维护。',
|
||
})
|
||
|
||
Message.success('测试数据已填入!')
|
||
}
|
||
|
||
// 取消
|
||
const handleCancel = () => {
|
||
emit('update:visible', false)
|
||
resetForm()
|
||
}
|
||
</script>
|
||
|
||
<style scoped lang="scss">
|
||
.tab-navigation {
|
||
display: flex;
|
||
border-bottom: 1px solid var(--color-border);
|
||
margin-bottom: 24px;
|
||
|
||
.tab-item {
|
||
padding: 12px 24px;
|
||
cursor: pointer;
|
||
border-bottom: 2px solid transparent;
|
||
transition: all 0.3s ease;
|
||
font-weight: 500;
|
||
color: var(--color-text-2);
|
||
|
||
&:hover {
|
||
color: var(--color-primary);
|
||
}
|
||
|
||
&.active {
|
||
color: var(--color-primary);
|
||
border-bottom-color: var(--color-primary);
|
||
}
|
||
}
|
||
}
|
||
|
||
.tab-content {
|
||
.arco-form-item {
|
||
margin-bottom: 24px;
|
||
|
||
.arco-form-item-label {
|
||
font-weight: 500;
|
||
color: var(--color-text-1);
|
||
margin-bottom: 8px;
|
||
}
|
||
|
||
.field-tip {
|
||
margin-top: 4px;
|
||
font-size: 12px;
|
||
color: var(--color-text-3);
|
||
display: flex;
|
||
align-items: center;
|
||
line-height: 1.4;
|
||
}
|
||
}
|
||
|
||
.arco-input,
|
||
.arco-select,
|
||
.arco-input-number,
|
||
.arco-date-picker {
|
||
border-radius: 6px;
|
||
border: 1px solid var(--color-border);
|
||
transition: all 0.2s ease;
|
||
|
||
&:hover {
|
||
border-color: var(--color-primary-light-3);
|
||
}
|
||
|
||
&:focus,
|
||
&.arco-input-focus,
|
||
&.arco-select-focus {
|
||
border-color: var(--color-primary);
|
||
box-shadow: 0 0 0 2px rgba(var(--primary-6), 0.1);
|
||
}
|
||
}
|
||
|
||
.arco-textarea {
|
||
border-radius: 6px;
|
||
border: 1px solid var(--color-border);
|
||
transition: all 0.2s ease;
|
||
|
||
&:hover {
|
||
border-color: var(--color-primary-light-3);
|
||
}
|
||
|
||
&:focus,
|
||
&.arco-textarea-focus {
|
||
border-color: var(--color-primary);
|
||
box-shadow: 0 0 0 2px rgba(var(--primary-6), 0.1);
|
||
}
|
||
}
|
||
}
|
||
|
||
// 测试数据区域样式
|
||
.test-data-section {
|
||
background: linear-gradient(135deg, #f0f9ff 0%, #e0f2fe 100%);
|
||
border: 1px solid #bae6fd;
|
||
border-radius: 8px;
|
||
padding: 12px 16px;
|
||
margin-bottom: 20px;
|
||
|
||
.test-data-header {
|
||
display: flex;
|
||
flex-direction: column;
|
||
margin-bottom: 12px;
|
||
|
||
.test-data-title {
|
||
font-weight: 600;
|
||
color: #1e40af;
|
||
font-size: 14px;
|
||
margin-bottom: 4px;
|
||
}
|
||
|
||
.test-data-desc {
|
||
color: #64748b;
|
||
font-size: 12px;
|
||
line-height: 1.4;
|
||
}
|
||
}
|
||
|
||
.arco-btn {
|
||
background: linear-gradient(135deg, #3b82f6 0%, #1d4ed8 100%);
|
||
border: none;
|
||
color: white;
|
||
font-weight: 500;
|
||
box-shadow: 0 2px 4px rgba(59, 130, 246, 0.3);
|
||
transition: all 0.3s ease;
|
||
|
||
&:hover {
|
||
transform: translateY(-1px);
|
||
box-shadow: 0 4px 8px rgba(59, 130, 246, 0.4);
|
||
}
|
||
|
||
&:active {
|
||
transform: translateY(0);
|
||
}
|
||
}
|
||
}
|
||
|
||
// 响应式设计
|
||
@media (max-width: 768px) {
|
||
.tab-navigation {
|
||
.tab-item {
|
||
padding: 8px 16px;
|
||
font-size: 14px;
|
||
}
|
||
}
|
||
|
||
.tab-content {
|
||
.arco-row {
|
||
.arco-col {
|
||
margin-bottom: 16px;
|
||
}
|
||
}
|
||
}
|
||
|
||
.test-data-section {
|
||
padding: 8px 12px;
|
||
margin-bottom: 16px;
|
||
}
|
||
}
|
||
</style> |