排产模块优化 / 排产单页面优化,排产模块优化 / 订单跟踪页面优化

This commit is contained in:
朱昊天
2026-07-09 17:13:46 +08:00
parent 2cd141262b
commit a0c7da8fe0
14 changed files with 723 additions and 139 deletions

View File

@@ -265,4 +265,14 @@ public class CrmOrderBo extends BaseEntity {
@JsonFormat(pattern = "yyyy-MM-dd")
private Date deliveryDateEnd;
@DateTimeFormat(pattern = "yyyy-MM-dd")
@JsonFormat(pattern = "yyyy-MM-dd")
private Date bindDateStart;
@DateTimeFormat(pattern = "yyyy-MM-dd")
@JsonFormat(pattern = "yyyy-MM-dd")
private Date bindDateEnd;
private Boolean onlyBoundSchedule;
}

View File

@@ -247,6 +247,24 @@ public class CrmOrderServiceImpl implements ICrmOrderService {
qw.lt(bo.getSignDateEnd() != null, "co.sign_time", addOneDay(bo.getSignDateEnd()));
qw.ge(bo.getDeliveryDateStart() != null, "co.delivery_date", bo.getDeliveryDateStart());
qw.lt(bo.getDeliveryDateEnd() != null, "co.delivery_date", addOneDay(bo.getDeliveryDateEnd()));
boolean applyBoundFilter = Boolean.TRUE.equals(bo.getOnlyBoundSchedule())
|| bo.getBindDateStart() != null
|| bo.getBindDateEnd() != null;
if (applyBoundFilter) {
StringBuilder existsSql = new StringBuilder();
List<Object> args = new ArrayList<>();
existsSql.append("exists (select 1 from sch_sale_schedule_rel rel where rel.del_flag = 0 and rel.order_id = co.order_id");
if (bo.getBindDateStart() != null) {
existsSql.append(" and rel.create_time >= {").append(args.size()).append("}");
args.add(bo.getBindDateStart());
}
if (bo.getBindDateEnd() != null) {
existsSql.append(" and rel.create_time < {").append(args.size()).append("}");
args.add(addOneDay(bo.getBindDateEnd()));
}
existsSql.append(")");
qw.apply(existsSql.toString(), args.toArray());
}
if(bo.getOrderIds() !=null){
qw.in(!bo.getOrderIds().isEmpty(), "co.order_id", bo.getOrderIds());
}

View File

@@ -23,6 +23,7 @@ import com.klp.flow.domain.bo.SchProdScheduleItemBo;
import com.klp.flow.domain.bo.SchProdScheduleItemMergeBo;
import com.klp.flow.domain.bo.SchProdScheduleItemReceiveBo;
import com.klp.flow.domain.bo.SchProdScheduleItemMergeValidateBo;
import com.klp.flow.domain.bo.SchProdScheduleItemSortBo;
import com.klp.flow.service.ISchProdScheduleItemService;
import com.klp.common.core.page.TableDataInfo;
@@ -138,4 +139,9 @@ public class SchProdScheduleItemController extends BaseController {
public R<SchProdScheduleItemMergeValidateVo> mergeValidate(@Validated @RequestBody SchProdScheduleItemMergeValidateBo validateBo) {
return R.ok(iSchProdScheduleItemService.validateMerge(validateBo));
}
@PostMapping("/sort")
public R<Void> saveSort(@Validated @RequestBody SchProdScheduleItemSortBo sortBo) {
return toAjax(iSchProdScheduleItemService.saveSort(sortBo));
}
}

View File

@@ -135,6 +135,10 @@ public class SchProdScheduleItem extends BaseEntity {
* 工序ID
*/
private Long actionId;
/**
* 排序号
*/
private Integer sortNo;
/**
* 规格 例1.0X1250
*/

View File

@@ -162,6 +162,10 @@ public class SchProdScheduleItemBo extends BaseEntity {
* 工序ID
*/
private Long actionId;
/**
* 排序号
*/
private Integer sortNo;
/**
* 规格 例1.0X1250

View File

@@ -0,0 +1,14 @@
package com.klp.flow.domain.bo;
import lombok.Data;
import javax.validation.constraints.NotEmpty;
import java.util.List;
@Data
public class SchProdScheduleItemSortBo {
@NotEmpty(message = "scheduleIds不能为空")
private List<Long> scheduleIds;
}

View File

@@ -202,6 +202,11 @@ public class SchProdScheduleItemVo {
@TableField(exist = false)
private String stepName;
/**
* 排序号
*/
private Integer sortNo;
/**
* 规格 例1.0X1250
*/

View File

@@ -7,6 +7,7 @@ import com.klp.flow.domain.bo.SchProdScheduleItemBo;
import com.klp.flow.domain.bo.SchProdScheduleItemMergeBo;
import com.klp.flow.domain.bo.SchProdScheduleItemReceiveBo;
import com.klp.flow.domain.bo.SchProdScheduleItemMergeValidateBo;
import com.klp.flow.domain.bo.SchProdScheduleItemSortBo;
import com.klp.common.core.page.TableDataInfo;
import com.klp.common.core.domain.PageQuery;
@@ -70,4 +71,9 @@ public interface ISchProdScheduleItemService {
* 合并校验:检查待合并记录来源产需单的 header 字段是否一致
*/
SchProdScheduleItemMergeValidateVo validateMerge(SchProdScheduleItemMergeValidateBo validateBo);
/**
* 保存已排产拖拽排序
*/
Boolean saveSort(SchProdScheduleItemSortBo sortBo);
}

View File

@@ -13,6 +13,7 @@ import com.klp.flow.domain.bo.SchProdScheduleItemBo;
import com.klp.flow.domain.bo.SchProdScheduleItemMergeBo;
import com.klp.flow.domain.bo.SchProdScheduleItemReceiveBo;
import com.klp.flow.domain.bo.SchProdScheduleItemMergeValidateBo;
import com.klp.flow.domain.bo.SchProdScheduleItemSortBo;
import com.klp.flow.domain.vo.SchProdScheduleItemVo;
import com.klp.flow.domain.vo.SchProdScheduleItemMergeValidateVo;
import com.klp.flow.domain.SchProdScheduleItem;
@@ -56,7 +57,12 @@ public class SchProdScheduleItemServiceImpl implements ISchProdScheduleItemServi
*/
@Override
public SchProdScheduleItemVo queryById(Long scheduleId){
return baseMapper.selectVoById(scheduleId);
SchProdScheduleItemVo vo = baseMapper.selectVoById(scheduleId);
if (vo != null) {
fillStepName(java.util.Collections.singletonList(vo));
fillMissingHeaderFields(java.util.Collections.singletonList(vo));
}
return vo;
}
/**
@@ -68,6 +74,7 @@ public class SchProdScheduleItemServiceImpl implements ISchProdScheduleItemServi
Page<SchProdScheduleItemVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
if (result.getRecords() != null && !result.getRecords().isEmpty()) {
fillStepName(result.getRecords());
fillMissingHeaderFields(result.getRecords());
}
return TableDataInfo.build(result);
}
@@ -81,6 +88,7 @@ public class SchProdScheduleItemServiceImpl implements ISchProdScheduleItemServi
List<SchProdScheduleItemVo> list = baseMapper.selectVoList(lqw);
if (list != null && !list.isEmpty()) {
fillStepName(list);
fillMissingHeaderFields(list);
}
return list;
}
@@ -121,6 +129,8 @@ public class SchProdScheduleItemServiceImpl implements ISchProdScheduleItemServi
lqw.eq(StringUtils.isNotBlank(bo.getRowRemark()), SchProdScheduleItem::getRowRemark, bo.getRowRemark());
// actionId
lqw.eq(bo.getActionId() != null, SchProdScheduleItem::getActionId, bo.getActionId());
lqw.orderByAsc(SchProdScheduleItem::getSortNo);
lqw.orderByAsc(SchProdScheduleItem::getScheduleId);
return lqw;
}
@@ -148,6 +158,149 @@ public class SchProdScheduleItemServiceImpl implements ISchProdScheduleItemServi
}
}
private void fillMissingHeaderFields(List<SchProdScheduleItemVo> voList) {
List<SchProdScheduleItemVo> missingList = voList.stream()
.filter(vo -> StringUtils.isBlank(vo.getCustomerName())
|| StringUtils.isBlank(vo.getBusinessUser())
|| StringUtils.isBlank(vo.getBusinessPhone())
|| vo.getDeliveryCycle() == null
|| StringUtils.isBlank(vo.getProductType())
|| StringUtils.isBlank(vo.getUsePurpose()))
.collect(Collectors.toList());
if (missingList.isEmpty()) {
return;
}
List<String> scheduleNos = missingList.stream()
.map(SchProdScheduleItemVo::getScheduleNo)
.filter(StringUtils::isNotBlank)
.distinct()
.collect(Collectors.toList());
if (scheduleNos.isEmpty()) {
return;
}
List<SchProdSchedule> headers = schProdScheduleMapper.selectList(
Wrappers.<SchProdSchedule>lambdaQuery()
.in(SchProdSchedule::getScheduleNo, scheduleNos)
);
Map<String, SchProdSchedule> headerMap = headers.stream()
.collect(Collectors.toMap(SchProdSchedule::getScheduleNo, h -> h, (v1, v2) -> v1));
for (SchProdScheduleItemVo vo : missingList) {
SchProdSchedule header = headerMap.get(vo.getScheduleNo());
if (header == null) {
continue;
}
boolean changed = false;
SchProdScheduleItem update = new SchProdScheduleItem();
update.setScheduleId(vo.getScheduleId());
if (StringUtils.isBlank(vo.getCustomerName()) && StringUtils.isNotBlank(header.getCustomerName())) {
vo.setCustomerName(header.getCustomerName());
update.setCustomerName(header.getCustomerName());
changed = true;
}
if (StringUtils.isBlank(vo.getBusinessUser()) && StringUtils.isNotBlank(header.getBusinessUser())) {
vo.setBusinessUser(header.getBusinessUser());
update.setBusinessUser(header.getBusinessUser());
changed = true;
}
if (StringUtils.isBlank(vo.getBusinessPhone()) && StringUtils.isNotBlank(header.getBusinessPhone())) {
vo.setBusinessPhone(header.getBusinessPhone());
update.setBusinessPhone(header.getBusinessPhone());
changed = true;
}
if (vo.getDeliveryCycle() == null && header.getDeliveryCycle() != null) {
vo.setDeliveryCycle(header.getDeliveryCycle());
update.setDeliveryCycle(header.getDeliveryCycle());
changed = true;
}
if (StringUtils.isBlank(vo.getProductType()) && StringUtils.isNotBlank(header.getProductType())) {
vo.setProductType(header.getProductType());
update.setProductType(header.getProductType());
changed = true;
}
if (StringUtils.isBlank(vo.getUsePurpose()) && StringUtils.isNotBlank(header.getUsePurpose())) {
vo.setUsePurpose(header.getUsePurpose());
update.setUsePurpose(header.getUsePurpose());
changed = true;
}
if (StringUtils.isBlank(vo.getThicknessTolerance()) && StringUtils.isNotBlank(header.getThicknessTolerance())) {
vo.setThicknessTolerance(header.getThicknessTolerance());
update.setThicknessTolerance(header.getThicknessTolerance());
changed = true;
}
if (StringUtils.isBlank(vo.getWidthTolerance()) && StringUtils.isNotBlank(header.getWidthTolerance())) {
vo.setWidthTolerance(header.getWidthTolerance());
update.setWidthTolerance(header.getWidthTolerance());
changed = true;
}
if (StringUtils.isBlank(vo.getSurfaceQuality()) && StringUtils.isNotBlank(header.getSurfaceQuality())) {
vo.setSurfaceQuality(header.getSurfaceQuality());
update.setSurfaceQuality(header.getSurfaceQuality());
changed = true;
}
if (StringUtils.isBlank(vo.getSurfaceTreatment()) && StringUtils.isNotBlank(header.getSurfaceTreatment())) {
vo.setSurfaceTreatment(header.getSurfaceTreatment());
update.setSurfaceTreatment(header.getSurfaceTreatment());
changed = true;
}
if (StringUtils.isBlank(vo.getInnerDiameter()) && StringUtils.isNotBlank(header.getInnerDiameter())) {
vo.setInnerDiameter(header.getInnerDiameter());
update.setInnerDiameter(header.getInnerDiameter());
changed = true;
}
if (StringUtils.isBlank(vo.getOuterDiameter()) && StringUtils.isNotBlank(header.getOuterDiameter())) {
vo.setOuterDiameter(header.getOuterDiameter());
update.setOuterDiameter(header.getOuterDiameter());
changed = true;
}
if (StringUtils.isBlank(vo.getPackReq()) && StringUtils.isNotBlank(header.getPackReq())) {
vo.setPackReq(header.getPackReq());
update.setPackReq(header.getPackReq());
changed = true;
}
if (StringUtils.isBlank(vo.getCutEdgeReq()) && StringUtils.isNotBlank(header.getCutEdgeReq())) {
vo.setCutEdgeReq(header.getCutEdgeReq());
update.setCutEdgeReq(header.getCutEdgeReq());
changed = true;
}
if (StringUtils.isBlank(vo.getSingleCoilWeight()) && StringUtils.isNotBlank(header.getSingleCoilWeight())) {
vo.setSingleCoilWeight(header.getSingleCoilWeight());
update.setSingleCoilWeight(header.getSingleCoilWeight());
changed = true;
}
if (StringUtils.isBlank(vo.getWeightDeviation()) && StringUtils.isNotBlank(header.getWeightDeviation())) {
vo.setWeightDeviation(header.getWeightDeviation());
update.setWeightDeviation(header.getWeightDeviation());
changed = true;
}
if (StringUtils.isBlank(vo.getOtherTechReq()) && StringUtils.isNotBlank(header.getOtherTechReq())) {
vo.setOtherTechReq(header.getOtherTechReq());
update.setOtherTechReq(header.getOtherTechReq());
changed = true;
}
if (StringUtils.isBlank(vo.getPaymentDesc()) && StringUtils.isNotBlank(header.getPaymentDesc())) {
vo.setPaymentDesc(header.getPaymentDesc());
update.setPaymentDesc(header.getPaymentDesc());
changed = true;
}
if (StringUtils.isBlank(vo.getRemark()) && StringUtils.isNotBlank(header.getRemark())) {
vo.setRemark(header.getRemark());
update.setRemark(header.getRemark());
changed = true;
}
if (changed) {
baseMapper.updateById(update);
}
}
}
/**
* 新增排产单主加明细可合并
*/
@@ -504,6 +657,22 @@ public class SchProdScheduleItemServiceImpl implements ISchProdScheduleItemServi
return vo;
}
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean saveSort(SchProdScheduleItemSortBo sortBo) {
List<Long> scheduleIds = sortBo.getScheduleIds();
for (int i = 0; i < scheduleIds.size(); i++) {
Long id = scheduleIds.get(i);
baseMapper.update(
null,
Wrappers.<SchProdScheduleItem>lambdaUpdate()
.set(SchProdScheduleItem::getSortNo, i + 1)
.eq(SchProdScheduleItem::getScheduleId, id)
);
}
return true;
}
/**
* 反射获取字段值(用于动态字段比较 — SchProdSchedule header
*/

View File

@@ -33,6 +33,7 @@
<result property="returnReason" column="return_reason"/>
<result property="scheduleDetailIds" column="schedule_detail_ids"/>
<result property="actionId" column="action_id"/>
<result property="sortNo" column="sort_no"/>
<result property="spec" column="spec"/>
<result property="material" column="material"/>
<result property="scheduleWeight" column="schedule_weight"/>

View File

@@ -99,3 +99,11 @@ export function mergeScheduleItem(data) {
data
})
}
export function saveScheduleItemSort(data) {
return request({
url: '/flow/prodScheduleItem/sort',
method: 'post',
data
})
}

View File

@@ -32,6 +32,22 @@
<el-date-picker clearable v-model="queryParams.deliveryDateEnd" type="date" value-format="yyyy-MM-dd"
placeholder="交货结束" style="width: 150px;" @change="handleSearch" />
</div>
<div style="display: flex; align-items: center; gap: 4px; font-size: 13px; color: #606266;">
<span style="white-space: nowrap;">绑定日期</span>
<el-date-picker
v-model="bindDateRange"
type="daterange"
value-format="yyyy-MM-dd"
unlink-panels
clearable
range-separator="~"
start-placeholder="开始"
end-placeholder="结束"
:picker-options="bindDatePickerOptions"
style="width: 260px;"
@change="handleSearch"
/>
</div>
</div>
<div v-show="showMoreFilter" class="more-filter"
style="margin-top: 8px; padding-top: 10px; border-top: 1px dashed #e4e7ed;">
@@ -209,6 +225,29 @@ export default {
batchTargetContractId: '',
batchTransferCoilIds: [],
batchTransferLoading: false,
bindDateRange: [],
bindDatePickerOptions: {
shortcuts: [
{
text: '今天',
onClick(picker) {
const today = new Date()
const start = new Date(today.getFullYear(), today.getMonth(), today.getDate())
const end = new Date(today.getFullYear(), today.getMonth(), today.getDate())
picker.$emit('pick', [start, end])
}
},
{
text: '最近7天',
onClick(picker) {
const end = new Date()
const start = new Date()
start.setDate(start.getDate() - 6)
picker.$emit('pick', [start, end])
}
}
]
},
queryParams: {
keyword: '',
orderCode: '',
@@ -218,6 +257,9 @@ export default {
signDateEnd: undefined,
deliveryDateStart: undefined,
deliveryDateEnd: undefined,
bindDateStart: undefined,
bindDateEnd: undefined,
onlyBoundSchedule: true,
pageNum: 1,
pageSize: 10
}
@@ -249,9 +291,35 @@ export default {
}
},
created() {
this.initBindDateRange()
this.getList()
},
methods: {
formatDate(date) {
if (!date) return ''
const y = date.getFullYear()
const m = String(date.getMonth() + 1).padStart(2, '0')
const d = String(date.getDate()).padStart(2, '0')
return `${y}-${m}-${d}`
},
initBindDateRange() {
const end = new Date()
const start = new Date()
start.setDate(start.getDate() - 6)
this.bindDateRange = [this.formatDate(start), this.formatDate(end)]
},
syncBindQueryParams() {
const range = this.bindDateRange || []
if (Array.isArray(range) && range.length === 2 && range[0] && range[1]) {
this.queryParams.bindDateStart = range[0]
this.queryParams.bindDateEnd = range[1]
this.queryParams.onlyBoundSchedule = true
return
}
this.queryParams.bindDateStart = undefined
this.queryParams.bindDateEnd = undefined
this.queryParams.onlyBoundSchedule = false
},
toggleMoreFilter() {
this.showMoreFilter = !this.showMoreFilter
},
@@ -267,9 +335,11 @@ export default {
this.queryParams.signDateEnd = undefined
this.queryParams.deliveryDateStart = undefined
this.queryParams.deliveryDateEnd = undefined
this.initBindDateRange()
this.handleSearch()
},
getList() {
this.syncBindQueryParams()
this.orderLoading = true
listCrmOrder(this.queryParams).then(res => {
this.orderList = res.rows || []

View File

@@ -44,21 +44,29 @@
</span>
</div>
<div class="aps-sch-item-actions">
<el-button type="text" size="small" style="color:#52c41a;" @click.stop="handleAccept(sch)">接收</el-button>
<el-button type="text" size="small" style="color:#ff4d4f;" @click.stop="handleReject(sch)">驳回</el-button>
<el-button type="text" size="mini" style="color:#52c41a;" @click.stop="handleAccept(sch)">接收</el-button>
<el-button type="text" size="mini" style="color:#ff4d4f;" @click.stop="handleReject(sch)">驳回</el-button>
</div>
</div>
<!-- 产需单完整信息表 -->
<table class="req-info-table">
<colgroup>
<col style="width: 88px;">
<col>
<col style="width: 88px;">
<col>
<col style="width: 88px;">
<col>
<col style="width: 88px;">
<col>
</colgroup>
<tbody>
<tr>
<td class="req-td-label">排产单号</td>
<td class="req-td-value">{{ sch.scheduleNo }}</td>
<td class="req-td-label">生产日期</td>
<td class="req-td-value">{{ sch.prodDate }}</td>
</tr>
<tr>
<td class="req-td-label">排产状态</td>
<td class="req-td-value">
<span class="aps-status-tag" :class="'status-' + (sch.scheduleStatus || 1)">{{ statusMap[sch.scheduleStatus] || '未知' }}</span>
@@ -67,28 +75,20 @@
<td class="req-td-value">{{ sch.businessUser }}</td>
</tr>
<tr>
<td class="req-td-label">联系电话</td>
<td class="req-td-value">{{ sch.businessPhone }}</td>
<td class="req-td-label">订货单位</td>
<td class="req-td-value">{{ sch.customerName }}</td>
</tr>
<tr>
<td class="req-td-label">联系电话</td>
<td class="req-td-value">{{ sch.businessPhone }}</td>
<td class="req-td-label">交货期()</td>
<td class="req-td-value">{{ sch.deliveryCycle }}</td>
<td class="req-td-label">产品用途</td>
<td class="req-td-value">{{ sch.usePurpose }}</td>
</tr>
<tr>
<td class="req-td-label">品名</td>
<td class="req-td-value" colspan="3">{{ sch.productType }}</td>
<td class="req-td-value">{{ sch.productType }}</td>
</tr>
<tr>
<td class="req-td-label">厚度公差</td>
<td class="req-td-value">{{ sch.thicknessTolerance }}</td>
<td class="req-td-label">宽度公差</td>
<td class="req-td-value">{{ sch.widthTolerance }}</td>
</tr>
<tr>
<td class="req-td-label">表面质量</td>
<td class="req-td-value">{{ sch.surfaceQuality }}</td>
<td class="req-td-label">表面处理</td>
@@ -99,8 +99,6 @@
<td class="req-td-value">{{ sch.innerDiameter }}</td>
<td class="req-td-label">外径要求</td>
<td class="req-td-value">{{ sch.outerDiameter }}</td>
</tr>
<tr>
<td class="req-td-label">包装要求</td>
<td class="req-td-value">{{ sch.packReq }}</td>
<td class="req-td-label">切边要求</td>
@@ -111,22 +109,24 @@
<td class="req-td-value">{{ sch.singleCoilWeight }}</td>
<td class="req-td-label">交货重量偏差</td>
<td class="req-td-value">{{ sch.weightDeviation }}</td>
</tr>
<tr>
<td class="req-td-label">其他技术要求</td>
<td class="req-td-value" colspan="3">{{ sch.otherTechReq }}</td>
</tr>
<tr>
<td class="req-td-label">付款情况说明</td>
<td class="req-td-value" colspan="3">{{ sch.paymentDesc }}</td>
<td class="req-td-label">产品用途</td>
<td class="req-td-value" colspan="3">{{ sch.usePurpose || '-' }}</td>
</tr>
<tr>
<td class="req-td-label">备注</td>
<td class="req-td-value" colspan="3">{{ sch.remark }}</td>
<td class="req-td-value" colspan="7">{{ sch.remark || '-' }}</td>
</tr>
<tr v-if="sch.otherTechReq">
<td class="req-td-label">其他技术要求</td>
<td class="req-td-value" colspan="7">{{ sch.otherTechReq }}</td>
</tr>
<tr v-if="sch.paymentDesc">
<td class="req-td-label">付款情况说明</td>
<td class="req-td-value" colspan="7">{{ sch.paymentDesc }}</td>
</tr>
<tr v-if="sch.returnReason">
<td class="req-td-label" style="color:#e74c3c;">驳回原因</td>
<td class="req-td-value" colspan="3" style="color:#e74c3c;background:#fdecea;">{{ sch.returnReason }}</td>
<td class="req-td-value" colspan="7" style="color:#e74c3c;background:#fdecea;">{{ sch.returnReason }}</td>
</tr>
</tbody>
</table>
@@ -156,7 +156,7 @@
<div v-else class="aps-sch-item-empty">暂无明细</div>
</div>
</div>
<div v-else-if="!loading" style="padding:40px;text-align:center;color:#909399;">
<div v-else-if="!loading" style="padding:24px;text-align:center;color:#909399;">
{{ hasQueried ? '该日期暂无待审核产需单' : '请选择日期查询' }}
</div>
</div>
@@ -184,53 +184,78 @@
</div>
<table class="req-info-table">
<colgroup>
<col style="width: 88px;">
<col>
<col style="width: 88px;">
<col>
<col style="width: 88px;">
<col>
<col style="width: 88px;">
<col>
</colgroup>
<tbody>
<tr>
<td class="req-td-label">排产单号</td><td class="req-td-value">{{ sch.scheduleNo }}</td>
<td class="req-td-label">生产日期</td><td class="req-td-value">{{ sch.prodDate }}</td>
<td class="req-td-label">排产单号</td>
<td class="req-td-value">{{ sch.scheduleNo }}</td>
<td class="req-td-label">生产日期</td>
<td class="req-td-value">{{ sch.prodDate }}</td>
<td class="req-td-label">排产状态</td>
<td class="req-td-value">
<span class="aps-status-tag status-2">已接收</span>
</td>
<td class="req-td-label">业务员</td>
<td class="req-td-value">{{ sch.businessUser }}</td>
</tr>
<tr>
<td class="req-td-label">业务员</td><td class="req-td-value">{{ sch.businessUser }}</td>
<td class="req-td-label">联系电话</td><td class="req-td-value">{{ sch.businessPhone }}</td>
<td class="req-td-label">订货单位</td>
<td class="req-td-value">{{ sch.customerName }}</td>
<td class="req-td-label">联系电话</td>
<td class="req-td-value">{{ sch.businessPhone }}</td>
<td class="req-td-label">交货期()</td>
<td class="req-td-value">{{ sch.deliveryCycle }}</td>
<td class="req-td-label">品名</td>
<td class="req-td-value">{{ sch.productType }}</td>
</tr>
<tr>
<td class="req-td-label">订货单位</td><td class="req-td-value">{{ sch.customerName }}</td>
<td class="req-td-label">交货期()</td><td class="req-td-value">{{ sch.deliveryCycle }}</td>
<td class="req-td-label">厚度公差</td>
<td class="req-td-value">{{ sch.thicknessTolerance }}</td>
<td class="req-td-label">宽度公差</td>
<td class="req-td-value">{{ sch.widthTolerance }}</td>
<td class="req-td-label">表面质量</td>
<td class="req-td-value">{{ sch.surfaceQuality }}</td>
<td class="req-td-label">表面处理</td>
<td class="req-td-value">{{ sch.surfaceTreatment }}</td>
</tr>
<tr>
<td class="req-td-label">品名</td><td class="req-td-value" colspan="3">{{ sch.productType }}</td>
<td class="req-td-label">内径尺寸</td>
<td class="req-td-value">{{ sch.innerDiameter }}</td>
<td class="req-td-label">外径要求</td>
<td class="req-td-value">{{ sch.outerDiameter }}</td>
<td class="req-td-label">包装要求</td>
<td class="req-td-value">{{ sch.packReq }}</td>
<td class="req-td-label">切边要求</td>
<td class="req-td-value">{{ sch.cutEdgeReq }}</td>
</tr>
<tr>
<td class="req-td-label">产品用途</td><td class="req-td-value" colspan="3">{{ sch.usePurpose }}</td>
<td class="req-td-label">单件重量</td>
<td class="req-td-value">{{ sch.singleCoilWeight }}</td>
<td class="req-td-label">交货重量偏差</td>
<td class="req-td-value">{{ sch.weightDeviation }}</td>
<td class="req-td-label">产品用途</td>
<td class="req-td-value" colspan="3">{{ sch.usePurpose || '-' }}</td>
</tr>
<tr>
<td class="req-td-label">厚度公差</td><td class="req-td-value">{{ sch.thicknessTolerance }}</td>
<td class="req-td-label">宽度公差</td><td class="req-td-value">{{ sch.widthTolerance }}</td>
</tr>
<tr>
<td class="req-td-label">表面质量</td><td class="req-td-value">{{ sch.surfaceQuality }}</td>
<td class="req-td-label">表面处理</td><td class="req-td-value">{{ sch.surfaceTreatment }}</td>
</tr>
<tr>
<td class="req-td-label">内径尺寸</td><td class="req-td-value">{{ sch.innerDiameter }}</td>
<td class="req-td-label">外径要求</td><td class="req-td-value">{{ sch.outerDiameter }}</td>
</tr>
<tr>
<td class="req-td-label">包装要求</td><td class="req-td-value">{{ sch.packReq }}</td>
<td class="req-td-label">切边要求</td><td class="req-td-value">{{ sch.cutEdgeReq }}</td>
</tr>
<tr>
<td class="req-td-label">单件重量</td><td class="req-td-value">{{ sch.singleCoilWeight }}</td>
<td class="req-td-label">交货重量偏差</td><td class="req-td-value">{{ sch.weightDeviation }}</td>
<td class="req-td-label">备注</td>
<td class="req-td-value" colspan="7">{{ sch.remark || '-' }}</td>
</tr>
<tr v-if="sch.otherTechReq">
<td class="req-td-label">其他技术要求</td><td class="req-td-value" colspan="3">{{ sch.otherTechReq }}</td>
<td class="req-td-label">其他技术要求</td>
<td class="req-td-value" colspan="7">{{ sch.otherTechReq }}</td>
</tr>
<tr v-if="sch.paymentDesc">
<td class="req-td-label">付款情况说明</td><td class="req-td-value" colspan="3">{{ sch.paymentDesc }}</td>
</tr>
<tr v-if="sch.remark">
<td class="req-td-label">备注</td><td class="req-td-value" colspan="3">{{ sch.remark }}</td>
<td class="req-td-label">付款情况说明</td>
<td class="req-td-value" colspan="7">{{ sch.paymentDesc }}</td>
</tr>
</tbody>
</table>
@@ -254,7 +279,7 @@
<div v-else class="aps-sch-item-empty">暂无明细</div>
</div>
</div>
<div v-else-if="!acceptedLoading" style="padding:40px;text-align:center;color:#909399;">
<div v-else-if="!acceptedLoading" style="padding:24px;text-align:center;color:#909399;">
{{ hasQueried ? '该日期暂无已接收产需单' : '请选择日期查询' }}
</div>
</div>
@@ -284,64 +309,66 @@
{{ tab }}
<span class="aps-step-tab-count">{{ scheduledItemList.filter(i => normalizeStepName(i.stepName) === tab).length }}</span>
</span>
<div class="aps-step-tabs-right">
<el-button size="mini" class="aps-btn-red" :disabled="!scheduledSortDirty" :loading="saveSortLoading" @click="handleSaveScheduledSort">保存排序</el-button>
</div>
</div>
<!-- 表格 -->
<el-table
ref="scheduledTable"
:data="currentStepItems"
border
size="small"
class="aps-table"
>
<el-table-column label="排产单号" prop="scheduleNo" min-width="140" show-overflow-tooltip />
<el-table-column label="生产日期" prop="prodDate" width="110" align="center" show-overflow-tooltip />
<el-table-column label="工序步骤" prop="stepName" width="120" align="center" show-overflow-tooltip />
<el-table-column label="排产状态" width="115" align="center">
<template slot-scope="scope">
<el-select
v-model="scope.row.scheduleStatus"
size="mini"
:loading="scope.row._statusLoading"
@change="val => handleInlineStatusChange(scope.row, val)"
@click.stop.native
>
<el-option v-for="(label, val) in statusMap" :key="val" :label="label" :value="Number(val)" />
</el-select>
</template>
</el-table-column>
<el-table-column label="规格" prop="spec" min-width="120" show-overflow-tooltip />
<el-table-column label="材质" prop="material" width="90" align="center" show-overflow-tooltip />
<el-table-column label="排产吨数" prop="scheduleWeight" width="100" align="right" show-overflow-tooltip />
<el-table-column label="品名项" prop="productItem" min-width="100" show-overflow-tooltip />
<el-table-column label="品名" prop="productType" min-width="90" align="center" show-overflow-tooltip />
<el-table-column label="订货单位" prop="customerName" min-width="140" show-overflow-tooltip />
<el-table-column label="业务员" prop="businessUser" width="90" align="center" show-overflow-tooltip />
<el-table-column label="联系电话" prop="businessPhone" width="110" align="center" show-overflow-tooltip />
<el-table-column label="交货期(天)" prop="deliveryCycle" width="100" align="center" show-overflow-tooltip />
<el-table-column label="产品用途" prop="usePurpose" min-width="120" show-overflow-tooltip />
<el-table-column label="厚度公差" prop="thicknessTolerance" min-width="100" show-overflow-tooltip />
<el-table-column label="宽度公差" prop="widthTolerance" min-width="100" show-overflow-tooltip />
<el-table-column label="表面质量" prop="surfaceQuality" min-width="100" show-overflow-tooltip />
<el-table-column label="表面处理" prop="surfaceTreatment" min-width="100" show-overflow-tooltip />
<el-table-column label="内径尺寸" prop="innerDiameter" width="90" align="center" show-overflow-tooltip />
<el-table-column label="外径要求" prop="outerDiameter" width="90" align="center" show-overflow-tooltip />
<el-table-column label="包装要求" prop="packReq" min-width="100" show-overflow-tooltip />
<el-table-column label="切边要求" prop="cutEdgeReq" min-width="100" show-overflow-tooltip />
<el-table-column label="单件重量" prop="singleCoilWeight" width="90" align="center" show-overflow-tooltip />
<el-table-column label="交货重量偏差" prop="weightDeviation" min-width="110" show-overflow-tooltip />
<el-table-column label="其他技术要求" prop="otherTechReq" min-width="130" show-overflow-tooltip />
<el-table-column label="付款情况说明" prop="paymentDesc" min-width="130" show-overflow-tooltip />
<el-table-column label="单行排产备注" prop="rowRemark" min-width="100" show-overflow-tooltip />
<el-table-column label="备注" prop="remark" min-width="100" show-overflow-tooltip />
<el-table-column label="操作" width="150" align="center" fixed="right">
<template slot-scope="scope">
<div style="display:flex; justify-content:center; gap:0;">
<el-button type="text" size="small" style="color:#409EFF;padding:0 6px;" @click="handleEditScheduled(scope.row)">编辑</el-button>
<el-button type="text" size="small" style="color:#ff4d4f;padding:0 6px;" @click="handleDeleteScheduled(scope.row)">删除</el-button>
<div class="aps-scheduled-cards">
<draggable v-model="scheduledStepItems" ghost-class="aps-drag-ghost" handle=".aps-drag-handle" @end="handleScheduledDragEnd">
<div v-for="row in scheduledStepItems" :key="row.scheduleId" class="aps-scheduled-card">
<div class="aps-scheduled-card-header">
<div class="aps-scheduled-card-title">
<i class="el-icon-rank aps-drag-handle"></i>
<span class="aps-scheduled-no">{{ row.scheduleNo }}</span>
<span class="aps-scheduled-step">{{ row.stepName }}</span>
</div>
<div class="aps-scheduled-card-actions">
<el-select
v-model="row.scheduleStatus"
size="mini"
:loading="row._statusLoading"
@change="val => handleInlineStatusChange(row, val)"
@click.stop.native
style="width: 110px;"
>
<el-option v-for="(label, val) in statusMap" :key="val" :label="label" :value="Number(val)" />
</el-select>
<el-button type="text" size="mini" style="color:#409EFF;padding:0 6px;" @click="handleEditScheduled(row)">编辑</el-button>
<el-button type="text" size="mini" style="color:#ff4d4f;padding:0 6px;" @click="handleDeleteScheduled(row)">删除</el-button>
</div>
</div>
</template>
</el-table-column>
</el-table>
<div class="aps-scheduled-card-body">
<div class="aps-scheduled-kv">
<div class="kv-item"><span class="kv-label">生产日期</span><span class="kv-value">{{ row.prodDate }}</span></div>
<div class="kv-item"><span class="kv-label">规格</span><span class="kv-value">{{ row.spec }}</span></div>
<div class="kv-item"><span class="kv-label">材质</span><span class="kv-value">{{ row.material }}</span></div>
<div class="kv-item"><span class="kv-label">排产吨数</span><span class="kv-value">{{ row.scheduleWeight }}</span></div>
<div class="kv-item"><span class="kv-label">品名项</span><span class="kv-value">{{ row.productItem }}</span></div>
<div class="kv-item"><span class="kv-label">品名</span><span class="kv-value">{{ row.productType }}</span></div>
<div class="kv-item"><span class="kv-label">订货单位</span><span class="kv-value">{{ row.customerName }}</span></div>
<div class="kv-item"><span class="kv-label">业务员</span><span class="kv-value">{{ row.businessUser }}</span></div>
<div class="kv-item"><span class="kv-label">联系电话</span><span class="kv-value">{{ row.businessPhone }}</span></div>
<div class="kv-item"><span class="kv-label">交货期()</span><span class="kv-value">{{ row.deliveryCycle }}</span></div>
<div class="kv-item"><span class="kv-label">厚度公差</span><span class="kv-value">{{ row.thicknessTolerance }}</span></div>
<div class="kv-item"><span class="kv-label">宽度公差</span><span class="kv-value">{{ row.widthTolerance }}</span></div>
<div class="kv-item"><span class="kv-label">表面质量</span><span class="kv-value">{{ row.surfaceQuality }}</span></div>
<div class="kv-item"><span class="kv-label">表面处理</span><span class="kv-value">{{ row.surfaceTreatment }}</span></div>
<div class="kv-item"><span class="kv-label">内径尺寸</span><span class="kv-value">{{ row.innerDiameter }}</span></div>
<div class="kv-item"><span class="kv-label">外径要求</span><span class="kv-value">{{ row.outerDiameter }}</span></div>
<div class="kv-item"><span class="kv-label">包装要求</span><span class="kv-value">{{ row.packReq }}</span></div>
<div class="kv-item"><span class="kv-label">切边要求</span><span class="kv-value">{{ row.cutEdgeReq }}</span></div>
<div class="kv-item"><span class="kv-label">单件重量</span><span class="kv-value">{{ row.singleCoilWeight }}</span></div>
<div class="kv-item"><span class="kv-label">交货重量偏差</span><span class="kv-value">{{ row.weightDeviation }}</span></div>
<div class="kv-item kv-span-4"><span class="kv-label">产品用途</span><span class="kv-value kv-value-wrap">{{ row.usePurpose }}</span></div>
<div class="kv-item kv-span-4" v-if="row.otherTechReq"><span class="kv-label">其他技术要求</span><span class="kv-value kv-value-wrap">{{ row.otherTechReq }}</span></div>
<div class="kv-item kv-span-4" v-if="row.paymentDesc"><span class="kv-label">付款情况说明</span><span class="kv-value kv-value-wrap">{{ row.paymentDesc }}</span></div>
<div class="kv-item kv-span-4" v-if="row.rowRemark"><span class="kv-label">单行排产备注</span><span class="kv-value kv-value-wrap">{{ row.rowRemark }}</span></div>
<div class="kv-item kv-span-4" v-if="row.remark"><span class="kv-label">备注</span><span class="kv-value kv-value-wrap">{{ row.remark }}</span></div>
</div>
</div>
</div>
</draggable>
</div>
</template>
<div v-else-if="!schLoading" style="padding:40px;text-align:center;color:#909399;">
{{ hasQueried ? '该日期暂无已排产数据' : '请选择日期查询' }}
@@ -645,14 +672,16 @@ import {
listScheduleItem,
updateScheduleItem,
delScheduleItem,
receiveScheduleItem
receiveScheduleItem,
saveScheduleItemSort
} from '@/api/aps/schedule'
import { PROCESSES } from '@/utils/meta'
import ProcessSelect from '@/components/KLPService/ProcessSelect/index.vue'
import draggable from 'vuedraggable'
export default {
name: 'ApsSchedule',
components: { ProcessSelect },
components: { ProcessSelect, draggable },
data() {
const today = new Date()
const y = today.getFullYear()
@@ -678,6 +707,10 @@ export default {
// 已排产
scheduledItemList: [],
scheduledStepTab: '',
scheduledOrderMap: {},
scheduledStepItems: [],
scheduledSortDirtyMap: {},
saveSortLoading: false,
// 驳回
rejectDialogVisible: false,
@@ -724,13 +757,82 @@ export default {
return this.scheduledItemList.filter(
item => this.normalizeStepName(item.stepName) === tab
)
},
scheduledSortDirty() {
const tab = this.scheduledStepTab
if (!tab) return false
return !!this.scheduledSortDirtyMap[tab]
}
},
watch: {
scheduledStepTab() {
this.refreshScheduledStepItems()
}
},
watch: {},
created() {
this.handleQuery()
},
methods: {
getScheduledItemKey(row) {
return row && row.scheduleId != null ? String(row.scheduleId) : ''
},
refreshScheduledStepItems() {
const tab = this.scheduledStepTab
if (!tab) {
this.scheduledStepItems = []
return
}
const stepItems = this.scheduledItemList.filter(i => this.normalizeStepName(i.stepName) === tab)
const order = this.scheduledOrderMap[tab]
if (!Array.isArray(order) || order.length === 0) {
const keys = stepItems.map(i => this.getScheduledItemKey(i)).filter(Boolean)
this.$set(this.scheduledOrderMap, tab, keys)
this.scheduledStepItems = stepItems.slice()
return
}
const indexMap = new Map(order.map((k, idx) => [k, idx]))
this.scheduledStepItems = stepItems
.slice()
.sort((a, b) => {
const ka = this.getScheduledItemKey(a)
const kb = this.getScheduledItemKey(b)
const ia = indexMap.has(ka) ? indexMap.get(ka) : 999999
const ib = indexMap.has(kb) ? indexMap.get(kb) : 999999
return ia - ib
})
const existKeys = new Set(stepItems.map(i => this.getScheduledItemKey(i)))
const nextOrder = order.filter(k => existKeys.has(k))
const missing = stepItems.map(i => this.getScheduledItemKey(i)).filter(k => k && !nextOrder.includes(k))
if (missing.length) {
nextOrder.push(...missing)
}
if (nextOrder.join('|') !== order.join('|')) {
this.$set(this.scheduledOrderMap, tab, nextOrder)
}
},
handleScheduledDragEnd() {
const tab = this.scheduledStepTab
if (!tab) return
const keys = (this.scheduledStepItems || []).map(i => this.getScheduledItemKey(i)).filter(Boolean)
this.$set(this.scheduledOrderMap, tab, keys)
this.$set(this.scheduledSortDirtyMap, tab, true)
},
handleSaveScheduledSort() {
const tab = this.scheduledStepTab
if (!tab) return
const scheduleIds = (this.scheduledStepItems || []).map(i => i.scheduleId).filter(v => v != null)
if (scheduleIds.length === 0) return
this.saveSortLoading = true
saveScheduleItemSort({ scheduleIds }).then(() => {
this.$modal.msgSuccess('排序已保存')
this.$set(this.scheduledSortDirtyMap, tab, false)
this.queryScheduled()
}).catch(() => {
this.$modal.msgError('保存排序失败')
}).finally(() => {
this.saveSortLoading = false
})
},
getEmptyEditForm() {
return {
scheduleId: undefined,
@@ -929,14 +1031,18 @@ export default {
this.schLoading = true
this.scheduledItemList = []
this.scheduledStepTab = ''
this.scheduledOrderMap = {}
this.scheduledStepItems = []
this.scheduledSortDirtyMap = {}
listScheduleItem({ prodDate: this.queryDate, pageNum: 1, pageSize: 999 }).then(res => {
this.scheduledItemList = (res.rows || []).sort((a, b) => (a.scheduleNo || '').localeCompare(b.scheduleNo || ''))
this.scheduledItemList = res.rows || []
// 默认选中第一个步骤tab
const tabs = this.scheduledStepTabs
if (tabs.length > 0) {
this.scheduledStepTab = tabs[0]
}
this.refreshScheduledStepItems()
const totalWeight = this.scheduledItemList.reduce((sum, d) => {
const w = parseFloat(d.scheduleWeight)
return sum + (isNaN(w) ? 0 : w)
@@ -945,6 +1051,9 @@ export default {
}).catch((e) => {
console.error('queryScheduled error:', e)
this.scheduledItemList = []
this.scheduledOrderMap = {}
this.scheduledStepItems = []
this.scheduledSortDirtyMap = {}
this.summaryText = ''
}).finally(() => {
this.schLoading = false
@@ -1046,20 +1155,20 @@ export default {
.aps-sch-page {
height: 100%;
padding: 8px;
padding: 6px;
box-sizing: border-box;
background: $aps-bg;
display: flex;
flex-direction: column;
gap: 12px;
gap: 10px;
}
// 工具栏
.aps-sch-toolbar {
display: flex;
align-items: center;
gap: 10px;
padding: 10px 16px;
gap: 8px;
padding: 8px 12px;
background: $aps-white;
border: 1px solid $aps-border;
border-radius: $aps-radius;
@@ -1126,6 +1235,15 @@ export default {
@include aps-btn-red;
}
.aps-btn-red.is-disabled,
.aps-btn-red.is-disabled:hover,
.aps-btn-red.is-disabled:focus,
.aps-btn-red.is-disabled:active {
color: $aps-silver-4;
background: $aps-silver-2;
border-color: $aps-silver-3;
}
.detail-card {
background: $aps-white;
border: 1px solid $aps-border;
@@ -1137,7 +1255,7 @@ export default {
.detail-card-header {
background: linear-gradient(to right, $aps-red-2, $aps-red-3);
color: white;
padding: 8px 14px;
padding: 6px 12px;
font-size: 13px;
font-weight: 600;
display: flex;
@@ -1147,7 +1265,7 @@ export default {
}
.detail-card-body {
padding: 14px;
padding: 10px;
}
.form-grid-2 {
@@ -1197,8 +1315,8 @@ export default {
.aps-sch-list {
display: flex;
flex-direction: column;
gap: 10px;
padding: 8px;
gap: 8px;
padding: 6px;
}
.aps-sch-item {
@@ -1213,7 +1331,7 @@ export default {
display: flex;
align-items: center;
justify-content: space-between;
padding: 8px 14px;
padding: 6px 12px;
background: linear-gradient(135deg, $aps-silver-1 0%, #f8f9fb 100%);
border-bottom: 1px solid $aps-border;
}
@@ -1221,7 +1339,7 @@ export default {
.aps-sch-item-header-left {
display: flex;
align-items: center;
gap: 12px;
gap: 10px;
flex: 1;
min-width: 0;
}
@@ -1238,7 +1356,7 @@ export default {
.aps-status-tag {
display: inline-block;
font-size: 11px;
padding: 2px 8px;
padding: 2px 6px;
border-radius: 3px;
font-weight: 500;
white-space: nowrap;
@@ -1254,15 +1372,17 @@ export default {
width: 100%;
border-collapse: collapse;
font-size: 12px;
table-layout: fixed;
td {
padding: 5px 10px;
padding: 3px 6px;
border: 1px solid $aps-silver-mid;
vertical-align: middle;
word-break: break-word;
}
.req-td-label {
width: 100px;
width: 80px;
background: $aps-silver-1;
color: $aps-text-muted;
font-weight: 500;
@@ -1272,6 +1392,15 @@ export default {
.req-td-value {
color: $aps-text;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.req-td-value[colspan] {
overflow: visible;
text-overflow: clip;
white-space: normal;
}
}
@@ -1283,9 +1412,9 @@ export default {
.aps-sch-item-actions {
display: flex;
gap: 6px;
gap: 4px;
flex-shrink: 0;
margin-left: 12px;
margin-left: 8px;
}
// 明细表
@@ -1298,7 +1427,7 @@ export default {
padding: 7px 14px;
background: $aps-silver-1;
border-bottom: 1px solid $aps-border;
font-size: 12px;
font-size: 14px;
font-weight: 600;
color: $aps-text;
}
@@ -1307,7 +1436,7 @@ export default {
display: flex;
padding: 7px 14px;
border-bottom: 1px solid $aps-silver-mid;
font-size: 12px;
font-size: 14px;
color: $aps-text;
cursor: pointer;
transition: background 0.15s;
@@ -1330,7 +1459,7 @@ export default {
}
.aps-sch-item-empty {
padding: 20px;
padding: 14px;
text-align: center;
color: $aps-text-muted;
font-size: 12px;
@@ -1370,6 +1499,12 @@ export default {
border-bottom: 1px solid $aps-border;
}
.aps-step-tabs-right {
margin-left: auto;
display: flex;
align-items: center;
}
.aps-step-tab {
display: inline-flex;
align-items: center;
@@ -1417,4 +1552,135 @@ export default {
background: rgba(255, 255, 255, 0.25);
}
}
.aps-scheduled-cards {
padding: 10px 10px 12px;
}
.aps-scheduled-card {
background: $aps-white;
border: 1px solid $aps-border;
border-radius: $aps-radius;
box-shadow: $aps-shadow-sm;
overflow: hidden;
}
.aps-scheduled-card + .aps-scheduled-card {
margin-top: 10px;
}
.aps-scheduled-card-header {
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
padding: 8px 12px;
background: linear-gradient(135deg, $aps-silver-1 0%, #f8f9fb 100%);
border-bottom: 1px solid $aps-border;
}
.aps-scheduled-card-title {
display: flex;
align-items: center;
gap: 10px;
min-width: 0;
flex: 1;
}
.aps-drag-handle {
cursor: grab;
color: $aps-text-muted;
font-size: 16px;
flex: 0 0 auto;
}
.aps-scheduled-no {
color: $aps-red-2;
font-weight: 600;
font-size: 13px;
white-space: nowrap;
}
.aps-scheduled-step {
color: $aps-text-muted;
font-size: 12px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.aps-scheduled-card-actions {
display: flex;
align-items: center;
gap: 4px;
flex: 0 0 auto;
}
.aps-scheduled-card-body {
padding: 10px 12px 12px;
}
.aps-scheduled-kv {
display: grid;
grid-template-columns: repeat(4, minmax(0, 1fr));
gap: 8px 12px;
}
.kv-item {
min-width: 0;
display: flex;
align-items: baseline;
gap: 8px;
}
.kv-label {
flex: 0 0 auto;
color: $aps-text-muted;
font-size: 12px;
white-space: nowrap;
}
.kv-value {
color: $aps-text;
font-size: 12px;
font-weight: 500;
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.kv-value-wrap {
white-space: normal;
overflow: visible;
text-overflow: clip;
}
.kv-span-2 {
grid-column: span 2;
}
.kv-span-4 {
grid-column: 1 / -1;
}
.aps-drag-ghost {
opacity: 0.6;
}
@media (max-width: 1366px) {
.aps-scheduled-kv {
grid-template-columns: repeat(3, minmax(0, 1fr));
}
}
@media (max-width: 1024px) {
.aps-scheduled-kv {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
.kv-span-2 {
grid-column: span 2;
}
}
</style>

View File

@@ -0,0 +1,3 @@
ALTER TABLE sch_prod_schedule_item
ADD COLUMN sort_no INT NOT NULL DEFAULT 999999 AFTER action_id;