Files
zyt/TUICallKit-Vue3/pages/Card/edit_card.vue
T
2026-03-11 09:49:47 +08:00

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>