viewMask.vue 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167
  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. spaceList:[],
  166. spaceObj:null,
  167. }
  168. },
  169. props:{
  170. // layoutList:{
  171. // type: [Array ,Object],
  172. // default: [],
  173. // }
  174. },
  175. computed:{
  176. curSpaceId() {
  177. return this.$store.state.curSpaceId;
  178. },
  179. curHouseObj() {
  180. return this.$store.state.curHouseObj;
  181. },
  182. arrFrunList() {
  183. return webglCom.arrFrunList;
  184. },
  185. aiData() {
  186. return this.$store.state.aiData;
  187. },
  188. userId() {
  189. return this.$store.state.userId;
  190. },
  191. },
  192. watch: {
  193. curHouseObj: {
  194. handler(newVal,oldVal) {
  195. console.warn("***curHouseObj-CHANGE-viewMask***", newVal)
  196. if (newVal) {
  197. this.initData(newVal);
  198. }
  199. },
  200. immediate: true
  201. },
  202. curSpaceId: {
  203. handler(newVal,oldVal) {
  204. if (newVal) {
  205. console.warn("***curSpaceId-CHANGE-viewMask***", newVal,oldVal,this.spaceList)
  206. if(!this.spaceList){
  207. this.initData(webglCom.curHouseObj,newVal);
  208. }else{
  209. const spaceDetail = this.spaceList.find(it=>it.spaceId == newVal);
  210. this.spaceObj = spaceDetail;
  211. this.getAiBeautyFamily();
  212. }
  213. }
  214. },
  215. immediate: true
  216. },
  217. arrFrunList: {
  218. handler(newVal,oldVal) {
  219. console.warn("***arrFrunList-CHANGE-viewMask***", newVal,oldVal)
  220. if (newVal == null) {
  221. return;
  222. }
  223. this.updataLable();
  224. },
  225. immediate: true
  226. },
  227. },
  228. filters:{
  229. // spaceTypeFilter(type){
  230. // let name = spaceTypes[type - 1];
  231. // return name || '-'
  232. // },
  233. },
  234. mounted() {//组件挂载时事件
  235. this.screenWidth = window.screen.width;
  236. this.screenHeight = window.screen.height;
  237. if(window.innerWidth && window.screen.width){
  238. this.screenWidth = Math.min(window.innerWidth,window.screen.width)
  239. }
  240. if(window.innerHeight && window.screen.height){
  241. this.screenHeight = Math.min(window.innerHeight,window.screen.height)
  242. }
  243. },
  244. beforeDestroy:function(){
  245. console.warn("***beforeDestroy***");//更新到页面上的数据
  246. this.stopInterval();
  247. },
  248. methods:{
  249. initData(data,spaceId=''){
  250. let spaceDetail = data || webglCom.curHouseObj;
  251. let spaceList = typeof(spaceDetail.houseJson)=="string" ? JSON.parse(spaceDetail.houseJson) : spaceDetail.houseJson;
  252. this.spaceList = spaceList;
  253. this.datalist = [];
  254. spaceList.forEach(it=>{
  255. if(it.spaceName && !it.isSizeLock){
  256. this.datalist.push(it);
  257. }
  258. })
  259. if(spaceId){
  260. this.spaceObj = this.spaceList.find(it=>it.spaceId == spaceId);
  261. this.getAiBeautyFamily();
  262. }
  263. },
  264. //更改空间显示名称 X空间 类型 根据布局所属类型来显示
  265. updataLable(){
  266. let list = this.arrFrunList;
  267. this.datalist.forEach(lable=>{
  268. if(lable.spaceType==15){
  269. let layoutId = lable.layoutId;
  270. let layout = list.find(it=>it.id == layoutId);
  271. if(layout){
  272. let name = spaceTypes[layout.type - 1];
  273. lable.text = name;
  274. }
  275. }else{
  276. let name = spaceTypes[lable.spaceType - 1];
  277. lable.text = name;
  278. }
  279. })
  280. this.$forceUpdate()
  281. console.warn("***updataLable***",this.datalist)
  282. },
  283. swiperChangeImg(e){
  284. this.currentIndex = e.detail?e.detail.current:e;
  285. this.checked = this.aiImagesList[this.currentIndex].checked;
  286. console.warn("***swiperChangeImg***",this.checked);//更新到页面上的数据
  287. },
  288. //切换空间
  289. changeSpace(item){
  290. if(item.spaceId == this.spaceObj.spaceId){
  291. return false
  292. }
  293. webglCom.changeSpace(item.spaceId);
  294. this.spaceObj = item;
  295. this.getAiBeautyFamily()
  296. let param = {
  297. type: 'CLK', //埋点类型
  298. clkId: 'clk_2cmina_23080417', //点击ID
  299. clkName: 'changeangle_clk', //点击前往的页面名称
  300. clkParams: {
  301. locusName: "空间切换",
  302. locusValue:item.text,
  303. spaceId:item.spaceId,
  304. type:item.text,
  305. }
  306. };
  307. util.trackRequest(param);
  308. },
  309. showOrHideWebGl(){
  310. this.showAIImage = !this.showAIImage;
  311. let param = {
  312. type: 'CLK', //埋点类型
  313. clkId: 'clk_2cmina_23080415', //点击ID
  314. clkName: 'contrast_clk', //点击前往的页面名称
  315. clkParams: {
  316. locusName: "对比",
  317. }
  318. };
  319. util.trackRequest(param);
  320. },
  321. //空间或者风格切换
  322. selectAction(selItem,type,index) {
  323. console.log('点击动作111:', selItem,type,index)
  324. var self = this;
  325. if(this.themeIndex == index){
  326. return false
  327. }
  328. this.themeIndex = index;
  329. let param = {
  330. type: 'CLK', //埋点类型
  331. clkId: 'clk_2cmina_23112701', //点击ID
  332. clkName: 'AIstyle_theme_clk', //点击前往的页面名称
  333. clkParams: {
  334. locusName: "AI 主题",
  335. type:this.themeList[this.themeIndex].text
  336. }
  337. };
  338. util.trackRequest(param);
  339. },
  340. //切换模式
  341. changeModel(){
  342. this.modelType = (this.modelType + 1) >2 ? 1 : 2;
  343. },
  344. //保存到相册
  345. save() {
  346. //表示canvas正在绘制,不能进行保存
  347. if (!this.aiImagesList || this.aiImagesList.length==0) {
  348. return false;
  349. }
  350. var _resultImg = this.aiImagesList[this.currentIndex].image;
  351. //正在选择照片,不能生效
  352. if (!_resultImg || _resultImg.length==0) {
  353. this.showToast("请选中图片后再试!");
  354. return false;
  355. }
  356. var para = {
  357. type: 'CLK', //埋点类型
  358. clkId: 'clk_2cmina_56', //点击ID,固定
  359. clkName: "share-savepic", //点击名称
  360. expand: {
  361. "resultImg": (_resultImg || ""),
  362. },
  363. }
  364. util.trackRequest(para);
  365. if(navigator.userAgent.toLocaleLowerCase().includes('micromessenger')){
  366. this.$message("请长按图片保存!");
  367. }else{
  368. this.saveImageHandle(_resultImg);
  369. }
  370. },
  371. downloadIamge(imgsrc) { //下载图片地址和图片名
  372. var fileName = "4DImage" + util.formatDate(new Date(), "yyyyMMddhhmmss") + '.jpg';
  373. const image = new Image();
  374. // 解决跨域 Canvas 污染问题
  375. image.setAttribute("crossOrigin", "anonymous");
  376. image.onload = ()=> {
  377. // let canvas = document.createElement("canvas");
  378. // canvas.width = image.width;
  379. // canvas.height = image.height;
  380. // const context = canvas.getContext("2d");
  381. // context.drawImage(image, 0, 0, image.width, image.height);
  382. // const url = canvas.toDataURL("image/jpg"); //得到图片的base64编码数据
  383. const a = document.createElement("a"); // 生成一个a元素
  384. const event = new MouseEvent("click"); // 创建一个单击事件
  385. a.download = fileName || "photo"; // 设置图片名称
  386. a.href = imgsrc; // 将生成的URL设置为a.href属性
  387. a.dispatchEvent(event); // 触发a的单击事件
  388. this.showToast("保存成功!");
  389. };
  390. image.src = imgsrc;
  391. },
  392. saveImageHandle(_resultImg){
  393. let param = {
  394. type: 'CLK', //埋点类型
  395. clkId: 'clk_2cmina_23080414', //点击ID
  396. clkName: 'download_clk', //点击前往的页面名称
  397. clkParams: {
  398. locusName: "下载",
  399. img:_resultImg
  400. }
  401. };
  402. util.trackRequest(param);
  403. this.downloadIamge(_resultImg);
  404. },
  405. //点赞喜欢
  406. changeAIImg() {
  407. // let lastPage = getCurrentPages()[getCurrentPages().length - 2] ? getCurrentPages()[getCurrentPages().length - 2].$vm : null;
  408. this.checked = !this.checked;//变更选项
  409. this.aiImagesList[this.currentIndex].checked = this.checked;
  410. console.warn("***changeAIImg***",this.checked,this.aiData)
  411. if(this.aiData){//给上一个页面回传生成的数据
  412. let space = this.aiData.find(it=>{
  413. return it.spaceId == this.spaceObj.spaceId
  414. })
  415. if(space){
  416. let cind = space.aiImagesList.find(it=>it.image == this.aiImagesList[this.currentIndex].image)
  417. if(cind){
  418. cind.checked = this.checked;
  419. }
  420. }
  421. }
  422. if(this.checked){
  423. let param = {
  424. type: 'CLK', //埋点类型
  425. clkId: 'clk_2cmina_23080418', //点击ID
  426. clkName: 'chooseprogramme_clk', //点击前往的页面名称
  427. clkParams: {
  428. locusName: "选定风格/视角",
  429. style:this.styleList[this.curStyleIndex].styleName,
  430. img:this.aiImagesList[this.currentIndex].image,
  431. }
  432. };
  433. util.trackRequest(param);
  434. }
  435. },
  436. rightScroll(){//右滑
  437. if(this.currentIndex <= (this.aiImagesList.length - 1) && this.currentIndex > 0){
  438. // this.currentIndex --;
  439. this.$refs.carousel.prev();
  440. }
  441. },
  442. leftScroll(){//继续生成
  443. if(this.currentIndex != this.aiImagesList.length - 1){
  444. if(this.currentIndex<this.aiImagesList.length - 1){
  445. // this.currentIndex ++;
  446. this.$refs.carousel.next();
  447. }
  448. return false;
  449. }
  450. console.log("***leftScroll***",this.currentIndex,this.aiImagesList.length)
  451. this.aiSubmit(2);//继续生成下一张
  452. },
  453. //预览图片-使用微信自带的预览功能,即H5中不可用
  454. previewAction() {
  455. if(wx && typeof(wx.previewImage)=='function'){
  456. let imglist = this.aiImagesList.map(it=>it.image);
  457. wx.previewImage({
  458. current: this.currentIndex,
  459. urls: imglist,
  460. success: (res) => {
  461. console.log('图片预览:', res);
  462. },
  463. fail:(err)=>{
  464. console.warn('图片预览-err:', res);
  465. }
  466. })
  467. }
  468. },
  469. mynavigateFuc(e) {
  470. if (e) {
  471. let param = {
  472. type: 'CLK', //埋点类型
  473. clkId: 'clk_2cmina_23080408', //点击ID
  474. clkName: 'WeCom_clk', //点击前往的页面名称
  475. clkParams: {
  476. locusName: "联系定制",
  477. }
  478. };
  479. util.trackRequest(param);
  480. if(window.__wxjs_environment === 'miniprogram'){
  481. wx.miniProgram.navigateTo({url: '/pages/transfer/transfer?event=openCustomerServiceChat&houseId='+this.$store.state.houseId})
  482. }else{
  483. this.$message.warning("敬请期待");
  484. }
  485. }
  486. },
  487. catchTapEvent:function(){
  488. return false;
  489. },
  490. //获取AI风格列表
  491. async getAiBeautyFamily() {
  492. // const spaceName = this.spaceTypes[this.spaceObj.spaceType - 1].title;
  493. let res = await requestConfig("getHardboundEffects", {
  494. "houseId": this.$route.query.houseId || this.$store.state.houseId,
  495. "spaceType": this.spaceObj.layoutSpaceType || this.spaceObj.spaceType,
  496. "spaceName": this.spaceObj.layoutSpaceName || this.spaceObj.spaceName,
  497. });
  498. this.styleList = [];
  499. // alert("***getAiBeautyFamily-res***"+JSON.stringify(res))
  500. if (res.success) {
  501. let list = res.list;
  502. this.styleList = list;
  503. }
  504. },
  505. //风格选择
  506. selectStyle(idx){
  507. if(this.curStyleIndex == idx){
  508. return false
  509. }
  510. this.curStyleIndex = idx;
  511. let param = {
  512. type: 'CLK', //埋点类型
  513. clkId: 'clk_2cmina_23080416', //点击ID
  514. clkName: 'AIstyle_ret_clk', //点击前往的页面名称
  515. clkParams: {
  516. locusName: "AI 风格",
  517. type:this.styleList[this.curStyleIndex].styleName
  518. }
  519. };
  520. util.trackRequest(param);
  521. },
  522. // AI渲染
  523. async aiSubmit(type) {
  524. if(!this.styleList || this.styleList.length==0 || this.curStyleIndex==-1
  525. || !this.styleList[this.curStyleIndex].prompt || !this.styleList[this.curStyleIndex].negativePrompt){
  526. return false;
  527. }
  528. // 防止连续点击处理
  529. if (this.aiFlag) {
  530. return
  531. }
  532. this.aiFlag = true;
  533. this.aiImage = "";//清空AI结果图
  534. this.stopInterval();
  535. this.myloading = true;
  536. this.loadingMsg = "启动中";
  537. let shottingImg = await webglCom.creatShotImg();//开始截图-返回的是图片地址
  538. if(!shottingImg){
  539. this.showToast("渲染失败,请重试");
  540. return false;
  541. }
  542. // ?x-oss-process=image/auto-orient,1/quality,Q_46/format,jpg //阿里OSS
  543. // "?imageMogr2/auto-orient/format/webp/blur/1x0/quality/75";//七牛云压缩图片
  544. // shottingImg += "?x-oss-process=image/auto-orient,1/quality,Q_46/format,jpg";//压缩图片
  545. this.shottingImg = shottingImg;
  546. this.changeImg2Base64(this.shottingImg, false);
  547. console.warn("***shottingImg***",this.shottingImg)
  548. if(type==1){
  549. let param = {
  550. type: 'CLK', //埋点类型
  551. clkId: 'clk_2cmina_23080413', //点击ID
  552. clkName: 'AIcreate_clk', //点击前往的页面名称
  553. clkParams: {
  554. locusName: "AI生成",
  555. userparamter:{
  556. shottingImg:this.shottingImg,
  557. style:this.styleList[this.curStyleIndex].styleName
  558. }
  559. }
  560. };
  561. util.trackRequest(param);
  562. }else{
  563. let param = {
  564. type: 'CLK', //埋点类型
  565. clkId: 'clk_2cmina_23080419', //点击ID
  566. clkName: 'continueAIcreate_clk', //点击前往的页面名称
  567. clkParams: {
  568. locusName: "继续生成",
  569. userparamter:{
  570. shottingImg:this.shottingImg,
  571. style:this.styleList[this.curStyleIndex].styleName
  572. }
  573. }
  574. };
  575. util.trackRequest(param);
  576. }
  577. },
  578. changeImg2Base64(url, isRepeat) {
  579. var self = this;
  580. if(isRepeat && self.inputBase64Url){//重复使用
  581. self.startServer();
  582. }else{
  583. self.startServer();
  584. }
  585. },
  586. //前置逻辑
  587. async prevHandle(parmas){
  588. //不是首次请求,则无需前置判断 用户上传的也不需要前置处理
  589. if(this.subType!=0){
  590. return '';
  591. }
  592. return new Promise(async (resolve, reject) => {
  593. let _data = JSON.parse(JSON.stringify(parmas))
  594. delete _data.webhook;
  595. let res = await requestConfig("img2img_local", _data);
  596. if (res.success) {
  597. if (res.success && res.single) {
  598. let resultImg = res.single;
  599. resolve(resultImg);
  600. }else{
  601. resolve('');
  602. }
  603. }else{
  604. resolve('');
  605. }
  606. })
  607. },
  608. //开始图生图流程
  609. async startServer() {
  610. if(!this.styleList || this.curStyleIndex < 0 || !this.styleList[this.curStyleIndex].imgUrl){
  611. return false
  612. }
  613. if(this.$parent.pvCurPageName!="room_show"){//说明用户切换页面了
  614. console.warn("***用户已经退出页面***")
  615. return false;
  616. }
  617. let imgUrl = this.styleList[this.curStyleIndex].imgUrl;
  618. let subType = this.subType;
  619. let session_hash = Date.now();
  620. let theme = this.themeList[this.themeIndex];//主题数据
  621. let prompt = this.styleList[this.curStyleIndex].prompt + theme.prot;
  622. let noPromot = this.styleList[this.curStyleIndex].negativePrompt;
  623. let unit = 768 / this.screenWidth;
  624. this.imageWidth = parseInt((this.screenWidth * unit).toFixed());
  625. this.imageHeight = parseInt((this.$parent.canvasHeight * unit).toFixed());
  626. this.timeOut = this.modelType==1? 20000: 50000;
  627. var parmas = {
  628. negativePrompt: noPromot,
  629. prompt: prompt,
  630. "batchSize": 1,
  631. brandId: $config.brandId,
  632. height: this.imageHeight,
  633. width: this.imageWidth,
  634. "moduleType": "AI_Biography",
  635. "steps":20,
  636. "sampler":"DDIM",
  637. "controlNetSessionHash":session_hash,
  638. "cfgScale":12,
  639. "denoising":0.9,
  640. image:this.shottingImg,
  641. styleImage:imgUrl,
  642. keyword: "replicate",
  643. model: this.modelType==1? "lucataco/ssd-1b" : 'catio-apps/controlnet-interior-design',
  644. };
  645. if(this.modelType==2){//精准设计
  646. if(subType == 0){//首次
  647. parmas.model = this.reqList[0].model;
  648. }else{//重试
  649. parmas.model = this.reqListReset[0].model;
  650. }
  651. }else{//创意设计
  652. if(subType == 0){//首次
  653. parmas.model = "lucataco/ssd-1b";
  654. }else{//重试
  655. parmas.model = "deployments/elabgroup/elab-ssd-1b";
  656. }
  657. }
  658. let result = await this.prevHandle(parmas);
  659. console.warn("***prevHandle***",result)
  660. if(result && result.length>0){
  661. this.randomHandle(result)
  662. return false;
  663. }else{
  664. if(this.modelType==2){//精准设计
  665. this.otherHandle(parmas);//发送其他AI请求
  666. }
  667. let res = await requestConfig("generateTaskImgToImgForAliyun", parmas);
  668. console.log("图生图结果:", res);
  669. let that = this;
  670. if (res.success && res.single) {
  671. this.aiPicId = res.single;
  672. if(this.modelType==2){//精准设计
  673. if(subType == 0){//首次
  674. this.reqList[0].aiPicId = this.aiPicId;
  675. }else{//重试
  676. this.reqListReset[0].aiPicId = this.aiPicId;
  677. }
  678. }
  679. if (this.aiPicId) {
  680. this.startInterval();//开始轮询AI生成图的结果
  681. }else{
  682. this.stopInterval()
  683. }
  684. }else{
  685. this.stopInterval()
  686. this.showToast("渲染失败,请重试")
  687. }
  688. }
  689. },
  690. stopInterval() {
  691. if (this.randomTimer) {
  692. clearInterval(this.randomTimer);
  693. this.randomTimer = null;
  694. }
  695. if (this.timer) {
  696. // clearInterval(this.timer);
  697. this.timer = null;
  698. }
  699. if (this.outTimer) {
  700. clearTimeout(this.outTimer)
  701. this.outTimer = null
  702. }
  703. this.subType = 0;
  704. this.reqList.forEach(it=>{
  705. it.aiPicId = '';
  706. it.resultImg = '';
  707. })
  708. this.reqListReset.forEach(it=>{
  709. it.aiPicId = '';
  710. it.resultImg = '';
  711. })
  712. // this.random = 1;
  713. this.myloading = false;
  714. this.aiFlag = false;
  715. },
  716. //随机处理
  717. randomHandle(resultImg){
  718. if(this.timer || !resultImg){
  719. return false;
  720. }
  721. let self = this;
  722. var count = 1;
  723. var process = 0;//进度
  724. var randomNum = Math.floor(Math.random() * 4 + 5);//5-8随机数
  725. this.randomTimer = setInterval(function() {
  726. process = parseInt(count * 100/(randomNum));
  727. if(process>=100){
  728. process = 99;
  729. }
  730. if (count < randomNum) {//没有到上限
  731. // if(!self.showAIImage){
  732. self.myloading = true;
  733. self.loadingMsg = '生成中…' + process + '%';
  734. // }
  735. }else{
  736. self.myloading = false;
  737. self.resultHandle(resultImg);
  738. }
  739. count = count + 1;
  740. }, 1000);
  741. },
  742. otherHandle(parmas){
  743. let reqList = [];
  744. if(this.subType == 0){//首次
  745. reqList = this.reqList;
  746. }else{//重试
  747. reqList = this.reqListReset;
  748. }
  749. reqList.forEach(async (it,index)=>{
  750. let _data = JSON.parse(JSON.stringify(parmas));
  751. if(index>0){
  752. _data.model = it.model;
  753. let res = await requestConfig("generateTaskImgToImgForAliyun", _data);
  754. if (res.success) {
  755. console.log('生成结果123:', res);
  756. it.aiPicId = res.single || '';
  757. }
  758. }
  759. })
  760. },
  761. //开始生成AI图的轮询,每隔1s轮询一次
  762. startInterval() {
  763. if(this.timer){
  764. return false;
  765. }
  766. let self = this;
  767. this.count = 1;//轮询次数
  768. var random = 0;
  769. this.currentImg = false;//当次生成图还没有结果
  770. this.timer = 1;
  771. this.getOutPicture();//不在轮询,而是等结果
  772. this.setOutTimer();//设置超时逻辑
  773. },
  774. //设置一个超时逻辑,到底指定时间后停止轮询,当前是90s
  775. setOutTimer() {
  776. if (this.outTimer) {
  777. clearTimeout(this.outTimer)
  778. this.outTimer = null
  779. }
  780. var self = this;
  781. this.outTimer = setTimeout(function() {
  782. if (self.timer) {
  783. let hasResult = false;
  784. if(self.modelType==2){//精准设计
  785. let reqList = [];
  786. if(self.subType == 0){//首次
  787. reqList = self.reqList;
  788. }else{//重试
  789. reqList = self.reqListReset;
  790. }
  791. reqList.some((item,index) => {
  792. if(item.resultImg){
  793. hasResult = true;
  794. self.resultHandle(item.resultImg)
  795. }
  796. });
  797. }
  798. console.warn("***hasResult***",hasResult)
  799. if(!hasResult){//没有结果
  800. self.stopInterval();//停止轮询
  801. // self.$message.warning("AI开了个小差,请稍后再试");
  802. // self.dialogVisible = true;//弹出超时提示
  803. MessageBox.confirm('',{
  804. title: '提示',
  805. message: '当前AI使用火爆,请继续尝试?',
  806. showCancelButton: true,
  807. confirmButtonText:'继续尝试',
  808. cancelButtonText:'取消等待',
  809. }).then(action => {
  810. console.warn("***MessageBox-action***",action)
  811. if(action == 'confirm'){
  812. self.confirmHandle(1);
  813. }
  814. }).catch(err=>{
  815. console.warn("***MessageBox-err***",err)
  816. if(err == 'cancel'){
  817. self.cancelHandle();
  818. }
  819. });
  820. // MessageBox.confirm('确定执行此操作?')
  821. }
  822. }
  823. clearTimeout(self.outTimer);
  824. self.outTimer = null
  825. }, this.timeOut);
  826. },
  827. confirmHandle(type){
  828. console.log('用户点击确定')
  829. this.subType = type || 0;
  830. this.startServer();
  831. },
  832. cancelHandle(){
  833. console.log('用户点击取消')
  834. this.subType = 0;
  835. },
  836. //获取生成图结果
  837. getOutPicture() {
  838. if(this.timer==null){
  839. console.warn("***当前轮询已经结束了1***")
  840. return false;
  841. }
  842. if(this.modelType==2){//精准设计
  843. let reqList = [];
  844. if(this.subType == 0){//首次
  845. reqList = this.reqList;
  846. }else{//重试
  847. reqList = this.reqListReset;
  848. }
  849. reqList.forEach((item,index) => {
  850. this.singleHandle(item)
  851. });
  852. }
  853. else{
  854. this.singleHandle({aiPicId:this.aiPicId})
  855. }
  856. },
  857. //发出获取结果请求获取AI生成结果
  858. async singleHandle(model){
  859. if(!model || !model.aiPicId){
  860. return false;
  861. }
  862. var parmas = {
  863. id: model.aiPicId,
  864. };
  865. let res = await requestConfig("getPredictions", parmas);
  866. if (res.success && res.single) {
  867. if(this.currentImg){//当前已经有生成图了
  868. console.warn("***当前已经有最高级生成图了***")
  869. return false;
  870. }
  871. if(this.timer==null){
  872. console.warn("***当前轮询已经结束了***")
  873. return false;
  874. }
  875. if (res.single.status == 'succeeded' && res.single.output) {
  876. if(this.modelType==2){//精准设计
  877. model.resultImg = res.single.output;
  878. if(model.level=='5'){//最高级了
  879. this.currentImg = true;
  880. setTimeout(()=>{
  881. this.resultHandle(res.single.output)
  882. },1500)
  883. }
  884. }else{
  885. this.currentImg = true;
  886. setTimeout(()=>{
  887. this.resultHandle(res.single.output)
  888. },1500)
  889. }
  890. console.warn("***有生成图了***",model)
  891. }
  892. if(this.modelType==2){//最高优先级返回没有图片,则处理进度条事宜
  893. if(model.level=='5'){
  894. this.processHandle(res.single);
  895. }
  896. }else{//普通设计
  897. this.processHandle(res.single);
  898. }
  899. } else if (!res.success) {
  900. this.stopInterval();//停止轮询
  901. this.showToast("渲染失败,请重试")
  902. }
  903. },
  904. //进度处理
  905. processHandle(single){
  906. console.warn("***single***",single.status,single.progress,this.count,single);
  907. let self = this;
  908. if(single.status=='starting'){//启动中的逻辑
  909. if(this.count>=20){
  910. this.stopInterval();//停止轮询
  911. // this.dialogAIVisible = true;
  912. MessageBox.confirm('',{
  913. title: '提示',
  914. message: 'AI开了小差,是否重新生成?',
  915. showCancelButton: true,
  916. confirmButtonText:'继续生成',
  917. cancelButtonText:'放弃生成',
  918. }).then(action => {
  919. console.warn("***MessageBox-action***",action)
  920. if(action == 'confirm'){
  921. this.confirmHandle(0);
  922. }
  923. }).catch(err=>{
  924. if(err == 'cancel'){
  925. this.cancelHandle();
  926. }
  927. });
  928. }else{
  929. this.myloading = true;
  930. this.loadingMsg = '启动中';
  931. }
  932. this.count = this.count + 1;
  933. this.getOutPicture();
  934. }else if(single.status=='processing'){
  935. let random = single.progress || 0;
  936. if(random >= 100){
  937. random = 99;
  938. }
  939. this.myloading = true;
  940. this.loadingMsg = '生成中…' + parseInt(random) + '%';
  941. this.getOutPicture();
  942. }else if(single.status=='succeeded'){
  943. this.myloading = true;
  944. this.loadingMsg = '生成中…100%';
  945. }
  946. },
  947. //返回结果处理
  948. resultHandle(resultImg){
  949. this.currentImg = true;
  950. // this.random = 100;
  951. this.aiImage = resultImg;
  952. this.showAIFlag = true;
  953. let newImage = resultImg;
  954. let aiStyleName = this.styleList[this.curStyleIndex].styleName;
  955. let _data = {
  956. image:newImage,
  957. checked:false,
  958. list:[newImage],
  959. spaceId:this.curSpaceId,//记录下当前生成的AI图是哪个空间的,因为会切换空间
  960. aiStyleName:aiStyleName,
  961. }
  962. this.aiImagesList.push(_data);
  963. this.showAIImage = true;//显示AI结果集合-因为生成了AI图片
  964. // if(this.$parent && typeof(this.$parent.clearHandle)=="function" ){
  965. // this.$parent.clearHandle();
  966. // }
  967. let cpAiData = JSON.parse(JSON.stringify(this.aiData)) || []
  968. if(cpAiData && this.curHouseObj && this.curHouseObj.houseFloor){//给上一个页面回传生成的数据
  969. let space = cpAiData.find(it=>{
  970. return it.houseFloor == this.curHouseObj.houseFloor && it.spaceId == this.spaceObj.spaceId
  971. })
  972. if(space){
  973. let data ={
  974. aiStyleName:aiStyleName,
  975. image:newImage,
  976. checked:false,
  977. }
  978. space.aiImagesList.push(data);
  979. }else{//不存在则构建数据
  980. let data = {
  981. houseFloor:this.curHouseObj.houseFloor,//当前的楼层
  982. spaceId:this.spaceObj.spaceId,
  983. aiImagesList:[
  984. {
  985. aiStyleName:aiStyleName,
  986. image:newImage,
  987. checked:false,
  988. }
  989. ]
  990. }
  991. cpAiData.push(data)
  992. }
  993. this.$store.dispatch('setAiData', cpAiData)
  994. }
  995. this.stopInterval();
  996. if(this.aiImagesList.length>1){
  997. setTimeout(()=>{
  998. this.$refs.carousel.setActiveItem(this.aiImagesList.length-1);//切换到最后一张
  999. }, 1000);
  1000. }
  1001. },
  1002. //空间数据整理
  1003. spaceAIHandle(){
  1004. let curHouseObj = this.curHouseObj;//当前户型数据对象
  1005. let aiImagesList = this.aiImagesList;//AI生成图数据对象
  1006. let wallList = webglCom.wallList;//当前户型墙体数据列表对象
  1007. let spaceList = JSON.parse(curHouseObj.houseJson);
  1008. //遍历当前户型下的每一个空间
  1009. spaceList.forEach((item)=>{
  1010. let space = item;
  1011. let list = aiImagesList.filter(it=>it.spaceId==space.spaceId);//找到AI生成图中的当前空间
  1012. if(list && list.length>0){
  1013. list = list.filter(it=>it.checked==true);//过滤选中的
  1014. list = list.map(it=>{
  1015. return it.image
  1016. })
  1017. space.hardboundEffect = list;
  1018. console.warn("submitHouse: ", list,space);
  1019. }
  1020. let wall = wallList.find(it=>it.id==space.wallId);
  1021. if(wall){//找到当前空间的墙体数据
  1022. space.wallList = JSON.stringify(wall);
  1023. }
  1024. })
  1025. setStorage('spaceList', spaceList);//把空间选择的数据存入本地缓存里面,方便后续使用
  1026. console.warn("**spaceList**",spaceList)
  1027. },
  1028. async submitHouse(){
  1029. const loading = this.$loading({
  1030. lock: true,
  1031. text: '提交中...',
  1032. spinner: 'el-icon-loading',
  1033. background: 'rgba(0, 0, 0, 0.7)'
  1034. });
  1035. let shottingImg = getStorage('shottingImg');//把空间选择的数据存入本地缓存里面,方便后续使用
  1036. console.warn("***shottingImg***",shottingImg);
  1037. let userId = this.userId ? this.userId : '';
  1038. let curLayoutStruct = JSON.parse(getStorage('curLayoutStruct')) ;//获取楼层的数据-户型数组
  1039. let curHouseObj = this.curHouseObj;//当前户型数据对象
  1040. let curHouseType = getStorage('curHouseType');//把楼层的数据存入缓存中
  1041. let curHouseName = getStorage('curHouseName');//把楼层的数据存入缓存中
  1042. let param = {
  1043. "brandId": $config.brandId,
  1044. "houseId": curHouseObj.houseId,
  1045. "userId": userId,
  1046. "floot": curHouseObj.houseFloor,
  1047. "spaceName": curHouseName,
  1048. "spaceStructure": curHouseType,
  1049. "curFloor":curHouseObj.houseFloor,
  1050. layoutStruct:[],
  1051. }
  1052. let wallList = webglCom.wallList;//当前户型墙体数据列表对象
  1053. //处理每一个楼层
  1054. curLayoutStruct.forEach((layoutStruct,index)=>{
  1055. let houseData = {
  1056. "layoutId": layoutStruct.id,
  1057. "layoutName": layoutStruct.name,
  1058. "layoutArea": layoutStruct.houseArea,
  1059. "floor": layoutStruct.houseFloor,
  1060. "layoutImgCustomized": shottingImg,
  1061. "style": "",
  1062. "houseJson": []
  1063. }
  1064. let spaceList = JSON.parse(layoutStruct.houseJson);
  1065. let styleList = [];
  1066. //遍历当前户型下的每一个空间
  1067. spaceList.forEach((item)=>{
  1068. let space = JSON.parse(JSON.stringify(item));
  1069. //找到当前空间对象对应的AI数据对象
  1070. let AISpace = null;
  1071. AISpace = this.aiData && this.aiData.find(it=>{
  1072. return it.houseFloor == layoutStruct.houseFloor && it.spaceId == space.spaceId
  1073. });
  1074. if(AISpace){
  1075. let list = AISpace.aiImagesList.filter(it=>it.checked==true);//过滤选中的
  1076. list.forEach(it=>{
  1077. styleList.push(it.aiStyleName);
  1078. })
  1079. list = list.map(it=>{
  1080. return it.image
  1081. })
  1082. space.hardboundEffect = list;
  1083. console.warn("submitHouse: ", list,space);
  1084. }
  1085. let wall = wallList.find(it=>it.id==space.wallId);
  1086. if(wall){//找到当前空间的墙体数据
  1087. space.wallList = JSON.stringify(wall);
  1088. }
  1089. houseData.houseJson.push(space)
  1090. })
  1091. //寻找styleList里面出现最多次数的风格
  1092. if(styleList && styleList.length>0){
  1093. let maxEle = styleList[0];
  1094. let maxNum = 1;
  1095. styleList.reduce((p,k)=>{
  1096. p[k] ? p[k]++ : p[k]=1;
  1097. if(p[k] > maxNum){
  1098. maxEle = k;
  1099. maxNum ++
  1100. }
  1101. return p;
  1102. },{});
  1103. houseData.style = maxEle;
  1104. }
  1105. param.layoutStruct.push(houseData)
  1106. })
  1107. param.expand = getStorage('expand') || ''
  1108. console.warn("submitHouse-param: ", param);
  1109. let trackparam = {
  1110. type: 'CLK', //埋点类型
  1111. clkId: 'clk_2cmina_23080409', //点击ID
  1112. clkName: 'submit_clk', //点击前往的页面名称
  1113. clkParams: {
  1114. locusName: "数据提交",
  1115. postAIData:this.aiData,
  1116. }
  1117. };
  1118. util.trackRequest(trackparam);
  1119. let res = await requestConfig("saveCustomizedRecord", param);
  1120. loading.close();
  1121. if(res && res.success && res.single){//提交成功
  1122. let data = {
  1123. houseId:this.$route.query.houseId || this.$store.state.houseId,
  1124. id:res.single,
  1125. }
  1126. webglCom.saveState();//记录下当前的控制器状态
  1127. webglCom.showWebgl = false;//隐藏webgl
  1128. router.push({
  1129. name: "webgl_rxdz_customize",
  1130. query:data
  1131. });
  1132. }
  1133. },
  1134. //进入下一步
  1135. gonext(){
  1136. this.spaceAIHandle()
  1137. router.push({
  1138. name: "webgl_rxdz_test_env",
  1139. query:{
  1140. houseId:this.$route.query.houseId || this.$store.state.houseId,
  1141. }
  1142. });
  1143. },
  1144. showToast(title,time=3000){
  1145. this.myloading = false;
  1146. this.$store.state.loading = true;
  1147. this.$store.state.loadingMsg = title || "";
  1148. setTimeout(()=>{
  1149. this.$store.state.loading = false;
  1150. }, time);
  1151. }
  1152. }
  1153. }
  1154. </script>
  1155. <style lang="scss" scoped>
  1156. @import "./viewMask.scss";
  1157. </style>
  1158. <style lang="css" scoped>
  1159. /* @import "@/common/css/common.css"; */
  1160. </style>