vision-input.vue 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. <template>
  2. <view class="page">
  3. <view class="bg-gradient"></view>
  4. <van-nav-bar :title="inputType === 'vision' ? '视力录入' : '屈光度录入'" left-arrow @click-left="onBack" fixed :z-index="999" />
  5. <view class="header">
  6. <view class="student-info">
  7. <view class="info-row">
  8. <image class="gender-icon" :src="studentInfo.gender === '男' ? '/static/images/icon/man.png' : '/static/images/icon/woman.png'" mode="aspectFit"></image>
  9. <text class="student-name">{{ studentInfo.name }}</text>
  10. </view>
  11. <view class="detail-row">
  12. <text>学校:{{ schoolName }}</text>
  13. </view>
  14. <view class="detail-row">
  15. <text>班级:{{ studentInfo.class }}</text>
  16. </view>
  17. <view class="detail-row">
  18. <text>身份证:{{ studentInfo.idCard }}</text>
  19. </view>
  20. </view>
  21. </view>
  22. <view class="content">
  23. <view class="section-header">
  24. <text class="section-title">眼科检查</text>
  25. </view>
  26. <view class="form-item" v-if="inputType === 'vision'">
  27. <text class="label">左眼远视力</text>
  28. <input class="value-input" v-model="formData.leftVision" type="digit" placeholder="请输入" @blur="formatVision('leftVision')" />
  29. </view>
  30. <view class="form-item" v-if="inputType === 'vision'">
  31. <text class="label">右眼远视力</text>
  32. <input class="value-input" v-model="formData.rightVision" type="digit" placeholder="请输入" @blur="formatVision('rightVision')" />
  33. </view>
  34. <view class="form-item" v-if="inputType === 'refraction'">
  35. <text class="label">左眼屈光度</text>
  36. <input class="value-input" v-model="formData.leftRefraction" type="number" placeholder="请输入" />
  37. </view>
  38. <view class="form-item" v-if="inputType === 'refraction'">
  39. <text class="label">右眼屈光度</text>
  40. <input class="value-input" v-model="formData.rightRefraction" type="number" placeholder="请输入" />
  41. </view>
  42. </view>
  43. <view class="footer">
  44. <view class="footer-btns">
  45. <van-button plain type="primary" round size="large" @click="onBack" icon="replay">返回</van-button>
  46. <van-button type="primary" round size="large" icon="success" @click="handleSave">保存</van-button>
  47. </view>
  48. </view>
  49. </view>
  50. </template>
  51. <script setup>
  52. import { inputVisionData, inputRefractionData } from '@/services/common'
  53. const STORAGE_KEY = 'eye_examine_user_info'
  54. const userInfo = ref({})
  55. const studentInfo = ref({})
  56. const inputType = ref('')
  57. const visionDataId = ref('')
  58. const schoolName = ref('')
  59. const formData = ref({
  60. leftVision: '',
  61. rightVision: '',
  62. leftRefraction: '',
  63. rightRefraction: ''
  64. })
  65. onLoad((options) => {
  66. studentInfo.value = {
  67. id: options.studentId || '',
  68. name: decodeURIComponent(options.studentName || ''),
  69. gender: decodeURIComponent(options.studentGender || ''),
  70. idCard: decodeURIComponent(options.studentIdCard || ''),
  71. classId: options.classId || '',
  72. class: `${decodeURIComponent(options.grade || '')} ${decodeURIComponent(options.className || '')}`
  73. }
  74. inputType.value = options.type || ''
  75. visionDataId.value = options.visionDataId || ''
  76. schoolName.value = decodeURIComponent(options.schoolName || '')
  77. userInfo.value = {
  78. name: decodeURIComponent(options.userName || ''),
  79. phone: decodeURIComponent(options.userPhone || ''),
  80. organization: decodeURIComponent(options.userOrg || '')
  81. }
  82. })
  83. const onBack = () => {
  84. uni.navigateBack({
  85. delta: 1
  86. })
  87. }
  88. const formatVision = (field) => {
  89. const value = parseFloat(formData.value[field])
  90. if (!isNaN(value)) {
  91. formData.value[field] = value.toFixed(1)
  92. }
  93. }
  94. const handleSave = async () => {
  95. if (inputType.value === 'vision') {
  96. if (!formData.value.leftVision || !formData.value.rightVision) {
  97. return uni.showToast({
  98. title: '请填写完整视力信息',
  99. icon: 'none'
  100. })
  101. }
  102. try {
  103. const params = {
  104. student_id: parseInt(studentInfo.value.id),
  105. left_eye_vision: parseFloat(formData.value.leftVision),
  106. right_eye_vision: parseFloat(formData.value.rightVision),
  107. input_user: userInfo.value.name,
  108. operator_phone: userInfo.value.phone
  109. }
  110. if (visionDataId.value) {
  111. params.vision_data_id = visionDataId.value
  112. }
  113. const res = await inputVisionData(params)
  114. if (res && res.code === 200) {
  115. uni.showToast({
  116. title: '保存成功',
  117. icon: 'success',
  118. duration: 1000
  119. })
  120. setTimeout(() => {
  121. uni.navigateBack({ delta: 2 })
  122. }, 1000)
  123. }
  124. } catch (error) {
  125. console.error('保存视力数据失败', error)
  126. }
  127. } else if (inputType.value === 'refraction') {
  128. if (!formData.value.leftRefraction || !formData.value.rightRefraction) {
  129. return uni.showToast({
  130. title: '请填写完整屈光度信息',
  131. icon: 'none'
  132. })
  133. }
  134. try {
  135. const params = {
  136. student_id: parseInt(studentInfo.value.id),
  137. left_eye_refraction: parseFloat(formData.value.leftRefraction),
  138. right_eye_refraction: parseFloat(formData.value.rightRefraction),
  139. input_user: userInfo.value.name,
  140. operator_phone: userInfo.value.phone
  141. }
  142. if (visionDataId.value) {
  143. params.vision_data_id = visionDataId.value
  144. }
  145. const res = await inputRefractionData(params)
  146. if (res && res.code === 200) {
  147. uni.showToast({
  148. title: '保存成功',
  149. icon: 'success',
  150. duration: 1000
  151. })
  152. setTimeout(() => {
  153. uni.navigateBack({ delta: 2 })
  154. }, 1000)
  155. }
  156. } catch (error) {
  157. console.error('保存屈光度数据失败', error)
  158. }
  159. }
  160. }
  161. </script>
  162. <style lang="scss" scoped>
  163. .page {
  164. min-height: 100vh;
  165. position: relative;
  166. }
  167. .bg-gradient {
  168. position: fixed;
  169. top: 0;
  170. left: 0;
  171. right: 0;
  172. bottom: 0;
  173. background: linear-gradient(180deg, #4A9FF5 0%, #E8F5FF 100%);
  174. z-index: 0;
  175. pointer-events: none;
  176. }
  177. .header {
  178. padding: 20rpx 30rpx;
  179. padding-top: calc(20rpx + 46px);
  180. position: relative;
  181. z-index: 1;
  182. }
  183. .student-info {
  184. background: rgba(255, 255, 255, 0.9);
  185. border-radius: 20rpx;
  186. padding: 30rpx;
  187. }
  188. .info-row {
  189. display: flex;
  190. align-items: center;
  191. margin-bottom: 20rpx;
  192. }
  193. .gender-icon {
  194. width: 40rpx;
  195. height: 40rpx;
  196. margin-right: 10rpx;
  197. }
  198. .student-name {
  199. font-size: 32rpx;
  200. font-weight: bold;
  201. color: #333;
  202. }
  203. .detail-row {
  204. font-size: 26rpx;
  205. color: #666;
  206. margin-top: 10rpx;
  207. }
  208. .content {
  209. padding: 30rpx;
  210. position: relative;
  211. z-index: 1;
  212. padding-bottom: 150rpx;
  213. }
  214. .section-header {
  215. display: flex;
  216. align-items: center;
  217. justify-content: space-between;
  218. margin-bottom: 20rpx;
  219. }
  220. .section-title {
  221. font-size: 32rpx;
  222. font-weight: bold;
  223. color: #333;
  224. }
  225. .form-item {
  226. background: #fff;
  227. border-radius: 20rpx;
  228. padding: 30rpx;
  229. margin-bottom: 20rpx;
  230. display: flex;
  231. align-items: center;
  232. justify-content: space-between;
  233. }
  234. .label {
  235. font-size: 28rpx;
  236. color: #333;
  237. }
  238. .value {
  239. font-size: 32rpx;
  240. font-weight: bold;
  241. color: #0063F5;
  242. flex: 1;
  243. text-align: center;
  244. }
  245. .value-input {
  246. font-size: 32rpx;
  247. font-weight: bold;
  248. color: #0063F5;
  249. flex: 1;
  250. text-align: center;
  251. }
  252. .edit-icon {
  253. width: 40rpx;
  254. height: 40rpx;
  255. }
  256. .footer {
  257. position: fixed;
  258. bottom: 0;
  259. left: 0;
  260. right: 0;
  261. padding: 30rpx;
  262. background: #fff;
  263. z-index: 10;
  264. }
  265. .footer-btns {
  266. display: flex;
  267. gap: 20rpx;
  268. button {
  269. flex: 1;
  270. }
  271. }
  272. </style>