猫妈狗爸伴宠师小程序前端代码
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1163 lines
37 KiB

3 months ago
2 weeks ago
3 months ago
3 months ago
3 months ago
2 weeks ago
3 months ago
2 weeks ago
3 months ago
2 weeks ago
3 months ago
3 months ago
3 months ago
2 weeks ago
2 weeks ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
2 weeks ago
3 months ago
2 weeks ago
3 months ago
3 months ago
2 weeks ago
3 months ago
2 weeks ago
2 weeks ago
2 weeks ago
3 months ago
2 weeks ago
3 months ago
2 weeks ago
2 weeks ago
3 months ago
3 months ago
2 weeks ago
3 months ago
2 weeks ago
3 months ago
3 months ago
3 months ago
2 weeks ago
3 months ago
2 weeks ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
2 weeks ago
2 weeks ago
  1. <template>
  2. <view class="personal-pet-cat container">
  3. <view class="personal-pet-img">
  4. <view class="personal-pet-info-title">
  5. 宠物头像
  6. </view>
  7. <view style="display: flex;justify-content: center;">
  8. <u-upload accept="image" :capture="['album','camera']" :fileList="fileList" @afterRead="afterRead"
  9. @delete="deletePic" :max-count="1" name="pet" width="60" height="60" :custom-style="{flex:0}">
  10. <image src="https://catmdogf.oss-cn-shanghai.aliyuncs.com/CMDF/front/personal/index/cat_new.png"
  11. style="width: 60px;height: 60px;"></image>
  12. </u-upload>
  13. </view>
  14. </view>
  15. <!-- 宠物基本信息 -->
  16. <view class="personal-pet-basic-info">
  17. <view class="personal-pet-info-title border-bottom">
  18. 宠物基本信息
  19. </view>
  20. <u--form labelPosition="left" :model="petBaseInfo" ref="uForm">
  21. <u-form-item required label="昵称" :prop="`petBaseInfo.nickName`" labelWidth="80" borderBottom>
  22. <u--input v-model="petBaseInfo.nickName" placeholder="请输入宠物昵称"
  23. placeholderStyle="text-align:right;color:#AAA" border="none" inputAlign="right"></u--input>
  24. </u-form-item>
  25. <u-form-item label="性别" :prop="`petBaseInfo.sex`" labelWidth="80" borderBottom @click="showSex = true">
  26. <u--input v-model="sexText" disabled disabledColor="#ffffff" placeholder="请选择"
  27. placeholderStyle="text-align:right;color:#AAA" border="none" inputAlign="right"></u--input>
  28. <u-icon slot="right" name="arrow-right" color="#AAA"></u-icon>
  29. </u-form-item>
  30. <u-form-item required label="品种" :prop="`petBaseInfo.type`" labelWidth="80" borderBottom>
  31. <u--input v-model="petBaseInfo.type" placeholder="请输入"
  32. placeholderStyle="text-align:right;color:#AAA" border="none" inputAlign="right"></u--input>
  33. <u-icon slot="right" name="arrow-right" color="#AAA"></u-icon>
  34. </u-form-item>
  35. <u-form-item required label="体重" :prop="`petBaseInfo.weight`" labelWidth="80" borderBottom ref="item1">
  36. <u--input v-model="petBaseInfo.weight" placeholder="请输入(单位kg)"
  37. placeholderStyle="text-align:right;color:#AAA" border="none" inputAlign="right" type="number"></u--input>
  38. <u-icon slot="right" name="arrow-right" color="#AAA"></u-icon>
  39. </u-form-item>
  40. <u-form-item label="出生年月" :prop="`petBaseInfo.birthday`" labelWidth="80" borderBottom
  41. @click="yearMonthOpen">
  42. <u--input v-model="petBaseInfo.birthday" disabled disabledColor="#ffffff" placeholder="请选择"
  43. placeholderStyle="text-align:right;color:#AAA" border="none" inputAlign="right"></u--input>
  44. <u-icon slot="right" name="arrow-right" color="#AAA"></u-icon>
  45. </u-form-item>
  46. <u-form-item required label="性格" :prop="`petBaseInfo.personality`" labelWidth="80" borderBottom
  47. @click="dispositionSelectOpen">
  48. <u--input v-model="personalityText" disabled disabledColor="#ffffff" placeholder="请选择"
  49. placeholderStyle="text-align:right;color:#AAA" border="none" inputAlign="right"></u--input>
  50. <u-icon slot="right" name="arrow-right" color="#AAA"></u-icon>
  51. </u-form-item>
  52. </u--form>
  53. </view>
  54. <!-- 性格选择弹窗 -->
  55. <view style="background-color: #fffcf2;padding: 10px 20px;" v-show="showDisposition">
  56. <view style="height: 85%;">
  57. <u-checkbox-group v-model="tempPersonality" @change="personalityCheckboxChange" iconPlacement="left"
  58. placement="row" style="flex-wrap: wrap;" activeColor="#ffbf60">
  59. <u-checkbox :customStyle="{margin: '8px'}" v-for="(item, index) in dispositionActions" :key="item"
  60. :label="item" :name="item">
  61. </u-checkbox>
  62. </u-checkbox-group>
  63. <view class="personal-pet-disposition-btns">
  64. <view class="personal-pet-disposition-btn">
  65. <u-button color="#FFF4E4" @click="dispositionSelectClose">
  66. <view style="color: #A9A9A9;">
  67. 取消
  68. </view>
  69. </u-button>
  70. </view>
  71. <view class="personal-pet-disposition-btn" @click="dispositionSelectConfirm">
  72. <u-button color="#FFBF60">
  73. <view style="color: #fff;">
  74. 确定
  75. </view>
  76. </u-button>
  77. </view>
  78. </view>
  79. </view>
  80. </view>
  81. <!-- 宠物健康信息 -->
  82. <view class="personal-pet-health-info">
  83. <view class="personal-pet-info-title border-bottom">
  84. 宠物健康情况
  85. </view>
  86. <u--form labelPosition="left" :model="petHealthInfo" ref="uHealthForm">
  87. <u-form-item required label="疫苗" :prop="`petHealthInfo.vaccine`" labelWidth="80" borderBottom
  88. @click="showVaccine = true">
  89. <u--input v-model="vaccineText" disabled disabledColor="#ffffff" placeholder="请选择"
  90. placeholderStyle="text-align:right;color:#AAA" border="none" inputAlign="right"></u--input>
  91. <u-icon slot="right" name="arrow-right" color="#AAA"></u-icon>
  92. </u-form-item>
  93. <u-form-item required label="驱虫" :prop="`petHealthInfo.deworm`" labelWidth="80" borderBottom
  94. @click="showExpelling = true">
  95. <u--input v-model="dewormText" disabled disabledColor="#ffffff" placeholder="请选择"
  96. placeholderStyle="text-align:right;color:#AAA" border="none" inputAlign="right"></u--input>
  97. <u-icon slot="right" name="arrow-right" color="#AAA"></u-icon>
  98. </u-form-item>
  99. <u-form-item label="绝育" :prop="`petHealthInfo.neutered`" labelWidth="80" borderBottom
  100. @click="showSterilization = true">
  101. <u--input v-model="neuteredText" disabled disabledColor="#ffffff" placeholder="请选择"
  102. placeholderStyle="text-align:right;color:#AAA" border="none" inputAlign="right"></u--input>
  103. <u-icon slot="right" name="arrow-right" color="#AAA"></u-icon>
  104. </u-form-item>
  105. <u-form-item v-if="petType === '1' || petType === '狗狗' " label="狗证" :prop="`petHealthInfo.petCard`"
  106. labelWidth="80" borderBottom @click="showDog = true">
  107. <u--input v-model="petCartText" disabled disabledColor="#ffffff" placeholder="请选择"
  108. placeholderStyle="text-align:right;color:#AAA" border="none" inputAlign="right"></u--input>
  109. <u-icon slot="right" name="arrow-right" color="#AAA"></u-icon>
  110. </u-form-item>
  111. <view class="dog-tips" v-if="petType === 'dog' || petType === '狗狗'">
  112. <u-icon name="info-circle" color="#A94F20" size="12"></u-icon>
  113. <view style="margin-left: 3px;">
  114. 未办理养犬许可证且需要外出遛狗, 犬只存在被相关单位收缴
  115. 甚至捕杀的可能请您遵守当地养犬规范合法文明养犬具体
  116. 请您查看当地养犬条例
  117. </view>
  118. </view>
  119. <u-form-item required label="健康" :prop="`petHealthInfo.health`" labelWidth="80" @click="healthsSelect">
  120. <u--input v-model="healthText" disabled disabledColor="#ffffff" placeholder="请选择"
  121. placeholderStyle="text-align:right;color:#AAA" border="none" inputAlign="right"></u--input>
  122. <view slot="right">
  123. <u-icon v-if="showHealths" name="arrow-down" color="#AAA"></u-icon>
  124. <u-icon v-else name="arrow-right" color="#AAA"></u-icon>
  125. </view>
  126. </u-form-item>
  127. </u--form>
  128. </view>
  129. <!-- 健康选择弹窗 -->
  130. <view class="health-select" v-show="showHealths">
  131. <view style="padding: 10px;height: 85%;">
  132. <u-checkbox-group v-model="tempHealthStatus" @change="healthCheckboxChange" placement="column"
  133. activeColor="#ffbf60">
  134. <u-checkbox :customStyle="{marginBottom: '8px'}" v-for="(item, index) in healthData" :key="index"
  135. :label="item" :name="item">
  136. </u-checkbox>
  137. </u-checkbox-group>
  138. <!-- 只有选择了"其他"才显示输入框 -->
  139. <view v-if="tempHealthStatus && tempHealthStatus.includes('其他')" style="margin-top: 10px;">
  140. <u--input placeholder="请输入其他健康特征"
  141. border="surround" maxlength='20'
  142. :customStyle="{backgroundColor: '#fff', borderColor: '#ffbf60'}"
  143. v-model="tempRemark"></u--input>
  144. </view>
  145. <view class="health-select-btns">
  146. <view class="health-select-btn">
  147. <u-button color="#FFF4E4" @click="healthSelectClose">
  148. <view style="color: #A9A9A9;">
  149. 取消
  150. </view>
  151. </u-button>
  152. </view>
  153. <view class="health-select-btn" @click="healthSelectConfirm">
  154. <u-button color="#FFBF60">
  155. <view style="color: #fff;">
  156. 确定
  157. </view>
  158. </u-button>
  159. </view>
  160. </view>
  161. </view>
  162. </view>
  163. <!-- 各种选择器 -->
  164. <u-picker :show="showSex" :columns="sexActions" @cancel="showSex = false" @confirm="sexSelect"></u-picker>
  165. <u-picker :show="showVaccine" :columns="vaccineActions" @cancel="showVaccine = false"
  166. :immediateChange="true" @confirm="vaccineSelect"></u-picker>
  167. <u-picker :show="showExpelling" :columns="expellingActions" @cancel="showExpelling = false"
  168. :immediateChange="true" @confirm="expellingSelect"></u-picker>
  169. <u-picker :show="showSterilization" :columns="sterilizationActions"
  170. @cancel="showSterilization = false" :immediateChange="true" @confirm="sterilizationSelect"></u-picker>
  171. <u-picker :show="showDog" :columns="dogActions" @cancel="showDog = false"
  172. :immediateChange="true" @confirm="dogSelect"></u-picker>
  173. <u-datetime-picker :maxDate='getMaxDate()' :minDate="getMinDate()" :show="showBirthday" v-model="tempBirthday"
  174. mode="year-month" @confirm="yearMonthConfirm" @cancel="yearMonthClose"></u-datetime-picker>
  175. <view class="personal-pet-info-btns">
  176. <view class="personal-pet-btns">
  177. <view class="personal-pet-btn">
  178. <u-button color="#FFF4E4" @click="cancelPet">
  179. <view style="color: #A9A9A9;">
  180. 取消
  181. </view>
  182. </u-button>
  183. </view>
  184. <view class="personal-pet-btn" @click="save">
  185. <u-button color="#FFBF60" :loading="loading">
  186. <view style="color: #fff;">
  187. 保存
  188. </view>
  189. </u-button>
  190. </view>
  191. </view>
  192. </view>
  193. <u-modal :show="showDel" @confirm="confirmDel" @cancel="showDel = false" ref="uModal" showCancelButton
  194. :asyncClose="true" :content="delContent">
  195. </u-modal>
  196. </view>
  197. </template>
  198. <script setup>
  199. import {
  200. ref,
  201. onMounted,
  202. computed
  203. } from 'vue';
  204. import {
  205. addPet,
  206. getPetDetails,
  207. updatePet,
  208. delByPetId
  209. } from '@/api/pet/index.js';
  210. import {
  211. useRoute,
  212. useRouter
  213. } from 'vue-router';
  214. import {
  215. onLoad
  216. } from '@dcloudio/uni-app'
  217. const route = useRoute();
  218. const router = useRouter();
  219. const loading = ref(false);
  220. const fileList = ref([]);
  221. const petId = ref('');
  222. const userId = ref('');
  223. const petType = ref('dog');
  224. const optionType = ref('add');
  225. const isNewOrder = ref(false);
  226. const delContent = ref('');
  227. const headImage = ref('');
  228. // 宠物基本信息
  229. const petBaseInfo = ref({
  230. nickName: '',
  231. sex: '',
  232. type: '',
  233. weight: '',
  234. birthday: '',
  235. personality: ''
  236. });
  237. // 宠物健康信息
  238. const petHealthInfo = ref({
  239. vaccine: '',
  240. deworm: '',
  241. neutered: '',
  242. petCard: '',
  243. health: '',
  244. remark: ''
  245. });
  246. const showDel = ref(false);
  247. const uModal = ref(null);
  248. // 基本信息相关的响应式数据
  249. const showSex = ref(false);
  250. const showBirthday = ref(false);
  251. const showDisposition = ref(false);
  252. const sexActions = ref([
  253. ['男生', '女生']
  254. ]);
  255. const dispositionActions = ref([
  256. '友善热情', '害羞胆怯', '比较顽皮', '粘人乖巧', '顽皮捣蛋', '内向胆小', '有攻击性'
  257. ]);
  258. const tempBirthday = ref('');
  259. const tempPersonality = ref([]);
  260. const uForm = ref(null);
  261. const item1 = ref(null);
  262. // 健康信息相关的响应式数据
  263. const showVaccine = ref(false);
  264. const showExpelling = ref(false);
  265. const showSterilization = ref(false);
  266. const showDog = ref(false);
  267. const showHealths = ref(false);
  268. const vaccineActions = ref([
  269. ['每年都免疫', '有免疫史', '未免疫']
  270. ]);
  271. const expellingActions = ref([
  272. ['未驱虫', '定期驱虫', '有驱虫史']
  273. ]);
  274. const sterilizationActions = ref([
  275. ['已绝育', '未绝育']
  276. ]);
  277. const dogActions = ref([
  278. ['是', '否']
  279. ]);
  280. const healthData = ref([
  281. '身体健康,无异常',
  282. '近3个月有做过手术',
  283. '有过往病史、过敏史',
  284. '宠物食欲及肠胃不佳',
  285. '宠物部分身体部位有受伤',
  286. '宠物皮肤敏感或正患有皮肤疾病',
  287. '其他'
  288. ]);
  289. const tempHealthStatus = ref([]);
  290. const tempRemark = ref('');
  291. const uHealthForm = ref(null);
  292. // 计算属性
  293. const sexText = computed(() => {
  294. const sexMap = {
  295. 0: '男生',
  296. 1: '女生'
  297. };
  298. return sexMap[petBaseInfo.value.sex] || '';
  299. });
  300. const personalityText = computed(() => {
  301. if (petBaseInfo.value.personality) {
  302. // 如果是字符串,直接返回
  303. if (typeof petBaseInfo.value.personality === 'string') {
  304. return petBaseInfo.value.personality;
  305. }
  306. // 如果是数组,转换为逗号分隔的字符串
  307. if (Array.isArray(petBaseInfo.value.personality) && petBaseInfo.value.personality.length > 0) {
  308. return petBaseInfo.value.personality.join(',');
  309. }
  310. }
  311. return '';
  312. });
  313. const vaccineText = computed(() => {
  314. const vaccineMap = {
  315. 0: '每年都免疫',
  316. 1: '有免疫史',
  317. 2: '未免疫'
  318. };
  319. return vaccineMap[petHealthInfo.value.vaccine] || ''
  320. });
  321. const dewormText = computed(() => {
  322. const dewormMap = {
  323. 0: '未驱虫',
  324. 1: '定期驱虫',
  325. 2: '有驱虫史'
  326. };
  327. return dewormMap[petHealthInfo.value.deworm] || ''
  328. });
  329. const neuteredText = computed(() => {
  330. const neuteredMap = {
  331. 0: '已绝育',
  332. 1: '未绝育'
  333. };
  334. return neuteredMap[petHealthInfo.value.neutered] || ''
  335. });
  336. const petCartText = computed(() => {
  337. const petCartMap = {
  338. 0: '是',
  339. 1: '否'
  340. };
  341. return petCartMap[petHealthInfo.value.petCard] || ''
  342. });
  343. const healthText = computed(() => {
  344. if (petHealthInfo.value.health) {
  345. let healthDisplay = '';
  346. // 如果是字符串,直接使用
  347. if (typeof petHealthInfo.value.health === 'string') {
  348. healthDisplay = petHealthInfo.value.health;
  349. }
  350. // 如果是数组,转换为逗号分隔的字符串
  351. else if (Array.isArray(petHealthInfo.value.health) && petHealthInfo.value.health.length > 0) {
  352. healthDisplay = petHealthInfo.value.health.join(',');
  353. }
  354. // 处理"其他"选项的显示
  355. if (healthDisplay.includes('其他') && petHealthInfo.value.remark) {
  356. healthDisplay = healthDisplay.replace('其他', `其他:${petHealthInfo.value.remark}`);
  357. }
  358. return healthDisplay;
  359. }
  360. return '';
  361. });
  362. onLoad((option) => {
  363. petType.value = option.petType;
  364. userId.value = option.userId
  365. optionType.value = option.optionType;
  366. if (optionType.value === 'edit') {
  367. petId.value = option.petId;
  368. getPetDetailsFunc(option.petId);
  369. }
  370. if (option.isNewOrder) {
  371. isNewOrder.value = true;
  372. }
  373. });
  374. const deletePic = (event) => {
  375. fileList.value.splice(event.index, 1);
  376. };
  377. const afterRead = async (event) => {
  378. let lists = [].concat(event.file);
  379. let fileListLen = fileList.value.length;
  380. lists.map((item) => {
  381. fileList.value.push({
  382. ...item,
  383. status: 'uploading',
  384. message: '上传中'
  385. });
  386. });
  387. for (let i = 0; i < lists.length; i++) {
  388. const result = await uploadFilePromise(lists[i].url);
  389. let item = fileList.value[fileListLen];
  390. fileList.value.splice(fileListLen, 1, Object.assign(item, {
  391. status: 'success',
  392. message: '',
  393. url: result
  394. }));
  395. fileListLen++;
  396. }
  397. };
  398. const uploadFilePromise = (url) => {
  399. return new Promise((resolve, reject) => {
  400. uni.uploadFile({
  401. url: 'https://store-test.catmdogd.com/test-api/h5/oss/upload',
  402. filePath: url,
  403. name: 'file',
  404. formData: {
  405. user: 'test'
  406. },
  407. success: (res) => {
  408. setTimeout(() => {
  409. if (res && res.data) {
  410. let resData = JSON.parse(res.data);
  411. resolve(resData.url);
  412. }
  413. reject("上传失败");
  414. }, 1000);
  415. }
  416. });
  417. });
  418. };
  419. const getPetDetailsFunc = (petId) => {
  420. getPetDetails({
  421. id: petId
  422. }).then((res) => {
  423. if (res.code == 200) {
  424. const {
  425. headImage,
  426. nickName,
  427. sex,
  428. type,
  429. weight,
  430. birthday,
  431. personality,
  432. vaccine,
  433. deworm,
  434. neutered,
  435. petCard,
  436. health,
  437. remark
  438. } = res.data;
  439. console.log('=== 后端返回的原始数据 ===');
  440. console.log('birthday:', birthday);
  441. console.log('personality:', personality);
  442. console.log('health:', health);
  443. console.log('remark:', remark);
  444. // 处理日期格式:从 "yyyy-MM-dd HH:mm:ss" 转换为 "yyyy-MM"
  445. let processedBirthday = '';
  446. if (birthday) {
  447. if (typeof birthday === 'string' && birthday.length >= 7) {
  448. processedBirthday = birthday.substring(0, 7); // 取前7位 "yyyy-MM"
  449. } else {
  450. processedBirthday = birthday;
  451. }
  452. }
  453. // 处理性格数据:从逗号分隔字符串转换为原始格式(保持字符串,在打开时转换为数组)
  454. let processedPersonality = '';
  455. if (personality) {
  456. // 统一逗号格式,将英文逗号转换为中文逗号用于显示
  457. processedPersonality = personality.replace(/,/g, ',');
  458. }
  459. // 处理健康数据:从逗号分隔字符串转换为原始格式(保持字符串,在打开时转换为数组)
  460. let processedHealth = '';
  461. if (health) {
  462. // 统一逗号格式,将英文逗号转换为中文逗号用于显示
  463. processedHealth = health.replace(/,/g, ',');
  464. }
  465. console.log('=== 处理后的数据 ===');
  466. console.log('processedBirthday:', processedBirthday);
  467. console.log('processedPersonality:', processedPersonality);
  468. console.log('processedHealth:', processedHealth);
  469. petBaseInfo.value = {
  470. nickName,
  471. sex,
  472. type,
  473. weight,
  474. birthday: processedBirthday,
  475. personality: processedPersonality
  476. };
  477. petHealthInfo.value = {
  478. vaccine,
  479. deworm,
  480. neutered,
  481. petCard,
  482. health: processedHealth,
  483. remark
  484. };
  485. fileList.value = [{
  486. url: headImage
  487. }];
  488. console.log('=== 最终设置的数据 ===');
  489. console.log('petBaseInfo:', petBaseInfo.value);
  490. console.log('petHealthInfo:', petHealthInfo.value);
  491. } else {
  492. uni.showToast({
  493. title: '获取pet失败',
  494. duration: 3000,
  495. icon: "none"
  496. });
  497. }
  498. });
  499. };
  500. // 基本信息相关方法
  501. const sexSelect = (e) => {
  502. petBaseInfo.value.sex = e.indexs[0];
  503. showSex.value = false;
  504. console.log('性别选择:', petBaseInfo.value.sex);
  505. };
  506. const yearMonthOpen = () => {
  507. if (petBaseInfo.value.birthday) {
  508. tempBirthday.value = Number(new Date(petBaseInfo.value.birthday));
  509. } else {
  510. tempBirthday.value = Number(new Date());
  511. }
  512. showBirthday.value = true;
  513. };
  514. const yearMonthClose = () => {
  515. showBirthday.value = false;
  516. };
  517. const yearMonthConfirm = (e) => {
  518. const timeFormat = uni.$u.timeFormat;
  519. petBaseInfo.value.birthday = timeFormat(e.value, 'yyyy-mm');
  520. showBirthday.value = false;
  521. console.log('生日选择:', petBaseInfo.value.birthday);
  522. };
  523. const dispositionSelectOpen = () => {
  524. // 将字符串转换为数组,或者如果已经是数组就直接使用
  525. console.log('=== 打开性格选择弹窗 ===');
  526. console.log('当前性格数据:', petBaseInfo.value.personality, '类型:', typeof petBaseInfo.value.personality);
  527. if (typeof petBaseInfo.value.personality === 'string' && petBaseInfo.value.personality.trim() !== '') {
  528. // 同时支持中文逗号和英文逗号分隔
  529. let personalityArray = petBaseInfo.value.personality.split(/[,,]/).map(item => item.trim()).filter(item => item !== '');
  530. tempPersonality.value = personalityArray;
  531. console.log('从字符串解析的性格数组:', personalityArray);
  532. } else if (Array.isArray(petBaseInfo.value.personality)) {
  533. tempPersonality.value = petBaseInfo.value.personality || [];
  534. console.log('直接使用数组:', petBaseInfo.value.personality);
  535. } else {
  536. tempPersonality.value = [];
  537. console.log('设置为空数组');
  538. }
  539. console.log('最终tempPersonality.value:', tempPersonality.value);
  540. console.log('=== 性格弹窗准备完成 ===');
  541. showDisposition.value = true;
  542. };
  543. const dispositionSelectClose = () => {
  544. // 恢复到原来的状态,而不是清空
  545. if (typeof petBaseInfo.value.personality === 'string' && petBaseInfo.value.personality.trim() !== '') {
  546. let personalityArray = petBaseInfo.value.personality.split(/[,,]/).map(item => item.trim()).filter(item => item !== '');
  547. tempPersonality.value = personalityArray;
  548. } else {
  549. tempPersonality.value = [];
  550. }
  551. showDisposition.value = false;
  552. };
  553. const dispositionSelectConfirm = () => {
  554. // 将数组转换为逗号分隔的字符串保存到后端
  555. console.log('=== 性格选择确认开始 ===');
  556. console.log('tempPersonality.value:', tempPersonality.value);
  557. console.log('tempPersonality类型:', typeof tempPersonality.value);
  558. console.log('tempPersonality长度:', tempPersonality.value?.length);
  559. // 检查是否至少选择了一个性格
  560. if (!tempPersonality.value || tempPersonality.value.length === 0) {
  561. uni.showToast({
  562. title: '请至少选择一个性格特征!',
  563. duration: 2000,
  564. icon: "none"
  565. });
  566. return;
  567. }
  568. const personalityString = tempPersonality.value.join(',');
  569. console.log('转换后的personalityString:', personalityString);
  570. console.log('personalityString长度:', personalityString.length);
  571. petBaseInfo.value.personality = personalityString;
  572. // 保持tempPersonality和petBaseInfo.personality的同步,确保提交时使用正确的数据
  573. console.log('保存后petBaseInfo.value.personality:', petBaseInfo.value.personality);
  574. console.log('保存后personalityText.value:', personalityText.value);
  575. console.log('=== 性格选择确认完成 ===');
  576. showDisposition.value = false;
  577. };
  578. const personalityCheckboxChange = (n) => {
  579. console.log('性格checkbox变化:', n, tempPersonality.value);
  580. };
  581. const getMaxDate = () => {
  582. return Date.now();
  583. };
  584. const getMinDate = () => {
  585. let dt = new Date();
  586. dt.setFullYear(dt.getFullYear() - 30);
  587. return Date.parse(dt);
  588. };
  589. // 健康信息相关方法
  590. const vaccineSelect = (e) => {
  591. petHealthInfo.value.vaccine = e.indexs[0];
  592. showVaccine.value = false;
  593. console.log('疫苗选择:', petHealthInfo.value.vaccine);
  594. };
  595. const expellingSelect = (e) => {
  596. petHealthInfo.value.deworm = e.indexs[0];
  597. showExpelling.value = false;
  598. console.log('驱虫选择:', petHealthInfo.value.deworm);
  599. };
  600. const sterilizationSelect = (e) => {
  601. petHealthInfo.value.neutered = e.indexs[0];
  602. showSterilization.value = false;
  603. console.log('绝育选择:', petHealthInfo.value.neutered);
  604. };
  605. const dogSelect = (e) => {
  606. petHealthInfo.value.petCard = e.indexs[0];
  607. showDog.value = false;
  608. console.log('狗证选择:', petHealthInfo.value.petCard);
  609. };
  610. const healthsSelect = () => {
  611. // 初始化临时健康状态和备注
  612. console.log('=== 打开健康选择弹窗 ===');
  613. console.log('当前健康数据:', petHealthInfo.value.health, '类型:', typeof petHealthInfo.value.health);
  614. console.log('当前备注数据:', petHealthInfo.value.remark);
  615. if (typeof petHealthInfo.value.health === 'string' && petHealthInfo.value.health.trim() !== '') {
  616. // 同时支持中文逗号和英文逗号分隔
  617. let healthArray = petHealthInfo.value.health.split(/[,,]/).map(item => item.trim()).filter(item => item !== '');
  618. // 处理"其他:xxx"格式的数据
  619. let processedHealthArray = [];
  620. let otherRemark = '';
  621. healthArray.forEach(item => {
  622. if (item.startsWith('其他:')) {
  623. processedHealthArray.push('其他');
  624. otherRemark = item.substring(3); // 去掉"其他:"前缀
  625. } else {
  626. processedHealthArray.push(item);
  627. }
  628. });
  629. tempHealthStatus.value = processedHealthArray;
  630. // 如果从健康数据中解析出了"其他"的备注,优先使用它
  631. tempRemark.value = otherRemark || petHealthInfo.value.remark || '';
  632. console.log('从字符串解析的健康数组:', processedHealthArray);
  633. console.log('解析出的其他备注:', otherRemark);
  634. } else if (Array.isArray(petHealthInfo.value.health)) {
  635. tempHealthStatus.value = petHealthInfo.value.health || [];
  636. tempRemark.value = petHealthInfo.value.remark || '';
  637. console.log('直接使用数组:', petHealthInfo.value.health);
  638. } else {
  639. tempHealthStatus.value = [];
  640. tempRemark.value = petHealthInfo.value.remark || '';
  641. console.log('设置为空数组');
  642. }
  643. console.log('最终tempHealthStatus.value:', tempHealthStatus.value);
  644. console.log('最终tempRemark.value:', tempRemark.value);
  645. console.log('=== 健康弹窗准备完成 ===');
  646. showHealths.value = true;
  647. uni.pageScrollTo({
  648. scrollTop: 2000,
  649. duration: 300
  650. });
  651. };
  652. const healthSelectClose = () => {
  653. tempHealthStatus.value = [];
  654. tempRemark.value = '';
  655. showHealths.value = false;
  656. };
  657. const healthSelectConfirm = () => {
  658. // 将数组转换为逗号分隔的字符串保存到后端
  659. console.log('=== 健康选择确认开始 ===');
  660. console.log('tempHealthStatus.value:', tempHealthStatus.value);
  661. console.log('tempHealthStatus类型:', typeof tempHealthStatus.value);
  662. console.log('tempHealthStatus长度:', tempHealthStatus.value?.length);
  663. console.log('tempRemark.value:', tempRemark.value);
  664. console.log('tempRemark是否有值:', tempRemark.value && tempRemark.value.trim() !== '');
  665. // 检查是否至少选择了一个健康状态
  666. if (!tempHealthStatus.value || tempHealthStatus.value.length === 0) {
  667. uni.showToast({
  668. title: '请至少选择一个健康状态!',
  669. duration: 2000,
  670. icon: "none"
  671. });
  672. return;
  673. }
  674. let healthArray = [...tempHealthStatus.value];
  675. console.log('原始healthArray:', healthArray);
  676. console.log('是否包含其他:', healthArray.includes('其他'));
  677. // 处理"其他"选项 - 如果选择了"其他"且有备注,合并为"其他:备注"
  678. if (healthArray.includes('其他') && tempRemark.value && tempRemark.value.trim() !== '') {
  679. const otherIndex = healthArray.indexOf('其他');
  680. const newOtherValue = `其他:${tempRemark.value.trim()}`;
  681. healthArray[otherIndex] = newOtherValue;
  682. console.log('替换其他选项:', newOtherValue);
  683. }
  684. const healthString = healthArray.join(',');
  685. console.log('转换后的healthString:', healthString);
  686. console.log('healthString长度:', healthString.length);
  687. petHealthInfo.value.health = healthString;
  688. petHealthInfo.value.remark = tempRemark.value; // 保持remark字段同步
  689. console.log('保存后petHealthInfo.value.health:', petHealthInfo.value.health);
  690. console.log('保存后petHealthInfo.value.remark:', petHealthInfo.value.remark);
  691. console.log('保存后healthText.value:', healthText.value);
  692. console.log('=== 健康选择确认完成 ===');
  693. showHealths.value = false;
  694. };
  695. const healthCheckboxChange = (n) => {
  696. console.log('=== 健康checkbox变化 ===');
  697. console.log('新值:', n);
  698. console.log('tempHealthStatus.value:', tempHealthStatus.value);
  699. console.log('是否包含其他:', tempHealthStatus.value.includes('其他'));
  700. // 如果取消选择"其他",清空备注
  701. if (!tempHealthStatus.value.includes('其他')) {
  702. tempRemark.value = '';
  703. console.log('取消选择其他,清空备注');
  704. }
  705. console.log('当前备注:', tempRemark.value);
  706. console.log('=== 健康checkbox变化完成 ===');
  707. };
  708. const save = () => {
  709. console.log('=== 开始保存宠物信息 ===');
  710. console.log('petBaseInfo:', petBaseInfo.value);
  711. console.log('petHealthInfo:', petHealthInfo.value);
  712. console.log('当前personality值:', petBaseInfo.value.personality, '长度:', petBaseInfo.value.personality?.length);
  713. console.log('personalityText显示值:', personalityText.value);
  714. if (!(fileList.value.length > 0 && fileList.value[0].url)) {
  715. uni.showToast({
  716. title: '请上传宠物照片!',
  717. duration: 3000,
  718. icon: "none"
  719. });
  720. return;
  721. }
  722. headImage.value = fileList.value[0].url;
  723. // 确保性格数据正确处理
  724. let finalPersonality = '';
  725. // 优先使用tempPersonality中的数据(如果用户有操作过弹窗)
  726. if (tempPersonality.value && tempPersonality.value.length > 0) {
  727. finalPersonality = tempPersonality.value.join(',');
  728. console.log('使用tempPersonality数据:', finalPersonality);
  729. } else if (petBaseInfo.value.personality && petBaseInfo.value.personality.trim() !== '') {
  730. // 如果没有temp数据,使用原有数据并转换为英文逗号
  731. finalPersonality = petBaseInfo.value.personality.replace(/,/g, ',');
  732. console.log('使用petBaseInfo原有数据:', finalPersonality);
  733. }
  734. // 确保健康数据正确处理
  735. let finalHealth = '';
  736. let finalRemark = tempRemark.value || petHealthInfo.value.remark || '';
  737. console.log('=== 处理健康数据开始 ===');
  738. console.log('petHealthInfo.value.health:', petHealthInfo.value.health);
  739. console.log('tempHealthStatus.value:', tempHealthStatus.value);
  740. console.log('tempRemark.value:', tempRemark.value);
  741. console.log('petHealthInfo.value.remark:', petHealthInfo.value.remark);
  742. // 优先使用tempHealthStatus中的数据(如果用户有操作过弹窗)
  743. if (tempHealthStatus.value && tempHealthStatus.value.length > 0) {
  744. let healthArray = [...tempHealthStatus.value];
  745. console.log('使用tempHealthStatus数据:', healthArray);
  746. // 处理"其他"选项
  747. if (healthArray.includes('其他') && tempRemark.value && tempRemark.value.trim() !== '') {
  748. const otherIndex = healthArray.indexOf('其他');
  749. const newOtherValue = `其他:${tempRemark.value.trim()}`;
  750. healthArray[otherIndex] = newOtherValue;
  751. console.log('合并其他选项和备注:', newOtherValue);
  752. }
  753. finalHealth = healthArray.join(',');
  754. console.log('使用tempHealthStatus生成的finalHealth:', finalHealth);
  755. } else if (petHealthInfo.value.health && petHealthInfo.value.health.trim() !== '') {
  756. // 如果没有temp数据,使用原有数据并转换为英文逗号
  757. finalHealth = petHealthInfo.value.health.replace(/,/g, ',');
  758. console.log('使用petHealthInfo原有数据:', finalHealth);
  759. }
  760. console.log('最终finalHealth:', finalHealth);
  761. console.log('最终finalRemark:', finalRemark);
  762. console.log('=== 处理健康数据完成 ===');
  763. // 处理生日格式转换
  764. let finalBirthday = '';
  765. if (petBaseInfo.value.birthday) {
  766. // 将 "2025-07" 格式转换为 "2025-07-01 00:00:00" 格式
  767. if (petBaseInfo.value.birthday.length === 7) { // 格式为 "2025-07"
  768. finalBirthday = `${petBaseInfo.value.birthday}-01 00:00:00`;
  769. } else {
  770. finalBirthday = petBaseInfo.value.birthday;
  771. }
  772. }
  773. console.log('原生日格式:', petBaseInfo.value.birthday);
  774. console.log('转换后生日格式:', finalBirthday);
  775. let params = {
  776. ...{
  777. petType: petType.value,
  778. headImage: headImage.value
  779. },
  780. userId:userId.value,
  781. ...petBaseInfo.value,
  782. ...petHealthInfo.value,
  783. personality: finalPersonality, // 确保personality字段有正确的数据
  784. health: finalHealth, // 确保health字段有正确的数据
  785. remark: finalRemark, // 确保remark字段有正确的数据
  786. birthday: finalBirthday // 确保birthday字段格式正确
  787. };
  788. console.log('合并后的提交参数:', params);
  789. console.log('其中personality值:', params.personality, '类型:', typeof params.personality, '长度:', params.personality?.length);
  790. console.log('其中health值:', params.health, '类型:', typeof params.health, '长度:', params.health?.length);
  791. console.log('其中remark值:', params.remark, '类型:', typeof params.remark, '长度:', params.remark?.length);
  792. console.log('其中birthday值:', params.birthday, '类型:', typeof params.birthday);
  793. console.log('finalPersonality:', finalPersonality);
  794. console.log('finalHealth:', finalHealth);
  795. console.log('finalRemark:', finalRemark);
  796. console.log('finalBirthday:', finalBirthday);
  797. if (!params.nickName) {
  798. uni.showToast({
  799. title: '请填写宠物昵称!',
  800. duration: 3000,
  801. icon: "none"
  802. });
  803. return;
  804. }
  805. if (!params.type) {
  806. uni.showToast({
  807. title: '请输入宠物品种!',
  808. duration: 3000,
  809. icon: "none"
  810. });
  811. return;
  812. }
  813. if (!params.weight) {
  814. uni.showToast({
  815. title: '请选择宠物体重!',
  816. duration: 3000,
  817. icon: "none"
  818. });
  819. return;
  820. }
  821. if (!params.personality || params.personality.trim() === '' || params.personality === undefined || params.personality === null) {
  822. console.log('=== 性格验证失败详情 ===');
  823. console.log('params.personality:', params.personality);
  824. console.log('petBaseInfo.value.personality:', petBaseInfo.value.personality);
  825. console.log('personalityText.value:', personalityText.value);
  826. console.log('tempPersonality.value:', tempPersonality.value);
  827. uni.showToast({
  828. title: '请选择宠物性格!',
  829. duration: 3000,
  830. icon: "none"
  831. });
  832. return;
  833. }
  834. if (!(params.vaccine >= 0)) {
  835. uni.showToast({
  836. title: '请选择宠物疫苗情况!',
  837. duration: 3000,
  838. icon: "none"
  839. });
  840. return;
  841. }
  842. if (!(params.deworm >= 0)) {
  843. uni.showToast({
  844. title: '请选择宠物驱虫情况!',
  845. duration: 3000,
  846. icon: "none"
  847. });
  848. return;
  849. }
  850. if (!params.health || params.health.trim() === '' || params.health === undefined || params.health === null) {
  851. console.log('=== 健康验证失败详情 ===');
  852. console.log('params.health:', params.health);
  853. console.log('petHealthInfo.value.health:', petHealthInfo.value.health);
  854. console.log('healthText.value:', healthText.value);
  855. console.log('tempHealthStatus.value:', tempHealthStatus.value);
  856. console.log('tempRemark.value:', tempRemark.value);
  857. uni.showToast({
  858. title: '请选择宠物健康情况',
  859. duration: 3000,
  860. icon: "none"
  861. });
  862. return;
  863. }
  864. loading.value = true;
  865. if (optionType.value === 'edit') {
  866. params.id = petId.value;
  867. updatePet(params).then((res) => {
  868. if (res && res.code === 200) {
  869. uni.showToast({
  870. title: '保存成功',
  871. duration: 3000,
  872. icon: "none"
  873. });
  874. setTimeout(() => {
  875. loading.value = false;
  876. if (isNewOrder.value) {
  877. router.push('/pages/newOrder/petList');
  878. } else {
  879. const len = getCurrentPages().length;
  880. if (len >= 2) {
  881. uni.navigateBack();
  882. } else {
  883. router.push('/pages/personalCenter/pet');
  884. }
  885. }
  886. }, 1000);
  887. } else {
  888. loading.value = false;
  889. uni.showToast({
  890. title: '更新pet失败',
  891. duration: 3000,
  892. icon: "none"
  893. });
  894. }
  895. });
  896. } else if (optionType.value === 'add') {
  897. addPet(params).then((res) => {
  898. if (res.code == 200) {
  899. uni.showToast({
  900. title: '保存成功',
  901. duration: 3000,
  902. icon: "none"
  903. });
  904. setTimeout(() => {
  905. loading.value = false;
  906. uni.navigateBack();
  907. }, 1000);
  908. } else {
  909. loading.value = false;
  910. uni.showToast({
  911. title: '新增pet失败',
  912. duration: 3000,
  913. icon: "none"
  914. });
  915. }
  916. });
  917. }
  918. };
  919. const cancelPet = () => {
  920. uni.navigateBack(-1);
  921. };
  922. const confirmDel = () => {
  923. delByPetId(petId.value).then((res) => {
  924. uni.showToast({
  925. title: '删除成功',
  926. duration: 3000,
  927. icon: "none"
  928. });
  929. showDel.value = false;
  930. setTimeout(() => {
  931. const len = getCurrentPages().length;
  932. loading.value = false;
  933. if (len >= 2) {
  934. uni.navigateBack();
  935. } else {
  936. router.push('/pages/personalCenter/pet');
  937. }
  938. }, 2000);
  939. });
  940. };
  941. </script>
  942. <style lang="scss" scoped>
  943. .personal-pet-cat {
  944. .breed-select {
  945. background-color: #fff;
  946. box-sizing: border-box;
  947. width: 100%;
  948. padding: 20px;
  949. border-radius: 8px 8px 0 0;
  950. position: absolute;
  951. bottom: 0;
  952. .breed-select-btn {
  953. display: flex;
  954. justify-content: space-around;
  955. align-items: center;
  956. }
  957. }
  958. .personal-pet-info-title {
  959. font-size: 14px;
  960. color: #333;
  961. font-weight: bold;
  962. padding-bottom: 10px;
  963. }
  964. .border-bottom {
  965. border-bottom: 1px solid #efefef;
  966. }
  967. .personal-pet-img {
  968. height: 118px;
  969. background-color: #fff;
  970. padding: 10px 20px;
  971. }
  972. .personal-pet-basic-info {
  973. background-color: #fff;
  974. margin-top: 10px;
  975. padding: 10px 20px;
  976. }
  977. .personal-pet-health-info {
  978. background-color: #fff;
  979. padding: 10px 20px 0 20px;
  980. margin-top: 10px;
  981. }
  982. }
  983. .container {
  984. position: relative;
  985. height: 100%;
  986. padding-bottom: 90px;
  987. .personal-pet-info-btns {
  988. box-sizing: border-box;
  989. background-color: #FFFFFF;
  990. padding: 20rpx 20rpx 40rpx 20rpx;
  991. width: 100%;
  992. height: 160rpx;
  993. position: fixed;
  994. bottom: 0;
  995. z-index: 100;
  996. display: flex;
  997. .personal-pet-btns {
  998. display: flex;
  999. justify-content: space-around;
  1000. align-items: center;
  1001. flex-wrap: nowrap;
  1002. width: 100%;
  1003. height: 90rpx;
  1004. border-radius: 6px;
  1005. font-size: 16px;
  1006. color: #FFFFFF;
  1007. .personal-pet-btn {
  1008. width: 40%;
  1009. }
  1010. }
  1011. }
  1012. }
  1013. .personal-pet-disposition-btns {
  1014. display: flex;
  1015. justify-content: space-between;
  1016. box-sizing: border-box;
  1017. background-color: #FFFFFF;
  1018. padding: 20rpx 20rpx 40rpx 20rpx;
  1019. left: 0;
  1020. width: 100%;
  1021. height: 160rpx;
  1022. position: fixed;
  1023. bottom: 0;
  1024. z-index: 100;
  1025. }
  1026. .personal-pet-disposition-btn {
  1027. width: 40%;
  1028. }
  1029. .health-select {
  1030. background-color: #fffcf2;
  1031. padding: 10px 20px;
  1032. }
  1033. .dog-tips {
  1034. color: #A94F20;
  1035. font-size: 12px;
  1036. display: flex;
  1037. align-items: baseline;
  1038. margin-top: 5px;
  1039. }
  1040. .health-select-btns {
  1041. display: flex;
  1042. justify-content: space-between;
  1043. box-sizing: border-box;
  1044. background-color: #FFFFFF;
  1045. padding: 20rpx 20rpx 40rpx 20rpx;
  1046. left: 0;
  1047. width: 100%;
  1048. height: 160rpx;
  1049. position: fixed;
  1050. bottom: 0;
  1051. z-index: 100;
  1052. }
  1053. .health-select-btn {
  1054. width: 40%;
  1055. }
  1056. </style>