ProcessForm.vue 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571
  1. <template>
  2. <el-form
  3. ref="formRef"
  4. :model="dataForm"
  5. label-width="110px"
  6. :rules="dataRule"
  7. :toggleType="isDetail"
  8. >
  9. <div class="info-wrap" v-if="!isDetail">
  10. <el-row :gutter="20">
  11. <el-col :span="12" :xs="24">
  12. <el-form-item label="长者姓名" prop="elderlyId">
  13. <SelectElder v-model="dataForm.elderlyId" type="2" @elder="handleSelectElder" :tId="dataForm.tenantId"/>
  14. </el-form-item>
  15. </el-col>
  16. <el-col :span="12" :xs="24">
  17. <el-form-item label="身份证号" prop="idCard">
  18. <TgInput v-model="dataForm.idCard" disabled />
  19. </el-form-item>
  20. </el-col>
  21. <el-col :span="12" :xs="24">
  22. <el-form-item label="原护理等级" prop="originalName">
  23. <TgInput v-model="dataForm.originalName" disabled />
  24. </el-form-item>
  25. </el-col>
  26. <el-col :span="12" :xs="24">
  27. <el-form-item label="床位号" prop="bedName">
  28. <TgInput v-model="dataForm.bedName" disabled />
  29. </el-form-item>
  30. </el-col>
  31. <el-col :span="12" :xs="24">
  32. <el-form-item label="变更生效日期" prop="changeDate">
  33. <!-- :disabledDate="(arg) => disabledDate(arg)" -->
  34. <TgDatePicker v-model="dataForm.changeDate" type="date" placeholder="变更生效日期" />
  35. </el-form-item>
  36. </el-col>
  37. <el-col :span="12" :xs="24">
  38. <el-form-item label="原护理费价格" prop="actualAmount">
  39. <TgInput v-model="dataForm.oldActualAmount" disabled />
  40. </el-form-item>
  41. </el-col>
  42. <el-col :span="12" :xs="24">
  43. <el-form-item label="阶段评估" prop="associateId">
  44. <TgSelect v-model="dataForm.associateId" @change="handleChangeAssociate">
  45. <el-option
  46. v-for="(n, i) in evaluationList"
  47. :key="i"
  48. :label="n.processName"
  49. :value="n.evaluationProcessId"
  50. />
  51. </TgSelect>
  52. </el-form-item>
  53. </el-col>
  54. <el-col :span="12" :xs="24">
  55. <el-form-item label="能力评估结果">
  56. <el-button
  57. :disabled="!dataForm.associateId"
  58. style="width: 100%"
  59. @click="handleOpenReport"
  60. ><Icon icon="ep:document" />{{ propertiesName }}</el-button
  61. >
  62. </el-form-item>
  63. </el-col>
  64. <el-col :span="6" :xs="24">
  65. <el-form-item label="新护理等级" prop="expectId">
  66. <TgSelect
  67. v-model="dataForm.expectId"
  68. placeholder="请选择"
  69. :disabled="!dataForm.elderlyId"
  70. clearable
  71. @change="handleChange"
  72. :list="nurseList"
  73. dict-label="chargeName"
  74. dict-value="id"
  75. >
  76. <el-option v-for="t in nurseList" :key="t.id" :label="t.chargeName" :value="t.id" />
  77. </TgSelect>
  78. </el-form-item>
  79. </el-col>
  80. <el-col :span="6" :xs="24">
  81. <el-form-item label="新护理费原价">
  82. <span class="price">¥{{ formatNum(dataForm.amount) }}元/月</span>
  83. </el-form-item>
  84. </el-col>
  85. <el-col :span="12" :xs="24">
  86. <el-form-item label="是否打折">
  87. <el-switch
  88. v-model="dataForm.isDiscount"
  89. inline-prompt
  90. active-text="是"
  91. inactive-text="否"
  92. :active-value="1"
  93. :inactive-value="0"
  94. @change="handleSwicth"
  95. />
  96. </el-form-item>
  97. </el-col>
  98. <template v-if="dataForm.isDiscount==1">
  99. <el-col :span="12" :xs="24">
  100. <el-form-item label="折扣金额(元)" prop="discountAmount">
  101. <TgInput v-model="discountAmount" append-text="¥" @blur="handleBlur(dataForm, 1)" style="width: 10vw;"/>
  102. <el-text style="color: red;margin-left: 2vw">折后金额:{{dataForm.amount-discountAmount}}</el-text>
  103. </el-form-item>
  104. </el-col>
  105. <el-col :span="12" :xs="24">
  106. <el-form-item label="折扣率" prop="discount">
  107. <TgInputNumber v-model="discount" @blur="handleBlur(dataForm, 2)" disabled/>
  108. </el-form-item>
  109. </el-col>
  110. </template>
  111. <el-col :span="24">
  112. <el-form-item prop="reason" label="变更原因">
  113. <TgTextarea v-model="dataForm.reason" />
  114. </el-form-item>
  115. </el-col>
  116. <el-col :span="24">
  117. <el-form-item prop="changeFiles" label="附件">
  118. <SelectUpload
  119. v-model="dataForm.changeFiles"
  120. fun-name="附件"
  121. :elder="{ elderId: dataForm.elderlyId, elderName: dataForm.elderName }"
  122. />
  123. </el-form-item>
  124. </el-col>
  125. </el-row>
  126. </div>
  127. <div v-else>
  128. <div class="info-title">长者信息</div>
  129. <div class="info-wrap">
  130. <el-row :gutter="20">
  131. <el-col :xs="24" :sm="24" :md="24" :lg="processType == 2 ? 24 : 8">
  132. <el-form-item label="长者姓名" prop="elderlyId">
  133. <SelectElder v-model="dataForm.elderlyId" type="1" />
  134. </el-form-item>
  135. </el-col>
  136. <el-col :xs="24" :sm="24" :md="24" :lg="processType == 2 ? 24 : 8">
  137. <el-form-item label="证件号码" prop="idCard">
  138. <TgInput v-model="dataForm.idCard" disabled />
  139. </el-form-item>
  140. </el-col>
  141. <el-col :xs="24" :sm="24" :md="24" :lg="processType == 2 ? 24 : 8">
  142. <el-form-item label="床位号" prop="bedName">
  143. <TgInput v-model="dataForm.bedName" disabled />
  144. </el-form-item>
  145. </el-col>
  146. <!-- <el-col :xs="24" :sm="24" :md="24" :lg="processType == 2 ? 24 : 8">
  147. <el-form-item label="阶段评估" prop="evaluationProcessId">
  148. <TgSelect
  149. v-model="dataForm.evaluationProcessId"
  150. @change="handleChangeAssociate"
  151. :list="evaluationList"
  152. dict-label="processName"
  153. dict-value="evaluationProcessId"
  154. >
  155. <el-option
  156. v-for="(n, i) in evaluationList"
  157. :key="i"
  158. :label="n.processName"
  159. :value="n.evaluationProcessId"
  160. />
  161. </TgSelect>
  162. </el-form-item>
  163. </el-col> -->
  164. <el-col :xs="24" :sm="24" :md="24" :lg="processType == 2 ? 24 : 8">
  165. <el-form-item label="能力评估结果">
  166. <el-button
  167. :disabled="!!!dataForm.evaluationProcessId"
  168. style="width: 200px"
  169. @click="handleOpenReport"
  170. ><Icon icon="ep:document" />{{ propertiesName }}</el-button
  171. >
  172. </el-form-item>
  173. </el-col>
  174. <el-col :xs="24" :sm="24" :md="24" :lg="processType == 2 ? 24 : 8">
  175. <el-form-item label="变更生效日期" prop="changeDate">
  176. <TgDatePicker v-model="dataForm.changeDate" type="date" placeholder="变更生效日期" />
  177. </el-form-item>
  178. </el-col>
  179. </el-row>
  180. </div>
  181. <div class="info-title">变更前</div>
  182. <div class="info-wrap">
  183. <el-row :gutter="20">
  184. <el-col :xs="24" :sm="24" :md="24" :lg="processType == 2 ? 24 : 8">
  185. <el-form-item label="护理等级" prop="originalName">
  186. <TgInput v-model="dataForm.originalName" />
  187. </el-form-item>
  188. </el-col>
  189. <el-col :xs="24" :sm="24" :md="24" :lg="processType == 2 ? 24 : 8">
  190. <el-form-item label="护理标准价格" prop="originalAmount">
  191. <TgInput v-model="dataForm.originalAmount" />
  192. </el-form-item>
  193. </el-col>
  194. <el-col :xs="24" :sm="24" :md="24" :lg="processType == 2 ? 24 : 8">
  195. <el-form-item label="是否打折" prop="originalIsDiscount">
  196. <TgSwitch v-model="dataForm.originalIsDiscount" />
  197. </el-form-item>
  198. </el-col>
  199. </el-row>
  200. </div>
  201. <div class="info-title">变更后</div>
  202. <div class="info-wrap">
  203. <el-row>
  204. <el-col :xs="24" :sm="24" :md="24" :lg="processType == 2 ? 24 : 8">
  205. <el-form-item label="护理等级" prop="expectId">
  206. <TgSelect
  207. v-model="dataForm.expectId"
  208. placeholder="请选择"
  209. clearable
  210. @change="handleChange"
  211. :list="nurseList"
  212. dict-label="chargeName"
  213. dict-value="id"
  214. >
  215. <el-option v-for="t in nurseList" :key="t.id" :label="t.chargeName" :value="t.id" />
  216. </TgSelect>
  217. </el-form-item>
  218. </el-col>
  219. <el-col :xs="24" :sm="24" :md="24" :lg="processType == 2 ? 24 : 8">
  220. <el-form-item label="护理标准价格" prop="actualAmount">
  221. {{ formatNum(dataForm.amount) }}
  222. </el-form-item>
  223. </el-col>
  224. <el-col :xs="24" :sm="24" :md="24" :lg="processType == 2 ? 24 : 8">
  225. <el-form-item :label="(diffValueStr(dataForm)==0?'':diffValueStr(dataForm)>0?'需补缴':'需退款')" prop="actualAmount">
  226. <el-text style="font-weight: bold;color: red">{{ Math.abs(diffValueStr(dataForm)).toFixed(2) }}</el-text>
  227. </el-form-item>
  228. </el-col>
  229. <el-col :xs="24" :sm="24" :md="24" :lg="processType == 2 ? 24 : 8">
  230. <el-form-item label="是否打折" prop="isDiscount">
  231. <TgSwitch v-model="dataForm.isDiscount" />
  232. </el-form-item>
  233. </el-col>
  234. <el-col :xs="24" :sm="24" :md="24" :lg="processType == 2 ? 24 : 8" v-show="dataForm.isDiscount==1">
  235. <el-form-item label="折后价格" prop="actualAmount">
  236. {{ formatNum(dataForm.actualAmount) }}
  237. </el-form-item>
  238. </el-col>
  239. <el-col :span="24">
  240. <el-form-item label="变更原因" prop="reason">
  241. <TgTextarea v-model="dataForm.reason" />
  242. </el-form-item>
  243. </el-col>
  244. <el-col :span="24">
  245. <el-form-item prop="changeFiles" label="附件">
  246. <SelectUpload
  247. v-model="dataForm.changeFiles"
  248. fun-name="附件"
  249. :elder="{ elderId: dataForm.elderlyId, elderName: dataForm.elderName }"
  250. :is-detail="isDetail"
  251. />
  252. </el-form-item>
  253. </el-col>
  254. </el-row>
  255. </div>
  256. </div>
  257. </el-form>
  258. <EvaluationDetail ref="reportRef" />
  259. </template>
  260. <script setup lang="ts">
  261. import { getNursingLevelPage } from '@/api/elderly/nursing'
  262. import { getOverheadListByType } from '@/api/elderly/fee/overheadCharge'
  263. import { getChargeCategoryTree } from '@/api/elderly/fee/chargeCategory'
  264. import { filteredTreeData, findTreeNode } from '@/utils/tree'
  265. import { formatTime, getParentNodesById } from '@/utils'
  266. import { formatNum } from '@/utils/formatter'
  267. import { getBusinessId } from '@/api/elderly/common'
  268. import { getNurseChangeRecordById, getEvaluationByElderId } from '@/api/elderly/elder/nurse-change'
  269. import EvaluationDetail from '@/views/elderly/assess/synthetic-ability/Detail.vue'
  270. import { getEvaluationProcessConfigList } from '@/api/elderly/assess/evaluation-process'
  271. import { getSyntheticAbilityName } from '@/utils/synthetic-ability'
  272. import { nurseChangeFormType } from '../types'
  273. import { getTenantId } from '@/utils/auth'
  274. defineOptions({ name: 'NurseChangeProcessForm' })
  275. const formRef = ref() // 表单 Ref
  276. const state = reactive<nurseChangeFormType>({
  277. dataForm: {
  278. id: '',
  279. elderlyId: '',
  280. elderName: '',
  281. idCard: '',
  282. originalName: '',
  283. originalId: '',
  284. bedName: '',
  285. categoryName: '',
  286. overheadChargeId: '',
  287. expectOverheadChargeId: '',
  288. expectId: '',
  289. expectName: '',
  290. changeDate: formatTime(Date.now(), 'yyyy-MM-dd'),
  291. associateId: '',
  292. isDiscount: '',
  293. amount: 0,
  294. discountAmount: '',
  295. discount: undefined,
  296. actualAmount: 0,
  297. originalAmount: undefined,
  298. originalIsDiscount: undefined,
  299. evaluationProcessId: undefined,
  300. reason: '',
  301. changeFiles: [],
  302. startTenantId: '', // 流程租户id
  303. tenantId: undefined,
  304. },
  305. dataRule: {
  306. elderlyId: [{ required: true, message: '长者不能为空', trigger: 'blur' }],
  307. changeDate: [{ required: true, message: '变更生效日期不能为空', trigger: 'blur' }],
  308. expectId: [{ required: true, message: '新护理等级不能为空', trigger: 'blur' }],
  309. expectOverheadChargeId: [{ required: true, message: '护理标准不能为空', trigger: 'blur' }],
  310. // associateId: [{ required: true, message: '阶段评估不能为空', trigger: 'blur' }],
  311. discountAmount: [{ required: true, message: '折扣金额不能为空', trigger: 'blur' }],
  312. discount: [{ required: true, message: '折扣率不能为空', trigger: 'blur' }]
  313. }
  314. })
  315. const { dataForm, dataRule } = toRefs(state)
  316. const resetFormField = reactive({ ...dataForm.value })
  317. const loading = ref(false)
  318. const discountAmount = ref()
  319. const discount = ref()
  320. const isDetail = ref(false)
  321. /** 打开弹窗 */
  322. const init = async (id, detail, status) => {
  323. dataForm.value.startTenantId = getTenantId()
  324. dataForm.value.tenantId = getTenantId()
  325. await getTreeData()
  326. await getNurseLevelList()
  327. isDetail.value = detail
  328. if (id) {
  329. const res = await getNurseChangeRecordById(id, status,isDetail.value)
  330. dataForm.value = res
  331. dataForm.value.changeFiles = res.changeFiles ? JSON.parse(res.changeFiles) : []
  332. dataForm.value.associateId = res.evaluationProcessId
  333. discount.value = formatNum(res.discount)
  334. discountAmount.value = formatNum(res.discountAmount)
  335. syntheticAbilityId.value = res.syntheticAbilityId
  336. await getEvaluation()
  337. active.value = getSyntheticAbilityName(res.totalScore)
  338. if(!res.startTenantId){
  339. dataForm.value.startTenantId = getTenantId()
  340. }else {
  341. dataForm.value.tenantId = dataForm.value.startTenantId
  342. }
  343. }
  344. await getOverheadList()
  345. if(id){
  346. handleChange(1)
  347. }
  348. }
  349. const submitForm = async () => {
  350. // 校验表单
  351. if (!formRef.value) return
  352. const valid = await formRef.value.validate()
  353. if (!valid) return
  354. return {
  355. valid,
  356. dataForm: {
  357. ...dataForm.value,
  358. changeFiles: JSON.stringify(dataForm.value.changeFiles),
  359. type: 5 // 护理变更
  360. }
  361. }
  362. }
  363. const nurseLevelList = ref<{ nurseLevelName: string; id: string | number }[]>([])
  364. const getNurseLevelList = async () => {
  365. try {
  366. const data = await getNursingLevelPage({
  367. pageNum: 1,
  368. pageSize: 100
  369. })
  370. nurseLevelList.value = data.list
  371. } finally {
  372. }
  373. }
  374. // 查询评估记录表
  375. const evaluationList = ref<
  376. {
  377. evaluationProcessId: string
  378. processName: string
  379. syntheticAbilityId: number
  380. type: string
  381. totalScore: string
  382. }[]
  383. >([])
  384. const propertiesName = ref('') // 评估登记
  385. const getEvaluation = async () => {
  386. const res = await getEvaluationByElderId(dataForm.value.elderlyId)
  387. evaluationList.value = res
  388. // 获取对应的分数段
  389. const result = res[0] && res[0].evaluationProcessId ? await getEvaluationProcessConfigList({
  390. evaluationProcessId: res[0].evaluationProcessId
  391. }) : []
  392. const arr = [...result, {propertiesName: '未评估'}]
  393. // 找到对应的分数段
  394. if (res.totalScore && res.totalScore >= 0 && res.syntheticAbilityInfoList.length) {
  395. for (let i = 0; i < arr.length; i++) {
  396. if (Number(res.totalScore) >= arr[i].minValue && Number(res.totalScore) <= arr[i].maxValue) {
  397. propertiesName.value = arr[i].propertiesName || '查看'
  398. return false
  399. }
  400. }
  401. } else {
  402. propertiesName.value = arr[arr.length - 1].propertiesName
  403. }
  404. }
  405. const diffValueStr = (dataForm) =>{
  406. try {
  407. return parseFloat((dataForm.actualAmount - dataForm.originalAmount).toFixed(2))
  408. }catch (_) {}
  409. return 0
  410. }
  411. // 护理标准
  412. const nurseList = ref<{ chargeName: string; id: string; price: number; superiorsId: string }[]>([])
  413. const getOverheadList = async () => {
  414. const res = await getOverheadListByType(2, dataForm.value.startTenantId)
  415. nurseList.value = res
  416. }
  417. // 项目类别
  418. const treeList = ref()
  419. const getTreeData = async () => {
  420. try {
  421. loading.value = true
  422. const data = await getChargeCategoryTree()
  423. treeList.value = filteredTreeData(data, 'childrenList')
  424. } catch (err) {
  425. console.log('err', err)
  426. } finally {
  427. loading.value = false
  428. }
  429. }
  430. // 护理标准
  431. const handleChange = (type=2) => {
  432. dataForm.value.expectOverheadChargeId = dataForm.value.expectId
  433. const item = nurseList.value.find((item) => item.id == dataForm.value.expectId)
  434. dataForm.value.expectName = item?.chargeName
  435. dataForm.value.amount = Number(item?.price)
  436. // 在tree中找到这棵树的上一级
  437. let node = findTreeNode(treeList.value, item?.superiorsId, 'id', 'childrenList')
  438. // 找到对应的名称
  439. const res = getParentNodesById(treeList.value, node.parentId, node.id)
  440. // 只保留最后两位
  441. if(res.length - 2 > 0){
  442. for(let i = 0; i <= res.length - 2; i++){
  443. res.pop()
  444. }
  445. }
  446. dataForm.value.categoryName = res.reverse().join('-')
  447. if(type!=1){
  448. handleSwicth()
  449. }
  450. // nurseList.value.map((item)=>{
  451. // if(item.id==overheadChargeId){
  452. // dataForm.value.originalAmount = item.price
  453. // }
  454. // })
  455. // 如果没有打折
  456. if(dataForm.value.isDiscount!=1){
  457. dataForm.value.actualAmount = dataForm.value.amount
  458. }else{
  459. handleBlur(dataForm.value, 1)
  460. }
  461. }
  462. // 折扣和折扣率换算
  463. const handleBlur = (item, type = 0) => {
  464. if (type == 1) {
  465. // 折扣价格
  466. item.discountAmount = discountAmount.value
  467. item.actualAmount = item.amount - discountAmount.value
  468. item.discount = item.discountAmount ? (1000 - (item.discountAmount / item.amount) * 1000) * 10 / 1000 : ''
  469. discount.value = item.discount
  470. } else if (type == 2) {
  471. item.discount = discount.value
  472. item.actualAmount = item.amount * (((item.discount / 100) * 10 * 100) / 100)
  473. item.discountAmount = ((item.amount * (1 - item.discount / 10)) / 10) * 10
  474. discountAmount.value = formatNum(((item.amount * (1 - item.discount / 10)) / 10) * 10)
  475. }
  476. item.totalAmount = item.isDiscount
  477. ? item.discount
  478. ? item.actualAmount
  479. : item.amount
  480. : item.amount
  481. }
  482. // 是否打折
  483. const handleSwicth = () => {
  484. if(!isDetail.value){
  485. dataForm.value.discountAmount = ''
  486. dataForm.value.actualAmount = 0
  487. dataForm.value.discount = undefined
  488. discount.value = undefined
  489. discountAmount.value = ''
  490. }
  491. }
  492. //let overheadChargeId = 0
  493. // 选择长者
  494. const handleSelectElder = (item) => {
  495. dataForm.value.idCard = item.idCard
  496. dataForm.value.bedName = item.bedName
  497. dataForm.value.originalName = item.itemName
  498. dataForm.value.overheadChargeId = item.overheadChargeId
  499. dataForm.value.originalId = item.originalId
  500. dataForm.value.associateId = '' // 清空评估表
  501. dataForm.value.elderName = item.elderName
  502. dataForm.value.originalAmount = item.actualAmount
  503. dataForm.value.oldActualAmount = item.actualAmount
  504. //overheadChargeId = item.overheadChargeId
  505. getEvaluation()
  506. }
  507. /** 重置表单 */
  508. const resetForm = () => {
  509. dataForm.value = {...resetFormField}
  510. formRef.value?.resetFields()
  511. }
  512. const active = ref()
  513. // 得到评估报告id
  514. const syntheticAbilityId = ref()
  515. const handleChangeAssociate = (val) => {
  516. let item = evaluationList.value.find((item) => item.evaluationProcessId == val)
  517. syntheticAbilityId.value = item?.syntheticAbilityId
  518. // 评估结果
  519. active.value = getSyntheticAbilityName(item?.totalScore)
  520. }
  521. // 打开评估报告
  522. const reportRef = ref()
  523. const handleOpenReport = () => {
  524. reportRef.value.open(syntheticAbilityId.value)
  525. }
  526. // 根据流程获取业务id
  527. const processType = ref()
  528. const getProcess = async (id, type, status) => {
  529. const res = await getBusinessId(id)
  530. init(res.businessId, true, status)
  531. processType.value = type
  532. }
  533. const disabledDate = (time) =>{
  534. const now = new Date()
  535. const startOfMonth = new Date(now.getFullYear(), now.getMonth(), 1)
  536. const endOfMonth = new Date(now.getFullYear(), now.getMonth() + 1, 0)
  537. return time < startOfMonth || time > endOfMonth
  538. }
  539. const setTenantId = (tId) => {
  540. dataForm.value.tenantId = tId
  541. }
  542. defineExpose({ init, submitForm, resetForm, getProcess, setTenantId }) // 提供 open 方法,用于打开弹窗
  543. </script>