myStar copy.vue 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357
  1. <template>
  2. <view class="star-container">
  3. <!-- 性别选择弹窗 -->
  4. <view class="gender-popup" v-if="!selectedGender && !showInfo">
  5. <view class="popup-content">
  6. <view class="popup-title">请选择性别</view>
  7. <view class="gender-cards">
  8. <view class="gender-card" :class="{'selected': tempGender === 'male'}" @tap="selectGender('male')">
  9. <image src="/static/home/nan.png" mode="aspectFit"></image>
  10. <text>男生</text>
  11. <image v-if="tempGender === 'male'" class="check-icon" src="/static/gender/check.png"
  12. mode="aspectFit">
  13. </image>
  14. </view>
  15. <view class="gender-card" :class="{'selected': tempGender === 'female'}"
  16. @tap="selectGender('female')">
  17. <image src="/static/home/nv.png" mode="aspectFit"></image>
  18. <text>女生</text>
  19. <image v-if="tempGender === 'female'" class="check-icon" src="/static/gender/check.png"
  20. mode="aspectFit">
  21. </image>
  22. </view>
  23. </view>
  24. <view class="confirm-btn" @tap="confirmGender">
  25. 创建星灵
  26. </view>
  27. </view>
  28. </view>
  29. <!-- 加载动画区域 -->
  30. <view class="loading-area" v-if="isLoading">
  31. <view class="loading-wrapper">
  32. <!-- 中心蓝色旋转圆 -->
  33. <view class="center-circle"></view>
  34. <!-- 外围16个小球 -->
  35. <view class="orbit-balls">
  36. <view class="ball" v-for="(item,index) in 16" :key="index" :style="{
  37. transform: `rotate(${index * 22.5}deg)`,
  38. '--delay': `${index * 0.2}s`,
  39. '--color': ballColors[index % 8]
  40. }">
  41. <view class="ball-item"></view>
  42. </view>
  43. </view>
  44. </view>
  45. <text class="loading-text">正在加载...</text>
  46. </view>
  47. <!-- 角色信息展示页面 -->
  48. <view class="character-info" v-else-if="showInfo">
  49. <view class="info-container">
  50. <!-- 角色立绘区域 -->
  51. <view class="character-portrait">
  52. <image :src="starInfo.image" mode="aspectFit" class="portrait-image"></image>
  53. <text class="character-name">{{starInfo.name}}</text>
  54. </view>
  55. <!-- 角色信息板块 -->
  56. <view class="info-section">
  57. <view class="section-title">关于Ta</view>
  58. <!-- 人物简介 -->
  59. <view class="description-box">
  60. <text class="description-text">{{starInfo.content}}</text>
  61. </view>
  62. <!-- 标签展示 -->
  63. <view class="tags-box">
  64. <view class="tag-item" v-for="tag in formData.tags" :key="tag">
  65. {{tag}}
  66. </view>
  67. </view>
  68. </view>
  69. </view>
  70. <!-- 底部按钮 -->
  71. <view class="join-button" @tap="handleJoin">
  72. 入驻星球
  73. </view>
  74. </view>
  75. <!-- 表单页面 -->
  76. <view class="form-page" v-else-if="showForm">
  77. <form @submit="submitForm">
  78. <view class="form-group">
  79. <view class="label">
  80. <text class="required">*</text>
  81. <text>昵称</text>
  82. </view>
  83. <input class="input" v-model="formData.nickname" placeholder="给星灵取个名字"
  84. :class="{'error': showError && !formData.nickname}" />
  85. </view>
  86. <view class="form-group">
  87. <view class="label">性别</view>
  88. <view class="gender-options">
  89. <view class="gender-option">
  90. 已选{{starInfo.sex==1?'男':'女'}}
  91. </view>
  92. </view>
  93. </view>
  94. <view class="form-group">
  95. <view class="label">
  96. <text class="required">*</text>
  97. <text>人物简介</text>
  98. </view>
  99. <view class="textarea-container">
  100. <textarea class="textarea" v-model="formData.description"
  101. placeholder="填写这个角色的人物介绍,例如性格、身份、背景与历程..." :maxlength="255"
  102. :class="{'error': showError && !formData.description}" />
  103. <text class="word-count">{{formData.description.length}}/255</text>
  104. </view>
  105. </view>
  106. <view class="form-group">
  107. <view class="label">人物标签</view>
  108. <scroll-view class="tags-scroll" scroll-x="true" show-scrollbar="false">
  109. <view class="tags-container">
  110. <view class="tag" v-for="tag in predefinedTags" :key="tag">
  111. {{tag}}
  112. </view>
  113. </view>
  114. </scroll-view>
  115. </view>
  116. </form>
  117. <view class="submit-button" @tap="submitStar">
  118. 确定并提交
  119. </view>
  120. </view>
  121. <!-- 角色展示页面 -->
  122. <view class="character-page" v-else-if="selectedGender">
  123. <view class="character-container">
  124. <image :src="starImg" mode="aspectFit" class="character-image"></image>
  125. </view>
  126. <view class="bottom-button" @tap="goToSetProfile">
  127. 设置星灵简介
  128. </view>
  129. </view>
  130. <!-- 收藏内容区域 -->
  131. <view class="star-content" v-else>
  132. <view class="star-list">
  133. <!-- 这里放收藏列表内容 -->
  134. </view>
  135. </view>
  136. </view>
  137. </template>
  138. <script>
  139. import tabbarView from "@/components/tabbar/tabbar.vue"
  140. export default {
  141. components: {
  142. tabbarView
  143. },
  144. data() {
  145. return {
  146. isLoading: false,
  147. selectedGender: null,
  148. tempGender: null,
  149. tabbars: [],
  150. ballColors: [
  151. '#FF6B6B', // 红色
  152. '#4ECDC4', // 青色
  153. '#45B7D1', // 蓝色
  154. '#96CEB4', // 绿色
  155. '#FFEEAD', // 黄色
  156. '#D4A5A5', // 粉色
  157. '#9A8194', // 紫色
  158. '#FF9F1C' // 橙色
  159. ],
  160. showForm: false,
  161. showError: false,
  162. formData: {
  163. nickname: '',
  164. gender: '其他',
  165. description: '',
  166. tags: []
  167. },
  168. predefinedTags: [],
  169. showInfo: false,
  170. starImg: '',
  171. starInfo: {}
  172. }
  173. },
  174. onLoad() {
  175. this.getStar('get');
  176. },
  177. methods: {
  178. selectGender(gender) {
  179. this.tempGender = gender;
  180. },
  181. confirmGender() {
  182. if (!this.tempGender) return;
  183. this.selectedGender = this.tempGender;
  184. this.isLoading = true;
  185. this.getStar('make');
  186. },
  187. goToSetProfile() {
  188. this.showForm = true;
  189. },
  190. toggleTag(tag) {
  191. const index = this.formData.tags.indexOf(tag);
  192. if (index > -1) {
  193. this.formData.tags.splice(index, 1);
  194. } else {
  195. this.formData.tags.push(tag);
  196. }
  197. },
  198. handleJoin() {
  199. console.log('入驻星球');
  200. // 处理入驻逻辑
  201. },
  202. getStar(act) {
  203. let that = this;
  204. console.log("uuid", getApp().globalData.uuid);
  205. // 设置加载状态
  206. if (act === 'make') {
  207. this.isLoading = true;
  208. }
  209. uni.request({
  210. url: this.$apiHost + '/Work/getStar',
  211. data: {
  212. uuid: getApp().globalData.uuid,
  213. sex: this.tempGender,
  214. act: act,
  215. },
  216. header: {
  217. "content-type": "application/json",
  218. 'sign': getApp().globalData.headerSign
  219. },
  220. // 设置60秒超时
  221. timeout: 60000,
  222. success: (res) => {
  223. console.log("res.data", res.data);
  224. if (res.data.have == 0) {
  225. this.showInfo = false;
  226. this.starImg = res.data.image;
  227. } else {
  228. //首次进来获取到了
  229. this.showInfo = true;
  230. }
  231. if (res.data.success === "yes") {
  232. this.starImg = res.data.image;
  233. }
  234. if (res.data.info && res.data.info.tags != "") {
  235. let img2 = [];
  236. var n2 = res.data.info.tags.split(",");
  237. n2.map((filePath) => {
  238. img2.push(filePath)
  239. })
  240. this.predefinedTags = img2;
  241. this.formData.tags = img2;
  242. }
  243. this.starInfo = res.data.info || {};
  244. this.formData.description = this.starInfo.content;
  245. if (act == 'make') {
  246. // 模拟加载过程
  247. setTimeout(() => {
  248. that.isLoading = false;
  249. }, 300);
  250. }
  251. },
  252. fail: (err) => {
  253. console.error('请求失败:', err);
  254. // 显示错误提示
  255. uni.showToast({
  256. title: '网络请求失败,请重试',
  257. icon: 'none',
  258. duration: 2000
  259. });
  260. // 重置加载状态
  261. if (act === 'make') {
  262. that.isLoading = false;
  263. }
  264. // 如果是网络超时,自动重试一次
  265. if (err.errMsg.includes('timeout')) {
  266. setTimeout(() => {
  267. console.log('请求超时,正在重试...');
  268. that.getStar(act);
  269. }, 1000);
  270. }
  271. },
  272. complete: () => {
  273. // 确保在任何情况下都能重置加载状态
  274. if (act === 'make' && this.isLoading) {
  275. this.isLoading = false;
  276. }
  277. }
  278. });
  279. },
  280. submitStar() {
  281. let that = this;
  282. uni.showLoading({
  283. mask: true
  284. })
  285. uni.request({
  286. url: this.$apiHost + '/Work/getStar',
  287. data: {
  288. uuid: getApp().globalData.uuid,
  289. sex: this.tempGender,
  290. name: this.formData.nickname,
  291. content: this.formData.description,
  292. act: 'submit',
  293. },
  294. header: {
  295. "content-type": "application/json",
  296. 'sign': getApp().globalData.headerSign
  297. },
  298. // 设置60秒超时
  299. timeout: 10000,
  300. success: (res) => {
  301. console.log("res.data", res.data);
  302. uni.showToast({
  303. title: res.data.str,
  304. icon: 'none',
  305. duration: 2000
  306. });
  307. if (res.data.success === "yes") {
  308. setTimeout(() => {
  309. that.getStar('get');
  310. }, 300);
  311. }
  312. },
  313. fail: (err) => {
  314. console.error('请求失败:', err);
  315. // 显示错误提示
  316. uni.showToast({
  317. title: '网络请求失败,请重试',
  318. icon: 'none',
  319. duration: 2000
  320. });
  321. },
  322. complete: () => {
  323. uni.hideLoading()
  324. }
  325. });
  326. }
  327. }
  328. }
  329. </script>
  330. <style lang="scss">
  331. @import './myStar.scss';
  332. </style>