years.vue 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  1. <template>
  2. <div class="flex flex-center flex-col">
  3. <div class="full-width">
  4. <basic-tab
  5. :tabs="tabs"
  6. :full="true"
  7. @change="change"
  8. style="width: 99%"
  9. />
  10. </div>
  11. <el-row class="flex flex-center full-width mt-10 flex-wrap">
  12. <el-col :span="12" v-for="i in dash" :key="i">
  13. <div class="box" :style="`box-shadow: ` + i.box">
  14. <div class="flex flex-col bold font-16 padding-14">
  15. <div class="flex flex-justify-start flex-align-end">
  16. <img :src="i.icon" />
  17. <span class="grey-6 ml-5">{{ i.name }}</span>
  18. <span v-if="i.index !== 2" class="font-12 grey-6 ml-10"
  19. >万元</span
  20. >
  21. </div>
  22. <div
  23. v-if="i.index !== 2"
  24. class="flex flex-align-end flex-justify-start mt-10"
  25. >
  26. <span class="grey" style="margin-left: 3px">¥</span>
  27. <span class="ml-5 font-24" :style="`color:` + i.color">{{
  28. info[i.prop] ? info[i.prop].toLocaleString() : '0'
  29. }}</span>
  30. <el-icon
  31. :size="15"
  32. v-if="
  33. (i.index === 0 && user.info.viewStage === 1) ||
  34. (i.index === 0 &&
  35. permissions.vaildPermission('edit_plan_amount'))
  36. "
  37. class="ml-10 pointer"
  38. @click="edit(i)"
  39. >
  40. <Edit />
  41. </el-icon>
  42. </div>
  43. <div v-else class="flex flex-justify-start flex-center full-width">
  44. <div class="progress-bar mt-10">
  45. <div
  46. v-if="info[i.prop]"
  47. class="bar full-height"
  48. :style="
  49. `width: ` +
  50. (Number.parseFloat(info[i.prop].replace('%', '')) > 100
  51. ? '100%'
  52. : info[i.prop])
  53. "
  54. ></div>
  55. </div>
  56. <span class="ml-10 font-24 mt-10" :style="`color:` + i.color">{{
  57. info[i.prop]
  58. }}</span>
  59. </div>
  60. </div>
  61. <div style="margin-top: -20px">
  62. <wave :color="i.color" />
  63. </div>
  64. </div>
  65. </el-col>
  66. </el-row>
  67. </div>
  68. </template>
  69. <script>
  70. import basicTab from '@/components/basic-tab/index.vue'
  71. import wave from '@/views/invest/components/wave.vue'
  72. import { useStore } from '@/store/user.js'
  73. import { ElMessageBox } from 'element-plus'
  74. import index from '@/views/task/index.vue'
  75. import permissionStore from '@/store/permission.js'
  76. export default {
  77. name: 'years',
  78. computed: {
  79. index() {
  80. return index
  81. }
  82. },
  83. components: { basicTab, wave },
  84. setup() {
  85. const user = useStore()
  86. const permissions = permissionStore()
  87. return { user, permissions }
  88. },
  89. props: {
  90. deptId: {
  91. type: String,
  92. default: ''
  93. },
  94. year: {
  95. type: String,
  96. default: ''
  97. }
  98. },
  99. watch: {
  100. deptId: {
  101. handler(val) {
  102. this.load()
  103. },
  104. immediate: true
  105. },
  106. year: {
  107. handler(val) {
  108. this.load()
  109. },
  110. immediate: true
  111. }
  112. },
  113. data() {
  114. return {
  115. times: [],
  116. info: {},
  117. tabs: [
  118. { name: '总览', value: 0 },
  119. { name: '一季度', value: 1 },
  120. { name: '二季度', value: 2 },
  121. { name: '三季度', value: 3 },
  122. { name: '四季度', value: 4 }
  123. ],
  124. quarter: '',
  125. dash: [
  126. {
  127. icon: new URL('../../../assets/svg/invest/1.svg', import.meta.url)
  128. .href,
  129. name: '责任目标',
  130. value: 0,
  131. prop: 'plan_complete_amount',
  132. box: '0 1px 10px 0 rgba(105, 204, 243, 0.3)',
  133. color: '#32B5F3',
  134. index: 0,
  135. background: new URL(
  136. '../../../assets/svg/invest/bg1.svg',
  137. import.meta.url
  138. ).href
  139. },
  140. {
  141. icon: new URL('../../../assets/svg/invest/2.svg', import.meta.url)
  142. .href,
  143. name: '累计完成投资',
  144. value: 0,
  145. prop: 'total_complete_amount',
  146. box: '0 1px 10px 0 rgba(200, 150, 230, 0.3)',
  147. color: '#AD46CB',
  148. index: 1
  149. },
  150. {
  151. icon: new URL('../../../assets/svg/invest/3.svg', import.meta.url)
  152. .href,
  153. name: '投资完成比例',
  154. value: 0,
  155. prop: 'rate',
  156. box: '0 1px 10px 0 rgba(236, 171, 83, 0.3)',
  157. color: '#EC9040',
  158. index: 2
  159. },
  160. {
  161. icon: new URL('../../../assets/svg/invest/4.svg', import.meta.url)
  162. .href,
  163. name: '累计纳统投资',
  164. value: 0,
  165. prop: 'total_investment_amount',
  166. box: '0 1px 10px 0 rgba(119, 94, 241, 0.3)',
  167. color: '#4F5EE7',
  168. index: 3
  169. }
  170. ]
  171. }
  172. },
  173. created() {
  174. this.init()
  175. },
  176. methods: {
  177. load() {
  178. this.tabs[0].name = this.year + '年总览'
  179. this.$api.invest
  180. .homeInvest({
  181. deptId: this.deptId === null ? '' : this.deptId,
  182. year: this.year === null ? '' : this.year,
  183. quarter: this.quarter
  184. })
  185. .then(res => {
  186. if (res.code === 200) {
  187. this.info = res.data
  188. }
  189. })
  190. },
  191. init() {
  192. const year = new Date().getFullYear()
  193. this.tabs[0].name = year + '年总览'
  194. },
  195. change(index) {
  196. this.quarter = index.value === 0 ? '' : index.value
  197. this.$emit('change', index)
  198. this.load()
  199. },
  200. edit(item) {
  201. ElMessageBox.prompt(
  202. '当前责任目标为' +
  203. this.info[item.prop].toLocaleString() +
  204. '万元,请输入新的责任目标(数字,小数点)',
  205. '提示',
  206. {
  207. confirmButtonText: '保存',
  208. cancelButtonText: '取消',
  209. inputPattern: /^([1-9]\d*|0)(\.\d+)?$/,
  210. inputErrorMessage: '信息错误'
  211. }
  212. ).then(({ value }) => {
  213. let data = {}
  214. switch (this.quarter) {
  215. case 0: // 年度
  216. data = { number: value }
  217. break
  218. case 1: // 1季度
  219. data = { number: value, type: 1 }
  220. break
  221. case 2: // 2季度
  222. data = { number: value, type: 2 }
  223. break
  224. case 3: // 3季度
  225. data = { number: value, type: 3 }
  226. break
  227. case 4: // 4季度
  228. data = { number: value, type: 4 }
  229. break
  230. default:
  231. data = { number: value }
  232. break
  233. }
  234. this.$api.invest
  235. .savePlan(
  236. Object.assign(
  237. {
  238. deptId: this.deptId === null ? '' : this.deptId,
  239. year: this.year === null ? '' : this.year
  240. },
  241. data
  242. )
  243. )
  244. .then(res => {
  245. if (res.code === 200) {
  246. this.$message.success(res.msg)
  247. this.info[item.prop] = value
  248. } else {
  249. this.$message.error(res.msg)
  250. }
  251. })
  252. })
  253. }
  254. }
  255. }
  256. </script>
  257. <style lang="scss" scoped>
  258. .content {
  259. background-image: url('@/assets/svg/invest/wave/1.svg');
  260. background-size: 100% 100%;
  261. background-repeat: no-repeat;
  262. }
  263. .box {
  264. min-width: 280px;
  265. border-radius: 8px;
  266. min-height: 115px;
  267. margin: 20px;
  268. background-color: #f6f9fd;
  269. }
  270. .progress-bar {
  271. width: 60%;
  272. height: 10px;
  273. background: white;
  274. border-radius: 10px;
  275. margin-left: 5px;
  276. border: 1px solid #f8b65f;
  277. }
  278. .bar {
  279. background: #f8b65f;
  280. border-radius: 10px;
  281. }
  282. </style>