|
@@ -1,31 +1,86 @@
|
|
|
<template>
|
|
<template>
|
|
|
- <div>
|
|
|
|
|
- <a-card>
|
|
|
|
|
- <a-space>
|
|
|
|
|
- <a-input-search v-model:value="searchKeyword" placeholder="搜索批次号" style="width: 300px" @search="loadBatches" />
|
|
|
|
|
- <a-button type="primary" @click="showCreateModal">创建批次</a-button>
|
|
|
|
|
|
|
+ <div class="p-4 md:p-8">
|
|
|
|
|
+ <!-- 头部工具栏 -->
|
|
|
|
|
+ <a-card class="mb-6 bg-gray-50 rounded-lg shadow-sm !border-0">
|
|
|
|
|
+ <a-space size="large" wrap>
|
|
|
|
|
+ <a-input-search v-model:value="searchKeyword" placeholder="搜索批次号" class="w-full sm:w-80" @search="loadBatches" />
|
|
|
|
|
+ <a-button type="primary" @click="showCreateModal" class="shadow-sm hover:shadow-md transition-shadow">
|
|
|
|
|
+ <PlusOutlined class="mr-2" />
|
|
|
|
|
+ 创建批次
|
|
|
|
|
+ </a-button>
|
|
|
</a-space>
|
|
</a-space>
|
|
|
</a-card>
|
|
</a-card>
|
|
|
|
|
|
|
|
- <a-card class="mt-4" title="裁床批次列表">
|
|
|
|
|
|
|
+ <!-- 桌面端:裁床批次列表表格 -->
|
|
|
|
|
+ <a-card v-if="!layoutStore.isMobile" class="rounded-xl shadow-md !border-0" title="裁床批次列表">
|
|
|
<a-table :columns="columns" :dataSource="batches" :loading="loading" rowKey="id">
|
|
<a-table :columns="columns" :dataSource="batches" :loading="loading" rowKey="id">
|
|
|
<template #status="{ record }">
|
|
<template #status="{ record }">
|
|
|
- <a-tag :color="getStatusColor(record.status)">{{ getStatusText(record.status) }}</a-tag>
|
|
|
|
|
|
|
+ <a-tag :color="getStatusColor(record.status)" class="!rounded-full">{{ getStatusText(record.status) }}</a-tag>
|
|
|
</template>
|
|
</template>
|
|
|
<template #action="{ record }">
|
|
<template #action="{ record }">
|
|
|
<a-space>
|
|
<a-space>
|
|
|
- <a-button size="small" @click="showBundlesModal(record)">查看扎号</a-button>
|
|
|
|
|
- <a-button size="small" @click="showEditModal(record)">编辑</a-button>
|
|
|
|
|
|
|
+ <a-button size="small" @click="showBundlesModal(record)" class="hover:shadow-sm transition-shadow">
|
|
|
|
|
+ <EyeOutlined class="mr-1" />
|
|
|
|
|
+ 查看扎号
|
|
|
|
|
+ </a-button>
|
|
|
|
|
+ <a-button size="small" @click="showEditModal(record)" class="hover:shadow-sm transition-shadow">
|
|
|
|
|
+ <EditOutlined class="mr-1" />
|
|
|
|
|
+ 编辑
|
|
|
|
|
+ </a-button>
|
|
|
<a-popconfirm title="确定删除此批次吗?" @confirm="deleteBatch(record.id)">
|
|
<a-popconfirm title="确定删除此批次吗?" @confirm="deleteBatch(record.id)">
|
|
|
- <a-button size="small" danger>删除</a-button>
|
|
|
|
|
|
|
+ <a-button size="small" danger class="hover:shadow-sm transition-shadow">
|
|
|
|
|
+ <DeleteOutlined class="mr-1" />
|
|
|
|
|
+ 删除
|
|
|
|
|
+ </a-button>
|
|
|
</a-popconfirm>
|
|
</a-popconfirm>
|
|
|
</a-space>
|
|
</a-space>
|
|
|
</template>
|
|
</template>
|
|
|
</a-table>
|
|
</a-table>
|
|
|
</a-card>
|
|
</a-card>
|
|
|
|
|
|
|
|
|
|
+ <!-- 移动端:批次卡片列表 -->
|
|
|
|
|
+ <div v-else class="space-y-3">
|
|
|
|
|
+ <a-spin :spinning="loading">
|
|
|
|
|
+ <a-empty v-if="!loading && batches.length === 0" description="暂无批次数据" class="py-8" />
|
|
|
|
|
+ <a-card
|
|
|
|
|
+ v-for="item in batches"
|
|
|
|
|
+ :key="item.id"
|
|
|
|
|
+ class="rounded-xl shadow-sm !border-0"
|
|
|
|
|
+ size="small"
|
|
|
|
|
+ >
|
|
|
|
|
+ <div class="flex items-start justify-between gap-2 mb-2">
|
|
|
|
|
+ <span class="font-medium text-gray-900 break-all">{{ item.batch_no }}</span>
|
|
|
|
|
+ <a-tag :color="getStatusColor(item.status)" class="!rounded-full !mr-0 flex-shrink-0">
|
|
|
|
|
+ {{ getStatusText(item.status) }}
|
|
|
|
|
+ </a-tag>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="text-sm text-gray-500 space-y-1 mb-3">
|
|
|
|
|
+ <div>工单号:{{ item.order_no }}</div>
|
|
|
|
|
+ <div>颜色:{{ item.color }}</div>
|
|
|
|
|
+ <div>数量:{{ item.completed_qty }} / {{ item.total_qty }}</div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="flex items-center gap-2 pt-3 border-t border-gray-100">
|
|
|
|
|
+ <a-button size="small" @click="showBundlesModal(item)">
|
|
|
|
|
+ <EyeOutlined class="mr-1" />
|
|
|
|
|
+ 查看扎号
|
|
|
|
|
+ </a-button>
|
|
|
|
|
+ <a-button size="small" @click="showEditModal(item)">
|
|
|
|
|
+ <EditOutlined class="mr-1" />
|
|
|
|
|
+ 编辑
|
|
|
|
|
+ </a-button>
|
|
|
|
|
+ <a-popconfirm title="确定删除此批次吗?" @confirm="deleteBatch(item.id)">
|
|
|
|
|
+ <a-button size="small" danger>
|
|
|
|
|
+ <DeleteOutlined class="mr-1" />
|
|
|
|
|
+ 删除
|
|
|
|
|
+ </a-button>
|
|
|
|
|
+ </a-popconfirm>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </a-card>
|
|
|
|
|
+ </a-spin>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
<!-- 创建/编辑批次模态框 -->
|
|
<!-- 创建/编辑批次模态框 -->
|
|
|
- <a-modal v-model:open="modalVisible" :title="modalTitle" @ok="handleSubmit" :confirmLoading="submitting" width="600px">
|
|
|
|
|
|
|
+ <a-modal v-model:open="modalVisible" :title="modalTitle" @ok="handleSubmit" :confirmLoading="submitting" :width="modalWidth" class="!rounded-xl">
|
|
|
<a-form ref="formRef" :model="formState" :rules="formRules" layout="vertical">
|
|
<a-form ref="formRef" :model="formState" :rules="formRules" layout="vertical">
|
|
|
<a-form-item label="工单" name="work_order_id" v-if="!isEdit">
|
|
<a-form-item label="工单" name="work_order_id" v-if="!isEdit">
|
|
|
<a-select v-model:value="formState.work_order_id" placeholder="请选择工单">
|
|
<a-select v-model:value="formState.work_order_id" placeholder="请选择工单">
|
|
@@ -47,7 +102,7 @@
|
|
|
</a-modal>
|
|
</a-modal>
|
|
|
|
|
|
|
|
<!-- 扎号管理模态框 -->
|
|
<!-- 扎号管理模态框 -->
|
|
|
- <a-modal v-model:open="bundlesModalVisible" :title="`扎号管理 - ${currentBatch?.batch_no}`" width="900px" :footer="null">
|
|
|
|
|
|
|
+ <a-modal v-model:open="bundlesModalVisible" :title="`扎号管理 - ${currentBatch?.batch_no}`" :width="bundlesModalWidth" :footer="null" class="!rounded-xl">
|
|
|
<a-space class="mb-4">
|
|
<a-space class="mb-4">
|
|
|
<a-button type="primary" @click="showAddBundleModal">添加扎号</a-button>
|
|
<a-button type="primary" @click="showAddBundleModal">添加扎号</a-button>
|
|
|
<a-button @click="generateAllQRCodes">批量生成二维码</a-button>
|
|
<a-button @click="generateAllQRCodes">批量生成二维码</a-button>
|
|
@@ -65,7 +120,7 @@
|
|
|
</a-modal>
|
|
</a-modal>
|
|
|
|
|
|
|
|
<!-- 添加扎号模态框 -->
|
|
<!-- 添加扎号模态框 -->
|
|
|
- <a-modal v-model:open="addBundleModalVisible" title="添加扎号" @ok="handleAddBundle" :confirmLoading="addingBundle">
|
|
|
|
|
|
|
+ <a-modal v-model:open="addBundleModalVisible" title="添加扎号" @ok="handleAddBundle" :confirmLoading="addingBundle" :width="modalWidth" class="!rounded-xl">
|
|
|
<a-form layout="vertical">
|
|
<a-form layout="vertical">
|
|
|
<a-form-item label="尺码" required>
|
|
<a-form-item label="尺码" required>
|
|
|
<a-input v-model:value="newBundle.size" placeholder="如:S/M/L/XL" />
|
|
<a-input v-model:value="newBundle.size" placeholder="如:S/M/L/XL" />
|
|
@@ -77,7 +132,7 @@
|
|
|
</a-modal>
|
|
</a-modal>
|
|
|
|
|
|
|
|
<!-- 单个扎号二维码展示 -->
|
|
<!-- 单个扎号二维码展示 -->
|
|
|
- <a-modal v-model:open="bundleQRVisible" title="扎号二维码" :footer="null" width="400px">
|
|
|
|
|
|
|
+ <a-modal v-model:open="bundleQRVisible" title="扎号二维码" :footer="null" :width="qrModalWidth" class="!rounded-xl">
|
|
|
<div class="text-center">
|
|
<div class="text-center">
|
|
|
<img :src="bundleQRUrl" alt="扎号二维码" style="width: 100%" />
|
|
<img :src="bundleQRUrl" alt="扎号二维码" style="width: 100%" />
|
|
|
<p class="mt-4 text-gray-600 text-sm">扎号: {{ currentBundle?.bundle_no }}</p>
|
|
<p class="mt-4 text-gray-600 text-sm">扎号: {{ currentBundle?.bundle_no }}</p>
|
|
@@ -87,11 +142,13 @@
|
|
|
</template>
|
|
</template>
|
|
|
|
|
|
|
|
<script setup lang="ts">
|
|
<script setup lang="ts">
|
|
|
-import { ref, reactive, onMounted } from 'vue';
|
|
|
|
|
|
|
+import { ref, reactive, onMounted, computed } from 'vue';
|
|
|
import { message } from 'ant-design-vue';
|
|
import { message } from 'ant-design-vue';
|
|
|
|
|
+import { PlusOutlined, EditOutlined, DeleteOutlined, EyeOutlined } from '@ant-design/icons-vue';
|
|
|
import { WorkOrderApi, createApiClient } from '@smartcut/api-client';
|
|
import { WorkOrderApi, createApiClient } from '@smartcut/api-client';
|
|
|
import { STORAGE_KEYS } from '@smartcut/shared-utils';
|
|
import { STORAGE_KEYS } from '@smartcut/shared-utils';
|
|
|
import { getApiBaseUrl } from '@/apiConfig';
|
|
import { getApiBaseUrl } from '@/apiConfig';
|
|
|
|
|
+import { useLayoutStore } from '@/stores/layout';
|
|
|
import type { WorkOrder, CutBatch, CutBundle } from '@smartcut/types';
|
|
import type { WorkOrder, CutBatch, CutBundle } from '@smartcut/types';
|
|
|
|
|
|
|
|
const apiClient = createApiClient({
|
|
const apiClient = createApiClient({
|
|
@@ -101,6 +158,11 @@ const apiClient = createApiClient({
|
|
|
|
|
|
|
|
const workOrderApi = new WorkOrderApi(apiClient);
|
|
const workOrderApi = new WorkOrderApi(apiClient);
|
|
|
|
|
|
|
|
|
|
+const layoutStore = useLayoutStore();
|
|
|
|
|
+const modalWidth = computed(() => layoutStore.isMobile ? '90%' : 600);
|
|
|
|
|
+const bundlesModalWidth = computed(() => layoutStore.isMobile ? '90%' : 900);
|
|
|
|
|
+const qrModalWidth = computed(() => layoutStore.isMobile ? '90%' : '400px');
|
|
|
|
|
+
|
|
|
const batches = ref<CutBatch[]>([]);
|
|
const batches = ref<CutBatch[]>([]);
|
|
|
const workOrders = ref<WorkOrder[]>([]);
|
|
const workOrders = ref<WorkOrder[]>([]);
|
|
|
const bundles = ref<CutBundle[]>([]);
|
|
const bundles = ref<CutBundle[]>([]);
|