sumResult.vue 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. <!-- 売上集計結果 -->
  2. <template>
  3. <div class="app-container">
  4. <div class="csv-title">
  5. <el-button @click="handleExportCSV" class="append-button">CSV出力</el-button>
  6. </div>
  7. <el-table v-show="initLoadingCompleted && aggregationType === AGGREGATION_TYPE.FC" v-loading="listLoading" :border="true" :data="fcItemList">
  8. <el-table-column :show-overflow-tooltip="true" align="left" header-align="center" label="FC" min-width="60"
  9. prop="fcName"
  10. >
  11. </el-table-column>
  12. <el-table-column :show-overflow-tooltip="true" align="left" header-align="center" label="エリア" min-width="70"
  13. prop="areaName"
  14. width=""/>
  15. <el-table-column :show-overflow-tooltip="true" align="left" header-align="center" label="売上合計" min-width="80"
  16. prop="totalSales"
  17. width=""/>
  18. <el-table-column :show-overflow-tooltip="true" align="left" header-align="center" label="店舗数" min-width="60"
  19. prop="storeCount"
  20. width=""/>
  21. <el-table-column :show-overflow-tooltip="true" align="left" header-align="center" label="平均売上" min-width="60"
  22. prop="avgSales"
  23. width=""/>
  24. <el-table-column :show-overflow-tooltip="true" align="left" header-align="center" :label="ratioLabel" min-width="40"
  25. prop="prevRatio"
  26. width=""/>
  27. <el-table-column :show-overflow-tooltip="true" align="left" header-align="center" label="FC内売上シェア" min-width="50"
  28. prop="salesShare"
  29. width=""/>
  30. </el-table>
  31. <el-table v-show="initLoadingCompleted && aggregationType === AGGREGATION_TYPE.STORE" v-loading="listLoading" :border="true" :data="storeItemList">
  32. <el-table-column :show-overflow-tooltip="true" align="left" header-align="center" label="FC" min-width="60"
  33. prop="fcName"
  34. >
  35. </el-table-column>
  36. <el-table-column :show-overflow-tooltip="true" align="left" header-align="center" label="エリア" min-width="70"
  37. prop="areaName"
  38. width=""/>
  39. <el-table-column :show-overflow-tooltip="true" align="left" header-align="center" label="売上合計" min-width="60"
  40. prop="totalSales"
  41. width=""/>
  42. <el-table-column :show-overflow-tooltip="true" align="left" header-align="center" label="店舗名" min-width="70"
  43. prop="storeName"
  44. width=""/>
  45. <el-table-column :show-overflow-tooltip="true" align="left" header-align="center" label="平均取引額" min-width="60"
  46. prop="avgTransaction"
  47. width=""/>
  48. <el-table-column :show-overflow-tooltip="true" align="left" header-align="center" :label="ratioLabel" min-width="40"
  49. prop="prevRatio"
  50. width=""/>
  51. <el-table-column :show-overflow-tooltip="true" align="left" header-align="center" label="FC内売上シェア" min-width="50"
  52. prop="salesShare"
  53. width=""/>
  54. </el-table>
  55. <pagination v-show="listTotalCnt>0"
  56. v-model:limit="queryParams.pageSize"
  57. v-model:page="queryParams.pageNum"
  58. :total="listTotalCnt"
  59. @pagination="getSearchList"/>
  60. </div>
  61. </template>
  62. <script name="purchaseSaleResults" setup>
  63. import { purchaseSaleList} from "@/api/fcbi/purchaseSale.js"
  64. import useSalesStore from '@/store/modules/sales.js';
  65. import {download} from "@/utils/request.js";
  66. import { AGGREGATION_TYPE, TARGET_PERIOD_TYPE } from '@/constants';
  67. defineExpose({
  68. AGGREGATION_TYPE,
  69. TARGET_PERIOD_TYPE
  70. });
  71. // 認証項目のテーブルデータを格納するリアクティブ
  72. const fcItemList = ref([]);
  73. const storeItemList = ref([]);
  74. // データ読み込み中のローディング状態を管理するリアクティブ
  75. const listLoading = ref(false);
  76. // 検索結果の総件数を格納するリアクティブ
  77. const listTotalCnt = ref(0);
  78. // 初期ロードが完了したかどうかを示すリアクティブ
  79. const initLoadingCompleted = ref(false);
  80. const SalesStore = useSalesStore();
  81. const aggregationType = computed(() => {
  82. return SalesStore.salesData.aggregationType;
  83. });
  84. const ratioLabel = computed(() => {
  85. // 从存储中获取选择的类型(月指定/年度指定)
  86. const { releaseType } = SalesStore.salesData;
  87. // 返回对应的标题
  88. return releaseType === 'immediate' ? '前月比' : '前年度比';
  89. });
  90. /**
  91. * コンポーネントの状態を管理するリアクティブオブジェクト
  92. */
  93. const data = reactive({
  94. form: {},
  95. queryParams: {
  96. pageNum: 1,
  97. pageSize: 50,
  98. startYear: '',
  99. startMonth: '',
  100. annual: '',
  101. brandCode: [],
  102. regions: [],
  103. salesFlag: 0
  104. },
  105. });
  106. // リアクティブオブジェクトからプロパティを参照可能なオブジェクトに変換
  107. const {queryParams} = toRefs(data);
  108. onMounted(() => {
  109. const {
  110. startYear,
  111. startMonth,
  112. annual,
  113. brandCodes,
  114. regionCodes,
  115. salesFlag,
  116. aggregationType
  117. } = SalesStore.salesData;
  118. queryParams.value.startYear = startYear;
  119. queryParams.value.startMonth = startMonth;
  120. queryParams.value.annual = annual;
  121. queryParams.value.regionCodes = regionCodes;
  122. queryParams.value.brandCodes = brandCodes;
  123. queryParams.value.salesFlag = salesFlag;
  124. queryParams.value.aggregationType = aggregationType;
  125. getSearchList();
  126. });
  127. /**
  128. * 発注リストを検索する関数
  129. * APIを呼び出して検索条件に一致する発注データを取得する
  130. */
  131. function getSearchList() {
  132. listLoading.value = true;
  133. const params = {
  134. pageNum: queryParams.value.pageNum,
  135. pageSize: queryParams.value.pageSize,
  136. // 月指定参数(仅当月指定时有效)
  137. startYear: queryParams.value.startYear,
  138. startMonth: queryParams.value.startMonth,
  139. // 年度指定参数(仅当年度指定时有效)
  140. annual: queryParams.value.annual,
  141. // FC选择值
  142. brandCodes: queryParams.value.brandCodes,
  143. // エリア选择值
  144. regionCodes: queryParams.value.regionCodes,
  145. // 标志位(用于后端判断逻辑)
  146. salesFlag: queryParams.value.salesFlag
  147. };
  148. purchaseSaleList(params).then(response => {
  149. fcItemList.value = response.rows;
  150. storeItemList.value = response.rows;
  151. listTotalCnt.value = response.total;
  152. listLoading.value = false;
  153. initLoadingCompleted.value = true;
  154. });
  155. }
  156. function handleExportCSV() {
  157. const { salesFlag } = queryParams.value;
  158. let fileNamePrefix;
  159. switch (salesFlag) {
  160. case 1:
  161. fileNamePrefix = "monthly_fc_sales_by_current_region";
  162. break;
  163. case 2:
  164. fileNamePrefix = "monthly_fc_sales_by_parent_region";
  165. break;
  166. case 3:
  167. fileNamePrefix = "annual_fc_sales_by_current_region";
  168. break;
  169. case 4:
  170. fileNamePrefix = "annual_fc_sales_by_parent_region";
  171. break;
  172. case 5:
  173. fileNamePrefix = "monthly_store_sales_by_region";
  174. break;
  175. default:
  176. fileNamePrefix = "annual_store_sales_by_region";
  177. }
  178. const fileName = `${fileNamePrefix}_${new Date().getTime()}.csv`;
  179. const exportParams = {
  180. pageNum: queryParams.value.pageNum,
  181. pageSize: queryParams.value.pageSize,
  182. // 月指定参数(仅当月指定时有效)
  183. startYear: queryParams.value.startYear,
  184. startMonth: queryParams.value.startMonth,
  185. // 年度指定参数(仅当年度指定时有效)
  186. annual: queryParams.value.annual,
  187. // FC选择值
  188. brandCodes: queryParams.value.brandCodes,
  189. // エリア选择值
  190. regionCodes: queryParams.value.regionCodes,
  191. // 标志位(用于后端判断逻辑)
  192. salesFlag: queryParams.value.salesFlag
  193. };
  194. download('system/purchase/sale/exportResultsCsv', exportParams, fileName);
  195. }
  196. </script>
  197. <style>
  198. .csv-title {
  199. font-size: 14px;
  200. color: #606266;
  201. margin: 0 0 15px 20px;
  202. padding-top: 10px;
  203. font-weight: 700;
  204. }
  205. .append-button{
  206. background-color: #FF0066;
  207. color: white;
  208. width: 200px;
  209. }
  210. /* 响应式样式 */
  211. @media (max-width: 767px) {
  212. /* 手机设备 */
  213. .csv-title {
  214. margin-left: 10px;
  215. font-size: 13px;
  216. }
  217. .append-button {
  218. width: 120px;
  219. font-size: 12px;
  220. padding: 8px 0;
  221. }
  222. .el-table {
  223. font-size: 12px;
  224. }
  225. .el-table-column {
  226. min-width: 40px !important;
  227. }
  228. }
  229. @media (min-width: 768px) and (max-width: 1023px) {
  230. /* 平板设备 */
  231. .csv-title {
  232. margin-left: 15px;
  233. }
  234. .append-button {
  235. width: 160px;
  236. }
  237. }
  238. /* 电脑设备保持原有样式 */
  239. @media (min-width: 1024px) {
  240. .csv-title {
  241. margin-left: 20px;
  242. }
  243. .append-button {
  244. width: 200px;
  245. }
  246. }
  247. </style>