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.

303 lines
7.1 KiB

  1. <template>
  2. <view class="personality-select-container">
  3. <!-- 性格描述 -->
  4. <view class="personality-description">
  5. <view class="section-title">性格描述</view>
  6. <view class="description-input">
  7. <textarea
  8. v-model="personalityDescription"
  9. placeholder="请描述您的宠物性格"
  10. class="description-textarea"
  11. maxlength="200"
  12. ></textarea>
  13. </view>
  14. </view>
  15. <!-- 快捷选择 -->
  16. <view class="quick-selection">
  17. <view class="section-title">快捷选择</view>
  18. <view class="selection-grid">
  19. <view
  20. v-for="(item, index) in personalityOptions"
  21. :key="index"
  22. :class="['selection-item', { 'selected': selectedPersonalities.includes(item) }]"
  23. @click="togglePersonality(item)"
  24. >
  25. {{ item }}
  26. </view>
  27. </view>
  28. </view>
  29. <!-- 保存按钮 -->
  30. <view class="save-button-container">
  31. <u-button
  32. color="#FFBF60"
  33. @click="savePersonality"
  34. :loading="loading"
  35. class="save-button"
  36. >
  37. <view style="color: #fff;">保存</view>
  38. </u-button>
  39. </view>
  40. </view>
  41. </template>
  42. <script>
  43. import { getDictList } from "@/api/system/user"
  44. export default {
  45. data() {
  46. return {
  47. loading: false,
  48. personalityDescription: '',
  49. selectedPersonalities: [],
  50. personalityOptions: [],
  51. originalPersonality: ''
  52. }
  53. },
  54. onLoad(options) {
  55. // 接收传入的性格数据
  56. if (options.personality) {
  57. this.originalPersonality = decodeURIComponent(options.personality);
  58. this.parsePersonality(this.originalPersonality);
  59. }
  60. },
  61. mounted() {
  62. this.getPersonalityDataList();
  63. },
  64. methods: {
  65. // 解析传入的性格数据
  66. parsePersonality(personality) {
  67. if (!personality) return;
  68. // 等待API数据加载完成后再解析
  69. if (this.personalityOptions.length === 0) {
  70. setTimeout(() => {
  71. this.parsePersonality(personality);
  72. }, 100);
  73. return;
  74. }
  75. // 处理数组形式的性格数据
  76. if (Array.isArray(personality)) {
  77. // 分离描述和快捷选择
  78. this.selectedPersonalities = personality.filter(item =>
  79. this.personalityOptions.includes(item)
  80. );
  81. // 描述部分是数组中不在快捷选择里的项
  82. const descriptions = personality.filter(item =>
  83. !this.personalityOptions.includes(item)
  84. );
  85. this.personalityDescription = descriptions.join(',');
  86. } else {
  87. // 兼容字符串形式的数据
  88. const parts = personality.split(',');
  89. if (parts.length > 1) {
  90. // 最后一部分是快捷选择
  91. const quickSelections = parts[parts.length - 1];
  92. this.selectedPersonalities = this.personalityOptions.filter(item =>
  93. quickSelections.includes(item)
  94. );
  95. // 前面的部分是描述
  96. this.personalityDescription = parts.slice(0, -1).join(',');
  97. } else {
  98. // 只有快捷选择
  99. this.selectedPersonalities = this.personalityOptions.filter(item =>
  100. personality.includes(item)
  101. );
  102. }
  103. }
  104. },
  105. // 切换性格选择
  106. togglePersonality(personality) {
  107. const index = this.selectedPersonalities.indexOf(personality);
  108. if (index > -1) {
  109. this.selectedPersonalities.splice(index, 1);
  110. } else {
  111. this.selectedPersonalities.push(personality);
  112. }
  113. },
  114. // 获取性格数据列表
  115. getPersonalityDataList() {
  116. getDictList('pet_personality').then(res => {
  117. if (res.code == 200) {
  118. this.personalityOptions = Array.from(new Set(res.data.map(e => e.dictLabel)));
  119. } else {
  120. this.$modal.showToast('获取性格失败');
  121. }
  122. }).catch(err => {
  123. console.error('获取性格数据失败:', err);
  124. this.$modal.showToast('获取性格数据失败');
  125. });
  126. },
  127. // 保存性格选择
  128. savePersonality() {
  129. this.loading = true;
  130. // 组合性格描述和快捷选择,保持数组形式
  131. let finalPersonality = [];
  132. if (this.personalityDescription.trim()) {
  133. finalPersonality.push(this.personalityDescription.trim());
  134. }
  135. if (this.selectedPersonalities.length > 0) {
  136. finalPersonality = finalPersonality.concat(this.selectedPersonalities);
  137. }
  138. // 验证是否至少选择了一项
  139. if (finalPersonality.length === 0) {
  140. this.$modal.showToast('请至少选择一项性格特征');
  141. this.loading = false;
  142. return;
  143. }
  144. // 延迟一下模拟保存过程
  145. setTimeout(() => {
  146. this.loading = false;
  147. // 返回上一页并传递选择的性格数据
  148. const pages = getCurrentPages();
  149. // 安全检查:确保有足够的页面
  150. if (!pages || pages.length < 2) {
  151. console.warn('页面栈不足,无法获取上一页')
  152. uni.navigateBack();
  153. return;
  154. }
  155. const prevPage = pages[pages.length - 2];
  156. if (prevPage && prevPage.$vm) {
  157. // 更新父页面的性格数据
  158. if (prevPage.$vm.petBaseInfo) {
  159. prevPage.$vm.petBaseInfo.personality = finalPersonality;
  160. // 触发父页面的更新事件
  161. prevPage.$vm.$emit('update:petBaseInfo', prevPage.$vm.petBaseInfo);
  162. } else {
  163. console.warn('上一页没有petBaseInfo')
  164. }
  165. } else {
  166. console.warn('无法找到上一页')
  167. }
  168. // uni.showToast({
  169. // title: '保存成功',
  170. // icon: 'success',
  171. // duration: 1500
  172. // });
  173. // 返回上一页
  174. setTimeout(() => {
  175. uni.navigateBack();
  176. }, 0);
  177. }, 0);
  178. }
  179. }
  180. }
  181. </script>
  182. <style lang="scss">
  183. .personality-select-container {
  184. min-height: 100vh;
  185. background-color: #f5f5f5;
  186. padding: 20px;
  187. box-sizing: border-box;
  188. padding-bottom: 120px;
  189. }
  190. .section-title {
  191. font-size: 16px;
  192. font-weight: bold;
  193. color: #333;
  194. margin-bottom: 15px;
  195. }
  196. .personality-description {
  197. background-color: #fff;
  198. border-radius: 8px;
  199. padding: 20px;
  200. margin-bottom: 20px;
  201. .description-input {
  202. .description-textarea {
  203. width: 100%;
  204. min-height: 100px;
  205. padding: 15px;
  206. border: 1px solid #e0e0e0;
  207. border-radius: 8px;
  208. font-size: 14px;
  209. line-height: 1.5;
  210. background-color: #fafafa;
  211. box-sizing: border-box;
  212. resize: none;
  213. &::placeholder {
  214. color: #999;
  215. }
  216. }
  217. }
  218. }
  219. .quick-selection {
  220. background-color: #fff;
  221. border-radius: 8px;
  222. padding: 20px;
  223. margin-bottom: 100px;
  224. .selection-grid {
  225. display: grid;
  226. grid-template-columns: 1fr 1fr 1fr 1fr;
  227. gap: 8px;
  228. .selection-item {
  229. padding: 10px 4px;
  230. background-color: #f5f5f5;
  231. border-radius: 6px;
  232. text-align: center;
  233. font-size: 12px;
  234. color: #666;
  235. border: 1px solid transparent;
  236. transition: all 0.3s ease;
  237. line-height: 1.1;
  238. white-space: nowrap;
  239. overflow: hidden;
  240. text-overflow: ellipsis;
  241. min-height: 40px;
  242. display: flex;
  243. align-items: center;
  244. justify-content: center;
  245. &.selected {
  246. background-color: #FFBF60;
  247. color: #fff;
  248. border-color: #FFBF60;
  249. }
  250. &:active {
  251. transform: scale(0.98);
  252. }
  253. }
  254. }
  255. }
  256. .save-button-container {
  257. position: fixed;
  258. bottom: 0;
  259. left: 0;
  260. right: 0;
  261. padding: 20px;
  262. background-color: #fff;
  263. border-top: 1px solid #e0e0e0;
  264. .save-button {
  265. width: 100%;
  266. height: 50px;
  267. border-radius: 8px;
  268. }
  269. }
  270. </style>