viewMask.vue 31 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093
  1. <template src="./viewMask.html">
  2. </template>
  3. <script>
  4. const util = require('@/utils/util.js').default;
  5. import { MessageBox } from 'mint-ui';
  6. // const config = require('@/services/url$config.js');
  7. import touchHandle from '@/mixins/touchHandle.js';
  8. // import requestConfig from '@/static/lib/requestConfig';
  9. // const app = getApp(); //获取应用实例
  10. export default {
  11. mixins: [touchHandle],
  12. data: function() {
  13. return {
  14. currentIndex:0, //当前看到的图片序号
  15. showAIImage: false,//是否显示当前AI结果集合 默认不显示,因为没有
  16. aiImagesList:[
  17. ],//AI生成的图片列表
  18. styleList: [], //风格列表数据
  19. curStyleIndex: 0, //当前选中的风格序号
  20. aiFlag:false,
  21. aiImage: "",
  22. inputBase64Url: "",
  23. aiPicId: "", // 图生图任务ID
  24. randomTimer:null,
  25. timer: null,
  26. outTimer: null,
  27. imageWidth: 750,
  28. imageHeight: 448,
  29. showAIFlag:false,//继续生成状态切换标志
  30. checked:false,
  31. shottingImg:'',
  32. count:0,
  33. random:1,
  34. // disableAble:false,
  35. spaceTypes: [{
  36. icon: "",
  37. title: "卧室",
  38. subtitle: "0个布局",
  39. englishRemark: "bedroom",
  40. },
  41. {
  42. icon: "",
  43. title: "客厅",
  44. subtitle: "0个布局",
  45. englishRemark: "living room",
  46. },
  47. {
  48. icon: "",
  49. title: "餐厅",
  50. subtitle: "0个布局",
  51. englishRemark: "dinning room",
  52. },
  53. {
  54. icon: "",
  55. title: "厨房",
  56. subtitle: "0个个布局",
  57. englishRemark: "kitchen",
  58. },
  59. {
  60. icon: "",
  61. title: "玄关",
  62. subtitle: "0个布局",
  63. englishRemark: "hallway",
  64. },
  65. {
  66. icon: "",
  67. title: "卫生间",
  68. subtitle: "0个布局",
  69. englishRemark: "bathroom",
  70. },
  71. {
  72. icon: "",
  73. title: "衣帽间",
  74. subtitle: "0个布局",
  75. englishRemark: "walkin closet",
  76. },
  77. {
  78. icon: "",
  79. title: "收纳",
  80. subtitle: "0个布局",
  81. englishRemark: "storage room",
  82. },
  83. {
  84. icon: "",
  85. title: "阳台",
  86. subtitle: "0个布局",
  87. englishRemark: "balcony",
  88. },
  89. {
  90. icon: "",
  91. title: "飘窗",
  92. subtitle: "0个布局",
  93. englishRemark: "bay window",
  94. },
  95. {
  96. icon: "",
  97. title: "链接空间",
  98. subtitle: "0个布局",
  99. englishRemark: "connecting space between two rooms",
  100. },
  101. {
  102. icon: "",
  103. title: "自定义",
  104. subtitle: "0个布局",
  105. englishRemark: "room",
  106. },
  107. ],
  108. myloading:false,
  109. loadingMsg:'',
  110. screenWidth:0,
  111. screenHeight:0,
  112. modelType:2, //当前模型类型,1指创意设计 2指精准设计 默认2
  113. themeIndex:0,
  114. themeList:[
  115. {
  116. id:1,
  117. text:'默认',
  118. prot:'',
  119. },
  120. {
  121. id:2,
  122. leftColor:'#F4EBDE',
  123. rightColor:'#C1C9B4',
  124. text:'莫兰素雅',
  125. prot:'Soft grays, warm earth tones, subtle blues, soft pinks,',
  126. },
  127. {
  128. id:3,
  129. leftColor:'#1F1F1F',
  130. rightColor:'#FFFFFF',
  131. text:'经典黑白',
  132. prot:'Classic black and pure white,',
  133. },
  134. {
  135. id:4,
  136. leftColor:'#6FA5BE',
  137. rightColor:'#E2CCC5',
  138. text:'海岸珊瑚',
  139. prot:'Deep ocean blue paired with vibrant coral red,',
  140. },
  141. {
  142. id:5,
  143. leftColor:'#849059',
  144. rightColor:'#E6CEB4',
  145. text:'森林璀璨',
  146. prot:'Deep forest green paired with luxurious gold,'
  147. },
  148. {
  149. id:6,
  150. leftColor:'#A1BACB',
  151. rightColor:'#E6DFD8',
  152. text:'梦幻静谧',
  153. prot:'Dreamy powder blue paired with neutral gray,'
  154. },
  155. {
  156. id:7,
  157. leftColor:'#303B2B',
  158. rightColor:'#D8C8A6',
  159. text:'自然和谐',
  160. prot:'Natural olive green paired with warm beige,'
  161. },
  162. {
  163. id:8,
  164. leftColor:'#652C30',
  165. rightColor:'#D5C3B0',
  166. text:'醇酒乳香',
  167. prot:'Rich burgundy paired with soft cream,'
  168. },
  169. {
  170. id:9,
  171. leftColor:'#E3C7C5',
  172. rightColor:'#EDE4DB',
  173. text:'雅致浪漫',
  174. prot:'Understated taupe paired with romantic pink,'
  175. },
  176. {
  177. id:10,
  178. leftColor:'#2C3C6E',
  179. rightColor:'#F0DBBD',
  180. text:'夜空璀璨',
  181. prot:'Elegant navy blue paired with glamorous gold,'
  182. },
  183. {
  184. id:11,
  185. leftColor:'#ACC9A1',
  186. rightColor:'#E6DCC6',
  187. text:'复古翠绿',
  188. prot:'Vintage tan paired with vibrant green,'
  189. },
  190. {
  191. id:12,
  192. leftColor:'#AAA8A7',
  193. rightColor:'#D8A176',
  194. text:'暖阳灰影',
  195. prot:'Warm orange paired with cool gray,'
  196. },
  197. {
  198. id:13,
  199. leftColor:'#413D41',
  200. rightColor:'#D1B687',
  201. text:'耀眼黑金',
  202. prot:'black and gold,'
  203. },
  204. ],
  205. timeOut:20000, //超时时间
  206. subType:0,
  207. currentImg:null,
  208. reqList:[
  209. {
  210. model:'batouresearch/sdxl-controlnet-lora',
  211. level:'5',
  212. aiPicId:'',
  213. resultImg:'',
  214. }
  215. ],
  216. reqListReset:[
  217. {
  218. model:'deployments/elabgroup/elab-sdxl-controlnet-lora',
  219. level:'3',
  220. aiPicId:'',
  221. resultImg:'',
  222. },{
  223. model:'batouresearch/sdxl-controlnet-lora',
  224. level:'5',
  225. aiPicId:'',
  226. resultImg:'',
  227. }
  228. ],
  229. dialogVisible: false,
  230. dialogAIVisible: false,
  231. }
  232. },
  233. props:{
  234. spaceObj: {
  235. type: Object,
  236. default: null,
  237. },
  238. },
  239. watch: {
  240. spaceObj(newVal, oldVal) {
  241. if (newVal == null) {
  242. return;
  243. }
  244. console.log("当前空间数据view-mark-watch:", newVal);
  245. this.getAiBeautyFamily();
  246. // this.curSpaceArea = parseFloat(
  247. // (newVal.spaceWidth * newVal.spaceHeight) / 10000
  248. // ).toFixed(2);
  249. // this.getOverallArrangementDetailsList();
  250. },
  251. },
  252. mounted() {//组件挂载时事件
  253. // console.warn("***mounted-nav***",this.seedItem)
  254. // if(this.seedItem){
  255. // this.title = this.seedItem.seedText;
  256. // }
  257. // wx.checkJsApi({
  258. // jsApiList: ['previewImage'], // 需要检测的JS接口列表,所有JS接口列表见附录2,
  259. // success: function(res) {
  260. // // 以键值对的形式返回,可用的api值true,不可用为false
  261. // // 如:{"checkResult":{"chooseImage":true},"errMsg":"checkJsApi:ok"}
  262. // console.warn("checkJsApi",res)
  263. // // alert('su'+ JSON.stringify(res))
  264. // },
  265. // fail:(err)=>{
  266. // console.warn("checkJsApi-err",err)
  267. // // alert('err'+ JSON.stringify(err) )
  268. // }
  269. // })
  270. this.screenWidth = window.screen.width;
  271. this.screenHeight = window.screen.height;
  272. if(window.innerWidth && window.screen.width){
  273. this.screenWidth = Math.min(window.innerWidth,window.screen.width)
  274. }
  275. if(window.innerHeight && window.screen.height){
  276. this.screenHeight = Math.min(window.innerHeight,window.screen.height)
  277. }
  278. },
  279. // 页面被展示时执行
  280. onPageShow: function() {
  281. },
  282. //页面被隐藏时执行
  283. onPageHide: function() {
  284. },
  285. beforeDestroy:function(){
  286. console.warn("***beforeDestroy***");//更新到页面上的数据
  287. this.stopInterval();
  288. },
  289. computed: {
  290. aiData() {
  291. return this.$store.state.aiData;
  292. },
  293. curHouseObj() {
  294. return this.$store.state.curHouseObj;
  295. },
  296. },
  297. methods:{
  298. swiperChangeImg(e){
  299. this.currentIndex = e.detail?e.detail.current:e;
  300. this.checked = this.aiImagesList[this.currentIndex].checked;
  301. console.warn("***swiperChangeImg***",this.checked);//更新到页面上的数据
  302. },
  303. //视角切换
  304. switchActor(){
  305. // this.$parent.clearHandle()
  306. this.$emit('switchActor');
  307. this.showAIImage = false;//隐藏AI结果集合-执行切换视角
  308. let index = this.$parent.currentActor.userIndex;//当前视角的序号
  309. let nextIndex = (index + 1) % this.$parent.actors.length;
  310. let param = {
  311. type: 'CLK', //埋点类型
  312. clkId: 'clk_2cmina_23080417', //点击ID
  313. clkName: 'changeangle_clk', //点击前往的页面名称
  314. clkParams: {
  315. locusName: "视角切换",
  316. type:this.$parent.actors[nextIndex].actorEum
  317. }
  318. };
  319. util.trackRequest(param);
  320. },
  321. showOrHideWebGl(){
  322. // this.$parent.clearHandle()
  323. this.showAIImage = !this.showAIImage;
  324. let param = {
  325. type: 'CLK', //埋点类型
  326. clkId: 'clk_2cmina_23080415', //点击ID
  327. clkName: 'contrast_clk', //点击前往的页面名称
  328. clkParams: {
  329. locusName: "对比",
  330. }
  331. };
  332. util.trackRequest(param);
  333. },
  334. //空间或者风格切换
  335. selectAction(selItem,type,index) {
  336. console.log('点击动作111:', selItem,type,index)
  337. var self = this;
  338. if(this.themeIndex == index){
  339. return false
  340. }
  341. this.themeIndex = index;
  342. let param = {
  343. type: 'CLK', //埋点类型
  344. clkId: 'clk_2cmina_23112701', //点击ID
  345. clkName: 'AIstyle_theme_clk', //点击前往的页面名称
  346. clkParams: {
  347. locusName: "AI 主题",
  348. type:this.themeList[this.themeIndex].text
  349. }
  350. };
  351. util.trackRequest(param);
  352. },
  353. //切换模式
  354. changeModel(){
  355. this.modelType = (this.modelType + 1) >2 ? 1 : 2;
  356. },
  357. //保存到相册
  358. save() {
  359. //表示canvas正在绘制,不能进行保存
  360. if (!this.aiImagesList || this.aiImagesList.length==0) {
  361. return false;
  362. }
  363. var _resultImg = this.aiImagesList[this.currentIndex].image;
  364. //正在选择照片,不能生效
  365. if (!_resultImg || _resultImg.length==0) {
  366. this.showToast("请选中图片后再试!");
  367. return false;
  368. }
  369. var para = {
  370. type: 'CLK', //埋点类型
  371. clkId: 'clk_2cmina_56', //点击ID,固定
  372. clkName: "share-savepic", //点击名称
  373. expand: {
  374. "resultImg": (_resultImg || ""),
  375. },
  376. }
  377. util.trackRequest(para);
  378. if(navigator.userAgent.toLocaleLowerCase().includes('micromessenger')){
  379. this.$message("请长按图片保存!");
  380. }else{
  381. this.saveImageHandle(_resultImg);
  382. }
  383. },
  384. downloadIamge(imgsrc) { //下载图片地址和图片名
  385. var fileName = "4DImage" + util.formatDate(new Date(), "yyyyMMddhhmmss") + '.jpg';
  386. const image = new Image();
  387. // 解决跨域 Canvas 污染问题
  388. image.setAttribute("crossOrigin", "anonymous");
  389. image.onload = ()=> {
  390. // let canvas = document.createElement("canvas");
  391. // canvas.width = image.width;
  392. // canvas.height = image.height;
  393. // const context = canvas.getContext("2d");
  394. // context.drawImage(image, 0, 0, image.width, image.height);
  395. // const url = canvas.toDataURL("image/jpg"); //得到图片的base64编码数据
  396. const a = document.createElement("a"); // 生成一个a元素
  397. const event = new MouseEvent("click"); // 创建一个单击事件
  398. a.download = fileName || "photo"; // 设置图片名称
  399. a.href = imgsrc; // 将生成的URL设置为a.href属性
  400. a.dispatchEvent(event); // 触发a的单击事件
  401. this.showToast("保存成功!");
  402. };
  403. image.src = imgsrc;
  404. },
  405. saveImageHandle(_resultImg){
  406. let param = {
  407. type: 'CLK', //埋点类型
  408. clkId: 'clk_2cmina_23080414', //点击ID
  409. clkName: 'download_clk', //点击前往的页面名称
  410. clkParams: {
  411. locusName: "下载",
  412. img:_resultImg
  413. }
  414. };
  415. util.trackRequest(param);
  416. this.downloadIamge(_resultImg);
  417. },
  418. //点赞喜欢
  419. changeAIImg() {
  420. // let lastPage = getCurrentPages()[getCurrentPages().length - 2] ? getCurrentPages()[getCurrentPages().length - 2].$vm : null;
  421. this.checked = !this.checked;//变更选项
  422. this.aiImagesList[this.currentIndex].checked = this.checked;
  423. console.warn("***changeAIImg***",this.checked,this.aiData)
  424. if(this.aiData){//给上一个页面回传生成的数据
  425. let space = this.aiData.find(it=>{
  426. return it.spaceId == this.spaceObj.spaceId
  427. })
  428. if(space){
  429. space.aiImagesList[this.currentIndex].checked = this.checked;
  430. }
  431. }
  432. if(this.checked){
  433. let param = {
  434. type: 'CLK', //埋点类型
  435. clkId: 'clk_2cmina_23080418', //点击ID
  436. clkName: 'chooseprogramme_clk', //点击前往的页面名称
  437. clkParams: {
  438. locusName: "选定风格/视角",
  439. style:this.styleList[this.curStyleIndex].styleName,
  440. img:this.aiImagesList[this.currentIndex].image,
  441. }
  442. };
  443. util.trackRequest(param);
  444. }
  445. },
  446. rightScroll(){//右滑
  447. if(this.currentIndex <= (this.aiImagesList.length - 1) && this.currentIndex > 0){
  448. // this.currentIndex --;
  449. this.$refs.carousel.prev();
  450. }
  451. },
  452. leftScroll(){//继续生成
  453. if(this.currentIndex != this.aiImagesList.length - 1){
  454. if(this.currentIndex<this.aiImagesList.length - 1){
  455. // this.currentIndex ++;
  456. this.$refs.carousel.next();
  457. }
  458. return false;
  459. }
  460. console.log("***leftScroll***",this.currentIndex,this.aiImagesList.length)
  461. this.aiSubmit(2);//继续生成下一张
  462. },
  463. //预览图片-使用微信自带的预览功能,即H5中不可用
  464. previewAction() {
  465. if(wx && typeof(wx.previewImage)=='function'){
  466. let imglist = this.aiImagesList.map(it=>it.image);
  467. wx.previewImage({
  468. current: this.currentIndex,
  469. urls: imglist,
  470. success: (res) => {
  471. console.log('图片预览:', res);
  472. },
  473. fail:(err)=>{
  474. console.warn('图片预览-err:', res);
  475. }
  476. })
  477. }
  478. },
  479. //返回上一页
  480. goback(){
  481. this.$router.go(-1);
  482. },
  483. mynavigateFuc(e) {
  484. if (e) {
  485. // this.$parent.clearHandle();
  486. let param = {
  487. type: 'CLK', //埋点类型
  488. clkId: 'clk_2cmina_23080408', //点击ID
  489. clkName: 'WeCom_clk', //点击前往的页面名称
  490. clkParams: {
  491. locusName: "联系定制",
  492. }
  493. };
  494. util.trackRequest(param);
  495. if(window.__wxjs_environment === 'miniprogram'){
  496. wx.miniProgram.navigateTo({url: '/pages/transfer/transfer?event=openCustomerServiceChat&houseId='+this.$store.state.houseId})
  497. }else{
  498. this.$message.warning("敬请期待");
  499. }
  500. }
  501. },
  502. catchTapEvent:function(){
  503. return false;
  504. },
  505. //获取AI风格列表
  506. async getAiBeautyFamily() {
  507. // const spaceName = this.spaceTypes[this.spaceObj.spaceType - 1].title;
  508. let res = await requestConfig("getHardboundEffects", {
  509. "houseId": this.$route.query.houseId,
  510. "spaceType": this.spaceObj.spaceType,
  511. "spaceName": this.spaceObj.spaceName,
  512. });
  513. this.styleList = [];
  514. if (res.success) {
  515. let list = res.list;
  516. this.styleList = list;
  517. }
  518. if(!this.styleList || this.styleList.length==0){
  519. // this.disableAble = true;//不能点击-没有风格
  520. let unit = this.screenWidth / 750;//单位rpm 对应 px 的值
  521. this.$parent.canvasHeight = this.screenHeight - (208 * unit);
  522. this.$parent.camera.aspect = this.screenWidth / this.$parent.canvasHeight;
  523. this.$parent.camera.updateProjectionMatrix();
  524. this.$parent.renderer.setSize(this.screenWidth, this.$parent.canvasHeight);
  525. }else{
  526. // this.disableAble = false;//可以点击
  527. }
  528. },
  529. //风格选择
  530. selectStyle(idx){
  531. if(this.curStyleIndex == idx){
  532. return false
  533. }
  534. this.curStyleIndex = idx;
  535. let param = {
  536. type: 'CLK', //埋点类型
  537. clkId: 'clk_2cmina_23080416', //点击ID
  538. clkName: 'AIstyle_ret_clk', //点击前往的页面名称
  539. clkParams: {
  540. locusName: "AI 风格",
  541. type:this.styleList[this.curStyleIndex].styleName
  542. }
  543. };
  544. util.trackRequest(param);
  545. },
  546. // AI渲染
  547. async aiSubmit(type) {
  548. if(!this.styleList || this.styleList.length==0 || this.curStyleIndex==-1
  549. || !this.styleList[this.curStyleIndex].prompt || !this.styleList[this.curStyleIndex].negativePrompt){
  550. return false;
  551. }
  552. // 防止连续点击处理
  553. if (this.aiFlag) {
  554. return
  555. }
  556. this.aiFlag = true;
  557. this.aiImage = "";//清空AI结果图
  558. this.stopInterval();
  559. // if(!this.showAIImage){
  560. this.myloading = true;
  561. this.loadingMsg = "启动中";
  562. // }
  563. // this.inputBase64Url = await this.shottingAction(2);//开始截图-返回的是base64的数据
  564. // this.startServer();
  565. // let base64 = await this.$parent.shottingAction(2);//开始截图-返回的是base64
  566. let shottingImg = await this.$parent.shottingAction();//开始截图-返回的是图片地址
  567. if(!shottingImg){
  568. this.showToast("渲染失败,请重试");
  569. return false;
  570. }
  571. // ?x-oss-process=image/auto-orient,1/quality,Q_46/format,jpg //阿里OSS
  572. // "?imageMogr2/auto-orient/format/webp/blur/1x0/quality/75";//七牛云压缩图片
  573. shottingImg += "?x-oss-process=image/auto-orient,1/quality,Q_46/format,jpg";//压缩图片
  574. this.shottingImg = shottingImg;
  575. this.changeImg2Base64(this.shottingImg, false);
  576. console.warn("***shottingImg***",this.shottingImg)
  577. if(type==1){
  578. let param = {
  579. type: 'CLK', //埋点类型
  580. clkId: 'clk_2cmina_23080413', //点击ID
  581. clkName: 'AIcreate_clk', //点击前往的页面名称
  582. clkParams: {
  583. locusName: "AI生成",
  584. userparamter:{
  585. shottingImg:this.shottingImg,
  586. style:this.styleList[this.curStyleIndex].styleName
  587. }
  588. }
  589. };
  590. util.trackRequest(param);
  591. }else{
  592. let param = {
  593. type: 'CLK', //埋点类型
  594. clkId: 'clk_2cmina_23080419', //点击ID
  595. clkName: 'continueAIcreate_clk', //点击前往的页面名称
  596. clkParams: {
  597. locusName: "继续生成",
  598. userparamter:{
  599. shottingImg:this.shottingImg,
  600. style:this.styleList[this.curStyleIndex].styleName
  601. }
  602. }
  603. };
  604. util.trackRequest(param);
  605. }
  606. },
  607. image2Base64(imgUrl) {//导入的图片路径
  608. var toBase64= new Promise(function(resolve, reject){
  609. window.URL = window.URL || window.webkitURL;
  610. var xhr = new XMLHttpRequest();
  611. xhr.open("get", imgUrl, true);
  612. // 至关重要
  613. xhr.responseType = "blob";//文件流
  614. xhr.onload = function (res) {
  615. if (res.currentTarget.status == 200) {
  616. //得到一个blob对象
  617. var blob = res.currentTarget.response;
  618. // 至关重要
  619. let oFileReader = new FileReader();
  620. oFileReader.onloadend = function (e) {
  621. let base64 = e.target.result;//base64
  622. resolve(base64)
  623. };
  624. oFileReader.readAsDataURL(blob);
  625. }
  626. }
  627. xhr.send();
  628. });
  629. return toBase64;
  630. },
  631. changeImg2Base64(url, isRepeat) {
  632. var self = this;
  633. if(isRepeat && self.inputBase64Url){//重复使用
  634. self.startServer();
  635. }else{
  636. self.startServer();
  637. }
  638. },
  639. //前置逻辑
  640. async prevHandle(parmas){
  641. //不是首次请求,则无需前置判断 用户上传的也不需要前置处理
  642. if(this.subType!=0){
  643. return '';
  644. }
  645. return new Promise(async (resolve, reject) => {
  646. let _data = JSON.parse(JSON.stringify(parmas))
  647. delete _data.webhook;
  648. let res = await requestConfig("img2img_local", _data);
  649. if (res.success) {
  650. if (res.success && res.single) {
  651. let resultImg = res.single;
  652. resolve(resultImg);
  653. }else{
  654. resolve('');
  655. }
  656. }else{
  657. resolve('');
  658. }
  659. })
  660. },
  661. //开始图生图流程
  662. async startServer() {
  663. if(!this.styleList || this.curStyleIndex < 0 || !this.styleList[this.curStyleIndex].imgUrl){
  664. return false
  665. }
  666. if(this.$parent.pvCurPageName!="room_show"){//说明用户切换页面了
  667. console.warn("***用户已经退出页面***")
  668. return false;
  669. }
  670. let imgUrl = this.styleList[this.curStyleIndex].imgUrl;
  671. let subType = this.subType;
  672. let session_hash = Date.now();
  673. let theme = this.themeList[this.themeIndex];//主题数据
  674. let prompt = this.styleList[this.curStyleIndex].prompt + theme.prot;
  675. let noPromot = this.styleList[this.curStyleIndex].negativePrompt;
  676. let unit = 768 / this.screenWidth;
  677. this.imageWidth = parseInt((this.screenWidth * unit).toFixed());
  678. this.imageHeight = parseInt((this.$parent.canvasHeight * unit).toFixed());
  679. this.timeOut = this.modelType==1? 20000: 50000;
  680. var parmas = {
  681. negativePrompt: noPromot,
  682. prompt: prompt,
  683. "batchSize": 1,
  684. brandId: $config.brandId,
  685. height: this.imageHeight,
  686. width: this.imageWidth,
  687. "moduleType": "AI_Biography",
  688. "steps":20,
  689. "sampler":"DDIM",
  690. "controlNetSessionHash":session_hash,
  691. "cfgScale":12,
  692. "denoising":0.9,
  693. image:this.shottingImg,
  694. styleImage:imgUrl,
  695. keyword: "replicate",
  696. model: this.modelType==1? "lucataco/ssd-1b" : 'catio-apps/controlnet-interior-design',
  697. };
  698. if(this.modelType==2){//精准设计
  699. if(subType == 0){//首次
  700. parmas.model = this.reqList[0].model;
  701. }else{//重试
  702. parmas.model = this.reqListReset[0].model;
  703. }
  704. }else{//创意设计
  705. if(subType == 0){//首次
  706. parmas.model = "lucataco/ssd-1b";
  707. }else{//重试
  708. parmas.model = "deployments/elabgroup/elab-ssd-1b";
  709. }
  710. }
  711. let result = await this.prevHandle(parmas);
  712. console.warn("***prevHandle***",result)
  713. if(result && result.length>0){
  714. this.randomHandle(result)
  715. return false;
  716. }else{
  717. if(this.modelType==2){//精准设计
  718. this.otherHandle(parmas);//发送其他AI请求
  719. }
  720. let res = await requestConfig("generateTaskImgToImgForAliyun", parmas);
  721. console.log("图生图结果:", res);
  722. let that = this;
  723. if (res.success && res.single) {
  724. this.aiPicId = res.single;
  725. if(this.modelType==2){//精准设计
  726. if(subType == 0){//首次
  727. this.reqList[0].aiPicId = this.aiPicId;
  728. }else{//重试
  729. this.reqListReset[0].aiPicId = this.aiPicId;
  730. }
  731. }
  732. if (this.aiPicId) {
  733. this.startInterval();//开始轮询AI生成图的结果
  734. }else{
  735. this.stopInterval()
  736. }
  737. }else{
  738. this.stopInterval()
  739. this.showToast("渲染失败,请重试")
  740. }
  741. }
  742. },
  743. stopInterval() {
  744. if (this.randomTimer) {
  745. clearInterval(this.randomTimer);
  746. this.randomTimer = null;
  747. }
  748. if (this.timer) {
  749. // clearInterval(this.timer);
  750. this.timer = null;
  751. }
  752. if (this.outTimer) {
  753. clearTimeout(this.outTimer)
  754. this.outTimer = null
  755. }
  756. this.subType = 0;
  757. this.reqList.forEach(it=>{
  758. it.aiPicId = '';
  759. it.resultImg = '';
  760. })
  761. this.reqListReset.forEach(it=>{
  762. it.aiPicId = '';
  763. it.resultImg = '';
  764. })
  765. // this.random = 1;
  766. this.myloading = false;
  767. this.aiFlag = false;
  768. },
  769. //随机处理
  770. randomHandle(resultImg){
  771. if(this.timer || !resultImg){
  772. return false;
  773. }
  774. let self = this;
  775. var count = 1;
  776. var process = 0;//进度
  777. var randomNum = Math.floor(Math.random() * 4 + 5);//5-8随机数
  778. this.randomTimer = setInterval(function() {
  779. process = parseInt(count * 100/(randomNum));
  780. if(process>=100){
  781. process = 99;
  782. }
  783. if (count < randomNum) {//没有到上限
  784. // if(!self.showAIImage){
  785. self.myloading = true;
  786. self.loadingMsg = '生成中…' + process + '%';
  787. // }
  788. }else{
  789. self.myloading = false;
  790. self.resultHandle(resultImg);
  791. }
  792. count = count + 1;
  793. }, 1000);
  794. },
  795. otherHandle(parmas){
  796. let reqList = [];
  797. if(this.subType == 0){//首次
  798. reqList = this.reqList;
  799. }else{//重试
  800. reqList = this.reqListReset;
  801. }
  802. reqList.forEach(async (it,index)=>{
  803. let _data = JSON.parse(JSON.stringify(parmas));
  804. if(index>0){
  805. _data.model = it.model;
  806. let res = await requestConfig("generateTaskImgToImgForAliyun", _data);
  807. if (res.success) {
  808. console.log('生成结果123:', res);
  809. it.aiPicId = res.single || '';
  810. }
  811. }
  812. })
  813. },
  814. //开始生成AI图的轮询,每隔1s轮询一次
  815. startInterval() {
  816. if(this.timer){
  817. return false;
  818. }
  819. let self = this;
  820. this.count = 1;//轮询次数
  821. var random = 0;
  822. this.currentImg = false;//当次生成图还没有结果
  823. this.timer = 1;
  824. this.getOutPicture();//不在轮询,而是等结果
  825. this.setOutTimer();//设置超时逻辑
  826. },
  827. //设置一个超时逻辑,到底指定时间后停止轮询,当前是90s
  828. setOutTimer() {
  829. if (this.outTimer) {
  830. clearTimeout(this.outTimer)
  831. this.outTimer = null
  832. }
  833. var self = this;
  834. this.outTimer = setTimeout(function() {
  835. if (self.timer) {
  836. let hasResult = false;
  837. if(self.modelType==2){//精准设计
  838. let reqList = [];
  839. if(self.subType == 0){//首次
  840. reqList = self.reqList;
  841. }else{//重试
  842. reqList = self.reqListReset;
  843. }
  844. reqList.some((item,index) => {
  845. if(item.resultImg){
  846. hasResult = true;
  847. self.resultHandle(item.resultImg)
  848. }
  849. });
  850. }
  851. console.warn("***hasResult***",hasResult)
  852. if(!hasResult){//没有结果
  853. self.stopInterval();//停止轮询
  854. // self.$message.warning("AI开了个小差,请稍后再试");
  855. // self.dialogVisible = true;//弹出超时提示
  856. MessageBox.confirm('',{
  857. title: '提示',
  858. message: '当前AI使用火爆,请继续尝试?',
  859. showCancelButton: true,
  860. confirmButtonText:'继续尝试',
  861. cancelButtonText:'取消等待',
  862. }).then(action => {
  863. console.warn("***MessageBox-action***",action)
  864. if(action == 'confirm'){
  865. self.confirmHandle(1);
  866. }
  867. }).catch(err=>{
  868. console.warn("***MessageBox-err***",err)
  869. if(err == 'cancel'){
  870. self.cancelHandle();
  871. }
  872. });
  873. // MessageBox.confirm('确定执行此操作?')
  874. }
  875. }
  876. clearTimeout(self.outTimer);
  877. self.outTimer = null
  878. }, this.timeOut);
  879. },
  880. confirmHandle(type){
  881. console.log('用户点击确定')
  882. this.dialogVisible = false;
  883. this.dialogAIVisible = false;
  884. this.subType = type || 0;
  885. this.startServer();
  886. },
  887. cancelHandle(){
  888. console.log('用户点击取消')
  889. this.dialogVisible = false;
  890. this.dialogAIVisible = false;
  891. this.subType = 0;
  892. },
  893. //获取生成图结果
  894. getOutPicture() {
  895. if(this.timer==null){
  896. console.warn("***当前轮询已经结束了1***")
  897. return false;
  898. }
  899. if(this.modelType==2){//精准设计
  900. let reqList = [];
  901. if(this.subType == 0){//首次
  902. reqList = this.reqList;
  903. }else{//重试
  904. reqList = this.reqListReset;
  905. }
  906. reqList.forEach((item,index) => {
  907. this.singleHandle(item)
  908. });
  909. }
  910. else{
  911. this.singleHandle({aiPicId:this.aiPicId})
  912. }
  913. },
  914. //发出获取结果请求获取AI生成结果
  915. async singleHandle(model){
  916. if(!model || !model.aiPicId){
  917. return false;
  918. }
  919. var parmas = {
  920. id: model.aiPicId,
  921. };
  922. let res = await requestConfig("getPredictions", parmas);
  923. if (res.success && res.single) {
  924. if(this.currentImg){//当前已经有生成图了
  925. console.warn("***当前已经有最高级生成图了***")
  926. return false;
  927. }
  928. if(this.timer==null){
  929. console.warn("***当前轮询已经结束了***")
  930. return false;
  931. }
  932. if (res.single.status == 'succeeded' && res.single.output) {
  933. if(this.modelType==2){//精准设计
  934. model.resultImg = res.single.output;
  935. if(model.level=='5'){//最高级了
  936. this.currentImg = true;
  937. setTimeout(()=>{
  938. this.resultHandle(res.single.output)
  939. },1500)
  940. }
  941. }else{
  942. this.currentImg = true;
  943. setTimeout(()=>{
  944. this.resultHandle(res.single.output)
  945. },1500)
  946. }
  947. console.warn("***有生成图了***",model)
  948. }
  949. if(this.modelType==2){//最高优先级返回没有图片,则处理进度条事宜
  950. if(model.level=='5'){
  951. this.processHandle(res.single);
  952. }
  953. }else{//普通设计
  954. this.processHandle(res.single);
  955. }
  956. } else if (!res.success) {
  957. this.stopInterval();//停止轮询
  958. this.showToast("渲染失败,请重试")
  959. }
  960. },
  961. //进度处理
  962. processHandle(single){
  963. console.warn("***single***",single.status,single.progress,this.count,single);
  964. let self = this;
  965. if(single.status=='starting'){//启动中的逻辑
  966. if(this.count>=20){
  967. this.stopInterval();//停止轮询
  968. // this.dialogAIVisible = true;
  969. MessageBox.confirm('',{
  970. title: '提示',
  971. message: 'AI开了小差,是否重新生成?',
  972. showCancelButton: true,
  973. confirmButtonText:'继续生成',
  974. cancelButtonText:'放弃生成',
  975. }).then(action => {
  976. console.warn("***MessageBox-action***",action)
  977. if(action == 'confirm'){
  978. this.confirmHandle(0);
  979. }
  980. }).catch(err=>{
  981. if(err == 'cancel'){
  982. this.cancelHandle();
  983. }
  984. });
  985. }else{
  986. this.myloading = true;
  987. this.loadingMsg = '启动中';
  988. }
  989. this.count = this.count + 1;
  990. this.getOutPicture();
  991. }else if(single.status=='processing'){
  992. let random = single.progress || 0;
  993. if(random >= 100){
  994. random = 99;
  995. }
  996. // uni.showLoading({
  997. // icon: 'loading',
  998. // title: '生成中…' + parseInt(random) + '%'
  999. // })
  1000. // if(!this.showAIImage){
  1001. this.myloading = true;
  1002. this.loadingMsg = '生成中…' + parseInt(random) + '%';
  1003. // }
  1004. this.getOutPicture();
  1005. }else if(single.status=='succeeded'){
  1006. // uni.showLoading({
  1007. // icon: 'loading',
  1008. // title: '生成中…100%',
  1009. // duration:2000,
  1010. // })
  1011. // if(!this.showAIImage){
  1012. this.myloading = true;
  1013. this.loadingMsg = '生成中…100%';
  1014. // }
  1015. }
  1016. },
  1017. //返回结果处理
  1018. resultHandle(resultImg){
  1019. this.currentImg = true;
  1020. // this.random = 100;
  1021. this.aiImage = resultImg;
  1022. this.showAIFlag = true;
  1023. let newImage = resultImg;
  1024. let aiStyleName = this.styleList[this.curStyleIndex].styleName;
  1025. let _data = {
  1026. image:newImage,
  1027. checked:false,
  1028. list:[newImage],
  1029. }
  1030. this.aiImagesList.push(_data);
  1031. this.showAIImage = true;//显示AI结果集合-因为生成了AI图片
  1032. if(this.$parent && typeof(this.$parent.clearHandle)=="function" ){
  1033. this.$parent.clearHandle();
  1034. }
  1035. let cpAiData = JSON.parse(JSON.stringify(this.aiData)) || []
  1036. if(cpAiData && this.curHouseObj && this.curHouseObj.houseFloor){//给上一个页面回传生成的数据
  1037. let space = cpAiData.find(it=>{
  1038. return it.houseFloor == this.curHouseObj.houseFloor && it.spaceId == this.spaceObj.spaceId
  1039. })
  1040. if(space){
  1041. let data ={
  1042. aiStyleName:aiStyleName,
  1043. image:newImage,
  1044. checked:false,
  1045. }
  1046. space.aiImagesList.push(data);
  1047. }else{//不存在则构建数据
  1048. let data = {
  1049. houseFloor:this.curHouseObj.houseFloor,//当前的楼层
  1050. spaceId:this.spaceObj.spaceId,
  1051. aiImagesList:[
  1052. {
  1053. aiStyleName:aiStyleName,
  1054. image:newImage,
  1055. checked:false,
  1056. }
  1057. ]
  1058. }
  1059. cpAiData.push(data)
  1060. }
  1061. this.$store.dispatch('setAiData', cpAiData)
  1062. }
  1063. this.stopInterval();
  1064. if(this.aiImagesList.length>1){
  1065. setTimeout(()=>{
  1066. // this.$refs.carousel.next();
  1067. this.$refs.carousel.setActiveItem(this.aiImagesList.length-1);//切换到最后一张
  1068. }, 1000);
  1069. }
  1070. },
  1071. showToast(title,time=3000){
  1072. this.myloading = false;
  1073. this.$store.state.loading = true;
  1074. this.$store.state.loadingMsg = title || "";
  1075. setTimeout(()=>{
  1076. this.$store.state.loading = false;
  1077. }, time);
  1078. }
  1079. }
  1080. }
  1081. </script>
  1082. <style lang="scss" scoped>
  1083. @import "./viewMask.scss";
  1084. </style>
  1085. <style lang="css" scoped>
  1086. /* @import "@/common/css/common.css"; */
  1087. </style>