pc网页版软测宝
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.

783 lines
33 KiB

12 months ago
<template>
<div :style="{ background: mydetails ? '#FFFFFF' : '#F4F5FA' }">
<div class="zxzx" @click="zixunClick">在线咨询</div>
<div :class="mydetails ? 'mycrowdbig' : 'crowdbig'">
<div style="display: flex; align-items: center; margin: 20px 0">
<div style="display: flex; align-items: center; width: 150px">
<div class="dvied"></div>
<div style="font-weight: bold; color: #333333; font-size: 18px; margin-left: 10px">任务详情</div>
</div>
</div>
<div style="display: flex; justify-content: space-between">
<div style="width: 850px">
<div
style="
background: #ffffff;
box-shadow: 0px 2px 8px 0px rgba(54, 61, 67, 0.1);
padding: 15px 0px;
"
>
<div style="padding: 0px 30px">
<div
style="
display: flex;
font-size: 35rpx;
font-weight: bold;
justify-content: space-between;
"
>
<p style="color: #333333">{{ task.project_name }}</p>
<p v-if="task.price == 0" style="color: #fd461a">面议</p>
<p v-else style="color: #fd461a">¥{{ task.price }}</p>
</div>
10 months ago
<div style="display: flex; flex-wrap: wrap">
12 months ago
<div class="tabone">
<span v-if="task.task_status == 0">竞标中</span>
<span v-if="task.task_status == 1">竞标成功</span>
<span v-if="task.task_status == 2">竞标失败</span>
</div>
<div
v-for="it in findLabelValueByProp(
tasktypelist,
task.test_type,
'dictValue',
'dictLabel',
).split(',')"
:key="it"
class="tabone"
10 months ago
style="background: #e8eef5; color: #525b65"
12 months ago
>
<span>{{ it }}</span>
</div>
10 months ago
<!-- 语言 -->
<template v-if="task.language">
<div class="tabone tabone1" v-for="it in task.language.split(',')" :key="it">
{{ it }}
</div>
</template>
12 months ago
</div>
</div>
<div style="width: 100%; height: 1px; background-color: #ebebeb; margin: 14px 0 19px 0"></div>
<div style="padding: 0px 30px">
<div style="color: #808080; font-size: 24rpx; margin: 36rpx 25rpx 0 25rpx">
<p v-if="task && task.create_time" style="margin-bottom: 10px">
发布日期{{ task.create_time.slice(0, 10) }}
</p>
<p style="margin-bottom: 10px">需要人数{{ task.need_person }}</p>
<p style="margin-bottom: 10px">项目周期{{ task.period }}</p>
<p style="margin-bottom: 10px">
驻场需求
<span v-if="task.onsite_type == 0"> 无需驻场</span>
<span v-if="task.onsite_type == 1"> 偶尔驻场</span>
<span v-if="task.onsite_type == 2"> 定期驻场</span>
</p>
<p style="margin-bottom: 10px">技能要求{{ task.tech_need }}</p>
<p style="margin-bottom: 10px">地域要求{{ task.area }}</p>
<!-- <p style='margin-bottom:10px'>竞标者要求
<span v-if='task.applicant_type==0'>个人测试者</span>
<span v-if='task.applicant_type==1'>认证测试公司</span>
<span v-if='task.applicant_type==2'>个人测试者/认证测试公司</span>
</p> -->
<!-- <p style='margin-bottom:10px'>需支持/适配的客户端网站</p>
<p>合作倾向希望与关键科技合作</p> -->
</div>
<div style="display: flex; align-items: center; width: 150px; margin-top: 30px">
<div class="dvied"></div>
<div style="font-weight: bold; color: #333333; font-size: 17px; margin-left: 10px">
需求描述
</div>
</div>
<p
v-if="task.project_desc"
v-html="task.project_desc"
style="color: #808080; line-height: 23px; font-size: 24rpx; white-space: pre-line"
></p>
<p v-else style="margin-left: 10px"></p>
<div style="display: flex; align-items: center; width: 150px; margin-top: 30px">
<div class="dvied"></div>
<div style="font-weight: bold; color: #333333; font-size: 17px; margin-left: 10px">
附件
</div>
</div>
<div style="display: flex; align-items: center; margin: 12px 0">
<img
style="width: 17px; height: 20px; margin-right: 5px"
src="/assets/crowd/upload.png"
alt=""
/>
<!-- <p style="color:#1578ED;font-size: 12px;"></p> -->
<p
@click="openurl(task.attachment)"
v-if="task.attachment"
style="color: #1578ed; font-size: 12px; cursor: pointer"
>
项目附件
</p>
<p v-else style="color: #1578ed; font-size: 12px"></p>
<!-- <p style="color:#1578ED;font-size: 12px;">项目附件.zip</p> -->
</div>
</div>
<div style="width: 100%; height: 1px; background-color: #ebebeb; margin: 14px 0 19px 0"></div>
<div style="display: flex; justify-content: end" v-if="task.task_status == 0">
<div
v-if="demtype == 1"
class="tabone"
style="margin-right: 30px; width: 85px; cursor: pointer; background: #909399"
>
已竞标
</div>
<div
v-else
@click="applyfor"
class="tabone"
style="margin-right: 30px; width: 85px; cursor: pointer"
>
竞标报名
</div>
</div>
<div style="display: flex; justify-content: end" v-else>
<div
class="tabone"
style="margin-right: 30px; width: 85px; cursor: pointer; background: #909399"
>
报名结束
</div>
</div>
</div>
<div
v-if="userprogramme && userprogramme.period"
style="
background: #ffffff;
box-shadow: 0px 2px 8px 0px rgba(54, 61, 67, 0.1);
padding: 15px 0px;
margin-top: 16px;
"
>
<div style="font-weight: bold; color: #333333; font-size: 17px; margin-left: 30px">
竞标方案
</div>
<div style="width: 100%; height: 1px; background-color: #ebebeb; margin: 14px 0 19px 0"></div>
<div
style="
font-size: 14px;
text-align: left;
color: #333333;
margin: 20px 0px;
line-height: 25px;
padding-left: 30px;
"
>
<p>竞标日期{{ userprogramme.apply_time.slice(0, 10) }}</p>
<p>竞标工期{{ userprogramme.period ? userprogramme.period + '天' : '无' }}</p>
<p>
竞标优势{{ userprogramme.competition_edge ? userprogramme.competition_edge : '无' }}
</p>
<p>
竞标附件
<span
@click="openurl(userprogramme.attachment)"
v-if="userprogramme.attachment"
style="color: #1578ed; cursor: pointer"
>项目附件</span
>
<span v-else style="margin-left: -3px"></span>
</p>
</div>
</div>
<div
style="
background: #ffffff;
box-shadow: 0px 2px 8px 0px rgba(54, 61, 67, 0.1);
padding: 15px 0px;
margin-top: 16px;
"
>
<div style="font-weight: bold; color: #333333; font-size: 17px; margin-left: 30px">
报名列表
</div>
<div style="width: 100%; height: 1px; background-color: #ebebeb; margin: 14px 0 19px 0"></div>
<div v-if="entrants.length > 0" style="display: flex; flex-wrap: wrap; margin-left: 30px">
10 months ago
<div v-for="(item, key) of entrants" :key="key" @click="gouserhome(item)" class="signst">
12 months ago
<img :src="item.avatar ? item.avatar : '/assets/home/defaultAva.jpg'" alt="" />
<p>{{ item.nick_name.slice(0, 1) }}**</p>
<div class="success" v-if="item.status != 0 && item.status != 2">
<img src="/assets/crowd/success.png" alt="" />
竞标成功
</div>
<div v-else class="success1"></div>
</div>
</div>
<div v-else style="color: #808080; margin-left: 30px"></div>
</div>
</div>
<div>
<div
style="
width: 330px;
background: #ffffff;
box-shadow: 0px 2px 8px 0px rgba(54, 61, 67, 0.1);
padding: 15px 0px;
text-align: center;
"
>
<div style="width: 76px; height: 76px; margin: 20px auto" @click="openCompanyReview">
<img
style="width: 76px; object-fit: contain; height: 76px"
:src="task.avatar ? task.avatar : '/assets/home/defaultAva.jpg'"
alt=""
/>
</div>
<p style="margin: -5px 0; font-size: 20px; color: #1a1a1a; font-weight: bold">
{{ task.company_name }}
</p>
<template v-if="task.commentsStar && task.commentsStar != 0">
<p style="font-size: 16px; color: #808080">
<span>评分</span>
11 months ago
<span style="color: #f38f0d; font-weight: 600">{{ task.commentsStar }} </span>
12 months ago
</p>
<div class="ratebox" style="display: flex; justify-content: center">
<el-rate v-model="task.commentsStar" disabled></el-rate>
</div>
</template>
11 months ago
<div
v-else
style="
font-weight: 500;
font-size: 16px;
color: #666666;
text-align: center;
margin-top: 20px;
"
>
暂无评分
</div>
12 months ago
<div style="height: 20px"></div>
<div style="width: 100%; height: 1px; background-color: #ebebeb; margin: 14px 0 19px 0"></div>
<div style="padding: 0 23px; text-align: left">
<div style="font-size: 12px">
<span style="color: #4d4d4d">企业简介</span>
<span style="color: #808080; line-height: 23px">{{ task.company_desc }}</span>
</div>
</div>
</div>
<!-- <div style="background: #FAFAFA;">
<div style="width:200px;margin: 0 auto;display: flex;justify-content: space-between;">
<div style="display: flex;flex-direction: column;align-items: center;margin:-8px 0 0px 0;">
<p style="color: #222121;font-size: 24px;font-weight: 800;">{{task.personal_app_count}}</p>
<p style="color: #808080;font-size: 16px;margin-top: -15px;">发包总数</p>
</div>
<div style="display: flex;flex-direction: column;align-items: center;margin:-8px 0 0px 0;">
<p style="color: #F98F31;font-size: 24px;font-weight: 800;">优秀</p>
<p style="color: #808080;font-size: 16px;margin-top: -15px;">综合评价</p>
</div>
</div>
</div> -->
</div>
</div>
</div>
<el-dialog
:title="diatitle"
:visible.sync="paydiaopen"
width="650px"
:close-on-click-modal="false"
append-to-body
class="paydialog"
>
<el-form
:model="biddingobj"
label-width="100px"
ref="biddingobj"
:rules="rules"
class="demo-ruleForm"
style="margin-top: 20px"
>
<el-form-item label="预算周期" prop="period">
<el-input v-model="biddingobj.period" max="1000" style="width: 90%" placeholder="请输入预算周期">
<i slot="suffix" style="font-style: normal; margin-right: 10px"></i>
</el-input>
</el-form-item>
<el-form-item label="竞标优势" prop="competitionEdge">
<el-input
maxlength="2800"
:row="6"
show-word-limit
type="textarea"
v-model="biddingobj.competitionEdge"
placeholder="请输入竞标优势"
style="width: 90%"
></el-input>
</el-form-item>
<el-form-item label="竞标附件">
<div style="text-align: left">
<nonimage-upload
v-model="biddingobj.attachment"
imageType="pdf|doc|docx|zip|rar"
:serverAddr="materialServerAddr"
fileName="实施结果"
:limit="1"
@setImgPath="setImgPath"
/>
</div>
</el-form-item>
<el-form-item>
<div class="facj" style="margin-left: 100px">
<div @click="sumbit('cancel')">取消</div>
<div @click="sumbit('determine')">确定</div>
</div>
</el-form-item>
</el-form>
</el-dialog>
<el-dialog :visible.sync="resultOpen" width="500px" :close-on-click-modal="false" append-to-body>
<div>
<p>竞标信息已提交竞标结果会通过网页站内消息通知</p>
<p>也可以扫码登录微信小程序关键测试宝实时查看站内消息通知</p>
<img style="width: 150px; height: 150px; margin-left: 150px" src="/assets/homepage/xcx.jpg" alt="" />
</div>
<span slot="footer" class="dialog-footer">
<el-button type="primary" @click="resultFn"> </el-button>
</span>
</el-dialog>
<companyReviewVue ref="companyReviewVue" :task="task" />
</div>
</template>
<script>
import { mapGetters } from 'vuex'
import { getById, claimTask, competitivetask } from '@/api/crowdsource/crowdsource'
import { applicantlist, onsiteTypelist, processStatuslist } from '@/const/dict/commondict'
import { findByvalue, findLabelValueByProp } from '@/util/util'
import { getInfo } from '@/api/system/login'
import NonimageUpload from '@/page/common/NonimageUpload'
import mixin from '@/mixin/index.js'
import companyReviewVue from '@/page/common/companyReview.vue'
11 months ago
import { gettesterId } from '@/api/tester/CompanyApply'
12 months ago
export default {
props: ['mydetails'],
mixins: [mixin],
data() {
return {
value: 5,
value1: 5,
resultOpen: false,
diatitle: '提交竞标方案',
paydiaopen: false,
// tasktypelist:[{name:'静态测试',id:'static'},{name:'功能测试',id:'function'},{name:'性能测试',id:'performance'},{name:'安全测试',id:'security'},
// {name:'配置项测试',id:'configuration'},{name:'可靠性测试',id:'reliability'}, {name:'研发任务',id:'development'},{name:'用人任务',id:'outsource'},{name:'其他',id:'other'}],
biddingobj: { taskId: '', applicantId: '', period: '', competitionEdge: '', attachment: [] },
task: {}, //基本信息
// company:{},//发布者信息
publisher: {},
onsiteTypelist, //驻场需求
applicantlist, //竞标者要求
processStatuslist, //任务状态
entrants: [], //竞争者名单
materialServerAddr: '',
demtype: '', //是否已经竞标
rules: {
period: [
{ required: true, message: '请输入预算周期', trigger: 'blur' },
{ max: 1000, message: '预算周期最多为1000', trigger: 'blur' },
{
pattern: /^[1-9]\d*$/,
message: '预算周期需填写正整数',
trigger: 'blur',
},
],
competitionEdge: [{ required: true, message: '请输入竞标优势', trigger: 'blur' }],
},
userprogramme: {},
10 months ago
baseurl: process.env.VUE_APP_BASE_TARGET,
10 months ago
base: process.env.VUE_APP_BASE_API,
12 months ago
}
},
components: {
NonimageUpload,
companyReviewVue,
},
computed: {
...mapGetters(['testtypelist', 'feescopelist', 'userinform', 'userId', 'token']),
},
mounted() {
let id = this.$route.query.id
getById(id, this.userId).then((response) => {
// console.log('任务信息:',response)
this.task = response.task
this.entrants = response.entrants
if (response.user_plan) {
this.userprogramme = response.user_plan
}
let currentis = null
if (this.entrants.length > 0) {
this.entrants.forEach((item) => {
if (this.userId == item.user_id) {
currentis = item
}
10 months ago
if (item.avatar && item.avatar.indexOf('http') == -1) {
10 months ago
item.avatar = this.base + item.avatar
}
12 months ago
})
}
if (currentis) {
// console.log('currentis---',currentis)
this.demtype = 1
}
// this.company = response.company;
})
10 months ago
// if (this.token) {
// getInfo().then((res) => {
// // console.log('用户信息',res)
// const user = res.user
// this.$store.commit('SET_USERINFORM', user)
// })
// }
12 months ago
// getApplicant(id).then(response => {
// console.log('竞标者名单',response)
// this.applicantdataList = response.data;
// })
},
methods: {
10 months ago
// 前往公司主页
gouserhome(item) {
10 months ago
if (!this.token) {
this.$confirm('您未登录,请登录后查看', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
})
.then(() => {
this.$router.push('/login?type=log')
})
.catch(() => {
// console.log('取消')
})
} else {
this.$router.push({
path: '/crowdsourcing/userhome',
query: { id: item.user_id, id2: this.$route.query.id },
})
}
10 months ago
},
12 months ago
// 打开公司评论信息
openCompanyReview() {
this.$refs.companyReviewVue.open = true
this.$refs.companyReviewVue.value = this.task.commentsStar
this.$refs.companyReviewVue.getList(this.task.publisher_id)
},
// 咨询点击
zixunClick() {
const bigbox = document.querySelector('#minidialog')
const x = document.querySelector('.closeX')
x.style.display = 'block'
bigbox.style.width = '300px'
bigbox.style.height = 'auto'
bigbox.style.display = 'block'
bigbox.style.bottom = '0'
bigbox.style.right = '0'
},
findByvalue,
findLabelValueByProp,
setImgPath(value) {
// console.log('vaa---',value)
if (value) {
this.biddingobj.attachment = value
}
},
openurl(url) {
this.$message.success('下载成功')
window.location.href = url
},
applyfor() {
if (!this.token) {
this.$confirm('您未登录,请您先去登录', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
})
.then(() => {
this.$router.push('/login?type=log')
})
.catch(() => {
// console.log('取消')
})
} else {
11 months ago
gettesterId(this.userId).then((res) => {
10 months ago
if (res.code == 200 && res.data.companyApplyId) {
return this.$message.warning('仅支持个人用户竞标报名')
}
11 months ago
if (res.code == 200 && res.data.applyId) {
if (res.data.applyId && res.data.status == 1) {
this.paydiaopen = true
10 months ago
this.biddingobj.status = res.data.status
12 months ago
} else {
11 months ago
this.$confirm('未实名认证用户无法报名,请先去个人中心做实名认证', '提示', {
type: 'warning',
confirmButtonText: '去实名认证',
}).then(() => {
this.$router.push(`/console/profile`)
})
12 months ago
}
11 months ago
} else {
10 months ago
this.$confirm('未实名认证用户无法报名,请先去个人中心做实名认证', '提示', {
type: 'warning',
confirmButtonText: '去实名认证',
}).then(() => {
this.$router.push(`/console/profile`)
})
12 months ago
}
11 months ago
})
12 months ago
}
},
resultFn() {
this.resultOpen = false
this.$nextTick(() => {
let id = this.$route.query.id
getById(id, this.userId).then((response) => {
// console.log('任务信息:',response)
this.task = response.task
this.entrants = response.entrants
if (response.user_plan) {
this.userprogramme = response.user_plan
}
let currentis = null
if (this.entrants.length > 0) {
this.entrants.forEach((item) => {
if (this.userId == item.user_id) {
currentis = item
}
10 months ago
if (item.avatar && item.avatar.indexOf('http') == -1) {
item.avatar = this.base + item.avatar
}
12 months ago
})
}
if (currentis) {
// console.log('currentis---',currentis)
this.demtype = 1
}
// this.company = response.company;
})
})
},
sumbit(type) {
if (type == 'cancel') {
this.paydiaopen = false
} else {
this.$refs['biddingobj'].validate((valid) => {
if (valid) {
if (parseInt(this.biddingobj.period) > 1000) {
this.$message.warning('预算周期最多为1000天')
}
let attachment = ''
if (this.biddingobj.attachment.length == 0) {
attachment = ''
} else {
10 months ago
attachment = this.baseurl + this.biddingobj.attachment
12 months ago
}
let data = {
taskId: this.task.task_id,
applicantId: this.userId,
period: parseInt(this.biddingobj.period),
competitionEdge: this.biddingobj.competitionEdge,
attachment,
10 months ago
status: this.biddingobj.status,
12 months ago
}
// console.log('竞标数据',data)
// return
competitivetask(data).then((res) => {
// console.log('res',res)
if (res.data.code == 200) {
this.paydiaopen = false
// this.$notify({
// title: '竞标成功',
// message: '竞标',
// align: 'center',
// type: 'success'
// });
this.resultOpen = true
// this.$alert("应征任务成功,请等待应征结果通知。")
// setTimeout(() => {
// this.$router.push("/console/myparticipate")
// },1000);
} else {
this.paydiaopen = false
this.$alert(res.data.msg)
// this.$refs.uToast.show({ title: res.data.msg, type: 'info'})
}
})
}
})
}
},
},
}
</script>
<style scoped>
/* 咨询 */
.zxzx {
z-index: 2147483639;
width: 180px;
height: 68px;
position: fixed;
right: 16px;
top: 600px;
font-weight: 500;
font-size: 17px;
color: #ffffff;
background: url('/assets/ability/zixun.gif');
background-size: 100% 100%;
line-height: 68px;
text-indent: 2em;
cursor: pointer;
}
.tabone {
10 months ago
padding: 0px 10px;
12 months ago
color: #ffffff;
background: #2286fa;
border-radius: 3px;
text-align: center;
10 months ago
/* width: 75px; */
12 months ago
margin-right: 8px;
line-height: 28px;
height: 28px;
font-size: 14px;
}
10 months ago
.tabone1 {
background: #fcf0e6;
border-radius: 4px;
font-weight: 500;
font-size: 14px;
color: #554c42;
}
12 months ago
.dvied {
width: 4px;
height: 18px;
background: #0066eb;
}
.release {
width: 159px;
height: 40px;
margin-left: 20px;
background: #fc5c1d;
box-shadow: 0px 1px 13px 0px rgba(12, 54, 110, 0.31);
border-radius: 4px;
font-size: 16px;
font-weight: bold;
color: #ffffff;
line-height: 40px;
text-align: center;
cursor: pointer;
}
.crofinf {
font-weight: bold;
color: #333333;
font-size: 16px;
/* position:absolute; */
margin: 0px 6px -18px 0px;
}
.taskname {
background: #f4f5fa;
padding: 10px 20px;
display: flex;
align-items: center;
margin: 12px 0;
height: 20px;
font-size: 14px;
}
.taskname p:nth-child(1) {
width: 85px;
}
.crowdbig {
width: 1200px;
margin: 0px auto;
padding: 30px 0;
}
.mycrowdbig {
width: 1200px;
margin: 0px auto;
padding: 30px 0;
}
@media screen and (max-width: 1500px) {
.crowdbig {
width: 1200px;
margin: 0px auto;
padding: 30px 0;
}
.mycrowdbig {
width: 1000px;
margin: 0px auto;
padding: 30px 0;
}
}
@media screen and (min-width: 1500px) and (max-width: 1560px) {
.crowdbig {
width: 1200px;
margin: 0px auto;
padding: 30px 0;
}
.mycrowdbig {
width: 1100px;
margin: 0px auto;
padding: 30px 0;
}
}
.signst {
display: flex;
flex-direction: column;
align-items: center;
margin: 10px;
}
.signst .success1 {
width: 88px;
height: 26px;
}
.signst .success {
width: 88px;
height: 26px;
background: #21b96c;
border-radius: 13px;
display: flex;
justify-content: center;
align-items: center;
font-weight: 500;
font-size: 14px;
color: #ffffff;
}
.signst .success img {
width: 12px;
height: 12px;
}
.signst img {
width: 40px;
height: 40px;
border-radius: 50%;
}
.signst p {
font-size: 11px;
margin-top: 5px;
}
.facj {
display: flex;
width: 220px;
margin: 50px auto 0 auto;
justify-content: space-between;
cursor: pointer;
}
.facj div {
width: 100px;
height: 34px;
background: #1472ec;
border-radius: 4px;
color: #ffffff;
font-size: 14px;
line-height: 34px;
text-align: center;
}
.ratebox >>> .el-rate__icon {
font-size: 30px !important;
}
</style>