652 lines
17 KiB
JavaScript
652 lines
17 KiB
JavaScript
|
|
import { fetchDemandContractDetail, demandOperate } from '../../../services/demand/fetchDemand';
|
|
// pages/demand/contract/index.js
|
|
Page({
|
|
|
|
/**
|
|
* 页面的初始数据
|
|
*/
|
|
data: {
|
|
demandId: 0,
|
|
actualAccount: 0,
|
|
contract: null,
|
|
agreementUrl: '', // 签约条款URL
|
|
phoneError: '', // 个人联系电话错误提示
|
|
companyPhoneError: '', // 企业联系电话错误提示
|
|
// 附件上传
|
|
attachFiles: [],
|
|
attachMax: 5, // 最多上传5个附件
|
|
attachConfig: {
|
|
count: 5,
|
|
},
|
|
attachSizeLimit: {
|
|
size: 20, unit: 'MB', message: '附件大小不超过 {sizeLimit} MB'
|
|
},
|
|
gridConfig: {
|
|
column: 4,
|
|
width: 160,
|
|
height: 160,
|
|
},
|
|
formData: {
|
|
contractType: 'personal', // 默认选择个人签约
|
|
// 个人签约信息
|
|
name: '',
|
|
phone: '',
|
|
idCard: '',
|
|
// 企业签约信息
|
|
companyName: '',
|
|
legalPerson: '',
|
|
companyPhone: '',
|
|
// 开发信息
|
|
taskContent: '',
|
|
needDays: '',
|
|
totalCost: '',
|
|
attachFiles: [],
|
|
// 签约条款
|
|
agreementChecked: false
|
|
}
|
|
},
|
|
|
|
/**
|
|
* 生命周期函数--监听页面加载
|
|
*/
|
|
onLoad(options) {
|
|
// 设置签约条款URL(进行编码)
|
|
const source = options?.source;
|
|
const demandId = options?.demandId;
|
|
const agreementUrl = encodeURIComponent(wx.$api.ApiRoot + '/assets/h5/terms/platform_contract_service_terms.html');
|
|
this.setData({
|
|
source,
|
|
demandId,
|
|
agreementUrl
|
|
});
|
|
this.getContractDetail();
|
|
},
|
|
|
|
/**
|
|
* 生命周期函数--监听页面初次渲染完成
|
|
*/
|
|
onReady() {
|
|
|
|
},
|
|
|
|
/**
|
|
* 生命周期函数--监听页面显示
|
|
*/
|
|
onShow() {
|
|
|
|
},
|
|
|
|
/**
|
|
* 生命周期函数--监听页面隐藏
|
|
*/
|
|
onHide() {
|
|
|
|
},
|
|
|
|
/**
|
|
* 生命周期函数--监听页面卸载
|
|
*/
|
|
onUnload() {
|
|
|
|
},
|
|
|
|
/**
|
|
* 页面相关事件处理函数--监听用户下拉动作
|
|
*/
|
|
onPullDownRefresh() {
|
|
|
|
},
|
|
|
|
/**
|
|
* 页面上拉触底事件的处理函数
|
|
*/
|
|
onReachBottom() {
|
|
|
|
},
|
|
|
|
/**
|
|
* 用户点击右上角分享
|
|
*/
|
|
onShareAppMessage() {
|
|
|
|
},
|
|
|
|
// 签约类型切换
|
|
onContractTypeChange(e) {
|
|
console.log(e.detail.value)
|
|
this.setData({
|
|
'formData.contractType': e.detail.value
|
|
});
|
|
},
|
|
|
|
// 个人签约信息变更
|
|
onNameChange(e) {
|
|
this.setData({
|
|
'formData.name': e.detail.value
|
|
});
|
|
},
|
|
|
|
onPhoneChange(e) {
|
|
this.setData({
|
|
'formData.phone': e.detail.value
|
|
});
|
|
// 输入过程中若已修正为合法手机号,立即清除错误提示
|
|
if (this.data.phoneError && this.isPhone(e.detail.value)) {
|
|
this.setData({ phoneError: '' });
|
|
}
|
|
},
|
|
|
|
onPhoneBlur(e) {
|
|
this.setData({
|
|
phoneError: this.getPhoneError(e.detail.value)
|
|
});
|
|
},
|
|
|
|
onIdCardChange(e) {
|
|
this.setData({
|
|
'formData.idCard': e.detail.value
|
|
});
|
|
},
|
|
|
|
// 企业签约信息变更
|
|
onCompanyNameChange(e) {
|
|
this.setData({
|
|
'formData.companyName': e.detail.value
|
|
});
|
|
},
|
|
|
|
onLegalPersonChange(e) {
|
|
this.setData({
|
|
'formData.legalPerson': e.detail.value
|
|
});
|
|
},
|
|
|
|
onCompanyPhoneChange(e) {
|
|
this.setData({
|
|
'formData.companyPhone': e.detail.value
|
|
});
|
|
if (this.data.companyPhoneError && this.isPhone(e.detail.value)) {
|
|
this.setData({ companyPhoneError: '' });
|
|
}
|
|
},
|
|
|
|
onCompanyPhoneBlur(e) {
|
|
this.setData({
|
|
companyPhoneError: this.getPhoneError(e.detail.value)
|
|
});
|
|
},
|
|
|
|
// 开发信息变更
|
|
onDevelopmentContentChange(e) {
|
|
this.setData({
|
|
'formData.taskContent': e.detail.value
|
|
});
|
|
},
|
|
|
|
onDevelopmentPeriodChange(e) {
|
|
this.setData({
|
|
'formData.needDays': e.detail.value
|
|
});
|
|
},
|
|
|
|
onTotalCostChange(e) {
|
|
const number = Number(e.detail.value * 0.9);
|
|
this.setData({
|
|
'formData.totalCost': e.detail.value,
|
|
'actualAccount': Math.round(e.detail.value * 0.9)
|
|
});
|
|
},
|
|
|
|
// 附件选择成功(仅开发者可上传)
|
|
handleSuccessAttach(e) {
|
|
if (this.data.source != 'dev') {
|
|
return;
|
|
}
|
|
const files = e.detail?.files || [];
|
|
const { attachFiles, attachMax } = this.data;
|
|
const remain = attachMax - attachFiles.length;
|
|
const accepted = files.slice(0, remain);
|
|
if (files.length > remain) {
|
|
wx.showToast({
|
|
title: `最多上传${attachMax}个附件`,
|
|
icon: 'none'
|
|
});
|
|
}
|
|
if (!accepted.length) {
|
|
return;
|
|
}
|
|
const list = [...attachFiles, ...accepted];
|
|
this.setData({
|
|
attachFiles: list,
|
|
attachConfig: { count: attachMax - list.length },
|
|
'formData.attachFiles': list
|
|
});
|
|
this.uploadAttachFiles(accepted);
|
|
},
|
|
|
|
// 移除附件(仅开发者可移除;客户侧附件为开发者上传,只读)
|
|
handleRemoveAttach(e) {
|
|
if (this.data.source != 'dev') {
|
|
return;
|
|
}
|
|
const { index } = e.currentTarget.dataset;
|
|
const { attachFiles, attachMax } = this.data;
|
|
attachFiles.splice(index, 1);
|
|
this.setData({
|
|
attachFiles,
|
|
attachConfig: { count: attachMax - attachFiles.length },
|
|
'formData.attachFiles': attachFiles
|
|
});
|
|
},
|
|
|
|
// 附件预览:客户点击开发者上传的附件进行查看
|
|
handlePreviewAttach(e) {
|
|
// 仅客户侧可预览;开发者侧附件可删除,避免删除时误触预览
|
|
if (this.data.source == 'dev') {
|
|
return;
|
|
}
|
|
const { index } = e.currentTarget.dataset;
|
|
const file = this.data.attachFiles[index];
|
|
const fileUrl = file ? (file.fullUrl || file.url) : '';
|
|
if (!fileUrl) {
|
|
return;
|
|
}
|
|
// 图片直接预览
|
|
if (/\.(jpe?g|png|gif|webp|bmp)$/i.test(fileUrl)) {
|
|
wx.previewImage({
|
|
urls: [fileUrl]
|
|
});
|
|
return;
|
|
}
|
|
// 其他文件下载后打开
|
|
wx.showLoading({ title: '加载中...' });
|
|
wx.downloadFile({
|
|
url: fileUrl,
|
|
success: (res) => {
|
|
wx.hideLoading();
|
|
if (res.statusCode === 200) {
|
|
wx.openDocument({
|
|
filePath: res.tempFilePath,
|
|
showMenu: true,
|
|
fail: () => {
|
|
wx.showToast({ title: '该文件类型暂不支持预览', icon: 'none' });
|
|
}
|
|
});
|
|
} else {
|
|
wx.showToast({ title: '附件加载失败', icon: 'none' });
|
|
}
|
|
},
|
|
fail: () => {
|
|
wx.hideLoading();
|
|
wx.showToast({ title: '附件加载失败', icon: 'none' });
|
|
}
|
|
});
|
|
},
|
|
|
|
// 上传附件到服务器
|
|
uploadAttachFiles(files) {
|
|
files.forEach((file, index) => {
|
|
if (file.status === 'done') {
|
|
return;
|
|
}
|
|
wx.uploadFile({
|
|
url: wx.$api.UploadFile,
|
|
filePath: file.url,
|
|
name: 'file',
|
|
formData: {
|
|
'name': file.name,
|
|
'type': file.type
|
|
},
|
|
header: {
|
|
'Accept': 'application/json',
|
|
'token': wx.getStorageSync('token')
|
|
},
|
|
success: (res) => {
|
|
if (res.statusCode == 413) {
|
|
wx.showToast({
|
|
title: '附件大小超出限制',
|
|
icon: 'none'
|
|
});
|
|
this.removeAttachByUrl(file.url);
|
|
return;
|
|
}
|
|
let response = {};
|
|
try {
|
|
response = JSON.parse(res.data);
|
|
} catch (err) {
|
|
response = {};
|
|
}
|
|
if (response.code === 1 && response.data && response.data.length > 0) {
|
|
this.updateAttachFile({
|
|
...file,
|
|
fullUrl: response.data[0].url,
|
|
status: 'done'
|
|
});
|
|
if (index === files.length - 1) {
|
|
wx.showToast({
|
|
title: '附件上传成功',
|
|
icon: 'success'
|
|
});
|
|
}
|
|
} else {
|
|
wx.showToast({
|
|
title: response.msg || '附件上传失败',
|
|
icon: 'none'
|
|
});
|
|
this.removeAttachByUrl(file.url);
|
|
}
|
|
},
|
|
fail: () => {
|
|
wx.showToast({
|
|
title: '附件上传失败',
|
|
icon: 'none'
|
|
});
|
|
this.removeAttachByUrl(file.url);
|
|
}
|
|
});
|
|
});
|
|
},
|
|
|
|
// 更新单个附件(上传完成后回写)
|
|
updateAttachFile(newFile) {
|
|
const { attachFiles, attachMax } = this.data;
|
|
const idx = attachFiles.findIndex(item => item.url === newFile.url);
|
|
if (idx === -1) {
|
|
return;
|
|
}
|
|
const list = [...attachFiles];
|
|
list[idx] = newFile;
|
|
this.setData({
|
|
attachFiles: list,
|
|
attachConfig: { count: attachMax - list.length },
|
|
'formData.attachFiles': list
|
|
});
|
|
},
|
|
|
|
// 上传失败时移除附件
|
|
removeAttachByUrl(url) {
|
|
const { attachFiles, attachMax } = this.data;
|
|
const list = attachFiles.filter(item => item.url !== url);
|
|
this.setData({
|
|
attachFiles: list,
|
|
attachConfig: { count: attachMax - list.length },
|
|
'formData.attachFiles': list
|
|
});
|
|
},
|
|
|
|
// 签约条款变更
|
|
onAgreementChange(e) {
|
|
console.log('checkbox', e);
|
|
this.setData({
|
|
'formData.agreementChecked': e.detail.checked
|
|
});
|
|
},
|
|
|
|
// 是否为合法手机号(复用项目内置正则)
|
|
isPhone(phone) {
|
|
const value = String(phone === undefined || phone === null ? '' : phone).trim();
|
|
if (!value) {
|
|
return false;
|
|
}
|
|
return wx.$util.phoneRegCheck(value);
|
|
},
|
|
|
|
// 手机号错误提示文案,合法或为空时返回空串(为空由必填校验负责提示)
|
|
getPhoneError(phone) {
|
|
const value = String(phone === undefined || phone === null ? '' : phone).trim();
|
|
if (!value || this.isPhone(value)) {
|
|
return '';
|
|
}
|
|
return '手机号格式不正确,请输入11位手机号';
|
|
},
|
|
|
|
// 提交时校验手机号:写入错误态并 toast,返回是否存在错误
|
|
hasPhoneError(phone, errorField) {
|
|
const error = this.getPhoneError(phone);
|
|
this.setData({
|
|
[errorField]: error
|
|
});
|
|
if (error) {
|
|
wx.showToast({
|
|
title: error,
|
|
icon: 'none'
|
|
});
|
|
}
|
|
return !!error;
|
|
},
|
|
|
|
// 表单验证
|
|
validateForm() {
|
|
const { formData } = this.data;
|
|
const contractType = formData.contractType;
|
|
if (contractType === 'personal') {
|
|
// 身份证号暂不采集
|
|
if (!formData.name || !formData.phone) {
|
|
wx.showToast({
|
|
title: '请填写完整的个人信息',
|
|
icon: 'none'
|
|
});
|
|
return false;
|
|
}
|
|
if (this.hasPhoneError(formData.phone, 'phoneError')) {
|
|
return false;
|
|
}
|
|
} else {
|
|
if (!formData.companyName || !formData.legalPerson || !formData.companyPhone) {
|
|
wx.showToast({
|
|
title: '请填写完整的企业信息',
|
|
icon: 'none'
|
|
});
|
|
return false;
|
|
}
|
|
if (this.hasPhoneError(formData.companyPhone, 'companyPhoneError')) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if (!formData.taskContent || !formData.needDays || !formData.totalCost) {
|
|
wx.showToast({
|
|
title: '请填写完整的开发信息',
|
|
icon: 'none'
|
|
});
|
|
return false;
|
|
}
|
|
|
|
if (this.data.attachFiles.some(item => item.status !== 'done')) {
|
|
wx.showToast({
|
|
title: '附件上传中,请稍候',
|
|
icon: 'none'
|
|
});
|
|
return false;
|
|
}
|
|
|
|
if (!formData.agreementChecked) {
|
|
wx.showToast({
|
|
title: '请阅读并同意签约条款',
|
|
icon: 'none'
|
|
});
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
},
|
|
|
|
//获取签约详情
|
|
getContractDetail() {
|
|
let { demandId, formData } = this.data;
|
|
let params = {
|
|
demandId,
|
|
}
|
|
fetchDemandContractDetail(params).then(
|
|
(res) => {
|
|
console.log(res);
|
|
if (res.code == 1) {
|
|
let resData = res.data;
|
|
const isDev = this.data.source == 'dev';
|
|
let resFormData = isDev ? resData.data_json.devData : resData.data_json.customData;
|
|
this.setData({
|
|
contract: resData,
|
|
formData: resFormData,
|
|
'formData.contractType': resFormData?.contractType || 'personal',
|
|
'formData.taskContent': resData.task_content,
|
|
'formData.needDays': resData.need_days,
|
|
'formData.totalCost': resData.total_amount,
|
|
});
|
|
|
|
// 客户签约时,附件展示开发者签约时上传的附件,仅可预览,不可删除和上传
|
|
const rawAttachFiles = isDev
|
|
? (resFormData?.attachFiles || [])
|
|
: (resData.data_json?.devData?.attachFiles || []);
|
|
// 统一补齐 fullUrl 与上传状态,便于预览取地址、提交时跳过上传中校验
|
|
const attachFiles = rawAttachFiles.map((file) => ({
|
|
...file,
|
|
fullUrl: file.fullUrl || file.url,
|
|
status: file.status || 'done'
|
|
}));
|
|
this.setData({
|
|
attachFiles,
|
|
'formData.attachFiles': attachFiles,
|
|
attachConfig: { count: this.data.attachMax - attachFiles.length }
|
|
});
|
|
}
|
|
}
|
|
);
|
|
},
|
|
|
|
// 返回列表页并刷新,同时给中间的详情页打刷新标记(详情页 onShow 检测 freshPage 重新拉取)
|
|
backAndRefreshAll() {
|
|
const pages = getCurrentPages();
|
|
const detailPage = pages.length >= 2 ? pages[pages.length - 2] : null;
|
|
if (detailPage) {
|
|
detailPage.setData({ freshPage: true });
|
|
}
|
|
wx.$util.backAndRefresh(2);
|
|
},
|
|
|
|
//签约订单支付
|
|
onPay(order) {
|
|
let goodsList = [];
|
|
let storeId = order.store_id;
|
|
order.order_goods.forEach((data) => {
|
|
let query = {
|
|
quantity: data.buy_quantity,
|
|
storeId: storeId,
|
|
spuId: data.spu_id,
|
|
goodsName: data.goods_name,
|
|
available: 1,
|
|
price: data.goods_payment_price,
|
|
primaryImage: data.goods_picture_url,
|
|
skuId: data.sku_id,
|
|
thumb: data.goods_picture_url,
|
|
title: data.goods_name,
|
|
};
|
|
goodsList.push(query);
|
|
});
|
|
console.log(goodsList);
|
|
console.log(JSON.stringify(goodsList));
|
|
let urlQueryStr = wx.$util.obj2Params({
|
|
orderNo: order.order_no,
|
|
goodsRequestList: JSON.stringify(goodsList),
|
|
}, true);
|
|
console.log(urlQueryStr);
|
|
urlQueryStr = urlQueryStr ? `?${urlQueryStr}` : '';
|
|
const path = `/pages/order/order-confirm/index${urlQueryStr}`;
|
|
wx.navigateTo({
|
|
url: path,
|
|
});
|
|
},
|
|
|
|
// 提交表单
|
|
onSubmit() {
|
|
if (!this.validateForm()) {
|
|
return;
|
|
}
|
|
|
|
// TODO: 调用后端API提交签约信息
|
|
wx.showLoading({
|
|
title: '提交中...'
|
|
});
|
|
|
|
const { demandId, formData, source } = this.data;
|
|
// 附件只提交服务端地址与文件名,避免提交本地临时路径
|
|
const submitFormData = {
|
|
...formData,
|
|
attachFiles: (formData.attachFiles || []).map(file => ({
|
|
url: file.fullUrl || file.url,
|
|
name: file.name
|
|
}))
|
|
};
|
|
let params = {
|
|
demandId,
|
|
formData: submitFormData,
|
|
source,
|
|
'agree': 1,
|
|
'contractType': 1,
|
|
'opType': source == 'dev' ? 'contractDev' : 'contractCustomer',
|
|
}
|
|
demandOperate(params).then(
|
|
(res) => {
|
|
console.log(res);
|
|
wx.hideLoading();
|
|
if (res.code == 1) {
|
|
if (source == 'dev') {
|
|
wx.showModal({
|
|
title: '提示',
|
|
showCancel: false,
|
|
content: '签约已提交,等待客户签约确认',
|
|
success: (res2) => {
|
|
if (res2.confirm) {
|
|
//返回上一页
|
|
// wx.navigateBack({ delta: 2 });
|
|
this.backAndRefreshAll();
|
|
console.log('用户点击确定');
|
|
}
|
|
}
|
|
});
|
|
} else {
|
|
if (res.data.order_status == 20) {
|
|
wx.showModal({
|
|
title: '提示',
|
|
showCancel: false,
|
|
content: '签约完成,等待开发者开始工作,返回我的需求列表',
|
|
success: (res3) => {
|
|
if (res3.confirm) {
|
|
// wx.navigateBack({ delta: 2 });
|
|
this.backAndRefreshAll();
|
|
console.log('用户点击确定');
|
|
}
|
|
}
|
|
});
|
|
return;
|
|
}
|
|
wx.showModal({
|
|
title: '提示',
|
|
showCancel: false,
|
|
content: '签约完成,去支付首付款(总金额的50%)',
|
|
success: (res2) => {
|
|
if (res2.confirm) {
|
|
//支付预付款
|
|
this.onPay(res.data);
|
|
console.log('用户点击确定');
|
|
}
|
|
}
|
|
});
|
|
}
|
|
} else {
|
|
wx.showToast({
|
|
title: res.msg,
|
|
icon: 'none'
|
|
});
|
|
}
|
|
},
|
|
() => {
|
|
//接口异常处理
|
|
wx.showToast({
|
|
title: '操作失败',
|
|
icon: 'none'
|
|
});
|
|
},
|
|
);
|
|
}
|
|
}) |