490 lines
13 KiB
Vue
490 lines
13 KiB
Vue
|
<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);
|
|||
|
// 将画布内容转换为 DataURL(Base64 编码)
|
|||
|
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>
|