YingXingAI/pages/my/fileAcc/fileAcc.vue

490 lines
13 KiB
Vue
Raw Normal View History

2025-06-30 14:43:02 +08:00
<template>
<view>
<u-navbar title="附件简历"></u-navbar>
<!-- 内容 -->
<view class="item-box" v-for="(x, xIndex) in fileList" :key="xIndex">
<view class="item-left">
<image
v-if="['pdf', 'PDF'].includes(x.type)"
style="width: 60rpx; height: 60rpx"
src="/static/common/img/pdf.svg"
/>
<image
v-else-if="['doc', 'docx', 'DOC', 'DOCX'].includes(x.type)"
style="width: 60rpx; height: 60rpx"
src="/static/common/img/word.svg"
/>
<image
v-else
style="width: 60rpx; height: 60rpx"
src="/static/common/img/img.svg"
/>
</view>
<view class="item-center" @click="downLoadFn(x)">
<view class="title-box" :class="x.isShow ? 'isShow' : ''">{{
x.resumeName
}}</view>
<view class="item-date">
<text>{{ x.size }}MB</text>
<text>上传于 {{ x.createTime }}</text>
</view>
</view>
<view class="item-right" @click="sheetFn(x)">
<image style="width: 30rpx; height: 30rpx" src="/static/common/img/sheet.svg" />
</view>
<!-- 定位盒子 -->
<!-- <view class="show-box" v-if="x.isShow">展示</view> -->
</view>
<!-- 空内容 -->
<view v-if="!fileList.length" style="padding-top: 100rpx">
<no-data type="resume" text="当前暂无附件简历">
</no-data>
</view>
<!-- 占位 -->
<view style="height: 20rpx"></view>
<!-- 按钮 -->
<view class="btn-box" @click="selectFn">
去添加
<!-- <u-button
style="width: 254rpx"
shape="square"
type="primary"
:loading="loading"
@click="selectFn"
>上传附件简历</u-button
> -->
</view>
<u-top-tips ref="uTips" :navbar-height="50"></u-top-tips>
<u-toast ref="uToast" />
<u-action-sheet
@click="sheetConfirm"
:list="list"
v-model="selectShow"
></u-action-sheet>
</view>
</template>
<script>
import NoData from '@/components/NoData.vue';
export default {
components: {
NoData
},
data() {
return {
action: "app/User/AddUserFile",
header: { Authorization: "" },
fileList: [],
queryParams: {
type: "add",
},
loading: false,
pathArr: [],
selectShow: false,
list: [
{
text: "设置为展示简历",
color: "#2979ff",
},
{
text: "删除",
color: "red",
},
],
currentRow: {},
};
},
onLoad(e) {
this.header.Authorization = "Bearer " + this.vuex_token;
Object.assign(this.queryParams, e);
},
onShow() {
this.getListFn();
},
created() {},
methods: {
sheetFn(x) {
this.currentRow = x;
this.selectShow = true;
},
sheetConfirm(val) {
console.log(val, "val*--");
// 设置为展示简历
if (val === 0) {
this.setFileFn(this.currentRow);
}
// 删除
if (val === 1) {
this.deleteFn(this.currentRow);
}
},
async getListFn() {
const req = {
userId: this.vuex_user.id,
};
// 待审核
const res = await this.$u.apiList.GetUserFileApi(req);
console.log(res, "res--");
this.fileList = res
.map((x) => {
//添加一个类型
x.type = x.url.split(".").at(-1);
return x;
})
.sort((a, b) => {
//根据时间排序
let dateA = new Date(a.createTime);
let dateB = new Date(b.createTime);
return dateB - dateA;
})
.sort((a, b) => {
//true的显示最上方
if (a.isShow) {
return -1;
}
return 0;
});
},
// 设置为展示简历
async setFileFn(row) {
const req = {
id: row.id,
};
const res = await this.$u.apiList.UpdateUserFileApi(req);
/* uni.showToast({
title: "设置成功",
duration: 1000,
}); */
this.$refs.uToast.show({
title: "设置成功",
type: "success",
});
setTimeout(() => {
this.getListFn();
}, 1000);
},
// 删除
deleteFn(row) {
uni.showModal({
// title: "提示",
content: `确定删除此附件?`,
success: async (res) => {
if (res.confirm) {
const req = {
id: row.id,
};
const res = await this.$u.apiList.DelUserFileApi(req);
console.log(res, "res--");
/* uni.showToast({
title: "删除成功",
duration: 1000,
}); */
this.$refs.uToast.show({
title: "删除成功",
type: "success",
});
setTimeout(() => {
this.getListFn();
}, 1000);
}
if (res.cancel) {
// console.log('用户点击取消');
}
},
});
},
// 选择文件
selectFn() {
// 最多上传5个文件
if (this.fileList.length > 4) {
/* uni.showToast({
icon: "none",
title: "最多上传五个附件简历",
duration: 2000,
}); */
this.$refs.uToast.show({
title: "最多上传五个附件简历",
type: "error",
});
return;
}
// this.$refs.uUpload.selectFile();
let that = this;
const fileType = [
".doc",
".docx",
".jpg",
".png",
".pdf",
".DOC",
".DOCX",
".JPG",
".PNG",
".PDF",
];
uni.chooseFile({
count: 1,
extension: fileType,
success(res) {
// tempFilePath可以作为img标签的src属性显示图片
console.log(res, "res--");
// 限制文件类型
const someType = res.tempFiles.some((x) => {
console.log(x.name.split(".").at(-1));
const currentType = x.name.split(".").at(-1);
// console.log(currentType, "currentType");
return !fileType.includes("." + currentType);
});
if (someType) {
/* uni.showToast({
icon: "none",
title: "仅允许选择DOC、DOCX、JPG、PNG、PDF格式文件",
duration: 2000,
}); */
that.$refs.uToast.show({
title: "仅允许选择DOC、DOCX、JPG、PNG、PDF格式文件",
type: "error",
});
return;
}
// 限制文件个数
console.log(res.tempFilePaths.length, "res.tempFilePaths.length--");
if (res.tempFilePaths.length > 5) {
console.log("6666");
/* uni.showToast({
icon: "none",
title: "单次最多选择5个附件",
duration: 2000,
}); */
that.$refs.uToast.show({
title: "单次最多选择5个附件",
type: "error",
});
return;
}
// 限制文件大小
const someSize = res.tempFiles.some((x) => x.size > 1024 * 1024 * 20);
if (someSize) {
/* uni.showToast({
icon: "none",
title: "仅允许选择20M内大小文件",
duration: 2000,
}); */
that.$refs.uToast.show({
title: "仅允许选择20M内大小文件",
type: "error",
});
return;
}
// return
// 上传逻辑
that.pathArr = res.tempFilePaths;
res.tempFiles.forEach((x, xIndex) => {
that.uploadFn(x, xIndex);
});
},
});
},
// 上传
uploadFn(file, index) {
uni.showLoading({
title: "上传中",
});
uni.uploadFile({
url: this.$u.http.config.imgUrl + this.action,
filePath: this.pathArr[index],
name: "file",
header: this.header,
success: (res) => {
console.log(res, "res--成功");
this.getListFn();
},
fail: (e) => {
console.log("失败");
uni.hideLoading();
},
complete: (res) => {
console.log("完成");
uni.hideLoading();
},
});
},
// 下崽
downLoadFn(row) {
function stringToBase64(str) {
// 将字符串转换为二进制数据
var binary = window.atob(str);
var len = binary.length;
var bytes = new Uint8Array(len);
for (var i = 0; i < len; i++) {
bytes[i] = binary.charCodeAt(i);
}
// 将二进制数据转换为Base64字符串
return window.btoa(String.fromCharCode.apply(null, new Uint8Array(bytes)));
}
function urlToBase64(url) {
// 创建一个 Image 对象
var img = new Image();
img.crossOrigin = "Anonymous";
// 当图像加载完成时执行的函数
img.onload = function () {
var canvas = document.createElement("canvas");
canvas.width = img.width;
canvas.height = img.height;
var ctx = canvas.getContext("2d");
// 将图像绘制到画布上
ctx.drawImage(img, 0, 0);
// 将画布内容转换为 DataURLBase64 编码)
var base64 = canvas.toDataURL();
console.log(base64);
};
// 设置图像的源
img.src = url;
}
function base64Encode(str) {
try {
// 对于普通的 ASCII 字符串,直接使用 btoa 函数进行 Base64 编码
return btoa(str);
} catch (error) {
// 处理包含非 ASCII 字符的情况
let utf8Str = unescape(encodeURIComponent(str));
let binary = "";
for (let i = 0; i < utf8Str.length; i++) {
binary += String.fromCharCode(utf8Str.charCodeAt(i));
}
return btoa(binary);
}
}
const downUrl = this.$u.http.config.imgUrl + row.url.slice(1);
window.open(
"http://sl.vrgon.com:8012/onlinePreview?url=" +
encodeURIComponent(base64Encode(downUrl))
);
return;
console.log(downUrl, "downUrl--");
const a = document.createElement("a");
a.href = downUrl;
a.download = row.resumeName;
a.click();
return;
// 下载文件
const downloadFile = (url, downName) => {
const xhr = new XMLHttpRequest();
xhr.open("GET", url, true);
xhr.responseType = "blob";
xhr.onload = function () {
if (this.status === 200) {
const a = document.createElement("a");
const urlObj = window.URL || window.webkitURL;
const blob = new Blob([this.response], {
type: this.getResponseHeader("Content-Type"),
});
const url = urlObj.createObjectURL(blob);
a.href = url;
a.download = downName;
a.click();
}
};
xhr.send();
};
downloadFile(downUrl, row.resumeName);
return;
// 下载文件
uni.downloadFile({
url: downUrl,
success: (res) => {
if (res.statusCode === 200) {
// console.log("下载成功");
}
},
});
},
},
};
</script>
<style lang="scss" scoped>
.isShow {
color: #2979ff;
}
.title-box {
word-break: break-all;
display: -webkit-box; /* 使用弹性盒模型 */
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
}
// 按钮
.btn-box {
width: 254rpx;
height: 92rpx;
border-radius: 100rpx;
color: white;
font-size: 32rpx;
margin: 0 auto;
background: #3cb5fb;
text-align: center;
line-height: 90rpx;
box-shadow: 0 0 20rpx rgba(0, 0, 0, 0.3);
}
.item-box {
padding-left: 30rpx;
padding-right: 30rpx;
padding-top: 20rpx;
padding-bottom: 20rpx;
// border: 1px solid red;
background-color: white;
border-bottom: 1px solid #eef0f2;
display: flex;
position: relative;
.show-box {
position: absolute;
right: 10rpx;
top: 5rpx;
// transform: translateX(-50%);
color: #49cc90;
font-size: 20rpx;
transform: skewY(10deg);
// letter-spacing: 10rpx;
animation: breath 4s ease-in-out infinite;
}
@keyframes breath {
0% {
opacity: 0.5; /* 初始透明度较低,文字较淡 */
}
50% {
opacity: 1; /* 透明度达到最大,文字完全显示 */
}
100% {
opacity: 0.5; /* 回到初始透明度,文字再次变淡 */
}
}
.item-left {
display: flex;
justify-content: center;
align-items: center;
}
.item-center {
flex: 1;
padding-left: 30rpx;
padding-right: 30rpx;
font-size: 30rpx;
color: black;
word-break: break-all;
.item-date {
display: flex;
justify-content: space-between;
margin-top: 10rpx;
font-size: 25rpx;
color: #9e9e9e;
}
}
.item-right {
display: flex;
align-items: center;
}
}
</style>