addRole.vue 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  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. success: (res) => {
  132. let data = JSON.parse(res.data);
  133. if(data){
  134. if(data.code!==0) return
  135. setTimeout(() => {
  136. resolve(data.data);
  137. }, 1000);
  138. }
  139. },
  140. });
  141. });
  142. },
  143. selectModel(){
  144. uni.navigateTo({
  145. url:'/pagesRole/roleModel',
  146. events:{
  147. selectRoleModel:data=>{
  148. this.agentDto = {...this.agentDto,...data};
  149. this.modelText = data.agentName||'';
  150. this.deviceMemo = data.systemPrompt||'';
  151. this.getModelVoiceList();
  152. }
  153. }
  154. })
  155. },
  156. getModelVoiceList(){
  157. this.$api.get(`/models/${this.agentDto.ttsModelId}/voices`).then(res=>{
  158. if(res.data.code!==0) return this.$showToast(res.data.msg)
  159. this.voiceList = [res.data.data];
  160. this.voiceText = res.data.data.find(v=>v.id===this.agentDto.ttsVoiceId)?.name||'';
  161. })
  162. },
  163. confirm(e){
  164. this.show = false;
  165. this.agentDto.ttsVoiceId = e.value[0].id;
  166. this.voiceText = e.value[0].name;
  167. },
  168. comfirmSure(){
  169. if(!this.agentDto.agentName) return this.$showToast('请输入角色昵称')
  170. if(this.agentDto.modelText==='请选择角色模版') return this.$showToast('请选择角色模板')
  171. if(this.agentDto.voiceText==='请选择音色') return this.$showToast('请选择音色')
  172. let dto = JSON.parse(JSON.stringify(this.agentDto));
  173. if(this.agentId) dto.deviceId = this.deviceId;
  174. this.$api.post(this.agentId?`/agent/update/${this.agentId}`:'/agent',dto).then(res=>{
  175. if(res.data.code!==0) return this.$showToast(res.data.msg)
  176. this.$showToast(this.agentId?'编辑成功':'创建成功');
  177. setTimeout(()=>{
  178. let url = this.agentId?'/pages/home':'/pages/role'
  179. uni.reLaunch({ url })
  180. },1500)
  181. })
  182. },
  183. getDetail(){
  184. this.$api.get(`/agent/${this.agentId}`).then(res=>{
  185. if(res.data.code!==0) return this.$showToast(res.data.msg)
  186. this.agentDto = {...this.agentDto,...res.data.data};
  187. this.deviceMemo = this.agentDto.systemPrompt;
  188. this.getModelVoiceList();
  189. this.getAgentModelList();
  190. })
  191. },
  192. getAgentModelList(){
  193. this.$api.get('/agent/template').then(res=>{
  194. if(res.data.code!==0) return this.$showToast(res.data.msg)
  195. if(res.data.data.length){
  196. this.modelText = res.data.data.find(d=>d.systemPrompt===this.agentDto.systemPrompt)?.agentName;
  197. }
  198. })
  199. },
  200. }
  201. }
  202. </script>
  203. <style scoped lang="less">
  204. .ph{
  205. font-family: PingFangSC, PingFang SC;
  206. font-weight: 400;
  207. font-size: 28rpx;
  208. color: #A6A6A6;
  209. line-height: 40rpx;
  210. text-align: right;
  211. }
  212. .page{
  213. background: #F7F6F9;
  214. padding: 0 30rpx 30rpx;
  215. box-sizing: border-box;
  216. .box{
  217. background: #FFFFFF;
  218. border-radius: 24rpx;
  219. margin-top: 20rpx;
  220. width: 100%;
  221. padding: 40rpx 30rpx;
  222. box-sizing: border-box;
  223. .title{
  224. font-family: PingFang-SC, PingFang-SC;
  225. font-weight: bold;
  226. font-size: 30rpx;
  227. color: #111111;
  228. line-height: 32rpx;
  229. span{
  230. font-size: 32rpx;
  231. color: #F31616;
  232. }
  233. }
  234. .upload{
  235. margin-top: 12rpx;
  236. display: flex;
  237. flex-direction: column;
  238. align-items: center;
  239. .sc{
  240. width: 188rpx;
  241. height: 188rpx;
  242. }
  243. .text{
  244. font-family: PingFangSC, PingFang SC;
  245. font-weight: 400;
  246. font-size: 26rpx;
  247. color: #A6A6A6;
  248. line-height: 37rpx;
  249. text-align: center;
  250. margin-top: 8rpx;
  251. }
  252. }
  253. .right{
  254. .mtext{
  255. font-family: PingFangSC, PingFang SC;
  256. font-weight: 400;
  257. font-size: 28rpx;
  258. color: #A6A6A6;
  259. line-height: 40rpx;
  260. text-align: right;
  261. &.active{
  262. color: #111111;
  263. }
  264. }
  265. image{
  266. width: 36rpx;
  267. height: 36rpx;
  268. margin-left: 10rpx;
  269. }
  270. }
  271. .desc{
  272. margin-top: 20rpx;
  273. min-height: 200rpx;
  274. }
  275. .tip{
  276. font-family: PingFangSC, PingFang SC;
  277. font-weight: 400;
  278. font-size: 28rpx;
  279. color: #A6A6A6;
  280. line-height: 40rpx;
  281. text-align: right;
  282. }
  283. .imgs{
  284. width: 188rpx;
  285. height: 188rpx;
  286. border-radius: 50%;
  287. position: relative;
  288. .img1{
  289. width: 188rpx;
  290. height: 188rpx;
  291. border-radius: 50%;
  292. position: absolute;
  293. z-index: 2;
  294. }
  295. .img2{
  296. width: 42rpx;
  297. height: 42rpx;
  298. position: absolute;
  299. right: 0;
  300. bottom: 0;
  301. z-index: 3;
  302. }
  303. }
  304. }
  305. .zt_btn{
  306. margin-top: 54rpx;
  307. }
  308. input{
  309. border: none;
  310. text-align: right;
  311. font-size: 28rpx;
  312. }
  313. }
  314. </style>