management.vue 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374
  1. <template >
  2. <el-card id="management">
  3. <div slot="header" class="clearfix">
  4. <searchHeader
  5. :dates="mdate"
  6. :title="'经营数据'"
  7. @changeValue="changeValue"
  8. :isShowQuert="true"
  9. :endDate="endDate"
  10. ref="searchHeader"
  11. />
  12. </div>
  13. <el-tabs v-model="activeName">
  14. <el-tab-pane label="总览" name="first">
  15. <div v-if="activeName == 'first'">
  16. <manageOrganAll :data="data" :search="search" ref='manageOrganAll'/>
  17. </div>
  18. </el-tab-pane>
  19. <el-tab-pane label="分部数据" name="second">
  20. <div v-if="activeName == 'second'">
  21. <manageOrgan :data="data" :search="search" ref='manageOrgan'/>
  22. </div>
  23. </el-tab-pane>
  24. </el-tabs>
  25. </el-card>
  26. </template>
  27. <script>
  28. import "echarts/lib/component/dataZoom";
  29. import countTo from "vue-count-to";
  30. import veLine from "v-charts/lib/line.common";
  31. import histogram from "v-charts/lib/histogram.common";
  32. import searchHeader from "./modals/searchDayHeader";
  33. import { getIndex } from "../api";
  34. import { getTimes } from "@/utils";
  35. import { descs, chioseNum } from "../constant";
  36. import { orderType } from "@/constant";
  37. import manageOrganAll from "./modals/manageOrganAll";
  38. import manageOrgan from "./modals/manageOrgan";
  39. export default {
  40. props: ["data", "search"],
  41. components: {
  42. "ve-line": veLine,
  43. "count-to": countTo,
  44. "ve-histogram": histogram,
  45. searchHeader,
  46. manageOrganAll,
  47. manageOrgan
  48. },
  49. computed: {
  50. legend() {
  51. return {
  52. left: "10px",
  53. };
  54. },
  55. items() {
  56. let obj = {};
  57. let arr = [
  58. "TOTAL_AMOUNT",
  59. "FINANCE_AMOUNT",
  60. "FINANCE_BALANCE_AMOUNT",
  61. "FINANCE_PAY",
  62. ];
  63. arr.forEach((str) => {
  64. if (this.data[str]) {
  65. obj[str] = this.data[str];
  66. }
  67. });
  68. // console.log(obj);
  69. return obj;
  70. },
  71. items2() {
  72. let obj = {};
  73. let arr = [
  74. "APPLY_AMOUNT",
  75. "RENEW_AMOUNT",
  76. "VIP_AMOUNT",
  77. "PRACTICE_AMOUNT",
  78. "OTHER_AMOUNT",
  79. ];
  80. arr.forEach((str) => {
  81. if (this.data[str]) {
  82. obj[str] = this.data[str];
  83. }
  84. });
  85. return obj;
  86. },
  87. chartExtend() {
  88. return {
  89. series: {
  90. smooth: false,
  91. },
  92. yAxis: {
  93. //纵轴标尺固定
  94. minInterval: 1,
  95. type: "value",
  96. scale: true,
  97. min: 0,
  98. axisLabel: {
  99. formatter: "{value}元",
  100. },
  101. },
  102. tooltip: {
  103. axisPointer: {
  104. type: "shadow",
  105. shadowStyle: {
  106. color: "rgba(150,150,150,0.2)",
  107. },
  108. },
  109. formatter: (item) => {
  110. return [
  111. item[0].axisValueLabel,
  112. ...item.map(
  113. (d) => `<br/>${d.marker}${d.seriesName}: ${d.value[1]} 元`
  114. ),
  115. ].join("");
  116. },
  117. },
  118. };
  119. },
  120. dataZoom() {
  121. return [
  122. {
  123. type: "slider",
  124. start: 50,
  125. end: 100,
  126. filterMode: "empty",
  127. },
  128. ];
  129. },
  130. chartData() {
  131. const values = Object.values({ ...this.items, ...this.items2 });
  132. const months = {};
  133. for (const item of values) {
  134. for (const row of item.indexMonthData || []) {
  135. const key = this.$helpers.dayjs(row.month).format("YYYY-MM-DD");
  136. if (!months[key]) {
  137. months[key] = {
  138. 日期: key,
  139. };
  140. }
  141. months[key][item.title] = row.percent;
  142. }
  143. }
  144. // console.log(values);
  145. return {
  146. columns: [
  147. "日期",
  148. "总收入",
  149. "现金收入",
  150. "余额收入",
  151. "财务支出",
  152. "报名缴费收入",
  153. "网管课收入",
  154. "其他收入",
  155. "乐团续费收入",
  156. "VIP课收入",
  157. ],
  158. rows: Object.values(months),
  159. loading: true,
  160. };
  161. },
  162. chartDataForMoth() {
  163. const values = Object.values({ ...this.items, ...this.items2 });
  164. const months = {};
  165. for (const item of values) {
  166. for (const row of item.indexMonthData || []) {
  167. const key = this.$helpers.dayjs(row.month).format("YYYY-MM");
  168. if (!months[key]) {
  169. months[key] = {
  170. 月份: key,
  171. };
  172. months[key][item.title] = row.percent;
  173. } else {
  174. if (months[key][item.title]) {
  175. months[key][item.title] = (
  176. parseFloat(months[key][item.title]) + parseFloat(row.percent)
  177. ).toFixed(2);
  178. } else {
  179. months[key][item.title] = parseFloat(row.percent).toFixed(2);
  180. }
  181. }
  182. }
  183. }
  184. return {
  185. columns: [
  186. "月份",
  187. "总收入",
  188. "现金收入",
  189. "余额收入",
  190. "财务支出",
  191. "报名缴费收入",
  192. "网管课收入",
  193. "其他收入",
  194. "乐团续费收入",
  195. "VIP课收入",
  196. ],
  197. rows: Object.values(months),
  198. loading: true,
  199. };
  200. },
  201. dataEmpty() {
  202. return !this.chartData.rows.length;
  203. },
  204. },
  205. data() {
  206. // this.chartSettings = {
  207. // stack: { 总收入: [`现金收入`, `余额收入`] },
  208. // };
  209. return {
  210. orderType,
  211. active: "SHOULD_INCOME_MONEY",
  212. timer: "day",
  213. mdate: [],
  214. loading: false,
  215. endDate: "",
  216. show: true,
  217. activeName: "first",
  218. };
  219. },
  220. mounted() {
  221. this.init();
  222. },
  223. methods: {
  224. init() {
  225. this.$refs.searchHeader.initStatue("month");
  226. this.mdate = this.getInitDate();
  227. this.endDate = this.$helpers.dayjs(new Date()).format("YYYY-MM-DD");
  228. // this.$refs.searchHeader.initStatue()
  229. this.changeValue(this.mdate);
  230. },
  231. changeValue(date) {
  232. // 请求更改数据
  233. this.mdate = date;
  234. // this.isDayOrMoth(date);
  235. if(this.$refs.manageOrganAll&&this.$refs.manageOrganAll.isDayOrMoth){
  236. this.$refs.manageOrganAll.isDayOrMoth(date)
  237. }
  238. this.FetchDetail();
  239. },
  240. async FetchDetail() {
  241. this.loading = true;
  242. let data = [];
  243. try {
  244. const { dates, ...rest } = this.search;
  245. const res = await getIndex({
  246. ...rest,
  247. ...getTimes(this.mdate, ["startDate", "endDate"]),
  248. //
  249. dataTypes:
  250. "FINANCE_AMOUNT,FINANCE_BALANCE_AMOUNT,FINANCE_PAY,TOTAL_AMOUNT",
  251. });
  252. for (const item of res.data) {
  253. // 再循环一遍
  254. for (const key in { ...this.items, ...this.items2 }) {
  255. // console.log(key);
  256. if (item.dataType == key) {
  257. data[item.dataType] = {
  258. ...item,
  259. desc: descs[item.dataType],
  260. };
  261. }
  262. }
  263. }
  264. } catch (error) {
  265. console.log(error);
  266. }
  267. this.loading = false;
  268. this.$emit("resetDate", data);
  269. },
  270. isDayOrMoth(arr) {
  271. if (!arr || arr.length < 1) {
  272. this.timer = "day";
  273. } else {
  274. const count = this.$helpers
  275. .dayjs(arr[0])
  276. .diff(this.$helpers.dayjs(arr[1]), "day");
  277. Math.abs(count) > chioseNum
  278. ? (this.timer = "month")
  279. : (this.timer = "day");
  280. }
  281. },
  282. getInitDate() {
  283. const end = this.$helpers.dayjs(new Date()).format("YYYY-MM-DD");
  284. const start = this.$helpers
  285. .dayjs(new Date())
  286. .set("date", 1)
  287. .format("YYYY-MM-DD");
  288. return [start, end];
  289. },
  290. changeTimer(val){
  291. this.timer = val
  292. }
  293. },
  294. };
  295. </script>
  296. <style lang="less" scoped>
  297. /deep/.description-title {
  298. margin-bottom: 0;
  299. }
  300. #management .statistic .statistic-content > span {
  301. &:first-child {
  302. font-size: 14px !important;
  303. }
  304. font-size: 18px !important;
  305. }
  306. .chioseBox {
  307. position: absolute;
  308. right: 20px;
  309. z-index: 1000;
  310. }
  311. .wrap {
  312. position: relative;
  313. }
  314. .blod {
  315. font-weight: bold;
  316. color: var(--color-primary);
  317. font-size: 22px !important;
  318. }
  319. // .chioseBox {
  320. // position: absolute;
  321. // right: 20px;
  322. // z-index: 1000;
  323. // }
  324. // .wrap {
  325. // position: relative;
  326. // }
  327. .statisticWrap {
  328. // box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.08);
  329. border-radius: 4px;
  330. border: 1px solid #ebeef5;
  331. padding-top: 10px;
  332. margin-bottom: 10px;
  333. position: relative;
  334. &:after {
  335. top: -16px;
  336. margin-left: calc(10% - 14px);
  337. border-top-width: 0;
  338. border-color: transparent;
  339. border-bottom-color: #fff;
  340. content: " ";
  341. border-width: 8px;
  342. position: absolute;
  343. display: block;
  344. width: 0;
  345. height: 0;
  346. border-style: solid;
  347. z-index: 101;
  348. }
  349. &:before {
  350. top: -20px;
  351. margin-left: calc(10% - 16px);
  352. border-top-width: 0;
  353. border-color: transparent;
  354. border-bottom-color: #ebeef5;
  355. content: " ";
  356. border-width: 10px;
  357. position: absolute;
  358. display: block;
  359. width: 0;
  360. height: 0;
  361. border-style: solid;
  362. z-index: 100;
  363. }
  364. }
  365. </style>