Browse Source

feat(components): 添加只读模式支持和验证规则

- 在 poCustomer_FieldAuth 组件中添加 readonly 属性和相关禁用逻辑
- 在 poCustomer_UserScope 组件中添加 readonly 属性和相关禁用逻辑
- 在 srmSupplier_Address 组件中添加 readonly 属性和相关显示控制
- 在 srmSupplier_Contract 组件中添加 readonly 模式下的查看功能
- 在 srmSupplier_DocumentDefinition 组件中添加 readonly 模式控制
- 为 partInfoList 中的 partSpec 字段添加必填验证规则
- 新增 poCustomerView 只读查询页面,支持权限查看功能
- 新增 supplierListView 只读查询页面,支持供应商信息查看功能
- 优化合同组件中的有效期设置逻辑,支持清空操作
- 调整文档组件中的操作按钮显示逻辑,适配只读模式
master
qiankanghui 2 weeks ago
parent
commit
c140685dc0
  1. 13
      src/views/modules/order/com_poCustomer_FieldAuth.vue
  2. 11
      src/views/modules/order/com_poCustomer_UserScope.vue
  3. 283
      src/views/modules/order/poCustomerView.vue
  4. 3
      src/views/modules/srmPart/partInfoList.vue
  5. 10
      src/views/modules/srmSupplier/com_srmSupplier_Address.vue
  6. 55
      src/views/modules/srmSupplier/com_srmSupplier_Contract.vue
  7. 36
      src/views/modules/srmSupplier/com_srmSupplier_DocumentDefinition.vue
  8. 1261
      src/views/modules/srmSupplier/supplierListView.vue
  9. 365
      src/views/modules/supplier/supplierPartMoqPriceView.vue
  10. 580
      src/views/modules/supplier/supplierPartNewProductAuditView.vue
  11. 8
      src/views/modules/sys/user-add-or-update.vue

13
src/views/modules/order/com_poCustomer_FieldAuth.vue

@ -1,6 +1,6 @@
<template> <template>
<div class="po-customer-field-auth"> <div class="po-customer-field-auth">
<el-button type="primary" :loading="saving" style="margin-bottom: 10px" @click="save">保存字段权限</el-button>
<el-button v-if="!readonly" type="primary" :loading="saving" style="margin-bottom: 10px" @click="save">保存字段权限</el-button>
<div class="rq"> <div class="rq">
<el-table class="field-auth-table" :data="rows" border style="width: 100%" height="400"> <el-table class="field-auth-table" :data="rows" border style="width: 100%" height="400">
<el-table-column prop="fieldCode" label="字段编码" min-width="160" /> <el-table-column prop="fieldCode" label="字段编码" min-width="160" />
@ -9,7 +9,7 @@
<template slot-scope="{ row }"> <template slot-scope="{ row }">
<el-input <el-input
v-model="row.displayLabel" v-model="row.displayLabel"
:disabled="!isExtField(row)"
:disabled="readonly || !isExtField(row)"
clearable clearable
placeholder="扩展字段可维护" placeholder="扩展字段可维护"
/> />
@ -19,7 +19,7 @@
<template slot-scope="{ row }"> <template slot-scope="{ row }">
<el-input <el-input
v-model="row.dictType" v-model="row.dictType"
:disabled="!isDictTypeEditable(row)"
:disabled="readonly || !isDictTypeEditable(row)"
clearable clearable
:placeholder="isExtDateField(row) ? '日期扩展字段不可填' : '留空=默认组件'" :placeholder="isExtDateField(row) ? '日期扩展字段不可填' : '留空=默认组件'"
/> />
@ -31,13 +31,13 @@
v-model="row.visibleFlag" v-model="row.visibleFlag"
true-label="Y" true-label="Y"
false-label="N" false-label="N"
:disabled="isMandatoryField(row)"
:disabled="readonly || isMandatoryField(row)"
@change="onVisibleChange(row)" /> @change="onVisibleChange(row)" />
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="必填" width="70"> <el-table-column label="必填" width="70">
<template slot-scope="{ row }"> <template slot-scope="{ row }">
<el-checkbox v-model="row.requiredFlag" :disabled="!isExtField(row)" true-label="Y" false-label="N" />
<el-checkbox v-model="row.requiredFlag" :disabled="readonly || !isExtField(row)" true-label="Y" false-label="N" />
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
@ -52,7 +52,8 @@ export default {
name: 'ComPoCustomerFieldAuth', name: 'ComPoCustomerFieldAuth',
props: { props: {
site: { type: String, required: true }, site: { type: String, required: true },
customerCode: { type: String, default: '' }
customerCode: { type: String, default: '' },
readonly: { type: Boolean, default: false }
}, },
data () { data () {
return { rows: [], saving: false } return { rows: [], saving: false }

11
src/views/modules/order/com_poCustomer_UserScope.vue

@ -1,6 +1,6 @@
<template> <template>
<div> <div>
<el-form :inline="true" label-position="top" style="margin-top: 10px">
<el-form v-if="!readonly" :inline="true" label-position="top" style="margin-top: 10px">
<el-form-item > <el-form-item >
<el-button type="primary" @click="openUserPicker">选择账号</el-button> <el-button type="primary" @click="openUserPicker">选择账号</el-button>
<el-button type="primary" :loading="saving" @click="save">保存</el-button> <el-button type="primary" :loading="saving" @click="save">保存</el-button>
@ -11,7 +11,7 @@
<el-table-column prop="userName" label="账号" min-width="180" /> <el-table-column prop="userName" label="账号" min-width="180" />
<el-table-column label="启用" width="100" align="center"> <el-table-column label="启用" width="100" align="center">
<template slot-scope="{ row }"> <template slot-scope="{ row }">
<el-select v-model="row.active" size="mini" style="width: 80px">
<el-select v-model="row.active" size="mini" style="width: 80px" :disabled="readonly">
<el-option label="Y" value="Y" /> <el-option label="Y" value="Y" />
<el-option label="N" value="N" /> <el-option label="N" value="N" />
</el-select> </el-select>
@ -19,10 +19,10 @@
</el-table-column> </el-table-column>
<el-table-column label="备注" min-width="220"> <el-table-column label="备注" min-width="220">
<template slot-scope="{ row }"> <template slot-scope="{ row }">
<el-input v-model="row.remark" size="mini" />
<el-input v-model="row.remark" size="mini" :disabled="readonly" />
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="操作" width="80" align="center">
<el-table-column v-if="!readonly" label="操作" width="80" align="center">
<template slot-scope="scope"> <template slot-scope="scope">
<el-link type="danger" @click="removeRow(scope.$index)">删除</el-link> <el-link type="danger" @click="removeRow(scope.$index)">删除</el-link>
</template> </template>
@ -78,7 +78,8 @@ export default {
name: 'ComPoCustomerUserScope', name: 'ComPoCustomerUserScope',
props: { props: {
site: { type: String, required: true }, site: { type: String, required: true },
customerCode: { type: String, default: '' }
customerCode: { type: String, default: '' },
readonly: { type: Boolean, default: false }
}, },
data () { data () {
return { return {

283
src/views/modules/order/poCustomerView.vue

@ -0,0 +1,283 @@
<template>
<div class="mod-config">
<el-form :inline="true" label-position="top" :model="searchData">
<el-form-item label="Customer编码">
<el-input v-model="searchData.customerCode" clearable style="width: 160px" placeholder="请输入编码" />
</el-form-item>
<el-form-item label="Customer名称">
<el-input v-model="searchData.customerName" clearable style="width: 220px" placeholder="请输入名称" />
</el-form-item>
<el-form-item label="启用">
<el-select v-model="searchData.active" clearable style="width: 120px">
<el-option label="Y" value="Y" />
<el-option label="N" value="N" />
</el-select>
</el-form-item>
<el-form-item label=" ">
<el-button type="primary" @click="getDataList()">查询</el-button>
<el-button type="primary" @click="exportExcel()">导出</el-button>
</el-form-item>
</el-form>
<el-table
:height="height"
:data="dataList"
border
v-loading="dataListLoading"
style="width: 100%;">
<el-table-column
v-for="(item,index) in columnList"
:key="index"
:sortable="item.columnSortable"
:prop="item.columnProp"
:header-align="item.headerAlign"
:show-overflow-tooltip="item.showOverflowTooltip"
:align="item.align"
:fixed="item.fixed === '' ? false : item.fixed"
:min-width="item.columnWidth"
:label="item.columnLabel" />
<el-table-column
fixed="right"
header-align="center"
align="center"
width="90"
label="操作">
<template slot-scope="scope">
<el-link style="cursor: pointer" @click="openAuthModal(scope.row)">权限</el-link>
</template>
</el-table-column>
</el-table>
<el-pagination
@size-change="sizeChangeHandle"
@current-change="currentChangeHandle"
:current-page="pageIndex"
:page-sizes="[20, 50, 100, 200, 500]"
:page-size="pageSize"
:total="totalPage"
layout="total, sizes, prev, pager, next, jumper" />
<!-- 权限查看:只读,不允许任何操作 -->
<el-dialog
class="customer-auth-dialog"
title="Customer 权限查看"
:visible.sync="authModalFlag"
width="960px"
top="4vh"
:close-on-click-modal="false"
v-drag
append-to-body>
<div v-if="authCustomerCode">
<p style="margin-bottom: 8px">当前 Customer:<strong>{{ authCustomerCode }}</strong>(仅查看,不可操作)</p>
<el-tabs v-model="authActiveTab">
<el-tab-pane label="可见账号" name="userScope">
<com-po-customer-user-scope :site="searchData.site" :customer-code="authCustomerCode" :readonly="true" />
</el-tab-pane>
<el-tab-pane label="字段权限" name="fieldAuth">
<com-po-customer-field-auth :site="searchData.site" :customer-code="authCustomerCode" :readonly="true" />
</el-tab-pane>
</el-tabs>
</div>
</el-dialog>
</div>
</template>
<script>
import { searchPoCustomerPage } from '@/api/order/poCustomer.js'
import { formatPoOrderTypeLabel } from '@/views/modules/order/poOrderTypeOptions'
import ComPoCustomerUserScope from './com_poCustomer_UserScope.vue'
import ComPoCustomerFieldAuth from './com_poCustomer_FieldAuth.vue'
import excel from '@/utils/excel-util.js'
export default {
name: 'poCustomerView',
components: {
ComPoCustomerUserScope,
ComPoCustomerFieldAuth
},
data () {
return {
exportName: 'Customer查询_' + this.dayjs().format('YYYYMMDDHHmmss'),
height: 200,
dataList: [],
dataListLoading: false,
pageIndex: 1,
pageSize: 20,
totalPage: 0,
searchData: {
site: this.$store.state.user.site,
customerCode: '',
customerName: '',
active: '',
page: 1,
limit: 10
},
authModalFlag: false,
authActiveTab: 'userScope',
authCustomerCode: '',
columnList: [
{
columnProp: 'customerCode',
headerAlign: 'center',
align: 'center',
columnLabel: '编码',
columnHidden: false,
columnSortable: false,
fixed: '',
columnWidth: 160,
showOverflowTooltip: true
},
{
columnProp: 'customerName',
headerAlign: 'center',
align: 'left',
columnLabel: '名称',
columnHidden: false,
columnSortable: false,
fixed: '',
columnWidth: 260,
showOverflowTooltip: true
},
{
columnProp: 'orderTypeLabel',
headerAlign: 'center',
align: 'center',
columnLabel: '订单类型',
columnHidden: false,
columnSortable: false,
fixed: '',
columnWidth: 120,
showOverflowTooltip: true
},
{
columnProp: 'active',
headerAlign: 'center',
align: 'center',
columnLabel: '启用',
columnHidden: false,
columnSortable: false,
fixed: '',
columnWidth: 90,
showOverflowTooltip: true
},
{
columnProp: 'remark',
headerAlign: 'center',
align: 'left',
columnLabel: '备注',
columnHidden: false,
columnSortable: false,
fixed: '',
columnWidth: 260,
showOverflowTooltip: true
}
]
}
},
mounted () {
this.$nextTick(() => {
this.height = window.innerHeight - 180
})
},
created () {
this.getDataList()
},
methods: {
getDataList () {
this.dataListLoading = true
const params = {
...this.searchData,
site: this.$store.state.user.site,
page: this.pageIndex,
limit: this.pageSize
}
searchPoCustomerPage(params).then(({ data }) => {
if (data && data.code === 0) {
const pageData = data.page
this.dataList = (pageData && pageData.list ? pageData.list : []).map(item => {
const normalizedOrderType = item && item.orderType ? item.orderType : 'PO'
return {
...item,
orderType: normalizedOrderType,
orderTypeLabel: formatPoOrderTypeLabel(normalizedOrderType)
}
})
this.pageIndex = pageData && pageData.currPage ? pageData.currPage : 1
this.pageSize = pageData && pageData.pageSize ? pageData.pageSize : this.pageSize
this.totalPage = pageData && pageData.totalCount ? pageData.totalCount : 0
} else {
this.$message.error((data && data.msg) || '获取数据失败')
}
}).catch(err => {
this.$message.error((err && err.message) || '获取数据失败')
}).finally(() => {
this.dataListLoading = false
})
},
sizeChangeHandle (val) {
this.pageSize = val
this.pageIndex = 1
this.getDataList()
},
currentChangeHandle (val) {
this.pageIndex = val
this.getDataList()
},
// 打开权限查看弹窗(只读)
openAuthModal (row) {
this.authCustomerCode = row.customerCode
this.authActiveTab = 'userScope'
this.authModalFlag = true
},
exportExcel () {
const params = {
...this.searchData,
site: this.$store.state.user.site
}
excel.exportTable({
url: '/poCustomer/list',
columnMapping: this.columnList,
mergeSetting: [],
params,
fileName: this.exportName + '.xlsx',
rowFetcher: res => {
if (res && res.data && res.data.code === 0) {
const rows = (res.data.rows || []).map(item => {
const normalizedOrderType = item && item.orderType ? item.orderType : 'PO'
return {
...item,
orderTypeLabel: formatPoOrderTypeLabel(normalizedOrderType)
}
})
return { rows }
}
return { rows: [] }
},
columnFormatter: [],
dropColumns: []
})
}
}
}
</script>
<style scoped>
.mod-config {
padding: 0;
}
.el-table /deep/ .cell {
height: auto;
line-height: 1.5;
}
</style>
<style lang="scss">
.customer-auth-dialog .el-dialog__body {
padding-bottom: 10px;
}
</style>

3
src/views/modules/srmPart/partInfoList.vue

@ -912,6 +912,9 @@ export default {
partRules: { partRules: {
partDesc: [ partDesc: [
{ required: true, message: ' ', trigger: 'blur' } { required: true, message: ' ', trigger: 'blur' }
],
partSpec: [
{ required: true, message: ' ', trigger: 'blur' }
], ],
npc: [ npc: [
{ required: true, message: ' ', trigger: 'blur' } { required: true, message: ' ', trigger: 'blur' }

10
src/views/modules/srmSupplier/com_srmSupplier_Address.vue

@ -12,7 +12,7 @@
</el-form-item> </el-form-item>
<el-form-item label=" "> <el-form-item label=" ">
<el-button type="primary" @click="getDataList()">查询</el-button> <el-button type="primary" @click="getDataList()">查询</el-button>
<el-button type="primary" @click="addModal()">新增</el-button>
<el-button v-if="!readonly" type="primary" @click="addModal()">新增</el-button>
</el-form-item> </el-form-item>
</el-form> </el-form>
@ -37,6 +37,7 @@
</template> </template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column
v-if="!readonly"
header-align="center" header-align="center"
align="center" align="center"
width="120" width="120"
@ -199,6 +200,13 @@ export default {
Chooselist, Chooselist,
SysDictSelect SysDictSelect
}, },
props: {
// 只读模式:隐藏新增/编辑/删除,仅保留查询与查看(供只读查询页复用;默认 false 不影响原页面)
readonly: {
type: Boolean,
default: false
}
},
data() { data() {
return { return {
dataList: [], dataList: [],

55
src/views/modules/srmSupplier/com_srmSupplier_Contract.vue

@ -2,7 +2,7 @@
<div class="customer-css"> <div class="customer-css">
<el-form label-position="top" style="margin-top: 1px; margin-left: 0px;"> <el-form label-position="top" style="margin-top: 1px; margin-left: 0px;">
<el-form :inline="true" label-position="top" style="margin-top: 0px"> <el-form :inline="true" label-position="top" style="margin-top: 0px">
<el-button type="primary" @click="addModal()">新增</el-button>
<el-button v-if="!readonly" type="primary" @click="addModal()">新增</el-button>
</el-form> </el-form>
</el-form> </el-form>
<el-table <el-table
@ -34,9 +34,12 @@
fixed="right" fixed="right"
label="操作"> label="操作">
<template slot-scope="scope"> <template slot-scope="scope">
<a type="text" size="small" v-if="scope.row.needRenew=='Y'" @click="renewModew(scope.row)">续签 |</a>
<a type="text" size="small" @click="editModel(scope.row)">编辑 |</a>
<a type="text" size="small" @click="deleteData(scope.row)">删除</a>
<a type="text" size="small" v-if="readonly" @click="viewModel(scope.row)">查看</a>
<template v-else>
<a type="text" size="small" v-if="scope.row.needRenew=='Y'" @click="renewModew(scope.row)">续签 |</a>
<a type="text" size="small" @click="editModel(scope.row)">编辑 |</a>
<a type="text" size="small" @click="deleteData(scope.row)">删除</a>
</template>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
@ -61,6 +64,7 @@
type="date" type="date"
format="yyyy-MM-dd" format="yyyy-MM-dd"
value-format="yyyy-MM-dd" value-format="yyyy-MM-dd"
:disabled="readonly"
placeholder="选择日期"> placeholder="选择日期">
</el-date-picker> </el-date-picker>
</el-form-item> </el-form-item>
@ -73,37 +77,38 @@
type="date" type="date"
format="yyyy-MM-dd" format="yyyy-MM-dd"
value-format="yyyy-MM-dd" value-format="yyyy-MM-dd"
:disabled="readonly"
placeholder="选择日期"> placeholder="选择日期">
</el-date-picker> </el-date-picker>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="6"> <el-col :span="6">
<el-form-item :label="'金额'" > <el-form-item :label="'金额'" >
<el-input v-model="contractModelData.amout" type="number" style="width: 130px"></el-input>
<el-input v-model="contractModelData.amout" type="number" :disabled="readonly" style="width: 130px"></el-input>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="6"> <el-col :span="6">
<el-form-item :label="'货币'" > <el-form-item :label="'货币'" >
<el-input v-model="contractModelData.currency" style="width: 130px"></el-input>
<el-input v-model="contractModelData.currency" :disabled="readonly" style="width: 130px"></el-input>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="6"> <el-col :span="6">
<el-form-item :label="'合同编号'" > <el-form-item :label="'合同编号'" >
<el-input v-model="contractModelData.contractNo" style="width: 130px" ></el-input>
<el-input v-model="contractModelData.contractNo" :disabled="readonly" style="width: 130px" ></el-input>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="6"> <el-col :span="6">
<el-form-item :label="'合同名称'" > <el-form-item :label="'合同名称'" >
<el-input v-model="contractModelData.contractName" style="width: 130px" ></el-input>
<el-input v-model="contractModelData.contractName" :disabled="readonly" style="width: 130px" ></el-input>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="24"> <el-col :span="24">
<el-form-item :label="'合同详情'"> <el-form-item :label="'合同详情'">
<el-input type="textarea" :rows="3" v-model="contractModelData.contractDetail" style=""></el-input>
<el-input type="textarea" :rows="3" v-model="contractModelData.contractDetail" :disabled="readonly" style=""></el-input>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="4" style="margin-top: 50px"> <el-col :span="4" style="margin-top: 50px">
<el-button class="customer-bun-min" type="primary" @click="handleUpload" style="">上传</el-button>
<el-button v-if="!readonly" class="customer-bun-min" type="primary" @click="handleUpload" style="">上传</el-button>
</el-col> </el-col>
</el-row> </el-row>
@ -143,13 +148,13 @@
label="操作"> label="操作">
<template slot-scope="scope"> <template slot-scope="scope">
<a type="text" size="small" @click="handleDownload(scope.row)">查看 </a> <a type="text" size="small" @click="handleDownload(scope.row)">查看 </a>
<a type="text" size="small" v-if="contractModelData.id===0" @click="deleteFile(scope.$index)"> | 删除</a>
<a type="text" size="small" v-if="contractModelData.id===0 && !readonly" @click="deleteFile(scope.$index)"> | 删除</a>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
<el-footer style="height:40px;margin-top: 10px;text-align:center"> <el-footer style="height:40px;margin-top: 10px;text-align:center">
<el-button type="primary" @click="submitData()">提交</el-button>
<el-button type="primary" @click="contractModelFlag=false">取消并关闭</el-button>
<el-button v-if="!readonly" type="primary" @click="submitData()">提交</el-button>
<el-button type="primary" @click="contractModelFlag=false">{{ readonly ? '关闭' : '取消并关闭' }}</el-button>
</el-footer> </el-footer>
</el-dialog> </el-dialog>
@ -199,6 +204,13 @@ export default {
components: { components: {
Chooselist Chooselist
}, },
props: {
// 只读模式:隐藏新增/续签/编辑/删除/上传/提交,仅保留查看与附件下载(默认 false 不影响原页面)
readonly: {
type: Boolean,
default: false
}
},
data() { data() {
return { return {
dataList: [], dataList: [],
@ -579,6 +591,23 @@ export default {
}) })
this.contractModelFlag=true; this.contractModelFlag=true;
}, },
// 只读查看:打开合同弹窗展示信息与附件,配合 readonly 禁用编辑、隐藏提交/上传/删除
viewModel(row){
this.contractModelData=JSON.parse(JSON.stringify(row));
let params={
orderRef1:row.site,
orderRef2:row.contractId,
orderReftype:'SrmSupplierContract',
}
queryOss(params).then(({data})=>{
if (data && data.code === 0){
this.fileList = data.rows;
}else {
this.fileList = [];
}
})
this.contractModelFlag=true;
},
deleteData(row){ deleteData(row){
this.$confirm(`确认删除?`, '提示', { this.$confirm(`确认删除?`, '提示', {
confirmButtonText: '确认', confirmButtonText: '确认',

36
src/views/modules/srmSupplier/com_srmSupplier_DocumentDefinition.vue

@ -2,7 +2,7 @@
<div class="customer-css"> <div class="customer-css">
<el-form label-position="top" style="margin-top: 1px; margin-left: 0px;"> <el-form label-position="top" style="margin-top: 1px; margin-left: 0px;">
<el-form :inline="true" label-position="top" style="margin-top: 0px"> <el-form :inline="true" label-position="top" style="margin-top: 0px">
<el-button type="primary" @click="openDocumentListModel()">编辑文档清单</el-button>
<el-button v-if="!readonly" type="primary" @click="openDocumentListModel()">编辑文档清单</el-button>
</el-form> </el-form>
</el-form> </el-form>
<el-table <el-table
@ -182,8 +182,8 @@
</el-col> </el-col>
</el-row> </el-row>
</el-form> </el-form>
<el-button type="primary" @click="handleUpload">上传文档</el-button>
<el-button type="warning" @click="openValidToDialog()">设置文档有效期提醒</el-button>
<el-button v-if="!readonly" type="primary" @click="handleUpload">上传文档</el-button>
<el-button v-if="!readonly" type="warning" @click="openValidToDialog()">设置文档有效期提醒</el-button>
<el-table <el-table
:height="240" :height="240"
@ -218,8 +218,8 @@
fixed="right" fixed="right"
label="操作"> label="操作">
<template slot-scope="scope"> <template slot-scope="scope">
<a type="text" size="small" @click="handleDownload(scope.row)">查看 |</a>
<a type="text" size="small" @click="handleRemove(scope.row)">删除</a>
<a type="text" size="small" @click="handleDownload(scope.row)">查看{{ readonly ? '' : ' |' }}</a>
<a type="text" size="small" v-if="!readonly" @click="handleRemove(scope.row)">删除</a>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
@ -260,14 +260,15 @@
<el-dialog title="设置文档有效期提醒" :visible.sync="validToDialogVisible" v-drag width="360px" append-to-body :close-on-click-modal="false"> <el-dialog title="设置文档有效期提醒" :visible.sync="validToDialogVisible" v-drag width="360px" append-to-body :close-on-click-modal="false">
<el-form label-position="top"> <el-form label-position="top">
<el-form-item label="有效期至" required>
<el-form-item label="有效期至">
<el-date-picker <el-date-picker
style="width: 100%" style="width: 100%"
v-model="validToForm.validTo" v-model="validToForm.validTo"
type="date" type="date"
format="yyyy-MM-dd" format="yyyy-MM-dd"
value-format="yyyy-MM-dd" value-format="yyyy-MM-dd"
placeholder="选择有效期">
clearable
placeholder="选择有效期(可为空)">
</el-date-picker> </el-date-picker>
</el-form-item> </el-form-item>
</el-form> </el-form>
@ -302,6 +303,13 @@ export default {
components: { components: {
Chooselist Chooselist
}, },
props: {
// 只读模式:隐藏编辑文档清单/上传/设置有效期/删除,仅保留查看与附件下载(默认 false 不影响原页面)
readonly: {
type: Boolean,
default: false
}
},
data() { data() {
return { return {
documentSelection: [], documentSelection: [],
@ -678,8 +686,10 @@ export default {
responsibleDepartmentName:row.responsibleDepartmentName, responsibleDepartmentName:row.responsibleDepartmentName,
validTo:row.validTo || '', validTo:row.validTo || '',
} }
//上传和删除功能是通用方法不修改uploadFlag 开关model的时候刷新
this.refreshDocumentList();
//上传和删除功能是通用方法不修改uploadFlag 开关model的时候刷新;只读模式不触发写库刷新
if (!this.readonly) {
this.refreshDocumentList();
}
this.searchFiles() this.searchFiles()
this.fileListModelFlag=true this.fileListModelFlag=true
@ -817,16 +827,12 @@ export default {
this.validToForm.validTo = this.fileData.validTo || '' this.validToForm.validTo = this.fileData.validTo || ''
this.validToDialogVisible = true this.validToDialogVisible = true
}, },
// 仅修改当前文档记录的 validTo,按 id 更新
// 仅修改当前文档记录的 validTo,按 id 更新;有效期允许为空(清空时传 null,后端存为 NULL)
saveValidTo(){ saveValidTo(){
if(!this.validToForm.validTo){
this.$message.warning('请选择有效期!')
return
}
let inData={ let inData={
id:this.fileData.id, id:this.fileData.id,
site:this.searchData.site, site:this.searchData.site,
validTo:this.validToForm.validTo,
validTo:this.validToForm.validTo || null,
} }
this.validToSaving = true this.validToSaving = true
updateDocumentValidTo(inData).then(({data})=>{ updateDocumentValidTo(inData).then(({data})=>{

1261
src/views/modules/srmSupplier/supplierListView.vue
File diff suppressed because it is too large
View File

365
src/views/modules/supplier/supplierPartMoqPriceView.vue

@ -0,0 +1,365 @@
<template>
<div ref="pageRoot" class="customer-css supplier-part-moq-price">
<el-form :inline="true" label-position="top" class="pi-search-form">
<el-form-item>
<span slot="label" style="" @click="getBaseList(520, 'search')"><a href="javascript:void(0)">供应商编号</a></span>
<el-input
v-model="searchData.supplierNo"
placeholder="选择或输入编号"
style="width: 180px"
clearable
@keyup.enter.native="searchSupplierPartList"
/>
</el-form-item>
<el-form-item label="产品编码">
<el-input
v-model="searchData.partNo"
placeholder="产品编码"
style="width: 160px"
clearable
@keyup.enter.native="searchSupplierPartList"
/>
</el-form-item>
<el-form-item label="Item">
<el-input
v-model="searchData.item"
placeholder="Item"
style="width: 140px"
clearable
@keyup.enter.native="searchSupplierPartList"
/>
</el-form-item>
<el-form-item label="SKU">
<el-input
v-model="searchData.sku"
placeholder="SKU"
style="width: 140px"
clearable
@keyup.enter.native="searchSupplierPartList"
/>
</el-form-item>
<el-form-item label="物料名称">
<el-input
v-model="searchData.partDesc"
placeholder="物料名称"
style="width: 180px"
clearable
@keyup.enter.native="searchSupplierPartList"
/>
</el-form-item>
<el-form-item label="是否在用">
<el-select v-model="searchData.active" style="width: 120px" clearable>
<el-option label="在用" value="Y" />
<el-option label="禁用" value="N" />
</el-select>
</el-form-item>
<el-form-item label=" ">
<el-button
type="primary"
class="customer-bun-min"
:loading="topLoading"
@click="searchSupplierPartList"
>查询</el-button>
<el-button class="customer-bun-min" @click="resetSearch">重置</el-button>
</el-form-item>
</el-form>
<el-table
ref="topTable"
:data="supplierPartList"
:height="topTableHeight"
border
stripe
highlight-current-row
v-loading="topLoading"
style="width: 100%"
empty-text="点击查询查看数据"
@row-click="handleTopRowClick"
>
<el-table-column prop="supplierCode" label="供应商编号" min-width="120" header-align="center" align="center" />
<el-table-column prop="supplierName" label="供应商名称" min-width="180" header-align="center" align="left" show-overflow-tooltip />
<el-table-column prop="currency" label="币种" min-width="90" header-align="center" align="center" />
<el-table-column prop="partNo" label="产品编码" min-width="140" header-align="center" align="center" />
<el-table-column prop="item" label="Item" min-width="120" header-align="center" align="center" show-overflow-tooltip />
<el-table-column prop="sku" label="SKU" min-width="120" header-align="center" align="center" show-overflow-tooltip />
<el-table-column prop="partDesc" label="物料名称" min-width="200" header-align="center" align="left" show-overflow-tooltip />
<el-table-column prop="moqColor" label="MOQ/COLOR" min-width="120" header-align="center" align="right" :formatter="formatNumberCell" />
<el-table-column prop="moq" label="QTY/PO" min-width="110" header-align="center" align="right" :formatter="formatNumberCell" />
<el-table-column prop="qtyCarton" label="QTY/CARTON" min-width="120" header-align="center" align="right" :formatter="formatNumberCell" />
<el-table-column prop="active" label="在用" min-width="80" header-align="center" align="center">
<template slot-scope="scope">
<span>{{ scope.row.active === 'Y' ? '是' : '否' }}</span>
</template>
</el-table-column>
</el-table>
<el-pagination
class="main-pagination"
style="margin-top: 6px"
@size-change="sizeChangeHandle"
@current-change="currentChangeHandle"
:current-page="pageIndex"
:page-sizes="[20, 50, 100, 200, 500]"
:page-size="pageSize"
:total="totalPage"
layout="total, sizes, prev, pager, next, jumper"
/>
<div class="table-toolbar">
<span class="selected-text">
当前选择:
{{ selectedSupplierPart ? `${selectedSupplierPart.supplierCode} / ${selectedSupplierPart.partNo}` : '未选择供应商物料' }}
</span>
</div>
<el-table
:data="currentTierPriceList"
:height="bottomTableHeight"
border
stripe
v-loading="bottomLoading"
style="width: 100%"
empty-text="请选择上方供应商物料后查看当前阶梯价"
>
<el-table-column prop="qtyStart" label="开始数量" min-width="100" header-align="center" align="right" :formatter="formatNumberCell" />
<el-table-column prop="qtyEnd" label="结束数量" min-width="100" header-align="center" align="right" :formatter="formatNumberCell" />
<el-table-column prop="unitPrice" label="单价" min-width="120" header-align="center" align="right" :formatter="formatNumberCell" />
<el-table-column prop="priceDate" label="价格日期" min-width="130" header-align="center" align="center" />
<el-table-column prop="remark" label="备注" min-width="180" header-align="center" align="left" show-overflow-tooltip />
</el-table>
<Chooselist ref="baseList" @getBaseData="getBaseData" />
</div>
</template>
<script>
import Chooselist from '@/views/modules/common/Chooselist_eam'
import {
listSupplierPartMoqPage,
listCurrentTierPrice
} from '@/api/supplier/supplierPartMoqPrice'
export default {
name: 'SupplierPartMoqPriceView',
components: {
Chooselist
},
data () {
return {
topTableHeight: 260,
bottomTableHeight: 260,
tagNo: '',
tagType: 'search',
searchData: {
site: this.$store.state.user.site,
supplierNo: '',
partNo: '',
item: '',
sku: '',
partDesc: '',
active: ''
},
topLoading: false,
bottomLoading: false,
pageIndex: 1,
pageSize: 50,
totalPage: 0,
supplierPartList: [],
selectedSupplierPart: null,
currentTierPriceList: []
}
},
mounted () {
// 只读查询页:初始化不自动查询,需手动点击查询
this.handleResize()
window.addEventListener('resize', this.handleResize)
},
beforeDestroy () {
window.removeEventListener('resize', this.handleResize)
},
methods: {
handleResize () {
// 上下双表按可视区等分高度,避免底部留白
this.$nextTick(() => {
const pageRootEl = this.$refs.pageRoot || this.$el
const topTableVm = this.$refs.topTable
const topTableEl = topTableVm && topTableVm.$el
if (!pageRootEl || !topTableEl) {
return
}
const toolbarEl = pageRootEl.querySelector('.table-toolbar')
const toolbarRect = toolbarEl ? toolbarEl.getBoundingClientRect() : { height: 0 }
const toolbarStyle = toolbarEl ? window.getComputedStyle(toolbarEl) : null
const toolbarOuterHeight = toolbarEl
? toolbarRect.height + (parseFloat(toolbarStyle.marginTop) || 0) + (parseFloat(toolbarStyle.marginBottom) || 0)
: 0
const paginationEl = pageRootEl.querySelector('.main-pagination')
const paginationRect = paginationEl ? paginationEl.getBoundingClientRect() : { height: 0 }
const paginationStyle = paginationEl ? window.getComputedStyle(paginationEl) : null
const paginationOuterHeight = paginationEl
? paginationRect.height + (parseFloat(paginationStyle.marginTop) || 0) + (parseFloat(paginationStyle.marginBottom) || 0)
: 0
const rootStyle = window.getComputedStyle(pageRootEl)
const rootPaddingBottom = parseFloat(rootStyle.paddingBottom) || 0
const topTableTop = topTableEl.getBoundingClientRect().top
// 预留安全边距,避免双表总高度刚好贴边导致轻微超出
const viewportBottomGap = 24
const tablesAvailableHeight = window.innerHeight - topTableTop - paginationOuterHeight - toolbarOuterHeight - rootPaddingBottom - viewportBottomGap
const equalHeight = Math.floor(tablesAvailableHeight / 2)
const nextHeight = Number.isFinite(equalHeight) && equalHeight > 120 ? equalHeight : 260
this.topTableHeight = nextHeight
this.bottomTableHeight = nextHeight
})
},
getBaseList (val, type) {
this.tagNo = val
this.tagType = type || 'search'
this.$nextTick(() => {
let strVal = ''
let conSql = ''
if (val === 520) {
strVal = this.searchData.supplierNo || ''
conSql = " and site = '" + this.$store.state.user.site + "'"
}
// 快捷查询:供应商编号(520),仅用于查询筛选
this.$refs.baseList.init(val, strVal, conSql)
})
},
getBaseData (val) {
if (this.tagNo === 520 && this.tagType === 'search') {
this.searchData.supplierNo = val.supplier_no || ''
}
},
resetSearch () {
this.searchData = {
site: this.$store.state.user.site,
supplierNo: '',
partNo: '',
item: '',
sku: '',
partDesc: '',
active: ''
}
this.pageIndex = 1
this.totalPage = 0
this.supplierPartList = []
this.selectedSupplierPart = null
this.currentTierPriceList = []
},
searchSupplierPartList (resetPage = true) {
if (resetPage) {
this.pageIndex = 1
}
this.topLoading = true
const inData = {
site: this.$store.state.user.site,
supplierCode: (this.searchData.supplierNo || '').trim(),
partNo: (this.searchData.partNo || '').trim(),
item: (this.searchData.item || '').trim(),
sku: (this.searchData.sku || '').trim(),
partDesc: (this.searchData.partDesc || '').trim(),
active: this.searchData.active || '',
page: this.pageIndex,
limit: this.pageSize
}
listSupplierPartMoqPage(inData).then(({ data }) => {
if (data && data.code === 0) {
const pageData = data.page || {}
const rows = Array.isArray(pageData.list) ? pageData.list : (data.rows || [])
this.supplierPartList = rows.map(item => ({
...item,
moq: this.normalizeNumberValue(item.moq, 0),
moqColor: this.normalizeNumberValue(item.moqColor, 0),
qtyCarton: this.normalizeNumberValue(item.qtyCarton, 0)
}))
this.pageIndex = Number(pageData.currPage || this.pageIndex || 1)
this.pageSize = Number(pageData.pageSize || this.pageSize || 50)
this.totalPage = Number(pageData.totalCount || 0)
this.selectedSupplierPart = null
this.currentTierPriceList = []
if (this.supplierPartList.length > 0) {
this.$refs.topTable.setCurrentRow(this.supplierPartList[0])
this.handleTopRowClick(this.supplierPartList[0])
}
} else {
this.supplierPartList = []
this.totalPage = 0
this.$alert((data && data.msg) || '查询失败', '错误', { confirmButtonText: '确定' })
}
}).catch(() => {
this.$message.error('查询失败')
}).finally(() => {
this.topLoading = false
})
},
sizeChangeHandle (val) {
this.pageSize = val
this.pageIndex = 1
this.searchSupplierPartList(false)
},
currentChangeHandle (val) {
this.pageIndex = val
this.searchSupplierPartList(false)
},
handleTopRowClick (row) {
this.selectedSupplierPart = row ? JSON.parse(JSON.stringify(row)) : null
this.loadCurrentTierPrice()
},
loadCurrentTierPrice () {
if (!this.selectedSupplierPart) {
this.currentTierPriceList = []
return
}
this.bottomLoading = true
const inData = {
site: this.$store.state.user.site,
supplierCode: this.selectedSupplierPart.supplierCode,
partNo: this.selectedSupplierPart.partNo
}
listCurrentTierPrice(inData).then(({ data }) => {
if (data && data.code === 0) {
this.currentTierPriceList = (data.rows || []).map(item => ({
...item,
qtyStart: this.normalizeNumberValue(item.qtyStart, 0),
qtyEnd: this.normalizeNumberValue(item.qtyEnd, 0),
unitPrice: this.normalizeNumberValue(item.unitPrice, 0)
}))
} else {
this.currentTierPriceList = []
this.$alert((data && data.msg) || '获取当前阶梯价失败', '错误', { confirmButtonText: '确定' })
}
}).catch(() => {
this.currentTierPriceList = []
this.$message.error('获取当前阶梯价失败')
}).finally(() => {
this.bottomLoading = false
})
},
normalizeNumberValue (value, defaultValue = 0) {
if (value === null || value === undefined || value === '') return defaultValue
const num = Number(value)
if (Number.isNaN(num)) return defaultValue
return Object.is(num, -0) ? 0 : num
},
formatNumberCell (row, column, cellValue) {
return String(this.normalizeNumberValue(cellValue, 0))
}
}
}
</script>
<style scoped>
.supplier-part-moq-price .table-toolbar {
margin: 8px 0;
display: flex;
justify-content: space-between;
align-items: center;
}
.supplier-part-moq-price .selected-text {
font-size: 13px;
color: #606266;
}
</style>

580
src/views/modules/supplier/supplierPartNewProductAuditView.vue

@ -0,0 +1,580 @@
<template>
<div ref="pageRoot" class="customer-css supplier-part-new-product-audit">
<el-form :inline="true" label-position="top" class="pi-search-form">
<el-form-item>
<span slot="label" @click="getBaseList(520)"><a href="javascript:void(0)">供应商编号</a></span>
<el-input
v-model="searchData.supplierCode"
placeholder="选择或输入编号"
style="width: 180px"
clearable
@keyup.enter.native="searchSupplierPartList"
/>
</el-form-item>
<el-form-item label="产品编码">
<el-input
v-model="searchData.partNo"
placeholder="产品编码"
style="width: 160px"
clearable
@keyup.enter.native="searchSupplierPartList"
/>
</el-form-item>
<el-form-item label="Item">
<el-input
v-model="searchData.item"
placeholder="Item"
style="width: 140px"
clearable
@keyup.enter.native="searchSupplierPartList"
/>
</el-form-item>
<el-form-item label="SKU">
<el-input
v-model="searchData.sku"
placeholder="SKU"
style="width: 140px"
clearable
@keyup.enter.native="searchSupplierPartList"
/>
</el-form-item>
<el-form-item label="物料名称">
<el-input
v-model="searchData.partDesc"
placeholder="物料名称"
style="width: 180px"
clearable
@keyup.enter.native="searchSupplierPartList"
/>
</el-form-item>
<el-form-item label="是否完成新品审核">
<el-select v-model="searchData.newProductAudited" style="width: 120px" clearable>
<el-option label="是" value="Y" />
<el-option label="否" value="N" />
</el-select>
</el-form-item>
<el-form-item label="当前是否需要审核">
<el-select v-model="searchData.needNewProductAudit" style="width: 120px" clearable>
<el-option label="是" value="Y" />
<el-option label="否" value="N" />
</el-select>
</el-form-item>
<el-form-item label="是否需要提交测试">
<el-select v-model="searchData.needSubmitTest" style="width: 120px" clearable>
<el-option label="是" value="Y" />
<el-option label="否" value="N" />
</el-select>
</el-form-item>
<el-form-item label=" ">
<el-button
type="primary"
class="customer-bun-min"
:loading="mainLoading"
@click="searchSupplierPartList"
>查询</el-button>
<el-button class="customer-bun-min" @click="resetSearch">重置</el-button>
</el-form-item>
</el-form>
<el-table
ref="mainTable"
:data="supplierPartList"
:height="mainTableHeight"
border
stripe
highlight-current-row
v-loading="mainLoading"
style="width: 100%"
empty-text="点击查询查看数据"
@row-click="handleMainRowClick"
>
<el-table-column prop="supplierCode" label="供应商编号" min-width="80" header-align="center" align="center" />
<el-table-column prop="supplierName" label="供应商名称" min-width="180" header-align="center" align="left" show-overflow-tooltip />
<el-table-column prop="partNo" label="产品编码" min-width="100" header-align="center" align="center" />
<el-table-column prop="item" label="Item" min-width="100" header-align="center" align="center" show-overflow-tooltip />
<el-table-column prop="sku" label="SKU" min-width="100" header-align="center" align="center" show-overflow-tooltip />
<el-table-column prop="partDesc" label="物料名称" min-width="200" header-align="center" align="left" show-overflow-tooltip />
<el-table-column label="新品审核" min-width="80" header-align="center" align="center">
<template slot-scope="scope">
<span>{{ scope.row.newProductAudited === 'Y' ? '是' : '否' }}</span>
</template>
</el-table-column>
<el-table-column label="当前需要审核" min-width="100" header-align="center" align="center">
<template slot-scope="scope">
<span>{{ scope.row.needNewProductAudit === 'Y' ? '是' : '否' }}</span>
</template>
</el-table-column>
<el-table-column label="需要提交测试" min-width="100" header-align="center" align="center">
<template slot-scope="scope">
<span>{{ scope.row.needSubmitTest === 'Y' ? '是' : '否' }}</span>
</template>
</el-table-column>
<el-table-column label="审核状态" min-width="80" header-align="center" align="center">
<template slot-scope="scope">
<span>{{ formatLatestAuditStatus(scope.row.latestAuditStatus) }}</span>
</template>
</el-table-column>
</el-table>
<el-pagination
class="main-pagination"
style="margin-top: 6px"
@size-change="sizeChangeHandle"
@current-change="currentChangeHandle"
:current-page="pageIndex"
:page-sizes="[20, 50, 100, 200, 500]"
:page-size="pageSize"
:total="totalPage"
layout="total, sizes, prev, pager, next, jumper"
/>
<el-tabs v-model="activeTab" class="detail-tabs">
<el-tab-pane label="审核记录" name="audit">
<el-table
ref="auditTable"
:data="auditRecordList"
:height="detailTableHeight"
border
stripe
v-loading="auditLoading"
style="width: 100%"
empty-text="请选择上方供应商物料后查看审核记录"
>
<el-table-column prop="auditRoundNo" label="审核轮次" min-width="90" header-align="center" align="center" />
<el-table-column label="部门" min-width="100" header-align="center" align="center">
<template slot-scope="scope">
<span>{{ formatDeptType(scope.row.deptType) }}</span>
</template>
</el-table-column>
<el-table-column label="状态" min-width="100" header-align="center" align="center">
<template slot-scope="scope">
<span>{{ formatAuditStatus(scope.row.status) }}</span>
</template>
</el-table-column>
<el-table-column label="审核结论" min-width="100" header-align="center" align="center">
<template slot-scope="scope">
<span>{{ formatAuditResult(scope.row.auditResult) }}</span>
</template>
</el-table-column>
<el-table-column label="需要测试" min-width="90" header-align="center" align="center">
<template slot-scope="scope">
<span>{{ scope.row.needTest === 'Y' ? '是' : '否' }}</span>
</template>
</el-table-column>
<el-table-column prop="auditOpinion" label="审核意见" min-width="220" header-align="center" align="left" show-overflow-tooltip />
<el-table-column prop="auditor" label="审核人" min-width="120" header-align="center" align="center" />
<el-table-column prop="auditTime" label="审核时间" min-width="160" header-align="center" align="center" />
</el-table>
</el-tab-pane>
<el-tab-pane label="测试记录" name="test">
<el-table
ref="testTable"
:data="testRecordList"
:height="detailTableHeight"
border
stripe
v-loading="testLoading"
style="width: 100%"
empty-text="请选择上方供应商物料后查看测试记录"
>
<el-table-column prop="submitTime" label="提交日期" min-width="120" header-align="center" align="center" :formatter="formatDateOnlyCell" />
<el-table-column prop="testTime" label="测试日期" min-width="120" header-align="center" align="center" :formatter="formatDateOnlyCell" />
<el-table-column prop="tester" label="测试人" min-width="120" header-align="center" align="center" />
<el-table-column label="测试结果" min-width="100" header-align="center" align="center">
<template slot-scope="scope">
<span>{{ formatTestResult(scope.row.testResult) }}</span>
</template>
</el-table-column>
<el-table-column prop="remark" label="备注" min-width="220" header-align="center" align="left" show-overflow-tooltip />
<el-table-column label="操作" width="100" header-align="center" align="center" fixed="right">
<template slot-scope="scope">
<el-link style="cursor: pointer" @click.stop="openTestAttachmentList(scope.row)">测试附件</el-link>
</template>
</el-table-column>
</el-table>
</el-tab-pane>
</el-tabs>
<el-dialog title="测试附件清单" :close-on-click-modal="false" v-drag :visible.sync="testAttachmentDialogVisible" width="860px">
<el-table :height="360" :data="testAttachmentFileList" border v-loading="testAttachmentLoading" style="width: 100%">
<el-table-column prop="fileName" label="文件名称" min-width="300" show-overflow-tooltip />
<el-table-column prop="createdBy" label="上传人" width="120" align="center" />
<el-table-column prop="createDate" label="上传时间" width="180" align="center" />
<el-table-column prop="cadditionalInfo" label="备注" min-width="180" show-overflow-tooltip />
<el-table-column label="操作" width="90" align="center" fixed="right">
<template slot-scope="scope">
<el-link type="primary" @click="previewTestAttachmentFile(scope.row)">查看</el-link>
</template>
</el-table-column>
</el-table>
<el-footer style="height:40px;margin-top: 10px;text-align:center">
<el-button type="primary" @click="testAttachmentDialogVisible = false">关闭</el-button>
</el-footer>
</el-dialog>
<Chooselist ref="baseList" @getBaseData="getBaseData" />
</div>
</template>
<script>
import Chooselist from '@/views/modules/common/Chooselist_eam'
import {
listNewProductAuditSupplierPartPage,
listNewProductAuditRecord,
listNewProductTestRecord
} from '@/api/supplier/supplierPartNewProductAudit'
import {
queryOssFilePlus,
previewOssFileById
} from '@/api/oss/oss'
export default {
name: 'SupplierPartNewProductAuditView',
components: { Chooselist },
data () {
return {
searchData: {
site: this.$store.state.user.site,
supplierCode: '',
partNo: '',
item: '',
sku: '',
partDesc: '',
newProductAudited: 'N',
needNewProductAudit: '',
needSubmitTest: ''
},
mainLoading: false,
auditLoading: false,
testLoading: false,
pageIndex: 1,
pageSize: 50,
totalPage: 0,
supplierPartList: [],
selectedSupplierPart: null,
activeTab: 'audit',
auditRecordList: [],
testRecordList: [],
mainTableHeight: 300,
detailTableHeight: 260,
testAttachmentDialogVisible: false,
testAttachmentLoading: false,
testAttachmentCurrentRow: null,
testAttachmentFileList: []
}
},
mounted () {
// 只读查询页:初始化不自动查询,需手动点击查询
this.handleResize()
window.addEventListener('resize', this.handleResize)
},
beforeDestroy () {
window.removeEventListener('resize', this.handleResize)
},
methods: {
handleResize () {
this.$nextTick(() => {
const pageRootEl = this.$refs.pageRoot || this.$el
const mainTableVm = this.$refs.mainTable
const mainTableEl = mainTableVm && mainTableVm.$el
if (!pageRootEl || !mainTableEl) {
return
}
const toolbarEl = pageRootEl.querySelector('.table-toolbar')
const tabsHeaderEl = pageRootEl.querySelector('.detail-tabs .el-tabs__header')
const tabToolbarEl = pageRootEl.querySelector('.detail-tabs .tab-toolbar')
const paginationEl = pageRootEl.querySelector('.main-pagination')
const toolbarHeight = toolbarEl ? toolbarEl.getBoundingClientRect().height : 0
const tabsHeaderHeight = tabsHeaderEl ? tabsHeaderEl.getBoundingClientRect().height : 40
const tabToolbarHeight = tabToolbarEl ? tabToolbarEl.getBoundingClientRect().height : 0
const paginationRect = paginationEl ? paginationEl.getBoundingClientRect() : { height: 0 }
const paginationStyle = paginationEl ? window.getComputedStyle(paginationEl) : null
const paginationOuterHeight = paginationEl
? paginationRect.height + (parseFloat(paginationStyle.marginTop) || 0) + (parseFloat(paginationStyle.marginBottom) || 0)
: 0
const rootStyle = window.getComputedStyle(pageRootEl)
const rootPaddingBottom = parseFloat(rootStyle.paddingBottom) || 0
const topOffset = mainTableEl.getBoundingClientRect().top
const viewportBottomGap = 24
const availableHeight = window.innerHeight - topOffset - paginationOuterHeight - toolbarHeight - rootPaddingBottom - viewportBottomGap
const mainHeight = Math.max(220, Math.floor(availableHeight * 0.42))
const detailHeight = Math.max(220, Math.floor(availableHeight - mainHeight - tabsHeaderHeight - tabToolbarHeight - 24))
this.mainTableHeight = mainHeight
this.detailTableHeight = detailHeight
this.refreshTableLayout()
})
},
refreshTableLayout () {
this.$nextTick(() => {
if (this.$refs.mainTable) this.$refs.mainTable.doLayout()
if (this.$refs.auditTable) this.$refs.auditTable.doLayout()
if (this.$refs.testTable) this.$refs.testTable.doLayout()
})
},
getBaseList (tagNo) {
this.$nextTick(() => {
let strVal = ''
let conSql = ''
if (tagNo === 520) {
strVal = this.searchData.supplierCode || ''
conSql = " and site = '" + this.$store.state.user.site + "'"
}
this.$refs.baseList.init(tagNo, strVal, conSql)
})
},
getBaseData (val) {
if (!val) return
this.searchData.supplierCode = val.supplier_no || ''
},
resetSearch () {
this.searchData = {
site: this.$store.state.user.site,
supplierCode: '',
partNo: '',
item: '',
sku: '',
partDesc: '',
newProductAudited: '',
needNewProductAudit: '',
needSubmitTest: ''
}
this.pageIndex = 1
this.totalPage = 0
this.supplierPartList = []
this.selectedSupplierPart = null
this.auditRecordList = []
this.testRecordList = []
this.refreshTableLayout()
},
searchSupplierPartList (resetPage = true) {
if (resetPage) {
this.pageIndex = 1
}
const payload = {
site: this.$store.state.user.site,
supplierCode: (this.searchData.supplierCode || '').trim(),
partNo: (this.searchData.partNo || '').trim(),
item: (this.searchData.item || '').trim(),
sku: (this.searchData.sku || '').trim(),
partDesc: (this.searchData.partDesc || '').trim(),
newProductAudited: this.searchData.newProductAudited || '',
needNewProductAudit: this.searchData.needNewProductAudit || '',
needSubmitTest: this.searchData.needSubmitTest || '',
page: this.pageIndex,
limit: this.pageSize
}
this.mainLoading = true
listNewProductAuditSupplierPartPage(payload).then(({ data }) => {
if (data && data.code === 0) {
const pageData = data.page || {}
this.supplierPartList = Array.isArray(pageData.list) ? pageData.list : (data.rows || [])
this.pageIndex = Number(pageData.currPage || this.pageIndex || 1)
this.pageSize = Number(pageData.pageSize || this.pageSize || 50)
this.totalPage = Number(pageData.totalCount || 0)
if (!this.supplierPartList.length) {
this.selectedSupplierPart = null
this.auditRecordList = []
this.testRecordList = []
return
}
const previousKey = this.selectedSupplierPart
? `${this.selectedSupplierPart.site || ''}-${this.selectedSupplierPart.supplierCode || ''}-${this.selectedSupplierPart.partNo || ''}`
: ''
const matched = this.supplierPartList.find(item =>
`${item.site || ''}-${item.supplierCode || ''}-${item.partNo || ''}` === previousKey
)
const target = matched || this.supplierPartList[0]
this.handleMainRowClick(target)
} else {
this.$message.error((data && data.msg) || '加载供应商可供物料失败')
this.supplierPartList = []
this.totalPage = 0
this.selectedSupplierPart = null
this.auditRecordList = []
this.testRecordList = []
}
}).catch(() => {
this.$message.error('加载供应商可供物料失败')
this.supplierPartList = []
this.totalPage = 0
this.selectedSupplierPart = null
this.auditRecordList = []
this.testRecordList = []
}).finally(() => {
this.mainLoading = false
this.refreshTableLayout()
})
},
sizeChangeHandle (val) {
this.pageSize = val
this.pageIndex = 1
this.searchSupplierPartList(false)
},
currentChangeHandle (val) {
this.pageIndex = val
this.searchSupplierPartList(false)
},
handleMainRowClick (row) {
if (!row) return
this.selectedSupplierPart = row
this.$nextTick(() => {
if (this.$refs.mainTable) {
this.$refs.mainTable.setCurrentRow(row)
}
})
this.fetchAuditRecordList()
this.fetchTestRecordList()
},
fetchAuditRecordList () {
if (!this.selectedSupplierPart) {
this.auditRecordList = []
return
}
this.auditLoading = true
listNewProductAuditRecord({
site: this.selectedSupplierPart.site,
supplierCode: this.selectedSupplierPart.supplierCode,
partNo: this.selectedSupplierPart.partNo
}).then(({ data }) => {
if (data && data.code === 0) {
this.auditRecordList = data.rows || []
} else {
this.auditRecordList = []
this.$message.error((data && data.msg) || '加载审核记录失败')
}
}).catch(() => {
this.auditRecordList = []
this.$message.error('加载审核记录失败')
}).finally(() => {
this.auditLoading = false
this.refreshTableLayout()
})
},
fetchTestRecordList () {
if (!this.selectedSupplierPart) {
this.testRecordList = []
return
}
this.testLoading = true
listNewProductTestRecord({
site: this.selectedSupplierPart.site,
supplierCode: this.selectedSupplierPart.supplierCode,
partNo: this.selectedSupplierPart.partNo
}).then(({ data }) => {
if (data && data.code === 0) {
this.testRecordList = data.rows || []
} else {
this.testRecordList = []
this.$message.error((data && data.msg) || '加载测试记录失败')
}
}).catch(() => {
this.testRecordList = []
this.$message.error('加载测试记录失败')
}).finally(() => {
this.testLoading = false
this.refreshTableLayout()
})
},
buildTestAttachmentQueryParams (row) {
return {
orderRef1: row.site || '',
orderRef2: row.supplierCode || '',
orderRef3: row.partNo || '',
orderRef4: String(row.id || ''),
orderReftype: 'SUPPLIER_PART_NEW_PRODUCT_TEST'
}
},
openTestAttachmentList (row) {
if (!row || !row.id) {
this.$message.warning('测试记录无效')
return
}
this.testAttachmentCurrentRow = {
id: row.id,
site: row.site,
supplierCode: row.supplierCode,
partNo: row.partNo
}
this.testAttachmentDialogVisible = true
this.fetchTestAttachmentFileList()
},
fetchTestAttachmentFileList () {
if (!this.testAttachmentCurrentRow) {
this.testAttachmentFileList = []
return
}
this.testAttachmentLoading = true
queryOssFilePlus(this.buildTestAttachmentQueryParams(this.testAttachmentCurrentRow)).then(({ data }) => {
if (data && data.code === 0) {
this.testAttachmentFileList = data.rows || []
} else {
this.testAttachmentFileList = []
}
}).catch(() => {
this.testAttachmentFileList = []
}).finally(() => {
this.testAttachmentLoading = false
})
},
previewTestAttachmentFile (row) {
previewOssFileById({ id: row.id }).then((response) => {
const contentType = (response.headers && response.headers['content-type']) || 'application/octet-stream'
const blob = new Blob([response.data], { type: contentType })
const link = document.createElement('a')
link.href = URL.createObjectURL(blob)
link.setAttribute('download', row.fileName)
link.target = '_blank'
link.click()
URL.revokeObjectURL(link.href)
})
},
formatLatestAuditStatus (status) {
const val = (status || 'NONE').toUpperCase()
if (val === 'IN_PROGRESS') return '审核中'
if (val === 'REJECTED') return '不通过'
if (val === 'APPROVED') return '已通过'
return '未发起'
},
formatDeptType (deptType) {
const val = (deptType || '').toUpperCase()
if (val === 'PURCHASE') return '采购部门'
if (val === 'QUALITY') return '质量部门'
return deptType || ''
},
formatAuditStatus (status) {
const val = (status || '').toUpperCase()
if (val === 'PENDING') return '待审核'
if (val === 'DONE') return '已审核'
return status || ''
},
formatAuditResult (result) {
const val = (result || '').toUpperCase()
if (val === 'AGREE') return '同意'
if (val === 'REJECT') return '不同意'
return ''
},
formatTestResult (result) {
const val = (result || '').toUpperCase()
if (val === 'PASS') return '通过'
if (val === 'FAIL') return '不通过'
return result || ''
},
formatDateOnlyCell (row, column, cellValue) {
return this.getDatePart(cellValue)
},
getDatePart (value) {
if (!value) return ''
const raw = String(value).trim()
if (!raw) return ''
return raw.length >= 10 ? raw.substring(0, 10) : raw
}
}
}
</script>
<style scoped>
.supplier-part-new-product-audit .detail-tabs {
margin-top: 6px;
}
</style>

8
src/views/modules/sys/user-add-or-update.vue

@ -182,12 +182,10 @@ export default {
let strVal = ""; let strVal = "";
let conSql = ""; let conSql = "";
if (val === 520) { if (val === 520) {
if (!this.dataForm.site) {
this.$message.warning('请先选择工厂')
return
}
strVal = this.dataForm.supplierNo || '' strVal = this.dataForm.supplierNo || ''
conSql = " and site = '" + this.dataForm.site + "'"
// site 过滤由 Chooselist 组件内部按当前登录用户 site(param4=this.$store.state.user.site)自动追加,
// 与 supplierList.vue 选择供应商编码的逻辑保持一致,只能查到当前 site 下的供应商;
// 此处不再传基于 dataForm.site 的 conSql,否则会与内置 site 条件冲突导致查不到数据。
} }
this.$refs.baseList.init(val,strVal,conSql) this.$refs.baseList.init(val,strVal,conSql)
}) })

Loading…
Cancel
Save