<template>
<a-card :bordered="false" :class="{isShowStyle: indirectFlag}">
<!-- 查询区域 -->
<div class="table-page-search-wrapper" v-if="!indirectFlag">
<a-form layout="inline" @keyup.enter.native="searchQuery">
<a-row :gutter='24'>
<a-col :span='8'>
<a-form-item label='主机厂'>
<a-input v-model.trim='queryParam.oems' placeholder='请输入主机厂名称'></a-input>
</a-form-item>
</a-col>
<a-col :span='8'>
<a-form-item label='客户名称'>
<a-input v-model.trim='queryParam.endUser' placeholder='请输入客户名称'></a-input>
</a-form-item>
</a-col>
<a-col :span='8'>
<span style='float: left;overflow: hidden;' class='table-page-search-submitButtons'>
<a-button type='primary' @click='searchQuery' icon='search'>查询</a-button>
<a-button type='primary' @click='reset' icon='reload' style='margin-left: 8px'>重置</a-button>
</span>
</a-col>
</a-row>
</a-form>
</div>
<!-- 查询区域-END -->
<!-- 操作按钮区域 -->
<div class="table-operator">
<!-- <a-button @click="handleAdd" type="primary" icon="plus" v-if="indirectModal" :disabled="hiddenFlag">新增-->
<!-- </a-button>-->
<a-upload v-if="!hiddenFlag" name="file" :showUploadList="false" :multiple="false" :headers="tokenHeader" :action="importExcelUrl"
@change="handleImportExcel">
<a-button type="primary" icon="import" :disabled="hiddenFlag">导入</a-button>
</a-upload>
<!-- <a-button icon='link' type='primary' @click='outmb' v-if="indirectModal" :disabled="hiddenFlag">-->
<!-- 导入模板-->
<!-- </a-button>-->
<a-button icon='link' type='primary' @click='outmb1' :disabled="hiddenFlag">
导入模板
</a-button>
<a-button type="primary" @click="bacthSave" v-if="indirectModal" :disabled="hiddenFlag">保存</a-button>
<a-button type="primary" @click="subStatus" v-if="indirectModal" :disabled="hiddenFlag">提交</a-button>
<a-dropdown v-if='selectedRowKeys.length > 0'>
<a-menu slot='overlay'>
<a-menu-item key='1' @click='batchDelete'>
<a-icon type='delete' />
删除
</a-menu-item>
</a-menu>
<a-button style='margin-left: 8px'> 批量操作
<a-icon type='down' />
</a-button>
</a-dropdown>
</div>
<!-- table区域-begin -->
<div>
<!-- <div class="ant-alert ant-alert-info" style="margin-bottom: 16px;">-->
<!-- <i class="anticon anticon-info-circle ant-alert-icon"></i> 已选择 <a-->
<!-- style="font-weight: 600">{{ selectedRowKeys.length }}</a>项-->
<!-- <a style="margin-left: 24px" @click="onClearSelected">清空</a>-->
<!-- </div>-->
<j-editable-table
v-if="indirectModal"
ref="editableTable"
size="middle"
bordered
rowKey="id"
:columns="dynamicColumns"
:dataSource="dataSource"
:rowNumber="true"
:pagination="ipagination"
:loading="loading"
:rowSelection="{selectedRowKeys: selectedRowKeys, onChange: onSelectChange}"
class="j-table-force-nowrap"
:actionButton="true"
:disabledRows="{ status:1}"
@change="handleTableChange">
<template v-slot:oemsSlot="props">
<a-input
v-model='props.text'
placeholder='请输入主机厂'
:disabled="isDisabled(props)"
@input="oemsInput(props)">
<a-icon slot='prefix' type='cluster' @click.stop='handleOemsClick(props)'/>
</a-input>
</template>
<template v-slot:productSearchSlot="props">
<a-select
v-model="props.text"
show-search
placeholder="请选择产品名称"
:default-active-first-option="false"
:show-arrow="false"
:filter-option="false"
:not-found-content="null"
style="width: 100%"
@search="handleProductSearch"
@change="handleProductChange(props)"
>
<a-select-option v-for="item in productList" :key="item.value" :value="item.value">
{{ item.text }}
</a-select-option>
</a-select>
</template>
<template v-slot:productSlot="props">
<j-search-select-tag v-model="props.text" placeholder="请选择产品名称" dict="bs_inventory GROUP BY cInvName, cInvName, cInvName" />
</template>
<template v-slot:publishSlot="props">
<div>
<a-input-search
v-model="props.text"
placeholder="请先选择用户"
readOnly
unselectable="on"
@search="onSearchDepUser(props)">
<a-button slot="enterButton" :disabled="false">选择用户</a-button>
</a-input-search>
<j-select-user-by-dep-modal ref="selectModal" modal-width="80%" :multi="false" @ok="selectOK" :user-ids="props.value" @initComp="initComp"/>
</div>
</template>
<span slot='titleSlot' slot-scope='text'>
<j-ellipsis :value='text' :length='40'/>
</span>
</j-editable-table>
<a-table
v-else
ref="table"
size="middle"
bordered
rowKey="id"
:columns="columns"
:dataSource="dataSource"
:pagination="ipagination"
:loading="loading"
:rowSelection="{selectedRowKeys: selectedRowKeys, onChange: onSelectChange}"
class="j-table-force-nowrap"
@change="handleTableChange">
<span slot='titleSlot' slot-scope='text'>
<j-ellipsis :value='text' :length='40'/>
</span>
<span slot="action" slot-scope="text, record">
<a @click="handleEdit(record)"
:disabled="!record.editBtn">编辑</a>
<a-divider type="vertical"/>
<a-popconfirm title="确定删除吗?" @confirm="() => handleDelete(record.id)">
<a :disabled="!record.editBtn">删除</a>
</a-popconfirm>
</span>
</a-table>
</div>
<indirectBusinessProducts-modal ref="modalForm" :indirectModal="indirectModal"
@ok="modalFormOk"></indirectBusinessProducts-modal>
<indirectBusinessProducts-item-modal ref="modalItemForm" @ok="modalFormOk"></indirectBusinessProducts-item-modal>
<a-modal
title='客户名称(主机厂)'
:width='1000'
:visible='cusVisible'
@ok='handleCusSubmit'
@cancel='closeCusModal'
cancelText='关闭'>
<cus-component ref='cusComponent'></cus-component>
</a-modal>
</a-card>
</template>
<script>
import '@/assets/less/TableExpand.less'
import {mixinDevice} from '@/utils/mixin'
import {JeecgListMixin} from '@/mixins/JeecgListMixin'
import IndirectBusinessProductsModal from './modules/IndirectBusinessProductsModal'
import JEllipsis from "../../../components/jeecg/JEllipsis.vue";
import IndirectBusinessProductsItemModal from "./modules/IndirectBusinessProductsItemModal.vue";
import {deleteAction, downFile, getAction, postAction, putAction} from "../../../api/manage";
import {filterDictText, initDictOptions} from '@/components/dict/JDictSelectUtil'
import {FormTypes} from '@/utils/JEditableTableUtil'
import JEditableTable from "@comp/jeecg/JEditableTable.vue";
import CusComponent from "@views/modules/eoa/plan/components/CusComponent.vue";
import JSelectUserByDep from "@comp/jeecgbiz/JSelectUserByDep.vue";
import JSelectUserByDepModal from "@comp/jeecgbiz/modal/JSelectUserByDepModal.vue";
import JSearchSelectTag from "@comp/dict/JSearchSelectTag.vue";
export default {
name: "IndirectBusinessProductsList",
mixins: [JeecgListMixin, mixinDevice],
components: {
JSearchSelectTag,
JSelectUserByDepModal,
JSelectUserByDep,
CusComponent,
JEditableTable,
IndirectBusinessProductsItemModal,
JEllipsis,
IndirectBusinessProductsModal
},
props: {
indirectFlag: {
type: Boolean,
default: false
},
indirectModal: {
type: Object,
default: () => {
}
},
hiddenFlag: {
type: Boolean,
default: false
},
},
data() {
return {
usernames: null,
value: null,
userIds: null,
description: 'indirect_business_products管理页面',
statusDictOptions: [],
busType: 'my',
cusVisible: false,
// 表头
columns: [
{
title: '#',
dataIndex: '',
key: 'rowIndex',
width: 60,
align: "center",
customRender: function (t, r, index) {
return parseInt(index) + 1;
}
},
// {
// title: '客户名称(主机厂)',
// align: "center",
// dataIndex: 'oems'
// },
{
title: '客户名称',
align: "center",
dataIndex: 'endUser'
},
{
title: '终端用户',
align: "center",
dataIndex: 'oems',
scopedSlots: {customRender: 'titleSlot'},
width: 100
},
{
title: '车型(米)',
align: "center",
dataIndex: 'carType',
customRender: (text, record, index) => {
//字典值替换通用方法
return filterDictText(this.vehicleModelOptions, text);
}
},
{
title: '产品明细',
align: "center",
scopedSlots: {customRender: 'titleSlot'},
dataIndex: 'productDetails'
},
{
title: '发布数量',
align: "center",
dataIndex: 'number'
},
{
title: '预测金额',
align: "center",
dataIndex: 'redictedAmount'
},
{
title: '发布人',
align: "center",
dataIndex: 'publishName'
},
{
title: '发布时间',
align: "center",
dataIndex: 'publishTime',
customRender: function (text) {
return !text ? "" : (text.length > 10 ? text.substr(0, 10) : text)
}
},
{
title: '产品类型',
align: "center",
dataIndex: 'productType',
customRender: (text, record, index) => {
//字典值替换通用方法
return filterDictText(this.productTypeOptions, text);
}
},
// {
// title: '产品大类',
// align: "center",
// dataIndex: 'productCategories'
// },
{
title: '提交状态',
align: "center",
dataIndex: 'status',
customRender: (text, record, index) => {
//字典值替换通用方法
return filterDictText(this.statusDictOptions, text);
}
},
{
title: '操作',
dataIndex: 'action',
align: "center",
// fixed:"right",
width: 147,
scopedSlots: {customRender: 'action'}
}
],
url: {
list: "/indirect_business/products/list",
delete: "/indirect_business/products/delete",
deleteBatch: "/indirect_business/products/deleteBatch",
setStatus: "/indirect_business/products/setStatus",
batchAdd: "/indirect_business/products/batchAdd",
teamExcelTemplate: "indirect_business/indirectBusiness/teamExcelTemplate",
teamExcelTemplateProduct: "indirect_business/indirectBusiness/teamExcelTemplateProduct",
importExcelUrl: "indirect_business/products/importExcel",
},
dictOptions: {},
queryParam:{
status:'1'
},
productList: [],//储存产品信息列表
currentClickRowId: null, // 存储当前点击的行ID
}
},
computed: {
importExcelUrl: function () {
if (!this.indirectModal) {
return `${window._CONFIG['domianURL']}/${this.url.importExcelUrl}`;
} else {
return `${window._CONFIG['domianURL']}/${this.url.importExcelUrl}?busId=${this.indirectModal.busId}&endUser=${this.indirectModal.endCustomer}`;
}
},
getLoginUsername() {
return this.$store.getters.userInfo.username;
},
loginPermissions() {
return this.indirectModal.helpPerson.includes(this.$store.getters.userInfo.username);
},
rowSelection() {
return {
onChange: (selectedRowKeys, selectedRows) => {
this.onSelectChange(selectedRowKeys, selectedRows);
},
getCheckboxProps: record => ({
props: {
disabled: record.status === 1 || record.status === null
},
}),
};
},
dynamicColumns() {
const baseColumns = [
{
title: "busId",
align: "center",
key: "busId",
type: FormTypes.hidden,
defaultValue: this.indirectModal.busId
},
// 动态客户名称列
{
title: this.indirectModal.category === '1' ? '客户名称' : '终端客户名称',
align: "center",
key: 'endUser',
type: FormTypes.input,
placeholder: '请输入客户名称',
disabled: true,
defaultValue: this.indirectModal.endCustomer,
width: '220px'
}
];
if (this.indirectModal.category === '2'){
baseColumns.push({
title: '主机厂',
align: "center",
key: 'oems',
placeholder: "请选择主机厂",
type: FormTypes.slot,
slotName: 'oemsSlot',
validateRules: this.indirectModal.category === '2' ? [
{
required: true,
message: '主机厂不能为空'
},
{
validator: (rule, value, callback) => {
if (value === '' || value === null || value === undefined) {
callback(new Error('请选择主机厂')); // 配合 required 使用
}
}
}
] : [],
width: '220px',
});
}
baseColumns.push({
title: '车型(米)',
align: "center",
key: 'carType',
type: FormTypes.select,
dictCode: 'vehicle_model',
placeholder: '请选择车型',
customRender: (text, record, index) => {
//字典值替换通用方法
return filterDictText(this.vehicleModelOptions, text);
},
width: '150px'
})
baseColumns.push({
title: '产品名称',
align: "center",
key: 'productDetails',
placeholder: "请选择产品名称",
type: FormTypes.slot,
slotName: 'productSearchSlot',
width: '240px'
})
baseColumns.push({
title: '发布数量',
align: "center",
key: 'number',
type: FormTypes.input,
inputType: 'number',
placeholder: "请输入发布数量",
validateRules: [
{
pattern: /^[1-9]\d*$/, // 正整数正则
message: '发布数量必须是正整数'
}
],
width: '150px'
})
baseColumns.push({
title: '预测金额',
align: "center",
key: 'redictedAmount',
type: FormTypes.input,
inputType: 'number',
placeholder: "请输入预测金额",
// 动态校验规则(category == '2' 时必填且必须为正数)
validateRules: this.indirectModal.category === '2' ? [
{
required: true,
message: '预测金额不能为空',
trigger: ['blur', 'change'] // 触发校验的时机
},
{
pattern: /^(0|[1-9]\d*)(\.\d+)?$/, // 正整数正则
message: '发布数量必须是正数'
}
] : [],
width: '150px'
})
if (this.indirectModal.category === '2'){
baseColumns.push({
title: '主机厂负责人',
align: "center",
key: 'oemResponsiblePerson',
type: FormTypes.hidden,
});
}
// if (this.indirectModal.category === '2'){
// baseColumns.push({
// title: '主机厂负责人',
// align: "center",
// key: 'oemResponsiblePersonName',
// type: FormTypes.input,
// disabled: true,
// width: '200px'
// });
// }
baseColumns.push({
title: '发布人',
align: "center",
key: 'publishBy',
type: FormTypes.hidden,
defaultValue: this.$store.getters.userInfo.username,
placeholder: "请选择发布人",
width: '240px'
})
baseColumns.push({
title: '发布人',
align: "center",
key: 'publishName',
type: FormTypes.slot,
slotName: 'publishSlot',
defaultValue: this.$store.getters.userInfo.realname,
placeholder: "请选择发布人",
width: '240px'
})
baseColumns.push({
title: '发布时间',
align: "center",
key: 'publishTime',
type: FormTypes.date,
customRender: function (text) {
return !text ? "" : (text.length > 10 ? text.substr(0, 10) : text)
},
defaultValue: this.formatDate(new Date()),
width: '170px'
})
baseColumns.push({
title: '产品类型',
align: "center",
key: 'productType',
placeholder: "请选择产品类型",
type: FormTypes.select,
dictCode: 'product_type',
customRender: (text, record, index) => {
//字典值替换通用方法
return filterDictText(this.productTypeOptions, text);
},
defaultValue: '0',
width: '130px'
})
baseColumns.push({
title: '提交状态',
align: "center",
key: 'status',
type: FormTypes.select,
dictCode: 'public_status',
customRender: (text, record, index) => {
//字典值替换通用方法
return filterDictText(this.statusDictOptions, text);
},
defaultValue: '0',
disabled: true,
width: '130px'
})
return baseColumns;
},
},
methods: {
initDictConfig() {
getAction('/base/bsInventory/distinctAllList',null).then((res) => {
if (res.success) {
this.productList = res.result.map(item => ({
text: item.cinvname,
value: item.cinvname
}))
}
})
//判断查询条件
if (!this.indirectModal){
this.queryParam.status = 1
this.loadData(1)
}else{
this.queryParam.busId = this.indirectModal.busId
this.queryParam.status = ''
this.loadData(1)
}
console.log('this.queryParam.status',this.queryParam.status)
initDictOptions('public_status').then((res) => {
if (res.success) {
this.statusDictOptions = res.result
}
})
initDictOptions('vehicle_model').then((res) => {
if (res.success) {
this.vehicleModelOptions = res.result
}
})
initDictOptions('product_type').then((res) => {
if (res.success) {
this.productTypeOptions = res.result
}
})
},
// 产品名称远程搜索
handleProductSearch(value) {
if (!value) return; // 空输入不查询
// 调用接口查询匹配的产品
getAction('/base/bsInventory/distinctAllList', {
'cinvname': value
}).then(res => {
if (res.success) {
this.productList = res.result.map(item => ({
text: item.cinvname,
value: item.cinvname
}));
}
});
},
handleProductChange(props) {
// 存储当前点击的行记录和ID
this.currentClickRowId = props.rowId;
this.$refs.editableTable.setValues([{
rowKey: this.currentClickRowId,
values: {
'productDetails': props.text
}
}]);
},
outmb() {
downFile(this.url.teamExcelTemplate, '').then((res) => {
if (!res) {
this.$message.warning('文件下载失败')
return
}
let blob = new Blob([res], {type: 'application/vnd.ms-excel'})
let downloadElement = document.createElement('a')
let href = window.URL.createObjectURL(blob) // 创建下载的链接
downloadElement.href = href
downloadElement.download = '间接销售登记表导入模板.xls' // 下载后文件名
document.body.appendChild(downloadElement)
downloadElement.click() // 点击下载
document.body.removeChild(downloadElement) // 下载完成移除元素
window.URL.revokeObjectURL(href) // 释放掉blob对象
})
},
outmb1() {
downFile(this.url.teamExcelTemplateProduct, '').then((res) => {
if (!res) {
this.$message.warning('文件下载失败')
return
}
let blob = new Blob([res], {type: 'application/vnd.ms-excel'})
let downloadElement = document.createElement('a')
let href = window.URL.createObjectURL(blob) // 创建下载的链接
downloadElement.href = href
downloadElement.download = '间接销售登记导入模板.xlsx' // 下载后文件名
document.body.appendChild(downloadElement)
downloadElement.click() // 点击下载
document.body.removeChild(downloadElement) // 下载完成移除元素
window.URL.revokeObjectURL(href) // 释放掉blob对象
})
},
subStatus(){
const ids = this.$refs.editableTable.getSelection()
if (ids.length==0){
this.$message.warn("请选择一条记录")
return;
}
const selectedRow = this.$refs.editableTable.getValuesSync({rowIds: ids}).values
selectedRow.forEach(item => {
if (item.status == "1"){
this.$message.warn("请选择未提交的数据")
return;
}
})
let that = this
that.$confirm({
title: '提示',
content: '确认提交吗?',
onOk: function() {
putAction(that.url.setStatus, selectedRow).then((res) => {
if (res.success) {
that.$message.success(res.message);
that.loadData();
that.onClearSelected();
} else {
that.$message.warning(res.message);
that.loadData();
}
})
}
})
},
bacthSave() {
this.$refs.editableTable.getValues(error => {
if (error === 0) {
let that = this
postAction(that.url.batchAdd, this.$refs.editableTable.getValuesSync().values).then((res) => {
if (res.success) {
that.$message.success(res.message);
that.loadData();
} else {
that.$message.warning(res.message);
that.loadData();
}
})
} else {
this.$message.error('验证未通过')
}
})
},
reset(){
this.queryParam = {status:'1'}
this.loadData()
},
batchDelete: function () {
if(!this.url.deleteBatch){
this.$message.error("请设置url.deleteBatch属性!")
return
}
if (this.selectedRowKeys.length <= 0) {
this.$message.warning('请选择一条记录!');
return;
} else if (this.selectionRows.some(item => item.status != 0)) {
this.$message.warning('请选择未提交记录!')
return;
} else {
var ids = "";
for (var a = 0; a < this.selectedRowKeys.length; a++) {
ids += this.selectedRowKeys[a] + ",";
}
var that = this;
this.$confirm({
title: "确认删除",
content: "是否删除选中数据?",
onOk: function () {
that.loading = true;
deleteAction(that.url.deleteBatch, {ids: ids}).then((res) => {
if (res.success) {
that.$message.success(res.message);
that.loadData();
that.onClearSelected();
} else {
that.$message.warning(res.message);
}
}).finally(() => {
that.loading = false;
});
}
});
}
},
handleCusSubmit() {
if (!this.$refs.cusComponent.selectionRows || this.$refs.cusComponent.selectionRows.length === 0) {
this.$message.warning('请选择一条记录')
return false
}
var customerNames = "";
var oemResponsiblePerson = "";
var oemResponsiblePersonName = "";
for (var a = 0; a < this.$refs.cusComponent.selectedRowRecords.length; a++) {
customerNames += this.$refs.cusComponent.selectedRowRecords[a].customerName + ",";
if (this.$refs.cusComponent.selectedRowRecords[a].responsiblePerson !== null) {
oemResponsiblePerson += this.$refs.cusComponent.selectedRowRecords[a].responsiblePerson + ",";
}
if (this.$refs.cusComponent.selectedRowRecords[a].responsiblePersonName!==null){
oemResponsiblePersonName += this.$refs.cusComponent.selectedRowRecords[a].responsiblePersonName + ",";
}
}
const oems = customerNames.substr(0,customerNames.length-1)
const oemResponsiblePersons = oemResponsiblePerson.substr(0,oemResponsiblePerson.length-1)
const oemResponsiblePersonNames = oemResponsiblePersonName.substr(0,oemResponsiblePersonName.length-1)
// 找到当前点击的行并更新数据
this.$refs.editableTable.setValues(
[{
rowKey: this.currentClickRowId,
values: {
'oems': oems,
'oemResponsiblePerson': oemResponsiblePersons,
'oemResponsiblePersonName': oemResponsiblePersonNames,
}
}]
)
this.closeCusModal()
},
oemsInput(props) {
// 存储当前点击的行记录和ID
this.currentClickRowId = props.rowId;
// 找到当前点击的行并更新数据
this.$refs.editableTable.setValues(
[{
rowKey: this.currentClickRowId,
values: {
'oems': props.text
}
}]
)
},
handleOemsClick(props) {
console.log("主机厂",this.$refs.editableTable.getValues({rowIds: props.rowId}))
// 存储当前点击的行记录和ID
this.currentClickRowId = props.rowId;
this.openCusModal(); // 直接打开弹窗
},
openCusModal() {
this.cusVisible = true
},
closeCusModal() {
this.$refs.cusComponent.selectionRows = []
this.$refs.cusComponent.selectedRowKeys = []
this.$refs.cusComponent.queryParam = {}
this.cusVisible = false
},
formatDate(date) {
const year = date.getFullYear()
const month = (date.getMonth() + 1).toString().padStart(2, '0')
const day = date.getDate().toString().padStart(2, '0')
return `${year}-${month}-${day}`
},
initComp(userNames) {
this.userNames = userNames
},
onSearchDepUser(props) {
this.currentClickRowId = props.rowId
if (this.isSelectUser) this.$refs.selectModal.queryParam.username = this.value;
this.$refs.selectModal.showModal()
this.$refs.selectModal.queryParam.username = "";
},
selectOK(rows, idstr) {
if (!rows) {
this.userNames = ''
this.userIds = ''
} else {
let temp = ''
for (let item of rows) {
temp += ',' + item.realname
}
this.userNames = temp.substring(1)
this.userIds = idstr
// 找到当前点击的行并更新数据
this.$refs.editableTable.setValues(
[{
rowKey: this.currentClickRowId,
values: {
'publishBy': this.userIds,
'publishName': this.userNames,
}
}]
)
}
},
// 判断是否禁用
isDisabled(props){
const item = this.$refs.editableTable.getValuesSync({rowIds: [props.rowId]})
return item.values[0].status === '1'
}
}
}
</script>
<style scoped>
@import '~@assets/less/common.less';
.isShowStyle /deep/ .ant-card-body {
padding: unset;
}
</style>中<template v-slot:oemsSlot="props">
<a-input
v-model='props.text'
placeholder='请输入主机厂'
:disabled="isDisabled(props)"
@input="oemsInput(props)">
<a-icon slot='prefix' type='cluster' @click.stop='handleOemsClick(props)'/>
</a-input>
</template>插槽的:disabled我这样子用会报错,应该怎么使用,jeecg
最新发布