index.vue 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440
  1. <script setup>
  2. import {
  3. ref
  4. } from "vue"
  5. import {
  6. onLoad,
  7. onShow,
  8. } from "@dcloudio/uni-app"
  9. import {
  10. getOverdueNum
  11. } from "@/api/work/overdue.js"
  12. import {
  13. getannouncementList,
  14. getUnwriteReportList,
  15. getHomeStats
  16. } from "@/api/home.js"
  17. import {
  18. getJSDDlist,
  19. getHYFLlist,
  20. } from "@/api/work/projectInfo.js";
  21. import {
  22. getMessageNum
  23. } from "@/api/work/message.js"
  24. import store from '@/store'
  25. import {
  26. checkRoleById
  27. } from "@/utils/permission.js"
  28. import iconEnterpriseInfo from "@/static/func/enterpriseInfos.svg";
  29. import iconProjectInfo from "@/static/func/projectInfo.svg";
  30. import iconReserveProject from "@/static/func/reserveProject.svg";
  31. import iconContact from "@/static/func/contact.svg";
  32. import iconQuestionList from "@/static/func/questionList.svg";
  33. import iconQuestionInput from "@/static/func/questionInput.svg";
  34. import iconQuestionTrace from "@/static/func/questionTrace.svg";
  35. import iconFundPlan from "@/static/func/fundPlan.svg";
  36. import iconFundUse from "@/static/func/fundUse.svg";
  37. import iconProjectPercents from "@/static/func/projectPercents.svg";
  38. import iconImportant from "@/static/func/important.svg";
  39. import iconPreFlow from "@/static/func/preFlow.svg";
  40. import iconWeekly from "@/static/func/weekly.svg";
  41. import iconMonthly from "@/static/func/monthly.svg";
  42. import iconYearly from "@/static/func/yearly.svg";
  43. import iconOverdued from "@/static/func/overdued.svg";
  44. import iconOverdueWill from "@/static/func/overdueWill.svg";
  45. // 项目信息
  46. let projectYear = ref(2023);
  47. // 选择年
  48. let yearShow = ref(false);
  49. let defaultIndex = ref([0]);
  50. let yearColumns = ref([
  51. ["2000", "2001", "2002", "2003", "2004", "2005", "2006", "2007", "2008", "2009", "2010", "2011", "2012",
  52. "2013",
  53. "2014", "2015", "2016", "2017", "2018", "2019", "2020", "2021", "2022", "2023", "2024", "2025", "2026",
  54. "2027", "2028", "2029", "2030", "2031", "2032", "2033"
  55. ]
  56. ])
  57. const yearShowChoose = function() {
  58. yearShow.value = true;
  59. }
  60. const yearClose = function(e) {
  61. if (e) {
  62. projectYear.value = e.value[0];
  63. // 获取最新数据
  64. getProjectInfo();
  65. }
  66. yearShow.value = false;
  67. }
  68. // 选择分类
  69. let projectKind = ref(null);
  70. let projectKindId = null;
  71. let kindShow = ref(false);
  72. let kindColumns = ref([]);
  73. const kindShowChoose = function() {
  74. kindShow.value = true;
  75. }
  76. const kindClose = function(e) {
  77. if (e) {
  78. projectKind.value = e.value[0];
  79. projectKindId = hyflFull.find(item => item.value === projectKind.value).key;
  80. // 获取最新数据
  81. getProjectInfo();
  82. }
  83. kindShow.value = false;
  84. }
  85. let hyflFull = [];
  86. const getHYFL = function() {
  87. getHYFLlist().then(res => {
  88. hyflFull = res.data.list;
  89. kindColumns.value = [res.data.list.map(item => item.value)];
  90. })
  91. };
  92. // 选择地点
  93. let projectArea = ref(null);
  94. let projectAreaId = null;
  95. let areaShow = ref(false);
  96. let areaColumns = ref([]);
  97. const areaShowChoose = function() {
  98. areaShow.value = true;
  99. }
  100. const areaClose = function(e) {
  101. if (e) {
  102. projectArea.value = e.value[0];
  103. projectAreaId = jsddFull.find(item => item.value === projectArea.value).key;
  104. // 获取最新数据
  105. getProjectInfo();
  106. }
  107. areaShow.value = false;
  108. }
  109. let jsddFull = [];
  110. const getJSDD = function() {
  111. getJSDDlist().then(res => {
  112. jsddFull = res.data.list;
  113. areaColumns.value = [res.data.list.map(item => item.value)];
  114. })
  115. };
  116. let projectNum = ref([{
  117. name: "亿元以下",
  118. key: "numAmt1",
  119. value: 0,
  120. }, {
  121. name: "1-5亿",
  122. key: "numAmt2",
  123. value: 0,
  124. }, {
  125. name: "5-10亿",
  126. key: "numAmt3",
  127. value: 0,
  128. }, {
  129. name: "10亿以上",
  130. key: "numAmt4",
  131. value: 0,
  132. }]);
  133. let fundNum = ref([{
  134. name: "年度计划投资",
  135. key: "amtJh",
  136. value: 0,
  137. }, {
  138. name: "当月计划投资",
  139. key: "monthPlan",
  140. value: 0,
  141. }, {
  142. name: "年度完成投资",
  143. key: "amtSj",
  144. value: 0,
  145. }]);
  146. let fullPercents = ref(0);
  147. let pieOpts = ref({
  148. color: ["#03873F", "#00B250", "#1BBF65", "#31DF80", "#69E2A0"],
  149. enableScroll: false,
  150. legend: {
  151. show: false
  152. },
  153. extra: {
  154. pie: {
  155. customRadius: 80,
  156. border: false,
  157. }
  158. }
  159. })
  160. let ringOpts = ref({
  161. color: ["#3E76FC", "#7AA2FF", "#B8CDFF"],
  162. enableScroll: false,
  163. legend: {
  164. show: false
  165. },
  166. title: {
  167. name: "300",
  168. fontSize: 14,
  169. color: "#3D3D3D"
  170. },
  171. subtitle: {
  172. name: "项目总数",
  173. fontSize: 14,
  174. color: "#3D3D3D"
  175. },
  176. extra: {
  177. ring: {
  178. customRadius: 55,
  179. ringWidth: 20,
  180. border: false,
  181. }
  182. }
  183. })
  184. let ringTotal = ref(0);
  185. let ringChartData = ref({
  186. series: [{
  187. data: [{
  188. name: '新建项目',
  189. value: 100,
  190. labelShow: false
  191. }, {
  192. name: '续建项目',
  193. value: 100,
  194. labelShow: false
  195. }, {
  196. name: '储备项目',
  197. value: 100,
  198. labelShow: false
  199. }]
  200. }]
  201. })
  202. let showRing = ref(false)
  203. let showPie = ref(false)
  204. let pieChartData = ref({
  205. series: [{
  206. data: [{
  207. name: "无数据",
  208. value: 0,
  209. labelShow: false
  210. }]
  211. }]
  212. })
  213. function getProjectInfo() {
  214. getHomeStats({
  215. year: projectYear.value,
  216. indusKind: projectKindId,
  217. buildAddre: projectAreaId
  218. }).then(res => {
  219. const {
  220. data
  221. } = res;
  222. for (let i in projectNum.value) {
  223. projectNum.value[i].value = data[projectNum.value[i].key] ?? "--";
  224. }
  225. for (let i in fundNum.value) {
  226. fundNum.value[i].value = data[fundNum.value[i].key] ?? "--";
  227. }
  228. fullPercents.value = (data.numBl ?? "") === "" ? 0 : parseFloat(data.numBl);
  229. // 圆环图
  230. numNew.value = ringChartData.value.series[0].data[0].value = data.numNew;
  231. numOld.value = ringChartData.value.series[0].data[1].value = data.numOld;
  232. numNo.value = ringChartData.value.series[0].data[2].value = data.numNo;
  233. ringOpts.value.title.name = data.numTotal ?? "0";
  234. showRing.value = true;
  235. let tempArr = [];
  236. for (let i in data.buildAddress) {
  237. tempArr.push({
  238. name: data.buildAddress[i].title,
  239. value: data.buildAddress[i].num,
  240. labelShow: false
  241. })
  242. }
  243. if (data.buildAddress.length > 0) {
  244. pieChartData.value.series[0].data = tempArr
  245. } else {
  246. pieChartData.value.series[0].data = [{
  247. name: "无数据",
  248. value: 0,
  249. labelShow: false
  250. }]
  251. };
  252. showPie.value = true;
  253. })
  254. }
  255. let numNew = ref(0);
  256. let numOld = ref(0);
  257. let numNo = ref(0);
  258. // 公告列表
  259. let announcementList = ref([]);
  260. function getAnnounceMent() {
  261. getannouncementList({
  262. pageNo: 1,
  263. pageSize: 3
  264. }).then(res => {
  265. let titleList = res.data.list.map(item => {
  266. return item.title
  267. })
  268. announcementList.value = titleList.length > 0 ? titleList : ['当前暂无公告'];
  269. })
  270. }
  271. // 逾期数量
  272. let overdueWill = ref(0);
  273. let overdued = ref(0);
  274. function getOverdue() {
  275. getOverdueNum().then(res => {
  276. let bigItem = functionList.value.find(item => item.name === "问题督办");
  277. let willItem = bigItem.funcList.find(item => item.name === "预期提醒");
  278. willItem.badgeValue = res.data.willOver ?? 0;
  279. let overduedItem = bigItem.funcList.find(item => item.name === "已逾期");
  280. overduedItem.badgeValue = res.data.isOver ?? 0;
  281. // overdueWill.value = res.data.willOver ?? 0;
  282. // overdued.value = res.data.isOver ?? 0;
  283. })
  284. }
  285. // 功能列表
  286. let functionList = ref([{
  287. name: '基本信息',
  288. permissionCode: '712',
  289. funcList: [{
  290. name: '企业信息',
  291. url: '/pages/enterpriseInfo/index',
  292. icon: iconEnterpriseInfo,
  293. permissionCode: '7121'
  294. }, {
  295. name: '项目台账',
  296. url: '/pages/projectInfo/index',
  297. icon: iconProjectInfo,
  298. permissionCode: '7111'
  299. }, {
  300. name: '储备项目',
  301. url: '/pages/cbProject/index',
  302. icon: iconReserveProject,
  303. permissionCode: '7112'
  304. }, {
  305. name: '联系人',
  306. url: '/pages/contact/index',
  307. icon: iconContact,
  308. permissionCode: '7112'
  309. }]
  310. },
  311. {
  312. name: '由项目申报单位填写',
  313. permissionCode: '811',
  314. funcList: [{
  315. name: '周报',
  316. url: '/pages/weekly/index',
  317. icon: iconWeekly,
  318. permissionCode: '8112'
  319. }, {
  320. name: '月报',
  321. url: '/pages/monthly/index',
  322. icon: iconMonthly,
  323. permissionCode: '8113'
  324. }, {
  325. name: '年度计划',
  326. url: '/pages/yearly/index',
  327. icon: iconYearly,
  328. permissionCode: '8111'
  329. }]
  330. },
  331. {
  332. name: '问题督办',
  333. permissionCode: '713',
  334. funcList: [{
  335. name: '问题清单',
  336. url: '/pages/oversee/index',
  337. icon: iconQuestionList,
  338. permissionCode: '7131'
  339. }, {
  340. name: '问题录入',
  341. url: '/pages/questionInput/index',
  342. icon: iconQuestionInput,
  343. permissionCode: '7132'
  344. }, {
  345. name: '问题跟踪',
  346. url: '/pages/questionTrace/index',
  347. icon: iconQuestionTrace,
  348. permissionCode: '7133'
  349. }, {
  350. name: '预期提醒',
  351. url: '/pages/overdue/index',
  352. icon: iconOverdueWill,
  353. permissionCode: '7133',
  354. showBadge: true,
  355. badgeValue: 0
  356. }, {
  357. name: '已逾期',
  358. url: '/pages/overdue/overdued/index',
  359. icon: iconOverdued,
  360. permissionCode: '7133',
  361. showBadge: true,
  362. badgeValue: 0
  363. }]
  364. },
  365. {
  366. name: '统计分析',
  367. permissionCode: '714',
  368. lastLine: true,
  369. funcList: [{
  370. name: '资金计划',
  371. url: '/pages/countAnalysis/fundPlan/index',
  372. icon: iconFundPlan,
  373. permissionCode: '7141',
  374. }, {
  375. name: '资金使用',
  376. url: '/pages/countAnalysis/fundUse/index',
  377. icon: iconFundUse,
  378. permissionCode: '7142'
  379. }, {
  380. name: '项目进度',
  381. url: '/pages/countAnalysis/projectProcess/index',
  382. icon: iconProjectPercents,
  383. permissionCode: '7143'
  384. }, {
  385. name: '重大事项',
  386. url: '/pages/important/index',
  387. icon: iconImportant,
  388. permissionCode: '7143'
  389. }, {
  390. name: '前期手续',
  391. url: '/pages/preFlow/index',
  392. icon: iconPreFlow,
  393. permissionCode: '7143'
  394. }]
  395. },
  396. ])
  397. // 判断功能菜单权限
  398. const roles = store.getters && store.getters.permissions;
  399. function judgeFuncList() {
  400. let tempList = JSON.parse(JSON.stringify(functionList.value))
  401. for (let i in tempList) {
  402. //如果父级都没权限 直接移除
  403. if (!roles.includes(tempList[i].permissionCode)) {
  404. tempList[i].ban = true
  405. } else {
  406. let funcListSon = tempList[i].funcList
  407. for (let j in funcListSon) {
  408. if (!roles.includes(funcListSon[j].permissionCode)) {
  409. funcListSon[j].ban = true
  410. }
  411. }
  412. }
  413. }
  414. let filterList = tempList.filter(item => {
  415. return !item.ban
  416. })
  417. for (let i in filterList) {
  418. let filterListSon = filterList[i].funcList.filter(item => {
  419. return !item.ban
  420. })
  421. filterList[i].funcList = filterListSon
  422. }
  423. functionList.value = filterList
  424. }
  425. function goToPage(url, permissionCode) {
  426. if (permissionCode) {
  427. let havePermission = checkRoleById([permissionCode])
  428. if (!havePermission) return
  429. }
  430. uni.navigateTo({
  431. url
  432. })
  433. }
  434. // =============================未填写周报月报
  435. let popupShow = ref(false)
  436. let unWriteList = ref([])
  437. let unWriteListTotal = ref(0)
  438. function getUnwirteList() {
  439. getUnwriteReportList().then(res => {
  440. if (res.data.list.length > 0) {
  441. popupShow.value = true;
  442. unWriteList.value = res.data.list;
  443. unWriteListTotal.value = res.data.list.length;
  444. }
  445. })
  446. }
  447. function goToWriteReport(item) {
  448. const {
  449. sub_id: subId,
  450. month1: kj_month,
  451. } = item;
  452. let year = item.month1.substr(0, 4)
  453. let startDate = item.month1.substr(0, 10)
  454. if (item.kind === "1") { // 周报
  455. uni.navigateTo({
  456. url: `/pages/weekly/input/index?subId=${subId}&startDate=${startDate}&year=${year}&kj_month=${kj_month}`
  457. })
  458. } else { // 月报
  459. let kjMonth = kj_month.substring(0, 4) + '年' + kj_month.substring(4, 6) + '月';
  460. uni.navigateTo({
  461. url: `/pages/monthly/input/index?subId=${subId}&startDate=${startDate}&year=${year}&kj_month=${kjMonth}`
  462. })
  463. }
  464. }
  465. function popupClose() {
  466. popupShow.value = false
  467. }
  468. function getMessageCount() {
  469. getMessageNum().then(res => {
  470. if (res.data.count) {
  471. uni.setTabBarBadge({ //显示数字
  472. index: 1, //tabbar下标
  473. text: res.data.count + '' //数字
  474. })
  475. } else {
  476. uni.removeTabBarBadge({ //显示数字
  477. index: 1, //tabbar下标
  478. })
  479. }
  480. })
  481. }
  482. onLoad(() => {
  483. let now = new Date();
  484. projectYear.value = now.getFullYear();
  485. defaultIndex.value = [projectYear.value - 2000];
  486. judgeFuncList(); //判断权限
  487. getAnnounceMent(); //获取公告
  488. getHYFL(); //获取行业分类
  489. getJSDD(); //获取建设地点
  490. getProjectInfo(); //获取项目数据
  491. getOverdue(); //获取逾期数量
  492. getUnwirteList(); //获取未填写周报月报信息
  493. getMessageCount(); //获取未读消息数量
  494. });
  495. onShow(() => {
  496. if (popupShow.value) {
  497. getUnwirteList();
  498. }
  499. })
  500. </script>
  501. <template>
  502. <view class="container">
  503. <!-- 头 固定-->
  504. <view class="title-content">
  505. <!-- <text class="title">工作台</text> -->
  506. <!-- 搜索 -->
  507. <!-- <view class="search">
  508. <view class="search-input">
  509. <view class="search-icon"></view>
  510. <input @focus="goToPage('/pages/search/index')" placeholder="项目、领导电话..."
  511. placeholder-style="color: #D8D8D8;font-size:24rpx" />
  512. </view>
  513. <view class="search-focus" @click="goToPage('/pages/focus/index')">
  514. <view class="search-focus-icon"></view>
  515. 关注
  516. </view>
  517. </view> -->
  518. <view class="title">
  519. <view class="title-text">工作台</view>
  520. <view class="title-search" @click="goToPage('/pages/search/index')"></view>
  521. </view>
  522. </view>
  523. <!-- <view class="top-blue"> -->
  524. <!-- 新增功能 -->
  525. <!-- <view class="special-funcs">
  526. <view class="special-func-item gov" @click="goToPage('/pages/policy/search/index')">
  527. <view class="special-func-title">
  528. <view class="special-func-name">政策文件</view>
  529. <u-icon name="arrow-right" color="#fff" size="16" customStyle="margin-top:2rpx"></u-icon>
  530. </view>
  531. </view>
  532. <view class="special-func-item todo" @click="goToPage('/pages/process/index')">
  533. <view class="special-func-title">
  534. <view class="special-func-name">办事流程</view>
  535. <u-icon name="arrow-right" color="#fff" size="16" customStyle="margin-top:2rpx"></u-icon>
  536. </view>
  537. </view>
  538. <view class="special-func-item images" @click="goToPage('/pages/projectImage/index')">
  539. <view class="special-func-title">
  540. <view class="special-func-name">项目形象进度</view>
  541. <u-icon name="arrow-right" color="#fff" size="16" customStyle="margin-top:2rpx"></u-icon>
  542. </view>
  543. </view>
  544. </view>
  545. -->
  546. <!-- 公告 -->
  547. <!-- <view class="announcementList"> -->
  548. <!-- <view class="announcementList-text">通知公告</view> -->
  549. <!-- <u-notice-bar :text="announcementList" url="/pages/announcement/list/index" direction="column"
  550. mode="link" bgColor="#FFF7DC " color="#FF8D02"></u-notice-bar>
  551. </view> -->
  552. <!-- </view> -->
  553. <!-- 功能区 -->
  554. <view class="function-list">
  555. <view class="func-kind" v-for="item in functionList">
  556. <view class="func-kind-title">
  557. <view class="func-kind-icon"></view>
  558. {{item.name}}
  559. </view>
  560. <u-grid :border="false" col="4">
  561. <u-grid-item v-for="(listItem,listIndex) in item.funcList" :key="listIndex"
  562. @click="goToPage(listItem.url,listItem.permissionCode)">
  563. <view class="grid-item">
  564. <u-badge v-if="listItem.showBadge" class="badge-num" type="error" max="99"
  565. :value="listItem.badgeValue"></u-badge>
  566. <view class="grid-item-icon">
  567. <image :src="listItem.icon"></image>
  568. </view>
  569. {{listItem.name}}
  570. </view>
  571. </u-grid-item>
  572. </u-grid>
  573. </view>
  574. </view>
  575. <!-- 项目信息 -->
  576. <view class="project-info">
  577. <view class="project-info-select">
  578. <view class="choose-year" @click="yearShowChoose()">
  579. 年度:{{projectYear}}
  580. <u-icon name="arrow-right" color="#343437" size="14" customStyle="margin-left:10rpx"></u-icon>
  581. </view>
  582. <view class="choose-year border" @click="kindShowChoose()">
  583. {{projectKind ??"行业分类"}}
  584. <u-icon name="arrow-right" color="#343437" size="14" customStyle="margin-left:10rpx"></u-icon>
  585. </view>
  586. <view class="choose-year" @click="areaShowChoose()">
  587. {{projectArea ??"建设地点"}}
  588. <u-icon name="arrow-right" color="#343437" size="14" customStyle="margin-left:10rpx"></u-icon>
  589. </view>
  590. </view>
  591. <view class="project-num-box">
  592. <view class="project-num">
  593. <view class="project-num-title blue">
  594. 亿元项目数(单位:个)
  595. </view>
  596. <view class="project-num-minbox">
  597. <view class=" project-num-item" v-for="(item,index) in projectNum" :key="index">
  598. <view class="project-num-value">{{item.value}}</view>
  599. <text style="color:#82828C">{{item.name}}</text>
  600. </view>
  601. </view>
  602. </view>
  603. <view class="project-num">
  604. <view class="project-num-title">
  605. 资金使用情况(单位:万元)
  606. <u-icon name="arrow-right" color="#7D7D9C" size="14"></u-icon>
  607. </view>
  608. <view class="project-num-minbox">
  609. <view class="project-num-item" v-for="(item,index) in fundNum" :key="index">
  610. <view class="project-num-value">{{item.value}}</view>
  611. <text style="color:#82828C">{{item.name}}</text>
  612. </view>
  613. </view>
  614. </view>
  615. <view class="project-process">
  616. 实际整体进度
  617. <view class="line-progress">
  618. <u-line-progress :percentage="fullPercents" inactiveColor="#C1CEED" activeColor="#5D5AFF" :showText="false"
  619. height="13"></u-line-progress>
  620. </view>
  621. <view class="percent">
  622. {{fullPercents}}%
  623. </view>
  624. </view>
  625. </view>
  626. </view>
  627. <!-- 饼图 -->
  628. <view class="charts">
  629. <view class="charts-item">
  630. <view class="charts-item-title">单位:个</view>
  631. <view class="charts-item-ring">
  632. <qiun-data-charts v-if="showRing" type="ring" :opts="ringOpts" :chartData="ringChartData" />
  633. </view>
  634. <view class="charts-item-description">
  635. <view class="charts-item-key">
  636. <view class="charts-item-color"></view>
  637. <view class="charts-item-name">新建项目</view>
  638. </view>
  639. <view class="charts-item-value">{{numNew}}</view>
  640. </view>
  641. <view class="charts-item-description">
  642. <view class="charts-item-key">
  643. <view class="charts-item-color"></view>
  644. <view class="charts-item-name">续建项目</view>
  645. </view>
  646. <view class="charts-item-value">{{numOld}}</view>
  647. </view>
  648. <view class="charts-item-description">
  649. <view class="charts-item-key">
  650. <view class="charts-item-color"></view>
  651. <view class="charts-item-name">储备项目</view>
  652. </view>
  653. <view class="charts-item-value">{{numNo}}</view>
  654. </view>
  655. </view>
  656. <view class="charts-item">
  657. <view class="charts-item-pie">
  658. <qiun-data-charts v-if="showPie" type="pie" :opts="pieOpts" :chartData="pieChartData" />
  659. </view>
  660. <view class="charts-item-text">建设地点</view>
  661. <view class="charts-item-text">投资占比</view>
  662. </view>
  663. </view>
  664. <!-- 逾期提醒 -->
  665. <!-- <view class="overdue">
  666. <view class="overdue-item" @click="goToPage('/pages/overdue/index')">
  667. <view class="overdue-icon overdue-will">
  668. <view class="badge-box">
  669. <u-badge class="badge-num" type="error" max="99" :value="overdueWill"></u-badge>
  670. </view>
  671. </view>
  672. <view class="overdue-item-text">
  673. 预期提醒
  674. <u-icon name="arrow-right" color="#343437" size="16" customStyle="margin-left:20rpx"></u-icon>
  675. </view>
  676. </view>
  677. <view class="overdue-item" @click="goToPage('/pages/overdue/overdued/index')">
  678. <view class="overdue-icon overdued">
  679. <view class="badge-box">
  680. <u-badge class="badge-num" type="error" max="99" :value="overdued"></u-badge>
  681. </view>
  682. </view>
  683. <view class="overdue-item-text">
  684. 已逾期
  685. <u-icon name="arrow-right" color="#343437" size="16" customStyle="margin-left:20rpx"></u-icon>
  686. </view>
  687. </view>
  688. </view>
  689. -->
  690. <!-- 周报日报年度计划 -->
  691. <!-- <view v-if="roles.includes('811')" class="report">
  692. <view v-if="roles.includes('8112')" class="report-item" @click="goToPage('/pages/weekly/index','8112')">
  693. <view class="report-icon weekly"></view>
  694. <view class="report-item-text">周报</view>
  695. </view>
  696. <view v-if="roles.includes('8113')" class="report-item" @click="goToPage('/pages/monthly/index','8113')">
  697. <view class="report-icon monthly"></view>
  698. <view class="report-item-text">月报</view>
  699. </view>
  700. <view v-if="roles.includes('8111')" class="report-item" @click="goToPage('/pages/yearly/index','8111')">
  701. <view class="report-icon yearly"></view>
  702. <view class="report-item-text">年度计划</view>
  703. </view>
  704. </view>-->
  705. <!-- 中部间隔 -->
  706. <view class="gap-line"></view>
  707. <!-- 底部间隔 -->
  708. <view class="gap-bottom"></view>
  709. <!-- 周报月报弹窗 -->
  710. <u-popup :show="popupShow" :round="20" @close="popupClose()" mode="center" closeable>
  711. <view class="remind-box">
  712. <text class="remind-title">提示</text>
  713. <view class="remind-card" v-for="(item,index) in unWriteList" :key="index">
  714. <view class="remind-item">
  715. <view class="remind-item-name">类型</view>
  716. <view class="remind-item-content">{{item.kind==='1'?'缺失周报':'缺失月报'}}</view>
  717. </view>
  718. <view class="remind-item">
  719. <view class="remind-item-name">项目名称</view>
  720. <view class="remind-item-content">{{item.sub_name || '--'}}</view>
  721. </view>
  722. <view class="remind-item">
  723. <view class="remind-item-name">说明</view>
  724. <view class="remind-item-content">{{item.remark || '--'}}</view>
  725. </view>
  726. <view class="remind-item">
  727. <view class="remind-item-btn" @click="goToWriteReport(item)">
  728. {{item.kind==='1'?'填写周报':'填写月报'}}
  729. </view>
  730. </view>
  731. <view class="remind-count">
  732. {{index + 1}}/{{unWriteListTotal}}
  733. </view>
  734. </view>
  735. </view>
  736. </u-popup>
  737. <!-- 年度选择 -->
  738. <u-picker :show="yearShow" :defaultIndex="defaultIndex" :columns="yearColumns" @confirm="yearClose"
  739. @cancel="yearClose" @close="yearClose" closeOnClickOverlay></u-picker>
  740. <!-- 行业选择 -->
  741. <u-picker :show="kindShow" :columns="kindColumns" @confirm="kindClose" @cancel="kindClose" @close="kindClose"
  742. closeOnClickOverlay></u-picker>
  743. <!-- 地点选择 -->
  744. <u-picker :show="areaShow" :columns="areaColumns" @confirm="areaClose" @cancel="areaClose" @close="areaClose"
  745. closeOnClickOverlay></u-picker>
  746. </view>
  747. </template>
  748. <style lang="scss" scoped>
  749. @font-face {
  750. font-family: TITLETEXT;
  751. src: url('@/font/RuiZiAoYunJingShenPinBoJianMianFei-Shan(REEJI-PinboGB-Flash)-2.ttf');
  752. }
  753. page {
  754. height: 100%;
  755. background-color: #F9FBFF;
  756. }
  757. .container {
  758. background: #F9FBFF;
  759. }
  760. .title-content {
  761. position: fixed;
  762. top: 0;
  763. left: 0;
  764. width: 100%;
  765. height: 190rpx;
  766. padding-top: 100rpx;
  767. background-color: #1763E7;
  768. z-index: 1;
  769. .title {
  770. position: relative;
  771. display: flex;
  772. justify-content: center;
  773. align-items: center;
  774. font-size: 36rpx;
  775. font-weight: 700;
  776. color: #FFF;
  777. .title-search {
  778. position: absolute;
  779. right: 3%;
  780. width: 46rpx;
  781. height: 46rpx;
  782. background-image: url("@/static/search.png");
  783. background-size: 100% 100%;
  784. }
  785. }
  786. }
  787. .search {
  788. display: flex;
  789. justify-content: space-between;
  790. width: 92%;
  791. height: 68rpx;
  792. margin: 32rpx auto 44rpx;
  793. .search-input {
  794. display: flex;
  795. align-items: center;
  796. width: 592rpx;
  797. height: 100%;
  798. padding: 0 30rpx;
  799. box-sizing: border-box;
  800. text-align: left;
  801. background-color: #fff;
  802. border-radius: 16rpx;
  803. .search-icon {
  804. width: 28rpx;
  805. height: 32rpx;
  806. margin-right: 26rpx;
  807. background-image: url('@/static/search-black.png');
  808. background-size: 100% 100%;
  809. }
  810. }
  811. .search-focus {
  812. width: 50rpx;
  813. height: 100%;
  814. font-size: 24rpx;
  815. color: #fff;
  816. font-weight: 400;
  817. line-height: 30rpx;
  818. .search-focus-icon {
  819. width: 36rpx;
  820. height: 32rpx;
  821. margin: 0 auto 10rpx;
  822. background-image: url('@/static/focus.png');
  823. background-size: 100% 100%;
  824. }
  825. }
  826. }
  827. .top-blue {
  828. width: 100%;
  829. height: 722rpx;
  830. padding-top: 288rpx;
  831. margin-bottom: 82rpx;
  832. background: #1763E7;
  833. border-radius: 0 0 40rpx 40rpx;
  834. }
  835. .announcementList {
  836. width: 92%;
  837. height: 72rpx;
  838. margin: 0 auto 32rpx;
  839. padding: 10rpx 0;
  840. color: #FF8D02;
  841. background-color: #FFF7DC;
  842. border-radius: 26rpx;
  843. .announcementList-text {
  844. margin-bottom: 18rpx;
  845. font-size: 28rpx;
  846. }
  847. }
  848. ::v-deep .u-notice-bar {
  849. width: 100%;
  850. // padding: 0;
  851. border-radius: 19rpx;
  852. }
  853. ::v-deep .u-notice__swiper__item__text {
  854. overflow: hidden;
  855. text-overflow: ellipsis;
  856. white-space: nowrap;
  857. }
  858. .special-funcs {
  859. display: flex;
  860. justify-content: space-between;
  861. width: 92%;
  862. height: 210rpx;
  863. margin: 50rpx auto 32rpx;
  864. background-size: 100% 100%;
  865. .special-func-item {
  866. width: 200rpx;
  867. height: 210rpx;
  868. padding: 34rpx 18rpx;
  869. box-sizing: border-box;
  870. background-size: 100% 100%;
  871. .special-func-title {
  872. display: flex;
  873. justify-content: space-between;
  874. align-items: flex-start;
  875. }
  876. .special-func-name {
  877. color: #FFFFFF;
  878. line-height: 34rpx;
  879. font-size: 32rpx;
  880. font-family: TITLETEXT;
  881. }
  882. }
  883. .gov {
  884. background-image: url('@/static/special-gov.png');
  885. }
  886. .todo {
  887. background-image: url('@/static/special-todo.png');
  888. }
  889. .images {
  890. background-image: url('@/static/special-image.png');
  891. }
  892. }
  893. .project-info-select {
  894. display: flex;
  895. justify-content: space-between;
  896. width: calc(100% - 48rpx);
  897. height: 80rpx;
  898. margin: 0 auto;
  899. background-color: #fff;
  900. border-radius: 16rpx;
  901. box-shadow: 0rpx 8rpx 20rpx 0rpx rgba(0, 0, 0, 0.03);
  902. .choose-year {
  903. flex: 1;
  904. display: flex;
  905. align-items: center;
  906. justify-content: center;
  907. font-size: 24rpx;
  908. font-weight: 500;
  909. color: #343437;
  910. }
  911. .border {
  912. border-left: 3rpx solid #EAF0FD;
  913. border-right: 3rpx solid #EAF0FD;
  914. ;
  915. }
  916. }
  917. .project-info {
  918. width: calc(100% - 48rpx);
  919. min-height: 326rpx;
  920. margin: 0 auto 25rpx;
  921. border-radius: 28rpx;
  922. background-color: #F9FBFF;
  923. border: 2rpx solid #C1CEED;
  924. overflow: hidden;
  925. .project-num-box {
  926. width: 100%;
  927. .project-num {
  928. width: 100%;
  929. height: 222rpx;
  930. padding: 40rpx 32rpx;
  931. box-sizing: border-box;
  932. border-bottom: 3rpx solid #EAF0FD;
  933. }
  934. }
  935. .project-num-title {
  936. display: flex;
  937. justify-content: space-between;
  938. margin-bottom: 40rpx;
  939. font-weight: 500;
  940. font-size: 28rpx;
  941. color: #E49F15;
  942. }
  943. .blue {
  944. color: #1763E7
  945. }
  946. .project-num-minbox {
  947. display: flex;
  948. }
  949. .project-num-item {
  950. flex: 1;
  951. margin: auto 0;
  952. font-size: 24rpx;
  953. color: #343437;
  954. text-align: center;
  955. .project-num-value {
  956. margin-bottom: 8rpx;
  957. font-size: 36rpx;
  958. color: #343437;
  959. font-weight: 700;
  960. }
  961. }
  962. .project-process {
  963. display: flex;
  964. align-items: center;
  965. justify-content: space-between;
  966. width: 100%;
  967. height: 108rpx;
  968. padding: 0 36rpx;
  969. font-size: 28rpx;
  970. font-weight: 500;
  971. color: #4B17E7;
  972. .line-progress {
  973. width: 50%;
  974. }
  975. .percent {
  976. color: #4B17E7;
  977. }
  978. }
  979. }
  980. .charts {
  981. display: flex;
  982. justify-content: space-between;
  983. width: calc(100% - 48rpx);
  984. height: 438rpx;
  985. margin: 0 auto 54rpx;
  986. gap: 30rpx;
  987. .charts-item {
  988. width: 336rpx;
  989. height: 100%;
  990. padding: 22rpx 32rpx;
  991. box-sizing: border-box;
  992. border-radius: 40rpx;
  993. border: 3rpx solid rgba(200, 216, 247, 0.302);
  994. .charts-item-title {
  995. font-size: 24rpx;
  996. color: #343437;
  997. }
  998. .charts-item-ring {
  999. height: 250rpx;
  1000. margin: 0 auto;
  1001. }
  1002. .charts-item-pie {
  1003. width: 100%;
  1004. height: 300rpx;
  1005. margin: 0 auto;
  1006. }
  1007. .charts-item-text {
  1008. width: 100%;
  1009. text-align: center;
  1010. font-size: 28rpx;
  1011. font-weight: 500;
  1012. color: #3D3D3D;
  1013. }
  1014. }
  1015. }
  1016. .charts-item-description {
  1017. display: flex;
  1018. align-items: center;
  1019. justify-content: space-between;
  1020. width: 100%;
  1021. margin: 4rpx 0;
  1022. font-size: 24rpx;
  1023. .charts-item-key {
  1024. display: flex;
  1025. align-items: center;
  1026. }
  1027. .charts-item-color {
  1028. width: 24rpx;
  1029. height: 24rpx;
  1030. margin-right: 16rpx;
  1031. background: #3E76FC;
  1032. border-radius: 6rpx;
  1033. }
  1034. .charts-item-name {
  1035. color: #82828C;
  1036. }
  1037. .charts-item-value {
  1038. font-weight: 500;
  1039. color: #343437;
  1040. }
  1041. }
  1042. .overdue {
  1043. display: flex;
  1044. justify-content: space-between;
  1045. width: 92%;
  1046. height: 136rpx;
  1047. margin: 25rpx auto;
  1048. border-radius: 28rpx;
  1049. backdrop-filter: blur(40rpx);
  1050. }
  1051. .overdue-item {
  1052. display: flex;
  1053. justify-content: space-between;
  1054. align-items: center;
  1055. width: 328rpx;
  1056. height: 136rpx;
  1057. padding: 0 28rpx 0 44rpx;
  1058. box-sizing: border-box;
  1059. font-size: 32rpx;
  1060. color: #001D4F;
  1061. font-weight: 400;
  1062. font-family: TITLETEXT;
  1063. background-color: #fff;
  1064. border-radius: 28rpx;
  1065. .overdue-icon {
  1066. background-size: 100% 100%;
  1067. background-position: center center;
  1068. }
  1069. .overdue-will {
  1070. width: 52rpx;
  1071. height: 53rpx;
  1072. background-image: url('@/static/overdue-warn.png');
  1073. .badge-num {
  1074. position: absolute;
  1075. top: 40rpx;
  1076. right: -36rpx;
  1077. }
  1078. }
  1079. .overdued {
  1080. width: 61rpx;
  1081. height: 54rpx;
  1082. background-image: url('@/static/overdue.png');
  1083. .badge-num {
  1084. position: absolute;
  1085. top: 40rpx;
  1086. right: -36rpx
  1087. }
  1088. }
  1089. .badge-box {
  1090. position: relative;
  1091. }
  1092. .overdue-item-text {
  1093. display: flex;
  1094. align-items: center;
  1095. }
  1096. }
  1097. .report {
  1098. display: flex;
  1099. justify-content: space-between;
  1100. width: 92%;
  1101. margin: 25rpx auto 0;
  1102. padding: 0 78rpx;
  1103. height: 164rpx;
  1104. border-radius: 28rpx;
  1105. background: #fff;
  1106. }
  1107. .report-item {
  1108. width: 128rpx;
  1109. height: 142rpx;
  1110. margin: auto 0;
  1111. text-align: center;
  1112. .report-icon {
  1113. width: 96rpx;
  1114. height: 96rpx;
  1115. margin: 0 auto;
  1116. background-size: 100% 100%;
  1117. }
  1118. .weekly {
  1119. background-image: url('@/static/icon-weekly.svg');
  1120. }
  1121. .monthly {
  1122. background-image: url('@/static/icon-monthly.svg');
  1123. }
  1124. .yearly {
  1125. background-image: url('@/static/icon-yearly.svg');
  1126. }
  1127. .report-item-text {
  1128. margin-top: 10rpx;
  1129. color: #000;
  1130. font-size: 28rpx;
  1131. }
  1132. }
  1133. .gap-line {
  1134. width: 100%;
  1135. height: 20rpx;
  1136. background: #E8ECF4;
  1137. }
  1138. .function-list {
  1139. width: 100%;
  1140. min-height: 100rpx;
  1141. margin: 200rpx auto 0;
  1142. padding: 32rpx;
  1143. box-sizing: border-box;
  1144. .func-kind-title {
  1145. position: relative;
  1146. display: flex;
  1147. align-items: center;
  1148. width: 158rpx;
  1149. height: 48rpx;
  1150. padding-left: 27rpx;
  1151. margin-bottom: 32rpx;
  1152. font-weight: 400;
  1153. color: #001D4F;
  1154. line-height: 30rpx;
  1155. font-size: 32rpx;
  1156. font-family: TITLETEXT;
  1157. background: linear-gradient(90deg, rgba(23, 99, 231, 0.37) 0%, rgba(255, 255, 255, 0) 100%);
  1158. white-space: nowrap;
  1159. .func-kind-icon {
  1160. position: absolute;
  1161. top: 0;
  1162. left: -9rpx;
  1163. width: 18rpx;
  1164. height: 48rpx;
  1165. margin-right: 18rpx;
  1166. background: #1869F6;
  1167. border-radius: 9rpx;
  1168. }
  1169. }
  1170. .grid-item {
  1171. height: 92rpx;
  1172. margin: 18rpx 0 46rpx;
  1173. font-size: 24rpx;
  1174. color: #343437;
  1175. .badge-num {
  1176. position: absolute;
  1177. top: 0;
  1178. right: 25rpx;
  1179. }
  1180. .grid-item-icon {
  1181. width: 56rpx;
  1182. height: 56rpx;
  1183. margin: 0 auto 6rpx;
  1184. image {
  1185. width: 100%;
  1186. height: 100%;
  1187. }
  1188. }
  1189. }
  1190. .bottom-item {
  1191. margin-bottom: 0;
  1192. }
  1193. }
  1194. .gap-bottom {
  1195. width: 100%;
  1196. height: 100rpx;
  1197. }
  1198. .remind-box {
  1199. width: 672rpx;
  1200. min-height: 464rpx;
  1201. max-height: 858rpx;
  1202. padding: 16rpx 40rpx;
  1203. overflow: hidden;
  1204. overflow-y: scroll;
  1205. .remind-title {
  1206. color: #FF4800;
  1207. font-size: 36rpx;
  1208. }
  1209. .remind-card {
  1210. position: relative;
  1211. min-height: 376rpx;
  1212. padding-bottom: 32rpx;
  1213. border-bottom: 2rpx solid #D8D8D8;
  1214. .remind-count {
  1215. position: absolute;
  1216. top: 0;
  1217. right: -40rpx;
  1218. display: flex;
  1219. align-items: center;
  1220. justify-content: center;
  1221. width: 134rpx;
  1222. height: 64rpx;
  1223. font-size: 32rpx;
  1224. color: #1869F6;
  1225. background: #CEE0FF;
  1226. border-radius: 32rpx 0rpx 0rpx 32rpx;
  1227. }
  1228. }
  1229. .remind-item {
  1230. display: flex;
  1231. align-items: flex-start;
  1232. margin-top: 40rpx;
  1233. font-size: 32rpx;
  1234. .remind-item-name {
  1235. min-width: 192rpx;
  1236. color: #9E9E9E;
  1237. }
  1238. .remind-item-content {
  1239. color: #343437;
  1240. float: left;
  1241. }
  1242. .remind-item-btn {
  1243. width: 100%;
  1244. height: 84rpx;
  1245. line-height: 84rpx;
  1246. font-size: 36rpx;
  1247. color: #fff;
  1248. text-align: center;
  1249. background: #1869F6;
  1250. border-radius: 16rpx;
  1251. }
  1252. }
  1253. }
  1254. ::v-deep .u-popup__content {
  1255. overflow: hidden;
  1256. }
  1257. </style>