1297 lines
30 KiB
Vue
1297 lines
30 KiB
Vue
<template>
|
|
<view class="edit-container">
|
|
|
|
|
|
<!-- 加载状态 -->
|
|
<view v-if="loading" class="loading-state">
|
|
<text>加载中...</text>
|
|
</view>
|
|
|
|
<!-- 编辑表单 -->
|
|
<view v-else class="form-wrapper">
|
|
<!-- 患者基本信息 -->
|
|
<view class="form-section">
|
|
<text class="section-title">患者基本信息</text>
|
|
|
|
<view class="form-group">
|
|
<text class="form-label">患者姓名</text>
|
|
<input
|
|
v-model="formData.patient_name"
|
|
class="form-input"
|
|
placeholder="请输入患者姓名"
|
|
maxlength="50"
|
|
/>
|
|
</view>
|
|
|
|
<view class="form-group">
|
|
<text class="form-label">性别</text>
|
|
<view class="gender-group">
|
|
<view
|
|
class="gender-btn"
|
|
:class="{ active: formData.gender === 1 }"
|
|
@click="formData.gender = 1"
|
|
>
|
|
男
|
|
</view>
|
|
<view
|
|
class="gender-btn"
|
|
:class="{ active: formData.gender === 0 }"
|
|
@click="formData.gender = 0"
|
|
>
|
|
女
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<view class="form-group">
|
|
<text class="form-label">年龄</text>
|
|
<input
|
|
v-model.number="formData.age"
|
|
class="form-input"
|
|
type="number"
|
|
placeholder="请输入年龄"
|
|
min="0"
|
|
max="150"
|
|
/>
|
|
</view>
|
|
|
|
<!-- <view class="form-group">
|
|
<text class="form-label">诊断日期</text>
|
|
<view class="date-input" @click="showDatePicker = true">
|
|
<text>{{ formData.diagnosis_date || '请选择日期' }}</text>
|
|
<text class="date-icon">📅</text>
|
|
</view>
|
|
</view> -->
|
|
</view>
|
|
|
|
<!-- 诊断信息 -->
|
|
<!-- <view class="form-section">
|
|
<text class="section-title">诊断信息</text>
|
|
|
|
<view class="form-group">
|
|
<text class="form-label">诊断类型</text>
|
|
<picker
|
|
:range="diagnosisTypeOptions"
|
|
range-key="name"
|
|
@change="onDiagnosisTypeChange"
|
|
>
|
|
<view class="picker-input">
|
|
<text>{{ getDiagnosisTypeName(formData.diagnosis_type) || '请选择' }}</text>
|
|
<text class="picker-icon">▼</text>
|
|
</view>
|
|
</picker>
|
|
</view>
|
|
|
|
<view class="form-group">
|
|
<text class="form-label">证型</text>
|
|
<picker
|
|
:range="syndromeTypeOptions"
|
|
range-key="name"
|
|
@change="onSyndromeTypeChange"
|
|
>
|
|
<view class="picker-input">
|
|
<text>{{ getSyndromeTypeName(formData.syndrome_type) || '请选择' }}</text>
|
|
<text class="picker-icon">▼</text>
|
|
</view>
|
|
</picker>
|
|
</view>
|
|
|
|
<view class="form-group">
|
|
<text class="form-label">糖尿病期数</text>
|
|
<picker
|
|
:range="diabetesTypeOptions"
|
|
range-key="name"
|
|
@change="onDiabetesTypeChange"
|
|
>
|
|
<view class="picker-input">
|
|
<text>{{ getDiabetesTypeName(formData.diabetes_type) || '请选择' }}</text>
|
|
<text class="picker-icon">▼</text>
|
|
</view>
|
|
</picker>
|
|
</view>
|
|
</view> -->
|
|
|
|
<!-- 现病史 -->
|
|
<view class="form-section">
|
|
<text class="section-title">现病史</text>
|
|
|
|
<view class="form-group">
|
|
<text class="form-label">口腔感觉</text>
|
|
<view class="checkbox-group">
|
|
<view
|
|
v-for="item in appetiteOptions"
|
|
:key="item.value"
|
|
class="checkbox-item"
|
|
:class="{ active: formData.appetite === item.value }"
|
|
@click="formData.appetite = item.value"
|
|
>
|
|
{{ item.name }}
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<view class="form-group">
|
|
<text class="form-label">每日饮水量</text>
|
|
<view class="checkbox-group">
|
|
<view
|
|
v-for="item in waterIntakeOptions"
|
|
:key="item.value"
|
|
class="checkbox-item"
|
|
:class="{ active: formData.water_intake === item.value }"
|
|
@click="formData.water_intake = item.value"
|
|
>
|
|
{{ item.name }}
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<view class="form-group">
|
|
<text class="form-label">体重变化</text>
|
|
<view class="checkbox-group">
|
|
<view
|
|
v-for="item in weightChangeOptions"
|
|
:key="item.value"
|
|
class="checkbox-item"
|
|
:class="{ active: formData.weight_change === item.value }"
|
|
@click="formData.weight_change = item.value"
|
|
>
|
|
{{ item.name }}
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<view class="form-group">
|
|
<text class="form-label">脂肪肝程度</text>
|
|
<view class="checkbox-group">
|
|
<view
|
|
v-for="item in fattyLiverDegreeOptions"
|
|
:key="item.value"
|
|
class="checkbox-item"
|
|
:class="{ active: formData.fatty_liver_degree === item.value }"
|
|
@click="formData.fatty_liver_degree = item.value"
|
|
>
|
|
{{ item.name }}
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<view class="form-group">
|
|
<text class="form-label">饮食情况</text>
|
|
<view class="multi-checkbox-group">
|
|
<view
|
|
v-for="item in dietConditionOptions"
|
|
:key="item.value"
|
|
class="multi-checkbox-item"
|
|
:class="{ active: formData.diet_condition.includes(item.value) }"
|
|
@click="toggleMultiCheckbox('diet_condition', item.value)"
|
|
>
|
|
{{ item.name }}
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<view class="form-group">
|
|
<text class="form-label">肢体感觉</text>
|
|
<view class="multi-checkbox-group">
|
|
<view
|
|
v-for="item in bodyFeelingOptions"
|
|
:key="item.value"
|
|
class="multi-checkbox-item"
|
|
:class="{ active: formData.body_feeling.includes(item.value) }"
|
|
@click="toggleMultiCheckbox('body_feeling', item.value)"
|
|
>
|
|
{{ item.name }}
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<view class="form-group">
|
|
<text class="form-label">睡眠情况</text>
|
|
<view class="multi-checkbox-group">
|
|
<view
|
|
v-for="item in sleepConditionOptions"
|
|
:key="item.value"
|
|
class="multi-checkbox-item"
|
|
:class="{ active: formData.sleep_condition.includes(item.value) }"
|
|
@click="toggleMultiCheckbox('sleep_condition', item.value)"
|
|
>
|
|
{{ item.name }}
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<view class="form-group">
|
|
<text class="form-label">眼睛情况</text>
|
|
<view class="multi-checkbox-group">
|
|
<view
|
|
v-for="item in eyeConditionOptions"
|
|
:key="item.value"
|
|
class="multi-checkbox-item"
|
|
:class="{ active: formData.eye_condition.includes(item.value) }"
|
|
@click="toggleMultiCheckbox('eye_condition', item.value)"
|
|
>
|
|
{{ item.name }}
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<view class="form-group">
|
|
<text class="form-label">头部感觉</text>
|
|
<view class="multi-checkbox-group">
|
|
<view
|
|
v-for="item in headFeelingOptions"
|
|
:key="item.value"
|
|
class="multi-checkbox-item"
|
|
:class="{ active: formData.head_feeling.includes(item.value) }"
|
|
@click="toggleMultiCheckbox('head_feeling', item.value)"
|
|
>
|
|
{{ item.name }}
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<view class="form-group">
|
|
<text class="form-label">出汗情况</text>
|
|
<view class="multi-checkbox-group">
|
|
<view
|
|
v-for="item in sweatConditionOptions"
|
|
:key="item.value"
|
|
class="multi-checkbox-item"
|
|
:class="{ active: formData.sweat_condition.includes(item.value) }"
|
|
@click="toggleMultiCheckbox('sweat_condition', item.value)"
|
|
>
|
|
{{ item.name }}
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<view class="form-group">
|
|
<text class="form-label">皮肤情况</text>
|
|
<view class="multi-checkbox-group">
|
|
<view
|
|
v-for="item in skinConditionOptions"
|
|
:key="item.value"
|
|
class="multi-checkbox-item"
|
|
:class="{ active: formData.skin_condition.includes(item.value) }"
|
|
@click="toggleMultiCheckbox('skin_condition', item.value)"
|
|
>
|
|
{{ item.name }}
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<view class="form-group">
|
|
<text class="form-label">小便情况</text>
|
|
<view class="multi-checkbox-group">
|
|
<view
|
|
v-for="item in urineConditionOptions"
|
|
:key="item.value"
|
|
class="multi-checkbox-item"
|
|
:class="{ active: formData.urine_condition.includes(item.value) }"
|
|
@click="toggleMultiCheckbox('urine_condition', item.value)"
|
|
>
|
|
{{ item.name }}
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<view class="form-group">
|
|
<text class="form-label">大便情况</text>
|
|
<view class="multi-checkbox-group">
|
|
<view
|
|
v-for="item in stoolConditionOptions"
|
|
:key="item.value"
|
|
class="multi-checkbox-item"
|
|
:class="{ active: formData.stool_condition.includes(item.value) }"
|
|
@click="toggleMultiCheckbox('stool_condition', item.value)"
|
|
>
|
|
{{ item.name }}
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<view class="form-group">
|
|
<text class="form-label">腰肾情况</text>
|
|
<view class="multi-checkbox-group">
|
|
<view
|
|
v-for="item in kidneyConditionOptions"
|
|
:key="item.value"
|
|
class="multi-checkbox-item"
|
|
:class="{ active: formData.kidney_condition.includes(item.value) }"
|
|
@click="toggleMultiCheckbox('kidney_condition', item.value)"
|
|
>
|
|
{{ item.name }}
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 既往史 -->
|
|
<view class="form-section">
|
|
<text class="section-title">既往史</text>
|
|
|
|
<view class="form-group">
|
|
<text class="form-label">既往史</text>
|
|
<view class="multi-checkbox-group">
|
|
<view
|
|
v-for="item in pastHistoryOptions"
|
|
:key="item.value"
|
|
class="multi-checkbox-item"
|
|
:class="{ active: formData.past_history.includes(item.value) }"
|
|
@click="toggleMultiCheckbox('past_history', item.value)"
|
|
>
|
|
{{ item.name }}
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<view class="form-group">
|
|
<text class="form-label">外伤史</text>
|
|
<view class="radio-group">
|
|
<view
|
|
class="radio-item"
|
|
:class="{ active: formData.trauma_history === 1 }"
|
|
@click="formData.trauma_history = 1"
|
|
>
|
|
有
|
|
</view>
|
|
<view
|
|
class="radio-item"
|
|
:class="{ active: formData.trauma_history === 0 }"
|
|
@click="formData.trauma_history = 0"
|
|
>
|
|
无
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<view class="form-group">
|
|
<text class="form-label">手术史</text>
|
|
<view class="radio-group">
|
|
<view
|
|
class="radio-item"
|
|
:class="{ active: formData.surgery_history === 1 }"
|
|
@click="formData.surgery_history = 1"
|
|
>
|
|
有
|
|
</view>
|
|
<view
|
|
class="radio-item"
|
|
:class="{ active: formData.surgery_history === 0 }"
|
|
@click="formData.surgery_history = 0"
|
|
>
|
|
无
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<view class="form-group">
|
|
<text class="form-label">过敏史</text>
|
|
<view class="radio-group">
|
|
<view
|
|
class="radio-item"
|
|
:class="{ active: formData.allergy_history === 1 }"
|
|
@click="formData.allergy_history = 1"
|
|
>
|
|
有
|
|
</view>
|
|
<view
|
|
class="radio-item"
|
|
:class="{ active: formData.allergy_history === 0 }"
|
|
@click="formData.allergy_history = 0"
|
|
>
|
|
无
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<view class="form-group">
|
|
<text class="form-label">家族病史</text>
|
|
<view class="radio-group">
|
|
<view
|
|
class="radio-item"
|
|
:class="{ active: formData.family_history === 1 }"
|
|
@click="formData.family_history = 1"
|
|
>
|
|
有
|
|
</view>
|
|
<view
|
|
class="radio-item"
|
|
:class="{ active: formData.family_history === 0 }"
|
|
@click="formData.family_history = 0"
|
|
>
|
|
无
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<view class="form-group">
|
|
<text class="form-label">妊娠哺乳史</text>
|
|
<view class="radio-group">
|
|
<view
|
|
class="radio-item"
|
|
:class="{ active: formData.pregnancy_history === 1 }"
|
|
@click="formData.pregnancy_history = 1"
|
|
>
|
|
有
|
|
</view>
|
|
<view
|
|
class="radio-item"
|
|
:class="{ active: formData.pregnancy_history === 0 }"
|
|
@click="formData.pregnancy_history = 0"
|
|
>
|
|
无
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 临床信息 -->
|
|
<view class="form-section">
|
|
<text class="section-title">临床信息</text>
|
|
|
|
<view class="form-group">
|
|
<text class="form-label">症状</text>
|
|
<textarea
|
|
v-model="formData.symptoms"
|
|
class="form-textarea"
|
|
placeholder="请输入症状描述"
|
|
maxlength="1500"
|
|
/>
|
|
</view>
|
|
|
|
<view class="form-group">
|
|
<text class="form-label">舌苔</text>
|
|
<textarea
|
|
v-model="formData.tongue_coating"
|
|
class="form-textarea"
|
|
placeholder="请输入舌苔描述"
|
|
maxlength="1500"
|
|
/>
|
|
</view>
|
|
|
|
<view class="form-group">
|
|
<text class="form-label">脉象</text>
|
|
<textarea
|
|
v-model="formData.pulse"
|
|
class="form-textarea"
|
|
placeholder="请输入脉象描述"
|
|
maxlength="1500"
|
|
/>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 治疗信息 -->
|
|
<!-- <view class="form-section">
|
|
<text class="section-title">治疗信息</text>
|
|
|
|
<view class="form-group">
|
|
<text class="form-label">治则</text>
|
|
<input
|
|
v-model="formData.treatment_principle"
|
|
class="form-input"
|
|
placeholder="请输入治则"
|
|
maxlength="100"
|
|
/>
|
|
</view>
|
|
|
|
<view class="form-group">
|
|
<text class="form-label">处方</text>
|
|
<textarea
|
|
v-model="formData.prescription"
|
|
class="form-textarea"
|
|
placeholder="请输入处方"
|
|
maxlength="500"
|
|
/>
|
|
</view>
|
|
|
|
<view class="form-group">
|
|
<text class="form-label">医嘱</text>
|
|
<textarea
|
|
v-model="formData.doctor_advice"
|
|
class="form-textarea"
|
|
placeholder="请输入医嘱"
|
|
maxlength="500"
|
|
/>
|
|
</view>
|
|
</view> -->
|
|
|
|
<!-- 备注 -->
|
|
<view class="form-section">
|
|
<view class="form-group">
|
|
<text class="form-label">备注</text>
|
|
<textarea
|
|
v-model="formData.remark"
|
|
class="form-textarea"
|
|
placeholder="请输入备注"
|
|
maxlength="500"
|
|
/>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 操作按钮 -->
|
|
<view class="button-group">
|
|
<button class="btn btn-cancel" @click="goBack">取消</button>
|
|
<button class="btn btn-submit" @click="submitForm" :disabled="submitting">
|
|
{{ submitting ? '保存中...' : '保存修改' }}
|
|
</button>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 日期选择器 -->
|
|
<view v-if="showDatePicker" class="date-picker-overlay">
|
|
<view class="date-picker-container">
|
|
<view class="date-picker-header">
|
|
<text class="date-btn-cancel" @click="showDatePicker = false">取消</text>
|
|
<text class="date-btn-confirm" @click="confirmDate">确定</text>
|
|
</view>
|
|
<picker-view
|
|
:value="datePickerValue"
|
|
@change="onDateChange"
|
|
class="date-picker-view"
|
|
>
|
|
<picker-view-column>
|
|
<view v-for="year in yearRange" :key="year" class="picker-item">{{ year }}</view>
|
|
</picker-view-column>
|
|
<picker-view-column>
|
|
<view v-for="month in monthRange" :key="month" class="picker-item">{{ String(month).padStart(2, '0') }}</view>
|
|
</picker-view-column>
|
|
<picker-view-column>
|
|
<view v-for="day in dayRange" :key="day" class="picker-item">{{ String(day).padStart(2, '0') }}</view>
|
|
</picker-view-column>
|
|
</picker-view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { ref, onMounted, getCurrentInstance } from 'vue'
|
|
|
|
const { proxy } = getCurrentInstance()
|
|
|
|
// 数据
|
|
const loading = ref(false)
|
|
const submitting = ref(false)
|
|
const showDatePicker = ref(false)
|
|
const diagnosisId = ref(null)
|
|
const patientId = ref(null)
|
|
|
|
// 表单数据
|
|
const formData = ref({
|
|
patient_name: '',
|
|
gender: 1,
|
|
age: '',
|
|
diagnosis_date: '',
|
|
diagnosis_type: '',
|
|
syndrome_type: '',
|
|
diabetes_type: '',
|
|
// 现病史
|
|
appetite: '',
|
|
water_intake: '',
|
|
diet_condition: [],
|
|
weight_change: '',
|
|
body_feeling: [],
|
|
sleep_condition: [],
|
|
eye_condition: [],
|
|
head_feeling: [],
|
|
sweat_condition: [],
|
|
skin_condition: [],
|
|
urine_condition: [],
|
|
stool_condition: [],
|
|
kidney_condition: [],
|
|
fatty_liver_degree: '',
|
|
// 既往史
|
|
past_history: [],
|
|
trauma_history: 0,
|
|
surgery_history: 0,
|
|
allergy_history: 0,
|
|
family_history: 0,
|
|
pregnancy_history: 0,
|
|
// 临床信息
|
|
symptoms: '',
|
|
tongue_coating: '',
|
|
pulse: '',
|
|
treatment_principle: '',
|
|
prescription: '',
|
|
doctor_advice: '',
|
|
remark: ''
|
|
})
|
|
|
|
// 字典选项
|
|
const diagnosisTypeOptions = ref([])
|
|
const syndromeTypeOptions = ref([])
|
|
const diabetesTypeOptions = ref([])
|
|
const pastHistoryOptions = ref([])
|
|
// 现病史选项
|
|
const appetiteOptions = ref([])
|
|
const waterIntakeOptions = ref([])
|
|
const dietConditionOptions = ref([])
|
|
const weightChangeOptions = ref([])
|
|
const bodyFeelingOptions = ref([])
|
|
const sleepConditionOptions = ref([])
|
|
const eyeConditionOptions = ref([])
|
|
const headFeelingOptions = ref([])
|
|
const sweatConditionOptions = ref([])
|
|
const skinConditionOptions = ref([])
|
|
const urineConditionOptions = ref([])
|
|
const stoolConditionOptions = ref([])
|
|
const kidneyConditionOptions = ref([])
|
|
const fattyLiverDegreeOptions = ref([])
|
|
|
|
// 日期选择器
|
|
const datePickerValue = ref([0, 0, 0])
|
|
const yearRange = ref([])
|
|
const monthRange = ref(Array.from({ length: 12 }, (_, i) => i + 1))
|
|
const dayRange = ref(Array.from({ length: 31 }, (_, i) => i + 1))
|
|
|
|
// 页面加载
|
|
onMounted(() => {
|
|
loadDictOptions()
|
|
loadCardDetail()
|
|
initDatePicker()
|
|
})
|
|
|
|
// 获取字典选项
|
|
const loadDictOptions = async () => {
|
|
try {
|
|
const dictTypes = [
|
|
'diagnosis_type',
|
|
'syndrome_type',
|
|
'diabetes_type',
|
|
'past_history',
|
|
'appetite',
|
|
'water_intake',
|
|
'diet_condition',
|
|
'weight_change',
|
|
'body_feeling',
|
|
'sleep_condition',
|
|
'eye_condition',
|
|
'head_feeling',
|
|
'sweat_condition',
|
|
'skin_condition',
|
|
'urine_condition',
|
|
'stool_condition',
|
|
'kidney_condition',
|
|
'fatty_liver_degree'
|
|
]
|
|
|
|
// 并行请求所有字典数据
|
|
const results = await Promise.all(
|
|
dictTypes.map(type =>
|
|
proxy.apiUrl({
|
|
url: '/api/tcm/getDict',
|
|
method: 'GET',
|
|
data: { type }
|
|
})
|
|
)
|
|
)
|
|
|
|
// 处理返回的数据
|
|
results.forEach((res, index) => {
|
|
const type = dictTypes[index]
|
|
if (res.code === 1 && res.data) {
|
|
const data = res.data[type] || []
|
|
// 转换数据格式
|
|
const options = Array.isArray(data) ? data : Object.entries(data).map(([key, value]) => ({
|
|
value: key,
|
|
name: value
|
|
}))
|
|
|
|
// 根据类型赋值
|
|
switch (type) {
|
|
case 'diagnosis_type':
|
|
diagnosisTypeOptions.value = options
|
|
break
|
|
case 'syndrome_type':
|
|
syndromeTypeOptions.value = options
|
|
break
|
|
case 'diabetes_type':
|
|
diabetesTypeOptions.value = options
|
|
break
|
|
case 'past_history':
|
|
pastHistoryOptions.value = options
|
|
break
|
|
case 'appetite':
|
|
appetiteOptions.value = options
|
|
break
|
|
case 'water_intake':
|
|
waterIntakeOptions.value = options
|
|
break
|
|
case 'diet_condition':
|
|
dietConditionOptions.value = options
|
|
break
|
|
case 'weight_change':
|
|
weightChangeOptions.value = options
|
|
break
|
|
case 'body_feeling':
|
|
bodyFeelingOptions.value = options
|
|
break
|
|
case 'sleep_condition':
|
|
sleepConditionOptions.value = options
|
|
break
|
|
case 'eye_condition':
|
|
eyeConditionOptions.value = options
|
|
break
|
|
case 'head_feeling':
|
|
headFeelingOptions.value = options
|
|
break
|
|
case 'sweat_condition':
|
|
sweatConditionOptions.value = options
|
|
break
|
|
case 'skin_condition':
|
|
skinConditionOptions.value = options
|
|
break
|
|
case 'urine_condition':
|
|
urineConditionOptions.value = options
|
|
break
|
|
case 'stool_condition':
|
|
stoolConditionOptions.value = options
|
|
break
|
|
case 'kidney_condition':
|
|
kidneyConditionOptions.value = options
|
|
break
|
|
case 'fatty_liver_degree':
|
|
fattyLiverDegreeOptions.value = options
|
|
break
|
|
}
|
|
}
|
|
})
|
|
} catch (err) {
|
|
console.error('加载字典数据失败:', err)
|
|
}
|
|
}
|
|
|
|
// 初始化日期选择器
|
|
const initDatePicker = () => {
|
|
const currentYear = new Date().getFullYear()
|
|
yearRange.value = Array.from({ length: 100 }, (_, i) => currentYear - 50 + i)
|
|
}
|
|
|
|
// 加载就诊卡详情
|
|
const loadCardDetail = async () => {
|
|
loading.value = true
|
|
try {
|
|
const pages = getCurrentPages()
|
|
const currentPage = pages[pages.length - 1]
|
|
diagnosisId.value = currentPage.options.id
|
|
|
|
if (!diagnosisId.value) {
|
|
uni.showToast({ title: '诊单ID不存在', icon: 'none' })
|
|
setTimeout(() => uni.navigateBack(), 1500)
|
|
return
|
|
}
|
|
|
|
const userData = uni.getStorageSync('userData')
|
|
patientId.value = userData?.diagnosis?.patient_id
|
|
|
|
if (!patientId.value) {
|
|
uni.showToast({ title: '请先登录', icon: 'none' })
|
|
setTimeout(() => uni.redirectTo({ url: '/pages/login/login' }), 1500)
|
|
return
|
|
}
|
|
|
|
const res = await proxy.apiUrl({
|
|
url: '/api/tcm/diagnosisDetail',
|
|
method: 'GET',
|
|
data: {
|
|
id: diagnosisId.value,
|
|
user_id: patientId.value
|
|
}
|
|
})
|
|
|
|
if (res.code === 1) {
|
|
const diagnosis = res.data
|
|
|
|
if (diagnosis.patient_id !== patientId.value) {
|
|
uni.showToast({ title: '无权限编辑此诊单', icon: 'none' })
|
|
setTimeout(() => uni.navigateBack(), 1500)
|
|
return
|
|
}
|
|
|
|
// 处理数组字段
|
|
const arrayFields = ['diet_condition', 'body_feeling', 'sleep_condition', 'eye_condition', 'head_feeling', 'sweat_condition', 'skin_condition', 'urine_condition', 'stool_condition', 'kidney_condition', 'past_history']
|
|
arrayFields.forEach(field => {
|
|
if (typeof diagnosis[field] === 'string' && diagnosis[field]) {
|
|
diagnosis[field] = diagnosis[field].split(',')
|
|
} else if (!diagnosis[field]) {
|
|
diagnosis[field] = []
|
|
}
|
|
})
|
|
|
|
formData.value = diagnosis
|
|
} else {
|
|
uni.showToast({ title: res.msg || '获取失败', icon: 'none' })
|
|
setTimeout(() => uni.navigateBack(), 1500)
|
|
}
|
|
} catch (err) {
|
|
console.error('加载诊单详情失败:', err)
|
|
uni.showToast({ title: '加载失败', icon: 'none' })
|
|
setTimeout(() => uni.navigateBack(), 1500)
|
|
} finally {
|
|
loading.value = false
|
|
}
|
|
}
|
|
|
|
// 多选框切换
|
|
const toggleMultiCheckbox = (field, value) => {
|
|
const index = formData.value[field].indexOf(value)
|
|
if (index > -1) {
|
|
formData.value[field].splice(index, 1)
|
|
} else {
|
|
formData.value[field].push(value)
|
|
}
|
|
}
|
|
|
|
const onDiagnosisTypeChange = (e) => {
|
|
formData.value.diagnosis_type = diagnosisTypeOptions.value[e.detail.value].value
|
|
}
|
|
|
|
const onSyndromeTypeChange = (e) => {
|
|
formData.value.syndrome_type = syndromeTypeOptions.value[e.detail.value].value
|
|
}
|
|
|
|
const onDiabetesTypeChange = (e) => {
|
|
formData.value.diabetes_type = diabetesTypeOptions.value[e.detail.value].value
|
|
}
|
|
|
|
const getDiagnosisTypeName = (type) => {
|
|
const item = diagnosisTypeOptions.value.find(i => i.value === type)
|
|
return item ? item.name : ''
|
|
}
|
|
|
|
const getSyndromeTypeName = (type) => {
|
|
const item = syndromeTypeOptions.value.find(i => i.value === type)
|
|
return item ? item.name : ''
|
|
}
|
|
|
|
const getDiabetesTypeName = (type) => {
|
|
const item = diabetesTypeOptions.value.find(i => i.value === type)
|
|
return item ? item.name : ''
|
|
}
|
|
|
|
const onDateChange = (e) => {
|
|
datePickerValue.value = e.detail.value
|
|
}
|
|
|
|
const confirmDate = () => {
|
|
const year = yearRange.value[datePickerValue.value[0]]
|
|
const month = String(monthRange.value[datePickerValue.value[1]]).padStart(2, '0')
|
|
const day = String(dayRange.value[datePickerValue.value[2]]).padStart(2, '0')
|
|
formData.value.diagnosis_date = `${year}-${month}-${day}`
|
|
showDatePicker.value = false
|
|
}
|
|
|
|
const submitForm = async () => {
|
|
if (!formData.value.patient_name) {
|
|
uni.showToast({ title: '患者姓名不能为空', icon: 'none' })
|
|
return
|
|
}
|
|
|
|
if (!formData.value.diagnosis_date) {
|
|
uni.showToast({ title: '诊断日期不能为空', icon: 'none' })
|
|
return
|
|
}
|
|
|
|
if (!formData.value.diagnosis_type) {
|
|
uni.showToast({ title: '诊断类型不能为空', icon: 'none' })
|
|
return
|
|
}
|
|
|
|
if (!formData.value.syndrome_type) {
|
|
uni.showToast({ title: '证型不能为空', icon: 'none' })
|
|
return
|
|
}
|
|
|
|
submitting.value = true
|
|
try {
|
|
// 处理数组字段,转换为逗号分隔的字符串
|
|
const submitData = { ...formData.value }
|
|
const arrayFields = ['diet_condition', 'body_feeling', 'sleep_condition', 'eye_condition', 'head_feeling', 'sweat_condition', 'skin_condition', 'urine_condition', 'stool_condition', 'kidney_condition', 'past_history']
|
|
arrayFields.forEach(field => {
|
|
if (Array.isArray(submitData[field])) {
|
|
submitData[field] = submitData[field].join(',')
|
|
}
|
|
})
|
|
|
|
const res = await proxy.apiUrl({
|
|
url: '/api/tcm/updateCard',
|
|
method: 'POST',
|
|
data: {
|
|
id: diagnosisId.value,
|
|
patient_id: patientId.value,
|
|
...submitData
|
|
}
|
|
})
|
|
|
|
if (res.code === 1) {
|
|
uni.showToast({ title: '保存成功', icon: 'success' })
|
|
setTimeout(() => {
|
|
uni.navigateBack()
|
|
}, 1500)
|
|
} else {
|
|
uni.showToast({ title: res.msg || '保存失败', icon: 'none' })
|
|
}
|
|
} catch (err) {
|
|
console.error('保存失败:', err)
|
|
uni.showToast({ title: '保存失败', icon: 'none' })
|
|
} finally {
|
|
submitting.value = false
|
|
}
|
|
}
|
|
|
|
const goBack = () => {
|
|
uni.navigateBack()
|
|
}
|
|
</script>
|
|
|
|
<style scoped>
|
|
.edit-container {
|
|
min-height: 100vh;
|
|
background: #f5f5f5;
|
|
}
|
|
|
|
.header {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
background: #ffffff;
|
|
padding: 20rpx 30rpx;
|
|
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.05);
|
|
}
|
|
|
|
.header-back {
|
|
font-size: 40rpx;
|
|
color: #1890ff;
|
|
width: 60rpx;
|
|
height: 60rpx;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
}
|
|
|
|
.header-title {
|
|
font-size: 36rpx;
|
|
font-weight: bold;
|
|
color: #333333;
|
|
flex: 1;
|
|
text-align: center;
|
|
}
|
|
|
|
.header-placeholder {
|
|
width: 60rpx;
|
|
}
|
|
|
|
.loading-state {
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
height: 100vh;
|
|
font-size: 28rpx;
|
|
color: #999999;
|
|
}
|
|
|
|
.form-wrapper {
|
|
padding: 30rpx;
|
|
}
|
|
|
|
.form-section {
|
|
background: #ffffff;
|
|
border-radius: 16rpx;
|
|
padding: 30rpx;
|
|
margin-bottom: 24rpx;
|
|
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.05);
|
|
}
|
|
|
|
.section-title {
|
|
font-size: 32rpx;
|
|
font-weight: bold;
|
|
color: #1890ff;
|
|
margin-bottom: 24rpx;
|
|
display: block;
|
|
padding-bottom: 16rpx;
|
|
border-bottom: 2rpx solid #f0f0f0;
|
|
}
|
|
|
|
.form-group {
|
|
margin-bottom: 24rpx;
|
|
}
|
|
|
|
.form-group:last-child {
|
|
margin-bottom: 0;
|
|
}
|
|
|
|
.form-label {
|
|
display: block;
|
|
font-size: 28rpx;
|
|
color: #333333;
|
|
font-weight: 500;
|
|
margin-bottom: 16rpx;
|
|
line-height: 1.5;
|
|
}
|
|
|
|
.form-input {
|
|
width: 100%;
|
|
padding: 20rpx;
|
|
border: 2rpx solid #e8e8e8;
|
|
border-radius: 12rpx;
|
|
font-size: 28rpx;
|
|
line-height: 1.5;
|
|
color: #333333;
|
|
background: #ffffff;
|
|
box-sizing: border-box;
|
|
display: block;
|
|
height: auto;
|
|
min-height: 60rpx;
|
|
}
|
|
|
|
.form-input::placeholder {
|
|
color: #cccccc;
|
|
}
|
|
|
|
.form-textarea {
|
|
width: 100%;
|
|
padding: 20rpx;
|
|
border: 2rpx solid #e8e8e8;
|
|
border-radius: 12rpx;
|
|
font-size: 28rpx;
|
|
line-height: 1.6;
|
|
color: #333333;
|
|
background: #ffffff;
|
|
box-sizing: border-box;
|
|
min-height: 140rpx;
|
|
display: block;
|
|
font-family: inherit;
|
|
}
|
|
|
|
.form-textarea::placeholder {
|
|
color: #cccccc;
|
|
}
|
|
|
|
.gender-group {
|
|
display: flex;
|
|
gap: 20rpx;
|
|
}
|
|
|
|
.gender-btn {
|
|
flex: 1;
|
|
padding: 20rpx;
|
|
border: 2rpx solid #e8e8e8;
|
|
border-radius: 12rpx;
|
|
text-align: center;
|
|
font-size: 28rpx;
|
|
line-height: 1.5;
|
|
color: #666666;
|
|
background: #ffffff;
|
|
transition: all 0.3s;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
min-height: 60rpx;
|
|
}
|
|
|
|
.gender-btn.active {
|
|
border-color: #1890ff;
|
|
background: #e6f7ff;
|
|
color: #1890ff;
|
|
font-weight: bold;
|
|
}
|
|
|
|
.radio-group {
|
|
display: flex;
|
|
gap: 20rpx;
|
|
}
|
|
|
|
.radio-item {
|
|
flex: 1;
|
|
padding: 16rpx 20rpx;
|
|
border: 2rpx solid #e8e8e8;
|
|
border-radius: 12rpx;
|
|
text-align: center;
|
|
font-size: 26rpx;
|
|
color: #666666;
|
|
background: #ffffff;
|
|
transition: all 0.3s;
|
|
}
|
|
|
|
.radio-item.active {
|
|
border-color: #1890ff;
|
|
background: #e6f7ff;
|
|
color: #1890ff;
|
|
font-weight: bold;
|
|
}
|
|
|
|
.checkbox-group {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: 12rpx;
|
|
}
|
|
|
|
.checkbox-item {
|
|
padding: 12rpx 20rpx;
|
|
border: 2rpx solid #e8e8e8;
|
|
border-radius: 20rpx;
|
|
font-size: 26rpx;
|
|
color: #666666;
|
|
background: #ffffff;
|
|
transition: all 0.3s;
|
|
}
|
|
|
|
.checkbox-item.active {
|
|
border-color: #1890ff;
|
|
background: #e6f7ff;
|
|
color: #1890ff;
|
|
font-weight: bold;
|
|
}
|
|
|
|
.multi-checkbox-group {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: 12rpx;
|
|
}
|
|
|
|
.multi-checkbox-item {
|
|
padding: 12rpx 20rpx;
|
|
border: 2rpx solid #e8e8e8;
|
|
border-radius: 20rpx;
|
|
font-size: 26rpx;
|
|
color: #666666;
|
|
background: #ffffff;
|
|
transition: all 0.3s;
|
|
}
|
|
|
|
.multi-checkbox-item.active {
|
|
border-color: #1890ff;
|
|
background: #e6f7ff;
|
|
color: #1890ff;
|
|
font-weight: bold;
|
|
}
|
|
|
|
.date-input {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
padding: 20rpx;
|
|
border: 2rpx solid #e8e8e8;
|
|
border-radius: 12rpx;
|
|
background: #ffffff;
|
|
font-size: 28rpx;
|
|
line-height: 1.5;
|
|
color: #333333;
|
|
min-height: 60rpx;
|
|
}
|
|
|
|
.date-icon {
|
|
font-size: 32rpx;
|
|
margin-left: 12rpx;
|
|
}
|
|
|
|
.picker-input {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
padding: 20rpx;
|
|
border: 2rpx solid #e8e8e8;
|
|
border-radius: 12rpx;
|
|
background: #ffffff;
|
|
font-size: 28rpx;
|
|
line-height: 1.5;
|
|
color: #333333;
|
|
min-height: 60rpx;
|
|
}
|
|
|
|
.picker-icon {
|
|
font-size: 20rpx;
|
|
color: #999999;
|
|
margin-left: 12rpx;
|
|
}
|
|
|
|
.button-group {
|
|
display: flex;
|
|
gap: 20rpx;
|
|
margin-top: 40rpx;
|
|
margin-bottom: 40rpx;
|
|
}
|
|
|
|
.btn {
|
|
flex: 1;
|
|
padding: 20rpx;
|
|
border-radius: 12rpx;
|
|
font-size: 32rpx;
|
|
font-weight: bold;
|
|
border: none;
|
|
cursor: pointer;
|
|
transition: all 0.3s;
|
|
}
|
|
|
|
.btn:active {
|
|
transform: scale(0.98);
|
|
}
|
|
|
|
.btn:disabled {
|
|
opacity: 0.6;
|
|
cursor: not-allowed;
|
|
}
|
|
|
|
.btn-cancel {
|
|
background: #f0f0f0;
|
|
color: #666666;
|
|
}
|
|
|
|
.btn-submit {
|
|
background: #1890ff;
|
|
color: #ffffff;
|
|
}
|
|
|
|
.btn-submit:active:not(:disabled) {
|
|
background: #0050b3;
|
|
}
|
|
|
|
.date-picker-overlay {
|
|
position: fixed;
|
|
top: 0;
|
|
left: 0;
|
|
right: 0;
|
|
bottom: 0;
|
|
background: rgba(0, 0, 0, 0.5);
|
|
display: flex;
|
|
flex-direction: column;
|
|
justify-content: flex-end;
|
|
z-index: 999;
|
|
}
|
|
|
|
.date-picker-container {
|
|
background: #ffffff;
|
|
border-radius: 20rpx 20rpx 0 0;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.date-picker-header {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
padding: 20rpx 30rpx;
|
|
border-bottom: 2rpx solid #f0f0f0;
|
|
}
|
|
|
|
.date-btn-cancel,
|
|
.date-btn-confirm {
|
|
font-size: 28rpx;
|
|
color: #1890ff;
|
|
font-weight: bold;
|
|
}
|
|
|
|
.date-picker-view {
|
|
height: 300rpx;
|
|
}
|
|
|
|
.picker-item {
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
height: 50px;
|
|
font-size: 28rpx;
|
|
color: #333333;
|
|
}
|
|
</style>
|