add.vue 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. <template>
  2. <div class="app-container">
  3. <van-form ref="formRef" @submit="onSubmit" required="auto">
  4. <h4 class="mb8 mt8">灭菌信息</h4>
  5. <van-cell-group>
  6. <van-field
  7. v-model="state.form.recordDate"
  8. label="日期"
  9. placeholder="请选择日期"
  10. :readonly="isDetail"
  11. :rules="isDetail ? [] : [{ required: true, message: '请选择日期' }]"
  12. @click="isDetail || (showDatePicker = true)"
  13. />
  14. <van-field
  15. v-model="state.form.operator"
  16. label="实验/移交人"
  17. placeholder="当前用户"
  18. readonly
  19. />
  20. </van-cell-group>
  21. <h4 class="mb8 mt8">灭菌物品</h4>
  22. <van-cell-group>
  23. <van-field label="选择灭菌物品">
  24. <template #input>
  25. <van-checkbox-group v-model="state.checkedItems" direction="horizontal">
  26. <van-checkbox style="margin-bottom:15px;" name="10" shape="square" :disabled="isDetail">实验固体废弃物</van-checkbox>
  27. <van-checkbox style="margin-bottom:15px;" name="20" shape="square" :disabled="isDetail">防护物品固体废弃物</van-checkbox>
  28. <van-checkbox style="margin-bottom:15px;" name="30" shape="square" :disabled="isDetail">需重复使用的器皿</van-checkbox>
  29. <van-checkbox name="40" shape="square" :disabled="isDetail">液体废弃物</van-checkbox>
  30. </van-checkbox-group>
  31. </template>
  32. </van-field>
  33. <van-field
  34. v-if="state.checkedItems.includes('40')"
  35. v-model="state.form.liquidWasteDesc"
  36. label="液体废弃物名称"
  37. placeholder="请填写液体废弃物名称"
  38. maxlength="255"
  39. :readonly="isDetail"
  40. />
  41. </van-cell-group>
  42. <h4 class="mb8 mt8">灭菌详情</h4>
  43. <van-cell-group>
  44. <van-field
  45. v-model="state.form.quantity"
  46. label="数量/袋"
  47. placeholder="如:5"
  48. maxlength="255"
  49. :readonly="isDetail"
  50. :rules="isDetail ? [] : [{ required: true, message: '请输入数量/袋' }]"
  51. />
  52. <van-field name="uploader" label="灭菌物理监测">
  53. <template #input>
  54. <template v-if="isDetail">
  55. <a v-if="state.form.monitorAttachment" :href="state.form.monitorAttachment" target="_blank" style="color:#3c78e3">{{ state.form.monitorAttachmentName || '查看附件' }}</a>
  56. <span v-else>-</span>
  57. </template>
  58. <van-uploader v-else v-model="state.fileList" :after-read="afterRead" preview-size="60" :preview-full-image="true" :max-count="1" />
  59. </template>
  60. </van-field>
  61. <van-field
  62. v-model="state.form.duration"
  63. label="灭菌时长/min"
  64. placeholder="如:30"
  65. maxlength="225"
  66. :readonly="isDetail"
  67. :rules="isDetail ? [] : [{ required: true, message: '请输入灭菌时长' }]"
  68. />
  69. </van-cell-group>
  70. <h4 class="mb8 mt8">仪器状态</h4>
  71. <van-cell-group>
  72. <van-field label="状态" :rules="isDetail ? [] : [{ required: true, message: '请选择仪器状态' }]">
  73. <template #input>
  74. <van-radio-group v-model="state.form.instrumentStatus" direction="horizontal">
  75. <van-radio name="10" :disabled="isDetail">正常</van-radio>
  76. <van-radio name="20" :disabled="isDetail">故障</van-radio>
  77. </van-radio-group>
  78. </template>
  79. </van-field>
  80. <van-field
  81. v-if="state.form.instrumentStatus === '20'"
  82. v-model="state.form.faultDesc"
  83. label="故障描述"
  84. placeholder="请描述故障情况"
  85. maxlength="512"
  86. type="textarea"
  87. rows="2"
  88. autosize
  89. :readonly="isDetail"
  90. />
  91. </van-cell-group>
  92. <van-action-bar placeholder>
  93. <van-action-bar-icon icon="wap-home-o" text="首页" @click="router.push('/home')" />
  94. <van-action-bar-icon icon="revoke" text="返回" @click="router.push('/sterilization')" />
  95. <van-action-bar-button v-if="!isDetail" type="primary" :text="isEditMode ? '保存修改' : '立即提交'" :loading="submitting" native-type="submit" />
  96. </van-action-bar>
  97. </van-form>
  98. <van-popup v-model:show="showDatePicker" position="bottom">
  99. <van-date-picker v-model="currentDate" title="选择日期" @confirm="onConfirmDate" @cancel="showDatePicker = false" />
  100. </van-popup>
  101. </div>
  102. </template>
  103. <script lang="ts" setup>
  104. import to from 'await-to-js'
  105. import { computed, onMounted, reactive, ref } from 'vue'
  106. import { useRouter, useRoute } from 'vue-router'
  107. import { useSterilizationApi } from '/@/api/sterilization'
  108. import { useUserInfo } from '/@/stores/userInfo'
  109. import { formatDate } from '/@/utils/formatTime'
  110. import { handleUpload } from '/@/utils/upload'
  111. import { showNotify } from 'vant'
  112. const router = useRouter()
  113. const route = useRoute()
  114. const sterilizationApi = useSterilizationApi()
  115. const userStore = useUserInfo()
  116. const formRef = ref()
  117. const showDatePicker = ref(false)
  118. const currentDate = ref([new Date().getFullYear(), new Date().getMonth() + 1, new Date().getDate()])
  119. const submitting = ref(false)
  120. const pageMode = computed(() => (route.query.mode as string) || 'add')
  121. const isDetail = computed(() => pageMode.value === 'detail')
  122. const isEditMode = computed(() => pageMode.value === 'edit')
  123. const state = reactive({
  124. form: {
  125. id: 0,
  126. recordDate: formatDate(new Date(), 'YYYY-mm-dd'),
  127. operatorId: 0,
  128. operator: '',
  129. sterilizationItems: '',
  130. liquidWasteDesc: '',
  131. quantity: '',
  132. monitorAttachment: '',
  133. monitorAttachmentName: '',
  134. duration: '',
  135. instrumentStatus: '10',
  136. faultDesc: '',
  137. },
  138. checkedItems: [] as string[],
  139. fileList: [] as any[],
  140. })
  141. const onConfirmDate = () => {
  142. showDatePicker.value = false
  143. state.form.recordDate = `${currentDate.value[0]}-${String(currentDate.value[1]).padStart(2, '0')}-${String(currentDate.value[2]).padStart(2, '0')}`
  144. }
  145. const initForm = () => {
  146. const u = userStore.userInfos
  147. state.form.operatorId = u.id
  148. state.form.operator = u.nickName || ''
  149. state.form.recordDate = formatDate(new Date(), 'YYYY-mm-dd')
  150. }
  151. const loadData = async (id: number) => {
  152. const [err, res]: any = await to(sterilizationApi.getById({ id }))
  153. if (err) return
  154. const d = res?.data
  155. if (d) {
  156. state.form = {
  157. id: d.id || 0,
  158. recordDate: d.recordDate ? d.recordDate.slice(0, 10) : '',
  159. operatorId: d.operatorId || 0,
  160. operator: d.operator || '',
  161. sterilizationItems: d.sterilizationItems || '',
  162. liquidWasteDesc: d.liquidWasteDesc || '',
  163. quantity: d.quantity || '',
  164. monitorAttachment: d.monitorAttachment || '',
  165. monitorAttachmentName: d.monitorAttachmentName || '',
  166. duration: d.duration || '',
  167. instrumentStatus: d.instrumentStatus || '10',
  168. faultDesc: d.faultDesc || '',
  169. }
  170. state.checkedItems = d.sterilizationItems ? d.sterilizationItems.split(',').filter(Boolean) : []
  171. if (d.monitorAttachment) {
  172. state.fileList = [{ name: d.monitorAttachmentName || d.monitorAttachment.split('/').pop() || '附件', url: d.monitorAttachment }]
  173. }
  174. }
  175. }
  176. const afterRead = async (file: any) => {
  177. file.status = 'uploading'
  178. const [err, res]: ToResponse = await to(handleUpload(file.file))
  179. if (err) {
  180. file.status = 'failed'
  181. return
  182. }
  183. file.status = 'success'
  184. file.url = res as string
  185. file.name = file.file.name
  186. state.form.monitorAttachment = res as string
  187. state.form.monitorAttachmentName = file.file.name
  188. }
  189. const onSubmit = async () => {
  190. const [errValid] = await to(formRef.value.validate())
  191. if (errValid) return
  192. if (state.checkedItems.length === 0) {
  193. showNotify({ type: 'warning', message: '请至少选择一项灭菌物品' })
  194. return
  195. }
  196. submitting.value = true
  197. state.form.sterilizationItems = state.checkedItems.join(',')
  198. const params = JSON.parse(JSON.stringify(state.form))
  199. const post = isEditMode.value ? sterilizationApi.update : sterilizationApi.create
  200. const [err]: any = await to(post(params))
  201. submitting.value = false
  202. if (err) return
  203. showNotify({ type: 'success', message: isEditMode.value ? '修改成功' : '新增成功' })
  204. setTimeout(() => {
  205. router.push('/sterilization')
  206. }, 1000)
  207. }
  208. onMounted(async () => {
  209. const id = route.query.id
  210. if (id) {
  211. await loadData(Number(id))
  212. } else {
  213. initForm()
  214. }
  215. })
  216. </script>
  217. <style lang="scss" scoped>
  218. .app-container {
  219. h4 {
  220. margin: 10px 0;
  221. height: 20px;
  222. line-height: 20px;
  223. padding-left: 16px;
  224. &::before {
  225. display: inline-block;
  226. content: '';
  227. background-color: #3c78e3;
  228. width: 4px;
  229. height: 20px;
  230. margin-right: 4px;
  231. vertical-align: top;
  232. }
  233. }
  234. }
  235. </style>