makeMusicDetail.vue 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  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')">
  93. 情感
  94. <view class="indicator-triangle">
  95. </view>
  96. </text>
  97. <text :class="{ 'active': selectedTab === 'genre' }" @click="selectTab('genre')">
  98. 流派
  99. <view class="indicator-triangle">
  100. </view>
  101. </text>
  102. <text :class="{ 'active': selectedTab === 'era' }" @click="selectTab('era')">
  103. 年代
  104. <view class="indicator-triangle">
  105. </view>
  106. </text>
  107. <text :class="{ 'active': selectedTab === 'instrument' }" @click="selectTab('instrument')">
  108. 乐器
  109. <view class="indicator-triangle">
  110. </view>
  111. </text>
  112. </view>
  113. <view class="tags">
  114. <text v-for="(tag, index) in currentTags" :key="index"
  115. :class="['tag', { active: selectedTags[selectedTab].includes(tag) }]" @click="toggleTag(tag)">
  116. {{ tag }}
  117. </text>
  118. </view>
  119. </view>
  120. </view>
  121. <!-- 底部按钮 -->
  122. <view class="bottom-button">
  123. <button v-if="doYouWantToEdit" class="generate-btn" @click="generateMusic">立即生成
  124. <image src="/static/icon/coin_cd.png" mode="aspectFit"></image>
  125. 10
  126. </button>
  127. <view v-else class="generate-btn prohibit">生成中 </view>
  128. <view class="promotion-link">
  129. <image class="vip" src="/static/makedetail/wd_icon_vip(1).png" mode="aspectFit"></image>
  130. <text> 即刻开通订阅,获取各种福利! </text>
  131. <image class="jiantou" src="/static/makedetail/cz_icon_jiantou.png" mode="aspectFit"></image>
  132. </view>
  133. </view>
  134. </view>
  135. </template>
  136. <script>
  137. export default {
  138. name: 'MakeMusicDetail',
  139. data() {
  140. return {
  141. songName: '',
  142. lyrics: '',
  143. selectedTags: {
  144. emotion: [],
  145. genre: [],
  146. era: [],
  147. instrument: []
  148. },
  149. textareaHeight: 120,
  150. minHeight: 120,
  151. selectedTab: 'emotion',
  152. tagOptions: {
  153. emotion: ['欢快', '悲伤', '积极', '浪漫', '忧郁', '华丽', '闪耀', '神秘', '惊怒', '紧张', '恐怖', '平静'],
  154. genre: ['流行', '摇滚', '民谣', '电子', 'R&B', '嘻哈', '古典', '爵士'],
  155. era: ['80年代', '90年代', '00年代', '10年代', '20年代'],
  156. instrument: ['钢琴', '吉他', '贝斯', '鼓', '小提琴', '萨克斯', '电子合成器']
  157. },
  158. inQueue: false,//是否创作中
  159. queuing: false,//是否排队中
  160. queueMessage: '',
  161. myinfo: {}
  162. }
  163. },
  164. onLoad() {
  165. // this.checkQueueStatus();
  166. this.getMyInfo();
  167. },
  168. computed: {
  169. currentTags() {
  170. return this.selectedTab ? this.tagOptions[this.selectedTab] : [];
  171. }
  172. },
  173. methods: {
  174. doYouWantToEdit() {
  175. return this.inQueue || this.queuing
  176. },
  177. goBack() {
  178. uni.navigateBack({
  179. delta: 1
  180. });
  181. },
  182. getMyInfo() {
  183. uni.request({
  184. url: this.$apiHost + '/My/getnum',
  185. method: 'GET',
  186. header: {
  187. 'content-type': 'application/json',
  188. 'sign': getApp().globalData.headerSign
  189. },
  190. data: {
  191. uuid: getApp().globalData.uuid
  192. },
  193. success: (res) => {
  194. console.log("获取用户信息:", res.data);
  195. this.myinfo = res.data
  196. }
  197. })
  198. },
  199. checkQueueStatus() {
  200. uni.request({
  201. url: this.$apiHost + '/WorkAI/queueStatus',
  202. method: 'GET',
  203. header: {
  204. 'content-type': 'application/json',
  205. 'sign': getApp().globalData.headerSign
  206. },
  207. data: {
  208. uuid: getApp().globalData.uuid,
  209. task_type: 2
  210. },
  211. success: (res) => {
  212. console.log("音乐队列状态:", res.data);
  213. if (res.data.success === "yes") {
  214. this.inQueue = res.data.in_queue
  215. if (this.inQueue) {
  216. this.queueMessage = res.data.str
  217. }
  218. }
  219. },
  220. fail: (err) => {
  221. console.log('获取队列状态失败:', err);
  222. uni.showToast({
  223. title: '获取状态失败',
  224. icon: 'none'
  225. });
  226. }
  227. })
  228. this.getMyInfo();
  229. },
  230. generateMusic() {
  231. if (!this.songName.trim()) {
  232. uni.showToast({
  233. title: '请输入歌曲名称',
  234. icon: 'none'
  235. })
  236. return
  237. }
  238. if (!this.lyrics.trim()) {
  239. uni.showToast({
  240. title: '请输入歌词内容',
  241. icon: 'none'
  242. })
  243. return
  244. }
  245. // 合并所有选中的标签
  246. let allSelectedTags = [
  247. ...this.selectedTags.emotion,
  248. ...this.selectedTags.genre,
  249. ...this.selectedTags.era,
  250. ...this.selectedTags.instrument
  251. ];
  252. let that = this
  253. uni.request({
  254. url: this.$apiHost + '/WorkAI/creatorMusic',
  255. data: {
  256. uuid: getApp().globalData.uuid,
  257. name: this.songName,
  258. lyrics: this.lyrics,
  259. style: allSelectedTags.join(',')
  260. },
  261. method: 'POST',
  262. header: {
  263. 'Content-Type': 'application/x-www-form-urlencoded',
  264. 'sign': getApp().globalData.headerSign
  265. },
  266. dataType: 'json',
  267. success: (res) => {
  268. console.log("生成结果:", res.data);
  269. uni.showToast({
  270. title: res.data.str || '请求成功',
  271. icon: 'none'
  272. });
  273. if (res.data.success == "yes") {
  274. setTimeout(function () {
  275. // that.checkQueueStatus()
  276. //返回上一页
  277. uni.navigateBack()
  278. }, 500);
  279. }
  280. },
  281. fail: (err) => {
  282. console.log('生成失败:', err);
  283. uni.showToast({
  284. title: '生成请求失败',
  285. icon: 'none'
  286. });
  287. }
  288. })
  289. },
  290. onTextareaInput(e) {
  291. const lineHeight = 20; // 假设每行高度为20px
  292. const padding = 30; // 上下padding各15px
  293. const value = e.detail.value;
  294. const lines = value.split('\n').length;
  295. // 计算每行的平均字符数
  296. const avgCharsPerLine = 30; // 根据实际输入框宽度调整
  297. const textLines = Math.ceil(value.length / avgCharsPerLine);
  298. // 取行数的最大值,确保有足够空间显示
  299. const totalLines = Math.max(lines, textLines);
  300. const newHeight = Math.max(totalLines * lineHeight + padding, this.minHeight);
  301. this.textareaHeight = newHeight;
  302. },
  303. selectTab(tab) {
  304. if (this.selectedTab !== tab) {
  305. this.selectedTab = tab;
  306. // 不再清空已选择的标签
  307. }
  308. },
  309. toggleTag(tag) {
  310. if (this.selectedTags[this.selectedTab].includes(tag)) {
  311. this.selectedTags[this.selectedTab] = this.selectedTags[this.selectedTab].filter(t => t !== tag);
  312. } else {
  313. this.selectedTags[this.selectedTab].push(tag);
  314. }
  315. }
  316. }
  317. }
  318. </script>
  319. <style lang="scss">
  320. @import './makeMusicDetail.scss';
  321. </style>