feat(quotation): 增加报价单详情查看和复制创建功能

- 关闭开发环境邮件发送功能
- 隐藏报价金额显示折后金额
- 添加详情按钮用于查看报价单详情
- 添加复制创建按钮实现基于现有报价单创建新报价单
- 实现复制创建功能清除原报价单ID和状态信息
- 添加项目表单中的报价单导入功能
- 更新删除接口路径为批量删除模式
- 修复删除确认提示信息过长问题
dev_1.0.2
chenhao 2026-01-30 11:22:24 +08:00
parent 61b10eba26
commit 701d90779a
4 changed files with 125 additions and 7 deletions

View File

@ -38,7 +38,7 @@ export function updateQuotation(data) {
// 删除报价单
export function delQuotation(id) {
return request({
url: '/quotation/' + id,
url: '/quotation/remove/batch/' + id,
method: 'delete'
})
}

View File

@ -83,8 +83,8 @@
<el-table-column label="报价单号" align="center" prop="quotationCode" />
<el-table-column label="报价单" align="center" prop="quotationName" />
<el-table-column label="项目编号" align="center" prop="projectCode" />
<el-table-column label="报价金额" align="center" prop="quotationAmount" />
<el-table-column label="折后金额" align="center" prop="discountAmount" />
<!-- <el-table-column label="报价金额" align="center" prop="quotationAmount" />-->
<el-table-column label="报价金额(¥)" align="center" prop="discountAmount" />
<el-table-column label="状态" align="center" prop="quotationStatus" />
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
<template slot-scope="scope">
@ -94,6 +94,13 @@
<el-table-column label="备注" align="center" prop="remark" />
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button
size="mini"
type="text"
icon="el-icon-view"
@click="handleDetail(scope.row)"
v-hasPermi="['base:quotation:query']"
>详情</el-button>
<el-button
size="mini"
type="text"
@ -101,6 +108,13 @@
@click="handleUpdate(scope.row)"
v-hasPermi="['base:quotation:edit']"
>修改</el-button>
<el-button
size="mini"
type="text"
icon="el-icon-document-copy"
@click="handleCopy(scope.row)"
v-hasPermi="['base:quotation:add']"
>复制创建</el-button>
<el-button
size="mini"
type="text"
@ -218,6 +232,7 @@
</div>
</div>
</el-dialog>
<quotation-detail ref="detail" :agent-options="agentOptions" />
</div>
</template>
@ -225,13 +240,14 @@
import { listQuotation, getQuotation, delQuotation, addQuotation, updateQuotation,exportSingleQuotation } from "@/api/base/quotation";
import { listAgent } from "@/api/system/agent";
import ProductConfig from "@/views/project/info/ProductConfig";
import QuotationDetail from "./detail";
import {isEmpty} from "@/utils/validate";
import {exportPurchaseorder} from "@/api/sip/purchaseorder";
export default {
name: "Quotation",
components: {
ProductConfig
ProductConfig,
QuotationDetail
},
dicts: ['currency_type'],
data() {
@ -346,6 +362,9 @@ export default {
this.loading = false;
});
},
handleDetail(row) {
this.$refs.detail.open(row.id);
},
handleExport(row){
this.$modal.confirm('是否确认导出已审批的采购数据项?').then(() => {
return exportSingleQuotation(row.id);
@ -415,6 +434,45 @@ export default {
this.activeStep = 1;
this.title = "添加报价单";
},
/** 复制创建 */
handleCopy(row) {
this.reset();
const id = row.id || this.ids
getQuotation(id).then(response => {
this.form = response.data;
// Reset ID and Code for new creation
this.form.id = null;
this.form.quotationCode = null;
this.form.quotationStatus = null;
this.form.createTime = null;
this.form.updateTime = null;
this.form.createBy = null;
this.form.updateBy = null;
// Ensure product lists are initialized if null
this.form.softwareProjectProductInfoList = this.form.softwareProjectProductInfoList || [];
this.form.hardwareProjectProductInfoList = this.form.hardwareProjectProductInfoList || [];
this.form.maintenanceProjectProductInfoList = this.form.maintenanceProjectProductInfoList || [];
// Clear IDs in configuration lists to ensure they are created as new records
const clearIds = (list) => {
if (list && list.length > 0) {
list.forEach(item => {
item.id = null;
item.quotationId = null;
});
}
};
clearIds(this.form.softwareProjectProductInfoList);
clearIds(this.form.hardwareProjectProductInfoList);
clearIds(this.form.maintenanceProjectProductInfoList);
this.open = true;
this.activeStep = 1;
this.title = "复制创建报价单";
});
},
/** 修改按钮操作 */
handleUpdate(row) {
this.reset();
@ -500,7 +558,7 @@ export default {
/** 删除按钮操作 */
handleDelete(row) {
const ids = row.id || this.ids;
this.$modal.confirm('是否确认删除报价单编号为"' + ids + '"的数据项').then(function() {
this.$modal.confirm('是否确认删除报价单').then(function() {
return delQuotation(ids);
}).then(() => {
this.getList();

View File

@ -289,6 +289,7 @@
</el-tab-pane>
<el-tab-pane label="配置信息" name="productConfig">
<div style="max-height: 60vh; overflow-y: auto; padding: 15px;">
<el-button type="primary" plain icon="el-icon-download" size="mini" @click="openSelectQuotation" class="mb8" :disabled="isFormDisabled">报价单导入</el-button>
<!-- 产品配置信息 -->
<product-config v-model="form.productConfig" ref="productConfig" :disabled="isFormDisabled" />
</div>
@ -432,6 +433,7 @@
</el-dialog>
<select-agent :visible.sync="selectAgentVisible" @agent-selected="handleAgentSelected" />
<select-quotation :visible.sync="selectQuotationVisible" @quotation-selected="handleQuotationSelected" />
<select-customer :visible.sync="selectCustomerVisible" @customer-selected="handleCustomerSelected" />
<select-partner :visible.sync="selectPartnerVisible" @partner-selected="handlePartnerSelected" />
<select-user :visible.sync="selectUserVisible" @user-selected="handleUserSelected" />
@ -440,8 +442,10 @@
<script>
import { getProject, addProject, updateProject } from "@/api/project/info";
import { getQuotation } from "@/api/base/quotation";
import { listAreas } from "@/api/system/area";
import SelectAgent from "../../system/agent/selectAgent.vue";
import SelectQuotation from "../../base/quotation/selectQuotation.vue";
import SelectCustomer from "../../system/customer/selectCustomer.vue";
import SelectPartner from "../../system/partner/selectPartner.vue";
import SelectUser from "@/views/system/user/selectUser";
@ -454,6 +458,7 @@ export default {
name: "ProjectForm",
components: {
SelectAgent,
SelectQuotation,
SelectCustomer,
SelectPartner,
SelectUser,
@ -492,6 +497,7 @@ export default {
cityOptions: [],
industryOptions: [],
selectAgentVisible: false,
selectQuotationVisible: false,
selectCustomerVisible: false,
selectPartnerVisible: false,
selectUserVisible: false,
@ -836,6 +842,60 @@ export default {
});
}
},
openSelectQuotation() {
this.selectQuotationVisible = true;
},
handleQuotationSelected(quotation) {
if (!quotation) return;
const confirmImport = () => {
getQuotation(quotation.id).then(response => {
const data = response.data;
// Clear IDs
const clearIds = (list) => {
if (list && list.length > 0) {
list.forEach(item => {
item.id = null;
item.quotationId = null;
item.projectId = null;
});
}
};
const softwareList = data.softwareProjectProductInfoList || [];
const hardwareList = data.hardwareProjectProductInfoList || [];
const maintenanceList = data.maintenanceProjectProductInfoList || [];
clearIds(softwareList);
clearIds(hardwareList);
clearIds(maintenanceList);
this.$set(this.form.productConfig, 'softwareProjectProductInfoList', softwareList);
this.$set(this.form.productConfig, 'hardwareProjectProductInfoList', hardwareList);
this.$set(this.form.productConfig, 'maintenanceProjectProductInfoList', maintenanceList);
this.$modal.msgSuccess("导入成功");
});
};
// Check if config exists
const hasConfig = (
(this.form.productConfig.softwareProjectProductInfoList && this.form.productConfig.softwareProjectProductInfoList.length > 0) ||
(this.form.productConfig.hardwareProjectProductInfoList && this.form.productConfig.hardwareProjectProductInfoList.length > 0) ||
(this.form.productConfig.maintenanceProjectProductInfoList && this.form.productConfig.maintenanceProjectProductInfoList.length > 0)
);
if (hasConfig) {
this.$confirm('当前项目已有配置信息,导入将覆盖现有配置,是否确认导入?', "警告", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
confirmImport();
}).catch(() => {});
} else {
confirmImport();
}
},
openSelectAgent() {
this.selectAgentVisible = true;
},

View File

@ -68,4 +68,4 @@ unis:
# 执行单截止时间
endHour: 96
mail:
enabled: true
enabled: false