index.vue 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572
  1. <template>
  2. <view class="page-wrap">
  3. <uni-section :title="curGroupName">
  4. <template v-slot:decoration>
  5. <view class="decoration">
  6. <image class="icon" src="/static/images/admin_icon.png"></image>
  7. </view>
  8. </template>
  9. <view class="tab-container">
  10. <view class="item" @click="linkTo('duty')">
  11. <view class="icon">
  12. <image src="/static/images/duty.png" mode=""></image>
  13. </view>
  14. <view class="name">应急值守</view>
  15. </view>
  16. <view class="item" @click="linkTo('team')">
  17. <view class="icon">
  18. <image src="/static/images/team.png" mode=""></image>
  19. </view>
  20. <view class="name">队伍建设</view>
  21. </view>
  22. <view class="item" @click="linkTo('goods')">
  23. <view class="icon">
  24. <image src="/static/images/goods.png" mode=""></image>
  25. </view>
  26. <view class="name">物资储备</view>
  27. </view>
  28. <view class="item" @click="linkTo('industry')">
  29. <view class="icon">
  30. <image src="/static/images/industry.png" mode=""></image>
  31. </view>
  32. <view class="name">行业管理</view>
  33. </view>
  34. <view class="item" @click="linkTo('danger')">
  35. <view class="icon">
  36. <image src="/static/images/danger.png" mode=""></image>
  37. </view>
  38. <view class="name">隐患管理</view>
  39. </view>
  40. <view class="item" @click="linkTo('disaster')">
  41. <view class="icon">
  42. <image src="/static/images/disaster.png" mode=""></image>
  43. </view>
  44. <view class="name">自然灾害</view>
  45. </view>
  46. <view class="item" @click="linkTo('reporting')">
  47. <view class="icon">
  48. <image src="/static/images/reporting.png" mode=""></image>
  49. </view>
  50. <view class="name">突发事件</view>
  51. </view>
  52. <view class="item" @click="linkTo('camera')">
  53. <view class="icon">
  54. <image src="/static/images/camera.png" mode=""></image>
  55. </view>
  56. <view class="name">现场视频</view>
  57. </view>
  58. </view>
  59. </uni-section>
  60. <div class="duty-conatiner">
  61. <uni-section title="值班情况">
  62. <template v-slot:decoration>
  63. <view class="decoration">
  64. <image class="icon" src="/static/images/duty_icon.png"></image>
  65. </view>
  66. </template>
  67. <template v-slot:right>
  68. <view style="width: 200px;">
  69. <uni-data-select v-model="dutyGroupId" :localdata="groupList" :value="curGroupId" placeholder="请选择部门"
  70. :clear="false" @change="getdutyData"></uni-data-select>
  71. </view>
  72. </template>
  73. <view class="filter-box">
  74. <view class="bt lf" @click="changeDate(-1)">
  75. <uni-icons type="left" color="#777" size="30"></uni-icons>
  76. </view>
  77. <view class="time">{{dutyDate}}</view>
  78. <view class="bt rt" @click="changeDate(1)">
  79. <uni-icons type="right" color="#777" size="30"></uni-icons>
  80. </view>
  81. </view>
  82. <view class="duty-item" v-for="(duty,index) in dutys" :key="duty.accountId">
  83. <view class="avatar">
  84. <image class="icon" src="/static/images/avatar.png" mode=""></image>
  85. </view>
  86. <view class="info">
  87. <view class="top">
  88. <view class="posName">
  89. <text>{{duty.posName}}</text>
  90. </view>
  91. <view class="posbox">
  92. <view class="positionName">
  93. <uni-tag :inverted="true" :text="duty.positionName" type="success" size="small"></uni-tag>
  94. </view>
  95. <view class="groupName">
  96. <uni-tag :inverted="true" :text="duty.groupName" type="primary" size="small"></uni-tag>
  97. </view>
  98. </view>
  99. </view>
  100. <view class="bottom">
  101. <view class="user">
  102. <div class="userinfo">
  103. <image class="icon" src="/static/images/user.png"></image>
  104. <view class="name">{{duty.accountName}}</view>
  105. </div>
  106. </view>
  107. <view class="phone" @click="callPhone(duty.accountPhone)">
  108. <image class="icon" src="/static/images/phone.png"></image>
  109. <view class="phoneNumber">{{duty.accountPhone||'未填写'}}</view>
  110. </view>
  111. </view>
  112. </view>
  113. </view>
  114. <view class="isEmpty" v-if="dutys.length<1">
  115. 暂无数据
  116. </view>
  117. </uni-section>
  118. </div>
  119. <div class="item-conatiner">
  120. <uni-section title="统计分析">
  121. <template v-slot:decoration>
  122. <view class="decoration">
  123. <image class="icon" src="/static/images/statistics_icon.png"></image>
  124. </view>
  125. </template>
  126. <view class="statisticsTabs">
  127. <uni-segmented-control :current="statisticsIdx" :values="statisticsTabs" style-type="text"
  128. active-color="#007aff" @clickItem="changeStatics" />
  129. </view>
  130. <view class="statisticscont">
  131. <uni-table border stripe emptyText="暂无更多数据">
  132. <uni-tr>
  133. <uni-th align="center" width='50'>序号</uni-th>
  134. <uni-th align="center">{{statisticsData.name}}</uni-th>
  135. <uni-th align="center">{{statisticsData.unit}}</uni-th>
  136. </uni-tr>
  137. <uni-tr v-for="(item,idx) in statisticsData.items" :key="idx">
  138. <uni-td align="center">{{idx+1}}</uni-td>
  139. <uni-td align="center">{{item.name}}</uni-td>
  140. <uni-td align="center">{{item.num}}</uni-td>
  141. </uni-tr>
  142. </uni-table>
  143. </view>
  144. <uni-card margin='10px 0' padding='0'>
  145. <StatisticsChart :data='chartdata'></StatisticsChart>
  146. </uni-card>
  147. </uni-section>
  148. </div>
  149. </view>
  150. </template>
  151. <script>
  152. import StatisticsChart from '@/components/IndexBarChart.vue'
  153. import Echart from '@/components/Echart.vue'
  154. import dutyApi from '@/api/duty.js'
  155. import teamApi from '@/api/team.js'
  156. import goodsApi from '@/api/goods.js'
  157. import industryApi from '@/api/industry.js'
  158. import dangerApi from '@/api/danger.js'
  159. import reportingApi from '@/api/reporting.js'
  160. import {
  161. parseTime
  162. } from '@/libs/index.js'
  163. import {
  164. selectGroupUser,
  165. getGroupView
  166. } from '@/api/system.js'
  167. export default {
  168. components: {
  169. StatisticsChart
  170. },
  171. computed: {
  172. groupList() {
  173. let groupView = this.groupView;
  174. if (groupView && groupView.length > 0) {
  175. let groupList = []
  176. groupView.map((item, index) => {
  177. groupList.push({
  178. ...item,
  179. value: item.groupId,
  180. text: item.groupName
  181. })
  182. if (Array.isArray(item.children) && item.children.length > 0) {
  183. groupList = groupList.concat(item.children.map(item => {
  184. return {
  185. ...item,
  186. value: item.groupId,
  187. text: item.groupName
  188. }
  189. }))
  190. }
  191. })
  192. this.dutyGroupId = this.curGroupId
  193. return groupList
  194. } else {
  195. return []
  196. }
  197. }
  198. },
  199. data() {
  200. return {
  201. curGroupId: null,
  202. curGroupName: "",
  203. dutys: [],
  204. groupView: [],
  205. statisticsIdx: 0,
  206. dutyDate: parseTime(new Date(), '{y}-{m}-{d}'),
  207. dutyGroupId: undefined,
  208. statisticsTabs: ['队伍建设', '物资储备', '行业管理', '隐患管理', '突发事件'],
  209. statisticsData: {
  210. name: "救援队",
  211. unit: "人数",
  212. items: []
  213. },
  214. chartdata: {
  215. yData: [],
  216. xData: []
  217. }
  218. }
  219. },
  220. onShow() {
  221. this.init()
  222. },
  223. methods: {
  224. init() {
  225. let userData = uni.getStorageSync('accountInfo')
  226. this.curGroupId = userData.groupId
  227. this.curGroupName = userData.groupName
  228. this.getdutyData();
  229. this.getStatisticsData()
  230. this.getBaseData()
  231. },
  232. changeDate(step) {
  233. let date = new Date(this.dutyDate)
  234. date.setDate(date.getDate() + step)
  235. this.dutyDate = parseTime(date, '{y}-{m}-{d}')
  236. this.getdutyData()
  237. },
  238. getdutyData() {
  239. dutyApi.getRecordByList({
  240. dutyDate: this.dutyDate,
  241. groupId: this.dutyGroupId
  242. }).then((res) => {
  243. this.dutys = res.data
  244. })
  245. },
  246. getBaseData() {
  247. //dutyApi.getByList().then((res) => {
  248. // uni.setStorageSync("dutys", res.data)
  249. //})
  250. selectGroupUser().then((res) => {
  251. uni.setStorageSync("groupUser", res.data)
  252. })
  253. getGroupView().then((res) => {
  254. uni.setStorageSync("groupView", res.data)
  255. this.groupView = res.data
  256. })
  257. },
  258. getStatisticsData() {
  259. if (this.statisticsIdx === 0) {
  260. teamApi.counterByMember().then((res) => {
  261. let data = res.data;
  262. this.statisticsData.items = data.map(item => {
  263. return {
  264. name: item.teamName,
  265. num: item.count
  266. }
  267. });
  268. })
  269. teamApi.counterByCat().then((res) => {
  270. let data = res.data;
  271. this.chartdata = {
  272. yData: data.map(item => item.count),
  273. xData: data.map(item => item.teamCatTitle),
  274. name: "队伍建设"
  275. }
  276. })
  277. }
  278. if (this.statisticsIdx === 1) {
  279. goodsApi.totalByCat().then((res) => {
  280. let data = res.data;
  281. this.statisticsData.items = data.map(item => {
  282. return {
  283. name: item.goodsCatTitle,
  284. num: item.total
  285. }
  286. });
  287. this.chartdata = {
  288. yData: data.map(item => item.total),
  289. xData: data.map(item => item.goodsCatTitle),
  290. name: "数量"
  291. }
  292. })
  293. }
  294. if (this.statisticsIdx === 2) {
  295. industryApi.counterByGroup().then((res) => {
  296. let data = res.data;
  297. this.statisticsData.items = data.map(item => {
  298. return {
  299. name: item.groupName,
  300. num: item.count
  301. }
  302. });
  303. })
  304. industryApi.counterByCat().then((res) => {
  305. let data = res.data;
  306. this.chartdata = {
  307. yData: data.map(item => item.count),
  308. xData: data.map(item => item.entCatTitle),
  309. name: "企业/单位数目"
  310. }
  311. })
  312. }
  313. if (this.statisticsIdx === 3) {
  314. dangerApi.counterByGroup().then((res) => {
  315. let data = res.data;
  316. this.statisticsData.items = data.map(item => {
  317. return {
  318. name: item.groupName,
  319. num: item.count
  320. }
  321. });
  322. })
  323. dangerApi.counterByCat().then((res) => {
  324. let data = res.data;
  325. this.chartdata = {
  326. yData: data.map(item => item.count),
  327. xData: data.map(item => item.dangerCatTitle),
  328. name: "隐患数目"
  329. }
  330. })
  331. }
  332. if (this.statisticsIdx === 4) {
  333. reportingApi.counterByType().then((res) => {
  334. let data = res.data;
  335. this.statisticsData.items = data.map(item => {
  336. return {
  337. name: item.reportingTypeTitle,
  338. num: item.count
  339. }
  340. });
  341. this.chartdata = {
  342. yData: data.map(item => item.count),
  343. xData: data.map(item => item.reportingTypeTitle),
  344. name: "突发事件"
  345. }
  346. })
  347. }
  348. },
  349. linkTo(type) {
  350. uni.navigateTo({
  351. url: `/packageA/pages/${type}/index`
  352. })
  353. },
  354. changeStatics({
  355. currentIndex
  356. }) {
  357. if (this.statisticsIdx !== currentIndex) {
  358. this.statisticsIdx = currentIndex
  359. let ths = [{
  360. name: "救援队",
  361. unit: "人数"
  362. }, {
  363. name: "物资分类",
  364. unit: "数量"
  365. }, {
  366. name: "监管单位",
  367. unit: "企业/单位数目"
  368. }, {
  369. name: "监管单位",
  370. unit: "隐患数目"
  371. }, {
  372. name: "突发事件",
  373. unit: "数目"
  374. }]
  375. this.statisticsData = {
  376. name: ths[currentIndex].name,
  377. unit: ths[currentIndex].unit,
  378. items: []
  379. },
  380. this.getStatisticsData()
  381. }
  382. },
  383. callPhone(phoneNumber) {
  384. if (!phoneNumber) return
  385. wx.makePhoneCall({
  386. phoneNumber
  387. })
  388. }
  389. }
  390. }
  391. </script>
  392. <style lang="scss" scoped>
  393. .page-wrap {
  394. padding: 20rpx;
  395. background-color: #f5f5f5;
  396. .decoration {
  397. padding-right: 6rpx;
  398. image {
  399. display: block;
  400. width: 30rpx;
  401. height: 30rpx;
  402. }
  403. }
  404. .tab-container {
  405. background: #fff;
  406. display: flex;
  407. justify-content: space-between;
  408. align-items: center;
  409. flex-wrap: wrap;
  410. padding-bottom: 20rpx;
  411. .item {
  412. width: 25%;
  413. display: flex;
  414. justify-content: space-between;
  415. align-items: center;
  416. flex-direction: column;
  417. padding: 0 10rpx 20rpx;
  418. box-sizing: border-box;
  419. .icon {
  420. width: 80rpx;
  421. height: 80rpx;
  422. image {
  423. display: block;
  424. width: 80rpx;
  425. height: 80rpx;
  426. }
  427. }
  428. .name {
  429. padding-top: 16rpx;
  430. line-height: 1;
  431. font-size: 28rpx;
  432. color: #222222;
  433. text-align: center;
  434. }
  435. }
  436. }
  437. .duty-conatiner {
  438. margin-top: 40rpx;
  439. padding-bottom: 10rpx;
  440. background-color: #fff;
  441. .filter-box {
  442. display: flex;
  443. justify-content: center;
  444. align-items: center;
  445. padding-bottom: 20rpx;
  446. .time {
  447. padding: 16rpx 20rpx;
  448. width: 260rpx;
  449. border: 1px solid #ddd;
  450. text-align: center;
  451. border-radius: 6px;
  452. margin: 0 40rpx;
  453. font-size: 32rpx;
  454. line-height: 1;
  455. color: #424242;
  456. font-weight: 600;
  457. box-shadow: 0 0 4px rgba(0, 0, 0, 0.2);
  458. }
  459. }
  460. .isEmpty {
  461. text-align: center;
  462. font-size: 36rpx;
  463. line-height: 1;
  464. padding: 36rpx;
  465. color: #999999;
  466. background-color: #f8f8f8;
  467. }
  468. .duty-item {
  469. display: flex;
  470. justify-content: space-between;
  471. align-items: center;
  472. position: relative;
  473. box-shadow: 0px 0px 3px 1px rgba(0, 0, 0, 0.08);
  474. padding: 20rpx 14rpx;
  475. margin: 20rpx;
  476. .icon,
  477. .icon image {
  478. display: block;
  479. width: 30rpx;
  480. height: 30rpx;
  481. flex-shrink: 0;
  482. }
  483. .avatar {
  484. image {
  485. width: 60rpx;
  486. height: 60rpx;
  487. }
  488. }
  489. .posbox {
  490. // display: flex;
  491. // align-items: center;
  492. // justify-content: space-between;
  493. padding: 20rpx 0;
  494. // .groupName,.positionName{
  495. // width: 45%;
  496. // overflow: hidden;
  497. // text-overflow: ellipsis;
  498. // &.positionName{
  499. // display: flex;
  500. // align-items: center;
  501. // justify-content: flex-end;
  502. // }
  503. // }
  504. .groupName {
  505. margin-top: 16rpx;
  506. }
  507. }
  508. .info {
  509. flex: 1;
  510. padding: 0 14rpx;
  511. .user,
  512. .phone {
  513. display: flex;
  514. align-items: center;
  515. .name,
  516. .phoneNumber {
  517. color: #999;
  518. font-size: 12px;
  519. font-weight: normal;
  520. // overflow: hidden;
  521. line-height: 1;
  522. }
  523. }
  524. .user {
  525. padding: 10rpx 0;
  526. .userinfo {
  527. display: flex;
  528. align-items: center;
  529. }
  530. }
  531. .bottom {
  532. display: flex;
  533. justify-content: space-between;
  534. align-items: center;
  535. }
  536. }
  537. }
  538. }
  539. .statisticsTabs {
  540. padding: 0 16rpx 40rpx 16rpx;
  541. }
  542. .statisticscont {
  543. padding: 0 16rpx;
  544. }
  545. }
  546. </style>