YearSystemApplyCount.vue 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417
  1. <template>
  2. <div class="card-search">
  3. <!-- 查询表单 -->
  4. <a-form
  5. ref="formRef"
  6. name="advanced_search"
  7. class="ant-advanced-search-form"
  8. :model="searchParams"
  9. >
  10. <a-row :gutter="24">
  11. <a-col :span="6">
  12. <a-form-item label="查询年份" :label-col="{span:6}" name="reportDate">
  13. <a-date-picker format="YYYY" picker="year" v-model:value="pickerDate" :allow-clear="false"
  14. @change="pickerDateChange"/>
  15. </a-form-item>
  16. </a-col>
  17. <a-col :span="6">
  18. <a-form-item label="运营机构" :label-col="{span:6}" name="institutionID">
  19. <a-select
  20. ref="select"
  21. v-model:value="searchParams.institutionID"
  22. :options="allInstitutions"
  23. :field-names="{ label: 'text', value: 'value' }"
  24. :allow-clear="true"
  25. @change="loadData"
  26. >
  27. </a-select>
  28. </a-form-item>
  29. </a-col>
  30. <a-col :span="6">
  31. <a-form-item label="县区" :label-col="{span:6}" name="regionCode">
  32. <a-select
  33. ref="select"
  34. v-model:value="searchParams.regionCode"
  35. :options="regionList"
  36. :field-names="{ label: 'name', value: 'code' }"
  37. :allow-clear="true"
  38. @change="loadData"
  39. >
  40. </a-select>
  41. </a-form-item>
  42. </a-col>
  43. <a-col :span="6" style="text-align: left">
  44. <a-button type="primary" html-type="submit" @click="loadData" :loading="tableLoading">查询</a-button>
  45. <a-button style="margin: 0 8px" @click="onReset">重置</a-button>
  46. <a style="font-size: 12px" @click="expand = !expand">
  47. <template v-if="expand">
  48. <UpOutlined/>
  49. </template>
  50. <template v-else>
  51. <DownOutlined/>
  52. </template>
  53. {{ expand ? '收缩' : '展开' }}
  54. </a>
  55. </a-col>
  56. </a-row>
  57. <a-row :gutter="24" v-show="expand">
  58. <a-col :span="6">
  59. <a-form-item label="驿站" :label-col="{span:6}" name="siteID">
  60. <a-select
  61. ref="select"
  62. v-model:value="searchParams.siteID"
  63. :options="allSites"
  64. @change="loadData"
  65. :field-names="{ label: 'siteName', value: 'siteID' }"
  66. :allow-clear="true"
  67. >
  68. </a-select>
  69. </a-form-item>
  70. </a-col>
  71. </a-row>
  72. </a-form>
  73. <!-- 操作按钮 -->
  74. <a-row class="edit-operation" style="margin-bottom: 20px">
  75. <a-col :span="24" class="flex-space-between">
  76. <div>
  77. <a-radio-group v-model:value="dataType" button-style="solid" @change="dataTypeChange">
  78. <a-radio-button value="table">表格</a-radio-button>
  79. <a-radio-button value="imageTable">图表</a-radio-button>
  80. </a-radio-group>
  81. </div>
  82. <div>
  83. <BExportExcel :filename="searchParams.year + '系统使用情况统计'"
  84. :params="{...exportSearchParams}"
  85. :title="'导出'"
  86. :url="'statistics/export/yearSystemApplyCount'"></BExportExcel>
  87. </div>
  88. </a-col>
  89. </a-row>
  90. <!-- 数据展示 -->
  91. <div v-show="dataType == 'table'">
  92. <a-table :columns="originalColumns" :data-source="systemApplyCount" :scroll="{ x:'1300' }"
  93. :loading="tableLoading"
  94. :pagination="false"
  95. bordered>
  96. </a-table>
  97. </div>
  98. <div v-show="dataType == 'imageTable'" class="image-table-box">
  99. <div id="companyImageTable" class="echarts-main"></div>
  100. <div id="postImageTable" class="echarts-main"></div>
  101. <div id="jobUserImageTable" class="echarts-main"></div>
  102. <div id="yearCountImageTable" class="echarts-main"></div>
  103. </div>
  104. </div>
  105. </template>
  106. <script setup lang="ts">
  107. import {computed, onMounted, reactive, ref} from "vue";
  108. import {getMonthSystemDataCount, getYearSystemDataCount} from "@/api/statistics";
  109. import dayjs from "dayjs";
  110. import BExportExcel from "@/components/basic/excel/exportExcel/exportExcel.vue";
  111. import {initBarImageTable, initLineImageTable} from "@/utils/echartsUtil";
  112. import {getInstitutionDataList} from "@/api/baseSettings/institution";
  113. import {getRegionCodeList} from "@/api/system/area/index";
  114. import type {SelectProps} from "ant-design-vue";
  115. import {DownOutlined, UpOutlined} from "@ant-design/icons-vue";
  116. import {getSiteList} from "@/api/baseSettings/siteInfo";
  117. const expand = ref(false);
  118. // 查询条件
  119. const searchParams = reactive({
  120. year: "",
  121. institutionID: "",
  122. regionCode: "",
  123. siteID: ""
  124. })
  125. // 导出Excel查询参数
  126. const exportSearchParams = computed(() => {
  127. return JSON.parse(JSON.stringify(searchParams));
  128. })
  129. const pickerDate = ref<any>(dayjs());
  130. // 表格加载
  131. const tableLoading = ref(false);
  132. // 展示类型切换
  133. const dataType = ref("table");
  134. // 统计数据
  135. const systemApplyCount = ref<Array<any>>([]);
  136. // 表格定义
  137. const originalColumns = ref<Array<any>>([
  138. {
  139. title: '项目', dataIndex: 'regionName', key: 'regionName', align: "center", width: 200, fixed: 'left'
  140. },
  141. {
  142. title: '汇总',
  143. children: [
  144. {title: '驿站人员数量', dataIndex: 'siteUserCount', key: 'siteUserCount', width: 120, align: "center"},
  145. {title: '录入企业数量', dataIndex: 'companyCount', key: 'companyCount', width: 120, align: "center"},
  146. {title: '收集岗位数量', dataIndex: 'postCount', key: 'postCount', width: 120, align: "center"},
  147. {title: '登记求职人数', dataIndex: 'jobUserCount', key: 'jobUserCount', width: 120, align: "center"},
  148. ]
  149. },
  150. {
  151. title: '1月',
  152. children: [
  153. {title: '录入企业数量', dataIndex: 'companyCount', key: 'companyCount', width: 120, align: "center"},
  154. {title: '收集岗位数量', dataIndex: 'postCount', key: 'postCount', width: 120, align: "center"},
  155. {title: '登记求职人数', dataIndex: 'jobUserCount', key: 'jobUserCount', width: 120, align: "center"},
  156. ]
  157. }
  158. ])
  159. // 查询方法未处理的初始数据
  160. const searchOriginalList = ref();
  161. // 运营机构
  162. const allInstitutions = ref<any>([]);
  163. // 所属区县
  164. const regionList = ref<SelectProps['options']>();
  165. // 驿站
  166. const allSites = ref<any>([]);
  167. // 数据加载
  168. function loadData() {
  169. tableLoading.value = true;
  170. getYearSystemDataCount(searchParams).then((result: any) => {
  171. searchOriginalList.value = result;
  172. if (dataType.value == 'table') {
  173. analysisByTable();
  174. }
  175. if (dataType.value == 'imageTable') {
  176. analysisByImageTable();
  177. }
  178. }).finally(() => {
  179. tableLoading.value = false;
  180. })
  181. }
  182. // 解析生成表格内容
  183. function analysisByTable() {
  184. let arr = new Array<any>();
  185. // 获取到区县名称信息
  186. if (searchOriginalList.value && Object.keys(searchOriginalList.value).length > 0) {
  187. // 获取到查询结果Map中的第一个键值对,解析获取到县区信息,填充进初始数组中
  188. searchOriginalList.value[Object.keys(searchOriginalList.value)[0]].forEach((item: any) => {
  189. arr.push({
  190. regionCode: item.regionCode,
  191. regionName: item.regionName
  192. });
  193. });
  194. }
  195. // 初始化表结构
  196. originalColumns.value = [{
  197. title: '项目', dataIndex: 'regionName', key: 'regionName', align: "center", width: 200, fixed: 'left'
  198. }]
  199. // 解析汇总数据
  200. initTableData(searchOriginalList.value, '汇总', arr, 'hz', true);
  201. // 解析第一周到第五周的统计数据
  202. for (let i = 1; i <= 12; i++) {
  203. // 填充数据
  204. initTableData(searchOriginalList.value, i + '月', arr, i + 'z', false);
  205. }
  206. systemApplyCount.value = arr;
  207. }
  208. function analysisByImageTable() {
  209. let regionNameList = new Array<any>();
  210. let yearNameList = new Array<any>();
  211. // 获取到区县名称信息
  212. if (searchOriginalList.value && Object.keys(searchOriginalList.value).length > 0) {
  213. // 获取到查询结果Map中的第一个键值对,解析获取到县区信息,填充进初始数组中
  214. searchOriginalList.value[Object.keys(searchOriginalList.value)[0]].forEach((item: any) => {
  215. if (item.regionCode != 100) {
  216. regionNameList.push(item.regionName);
  217. }
  218. });
  219. }
  220. // 初始化折线图数据
  221. let yearLineData = [
  222. {
  223. name: '驿站人员数量',
  224. type: 'line',
  225. data: new Array<any>()
  226. },
  227. {
  228. name: '录入企业数量',
  229. type: 'line',
  230. data: new Array<any>()
  231. },
  232. {
  233. name: '收集岗位数量',
  234. type: 'line',
  235. data: new Array<any>()
  236. },
  237. {
  238. name: '登记求职人数',
  239. type: 'line',
  240. data: new Array<any>()
  241. },
  242. ]
  243. // 解析1到12月的统计数据
  244. for (let i = 1; i <= 12; i++) {
  245. if (searchOriginalList.value[i + '月']) {
  246. yearNameList.push(i + '月');
  247. // 查询获取到每周的合计总数,填充进折线图数据中
  248. const hjData = searchOriginalList.value[i + '月'].find(item => item.regionCode == '100');
  249. if (hjData) {
  250. yearLineData[0].data.push(hjData.siteUserCount);
  251. yearLineData[1].data.push(hjData.companyCount);
  252. yearLineData[2].data.push(hjData.postCount);
  253. yearLineData[3].data.push(hjData.jobUserCount);
  254. }
  255. }
  256. }
  257. // 收集图表数据
  258. let companyImageTableData = new Array<any>();
  259. let postImageTableData = new Array<any>();
  260. let jobUserImageTableData = new Array<any>();
  261. searchOriginalList.value['汇总'].forEach((item: any) => {
  262. if (item.regionCode != 100) {
  263. companyImageTableData.push(item.companyCount)
  264. postImageTableData.push(item.postCount)
  265. jobUserImageTableData.push(item.jobUserCount)
  266. }
  267. })
  268. // 初始化图表
  269. initBarImageTable(regionNameList, companyImageTableData, [], "companyImageTable", '录入企业数量');
  270. initBarImageTable(regionNameList, postImageTableData, [], "postImageTable", "收集岗位数量");
  271. initBarImageTable(regionNameList, jobUserImageTableData, [], "jobUserImageTable", "登记求职人数");
  272. initLineImageTable(yearNameList, yearLineData, ["驿站人员数量", "录入企业数量", "收集岗位数量", "登记求职人数"], "yearCountImageTable", "全市就业驿站运行概括");
  273. }
  274. // 查询重置
  275. function onReset() {
  276. searchParams.year = dayjs().format("YYYY");
  277. pickerDate.value = dayjs();
  278. searchParams.regionCode = ''
  279. searchParams.institutionID = ''
  280. searchParams.siteID = ''
  281. loadData()
  282. }
  283. // 日期变更事件
  284. function pickerDateChange(date: any, dateStr: string) {
  285. console.log(date);
  286. searchParams.year = dateStr;
  287. loadData();
  288. }
  289. // 表格数据与结构定义初始化
  290. function initTableData(result: any, resultKey: any, arr: any, arrNewKey: any, isShowSiteUser: boolean) {
  291. if (!result[resultKey]) {
  292. return;
  293. }
  294. // 填充数据
  295. result[resultKey].forEach((item: any) => {
  296. let arrItem = arr.find((arrElement: any) => arrElement.regionCode === item.regionCode);
  297. if (arrItem) {
  298. // 将item的其他字段重命名,然后将其赋值给arr中对应的元素
  299. Object.keys(item).forEach(key => {
  300. if (key !== 'regionCode' && key !== 'regionName') {
  301. arrItem[key + arrNewKey] = item[key];
  302. }
  303. });
  304. }
  305. })
  306. let table = {
  307. title: resultKey,
  308. children: [
  309. {
  310. title: '录入企业数量',
  311. dataIndex: 'companyCount' + arrNewKey,
  312. key: 'companyCount' + arrNewKey,
  313. width: 120,
  314. align: "center"
  315. },
  316. {
  317. title: '收集岗位数量',
  318. dataIndex: 'postCount' + arrNewKey,
  319. key: 'postCount' + arrNewKey,
  320. width: 120,
  321. align: "center"
  322. },
  323. {
  324. title: '登记求职人数',
  325. dataIndex: 'jobUserCount' + arrNewKey,
  326. key: 'jobUserCount' + arrNewKey,
  327. width: 120,
  328. align: "center"
  329. },
  330. ]
  331. }
  332. // 按要求进行展示驿站人员数量
  333. if (isShowSiteUser) {
  334. table.children.unshift({
  335. title: '驿站人员数量',
  336. dataIndex: 'siteUserCount' + arrNewKey,
  337. key: 'siteUserCount' + arrNewKey,
  338. width: 120,
  339. align: "center"
  340. },)
  341. }
  342. // 填充表结构
  343. originalColumns.value.push(table)
  344. }
  345. function dataTypeChange() {
  346. if (dataType.value == 'table') {
  347. analysisByTable();
  348. }
  349. if (dataType.value == 'imageTable') {
  350. setTimeout(() => {
  351. analysisByImageTable();
  352. }, 100);
  353. }
  354. }
  355. const getAllInstitutions = async function () {
  356. allInstitutions.value = await getInstitutionDataList();
  357. }
  358. const getRegionList = async function () {
  359. regionList.value = await getRegionCodeList();
  360. }
  361. const getAllSites = () => {
  362. getSiteList({
  363. pageIndex: 1,
  364. pageSize: 9999
  365. }).then((result: any) => {
  366. allSites.value = result.list;
  367. })
  368. }
  369. onMounted(() => {
  370. searchParams.year = dayjs().format("YYYY");
  371. loadData();
  372. getAllInstitutions();
  373. getRegionList();
  374. getAllSites();
  375. })
  376. </script>
  377. <script lang="ts">
  378. // 设置页面名称进行组件缓存
  379. export default {
  380. name: "YearSystemApplyDataCount",
  381. }
  382. </script>
  383. <style lang="less" scoped>
  384. .image-table-box {
  385. width: 100%;
  386. height: 100%;
  387. display: grid;
  388. grid-template-columns: repeat(2, minmax(0, 1fr));
  389. gap: 10px;
  390. .echarts-main {
  391. height: 280px;
  392. }
  393. }
  394. </style>