CompanyStatistics.vue 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489
  1. <template>
  2. <div class="card-search">
  3. <a-form
  4. ref="formRef"
  5. name="advanced_search"
  6. class="ant-advanced-search-form"
  7. :model="searchParams"
  8. >
  9. <a-row :gutter="24">
  10. <a-col :span="6">
  11. <a-form-item label="日期" :label-col="{ span: 8 }" name="emphasisTypeId">
  12. <a-range-picker format="YYYY-MM-DD" :placeholder="['开始日期', '结束日期']" v-model:value="reportDate"
  13. @change="onRangeChange"/>
  14. </a-form-item>
  15. </a-col>
  16. <a-col :span="6" style="text-align: left">
  17. <a-button type="primary" html-type="submit" @click="onFinish">查询</a-button>
  18. <a-button
  19. style="margin: 0 8px"
  20. @click="
  21. () => {
  22. formRef.resetFields();
  23. onFinish();
  24. }
  25. ">重置
  26. </a-button>
  27. </a-col>
  28. </a-row>
  29. </a-form>
  30. <!-- 操作按钮 -->
  31. <a-row class="edit-operation" style="margin-bottom: 20px">
  32. <a-col :span="24" class="flex-space-between">
  33. <div>
  34. <a-radio-group v-model:value="searchType" button-style="solid" @change="searchTypeChange">
  35. <a-radio-button value="companyCount">各区县企业入库与走访情况统计</a-radio-button>
  36. <a-radio-button value="workSituationCount">各区县企业用工人数与岗位招聘人数统计</a-radio-button>
  37. <a-radio-button value="industryWorkSituationCount">各行业企业用工人数与岗位招聘人数统计</a-radio-button>
  38. </a-radio-group>
  39. </div>
  40. <div>
  41. </div>
  42. </a-col>
  43. </a-row>
  44. <!-- 数据展示 -->
  45. <!-- 企业入库与走访情况统计 -->
  46. <div v-show="searchType == 'companyCount'">
  47. <a-table :columns="companyCountDataTableColumns" :data-source="companyCountDataList"
  48. :scroll="{ x:'100%' }"
  49. :loading="searchLoading"
  50. :pagination="false"
  51. bordered>
  52. </a-table>
  53. </div>
  54. <!-- 企业用工人数与岗位招聘人数统计 -->
  55. <div v-show="searchType == 'workSituationCount'">
  56. <a-table :columns="workSituationCountDataTableColumns" :data-source="workSituationCountDataList"
  57. :scroll="{ x:'100%' }"
  58. :loading="searchLoading"
  59. :pagination="false"
  60. bordered>
  61. </a-table>
  62. </div>
  63. <!-- 企业用工人数与岗位招聘人数统计 -->
  64. <div v-show="searchType == 'industryWorkSituationCount'">
  65. <a-table :columns="industryWorkSituationCountDataTableColumns" :data-source="industryWorkSituationCountDataList"
  66. :scroll="{ x:'100%' }"
  67. :loading="searchLoading"
  68. :pagination="false"
  69. bordered>
  70. </a-table>
  71. </div>
  72. </div>
  73. </template>
  74. <script setup lang="ts">
  75. import {onMounted, reactive, ref} from "vue";
  76. import type {RangeValue} from "ant-design-vue/es/vc-picker/interface";
  77. import dayjs from "dayjs";
  78. import {getSysDictionaryList} from "@/api/system/dictionary";
  79. import {
  80. getIndustryCompanyWorkSituationCount,
  81. getRegionCompanyModelCompanyCount,
  82. getRegionCompanyWorkSituationCount
  83. } from "@/api/statistics";
  84. const searchParams = reactive({
  85. startDate: "",
  86. endDate: "",
  87. });
  88. const reportDate = ref<RangeValue<any>>();
  89. const searchType = ref("companyCount");
  90. const formRef = ref();
  91. const searchLoading = ref(false);
  92. const companyModelList = ref<Array<any>>();
  93. // 企业入库与走访情况统计表结构
  94. const companyCountDataTableColumns = ref<Array<any>>([
  95. {
  96. title: '区县', dataIndex: 'regionName', key: 'regionName', align: "center", width: 280
  97. },
  98. ]);
  99. const companyCountDataList = ref<Array<any>>([]);
  100. const companyCountKeyTemp = ref<Array<any>>([]);
  101. // 企业用工人数与岗位招聘人数统计表结构
  102. const workSituationCountDataTableColumns = ref<Array<any>>([
  103. {
  104. title: '区县', dataIndex: 'regionName', key: 'regionName', align: "center", width: 280
  105. },
  106. ]);
  107. const workSituationCountDataList = ref<Array<any>>([]);
  108. const workSituationCountKeyTemp = ref<Array<any>>([]);
  109. // 各行业企业用工人数与岗位招聘人数统计表结构
  110. const industryWorkSituationCountDataTableColumns = ref<Array<any>>([
  111. {
  112. title: '产业分类', dataIndex: 'estateCategoryName', key: 'estateCategoryName', align: "center", width: 150,
  113. customCell: (record, index: any) => {
  114. const obj = {
  115. colSpan: 1,
  116. rowSpan: 1,
  117. };
  118. if (record.estateCategoryName == '合计' || record.estateCategoryName == '小计') {
  119. obj.colSpan = 3;
  120. }
  121. if (index === 0 || record.estateCategoryName !== industryWorkSituationCountDataList.value[index - 1].estateCategoryName) {
  122. for (let i = index + 1; i < industryWorkSituationCountDataList.value.length; i++) {
  123. if (industryWorkSituationCountDataList.value[i].estateCategoryName == record.estateCategoryName) {
  124. obj.rowSpan++;
  125. } else {
  126. break;
  127. }
  128. }
  129. } else {
  130. obj.rowSpan = 0;
  131. }
  132. return obj;
  133. },
  134. }, {
  135. title: '所属行业', dataIndex: 'parentIndustryName', key: 'parentIndustryName', align: "center", width: 150,
  136. customCell: (record, index: any) => {
  137. const obj = {
  138. colSpan: 1,
  139. rowSpan: 1,
  140. };
  141. if (record.estateCategoryName == '合计' || record.estateCategoryName == '小计') {
  142. obj.colSpan = 0;
  143. }
  144. if (index === 0 || record.parentIndustryName !== industryWorkSituationCountDataList.value[index - 1].parentIndustryName) {
  145. for (let i = index + 1; i < industryWorkSituationCountDataList.value.length; i++) {
  146. if (industryWorkSituationCountDataList.value[i].parentIndustryName == record.parentIndustryName) {
  147. obj.rowSpan++;
  148. } else {
  149. break;
  150. }
  151. }
  152. } else {
  153. obj.rowSpan = 0;
  154. }
  155. return obj;
  156. },
  157. }, {
  158. title: '行业名称', dataIndex: 'industryName', key: 'industryName', align: "center", width: 200,
  159. customCell: (record) => {
  160. const obj = {
  161. colSpan: 1,
  162. rowSpan: 1,
  163. };
  164. if (record.estateCategoryName == '合计' || record.estateCategoryName == '小计') {
  165. obj.colSpan = 0;
  166. }
  167. return obj;
  168. },
  169. },
  170. ]);
  171. const industryWorkSituationCountDataList = ref<Array<any>>([]);
  172. const industryWorkSituationCountKeyTemp = ref<Array<any>>([]);
  173. // 时间段变更事件
  174. const onRangeChange = (dateString: [string, string]) => {
  175. searchParams.startDate = dateString != null ? dayjs(dateString[0]).format("YYYY-MM-DD") : "";
  176. searchParams.endDate = dateString != null ? dayjs(dateString[1]).format("YYYY-MM-DD") : "";
  177. onFinish();
  178. };
  179. function onFinish() {
  180. searchTypeChange();
  181. }
  182. // 获取企业规模
  183. function getCompanyModel() {
  184. getSysDictionaryList("CompanyModel").then((result: any) => {
  185. companyModelList.value = result;
  186. // 生成表结构
  187. result.forEach((item: any) => {
  188. const key = 'companyModel' + item.value;
  189. // 企业入库与走访情况统计表结构
  190. companyCountKeyTemp.value.push(...[key + 'Count', key + 'SigninCount']);
  191. companyCountDataTableColumns.value.push({
  192. title: item.name, dataIndex: key, key, align: "center",
  193. children: [
  194. {
  195. title: '入库',
  196. dataIndex: key + 'Count',
  197. key: key + 'Count',
  198. align: "center"
  199. },
  200. {
  201. title: '走访',
  202. dataIndex: key + 'SigninCount',
  203. key: key + 'SigninCount',
  204. align: "center"
  205. },
  206. ]
  207. })
  208. // 区县企业用工人数与岗位招聘人数统计表结构
  209. workSituationCountKeyTemp.value.push(...[key + 'WorkSituationCount', key + 'RecruitCount']);
  210. workSituationCountDataTableColumns.value.push({
  211. title: item.name, dataIndex: key, key, align: "center",
  212. children: [
  213. {
  214. title: '用工人数',
  215. dataIndex: key + 'WorkSituationCount',
  216. key: key + 'WorkSituationCount',
  217. align: "center"
  218. },
  219. {
  220. title: '岗位人数',
  221. dataIndex: key + 'RecruitCount',
  222. key: key + 'RecruitCount',
  223. align: "center"
  224. },
  225. ]
  226. })
  227. // 行业企业用工人数与岗位招聘人数统计表结构
  228. industryWorkSituationCountKeyTemp.value.push(...[key + 'WorkSituationCount', key + 'RecruitCount']);
  229. industryWorkSituationCountDataTableColumns.value.push({
  230. title: item.name, dataIndex: key, key, align: "center",
  231. children: [
  232. {
  233. title: '用工人数',
  234. dataIndex: key + 'WorkSituationCount',
  235. key: key + 'WorkSituationCount',
  236. align: "center"
  237. },
  238. {
  239. title: '岗位人数',
  240. dataIndex: key + 'RecruitCount',
  241. key: key + 'RecruitCount',
  242. align: "center"
  243. },
  244. ]
  245. })
  246. })
  247. });
  248. }
  249. function searchTypeChange() {
  250. if (searchType.value == "companyCount") {
  251. searchLoading.value = true;
  252. companyCountDataList.value = [];
  253. getRegionCompanyModelCompanyCount({...searchParams}).then((result: any) => {
  254. // 初始化合计数据
  255. let count = {
  256. regionCode: -1,
  257. regionName: "合计",
  258. }
  259. // 初始化字段值为O
  260. companyCountKeyTemp.value.forEach((key: any) => {
  261. count[key] = 0;
  262. })
  263. result.forEach((resItem: any) => {
  264. const key = 'companyModel' + resItem.companyModel;
  265. // 查询获取区县数据的下标,保证每个区县只存在一条数据
  266. const findIndex = companyCountDataList.value.findIndex((find: any) => find.regionCode == resItem.regionCode);
  267. if (findIndex > -1) {
  268. // 区县已存在,修改这条数据
  269. if (resItem.companyCount > 0) {
  270. companyCountDataList.value[findIndex][key + 'Count'] = resItem.companyCount;
  271. count[key + 'Count'] += resItem.companyCount;
  272. }
  273. if (resItem.signinCompanyCount > 0) {
  274. companyCountDataList.value[findIndex][key + 'SigninCount'] = resItem.signinCompanyCount;
  275. count[key + 'SigninCount'] += resItem.signinCompanyCount;
  276. }
  277. } else {
  278. // 不存在,新增一条数据
  279. const newData = {
  280. regionCode: resItem.regionCode,
  281. regionName: resItem.regionName,
  282. }
  283. companyCountKeyTemp.value.forEach((key: any) => {
  284. newData[key] = 0;
  285. })
  286. if (resItem.companyCount > 0) {
  287. newData[key + 'Count'] = resItem.companyCount;
  288. count[key + 'Count'] += resItem.companyCount;
  289. }
  290. if (resItem.signinCompanyCount > 0) {
  291. newData[key + 'SigninCount'] = resItem.signinCompanyCount;
  292. count[key + 'SigninCount'] += resItem.signinCompanyCount;
  293. }
  294. companyCountDataList.value.push(newData);
  295. }
  296. });
  297. console.log(count);
  298. companyCountDataList.value.push(count);
  299. }).finally(() => {
  300. searchLoading.value = false;
  301. })
  302. }
  303. if (searchType.value == "workSituationCount") {
  304. searchLoading.value = true;
  305. workSituationCountDataList.value = [];
  306. getRegionCompanyWorkSituationCount({...searchParams}).then((result: any) => {
  307. // 初始化合计数据
  308. let count = {
  309. regionCode: -1,
  310. regionName: "合计",
  311. }
  312. // 初始化字段值为O
  313. workSituationCountKeyTemp.value.forEach((key: any) => {
  314. count[key] = 0;
  315. });
  316. result.forEach((resItem: any) => {
  317. const key = 'companyModel' + resItem.companyModel;
  318. // 查询获取区县数据的下标,保证每个区县只存在一条数据
  319. const findIndex = workSituationCountDataList.value.findIndex((find: any) => find.regionCode == resItem.regionCode);
  320. if (findIndex > -1) {
  321. // 区县已存在,修改这条数据
  322. if (resItem.workSituationCount > 0) {
  323. workSituationCountDataList.value[findIndex][key + 'WorkSituationCount'] = resItem.workSituationCount;
  324. count[key + 'WorkSituationCount'] += resItem.workSituationCount;
  325. }
  326. if (resItem.recruitCount > 0) {
  327. workSituationCountDataList.value[findIndex][key + 'RecruitCount'] = resItem.recruitCount;
  328. count[key + 'RecruitCount'] += resItem.recruitCount;
  329. }
  330. } else {
  331. // 不存在,新增一条数据
  332. const newData = {
  333. regionCode: resItem.regionCode,
  334. regionName: resItem.regionName,
  335. }
  336. workSituationCountKeyTemp.value.forEach((key: any) => {
  337. newData[key] = 0;
  338. })
  339. if (resItem.workSituationCount > 0) {
  340. newData[key + 'WorkSituationCount'] = resItem.workSituationCount;
  341. count[key + 'WorkSituationCount'] += resItem.workSituationCount;
  342. }
  343. if (resItem.recruitCount > 0) {
  344. newData[key + 'RecruitCount'] = resItem.recruitCount;
  345. count[key + 'RecruitCount'] += resItem.recruitCount;
  346. }
  347. workSituationCountDataList.value.push(newData);
  348. }
  349. });
  350. workSituationCountDataList.value.push(count);
  351. }).finally(() => {
  352. searchLoading.value = false;
  353. })
  354. }
  355. if (searchType.value == "industryWorkSituationCount") {
  356. searchLoading.value = true;
  357. industryWorkSituationCountDataList.value = [];
  358. getIndustryCompanyWorkSituationCount({...searchParams}).then((result: any) => {
  359. // 初始化合计数据
  360. let count = {
  361. estateCategoryId: -1,
  362. estateCategoryName: "合计",
  363. parentIndustryName: "合计",
  364. industryName: "合计"
  365. }
  366. // 初始化字段值为O
  367. industryWorkSituationCountKeyTemp.value.forEach((key: any) => {
  368. count[key] = 0;
  369. });
  370. result.forEach((resItem: any) => {
  371. const key = 'companyModel' + resItem.companyModel;
  372. // 查询获取行业数据的下标,保证每个区县只存在一条数据
  373. const findIndex = industryWorkSituationCountDataList.value.findIndex((find: any) => find.industryName == resItem.industryName);
  374. if (findIndex > -1) {
  375. // 行业已存在,修改这条数据
  376. if (resItem.workSituationCount > 0) {
  377. industryWorkSituationCountDataList.value[findIndex][key + 'WorkSituationCount'] = resItem.workSituationCount;
  378. count[key + 'WorkSituationCount'] += resItem.workSituationCount;
  379. }
  380. if (resItem.recruitCount > 0) {
  381. industryWorkSituationCountDataList.value[findIndex][key + 'RecruitCount'] = resItem.recruitCount;
  382. count[key + 'RecruitCount'] += resItem.recruitCount;
  383. }
  384. } else {
  385. // 不存在,新增一条数据
  386. const newData = {
  387. parentIndustryName: resItem.parentIndustryName,
  388. industryName: resItem.industryName,
  389. }
  390. setEstateCategoryName(newData);
  391. industryWorkSituationCountKeyTemp.value.forEach((key: any) => {
  392. newData[key] = 0;
  393. })
  394. if (resItem.workSituationCount > 0) {
  395. newData[key + 'WorkSituationCount'] = resItem.workSituationCount;
  396. count[key + 'WorkSituationCount'] += resItem.workSituationCount;
  397. }
  398. if (resItem.recruitCount > 0) {
  399. newData[key + 'RecruitCount'] = resItem.recruitCount;
  400. count[key + 'RecruitCount'] += resItem.recruitCount;
  401. }
  402. industryWorkSituationCountDataList.value.push(newData);
  403. }
  404. });
  405. // 按产业分类进行排序
  406. industryWorkSituationCountDataList.value.sort((a, b) => a.estateCategoryId - b.estateCategoryId);
  407. // 统计小计数据
  408. calculateCategorySubtotal();
  409. // 在末尾添加合计数据
  410. industryWorkSituationCountDataList.value.push(count);
  411. }).finally(() => {
  412. searchLoading.value = false;
  413. })
  414. }
  415. }
  416. // 按一级行业名称判断所属产业
  417. function setEstateCategoryName(newData: any) {
  418. // 所属产业判断
  419. const categoryMap = {
  420. '农、林、牧、渔业': {name: '第一产业', id: 1},
  421. '采矿业': {name: '第二产业', id: 2},
  422. '制造业': {name: '第二产业', id: 2},
  423. '电力、热力、燃气及水生产和供应业': {name: '第二产业', id: 2},
  424. '建筑业': {name: '第二产业', id: 2}
  425. };
  426. if (newData.parentIndustryName && categoryMap[newData.parentIndustryName]) {
  427. const category = categoryMap[newData.parentIndustryName];
  428. newData.estateCategoryName = category.name;
  429. newData.estateCategoryId = category.id;
  430. } else {
  431. newData.estateCategoryName = '第三产业';
  432. newData.estateCategoryId = 3;
  433. }
  434. }
  435. // 统计小计数据
  436. function calculateCategorySubtotal() {
  437. // 初始化每个类别的计数对象
  438. const categorySubtotal = {
  439. 1: {}, // 第一产业
  440. 2: {}, // 第二产业
  441. 3: {} // 第三产业
  442. };
  443. // 初始化字段值为0
  444. industryWorkSituationCountKeyTemp.value.forEach((key: any) => {
  445. [1, 2, 3].forEach(categoryId => {
  446. categorySubtotal[categoryId][key] = 0;
  447. });
  448. });
  449. // 循环统计数据,进行小计数量的累加
  450. industryWorkSituationCountDataList.value.forEach((count: any) => {
  451. if (categorySubtotal[count.estateCategoryId]) {
  452. Object.keys(categorySubtotal[count.estateCategoryId]).forEach(key => {
  453. categorySubtotal[count.estateCategoryId][key] += count[key];
  454. });
  455. }
  456. });
  457. // 设置文本字段名称
  458. ['estateCategoryName', 'parentIndustryName', 'industryName'].forEach((key: any) => {
  459. [1, 2, 3].forEach(categoryId => {
  460. categorySubtotal[categoryId][key] = '小计';
  461. });
  462. });
  463. // 向表格插入小计数据
  464. [1, 2, 3].forEach(categoryId => {
  465. const lastIndex = industryWorkSituationCountDataList.value.map(item => item.estateCategoryId).lastIndexOf(categoryId);
  466. if (lastIndex !== -1) {
  467. industryWorkSituationCountDataList.value.splice(lastIndex + 1, 0, categorySubtotal[categoryId]);
  468. }
  469. });
  470. }
  471. onMounted(() => {
  472. getCompanyModel();
  473. onFinish();
  474. })
  475. </script>
  476. <style scoped>
  477. </style>