makeMusicDetail.vue 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. <template>
  2. <view class="make-music-detail">
  3. <!-- 顶部导航 -->
  4. <view class="nav-bar">
  5. <view class="left">
  6. <view class="uni-btn-icon" @click="goBack">&#xe601;</view>
  7. </view>
  8. <view class="center">音乐制作</view>
  9. <view class="right">
  10. <view class="coinM">
  11. <image src="/static/icon/coin_m.png" mode="aspectFit"></image>
  12. <text>{{myinfo.num_gmm}}</text>
  13. </view>
  14. <view class="coinC">
  15. <image src="/static/icon/coin_cd.png" mode="aspectFit"></image>
  16. <text>{{myinfo.num_gmd}}</text>
  17. </view>
  18. </view>
  19. </view>
  20. <!-- 队列状态显示 -->
  21. <view class="preview-section" v-if="inQueue">
  22. <view class="preview-card">
  23. <image class="loading-icon" src="/static/loading.png" mode="aspectFit"></image>
  24. <text class="loading-text">{{queueMessage}}</text>
  25. <text class="sub-text">请耐心等待制作完成</text>
  26. </view>
  27. </view>
  28. <!-- 主要内容区 -->
  29. <view class="content" v-if="!inQueue">
  30. <!-- 歌曲名称输入 -->
  31. <view class="input-section">
  32. <text class="label">歌曲名称</text>
  33. <input type="text" placeholder="请输入名称..." class="input-field" maxlength="30" v-model="songName" />
  34. <text class="count">{{songName.length}}/30</text>
  35. </view>
  36. <!-- 创作歌词输入 -->
  37. <view class="input-section">
  38. <text class="label">创作歌词</text>
  39. <textarea placeholder="请在此处输入您想要进行联想的内容或者歌词" class="textarea-field" maxlength="800" v-model="lyrics"
  40. :style="{height: textareaHeight + 'px'}" @input="onTextareaInput" />
  41. <view class="textarea-footer">
  42. <text class="count">{{lyrics.length}}/800</text>
  43. <text class="ai-btn" v-if="false">AI润词</text>
  44. </view>
  45. </view>
  46. <!-- 音乐风格选择 -->
  47. <view class="style-section">
  48. <text class="label">音乐风格</text>
  49. <view class="tabs">
  50. <text :class="{'active': selectedTab === 'emotion'}" @click="selectTab('emotion')">情感</text>
  51. <text :class="{'active': selectedTab === 'genre'}" @click="selectTab('genre')">流派</text>
  52. <text :class="{'active': selectedTab === 'era'}" @click="selectTab('era')">年代</text>
  53. <text :class="{'active': selectedTab === 'instrument'}" @click="selectTab('instrument')">乐器</text>
  54. </view>
  55. <view class="tags">
  56. <text v-for="(tag, index) in currentTags" :key="index"
  57. :class="['tag', { active: selectedTags[selectedTab].includes(tag) }]" @click="toggleTag(tag)">
  58. {{tag}}
  59. </text>
  60. </view>
  61. </view>
  62. </view>
  63. <!-- 底部按钮 -->
  64. <view class="bottom-section" v-if="!inQueue">
  65. <button class="submit-btn" @click="generateMusic">立即生成<text class="small">(需消耗10枚豆)</text></button>
  66. <view class="promotion-text">
  67. <text class="link-text">即刻开通订阅,我取各种福利</text>
  68. </view>
  69. </view>
  70. </view>
  71. </template>
  72. <script>
  73. export default {
  74. name: 'MakeMusicDetail',
  75. data() {
  76. return {
  77. songName: '',
  78. lyrics: '',
  79. selectedTags: {
  80. emotion: [],
  81. genre: [],
  82. era: [],
  83. instrument: []
  84. },
  85. textareaHeight: 120,
  86. minHeight: 120,
  87. selectedTab: 'emotion',
  88. tagOptions: {
  89. emotion: ['欢快', '悲伤', '积极', '浪漫', '忧郁', '华丽', '闪耀', '神秘', '惊怒', '紧张', '恐怖', '平静'],
  90. genre: ['流行', '摇滚', '民谣', '电子', 'R&B', '嘻哈', '古典', '爵士'],
  91. era: ['80年代', '90年代', '00年代', '10年代', '20年代'],
  92. instrument: ['钢琴', '吉他', '贝斯', '鼓', '小提琴', '萨克斯', '电子合成器']
  93. },
  94. inQueue: false,
  95. queueMessage: '',
  96. myinfo: {}
  97. }
  98. },
  99. onLoad() {
  100. // this.checkQueueStatus();
  101. this.getMyInfo();
  102. },
  103. computed: {
  104. currentTags() {
  105. return this.selectedTab ? this.tagOptions[this.selectedTab] : [];
  106. }
  107. },
  108. methods: {
  109. goBack() {
  110. uni.navigateBack({
  111. delta: 1
  112. });
  113. },
  114. getMyInfo() {
  115. uni.request({
  116. url: this.$apiHost + '/My/getnum',
  117. method: 'GET',
  118. header: {
  119. 'content-type': 'application/json',
  120. 'sign': getApp().globalData.headerSign
  121. },
  122. data: {
  123. uuid: getApp().globalData.uuid
  124. },
  125. success: (res) => {
  126. console.log("获取用户信息:", res.data);
  127. this.myinfo = res.data
  128. }
  129. })
  130. },
  131. checkQueueStatus() {
  132. uni.request({
  133. url: this.$apiHost + '/WorkAI/queueStatus',
  134. method: 'GET',
  135. header: {
  136. 'content-type': 'application/json',
  137. 'sign': getApp().globalData.headerSign
  138. },
  139. data: {
  140. uuid: getApp().globalData.uuid,
  141. task_type: 2
  142. },
  143. success: (res) => {
  144. console.log("音乐队列状态:", res.data);
  145. if (res.data.success === "yes") {
  146. this.inQueue = res.data.in_queue
  147. if (this.inQueue) {
  148. this.queueMessage = res.data.str
  149. }
  150. }
  151. },
  152. fail: (err) => {
  153. console.log('获取队列状态失败:', err);
  154. uni.showToast({
  155. title: '获取状态失败',
  156. icon: 'none'
  157. });
  158. }
  159. })
  160. this.getMyInfo();
  161. },
  162. generateMusic() {
  163. if (!this.songName.trim()) {
  164. uni.showToast({
  165. title: '请输入歌曲名称',
  166. icon: 'none'
  167. })
  168. return
  169. }
  170. if (!this.lyrics.trim()) {
  171. uni.showToast({
  172. title: '请输入歌词内容',
  173. icon: 'none'
  174. })
  175. return
  176. }
  177. // 合并所有选中的标签
  178. let allSelectedTags = [
  179. ...this.selectedTags.emotion,
  180. ...this.selectedTags.genre,
  181. ...this.selectedTags.era,
  182. ...this.selectedTags.instrument
  183. ];
  184. let that = this
  185. uni.request({
  186. url: this.$apiHost + '/WorkAI/creatorMusic',
  187. data: {
  188. uuid: getApp().globalData.uuid,
  189. name: this.songName,
  190. lyrics: this.lyrics,
  191. style: allSelectedTags.join(',')
  192. },
  193. method: 'POST',
  194. header: {
  195. 'Content-Type': 'application/x-www-form-urlencoded',
  196. 'sign': getApp().globalData.headerSign
  197. },
  198. dataType: 'json',
  199. success: (res) => {
  200. console.log("生成结果:", res.data);
  201. uni.showToast({
  202. title: res.data.str || '请求成功',
  203. icon: 'none'
  204. });
  205. if (res.data.success == "yes") {
  206. setTimeout(function() {
  207. // that.checkQueueStatus()
  208. //返回上一页
  209. uni.navigateBack()
  210. }, 500);
  211. }
  212. },
  213. fail: (err) => {
  214. console.log('生成失败:', err);
  215. uni.showToast({
  216. title: '生成请求失败',
  217. icon: 'none'
  218. });
  219. }
  220. })
  221. },
  222. onTextareaInput(e) {
  223. const lineHeight = 20; // 假设每行高度为20px
  224. const padding = 30; // 上下padding各15px
  225. const value = e.detail.value;
  226. const lines = value.split('\n').length;
  227. // 计算每行的平均字符数
  228. const avgCharsPerLine = 30; // 根据实际输入框宽度调整
  229. const textLines = Math.ceil(value.length / avgCharsPerLine);
  230. // 取行数的最大值,确保有足够空间显示
  231. const totalLines = Math.max(lines, textLines);
  232. const newHeight = Math.max(totalLines * lineHeight + padding, this.minHeight);
  233. this.textareaHeight = newHeight;
  234. },
  235. selectTab(tab) {
  236. if (this.selectedTab !== tab) {
  237. this.selectedTab = tab;
  238. // 不再清空已选择的标签
  239. }
  240. },
  241. toggleTag(tag) {
  242. if (this.selectedTags[this.selectedTab].includes(tag)) {
  243. this.selectedTags[this.selectedTab] = this.selectedTags[this.selectedTab].filter(t => t !== tag);
  244. } else {
  245. this.selectedTags[this.selectedTab].push(tag);
  246. }
  247. }
  248. }
  249. }
  250. </script>
  251. <style lang="scss">
  252. @import './makeMusicDetail.scss';
  253. </style>