<template>
|
<view class="form-item">
|
<view class="form-label" :class="{ required: required }">{{ label }}</view>
|
<picker
|
v-if="!isHome && departmentOptions.length > 0"
|
mode="selector"
|
:range="departmentOptions"
|
range-key="text"
|
:value="selectedIndex"
|
@change="onDepartmentChange"
|
>
|
<view class="form-input picker-input">
|
{{ displayText }}
|
<uni-icons type="arrowright" size="16" color="#999"></uni-icons>
|
</view>
|
</picker>
|
<input
|
v-else-if="!isHome"
|
class="form-input"
|
placeholder="请输入科室"
|
:value="value"
|
@input="onDepartmentInput"
|
/>
|
<view v-else class="form-input picker-input disabled">
|
其它
|
</view>
|
</view>
|
</template>
|
|
<script>
|
import { getHospitalDepartments } from "@/api/dictionary"
|
|
export default {
|
name: 'DepartmentSelector',
|
props: {
|
// 标签文本
|
label: {
|
type: String,
|
default: '科室'
|
},
|
// 是否必填
|
required: {
|
type: Boolean,
|
default: false
|
},
|
// 当前选中的科室名称
|
value: {
|
type: String,
|
default: ''
|
},
|
// 当前选中的科室ID
|
departmentId: {
|
type: [Number, String],
|
default: null
|
},
|
// 是否为"家中"(如果是家中,显示"其它"且不可选择)
|
isHome: {
|
type: Boolean,
|
default: false
|
},
|
// 占位符
|
placeholder: {
|
type: String,
|
default: '请选择科室'
|
}
|
},
|
data() {
|
return {
|
departmentOptions: [], // 科室选项列表
|
selectedIndex: -1
|
}
|
},
|
computed: {
|
displayText() {
|
if (this.selectedIndex >= 0 && this.selectedIndex < this.departmentOptions.length) {
|
return this.departmentOptions[this.selectedIndex].text
|
}
|
return this.value || this.placeholder
|
}
|
},
|
watch: {
|
value: {
|
immediate: true,
|
handler(newVal) {
|
if (newVal) {
|
this.updateSelectedIndex(newVal)
|
} else {
|
this.selectedIndex = -1
|
}
|
}
|
},
|
departmentId: {
|
immediate: true,
|
handler(newVal) {
|
if (newVal) {
|
this.updateSelectedIndexById(newVal)
|
}
|
}
|
},
|
departmentOptions: {
|
immediate: true,
|
handler() {
|
if (this.value) {
|
this.updateSelectedIndex(this.value)
|
} else if (this.departmentId) {
|
this.updateSelectedIndexById(this.departmentId)
|
}
|
}
|
}
|
},
|
mounted() {
|
this.loadDepartments()
|
},
|
methods: {
|
// 加载科室数据
|
loadDepartments() {
|
getHospitalDepartments().then(response => {
|
const list = response.data || []
|
this.departmentOptions = list.map(item => ({
|
id: item.vID,
|
text: item.vtext,
|
dictValue: item.vtext
|
}))
|
}).catch(error => {
|
console.error('加载科室数据失败:', error)
|
this.departmentOptions = []
|
})
|
},
|
|
// 根据科室名称更新选中索引
|
updateSelectedIndex(departmentName) {
|
if (!departmentName || this.departmentOptions.length === 0) {
|
this.selectedIndex = -1
|
return
|
}
|
|
const index = this.departmentOptions.findIndex(d => d.text === departmentName)
|
this.selectedIndex = index !== -1 ? index : -1
|
},
|
|
// 根据科室ID更新选中索引
|
updateSelectedIndexById(departmentId) {
|
if (!departmentId || this.departmentOptions.length === 0) {
|
this.selectedIndex = -1
|
return
|
}
|
|
const index = this.departmentOptions.findIndex(d => d.id == departmentId)
|
this.selectedIndex = index !== -1 ? index : -1
|
},
|
|
// 科室选择变化(picker)
|
onDepartmentChange(e) {
|
const index = e.detail.value
|
|
// 安全检查:确保索引有效且选项存在
|
if (index < 0 || index >= this.departmentOptions.length) {
|
console.warn('科室选择索引越界:', index, '数组长度:', this.departmentOptions.length)
|
return
|
}
|
|
const selected = this.departmentOptions[index]
|
|
// 二次检查:确保选中项存在且有text属性
|
if (!selected || !selected.text) {
|
console.warn('科室选项数据异常:', selected)
|
return
|
}
|
|
this.selectedIndex = index
|
|
this.$emit('input', selected.text)
|
this.$emit('change', {
|
department: selected.text,
|
departmentId: selected.id
|
})
|
},
|
|
// 科室输入(手动输入)
|
onDepartmentInput(e) {
|
const department = e.detail.value
|
this.$emit('input', department)
|
this.$emit('change', {
|
department: department,
|
departmentId: null
|
})
|
}
|
}
|
}
|
</script>
|
|
<style lang="scss" scoped>
|
.form-item {
|
margin-bottom: 40rpx;
|
|
.form-label {
|
font-size: 28rpx;
|
margin-bottom: 15rpx;
|
color: #333;
|
|
&.required::before {
|
content: '*';
|
color: #ff0000;
|
margin-right: 5rpx;
|
}
|
}
|
|
.form-input {
|
width: 100%;
|
height: 70rpx;
|
padding: 0 20rpx;
|
border: 1rpx solid #eee;
|
border-radius: 10rpx;
|
font-size: 28rpx;
|
box-sizing: border-box;
|
|
&.picker-input {
|
display: flex;
|
align-items: center;
|
justify-content: space-between;
|
}
|
|
&.disabled {
|
background-color: #f5f5f5;
|
color: #999;
|
}
|
}
|
}
|
</style>
|