x
This commit is contained in:
@@ -81,57 +81,57 @@ onMounted(() => { loadCustomers() })
|
||||
<template>
|
||||
<div class="customers-tab">
|
||||
<div class="table-header">
|
||||
<el-button type="primary" @click="openCreateCustomer">+ 新增客户</el-button>
|
||||
<t-button type="primary" @click="openCreateCustomer">+ 新增客户</t-button>
|
||||
</div>
|
||||
<el-table :data="state.customers" style="width: 100%" v-loading="state.loading" empty-text="暂无客户数据">
|
||||
<el-table-column prop="code" label="编码" />
|
||||
<el-table-column prop="name" label="名称" />
|
||||
<el-table-column prop="contact_person" label="联系人">
|
||||
<t-table :data="state.customers" style="width: 100%" :loading="state.loading" empty-text="暂无客户数据">
|
||||
<t-table-column prop="code" label="编码" />
|
||||
<t-table-column prop="name" label="名称" />
|
||||
<t-table-column prop="contact_person" label="联系人">
|
||||
<template #default="{ row }">
|
||||
{{ row.contact_person || '-' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="phone" label="电话">
|
||||
</t-table-column>
|
||||
<t-table-column prop="phone" label="电话">
|
||||
<template #default="{ row }">
|
||||
{{ row.phone || '-' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="email" label="邮箱">
|
||||
</t-table-column>
|
||||
<t-table-column prop="email" label="邮箱">
|
||||
<template #default="{ row }">
|
||||
{{ row.email || '-' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="180">
|
||||
</t-table-column>
|
||||
<t-table-column label="操作" width="180">
|
||||
<template #default="{ row }">
|
||||
<el-button size="small" @click="editCustomer(row)">编辑</el-button>
|
||||
<el-button size="small" type="danger" @click="deleteCustomer(row.id)">删除</el-button>
|
||||
<t-button size="small" @click="editCustomer(row)">编辑</t-button>
|
||||
<t-button size="small" type="danger" @click="deleteCustomer(row.id)">删除</t-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</t-table-column>
|
||||
</t-table>
|
||||
|
||||
<el-dialog v-model="showModal" :title="editingItem ? '编辑客户' : '新增客户'" width="520px" :close-on-click-modal="false">
|
||||
<el-form :model="form" label-width="80px">
|
||||
<el-form-item label="名称" required>
|
||||
<el-input v-model="form.name" placeholder="请输入客户名称" />
|
||||
</el-form-item>
|
||||
<el-form-item label="联系人">
|
||||
<el-input v-model="form.contact_person" placeholder="请输入联系人" />
|
||||
</el-form-item>
|
||||
<el-form-item label="电话">
|
||||
<el-input v-model="form.phone" placeholder="请输入电话" />
|
||||
</el-form-item>
|
||||
<el-form-item label="邮箱">
|
||||
<el-input v-model="form.email" type="email" placeholder="请输入邮箱" />
|
||||
</el-form-item>
|
||||
<el-form-item label="地址">
|
||||
<el-input v-model="form.address" placeholder="请输入地址" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<t-dialog v-model="showModal" :title="editingItem ? '编辑客户' : '新增客户'" width="520px" :close-on-click-modal="false">
|
||||
<t-form :model="form" label-width="80px">
|
||||
<t-form-item label="名称" required>
|
||||
<t-input v-model="form.name" placeholder="请输入客户名称" />
|
||||
</t-form-item>
|
||||
<t-form-item label="联系人">
|
||||
<t-input v-model="form.contact_person" placeholder="请输入联系人" />
|
||||
</t-form-item>
|
||||
<t-form-item label="电话">
|
||||
<t-input v-model="form.phone" placeholder="请输入电话" />
|
||||
</t-form-item>
|
||||
<t-form-item label="邮箱">
|
||||
<t-input v-model="form.email" type="email" placeholder="请输入邮箱" />
|
||||
</t-form-item>
|
||||
<t-form-item label="地址">
|
||||
<t-input v-model="form.address" placeholder="请输入地址" />
|
||||
</t-form-item>
|
||||
</t-form>
|
||||
<template #footer>
|
||||
<el-button @click="showModal = false">取消</el-button>
|
||||
<el-button type="primary" @click="save">保存</el-button>
|
||||
<t-button @click="showModal = false">取消</t-button>
|
||||
<t-button type="primary" @click="save">保存</t-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</t-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -4,8 +4,8 @@ const { state, formatCurrency } = useInventory()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="8" v-for="card in [
|
||||
<t-row :gutter="16">
|
||||
<t-col :span="8" v-for="card in [
|
||||
{ icon: '📦', value: state.dashboard?.product_count || 0, label: '成品数量' },
|
||||
{ icon: '📊', value: state.dashboard?.total_stock || 0, label: '物料库存总量' },
|
||||
{ icon: '💰', value: formatCurrency(state.dashboard?.total_value || 0), label: '库存价值' },
|
||||
@@ -13,7 +13,7 @@ const { state, formatCurrency } = useInventory()
|
||||
{ icon: '👥', value: state.dashboard?.customer_count || 0, label: '客户' },
|
||||
{ icon: '🏪', value: state.dashboard?.warehouse_count || 0, label: '仓库' }
|
||||
]" :key="card.label" style="margin-bottom: 16px">
|
||||
<el-card shadow="hover">
|
||||
<t-card shadow="hover">
|
||||
<div style="display: flex; align-items: center; gap: 12px;">
|
||||
<span style="font-size: 32px;">{{ card.icon }}</span>
|
||||
<div>
|
||||
@@ -21,9 +21,9 @@ const { state, formatCurrency } = useInventory()
|
||||
<div style="color: var(--text-tertiary); font-size: 13px;">{{ card.label }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</t-card>
|
||||
</t-col>
|
||||
</t-row>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
@@ -74,192 +74,192 @@ function getTransactionStatusLabel(status: string): string {
|
||||
<div>
|
||||
<div style="margin-bottom: 16px; display: flex; gap: 12px; align-items: center; flex-wrap: wrap;">
|
||||
<span style="font-weight: 600;">统计周期:</span>
|
||||
<el-input-number
|
||||
<t-input-number
|
||||
v-model="periodYear"
|
||||
:min="2020"
|
||||
:max="2099"
|
||||
style="width: 120px;"
|
||||
/>
|
||||
<span>年</span>
|
||||
<el-select v-model="periodQuarter" placeholder="选择季度" style="width: 120px;">
|
||||
<el-option
|
||||
<t-select v-model="periodQuarter" placeholder="选择季度" style="width: 120px;">
|
||||
<t-option
|
||||
v-for="q in quarterOptions"
|
||||
:key="q.value"
|
||||
:label="q.label"
|
||||
:value="q.value"
|
||||
/>
|
||||
</el-select>
|
||||
<el-button type="primary" @click="refreshFinance">刷新统计</el-button>
|
||||
<el-tag type="info" size="large">{{ periodLabel }}</el-tag>
|
||||
</t-select>
|
||||
<t-button type="primary" @click="refreshFinance">刷新统计</t-button>
|
||||
<t-tag type="info" size="large">{{ periodLabel }}</t-tag>
|
||||
</div>
|
||||
|
||||
<el-row :gutter="16" style="margin-bottom: 16px;">
|
||||
<el-col :span="6">
|
||||
<el-card shadow="hover">
|
||||
<t-row :gutter="16" style="margin-bottom: 16px;">
|
||||
<t-col :span="6">
|
||||
<t-card shadow="hover">
|
||||
<div style="text-align: center;">
|
||||
<div style="color: #909399; font-size: 14px; margin-bottom: 8px;">应收总额</div>
|
||||
<div style="font-size: 24px; font-weight: 700; color: #409eff;">
|
||||
{{ formatCurrency(totalReceivable) }}
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-card shadow="hover">
|
||||
</t-card>
|
||||
</t-col>
|
||||
<t-col :span="6">
|
||||
<t-card shadow="hover">
|
||||
<div style="text-align: center;">
|
||||
<div style="color: #909399; font-size: 14px; margin-bottom: 8px;">应付总额</div>
|
||||
<div style="font-size: 24px; font-weight: 700; color: #e6a23c;">
|
||||
{{ formatCurrency(totalPayable) }}
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-card shadow="hover">
|
||||
</t-card>
|
||||
</t-col>
|
||||
<t-col :span="6">
|
||||
<t-card shadow="hover">
|
||||
<div style="text-align: center;">
|
||||
<div style="color: #909399; font-size: 14px; margin-bottom: 8px;">周期收款</div>
|
||||
<div style="font-size: 24px; font-weight: 700; color: #67c23a;">
|
||||
{{ formatCurrency(periodReceived) }}
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-card shadow="hover">
|
||||
</t-card>
|
||||
</t-col>
|
||||
<t-col :span="6">
|
||||
<t-card shadow="hover">
|
||||
<div style="text-align: center;">
|
||||
<div style="color: #909399; font-size: 14px; margin-bottom: 8px;">周期付款</div>
|
||||
<div style="font-size: 24px; font-weight: 700; color: #f56c6c;">
|
||||
{{ formatCurrency(periodPaid) }}
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</t-card>
|
||||
</t-col>
|
||||
</t-row>
|
||||
|
||||
<el-card style="margin-bottom: 16px;">
|
||||
<t-card style="margin-bottom: 16px;">
|
||||
<template #header>
|
||||
<span style="font-weight: 600;">客户账款(周期)</span>
|
||||
</template>
|
||||
<el-table :data="state.customerFinanceStatement" v-loading="state.loading" stripe size="small">
|
||||
<el-table-column prop="partner_name" label="客户" />
|
||||
<el-table-column prop="order_count" label="订单数" />
|
||||
<el-table-column prop="transaction_count" label="流水数" />
|
||||
<el-table-column label="订单金额">
|
||||
<t-table :data="state.customerFinanceStatement" :loading="state.loading" stripe size="small">
|
||||
<t-table-column prop="partner_name" label="客户" />
|
||||
<t-table-column prop="order_count" label="订单数" />
|
||||
<t-table-column prop="transaction_count" label="流水数" />
|
||||
<t-table-column label="订单金额">
|
||||
<template #default="{ row }">{{ formatCurrency(row.order_amount) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="订单已收">
|
||||
</t-table-column>
|
||||
<t-table-column label="订单已收">
|
||||
<template #default="{ row }">{{ formatCurrency(row.order_received) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="实收流水">
|
||||
</t-table-column>
|
||||
<t-table-column label="实收流水">
|
||||
<template #default="{ row }">{{ formatCurrency(row.transaction_received) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="应收余额">
|
||||
</t-table-column>
|
||||
<t-table-column label="应收余额">
|
||||
<template #default="{ row }">{{ formatCurrency(row.receivable_balance) }}</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-empty v-if="!state.loading && state.customerFinanceStatement.length === 0" description="暂无数据" />
|
||||
</el-card>
|
||||
</t-table-column>
|
||||
</t-table>
|
||||
<t-empty v-if="!state.loading && state.customerFinanceStatement.length === 0" description="暂无数据" />
|
||||
</t-card>
|
||||
|
||||
<el-card style="margin-bottom: 16px;">
|
||||
<t-card style="margin-bottom: 16px;">
|
||||
<template #header>
|
||||
<span style="font-weight: 600;">供应商账款(周期)</span>
|
||||
</template>
|
||||
<el-table :data="state.supplierFinanceStatement" v-loading="state.loading" stripe size="small">
|
||||
<el-table-column prop="partner_name" label="供应商" />
|
||||
<el-table-column prop="order_count" label="订单数" />
|
||||
<el-table-column prop="transaction_count" label="流水数" />
|
||||
<el-table-column label="订单金额">
|
||||
<t-table :data="state.supplierFinanceStatement" :loading="state.loading" stripe size="small">
|
||||
<t-table-column prop="partner_name" label="供应商" />
|
||||
<t-table-column prop="order_count" label="订单数" />
|
||||
<t-table-column prop="transaction_count" label="流水数" />
|
||||
<t-table-column label="订单金额">
|
||||
<template #default="{ row }">{{ formatCurrency(row.order_amount) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="订单已付">
|
||||
</t-table-column>
|
||||
<t-table-column label="订单已付">
|
||||
<template #default="{ row }">{{ formatCurrency(row.order_paid) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="实付流水">
|
||||
</t-table-column>
|
||||
<t-table-column label="实付流水">
|
||||
<template #default="{ row }">{{ formatCurrency(row.transaction_paid) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="应付余额">
|
||||
</t-table-column>
|
||||
<t-table-column label="应付余额">
|
||||
<template #default="{ row }">{{ formatCurrency(row.payable_balance) }}</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-empty v-if="!state.loading && state.supplierFinanceStatement.length === 0" description="暂无数据" />
|
||||
</el-card>
|
||||
</t-table-column>
|
||||
</t-table>
|
||||
<t-empty v-if="!state.loading && state.supplierFinanceStatement.length === 0" description="暂无数据" />
|
||||
</t-card>
|
||||
|
||||
<el-card style="margin-bottom: 16px;">
|
||||
<t-card style="margin-bottom: 16px;">
|
||||
<template #header>
|
||||
<span style="font-weight: 600;">客户-商品追溯(周期)</span>
|
||||
</template>
|
||||
<el-table :data="state.customerProductStatement" v-loading="state.loading" stripe size="small">
|
||||
<el-table-column prop="partner_name" label="客户" />
|
||||
<el-table-column prop="product_sku" label="SKU" />
|
||||
<el-table-column prop="product_name" label="商品" />
|
||||
<el-table-column prop="order_count" label="订单数" />
|
||||
<el-table-column prop="quantity" label="数量" />
|
||||
<el-table-column label="订单金额">
|
||||
<t-table :data="state.customerProductStatement" :loading="state.loading" stripe size="small">
|
||||
<t-table-column prop="partner_name" label="客户" />
|
||||
<t-table-column prop="product_sku" label="SKU" />
|
||||
<t-table-column prop="product_name" label="商品" />
|
||||
<t-table-column prop="order_count" label="订单数" />
|
||||
<t-table-column prop="quantity" label="数量" />
|
||||
<t-table-column label="订单金额">
|
||||
<template #default="{ row }">{{ formatCurrency(row.order_amount) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="已结款">
|
||||
</t-table-column>
|
||||
<t-table-column label="已结款">
|
||||
<template #default="{ row }">{{ formatCurrency(row.settled_amount) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="未结款">
|
||||
</t-table-column>
|
||||
<t-table-column label="未结款">
|
||||
<template #default="{ row }">{{ formatCurrency(row.unsettled_amount) }}</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-empty v-if="!state.loading && state.customerProductStatement.length === 0" description="暂无数据" />
|
||||
</el-card>
|
||||
</t-table-column>
|
||||
</t-table>
|
||||
<t-empty v-if="!state.loading && state.customerProductStatement.length === 0" description="暂无数据" />
|
||||
</t-card>
|
||||
|
||||
<el-card style="margin-bottom: 16px;">
|
||||
<t-card style="margin-bottom: 16px;">
|
||||
<template #header>
|
||||
<span style="font-weight: 600;">供应商-商品追溯(周期)</span>
|
||||
</template>
|
||||
<el-table :data="state.supplierProductStatement" v-loading="state.loading" stripe size="small">
|
||||
<el-table-column prop="partner_name" label="供应商" />
|
||||
<el-table-column prop="product_sku" label="SKU" />
|
||||
<el-table-column prop="product_name" label="商品" />
|
||||
<el-table-column prop="order_count" label="订单数" />
|
||||
<el-table-column prop="quantity" label="数量" />
|
||||
<el-table-column label="订单金额">
|
||||
<t-table :data="state.supplierProductStatement" :loading="state.loading" stripe size="small">
|
||||
<t-table-column prop="partner_name" label="供应商" />
|
||||
<t-table-column prop="product_sku" label="SKU" />
|
||||
<t-table-column prop="product_name" label="商品" />
|
||||
<t-table-column prop="order_count" label="订单数" />
|
||||
<t-table-column prop="quantity" label="数量" />
|
||||
<t-table-column label="订单金额">
|
||||
<template #default="{ row }">{{ formatCurrency(row.order_amount) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="已结款">
|
||||
</t-table-column>
|
||||
<t-table-column label="已结款">
|
||||
<template #default="{ row }">{{ formatCurrency(row.settled_amount) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="未结款">
|
||||
</t-table-column>
|
||||
<t-table-column label="未结款">
|
||||
<template #default="{ row }">{{ formatCurrency(row.unsettled_amount) }}</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-empty v-if="!state.loading && state.supplierProductStatement.length === 0" description="暂无数据" />
|
||||
</el-card>
|
||||
</t-table-column>
|
||||
</t-table>
|
||||
<t-empty v-if="!state.loading && state.supplierProductStatement.length === 0" description="暂无数据" />
|
||||
</t-card>
|
||||
|
||||
<el-card>
|
||||
<t-card>
|
||||
<template #header>
|
||||
<span style="font-weight: 600;">最近财务流水</span>
|
||||
</template>
|
||||
<el-table :data="state.financeTransactions" v-loading="state.loading" stripe size="small">
|
||||
<el-table-column prop="order_no" label="单号" />
|
||||
<el-table-column label="类型">
|
||||
<t-table :data="state.financeTransactions" :loading="state.loading" stripe size="small">
|
||||
<t-table-column prop="order_no" label="单号" />
|
||||
<t-table-column label="类型">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="getTransactionTypeTag(row.type)" size="small">
|
||||
<t-tag :type="getTransactionTypeTag(row.type)" size="small">
|
||||
{{ getTransactionTypeLabel(row.type) }}
|
||||
</el-tag>
|
||||
</t-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="partner_name" label="往来方" />
|
||||
<el-table-column label="金额">
|
||||
</t-table-column>
|
||||
<t-table-column prop="partner_name" label="往来方" />
|
||||
<t-table-column label="金额">
|
||||
<template #default="{ row }">{{ formatCurrency(row.amount) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="状态">
|
||||
</t-table-column>
|
||||
<t-table-column label="状态">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="row.status === 'confirmed' ? 'success' : 'warning'" size="small">
|
||||
<t-tag :type="row.status === 'confirmed' ? 'success' : 'warning'" size="small">
|
||||
{{ getTransactionStatusLabel(row.status) }}
|
||||
</el-tag>
|
||||
</t-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="日期">
|
||||
</t-table-column>
|
||||
<t-table-column label="日期">
|
||||
<template #default="{ row }">{{ formatDate(row.transaction_date) }}</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-empty v-if="!state.loading && state.financeTransactions.length === 0" description="暂无数据" />
|
||||
</el-card>
|
||||
</t-table-column>
|
||||
</t-table>
|
||||
<t-empty v-if="!state.loading && state.financeTransactions.length === 0" description="暂无数据" />
|
||||
</t-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ const { state, menuGroups, openGroups, toggleGroup, handleMenuClick } = useInven
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<el-menu
|
||||
<t-menu
|
||||
:default-active="state.activeTab"
|
||||
class="inventory-sidebar"
|
||||
@select="(key: string) => handleMenuClick(key)"
|
||||
@@ -13,17 +13,17 @@ const { state, menuGroups, openGroups, toggleGroup, handleMenuClick } = useInven
|
||||
<div v-for="group in menuGroups" :key="group.key" class="sidebar-group">
|
||||
<div class="sidebar-group-title" @click="toggleGroup(group.key)">
|
||||
<span>{{ group.title }}</span>
|
||||
<el-icon><component :is="openGroups[group.key] ? 'ArrowDown' : 'ArrowRight'" /></el-icon>
|
||||
<t-icon><component :is="openGroups[group.key] ? 'ArrowDown' : 'ArrowRight'" /></t-icon>
|
||||
</div>
|
||||
<template v-if="openGroups[group.key]">
|
||||
<el-menu-item
|
||||
<t-menu-item
|
||||
v-for="item in group.items"
|
||||
:key="group.key + '-' + item.key"
|
||||
:index="item.key"
|
||||
>
|
||||
{{ item.label }}
|
||||
</el-menu-item>
|
||||
</t-menu-item>
|
||||
</template>
|
||||
</div>
|
||||
</el-menu>
|
||||
</t-menu>
|
||||
</template>
|
||||
|
||||
@@ -87,62 +87,62 @@ onMounted(() => { loadInventory() })
|
||||
<template>
|
||||
<div class="inventory-tab">
|
||||
<div class="table-header">
|
||||
<el-button type="primary" @click="openCreate">+ 新增物料库存</el-button>
|
||||
<t-button type="primary" @click="openCreate">+ 新增物料库存</t-button>
|
||||
</div>
|
||||
<el-table :data="state.inventory" style="width: 100%" v-loading="state.loading" empty-text="暂无库存数据">
|
||||
<el-table-column prop="product_sku" label="SKU" />
|
||||
<el-table-column prop="product_name" label="物料" />
|
||||
<el-table-column prop="warehouse_name" label="仓库" />
|
||||
<el-table-column prop="quantity" label="数量" />
|
||||
<el-table-column prop="available_quantity" label="可用" />
|
||||
<el-table-column label="操作" width="180">
|
||||
<t-table :data="state.inventory" style="width: 100%" :loading="state.loading" empty-text="暂无库存数据">
|
||||
<t-table-column prop="product_sku" label="SKU" />
|
||||
<t-table-column prop="product_name" label="物料" />
|
||||
<t-table-column prop="warehouse_name" label="仓库" />
|
||||
<t-table-column prop="quantity" label="数量" />
|
||||
<t-table-column prop="available_quantity" label="可用" />
|
||||
<t-table-column label="操作" width="180">
|
||||
<template #default="{ row }">
|
||||
<el-button size="small" @click="openEdit(row)">编辑</el-button>
|
||||
<el-button size="small" type="danger" @click="deleteItem(row.id)">删除</el-button>
|
||||
<t-button size="small" @click="openEdit(row)">编辑</t-button>
|
||||
<t-button size="small" type="danger" @click="deleteItem(row.id)">删除</t-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</t-table-column>
|
||||
</t-table>
|
||||
|
||||
<el-dialog v-model="showModal" :title="editingItem ? '编辑物料库存' : '新增物料库存'" width="520px" :close-on-click-modal="false">
|
||||
<el-form :model="form" label-width="80px">
|
||||
<el-form-item label="物料" required>
|
||||
<el-select v-model="form.product_id" placeholder="请选择物料" style="width: 100%">
|
||||
<el-option
|
||||
<t-dialog v-model="showModal" :title="editingItem ? '编辑物料库存' : '新增物料库存'" width="520px" :close-on-click-modal="false">
|
||||
<t-form :model="form" label-width="80px">
|
||||
<t-form-item label="物料" required>
|
||||
<t-select v-model="form.product_id" placeholder="请选择物料" style="width: 100%">
|
||||
<t-option
|
||||
v-for="m in state.materials"
|
||||
:key="m.id"
|
||||
:label="m.name + (m.sku ? ' (' + m.sku + ')' : '')"
|
||||
:value="m.id"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="仓库" required>
|
||||
<el-select v-model="form.warehouse_id" placeholder="请选择仓库" style="width: 100%">
|
||||
<el-option
|
||||
</t-select>
|
||||
</t-form-item>
|
||||
<t-form-item label="仓库" required>
|
||||
<t-select v-model="form.warehouse_id" placeholder="请选择仓库" style="width: 100%">
|
||||
<t-option
|
||||
v-for="w in state.warehouses"
|
||||
:key="w.id"
|
||||
:label="w.name"
|
||||
:value="w.id"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="数量" required>
|
||||
<el-input-number v-model="form.quantity" :min="0" style="width: 100%" />
|
||||
</el-form-item>
|
||||
<el-form-item label="锁定数量">
|
||||
<el-input-number v-model="form.locked_quantity" :min="0" style="width: 100%" />
|
||||
</el-form-item>
|
||||
<el-form-item label="批次号">
|
||||
<el-input v-model="form.batch_no" placeholder="请输入批次号" />
|
||||
</el-form-item>
|
||||
<el-form-item label="库位">
|
||||
<el-input v-model="form.location" placeholder="请输入库位" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</t-select>
|
||||
</t-form-item>
|
||||
<t-form-item label="数量" required>
|
||||
<t-input-number v-model="form.quantity" :min="0" style="width: 100%" />
|
||||
</t-form-item>
|
||||
<t-form-item label="锁定数量">
|
||||
<t-input-number v-model="form.locked_quantity" :min="0" style="width: 100%" />
|
||||
</t-form-item>
|
||||
<t-form-item label="批次号">
|
||||
<t-input v-model="form.batch_no" placeholder="请输入批次号" />
|
||||
</t-form-item>
|
||||
<t-form-item label="库位">
|
||||
<t-input v-model="form.location" placeholder="请输入库位" />
|
||||
</t-form-item>
|
||||
</t-form>
|
||||
<template #footer>
|
||||
<el-button @click="showModal = false">取消</el-button>
|
||||
<el-button type="primary" @click="save">保存</el-button>
|
||||
<t-button @click="showModal = false">取消</t-button>
|
||||
<t-button type="primary" @click="save">保存</t-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</t-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -175,139 +175,139 @@ onMounted(() => { loadMaterials() })
|
||||
<template>
|
||||
<div>
|
||||
<div style="margin-bottom: 12px; display: flex; gap: 8px;">
|
||||
<el-button type="primary" @click="openCreateMaterial">新增物料</el-button>
|
||||
<el-button type="success" @click="openRestockModal">物料补货</el-button>
|
||||
<t-button type="primary" @click="openCreateMaterial">新增物料</t-button>
|
||||
<t-button type="success" @click="openRestockModal">物料补货</t-button>
|
||||
</div>
|
||||
|
||||
<el-table :data="state.materials" v-loading="state.loading" stripe>
|
||||
<el-table-column prop="sku" label="SKU" />
|
||||
<el-table-column prop="name" label="名称" />
|
||||
<el-table-column prop="category" label="分类">
|
||||
<t-table :data="state.materials" :loading="state.loading" stripe>
|
||||
<t-table-column prop="sku" label="SKU" />
|
||||
<t-table-column prop="name" label="名称" />
|
||||
<t-table-column prop="category" label="分类">
|
||||
<template #default="{ row }">{{ row.category || '-' }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="unit" label="单位" />
|
||||
<el-table-column label="成本价">
|
||||
</t-table-column>
|
||||
<t-table-column prop="unit" label="单位" />
|
||||
<t-table-column label="成本价">
|
||||
<template #default="{ row }">{{ formatCurrency(row.cost_price) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="min_stock" label="最低库存">
|
||||
</t-table-column>
|
||||
<t-table-column prop="min_stock" label="最低库存">
|
||||
<template #default="{ row }">{{ row.min_stock ?? '-' }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="180">
|
||||
</t-table-column>
|
||||
<t-table-column label="操作" width="180">
|
||||
<template #default="{ row }">
|
||||
<el-button type="primary" size="small" @click="editMaterial(row)">编辑</el-button>
|
||||
<el-button type="danger" size="small" @click="deleteMaterial(row.id)">删除</el-button>
|
||||
<t-button type="primary" size="small" @click="editMaterial(row)">编辑</t-button>
|
||||
<t-button type="danger" size="small" @click="deleteMaterial(row.id)">删除</t-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-empty v-if="!state.loading && state.materials.length === 0" description="暂无物料数据" />
|
||||
</t-table-column>
|
||||
</t-table>
|
||||
<t-empty v-if="!state.loading && state.materials.length === 0" description="暂无物料数据" />
|
||||
|
||||
<el-dialog
|
||||
v-model="showModal"
|
||||
<t-dialog
|
||||
v-model:visible="showModal"
|
||||
:title="(editingItem ? '编辑' : '新增') + '物料'"
|
||||
width="560px"
|
||||
@closed="closeModal"
|
||||
>
|
||||
<el-form label-width="100px">
|
||||
<el-form-item label="类型">
|
||||
<el-input model-value="物料(纳入库存)" disabled />
|
||||
</el-form-item>
|
||||
<el-form-item label="SKU" required>
|
||||
<el-input v-model="form.sku" placeholder="产品编码" />
|
||||
</el-form-item>
|
||||
<el-form-item label="名称" required>
|
||||
<el-input v-model="form.name" placeholder="产品名称" />
|
||||
</el-form-item>
|
||||
<el-form-item label="分类">
|
||||
<el-input v-model="form.category" placeholder="产品分类" />
|
||||
</el-form-item>
|
||||
<el-form-item label="单位">
|
||||
<el-input v-model="form.unit" placeholder="kg" />
|
||||
</el-form-item>
|
||||
<el-form-item label="成本价">
|
||||
<el-input-number v-model="form.cost_price" :precision="2" :min="0" :step="0.01" style="width:100%" />
|
||||
</el-form-item>
|
||||
<el-form-item label="最低库存">
|
||||
<el-input-number v-model="form.min_stock" :min="0" style="width:100%" />
|
||||
</el-form-item>
|
||||
<el-form-item label="最高库存">
|
||||
<el-input-number v-model="form.max_stock" :min="0" style="width:100%" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<t-form label-width="100px">
|
||||
<t-form-item label="类型">
|
||||
<t-input model-value="物料(纳入库存)" disabled />
|
||||
</t-form-item>
|
||||
<t-form-item label="SKU" required>
|
||||
<t-input v-model="form.sku" placeholder="产品编码" />
|
||||
</t-form-item>
|
||||
<t-form-item label="名称" required>
|
||||
<t-input v-model="form.name" placeholder="产品名称" />
|
||||
</t-form-item>
|
||||
<t-form-item label="分类">
|
||||
<t-input v-model="form.category" placeholder="产品分类" />
|
||||
</t-form-item>
|
||||
<t-form-item label="单位">
|
||||
<t-input v-model="form.unit" placeholder="kg" />
|
||||
</t-form-item>
|
||||
<t-form-item label="成本价">
|
||||
<t-input-number v-model="form.cost_price" :precision="2" :min="0" :step="0.01" style="width:100%" />
|
||||
</t-form-item>
|
||||
<t-form-item label="最低库存">
|
||||
<t-input-number v-model="form.min_stock" :min="0" style="width:100%" />
|
||||
</t-form-item>
|
||||
<t-form-item label="最高库存">
|
||||
<t-input-number v-model="form.max_stock" :min="0" style="width:100%" />
|
||||
</t-form-item>
|
||||
</t-form>
|
||||
<template #footer>
|
||||
<el-button @click="showModal = false">取消</el-button>
|
||||
<el-button type="primary" @click="saveProduct">保存</el-button>
|
||||
<t-button @click="showModal = false">取消</t-button>
|
||||
<t-button type="primary" @click="saveProduct">保存</t-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</t-dialog>
|
||||
|
||||
<el-dialog
|
||||
v-model="showRestockModal"
|
||||
<t-dialog
|
||||
v-model:visible="showRestockModal"
|
||||
title="物料补货"
|
||||
width="900px"
|
||||
@closed="closeRestockModal"
|
||||
>
|
||||
<el-form label-width="100px" style="margin-bottom: 16px;">
|
||||
<el-form-item label="供应商">
|
||||
<el-select v-model="restockSupplierId" placeholder="请选择供应商" style="width:100%">
|
||||
<el-option
|
||||
<t-form label-width="100px" style="margin-bottom: 16px;">
|
||||
<t-form-item label="供应商">
|
||||
<t-select v-model="restockSupplierId" placeholder="请选择供应商" style="width:100%">
|
||||
<t-option
|
||||
v-for="supplier in state.suppliers"
|
||||
:key="supplier.id"
|
||||
:label="supplier.name"
|
||||
:value="supplier.id"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</t-select>
|
||||
</t-form-item>
|
||||
</t-form>
|
||||
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 12px;">
|
||||
<span style="font-weight: 600;">补货物料明细</span>
|
||||
<el-button type="primary" size="small" @click="addRestockItem">+ 添加物料</el-button>
|
||||
<t-button type="primary" size="small" @click="addRestockItem">+ 添加物料</t-button>
|
||||
</div>
|
||||
<el-table :data="restockItems" border size="small">
|
||||
<el-table-column label="物料" min-width="200">
|
||||
<t-table :data="restockItems" border size="small">
|
||||
<t-table-column label="物料" min-width="200">
|
||||
<template #default="{ row: line }">
|
||||
<el-select v-model="line.material_id" placeholder="请选择物料" style="width:100%">
|
||||
<el-option
|
||||
<t-select v-model="line.material_id" placeholder="请选择物料" style="width:100%">
|
||||
<t-option
|
||||
v-for="material in state.materials"
|
||||
:key="material.id"
|
||||
:label="`${material.sku} - ${material.name}`"
|
||||
:value="material.id"
|
||||
/>
|
||||
</el-select>
|
||||
</t-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="数量" width="120">
|
||||
</t-table-column>
|
||||
<t-table-column label="数量" width="120">
|
||||
<template #default="{ row: line }">
|
||||
<el-input-number v-model="line.quantity" :min="1" size="small" style="width:100%" />
|
||||
<t-input-number v-model="line.quantity" :min="1" size="small" style="width:100%" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="单价" width="120">
|
||||
</t-table-column>
|
||||
<t-table-column label="单价" width="120">
|
||||
<template #default="{ row: line }">
|
||||
<el-input-number v-model="line.unit_price" :min="0" :precision="2" :step="0.01" size="small" style="width:100%" />
|
||||
<t-input-number v-model="line.unit_price" :min="0" :precision="2" :step="0.01" size="small" style="width:100%" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="总价" width="120">
|
||||
</t-table-column>
|
||||
<t-table-column label="总价" width="120">
|
||||
<template #default="{ row: line }">
|
||||
{{ formatCurrency((line.unit_price || 0) * (line.quantity || 0)) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="备注" width="150">
|
||||
</t-table-column>
|
||||
<t-table-column label="备注" width="150">
|
||||
<template #default="{ row: line }">
|
||||
<el-input v-model="line.remark" size="small" placeholder="备注" />
|
||||
<t-input v-model="line.remark" size="small" placeholder="备注" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="80">
|
||||
</t-table-column>
|
||||
<t-table-column label="操作" width="80">
|
||||
<template #default="{ $index }">
|
||||
<el-button type="danger" size="small" @click="removeRestockItem($index)">删除</el-button>
|
||||
<t-button type="danger" size="small" @click="removeRestockItem($index)">删除</t-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</t-table-column>
|
||||
</t-table>
|
||||
<div style="text-align: right; margin-top: 8px; font-weight: 600;">
|
||||
补货总金额:{{ formatCurrency(restockTotalAmount) }}
|
||||
</div>
|
||||
<template #footer>
|
||||
<el-button @click="showRestockModal = false">取消</el-button>
|
||||
<el-button type="primary" @click="saveRestock">创建采购订单</el-button>
|
||||
<t-button @click="showRestockModal = false">取消</t-button>
|
||||
<t-button type="primary" @click="saveRestock">创建采购订单</t-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</t-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -16,28 +16,28 @@ onMounted(() => { loadMovements() })
|
||||
|
||||
<template>
|
||||
<div class="movements-tab">
|
||||
<el-table :data="state.movements" style="width: 100%" v-loading="state.loading" empty-text="暂无库存变动记录">
|
||||
<el-table-column label="物料">
|
||||
<t-table :data="state.movements" style="width: 100%" :loading="state.loading" empty-text="暂无库存变动记录">
|
||||
<t-table-column label="物料">
|
||||
<template #default="{ row }">
|
||||
{{ row.product_name }}{{ row.product_sku ? ' (' + row.product_sku + ')' : '' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="类型" width="140">
|
||||
</t-table-column>
|
||||
<t-table-column label="类型" width="140">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="getMovementTagType(row.movement_type)" size="small">
|
||||
<t-tag :type="getMovementTagType(row.movement_type)" size="small">
|
||||
{{ getMovementTypeLabel(row.movement_type) }}
|
||||
</el-tag>
|
||||
</t-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="quantity" label="数量" width="80" />
|
||||
<el-table-column prop="before_quantity" label="变动前" width="80" />
|
||||
<el-table-column prop="after_quantity" label="变动后" width="80" />
|
||||
<el-table-column label="时间" width="180">
|
||||
</t-table-column>
|
||||
<t-table-column prop="quantity" label="数量" width="80" />
|
||||
<t-table-column prop="before_quantity" label="变动前" width="80" />
|
||||
<t-table-column prop="after_quantity" label="变动后" width="80" />
|
||||
<t-table-column label="时间" width="180">
|
||||
<template #default="{ row }">
|
||||
{{ formatDateTime(row.created_at) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</t-table-column>
|
||||
</t-table>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -124,102 +124,102 @@ onMounted(() => { loadFinishedProducts() })
|
||||
<template>
|
||||
<div>
|
||||
<div style="margin-bottom: 12px;">
|
||||
<el-button type="primary" @click="openCreateProduct">新增成品</el-button>
|
||||
<t-button type="primary" @click="openCreateProduct">新增成品</t-button>
|
||||
</div>
|
||||
|
||||
<el-table :data="state.finishedProducts" v-loading="state.loading" stripe>
|
||||
<el-table-column prop="sku" label="SKU" />
|
||||
<el-table-column prop="name" label="名称" />
|
||||
<el-table-column prop="category" label="分类">
|
||||
<t-table :data="state.finishedProducts" :loading="state.loading" stripe>
|
||||
<t-table-column prop="sku" label="SKU" />
|
||||
<t-table-column prop="name" label="名称" />
|
||||
<t-table-column prop="category" label="分类">
|
||||
<template #default="{ row }">{{ row.category || '-' }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="unit" label="单位" />
|
||||
<el-table-column label="成本价">
|
||||
</t-table-column>
|
||||
<t-table-column prop="unit" label="单位" />
|
||||
<t-table-column label="成本价">
|
||||
<template #default="{ row }">{{ formatCurrency(row.cost_price) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="销售价">
|
||||
</t-table-column>
|
||||
<t-table-column label="销售价">
|
||||
<template #default="{ row }">{{ formatCurrency(row.sale_price) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="基础物料成本">
|
||||
</t-table-column>
|
||||
<t-table-column label="基础物料成本">
|
||||
<template #default="{ row }">{{ formatCurrency(row.material_cost || 0) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="180">
|
||||
</t-table-column>
|
||||
<t-table-column label="操作" width="180">
|
||||
<template #default="{ row }">
|
||||
<el-button type="primary" size="small" @click="editProduct(row)">编辑</el-button>
|
||||
<el-button type="danger" size="small" @click="deleteProduct(row.id)">删除</el-button>
|
||||
<t-button type="primary" size="small" @click="editProduct(row)">编辑</t-button>
|
||||
<t-button type="danger" size="small" @click="deleteProduct(row.id)">删除</t-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-empty v-if="!state.loading && state.finishedProducts.length === 0" description="暂无成品数据" />
|
||||
</t-table-column>
|
||||
</t-table>
|
||||
<t-empty v-if="!state.loading && state.finishedProducts.length === 0" description="暂无成品数据" />
|
||||
|
||||
<el-dialog
|
||||
v-model="showModal"
|
||||
<t-dialog
|
||||
v-model:visible="showModal"
|
||||
:title="(editingItem ? '编辑' : '新增') + '成品'"
|
||||
width="560px"
|
||||
@closed="closeModal"
|
||||
>
|
||||
<el-form label-width="100px">
|
||||
<el-form-item label="类型">
|
||||
<el-input model-value="成品(按单生产,不做库存)" disabled />
|
||||
</el-form-item>
|
||||
<el-form-item label="SKU" required>
|
||||
<el-input v-model="form.sku" placeholder="产品编码" />
|
||||
</el-form-item>
|
||||
<el-form-item label="名称" required>
|
||||
<el-input v-model="form.name" placeholder="产品名称" />
|
||||
</el-form-item>
|
||||
<el-form-item label="分类">
|
||||
<el-input v-model="form.category" placeholder="产品分类" />
|
||||
</el-form-item>
|
||||
<el-form-item label="单位">
|
||||
<el-input v-model="form.unit" placeholder="件" />
|
||||
</el-form-item>
|
||||
<el-form-item label="成本价">
|
||||
<el-input-number v-model="form.cost_price" :precision="2" :min="0" :step="0.01" style="width:100%" />
|
||||
</el-form-item>
|
||||
<el-form-item label="销售价">
|
||||
<el-input-number v-model="form.sale_price" :precision="2" :min="0" :step="0.01" style="width:100%" />
|
||||
</el-form-item>
|
||||
<el-form-item label="说明">
|
||||
<el-input model-value="成品不做库存,成本由下方BOM定义物料构成后自动计算" disabled />
|
||||
</el-form-item>
|
||||
<t-form label-width="100px">
|
||||
<t-form-item label="类型">
|
||||
<t-input model-value="成品(按单生产,不做库存)" disabled />
|
||||
</t-form-item>
|
||||
<t-form-item label="SKU" required>
|
||||
<t-input v-model="form.sku" placeholder="产品编码" />
|
||||
</t-form-item>
|
||||
<t-form-item label="名称" required>
|
||||
<t-input v-model="form.name" placeholder="产品名称" />
|
||||
</t-form-item>
|
||||
<t-form-item label="分类">
|
||||
<t-input v-model="form.category" placeholder="产品分类" />
|
||||
</t-form-item>
|
||||
<t-form-item label="单位">
|
||||
<t-input v-model="form.unit" placeholder="件" />
|
||||
</t-form-item>
|
||||
<t-form-item label="成本价">
|
||||
<t-input-number v-model="form.cost_price" :precision="2" :min="0" :step="0.01" style="width:100%" />
|
||||
</t-form-item>
|
||||
<t-form-item label="销售价">
|
||||
<t-input-number v-model="form.sale_price" :precision="2" :min="0" :step="0.01" style="width:100%" />
|
||||
</t-form-item>
|
||||
<t-form-item label="说明">
|
||||
<t-input model-value="成品不做库存,成本由下方BOM定义物料构成后自动计算" disabled />
|
||||
</t-form-item>
|
||||
|
||||
<template v-if="editingItem">
|
||||
<el-divider content-position="left">BOM物料配置</el-divider>
|
||||
<t-divider content-position="left">BOM物料配置</t-divider>
|
||||
<div style="padding: 0 12px 12px 12px;">
|
||||
<el-button type="primary" size="small" @click="addBomItem" style="margin-bottom:8px">+ 添加物料</el-button>
|
||||
<el-table :data="bomItems" size="small" border>
|
||||
<el-table-column label="物料">
|
||||
<t-button type="primary" size="small" @click="addBomItem" style="margin-bottom:8px">+ 添加物料</t-button>
|
||||
<t-table :data="bomItems" size="small" border>
|
||||
<t-table-column label="物料">
|
||||
<template #default="{ row: bomItem }">
|
||||
<el-select v-model="bomItem.material_id" placeholder="选择物料" style="width:100%">
|
||||
<el-option
|
||||
<t-select v-model="bomItem.material_id" placeholder="选择物料" style="width:100%">
|
||||
<t-option
|
||||
v-for="material in state.materials"
|
||||
:key="material.id"
|
||||
:label="`${material.sku} - ${material.name}`"
|
||||
:value="material.id"
|
||||
/>
|
||||
</el-select>
|
||||
</t-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="数量" width="120">
|
||||
</t-table-column>
|
||||
<t-table-column label="数量" width="120">
|
||||
<template #default="{ row: bomItem }">
|
||||
<el-input-number v-model="bomItem.quantity" :min="0.0001" :step="0.0001" size="small" style="width:100%" />
|
||||
<t-input-number v-model="bomItem.quantity" :min="0.0001" :step="0.0001" size="small" style="width:100%" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="80">
|
||||
</t-table-column>
|
||||
<t-table-column label="操作" width="80">
|
||||
<template #default="{ $index }">
|
||||
<el-button type="danger" size="small" @click="removeBomItem($index)">删除</el-button>
|
||||
<t-button type="danger" size="small" @click="removeBomItem($index)">删除</t-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</t-table-column>
|
||||
</t-table>
|
||||
</div>
|
||||
</template>
|
||||
</el-form>
|
||||
</t-form>
|
||||
<template #footer>
|
||||
<el-button @click="showModal = false">取消</el-button>
|
||||
<el-button type="primary" @click="saveProduct">保存</el-button>
|
||||
<t-button @click="showModal = false">取消</t-button>
|
||||
<t-button type="primary" @click="saveProduct">保存</t-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</t-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -1,10 +1,22 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, onMounted } from 'vue'
|
||||
import { ElMessageBox } from 'element-plus'
|
||||
import { DialogPlugin } from 'tdesign-vue-next'
|
||||
import { useInventory } from '../composables/useInventory'
|
||||
import { apiRequest } from '@/shared/api'
|
||||
import { addNotification, handleApiError } from '@/shared/notification'
|
||||
|
||||
function confirmDialog(header: string, body: string, theme: string, confirmText: string, cancelText: string): Promise<boolean> {
|
||||
return new Promise((resolve) => {
|
||||
const dlg = DialogPlugin.confirm({
|
||||
header, body, theme: theme as any,
|
||||
confirmBtn: confirmText, cancelBtn: cancelText,
|
||||
onConfirm: () => { dlg.hide(); resolve(true) },
|
||||
onCancel: () => { dlg.hide(); resolve(false) },
|
||||
onClose: () => { resolve(false) }
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
const {
|
||||
state,
|
||||
formatCurrency,
|
||||
@@ -140,11 +152,7 @@ async function savePurchaseOrder() {
|
||||
}
|
||||
|
||||
async function deleteOrder(id: number) {
|
||||
try {
|
||||
await ElMessageBox.confirm('确定要删除这个采购订单吗?', '删除确认', {
|
||||
confirmButtonText: '删除', cancelButtonText: '取消', type: 'warning'
|
||||
})
|
||||
} catch { return }
|
||||
if (!await confirmDialog('删除确认', '确定要删除这个采购订单吗?', 'warning', '删除', '取消')) return
|
||||
try {
|
||||
await apiRequest(`/api/purchase-orders/${id}`, { method: 'DELETE' })
|
||||
addNotification('采购订单已删除', 'success')
|
||||
@@ -212,29 +220,15 @@ async function receivePurchaseOrder() {
|
||||
|
||||
async function markAsPaid(orderId: number, receiptStatus: string) {
|
||||
if (receiptStatus !== 'received') {
|
||||
try {
|
||||
await ElMessageBox.confirm(
|
||||
'该订单尚未全部收货,确定要提前付款吗?建议先完成收货后再付款。',
|
||||
'非标准流程提醒',
|
||||
{ confirmButtonText: '仍要付款', cancelButtonText: '取消', type: 'warning' }
|
||||
)
|
||||
} catch { return }
|
||||
if (!await confirmDialog('非标准流程提醒', '该订单尚未全部收货,确定要提前付款吗?建议先完成收货后再付款。', 'warning', '仍要付款', '取消')) return
|
||||
} else {
|
||||
try {
|
||||
await ElMessageBox.confirm('确认已向供应商支付该订单款项?', '付款确认', {
|
||||
confirmButtonText: '确认付款', cancelButtonText: '取消', type: 'success'
|
||||
})
|
||||
} catch { return }
|
||||
if (!await confirmDialog('付款确认', '确认已向供应商支付该订单款项?', 'success', '确认付款', '取消')) return
|
||||
}
|
||||
await doUpdateStatus(orderId, 'paid', '已付款')
|
||||
}
|
||||
|
||||
async function cancelOrder(orderId: number) {
|
||||
try {
|
||||
await ElMessageBox.confirm('确定要作废该订单吗?此操作不可撤销。', '作废确认', {
|
||||
confirmButtonText: '确认作废', cancelButtonText: '取消', type: 'error'
|
||||
})
|
||||
} catch { return }
|
||||
if (!await confirmDialog('作废确认', '确定要作废该订单吗?此操作不可撤销。', 'error', '确认作废', '取消')) return
|
||||
await doUpdateStatus(orderId, 'cancelled', '已作废')
|
||||
}
|
||||
|
||||
@@ -280,223 +274,223 @@ onMounted(() => {
|
||||
<template>
|
||||
<div>
|
||||
<div style="margin-bottom: 12px; display: flex; gap: 12px; align-items: center;">
|
||||
<el-select
|
||||
<t-select
|
||||
v-model="purchaseWarehouseId"
|
||||
placeholder="选择仓库"
|
||||
style="width: 200px;"
|
||||
clearable
|
||||
>
|
||||
<el-option
|
||||
<t-option
|
||||
v-for="warehouse in state.warehouses"
|
||||
:key="warehouse.id"
|
||||
:label="warehouse.name"
|
||||
:value="warehouse.id"
|
||||
/>
|
||||
</el-select>
|
||||
<el-button @click="loadPurchaseOrders">刷新</el-button>
|
||||
<el-button type="primary" @click="openCreateOrder">新增采购订单</el-button>
|
||||
</t-select>
|
||||
<t-button @click="loadPurchaseOrders">刷新</t-button>
|
||||
<t-button type="primary" @click="openCreateOrder">新增采购订单</t-button>
|
||||
</div>
|
||||
|
||||
<el-table :data="state.purchaseOrders" v-loading="state.loading" stripe>
|
||||
<el-table-column prop="order_no" label="采购单" />
|
||||
<el-table-column prop="supplier_name" label="供应商" />
|
||||
<el-table-column label="状态">
|
||||
<t-table :data="state.purchaseOrders" :loading="state.loading" stripe>
|
||||
<t-table-column prop="order_no" label="采购单" />
|
||||
<t-table-column prop="supplier_name" label="供应商" />
|
||||
<t-table-column label="状态">
|
||||
<template #default="{ row }">
|
||||
<div style="display: flex; gap: 4px;">
|
||||
<el-tag
|
||||
<t-tag
|
||||
:type="row.receipt_status === 'received' ? 'success' : row.receipt_status === 'partial_received' ? 'warning' : row.receipt_status === 'cancelled' ? 'danger' : 'info'"
|
||||
size="small"
|
||||
>{{ getReceiptStatusLabel(row.receipt_status) }}</el-tag>
|
||||
<el-tag
|
||||
>{{ getReceiptStatusLabel(row.receipt_status) }}</t-tag>
|
||||
<t-tag
|
||||
:type="row.payment_status === 'paid' ? 'success' : 'info'"
|
||||
size="small"
|
||||
>{{ getPaymentStatusLabel(row.payment_status) }}</el-tag>
|
||||
>{{ getPaymentStatusLabel(row.payment_status) }}</t-tag>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="订单创建">
|
||||
</t-table-column>
|
||||
<t-table-column label="订单创建">
|
||||
<template #default="{ row }">{{ formatDateTime(row.created_at) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="预计到货">
|
||||
</t-table-column>
|
||||
<t-table-column label="预计到货">
|
||||
<template #default="{ row }">{{ formatDate(row.expected_date) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="实际到货">
|
||||
</t-table-column>
|
||||
<t-table-column label="实际到货">
|
||||
<template #default="{ row }">{{ row.received_at ? formatDateTime(row.received_at) : '-' }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="实际付款">
|
||||
</t-table-column>
|
||||
<t-table-column label="实际付款">
|
||||
<template #default="{ row }">{{ row.paid_at ? formatDateTime(row.paid_at) : '-' }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="总金额">
|
||||
</t-table-column>
|
||||
<t-table-column label="总金额">
|
||||
<template #default="{ row }">{{ formatCurrency(row.total_amount) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="已付款">
|
||||
</t-table-column>
|
||||
<t-table-column label="已付款">
|
||||
<template #default="{ row }">{{ formatCurrency(row.paid_amount || 0) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="280">
|
||||
</t-table-column>
|
||||
<t-table-column label="操作" width="280">
|
||||
<template #default="{ row }">
|
||||
<el-button
|
||||
<t-button
|
||||
type="primary"
|
||||
size="small"
|
||||
:disabled="isPurchaseOrderLocked(row.status)"
|
||||
@click="editOrder(row)"
|
||||
>
|
||||
编辑
|
||||
</el-button>
|
||||
<el-button
|
||||
</t-button>
|
||||
<t-button
|
||||
type="danger"
|
||||
size="small"
|
||||
:disabled="isPurchaseOrderLocked(row.status)"
|
||||
@click="deleteOrder(row.id)"
|
||||
>
|
||||
删除
|
||||
</el-button>
|
||||
<el-button
|
||||
</t-button>
|
||||
<t-button
|
||||
v-if="row.receipt_status === 'pending' || row.receipt_status === 'partial_received'"
|
||||
type="success"
|
||||
size="small"
|
||||
@click="openReceiveDialog(row)"
|
||||
>
|
||||
到货入库
|
||||
</el-button>
|
||||
<el-button
|
||||
</t-button>
|
||||
<t-button
|
||||
v-if="row.payment_status !== 'paid' && row.receipt_status !== 'cancelled'"
|
||||
type="warning"
|
||||
size="small"
|
||||
@click="markAsPaid(row.id, row.receipt_status)"
|
||||
>
|
||||
标记已付款
|
||||
</el-button>
|
||||
<el-button
|
||||
</t-button>
|
||||
<t-button
|
||||
v-if="row.payment_status !== 'paid' && row.receipt_status !== 'cancelled'"
|
||||
type="info"
|
||||
size="small"
|
||||
@click="cancelOrder(row.id)"
|
||||
>
|
||||
作废
|
||||
</el-button>
|
||||
</t-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-empty v-if="!state.loading && state.purchaseOrders.length === 0" description="暂无采购订单" />
|
||||
</t-table-column>
|
||||
</t-table>
|
||||
<t-empty v-if="!state.loading && state.purchaseOrders.length === 0" description="暂无采购订单" />
|
||||
|
||||
<el-dialog
|
||||
v-model="showModal"
|
||||
<t-dialog
|
||||
v-model:visible="showModal"
|
||||
:title="(editingItem ? '编辑' : '新增') + '采购订单'"
|
||||
width="800px"
|
||||
@closed="closeModal"
|
||||
>
|
||||
<el-form label-width="100px">
|
||||
<el-form-item label="供应商" required>
|
||||
<el-select v-model="form.supplier_id" placeholder="请选择供应商" style="width:100%">
|
||||
<el-option
|
||||
<t-form label-width="100px">
|
||||
<t-form-item label="供应商" required>
|
||||
<t-select v-model="form.supplier_id" placeholder="请选择供应商" style="width:100%">
|
||||
<t-option
|
||||
v-for="supplier in state.suppliers"
|
||||
:key="supplier.id"
|
||||
:label="supplier.name"
|
||||
:value="supplier.id"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="预计到货">
|
||||
<el-date-picker
|
||||
</t-select>
|
||||
</t-form-item>
|
||||
<t-form-item label="预计到货">
|
||||
<t-date-picker
|
||||
v-model="form.expected_date"
|
||||
type="date"
|
||||
placeholder="选择日期"
|
||||
style="width:100%"
|
||||
value-format="YYYY-MM-DD"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="备注">
|
||||
<el-input v-model="form.remark" placeholder="备注信息" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</t-form-item>
|
||||
<t-form-item label="备注">
|
||||
<t-input v-model="form.remark" placeholder="备注信息" />
|
||||
</t-form-item>
|
||||
</t-form>
|
||||
|
||||
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 12px;">
|
||||
<span style="font-weight: 600;">物料明细</span>
|
||||
<el-button type="primary" size="small" @click="addOrderItem">+ 添加物料</el-button>
|
||||
<t-button type="primary" size="small" @click="addOrderItem">+ 添加物料</t-button>
|
||||
</div>
|
||||
<el-table :data="orderItems" border size="small">
|
||||
<el-table-column label="物料" min-width="200">
|
||||
<t-table :data="orderItems" border size="small">
|
||||
<t-table-column label="物料" min-width="200">
|
||||
<template #default="{ row: line }">
|
||||
<el-select v-model="line.product_id" placeholder="请选择物料" style="width:100%">
|
||||
<el-option
|
||||
<t-select v-model="line.product_id" placeholder="请选择物料" style="width:100%">
|
||||
<t-option
|
||||
v-for="material in state.materials"
|
||||
:key="material.id"
|
||||
:label="`${material.sku} - ${material.name}`"
|
||||
:value="material.id"
|
||||
/>
|
||||
</el-select>
|
||||
</t-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="数量" width="120">
|
||||
</t-table-column>
|
||||
<t-table-column label="数量" width="120">
|
||||
<template #default="{ row: line }">
|
||||
<el-input-number v-model="line.quantity" :min="0.0001" :step="0.0001" size="small" style="width:100%" />
|
||||
<t-input-number v-model="line.quantity" :min="0.0001" :step="0.0001" size="small" style="width:100%" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="单价" width="120">
|
||||
</t-table-column>
|
||||
<t-table-column label="单价" width="120">
|
||||
<template #default="{ row: line }">
|
||||
<el-input-number
|
||||
<t-input-number
|
||||
:model-value="(state.materials.find((m: any) => m.id === line.product_id)?.cost_price || 0)"
|
||||
disabled
|
||||
size="small"
|
||||
style="width:100%"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="总价" width="120">
|
||||
</t-table-column>
|
||||
<t-table-column label="总价" width="120">
|
||||
<template #default="{ row: line }">
|
||||
{{ formatCurrency((state.materials.find((m: any) => m.id === line.product_id)?.cost_price || 0) * (line.quantity || 0)) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="备注" width="150">
|
||||
</t-table-column>
|
||||
<t-table-column label="备注" width="150">
|
||||
<template #default="{ row: line }">
|
||||
<el-input v-model="line.remark" size="small" placeholder="备注" />
|
||||
<t-input v-model="line.remark" size="small" placeholder="备注" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="80">
|
||||
</t-table-column>
|
||||
<t-table-column label="操作" width="80">
|
||||
<template #default="{ $index }">
|
||||
<el-button type="danger" size="small" @click="removeOrderItem($index)">删除</el-button>
|
||||
<t-button type="danger" size="small" @click="removeOrderItem($index)">删除</t-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</t-table-column>
|
||||
</t-table>
|
||||
<div style="text-align: right; margin-top: 8px; font-weight: 600;">
|
||||
订单总金额:{{ formatCurrency(orderTotalAmount) }}
|
||||
</div>
|
||||
<template #footer>
|
||||
<el-button @click="showModal = false">取消</el-button>
|
||||
<el-button type="primary" @click="savePurchaseOrder">保存</el-button>
|
||||
<t-button @click="showModal = false">取消</t-button>
|
||||
<t-button type="primary" @click="savePurchaseOrder">保存</t-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</t-dialog>
|
||||
|
||||
<el-dialog
|
||||
v-model="showReceiveModal"
|
||||
<t-dialog
|
||||
v-model:visible="showReceiveModal"
|
||||
title="采购到货入库"
|
||||
width="700px"
|
||||
@closed="closeReceiveModal"
|
||||
>
|
||||
<el-form label-width="100px">
|
||||
<el-form-item label="入库仓库" required>
|
||||
<el-select v-model="receiveWarehouseId" placeholder="请选择仓库" style="width:100%">
|
||||
<el-option
|
||||
<t-form label-width="100px">
|
||||
<t-form-item label="入库仓库" required>
|
||||
<t-select v-model="receiveWarehouseId" placeholder="请选择仓库" style="width:100%">
|
||||
<t-option
|
||||
v-for="warehouse in state.warehouses"
|
||||
:key="warehouse.id"
|
||||
:label="warehouse.name"
|
||||
:value="warehouse.id"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="备注">
|
||||
<el-input v-model="receiveRemark" placeholder="入库备注" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-table :data="receiveItems" border size="small">
|
||||
<el-table-column prop="material_label" label="物料" />
|
||||
<el-table-column prop="id" label="明细ID" width="80" />
|
||||
<el-table-column label="剩余待入库" width="100">
|
||||
</t-select>
|
||||
</t-form-item>
|
||||
<t-form-item label="备注">
|
||||
<t-input v-model="receiveRemark" placeholder="入库备注" />
|
||||
</t-form-item>
|
||||
</t-form>
|
||||
<t-table :data="receiveItems" border size="small">
|
||||
<t-table-column prop="material_label" label="物料" />
|
||||
<t-table-column prop="id" label="明细ID" width="80" />
|
||||
<t-table-column label="剩余待入库" width="100">
|
||||
<template #default="{ row: item }">{{ item.remaining }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="本次入库" width="140">
|
||||
</t-table-column>
|
||||
<t-table-column label="本次入库" width="140">
|
||||
<template #default="{ row: item }">
|
||||
<el-input-number
|
||||
<t-input-number
|
||||
v-model="item.receive_quantity"
|
||||
:min="0"
|
||||
:max="item.remaining"
|
||||
@@ -504,13 +498,13 @@ onMounted(() => {
|
||||
style="width:100%"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</t-table-column>
|
||||
</t-table>
|
||||
<template #footer>
|
||||
<el-button @click="showReceiveModal = false">取消</el-button>
|
||||
<el-button type="primary" @click="receivePurchaseOrder">确认入库</el-button>
|
||||
<t-button @click="showReceiveModal = false">取消</t-button>
|
||||
<t-button type="primary" @click="receivePurchaseOrder">确认入库</t-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</t-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -1,10 +1,22 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, onMounted } from 'vue'
|
||||
import { ElMessageBox } from 'element-plus'
|
||||
import { DialogPlugin } from 'tdesign-vue-next'
|
||||
import { useInventory } from '../composables/useInventory'
|
||||
import { apiRequest } from '@/shared/api'
|
||||
import { addNotification, handleApiError } from '@/shared/notification'
|
||||
|
||||
function confirmDialog(header: string, body: string, theme: string, confirmText: string, cancelText: string): Promise<boolean> {
|
||||
return new Promise((resolve) => {
|
||||
const dlg = DialogPlugin.confirm({
|
||||
header, body, theme: theme as any,
|
||||
confirmBtn: confirmText, cancelBtn: cancelText,
|
||||
onConfirm: () => { dlg.hide(); resolve(true) },
|
||||
onCancel: () => { dlg.hide(); resolve(false) },
|
||||
onClose: () => { resolve(false) }
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
const {
|
||||
state,
|
||||
formatCurrency,
|
||||
@@ -156,11 +168,7 @@ async function saveSalesOrder() {
|
||||
}
|
||||
|
||||
async function deleteOrder(id: number) {
|
||||
try {
|
||||
await ElMessageBox.confirm('确定要删除这个销售订单吗?', '删除确认', {
|
||||
confirmButtonText: '删除', cancelButtonText: '取消', type: 'warning'
|
||||
})
|
||||
} catch { return }
|
||||
if (!await confirmDialog('删除确认', '确定要删除这个销售订单吗?', 'warning', '删除', '取消')) return
|
||||
try {
|
||||
await apiRequest(`/api/sales-orders/${id}`, { method: 'DELETE' })
|
||||
addNotification('销售订单已删除', 'success')
|
||||
@@ -173,39 +181,21 @@ async function deleteOrder(id: number) {
|
||||
}
|
||||
|
||||
async function markDelivered(orderId: number) {
|
||||
try {
|
||||
await ElMessageBox.confirm('确认该订单已交付?', '交付确认', {
|
||||
confirmButtonText: '确认交付', cancelButtonText: '取消', type: 'success'
|
||||
})
|
||||
} catch { return }
|
||||
if (!await confirmDialog('交付确认', '确认该订单已交付?', 'success', '确认交付', '取消')) return
|
||||
await doUpdateStatus(orderId, 'delivered', '已交付')
|
||||
}
|
||||
|
||||
async function markPaid(orderId: number, deliveryStatus: string) {
|
||||
if (deliveryStatus !== 'delivered') {
|
||||
try {
|
||||
await ElMessageBox.confirm(
|
||||
'当前订单尚未交付,确定要提前收款吗?建议先确认交付后再收款。',
|
||||
'非标准流程提醒',
|
||||
{ confirmButtonText: '仍要收款', cancelButtonText: '取消', type: 'warning' }
|
||||
)
|
||||
} catch { return }
|
||||
if (!await confirmDialog('非标准流程提醒', '当前订单尚未交付,确定要提前收款吗?建议先确认交付后再收款。', 'warning', '仍要收款', '取消')) return
|
||||
} else {
|
||||
try {
|
||||
await ElMessageBox.confirm('确认已收到该订单款项?', '收款确认', {
|
||||
confirmButtonText: '确认收款', cancelButtonText: '取消', type: 'success'
|
||||
})
|
||||
} catch { return }
|
||||
if (!await confirmDialog('收款确认', '确认已收到该订单款项?', 'success', '确认收款', '取消')) return
|
||||
}
|
||||
await doUpdateStatus(orderId, 'paid', '已收款')
|
||||
}
|
||||
|
||||
async function cancelOrder(orderId: number) {
|
||||
try {
|
||||
await ElMessageBox.confirm('确定要作废该订单吗?此操作不可撤销。', '作废确认', {
|
||||
confirmButtonText: '确认作废', cancelButtonText: '取消', type: 'error'
|
||||
})
|
||||
} catch { return }
|
||||
if (!await confirmDialog('作废确认', '确定要作废该订单吗?此操作不可撤销。', 'error', '确认作废', '取消')) return
|
||||
await doUpdateStatus(orderId, 'cancelled', '已作废')
|
||||
}
|
||||
|
||||
@@ -316,146 +306,146 @@ onMounted(() => {
|
||||
<template>
|
||||
<div>
|
||||
<div style="margin-bottom: 12px; display: flex; gap: 12px; align-items: center;">
|
||||
<el-select
|
||||
<t-select
|
||||
v-model="productionWarehouseId"
|
||||
placeholder="选择仓库"
|
||||
style="width: 200px;"
|
||||
clearable
|
||||
>
|
||||
<el-option
|
||||
<t-option
|
||||
v-for="warehouse in state.warehouses"
|
||||
:key="warehouse.id"
|
||||
:label="warehouse.name"
|
||||
:value="warehouse.id"
|
||||
/>
|
||||
</el-select>
|
||||
<el-button @click="loadProductionOrders">刷新</el-button>
|
||||
<el-button type="primary" @click="openCreateOrder">新增销售订单</el-button>
|
||||
</t-select>
|
||||
<t-button @click="loadProductionOrders">刷新</t-button>
|
||||
<t-button type="primary" @click="openCreateOrder">新增销售订单</t-button>
|
||||
</div>
|
||||
|
||||
<el-table :data="state.productionOrders" v-loading="state.loading" stripe>
|
||||
<el-table-column prop="order_no" label="销售单" />
|
||||
<el-table-column prop="customer_name" label="客户" />
|
||||
<el-table-column label="订单金额">
|
||||
<t-table :data="state.productionOrders" :loading="state.loading" stripe>
|
||||
<t-table-column prop="order_no" label="销售单" />
|
||||
<t-table-column prop="customer_name" label="客户" />
|
||||
<t-table-column label="订单金额">
|
||||
<template #default="{ row }">{{ formatCurrency(row.total_amount) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="交付日期">
|
||||
</t-table-column>
|
||||
<t-table-column label="交付日期">
|
||||
<template #default="{ row }">{{ formatDate(row.delivery_date) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="订单创建">
|
||||
</t-table-column>
|
||||
<t-table-column label="订单创建">
|
||||
<template #default="{ row }">{{ formatDateTime(row.created_at) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="实际交付">
|
||||
</t-table-column>
|
||||
<t-table-column label="实际交付">
|
||||
<template #default="{ row }">{{ row.delivered_at ? formatDateTime(row.delivered_at) : '-' }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="实际收款">
|
||||
</t-table-column>
|
||||
<t-table-column label="实际收款">
|
||||
<template #default="{ row }">{{ row.paid_at ? formatDateTime(row.paid_at) : '-' }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="订单状态" width="160">
|
||||
</t-table-column>
|
||||
<t-table-column label="订单状态" width="160">
|
||||
<template #default="{ row }">
|
||||
<div style="display: flex; gap: 4px;">
|
||||
<el-tag
|
||||
<t-tag
|
||||
:type="row.delivery_status === 'delivered' ? 'warning' : row.delivery_status === 'cancelled' ? 'danger' : 'info'"
|
||||
size="small"
|
||||
>{{ getDeliveryStatusLabel(row.delivery_status) }}</el-tag>
|
||||
<el-tag
|
||||
>{{ getDeliveryStatusLabel(row.delivery_status) }}</t-tag>
|
||||
<t-tag
|
||||
:type="row.payment_status === 'paid' ? 'success' : 'info'"
|
||||
size="small"
|
||||
>{{ getPaymentStatusLabel(row.payment_status) }}</el-tag>
|
||||
>{{ getPaymentStatusLabel(row.payment_status) }}</t-tag>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="280">
|
||||
</t-table-column>
|
||||
<t-table-column label="操作" width="280">
|
||||
<template #default="{ row }">
|
||||
<el-button
|
||||
<t-button
|
||||
v-if="row.delivery_status === 'manufacturing'"
|
||||
type="success" size="small"
|
||||
@click="markDelivered(row.id)"
|
||||
>已交付</el-button>
|
||||
<el-button
|
||||
>已交付</t-button>
|
||||
<t-button
|
||||
v-if="row.payment_status !== 'paid' && row.delivery_status !== 'cancelled'"
|
||||
type="warning" size="small"
|
||||
@click="markPaid(row.id, row.delivery_status)"
|
||||
>已收款</el-button>
|
||||
<el-button
|
||||
>已收款</t-button>
|
||||
<t-button
|
||||
type="primary" size="small"
|
||||
:disabled="row.payment_status === 'paid' || row.delivery_status === 'cancelled'"
|
||||
@click="editOrder(row)"
|
||||
>编辑</el-button>
|
||||
<el-button type="danger" size="small" @click="deleteOrder(row.id)">删除</el-button>
|
||||
<el-button
|
||||
>编辑</t-button>
|
||||
<t-button type="danger" size="small" @click="deleteOrder(row.id)">删除</t-button>
|
||||
<t-button
|
||||
v-if="row.payment_status !== 'paid' && row.delivery_status !== 'cancelled'"
|
||||
type="info" size="small"
|
||||
@click="cancelOrder(row.id)"
|
||||
>作废</el-button>
|
||||
>作废</t-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-empty v-if="!state.loading && state.productionOrders.length === 0" description="暂无销售订单" />
|
||||
</t-table-column>
|
||||
</t-table>
|
||||
<t-empty v-if="!state.loading && state.productionOrders.length === 0" description="暂无销售订单" />
|
||||
|
||||
<el-dialog
|
||||
v-model="showModal"
|
||||
<t-dialog
|
||||
v-model:visible="showModal"
|
||||
:title="(editingItem ? '编辑' : '新增') + '销售订单'"
|
||||
width="900px"
|
||||
@closed="closeModal"
|
||||
>
|
||||
<el-form label-width="100px">
|
||||
<el-form-item label="客户" required>
|
||||
<el-select v-model="form.customer_id" placeholder="请选择客户" style="width:100%">
|
||||
<el-option
|
||||
<t-form label-width="100px">
|
||||
<t-form-item label="客户" required>
|
||||
<t-select v-model="form.customer_id" placeholder="请选择客户" style="width:100%">
|
||||
<t-option
|
||||
v-for="customer in state.customers"
|
||||
:key="customer.id"
|
||||
:label="customer.name"
|
||||
:value="customer.id"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="交付日期">
|
||||
<el-date-picker
|
||||
</t-select>
|
||||
</t-form-item>
|
||||
<t-form-item label="交付日期">
|
||||
<t-date-picker
|
||||
v-model="form.delivery_date"
|
||||
type="date"
|
||||
placeholder="选择日期"
|
||||
style="width:100%"
|
||||
value-format="YYYY-MM-DD"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="备注">
|
||||
<el-input v-model="form.remark" placeholder="备注信息" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</t-form-item>
|
||||
<t-form-item label="备注">
|
||||
<t-input v-model="form.remark" placeholder="备注信息" />
|
||||
</t-form-item>
|
||||
</t-form>
|
||||
|
||||
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 12px;">
|
||||
<span style="font-weight: 600;">模具明细</span>
|
||||
<div style="display: flex; gap: 8px;">
|
||||
<el-button v-if="editingItem" type="warning" size="small" @click="openConsumptionModal">+ 消耗物料</el-button>
|
||||
<el-button type="primary" size="small" @click="addMoldItem">+ 添加模具</el-button>
|
||||
<t-button v-if="editingItem" type="warning" size="small" @click="openConsumptionModal">+ 消耗物料</t-button>
|
||||
<t-button type="primary" size="small" @click="addMoldItem">+ 添加模具</t-button>
|
||||
</div>
|
||||
</div>
|
||||
<el-table :data="moldItems" border size="small">
|
||||
<el-table-column label="模式" width="80">
|
||||
<t-table :data="moldItems" border size="small">
|
||||
<t-table-column label="模式" width="80">
|
||||
<template #default="{ row: line }">
|
||||
<el-select v-model="line.mold_mode" size="small" style="width:100%">
|
||||
<el-option label="新模" value="new" />
|
||||
<el-option label="改模" value="existing" />
|
||||
</el-select>
|
||||
<t-select v-model="line.mold_mode" size="small" style="width:100%">
|
||||
<t-option label="新模" value="new" />
|
||||
<t-option label="改模" value="existing" />
|
||||
</t-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="模具SKU" min-width="120">
|
||||
</t-table-column>
|
||||
<t-table-column label="模具SKU" min-width="120">
|
||||
<template #default="{ row: line }">
|
||||
<el-input v-if="line.mold_mode === 'new'" v-model="line.mold_sku" size="small" placeholder="模具SKU" />
|
||||
<el-select v-else v-model="line.mold_id" placeholder="选择模具" size="small" style="width:100%">
|
||||
<el-option
|
||||
<t-input v-if="line.mold_mode === 'new'" v-model="line.mold_sku" size="small" placeholder="模具SKU" />
|
||||
<t-select v-else v-model="line.mold_id" placeholder="选择模具" size="small" style="width:100%">
|
||||
<t-option
|
||||
v-for="product in state.finishedProducts"
|
||||
:key="product.id"
|
||||
:label="`${product.sku} - ${product.name}`"
|
||||
:value="product.id"
|
||||
/>
|
||||
</el-select>
|
||||
</t-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="模具名称" min-width="120">
|
||||
</t-table-column>
|
||||
<t-table-column label="模具名称" min-width="120">
|
||||
<template #default="{ row: line }">
|
||||
<el-input
|
||||
<t-input
|
||||
v-if="line.mold_mode === 'new'"
|
||||
v-model="line.mold_name"
|
||||
size="small"
|
||||
@@ -465,118 +455,118 @@ onMounted(() => {
|
||||
{{ state.finishedProducts.find((p: any) => p.id === line.mold_id)?.name || '-' }}
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="数量" width="100">
|
||||
</t-table-column>
|
||||
<t-table-column label="数量" width="100">
|
||||
<template #default="{ row: line }">
|
||||
<el-input-number v-model="line.quantity" :min="1" size="small" style="width:100%" />
|
||||
<t-input-number v-model="line.quantity" :min="1" size="small" style="width:100%" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="单价" width="120">
|
||||
</t-table-column>
|
||||
<t-table-column label="单价" width="120">
|
||||
<template #default="{ row: line }">
|
||||
<el-input-number v-model="line.unit_price" :min="0" :precision="2" :step="0.01" size="small" style="width:100%" />
|
||||
<t-input-number v-model="line.unit_price" :min="0" :precision="2" :step="0.01" size="small" style="width:100%" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="备注" width="120">
|
||||
</t-table-column>
|
||||
<t-table-column label="备注" width="120">
|
||||
<template #default="{ row: line }">
|
||||
<el-input v-model="line.remark" size="small" placeholder="备注" />
|
||||
<t-input v-model="line.remark" size="small" placeholder="备注" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="80">
|
||||
</t-table-column>
|
||||
<t-table-column label="操作" width="80">
|
||||
<template #default="{ $index }">
|
||||
<el-button type="danger" size="small" @click="removeMoldItem($index)">删除</el-button>
|
||||
<t-button type="danger" size="small" @click="removeMoldItem($index)">删除</t-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</t-table-column>
|
||||
</t-table>
|
||||
<div style="text-align: right; margin-top: 8px; font-weight: 600;">
|
||||
订单总金额:{{ formatCurrency(orderTotalAmount) }}
|
||||
</div>
|
||||
|
||||
<template v-if="editingItem && consumedMaterials.length > 0">
|
||||
<el-divider content-position="left">已消耗物料</el-divider>
|
||||
<el-table :data="consumedMaterials" border size="small">
|
||||
<el-table-column label="物料">
|
||||
<t-divider content-position="left">已消耗物料</t-divider>
|
||||
<t-table :data="consumedMaterials" border size="small">
|
||||
<t-table-column label="物料">
|
||||
<template #default="{ row: item }">{{ item.material_name }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="数量">
|
||||
</t-table-column>
|
||||
<t-table-column label="数量">
|
||||
<template #default="{ row: item }">{{ item.quantity }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="单价">
|
||||
</t-table-column>
|
||||
<t-table-column label="单价">
|
||||
<template #default="{ row: item }">{{ formatCurrency(item.unit_price) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="备注">
|
||||
</t-table-column>
|
||||
<t-table-column label="备注">
|
||||
<template #default="{ row: item }">{{ item.remark || '-' }}</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</t-table-column>
|
||||
</t-table>
|
||||
</template>
|
||||
|
||||
<template #footer>
|
||||
<el-button @click="showModal = false">取消</el-button>
|
||||
<el-button type="primary" @click="saveSalesOrder">保存</el-button>
|
||||
<t-button @click="showModal = false">取消</t-button>
|
||||
<t-button type="primary" @click="saveSalesOrder">保存</t-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</t-dialog>
|
||||
|
||||
<el-dialog
|
||||
v-model="showConsumptionModal"
|
||||
<t-dialog
|
||||
v-model:visible="showConsumptionModal"
|
||||
title="物料消耗"
|
||||
width="800px"
|
||||
@closed="closeConsumptionModal"
|
||||
>
|
||||
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 12px;">
|
||||
<span style="font-weight: 600;">消耗物料明细</span>
|
||||
<el-button type="primary" size="small" @click="addConsumptionItem">+ 添加物料</el-button>
|
||||
<t-button type="primary" size="small" @click="addConsumptionItem">+ 添加物料</t-button>
|
||||
</div>
|
||||
<el-table :data="consumptionItems" border size="small">
|
||||
<el-table-column label="物料" min-width="200">
|
||||
<t-table :data="consumptionItems" border size="small">
|
||||
<t-table-column label="物料" min-width="200">
|
||||
<template #default="{ row: line }">
|
||||
<el-select v-model="line.material_id" placeholder="请选择物料" style="width:100%">
|
||||
<el-option
|
||||
<t-select v-model="line.material_id" placeholder="请选择物料" style="width:100%">
|
||||
<t-option
|
||||
v-for="material in state.materials"
|
||||
:key="material.id"
|
||||
:label="`${material.sku} - ${material.name}`"
|
||||
:value="material.id"
|
||||
/>
|
||||
</el-select>
|
||||
</t-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="数量" width="120">
|
||||
</t-table-column>
|
||||
<t-table-column label="数量" width="120">
|
||||
<template #default="{ row: line }">
|
||||
<el-input-number v-model="line.quantity" :min="0.0001" :step="0.0001" size="small" style="width:100%" />
|
||||
<t-input-number v-model="line.quantity" :min="0.0001" :step="0.0001" size="small" style="width:100%" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="单价" width="120">
|
||||
</t-table-column>
|
||||
<t-table-column label="单价" width="120">
|
||||
<template #default="{ row: line }">
|
||||
<el-input-number
|
||||
<t-input-number
|
||||
:model-value="state.materials.find((m: any) => m.id === line.material_id)?.cost_price || 0"
|
||||
disabled
|
||||
size="small"
|
||||
style="width:100%"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="总价" width="120">
|
||||
</t-table-column>
|
||||
<t-table-column label="总价" width="120">
|
||||
<template #default="{ row: line }">
|
||||
{{ formatCurrency((state.materials.find((m: any) => m.id === line.material_id)?.cost_price || 0) * (line.quantity || 0)) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="备注" width="150">
|
||||
</t-table-column>
|
||||
<t-table-column label="备注" width="150">
|
||||
<template #default="{ row: line }">
|
||||
<el-input v-model="line.remark" size="small" placeholder="备注" />
|
||||
<t-input v-model="line.remark" size="small" placeholder="备注" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="80">
|
||||
</t-table-column>
|
||||
<t-table-column label="操作" width="80">
|
||||
<template #default="{ $index }">
|
||||
<el-button type="danger" size="small" @click="removeConsumptionItem($index)">删除</el-button>
|
||||
<t-button type="danger" size="small" @click="removeConsumptionItem($index)">删除</t-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</t-table-column>
|
||||
</t-table>
|
||||
<div style="text-align: right; margin-top: 8px; font-weight: 600;">
|
||||
消耗总金额:{{ formatCurrency(consumptionTotalAmount) }}
|
||||
</div>
|
||||
<template #footer>
|
||||
<el-button @click="showConsumptionModal = false">取消</el-button>
|
||||
<el-button type="primary" @click="saveConsumption">保存消耗</el-button>
|
||||
<t-button @click="showConsumptionModal = false">取消</t-button>
|
||||
<t-button type="primary" @click="saveConsumption">保存消耗</t-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</t-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -81,57 +81,57 @@ onMounted(() => { loadSuppliers() })
|
||||
<template>
|
||||
<div class="suppliers-tab">
|
||||
<div class="table-header">
|
||||
<el-button type="primary" @click="openCreateSupplier">+ 新增供应商</el-button>
|
||||
<t-button type="primary" @click="openCreateSupplier">+ 新增供应商</t-button>
|
||||
</div>
|
||||
<el-table :data="state.suppliers" style="width: 100%" v-loading="state.loading" empty-text="暂无供应商数据">
|
||||
<el-table-column prop="code" label="编码" />
|
||||
<el-table-column prop="name" label="名称" />
|
||||
<el-table-column prop="contact_person" label="联系人">
|
||||
<t-table :data="state.suppliers" style="width: 100%" :loading="state.loading" empty-text="暂无供应商数据">
|
||||
<t-table-column prop="code" label="编码" />
|
||||
<t-table-column prop="name" label="名称" />
|
||||
<t-table-column prop="contact_person" label="联系人">
|
||||
<template #default="{ row }">
|
||||
{{ row.contact_person || '-' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="phone" label="电话">
|
||||
</t-table-column>
|
||||
<t-table-column prop="phone" label="电话">
|
||||
<template #default="{ row }">
|
||||
{{ row.phone || '-' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="email" label="邮箱">
|
||||
</t-table-column>
|
||||
<t-table-column prop="email" label="邮箱">
|
||||
<template #default="{ row }">
|
||||
{{ row.email || '-' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="180">
|
||||
</t-table-column>
|
||||
<t-table-column label="操作" width="180">
|
||||
<template #default="{ row }">
|
||||
<el-button size="small" @click="editSupplier(row)">编辑</el-button>
|
||||
<el-button size="small" type="danger" @click="deleteSupplier(row.id)">删除</el-button>
|
||||
<t-button size="small" @click="editSupplier(row)">编辑</t-button>
|
||||
<t-button size="small" type="danger" @click="deleteSupplier(row.id)">删除</t-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</t-table-column>
|
||||
</t-table>
|
||||
|
||||
<el-dialog v-model="showModal" :title="editingItem ? '编辑供应商' : '新增供应商'" width="520px" :close-on-click-modal="false">
|
||||
<el-form :model="form" label-width="80px">
|
||||
<el-form-item label="名称" required>
|
||||
<el-input v-model="form.name" placeholder="请输入供应商名称" />
|
||||
</el-form-item>
|
||||
<el-form-item label="联系人">
|
||||
<el-input v-model="form.contact_person" placeholder="请输入联系人" />
|
||||
</el-form-item>
|
||||
<el-form-item label="电话">
|
||||
<el-input v-model="form.phone" placeholder="请输入电话" />
|
||||
</el-form-item>
|
||||
<el-form-item label="邮箱">
|
||||
<el-input v-model="form.email" type="email" placeholder="请输入邮箱" />
|
||||
</el-form-item>
|
||||
<el-form-item label="地址">
|
||||
<el-input v-model="form.address" placeholder="请输入地址" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<t-dialog v-model="showModal" :title="editingItem ? '编辑供应商' : '新增供应商'" width="520px" :close-on-click-modal="false">
|
||||
<t-form :model="form" label-width="80px">
|
||||
<t-form-item label="名称" required>
|
||||
<t-input v-model="form.name" placeholder="请输入供应商名称" />
|
||||
</t-form-item>
|
||||
<t-form-item label="联系人">
|
||||
<t-input v-model="form.contact_person" placeholder="请输入联系人" />
|
||||
</t-form-item>
|
||||
<t-form-item label="电话">
|
||||
<t-input v-model="form.phone" placeholder="请输入电话" />
|
||||
</t-form-item>
|
||||
<t-form-item label="邮箱">
|
||||
<t-input v-model="form.email" type="email" placeholder="请输入邮箱" />
|
||||
</t-form-item>
|
||||
<t-form-item label="地址">
|
||||
<t-input v-model="form.address" placeholder="请输入地址" />
|
||||
</t-form-item>
|
||||
</t-form>
|
||||
<template #footer>
|
||||
<el-button @click="showModal = false">取消</el-button>
|
||||
<el-button type="primary" @click="save">保存</el-button>
|
||||
<t-button @click="showModal = false">取消</t-button>
|
||||
<t-button type="primary" @click="save">保存</t-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</t-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user