ProcessForm.vue 20 KB

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