viewMask.vue 32 KB

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