AI-draw.vue 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824
  1. <template>
  2. <view class="container" :style="{'top': (viewTop / 10) + 'vw', 'height': viewHeight + 'px'}">
  3. <view class="content">
  4. <scroll-view scroll-y="true" :show-scrollbar="false" :scroll-top="scroll_top" style="top: 0%;width: 80vw; height:65%;position: absolute;">
  5. <view class="scroll-view-text">
  6. <view style="margin-left: 13%; display: flex; align-items: center;justify-content: center;width: 100%; user-select: text;" v-for="(msgIndex,index) in recvMsgQueue " :key="index">
  7. <!-- ai 的消息结构体 -->
  8. <view v-if="isAItell(recvMsgQueue[index].who_msg)" style="width: 100%;height: 100%;margin-bottom: 1%;">
  9. <text style=" font-size: 10rpx;color: #B34FFF;font-size: 10rpx;margin-left: 2%;background: linear-gradient(90deg, #24BF74 10%, #FAEE07 90%);-webkit-background-clip: text;-webkit-text-fill-color: transparent;">
  10. {{ai_name}}
  11. </text>
  12. <view style="margin-bottom: 3%; margin-top: 1%;margin-left: 1%;padding: 1%; width: 70%;background: #2A2832;border-radius: 10rpx 10rpx 10rpx 10rpx;">
  13. <view @tap="handleClick()" style="width: 100%;background-color: #2A2832;color: white;" class="htmlContent" ref="htmlContent" v-html="returnText(recvMsgQueue[index].msg_text)" >
  14. </view>
  15. <image v-if="getImg(index)!=''" :src="getImg(index)" @click="onclickAiGetImg(index)"></image>
  16. <view @click="stopRecv()" v-if="recvStatus&&recvMsgQueue[index].isFinish==false" style="display: flex;width: 100%;align-items: center;justify-content: center;">
  17. <image src="../../static/closed.png" style="width: 50upx;height: 50upx;align-self: center;"></image>
  18. </view>
  19. </view>
  20. <view v-if="false" style="margin-left: 65%;">
  21. <image src="../../static/msg-opt-3.png" style="margin-left: 10upx;width: 30upx;height: 30upx;"></image>
  22. <image src="../../static/msg-opt-4.png" style="margin-left: 10upx;width: 30upx;height: 30upx;"></image>
  23. </view>
  24. <view style=" display: flex;flex-wrap: wrap;width: 50%;">
  25. <view style="width: 23%;justify-content: center;align-items: center;display: flex;margin-top: 2%; margin-right: 2%;" v-for="(item,i) in recvMsgQueue[index].actions" key="key">
  26. <view @click="clickitem(recvMsgQueue[index].actions[i],recvMsgQueue[index].image_id)" style="background-color: #32B3AA;display: flex; box-sizing: border-box; border-radius: 5px;align-items: center;justify-content: center;width: 100%; padding: 2%; font-size: 1.7vw; word-break: break-all; text-overflow: ellipsis; word-wrap: break-word; white-space: pre-wrap; text-align: center;">{{recvMsgQueue[index].actions[i]}}</view>
  27. </view>
  28. </view>
  29. </view>
  30. <!-- 我发送 的消息结构体 -->
  31. <view v-if="!isAItell(recvMsgQueue[index].who_msg)" style="width: 100%;height: 100%;margin-top: 1%;">
  32. <view style=" font-size: 10rpx;color: #B34FFF;font-size: 10rpx;margin-left: 2%;">
  33. {{user_name}}
  34. </view>
  35. <view style="margin-bottom: 3%; margin-top: 1%;margin-left: 1%;padding: 1%; width: 70%;background: #2A2832;border-radius: 10rpx 10rpx 10rpx 10rpx;">
  36. <view style="width: 100%;background-color: #2A2832;color: white;" class="htmlContent" ref="htmlContent" >
  37. {{recvMsgQueue[index].msg_text}}
  38. </view>
  39. <image v-if="recvMsgQueue[index].des_img!=''" :src="recvMsgQueue[index].des_img" style="background-color: #111111; margin-top: 1%;" mode="aspectFit" @click="onclickSendImg(index)"></image>
  40. </view>
  41. <view v-if="false" style="margin-left: 65%;">
  42. <image src="../../static/msg-opt-1.png" style="margin-left: 10upx; width: 30upx;height: 30upx;"></image>
  43. <image src="../../static/msg-opt-2.png" style="margin-left: 10upx;width: 30upx;height: 30upx;"></image>
  44. <image src="../../static/msg-opt-3.png" style="margin-left: 10upx;width: 30upx;height: 30upx;"></image>
  45. <image src="../../static/msg-opt-4.png" style="margin-left: 10upx;width: 30upx;height: 30upx;"></image>
  46. </view>
  47. </view>
  48. </view>
  49. </view>
  50. </scroll-view>
  51. <view class="inputbox" style="display: flex;width: 70vw;height: 90upx;position: absolute;bottom:300upx;">
  52. <view style="display: flex;align-items: center;justify-content: center;width: 5%;position: relative;">
  53. <image @click="onclickchooseImg()" src="../../static/img_upload.png" style="width: 65upx;height: 65upx;"></image>
  54. </view>
  55. <view style="display: flex;width: 90%; margin-left: 5px; border-radius: 25px 25px 25px 25px;opacity: 1;border: 1px solid #32B3AA;" class="textarea-box">
  56. <view style="width: 90%; height: 100%; display: flex;align-items: center;justify-content: center" >
  57. <textarea v-model="inputValue" :cursor-spacing="15" class="textarea" auto-height="true"
  58. @keydown.enter="onKeydown('enter')" :disabled="disabled"
  59. @input="onKeyInput"
  60. placeholder="请输入消息内容(使用 Enter 发送)" :maxlength="-1"
  61. placeholder-class="input-placeholder"></textarea>
  62. </view>
  63. <view v-if="recvStatus==false" style="width: 10%; height: 100%; display: flex; color: aliceblue;align-items: center;justify-content: center" @click="sendMsg">
  64. <image src="../../static/img_send.png" style="width: 29.57upx;height: 37.67upx;" ></image>
  65. </view>
  66. </view>
  67. <view style=" display: flex;align-items: center;justify-content: center;width: 5%;position: relative;">
  68. <image @click="onclickdelete()" src="../../static/img_delete.png" style="width: 50upx;height: 70upx;"></image>
  69. </view>
  70. </view>
  71. </view>
  72. <view style="position: absolute;top: 10%;right: 5%;width: 200upx;display: flex;align-items: center;justify-content: center;">
  73. <view style="color: white;margin-right: 10upx;">开启快速</view>
  74. <image @click="is_open_relax=false" v-show="is_open_relax==true" src="../../static/img-off.png" style="width: 60upx;height: 30upx;"></image>
  75. <image @click="is_open_relax=true" v-show="is_open_relax==false" src="../../static/img-on.png" style="width: 60upx;height: 30upx;"></image>
  76. </view>
  77. <view v-if="false" @click="is_show_import_img_view=true" style="position: absolute;top: 20%;right: 5%;width: 200upx;display: flex;align-items: center;justify-content: center;">
  78. <view style="color: white;margin-right: 10upx;">导入图片</view>
  79. <image src="../../static/import-img.png" style="width: 60upx;height: 60upx;"></image>
  80. </view>
  81. <view v-if="is_show_import_img_view==true" style=" display: flex; height: 100vh; position: absolute;top: 0;width: 500upx;background-color:#24BF74;">
  82. <view style="width: 100%;;">
  83. <view @click="onFileInput" style="display: flex;align-items: center;justify-content: center;margin-top: 5%;center;margin-bottom: 5%;">
  84. <image :src="cur_select_img" style="width: 100upx;height: 100upx;"></image>
  85. </view>
  86. <view style="display: flex;align-items: center;justify-content: center;margin-top: 5%;center;margin-bottom: 5%;">
  87. <textarea style="display: flex;align-items: center;justify-content: center;" v-model="diy_inputValue" :cursor-spacing="15" auto-height="true"
  88. @input="onKeyInput"
  89. placeholder="请输入描述" :maxlength="-1"
  90. placeholder-class="input-placeholder"></textarea>
  91. </view>
  92. <view @click="send_diy_img()" style="display: flex;align-items: center;justify-content: center;margin-top: 5%;center;margin-bottom: 5%;">
  93. <view style="display: flex;align-items: center;justify-content: center;background-color: aqua;;border-radius: 10rpx 10rpx 10rpx 10rpx;width: 50%;">发送</view>
  94. </view>
  95. <view @click="is_show_import_img_view=false" style="display: flex;align-items: center;justify-content: center;margin-top: 5%;center;margin-bottom: 5%;">
  96. <view style="display: flex;align-items: center;justify-content: center;background-color: aqua;;border-radius: 10rpx 10rpx 10rpx 10rpx;width: 50%;">关闭</view>
  97. </view>
  98. <scroll-view scroll-y="true" style="height:500upx;">
  99. <view @click="selectImg(import_list[j])" style="display: flex;align-items: center;justify-content: center;" v-for="(itemx,j) in import_list" :key="j">
  100. <image style="width: 150upx;height: 150upx;margin-top: 5%;" :src="import_list[j]"></image>
  101. </view>
  102. </scroll-view>
  103. </view>
  104. </view>
  105. <view v-if="choose_img_tempFilePath != ''" style="position: fixed; top: 535px; left: 20%; width: 130px; height: 90px;">
  106. <view style="position: absolute; top: 10px; width: 120px; height: 80px; background-color: #111111;">
  107. <image style="width: 100%; height: 100%;" :src="choose_img_tempFilePath" mode="aspectFill" @click="onclickPreviewChooseImg"></image>
  108. </view>
  109. <view style="position: absolute; right: 0; width: 30px; height: 30px;" @click="onclickDeleteChooseImg">
  110. <image style="margin-left: 10px; width: 20px; height: 20px;" src="../../static/img_jian.png" mode="aspectFit"></image>
  111. </view>
  112. </view>
  113. <view v-if="is_up_img_file" style="align-items: center;justify-content: center;display: flex; color: aliceblue; position: absolute; width: 100vw;height:100vh;background-color: black;opacity: 70%;">
  114. 正在上传图片...
  115. </view>
  116. </view>
  117. </template>
  118. <script>
  119. import marked from '../marked/marked.min.js';
  120. import config from '../index/config.js';
  121. import hljs from "../highlight.js/lib/common.js";
  122. import interfaces from '../../utils/interfaces.js'
  123. import "../highlight.js/styles/atom-one-dark.css";
  124. // import '../v-copy.js';
  125. // 键盘的shift键是否被按下
  126. let shiftKeyPressed = false
  127. export default {
  128. components:{
  129. marked
  130. },
  131. data() {
  132. return {
  133. diy_inputValue: '',
  134. is_up_img_file:false,
  135. import_list:[],
  136. is_show_import_img_view:false,
  137. is_open_relax:true,
  138. code:'',
  139. title: 'Hello',
  140. disabled: false,
  141. socketOpen:false,
  142. socketMsgQueue:[],
  143. recvMsgQueue:[],
  144. sendMsgQueue:[],
  145. inputValue: '',
  146. inputOldValue: '',
  147. _socketTask:null,
  148. scroll_text_:"\n",
  149. sendStatus:false,
  150. recvStatus:false,
  151. all_src_list:[],
  152. src_index:0,
  153. scroll_top:0,
  154. user_name:'ZYWZ', //用户名字
  155. ai_name:"SmartAssistant", //ai名字
  156. user_mobile:"18612220000",//用户手机号
  157. ani:'',
  158. ani_style:{
  159. width: "100upx",height: "100upx",rotate: 0,left:"25%",right:"25%",position:"absolute"
  160. },
  161. angle:359,
  162. imageUrl:'',
  163. fileData:null,
  164. cur_select_img:'../../static/import-img.png',
  165. choose_img_tempFilePath: '',
  166. }
  167. },
  168. mounted(){
  169. this.user_mobile = this.tools.get_user_info().mobile
  170. marked.setOptions({
  171. renderer: new marked.Renderer(),
  172. gfm: true,
  173. tables: true,
  174. breaks: false,
  175. pedantic: false,
  176. sanitize: false,
  177. smartLists: true,
  178. smartypants: false,
  179. highlight: function (code) {
  180. return hljs.highlightAuto(code).value;
  181. },
  182. langPrefix:"hljs language-"
  183. });
  184. },
  185. props: {
  186. viewTop: {
  187. type: Number,
  188. default: 0
  189. },
  190. viewHeight: {
  191. type: Number,
  192. default: 0
  193. }
  194. },
  195. methods: {
  196. send_diy_img(){
  197. if(this.cur_select_img==="../../static/import-img.png"){
  198. uni.showToast({
  199. title:"请选择图片"
  200. })
  201. return
  202. }
  203. if(this.diy_inputValue.length>0){
  204. this.is_show_import_img_view = false;
  205. let des_img = this.cur_select_img;
  206. this.sendSocketMessage(this.diy_inputValue,this.cur_select_img+" "+this.diy_inputValue,des_img)
  207. this.diy_inputValue = '';
  208. }else{
  209. uni.showToast({
  210. title:"请添加描述,只支持英文哦"
  211. })
  212. }
  213. },
  214. selectImg(path){
  215. let self = this;
  216. self.cur_select_img = path;
  217. },
  218. onFileInput(event) {
  219. let self = this;
  220. uni.chooseImage({
  221. success: (chooseImageRes) => {
  222. const tempFilePaths = chooseImageRes.tempFilePaths;
  223. self.is_up_img_file = true;
  224. uni.uploadFile({
  225. url: 'https://mlapi.hainanmlwl.com/file/upload_aiimg', //仅为示例,非真实的接口地址
  226. filePath: tempFilePaths[0],
  227. name: 'aiimg_url',
  228. formData: {
  229. // 'aiimg_url': self.cur_select_img
  230. },
  231. success: (uploadFileRes) => {
  232. self.is_up_img_file = false;
  233. let obj = JSON.parse(uploadFileRes.data)
  234. uni.showModal({
  235. content:obj.message,
  236. showCancel:false
  237. })
  238. console.log("self.cur_select_img",self.cur_select_img)
  239. if(obj.code==10000){
  240. let img_url = obj.content.surl
  241. self.import_list.push(img_url)
  242. self.cur_select_img = img_url;
  243. }
  244. console.log("uploadFile",obj);
  245. },
  246. fail() {
  247. uni.showModal({
  248. content:"上传失败",
  249. showCancel:false
  250. })
  251. self.is_up_img_file = false;
  252. }
  253. });
  254. }
  255. });
  256. // console.log("onFileInput",event)
  257. // const file = event.target.files[0] // 获取选择的文件
  258. // const reader = new FileReader() // 创建FileReader对象
  259. // // 当文件被读取时,将其转换为DataURL格式的字符串,并将其作为imageUrl值赋给组件的data属性中
  260. // reader.onload = (e) => {
  261. // this.imageUrl = e.target.result
  262. // // 保存文件对象到data属性中
  263. // this.fileData = file
  264. // }
  265. // reader.readAsDataURL(file) // 读取文件并启动onload回调函数
  266. },
  267. clickitem(action,image_id){
  268. switch(action){
  269. case "upsample1":
  270. break;
  271. case "upsample2":
  272. break;
  273. case "upsample3":
  274. break;
  275. case "upsample4":
  276. break;
  277. case "variation1":
  278. break;
  279. case "variation2":
  280. break;
  281. case "variation3":
  282. break;
  283. case "variation4":
  284. break;
  285. }
  286. console.log("clickitem",this.recvStatus,action,image_id)
  287. if(!this.recvStatus){
  288. this.sendSocketMessage(action,'','',action,image_id)
  289. }
  290. },
  291. getImg(index){
  292. return this.recvMsgQueue[index].msg_img
  293. },
  294. onclickdelete(){
  295. let self = this;
  296. if(self.recvMsgQueue.length>0&&self.recvMsgQueue[self.recvMsgQueue.length-1].isFinish){
  297. uni.showModal({
  298. showCancel:true,
  299. content:"是否删除记录",
  300. success:(res)=>{
  301. if(res.confirm){
  302. self.recvMsgQueue = []
  303. }
  304. }
  305. })
  306. }
  307. },
  308. // #ifdef H5 && VUE2
  309. onKeydown(keyname) {
  310. let self = this;
  311. if(self.inputOldValue!=self.inputValue){
  312. self.sendMsg();
  313. }else{
  314. }
  315. },
  316. onKeyup(keyname) {
  317. let self = this;
  318. self.inputOldValue=self.inputValue;
  319. },
  320. // #endif
  321. setCopy(content){
  322. // 使用#ifdef H5和#endif控制各端调用情况
  323. // 该方法不支持h5
  324. //#ifndef H5
  325. uni.setClipboardData({
  326. data: String(content), // 必须字符串
  327. success: function () {
  328. console.log('success');
  329. }
  330. });
  331. //#endif
  332. // h5端赋值方法,使用创建节点
  333. // #ifdef H5
  334. if (!document.queryCommandSupported('copy')) { // 兼容某些浏览器的判断
  335. console.log('该浏览器不支持')
  336. }
  337. let textarea = document.createElement("textarea")
  338. textarea.value = content
  339. textarea.readOnly = "readOnly"
  340. document.body.appendChild(textarea)
  341. textarea.select() // 选择对象
  342. textarea.setSelectionRange(0, content.length) // 核心
  343. let result = document.execCommand("copy") // 执行浏览器复制命令
  344. if (result) {
  345. uni.showToast({
  346. title: '复制成功',
  347. duration: 2000
  348. });
  349. }
  350. textarea.remove()
  351. // #endif
  352. },
  353. updateSrcList(){
  354. let self = this;
  355. let list = this.getIndexList(self.scroll_text_);
  356. for (var i = 0; i < list.length; i+=2) {
  357. let start = list[i];
  358. let end = list[i+1];
  359. self.all_src_list.push(self.scroll_text_.substring(start,end))
  360. }
  361. console.log("updateSrcList",self.all_src_list,self.scroll_text_)
  362. },
  363. stopRecv(){
  364. let self =this;
  365. self._socketTask.close()
  366. // self.initTcp(true);
  367. self.finish_recv();
  368. },
  369. handleClick(e) {
  370. e = e || window.event;
  371. let target = e.target || e.srcElement;
  372. let name = target.tagName.toLowerCase();
  373. let self =this;
  374. if(name.substring(0,3)=="abc"){
  375. let name_list = name.split('_');
  376. if(name_list.length>0){
  377. let index = parseInt(name_list[1])-1;
  378. console.log("handleClick",index,self.all_src_list)
  379. self.setCopy(self.all_src_list[index])
  380. }
  381. console.log("handleClick",self.all_src_list[index])
  382. console.log(target.tagName.toLowerCase())
  383. }
  384. console.log(name.substring(0,3))
  385. },
  386. copyUpdates(){
  387. let self = this;
  388. let str = self.recvMsgQueue[self.recvMsgQueue.length-1].msg_text
  389. let key = "</code></pre>";
  390. let index = self.all_src_list.length;
  391. while(str.indexOf(key) != -1){
  392. index++;
  393. let s_tag = "</code><abc_"+index+" class=\"copy-button\">Copy</abc_"+index+"></pre>"
  394. console.log("s_tag",s_tag)
  395. str=str.replace("</code></pre>", s_tag)
  396. }
  397. // str=str.replaceAll("</code></pre>", "</code><abc class=\"copy-button\">Copy</abc></pre>")
  398. self.recvMsgQueue[self.recvMsgQueue.length-1].msg_text = str
  399. // console.log("copyUpdates",str)
  400. self.$forceUpdate();
  401. },
  402. getIndexList(box_str){
  403. let box = box_str;
  404. let boxarr=[];
  405. let pos = box.indexOf('```');
  406. while(pos>-1){
  407. boxarr.push(pos);
  408. pos= box.indexOf('```',pos+1);
  409. }
  410. return boxarr
  411. },
  412. returnText(text){
  413. return "<style> body { background-color: black; color: white; } pre {position: relative;}.copy-button { position: absolute; top: 0;right: 0;padding: 4px 8px;background-color: #333;color: #fff;cursor: pointer;user-select: none;} p {line-height: 2;} li{line-height: 1.5;} table {border-collapse: collapse;width: 100%;font-family: Arial, sans-serif;font-size: 14px;}table th,table td {border: 1px solid #ddd;padding: 8px;text-align: left;}</style>" +text
  414. },
  415. // 滚动窗口以显示最新的一条消息
  416. showLastMsg() {
  417. let self = this;
  418. let container = uni.createSelectorQuery().in(this).select(".scroll-view-text");
  419. // 利用uniapp提供的接口获取可视区域的高度和滚动高度
  420. // let query=uni.createSelectorQuery()
  421. // let container=query.select('.box');
  422. container.fields({
  423. // rect:true, //是否返回节点布局位置信息{left,top,right,bottom}
  424. size:true, //是否返回节点尺寸信息{width,height}
  425. scrollOffset:true //是否返回节点滚动信息{scrollLeft,scrollTop}
  426. },(res)=>{
  427. self.scroll_top = res.height;
  428. // console.log(res)
  429. }).exec()
  430. },
  431. isAItell(type){
  432. if(type===config.type_ai){
  433. return true;
  434. }
  435. return false;
  436. },
  437. make_avatar(type){
  438. if(type===config.type_ai){
  439. return "../../static/PubImgs_avatar_avatar7.png";
  440. }
  441. return "../../static/PubImgs_avatar_avatar8.png";
  442. },
  443. isShow(text){
  444. return text!="";
  445. },
  446. initAni(){
  447. let self = this;
  448. if(!self.disabled){
  449. clearTimeout(self.initAni)
  450. return;
  451. }
  452. let loading_title = self.recvMsgQueue[self.recvMsgQueue.length-1].loading_title;
  453. let loading_title_str = ""
  454. for (var i = 0; i < loading_title; i++) {
  455. loading_title_str+="."
  456. }
  457. // console.log("loading_title_str",loading_title_str)
  458. self.recvMsgQueue[self.recvMsgQueue.length-1].msg_text ="正在生成" +loading_title_str;
  459. loading_title = loading_title>=3?0: (loading_title+1)
  460. self.recvMsgQueue[self.recvMsgQueue.length-1].loading_title = loading_title;
  461. setTimeout(self.initAni,1000)
  462. },
  463. async finish_recv(){
  464. let self = this;
  465. self.recvStatus = false;
  466. self.disabled = false;
  467. clearTimeout(self.initAni)
  468. self.scroll_text_+="\n"
  469. console.log("self.recvMsgQueue",self.scroll_text_)
  470. self.stopUpdateView();
  471. self.copyUpdates();
  472. self.updateSrcList();
  473. self.showLastMsg();
  474. self.recvMsgQueue[self.recvMsgQueue.length-1].isFinish = true;
  475. },
  476. async sendMsg(){
  477. if(this.choose_img_tempFilePath != '') {
  478. this.sendImageAndTextOperation()
  479. return
  480. }
  481. // 如果内容为空
  482. if (!this.inputValue) {
  483. // 弹出提示框
  484. return uni.showToast({
  485. // 提示内容
  486. title: '内容不能为空',
  487. // 不显示图标
  488. icon: 'none'
  489. });
  490. }
  491. this.sendSocketMessage(this.inputValue)
  492. },
  493. onKeyInput(event) {
  494. // console.log("onKeyInput",event.target.value)
  495. let self = this;
  496. // self.inputOldValue=self.inputValue
  497. },
  498. startUpdateView(){
  499. let self = this;
  500. self.$forceUpdate();
  501. setTimeout(self.startUpdateView,500)
  502. },
  503. stopUpdateView(){
  504. let self = this;
  505. clearTimeout(self.startUpdateView)
  506. },
  507. sendSocketMessage(msg,prompt=msg,des_img='',action='generate',image_id='') {
  508. console.log("sendSocketMessage send",des_img)
  509. let self = this;
  510. let isRelax = self.is_open_relax;
  511. let token = isRelax?"7d995cf958f54d2c9c3264e645a9c4d9":"bdb957b8003e4a46b6b26a7174be5789";
  512. let relax = isRelax?"/relax" :"";
  513. let url = 'https://api.zhishuyun.com/midjourney/imagine' +relax +'?token='+token
  514. self.sendStatus = true;
  515. self.disabled = true;
  516. self.ani_style.rotate = 0;
  517. self.inputValue = '';
  518. self.recvMsgQueue.push({who_msg:config.type_self,msg_type:0,msg_text:msg,isFinish:true,'des_img':des_img})
  519. self.recvMsgQueue.push({who_msg:config.type_ai,msg_type:0,msg_text:"正在生成...",msg_img:"",isFinish:false,actions:[],image_id:"",task_id:"",loading_title:1})
  520. // self.recvMsgQueue[self.recvMsgQueue.length-1].actions=['upsample1', 'upsample2', 'upsample3', 'upsample4', 'variation1', 'variation2', 'variation3', 'variation4']
  521. self.initAni();
  522. uni.request({
  523. url:url,
  524. timeout:600000,
  525. header: {'Content-Type':'application/json','accept':'application/json'},
  526. method:'POST',
  527. data:{'prompt':prompt,'action':action,'image_id':image_id},
  528. success:(res)=>{
  529. self.finish_recv()
  530. if(res.statusCode===200){
  531. let html_img = '<!DOCTYPE html> <html><head></head><body> <img src='+res.data.image_url+ '></body></html>'
  532. self.recvMsgQueue[self.recvMsgQueue.length-1].msg_img = res.data.image_url;
  533. self.recvMsgQueue[self.recvMsgQueue.length-1].msg_text = "";
  534. self.recvMsgQueue[self.recvMsgQueue.length-1].image_id = res.data.image_id;
  535. console.log("res.data.actions",res.data.actions)
  536. self.recvMsgQueue[self.recvMsgQueue.length-1].actions = [];
  537. let list = [];
  538. list = res.data.actions;
  539. for (var i = 0; i < list.length; i++) {
  540. self.recvMsgQueue[self.recvMsgQueue.length-1].actions.push(list[i])
  541. }
  542. }else{
  543. uni.showModal({
  544. content:res.data.detail+":"+res.statusCode,
  545. showCancel:false
  546. })
  547. self.recvMsgQueue[self.recvMsgQueue.length-1].msg_text = res.data.detail;
  548. }
  549. console.log("Ai-view",res)
  550. },
  551. fail: (e) => {
  552. console.log('fail', e)
  553. self.finish_recv()
  554. self.recvMsgQueue[self.recvMsgQueue.length-1].msg_text ="生成失败";
  555. }
  556. })
  557. },
  558. onclickSendImg(index){
  559. let img_url = this.recvMsgQueue[index].des_img
  560. if(img_url) {
  561. uni.previewImage({
  562. urls:[img_url]
  563. })
  564. } else {
  565. uni.showToast({
  566. icon:'error',
  567. title:'预览图片失败',
  568. duration:2000
  569. })
  570. }
  571. },
  572. onclickAiGetImg(index){
  573. let img_url = this.getImg(index)
  574. if(img_url) {
  575. uni.previewImage({
  576. urls:[img_url]
  577. })
  578. } else {
  579. uni.showToast({
  580. icon:'error',
  581. title:'预览图片失败',
  582. duration:2000
  583. })
  584. }
  585. },
  586. onclickPreviewChooseImg() {
  587. let img_url = this.choose_img_tempFilePath
  588. if(img_url) {
  589. uni.previewImage({
  590. urls:[img_url]
  591. })
  592. } else {
  593. uni.showToast({
  594. icon:'error',
  595. title:'预览图片失败',
  596. duration:2000
  597. })
  598. }
  599. },
  600. onclickDeleteChooseImg() {
  601. let self = this
  602. uni.showModal({
  603. showCancel:true,
  604. content:"是否删除",
  605. success:(res)=>{
  606. if(res.confirm){
  607. self.choose_img_tempFilePath = ''
  608. }
  609. }
  610. })
  611. },
  612. onclickchooseImg(event){
  613. let self = this;
  614. uni.chooseImage({
  615. success: (chooseImageRes) => {
  616. const tempFilePaths = chooseImageRes.tempFilePaths;
  617. this.choose_img_tempFilePath = tempFilePaths[0]
  618. if(tempFilePaths.length > 0) {
  619. self.choose_img_tempFilePath = tempFilePaths[0]
  620. } else {
  621. uni.showToast({
  622. icon:'error',
  623. title:'图片选择失败,请重新选择',
  624. duration:2000
  625. })
  626. }
  627. }
  628. });
  629. },
  630. sendImageAndTextOperation() {
  631. if (this.inputValue.length == 0) {
  632. return uni.showToast({
  633. title: '请添加描述哦,只支持英文',
  634. icon: 'none'
  635. });
  636. }
  637. let self = this
  638. self.is_up_img_file = true
  639. // 上传图片+发送图片链接和文本
  640. // 上传图片
  641. uni.uploadFile({
  642. url: 'https://mlapi.hainanmlwl.com/file/upload_aiimg',
  643. filePath: self.choose_img_tempFilePath,
  644. name: 'aiimg_url',
  645. formData: {
  646. // 'aiimg_url': self.cur_select_img
  647. },
  648. success: (uploadFileRes) => {
  649. console.log("uploadFile",uploadFileRes);
  650. self.is_up_img_file = false;
  651. let obj = JSON.parse(uploadFileRes.data)
  652. uni.showToast({
  653. title:obj.message,
  654. duration:1500
  655. })
  656. if(obj.code == 10000) {
  657. let img_url = obj.content.surl
  658. if(img_url == '') {
  659. uni.showModal({
  660. content:"图片链接为空",
  661. showCancel:false
  662. })
  663. return
  664. }
  665. if(self.choose_img_tempFilePath != '') {
  666. self.choose_img_tempFilePath = ''
  667. }
  668. // 发送
  669. self.sendSocketMessage(self.inputValue, img_url+" "+self.inputValue ,img_url)
  670. } else {
  671. uni.showModal({
  672. showCancel:false,
  673. content:obj.msg
  674. })
  675. }
  676. },
  677. fail(err) {
  678. console.log('上传失败err=',err)
  679. uni.showModal({
  680. content:"上传失败",
  681. showCancel:false
  682. })
  683. self.is_up_img_file = false;
  684. }
  685. });
  686. // if(this.cur_select_img==="../../static/import-img.png"){
  687. // uni.showToast({
  688. // title:"请选择图片"
  689. // })
  690. // return
  691. // }
  692. // if(this.diy_inputValue.length>0){
  693. // this.is_show_import_img_view = false;
  694. // let des_img = this.cur_select_img;
  695. // this.sendSocketMessage(this.diy_inputValue,this.cur_select_img+" "+this.diy_inputValue,des_img)
  696. // this.diy_inputValue = '';
  697. // }else{
  698. // uni.showToast({
  699. // title:"请添加描述,只支持英文哦"
  700. // })
  701. // }
  702. }
  703. }
  704. }
  705. </script>
  706. <style>
  707. .container{
  708. display: flex;
  709. box-sizing: border-box;
  710. flex-direction: column;
  711. position: fixed;
  712. /* position: relative; */
  713. /* background-color: #2A2832; */
  714. left: 0;
  715. width: 100%;
  716. justify-content: center;
  717. }
  718. .content {
  719. height: 100%;
  720. display: flex;
  721. flex-direction: column;
  722. align-items: center;
  723. justify-content: center;
  724. position: relative;
  725. background-color: #2A2832;
  726. }
  727. .text-area {
  728. display: flex;
  729. justify-content: center;
  730. }
  731. .title {
  732. font-size: 36rpx;
  733. color: #8f8f94;
  734. }
  735. .textarea-box,
  736. .textarea {
  737. width: 100%;
  738. height: 100%;
  739. margin-left: 3%;
  740. },
  741. textarea-box {
  742. width: 100% !important;
  743. }
  744. .textarea-box,
  745. .textarea,
  746. textarea,
  747. textarea-box {
  748. /* height: 120px; */
  749. }
  750. .textarea-box {
  751. background-color: #FFF;
  752. }
  753. uni-scroll-view .uni-scroll-view::-webkit-scrollbar {
  754. display: none;
  755. width: 0 !important;
  756. height: 0 !important;
  757. -webkit-appearance: none;
  758. background: transparent;
  759. color: transparent;
  760. }
  761. </style>