From cb76922f5e8ccade2bdd3e1c73c64c2fe711c45f Mon Sep 17 00:00:00 2001
From: chenhj <1263187585@qq.com>
Date: 星期一, 20 四月 2026 15:46:20 +0800
Subject: [PATCH] feat(salesQuotation): 添加导入详情功能及优化界面交互
---
src/views/salesManagement/salesQuotation/index.vue | 1052 +++++++++++++++++++++++++++++++---------------------------
1 files changed, 562 insertions(+), 490 deletions(-)
diff --git a/src/views/salesManagement/salesQuotation/index.vue b/src/views/salesManagement/salesQuotation/index.vue
index 0acfc93..23b68be 100644
--- a/src/views/salesManagement/salesQuotation/index.vue
+++ b/src/views/salesManagement/salesQuotation/index.vue
@@ -5,33 +5,36 @@
<el-row :gutter="20" class="search-row">
<el-col :span="8">
<el-input
- v-model="searchForm.quotationNo"
- placeholder="璇疯緭鍏ユ姤浠峰崟鍙�"
- clearable
- @keyup.enter="handleSearch"
+ v-model="searchForm.quotationNo"
+ placeholder="璇疯緭鍏ユ姤浠峰崟鍙�"
+ clearable
+ @keyup.enter="handleSearch"
>
<template #prefix>
- <el-icon><Search /></el-icon>
+ <el-icon>
+ <Search/>
+ </el-icon>
</template>
</el-input>
</el-col>
<el-col :span="8">
<el-select v-model="searchForm.customer" placeholder="璇烽�夋嫨瀹㈡埛" clearable>
- <el-option v-for="item in customerOption" :key="item.id" :label="item.customerName" :value="item.customerName">
- {{
- item.customerName + "鈥斺��" + item.taxpayerIdentificationNumber
- }}
- </el-option>
+ <el-option v-for="item in customerOption" :key="item.id" :label="item.customerName"
+ :value="item.customerName">
+ {{
+ item.customerName + "鈥斺��" + item.taxpayerIdentificationNumber
+ }}
+ </el-option>
</el-select>
</el-col>
-<!-- <el-col :span="6">-->
-<!-- <el-select v-model="searchForm.status" placeholder="璇烽�夋嫨鎶ヤ环鐘舵��" clearable>-->
-<!-- <el-option label="鑽夌" value="鑽夌"></el-option>-->
-<!-- <el-option label="宸插彂閫�" value="宸插彂閫�"></el-option>-->
-<!-- <el-option label="瀹㈡埛纭" value="瀹㈡埛纭"></el-option>-->
-<!-- <el-option label="宸茶繃鏈�" value="宸茶繃鏈�"></el-option>-->
-<!-- </el-select>-->
-<!-- </el-col>-->
+ <!-- <el-col :span="6">-->
+ <!-- <el-select v-model="searchForm.status" placeholder="璇烽�夋嫨鎶ヤ环鐘舵��" clearable>-->
+ <!-- <el-option label="鑽夌" value="鑽夌"></el-option>-->
+ <!-- <el-option label="宸插彂閫�" value="宸插彂閫�"></el-option>-->
+ <!-- <el-option label="瀹㈡埛纭" value="瀹㈡埛纭"></el-option>-->
+ <!-- <el-option label="宸茶繃鏈�" value="宸茶繃鏈�"></el-option>-->
+ <!-- </el-select>-->
+ <!-- </el-col>-->
<el-col :span="8">
<el-button type="primary" @click="handleSearch">鎼滅储</el-button>
<el-button @click="resetSearch">閲嶇疆</el-button>
@@ -46,19 +49,19 @@
<!-- 鎶ヤ环鍒楄〃 -->
<el-table
- :data="filteredList"
- style="width: 100%"
- v-loading="loading"
- border
- stripe
- height="calc(100vh - 22em)"
+ :data="filteredList"
+ style="width: 100%"
+ v-loading="loading"
+ border
+ stripe
+ height="calc(100vh - 22em)"
>
- <el-table-column align="center" label="搴忓彿" type="index" width="60" />
- <el-table-column prop="quotationNo" label="鎶ヤ环鍗曞彿" />
- <el-table-column prop="customer" label="瀹㈡埛鍚嶇О" />
- <el-table-column prop="salesperson" label="涓氬姟鍛�" width="100" />
- <el-table-column prop="quotationDate" label="鎶ヤ环鏃ユ湡" width="120" />
- <el-table-column prop="validDate" label="鏈夋晥鏈熻嚦" width="120" />
+ <el-table-column align="center" label="搴忓彿" type="index" width="60"/>
+ <el-table-column prop="quotationNo" label="鎶ヤ环鍗曞彿"/>
+ <el-table-column prop="customer" label="瀹㈡埛鍚嶇О"/>
+ <el-table-column prop="salesperson" label="涓氬姟鍛�" width="100"/>
+ <el-table-column prop="quotationDate" label="鎶ヤ环鏃ユ湡" width="120"/>
+ <el-table-column prop="validDate" label="鏈夋晥鏈熻嚦" width="120"/>
<el-table-column prop="status" label="瀹℃壒鐘舵��" width="120" align="center">
<template #default="{ row }">
<el-tag :type="getStatusType(row.status)" disable-transitions>
@@ -71,350 +74,384 @@
楼{{ scope.row.totalAmount.toFixed(2) }}
</template>
</el-table-column>
- <el-table-column label="鎿嶄綔" width="200" fixed="right" align="center">
+ <el-table-column label="鎿嶄綔" width="250" fixed="right" align="center">
<template #default="scope">
- <el-button link type="primary" @click="handleEdit(scope.row)" :disabled="!['寰呭鎵�','鎷掔粷'].includes(scope.row.status)">缂栬緫</el-button>
+ <el-button link type="primary" @click="handleEdit(scope.row)"
+ :disabled="!['寰呭鎵�','鎷掔粷'].includes(scope.row.status)">缂栬緫
+ </el-button>
<el-button link type="primary" @click="handleView(scope.row)" style="color: #67C23A">鏌ョ湅</el-button>
<el-button link type="danger" @click="handleDelete(scope.row)">鍒犻櫎</el-button>
+ <el-button link type="primary" @click="handleImportDetail(scope.row)">瀵煎叆璇︽儏</el-button>
</template>
</el-table-column>
</el-table>
<!-- 鍒嗛〉 -->
<pagination
- :total="pagination.total"
- layout="total, sizes, prev, pager, next, jumper"
- :page="pagination.currentPage"
- :limit="pagination.pageSize"
- @pagination="handleCurrentChange"
+ :total="pagination.total"
+ layout="total, sizes, prev, pager, next, jumper"
+ :page="pagination.currentPage"
+ :limit="pagination.pageSize"
+ @pagination="handleCurrentChange"
/>
</el-card>
<!-- 鏂板/缂栬緫瀵硅瘽妗� -->
- <FormDialog v-model="dialogVisible" :title="dialogTitle" width="85%" :close-on-click-modal="false" @close="dialogVisible = false" @confirm="handleSubmit" @cancel="dialogVisible = false">
+ <FormDialog v-model="dialogVisible" :title="dialogTitle" width="85%" :close-on-click-modal="false"
+ @close="dialogVisible = false" @confirm="handleSubmit" @cancel="dialogVisible = false">
<div class="quotation-form-container">
<el-form :model="form" :rules="rules" ref="formRef" label-width="120px" class="quotation-form">
- <!-- 鍩烘湰淇℃伅 -->
- <el-card class="form-card" shadow="hover">
- <template #header>
- <div class="card-header-wrapper">
- <el-icon class="card-icon"><Document /></el-icon>
- <span class="card-title">鍩烘湰淇℃伅</span>
- </div>
- </template>
- <div class="form-content">
- <el-row :gutter="24">
- <el-col :span="12">
- <el-form-item label="瀹㈡埛鍚嶇О" prop="customer">
- <el-select v-model="form.customer" placeholder="璇烽�夋嫨瀹㈡埛" style="width: 100%" @change="handleCustomerChange" clearable>
- <el-option v-for="item in customerOption" :key="item.id" :label="item.customerName" :value="item.customerName">
- {{
- item.customerName + "鈥斺��" + item.taxpayerIdentificationNumber
- }}
- </el-option>
- </el-select>
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="涓氬姟鍛�" prop="salesperson">
- <el-select v-model="form.salesperson" placeholder="璇烽�夋嫨涓氬姟鍛�" style="width: 100%" clearable>
- <el-option v-for="item in userList" :key="item.nickName" :label="item.nickName"
- :value="item.nickName" />
- </el-select>
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="24">
- <el-col :span="12">
- <el-form-item label="鎶ヤ环鏃ユ湡" prop="quotationDate">
- <el-date-picker
- v-model="form.quotationDate"
- type="date"
- placeholder="閫夋嫨鎶ヤ环鏃ユ湡"
- style="width: 100%"
- format="YYYY-MM-DD"
- value-format="YYYY-MM-DD"
- clearable
- />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="鏈夋晥鏈熻嚦" prop="validDate">
- <el-date-picker
- v-model="form.validDate"
- type="date"
- placeholder="閫夋嫨鏈夋晥鏈�"
- style="width: 100%"
- format="YYYY-MM-DD"
- value-format="YYYY-MM-DD"
- clearable
- />
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="24">
- <el-col :span="12">
- <el-form-item label="浠樻鏂瑰紡" prop="paymentMethod">
- <el-input v-model="form.paymentMethod" placeholder="璇疯緭鍏ヤ粯娆炬柟寮�" clearable />
- </el-form-item>
- </el-col>
- </el-row>
- </div>
- </el-card>
-
- <!-- 瀹℃壒浜轰俊鎭� -->
- <el-card class="form-card" shadow="hover">
- <template #header>
- <div class="card-header-wrapper">
- <el-icon class="card-icon"><UserFilled /></el-icon>
- <span class="card-title">瀹℃壒浜洪�夋嫨</span>
- <el-button type="primary" size="small" @click="addApproverNode" class="header-btn">
- <el-icon><Plus /></el-icon>
- 鏂板鑺傜偣
- </el-button>
- </div>
- </template>
- <div class="form-content">
- <el-row>
- <el-col :span="24">
- <el-form-item>
- <div class="approver-nodes-container">
- <div
- v-for="(node, index) in approverNodes"
- :key="node.id"
- class="approver-node-item"
- >
- <div class="approver-node-label">
- <span class="node-step">{{ index + 1 }}</span>
- <span class="node-text">瀹℃壒浜�</span>
- <el-icon class="arrow-icon"><ArrowRight /></el-icon>
- </div>
- <el-select
- v-model="node.userId"
- placeholder="閫夋嫨浜哄憳"
- class="approver-select"
+ <!-- 鍩烘湰淇℃伅 -->
+ <el-card class="form-card" shadow="hover">
+ <template #header>
+ <div class="card-header-wrapper">
+ <el-icon class="card-icon">
+ <Document/>
+ </el-icon>
+ <span class="card-title">鍩烘湰淇℃伅</span>
+ </div>
+ </template>
+ <div class="form-content">
+ <el-row :gutter="24">
+ <el-col :span="12">
+ <el-form-item label="瀹㈡埛鍚嶇О" prop="customer">
+ <el-select v-model="form.customer" placeholder="璇烽�夋嫨瀹㈡埛" style="width: 100%"
+ @change="handleCustomerChange" clearable>
+ <el-option v-for="item in customerOption" :key="item.id" :label="item.customerName"
+ :value="item.customerName">
+ {{
+ item.customerName + "鈥斺��" + item.taxpayerIdentificationNumber
+ }}
+ </el-option>
+ </el-select>
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="涓氬姟鍛�" prop="salesperson">
+ <el-select v-model="form.salesperson" placeholder="璇烽�夋嫨涓氬姟鍛�" style="width: 100%" clearable>
+ <el-option v-for="item in userList" :key="item.nickName" :label="item.nickName"
+ :value="item.nickName"/>
+ </el-select>
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="24">
+ <el-col :span="12">
+ <el-form-item label="鎶ヤ环鏃ユ湡" prop="quotationDate">
+ <el-date-picker
+ v-model="form.quotationDate"
+ type="date"
+ placeholder="閫夋嫨鎶ヤ环鏃ユ湡"
+ style="width: 100%"
+ format="YYYY-MM-DD"
+ value-format="YYYY-MM-DD"
clearable
+ />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鏈夋晥鏈熻嚦" prop="validDate">
+ <el-date-picker
+ v-model="form.validDate"
+ type="date"
+ placeholder="閫夋嫨鏈夋晥鏈�"
+ style="width: 100%"
+ format="YYYY-MM-DD"
+ value-format="YYYY-MM-DD"
+ clearable
+ />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="24">
+ <el-col :span="12">
+ <el-form-item label="浠樻鏂瑰紡" prop="paymentMethod">
+ <el-input v-model="form.paymentMethod" placeholder="璇疯緭鍏ヤ粯娆炬柟寮�" clearable/>
+ </el-form-item>
+ </el-col>
+ </el-row>
+ </div>
+ </el-card>
+
+ <!-- 瀹℃壒浜轰俊鎭� -->
+ <el-card class="form-card" shadow="hover">
+ <template #header>
+ <div class="card-header-wrapper">
+ <el-icon class="card-icon">
+ <UserFilled/>
+ </el-icon>
+ <span class="card-title">瀹℃壒浜洪�夋嫨</span>
+ <el-button type="primary" size="small" @click="addApproverNode" class="header-btn">
+ <el-icon>
+ <Plus/>
+ </el-icon>
+ 鏂板鑺傜偣
+ </el-button>
+ </div>
+ </template>
+ <div class="form-content">
+ <el-row>
+ <el-col :span="24">
+ <el-form-item>
+ <div class="approver-nodes-container">
+ <div
+ v-for="(node, index) in approverNodes"
+ :key="node.id"
+ class="approver-node-item"
+ >
+ <div class="approver-node-label">
+ <span class="node-step">{{ index + 1 }}</span>
+ <span class="node-text">瀹℃壒浜�</span>
+ <el-icon class="arrow-icon">
+ <ArrowRight/>
+ </el-icon>
+ </div>
+ <el-select
+ v-model="node.userId"
+ placeholder="閫夋嫨浜哄憳"
+ class="approver-select"
+ clearable
+ >
+ <el-option
+ v-for="user in userList"
+ :key="user.userId"
+ :label="user.nickName"
+ :value="user.userId"
+ />
+ </el-select>
+ <el-button
+ type="danger"
+ size="small"
+ :icon="Delete"
+ @click="removeApproverNode(index)"
+ v-if="approverNodes.length > 1"
+ class="remove-btn"
+ >鍒犻櫎
+ </el-button>
+ </div>
+ </div>
+ </el-form-item>
+ </el-col>
+ </el-row>
+ </div>
+ </el-card>
+
+ <!-- 浜у搧淇℃伅 -->
+ <el-card class="form-card" shadow="hover">
+ <template #header>
+ <div class="card-header-wrapper">
+ <el-icon class="card-icon">
+ <Box/>
+ </el-icon>
+ <span class="card-title">浜у搧淇℃伅</span>
+ <el-button type="primary" size="small" @click="addProduct" class="header-btn">
+ <el-icon>
+ <Plus/>
+ </el-icon>
+ 娣诲姞浜у搧
+ </el-button>
+ </div>
+ </template>
+ <div class="form-content">
+ <el-table :data="form.products" border style="width: 100%" class="product-table"
+ v-if="form.products.length > 0">
+ <el-table-column prop="product" label="浜у搧鍚嶇О" width="200">
+ <template #default="scope">
+ <el-form-item :prop="`products.${scope.$index}.productId`" class="product-table-form-item">
+ <el-tree-select
+ v-model="scope.row.productId"
+ placeholder="璇烽�夋嫨"
+ clearable
+ check-strictly
+ @change="getModels($event, scope.row)"
+ :data="productOptions"
+ :render-after-expand="false"
+ style="width: 100%"
+ />
+ </el-form-item>
+ </template>
+ </el-table-column>
+ <el-table-column prop="specification" label="瑙勬牸鍨嬪彿" width="200">
+ <template #default="scope">
+ <el-form-item :prop="`products.${scope.$index}.specificationId`" class="product-table-form-item">
+ <el-select
+ v-model="scope.row.specificationId"
+ placeholder="璇烽�夋嫨"
+ clearable
+ @change="getProductModel($event, scope.row)"
+ style="width: 100%"
>
<el-option
- v-for="user in userList"
- :key="user.userId"
- :label="user.nickName"
- :value="user.userId"
+ v-for="item in scope.row.modelOptions || []"
+ :key="item.id"
+ :label="item.model"
+ :value="item.id"
/>
</el-select>
- <el-button
- type="danger"
- size="small"
- :icon="Delete"
- @click="removeApproverNode(index)"
- v-if="approverNodes.length > 1"
- class="remove-btn"
- >鍒犻櫎</el-button>
- </div>
- </div>
- </el-form-item>
- </el-col>
- </el-row>
- </div>
- </el-card>
-
- <!-- 浜у搧淇℃伅 -->
- <el-card class="form-card" shadow="hover">
- <template #header>
- <div class="card-header-wrapper">
- <el-icon class="card-icon"><Box /></el-icon>
- <span class="card-title">浜у搧淇℃伅</span>
- <el-button type="primary" size="small" @click="addProduct" class="header-btn">
- <el-icon><Plus /></el-icon>
- 娣诲姞浜у搧
- </el-button>
+ </el-form-item>
+ </template>
+ </el-table-column>
+ <el-table-column prop="unit" label="鍗曚綅">
+ <template #default="scope">
+ <el-form-item :prop="`products.${scope.$index}.unit`" class="product-table-form-item">
+ <el-input v-model="scope.row.unit" placeholder="鍗曚綅" clearable/>
+ </el-form-item>
+ </template>
+ </el-table-column>
+ <el-table-column prop="unitPrice" label="鍗曚环">
+ <template #default="scope">
+ <el-form-item :prop="`products.${scope.$index}.unitPrice`" class="product-table-form-item">
+ <el-input-number v-model="scope.row.unitPrice" :min="0" :precision="2" style="width: 100%"/>
+ </el-form-item>
+ </template>
+ </el-table-column>
+ <el-table-column label="鎿嶄綔" width="80" align="center">
+ <template #default="scope">
+ <el-button link type="danger" @click="removeProduct(scope.$index)">鍒犻櫎</el-button>
+ </template>
+ </el-table-column>
+ </el-table>
+ <el-empty v-else description="鏆傛棤浜у搧锛岃鐐瑰嚮娣诲姞浜у搧" :image-size="80"/>
</div>
- </template>
- <div class="form-content">
- <el-table :data="form.products" border style="width: 100%" class="product-table" v-if="form.products.length > 0">
- <el-table-column prop="product" label="浜у搧鍚嶇О" width="200">
- <template #default="scope">
- <el-form-item :prop="`products.${scope.$index}.productId`" class="product-table-form-item">
- <el-tree-select
- v-model="scope.row.productId"
- placeholder="璇烽�夋嫨"
- clearable
- check-strictly
- @change="getModels($event, scope.row)"
- :data="productOptions"
- :render-after-expand="false"
- style="width: 100%"
- />
- </el-form-item>
- </template>
- </el-table-column>
- <el-table-column prop="specification" label="瑙勬牸鍨嬪彿" width="200">
- <template #default="scope">
- <el-form-item :prop="`products.${scope.$index}.specificationId`" class="product-table-form-item">
- <el-select
- v-model="scope.row.specificationId"
- placeholder="璇烽�夋嫨"
- clearable
- @change="getProductModel($event, scope.row)"
- style="width: 100%"
- >
- <el-option
- v-for="item in scope.row.modelOptions || []"
- :key="item.id"
- :label="item.model"
- :value="item.id"
- />
- </el-select>
- </el-form-item>
- </template>
- </el-table-column>
- <el-table-column prop="unit" label="鍗曚綅">
- <template #default="scope">
- <el-form-item :prop="`products.${scope.$index}.unit`" class="product-table-form-item">
- <el-input v-model="scope.row.unit" placeholder="鍗曚綅" clearable/>
- </el-form-item>
- </template>
- </el-table-column>
- <el-table-column prop="unitPrice" label="鍗曚环">
- <template #default="scope">
- <el-form-item :prop="`products.${scope.$index}.unitPrice`" class="product-table-form-item">
- <el-input-number v-model="scope.row.unitPrice" :min="0" :precision="2" style="width: 100%" />
- </el-form-item>
- </template>
- </el-table-column>
- <el-table-column label="鎿嶄綔" width="80" align="center">
- <template #default="scope">
- <el-button link type="danger" @click="removeProduct(scope.$index)">鍒犻櫎</el-button>
- </template>
- </el-table-column>
- </el-table>
- <el-empty v-else description="鏆傛棤浜у搧锛岃鐐瑰嚮娣诲姞浜у搧" :image-size="80" />
- </div>
- </el-card>
+ </el-card>
- <!-- 澶囨敞淇℃伅 -->
- <el-card class="form-card" shadow="hover">
- <template #header>
- <div class="card-header-wrapper">
- <el-icon class="card-icon"><EditPen /></el-icon>
- <span class="card-title">澶囨敞淇℃伅</span>
+ <!-- 澶囨敞淇℃伅 -->
+ <el-card class="form-card" shadow="hover">
+ <template #header>
+ <div class="card-header-wrapper">
+ <el-icon class="card-icon">
+ <EditPen/>
+ </el-icon>
+ <span class="card-title">澶囨敞淇℃伅</span>
+ </div>
+ </template>
+ <div class="form-content">
+ <el-form-item label="澶囨敞" prop="remark">
+ <el-input
+ type="textarea"
+ v-model="form.remark"
+ placeholder="璇疯緭鍏ュ娉ㄤ俊鎭紙閫夊~锛�"
+ :rows="4"
+ maxlength="500"
+ show-word-limit
+ ></el-input>
+ </el-form-item>
</div>
- </template>
- <div class="form-content">
- <el-form-item label="澶囨敞" prop="remark">
- <el-input
- type="textarea"
- v-model="form.remark"
- placeholder="璇疯緭鍏ュ娉ㄤ俊鎭紙閫夊~锛�"
- :rows="4"
- maxlength="500"
- show-word-limit
- ></el-input>
- </el-form-item>
- </div>
- </el-card>
- </el-form>
+ </el-card>
+ </el-form>
</div>
</FormDialog>
- <FormDialog v-model="importDialogVisible" title="瀵煎叆鎶ヤ环鍗�" width="85%" :close-on-click-modal="false" @close="importDialogVisible = false" @confirm="handleImportSubmit" @cancel="importDialogVisible = false">
+ <FormDialog v-model="importDialogVisible" title="瀵煎叆鎶ヤ环鍗�" width="85%" :close-on-click-modal="false"
+ @close="importDialogVisible = false" @confirm="handleImportSubmit"
+ @cancel="importDialogVisible = false">
<!-- 瀹℃壒浜轰俊鎭� -->
- <el-card class="form-card" shadow="hover">
- <template #header>
- <div class="card-header-wrapper">
- <el-icon class="card-icon"><UserFilled /></el-icon>
- <span class="card-title">瀹℃壒浜洪�夋嫨</span>
- <el-button type="primary" size="small" @click="addImportApproverNode" class="header-btn">
- <el-icon><Plus /></el-icon>
- 鏂板鑺傜偣
- </el-button>
- </div>
- </template>
- <div class="form-content">
- <el-row>
- <el-col :span="24">
- <el-form-item>
- <div class="approver-nodes-container">
- <div
+ <el-card class="form-card" shadow="hover">
+ <template #header>
+ <div class="card-header-wrapper">
+ <el-icon class="card-icon">
+ <UserFilled/>
+ </el-icon>
+ <span class="card-title">瀹℃壒浜洪�夋嫨</span>
+ <el-button type="primary" size="small" @click="addImportApproverNode" class="header-btn">
+ <el-icon>
+ <Plus/>
+ </el-icon>
+ 鏂板鑺傜偣
+ </el-button>
+ </div>
+ </template>
+ <div class="form-content">
+ <el-row>
+ <el-col :span="24">
+ <el-form-item>
+ <div class="approver-nodes-container">
+ <div
v-for="(node, index) in importApproverNodes"
:key="node.id"
class="approver-node-item"
- >
- <div class="approver-node-label">
- <span class="node-step">{{ index + 1 }}</span>
- <span class="node-text">瀹℃壒浜�</span>
- <el-icon class="arrow-icon"><ArrowRight /></el-icon>
- </div>
- <el-select
+ >
+ <div class="approver-node-label">
+ <span class="node-step">{{ index + 1 }}</span>
+ <span class="node-text">瀹℃壒浜�</span>
+ <el-icon class="arrow-icon">
+ <ArrowRight/>
+ </el-icon>
+ </div>
+ <el-select
v-model="node.userId"
placeholder="閫夋嫨浜哄憳"
class="approver-select"
clearable
- >
- <el-option
+ >
+ <el-option
v-for="user in userList"
:key="user.userId"
:label="user.nickName"
:value="user.userId"
- />
- </el-select>
- <el-button
+ />
+ </el-select>
+ <el-button
type="danger"
size="small"
:icon="Delete"
@click="removeImportApproverNode(index)"
v-if="importApproverNodes.length > 1"
class="remove-btn"
- >鍒犻櫎</el-button>
- </div>
+ >鍒犻櫎
+ </el-button>
</div>
- </el-form-item>
- </el-col>
- </el-row>
+ </div>
+ </el-form-item>
+ </el-col>
+ </el-row>
+ </div>
+ </el-card>
+ <el-card class="form-card" shadow="hover">
+ <template #header>
+ <div class="card-header-wrapper">
+ <el-icon class="card-icon">
+ <Paperclip/>
+ </el-icon>
+ <span class="card-title">闄勪欢鏉愭枡</span>
</div>
- </el-card>
- <el-card class="form-card" shadow="hover">
- <template #header>
- <div class="card-header-wrapper">
- <el-icon class="card-icon"><Paperclip /></el-icon>
- <span class="card-title">闄勪欢鏉愭枡</span>
- </div>
- </template>
- <div class="form-content">
- <el-form-item label="闄勪欢鏉愭枡" prop="files">
- <el-upload
- v-model:file-list="importFileList"
- :limit="1"
- ref="fileUpload"
- :auto-upload="false"
- :on-change="handleFileChange"
- :on-exceed="handleExceed"
- :on-remove="handleRemove"
- :on-preview="handlePreview"
- :show-file-list="true"
- >
- <el-button type="primary">涓婁紶</el-button>
- <template #file="{ file }">
- <div style="display:flex; align-items:center; gap: 10px; width: 100%;">
+ </template>
+ <div class="form-content">
+ <el-button type="primary" @click="downloadImportTemplate" style="margin-bottom: 20px">涓嬭浇妯℃澘鏂囦欢</el-button>
+ <el-form-item label="闄勪欢鏉愭枡" prop="files">
+ <el-upload
+ v-model:file-list="importFileList"
+ :limit="1"
+ ref="fileUpload"
+ :auto-upload="false"
+ :on-change="handleFileChange"
+ :on-exceed="handleExceed"
+ :on-remove="handleRemove"
+ :on-preview="handlePreview"
+ :show-file-list="true"
+ >
+ <el-button type="primary">涓婁紶</el-button>
+ <template #file="{ file }">
+ <div style="display:flex; align-items:center; gap: 10px; width: 100%;">
<span style="flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;">
{{ file.name }}
</span>
-<!-- <div style="display:flex; align-items:center; gap: 6px;">-->
-<!-- <el-button link type="success" :icon="Download" @click="handleDownload(file)" />-->
-<!-- <el-button link type="primary" :icon="View" @click="handlePreview(file)" />-->
-<!-- <el-button link type="danger" :icon="Delete" @click="triggerRemoveFile(file)" />-->
-<!-- </div>-->
- </div>
- </template>
- <template #tip>
- <div class="el-upload__tip">
- 鏀寔鏂囨。锛坸ls, xlsx锛夋牸寮�
- </div>
- </template>
- </el-upload>
- </el-form-item>
- </div>
- </el-card>
+ <div style="display:flex; align-items:center; gap: 6px;">
+ <!-- <el-button link type="success" :icon="Download" @click="handleDownload(file)" />-->
+ <!-- <el-button link type="primary" :icon="View" @click="handlePreview(file)" />-->
+ <!-- <el-button link type="danger" :icon="Delete" @click="triggerRemoveFile(file)" />-->
+ </div>
+ </div>
+ </template>
+ <template #tip>
+ <div class="el-upload__tip">
+ 鏀寔鏂囨。锛坸ls, xlsx锛夋牸寮�
+ </div>
+ </template>
+ </el-upload>
+ </el-form-item>
+ </div>
+ </el-card>
</FormDialog>
<!-- 鏌ョ湅璇︽儏瀵硅瘽妗� -->
@@ -426,20 +463,22 @@
<el-descriptions-item label="鎶ヤ环鏃ユ湡">{{ currentQuotation.quotationDate }}</el-descriptions-item>
<el-descriptions-item label="鏈夋晥鏈熻嚦">{{ currentQuotation.validDate }}</el-descriptions-item>
<el-descriptions-item label="浠樻鏂瑰紡">{{ currentQuotation.paymentMethod }}</el-descriptions-item>
-<!-- <el-descriptions-item label="鎶ヤ环鐘舵��">-->
-<!-- <el-tag :type="getStatusType(currentQuotation.status)">{{ currentQuotation.status }}</el-tag>-->
-<!-- </el-descriptions-item>-->
+ <!-- <el-descriptions-item label="鎶ヤ环鐘舵��">-->
+ <!-- <el-tag :type="getStatusType(currentQuotation.status)">{{ currentQuotation.status }}</el-tag>-->
+ <!-- </el-descriptions-item>-->
<el-descriptions-item label="鎶ヤ环鎬婚" :span="2">
- <span style="font-size: 18px; color: #e6a23c; font-weight: bold;">楼{{ currentQuotation.totalAmount?.toFixed(2) }}</span>
+ <span style="font-size: 18px; color: #e6a23c; font-weight: bold;">楼{{
+ currentQuotation.totalAmount?.toFixed(2)
+ }}</span>
</el-descriptions-item>
</el-descriptions>
-
+
<div style="margin: 20px 0;">
<h4>浜у搧鏄庣粏</h4>
<el-table :data="currentQuotation.products" border style="width: 100%">
- <el-table-column prop="product" label="浜у搧鍚嶇О" />
- <el-table-column prop="specification" label="瑙勬牸鍨嬪彿" />
- <el-table-column prop="unit" label="鍗曚綅" />
+ <el-table-column prop="product" label="浜у搧鍚嶇О"/>
+ <el-table-column prop="specification" label="瑙勬牸鍨嬪彿"/>
+ <el-table-column prop="unit" label="鍗曚綅"/>
<el-table-column prop="unitPrice" label="鍗曚环">
<template #default="scope">
楼{{ scope.row.unitPrice.toFixed(2) }}
@@ -453,21 +492,38 @@
<p>{{ currentQuotation.remark }}</p>
</div>
</el-dialog>
+ <ImportQuotationDetail v-if="showDetail" v-model:showModal="showDetail" :quotationId="currentQuotation.id" />
</div>
</template>
<script setup>
-import { ref, reactive, computed, onMounted, markRaw, shallowRef, getCurrentInstance } from 'vue'
-import { ElMessage, ElMessageBox } from 'element-plus'
-import { Search, Document, UserFilled, Box, EditPen, Plus, ArrowRight, Delete, Download, View } from '@element-plus/icons-vue'
+import {ref, reactive, computed, onMounted, markRaw, shallowRef, getCurrentInstance} from 'vue'
+import {ElMessage, ElMessageBox} from 'element-plus'
+import {
+ Search,
+ Document,
+ UserFilled,
+ Box,
+ EditPen,
+ Plus,
+ ArrowRight,
+ Delete,
+} from '@element-plus/icons-vue'
import Pagination from '@/components/PIMTable/Pagination.vue'
import FormDialog from '@/components/Dialog/FormDialog.vue'
-import {getQuotationList,addQuotation,updateQuotation,deleteQuotation, importQuotation} from '@/api/salesManagement/salesQuotation.js'
+import ImportQuotationDetail from '@/views/salesManagement/salesQuotation/ImportQuotationDetail.vue'
+import {
+ getQuotationList,
+ addQuotation,
+ updateQuotation,
+ deleteQuotation,
+ importQuotation
+} from '@/api/salesManagement/salesQuotation.js'
import {userListNoPage} from "@/api/system/user.js";
import {customerList} from "@/api/salesManagement/salesLedger.js";
import {modelList, productTreeList} from "@/api/basicData/product.js";
-const { proxy } = getCurrentInstance();
+const {proxy} = getCurrentInstance();
// 鍝嶅簲寮忔暟鎹�
const loading = ref(false)
@@ -491,7 +547,7 @@
const viewDialogVisible = ref(false)
const importFileList = ref([])
const importApproverNodes = ref([
- { id: 1, userId: null }
+ {id: 1, userId: null}
])
let nextImportApproverId = 2
@@ -517,21 +573,21 @@
})
const baseRules = {
- customer: [{ required: true, message: '璇烽�夋嫨瀹㈡埛', trigger: 'change' }],
- salesperson: [{ required: true, message: '璇烽�夋嫨涓氬姟鍛�', trigger: 'change' }],
- quotationDate: [{ required: true, message: '璇烽�夋嫨鎶ヤ环鏃ユ湡', trigger: 'change' }],
- validDate: [{ required: true, message: '璇烽�夋嫨鏈夋晥鏈�', trigger: 'change' }],
- paymentMethod: [{ required: true, message: '璇疯緭鍏ヤ粯娆炬柟寮�', trigger: 'blur' }]
+ customer: [{required: true, message: '璇烽�夋嫨瀹㈡埛', trigger: 'change'}],
+ salesperson: [{required: true, message: '璇烽�夋嫨涓氬姟鍛�', trigger: 'change'}],
+ quotationDate: [{required: true, message: '璇烽�夋嫨鎶ヤ环鏃ユ湡', trigger: 'change'}],
+ validDate: [{required: true, message: '璇烽�夋嫨鏈夋晥鏈�', trigger: 'change'}],
+ paymentMethod: [{required: true, message: '璇疯緭鍏ヤ粯娆炬柟寮�', trigger: 'blur'}]
}
const productRowRules = {
- productId: [{ required: true, message: '璇烽�夋嫨浜у搧鍚嶇О', trigger: 'change' }],
- specificationId: [{ required: true, message: '璇烽�夋嫨瑙勬牸鍨嬪彿', trigger: 'change' }],
- unit: [{ required: true, message: '璇峰~鍐欏崟浣�', trigger: 'blur' }],
- unitPrice: [{ required: true, message: '璇峰~鍐欏崟浠�', trigger: 'change' }]
+ productId: [{required: true, message: '璇烽�夋嫨浜у搧鍚嶇О', trigger: 'change'}],
+ specificationId: [{required: true, message: '璇烽�夋嫨瑙勬牸鍨嬪彿', trigger: 'change'}],
+ unit: [{required: true, message: '璇峰~鍐欏崟浣�', trigger: 'blur'}],
+ unitPrice: [{required: true, message: '璇峰~鍐欏崟浠�', trigger: 'change'}]
}
const rules = computed(() => {
- const r = { ...baseRules }
+ const r = {...baseRules}
;(form.products || []).forEach((_, i) => {
r[`products.${i}.productId`] = productRowRules.productId
r[`products.${i}.specificationId`] = productRowRules.specificationId
@@ -545,18 +601,19 @@
// 瀹℃壒浜鸿妭鐐圭浉鍏�
const approverNodes = ref([
- { id: 1, userId: null }
+ {id: 1, userId: null}
])
let nextApproverId = 2
const isEdit = ref(false)
+const showDetail = ref(false)
const editId = ref(null)
const currentQuotation = ref({})
const formRef = ref()
// 娣诲姞瀹℃壒浜鸿妭鐐�
function addApproverNode() {
- approverNodes.value.push({ id: nextApproverId++, userId: null })
+ approverNodes.value.push({id: nextApproverId++, userId: null})
}
// 鍒犻櫎瀹℃壒浜鸿妭鐐�
@@ -566,7 +623,7 @@
// 瀵煎叆寮圭獥瀹℃壒浜鸿妭鐐圭浉鍏�
function addImportApproverNode() {
- importApproverNodes.value.push({ id: nextImportApproverId++, userId: null })
+ importApproverNodes.value.push({id: nextImportApproverId++, userId: null})
}
function removeImportApproverNode(index) {
@@ -600,7 +657,7 @@
const formData = new FormData()
formData.append('file', rawFile)
-
+
// 瀹℃牳浜� IDs锛屼互閫楀彿鍒嗗壊
const approveUserIds = importApproverNodes.value.map(node => node.userId).join(',')
formData.append('approveUserIdsJson', approveUserIds)
@@ -659,7 +716,7 @@
importFileList.value = list
};
- // 澶勭悊鏂囦欢绉婚櫎
+// 澶勭悊鏂囦欢绉婚櫎
function triggerRemoveFile(file) {
fileUpload.value?.handleRemove?.(file) || proxy.$refs.fileUpload?.handleRemove?.(file);
}
@@ -711,7 +768,7 @@
importFileList.value = []
// 鉁� 娓呯┖鈥滃鍏ョ敤鈥濈殑瀹℃壒浜�
- importApproverNodes.value = [{ id: 1, userId: null }]
+ importApproverNodes.value = [{id: 1, userId: null}]
nextImportApproverId = 2
let userLists = await userListNoPage();
@@ -729,118 +786,121 @@
isEdit.value = false
resetForm()
// 閲嶇疆瀹℃壒浜鸿妭鐐�
- approverNodes.value = [{ id: 1, userId: null }]
+ approverNodes.value = [{id: 1, userId: null}]
nextApproverId = 2
dialogVisible.value = true
- let userLists = await userListNoPage();
- // 鍙鍒堕渶瑕佺殑瀛楁锛岄伩鍏嶅皢缁勪欢寮曠敤鏀惧叆鍝嶅簲寮忓璞�
- userList.value = (userLists.data || []).map(item => ({
+ let userLists = await userListNoPage();
+ // 鍙鍒堕渶瑕佺殑瀛楁锛岄伩鍏嶅皢缁勪欢寮曠敤鏀惧叆鍝嶅簲寮忓璞�
+ userList.value = (userLists.data || []).map(item => ({
userId: item.userId,
nickName: item.nickName || '',
userName: item.userName || ''
}));
- getProductOptions();
- customerList().then((res) => {
- // 鍙鍒堕渶瑕佺殑瀛楁锛岄伩鍏嶅皢缁勪欢寮曠敤鏀惧叆鍝嶅簲寮忓璞�
- customerOption.value = (Array.isArray(res) ? res : []).map(item => ({
+ getProductOptions();
+ customerList().then((res) => {
+ // 鍙鍒堕渶瑕佺殑瀛楁锛岄伩鍏嶅皢缁勪欢寮曠敤鏀惧叆鍝嶅簲寮忓璞�
+ customerOption.value = (Array.isArray(res) ? res : []).map(item => ({
id: item.id,
customerName: item.customerName || '',
taxpayerIdentificationNumber: item.taxpayerIdentificationNumber || ''
}))
- });
+ });
}
const getProductOptions = () => {
- // 杩斿洖 Promise锛屼究浜庣紪杈戞椂 await 纭繚鑳藉弽鏄�
- return productTreeList().then((res) => {
- productOptions.value = convertIdToValue(res);
- return productOptions.value
- });
+ // 杩斿洖 Promise锛屼究浜庣紪杈戞椂 await 纭繚鑳藉弽鏄�
+ return productTreeList().then((res) => {
+ productOptions.value = convertIdToValue(res);
+ return productOptions.value
+ });
};
+
function convertIdToValue(data) {
- return data.map((item) => {
- const { id, children, ...rest } = item;
- const newItem = {
- ...rest,
- value: id, // 灏� id 鏀逛负 value
- };
- if (children && children.length > 0) {
- newItem.children = convertIdToValue(children);
- }
-
- return newItem;
- });
+ return data.map((item) => {
+ const {id, children, ...rest} = item;
+ const newItem = {
+ ...rest,
+ value: id, // 灏� id 鏀逛负 value
+ };
+ if (children && children.length > 0) {
+ newItem.children = convertIdToValue(children);
+ }
+
+ return newItem;
+ });
}
+
// 鏍规嵁鍚嶇О鍙嶆煡鑺傜偣 id锛屼究浜庝粎瀛樺悕绉版椂鐨勫弽鏄�
function findNodeIdByLabel(nodes, label) {
- if (!label) return null;
- for (let i = 0; i < nodes.length; i++) {
- const node = nodes[i];
- if (node.label === label) return node.value;
- if (node.children && node.children.length > 0) {
- const found = findNodeIdByLabel(node.children, label);
- if (found !== null && found !== undefined) return found;
- }
- }
- return null;
+ if (!label) return null;
+ for (let i = 0; i < nodes.length; i++) {
+ const node = nodes[i];
+ if (node.label === label) return node.value;
+ if (node.children && node.children.length > 0) {
+ const found = findNodeIdByLabel(node.children, label);
+ if (found !== null && found !== undefined) return found;
+ }
+ }
+ return null;
}
+
const getModels = (value, row) => {
- if (!row) return;
- // 濡傛灉娓呯┖閫夋嫨锛屽垯娓呯┖鐩稿叧瀛楁
- if (!value) {
- row.productId = '';
- row.product = '';
- row.modelOptions = [];
- row.specificationId = '';
- row.specification = '';
- row.unit = '';
- return;
- }
- // 鏇存柊 productId锛坴-model 宸茬粡鑷姩鏇存柊锛岃繖閲岀‘淇濅竴鑷存�э級
- row.productId = value;
- // 鎵惧埌瀵瑰簲鐨� label 骞惰祴鍊肩粰 row.product
- const label = findNodeById(productOptions.value, value);
- if (label) {
- row.product = label;
- }
- // 鑾峰彇瑙勬牸鍨嬪彿鍒楄〃锛岃缃埌褰撳墠琛岀殑 modelOptions
- modelList({ id: value }).then((res) => {
- row.modelOptions = res || [];
- });
+ if (!row) return;
+ // 濡傛灉娓呯┖閫夋嫨锛屽垯娓呯┖鐩稿叧瀛楁
+ if (!value) {
+ row.productId = '';
+ row.product = '';
+ row.modelOptions = [];
+ row.specificationId = '';
+ row.specification = '';
+ row.unit = '';
+ return;
+ }
+ // 鏇存柊 productId锛坴-model 宸茬粡鑷姩鏇存柊锛岃繖閲岀‘淇濅竴鑷存�э級
+ row.productId = value;
+ // 鎵惧埌瀵瑰簲鐨� label 骞惰祴鍊肩粰 row.product
+ const label = findNodeById(productOptions.value, value);
+ if (label) {
+ row.product = label;
+ }
+ // 鑾峰彇瑙勬牸鍨嬪彿鍒楄〃锛岃缃埌褰撳墠琛岀殑 modelOptions
+ modelList({id: value}).then((res) => {
+ row.modelOptions = res || [];
+ });
};
const getProductModel = (value, row) => {
- if (!row) return;
- // 濡傛灉娓呯┖閫夋嫨锛屽垯娓呯┖鐩稿叧瀛楁
- if (!value) {
- row.specificationId = '';
- row.specification = '';
- row.unit = '';
- return;
- }
- // 鏇存柊 specificationId锛坴-model 宸茬粡鑷姩鏇存柊锛岃繖閲岀‘淇濅竴鑷存�э級
- row.specificationId = value;
- const modelOptions = row.modelOptions || [];
- const index = modelOptions.findIndex((item) => item.id === value);
- if (index !== -1) {
- row.specification = modelOptions[index].model;
- row.unit = modelOptions[index].unit;
- } else {
- row.specification = '';
- row.unit = '';
- }
+ if (!row) return;
+ // 濡傛灉娓呯┖閫夋嫨锛屽垯娓呯┖鐩稿叧瀛楁
+ if (!value) {
+ row.specificationId = '';
+ row.specification = '';
+ row.unit = '';
+ return;
+ }
+ // 鏇存柊 specificationId锛坴-model 宸茬粡鑷姩鏇存柊锛岃繖閲岀‘淇濅竴鑷存�э級
+ row.specificationId = value;
+ const modelOptions = row.modelOptions || [];
+ const index = modelOptions.findIndex((item) => item.id === value);
+ if (index !== -1) {
+ row.specification = modelOptions[index].model;
+ row.unit = modelOptions[index].unit;
+ } else {
+ row.specification = '';
+ row.unit = '';
+ }
};
const findNodeById = (nodes, productId) => {
- for (let i = 0; i < nodes.length; i++) {
- if (nodes[i].value === productId) {
- return nodes[i].label; // 鎵惧埌鑺傜偣锛岃繑鍥� label
- }
- if (nodes[i].children && nodes[i].children.length > 0) {
- const foundLabel = findNodeById(nodes[i].children, productId);
- if (foundLabel) {
- return foundLabel; // 鍦ㄥ瓙鑺傜偣涓壘鍒帮紝杩斿洖 label
- }
- }
- }
- return null; // 娌℃湁鎵惧埌鑺傜偣锛岃繑鍥瀗ull
+ for (let i = 0; i < nodes.length; i++) {
+ if (nodes[i].value === productId) {
+ return nodes[i].label; // 鎵惧埌鑺傜偣锛岃繑鍥� label
+ }
+ if (nodes[i].children && nodes[i].children.length > 0) {
+ const foundLabel = findNodeById(nodes[i].children, productId);
+ if (foundLabel) {
+ return foundLabel; // 鍦ㄥ瓙鑺傜偣涓壘鍒帮紝杩斿洖 label
+ }
+ }
+ }
+ return null; // 娌℃湁鎵惧埌鑺傜偣锛岃繑鍥瀗ull
};
const handleView = (row) => {
// 鍙鍒堕渶瑕佺殑瀛楁锛岄伩鍏嶅皢缁勪欢寮曠敤鏀惧叆鍝嶅簲寮忓璞�
@@ -889,18 +949,18 @@
const productName = product.product || product.productName || ''
// 浼樺厛鐢� productId锛涘鏋滃彧鏈夊悕绉帮紝灏濊瘯鍙嶆煡 id 浠ヤ究鏍戦�夋嫨鍣ㄥ弽鏄�
const resolvedProductId = product.productId
- ? Number(product.productId)
- : findNodeIdByLabel(productOptions.value, productName) || ''
-
+ ? Number(product.productId)
+ : findNodeIdByLabel(productOptions.value, productName) || ''
+
// 濡傛灉鏈変骇鍝両D锛屽姞杞藉搴旂殑瑙勬牸鍨嬪彿鍒楄〃
let modelOptions = [];
let resolvedSpecificationId = product.specificationId || '';
-
+
if (resolvedProductId) {
try {
- const res = await modelList({ id: resolvedProductId });
+ const res = await modelList({id: resolvedProductId});
modelOptions = res || [];
-
+
// 濡傛灉杩斿洖鐨勬暟鎹病鏈� specificationId锛屼絾鏈� specification 鍚嶇О锛屾牴鎹悕绉版煡鎵� ID
if (!resolvedSpecificationId && product.specification) {
const foundModel = modelOptions.find(item => item.model === product.specification);
@@ -912,7 +972,7 @@
console.error('鍔犺浇瑙勬牸鍨嬪彿澶辫触:', error);
}
}
-
+
return {
productId: resolvedProductId,
product: productName,
@@ -931,7 +991,7 @@
form.discountRate = row.discountRate || 0
form.discountAmount = row.discountAmount || 0
form.totalAmount = row.totalAmount || 0
-
+
// 鍙嶆樉瀹℃壒浜�
if (row.approveUserIds) {
const userIds = row.approveUserIds.split(',')
@@ -941,10 +1001,10 @@
}))
nextApproverId = userIds.length + 1
} else {
- approverNodes.value = [{ id: 1, userId: null }]
+ approverNodes.value = [{id: 1, userId: null}]
nextApproverId = 2
}
-
+
// 鍔犺浇鐢ㄦ埛鍒楄〃
let userLists = await userListNoPage();
userList.value = (userLists.data || []).map(item => ({
@@ -952,7 +1012,7 @@
nickName: item.nickName || '',
userName: item.userName || ''
}));
-
+
dialogVisible.value = true
}
@@ -965,9 +1025,9 @@
}).then(() => {
const index = quotationList.value.findIndex(item => item.id === row.id)
if (index > -1) {
- deleteQuotation(row.id).then(res=>{
+ deleteQuotation(row.id).then(res => {
// console.log(res)
- if(res.code===200){
+ if (res.code === 200) {
ElMessage.success('鍒犻櫎鎴愬姛')
handleSearch()
}
@@ -1049,23 +1109,23 @@
ElMessage.error('璇蜂负鎵�鏈夊鎵硅妭鐐归�夋嫨瀹℃壒浜猴紒')
return
}
-
+
// 鏀堕泦鎵�鏈夎妭鐐圭殑瀹℃壒浜篿d
form.approveUserIds = approverNodes.value.map(node => node.userId).join(',')
-
+
// 璁$畻鎵�鏈変骇鍝佺殑鍗曚环鎬诲拰
form.totalAmount = form.products.reduce((sum, product) => {
const price = Number(product.unitPrice) || 0
return sum + price
}, 0)
-
+
if (isEdit.value) {
// 缂栬緫
const index = quotationList.value.findIndex(item => item.id === editId.value)
if (index > -1) {
- updateQuotation(form).then(res=>{
+ updateQuotation(form).then(res => {
// console.log(res)
- if(res.code===200){
+ if (res.code === 200) {
ElMessage.success('缂栬緫鎴愬姛')
dialogVisible.value = false
handleSearch()
@@ -1074,17 +1134,21 @@
}
} else {
// 鏂板
- addQuotation(form).then(res=>{
- if(res.code===200){
+ addQuotation(form).then(res => {
+ if (res.code === 200) {
ElMessage.success('鏂板鎴愬姛')
dialogVisible.value = false
handleSearch()
}
})
}
-
+
}
})
+}
+
+const downloadImportTemplate = () => {
+ proxy.download("/sales/quotation/downloadTemplate", {}, "鎶ヤ环鍗曞鍏ユā鏉�.xlsx");
}
const handleCurrentChange = (val) => {
@@ -1093,16 +1157,16 @@
// 鍒嗛〉鍙樺寲鏃堕噸鏂版煡璇㈠垪琛�
handleSearch()
}
-const handleSearch = ()=>{
+const handleSearch = () => {
const params = {
// 鍚庣鍒嗛〉鍙傛暟锛歝urrent / size
current: pagination.currentPage,
size: pagination.pageSize,
...searchForm
}
- getQuotationList(params).then(res=>{
+ getQuotationList(params).then(res => {
// console.log(res)
- if(res.code===200){
+ if (res.code === 200) {
// 鍙鍒堕渶瑕佺殑瀛楁锛岄伩鍏嶅皢缁勪欢寮曠敤鎴栧叾浠栧璞℃斁鍏ュ搷搴斿紡瀵硅薄
quotationList.value = (res.data.records || []).map(item => ({
id: item.id,
@@ -1136,17 +1200,23 @@
pagination.total = res.data.total
}
})
- customerList().then((res) => {
- // 鍙鍒堕渶瑕佺殑瀛楁锛岄伩鍏嶅皢缁勪欢寮曠敤鏀惧叆鍝嶅簲寮忓璞�
- customerOption.value = (Array.isArray(res) ? res : []).map(item => ({
+ customerList().then((res) => {
+ // 鍙鍒堕渶瑕佺殑瀛楁锛岄伩鍏嶅皢缁勪欢寮曠敤鏀惧叆鍝嶅簲寮忓璞�
+ customerOption.value = (Array.isArray(res) ? res : []).map(item => ({
id: item.id,
customerName: item.customerName || '',
taxpayerIdentificationNumber: item.taxpayerIdentificationNumber || ''
}))
- });
+ });
}
-onMounted(()=>{
+const handleImportDetail = (row) => {
+ showDetail.value = true
+ currentQuotation.value = row
+}
+
+
+onMounted(() => {
handleSearch()
})
</script>
@@ -1160,16 +1230,16 @@
padding: 10px 0;
max-height: calc(100vh - 200px);
overflow-y: auto;
-
+
&::-webkit-scrollbar {
width: 6px;
height: 6px;
}
-
+
&::-webkit-scrollbar-thumb {
background: #c1c1c1;
border-radius: 3px;
-
+
&:hover {
background: #a8a8a8;
}
@@ -1186,17 +1256,17 @@
margin-bottom: 24px;
border-radius: 8px;
transition: all 0.3s ease;
-
+
&:hover {
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08) !important;
}
-
+
:deep(.el-card__header) {
padding: 16px 20px;
background: linear-gradient(135deg, #f5f7fa 0%, #ffffff 100%);
border-bottom: 1px solid #ebeef5;
}
-
+
:deep(.el-card__body) {
padding: 20px;
}
@@ -1206,19 +1276,19 @@
display: flex;
align-items: center;
gap: 8px;
-
+
.card-icon {
font-size: 18px;
color: #409eff;
}
-
+
.card-title {
font-weight: 600;
font-size: 16px;
color: #303133;
flex: 1;
}
-
+
.header-btn {
margin-left: auto;
}
@@ -1230,9 +1300,11 @@
.product-table-form-item {
margin-bottom: 0;
+
:deep(.el-form-item__content) {
margin-left: 0 !important;
}
+
:deep(.el-form-item__label) {
width: auto;
min-width: auto;
@@ -1257,7 +1329,7 @@
border: 1px solid #e4e7ed;
transition: all 0.3s ease;
min-width: 180px;
-
+
&:hover {
border-color: #409eff;
background: #f0f7ff;
@@ -1271,7 +1343,7 @@
gap: 8px;
font-size: 14px;
color: #606266;
-
+
.node-step {
display: inline-flex;
align-items: center;
@@ -1284,11 +1356,11 @@
font-size: 12px;
font-weight: 600;
}
-
+
.node-text {
font-weight: 500;
}
-
+
.arrow-icon {
color: #909399;
font-size: 14px;
@@ -1307,20 +1379,20 @@
.product-table {
:deep(.el-table__header) {
background-color: #f5f7fa;
-
+
th {
background-color: #f5f7fa !important;
color: #606266;
font-weight: 600;
}
}
-
+
:deep(.el-table__row) {
&:hover {
background-color: #f5f7fa;
}
}
-
+
:deep(.el-table__cell) {
padding: 12px 0;
}
@@ -1335,7 +1407,7 @@
.approver-nodes-container {
gap: 16px;
}
-
+
.approver-node-item {
min-width: 160px;
}
--
Gitblit v1.9.3