BasicVitalsStep.vue 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  1. <!-- DEPRECATED: 已由 ComprehensiveSurvey.vue 替代,待确认无引用后清理(2026-10-16 标记) -->
  2. <template>
  3. <view class="vitals-step">
  4. <view class="step-title-row">
  5. <text class="step-title">基础体征</text>
  6. <text class="step-sub">填写身高、体重、血压、血糖等基础指标</text>
  7. </view>
  8. <!-- 身高 -->
  9. <view class="form-card">
  10. <view class="card-head">
  11. <text class="card-title">身高 (cm)</text>
  12. <view class="quick-chips">
  13. <view
  14. class="quick-chip"
  15. :class="{ 'quick-chip-on': heightQuick === 'normal' }"
  16. @click="setHeightQuick('normal')"
  17. ><text>正常</text></view>
  18. <view
  19. class="quick-chip"
  20. :class="{ 'quick-chip-on': heightQuick === 'high' }"
  21. @click="setHeightQuick('high')"
  22. ><text>偏高</text></view>
  23. <view
  24. class="quick-chip"
  25. :class="{ 'quick-chip-on': heightQuick === 'low' }"
  26. @click="setHeightQuick('low')"
  27. ><text>偏低</text></view>
  28. </view>
  29. </view>
  30. <input class="num-input" type="digit" v-model="inner.heightCm" placeholder="如 170"
  31. @input="onInput" />
  32. <text class="unit-hint">单位:厘米</text>
  33. </view>
  34. <!-- 体重 -->
  35. <view class="form-card">
  36. <view class="card-head">
  37. <text class="card-title">体重 (kg)</text>
  38. <view class="quick-chips">
  39. <view
  40. class="quick-chip"
  41. :class="{ 'quick-chip-on': weightQuick === 'normal' }"
  42. @click="setWeightQuick('normal')"
  43. ><text>正常</text></view>
  44. <view
  45. class="quick-chip"
  46. :class="{ 'quick-chip-on': weightQuick === 'high' }"
  47. @click="setWeightQuick('high')"
  48. ><text>偏重</text></view>
  49. <view
  50. class="quick-chip"
  51. :class="{ 'quick-chip-on': weightQuick === 'low' }"
  52. @click="setWeightQuick('low')"
  53. ><text>偏轻</text></view>
  54. </view>
  55. </view>
  56. <input class="num-input" type="digit" v-model="inner.weightKg" placeholder="如 60"
  57. @input="onInput" />
  58. <text class="unit-hint">单位:公斤</text>
  59. </view>
  60. <!-- 血压 -->
  61. <view class="form-card">
  62. <view class="card-head">
  63. <text class="card-title">血压</text>
  64. <view class="quick-chips">
  65. <view
  66. class="quick-chip"
  67. :class="{ 'quick-chip-on': bpQuick === 'normal' }"
  68. @click="setBpQuick('normal')"
  69. ><text>正常</text></view>
  70. <view
  71. class="quick-chip"
  72. :class="{ 'quick-chip-on': bpQuick === 'high' }"
  73. @click="setBpQuick('high')"
  74. ><text>偏高</text></view>
  75. <view
  76. class="quick-chip"
  77. :class="{ 'quick-chip-on': bpQuick === 'low' }"
  78. @click="setBpQuick('low')"
  79. ><text>偏低</text></view>
  80. </view>
  81. </view>
  82. <input class="num-input" type="text" v-model="inner.bloodPressure" placeholder="如 120/80"
  83. @input="onInput" />
  84. <text class="unit-hint">格式:收缩压/舒张压 (mmHg)</text>
  85. </view>
  86. <!-- 血糖 -->
  87. <view class="form-card">
  88. <view class="card-head">
  89. <text class="card-title">空腹血糖 (mmol/L)</text>
  90. <view class="quick-chips">
  91. <view
  92. class="quick-chip"
  93. :class="{ 'quick-chip-on': glucoseQuick === 'normal' }"
  94. @click="setGlucoseQuick('normal')"
  95. ><text>正常</text></view>
  96. <view
  97. class="quick-chip"
  98. :class="{ 'quick-chip-on': glucoseQuick === 'high' }"
  99. @click="setGlucoseQuick('high')"
  100. ><text>偏高</text></view>
  101. <view
  102. class="quick-chip"
  103. :class="{ 'quick-chip-on': glucoseQuick === 'low' }"
  104. @click="setGlucoseQuick('low')"
  105. ><text>偏低</text></view>
  106. </view>
  107. </view>
  108. <input class="num-input" type="digit" v-model="inner.bloodGlucose" placeholder="如 5.6"
  109. @input="onInput" />
  110. </view>
  111. <!-- 血脂 -->
  112. <view class="form-card">
  113. <view class="card-head">
  114. <text class="card-title">总胆固醇 (mmol/L)</text>
  115. <view class="quick-chips">
  116. <view
  117. class="quick-chip"
  118. :class="{ 'quick-chip-on': lipidQuick === 'normal' }"
  119. @click="setLipidQuick('normal')"
  120. ><text>正常</text></view>
  121. <view
  122. class="quick-chip"
  123. :class="{ 'quick-chip-on': lipidQuick === 'high' }"
  124. @click="setLipidQuick('high')"
  125. ><text>偏高</text></view>
  126. </view>
  127. </view>
  128. <input class="num-input" type="digit" v-model="inner.lipidCholesterol" placeholder="如 4.5"
  129. @input="onInput" />
  130. </view>
  131. <!-- 其他补充 -->
  132. <view class="form-card">
  133. <view class="card-head">
  134. <text class="card-title">其他补充(选填)</text>
  135. </view>
  136. <textarea class="notes-area" v-model="inner.notes" placeholder="其他想补充的健康信息"
  137. :maxlength="500" @input="onInput" />
  138. </view>
  139. </view>
  140. </template>
  141. <script>
  142. // 快捷标签 → 参考数值(近似参考值,点击后填入输入框,用户可继续手改)
  143. var QUICK_VALUES = {
  144. height: { normal: '170', high: '185', low: '155' },
  145. weight: { normal: '60', high: '80', low: '45' },
  146. bloodPressure: { normal: '120/80', high: '140/90', low: '90/60' },
  147. bloodGlucose: { normal: '5.0', high: '7.0', low: '3.5' },
  148. lipid: { normal: '4.5', high: '6.2' }
  149. }
  150. function matchQuick(map, val) {
  151. if (val === '' || val === null || val === undefined) return ''
  152. var v = String(val)
  153. for (var k in map) {
  154. if (Object.prototype.hasOwnProperty.call(map, k) && map[k] === v) return k
  155. }
  156. return ''
  157. }
  158. export default {
  159. name: 'BasicVitalsStep',
  160. props: {
  161. value: {
  162. type: Object,
  163. default: function() { return {} }
  164. }
  165. },
  166. data() {
  167. return {
  168. inner: {
  169. heightCm: '',
  170. weightKg: '',
  171. bloodPressure: '',
  172. bloodGlucose: '',
  173. lipidCholesterol: '',
  174. notes: ''
  175. }
  176. }
  177. },
  178. computed: {
  179. heightQuick: function() { return matchQuick(QUICK_VALUES.height, this.inner.heightCm) },
  180. weightQuick: function() { return matchQuick(QUICK_VALUES.weight, this.inner.weightKg) },
  181. bpQuick: function() { return matchQuick(QUICK_VALUES.bloodPressure, this.inner.bloodPressure) },
  182. glucoseQuick: function() { return matchQuick(QUICK_VALUES.bloodGlucose, this.inner.bloodGlucose) },
  183. lipidQuick: function() { return matchQuick(QUICK_VALUES.lipid, this.inner.lipidCholesterol) }
  184. },
  185. watch: {
  186. value: {
  187. deep: true,
  188. handler: function(val) {
  189. this.syncFromValue(val)
  190. }
  191. }
  192. },
  193. created: function() {
  194. this.syncFromValue(this.value)
  195. },
  196. methods: {
  197. syncFromValue: function(val) {
  198. if (!val) return
  199. this.inner.heightCm = val.heightCm != null ? String(val.heightCm) : ''
  200. this.inner.weightKg = val.weightKg != null ? String(val.weightKg) : ''
  201. this.inner.bloodPressure = val.bloodPressure != null ? String(val.bloodPressure) : ''
  202. this.inner.bloodGlucose = val.bloodGlucose != null ? String(val.bloodGlucose) : ''
  203. this.inner.lipidCholesterol = val.lipidCholesterol != null ? String(val.lipidCholesterol) : ''
  204. this.inner.notes = val.notes != null ? String(val.notes) : ''
  205. },
  206. onInput: function() {
  207. var payload = {
  208. heightCm: this.inner.heightCm,
  209. weightKg: this.inner.weightKg,
  210. bloodPressure: this.inner.bloodPressure,
  211. bloodGlucose: this.inner.bloodGlucose,
  212. lipidCholesterol: this.inner.lipidCholesterol,
  213. notes: this.inner.notes
  214. }
  215. this.$emit('input', payload)
  216. },
  217. // 快捷选择:点击标签把对应参考数值填入输入框(用户可继续手改)
  218. setHeightQuick: function(k) {
  219. this.inner.heightCm = QUICK_VALUES.height[k] || ''
  220. this.onInput()
  221. },
  222. setWeightQuick: function(k) {
  223. this.inner.weightKg = QUICK_VALUES.weight[k] || ''
  224. this.onInput()
  225. },
  226. setBpQuick: function(k) {
  227. this.inner.bloodPressure = QUICK_VALUES.bloodPressure[k] || ''
  228. this.onInput()
  229. },
  230. setGlucoseQuick: function(k) {
  231. this.inner.bloodGlucose = QUICK_VALUES.bloodGlucose[k] || ''
  232. this.onInput()
  233. },
  234. setLipidQuick: function(k) {
  235. this.inner.lipidCholesterol = QUICK_VALUES.lipid[k] || ''
  236. this.onInput()
  237. }
  238. }
  239. }
  240. </script>
  241. <style scoped>
  242. .vitals-step {
  243. padding: 10rpx 0 30rpx;
  244. }
  245. .step-title-row {
  246. margin-bottom: 20rpx;
  247. }
  248. .step-title {
  249. font-size: 34rpx;
  250. font-weight: 700;
  251. color: #333;
  252. }
  253. .step-sub {
  254. display: block;
  255. font-size: 24rpx;
  256. color: #999;
  257. margin-top: 8rpx;
  258. }
  259. .form-card {
  260. background: #fff;
  261. border-radius: 20rpx;
  262. padding: 24rpx;
  263. margin-bottom: 20rpx;
  264. box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.04);
  265. }
  266. .card-head {
  267. display: flex;
  268. align-items: center;
  269. justify-content: space-between;
  270. margin-bottom: 16rpx;
  271. }
  272. .card-title {
  273. font-size: 28rpx;
  274. font-weight: 600;
  275. color: #333;
  276. }
  277. .quick-chips {
  278. display: flex;
  279. flex-wrap: wrap;
  280. }
  281. .quick-chip {
  282. padding: 8rpx 20rpx;
  283. border-radius: 999rpx;
  284. background: #F1F5F9;
  285. font-size: 22rpx;
  286. color: #64748B;
  287. margin-left: 10rpx;
  288. margin-bottom: 6rpx;
  289. }
  290. .quick-chip-on {
  291. background: #FFF3E0;
  292. color: #F97316;
  293. font-weight: 600;
  294. }
  295. .num-input {
  296. height: 80rpx;
  297. border: 2rpx solid #E2E8F0;
  298. border-radius: 12rpx;
  299. padding: 0 20rpx;
  300. font-size: 28rpx;
  301. color: #333;
  302. background: #F8FAFC;
  303. }
  304. .unit-hint {
  305. display: block;
  306. font-size: 22rpx;
  307. color: #999;
  308. margin-top: 10rpx;
  309. }
  310. .notes-area {
  311. width: 100%;
  312. min-height: 160rpx;
  313. background: #F8FAFC;
  314. border: 2rpx solid #E2E8F0;
  315. border-radius: 12rpx;
  316. padding: 16rpx;
  317. font-size: 26rpx;
  318. color: #333;
  319. }
  320. </style>