makeMusicDetail.vue 9.5 KB

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