Browse Source

事业部进度展示设置

master
han\hanst 1 day ago
parent
commit
11029b01f7
  1. 2
      src/api/sampleTracking/sampleTracking.js
  2. 344
      src/views/modules/sampleTracking/projectProofTracking.vue

2
src/api/sampleTracking/sampleTracking.js

@ -23,3 +23,5 @@ export const updateProofTrackingComments = data => createAPI('/sampleTracking/pr
export const finishProofTracking = data => createAPI('/sampleTracking/proofTracking/finishProofing', 'POST', data) export const finishProofTracking = data => createAPI('/sampleTracking/proofTracking/finishProofing', 'POST', data)
export const deleteProofTracking = data => createAPI('/sampleTracking/proofTracking/delete', 'POST', data) export const deleteProofTracking = data => createAPI('/sampleTracking/proofTracking/delete', 'POST', data)
export const queryProofTrackingProcessHistory = data => createAPI('/sampleTracking/proofTracking/processHistory', 'POST', data) export const queryProofTrackingProcessHistory = data => createAPI('/sampleTracking/proofTracking/processHistory', 'POST', data)
export const queryProofTrackingBuProcessConfig = data => createAPI('/sampleTracking/proofTracking/buProcessConfig/list', 'POST', data)
export const saveProofTrackingBuProcessConfig = data => createAPI('/sampleTracking/proofTracking/buProcessConfig/save', 'POST', data)

344
src/views/modules/sampleTracking/projectProofTracking.vue

@ -1,6 +1,16 @@
<template> <template>
<div class="mod-config"> <div class="mod-config">
<el-form :inline="true" :model="searchData" label-position="top" class="search-form"> <el-form :inline="true" :model="searchData" label-position="top" class="search-form">
<el-form-item label="BU">
<el-select v-model="searchData.buNo" clearable filterable placeholder="全部" style="width: 130px" @change="handleSearchBuChange">
<el-option
v-for="item in userBuList"
:key="`searchBu_${item.buNo}`"
:label="item.buDesc ? `${normalizeBuNo(item.buNo, searchData.site)}-${item.buDesc}` : normalizeBuNo(item.buNo, searchData.site)"
:value="normalizeBuNo(item.buNo, searchData.site)"
/>
</el-select>
</el-form-item>
<el-form-item label="项目编码"> <el-form-item label="项目编码">
<el-input v-model="searchData.projectNo" clearable placeholder="请输入项目编码" style="width: 140px" /> <el-input v-model="searchData.projectNo" clearable placeholder="请输入项目编码" style="width: 140px" />
</el-form-item> </el-form-item>
@ -48,6 +58,7 @@
<el-button type="warning" @click="openCreateProofDialog()">新增打样</el-button> <el-button type="warning" @click="openCreateProofDialog()">新增打样</el-button>
<el-button type="success" plain :loading="syncNpiLoading" @click="syncToNpi()">同步项目物料到NPI</el-button> <el-button type="success" plain :loading="syncNpiLoading" @click="syncToNpi()">同步项目物料到NPI</el-button>
<el-button type="success" plain :loading="syncProofLoading" @click="syncProofToNpi()">同步打样到NPI</el-button> <el-button type="success" plain :loading="syncProofLoading" @click="syncProofToNpi()">同步打样到NPI</el-button>
<el-button type="info" v-if="isAuth('833001005:set')" plain @click="openBuProcessConfigDialog">事业部进度设置</el-button>
</el-row> </el-row>
</el-form-item> </el-form-item>
</el-form> </el-form>
@ -99,7 +110,7 @@
</el-table-column> </el-table-column>
<el-table-column <el-table-column
v-for="item in processColumns"
v-for="item in visibleProcessColumns"
:key="item.code" :key="item.code"
:label="item.label" :label="item.label"
width="120" width="120"
@ -107,7 +118,10 @@
header-align="center" header-align="center"
> >
<template slot-scope="scope"> <template slot-scope="scope">
<div :class="['process-cell', isProcessComplete(scope.row, item) ? 'is-complete' : '']">
<div
v-if="isProcessColumnVisibleForRow(scope.row, item)"
:class="['process-cell', isProcessComplete(scope.row, item) ? 'is-complete' : '']"
>
<el-date-picker <el-date-picker
v-if="batchEditMode" v-if="batchEditMode"
v-model="scope.row[item.actualField]" v-model="scope.row[item.actualField]"
@ -143,6 +157,7 @@
></el-button> ></el-button>
</div> </div>
</div> </div>
<div v-else class="process-cell process-cell--masked"></div>
</template> </template>
</el-table-column> </el-table-column>
@ -217,6 +232,37 @@
}" }"
>{{ processTooltip.content }}</div> >{{ processTooltip.content }}</div>
<el-dialog
title="事业部进度展示设置"
:visible.sync="buProcessConfigDialogVisible"
width="900px"
:close-on-click-modal="false"
custom-class="bu-process-config-dialog"
>
<el-table :data="buProcessConfigRows" border stripe max-height="560">
<el-table-column prop="buDesc" label="事业部名称" width="100" show-overflow-tooltip />
<el-table-column label="可见进度列表" min-width="450" class-name="bu-process-list-column">
<template slot-scope="scope">
<el-checkbox-group
v-model="scope.row.processCodes"
@change="handleBuProcessCodesChange(scope.row)"
>
<el-checkbox
v-for="column in processColumns"
:key="`${scope.row.buNo}_${column.code}`"
:label="column.code"
>{{ column.label }}</el-checkbox>
</el-checkbox-group>
</template>
</el-table-column>
</el-table>
<div slot="footer">
<el-button @click="buProcessConfigDialogVisible = false">取消</el-button>
<el-button type="primary" @click="saveBuProcessConfig">保存设置</el-button>
</div>
</el-dialog>
<el-dialog :title="oneKeyDialogMode === 'edit' ? '修改项目/物料/打样' : '一键创建项目/物料/打样'" :visible.sync="oneKeyDialogVisible" :close-on-click-modal="false" width="1000px"> <el-dialog :title="oneKeyDialogMode === 'edit' ? '修改项目/物料/打样' : '一键创建项目/物料/打样'" :visible.sync="oneKeyDialogVisible" :close-on-click-modal="false" width="1000px">
<el-form :model="oneKeyForm" label-position="top" class="one-key-grid-form"> <el-form :model="oneKeyForm" label-position="top" class="one-key-grid-form">
<el-row :gutter="16"> <el-row :gutter="16">
@ -762,7 +808,9 @@ import {
finishProofTracking, finishProofTracking,
oneKeyCreateProofTracking, oneKeyCreateProofTracking,
oneKeyUpdateProofTracking, oneKeyUpdateProofTracking,
queryProofTrackingBuProcessConfig,
queryProofTrackingProcessHistory, queryProofTrackingProcessHistory,
saveProofTrackingBuProcessConfig,
searchProjectInfoTracking, searchProjectInfoTracking,
searchProjectPartTracking, searchProjectPartTracking,
searchProofTracking, searchProofTracking,
@ -837,6 +885,7 @@ export default {
userName: this.$store.state.user.name, userName: this.$store.state.user.name,
projectNo: '', projectNo: '',
projectDesc: '', projectDesc: '',
buNo: '',
testPartNo: '', testPartNo: '',
partDesc: '', partDesc: '',
customerNo: '', customerNo: '',
@ -860,6 +909,9 @@ export default {
{ label: 'Inspection', code: 'inspection', planField: 'inspectionPlanDate', actualField: 'inspectionActualDate', statusField: 'inspectionStatus' }, { label: 'Inspection', code: 'inspection', planField: 'inspectionPlanDate', actualField: 'inspectionActualDate', statusField: 'inspectionStatus' },
{ label: 'Delivery&Package', code: 'deliveryPackage', planField: 'deliveryPackagePlanDate', actualField: 'deliveryPackageActualDate', statusField: 'deliveryPackageStatus' } { label: 'Delivery&Package', code: 'deliveryPackage', planField: 'deliveryPackagePlanDate', actualField: 'deliveryPackageActualDate', statusField: 'deliveryPackageStatus' }
], ],
buProcessConfigDialogVisible: false,
buProcessConfigRows: [],
buProcessConfigMap: {},
projectCategoryList: ['Low Risk', 'High Risk', 'Sustaining'], projectCategoryList: ['Low Risk', 'High Risk', 'Sustaining'],
cProjectRegionList: [ cProjectRegionList: [
{ cProjectRegion: 'Global' }, { cProjectRegion: 'Global' },
@ -1004,19 +1056,262 @@ export default {
} }
}, },
activated () { activated () {
this.loadUserBuList()
this.loadUserBuList().then(() => {
this.queryBuProcessConfig()
})
this.getDataList() this.getDataList()
}, },
computed: {
visibleProcessColumns () {
const searchBuNo = this.getSelectedSearchBuNo()
// BUBU
if (!searchBuNo) {
return this.processColumns
}
const visibleCodes = this.getProcessVisibleCodesByBuNo(searchBuNo)
if (!visibleCodes) {
return this.processColumns
}
const visibleColumns = this.processColumns.filter(item => visibleCodes.indexOf(item.code) > -1)
return visibleColumns.length > 0 ? visibleColumns : this.processColumns
}
},
methods: { methods: {
loadUserBuList () { loadUserBuList () {
if (this.userBuList.length > 0) { if (this.userBuList.length > 0) {
return
this.ensureBuProcessConfigRows()
return Promise.resolve(this.userBuList)
} }
const params = { username: this.$store.state.user.name } const params = { username: this.$store.state.user.name }
getSiteAndBuByUserName(params).then(({ data }) => {
return getSiteAndBuByUserName(params).then(({ data }) => {
if (data && data.code === 0) { if (data && data.code === 0) {
this.userBuList = data.rows || []
const excludedBuNoList = ['3_02-Hardtag', '4_04-MHM', '5_05-Alpha']
this.userBuList = (data.rows || []).filter(item => {
const buNo = item && item.buNo ? String(item.buNo).trim() : ''
return excludedBuNoList.indexOf(buNo) === -1
})
this.ensureBuProcessConfigRows()
} }
return this.userBuList
}).catch(() => {
this.userBuList = []
this.ensureBuProcessConfigRows()
return []
})
},
getAllProcessCodes () {
return this.processColumns.map(item => item.code)
},
normalizeBuNo (buNo, site) {
const rawBuNo = buNo == null ? '' : String(buNo).trim()
if (!rawBuNo) {
return ''
}
const splitIdx = rawBuNo.indexOf('_')
if (splitIdx < 1 || splitIdx >= rawBuNo.length - 1) {
return rawBuNo
}
// BUsite 2_01-Label -> 01-Label
return rawBuNo.substring(splitIdx + 1)
},
getValidProcessCodes (codes) {
if (!Array.isArray(codes) || codes.length === 0) {
return []
}
const allCodes = this.getAllProcessCodes()
const normalizedCodes = []
codes.forEach(code => {
const codeVal = code == null ? '' : String(code).trim()
if (!codeVal || allCodes.indexOf(codeVal) === -1) {
return
}
if (normalizedCodes.indexOf(codeVal) === -1) {
normalizedCodes.push(codeVal)
}
})
return normalizedCodes
},
getBuProcessConfigEntry (buNo, site) {
const normalizedBuNo = this.normalizeBuNo(buNo, site)
if (!normalizedBuNo) {
return null
}
const config = this.buProcessConfigMap[normalizedBuNo]
if (config) {
return { key: normalizedBuNo, config: config }
}
return null
},
getSelectedSearchBuNo () {
return this.normalizeBuNo(this.searchData.buNo, this.searchData.site)
},
handleSearchBuChange () {
// BU
this.getDataList('Y')
},
getProcessVisibleCodesByBuNo (buNo, site) {
const configEntry = this.getBuProcessConfigEntry(buNo, site)
const config = configEntry ? configEntry.config : null
// null BU
if (!config || config.showAll !== false) {
return null
}
const validCodes = this.getValidProcessCodes(config.processCodes)
if (validCodes.length === 0 || validCodes.length >= this.processColumns.length) {
return null
}
return validCodes
},
isProcessColumnVisibleForRow (row, processCol) {
if (!row || !processCol) {
return true
}
// BUBU
if (this.getSelectedSearchBuNo()) {
return true
}
const visibleCodes = this.getProcessVisibleCodesByBuNo(row.buNo, row.site)
if (!visibleCodes) {
return true
}
return visibleCodes.indexOf(processCol.code) > -1
},
queryBuProcessConfig () {
const inData = {
site: this.$store.state.user.site,
userName: this.$store.state.user.name
}
queryProofTrackingBuProcessConfig(inData).then(({ data }) => {
if (!(data && data.code === 0)) {
this.$message.error((data && data.msg) || '加载事业部进度展示配置失败')
return
}
const rows = data.rows || []
const nextMap = {}
const allCodeCount = this.processColumns.length
rows.forEach(item => {
const buNo = this.normalizeBuNo(item && item.buNo ? item.buNo : '', this.$store.state.user.site)
if (!buNo) {
return
}
const processCodes = this.getValidProcessCodes(item.processCodes)
const showAll = item.showAll !== false || processCodes.length === 0 || processCodes.length >= allCodeCount
if (!showAll) {
nextMap[buNo] = {
showAll: false,
processCodes: processCodes
}
}
})
this.buProcessConfigMap = nextMap
this.ensureBuProcessConfigRows()
this.refreshTrackingTableLayout()
}).catch(() => {
this.$message.error('加载事业部进度展示配置异常')
})
},
ensureBuProcessConfigRows () {
const allCodes = this.getAllProcessCodes()
const rows = []
const usedBuMap = {}
const appendRow = (buNo, buDesc, site) => {
const key = this.normalizeBuNo(buNo, site || this.$store.state.user.site)
if (!key || usedBuMap[key]) {
return
}
usedBuMap[key] = true
const cfg = this.buProcessConfigMap[key]
const row = {
buNo: key,
buDesc: buDesc || key,
processCodes: allCodes.slice()
}
if (cfg && cfg.showAll === false) {
const validCodes = this.getValidProcessCodes(cfg.processCodes)
if (validCodes.length > 0 && validCodes.length < allCodes.length) {
row.processCodes = validCodes
}
}
rows.push(row)
}
this.userBuList.forEach(item => {
if (!item || !item.buNo) {
return
}
appendRow(item.buNo, item.buDesc || this.normalizeBuNo(item.buNo, this.$store.state.user.site), this.$store.state.user.site)
})
Object.keys(this.buProcessConfigMap).forEach(buNo => {
appendRow(buNo, buNo, this.$store.state.user.site)
})
this.buProcessConfigRows = rows
},
openBuProcessConfigDialog () {
this.ensureBuProcessConfigRows()
this.buProcessConfigDialogVisible = true
},
refreshTrackingTableLayout () {
this.$nextTick(() => {
const tableRef = this.$refs.trackingTable
if (tableRef && tableRef.doLayout) {
tableRef.doLayout()
}
})
},
handleBuProcessCodesChange (row) {
if (!row) {
return
}
row.processCodes = this.getValidProcessCodes(row.processCodes)
},
saveBuProcessConfig () {
if (!this.buProcessConfigRows || this.buProcessConfigRows.length === 0) {
this.$message.warning('暂无可配置的事业部')
return
}
const nextMap = {}
const allCodeCount = this.processColumns.length
const submitRows = []
for (let i = 0; i < this.buProcessConfigRows.length; i++) {
const row = this.buProcessConfigRows[i]
const buNo = this.normalizeBuNo(row && row.buNo ? row.buNo : '', this.$store.state.user.site)
if (!buNo) {
continue
}
const validCodes = this.getValidProcessCodes(row.processCodes)
if (validCodes.length === 0) {
this.$message.warning(`事业部【${row.buDesc || buNo}】至少需要选择一个可见进度`)
return
}
const showAll = validCodes.length >= allCodeCount
if (!showAll) {
nextMap[buNo] = {
showAll: false,
processCodes: validCodes
}
}
submitRows.push({
buNo: buNo,
showAll: showAll,
processCodes: validCodes
})
}
const inData = {
site: this.$store.state.user.site,
updateBy: this.$store.state.user.name,
rows: submitRows
}
saveProofTrackingBuProcessConfig(inData).then(({ data }) => {
if (!(data && data.code === 0)) {
this.$message.error((data && data.msg) || '事业部进度展示设置保存失败')
return
}
this.buProcessConfigMap = nextMap
this.ensureBuProcessConfigRows()
this.buProcessConfigDialogVisible = false
this.$message.success(data.msg || '事业部进度展示设置已保存')
this.refreshTrackingTableLayout()
}).catch(() => {
this.$message.error('事业部进度展示设置保存异常')
}) })
}, },
getRoleApi (apiKey) { getRoleApi (apiKey) {
@ -1312,6 +1607,7 @@ export default {
page: this.pageIndex, page: this.pageIndex,
limit: this.pageSize limit: this.pageSize
}) })
inData.buNo = this.normalizeBuNo(inData.buNo, inData.site)
this.dataListLoading = true this.dataListLoading = true
searchProofTracking(inData).then(({ data }) => { searchProofTracking(inData).then(({ data }) => {
this.dataListLoading = false this.dataListLoading = false
@ -1363,6 +1659,7 @@ export default {
resetSearch () { resetSearch () {
this.searchData.projectNo = '' this.searchData.projectNo = ''
this.searchData.projectDesc = '' this.searchData.projectDesc = ''
this.searchData.buNo = ''
this.searchData.testPartNo = '' this.searchData.testPartNo = ''
this.searchData.partDesc = '' this.searchData.partDesc = ''
this.searchData.customerNo = '' this.searchData.customerNo = ''
@ -2531,6 +2828,37 @@ export default {
flex-wrap: wrap; flex-wrap: wrap;
} }
.bu-process-config-dialog .el-checkbox-group {
display: grid;
grid-template-columns: repeat(5, minmax(110px, 1fr));
column-gap: 12px;
row-gap: 8px;
align-items: center;
}
.bu-process-config-dialog .bu-process-list-column .cell {
white-space: normal !important;
height: auto !important;
line-height: 20px;
padding-top: 6px;
padding-bottom: 6px;
overflow: hidden;
}
.bu-process-config-dialog .bu-process-list-column {
vertical-align: top;
}
.bu-process-config-dialog .bu-process-list-column .el-checkbox,
.bu-process-config-dialog .bu-process-list-column .el-checkbox + .el-checkbox {
width: 100%;
margin: 0 !important;
}
.bu-process-config-dialog .bu-process-list-column .el-checkbox__label {
white-space: nowrap;
}
.button-col { .button-col {
margin-bottom: 8px; margin-bottom: 8px;
} }
@ -2587,6 +2915,10 @@ export default {
color: #8c8c8c; color: #8c8c8c;
} }
.process-cell--masked {
background: transparent !important;
}
.process-content { .process-content {
display: flex; display: flex;
align-items: center; align-items: center;

Loading…
Cancel
Save