kpi-analysis-form.vue 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398
  1. <template>
  2. <div :class="$style.searchdiv">
  3. <a-card :class="$style.searchWrap">
  4. <a-form-model
  5. ref="advancedSearchForm"
  6. class="ant-advanced-search-form"
  7. :model="form"
  8. :rules="rules"
  9. v-bind="formItemLayout"
  10. >
  11. <a-row :gutter="24" :class="$style.antformitem">
  12. <a-col :span="24" :class="$style.deptCol">
  13. <a-form-model-item label="监测单位" prop="dept">
  14. <sd-group-picker v-model="form.dept" />
  15. </a-form-model-item>
  16. </a-col>
  17. <a-col :span="12">
  18. <a-form-model-item label="时间维度" prop="date">
  19. <a-select v-model="form.date" :options="dateOptions" @change="dateChange"></a-select>
  20. </a-form-model-item>
  21. </a-col>
  22. <a-col :span="12" style="margin-bottom: 5px;">
  23. <a-form-model-item label="指标名称" prop="name">
  24. <a-select
  25. v-model="form.name"
  26. mode="multiple"
  27. :open="false"
  28. @focus="showSelectName"
  29. @change="selectChange"
  30. ></a-select>
  31. </a-form-model-item>
  32. </a-col>
  33. <a-col :span="12">
  34. <a-form-model-item label="日期时间" prop="dateTime">
  35. <a-range-picker
  36. v-model="form.dateTime"
  37. :disabledDate="disabledDate"
  38. @calendarChange="calendarPriceRangeChange"
  39. @change="changePriceRangeDate"
  40. ></a-range-picker>
  41. </a-form-model-item>
  42. </a-col>
  43. </a-row>
  44. <a-row>
  45. <a-col :span="16"> </a-col>
  46. <a-col :class="$style.searchbutton" :span="8">
  47. <div class="reportbuttonContent" style="margin-right:15%">
  48. <a-button @click="handleReset">重置</a-button>
  49. <a-button type="primary" html-type="submit" @click="submitForm">查询</a-button>
  50. <a-button type="primary" @click="exportData">导出</a-button>
  51. <input id="normal" type="text" style="border: none;width: 0;outline: none;" />
  52. </div>
  53. </a-col>
  54. </a-row>
  55. </a-form-model>
  56. </a-card>
  57. <a-card class="sd-has-table">
  58. <div v-show="!flag">
  59. <a-empty />
  60. </div>
  61. <div v-for="(oneData, index) in form.name" :key="oneData">
  62. <div v-show="flag">
  63. <!-- 图标and列表组件 -->
  64. <kpi-analysis-form-echarts
  65. :key="echartsKey"
  66. :title="oneData"
  67. :indi-id="form.nameId[index]"
  68. :params="params"
  69. ></kpi-analysis-form-echarts>
  70. </div>
  71. </div>
  72. </a-card>
  73. <!-- 指标选择器 -->
  74. <kpi-analysis-select-modal
  75. :visible="visible"
  76. :select-expressions="selectExpressions"
  77. @handleCancel="handleCancel"
  78. @handleOk="handleOk"
  79. />
  80. </div>
  81. </template>
  82. <script>
  83. import moment from 'moment'
  84. import { message } from '@/common/one-ui'
  85. import download from '@/common/services/download'
  86. import kpiAnalysisFormEcharts from './kpi-analysis-form-echarts.vue'
  87. import kpiAnalysisSelectModal from './kpi-analysis-select-modal.vue'
  88. import kpiAnalysisFormService from './kpi-analysis-form-service'
  89. import components from './_import-components/kpi-analysis-form-import'
  90. export default {
  91. name: 'KpiAnalysisForm',
  92. metaInfo: {
  93. title: '指标分析',
  94. },
  95. components: {
  96. kpiAnalysisFormEcharts,
  97. kpiAnalysisSelectModal,
  98. ...components,
  99. },
  100. data() {
  101. return {
  102. params: {},
  103. echartsKey: 0,
  104. flag: false,
  105. isCancel: false,
  106. selectExpressions: [],
  107. visible: false,
  108. dateOptions: [], // 时间维度字典
  109. form: {
  110. dept: [],
  111. date: null,
  112. name: [],
  113. nameId: [],
  114. dateTime: [],
  115. },
  116. rules: {
  117. dept: [{ required: true, message: '请选择监测单位', trigger: 'change' }],
  118. date: [{ required: true, message: '请选择时间维度', trigger: 'change' }],
  119. name: [{ required: true, message: '请选择指标名称', trigger: 'change' }],
  120. dateTime: [
  121. {
  122. required: true,
  123. message: '请选择时间范围',
  124. trigger: 'change',
  125. validator: this.checkDateTime,
  126. },
  127. ],
  128. },
  129. formItemLayout: {
  130. labelCol: { span: 6 },
  131. wrapperCol: { span: 14 },
  132. },
  133. selectPriceDate: '',
  134. }
  135. },
  136. created() {
  137. // 获取指标时间范围
  138. kpiAnalysisFormService.getDictValue('KPI_FREQUENCY').then((res) => {
  139. this.dateOptions = res.data.map((item) => {
  140. return {
  141. label: item.name,
  142. value: item.id,
  143. }
  144. })
  145. })
  146. },
  147. methods: {
  148. changePriceRangeDate() {
  149. this.selectPriceDate = ''
  150. },
  151. calendarPriceRangeChange(date) {
  152. this.selectPriceDate = date[0]
  153. },
  154. disabledDate(current) {
  155. if (this.selectPriceDate) {
  156. const selectV = moment(this.selectPriceDate, 'YYYY-MM-DD').valueOf()
  157. const disabled = current.year() !== new Date(selectV).getFullYear()
  158. return disabled
  159. } else {
  160. return false
  161. }
  162. },
  163. checkDateTime(rule, value, callback) {
  164. if (value.length === 0) return false
  165. if (this.form.date === '1') {
  166. // 日
  167. const days = moment(value[1]).diff(moment(value[0]), 'days')
  168. if (days > 30) {
  169. rule.message = '时间维度为日时,日期范围不能超过30天'
  170. return false
  171. }
  172. } else if (this.form.date === '2') {
  173. // 周
  174. const weeks = moment(value[1]).diff(moment(value[0]), 'weeks')
  175. if (weeks > 30) {
  176. rule.message = '时间维度为周时,日期范围不能超过30周'
  177. return false
  178. }
  179. }
  180. return true
  181. },
  182. // 日期范围变更时
  183. dateChange(val) {
  184. this.form.name = []
  185. this.form.nameId = []
  186. this.selectExpressions = [
  187. {
  188. dataType: 'str',
  189. name: 'indiFrequency',
  190. op: 'eq',
  191. stringValue: val,
  192. },
  193. {
  194. dataType: 'str',
  195. name: 'indiStatus',
  196. op: 'eq',
  197. stringValue: '1',
  198. },
  199. ]
  200. },
  201. handleOk(rows) {
  202. this.form.name = []
  203. this.form.nameId = []
  204. rows.forEach((item) => {
  205. this.form.name.push(item.indiName)
  206. this.form.nameId.push(item.id)
  207. })
  208. this.flag = false
  209. this.handleCancel()
  210. },
  211. handleCancel(event) {
  212. this.isCancel = true
  213. this.visible = false
  214. },
  215. selectChange(val) {
  216. const newId = []
  217. val.forEach((item, index) => {
  218. if (this.form.name.includes(item)) {
  219. newId.push(this.form.nameId[index])
  220. }
  221. })
  222. this.form.name = val
  223. this.form.nameId = newId
  224. },
  225. // 显示选择指标名称
  226. showSelectName(e) {
  227. if (!this.form.date) {
  228. message.info('请先选择时间维度', 1)
  229. return
  230. }
  231. if (this.isCancel) {
  232. this.isCancel = false
  233. document.querySelector('#normal').focus()
  234. return
  235. }
  236. this.visible = true
  237. },
  238. submitForm() {
  239. this.params = {
  240. dateStart: moment(this.form.dateTime[0]).format('YYYY-MM-DD'),
  241. dateEnd: moment(this.form.dateTime[1]).format('YYYY-MM-DD'),
  242. unitIds: this.form.dept.map((item) => item.code).join(','),
  243. indiFrequency: this.form.date,
  244. }
  245. this.flag = false
  246. this.$refs.advancedSearchForm.validate((valid, values) => {
  247. if (valid) {
  248. this.echartsKey++
  249. this.flag = true
  250. }
  251. })
  252. },
  253. handleReset() {
  254. this.$refs.advancedSearchForm.resetFields()
  255. this.flag = false
  256. },
  257. // 导出接口
  258. exportData() {
  259. // if (this.$refs.dataTable.data.length === 0) {
  260. // message.warning('未查询出可导出数据', 1)
  261. // return
  262. // }
  263. this.$refs.advancedSearchForm.validate((valid, values) => {
  264. if (valid) {
  265. const data = { ...this.params, indiId: this.form.nameId.join(',') }
  266. kpiAnalysisFormService
  267. .exportKpiAssayList(data)
  268. .then((res) => {
  269. const url = URL.createObjectURL(res.data)
  270. download(url, '指标分析导出.xls')
  271. })
  272. .catch(() => {
  273. message.error('导出失败')
  274. })
  275. }
  276. })
  277. },
  278. },
  279. }
  280. </script>
  281. <style module lang="scss">
  282. @use '@/common/design' as *;
  283. .toptitle {
  284. color: #404040;
  285. font-weight: bold;
  286. font-size: 22px;
  287. margin-left: calc(50% - 150px);
  288. }
  289. .search-wrap {
  290. margin-bottom: $padding-lg;
  291. :global(.ant-advanced-search-form) {
  292. padding: 0;
  293. background: transparent;
  294. border: none;
  295. :global(.ant-form-item) {
  296. margin-bottom: 15px;
  297. }
  298. }
  299. :global .ant-divider-horizontal {
  300. margin: 10px 0;
  301. }
  302. }
  303. .searchdiv {
  304. background-color: #f0f2f5;
  305. height: 100%;
  306. :global(.sd-has-table.ant-card) {
  307. min-height: calc(100vh - 350px);
  308. }
  309. :global(.reporttablecardxm) {
  310. :global(.ant-table-body) {
  311. height: calc(100vh - 350px);
  312. overflow: auto;
  313. }
  314. }
  315. :global(.ant-col-6) {
  316. width: 220px;
  317. }
  318. }
  319. .emptyecharts {
  320. width: 600px;
  321. height: 400px;
  322. margin: auto auto;
  323. text-align: center;
  324. &::after {
  325. content: '无数据';
  326. padding-top: 150px;
  327. display: block;
  328. }
  329. }
  330. .echarts {
  331. width: 100%;
  332. height: 400px;
  333. margin: auto auto;
  334. text-align: center;
  335. }
  336. .piespan {
  337. margin-left: -600px;
  338. position: relative;
  339. .cate {
  340. position: absolute;
  341. right: 300px;
  342. top: 30px;
  343. z-index: 5;
  344. // overflow: auto;
  345. // height: 250px;
  346. li {
  347. cursor: pointer;
  348. list-style: none;
  349. font-size: 13px;
  350. line-height: 23px;
  351. color: #919191;
  352. padding-left: 15px;
  353. position: relative;
  354. }
  355. }
  356. }
  357. .pdiv {
  358. height: 14px;
  359. width: 14px;
  360. background: #54c5eb;
  361. border-radius: 11px;
  362. position: absolute;
  363. left: -7px;
  364. top: 5px;
  365. }
  366. .cateli-span {
  367. color: #0162eb;
  368. display: inline-block;
  369. width: 180px;
  370. }
  371. .cateli-point {
  372. display: inline-block;
  373. width: 80px;
  374. }
  375. .backicon {
  376. position: absolute;
  377. top: 3px;
  378. left: 5px;
  379. cursor: pointer;
  380. }
  381. .antformitem {
  382. :global(.ant-select) {
  383. padding: 0;
  384. }
  385. }
  386. .dept-col {
  387. :global(.ant-col-14) {
  388. width: calc(80% + -10px);
  389. }
  390. }
  391. </style>