index.vue 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597
  1. <script setup>
  2. import {
  3. ref,
  4. reactive
  5. } from "vue";
  6. import {
  7. onLoad,
  8. onReachBottom
  9. } from "@dcloudio/uni-app"
  10. import {
  11. getProjectInfoList,
  12. } from "@/api/work/projectInfo.js";
  13. import {
  14. getYearthroughList,
  15. getYearMonththroughList,
  16. getAreaCountValue,
  17. } from "@/api/work/countAnalysis.js";
  18. import {
  19. addFocus,
  20. cancelFocus
  21. } from "@/api/work/focus.js";
  22. let pageKey = ref(null);
  23. let loading = ref(true);
  24. let moreListFlag = true;
  25. let projectList = ref([]);
  26. let listTotal = ref(0);
  27. let searchInfo = ref({
  28. pageNo: 1,
  29. pageSize: 10,
  30. })
  31. function getList() {
  32. if (searchInfo.value.pageNo == 1) {
  33. loading.value = true
  34. }
  35. getProjectInfoList(searchInfo.value).then(res => {
  36. loading.value = false
  37. projectList.value = projectList.value.concat(res.data.list);
  38. listTotal.value = res.data.total;
  39. if (res.data.total == searchInfo.value.pageNo * searchInfo.value.pageSize - (10 - res.data.list
  40. .length)) moreListFlag = false;
  41. }).catch(() => {
  42. loading.value = false
  43. })
  44. }
  45. // 收藏/取消
  46. function changeFocus(id, status) {
  47. let item = projectList.value.find(item => item.id === id);
  48. if (status) {
  49. cancelFocus({
  50. subId: id
  51. }).then(res => {
  52. if (res.code === 200) {
  53. item.isAttention = 0;
  54. }
  55. }).catch(() => {
  56. uni.showToast({
  57. title: "更改收藏状态失败。",
  58. icon: "none",
  59. duration: 2000
  60. })
  61. })
  62. } else {
  63. addFocus({
  64. subId: id
  65. }).then(res => {
  66. if (res.code === 200) {
  67. item.isAttention = 1;
  68. }
  69. }).catch(() => {
  70. uni.showToast({
  71. title: "更改收藏状态失败。",
  72. icon: "none",
  73. duration: 2000
  74. })
  75. })
  76. }
  77. }
  78. function goToDetail(id, subName) {
  79. uni.navigateTo({
  80. url: `/pages/projectInfo/detail/index?id=${id}&subName=${subName}`
  81. })
  82. }
  83. function goToReport(type, subId, subName) {
  84. uni.navigateTo({
  85. url: `/pages/projectInfo/report/index?type=${type}&subId=${subId}&subName=${subName}`
  86. })
  87. }
  88. function getYearList() {
  89. if (searchInfo.value.pageNo == 1) {
  90. loading.value = true
  91. }
  92. let params = Object.assign({}, searchInfo.value);
  93. if (pageKey.value === 'yearAmt' || pageKey.value === 'ndjh') {
  94. params = Object.assign({
  95. orderType: orderByStatus.value || null
  96. }, searchInfo.value)
  97. }
  98. getYearthroughList(params).then(res => {
  99. loading.value = false
  100. projectList.value = projectList.value.concat(res.data.list);
  101. listTotal.value = res.data.total;
  102. if (res.data.total == searchInfo.value.pageNo * searchInfo.value.pageSize - (10 - res.data.list
  103. .length)) moreListFlag = false;
  104. }).catch(() => {
  105. loading.value = false
  106. })
  107. }
  108. function getMonthList() {
  109. if (searchInfo.value.pageNo == 1) {
  110. loading.value = true
  111. }
  112. let params = Object.assign({}, searchInfo.value)
  113. if (pageKey.value === 'ndjh') {
  114. params = Object.assign({
  115. orderType: orderByStatus.value
  116. }, searchInfo.value)
  117. }
  118. getYearMonththroughList(params).then(res => {
  119. loading.value = false
  120. projectList.value = projectList.value.concat(res.data.list);
  121. listTotal.value = res.data.total;
  122. if (res.data.total == searchInfo.value.pageNo * searchInfo.value.pageSize - (10 - res.data.list
  123. .length)) moreListFlag = false;
  124. }).catch(() => {
  125. loading.value = false
  126. })
  127. }
  128. // 按金额排序
  129. let orderByStatus = ref("")
  130. const changeOrderByStatus = () => {
  131. if (orderByStatus.value === "desc") {
  132. orderByStatus.value = "asc"
  133. } else if (orderByStatus.value === "asc") {
  134. orderByStatus.value = ""
  135. } else {
  136. orderByStatus.value = "desc"
  137. }
  138. if (pageKey.value === 'yearAmt') {
  139. projectList.value = [];
  140. getYearList();
  141. }
  142. if (pageKey.value === 'ndjh') {
  143. projectList.value = [];
  144. getMonthList();
  145. }
  146. }
  147. // 统计数据
  148. let countList = ref([{
  149. title: "年度计划投资(万元)",
  150. key: "sumYearAmt",
  151. value: 0,
  152. color: ""
  153. }, {
  154. title: "全年占比",
  155. key: "yearRt",
  156. value: 0,
  157. color: "",
  158. isRate: true,
  159. }, {
  160. title: "当月完成金额(万元)",
  161. key: "sumMonthAmtSj",
  162. value: 0,
  163. color: "count-special-value"
  164. }, {
  165. title: "当月占比",
  166. key: "monthRt",
  167. value: 0,
  168. color: "count-special-value",
  169. isRate: true,
  170. }]);
  171. const getCountValue = () => {
  172. let params = {
  173. year: searchInfo.value.year,
  174. indusKind: searchInfo.value.indusKind,
  175. subjectId: searchInfo.value.subjectId,
  176. zjly: searchInfo.value.zjly,
  177. }
  178. getAreaCountValue(params).then(res => {
  179. for (let i in countList.value) {
  180. countList.value[i].value = res.data[countList.value[i].key] ?? 0;
  181. }
  182. })
  183. }
  184. let title = ref('')
  185. onLoad(options => {
  186. pageKey.value = options.key;
  187. searchInfo.value = Object.assign(searchInfo.value, options);
  188. if (pageKey.value === "num" || pageKey.value === "totalAmt") getList();
  189. if (pageKey.value === "yearAmt") getYearList();
  190. if (pageKey.value === "compAmt") getMonthList();
  191. if (pageKey.value === "home") {
  192. title.value = `详情(${options?.name})`
  193. getMonthList();
  194. getCountValue();
  195. }
  196. if (options.key === 'mothAmt') {
  197. pageKey.value = options.key
  198. title.value = `详情(${options?.name})`
  199. getYearList();
  200. }
  201. if (options.key === 'year') {
  202. pageKey.value = 'yearAmt'
  203. title.value = `详情(${options?.name})`
  204. getYearList();
  205. }
  206. if (options.key === 'ndjh') {
  207. title.value = `详情(${options?.name})`
  208. getMonthList()
  209. }
  210. })
  211. onReachBottom(() => {
  212. if (!moreListFlag) {
  213. return uni.showToast({
  214. title: "已经到底了。",
  215. icon: "none",
  216. duration: 2000
  217. })
  218. }
  219. searchInfo.value.pageNo++;
  220. if (pageKey.value === "num" || pageKey.value === "totalAmt") getList();
  221. if (["yearAmt", "mothAmt", "home"].includes(pageKey.value)) getYearList();
  222. if (pageKey.value === "compAmt" || pageKey.value === "ndjh") getMonthList();
  223. })
  224. </script>
  225. <template>
  226. <view class="container">
  227. <page-title>{{title || '详情'}}</page-title>
  228. <view class="cards-list" v-if="pageKey === 'num'">
  229. <view class="card" v-for="(item,index) in projectList" :key="index">
  230. <!-- 灯与收藏 -->
  231. <view class="card-item light-item">
  232. <view class="card-name-title card-light">
  233. <view v-if="item.isShow === '1'">
  234. <view v-if="item.status_fgw === '0'" class="card-light-bottom light-green"></view>
  235. <view v-if="item.status_fgw === '1'" class="card-light-bottom light-yellow"></view>
  236. <view v-if="item.status_fgw === '2'" class="card-light-bottom light-red"></view>
  237. </view>
  238. </view>
  239. <view class="card-item-content">
  240. <view class="focus" :class="item.isAttention?'focus-on':''" @click="changeFocus(item.id,item.isAttention)">
  241. </view>
  242. </view>
  243. </view>
  244. <!-- 项目名称 -->
  245. <view class="card-name">
  246. <view class="card-name-title">
  247. <text class="card-name-description">项目名称</text>
  248. </view>
  249. <text class="card-name-text">{{item.subName || "--"}}</text>
  250. </view>
  251. <!-- 总投资(万元) -->
  252. <view class="card-item">
  253. <view class="card-item-name">总投资(万元)</view>
  254. <view class="card-item-content">{{item.amtTotal || "--"}}</view>
  255. </view>
  256. <!-- 申报单位 -->
  257. <view class="card-item">
  258. <view class="card-item-name">申报单位</view>
  259. <view class="card-item-content">{{item.unitName || "--"}}</view>
  260. </view>
  261. <!-- 当前状态 -->
  262. <view class="card-item">
  263. <view class="card-item-name">当前状态</view>
  264. <view class="card-item-content">{{item.status || "--"}}</view>
  265. </view>
  266. <!-- 计划日期 -->
  267. <view class="card-item">
  268. <view class="card-item-name">计划日期</view>
  269. <view class="card-item-content">{{item.beginDate || "--"}}</view>
  270. </view>
  271. <!-- 红灯原因 -->
  272. <view class="card-item" v-if="item.status_fgw === '2'">
  273. <view class="card-item-name">红灯原因</view>
  274. <view class="card-item-content">{{ item.colorReason??"--" }}</view>
  275. </view>
  276. <!-- 黄灯原因 -->
  277. <view class="card-item" v-if="item.status_fgw === '1'">
  278. <view class="card-item-name">黄灯原因</view>
  279. <view class="card-item-content">{{ item.colorReason??"--" }}</view>
  280. </view>
  281. <!-- 项目查看按钮(特殊) -->
  282. <view class="card-item" v-if="item.usersub == 1">
  283. <view class="card-btn fat-btn special-btn" @click="goToDetail(item.id,item.subName)">项目查看</view>
  284. </view>
  285. <!-- 项目查看按钮 -->
  286. <view class="card-item" v-else>
  287. <view class="card-btn fat-btn" @click="goToDetail(item.id,item.subName)">项目查看</view>
  288. </view>
  289. <!-- 周月年报按钮 -->
  290. <view class="card-item bottom-item">
  291. <view class="card-btn thin-btn report-btn" @click="goToReport('weekly',item.id,item.subName)">周报
  292. </view>
  293. <view class="card-btn thin-btn report-btn" @click="goToReport('monthly',item.id,item.subName)">月报
  294. </view>
  295. <view class="card-btn thin-btn report-btn" @click="goToReport('yearly',item.id,item.subName)">年度计划
  296. </view>
  297. </view>
  298. <!-- 编号 -->
  299. <view class="card-value">{{index + 1}} / {{listTotal}}</view>
  300. </view>
  301. <empty-show v-if="projectList.length===0"></empty-show>
  302. </view>
  303. <view class="cards-list" v-if="pageKey === 'totalAmt'">
  304. <view class="card no-padding" v-for="(item,index) in projectList" :key="index">
  305. <card-title :numerator="index+1" :denominator="listTotal"></card-title>
  306. <view class="card-name">
  307. <view class="card-name-title">
  308. <text class="card-name-description">项目名称</text>
  309. </view>
  310. <text class="card-name-text">{{item.subName || "--"}}</text>
  311. </view>
  312. <view class="card-item">
  313. <view class="card-item-name">计划投资金额</view>
  314. <view class="card-item-content">{{item.amtTotal ?? "--"}}</view>
  315. </view>
  316. </view>
  317. <empty-show v-if="projectList.length===0"></empty-show>
  318. </view>
  319. <view class="cards-list" v-if="['yearAmt','mothAmt','home'].includes(pageKey)">
  320. <view class="count-value" v-if="pageKey === 'home'">
  321. <view class="count-item" v-for="(item,index) in countList" :key="index">
  322. <view class="count-item-value" :class="item.color">{{item.value}}{{item.isRate ? "%" : ""}}</view>
  323. <view class="count-item-description">{{item.title}}</view>
  324. </view>
  325. </view>
  326. <view class="order-by" v-if="pageKey === 'yearAmt' || pageKey === 'mothAmt' || pageKey === 'ndjh'">
  327. <view class=" order-by-item">
  328. 金额
  329. <view class="order-by-icon" :class="orderByStatus" @click="changeOrderByStatus()"></view>
  330. </view>
  331. </view>
  332. <view class="card no-padding" v-for="(item,index) in projectList" :key="index">
  333. <card-title :numerator="index+1" :denominator="listTotal"></card-title>
  334. <view class="card-name">
  335. <view class="card-name-title">
  336. <text class="card-name-description">项目名称</text>
  337. </view>
  338. <text class="card-name-text">{{item.subName || "--"}}</text>
  339. </view>
  340. <view class="card-item">
  341. <view class="card-item-name">年度</view>
  342. <view class="card-item-content">{{item.y_month ?? "--"}}</view>
  343. </view>
  344. <view class="card-item">
  345. <view class="card-item-name">计划投资金额</view>
  346. <view class="card-item-content">{{item.amt ?? "--"}}万元</view>
  347. </view>
  348. </view>
  349. <empty-show v-if="projectList.length===0"></empty-show>
  350. </view>
  351. <view class="cards-list" v-if="pageKey === 'compAmt' || pageKey === 'ndjh'">
  352. <view class="order-by" v-if="pageKey === 'yearAmt' || pageKey === 'mothAmt' || pageKey === 'ndjh'">
  353. <view class=" order-by-item">
  354. 金额
  355. <view class="order-by-icon" :class="orderByStatus" @click="changeOrderByStatus()"></view>
  356. </view>
  357. </view>
  358. <view class="card no-padding" v-for="(item,index) in projectList" :key="index">
  359. <card-title :numerator="index+1" :denominator="listTotal"></card-title>
  360. <view class="card-name">
  361. <view class="card-name-title">
  362. <text class="card-name-description">项目名称</text>
  363. </view>
  364. <text class="card-name-text">{{item.subName || "--"}}</text>
  365. </view>
  366. <view class="card-item">
  367. <view class="card-item-name">年度</view>
  368. <view class="card-item-content">{{item.month ?? "--"}}</view>
  369. </view>
  370. <view class="card-item">
  371. <view class="card-item-name">实际投资金额</view>
  372. <view class="card-item-content">{{item.amt ?? "--"}}万元</view>
  373. </view>
  374. </view>
  375. <empty-show v-if="projectList.length===0"></empty-show>
  376. </view>
  377. </view>
  378. </template>
  379. <style lang="scss" scoped>
  380. .no-padding {
  381. padding-top: 0 !important;
  382. }
  383. .card {
  384. padding-top: 16rpx;
  385. overflow: hidden;
  386. }
  387. .light-item {
  388. margin-bottom: 32rpx;
  389. }
  390. .card-light {
  391. display: flex;
  392. align-items: center;
  393. justify-content: center;
  394. }
  395. .card-light-bottom {
  396. width: 122rpx;
  397. height: 44rpx;
  398. margin: auto 0;
  399. background-size: 100% 100%;
  400. }
  401. .light-red {
  402. background-image: url('@/static/icon-light-red.png');
  403. }
  404. .light-yellow {
  405. background-image: url('@/static/icon-light-yellow.png');
  406. }
  407. .light-green {
  408. background-image: url('@/static/icon-light-green.png');
  409. }
  410. .focus {
  411. width: 46rpx;
  412. height: 40rpx;
  413. background-image: url("@/static/focus-off.png");
  414. background-size: 100% 100%;
  415. }
  416. .focus-on {
  417. background-image: url("@/static/focus-on.png");
  418. }
  419. .special-btn {
  420. background: linear-gradient(225deg, #2428F1 0%, #12C8C2 94%);
  421. }
  422. .bottom-item {
  423. margin-bottom: 64rpx;
  424. }
  425. .card-value {
  426. position: absolute;
  427. bottom: 0;
  428. right: 0;
  429. width: 255rpx;
  430. height: 68rpx;
  431. padding-right: 22rpx;
  432. text-align: right;
  433. line-height: 68rpx;
  434. color: #1869F6;
  435. font-size: 32rpx;
  436. background: linear-gradient(270deg, #B2CEFF 0%, rgba(219, 232, 255, 0) 100%);
  437. }
  438. .order-by {
  439. display: flex;
  440. align-items: center;
  441. justify-content: space-between;
  442. width: 100%;
  443. height: 106rpx;
  444. margin-bottom: 34rpx;
  445. padding: 0 40rpx;
  446. border-radius: 40rpx;
  447. background: #FFF;
  448. .order-by-item {
  449. flex: 1;
  450. display: flex;
  451. justify-content: center;
  452. align-items: center;
  453. font-size: 32rpx;
  454. color: #343437;
  455. .order-by-icon {
  456. width: 22rpx;
  457. height: 46rpx;
  458. margin-left: 24rpx;
  459. background-image: url("@/static/orderBy-none.png");
  460. background-size: 100% 100%;
  461. }
  462. .desc {
  463. background-image: url("@/static/orderBy-desc.png");
  464. }
  465. .asc {
  466. background-image: url("@/static/orderBy-asc.png");
  467. }
  468. }
  469. }
  470. .count-value {
  471. display: flex;
  472. flex-wrap: wrap;
  473. width: 100%;
  474. height: 200rpx;
  475. margin-bottom: 20rpx;
  476. background: linear-gradient(180deg, #FFFFFF 2%, #A5C6FF 100%);
  477. border-radius: 40rpx 40rpx 40rpx 40rpx;
  478. opacity: 1;
  479. border: 4rpx solid #fff;
  480. .count-item {
  481. display: flex;
  482. flex-direction: column;
  483. justify-content: center;
  484. width: 50%;
  485. height: 50%;
  486. text-align: center;
  487. .count-item-value {
  488. margin-bottom: 8rpx;
  489. font-size: 34rpx;
  490. font-weight: 500;
  491. color: #FF4000;
  492. }
  493. .count-special-value {
  494. color: #330DDF;
  495. }
  496. .count-item-description {
  497. font-size: 24rpx;
  498. color: #343437;
  499. }
  500. }
  501. }
  502. </style>