shish 2 дней назад
Родитель
Сommit
cba47e72e9
3 измененных файлов с 122 добавлено и 16 удалено
  1. 12 6
      ghsApp/src/admin/stat/customSale.vue
  2. 109 10
      ghsApp/src/admin/stat/distSale.vue
  3. 1 0
      ghsApp/src/api/stat/index.js

+ 12 - 6
ghsApp/src/admin/stat/customSale.vue

@@ -83,17 +83,23 @@ export default {
 	mixins: [list],
 	mixins: [list],
 	computed: {
 	computed: {
 		...mapGetters(["getDictionariesInfo","getLoginInfo"]),
 		...mapGetters(["getDictionariesInfo","getLoginInfo"]),
-		// 底部总扎数:优先用接口 totalCount(含隔天售后扣减),没有则按各客户 count 汇总
+		// 总扎数:优先用接口 totalCount;list 经 PHP 关联数组 JSON 后可能是对象,不能直接 forEach
 		totalCount() {
 		totalCount() {
-			const profile = this.profile || {}
+			const profile = Array.isArray(this.profile) ? {} : (this.profile || {})
 			if (profile.totalCount != null && profile.totalCount !== '') {
 			if (profile.totalCount != null && profile.totalCount !== '') {
 				return parseFloat(profile.totalCount) || 0
 				return parseFloat(profile.totalCount) || 0
 			}
 			}
-			const list = profile.list || []
+			const list = profile.list
+			let rows = []
+			if (Array.isArray(list)) {
+				rows = list
+			} else if (list && typeof list === 'object') {
+				rows = Object.keys(list).map(key => list[key])
+			}
 			let sum = 0
 			let sum = 0
-			list.forEach(item => {
-				sum += parseFloat(item.count) || 0
-			})
+			for (let i = 0; i < rows.length; i++) {
+				sum += parseFloat(rows[i] && rows[i].count) || 0
+			}
 			return parseFloat(sum.toFixed(2)) || 0
 			return parseFloat(sum.toFixed(2)) || 0
 		}
 		}
 	},
 	},

+ 109 - 10
ghsApp/src/admin/stat/distSale.vue

@@ -15,8 +15,31 @@
 			<view class="space-view ex-table">
 			<view class="space-view ex-table">
 				<block>
 				<block>
 					<t-table :headerBackgroundColor="'#F0F2F6'">
 					<t-table :headerBackgroundColor="'#F0F2F6'">
+						<!-- 合计在表头上方:五项同一行,和客户业绩页同一套排版 -->
+						<view class="stat-summary">
+							<view class="stat-summary-item">
+								<view class="stat-summary-label">笔数</view>
+								<view class="stat-summary-value">{{profile.totalNum||0}}</view>
+							</view>
+							<view class="stat-summary-item">
+								<view class="stat-summary-label">扎数</view>
+								<view class="stat-summary-value">{{totalCount}}</view>
+							</view>
+							<view class="stat-summary-item">
+								<view class="stat-summary-label">收入</view>
+								<view class="stat-summary-value">¥{{profile.totalAmount||0}}</view>
+							</view>
+							<view class="stat-summary-item">
+								<view class="stat-summary-label">成本</view>
+								<view class="stat-summary-value">¥{{profile.totalCost||0}}</view>
+							</view>
+							<view class="stat-summary-item">
+								<view class="stat-summary-label">利润</view>
+								<view class="stat-summary-value">¥{{profile.totalProfit||0}}</view>
+							</view>
+						</view>
+						<!-- 片区名改为行标题独占一行,表头只保留 5 列指标,避免长名称把行高撑乱 -->
 						<t-tr header>
 						<t-tr header>
-							<t-th>片区</t-th>
 							<t-th>笔数</t-th>
 							<t-th>笔数</t-th>
 							<t-th>扎数</t-th>
 							<t-th>扎数</t-th>
 							<t-th>金额</t-th>
 							<t-th>金额</t-th>
@@ -24,18 +47,17 @@
 							<t-th>利润</t-th>
 							<t-th>利润</t-th>
 						</t-tr>
 						</t-tr>
 							<block v-if="profile.list && !$util.isEmpty(profile.list)">
 							<block v-if="profile.list && !$util.isEmpty(profile.list)">
-								<view v-for="(item, index) in profile.list" :key="index">
+								<view v-for="(item, index) in profile.list" :key="index" class="sale-item">
+									<view class="sale-item-name">{{item.distName?item.distName:'-'}}</view>
 									<t-tr>
 									<t-tr>
-										<t-td><view style="color:#333333;font-size:28upx;">{{item.distName?item.distName:'-'}}</view></t-td>
-										<t-td><view style="color:#333333;font-size:28upx;">{{parseFloat(item.num)}}</view></t-td>
-										<t-td><view style="color:#333333;font-size:28upx;">{{item.count?parseFloat(item.count):0}}</view></t-td>
-										<t-td><view style="color:#333333;font-size:28upx;">¥{{parseFloat(item.amount)}}</view></t-td>
-										<t-td><view style="color:#333333;font-size:28upx;">¥{{parseFloat(item.cost)}}</view></t-td>
-										<t-td><view style="color:#333333;font-size:28upx;">¥{{parseFloat(item.profit)}}</view></t-td>
+										<t-td><view class="sale-cell">{{parseFloat(item.num)}}笔</view></t-td>
+										<t-td><view class="sale-cell">{{item.count?parseFloat(item.count):0}}扎</view></t-td>
+										<t-td><view class="sale-cell">¥{{parseFloat(item.amount)}}</view></t-td>
+										<t-td><view class="sale-cell">¥{{parseFloat(item.cost)}}</view></t-td>
+										<t-td><view class="sale-cell">¥{{parseFloat(item.profit)}}</view></t-td>
 									</t-tr>
 									</t-tr>
 								</view>
 								</view>
 							</block>
 							</block>
-							<t-tr><t-td><view style="color:black;font-weight:bold;font-size:28upx;">{{profile.totalNum||0}}笔¥{{profile.totalAmount||0}} 成本¥{{ profile.totalCost||0 }} 利润¥{{ profile.totalProfit||0 }}</view></t-td></t-tr>
 					</t-table>
 					</t-table>
 				</block>
 				</block>
 			</view>
 			</view>
@@ -45,6 +67,10 @@
 </view>
 </view>
 </template>
 </template>
 <script>
 <script>
+/**
+ * ghsApp 片区业绩:按片区汇总笔数/扎数/金额/成本/利润。
+ * 工作台进入;排版对齐客户业绩页,长片区名单独占满一行。
+ */
 import AppWrapperEmpty from "@/components/app-wrapper-empty";
 import AppWrapperEmpty from "@/components/app-wrapper-empty";
 import { getStatDist } from "@/api/stat";
 import { getStatDist } from "@/api/stat";
 import { list } from "@/mixins";
 import { list } from "@/mixins";
@@ -55,7 +81,28 @@ import {mapActions, mapGetters} from "vuex";
 export default {
 export default {
 	components: { AppWrapperEmpty,ShopSelect,AppSearchModule,DateSelect },
 	components: { AppWrapperEmpty,ShopSelect,AppSearchModule,DateSelect },
 	mixins: [list],
 	mixins: [list],
-	computed: {		...mapGetters(["getDictionariesInfo","getLoginInfo"])	},
+	computed: {
+		...mapGetters(["getDictionariesInfo","getLoginInfo"]),
+		// 总扎数:优先用接口 totalCount;list 经 PHP 关联数组 JSON 后可能是对象,不能直接 forEach
+		totalCount() {
+			const profile = Array.isArray(this.profile) ? {} : (this.profile || {})
+			if (profile.totalCount != null && profile.totalCount !== '') {
+				return parseFloat(profile.totalCount) || 0
+			}
+			const list = profile.list
+			let rows = []
+			if (Array.isArray(list)) {
+				rows = list
+			} else if (list && typeof list === 'object') {
+				rows = Object.keys(list).map(key => list[key])
+			}
+			let sum = 0
+			for (let i = 0; i < rows.length; i++) {
+				sum += parseFloat(rows[i] && rows[i].count) || 0
+			}
+			return parseFloat(sum.toFixed(2)) || 0
+		}
+	},
 	data() {
 	data() {
 		return {
 		return {
 			params:{
 			params:{
@@ -159,6 +206,58 @@ export default {
 			::v-deep.icon-info {
 			::v-deep.icon-info {
 				color: #333333;
 				color: #333333;
 			}
 			}
+			/* 名称与指标拆成两行:片区名用满屏宽完整展示,指标 5 列对齐表头 */
+			.sale-item {
+				border-bottom: 1upx solid #eeeeee;
+				::v-deep .t-tr {
+					border-bottom: none;
+					padding-top: 8upx;
+					padding-bottom: 16upx;
+				}
+			}
+			/* 片区名用主题蓝加粗,和下面黑色指标数字区分开 */
+			.sale-item-name {
+				padding: 20upx 40upx 4upx;
+				color: #3385FF;
+				font-size: 28upx;
+				font-weight: bold;
+				line-height: 1.4;
+				word-break: break-all;
+			}
+			.sale-cell {
+				color: #333333;
+				font-size: 28upx;
+				white-space: nowrap;
+			}
+			/* 合计五项同一行;排不下才换行 */
+			.stat-summary {
+				display: flex;
+				flex-direction: row;
+				flex-wrap: wrap;
+				background: #F7F8FA;
+				padding: 16upx 8upx 4upx;
+				border-bottom: 1upx solid #eeeeee;
+			}
+			.stat-summary-item {
+				flex: 1;
+				min-width: 120upx;
+				display: flex;
+				flex-direction: column;
+				align-items: center;
+				margin-bottom: 12upx;
+			}
+			.stat-summary-label {
+				font-size: 24upx;
+				color: #666666;
+				margin-bottom: 6upx;
+			}
+			.stat-summary-value {
+				font-size: 24upx;
+				font-weight: bold;
+				color: #333333;
+				text-align: center;
+				word-break: break-all;
+			}
 		}
 		}
 	}
 	}
 	.bar-view {
 	.bar-view {

+ 1 - 0
ghsApp/src/api/stat/index.js

@@ -75,6 +75,7 @@ export const getStatKhCgProfile = data => {
 	return https.get('/stat-kh-cg/profile', data)
 	return https.get('/stat-kh-cg/profile', data)
 }
 }
 
 
+// 片区业绩:按片区汇总笔数/扎数/金额/成本/利润,对应 StatSaleClass::customDistStat
 export const getStatDist = data => {
 export const getStatDist = data => {
 	return https.get('/stat-kh-cg/dist', data)
 	return https.get('/stat-kh-cg/dist', data)
 }
 }