| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562 |
- <template>
- <div class="resout-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="#333" size="26" />
- </template>
- </van-nav-bar>
- </div>
- <div class="container">
- <van-button v-show="Object.keys(groupedImages).length > 0" class="selecBtn" size="small"
- @click="selectImage">
- {{ isLongPressing ? "取消" : "选择" }}
- </van-button>
- <!-- 图片列表 -->
- <div class="image-groups" v-if="Object.keys(groupedImages).length > 0">
- <div v-for="(group, date) in groupedImages" :key="date" class="image-group">
- <div class="group-header">{{ formatDate(date) }}</div>
- <div class="image-grid">
- <div v-for="image in group" :key="image.F_ID" class="image-item" @click="toResultPage(image)">
- <div v-if="image.StateCode == 2" class="result-image-box">
- <van-image lazy-load :src="image.F_UserFilePath" class="house-image" alt="AI设计图"
- fit="cover" radius="5px" />
- <p class="WallFinishing" v-if="image.F_WallFinishing">{{ image.F_WallFinishing }}</p>
- <p class="WallFinishing"
- v-else-if="image.WallRepairAnalysis && image.WallRepairAnalysis.wallFinishing">{{
- image.WallRepairAnalysis.wallFinishing }}</p>
- </div>
- <div v-else class="loading-state">
- <img v-if="image.StateCode != 3 && image.StateCode != 4"
- src="@/assets/AIDesign/loding.gif" style="width: 50px;">
- <p class="loading-text" v-if="image.StateCode == 3 || image.StateCode == 4">生成失败</p>
- <p class="loading-text" v-else>图片正在生成中</p>
- </div>
- <div class="select-indicator" v-if="isLongPressing && image.StateCode == 2">
- <div class="select-indicator-circle">
- <span v-if="selectedImages.includes(getImageIndex(image))"
- class="icon-select selected"></span>
- </div>
- </div>
- </div>
- </div>
- </div>
- </div>
- <!-- 加载状态 -->
- <div v-if="isLoadingMore" class="loading-more">
- <van-loading size="20px" />
- <span class="loading-text">加载更多...</span>
- </div>
- <van-empty v-else-if="!isLoding && Object.keys(groupedImages).length === 0">
- <p>暂无数据</p>
- </van-empty>
- <!-- 已加载全部数据提示 -->
- <div v-if="!hasMore && !isLoding && Object.keys(groupedImages).length !== 0" class="load-all">
- 已加载全部数据
- </div>
- <!-- 删除按钮 -->
- <button class="delete-button" @click="deleteImage" v-if="selectedImages.length > 0">
- 删除图片({{ selectedImages.length }})
- </button>
- </div>
- </div>
- </template>
- <script lang="ts">
- import { Component, Vue } from "vue-property-decorator";
- import { diagGetDesignList, diagDeleteEntity } from "@/api/indexAI";
- import { Lazyload, Loading } from 'vant';
- import { toLBHome } from '@/utils/index';
- Vue.use(Lazyload);
- Vue.use(Loading);
- interface ImageItem {
- F_ID: string;
- BaseUrl: string;
- F_ResultFilePath: string;
- CreateDate: string;
- StateCode: number;
- }
- @Component
- export default class Resout extends Vue {
- private images: ImageItem[] = [];
- private selectedImages: number[] = [];
- private pressTimer: number | null = null;
- private isLongPressing = false;
- private isLoding = true;
- // 分页参数
- private pagination = {
- rows: 10, // 每页加载10条,适合移动端
- page: 1, // 当前页码
- sidx: "CreateDate",
- sord: "desc",
- records: 0, // 总记录数
- total: 0 // 总页数
- };
- // 滚动加载相关状态
- private isLoadingMore = false; // 是否正在加载更多
- private hasMore = true; // 是否还有更多数据
- private isProcessing = false; // 防止重复加载的锁
- private wallType = '';
- activated() {
- // 初始化数据
- this.initialize();
- this.getDataInfioList();
- // 监听滚动事件
- window.addEventListener('scroll', this.handleScroll);
- }
- deactivated() {
- clearTimeout(this.pressTimer);
- this.pressTimer = null;
- // 移除滚动监听
- window.removeEventListener('scroll', this.handleScroll);
- }
- initialize() {
- clearTimeout(this.pressTimer);
- this.images = [];
- this.wallType = this.$route.query.wallType || 'outside';
- this.pagination.page = 1;
- this.selectedImages = [];
- this.pressTimer = null;
- this.isLongPressing = false;
- this.isLoding = true;
- this.isLoadingMore = false;
- this.hasMore = true;
- this.isProcessing = false; // 防止重复加载的锁
- }
- // 处理滚动事件
- private handleScroll() {
- // 防止重复触发加载
- if (this.isProcessing || !this.hasMore || this.isLoadingMore) return;
- // 获取滚动相关参数
- const scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop;
- const clientHeight = document.documentElement.clientHeight || window.innerHeight;
- const scrollHeight = document.documentElement.scrollHeight || document.body.scrollHeight;
- // 当滚动到距离底部200px时触发加载
- if (scrollTop + clientHeight >= scrollHeight - 200) {
- this.loadMoreData();
- }
- }
- // 加载更多数据
- private loadMoreData() {
- if (this.pagination.page >= this.pagination.total) {
- this.hasMore = false;
- return;
- }
- this.isProcessing = true;
- this.isLoadingMore = true;
- this.pagination.page += 1;
- // 延迟执行,优化用户体验
- setTimeout(() => {
- this.getDataInfioList(true);
- }, 300);
- }
- // 按日期分组逻辑
- get groupedImages(): Record<string, ImageItem[]> {
- if (!this.images || this.images.length === 0) return {};
- const groups: Record<string, ImageItem[]> = {};
- this.images.forEach(image => {
- const date = image.CreateDate.split('T')[0];
- if (!groups[date]) {
- groups[date] = [];
- }
- groups[date].push(image);
- });
- // 按日期倒序排列
- const sortedGroups: Record<string, ImageItem[]> = {};
- Object.keys(groups)
- .sort((a, b) => new Date(b).getTime() - new Date(a).getTime())
- .forEach(key => {
- sortedGroups[key] = groups[key];
- });
- return sortedGroups;
- }
- // 获取数据列表 - 支持加载更多
- getDataInfioList(isLoadMore = false): void {
- const userInfo: any = JSON.parse(window.localStorage.getItem("userInfoV1")!);
- // 0外墙 1内墙
- const Entrytype = this.wallType === 'inside' ? 1 : 0;
- const queryJson = {
- // WXuserid: userInfo.loginName,
- Entrytype
- };
- const formData = new FormData();
- formData.append("pagination", JSON.stringify(this.pagination));
- formData.append("queryJson", JSON.stringify(queryJson));
- diagGetDesignList(formData).then((res) => {
- if (res.StatusCode == 200) {
- // 加载更多时合并数据,否则替换数据
- this.images = isLoadMore ? [...this.images, ...res.Data.rows] : res.Data.rows;
- // 更新分页信息
- this.pagination.records = res.Data.records;
- this.pagination.total = res.Data.total;
- // 判断是否还有更多数据
- this.hasMore = this.pagination.page < this.pagination.total;
- } else {
- this.$toast.fail(res.Info);
- }
- // 重置加载状态
- this.isLoding = false;
- this.isLoadingMore = false;
- this.isProcessing = false;
- }).catch(() => {
- // 错误处理
- this.isLoding = false;
- this.isLoadingMore = false;
- this.isProcessing = false;
- this.$toast.fail('加载失败,请重试');
- });
- }
- // 其他原有方法保持不变...
- returnPage() {
- this.$router.push({ path: '/AIDesign/diagnose', query: { wallType: this.wallType } });
- }
- toHome() {
- toLBHome()
- }
- // 去结果页面
- toResultPage(image) {
- if (this.isLongPressing && image.StateCode == 2) {
- this.toggleSelect(this.getImageIndex(image));
- } else {
- this.$router.push({
- path: '/AIDesign/diagnoseResult',
- query: {
- F_id: image.F_ID,
- wallType: this.wallType
- }
- });
- }
- }
- getImageIndex(image: ImageItem): number {
- return this.images.findIndex((item: ImageItem) => item.F_ID === image.F_ID);
- }
- formatDate(dateString: string): string {
- const date = new Date(dateString);
- const today = new Date();
- const yesterday = new Date(today);
- yesterday.setDate(yesterday.getDate() - 1);
- if (date.toDateString() === today.toDateString()) {
- return '今天';
- }
- if (date.toDateString() === yesterday.toDateString()) {
- return '昨天';
- }
- if (date.getFullYear() === today.getFullYear()) {
- return `${date.getMonth() + 1}月${date.getDate()}日`;
- }
- return `${date.getFullYear()}年${date.getMonth() + 1}月${date.getDate()}日`;
- }
- selectImage() {
- this.selectedImages = [];
- this.isLongPressing = !this.isLongPressing;
- }
- handleTouchStart(index: number, event: Event): void {
- event.preventDefault();
- this.pressTimer = window.setTimeout(() => {
- this.isLongPressing = true;
- this.toggleSelect(index);
- }, 500);
- }
- handleTouchEnd(index: number): void {
- if (this.pressTimer) {
- clearTimeout(this.pressTimer);
- this.pressTimer = null;
- }
- if (!this.isLongPressing) {
- this.toggleSelect(index);
- } else {
- const F_ID = this.images[index].F_ID;
- this.$router.push({
- path: '/AIDesign/diagnoseResult',
- query: {
- F_id: F_ID,
- wallType: this.wallType
- }
- });
- }
- this.isLongPressing = false;
- }
- toggleSelect(index: number): void {
- const idx = this.selectedImages.indexOf(index);
- if (idx === -1) {
- this.selectedImages.push(index);
- } else {
- this.selectedImages.splice(idx, 1);
- }
- }
- saveImage(): void {
- this.selectedImages.forEach((index) => {
- if (index < 0 || index >= this.images.length) return;
- const image = this.images[index];
- if (!image) return;
- const imageUrl = image.BaseUrl + image.F_ResultFilePath;
- this.downloadImage(imageUrl, `ai-design-${image.F_ID}.png`);
- });
- }
- downloadImage(imageUrl: string, filename: string): void {
- fetch(imageUrl).then(response => response.blob()).then(blob => {
- const blobUrl = URL.createObjectURL(blob);
- const link = document.createElement('a');
- link.href = blobUrl;
- link.download = `ai-design-${new Date().getTime()}.png`;
- link.style.display = 'none';
- document.body.appendChild(link);
- link.click();
- document.body.removeChild(link);
- URL.revokeObjectURL(blobUrl);
- }).catch(error => {
- console.error('图片下载失败:', error);
- this.$toast.fail('图片下载失败');
- });
- }
- deleteImage(): void {
- const F_ids = this.selectedImages.map(index => this.images[index].F_ID);
- const formData = new FormData();
- formData.append("F_ids", JSON.stringify(F_ids));
- diagDeleteEntity(formData).then((res) => {
- if (res.StatusCode == 200) {
- this.$toast.success("删除成功");
- // 重新加载第一页数据
- this.pagination.page = 1;
- this.getDataInfioList();
- this.selectedImages = [];
- } else {
- this.$toast.fail(res.Info);
- }
- });
- }
- beforeDestroy() {
- if (this.pressTimer) {
- clearTimeout(this.pressTimer);
- }
- window.removeEventListener('scroll', this.handleScroll);
- }
- }
- </script>
- <style scoped lang="scss">
- /* 原有样式保持不变,增加以下样式 */
- // 加载更多样式
- .loading-more {
- display: flex;
- align-items: center;
- justify-content: center;
- padding: 20px 0;
- color: #666;
- .loading-text {
- margin-left: 8px;
- font-size: 14px;
- }
- }
- // 加载完成提示
- .load-all {
- text-align: center;
- padding: 15px 0;
- color: #999;
- font-size: 14px;
- }
- /* 其他原有样式... */
- .resout-container {
- background-color: #f8f9fa;
- min-height: 100vh;
- flex-direction: column;
- }
- .container {
- padding: 20px;
- position: relative;
- .selecBtn {
- font-size: 14px;
- width: 50px;
- position: absolute;
- right: 20px;
- top: 14px;
- border-radius: 8px;
- background-color: #2484F2;
- color: #fff;
- }
- }
- .image-groups {
- flex: 1;
- }
- .image-group {
- margin-bottom: 24px;
- }
- .group-header {
- font-size: 16px;
- font-weight: 500;
- color: #333;
- margin-bottom: 12px;
- padding-left: 8px;
- }
- .image-grid {
- display: grid;
- //grid-template-columns: repeat(2, 1fr);
- //gap: 16px;
- }
- .image-item {
- position: relative;
- cursor: pointer;
- margin-bottom: 20px;
- .result-image-box {
- display: flex;
- align-items: center;
- .house-image {
- height: 90px;
- width: 90px;
- margin-right: 16px;
- }
- .WallFinishing {
- flex: calc(100% - 100px);
- display: -webkit-box;
- -webkit-line-clamp: 3;
- -webkit-box-orient: vertical;
- overflow: hidden;
- text-overflow: ellipsis;
- }
- }
- }
- .loading-state {
- width: 90px;
- height: 90px;
- display: flex;
- flex-direction: column;
- align-items: center;
- justify-content: center;
- color: #666;
- text-align: center;
- background-image: url('../../assets/AIDesign/bg.png');
- background-size: 100% 100%;
- border-radius: 5px;
- }
- .loading-text {
- margin-top: 10px;
- font-size: 14px;
- color: white;
- line-height: 15px;
- font-size: 11px;
- }
- .select-indicator {
- position: absolute;
- top: 5px;
- left: 5px;
- }
- .select-indicator-circle {
- width: 24px;
- height: 24px;
- border-radius: 50%;
- background-color: #B2C4DB;
- display: flex;
- align-items: center;
- justify-content: center;
- }
- .icon-select {
- width: 10px;
- height: 10px;
- border-radius: 50%;
- display: flex;
- align-items: center;
- justify-content: center;
- }
- .icon-select.selected {
- background-color: #FFFFFF;
- }
- .delete-button {
- position: fixed;
- bottom: 20px;
- left: 5%;
- width: 90%;
- padding: 12px 16px;
- background-color: #E96337;
- border: none;
- border-radius: 12px;
- color: white;
- font-weight: 600;
- cursor: pointer;
- transition: all 0.2s ease;
- text-align: center;
- font-size: 16px;
- font-weight: normal;
- }
- .delete-button:active {
- transform: scale(0.98);
- }
- .header {
- border-bottom: 1px solid #f8f8f8;
- .van-nav-bar__title {
- font-size: 20px;
- color: #333;
- }
- .van-icon {
- font-size: 20px;
- color: #333 !important;
- }
- }
- </style>
|