This commit is contained in:
磷叶 2025-03-05 18:03:14 +08:00
parent a8e2a54991
commit 367c1214b5
11 changed files with 800 additions and 320 deletions

View File

@ -42,3 +42,12 @@ export function delOrderProd(id) {
method: 'delete'
})
}
// 查询订单产品分组
export function listOrderProdGroupByName(query) {
return request({
url: '/bst/orderProd/groupByName',
method: 'get',
params: query
})
}

View File

@ -9,6 +9,15 @@ export function listProdProcess(query) {
})
}
// 分组查询工序列表
export function groupByNameProdProcess(query) {
return request({
url: '/bst/prodProcess/groupByName',
method: 'get',
params: query
})
}
// 查询产品工序列表
export function listProdProcessByIds(ids) {
return request({

View File

@ -0,0 +1,10 @@
import request from '@/utils/request'
// 获取工序汇总数据
export function getProdProcessSum(query) {
return request({
url: '/dashboard/prodProcess/sum',
method: 'get',
params: query
})
}

View File

@ -16,20 +16,38 @@
<!-- 订单信息区域 -->
<div @click="handleOrderClick(order)">
<el-descriptions :column="2" size="small">
<el-descriptions-item label="订单" :span="2">{{ order.orderNo | dv}}</el-descriptions-item>
<el-descriptions-item label="订单日期" :span="2">{{ order.orderDate | dv}}</el-descriptions-item>
<el-descriptions-item label="客户" :span="2">{{ order.customer | dv}}</el-descriptions-item>
<el-descriptions-item label="订单数量" :span="2">{{ order.num | dv}} {{order.unit}}</el-descriptions-item>
<el-descriptions :column="1" size="small">
<el-descriptions-item label="订单">{{ order.orderNo | dv}}</el-descriptions-item>
<el-descriptions-item label="订单日期">{{ order.orderDate | dv}}</el-descriptions-item>
<el-descriptions-item label="客户">{{ order.customer | dv}}</el-descriptions-item>
<el-descriptions-item label="交货日期">{{ order.deliveryDate | dv}}</el-descriptions-item>
</el-descriptions>
</div>
</div>
<div class="progress-container">
<el-progress :percentage="order.progress" :color="ProgressColors" :format="ProgressFormat" style="width: 100%;" :stroke-width="10"/>
<el-descriptions :column="3" size="small">
<el-descriptions-item label="总数量">{{ order.totalNum | dv}}</el-descriptions-item>
<el-descriptions-item label="汇报生产数">{{ order.reportNum | dv}}</el-descriptions-item>
<el-descriptions-item label="仓库清点数">{{ order.storeNum | dv}}</el-descriptions-item>
<div class="progress-title">成品生产进度
<el-tooltip content="成品生产进度 = 成品清点数 / 订单数量" placement="top">
<el-icon :size="12" class="el-icon-question"/>
</el-tooltip>
</div>
<el-progress :percentage="order.endProgress" :color="ProgressColors" :format="ProgressFormat" style="width: 100%;" :stroke-width="6"/>
<el-descriptions :column="3" size="mini">
<el-descriptions-item label="订单数量">{{ order.num | dv}} {{order.unit}}</el-descriptions-item>
<el-descriptions-item label="成品上报数">{{ order.endReportNum | dv}} {{order.unit}}</el-descriptions-item>
<el-descriptions-item label="成品清点数">{{ order.endStoreNum | dv}} {{order.unit}}</el-descriptions-item>
</el-descriptions>
</div>
<div class="progress-container">
<div class="progress-title">总生产进度
<el-tooltip content="总生产进度 = 除成品外的清点数 / 除成品外的数量" placement="top">
<el-icon :size="12" class="el-icon-question"/>
</el-tooltip>
</div>
<el-progress :percentage="order.progress" :color="ProgressColors" :format="ProgressFormat" width="100%" :stroke-width="6"/>
<el-descriptions :column="3" size="mini">
<el-descriptions-item label="总产品数" :span="1">{{ order.totalNum - order.num | dv}}</el-descriptions-item>
<el-descriptions-item label="上报产品数" :span="1">{{ order.reportNum | dv}}</el-descriptions-item>
<el-descriptions-item label="清点产品数" :span="1">{{ order.storeNum | dv}}</el-descriptions-item>
</el-descriptions>
</div>
@ -38,13 +56,14 @@
<div class="sub-product" v-for="(prod, index) in order.prodList" :key="index">
<image-preview class="prod-image" :src="prod.picture" :width="28" :height="28" />
<span class="prod-name">{{ prod.name | dv }}</span>
<el-tag v-if="prod.isEnd" type="success" size="mini">成品</el-tag>
<dict-tag class="prod-type" :value="prod.workType" :options="dict.type.order_prod_work_type" size="mini"/>
<div class="prod-progress">
<el-progress
:percentage="prod.progress || 0"
:color="ProgressColors"
:format="ProgressFormat"
:stroke-width="6"
:stroke-width="4"
/>
</div>
</div>
@ -223,7 +242,13 @@ export default {
}
.progress-container {
margin-bottom: 8px;
border-top: 1px solid #f0f2f5;
padding-top: 4px;
padding-bottom: 4px;
.progress-title {
font-size: 12px;
color: #606266;
}
}
.order-main-image {

View File

@ -121,7 +121,7 @@
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList" :columns="columns"></right-toolbar>
</el-row>
<el-table v-loading="loading" :data="orderList" @selection-change="handleSelectionChange" :default-sort="defaultSort" @sort-change="onSortChange">
<el-table size="mini" v-loading="loading" :data="orderList" @selection-change="handleSelectionChange" :default-sort="defaultSort" @sort-change="onSortChange">
<el-table-column type="selection" width="55" align="center" />
<template v-for="column of showColumns">
<el-table-column
@ -146,7 +146,12 @@
<image-preview :src="d.row.picture" :width="50" :height="50"/>
</template>
<template v-else-if="column.key === 'progress'">
<el-progress :percentage="d.row.progress" :color="ProgressColors" :format="ProgressFormat"/>
<div class="progress-container">
成品进度:<el-progress :percentage="d.row.endProgress" :color="ProgressColors" style="width: 160px" :format="ProgressFormat"/>
</div>
<div class="progress-container">
生产进度:<el-progress :percentage="d.row.progress" :color="ProgressColors" style="width: 160px" :format="ProgressFormat"/>
</div>
</template>
<template v-else-if="['num', 'reportNum', 'storeNum'].includes(column.key)">
{{d.row[column.key] | dv}}{{d.row.unit}}
@ -238,15 +243,12 @@ export default {
{key: 'customer', visible: true, label: '客户', minWidth: null, sortable: false, overflow: false, align: 'center', width: null},
{key: 'orderDate', visible: true, label: '订单日期', minWidth: null, sortable: true, overflow: false, align: 'center', width: "100"},
{key: 'deliveryDate', visible: true, label: '交货日期', minWidth: null, sortable: true, overflow: false, align: 'center', width: "100"},
// {key: 'name', visible: true, label: '', minWidth: null, sortable: false, overflow: true, align: 'center', width: null},
{key: 'material', visible: true, label: '用料', minWidth: null, sortable: false, overflow: true, align: 'center', width: null},
// {key: 'contentNum', visible: true, label: '', minWidth: null, sortable: true, overflow: true, align: 'center', width: null},
// {key: 'packageSize', visible: true, label: '', minWidth: null, sortable: false, overflow: true, align: 'center', width: null},
{key: 'remark', visible: true, label: '要求', minWidth: null, sortable: false, overflow: true, align: 'center', width: null},
{key: 'num', visible: true, label: '数量', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
{key: 'reportNum', visible: true, label: '已上报', minWidth: null, sortable: false, overflow: false, align: 'center', width: null},
{key: 'storeNum', visible: true, label: '已清点', minWidth: null, sortable: false, overflow: false, align: 'center', width: null},
{key: 'progress', visible: true, label: '进度', minWidth: null, sortable: false, overflow: false, align: 'center', width: "160"},
{key: 'progress', visible: true, label: '进度', minWidth: null, sortable: false, overflow: false, align: 'center', width: "250"},
{key: 'createBy', visible: true, label: '创建人', minWidth: null, sortable: false, overflow: false, align: 'center', width: null},
{key: 'createTime', visible: true, label: '创建时间', minWidth: null, sortable: true, overflow: false, align: 'center', width: "100"},
],
@ -375,3 +377,12 @@ export default {
}
};
</script>
<style lang="scss" scoped>
.progress-container {
display: flex;
flex-direction: row;
align-items: center;
}
</style>

View File

@ -1,11 +1,11 @@
<template>
<div class="app-container" v-loading="loading">
<el-row :gutter="16">
<el-col :span="18">
<el-col :span="24">
<el-card class="card-box" header="基础信息">
<div class="detail-box">
<image-preview :src="detail.picture" :width="100" :height="100" style="margin-right: 16px"/>
<el-descriptions style="flex: 1" :column="3">
<el-descriptions style="flex: 1" :column="4">
<el-descriptions-item label="订单编号">{{ detail.orderNo | dv}}</el-descriptions-item>
<el-descriptions-item label="客户单号">{{ detail.customOrderNo | dv}}</el-descriptions-item>
<el-descriptions-item label="订单状态">
@ -14,10 +14,7 @@
<el-descriptions-item label="客户">{{ detail.customer | dv}}</el-descriptions-item>
<el-descriptions-item label="订单日期">{{ detail.orderDate | dv}}</el-descriptions-item>
<el-descriptions-item label="交货日期">{{ detail.deliveryDate | dv}}</el-descriptions-item>
<!-- <el-descriptions-item label="产品名称">{{ detail.name | dv}}</el-descriptions-item> -->
<el-descriptions-item label="用料">{{ detail.material | dv}}</el-descriptions-item>
<!-- <el-descriptions-item label="装量">{{ detail.contentNum | dv}}</el-descriptions-item> -->
<!-- <el-descriptions-item label="包装尺寸">{{ detail.packageSize | dv}}</el-descriptions-item> -->
<el-descriptions-item label="特殊要求" :span="2">{{ detail.remark | dv}}</el-descriptions-item>
<el-descriptions-item label="创建人">{{ detail.createBy | dv}}</el-descriptions-item>
<el-descriptions-item label="创建时间">{{ detail.createTime | dv}}</el-descriptions-item>
@ -25,54 +22,95 @@
</div>
</el-card>
</el-col>
<el-col :span="6">
<el-card class="card-box progress-card" header="生产进度">
<div class="progress-content">
<div class="progress-circle">
<el-progress
type="circle"
:percentage="detail.progress || 0"
:color="ProgressColors"
:format="ProgressFormat"
:stroke-width="10"
:width="120"
/>
</div>
</el-row>
<div class="progress-stats">
<div class="stat-item">
<el-row :gutter="16">
<el-col :span="12">
<el-card class="card-box" header="成品进度">
<div class="progress-card">
<el-progress
type="circle"
:percentage="detail.endProgress || 0"
:color="ProgressColors"
:format="ProgressFormat"
:stroke-width="10"
:width="120"
/>
<el-row style="flex: 1;margin-left: 12px;" :gutter="16">
<el-col :span="12" class="stat-item">
<div class="stat-label">订单数量</div>
<div class="stat-value">{{ detail.num | dv }} {{detail.unit}}</div>
</div>
<div class="stat-item">
</el-col>
<el-col :span="12" class="stat-item">
<div class="stat-label">成品上报数</div>
<div class="stat-value">{{ detail.endReportNum | dv }} {{detail.unit}}</div>
</el-col>
<el-col :span="12" class="stat-item">
<div class="stat-label">成品清点数</div>
<div class="stat-value">{{ detail.endStoreNum | dv }} {{detail.unit}}</div>
</el-col>
<el-col :span="12" class="stat-item">
<div class="stat-label">成品未完成数</div>
<div class="stat-value uncompleted">{{ detail.num - detail.endReportNum | dv }} {{detail.unit}}</div>
</el-col>
</el-row>
</div>
</el-card>
</el-col>
<el-col :span="12">
<el-card class="card-box" header="生产进度">
<div class="progress-card">
<el-progress
type="circle"
:percentage="detail.progress || 0"
:color="ProgressColors"
:format="ProgressFormat"
:stroke-width="10"
:width="120"
/>
<el-row style="flex: 1;margin-left: 12px;" :gutter="16">
<el-col :span="12" class="stat-item">
<div class="stat-label">总数量</div>
<div class="stat-value">{{ detail.totalNum | dv }} {{detail.unit}}</div>
</div>
<div class="stat-item">
<div class="stat-value">{{ detail.totalNum - detail.num | dv }}</div>
</el-col>
<el-col :span="12" class="stat-item">
<div class="stat-label">汇报生产数</div>
<div class="stat-value">{{ detail.reportNum | dv }} {{detail.unit}}</div>
</div>
<div class="stat-item">
<div class="stat-value">{{ detail.reportNum | dv }}</div>
</el-col>
<el-col :span="12" class="stat-item">
<div class="stat-label">仓库清点数</div>
<div class="stat-value">{{ detail.storeNum | dv }} {{detail.unit}}</div>
</div>
</div>
<div class="stat-value">{{ detail.storeNum | dv }}</div>
</el-col>
<el-col :span="12" class="stat-item">
<div class="stat-label">未完成数</div>
<div class="stat-value uncompleted">{{ detail.totalNum - detail.reportNum | dv }}</div>
</el-col>
</el-row>
</div>
</el-card>
</el-col>
</el-row>
<el-card class="card-box">
<el-card class="card-box" v-if="detail.id != null">
<el-tabs>
<el-tab-pane label="产品列表">
<el-tab-pane lazy label="产品列表">
<order-prod
v-if="detail.id != null"
:query="{orderId: detail.id}"
hidden-search
:container-class="null"
:hide-columns="['id', 'orderNo']"
/>
</el-tab-pane>
<el-tab-pane lazy label="工序进度">
<prod-process
:query="{orderId: detail.id, orderStatusList: []}"
hidden-search
:container-class="null"
:hide-columns="['id', 'orderNo', 'orderPicture', 'orderStatus', 'handleWay']"
/>
</el-tab-pane>
</el-tabs>
</el-card>
</div>
@ -82,10 +120,11 @@
import { getOrder } from '@/api/bst/order'
import { ProgressColors, ProgressFormat } from '@/utils/constants'
import OrderProd from '@/views/bst/orderProd/index.vue'
import ProdProcess from '@/views/bst/prodProcess/index.vue'
export default {
name: "OrderView",
components: { OrderProd },
components: { OrderProd, ProdProcess },
dicts: ['order_status'],
data() {
return {
@ -119,54 +158,29 @@ export default {
}
.progress-card {
.progress-header {
display: flex;
align-items: center;
.stat-item {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 16px;
.title {
font-size: 16px;
font-weight: 500;
color: #303133;
padding: 8px 0;
overflow: hidden;
border-bottom: 1px solid #EBEEF5;
.stat-label {
font-size: 14px;
color: #606266;
}
}
.progress-content {
display: flex;
align-items: center;
padding: 0 16px;
}
.progress-circle {
flex-shrink: 0;
}
.progress-stats {
flex: 1;
margin-left: 24px;
.stat-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 8px 0;
border-bottom: 1px solid #EBEEF5;
&:last-child {
border-bottom: none;
}
.stat-label {
font-size: 14px;
color: #606266;
}
.stat-value {
font-size: 16px;
font-weight: 600;
color: #6699ff;
}
.stat-value {
font-size: 16px;
font-weight: 600;
color: #6699ff;
}
.uncompleted {
color: #f56c6c;
}
}
}

View File

@ -0,0 +1,126 @@
<template>
<el-table
size="mini"
:data="data"
@selection-change="handleSelectionChange"
:default-sort="defaultSort"
@sort-change="onSortChange">
<el-table-column type="selection" width="50" align="center" />
<template v-for="column of showColumns">
<el-table-column
:key="column.key"
:label="column.label"
:prop="column.key"
:align="column.align"
:min-width="column.minWidth"
:sort-orders="orderSorts"
:sortable="column.sortable"
:show-overflow-tooltip="column.overflow"
:width="column.width"
>
<template slot-scope="d">
<template v-if="column.key === 'id'">
{{d.row[column.key]}}
</template>
<template v-else-if="column.key === 'workType'">
<template v-if="d.row.workType === ProdWorkType.BUY">{{d.row.workName}}</template>
<dict-tag :options="dict.type.order_prod_work_type" :value="d.row[column.key]" size="mini"/>
</template>
<template v-else-if="column.key === 'orderNo'">
<order-link :id="d.row.orderId" :name="d.row.orderNo"/>
</template>
<template v-else-if="column.key === 'picture'">
<image-preview :src="d.row.picture" :width="50" :height="50"/>
</template>
<template v-else-if="column.key === 'isEnd'">
<boolean-tag :value="d.row.isEnd" size="mini"/>
</template>
<template v-else-if="column.key === 'progress'">
<el-popover :width="500" trigger="hover" placement="left">
<process-card-list :data="d.row.processList" />
<template #reference>
<el-progress :percentage="d.row.progress" :color="ProgressColors" :format="ProgressFormat" style="cursor: pointer;" />
</template>
</el-popover>
</template>
<template v-else>
{{d.row[column.key]}}
</template>
</template>
</el-table-column>
</template>
</el-table>
</template>
<script>
import { $showColumns } from '@/utils/mixins'
import BooleanTag from '@/components/BooleanTag/index.vue'
import OrderLink from '@/components/Business/Order/OrderLink.vue'
import ProcessCardList from '@/views/bst/prodProcess/components/ProcessCardList.vue'
import { ProdWorkType } from '@/utils/enums'
import { ProgressColors, ProgressFormat } from '@/utils/constants'
//
const defaultSort = {
prop: "createTime",
order: "descending"
}
export default {
name: "ProdTable",
mixins: [$showColumns],
dicts: ['order_prod_work_type'],
components: { OrderLink, BooleanTag, ProcessCardList },
props: {
data: {
type: Array,
default: () => []
},
defaultSort: {
type: Object,
default: () => defaultSort
},
},
data() {
return {
ProdWorkType,
ProgressColors,
//
orderSorts: ['ascending', 'descending', null],
//
columns: [
{key: 'id', visible: false, label: 'ID', minWidth: null, sortable: true, overflow: false, align: 'center', width: "80"},
{key: 'orderNo', visible: true, label: '订单', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
{key: 'no', visible: true, label: '序号', minWidth: null, sortable: false, overflow: false, align: 'center', width: "80"},
{key: 'picture', visible: true, label: '图片', minWidth: null, sortable: false, overflow: false, align: 'center', width: "80"},
{key: 'name', visible: true, label: '产品名称', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
{key: 'workType', visible: true, label: '加工商', minWidth: null, sortable: true, overflow: false, align: 'center', width: "100"},
{key: 'materialNo', visible: true, label: '物料编号', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
{key: 'remark', visible: true, label: '备注', minWidth: null, sortable: true, overflow: true, align: 'center', width: null},
{key: 'isEnd', visible: true, label: '成品', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
{key: 'handleWay', visible: true, label: '处理方式', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
{key: 'effect', visible: true, label: '效果/包装', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
{key: 'color', visible: true, label: '颜色', minWidth: null, sortable: true, overflow: false, align: 'center', width: "80"},
{key: 'coverColor', visible: true, label: '球盖/外箱', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
{key: 'contentNum', visible: true, label: '装量', minWidth: null, sortable: true, overflow: false, align: 'center', width: "80"},
{key: 'num', visible: true, label: '数量', minWidth: null, sortable: true, overflow: false, align: 'center', width: "80"},
{key: 'reportNum', visible: true, label: '已上报', minWidth: null, sortable: false, overflow: false, align: 'center', width: "80"},
{key: 'storeNum', visible: true, label: '已清点', minWidth: null, sortable: false, overflow: false, align: 'center', width: "80"},
{key: 'progress', visible: true, label: '进度', minWidth: null, sortable: false, overflow: false, align: 'center', width: "160"},
],
}
},
created() {
this.initColumns();
},
methods: {
ProgressFormat,
handleSelectionChange(selection) {
this.$emit('selection-change', selection);
},
onSortChange(column) {
this.$emit('sort-change', column);
}
}
}
</script>

View File

@ -0,0 +1,244 @@
<template>
<div :class="containerClass">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
<el-form-item label="订单编号" prop="orderNo" v-if="isShow('orderNo')">
<el-input
v-model="queryParams.orderNo"
placeholder="请输入订单编号"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="加工商" prop="workType" v-if="isShow('workType')">
<el-select v-model="queryParams.workType" placeholder="请选择加工商" clearable @change="handleQuery">
<el-option
v-for="dict in dict.type.order_prod_work_type"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="是否成品" prop="isEnd" v-if="isShow('isEnd')">
<el-radio-group v-model="queryParams.isEnd" @change="handleQuery">
<el-radio :label="null">全部</el-radio>
<el-radio :label="true"></el-radio>
<el-radio :label="false"></el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="物料编码" prop="materialNo" v-if="isShow('materialNo')">
<el-input
v-model="queryParams.materialNo"
placeholder="请输入物料编码"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="名称" prop="name" v-if="isShow('name')">
<el-input
v-model="queryParams.name"
placeholder="请输入名称"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="规格" prop="spec" v-if="isShow('spec')">
<el-input
v-model="queryParams.spec"
placeholder="请输入规格"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="处理方式" prop="handleWay">
<el-input
v-model="queryParams.handleWay"
placeholder="请输入处理方式"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="效果" prop="effect">
<el-input
v-model="queryParams.effect"
placeholder="请输入效果"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="颜色" prop="color">
<el-input
v-model="queryParams.color"
placeholder="请输入颜色"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="盖子颜色" prop="coverColor">
<el-input
v-model="queryParams.coverColor"
placeholder="请输入盖子颜色"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<el-row :gutter="10" class="mb8">
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<!-- 分组表格 -->
<el-table
v-loading="loading"
size="mini"
:data="groupList"
@selection-change="handleSelectionChange">
<el-table-column type="selection" width="50" align="center" />
<el-table-column type="expand">
<template slot-scope="scope">
<prod-table :data="scope.row.prodList" />
</template>
</el-table-column>
<el-table-column label="产品名称" prop="name" align="left" />
<el-table-column label="总数量" prop="totalNum" align="center" width="100" />
<el-table-column label="已上报" prop="reportNum" align="center" width="100" />
<el-table-column label="已清点" prop="storeNum" align="center" width="100" />
<el-table-column label="进度" align="center" width="160">
<template slot-scope="scope">
<el-progress
:percentage="calculateProgress(scope.row)"
:color="ProgressColors"
:format="ProgressFormat"
/>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total>0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getList"
/>
</div>
</template>
<script>
import { listOrderProdGroupByName } from '@/api/bst/orderProd'
import { $showColumns } from '@/utils/mixins'
import { ProgressColors, ProgressFormat } from '@/utils/constants'
import ProdTable from './components/ProdTable.vue'
export default {
name: "OrderProdGroup",
mixins: [$showColumns],
dicts: ['order_prod_work_type'],
components: { ProdTable },
props: {
query: {
type: Object,
default: () => ({})
},
//
hiddenSearch: {
type: Boolean,
default: false,
},
containerClass: {
type: String,
default: "app-container"
}
},
data() {
return {
ProgressColors,
//
loading: true,
//
ids: [],
//
single: true,
//
multiple: true,
//
showSearch: true,
//
total: 0,
//
groupList: [],
//
queryParams: {
pageNum: 1,
pageSize: 20,
orderId: null,
workType: null,
isEnd: null,
materialNo: null,
name: null,
spec: null,
remark: null,
handleWay: null,
effect: null,
color: null,
coverColor: null,
orderNo: null
}
};
},
created() {
this.queryParams = {
...this.queryParams,
...this.query,
}
this.showSearch = !this.hiddenSearch;
this.initColumns();
this.getList();
},
methods: {
ProgressFormat,
calculateProgress(row) {
if (!row.totalNum || row.totalNum === 0) {
return 0;
}
return (row.storeNum / row.totalNum) * 100;
},
/** 查询订单产品分组列表 */
getList() {
this.loading = true;
listOrderProdGroupByName(this.queryParams).then(response => {
this.groupList = response.rows;
this.total = response.total;
this.loading = false;
});
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNum = 1;
this.getList();
},
/** 重置按钮操作 */
resetQuery() {
this.resetForm("queryForm");
this.handleQuery();
},
//
handleSelectionChange(selection) {
this.ids = selection.map(item => item.id)
this.single = selection.length!==1
this.multiple = !selection.length
}
}
};
</script>
<style lang="scss" scoped>
</style>

View File

@ -90,92 +90,26 @@
</el-form>
<el-row :gutter="10" class="mb8">
<!-- <el-col :span="1.5">-->
<!-- <el-button-->
<!-- type="primary"-->
<!-- plain-->
<!-- icon="el-icon-plus"-->
<!-- size="mini"-->
<!-- @click="handleAdd"-->
<!-- v-has-permi="['bst:orderProd:add']"-->
<!-- >新增</el-button>-->
<!-- </el-col>-->
<!-- <el-col :span="1.5">-->
<!-- <el-button-->
<!-- type="danger"-->
<!-- plain-->
<!-- icon="el-icon-delete"-->
<!-- size="mini"-->
<!-- :disabled="multiple"-->
<!-- @click="handleDelete"-->
<!-- v-has-permi="['bst:orderProd:remove']"-->
<!-- >删除</el-button>-->
<!-- </el-col>-->
<!-- <el-col :span="1.5">-->
<!-- <el-button-->
<!-- type="warning"-->
<!-- plain-->
<!-- icon="el-icon-download"-->
<!-- size="mini"-->
<!-- @click="handleExport"-->
<!-- v-has-permi="['bst:orderProd:export']"-->
<!-- >导出</el-button>-->
<!-- </el-col>-->
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList" :columns="columns"></right-toolbar>
<el-col :span="1.5">
<el-button
type="warning"
plain
icon="el-icon-download"
size="mini"
@click="handleExport"
v-has-permi="['bst:orderProd:export']"
>导出</el-button>
</el-col>
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList" ></right-toolbar>
</el-row>
<el-table
<prod-table
v-loading="loading"
size="mini"
:data="orderProdList"
@selection-change="handleSelectionChange"
:default-sort="defaultSort"
@sort-change="onSortChange">
<el-table-column type="selection" width="50" align="center" />
<template v-for="column of showColumns">
<el-table-column
:key="column.key"
:label="column.label"
:prop="column.key"
:align="column.align"
:min-width="column.minWidth"
:sort-orders="orderSorts"
:sortable="column.sortable"
:show-overflow-tooltip="column.overflow"
:width="column.width"
>
<template slot-scope="d">
<template v-if="column.key === 'id'">
{{d.row[column.key]}}
</template>
<template v-else-if="column.key === 'workType'">
<template v-if="d.row.workType === ProdWorkType.BUY">{{d.row.workName}}</template>
<dict-tag :options="dict.type.order_prod_work_type" :value="d.row[column.key]" size="mini"/>
</template>
<template v-else-if="column.key === 'orderNo'">
<order-link :id="d.row.orderId" :name="d.row.orderNo"/>
</template>
<template v-else-if="column.key === 'picture'">
<image-preview :src="d.row.picture" :width="50" :height="50"/>
</template>
<template v-else-if="column.key === 'isEnd'">
<boolean-tag :value="d.row.isEnd"/>
</template>
<template v-else-if="column.key === 'progress'">
<el-popover :width="500" trigger="hover" placement="left">
<process-card-list :data="d.row.processList" />
<template #reference>
<el-progress :percentage="d.row.progress" :color="ProgressColors" :format="ProgressFormat" style="cursor: pointer;" />
</template>
</el-popover>
</template>
<template v-else>
{{d.row[column.key]}}
</template>
</template>
</el-table-column>
</template>
</el-table>
@selection-change="handleSelectionChange"
:default-sort="defaultSort"
@sort-change="onSortChange"
/>
<pagination
v-show="total>0"
@ -184,8 +118,6 @@
:limit.sync="queryParams.pageSize"
@pagination="getList"
/>
</div>
</template>
@ -193,12 +125,9 @@
import { addOrderProd, getOrderProd, listOrderProd, updateOrderProd } from '@/api/bst/orderProd'
import FormCol from '@/components/FormCol/index.vue'
import { $showColumns } from '@/utils/mixins'
import BooleanTag from '@/components/BooleanTag/index.vue'
import { ProgressColors, ProgressFormat } from '@/utils/constants'
import ProdProcess from '@/views/bst/prodProcess/index.vue'
import OrderLink from '@/components/Business/Order/OrderLink.vue'
import ProcessCardList from '@/views/bst/prodProcess/components/ProcessCardList.vue'
import { ProdWorkType } from '@/utils/enums'
import ProdTable from './components/ProdTable.vue'
//
const defaultSort = {
@ -210,7 +139,7 @@ export default {
name: "OrderProd",
mixins: [$showColumns],
dicts: ['order_prod_work_type'],
components: { OrderLink, ProdProcess, BooleanTag, FormCol, ProcessCardList},
components: { FormCol, ProdTable },
props: {
query: {
type: Object,
@ -231,28 +160,6 @@ export default {
ProdWorkType,
ProgressColors,
span: 24,
//
columns: [
{key: 'id', visible: false, label: 'ID', minWidth: null, sortable: true, overflow: false, align: 'center', width: "80"},
{key: 'orderNo', visible: true, label: '订单', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
{key: 'no', visible: true, label: '序号', minWidth: null, sortable: false, overflow: false, align: 'center', width: "80"},
{key: 'picture', visible: true, label: '图片', minWidth: null, sortable: false, overflow: false, align: 'center', width: "80"},
{key: 'name', visible: true, label: '产品名称', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
{key: 'workType', visible: true, label: '加工商', minWidth: null, sortable: true, overflow: false, align: 'center', width: "100"},
{key: 'materialNo', visible: true, label: '物料编号', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
// {key: 'spec', visible: true, label: '', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
{key: 'remark', visible: true, label: '备注', minWidth: null, sortable: true, overflow: true, align: 'center', width: null},
// {key: 'isEnd', visible: true, label: '', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
{key: 'handleWay', visible: true, label: '处理方式', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
{key: 'effect', visible: true, label: '效果/包装尺寸', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
{key: 'color', visible: true, label: '颜色', minWidth: null, sortable: true, overflow: false, align: 'center', width: "80"},
{key: 'coverColor', visible: true, label: '球盖/外箱尺寸', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
{key: 'contentNum', visible: true, label: '装量', minWidth: null, sortable: true, overflow: false, align: 'center', width: "80"},
{key: 'num', visible: true, label: '数量', minWidth: null, sortable: true, overflow: false, align: 'center', width: "80"},
{key: 'reportNum', visible: true, label: '已上报', minWidth: null, sortable: false, overflow: false, align: 'center', width: "80"},
{key: 'storeNum', visible: true, label: '已清点', minWidth: null, sortable: false, overflow: false, align: 'center', width: "80"},
{key: 'progress', visible: true, label: '进度', minWidth: null, sortable: false, overflow: false, align: 'center', width: "160"},
],
//
orderSorts: ['ascending', 'descending', null],
//
@ -422,21 +329,11 @@ export default {
}
});
},
/** 删除按钮操作 */
handleDelete(row) {
const ids = row.id || this.ids;
this.$modal.confirm('是否确认删除订单产品编号为"' + ids + '"的数据项?').then(function() {
return delOrderProd(ids);
}).then(() => {
this.getList();
this.$modal.msgSuccess("删除成功");
}).catch(() => {});
},
/** 导出按钮操作 */
handleExport() {
this.download('bst/orderProd/export', {
...this.queryParams
}, `orderProd_${new Date().getTime()}.xlsx`)
}, `订单产品导出_${new Date().getTime()}.xlsx`)
}
}
};

View File

@ -0,0 +1,140 @@
<template>
<el-table
size="mini"
v-loading="loading"
:data="processList"
@selection-change="handleSelectionChange"
:default-sort="defaultSort"
@sort-change="onSortChange"
>
<el-table-column type="selection" width="55" align="center" />
<template v-for="column of showColumns">
<el-table-column
:key="column.key"
:label="column.label"
:prop="column.key"
:align="column.align"
:min-width="column.minWidth"
:sort-orders="orderSorts"
:sortable="column.sortable"
:show-overflow-tooltip="column.overflow"
:width="column.width"
>
<template slot-scope="d">
<template v-if="column.key === 'id'">
{{d.row[column.key]}}
</template>
<template v-else-if="column.key === 'isEnd'">
<boolean-tag :value="d.row.isEnd" size="mini"/>
</template>
<template v-else-if="column.key === 'orderNo'">
<order-link :id="d.row.orderId" :name="d.row.orderNo"/>
</template>
<template v-else-if="column.key === 'orderStatus'">
<dict-tag :value="d.row.orderStatus" :options="dict.type.order_status" size="mini"/>
</template>
<template v-else-if="column.key === 'progress'">
<el-progress :percentage="d.row.progress" :color="ProgressColors" :format="ProgressFormat"/>
</template>
<template v-else-if="['orderPicture', 'orderProdPicture'].includes(column.key)">
<image-preview :src="d.row[column.key]" :width="50" :height="50"/>
</template>
<template v-else>
{{d.row[column.key]}}
</template>
</template>
</el-table-column>
</template>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" v-if="!isCustomData">
<template slot-scope="scope">
<el-button
size="mini"
type="text"
icon="el-icon-view"
@click="handleView(scope.row)"
v-has-permi="['bst:prodProcess:query']"
>详情</el-button>
</template>
</el-table-column>
</el-table>
</template>
<script>
import { $showColumns } from '@/utils/mixins'
import BooleanTag from '@/components/BooleanTag/index.vue'
import OrderLink from '@/components/Business/Order/OrderLink.vue'
import { OrderStatus } from '@/utils/enums'
import { ProgressColors, ProgressFormat } from '@/utils/constants'
//
const defaultSort = {
prop: "createTime",
order: "descending"
}
export default {
name: "ProcessTable",
dicts: ['order_status'],
mixins: [$showColumns],
components: { OrderLink, BooleanTag },
props: {
processList: {
type: Array,
default: () => []
},
loading: {
type: Boolean,
default: false
},
isCustomData: {
type: Boolean,
default: false
},
sum: {
type: Object,
default: () => ({})
}
},
data() {
return {
OrderStatus,
ProgressColors,
ProgressFormat,
//
orderSorts: ['ascending', 'descending', null],
defaultSort,
//
columns: [
{key: 'id', visible: false, label: 'ID', minWidth: null, sortable: true, overflow: false, align: 'center', width: "80"},
{key: 'orderNo', visible: true, label: '订单', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
{key: 'orderPicture', visible: true, label: '订单主图', minWidth: null, sortable: false, overflow: false, align: 'center', width: null},
{key: 'orderStatus', visible: true, label: '状态', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
{key: 'orderProdName', visible: true, label: '产品', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
{key: 'orderProdPicture', visible: true, label: '产品主图', minWidth: null, sortable: false, overflow: false, align: 'center', width: null},
{key: 'deptName', visible: true, label: '工序', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
{key: 'handleWay', visible: true, label: '处理方式', minWidth: null, sortable: false, overflow: false, align: 'center', width: null},
{key: 'effect', visible: true, label: '效果', minWidth: null, sortable: false, overflow: false, align: 'center', width: null},
{key: 'color', visible: true, label: '颜色', minWidth: null, sortable: false, overflow: false, align: 'center', width: null},
{key: 'coverColor', visible: true, label: '盖子颜色', minWidth: null, sortable: false, overflow: false, align: 'center', width: null},
{key: 'remark', visible: true, label: '备注', minWidth: null, sortable: false, overflow: false, align: 'center', width: null},
{key: 'isEnd', visible: true, label: '最终', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
{key: 'num', visible: true, label: '数量', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
{key: 'reportNum', visible: true, label: '已上报', minWidth: null, sortable: false, overflow: false, align: 'center', width: null},
{key: 'storeNum', visible: true, label: '已清点', minWidth: null, sortable: false, overflow: false, align: 'center', width: null},
{key: 'progress', visible: true, label: '进度', minWidth: null, sortable: false, overflow: false, align: 'center', width: "160"},
],
}
},
methods: {
handleView(row) {
this.$emit('view', row);
},
handleSelectionChange(selection) {
this.$emit('selection-change', selection);
},
onSortChange(column) {
this.$emit('sort-change', column);
}
}
}
</script>

View File

@ -1,6 +1,6 @@
<template>
<div :class="containerClass">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch && !isCustomData" label-width="68px">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
<el-form-item label="订单编号" prop="orderNo">
<el-input
v-model="queryParams.orderNo"
@ -107,78 +107,56 @@
<!-- </el-col>-->
<right-toolbar
:showSearch.sync="showSearch"
:search="!isCustomData"
:show-refresh="!isCustomData"
@queryTable="getList"
:columns="columns"/>
@queryTable="getList"/>
</el-row>
<el-table v-loading="loading" :data="prodProcessList" @selection-change="handleSelectionChange" :default-sort="defaultSort" @sort-change="onSortChange">
<el-table-column type="selection" width="55" align="center" />
<template v-for="column of showColumns">
<el-table-column
:key="column.key"
:label="column.label"
:prop="column.key"
:align="column.align"
:min-width="column.minWidth"
:sort-orders="orderSorts"
:sortable="column.sortable"
:show-overflow-tooltip="column.overflow"
:width="column.width"
>
<template slot-scope="d">
<template v-if="column.key === 'id'">
{{d.row[column.key]}}
</template>
<template v-else-if="column.key === 'isEnd'">
<boolean-tag :value="d.row.isEnd"/>
</template>
<template v-else-if="column.key === 'orderNo'">
<order-link :id="d.row.orderId" :name="d.row.orderNo"/>
</template>
<template v-else-if="column.key === 'orderStatus'">
<dict-tag :value="d.row.orderStatus" :options="dict.type.order_status"/>
</template>
<template v-else-if="column.key === 'progress'">
<el-progress :percentage="d.row.progress" :color="ProgressColors" :format="ProgressFormat"/>
</template>
<template v-else-if="['orderPicture', 'orderProdPicture'].includes(column.key)">
<image-preview :src="d.row[column.key]" :width="50" :height="50"/>
</template>
<template v-else>
{{d.row[column.key]}}
</template>
</template>
</el-table-column>
</template>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" v-if="!isCustomData">
<!-- 分组表格 -->
<el-table
v-loading="loading"
size="mini"
:data="groupList"
:default-expand-all="true"
:row-style="{backgroundColor: 'rgb(221 239 255)'}"
@selection-change="handleSelectionChange">
<el-table-column type="selection" width="50" align="center" />
<el-table-column type="expand">
<template slot-scope="scope">
<!-- <el-button
size="mini"
type="text"
icon="el-icon-plus"
@click="handleStore(scope.row)"
v-has-permi="['bst:store:add']"
v-show="OrderStatus.canAddStore().includes(scope.row.orderStatus)"
>上报入库</el-button> -->
<el-button
size="mini"
type="text"
icon="el-icon-view"
@click="handleView(scope.row)"
v-has-permi="['bst:prodProcess:query']"
>详情</el-button>
<process-table
:processList="scope.row.processList"
:loading="loading"
:sum="sum"
@view="handleView"
@selection-change="handleSelectionChange"
@sort-change="onSortChange"
/>
</template>
</el-table-column>
<el-table-column label="产品名称" prop="name" align="left" />
<el-table-column label="进度" align="center" width="600">
<template slot-scope="scope">
<div style="display: flex; flex-direction: row; align-items: center; justify-content: space-between;">
<div>总数量{{ scope.row.totalNum | dv}}</div>
<div>已上报{{ scope.row.reportNum | dv}}</div>
<div>已清点{{ scope.row.storeNum | dv}}</div>
<el-progress
style="width: 160px"
:percentage="calculateProgress(scope.row)"
:color="ProgressColors"
:format="ProgressFormat"
/>
</div>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total>0 && !isCustomData"
v-show="total>0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getList"
:page-sizes="[5, 10,]"
/>
<prod-process-detail :id="row.id" :show.sync="showDetail" />
@ -190,6 +168,7 @@ import {
addProdProcess,
delProdProcess,
getProdProcess,
groupByNameProdProcess,
listProdProcess,
updateProdProcess
} from '@/api/bst/prodProcess'
@ -201,6 +180,8 @@ import { ProgressColors, ProgressFormat } from '@/utils/constants'
import OrderLink from '@/components/Business/Order/OrderLink.vue'
import { OrderStatus } from '@/utils/enums'
import ProdProcessDetail from '@/views/bst/prodProcess/components/ProdProcessDetail.vue'
import ProcessTable from '@/views/bst/prodProcess/components/ProcessTable.vue'
import { getProdProcessSum } from '@/api/dashboard/prodProcess'
//
const defaultSort = {
@ -212,21 +193,32 @@ export default {
name: "ProdProcess",
dicts: ['order_status'],
mixins: [$showColumns],
components: { OrderLink, DeptTreeSelect, BooleanTag, FormCol, ProdProcessDetail},
components: {
OrderLink,
DeptTreeSelect,
BooleanTag,
FormCol,
ProdProcessDetail,
ProcessTable
},
props: {
//
customData: {
type: Array,
default: () => ([])
},
//
isCustomData: {
type: Boolean,
default: false,
},
containerClass: {
type: String,
default: "app-container"
},
//
hiddenSearch: {
type: Boolean,
default: false,
},
query: {
type: Object,
default: () => ({})
}
},
data() {
@ -237,26 +229,6 @@ export default {
row: {},
showStoreEdit: false,
span: 24,
//
columns: [
{key: 'id', visible: false, label: 'ID', minWidth: null, sortable: true, overflow: false, align: 'center', width: "80"},
{key: 'orderNo', visible: true, label: '订单', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
{key: 'orderPicture', visible: true, label: '订单主图', minWidth: null, sortable: false, overflow: false, align: 'center', width: null},
{key: 'orderStatus', visible: true, label: '状态', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
{key: 'orderProdName', visible: true, label: '产品', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
{key: 'orderProdPicture', visible: true, label: '产品主图', minWidth: null, sortable: false, overflow: false, align: 'center', width: null},
{key: 'deptName', visible: true, label: '工序', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
{key: 'handleWay', visible: true, label: '处理方式', minWidth: null, sortable: false, overflow: false, align: 'center', width: null},
{key: 'effect', visible: true, label: '效果', minWidth: null, sortable: false, overflow: false, align: 'center', width: null},
{key: 'color', visible: true, label: '颜色', minWidth: null, sortable: false, overflow: false, align: 'center', width: null},
{key: 'coverColor', visible: true, label: '盖子颜色', minWidth: null, sortable: false, overflow: false, align: 'center', width: null},
{key: 'remark', visible: true, label: '备注', minWidth: null, sortable: false, overflow: false, align: 'center', width: null},
{key: 'isEnd', visible: true, label: '最终', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
{key: 'num', visible: true, label: '数量', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
{key: 'reportNum', visible: true, label: '已上报', minWidth: null, sortable: false, overflow: false, align: 'center', width: null},
{key: 'storeNum', visible: true, label: '已清点', minWidth: null, sortable: false, overflow: false, align: 'center', width: null},
{key: 'progress', visible: true, label: '进度', minWidth: null, sortable: false, overflow: false, align: 'center', width: "160"},
],
//
orderSorts: ['ascending', 'descending', null],
//
@ -272,7 +244,7 @@ export default {
//
total: 0,
//
prodProcessList: [],
groupList: [],
//
title: "",
//
@ -281,9 +253,7 @@ export default {
//
queryParams: {
pageNum: 1,
pageSize: 20,
orderByColumn: defaultSort.prop,
isAsc: defaultSort.order,
pageSize: 5,
id: null,
orderProdId: null,
deptId: null,
@ -315,24 +285,43 @@ export default {
deleted: [
{ required: true, message: "删除标志不能为空", trigger: "blur" }
]
}
},
sum: {}
};
},
created() {
this.initColumns();
if (this.isCustomData) {
this.prodProcessList = this.customData;
this.showSearch = !this.hiddenSearch;
this.columns.forEach(item => {
item.sortable = false
})
} else {
this.getList();
this.queryParams = {
...this.queryParams,
...this.query
}
this.getList();
},
methods: {
calculateProgress(row) {
return row.storeNum / row.totalNum * 100;
},
getSummary({columns, data}) {
const sums = ['合计'];
if (this.sum == null) {
return sums;
}
columns.forEach((column, index) => {
if (index === 0) {
return;
}
if (['num', 'reportNum', 'storeNum'].includes(column.property)) {
sums[index] = this.sum[column.property] || 0;
} else {
sums[index] = '';
}
});
return sums;
},
handleView(row) {
this.row = row;
this.showDetail = true;
@ -357,10 +346,16 @@ export default {
/** 查询产品工序列表 */
getList() {
this.loading = true;
listProdProcess(this.queryParams).then(response => {
this.prodProcessList = response.rows;
groupByNameProdProcess(this.queryParams).then(response => {
this.groupList = response.rows;
this.total = response.total;
this.loading = false;
this.getSum();
});
},
getSum() {
getProdProcessSum(this.queryParams).then(response => {
this.sum = response.data;
});
},
//