|
@@ -1,188 +1,245 @@
|
|
<template>
|
|
<template>
|
|
- <div class="container mx-auto px-4">
|
|
|
|
- <header class="bg-gray-800 text-white p-4 flex justify-between items-center">
|
|
|
|
- <h1 class="text-2xl">原料品类管理</h1>
|
|
|
|
- <div>
|
|
|
|
- <a href="#/add-raw-material" class="mr-2"><button class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">新增</button></a>
|
|
|
|
- <a href="#/edit-raw-material" class="mr-2"><button class="bg-green-500 hover:bg-green-700 text-white font-bold py-2 px-4 rounded">修改</button></a>
|
|
|
|
- <a href="#" @click.prevent="deleteSelected" class="mr-2"><button class="bg-red-500 hover:bg-red-700 text-white font-bold py-2 px-4 rounded">删除</button></a>
|
|
|
|
- <a href="#" @click.prevent="exportData" class="mr-2"><button class="bg-purple-500 hover:bg-purple-700 text-white font-bold py-2 px-4 rounded">导出</button></a>
|
|
|
|
- <a href="#" @click.prevent="importData" class="mr-2"><button class="bg-teal-500 hover:bg-teal-700 text-white font-bold py-2 px-4 rounded">导入</button></a>
|
|
|
|
|
|
+ <div class="min-h-screen bg-gray-100 dark:bg-gray-900">
|
|
|
|
+ <!-- 顶部导航 -->
|
|
|
|
+ <div class="bg-white dark:bg-gray-800 shadow">
|
|
|
|
+ <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
|
|
|
+ <div class="flex justify-between h-16">
|
|
|
|
+ <div class="flex">
|
|
|
|
+ <div class="flex-shrink-0 flex items-center">
|
|
|
|
+ <h1 class="text-xl font-bold text-gray-900 dark:text-white">原料品类管理</h1>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ <div class="flex items-center space-x-4">
|
|
|
|
+ <a href="#/raw-material-category/add" class="btn-primary">
|
|
|
|
+ 新增
|
|
|
|
+ </a>
|
|
|
|
+ <button @click="exportData" class="btn-secondary">
|
|
|
|
+ 导出数据
|
|
|
|
+ </button>
|
|
|
|
+ <a href="#/raw-material-category/import" class="btn-secondary">
|
|
|
|
+ 导入数据
|
|
|
|
+ </a>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
</div>
|
|
</div>
|
|
- </header>
|
|
|
|
-
|
|
|
|
- <section class="mt-4">
|
|
|
|
- <div class="mb-4">
|
|
|
|
- <input v-model="search.materialCode" placeholder="物料编码" class="border p-2 mr-2" />
|
|
|
|
- <input v-model="search.materialGroup" placeholder="物料组" class="border p-2 mr-2" />
|
|
|
|
- <input v-model="search.categoryOne" placeholder="类别一" class="border p-2 mr-2" />
|
|
|
|
- <input v-model="search.categoryTwo" placeholder="类别二" class="border p-2 mr-2" />
|
|
|
|
- <input v-model="search.rawMaterialClass" placeholder="原料大类" class="border p-2 mr-2" />
|
|
|
|
- <button @click="resetSearch" class="bg-gray-500 hover:bg-gray-700 text-white font-bold py-2 px-4 rounded mr-2">重置</button>
|
|
|
|
- <button @click="performSearch" class="bg-gray-500 hover:bg-gray-700 text-white font-bold py-2 px-4 rounded">查询</button>
|
|
|
|
|
|
+ </div>
|
|
|
|
+
|
|
|
|
+ <!-- 主要内容 -->
|
|
|
|
+ <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
|
|
|
|
+ <!-- 搜索和筛选 -->
|
|
|
|
+ <div class="bg-white dark:bg-gray-800 rounded-lg shadow mb-8">
|
|
|
|
+ <div class="p-6">
|
|
|
|
+ <div class="grid grid-cols-1 md:grid-cols-5 gap-4">
|
|
|
|
+ <div>
|
|
|
|
+ <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">物料编码</label>
|
|
|
|
+ <input
|
|
|
|
+ v-model="search.materialCode"
|
|
|
|
+ type="text"
|
|
|
|
+ placeholder="物料编码"
|
|
|
|
+ class="mt-1 form-input"
|
|
|
|
+ />
|
|
|
|
+ </div>
|
|
|
|
+ <div>
|
|
|
|
+ <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">物料组</label>
|
|
|
|
+ <input
|
|
|
|
+ v-model="search.materialGroup"
|
|
|
|
+ type="text"
|
|
|
|
+ placeholder="物料组"
|
|
|
|
+ class="mt-1 form-input"
|
|
|
|
+ />
|
|
|
|
+ </div>
|
|
|
|
+ <div>
|
|
|
|
+ <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">类别一</label>
|
|
|
|
+ <input
|
|
|
|
+ v-model="search.categoryOne"
|
|
|
|
+ type="text"
|
|
|
|
+ placeholder="类别一"
|
|
|
|
+ class="mt-1 form-input"
|
|
|
|
+ />
|
|
|
|
+ </div>
|
|
|
|
+ <div>
|
|
|
|
+ <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">类别二</label>
|
|
|
|
+ <input
|
|
|
|
+ v-model="search.categoryTwo"
|
|
|
|
+ type="text"
|
|
|
|
+ placeholder="类别二"
|
|
|
|
+ class="mt-1 form-input"
|
|
|
|
+ />
|
|
|
|
+ </div>
|
|
|
|
+ <div>
|
|
|
|
+ <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">原料大类</label>
|
|
|
|
+ <input
|
|
|
|
+ v-model="search.rawMaterialClass"
|
|
|
|
+ type="text"
|
|
|
|
+ placeholder="原料大类"
|
|
|
|
+ class="mt-1 form-input"
|
|
|
|
+ />
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ <div class="flex justify-end mt-4">
|
|
|
|
+ <button @click="resetSearch" class="btn-secondary mr-4">
|
|
|
|
+ 重置
|
|
|
|
+ </button>
|
|
|
|
+ <button @click="filterData" class="btn-primary">
|
|
|
|
+ 查询
|
|
|
|
+ </button>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
- <table class="w-full border-collapse border">
|
|
|
|
- <thead>
|
|
|
|
- <tr>
|
|
|
|
- <th class="border p-2"><input type="checkbox" v-model="selectAll" @change="toggleSelectAll" /></th>
|
|
|
|
- <th class="border p-2">序号</th>
|
|
|
|
- <th class="border p-2">物料编码</th>
|
|
|
|
- <th class="border p-2">物料组</th>
|
|
|
|
- <th class="border p-2">类别一</th>
|
|
|
|
- <th class="border p-2">类别二</th>
|
|
|
|
- <th class="border p-2">原料大类</th>
|
|
|
|
- </tr>
|
|
|
|
- </thead>
|
|
|
|
- <tbody>
|
|
|
|
- <tr v-for="(item, index) in filteredItems" :key="index">
|
|
|
|
- <td class="border p-2"><input type="checkbox" v-model="selectedItems" :value="item" /></td>
|
|
|
|
- <td class="border p-2">{{ index + 1 }}</td>
|
|
|
|
- <td class="border p-2">{{ item.materialCode }}</td>
|
|
|
|
- <td class="border p-2">{{ item.materialGroup }}</td>
|
|
|
|
- <td class="border p-2">{{ item.categoryOne }}</td>
|
|
|
|
- <td class="border p-2">{{ item.categoryTwo }}</td>
|
|
|
|
- <td class="border p-2">{{ item.rawMaterialClass }}</td>
|
|
|
|
- </tr>
|
|
|
|
- </tbody>
|
|
|
|
- </table>
|
|
|
|
- </section>
|
|
|
|
|
|
+ <!-- 原料品类列表 -->
|
|
|
|
+ <div class="bg-white dark:bg-gray-800 rounded-lg shadow">
|
|
|
|
+ <div class="overflow-x-auto">
|
|
|
|
+ <table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
|
|
|
|
+ <thead class="bg-gray-50 dark:bg-gray-700">
|
|
|
|
+ <tr>
|
|
|
|
+ <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">序号</th>
|
|
|
|
+ <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">物料编码</th>
|
|
|
|
+ <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">物料组</th>
|
|
|
|
+ <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">类别一</th>
|
|
|
|
+ <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">类别二</th>
|
|
|
|
+ <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">原料大类</th>
|
|
|
|
+ <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">选择</th>
|
|
|
|
+ <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">操作</th>
|
|
|
|
+ </tr>
|
|
|
|
+ </thead>
|
|
|
|
+ <tbody class="bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700">
|
|
|
|
+ <tr v-for="(item, index) in filteredData" :key="item.id">
|
|
|
|
+ <td class="px-6 py-4 whitespace-nowrap">
|
|
|
|
+ <div class="text-sm text-gray-900 dark:text-white">{{ index + 1 }}</div>
|
|
|
|
+ </td>
|
|
|
|
+ <td class="px-6 py-4 whitespace-nowrap">
|
|
|
|
+ <div class="text-sm text-gray-900 dark:text-white">{{ item.materialCode }}</div>
|
|
|
|
+ </td>
|
|
|
|
+ <td class="px-6 py-4 whitespace-nowrap">
|
|
|
|
+ <div class="text-sm text-gray-900 dark:text-white">{{ item.materialGroup }}</div>
|
|
|
|
+ </td>
|
|
|
|
+ <td class="px-6 py-4 whitespace-nowrap">
|
|
|
|
+ <div class="text-sm text-gray-900 dark:text-white">{{ item.categoryOne }}</div>
|
|
|
|
+ </td>
|
|
|
|
+ <td class="px-6 py-4 whitespace-nowrap">
|
|
|
|
+ <div class="text-sm text-gray-900 dark:text-white">{{ item.categoryTwo }}</div>
|
|
|
|
+ </td>
|
|
|
|
+ <td class="px-6 py-4 whitespace-nowrap">
|
|
|
|
+ <div class="text-sm text-gray-900 dark:text-white">{{ item.rawMaterialClass }}</div>
|
|
|
|
+ </td>
|
|
|
|
+ <td class="px-6 py-4 whitespace-nowrap">
|
|
|
|
+ <input type="checkbox" v-model="selectedItems" :value="item.id" class="form-checkbox" />
|
|
|
|
+ </td>
|
|
|
|
+ <td class="px-6 py-4 whitespace-nowrap text-sm font-medium">
|
|
|
|
+ <a :href="'#/raw-material-category/edit/' + item.id" class="text-indigo-600 hover:text-indigo-900 dark:text-indigo-400 dark:hover:text-indigo-300 mr-4">
|
|
|
|
+ 修改
|
|
|
|
+ </a>
|
|
|
|
+ <button @click="deleteItem(item)" class="text-red-600 hover:text-red-900 dark:text-red-400 dark:hover:text-red-300">
|
|
|
|
+ 删除
|
|
|
|
+ </button>
|
|
|
|
+ </td>
|
|
|
|
+ </tr>
|
|
|
|
+ </tbody>
|
|
|
|
+ </table>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
</template>
|
|
|
|
|
|
-<script>
|
|
|
|
-import { ref, computed } from 'vue';
|
|
|
|
-
|
|
|
|
-export default {
|
|
|
|
- name: 'RawMaterialCategoryView',
|
|
|
|
- setup() {
|
|
|
|
- const search = ref({
|
|
|
|
- materialCode: '',
|
|
|
|
- materialGroup: '',
|
|
|
|
- categoryOne: '',
|
|
|
|
- categoryTwo: '',
|
|
|
|
- rawMaterialClass: ''
|
|
|
|
- });
|
|
|
|
-
|
|
|
|
- const items = ref([
|
|
|
|
- { materialCode: 'MC001', materialGroup: 'MG001', categoryOne: 'C1', categoryTwo: 'C2', rawMaterialClass: 'RMC1' },
|
|
|
|
- { materialCode: 'MC002', materialGroup: 'MG002', categoryOne: 'C3', categoryTwo: 'C4', rawMaterialClass: 'RMC2' },
|
|
|
|
- // Add more items as needed
|
|
|
|
- ]);
|
|
|
|
-
|
|
|
|
- const selectedItems = ref([]);
|
|
|
|
-
|
|
|
|
- const selectAll = computed({
|
|
|
|
- get: () => items.value.length > 0 && selectedItems.value.length === items.value.length,
|
|
|
|
- set: (value) => {
|
|
|
|
- selectedItems.value = value ? items.value.slice() : [];
|
|
|
|
- }
|
|
|
|
- });
|
|
|
|
-
|
|
|
|
- const toggleSelectAll = () => {
|
|
|
|
- selectAll.value = !selectAll.value;
|
|
|
|
- };
|
|
|
|
-
|
|
|
|
- const resetSearch = () => {
|
|
|
|
- search.value = {
|
|
|
|
- materialCode: '',
|
|
|
|
- materialGroup: '',
|
|
|
|
- categoryOne: '',
|
|
|
|
- categoryTwo: '',
|
|
|
|
- rawMaterialClass: ''
|
|
|
|
- };
|
|
|
|
- };
|
|
|
|
-
|
|
|
|
- const performSearch = () => {
|
|
|
|
- // Implement search logic here
|
|
|
|
- };
|
|
|
|
-
|
|
|
|
- const deleteSelected = () => {
|
|
|
|
- if (selectedItems.value.length > 0) {
|
|
|
|
- if (confirm('确定要删除选中的项吗?')) {
|
|
|
|
- items.value = items.value.filter(item => !selectedItems.value.includes(item));
|
|
|
|
- selectedItems.value = [];
|
|
|
|
- }
|
|
|
|
- } else {
|
|
|
|
- alert('请选择要删除的项');
|
|
|
|
- }
|
|
|
|
- };
|
|
|
|
-
|
|
|
|
- const exportData = () => {
|
|
|
|
- // Implement export logic here
|
|
|
|
- };
|
|
|
|
-
|
|
|
|
- const importData = () => {
|
|
|
|
- // Implement import logic here
|
|
|
|
- };
|
|
|
|
-
|
|
|
|
- const filteredItems = computed(() => {
|
|
|
|
- return items.value.filter(item => {
|
|
|
|
- return (
|
|
|
|
- (!search.value.materialCode || item.materialCode.includes(search.value.materialCode)) &&
|
|
|
|
- (!search.value.materialGroup || item.materialGroup.includes(search.value.materialGroup)) &&
|
|
|
|
- (!search.value.categoryOne || item.categoryOne.includes(search.value.categoryOne)) &&
|
|
|
|
- (!search.value.categoryTwo || item.categoryTwo.includes(search.value.categoryTwo)) &&
|
|
|
|
- (!search.value.rawMaterialClass || item.rawMaterialClass.includes(search.value.rawMaterialClass))
|
|
|
|
- );
|
|
|
|
- });
|
|
|
|
- });
|
|
|
|
-
|
|
|
|
- return {
|
|
|
|
- search,
|
|
|
|
- items,
|
|
|
|
- selectedItems,
|
|
|
|
- selectAll,
|
|
|
|
- toggleSelectAll,
|
|
|
|
- resetSearch,
|
|
|
|
- performSearch,
|
|
|
|
- deleteSelected,
|
|
|
|
- exportData,
|
|
|
|
- importData,
|
|
|
|
- filteredItems
|
|
|
|
- };
|
|
|
|
|
|
+<script setup>
|
|
|
|
+import { ref, computed } from 'vue'
|
|
|
|
+
|
|
|
|
+// 数据定义
|
|
|
|
+const rawMaterials = ref([
|
|
|
|
+ {
|
|
|
|
+ id: 1,
|
|
|
|
+ materialCode: 'MC001',
|
|
|
|
+ materialGroup: 'MG001',
|
|
|
|
+ categoryOne: 'Category 1',
|
|
|
|
+ categoryTwo: 'Subcategory 1',
|
|
|
|
+ rawMaterialClass: 'Class A'
|
|
|
|
+ },
|
|
|
|
+ // 更多示例数据...
|
|
|
|
+])
|
|
|
|
+
|
|
|
|
+const search = ref({
|
|
|
|
+ materialCode: '',
|
|
|
|
+ materialGroup: '',
|
|
|
|
+ categoryOne: '',
|
|
|
|
+ categoryTwo: '',
|
|
|
|
+ rawMaterialClass: ''
|
|
|
|
+})
|
|
|
|
+
|
|
|
|
+const selectedItems = ref([])
|
|
|
|
+
|
|
|
|
+// 计算属性
|
|
|
|
+const filteredData = computed(() => {
|
|
|
|
+ return rawMaterials.value.filter(item => {
|
|
|
|
+ const matchesMaterialCode = !search.value.materialCode ||
|
|
|
|
+ item.materialCode.toLowerCase().includes(search.value.materialCode.toLowerCase())
|
|
|
|
+ const matchesMaterialGroup = !search.value.materialGroup ||
|
|
|
|
+ item.materialGroup.toLowerCase().includes(search.value.materialGroup.toLowerCase())
|
|
|
|
+ const matchesCategoryOne = !search.value.categoryOne ||
|
|
|
|
+ item.categoryOne.toLowerCase().includes(search.value.categoryOne.toLowerCase())
|
|
|
|
+ const matchesCategoryTwo = !search.value.categoryTwo ||
|
|
|
|
+ item.categoryTwo.toLowerCase().includes(search.value.categoryTwo.toLowerCase())
|
|
|
|
+ const matchesRawMaterialClass = !search.value.rawMaterialClass ||
|
|
|
|
+ item.rawMaterialClass.toLowerCase().includes(search.value.rawMaterialClass.toLowerCase())
|
|
|
|
+ return matchesMaterialCode && matchesMaterialGroup && matchesCategoryOne && matchesCategoryTwo && matchesRawMaterialClass
|
|
|
|
+ })
|
|
|
|
+})
|
|
|
|
+
|
|
|
|
+// 方法
|
|
|
|
+const resetSearch = () => {
|
|
|
|
+ search.value = {
|
|
|
|
+ materialCode: '',
|
|
|
|
+ materialGroup: '',
|
|
|
|
+ categoryOne: '',
|
|
|
|
+ categoryTwo: '',
|
|
|
|
+ rawMaterialClass: ''
|
|
}
|
|
}
|
|
-};
|
|
|
|
-</script>
|
|
|
|
|
|
+}
|
|
|
|
|
|
-<style scoped>
|
|
|
|
-.container {
|
|
|
|
- max-width: 1200px;
|
|
|
|
|
|
+const filterData = () => {
|
|
|
|
+ // 实现过滤逻辑
|
|
}
|
|
}
|
|
|
|
|
|
-header {
|
|
|
|
- display: flex;
|
|
|
|
- justify-content: space-between;
|
|
|
|
- align-items: center;
|
|
|
|
|
|
+const deleteItem = (item) => {
|
|
|
|
+ if (confirm('确定要删除这个原料品类吗?')) {
|
|
|
|
+ rawMaterials.value = rawMaterials.value.filter(i => i.id !== item.id)
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
-table {
|
|
|
|
- width: 100%;
|
|
|
|
- border-collapse: collapse;
|
|
|
|
|
|
+const exportData = () => {
|
|
|
|
+ // 实现导出逻辑
|
|
|
|
+ const data = JSON.stringify(rawMaterials.value, null, 2)
|
|
|
|
+ const blob = new Blob([data], { type: 'application/json' })
|
|
|
|
+ const url = URL.createObjectURL(blob)
|
|
|
|
+ const a = document.createElement('a')
|
|
|
|
+ a.href = url
|
|
|
|
+ a.download = 'raw_material_categories.json'
|
|
|
|
+ document.body.appendChild(a)
|
|
|
|
+ a.click()
|
|
|
|
+ document.body.removeChild(a)
|
|
|
|
+ URL.revokeObjectURL(url)
|
|
}
|
|
}
|
|
|
|
+</script>
|
|
|
|
|
|
-th, td {
|
|
|
|
- border: 1px solid #ddd;
|
|
|
|
- padding: 8px;
|
|
|
|
|
|
+<style scoped>
|
|
|
|
+.btn-primary {
|
|
|
|
+ @apply bg-blue-500 text-white px-4 py-2 rounded hover:bg-blue-600;
|
|
}
|
|
}
|
|
|
|
|
|
-th {
|
|
|
|
- background-color: #f2f2f2;
|
|
|
|
|
|
+.btn-secondary {
|
|
|
|
+ @apply bg-gray-300 text-gray-700 px-4 py-2 rounded hover:bg-gray-400;
|
|
}
|
|
}
|
|
|
|
|
|
-@media (max-width: 600px) {
|
|
|
|
- header {
|
|
|
|
- flex-direction: column;
|
|
|
|
- align-items: flex-start;
|
|
|
|
- }
|
|
|
|
|
|
+.form-input {
|
|
|
|
+ @apply appearance-none block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm placeholder-gray-400 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm;
|
|
|
|
+}
|
|
|
|
|
|
- header div {
|
|
|
|
- margin-top: 10px;
|
|
|
|
- }
|
|
|
|
|
|
+.form-select {
|
|
|
|
+ @apply appearance-none block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm placeholder-gray-400 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm;
|
|
|
|
+}
|
|
|
|
|
|
- table {
|
|
|
|
- display: block;
|
|
|
|
- overflow-x: auto;
|
|
|
|
- }
|
|
|
|
|
|
+.form-checkbox {
|
|
|
|
+ @apply w-4 h-4 text-indigo-600 focus:ring-indigo-500 border-gray-300 rounded;
|
|
}
|
|
}
|
|
</style>
|
|
</style>
|