| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450 |
- <template>
- <div class="design-container AI-Design-container">
- <div class="header">
- <van-nav-bar title="内墙设计" left-arrow @click-left="returnPage" @click-right="toHome">
- <template #right>
- <van-icon name="wap-home-o" color="#000" size="26" />
- </template>
- </van-nav-bar>
- </div>
- <div class="container">
- <!-- 历史生图 -->
- <div class="history-section">
- <div class="history-header" @click="viewHistory">
- <van-icon name="clock-o" color="#EC8868" />
- <span>历史生图</span>
- <span v-if="!readState" class="badge-dot"></span>
- </div>
- </div>
- <!-- 图片选择 -->
- <div class="image-selection">
- <div class="image-placeholder">
- <div v-if="selectedImage" class="selected-image-preview">
- <img :src="selectedImage" alt="预览图片" class="preview-image" @click="imgClick(selectedImage)" />
- </div>
- <div v-else class="placeholder">
- <img width="50" :src="require('@/assets/AIDesign/picture.png')" />
- <p class="placeholder-text">请上传一张待设计内墙的房屋照片</p>
- <p class="placeholder-text-tit">(避免模糊、光线不佳)</p>
- </div>
- <div class="image-buttons">
- <!-- 原生上传按钮 -->
- <div class="upload-container">
- <input type="file" accept="image/*" class="native-upload-input" @change="handleFileChange">
- <button class="image-btn">
- <span>选择图片</span>
- </button>
- </div>
- </div>
- </div>
- </div>
- <div class="insideInfo">
- <van-tabs v-model="activeName" @change="tabsChange" title-active-color="#383838" color="#383838"
- title-inactive-color="#b3b3b3" line-width="78" line-height="4">
- <van-tab title="魔术漆" name="魔术漆"></van-tab>
- <van-tab title="内墙平涂" name="内墙平涂"></van-tab>
- <van-tab title="风格" name="风格"></van-tab>
- </van-tabs>
- <!-- 风格 -->
- <div class="radio-group-container" v-show="activeName === '风格'">
- <van-radio-group v-model="DesignStyle_selValue" class="custom-radio-group3" @change="handleChange">
- <van-radio v-for="(item, index) in DesignStyle_options" :key="index" :name="item.value"
- class="custom-radio custom-radio3">
- <div class="radio-content radio-content-text
- ">
- {{ item.text }}
- <div v-if="DesignStyle_selValue === item.value" class="check-indicator">
- <van-icon name="success" color="#fff" size="10" />
- </div>
- </div>
- </van-radio>
- </van-radio-group>
- </div>
- <!--魔术漆 -->
- <div class="radio-group-container1" v-show="activeName === '魔术漆'">
- <div class="toggle-div">
- <van-icon :name="isExpanded ? 'arrow-up' : 'arrow-down'" class="toggle-icon" @click="toggleExpand" />
- </div>
- <!-- 纹理 -->
- <!-- 单选组:默认显示第一行,展开后显示全部 -->
- <van-radio-group v-model="textureCode_selValue" class="custom-radio-group" @change="handleTextureCodeChange">
- <div class="radio-wrapper" :class="isExpanded ? 'radio-column' : 'radio-row'" ref="textureRef">
- <van-radio class="custom-radio" v-for="(item, index) in textureCode_options" :key="index"
- :name="item.text" @click="selectRadio(item.text, 'textureRef', index)">
- <div class="radio-content" :class="{ 'radio-content--active': textureCode_selValue === item.text }">
- {{ item.text }}
- </div>
- </van-radio>
- </div>
- </van-radio-group>
- <!--纹理-颜色-放大版 -->
- <div class="wenli-plus" v-if="textureCodeWithColor_selItem">
- <van-image class="cardImg" fit="cover" :src="imgBaseUrl + textureCodeWithColor_selItem.imgPath" />
- <div class="wenli-plus-tit">{{ textureCodeWithColor_selItem.text }}</div>
- <div class="wenli-plus-subheading" v-if="textureCode_selItem && textureCode_selItem.text">
- 立邦魔术漆,{{ textureCode_selItem.text }}系列</div>
- </div>
- <!-- 纹理-颜色 -->
- <van-radio-group v-model="textureCodeWithColor_selValue" class="custom-radio-group4"
- @change="handleTextureCodeWithColorChange">
- <van-radio v-for="(item, index) in textureCodeWithColor_options" :key="index" :name="item.value"
- class="custom-radio custom-radio4">
- <div class="radio-content radio-content-color">
- <!-- <van-image class="cardImg" lazy-load :src="imgBaseUrl + item.imgPath" /> -->
- <img class="cardImg" :src="imgBaseUrl + item.imgPath" />
- <div v-if="textureCodeWithColor_selValue === item.value" class="check-indicator">
- <van-icon name="success" color="#fff" size="10" />
- </div>
- <div class="custom-radio-text">{{ item.text }}</div>
- </div>
- </van-radio>
- </van-radio-group>
- </div>
- <!--内墙平涂 -->
- <div class="radio-group-container1" v-show="activeName === '内墙平涂'">
- <!--内墙平涂-放大版 -->
- <div class="color-plus" v-if="color_selItem">
- <div class="cardImg" :style="{ backgroundColor: color_selItem.value.slice(0, 7) }"></div>
- <div class="color-plus-info">
- <div class="color-plus-tit">{{ color_selItem.text }}</div>
- <p>{{ color_selItem.ext1 }}</p>
- <p>{{ color_selItem.ext2 }}</p>
- <div class="color-plus-subheading">{{ color_selItem.ext3 }}</div>
- </div>
- </div>
- <van-radio-group v-model="color_selValue" class="custom-radio-group4" @change="handleColorChange">
- <van-radio v-for="(item, index) in color_options" :key="index" :name="item.value"
- class="custom-radio custom-radio4">
- <div class="radio-content radio-content-color">
- <div class="cardImg" :style="{ backgroundColor: item.value.slice(0, 7) }"></div>
- <div v-if="color_selValue === item.value" class="check-indicator">
- <van-icon name="success" color="#fff" size="10" />
- </div>
- <div class="custom-radio-text">{{ item.text }}</div>
- </div>
- </van-radio>
- </van-radio-group>
- </div>
- </div>
- <!-- AI生成按钮 -->
- <div class="generate-section">
- <van-button v-show="AIBtnDisabled" type="primary" block color="#E87838" disabled loading loading-type="spinner"
- loading-text="AI生成"></van-button>
- <van-button v-show="!AIBtnDisabled" type="primary" block @click="generateDesign"
- color="#E87838">AI生成</van-button>
- <div class="btn-note">*效果图仅供参考, 不作为交付标准</div>
- </div>
- </div>
- <!-- 上传 -->
- <van-action-sheet v-model="projectActionLoadingShow">
- <div class="project-action-box">
- <img src="../../assets/AIDesign/project_action_loading.png">
- <div class="tip" style="margin-top: 20px;">正在为您飞速上传...</div>
- <div class="tip-content">为了给您更好的生图效果,请避免上传模糊、光线不佳、非外墙的图片。<br />立邦AI效果图仅为意向图,不作为施工交付标准。</div>
- <div class="btn" @click="projectActionLoadingShow = false">我知道了</div>
- </div>
- </van-action-sheet>
- <van-dialog v-model="dialogShow" :show-confirm-button="false">
- <div class="dialog-box">
- <div class="dialog-content">{{ dialogContent }}</div>
- <div class="dialog-btn" @click="dialogShow = false">知道了</div>
- </div>
- </van-dialog>
- </div>
- </template>
- <script lang="ts">
- import { Component, Vue, Ref } from "vue-property-decorator";
- import { insideCreateDesign, insideGetEntity, insideGetReadState, insideUpdateReadState, GetDictList } from "@/api/indexAI";
- import { ImagePreview } from 'vant';
- import { Dialog } from 'vant';
- import { getWecomType, toLBHome } from '@/utils/index';
- declare let wx: any;
- import axios from "axios";
- @Component({
- })
- export default class extends Vue {
- // 添加鼠标拖拽相关引用
- $refs!: {
- stoneColorsRef: HTMLDivElement;
- processesRef: HTMLDivElement;
- splitsRef: HTMLDivElement;
- windowsRef: HTMLDivElement;
- railingsRef: HTMLDivElement;
- tilesRef: HTMLDivElement;
- };
- private imgBaseUrl = '';
- private activeName = "魔术漆";// tab选中的项
- private readState = true;//历史生土
- private projectActionLoadingShow = false;//图片上传中
- private serviceCodeArray = [];//服务商
- private dialogShow = false;//提交之后错误弹窗
- private dialogContent = '';//提交之后错误提示
- private AIBtnDisabled = false;//ai生成按钮状态
- private selectedImage: string | null = null; // 存储选择的图片
- private DesignStyle_selValue = '';// 风格选中的值
- private textureCode_selValue = '';// 深槽工艺选中的值
- private color_selValue = '';// 电子色卡选中的值
- private DesignStyle_options = [];//风格列表
- private textureCode_options = [];//深槽工艺列表
- private color_options = [];//电子色卡列表
- private textureCodeWithColor_selValue = '';//颜色纹理选中的值
- private textureCodeWithColor_options = [];//包含颜色和纹理的组合参数
- private textureCode_selItem = null;//选中的一级纹理
- private textureCodeWithColor_selItem = null;//选中的二级纹理
- private isExpanded = false;//展开/折叠状态
- private isEchoAssign: boolean = false;// 新增:标记是否为代码回显赋值(默认 false)
- private textureCode_selItem_index = 0;//纹理一级分类的选中索引
- private color_selItem = null;//选中的色卡
- // 当前选中的选项
- private oldf_id = null;
- private Userfile1 = null;
- // 添加鼠标拖拽相关数据
- private isMouseDown = false;
- private startX = 0;
- private scrollLeft = 0;
- private currentScrollElement: HTMLElement | null = null;
- @Ref('textureRef') private textureRef!: HTMLDivElement;
- created() {
- // this.getServiceCode();
- // 图片头
- if (window.location.href.indexOf('aidesign.') > -1) {
- this.imgBaseUrl = 'https://aidesign.nipponpaint.com.cn'
- } else {
- this.imgBaseUrl = 'https://aidesigntest.nipponpaint.com.cn'
- }
- }
- activated() {
- // 初始化数据
- this.initialize();
- this.getPicList();
- this.GetReadStateFn();
- }
- private initialize() {
- this.activeName = "魔术漆";
- this.readState = true;
- this.projectActionLoadingShow = false;
- this.dialogShow = false;//提交之后错误弹窗
- this.dialogContent = '';//提交之后错误提示
- this.AIBtnDisabled = false;//ai生成按钮状态
- this.selectedImage = '';
- this.DesignStyle_selValue = '';// 风格选中的值
- this.textureCode_selValue = '';// 深槽工艺选中的值
- this.color_selValue = '';// 电子色卡选中的值
- this.oldf_id = null;
- this.Userfile1 = null;
- this.textureCodeWithColor_selValue = '';//颜色纹理选中的值
- this.textureCodeWithColor_options = [];//包含颜色和纹理的组合参数
- this.textureCode_selItem = null;
- this.textureCodeWithColor_selItem = null;
- this.isExpanded = false;//展开/折叠状态
- this.isEchoAssign = false;
- this.textureCode_selItem_index = 0;
- this.color_selItem = null;
- }
- tabsChange(value: string) {
- this.DesignStyle_selValue = '';// 风格选中的值
- this.isExpanded = false;
- if (value === '魔术漆') {
- // 纹理默认第一个
- this.initDefaultTextureSelection()
- } else if (value === '内墙平涂') {
- // 色卡默认第一个
- this.color_selItem = this.color_options[0];
- this.color_selValue = this.color_options[0].value;
- }
- }
- // 初始化默认选择第一级纹理第一项
- initDefaultTextureSelection() {
- // 标记当前是初始化赋值,避免change事件清空二级
- this.isEchoAssign = true;
- if (this.textureCode_options.length > 0) {
- const firstTexture = this.textureCode_options[0];
- this.textureCode_selValue = firstTexture.text;
- this.textureCode_selItem = firstTexture;
- this.textureCode_selItem_index = 0;
- // 手动更新二级纹理选项
- this.textureCodeWithColor_options = firstTexture.subitems || [];
- if (this.textureCodeWithColor_options.length > 0) {
- const firstColor = this.textureCodeWithColor_options[0];
- this.textureCodeWithColor_selValue = firstColor.value;
- this.textureCodeWithColor_selItem = firstColor;
- }
- }
- this.textureCode_selItem_index = 0;
- // 初始化完成后重置标记
- this.$nextTick(() => {
- this.isEchoAssign = false;
- this.scrollIntoSel();
- });
- }
- // 选中变化时的回调
- handleChange(value: string | number) {
- // console.log("value=", value)
- // console.log("风格=",this.DesignStyle_selValue)
- // console.log("魔术漆=",this.textureCode_selValue)
- // console.log("内墙平涂=",this.color_selValue)
- }
- // 选择色卡
- handleColorChange(value: string | number) {
- // console.log("选择色卡")
- const selectedItem = this.color_options.find(
- item => item.value === value
- );
- this.color_selItem = selectedItem || null;
- }
- // 选择一级纹理
- handleTextureCodeChange(selectedValue: string | number) {
- // 防止回显触发
- if (!this.isEchoAssign) {
- // console.log("选一级纹理")
- this.textureCodeWithColor_selItem = null;
- // 找到选中的纹理项和索引
- let selectedItem = null;
- let selectedIndex = -1;
- this.textureCode_options.forEach((item, index) => {
- if (item.text === selectedValue) {
- selectedItem = item;
- selectedIndex = index;
- }
- });
- this.textureCode_selItem = selectedItem || null;
- this.textureCode_selItem_index = selectedIndex;
- // 更新颜色选项数组(如果选中项有subitems则赋值,否则置空)
- this.textureCodeWithColor_options = selectedItem && selectedItem.subitems ? selectedItem.subitems : [];
- this.textureCodeWithColor_selValue = '';
- }
- }
- // 选择二级纹理
- handleTextureCodeWithColorChange(value: string | number) {
- // 防止回显触发
- if (!this.isEchoAssign) {
- // console.log("选二级纹理")
- // 找到选中的纹理项
- const selectedItem = this.textureCodeWithColor_options.find(
- item => item.value === value
- );
- this.textureCodeWithColor_selItem = selectedItem || null;
- }
- }
- // 切换展开/折叠
- toggleExpand() {
- this.isExpanded = !this.isExpanded;
- this.scrollIntoSel();
- }
- // 滑动到用户所选位置
- scrollIntoSel() {
- if (!this.isExpanded && this.textureCode_selItem_index !== -1) {
- this.$nextTick(() => {
- const targetItem = this.textureRef.children[this.textureCode_selItem_index];
- if (targetItem) {
- try {
- // 滚动到选中项(居中显示,平滑滚动)
- (targetItem as HTMLElement).scrollIntoView({
- behavior: 'smooth',
- block: 'nearest',
- inline: 'center'
- });
- } catch (e) {
- const container = this.textureRef;
- const itemLeft = targetItem.offsetLeft;
- const itemWidth = targetItem.offsetWidth;
- const containerWidth = container.clientWidth;
- const targetScrollLeft = itemLeft - (containerWidth - itemWidth) / 2;
- container.scrollLeft = targetScrollLeft;
- }
- }
- });
- }
- }
- private selectRadio(code: string, refsName: string, selcIndex: number) {
- this.autoScrollToActive(refsName, selcIndex); // 选中后触发自动滚动
- }
- private autoScrollToActive(refsName: string, selcIndex: number) {
- const container = this.$refs[refsName];
- const activeItem = container.children[selcIndex];
- const itemWidth = activeItem.offsetWidth * 1.1;
- // 判断选中项是否完全在可视范围内
- const containerRect = container.getBoundingClientRect(); // 容器可视区域
- const itemRect = activeItem.getBoundingClientRect(); // 选中项位置
- // 完全可见的条件:左≥容器左,右≤容器右
- const isFullyVisibleL = itemRect.left >= containerRect.left;
- const isFullyVisibleR = itemRect.right <= containerRect.right - 26;
- if (!isFullyVisibleL) {
- container.scrollBy({
- left: -itemWidth, // 右边滑一格多的距离
- behavior: 'smooth' // 平滑滚动
- });
- } else if (!isFullyVisibleR) {
- container.scrollBy({
- left: itemWidth, // 左滑一格多的距离
- behavior: 'smooth' // 平滑滚动
- });
- }
- }
- private getServiceCode() {
- let that = this;
- const userInfo: any = JSON.parse(window.localStorage.getItem("userInfoV1")!);
- let serviceCodeArray = [];
- if (userInfo.loginTypeList.length > 0) {
- userInfo.loginTypeList.forEach(item => {
- if (item.shopType == 'stoneLikePaint') {
- item.shopList.forEach(childItem => {
- serviceCodeArray.push(childItem.shop_code);
- })
- }
- })
- }
- that.serviceCodeArray = serviceCodeArray;
- }
- // 处理文件选择
- handleFileChange(e) {
- const file = e.target.files[0]; // 获取选中的文件
- if (!file) return; // 未选择文件直接返回
- // 1. 校验文件类型
- if (!file.type.match('image.*')) {
- this.$toast('请选择图片文件');
- this.clearInput(e.target); // 清除选择,避免重复触发同一文件
- return;
- }
- let FileSize = (file.size / 1024 / 1024).toFixed(2);
- console.log("用户选择的图片大小=", file.size + 'KB', ' =', FileSize + 'M')
- // 2. 校验文件大小)
- const maxSize = 20 * 1024 * 1024; // 10MB
- if (file.size > maxSize) {
- this.$toast('图片大小不能超过10MB');
- this.clearInput(e.target);
- return;
- }
- // 3. 处理选中的文件(对应 afterRead)
- this.handleAfterRead(file);
- // 清除 input 值,确保同一文件能被再次选择
- this.clearInput(e.target);
- }
- // 处理校验通过后的文件(对应 afterRead)
- handleAfterRead(file) {
- console.log("选中的图片信息:", file);
- // 生成图片预览(如果需要,和 van-uploader 的 content 类似)
- const reader = new FileReader();
- reader.onload = (event) => {
- this.selectedImage = event.target.result; // 预览图的 base64
- };
- reader.readAsDataURL(file); // 转换为 base64
- this.Userfile1 = file; // 保存原始文件对象(用于后续上传)
- }
- // 清除 input 值(解决同一文件无法重复选择的问题)
- clearInput(input) {
- input.value = '';
- }
- imgClick(url) {
- ImagePreview([url]);
- }
- GetReadStateFn() {
- const formData = new FormData();
- // const userInfo: any = JSON.parse(window.localStorage.getItem("userInfoV1")!);
- // formData.append('WXuserid', userInfo.loginName);
- insideGetReadState(formData).then(response => {
- if (response.StatusCode == 200) {
- this.readState = response.Data.readState;
- }
- });
- }
- insideUpdateReadStateFn() {
- const formData = new FormData();
- // const userInfo: any = JSON.parse(window.localStorage.getItem("userInfoV1")!);
- // formData.append('WXuserid', userInfo.loginName);
- insideUpdateReadState(formData).then(response => { });
- }
- GetEntityData(F_id) {
- const formData = new FormData();
- formData.append('F_id', F_id);
- insideGetEntity(formData).then(response => {
- // console.log(response);
- if (response.StatusCode == 200) {
- if (response.Data) {
- if (response.Data.F_UserFilePath) {
- this.selectedImage = response.Data.BaseUrl + response.Data.F_UserFilePath;
- }
- this.isEchoAssign = true;
- // 内墙结果-回显
- this.DesignStyle_selValue = response.Data.F_Style;// 风格选中的值
- // this.textureCode_selValue = response.Data.F_TextureCode;// 深槽工艺选中的值
- this.color_selValue = response.Data.F_Color;// 电子色卡选中的值
- const F_TextureCodeWithColor = response.Data.F_TextureCodeWithColor;
- // 处理纹理
- if (F_TextureCodeWithColor) {
- this.textureCode_selValue = F_TextureCodeWithColor.split("-")[1];
- // 找到选中的纹理项和索引
- let selectedItem = null;
- let selectedIndex = -1;
- this.textureCode_options.forEach((item, index) => {
- if (item.text === this.textureCode_selValue) {
- selectedItem = item;
- selectedIndex = index;
- }
- });
- this.textureCode_selItem_index = selectedIndex;
- // 找到选中的纹理颜色
- const textureCodeWithColorOp = selectedItem && selectedItem.subitems ? selectedItem.subitems : []
- const selectedItemColor = textureCodeWithColorOp.find(
- item => item.value === F_TextureCodeWithColor
- );
- this.textureCodeWithColor_selValue = F_TextureCodeWithColor;// 颜色纹理选中的值
- this.textureCode_selItem = selectedItem || null;
- this.textureCodeWithColor_selItem = selectedItemColor || null;
- this.textureCodeWithColor_options = textureCodeWithColorOp;
- this.$nextTick(() => {
- this.isEchoAssign = false;
- this.scrollIntoSel();
- });
- } else if (this.color_selValue) {
- // 找到选中的色卡
- const selectedItemColor = this.color_options.find(
- item => item.value === this.color_selValue
- );
- this.color_selItem = selectedItemColor;
- }
- this.oldf_id = response.Data.F_ID;
- if (this.DesignStyle_selValue && this.DesignStyle_selValue !== 'CUSTOM') {
- this.activeName = '风格';
- } else if (this.textureCode_selValue) {
- this.activeName = '魔术漆';
- } else if (this.color_selValue) {
- this.activeName = '内墙平涂';
- } else {
- this.activeName = '';
- }
- }
- }
- })
- }
- // 添加一个新的辅助方法用于将图片URL转换为File对象
- private async urlToFile(url: string, filename: string): Promise<File> {
- try {
- const response = await fetch(url);
- const blob = await response.blob();
- return new File([blob], filename, { type: blob.type });
- } catch (error) {
- console.error('图片转换失败:', error);
- this.$toast('图片加载失败');
- throw error;
- }
- }
- private viewHistory() {
- this.insideUpdateReadStateFn();
- // console.log('查看历史生成');
- // 实现查看历史生成逻辑
- this.$router.push({ path: '/AIDesign/history', query: { wallType: "inside" } });
- }
- // 添加鼠标滚轮事件处理
- private handleWheel(e: WheelEvent) {
- const container = e.currentTarget as HTMLElement;
- if (container) {
- container.scrollLeft += e.deltaY;
- }
- }
- // 添加鼠标按下事件处理
- private handleMouseDown(e: MouseEvent) {
- this.isMouseDown = true;
- this.currentScrollElement = e.currentTarget as HTMLElement;
- if (this.currentScrollElement) {
- this.currentScrollElement.style.cursor = 'grabbing';
- this.startX = e.pageX - this.currentScrollElement.offsetLeft;
- this.scrollLeft = this.currentScrollElement.scrollLeft;
- }
- }
- // 添加鼠标移动事件处理
- private handleMouseMove(e: MouseEvent) {
- if (!this.isMouseDown) return;
- e.preventDefault();
- if (this.currentScrollElement) {
- const x = e.pageX - this.currentScrollElement.offsetLeft;
- const walk = (x - this.startX) * 2;
- this.currentScrollElement.scrollLeft = this.scrollLeft - walk;
- }
- }
- // 添加鼠标释放事件处理
- private handleMouseUp() {
- this.isMouseDown = false;
- if (this.currentScrollElement) {
- this.currentScrollElement.style.cursor = 'grab';
- }
- this.currentScrollElement = null;
- }
- private generateDesign() {
- let that = this;
- if (!this.Userfile1 && !this.oldf_id) {
- this.$toast.fail('请选择图片');
- return;
- }
- if (this.activeName === '风格' && (!this.DesignStyle_selValue || this.DesignStyle_selValue === 'CUSTOM')) {
- this.$toast.fail(`请选择${this.activeName}`);
- return;
- }
- if (this.activeName === '魔术漆' && !this.textureCodeWithColor_selValue) {
- this.$toast.fail(`请选择${this.activeName}`);
- return;
- }
- const formData = new FormData();
- // const userInfo: any = JSON.parse(window.localStorage.getItem("userInfoV1")!);
- // let serviceCodeArray = [];
- // if (userInfo.loginTypeList.length > 0) {
- // userInfo.loginTypeList.forEach(item => {
- // if (item.shopType == 'stoneLikePaint') {
- // item.shopList.forEach(childItem => {
- // serviceCodeArray.push(childItem.shop_code);
- // })
- // }
- // })
- // }
- // formData.append('WXuserid', userInfo.loginName);
- let DesignStyle_selValue_sub = this.DesignStyle_selValue;
- //风格有值,清除纹理和色卡
- if (this.activeName === '风格') {
- this.textureCodeWithColor_selValue = '';//纹理
- this.color_selValue = '';//色卡
- } else if (this.activeName === '魔术漆') {
- this.color_selValue = '';//色卡
- } else if (this.activeName === '内墙平涂') {
- this.textureCodeWithColor_selValue = '';//纹理
- }
- if (!this.DesignStyle_selValue) {
- DesignStyle_selValue_sub = 'CUSTOM';
- }
- formData.append('DesignStyle', DesignStyle_selValue_sub);
- formData.append('textureCodeWithColor', this.textureCodeWithColor_selValue);
- formData.append('color', this.color_selValue);
- if (this.Userfile1) {
- formData.append('Userfile1', this.Userfile1);
- } else {
- formData.append('oldf_id', this.oldf_id);
- }
- // 企微类型
- // const agentFrom = window.localStorage.getItem('agentFromAI');
- // const wecomType = getWecomType(agentFrom);
- formData.append('wecomType', 5);
- // // 服务商代码
- // if (serviceCodeArray.length > 0) {
- // formData.append('serivceCode', serviceCodeArray.join(','));
- // }
- // // 姓名
- // formData.append('userName', userInfo.userName);
- // const customerCode = userInfo.sysUserExt && userInfo.sysUserExt.customerCode ? userInfo.sysUserExt.customerCode : '';
- // // 经销商代码
- // formData.append('distributorCode', customerCode);
- // //原服务商用户、新增经销商用户
- // // 大区
- // formData.append('regionName', userInfo.officeName || '');
- // // 公司名称
- // formData.append('companyName', userInfo.companyName || '');
- // // 员工号
- // let employeeID = userInfo.sysUserExt && userInfo.sysUserExt.sapEmployeeId ? userInfo.sysUserExt.sapEmployeeId : '';
- // formData.append('employeeID', employeeID);
- // //销售部---原服务商用户、新增经销商用户
- // formData.append('salesDepartment', userInfo.subOfficeName || '');
- // // 销售部ID
- // formData.append('salesDepartmentCode', userInfo.subOfficeCode || '');
- // 遍历打印
- formData.forEach((value, key) => {
- console.log(`key: ${key}, value: ${value}`);
- });
- that.AIBtnDisabled = true;
- insideCreateDesign(formData).then(response => {
- // console.log(response);
- if (response.StatusCode == 200) {
- that.projectActionLoadingShow = false;
- that.AIBtnDisabled = false;
- window.localStorage.setItem("type", 'design');
- this.$router.push({
- path: '/AIDesign/result',
- query: {
- F_id: response.Data.F_ID,
- fromPage: 'design',
- wallType: 'inside'
- }
- });
- } else if (response.StatusCode == 410) {
- that.dialogContent = response.Info;
- that.projectActionLoadingShow = false;
- that.AIBtnDisabled = false;
- that.dialogShow = true;
- } else {
- that.projectActionLoadingShow = false;
- that.AIBtnDisabled = false;
- that.$toast(response.Info);
- }
- })
- .catch((err) => {
- that.projectActionLoadingShow = false;//弹窗
- that.AIBtnDisabled = false;//ai生成按钮
- })
- }
- //获取风格选项图片列表
- private getPicList() {
- let that = this;
- const formData = new FormData();
- // const userInfo: any = JSON.parse(window.localStorage.getItem("userInfoV1")!);
- // let roleIdArray = [];
- // if (userInfo.roles.length > 0) {
- // userInfo.roles.forEach(item => {
- // roleIdArray.push(item.roleId);
- // })
- // }
- // formData.append('roleIds', roleIdArray.join(','));
- // formData.append('WXuserid', userInfo.loginName);
- formData.append('baseType', 1);//必填 0外墙 1内墙
- const agentFrom = window.localStorage.getItem('agentFromAI');
- const wecomType = getWecomType(agentFrom);
- formData.append('wecomType', 5);
- // const isRefresh = userInfo.isRefreshProvider === '是' ? 1 : 0;//0=否 1=是
- // formData.append('isRefresh', isRefresh);
- GetDictList(formData).then(response => {
- if (response.StatusCode == 200) {
- if (response.Data && response.Data.dict) {
- this.DesignStyle_options = response.Data.dict.InnerStyle;
- this.textureCode_options = response.Data.dict.InnerNewTextureCode;
- this.color_options = response.Data.dict.color;
- let F_id = this.$route.query.F_id;
- if (F_id) {
- this.GetEntityData(F_id);
- } else {
- // 纹理默认第一个
- this.initDefaultTextureSelection()
- }
- } else {
- console.log(response.Info);
- }
- }
- });
- }
- returnPage() {
- this.$router.push({ path: "/AiDesign" });
- }
- toHome() {
- toLBHome()
- }
- }
- </script>
- <style scoped lang="scss">
- .design-container {
- /* margin: 0 auto;
- max-width: 750px; */
- background-color: #f8f9fa;
- min-height: 100vh;
- flex-direction: column;
- }
- .container {
- padding: 0 20px;
- }
- .top-nav {
- display: flex;
- justify-content: space-between;
- align-items: center;
- padding: 16px 20px;
- background-color: white;
- box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
- position: sticky;
- top: 0;
- z-index: 10;
- }
- .back-btn,
- .more-btn {
- width: 40px;
- height: 40px;
- display: flex;
- justify-content: center;
- align-items: center;
- cursor: pointer;
- }
- .title {
- font-size: 15px;
- font-weight: bold;
- color: #000;
- }
- .history-section {
- margin: 20px 0;
- }
- .history-header {
- display: flex;
- align-items: center;
- gap: 12px;
- padding: 12px 16px;
- background-color: #ffffff;
- border-radius: 18px;
- box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
- border: 1px solid #e9ecef;
- /* margin-bottom: 10px; */
- }
- .icon-clock {
- font-size: 12px;
- margin-right: 8px;
- }
- .history-header span {
- font-weight: 500;
- color: #EC8868;
- }
- .history-header .badge-dot {
- width: 5px;
- height: 5px;
- background-color: #ff4d4f;
- border-radius: 50%;
- }
- .history-content {
- padding: 20px;
- border-radius: 8px;
- background-color: white;
- text-align: center;
- // border: 1px dashed #ddd;
- }
- .no-history {
- color: #999;
- font-size: 12px;
- }
- .image-selection {
- text-align: center;
- .image-placeholder {
- position: relative;
- display: flex;
- flex-direction: column;
- justify-content: center;
- align-items: center;
- height: 200px;
- margin-bottom: 20px;
- background-color: #ffffff;
- border-radius: 12px;
- box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
- border: 1px dashed #ddd;
- padding: 10px;
- padding-bottom: 50px;
- }
- .image-buttons {
- position: absolute;
- right: 10px;
- bottom: 10px;
- display: flex;
- gap: 16px;
- width: 100%;
- justify-content: flex-end;
- }
- }
- // 内墙
- .insideInfo {
- padding: 1.2rem 0;
- background-color: #ffffff;
- border-radius: 8px;
- box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
- .radio-group-container {
- padding: 16px 10px;
- }
- /* 单个选项样式 */
- .custom-radio {
- flex-shrink: 0;
- align-items: flex-start;
- justify-content: center;
- }
- // 纯文字
- .custom-radio-group3 {
- display: flex;
- flex-wrap: wrap;
- // column-gap: 8px;
- // row-gap: 16px;
- }
- .custom-radio3 {
- width: calc(33% - 8px);
- margin: 0 4px 16px;
- }
- /* 最后一个元素取消右侧间距 */
- .custom-radio3:nth-child(3n) {
- margin-right: 0;
- }
- // 上图下文字
- .custom-radio-group4 {
- display: flex;
- flex-wrap: wrap;
- // column-gap: 2px;
- // row-gap: 16px;
- }
- .custom-radio4 {
- width: calc(25% - 2px);
- margin: 0 1px 16px;
- }
- .custom-radio4:nth-child(4n) {
- margin-right: 0;
- }
- .radio-content-text {
- padding: 12px 0;
- text-align: center;
- border: 1px solid #E5E5E5;
- border-radius: 4px;
- box-sizing: border-box;
- transition: all 0.2s;
- font-size: 12px;
- }
- /* 选中指示器(橙色三角形背景) */
- .check-indicator {
- position: absolute;
- width: 20px;
- height: 20px;
- background-color: #F0A43A;
- /* 三角形效果 */
- clip-path: polygon(0 0, 0 100%, 100% 0);
- .van-icon {
- position: relative;
- }
- }
- /* 选项内容容器 */
- .radio-content {
- position: relative;
- width: 100%;
- }
- .custom-radio-text {
- font-size: 12px;
- text-align: center;
- line-height: 14px;
- width: 100%;
- margin: 0 auto;
- position: absolute;
- z-index: 2;
- color: #000;
- bottom: 4px;
- left: 0;
- }
- .radio-content-color {
- font-size: 12px;
- width: 60px;
- height: 60px;
- position: relative;
- border: 1px solid #E5E5E5;
- margin: 0 auto;
- .cardImg {
- width: 100%;
- height: 100%;
- }
- .check-indicator {
- left: 0;
- top: 0;
- .van-icon {
- top: -5px;
- left: 0px;
- }
- }
- }
- .radio-content-text {
- border-radius: 4px;
- .check-indicator {
- border-radius: 2px 0 0 0;
- top: 0;
- left: 0;
- .van-icon {
- top: -5px;
- left: -3px;
- }
- }
- }
- /* 隐藏Vant默认的选中样式 */
- .custom-radio ::v-deep .van-radio__icon {
- display: none;
- }
- .custom-radio ::v-deep .van-radio__label {
- width: 100%;
- margin-left: 0;
- border-radius: inherit;
- flex: 1;
- }
- }
- ::v-deep .van-tab__text {
- font-size: 15px;
- font-weight: 500;
- line-height: 2.6rem;
- }
- ::v-deep .van-tab--active .van-tab__text {
- font-size: 17px;
- }
- /* 选中状态的边框样式 */
- ::v-deep .van-radio__icon--checked+.van-radio__label>.radio-content-text {
- border-color: #F0A43A;
- }
- ::v-deep .van-radio__icon--checked+.van-radio__label>.radio-content-color {
- border-color: #F0A43A;
- }
- ::v-deep .van-button--normal {
- font-size: 16px;
- border-radius: 10px;
- }
- .project-action-box {
- flex-direction: column;
- display: flex;
- box-sizing: border-box;
- padding: 15px 5px 45px 5px;
- width: 100%;
- img {
- width: 100%;
- height: auto;
- }
- .tip {
- padding: 0 20px;
- font-size: 16px;
- font-weight: 700;
- }
- .tip-content {
- padding: 0 20px;
- margin-top: 30px;
- font-size: 14px;
- }
- .btn {
- height: 44px;
- line-height: 44px;
- text-align: center;
- margin: 20px;
- font-size: 16px;
- color: #FFFFFF;
- background-color: #2484F2;
- border-radius: 10px;
- }
- .btn2 {
- width: 100%;
- font-size: 14px;
- text-align: center;
- }
- }
- .list-item-checked {
- width: 100%;
- flex-direction: column;
- display: flex;
- box-sizing: border-box;
- border-radius: 10px;
- // box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
- padding: 15px;
- margin-bottom: 20px;
- position: relative;
- .img-item {
- position: absolute;
- bottom: 0;
- right: 5px;
- }
- .img-checked {
- width: 30px;
- }
- .title-item {
- flex-direction: row;
- display: flex;
- justify-content: space-between;
- align-items: center;
- margin-bottom: 5px;
- .title {
- font-size: 15px;
- font-weight: 700;
- }
- .status {
- font-size: 14px;
- color: #999999;
- min-width: 45px;
- margin-left: 10px;
- }
- }
- .user-item {
- flex-direction: row;
- display: flex;
- justify-content: flex-start;
- align-items: center;
- margin-top: 8px;
- .txt {
- font-size: 14px;
- color: #999999;
- margin-left: 10px;
- }
- }
- }
- .selected-image-preview {
- width: 100%;
- height: 100%;
- display: flex;
- justify-content: center;
- align-items: center;
- }
- .preview-image {
- max-width: 100%;
- max-height: 100%;
- object-fit: contain;
- }
- .placeholder-text {
- color: #999;
- font-size: 15px;
- text-align: center;
- margin-bottom: 20px;
- margin-top: 10px;
- }
- .placeholder-text-tit {
- color: #999;
- font-size: 15px;
- text-align: center;
- margin-bottom: 20px;
- margin-top: -10px;
- }
- .generate-section {
- display: flex;
- flex-direction: column;
- align-items: center;
- gap: 8px;
- /* 按钮和文字说明之间的间距 */
- margin-bottom: 20px;
- margin-top: 50px;
- }
- .btn-note {
- font-size: 12px;
- color: #999;
- text-align: center;
- line-height: 1.2;
- }
- .header {
- border-bottom: 1px solid #f8f8f8;
- .van-nav-bar__title {
- font-size: 20px;
- color: #000;
- }
- .van-icon {
- font-size: 20px;
- color: #000 !important;
- }
- }
- .dialog-box {
- flex-direction: column;
- display: flex;
- box-sizing: border-box;
- position: relative;
- .dialog-content {
- padding: 20px 20px 10px 20px;
- }
- .dialog-btn {
- height: 44px;
- line-height: 44px;
- text-align: center;
- margin: 20px;
- font-size: 16px;
- color: #FFFFFF;
- background-color: #2484F2;
- border-radius: 10px;
- }
- }
- ::v-deep .van-button__loading+.van-button__text {
- margin-left: 10px;
- }
- /* 样式调整:隐藏原生 input,按钮样式保持不变 */
- .upload-container {
- position: relative;
- display: inline-block;
- .native-upload-input {
- position: absolute;
- top: 0;
- left: 0;
- width: 100%;
- height: 100%;
- opacity: 0;
- cursor: pointer;
- z-index: 1;
- }
- .image-btn {
- padding: 8px 16px;
- border: none;
- border-radius: 8px;
- background-color: #2484F2;
- color: white;
- font-size: 12px;
- cursor: pointer;
- display: flex;
- align-items: center;
- gap: 8px;
- transition: all 0.2s ease;
- }
- }
- .wenli-plus,
- .color-plus {
- width: 100%;
- height: 90px;
- margin: 10px auto;
- position: relative;
- .cardImg {
- width: 100%;
- height: 100%;
- img {
- width: 100%;
- height: auto;
- }
- }
- .wenli-plus-tit {
- font-size: 16px;
- font-weight: 500;
- line-height: 14px;
- width: 100%;
- position: absolute;
- z-index: 2;
- color: #000;
- top: 25px;
- left: 20px;
- }
- .wenli-plus-subheading {
- font-size: 12px;
- line-height: 14px;
- width: 100%;
- position: absolute;
- z-index: 2;
- color: #86909C;
- top: 50px;
- left: 20px;
- }
- }
- .color-plus {
- margin: 0px auto 10px;
- .color-plus-info {
- position: absolute;
- width: calc(100% - 20px);
- height: 100%;
- top: 0;
- left: 20px;
- display: flex;
- flex-direction: column;
- justify-content: center;
- .color-plus-tit {
- font-size: 16px;
- font-weight: 500;
- line-height: 26px;
- width: 100%;
- color: #000;
- }
- p {
- font-size: 11px;
- line-height: 15px;
- color: rgba(56, 56, 56, 1);
- }
- .color-plus-subheading {
- font-size: 11px;
- line-height: 15px;
- width: 100%;
- color: #86909C;
- }
- }
- }
- // 纹理
- .radio-group-container1 {
- padding: 16px 0;
- position: relative;
- .toggle-div {
- position: absolute;
- top: 19px;
- right: 0px;
- background-color: #F7F7F7;
- width: 26px;
- height: 26px;
- border-radius: 50%;
- display: flex;
- align-items: center;
- justify-content: center;
- z-index: 5;
- box-shadow: 0 4px 8px rgba(78, 78, 78, 0.3);
- /* 展开/折叠图标 */
- .toggle-icon {
- cursor: pointer;
- color: #999;
- font-size: 18px;
- transition: transform 0.2s ease;
- }
- }
- .radio-row {
- overflow-x: auto;
- scroll-behavior: smooth;
- cursor: grab;
- flex-wrap: nowrap;
- .custom-radio {
- width: 72px;
- }
- }
- .radio-column {
- flex-wrap: wrap;
- .custom-radio {
- width: calc(25% - 10px);
- }
- }
- .radio-wrapper {
- padding: 0px 6px;
- display: flex;
- margin: 0 auto 8px;
- user-select: none;
- font-size: 12px;
- .custom-radio {
- flex-shrink: 0;
- --van-radio-size: 0;
- margin: 0 4px 15px;
- border: 1px solid #383838;
- transition: background-color 0.2s ease;
- border-radius: 10px;
- overflow: hidden;
- padding: 0 !important;
- box-sizing: border-box;
- display: flex;
- justify-content: flex-start;
- }
- .custom-radio ::v-deep .van-radio__label {
- flex: 1 !important;
- height: 100%;
- display: flex;
- align-items: center;
- border-radius: inherit;
- margin: 0 !important;
- width: 100% !important;
- }
- /* 单选内容容器 */
- .radio-content {
- width: 100%;
- height: 28px;
- white-space: nowrap;
- display: flex;
- align-items: center;
- justify-content: center;
- background: #fff;
- font-size: 11px;
- position: relative;
- text-align: center;
- }
- .radio-content--active {
- background: #383838;
- color: #fff;
- }
- }
- ::-webkit-scrollbar {
- display: none;
- }
- .custom-radio-group4 {
- padding: 0 10px;
- }
- }
- </style>
|