|
@@ -0,0 +1,515 @@
|
|
|
+<template>
|
|
|
+ <div class="p-6">
|
|
|
+ <!-- 头部操作区 -->
|
|
|
+ <div class="bg-white rounded-lg shadow p-6 mb-6">
|
|
|
+ <div class="flex justify-between items-center">
|
|
|
+ <h2 class="text-2xl font-bold text-gray-800">原料品类管理</h2>
|
|
|
+ <div class="flex space-x-4">
|
|
|
+ <button
|
|
|
+ @click="showAddDialog = true"
|
|
|
+ class="flex items-center px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors"
|
|
|
+ >
|
|
|
+ <PlusIcon class="w-5 h-5 mr-2" />
|
|
|
+ 新增
|
|
|
+ </button>
|
|
|
+ <button
|
|
|
+ @click="handleExport"
|
|
|
+ class="flex items-center px-4 py-2 bg-green-600 text-white rounded-lg hover:bg-green-700 transition-colors"
|
|
|
+ >
|
|
|
+ <DownloadIcon class="w-5 h-5 mr-2" />
|
|
|
+ 导出
|
|
|
+ </button>
|
|
|
+ <div class="relative">
|
|
|
+ <input
|
|
|
+ type="file"
|
|
|
+ class="hidden"
|
|
|
+ ref="fileInput"
|
|
|
+ @change="handleFileChange"
|
|
|
+ />
|
|
|
+ <button
|
|
|
+ @click="$refs.fileInput.click()"
|
|
|
+ class="flex items-center px-4 py-2 bg-purple-600 text-white rounded-lg hover:bg-purple-700 transition-colors"
|
|
|
+ >
|
|
|
+ <UploadIcon class="w-5 h-5 mr-2" />
|
|
|
+ 导入
|
|
|
+ </button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 筛选区 -->
|
|
|
+ <div class="bg-white rounded-lg shadow p-6 mb-6">
|
|
|
+ <div class="flex flex-wrap gap-4">
|
|
|
+ <div class="relative flex-1 min-w-[200px]">
|
|
|
+ <SearchIcon class="absolute left-3 top-1/2 transform -translate-y-1/2 w-5 h-5 text-gray-400" />
|
|
|
+ <input
|
|
|
+ v-model="searchQuery.materialCode"
|
|
|
+ type="text"
|
|
|
+ placeholder="物料编码"
|
|
|
+ class="w-full pl-10 pr-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500"
|
|
|
+ @input="handleSearch"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ <div class="relative flex-1 min-w-[200px]">
|
|
|
+ <SearchIcon class="absolute left-3 top-1/2 transform -translate-y-1/2 w-5 h-5 text-gray-400" />
|
|
|
+ <input
|
|
|
+ v-model="searchQuery.materialGroup"
|
|
|
+ type="text"
|
|
|
+ placeholder="物料组"
|
|
|
+ class="w-full pl-10 pr-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500"
|
|
|
+ @input="handleSearch"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ <div class="relative flex-1 min-w-[200px]">
|
|
|
+ <SearchIcon class="absolute left-3 top-1/2 transform -translate-y-1/2 w-5 h-5 text-gray-400" />
|
|
|
+ <input
|
|
|
+ v-model="searchQuery.categoryOne"
|
|
|
+ type="text"
|
|
|
+ placeholder="类别一"
|
|
|
+ class="w-full pl-10 pr-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500"
|
|
|
+ @input="handleSearch"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ <div class="relative flex-1 min-w-[200px]">
|
|
|
+ <SearchIcon class="absolute left-3 top-1/2 transform -translate-y-1/2 w-5 h-5 text-gray-400" />
|
|
|
+ <input
|
|
|
+ v-model="searchQuery.categoryTwo"
|
|
|
+ type="text"
|
|
|
+ placeholder="类别二"
|
|
|
+ class="w-full pl-10 pr-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500"
|
|
|
+ @input="handleSearch"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ <div class="relative flex-1 min-w-[200px]">
|
|
|
+ <SearchIcon class="absolute left-3 top-1/2 transform -translate-y-1/2 w-5 h-5 text-gray-400" />
|
|
|
+ <input
|
|
|
+ v-model="searchQuery.rawMaterialCategory"
|
|
|
+ type="text"
|
|
|
+ placeholder="原料大类"
|
|
|
+ class="w-full pl-10 pr-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500"
|
|
|
+ @input="handleSearch"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ <div class="flex items-center space-x-2">
|
|
|
+ <button
|
|
|
+ @click="resetFilters"
|
|
|
+ class="px-4 py-2 bg-gray-600 text-white rounded-lg hover:bg-gray-700"
|
|
|
+ >
|
|
|
+ 重置
|
|
|
+ </button>
|
|
|
+ <button
|
|
|
+ @click="handleSearch"
|
|
|
+ class="px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700"
|
|
|
+ >
|
|
|
+ 查询
|
|
|
+ </button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 原料品类列表 -->
|
|
|
+ <div class="bg-white rounded-lg shadow overflow-hidden">
|
|
|
+ <div class="overflow-x-auto">
|
|
|
+ <table class="min-w-full divide-y divide-gray-200">
|
|
|
+ <thead class="bg-gray-50">
|
|
|
+ <tr>
|
|
|
+ <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
|
|
|
+ <input
|
|
|
+ type="checkbox"
|
|
|
+ v-model="selectAll"
|
|
|
+ class="rounded border-gray-300 text-blue-600 focus:ring-blue-500"
|
|
|
+ />
|
|
|
+ </th>
|
|
|
+ <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
|
|
|
+ 序号
|
|
|
+ </th>
|
|
|
+ <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
|
|
|
+ 物料编码
|
|
|
+ </th>
|
|
|
+ <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
|
|
|
+ 物料组
|
|
|
+ </th>
|
|
|
+ <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
|
|
|
+ 类别一
|
|
|
+ </th>
|
|
|
+ <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
|
|
|
+ 类别二
|
|
|
+ </th>
|
|
|
+ <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
|
|
|
+ 原料大类
|
|
|
+ </th>
|
|
|
+ <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
|
|
|
+ 操作
|
|
|
+ </th>
|
|
|
+ </tr>
|
|
|
+ </thead>
|
|
|
+ <tbody class="bg-white divide-y divide-gray-200">
|
|
|
+ <tr v-for="(rawMaterial, index) in filteredRawMaterials" :key="rawMaterial.id" class="hover:bg-gray-50">
|
|
|
+ <td class="px-6 py-4 whitespace-nowrap">
|
|
|
+ <input
|
|
|
+ type="checkbox"
|
|
|
+ v-model="selectedItems"
|
|
|
+ :value="rawMaterial.id"
|
|
|
+ class="rounded border-gray-300 text-blue-600 focus:ring-blue-500"
|
|
|
+ />
|
|
|
+ </td>
|
|
|
+ <td class="px-6 py-4 whitespace-nowrap">{{ index + 1 }}</td>
|
|
|
+ <td class="px-6 py-4 whitespace-nowrap">{{ rawMaterial.materialCode }}</td>
|
|
|
+ <td class="px-6 py-4 whitespace-nowrap">{{ rawMaterial.materialGroup }}</td>
|
|
|
+ <td class="px-6 py-4 whitespace-nowrap">{{ rawMaterial.categoryOne }}</td>
|
|
|
+ <td class="px-6 py-4 whitespace-nowrap">{{ rawMaterial.categoryTwo }}</td>
|
|
|
+ <td class="px-6 py-4 whitespace-nowrap">{{ rawMaterial.rawMaterialCategory }}</td>
|
|
|
+ <td class="px-6 py-4 whitespace-nowrap">
|
|
|
+ <div class="flex space-x-2">
|
|
|
+ <button
|
|
|
+ @click="handleEdit(rawMaterial)"
|
|
|
+ class="px-3 py-1 text-sm text-green-600 hover:text-green-800"
|
|
|
+ >
|
|
|
+ 修改
|
|
|
+ </button>
|
|
|
+ <button
|
|
|
+ @click="handleDelete(rawMaterial)"
|
|
|
+ class="px-3 py-1 text-sm text-red-600 hover:text-red-800"
|
|
|
+ >
|
|
|
+ 删除
|
|
|
+ </button>
|
|
|
+ </div>
|
|
|
+ </td>
|
|
|
+ </tr>
|
|
|
+ </tbody>
|
|
|
+ </table>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 批量操作 -->
|
|
|
+ <div v-if="selectedItems.length > 0" class="px-6 py-4 bg-gray-50 border-t border-gray-200">
|
|
|
+ <div class="flex items-center justify-between">
|
|
|
+ <span class="text-sm text-gray-600">已选择 {{ selectedItems.length }} 项</span>
|
|
|
+ <div class="flex space-x-4">
|
|
|
+ <button
|
|
|
+ @click="handleBatchEdit"
|
|
|
+ class="flex items-center px-4 py-2 text-sm text-blue-600 hover:text-blue-800"
|
|
|
+ >
|
|
|
+ <EditIcon class="w-4 h-4 mr-1" />
|
|
|
+ 批量修改
|
|
|
+ </button>
|
|
|
+ <button
|
|
|
+ @click="handleBatchDelete"
|
|
|
+ class="flex items-center px-4 py-2 text-sm text-red-600 hover:text-red-800"
|
|
|
+ >
|
|
|
+ <TrashIcon class="w-4 h-4 mr-1" />
|
|
|
+ 批量删除
|
|
|
+ </button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 分页 -->
|
|
|
+ <div class="px-6 py-4 bg-gray-50 border-t border-gray-200">
|
|
|
+ <div class="flex items-center justify-between">
|
|
|
+ <div class="flex items-center">
|
|
|
+ <span class="text-sm text-gray-700 mr-4">每页显示</span>
|
|
|
+ <select
|
|
|
+ v-model="pageSize"
|
|
|
+ class="px-2 py-1 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
|
|
+ @change="handleSizeChange"
|
|
|
+ >
|
|
|
+ <option v-for="size in [10, 20, 50, 100]" :key="size" :value="size">
|
|
|
+ {{ size }}
|
|
|
+ </option>
|
|
|
+ </select>
|
|
|
+ </div>
|
|
|
+ <div class="flex items-center space-x-2">
|
|
|
+ <button
|
|
|
+ @click="currentPage--"
|
|
|
+ :disabled="currentPage === 1"
|
|
|
+ class="px-3 py-1 border border-gray-300 rounded-md disabled:opacity-50"
|
|
|
+ >
|
|
|
+ <ChevronLeftIcon class="w-4 h-4" />
|
|
|
+ </button>
|
|
|
+ <span class="text-sm text-gray-700">
|
|
|
+ 第 {{ currentPage }} 页 / 共 {{ totalPages }} 页
|
|
|
+ </span>
|
|
|
+ <button
|
|
|
+ @click="currentPage++"
|
|
|
+ :disabled="currentPage === totalPages"
|
|
|
+ class="px-3 py-1 border border-gray-300 rounded-md disabled:opacity-50"
|
|
|
+ >
|
|
|
+ <ChevronRightIcon class="w-4 h-4" />
|
|
|
+ </button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 新增/编辑原料品类对话框 -->
|
|
|
+ <div v-if="showAddDialog" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center">
|
|
|
+ <div class="bg-white rounded-lg shadow-xl w-1/2 max-w-2xl">
|
|
|
+ <div class="flex justify-between items-center p-6 border-b">
|
|
|
+ <h3 class="text-lg font-semibold">{{ isEdit ? '编辑原料品类' : '新增原料品类' }}</h3>
|
|
|
+ <button @click="showAddDialog = false" class="text-gray-400 hover:text-gray-500">
|
|
|
+ <XIcon class="w-5 h-5" />
|
|
|
+ </button>
|
|
|
+ </div>
|
|
|
+ <form @submit.prevent="handleSubmit" class="p-6">
|
|
|
+ <div class="grid grid-cols-2 gap-6">
|
|
|
+ <div>
|
|
|
+ <label class="block text-sm font-medium text-gray-700 mb-1">物料编码</label>
|
|
|
+ <input
|
|
|
+ v-model="addForm.materialCode"
|
|
|
+ type="text"
|
|
|
+ class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
|
|
+ required
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ <div>
|
|
|
+ <label class="block text-sm font-medium text-gray-700 mb-1">物料组</label>
|
|
|
+ <input
|
|
|
+ v-model="addForm.materialGroup"
|
|
|
+ type="text"
|
|
|
+ class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
|
|
+ required
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ <div>
|
|
|
+ <label class="block text-sm font-medium text-gray-700 mb-1">类别一</label>
|
|
|
+ <input
|
|
|
+ v-model="addForm.categoryOne"
|
|
|
+ type="text"
|
|
|
+ class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
|
|
+ required
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ <div>
|
|
|
+ <label class="block text-sm font-medium text-gray-700 mb-1">类别二</label>
|
|
|
+ <input
|
|
|
+ v-model="addForm.categoryTwo"
|
|
|
+ type="text"
|
|
|
+ class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
|
|
+ required
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ <div>
|
|
|
+ <label class="block text-sm font-medium text-gray-700 mb-1">原料大类</label>
|
|
|
+ <input
|
|
|
+ v-model="addForm.rawMaterialCategory"
|
|
|
+ type="text"
|
|
|
+ class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
|
|
+ required
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="mt-6 flex justify-end space-x-4">
|
|
|
+ <button
|
|
|
+ type="button"
|
|
|
+ @click="showAddDialog = false"
|
|
|
+ class="px-4 py-2 border border-gray-300 rounded-md text-gray-700 hover:bg-gray-50"
|
|
|
+ >
|
|
|
+ 取消
|
|
|
+ </button>
|
|
|
+ <button
|
|
|
+ type="submit"
|
|
|
+ class="px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700"
|
|
|
+ >
|
|
|
+ 确定
|
|
|
+ </button>
|
|
|
+ </div>
|
|
|
+ </form>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script setup>
|
|
|
+import { ref, computed, onMounted, onUnmounted, watch, nextTick } from 'vue'
|
|
|
+import { useRouter } from 'vue-router'
|
|
|
+import {
|
|
|
+ PlusIcon,
|
|
|
+ DownloadIcon,
|
|
|
+ UploadIcon,
|
|
|
+ SearchIcon,
|
|
|
+ ChevronUpIcon,
|
|
|
+ ChevronDownIcon,
|
|
|
+ EditIcon,
|
|
|
+ TrashIcon,
|
|
|
+ ChevronLeftIcon,
|
|
|
+ ChevronRightIcon,
|
|
|
+ XIcon,
|
|
|
+} from 'lucide-vue-next'
|
|
|
+
|
|
|
+const router = useRouter()
|
|
|
+
|
|
|
+// Mock 数据
|
|
|
+const mockData = {
|
|
|
+ rawMaterials: {
|
|
|
+ list: [
|
|
|
+ {
|
|
|
+ id: 1,
|
|
|
+ materialCode: 'RM001',
|
|
|
+ materialGroup: 'MG001',
|
|
|
+ categoryOne: 'C1',
|
|
|
+ categoryTwo: 'C2',
|
|
|
+ rawMaterialCategory: 'RMC1'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ id: 2,
|
|
|
+ materialCode: 'RM002',
|
|
|
+ materialGroup: 'MG002',
|
|
|
+ categoryOne: 'C1',
|
|
|
+ categoryTwo: 'C2',
|
|
|
+ rawMaterialCategory: 'RMC2'
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ total: 2
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// 状态管理
|
|
|
+const loading = ref(false)
|
|
|
+const searchQuery = ref({
|
|
|
+ materialCode: '',
|
|
|
+ materialGroup: '',
|
|
|
+ categoryOne: '',
|
|
|
+ categoryTwo: '',
|
|
|
+ rawMaterialCategory: ''
|
|
|
+})
|
|
|
+const currentPage = ref(1)
|
|
|
+const pageSize = ref(10)
|
|
|
+const total = ref(0)
|
|
|
+const selectedItems = ref([])
|
|
|
+const showAddDialog = ref(false)
|
|
|
+const isEdit = ref(false)
|
|
|
+const sortKey = ref('')
|
|
|
+const sortOrder = ref('asc')
|
|
|
+
|
|
|
+// 计算属性
|
|
|
+const filteredRawMaterials = computed(() => {
|
|
|
+ return mockData.rawMaterials.list.filter(rawMaterial => {
|
|
|
+ return (
|
|
|
+ (!searchQuery.value.materialCode || rawMaterial.materialCode.includes(searchQuery.value.materialCode)) &&
|
|
|
+ (!searchQuery.value.materialGroup || rawMaterial.materialGroup.includes(searchQuery.value.materialGroup)) &&
|
|
|
+ (!searchQuery.value.categoryOne || rawMaterial.categoryOne.includes(searchQuery.value.categoryOne)) &&
|
|
|
+ (!searchQuery.value.categoryTwo || rawMaterial.categoryTwo.includes(searchQuery.value.categoryTwo)) &&
|
|
|
+ (!searchQuery.value.rawMaterialCategory || rawMaterial.rawMaterialCategory.includes(searchQuery.value.rawMaterialCategory))
|
|
|
+ )
|
|
|
+ })
|
|
|
+})
|
|
|
+
|
|
|
+const totalPages = computed(() => {
|
|
|
+ return Math.ceil(total.value / pageSize.value)
|
|
|
+})
|
|
|
+
|
|
|
+const selectAll = computed({
|
|
|
+ get: () => selectedItems.value.length === filteredRawMaterials.value.length,
|
|
|
+ set: (value) => {
|
|
|
+ selectedItems.value = value ? filteredRawMaterials.value.map(r => r.id) : []
|
|
|
+ }
|
|
|
+})
|
|
|
+
|
|
|
+// 方法
|
|
|
+const handleSearch = () => {
|
|
|
+ currentPage.value = 1
|
|
|
+ fetchRawMaterials()
|
|
|
+}
|
|
|
+
|
|
|
+const resetFilters = () => {
|
|
|
+ searchQuery.value = {
|
|
|
+ materialCode: '',
|
|
|
+ materialGroup: '',
|
|
|
+ categoryOne: '',
|
|
|
+ categoryTwo: '',
|
|
|
+ rawMaterialCategory: ''
|
|
|
+ }
|
|
|
+ handleSearch()
|
|
|
+}
|
|
|
+
|
|
|
+const handleSort = (prop) => {
|
|
|
+ if (sortKey.value === prop) {
|
|
|
+ sortOrder.value = sortOrder.value === 'asc' ? 'desc' : 'asc'
|
|
|
+ } else {
|
|
|
+ sortKey.value = prop
|
|
|
+ sortOrder.value = 'asc'
|
|
|
+ }
|
|
|
+ const sortedRawMaterials = [...filteredRawMaterials.value]
|
|
|
+ sortedRawMaterials.sort((a, b) => {
|
|
|
+ const aValue = a[prop]
|
|
|
+ const bValue = b[prop]
|
|
|
+ if (sortOrder.value === 'asc') {
|
|
|
+ return aValue > bValue ? 1 : -1
|
|
|
+ } else {
|
|
|
+ return aValue < bValue ? 1 : -1
|
|
|
+ }
|
|
|
+ })
|
|
|
+ filteredRawMaterials.value = sortedRawMaterials
|
|
|
+}
|
|
|
+
|
|
|
+const handleSizeChange = () => {
|
|
|
+ currentPage.value = 1
|
|
|
+ fetchRawMaterials()
|
|
|
+}
|
|
|
+
|
|
|
+const handleFileChange = (event) => {
|
|
|
+ const file = event.target.files[0]
|
|
|
+ if (file) {
|
|
|
+ // 处理文件上传
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+const handleExport = () => {
|
|
|
+ // 实现导出逻辑
|
|
|
+}
|
|
|
+
|
|
|
+const handleBatchEdit = () => {
|
|
|
+ // 实现批量编辑逻辑
|
|
|
+}
|
|
|
+
|
|
|
+const handleBatchDelete = () => {
|
|
|
+ // 实现批量删除逻辑
|
|
|
+}
|
|
|
+
|
|
|
+const handleEdit = (rawMaterial) => {
|
|
|
+ isEdit.value = true
|
|
|
+ addForm.value = { ...rawMaterial }
|
|
|
+ showAddDialog.value = true
|
|
|
+}
|
|
|
+
|
|
|
+const handleDelete = (rawMaterial) => {
|
|
|
+ // 实现删除逻辑
|
|
|
+}
|
|
|
+
|
|
|
+const handleSubmit = () => {
|
|
|
+ // 实现表单提交逻辑
|
|
|
+}
|
|
|
+
|
|
|
+// 数据获取
|
|
|
+const fetchRawMaterials = async () => {
|
|
|
+ try {
|
|
|
+ loading.value = true
|
|
|
+ // 模拟网络延迟
|
|
|
+ await new Promise(resolve => setTimeout(resolve, 500))
|
|
|
+ total.value = mockData.rawMaterials.total
|
|
|
+ } catch (error) {
|
|
|
+ console.error('获取数据失败:', error)
|
|
|
+ } finally {
|
|
|
+ loading.value = false
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// 生命周期钩子
|
|
|
+onMounted(() => {
|
|
|
+ fetchRawMaterials()
|
|
|
+})
|
|
|
+
|
|
|
+onUnmounted(() => {
|
|
|
+ // 清理工作
|
|
|
+})
|
|
|
+
|
|
|
+// 表单数据
|
|
|
+const addForm = ref({
|
|
|
+ materialCode: '',
|
|
|
+ materialGroup: '',
|
|
|
+ categoryOne: '',
|
|
|
+ categoryTwo: '',
|
|
|
+ rawMaterialCategory: ''
|
|
|
+})
|
|
|
+</script>
|