armg 1 주 전
부모
커밋
f492344327
6개의 변경된 파일760개의 추가작업 그리고 70개의 파일을 삭제
  1. 27 0
      src/api/indexAI.js
  2. 7 1
      src/router/index.ts
  3. 506 0
      src/views/AIDesign/GeneratePlan.vue
  4. 62 16
      src/views/AIDesign/diagnoseResult.vue
  5. 2 2
      src/views/AIDesign/index.vue
  6. 156 51
      src/views/AIDesign/result.vue

+ 27 - 0
src/api/indexAI.js

@@ -297,4 +297,31 @@ export function wecomTicket(query) {
         method: 'post',
         data: query
     })
+}
+
+// 埋点
+export function AddTrackEvent(query) {
+    const auth = getAuthCredentials();
+    query.append('loginMark', auth.loginMark);
+    query.append('token', auth.token);
+    return request({
+        url: '/aidesign/AddTrackEvent',
+        method: 'post',
+        data: query
+    })
+}
+
+//获取确认下单地址
+export function GetOrderAddress() {
+    const formData = new FormData();
+    const auth = getAuthCredentials();
+    formData.append('loginMark', auth.loginMark);
+    formData.append('token', auth.token);
+    const userInfo = JSON.parse(window.localStorage.getItem("userInfoV1"));
+    formData.append('WXuserid', userInfo.loginName);
+    return request({
+        url: '/aidesign/outside/GetOrderAddress',
+        method: 'post',
+        data: formData
+    })
 }

+ 7 - 1
src/router/index.ts

@@ -80,7 +80,13 @@ const router = new VueRouter({
           path: "/AIDesign/diagnoseResult",
           component: () => import("../views/AIDesign/diagnoseResult.vue"),
           meta: { requiresAuth: true } // 标记需要登录的页面
-        }
+        },
+        // 生成方案
+        {
+          path: "/AIDesign/GeneratePlan",
+          component: () => import("../views/AIDesign/GeneratePlan.vue"),
+          meta: { requiresAuth: true }
+        },
       ]
     },
   ]

+ 506 - 0
src/views/AIDesign/GeneratePlan.vue

@@ -0,0 +1,506 @@
+<template>
+    <div class="generate-plan-page 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="#333" size="26" />
+                </template>
+            </van-nav-bar>
+        </div>
+
+        <!-- 已生成方案区域 -->
+        <div class="generated-section">
+            <div class="generated-header">
+                <div class="generated-title">已生成</div>
+                <div>
+                    <div class="scheme-info"><span class="orgin-color">{{ stoneColors }}</span>{{ planParams.F_ColorCard
+                        }}</div>
+                    <span class="gray-color">|</span>
+                    <div class="scheme-process"><span class="orgin-color">{{ planParams.F_DeepGrooveTech }}</span>工艺
+                    </div>
+                </div>
+                <van-tag color="#FF8D1A" class="ai-tag">AI效果图</van-tag>
+            </div>
+
+            <!-- 效果图 -->
+            <div class="scheme-image">
+                <img :src="planParams.BaseUrl + planParams.F_ResultSmallFilePath" alt="房屋效果图"
+                    @click="imgClick(imageUrl)" />
+            </div>
+            <!-- 推荐方案区域 -->
+            <div class="recommend-scheme">
+                <h3 class="recommend-title">推荐方案</h3>
+
+                <div class="custom-table">
+                    <div class="table-header">
+                        <div class="table-cell" style="flex:0.8;">工序</div>
+                        <div class="table-cell" style="flex:1.6;">别墅之星系列</div>
+                        <div class="table-cell" style="flex:0.6;">使用量</div>
+                    </div>
+                    <div class="table-row" v-for="(item, index) in processData" :key="index">
+                        <div class="table-cell" style="flex:0.8;">{{ item.F_ProcedureName }}</div>
+                        <div class="table-cell" style="flex:1.6;">{{ item.F_ProductName }}</div>
+                        <div class="table-cell" style="flex:0.6;">{{ item.usage }}{{ item.F_OrderUnit }}</div>
+                    </div>
+                </div>
+
+                <!-- 施工面积 -->
+                <div class="construction-area">
+                    <h3>施工</h3>
+                    <div class="construction-info">
+                        <span>主色面积</span>
+                        <div @click="openAreaPopup">
+                            <span class="area-value">{{ mainArea }} </span>
+                            ㎡
+                            <van-icon name="arrow" size="12" />
+                        </div>
+
+
+                    </div>
+                </div>
+
+                <!-- 提示语 -->
+                <div class="notice-bar">
+                    <span>该方案能有效还原意向效果</span>,快去看看吧~
+                </div>
+
+                <!-- 确认按钮 -->
+                <van-button class="confirm-btn" color="#E87838" block @click="confirmScheme">
+                    确认方案 去下单
+                </van-button>
+            </div>
+        </div>
+
+        <!-- 面积输入弹窗 -->
+        <van-popup v-model="areaPopupShow" round position="bottom" :style="{ height: '150px', width: '100%' }"
+            class="area-popup">
+            <!-- 弹窗内容容器:Flex垂直布局,高度100% -->
+            <div class="popup-content">
+                <h3 class="popup-title">面积</h3>
+                <div class="popup-c">
+                    <p class="popup-desc">请输入主色施工面积</p>
+                    <van-field ref="areaField" type="tel" @input="onNativeInput" class="custom-field"
+                        v-model="inputArea" placeholder="输入面积㎡" :maxlength="maxLength" @keyup.enter="confirmInput"
+                        @blur="confirmInput" />
+                </div>
+            </div>
+        </van-popup>
+    </div>
+</template>
+
+<script lang="ts">
+import Vue from 'vue';
+import { Component, Ref } from 'vue-property-decorator';
+import { getWecomType, toLBHome, toXiaoChengxu, getWxconfig ,getWecomTypeName} from '@/utils/index';
+import { Tag, Field, ImagePreview } from 'vant';
+import { GetProductInfo, GetDictList, AddTrackEvent ,GetOrderAddress } from "@/api/indexAI";
+Vue.use(Tag)
+@Component({
+    components: {}
+})
+export default class GeneratePlan extends Vue {
+    @Ref('areaField') private areaField!: Field;
+    // 工序数据(与原表格数据一致)
+    private processData = [];
+    private maxLength = 10;//面积最长位数
+    // 主色面积
+    private mainArea = '300';
+    // 面积输入弹窗显示状态
+    private areaPopupShow = false;
+    // 输入的面积
+    private inputArea = '';
+    private planParams = {};
+    // 数字键盘显示状态(核心:控制键盘自动弹出)
+    private showKeyboard = false;
+    private imageUrl = ''; // 替换为实际图片路径
+    private stoneColors = '';
+    created() {
+    }
+
+    activated() {
+        this.initialize();
+        this.getPicList();
+        let planParams = sessionStorage.getItem("planParams");
+        if (planParams) {
+            this.planParams = JSON.parse(planParams)
+            const high_Definition_img = this.planParams.F_ResultFilePath || this.planParams.F_ResultlargeFilePath || this.planParams.F_ResultSmallFilePath;
+            this.imageUrl = this.planParams.BaseUrl + high_Definition_img;
+            this.GetProductInfoFn()
+        }
+    }
+
+    private initialize() {
+        this.processData = [];
+        this.mainArea = '300';
+        this.areaPopupShow = false;
+        this.inputArea = '';
+        this.planParams = {};
+        this.showKeyboard = false;
+    }
+    // 推荐方案
+    private GetProductInfoFn() {
+        let that = this;
+        const formData = new FormData();
+        formData.append('colorCard', that.planParams.F_ColorCard);
+        formData.append('deepGrooveTech', that.planParams.F_DeepGrooveTech);
+        GetProductInfo(formData).then(response => {
+            if (response.StatusCode == 200 && response.Data.length > 0) {
+                let resData = that.processResData(response.Data, that.mainArea);
+                that.processData = resData;
+            } else {
+                that.$toast(`${response.Info}`);
+            }
+        })
+    }
+    //获取电子色卡
+    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', 0);//必填 0外墙 1内墙
+        const agentFrom = window.localStorage.getItem('agentFromAI');
+        const wecomType = getWecomType(agentFrom);
+        formData.append('wecomType', wecomType);
+        GetDictList(formData).then(response => {
+            if (response.StatusCode == 200) {
+                if (response.Data && response.Data.dict) {
+                    // 仿石漆电子色卡选项
+                    let stoneColors_option = response.Data.dict.ColorCard;
+                    const targetItem = stoneColors_option.find(item => item.value === that.planParams.F_ColorCard);
+                    that.stoneColors = targetItem ? targetItem.text : '';
+                }
+            }
+        });
+    }
+    // 处理数据的函数
+    private processResData(data, area) {
+        return data.map(item => {
+            // 计算usage值:inputArea * F_UsagePerSqM / F_PackagingQuantity
+            const usageValue = area * item.F_UsagePerSqM / item.F_PackagingQuantity;
+            // 向上取整
+            const usage = Math.ceil(usageValue);
+            return {
+                ...item,
+                usage: usage // 新增的使用量属性
+            };
+        });
+    }
+
+    // 打开面积输入弹窗
+    private openAreaPopup() {
+        this.inputArea = this.mainArea;
+        this.areaPopupShow = true;
+        this.showKeyboard = true; // 显示数字键盘
+        this.$nextTick(() => {
+            // 输入框自动获取焦点(可选,增强交互)
+            (this.areaField as any).focus();
+        });
+    }
+
+
+    // 监听原生输入,限制最多10位
+    private onNativeInput(value: string) {
+        // 过滤非数字字符
+        const pureNum = value.replace(/\D/g, '');
+        // 长度校验
+        if (pureNum.length > this.maxLength) {
+            this.inputArea = pureNum.slice(0, this.maxLength);
+            this.$toast(`最多只能输入${this.maxLength}位数字`);
+        } else {
+            this.inputArea = pureNum;
+        }
+    }
+
+    // 确认输入(弹窗外的确认方案按钮可调用)
+    private confirmInput() {
+        const areaNum = Number(this.inputArea);
+        if (!isNaN(areaNum) && areaNum > 0) {
+            this.mainArea = this.inputArea;
+            this.areaPopupShow = false;
+            this.processData = this.processResData(this.processData, this.mainArea);
+        } else {
+            this.$toast('请输入主色施工面积');
+        }
+    }
+
+    // 确认方案
+    private confirmScheme() {
+        let that = this;
+        if (Number(this.mainArea) > 0) {
+            const formData = new FormData();
+            formData.append('eventname', '确认方案去下单');//事件名称
+            formData.append('eventtype', 'click');//事件类型
+            formData.append('menupath', '外墙质感/结果页/确认AI设计/确认方案去下单');//完整菜单路径
+            const eventdataObj = {
+                wecomType: getWecomTypeName(window.localStorage.getItem('agentFromAI')),
+                F_ColorCard: that.planParams.F_ColorCard,
+                F_DeepGrooveTech: that.planParams.F_DeepGrooveTech,
+                F_UserArea: that.mainArea,
+                F_ID: that.planParams.F_ID
+            };
+            formData.append('eventdata', JSON.stringify(eventdataObj));//事件数据
+            AddTrackEvent(formData)//埋点
+            // 获取确认下单地址
+            GetOrderAddress().then((res)=>{
+                if(res.StatusCode == 200 && res.Data){
+                    window.location.href = res.Data;
+                }else{
+                    if(res && res.Info){
+                        this.$toast(res.Info)
+                    }else{
+                        this.$toast("系统未知错误,请反馈给管理员.")
+                    }
+                }
+            })
+
+        } else {
+            this.$toast('请输入有效的主色施工面积');
+        }
+    }
+    imgClick(url) {
+        ImagePreview([url]);
+    }
+    returnPage() {
+        this.$router.back();
+    }
+    toHome() {
+        toLBHome()
+    }
+}
+</script>
+<style scoped lang="scss">
+.generate-plan-page {
+    background-color: #f5f5f5;
+    min-height: 100vh;
+    flex-direction: column;
+    padding-bottom: 20px;
+
+    .generated-section {
+        padding: 0 16px;
+
+        .generated-header {
+            margin-bottom: 4px;
+
+            .generated-title {
+                font-size: 22px;
+                font-weight: bold;
+                margin-right: 10px;
+                line-height: 34px;
+                padding-top: 5px;
+            }
+
+            .orgin-color {
+                color: rgba(255, 141, 26, 1);
+            }
+
+            .gray-color {
+                height: 14px;
+                color: rgb(166, 166, 166);
+                display: inline-block;
+                overflow: hidden;
+                margin: 0 4px;
+            }
+
+            .scheme-info,
+            .scheme-process {
+                font-size: 12px;
+                color: #000;
+                display: inline-block;
+            }
+
+            .ai-tag {
+                border-radius: 4px;
+                margin: 5px 0 3px;
+                padding: 1.5px 4px;
+            }
+        }
+
+        .scheme-image {
+            display: flex;
+            justify-content: center;
+            align-items: center;
+            margin-bottom: 15px;
+
+            img {
+                // width: 60%;
+                width: 100%;
+                height: auto;
+                border-radius: 8px;
+            }
+        }
+
+        .recommend-scheme {
+            background-color: #fff;
+            border-radius: 8px;
+            padding: 15px 10px;
+
+            .recommend-title {
+                font-size: 16px;
+                font-weight: bold;
+                margin-bottom: 10px;
+            }
+
+            // 自定义表格样式
+            .custom-table {
+                width: 100%;
+                border-radius: 4px;
+                overflow: hidden;
+                border: 1px solid #eee;
+
+                .table-header {
+                    display: flex;
+                    background-color: #f8f8f8;
+                    font-weight: bold;
+
+                    .table-cell {
+                        flex: 1;
+                        padding: 10px;
+                        text-align: center;
+                        font-size: 14px;
+                        border-right: 1px solid #eee;
+
+                        &:last-child {
+                            border-right: none;
+                        }
+                    }
+                }
+
+                .table-row {
+                    display: flex;
+                    border-bottom: 1px solid #eee;
+                    align-items: stretch;
+
+                    &:last-child {
+                        border-bottom: none;
+                    }
+
+                    .table-cell {
+                        display: flex;
+                        align-items: center;
+                        justify-content: center;
+                        flex: 1;
+                        padding: 10px;
+                        text-align: center;
+                        font-size: 12px;
+                        color: #333;
+                        word-break: break-all; // 文字换行
+                        border-right: 1px solid #eee;
+                        &:last-child {
+                            border-right: none;
+                        }
+                    }
+                }
+            }
+
+            .construction-area {
+                margin: 15px 0 0;
+                padding: 10px 0;
+                // border-top: 1px solid #eee;
+
+                .area-value {
+                    color: #e55b2a;
+                    font-weight: bold;
+                }
+
+                h3 {
+                    font-size: 16px;
+                    font-weight: bold;
+                }
+
+                .construction-info {
+                    display: flex;
+                    justify-content: space-between;
+                    align-items: center;
+                    margin-top: 10px;
+
+                }
+            }
+
+            .notice-bar {
+                height: 30px;
+                margin: 10px 0 0;
+                padding-bottom: 22px;
+                position: relative;
+                bottom: -22px;
+                border-radius: 14px 14px 0 0;
+                line-height: 30px;
+                color: #000000;
+                font-size: 12px;
+                background: linear-gradient(180deg, #F6F2B5 0%, #F9F3D8 100%);
+
+                span {
+                    padding-left: 15px;
+                    color: #FF8D1A;
+                    font-weight: bold;
+                }
+            }
+
+            .confirm-btn {
+                padding: 16px;
+                background-color: #E96337;
+                border: none;
+                border-radius: 30px;
+                color: white;
+                font-weight: 600;
+                cursor: pointer;
+                transition: all 0.2s ease;
+                text-align: center;
+                min-width: 90%;
+            }
+        }
+    }
+
+    // 弹窗样式
+    .area-popup {
+        padding: 0;
+        box-sizing: border-box;
+
+        .popup-content {
+            padding: 15px;
+            box-sizing: border-box;
+
+            .popup-title {
+                font-size: 20px;
+                font-weight: bold;
+                margin-bottom: 5px;
+            }
+
+            .popup-c {
+                display: flex;
+                flex-direction: column;
+                align-items: center;
+            }
+
+            .popup-desc {
+                color: #000;
+                margin-bottom: 5px;
+            }
+
+            .custom-field {
+                width: 150px;
+                margin: 0px auto;
+                text-align: center;
+
+                ::v-deep input {
+                    caret-color: #e55b2a;
+                    outline: none;
+                    pointer-events: auto;
+                    text-align: center;
+                    font-size: 18px;
+                    color: #e55b2a;
+                    font-weight: bold;
+                }
+            }
+        }
+    }
+}
+</style>

+ 62 - 16
src/views/AIDesign/diagnoseResult.vue

@@ -22,14 +22,9 @@
                     <img :src="canvasImg" alt="">
                 </div>
                 <!-- 诊断内容容器(用于生成图片) -->
-                <!-- <div class="diagnosis-container" ref="diagnosisRef" @touchstart="(e) => startLongPress(e, 'box')"
-                @touchend="endLongPress" @touchcancel="endLongPress" @mousedown="(e) => startLongPress(e, 'box')"
-                @mouseup="endLongPress" @mouseleave="endLongPress"> -->
                 <div class="diagnosis-container" ref="diagnosisRef">
                     <div class="diagnosis-img-box">
                         <img src="../../assets/AIDesign/diagnoseTit.png" class="diagnoseTitBg">
-                        <!-- <van-image class="diagnosis-image" :src="UserFilePathUrl" fit="contain" v-if="UserFilePathUrl"
-                            placeholder="加载中..." @click="imgClick(UserFilePathUrl)" id="diagnoseResultImg" /> -->
                         <img class="diagnosis-image" :src="UserFilePathUrl" v-show="UserFilePathUrl"
                             @click="imgClick(UserFilePathUrl)" style="object-fit: contain;" />
 
@@ -53,7 +48,6 @@
                             </h2>
                             <div class="content-item" v-for="(item, index) in wallInfo.surfaceConditions"
                                 :key="'surfaceConditions' + index">
-                                <!-- <span v-show="wallType === 'inside'">{{ index + 1 }}.</span> -->
                                 <p class="item-desc"> {{ item }}</p>
                             </div>
                         </div>
@@ -69,12 +63,12 @@
                         </div>
                         <!-- 外墙-解决方案 -->
                         <section v-if="wallType === 'outside'">
-                            <div class="diagnosis-box">
+                            <div class="diagnosis-box" v-if="wallInfo.Solutions">
                                 <h2>
                                     <van-icon name="play" color="#2484F2" size="24" class="triangle" />
                                     解决方案
                                 </h2>
-                                <div class="content-item" v-for="(item, index) in wallInfo.solutions"
+                                <div class="content-item" v-for="(item, index) in wallInfo.Solutions"
                                     :key="'solutions' + index">
                                     <h3 class="item-title">{{ numberToChinese(index + 1) }}、{{ item.name }}</h3>
                                     <div class="item-desc" v-for="(items, indexs) in item.solution"
@@ -84,6 +78,41 @@
                                     </div>
                                 </div>
                             </div>
+                            <div class="diagnosis-box" v-if="wallInfo.DetectionDetails">
+                                <h2>
+                                    <van-icon name="play" color="#2484F2" size="24" class="triangle" />
+                                    墙病诊断详情
+                                </h2>
+                                <div class="content-item content-item-detectionDetails"
+                                    v-for="(item, index) in wallInfo.DetectionDetails"
+                                    :key="'detectionDetails' + index">
+                                    <div class="reason-title">
+                                        <div class="reason-title-l">{{ index + 1 }}.{{ item.Name }} </div>
+                                    </div>
+                                    <section>
+                                        <!-- 原因分析 -->
+                                        <div class="detail-title">原因分析</div>
+                                        <div v-for="(cause, i) in item.Causes" :key="'causes' + i" :value="cause"
+                                            class="detail-item">
+                                            <van-icon name="location-o" />
+                                            {{ cause }}
+                                        </div>
+                                        <!-- 潜在危害 -->
+                                        <div class="detail-title">潜在危害</div>
+                                        <div v-for="(hazard, i) in item.Hazards" :key="'hazards' + i" :value="hazard"
+                                            class="detail-item hazard-item">
+                                            <van-icon name="warning-o"/>
+                                            {{ hazard }}
+                                        </div>
+                                        <!-- 修复工艺 -->
+                                        <div class="detail-title">推荐修复工艺</div>
+                                        <div class="detail-item" v-for="(items, indexs) in item.RepairProcesses"
+                                        :key="'RepairProcesses' + indexs">
+                                            {{ indexs + 1 }}.{{ items }}
+                                        </div>
+                                    </section>
+                                </div>
+                            </div>
                         </section>
                         <!-- 内墙-墙病诊断详情 -->
                         <section v-if="wallType === 'inside'">
@@ -97,11 +126,6 @@
                                     :key="'detectionDetails' + index">
                                     <div class="reason-title">
                                         <div class="reason-title-l">{{ index + 1 }}.{{ item.name }} </div>
-                                        <!-- <div class="confidence-badge">
-                                        <van-icon name="info-o" />
-                                        <span class="confidence-text">置信度: </span>
-                                        <span class="confidence-value">{{ (item.confidence * 100).toFixed(0) }}%</span>
-                                    </div> -->
                                     </div>
                                     <section>
                                         <!-- 原因分析 -->
@@ -188,9 +212,9 @@
 <script lang="ts">
 import { Component, Vue, Ref, Watch } from 'vue-property-decorator';
 import html2canvas from 'html2canvas';
-import { NavBar, Button, Image, Loading, Empty, Toast, ImagePreview } from 'vant';
+import { NavBar, Button, Image, Loading, Empty, Toast, ImagePreview, Tag } from 'vant';
 import { diagGetEntity, diagGetReadState, diagUpdateReadState } from "@/api/indexAI";
-import { getWecomType, toLBHome,getWxconfig } from '@/utils/index';
+import { getWecomType, toLBHome, getWxconfig } from '@/utils/index';
 import axios from "axios";
 declare let wx: any;
 @Component({
@@ -200,7 +224,8 @@ declare let wx: any;
         VanImage: Image,
         VanLoading: Loading,
         VanEmpty: Empty,
-        VanToast: Toast
+        VanToast: Toast,
+        VanTag: Tag
     }
 })
 export default class DiagnosisPage extends Vue {
@@ -547,6 +572,16 @@ export default class DiagnosisPage extends Vue {
 </script>
 
 <style scoped lang="scss">
+.van-tag {
+    margin-left: 34px;
+    font-size: 14px;
+    padding: 3px 10px 4px;
+}
+
+.margin-top-10 {
+    margin-top: 10px;
+}
+
 .diagnosis-page {
     background-color: #f8f9fa;
     min-height: 100vh;
@@ -701,6 +736,10 @@ export default class DiagnosisPage extends Vue {
                         color: #696868;
                         padding: 0 10px;
                     }
+
+                    .items-desc1 {
+                        color: #333;
+                    }
                 }
 
                 .content-item-detectionDetails {
@@ -851,6 +890,13 @@ export default class DiagnosisPage extends Vue {
 
         }
 
+        h5 {
+            font-size: 15px;
+            font-weight: bold;
+            color: #333;
+            margin-bottom: 6px;
+        }
+
         ul {
             padding-top: 20px;
             font-size: 14px;

+ 2 - 2
src/views/AIDesign/index.vue

@@ -56,7 +56,7 @@
       <!-- 我要设计 -->
       <div class="card card-design" @click="handleDesignClick('inside')">
         <div class="card-content">
-          <div class="card-title" style="color: #512E79;">我要设计 震撼上线!</div>
+          <div class="card-title" style="color: #512E79;">我要设计</div>
           <div class="card-desc" style="color: #7F639E;">AI在线生图,快速预览效果</div>
         </div>
         <div class="card-icon">
@@ -67,7 +67,7 @@
       <!-- 一键诊断 -->
       <div class="card card-diagnosis" @click="handleDiagnosisClick('inside')">
         <div class="card-content">
-          <div class="card-title" style="color: #2F655B;">一键诊断 震撼上线!</div>
+          <div class="card-title" style="color: #2F655B;">一键诊断</div>
           <div class="card-desc" style="color: #6D9587;">AI诊断墙面问题,提供解决方案</div>
         </div>
         <div class="card-icon">

+ 156 - 51
src/views/AIDesign/result.vue

@@ -39,13 +39,45 @@
         </div>
       </div>
 
-      <!-- 保存按钮 -->
-      <!-- <button class="save-button" :disabled="!imageUrl" :class="{ 'save-button-disabled': !imageUrl }"
-        @click="saveImageToAlbum">保存图片</button> -->
-
       <!-- 功能按钮组 -->
-      <div class="button-group">
-        <!--<button class="action-button" :disabled="!imageUrl" :class="{ 'save-button-disabled': !imageUrl }"-->
+      <!-- 外墙 -->
+      <div class="button-group-outside" v-if="wallType === 'outside'">
+        <button class="action-button-big flex-center" @click="handleAIfun"
+          v-if="agentFrom === 'stoneLikePaint' && allRes && allRes.F_DesignStyle != 'CHANGE_COLOR'">
+          <img src="@/assets/AIDesign/file-excel-2-line.png" class="icon" />
+          <div>
+            <div class="title">确认AI设计</div>
+            <div class="text">生成解决方案</div>
+          </div>
+        </button>
+        <div class="flex-between">
+          <button class="action-button-middle flex-center" :disabled="regenerateDisable"
+            :class="regenerateDisable == true ? 'save-button-disabled' : ''" @click="regenerate">
+            <!-- <van-icon class="icon" name="replay" /> -->
+            <img src="@/assets/AIDesign/resetIcon.png" class="icon" />
+            <div>
+              <div class="title">重新生成</div>
+              <div class="text">再来一次也不错</div>
+            </div>
+          </button>
+          <button class="action-button-middle flex-center" @click="viewHistory">
+            <!-- <van-icon class="icon" name="clock-o" /> -->
+            <img src="@/assets/AIDesign/historyIcon.png" class="icon" />
+            <div>
+              <div class="title">历史生图
+                <!-- <span v-if="!readState" class="badge-dot"></span> -->
+              </div>
+              <div class="text">保留每一张</div>
+            </div>
+          </button>
+        </div>
+        <!-- 服务商随身邦和部分经销商展示转人工  :disabled="projectDisableFlag" :class="projectDisableFlag == true ? 'save-button-disabled' : ''"-->
+        <div class="action-button-small" v-if="showArtificial && !projectDisableFlag" @click="manualDesign">
+          <span class="text">转人工设计</span>
+        </div>
+      </div>
+      <!-- 内墙 -->
+      <div class="button-group" v-if="wallType === 'inside'">
         <button class="action-button" :disabled="regenerateDisable"
           :class="regenerateDisable == true ? 'save-button-disabled' : ''" @click="regenerate">
           <van-icon class="icon" name="replay" />
@@ -56,22 +88,16 @@
           <span class="text">历史生图</span>
           <span v-if="!readState" class="badge-dot"></span>
         </button>
-        <!-- 服务商随身邦和部分经销商展示转人工 -->
-        <button class="action-button" @click="manualDesign" v-if="showArtificial" :disabled="projectDisableFlag"
-          :class="projectDisableFlag == true ? 'save-button-disabled' : ''">
-          <van-icon class="icon" name="user-o" />
-          <span class="text">转人工设计(原别墅之星小程序)</span>
-        </button>
       </div>
-    </div>
 
+    </div>
   </div>
 </template>
 <script lang="ts">
 import { ImagePreview, Dialog } from 'vant';
 import { Component, Vue } from "vue-property-decorator";
-import { GetEntity, GetReadState, UpdateReadState, insideGetEntity, insideGetReadState, insideUpdateReadState, GetProjectlist, GetDictList } from "@/api/indexAI";
-import { getWecomType, toLBHome, toXiaoChengxu, getWxconfig } from '@/utils/index';
+import { GetEntity, GetReadState, UpdateReadState, insideGetEntity, insideGetReadState, insideUpdateReadState, GetProjectlist, GetDictList, AddTrackEvent } from "@/api/indexAI";
+import { getWecomType, toLBHome, toXiaoChengxu, getWxconfig ,getWecomTypeName } from '@/utils/index';
 import axios from "axios";
 declare let wx: any;
 @Component
@@ -120,6 +146,7 @@ export default class extends Vue {
   private isNeedProjectFlag = true;//是否需要项目-接口获取
   private projectDisableFlag = true;//转人工不可点击
   private serviceCodeArray = [];
+  private allRes = null;
   created() {
     if (this.$route.query.WecomType) {
       sessionStorage.setItem("WecomType", this.$route.query.WecomType);
@@ -146,7 +173,7 @@ export default class extends Vue {
     //   this.showArtificial = true;
     // }
     // 从经销商随身邦进入的,显示转人工按钮,没有次数限制
-    if (this.agentFrom === 'ssb' && this.wallType === 'outside') {
+    if ((this.agentFrom === 'ssb' || this.agentFrom === 'dg') && this.wallType === 'outside') {
       this.showArtificial = true;
       this.projectDisableFlag = false;
     }
@@ -182,6 +209,7 @@ export default class extends Vue {
     this.isNeedProjectFlag = true;
     this.projectDisableFlag = true;
     this.showArtificial = false;
+    this.allRes = null;
   }
   // 是否关联了项目
   getIsNeedProjectFlag() {
@@ -320,6 +348,7 @@ export default class extends Vue {
             that.startPolling();
           }, that.designTimer[that.wallType]);
         } else {
+          this.allRes = response.Data;
           this.StateCode = response.Data.StateCode;
           this.StateInfo = response.Data.Description;
           this.projectId = response.Data.ProjectID;
@@ -367,6 +396,7 @@ export default class extends Vue {
       // console.log(response);
       if (response.StatusCode == 200) {
         if (response.Data) {
+          this.allRes = response.Data;
           this.StateCode = response.Data.StateCode;
           this.StateInfo = response.Data.Description;
           this.F_OutsideType = response.Data.F_OutsideType;
@@ -544,7 +574,15 @@ export default class extends Vue {
 
   private manualDesign(): void {
     let that = this;
-    // debugger
+    const formData = new FormData();
+    formData.append('eventname', '转人工设计');//事件名称
+    formData.append('eventtype', 'click');//事件类型
+    formData.append('menupath', '外墙质感/结果页/转人工设计');//完整菜单路径
+    const eventdataObj = {
+      wecomType: getWecomTypeName(window.localStorage.getItem('agentFromAI')),
+    };
+    formData.append('eventdata', JSON.stringify(eventdataObj));//事件数据
+    AddTrackEvent(formData)//埋点
     // console.log('转人工设计');
     // 实现转人工设计逻辑
     // that.$magnetlogadd.setLog('AI外墙设计-转人工设计', function () {
@@ -607,7 +645,7 @@ export default class extends Vue {
           padding: 0 5px;
           height: 17px;
           line-height: 17px;
-          border-radius: 32px;
+          border-radius: 4px;
           font-size: 10px;
         }
       }
@@ -617,6 +655,7 @@ export default class extends Vue {
 
         .tit {
           background: rgba(204, 204, 204, 1);
+
         }
       }
 
@@ -625,7 +664,7 @@ export default class extends Vue {
 
         .tit {
           color: #fff;
-          background: rgba(244, 155, 125, 1);
+          background: #FF8D1A;
         }
       }
     }
@@ -746,48 +785,114 @@ export default class extends Vue {
 /* .save-button:hover {
   background-color: #e04a1d;
 } */
+.button-group-outside {
+  .flex-center {
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    border: none;
+    margin-top: 10px;
+  }
+
+  .flex-between {
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    border: none;
+  }
+
+  .title {
+    font-size: 16px;
+    color: rgb(23, 23, 23);
+    font-weight: 600;
+    line-height: 16px;
+  }
+
+  .text {
+    font-size: 12px;
+    color: rgb(134, 144, 156);
+    line-height: 12px;
+    margin-top: 5px;
+  }
+
+  .icon {
+    width: 28px;
+    height: auto;
+    margin-right: 10px;
+  }
+
+  .action-button-big {
+    width: 100%;
+    height: 72px;
+    text-align: center;
+    border-radius: 8px;
+    background: rgba(248, 243, 204, 1);
+  }
+
+  .action-button-middle {
+    width: 48.5%;
+    height: 72px;
+    border-radius: 8px;
+    background: rgba(240, 240, 240, 1);
+  }
+
+  .action-button-small {
+    width: fit-content;
+    margin: 10px auto;
+    text-align: center;
+    text-decoration: underline;
+    font-size: 14px;
+    line-height: 18px;
+
+    .text {
+      font-size: 14px;
+      color: rgb(23, 23, 23);
+    }
+  }
+}
 
 .button-group {
   margin-top: 20px;
-}
 
-.action-button {
-  width: 100%;
-  padding: 14px;
-  margin-bottom: 12px;
-  background-color: white;
-  border: 1px solid #e0e0e0;
-  border-radius: 12px;
-  font-size: 15px;
-  color: #333;
-  cursor: pointer;
-  display: flex;
-  align-items: center;
-  justify-content: flex-start;
-  transition: background-color 0.3s ease;
-}
+  .action-button {
+    width: 100%;
+    padding: 14px;
+    margin-bottom: 12px;
+    background-color: white;
+    border: 1px solid #e0e0e0;
+    border-radius: 12px;
+    font-size: 15px;
+    color: #333;
+    cursor: pointer;
+    display: flex;
+    align-items: center;
+    justify-content: flex-start;
+    transition: background-color 0.3s ease;
+  }
 
-.action-button:hover {
-  background-color: #f5f5f5;
-}
+  .action-button:hover {
+    background-color: #f5f5f5;
+  }
 
-.badge-dot {
-  margin-left: 10px;
-  width: 5px;
-  height: 5px;
-  background-color: #ff4d4f;
-  border-radius: 50%;
-}
+  .badge-dot {
+    margin-left: 10px;
+    width: 5px;
+    height: 5px;
+    background-color: #ff4d4f;
+    border-radius: 50%;
+  }
 
-.icon {
-  margin-right: 10px;
-  font-size: 18px;
-}
+  .icon {
+    margin-right: 10px;
+    font-size: 18px;
+  }
 
-.text {
-  font-weight: 500;
+  .text {
+    font-weight: 500;
+  }
 }
 
+
 .van-nav-bar__title {
   font-size: 20px;
   color: #333;