| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344 |
- <template>
- <el-dialog :model-value="visible" @update:model-value="$emit('update:visible', $event)" title="新增宠物" width="800px"
- destroy-on-close append-to-body>
- <el-tabs v-model="activeTab">
- <el-tab-pane label="基本信息" name="basic">
- <el-form :model="form" label-width="100px">
- <el-row>
- <el-col :span="24" style="display: flex; justify-content: center; margin-bottom: 20px">
- <el-upload class="avatar-uploader" action="#" :show-file-list="false" :auto-upload="false"
- :on-change="handleUploadFile">
- <el-avatar v-if="avatarDisplayUrl" :src="avatarDisplayUrl" :size="80" />
- <el-icon v-else class="avatar-uploader-icon">
- <Plus />
- </el-icon>
- </el-upload>
- </el-col>
- <el-col :span="12">
- <el-form-item label="宠物姓名" required><el-input v-model="form.name" /></el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="所属主人" required>
- <el-select v-model="form.userId" placeholder="选择主人" style="width: 100%" filterable disabled>
- <el-option v-for="user in userOptions" :key="user.id" :label="user.name" :value="user.id" />
- </el-select>
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="性别">
- <el-select v-model="form.gender" placeholder="请选择">
- <el-option v-for="dict in sys_pet_gender" :key="dict.value" :label="dict.label"
- :value="parseInt(dict.value)" />
- </el-select>
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="品种" required>
- <el-input v-model="form.breed" placeholder="请输入品种" style="width: 100%" />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="体型" required>
- <el-select v-model="form.size" style="width: 100%">
- <el-option v-for="dict in sys_pet_size" :key="dict.value" :label="dict.label" :value="dict.value" />
- </el-select>
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="体重(kg)" required><el-input-number v-model="form.weight" :min="0" :precision="1"
- style="width: 100%" /></el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="年龄(岁)" required><el-input-number v-model="form.age" :min="0"
- style="width: 100%" /></el-form-item>
- </el-col>
- <el-col :span="24">
- <el-form-item label="性格关键词"><el-input v-model="form.personality" placeholder="如:活泼、粘人" /></el-form-item>
- </el-col>
- <el-col :span="24">
- <el-form-item label="萌宠性格"><el-input v-model="form.cutePersonality" type="textarea"
- placeholder="详细描述" /></el-form-item>
- </el-col>
- <el-col :span="24">
- <el-form-item label="宠物标签">
- <el-select v-model="form.tagIds" multiple placeholder="选择标签" style="width: 100%">
- <el-option v-for="tag in allPetTags" :key="tag.id" :label="tag.name" :value="tag.id">
- <el-tag :type="tag.colorType || 'info'" effect="light" size="small">{{ tag.name }}</el-tag>
- </el-option>
- </el-select>
- </el-form-item>
- </el-col>
- </el-row>
- </el-form>
- </el-tab-pane>
- <el-tab-pane label="家庭信息" name="family">
- <el-form :model="form" label-width="120px">
- <el-form-item label="新来家庭时间">
- <el-date-picker v-model="form.arrivalTime" type="date" placeholder="选择日期" style="width: 100%" />
- </el-form-item>
- <el-form-item label="家庭房屋类型" required>
- <el-radio-group v-model="form.houseType">
- <el-radio v-for="dict in sys_house_type" :key="dict.value" :value="dict.value">{{ dict.label }}</el-radio>
- </el-radio-group>
- </el-form-item>
- <el-form-item label="入门方式" required>
- <el-radio-group v-model="form.entryMethod">
- <el-radio v-for="dict in sys_entry_method" :key="dict.value" :value="dict.value">{{ dict.label
- }}</el-radio>
- </el-radio-group>
- </el-form-item>
- <el-form-item label="密码" v-if="form.entryMethod === 'password'" required>
- <el-input v-model="form.entryPassword" placeholder="请输入门锁密码" />
- </el-form-item>
- <el-form-item label="钥匙位置" v-if="form.entryMethod === 'key'" required>
- <el-input v-model="form.keyLocation" placeholder="请输入钥匙存放位置" />
- </el-form-item>
- </el-form>
- </el-tab-pane>
- <el-tab-pane label="健康状况" name="health">
- <el-form :model="form" label-width="120px">
- <el-form-item label="健康状态" required>
- <el-radio-group v-model="form.healthStatus">
- <el-radio value="健康">健康</el-radio>
- <el-radio value="亚健康">亚健康</el-radio>
- <el-radio value="疾病">疾病</el-radio>
- </el-radio-group>
- </el-form-item>
- <el-form-item label="是否有攻击倾向" required>
- <el-switch v-model="form.aggression" active-text="是" inactive-text="否" :active-value="1"
- :inactive-value="0" />
- </el-form-item>
- <el-form-item label="疫苗情况" required>
- <el-radio-group v-model="form.vaccineStatus">
- <el-radio value="无">无</el-radio>
- <el-radio value="已打1次">已打1次</el-radio>
- <el-radio value="已打2次">已打2次</el-radio>
- <el-radio value="已打3次">已打3次</el-radio>
- </el-radio-group>
- </el-form-item>
- <el-form-item label="疫苗凭证">
- <el-upload class="avatar-uploader" action="#" :show-file-list="false" :auto-upload="false"
- :on-change="handleUploadVaccineCert">
- <img v-if="vaccineCertDisplayUrl" :src="vaccineCertDisplayUrl" class="avatar"
- style="width: 100px; height: 100px; object-fit: cover" />
- <el-icon v-else class="avatar-uploader-icon" style="width: 100px; height: 100px; line-height: 100px">
- <Plus />
- </el-icon>
- </el-upload>
- </el-form-item>
- <el-form-item label="既往病史" required>
- <el-input v-model="form.medicalHistory" type="textarea" placeholder="如有病史请记录" />
- </el-form-item>
- <el-form-item label="过敏史" required>
- <el-input v-model="form.allergies" type="textarea" placeholder="如有过敏源请记录" />
- </el-form-item>
- </el-form>
- </el-tab-pane>
- </el-tabs>
- <template #footer>
- <span class="dialog-footer">
- <el-button @click="$emit('update:visible', false)">取消</el-button>
- <el-button type="primary" :loading="submitLoading" @click="saveData">保存</el-button>
- </span>
- </template>
- </el-dialog>
- </template>
- <script setup>
- import { ref, reactive, watch, onMounted, getCurrentInstance, toRefs } from 'vue'
- import { ElMessage } from 'element-plus'
- import { globalHeaders } from '@/utils/request'
- import { addPetOnOrder } from '@/api/archieves/pet'
- import { getCustomer } from '@/api/archieves/customer'
- import { listAllTag } from '@/api/archieves/tag'
- const props = defineProps({
- visible: { type: Boolean, default: false },
- userId: { type: [String, Number], default: '' },
- userOptions: { type: Array, default: () => [] }
- })
- const emit = defineEmits(['update:visible', 'success'])
- const { proxy } = getCurrentInstance()
- const { sys_pet_gender, sys_pet_type, sys_pet_size, sys_house_type, sys_entry_method } = toRefs(
- proxy?.useDict('sys_pet_gender', 'sys_pet_type', 'sys_pet_size', 'sys_house_type', 'sys_entry_method')
- )
- const activeTab = ref('basic')
- const submitLoading = ref(false)
- const allPetTags = ref([])
- const avatarDisplayUrl = ref('')
- const vaccineCertDisplayUrl = ref('')
- const baseUrl = import.meta.env.VITE_APP_BASE_API
- const uploadUrl = baseUrl + '/resource/oss/upload'
- const form = reactive({
- userId: undefined,
- avatar: undefined,
- name: '',
- type: 0,
- gender: undefined,
- breed: '',
- birthday: '',
- age: 1,
- weight: 5,
- size: 'small',
- isSterilized: 0,
- arrivalTime: '',
- houseType: '',
- entryMethod: '',
- entryPassword: '',
- keyLocation: '',
- personality: '',
- cutePersonality: '',
- healthStatus: '健康',
- aggression: 0,
- vaccineStatus: '无',
- vaccineCert: undefined,
- medicalHistory: '',
- allergies: '',
- remark: '',
- tagIds: []
- })
- watch(() => props.visible, (val) => {
- if (val) {
- activeTab.value = 'basic'
- submitLoading.value = false
- avatarDisplayUrl.value = ''
- vaccineCertDisplayUrl.value = ''
- Object.assign(form, {
- userId: props.userId, avatar: undefined, name: '', type: 0, gender: undefined,
- breed: '', birthday: '', age: 1, weight: 5, size: 'small', isSterilized: 0,
- arrivalTime: '', houseType: '', entryMethod: '', entryPassword: '', keyLocation: '',
- personality: '', cutePersonality: '', healthStatus: '健康', aggression: 0,
- vaccineStatus: '无', vaccineCert: undefined, medicalHistory: '', allergies: '', remark: '', tagIds: []
- })
- // 自动从主人信息填充家庭信息重叠字段
- if (props.userId) {
- fetchAndFillOwnerInfo(props.userId)
- }
- }
- })
- const fetchAndFillOwnerInfo = (userId) => {
- getCustomer(userId).then((res) => {
- const data = res.data
- if (data) {
- form.houseType = data.houseType || form.houseType
- form.entryMethod = data.entryMethod || form.entryMethod
- form.entryPassword = data.entryPassword || form.entryPassword
- form.keyLocation = data.keyLocation || form.keyLocation
- }
- }).catch(() => {
- // 获取主人信息失败不影响新增宠物流程
- })
- }
- const loadTags = () => {
- listAllTag({ category: 'pet', status: 0 }).then((res) => {
- allPetTags.value = res.data || []
- })
- }
- const handleUploadFile = async (file) => {
- const formData = new FormData()
- formData.append('file', file.raw)
- try {
- const headers = globalHeaders()
- const res = await fetch(uploadUrl, {
- method: 'POST',
- headers: {
- 'Authorization': headers.Authorization,
- 'clientid': headers.clientid
- },
- body: formData
- })
- const result = await res.json()
- if (result.code === 200) {
- form.avatar = result.data.ossId
- avatarDisplayUrl.value = result.data.url
- } else {
- ElMessage.error(result.msg || '头像上传失败')
- }
- } catch (e) {
- ElMessage.error('头像上传失败')
- }
- }
- const handleUploadVaccineCert = async (file) => {
- const formData = new FormData()
- formData.append('file', file.raw)
- try {
- const headers = globalHeaders()
- const res = await fetch(uploadUrl, {
- method: 'POST',
- headers: {
- 'Authorization': headers.Authorization,
- 'clientid': headers.clientid
- },
- body: formData
- })
- const result = await res.json()
- if (result.code === 200) {
- form.vaccineCert = result.data.ossId
- vaccineCertDisplayUrl.value = result.data.url
- } else {
- ElMessage.error(result.msg || '疫苗凭证上传失败')
- }
- } catch (e) {
- ElMessage.error('疫苗凭证上传失败')
- }
- }
- const saveData = () => {
- if (!form.name) return ElMessage.warning('请输入宠物姓名')
- if (!form.userId) return ElMessage.warning('请先选择或新增所属主人')
- if (!form.breed) return ElMessage.warning('请输入品种');
- if (!form.size) return ElMessage.warning('请选择体型');
- if (form.weight === undefined || form.weight === null) return ElMessage.warning('请输入体重(kg)');
- if (form.age === undefined || form.age === null) return ElMessage.warning('请输入年龄(岁)');
- if (!form.houseType) return ElMessage.warning('请选择家庭房屋类型');
- if (!form.entryMethod) return ElMessage.warning('请选择入门方式');
- if (form.entryMethod === 'password' && !form.entryPassword) return ElMessage.warning('请输入门锁密码');
- if (form.entryMethod === 'key' && !form.keyLocation) return ElMessage.warning('请输入钥匙存放位置');
- if (!form.healthStatus) return ElMessage.warning('请选择健康状态');
- if (form.aggression === undefined || form.aggression === null) return ElMessage.warning('请选择是否有攻击倾向');
- if (!form.vaccineStatus) return ElMessage.warning('请选择疫苗情况');
- if (!form.medicalHistory) return ElMessage.warning('请输入既往病史');
- if (!form.allergies) return ElMessage.warning('请输入过敏史');
- submitLoading.value = true
- addPetOnOrder(form).then(res => {
- emit('success', res.data)
- emit('update:visible', false)
- }).finally(() => {
- submitLoading.value = false
- })
- }
- onMounted(() => {
- loadTags()
- })
- </script>
- <style scoped>
- .avatar-uploader-icon {
- font-size: 28px;
- color: #8c939d;
- width: 80px;
- height: 80px;
- text-align: center;
- border: 1px dashed #dcdfe6;
- border-radius: 50%;
- display: flex;
- justify-content: center;
- align-items: center;
- }
- .avatar-uploader-icon:hover {
- border-color: var(--el-color-primary);
- }
- </style>
|