From 7ec0b6ddb14897fa47769b14cc4cb36049bb5ebb Mon Sep 17 00:00:00 2001
From: 云 <2163098428@qq.com>
Date: 星期一, 22 六月 2026 09:11:53 +0800
Subject: [PATCH] 1、报价系统中,需将付款方式改为选择项(现金、电汇、微信、支付宝等),不能做成手工输入;4、退货单未明确退货规则;5、客户往来信息过于简单,只做总结性信息,无多维度明细信息;
---
src/views/salesManagement/deliveryLedger/index.vue | 35
src/api/salesManagement/indicatorStats.js | 27
src/views/salesManagement/receiptPaymentLedger/detail.vue | 387 +++++++++
src/views/salesManagement/receiptPaymentLedger/index.vue | 30
src/views/salesManagement/salesLedger/index.vue | 39
src/views/salesManagement/salesQuotation/index.vue | 10
src/router/index.js | 13
src/views/salesManagement/returnOrder/index.vue | 15
src/views/procurementManagement/procurementLedger/index.vue | 13
doc/20260618_customer_transactions_optimization.md | 788 ++++++++++++++++++
src/views/salesManagement/returnOrder/components/formDia.vue | 139 ++
doc/20260618_return_status_field.md | 201 ++++
src/api/salesManagement/returnOrder.js | 10
doc/20260618_shipping_info_for_return.md | 365 ++++++++
src/views/salesManagement/receiptPaymentLedger/components/ShipmentTable.vue | 197 ++++
src/views/salesManagement/receiptPaymentLedger/components/ProductTable.vue | 229 +++++
16 files changed, 2,471 insertions(+), 27 deletions(-)
diff --git a/doc/20260618_customer_transactions_optimization.md b/doc/20260618_customer_transactions_optimization.md
new file mode 100644
index 0000000..b228183
--- /dev/null
+++ b/doc/20260618_customer_transactions_optimization.md
@@ -0,0 +1,788 @@
+# 瀹㈡埛寰�鏉ュ缁村害鏄庣粏鍔熻兘鍓嶇鑱旇皟鏂囨。
+
+> 浼樺寲瀹㈡埛寰�鏉ュ姛鑳斤紝鏂板澶氱淮搴︽槑缁嗘煡璇㈡帴鍙o紝鏀寔浜у搧鏄庣粏鍜屽彂璐ф槑缁嗙淮搴�
+
+## 娑夊強椤甸潰
+
+- 钀ラ攢绠$悊 / 瀹㈡埛寰�鏉� - 瀹㈡埛寰�鏉ュ垪琛ㄩ〉
+- 钀ラ攢绠$悊 / 瀹㈡埛寰�鏉� - 瀹㈡埛寰�鏉ヨ鎯呴〉锛堟柊澧烇級
+- 钀ラ攢绠$悊 / 瀹㈡埛寰�鏉� - 浜у搧鏄庣粏Tab锛堟柊澧烇級
+- 钀ラ攢绠$悊 / 瀹㈡埛寰�鏉� - 鍙戣揣鏄庣粏Tab锛堟柊澧烇級
+
+## API
+
+### 1. 瀹㈡埛寰�鏉ュ垪琛紙鍘熸湁鎺ュ彛锛屾湭鍙樻洿锛�
+
+| 鏂规硶 | 璺緞 | 璇存槑 |
+|------|------|------|
+| GET | /metricStatistics/customewTransactions | 瀹㈡埛寰�鏉ュ垪琛� |
+
+**璇锋眰鍙傛暟锛�**
+
+| 鍙傛暟 | 绫诲瀷 | 蹇呭~ | 璇存槑 |
+|------|------|------|------|
+| pageNum | Long | 鍚� | 椤电爜锛岄粯璁�1 |
+| pageSize | Long | 鍚� | 姣忛〉鏉℃暟锛岄粯璁�10 |
+| customerName | String | 鍚� | 瀹㈡埛鍚嶇О锛堟ā绯婃悳绱級 |
+
+**鍝嶅簲瀛楁锛�**
+
+| 瀛楁 | 绫诲瀷 | 璇存槑 |
+|------|------|------|
+| customerId | Long | 瀹㈡埛ID |
+| customerName | String | 瀹㈡埛鍚嶇О |
+| contractAmounts | BigDecimal | 鍚堝悓鎬婚噾棰� |
+| receiptPaymentAmount | BigDecimal | 鏀舵閲戦 |
+| receiptableAmount | BigDecimal | 搴旀敹閲戦 |
+
+---
+
+### 2. 瀹㈡埛寰�鏉ョ粺璁℃眹鎬伙紙鏂板锛�
+
+| 鏂规硶 | 璺緞 | 璇存槑 |
+|------|------|------|
+| GET | /metricStatistics/customerTransactionsSummary | 瀹㈡埛寰�鏉ョ粺璁℃眹鎬� |
+
+**璇锋眰鍙傛暟锛�**
+
+| 鍙傛暟 | 绫诲瀷 | 蹇呭~ | 璇存槑 |
+|------|------|------|------|
+| customerId | Long | 鏄� | 瀹㈡埛ID |
+
+**鍝嶅簲瀛楁锛�**
+
+| 瀛楁 | 绫诲瀷 | 璇存槑 |
+|------|------|------|
+| customerId | Long | 瀹㈡埛ID |
+| customerName | String | 瀹㈡埛鍚嶇О |
+| contractAmounts | BigDecimal | 鍚堝悓鎬婚噾棰� |
+| contractCount | Integer | 鍚堝悓鏁伴噺 |
+| productCount | Integer | 浜у搧绉嶇被鏁� |
+| shippedAmounts | BigDecimal | 鍙戣揣鎬婚噾棰� |
+| shippedQuantity | BigDecimal | 鍙戣揣鎬绘暟閲� |
+| receivedAmounts | BigDecimal | 鏀舵閲戦 |
+| receivableAmounts | BigDecimal | 搴旀敹閲戦 |
+| returnAmounts | BigDecimal | 閫�璐ч噾棰� |
+| unshippedAmounts | BigDecimal | 鏈彂璐ч噾棰� |
+| receivedRate | BigDecimal | 鏀舵鐜�(%) |
+| shippedRate | BigDecimal | 鍙戣揣鐜�(%) |
+
+**鍝嶅簲绀轰緥锛�**
+
+```json
+{
+ "code": 200,
+ "msg": "鎿嶄綔鎴愬姛",
+ "data": {
+ "customerId": 1,
+ "customerName": "瀹㈡埛A",
+ "contractAmounts": 100000.00,
+ "contractCount": 5,
+ "productCount": 12,
+ "shippedAmounts": 80000.00,
+ "shippedQuantity": 500,
+ "receivedAmounts": 60000.00,
+ "receivableAmounts": 20000.00,
+ "returnAmounts": 5000.00,
+ "unshippedAmounts": 20000.00,
+ "receivedRate": 75.00,
+ "shippedRate": 80.00
+ }
+}
+```
+
+---
+
+### 3. 瀹㈡埛寰�鏉ヤ骇鍝佹槑缁嗭紙鏂板锛�
+
+| 鏂规硶 | 璺緞 | 璇存槑 |
+|------|------|------|
+| GET | /metricStatistics/customerTransactionsProducts | 瀹㈡埛寰�鏉ヤ骇鍝佹槑缁� |
+
+**璇锋眰鍙傛暟锛�**
+
+| 鍙傛暟 | 绫诲瀷 | 蹇呭~ | 璇存槑 |
+|------|------|------|------|
+| customerId | Long | 鏄� | 瀹㈡埛ID |
+| salesLedgerId | Long | 鍚� | 閿�鍞彴璐D锛堝彲閫夛紝鐢ㄤ簬绛涢�夋煇鍚堝悓锛� |
+| pageNum | Long | 鍚� | 椤电爜锛岄粯璁�1 |
+| pageSize | Long | 鍚� | 姣忛〉鏉℃暟锛岄粯璁�10 |
+
+**鍝嶅簲瀛楁锛�**
+
+| 瀛楁 | 绫诲瀷 | 璇存槑 |
+|------|------|------|
+| salesLedgerId | Long | 閿�鍞彴璐D |
+| salesContractNo | String | 閿�鍞悎鍚屽彿 |
+| productId | Long | 浜у搧ID |
+| productName | String | 浜у搧鍚嶇О |
+| model | String | 瑙勬牸鍨嬪彿 |
+| unit | String | 鍗曚綅 |
+| contractQuantity | BigDecimal | 鍚堝悓鏁伴噺 |
+| taxInclusiveUnitPrice | BigDecimal | 鍚堝悓鍗曚环(鍚◣) |
+| contractAmount | BigDecimal | 鍚堝悓閲戦 |
+| shippedQuantity | BigDecimal | 宸插彂璐ф暟閲� |
+| shippedAmount | BigDecimal | 宸插彂璐ч噾棰� |
+| receivedAmount | BigDecimal | 宸叉敹娆鹃噾棰� |
+| receivableAmount | BigDecimal | 搴旀敹閲戦 |
+
+**鍝嶅簲绀轰緥锛�**
+
+```json
+{
+ "code": 200,
+ "msg": "鎿嶄綔鎴愬姛",
+ "data": {
+ "records": [
+ {
+ "salesLedgerId": 1,
+ "salesContractNo": "HT-2026-001",
+ "productId": 10,
+ "productName": "浜у搧A",
+ "model": "瑙勬牸1",
+ "unit": "浠�",
+ "contractQuantity": 100,
+ "taxInclusiveUnitPrice": 50.00,
+ "contractAmount": 5000.00,
+ "shippedQuantity": 80,
+ "shippedAmount": 4000.00,
+ "receivedAmount": 3000.00,
+ "receivableAmount": 1000.00
+ }
+ ],
+ "total": 25,
+ "pageNum": 1,
+ "pageSize": 10
+ }
+}
+```
+
+---
+
+### 4. 瀹㈡埛寰�鏉ュ彂璐ф槑缁嗭紙鏂板锛�
+
+| 鏂规硶 | 璺緞 | 璇存槑 |
+|------|------|------|
+| GET | /metricStatistics/customerTransactionsShipments | 瀹㈡埛寰�鏉ュ彂璐ф槑缁� |
+
+**璇锋眰鍙傛暟锛�**
+
+| 鍙傛暟 | 绫诲瀷 | 蹇呭~ | 璇存槑 |
+|------|------|------|------|
+| customerId | Long | 鏄� | 瀹㈡埛ID |
+| salesLedgerId | Long | 鍚� | 閿�鍞彴璐D锛堝彲閫夛紝鐢ㄤ簬绛涢�夋煇鍚堝悓锛� |
+| pageNum | Long | 鍚� | 椤电爜锛岄粯璁�1 |
+| pageSize | Long | 鍚� | 姣忛〉鏉℃暟锛岄粯璁�10 |
+
+**鍝嶅簲瀛楁锛�**
+
+| 瀛楁 | 绫诲瀷 | 璇存槑 |
+|------|------|------|
+| salesLedgerId | Long | 閿�鍞彴璐D |
+| salesContractNo | String | 閿�鍞悎鍚屽彿 |
+| shippingId | Long | 鍙戣揣鍗旾D |
+| shippingNo | String | 鍙戣揣鍗曞彿 |
+| productName | String | 浜у搧鍚嶇О |
+| model | String | 瑙勬牸鍨嬪彿 |
+| shippingQuantity | BigDecimal | 鍙戣揣鏁伴噺 |
+| shippingAmount | BigDecimal | 鍙戣揣閲戦(鍚◣) |
+| batchNo | String | 鍑哄簱鎵瑰彿 |
+| shippingDate | LocalDate | 鍙戣揣鏃ユ湡 |
+| approvalStatus | Integer | 瀹℃壒鐘舵��(0寰呭/1宸插) |
+| receivedAmount | BigDecimal | 宸叉敹娆鹃噾棰� |
+| receivableAmount | BigDecimal | 搴旀敹閲戦 |
+
+**鍝嶅簲绀轰緥锛�**
+
+```json
+{
+ "code": 200,
+ "msg": "鎿嶄綔鎴愬姛",
+ "data": {
+ "records": [
+ {
+ "salesLedgerId": 1,
+ "salesContractNo": "HT-2026-001",
+ "shippingId": 100,
+ "shippingNo": "FH-2026-001",
+ "productName": "浜у搧A",
+ "model": "瑙勬牸1",
+ "shippingQuantity": 50,
+ "shippingAmount": 2500.00,
+ "batchNo": "20260618001",
+ "shippingDate": "2026-06-18",
+ "approvalStatus": 1,
+ "receivedAmount": 2000.00,
+ "receivableAmount": 500.00
+ }
+ ],
+ "total": 30,
+ "pageNum": 1,
+ "pageSize": 10
+ }
+}
+```
+
+---
+
+## 鍓嶇椤甸潰璁捐
+
+### 1. 瀹㈡埛寰�鏉ュ垪琛ㄩ〉锛堜紭鍖栵級
+
+```html
+<template>
+ <div class="app-container">
+ <!-- 鎼滅储鏍� -->
+ <el-form :model="queryParams" ref="queryForm" :inline="true">
+ <el-form-item label="瀹㈡埛鍚嶇О" prop="customerName">
+ <el-input v-model="queryParams.customerName" placeholder="璇疯緭鍏ュ鎴峰悕绉�" clearable />
+ </el-form-item>
+ <el-form-item>
+ <el-button type="primary" @click="getList">鎼滅储</el-button>
+ <el-button @click="resetQuery">閲嶇疆</el-button>
+ </el-form-item>
+ </el-form>
+
+ <!-- 鏁版嵁琛ㄦ牸 -->
+ <el-table :data="list" v-loading="loading">
+ <el-table-column label="瀹㈡埛鍚嶇О" prop="customerName" />
+ <el-table-column label="鍚堝悓鎬婚噾棰�" prop="contractAmounts" align="right">
+ <template #default="{ row }">
+ {{ formatMoney(row.contractAmounts) }}
+ </template>
+ </el-table-column>
+ <el-table-column label="鏀舵閲戦" prop="receiptPaymentAmount" align="right">
+ <template #default="{ row }">
+ {{ formatMoney(row.receiptPaymentAmount) }}
+ </template>
+ </el-table-column>
+ <el-table-column label="搴旀敹閲戦" prop="receiptableAmount" align="right">
+ <template #default="{ row }">
+ <span :class="{ 'text-danger': row.receiptableAmount > 0 }">
+ {{ formatMoney(row.receiptableAmount) }}
+ </span>
+ </template>
+ </el-table-column>
+ <el-table-column label="鎿嶄綔" width="150" align="center">
+ <template #default="{ row }">
+ <el-button type="text" @click="viewDetail(row)">鏌ョ湅鏄庣粏</el-button>
+ </template>
+ </el-table-column>
+ </el-table>
+
+ <!-- 鍒嗛〉 -->
+ <el-pagination
+ v-show="total > 0"
+ :total="total"
+ :page.sync="queryParams.pageNum"
+ :limit.sync="queryParams.pageSize"
+ @pagination="getList"
+ />
+ </div>
+</template>
+
+<script>
+export default {
+ name: 'CustomerTransactions',
+ data() {
+ return {
+ loading: false,
+ list: [],
+ total: 0,
+ queryParams: {
+ pageNum: 1,
+ pageSize: 10,
+ customerName: ''
+ }
+ }
+ },
+ created() {
+ this.getList()
+ },
+ methods: {
+ getList() {
+ this.loading = true
+ this.$axios.get('/metricStatistics/customewTransactions', { params: this.queryParams })
+ .then(res => {
+ this.list = res.data.records
+ this.total = res.data.total
+ })
+ .finally(() => {
+ this.loading = false
+ })
+ },
+ resetQuery() {
+ this.queryParams.customerName = ''
+ this.getList()
+ },
+ formatMoney(value) {
+ if (!value) return '0.00'
+ return Number(value).toFixed(2)
+ },
+ viewDetail(row) {
+ this.$router.push({ path: '/sales/customerTransactions/detail', query: { customerId: row.customerId } })
+ }
+ }
+}
+</script>
+```
+
+---
+
+### 2. 瀹㈡埛寰�鏉ヨ鎯呴〉锛堟柊澧烇級
+
+```html
+<template>
+ <div class="app-container">
+ <!-- 椤堕儴缁熻鍗$墖 -->
+ <el-card class="summary-card">
+ <div slot="header">
+ <span>{{ summary.customerName }} - 寰�鏉ョ粺璁�</span>
+ </div>
+ <el-row :gutter="20">
+ <el-col :span="4">
+ <div class="stat-item">
+ <div class="stat-label">鍚堝悓鎬婚噾棰�</div>
+ <div class="stat-value">{{ formatMoney(summary.contractAmounts) }}</div>
+ </div>
+ </el-col>
+ <el-col :span="4">
+ <div class="stat-item">
+ <div class="stat-label">鍚堝悓鏁伴噺</div>
+ <div class="stat-value">{{ summary.contractCount }}浠�</div>
+ </div>
+ </el-col>
+ <el-col :span="4">
+ <div class="stat-item">
+ <div class="stat-label">浜у搧绉嶇被</div>
+ <div class="stat-value">{{ summary.productCount }}绉�</div>
+ </div>
+ </el-col>
+ <el-col :span="4">
+ <div class="stat-item">
+ <div class="stat-label">鍙戣揣閲戦</div>
+ <div class="stat-value">{{ formatMoney(summary.shippedAmounts) }}</div>
+ </div>
+ </el-col>
+ <el-col :span="4">
+ <div class="stat-item">
+ <div class="stat-label">鏀舵閲戦</div>
+ <div class="stat-value text-success">{{ formatMoney(summary.receivedAmounts) }}</div>
+ </div>
+ </el-col>
+ <el-col :span="4">
+ <div class="stat-item">
+ <div class="stat-label">搴旀敹閲戦</div>
+ <div class="stat-value text-danger">{{ formatMoney(summary.receivableAmounts) }}</div>
+ </div>
+ </el-col>
+ </el-row>
+ <el-row :gutter="20" style="margin-top: 15px;">
+ <el-col :span="4">
+ <div class="stat-item">
+ <div class="stat-label">閫�璐ч噾棰�</div>
+ <div class="stat-value">{{ formatMoney(summary.returnAmounts) }}</div>
+ </div>
+ </el-col>
+ <el-col :span="4">
+ <div class="stat-item">
+ <div class="stat-label">鏈彂璐ч噾棰�</div>
+ <div class="stat-value text-warning">{{ formatMoney(summary.unshippedAmounts) }}</div>
+ </div>
+ </el-col>
+ <el-col :span="4">
+ <div class="stat-item">
+ <div class="stat-label">鏀舵鐜�</div>
+ <div class="stat-value">
+ <el-progress :percentage="summary.receivedRate || 0" :stroke-width="18" />
+ </div>
+ </div>
+ </el-col>
+ <el-col :span="4">
+ <div class="stat-item">
+ <div class="stat-label">鍙戣揣鐜�</div>
+ <div class="stat-value">
+ <el-progress :percentage="summary.shippedRate || 0" :stroke-width="18" color="#67c23a" />
+ </div>
+ </div>
+ </el-col>
+ </el-row>
+ </el-card>
+
+ <!-- Tab 鍒囨崲 -->
+ <el-tabs v-model="activeTab" @tab-click="handleTabChange">
+ <el-tab-pane label="浜у搧鏄庣粏" name="products">
+ <product-table :customerId="customerId" />
+ </el-tab-pane>
+ <el-tab-pane label="鍙戣揣鏄庣粏" name="shipments">
+ <shipment-table :customerId="customerId" />
+ </el-tab-pane>
+ <el-tab-pane label="鍚堝悓鏄庣粏" name="contracts">
+ <contract-table :customerId="customerId" />
+ </el-tab-pane>
+ </el-tabs>
+ </div>
+</template>
+
+<script>
+import ProductTable from './components/ProductTable.vue'
+import ShipmentTable from './components/ShipmentTable.vue'
+import ContractTable from './components/ContractTable.vue'
+
+export default {
+ name: 'CustomerTransactionsDetail',
+ components: { ProductTable, ShipmentTable, ContractTable },
+ data() {
+ return {
+ customerId: null,
+ summary: {},
+ activeTab: 'products'
+ }
+ },
+ created() {
+ this.customerId = this.$route.query.customerId
+ if (this.customerId) {
+ this.getSummary()
+ }
+ },
+ methods: {
+ getSummary() {
+ this.$axios.get('/metricStatistics/customerTransactionsSummary', {
+ params: { customerId: this.customerId }
+ }).then(res => {
+ this.summary = res.data
+ })
+ },
+ formatMoney(value) {
+ if (!value) return '0.00'
+ return Number(value).toFixed(2)
+ },
+ handleTabChange(tab) {
+ // Tab 鍒囨崲鏃跺埛鏂板瓙缁勪欢鏁版嵁
+ }
+ }
+}
+</script>
+
+<style scoped>
+.summary-card {
+ margin-bottom: 20px;
+}
+.stat-item {
+ text-align: center;
+}
+.stat-label {
+ font-size: 14px;
+ color: #909399;
+}
+.stat-value {
+ font-size: 18px;
+ font-weight: bold;
+ margin-top: 5px;
+}
+.text-success {
+ color: #67c23a;
+}
+.text-danger {
+ color: #f56c6c;
+}
+.text-warning {
+ color: #e6a23c;
+}
+</style>
+```
+
+---
+
+### 3. 浜у搧鏄庣粏缁勪欢 (ProductTable.vue)
+
+```html
+<template>
+ <div>
+ <!-- 绛涢�� -->
+ <el-form :inline="true" size="small">
+ <el-form-item label="鍚堝悓鍙�">
+ <el-select v-model="filterData.salesLedgerId" clearable placeholder="鍏ㄩ儴鍚堝悓" @change="getList">
+ <el-option v-for="item in contractList" :key="item.id" :label="item.salesContractNo" :value="item.id" />
+ </el-select>
+ </el-form-item>
+ </el-form>
+
+ <!-- 琛ㄦ牸 -->
+ <el-table :data="list" v-loading="loading" size="small">
+ <el-table-column label="鍚堝悓鍙�" prop="salesContractNo" width="150" />
+ <el-table-column label="浜у搧鍚嶇О" prop="productName" />
+ <el-table-column label="瑙勬牸鍨嬪彿" prop="model" width="120" />
+ <el-table-column label="鍗曚綅" prop="unit" width="80" />
+ <el-table-column label="鍚堝悓鏁伴噺" prop="contractQuantity" align="right" width="100" />
+ <el-table-column label="鍚堝悓鍗曚环" prop="taxInclusiveUnitPrice" align="right" width="100">
+ <template #default="{ row }">
+ {{ formatMoney(row.taxInclusiveUnitPrice) }}
+ </template>
+ </el-table-column>
+ <el-table-column label="鍚堝悓閲戦" prop="contractAmount" align="right" width="120">
+ <template #default="{ row }">
+ {{ formatMoney(row.contractAmount) }}
+ </template>
+ </el-table-column>
+ <el-table-column label="宸插彂璐ф暟閲�" prop="shippedQuantity" align="right" width="100" />
+ <el-table-column label="宸插彂璐ч噾棰�" prop="shippedAmount" align="right" width="120">
+ <template #default="{ row }">
+ {{ formatMoney(row.shippedAmount) }}
+ </template>
+ </el-table-column>
+ <el-table-column label="宸叉敹娆鹃噾棰�" prop="receivedAmount" align="right" width="120">
+ <template #default="{ row }">
+ <span class="text-success">{{ formatMoney(row.receivedAmount) }}</span>
+ </template>
+ </el-table-column>
+ <el-table-column label="搴旀敹閲戦" prop="receivableAmount" align="right" width="120">
+ <template #default="{ row }">
+ <span :class="{ 'text-danger': row.receivableAmount > 0 }">
+ {{ formatMoney(row.receivableAmount) }}
+ </span>
+ </template>
+ </el-table-column>
+ <el-table-column label="鍙戣揣杩涘害" width="150">
+ <template #default="{ row }">
+ <el-progress
+ :percentage="calcPercent(row.shippedQuantity, row.contractQuantity)"
+ :stroke-width="10"
+ />
+ </template>
+ </el-table-column>
+ </el-table>
+
+ <!-- 鍒嗛〉 -->
+ <el-pagination
+ v-show="total > 0"
+ :total="total"
+ :page.sync="queryParams.pageNum"
+ :limit.sync="queryParams.pageSize"
+ layout="total, prev, pager, next"
+ @pagination="getList"
+ />
+ </div>
+</template>
+
+<script>
+export default {
+ name: 'ProductTable',
+ props: {
+ customerId: {
+ type: Number,
+ required: true
+ }
+ },
+ data() {
+ return {
+ loading: false,
+ list: [],
+ total: 0,
+ queryParams: {
+ pageNum: 1,
+ pageSize: 10,
+ customerId: null,
+ salesLedgerId: null
+ },
+ filterData: {
+ salesLedgerId: null
+ },
+ contractList: []
+ }
+ },
+ watch: {
+ customerId(val) {
+ if (val) {
+ this.queryParams.customerId = val
+ this.getList()
+ this.getContractList()
+ }
+ }
+ },
+ methods: {
+ getList() {
+ this.loading = true
+ this.queryParams.salesLedgerId = this.filterData.salesLedgerId
+ this.$axios.get('/metricStatistics/customerTransactionsProducts', { params: this.queryParams })
+ .then(res => {
+ this.list = res.data.records
+ this.total = res.data.total
+ })
+ .finally(() => {
+ this.loading = false
+ })
+ },
+ getContractList() {
+ // 鑾峰彇璇ュ鎴风殑鍚堝悓鍒楄〃鐢ㄤ簬绛涢��
+ this.$axios.get('/metricStatistics/customewTransactionsDetails', {
+ params: { customerId: this.customerId, pageNum: 1, pageSize: 100 }
+ }).then(res => {
+ this.contractList = res.data.records
+ })
+ },
+ formatMoney(value) {
+ if (!value) return '0.00'
+ return Number(value).toFixed(2)
+ },
+ calcPercent(shipped, total) {
+ if (!total || total === 0) return 0
+ return Math.round((shipped / total) * 100)
+ }
+ }
+}
+</script>
+```
+
+---
+
+### 4. 鍙戣揣鏄庣粏缁勪欢 (ShipmentTable.vue)
+
+```html
+<template>
+ <div>
+ <!-- 绛涢�� -->
+ <el-form :inline="true" size="small">
+ <el-form-item label="鍚堝悓鍙�">
+ <el-select v-model="filterData.salesLedgerId" clearable placeholder="鍏ㄩ儴鍚堝悓" @change="getList">
+ <el-option v-for="item in contractList" :key="item.id" :label="item.salesContractNo" :value="item.id" />
+ </el-select>
+ </el-form-item>
+ </el-form>
+
+ <!-- 琛ㄦ牸 -->
+ <el-table :data="list" v-loading="loading" size="small">
+ <el-table-column label="鍚堝悓鍙�" prop="salesContractNo" width="150" />
+ <el-table-column label="鍙戣揣鍗曞彿" prop="shippingNo" width="150" />
+ <el-table-column label="浜у搧鍚嶇О" prop="productName" />
+ <el-table-column label="瑙勬牸鍨嬪彿" prop="model" width="120" />
+ <el-table-column label="鍙戣揣鏁伴噺" prop="shippingQuantity" align="right" width="100" />
+ <el-table-column label="鍙戣揣閲戦" prop="shippingAmount" align="right" width="120">
+ <template #default="{ row }">
+ {{ formatMoney(row.shippingAmount) }}
+ </template>
+ </el-table-column>
+ <el-table-column label="鍑哄簱鎵瑰彿" prop="batchNo" width="150" />
+ <el-table-column label="鍙戣揣鏃ユ湡" prop="shippingDate" width="120" />
+ <el-table-column label="瀹℃壒鐘舵��" prop="approvalStatus" width="100">
+ <template #default="{ row }">
+ <el-tag :type="row.approvalStatus === 1 ? 'success' : 'warning'" size="mini">
+ {{ row.approvalStatus === 1 ? '宸插' : '寰呭' }}
+ </el-tag>
+ </template>
+ </el-table-column>
+ <el-table-column label="宸叉敹娆鹃噾棰�" prop="receivedAmount" align="right" width="120">
+ <template #default="{ row }">
+ <span class="text-success">{{ formatMoney(row.receivedAmount) }}</span>
+ </template>
+ </el-table-column>
+ <el-table-column label="搴旀敹閲戦" prop="receivableAmount" align="right" width="120">
+ <template #default="{ row }">
+ <span :class="{ 'text-danger': row.receivableAmount > 0 }">
+ {{ formatMoney(row.receivableAmount) }}
+ </span>
+ </template>
+ </el-table-column>
+ </el-table>
+
+ <!-- 鍒嗛〉 -->
+ <el-pagination
+ v-show="total > 0"
+ :total="total"
+ :page.sync="queryParams.pageNum"
+ :limit.sync="queryParams.pageSize"
+ layout="total, prev, pager, next"
+ @pagination="getList"
+ />
+ </div>
+</template>
+
+<script>
+export default {
+ name: 'ShipmentTable',
+ props: {
+ customerId: {
+ type: Number,
+ required: true
+ }
+ },
+ data() {
+ return {
+ loading: false,
+ list: [],
+ total: 0,
+ queryParams: {
+ pageNum: 1,
+ pageSize: 10,
+ customerId: null,
+ salesLedgerId: null
+ },
+ filterData: {
+ salesLedgerId: null
+ },
+ contractList: []
+ }
+ },
+ watch: {
+ customerId(val) {
+ if (val) {
+ this.queryParams.customerId = val
+ this.getList()
+ this.getContractList()
+ }
+ }
+ },
+ methods: {
+ getList() {
+ this.loading = true
+ this.queryParams.salesLedgerId = this.filterData.salesLedgerId
+ this.$axios.get('/metricStatistics/customerTransactionsShipments', { params: this.queryParams })
+ .then(res => {
+ this.list = res.data.records
+ this.total = res.data.total
+ })
+ .finally(() => {
+ this.loading = false
+ })
+ },
+ getContractList() {
+ this.$axios.get('/metricStatistics/customewTransactionsDetails', {
+ params: { customerId: this.customerId, pageNum: 1, pageSize: 100 }
+ }).then(res => {
+ this.contractList = res.data.records
+ })
+ },
+ formatMoney(value) {
+ if (!value) return '0.00'
+ return Number(value).toFixed(2)
+ }
+ }
+}
+</script>
+```
+
+---
+
+## 娉ㄦ剰浜嬮」
+
+1. **璺敱閰嶇疆**锛氶渶鍦ㄨ矾鐢变腑鏂板瀹㈡埛寰�鏉ヨ鎯呴〉璺敱 `/sales/customerTransactions/detail`
+2. **缁勪欢鎷嗗垎**锛氫骇鍝佹槑缁嗗拰鍙戣揣鏄庣粏寤鸿鎷嗗垎涓虹嫭绔嬬粍浠讹紝渚夸簬澶嶇敤鍜岀淮鎶�
+3. **绛涢�夎仈鍔�**锛氫骇鍝佹槑缁嗗拰鍙戣揣鏄庣粏鏀寔鎸夊悎鍚岀瓫閫夛紝鍚堝悓鍒楄〃浠庡師鏈夋帴鍙h幏鍙�
+4. **鏁版嵁鏍煎紡**锛氶噾棰濆瓧娈甸渶缁熶竴浣跨敤 `formatMoney` 鏂规硶鏍煎紡鍖栨樉绀�
+5. **杩涘害鏉℃樉绀�**锛氫骇鍝佹槑缁嗕腑鐨勫彂璐ц繘搴︿娇鐢� `el-progress` 缁勪欢鐩磋灞曠ず
+6. **鐘舵�佹爣璇�**锛氬簲鏀堕噾棰濆ぇ浜�0鏃朵娇鐢ㄧ孩鑹叉爣璇嗭紝宸叉敹娆句娇鐢ㄧ豢鑹叉爣璇�
+7. **瀹℃壒鐘舵��**锛氬彂璐ф槑缁嗕腑鐨勫鎵圭姸鎬佷娇鐢� `el-tag` 灞曠ず锛屽凡瀹′负缁胯壊锛屽緟瀹′负榛勮壊
+
+---
+
+## 鏁版嵁瀵规瘮
+
+### 浼樺寲鍓� vs 浼樺寲鍚�
+
+| 缁村害 | 浼樺寲鍓� | 浼樺寲鍚� |
+|------|--------|--------|
+| 瀹㈡埛寰�鏉� | 鍙湁鍚堝悓閲戦銆佹敹娆俱�佸簲鏀� | 鏂板鍚堝悓鏁般�佷骇鍝佹暟銆佸彂璐х巼銆佹敹娆剧巼绛�12椤规寚鏍� |
+| 鏄庣粏缁村害 | 浠呭悎鍚屾槑缁� | 鏂板浜у搧鏄庣粏銆佸彂璐ф槑缁� |
+| 绛涢�夎兘鍔� | 浠呮寜瀹㈡埛鍚嶇瓫閫� | 鏀寔鎸夊悎鍚岀瓫閫変骇鍝�/鍙戣揣鏄庣粏 |
+| 鏁版嵁杩芥函 | 鏃犳硶杩芥函鍏蜂綋鍙戣揣 | 鍙拷婧瘡鏉″彂璐ц褰曠殑鏀舵鎯呭喌 |
+| 杩涘害灞曠ず | 鏃� | 鍙戣揣杩涘害鏉$洿瑙傚睍绀� |
\ No newline at end of file
diff --git a/doc/20260618_return_status_field.md b/doc/20260618_return_status_field.md
new file mode 100644
index 0000000..30d3c67
--- /dev/null
+++ b/doc/20260618_return_status_field.md
@@ -0,0 +1,201 @@
+# 閫�璐х姸鎬佸瓧娈垫帴鍙e彉鏇村墠绔仈璋冩枃妗�
+
+> 閿�鍞��璐с�佸彂璐у彴璐︺�侀攢鍞彴璐︽帴鍙f柊澧為��璐х姸鎬佸瓧娈�
+
+## 娑夊強椤甸潰
+
+- 閿�鍞鐞� / 閿�鍞��璐� - 鏂板/缂栬緫閫�璐у崟椤甸潰
+- 閿�鍞鐞� / 鍙戣揣鍙拌处鍒楄〃椤甸潰
+- 閿�鍞鐞� / 閿�鍞彴璐﹀垪琛ㄩ〉闈�
+
+---
+
+## API 鍙樻洿
+
+### 1. 閿�鍞��璐�-鍙戣揣淇℃伅鏌ヨ
+
+| 鏂规硶 | 璺緞 | 璇存槑 |
+|------|------|------|
+| GET | /shippingInfo/getForReturn | 閿�鍞��璐�-閫氳繃瀹㈡埛鍚嶇О鏌ヨ鍙戣揣淇℃伅 |
+
+**鏂板鍝嶅簲瀛楁锛�**
+
+| 瀛楁 | 绫诲瀷 | 璇存槑 |
+|------|------|------|
+| returnedQuantity | BigDecimal | 宸查��璐ф暟閲� |
+| returnStatus | String | 閫�璐х姸鎬侊細鏃犻��璐�/閮ㄥ垎閫�璐�/鍏ㄩ儴閫�璐� |
+
+**鍝嶅簲绀轰緥锛�**
+
+```json
+{
+ "code": 200,
+ "data": [
+ {
+ "shippingId": 100,
+ "shippingNo": "FH-2026-001",
+ "shippingQuantity": 50,
+ "returnedQuantity": 10,
+ "returnStatus": "閮ㄥ垎閫�璐�",
+ "batchNo": "20260618001",
+ "displayLabel": "20260618001-浜珹12345-2026-06-18"
+ }
+ ]
+}
+```
+
+---
+
+### 2. 鍙戣揣鍙拌处鍒楄〃
+
+| 鏂规硶 | 璺緞 | 璇存槑 |
+|------|------|------|
+| GET | /shippingInfo/listPage | 鍙戣揣淇℃伅鍒嗛〉鍒楄〃 |
+
+**鏂板鍝嶅簲瀛楁锛�**
+
+| 瀛楁 | 绫诲瀷 | 璇存槑 |
+|------|------|------|
+| returnedQuantity | BigDecimal | 宸查��璐ф暟閲� |
+| returnStatus | String | 閫�璐х姸鎬侊細鏃犻��璐�/閮ㄥ垎閫�璐�/鍏ㄩ儴閫�璐� |
+
+**鍝嶅簲绀轰緥锛�**
+
+```json
+{
+ "code": 200,
+ "data": {
+ "records": [
+ {
+ "id": 100,
+ "shippingNo": "FH-2026-001",
+ "totalQuantity": 50,
+ "returnedQuantity": 0,
+ "returnStatus": "鏃犻��璐�"
+ }
+ ]
+ }
+}
+```
+
+---
+
+### 3. 閿�鍞彴璐﹀垪琛�
+
+| 鏂规硶 | 璺緞 | 璇存槑 |
+|------|------|------|
+| GET | /salesLedger/listPage | 閿�鍞彴璐﹀垎椤靛垪琛� |
+
+**鏂板鍝嶅簲瀛楁锛�**
+
+| 瀛楁 | 绫诲瀷 | 璇存槑 |
+|------|------|------|
+| returnedQuantity | BigDecimal | 宸查��璐ф暟閲忥紙璇ラ攢鍞悎鍚屼笅鎵�鏈夊彂璐х殑绱閫�璐ф暟锛� |
+| returnStatus | String | 閫�璐х姸鎬侊細鏃犻��璐�/閮ㄥ垎閫�璐�/鍏ㄩ儴閫�璐� |
+
+**鍝嶅簲绀轰緥锛�**
+
+```json
+{
+ "code": 200,
+ "data": {
+ "records": [
+ {
+ "id": 1,
+ "salesContractNo": "HT-2026-001",
+ "contractAmount": 100000,
+ "returnedQuantity": 30,
+ "returnStatus": "閮ㄥ垎閫�璐�"
+ }
+ ]
+ }
+}
+```
+
+---
+
+## 鍓嶇淇敼鐐�
+
+### 1. 鍙戣揣鍙拌处鍒楄〃椤甸潰
+
+**鏂板琛ㄦ牸鍒楋細**
+
+```html
+<el-table-column label="閫�璐х姸鎬�" prop="returnStatus" width="100">
+ <template #default="{ row }">
+ <el-tag
+ :type="row.returnStatus === '鏃犻��璐�' ? 'success' : (row.returnStatus === '鍏ㄩ儴閫�璐�' ? 'danger' : 'warning')"
+ >
+ {{ row.returnStatus }}
+ </el-tag>
+ </template>
+</el-table-column>
+<el-table-column label="宸查��璐ф暟閲�" prop="returnedQuantity" width="120" />
+```
+
+### 2. 閿�鍞彴璐﹀垪琛ㄩ〉闈�
+
+**鏂板琛ㄦ牸鍒楋細**
+
+```html
+<el-table-column label="閫�璐х姸鎬�" prop="returnStatus" width="100">
+ <template #default="{ row }">
+ <el-tag
+ :type="row.returnStatus === '鏃犻��璐�' ? 'success' : (row.returnStatus === '鍏ㄩ儴閫�璐�' ? 'danger' : 'warning')"
+ >
+ {{ row.returnStatus }}
+ </el-tag>
+ </template>
+</el-table-column>
+```
+
+### 3. 閿�鍞��璐ч〉闈� - 鍙戣揣淇℃伅閫夋嫨
+
+**涓嬫媺閫夐」澧炲己鏄剧ず锛�**
+
+```html
+<el-select v-model="form.shippingId" placeholder="璇烽�夋嫨鍙戣揣淇℃伅" filterable>
+ <el-option
+ v-for="item in shippingList"
+ :key="item.shippingId"
+ :label="item.displayLabel"
+ :value="item.shippingId"
+ >
+ <div style="display: flex; justify-content: space-between;">
+ <span>{{ item.displayLabel }}</span>
+ <el-tag
+ size="small"
+ :type="item.returnStatus === '鏃犻��璐�' ? 'success' : 'warning'"
+ style="margin-left: 8px;"
+ >
+ {{ item.returnStatus }}
+ </el-tag>
+ </div>
+ </el-option>
+</el-select>
+```
+
+---
+
+## 閫�璐х姸鎬佽绠楅�昏緫
+
+| 鏉′欢 | 鐘舵�� |
+|------|------|
+| 閫�璐ф暟閲� = 0 | 鏃犻��璐� |
+| 閫�璐ф暟閲� >= 鍙戣揣鏁伴噺 | 鍏ㄩ儴閫�璐� |
+| 閫�璐ф暟閲� > 0 涓� < 鍙戣揣鏁伴噺 | 閮ㄥ垎閫�璐� |
+
+---
+
+## 娉ㄦ剰浜嬮」
+
+1. **閿�鍞彴璐︾殑閫�璐ф暟閲�**锛氭槸鎸夐攢鍞悎鍚岀淮搴︾殑姹囨�伙紝鍗宠鍚堝悓涓嬫墍鏈夊彂璐у崟鐨勭疮璁¢��璐ф暟閲�
+
+2. **鍙戣揣鍙拌处鐨勯��璐ф暟閲�**锛氭槸鎸夊崟鏉″彂璐ц褰曠淮搴︾殑閫�璐ф暟閲�
+
+3. **鍓嶇灞曠ず寤鸿**锛�
+ - 鏃犻��璐э細缁胯壊鏍囩 (`success`)
+ - 閮ㄥ垎閫�璐э細榛勮壊鏍囩 (`warning`)
+ - 鍏ㄩ儴閫�璐э細绾㈣壊鏍囩 (`danger`)
+
+4. **閿�鍞��璐ч�夋嫨鍙戣揣淇℃伅鏃�**锛氬墠绔彲浠ユ牴鎹� `returnStatus` 杩囨护鎴栨彁绀虹敤鎴凤紝閬垮厤閫夋嫨宸插叏閮ㄩ��璐х殑鍙戣揣璁板綍
diff --git a/doc/20260618_shipping_info_for_return.md b/doc/20260618_shipping_info_for_return.md
new file mode 100644
index 0000000..5568361
--- /dev/null
+++ b/doc/20260618_shipping_info_for_return.md
@@ -0,0 +1,365 @@
+# 閿�鍞��璐у彂璐т俊鎭帴鍙d紭鍖栧墠绔仈璋冩枃妗�
+
+> 浼樺寲閿�鍞��璐у満鏅笅鐨勫彂璐т俊鎭煡璇㈡帴鍙o紝鏂板鎵规鍙峰瓧娈碉紝骞舵彁渚涚粍鍚堟樉绀烘爣绛�
+
+## 娑夊強椤甸潰
+
+- 閿�鍞鐞� / 閿�鍞��璐� - 鏂板/缂栬緫閫�璐у崟椤甸潰
+- 閿�鍞��璐� - 閫夋嫨鍙戣揣鍗曚笅鎷夋
+
+## API
+
+### 鏂板鎺ュ彛锛氶攢鍞��璐�-鍙戣揣淇℃伅鏌ヨ
+
+| 鏂规硶 | 璺緞 | 璇存槑 |
+|------|------|------|
+| GET | /shippingInfo/getForReturn | 閿�鍞��璐�-閫氳繃瀹㈡埛鍚嶇О鏌ヨ鍙戣揣淇℃伅锛堝惈鎵规鍙凤級 |
+
+**璇锋眰鍙傛暟锛�**
+
+| 鍙傛暟 | 绫诲瀷 | 蹇呭~ | 璇存槑 |
+|------|------|------|------|
+| customerName | String | 鏄� | 瀹㈡埛鍚嶇О |
+
+**鍝嶅簲瀛楁锛�**
+
+| 瀛楁 | 绫诲瀷 | 璇存槑 |
+|------|------|------|
+| shippingId | Long | 鍙戣揣鍗旾D |
+| shippingNo | String | 鍙戣揣鍗曞彿 |
+| salesContractNo | String | 閿�鍞悎鍚屽彿 |
+| customerName | String | 瀹㈡埛鍚嶇О |
+| productName | String | 浜у搧鍚嶇О |
+| model | String | 瑙勬牸鍨嬪彿 |
+| shippingQuantity | BigDecimal | 鍙戣揣鏁伴噺 |
+| batchNo | String | 鎵规鍙� |
+| shippingCarNumber | String | 杞︾墝鍙� |
+| createTime | LocalDateTime | 鍒涘缓鏃堕棿 |
+| displayLabel | String | 鏄剧ず鏍囩锛堟壒娆″彿-杞︾墝鍙�-鍒涘缓鏃堕棿锛� |
+
+**鍝嶅簲绀轰緥锛�**
+
+```json
+{
+ "code": 200,
+ "msg": "鎿嶄綔鎴愬姛",
+ "data": [
+ {
+ "shippingId": 100,
+ "shippingNo": "FH-2026-001",
+ "salesContractNo": "HT-2026-001",
+ "customerName": "瀹㈡埛A",
+ "productName": "浜у搧A",
+ "model": "瑙勬牸1",
+ "shippingQuantity": 50,
+ "batchNo": "20260618001",
+ "shippingCarNumber": "浜珹12345",
+ "createTime": "2026-06-18 10:30:00",
+ "displayLabel": "20260618001-浜珹12345-2026-06-18"
+ },
+ {
+ "shippingId": 101,
+ "shippingNo": "FH-2026-002",
+ "salesContractNo": "HT-2026-002",
+ "customerName": "瀹㈡埛A",
+ "productName": "浜у搧B",
+ "model": "瑙勬牸2",
+ "shippingQuantity": 30,
+ "batchNo": "20260618002",
+ "shippingCarNumber": "浜珺67890",
+ "createTime": "2026-06-17 14:20:00",
+ "displayLabel": "20260618002-浜珺67890-2026-06-17"
+ }
+ ]
+}
+```
+
+---
+
+## 鍘熸湁鎺ュ彛锛堜繚鐣欎笉鍙橈級
+
+| 鏂规硶 | 璺緞 | 璇存槑 |
+|------|------|------|
+| GET | /shippingInfo/getByCustomerName | 閫氳繃瀹㈡埛鍚嶇О鏌ヨ鍏宠仈鐨勫彂璐у崟鍙凤紙鍘熸湁鎺ュ彛锛� |
+
+---
+
+## 鍓嶇淇敼鐐�
+
+### 1. 閿�鍞��璐ч〉闈� - 鍙戣揣鍗曢�夋嫨涓嬫媺妗�
+
+**淇敼鍓嶏細**
+```html
+<el-form-item label="鍙戣揣鍗曞彿">
+ <el-select v-model="form.shippingId" placeholder="璇烽�夋嫨鍙戣揣鍗曞彿">
+ <el-option
+ v-for="item in shippingList"
+ :key="item.id"
+ :label="item.shippingNo"
+ :value="item.id"
+ />
+ </el-select>
+</el-form-item>
+```
+
+**淇敼鍚庯細**
+```html
+<el-form-item label="鍙戣揣鍗曞彿">
+ <el-select
+ v-model="form.shippingId"
+ placeholder="璇烽�夋嫨鍙戣揣鍗曞彿"
+ filterable
+ @change="onShippingChange"
+ >
+ <el-option
+ v-for="item in shippingList"
+ :key="item.shippingId"
+ :label="item.displayLabel"
+ :value="item.shippingId"
+ >
+ <span style="float: left">{{ item.displayLabel }}</span>
+ <span style="float: right; color: #8492a6; font-size: 12px">
+ {{ item.productName }} - {{ item.shippingQuantity }}{{ item.model ? '(' + item.model + ')' : '' }}
+ </span>
+ </el-option>
+ </el-select>
+</el-form-item>
+```
+
+### 2. data 鏁版嵁
+
+```js
+data() {
+ return {
+ form: {
+ shippingId: null,
+ batchNo: '',
+ shippingCarNumber: '',
+ productName: '',
+ model: '',
+ shippingQuantity: null,
+ },
+ shippingList: [],
+ }
+}
+```
+
+### 3. methods 鏂规硶
+
+```js
+methods: {
+ // 鏌ヨ鍙戣揣淇℃伅鍒楄〃
+ getShippingList(customerName) {
+ if (!customerName) {
+ this.shippingList = [];
+ return;
+ }
+ this.$axios.get('/shippingInfo/getForReturn', {
+ params: { customerName }
+ }).then(res => {
+ this.shippingList = res.data || [];
+ });
+ },
+
+ // 鍙戣揣鍗曢�夋嫨鍙樺寲
+ onShippingChange(shippingId) {
+ const selected = this.shippingList.find(item => item.shippingId === shippingId);
+ if (selected) {
+ // 鍥炴樉鏁版嵁
+ this.form.batchNo = selected.batchNo || '';
+ this.form.shippingCarNumber = selected.shippingCarNumber || '';
+ this.form.productName = selected.productName || '';
+ this.form.model = selected.model || '';
+ this.form.shippingQuantity = selected.shippingQuantity || 0;
+ this.form.salesContractNo = selected.salesContractNo || '';
+ this.form.shippingNo = selected.shippingNo || '';
+ }
+ },
+}
+```
+
+### 4. 瀹屾暣绀轰緥锛堥攢鍞��璐ц〃鍗曪級
+
+```html
+<template>
+ <div class="app-container">
+ <el-form :model="form" :rules="rules" ref="formRef" label-width="120px">
+ <!-- 瀹㈡埛閫夋嫨 -->
+ <el-form-item label="瀹㈡埛鍚嶇О" prop="customerName">
+ <el-select
+ v-model="form.customerName"
+ placeholder="璇烽�夋嫨瀹㈡埛"
+ filterable
+ @change="onCustomerChange"
+ >
+ <el-option
+ v-for="item in customerList"
+ :key="item.id"
+ :label="item.customerName"
+ :value="item.customerName"
+ />
+ </el-select>
+ </el-form-item>
+
+ <!-- 鍙戣揣鍗曢�夋嫨 -->
+ <el-form-item label="鍙戣揣淇℃伅" prop="shippingId">
+ <el-select
+ v-model="form.shippingId"
+ placeholder="璇烽�夋嫨鍙戣揣鍗曞彿"
+ filterable
+ :disabled="!form.customerName"
+ @change="onShippingChange"
+ >
+ <el-option
+ v-for="item in shippingList"
+ :key="item.shippingId"
+ :label="item.displayLabel"
+ :value="item.shippingId"
+ >
+ <div style="display: flex; justify-content: space-between;">
+ <span>{{ item.displayLabel }}</span>
+ <span style="color: #909399; font-size: 12px">
+ {{ item.productName }}
+ </span>
+ </div>
+ </el-option>
+ </el-select>
+ </el-form-item>
+
+ <!-- 鍥炴樉淇℃伅锛堝彧璇伙級 -->
+ <el-row :gutter="20">
+ <el-col :span="8">
+ <el-form-item label="鎵规鍙�">
+ <el-input v-model="form.batchNo" disabled />
+ </el-form-item>
+ </el-col>
+ <el-col :span="8">
+ <el-form-item label="杞︾墝鍙�">
+ <el-input v-model="form.shippingCarNumber" disabled />
+ </el-form-item>
+ </el-col>
+ <el-col :span="8">
+ <el-form-item label="浜у搧鍚嶇О">
+ <el-input v-model="form.productName" disabled />
+ </el-form-item>
+ </el-col>
+ </el-row>
+
+ <el-row :gutter="20">
+ <el-col :span="8">
+ <el-form-item label="瑙勬牸鍨嬪彿">
+ <el-input v-model="form.model" disabled />
+ </el-form-item>
+ </el-col>
+ <el-col :span="8">
+ <el-form-item label="鍙戣揣鏁伴噺">
+ <el-input v-model="form.shippingQuantity" disabled />
+ </el-form-item>
+ </el-col>
+ <el-col :span="8">
+ <el-form-item label="閿�鍞悎鍚屽彿">
+ <el-input v-model="form.salesContractNo" disabled />
+ </el-form-item>
+ </el-col>
+ </el-row>
+
+ <!-- 鍏朵粬閫�璐ц〃鍗曞瓧娈�... -->
+ </el-form>
+ </div>
+</template>
+
+<script>
+export default {
+ name: 'SalesReturnForm',
+ data() {
+ return {
+ form: {
+ customerName: '',
+ shippingId: null,
+ batchNo: '',
+ shippingCarNumber: '',
+ productName: '',
+ model: '',
+ shippingQuantity: null,
+ salesContractNo: '',
+ shippingNo: '',
+ },
+ rules: {
+ customerName: [{ required: true, message: '璇烽�夋嫨瀹㈡埛', trigger: 'change' }],
+ shippingId: [{ required: true, message: '璇烽�夋嫨鍙戣揣淇℃伅', trigger: 'change' }],
+ },
+ customerList: [],
+ shippingList: [],
+ };
+ },
+ methods: {
+ // 瀹㈡埛閫夋嫨鍙樺寲
+ onCustomerChange(customerName) {
+ // 娓呯┖鍙戣揣鍗曢�夋嫨
+ this.form.shippingId = null;
+ this.clearShippingInfo();
+ // 鏌ヨ鍙戣揣淇℃伅
+ this.getShippingList(customerName);
+ },
+
+ // 鏌ヨ鍙戣揣淇℃伅鍒楄〃
+ getShippingList(customerName) {
+ if (!customerName) {
+ this.shippingList = [];
+ return;
+ }
+ this.$axios.get('/shippingInfo/getForReturn', {
+ params: { customerName }
+ }).then(res => {
+ this.shippingList = res.data || [];
+ });
+ },
+
+ // 鍙戣揣鍗曢�夋嫨鍙樺寲
+ onShippingChange(shippingId) {
+ const selected = this.shippingList.find(item => item.shippingId === shippingId);
+ if (selected) {
+ this.form.batchNo = selected.batchNo || '';
+ this.form.shippingCarNumber = selected.shippingCarNumber || '';
+ this.form.productName = selected.productName || '';
+ this.form.model = selected.model || '';
+ this.form.shippingQuantity = selected.shippingQuantity;
+ this.form.salesContractNo = selected.salesContractNo || '';
+ this.form.shippingNo = selected.shippingNo || '';
+ } else {
+ this.clearShippingInfo();
+ }
+ },
+
+ // 娓呯┖鍙戣揣淇℃伅
+ clearShippingInfo() {
+ this.form.batchNo = '';
+ this.form.shippingCarNumber = '';
+ this.form.productName = '';
+ this.form.model = '';
+ this.form.shippingQuantity = null;
+ this.form.salesContractNo = '';
+ this.form.shippingNo = '';
+ },
+ },
+};
+</script>
+```
+
+---
+
+## 娉ㄦ剰浜嬮」
+
+1. **鏂版帴鍙� vs 鍘熸帴鍙�**锛�
+ - `getForReturn`锛堟柊澧烇級锛氫笓闂ㄧ敤浜庨攢鍞��璐у満鏅紝杩斿洖鎵规鍙峰拰缁勫悎鏄剧ず鏍囩
+ - `getByCustomerName`锛堝師鏈夛級锛氫繚鎸佷笉鍙橈紝鍏朵粬鍦烘櫙鍙户缁娇鐢�
+
+2. **displayLabel 鏍煎紡**锛歚鎵规鍙�-杞︾墝鍙�-鍒涘缓鏃堕棿(yyyy-MM-dd)`
+ - 绀轰緥锛歚20260618001-浜珹12345-2026-06-18`
+ - 濡傛灉鏌愬瓧娈典负绌猴紝浼氭樉绀虹┖瀛楃涓诧紝濡� `--2026-06-18`
+
+3. **鏁版嵁鍥炴樉**锛氶�夋嫨鍙戣揣鍗曞悗锛屾壒娆″彿銆佽溅鐗屽彿銆佷骇鍝佸悕绉扮瓑瀛楁鑷姩濉厖鍒拌〃鍗曚腑锛屽墠绔彧闇�灞曠ず鍗冲彲
+
+4. **瀹㈡埛鍒囨崲**锛氬垏鎹㈠鎴锋椂锛岄渶娓呯┖宸查�夌殑鍙戣揣鍗曞拰鐩稿叧鍥炴樉鏁版嵁
+
+5. **涓嬫媺绛涢��**锛氬缓璁紑鍚� `filterable` 灞炴�э紝鏂逛究鐢ㄦ埛閫氳繃鎵规鍙锋垨杞︾墝鍙峰揩閫熺瓫閫�
diff --git a/src/api/salesManagement/indicatorStats.js b/src/api/salesManagement/indicatorStats.js
index c29eac3..5d66e86 100644
--- a/src/api/salesManagement/indicatorStats.js
+++ b/src/api/salesManagement/indicatorStats.js
@@ -36,3 +36,30 @@
params: query,
});
}
+
+// 瀹㈡埛寰�鏉ョ粺璁℃眹鎬�
+export function customerTransactionsSummary(query) {
+ return request({
+ url: "/metricStatistics/customerTransactionsSummary",
+ method: "get",
+ params: query,
+ });
+}
+
+// 瀹㈡埛寰�鏉ヤ骇鍝佹槑缁�
+export function customerTransactionsProducts(query) {
+ return request({
+ url: "/metricStatistics/customerTransactionsProducts",
+ method: "get",
+ params: query,
+ });
+}
+
+// 瀹㈡埛寰�鏉ュ彂璐ф槑缁�
+export function customerTransactionsShipments(query) {
+ return request({
+ url: "/metricStatistics/customerTransactionsShipments",
+ method: "get",
+ params: query,
+ });
+}
diff --git a/src/api/salesManagement/returnOrder.js b/src/api/salesManagement/returnOrder.js
index f945fc9..b809aa7 100644
--- a/src/api/salesManagement/returnOrder.js
+++ b/src/api/salesManagement/returnOrder.js
@@ -71,6 +71,16 @@
})
}
+// 閿�鍞��璐�-鍙戣揣淇℃伅鏌ヨ锛堝惈鎵规鍙凤級
+// /shippingInfo/getForReturn
+export function getShippingInfoForReturn(query) {
+ return request({
+ url: '/shippingInfo/getForReturn',
+ method: 'get',
+ params: query,
+ })
+}
+
// 澶勭悊
// /returnManagement/handle
export function returnManagementHandle(data) {
diff --git a/src/router/index.js b/src/router/index.js
index 7be3668..e05a1af 100644
--- a/src/router/index.js
+++ b/src/router/index.js
@@ -131,6 +131,19 @@
},
],
},
+ {
+ path: "/customer-transactions-detail",
+ component: Layout,
+ hidden: true,
+ children: [
+ {
+ path: "",
+ component: () => import("@/views/salesManagement/receiptPaymentLedger/detail.vue"),
+ name: "CustomerTransactionsDetail",
+ meta: { title: "瀹㈡埛寰�鏉ヨ鎯�", activeMenu: "/salesManagement/receiptPaymentLedger" },
+ },
+ ],
+ },
// 璐㈠姟绠$悊妯″潡璺敱
// {
// path: "/financial",
diff --git a/src/views/procurementManagement/procurementLedger/index.vue b/src/views/procurementManagement/procurementLedger/index.vue
index 785ce11..03d2ad2 100644
--- a/src/views/procurementManagement/procurementLedger/index.vue
+++ b/src/views/procurementManagement/procurementLedger/index.vue
@@ -351,9 +351,16 @@
<el-row :gutter="30">
<el-col :span="12">
<el-form-item label="浠樻鏂瑰紡">
- <el-input v-model="form.paymentMethod"
- placeholder="璇疯緭鍏�"
- clearable />
+ <el-select v-model="form.paymentMethod"
+ placeholder="璇烽�夋嫨"
+ clearable
+ style="width: 100%">
+ <el-option label="鐜伴噾" value="鐜伴噾" />
+ <el-option label="鐢垫眹" value="鐢垫眹" />
+ <el-option label="寰俊" value="寰俊" />
+ <el-option label="鏀粯瀹�" value="鏀粯瀹�" />
+ <el-option label="鏀エ" value="鏀エ" />
+ </el-select>
</el-form-item>
</el-col>
<el-col :span="12">
diff --git a/src/views/salesManagement/deliveryLedger/index.vue b/src/views/salesManagement/deliveryLedger/index.vue
index 30a1f9a..7a1c037 100644
--- a/src/views/salesManagement/deliveryLedger/index.vue
+++ b/src/views/salesManagement/deliveryLedger/index.vue
@@ -124,6 +124,31 @@
</template>
</el-table-column>
<el-table-column
+ label="閫�璐х姸鎬�"
+ prop="returnStatus"
+ align="center"
+ width="100"
+ >
+ <template #default="scope">
+ <el-tag
+ :type="getReturnStatusType(scope.row.returnStatus)"
+ size="small"
+ >
+ {{ scope.row.returnStatus || '鏃犻��璐�' }}
+ </el-tag>
+ </template>
+ </el-table-column>
+ <el-table-column
+ label="宸查��璐ф暟閲�"
+ prop="returnedQuantity"
+ align="center"
+ width="100"
+ >
+ <template #default="scope">
+ {{ scope.row.returnedQuantity || 0 }}
+ </template>
+ </el-table-column>
+ <el-table-column
label="鍑哄簱鍗曞彿"
prop="outboundBatches"
show-overflow-tooltip
@@ -870,6 +895,16 @@
return statusStr === "瀹℃牳涓�" || statusStr === "1";
};
+// 鑾峰彇閫�璐х姸鎬佹爣绛剧被鍨�
+const getReturnStatusType = (returnStatus) => {
+ const statusMap = {
+ '鏃犻��璐�': 'success',
+ '閮ㄥ垎閫�璐�': 'warning',
+ '鍏ㄩ儴閫�璐�': 'danger',
+ };
+ return statusMap[returnStatus] || 'info';
+};
+
onMounted(() => {
getList();
});
diff --git a/src/views/salesManagement/receiptPaymentLedger/components/ProductTable.vue b/src/views/salesManagement/receiptPaymentLedger/components/ProductTable.vue
new file mode 100644
index 0000000..999918d
--- /dev/null
+++ b/src/views/salesManagement/receiptPaymentLedger/components/ProductTable.vue
@@ -0,0 +1,229 @@
+<template>
+ <div class="product-table-container">
+ <el-table
+ :data="list"
+ v-loading="loading"
+ size="small"
+ border
+ class="custom-table"
+ :height="tableHeight"
+ >
+ <el-table-column label="鍚堝悓鍙�" prop="salesContractNo" width="160" show-overflow-tooltip>
+ <template #default="{ row }">
+ <span class="contract-no">{{ row.salesContractNo || '--' }}</span>
+ </template>
+ </el-table-column>
+ <el-table-column label="浜у搧鍚嶇О" prop="productName" min-width="180" show-overflow-tooltip />
+ <el-table-column label="瑙勬牸鍨嬪彿" prop="model" width="140" show-overflow-tooltip>
+ <template #default="{ row }">
+ <span class="model-text">{{ row.model || '--' }}</span>
+ </template>
+ </el-table-column>
+ <el-table-column label="鍗曚綅" prop="unit" width="80" align="center" />
+ <el-table-column label="鍚堝悓鏁伴噺" prop="contractQuantity" align="right" width="100">
+ <template #default="{ row }">
+ <span class="quantity">{{ formatNumber(row.contractQuantity) }}</span>
+ </template>
+ </el-table-column>
+ <el-table-column label="鍚堝悓鍗曚环" prop="taxInclusiveUnitPrice" align="right" width="110">
+ <template #default="{ row }">
+ <span class="price">楼{{ formatMoney(row.taxInclusiveUnitPrice) }}</span>
+ </template>
+ </el-table-column>
+ <el-table-column label="鍚堝悓閲戦" prop="contractAmount" align="right" width="130">
+ <template #default="{ row }">
+ <span class="amount">楼{{ formatMoney(row.contractAmount) }}</span>
+ </template>
+ </el-table-column>
+ <el-table-column label="宸插彂璐ф暟閲�" prop="shippedQuantity" align="right" width="100">
+ <template #default="{ row }">
+ <span class="shipped-qty">{{ formatNumber(row.shippedQuantity) }}</span>
+ </template>
+ </el-table-column>
+ <el-table-column label="宸插彂璐ч噾棰�" prop="shippedAmount" align="right" width="130">
+ <template #default="{ row }">
+ <span class="shipped-amt">楼{{ formatMoney(row.shippedAmount) }}</span>
+ </template>
+ </el-table-column>
+ <el-table-column label="鍙戣揣杩涘害" width="180" align="center">
+ <template #default="{ row }">
+ <div class="progress-cell">
+ <el-progress
+ :percentage="calcPercent(row.shippedQuantity, row.contractQuantity)"
+ :stroke-width="8"
+ :show-text="false"
+ :color="getProgressColor(calcPercent(row.shippedQuantity, row.contractQuantity))"
+ />
+ <span class="progress-text">{{ calcPercent(row.shippedQuantity, row.contractQuantity) }}%</span>
+ </div>
+ </template>
+ </el-table-column>
+ </el-table>
+
+ <div class="pagination-wrapper">
+ <pagination
+ v-show="total > 0"
+ :total="total"
+ :page="queryParams.pageNum"
+ :limit="queryParams.pageSize"
+ @pagination="handlePagination"
+ />
+ </div>
+ </div>
+</template>
+
+<script setup>
+import { ref, watch, computed } from 'vue'
+import { customerTransactionsProducts } from '@/api/salesManagement/indicatorStats.js'
+import Pagination from '@/components/PIMTable/Pagination.vue'
+
+const props = defineProps({
+ customerId: {
+ type: [Number, String],
+ required: true
+ }
+})
+
+const loading = ref(false)
+const list = ref([])
+const total = ref(0)
+const queryParams = ref({
+ pageNum: 1,
+ pageSize: 10,
+ customerId: null
+})
+
+const tableHeight = computed(() => `calc(100vh - 32em)`)
+
+const getList = () => {
+ loading.value = true
+ queryParams.value.customerId = props.customerId
+ customerTransactionsProducts(queryParams.value)
+ .then(res => {
+ if (res.code === 200) {
+ list.value = res.data?.records || []
+ total.value = res.data?.total || 0
+ }
+ })
+ .finally(() => {
+ loading.value = false
+ })
+}
+
+const handlePagination = ({ page, limit }) => {
+ queryParams.value.pageNum = page
+ queryParams.value.pageSize = limit
+ getList()
+}
+
+const formatMoney = (value) => {
+ if (!value) return '0.00'
+ return Number(value).toLocaleString('zh-CN', { minimumFractionDigits: 2, maximumFractionDigits: 2 })
+}
+
+const formatNumber = (value) => {
+ if (!value) return '0'
+ return Number(value).toLocaleString('zh-CN')
+}
+
+const calcPercent = (shipped, total) => {
+ if (!total || total === 0) return 0
+ return Math.min(100, Math.round((shipped / total) * 100))
+}
+
+const getProgressColor = (percent) => {
+ if (percent < 30) return '#f56c6c'
+ if (percent < 60) return '#e6a23c'
+ if (percent < 80) return '#409eff'
+ return '#67c23a'
+}
+
+watch(() => props.customerId, (val) => {
+ if (val) {
+ queryParams.value.pageNum = 1
+ getList()
+ }
+}, { immediate: true })
+</script>
+
+<style scoped lang="scss">
+.product-table-container {
+ .custom-table {
+ border-radius: 8px;
+ overflow: hidden;
+
+ :deep(.el-table__header-wrapper) {
+ th {
+ background: #f8f9fb !important;
+ font-weight: 600;
+ color: #303133;
+ }
+ }
+
+ :deep(.el-table__row) {
+ transition: all 0.2s;
+
+ &:hover > td {
+ background: #f5f7fa !important;
+ }
+ }
+
+ .contract-no {
+ color: #409eff;
+ font-weight: 500;
+ }
+
+ .model-text {
+ color: #606266;
+ }
+
+ .quantity {
+ font-weight: 500;
+ color: #303133;
+ }
+
+ .price {
+ color: #606266;
+ }
+
+ .amount {
+ font-weight: 600;
+ color: #303133;
+ }
+
+ .shipped-qty {
+ color: #67c23a;
+ font-weight: 500;
+ }
+
+ .shipped-amt {
+ color: #67c23a;
+ font-weight: 500;
+ }
+
+ .progress-cell {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ padding: 0 10px;
+
+ .el-progress {
+ flex: 1;
+ }
+
+ .progress-text {
+ font-size: 12px;
+ color: #606266;
+ min-width: 32px;
+ text-align: right;
+ }
+ }
+ }
+}
+
+.pagination-wrapper {
+ padding: 16px 0 0;
+ display: flex;
+ justify-content: flex-end;
+}
+</style>
diff --git a/src/views/salesManagement/receiptPaymentLedger/components/ShipmentTable.vue b/src/views/salesManagement/receiptPaymentLedger/components/ShipmentTable.vue
new file mode 100644
index 0000000..68e88a6
--- /dev/null
+++ b/src/views/salesManagement/receiptPaymentLedger/components/ShipmentTable.vue
@@ -0,0 +1,197 @@
+<template>
+ <div class="shipment-table-container">
+ <el-table
+ :data="list"
+ v-loading="loading"
+ size="small"
+ border
+ class="custom-table"
+ :height="tableHeight"
+ >
+ <el-table-column label="鍚堝悓鍙�" prop="salesContractNo" width="160" show-overflow-tooltip>
+ <template #default="{ row }">
+ <span class="contract-no">{{ row.salesContractNo || '--' }}</span>
+ </template>
+ </el-table-column>
+ <el-table-column label="鍙戣揣鍗曞彿" prop="shippingNo" width="160" show-overflow-tooltip>
+ <template #default="{ row }">
+ <span class="shipping-no">{{ row.shippingNo || '--' }}</span>
+ </template>
+ </el-table-column>
+ <el-table-column label="浜у搧鍚嶇О" prop="productName" min-width="160" show-overflow-tooltip />
+ <el-table-column label="瑙勬牸鍨嬪彿" prop="model" width="140" show-overflow-tooltip>
+ <template #default="{ row }">
+ <span class="model-text">{{ row.model || '--' }}</span>
+ </template>
+ </el-table-column>
+ <el-table-column label="鍙戣揣鏁伴噺" prop="shippingQuantity" align="right" width="100">
+ <template #default="{ row }">
+ <span class="quantity">{{ formatNumber(row.shippingQuantity) }}</span>
+ </template>
+ </el-table-column>
+ <el-table-column label="鍙戣揣閲戦" prop="shippingAmount" align="right" width="130">
+ <template #default="{ row }">
+ <span class="amount">楼{{ formatMoney(row.shippingAmount) }}</span>
+ </template>
+ </el-table-column>
+ <el-table-column label="鍑哄簱鎵瑰彿" prop="batchNo" width="160" show-overflow-tooltip>
+ <template #default="{ row }">
+ <span class="batch-no">{{ row.batchNo || '--' }}</span>
+ </template>
+ </el-table-column>
+ <el-table-column label="鍙戣揣鏃ユ湡" prop="shippingDate" width="120" align="center">
+ <template #default="{ row }">
+ <span class="date-text">{{ row.shippingDate || '--' }}</span>
+ </template>
+ </el-table-column>
+ <el-table-column label="瀹℃壒鐘舵��" prop="approvalStatus" width="100" align="center">
+ <template #default="{ row }">
+ <el-tag
+ :type="row.approvalStatus === 1 ? 'success' : 'warning'"
+ size="small"
+ effect="light"
+ round
+ >
+ {{ row.approvalStatus === 1 ? '宸插' : '寰呭' }}
+ </el-tag>
+ </template>
+ </el-table-column>
+ </el-table>
+
+ <div class="pagination-wrapper">
+ <pagination
+ v-show="total > 0"
+ :total="total"
+ :page="queryParams.pageNum"
+ :limit="queryParams.pageSize"
+ @pagination="handlePagination"
+ />
+ </div>
+ </div>
+</template>
+
+<script setup>
+import { ref, watch, computed } from 'vue'
+import { customerTransactionsShipments } from '@/api/salesManagement/indicatorStats.js'
+import Pagination from '@/components/PIMTable/Pagination.vue'
+
+const props = defineProps({
+ customerId: {
+ type: [Number, String],
+ required: true
+ }
+})
+
+const loading = ref(false)
+const list = ref([])
+const total = ref(0)
+const queryParams = ref({
+ pageNum: 1,
+ pageSize: 10,
+ customerId: null
+})
+
+const tableHeight = computed(() => `calc(100vh - 32em)`)
+
+const getList = () => {
+ loading.value = true
+ queryParams.value.customerId = props.customerId
+ customerTransactionsShipments(queryParams.value)
+ .then(res => {
+ if (res.code === 200) {
+ list.value = res.data?.records || []
+ total.value = res.data?.total || 0
+ }
+ })
+ .finally(() => {
+ loading.value = false
+ })
+}
+
+const handlePagination = ({ page, limit }) => {
+ queryParams.value.pageNum = page
+ queryParams.value.pageSize = limit
+ getList()
+}
+
+const formatMoney = (value) => {
+ if (!value) return '0.00'
+ return Number(value).toLocaleString('zh-CN', { minimumFractionDigits: 2, maximumFractionDigits: 2 })
+}
+
+const formatNumber = (value) => {
+ if (!value) return '0'
+ return Number(value).toLocaleString('zh-CN')
+}
+
+watch(() => props.customerId, (val) => {
+ if (val) {
+ queryParams.value.pageNum = 1
+ getList()
+ }
+}, { immediate: true })
+</script>
+
+<style scoped lang="scss">
+.shipment-table-container {
+ .custom-table {
+ border-radius: 8px;
+ overflow: hidden;
+
+ :deep(.el-table__header-wrapper) {
+ th {
+ background: #f8f9fb !important;
+ font-weight: 600;
+ color: #303133;
+ }
+ }
+
+ :deep(.el-table__row) {
+ transition: all 0.2s;
+
+ &:hover > td {
+ background: #f5f7fa !important;
+ }
+ }
+
+ .contract-no {
+ color: #409eff;
+ font-weight: 500;
+ }
+
+ .shipping-no {
+ color: #909399;
+ font-size: 12px;
+ }
+
+ .model-text {
+ color: #606266;
+ }
+
+ .quantity {
+ font-weight: 500;
+ color: #303133;
+ }
+
+ .amount {
+ font-weight: 600;
+ color: #67c23a;
+ }
+
+ .batch-no {
+ color: #606266;
+ font-size: 12px;
+ }
+
+ .date-text {
+ color: #606266;
+ }
+ }
+}
+
+.pagination-wrapper {
+ padding: 16px 0 0;
+ display: flex;
+ justify-content: flex-end;
+}
+</style>
diff --git a/src/views/salesManagement/receiptPaymentLedger/detail.vue b/src/views/salesManagement/receiptPaymentLedger/detail.vue
new file mode 100644
index 0000000..4d8ae4e
--- /dev/null
+++ b/src/views/salesManagement/receiptPaymentLedger/detail.vue
@@ -0,0 +1,387 @@
+<template>
+ <div class="customer-detail-page">
+ <!-- 椤堕儴瀵艰埅鏍� -->
+ <div class="page-header">
+ <div class="header-left">
+ <el-button @click="goBack" :icon="ArrowLeft" circle />
+ <div class="customer-info">
+ <span class="customer-name">{{ summary.customerName || '瀹㈡埛寰�鏉ヨ鎯�' }}</span>
+ <span class="customer-tag">瀹㈡埛寰�鏉ョ粺璁�</span>
+ </div>
+ </div>
+ </div>
+
+ <!-- 缁熻鍗$墖鍖� -->
+ <div class="stats-section" v-loading="summaryLoading">
+ <div class="stats-grid">
+ <div class="stat-card primary">
+ <div class="stat-icon">
+ <el-icon><Document /></el-icon>
+ </div>
+ <div class="stat-content">
+ <div class="stat-label">鍚堝悓鎬婚噾棰�</div>
+ <div class="stat-value">
+ <span class="currency">楼</span>
+ <span class="number">{{ formatMoney(summary.contractAmounts) }}</span>
+ </div>
+ </div>
+ </div>
+
+ <div class="stat-card success">
+ <div class="stat-icon">
+ <el-icon><Tickets /></el-icon>
+ </div>
+ <div class="stat-content">
+ <div class="stat-label">鍚堝悓鏁伴噺</div>
+ <div class="stat-value">
+ <span class="number">{{ summary.contractCount || 0 }}</span>
+ <span class="unit">浠�</span>
+ </div>
+ </div>
+ </div>
+
+ <div class="stat-card info">
+ <div class="stat-icon">
+ <el-icon><Van /></el-icon>
+ </div>
+ <div class="stat-content">
+ <div class="stat-label">鍙戣揣閲戦</div>
+ <div class="stat-value">
+ <span class="currency">楼</span>
+ <span class="number">{{ formatMoney(summary.shippedAmounts) }}</span>
+ </div>
+ </div>
+ </div>
+
+ <div class="stat-card danger">
+ <div class="stat-icon">
+ <el-icon><Clock /></el-icon>
+ </div>
+ <div class="stat-content">
+ <div class="stat-label">鏈彂璐ч噾棰�</div>
+ <div class="stat-value">
+ <span class="currency">楼</span>
+ <span class="number">{{ formatMoney(summary.unshippedAmounts) }}</span>
+ </div>
+ </div>
+ </div>
+
+ <div class="stat-card progress-card">
+ <div class="stat-content-full">
+ <div class="progress-header">
+ <span class="stat-label">鍙戣揣杩涘害</span>
+ <span class="progress-value">{{ summary.shippedRate || 0 }}%</span>
+ </div>
+ <el-progress
+ :percentage="summary.shippedRate || 0"
+ :stroke-width="12"
+ :show-text="false"
+ :color="getProgressColor(summary.shippedRate)"
+ />
+ <div class="progress-footer">
+ <span>宸插彂璐�: 楼{{ formatMoney(summary.shippedAmounts) }}</span>
+ <span>鎬婚: 楼{{ formatMoney(summary.contractAmounts) }}</span>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+
+ <!-- Tab 鍒囨崲 -->
+ <div class="table-section">
+ <el-tabs v-model="activeTab" class="custom-tabs">
+ <el-tab-pane label="浜у搧鏄庣粏" name="products">
+ <ProductTable :customerId="customerId" v-if="customerId && activeTab === 'products'" />
+ </el-tab-pane>
+ <!-- <el-tab-pane label="鍙戣揣鏄庣粏" name="shipments">
+ <ShipmentTable :customerId="customerId" v-if="customerId && activeTab === 'shipments'" />
+ </el-tab-pane> -->
+ </el-tabs>
+ </div>
+ </div>
+</template>
+
+<script setup>
+import { ref, onMounted } from 'vue'
+import { useRoute, useRouter } from 'vue-router'
+import { ArrowLeft, Document, Tickets, Van, Clock } from '@element-plus/icons-vue'
+import { customerTransactionsSummary } from '@/api/salesManagement/indicatorStats.js'
+import ProductTable from './components/ProductTable.vue'
+// import ShipmentTable from './components/ShipmentTable.vue'
+
+const route = useRoute()
+const router = useRouter()
+
+const customerId = ref(null)
+const summary = ref({})
+const summaryLoading = ref(false)
+const activeTab = ref('products')
+
+const getSummary = () => {
+ if (!customerId.value) return
+ summaryLoading.value = true
+ customerTransactionsSummary({ customerId: customerId.value })
+ .then(res => {
+ if (res.code === 200) {
+ summary.value = res.data || {}
+ }
+ })
+ .finally(() => {
+ summaryLoading.value = false
+ })
+}
+
+const formatMoney = (value) => {
+ if (!value) return '0.00'
+ return Number(value).toLocaleString('zh-CN', { minimumFractionDigits: 2, maximumFractionDigits: 2 })
+}
+
+const getProgressColor = (rate) => {
+ if (!rate || rate < 30) return '#f56c6c'
+ if (rate < 60) return '#e6a23c'
+ if (rate < 80) return '#409eff'
+ return '#67c23a'
+}
+
+const goBack = () => {
+ router.push('/salesManagement/receiptPaymentLedger')
+}
+
+onMounted(() => {
+ customerId.value = route.query.customerId
+ if (customerId.value) {
+ getSummary()
+ }
+})
+</script>
+
+<style scoped lang="scss">
+.customer-detail-page {
+ background: #f5f7fa;
+ min-height: calc(100vh - 84px);
+ padding: 20px;
+}
+
+.page-header {
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+ border-radius: 12px;
+ padding: 20px 24px;
+ margin-bottom: 20px;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ box-shadow: 0 4px 15px rgba(102, 126, 234, 0.3);
+
+ .header-left {
+ display: flex;
+ align-items: center;
+ gap: 16px;
+
+ .el-button {
+ background: rgba(255, 255, 255, 0.2);
+ border: none;
+ color: white;
+
+ &:hover {
+ background: rgba(255, 255, 255, 0.3);
+ }
+ }
+
+ .customer-info {
+ display: flex;
+ flex-direction: column;
+ gap: 4px;
+
+ .customer-name {
+ font-size: 20px;
+ font-weight: 600;
+ color: white;
+ }
+
+ .customer-tag {
+ font-size: 12px;
+ color: rgba(255, 255, 255, 0.8);
+ background: rgba(255, 255, 255, 0.2);
+ padding: 2px 10px;
+ border-radius: 10px;
+ width: fit-content;
+ }
+ }
+ }
+}
+
+.stats-section {
+ margin-bottom: 20px;
+}
+
+.stats-grid {
+ display: grid;
+ grid-template-columns: repeat(5, 1fr);
+ gap: 16px;
+
+ @media (max-width: 1400px) {
+ grid-template-columns: repeat(3, 1fr);
+ }
+
+ @media (max-width: 1000px) {
+ grid-template-columns: repeat(2, 1fr);
+ }
+}
+
+.stat-card {
+ background: white;
+ border-radius: 12px;
+ padding: 20px;
+ display: flex;
+ align-items: center;
+ gap: 16px;
+ box-shadow: 0 2px 12px rgba(0, 0, 0, 0.05);
+ transition: all 0.3s ease;
+ position: relative;
+ overflow: hidden;
+
+ &::before {
+ content: '';
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 4px;
+ height: 100%;
+ }
+
+ &:hover {
+ transform: translateY(-2px);
+ box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
+ }
+
+ &.primary::before { background: linear-gradient(180deg, #667eea, #764ba2); }
+ &.success::before { background: linear-gradient(180deg, #67c23a, #4a9c2d); }
+ &.warning::before { background: linear-gradient(180deg, #e6a23c, #c78a2f); }
+ &.info::before { background: linear-gradient(180deg, #409eff, #2d7dd2); }
+ &.danger::before { background: linear-gradient(180deg, #f56c6c, #c45656); }
+ &.progress-card::before { background: linear-gradient(180deg, #909399, #606266); }
+
+ .stat-icon {
+ width: 52px;
+ height: 52px;
+ border-radius: 12px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ font-size: 24px;
+ flex-shrink: 0;
+ }
+
+ &.primary .stat-icon { background: linear-gradient(135deg, rgba(102, 126, 234, 0.15), rgba(118, 75, 162, 0.15)); color: #667eea; }
+ &.success .stat-icon { background: linear-gradient(135deg, rgba(103, 194, 58, 0.15), rgba(74, 156, 45, 0.15)); color: #67c23a; }
+ &.warning .stat-icon { background: linear-gradient(135deg, rgba(230, 162, 60, 0.15), rgba(199, 138, 47, 0.15)); color: #e6a23c; }
+ &.info .stat-icon { background: linear-gradient(135deg, rgba(64, 158, 255, 0.15), rgba(45, 125, 210, 0.15)); color: #409eff; }
+ &.danger .stat-icon { background: linear-gradient(135deg, rgba(245, 108, 108, 0.15), rgba(196, 86, 86, 0.15)); color: #f56c6c; }
+ &.progress-card .stat-icon { display: none; }
+
+ .stat-content {
+ flex: 1;
+ min-width: 0;
+ }
+
+ .stat-label {
+ font-size: 13px;
+ color: #909399;
+ margin-bottom: 6px;
+ }
+
+ .stat-value {
+ .currency {
+ font-size: 14px;
+ color: #606266;
+ margin-right: 2px;
+ }
+
+ .number {
+ font-size: 22px;
+ font-weight: 600;
+ color: #303133;
+ }
+
+ .unit {
+ font-size: 14px;
+ color: #909399;
+ margin-left: 4px;
+ }
+ }
+
+ &.progress-card {
+ grid-column: span 1;
+
+ @media (max-width: 1600px) {
+ grid-column: span 1;
+ }
+
+ .stat-content-full {
+ width: 100%;
+ }
+
+ .progress-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 10px;
+
+ .stat-label {
+ margin-bottom: 0;
+ }
+
+ .progress-value {
+ font-size: 18px;
+ font-weight: 600;
+ color: #303133;
+ }
+ }
+
+ .progress-footer {
+ display: flex;
+ justify-content: space-between;
+ margin-top: 10px;
+ font-size: 12px;
+ color: #909399;
+ }
+ }
+}
+
+.table-section {
+ background: white;
+ border-radius: 12px;
+ padding: 20px;
+ box-shadow: 0 2px 12px rgba(0, 0, 0, 0.05);
+
+ .custom-tabs {
+ :deep(.el-tabs__header) {
+ margin-bottom: 0;
+
+ .el-tabs__nav-wrap::after {
+ height: 1px;
+ }
+
+ .el-tabs__item {
+ font-size: 15px;
+ padding: 0 24px;
+ height: 44px;
+ line-height: 44px;
+
+ &.is-active {
+ font-weight: 600;
+ }
+ }
+
+ .el-tabs__active-bar {
+ height: 3px;
+ border-radius: 2px;
+ }
+ }
+
+ :deep(.el-tabs__content) {
+ padding-top: 20px;
+ }
+ }
+}
+</style>
diff --git a/src/views/salesManagement/receiptPaymentLedger/index.vue b/src/views/salesManagement/receiptPaymentLedger/index.vue
index abcef02..ec81d9a 100644
--- a/src/views/salesManagement/receiptPaymentLedger/index.vue
+++ b/src/views/salesManagement/receiptPaymentLedger/index.vue
@@ -42,6 +42,26 @@
show-overflow-tooltip
:formatter="formattedNumber"
width="150" />
+ <el-table-column label="鏀舵閲戦(鍏�)"
+ prop="receiptPaymentAmount"
+ show-overflow-tooltip
+ :formatter="formattedNumber"
+ width="150" />
+ <el-table-column label="搴旀敹閲戦(鍏�)"
+ prop="receiptableAmount"
+ show-overflow-tooltip
+ width="150">
+ <template #default="{ row }">
+ <span :style="{ color: row.receiptableAmount > 0 ? '#f56c6c' : '#606266' }">
+ {{ formattedNumber(null, null, row.receiptableAmount) }}
+ </span>
+ </template>
+ </el-table-column>
+ <el-table-column label="鎿嶄綔" width="100" align="center" fixed="right">
+ <template #default="{ row }">
+ <el-button type="primary" link size="small" @click="viewDetail(row)">鏌ョ湅鏄庣粏</el-button>
+ </template>
+ </el-table-column>
<!-- <el-table-column label="搴旀敹閲戦(鍏�)"-->
<!-- prop="receiptableAmount"-->
<!-- show-overflow-tooltip-->
@@ -145,6 +165,7 @@
<script setup>
import { onMounted, ref, reactive, toRefs, getCurrentInstance } from "vue";
+ import { useRouter } from "vue-router";
import {
customewTransactions,
} from "@/api/salesManagement/indicatorStats.js";
@@ -152,6 +173,7 @@
import Pagination from "../../../components/PIMTable/Pagination.vue";
const { proxy } = getCurrentInstance();
+ const router = useRouter();
const tableData = ref([]);
const orderRecord = ref([]);
const tableLoading = ref(false);
@@ -265,6 +287,14 @@
getOrderList(customerId.value);
};
+ // 鏌ョ湅鏄庣粏
+ const viewDetail = (row) => {
+ router.push({
+ path: '/customer-transactions-detail',
+ query: { customerId: row.customerId }
+ });
+ };
+
// 瀹℃牳鐘舵�佹爣绛剧被鍨�
const getApprovalStatusType = (status) => {
const statusMap = {
diff --git a/src/views/salesManagement/returnOrder/components/formDia.vue b/src/views/salesManagement/returnOrder/components/formDia.vue
index 0ef4754..1f59c96 100644
--- a/src/views/salesManagement/returnOrder/components/formDia.vue
+++ b/src/views/salesManagement/returnOrder/components/formDia.vue
@@ -32,14 +32,32 @@
</el-form-item>
</el-col>
<el-col :span="4">
- <el-form-item label="鍏宠仈鎵瑰彿锛�" prop="shippingId">
- <el-select v-model="form.shippingId" filterable placeholder="璇烽�夋嫨鍏宠仈鎵瑰彿" @change="outboundNoChange">
+ <el-form-item label="鍙戣揣淇℃伅锛�" prop="shippingId">
+ <el-select
+ v-model="form.shippingId"
+ filterable
+ placeholder="璇烽�夋嫨鍙戣揣淇℃伅"
+ :disabled="!form.customerId"
+ @change="outboundNoChange"
+ >
<el-option
v-for="item in outboundOptions"
- :key="item.value"
- :label="item.label"
- :value="item.value"
- />
+ :key="item.shippingId"
+ :label="item.displayLabel"
+ :value="item.shippingId"
+ :disabled="item.returnStatus === '鍏ㄩ儴閫�璐�'"
+ >
+ <div style="display: flex; justify-content: space-between; align-items: center;">
+ <span>{{ item.displayLabel }}</span>
+ <el-tag
+ size="small"
+ :type="getReturnStatusType(item.returnStatus)"
+ style="margin-left: 8px;"
+ >
+ {{ item.returnStatus || '鏃犻��璐�' }}
+ </el-tag>
+ </div>
+ </el-option>
</el-select>
</el-form-item>
</el-col>
@@ -71,6 +89,39 @@
<el-col :span="4">
<el-form-item label="閫�娆炬�婚锛�" prop="refundAmount">
<el-input v-model="form.refundAmount" disabled placeholder="鑷姩璁$畻" />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <!-- 鍙戣揣淇℃伅鍥炴樉 -->
+ <el-row :gutter="30" v-if="form.shippingId">
+ <el-col :span="4">
+ <el-form-item label="鎵规鍙凤細">
+ <el-input v-model="form.batchNo" disabled placeholder="--" />
+ </el-form-item>
+ </el-col>
+ <el-col :span="4">
+ <el-form-item label="杞︾墝鍙凤細">
+ <el-input v-model="form.shippingCarNumber" disabled placeholder="--" />
+ </el-form-item>
+ </el-col>
+ <el-col :span="4">
+ <el-form-item label="浜у搧鍚嶇О锛�">
+ <el-input v-model="form.productName" disabled placeholder="--" />
+ </el-form-item>
+ </el-col>
+ <el-col :span="4">
+ <el-form-item label="瑙勬牸鍨嬪彿锛�">
+ <el-input v-model="form.model" disabled placeholder="--" />
+ </el-form-item>
+ </el-col>
+ <el-col :span="4">
+ <el-form-item label="鍙戣揣鏁伴噺锛�">
+ <el-input v-model="form.shippingQuantity" disabled placeholder="--" />
+ </el-form-item>
+ </el-col>
+ <el-col :span="4">
+ <el-form-item label="閿�鍞悎鍚屽彿锛�">
+ <el-input v-model="form.salesContractNo" disabled placeholder="--" />
</el-form-item>
</el-col>
</el-row>
@@ -172,7 +223,7 @@
<script setup>
import { reactive, ref, toRefs, getCurrentInstance } from "vue";
-import { returnManagementAdd, returnManagementUpdate, returnManagementGetByShippingId, getSalesLedger, returnManagementGetById } from "@/api/salesManagement/returnOrder.js";
+import { returnManagementAdd, returnManagementUpdate, returnManagementGetByShippingId, getSalesLedger, returnManagementGetById, getShippingInfoForReturn } from "@/api/salesManagement/returnOrder.js";
import useUserStore from "@/store/modules/user.js";
import { userListNoPageByTenantId } from "@/api/system/user.js";
import { listProject } from "@/api/projectManagement/project.js";
@@ -197,6 +248,14 @@
status: 0,
returnReason: "",
refundAmount: "",
+ // 鍙戣揣淇℃伅鍥炴樉瀛楁
+ batchNo: "",
+ shippingCarNumber: "",
+ productName: "",
+ model: "",
+ shippingQuantity: null,
+ salesContractNo: "",
+ shippingNo: "",
},
rules: {
returnNo: [{
@@ -207,7 +266,7 @@
}, trigger: "blur"
}],
customerId: [{ required: true, message: "璇烽�夋嫨瀹㈡埛", trigger: "change" }],
- shippingId: [{ required: true, message: "璇烽�夋嫨鍏宠仈鍑哄簱鍗曞彿", trigger: "change" }],
+ shippingId: [{ required: true, message: "璇烽�夋嫨鍙戣揣淇℃伅", trigger: "change" }],
}
});
const { form, rules } = toRefs(data);
@@ -501,6 +560,13 @@
status: 0,
returnReason: "",
refundAmount: "",
+ batchNo: "",
+ shippingCarNumber: "",
+ productName: "",
+ model: "",
+ shippingQuantity: null,
+ salesContractNo: "",
+ shippingNo: "",
});
form.value.maker = userStore.nickName || userStore.name || "";
form.value.makeTime = new Date().toISOString().replace('T', ' ').split('.')[0]; // Default to now
@@ -584,33 +650,68 @@
if (clearDownstream) {
form.value.shippingId = "";
outboundOptions.value = [];
+ clearShippingInfo();
}
-
- // Find customer name for getSalesLedger if it requires name
+
+ // Find customer name for API
const customer = customerNameOptions.value.find(c => c.id === val);
if (!customer) return;
- // Assuming getSalesLedger takes customerName. If it takes ID, adjust accordingly.
- // Previous code used customerName. Let's try passing customerName.
- getSalesLedger({
- customerName: customer.label,
+ // 浣跨敤鏂版帴鍙� getShippingInfoForReturn
+ getShippingInfoForReturn({
+ customerName: customer.label,
}).then(res => {
if(res.code === 200){
- outboundOptions.value = res.data.map(item => ({
- label: item.shippingNo, // Or whatever the outbound number field is
- value: item.id,
- }))
+ outboundOptions.value = res.data || [];
}
})
};
+// 娓呯┖鍙戣揣淇℃伅
+const clearShippingInfo = () => {
+ form.value.batchNo = "";
+ form.value.shippingCarNumber = "";
+ form.value.productName = "";
+ form.value.model = "";
+ form.value.shippingQuantity = null;
+ form.value.salesContractNo = "";
+ form.value.shippingNo = "";
+};
+
+// 鑾峰彇閫�璐х姸鎬佹爣绛剧被鍨�
+const getReturnStatusType = (returnStatus) => {
+ const statusMap = {
+ '鏃犻��璐�': 'success',
+ '閮ㄥ垎閫�璐�': 'warning',
+ '鍏ㄩ儴閫�璐�': 'danger',
+ };
+ return statusMap[returnStatus] || 'info';
+};
+
const outboundNoChange = async (val, clearTable = true) => {
// val is shippingId
+ // 浠� outboundOptions 涓壘鍒伴�変腑鐨勫彂璐т俊鎭�
+ const selected = outboundOptions.value.find(item => item.shippingId === val);
+
+ if (selected) {
+ // 鍥炴樉鏁版嵁
+ form.value.batchNo = selected.batchNo || "";
+ form.value.shippingCarNumber = selected.shippingCarNumber || "";
+ form.value.productName = selected.productName || "";
+ form.value.model = selected.model || "";
+ form.value.shippingQuantity = selected.shippingQuantity || 0;
+ form.value.salesContractNo = selected.salesContractNo || "";
+ form.value.shippingNo = selected.shippingNo || "";
+ } else {
+ clearShippingInfo();
+ }
+
+ // 鑾峰彇浜у搧鍒楄〃
let res = await returnManagementGetByShippingId({ shippingId: val });
if(res.code === 200){
// If backend returns project info, set it
if (res.data.projectId) form.value.projectId = res.data.projectId;
-
+
availableProducts.value = mergeShippingProductLists(res.data);
if (clearTable) tableData.value = [];
}
diff --git a/src/views/salesManagement/returnOrder/index.vue b/src/views/salesManagement/returnOrder/index.vue
index 19d313c..776ef0c 100644
--- a/src/views/salesManagement/returnOrder/index.vue
+++ b/src/views/salesManagement/returnOrder/index.vue
@@ -38,6 +38,11 @@
<template #status="{ row }">
<el-tag :type="getStatusType(row.status)">{{ getStatusText(row.status) }}</el-tag>
</template>
+ <template #returnStatus="{ row }">
+ <el-tag :type="getReturnStatusType(row.returnStatus)" size="small">
+ {{ row.returnStatus || '鏃犻��璐�' }}
+ </el-tag>
+ </template>
</PIMTable>
</div>
<form-dia ref="formDia" @close="handleQuery" />
@@ -114,6 +119,7 @@
const defaultColumns = [
{ label: "閫�璐у崟鍙�", prop: "returnNo", minWidth: 160 },
{ label: "鍗曟嵁鐘舵��", prop: "status", minWidth: 90, dataType: "slot", slot: "status" },
+ { label: "閫�璐х姸鎬�", prop: "returnStatus", minWidth: 100, dataType: "slot", slot: "returnStatus" },
{ label: "鍒跺崟鏃堕棿", prop: "makeTime", minWidth: 170 },
{ label: "瀹㈡埛鍚嶇О", prop: "customerName", minWidth: 220 },
{ label: "閿�鍞崟鍙�", prop: "salesContractNo", minWidth: 160 },
@@ -207,6 +213,15 @@
return statusMap[status] || "鏈煡";
};
+const getReturnStatusType = (returnStatus) => {
+ const statusMap = {
+ '鏃犻��璐�': 'success',
+ '閮ㄥ垎閫�璐�': 'warning',
+ '鍏ㄩ儴閫�璐�': 'danger',
+ };
+ return statusMap[returnStatus] || 'info';
+};
+
onMounted(() => {
getList();
});
diff --git a/src/views/salesManagement/salesLedger/index.vue b/src/views/salesManagement/salesLedger/index.vue
index 7cf9d6d..a403dc6 100644
--- a/src/views/salesManagement/salesLedger/index.vue
+++ b/src/views/salesManagement/salesLedger/index.vue
@@ -248,6 +248,21 @@
width="200"
show-overflow-tooltip
/>
+ <el-table-column
+ label="閫�璐х姸鎬�"
+ prop="returnStatus"
+ align="center"
+ width="100"
+ >
+ <template #default="scope">
+ <el-tag
+ :type="getReturnStatusType(scope.row.returnStatus)"
+ size="small"
+ >
+ {{ scope.row.returnStatus || '鏃犻��璐�' }}
+ </el-tag>
+ </template>
+ </el-table-column>
<el-table-column fixed="right" label="鎿嶄綔" width="220" align="center">
<template #default="scope">
<el-button link type="primary" @click="openForm('view', scope.row)"
@@ -404,12 +419,19 @@
</el-col>
<el-col :span="12">
<el-form-item label="浠樻鏂瑰紡">
- <el-input
+ <el-select
v-model="form.paymentMethod"
- placeholder="璇疯緭鍏�"
+ placeholder="璇烽�夋嫨"
clearable
:disabled="operationType === 'view'"
- />
+ style="width: 100%"
+ >
+ <el-option label="鐜伴噾" value="鐜伴噾" />
+ <el-option label="鐢垫眹" value="鐢垫眹" />
+ <el-option label="寰俊" value="寰俊" />
+ <el-option label="鏀粯瀹�" value="鏀粯瀹�" />
+ <el-option label="鏀エ" value="鏀エ" />
+ </el-select>
</el-form-item>
</el-col>
</el-row>
@@ -3002,6 +3024,17 @@
let res = await userStore.getInfo();
currentFactoryName.value = res.user.currentFactoryName;
};
+
+// 鑾峰彇閫�璐х姸鎬佹爣绛剧被鍨�
+const getReturnStatusType = (returnStatus) => {
+ const statusMap = {
+ '鏃犻��璐�': 'success',
+ '閮ㄥ垎閫�璐�': 'warning',
+ '鍏ㄩ儴閫�璐�': 'danger',
+ };
+ return statusMap[returnStatus] || 'info';
+};
+
onMounted(() => {
searchForm.salesContractNo = route.query.salesContractNo;
getList();
diff --git a/src/views/salesManagement/salesQuotation/index.vue b/src/views/salesManagement/salesQuotation/index.vue
index 3944b41..3072350 100644
--- a/src/views/salesManagement/salesQuotation/index.vue
+++ b/src/views/salesManagement/salesQuotation/index.vue
@@ -148,7 +148,13 @@
<el-row :gutter="24">
<el-col :span="12">
<el-form-item label="浠樻鏂瑰紡" prop="paymentMethod">
- <el-input v-model="form.paymentMethod" placeholder="璇疯緭鍏ヤ粯娆炬柟寮�" clearable />
+ <el-select v-model="form.paymentMethod" placeholder="璇烽�夋嫨浠樻鏂瑰紡" clearable style="width: 100%">
+ <el-option label="鐜伴噾" value="鐜伴噾" />
+ <el-option label="鐢垫眹" value="鐢垫眹" />
+ <el-option label="寰俊" value="寰俊" />
+ <el-option label="鏀粯瀹�" value="鏀粯瀹�" />
+ <el-option label="鏀エ" value="鏀エ" />
+ </el-select>
</el-form-item>
</el-col>
</el-row>
@@ -346,7 +352,7 @@
salesperson: [{ required: true, message: '璇烽�夋嫨涓氬姟鍛�', trigger: 'change' }],
quotationDate: [{ required: true, message: '璇烽�夋嫨鎶ヤ环鏃ユ湡', trigger: 'change' }],
validDate: [{ required: true, message: '璇烽�夋嫨鏈夋晥鏈�', trigger: 'change' }],
- paymentMethod: [{ required: true, message: '璇疯緭鍏ヤ粯娆炬柟寮�', trigger: 'blur' }]
+ paymentMethod: [{ required: true, message: '璇烽�夋嫨浠樻鏂瑰紡', trigger: 'change' }]
}
const productRowRules = {
--
Gitblit v1.9.3