addRole.vue 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. <template>
  2. <view class="page" :style="{'min-height':h+'px', 'padding-top':mt+'px'}">
  3. <cus-header :title='title' bgColor="transparent"></cus-header>
  4. <div class="box">
  5. <div class="title adfac">角色形象</div>
  6. <div class="upload">
  7. <div class="sc">
  8. <u-upload width="188rpx" height="188rpx"
  9. :fileList="fileList"
  10. @afterRead="afterRead"
  11. @delete="deletePic"
  12. :maxCount="1"
  13. >
  14. <div class="imgs">
  15. <image class="img1" src="http://106.54.209.120:8188/static/role_upload.png"></image>
  16. <image class="img2" src="http://106.54.209.120:8188/static/upload_add.png"></image>
  17. </div>
  18. </u-upload>
  19. </div>
  20. <div class="text">上传角色形象</div>
  21. </div>
  22. </div>
  23. <div class="box adfacjb">
  24. <div class="title">角色昵称<span>*</span></div>
  25. <input type="text" v-model="agentDto.agentName" placeholder="请输入角色昵称" placeholder-class="ph">
  26. </div>
  27. <div class="box adfacjb" @tap="selectModel">
  28. <div class="title">角色模板<span>*</span></div>
  29. <div class="right adfac">
  30. <div class="mtext" :class="{'active':modelText!=='请选择角色模版'}">{{modelText}}</div>
  31. <image src="http://106.54.209.120:8188/static/arrow_right.png"></image>
  32. </div>
  33. </div>
  34. <div class="box">
  35. <div class="top adfacjb">
  36. <div class="title">设备描述</div>
  37. <div class="tip">回显不可编辑</div>
  38. </div>
  39. <div class="desc">{{deviceMemo||''}}</div>
  40. </div>
  41. <div class="box adfacjb">
  42. <div class="title">音色<span>*</span></div>
  43. <div class="right adfac" @tap="show=true">
  44. <div class="mtext" :class="{'active':voiceText!=='请选择音色'}">{{voiceText}}</div>
  45. <image src="http://106.54.209.120:8188/static/arrow_right.png"></image>
  46. </div>
  47. </div>
  48. <div class="zt_btn" @tap="comfirmSure">{{agentId?'编辑角色':'创建角色'}}</div>
  49. <u-picker :itemHeight="88" title="角色音色" :show="show" :columns="voiceList" keyName="name"
  50. @cancel="show=false" @confirm="confirm" :immediateChange="true" style="height: 500rpx;">
  51. </u-picker>
  52. </view>
  53. </template>
  54. <script>
  55. const baseApi = require('@/http/baseApi.js')
  56. export default {
  57. data(){
  58. return {
  59. title:'创建角色',
  60. modelText:'请选择角色模版',
  61. voiceText:'请选择音色',
  62. fileList:[],
  63. show:false,
  64. voiceList:[],
  65. deviceMemo:'',
  66. modelMap:new Map(),
  67. agentId:'',
  68. deviceId:'',
  69. agentDto:{
  70. "agentName": "",
  71. "asrModelId": "",
  72. "vadModelId": "",
  73. "llmModelId": "",
  74. "ttsModelId": "",
  75. "ttsVoiceId": "",
  76. "memModelId": "",
  77. "intentModelId": "",
  78. "systemPrompt": "",
  79. "langCode": "",
  80. "language": "",
  81. "deviceId": ""
  82. }
  83. }
  84. },
  85. onLoad(option) {
  86. if(option.agentId){
  87. this.title = '编辑角色';
  88. this.agentId = option.agentId;
  89. this.deviceId = option.deviceId;
  90. this.getDetail();
  91. }
  92. },
  93. methods:{
  94. // 删除图片
  95. deletePic(event) {
  96. this.fileList.splice(event.index, 1);
  97. },
  98. // 新增图片
  99. async afterRead(event) {
  100. // 当设置 multiple 为 true 时, file 为数组格式,否则为对象格式
  101. let lists = [].concat(event.file);
  102. let fileListLen = this.fileList.length;
  103. lists.map((item) => {
  104. this.fileList.push({
  105. ...item,
  106. status: "uploading",
  107. message: "上传中",
  108. });
  109. });
  110. for (let i = 0; i < lists.length; i++) {
  111. const result = await this.uploadFilePromise(lists[i].url);
  112. let item = this.fileList[fileListLen];
  113. this.fileList.splice(
  114. fileListLen,
  115. 1,
  116. Object.assign(item, {
  117. status: "success",
  118. message: "",
  119. url: result,
  120. })
  121. );
  122. fileListLen++;
  123. }
  124. },
  125. uploadFilePromise(url) {
  126. return new Promise((resolve, reject) => {
  127. uni.uploadFile({
  128. url: baseApi.BaseApi + '/sys/oss/uploadFile',
  129. filePath: url,
  130. name: "file",
  131. header:{
  132. token: uni.getStorageSync('token')
  133. },
  134. success: (res) => {
  135. let data = JSON.parse(res.data);
  136. if(data){
  137. if(data.code!==0) return
  138. setTimeout(() => {
  139. resolve(data.data);
  140. }, 1000);
  141. }
  142. },
  143. });
  144. });
  145. },
  146. selectModel(){
  147. uni.navigateTo({
  148. url:'/pagesRole/roleModel',
  149. events:{
  150. selectRoleModel:data=>{
  151. this.agentDto = {...this.agentDto,...data};
  152. this.modelText = data.agentName||'';
  153. this.deviceMemo = data.systemPrompt||'';
  154. this.getModelVoiceList();
  155. }
  156. }
  157. })
  158. },
  159. getModelVoiceList(){
  160. this.$api.get(`/models/${this.agentDto.ttsModelId}/voices`).then(res=>{
  161. if(res.data.code!==0) return this.$showToast(res.data.msg)
  162. this.voiceList = [res.data.data];
  163. this.voiceText = res.data.data.find(v=>v.id===this.agentDto.ttsVoiceId)?.name||'';
  164. })
  165. },
  166. confirm(e){
  167. this.show = false;
  168. this.agentDto.ttsVoiceId = e.value[0].id;
  169. this.voiceText = e.value[0].name;
  170. },
  171. comfirmSure(){
  172. if(!this.agentDto.agentName) return this.$showToast('请输入角色昵称')
  173. if(this.agentDto.modelText==='请选择角色模版') return this.$showToast('请选择角色模板')
  174. if(this.agentDto.voiceText==='请选择音色') return this.$showToast('请选择音色')
  175. let dto = JSON.parse(JSON.stringify(this.agentDto));
  176. if(this.agentId) dto.deviceId = this.deviceId;
  177. this.$api.post(this.agentId?`/agent/update/${this.agentId}`:'/agent',dto).then(res=>{
  178. if(res.data.code!==0) return this.$showToast(res.data.msg)
  179. this.$showToast(this.agentId?'编辑成功':'创建成功');
  180. setTimeout(()=>{
  181. let url = this.agentId?'/pages/home':'/pages/role'
  182. uni.reLaunch({ url })
  183. },1500)
  184. })
  185. },
  186. getDetail(){
  187. this.$api.get(`/agent/${this.agentId}`).then(res=>{
  188. if(res.data.code!==0) return this.$showToast(res.data.msg)
  189. this.agentDto = {...this.agentDto,...res.data.data};
  190. this.deviceMemo = this.agentDto.systemPrompt;
  191. this.getModelVoiceList();
  192. this.getAgentModelList();
  193. })
  194. },
  195. getAgentModelList(){
  196. this.$api.get('/agent/template').then(res=>{
  197. if(res.data.code!==0) return this.$showToast(res.data.msg)
  198. if(res.data.data.length){
  199. this.modelText = res.data.data.find(d=>d.systemPrompt===this.agentDto.systemPrompt)?.agentName;
  200. }
  201. })
  202. },
  203. }
  204. }
  205. </script>
  206. <style scoped lang="less">
  207. .ph{
  208. font-family: PingFangSC, PingFang SC;
  209. font-weight: 400;
  210. font-size: 28rpx;
  211. color: #A6A6A6;
  212. line-height: 40rpx;
  213. text-align: right;
  214. }
  215. .page{
  216. background: #F7F6F9;
  217. padding: 0 30rpx 30rpx;
  218. box-sizing: border-box;
  219. .box{
  220. background: #FFFFFF;
  221. border-radius: 24rpx;
  222. margin-top: 20rpx;
  223. width: 100%;
  224. padding: 40rpx 30rpx;
  225. box-sizing: border-box;
  226. .title{
  227. font-family: PingFang-SC, PingFang-SC;
  228. font-weight: bold;
  229. font-size: 30rpx;
  230. color: #111111;
  231. line-height: 32rpx;
  232. span{
  233. font-size: 32rpx;
  234. color: #F31616;
  235. }
  236. }
  237. .upload{
  238. margin-top: 12rpx;
  239. display: flex;
  240. flex-direction: column;
  241. align-items: center;
  242. .sc{
  243. width: 188rpx;
  244. height: 188rpx;
  245. }
  246. .text{
  247. font-family: PingFangSC, PingFang SC;
  248. font-weight: 400;
  249. font-size: 26rpx;
  250. color: #A6A6A6;
  251. line-height: 37rpx;
  252. text-align: center;
  253. margin-top: 8rpx;
  254. }
  255. }
  256. .right{
  257. .mtext{
  258. font-family: PingFangSC, PingFang SC;
  259. font-weight: 400;
  260. font-size: 28rpx;
  261. color: #A6A6A6;
  262. line-height: 40rpx;
  263. text-align: right;
  264. &.active{
  265. color: #111111;
  266. }
  267. }
  268. image{
  269. width: 36rpx;
  270. height: 36rpx;
  271. margin-left: 10rpx;
  272. }
  273. }
  274. .desc{
  275. margin-top: 20rpx;
  276. min-height: 200rpx;
  277. }
  278. .tip{
  279. font-family: PingFangSC, PingFang SC;
  280. font-weight: 400;
  281. font-size: 28rpx;
  282. color: #A6A6A6;
  283. line-height: 40rpx;
  284. text-align: right;
  285. }
  286. .imgs{
  287. width: 188rpx;
  288. height: 188rpx;
  289. border-radius: 50%;
  290. position: relative;
  291. .img1{
  292. width: 188rpx;
  293. height: 188rpx;
  294. border-radius: 50%;
  295. position: absolute;
  296. z-index: 2;
  297. }
  298. .img2{
  299. width: 42rpx;
  300. height: 42rpx;
  301. position: absolute;
  302. right: 0;
  303. bottom: 0;
  304. z-index: 3;
  305. }
  306. }
  307. }
  308. .zt_btn{
  309. margin-top: 54rpx;
  310. }
  311. input{
  312. border: none;
  313. text-align: right;
  314. font-size: 28rpx;
  315. }
  316. }
  317. </style>