index.vue 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347
  1. <template>
  2. <div class="blocking-data-screen">
  3. <div class="screen-header">
  4. <div class="header-title">盛世鹰眸质控系统【查堵】(安检站)</div>
  5. </div>
  6. <div class="filter-section">
  7. <div class="filter-row">
  8. <div class="filter-item">
  9. <span class="filter-label">日期:</span>
  10. <el-date-picker v-model="filterParams.dateRange" type="daterange" range-separator="-" start-placeholder="开始日期"
  11. end-placeholder="结束日期" value-format="YYYY-MM-DD HH:mm:ss" :default-time="defaultTime"
  12. style="width: 280px" />
  13. </div>
  14. <div class="filter-item">
  15. <span class="filter-label">分管主管:</span>
  16. <el-select v-model="filterParams.supervisorId" placeholder="请选择主管" filterable clearable style="width: 200px">
  17. <el-option v-for="item in supervisorOptions" :key="item.value" :label="item.label" :value="item.value" />
  18. </el-select>
  19. </div>
  20. <div class="filter-item">
  21. <span class="filter-label">分管班组长:</span>
  22. <el-select v-model="filterParams.teamLeaderId" placeholder="请选择班组长" filterable clearable style="width: 200px">
  23. <el-option v-for="item in teamLeaderOptions" :key="item.value" :label="item.label" :value="item.value" />
  24. </el-select>
  25. </div>
  26. <div class="filter-item">
  27. <span class="filter-label">航站楼:</span>
  28. <el-select v-model="filterParams.terminalId" placeholder="请选择区域" clearable style="width: 200px"
  29. @change="terminalChange">
  30. <el-option v-for="item in terminalOptions" :key="item.value" :label="item.label" :value="item.value" />
  31. </el-select>
  32. </div>
  33. <div class="filter-item">
  34. <span class="filter-label">漏检物品:</span>
  35. <el-tree-select v-model="filterParams.missCheckItem" :data="missedItemOptions"
  36. :props="{ value: 'id', label: 'name', children: 'children', disabled: data => data.children && data.children.length > 0 }"
  37. value-key="id" placeholder="请选择漏检物品" check-strictly style="width: 200px" clearable @change="missCheckItemChange"/>
  38. </div>
  39. <div class="filter-item">
  40. <span class="filter-label">分大队:</span>
  41. <el-select v-model="filterParams.brigadeId" placeholder="请选择大队" clearable style="width: 200px">
  42. <el-option v-for="item in brigadeOptions" :key="item.value" :label="item.label" :value="item.value" />
  43. </el-select>
  44. </div>
  45. <!-- <div class="filter-actions">
  46. <el-button type="primary" @click="handleFilter">查询</el-button>
  47. <el-button @click="resetFilter">重置</el-button>
  48. </div> -->
  49. </div>
  50. </div>
  51. <div class="screen-content">
  52. <div v-if="filterParams.brigadeId=='all'" class="grid-layout">
  53. <div class="grid-item">
  54. <module-one :filter-params="filterParams" />
  55. </div>
  56. <div class="grid-item">
  57. <module-two :filter-params="filterParams" />
  58. </div>
  59. <div class="grid-item">
  60. <module-three :filter-params="filterParams" />
  61. </div>
  62. <div class="grid-item">
  63. <module-four :filter-params="filterParams" />
  64. </div>
  65. </div>
  66. <div v-else class="grid-layout">
  67. <div class="grid-item">
  68. <module-brigade-one :filter-params="filterParams" />
  69. </div>
  70. <div class="grid-item">
  71. <module-brigade-two :filter-params="filterParams" />
  72. </div>
  73. <div class="grid-item">
  74. <module-brigade-three :filter-params="filterParams" />
  75. </div>
  76. </div>
  77. </div>
  78. </div>
  79. </template>
  80. <script setup>
  81. import { ref, reactive, onMounted } from 'vue'
  82. import { listDept } from '@/api/system/dept'
  83. import { selectUserLeaderListByCondition } from '@/api/system/user'
  84. import { listCategory } from '@/api/system/category'
  85. import { listPosition } from '@/api/system/position'
  86. import ModuleOne from './components/ModuleOne.vue'
  87. import ModuleTwo from './components/ModuleTwo.vue'
  88. import ModuleThree from './components/ModuleThree.vue'
  89. import ModuleFour from './components/ModuleFour.vue'
  90. import ModuleBrigadeOne from './components/ModuleBrigadeOne.vue'
  91. import ModuleBrigadeTwo from './components/ModuleBrigadeTwo.vue'
  92. import ModuleBrigadeThree from './components/ModuleBrigadeThree.vue'
  93. // 默认时间设置
  94. const defaultTime = [
  95. new Date(2000, 1, 1, 0, 0, 0),
  96. new Date(2000, 1, 1, 23, 59, 59)
  97. ]
  98. // 筛选参数
  99. const filterParams = reactive({
  100. dateRange: [],
  101. supervisorId: '',
  102. teamLeaderId: '',
  103. terminal: '',
  104. terminalId: '',
  105. missCheckItem: '',
  106. brigadeId: 'all'
  107. })
  108. // 选项数据
  109. const supervisorOptions = ref([])
  110. const teamLeaderOptions = ref([])
  111. const brigadeOptions = ref([])
  112. const missedItemOptions = ref([])
  113. const terminalOptions = ref([])
  114. // 获取漏检物品树状选项
  115. function getMissedItemOptions() {
  116. listCategory().then(response => {
  117. missedItemOptions.value = handleTree(response.data, "id", "parentId")
  118. })
  119. }
  120. const terminalChange = (value) => {
  121. if(!value){
  122. filterParams.terminal = ''
  123. filterParams.terminalId = ''
  124. return;
  125. }
  126. filterParams.terminal = terminalOptions.value.find(item => item.value === value).label
  127. }
  128. const missCheckItemChange = (value) => {
  129. if(!value){
  130. filterParams.missCheckItem = ''
  131. return;
  132. }
  133. }
  134. // 树形数据处理函数
  135. function handleTree(data, id, parentId) {
  136. const result = []
  137. const map = {}
  138. data.forEach(item => {
  139. map[item[id]] = { ...item, children: [] }
  140. })
  141. data.forEach(item => {
  142. const parent = map[item[parentId]]
  143. if (parent) {
  144. parent.children.push(map[item[id]])
  145. } else {
  146. result.push(map[item[id]])
  147. }
  148. })
  149. return result
  150. }
  151. // 获取航站楼选项
  152. function getTerminalOptions() {
  153. listPosition({ positionType: 'TERMINL' }).then(response => {
  154. terminalOptions.value = (response.data || []).map(item => ({
  155. value: item.id,
  156. label: item.name
  157. }))
  158. // 添加"整体"选项到最前面
  159. terminalOptions.value.unshift({ label: '整体', value: 'all' })
  160. })
  161. }
  162. function getTeamLeaderOptions() {
  163. selectUserLeaderListByCondition({ roleKeyList: ['banzuzhang'] }).then(response => {
  164. teamLeaderOptions.value = (response.data || []).map(item => ({
  165. value: item.userId,
  166. label: item.nickName
  167. }))
  168. })
  169. }
  170. // 获取主管选项
  171. function getSupervisorOptions() {
  172. selectUserLeaderListByCondition({ roleKeyList: ['kezhang'] }).then(response => {
  173. supervisorOptions.value = (response.data || []).map(item => ({
  174. value: item.userId,
  175. label: item.nickName
  176. }))
  177. })
  178. }
  179. // 获取大队选项
  180. function getBrigadeOptions() {
  181. listDept({}).then(response => {
  182. const deptList = response.data || []
  183. // 筛选类型为 BRIGADE 的部门,并过滤特定的大队ID
  184. brigadeOptions.value = deptList.filter(item => item.deptType === 'BRIGADE' && [311, 314, 315].includes(item.deptId)).map(item => ({
  185. value: item.deptId,
  186. label: item.deptName
  187. }))
  188. // 添加"全站"选项到最前面
  189. brigadeOptions.value.unshift({ label: '全站', value: 'all' })
  190. })
  191. }
  192. const setDefaultDateRange = () => {
  193. const now = new Date()
  194. const startOfMonth = new Date(now.getFullYear(), now.getMonth(), 1)
  195. const endOfToday = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 23, 59, 59)
  196. // 格式化日期为 YYYY-MM-DD HH:mm:ss 格式
  197. const formatDate = (date) => {
  198. const year = date.getFullYear()
  199. const month = String(date.getMonth() + 1).padStart(2, '0')
  200. const day = String(date.getDate()).padStart(2, '0')
  201. const hours = String(date.getHours()).padStart(2, '0')
  202. const minutes = String(date.getMinutes()).padStart(2, '0')
  203. const seconds = String(date.getSeconds()).padStart(2, '0')
  204. return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`
  205. }
  206. filterParams.dateRange = [formatDate(startOfMonth), formatDate(endOfToday)]
  207. }
  208. // 处理筛选
  209. const handleFilter = () => {
  210. console.log('筛选参数:', filterParams)
  211. // 强制触发响应式更新,确保子组件能监听到变化
  212. filterParams.dateRange = [...filterParams.dateRange]
  213. }
  214. // 重置筛选
  215. const resetFilter = () => {
  216. Object.assign(filterParams, {
  217. dateRange: [],
  218. supervisorId: '',
  219. teamLeaderId: '',
  220. terminal: '',
  221. missCheckItem: '',
  222. terminalId: '',
  223. brigadeId: 'all'
  224. })
  225. setDefaultDateRange()
  226. }
  227. // 组件挂载时设置默认日期和获取用户数据
  228. onMounted(() => {
  229. setDefaultDateRange()
  230. getTeamLeaderOptions()
  231. getSupervisorOptions()
  232. getBrigadeOptions()
  233. getMissedItemOptions()
  234. getTerminalOptions()
  235. })
  236. </script>
  237. <style lang="less" scoped>
  238. .blocking-data-screen {
  239. width: 100%;
  240. height: 100vh;
  241. display: flex;
  242. flex-direction: column;
  243. overflow: hidden;
  244. }
  245. .screen-header {
  246. height: 60px;
  247. display: flex;
  248. align-items: center;
  249. justify-content: space-between;
  250. padding: 0 30px;
  251. // border-bottom: 2px solid rgba(112, 207, 231, 0.5);
  252. }
  253. .header-title {
  254. font-size: 24px;
  255. font-weight: bold;
  256. color: black;
  257. // text-shadow: 0 0 10px rgba(112, 207, 231, 0.5);
  258. }
  259. .filter-section {
  260. // background: #f8f9fa;
  261. padding: 20px 30px;
  262. border-bottom: 1px solid #e8e8e8;
  263. }
  264. .filter-row {
  265. display: flex;
  266. align-items: center;
  267. gap: 20px;
  268. margin-bottom: 15px;
  269. &:last-child {
  270. margin-bottom: 0;
  271. }
  272. }
  273. .filter-item {
  274. display: flex;
  275. align-items: center;
  276. gap: 8px;
  277. }
  278. .filter-label {
  279. font-size: 14px;
  280. color: #606266;
  281. font-weight: 500;
  282. white-space: nowrap;
  283. }
  284. .filter-actions {
  285. display: flex;
  286. align-items: center;
  287. gap: 10px;
  288. margin-left: auto;
  289. }
  290. .screen-content {
  291. flex: 1;
  292. padding: 20px;
  293. overflow: auto;
  294. }
  295. .grid-layout {
  296. display: grid;
  297. grid-template-columns: 1fr;
  298. gap: 20px;
  299. height: 100%;
  300. }
  301. .grid-item {
  302. width: 100%;
  303. }
  304. </style>