You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

459 lines
10 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<template>
<view class="container">
<!-- 生成记录列表 -->
<view class="record-list">
<uv-swipe-action>
<uv-swipe-action-item @click="index => controlItem(index,record)" :options="options"
v-for="record in list" :key="record.ID">
<view class="record-item">
<!-- 记录信息 -->
<view class="record-info">
<view class="record-title">{{ record.file_name || record.order_no || record.plannedNo }}
</view>
<view class="record-time">
生成时间:
{{
record.CreatedAt
? dayjs(record.CreatedAt).format("YYYY-MM-DD HH:mm:ss")
: ""
}}
</view>
</view>
<!-- 状态标签 -->
<view class="status-tag" :class="{
completed: record.status == 4,
failed: record.status == 5,
waitting:record.status == 1
}">
<span v-if="record.status == 4">已完成</span>
<span v-else-if="record.status == 5">生成失败</span>
<span v-else-if="record.status == 1">等待生成</span>
<span v-else>生成中</span>
</view>
<!-- 操作按钮 -->
<view class="record-actions">
<uv-button v-if="record.status === 4" type="primary" size="small"
@click="downloadRecord(record)">
<uv-icon name="download" size="14" color="white" style="margin-right: 4px"></uv-icon>
下载
</uv-button>
<uv-button v-else type="info" size="small" disabled>
<uv-icon name="download" size="14" color="#aaa" style="margin-right: 4px"></uv-icon>
下载
</uv-button>
</view>
</view>
</uv-swipe-action-item>
</uv-swipe-action>
</view>
<!-- 空状态 -->
<view v-if="list.length === 0 && loadingStatus !== 'loading'" class="empty-state">
<uv-icon name="file-text" size="60" color="#ccc"></uv-icon>
<text class="empty-text">暂无生成记录</text>
</view>
<!-- 加载更多 -->
<uv-load-more v-else :status="loadingStatus" @loadmore="loadmore" />
<!-- 参数展示弹窗 -->
<uv-modal ref="paramsModalRef" title="生成参数" :showCancelButton="false" confirmText="确定">
<view class="params-modal-content">
<view v-if="currentParams.length === 0" class="no-params">
暂无参数信息
</view>
<view v-else class="params-list">
<view v-for="param in currentParams" :key="param.name" class="param-item">
<view class="param-name">{{ param.name }}</view>
<view class="param-value">{{ param.value || '' }}</view>
</view>
</view>
</view>
</uv-modal>
<!-- 投诉与纠纷 -->
<ComplaintFooter />
</view>
</template>
<script setup>
import {
ref,
onMounted
} from "vue";
import ComplaintFooter from "/components/ComplaintFooter/ComplaintFooter.vue";
import RPC from "@/utils/request";
import dayjs from "dayjs";
import {
onShow,
onPullDownRefresh,
onReachBottom
} from "@dcloudio/uni-app";
const options = ref([{
text: "参数",
style: {
backgroundColor: "#6eb0ea",
},
}, {
text: "删除",
style: {
backgroundColor: "#f56c6c",
},
}]);
const currentParams = ref([])
const showParamsModal = ref(false)
const paramsModalRef = ref(null)
const controlItem = (index, item) => {
console.log(index, item);
if (index.index === 0) {
// 显示参数弹窗
showParams(item);
} else {
deleteRecord(item);
}
};
// 显示参数弹窗
const showParams = (item) => {
if (item.template_data) {
currentParams.value = Object.entries(item.template_data).map(([key, value]) => ({
name: key,
value: value
}));
} else {
currentParams.value = [];
}
paramsModalRef.value.open();
};
// 响应式数据
const loading = ref(false);
const loadingStatus = ref("loadmore");
const page = ref(1);
const list = ref([]);
const count = ref(0);
// 下载记录
const downloadRecord = (record) => {
uni.showLoading({
title: "准备下载...",
});
// #ifdef H5
// H5端直接使用浏览器下载
const link = document.createElement("a");
link.href = record.result_url;
link.download = record.file_name || "download";
link.target = "_blank";
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
// downloadA(record.result_url, (record.file_name || record.plannedNo))
uni.hideLoading();
uni.showToast({
title: "开始下载",
icon: "success",
});
// uni.request({
// url:'/api/proxyDownload',
// data:{"name":record.file_name || record.plannedNo,url:record.result_url},
// method:'POST',
// responseType: 'arraybuffer',
// success:res => {
// const blob = new Blob([res.data], {
// type: 'application/pdf'
// })
// const base64 = res.data
// const iframe = document.createElement('iframe')
// iframe.style.display = 'none'
// iframe.src = `data:application/pdf;base64,${base64}`
// document.body.appendChild(iframe)
// // const url = URL.createObjectURL(blob)
// // const a = document.createElement('a')
// // a.href = url
// // a.download = record.file_name
// // a.click()
// // URL.revokeObjectURL(url)
// },
// complete:() => {
// uni.hideLoading();
// }
// })
// #endif
// #ifdef MP-WEIXIN
// 小程序和App端使用uni.downloadFile
uni.downloadFile({
url: record.result_url,
success: (res) => {
console.log(res);
if (res.statusCode === 200) {
uni.openDocument({
filePath: res.tempFilePath,
showMenu: true,
success: () => {
uni.hideLoading();
uni.showToast({
title: "下载成功",
icon: "success",
});
},
fail: () => {
uni.hideLoading();
uni.showToast({
title: "保存失败",
icon: "none",
});
},
});
} else {
uni.hideLoading();
uni.showToast({
title: "下载失败",
icon: "none",
});
}
},
fail: () => {
uni.hideLoading();
uni.showToast({
title: "下载失败",
icon: "none",
});
},
});
// #endif
};
// 删除记录
const deleteRecord = (record) => {
uni.showModal({
title: "确认删除",
content: "确定要删除这条生成记录吗?删除后无法恢复。",
success: (res) => {
if (res.confirm) {
RPC.post('/planned_delete', {
id: record.ID
}).then(() => {
list.value = list.value.filter((item) => item.ID !== record.ID);
uni.showToast({
title: "删除成功",
icon: "success",
});
})
// 从列表中移除记录
}
},
});
};
// 加载生成记录
const loadRecords = async () => {
uni.showLoading();
loadingStatus.value = "loading";
RPC.post("/planned_list", {
page: page.value,
page_size: 20
})
.then((res) => {
list.value = [...list.value, ...res.list];
count.value = res.total;
if (list.value.length >= count.value) {
loadingStatus.value = "nomore";
} else {
loadingStatus.value = "loadmore";
}
})
.catch(() => {
loadingStatus.value = "loadmore";
}).finally(() => {
uni.hideLoading();
});
};
// 刷新数据
onPullDownRefresh(() => {
list.value = [];
page.value = 1;
loadingStatus.value = "loading";
RPC.post("/planned_list", {
page: page.value,
page_size: 20
})
.then((res) => {
list.value = [...list.value, ...res.list];
count.value = res.total;
if (list.value.length >= count.value) {
loadingStatus.value = "nomore";
} else {
loadingStatus.value = "loadmore";
}
})
.catch(() => {
loadingStatus.value = "loadmore";
})
.finally(() => {
uni.stopPullDownRefresh();
});
});
onReachBottom(() => {
loadmore();
});
const loadmore = () => {
if (list.value.length >= count.value || loadingStatus.value === "loading")
return;
console.log("上拉加载:");
loadingStatus.value = "loading";
page.value = ++page.value;
loadRecords();
};
onShow(() => {
// 页面显示时刷新数据
list.value = [];
page.value = 1;
loadRecords();
});
</script>
<style lang="scss" scoped>
.container {
font-size: 14px;
min-height: 100vh;
background-color: #f8f8f8;
padding: 16px;
}
.record-list {
.record-item {
background: white;
border-radius: 12px;
padding: 16px;
margin-bottom: 12px;
display: flex;
align-items: center;
gap: 12px;
.record-info {
flex: 1;
overflow: auto;
.record-title {
width: 100%;
font-size: 16px;
color: #333;
font-weight: 500;
margin-bottom: 6px;
word-wrap: break-word;
white-space: normal;
}
.record-time {
font-size: 13px;
color: #999;
}
}
.status-tag {
flex-shrink: 0;
padding: 4px 8px;
border-radius: 4px;
font-size: 12px;
font-weight: 500;
background: #fff7e6;
color: #fa8c16;
&.completed {
background: #e8f5e8;
color: #52c41a;
}
&.failed {
background: #fff1f0;
color: #ff4d4f;
}
&.processing {
background: #fff7e6;
color: #fa8c16;
}
&.waitting {
background: #fff7e6;
color: #4ad6f1;
}
}
.record-actions {
display: flex;
align-items: center;
flex-shrink: 0;
}
}
}
.empty-state {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 80px 20px;
.empty-text {
color: #999;
font-size: 14px;
margin-top: 16px;
}
}
.load-more {
padding: 20px;
text-align: center;
}
.params-modal-content {
padding: 20px 0;
max-height: 400px;
overflow-y: auto;
.no-params {
text-align: center;
color: #999;
font-size: 14px;
padding: 20px 0;
}
.params-list {
.param-item {
display: flex;
align-items: flex-start;
padding: 12px 0;
border-bottom: 1px solid #f0f0f0;
&:last-child {
border-bottom: none;
}
.param-name {
flex-shrink: 0;
font-weight: 500;
color: #333;
font-size: 14px;
min-width: 80px;
margin-right: 12px;
}
.param-value {
flex: 1;
color: #666;
font-size: 14px;
word-wrap: break-word;
white-space: normal;
}
}
}
}
</style>