create.vue 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498
  1. <template>
  2. <hc-card scrollbar is-action-btn class="create-project">
  3. <template #header>
  4. <div class="flex-1 text-center text-[24px] font-bold">项目信息填写</div>
  5. </template>
  6. <el-form ref="formRef" :model="baseForm" label-width="auto" :rules="baseFormRules" size="large" label-position="left">
  7. <el-row :gutter="20">
  8. <el-col :span="12">
  9. <el-form-item label="项目名称:" prop="name">
  10. <el-input v-model="baseForm.name" placeholder="请输入" clearable />
  11. </el-form-item>
  12. </el-col>
  13. <el-col :span="12">
  14. <el-form-item label="建设规模:" prop="buildScale">
  15. <el-input v-model="baseForm.buildScale" placeholder="请输入" clearable>
  16. <template #append>
  17. <el-select v-model="baseForm.buildScaleUnit" placeholder="单位" style="width: 80px">
  18. <el-option label="公里" value="1" />
  19. <el-option label="无" value="2" />
  20. </el-select>
  21. </template>
  22. </el-input>
  23. </el-form-item>
  24. </el-col>
  25. <el-col :span="6">
  26. <el-form-item label="项目阶段:" prop="projectStage">
  27. <el-select v-model="baseForm.projectStage" placeholder="请选择">
  28. <el-option v-for="item in stateOptions" :key="item.value" :label="item.label" :value="item.value" />
  29. </el-select>
  30. </el-form-item>
  31. </el-col>
  32. <el-col :span="6">
  33. <el-form-item label="项目类型:" prop="projectType">
  34. <el-select v-model="baseForm.projectType" placeholder="请选择">
  35. <el-option v-for="item in typeOptions" :key="item.value" :label="item.label" :value="item.value" />
  36. </el-select>
  37. </el-form-item>
  38. </el-col>
  39. <el-col :span="6">
  40. <el-form-item label="总投资:" prop="allInvestMoney">
  41. <el-input
  42. v-model="baseForm.allInvestMoney" placeholder="请输入" clearable
  43. :formatter="formatInput"
  44. >
  45. <template #append>亿元</template>
  46. </el-input>
  47. </el-form-item>
  48. </el-col>
  49. <el-col :span="6">
  50. <el-form-item label="十四五计划投资:" prop="fourteenFiveInvest">
  51. <el-input
  52. v-model="baseForm.fourteenFiveInvest" placeholder="请输入" clearable
  53. :formatter="formatInput"
  54. >
  55. <template #append>亿元</template>
  56. </el-input>
  57. </el-form-item>
  58. </el-col>
  59. <el-col :span="6">
  60. <el-form-item label="开工年:" prop="startYear">
  61. <el-date-picker ref="startYearRef" v-model="baseForm.startYear" class="block" type="year" placeholder="请选择" value-format="YYYY" @change="startYearChange" />
  62. </el-form-item>
  63. </el-col>
  64. <el-col :span="6">
  65. <el-form-item label="完工年:" prop="endYear">
  66. <el-date-picker ref="endYearRef" v-model="baseForm.endYear" class="block" type="year" placeholder="请选择" value-format="YYYY" @change="endYearChange" @blur="endYearBlur" />
  67. </el-form-item>
  68. </el-col>
  69. <el-col :span="6">
  70. <el-form-item label="市级重点项目:" prop="isFocusProject">
  71. <el-select v-model="baseForm.isFocusProject" placeholder="请选择">
  72. <el-option label="是" :value="1" />
  73. <el-option label="否" :value="0" />
  74. </el-select>
  75. </el-form-item>
  76. </el-col>
  77. <el-col :span="6">
  78. <el-form-item label="交通强国建设试点任务:" prop="isPilotPlan">
  79. <el-select v-model="baseForm.isPilotPlan" placeholder="请选择">
  80. <el-option label="是" :value="1" />
  81. <el-option label="否" :value="0" />
  82. </el-select>
  83. </el-form-item>
  84. </el-col>
  85. <el-col :span="8">
  86. <el-form-item label="牵头单位:" prop="leaderUnit">
  87. <el-input v-model="baseForm.leaderUnit" placeholder="请输入" clearable type="textarea" />
  88. </el-form-item>
  89. </el-col>
  90. <el-col :span="8">
  91. <el-form-item label="配合单位:" prop="assistUnit">
  92. <el-input v-model="baseForm.assistUnit" placeholder="请输入" clearable type="textarea" />
  93. </el-form-item>
  94. </el-col>
  95. <el-col :span="8">
  96. <el-form-item label="责任单位:" prop="dutyUnit">
  97. <el-input v-model="baseForm.dutyUnit" placeholder="请输入" clearable type="textarea" />
  98. </el-form-item>
  99. </el-col>
  100. </el-row>
  101. </el-form>
  102. <hc-card-item class="year-detail mt-3">
  103. <template #header>
  104. <el-select v-model="selectYear" placeholder="选择年份" class="select-year w-[100px]" @change="changeYear">
  105. <el-option v-for="(item, index) in yearOptions" :key="item.value" :label="item.label" :value="item.value" />
  106. </el-select>
  107. </template>
  108. <el-form :model="yearOptions[selectIndex].yearForm" label-width="auto" class="mt-3" label-position="left" size="large">
  109. <el-form-item label="全年计划投资:" prop="yearlyInvest" class="w-100">
  110. <el-input
  111. v-model="yearOptions[selectIndex].yearForm.yearlyInvest" placeholder="请输入" clearable
  112. :formatter="formatInput"
  113. >
  114. <template #append>亿元</template>
  115. </el-input>
  116. </el-form-item>
  117. <el-form-item label="预计完成投资额:" prop="key1">
  118. <div class="quarter-box w-full flex">
  119. <div class="flex">
  120. <el-input v-model="yearOptions[selectIndex].yearForm.oneInvest" placeholder="请输入" clearable :formatter="formatInput">
  121. <template #prepend>一季度</template>
  122. <template #append>亿元</template>
  123. </el-input>
  124. </div>
  125. <div class="ml-[40px] flex">
  126. <el-input v-model="yearOptions[selectIndex].yearForm.twoInvest" placeholder="请输入" clearable :formatter="formatInput">
  127. <template #prepend>二季度</template>
  128. <template #append>亿元</template>
  129. </el-input>
  130. </div>
  131. <div class="ml-[40px] flex">
  132. <el-input v-model="yearOptions[selectIndex].yearForm.threeInvest" placeholder="请输入" clearable :formatter="formatInput">
  133. <template #prepend>三季度</template>
  134. <template #append>亿元</template>
  135. </el-input>
  136. </div>
  137. <div class="ml-[40px] flex">
  138. <el-input v-model="yearOptions[selectIndex].yearForm.fourInvest" placeholder="请输入" clearable :formatter="formatInput">
  139. <template #prepend>四季度</template>
  140. <template #append>亿元</template>
  141. </el-input>
  142. </div>
  143. </div>
  144. </el-form-item>
  145. <el-form-item label="全年目标:" prop="yearlyTarget">
  146. <el-input v-model="yearOptions[selectIndex].yearForm.yearlyTarget" placeholder="请输入" clearable type="textarea" />
  147. </el-form-item>
  148. </el-form>
  149. <el-form :model="yearOptions[selectIndex]?.yearForm" label-width="auto" class="mt-3" label-position="left">
  150. <div class="hc-form-item-title">各季度工作计划:</div>
  151. <el-form-item label="一季度:" prop="onePlan">
  152. <el-input v-model="yearOptions[selectIndex].yearForm.onePlan" placeholder="请输入" clearable type="textarea" />
  153. </el-form-item>
  154. <el-form-item label="二季度:" prop="twoPlan">
  155. <el-input v-model="yearOptions[selectIndex].yearForm.twoPlan" placeholder="请输入" clearable type="textarea" />
  156. </el-form-item>
  157. <el-form-item label="三季度:" prop="threePlan ">
  158. <el-input v-model="yearOptions[selectIndex].yearForm.threePlan" placeholder="请输入" clearable type="textarea" />
  159. </el-form-item>
  160. <el-form-item label="四季度:" prop="fourPlan">
  161. <el-input v-model="yearOptions[selectIndex].yearForm.fourPlan" placeholder="请输入" clearable type="textarea" />
  162. </el-form-item>
  163. </el-form>
  164. </hc-card-item>
  165. <template #action>
  166. <el-button type="info" @click="cancelClick">取消</el-button>
  167. <el-button v-if="!formInfo.id" color="#20C98B" type="primary" class="text-white" @click="createClick">创建</el-button>
  168. <el-button v-else type="warning" @click="saveClick">保存</el-button>
  169. </template>
  170. </hc-card>
  171. </template>
  172. <script setup>
  173. import { onMounted, ref, watch } from 'vue'
  174. import { isNullES } from 'js-fast-way'
  175. import { arrIndex, formValidate, getArrValue, getObjValue } from 'js-fast-way'
  176. import mainApi from '~api/project/project'
  177. import { getDictionaryData } from '~src/utils/tools'
  178. const props = defineProps({
  179. form: {
  180. type: Object,
  181. default: () => ({}),
  182. },
  183. })
  184. //事件
  185. const emit = defineEmits(['back'])
  186. //监听权限
  187. const formInfo = ref(props.form)
  188. watch(() => props.form, (data) => {
  189. formInfo.value = data
  190. })
  191. //渲染完成
  192. onMounted(async () => {
  193. await getProStation()
  194. await getProType()
  195. getDataApi()
  196. })
  197. const getDataApi = async () => {
  198. const form = getObjValue(formInfo.value)
  199. if (!isNullES(form.id)) {
  200. getProDetail(form.id)
  201. }
  202. }
  203. const getProDetail = async (id)=>{
  204. const { error, code, data } = await mainApi.detail(id)
  205. //处理数据
  206. if (!error && code === 200) {
  207. baseForm.value = getObjValue(data)
  208. let list = getArrValue(baseForm.value?.list)
  209. if (list.length > 0) {
  210. selectYear.value = list[0].planYear
  211. }
  212. baseForm.value.startYear = data.startYear.toString()
  213. baseForm.value.endYear = data.endYear.toString()
  214. yearOptions.value = []
  215. list.forEach((ele)=>{
  216. yearOptions.value.push({
  217. value:ele.planYear,
  218. label:ele.planYear,
  219. yearForm:ele,
  220. })
  221. })
  222. } else {
  223. baseForm.value = {}
  224. }
  225. }
  226. const baseForm = ref({ buildScaleUnit:'1' })
  227. const baseFormRules = {
  228. name: {
  229. required: true,
  230. trigger: 'blur',
  231. message: '请输入项目名称',
  232. },
  233. projectStage: {
  234. required: true,
  235. trigger: 'blur',
  236. message: '请选择项目阶段',
  237. },
  238. projectType: {
  239. required: true,
  240. trigger: 'blur',
  241. message: '请选择项目类型',
  242. },
  243. }
  244. const unitSelect = ref('')
  245. //项目阶段
  246. const stateOptions = ref([])
  247. const getProStation = async () => {
  248. stateOptions.value = await getDictionaryData('projectStage', true)
  249. }
  250. //项目类型
  251. const typeOptions = ref([])
  252. const getProType = async () => {
  253. typeOptions.value = await getDictionaryData('projectType', true)
  254. }
  255. const endYearRef = ref(null)
  256. const startYearRef = ref(null)
  257. //开始年
  258. const startYearChange = (val) => {
  259. baseForm.value.startYear = val.toString()
  260. endYearRef.value?.focus()
  261. endYearRef.value?.handleOpen()
  262. startYearRef.value?.handleClose()
  263. }
  264. //结束年
  265. const endYearChange = (val) => {
  266. if (isNullES(val)) {
  267. baseForm.value.startYear = ''
  268. }
  269. baseForm.value.endYear = val.toString()
  270. }
  271. //失去焦点
  272. const endYearBlur = () => {
  273. if (isNullES(baseForm.value.startYear) || isNullES(baseForm.value.endYear)) {
  274. baseForm.value.startYear = ''
  275. baseForm.value.endYear = ''
  276. window.$message.warning('请重新选择完整的范围年份')
  277. }
  278. let years = []
  279. let startYear = baseForm.value.startYear
  280. let endYear = baseForm.value.endYear
  281. for (let year = startYear; year <= endYear; year++) {
  282. years.push(
  283. {
  284. value:year,
  285. label:year,
  286. yearForm:{
  287. planYear:year,
  288. oneInvest:'',
  289. twoInvest:'',
  290. threeInvest:'',
  291. fourInvest:'',
  292. yearlyTarget:'',
  293. onePlan:'',
  294. twoPlan:'',
  295. threePlan:'',
  296. fourPlan:'',
  297. },
  298. },
  299. )
  300. }
  301. yearOptions.value = years
  302. selectYear.value = yearOptions.value[0].value
  303. }
  304. //选择年份
  305. const selectIndex = ref(0)
  306. const yearOptions = ref([{
  307. yearForm:{
  308. yearlyInvest:'',
  309. oneInvest:'',
  310. twoInvest:'',
  311. threeInvest:'',
  312. fourInvest:'',
  313. yearlyTarget:'',
  314. onePlan:'',
  315. twoPlan:'',
  316. threePlan:'',
  317. fourPlan:'',
  318. planYear:'',
  319. },
  320. }])
  321. const selectYear = ref('')
  322. const changeYear = (val)=>{
  323. selectIndex.value = arrIndex(yearOptions.value, 'value', val)
  324. console.log( selectIndex.value, '111111')
  325. }
  326. const formatInput = (value)=>{
  327. // 如果输入为空,则直接返回空字符串
  328. if (!value) {
  329. return ''
  330. }
  331. // 移除非数字和小数点
  332. value = value.replace(/[^\d.]/g, '')
  333. // 使用正则表达式匹配输入是否合法
  334. const regExp = /^\d+(\.\d{0,2})?$/
  335. if (regExp.test(value)) {
  336. return value // 如果输入合法,则返回原始值
  337. } else {
  338. // 如果输入不合法,则移除非法字符,并返回处理后的值
  339. return value.slice(0, -1)
  340. }
  341. }
  342. //监听
  343. watch(() => [
  344. yearOptions.value[selectIndex.value].yearForm.oneInvest,
  345. yearOptions.value[selectIndex.value].yearForm.twoInvest,
  346. yearOptions.value[selectIndex.value].yearForm.threeInvest,
  347. yearOptions.value[selectIndex.value].yearForm.fourInvest,
  348. ], ([key2, key3, key4, key5]) => {
  349. yearOptions.value[selectIndex.value].yearForm.yearlyInvest = Number(key2) + Number(key3) + Number(key4) + Number(key5)
  350. },
  351. )
  352. //取消
  353. const cancelClick = () => {
  354. emit('back')
  355. }
  356. //创建
  357. const formRef = ref(null)
  358. const creatLoading = ref(false)
  359. const createClick = async () => {
  360. const form = formInfo.value
  361. console.log(form)
  362. // if (isNullES(form.id)) cancelClick()
  363. console.log(baseForm.value, 'baseForm.value')
  364. console.log(yearOptions.value, '111111')
  365. let list = []
  366. yearOptions.value.forEach((ele)=>{
  367. let yearForm = ele.yearForm
  368. list.push(yearForm)
  369. })
  370. const isValidate = await formValidate(formRef.value)
  371. if (!isValidate) return false
  372. creatLoading.value = true
  373. //发起请求
  374. const { error, code, msg } = await mainApi.add({
  375. ...baseForm.value,
  376. list,
  377. })
  378. //判断状态
  379. creatLoading.value = false
  380. if (!error && code === 200) {
  381. window?.$message?.success(msg)
  382. console.log(form.id, 'form.id')
  383. if (isNullES(form.id)) {
  384. baseForm.value = {}
  385. yearOptions.value = [{
  386. yearForm:{
  387. yearlyInvest:'',
  388. oneInvest:'',
  389. twoInvest:'',
  390. threeInvest:'',
  391. fourInvest:'',
  392. yearlyTarget:'',
  393. onePlan:'',
  394. twoPlan:'',
  395. threePlan:'',
  396. fourPlan:'',
  397. },
  398. }]
  399. // cancelClick()
  400. }
  401. } else {
  402. window.$message.error(msg ?? '操作失败')
  403. }
  404. console.log('创建')
  405. }
  406. //保存
  407. const saveClick = async () => {
  408. let list = []
  409. yearOptions.value.forEach((ele)=>{
  410. let yearForm = ele.yearForm
  411. list.push(yearForm)
  412. })
  413. const isValidate = await formValidate(formRef.value)
  414. if (!isValidate) return false
  415. creatLoading.value = true
  416. //发起请求
  417. const { error, code, msg } = await mainApi.update({
  418. ...baseForm.value,
  419. list,
  420. })
  421. //判断状态
  422. creatLoading.value = false
  423. if (!error && code === 200) {
  424. window?.$message?.success(msg)
  425. const form = getObjValue(formInfo.value)
  426. getProDetail(form.id)
  427. } else {
  428. window.$message.error(msg ?? '操作失败')
  429. }
  430. console.log('创建')
  431. }
  432. </script>
  433. <style lang="scss">
  434. .create-project .el-card .el-card__body .hc-card-main-body {
  435. padding: 14px;
  436. .el-scrollbar__bar.is-vertical {
  437. right: -16px;
  438. }
  439. }
  440. .hc-card-item-box.year-detail {
  441. padding: 20px;
  442. background: #f7f7f7;
  443. border-radius: 5px;
  444. .hc-card-item-header {
  445. border-bottom: 1px solid #ecebeb;
  446. padding-bottom: 16px;
  447. .item-header {
  448. justify-content: center;
  449. }
  450. }
  451. .hc-form-item-title {
  452. position: relative;
  453. padding: 10px 0;
  454. margin-bottom: 14px;
  455. }
  456. }
  457. .quarter-box {
  458. position: relative;
  459. justify-content: space-around;
  460. }
  461. .form-text {
  462. white-space: nowrap;
  463. color:var(--el-text-color-regular) ;
  464. font-size: var(--el-form-label-font-size);
  465. }
  466. </style>