wzz 2 тижнів тому
батько
коміт
7660d8ea13

+ 3 - 2
src/App.vue

@@ -2,8 +2,9 @@
 import md5 from '@/common/md5.js';
 export default {
   globalData: {
-    shareUrl: "https://tts.xazhima.com/tingli/", //公共接口地址
-    //shareUrl:"http://8.136.230.133/tinnitus-php/", //测试地址(2.0后台,旧)
+    // FIXME-DEMO: 临时切回旧测试后台,查一下耳鸣量表"头痛的时间"题目的 category_id,查完记得改回公共接口地址
+    //shareUrl: "http://8.136.230.133/tinnitus-php/", //测试地址(2.0后台,旧)
+    shareUrl:"https://tts.xazhima.com/tingli/", //公共接口地址(正式)
     //shareUrl:"https://tts.xazhima.com/", //测试地址(更旧)
     //shareUrl:"https://h.xayuanju.com/",
     globalTimestamp: Date.now().toString(),

+ 19 - 57
src/pages/index/articleDetail.vue

@@ -1,78 +1,40 @@
-<!-- 病例分析分享 / 用嗓科普 通用富文本详情页 -->
+<!-- 病例分析分享 / 用嗓科普 详情页,和"关于我们"一样用 web-view 整页加载后台的静态 HTML -->
 <template>
-  <view class="detail-page">
-    <view class="detail-title">{{ article.title }}</view>
-    <view class="detail-sub">{{ article.hospital }}  {{ article.doctor }}  {{ article.date }}</view>
-    <mp-html :content="article.content" />
+  <view class="content">
+    <view class="artical">
+      <web-view :src="urlParse"></web-view>
+    </view>
   </view>
 </template>
 
 <script>
-import mpHtml from 'mp-html/dist/uni-app/components/mp-html/mp-html.vue'
-import { request } from '@/utils/request.js'
-
 export default {
-  components: { mpHtml },
   data() {
     return {
       id: '',
       category: '',
-      article: {
-        title: '',
-        hospital: '',
-        doctor: '',
-        date: '',
-        content: '',
-      },
+      urlParse: '',
     }
   },
   onLoad(query) {
     this.id = query.id
     this.category = query.category
-    this.getDetail()
-  },
-  methods: {
-    async getDetail() {
-      const res = await request('article', 'get_info_by_id', { id: this.id })
-      if (res.code === 200) {
-        const item = res.data || {}
-        this.article = {
-          title: item.title,
-          hospital: item.hospital_name,
-          doctor: item.doctor_name,
-          date: this.formatDate(item.create_time),
-          content: item.content,
-        }
-        uni.setNavigationBarTitle({ title: item.title || '详情' })
-      } else {
-        console.error('getDetail failed', this.id, res)
-      }
-    },
-    formatDate(ts) {
-      if (!ts) return ''
-      const d = new Date(Number(ts) * 1000)
-      const y = d.getFullYear()
-      const m = String(d.getMonth() + 1).padStart(2, '0')
-      const day = String(d.getDate()).padStart(2, '0')
-      return `${y}-${m}-${day}`
-    },
+    // 详情地址格式:{shareUrl}content/{id除以1000向下取整}/{id}.html
+    this.urlParse = getApp().globalData.shareUrl + 'content/' + Math.floor(this.id / 1000) + '/' + this.id + '.html?time=' + Date.now()
   },
 }
 </script>
 
-<style scoped>
-.detail-page {
-  padding: 30rpx;
-}
-.detail-title {
-  font-size: 34rpx;
-  font-weight: bold;
-  color: #0d1937;
-  line-height: 48rpx;
-}
-.detail-sub {
-  font-size: 24rpx;
-  color: #a7adba;
-  margin: 16rpx 0 30rpx;
+<style lang="scss" scoped>
+.content {
+  display: flex;
+  flex-direction: column;
+
+  .artical {
+    font-size: 32rpx;
+    box-shadow: 0px 4rpx 32rpx rgba(0, 0, 0, 0.1);
+    border-radius: 32rpx;
+    padding: 30rpx;
+  }
 }
 </style>

+ 8 - 2
src/pages/selfCenter/info.vue

@@ -129,11 +129,17 @@ export default {
 			// 用合并而不是整体替换,后台还没实现的新字段会保留 data() 里的默认值,不会变成 undefined(跟 history.vue 一致)
 			this.baseFormData = Object.assign({}, this.baseFormData, res.data);
 			// 后台没填过的选择类字段存的是字符串 "0"(或者字段压根不存在),选项列表都是从 value:1 开始编号,
-			// 统一兜底成 1,否则这几个只读下拉会显示空白
-			['sex','profession','marriage','type','hospital_id','doctor_id'].forEach((key)=>{
+			// 统一兜底成 1,否则这几个只读下拉会显示空白。hospital_id/doctor_id 是真实数据库 ID 不是从 1 编号,
+			// 不能这样兜底,直接转数字类型即可,是 0 就让它显示为空(跟 history.vue 保持一致的判断)
+			['sex','profession','marriage','type'].forEach((key)=>{
 				if (!this.baseFormData[key] || this.baseFormData[key] == '0') this.baseFormData[key] = 1
 				this.baseFormData[key] = Number(this.baseFormData[key])
 			})
+			this.baseFormData.hospital_id = Number(this.baseFormData.hospital_id)
+			this.baseFormData.doctor_id = Number(this.baseFormData.doctor_id)
+			// 有无孩子/工作地点是 uni-data-checkbox/uni-data-select 选择框,不转数字类型的话严格比较匹配不上,回显不出来
+			this.baseFormData.has_children = Number(this.baseFormData.has_children)
+			if (this.baseFormData.work_address) this.baseFormData.work_address = Number(this.baseFormData.work_address)
 			if (this.baseFormData.work_address == null || this.baseFormData.work_address == undefined) this.baseFormData.work_address = ''
 			// 后台返回 0 代表没填过,这几个数字字段不应该显示字面上的 "0",统一归一化成空字符串
 			['age','height','weight','children_age','symptom_duration'].forEach((key)=>{

+ 23 - 4
src/pages/sickForm/history.vue

@@ -38,7 +38,7 @@
 						<uni-data-checkbox v-model="baseFormData.has_children" :localdata="yesNoOptions" :wrap="true"/>
 					</uni-forms-item>
 					<uni-forms-item label="孩子年龄" required name="children_age" box-width="190rpx" v-if="baseFormData.has_children === 1">
-						<uni-easyinput type="number" :value="baseFormData.children_age" @input="baseFormData.children_age = $event" placeholder="请输入" />
+						<uni-easyinput type="number" :value="baseFormData.children_age" @input="onChildrenAgeInput" placeholder="请输入" />
 					</uni-forms-item>
 					<uni-forms-item label="职业" required name="profession" box-width="190rpx">
 						<picker @change="change('profession',$event)" :value="pickerIndexObj.profession" :range="selectData.profession" range-key="text">
@@ -244,6 +244,10 @@ export default {
 	  }
   },
   methods: {
+		onChildrenAgeInput(value) {
+			// 输入过程中就限制,不超过 99
+			this.baseFormData.children_age = (value !== '' && Number(value) > 99) ? '99' : value
+		},
 		getQueryParams(str) {
 			const paramsArr = str.split('&');
 			const paramObj = {};
@@ -358,6 +362,10 @@ export default {
 			})
 			this.baseFormData.sex = Number(this.baseFormData.sex);
 			if(this.baseFormData.sex == '0')this.baseFormData.sex = '';
+			// 有无孩子/工作地点是 uni-data-checkbox 单选,选项值是数字,后台存的是字符串,
+			// 不转成数字类型的话严格比较匹配不上,选择器不会回显(work_address 为空字符串时不转,保持未选中状态)
+			this.baseFormData.has_children = Number(this.baseFormData.has_children);
+			if (this.baseFormData.work_address) this.baseFormData.work_address = Number(this.baseFormData.work_address);
 			this.baseFormData.profession = Number(this.baseFormData.profession);
 			this.baseFormData.marriage = Number(this.baseFormData.marriage);
 			this.baseFormData.type = Number(this.baseFormData.type);
@@ -372,7 +380,9 @@ export default {
 			this.baseFormData = Object.assign({}, this.baseFormData, res.data);
 			// 后台没填过的选择类字段存的是字符串 "0"(或者字段压根不存在),跟 age/sex 是同一套"0 代表未填"的约定,
 			// "0"/undefined 在 JS 里判真值容易漏判,选项列表都是从 value:1 开始编号,统一兜底成 1,否则选择器会显示空白
-			['profession','marriage','type','hospital_id','doctor_id'].forEach((key)=>{
+			// 注意:hospital_id/doctor_id 不能这么处理,它们是数据库里的真实 ID,不是从 1 开始编号,
+			// 硬编码成 1 大概率匹配不到真实医院/医生(见下面 getUserSelect/getDoctor 里"匹配不到就用列表第一个"的处理)
+			['profession','marriage','type'].forEach((key)=>{
 				if (!this.baseFormData[key] || this.baseFormData[key] == '0') this.baseFormData[key] = 1
 			})
 			if (this.baseFormData.work_address == null || this.baseFormData.work_address == undefined) this.baseFormData.work_address = ''
@@ -385,9 +395,18 @@ export default {
 			 let pickerArr = res.data;
 			 // 只处理表单里实际用到的字段,其余字段(比如 career_type)后台可能还会返回,忽略即可,
 			 // 避免像之前 career_type 那样污染 pickerIndexObj 导致提交校验报错
-			 ['profession','marriage','type','hospital'].forEach((key)=>{
-				 if (pickerArr[key]) this.pickerEchoShow(pickerArr[key], this.baseFormData[key === 'hospital' ? 'hospital_id' : key], key)
+			 ['profession','marriage','type'].forEach((key)=>{
+				 if (pickerArr[key]) this.pickerEchoShow(pickerArr[key], this.baseFormData[key], key)
 			 })
+			 if (pickerArr.hospital) {
+				 this.pickerEchoShow(pickerArr.hospital, this.baseFormData.hospital_id, 'hospital')
+				 // hospital_id 是真实医院 ID,不是从 1 开始编号,匹配不到时(包括原来是 0/空 的情况)默认选中返回的第一家医院
+				 if (this.pickerIndexObj.hospital === -1 && pickerArr.hospital.length) {
+					 this.pickerIndexObj.hospital = 0
+					 this.baseFormData.hospital_id = pickerArr.hospital[0].value
+					 this.baseFormData.hospital_name = pickerArr.hospital[0].text
+				 }
+			 }
 			 this.selectData = Object.assign({}, this.selectData, pickerArr);
 			 this.getDoctor(this.baseFormData.hospital_id)
 	     }

+ 15 - 7
src/pages/sickForm/historyDetail.vue

@@ -5,13 +5,13 @@
 				<template v-for="(item, idx) in sickHisList" :key="idx">
 				<view :id="'a' + item.id" v-if="isShowItem(item)">
 					<uni-forms-item :label=" item.is_child == '0' ? item.number + '.' + item.name : item.number + item.name" :isMultiple="item.type" isBold="bold" :nowLabelItem="item" :isShowInput="item.type == 3"
-					 :nowIndex='item.number'  @input="titleInput(item,$event)" @change="totalCalc(item,$event)" @percent="percentCalc(item,$event)" v-if="item.id != 205">
+					 :nowIndex='item.number'  @input="titleInput(item,$event)" @change="totalCalc(item,$event)" @percent="percentCalc(item,$event)" v-if="!isHeadacheItem(item)">
 					    <view v-if="item.pic_url">
 							 <image :src="globalUrl + item.pic_url" mode="aspectFit" style="width: 95%;height: 230rpx;" @click="preview(globalUrl + item.pic_url)"></image>
 						</view>
 						<uni-data-checkbox v-model="item.answer" :multiple="item.type" :localdata="item.items" @change="change(idx,item,$event)" v-if="item.type!=3"/>
 					</uni-forms-item>
-					<uni-forms-item label="( 1 ) 头痛的时间" isBold="bold"  v-if="item.id == 205" >
+					<uni-forms-item label="( 1 ) 头痛的时间" isBold="bold"  v-if="isHeadacheItem(item)" >
 						<view class="display-between" style="width:350rpx">
 							<uni-easyinput :value="headache" @input="headache = $event"  type="number" widthStyle="160rpx" />
 							<uni-data-checkbox v-model="unitValue" :localdata="unitList" @change="unitChange($event)" :wrap="true" />
@@ -57,8 +57,9 @@ export default {
   },
   onLoad(option) {
 	  this.pageId = option.id || 1;
+	  this.pageName = option.name || '病史信息'
 	  uni.setNavigationBarTitle({
-		title: option.name || '病史信息'
+		title: this.pageName
 	  });
 	  this.getcategory(this.pageId)
   },
@@ -66,6 +67,13 @@ export default {
 	isShowItem(item){
 		return !!(item && item.isShow)
 	},
+	// "头痛的时间"是"病史信息"模块里一道写死用 id=205 特殊渲染的题目。题目 id 是各量表各自独立编号的,不是全局唯一,
+	// VHI-30 量表里也存在 id=205 的题目(内容跟头痛无关),加了两层判断:进入模块时的顶层 category_id(pageId) + 题目 id,
+	// pageId=1 已确认是进入"病史信息"模块时传的顶层分类 ID,比页面名称字符串更可靠,顺带保留页面名称兜底。
+	// TODO: 等"病史信息"题目接口有真实数据后,最好换成后台专门给这道题的类型标识字段来判断,不再靠 id/分类猜测
+	isHeadacheItem(item){
+		return !!(item && (item.id == 205 || item.id == '205') && (this.pageId == 1 || this.pageId == '1') && this.pageName === '病史信息')
+	},
 	unitChange(e){
 			 this.unitValue = e.detail.value;
 			 this.unitSubmit = e.detail.value;
@@ -267,7 +275,7 @@ export default {
 			}
 		})
 		that.sickHisList.forEach((item)=>{
-			if (item.id == 205 || item.id == "205"){
+			if (this.isHeadacheItem(item)){
 				this.unitValue = item.answer.substr(-1);
 				this.unitSubmit = this.unitValue;
 				this.headache = item.answer.substr(0,(item.answer.length-1));
@@ -332,13 +340,13 @@ export default {
 	   if(result){
 		   // 修复:其他题目已有答案时,原来这里直接原样返回,完全没处理"头痛的时间"(id=205),
 		   // 会导致这道题的答案静默丢失,不会提交给后端。补上和 else 分支一致的拼接方式。
-		   let headacheItem = this.sickHisList.find((item)=>{ return item.id == 205 })
+		   let headacheItem = this.sickHisList.find((item)=>{ return this.isHeadacheItem(item) })
 		   if(headacheItem){
 			   result = headacheItem.id + ':' + this.headache + this.unitSubmit + ';' + result
 		   }
 	   }else {
 		   this.sickHisList.forEach((item)=>{
-			  if (item.id == 205){
+			  if (this.isHeadacheItem(item)){
 				   result =  item.id + ':' + this.headache + this.unitSubmit + ';' + result
 			  }
 			  else{
@@ -354,7 +362,7 @@ export default {
 				if(Array.isArray(item.answer) && item.answer.length === 1 && item.answer[0] === ''){
 					item.answer = ''
 				}
-				if(item.id == 205){
+				if(this.isHeadacheItem(item)){
 					item.answer = this.headache;
 				}
 			})