department.vue 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386
  1. <template>
  2. <div v-loading="loading">
  3. <div class="search clear">
  4. <div style="float:left;line-height:30px;display:flex;align-items:center">
  5. <el-popover placement="top" width="200" trigger="hover" content="不含业务公司供应商端数据">
  6. <template #reference>
  7. <i
  8. class="el-icon-warning-outline"
  9. style="font-size:16px;cursor:pointer;padding-top:5px;padding-right:5px;display:inline-block"
  10. ></i>
  11. </template>
  12. </el-popover>部门完成情况
  13. </div>
  14. <div style="float:right">
  15. <el-select
  16. size="small"
  17. style="margin-right:10px;width:135px"
  18. v-model="companyNo"
  19. @change="requestData"
  20. :disabled="isEmpty"
  21. >
  22. <el-option
  23. v-for="depart in cp_companies"
  24. :key="depart.value"
  25. :label="depart.label"
  26. :value="depart.value"
  27. />
  28. </el-select>
  29. <el-date-picker
  30. :disabled="isEmpty"
  31. class="fr picker no-padding"
  32. v-model="daytime"
  33. :picker-options="{ disbaledData(time) { return time.getTime() > Date.now(); } }"
  34. style=";width:100px"
  35. value-format="yyyy-MM-dd"
  36. format="yyyy-MM-dd"
  37. :editable="false"
  38. :clearable="false"
  39. placeholder="选择日期"
  40. :size="'small'"
  41. align="right"
  42. type="date"
  43. />
  44. </div>
  45. </div>
  46. <el-row style="margin-top: 10px; display: flex;width:100%;margin-top:10px" v-if="!isEmpty">
  47. <el-table
  48. border
  49. size="mini"
  50. :data="list"
  51. :header-cell-class-name="setHeaderClassName"
  52. :cell-class-name="setCellClassName"
  53. :span-method="spanMethod"
  54. >
  55. <!-- <el-table-column fixed="left" label="公司" prop="company" align="center" width="45px" /> -->
  56. <el-table-column fixed="left" label="部门" prop="depart" align="center" width="60px">
  57. <template slot-scope="scope">
  58. <p
  59. style="margin:0px"
  60. v-for="(chunk, index) in scope.row.depart.split('@')"
  61. :key="index"
  62. >{{ chunk }}</p>
  63. </template>
  64. </el-table-column>
  65. <el-table-column label="业绩类型" align="center" min-width="105px">
  66. <template slot-scope="scope">{{ scope.row.type }}</template>
  67. </el-table-column>
  68. <el-table-column label="当月销售(净)" align="center" min-width="105px">
  69. <template slot-scope="scope">{{ unit2TenThousand(scope.row.monthSale,isTenThound) }}</template>
  70. </el-table-column>
  71. <el-table-column label="当月销售" align="center" min-width="105px">
  72. <template slot-scope="scope">{{ unit2TenThousand(scope.row.monthSaleNotReturn,isTenThound) }}</template>
  73. </el-table-column>
  74. <el-table-column label="销售退货" align="center" min-width="105px">
  75. <template slot-scope="scope">{{ unit2TenThousand(scope.row.monthReturn,isTenThound) }}</template>
  76. </el-table-column>
  77. <el-table-column label="销售合计" align="center" min-width="105px">
  78. <template slot-scope="scope">{{ unit2TenThousand(scope.row.monthSaleAmount,isTenThound) }}</template>
  79. </el-table-column>
  80. <el-table-column label="当月成本(净)" align="center" min-width="105px">
  81. <template slot-scope="scope">{{ unit2TenThousand(scope.row.monthCost,isTenThound) }}</template>
  82. </el-table-column>
  83. </el-table>
  84. </el-row>
  85. <template v-else>
  86. <div style="text-align:center;line-height:60px;user-select:none">当前账号没有访问权限</div>
  87. </template>
  88. </div>
  89. </template>
  90. <script>
  91. import asyncRequest from "@/api/newResults";
  92. import setHeight from "@/mixins/index";
  93. import { mapCompany } from "./mapCompany";
  94. import dayjs from "dayjs";
  95. import {
  96. addition,
  97. division,
  98. subtraction,
  99. multiplication,
  100. unit2TenThousand
  101. } from "../newReport/src/_utils";
  102. export default {
  103. mixins: [setHeight],
  104. props: ["companies", "costField", "isTenThound"],
  105. data() {
  106. return {
  107. list: [],
  108. daytime: "",
  109. companyNo: "",
  110. loading: false,
  111. isEmpty: false,
  112. cp_companies: []
  113. };
  114. },
  115. computed: {
  116. currentCompanyName() {
  117. return this.companies.find(item => item.value === this.companyNo).label;
  118. }
  119. },
  120. mounted() {
  121. this.isEmpty = this.companies.length === 0;
  122. if (this.isEmpty) return;
  123. this.cp_companies = this.companies.map(item => ({
  124. ...item,
  125. label:
  126. mapCompany[item.label] === "万宇"
  127. ? `平台公司: 万宇`
  128. : `业务公司: ${mapCompany[item.label]}`
  129. }));
  130. let list = [
  131. "平台公司: 万宇",
  132. "业务公司: 百辰",
  133. "业务公司: 泓源",
  134. "业务公司: 普润",
  135. "业务公司: 锦兴",
  136. "业务公司: 知事"
  137. ];
  138. const cp_list = this.cp_companies.map(item => item.label);
  139. list = list.filter(item => cp_list.includes(item));
  140. this.cp_companies = list.map(item => this.cp_companies.find(cp_item => cp_item.label === item));
  141. this.companyNo = this.cp_companies[0].value;
  142. this.companyNo = this.cp_companies[0].value;
  143. this.daytime = this.transformTime();
  144. },
  145. watch: {
  146. daytime: {
  147. handler() {
  148. this.requestData();
  149. }
  150. }
  151. },
  152. methods: {
  153. addition,
  154. unit2TenThousand,
  155. setCellClassName({ column, row }) {
  156. const { label } = column;
  157. if(!label) return;
  158. let base = "";
  159. if (row.depart.indexOf("万宇") !== -1) base += "font-bold "
  160. if (label === "当月营收目标") {
  161. base += "bg__success";
  162. return base;
  163. }
  164. if ((label.indexOf("营业") !== -1 || label.indexOf("营收") !== -1) && label !== "当日营业收入") {
  165. base += "bg__success_1";
  166. return base;
  167. }
  168. if (label === "毛利目标") {
  169. base += "bg__primary";
  170. return base;
  171. }
  172. if (label.indexOf("毛利") !== -1) {
  173. base += "bg__primary_1";
  174. return base;
  175. }
  176. if (label.indexOf("成本") !== -1) {
  177. base += "bg__warning_1";
  178. return base;
  179. }
  180. return base;
  181. },
  182. setHeaderClassName({ column }) {
  183. const { label } = column;
  184. if (label === "当月营收目标") return "bg__success";
  185. if (
  186. (label.indexOf("营业") !== -1 || label.indexOf("营收") !== -1) &&
  187. label !== "当日营业收入"
  188. )
  189. return "bg__success_1";
  190. if (label === "毛利目标") return "bg__primary";
  191. if (label.indexOf("毛利") !== -1) return "bg__primary_1";
  192. if (label.indexOf("成本") !== -1) return "bg__warning_1";
  193. },
  194. getCurrentRateStyle(current) {
  195. const days = dayjs(this.daytime).daysInMonth();
  196. const oneDay = Number(division(100, days)).toFixed(2);
  197. const currentDay = dayjs(this.daytime).date();
  198. const currentTotalTip = Number(
  199. multiplication(currentDay, oneDay)
  200. ).toFixed(2);
  201. return Number(currentTotalTip) > Number(current) ? "color:red" : "";
  202. },
  203. getCurrentValueStyle(current, total) {
  204. const days = dayjs(this.daytime).daysInMonth();
  205. const oneDay = Number(division(total, days)).toFixed(2);
  206. const currentDay = dayjs(this.daytime).date();
  207. const currentTotalTip = Number(
  208. multiplication(currentDay, oneDay)
  209. ).toFixed(2);
  210. return Number(currentTotalTip) > Number(current) ? "color: red" : "";
  211. },
  212. transformTime() {
  213. let time = new Date();
  214. let y = time.getFullYear();
  215. let M = time.getMonth() + 1;
  216. let d = time.getDate();
  217. return y + "-" + (M < 10 ? "0" + M : M) + "-" + (d < 10 ? "0" + d : d);
  218. },
  219. /* 表格合并列和行 */
  220. spanMethod({ rowIndex, columnIndex }) {
  221. if (columnIndex === 0 || columnIndex === 3 || columnIndex === 4 || columnIndex === 5) {
  222. const _row = this.flitterData(this.list).one[rowIndex];
  223. const _col = _row > 0 ? 1 : 0;
  224. return { rowspan: _row, colspan: _col };
  225. }
  226. },
  227. /**合并表格的第一列,处理表格数据 */
  228. flitterData(arr) {
  229. let spanOneArr = [];
  230. let concatOne = 0;
  231. arr.forEach((item, index) => {
  232. if (index === 0) {
  233. spanOneArr.push(1);
  234. } else {
  235. //注意这里的quarterly是表格绑定的字段,根据自己的需求来改
  236. if (
  237. (item.depart === arr[index - 1].depart)) {
  238. //第一列需合并相同内容的判断条件
  239. spanOneArr[concatOne] += 1;
  240. spanOneArr.push(0);
  241. } else {
  242. spanOneArr.push(1);
  243. concatOne = index;
  244. }
  245. }
  246. });
  247. return { one: spanOneArr };
  248. },
  249. async requestData() {
  250. this.loading = true;
  251. const res = await asyncRequest.departmentEveryDay({
  252. daytime: this.daytime,
  253. companyNo: this.companyNo
  254. });
  255. if (res.code === 0 && res.data && res.data.length > 0) {
  256. let list = res.data;
  257. const mapToDepartment = {
  258. 百辰: "客服部@百辰",
  259. 泓源: "网络部@泓源",
  260. 普润: "项目部@普润",
  261. 平台: "平台部@万宇"
  262. };
  263. list = list.filter(item => Number(item.msale_total) !== 0);
  264. let mapList = ["平台", "百辰", "泓源", "普润"];
  265. const cl = list.map(item => item.depart);
  266. mapList = mapList.filter(item => cl.findIndex(i => i.indexOf(item)) !== -1);
  267. list = mapList.map(item => list.find(i => i.depart.indexOf(item) !== -1));
  268. list = list.filter(item => item)
  269. list = list.map(item => {
  270. const depart = mapToDepartment[item.depart] || '--'
  271. const monthSaleAmount = Number(subtraction(item.msale_total,item.mth_total)).toFixed(2)
  272. const zy = {
  273. depart,
  274. type:'直营/自营',
  275. monthSale:item.mzy_sale_total,
  276. monthSaleNotReturn:item.msale_total,
  277. monthReturn:item.mth_total,
  278. monthSaleAmount,
  279. monthCost:item.mzy_cost_total
  280. };
  281. const qd = {
  282. depart,
  283. type:'支付渠道',
  284. monthSale:item.mchannel_sale_total,
  285. monthSaleNotReturn:item.msale_total,
  286. monthReturn:item.mth_total,
  287. monthSaleAmount,
  288. monthCost:item.mchannel_cost_total
  289. };
  290. return [zy, qd]
  291. })
  292. const totalItem = list.reduce((prev,current) => ({
  293. ...prev,
  294. monthSaleNotReturn:Number(addition(prev.monthSaleNotReturn,current[0].monthSaleNotReturn)).toFixed(2),
  295. monthCost:Number(addition(Number(addition(prev.monthCost,current[0].monthCost)).toFixed(2),current[1].monthCost)).toFixed(2)
  296. }), {
  297. depart:'合计',
  298. type:'--',
  299. monthSale:'--',
  300. monthSaleNotReturn:0,
  301. monthReturn:'--',
  302. monthSaleAmount:'--',
  303. monthCost:0
  304. });
  305. console.log('🚀~',totalItem);
  306. const list_copy = [];
  307. list.forEach(item => Array.isArray(item) && item.forEach(i => list_copy.push(i)));
  308. this.list = [...list_copy,totalItem];
  309. } else {
  310. this.list = [];
  311. }
  312. this.getHeight();
  313. this.loading = false;
  314. }
  315. }
  316. };
  317. </script>
  318. <style lang="scss" scoped>
  319. .new-results {
  320. .search {
  321. height: 36px;
  322. padding: 0px 10px;
  323. margin-top: 10px;
  324. width: 100%;
  325. box-sizing: border-box;
  326. justify-content: space-between;
  327. }
  328. }
  329. .table-size {
  330. display: flex;
  331. width: 200px;
  332. border: 1px solid #ebeef5;
  333. flex-direction: column;
  334. p {
  335. flex: 1;
  336. border-bottom: 1px solid #ebeef5;
  337. padding: 5px 10px;
  338. margin: 0px;
  339. &:last-child {
  340. border: none;
  341. }
  342. }
  343. }
  344. </style>