``1123
This commit is contained in:
parent
c9468784b0
commit
8505056616
@ -24,6 +24,17 @@ export function updateFBl(data) {
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 获取BOM上传状态
|
||||
export function viewGetBomUploadStatus(rooteProdet) {
|
||||
return request({
|
||||
url: '/system/details/viewGetBomUploadStatus',
|
||||
method: 'post',
|
||||
params: {
|
||||
rooteProdet: rooteProdet
|
||||
}
|
||||
})
|
||||
}
|
||||
// 获取项目令号列表
|
||||
export function getProjectCodes(query) {
|
||||
return request({
|
||||
|
||||
@ -98,11 +98,11 @@ export function pushRouteBom(rooteProdet) {
|
||||
params: { rooteProdet },
|
||||
});
|
||||
}
|
||||
export function updateProcessPlan(rooteProdet) {
|
||||
export function updateProcessPlan(rooteProdet, ids) {
|
||||
return request({
|
||||
url: '/system/route/updateProcessPlan',
|
||||
method: 'post',
|
||||
params: { rooteProdet },
|
||||
params: { rooteProdet, ids },
|
||||
});
|
||||
|
||||
}export function updateProcesTime(rooteProdet) {
|
||||
|
||||
@ -8,7 +8,7 @@ import { isRelogin } from '@/utils/request'
|
||||
|
||||
NProgress.configure({ showSpinner: false })
|
||||
|
||||
const whiteList = ['/login', '/register', '/index','/indexDaping','/mrp2']
|
||||
const whiteList = ['/login', '/register', '/index', '/indexDaping', '/mrp2', '/system/cost']
|
||||
|
||||
router.beforeEach((to, from, next) => {
|
||||
NProgress.start()
|
||||
|
||||
@ -132,6 +132,13 @@ export const constantRoutes = [
|
||||
name: 'Mrp2Public',
|
||||
hidden: true,
|
||||
meta: { title: 'MRP2运算结果' }
|
||||
},
|
||||
{
|
||||
path: '/system/cost',
|
||||
component: () => import('@/views/system/cost/index'),
|
||||
name: 'CostPublic',
|
||||
hidden: true,
|
||||
meta: { title: '零件成本查询' }
|
||||
}
|
||||
// {
|
||||
// path: '/',
|
||||
|
||||
@ -140,6 +140,18 @@
|
||||
>更新物料清单
|
||||
</el-button>
|
||||
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="primary"
|
||||
plain
|
||||
icon="el-icon-view"
|
||||
size="mini"
|
||||
@click="getBomUploadStatus"
|
||||
v-hasPermi="['system:details:viewGetBomUploadStatus']"
|
||||
>查看BOM上传状态
|
||||
</el-button>
|
||||
|
||||
</el-col>
|
||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
@ -297,7 +309,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {listDetails, getDetails, delDetails, addDetails, updateDetails, updateFBl} from "@/api/system/details";
|
||||
import {listDetails, getDetails, delDetails, addDetails, updateDetails, updateFBl, viewGetBomUploadStatus} from "@/api/system/details";
|
||||
import upload from "svg-sprite-loader/examples/custom-runtime-generator/build/main";
|
||||
import {getToken} from "@/utils/auth";
|
||||
import axios from "axios";
|
||||
@ -490,8 +502,123 @@ export default {
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
/** 弹窗 **/
|
||||
resNotice(successCount) {
|
||||
/** 查看BOM上传状态 */
|
||||
getBomUploadStatus() {
|
||||
this.loading = true;
|
||||
this.reset();
|
||||
|
||||
// 检查是否有选中行
|
||||
if (!this.ids || this.ids.length === 0) {
|
||||
this.$modal.msgError("请先选择要查询的行!");
|
||||
this.loading = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// 获取第一个选中行的生产令号
|
||||
const firstSelectedItem = this.detailsList.find(row => row.id === this.ids[0]);
|
||||
if (!firstSelectedItem) {
|
||||
this.$modal.msgError("未找到选中的数据项!");
|
||||
this.loading = false;
|
||||
return;
|
||||
}
|
||||
|
||||
const rooteProdet = firstSelectedItem.totalWeight;
|
||||
console.log('选中的行ID:', this.ids);
|
||||
console.log('提取的生产令号:', rooteProdet);
|
||||
|
||||
if (!rooteProdet) {
|
||||
this.$modal.msgError("未获取到生产令号,请检查选中行的数据!");
|
||||
this.loading = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// 调用获取BOM上传状态接口
|
||||
viewGetBomUploadStatus(rooteProdet).then(response => {
|
||||
// 处理后端返回的BOM上传状态数据
|
||||
const bomData = response.data;
|
||||
if (bomData && bomData.items) {
|
||||
// 显示BOM上传状态结果
|
||||
this.showBomUploadStatus(bomData.items);
|
||||
} else {
|
||||
this.$modal.msgWarning("未获取到BOM上传状态数据");
|
||||
}
|
||||
}).catch(error => {
|
||||
console.error('获取BOM上传状态失败:', error);
|
||||
this.$modal.msgError("获取BOM上传状态失败,请重试!");
|
||||
}).finally(() => {
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
/** 显示BOM上传状态 **/
|
||||
showBomUploadStatus(items) {
|
||||
if (!items || items.length === 0) {
|
||||
this.$modal.msgWarning("暂无BOM上传状态数据");
|
||||
return;
|
||||
}
|
||||
|
||||
// 统计各状态数量
|
||||
const successCount = items.filter(item => item.code === '200').length; // 成功上传
|
||||
const existCount = items.filter(item => item.code === '100').length; // 已存在且一致
|
||||
const failedCount = items.filter(item => item.code === '300').length; // 上传失败
|
||||
const totalCount = items.length;
|
||||
|
||||
// 构建显示内容
|
||||
let content = `
|
||||
<div style="margin-bottom: 15px; padding: 10px; background-color: #f5f7fa; border-radius: 4px;">
|
||||
<div><strong>项目编码:</strong> ${items[0]?.projectCode || '未知'}</div>
|
||||
<div><strong>总计:</strong> ${totalCount} 条</div>
|
||||
<div><strong>成功上传:</strong> <span style="color: green;">${successCount}</span> 条</div>
|
||||
<div><strong>已存在:</strong> <span style="color: blue;">${existCount}</span> 条</div>
|
||||
<div><strong>上传失败:</strong> <span style="color: red;">${failedCount}</span> 条</div>
|
||||
</div>
|
||||
<div style="max-height: 400px; overflow-y: auto;">
|
||||
`;
|
||||
|
||||
items.forEach((item, index) => {
|
||||
let statusColor, statusText, backgroundColor;
|
||||
|
||||
switch(item.code) {
|
||||
case '100':
|
||||
statusColor = 'blue';
|
||||
statusText = '已存在';
|
||||
backgroundColor = '#f0f8ff';
|
||||
break;
|
||||
case '200':
|
||||
statusColor = 'green';
|
||||
statusText = '成功上传';
|
||||
backgroundColor = '#f0f9ff';
|
||||
break;
|
||||
case '300':
|
||||
statusColor = 'red';
|
||||
statusText = '上传失败';
|
||||
backgroundColor = '#fef2f2';
|
||||
break;
|
||||
default:
|
||||
statusColor = 'gray';
|
||||
statusText = '未知状态';
|
||||
backgroundColor = '#f5f5f5';
|
||||
}
|
||||
|
||||
content += `
|
||||
<div style="margin-bottom: 10px; padding: 8px; border: 1px solid #e4e7ed; border-radius: 4px; background-color: ${backgroundColor};">
|
||||
<div><strong>序号:</strong> ${index + 1}</div>
|
||||
<div><strong>物料编码:</strong> ${item.materialCode || '无'}</div>
|
||||
<div><strong>状态码:</strong> <span style="color: ${statusColor}; font-weight: bold;">${item.code}</span></div>
|
||||
<div><strong>上传状态:</strong> <span style="color: ${statusColor}; font-weight: bold;">${statusText}</span></div>
|
||||
<div><strong>说明:</strong> ${item.reason || '无'}</div>
|
||||
</div>
|
||||
`;
|
||||
});
|
||||
content += '</div>';
|
||||
|
||||
this.$alert(content, 'BOM上传状态', {
|
||||
dangerouslyUseHTMLString: true,
|
||||
confirmButtonText: '确定',
|
||||
customClass: 'bom-upload-status-dialog'
|
||||
});
|
||||
},
|
||||
/** 弹窗 **/
|
||||
resNotice(successCount) {
|
||||
this.$alert(`成功上传的条数:${successCount}`, '成功信息', {
|
||||
confirmButtonText: '确定',
|
||||
callback: action => {
|
||||
|
||||
110
src/views/system/productionPlan/components/GanttChart.vue
Normal file
110
src/views/system/productionPlan/components/GanttChart.vue
Normal file
@ -0,0 +1,110 @@
|
||||
<template>
|
||||
<div class="gantt-container">
|
||||
<div ref="gantt" class="gantt-chart"></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { gantt } from "dhtmlx-gantt";
|
||||
import "dhtmlx-gantt/codebase/dhtmlxgantt.css";
|
||||
|
||||
export default {
|
||||
name: "GanttChart",
|
||||
props: {
|
||||
tasks: {
|
||||
type: Object,
|
||||
default: () => ({
|
||||
data: []
|
||||
})
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.initGantt();
|
||||
},
|
||||
beforeDestroy() {
|
||||
if (gantt.$_initialized) {
|
||||
gantt.destructor();
|
||||
gantt.$_initialized = false;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
initGantt() {
|
||||
// 初始化甘特图
|
||||
gantt.init(this.$refs.gantt);
|
||||
|
||||
// 配置甘特图
|
||||
gantt.config.scale_unit = "day";
|
||||
gantt.config.date_scale = "%d %M";
|
||||
gantt.config.subscales = [
|
||||
{ unit: "hour", step: 6, date: "%H:%i" }
|
||||
];
|
||||
|
||||
gantt.config.columns = [
|
||||
{
|
||||
name: 'text',
|
||||
label: '生产令号',
|
||||
tree: true,
|
||||
width: 300, // 增大宽度
|
||||
align: "left",
|
||||
editor: {type: 'text', map_to: 'text'},
|
||||
onrender: function (task, node) {
|
||||
node.setAttribute("class", "gantt_cell gantt_last_cell gantt_cell_tree " + task.status);
|
||||
}
|
||||
},
|
||||
{name: "start_date", label: "开始时间", width: 100, resize: true, align: "left"}, // 增大宽度
|
||||
{name: "duration", label: "天数", width: 80, resize: true, align: "center"}, // 增大宽度
|
||||
{name: 'end_date', label: '完成时间', width: 90, resize: true, align: "left"}, // 增大宽度
|
||||
];
|
||||
|
||||
gantt.config.drag_progress = true;
|
||||
|
||||
// 启用任务拖拽
|
||||
gantt.config.drag_move = true;
|
||||
gantt.config.drag_resize = true;
|
||||
|
||||
// 自定义拖拽外观
|
||||
gantt.config.drag_lightbox = true;
|
||||
|
||||
// 任务更新时触发事件
|
||||
gantt.attachEvent("onTaskChanged", (id, task) => {
|
||||
this.$emit("task-updated", id, task);
|
||||
return true;
|
||||
});
|
||||
|
||||
// 任务拖拽结束时触发事件
|
||||
gantt.attachEvent("onAfterTaskDrag", (id, mode, e) => {
|
||||
this.$emit("task-dragged", id, mode, e);
|
||||
return true;
|
||||
});
|
||||
|
||||
console.log(this.tasks)
|
||||
|
||||
// 加载数据
|
||||
gantt.parse(this.tasks);
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
tasks: {
|
||||
deep: true,
|
||||
handler(newValue) {
|
||||
if (gantt.$_initialized) {
|
||||
gantt.clearAll();
|
||||
gantt.parse(newValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.gantt-container {
|
||||
width: 100%;
|
||||
height: 600px;
|
||||
}
|
||||
|
||||
.gantt-chart {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
784
src/views/system/productionPlan/index1.vue
Normal file
784
src/views/system/productionPlan/index1.vue
Normal file
@ -0,0 +1,784 @@
|
||||
<template>
|
||||
<div class="container">
|
||||
<div ref="gantt" class="gantt-container"></div>
|
||||
<div class="search-wrap">
|
||||
<div class="select-process">
|
||||
<span>选择工序:</span>
|
||||
<el-select v-model="value" placeholder="请选择" @change="selectChange">
|
||||
<el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</div>
|
||||
|
||||
<div class="search-item">
|
||||
<span>工作中心:</span>
|
||||
<el-select v-model="searchParams.workCenter" placeholder="请选择工作中心" @change="search">
|
||||
<el-option v-for="item in workCenterOptions" :key="item.value" :label="item.label" :value="item.value">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</div>
|
||||
|
||||
<div class="title">在产主要项目进度分析</div>
|
||||
</div>
|
||||
<div ref="gantt" class="gantt-container"></div>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
<script>
|
||||
import {gantt} from 'dhtmlx-gantt';
|
||||
import "dhtmlx-gantt/codebase/dhtmlxgantt.css";
|
||||
import 'font-awesome/css/font-awesome.min.css';
|
||||
import {listProcedure1, listProcedureGX} from "@/api/system/procedure";
|
||||
|
||||
export default {
|
||||
name: 'index1',
|
||||
data() {
|
||||
return {
|
||||
tasks: {
|
||||
data: []
|
||||
},
|
||||
options: [{
|
||||
value: '1',
|
||||
label: '下 料'
|
||||
}, {
|
||||
value: '2',
|
||||
label: '铆 焊'
|
||||
}, {
|
||||
value: '3',
|
||||
label: '热 处 理'
|
||||
}, {
|
||||
value: '4',
|
||||
label: '普车钻床'
|
||||
}, {
|
||||
value: '5',
|
||||
label: '走心 机'
|
||||
}, {
|
||||
value: '6',
|
||||
label: '龙门立加'
|
||||
}, {
|
||||
value: '7',
|
||||
label: '表面处理'
|
||||
}, {
|
||||
value: '8',
|
||||
label: '外购 件'
|
||||
}],
|
||||
value: '1',
|
||||
searchParams: {
|
||||
workCenter: ''
|
||||
},
|
||||
workCenterOptions: [
|
||||
{
|
||||
value: '车间1',
|
||||
label: '车间1'
|
||||
},
|
||||
{
|
||||
value: '车间2',
|
||||
label: '车间2'
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
created() {
|
||||
|
||||
},
|
||||
methods: {
|
||||
|
||||
//开始时间-结束时间参数
|
||||
DateDifference: function (strDateStart, strDateEnd) {
|
||||
var begintime_ms = Date.parse(new Date(strDateStart.replace(/-/g, '/'))) //begintime 为开始时间
|
||||
var endtime_ms = Date.parse(new Date(strDateEnd.replace(/-/g, '/'))) // endtime 为结束时间
|
||||
var date3 = endtime_ms - begintime_ms //时间差的毫秒数
|
||||
var days = Math.floor(date3 / (24 * 3600 * 1000))
|
||||
return days
|
||||
},
|
||||
initData: function () {
|
||||
this.loading = true;
|
||||
listProcedure1().then(response => {
|
||||
if (response && Array.isArray(response)) {
|
||||
this.loading = false;
|
||||
response.forEach(item => {
|
||||
item.day = item.duration
|
||||
if (!item.hasOwnProperty('progess')) {
|
||||
item.progess = 0
|
||||
}
|
||||
});
|
||||
|
||||
// 处理多级菜单数据
|
||||
// 当前结构:项目(父任务) -> 工序(子任务)
|
||||
// 建议结构:项目 -> 物料编码 -> 工序
|
||||
this.tasks.data = response.map(function (current, ind, arry) {
|
||||
var newObj = {}
|
||||
if (current.type) { //存在type字段 说明非一级菜单,判断阶段的具体类型 设置不同颜色
|
||||
if (current.type === 1) { //冒烟
|
||||
newObj = Object.assign({}, current, {
|
||||
'color': '#35a6e2'
|
||||
})
|
||||
} else if (current.type === 2) { //单元
|
||||
newObj = Object.assign({}, current, {
|
||||
'color': '#e5a087'
|
||||
})
|
||||
} else if (current.type === 3) { //回归
|
||||
newObj = Object.assign({}, current, {
|
||||
'color': '#62ddd4'
|
||||
})
|
||||
} else if (current.type === 4) {
|
||||
|
||||
newObj = Object.assign({}, current, {
|
||||
'color': '#d1a6ff'
|
||||
})
|
||||
} else if (current.type === 5) {
|
||||
|
||||
newObj = Object.assign({}, current, {
|
||||
'color': '#890864'
|
||||
})
|
||||
} else if (current.type === 6) {
|
||||
|
||||
newObj = Object.assign({}, current, {
|
||||
'color': '#b64e58'
|
||||
})
|
||||
} else if (current.type === 7) {
|
||||
|
||||
newObj = Object.assign({}, current, {
|
||||
'color': '#19842a'
|
||||
})
|
||||
} else if (current.type === 8) {
|
||||
|
||||
newObj = Object.assign({}, current, {
|
||||
'color': '#529578'
|
||||
})
|
||||
} else if (current.type === 9) {
|
||||
|
||||
newObj = Object.assign({}, current, {
|
||||
'color': '#e6a33d'
|
||||
})
|
||||
}
|
||||
} else { //一级菜单是蓝色的
|
||||
newObj = Object.assign({}, current, {
|
||||
'color': '#5692f0'
|
||||
})
|
||||
}
|
||||
return newObj
|
||||
})
|
||||
// this.initData(); // 调用初始化甘特图数据的方法
|
||||
// 数据解析
|
||||
gantt.parse(this.tasks)
|
||||
this.loading = false;
|
||||
} else {
|
||||
console.error('Invalid response data:', response);
|
||||
}
|
||||
}).catch(error => {
|
||||
console.error('Error fetching tasks:', error);
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
|
||||
selectChange(val) {
|
||||
console.log(val)
|
||||
this.loading = true;
|
||||
//将options.值传给后端
|
||||
const selectedOption = this.options.find(option => option.value===val)
|
||||
const text = selectedOption ? selectedOption.label : '';
|
||||
listProcedureGX({text: text}).then(response => {
|
||||
// 在这里处理返回的响应数据
|
||||
if (response && Array.isArray(response)) {
|
||||
this.loading = false;
|
||||
response.forEach(item => {
|
||||
item.day = item.duration
|
||||
if (!item.hasOwnProperty('progess')) {
|
||||
item.progess = 0
|
||||
}
|
||||
});
|
||||
|
||||
this.tasks.data = response.map(function (current, ind, arry) {
|
||||
var newObj = {}
|
||||
if (current.type) { //存在type字段 说明非一级菜单,判断阶段的具体类型 设置不同颜色
|
||||
console.log(333333,current)
|
||||
if (current.type === 1) { //冒烟
|
||||
newObj = Object.assign({}, current, {
|
||||
'color': '#35a6e2'
|
||||
})
|
||||
} else if (current.type === 2) { //单元
|
||||
newObj = Object.assign({}, current, {
|
||||
'color': '#e5a087'
|
||||
})
|
||||
} else if (current.type === 3) { //回归
|
||||
newObj = Object.assign({}, current, {
|
||||
'color': '#62ddd4'
|
||||
})
|
||||
} else if (current.type === 4) {
|
||||
|
||||
newObj = Object.assign({}, current, {
|
||||
'color': '#d1a6ff'
|
||||
})
|
||||
} else if (current.type === 5) {
|
||||
|
||||
newObj = Object.assign({}, current, {
|
||||
'color': '#890864'
|
||||
})
|
||||
} else if (current.type === 6) {
|
||||
|
||||
newObj = Object.assign({}, current, {
|
||||
'color': '#b64e58'
|
||||
})
|
||||
} else if (current.type === 7) {
|
||||
|
||||
newObj = Object.assign({}, current, {
|
||||
'color': '#19842a'
|
||||
})
|
||||
} else if (current.type === 8) {
|
||||
|
||||
newObj = Object.assign({}, current, {
|
||||
'color': '#529578'
|
||||
})
|
||||
} else if (current.type === 9) {
|
||||
|
||||
newObj = Object.assign({}, current, {
|
||||
'color': '#e6a33d'
|
||||
})
|
||||
}
|
||||
} else { //一级菜单是蓝色的
|
||||
newObj = Object.assign({}, current, {
|
||||
'color': '#5692f0'
|
||||
})
|
||||
}
|
||||
return newObj
|
||||
})
|
||||
|
||||
|
||||
//this.initData(); // 调用初始化甘特图数据的方法
|
||||
gantt.clearAll()
|
||||
// 数据解析
|
||||
gantt.parse(this.tasks)
|
||||
this.loading = false;
|
||||
} else {
|
||||
console.error('Invalid response data:', response);
|
||||
}
|
||||
}).catch(error => {
|
||||
console.error('Error fetching tasks:', error);
|
||||
this.loading = false;
|
||||
})
|
||||
},
|
||||
|
||||
search() {
|
||||
// 构建查询参数
|
||||
const params = {
|
||||
...this.searchParams,
|
||||
text: this.options.find(option => option.value === this.value).label
|
||||
};
|
||||
|
||||
// 调用后端API进行查询
|
||||
listProcedureGX(params).then(response => {
|
||||
// 处理返回的数据
|
||||
if (response && Array.isArray(response)) {
|
||||
// ...
|
||||
// 这里的数据处理逻辑和selectChange方法中的类似
|
||||
// ...
|
||||
gantt.clearAll();
|
||||
gantt.parse(this.tasks);
|
||||
} else {
|
||||
console.error('Invalid response data:', response);
|
||||
}
|
||||
}).catch(error => {
|
||||
console.error('Error fetching tasks:', error);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
mounted() {
|
||||
this.initData()
|
||||
|
||||
gantt.config.autofit = true;
|
||||
gantt.config.autosize = true;
|
||||
//自适应甘特图的尺寸大小, 使得在不出现滚动条的情况下, 显示全部任务
|
||||
gantt.config.autosize = true;
|
||||
//只读模式
|
||||
gantt.config.readonly = false;
|
||||
//是否显示左侧树表格
|
||||
gantt.config.show_grid = true;
|
||||
|
||||
// 启用任务拖拽
|
||||
gantt.config.drag_move = true;
|
||||
gantt.config.drag_resize = true;
|
||||
|
||||
// 自定义拖拽外观
|
||||
gantt.config.drag_lightbox = true;
|
||||
|
||||
// 任务更新时触发事件
|
||||
gantt.attachEvent("onTaskChanged", (id, task) => {
|
||||
console.log("任务更新:", id, task);
|
||||
const index = this.ganttData.data.findIndex(item => item.id === id);
|
||||
if (index !== -1) {
|
||||
this.$set(this.ganttData.data, index, { ...this.ganttData.data[index], ...task });
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
// 任务拖拽结束时触发事件
|
||||
gantt.attachEvent("onAfterTaskDrag", (id, mode, e) => {
|
||||
console.log("任务拖拽完成:", id, mode, e);
|
||||
return true;
|
||||
});
|
||||
|
||||
gantt.config.columns = [
|
||||
{
|
||||
name: 'text',
|
||||
label: '生产令号',
|
||||
tree: true,
|
||||
width: 300, // 增大宽度
|
||||
align: "left",
|
||||
editor: {type: 'text', map_to: 'text'},
|
||||
onrender: function (task, node) {
|
||||
node.setAttribute("class", "gantt_cell gantt_last_cell gantt_cell_tree " + task.status);
|
||||
}
|
||||
},
|
||||
{name: "start_date", label: "开始时间", width: 100, resize: true, align: "left"}, // 增大宽度
|
||||
{name: "duration", label: "天数", width: 80, resize: true, align: "center"}, // 增大宽度
|
||||
{name: 'end_date', label: '完成时间', width: 90, resize: true, align: "left"}, // 增大宽度
|
||||
]
|
||||
|
||||
|
||||
var weekScaleTemplate = function (date) {
|
||||
var dateToStr = gantt.date.date_to_str("%m %d");
|
||||
var endDate = gantt.date.add(gantt.date.add(date, 1, "week"), -1, "day");
|
||||
var weekNum = gantt.date.date_to_str("第 %W 周");
|
||||
return weekNum(date)
|
||||
};
|
||||
var daysStyle = function (date) {
|
||||
var dateToStr = gantt.date.date_to_str("%D");
|
||||
if (dateToStr(date) === "六" || dateToStr(date) === "日") return "weekend";
|
||||
return "";
|
||||
};
|
||||
gantt.config.subscales = [{
|
||||
unit: "week",
|
||||
step: 1,
|
||||
template: weekScaleTemplate
|
||||
},
|
||||
{
|
||||
unit: "day",
|
||||
step: 1,
|
||||
format: "%d",
|
||||
template: daysStyle
|
||||
}
|
||||
];
|
||||
// 今日标线需要用到插件marker
|
||||
// gantt需要用到的插件
|
||||
gantt.plugins({
|
||||
marker: true,
|
||||
fullscreen: true
|
||||
});
|
||||
let today = new Date();
|
||||
gantt.addMarker({
|
||||
start_date: today,
|
||||
css: 'today',
|
||||
text: '',
|
||||
});
|
||||
gantt.plugins({
|
||||
tooltip: true
|
||||
});
|
||||
gantt.attachEvent("onGanttReady", function () {
|
||||
var tooltips = gantt.text.tooltips;
|
||||
gantt.templates.tooltip_text = function (start, end, task) {
|
||||
|
||||
return task.toolTipsTxt + "<br/>" +
|
||||
"阶段:" + task.text + "<br/>" +
|
||||
"时长:" + task.duration + "天" + "<br/>" +
|
||||
gantt.templates.tooltip_date_format(start)
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
//设置任务条进度内容
|
||||
gantt.templates.progress_text = function (start, end, task) {
|
||||
return "<div style='text-align:left;color:#fff;padding-left:20px'>" + Math.round(task.progress * 100) +
|
||||
"% </div>";
|
||||
};
|
||||
|
||||
//任务条显示内容
|
||||
gantt.templates.task_text = function (start, end, task) {
|
||||
// return task.text + '(' + task.duration + '天)';
|
||||
return "<div style='text-align:center;color:#fff'>" + task.text + '(' + task.day + '天)' +
|
||||
"</div>";
|
||||
}
|
||||
|
||||
|
||||
// gantt.templates.scale_cell_class = function(date) {
|
||||
// /*if(date.getDay()== 0 || date.getDay()== 6){
|
||||
// return "weekend";
|
||||
// }*/
|
||||
// return 'weekend'
|
||||
// }
|
||||
|
||||
|
||||
//任务栏周末亮色
|
||||
gantt.templates.timeline_cell_class = function (item, date) {
|
||||
if (date.getDay() === 0 || date.getDay() === 6) {
|
||||
return "weekend";
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//任务条上的文字大小 以及取消border自带样式
|
||||
gantt.templates.task_class = function (start, end, item) {
|
||||
return item.$level === 0 ? 'firstLevelTask' : 'secondLevelTask'
|
||||
}
|
||||
|
||||
//甘特图图表宽度自适应
|
||||
gantt.config.autofit = true;
|
||||
gantt.config.layout = {
|
||||
css: "gantt_container",
|
||||
cols: [{
|
||||
width: 560,
|
||||
min_width: 200,
|
||||
rows: [{
|
||||
view: "grid",
|
||||
scrollX: "gridScroll",
|
||||
scrollable: true,
|
||||
scrollY: "scrollVer"
|
||||
},
|
||||
{
|
||||
view: "scrollbar",
|
||||
id: "gridScroll",
|
||||
group: "horizontal"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
resizer: true,
|
||||
width: 1
|
||||
},
|
||||
{
|
||||
rows: [{
|
||||
view: "timeline",
|
||||
scrollX: "scrollHor",
|
||||
scrollY: "scrollVer"
|
||||
},
|
||||
{
|
||||
view: "scrollbar",
|
||||
id: "scrollHor",
|
||||
group: "horizontal"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
view: "scrollbar",
|
||||
id: "scrollVer"
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
//时间轴图表中,任务条形图的高度
|
||||
gantt.config.task_height = 28
|
||||
//时间轴图表中,甘特图的高度
|
||||
gantt.config.row_height = 36
|
||||
//时间轴图表中,如果不设置,只有行边框,区分上下的任务,设置之后带有列的边框,整个时间轴变成格子状。
|
||||
gantt.config.show_task_cells = true
|
||||
//当task的长度改变时,自动调整图表坐标轴区间用于适配task的长度
|
||||
gantt.config.fit_tasks = true
|
||||
gantt.config.min_column_width = 50;
|
||||
gantt.config.auto_types = true;
|
||||
gantt.config.date_format = "%Y-%m-%d";
|
||||
gantt.config.scale_unit = "month";
|
||||
gantt.config.step = 1;
|
||||
gantt.config.date_scale = "%Y年%M";
|
||||
gantt.config.start_on_monday = true;
|
||||
gantt.config.scale_height = 90;
|
||||
gantt.config.autoscroll = true;
|
||||
gantt.config.calendar_property = "start_date";
|
||||
gantt.config.calendar_property = "end_date";
|
||||
gantt.config.readonly = true;
|
||||
gantt.config.drag_links = true;
|
||||
gantt.config.drag_tasks = true;
|
||||
gantt.config.wide_form = true;
|
||||
gantt.i18n.setLocale('cn');
|
||||
|
||||
// 初始化
|
||||
gantt.init(this.$refs.gantt)
|
||||
// 数据解析
|
||||
gantt.parse(this.tasks)
|
||||
gantt.render()
|
||||
gantt.refreshData()
|
||||
gantt.locale = {
|
||||
date: {
|
||||
month_full: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"],
|
||||
month_short: ["1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月"],
|
||||
day_full: ["星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"],
|
||||
day_short: ["日", "一", "二", "三", "四", "五", "六"]
|
||||
},
|
||||
labels: {
|
||||
dhx_cal_today_button: "今天",
|
||||
day_tab: "日",
|
||||
week_tab: "周",
|
||||
month_tab: "月",
|
||||
new_event: "新建日程",
|
||||
icon_save: "保存",
|
||||
icon_cancel: "关闭",
|
||||
icon_details: "详细",
|
||||
icon_edit: "编辑",
|
||||
icon_delete: "删除",
|
||||
confirm_closing: "请确认是否撤销修改!",
|
||||
confirm_deleting: "是否删除计划?",
|
||||
section_description: "描述:",
|
||||
section_time: "时间范围:",
|
||||
section_type: "类型:",
|
||||
section_text: "计划名称:",
|
||||
section_test: "测试:",
|
||||
section_projectClass: "项目类型:",
|
||||
taskProjectType_0: "项目任务",
|
||||
taskProjectType_1: "普通任务",
|
||||
section_head: "负责人:",
|
||||
section_priority: '优先级:',
|
||||
taskProgress: '任务状态',
|
||||
taskProgress_0: "未开始",
|
||||
taskProgress_1: "进行中",
|
||||
taskProgress_2: "已完成",
|
||||
taskProgress_3: "已延期",
|
||||
taskProgress_4: "搁置中",
|
||||
section_template: 'Details',
|
||||
/* grid columns */
|
||||
column_text: "计划名称",
|
||||
column_start_date: "开始时间",
|
||||
column_duration: "持续时间",
|
||||
column_add: "",
|
||||
column_priority: "难度",
|
||||
/* link confirmation */
|
||||
link: "关联",
|
||||
confirm_link_deleting: "将被删除",
|
||||
message_ok: '确定',
|
||||
message_cancel: '取消',
|
||||
link_start: " (开始)",
|
||||
link_end: " (结束)",
|
||||
|
||||
type_task: "任务",
|
||||
type_project: "项目",
|
||||
type_milestone: "里程碑",
|
||||
|
||||
minutes: "分钟",
|
||||
hours: "小时",
|
||||
days: "天",
|
||||
weeks: "周",
|
||||
months: "月",
|
||||
years: "年"
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
beforeDestroy() {
|
||||
if (gantt.$_initialized) {
|
||||
gantt.destructor();
|
||||
gantt.$_initialized = false;
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.firstLevelTask {
|
||||
border: none;
|
||||
|
||||
.gantt_task_content {
|
||||
font-size: 13px;
|
||||
}
|
||||
}
|
||||
|
||||
.secondLevelTask {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.thirdLevelTask {
|
||||
border: 2px solid #da645d;
|
||||
color: #da645d;
|
||||
background: #da645d;
|
||||
}
|
||||
|
||||
// 新增多级菜单样式
|
||||
.project-level {
|
||||
background: #5692f0;
|
||||
color: white;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.material-level {
|
||||
background: #35a6e2;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.process-level {
|
||||
background: #62ddd4;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.milestone-default {
|
||||
border: none;
|
||||
background: rgba(0, 0, 0, 0.45);
|
||||
}
|
||||
|
||||
.milestone-unfinished {
|
||||
border: none;
|
||||
background: #5692f0;
|
||||
}
|
||||
|
||||
.milestone-finished {
|
||||
border: none;
|
||||
background: #84bd54;
|
||||
}
|
||||
|
||||
.milestone-canceled {
|
||||
border: none;
|
||||
background: #da645d;
|
||||
}
|
||||
|
||||
html,
|
||||
body {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.container {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
position: relative;
|
||||
|
||||
.gantt_grid_head_cell {
|
||||
padding-left: 20px;
|
||||
text-align: left !important;
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.search-wrap{
|
||||
width: 100%;
|
||||
margin: 5px;
|
||||
padding: 15px;
|
||||
border: 0.5px solid #dad9d9;
|
||||
border-radius: 10px;
|
||||
display: flex;
|
||||
|
||||
.select-process{
|
||||
color: #a6aeb0;
|
||||
}
|
||||
|
||||
.title{
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
color: #4f9ec5;
|
||||
margin: auto;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
.select-wrap {
|
||||
position: absolute;
|
||||
top: 25px;
|
||||
z-index: 99;
|
||||
width: 90px;
|
||||
left: 180px;
|
||||
|
||||
.el-input__inner {
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
|
||||
.left-container {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.parent {
|
||||
.gantt_tree_icon {
|
||||
&.gantt_folder_open {
|
||||
background-image: url(assets/gantt-icon.svg) !important;
|
||||
}
|
||||
|
||||
&.gantt_folder_closed {
|
||||
background-image: url(assets/gantt-icon-up.svg) !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.green,
|
||||
.yellow,
|
||||
.pink,
|
||||
.popular {
|
||||
.gantt_tree_icon.gantt_file {
|
||||
background: none;
|
||||
position: relative;
|
||||
|
||||
&::before {
|
||||
content: "";
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
border-radius: 50%;
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.green {
|
||||
.gantt_tree_icon.gantt_file {
|
||||
&::before {
|
||||
background: #84bd54;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.yellow {
|
||||
.gantt_tree_icon.gantt_file {
|
||||
&::before {
|
||||
background: #fcca02;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.pink {
|
||||
.gantt_tree_icon.gantt_file {
|
||||
&::before {
|
||||
background: #da645d;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.popular {
|
||||
.gantt_tree_icon.gantt_file {
|
||||
&::before {
|
||||
background: #d1a6ff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.left-container {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.gantt_task_content {
|
||||
text-align: left;
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
.search-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
.search-item span {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.gantt-container {
|
||||
width: 100vw;
|
||||
min-width: 900px;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#app {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
@ -58,7 +58,7 @@
|
||||
</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button type="danger" plain icon="el-icon-edit" size="mini" @click="updateProcessPlan"
|
||||
<el-button type="danger" plain icon="el-icon-edit" size="mini" :disabled="multiple" @click="updateProcessPlan"
|
||||
v-hasPermi="['system:details:updateProcessPlan']">更新计划时间
|
||||
</el-button>
|
||||
</el-col>
|
||||
@ -1544,18 +1544,20 @@ export default {
|
||||
pushRouteBom(productionOrderNo),
|
||||
timeoutPromise
|
||||
]);
|
||||
// 处理后端返回的数据
|
||||
const {duplicateRoutes, failedRoutes, successfulRoutes} = response;
|
||||
// 提取物料编码
|
||||
// 处理后端返回的数据 - 适配新的返回结构 R<ProcessRoutePushResultDTO>
|
||||
const {duplicateRoutes, failedRoutes, successfulRoutes} = response.data;
|
||||
// 提取物料编码和错误信息
|
||||
const duplicateCodes = duplicateRoutes.join(', ');
|
||||
const failedCodes = failedRoutes.map(route => route.materialCode).join(', ');
|
||||
const failedInfo = failedRoutes.map(route =>
|
||||
`${route.materialCode} (${route.errorMessage || '未知错误'})`
|
||||
).join(', ');
|
||||
const successfulCodes = successfulRoutes.map(route => route.materialCode).join(', ');
|
||||
// 显示成功消息
|
||||
this.$alert(`
|
||||
<div><strong>成功 (${successfulRoutes.length}):</strong></div>
|
||||
<div style="margin-left: 20px;">${successfulCodes || '无'}</div>
|
||||
<div><strong>失败 (${failedRoutes.length}):</strong></div>
|
||||
<div style="margin-left: 20px;">${failedCodes || '无'}</div>
|
||||
<div style="margin-left: 20px;">${failedInfo || '无'}</div>
|
||||
<div><strong>重复 (${duplicateRoutes.length}):</strong></div>
|
||||
<div style="margin-left: 20px;">${duplicateCodes || '无'}</div>
|
||||
`, '推送完成', {
|
||||
@ -1592,16 +1594,24 @@ export default {
|
||||
},
|
||||
/** 更新计划时间间*/
|
||||
updateProcessPlan(row) {
|
||||
// 若未勾选任何行,则提示并返回
|
||||
if (!this.ids || this.ids.length === 0) {
|
||||
this.$modal.msgError("请先勾选至少一条数据再更新计划时间");
|
||||
return;
|
||||
}
|
||||
// 显示加载状态
|
||||
this.loading = true;
|
||||
// 调用 reset 方法,重置表单或状态
|
||||
this.reset();
|
||||
// 获取生产订单号
|
||||
const rooteProdet = this.params.productionOrderNo;
|
||||
//获取物料编码
|
||||
const materialCode = this.params.materialCode;
|
||||
|
||||
console.log(rooteProdet);
|
||||
|
||||
// 调用封装好的 API 方法
|
||||
updateProcessPlan(rooteProdet)
|
||||
// 调用封装好的 API 方法(带勾选的 ids)
|
||||
updateProcessPlan(rooteProdet, this.ids)
|
||||
.then(response => {
|
||||
// 假设后端返回的数据可以直接赋值给表单
|
||||
this.form = response;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user