This commit is contained in:
zhangwentao 2025-10-23 16:33:21 +08:00
parent af3dd0e8a7
commit 541f3b9b94
1676 changed files with 271924 additions and 0 deletions

29
.gitignore vendored Normal file
View File

@ -0,0 +1,29 @@
# 依赖包(一般通过 npm/yarn 安装,不需要提交)
node_modules/
# 编译生成的产物目录uniapp 编译后输出到 unpackage
unpackage/*
dist/
build/
# 其他临时文件、日志等
*.log
.DS_Store
# 本地环境配置(若有,比如包含敏感信息的 .env .local 等)
*.local
*.env
# 源码映射文件
*.map
# 编辑器/IDE 相关VS Code 的工作区配置,不同编辑器可按需加)
.vscode/
.idea/
# Source Map 文件(调试用,非业务代码)
*.js.map
# 其他常见忽略
logs/

191
App.vue Normal file
View File

@ -0,0 +1,191 @@
<script>
import { islog } from '@/api/login.js'
import { myRequest, dingRequest } from '@/util/api.js';
export default {
data() {
return{
//
firstApp:false,
agreeXieyi:false,
}
},
onLaunch() {
//
uni.setStorageSync('isAuth',true)
const updateManager = uni.getUpdateManager();
updateManager.onCheckForUpdate(function (res) {
//
if(res.hasUpdate){
updateManager.onUpdateReady(function (res) {
uni.showModal({
title: '更新提示',
content: '新版本已经准备好,是否重启应用?',
success(res) {
if (res.confirm) {
// applyUpdate
updateManager.applyUpdate();
}
}
})
})
}
})
},
onShow() {
},
methods:{
},
onHide() {
},
onShareAppMessage() {
}
}
</script>
<style lang="scss">
/* 注意要写在第一行同时给style标签加入lang="scss"属性 */
@import "uview-ui/index.scss";
.b_color{
color: #f00;
}
.bo_color{
color: #ffffff;
}
.safebottom{
width:750rpx;
height: calc(env(safe-area-inset-bottom) / 2);
}
.valueActive {
color: #333 !important;
}
.icon_creat {
position: fixed;
z-index: 1;
bottom: 180rpx;
right: 80rpx;
image {
width: 80rpx;
height: 80rpx;
border-radius: 50%;
}
}
/* 引入 css */
@import url('./static/font/iconfont.css');
/*每个页面公共css */
page {
background-color: #f5f5f5;
/* background-color: red; */
font-size: 26rpx;
color: #666;
}
//
.noData{
font-size:24rpx;
color:#666;
text-align: center;
margin-top:200rpx;
}
//
.top_required{
display: flex;
justify-content: center;
align-items: center;
font-size:28rpx;
color:#666;
padding:10rpx 0;
switch{
transform: scale(0.7);
}
}
/* 标题样式 */
.title-style {
padding: 20rpx 0 20rpx 24rpx;
font-size: 28rpx;
font-weight: 700;
}
.botsec{
height:30rpx;
}
/* 全局按钮样式 */
.btn_g {
width: 590rpx;
height: 80rpx;
line-height: 80rpx;
font-size: 28rpx;
text-align: center;
margin: 40rpx auto 30rpx;
color: #fff;
border-radius: 40rpx;
background:$uni-text-color;
}
/* 单元格 */
.industry_item_g {
padding-right: 30rpx;
display: flex;
justify-content: space-between;
height: 90rpx;
line-height: 90rpx;
border-bottom: 1rpx solid #EAEAEA;
}
/*按钮样式*/
.button-hover{
background:$uni-text-color;
border-radius: 40rpx;
}
.uni-picker-container .uni-picker-action.uni-picker-action-confirm{
color:$uni-text-color;
}
//
.privacy_mask{
width:100%;
background:#fff;
border-top-left-radius: 20rpx;
border-top-right-radius: 20rpx;
padding-top:50rpx;
padding-bottom: calc(env(safe-area-inset-bottom) / 2);
background: linear-gradient(180deg, #cfe8fe 50%, #F1F4F6 88%, #F4F4F4 100%);
.privacy_box{
padding:0 40rpx 30rpx;
.priva_tit{
font-size:28rpx;
color:#000;
}
.priva_tip{
font-size:24rpx;
color:#666;
margin:16rpx 0;
}
.priva_con{
font-size:24rpx;
color:#666;
line-height: 32rpx;
text{
color:$uni-text-color;
}
}
.agreebtn{
width:200rpx;
height:60rpx;
font-size: 24rpx;
text-align: center;
line-height: 60rpx;
background:$uni-text-color;
color:#fff;
margin:16rpx auto 30rpx;
}
.noagree{
font-size:24rpx;
text-align: center;
text{
color:#999;
}
}
}
}
</style>

97
api/clues.js Normal file
View File

@ -0,0 +1,97 @@
import { myRequest } from '@/util/api.js'
//获取线索 列表 有分页
export function netCluesList(data) {
return myRequest('leads/getList',data)
}
//获取 线索列表 无分页
export function netGetNopageClueslist(data) {
return myRequest('leads/getSelectList',data)
}
//添加 线索 、
export function netAddClues(data) {
return myRequest('leads/addLeads',data)
}
//线索 详情
export function netCluesDetail(data) {
return myRequest('leads/getDetail',data)
}
//修改 线索
export function netEditClues(data) {
return myRequest('leads/editLeads',data)
}
//删除 线索
export function netDelClues(data) {
return myRequest('leads/delLeads',data)
}
//线索 附件
export function netCluesFiles(data){
return myRequest('leads/getFilesList',data)
}
///////////////////////////////////////////////////////////////////////////////////
/*
线索池
*/
// 线索池列表 有分页
export function netCluesPoolList(data) {
return myRequest('leadspool/getList',data)
}
//添加 线索池 、
export function netAddCluesPool(data) {
return myRequest('leadspool/addLeads',data)
}
//线索池 详情
export function netCluesPoolDetail(data) {
return myRequest('leadspool/getDetail',data)
}
//修改 线索池
export function netEditCluesPool(data) {
return myRequest('leadspool/editLeads',data)
}
//删除 线索池
export function netDelCluesPool(data) {
return myRequest('leadspool/delLeads',data)
}
//线索池 附件
export function netCluesPoolFiles(data){
return myRequest('leadspool/getFilesList',data)
}
//领取 线索池
export function netReceiveCluesPool(data) {
return myRequest('leadspool/achieve',data)
}
//批量分配 线索
export function netAllDistriCluesPool(data) {
return myRequest('leadspool/transfer',data)
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////
//通知消息列表
export function netMessageList(data) {
return myRequest('message/getList',data)
}
//消息 列表
export function netAgentList(data) {
return myRequest('message/getInfo',data)
}
//公告 列表
export function netNoticeList(data) {
return myRequest('notice/getList',data)
}
//公告详情
export function netNoticeDetail(data) {
return myRequest('notice/getDetail',data)
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////

501
api/index.js Normal file
View File

@ -0,0 +1,501 @@
import { myRequest, BASE_URL } from '@/util/api.js'
// 上传图片
export const uploadUrl = BASE_URL+'common/upload'
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//首页 获取时间段
export function netTime(data) {
return myRequest('common/getTimes',data)
}
//添加 日程
export function netAddSchedule(data) {
return myRequest('event/addEvent',data)
}
//跟据时间 获取日程列表
export function netScheduleList(data) {
return myRequest('event/getEvent',data)
}
//修改日程 状态
export function netEditScheculeStatus(data) {
return myRequest('event/changeStatus',data)
}
//获取 待办 事项
export function netNeedDealtData() {
return myRequest('index/agent')
}
//获取 待跟进 任务列表
export function netGetFollowList() {
return myRequest('index/event_task')
}
//获取 待处理 日程列表
export function netGetScheList() {
return myRequest('index/event_one')
}
//获取 待审核 合同 列表
export function netGetContractList() {
return myRequest('index/examine_contract')
}
//获取 待审核 回款 列表
export function netGetPaymentList() {
return myRequest('index/examine_receivables')
}
//获取 待回款 提醒 列表
export function netGetPaymentRemindList() {
return myRequest('index/examine_receivables_plan')
}
//获取 出差 签到 列表
export function netGetSignList(data) {
return myRequest('event/getSign',data)
}
//签到 详情
export function netGetSignDetail(data) {
return myRequest('event/getSignDetail',data)
}
//添加 出差 签到
export function netAddSignin(data) {
return myRequest('event/addSign',data)
}
//数据 看板 成交排行 数据
export function netGetData(data) {
return myRequest('statistics/contractRanding',data)
}
//数据 看板 机型排行 数据
export function netGetModalData(data) {
return myRequest('statistics/contractRanking',data)
}
// 目标 完成 度
export function netTargetData(data) {
return myRequest('statistics/staffAchievementStatistics',data)
}
//回款 数据 排名
export function netPaymentRank(data) {
return myRequest('statistics/receivablesRanking',data)
}
//成交 数据 排行
export function netDealRank(data) {
return myRequest('statistics/contractMoneyRanking',data)
}
//业绩 新增 总汇
export function netAddDataRank() {
return myRequest('statistics/newRanking')
}
//客户新增 排行
export function netCustomerARank(data) {
return myRequest('statistics/newCustomer',data)
}
//客户跟进 数量 排行
export function netCustomerFRank(data) {
return myRequest('/statistics/newRecord',data)
}
/**
* 业绩 新增 个人 团队 数据
* */
//个人
export function netPersonalData(data) {
return myRequest('statistics/newRanking',data)
}
//团队
export function netTeamData(data) {
return myRequest('statistics/addCustomerStatistics',data)
}
////////////////////////////////////////////////////////////////////////////////////////////
//获取 周围 客户
export function netNearKehuList(data) {
return myRequest('customer/nearby',data)
}
/////////////////////////////////////////////////////////////////////////////////////////////
//获取个人基本信息
export function netGetUserInfo() {
return myRequest('staff/getInfo')
}
//编辑 个人 信息
export function netEditUserInfo(data) {
return myRequest('staff/editInfo',data)
}
//绑定 手机号
export function netBindPhone(data) {
return myRequest('staff/use_phone',data)
}
//重点关注 客户列表
export function netGetKeyKehu(data) {
return myRequest('customer/collectList',data)
}
//企业 信息
export function netCompanysInfo() {
return myRequest('index/getCompanys')
}
//反馈 意见
export function netFeedBack(data) {
return myRequest('index/feedback',data)
}
//用户 服务 协议
export function netServiceText(data) {
return myRequest('index/serviceContent')
}
///////////////////////////////////////////////////////////////////////////////////////////////////
//表单设置 leads 线索 customer 客户 contacts 联系人 contract 合同 examine回款 business商机
export function netSetForm(data) {
return myRequest('common/getForm',data)
}
//搜索条件 表单
export function netSearchForm(data) {
return myRequest('common/getSearchFields',data)
}
////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* 员工 接口
* */
//员工 列表
export function netStaffList(){
return myRequest('staff/getStaffList')
}
//员工 详情 id
export function netStaffDetail(data){
return myRequest('staff/getStaffDetail',data)
}
//员工 所属 客户列表 id
export function netStaffofCustomerList(data) {
return myRequest('staff/getStaffCustomer',data)
}
//禁用帐号
export function netDisableAccount(data) {
return myRequest('staff/disable_user',data)
}
//编辑员工
export function netEditStaff(data) {
return myRequest('staff/updateStaff',data)
}
//获取部门 列表
export function netDepartmentList() {
return myRequest('staff/getDepartment')
}
//获取 员工 业绩统计
export function netStaffAchievement(data) {
return myRequest('staff/getStaffStatistics',data)
}
//获取 待审核 员工 列表
export function netExamineStaffList(data) {
return myRequest('staff/getCheckStaffList',data)
}
//审核 员工 通过
export function netPassStaffInfo(data) {
return myRequest('staff/checkStaffSuccess',data)
}
//审核 员工 拒绝
export function netRefuseStaffInfo(data) {
return myRequest('staff/checkStaffError',data)
}
//获取员工默认的提醒或审核人 customer客户 record 跟进 contract 合同
// consume 费用 receivables 回款 approval':'工作报告'
export function netStaffDefaultReviewer(data) {
return myRequest('staff/getStaffIds',data)
}
///////////////////////////////////////////////////////////////////////////////////
/**
* 工作报告
* */
//创建工作报告
export function netCreateWork(data) {
return myRequest('daily/createDaily',data)
}
//获取 工作 报告
export function netWorkreportList(data) {
return myRequest('daily/getList',data)
}
//获取 工作报告 详情
export function netWorkDetail(data) {
return myRequest('daily/getDailyDetail',data)
}
//创建工作报告草稿
export function netCreateStraf(data) {
return myRequest('daily/daily_draft',data)
}
//获取 工作报告草稿 详情
export function netWorkDraftDetail(data) {
return myRequest('daily/getDailyDraftDetail',data)
}
//获取工作报告已读和未读列表
export function netWorkisRead(data) {
return myRequest('daily/getDailyRead',data)
}
//审批
//审批名称 列表
export function netWorkExamineName() {
return myRequest('approval/getList')
}
//获取审批记录列表
export function netWorkExamineList(data) {
return myRequest('approval/examineApprovalList',data)
}
//根据审批名称 获取 审批表单
export function netWorkExamineForm(data) {
return myRequest('approval/getFormapproval',data)
}
//获取 审批 详情
export function netWorkExamineDetail(data) {
return myRequest('approval/getDetail',data)
}
//创建 审批 提交
export function netCreateWorkExamine(data) {
return myRequest('approval/addApproval',data)
}
//获取产品 配置 列表
export function netProductConfig(data) {
return myRequest('product/getPartList',data)
}
//获取待审批数量
export function netPendApprovel(data) {
return myRequest('message/getExamineInfo',data)
}
//审批通知列表
export function netApprovelTip(data) {
return myRequest('message/getExamineRecord',data)
}
//获取审批通知 列表
export function netApprovelNotice(data) {
return myRequest('examine_record/get_examine_list',data)
}
//获取审批流程
// type: contract 合同 receivables 回款 consume 费用 achievement 业绩目标 approval 办公
export function netApprovalProcess(data) {
return myRequest('staff/getsteplist',data)
}
//审批流程详情
//type: contract 合同 receivables 回款 consume 费用 achievement 业绩目标 approval 办公
//relation_id
export function netApprovalDetail(data) {
return myRequest('staff/getstepdetail',data)
}
//线索更换负责人
export function netCluesTrans(data) {
return myRequest('leads/transfer',data)
}
/**
* 团队操作 接口
*/
//获取团队成员
export function netTeamList(data) {
return myRequest('setting/team',data)
}
//修改团队成员
export function netTeamEdit(data) {
return myRequest('setting/editShowStaff',data)
}
//获取业绩分割比例
export function netDistributionType(data) {
return myRequest('contract/getRatio',data)
}
//获取业绩统计
export function netAchievementStatistics(data) {
return myRequest('statistics/getAchievementDetail',data)
}
///////////////////////////////////////////////////////////////////////////
//判断是否已经设置
export function netisSetTimeslot() {
return myRequest('attendance/is_week')
}
//添加时间段
export function netAddTimeSlot(data) {
return myRequest('attendance/time_add',data)
}
//时间段修改
export function netEditTimeSlot(data) {
return myRequest('attendance/time_update',data)
}
//时间段列表
export function netTimeSlotList(data) {
return myRequest('attendance/time_list',data)
}
//时间段详情
export function netTimeSlotDetail(data) {
return myRequest('attendance/time_detail',data)
}
//时间段删除
export function netDelTimeSlot(data) {
return myRequest('attendance/time_del',data)
}
///////////////////////////////////////////////////////
//地址添加
export function netAddAddress(data) {
return myRequest('attendance/address_add',data)
}
//地址详情
export function netAddressDetail(data) {
return myRequest('attendance/address_detail',data)
}
//地址修改
export function netEditAddress(data) {
return myRequest('attendance/address_update',data)
}
//地址列表
export function netAddressList(data) {
return myRequest('attendance/address_list',data)
}
//地址删除
export function netDelAddress(data){
return myRequest('attendance/address_del',data)
}
////////////////////////////////////////////////////////////
//添加规则
export function netAddRules(data) {
return myRequest('attendance/rule_add',data)
}
//规则列表
export function netRulesList(data) {
return myRequest('attendance/rule_list',data)
}
//规则详情
export function netRulesDetail(data) {
return myRequest('attendance/rule_detail',data)
}
//规则删除
export function netDelRules(data) {
return myRequest('attendance/rule_del',data)
}
//规则修改
export function netEditRules(data) {
return myRequest('attendance/rule_update',data)
}
/////////////////////////////////////////////////////////////
//判断是否可以打卡
export function netIsPunch(data) {
return myRequest('attendance/is_card',data,'POST',false)
}
//正常打卡
export function netPunchClock(data) {
return myRequest('attendance/card_add',data)
}
//外出打卡
export function netOutClock(data) {
return myRequest('attendance/other_card',data)
}
//补卡申请
export function netSupplementClock(data) {
return myRequest('attendance/card_late',data)
}
//获取考情详情
export function netCheckworkDetail(data) {
return myRequest('attendance/get_statisc',data)
}
//获取打卡统计
export function netClockStatis(data) {
return myRequest('attendance/statistics',data)
}
//获取考勤月统计
export function netClockMonthStatis(data) {
return myRequest('attendance/month_statistics',data)
}
//获取 考勤日统计
export function netClockDayStatis(data) {
return myRequest('attendance/day_statistics',data)
}
//计算请假时长
export function netLeaveDuration(data) {
return myRequest('attendance/getleavetime',data)
}
//请假
export function netApplyLeave(data) {
return myRequest('attendance/leave',data)
}
//获取补卡记录
export function netCardList(data) {
return myRequest('attendance/get_card_late',data)
}
//补卡记录详情
export function netCardDetail(data) {
return myRequest('attendance/get_card_detail',data)
}
//获取请假记录
export function netLeaveList(data) {
return myRequest('attendance/get_leave',data)
}
//获取请假记录详情
export function netLeaveDetail(data) {
return myRequest('attendance/get_leave_detail',data)
}
//获取外勤打卡详情
export function netOutClockDetail(data) {
return myRequest('attendance/get_attendance_detail',data)
}
/////////////////////////////////////////////////////////////////////
//商机列表
export function netBusinessList(data) {
return myRequest('business/getList',data)
}
//商机详情
export function netBusinessDetail(data) {
return myRequest('business/getDetail',data)
}
//增加商机
export function netAddBusiness(data) {
return myRequest('business/addBusiness',data)
}
//修改商机
export function netEditBusiness(data) {
return myRequest('business/editBusiness',data)
}
//转移商机
export function netTransBusiness(data) {
return myRequest('business/batch_change',data)
}
//删除商机
export function netDelBusiness(data) {
return myRequest('business/delete',data)
}
//客户关联的商机
export function netRelationBusiness(data) {
return myRequest('business/business_list',data)
}
//选择关联 商机列表
export function netSelectBusinessList(data) {
return myRequest('business/get_select_list',data)
}
//商机关联的合同
export function netRelationContract(data) {
return myRequest('business/contract',data)
}
//推进商机 状态
export function netAdvanceBusiness(data) {
return myRequest('business/business_status',data)
}
//推进商机阶段的 历史
export function netBusinessHistory(data) {
return myRequest('business/business_history',data)
}

365
api/kehu.js Normal file
View File

@ -0,0 +1,365 @@
import { myRequest } from '@/util/api.js'
//客户列表
export function netKehuList(data) {
return myRequest('customer/getList',data)
}
//创建客户
export function netAddkehu(data) {
return myRequest('customer/addCustomer',data)
}
//筛选条件
export function netSelect() {
return myRequest('common/selectOption')
}
//客户 筛选条件 归属人
export function netSearchStaffList(data) {
return myRequest('customer/getSearchStaffList',data)
}
//上级 客户列表 筛选
export function netPrevCustomer(data) {
return myRequest('customer/getSelectList',data)
}
//根据 客户 筛选联系人 customer_id
export function netLianxiren(data) {
return myRequest('contacts/getSelectList',data)
}
//合同 筛选列表
export function netSelectContract(data) {
return myRequest('contract/getSelectList',data)
}
//客户名称查重
export function netCheckName(data) {
return myRequest('customer/selectName',data)
}
//创建 跟进 记录
export function netAddFollowRecords(data) {
return myRequest('record/createRecord',data)
}
//处理 跟进记录
export function netContinueIsFollow(data) {
return myRequest('record/record_add',data)
}
//跟进 记录 详情
export function netFollowRecordDetail(data) {
return myRequest('record/getRecordDetail',data)
}
//跟进 记录 添加评论
export function netAddComment(data) {
return myRequest('record/addComment',data)
}
//获取 评论 列表
export function netGetCommentList(data) {
return myRequest('record/commentList',data)
}
//员工 列表
export function netStaffList(data) {
return myRequest('common/getSelectStaff',data)
}
//获取客户 详情
export function netKehuDetail(data) {
return myRequest('customer/customerDetail',data)
}
//获取客户 跟进记录 线索动态
export function netKehuFollow(data) {
return myRequest('record/getList',data)
}
//待跟进客户
export function daibanKehuFollow(data) {
return myRequest('record/getcustomerList',data)
}
//新增联系人
export function netAddLianxiren(data) {
return myRequest('contacts/addContacts',data)
}
//创建合同
export function netCreateContract(data) {
return myRequest('contract/addContract',data)
}
//合同编号
export function netContractNum() {
return myRequest('contract/getContractNumber')
}
//移入 公海
export function netRemoveSeas(data) {
return myRequest('customer/moveSeas',data)
}
//领取客户
export function netReceiveKehu(data) {
return myRequest('customer/receive',data)
}
//转移 客户
export function netTransKehu(data) {
return myRequest('customer/transfer',data)
}
//重点关注
export function netKeyCollect(data) {
return myRequest('customer/collect',data)
}
//取消重点 关注
export function netRemoveColect(data) {
return myRequest('customer/cancelCollect',data)
}
//编辑 客户信息
export function netEditKehu(data) {
return myRequest('customer/editCustomer',data)
}
//联系人列表
export function netContactList(data) {
return myRequest('contacts/getList',data)
}
//详情 联系人列表
export function netContact(data) {
return myRequest('contacts/getSelectList',data)
}
//获取 客户 合同 列表
export function netContractList(data) {
return myRequest('contract/getCustomerContacts',data)
}
//获取 客户 相关信息 附件列表
export function netKehuFileList(data) {
return myRequest('customer/getFilesList',data)
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////
//获取联系人 详情
export function netConcatDetailInfo(data) {
return myRequest('contacts/getDetail',data)
}
//获取联系人 附件
export function netContactFileList(data) {
return myRequest('contacts/getFilesList',data)
}
//获取 操作记录 1客户 2联系人 3合同
export function netOperationList(data) {
return myRequest('operation/getList',data)
}
//编辑 联系人 信息
export function netEditContactInfo(data) {
return myRequest('contacts/editContacts',data)
}
//删除 联系人
export function netDelContact(data) {
return myRequest('contacts/delContacts',data)
}
//编辑 附件 名称
export function netEditFileName(data) {
return myRequest('file/editName',data)
}
///////////////////////////////////////////////////////////////////////////////////////////////////////
//合同详情
export function netContractDetail(data) {
return myRequest('contract/getDetail',data)
}
//回款计划 列表
export function netPlanListf(data) {
return myRequest('receivables_plan/getList',data)
}
//创建 回款 计划
export function netAddPlan(data) {
return myRequest('receivables_plan/addPlan',data)
}
//获取 回款 期数
export function netPaymentNum(data) {
return myRequest('receivables_plan/getSelectList',data)
}
//创建 回款
export function netAddPayment(data) {
return myRequest('receivables/addReceivables',data)
}
//回款 列表 回款记录 列表
export function netPaymentList(data) {
return myRequest('receivables/getList',data)
}
//回款编号
export function netPaymentNumber() {
return myRequest('receivables/getReceivablesNumber')
}
//获取 回款 详情
export function netPaymentDetail(data) {
return myRequest('receivables/getDetail',data)
}
//获取 回款 审批 流程 relation_type receivables 回款 contract 合同 consume 费用
export function netPaymentApproval(data) {
return myRequest('examine_record/getList',data)
}
//获取 合同 附件
export function netContractFileList(data) {
return myRequest('contract/getFilesList',data)
}
//审核 relation_type receivables 回款 contract 合同 consume 费用
export function netExamine(data) {
return myRequest('examine_record/examine',data)
}
//合同 撤回 审批
export function netCancelExamine(data) {
return myRequest('contract/cancel',data)
}
//编辑 合同
export function netEditContract(data) {
return myRequest('contract/editContract',data)
}
// 回款 撤回 审批
export function netPaymentCancel(data) {
return myRequest('receivables/cancel',data)
}
//编辑 回款 信息
export function netEditPaymentInfo(data) {
return myRequest('receivables/editReceivables',data)
}
//CRM 合同 列表
export function netCrmContractList(data) {
return myRequest('contract/getList',data)
}
//添加 合同时 获取购买产品
export function netContractProduct(data) {
return myRequest('product/getSelectList',data)
}
//获取产品分类
export function netProductClass(data) {
return myRequest('product/getProducttypeList',data)
}
//产品详情
export function netProductDetail(data) {
return myRequest('product/getProductDetail',data)
}
///////////////////////////////////////////////////////////////////////////////////////////////////
//新建 费用
export function netAddCost(data) {
return myRequest('consume/addConsume',data)
}
//费用 列表
export function netCostList(data) {
return myRequest('consume/getList',data)
}
//费用 详情
export function netCostDetail(data) {
return myRequest('consume/getDetail',data)
}
//编辑 费用
export function netEditCost(data) {
return myRequest('consume/editConsume',data)
}
/////////////////////////////////////////////////////////////////////////////////////
//下级 客户 列表
export function netSubordList(data) {
return myRequest('customer/getLowerCustomer',data)
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////
//当月 数据 简报
export function netGetBriefdata(data) {
return myRequest('index/briefing',data)
}
//交易额 排行
export function netTurnoverList(data) {
return myRequest('index/contractRanding',data)
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//实际 回款 数据
//身份为 员工时 获取 回款 列表
export function netGetreceivableStaff(){
return myRequest('statistics/receivablesStatistics')
}
//身份 为其他时 获取 回款 列表
export function netGetOthersReceivable() {
return myRequest('statistics/staffReceivablesStatistics')
}
///////////////////////////////////////////////////////////////////////////////
//业绩 目标
//获取 部门 年 筛选条件
export function netGetTargetSelect() {
return myRequest('achievement/getDepartment')
}
//获取 成员列表 目标 列表
export function netGetDepTargetlist(data) {
return myRequest('achievement/getStaffList',data)
}
//获取 成员 默认目标详情
export function netGetDefaultSelfDetail(data){
return myRequest('achievement/getMyAchievementDetail',data)
}
//修改 我的 业绩目标
export function netSetMymubiao(data){
return myRequest('achievement/staffEditAchievement',data)
}
//我的 业绩目标 修改记录
export function netGetRecordList(data) {
return myRequest('achievement/editRecords',data)
}
//修改 记录 修改 详情
export function netGetRecordDetail(data) {
return myRequest('achievement/getRecordsDetail',data)
}
//获取 部门 列表
export function netGetBumenList(data) {
return myRequest('achievement/getDepartmentList',data)
}
//获取 团队 列表
export function netGetTealList(data) {
return myRequest('achievement/getTeamList',data)
}
//获取 公司 列表
export function netGetGongsiList(data) {
return myRequest('achievement/getCompanyAchievement',data)
}
//设置 目标 金额
export function netSetTargetMoney(data) {
return myRequest('achievement/addAchievement',data)
}
//获取 默认 目标 金额
export function netGetDefaultMoney(data) {
return myRequest('achievement/getAchievementDetail',data)
}
//CRM 全局搜索
export function netQueryData(data) {
return myRequest('index/search',data)
}

69
api/login.js Normal file
View File

@ -0,0 +1,69 @@
import { myRequest } from '@/util/api.js'
//获取默认 信息
export function defaultInfo() {
return myRequest('common/getConfig')
}
//微信登陆
export function login(data){
return myRequest('staff/wxLogin',data)
}
//钉钉登陆
export function login2(data){
return myRequest('staff/dingLogin?code=' + data, null, 'get')
}
export function islog() {
return myRequest('staff/isLogin')
}
// https://crm.qdsd.vip/addons/qingdong/staff/dingLogin
export function dingLogin() {
return myRequest('staff/dingLogin')
}
//测试
export function islogin() {
return myRequest('staff/test')
}
//新版 登录
export function netNewLogin(data) {
return myRequest('staff/login',data)
}
//暂不登录 演示
export function netlogin_text() {
return myRequest('staff/logintest')
}
//退出登录
export function netOutLogin() {
return myRequest('staff/logout')
}
//获取地图 key
export function netMapKey() {
return myRequest('common/getConfig')
}
//发送code 给后台 获取用户信息
export function netSendCode(data) {
return myRequest('staff/wechatBind',data)
}
//判断是否绑定微信
export function nerIsbindWechat(){
return myRequest('staff/staffBind')
}
//解绑微信
export function netUnboundWecgat() {
return myRequest('staff/unboundWechat')
}
//修改密码
export function netEditPassword(data) {
return myRequest('staff/changepwd',data)
}

28
common/common.js Normal file
View File

@ -0,0 +1,28 @@
import { netStaffDefaultReviewer } from '@/api/index.js'
export const commonF = {
onShow() {
this.remindPeople = []
this.getDefaultRemind()
},
//监听 页面 卸载
onUnload() {
uni.removeStorageSync('remindlist')
},
methods:{
//获取 需要默认提醒的人
getDefaultRemind() {
netStaffDefaultReviewer({type:this.remindType}).then(res=>{
res = res.data
res.forEach((ele,index) => {
ele.isDel = false
})
this.remindPeople = this.$deWeight([...res,...uni.getStorageSync('remindlist')])
})
},
//删除 提醒人
delRemind(index) {
this.remindPeople.splice(index, 1)
uni.setStorageSync('remindlist', this.remindPeople)
},
}
}

View File

@ -0,0 +1,193 @@
<template>
<view class="boxwarp">
<view class="apptitle">审批流程</view>
<view class="approbox" v-if="process.status == 1">
<view class="appli" v-for="(item,index) in process.stepList" :key="index">
<view class="xian"></view>
<view class="title" v-if="item.status == 1">指定员工(任意一人)</view>
<view class="title" v-if="item.status == 2">指定员工(会签)</view>
<view class="title" v-if="item.status == 3">直属上级</view>
<view class="stafflist" v-for="(staffitem,staffindex) in item.stafflist" :key="staffindex">
<view class="staffli">
<image :src="staffitem.img" class="staffimg" mode=""></image>
<view class="staffname">{{staffitem.name}}</view>
</view>
<view class="staffcon">
<view class="approval_status">{{staffitem.examine_reord.check_time?staffitem.examine_reord.check_time:''}}</view>
<view class="approval_status" v-if="staffitem.examine_reord.status == 0">待审核</view>
<view class="approval_status" v-if="staffitem.examine_reord.status == 1">审核通过</view>
<view class="approval_status" v-if="staffitem.examine_reord.status == 2">审核拒绝</view>
<view class="approval_status" v-if="staffitem.examine_reord.status == 3">撤销审批</view>
<view class="approval_status">{{staffitem.examine_reord.content?staffitem.examine_reord.content:''}}</view>
</view>
</view>
</view>
</view>
<view class="info_item" v-if="process.status == 0">
<view class="operation_record">
<view class="record_item" v-for="(aitem,aindex) in process.stepList[0].stafflist" :key="aindex">
<image :src="aitem.img ? aitem.img : BASE_IMG_URL+'headImg.png'" mode="scaleToFill"></image>
<view class="record_info">
<view class="info_top">
<view>{{aitem.name}}</view>
<view class="record_time">
{{aitem.examine_reord.check_time ? aitem.examine_reord.check_time : ''}}
</view>
</view>
<view v-if="aitem.examine_reord.status == 0">待审核</view>
<view v-if="aitem.examine_reord.status == 1">审核通过</view>
<view v-if="aitem.examine_reord.status == 2">审核拒绝</view>
<view v-if="aitem.examine_reord.status == 3">撤销审批</view>
<view class="shenhetext" v-if="aitem.examine_reord.status == 1 || aitem.examine_reord.status == 2" style="margin-top:10rpx">审核意见{{aitem.examine_reord.content}}</view>
</view>
</view>
</view>
</view>
</view>
</template>
<script>
export default{
props:{
process:{
type:Object,
default:{}
}
},
data() {
return{
}
},
methods:{
}
}
</script>
<style lang="scss" scoped>
.boxwarp{
background:#fff;
width:100%;
padding-bottom:50rpx;
}
.apptitle{
padding:24rpx;
font-size: 32rpx;
color: #999;
}
.approbox{
padding:0 24rpx;
.appli{
padding-left:24rpx;
position: relative;
&::after{
content:'';
width:14rpx;
height:14rpx;
border-radius: 50%;
background:#5cbdb2;
position: absolute;
left:0;
top:10rpx;
}
&:last-child{
.xian{
display: none;
}
}
.xian{
width:2rpx;
height:calc(100% - 8rpx);
background:#5cbdb2;
position: absolute;
top:20rpx;
left:5rpx;
}
.title{
font-size:28rpx;
color:#666;
}
.stafflist{
margin-top:24rpx;
display: flex;
justify-content: flex-start;
align-items: center;
padding-bottom:24rpx;
border-bottom:1rpx solid #f5f5f5;
.staffli{
display: flex;
flex-direction: column;
align-items: center;
margin-right:24rpx;
margin-bottom:24rpx;
flex-shrink: 0;
.staffimg{
width:60rpx;
height:60rpx;
border-radius: 50%;
margin-bottom:10rpx;
}
.staffname{
font-size:26rpx;
color:#999;
}
}
.staffcon{
margin-left:24rpx;
.approval_status{
font-size:24rpx;
color:#333;
margin-bottom:15rpx;
}
}
}
}
}
.operation_record {
background:#fff;
padding: 20rpx 30rpx;
.record_item {
display: flex;
justify-content: space-between;
margin-bottom: 20rpx;
padding-bottom:20rpx;
border-bottom:1rpx solid #EAEAEA;
margin-bottom:20rpx;
&:last-child{
border-bottom:none;
}
image {
width: 80rpx;
height: 80rpx;
border-radius: 50%;
flex-shrink: 0;
}
.record_info {
flex: 1;
margin-left: 25rpx;
line-height: 40rpx;
font-size: 28rpx;
.info_top{
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom:10rpx;
}
.shenhetext{
font-size:26rpx;
color:#666;
line-height: 34rpx;
}
}
.record_line {
position: absolute;
top: -102rpx;
left: -26rpx;
height: 105rpx;
border-left: 4rpx dotted #dedede;
}
}
}
</style>

View File

@ -0,0 +1,378 @@
<template>
<view class="customer_dynamic">
<view class="fllow_item" v-for="(item,index) in list" :key="index"
@click.stop="isSeas == 1 ? clientClick(item.id) : ''">
<view class="item_content">
<view class="con_img">
<image style="width: 129rpx;height: 129rpx;border-radius: 50%;margin: 23rpx 36rpx 42rpx 35rpx;"
:src="item.staff.img ? item.staff.img : BASE_IMG_URL+'headImg.png'" class="headerimg" mode="scaleToFill">
</image>
<view class="main_first">
<view class="main_title">
<view class="first_left">
<view class="f_l_yop">
<view>{{item.staff.name}}</view>
<view>{{item.follow_time}}</view>
</view>
<view class="f_l_bottom" style="margin-top: 30rpx;">
<view class="main_type daofang" v-if="item.follow_type == '到访'">
{{item.follow_type}}
</view>
<view class="main_type genjin" v-if="item.follow_type == '跟进'">
{{item.follow_type}}
</view>
<view class="main_type other"
v-if="item.follow_type != '跟进' && item.follow_type != '到访'">
{{item.follow_type}}
</view>
</view>
</view>
</view>
</view>
</view>
<view class="con_main">
<view class="main_second">
<view>{{item.content}}</view>
</view>
<view class="lxs_time" v-if="item.next_time">下次跟进时间{{item.next_time ? item.next_time : ''}}</view>
<view class="main_img" @click.stop.prevent v-if="item.imgList.length != 0">
<image v-for="(ele,index) in item.imgList" :key="index" :src="ele.file_path" @click.stop="toPrevieImg(item.imgList,index)" class="imgbox" ></image>
</view>
<view class="fllow_file_li" @click.stop.prevent v-if="item.fileList.length != 0">
<view class="fil_li" v-for="(fileitem,fileindex) in item.fileList" :key="fileindex">
<image :src="BASE_IMG_URL+'fujian.png'" class="fileimg" mode="scaleToFill"></image>
<view class="filename" @click="openCommonFile(fileitem)">{{fileitem.name}}</view>
</view>
</view>
</view>
<view class="comment">
<image :src="BASE_IMG_URL+'pl.png'" mode="scaleToFill"></image>({{item.comment_num}})
<view class="span" style="margin-left:10rpx;display: block;">
查看评论
</view>
</view>
</view>
</view>
<u-empty v-if="list.length == 0" text="暂无更多"></u-empty>
</view>
</template>
<script>
import {
netKehuFollow,
netGetCommentList,
netFollowRecordDetail
} from '@/api/kehu.js'
import {
BASE_IMG_URL
} from '@/util/api.js'
export default {
props: {
kehuid: {
type: Number,
default: null
},
type: {
type: Number,
default: 1 //1 2 3 4线 5
},
isSeas: {
type: Number,
default: 1, //1 2
}
},
data() {
return {
list: [],
page: 1,
limit: 10,
totalPage: 1,
commont_list: [], //
id: '',
info: {},
BASE_IMG_URL: BASE_IMG_URL,
amount: [],
}
},
created() {
this.getFollowList()
},
onReachBottom() {
if (this.page >= this.totalPage) {
return
}
this.page = this.page + 1
this.getFollowList()
},
onLoad(options) {
},
onShow() {
},
methods: {
//
clientClick(id) {
uni.navigateTo({
url: '/pagesA/crm/cluesManagement/followUpDetail/followUpDetail?id=' + id,
})
},
getFollowList() {
let params = {
relation_id: this.kehuid,
relation_type: this.type, //1 2 3 4线 5
page: this.page
}
netKehuFollow(params).then(res => {
let arr = res.data.data
arr.forEach(ele=>{
ele.imgList = []
ele.fileList = []
ele.file.forEach(item=>{
if(item.types.indexOf('image') != -1){
ele.imgList.push({
id:item.id,
file_path:item.file_path,
name:item.name
})
}else{
ele.fileList.push({
id:item.id,
file_path:item.file_path,
name:item.name
})
}
})
})
this.list = this.list.concat(arr)
this.page = res.data.current_page
this.totalPage = res.data.last_page
})
},
//
toPrevieImg(arr,index) {
let data = []
arr.forEach(ele=>{
data.push(ele.file_path)
})
uni.previewImage({
urls: data,
current:index
})
}
}
}
</script>
<style lang="scss">
.fllow_file_li {
padding: 24rpx 34rpx;
background: #fff;
.fil_li {
display: flex;
justify-content: flex-start;
align-items: center;
padding-bottom: 14rpx;
padding-top:15rpx;
.fileimg {
width: 20rpx;
height: 20rpx;
margin-right:25rpx;
}
.filename {
width:450rpx;
font-size: 24rpx;
color: #999999;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.closeimg {
width: 32rpx;
height: 32rpx;
}
}
}
.comment {
margin-top: 20rpx;
height: 90rpx;
background: #fff;
border-top: 1rpx solid #ededed;
text-align: center;
display: flex;
justify-content: center;
align-items: center;
image {
width: 40rpx;
height: 36rpx;
float: left;
}
}
.customer_dynamic {
margin: 20rpx 0rpx;
.fllow_item {
.item_data {
// margin: 30rpx 0;
&::before {
content: '';
display: inline-block;
margin: 0 15rpx 0 24rpx;
width: 20rpx;
height: 20rpx;
border-radius: 10rpx;
border: 2rpx solid $uni-text-color;
}
}
.item_content {
display: block;
background-color: #fff;
padding: 24rpx 24rpx 10rpx;
border-radius: 10rpx;
margin-bottom: 30rpx;
.con_img {
display: flex;
.main_first {
margin-bottom: 25rpx;
padding-left: 25rpx;
flex: 1;
.main_time {
line-height: 25px;
}
.main_title {
display: flex;
width: 100%;
justify-content: space-between;
.first_left {
width: 100%;
margin-top: 25rpx;
.f_l_yop {
width: 100%;
display: flex;
justify-content: space-around;
}
:first-child {
font-size: 32rpx;
margin-right: 10rpx;
margin-top: -3rpx;
}
:last-child {
margin-top: 2rpx;
}
}
.main_type {
margin-left: 20rpx;
margin: 20rpx;
width: 85rpx;
height: 36rpx;
background: $uni-text-color-opcity;
// padding: 5rpx 20rpx;
border-radius: 10rpx;
color: $uni-text-color;
text-align: center;
line-height: 36rpx;
}
}
}
image {
width: 100rpx;
height: 100rpx;
border-radius: 50%;
}
}
.con_main {
flex: 1;
margin-left: 30rpx;
font-size: 30rpx;
color: #666666;
.main_second {
padding-bottom: 20rpx;
}
.main_img {
display: flex;
justify-content: flex-start;
align-items: center;
flex-wrap: wrap;
margin-top: 20rpx;
.imgbox {
padding: 10rpx;
border-radius: 10rpx;
width: 160rpx;
height: 160rpx;
margin-right: 14rpx;
margin-bottom: 14rpx;
}
}
.main_third {
display: flex;
justify-content: space-between;
align-items: center;
margin: 20rpx 0 10rpx;
.third_left {
display: flex;
justify-content: center;
align-items: center;
.icon-setup {
margin-top: -4rpx;
margin-right: 10rpx;
}
}
.third_right {
display: flex;
.right_num {
display: flex;
.icon-shaixuan {
margin-top: -4rpx;
margin-right: 10rpx;
}
:last-child {
margin-right: 20rpx;
}
}
.icon-arrows_right {
margin-top: -4rpx;
}
}
}
.main_fourth {
padding-bottom: 10rpx;
}
}
}
}
.fontColor {
color: #999;
}
}
</style>

View File

@ -0,0 +1,130 @@
const customerSortDatas = [
{
id:1,
name:'名称正序'
},
{
id:2,
name:'名称倒序'
},
{
id:3,
name:'创建时间正序'
},
{
id:4,
name:'创建时间倒序'
},
{
id:5,
name:'下次跟进时间正序'
},
{
id:6,
name:'下次跟进时间倒序'
},
]
const cluesSortDatas = ['客户名称','系统编号','线索来源','线索状态','联系人姓名','手机号码','归属人员','跟进次数','未跟进天数','最后跟进时间','下次跟进时间','下次跟进内容','备注信息','归属人员','所属部门',
'创建人员','前归属人','前所属部门','协作人员','创建时间','更新时间'];
const cluesScreenDatas = [
{
title: '联系人分类',
content: ['全部线索','我的线索','下属的线索','已转客户','公共线索'],
active : 0,
},
{
title: '线索来源',
content:['电话营销','主动来电','客户介绍','朋友介绍','独立开发','网络搜索','公告杂志','展会促销','其他途径'],
active : 0,
},
{
title: '线索状态',
content: ['初步意向','下次邀约','已转客户'],
active : 0,
},
{
title: '角色',
content: ['普通人','决策人','分项决策人','商务决策','财务决策','使用人','意见影响人'],
active : 0,
},
{
title: '尊称',
content: ['先生','女生'],
active : 0,
}
];
const followSortDatas = ['跟进人员','创建时间','所属模块','跟进类型'];
const followScreenDatas = [
{
title: '所属模块',
content: ['全部','线索','客户','商机','订单'],
active : 0,
},
{
title:'跟进类型',
content:['到访','电话','微信','短信','邮件','QQ','其他'],
active : 0,
}
]
const moreCompany = [
{
title: '联系人',
num: 100
},
{
title: '下级公司',
num: 100
},
{
title: '跟进记录',
num: 100
},
{
title: '订单记录',
num: 100
},
{
title: '费用记录',
num: 100
},
{
title: '相关附件',
num: 100
},
{
title: '归属记录',
num: 100
},
{
title: '操作日志',
num: 100
}
]
const moreLinkman = [
{
title: '相关联系人',
num: 100
},
{
title: '通话记录',
num: 100
},
{
title: '操作日志',
num: 100
},
]
export {
customerSortDatas,
cluesSortDatas,
cluesScreenDatas,
followSortDatas,
followScreenDatas,
moreCompany,
moreLinkman
}

View File

@ -0,0 +1,95 @@
<template>
<view class="info_detail">
<view class="info_item">
<view class="basic_main">
<view style="font-size: 30rpx;color: #999;display: -webkit-box;display: flex;flex-direction: row;align-items: center;">负责人</view>
<view style="font-size: 30rpx;color: #333;width: 450rpx;text-align: right;">{{info.owner_staff ? info.owner_staff.name: ''}}</view>
</view>
<view class="basic_main">
<view style="font-size: 30rpx;color: #999;display: -webkit-box;display: flex;flex-direction: row;align-items: center;">创建人</view>
<view style="font-size: 30rpx;color: #333;width: 450rpx;text-align: right;">{{info.create_staff ? info.create_staff.name: ''}}</view>
</view>
<view class="basic_main">
<view style="font-size: 32rpx;color: #999;display: flex;flex-direction: row;align-items: center;">所在地区</view>
<view
style="
font-size: 30rpx;
color: #333;
width: 450rpx;
text-align: right;
">{{info.address ? info.address : ''}}</view>
</view>
<view class="basic_main" @click="jumpMap">
<view style="font-size: 30rpx;color: #999;display: -webkit-box;display: flex;flex-direction: row;align-items: center;">详细地址</view>
<view style="font-size: 30rpx;color: #333;width: 450rpx;text-align: right;">{{info.address_detail ? info.address_detail : ''}}</view>
</view>
<form-item v-for="(item,index) in listForm" :key="index" :isEdit="false" :objInfo="item"></form-item>
</view>
</view>
</template>
<script>
import formItem from '@/components/form/formitem.vue'
import { netSetForm } from '@/api/index.js'
export default {
props:{
info:{
type:Object,
default:{}
}
},
components:{
formItem
},
created() {
this.getForm()
},
data() {
return {
listForm:[]
}
},
methods: {
getForm() {
netSetForm({type:'customer'}).then(res=>{
res = res.data.data
res.forEach(ele=>{
ele.value = this.info[ele.id]?this.info[ele.id]:''
})
this.listForm = res
})
},
jumpMap() {
uni.openLocation({
latitude: this.info.lat,
longitude: this.info.lng
})
}
}
}
</script>
<style lang="scss">
.info_detail {
margin-bottom: 100rpx;
.basic_head {
display: flex;
:last-child {
font-weight: 700;
margin-left: 8rpx;
}
}
.basic_main {
display: flex;
justify-content: space-between;
background-color: #fff;
line-height: 40rpx;
border-bottom: 1rpx solid #EAEAEA;
padding: 30rpx 40rpx 30rpx 47rpx;
:first-child {
color: #333;
}
}
}
</style>

View File

@ -0,0 +1,540 @@
<template>
<view class="select_warp">
<view class="manage_tab">
<view class="tab_array">
<image :src="BASE_IMG_URL+'ss.png'" mode="scaleToFill"></image>
<input @confirm="doSearch" type="text" placeholder-style="color:#999;"
:class="name ? 'fontactive' : ''" v-model="name" placeholder="客户名称" class="li_box" />
</view>
<view class="tab_screen" @click="screenClick">
<image :src="BASE_IMG_URL+'shaixuan.png'" mode="scaleToFill"></image>
</view>
</view>
<view class="" style="height:80rpx;"></view>
<uni-popup ref="popup" type="top" background-color="#fff">
<scroll-view scroll-y class="scrollbox" style="height:800rpx;background:#fff;">
<!--筛选模块 -->
<view class="screen_content" @tap.stop.prevent>
<view class="fir_li">
<view class="li_label">客户星级</view>
<u-rate :count="5" @change="changeLevel" v-model="level" active-color="#FFD049" inactive-color="#b2b2b2" gutter="20"></u-rate>
</view>
<view class="fir_li">
<view class="li_label">客户来源</view>
<picker @change="changeSource" :value="sourceIndex" :range="sourceList">
<view class="li_box">
<view class="form_right">
<view :class="source ? 'fontactive' : ''">{{source ? source : '点击选择'}}</view>
<view class="iconfont icon-arrows_right"></view>
</view>
</view>
</picker>
</view>
<view class="fir_li">
<view class="li_label">跟进状态</view>
<picker @change="changeFollow" :value="followIndex" :range="followList">
<view class="li_box">
<view class="form_right">
<view :class="follow ? 'fontactive' : ''">{{follow ? follow : '点击选择'}}</view>
<view class="iconfont icon-arrows_right"></view>
</view>
</view>
</picker>
</view>
<view class="fir_li">
<view class="li_label">成交状态</view>
<picker @change="changeStatus" :value="statusIndex" :range="statusArr">
<view class="li_box">
<view class="form_right">
<view :class="statusArr[statusIndex] ? 'fontactive' : ''">{{statusArr[statusIndex] ? statusArr[statusIndex] : '点击选择'}}</view>
<view class="iconfont icon-arrows_right"></view>
</view>
</view>
</picker>
</view>
<view class="fir_li" v-if="!isSeas">
<view class="li_label">归属人</view>
<view class="li_box" @click="toSelectStaff">
<view class="form_right">
<view :class="staffObj ? 'fontactive' : ''">
{{staffObj ? staffObj.name : '点击选择'}}</view>
<view class="iconfont icon-arrows_right"></view>
</view>
</view>
</view>
<view class="fir_li">
<view class="li_label">新增客户时间</view>
<view class="li_box" style="display: flex;justify-content: space-around;">
<picker @change="changeNewStartTime" mode="date" :end="new_end_time"
style="width:50%;border-right:1rpx solid #CCCCCC">
<view class="form_right">
<view style="flex:1;text-align: center;"
:class="new_start_time ? 'fontactive' : ''">
{{new_start_time ? new_start_time : '开始时间'}}</view>
<view class="iconfont icon-arrows_right"></view>
</view>
</picker>
<picker @change="changeNewEndTime" mode="date" :start="new_start_time" style="width:50%">
<view class="form_right">
<view style="flex:1;text-align: center;" :class="new_end_time ? 'fontactive' : ''">
{{new_end_time ? new_end_time : '结束时间'}}</view>
<view class="iconfont icon-arrows_right"></view>
</view>
</picker>
</view>
</view>
<view class="fir_li">
<view class="li_label">下次联系时间</view>
<view class="li_box" style="display: flex;justify-content: space-around;">
<picker @change="changeStartTime" mode="date" :end="end_time"
style="width:50%;border-right:1rpx solid #CCCCCC">
<view class="form_right">
<view style="flex:1;text-align: center;" :class="start_time ? 'fontactive' : ''">
{{start_time ? start_time : '开始时间'}}</view>
<view class="iconfont icon-arrows_right"></view>
</view>
</picker>
<picker @change="changeEndTime" mode="date" :start="start_time" style="width:50%">
<view class="form_right">
<view style="flex:1;text-align: center;" :class="end_time ? 'fontactive' : ''">
{{end_time ? end_time : '结束时间'}}</view>
<view class="iconfont icon-arrows_right"></view>
</view>
</picker>
</view>
</view>
<search-item v-for="(item,index) in searchForm" :key="index" :objInfo="item" @changeSearchData="changeSearchData"></search-item>
</view>
</scroll-view>
<view class="button_bottom">
<view @tap.stop="reset">重置</view>
<view @tap.stop="sureQuery">确定</view>
</view>
</uni-popup>
<select-staff ref="staffChild" @sureStaff="sureStaff"></select-staff>
</view>
</template>
<script>
import selectStaff from '@/components/selectStaff.vue'
import searchItem from '../../search/searchitem.vue'
import {
netSelect,
netSearchStaffList
} from '@/api/kehu.js'
import {
BASE_IMG_URL
} from '@/util/api.js'
export default {
components:{
selectStaff,
searchItem
},
data() {
return {
Strname: "", //
BASE_IMG_URL: BASE_IMG_URL,
date: '',
show: false,
start_time: '', //
end_time: '', //
name: '', //
level: '', //
source: '', //
sourceList: [],
sourceIndex: null,
follow: '', //
followList: [],
followIndex: null,
createtime: '', //
new_start_time: '', //
new_end_time: '', //
next_time: '', //
staffObj:null, //
ascripId:null,
count:5,
value:1,
showIndex:1,
//
contract_status:'', //0 1
statusArr:['未成交','已成交'],
statusIndex:null,
}
},
props: {
sortData: {
type: Array,
default: []
},
de_starttime: { //
type: String,
default: '',
},
de_endtime: { //
type: String,
default: ''
},
isSeas: {
type: Boolean,
default: false
},
de_staffid: { //
type: Number,
default: null
},
cusStatus: {
type: String,
default: ''
},
searchForm:{
type: Array,
default:()=>{
return []
}
}
},
created() {
this.ascripId = this.de_staffid
this.getSelect()
},
methods: {
//
changeStatus(e) {
this.statusIndex = e.detail.value
},
//
doSearch() {
let params = {
name:this.name,
}
if (!this.isSeas) {
params = Object.assign({}, params, {
staff_id: this.ascripId
})
}
this.$emit('queryData', params)
},
getSelect() {
netSelect().then(res => {
this.sourceList = res.data['客户来源']
this.followList = res.data['客户状态']
})
},
//
toSelectStaff() {
this.$refs.staffChild.init()
},
sureStaff(obj) {
this.staffObj = obj
this.ascripId = obj.id
},
//
getGuishu() {
netSearchStaffList().then(res => {
let arr = res.data
if (this.ascripId) {
arr.forEach((ele, index) => {
if (ele.id == this.ascripId) {
this.staffObj = ele
}
})
}
})
},
screenClick() {
this.$refs.popup.open()
if(this.showIndex == 1){
this.new_start_time = this.de_starttime
this.new_end_time = this.de_endtime
this.statusIndex = this.cusStatus
}
},
//
changeNewStartTime(e) {
this.showIndex = 2
this.new_start_time = e.detail.value
if(!this.new_end_time){
this.new_end_time = e.detail.value
}
},
//
changeNewEndTime(e) {
this.showIndex = 2
this.new_end_time = e.detail.value
if(!this.new_start_time){
this.new_start_time = e.detail.value
}
},
changeLevel(e) {
this.level = e
},
//
changeStartTime(e) {
this.start_time = e.detail.value
if(!this.end_time){
this.end_time = e.detail.value
}
},
changeEndTime(e) {
this.end_time = e.detail.value
if(!this.start_time){
this.start_time = e.detail.value
}
},
//
changeSource(e) {
this.sourceIndex = e.detail.value
this.source = this.sourceList[e.detail.value]
},
//
changeFollow(e) {
this.followIndex = e.detail.value
this.follow = this.followList[e.detail.value]
},
//
changeCreatetime(e) {
this.createtime = e.detail.value
},
changeSearchData(type,key,value){
this.$emit('changeSearchData',type,key,value)
},
//
reset() {
this.level = ''
this.source = ''
this.sourceIndex = null
this.follow = ''
this.followIndex = null
this.next_time = ''
this.start_time = ''
this.end_time = '',
this.createtime = '',
this.new_start_time = '',
this.new_end_time = '',
this.ascripId = null
this.staffObj = null
this.statusIndex = null
this.$emit('resetForm')
},
//
sureQuery() {
let params = {
level: this.level,
source: this.source,
follow: this.follow,
createtime: (this.new_start_time && this.new_end_time) ? (this.new_start_time + ',' + this.new_end_time) : '',
next_time: (this.start_time && this.end_time) ? (this.start_time + ',' + this.end_time) : '',
contract_status:this.statusIndex,
staff_id:this.staffObj?this.staffObj.id:'',
}
if (!this.isSeas) {
params = Object.assign({}, params, {
staff_id: this.ascripId
})
}
this.$refs.popup.close()
this.$emit('queryData', params)
}
}
}
</script>
<style lang="scss">
.fontactive {
color: #333;
}
.select_warp {
z-index: 9;
position: relative;
}
.custom {
padding: 100rpx 0 180rpx;
text-align: center;
color: $uni-text-color;
font-size: 28rpx;
}
.warpbox {
position: fixed;
width: 750rpx;
left: 0;
top: 80rpx;
bottom: 0;
z-index: 2;
background: rgba(0, 0, 0, 0.7);
// height:890rpx;
}
.screen_content {
width: 702rpx;
z-index: 2;
border-top: 1rpx solid #CCCCCC;
background-color: #fff;
padding: 24rpx;
.fir_li {
margin-bottom: 20rpx;
.li_label {
font-size: 28rpx;
color: #333333;
margin-bottom: 15rpx;
}
.li_box {
// width:700rpx;
width: 100%;
border-radius: 15rpx;
border: 1rpx solid #CCCCCC;
height: 60rpx;
padding: 0 35rpx;
line-height: 60rpx;
color: #999;
}
.form_right {
display: flex;
justify-content: space-between;
image {
width: 40rpx;
height: 40rpx;
margin: 28rpx 5rpx 0 0;
}
}
}
}
.sort_content {
background-color: #fff;
padding-top: 24rpx;
width: 750rpx;
z-index: 2;
border-top: 1rpx solid #CCCCCC;
.sort_feedback {
margin-bottom: 20rpx;
margin-top: 20rpx;
.feedback_header {
padding: 0 0 30rpx 24rpx;
font-size: 28rpx;
font-weight: 700;
}
.feedback_main {
padding: 0 24rpx;
.main_con {
padding-left: 20rpx;
background-color: #fff;
height: 80rpx;
line-height: 80rpx;
border: 1rpx solid #EAEAEA;
}
.tabactive {
border: 1rpx solid #ff7800;
color: #ff7800;
}
}
}
}
.manage_tab {
width: 100%;
height: 80rpx;
line-height: 80rpx;
background-color: $uni-text-color;
display: flex;
justify-content: space-around;
position: absolute;
left: 0;
top: 0;
z-index: 1;
.tab_array {
display: flex;
background: #fff;
border-radius: 34rpx;
height: 68rpx;
width: 467rpx;
overflow: hidden;
image {
width: 50rpx;
height: 50rpx;
margin: 8rpx 15rpx 0 28rpx;
}
input {
line-height: 68rpx;
height: 68rpx;
}
}
.tab_screen {
display: flex;
image {
width: 43rpx;
height: 44rpx;
margin-top: 10rpx;
}
}
}
.active {
&::after {
content: '';
float: right;
margin-right: 40rpx;
}
}
.mar-180 {
margin-bottom: 180rpx;
}
.button_bottom {
display: flex;
width: 100%;
height: 90rpx;
background-color: #fff;
line-height: 90rpx;
text-align: center;
font-size: 32rpx;
:first-child {
flex: 1;
color: $uni-text-color;
border-top: 1rpx solid #CCCCCC;
}
:last-child {
flex: 1;
background-color: $uni-text-color;
color: #fff;
}
}
.sort_active {
color: $uni-text-color;
}
//
.screen_active {
border: 1rpx solid $uni-text-color !important;
}
</style>

31
components/copy/copy.js Normal file
View File

@ -0,0 +1,31 @@
import { netStaffDefaultReviewer } from '@/api/index.js'
export const commonJS = {
onShow() {
//获取 默认的抄送人
this.getDefaultCopy()
},
onUnload() {
uni.removeStorageSync('copyPeople')
},
methods: {
getDefaultCopy() {
netStaffDefaultReviewer().then(res=>{
res = res.data
let arr = uni.getStorageSync('copyPeople')?uni.getStorageSync('copyPeople'):[]
arr.forEach((item,index)=>{
res.forEach(ele=>{
if(item.id == ele.id){
item.isDel = false
}
})
})
this.copyList = this.checkReport([...res,...uni.getStorageSync('copyPeople')])
})
},
delCopy(index) {
this.copyList.splice(index,1)
uni.setStorageSync('copyPeople',this.copyList)
},
}
}

View File

@ -0,0 +1,100 @@
<template>
<view class="affiliation">
<view class="aff_head">抄送人</view>
<view class="aff_con">
<view class="aff_item affbox" v-for="(item,index) in copyList" :key="index">
<image :src="BASE_IMG_URL+'img/close.png'" class="delremind" v-if="item.isDel" @click="delCopy(index)" mode=""></image>
<image :src="item.img ? item.img : BASE_IMG_URL+'img/headImg.png'"></image>
<view>{{item.name}}</view>
</view>
<view class="aff_item aff_last" @click="selectCopy">
<image :src="BASE_IMG_URL+'img/more.png'"></image>
<view>更多</view>
</view>
</view>
</view>
</template>
<script>
import { BASE_IMG_URL } from '@/util/api.js'
export default{
props:{
copyList:{
type:Array,
default:[]
}
},
data() {
return {
BASE_IMG_URL:BASE_IMG_URL,
}
},
methods:{
selectCopy() {
uni.navigateTo({
url: '/pagesA/crm/selectMember/selectMember?action=2'
})
},
//
delCopy(index) {
this.$emit('delCopyList',index)
},
}
}
</script>
<style lang="scss" scoped>
.affiliation {
background-color: #fff;
margin-bottom: 20rpx;
padding-bottom: 40rpx;
.aff_head {
height: 100rpx;
line-height: 100rpx;
padding-left: 30rpx;
}
.aff_con {
display: flex;
text-align: center;
flex-wrap: wrap;
.aff_item {
width: 100rpx;
margin-right: 15rpx;
margin-bottom:15rpx;
image {
margin-bottom: 15rpx;
width: 60rpx;
height: 60rpx;
border-radius: 50%;
}
}
.affbox {
position: relative;
.delremind {
width: 32rpx;
height: 32rpx;
border-radius: 50%;
position: absolute;
right: -16rpx;
top: -16rpx;
background: rgba(0, 0, 0, 0.5);
z-index: 2;
}
}
.aff_last {
image {
margin-bottom: 15rpx;
width: 80rpx;
height: 50rpx;
}
}
}
}
</style>

View File

@ -0,0 +1,137 @@
<template>
<view>
<view class="affiliation">
<view class="aff_head">
<text style="color: red;" v-if="flag">*</text>
{{title}}
<view class="order" v-if="title == '由谁审核'">依次审批</view>
</view>
<view class="aff_con">
<view class="aff_item affbox" v-for="(item,index) in remindPeople" :key="index">
<image :src="BASE_IMG_URL+'close.png'" class="delremind" v-if="item.isDel" @click="delRemind(index)" mode="scaleToFill"></image>
<image class="peopleimg" :src="item.img ? item.img : BASE_IMG_URL+'headImg.png'" mode="scaleToFill"></image>
<view>{{item.name}}</view>
</view>
<view class="aff_last" @click="moreClick">
<image :src="BASE_IMG_URL+'morebtn.png'" mode="scaleToFill"></image>
</view>
</view>
</view>
</view>
</template>
<script>
import { BASE_IMG_URL } from '@/util/api.js'
export default{
props:{
remindPeople:{
type:Array,
default:[]
},
title:{
type:String,
default:'由谁审核'
},
flag:{
type:Boolean,
default:true
}
},
data() {
return{
BASE_IMG_URL:BASE_IMG_URL
}
},
onShow() {
//
this.getDefaultRemind()
},
methods:{
//
moreClick() {
uni.navigateTo({
url: '/pagesA/crm/selectMember/selectMember',
success:()=>{
uni.setStorageSync('isJumpPage',true)
}
})
},
//
delRemind(index) {
this.$emit('delExamine',index)
},
}
}
</script>
<style lang="scss" scoped>
.info_head{
height: 80rpx;
line-height: 80rpx;
font-size: 30rpx;
color: #999;
padding-left: 69rpx;
}
.affiliation {
background-color: #fff;
margin-bottom: 20rpx;
padding-bottom: 40rpx;
.aff_head {
padding:30rpx 0 30rpx 47rpx;
font-size: 32rpx;
color: #999;
display: flex;
justify-content: flex-start;
align-items: center;
.order{
font-size:20rpx;
color:$uni-text-color;
padding:3rpx;
border:2rpx solid $uni-text-color;
border-radius: 5rpx;
margin-left:8rpx;
height:40rpx;
}
}
.aff_con {
display: flex;
flex-wrap: wrap;
text-align: center;
padding:0 20px;
.aff_item {
width: 100rpx;
margin-bottom:15rpx;
margin-right:15rpx;
.peopleimg{
width: 50rpx;
height: 50rpx;
border-radius: 50%;
}
}
.affbox {
position: relative;
.delremind {
width: 32rpx;
height: 32rpx;
border-radius: 50%;
position: absolute;
right: -16rpx;
top: -16rpx;
background: rgba(0, 0, 0, 0.5);
z-index: 2;
}
}
.aff_last {
width: 48rpx;
height: 48rpx;
border-radius: 50%;
// border: 1px solid #999999;
text-align: center;
image {
width:48rpx;
height: 48rpx;
}
}
}
}
</style>

View File

@ -0,0 +1,110 @@
<template>
<view class="boxwarp">
<view class="apptitle">审批流程</view>
<view class="approbox">
<view class="appli" v-for="(item,index) in list" :key="index">
<view class="xian"></view>
<view class="title" v-if="item.status == 1">指定员工(任意一人)</view>
<view class="title" v-if="item.status == 2">指定员工(会签)</view>
<view class="title" v-if="item.status == 3">直属上级</view>
<view class="stafflist">
<view class="staffli" v-for="(staffitem,staffindex) in item.stafflist" :key="staffindex">
<image :src="staffitem.img" class="staffimg" mode=""></image>
<view class="staffname">{{staffitem.name}}</view>
</view>
</view>
</view>
</view>
</view>
</template>
<script>
export default{
props:{
list:{
type:Array,
default:[]
}
},
data() {
return{
}
},
methods:{
}
}
</script>
<style lang="scss" scoped>
.boxwarp{
background:#fff;
width:100%;
padding-bottom:50rpx;
}
.apptitle{
padding:24rpx;
font-size: 32rpx;
color: #999;
}
.approbox{
padding:0 24rpx;
.appli{
padding-left:24rpx;
position: relative;
&::after{
content:'';
width:14rpx;
height:14rpx;
border-radius: 50%;
background:#5cbdb2;
position: absolute;
left:0;
top:10rpx;
}
&:last-child{
.xian{
display: none;
}
}
.xian{
width:2rpx;
height:calc(100% - 8rpx);
background:#5cbdb2;
position: absolute;
top:20rpx;
left:5rpx;
}
.title{
font-size:28rpx;
color:#666;
}
.stafflist{
display: flex;
justify-content: flex-start;
align-items: center;
flex-wrap: wrap;
margin-top:24rpx;
.staffli{
display: flex;
flex-direction: column;
align-items: center;
margin-right:24rpx;
margin-bottom:24rpx;
.staffimg{
width:60rpx;
height:60rpx;
border-radius: 50%;
margin-bottom:10rpx;
}
.staffname{
font-size:26rpx;
color:#999;
}
}
}
}
}
</style>

View File

@ -0,0 +1,520 @@
<template>
<view>
<view class="fllow_form" v-if="objInfo.component == 'input' && (objInfo.config.required ==true || !isNotRequired) && !objInfo.config.addShow">
<view><text :class="objInfo.config.required ==true ? 'b_color' : 'bo_color' ">*</text>{{objInfo.config.label}}</view>
<view class="form_input">
<input :type="objInfo.config.inputType?objInfo.config.inputType:'text'" v-if="isEdit" :class="objInfo.value ? 'valueActive' : '' " @input="changeInput"
placeholder-style="color:#999;font-size:32rpx;" :value="objInfo.value"
:placeholder="!isEdit ? '' : objInfo.config.placeholder" />
<view class="valueActive" v-if="!isEdit">{{objInfo.value?objInfo.value:''}}</view>
</view>
</view>
<view class="fllow_form" v-if="objInfo.component == 'input-number' && (objInfo.config.required ==true || !isNotRequired) && !objInfo.config.addShow">
<view><text :class="objInfo.config.required ==true ? 'b_color' : 'bo_color' ">*</text>{{objInfo.config.label}}</view>
<view class="form_input">
<input type="" @input="changeInput" :class="objInfo.value ? 'valueActive' : '' "
placeholder-style="color:#999;font-size:32rpx;" :disabled="!isEdit" :value="objInfo.value"
:placeholder="!isEdit ? '' : objInfo.config.placeholder" />
</view>
</view>
<view class="fllow_form" v-if="objInfo.component == 'select' && (objInfo.config.required ==true || !isNotRequired) && !objInfo.config.addShow">
<view><text :class="objInfo.config.required ==true ? 'b_color' : 'bo_color' ">*</text>{{objInfo.config.label}}</view>
<view class="form_right" @click="changeSelect">
<view :class="objInfo.value ? 'valueActive' : '' ">
{{!isEdit && !objInfo.value ? '' : objInfo.value ? objInfo.value : objInfo.config.placeholder}}
</view>
<view class="iconfont icon-arrows_right"></view>
</view>
</view>
<view class="fllow_form" v-if="objInfo.component == 'Rate' && (objInfo.config.required ==true || !isNotRequired) && !objInfo.config.addShow">
<view><text :class="objInfo.config.required ==true ? 'b_color' : 'bo_color' ">*</text>{{objInfo.config.label}}</view>
<view class="form_right">
<view>
<u-rate @change="changeRate" :disabled="!isEdit" v-model="objInfo.value" active-color="#FFD049" inactive-color="#b2b2b2" :size="35" :gutter="10"></u-rate>
</view>
</view>
</view>
<view class="fllow_form" v-if="objInfo.component == 'TimePicker' && (objInfo.config.required ==true || !isNotRequired) && !objInfo.config.addShow">
<view><text :class="objInfo.config.required ==true ? 'b_color' : 'bo_color' ">*</text>{{objInfo.config.label}}</view>
<picker @change="changeTime" @columnchange="changeColumn" mode="multiSelector" :disabled="!isEdit"
:range="dateTimeArray" :value="dateTime">
<view class="form_right">
<view :class="objInfo.value ? 'valueActive' : '' ">
{{objInfo.value ? objInfo.value : objInfo.config.placeholder}}
</view>
<view class="iconfont icon-arrows_right"></view>
</view>
</picker>
<!-- #ifdef MP-ALIPAY -->
<picker @change="changeAlipayTime" mode="date">
<view class="form_right" >
<view :class="objInfo.value ? 'valueActive' : '' ">
{{!isEdit && !objInfo.value ? '' : objInfo.value ? objInfo.value : objInfo.config.placeholder}}
</view>
<view class="iconfont icon-arrows_right"></view>
</view>
</picker>
<!-- #endif -->
</view>
<view class="fllow_area" v-if="objInfo.component == 'textarea' && (objInfo.config.required == true || !isNotRequired) && !objInfo.config.addShow">
<view class="area_head">
<text :class="objInfo.config.required == true ? 'b_color' : 'bo_color' ">*</text>
{{objInfo.config.label}}
</view>
<textarea
@input="changeTextarea"
maxlength="-1"
:auto-height="autoHeight"
:style="{height:height+'rpx'}"
:class="objInfo.value ? 'valueActive' : '' "
:value="objInfo.value ? objInfo.value : ''"
:disabled="!isEdit"
:placeholder="!isEdit ? '' : objInfo.config.placeholder"
placeholder-style="color:#999;font-size:32rpx;" />
</view>
<view class="fllow_form" v-if="objInfo.component == 'radio' && (objInfo.config.required ==true || !isNotRequired) && !objInfo.config.addShow">
<view><text :class="objInfo.config.required ==true ? 'b_color' : 'bo_color' ">*</text>{{objInfo.config.label}}</view>
<view class="form_right">
<radio-group @change="changeRadio" :disabled="!isEdit" class="labellist">
<label class="" class="labelbox" v-for="(item,index) in objInfo.config.content" :key="index">
<view>
<radio color="#008EFF" :disabled="!isEdit" :value="item.value"
:checked="item.value == objInfo.value" />
</view>
<view>{{item.value}}</view>
</label>
</radio-group>
</view>
</view>
<view class="fllow_area" v-if="objInfo.component == 'checkbox' && (objInfo.config.required ==true || !isNotRequired) && !objInfo.config.addShow">
<view class="area_head"><text :class="objInfo.config.required ==true ? 'b_color' : 'bo_color' ">*</text>{{objInfo.config.label}}</view>
<checkbox-group @change="changeCheckbox" style="display: flex;justify-content: flex-start;flex-wrap: wrap;" :value="objInfo.value">
<label class="" style="margin-right:15rpx;margin-bottom:25rpx;display: block;" v-for="(item,index) in objInfo.config.content" :key="index">
<checkbox class="checkbox" color="#ff7800" :value="item.value" :checked="objInfo.value.indexOf(item.value) != -1" :disabled="!isEdit"/>
<span>{{item.value}}</span>
</label>
</checkbox-group>
</view>
<!-- #ifdef MP-WEIXIN || APP-PLUS-->
<view class="fllow_form" v-if="objInfo.component == 'Cascader' && (objInfo.config.required ==true || !isNotRequired) && !objInfo.config.addShow">
<view><text :class="objInfo.config.required ==true ? 'b_color' : 'bo_color' ">*</text>{{objInfo.config.label}}</view>
<picker @change="changeAddress" :disabled="!isEdit" mode="region">
<view class="form_right">
<view :class="objInfo.value ? 'valueActive' : '' ">
{{!isEdit && !objInfo.value ? '' : objInfo.value ? objInfo.value : objInfo.config.placeholder}}
</view>
<view class="iconfont icon-arrows_right"></view>
</view>
</picker>
</view>
<!-- #endif -->
<!-- #ifdef MP-ALIPAY || H5 -->
<view class="fllow_form" v-if="objInfo.component == 'Cascader' && (objInfo.config.required ==true || !isNotRequired) && !objInfo.config.addShow">
<view><text :class="objInfo.config.required ==true ? 'b_color' : 'bo_color' ">*</text>{{objInfo.config.label}}</view>
<view class="form_right" v-if="!isEdit">
<view :class="objInfo.value ? 'valueActive' : '' ">{{!isEdit && !objInfo.value ? '' : objInfo.value ? objInfo.value : objInfo.config.placeholder}}</view>
<view class="iconfont icon-arrows_right"></view>
</view>
<view class="form_right" @click="show = true" v-else>
<view :class="objInfo.value ? 'valueActive' : '' ">{{!isEdit && !objInfo.value ? '' : objInfo.value ? objInfo.value : objInfo.config.placeholder}}</view>
<view class="iconfont icon-arrows_right"></view>
</view>
</view>
<!-- #endif -->
<view class="fllow_form" v-if="objInfo.component == 'DatePicker' && (objInfo.config.required ==true || !isNotRequired) && !objInfo.config.addShow">
<view><text :class="objInfo.config.required ==true ? 'b_color' : 'bo_color' ">*</text>{{objInfo.config.label}}</view>
<picker mode="date" @change="changeDate" :disabled="!isEdit">
<view class="form_right">
<view :class="objInfo.value ? 'valueActive' : '' ">
{{!isEdit && !objInfo.value ? '' : objInfo.value ? objInfo.value : objInfo.config.placeholder}}
</view>
<view class="iconfont icon-arrows_right"></view>
</view>
</picker>
</view>
<!-- 上传图片 -->
<upload-image
v-if="objInfo.component == 'uploadImage' && (objInfo.config.required || !isNotRequired) && !objInfo.config.addShow"
:flag="objInfo.config.required"
:imgList="objInfo.value?objInfo.value:[]"
@uploadImg="uploadImg"
@delImg="delImg"
:title="objInfo.config.label"
:single="objInfo.config.maxnum"
:isEdit="isEdit"
:istype="istype"
></upload-image>
<!-- 上传文件 -->
<upload-file
v-if="objInfo.component == 'uploadFile' && (objInfo.config.required || !isNotRequired) && !objInfo.config.addShow"
:title="objInfo.config.label"
:flag="objInfo.config.required"
:fileList="objInfo.value?objInfo.value:[]"
@uploadFile="uploadFile"
@delFile="delFile"
:isEdit="isEdit"
>
</upload-file>
<tki-tree
ref="tkitree"
v-if="objInfo.component == 'select'"
:range="objInfo.config.content"
:multiple="objInfo.config.multiple"
:rangeKey="'label'"
:idKey="'nodeKey'"
confirmColor="#008EFF"
@confirm="selectTree"
/>
<!-- 位置选择 -->
<u-select
v-model="show"
mode="mutil-column-auto"
value-name="code"
label-name="name"
child-name="children"
:list="addressList"
@confirm="confirm"
></u-select>
</view>
</template>
<script>
import {
dateTimePicker,
getMonthDay
} from '@/util/dateTimePicker.js'
import tkiTree from "@/components/tki-tree/tki-tree.vue"
import uploadImage from "@/components/uploadImg/index.vue"
import uploadFile from '@/components/uploadFile/index.vue'
const citysJSON = require('@/util/address.js');
export default {
props: {
objInfo: {
type: Object,
default: {}
},
isEdit: {
type: Boolean,
default: true
},
height: {
type: Number,
default: 300
},
autoHeight: {
type: Boolean,
default: false
},
index: {
type:Number,
default: null
},
isNotRequired:{
type:Boolean,
default:false
},
istype:{
type:String,
default:'all'
}
},
components: {
tkiTree,
uploadImage,
uploadFile
},
data() {
return {
dateTimeArray: [],
dateArr: [],
dateTime: [],
//
addressList:[],
show:false,
}
},
//
computed: {
},
watch:{
},
created() {
if (this.objInfo.component == 'TimePicker') {
this.initTime()
}
// #ifdef MP-ALIPAY || H5
if (this.objInfo.component == 'Cascader') {
this.addressList = citysJSON.citys
}
// #endif
},
onShow() {
},
methods: {
changeInput(e) {
let name = this.objInfo.id
let value = e.detail.value
this.$emit('changeData', name, value, this.objInfo)
},
changeSelect() {
if (this.isEdit) {
this.$refs.tkitree._show()
}
},
selectTree(arr) {
console.log(arr,'选择')
let name = this.objInfo.id
if(arr.length > 0) {
console.log('123456')
let value = []
arr.forEach(ele=>{
value.push(ele.label)
})
this.$emit('changeData', name, value.join(','), this.objInfo)
}else{
this.$emit('changeData', name, '', this.objInfo)
}
},
changeRate(e) {
let value = e
let name = this.objInfo.id
this.$emit('changeData', name, value, this.objInfo)
},
changeTextarea(e) {
let name = this.objInfo.id
let value = e.detail.value
this.$emit('changeData', name, value, this.objInfo)
},
changeRadio(e) {
let value = e.detail.value
let name = this.objInfo.id
this.$emit('changeData', name, value, this.objInfo)
},
changeCheckbox(e) {
let name = this.objInfo.id
let value = e.detail.value
this.$emit('changeData', name, value.join(','), this.objInfo)
},
changeAddress(e) {
let firstr = e.detail.value[0]
if (firstr.indexOf('市') != -1) {
let index = firstr.indexOf('市')
firstr = firstr.substring(0, index)
}
let address = firstr + '/' + e.detail.value[1] + '/' + e.detail.value[2]
let name = this.objInfo.id
this.$emit('changeData', name, address, this.objInfo)
},
confirm(e) {
let address = e[0].label+e[1].label+e[2].label
let name = this.objInfo.id
this.$emit('changeData', name, address, this.objInfo)
},
changeDate(e) {
let date = e.detail.value
let name = this.objInfo.id
this.$emit('changeData', name, date, this.objInfo)
},
withData(param) {
return param < 10 ? '0' + param : '' + param;
},
initTime() {
//
let obj = dateTimePicker()
//
let lastArray = obj.dateTimeArray.pop();
let lastTime = obj.dateTime.pop();
let lastDate = obj.dateArray.pop()
this.dateTimeArray = obj.dateTimeArray
this.dateArr = obj.dateArray
this.dateTime = obj.dateTime
},
changeColumn(e) {
let index = e.detail.column
let value = e.detail.value
if (index == 1) {
let obj = dateTimePicker()
//
let lastArray = obj.dateTimeArray.pop();
let lastTime = obj.dateTime.pop();
let lastDate = obj.dateArray.pop()
this.dateTimeArray = obj.dateTimeArray
this.dateArr = obj.dateArray
this.dateTime = obj.dateTime
}
},
//
changeTime(e) {
let arr = e.detail.value
if (arr.includes(-1)) {
uni.showToast({
title: '请选择正确的时间',
icon: 'none'
})
return
}
let str = this.handleTime(arr)
let name = this.objInfo.id
this.$emit('changeData', name, str, this.objInfo,this.index)
},
changeAlipayTime(e) {
let name = this.objInfo.id
this.$emit('changeData', name, e.detail.value, this.objInfo)
},
handleTime(arr) {
let year = this.dateArr[0][arr[0]]
let month = this.dateArr[1][arr[1]]
let day = this.dateArr[2][arr[2]]
let hour = this.dateArr[3][arr[3]]
let minu = this.dateArr[4][arr[4]]
let str = year + '-' + month + '-' + day + ' ' + hour + ':' + minu
return str
},
//
uploadImg(obj){
let name = this.objInfo.id
let arr = this.objInfo.value?this.objInfo.value:[]
arr.push(obj)
this.$emit('changeData', name, arr, this.objInfo)
},
delImg(index) {
let name = this.objInfo.id
let arr = this.objInfo.value
arr.splice(index,1)
this.$emit('changeData', name, arr, this.objInfo)
},
//
uploadFile(obj) {
let name = this.objInfo.id
let arr = this.objInfo.value?this.objInfo.value:[]
arr.push(obj)
this.$emit('changeData', name, arr, this.objInfo)
},
delFile(index) {
let name = this.objInfo.id
let arr = this.objInfo.value
arr.splice(index,1)
this.$emit('changeData', name, arr, this.objInfo)
}
}
}
</script>
<style lang="scss">
.b_color{
color: #f00;
}
.bo_color{
color: #ffffff;
}
.valueActive {
color: #333;
}
.labellist {
width: 100%;
display: flex;
justify-content: flex-start;
flex-wrap: wrap;
.labelbox {
display: flex;
justify-content: flex-start;
align-items: center;
}
}
radio {
transform: scale(0.6);
}
.sales_item {
display: flex;
justify-content: flex-start;
padding-bottom: 15rpx;
flex-wrap: wrap;
.checkbox {
display: flex;
justify-content: flex-start;
margin-right: 20rpx;
margin-bottom: 20rpx;
}
}
.u-checkbox__icon {
width: 20rpx;
height: 20rpx;
}
</style>
<style lang="scss" scoped>
.fllow_form {
display: flex;
justify-content: space-between;
align-items: center;
background-color: #fff;
border-bottom: 1rpx solid #EAEAEA;
padding: 30rpx 20rpx;
color: #999;
font-size: 32rpx;
:first-child {
flex-shrink: 0;
font-weight: 32rpx;
}
.form_right {
display: flex;
align-items: center;
justify-content:flex-end;
flex-wrap: wrap;
color: #999;
text-align: right;
font-weight: 32rpx;
}
.theme {
color: #5ca9fe;
}
text {
// color: #f00;
margin-left: 10rpx;
}
.form_input {
input {
text-align: right;
margin-right: 10rpx;
}
}
}
.fllow_area {
background-color: #fff;
padding: 30rpx 20rpx;
padding-bottom: 30rpx;
color: #999;
font-size: 32rpx;
.area_head {
margin-bottom:24rpx;
}
textarea {
width: 80%;
height: 300rpx;
padding: 30rpx;
background: #f8f8f8;
margin: 0 auto;
}
}
</style>

View File

@ -0,0 +1,423 @@
<template>
<view class="">
<!-- 输入框 -->
<view class="fir_li" v-if="objInfo.form_type == 'input'">
<view class="li_label">{{objInfo.name}}</view>
<view class="li_box">
<view class="form_right">
<input type="text" class="inputBox" :value="objInfo.value" @input="changeInput" :placeholder="objInfo.input_tips">
<view class="iconfont icon-arrows_right"></view>
</view>
</view>
</view>
<!-- 时间选择器 年月日 -->
<view class="fir_li" v-if="objInfo.form_type == 'DatePicker'">
<view class="li_label">{{objInfo.name}}</view>
<view class="li_box" style="display: flex;">
<picker @change="changeStartDate" mode="date" :end="objInfo.end_time"
style="width:50%;border-right:1rpx solid #CCCCCC">
<view class="form_right">
<view style="flex:1;text-align: center;"
:class="objInfo.start_time ? 'valueactive' : '' ">
{{objInfo.start_time ? objInfo.start_time : '开始时间'}}</view>
</view>
</picker>
<picker @change="changeEndDate" mode="date" :start="objInfo.start_time" style="width:50%">
<view class="form_right">
<view style="flex:1;text-align: center;"
:class="objInfo.end_time ? 'valueactive' : '' ">{{objInfo.end_time ? objInfo.end_time : '结束时间'}}
</view>
</view>
</picker>
</view>
</view>
<!-- 时间选择器 年月日 时分 -->
<view class="fir_li" v-if="objInfo.form_type == 'TimePicker'">
<view class="li_label">{{objInfo.name}}</view>
<view class="li_box" style="display: flex;">
<picker mode="multiSelector"
:range="dateTimeArray"
:value="dateTime"
@change="changeStartTime"
@columnchange="changeColumn"
style="width:50%;border-right:1rpx solid #CCCCCC">
<view class="form_right">
<view style="flex:1;text-align: center;"
:class="objInfo.start_time ? 'valueactive' : '' ">
{{objInfo.start_time ? objInfo.start_time : '开始时间'}}</view>
</view>
</picker>
<picker
mode="multiSelector"
:range="dateTimeArray"
:value="dateTime"
@change="changeEndTime"
@columnchange="changeColumn"
style="width:50%">
<view class="form_right">
<view style="flex:1;text-align: center;"
:class="objInfo.end_time ? 'valueactive' : '' ">{{objInfo.end_time ? objInfo.end_time : '结束时间'}}
</view>
</view>
</picker>
</view>
</view>
<!-- 文本框 -->
<view class="fir_li" v-if="objInfo.form_type == 'textarea'">
<view class="li_label">{{objInfo.name}}</view>
<view class="li_box_text">
<view class="form_right">
<textarea :value="objInfo.value ? objInfo.value : ''" :placeholder="objInfo.input_tips" @input="changeTextarea" />
</view>
</view>
</view>
<!-- 数字输入框 -->
<view class="fir_li" v-if="objInfo.form_type == 'input-number'">
<view class="li_label">{{objInfo.name}}</view>
<view class="li_box">
<view class="form_right">
<input type="digit" class="inputBox" @input="changeInputNumber" :class="objInfo.value ? 'valueActive' : '' "
placeholder-style="color:#999;font-size:32rpx;" :value="objInfo.value"
:placeholder="objInfo.input_tips" />
<view class="iconfont icon-arrows_right"></view>
</view>
</view>
</view>
<!-- 单选框 -->
<view class="fir_li" v-if="objInfo.form_type == 'radio'">
<view class="li_label">{{objInfo.name}}</view>
<view class="li_box_radio">
<view class="ra_box" v-for="(item,index) in objInfo.content" :key="index" @click="changeRadio(item)">
<radio :value="item" color="#008EFF" :checked="item == objInfo.value" />{{item}}
</view>
</view>
</view>
<!-- 多选框 -->
<view class="fir_li" v-if="objInfo.form_type == 'checkbox'">
<view class="li_label">{{objInfo.name}}</view>
<view class="li_box_radio">
<checkbox-group @change="changeCheckbox" style="display: flex;justify-content: flex-start;flex-wrap: wrap;" :value="objInfo.value">
<label class="" style="margin-right:15rpx;margin-bottom:25rpx;display: block;" v-for="(item,index) in objInfo.content" :key="index">
<checkbox class="checkbox" color="#ff7800" :value="item" :checked="objInfo.value.indexOf(item) != -1"/>
<span>{{item}}</span>
</label>
</checkbox-group>
</view>
</view>
<!-- 评分 -->
<view class="fir_li" v-if="objInfo.form_type == 'Rate'">
<view class="li_label">{{objInfo.name}}</view>
<view class="li_box_radio">
<u-rate @change="changeRate" v-model="objInfo.value" active-color="#FFD049" inactive-color="#b2b2b2" :size="35" :gutter="10"></u-rate>
</view>
</view>
<!-- 区域筛选 -->
<!-- #ifdef MP-WEIXIN || APP-PLUS-->
<view class="fir_li" v-if="objInfo.form_type == 'Cascader'">
<view class="li_label">{{objInfo.name}}</view>
<view class="li_box">
<picker @change="changeAddress" mode="region">
<view class="form_right">
<view :class="objInfo.value ? 'valueActive' : '' ">
{{objInfo.value ? objInfo.value : objInfo.input_tips}}
</view>
<view class="iconfont icon-arrows_right"></view>
</view>
</picker>
</view>
</view>
<!-- #endif -->
<!-- #ifdef MP-ALIPAY || H5 -->
<view class="fir_li" v-if="objInfo.form_type == 'Cascader'">
<view class="li_label">{{objInfo.name}}</view>
<view class="li_box">
<view class="form_right" @click="show = true" >
<view :class="objInfo.value ? 'valueActive' : '' ">{{objInfo.value ? objInfo.value : objInfo.input_tips}}</view>
<view class="iconfont icon-arrows_right"></view>
</view>
</view>
</view>
<!-- #endif -->
<!-- 下拉选择 -->
<view class="fir_li" v-if="objInfo.form_type == 'select'">
<view class="li_label">{{objInfo.name}}</view>
<view class="li_box">
<picker @change="changeSelect" :range="objInfo.content" :range-key="'label'">
<view class="form_right">
<view :class="objInfo.value ? 'valueActive' : '' ">
{{objInfo.value ? objInfo.value : objInfo.input_tips}}
</view>
<view class="iconfont icon-arrows_right"></view>
</view>
</picker>
<!-- <view class="form_right" @click="changeSelect" >
<view :class="objInfo.value ? 'valueActive' : '' ">{{objInfo.value ? objInfo.value : objInfo.input_tips}}</view>
<view class="iconfont icon-arrows_right"></view>
</view> -->
</view>
</view>
<!-- 位置选择 -->
<u-select
v-model="show"
mode="mutil-column-auto"
value-name="code"
label-name="name"
child-name="children"
:list="addressList"
@confirm="confirm"
></u-select>
<!-- 单选 -->
<tki-tree
ref="treeChild"
:range="objInfo.content"
:rangeKey="'label'"
:idKey="'nodeKey'"
confirmColor="#008EFF"
@confirm="selectTree"
></tki-tree>
</view>
</template>
<script>
import { dateTimePicker, getMonthDay } from '@/util/dateTimePicker.js'
import tkiTree from "@/components/tki-tree/tki-tree.vue"
const citysJSON = require('@/util/address.js');
export default{
data() {
return{
dateTimeArray: [],
dateArr: [],
dateTime: [],
showTree:false,
//
addressList:[],
show:false,
}
},
props:{
objInfo: {
type: Object,
default: {}
},
},
created() {
if (this.objInfo.form_type == 'TimePicker') {
this.initTime()
}
// #ifdef MP-ALIPAY || H5
if (this.objInfo.component == 'Cascader') {
this.addressList = citysJSON.citys
}
// #endif
},
methods:{
withData(param) {
return param < 10 ? '0' + param : '' + param;
},
initTime() {
let date = new Date()
let endYear = date.getFullYear()
let mont = this.withData(date.getMonth() + 1)
let day = this.withData(date.getDate())
let hour = this.withData(date.getHours())
let minu = this.withData(date.getMinutes())
let seco = this.withData(date.getSeconds())
//
let obj = dateTimePicker();
//
let lastArray = obj.dateTimeArray.pop();
let lastTime = obj.dateTime.pop();
let lastDate = obj.dateArray.pop()
this.dateTimeArray = obj.dateTimeArray
this.dateArr = obj.dateArray
this.dateTime = obj.dateTime
},
changeColumn(e) {
let index = e.detail.column
let value = e.detail.value
if (index == 1) {
let month = this.dateArr[index][value]
let date = new Date();
let endYear = date.getFullYear();
let obj = dateTimePicker();
//
let lastArray = obj.dateTimeArray.pop();
let lastTime = obj.dateTime.pop();
let lastDate = obj.dateArray.pop()
this.dateTimeArray = obj.dateTimeArray
this.dateArr = obj.dateArray
this.dateTime = obj.dateTime
}
},
handleTime(arr) {
let year = this.dateArr[0][arr[0]]
let month = this.dateArr[1][arr[1]]
let day = this.dateArr[2][arr[2]]
let hour = this.dateArr[3][arr[3]]
let minu = this.dateArr[4][arr[4]]
let str = year + '-' + month + '-' + day + ' ' + hour + ':' + minu
return str
},
//
changeStartTime(e) {
let arr = e.detail.value
if (arr.includes(-1)) {
uni.showToast({
title: '请选择正确的时间',
icon: 'none'
})
return
}
let str = this.handleTime(arr)
this.$emit('changeSearchData',this.objInfo.field,'start_time',str)
if(!this.objInfo.end_time){
this.$emit('changeSearchData',this.objInfo.field,'end_time',str)
}
},
//
changeEndTime(e) {
let arr = e.detail.value
if (arr.includes(-1)) {
uni.showToast({
title: '请选择正确的时间',
icon: 'none'
})
return
}
let str = this.handleTime(arr)
this.$emit('changeSearchData',this.objInfo.field,'end_time',str)
if(!this.objInfo.start_time){
this.$emit('changeSearchData',this.objInfo.field,'start_time',str)
}
},
//
changeInput(e) {
let value = e.detail.value
this.$emit('changeSearchData',this.objInfo.field,'value',value)
},
//
changeStartDate(e) {
let value = e.detail.value
this.$emit('changeSearchData',this.objInfo.field,'start_time',value)
if(!this.objInfo.end_time){
this.$emit('changeSearchData',this.objInfo.field,'end_time',value)
}
},
//
changeEndDate(e) {
let value = e.detail.value
this.$emit('changeSearchData',this.objInfo.field,'end_time',value)
if(!this.objInfo.start_time){
this.$emit('changeSearchData',this.objInfo.field,'start_time',value)
}
},
//
changeTextarea(e) {
let value = e.detail.value
this.$emit('changeSearchData', this.objInfo.field, 'value',value)
},
//
changeInputNumber(e) {
let value = e.detail.value
this.$emit('changeSearchData', this.objInfo.field, 'value',value)
},
//
changeRadio(item) {
this.$emit('changeSearchData', this.objInfo.field, 'value',item)
},
//
changeCheckbox(e) {
let arr = e.detail.value
this.$emit('changeSearchData', this.objInfo.field, 'value',arr.join(','))
},
//
changeRate(e) {
this.$emit('changeSearchData', this.objInfo.field, 'value', e)
},
//
changeAddress(e) {
let arr = e.detail.value
this.$emit('changeSearchData', this.objInfo.field, 'value', arr.join('/'))
},
confirm(e) {
let address = e[0].label+e[1].label+e[2].label
this.$emit('changeSearchData', this.objInfo.field, 'value', address)
},
//
changeSelect(e) {
// this.$refs.treeChild._show()
let index = e.detail.value
let value = this.objInfo.content[index].label
this.$emit('changeSearchData', this.objInfo.field, 'value', value)
},
selectTree(arr) {
let value = []
arr.forEach(ele=>{
value.push(ele.label)
})
this.$emit('changeSearchData', this.objInfo.field, 'value', value.join(','))
},
}
}
</script>
<style lang="scss" scoped>
.fir_li {
margin-bottom: 20rpx;
.li_label {
font-size: 28rpx;
color: #333333;
margin-bottom: 15rpx;
}
.li_box {
border-radius: 15rpx;
border: 1rpx solid #CCCCCC;
height: 60rpx;
padding: 0 35rpx;
line-height: 60rpx;
.form_right {
display: flex;
justify-content: space-between;
color: #999;
.inputBox{
width:85%;
height: 60rpx;
line-height: 60rpx;
}
}
}
.li_box_text{
border-radius: 15rpx;
border: 1rpx solid #CCCCCC;
padding: 0 35rpx;
.form_right{
textarea{
width:100%;
}
}
}
.li_box_radio{
margin:24rpx 0;
display: flex;
justify-content: flex-start;
flex-wrap: wrap;
.ra_box{
display: flex;
justify-content: center;
margin-right:15rpx;
radio{
transform: scale(0.7);
}
}
}
}
</style>

View File

@ -0,0 +1,212 @@
<template>
<view>
<uni-popup ref="popup" type="bottom" background-color="#fff" @touchmove.stop.prevent>
<view class="popup_title">选择商机</view>
<view class="searbox">
<image :src="BASE_IMG_URL+'ss.png'" class="searimg" mode="scaleToFill"></image>
<input @input="searchName" type="text" placeholder-style="color:#999;"
:class="keyword ? 'fontactive' : ''" v-model="keyword" placeholder="商机名称" class="li_box" />
</view>
<scroll-view scroll-y class="scrollbox" lower-threshold="30">
<view class="liwarp" v-for="(item,index) in businesslist" :key="index" @click="selectItem(item,index)">
<view class="warpleft">
<view class="name">名称:{{item.name}}</view>
</view>
<label class="radio">
<radio value="r1" color="#008EFF" :checked="businessObj.id == item.id" />
</label>
</view>
<view class="noData" v-if="businesslist.length == 0">暂无更多</view>
</scroll-view>
<view class="btnlist" @tap.stop.prevent>
<view class="btn secbtn" @click="hideSelect">取消</view>
<view class="btn firbtn" @click="sureSelect">确定</view>
</view>
</uni-popup>
</view>
</template>
<script>
import { netRelationBusiness, netSelectBusinessList } from '@/api/index.js'
import { BASE_IMG_URL } from '@/util/api.js'
export default{
props:{
},
data(){
return{
keyword:'',
businesslist:[],
page:1,
totalPage:1,
businessObj:{},
customer_id:'',
BASE_IMG_URL:BASE_IMG_URL
}
},
methods:{
init(id) {
if(id){
this.customer_id = id
}
this.$refs.popup.open()
this.page = 1
this.businesslist = []
this.getList()
},
getList() {
if(this.customer_id){
let params = {
page:this.page,
name:this.keyword,
customer_id:this.customer_id
}
netRelationBusiness(params).then(res=>{
this.businesslist = res.data
})
}else{
let params = {
page:this.page,
name:this.keyword,
}
netSelectBusinessList(params).then(res=>{
this.businesslist = res.data.data
this.totalPage = res.data.last_page
})
}
},
loadMoredata() {
if(this.page >= this.totalPage){
return
}
this.page ++
this.getList()
},
searchName(e) {
this.page = 1
this.businesslist = []
this.getList()
},
selectItem(item,index) {
this.businessObj = item
},
closePopup() {
this.$refs.popup.close()
},
sureSelect() {
if(!this.businessObj){
this.$refs.popup.close()
return
}
this.$refs.popup.close()
this.$emit('sureBusiness',this.businessObj)
},
hideSelect() {
this.$refs.popup.close()
}
}
}
</script>
<style>
radio{
transform: scale(0.7);
}
</style>
<style lang="scss" scoped>
.popup_title{
text-align: center;
font-size:34rpx;
color:#333;
padding:24rpx;
}
.searbox{
width:690rpx;
height:60rpx;
margin:0 24rpx 15rpx;
border-radius: 30rpx;
padding:0 24rpx;
display: flex;
justify-content: flex-start;
align-items: center;
background:#f5f5f5;
.searimg{
width: 50rpx;
height: 50rpx;
margin-right:10rpx;
}
.li_box{
width:630rpx;
}
}
.scrollbox{
width:100%;
height:600rpx;
background:#f5f5f5;
.liwarp {
width: 702rpx;
padding: 20rpx 30rpx;
margin: 20rpx auto;
background: #fff;
border-radius: 10rpx;
display: flex;
justify-content: space-between;
align-items: center;
.warpleft {
flex: 1;
display: flex;
justify-content: flex-start;
align-items: center;
.headerimg {
width: 50rpx;
height: 50rpx;
border-radius: 50%;
margin-right: 15rpx;
}
.name {
font-size: 24rpx;
color: #333;
}
.number {
font-size: 24rpx;
color: #999;
margin: 15rpx 0;
}
.guishu {
font-size: 24rpx;
color: #666;
}
}
}
}
.btnlist {
width: 750rpx;
display: flex;
justify-content: space-around;
padding: 30rpx 0;
border-top:1rpx solid #f5f5f5;
.btn {
width: 200rpx;
height: 60rpx;
border-radius: 30rpx;
font-size: 24rpx;
color: #fff;
text-align: center;
line-height: 60rpx;
}
.firbtn {
background: #14C2C1;
}
.secbtn {
background: #ff7800;
}
}
</style>

182
components/selectClue.vue Normal file
View File

@ -0,0 +1,182 @@
<template>
<view>
<uni-popup ref="popup" type="bottom" background-color="#fff" @touchmove.stop.prevent>
<view class="popup_title">选择线索</view>
<view class="searbox">
<image :src="BASE_IMG_URL+'ss.png'" class="searimg" mode="scaleToFill"></image>
<input @input="searchName" type="text" placeholder-style="color:#999;"
:class="keyword ? 'fontactive' : ''" v-model="keyword" placeholder="线索名称" class="li_box" />
</view>
<scroll-view scroll-y class="scrollbox" lower-threshold="30">
<view class="liwarp" v-for="(item,index) in clueList" :key="index" @click="selectItem(item,index)">
<view class="warpleft">
<view class="name">名称:{{item.name}}</view>
</view>
<label class="radio">
<radio value="r1" color="#008EFF" :checked="clueObj.id == item.id" />
</label>
</view>
<view class="noData" v-if="clueList.length == 0">暂无更多</view>
</scroll-view>
<view class="btnlist" @tap.stop.prevent>
<view class="btn secbtn" @click="hideSelect">取消</view>
<view class="btn firbtn" @click="sureSelect">确定</view>
</view>
</uni-popup>
</view>
</template>
<script>
import { netGetNopageClueslist } from '@/api/clues.js'
import { BASE_IMG_URL } from '@/util/api.js'
export default{
props:{
},
data(){
return{
keyword:'',
clueList:[],
clueObj:{},
BASE_IMG_URL:BASE_IMG_URL
}
},
methods:{
init() {
this.$refs.popup.open()
this.clueList = []
this.getLianxiren()
},
//
getLianxiren() {
netGetNopageClueslist({name:this.keyword}).then(res=>{
this.clueList = res.data
})
},
searchName(e) {
this.clueList = []
this.getLianxiren()
},
selectItem(item,index) {
this.clueObj = item
},
closePopup() {
this.$refs.popup.close()
},
sureSelect() {
if(!this.clueObj){
this.$refs.popup.close()
return
}
this.$refs.popup.close()
this.$emit('clueInfo',this.clueObj)
},
hideSelect() {
this.$refs.popup.close()
}
}
}
</script>
<style>
radio{
transform: scale(0.7);
}
</style>
<style lang="scss" scoped>
.popup_title{
text-align: center;
font-size:34rpx;
color:#333;
padding:24rpx;
}
.searbox{
width:690rpx;
height:60rpx;
margin:0 24rpx 15rpx;
border-radius: 30rpx;
padding:0 24rpx;
display: flex;
justify-content: flex-start;
align-items: center;
background:#f5f5f5;
.searimg{
width: 50rpx;
height: 50rpx;
margin-right:10rpx;
}
.li_box{
width:630rpx;
}
}
.scrollbox{
width:100%;
height:600rpx;
background:#f5f5f5;
.liwarp {
width: 702rpx;
padding: 20rpx 30rpx;
margin: 20rpx auto;
background: #fff;
border-radius: 10rpx;
display: flex;
justify-content: space-between;
align-items: center;
.warpleft {
flex: 1;
display: flex;
justify-content: flex-start;
align-items: center;
.headerimg {
width: 50rpx;
height: 50rpx;
border-radius: 50%;
margin-right: 15rpx;
}
.name {
font-size: 24rpx;
color: #333;
}
.number {
font-size: 24rpx;
color: #999;
margin: 15rpx 0;
}
.guishu {
font-size: 24rpx;
color: #666;
}
}
}
}
.btnlist {
width: 750rpx;
display: flex;
justify-content: space-around;
padding: 30rpx 0;
border-top:1rpx solid #f5f5f5;
.btn {
width: 200rpx;
height: 60rpx;
border-radius: 30rpx;
font-size: 24rpx;
color: #fff;
text-align: center;
line-height: 60rpx;
}
.firbtn {
background: #14C2C1;
}
.secbtn {
background: #ff7800;
}
}
</style>

View File

@ -0,0 +1,190 @@
<template>
<view>
<uni-popup ref="popup" type="bottom" background-color="#fff" @touchmove.stop.prevent>
<view class="popup_title">选择合同</view>
<view class="searbox">
<image :src="BASE_IMG_URL+'ss.png'" class="searimg" mode="scaleToFill"></image>
<input @input="searchName" type="text" placeholder-style="color:#999;"
:class="keyword ? 'fontactive' : ''" v-model="keyword" placeholder="合同名称" class="li_box" />
</view>
<scroll-view scroll-y class="scrollbox" lower-threshold="30">
<view class="liwarp" v-for="(item,index) in contractList" :key="index" @click="selectItem(item,index)">
<view class="warpleft">
<view class="name">名称:{{item.name}}</view>
</view>
<label class="radio">
<radio value="r1" color="#008EFF" :checked="contractObj.id == item.id" />
</label>
</view>
<view class="noData" v-if="contractList.length == 0">暂无更多</view>
</scroll-view>
<view class="btnlist" @tap.stop.prevent>
<view class="btn secbtn" @click="hideSelect">取消</view>
<view class="btn firbtn" @click="sureSelect">确定</view>
</view>
</uni-popup>
</view>
</template>
<script>
import { netSelectContract } from '@/api/kehu.js'
import { BASE_IMG_URL } from '@/util/api.js'
export default{
props:{
},
data(){
return{
customer_id:'', //id
keyword:'',
contractList:[],
contractObj:{},
BASE_IMG_URL:BASE_IMG_URL
}
},
methods:{
init(id) {
if(id){
this.customer_id = id
}
this.$refs.popup.open()
this.contractList = []
this.getContract()
},
//
getContract() {
let params = {
name:this.keyword,
customer_id:this.customer_id
}
netSelectContract(params).then(res=>{
this.contractList = res.data
})
},
searchName(e) {
this.contractList = []
this.getContract()
},
selectItem(item,index) {
this.contractObj = item
},
closePopup() {
this.$refs.popup.close()
},
sureSelect() {
if(!this.contractObj){
this.$refs.popup.close()
return
}
this.$refs.popup.close()
this.$emit('contractInfo',this.contractObj)
},
hideSelect() {
this.$refs.popup.close()
}
}
}
</script>
<style>
radio{
transform: scale(0.7);
}
</style>
<style lang="scss" scoped>
.popup_title{
text-align: center;
font-size:34rpx;
color:#333;
padding:24rpx;
}
.searbox{
width:690rpx;
height:60rpx;
margin:0 24rpx 15rpx;
border-radius: 30rpx;
padding:0 24rpx;
display: flex;
justify-content: flex-start;
align-items: center;
background:#f5f5f5;
.searimg{
width: 50rpx;
height: 50rpx;
margin-right:10rpx;
}
.li_box{
width:630rpx;
}
}
.scrollbox{
width:100%;
height:600rpx;
background:#f5f5f5;
.liwarp {
width: 702rpx;
padding: 20rpx 30rpx;
margin: 20rpx auto;
background: #fff;
border-radius: 10rpx;
display: flex;
justify-content: space-between;
align-items: center;
.warpleft {
flex: 1;
display: flex;
justify-content: flex-start;
align-items: center;
.headerimg {
width: 50rpx;
height: 50rpx;
border-radius: 50%;
margin-right: 15rpx;
}
.name {
font-size: 24rpx;
color: #333;
}
.number {
font-size: 24rpx;
color: #999;
margin: 15rpx 0;
}
.guishu {
font-size: 24rpx;
color: #666;
}
}
}
}
.btnlist {
width: 750rpx;
display: flex;
justify-content: space-around;
padding: 30rpx 0;
border-top:1rpx solid #f5f5f5;
.btn {
width: 200rpx;
height: 60rpx;
border-radius: 30rpx;
font-size: 24rpx;
color: #fff;
text-align: center;
line-height: 60rpx;
}
.firbtn {
background: #14C2C1;
}
.secbtn {
background: #ff7800;
}
}
</style>

View File

@ -0,0 +1,194 @@
<template>
<view>
<uni-popup ref="popup" type="bottom" background-color="#fff" @touchmove.stop.prevent>
<view class="popup_title">选择客户</view>
<view class="searbox">
<image :src="BASE_IMG_URL+'ss.png'" class="searimg" mode="scaleToFill"></image>
<input @input="searchName" type="text" placeholder-style="color:#999;"
:class="keyword ? 'fontactive' : ''" v-model="keyword" placeholder="客户名称" class="li_box" />
</view>
<scroll-view scroll-y class="scrollbox" @scrolltolower="loadMoredata" lower-threshold="30">
<view class="liwarp" v-for="(item,index) in customerlist" :key="index" @click="selectItem(item,index)">
<view class="warpleft">
<view class="name">名称:{{item.name}}</view>
</view>
<label class="radio">
<radio value="r1" color="#008EFF" :checked="preseCustomerObj.id == item.id" />
</label>
</view>
<view class="noData" v-if="customerlist.length == 0">暂无更多</view>
</scroll-view>
<view class="btnlist" @tap.stop.prevent>
<view class="btn secbtn" @click="hideSelect">取消</view>
<view class="btn firbtn" @click="sureSelect">确定</view>
</view>
</uni-popup>
</view>
</template>
<script>
import { netKehuList } from '@/api/kehu.js'
import { BASE_IMG_URL } from '@/util/api.js'
export default{
props:{
},
data(){
return{
keyword:'',
customerlist:[],
page:1,
totalPage:1,
preseCustomerObj:{},
BASE_IMG_URL:BASE_IMG_URL
}
},
methods:{
init() {
this.$refs.popup.open()
this.page = 1
this.customerlist = []
this.getList()
},
getList() {
let params = {page:this.page,name:this.keyword}
netKehuList(params).then(res=>{
this.customerlist = this.customerlist.concat(res.data.data)
this.totalPage = res.data.last_page
})
},
loadMoredata() {
if(this.page >= this.totalPage){
return
}
this.page ++
this.getList()
},
searchName(e) {
this.page = 1
this.customerlist = []
this.getList()
},
selectItem(item,index) {
this.preseCustomerObj = item
},
closePopup() {
this.$refs.popup.close()
},
sureSelect() {
if(!this.preseCustomerObj){
this.$refs.popup.close()
return
}
this.$refs.popup.close()
this.$emit('getCustomerinfo',this.preseCustomerObj)
},
hideSelect() {
this.$refs.popup.close()
}
}
}
</script>
<style>
radio{
transform: scale(0.7);
}
</style>
<style lang="scss" scoped>
.popup_title{
text-align: center;
font-size:34rpx;
color:#333;
padding:24rpx;
}
.searbox{
width:690rpx;
height:60rpx;
margin:0 24rpx 15rpx;
border-radius: 30rpx;
padding:0 24rpx;
display: flex;
justify-content: flex-start;
align-items: center;
background:#f5f5f5;
.searimg{
width: 50rpx;
height: 50rpx;
margin-right:10rpx;
}
.li_box{
width:630rpx;
}
}
.scrollbox{
width:100%;
height:600rpx;
background:#f5f5f5;
.liwarp {
width: 702rpx;
padding: 20rpx 30rpx;
margin: 20rpx auto;
background: #fff;
border-radius: 10rpx;
display: flex;
justify-content: space-between;
align-items: center;
.warpleft {
flex: 1;
display: flex;
justify-content: flex-start;
align-items: center;
.headerimg {
width: 50rpx;
height: 50rpx;
border-radius: 50%;
margin-right: 15rpx;
}
.name {
font-size: 24rpx;
color: #333;
}
.number {
font-size: 24rpx;
color: #999;
margin: 15rpx 0;
}
.guishu {
font-size: 24rpx;
color: #666;
}
}
}
}
.btnlist {
width: 750rpx;
display: flex;
justify-content: space-around;
padding: 30rpx 0;
border-top:1rpx solid #f5f5f5;
.btn {
width: 200rpx;
height: 60rpx;
border-radius: 30rpx;
font-size: 24rpx;
color: #fff;
text-align: center;
line-height: 60rpx;
}
.firbtn {
background: #14C2C1;
}
.secbtn {
background: #ff7800;
}
}
</style>

190
components/selectLink.vue Normal file
View File

@ -0,0 +1,190 @@
<template>
<view>
<uni-popup ref="popup" type="bottom" background-color="#fff" @touchmove.stop.prevent>
<view class="popup_title">选择联系人</view>
<view class="searbox">
<image :src="BASE_IMG_URL+'ss.png'" class="searimg" mode="scaleToFill"></image>
<input @input="searchName" type="text" placeholder-style="color:#999;"
:class="keyword ? 'fontactive' : ''" v-model="keyword" placeholder="联系人名称" class="li_box" />
</view>
<scroll-view scroll-y class="scrollbox" lower-threshold="30">
<view class="liwarp" v-for="(item,index) in linkList" :key="index" @click="selectItem(item,index)">
<view class="warpleft">
<view class="name">名称:{{item.name}} <text>{{item.customer?'('+item.customer.name+')':''}}</text> </view>
</view>
<label class="radio">
<radio value="r1" color="#008EFF" :checked="linkObj.id == item.id" />
</label>
</view>
<view class="noData" v-if="linkList.length == 0">暂无更多</view>
</scroll-view>
<view class="btnlist" @tap.stop.prevent>
<view class="btn secbtn" @click="hideSelect">取消</view>
<view class="btn firbtn" @click="sureSelect">确定</view>
</view>
</uni-popup>
</view>
</template>
<script>
import { netLianxiren } from '@/api/kehu.js'
import { BASE_IMG_URL } from '@/util/api.js'
export default{
props:{
},
data(){
return{
keyword:'',
customer_id:'',
linkList:[],
linkObj:{},
BASE_IMG_URL:BASE_IMG_URL
}
},
methods:{
init(id) {
if(id){
this.customer_id = id
}
this.$refs.popup.open()
this.linkList = []
this.getLianxiren()
},
//
getLianxiren() {
let params = {
name:this.keyword,
customer_id:this.customer_id
}
netLianxiren(params).then(res=>{
this.linkList = res.data
})
},
searchName(e) {
this.linkList = []
this.getLianxiren()
},
selectItem(item,index) {
this.linkObj = item
},
closePopup() {
this.$refs.popup.close()
},
sureSelect() {
if(!this.linkObj){
this.$refs.popup.close()
return
}
this.$refs.popup.close()
this.$emit('linkInfo',this.linkObj)
},
hideSelect() {
this.$refs.popup.close()
}
}
}
</script>
<style>
radio{
transform: scale(0.7);
}
</style>
<style lang="scss" scoped>
.popup_title{
text-align: center;
font-size:34rpx;
color:#333;
padding:24rpx;
}
.searbox{
width:690rpx;
height:60rpx;
margin:0 24rpx 15rpx;
border-radius: 30rpx;
padding:0 24rpx;
display: flex;
justify-content: flex-start;
align-items: center;
background:#f5f5f5;
.searimg{
width: 50rpx;
height: 50rpx;
margin-right:10rpx;
}
.li_box{
width:630rpx;
}
}
.scrollbox{
width:100%;
height:600rpx;
background:#f5f5f5;
.liwarp {
width: 702rpx;
padding: 20rpx 30rpx;
margin: 20rpx auto;
background: #fff;
border-radius: 10rpx;
display: flex;
justify-content: space-between;
align-items: center;
.warpleft {
flex: 1;
display: flex;
justify-content: flex-start;
align-items: center;
.headerimg {
width: 50rpx;
height: 50rpx;
border-radius: 50%;
margin-right: 15rpx;
}
.name {
font-size: 24rpx;
color: #333;
}
.number {
font-size: 24rpx;
color: #999;
margin: 15rpx 0;
}
.guishu {
font-size: 24rpx;
color: #666;
}
}
}
}
.btnlist {
width: 750rpx;
display: flex;
justify-content: space-around;
padding: 30rpx 0;
border-top:1rpx solid #f5f5f5;
.btn {
width: 200rpx;
height: 60rpx;
border-radius: 30rpx;
font-size: 24rpx;
color: #fff;
text-align: center;
line-height: 60rpx;
}
.firbtn {
background: #14C2C1;
}
.secbtn {
background: #ff7800;
}
}
</style>

View File

@ -0,0 +1,313 @@
<template>
<view>
<uni-popup ref="popup" type="bottom" background-color="#fff">
<view class="popup_title">添加产品</view>
<view class="searbox">
<image :src="BASE_IMG_URL+'search.png'" class="searchimg" mode=""></image>
<input type="text" placeholder="输入产品编号/名称搜索" @input="queryList" class="selfinput">
</view>
<scroll-view scroll-y class="scrollbox" lower-threshold="30">
<view class="pop_list">
<view class="pop_li" v-for="(item,index) in list" :key="index">
<view class="pop_li_top">
<view class="pop_title">{{item.name}}</view>
<view class="pop_num">{{item.num}}</view>
</view>
<view class="pop_info" @tap.stop="changeSelect(index)">
<view class="pop_radio">
<radio color='#008EFF' :checked="item.select" ></radio>
</view>
<image :src="item.img ? item.img : BASE_IMG_URL+'img/index-4.png'" class="infoimg" mode=""></image>
<view class="pop_info_cen">
<view class="pop_info_text">单位{{item.unit}}</view>
<view class="pop_info_text">零售价{{item.price}}</view>
<view class="pop_info_text">批发价{{item.wholesale}}</view>
<view class="pop_bottom" @tap.stop.prevent v-if="showNumber">
数量
<view class="conright">
<uni-number-box :min="1" v-model="item.number" @change="(e)=>{changeNumber(e,index)}"></uni-number-box>
</view>
</view>
</view>
</view>
</view>
<u-empty v-if="list.length == 0" text="暂无更多"></u-empty>
</view>
</scroll-view>
<view class="popup_bottom">
<view class="pp_left_box">
<view class="pp_left">
<radio color="#008EFF" :checked="isAll" @click="selectAll"></radio>全选
</view>
<view class="selectnum">已选{{selectArr.length}}</view>
</view>
<view class="pp_right">
<view class="right_btn remove" @click="closePopup">取消</view>
<view class="right_btn sure" @click="sureSelectData">确定</view>
</view>
</view>
</uni-popup>
</view>
</template>
<script>
import { netContractProduct } from '@/api/kehu.js'
import { BASE_IMG_URL } from '@/util/api.js'
export default{
props:{
showProduct:{
type:Boolean,
default:false
},
showNumber:{
type:Boolean,
default:true
}
},
data(){
return{
BASE_IMG_URL:BASE_IMG_URL,
name:'',
list:[],
isAll:false,
selectArr:[]
}
},
methods:{
queryList(e) {
this.name = e.detail.value
this.init()
},
init() {
this.$refs.popup.open()
this.list = []
this.getProductList()
},
getProductList() {
let params = {
name:this.name
}
netContractProduct(params).then(res=>{
let arr = res.data
arr.forEach(ele=>{
ele.number = 1
ele.select = false
})
this.list = arr
})
},
changeNumber(e,index) {
let obj = this.list[index]
if(e > 1){
obj.select = true
}
obj.number = e
this.$set(this.list,index,obj)
this.handleSelect()
},
//
changeSelect(index) {
let obj = this.list[index]
obj.select = !obj.select
this.$set(this.list,index,obj)
this.handleSelect()
},
//
selectAll() {
this.isAll = !this.isAll
let arr = this.list
if(this.isAll){
arr.forEach(ele=>{
ele.select = true
})
}else{
arr.forEach(ele=>{
ele.select = false
})
}
this.list = arr
this.handleSelect()
},
closePopup() {
this.$refs.popup.close()
},
handleSelect() {
let arr = this.list
let newdata = []
arr.forEach(ele=>{
if(ele.select){
newdata.push(ele.id)
}
})
this.selectArr = newdata
},
//
sureSelectData() {
let arr = this.list
let newarr = []
arr.forEach(ele=>{
if(ele.select){
newarr.push(ele)
}
})
this.closePopup()
this.$emit('selectList',newarr)
}
}
}
</script>
<style lang="scss" scoped>
view{
box-sizing: border-box;
}
.popup_title{
text-align: center;
font-size:34rpx;
color:#333333;
padding:24rpx;
}
.searbox{
width:650rpx;
height:68rpx;
border-radius: 34rpx;
margin:0 auto;
border:1rpx solid $uni-text-color;
display: flex;
justify-content: flex-start;
align-items: center;
padding:0 15rpx;
.searchimg{
width:48rpx;
height:48rpx;
margin-right:15rpx;
}
.selfinput{
width:450rpx;
font-size:26rpx;
color:$uni-text-color;
}
}
.scrollbox{
width:100%;
height:700rpx;
.pop_list{
padding:24rpx;
.pop_li{
background:#fff;
box-shadow: 1rpx 1rpx 8rpx 2rpx rgba(0,0,0,0.1);
border-radius: 24rpx;
margin-bottom:24rpx;
.pop_li_top{
padding:28rpx;
display: flex;
justify-content: space-between;
align-items: center;
border-bottom:1rpx solid #f5f5f5;
.pop_title{
font-size:34rpx;
color:#333333;
}
.pop_num{
font-size:30rpx;
color:#666666;
}
}
.pop_info{
display: flex;
justify-content: flex-start;
align-items: center;
padding:24rpx 30rpx;
.pop_radio{
margin-right:32rpx;
radio{
transform: scale(0.7);
}
}
.infoimg{
width:140rpx;
height:140rpx;
border-radius: 20rpx;
margin-right:60rpx;
}
.pop_info_cen{
.pop_info_text{
font-size:28rpx;
color:#666666;
margin-bottom:15rpx;
}
.pop_bottom{
display: flex;
justify-content: flex-start;
align-items: center;
font-size:28rpx;
color:#666666;
.conright{
margin-left:10rpx;
.stepbtn{
width:38rpx;
height:38rpx;
border:1rpx solid $uni-text-color;
}
}
}
}
}
}
}
}
.popup_bottom{
width:100%;
padding:0 24rpx;
height:100rpx;
border-top:1rpx solid #f5f5f5;
display: flex;
justify-content: space-between;
align-items: center;
.pp_left_box{
display: flex;
justify-content: flex-start;
align-items: center;
.pp_left{
display: flex;
justify-content: flex-start;
align-items: center;
font-size:26rpx;
color:3333;
radio{
transform: scale(0.7);
}
}
.selectnum{
font-size:30rpx;
color:#FE9440;
margin-left:24rpx;
}
}
.pp_right{
display: flex;
justify-content: flex-end;
align-items: center;
.right_btn{
width:165rpx;
height:60rpx;
font-size:30rpx;
text-align: center;
border-radius: 30rpx;
}
.remove{
border:1rpx solid $uni-text-color;
color:$uni-text-color;
line-height: 58rpx;
margin-right:24rpx;
}
.sure{
background:$uni-text-color;
color:#fff;
line-height: 58rpx;
}
}
}
</style>

View File

@ -0,0 +1,310 @@
<template>
<view>
<uni-popup ref="popup" type="bottom" background-color="#fff">
<view class="popup_title">产品配件</view>
<view class="searbox">
<image :src="BASE_IMG_URL+'search.png'" class="searchimg" mode=""></image>
<input type="text" placeholder="按照备件编号/名称搜索" @input="queryList" class="selfinput">
</view>
<scroll-view scroll-y class="scrollbox" lower-threshold="30">
<view class="pop_list">
<view class="pop_li" v-for="(item,index) in list" :key="index">
<view class="pop_li_top">
<view class="pop_title">{{item.name}}</view>
<view class="pop_num">{{item.num}}</view>
</view>
<view class="pop_info" @tap.stop="changeSelect(index)">
<view class="pop_radio">
<radio color='#008EFF' :checked="item.select" ></radio>
</view>
<image :src="item.img ? item.img : BASE_IMG_URL+'img/index-4.png'" class="infoimg" mode=""></image>
<view class="pop_info_cen">
<view class="pop_bottom" @tap.stop.prevent>
数量
<view class="conright">
<uni-number-box :min="1" v-model="item.number" @change="(e)=>{changeNumber(e,index)}"></uni-number-box>
</view>
</view>
</view>
</view>
</view>
<u-empty v-if="list.length == 0" text="暂无更多"></u-empty>
</view>
</scroll-view>
<view class="popup_bottom">
<view class="pp_left_box">
<view class="pp_left">
<radio color="#008EFF" :checked="isAll" @click="selectAll"></radio>全选
</view>
<view class="selectnum">已选{{selectArr.length}}</view>
</view>
<view class="pp_right">
<view class="right_btn remove" @click="closePopup">取消</view>
<view class="right_btn sure" @click="sureSelectData">确定</view>
</view>
</view>
</uni-popup>
</view>
</template>
<script>
import { netProductConfig } from '@/api/index.js'
import { BASE_IMG_URL } from '@/util/api.js'
export default{
props:{
showConfig:{
type:Boolean,
default:false
}
},
data(){
return{
BASE_IMG_URL:BASE_IMG_URL,
name:'',
product_id:'',
list:[],
isAll:false,
selectArr:[]
}
},
methods:{
queryList(e) {
this.name = e.detail.value
this.init(this.product_id)
},
init(id) {
this.$refs.popup.open()
this.product_id = id
this.list = []
this.getConfigList()
},
getConfigList() {
let params = {
product_id:this.product_id,
name:this.name
}
netProductConfig(params).then(res=>{
let arr = res.data
arr.forEach(ele=>{
ele.part_id = ele.id
ele.number = 1
ele.select = false
})
this.list = arr
})
},
changeNumber(e,index) {
let obj = this.list[index]
if(e > 1){
obj.select = true
}
obj.number = e
this.$set(this.list,index,obj)
this.handleSelect()
},
//
changeSelect(index) {
let obj = this.list[index]
obj.select = !obj.select
this.$set(this.list,index,obj)
this.handleSelect()
},
//
selectAll() {
this.isAll = !this.isAll
let arr = this.list
if(this.isAll){
arr.forEach(ele=>{
ele.select = true
})
}else{
arr.forEach(ele=>{
ele.select = false
})
}
this.list = arr
this.handleSelect()
},
closePopup() {
this.$refs.popup.close()
},
handleSelect() {
let arr = this.list
let newdata = []
arr.forEach(ele=>{
if(ele.select){
newdata.push(ele.id)
}
})
this.selectArr = newdata
},
//
sureSelectData() {
let arr = this.list
let newarr = []
arr.forEach(ele=>{
if(ele.select){
newarr.push(ele)
}
})
this.closePopup()
this.$emit('selectList',newarr)
}
}
}
</script>
<style lang="scss" scoped>
view{
box-sizing: border-box;
}
.popup_title{
text-align: center;
font-size:34rpx;
color:#333333;
padding:24rpx;
}
.searbox{
width:650rpx;
height:68rpx;
border-radius: 34rpx;
margin:0 auto;
border:1rpx solid $uni-text-color;
display: flex;
justify-content: flex-start;
align-items: center;
padding:0 15rpx;
.searchimg{
width:48rpx;
height:48rpx;
margin-right:15rpx;
}
.selfinput{
width:450rpx;
font-size:26rpx;
color:$uni-text-color;
}
}
.scrollbox{
width:100%;
height:700rpx;
.pop_list{
padding:24rpx;
.pop_li{
background:#fff;
box-shadow: 1rpx 1rpx 8rpx 2rpx rgba(0,0,0,0.1);
border-radius: 24rpx;
margin-bottom:24rpx;
.pop_li_top{
padding:28rpx;
display: flex;
justify-content: space-between;
align-items: center;
border-bottom:1rpx solid #f5f5f5;
.pop_title{
font-size:34rpx;
color:#333333;
}
.pop_num{
font-size:30rpx;
color:#666666;
}
}
.pop_info{
display: flex;
justify-content: flex-start;
align-items: center;
padding:24rpx 30rpx;
.pop_radio{
margin-right:32rpx;
radio{
transform: scale(0.7);
}
}
.infoimg{
width:140rpx;
height:140rpx;
border-radius: 20rpx;
margin-right:90rpx;
}
.pop_info_cen{
.pop_info_text{
font-size:28rpx;
color:#666666;
margin-bottom:15rpx;
}
.pop_bottom{
display: flex;
justify-content: flex-start;
align-items: center;
font-size:28rpx;
color:#666666;
.conright{
margin-left:10rpx;
.stepbtn{
width:38rpx;
height:38rpx;
border:1rpx solid $uni-text-color;
}
}
}
}
}
}
}
}
.popup_bottom{
width:100%;
padding:0 24rpx;
height:100rpx;
border-top:1rpx solid #f5f5f5;
display: flex;
justify-content: space-between;
align-items: center;
.pp_left_box{
display: flex;
justify-content: flex-start;
align-items: center;
.pp_left{
display: flex;
justify-content: flex-start;
align-items: center;
font-size:26rpx;
color:3333;
radio{
transform: scale(0.7);
}
}
.selectnum{
font-size:30rpx;
color:#FE9440;
margin-left:24rpx;
}
}
.pp_right{
display: flex;
justify-content: flex-end;
align-items: center;
.right_btn{
width:165rpx;
height:60rpx;
font-size:30rpx;
text-align: center;
border-radius: 30rpx;
}
.remove{
border:1rpx solid $uni-text-color;
color:$uni-text-color;
line-height: 58rpx;
margin-right:24rpx;
}
.sure{
background:$uni-text-color;
color:#fff;
line-height: 58rpx;
}
}
}
</style>

195
components/selectStaff.vue Normal file
View File

@ -0,0 +1,195 @@
<template>
<view>
<uni-popup ref="popup" type="bottom" background-color="#fff" @touchmove.stop.prevent>
<view class="popup_title">选择员工</view>
<view class="searbox">
<image :src="BASE_IMG_URL+'ss.png'" class="searimg" mode="scaleToFill"></image>
<input @input="searchName" type="text" placeholder-style="color:#999;"
:class="keyword ? 'fontactive' : ''" v-model="keyword" placeholder="员工名称" class="li_box" />
</view>
<scroll-view scroll-y class="scrollbox" lower-threshold="30">
<view class="liwarp" v-for="(item,index) in staffList" :key="index" @click="selectItem(item,index)">
<view class="warpleft">
<view class="name">名称:{{item.name}}</view>
</view>
<label class="radio">
<radio value="r1" color="#008EFF" :checked="staffObj.id == item.id" />
</label>
</view>
<view class="noData" v-if="staffList.length == 0">暂无更多</view>
</scroll-view>
<view class="btnlist" @tap.stop.prevent>
<view class="btn secbtn" @click="hideSelect">取消</view>
<view class="btn firbtn" @click="sureSelect">确定</view>
</view>
</uni-popup>
</view>
</template>
<script>
import { netSearchStaffList, netStaffList } from '@/api/kehu.js'
import { BASE_IMG_URL } from '@/util/api.js'
export default{
props:{
type:{
type:Number,
default:1 //1 2
}
},
data(){
return{
keyword:'',
staffList:[],
staffObj:{},
BASE_IMG_URL:BASE_IMG_URL
}
},
methods:{
init() {
this.$refs.popup.open()
this.staffList = []
this.getList()
},
getList() {
let params = {name:this.keyword}
if(this.type == 1) {
netSearchStaffList(params).then(res=>{
this.staffList = res.data
})
}else{
netStaffList(params).then(res=>{
this.staffList = res.data
})
}
},
searchName(e) {
this.staffList = []
this.getList()
},
selectItem(item,index) {
if(this.staffObj && this.staffObj.id == item.id){
this.staffObj = null
}else{
this.staffObj = item
}
},
closePopup() {
this.$refs.popup.close()
},
sureSelect() {
if(!this.staffObj){
this.$refs.popup.close()
return
}
this.$refs.popup.close()
this.$emit('sureStaff',this.staffObj)
},
hideSelect() {
this.$refs.popup.close()
}
}
}
</script>
<style>
radio{
transform: scale(0.7);
}
</style>
<style lang="scss" scoped>
.popup_title{
text-align: center;
font-size:34rpx;
color:#333;
padding:24rpx;
}
.searbox{
width:690rpx;
height:60rpx;
margin:0 24rpx 15rpx;
border-radius: 30rpx;
padding:0 24rpx;
display: flex;
justify-content: flex-start;
align-items: center;
background:#f5f5f5;
.searimg{
width: 50rpx;
height: 50rpx;
margin-right:10rpx;
}
.li_box{
width:630rpx;
}
}
.scrollbox{
width:100%;
height:600rpx;
background:#f5f5f5;
.liwarp {
width: 702rpx;
padding: 20rpx 30rpx;
margin: 20rpx auto;
background: #fff;
border-radius: 10rpx;
display: flex;
justify-content: space-between;
align-items: center;
.warpleft {
flex: 1;
display: flex;
justify-content: flex-start;
align-items: center;
.headerimg {
width: 50rpx;
height: 50rpx;
border-radius: 50%;
margin-right: 15rpx;
}
.name {
font-size: 24rpx;
color: #333;
}
.number {
font-size: 24rpx;
color: #999;
margin: 15rpx 0;
}
.guishu {
font-size: 24rpx;
color: #666;
}
}
}
}
.btnlist {
width: 750rpx;
display: flex;
justify-content: space-around;
padding: 30rpx 0;
border-top:1rpx solid #f5f5f5;
.btn {
width: 200rpx;
height: 60rpx;
border-radius: 30rpx;
font-size: 24rpx;
color: #fff;
text-align: center;
line-height: 60rpx;
}
.firbtn {
background: $uni-text-color;
}
.secbtn {
background: #ff7800;
}
}
</style>

View File

@ -0,0 +1,191 @@
<template>
<view>
<uni-popup ref="popup" type="bottom" background-color="#fff" @touchmove.stop.prevent>
<view class="popup_title">选择团队成员</view>
<view class="searbox">
<image :src="BASE_IMG_URL+'ss.png'" class="searimg" mode="scaleToFill"></image>
<input @input="searchName" type="text" placeholder-style="color:#999;"
:class="keyword ? 'fontactive' : ''" v-model="keyword" placeholder="员工名称" class="li_box" />
</view>
<scroll-view scroll-y class="scrollbox" lower-threshold="30">
<view class="liwarp" v-for="(item,index) in staffList" :key="index" @click="selectItem(item,index)">
<view class="warpleft">
<view class="name">名称:{{item.name}}({{item.roles == 1?'负责人':'成员'}})</view>
</view>
<label class="radio">
<radio value="r1" color="#008EFF" :checked="staffObj.id == item.id" />
</label>
</view>
<view class="noData" v-if="staffList.length == 0">暂无更多</view>
</scroll-view>
<view class="btnlist" @tap.stop.prevent>
<view class="btn secbtn" @click="hideSelect">取消</view>
<view class="btn firbtn" @click="sureSelect">确定</view>
</view>
</uni-popup>
</view>
</template>
<script>
import { netTeamList } from '@/api/index.js'
import { BASE_IMG_URL } from '@/util/api.js'
export default{
props:{
},
data(){
return{
id:'', //id
keyword:'',
staffList:[],
staffObj:{},
BASE_IMG_URL:BASE_IMG_URL
}
},
methods:{
init(id) {
this.id = id
this.$refs.popup.open()
this.staffList = []
this.getList()
},
getList() {
let params = {
name:this.keyword,
id:this.id
}
netTeamList(params).then(res=>{
this.staffList = res.data
})
},
searchName(e) {
this.staffList = []
this.getList()
},
selectItem(item,index) {
if(this.staffObj && this.staffObj.id == item.id){
this.staffObj = null
}else{
this.staffObj = item
}
},
closePopup() {
this.$refs.popup.close()
},
sureSelect() {
if(!this.staffObj){
this.$refs.popup.close()
return
}
this.$refs.popup.close()
this.$emit('sureTeam',this.staffObj)
},
hideSelect() {
this.$refs.popup.close()
}
}
}
</script>
<style>
radio{
transform: scale(0.7);
}
</style>
<style lang="scss" scoped>
.popup_title{
text-align: center;
font-size:34rpx;
color:#333;
padding:24rpx;
}
.searbox{
width:690rpx;
height:60rpx;
margin:0 24rpx 15rpx;
border-radius: 30rpx;
padding:0 24rpx;
display: flex;
justify-content: flex-start;
align-items: center;
background:#f5f5f5;
.searimg{
width: 50rpx;
height: 50rpx;
margin-right:10rpx;
}
.li_box{
width:630rpx;
}
}
.scrollbox{
width:100%;
height:600rpx;
background:#f5f5f5;
.liwarp {
width: 702rpx;
padding: 20rpx 30rpx;
margin: 20rpx auto;
background: #fff;
border-radius: 10rpx;
display: flex;
justify-content: space-between;
align-items: center;
.warpleft {
flex: 1;
display: flex;
justify-content: flex-start;
align-items: center;
.headerimg {
width: 50rpx;
height: 50rpx;
border-radius: 50%;
margin-right: 15rpx;
}
.name {
font-size: 24rpx;
color: #333;
}
.number {
font-size: 24rpx;
color: #999;
margin: 15rpx 0;
}
.guishu {
font-size: 24rpx;
color: #666;
}
}
}
}
.btnlist {
width: 750rpx;
display: flex;
justify-content: space-around;
padding: 30rpx 0;
border-top:1rpx solid #f5f5f5;
.btn {
width: 200rpx;
height: 60rpx;
border-radius: 30rpx;
font-size: 24rpx;
color: #fff;
text-align: center;
line-height: 60rpx;
}
.firbtn {
background: #14C2C1;
}
.secbtn {
background: #ff7800;
}
}
</style>

View File

@ -0,0 +1,152 @@
<template>
<view>
<view class="block-height"></view>
<view class="tab-warp">
<view class="tab-box">
<view class="tab-li" v-for="(item,index) in tablist" :key="index" @click="switchTabbar(item.pagePath)">
<image :src="currentPath == item.pagePath ? item.selectedIconPath : item.iconPath " class="tabimg" mode="scaleToFill"></image>
<view class="tab-text">{{item.text}}</view>
<view class="tab-number" v-if="item.num > 0">{{item.num}}</view>
</view>
</view>
</view>
</view>
</template>
<script>
import { netAgentList } from '@/api/clues.js'
import { BASE_IMG_URL } from '@/util/api.js'
export default{
props:{
tipNumber:{
type:Number,
default:0
}
},
data(){
return{
BASE_IMG_URL:BASE_IMG_URL,
tablist:[
{
pagePath: "/pages/index/index",
iconPath: BASE_IMG_URL+"tab1.png",
selectedIconPath: BASE_IMG_URL+"tab1_a.png",
text: "首页",
isTip:true,
num:0
},
{
pagePath: "/pagesA/crm/customerManagement/customerManagement",
iconPath: BASE_IMG_URL+"tab2.png",
selectedIconPath: BASE_IMG_URL+"tab2_a.png",
text: "客户",
isTip:true,
num:0
},
{
pagePath: "/pages/news/news",
iconPath: BASE_IMG_URL+"tab3.png",
selectedIconPath: BASE_IMG_URL+"tab3_a.png",
text: "消息",
isTip:true,
num: this.tipNumber
},
{
pagePath: "/pages/profile/profile",
iconPath: BASE_IMG_URL+"tab4.png",
selectedIconPath: BASE_IMG_URL+"tab4_a.png",
text: "我的",
isTip:true,
num:0
}
]
}
},
computed:{
currentPath() {
let pages = getCurrentPages();
let query = this.queryObj ? this.queryObj : {};
let currPage = null;
if (pages.length) {
currPage = pages[pages.length - 1].route;
}
if (Object.keys(query).length) {
let params = '';
for (let key in query) {
params += '?' + key + '=' + query[key] + '&';
}
params = params.substring(0, params.length - 1);
return '/' + currPage + params;
}
return '/' + currPage;
}
},
created() {
},
methods:{
switchTabbar(path) {
uni.redirectTo({
url: path,
fail:(err)=>{
console.log(err)
}
})
},
}
}
</script>
<style lang="scss" scoped>
.block-height{
width:750rpx;
height:150rpx;
}
.tab-warp{
width:750rpx;
height: calc(100rpx + env(safe-area-inset-bottom) / 2);
padding-bottom: calc(env(safe-area-inset-bottom) / 2);
background:#fff;
border-top: 1rpx solid #eeeeee;
position: fixed;
left:0;
bottom:0;
.tab-box{
width: 100%;
height: calc(100rpx + env(safe-area-inset-bottom) / 2);
display: flex;
align-items: center;
justify-content: space-around;
.tab-li {
height: 100%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
flex: 1;
position: relative;
.tabimg {
width: 50rpx;
height: 50rpx;
}
.tab-text {
font-size: 20rpx;
}
.tab-number{
font-size:24rpx;
color:#fff;
background:#F43F3B;
width:40rpx;
height:40rpx;
border-radius: 50%;
text-align: center;
line-height: 40rpx;
position: absolute;
right:30rpx;
top:0;
}
}
}
}
</style>

View File

@ -0,0 +1,167 @@
.tki-tree{
position: fixed;
top: 0rpx;
right: 0rpx;
bottom: 0rpx;
left: 0rpx;
height:100vh;
width:100%;
z-index: 9998;
display: none;
}
.tki-tree.show{
display: block;
}
.tki-tree-mask {
position: fixed;
top: 0rpx;
right: 0rpx;
bottom: 0rpx;
left: 0rpx;
z-index: 9998;
height:100vh;
background-color: rgba(0, 0, 0, 0.6);
opacity: 0;
transition: all 0.3s ease;
visibility: hidden;
}
.tki-tree-mask.show {
visibility: visible;
opacity: 1;
}
.tki-tree-cnt {
position: absolute;
/* top: 0rpx; */
right: 0rpx;
bottom: 0rpx;
left: 0rpx;
height:700rpx;
z-index: 9999;
/* top: 160rpx; */
transition: all 0.3s ease;
transform: translateY(100vh);
}
.tki-tree-cnt.show {
transform: translateY(0);
}
.tki-tree-bar {
background-color: #fff;
height: 72rpx;
padding-left: 20rpx;
padding-right: 20rpx;
display: flex;
justify-content: space-between;
align-items: center;
box-sizing: border-box;
border-bottom-width: 1rpx !important;
border-bottom-style: solid;
border-bottom-color: #f5f5f5;
font-size: 32rpx;
color: #757575;
line-height: 1;
}
.tki-tree-bar-confirm {
color: #07bb07;
}
.tki-tree-view {
position: absolute;
top: 0rpx;
right: 0rpx;
bottom: 0rpx;
left: 0rpx;
top: 100rpx;
background-color: #fff;
padding-top: 20rpx;
padding-right: 20rpx;
padding-bottom: 20rpx;
padding-left: 20rpx;
}
.tki-tree-view-sc {
height: 100%;
overflow: hidden;
}
.tki-tree-item {
display: flex;
justify-content: space-between;
align-items: center;
font-size: 26rpx;
color: #757575;
line-height: 1;
height: 0;
opacity: 0;
transition: 0.2s;
position: relative;
overflow: hidden;
}
.tki-tree-item.show {
height: 80rpx;
opacity: 1;
}
.tki-tree-item.showchild:before {
transform: rotate(90deg);
}
.tki-tree-item.last:before {
opacity: 0;
}
.tki-tree-icon {
width: 26rpx;
height: 26rpx;
margin-right: 8rpx;
}
.tki-tree-label {
flex: 1;
display: flex;
align-items: center;
height: 100%;
line-height: 1.2;
}
.tki-tree-check {
width: 40px;
height: 40px;
display: flex;
justify-content: center;
align-items: center;
}
.tki-tree-check-yes,
.tki-tree-check-no {
width: 20px;
height: 20px;
border-top-left-radius: 20%;
border-top-right-radius: 20%;
border-bottom-right-radius: 20%;
border-bottom-left-radius: 20%;
border-top-width: 1rpx;
border-left-width: 1rpx;
border-bottom-width: 1rpx;
border-right-width: 1rpx;
border-style: solid;
border-color: #07bb07;
display: flex;
justify-content: center;
align-items: center;
box-sizing: border-box;
}
.tki-tree-check-yes-b {
width: 12px;
height: 12px;
border-top-left-radius: 20%;
border-top-right-radius: 20%;
border-bottom-right-radius: 20%;
border-bottom-left-radius: 20%;
background-color: #07bb07;
}
.tki-tree-check .radio {
border-top-left-radius: 50%;
border-top-right-radius: 50%;
border-bottom-right-radius: 50%;
border-bottom-left-radius: 50%;
}
.tki-tree-check .radio .tki-tree-check-yes-b {
border-top-left-radius: 50%;
border-top-right-radius: 50%;
border-bottom-right-radius: 50%;
border-bottom-left-radius: 50%;
}
.hover-c {
opacity: 0.6;
}

View File

@ -0,0 +1,297 @@
<template xlang="wxml">
<view class="tki-tree" :class="{'show':showTree}">
<view class="tki-tree-mask" :class="{'show':showTree}" @tap="_cancel"></view>
<view class="tki-tree-cnt" :class="{'show':showTree}">
<view class="tki-tree-bar" style="height: 100rpx;line-height: 100rpx;">
<view class="tki-tree-bar-cancel" :style="{'color':cancelColor}" hover-class="hover-c" @tap="_cancel">取消</view>
<view class="tki-tree-bar-title" :style="{'color':titleColor}">{{title}}</view>
<view class="tki-tree-bar-confirm" :style="{'color':confirmColor}" hover-class="hover-c" @tap="_confirm">确定</view>
</view>
<view class="tki-tree-view">
<scroll-view class="tki-tree-view-sc" :scroll-y="true">
<block v-for="(item, index) in treeList" :key="index">
<view class="tki-tree-item" :style="[{
paddingLeft: item.rank*15 + 'px',
zIndex: item.rank*-1 +50
}]"
:class="{
border: border === true,
show: item.show,
last: item.lastRank,
showchild: item.showChild,
open: item.open,
}">
<view class="tki-tree-label" @tap.stop="_treeItemTap(item, index)">
<image class="tki-tree-icon" :src="item.lastRank ? lastIcon : item.showChild ? currentIcon : defaultIcon" mode="scaleToFill"></image>
{{item.name}}
</view>
<view class="tki-tree-check" @tap.stop="_treeItemSelect(item, index)" v-if="selectParent?true:item.lastRank">
<view class="tki-tree-check-yes" v-if="item.checked" :class="{'radio':!multiple}" :style="{'border-color':confirmColor}">
<view class="tki-tree-check-yes-b" :style="{'background-color':confirmColor}"></view>
</view>
<view class="tki-tree-check-no" v-else :class="{'radio':!multiple}" :style="{'border-color':confirmColor}"></view>
</view>
</view>
</block>
</scroll-view>
</view>
</view>
</view>
</template>
<script>
import { BASE_IMG_URL } from '@/util/api.js'
export default {
name: "tki-tree",
props: {
range: {
type: Array,
default: function() {
return []
}
},
idKey: {
type: String,
default: 'id'
},
rangeKey: {
type: String,
default: 'label'
},
title: {
type: String,
default: ''
},
multiple: { //
type: Boolean,
default: false
},
selectParent: { //
type: Boolean,
default: false
},
foldAll: { //
type: Boolean,
default: false
},
confirmColor: { //
type: String,
default: '' // #07bb07
},
cancelColor: { //
type: String,
default: '' // #757575
},
titleColor: { //
type: String,
default: '' // #757575
},
currentIcon: { // ic
type: String,
default: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFEAAABRCAYAAACqj0o2AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6MEQ0QTM0MzQ1Q0RBMTFFOUE0MjY4NzI1Njc1RjI1ODIiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MEQ0QTM0MzU1Q0RBMTFFOUE0MjY4NzI1Njc1RjI1ODIiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDowRDRBMzQzMjVDREExMUU5QTQyNjg3MjU2NzVGMjU4MiIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDowRDRBMzQzMzVDREExMUU5QTQyNjg3MjU2NzVGMjU4MiIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PidwepsAAAK0SURBVHja7JxbTsJAFIYHww7ciStgCeoGvGxAiOsgURegoL5720AXYLiIr0aJviq3Zx3PhIEnKG3ndtr+f3KixrSUj/ZjzjClIqUUiFm2gAAQAREQEUAEREAERAQQAREQAREBREAEREBEEqa67h9RFDWllDv0awWYlqlQHmu1WjMRRMoV1QFttA12y3xRtdNczq8EsE4/f8FumX2q77ROvNXk8UGMEKdUz6tYJHljaZAbuyUH+UR1to5BEohTuqwPCeS4pAA/qY6o/kyHOAMCeRK3owJnj+rH1jjxhqpVsstaebCz6TmnHWyXyY+xHjSBWBY/bvSgadtXBj9u9KCN3rnIfkzkQVsTEEX0Y2IP2oKo/HhMICcFAThUcwVZNGU6FdbX/XURzkbVF4+ybGhjPrFdgP66QdXNurGtSdk6Xdb9nAJ8oDo3OQlsQZzkdPw41ONBo6vI5scDefRjZg+6gpg3Pxp50CXEvPjR2IOuIXL3oxUPuobI3Y9WPOgDIlc/WvOgL4iL/vqFCcD7LH0xB4hj7cfQ/fWH9qCT+FhG0tN+DBk1PzjOM0SVllixcsBT1AvYc/kAPhc0hRg/3uvxoCgKRN9+dOrBUBB9+9GpB0NC9OVH5x4MDdG1H714kANEV3705kEOEBf9dcPi/lQnsuvLg1wgSu3Ha0v7Uh4MMgUXeuG71H407a+VBy9CPQkOdw+MtB+nGbd/D+FBbhBNxo9SjwcngJjNj0E9yBFiFj8G9SBXiGn8GNyDnCEm8SMLD3KHGOdHNh7kDjHOj2w8mAeIi/5arX+c6b/fxHz9oADEdGdjR/fXCw/OOB5oVfCOgnepz8IB14PMw03jCmTE+QBx5z0gAmKSqK9OUF+hcAeIhu/QYr4Qie8rjW83hhMBERARQAREQAREBBABERCLnH8BBgA+TQI7U4t53AAAAABJRU5ErkJggg=='
},
defaultIcon: { // ic
type: String,
default: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFEAAABRCAYAAACqj0o2AAACE0lEQVR4Xu3c200DMRCF4XEltJAOkEugA+ggpUAHoQMqiFMCdEAJUMEiS4mEELlIO7bPOeN9i6K1rG/952myyea1WiCtXmEuYBPR4RBMxInoIOCwhOtJLKVszWyXc/5y2BvNEq6I+/3+kFK6M7OHnPM7jcLKjbZAvD/uaZtzflm5P4rbWyJWgDcze1LPuzVihfxUz7sH4ilJ2bx7Isrm3RtRMu8RiHJ5j0SUyXs0okTeCIj0eSMh0uaNhkiZNyIiXd7IiDR5oyNS5M2ACJ83EyJs3myIkHkzIsLlzYwIkzc7IkTeCojD81ZCHJa3GuKQvBURu+etjNgtb3XELnlHQGyedyTEZnlHQ2ySd0RE97wjI7rlHR3RJe+JeIrbLOecD6ePpZQ6W1kn2epo4MUrPOKyLN8ppYq1+y1VStncOjIdGnFZlo+U0uOtWOeOY2TE12Ouq//pEA7xXL7XfvcufR8K0Svfv6CREN3yDYfYIt9QiK3yjYTYLF95xB75SiP2ylcZsVu+cogj8pVCHJWvEuKwfOkREfKlRkTJlxkRJl86RMR8qRBR82VChM0XHpEhX2hElnyREWnyhUNkzBcKkTVfJETafIcjKuQ7FFEl35GIMvl2R1TMtyuiar49EWXzbY5oZpv/hibXTF2h3+s60FRKeT6+3TjMS3nrA3ZFRD8xrfY3ER1kJ+JEdBBwWGKeRAfEH1wS5WFZSDB/AAAAAElFTkSuQmCC'
},
lastIcon: { // ic
type: String,
default: ''
},
border: { // 线
type: Boolean,
default: false
},
},
data() {
return {
showTree: false,
treeList: [],
selectIndex: -1,
}
},
computed: {},
methods: {
_show() {
this.showTree = true
},
_hide() {
this.showTree = false
},
_cancel() {
this._hide()
this.$emit("cancel", '');
},
_confirm() {
//
let rt = [],
obj = {};
this.treeList.forEach((v, i) => {
if (this.treeList[i].checked) {
obj = {}
obj.parents = this.treeList[i].parents
obj = Object.assign(obj, this.treeList[i].source)
//
delete obj.children
rt.push(obj)
}
})
this._hide()
this.$emit("confirm", rt);
},
//
_renderTreeList(list = [], rank = 0, parentId = [], parents = []) {
list.forEach(item => {
this.treeList.push({
id: item[this.idKey],
name: item[this.rangeKey],
source: item,
parentId, // id
parents, // id
rank, //
showChild: true, //
open: true, //
show: true, //
hideArr: [],
orChecked: item.checked ? item.checked : false,
checked: item.checked ? item.checked : false,
})
if (Array.isArray(item.children) && item.children.length > 0) {
let parentid = [...parentId],
parentArr = [...parents],
childrenid = [...childrenid];
delete parentArr.children
parentid.push(item[this.idKey]);
parentArr.push({
[this.idKey]: item[this.idKey],
[this.rangeKey]: item[this.rangeKey]
})
this._renderTreeList(item.children, rank + 1, parentid, parentArr);
} else {
this.treeList[this.treeList.length - 1].lastRank = true;
}
})
},
//
_defaultSelect() {
this.treeList.forEach((v, i) => {
if (v.checked) {
this.treeList.forEach((v2, i2) => {
if (v.parentId.toString().indexOf(v2.parentId.toString()) >= 0) {
v2.show = true
if (v.parentId.includes(v2.id)) {
v2.showChild = true;
v2.open = true;
}
}
})
}
})
},
//
_treeItemTap(item, index) {
if (item.lastRank === true) {
//
this.treeList[index].checked = !this.treeList[index].checked
this._fixMultiple(index)
return;
}
let list = this.treeList;
let id = item.id;
item.showChild = !item.showChild;
item.open = item.showChild ? true : !item.open;
list.forEach((childItem, i) => {
if (item.showChild === false) {
//
if (!childItem.parentId.includes(id)) {
return;
}
if (!this.foldAll) {
if (childItem.lastRank !== true && !childItem.open) {
childItem.showChild = false;
}
//
if (childItem.show) {
childItem.hideArr[item.rank] = id
}
} else {
if (childItem.lastRank !== true) {
childItem.showChild = false;
}
}
childItem.show = false;
} else {
//
if (childItem.parentId[childItem.parentId.length - 1] === id) {
childItem.show = true;
}
//
if (childItem.parentId.includes(id) && !this.foldAll) {
if (childItem.hideArr[item.rank] === id) {
childItem.show = true;
if (childItem.open && childItem.showChild) {
childItem.showChild = true
} else {
childItem.showChild = false
}
childItem.hideArr[item.rank] = null
}
}
}
})
},
_treeItemSelect(item, index) {
this.treeList[index].checked = !this.treeList[index].checked
this._fixMultiple(index)
},
//
_fixMultiple(index) {
if (!this.multiple) {
//
this.treeList.forEach((v, i) => {
if (i != index) {
this.treeList[i].checked = false
} else {
this.treeList[i].checked = true
}
})
}
},
//
_reTreeList() {
this.treeList.forEach((v, i) => {
this.treeList[i].checked = v.orChecked
})
},
_initTree(range = this.range){
this.treeList = [];
this._renderTreeList(range);
this.$nextTick(() => {
this._defaultSelect(range)
})
}
},
watch: {
range(list) {
this._initTree(list);
},
multiple() {
if (this.range.length) {
this._reTreeList();
}
},
selectParent() {
if (this.range.length) {
this._reTreeList();
}
},
},
mounted() {
this._initTree();
}
}
</script>
<style scoped>
@import "./style.css";
</style>

View File

@ -0,0 +1,165 @@
<template>
<view class="">
<view class="inp_warp">
<view class="inp_title key"><text :class="flag ? 'b_color' : 'bo_color' ">*</text>{{title}}:</view>
<view class="form_right" @click="toUploadFile" v-if="isEdit">
<view>点击上传</view>
<view class="iconfont icon-you"></view>
</view>
</view>
<view class="doc_item" v-for="(item,index) in fileList" :key="index">
<image :src="BASE_IMG_URL+'/file-clip.png'" class="remarkimg" ></image>
<view class="doc_name" @click="toLookFile(item)">{{item.name}}</view>
<image :src="BASE_IMG_URL+'/file_del.png'" @click="delFile(index)" class="deleimg" v-if="isEdit"></image>
</view>
</view>
</template>
<script>
import { BASE_IMG_URL } from '@/util/api.js'
import { uploadUrl } from '@/api/index.js'
export default{
props:{
title:{
type:String,
default:'附件'
},
flag:{ //
type:Boolean,
default:false
},
fileList:{
type:Array,
default:[]
},
isEdit:{
type:Boolean,
default:true
}
},
data() {
return{
BASE_IMG_URL:BASE_IMG_URL
}
},
methods:{
//
toUploadFile() {
wx.chooseMessageFile({
count:1,
success:(res)=>{
let data = res.tempFiles[0]
this.Upload(data.path,data.name)
}
})
},
Upload(file,name) {
uni.uploadFile({
url: uploadUrl,
name: 'file',
header: {
'token': uni.getStorageSync('token'),
},
filePath: file,
formData:{name},
success: (res) => {
let data = JSON.parse(res.data)
if (data.code == 1) {
let res = data.data
res.name = name
res.file_path = res.url
console.log(res,'上传文件')
this.$emit('uploadFile',res)
} else {
uni.showToast({
title: '上传失败',
icon: 'none'
})
}
},
fail: (err) => {
console.log(err)
}
})
},
//
toLookFile(item) {
this.openCommonFile(item)
},
//
delFile(id,index) {
console.log('删除文件')
this.$emit('delFile',index)
},
}
}
</script>
<style lang="scss" scoped>
.doc_item{
display: flex;
justify-content: space-between;
align-items: center;
padding:24rpx 35rpx;
background:#fff;
border-bottom:1rpx solid #EDEDED;
.remarkimg{
width:31rpx;
height:33rpx;
margin-right:15rpx;
}
.deleimg{
width:44rpx;
height:44rpx;
}
.doc_name{
width:575rpx;
font-size:24rpx;
color:#333;
overflow: hidden;
}
}
.inp_warp {
padding:30rpx;
background: #fff;
display: flex;
justify-content: space-between;
align-items: center;
border-bottom: 1rpx solid #EDEDED;
.inp_title {
font-size: 32rpx;
color:#999;
}
.form_right {
display: flex;
justify-content: flex-end;
align-items: center;
color: #999;
min-width:450rpx;
text-align: right;
image {
width: 40rpx;
height: 40rpx;
margin-left:24rpx;
}
.rightinput{
width:100%;
text-align: right;
}
}
.add_in{
display: flex;
justify-content: flex-end;
align-items: center;
font-size:26rpx;
color:#FFA205;
.icon-jiahaocu{
font-size:28rpx;
color:#FFA205;
margin-right:5rpx;
}
}
}
</style>

View File

@ -0,0 +1,250 @@
<template>
<view>
<view class="inp_warp">
<view class="inp_title key"><text :class="flag ? 'b_color' : 'bo_color' ">*</text>{{title}}:</view>
<view class="form_right" v-if="isEdit">
<view>上传图片</view>
<view class="iconfont icon-arrows_right"></view>
</view>
</view>
<view class="imglist">
<view class="imgbox" v-for="(item,index) in imgList" :key="index">
<image :src="BASE_IMG_URL+'/close.png'" class="delimg" @click="delImg(index)" v-if="isEdit"></image>
<image :src="item.file_path" class="selfimg_img" @click="toPriveImg(index)"></image>
</view>
<view class="imgbox_tow" @click="uploadFiles" v-if="imgList.length < single && isEdit">
<image :src="BASE_IMG_URL+'/addfile.png'" class="selfimg"></image>
</view>
</view>
<!-- <view class="imglist" v-else>
<view class="imgbox" v-for="(item,index) in imgList" :key="index">
<image :src="BASE_IMG_URL+'/close.png'" class="delimg" @click="delImg(index)" v-if="isEdit"></image>
<image :src="item.file_path" class="selfimg_img" @click="toPriveImg(index)"></image>
</view>
<view class="imgbox_tow" @click="uploadFiles" v-if="imgList.length < single && isEdit">
<image :src="BASE_IMG_URL+'/addfile.png'" class="selfimg" ></image>
</view>
</view> -->
</view>
</template>
<script>
import {
BASE_URL,
BASE_IMG_URL
} from '@/util/api.js'
import {
uploadUrl
} from '@/api/index.js'
export default {
props: {
imgList: {
type: Array,
default: []
},
flag: { //
type: Boolean,
default: true
},
title: { //
type: String,
default: '附件'
},
single: { //
type: Number,
default: 9
},
istype: {
type: String,
default: 'all'
},
isEdit: {
type: Boolean,
default: true
}
},
data() {
return {
BASE_IMG_URL: BASE_IMG_URL
}
},
methods: {
//
toPriveImg(index) {
this.openCommonImg(this.imgList, index)
},
//
uploadFiles() {
let arr = []
if (this.istype == 'all') {
arr = ['album', 'camera']
} else if (this.istype == 'album') {
//
arr = ['album']
} else if (this.istype == 'camera') {
//
arr = ['camera']
}
uni.chooseImage({
count: this.single,
sourceType: arr,
sizeType: ['compressed'],
success: (res) => {
console.log(res,'====')
let file = res.tempFilePaths
file.forEach(ele => {
if (this.imgList.length < this.single) {
this.toUpload(ele)
}
})
}
})
},
toUpload(file) {
uni.uploadFile({
url: uploadUrl,
name: 'file',
header: {
'token': uni.getStorageSync('token'),
},
filePath: file,
success: (res) => {
let data = JSON.parse(res.data)
if (data.code == 1) {
let obj = {
id: data.data.id,
file_path: data.data.url
}
this.$emit('uploadImg', obj)
} else {
uni.showToast({
title: '上传失败',
icon: 'none'
})
}
},
fail: (err) => {
console.log(err)
}
})
},
delImg(index) {
this.$emit('delImg', index)
},
//
getImageInfo(src) {
return new Promise((resolve, reject) => {
uni.showLoading({
title: '压缩中...',
icon: 'none'
});
uni.getImageInfo({
src: src,
success:(res)=>{
console.log('压缩前', res);
let canvasWidth = res.width; //
let canvasHeight = res.height;
let img = new Image();
img.src = res.path;
let canvas = document.createElement('canvas');
let ctx = canvas.getContext('2d');
canvas.width = canvasWidth / 2;
canvas.height = canvasHeight / 2;
console.log(img);
ctx.drawImage(img, 0, 0, canvasWidth / 2, canvasHeight / 2);
canvas.toBlob(function(fileSrc) {
let imgSrc = window.URL.createObjectURL(fileSrc);
console.log('压缩后', imgSrc);
resolve(imgSrc);
uni.hideLoading();
});
}
});
});
}
}
}
</script>
<style lang="scss" scoped>
.b_color {
color: #f00;
}
.bo_color {
color: #ffffff;
}
.imglist {
padding: 24rpx 34rpx;
background: #fff;
border-bottom: 1rpx solid #EDEDED;
display: flex;
justify-content: flex-start;
align-items: center;
flex-wrap: wrap;
.imgbox {
width: 160rpx;
height: 160rpx;
margin-right: 14rpx;
position: relative;
margin-bottom: 24rpx;
&:nth-child(4n) {
margin-right: 0;
}
.delimg {
width: 32rpx;
height: 32rpx;
border-radius: 50%;
position: absolute;
right: -16rpx;
top: -16rpx;
background: rgba(0, 0, 0, 0.5);
z-index: 2;
}
.selfimg_img {
width: 160rpx;
height: 160rpx;
}
}
.imgbox_tow {
width: 75rpx;
height: 75rpx;
.selfimg {
width: 75rpx;
height: 75rpx;
}
}
}
.inp_warp {
padding: 30rpx;
background: #fff;
display: flex;
justify-content: space-between;
align-items: center;
border-bottom: 1rpx solid #EDEDED;
.inp_title {
font-size: 32rpx;
color: #999;
}
.form_right {
display: flex;
justify-content: flex-end;
align-items: center;
color: #999;
min-width: 450rpx;
text-align: right;
}
}
</style>

View File

@ -0,0 +1,130 @@
/*
*此函数的作用是根据传入的一个日期返回这一周的日期或者这一个月的日期
* 如果是月的话注意还包含上个月和下个月的日期月的话总共数据有 6 * 7 = 42
*
*/
/*
* 时间格式化函数
* 重要提示微信小程序new Date('2020-04-16')在ios中无法获取时间对象
* 解决方式: 建议将时间都格式化成'2020/04/16 00:00:00'的格式
* 函数示例: formatDate(new Date(), 'YYYY/MM/dd hh:mm:ss')
*/
export const formatDate = (date, fmt) => {
if (/(y+)/.test(fmt)) {
fmt = fmt.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length))
}
let o = {
'M+': date.getMonth() + 1,
'd+': date.getDate(),
'h+': date.getHours(),
'm+': date.getMinutes(),
's+': date.getSeconds()
}
for (let k in o) {
if (new RegExp(`(${k})`).test(fmt)) {
let str = o[k] + ''
fmt = fmt.replace(RegExp.$1, (RegExp.$1.length === 1) ? str : padLeftZero(str))
}
}
return fmt
}
const padLeftZero = (str) => {
return ('00' + str).substr(str.length)
}
export const judgeType = (s) => {
// 函数返回数据的具体类型
return Object.prototype.toString.call(s).slice(8,-1);
}
export const equalDate = (d1, d2) => {
let result = false;
if (d1.getFullYear() === d2.getFullYear() && d1.getMonth() === d2.getMonth() && d1.getDate() === d2.getDate()) {
result = true;
}
return result;
}
/* ,2020-04-04
*/
export const dateEqual = (before, after) => {
before = new Date(before.replace('-', '/').replace('-', '/'))
after = new Date(after.replace('-', '/').replace('-', '/'))
if (before.getTime() - after.getTime() === 0) {
return true
} else {
return false
}
}
export const gegerateDates = (date = new Date(), type='week') => {
const result = [];
if (judgeType(date) === 'Date') {
// 年,月,日
const y = date.getFullYear();
const m = date.getMonth();
const d = date.getDate();
const days = new Date(y, m+1, 0).getDate();
// 获取日期是星期几
let weekIndex = date.getDay() === 0 ? 7 : date.getDay();
if (type === 'month') {
const dobj = new Date(y,m,1);
weekIndex = dobj.getDay() === 0 ? 7 : dobj.getDay();
}
if (type === 'week') {
for(let i = weekIndex - 1; i >0; i--) {
const dtemp = new Date(y,m,d);
dtemp.setDate(dtemp.getDate() - i);
result.push({
time: dtemp,
show: true,
fullDate: formatDate(dtemp, 'yyyy-MM-dd'),
isToday: equalDate(new Date(), dtemp)
})
}
for(let i = 0; i <= 7 - weekIndex; i++) {
const dtemp = new Date(y,m,d);
dtemp.setDate(dtemp.getDate() + i);
result.push({
time: dtemp,
show: true,
fullDate: formatDate(dtemp, 'yyyy-MM-dd'),
isToday: equalDate(new Date(), dtemp)
})
}
} else if (type === 'month') {
// 上个月
for(let i = weekIndex - 1; i > 0; i--) {
const dtemp = new Date(y,m,1);
dtemp.setDate(dtemp.getDate() - i);
result.push({
time: dtemp,
show: false,
fullDate: formatDate(dtemp, 'yyyy-MM-dd'),
isToday: equalDate(new Date(), dtemp)
});
}
// 这个月的日期
for (let i = 0; i < days; i++) {
const dtemp = new Date(y,m,1);
dtemp.setDate(dtemp.getDate() + i);
result.push({
time: dtemp,
show: true,
fullDate: formatDate(dtemp, 'yyyy-MM-dd'),
isToday: equalDate(new Date(), dtemp)
});
}
const len = 42 - result.length;
// 下个月的日期
for (let i = 1; i <= len;i++) {
const dtemp = new Date(y,m+1,0);
dtemp.setDate(dtemp.getDate() + i);
result.push({
time: dtemp,
show: false,
fullDate: formatDate(dtemp, 'yyyy-MM-dd'),
isToday: equalDate(new Date(), dtemp)
})
}
}
}
return result;
}

View File

@ -0,0 +1,474 @@
<template>
<view class="zzx-calendar">
<view class="calendar-heander">
<view class="time">{{timeStr}}</view>
<view class="month" @click="lookMonth">
查看月报
<view class="iconfont icon-arrows_right"></view>
</view>
<!-- <view class="back-today" @click="goback" v-if="showBack">
返回今日
</view> -->
</view>
<view class="calendar-weeks">
<view class="calendar-week" v-for="(week, index) in weeks" :key="index">
{{week}}
</view>
</view>
<view class="calendar-content">
<swiper class="calendar-swiper" :style="{
width: '100%',
height: sheight
}" :indicator-dots="false" :autoplay="false" :duration="duration" :current="current" @change="changeSwp" :circular="true">
<swiper-item class="calendar-item" v-for="sitem in swiper" :key="sitem">
<view class="calendar-days">
<template v-if="sitem === current">
<view class="calendar-day" v-for="(item,index) in days" :key="index"
:class="{
'day-hidden': !item.show
}" @click="clickItem(item)">
<view
class="date"
:class="[
item.isToday ? todayClass : '',
item.fullDate === selectedDate ? checkedClass : ''
]"
>
{{item.time.getDate()}}
</view>
<view class="dot-show" v-if="item.info" :style="dotStyle">
</view>
</view>
</template>
<template v-else>
<template v-if="current - sitem === 1 || current-sitem ===-2">
<view class="calendar-day" v-for="(item,index) in predays" :key="index"
:class="{
'day-hidden': !item.show
}">
<view
class="date"
:class="[
item.isToday ? todayClass : ''
]"
>
{{item.time.getDate()}}
</view>
</view>
</template>
<template v-else>
<view class="calendar-day" v-for="(item,index) in nextdays" :key="index"
:class="{
'day-hidden': !item.show
}">
<view
class="date"
:class="[
item.isToday ? todayClass : ''
]"
>
{{item.time.getDate()}}
</view>
</view>
</template>
</template>
</view>
</swiper-item>
</swiper>
<view class="mode-change" @click="changeMode">
<view :class="weekMode ? 'mode-arrow-bottom' : 'mode-arrow-top'">
</view>
</view>
</view>
</view>
</template>
<script>
import {gegerateDates, dateEqual,formatDate} from './generateDates.js';
export default {
props: {
duration: {
type: Number,
default: 500
},
dotList: {
type: Array, ///
default() {
return [
]
}
},
showBack: {
type: Boolean, //
default: false
},
todayClass: {
type: String, // class
default: 'is-today'
},
checkedClass: {
type: String, // class
default: 'is-checked'
},
dotStyle: {
type: Object, //
default() {
return {
background: '#c6c6c6'
}
}
},
defaultDate: {
type:String,
default:''
}
},
watch:{
dotList: function(newvalue){
const days = this.days.slice(0);
newvalue.forEach(item => {
const index = days.findIndex(ditem => ditem.fullDate === item.date);
if (index > 0) {
days[index].info = item
}
});
this.days = days;
},
},
computed: {
sheight() {
//
//
let h = '70rpx';
if (!this.weekMode) {
const d = new Date(this.currentYear, this.currentMonth, 0);
const days = d.getDate(); //
let day = new Date(d.setDate(1)).getDay();
if (day === 0) {
day = 7;
}
const pre = 8 - day;
const rows = Math.ceil((days-pre) / 7) + 1;
h = 70 * rows + 'rpx'
}
return h
},
timeStr() {
let str = '';
const d = new Date(this.currentYear, this.currentMonth - 1, this.currentDate);
const y = d.getFullYear();
const m = (d.getMonth()+1) <=9 ? `0${d.getMonth()+1}` : d.getMonth()+1;
str = `${y}${m}`;
return str;
},
predays() {
let pres = [];
if (this.weekMode) {
const d = new Date(this.currentYear, this.currentMonth - 1,this.currentDate)
d.setDate(d.getDate() - 7);
pres = gegerateDates(d, 'week')
} else {
const d = new Date(this.currentYear, this.currentMonth - 2,1)
pres = gegerateDates(d, 'month')
}
return pres;
},
nextdays() {
let nexts = [];
if (this.weekMode) {
const d = new Date(this.currentYear, this.currentMonth - 1,this.currentDate)
d.setDate(d.getDate() + 7);
nexts = gegerateDates(d, 'week')
} else {
const d = new Date(this.currentYear, this.currentMonth,1)
nexts = gegerateDates(d, 'month')
}
return nexts;
}
},
data() {
return {
weeks: ['一', '二', '三', '四', '五', '六', '日'],
current: 1,
currentYear: '',
currentMonth: '',
currentDate: '',
days: [],
weekMode: true,
swiper: [0,1,2],
selectedDate:'',
// dotList: [], //
};
},
methods: {
changeSwp(e) {
// console.log(e);
const pre = this.current;
const current = e.target.current;
/* //
*current - pre === 1, -2时是下一个月/
*current -pre === -1, 2时是上一个月或者上一周
*/
this.current = current;
if (current - pre === 1 || current - pre === -2) {
this.daysNext();
} else {
this.daysPre();
}
},
//
initDate(cur) {
let date = ''
if (cur) {
date = new Date(cur)
} else {
date = new Date()
}
this.currentDate = date.getDate() //
this.currentYear = date.getFullYear() //
this.currentMonth = date.getMonth() + 1 //
this.currentWeek = date.getDay() === 0 ? 7 : date.getDay() // 1...6,0 // 星期几
const nowY = new Date().getFullYear() //
const nowM = new Date().getMonth() + 1
const nowD = new Date().getDate() //
const nowW = new Date().getDay();
// this.selectedDate = formatDate(new Date(), 'yyyy-MM-dd')
this.days = [];
let days = [];
if (this.weekMode) {
days = gegerateDates(date, 'week');
// this.selectedDate = days[0].fullDate;
} else {
days = gegerateDates(date, 'month');
// const sel = new Date(this.selectedDate.replace('-', '/').replace('-', '/'));
// const isMonth = sel.getFullYear() === this.currentYear && (sel.getMonth() + 1) === this.currentMonth;
// if(!isMonth) {
// this.selectedDate = formatDate(new Date(this.currentYear, this.currentMonth-1,1), 'yyyy-MM-dd')
// }
}
days.forEach(day => {
const dot = this.dotList.find(item => {
return dateEqual(item.date, day.fullDate);
})
if (dot) {
day.info = dot;
}
})
this.days = days;
// ,
let obj = {
start: '',
end: ''
};
if (this.weekMode) {
obj.start = this.days[0].time;
obj.end = this.days[6].time
} else {
const start = new Date(this.currentYear, this.currentMonth - 1, 1);
const end = new Date(this.currentYear, this.currentMonth , 0);
obj.start = start;
obj.end = end;
}
this.$emit('days-change', obj)
},
//
daysPre () {
if (this.weekMode) {
const d = new Date(this.currentYear, this.currentMonth - 1,this.currentDate);
d.setDate(d.getDate() - 7);
this.initDate(d);
} else {
const d = new Date(this.currentYear, this.currentMonth -2, 1);
this.initDate(d);
}
},
//
daysNext () {
if (this.weekMode) {
const d = new Date(this.currentYear, this.currentMonth - 1,this.currentDate);
d.setDate(d.getDate() + 7);
this.initDate(d);
} else {
const d = new Date(this.currentYear, this.currentMonth, 1);
this.initDate(d);
}
},
changeMode() {
const premode = this.weekMode;
let isweek = false;
if (premode) {
isweek = !!this.days.find(item => item.fullDate === this.selectedDate)
}
this.weekMode = !this.weekMode;
let d = new Date(this.currentYear, this.currentMonth - 1, this.currentDate)
const sel = new Date(this.selectedDate.replace('-', '/').replace('-', '/'));
const isMonth = sel.getFullYear() === this.currentYear && (sel.getMonth() + 1) === this.currentMonth;
if ((this.selectedDate && isMonth) || isweek) {
d = new Date(this.selectedDate.replace('-', '/').replace('-', '/'))
}
this.initDate(d)
},
//
clickItem(e) {
this.selectedDate = e.fullDate;
this.$emit('selected-change', e);
},
goback() {
const d = new Date();
this.initDate(d);
},
//
lookMonth() {
this.$emit('lookMonth')
},
init(date){
console.log(date,'======================')
if(date){
this.initDate();
this.selectedDate = date
}
}
},
created() {
},
mounted() {
}
}
</script>
<style lang="scss" scoped>
.zzx-calendar {
width: 100%;
height: auto;
// .calendar-heander {
// text-align: center;
// height: 60upx;
// line-height: 60upx;
// position: relative;
// font-size: 30upx;
// .back-today {
// position: absolute;
// right: 0;
// width: 100upx;
// height: 30upx;
// line-height: 30upx;
// font-size: 20upx;
// top: 15upx;
// border-radius: 15upx 0 0 15upx;
// color: #ffffff;
// background-color: #FF6633;
// }
// }
.calendar-heander{
font-size:30upx;
display: flex;
justify-content: space-between;
align-items: center;
padding:24rpx;
.time{
color:#333;
}
.month{
display: flex;
justify-content: flex-end;
align-items: center;
}
}
.calendar-weeks {
width: 100%;
display: flex;
flex-flow:row nowrap;
height: 60upx;
line-height: 60upx;
justify-content: center;
align-items: center;
font-size: 26upx;
.calendar-week {
width: calc(100% / 7);
height: 100%;
text-align: center;
}
}
swiper {
width: 100%;
height: 60upx;
}
.calendar-content {
min-height: 60upx;
}
.calendar-swiper {
min-height: 70upx;
transition: height ease-out 0.3s;
}
.calendar-item {
margin: 0;
padding: 0;
height: 100%;
}
.calendar-days {
display: flex;
flex-flow: row wrap;
width: 100%;
height: 100%;
overflow: hidden;
font-size: 28upx;
.calendar-day {
width: calc(100% / 7);
height: 70upx;
text-align: center;
display: flex;
flex-flow: column nowrap;
justify-content: flex-start;
align-items: center;
}
}
.day-hidden {
visibility: hidden;
}
.mode-change {
display: flex;
justify-content: center;
margin-top:10upx;
.mode-arrow-top {
width: 0;
height:0;
border-left: 12upx solid transparent;
border-right: 12upx solid transparent;
border-bottom: 10upx solid $uni-text-color;
}
.mode-arrow-bottom {
width: 0;
height:0;
border-left: 12upx solid transparent;
border-right: 12upx solid transparent;
border-top: 10upx solid $uni-text-color;
}
}
.is-today {
background: #ffffff;
// border: 1upx solid #FF6633;
border-radius: 50%;
color: $uni-text-color;
}
.is-checked {
background: $uni-text-color;
color: #ffffff;
}
.date {
width: 50upx;
height: 50upx;
line-height: 50upx;
margin: 0 auto;
border-radius: 50upx;
}
.dot-show {
margin-top:4upx;
width: 10upx;
height: 10upx;
background: #c6c6c6;
border-radius: 10upx;
}
}
</style>

40
main.js Normal file
View File

@ -0,0 +1,40 @@
import Vue from 'vue'
import App from './App'
import store from './store/index.js';
// main.js 文件
import uView from "uview-ui";
import {VueJsonp} from 'vue-jsonp'
Vue.use(uView);
Vue.use(VueJsonp)
import common from './util/common.js'
import share from './util/share.js'
import examineTemplate from './components/examineTemplate';
import { checkReport } from '@/util/util.js'
Vue.component("examine-template",examineTemplate)
Vue.prototype.$bus = new Vue();
Vue.prototype.$indexType = null;
Vue.prototype.$noMultipleClicks = common.noMultipleClicks;
Vue.prototype.$deWeight = common.deWeight;
Vue.prototype.openCommonFile = common.openCommonFile;
Vue.prototype.openCommonImg = common.openCommonImg;
Vue.prototype.checkCommonForm = common.checkCommonForm
Vue.prototype.checkStartAndEnd = common.checkStartAndEnd
Vue.prototype.handleTime = common.handleTime
//搜索 表单 数据 处理
Vue.prototype.handleSearchForm = common.handleSearchForm
Vue.prototype.handleSureSearch = common.handleSureSearch
Vue.prototype.handleResetSearch = common.handleResetSearch
Vue.prototype.checkReport = checkReport
Vue.config.productionTip = false
Vue.mixin(share)
App.mpType = 'app'
const app = new Vue({
store,
...App,
})
app.$mount()

151
manifest.json Normal file
View File

@ -0,0 +1,151 @@
{
"name" : "华莱士CRM",
"appid" : "__UNI__8FF4260",
"description" : "",
"versionName" : "1.0.0",
"versionCode" : "100",
"transformPx" : false,
/* 5+App */
"app-plus" : {
"usingComponents" : true,
"nvueCompiler" : "uni-app",
"compilerVersion" : 3,
"splashscreen" : {
"alwaysShowBeforeRender" : true,
"waiting" : true,
"autoclose" : true,
"delay" : 0
},
/* */
"modules" : {
"Geolocation" : {},
"Maps" : {}
},
/* */
"distribute" : {
/* android */
"android" : {
"permissions" : [
"<uses-feature android:name=\"android.hardware.camera\"/>",
"<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_COARSE_LOCATION\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_FINE_LOCATION\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
"<uses-permission android:name=\"android.permission.BLUETOOTH\"/>",
"<uses-permission android:name=\"android.permission.BLUETOOTH_ADMIN\"/>",
"<uses-permission android:name=\"android.permission.CALL_PHONE\"/>",
"<uses-permission android:name=\"android.permission.CALL_PRIVILEGED\"/>",
"<uses-permission android:name=\"android.permission.CAMERA\"/>",
"<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
"<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
"<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
"<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
"<uses-permission android:name=\"android.permission.INTERNET\"/>",
"<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
"<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
"<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
"<uses-permission android:name=\"android.permission.VIBRATE\"/>",
"<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
"<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
],
"abiFilters" : [ "armeabi-v7a", "arm64-v8a" ]
},
/* ios */
"ios" : {
"dSYMs" : false
},
/* SDK */
"sdkConfigs" : {
"geolocation" : {
"system" : {
"__platform__" : [ "android" ]
}
},
"maps" : {
"amap" : {
"appkey_ios" : "",
"appkey_android" : ""
}
},
"ad" : {}
},
"icons" : {
"android" : {
"hdpi" : "",
"xhdpi" : ""
}
}
}
},
/* */
"quickapp" : {},
/* */
"mp-weixin" : {
"appid" : "wxf2b7106cda55602b",
"setting" : {
"urlCheck" : false,
"es6" : true,
"postcss" : false,
"minified" : true,
"checkSiteMap" : false
},
"usingComponents" : true,
"permission" : {
"pages" : [ "pages/locationMap/locationMap" ],
"scope.userLocation" : {
"desc" : "你的位置信息将用于小程序位置接口的效果展示" //
}
},
"optimization" : {
"subPackages" : true
},
"requiredPrivateInfos" : [ "getLocation", "chooseLocation" ]
},
"mp-alipay" : {
"usingComponents" : true,
"component2" : true,
"appid" : "",
"setting" : {
"urlCheck" : false,
"es6" : true,
"postcss" : true,
"minified" : true,
"checkSiteMap" : false
},
"permission" : {
"pages" : [ "pages/locationMap/locationMap" ],
"scope.userLocation" : {
"desc" : "你的位置信息将用于小程序位置接口的效果展示" //
}
}
},
"mp-baidu" : {
"usingComponents" : true
},
"mp-toutiao" : {
"usingComponents" : true
},
"uniStatistics" : {
"enable" : false
},
"h5" : {
"router" : {
"mode" : "hash",
"base" : "/assets/addons/qingdong/"
},
"devServer" : {
"disableHostCheck" : true
},
"sdkConfigs" : {
"maps" : {
"qqmap" : {
"key" : ""
}
}
}
},
"fallbackLocale" : "zh-Hans"
}
/* ios *//* SDK */

114
package-lock.json generated Normal file
View File

@ -0,0 +1,114 @@
{
"name": "crm",
"version": "1.0.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"argparse": {
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
"integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
"requires": {
"sprintf-js": "~1.0.2"
}
},
"bmaplib.curveline": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/bmaplib.curveline/-/bmaplib.curveline-1.0.0.tgz",
"integrity": "sha512-9wcFMVhiYxNPqpvsLDAADn3qDhNzXp2mA6VyHSHg2XOAgSooC7ZiujdFhy0sp+0QYjTfJ/MjmLuNoUg2HHxH4Q=="
},
"bmaplib.heatmap": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/bmaplib.heatmap/-/bmaplib.heatmap-1.0.4.tgz",
"integrity": "sha512-rmhqUARBpUSJ9jXzUI2j7dIOqnc38bqubkx/8a349U2qtw/ulLUwyzRD535OrA8G7w5cz4aPKm6/rNvUAarg/Q=="
},
"bmaplib.lushu": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/bmaplib.lushu/-/bmaplib.lushu-1.0.7.tgz",
"integrity": "sha512-LVvgpESPii6xGxyjnQjq8u+ic4NjvhdCPV/RiSS/PGTUdZKeTDS7prSpleJLZH3ES0+oc0gYn8bw0LtPYUSz2w=="
},
"bmaplib.markerclusterer": {
"version": "1.0.13",
"resolved": "https://registry.npmjs.org/bmaplib.markerclusterer/-/bmaplib.markerclusterer-1.0.13.tgz",
"integrity": "sha512-VrLyWSiuDEVNi0yUfwOhFQ6z1oEEHS4w36GNu3iASu6p52QIx9uAXMUkuSCHReNR0bj2Cp9SA1dSx5RpojXajQ==",
"requires": {
"bmaplib.texticonoverlay": "^1.0.2"
}
},
"bmaplib.texticonoverlay": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/bmaplib.texticonoverlay/-/bmaplib.texticonoverlay-1.0.2.tgz",
"integrity": "sha512-4ZTWr4ZP3B6qEWput5Tut16CfZgII38YwM3bpyb4gFTQyORlKYryFp9WHWrwZZaHlOyYDAXG9SX0hka43jTADg=="
},
"dingtalk-jsapi": {
"version": "2.15.6",
"resolved": "https://registry.npmjs.org/dingtalk-jsapi/-/dingtalk-jsapi-2.15.6.tgz",
"integrity": "sha512-804mFz2AFV/H9ysmo7dLqMjSGOQgREsgQIuep+Xg+yNQeQtnUOYntElEzlB798Sj/691e4mMKz9mtQ7v9qdjuA==",
"requires": {
"promise-polyfill": "^7.1.0"
}
},
"entities": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz",
"integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w=="
},
"linkify-it": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-2.2.0.tgz",
"integrity": "sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw==",
"requires": {
"uc.micro": "^1.0.1"
}
},
"markdown-it": {
"version": "8.4.2",
"resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-8.4.2.tgz",
"integrity": "sha512-GcRz3AWTqSUphY3vsUqQSFMbgR38a4Lh3GWlHRh/7MRwz8mcu9n2IO7HOh+bXHrR9kOPDl5RNCaEsrneb+xhHQ==",
"requires": {
"argparse": "^1.0.7",
"entities": "~1.1.1",
"linkify-it": "^2.0.0",
"mdurl": "^1.0.1",
"uc.micro": "^1.0.5"
}
},
"mdurl": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz",
"integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g=="
},
"promise-polyfill": {
"version": "7.1.2",
"resolved": "https://registry.npmjs.org/promise-polyfill/-/promise-polyfill-7.1.2.tgz",
"integrity": "sha512-FuEc12/eKqqoRYIGBrUptCBRhobL19PS2U31vMNTfyck1FxPyMfgsXyW4Mav85y/ZN1hop3hOwRlUDok23oYfQ=="
},
"sprintf-js": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
"integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g=="
},
"uc.micro": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz",
"integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA=="
},
"vue-baidu-map": {
"version": "0.21.22",
"resolved": "https://registry.npmjs.org/vue-baidu-map/-/vue-baidu-map-0.21.22.tgz",
"integrity": "sha512-WQMPCih4UTh0AZCKKH/OVOYnyAWjfRNeK6BIeoLmscyY5aF8zzlJhz/NOHLb3mdztIpB0Z6aohn4Jd9mfCSjQw==",
"requires": {
"bmaplib.curveline": "^1.0.0",
"bmaplib.heatmap": "^1.0.4",
"bmaplib.lushu": "^1.0.7",
"bmaplib.markerclusterer": "^1.0.13",
"markdown-it": "^8.4.0"
}
},
"vue-jsonp": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/vue-jsonp/-/vue-jsonp-2.1.0.tgz",
"integrity": "sha512-kezmjaAcMWdieO3tWxniC+82DitYUYjR1e2GsWIKHCTf+zhWUt2nPhN3dnmnAVhDQ+po3BspM7sKjiQaIhijUg=="
}
}
}

34
package.json Normal file
View File

@ -0,0 +1,34 @@
{
"name": "crm",
"version": "1.0.0",
"description": "",
"main": "main.js",
"dependencies": {
"dingtalk-jsapi": "^2.13.53",
"vue-baidu-map": "^0.21.22",
"vue-jsonp": "^2.0.0"
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "https://git.weixin.qq.com/liuchangqing/lxs_web.git"
},
"keywords": [],
"author": "",
"license": "ISC",
"uni-app": {
"scripts": {
"mp-dingtalk": {
"title": "钉钉小程序",
"env": {
"UNI_PLATFORM": "mp-alipay"
},
"define": {
"MP-DINGTALK": true
}
}
}
}
}

971
pages.json Normal file
View File

@ -0,0 +1,971 @@
{
"easycom": {
"^u-(.*)": "@/uview-ui/components/u-$1/u-$1.vue"
},
"pages": [
{
"path": "pages/index/index",
"style": {
"navigationBarTitleText": "CRM",
"navigationBarBackgroundColor": "#DFF0FF",
// #ifndef H5
"navigationStyle": "custom",
// #endif
"mp-alipay": {
"allowsBounceVertical": "NO",
"transparentTitle": "always",
"titlePenetrate": "YES"
}
}
},
{
"path": "pages/public/login",
"style": {
"navigationBarTitleText": "CRM",
"enablePullDownRefresh": false,
"navigationStyle": "custom"
}
},
{
"path": "pages/index/examineing",
"style": {
"navigationBarTitleText": "审核中",
"navigationBarBackgroundColor": "#008EFF"
}
},
{
"path": "pages/signin/signin",
"style": {
"navigationBarTitleText": "签到列表"
}
},
{
"path": "pages/index/groupCompany/chargelist/chargelist",
"style": {
"navigationBarTitleText": "费用列表",
"navigationBarBackgroundColor": "#008EFF"
}
},
{
"path": "pages/index/dataList",
"style": {
"navigationBarTitleText": "待办列表"
}
},
{
"path": "pages/index/newSche/newSche",
"style": {
"navigationBarTitleText": "新建日程"
}
},
{
"path": "pages/news/news",
"style": {
"navigationBarTitleText": "消息"
}
},
{
"path": "pages/index/groupCompany/groupCompany",
"style": {
"navigationBarTitleText": "客户详情",
"navigationBarBackgroundColor": "#008EFF"
}
},
{
"path": "pages/index/groupCompany/operation/operation",
"style": {
"navigationBarTitleText": "客户操作记录",
"navigationBarBackgroundColor": "#008EFF"
}
},
{
"path": "pages/index/groupCompany/attachment/attachment",
"style": {
"navigationBarTitleText": "附件",
"navigationBarBackgroundColor": "#008EFF"
}
},
{
"path": "pages/index/groupCompany/payment/payment",
"style": {
"navigationBarTitleText": "回款记录",
"navigationBarBackgroundColor": "#008EFF"
}
},
{
"path": "pages/index/groupCompany/subsidiary/subsidiary",
"style": {
"navigationBarTitleText": "子公司",
"navigationBarBackgroundColor": "#008EFF"
}
},
{
"path": "pages/index/groupCompany/subsidiary/newSubsidiary/newSubsidiary",
"style": {
"navigationBarTitleText": "新建子公司",
"navigationBarBackgroundColor": "#008EFF"
}
},
{
"path": "pages/index/groupCompany/pact/pact",
"style": {
"navigationBarTitleText": "合同列表",
"navigationBarBackgroundColor": "#008EFF"
}
},
{
"path": "pages/index/groupCompany/cost/addCost",
"style": {
"navigationBarTitleText": "新建费用",
"navigationBarBackgroundColor": "#008EFF"
}
},
{
"path": "pages/index/groupCompany/cost/costDetail",
"style": {
"navigationBarTitleText": "费用详情"
}
},
{
"path": "pages/index/groupCompany/cost/editCost",
"style": {
"navigationBarTitleText": "编辑费用"
}
},
{
"path": "pages/index/contract/contract",
"style": {
"navigationBarTitleText": "采购列表",
"navigationBarBackgroundColor": "#008EFF"
}
},
{
"path": "pages/examine/examine",
"style": {
"navigationBarTitleText": "审核结果"
}
},
{
"path": "pages/tovoid/tovoid",
"style": {
"navigationBarTitleText": "作废合同"
}
},
{
"path": "pages/index/groupCompany/contact/contactDetail",
"style": {
"navigationBarTitleText": "联系人详情"
}
},
{
"path": "pages/index/groupCompany/contact/editInfo",
"style": {
"navigationBarTitleText": "编辑信息"
}
},
{
"path": "pages/index/groupCompany/tranferClue/tranferClue",
"style": {
"navigationBarTitleText": "转移客户",
"enablePullDownRefresh": false,
"navigationBarBackgroundColor": "#008EFF"
}
},
{
"path": "pages/index/newSche/selectTimeRange/selectTimeRange",
"style": {
"navigationBarTitleText": "选择时间范围"
}
},
{
"path": "pages/profile/profile",
"style": {
"navigationBarTitleText": "我的"
}
},
{
"path": "pages/index/schedule/schedule",
"style": {
"navigationBarTitleText": "日程安排"
}
},
{
"path": "pages/news/theReminder/theReminder",
"style": {
"navigationBarTitleText": "提醒通知",
"enablePullDownRefresh": false
}
},
{
"path": "pages/news/notice",
"style": {
"navigationBarTitleText": "公告消息",
"enablePullDownRefresh": false
}
},
{
"path": "pages/news/noticeDetail",
"style": {
"navigationBarTitleText": "公告详情",
"enablePullDownRefresh": false
}
},
{
"path": "pages/nearby/nearby",
"style": {
"navigationBarTitleText": "地图位置"
}
},
{
"path": "pages/workreport/list",
"style": {
"navigationBarTitleText": "工作报告",
"enablePullDownRefresh": false
}
},
{
"path": "pages/index/workNews",
"style": {
"navigationBarTitleText": "工作动态"
}
}
],
"subPackages": [
{
"root": "pagesA",
"pages": [
{
"path": "crm/linkman/newLinkman/newLinkman",
"style": {
"navigationBarTitleText": "新建联系人",
"enablePullDownRefresh": false,
"navigationBarBackgroundColor": "#008EFF"
}
},
{
"path": "crm/search/search",
"style": {
"navigationBarTitleText": "搜索"
}
},
{
"path": "crm/search/searchList",
"style": {
"navigationBarTitleText": "搜索列表"
}
},
{
"path": "crm/followRecord/followRecord",
"style": {
"navigationBarTitleText": "跟进记录"
}
},
{
"path": "crm/followRecord/handle",
"style": {
"navigationBarTitleText": "处理跟进"
}
},
{
"path": "crm/followRecord/addfollow",
"style": {
"navigationBarTitleText": "新增跟进"
}
},
{
"path": "crm/followRecord/needrecord",
"style": {
"navigationBarTitleText": "待跟进记录"
}
},
{
"path": "crm/receivableRecords/receivableRecords",
"style": {
"navigationBarTitleText": "回款统计",
"navigationBarBackgroundColor": "#008EFF"
}
},
{
"path": "crm/createCustomer/selectIndustry/selectIndustry",
"style": {
"navigationBarTitleText": "选择行业"
}
},
{
"path": "crm/salesTarget/setPerfGoal/setPerfGoal",
"style": {
"navigationBarTitleText": "设置业绩目标",
"enablePullDownRefresh": false
}
},
{
"path": "crm/statisticalFrom/achieveRank",
"style": {
"navigationBarTitleText": "排行榜"
}
},
{
"path": "crm/statisticalFrom/personRank/personRank",
"style": {
"navigationBarTitleText": "成交数据排名",
"enablePullDownRefresh": false
}
},
{
"path": "crm/statisticalFrom/paymentRank/paymentRank",
"style": {
"navigationBarTitleText": "回款数据排名",
"enablePullDownRefresh": false
}
},
{
"path": "crm/statisticalFrom/collect/collect",
"style": {
"navigationBarTitleText": "销售简报",
"enablePullDownRefresh": false
}
},
{
"path": "crm/statisticalFrom/achieveStatis",
"style": {
"navigationBarTitleText": "业绩统计"
}
},
{
"path": "crm/createCustomer/createCustomer",
"style": {
"navigationBarTitleText": "新建客户",
"enablePullDownRefresh": false,
"navigationBarBackgroundColor": "#008EFF"
}
},
{
"path": "crm/createCustomer/editCustomer",
"style": {
"navigationBarTitleText": "编辑客户",
"enablePullDownRefresh": false
}
},
{
"path": "crm/selectMember/selectMember",
"style": {
"navigationBarTitleText": "选择成员",
"enablePullDownRefresh": false
}
},
{
"path": "crm/cluesManagement/followUpDetail/followUpDetail",
"style": {
"navigationBarTitleText": "评论",
"enablePullDownRefresh": false
}
},
{
"path": "crm/linkman/linkman",
"style": {
"navigationBarTitleText": "联系人",
"enablePullDownRefresh": false,
"navigationBarBackgroundColor": "#008EFF"
}
},
{
"path": "crm/cluesManagement/newClues/newClues",
"style": {
"navigationBarTitleText": "新增线索",
"enablePullDownRefresh": false
}
},
{
"path": "crm/cluesManagement/cluesMore/editInfo",
"style": {
"navigationBarTitleText": "编辑线索",
"enablePullDownRefresh": false
}
},
{
"path": "crm/salesTarget/salesTarget",
"style": {
"navigationBarTitleText": "业绩目标",
"enablePullDownRefresh": false
}
},
{
"path": "crm/salesTarget/myTarget",
"style": {
"navigationBarTitleText": "业绩目标",
"enablePullDownRefresh": false
}
},
{
"path": "crm/salesTarget/history_edit",
"style": {
"navigationBarTitleText": "历史记录",
"enablePullDownRefresh": false
}
},
{
"path": "crm/salesTarget/history_detail",
"style": {
"navigationBarTitleText": "详情",
"enablePullDownRefresh": false
}
},
{
"path": "crm/statisticalFrom/achievementObject/achievementObject",
"style": {
"navigationBarTitleText": "业绩目标完成度"
}
},
{
"path": "crm/customerManagement/newFllow/newFllow",
"style": {
"navigationBarTitleText": "新建跟进",
"navigationBarBackgroundColor": "#008EFF"
}
},
{
"path": "crm/contract/contract",
"style": {
"navigationBarTitleText": "新增合同",
"navigationBarBackgroundColor": "#008EFF"
}
},
{
"path": "crm/cluesManagement/cluesManagement",
"style": {
"navigationBarTitleText": "线索管理"
}
},
{
"path": "crm/cluesManagement/cluesMore/cluesMore",
"style": {
"navigationBarTitleText": "线索详情"
}
},
{
"path": "crm/cluesManagement/cluesMore/transfer",
"style": {
"navigationBarTitleText": "更换负责人"
}
},
{
"path": "crm/customerManagement/customerManagement",
"style": {
"navigationBarTitleText": "我的客户",
"navigationBarBackgroundColor": "#008EFF",
"app-plus": {
"bounce": "none" //
},
"mp-alipay": {
"allowsBounceVertical": "NO"
}
}
},
{
"path": "crm/customerManagement/waterCustomerManagement",
"style": {
"navigationBarTitleText": "公海客户"
}
},
{
"path": "user/bindaccount",
"style": {
"navigationBarTitleText": "第三方账号绑定"
}
},
{
"path": "work/approve/index",
"style": {
"navigationBarTitleText":"办公审批"
}
},
{
"path": "work/approve/createTab",
"style": {
"navigationBarTitleText":"新建审批"
}
},
{
"path":"work/approve/createForm",
"style": {
"navigationBarTitleText":"请假审批"
}
},
{
"path": "work/approve/approveDetail",
"style": {
"navigationBarTitleText":"审批详情"
}
},
{
"path": "work/approvelManage/index",
"style": {
"navigationBarTitleText": "审批管理"
}
},
{
"path": "work/approvelManage/list",
"style": {
"navigationBarTitleText": "审批信息"
}
},
{
"path":"product/index",
"style": {
"navigationBarTitleText": "产品列表"
}
},
{
"path": "product/detail",
"style": {
"navigationBarTitleText": "产品详情"
}
},
{
"path": "payment/index",
"style": {
"navigationBarTitleText": "回款列表"
}
},
{
"path": "payplan/index",
"style": {
"navigationBarTitleText": "回款计划"
}
},
{
"path": "cost/index",
"style": {
"navigationBarTitleText": "费用管理"
}
},
{
"path": "circulate/index",
"style": {
"navigationBarTitleText": "相关团队"
}
},
{
"path": "circulate/add",
"style": {
"navigationBarTitleText": "添加团队"
}
},
{
"path": "circulate/edit",
"style": {
"navigationBarTitleText": "修改团队"
}
},
{
"path": "profile/staff/examinestaff/index",
"style": {
"navigationBarTitleText": "员工审核列表",
"navigationBarBackgroundColor": "#008EFF"
}
},
{
"path": "profile/staff/stafflist/index",
"style": {
"navigationBarTitleText": "员工列表",
"navigationBarBackgroundColor": "#008EFF"
}
},
{
"path": "profile/staff/stafflist/editStaff",
"style": {
"navigationBarTitleText": "编辑员工",
"navigationBarBackgroundColor": "#008EFF"
}
},
{
"path": "profile/staff/stafflist/staffDetail",
"style": {
"navigationBarTitleText": "员工详情",
"navigationBarBackgroundColor": "#008EFF"
}
},
{
"path": "profile/mySet/setPersonData/setPersonData",
"style": {
"navigationBarTitleText": "编辑个人资料",
"enablePullDownRefresh": false
}
},
{
"path": "profile/mySet/keyFocus/keyFocus",
"style": {
"navigationBarTitleText": "重点关注"
}
},
{
"path": "profile/about/userServiceAgreement/userServiceAgreement",
"style": {
"navigationBarTitleText": "用户服务协议"
}
},
{
"path": "profile/about/about",
"style": {
"navigationBarTitleText": "关于"
}
},
{
"path": "profile/feedback/feedback",
"style": {
"navigationBarTitleText": "意见反馈"
}
},
{
"path": "profile/enterpriseInfo/enterpriseInfo",
"style": {
"navigationBarTitleText": "企业信息"
}
},
{
"path": "profile/set",
"style": {
"navigationBarTitleText": "设置"
}
},
{
"path": "profile/editPassword",
"style": {
"navigationBarTitleText": "修改密码"
}
},
{
"path": "profile/needDeal",
"style": {
"navigationBarTitleText": "待办事项"
}
},
{
"path": "signin/signDetail",
"style": {
"navigationBarTitleText": "签到详情"
}
},
{
"path": "signin/busSign",
"style": {
"navigationBarTitleText": "出差签到",
"navigationBarBackgroundColor": "#008EFF"
}
},
{
"path": "signin/record/record",
"style": {
"navigationBarTitleText": "签到记录",
"navigationBarBackgroundColor": "#008EFF"
}
},
{
"path": "punchclock/index",
"style": {
"navigationBarTitleText": "打卡"
}
},
{
"path": "punchclock/normalClock",
"style": {
"navigationBarTitleText": "上下班打卡"
}
},
{
"path": "punchclock/punchOut",
"style": {
"navigationBarTitleText": "外出打卡"
}
},
{
"path": "punchclock/punchstatis/supplementaryCard",
"style": {
"navigationBarTitleText": "打卡补卡"
}
},
{
"path": "punchclock/punchstatis/index",
"style": {
"navigationBarTitleText": "统计"
}
},
{
"path": "punchclock/punchstatis/monthStatis",
"style": {
"navigationBarTitleText": "月统计"
}
},
{
"path": "punchclock/punchstatis/dayStatis",
"style": {
"navigationBarTitleText": "日统计"
}
},
{
"path":"punchclock/clockrules/index",
"style": {
"navigationBarTitleText": "打卡规则"
}
},
{
"path": "punchclock/clockrules/addRules",
"style": {
"navigationBarTitleText": "打卡规则"
}
},
{
"path": "punchclock/clockrules/clockTime",
"style": {
"navigationBarTitleText":"打卡时间"
}
},
{
"path": "punchclock/clockrules/addClocktime",
"style": {
"navigationBarTitleText": "添加打卡时间"
}
},
{
"path": "punchclock/clockrules/clockPeriod",
"style": {
"navigationBarTitleText": "打卡时段设置"
}
},
{
"path": "punchclock/clockrules/punchPosition",
"style": {
"navigationBarTitleText": "打卡位置"
}
},
{
"path": "punchclock/clockrules/addPosition",
"style": {
"navigationBarTitleText": "添加打卡位置"
}
},
{
"path": "business/index",
"style": {
"navigationBarTitleText": "商机"
}
},
{
"path": "business/customer_business",
"style": {
"navigationBarTitleText": "商机"
}
},
{
"path": "business/addBusiness",
"style": {
"navigationBarTitleText": "添加商机"
}
},
{
"path": "business/detail",
"style": {
"navigationBarTitleText": "商机详情"
}
},
{
"path": "business/editBusiness",
"style": {
"navigationBarTitleText": "修改商机"
}
},
{
"path": "business/trans",
"style": {
"navigationBarTitleText": "转移商机"
}
},
{
"path": "business/advance",
"style": {
"navigationBarTitleText": "推进商机"
}
},
{
"path": "punchclock/punchstatis/leave",
"style": {
"navigationBarTitleText": "请假"
}
},
{
"path": "punchclock/card/index",
"style": {
"navigationBarTitleText": "补卡记录"
}
},
{
"path": "punchclock/card/detail",
"style": {
"navigationBarTitleText": "补卡详情"
}
},
{
"path": "punchclock/leave/index",
"style": {
"navigationBarTitleText": "请假记录"
}
},
{
"path": "punchclock/leave/detail",
"style": {
"navigationBarTitleText": "请假详情"
}
},
{
"path": "punchclock/punchstatis/clockOutDetail",
"style": {
"navigationBarTitleText": "外勤详情"
}
}
]
},
{
"root": "pagesB",
"pages": [
{
"path": "workreport/workDetail",
"style": {
"navigationBarTitleText": "报告详情",
"enablePullDownRefresh": false
}
},
{
"path": "workreport/createWork",
"style": {
"navigationBarTitleText": "新建工作报告",
"enablePullDownRefresh": false
}
},
{
"path": "workreport/addReports",
"style": {
"navigationBarTitleText": "添加报告",
"enablePullDownRefresh": false
}
},
{
"path": "contract/addContractPayment",
"style": {
"navigationBarTitleText": "新建回款",
"navigationBarBackgroundColor": "#008EFF"
}
},
{
"path": "contract/addPaymentPlan",
"style": {
"navigationBarTitleText": "新建回款计划",
"navigationBarBackgroundColor": "#008EFF"
}
},
{
"path": "contract/addPayment",
"style": {
"navigationBarTitleText": "新建回款",
"navigationBarBackgroundColor": "#008EFF"
}
},
{
"path": "contract/editPayment",
"style": {
"navigationBarTitleText": "编辑回款"
}
},
{
"path": "contract/paymentDetail",
"style": {
"navigationBarTitleText": "回款详情",
"navigationBarBackgroundColor": "#008EFF"
}
},
{
"path": "contract/returned",
"style": {
"navigationBarTitleText": "回款记录",
"navigationBarBackgroundColor": "#008EFF"
}
},
{
"path": "contract/plan",
"style": {
"navigationBarTitleText": "回款计划",
"navigationBarBackgroundColor": "#008EFF"
}
},
{
"path": "contract/operation",
"style": {
"navigationBarTitleText": "操作记录",
"navigationBarBackgroundColor": "#008EFF"
}
},
{
"path": "contract/contractDetail",
"style": {
"navigationBarTitleText": "合同详情",
"navigationBarBackgroundColor": "#008EFF"
}
},
{
"path": "contract/editContract",
"style": {
"navigationBarTitleText": "编辑合同"
}
},
{
"path": "cluepool/index",
"style": {
"navigationBarTitleText": "线索池"
}
},
{
"path": "cluepool/addCluePool",
"style": {
"navigationBarTitleText": "添加线索"
}
},
{
"path": "cluepool/clueDetail",
"style": {
"navigationBarTitleText": "线索详情"
}
},
{
"path": "cluepool/editInfo",
"style": {
"navigationBarTitleText": "编辑线索"
}
},
{
"path": "cluepool/transfer",
"style": {
"navigationBarTitleText": "分配线索"
}
}
]
}
],
"preloadRule": {
"pages/index/index": {
"network": "all",
"packages": ["pagesA"]
}
},
"globalStyle": {
"navigationBarTitleText": "CRM",
"backgroundColor": "#DFF0FF",
"navigationBarBackgroundColor": "#008EFF",
"navigationBarTextStyle": "white",
"mp-alipay": {
"allowsBounceVertical": "NO"
}
},
"lazyCodeLoading": "requiredComponents"
}

87
pages/examine/examine.vue Normal file
View File

@ -0,0 +1,87 @@
<template>
<view>
<view class="textbox">
<textarea name="" maxlength="-1" v-model="content" placeholder="请输入审核意见" id="" class="textcontent"></textarea>
</view>
<view class="btn" @click="$noMultipleClicks(saveExamine)">确定</view>
</view>
</template>
<script>
import { netExamine } from '@/api/kehu.js'
export default{
data() {
return{
noClick:true, //
status:'', //1 2
id:'',
type:'', //receivables contract consume
content:''
}
},
onLoad(options) {
this.status = options.status
this.id = options.id
this.type = options.type
},
onShow() {
if(this.status == 1) {
uni.setNavigationBarTitle({
title:'通过审核'
})
}else{
uni.setNavigationBarTitle({
title:'拒绝审核'
})
}
},
methods:{
saveExamine() {
let params = {
relation_type: this.type,
relation_id:this.id,
content:this.content,
status: this.status
}
netExamine(params).then(res=>{
uni.showToast({
title:res.msg,
icon:'none'
})
setTimeout(()=>{
uni.navigateBack({
delta:1
})
},2000)
})
}
}
}
</script>
<style lang="scss" scoped>
.textbox{
background:#fff;
padding:20rpx 24rpx;
// margin: 20rpx;
.textcontent{
width:94%;
height:300rpx;
border-radius: 8rpx;
border:1rpx solid #CCCCCC;
padding:20rpx;
margin: 0 auto;
}
}
.btn{
width:680rpx;
height:80rpx;
border-radius: 40rpx;
background:$uni-text-color;
margin:100rpx auto;
font-size:24rpx;
color:#fff;
text-align: center;
line-height: 80rpx;
}
</style>

View File

@ -0,0 +1,150 @@
<template>
<view class="status_mask">
<view class="status_box">
<view class="title">修改状态</view>
<view class="conwarp">
<view class="sta_title">
日程标题{{schesTitle}}
</view>
<view class="sta_self">
日程状态
<radio-group @change="radioChange" class="radiobox">
<label class="radiolist" v-for="(item, index) in statusList" :key="item.id">
<view>
<radio :value="item.id" color="#008EFF" :checked="item.id == schestatus" />
</view>
<view>{{item.name}}</view>
</label>
</radio-group>
</view>
</view>
<view class="btnli">
<view class="btn remove" @click="removeStatus">取消</view>
<view class="btn sure" @click="sureChange">确定</view>
</view>
</view>
</view>
</template>
<script>
import { netEditScheculeStatus } from '@/api/index.js'
export default {
props:{
schestatus:{
type:Number/String,
default:'0'
},
schesTitle:{
type:String,
default:''
}
},
data() {
return {
statusList:[
{id:'0', name:'未开始'},
{id:'1', name:'执行中'},
{id:'2', name:'已结束'},
{id:'3', name:'已取消'}
],
}
},
methods:{
radioChange(e) {
this.$emit('changeStatus',e.detail.value)
},
sureChange() {
this.$emit('changeSuccess')
},
removeStatus() {
this.$emit('closeStatus')
}
}
}
</script>
<style lang="scss">
radio{
transform: scale(0.6);
}
</style>
<style lang="scss" scoped>
.status_mask{
position: fixed;
left:0;
right:0;
top:0;
bottom:0;
background:rgba(0,0,0,0.5);
display: flex;
justify-content: center;
align-items: center;
z-index: 9;
.status_box{
background:#fff;
border-radius: 10rpx;
padding:20rpx;
min-width:300rpx;
max-width: 680rpx;
.title{
font-size:26rpx;
color:#333;
text-align: center;
padding-bottom:20rpx;
border-bottom:1rpx solid #CCCCCC;
margin-bottom:20rpx;
}
.conwarp{
.sta_title{
font-size:24rpx;
color:#666;
margin-bottom:20rpx;
margin-top:40rpx;
}
.sta_self{
display: flex;
justify-content: flex-start;
align-items: center;
font-size:24rpx;
.radiobox{
display: flex;
justify-content: flex-start;
align-items: center;
}
.radiolist{
display: flex;
justify-content: flex-start;
align-items: center;
}
}
}
.btnli{
display: flex;
justify-content: space-around;
align-items: center;
margin-top:50rpx;
padding-bottom:20rpx;
.btn{
width:200rpx;
height:60rpx;
border-radius: 15rpx;
font-size:24rpx;
color:#fff;
text-align: center;
line-height: 60rpx;
}
.sure{
background:$uni-text-color;
border: 1px solid $uni-text-color;
}
.remove{
background:none;
border: 1px solid $uni-text-color;
color: $uni-text-color;
}
}
}
}
</style>

View File

@ -0,0 +1,164 @@
<template>
<view>
<cover-view class="pop_mask">
<cover-view class="pop_box">
<cover-view class="title">新增</cover-view>
<cover-view class="tablist">
<cover-view class="tabli" @click="addSchedule">
<cover-view class="tabbox">
<cover-image src="/static/img/richeng.png" mode="scaleToFill" class="tabimg"></cover-image>
</cover-view>
<cover-view class="tabtit">安排日程</cover-view>
</cover-view>
<cover-view class="tabli" @click="addClue">
<cover-view class="tabbox">
<cover-image :src="BASE_IMG_URL+'xiansuo.png'" class="tabimg" mode="scaleToFill"></cover-image>
</cover-view>
<cover-view class="tabtit">新建线索</cover-view>
</cover-view>
<cover-view class="tabli" @click="addCustomer">
<cover-view class="tabbox">
<cover-image :src="BASE_IMG_URL+'kehu.png'" class="tabimg" mode="scaleToFill"></cover-image>
</cover-view>
<cover-view class="tabtit">新建客户</cover-view>
</cover-view>
<cover-view class="tabli" @click="workreport">
<cover-view class="tabbox">
<cover-image :src="BASE_IMG_URL+'baogao.png'" class="tabimg" mode="scaleToFill"></cover-image>
</cover-view>
<cover-view class="tabtit">工作报告</cover-view>
</cover-view>
<cover-view class="tabli" @click="addChuchai">
<cover-view class="tabbox">
<cover-image :src="BASE_IMG_URL+'qiandao.png'" class="tabimg" mode="scaleToFill"></cover-image>
</cover-view>
<cover-view class="tabtit">出差签到</cover-view>
</cover-view>
</cover-view>
<cover-view class="remove" @click="close">取消</cover-view>
</cover-view>
</cover-view>
</view>
</template>
<script>
import { BASE_IMG_URL } from '@/util/api.js'
export default {
data() {
return{
BASE_IMG_URL:BASE_IMG_URL,
}
},
methods:{
close() {
this.$emit('closePop')
},
//
addSchedule() {
uni.navigateTo({
url: '/pages/index/newSche/newSche'
})
},
//线
addClue() {
uni.navigateTo({
url:'/pagesA/crm/cluesManagement/newClues/newClues'
})
},
//
addCustomer() {
uni.navigateTo({
url:'/pagesA/crm/createCustomer/createCustomer'
})
},
//
linkmanClick() {
uni.navigateTo({
url:'/pagesA/crm/linkman/newLinkman/newLinkman'
})
},
//
addChuchai() {
uni.navigateTo({
url:'/pagesA/signin/busSign'
})
},
//
workreport() {
uni.navigateTo({
url:'/pagesB/workreport/createWork'
})
}
}
}
</script>
<style lang="scss" scoped>
.pop_mask{
position: fixed;
left:0;
right:0;
top:0;
bottom:0;
background:rgba(0,0,0,0.5);
z-index: 99999;
display: flex;
justify-content: center;
align-items: center;
.pop_box{
width:680rpx;
background:#f5f5f5;
border-radius: 20rpx;
padding-bottom:30rpx;
// border-top-left-radius: 20rpx;
// border-top-right-radius: 20rpx;
.title{
text-align: center;
padding:24rpx;
font-size:30rpx;
color:#333333;
border-bottom:1rpx solid #CCCCCC;
}
.tablist{
padding:20rpx 24rpx;
display: flex;
justify-content: space-between;
flex-wrap: wrap;
.tabli{
width:122rpx;
text-align: center;
font-size:24rpx;
color:#999999;
.tabbox{
margin:0 auto;
width:100rpx;
height:100rpx;
border-radius: 20rpx;
background:#ffffff;
display: flex;
justify-content: center;
align-items: center;
margin-bottom:15rpx;
.tabimg{
width:60rpx;
height:60rpx;
}
}
}
}
.remove{
width:600rpx;
heihgt:80rpx;
border-radius: 40rpx;
margin:0 auto;
background:$uni-text-color;
text-align: center;
line-height: 80rpx;
font-size:30rpx;
color:#fff;
}
}
}
</style>

View File

@ -0,0 +1,637 @@
<template>
<view>
<view class="tab_list" style="margin-top:0;">
<view class="tabli" :class="typeIndex == 0 ? 'tabliactive' : ''" @click="changeFirTab(0)">全部</view>
<view class="tabli" :class="typeIndex == 1 ? 'tabliactive' : ''" @click="changeFirTab(1)">我创建的</view>
<view class="tabli" :class="typeIndex == 2 ? 'tabliactive' : ''" @click="changeFirTab(2)">下属创建的</view>
</view>
<view class="select_warp">
<view class="searchbox">
<view class="searchtext" @click="toQuery">
<image style="width: 30rpx;height: 30rpx;margin-right: 5rpx;"
:src="BASE_IMG_URL+'shaixuan2.png'" mode="scaleToFill"></image>筛选
</view>
</view>
<uni-popup ref="screenpopup" type="top" background-color="#fff">
<view class="warpbox">
<scroll-view scroll-y class="scrollbox" style="height:680rpx;background:#fff;">
<!--筛选模块 -->
<view class="screen_content" @tap.stop.prevent>
<view class="fir_li" v-if="typeIndex == 2">
<view class="li_label">归属人</view>
<picker @change="changeAscrip" :value="ascripIndex" :range="ascripList" :range-key="'name'">
<view class="li_box" >
<view class="form_right" style="text-align: center;">
<view :class="ascripList[ascripIndex] ? 'valueactive' : ''">
{{ascripList[ascripIndex] ? ascripList[ascripIndex].name : '点击选择'}}
</view>
</view>
</view>
</picker>
</view>
<view class="fir_li">
<view class="li_label">关联客户</view>
<view class="li_box" @click="toSelectCustomer">
<view class="form_right" style="text-align: center;">
<view :class="customerObj ? 'valueactive' : ''">
{{customerObj ? customerObj.name : '点击选择'}}
</view>
</view>
</view>
</view>
<view class="fir_li">
<view class="li_label">合同状态</view>
<picker @change="changeTab" :value="status" :range="statusList">
<view class="li_box" >
<view class="form_right" style="text-align: center;">
<view :class="statusList[status] ? 'valueactive' : ''">
{{statusList[status] ? statusList[status] : '点击选择'}}
</view>
</view>
</view>
</picker>
</view>
<view class="fir_li">
<view class="li_label">签约时间</view>
<view class="li_box" style="display: flex;">
<picker @change="changeStartTime" mode="date" :end="end_time"
style="width:50%;border-right:1rpx solid #CCCCCC">
<view class="form_right">
<view style="flex:1;text-align: center;"
:class="start_time ? 'valueactive' : '' ">
{{start_time ? start_time : '生效时间'}}</view>
</view>
</picker>
<picker @change="changeEndTime" mode="date" :start="start_time" style="width:50%">
<view class="form_right">
<view style="flex:1;text-align: center;"
:class="end_time ? 'valueactive' : '' ">{{end_time ? end_time : '到期时间'}}
</view>
</view>
</picker>
</view>
</view>
<search-item v-for="(item,index) in searchForm" :key="index" :objInfo="item" @changeSearchData="changeSearchData"></search-item>
</view>
</scroll-view>
<view class="button_bottom">
<view @tap.stop="reset">重置</view>
<view @tap.stop="sureQuery">确定</view>
</view>
</view>
</uni-popup>
</view>
<view class="lxr_con_list" v-for="(item,index) in contract_list" :key="index"
@click="toContractDetail(item.id)">
<view class="name">{{item.name?item.name:'--'}}</view>
<view class="info">关联客户{{item.customer?item.customer.name:'--'}}</view>
<view class="info">合同编号{{item.num}}</view>
<view class="info">已回款&yen;{{item.receivables.repayment_money}}</view>
<view class="info">待回款&yen;{{item.receivables.be_money}}</view>
<view class="proce_li">
<view class="pro_li_left">
<view class="protext">回款进度</view>
<view class="probox">
<view class="proin"
:style="{width:(item.receivables.ratio >= 100 ? 100 : item.receivables.ratio) +'%'}">
</view>
</view>
<view class="pronum">{{item.receivables.ratio >= 100 ? 100 : item.receivables.ratio }}%</view>
</view>
<view class="pro_li_right">&yen;{{item.money}}</view>
</view>
<view class="info">签约时间{{item.order_date}}</view>
<view class="con_status" v-if="item.check_status == 0">
<span>待审核</span>
</view>
<view class="con_status" v-if="item.check_status == 1">
<span>审核中</span>
</view>
<view class="con_status pass" v-if="item.check_status == 2">
<span>审核通过</span>
</view>
<view class="con_status nopass" v-if="item.check_status == 3">
<span>审核未通过</span>
</view>
<view class="con_status nopass" v-if="item.check_status == 4">
<span>已撤回</span>
</view>
</view>
<u-empty v-if="contract_list.length == 0" text="暂无更多"></u-empty>
<view style="height: 200rpx;"></view>
<view class="bot_total" @click="lookTotal">总金额合计> </view>
<uni-popup ref="popup" type="bottom" background-color="#fff" @touchmove.stop.prevent>
<view class="botwarp">
<view class="wa_li">
<view class="wa_label">合同总金额</view>
<view class="wa_money"> <text>{{moneyInfo.allmoney?moneyInfo.allmoney:'0'}}</text> </view>
</view>
<view class="wa_li">
<view class="wa_label">已回款金额</view>
<view class="wa_money"> <text>{{moneyInfo.repayment_money?moneyInfo.repayment_money:'0'}}</text> </view>
</view>
<view class="wa_li">
<view class="wa_label">未回款金额</view>
<view class="wa_money"> <text>{{moneyInfo.be_money?moneyInfo.be_money:'0'}}</text> </view>
</view>
<view class="wa_btn" @click="removeTotal">取消</view>
</view>
</uni-popup>
<!-- 创建用户图标 -->
<view class="icon_creat" @click="toCreateContract">
<image :src="BASE_IMG_URL+'1.png'" mode="scaleToFill"></image>
</view>
<select-customer ref="customerChild" @getCustomerinfo="getCustomerinfo"></select-customer>
</view>
</template>
<script>
import {
netCrmContractList,
netSearchStaffList
} from '@/api/kehu.js'
import { BASE_IMG_URL } from '@/util/api.js'
import selectCustomer from '@/components/selectCustomer.vue'
import searchItem from '@/components/search/searchitem.vue'
export default {
components:{
selectCustomer,
searchItem
},
data() {
return {
moneyInfo:{}, //
contract_list: [], //
page: 1,
limit: 10,
totalPage: 1,
BASE_IMG_URL:BASE_IMG_URL,
name: '',
type: '', // '0 ','1 ','2 '
typeList: ['全部客户', '我的客户', '下级的客户'],
typeIndex: 0,
statusList:['全部','待审核','待回款','已回款'],
status:null,
start_time: '',
end_time: '',
ascripList: [], //
ascripId: null,
ascripIndex: null,
customerObj:null, //
goodsList: ['全部客户', '我的客户', '下级的客户'],
info: 0,
rSelect: [],
searchForm:[],
}
},
onLoad(options) {
if (options.startTime) {
this.typeIndex = options.type == 0 ? 1 : options.type == 1 ? 0 : 2
this.type = this.typeList[this.typeIndex]
this.start_time = options.startTime
this.end_time = options.endTime
this.ascripId = options.staffid
}
if(options.stime){
this.typeIndex = options.status
this.start_time = options.stime
this.end_time = options.etime
}
this.handleSearchForm('contract',(data)=>{
this.searchForm = data
})
},
onShow() {
this.init()
//
this.getGuishu()
},
onReachBottom() {
if (this.page >= this.totalPage) {
return
}
this.page++
this.getList()
},
methods: {
//
toSelectCustomer() {
this.$refs.customerChild.init()
},
getCustomerinfo(obj) {
this.customerObj = obj
},
init() {
this.page = 1
this.contract_list = []
setTimeout(()=>{
this.getList()
},200)
},
//
toQuery() {
this.$refs.screenpopup.open()
},
//
lookTotal() {
this.$refs.popup.open()
},
removeTotal() {
this.$refs.popup.close()
},
changeTab(e) {
this.status = e.detail.value
},
changeFirTab(type) {
this.typeIndex = type
this.init()
},
moveStop(){},
toCreateContract() {
uni.navigateTo({
url:'/pagesA/crm/contract/contract'
})
},
tab(index) {
this.info = index
},
//
getGuishu() {
netSearchStaffList().then(res => {
this.ascripList = res.data
if (this.ascripId) {
this.ascripList.forEach((ele, index) => {
if (ele.id == this.ascripId) {
this.ascripIndex = index
}
})
}
})
},
changeAscrip(e) {
this.ascripIndex = e.detail.value
this.ascripId = this.ascripList[this.ascripIndex].id
},
getList() {
let params = {
page: this.page,
limit: this.limit,
createtime: (this.start_time && this.end_time) ? (this.start_time + ',' + this.end_time) : '',
type: this.typeIndex,
status: this.status,
staff_id: this.ascripId,
customer_id: this.customerObj?this.customerObj.id:'',
...this.handleSureSearch(this.searchForm)
}
netCrmContractList(params).then(res => {
this.contract_list = this.contract_list.concat(res.data.data)
this.totalPage = res.data.last_page
this.moneyInfo = res.data.moneyinfo
})
},
//
changeType(e) {
this.typeIndex = e
},
//线
changeStartTime(e) {
this.start_time = e.detail.value
if(!this.end_time){
this.end_time = e.detail.value
}
},
//线
changeEndTime(e) {
this.end_time = e.detail.value
if(!this.start_time){
this.start_time = e.detail.value
}
},
changeSearchData(type,key,value){
let arr = this.searchForm
arr.forEach((ele,index)=>{
if(ele.field == type){
ele[key] = value
this.$set(this.searchForm, index, ele)
}
})
},
//
reset() {
this.type = ''
this.start_time = ''
this.end_time = ''
this.ascripId = null
this.ascripIndex = null
this.status = null
this.customerObj = null
this.searchForm = this.handleResetSearch(this.searchForm)
},
//
sureQuery() {
this.$refs.screenpopup.close()
this.init()
},
//
toContractDetail(id) {
uni.navigateTo({
url: '/pagesB/contract/contractDetail?id=' + id
})
},
}
}
</script>
<style lang="scss" scoped>
.tab_list{
width:750rpx;
height:80rpx;
display: flex;
justify-content: space-around;
align-items: center;
background:#fff;
.tabli{
font-size:24rpx;
color:#333;
line-height: 75rpx;
text-align: center;
border-bottom:4rpx solid #fff;
}
.tabliactive{
border-bottom:4rpx solid $uni-text-color;
}
}
.active {
border: 1px solid red;
text-align: center;
border: none;
background: $uni-text-color;
padding: 5rpx 10rpx ;
border-radius: 10rpx;
color: #FFFFFF;
border: 1px solid $uni-text-color !important;;
}
.list-box {
overflow: hidden;
white-space: nowrap;
}
.list-box {
overflow: hidden;
white-space: nowrap;
}
.list-item {
border: 1px solid #999999;
padding: 5rpx 10rpx ;
border-radius: 10rpx;
}
.valueactive {
color: #666;
}
.select_warp {
z-index: 9;
position: relative;
}
.searchbox {
display: flex;
justify-content: flex-end;
margin: 20rpx 0;
.searchtext {
display: flex;
justify-content: center;
align-items: center;
font-size: 30rpx;
color: #999;
margin-right: 55rpx;
background:#ffffff;
padding:8rpx;
border-radius: 5rpx;
}
}
.warpbox {
width: 750rpx;
background: rgba(0, 0, 0, 0.7);
.screen_content {
z-index: 2;
border-top: 1rpx solid #CCCCCC;
background-color: #fff;
padding: 24rpx;
.fir_li {
margin-bottom: 20rpx;
.li_label {
font-size: 28rpx;
margin-top: 30rpx;
margin-bottom: 20rpx;
}
.classify {
display: flex;
justify-content: space-around;
.classify_flex {
padding: 5rpx 16rpx;
color: #999;
font-size: 30rpx;
border: 1px solid #999;
border-radius: 10rpx;
}
.c_f {
background: $uni-text-color !important;
color: #fff;
}
}
.li_box {
border-radius: 15rpx;border: 1rpx solid #CCCCCC;
width:690rpx;
height: 60rpx;
padding: 0 35rpx;
line-height: 60rpx;
display: flex;
justify-content: space-around;
color: #999;
box-sizing: border-box;
}
.form_right {
color: #999;
text-align: center;
image {
width: 40rpx;
height: 40rpx;
margin: 28rpx 5rpx 0 0;
}
}
}
}
.button_bottom {
display: flex;
width: 100%;
height: 90rpx;
background-color: #fff;
line-height: 90rpx;
text-align: center;
font-size: 32rpx;
justify-content: space-around;
padding-bottom: 100rpx;
:first-child {
color: #999;
border: 1rpx solid #999;
width: 260rpx;
height: 88rpx;
line-height: 88rpx;
border-radius: 30rpx;
}
:last-child {
background-color: $uni-text-color;
color: #fff;
width: 260rpx;
height: 88rpx;
line-height: 88rpx;
border-radius: 30rpx;
}
}
}
.lxr_con_list {
padding: 20rpx 0;
margin-bottom: 20rpx;
background: #fff;
&:last-child {
border-bottom: none;
}
.name {
font-size: 34rpx;
color: #333333;
font-weight: 500;
border-bottom: 1rpx solid #ededed;
padding: 0 0 30rpx 63rpx;
}
.info {
font-size: 32rpx;
color: #999999;
margin: 10rpx 0;
padding-left: 63rpx;
}
.proce_li {
display: flex;
justify-content: space-between;
align-items: center;
padding-left: 63rpx;
margin: 10rpx 0;
.pro_li_left {
display: flex;
justify-content: flex-start;
align-items: center;
.protext {
font-size: 32rpx;
color: #999999;
}
.probox {
width: 120rpx;
height: 30rpx;
border-radius: 15rpx;
background: #C0C0C0;
margin: 0 15rpx;
.proin {
width: 20%;
height: 30rpx;
border-radius: 15rpx;
background: $uni-text-color;
}
}
.pronum {
font-size: 24rpx;
color: #999999;
}
}
.pro_li_right {
color:$uni-text-color;
font-size: 33rpx;
font-weight: 500;
margin-right: 28rpx;
}
}
.con_status {
width: 130rpx;
height: 36rpx;
text-align: center;
line-height: 36rpx;
background: $uni-text-color-opcity;
margin-top: 30rpx;
margin-left: 63rpx;
span {
font-size: 26rpx;
color: $uni-text-color;
}
}
.nopass {
color: #ec7f51;
}
.pass {
color: #22A7F6;
}
}
.bot_total{
position: fixed;
left:0;
bottom:0;
width:750rpx;
height:calc(80rpx + env(safe-area-inset-bottom) / 2);
background:#fff;
font-size:24rpx;
color:#333;
text-align: center;
line-height: 80rpx;
color:$uni-text-color;
border-top:1rpx solid #f5f5f5;
padding-bottom:calc(env(safe-area-inset-bottom) / 2);
}
.botwarp{
background:#fff;
padding:0 24rpx;
.wa_li{
padding:24rpx 35rpx;
border-bottom:1rpx solid #f5f5f5;
display: flex;
justify-content: space-between;
align-items: center;
.wa_label{
font-size:24rpx;
color:#333;
}
.wa_money{
font-size:24rpx;
color:#666;
text{
color:$uni-text-color;
}
}
}
.wa_btn{
width:100%;
height:100rpx;
font-size:24rpx;
color:$uni-text-color;
text-align: center;
line-height: 100rpx;
}
}
</style>

595
pages/index/dataList.vue Normal file
View File

@ -0,0 +1,595 @@
<template>
<view class="warp">
<view class="sche_con_item" v-if="type == 1 || type == 2" v-for="(item,index) in list" :key="index">
<view class="item_left">
<view class="start-time">
<image :src="BASE_IMG_URL+'start_time.png'" class="timeimg" mode="scaleToFill"></image>
:{{item.start_time}}
</view>
<view class="content-time">
<view class="title">{{item.title}}</view>
<view>备注{{item.remark}}</view>
<view>关联业务</view>
<view class="yewu" v-if="item.relation_type == 3" @click="toContractDetail(item.relation_id)">
<image :src="BASE_IMG_URL+'file.png'" class="fileimg" mode="scaleToFill"></image>
合同
</view>
<view class="yewu" v-if="item.relation_type == 1" @click="toMore(item.relation_id)">
<image :src="BASE_IMG_URL+'file.png'" class="fileimg" mode="scaleToFill"></image>
客户
</view>
<view class="yewu" v-if="item.relation_type == 2" @click="jumpDetail(item.relation_id)">
<image :src="BASE_IMG_URL+'file.png'" class="fileimg" mode="scaleToFill"></image>
联系人
</view>
<view class="yewu" v-if="item.relation_type == 4" @click="moreClick(item.relation_id)">
<image :src="BASE_IMG_URL+'file.png'" class="fileimg" mode="scaleToFill"></image>
线索
</view>
</view>
<view class="end-time">
<image :src="BASE_IMG_URL+'end_time.png'" class="timeimg" mode="scaleToFill"></image>
:{{item.end_time}}
</view>
</view>
<view @click="toEditstatuss(item)">
<view class="item_right" v-if="item.status == 0">
<image :src="BASE_IMG_URL+'time.png'" mode="scaleToFill"></image>
<view>未开始</view>
</view>
<view class="item_right" v-if="item.status == 1">
<image :src="BASE_IMG_URL+'time_ing.png'" mode="scaleToFill"></image>
<view>进行中</view>
</view>
<view class="item_right" v-if="item.status == 2">
<image :src="BASE_IMG_URL+'time_end.png'" mode="scaleToFill"></image>
<view>已结束</view>
</view>
<view class="item_right" v-if="item.status == 3">
<image :src="BASE_IMG_URL+'time_over.png'" mode="scaleToFill"></image>
<view>已取消</view>
</view>
</view>
</view>
<view class="sche_con_item" v-if="type == 3" v-for="(item,index) in list" :key="index"
@click="toContractDetail(item.id)">
<view class="lxr_con_list">
<view class="name">{{item.name}}</view>
<view class="info">已回款 {{item.receivables.repayment_money}} 待回款 {{item.receivables.be_money}}</view>
<view class="proce_li">
<view class="pro_li_left">
<view class="protext">回款进度</view>
<view class="probox">
<view class="proin"
:style="{width:(item.receivables.ratio >= 100 ? 100 : item.receivables.ratio) +'%'}">
</view>
</view>
<view class="pronum">{{item.receivables.ratio}}%</view>
</view>
<view class="pro_li_right">{{item.receivables.be_money}}</view>
</view>
<view class="con_status" v-if="item.check_status == 0">
待审核
</view>
<view class="con_status" v-if="item.check_status == 1">
审核中
</view>
<view class="con_status" v-if="item.check_status == 2">
审核通过
</view>
<view class="con_status warnstatus" v-if="item.check_status == 3">
审核未通过
</view>
<view class="con_status warnstatus" v-if="item.check_status == 4">
已撤回
</view>
</view>
</view>
<view class="sche_con_item" v-if="type == 4" v-for="(item,index) in list" :key="index"
@click="toPaymentDetail(item)">
<view class="cust_item_con">
<view class="con_info">
<view>{{item.number}}</view>
<view>回款日期: {{item.return_time}}</view>
<view class="recostatus" v-if="item.check_status == 0">待审核</view>
<view class="recostatus" v-if="item.check_status == 1">审核中</view>
<view class="recostatus" v-if="item.check_status == 2">审核通过</view>
<view class="recostatus warnstatus" v-if="item.check_status == 3">审核未通过</view>
<view class="recostatus warnstatus" v-if="item.check_status == 4">已撤回</view>
</view>
<view class="con_money">
&yen; {{item.money}}
</view>
</view>
</view>
<view class="sche_con_item" v-if="type == 5" v-for="(item,index) in list" :key="index">
<view class="cust_item_con">
<view class="con_info">
<view>{{item.num}}</view>
<view>待回款日期: {{item.return_date}}</view>
<view>回款方式: {{item.return_type}}</view>
</view>
<view class="con_money">
&yen; {{item.money}}
</view>
</view>
</view>
<view class="clineInfo" v-if="type == 9" v-for="(item,index) in list" :key="index" @click.stop="toDetail(item)">
<view class="info_head">
<view>{{item.name}}</view>
</view>
<view class="info_main">
<view >
<view class="main_left">
<view class="left_top" v-if="item.customer" style="margin-top: 20rpx;color: #666;font-size: 30rpx;">
{{item.customer ? item.customer.name : '--'}}
</view>
<view class="left_followUp" style="margin-top: 20rpx;color: #666;font-size: 30rpx;">
<view>下次跟进时间</view>
<view>{{item.next_time ? item.next_time : '--'}}</view>
</view>
<view class="left_foot">
<view class="l_box">
<span v-if="item.type == 0">初期沟通</span>
<span v-if="item.type == 1">立项跟踪</span>
<span v-if="item.type == 2">方案/报价</span>
<span v-if="item.type == 3">谈判审核</span>
<span v-if="item.type == 4">赢单</span>
<span v-if="item.type == 5">输单</span>
<span v-if="item.type == 6">无效</span>
</view>
</view>
</view>
</view>
<view class="main_right" v-if="item.owner_staff">
<image :src="item.owner_staff ? item.owner_staff.img : BASE_IMG_URL+'headImg.png'" mode="scaleToFill">
</image>
<view>{{item.owner_staff?item.owner_staff.name:''}}</view>
</view>
</view>
<view class="info_footer" @click.stop.prevent>
<view class="footer_content" @click="toAddfollow(item)">
<image :src="BASE_IMG_URL+'tj.png'" mode="scaleToFill"></image>
<view>跟进</view>
</view>
<view class="footer_content" @click="toTrans(item)">
<image :src="BASE_IMG_URL+'rq.png'" mode="scaleToFill"></image>
<view>转移</view>
</view>
</view>
</view>
<view style="height: 200rpx;"></view>
<u-empty v-if="list.length == 0" text="暂无更多"></u-empty>
<!-- 日程修改状态 -->
<pop-status :schesTitle="schesTitle" :schestatus="schestatus" v-if="statusPop" @closeStatus="closeStatus"
@changeStatus="changeStatus" @changeSuccess="changeStatusSuccess"></pop-status>
</view>
</template>
<script>
import {
netGetFollowList,
netGetScheList,
netGetContractList,
netGetPaymentRemindList,
netGetPaymentList
} from '@/api/index.js'
import {
pageJumps
} from "./index_page_jumps.js";
import popStatus from './components/popStatus.vue'
import {
netEditScheculeStatus
} from '@/api/index.js'
import {
BASE_IMG_URL
} from '@/util/api.js'
export default {
mixins: [pageJumps],
data() {
return {
list: [],
type: '', //1 2 3 4 5 9
statusPop: false, //
scheid: '', //id
schestatus: '', //
schesTitle: '', //
BASE_IMG_URL: BASE_IMG_URL,
}
},
components: {
popStatus
},
onLoad(options) {
this.type = options.type
},
onShow() {
this.getList()
},
methods: {
getList() {
if (this.type == 1) {
uni.setNavigationBarTitle({
title: '待跟进任务'
})
netGetFollowList().then(res => {
this.list = res.data
})
} else if (this.type == 2) {
uni.setNavigationBarTitle({
title: '待处理日程'
})
netGetScheList().then(res => {
this.list = res.data
netGetFollowList().then(res => {
this.list = this.list.concat(res.data)
})
})
} else if (this.type == 3) {
uni.setNavigationBarTitle({
title: '待审核合同'
})
netGetContractList().then(res => {
this.list = res.data
})
} else if (this.type == 4) {
uni.setNavigationBarTitle({
title: '待审核回款'
})
netGetPaymentList().then(res => {
this.list = res.data
})
} else if (this.type == 5) {
uni.setNavigationBarTitle({
title: '待回款提醒'
})
netGetPaymentRemindList().then(res => {
this.list = res.data
})
}
},
//
toContractDetail(id) {
uni.navigateTo({
url: '/pagesB/contract/contractDetail?id=' + id
})
},
//
toPaymentDetail(item) {
uni.navigateTo({
url: '/pagesB/contract/paymentDetail?id=' + item.id
})
},
//
toEditstatuss(item) {
this.scheid = item.id
this.schestatus = item.status
this.schesTitle = item.title
this.statusPop = true
uni.hideTabBar({
animation: true
})
},
//
closeStatus() {
this.statusPop = false
this.schestatus = ''
this.scheid = ''
uni.showTabBar({
animation: true
})
},
changeStatus(status) {
this.schestatus = status
},
//
changeStatusSuccess() {
let params = {
id: this.scheid,
status: this.schestatus
}
netEditScheculeStatus(params).then(res => {
this.statusPop = false
this.schestatus = ''
this.scheid = ''
uni.showToast({
title: '日程状态修改成功',
icon: 'none'
})
setTimeout(() => {
this.getList()
}, 2000)
})
},
}
}
</script>
<style scoped lang="scss">
.start-time {
color: $uni-text-color;
display: flex;
justify-content: flex-start;
align-items: center;
font-size: 30rpx;
.timeimg {
width: 50rpx;
height: 41rpx;
}
}
.end-time {
color: $uni-text-color;
display: flex;
justify-content: flex-start;
align-items: center;
font-size: 30rpx;
.timeimg {
width: 50rpx;
height: 41rpx;
margin-right: 10rpx;
}
}
.warp {
padding: 20rpx;
}
.warnstatus {
color: #ec7f51;
}
.sche_con_item {
display: flex;
justify-content: space-between;
align-items: center;
background-color: #fcfcfc;
padding: 20rpx;
margin-bottom: 24rpx;
.item_left {
flex: 1;
color: #999;
view {
margin-bottom: 10rpx;
}
.title {
color: #333;
}
.yewu {
display: flex;
justify-content: flex-start;
align-items: center;
background: #f5f7fa;
padding: 10rpx;
.fileimg {
width: 20rpx;
height: 20rpx;
margin-right: 15rpx;
}
}
:last-child {
margin-bottom: 0;
}
}
.item_right {
display: flex;
align-items: center;
color: #999;
image {
width: 40rpx;
height: 40rpx;
margin-right: 10rpx;
}
}
}
.noList {
font-size: 24rpx;
text-align: center;
padding: 80rpx 0;
color: #666;
}
.lxr_con_list {
width: 750rpx;
padding-bottom: 20rpx;
border-bottom: 1rpx solid #C0C0C0;
&:last-child {
border-bottom: none;
}
.name {
font-size: 28rpx;
color: #333333;
margin-top: 15rpx;
}
.info {
font-size: 24rpx;
color: #999999;
margin: 10rpx 0;
}
.proce_li {
display: flex;
justify-content: space-between;
align-items: center;
.pro_li_left {
display: flex;
justify-content: flex-start;
align-items: center;
.protext {
font-size: 24rpx;
color: #999999;
}
.probox {
width: 120rpx;
height: 15rpx;
border-radius: 8rpx;
background: #C0C0C0;
margin: 0 15rpx;
.proin {
width: 20%;
height: 15rpx;
border-radius: 8rpx;
background: #ff7800;
}
}
.pronum {
font-size: 24rpx;
color: #999999;
}
}
.pro_li_right {
color: #ec7f51;
font-size: 28rpx;
font-weight: 500;
}
}
.con_status {
font-size: 24rpx;
color: $uni-text-color;
margin-top: 10rpx;
}
}
.cust_item_con {
padding: 15rpx 0;
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
.con_info {
padding: 10rpx 0;
:first-child {
color: #060606;
font-weight: 700;
line-height: 50rpx;
font-size: 28rpx;
}
:last-child {
line-height: 50rpx;
}
}
.con_money {
color: #ec7f51;
font-size: 28rpx;
line-height: 150rpx;
font-weight: 700;
}
}
.clineInfo {
background-color: #fff;
padding: 30rpx 45rpx;
margin-bottom: 20rpx;
border-radius: 10rpx;
box-shadow: 2rpx 2rpx 50rpx rgba(0, 0, 0, 0.1);
.info_head {
display: flex;
justify-content: space-between;
:first-child {
font-size: 34rpx;
font-weight: 700;
color: #333;
}
}
.info_main {
display: flex;
justify-content: space-between;
.main_left {
.left_followUp {
display: flex;
padding-bottom: 30rpx;
font-size: 30rpx;
color: #666;
}
.left_star {
font-size: 30rpx;
color: #666;
display: flex;
padding-bottom: 30rpx;
}
.left_foot {
padding-bottom: 20rpx;
.l_box {
margin-right: 35rpx;
float: left;
span {
background: $uni-text-color-opcity;
padding: 5rpx 12rpx;
font-size: 26rpx;
color: $uni-text-color;
border-radius: 5rpx;
}
}
}
}
.main_right {
text-align: center;
padding: 20rpx 15rpx 0 0;
image {
border-radius: 50%;
width: 129rpx;
height: 129rpx;
margin-bottom: 5rpx;
}
}
}
.info_footer {
display: flex;
justify-content: space-around;
padding-top: 30rpx;
height: 80rpx;
border-top: 1px solid #ededed;
margin-top: 20rpx;
.footer_content {
// width: 25%;
line-height: 28rpx;
display: flex;
justify-content: center;
align-items: center;
image{
width: 48rpx;
height: 48rpx;
margin-right: 15rpx;
}
}
}
}
</style>

View File

@ -0,0 +1,41 @@
<template>
<view class="examine-warp">
<view class="exam-box">
<image :src="BASE_IMG_URL+'2.png'"class="examimg" mode="scaleToFill"></image>
<view class="exam-text">请耐心等待管理员通过审核</view>
</view>
</view>
</template>
<script>
import { BASE_IMG_URL } from '@/util/api.js'
export default{
data() {
return {
BASE_IMG_URL:BASE_IMG_URL,
}
},
}
</script>
<style lang="scss" scoped>
.examine-warp{
width:100%;
height:100vh;
display: flex;
justify-content: center;
align-items: center;
.exam-box{
text-align: center;
.examimg{
width:245rpx;
height:200rpx;
margin-bottom:20rpx;
}
.exam-text{
font-size:26rpx;
color:$uni-text-color;
}
}
}
</style>

View File

@ -0,0 +1,436 @@
<template>
<view class="cust_detail">
<view class="cust_item">
<view class="cust_item_head">
<view class="head_info">
<image :src="BASE_IMG_URL+'fujian.png'" class="peopleimg" mode="scaleToFill"></image>
<view>附件</view>
</view>
</view>
<view class="item_doc">
<view class="doc_item" v-for="(item,index) in file_list" :key="index" @click.stop="lookDetail(item)">
<view class="iconfont icon--task"></view>
<input type="text" :disabled="item.disabled" :focus="item.focus" :data-index="index"
v-model="item.name" @confirm="changeName" @blur="changeName" class="doc_name"/>
<view class="doc_size">{{item.size}}</view>
<!-- <image :src="BASE_IMG_URL+'edit.png'" class="editimg" @click.stop="edit(index)" v-if="type == 1" mode="scaleToFill"></image> -->
</view>
</view>
</view>
</view>
</template>
<script>
import {
netCluesFiles,
} from '@/api/clues.js'
import {netKehuFileList,netEditFileName, netContractFileList} from '@/api/kehu.js'
import { BASE_IMG_URL } from '@/util/api.js'
export default {
data() {
return {
file_list: [], //
BASE_IMG_URL:BASE_IMG_URL,
id:'',
contract_id:'',
types:Number, //3 2
type:1
}
},
onLoad(options) {
this.id = options.id
this.types = options.types
this.type = options.type
},
onShow() {
//
this.getFile()
},
created() {
},
methods: {
//
getFile() {
if(this.types == 2){
let params = {
customer_id: this.id
}
netKehuFileList(params).then(res=>{
res.data.forEach(item=>{
item.disabled = true
item.focus = false
})
this.file_list = res.data
})
}else{
let params = { contract_id:this.id }
netContractFileList(params).then(res=>{
res.data.forEach(item=>{
item.disabled = true
item.focus = false
})
this.file_list = res.data
})
}
},
//
lookDetail(item) {
if(item.types.indexOf('image') != -1){
uni.previewImage({
urls: [ item.file_path ]
})
}else{
uni.downloadFile({
url: item.file_path,
success:(res)=>{
uni.openDocument({
filePath:res.tempFilePath,
success:(res)=>console.log('成功打开文档')
})
},
fail:(err)=>{
console.log(err,'shibai')
}
})
}
},
//
edit(index) {
let obj = this.file_list[index]
obj.disabled = false
obj.focus = true
this.file_list[index] = obj
},
changeName(e) {
let name = e.detail.value
let index = e.currentTarget.dataset.index
let params = {
id: this.file_list[index].id,
name: this.file_list[index].name,
}
netEditFileName(params).then(res => {
uni.showToast({
title: res.msg,
icon: 'none'
})
setTimeout(() => {
this.getFile()
}, 2000)
})
},
}
}
</script>
<style lang="scss" scoped>
.cust_detail {
.cust_item {
padding: 0 24rpx;
background-color: #fff;
margin-bottom: 20rpx;
.cust_item_head {
display: flex;
justify-content: space-between;
line-height: 100rpx;
border-bottom: 1rpx solid #EAEAEA;
.head_info {
display: flex;
align-items: center;
.icon--task {
margin-right: 10rpx;
}
}
.head_new {
display: flex;
align-items: center;
color: #1c9bfc;
.icon-clock {
margin-right: 10rpx;
}
}
}
.lxr_con_list {
padding-bottom: 20rpx;
border-bottom: 1rpx solid #C0C0C0;
&:last-child {
border-bottom: none;
}
.name {
font-size: 28rpx;
color: #333333;
margin-top: 15rpx;
}
.info {
font-size: 24rpx;
color: #999999;
margin: 10rpx 0;
}
.proce_li {
display: flex;
justify-content: space-between;
align-items: center;
.pro_li_left {
display: flex;
justify-content: flex-start;
align-items: center;
.protext {
font-size: 24rpx;
color: #999999;
}
.probox {
width: 120rpx;
height: 15rpx;
border-radius: 8rpx;
background: #C0C0C0;
margin: 0 15rpx;
.proin {
width: 20%;
height: 15rpx;
border-radius: 8rpx;
background: #ff7800;
}
}
.pronum {
font-size: 24rpx;
color: #999999;
}
}
.pro_li_right {
color: #ec7f51;
font-size: 28rpx;
font-weight: 500;
}
}
.con_status {
font-size: 24rpx;
color:$uni-text-color;
margin-top: 10rpx;
}
}
.cust_item_con {
border-bottom: 1rpx solid #EAEAEA;
padding: 15rpx 0;
display: flex;
justify-content: space-between;
align-items: center;
.con_info {
padding: 10rpx 0;
:first-child {
color: #060606;
font-weight: 700;
line-height: 50rpx;
font-size: 28rpx;
}
:last-child {
color: #469369;
line-height: 50rpx;
}
}
.con_money {
color: #ec7f51;
font-size: 28rpx;
line-height: 150rpx;
font-weight: 700;
}
}
.item_doc {
.doc_item {
padding: 30rpx 0;
display: flex;
justify-content: space-between;
align-items: center;
background-color: #f7faff;
line-height: 60rpx;
margin-bottom: 20rpx;
.icon--task {
width: 50rpx;
padding-left: 10rpx;
}
.doc_name {
flex: 1;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.doc_size {
width: 130rpx;
}
.editimg {
width: 40rpx;
height: 40rpx;
}
.icon-clear {
width: 50rpx;
}
}
}
.operation_record {
padding: 40rpx 20rpx 40rpx 60rpx;
.record_item {
display: flex;
justify-content: space-between;
line-height: 86rpx;
margin-top: 20rpx;
.record_img {
position: relative;
display: flex;
line-height: 200rpx;
image {
width: 80rpx;
height: 80rpx;
}
.record_info {
margin-top: 16rpx;
margin-left: 15rpx;
line-height: 50rpx;
font-size: 28rpx;
:last-child {
font-size: 24rpx;
}
}
.record_line {
position: absolute;
top: -102rpx;
left: -26rpx;
height: 105rpx;
border-left: 4rpx dotted #dedede;
}
&::before {
content: '';
display: block;
position: absolute;
top: 6rpx;
left: -34rpx;
width: 15rpx;
height: 15rpx;
border: 5rpx solid #dedede;
border-radius: 15rpx;
}
}
}
}
}
}
.peopleimg {
width: 35rpx;
height: 35rpx;
margin-right: 15rpx;
}
.phoneimg {
width: 40rpx;
height: 60rpx;
margin-right: 20rpx;
}
.con-name,
.con-mobile {
line-height: 50rpx;
}
.con-mobile {
color: #999;
}
.cline_li{
padding:20rpx 0;
border-bottom:1rpx solid #CCCCCC;
&:last-child{
border-bottom:0;
}
}
.clineInfo {
.info_head {
display: flex;
justify-content: space-between;
:first-child {
font-size: 28rpx;
font-weight: 700;
color: #999;
}
:last-child {
&::before {
position: relative;
display: block;
content: '';
width: 10rpx;
height: 10rpx;
top: 24rpx;
left: -22rpx;
background-color: #52c1f5;
border-radius: 5rpx;
}
}
}
.info_main {
display: flex;
justify-content: space-between;
.main_left {
.left_followUp {
display: flex;
padding: 20rpx 0;
}
.left_star {
display: flex;
padding-bottom: 20rpx;
}
}
.main_right {
text-align: center;
padding: 20rpx 20rpx 0 0;
image {
width: 44rpx;
height: 44rpx;
margin-bottom: 5rpx;
}
}
}
}
</style>

View File

@ -0,0 +1,191 @@
<template>
<view class="cust_detail">
<view class="cust_item_con" v-for="(item,index1) in cost_list" :key="index1"
@click.stop="toCostDetail(item.id)">
<view class="con_info">
<view style="font-weight: 600;">{{item.consume_type}}</view>
<view class="c_time">{{item.consume_time}}</view>
</view>
<view class="con_center">
<view>消费金额</view>
<view class="con_money">&yen; {{item.money}}</view>
</view>
<view style="color: #999;font-size: 32rpx;margin:0 0 24rpx;">备注:{{item.remark}}</view>
<view class="con_foot" @click.stop.prevent>
<view class="c_f_top">
附件
</view>
<scroll-view scroll-x style="width: 100%; white-space: nowrap;margin:24rpx 0" >
<view
class="box" v-for="(ind,index2) in item.file_text" :key="index2"
@click.stop="toPrevimg(item.file_text,index2)"
style="display: inline-block;margin-right:50rpx; width: 150rpx; height: 150rpx;">
<image
:src=" ind? ind: BASE_IMG_URL+'headImg.png'"
class="headimg"
style="width: 150rpx;height: 150rpx;"
mode="scaleToFill"></image>
</view>
</scroll-view>
</view>
<view class="status" v-if="item.check_status == 0"><span>待审核</span></view>
<view class="status" v-if="item.check_status == 1"><span>审核中</span></view>
<view class="status" v-if="item.check_status == 2"><span>审核通过</span></view>
<view class="status" v-if="item.check_status == 3"><span>审核未通过</span></view>
<view class="status" v-if="item.check_status == 4"><span>撤销</span></view>
</view>
<view style="height: 200rpx;"></view>
<u-empty v-if="cost_list.length == 0" text="暂无更多"></u-empty>
<view class="icon_creat" v-if="type == 1" @click="addCost">
<image :src="BASE_IMG_URL+'1.png'" mode="scaleToFill"></image>
</view>
</view>
</template>
<script>
import {
netCostList
} from '@/api/kehu.js'
import {
netGetSignList
} from '@/api/index.js'
import {
BASE_IMG_URL
} from '@/util/api.js'
export default {
data() {
return {
BASE_IMG_URL: BASE_IMG_URL,
cost_list: [], //
id: '',
type:1, //1 2
}
},
onLoad(options) {
this.id = options.id
this.type = options.type
},
onShow() {
//
this.getCostlist()
},
methods: {
//
getCostlist() {
netCostList({
customer_id: this.id
}).then(res => {
this.cost_list = res.data.data
})
},
//
addCost() {
uni.navigateTo({
url: '/pages/index/groupCompany/cost/addCost?kehuid=' + this.id
})
},
//
toCostDetail(id) {
uni.navigateTo({
url: '/pages/index/groupCompany/cost/costDetail?id=' + id
})
},
//
toPrevimg(arr,index){
uni.previewImage({
current:index,
urls:arr
})
}
}
}
</script>
<style lang="scss" scoped>
.imgbox{
align-items: center;
margin-top:15rpx;
.box{
width: 150rpx;
height: 150rpx;
margin-left: 30rpx;
background: #ededed;
float: left;
}
image{
margin: auto 0;
}
}
.cust_detail{
.cust_item_con{
background: #fff;
margin-top: 20rpx;
padding:30rpx 24rpx 30rpx 45rpx;
.con_info{
display: flex;
justify-content: space-between;
font-size: 34rpx;
color: #333;
.c_time{
margin: 10rpx;
font-size: 28rpx;
color: #999;
}
}
.con_center{
display: flex;
justify-content: space-between;
font-size: 32rpx;
height: 80rpx;
line-height: 80rpx;
color:#999999;
.con_money{
color: $uni-text-color;
font-size: 40rpx;
font-weight: 600;
}
}
.con_foot{
.c_f_top{
font-size: 32rpx;
color: #999;
}
.c_f_foot{
display: flex;
justify-content: space-around;
.box{
width: 150rpx;
height: 150rpx;
background: #ededed;
}
image{
margin: auto 0;
}
}
}
.status{
span{
font-size: 26rpx;
color: $uni-text-color;
padding: 5rpx 12rpx;
background: $uni-text-color-opcity;
}
}
}
}
#btn {
font-size: 26rpx;
color: #fff;
text-align: center;
line-height: 88rpx;
width: 500rpx;
height: 88rpx;
background: $uni-text-color;
border-radius: 29rpx;
margin: 30rpx auto;
}
</style>

View File

@ -0,0 +1,85 @@
<template>
<view class="info_detail">
<view class="info_item">
<view class="basic_head">
<view class="iconfont icon-arrows_right"></view>
<view>基本信息</view>
</view>
<form-item v-for="(item,index) in baseForm" :key="index" :objInfo="item" :isEdit="false"></form-item>
</view>
<view class="info_item">
<view class="basic_head">
<view class="iconfont icon-arrows_right"></view>
<view>附加信息</view>
</view>
<form-item v-for="(item,index) in otherForm" :key="index" :objInfo="item" :isEdit="false"></form-item>
</view>
</view>
</template>
<script>
import formItem from '@/components/form/formitem.vue'
import { netSetForm } from '@/api/index.js'
export default {
props:{
info:{
type:Object,
default:{}
}
},
components:{
formItem
},
created() {
this.getForm()
},
data() {
return {
otherForm:[],
baseForm:[]
}
},
methods: {
getForm() {
netSetForm({type:'contacts'}).then(res=>{
res = res.data.data
res.forEach(ele=>{
ele.value = this.info[ele.id]?this.info[ele.id]:''
if(ele.id.indexOf('other') != -1) {
this.otherForm.push(ele)
}else{
this.baseForm.push(ele)
}
})
})
}
}
}
</script>
<style lang="scss">
.info_detail {
margin-bottom: 100rpx;
.basic_head {
display: flex;
padding: 30rpx 24rpx 30rpx;
:last-child {
font-weight: 700;
margin-left: 8rpx;
}
}
.basic_main {
display: flex;
justify-content: space-between;
padding: 0 32rpx;
background-color: #fff;
height: 90rpx;
line-height: 90rpx;
border-bottom: 1rpx solid #EAEAEA;
:first-child {
color: #999;
}
}
}
</style>

View File

@ -0,0 +1,288 @@
<template>
<view class="group_company">
<view class="group_head">
<view class="group_item">
<view>职务</view>
<view class="text">{{info && info.post?info.post : '--'}}</view>
</view>
<view class="group_item">
<view>手机号</view>
<view class="text">{{info && info.mobile?info.mobile : '--'}}</view>
</view>
<view class="group_item">
<view>下次跟进时间</view>
<view class="text">{{info && info.next_time ?info.next_time : '--'}}</view>
</view>
</view>
<view class="tabinfo" @click="toKehuInfo">
<view class="tableft">
<image :src="BASE_IMG_URL+'headImg.png'" class="headerimg" mode="scaleToFill"></image>
<view class="name">{{info && info.customer.name}}</view>
</view>
<image :src="BASE_IMG_URL+'right.png'" class="rightimg" mode="scaleToFill"></image>
</view>
<!-- 标签栏 -->
<view class="group_tab">
<u-tabs name="cate_name" :list="list" :is-scroll="false" active-color="#008EFF" :current="current"
@change="change"></u-tabs>
<view class="processing_title" v-if="current == 0">
<customer-dynamic v-if="info" :kehuid="info.id" :type="2"></customer-dynamic>
</view>
<view class="processing_title" v-if="current == 1">
<base-info v-if="info" :info="info"></base-info>
</view>
<view class="processing_title" v-if="current == 2">
<related-info v-if="info" :contactid="info.id"></related-info>
</view>
</view>
<!-- 底部导航栏 -->
<view class="bottom_nav" v-if="type == 1">
<view class="bottom_item" @click="followClick(info.id,2)">
<view class="iconfont icon-task"></view>
<view>写新跟进</view>
</view>
<view class="bottom_item" @click="ToCall">
<view class="iconfont icon-task"></view>
<view>拨打电话</view>
</view>
<view class="bottom_item" @click="toEditInfo">
<view class="iconfont icon-task"></view>
<view>编辑信息</view>
</view>
<view class="bottom_item" @click="delContact">
<view class="iconfont icon-task"></view>
<view>删除</view>
</view>
</view>
</view>
</template>
<script>
import customerDynamic from 'components/content/customerDynamic/customerDynamic.vue';
import baseInfo from './baseInfo.vue'
import { BASE_IMG_URL } from '@/util/api.js'
import relatedInfo from './relatedInfo.vue';
import {pageJumps} from "../group_page_jumps.js";
import { netConcatDetailInfo, netRemoveSeas, netReceiveKehu, netKeyCollect, netDelContact, netRemoveColect } from '@/api/kehu.js'
export default {
mixins:[pageJumps],
data() {
return {
show: false,
taskShow: true,
statusShow: false,
BASE_IMG_URL:BASE_IMG_URL,
telShow: false,
telname:'',
id:'', //id
info:null,
current: 0,
list: [{
name: '跟进记录',
status: 0
},
{
name: '基本信息',
status: 1
},
{
name:'相关信息',
status:2
}
],
type:1, //1 2
}
},
onLoad(options) {
this.id = options.id
this.type = options.type
},
onShow() {
this.info = null
this.getInfo()
},
components: {
customerDynamic,
baseInfo,
relatedInfo
},
methods: {
change(index) {
this.current = index;
},
tabs_change(e) {
this.current = e;
this.mescroll.resetUpScroll();
},
changeTabs(e) {
let index = e.detail.index
},
//
addContract(id) {
uni.navigateTo({
url:'/pagesA/crm/contract/contract?id='+id
})
},
//
getInfo() {
netConcatDetailInfo({id:this.id}).then(res=>{
this.info = res.data
uni.setNavigationBarTitle({
title:res.data.name
})
})
},
//
ToCall() {
// #ifdef MP-ALIPAY
dd.showCallMenu({
phoneNumber: this.info.mobile,
code: '+86'
})
// #endif
// #ifndef APP-PLUS || MP-ALIPAY
uni.makePhoneCall({
phoneNumber: this.info.mobile
})
// #endif
// #ifdef APP-PLUS
plus.device.dial(this.info.mobile, true);
// #endif
},
//
toEditInfo() {
uni.navigateTo({
url:'/pages/index/groupCompany/contact/editInfo?id='+this.info.id
})
},
//
toKehuInfo() {
uni.navigateTo({
url:'/pages/index/groupCompany/groupCompany?id='+this.info.customer.id
})
},
//
delContact() {
uni.showModal({
title:'提示',
content:'请确认是否删除?',
success:(res)=>{
if(res.confirm){
netDelContact({id:this.info.id}).then(res=>{
uni.showToast({
title:res.msg,
icon:'none'
})
setTimeout(()=>{
uni.navigateBack({
delta:1
})
},2000)
})
}
}
})
}
}
}
</script>
<style lang="scss">
.group_head {
display: flex;
flex-wrap: wrap;
padding: 20rpx 0;
background-color: #fff;
text-align: center;
.group_item {
width: 33.33%;
color: #ccc;
margin-bottom:15rpx;
.text{
line-height:48rpx;
color: #999;
}
.group_htz{
margin-top: 8rpx;
}
}
}
.tabinfo{
display: flex;
justify-content: space-between;
align-items: center;
padding:20rpx;
background:#fff;
border-top:1rpx solid #C0C0C0;
.tableft{
display: flex;
justify-content: flex-start;
align-items: center;
.headerimg{
width:45rpx;
height:45rpx;
border-radius: 50%;
}
.name{
font-size:26rpx;
color:$uni-text-color;
margin-left:24rpx;
}
}
.rightimg{
width:32rpx;
height:32rpx;
}
}
.group_tab {
margin: 20rpx 0;
}
.bottom_nav {
position: fixed;
display: flex;
bottom: 0;
left: 0;
right: 0;
padding: 20rpx 0;
background-color: #fff;
text-align: center;
color: #999;
display: flex;
justify-content: space-around;
align-items: center;
z-index: 9;
.bottom_item {
// width: 25%;
:first-child {
padding-bottom: 6rpx;
}
}
}
.pull_con {
padding: 40rpx 0 10rpx;
display: flex;
flex-wrap: wrap;
text-align: center;
color: #999;
.pull_item {
width: 25%;
:first-child {
padding-bottom: 10rpx;
}
:last-child {
padding-bottom: 50rpx;
}
}
}
</style>

View File

@ -0,0 +1,162 @@
<template>
<view class="new_linkman">
<view class="info_head">基础信息</view>
<form-item v-for="(item,index) in listForm" :key="index" :objInfo="item" @changeData="changeData"></form-item>
<view id="btn" class="btn_g bg-blue button-hover round" @click="toSave">
保存
</view>
</view>
</template>
<script>
import formItem from '@/components/form/formitem.vue'
import { netSetForm } from '@/api/index.js'
import { netSelect, netEditContactInfo, netConcatDetailInfo } from '@/api/kehu.js'
import { checkPhone } from '@/util/util.js'
export default {
components:{
formItem
},
data() {
return {
id:'', //
info:{},
listForm:[]
}
},
onLoad(options) {
this.id = options.id
//
this.getInfo()
},
methods: {
//
getInfo() {
netConcatDetailInfo({id:this.id}).then(res=>{
res = res.data
this.info = res
this.getForm()
})
},
getForm() {
netSetForm({type:'contacts'}).then(res=>{
res = res.data.data
res.forEach(ele=>{
ele.value = this.info[ele.id]?this.info[ele.id]:''
})
this.listForm = res
})
},
changeData(name,value,obj) {
let arr = this.listForm
arr.forEach((ele,index) => {
if(ele.id == obj.id){
ele.value = value
this.$set(this.listForm,index,ele)
}
})
},
//
toSave() {
let params = this.checkCommonForm(this.listForm)
if(!params){
return
}
params = Object.assign({},params,{id:this.id})
netEditContactInfo(params).then(res=>{
uni.showToast({
title: res.msg,
icon:'none',
duration: 2000
})
setTimeout(()=>{
uni.navigateBack({
delta:1
})
},2000)
})
},
}
}
</script>
<style lang="scss" scoped>
.new_linkman {
font-size: 28rpx;
.mar_top {
margin-top: 30rpx;
}
.info_head {
height: 80rpx;
line-height: 80rpx;
font-size: 24rpx;
color: #999;
padding-left: 24rpx;
}
.fllow_form {
display: flex;
justify-content: space-between;
height: 100rpx;
line-height: 100rpx;
background-color: #fff;
border-bottom: 1rpx solid #EAEAEA;
padding: 0 24rpx;
input {
height: 100rpx;
line-height: 100rpx;
}
.form_right {
display: flex;
color: #999;
image {
width: 40rpx;
height: 40rpx;
margin: 28rpx 5rpx 0 0;
}
}
.theme {
color: #5ca9fe;
}
text {
color: #f00;
margin-left: 10rpx;
}
.form_input {
input {
height: 100rpx;
line-height: 100rpx;
text-align: right;
margin-right: 10rpx;
}
}
}
.fllow_area {
background-color: #fff;
padding: 0 30rpx;
margin-bottom: 30rpx;
.area_head {
height: 100rpx;
line-height: 100rpx;
text {
color: #f00;
}
}
textarea {
width: 100%;
height: 300rpx;
background: #f8f8f8;
}
}
}
#btn {
font-size: 26rpx;
color: #fff;
text-align: center;
line-height: 88rpx;
width: 500rpx;
height: 88rpx;
background: $uni-text-color;
border-radius: 29rpx;
margin: 30rpx auto;
}
</style>

View File

@ -0,0 +1,343 @@
<template>
<view class="cust_detail">
<view class="cust_item">
<view class="cust_item_head">
<view class="head_info">
<image :src="BASE_IMG_URL+'fujian.png'" class="peopleimg" mode="scaleToFill"></image>
<view>附件</view>
</view>
</view>
<view class="item_doc">
<view class="doc_item" v-for="(item,index) in fileList" :key="index" @click.stop="lookDetail(item)">
<view class="iconfont icon--task"></view>
<input type="text" :disabled="item.disabled" :focus="item.focus" :data-index="index" v-model="item.name" @confirm="changeName" @blur="changeName" class="doc_name" />
<view class="doc_size">{{item.size}}</view>
<image :src="BASE_IMG_URL+'edit.png'" class="editimg" @click.stop="edit(index)" mode="scaleToFill"></image>
</view>
</view>
</view>
<view class="cust_item">
<view class="cust_item_head">
<view class="head_info">
<image :src="BASE_IMG_URL+'followRecord.png'" class="peopleimg" mode="scaleToFill"></image>
<view>操作记录</view>
</view>
</view>
<view class="operation_record" v-if="opera_list.length != 0">
<view class="record_item" v-for="(item,index) in opera_list" :key="index">
<image :src="item.staff.img ? item.staff.img : BASE_IMG_URL+'headImg.png'" mode="scaleToFill"></image>
<view class="record_info">
<view class="info_top">
<view>{{item.staff.name}}</view>
<view class="record_time">
{{item.createtime}}
</view>
</view>
<view>{{item.content}}</view>
</view>
</view>
</view>
</view>
</view>
</template>
<script>
import { netContactFileList, netOperationList, netEditFileName } from '@/api/kehu.js'
import { BASE_IMG_URL } from '@/util/api.js'
export default {
props:{
contactid:{
type:Number,
default:null
}
},
data() {
return {
fileList:[], //
opera_list:[], //
BASE_IMG_URL:BASE_IMG_URL,
}
},
created() {
//
this.getFile()
//
this.getOperalist()
},
methods: {
getFile() {
let params = { contacts_id:this.contactid }
netContactFileList(params).then(res=>{
res.data.forEach(item=>{
item.disabled = true
item.focus = false
})
this.fileList = res.data
})
},
getOperalist() {
let params = {
relation_type:2,
relation_id: this.contactid
}
netOperationList(params).then(res=>{
this.opera_list = res.data
})
},
//
lookDetail(item) {
if(item.types.indexOf('image') != -1){
uni.previewImage({
urls: [ item.file_path ]
})
}else{
uni.downloadFile({
url: item.file_path,
success:(res)=>{
uni.openDocument({
filePath:res.tempFilePath,
success:(res)=>console.log('成功打开文档')
})
},
fail:(err)=>{
console.log(err,'shibai')
}
})
}
},
//
edit(index) {
let obj = this.fileList[index]
obj.disabled = false
obj.focus = true
this.fileList[index] = obj
},
changeName(e) {
let name = e.detail.value
let index = e.currentTarget.dataset.index
let params = {
id: this.fileList[index].id,
name
}
netEditFileName(params).then(res=>{
uni.showToast({
title:res.msg,
icon:'none'
})
setTimeout(()=>{
this.getFile()
},2000)
})
},
}
}
</script>
<style lang="scss" scoped>
.cust_detail {
.cust_item {
padding: 0 24rpx;
background-color: #fff;
margin-bottom: 20rpx;
.cust_item_head {
display: flex;
justify-content: space-between;
line-height: 100rpx;
border-bottom: 1rpx solid #EAEAEA;
.head_info {
display: flex;
align-items: center;
.icon--task {
margin-right: 10rpx;
}
}
.head_new {
display: flex;
align-items: center;
color: #1c9bfc;
.icon-clock {
margin-right: 10rpx;
}
}
}
.lxr_con_list{
padding-bottom:20rpx;
border-bottom:1rpx solid #C0C0C0;
&:last-child{
border-bottom:none;
}
.name{
font-size:28rpx;
color:#333333;
margin-top:15rpx;
}
.info{
font-size:24rpx;
color:#999999;
margin:10rpx 0;
}
.proce_li{
display: flex;
justify-content: space-between;
align-items: center;
.pro_li_left{
display: flex;
justify-content: flex-start;
align-items: center;
.protext{
font-size:24rpx;
color:#999999;
}
.probox{
width:120rpx;
height:15rpx;
border-radius: 8rpx;
background:#C0C0C0;
margin:0 15rpx;
.proin{
width:20%;
height:15rpx;
border-radius: 8rpx;
background:#ff7800;
}
}
.pronum{
font-size:24rpx;
color:#999999;
}
}
.pro_li_right{
color: #ec7f51;
font-size: 28rpx;
font-weight: 500;
}
}
.con_status{
font-size:24rpx;
color:$uni-text-color;
margin-top:10rpx;
}
}
.cust_item_con {
border-bottom: 1rpx solid #EAEAEA;
padding:15rpx 0;
display: flex;
justify-content: space-between;
align-items: center;
.con_info {
padding: 10rpx 0;
:first-child {
color: #060606;
font-weight: 700;
line-height: 50rpx;
font-size: 28rpx;
}
:last-child {
color: #469369;
line-height: 50rpx;
}
}
.con_money {
color: #ec7f51;
font-size: 28rpx;
line-height: 150rpx;
font-weight: 700;
}
}
.item_doc {
// padding: 30rpx 0;
.doc_item {
display: flex;
align-items: center;
background-color: #f7faff;
line-height: 60rpx;
margin-bottom: 20rpx;
.icon--task {
width: 50rpx;
padding-left: 10rpx;
}
.doc_name {
flex: 1;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.doc_size {
width: 130rpx;
}
.editimg{
width: 40rpx;
height:40rpx;
}
.icon-clear {
width: 50rpx;
}
}
}
.operation_record {
padding: 40rpx 0rpx;
.record_item {
display: flex;
justify-content: space-between;
margin-bottom: 20rpx;
padding-bottom:20rpx;
border-bottom:1rpx solid #EAEAEA;
margin-bottom:20rpx;
&:last-child{
border-bottom:none;
}
image {
width: 80rpx;
height: 80rpx;
border-radius: 50%;
flex-shrink: 0;
}
.record_info {
flex: 1;
margin-left: 25rpx;
line-height: 40rpx;
font-size: 28rpx;
.info_top{
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom:10rpx;
}
.shenhetext{
font-size:26rpx;
color:#666;
line-height: 34rpx;
}
}
.record_line {
position: absolute;
top: -102rpx;
left: -26rpx;
height: 105rpx;
border-left: 4rpx dotted #dedede;
}
}
}
}
}
.peopleimg{
width:35rpx;
height:35rpx;
margin-right:15rpx;
}
.phoneimg{
width:40rpx;
height:60rpx;
margin-right: 20rpx;
}
.con-name,.con-mobile{
line-height: 50rpx;
}
.con-mobile{
color:#999;
}
</style>

View File

@ -0,0 +1,565 @@
<template>
<view class="new_fllow">
<view class="top_required">
只展示<span style="color:#f00">必填</span>字段<switch :checked="isRequired" color="#008EFF" @change="changeRequired" />
</view>
<view class="fllow_form">
<view><text>*</text>关联客户</view>
<view class="form_right" @click="changeCustomer">
<view :class="customerObj.id ? 'valueActive' : '' ">{{customerObj.id ? customerObj.name: '点击选择'}}</view>
<view class="iconfont icon-arrows_right"></view>
</view>
</view>
<view class="fllow_form">
<view><text>*</text>消费日期</view>
<picker mode="date" @change="changeTime">
<view class="form_right">
<view :class="consume_time ? 'valueActive' : '' ">{{consume_time ? consume_time : '点击选择'}}</view>
<view class="iconfont icon-arrows_right"></view>
</view>
</picker>
</view>
<view class="fllow_form">
<view><text>*</text>消费方式</view>
<picker :value="index" @change="changeType" :range="typeList">
<view class="form_right">
<view :class="consume_type ? 'valueActive' : '' ">{{consume_type ? consume_type : '点击选择'}}</view>
<view class="iconfont icon-arrows_right"></view>
</view>
</picker>
</view>
<view class="fllow_form">
<view><text>*</text>消费金额</view>
<view class="form_input">
<input type="text" :class="money ? 'valueActive' : '' " v-model="money"
placeholder-style="font-size:30rpx;color: #999;" placeholder="请输入消费金额" class="">
</view>
</view>
<view class="fllow_area" v-if="!isRequired">
<view class="area_head">备注</view>
<textarea v-model="remark" :class="remark ? 'valueActive' : '' " placeholder="请输入备注"
placeholder-style="color:#999" />
</view>
<view class="fllow_form" v-if="!isRequired">
<view style="padding-left: 23rpx;">上传附件</view>
<view class="form_right" @click="uploadClick">
<view>选择附件</view>
<view class="iconfont icon-arrows_right"></view>
</view>
</view>
<view class="imglist" v-if="imgList.length != 0">
<view class="imgbox" v-for="(item,imgindex) in imgList" :key="imgindex">
<image :src="BASE_IMG_URL+'close.png'" class="delimg" @click="delImg(imgindex)" mode="scaleToFill"></image>
<image :src="item.url" class="selfimg" @click="openCommonImg(imgList,imgindex)" mode="scaleToFill"></image>
</view>
</view>
<view class="fllow_file_li" v-if="fileList.length != 0">
<view class="fil_li" v-for="(item,fileindex) in fileList" :key="fileindex">
<image :src="BASE_IMG_URL+'fujian.png'" class="fileimg" mode="scaleToFill"></image>
<view class="filename" @click="openCommonFile(item)">{{item.name}}</view>
<image :src="BASE_IMG_URL+'close.png'" class="closeimg" @click="delFile(fileindex)" mode="scaleToFill">
</image>
</view>
</view>
<!-- 回款审批流程 -->
<!-- 固定审批 -->
<fixed-approval v-if="approvalPro.status == 1" :list="approvalPro.stepList"></fixed-approval>
<!-- 审核信息 -->
<examine-template v-if="approvalPro.status == 0" :remindPeople="remindPeople" @delExamine="delRemind"></examine-template>
<view id="btn" class="btn_g bg-blue button-hover round" @click="$noMultipleClicks(saveFollow)">
保存
</view>
<u-action-sheet :list="uploadActions" v-model="uploadShow" @click="uploadType"></u-action-sheet>
<!-- 选择客户 -->
<select-customer ref="customerChild" @getCustomerinfo="getCustomerinfo"></select-customer>
</view>
</template>
<script>
import {
netSelect,
netAddCost,
netPrevCustomer
} from '@/api/kehu.js'
import {
netStaffDefaultReviewer,
uploadUrl,
netApprovalProcess
} from '@/api/index.js'
import {
BASE_IMG_URL
} from '@/util/api.js'
import {
commonF
} from '@/common/common'
import fixedApproval from '@/components/fixedApproval.vue'
import selectCustomer from '@/components/selectCustomer.vue'
export default {
mixins: [commonF],
components:{
fixedApproval,
selectCustomer
},
data() {
return {
noClick: true, //
customer_id: '', //id
consume_time: '', //
consume_type: '', //
money: '', //
remark: '', //
file_ids: '', //id
BASE_IMG_URL: BASE_IMG_URL,
typeList: [], //
index: null,
DefaultRemind: [],
remindPeople: [], //
remindType: 'consume',
imgList: [],
fileList: [],
uploadShow: false,
uploadActions: [{
id: 1,
text: '拍照',
color: '#008EFF'
},
{
id: 2,
text: '从相册中选择',
color: '#008EFF'
},
],
//
customerList:[],
customerIndex:null,
customerObj:{},
approvalPro:{}, //
isRequired:false, //
}
},
onLoad(options) {
if(options.kehuid){
this.customer_id = options.kehuid
this.getKehu()
}
//
this.getType()
//
this.getProcess()
},
methods: {
//
changeRequired(e) {
this.isRequired = e.detail.value
},
//
getProcess() {
netApprovalProcess({type:'consume'}).then(res=>{
this.approvalPro = res.data
})
},
//
getKehu() {
netPrevCustomer().then(res=>{
this.customerList = res.data
if(this.customer_id){
this.customerList.forEach((ele,index)=>{
if(ele.id == this.customer_id){
this.customerObj = ele
}
})
}
})
},
//
changeCustomer(e) {
this.$refs.customerChild.init()
},
getCustomerinfo(obj) {
this.customerObj = obj
},
//
getType() {
netSelect().then(res => {
this.typeList = res.data['消费方式']
})
},
//
changeTime(e) {
this.consume_time = e.detail.value
},
//
changeType(e) {
this.consume_type = this.typeList[e.detail.value]
},
//
uploadClick() {
this.uploadShow = true
},
onCancel() {
this.uploadShow = false
},
uploadType(index) {
if (index == 0) {
//
uni.chooseImage({
sourceType: ['camera'],
sizeType: ['compressed'],
success: (res) => {
let file = res.tempFilePaths
file.forEach(ele => {
this.uploadFile(ele, 1)
})
}
})
} else if (index == 1) {
//
uni.chooseImage({
sourceType: ['album'],
sizeType: ['compressed'],
success: (res) => {
let file = res.tempFilePaths
file.forEach(ele => {
this.uploadFile(ele, 1)
})
}
})
} else {
//
wx.chooseMessageFile({
count: 1,
type: 'file',
success: (res) => {
let file = res.tempFiles[0]
this.uploadFile(file, 2)
},
fail: (err) => {
console.log(err)
}
})
}
},
//type 1 2
uploadFile(file, type) {
uni.uploadFile({
url: uploadUrl,
name: 'file',
header: {
'token': uni.getStorageSync('token')
},
// #ifdef MP-ALIPAY
fileType: 'image',
// #endif
filePath: type == 1 ? file : file.path,
success: (res) => {
let data = JSON.parse(res.data)
this.uploadShow = false
if (data.code == 1) {
if (type == 1) {
this.imgList.push(data.data)
} else {
file = Object.assign({}, file, data.data)
this.fileList.push(file)
}
} else {
uni.showToast({
title: '上传失败',
icon: 'none'
})
}
},
fail: (err) => {
console.log(err)
}
})
},
//
delImg(index) {
this.imgList.splice(index, 1)
},
//
delFile(index) {
this.fileList.splice(index, 1)
},
//
moreClick() {
uni.navigateTo({
url: '/pagesA/crm/selectMember/selectMember'
})
},
//
saveFollow() {
let {
consume_time, //
consume_type, //
money, //
remark, //
imgList,
fileList,
remindPeople, //
} = this
if(!this.customerObj.id){
uni.showToast({
title: '请选择关联客户',
icon: 'none'
})
return
}
if (!consume_time) {
uni.showToast({
title: '请选择消费日期',
icon: 'none'
})
return
}
if (!consume_type) {
uni.showToast({
title: '请选择消费方式',
icon: 'none'
})
return
}
if (!money) {
uni.showToast({
title: '请填写消费金额',
icon: 'none'
})
return
}
if ((!remindPeople || remindPeople.length == 0) && this.approvalPro.status == 0) {
uni.showToast({
title: '请选择流程审批人',
icon: 'none'
})
return
}
let arr = []
imgList.forEach(ele => {
arr.push(ele.id)
})
let file_ids = arr.join(',')
//
let remarr = []
remindPeople.forEach(ele => {
remarr.push(ele.id)
})
let params = {
customer_id:this.customerObj.id?this.customerObj.id:'', //id
consume_time, //
consume_type, //
money, //
remark, //
file_ids,
flow_staff_ids:this.approvalPro.status == 0 ? remarr.join(',') : ''
}
netAddCost(params).then(res => {
uni.showToast({
title: res.msg,
icon: 'none'
})
setTimeout(() => {
uni.navigateBack({
delta: 1
})
}, 2000)
})
}
}
}
</script>
<style lang="scss">
.valueActive {
color: #333;
}
.new_fllow {
font-size: 28rpx;
.fllow_form {
display: flex;
justify-content: space-between;
align-items: center;
height: 100rpx;
line-height: 100rpx;
background-color: #fff;
border-bottom: 1rpx solid #EAEAEA;
padding: 0 30rpx;
color: #999;
font-size: 32rpx;
.form_right {
display: flex;
color: #999;
image {
width: 40rpx;
height: 40rpx;
margin: 28rpx 5rpx 0 0;
}
}
text {
color: #f00;
margin-left: 10rpx;
}
.form_input {
input {
height: 100%;
// height: 100rpx;
// line-height: 100rpx;
text-align: right;
}
}
.fllow_button {
margin-top: 15rpx;
}
}
.fllow_file_li {
padding: 24rpx 34rpx;
background: #fff;
border-bottom: 1rpx solid #EAEAEA;
.fil_li {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 14rpx;
.fileimg {
width: 20rpx;
height: 20rpx;
}
.filename {
width:450rpx;
font-size: 24rpx;
color: #999999;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.closeimg {
width: 32rpx;
height: 32rpx;
}
}
}
.imglist {
padding: 24rpx 34rpx;
background: #fff;
border-bottom: 1rpx solid #EAEAEA;
display: flex;
justify-content: flex-start;
align-items: center;
flex-wrap: wrap;
.imgbox {
width: 160rpx;
height: 160rpx;
margin-right: 14rpx;
position: relative;
margin-bottom: 24rpx;
border: 1rpx solid #EAEAEA;
.delimg {
width: 32rpx;
height: 32rpx;
border-radius: 50%;
position: absolute;
right: -16rpx;
top: -16rpx;
background: rgba(0, 0, 0, 0.5);
z-index: 2;
}
.selfimg {
width: 160rpx;
height: 160rpx;
}
}
}
.fllow_area {
background-color: #fff;
// padding: 0 70rpx;
margin-bottom: 30rpx;
padding-bottom: 30rpx;
color: #999;
.area_head {
height: 100rpx;
line-height: 100rpx;
font-size: 32rpx;
padding: 0 30rpx;
text {
color: #f00;
}
}
textarea {
width: 80%;
height: 300rpx;
padding: 30rpx;
background: #f8f8f8;
border-radius: 15rpx;
margin: 0 auto;
}
}
.follow_task {
height: 80rpx;
line-height: 80rpx;
}
}
.imglist {
padding: 24rpx 34rpx;
background: #fff;
border-bottom: 1rpx solid #EAEAEA;
display: flex;
justify-content: flex-start;
align-items: center;
flex-wrap: wrap;
.imgbox {
width: 160rpx;
height: 160rpx;
margin-right: 14rpx;
position: relative;
margin-bottom: 24rpx;
border: 1rpx solid #EAEAEA;
.delimg {
width: 32rpx;
height: 32rpx;
border-radius: 50%;
position: absolute;
right: -16rpx;
top: -16rpx;
background: rgba(0, 0, 0, 0.5);
z-index: 2;
}
.selfimg {
width: 160rpx;
height: 160rpx;
}
}
}
#btn {
width: 500rpx;
height: 88rpx;
background: $uni-text-color;
border-radius: 29rpx;
font-size: 34rpx;
color: #fff;
line-height: 88rpx;
}
</style>

View File

@ -0,0 +1,354 @@
<template>
<view class="new_fllow">
<view class="fllow_form">
<view>提交人</view>
<view class="form_input" >
<view class="">
{{info.staff && info.staff.name}}
</view>
</view>
</view>
<view class="fllow_form">
<view>提交时间</view>
<view class="form_input">
<view class="">
{{info.createtime}}
</view>
</view>
</view>
<view class="fllow_form">
<view>关联客户</view>
<view class="form_input" >
{{info.customer && info.customer.name}}
</view>
</view>
<view class="fllow_form">
<view><text>*</text>消费日期</view>
<picker mode="date" disabled @change="changeTime">
<view class="form_right">
<view>{{info.consume_time}}</view>
<view class="iconfont icon-arrows_right"></view>
</view>
</picker>
</view>
<view class="fllow_form">
<view><text>*</text>消费方式</view>
<view class="form_right">
<view>{{info.consume_type}}</view>
<view class="iconfont icon-arrows_right"></view>
</view>
</view>
<view class="fllow_form">
<view><text>*</text>消费金额</view>
<view class="form_input" >
<input type="text" disabled v-model="info.money" placeholder-style="font-size:30rpx;color: #999;" placeholder="消费金额" class="">
</view>
</view>
<view class="fllow_area">
<view class="area_head">备注</view>
<textarea v-model="info.remark" disabled placeholder="请输入备注" placeholder-style="color:#999" />
</view>
<view class="fllow_form">
<view>附件</view>
</view>
<view class="imglist" v-if="info.files != 0">
<view class="imgbox" v-for="(item,index) in info.file_text" :key="index">
<image :src="item" class="selfimg" mode="scaleToFill" @click="previewImg(info.file_text,index)"></image>
</view>
</view>
<!-- 审批流程 -->
<approval-status :process="payment_approval"></approval-status>
<view style="height:100rpx;"></view>
<view class="botbtn" v-if="payment_approval.is_check == 1">
<view class="btn pass" @click="toPass">通过</view>
<view class="btn refuse" @click="toRefuse">拒绝</view>
</view>
<view class="editbox" v-if="info.check_status == 3">
<view class="editbtn" @click="toEdit">修改费用</view>
</view>
</view>
</template>
<script>
import { BASE_URL } from '@/util/api.js'
import { netSelect, netCostDetail } from '@/api/kehu.js'
import { netApprovalDetail } from '@/api/index.js'
import { BASE_IMG_URL } from '@/util/api.js'
import approvalStatus from '@/components/approvalStatus.vue'
export default {
components:{
approvalStatus
},
data() {
return {
id:'', //id
customer_id:'', //id
consume_time:'', //
consume_type:'', //
money:'', //
remark:'', //
file_ids:'', //id
BASE_IMG_URL:BASE_IMG_URL,
info:{},
payment_approval:{}, //
}
},
onLoad(options) {
this.id = options.id
},
onShow() {
//
// this.getType()
//
this.getDetail()
//
this.getApprovalList()
},
//
onUnload() {
uni.removeStorageSync('remindlist')
},
methods: {
//
getApprovalList() {
let params = {
type: 'consume',
relation_id: this.id
}
netApprovalDetail(params).then(res=>{
this.payment_approval = res.data
})
},
//
getDetail() {
netCostDetail({id:this.id}).then(res=>{
this.info = res.data
})
},
//
previewImg(arr,index) {
uni.previewImage({
urls: arr,
current:index,
fail:(err)=>{
console.log(err)
}
})
},
//
toPass() {
uni.navigateTo({ //status 1 2
url:'/pages/examine/examine?id='+this.id+'&type=consume&status=1'
})
},
//
toRefuse() {
uni.navigateTo({ //status 1 2
url:'/pages/examine/examine?id='+this.id+'&type=consume&status=2'
})
},
//
toEdit() {
uni.navigateTo({
url:'/pages/index/groupCompany/cost/editCost?id='+this.id
})
}
}
}
</script>
<style lang="scss">
.new_fllow {
font-size: 28rpx;
.fllow_form {
display: flex;
justify-content: space-between;
align-items: center;
height: 100rpx;
line-height: 100rpx;
background-color: #fff;
border-bottom: 1rpx solid #EAEAEA;
padding: 0 24rpx;
.form_right {
display: flex;
color: #999;
image {
width: 40rpx;
height: 40rpx;
margin: 28rpx 5rpx 0 0;
}
}
text {
color: #f00;
margin-left: 10rpx;
}
.form_input {
input {
height: 100%;
// line-height: 100rpx;
text-align: right;
margin-right: 10rpx;
color: #999;
}
}
.fllow_button {
margin-top: 15rpx;
}
}
.fllow_area {
background-color: #fff;
margin-bottom: 30rpx;
padding-bottom: 30rpx;
color: #999;
.area_head {
height: 100rpx;
line-height: 100rpx;
font-size: 32rpx;
padding: 0 30rpx;
text {
color: #f00;
}
}
textarea {
width: 80%;
height: 300rpx;
padding: 30rpx;
background: #f8f8f8;
margin: 0 auto;
}
}
.follow_task {
height: 80rpx;
line-height: 80rpx;
}
}
.imglist{
padding:24rpx 34rpx;
background:#fff;
border-bottom:1rpx solid #EAEAEA;
display: flex;
justify-content: flex-start;
align-items: center;
flex-wrap: wrap;
.imgbox{
width:140rpx;
height:140rpx;
margin-right:30rpx;
margin-bottom:24rpx;
border:1rpx solid #EAEAEA;
.selfimg{
width:140rpx;
height:140rpx;
}
}
}
.botbtn{
width:750rpx;
height:100rpx;
display: flex;
justify-content: space-around;
align-items:center;
border-top:1rpx solid #CCCCCC;
background:#fff;
position: fixed;
left:0;
bottom:0;
.btn{
width:300rpx;
height:80rpx;
border-radius: 40rpx;
font-size:26rpx;
color:#fff;
text-align: center;
line-height: 80rpx;
}
.pass{
background:$uni-text-color;
}
.refuse{
background:#F43F3B;
}
}
.basic_main {
display: flex;
justify-content: space-between;
padding: 0 32rpx;
background-color: #fff;
height: 90rpx;
line-height: 90rpx;
border-bottom: 1rpx solid #EAEAEA;
:first-child {
color: #999;
}
}
.operation_record {
background:#fff;
padding: 40rpx 30rpx;
.record_item {
display: flex;
justify-content: space-between;
margin-bottom: 20rpx;
padding-bottom:20rpx;
border-bottom:1rpx solid #EAEAEA;
margin-bottom:20rpx;
&:last-child{
border-bottom:none;
}
image {
width: 80rpx;
height: 80rpx;
border-radius: 50%;
flex-shrink: 0;
}
.record_info {
flex: 1;
margin-left: 25rpx;
line-height: 40rpx;
font-size: 28rpx;
.info_top{
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom:10rpx;
}
.shenhetext{
font-size:26rpx;
color:#666;
line-height: 34rpx;
}
}
.record_line {
position: absolute;
top: -102rpx;
left: -26rpx;
height: 105rpx;
border-left: 4rpx dotted #dedede;
}
}
}
.editbox{
width:750rpx;
height:100rpx;
display: flex;
justify-content: space-around;
align-items:center;
border-top:1rpx solid #CCCCCC;
background:#fff;
position: fixed;
left:0;
bottom:0;
.editbtn{
width:680rpx;
height:80rpx;
border-radius: 40rpx;
background:$uni-text-color;
font-size:26rpx;
color:#fff;
text-align: center;
line-height: 80rpx;
}
}
</style>

View File

@ -0,0 +1,483 @@
<template>
<view class="new_fllow">
<view class="fllow_form">
<view><text>*</text>消费日期</view>
<picker mode="date" @change="changeTime">
<view class="form_right">
<view>{{consume_time ? consume_time : '点击选择'}}</view>
<view class="iconfont icon-arrows_right"></view>
</view>
</picker>
</view>
<view class="fllow_form">
<view><text>*</text>消费方式</view>
<picker :value="index" @change="changeType" :range="typeList">
<view class="form_right">
<view>{{consume_type ? consume_type : '点击选择'}}</view>
<view class="iconfont icon-arrows_right"></view>
</view>
</picker>
</view>
<view class="fllow_form">
<view><text>*</text>消费金额</view>
<view class="form_input">
<input type="text" v-model="money" placeholder-style="font-size:30rpx;color: #999;" placeholder="消费金额" class="">
</view>
</view>
<view class="fllow_area">
<view class="area_head">备注</view>
<textarea v-model="remark" placeholder="请输入备注" placeholder-style="color:#999" />
</view>
<view class="fllow_form">
<view>上传附件</view>
<view class="form_right" @click="uploadClick">
<view>选择附件</view>
<view class="iconfont icon-arrows_right"></view>
</view>
</view>
<u-action-sheet
:list="uploadActions"
v-model="uploadShow"
@click="uploadType"
></u-action-sheet>
<view class="imglist" v-if="imgList.length != 0">
<view class="imgbox" v-for="(item,index) in imgList" :key="index">
<image :src="BASE_IMG_URL+'close.png'" class="delimg" @click="delImg(index)" mode="scaleToFill"></image>
<image :src="item.file_path" class="selfimg" mode="scaleToFill"></image>
</view>
</view>
<!-- 固定审批 -->
<fixed-approval v-if="approvalPro.status == 1" :list="approvalPro.stepList"></fixed-approval>
<!-- 审核信息 -->
<examine-template v-if="approvalPro.status == 0" :remindPeople="remindPeople" @delExamine="delRemind"></examine-template>
<view id="btn" class="btn_g bg-blue button-hover round" @click="saveFollow">
保存
</view>
</view>
</template>
<script>
import {
netSelect,
netEditCost,
netCostDetail
} from '@/api/kehu.js'
import {
BASE_IMG_URL
} from '@/util/api.js'
import {
netStaffDefaultReviewer,
uploadUrl,
netApprovalProcess
} from '@/api/index.js'
import { commonF } from '@/common/common'
import fixedApproval from '@/components/fixedApproval.vue'
export default {
mixins:[commonF],
components:{
fixedApproval
},
data() {
return {
id: '', //id
customer_id: '', //id
consume_time: '', //
consume_type: '', //
money: '', //
remark: '', //
file_ids: '', //id
BASE_IMG_URL: BASE_IMG_URL,
typeList: [], //
DefaultRemind: [],
remindPeople: [], //
remindType:'contract',
imgList: [],
uploadShow: false,
uploadActions: [{
id: 1,
text: '拍照',
color: '#008EFF'
}, {
id: 2,
text: '从相册中选择',
color: '#008EFF'
}, ],
show: false,
approvalPro:{}, //
}
},
onLoad(options) {
this.id = options.id
//
this.getDetail()
//
this.getProcess()
},
onShow() {
//
this.getType()
},
methods: {
//
getProcess() {
netApprovalProcess({type:'consume'}).then(res=>{
this.approvalPro = res.data
})
},
//
getDetail() {
netCostDetail({
id: this.id
}).then(res => {
res = res.data
this.consume_time = res.consume_time
this.consume_type = res.consume_type
this.money = res.money
this.remark = res.remark
this.imgList = res.files
this.customer_id = res.customer_id
})
},
//
getType() {
netSelect().then(res => {
this.typeList = res.data['消费方式']
})
},
//
changeTime(e) {
this.consume_time = e.detail.value
},
//
changeType(e) {
this.consume_type = this.typeList[e.detail.value]
},
//
uploadClick() {
this.uploadShow = true
},
onCancel() {
this.uploadShow = false
},
uploadType(index) {
if (index == 0) {
//
uni.chooseImage({
sourceType: ['camera'],
sizeType:['compressed'],
success: (res) => {
let file = res.tempFilePaths
file.forEach(ele=>{
this.uploadFile(ele, 1)
})
}
})
} else if (index == 1) {
//
uni.chooseImage({
sourceType: ['album'],
sizeType:['compressed'],
success: (res) => {
let file = res.tempFilePaths
file.forEach(ele=>{
this.uploadFile(ele, 1)
})
}
})
} else {
//
wx.chooseMessageFile({
count: 1,
type: 'file',
success: (res) => {
let file = res.tempFiles[0]
this.uploadFile(file, 2)
},
fail: (err) => {
console.log(err)
}
})
}
},
//type 1 2
uploadFile(file, type) {
uni.uploadFile({
url: uploadUrl,
name: 'file',
header: {
'token': uni.getStorageSync('token')
},
// #ifdef MP-ALIPAY
fileType:'image',
// #endif
filePath: type == 1 ? file : file.path,
success: (res) => {
let data = JSON.parse(res.data)
this.uploadShow = false
if (data.code == 1) {
if (type == 1) {
let obj = {
id:data.data.id,
file_path:data.data.url
}
this.imgList.push(obj)
} else {
let fileObj = {
id:data.data.id,
file_path:data.data.url
}
file = Object.assign({}, file, fileObj)
this.fileList.push(file)
}
} else {
uni.showToast({
title: '上传失败',
icon: 'none'
})
}
},
fail: (err) => {
console.log(err)
}
})
},
//
delImg(index) {
this.imgList.splice(index, 1)
},
//
moreClick() {
uni.navigateTo({
url: '/pagesA/crm/selectMember/selectMember'
})
},
//
saveFollow() {
let {
id,
customer_id, //id
consume_time, //
consume_type, //
money, //
remark, //
imgList,
remindPeople, //
} = this
if (!consume_time) {
uni.showToast({
title: '请选择消费日期',
icon: 'none'
})
return
}
if (!consume_type) {
uni.showToast({
title: '请选择消费方式',
icon: 'none'
})
return
}
if (!money) {
uni.showToast({
title: '请填写消费金额',
icon: 'none'
})
return
}
if ((!remindPeople || remindPeople.length == 0) && this.approvalPro.status == 0) {
uni.showToast({
title: '请选择流程审批人',
icon: 'none'
})
return
}
let arr = []
imgList.forEach(ele => {
arr.push(ele.id)
})
let file_ids = arr.join(',')
//
let remarr = []
remindPeople.forEach(ele => {
remarr.push(ele.id)
})
let flow_staff_id = remarr.join(',')
let params = {
id,
customer_id, //id
consume_time, //
consume_type, //
money, //
remark, //
file_ids,
flow_staff_ids:this.approvalPro.status == 0 ? remarr.join(',') : ''
}
netEditCost(params).then(res => {
uni.showToast({
title: res.msg,
icon: 'none'
})
setTimeout(() => {
uni.navigateBack({
delta: 1
})
}, 2000)
})
}
}
}
</script>
<style lang="scss">
.new_fllow {
margin-top: 40rpx;
font-size: 28rpx;
.fllow_form {
display: flex;
justify-content: space-between;
background-color: #fff;
border-bottom: 1rpx solid #EAEAEA;
padding: 24rpx;
.form_right {
display: flex;
color: #999;
image {
width: 40rpx;
height: 40rpx;
margin: 28rpx 5rpx 0 0;
}
}
text {
color: #f00;
margin-left: 10rpx;
}
.form_input {
input {
height: 92%;
// line-height: 100rpx;
text-align: right;
margin-right: 10rpx;
}
}
.fllow_button {
margin-top: 15rpx;
}
}
.imglist {
padding: 24rpx 34rpx;
background: #fff;
border-bottom: 1rpx solid #EAEAEA;
display: flex;
justify-content: flex-start;
align-items: center;
flex-wrap: wrap;
.imgbox {
width: 160rpx;
height: 160rpx;
margin-right: 14rpx;
position: relative;
margin-bottom: 24rpx;
border: 1rpx solid #EAEAEA;
.delimg {
width: 32rpx;
height: 32rpx;
border-radius: 50%;
position: absolute;
right: -16rpx;
top: -16rpx;
background: rgba(0, 0, 0, 0.5);
z-index: 2;
}
.selfimg {
width: 160rpx;
height: 160rpx;
}
}
}
.fllow_area {
background-color: #fff;
// padding: 0 70rpx;
margin-bottom: 30rpx;
padding-bottom: 30rpx;
color: #999;
.area_head {
padding:24rpx;
font-size: 32rpx;
text {
color: #f00;
}
}
textarea {
width: 80%;
height: 300rpx;
padding: 30rpx;
background: #f8f8f8;
margin: 0 auto;
}
}
.follow_task {
height: 80rpx;
line-height: 80rpx;
}
}
.imglist {
padding: 24rpx 34rpx;
background: #fff;
border-bottom: 1rpx solid #EAEAEA;
display: flex;
justify-content: flex-start;
align-items: center;
flex-wrap: wrap;
.imgbox {
width: 160rpx;
height: 160rpx;
margin-right: 14rpx;
position: relative;
margin-bottom: 24rpx;
border: 1rpx solid #EAEAEA;
.delimg {
width: 32rpx;
height: 32rpx;
border-radius: 50%;
position: absolute;
right: -16rpx;
top: -16rpx;
background: rgba(0, 0, 0, 0.5);
z-index: 2;
}
.selfimg {
width: 160rpx;
height: 160rpx;
}
}
}
#btn {
width: 500rpx;
height: 88rpx;
background: $uni-text-color;
border-radius: 29rpx;
font-size: 34rpx;
color: #fff;
line-height: 88rpx;
}
</style>

View File

@ -0,0 +1,665 @@
<template>
<view class="group_company">
<view class="group_head">
<view class="client">
{{(info.name) ? info.name : '--'}}
</view>
<view class="nickname" v-if="info.contacts">
{{(info.contacts) ? info.contacts.name : '--'}}<text>
|</text>{{(info.contacts) ? info.contacts.mobile : '--'}}
</view>
<view class="state" v-if="info.follow">
{{info.follow ? info.follow : '--'}}<text style="padding: 0 30rpx;"> |</text>
<u-rate :count="5" v-model="info.level" disabled active-color="#FFD049" inactive-color="#b2b2b2" :size="34" :gutter="10"></u-rate>
</view>
<view class="time" v-if="info.next_time">
下次跟进时间{{info.next_time ? info.next_time : '--'}}
</view>
<view class="site" v-if="info.address">
{{(info.address) ? info.address : '--'}}
</view>
<view class="roll">
<scroll-view scroll-x="true" class="scrollView" lower-threshold="50" enable-flex>
<view class="scrolllist">
<view class="scrollView_item" @click="toTeam">
<view class="scroll_top">
{{info.teamCount?info.teamCount:0}}
</view>
<view class="scroll_foot">
团队
</view>
</view>
<view class="scrollView_item" @click="toBusiness">
<view class="scroll_top">
{{info.bussinessCount?info.bussinessCount:0}}
</view>
<view class="scroll_foot">
商机
</view>
</view>
<view class="scrollView_item" @click="contact(info.id)">
<view class="scroll_top">
{{info.contactsCount?info.contactsCount:0}}
</view>
<view class="scroll_foot">
联系人
</view>
</view>
<view class="scrollView_item" @click="subord(info.id)">
<view class="scroll_top">
{{info.companyCount?info.companyCount:0}}
</view>
<view class="scroll_foot">
子公司
</view>
</view>
<view class="scrollView_item" @click="signList(info.id)">
<view class="scroll_top">
{{info.signCount?info.signCount:0}}
</view>
<view class="scroll_foot">
签到记录
</view>
</view>
<view class="scrollView_item" @click="Contract(info.id)">
<view class="scroll_top">
{{info.contractCount?info.contractCount:0}}
</view>
<view class="scroll_foot">
合同
</view>
</view>
<view class="scrollView_item" @click="cost(info.id)">
<view class="scroll_top">
{{info.consumeCount?info.consumeCount:0}}
</view>
<view class="scroll_foot">
费用
</view>
</view>
<view class="scrollView_item" @click="payment(info.id)">
<view class="scroll_top">
{{info.receivalbleCount?info.receivalbleCount:0}}
</view>
<view class="scroll_foot">
回款记录
</view>
</view>
<view class="scrollView_item" @click="accessory(info.id)">
<view class="scroll_top">
{{info.fileCount?info.fileCount:0}}
</view>
<view class="scroll_foot">
附件
</view>
</view>
<view class="scrollView_item" @click="operation(info.id)">
<view class="scroll_top">
{{info.operateCount?info.operateCount:0}}
</view>
<view class="scroll_foot">
操作记录
</view>
</view>
</view>
</scroll-view>
</view>
</view>
<!-- 标签栏 -->
<view class="group_tab">
<u-tabs name="cate_name" :list="list" :is-scroll="false" active-color="#008EFF" :current="current"
@change="change"></u-tabs>
<view class="processing_title" v-if="current == 0">
<customer-dynamic v-if="info && info.id" :isSeas="Number(type)" :kehuid="info.id" :type="1"></customer-dynamic>
</view>
<view class="processing_title" v-if="current == 1">
<info-detail v-if="info && info.id" :info="info"></info-detail>
</view>
</view>
<view style="height:100rpx"></view>
<!-- 底部导航栏 -->
<view class="bottom_nav" v-if="type == 1 && info.operation == 'update'">
<view class="bottom_item" @click="followClick">
<image :src="BASE_IMG_URL+'tj.png'" class="botimg"></image>
<view>跟进</view>
</view>
<view class="bottom_item" @click="telClick">
<image :src="BASE_IMG_URL+'dh.png'" class="botimg"></image>
<view>拨打电话</view>
</view>
<view class="bottom_item" @click="moreClick">
<image :src="BASE_IMG_URL+'morebtn.png'" class="botimg"></image>
<view>更多操作</view>
</view>
</view>
<u-popup v-model="show" mode="bottom" border-radius="20">
<view class="pull_head">更多操作</view>
<view class="pull_con">
<view class="pull_item" @click="transferClueClick(info.id)">
<view style="padding: 5rpx 12rpx;border: 1px solid #ededed;">转移客户</view>
</view>
<view class="pull_item" @click="removeSeas">
<view style="padding: 5rpx 12rpx;border: 1px solid #ededed;">移入公海</view>
</view>
<view class="pull_item" v-if="info && info.is_collect == 0" @click="Tofocus">
<view style="padding: 5rpx 12rpx;border: 1px solid #ededed;">重点关注</view>
</view>
<view class="pull_item" v-if="info && info.is_collect == 1" @click="ToRemovefocus">
<view style="padding: 5rpx 12rpx;border: 1px solid #ededed;">取消关注</view>
</view>
<view class="pull_item" @click="mapLocation">
<view style="padding: 5rpx 12rpx;border: 1px solid #ededed;">地图定位</view>
</view>
<view class="pull_item" @click="editClueClick(info.id)">
<view style="padding: 5rpx 12rpx;border: 1px solid #ededed;">编辑客户</view>
</view>
<view class="pull_item" @click="toSigntrip(info.id)">
<view style="padding: 5rpx 12rpx;border: 1px solid #ededed;">出差签到</view>
</view>
</view>
</u-popup>
<u-action-sheet
:list="telActions"
v-model="telShow"
:cancel-btn = "true"
@click="selectPhone"
></u-action-sheet>
</view>
</template>
<script>
import customerDynamic from 'components/content/customerDynamic/customerDynamic.vue';
import infoDetail from 'components/content/infoDetail/infoDetail.vue';
import {
moreCompany
} from 'components/content/data/data.js';
import {
pageJumps
} from "./group_page_jumps.js";
import {
BASE_IMG_URL
} from '@/util/api.js'
import {
netKehuDetail,
netRemoveSeas,
netReceiveKehu,
netKeyCollect,
netRemoveColect,
} from '@/api/kehu.js'
import {
netRelationBusiness
} from '@/api/index.js'
export default {
mixins: [pageJumps],
data() {
return {
BASE_IMG_URL: BASE_IMG_URL,
show: false,
taskShow: true,
statusShow: false,
// overShow: false,
moreCompany: [],
telShow: false,
telActions: [],
telname: '',
id: '', //id
info: {},
type: 1, //1 2
customer_id: '',
relation_id: '',
current: 0,
list: [{
name: '跟进记录',
status: 0
},
{
name: '基本信息',
status: 1
},
],
}
},
onLoad(options) {
this.id = options.id
this.moreCompany = moreCompany
this.type = options.type
},
onShow() {
this.getInfo()
},
components: {
customerDynamic,
infoDetail,
},
methods: {
//
followClick() {
uni.navigateTo({
url: '/pagesA/crm/customerManagement/newFllow/newFllow?id='+this.id+'&type=1'
})
},
change(index) {
this.current = index;
},
tabs_change(e) {
this.current = e;
this.mescroll.resetUpScroll();
},
//
accessory(id) {
uni.navigateTo({
url: '/pages/index/groupCompany/attachment/attachment?id=' + id + '&types=2' + '&type=' + this.type
})
},
//
lookDetail(item) {
if (item.types.indexOf('image') != -1) {
uni.previewImage({
urls: [item.file_path]
})
} else {
uni.downloadFile({
url: item.file_path,
success: (res) => {
uni.openDocument({
filePath: res.tempFilePath,
success: (res) => console.log('成功打开文档')
})
},
fail: (err) => {
console.log(err, 'shibai')
}
})
}
},
//
addContract(id) {
uni.navigateTo({
url: '/pagesA/crm/contract/contract?id=' + id
})
},
//
toTeam() {
uni.navigateTo({
url:'/pagesA/circulate/index?id='+this.info.id
})
},
//
contact(id) {
uni.navigateTo({
url: '/pagesA/crm/linkman/linkman?id=' + this.id + '&type=' + this.type
})
},
//
subord(id) {
uni.navigateTo({
url: '/pages/index/groupCompany/subsidiary/subsidiary?id=' + id + '&type=' + this.type
})
},
//
signList(id) {
uni.navigateTo({
url: '/pagesA/signin/record/record?id=' + id + '&type=' + this.type
})
},
//
Contract(id) {
uni.navigateTo({
url: '/pages/index/groupCompany/pact/pact?id=' + id + '&type=' + this.type
})
},
//
cost(id) {
uni.navigateTo({
url: '/pages/index/groupCompany/chargelist/chargelist?id=' + id + '&type=' + this.type
})
},
//
payment(id) {
uni.navigateTo({
url: '/pages/index/groupCompany/payment/payment?id=' + id + '&type=' + this.type
})
},
//
operation(id) {
uni.navigateTo({
url: '/pagesB/contract/operation?id=' + id + '&relation_type=1'
})
},
//
getInfo() {
this.info = {}
netKehuDetail({
id: this.id
}).then(res => {
this.info = res.data
uni.setNavigationBarTitle({
title: res.data.name
})
if (res.data.contacts) {
this.telname = res.data.contacts.name
this.telActions = [
{
text:res.data.contacts.name+res.data.contacts.mobile,
color:'#008EFF',
mobile:res.data.contacts.mobile
}
]
}
})
},
moreClick() {
this.show = true
},
//
removeSeas() {
this.show = false
uni.showModal({
title: '提示',
content: '确认要将当前客户移到公海吗?',
success: (res) => {
if (res.confirm) {
let params = {
id: this.info.id
}
netRemoveSeas(params).then(res => {
uni.showToast({
title: res.msg,
icon: 'none'
})
setTimeout(() => {
uni.setStorageSync('isJamp',true)
uni.navigateBack({
delta: 1
})
}, 1000)
})
}
}
})
},
//
Tofocus() {
let params = {
customer_id: this.info.id
}
netKeyCollect(params).then(res => {
uni.showToast({
title: res.msg,
icon: 'none'
})
this.show = false
setTimeout(() => {
this.getInfo()
}, 1000)
})
},
//
ToRemovefocus() {
let params = {
customer_id: this.info.id
}
netRemoveColect(params).then(res => {
uni.showToast({
title: res.msg,
icon: 'none'
})
this.show = false
setTimeout(() => {
this.getInfo()
}, 1000)
})
},
//
selectPhone(e) {
// #ifdef MP-ALIPAY
dd.showCallMenu({
phoneNumber: this.telActions[e].mobile,
code: '+86'
})
// #endif
// #ifndef APP-PLUS || MP-ALIPAY
uni.makePhoneCall({
phoneNumber: this.telActions[e].mobile
})
// #endif
// #ifdef APP-PLUS
plus.device.dial(this.telActions[e].mobile, true);
// #endif
},
//
mapLocation() {
uni.openLocation({
latitude: Number(this.info.lat),
longitude: Number(this.info.lng),
name: this.info.address,
address: this.info.address_detail,
success: (res) => {
console.log(res, this.info.lat, this.info.lng)
},
fail: (err) => {
console.log(err)
}
})
},
//
taskClick() {
this.taskShow = true;
this.show = false;
},
//
onCancel() {
this.taskShow = false;
this.statusShow = false;
this.telShow = false;
this.show = false;
},
//
statusClick() {
this.statusShow = true;
this.show = false;
},
//
telClick() {
this.telShow = true;
this.show = false;
},
// 线
getCluesClick(id) {
this.show = false;
uni.showModal({
title: '是否确定领取客户',
content: '领取后长时间未跟进,客户将自动转为公共客户',
cancelColor: "#9abcfb",
confirmColor: "#9abcfb",
success: function(ress) {
if (ress.confirm) {
netReceiveKehu({
customer_id: id
}).then(res => {
uni.showToast({
title: res.msg,
icon: 'none'
})
setTimeout(() => {
uni.navigateTo({
url: '/pages/index/groupCompany/groupCompany?id=' +
res.data.id
})
}, 1000)
})
} else if (ress.cancel) {
console.log('用户点击取消');
}
}
})
},
// 线
deleteClueClick() {
uni.showModal({
title: '删除线索',
content: '确定删除该条记录吗?',
cancelColor: "#9abcfb",
confirmColor: "#9abcfb",
success: function(res) {
if (res.confirm) {
console.log('用户点击确定');
} else if (res.cancel) {
console.log('用户点击取消');
}
}
})
},
//
onClickHide() {
this.overShow = false;
},
//
toSigntrip(id) {
uni.navigateTo({
url: '/pagesA/signin/busSign?customerid=' + id
})
},
//
toBusiness() {
uni.navigateTo({
url:'/pagesA/business/customer_business?id='+this.id
})
}
}
}
</script>
<style lang="scss">
.pull_head {
font-size: 34rpx;
color: #999;
padding: 30rpx 0;
text-align: center;
}
::-webkit-scrollbar {
width: 0;
height: 0;
color: transparent;
}
.group_head {
padding: 20rpx 42rpx;
background-color: $uni-text-color;
text-align: left;
color: #fff;
font-size: 30rpx;
.client {
font-size: 36rpx;
margin-bottom: 20rpx;
}
.nickname {
margin-bottom: 20rpx;
text {
padding: 0 30rpx;
}
}
.state {
margin-bottom: 20rpx;
text {
}
}
.time {
margin-bottom: 20rpx;
text {
padding: 0 30rpx;
}
}
.site {
margin-bottom: 20rpx;
}
.principal {
margin-bottom: 20rpx;
}
}
.group_tab {
margin: 20rpx 0;
}
.bottom_nav {
position: fixed;
bottom: 0;
left: 0;
right: 0;
padding: 20rpx 0;
background-color: #fff;
text-align: center;
color: #999;
z-index: 2;
display: flex;
justify-content: space-around;
align-items: center;
border-top:1rpx solid #f5f5f5;
.bottom_item{
font-size:24rpx;
.botimg{
width:40rpx;
height:40rpx;
}
}
}
.pull_con {
padding: 20rpx;
display: flex;
flex-wrap: wrap;
justify-content: flex-start;
text-align: center;
color: #999;
box-sizing: border-box;
margin-bottom:calc(env(safe-area-inset-bottom) / 2);
.pull_item {
width: 22%;
margin-bottom: 90rpx;
margin-right: 20rpx;
:first-child {
padding-bottom: 10rpx;
}
:last-child {
padding-bottom: 50rpx;
}
}
}
.scrollView {
margin:25rpx 0;
.scrolllist{
display: flex;
justify-content: flex-start;
align-items: center;
.scrollView_item {
flex-shrink: 0;
width:145rpx;
padding:15rpx 0;
background: #fff;
border-radius: 20rpx;
text-align: center;
margin-right: 15rpx;
.scroll_top{
color: $uni-text-color;
font-size: 32rpx;
font-weight: bold;
}
.scroll_foot{
font-size: 26rpx;
color: #333;
}
}
}
}
</style>

View File

@ -0,0 +1,50 @@
export const pageJumps = {
methods:{
// 写新跟进
followClick(id,type) {
this.show = false
uni.navigateTo({
url: '/pagesA/crm/customerManagement/newFllow/newFllow?id='+id+'&type='+type
})
},
//新增联系人
addLianxiren(id) {
uni.navigateTo({
url:'/pagesA/crm/linkman/newLinkman/newLinkman?id='+id
})
},
// 转为客户
toTheCustomClick() {
},
// more中的点击事件
// 写新跟进
pullFollowClick(id,type) {
uni.navigateTo({
url: '/pagesA/crm/customerManagement/newFllow/newFllow?id='+id+'&type='+type
})
this.show = false;
},
// 转移客户
transferClueClick(id) {
uni.navigateTo({
url: '/pages/index/groupCompany/tranferClue/tranferClue?id='+id
})
this.show = false;
},
// 地图定位
mapLocationClick(id) {
uni.navigateTo({
url: '/pages/index/locationMap/locationMap?id='+id
})
this.show = false;
},
// 编辑客户
editClueClick(id) {
uni.navigateTo({
url: '/pagesA/crm/createCustomer/editCustomer?id='+id
})
this.show = false;
},
}
}

View File

@ -0,0 +1,220 @@
<template>
<view class="cust_detail">
<view class="cust_item">
<view class="record_item" v-for="(item,index) in operation_lists" :key="index">
<image
:src="item.staff.img ? item.staff.img : BASE_IMG_URL+'img/headImg.png'"
mode="scaleToFill"
style="width: 80rpx;height: 80rpx;border-radius: 50%;flex-shrink: 0;"
></image>
<view class="record_info">
<view class="info_top">
<view>{{item.staff.name}}</view>
<view class="record_time">
{{item.createtime}}
</view>
</view>
<view>{{item.content}}</view>
</view>
</view>
</view>
</view>
</template>
<script>
import {netOperationList} from '@/api/kehu.js'
import {BASE_IMG_URL} from '@/util/api.js'
export default {
props: {
kehuid: {
type: Number,
default: null
},
},
data() {
return {
BASE_IMG_URL: BASE_IMG_URL,
operation_lists: [
//
{
staff:[{name:'name'}],
createtime:'createtime',
content:'content'
}
], //
kehuid:'',
type:Number
}
},
onLoad(options){
this.type = options.type,
this.kehuid = options.id
},
onShow(){
console.log(this.kehuid, '9-25')
//
this.operationList()
},
created() {
},
methods: {
//
operationList() {
let params = {
relation_type: this.type,
relation_id: this.kehuid
}
netOperationList(params).then(res => {
this.operation_list = res.data
})
},
}
}
</script>
<style lang="scss" scoped>
.cust_detail {
.cust_item {
margin-bottom: 20rpx;
.cust_item_head {
background: #fff;
display: flex;
justify-content: space-between;
line-height: 100rpx;
border-bottom: 1rpx solid #EAEAEA;
padding: 0 24rpx;
.head_info {
display: flex;
align-items: center;
.icon--task {
margin-right: 10rpx;
}
}
.head_new {
display: flex;
align-items: center;
color: #1c9bfc;
.icon-clock {
margin-right: 10rpx;
}
}
}
.lxr_con_list {
// padding: 20rpx;
background: #fff;
// border-bottom: 1rpx solid #C0C0C0;
// margin-bottom: 20rpx;
&:last-child {
border-bottom: none;
}
.name {
font-size: 28rpx;
color: #333333;
margin-top: 15rpx;
}
.info {
font-size: 24rpx;
color: #999999;
margin: 10rpx 0;
}
.proce_li {
display: flex;
justify-content: space-between;
align-items: center;
.pro_li_left {
display: flex;
justify-content: flex-start;
align-items: center;
.protext {
font-size: 24rpx;
color: #999999;
}
.probox {
width: 120rpx;
height: 15rpx;
border-radius: 8rpx;
background: #C0C0C0;
margin: 0 15rpx;
.proin {
width: 20%;
height: 15rpx;
border-radius: 8rpx;
background: #ff7800;
}
}
.pronum {
font-size: 24rpx;
color: #999999;
}
}
.pro_li_right {
color: #ec7f51;
font-size: 28rpx;
font-weight: 500;
}
}
.con_status {
font-size: 24rpx;
color: $uni-text-color;
margin-top: 10rpx;
}
}
.operation_record {
padding: 20rpx 30rpx;
background: #fff;
.record_item {
display: flex;
justify-content: space-between;
padding-bottom: 1rpx solid #EAEAEA;
&:last-child {
border-bottom: none;
}
image {
width: 80rpx;
height: 80rpx;
border-radius: 50%;
flex-shrink: 0;
}
.record_info {
flex: 1;
margin-left: 25rpx;
line-height: 40rpx;
font-size: 28rpx;
.info_top {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 10rpx;
font-size: 30rpx;
color: #999;
}
.shenhetext {
font-size: 26rpx;
color: #666;
line-height: 34rpx;
}
}
.record_line {
position: absolute;
top: -102rpx;
left: -26rpx;
height: 105rpx;
border-left: 4rpx dotted #dedede;
}
}
}
}
}
</style>

View File

@ -0,0 +1,367 @@
<template>
<view>
<view class="lxr_con_list" v-for="(item,index) in contract_list" :key="index"
@click="toContractDetail(item.id)">
<view class="name">{{item.name}}</view>
<view class="info">已回款 &yen;{{item.receivables.repayment_money}}</view>
<view class="info">待回款 &yen;{{item.receivables.be_money}}</view>
<view class="proce_li">
<view class="pro_li_left">
<view class="protext">回款进度</view>
<view class="probox">
<view class="proin"
:style="{width:(item.receivables.ratio >= 100 ? 100 : item.receivables.ratio) +'%'}">
</view>
</view>
<view class="pronum">{{item.receivables.ratio}}%</view>
</view>
<view class="pro_li_right">&yen;{{item.receivables.be_money}}</view>
</view>
<view class="info">签约时间{{item.order_date}}</view>
<view class="con_status" v-if="item.check_status == 0">
<span>待审核</span>
</view>
<view class="con_status" v-if="item.check_status == 1">
<span>审核中</span>
</view>
<view class="con_status pass" v-if="item.check_status == 2">
<span>审核通过</span>
</view>
<view class="con_status nopass" v-if="item.check_status == 3">
<span>审核未通过</span>
</view>
<view class="con_status nopass" v-if="item.check_status == 4">
<span>已撤回</span>
</view>
</view>
<view style="height:200rpx"></view>
<u-empty v-if="contract_list.length == 0" text="暂无更多"></u-empty>
<view class="icon_creat" v-if="type == 1" @click="addContract">
<image :src="BASE_IMG_URL+'1.png'" mode="scaleToFill"></image>
</view>
</view>
</template>
<script>
import {
netContractList
} from '@/api/kehu.js'
import {
BASE_IMG_URL
} from '@/util/api.js'
export default {
data() {
return {
BASE_IMG_URL:BASE_IMG_URL,
contract_list: [],
page: 1,
limit: 10,
totalPage: 1,
type:1, //1 2
// id:'',
customer_id:''
}
},
onLoad(options) {
this.id = options.id
this.type = options.type
},
onShow() {
this.contract_list = []
this.page = 1
this.getList()
},
onReachBottom() {
if (this.page >= this.totalPage) {
return
}
this.page++
this.getList()
},
methods: {
//
addContract() {
uni.navigateTo({
url: '/pagesA/crm/contract/contract?id='+this.id
})
},
getList() {
netContractList({customer_id:this.id}).then(res => {
this.contract_list = res.data
})
},
//
toContractDetail(id) {
uni.navigateTo({
url: '/pagesB/contract/contractDetail?id=' + id
})
},
}
}
</script>
<style lang="scss" scoped>
.active {
text-align: center;
border: none;
background:$uni-text-color;
padding: 5rpx 10rpx ;
border-radius: 10rpx;
color: #FFFFFF;
}
.list-box {
//     width: 100%;
overflow: hidden;
white-space: nowrap;
}
.list-box {
//     width: 100%;
overflow: hidden;
white-space: nowrap;
}
.list-item {
border: 1px solid #999;
// color: #999;
padding: 5rpx 10rpx ;border-radius: 10rpx;
}
.valueactive {
color: #666;
}
.select_warp {
z-index: 9;
}
.searchbox {
display: flex;
justify-content: flex-end;
margin: 20rpx 0;
background: #ffffff;
height: 100rpx;
.searchtext {
display: flex;
justify-content: center;
align-items: center;
font-size: 30rpx;
color: #999;
margin-right: 55rpx;
}
}
.warpbox {
position: fixed;
width: 750rpx;
left: 0;
top: 0rpx;
bottom: 0;
z-index: 2;
background: rgba(0, 0, 0, 0.7);
.screen_content {
width: 702rpx;
z-index: 2;
border-top: 1rpx solid #CCCCCC;
background-color: #fff;
padding: 24rpx;
.fir_li {
margin-bottom: 20rpx;
.li_label {
font-size: 28rpx;
color: $uni-text-color;
margin-top: 30rpx;
margin-bottom: 20rpx;
}
.classify {
// background: red;
display: flex;
justify-content: space-around;
.classify_flex {
padding: 5rpx 16rpx;
color: #999;
font-size: 30rpx;
border: 1px solid #999;
border-radius: 10rpx;
}
.c_f {
background: $uni-text-color !important;
color: #fff;
}
}
.li_box {
// width:700rpx;
height: 60rpx;
padding: 0 35rpx;
line-height: 60rpx;
display: flex;
justify-content: space-around;
color: #999;
}
.form_right {
// display: flex;
color: #999;
text-align: center;
// justify-content: space-between;
image {
width: 40rpx;
height: 40rpx;
margin: 28rpx 5rpx 0 0;
}
}
}
}
.button_bottom {
display: flex;
width: 100%;
height: 90rpx;
background-color: #fff;
line-height: 90rpx;
text-align: center;
font-size: 32rpx;
justify-content: space-around;
padding-bottom: 100rpx;
:first-child {
color: #999;
border: 1rpx solid #999;
width: 260rpx;
height: 88rpx;
line-height: 88rpx;
border-radius: 30rpx;
}
:last-child {
background-color: $uni-text-color;
color: #fff;
width: 260rpx;
height: 88rpx;
line-height: 88rpx;
border-radius: 30rpx;
}
}
}
.lxr_con_list {
padding: 20rpx 0;
margin-bottom: 20rpx;
background: #fff;
margin-top: 20rpx;
&:last-child {
border-bottom: none;
}
.name {
font-size: 34rpx;
color: #333333;
// margin-top: 15rpx;
font-weight: 500;
border-bottom: 1rpx solid #ededed;
padding: 0 0 30rpx 63rpx;
}
.info {
font-size: 32rpx;
color: #999999;
margin: 10rpx 0;
padding-left: 63rpx;
}
.proce_li {
display: flex;
justify-content: space-between;
align-items: center;
padding-left: 63rpx;
margin: 10rpx 0;
.pro_li_left {
display: flex;
justify-content: flex-start;
align-items: center;
.protext {
font-size: 32rpx;
color: #999999;
}
.probox {
width: 120rpx;
height: 30rpx;
border-radius: 15rpx;
background: #C0C0C0;
margin: 0 15rpx;
.proin {
width: 20%;
height: 30rpx;
border-radius: 15rpx;
background: $uni-text-color;
}
}
.pronum {
font-size: 24rpx;
color: #999999;
}
}
.pro_li_right {
color: $uni-text-color;
font-size: 40rpx;
font-weight: 500;
margin-right: 28rpx;
}
}
.con_status {
width: 130rpx;
height: 36rpx;
text-align: center;
line-height: 36rpx;
background: $uni-text-color-opcity;
margin-top: 30rpx;
margin-left: 63rpx;
span {
font-size: 26rpx;
color: $uni-text-color;
}
}
.nopass {
color: #ec7f51;
}
.pass {
color: #22A7F6;
}
}
#btn{
width: 500rpx;
height: 88rpx;
background: $uni-text-color;
border-radius: 29rpx;
font-size: 34rpx;
color: #fff;
line-height: 88rpx;
}
</style>

View File

@ -0,0 +1,160 @@
<template>
<view class="cust_detail">
<view class="cust_item_con" v-for="(item,index) in payment_list" :key="index"
@click="toPaymentDetail(item)">
<view class="con_info">
<view class="head">{{item.number}}</view>
<view class="con_money">
<view class="c_m_left">
回款金额
</view>
<view class="c_m_right">
&yen; {{item.money}}
</view>
</view>
<view class="con_time">回款日期{{item.return_time}}</view>
<view class="recostatus" v-if="item.check_status == 0">
<span>待审核</span>
</view>
<view class="recostatus" v-if="item.check_status == 1">
<span>审核中</span>
</view>
<view class="recostatus" v-if="item.check_status == 2">
<span>审核通过</span>
</view>
<view class="recostatus" v-if="item.check_status == 3" >
<span>审核未通过</span>
</view>
<view class="recostatus" v-if="item.check_status == 4" >
<span>已撤回</span>
</view>
</view>
</view>
<view style="height: 200rpx;"></view>
<u-empty v-if="payment_list.length == 0" text="暂无更多"></u-empty>
<view class="icon_creat" v-if="type == 1" @click="toAddPayment">
<image :src="BASE_IMG_URL+'1.png'" mode="scaleToFill"></image>
</view>
</view>
</template>
<script>
import {
netPaymentList
} from '@/api/kehu.js'
import {
netGetSignList
} from '@/api/index.js'
import {
BASE_IMG_URL
} from '@/util/api.js'
export default {
data() {
return {
BASE_IMG_URL: BASE_IMG_URL,
payment_list: [], //
kehuid:'',
type:1,
isSeas:1,
}
},
onLoad(options){
this.kehuid = options.id,
this.limit = options.limit
this.type = options.type
},
onShow() {
//
this.getPaymentList()
},
created() {
},
methods: {
//
getPaymentList() {
let params = {
customer_id: this.kehuid,
limit: 1000
}
netPaymentList(params).then(res => {
this.payment_list = res.data.data
})
console.log(this.payment_list, '回款记录')
},
//
toPaymentDetail(item) {
uni.navigateTo({
url: '/pagesB/contract/paymentDetail?id=' + item.id
})
},
//
toAddPayment() {
uni.navigateTo({
url: '/pagesB/contract/addContractPayment?kehuid=' + this.kehuid
})
},
}
}
</script>
<style lang="scss" scoped>
.cust_detail {
.cust_item_con {
background: #fff;
margin-top: 20rpx;
.con_info {
.head {
border-bottom: 1px solid #ededed;
font-size: 34rpx;
color: #333;
padding: 30rpx 60rpx;
}
.con_money {
display: flex;
justify-content: space-between;
.c_m_left {
padding: 35rpx 60rpx;
font-size: 32rpx;
color: #999;
}
.c_m_right {
padding: 30rpx;
font-size: 32rpx;
color: $uni-text-color;
font-weight: 500;
}
}
.con_time {
padding: 0 35rpx 30rpx 60rpx;
font-size: 32rpx;
color: #999;
}
.recostatus{
padding: 0 0 30rpx 60rpx;
span{
font-size: 26rpx;
color:$uni-text-color;
padding: 5rpx 12rpx;
background: $uni-text-color-opcity;
border-radius: 5rpx;
}
}
}
}
#btn {
font-size: 26rpx;
color: #fff;
text-align: center;
line-height: 88rpx;
width: 500rpx;
height: 88rpx;
background: $uni-text-color;
border-radius: 29rpx;
margin: 30rpx auto;
}
}
</style>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,177 @@
<template>
<view class="cust_detail">
<view class="cust_item">
<view class="cline_li" v-for="(item,index) in subord_list" :key="index">
<view class="clineInfo" @click="toDetail(item)">
<view class="info_head">
<view>{{item.name}}</view>
</view>
<view class="info_main">
<view class="main_left">
<view class="left_followUp">下次跟进时间{{item.next_time}}</view>
<view class="left_star">
<view style="float: left;">客户星级</view>
<view>
<u-rate :count="5" v-model="item.level" disabled active-color="#FFD049" inactive-color="#b2b2b2" :size="30" :gutter="10"></u-rate>
</view>
</view>
<view class="left_foot">
<view class="l_box">
<span>{{item.follow}}</span>
</view>
</view>
</view>
<view class="main_right">
<image :src="item.owner_staff.img ? item.owner_staff.img : BASE_IMG_URL+'headImg.png'" mode="scaleToFill"></image>
<view>{{item.owner_staff.name}}</view>
</view>
</view>
</view>
</view>
</view>
<view style="height: 200rpx;"></view>
<u-empty v-if="subord_list.length == 0" text="暂无更多"></u-empty>
<view class="icon_creat" v-if="type == 1" @click="toCreatCustomer">
<image :src="BASE_IMG_URL+'1.png'" mode="scaleToFill"></image>
</view>
</view>
</template>
<script>
import {
netSubordList
} from '@/api/kehu.js'
import {
netGetSignList
} from '@/api/index.js'
import {
BASE_IMG_URL
} from '@/util/api.js'
export default {
data() {
return {
BASE_IMG_URL: BASE_IMG_URL,
subord_list: [], //
kehuid: '',
type:1, //1 2
lists:[]
}
},
onLoad(options) {
this.kehuid = options.id
this.type = options.type
},
onShow() {
//
this.getSubordlist()
},
methods: {
//
getSubordlist() {
netSubordList({
id: this.kehuid
}).then(res => {
this.subord_list = res.data
})
},
//
toCreatCustomer() {
uni.navigateTo({
url: '/pagesA/crm/createCustomer/createCustomer?id=' + this.kehuid
})
},
//
toDetail(item,type) {
uni.navigateTo({
url: '/pages/index/groupCompany/groupCompany?id=' + item.id +"&type=" + this.type
})
}
}
}
</script>
<style lang="scss" scoped>
.icon_creat {
position: fixed;
z-index: 1;
bottom: 180rpx;
right: 80rpx;
image {
width: 80rpx;
height: 80rpx;
border-radius: 50%;
}
}
.cust_detail{
.cust_item{
.cline_li{
margin-top: 20rpx;
background: #fff;
.clineInfo{
.info_head{
font-size: 34rpx;
color: #333;
padding: 30rpx 50rpx;
}
.info_main{
display: flex;
justify-content: space-between;
margin-left: 50rpx;
margin-right: 60rpx;
.main_left{
padding-bottom: 20rpx;
.left_followUp{
font-size: 30rpx;
color: #666;
margin-bottom: 30rpx;
}
.left_star{
}
.left_foot {
padding-bottom: 20rpx;
margin-top: 20rpx;
.l_box {
margin-right: 35rpx;
float: left;
span {
background: $uni-text-color-opcity;
padding: 5rpx 12rpx;
font-size: 26rpx;
color: $uni-text-color;
border-radius: 5rpx;
}
}
}
}
.main_right{
text-align: center;
image{
width: 100rpx;
height: 100rpx;
border-radius: 50%;
}
}
}
}
}
}
#btn {
font-size: 26rpx;
color: #fff;
text-align: center;
line-height: 88rpx;
width: 500rpx;
height: 88rpx;
background: $uni-text-color;
border-radius: 29rpx;
margin: 30rpx auto;
display: flex;
bottom: 20rpx;
}
}
</style>

View File

@ -0,0 +1,140 @@
<template>
<view class="tranfer_clue">
<view class="fllow_form">
<view style="color: #333;font-size: 32rpx;"><text>*</text>接收对象</view>
<view class="form_right" @click="changeStaff">
<view>{{staffname ? staffname : '点击选择'}}</view>
<view class="iconfont icon-arrows_right"></view>
</view>
</view>
<view id="btn" class="btn_g bg-blue button-hover round" @click="Totrans">
保存
</view>
<!-- 选择员工 -->
<select-staff ref="staffChild" @sureStaff="sureSelect" :type="2"></select-staff>
</view>
</template>
<script>
import { netStaffList, netTransKehu } from '@/api/kehu.js'
import { BASE_IMG_URL } from '@/util/api.js'
import selectStaff from '@/components/selectStaff.vue'
export default {
components:{
selectStaff
},
data() {
return {
id:'', //id
staff_id:'', //id
staffname:'',
staffList:[],
staffIndex:null
}
},
onLoad(options) {
this.id = options.id
},
onShow() {
this.getList()
},
methods: {
getList() {
netStaffList().then(res=>{
this.staffList = res.data
})
},
changeStaff(e) {
this.$refs.staffChild.init()
},
sureSelect(obj) {
this.staff_id = obj.id
this.staffname = obj.name
},
Totrans() {
if(!this.staff_id){
uni.showToast({
title:'请选择接受对象',
icon:'none'
})
return
}
let params = {
id:this.id,
staff_id: this.staff_id
}
netTransKehu(params).then(res=>{
uni.showToast({
title:res.msg,
icon:'none'
})
setTimeout(()=>{
uni.redirectTo({
url:"/pagesA/crm/customerManagement/customerManagement"
})
},1000)
})
}
}
}
</script>
<style lang="scss" scoped>
.fllow_form {
display: flex;
justify-content: space-between;
height: 100rpx;
line-height: 100rpx;
background-color: #fff;
border-bottom: 1rpx solid #EAEAEA;
padding: 0 30rpx 0 47rpx;
margin: 0 0 30rpx;
.form_right {
display: flex;
color: #999;
image {
width: 40rpx;
height: 40rpx;
margin: 28rpx 5rpx 0 0;
}
}
text {
color: #f00;
margin-left: 10rpx;
}
}
.fllow_area {
background-color: #fff;
margin-bottom: 30rpx;
padding-bottom: 30rpx;
color: #999;
.area_head {
height: 100rpx;
line-height: 100rpx;
font-size: 32rpx;
padding: 0 70rpx;
text {
color: #f00;
}
}
textarea {
width: 80%;
height: 300rpx;
padding: 30rpx;
background: #f8f8f8;
margin: 0 auto;
}
}
#btn {
font-size: 26rpx;
color: #fff;
text-align: center;
line-height: 88rpx;
width: 500rpx;
height: 88rpx;
background: $uni-text-color;
border-radius: 29rpx;
}
</style>

835
pages/index/index.vue Normal file
View File

@ -0,0 +1,835 @@
<template>
<view class="warpbox">
<!-- #ifdef MP-WEIXIN -->
<cover-view class="headerbox" :style="{height:topHeight+'px',paddingTop:paddingHeight+'px'}">
<cover-view class="search_box" :style="{width:searchWidth+'rpx'}" @click="toSearch">
<cover-image :src="BASE_IMG_URL+'ss.png'" class="icon-search"></cover-image>
<cover-view class="self_search">输入客户线索联系人搜索</cover-view>
</cover-view>
</cover-view>
<cover-view :style="{height:topHeight+'px'}"></cover-view>
<!-- #endif -->
<!-- #ifdef MP-ALIPAY || APP-PLUS -->
<view class="headerbox_h5" style="height:150rpx">
<view class="search_box" :style="{width:searchWidth+'rpx'}" @click="toSearch">
<image :src="BASE_IMG_URL+'search.png'" class="iconsearch" mode="scaleToFill"></image>
<input type="text" disabled placeholder="输入客户、线索、联系人搜索" class="self_search">
</view>
</view>
<!-- #endif -->
<!-- #ifdef H5 -->
<view class="headerbox_h5">
<view class="search_box" :style="{width:searchWidth+'rpx'}" @click="toSearch">
<image :src="BASE_IMG_URL+'search.png'" class="iconsearch" mode="scaleToFill"></image>
<input type="text" disabled placeholder="输入客户、线索、联系人搜索" class="self_search">
</view>
</view>
<!-- #endif -->
<view class="topbox">
<view class="top_warp">
<view class="top_fir" @click="toWaterCustomer">
<image :src="BASE_IMG_URL+'index_new_1.png'" mode="scaleToFill"></image>
<view>公海客户</view>
</view>
<view class="top_fir" @click="toIndexClue">
<image :src="BASE_IMG_URL+'index_new_2.png'" mode="scaleToFill"></image>
<view>线索</view>
</view>
<view class="top_fir" @click="toIndexRecord">
<image :src="BASE_IMG_URL+'index_new_4.png'" mode="scaleToFill"></image>
<view>跟进记录</view>
</view>
<view class="top_fir" @click="toIndexContract">
<image :src="BASE_IMG_URL+'index_new_5.png'" mode="scaleToFill"></image>
<view>采购</view>
</view>
</view>
</view>
<view class="fun_warp">
<view class="fun_top">
<view class="fun_tit">常用功能</view>
</view>
<view class="fun_box">
<!-- <view class="fun_fir" @click="toBusiness">
<image :src="BASE_IMG_URL+'business.png'" mode="scaleToFill"></image>
<view>商机</view>
</view> -->
<view class="fun_fir" @click="toCluePool">
<image :src="BASE_IMG_URL+'clue_chi.png'" mode="scaleToFill"></image>
<view>线索池</view>
</view>
<view class="fun_fir" @click="approve">
<image :src="BASE_IMG_URL+'index_new_20.png'" mode="scaleToFill"></image>
<view>办公</view>
</view>
<view class="fun_fir" @click="toCostList">
<image :src="BASE_IMG_URL+'feiyong1.png'" mode="scaleToFill"></image>
<view>费用</view>
</view>
<view class="fun_fir" @click="workreport">
<image :src="BASE_IMG_URL+'index_new_12.png'" mode="scaleToFill"></image>
<view>工作报告</view>
</view>
<view class="fun_fir" @click="agendar">
<image :src="BASE_IMG_URL+'index_new_17.png'" mode="scaleToFill"></image>
<view>日程</view>
</view>
<view class="fun_fir" @click="toPayPlan">
<image :src="BASE_IMG_URL+'index_new_18.png'" mode="scaleToFill"></image>
<view>回款计划</view>
</view>
<view class="fun_fir" @click="toPayment">
<image :src="BASE_IMG_URL+'index_new_23.svg'" mode="scaleToFill"></image>
<view>回款单</view>
</view>
<view class="fun_fir" @click="achieveStatis">
<image :src="BASE_IMG_URL+'index_new_9.png'" mode="scaleToFill"></image>
<view>业绩统计</view>
</view>
<view class="fun_fir" @click="toProductList">
<image :src="BASE_IMG_URL+'index_new_11.png'" mode="scaleToFill"></image>
<view>产品</view>
</view>
<!-- #ifdef MP-WEIXIN -->
<view class="fun_fir" @click="toClock">
<image :src="BASE_IMG_URL+'daka1.png'" mode="scaleToFill"></image>
<view>打卡</view>
</view>
<!-- #endif -->
</view>
</view>
<!-- 数据简报 -->
<view class="pre-right">
<picker @change="changeType" :range="typeList" :value="typeIndex">
<view class="form_right">
<view style="margin-right:15rpx">{{typeList[typeIndex] ? typeList[typeIndex] : '点击选择'}}</view>
<image :src="BASE_IMG_URL+'newxia.png'" class="bottomimg" mode="scaleToFill"></image>
</view>
</picker>
<view class="form_right" style="margin-right:0" @click="changeDataTime">
<view style="margin-right:15rpx">{{text ? text : '点击选择'}}</view>
<image :src="BASE_IMG_URL+'newxia.png'" class="bottomimg" mode="scaleToFill"></image>
</view>
</view>
<view class="dataPre">
<view class="pre_list">
<view class="pre_title">
数据简报
</view>
</view>
<view class="pre_content">
<!-- <view class="content_item" @click="toCheckBusiness">
<view>{{info.business ? info.business : '0'}}</view>
<view>新增商机</view>
</view> -->
<view class="content_item" @click="toClue">
<view>{{info.leads ? info.leads : '0'}}</view>
<view>新增线索</view>
</view>
<view class="content_item" @click="toCustomer">
<view>{{info.customer ? info.customer : '0'}}</view>
<view>新增客户</view>
</view>
<view class="content_item" @click="toRecord">
<view>{{info.record ? info.record : '0'}}</view>
<view>新建跟进</view>
</view>
<view class="content_item" @click="toContract">
<view>{{info.contract ? info.contract : '0'}}</view>
<view>新增合同</view>
</view>
<view class="content_item" @click="toContract">
<view>{{info.contract_money ? info.contract_money :'0'}}</view>
<view>合同金额</view>
</view>
<view class="content_item" @click="toReturnedMoney">
<view>{{info.receivables ? info.receivables : '0'}}</view>
<view>回款金额</view>
</view>
<view class="content_item" @click="toCus(1)">
<view>{{info.customer_complate ? info.customer_complate : '0'}}</view>
<view>客户成交量</view>
</view>
<view class="content_item" @click="toCus(0)">
<view>{{info.customer_nocomplate ? info.customer_nocomplate : '0'}}</view>
<view>客户未成交量</view>
</view>
<!-- <view class="content_item" @click="toBus(2)">
<view>{{info.business_complate ? info.business_complate : '0'}}</view>
<view>商机成交量</view>
</view>
<view class="content_item" @click="toBus(1)">
<view>{{info.business_nocomplate ? info.business_nocomplate : '0'}}</view>
<view>商机未成交量</view>
</view>
<view class="content_item" @click="toBus(2)">
<view>{{info.business_complate_money ? info.business_complate_money : '0'}}</view>
<view>商机成交金额</view>
</view>
<view class="content_item" @click="toBus(1)">
<view>{{info.business_nocomplate_money ? info.business_nocomplate_money : '0'}}</view>
<view>商机未成交金额</view>
</view> -->
</view>
</view>
<!-- 业绩目标 -->
<view class="body_head">
<view class="conwarp">
<view class="con_title">业绩目标</view>
<picker @change="changeAchieve" :range="achieveArr" :value="achieveIndex" :range-key="'name'">
<view class="achivebox">
<view class="achitit">{{achieveArr[achieveIndex] ? achieveArr[achieveIndex].name : '点击选择'}}</view>
<image :src="BASE_IMG_URL+'newxia.png'" class="bottomimg" mode="scaleToFill"></image>
</view>
</picker>
</view>
<view class="con_head">
<view class="dountChart">
<qiun-data-charts type="arcbar" :animation="false" :opts="oneChart" canvasId="asdb" :canvas2d="true"
:chartData="chartData" />
</view>
<view class="money_show">
<view class="money_target">
<view>目标金额</view>
<view>&yen; {{target_money}}</view>
</view>
<view class=".money_target">
<view>完成金额</view>
<view>&yen; {{complete_money}}</view>
</view>
</view>
</view>
</view>
<!-- <view style="font-size:24rpx;text-align: center;color:#666;margin-top:30rpx">版权归属:山西青动时代科技有限公司</view> -->
<!-- 时间筛选 -->
<screen-pop ref="screenChild" @sureTime="sureTime"></screen-pop>
<!-- 底部导航 -->
<uniTabbar v-if="tipNumber || tipNumber==0" :tipNumber="tipNumber"></uniTabbar>
</view>
</template>
<script>
import uniTabbar from '@/components/tabbar/tabbar.vue'
import {
BASE_IMG_URL
} from '@/util/api.js'
import {
pageJumps,
statisticalPageJumps
} from "@/pagesA/crm/crm_page_jumps.js";
import {
netAgentList
} from '@/api/clues.js'
import {
getNowData
} from '@/util/weekTime.js'
import {
netGetBriefdata,
netTurnoverList
} from '@/api/kehu.js'
import {
netGetData,
netTime
} from '@/api/index.js'
import {
netMapKey
} from '@/api/login.js'
import screenPop from './screen.vue'
export default {
mixins: [pageJumps, statisticalPageJumps],
components: {
uniTabbar,
screenPop
},
data() {
return {
topHeight: 0,
paddingHeight: 0,
searchWidth: 470,
BASE_IMG_URL: BASE_IMG_URL,
tipNumber: null,
typeList: ['本人及下属', '仅本人', '仅下属'],
typeIndex: 0,
dataTime: '',
startTime:'',
endTime:'',
text:'本月',
info: {}, //
target_money: 0, //
complete_money: 0, //
percentage: 0, //
shows: false,
approvelNum: 0,
oneChart:{},
chartData: {},
//
achieveArr:[
{id:1,name:'合同'},
{id:2,name:'回款'}
],
achieveIndex:0
}
},
onLaunch() {
},
onLoad() {
//
uni.getSystemInfo({
success: (res) => {
let HeaderBar = 0
// #ifdef MP-WEIXIN
let rect = wx.getMenuButtonBoundingClientRect();
HeaderBar = rect.height + (rect.top - res.statusBarHeight) * 2 + res.statusBarHeight + 5;
this.topHeight = HeaderBar;
this.paddingHeight = rect.top
this.searchWidth = 470
// #endif
// #ifdef MP-ALIPAY || APP-PLUS
HeaderBar = res.pixelRatio * res.statusBarHeight
this.topHeight = HeaderBar
this.paddingHeight = res.statusBarHeight
this.searchWidth = 690
// #endif
// #ifdef H5
this.topHeight = 72
this.paddingHeight = 24
this.searchWidth = 690
// #endif
}
})
uni.setNavigationBarTitle({
title: uni.getStorageSync('NAME') ? uni.getStorageSync('NAME') : '青动CRM'
})
},
onShow() {
this.roleType = uni.getStorageSync('roleType')
this.rules = uni.getStorageSync('rules')
this.dataTime = getNowData().substr(0, 7)
if (uni.getStorageSync('isAuth')) {
this.getTip()
} else {
this.tipNumber = 0
}
},
methods: {
//
changeAchieve(e) {
this.achieveIndex = e.detail.value
//
this.getTarget()
},
getTime() {
netTime({times:'thismonth'}).then(res=>{
res = res.data
this.startTime = res.times[0]
this.endTime = res.times[1]
//
this.getData()
//
this.getTarget()
})
},
getOpenid() {
netMapKey().then(res => {
uni.setStorageSync('mapKey', res.data.map_key)
uni.setStorageSync('appid', res.data.appid)
})
},
getTip() {
netAgentList().then(res => {
uni.setStorageSync('token', res.data.userinfo.token)
uni.setStorageSync('roleType', res.data.userinfo.role_type)
uni.setStorageSync('rules', res.data.userinfo.rules)
this.tipNumber = res.data.total
this.approvelNum = res.data.examine.count
//
this.getTime()
//appid
this.getOpenid()
})
},
getData() {
let params = {
times: this.startTime+','+this.endTime,
type: this.typeIndex
}
netGetBriefdata(params).then(res => {
this.info = res.data
})
},
getTarget() {
let params = {
times: this.startTime+','+this.endTime,
type: this.typeIndex,
status: this.achieveArr[this.achieveIndex].id,
}
netGetData(params).then(res => {
this.complete_money = res.data.contract_moneys
this.target_money = res.data.achievement
let ratio = res.data.ratio>=100?100:res.data.ratio
let obj = {
series: [{
name: "已完成",
color: "#2979ff",
data: ratio/100
}]
};
let b = {
title: {
name: res.data.ratio+'%',
fontSize: 18,
color: "#2979ff"
},
subtitle: {
name: "完成率",
fontSize: 15,
color: "#666666"
},
extra: {
arcbar: {
type: "circle",
width: 12,
backgroundColor: "#E9E9E9",
startAngle: 1.5,
endAngle: 0.25,
gap: 2
}
}
}
this.oneChart = b
this.chartData = obj;
})
},
changeType(e) {
this.typeIndex = e.detail.value
this.getData()
this.getTarget()
},
changeDataTime(e) {
this.$refs.screenChild.init()
},
sureTime(params) {
console.log(params,'====')
if(params.text && params.start_time && params.end_time){
this.text = params.text
this.startTime = params.start_time
this.endTime = params.end_time
this.getData()
this.getTarget()
}
},
//
toProductList() {
uni.navigateTo({
url: '/pagesA/product/index'
})
},
//
toPayment() {
uni.navigateTo({
url: '/pagesA/payment/index'
})
},
//
toCostList() {
uni.navigateTo({
url: '/pagesA/cost/index'
})
},
//
toPayment() {
uni.navigateTo({
url: '/pagesA/payment/index'
})
},
//
toPayPlan() {
uni.navigateTo({
url: '/pagesA/payplan/index'
})
},
//
achieveStatis() {
uni.navigateTo({
url:'/pagesA/crm/statisticalFrom/achieveStatis'
})
},
//
toClock() {
uni.navigateTo({
url:'/pagesA/punchclock/index'
})
},
//
toBusiness() {
uni.navigateTo({
url:'/pagesA/business/index'
})
},
//
toCheckBusiness() {
uni.navigateTo({
url:'/pagesA/business/index?type='+this.typeIndex+'&stime='+this.startTime+'&etime='+this.endTime,
})
},
//
toCus(status) {
uni.navigateTo({
url:'/pagesA/crm/customerManagement/customerManagement?cusStatus='+status+'&stime='+this.startTime+'&etime='+this.endTime,
})
},
//
toBus(status) {
uni.navigateTo({
url:'/pagesA/business/index?busStatus='+status+'&stime='+this.startTime+'&etime='+this.endTime,
})
},
//线
toCluePool() {
uni.navigateTo({
url:'/pagesB/cluepool/index'
})
}
}
}
</script>
<style lang="scss" scoped>
.u-progress-info {
text-align: center;
}
.headerbox_h5 {
display: flex;
justify-content: flex-start;
align-items: center;
padding-top: var(--status-bar-height);
padding-left: 30rpx;
z-index: 9;
background: #DFF0FF;
box-sizing: border-box;
width: 100%;
height: 100rpx;
.search_box {
height: 60rpx;
border-radius: 30rpx;
background: #fff;
display: flex;
justify-content: flex-start;
align-items: center;
padding: 0 15rpx;
.iconsearch {
width: 50rpx;
height: 50rpx;
margin-right: 20rpx;
}
.self_search {
font-size: 24rpx;
color: #333;
height: 58rpx;
line-height: 58rpx;
padding: 0;
margin: 0;
width: 500rpx;
}
}
}
.headerbox {
background: #DFF0FF;
box-sizing: border-box;
width: 100%;
height: 150rpx;
position: fixed;
left: 0;
top: 0rpx;
padding-top: var(--status-bar-height);
padding-left: 30rpx;
z-index: 9;
.search_box {
height: 60rpx;
border-radius: 30rpx;
background: #fff;
display: flex;
justify-content: flex-start;
align-items: center;
padding: 0 15rpx;
.icon-search {
width: 40rpx;
height: 35rpx;
margin-right: 20rpx;
position: relative;
&::before {
content: '';
width: 0;
height: 0;
}
}
.self_search {
font-size: 24rpx;
color: #666;
height: 58rpx;
line-height: 58rpx;
padding: 0;
margin: 0;
width: 500rpx;
}
}
}
.topbox {
width: 100%;
background: linear-gradient(180deg, #DFF0FF 0%, #F1F4F6 48%, #F4F4F4 100%);
.top_warp {
width: 100%;
display: flex;
justify-content: space-between;
align-items: center;
box-sizing: border-box;
padding: 30rpx 60rpx;
text-align: center;
.top_fir {
font-size: 24rpx;
color: #333;
image {
width: 70rpx;
height: 70rpx;
margin-bottom: 10rpx;
}
}
}
}
.fun_warp {
padding: 30rpx 24rpx;
background: #fff;
width: 710rpx;
margin: 0 auto;
border-radius: 10rpx;
box-shadow: 1rpx 1rpx 10rpx rgba(0, 0, 0, 0.1);
.fun_top {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 25rpx;
.fun_tit {
font-size: 26rpx;
color: #333333;
font-weight: 700;
}
}
.fun_box {
display: flex;
justify-content: flex-start;
align-items: center;
flex-wrap: wrap;
.fun_fir {
flex-shrink: 0;
background: #fff;
border-radius: 10rpx;
text-align: center;
width: 23%;
height: 150rpx;
margin-right: 14rpx;
margin-bottom: 24rpx;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
font-size: 24rpx;
color: #000;
position: relative;
&:nth-child(4n) {
margin-right: 0;
}
image {
width: 50rpx;
height: 50rpx;
margin-bottom: 15rpx;
}
.tab-number {
font-size: 24rpx;
color: #fff;
background: #F43F3B;
width: 40rpx;
height: 40rpx;
border-radius: 50%;
text-align: center;
line-height: 40rpx;
position: absolute;
right: 30rpx;
top: 0;
}
}
}
}
.pre-right {
display: flex;
justify-content: flex-end;
align-items: center;
padding: 0 30rpx;
margin: 20rpx 0 30rpx 0;
.form_right {
width: 180rpx;
height: 50rpx;
line-height: 48rpx;
border-radius: 8rpx;
background: #fff;
margin-right: 15rpx;
font-size: 22rpx;
color: #666;
text-align: center;
display: flex;
justify-content: center;
align-items: center;
box-shadow: 2rpx 2rpx 50rpx rgba(0, 0, 0, 0.1);
.bottomimg {
width: 20rpx;
height: 33rpx;
}
}
// .newimg{
// image{
// width:20rpx;
// height:33rpx;
// }
// }
}
.dataPre {
background-color: #fff;
border-radius: 10rpx;
box-sizing: border-box;
padding: 20rpx 0 40rpx;
margin: 0 24rpx 30rpx 24rpx;
border-radius: 20rpx;
box-shadow: 1rpx 1rpx 10rpx rgba(0, 0, 0, 0.1);
.pre_content {
background-color: #fff;
display: flex;
flex-wrap: wrap;
.content_item {
width: 33.33%;
text-align: center;
:first-child {
font-size: 32rpx;
font-weight: 600;
margin-top: 26rpx;
margin-bottom: 10rpx;
color:#333;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
:last-child {
font-size: 24rpx;
padding: 0 20rpx;
color: #999;
}
}
}
}
.pre_list {
display: flex;
justify-content: space-between;
align-items: center;
padding: 20rpx 30rpx;
.pre_title {
font-size: 28rpx;
font-weight: 700;
}
}
.body_head {
width: 702rpx;
margin: 0 auto;
box-sizing: border-box;
padding: 30rpx;
border-radius: 20rpx;
background: #fff;
box-shadow: 1rpx 1rpx 10rpx rgba(0, 0, 0, 0.1);
z-index: 5;
.conwarp{
display: flex;
justify-content: space-between;
align-items: center;
.con_title {
font-weight: 700;
font-size: 28rpx;
}
.achivebox{
font-size:24rpx;
display: flex;
justify-content: center;
align-items: center;
.achitit{
margin-right:10rpx;
}
.bottomimg{
width: 35rpx;
height: 33rpx;
}
}
}
.con_head {
display: flex;
align-items: center;
.dountChart {
margin-top: 70rpx;
width: 350rpx;
height: 350rpx;
margin-right: 24rpx;
}
.money_show {
padding-top: 45rpx;
.money_target {
:first-child {
margin-bottom: 30rpx;
color: #666;
}
:last-child {
font-size: 40rpx;
margin-bottom: 30rpx;
color: #000;
}
}
}
}
}
</style>

View File

@ -0,0 +1,70 @@
export const pageJumps = {
methods:{
//合同详情
toContractDetail(id) {
uni.navigateTo({
url: '/pagesB/contract/contractDetail?id=' + id
})
},
//客户详情
toMore(id) {
uni.navigateTo({
url: '/pages/index/groupCompany/groupCompany?id='+id
})
},
//联系人详情
jumpDetail(id) {
uni.navigateTo({
url: "/pages/index/groupCompany/contact/contactDetail?id=" + id
})
},
// 线索 详情
moreClick(id) {
uni.navigateTo({
url:'/pagesA/crm/cluesManagement/cluesMore/cluesMore?id='+id
})
},
gotoVaried(type) {
switch (type) {
case 0: //跳地图
uni.navigateTo({
url: '/pages/index/locationMap/locationMap',
})
break;
case 1: //跳公司
uni.navigateTo({
url: '/pages/index/groupCompany/groupCompany',
})
break;
case 2: //跳员工
uni.showToast({
title: "员工页面未完成,无法跳转",
icon: "none",
duration: 1000
})
break;
case 3: //跳工作日报
uni.showToast({
title: "工作日报设计图报错,无法跳转",
icon: "none",
duration: 1000
})
break;
}
},
detail(){
uni.showToast({
title: "排行榜设计图报错,无法跳转",
icon: "none",
duration: 1000
})
},
redactSchedule(){
uni.showToast({
title: "编辑日程页面未完成,无法跳转",
icon: "none",
duration: 1000
})
}
}
}

View File

@ -0,0 +1,568 @@
<template>
<view class="new_sche">
<view class="top_required">
只展示<span style="color:#f00">必填</span>字段<switch :checked="isRequired" color="#008EFF" @change="changeRequired" />
</view>
<view class="fllow_form">
<view><text>*</text>日程标题</view>
<view class="form_right">
<input type="text" :class="title ? 'valueActive' : '' " class="inputtext" v-model="title" placeholder-style="font-size:30rpx;color: #999;" placeholder="填写日程标题" />
</view>
</view>
<view class="fllow_form">
<view><text>*</text>开始时间</view>
<!-- #ifdef MP-WEIXIN -->
<picker @change="changeStartTime" mode="multiSelector" :range="dateTimeArray" :value="dateTime">
<view class="form_right">
<view :class="start_time ? 'valueActive' : '' ">{{start_time ? start_time : '点击选择'}}</view>
<view class="iconfont icon-arrows_right"></view>
</view>
</picker>
<!-- #endif -->
<!-- #ifdef H5 || APP-PLUS-->
<picker @change="changeTime" mode="multiSelector" :range="dateTimeArray" :value="dateTime">
<view class="form_right">
<view :class="start_time ? 'valueActive' : '' ">{{start_time ? start_time : '点击选择'}}</view>
<view class="iconfont icon-arrows_right"></view>
</view>
</picker>
<!-- #endif -->
<!-- #ifdef MP-ALIPAY -->
<picker @change="changeAlipayStartTime" mode="date">
<view class="form_right">
<view :class="start_time ? 'valueActive' : '' ">{{start_time ? start_time : '点击选择'}}</view>
<view class="iconfont icon-arrows_right"></view>
</view>
</picker>
<!-- #endif -->
</view>
<view class="fllow_form">
<view><text>*</text>结束时间</view>
<!-- #ifdef MP-WEIXIN -->
<picker @change="changeEndTime" mode="multiSelector" :range="dateTimeArray" :value="dateTime">
<view class="form_right">
<view :class="end_time ? 'valueActive' : '' ">{{end_time ? end_time : '点击选择'}}</view>
<view class="iconfont icon-arrows_right"></view>
</view>
</picker>
<!-- #endif -->
<!-- #ifdef H5 || APP-PLUS-->
<picker @change="changeendTimeh5" mode="multiSelector" :range="dateTimeArray" :value="dateTime">
<view class="form_right">
<view :class="end_time ? 'valueActive' : '' ">{{end_time ? end_time : '点击选择'}}</view>
<view class="iconfont icon-arrows_right"></view>
</view>
</picker>
<!-- #endif -->
<!-- #ifdef MP-ALIPAY -->
<picker @change="changeAlipayEndTime" mode="date">
<view class="form_right">
<view :class="end_time ? 'valueActive' : '' ">{{end_time ? end_time : '点击选择'}}</view>
<view class="iconfont icon-arrows_right"></view>
</view>
</picker>
<!-- #endif -->
</view>
<view class="fllow_form">
<view><text>*</text>自动结束</view>
<view class="form_right">
<radio-group @change="changeAuto" class="labellist">
<label class="" class="labelbox">
<view>
<radio color="#008EFF" value="1"/>
</view>
<view></view>
</label>
<label class="" class="labelbox">
<view>
<radio color="#008EFF" value="0"/>
</view>
<view></view>
</label>
</radio-group>
</view>
</view>
<view class="fllow_form">
<view><text>*</text>日程状态</view>
<picker @change="changeSchedule" :range="schedule_list" :value="status">
<view class="form_right">
<view :class="schedule_list[status] ? 'valueActive' : '' ">{{schedule_list[status] ? schedule_list[status] : '点击选择'}}</view>
<view class="iconfont icon-arrows_right"></view>
</view>
</picker>
</view>
<view class="fllow_form">
<view><text>*</text>紧要程度</view>
<picker @change="changeLevel" :range="level_list" :range-key="'name'" :value="levelIndex">
<view class="form_right">
<view :class="level_list[levelIndex] ? 'valueActive' : '' ">{{level_list[levelIndex] ? level_list[levelIndex].name : '点击选择'}}</view>
<view class="iconfont icon-arrows_right"></view>
</view>
</picker>
</view>
<view class="fllow_form">
<view><text>*</text>提醒时间</view>
<picker @change="changeRemind" :range="remind_list" :value="remindtype">
<view class="form_right">
<view :class="remind_list[remindtype] ? 'valueActive' : '' ">{{remind_list[remindtype] ? remind_list[remindtype] : '点击选择'}}</view>
<view class="iconfont icon-arrows_right"></view>
</view>
</picker>
</view>
<view class="fllow_form">
<view><text>*</text>关联类型</view>
<view class="form_right">
<radio-group @change="changeRelation" class="labellist">
<label class="" v-for="(item, index) in relation_List" :key="index" class="labelbox">
<view>
<radio color="#008EFF" :value="item.id" :checked="item.id == relation_type" />
</view>
<view>{{item.name}}</view>
</label>
</radio-group>
</view>
</view>
<view class="fllow_form" v-if="relationName">
<view><text>*</text>{{relationName}}</view>
<view class="form_right" @click="toSelectGuanglian">
<view :class="guanlianName ? 'valueActive' : '' ">{{guanlianName ? guanlianName : '点击选择'}}</view>
<view class="iconfont icon-arrows_right"></view>
</view>
</view>
<view class="fllow_area" v-if="!isRequired">
<view class="area_head">备注</view>
<textarea v-model="remark" :class="remark ? 'valueActive' : '' " placeholder="备注" placeholder-style="color:#999" />
</view>
<view class="btn_g bg-blue button-hover round" @click="$noMultipleClicks(toAdd)">
保存
</view>
<!-- 选择客户 -->
<select-customer ref="customerChild" @getCustomerinfo="getCustomerinfo"></select-customer>
<!-- 选择联系人 -->
<select-link ref="linkChild" @linkInfo="linkInfo"></select-link>
<!-- 选择合同 -->
<select-contract ref="contractChild" @contractInfo="contractInfo"></select-contract>
<!-- 选择线索 -->
<select-clue ref="clueChild" @clueInfo="clueInfo"></select-clue>
</view>
</template>
<script>
import { netPrevCustomer, netLianxiren, netSelectContract } from '@/api/kehu.js'
import { netAddSchedule } from '@/api/index.js'
import { netGetNopageClueslist } from '@/api/clues.js'
import { dateTimePicker, getMonthDay } from '@/util/dateTimePicker.js'
import selectCustomer from '@/components/selectCustomer.vue'
import selectLink from '@/components/selectLink.vue'
import selectContract from '@/components/selectContract.vue'
import selectClue from '@/components/selectClue.vue'
export default {
components:{
selectCustomer,
selectLink,
selectContract,
selectClue
},
data() {
return {
schedule_list:['未开始','执行中','已结束','已取消'], //
level_list:[
{ id:1, name:'重要'},
{ id:2, name:'紧急'},
{ id:3, name:'普通'},
{ id:4, name:'重要且紧急'},
], //
levelIndex:null,
remind_list:['准时提醒','5分钟前','15分钟前','30分钟前','一个小时前','两个小时前','一天前','两天前','一周前'],
relation_List:[
{ id:'1', name:'客户'},
{ id:'2', name:'联系人'},
{ id:'3', name:'合同'},
{ id:'4', name:'线索'}
], //
guanlianName:'', //
title:'', //
start_time:'', //
end_time:'', //
status:'', //
auto_end:'', // 0 1
level:'', //
remindtype:'', //
remark:'', //
relation_type:'', //
relation_id:'', // id
relationName:'', //
dateTimeArray:null,
dateTime:null,
dateArr:null,
noClick:true,
isRequired:false, //
}
},
onLoad() {
this.initTime()
},
methods: {
//
changeRequired(e) {
this.isRequired = e.detail.value
},
initTime(){
let date = new Date();
let endYear = date.getFullYear();
//
let obj = dateTimePicker(this.startYear, endYear);
//
let lastArray = obj.dateTimeArray.pop();
let lastTime = obj.dateTime.pop();
let lastDate = obj.dateArray.pop()
this.dateTimeArray=obj.dateTimeArray
this.dateArr = obj.dateArray
this.dateTime=obj.dateTime
},
//
changeStartTime(e) {
let arr = e.detail.value
if(arr.includes(-1)){
uni.showToast({
title:'请选择正确的时间',
icon:'none'
})
return
}
let str = this.handleTime(arr)
this.start_time = str
},
changeAlipayStartTime(e) {
this.start_time = e.detail.value
},
//h5
changeTime(e) {
let arr = e.detail.value
let str = this.handleTime(arr)
this.start_time = str
},
handleTime(arr) {
let year = this.dateArr[0][arr[0]]
let month = this.dateArr[1][arr[1]]
let day = this.dateArr[2][arr[2]]
let hour = this.dateArr[3][arr[3]]
let minu = this.dateArr[4][arr[4]]
let str = year + '-' + month + '-' + day +' '+hour+':'+minu
return str
},
// h5
changeendTimeh5(e) {
let arr = e.detail.value
let str = this.handleTime(arr)
this.end_time = str
},
//
changeEndTime(e) {
let arr = e.detail.value
if(arr.includes(-1)){
uni.showToast({
title:'请选择正确的时间',
icon:'none'
})
return
}
let str = this.handleTime(arr)
this.end_time = str
},
changeAlipayEndTime(e) {
this.end_time = e.detail.value
},
handleTime(arr) {
let year = this.dateArr[0][arr[0]]
let month = this.dateArr[1][arr[1]]
let day = this.dateArr[2][arr[2]]
let hour = this.dateArr[3][arr[3]]
let minu = this.dateArr[4][arr[4]]
let str = year+'-'+month+'-'+day+' '+ hour+':'+minu
return str
},
//
changeAuto(e) {
this.auto_end = e.detail.value
},
//
changeSchedule(e) {
this.status = e.detail.value
},
//
changeLevel(e) {
this.levelIndex = e.detail.value
this.level = this.level_list[e.detail.value].id
},
//
changeRemind(e) {
this.remindtype = e.detail.value
},
//
changeRelation(e) {
this.relation_id = ''
this.guanlianid = ''
this.guanlianName = ''
this.relation_type = e.detail.value
if(this.relation_type == 1) {
//
this.relationName = '关联客户'
}else if(this.relation_type == 2) {
//
this.relationName = '关联联系人'
}else if(this.relation_type == 3) {
//
this.relationName = '关联合同'
}else if(this.relation_type == 4){
//线
this.relationName = '关联线索'
}
},
toSelectGuanglian() {
if(this.relation_type == 1) {
this.toSelectCustomer()
}else if(this.relation_type == 2){
this.toSelectLink()
}else if(this.relation_type == 3){
this.toSelectContract()
}else{
this.toSelectClue()
}
},
//
toSelectCustomer() {
this.$refs.customerChild.init()
},
getCustomerinfo(obj) {
this.relation_id = obj.id
this.guanlianName = obj.name
},
//
toSelectLink() {
this.$refs.linkChild.init()
},
linkInfo(obj) {
this.relation_id = obj.id
this.guanlianName = obj.name
},
//
toSelectContract() {
this.$refs.contractChild.init()
},
contractInfo(obj) {
this.relation_id = obj.id
this.guanlianName = obj.name
},
//线
toSelectClue() {
this.$refs.clueChild.init()
},
clueInfo(obj) {
this.relation_id = obj.id
this.guanlianName = obj.name
},
//
toAdd() {
let {
title, //
start_time, //
end_time, //
status, //
auto_end, // 0 1
level, //
remindtype, //
remark, //
relation_type, //
relation_id, // id
} = this
if(!title){
uni.showToast({
title:'请输入标题',
icon:'none'
})
return
}
if(!start_time){
uni.showToast({
title:'请选择开始时间',
icon:'none'
})
return
}
if(!end_time){
uni.showToast({
title:'请选择结束时间',
icon:'none'
})
return
}
if((status == null || status == '') && status != 0){
uni.showToast({
title:'请选择日程状态',
icon:'none'
})
return
}
if(!auto_end){
uni.showToast({
title:'请选择是否自动结束',
icon:'none'
})
return
}
if(!level){
uni.showToast({
title:'请选择紧要程度',
icon:'none'
})
return
}
if((remindtype == null || remindtype == '') && remindtype != 0){
uni.showToast({
title:'请选择提醒时间',
icon:'none'
})
return
}
if(!relation_type){
uni.showToast({
title:'请选择关联类型',
icon:'none'
})
return
}
if(!relation_id){
uni.showToast({
title:'请选择'+this.relationName,
icon:'none'
})
return
}
let params = {
title, //
start_time, //
end_time, //
status, //
auto_end, // 0 1
level, //
remindtype, //
remark, //
relation_type, //
relation_id, // id
}
netAddSchedule(params).then(res=>{
uni.showToast({
title: res.msg,
icon:'none'
})
setTimeout(()=>{
uni.navigateBack({
delta:1
})
},2000)
})
}
}
}
</script>
<style lang="scss">
.valueActive{
color:#333;
}
.labellist{
display: flex;
justify-content: flex-start;
.labelbox{
display: flex;
justify-content: flex-start;
align-items: center;
}
}
radio{
transform: scale(0.6);
}
</style>
<style lang="scss" scoped>
.new_sche {
font-size: 28rpx;
padding-bottom:40rpx;
.shce_title {
padding: 0 24rpx;
margin: 30rpx 0;
background-color: #fff;
input {
height: 100rpx;
line-height: 100rpx;
}
}
.fllow_form {
display: flex;
justify-content: space-between;
height: 100rpx;
line-height: 100rpx;
background-color: #fff;
border-bottom: 1rpx solid #EAEAEA;
padding: 0 24rpx;
.form_right {
display: flex;
align-items: center;
color: #999;
image {
width: 40rpx;
height: 40rpx;
margin: 28rpx 5rpx 0 0;
}
.inputtext{
// height: 100rpx;
// line-height: 100rpx;
text-align: right;
}
}
.theme {
color: #5ca9fe;
}
text {
color: #f00;
margin-left: 10rpx;
}
.form_input {
// input {
// height: 100rpx;
// line-height: 100rpx;
// text-align: right;
// }
}
.fllow_button {
margin-top: 15rpx;
}
}
.fllow_area {
background-color: #fff;
padding: 0 30rpx 50rpx;
margin-bottom: 30rpx;
.area_head {
height: 100rpx;
line-height: 100rpx;
text {
color: #f00;
}
}
textarea {
width: 100%;
height: 300rpx;
background: #f8f8f8;
}
}
}
</style>

View File

@ -0,0 +1,24 @@
export const pageJumps = {
methods:{
selectTime(){
uni.navigateTo({
url: '/pages/index/newSche/selectTimeRange/selectTimeRange'
})
},
selectTime(){
uni.navigateTo({
url: '/pages/index/newSche/selectTimeRange/selectTimeRange'
})
},
toReminders(){
uni.navigateTo({
url: '/pages/crm/customerManagement/newFllow/taskManager/taskManager'
})
},
toRemindWay(){
uni.navigateTo({
url: '/pages/crm/customerManagement/newFllow/remindWay/remindWay'
})
}
}
}

View File

@ -0,0 +1,281 @@
<template>
<view class="select_time_range">
<view class="sche_calendar">
<view class="sche_month">
<view class="iconfont icon-arrows_left" @click="prev"></view>
<view>{{time}}</view>
<view class="iconfont icon-arrows_right" @click="next"></view>
</view>
<view class="calendar">
<view class='header'>
<view v-for="(item,index) in date" :key="item" :class='[(index == todayIndex) && isTodayWeek ? "weekMark" : ""]'>{{item}}
</view>
</view>
<!-- 每一天你的日期 -->
<view class='date-box'>
<view v-for="(item,index) in dateArr" :key="item.isToday" :class='[isToday == item.isToday ? "nowDay" : "",todayData == item.isToday ? "nowdate" : ""]'
@click="everyDay(item.isToday,item.dateNum)">
<view></view>
<view class='date-head' :class="[item.dateNum>=start && item.dateNum <= end?'red':'']">
<view class="date-style">{{item.dateNum}}</view>
<view v-if="item.dateNum >=start && item.dateNum <= end > 0">{{item.dateNum ==start?'':''}}</view>
<view v-if="item.dateNum >=start && item.dateNum <= end > 0">{{item.dateNum ==end?'':''}}</view>
</view>
</view>
</view>
</view>
</view>
</view>
</template>
<script>
//
export default {
data() {
return {
date: ['日', '一', '二', '三', '四', '五', '六'],
todayIndex: 0, //
dateArr: [], //
todayData: 0, //
year: 0, //
month: 0, //
day: 0, //
isToday: 0, //
isTodayWeek: false, //
start: 0, //
end: 0, //
dataquan: true, //
time: '' //
}
},
onLoad() {
},
created() {
this.getDataInfo()
},
mounted() {
},
methods: {
getDataInfo() {
let now = new Date();
let year = now.getFullYear();
let month = (now.getMonth() + 1 + '').padStart(2, 0);
let day = (now.getDate() + '').padStart(2, 0);
this.dateInit();
this.year = year;
this.month = month;
this.day = now.getDate()
this.isToday = '' + year + "/" + month + "/" + day
this.todayData = '' + year + "/" + month + "/" + day
this.time = `${year}${month}`
},
//
everyDay(date, dateNum) {
// start end 0
if (this.dataquan === true) {
if (this.start != 0 && this.end != 0) {
this.start = 0 //
this.end = 0
}
// start end 0
if (this.start == 0 && this.end == 0) {
this.start = dateNum //
} else if (dateNum < this.start) {
this.end = this.start
this.start = dateNum
} else if (dateNum > this.start) {
this.end = dateNum
}
}
this.isToday = date
},
// yyyy-mm-dd
dateInit: function(setYear, setMonth) {
let dateArr = []; //
let arrLen = 0; //dateArr
let now = setYear ? new Date(setYear, setMonth) : new Date();
let year = setYear || now.getFullYear();
let nextYear = 0;
let month = setMonth || now.getMonth(); //+1便
let nextMonth = (month + 1) > 11 ? 1 : (month + 1);
let startWeek = new Date(year + '/' + (month + 1) + '/' + 1).getDay(); //1
let dayNums = new Date(year, nextMonth, 0).getDate(); //
let obj = {};
let num = 0;
//
if (month + 1 > 11) {
nextYear = year + 1;
dayNums = new Date(nextYear, nextMonth, 0).getDate();
}
arrLen = startWeek + dayNums;
for (let i = 0; i < arrLen; i++) {
if (i >= startWeek) {
num = i - startWeek + 1;
obj = {
isToday: '' + year + "/" + ((month + 1) + '').padStart(2, 0) + "/" + (num + '').padStart(2, 0),
nowdate: '' + year + "/" + ((month + 1) + '').padStart(2, 0) + "/" + (num + '').padStart(2, 0),
dateNum: num,
}
} else {
obj = {};
}
dateArr[i] = obj;
}
this.dateArr = dateArr
let nowDate = new Date();
let nowYear = nowDate.getFullYear();
let nowMonth = nowDate.getMonth() + 1;
let nowWeek = nowDate.getDay();
let getYear = setYear || nowYear;
let getMonth = setMonth >= 0 ? (setMonth + 1) : nowMonth;
if (nowYear == getYear && nowMonth == getMonth) {
this.isTodayWeek = true,
this.todayIndex = nowWeek
} else {
this.isTodayWeek = false,
this.todayIndex = -1
}
},
prev() {
this.year = parseInt(this.month) - 1 == 0 ? this.year - 1 : this.year
this.month = parseInt(this.month) - 1 == 0 ? 12 : parseInt(this.month) - 1;
let setYear = this.year;
let setMonth = this.month - 1
this.time = `${setYear}${(this.month+'').padStart(2,0)}`
this.dateInit(setYear, setMonth);
},
next() {
this.year = parseInt(this.month) + 1 > 12 ? this.year + 1 : this.year
this.month = parseInt(this.month) + 1 > 12 ? 1 : parseInt(this.month) + 1;
let setYear = this.year;
let setMonth = this.month - 1
this.time = `${setYear}${(this.month+'').padStart(2,0)}`
this.dateInit(setYear, setMonth);
},
}
}
</script>
<style lang="scss" scoped>
.sche_calendar {
background-color: #fff;
margin-bottom: 20rpx;
.sche_month {
display: flex;
height: 120rpx;
line-height: 120rpx;
text-align: center;
font-size: 32rpx;
justify-content: space-between;
padding: 0 50rpx;
.icon-arrows_left,
.icon-arrows_right {
font-size: 50rpx;
}
}
.calendar {
padding: 0 20rpx;
font-size: 24rpx;
color: #999;
background-color: #fff;
.header {
view {
display: inline-block;
width: 14.285%;
text-align: center;
padding: 20rpx 0;
}
.weekMark {
position: relative;
view {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
border-bottom: 1px solid #22A7F6;
}
}
}
.date-box>view {
position: relative;
display: inline-block;
width: 14.285%;
color: #020202;
text-align: center;
vertical-align: middle;
margin: 10rpx 0;
}
}
}
.red {
background: #52c1f5 !important;
border-radius: 0 !important;
width: auto !important;
color: #fff !important;
}
.date-box {
font-size: 0;
padding: 10rpx 0;
background-color: #fff;
}
.btn_fix {
position: fixed;
bottom: 100rpx;
right: 80rpx;
image {
width: 80rpx;
height: 80rpx;
background-color: #fff;
border-radius: 40rpx;
}
}
.date-head {
height: 60rpx;
/* line-height: 60rpx; */
font-size: 26rpx;
display: flex;
flex-flow: column;
justify-content: flex-start;
color: #999;
.date-style {
line-height: 50rpx;
}
}
.nowDay .date-head {
width: 60rpx;
border-radius: 50%;
text-align: center;
color: #fff !important;
background-color: #52c1f5;
font-weight: normal !important;
}
.nowdate .date-head {
color: #52c1f5;
font-weight: bold;
}
.van-hairline--top-bottom {
position: fixed;
}
</style>

View File

@ -0,0 +1,554 @@
<template>
<view class="schedule">
<view class="sche_calendar">
<view class="sche_month">
<view class="iconfont icon-arrows_left" @click="prev"></view>
<view>{{time}}</view>
<view class="iconfont icon-arrows_right" @click="next"></view>
</view>
<view class="calendar">
<view class='header'>
<view v-for="(item,index) in date" :key="item" :class='[(index == todayIndex) && isTodayWeek ? "weekMark" : ""]'>{{item}}
</view>
</view>
<!-- 每一天你的日期 -->
<view class='date-box'>
<view
v-for="(item,index) in dateArr"
:key="item.isToday" :class='[nowDate == item.nowdate ? "nowDay" : "",todayData == item.isToday ? "nowdate" : ""]'
@click="everyDay(item.isToday,item.dateNum)">
<view></view>
<view class='date-head' >
<view>{{item.dateNum}}</view>
<view :class='item.isEvent ? "circle_dot":""'></view>
<view v-if="item.dateNum >=start && item.dateNum <= end > 0">{{item.dateNum ==start?'开始':''}}</view>
<view v-if="item.dateNum >=start && item.dateNum <= end > 0">{{item.dateNum ==end?'结束':''}}</view>
</view>
</view>
</view>
</view>
</view>
<view class="sche_con">
<view class="sche_con_item" v-for="(item,index) in list[nowDate]" :key="index">
<view class="item_left">
<view class="start-time" >
<image :src="BASE_IMG_URL+'/start_time.png'" class="timeimg" mode=""></image>
:{{item.start_time}}
</view>
<view class="content-time" >
<view class="title">{{item.title}}</view>
<view>备注{{item.remark}}</view>
<view>关联业务</view>
<view class="yewu" v-if="item.relation_type == 3" @click="toContractDetail(item.relation_id)">
<image :src="BASE_IMG_URL+'/file.png'" class="fileimg" mode=""></image>
合同
</view>
<view class="yewu" v-if="item.relation_type == 1" @click="toMore(item.relation_id)">
<image :src="BASE_IMG_URL+'/file.png'" class="fileimg" mode=""></image>
客户
</view>
<view class="yewu" v-if="item.relation_type == 2" @click="jumpDetail(item.relation_id)">
<image :src="BASE_IMG_URL+'/file.png'" class="fileimg" mode=""></image>
联系人
</view>
<view class="yewu" v-if="item.relation_type == 4" @click="moreClick(item.relation_id)">
<image :src="BASE_IMG_URL+'/file.png'" class="fileimg" mode=""></image>
线索
</view>
</view>
<view class="end-time">
<image :src="BASE_IMG_URL+'/end_time.png'" class="timeimg" mode=""></image>
:{{item.end_time}}
</view>
</view>
<view @click="toEditstatuss(item)">
<view class="item_right" v-if="item.status == 0">
<image :src="BASE_IMG_URL+'/time.png'"></image>
<view>未开始</view>
</view>
<view class="item_right" v-if="item.status == 1">
<image :src="BASE_IMG_URL+'/time_ing.png'"></image>
<view>进行中</view>
</view>
<view class="item_right" v-if="item.status == 2">
<image :src="BASE_IMG_URL+'/time_end.png'"></image>
<view>已结束</view>
</view>
<view class="item_right" v-if="item.status == 3">
<image :src="BASE_IMG_URL+'/time_over.png'"></image>
<view>已取消</view>
</view>
</view>
</view>
<view class="noList" v-if="!list[nowDate] || list[nowDate].length == 0">没有更多日程</view>
</view>
<view class="btn_fix" @click="addSchedule">
<image :src="BASE_IMG_URL+'1.png'"></image>
</view>
<!-- 日程修改状态 -->
<pop-status
:id="scheid"
:schestatus="schestatus"
v-if="statusPop"
@closeStatus="closeStatus"
@changeStatus="changeStatus"
@changeSuccess="changeStatusSuccess"
></pop-status>
</view>
</template>
<script>
import { getNowData } from '@/util/weekTime.js'
import { netScheduleList, netEditScheculeStatus } from '@/api/index.js'
import {pageJumps} from "../index_page_jumps.js";
import popStatus from '../components/popStatus.vue'
import { BASE_IMG_URL } from '@/util/api.js'
export default {
mixins: [pageJumps],
components:{
popStatus
},
data() {
return {
BASE_IMG_URL:BASE_IMG_URL,
date: ['日', '一', '二', '三', '四', '五', '六'],
todayIndex: 0, //
dateArr: [], //
todayData: 0, //
year: 0, //
month: 0, //
day: 0, //
isToday: 0, //
isTodayWeek: false, //
start: 0, //
end: 0, //
dataquan: false, //
time: '', //
nowDate:'', // 2021-04-20
list:[],
statusPop:false, //
scheid:'', //id
schestatus:'', //
}
},
onLoad() {
},
onShow() {
this.getDataInfo()
//
this.getList()
this.nowDate = getNowData()
},
mounted() {
},
methods: {
addSchedule(){
uni.navigateTo({
url:'/pages/index/newSche/newSche'
})
},
//
getList() {
let firstDay = ''
this.dateArr.forEach(ele=>{
if(ele.dateNum == 1){
firstDay = ele.nowdate
}
})
let lastDay = this.dateArr[this.dateArr.length - 1].nowdate
let params = {
start_day: firstDay,
end_day: lastDay
}
netScheduleList(params).then(res=>{
this.list = res.data
//
this.handleIsEvent()
})
},
handleIsEvent() {
let dateArr = this.dateArr
let list = this.list
dateArr.forEach(ele=>{
if(ele.dateNum){
if(list[ele.isToday].length != 0) {
ele.isEvent = true
}else{
ele.isEvent = false
}
}
})
this.dateArr = dateArr
},
getDataInfo() {
let now = new Date();
let year = now.getFullYear();
let month = (now.getMonth() + 1 + '').padStart(2, 0);
let day = (now.getDate() + '').padStart(2, 0);
this.dateInit();
this.year = year;
this.month = month;
this.day = now.getDate()
this.isToday = '' + year + "/" + month + "/" + day
this.todayData = '' + year + "/" + month + "/" + day
this.time = `${year}${month}`
},
//
everyDay(date, dateNum) {
// start end 0
if (this.dataquan === true) {
if (this.start != 0 && this.end != 0) {
this.start = 0 //
this.end = 0
}
// start end 0
if (this.start == 0 && this.end == 0) {
this.start = dateNum //
} else if (dateNum < this.start) {
this.end = this.start
this.start = dateNum
} else if (dateNum > this.start) {
this.end = dateNum
}
}
this.nowDate = date
},
// yyyy-mm-dd
dateInit: function(setYear, setMonth) {
let dateArr = []; //
let arrLen = 0; //dateArr
let now = setYear ? new Date(setYear, setMonth) : new Date();
let year = setYear || now.getFullYear();
let nextYear = 0;
let month = setMonth || now.getMonth(); //+1便
let nextMonth = (month + 1) > 11 ? 1 : (month + 1);
let startWeek = new Date(year + '/' + (month + 1) + '/' + 1).getDay(); //1
let dayNums = new Date(year, nextMonth, 0).getDate(); //
let obj = {};
let num = 0;
//
if (month + 1 > 11) {
nextYear = year + 1;
dayNums = new Date(nextYear, nextMonth, 0).getDate();
}
arrLen = startWeek + dayNums;
for (let i = 0; i < arrLen; i++) {
if (i >= startWeek) {
num = i - startWeek + 1;
obj = {
isToday: '' + year + "-" + ((month + 1) + '').padStart(2, 0) + "-" + (num + '').padStart(2, 0),
nowdate: '' + year + "-" + ((month + 1) + '').padStart(2, 0) + "-" + (num + '').padStart(2, 0),
dateNum: num,
}
} else {
obj = {};
}
dateArr[i] = obj;
}
this.dateArr = dateArr
let nowDate = new Date();
let nowYear = nowDate.getFullYear();
let nowMonth = nowDate.getMonth() + 1;
let nowWeek = nowDate.getDay();
let getYear = setYear || nowYear;
let getMonth = setMonth >= 0 ? (setMonth + 1) : nowMonth;
if (nowYear == getYear && nowMonth == getMonth) {
this.isTodayWeek = true,
this.todayIndex = nowWeek
} else {
this.isTodayWeek = false,
this.todayIndex = -1
}
},
prev() {
this.year = parseInt(this.month) - 1 == 0 ? this.year - 1 : this.year
this.month = parseInt(this.month) - 1 == 0 ? 12 : parseInt(this.month) - 1;
let setYear = this.year;
let setMonth = this.month - 1
this.time = `${setYear}${(this.month+'').padStart(2,0)}`
this.dateInit(setYear, setMonth);
let nowDate = ''
this.dateArr.forEach(ele=>{
if(ele.dateNum == 1){
nowDate = ele.nowdate
}
})
this.nowDate = nowDate
this.getList()
},
next() {
this.year = parseInt(this.month) + 1 > 12 ? this.year + 1 : this.year
this.month = parseInt(this.month) + 1 > 12 ? 1 : parseInt(this.month) + 1;
let setYear = this.year;
let setMonth = this.month - 1
this.time = `${setYear}${(this.month+'').padStart(2,0)}`
this.dateInit(setYear, setMonth);
let nowDate = ''
this.dateArr.forEach(ele=>{
if(ele.dateNum == 1){
nowDate = ele.nowdate
}
})
this.nowDate = nowDate
this.getList()
},
//
toEditstatuss(item) {
this.scheid = item.id
this.schestatus = item.status
this.statusPop = true
uni.hideTabBar({
animation:true
})
},
//
closeStatus() {
this.statusPop = false
this.schestatus = ''
this.scheid = ''
uni.showTabBar({
animation:true
})
},
changeStatus(status) {
this.schestatus = status
},
//
changeStatusSuccess() {
let params = {
id: this.scheid,
status: this.schestatus
}
netEditScheculeStatus(params).then(res=>{
this.statusPop = false
this.schestatus = ''
this.scheid = ''
uni.showToast({
title:'日程状态修改成功',
icon:'none'
})
uni.showTabBar({
animation:true
})
setTimeout(()=>{
this.getList()
},1000)
})
},
}
}
</script>
<style lang="scss" scoped>
.start-time{
color: #0081FF;
display: flex;
justify-content: flex-start;
align-items: center;
.timeimg{
width:41rpx;
height:33rpx;
}
}
.end-time{
color: #ff7800;
display: flex;
justify-content: flex-start;
align-items: center;
.timeimg{
width:41rpx;
height:33rpx;
}
}
.sche_calendar {
background-color: #fff;
margin-bottom: 20rpx;
.sche_month {
display: flex;
height: 120rpx;
line-height: 120rpx;
text-align: center;
font-size: 32rpx;
justify-content: space-between;
padding: 0 50rpx;
.icon-arrows_left,
.icon-arrows_right {
font-size: 50rpx;
}
}
.calendar {
padding: 0 20rpx;
font-size: 24rpx;
color: #999;
background-color: #fff;
.header {
view {
display: inline-block;
width: 14.285%;
text-align: center;
padding: 20rpx 0;
}
.weekMark {
position: relative;
view {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
border-bottom: 1px solid #22A7F6;
}
}
}
.date-box>view {
position: relative;
display: inline-block;
width: 14.285%;
color: #020202;
text-align: center;
vertical-align: middle;
margin: 10rpx 0;
}
}
}
.sche_con {
background-color: #fff;
padding: 24rpx 24rpx 5rpx 24rpx;
.sche_con_item {
display: flex;
justify-content: space-between;
align-items: center;
background-color: #fcfcfc;
padding:20rpx 10rpx;
margin-bottom: 24rpx;
.item_left {
flex: 1;
color: #999;
view{
margin-bottom: 10rpx;
}
.title{
color: #333;
}
.yewu{
display: flex;
justify-content: flex-start;
align-items: center;
background:#f5f7fa;
padding:10rpx;
.fileimg{
width:20rpx;
height:20rpx;
margin-right:15rpx;
}
}
:last-child {
margin-bottom:0;
}
}
.item_right {
display: flex;
align-items: center;
color: #999;
image {
width: 40rpx;
height: 40rpx;
margin-right: 10rpx;
}
}
}
}
.circle_dot {
margin-left: 45rpx;
margin-top: 12rpx;
width: 12rpx;
height: 15rpx;
background-color: $uni-text-color;
border-radius: 8rpx;
}
.red {
background: red !important;
border-radius: 0 !important;
width: auto !important;
color: #333 !important;
}
.date-box {
font-size: 0;
padding: 10rpx 0;
background-color: #fff;
}
.btn_fix {
position: fixed;
bottom: 100rpx;
right: 80rpx;
image {
width: 80rpx;
height: 80rpx;
background-color: #fff;
border-radius: 40rpx;
}
}
.date-head {
height: 60rpx;
/* line-height: 60rpx; */
font-size: 26rpx;
display: flex;
flex-flow: column;
justify-content: flex-start;
color: #999;
}
.nowDay .date-head {
width: 60rpx;
border-radius: 50%;
text-align: center;
color: #fff !important;
background-color: $uni-text-color;
margin: -30rpx auto 0;
font-weight: normal !important;
line-height: 61rpx;
}
.nowdate .date-head {
color: #52c1f5;
font-weight: bold;
}
.van-hairline--top-bottom {
position: fixed;
}
.noList{
font-size:24rpx;
text-align: center;
padding:80rpx 0;
color:#666;
}
</style>

251
pages/index/screen.vue Normal file
View File

@ -0,0 +1,251 @@
<template>
<view class="">
<uni-popup ref="screenpopup" type="bottom" background-color="#fff">
<scroll-view scroll-y class="scrollbox" style="height:540rpx;background:#fff;">
<view class="screen_content">
<view class="fir_li">
<view class="li_label">时间筛选</view>
<view class="rightbox">
<view class="listwarp">
<view
class="li"
:class="index == timeIndex ?'liactive':''"
@click="changeTime(index)"
v-for="(item,index) in timeList"
:key="index">{{item.name}}</view>
</view>
<view class="time_warp" v-if="timeList[timeIndex] && timeList[timeIndex].value == 'zidingyi'">
<picker @change="changeStartTime" mode="date">
<view class="timebox">
{{start_time ? start_time : '开始时间'}}
</view>
</picker>
<view class="xian"></view>
<picker @change="changeEndTime" mode="date">
<view class="timebox">
{{end_time ? end_time : '结束时间'}}
</view>
</picker>
</view>
</view>
</view>
</view>
</scroll-view>
<view class="button_bottom">
<view @tap.stop="reset">重置</view>
<view @tap.stop="sureQuery">确定</view>
</view>
</uni-popup>
</view>
</template>
<script>
import { netTime } from '@/api/index.js'
export default{
data() {
return{
timeList:[
{value:'today',name:'今天'},
{value:'yesterday',name:'昨天'},
{value:'thisweek',name:'本周'},
{value:'lastweek',name:'上周'},
{value:'thismonth',name:'本月'},
{value:'lastmonth',name:'上月'},
{value:'thisquarter',name:'本季'},
{value:'lastquarter',name:'上季'},
{value:'thisyear',name:'今年'},
{value:'lastyear',name:'去年'},
{value:'zidingyi',name:'自定义'}
],
timeIndex:null,
start_time:'',
end_time:'',
s_time:'',
e_time:''
}
},
methods:{
init() {
this.$refs.screenpopup.open()
},
changeTime(index) {
this.timeIndex = index
this.getTime()
},
getTime() {
netTime({times:this.timeList[this.timeIndex].value}).then(res=>{
res = res.data
this.s_time = res.times[0]
this.e_time = res.times[1]
})
},
changeStartTime(e) {
this.start_time = e.detail.value
},
changeEndTime(e) {
this.end_time = e.detail.value
},
reset() {
this.timeIndex = null
this.start_time = ''
this.end_time = ''
},
sureQuery() {
let params = {
text:this.timeList[this.timeIndex]?this.timeList[this.timeIndex].name:'',
start_time:this.timeList[this.timeIndex] && this.timeList[this.timeIndex].value != 'zidingyi'?this.s_time:this.start_time,
end_time:this.timeList[this.timeIndex] && this.timeList[this.timeIndex].value != 'zidingyi'?this.e_time:this.end_time,
}
this.$refs.screenpopup.close()
this.$emit('sureTime',params)
}
}
}
</script>
<style lang="scss" scoped>
.screen_content {
z-index: 2;
border-top: 1rpx solid #CCCCCC;
background-color: #fff;
padding: 24rpx;
.fir_li {
margin-bottom: 20rpx;
.li_label {
font-size: 28rpx;
margin-top: 30rpx;
margin-bottom: 20rpx;
text-align: center;
}
.classify {
display: flex;
justify-content: space-around;
.classify_flex {
padding: 5rpx 16rpx;
color: #999;
font-size: 30rpx;
border: 1px solid #999;
border-radius: 10rpx;
}
.c_f {
background: $uni-text-color !important;
color: #fff;
}
}
.li_box {
border-radius: 15rpx;border: 1rpx solid #CCCCCC;
width:690rpx;
height: 60rpx;
padding: 0 35rpx;
line-height: 60rpx;
display: flex;
justify-content: space-around;
color: #999;
box-sizing: border-box;
}
.listwarp{
width:600rpx;
margin:0 auto;
padding:25rpx 0;
display: flex;
justify-content: flex-start;
flex-wrap: wrap;
align-items: center;
.li{
display: flex;
align-items: center;
justify-content: center;
width: 172rpx;
height: 54rpx;
background: #ededed;
border: 1rpx solid #ededed;
border-radius: 10rpx;
font-size:27rpx;
color:#999;
margin-right:40rpx;
margin-bottom:20rpx;
position: relative;
&:nth-child(3n){
margin-right:0;
}
.clearStaff{
position: absolute;
right:-20rpx;
top:-20rpx;
font-size:28rpx;
width:40rpx;
height:40rpx;
background:rgba(0,0,0,0.5);
border-radius: 50%;
text-align: center;
line-height: 38rpx;
color:#fff;
}
}
.liactive{
color:#666;
border: 1rpx solid $uni-text-color;
background:#fff;
}
}
.time_warp{
margin:0 auto;
width:600rpx;
display: flex;
justify-content: center;
align-items: center;
.timebox{
width: 172rpx;
height: 54rpx;
border-radius: 10rpx;
text-align: center;
line-height: 50rpx;
font-size:27rpx;
color:#666;
border:1rpx solid $uni-text-color;
}
.xian{
width:85rpx;
height:7rpx;
background:#ededed;
margin:0 20rpx;
}
.timeactive{
background:#0287FF;
color:#fff;
}
}
}
}
.button_bottom {
display: flex;
width: 100%;
height: 190rpx;
background-color: #fff;
line-height: 90rpx;
text-align: center;
font-size: 32rpx;
justify-content: space-around;
padding-bottom: 100rpx;
:first-child {
color: #999;
border: 1rpx solid #999;
width: 260rpx;
height: 70rpx;
line-height: 70rpx;
border-radius: 20rpx;
}
:last-child {
background-color: $uni-text-color;
color: #fff;
width: 260rpx;
height: 70rpx;
line-height: 70rpx;
border-radius: 20rpx;
}
}
</style>

297
pages/index/workNews.vue Normal file
View File

@ -0,0 +1,297 @@
<template>
<view>
<view class="work_trend">
<view class="querylist">
<view class="queryfir">
<picker @change="changeRead" :range="readList" :value="readIndex">
<view class="form_right">
<view>{{readList[readIndex] ? readList[readIndex] : '请选择'}}</view>
<image :src="BASE_IMG_URL+'newxia.png'" class="bottomimg" mode="scaleToFill"></image>
</view>
</picker>
</view>
</view>
<view class="item_content" v-for="(item,index) in workList" :key="index" @click.stop="clientClick(item,index)">
<view class="unread" v-if="item.is_read != 1"></view>
<view class="con_img">
<image :src="item.staff.img ? item.staff.img :BASE_IMG_URL+'headImg.png'" mode="scaleToFill"></image>
<view class="main_first">
<view class="main_title" >
<view class="first_left">
<view>{{item.staff.name}}</view>
<view class="fontColor">{{item.staff.post?item.staff.post:''}}</view>
</view>
<view class="main_type daofang" v-if="item.follow_type == '到访'">{{item.follow_type}}</view>
<view class="main_type genjin" v-if="item.follow_type == '跟进'">{{item.follow_type}}</view>
<view class="main_type other" v-if="item.follow_type != '跟进' && item.follow_type != '到访'">{{item.follow_type}}</view>
</view>
<view class="fontColor main_time">{{item.follow_time}}</view>
</view>
</view>
<view class="con_main">
<view class="main_second">
<view>{{item.content}}</view>
</view>
<view class="main_img" v-if="item.file.length != 0">
<image
:src="ele.file_path"
v-for="(ele,fileindex) in item.file"
:key="fileindex"
v-if="ele.types == 'image'"
class="imgbox"
mode="scaleToFill"
@click.stop="toPrevieImg(ele.file_path)"
></image>
</view>
<view class="main_third fontColor" v-if="item.next_time != null">
<view class="third_left" >
<view class="iconfont icon-clock"></view>
<view class="lxs_time">下次跟进时间{{item.next_time}}</view>
</view>
<view class="third_right">
<view class="iconfont icon-arrows_right"></view>
</view>
</view>
</view>
</view>
<view style="height: 200rpx;"></view>
<u-empty v-if="workList.length== 0" text="暂无更多"></u-empty>
</view>
</view>
</template>
<script>
import { netKehuFollow } from '@/api/kehu.js'
import { BASE_IMG_URL } from '@/util/api.js'
export default{
data() {
return{
readList:['全部','已读','未读'],
readIndex:0,
page:1,
totalPage:1,
limit:10,
workList:[],
BASE_IMG_URL:BASE_IMG_URL,
}
},
onShow() {
this.workList = []
this.page = 1
this.getWorkList()
},
onReachBottom() {
if(this.tabindex == 2){
if(this.page >= this.totalPage){
return
}
this.page ++
this.getWorkList()
}
},
methods:{
//
getWorkList() {
let params = {
page: this.page,
limit:this.limit,
is_read: this.readIndex
}
netKehuFollow(params).then(res=>{
this.workList = this.workList.concat(res.data.data)
this.totalPage = res.data.last_page
})
},
//
changeRead(e) {
this.readIndex = e.detail.value
this.page = 1
this.workList = []
this.getWorkList()
},
//
toPrevieImg(file) {
uni.previewImage({
urls: [file]
})
},
//
clientClick(item,index) {
uni.navigateTo({
url:'/pagesA/crm/cluesManagement/followUpDetail/followUpDetail?id='+item.id,
success:()=>{
let arr = this.workList
arr[index].is_read = 1
this.workList = arr
}
})
}
}
}
</script>
<style lang="scss" scoped>
.querylist{
margin:40rpx 0 30rpx;
padding:0 30rpx;
display: flex;
justify-content: flex-end;
align-items: center;
.queryfir{
margin-right:15rpx;
box-shadow: 2rpx 2rpx 50rpx rgba(0,0,0,0.1);
background:#fff;
border-radius: 8rpx;
.form_right{
width:180rpx;
height:50rpx;
font-size:22rpx;
color:#666;
text-align: center;
line-height: 48rpx;
display: flex;
justify-content: center;
align-items: center;
.bottomimg{
width:20rpx;
height:33rpx;
margin-left:15rpx;
}
}
}
}
//
.work_trend {
padding: 0 30rpx 0 30rpx ;
.querylist{
padding:0;
.queryfir{
margin-right:0;
}
}
.item_content {
display: block;
background-color: #fff;
padding: 24rpx 24rpx 10rpx;
border-radius: 10rpx;
margin-bottom: 30rpx;
box-shadow: 2rpx 2rpx 50rpx rgba(0,0,0,0.1);
position: relative;
.unread{
width:10rpx;
height:10rpx;
border-radius: 50%;
position: absolute;
right:5rpx;
top:5rpx;
background:#F43F3B;
}
.con_img {
display: flex;
.main_first {
margin-bottom: 25rpx;
padding-left: 25rpx;
flex: 1;
.main_time{
line-height: 25px;
}
.main_title{
display: flex;
justify-content: space-between;
.first_left {
display: flex;
:first-child {
font-size: 32rpx;
margin-right: 10rpx;
margin-top: -3rpx;
}
:last-child {
margin-top: 2rpx;
}
}
.main_type{
padding:5rpx 20rpx;
border-radius: 5rpx;
color:#fff;
}
.daofang{
background:$uni-text-color;
}
.genjin{
background:#ff7800;
}
.other{
background:#1CBBB4;
}
}
}
image {
width: 100rpx;
height: 100rpx;
border-radius: 50%;
}
}
.con_main {
flex: 1;
.main_second{
padding-bottom:20rpx;
}
.main_img{
display: flex;
justify-content: flex-start;
align-items: center;
flex-wrap: wrap;
margin-top: 20rpx;
.imgbox{
padding: 10rpx;
border-radius: 5rpx;
border:1rpx solid #CCC;
width:160rpx;
height:160rpx;
margin-right:14rpx;
margin-bottom:14rpx;
}
}
.main_third {
display: flex;
justify-content: space-between;
align-items: center;
margin: 20rpx 0 10rpx;
.third_left {
display: flex;
justify-content: flex-start;
align-items: center;
.lxs_time{
font-size:28rpx;
margin-left:10rpx;
}
}
.third_right {
display: flex;
.icon-arrows_right {
margin-top: -4rpx;
}
}
}
.main_fourth {
padding-bottom: 10rpx;
}
}
}
.fontColor {
color: #999;
}
.lxs_itme {
padding-left: 5px;
padding-top: 2px;
}
}
</style>

565
pages/nearby/nearby.vue Normal file
View File

@ -0,0 +1,565 @@
<template>
<view class="nearby">
<view class="select_box">
<picker @change="changeType" :value="typeIndex" :range="typeList">
<view class="sel_left">
{{typeList[typeIndex] ? typeList[typeIndex] : '全部'}}
<image :src="BASE_IMG_URL+'newxia.png'" class="xiaimg" mode="scaleToFill"></image>
</view>
</picker>
<picker @change="changeNear" :value="nearIndex" :range="nearList" :range-key="'name'">
<view class="sel_left">
{{nearList[nearIndex] ? nearList[nearIndex].name : '附近'}}
<image :src="BASE_IMG_URL+'newxia.png'" class="xiaimg" mode="scaleToFill"></image>
</view>
</picker>
</view>
<view class="map_show" :style="{height:isFullScreen ? mapHeight : '400rpx'}">
<map style="width: 750rpx; " :style="{height:isFullScreen ? mapHeight : '400rpx'}" :latitude="latitude" :longitude="longitude"
:markers="covers" @markertap="changeLiInfo"></map>
</view>
<view class="kehu-btn" v-show="isFullScreen" @click="isFullScreen = false">
查看详情
</view>
<view v-show="!isFullScreen" class="position">
<view class="xiawarp" @click="isFullScreen = true">
<image :src="BASE_IMG_URL+'xia_a.png'" class="xiaimg" mode="scaleToFill"></image>
</view>
<view class="map_rim">
<view>[当前位置]{{address}}</view>
<image :src="BASE_IMG_URL+'ydw.png'" class="weizhiimg" mode="scaleToFill"></image>
</view>
<view class="" style="padding:24rpx 30rpx">
<u-search @change="searchName" placeholder="请输入搜索关键词" />
</view>
<scroll-view scroll-y="true" class="scroll" :style="{height:height}">
<view v-if="showList" style="padding-bottom:calc(env(safe-area-inset-bottom) / 2)">
<view class="map_group" v-for="(item,index) in list" :key="index">
<view class="name_li">
<view class="name">
{{item.name}}
<text style="color:#008EFF;font-size:22rpx;margin-left:10rpx;" v-if="item.owner_staff_id > 0">归属人({{item.owner_staff.name}})</text>
</view>
<view class="status" v-if="item.follow">{{item.follow}}</view>
</view>
<view class="text">距离{{item.juli}} {{item.address_detail?item.address_detail:''}}</view>
<view class="text">跟进时间{{item.next_time}}</view>
<view class="bntlist">
<view class="anniu luxian" @click="lookMap(item)">查看路线</view>
<view class="anniu" style="color:#008EFF" v-if="item.owner_staff_id > 0" @click="toMore(item.id)">查看详情</view>
<view class="anniu lingqu" style="color:#008EFF" v-else @click="toGroupCompany(item)">领取</view>
</view>
</view>
<u-empty v-if="list.length == 0" text="暂无更多"></u-empty>
</view>
<view v-else>
<view class="backlist" @click="backList">返回列表</view>
<view class="map_group">
<view class="name_li">
<view class="name">{{liInfo.name}} <text style="color:#008EFF;font-size:22rpx;margin-left:10rpx;" v-if="item.owner_staff_id > 0">归属人({{item.owner_staff.name}})</text></view>
<view class="status" v-if="liInfo.follow">{{liInfo.follow}}</view>
</view>
<view class="text">距离{{liInfo.juli}} {{liInfo.address_detail?liInfo.address_detail:''}}</view>
<view class="text">跟进时间{{liInfo.next_time}}</view>
<view class="bntlist">
<view class="anniu luxian" @click="lookMap(liInfo)">查看路线</view>
<view class="anniu" style="color:#008EFF" v-if="liInfo.owner_staff_id > 0" @click="toMore(liInfo.id)">查看详情</view>
<view class="anniu lingqu" style="color:#008EFF" v-else @click="toGroupCompany(liInfo)">领取</view>
</view>
</view>
</view>
</scroll-view>
</view>
</view>
</template>
<script>
import { BASE_IMG_URL } from '@/util/api.js'
import uniTabbar from '@/components/tabbar/tabbar.vue'
import { netNearKehuList } from '@/api/index.js'
import { netReceiveKehu } from '@/api/kehu.js'
import { netAgentList } from '@/api/clues.js'
import { netMapKey } from '@/api/login.js'
var QQMapWX;
var qqmapsdk;
export default {
components:{
uniTabbar
},
data() {
return {
BASE_IMG_URL:BASE_IMG_URL,
tipNumber:null,
latitude: '',
longitude: '',
covers: [],
typeList:['全部客户','我的客户','下属负责的客户'],
typeIndex:null,
nearList:[
{id:0,name:'附近1KM',num:1},
{id:1,name:'附近3KM',num:3},
{id:2,name:'附近5KM',num:5},
{id:3,name:'附近10KM',num:10},
{id:4,name:'附近30KM',num:30},
{id:5,name:'附近200KM',num:200},
{id:6,name:'附近400KM',num:400},
{id:7,name:'附近600KM',num:600},
{id:8,name:'附近800KM',num:800},
{id:9,name:'全部',num:1000000},
],
nearIndex:2,
showMask:false,
maskType:1, //1 2
address:'',
list:[],
showList:true,
liInfo:{},
liId:'',
isFullScreen:true,
name:'', //
otherArr:[], //
// #ifdef H5
height: 'calc(100vh - env(safe-area-inset-bottom) - 822rpx)',
// #endif
// #ifndef H5
height: '400rpx',
// #endif
mapHeight:'400rpx'
}
},
onLoad() {
//
uni.getSystemInfo({
success: (res) => {
let ratio = 750/res.screenWidth
let height = res.windowHeight * ratio - 200
this.mapHeight = height+'rpx'
let scrollH = res.windowHeight * ratio - 750
this.height = scrollH+'rpx'
}
})
//key
this.getKey()
},
onShow() {
// this.getTip()
},
methods: {
//key
getKey() {
netMapKey().then(res=>{
if(res.data.map_key){
QQMapWX = require('../../util/qqmap-wx-jssdk.min.js')
qqmapsdk = new QQMapWX({
key: res.data.map_key //
})
//
this.getAddressinfo()
}else{
uni.showToast({
title:'请在后台配置地图key',
icon:'none'
})
}
})
},
getTip(){
netAgentList().then(res=>{
this.tipNumber = res.data.total
uni.setStorageSync('token',res.data.userinfo.token)
uni.setStorageSync('roleType',res.data.userinfo.role_type)
uni.setStorageSync('rules',res.data.userinfo.rules)
})
},
//
searchName(e) {
this.name = e
this.getKehuList()
},
getAddressinfo() {
uni.getLocation({
// #ifdef H5
type: 'wgs84',
// #endif
// #ifndef H5
type: 'gcj02',
// #endif
isHighAccuracy: true,
altitude: true,
success:(res)=>{
this.longitude = res.longitude
this.latitude = res.latitude
let covers = [
{
id:0,
latitude:res.latitude,
longitude:res.longitude,
iconPath:'../../static/selfweizhi.png',
width:20,
height:20,
label: {
content: '自己所在位置',
bgColor:'#fff',
fontSize: 12,
bgColor:'#008EFF',
color: '#fff',
padding:5,
textAlign: 'center',
borderRadius: 10
}
}
]
this.covers = covers
//
this.getKehuList()
// #ifndef H5
//
qqmapsdk.reverseGeocoder({
location: {
longitude: res.longitude,
latitude: res.latitude
},
success:(res)=>{
this.address = res.result.address
},
fail:(err)=>{
console.log('12465',err)
}
})
// #endif
// #ifdef H5
this.$jsonp('https://apis.map.qq.com/ws/geocoder/v1',{
key:key,
output:'jsonp',
location:`${res.latitude},${res.longitude}`,
get_poi:'1'
}).then(res=>{
this.address = res.result.address_component.province+res.result.address_component.city+res.result.formatted_addresses.rough
})
// #endif
},
fail:(err)=>{
if(err.errMsg == 'getLocation:fail auth deny'){
uni.showToast({
title:'请允许使用位置信息',
icon:'none'
})
}
}
})
},
//
getKehuList() {
let params = {
lng: this.longitude,
lat: this.latitude,
type: this.typeIndex,
name: this.name,
distance: this.nearList[this.nearIndex] ? this.nearList[this.nearIndex].num : ''
}
netNearKehuList(params).then(res=>{
this.list = res.data
this.handleCover(res.data)
})
},
handleCover(data) {
data.forEach((ele,index)=>{
if(ele.type == 3) {
this.otherArr.push(ele.id)
}
let coversArr = []
coversArr = coversArr.concat(this.covers)
coversArr.push({
id:ele.id,
latitude:ele.lat,
longitude:ele.lng,
iconPath:ele.type == 0 ? '../../static/selfweizhi.png' : ele.type == 1 ? '../../static/weizhi.png' : ele.type == 2 ? '../../static/greenweizhi.png' : '../../static/otherweizhi.png',
width:20,
height:20,
label: {
content: ele.name,
fontSize: 12,
bgColor:ele.type == 0 ? '#008EFF' : ele.type == 1 ? '#03aa96' : ele.type == 2 ? '#2cee99' : '#fe1212',
color: '#fff',
padding:5,
textAlign: 'center',
borderRadius: 10
}
})
this.covers = coversArr
})
},
//
changeLiInfo(e) {
let id = e.detail.markerId
if(id == 0 || (this.otherArr.indexOf(id) != -1)) {
return
}
this.isFullScreen = false
this.showList = false
this.list.forEach(ele=>{
if(ele.id == id) {
this.liInfo = ele
}
})
},
backList () {
this.showList = true
},
//
showAll() {
this.showMask = true
this.maskType = 1
},
changeType(e) {
this.typeIndex = e.detail.value
this.getKehuList()
},
changeNear(e) {
this.nearIndex = e.detail.value
this.getKehuList()
},
// 线
lookMap(item) {
uni.openLocation({
latitude: Number(item.lat),
longitude: Number(item.lng),
success:(res)=>{
console.log(res)
},
fail:(err)=>{
console.log(err)
}
})
},
//
toMore(id) {
uni.navigateTo({
url: '/pages/index/groupCompany/groupCompany?id='+id+'&type=1'
})
},
toGroupCompany(item) {
uni.showModal({
title:'是否确定领取公池客户',
content:'领取后长时间未跟进,客户将自动转为公共客户',
success:(res)=>{
if(res.confirm){
netReceiveKehu({customer_id:item.id}).then(res=>{
uni.showToast({
title:res.msg,
icon:'none'
})
setTimeout(()=>{
this.getKehuList()
let id = item.id
let arr = this.list
arr.forEach(ele=>{
if(ele.id == id){
this.liInfo = ele
}
})
},2000)
})
}
}
})
}
}
}
</script>
<style>
page{
background:#fff;
}
</style>
<style scoped lang="scss">
.select_box{
display: flex;
justify-content: space-around;
align-items: center;
height:110rpx;
background:#fff;
padding:0 20rpx;
position: relative;
.sel_left{
display: flex;
justify-content: space-between;
align-items: center;
padding:0 20rpx;
width:300rpx;
height:80rpx;
border-radius: 25rpx;
font-size:24rpx;
color:#333;
background:#f5f5f5;
.xiaimg{
width:20rpx;
height:30rpx;
}
}
}
.mask{
position: absolute;
width:750rpx;
top:110rpx;
bottom:0;
background:rgba(0,0,0,0.5);
z-index: 9;
.maskbox{
position: absolute;
left:0;
top:0;
width:750rpx;
background:#fff;
.leftbox{
padding:30rpx;
.leftli{
padding:20rpx;
border-bottom:1rpx solid #CCC;
font-size:24rpx;
color:#333;
}
.leftli_active{
color:$uni-text-color;
border-bottom:1rpx solid $uni-text-color;
}
}
.maskbtnli{
width:750rpx;
display: flex;
justify-content: space-around;
align-items: center;
padding:20rpx 0 30rpx;
.maskbtn{
width:300rpx;
height:60rpx;
border-radius: 30rpx;
line-height: 60rpx;
text-align: center;
font-size:24rpx;
color:#fff;
}
.sure{
background:$uni-text-color;
}
.reset{
background: $uni-text-color;
}
}
}
}
.nearby {
.map_show {
width: 750rpx;
height: 400rpx;
}
.kehu-btn{
width:750rpx;
height:100rpx;
padding-bottom: calc(env(safe-area-inset-bottom) / 2);
background:#fff;
border-top:1rpx solid #CCC;
font-size:26rpx;
color:#666;
text-align: center;
line-height: 100rpx;
color:$uni-text-color;
}
.scroll {
// 487 687
// height: 500rpx;
background:#fff;
.backlist{
font-size:24rpx;
color:$uni-text-color;
padding:20rpx;
}
.map_group {
background-color: #fff;
padding:30rpx;
border-bottom:1rpx solid #ccc;
.name_li{
display: flex;
justify-content: space-between;
align-items: center;
.name{
font-size:32rpx;
color:#333;
}
.status{
font-size:24rpx;
color:#fff;
padding:5rpx 8rpx;
border-radius: 10rpx;
background:$uni-text-color;
}
}
.text{
font-size:24rpx;
color:#666;
margin:15rpx 0;
}
.bntlist{
display: flex;
justify-content: space-around;
align-items: center;
.anniu{
width:240rpx;
height:60rpx;
border-radius: 30rpx;
font-size:26rpx;
color:#fff;
text-align: center;
line-height: 60rpx;
background:#fff;
border:1px solid $uni-text-color;
}
.luxian{
background:$uni-text-color;
border:1px solid $uni-text-color;
}
.lingqu{
background: #fff;
border:1px solid $uni-text-color;
}
}
}
}
.xiawarp{
background:#fff;
padding:10rpx 0;
text-align: center;
.xiaimg{
width:30rpx;
height:30rpx;
}
}
.map_rim {
display: flex;
padding: 0 20rpx;
height: 80rpx;
line-height: 80rpx;
background-color: #fff;
justify-content: space-between;
align-items: center;
font-size:24rpx;
color:#333;
border: 1rpx solid #EAEAEA;
.weizhiimg{
width:30rpx;
height:30rpx;
}
}
}
</style>

190
pages/news/news.vue Normal file
View File

@ -0,0 +1,190 @@
<template>
<view class="news">
<view class="news_item" @click="remind">
<view class="item_img">
<image :src="BASE_IMG_URL+'tixing1.png'" mode="scaleToFill"></image>
</view>
<view class="item_con">
<view>提醒通知</view>
<view>{{info && info.leads.msg}}</view>
</view>
<view class="item_messnum">
<view class="message_num" v-if="info && info.leads.count != 0">{{info && info.leads.count}}</view>
<view class="iconfont icon-arrows_right"></view>
</view>
</view>
<view class="news_item" @click="affiche">
<view class="item_img">
<image :src="BASE_IMG_URL+'gonggao1.png'" mode="scaleToFill"></image>
</view>
<view class="item_con">
<view>系统公告</view>
<view>{{info && info.notice.msg}}</view>
</view>
<view class="item_messnum">
<view class="message_num" v-if="info && info.notice.count != 0">{{info && info.notice.count}}</view>
<view class="iconfont icon-arrows_right"></view>
</view>
</view>
<view class="news_item" @click="workTrend">
<view class="item_img">
<image :src="BASE_IMG_URL+'gongzuo1.png'" mode="scaleToFill"></image>
</view>
<view class="item_con">
<view>工作动态</view>
<view>随时随地了解团队工作动态</view>
</view>
<view class="item_messnum">
<view class="iconfont icon-arrows_right" style="margin-left: 48rpx;"></view>
</view>
</view>
<view class="news_item" @click="schedule">
<view class="item_img">
<image :src="BASE_IMG_URL+'daiban.png'"></image>
</view>
<view class="item_con">
<view>待办事项</view>
<view>{{info && info.agent.msg}}</view>
</view>
<view class="item_messnum">
<view class="message_num" v-if="info && info.agent.count != 0">{{info.agent.count}}</view>
<view class="iconfont icon-arrows_right"></view>
</view>
</view>
<view class="news_item" @click="toLookList(2)">
<view class="item_img">
<image :src="BASE_IMG_URL+'chaoshi.png'"></image>
</view>
<view class="item_con">
<view>超时任务</view>
<view>{{info && info.task.msg}}</view>
</view>
<view class="item_messnum">
<view class="message_num" v-if="info && info.task.count != 0">{{info.task.count}}</view>
<view class="iconfont icon-arrows_right"></view>
</view>
</view>
<view class="news_item" @click="toApproveManage">
<view class="item_img">
<image :src="BASE_IMG_URL+'shenpi333.png'"></image>
</view>
<view class="item_con">
<view>审批管理</view>
<view>{{info && info.examine.msg}}</view>
</view>
<view class="item_messnum">
<view class="message_num" v-if="info && info.examine.count != 0">{{info.examine.count}}</view>
<view class="iconfont icon-arrows_right"></view>
</view>
</view>
<!-- 底部导航 -->
<uniTabbar v-if="tipNumber || tipNumber==0" :tipNumber="tipNumber"></uniTabbar>
</view>
</template>
<script>
import uniTabbar from '@/components/tabbar/tabbar.vue'
import { pageJumps} from "./news_page_jumps.js";
import { netAgentList } from '@/api/clues.js'
import { BASE_IMG_URL } from '@/util/api.js'
export default {
mixins: [pageJumps],
components:{
uniTabbar
},
data() {
return {
info:null,
BASE_IMG_URL:BASE_IMG_URL,
tipNumber:null
}
},
onShow() {
this.getList()
},
onReachBottom() {
if(this.page >= this.totalPage) {
return
}
this.page ++
this.getList()
},
methods: {
getList() {
netAgentList().then(res=>{
uni.setStorageSync('token',res.data.userinfo.token)
uni.setStorageSync('roleType',res.data.userinfo.role_type)
uni.setStorageSync('rules',res.data.userinfo.rules)
this.info = res.data
this.tipNumber = res.data.total
})
},
//
toLookList(type) {
uni.navigateTo({
url:'/pages/index/dataList?type='+type
})
},
//
toApproveManage() {
uni.navigateTo({
url:'/pagesA/work/approvelManage/index'
})
}
}
}
</script>
<style scoped lang="scss">
.news {
.news_item {
background-color: #fff;
display: flex;
border: 1rpx solid #EAEAEA;
padding:20rpx;
align-items: center;
.item_img {
width: 100rpx;
image {
width: 80rpx;
height: 80rpx;
}
}
.item_con {
flex: 1;
:first-child {
padding: 15rpx 0;
font-size: 28rpx;
}
:last-child {
padding-bottom: 20rpx;
color: #999;
font-size: 24rpx;
}
}
.item_messnum {
display: flex;
.message_num {
height: 40rpx;
line-height: 40rpx;
padding: 0 18rpx;
border-radius: 20rpx;
background-color: #f95e5a;
color: #fff;
}
.icon-arrows_right {
margin-top: -1rpx;
font-size: 38rpx;
}
}
}
}
</style>

View File

@ -0,0 +1,48 @@
import Vue from 'vue'
export const pageJumps = {
methods:{
//公告
affiche(){
uni.navigateTo({
url: '/pages/news/notice',
})
},
//提醒通知
remind(){
uni.navigateTo({
url: '/pages/news/theReminder/theReminder',
})
},
//待办
jumpDeal() {
uni.navigateTo({
url:'/pagesA/profile/needDeal'
})
},
//工作动态
workTrend(){
uni.navigateTo({
url: '/pages/index/workNews',
})
},
//日程
agendar(){
uni.navigateTo({
url: '/pages/index/schedule/schedule',
})
},
schedule(){
uni.navigateTo({
url: '/pagesA/profile/needDeal',
})
},
task(){
uni.showToast({
title: "超时任务设计页面出错,无法跳转",
icon: "none",
duration: 1000
})
}
}
}

106
pages/news/notice.vue Normal file
View File

@ -0,0 +1,106 @@
<template>
<view class="the_reminder">
<view class="reminder_item" v-for="(item,index) in list" :key="index" @click="toDetail(item.id)">
<view class="name" style="display: -webkit-box;
width: 300rpx;
overflow: hidden;
text-overflow: ellipsis;
word-wrap: break-word;
white-space: normal !important;
-webkit-line-clamp: 1;
-webkit-box-orient: vertical;">{{item.title}}</view>
<view>
<view class="time" style="float: left;margin-right: 10rpx;">{{item.createtime}}</view>
</view>
</view>
<view style="height: 200rpx;"></view>
<u-empty v-if="list.length == 0" text="暂无更多"></u-empty>
</view>
</template>
<script>
import { netNoticeList } from '@/api/clues.js'
export default {
data() {
return {
page:1,
limit:10,
totalPage:1,
list:[]
}
},
onShow() {
this.page = 1
this.list = []
this.getList()
},
onReachBottom() {
if(this.page >= this.totalPage){
return
}
this.page ++
this.getList()
},
methods: {
getList() {
let params = {
page: this.page,
limit: this.limit
}
netNoticeList(params).then(res=>{
this.list = this.list.concat(res.data.data)
this.totalPage = res.data.last_page
})
},
toDetail(id) {
uni.navigateTo({
url:'/pages/news/noticeDetail?id='+id
})
}
}
}
</script>
<style lang="scss" scoped>
.color{
background: #fff;
}
.colore{
background: #f00;
}
.the_reminder {
padding: 0 20rpx 100rpx;
.reminder_item {
background-color: #fff;
border-radius: 10rpx;
padding:30rpx;
margin-top:24rpx;
display: flex;
justify-content: space-between;
align-items: center;
.name{
font-size:26rpx;
color:#333333;
}
.time{
font-size:24rpx;
color:#999999;
}
}
}
.lxs_time{
padding-left: 5px;
padding-top: 1px;
}
.message_num {
width: 10rpx;
height: 10rpx;
// line-height: 10rpx;
border-radius: 20rpx;
// background-color: #f95e5a;
color: #fff;
float: right;
}
</style>

View File

@ -0,0 +1,60 @@
<template>
<view class="warp">
<view class="content title">
标题{{info.title}}
</view>
<view class="content time">
时间{{info.createtime}}
</view>
<view class="content">
内容
</view>
<view class="content" v-html="info.content"></view>
</view>
</template>
<script>
import { netNoticeDetail } from '@/api/clues.js'
export default{
data() {
return {
info:{},
id:''
}
},
onLoad(options) {
this.id = options.id
},
onShow() {
this.getDetail()
},
methods:{
getDetail() {
netNoticeDetail({id:this.id}).then(res=>{
this.info = res.data
})
}
}
}
</script>
<style lang="scss" scoped>
.warp{
padding:20rpx 24rpx;
background:#fff;
.content{
font-size:28rpx;
color:#666;
line-height: 45rpx;
width:100%;
}
.title{
font-size:32rpx;
color:#333;
}
.time{
color:#999;
font-size:26rpx;
}
}
</style>

View File

@ -0,0 +1,240 @@
<template>
<view class="the_reminder">
<view class="reminder_item" v-for="(item,index) in list" :key="index" @click="jumpDetail(item)">
<view class="item_con">
<view class="item_left">
<view class="iconfont icon-task"></view>
<view>{{item.content}}</view>
</view>
<view class="circle_dot" v-if="item.status == 0"></view>
</view>
<view class="item_time">
<view class="iconfont icon-clock"></view>
<view class="lxs_time">{{item.send_time}}</view>
</view>
</view>
<view style="height: 200rpx;"></view>
<u-empty v-if="list.length == 0" text="暂无更多"></u-empty>
</view>
</template>
<script>
import { netMessageList } from '@/api/clues.js'
export default {
data() {
return {
page:1,
limit:10,
totalPage:1,
list:[]
}
},
onShow() {
this.page = 1
this.list = []
this.getList()
},
onReachBottom() {
if(this.page >= this.totalPage){
return
}
this.page ++
this.getList()
},
methods: {
getList() {
let params = {
page: this.page,
limit: this.limit
}
netMessageList(params).then(res=>{
this.list = this.list.concat(res.data.data)
this.totalPage = res.data.last_page
})
},
//
jumpDetail(item) {
if(item.relation_type == 'examine'){
//
if(item.examine.relation_type == 'consume'){
//
let id = item.examine.relation_id
uni.navigateTo({
url: '/pages/index/groupCompany/cost/costDetail?id='+id
})
}else if(item.examine.relation_type == 'contract'){
//
let id = item.examine.relation_id
uni.navigateTo({
url: '/pagesB/contract/contractDetail?id=' + id
})
}else if(item.examine.relation_type == 'receivables'){
//
let id = item.examine.relation_id
uni.navigateTo({
url: '/pagesB/contract/paymentDetail?id='+id
})
}else if(item.examine.relation_type == 'achievement'){
//
let id = item.examine.relation_id
uni.navigateTo({
url: '/pagesA/crm/salesTarget/history_detail?id='+id
})
}else if(item.examine.relation_type == 'approval'){
let id = item.examine.relation_id
uni.navigateTo({
url:'/pagesA/work/approve/approveDetail?id='+id
})
}else if(item.examine.relation_type == 'leave'){
//
let id = item.examine.relation_id
uni.navigateTo({
url:'/pagesA/punchclock/leave/detail?id='+id
})
}else if(item.examine.relation_type == 'card'){
//
let id = item.examine.relation_id
uni.navigateTo({
url:'/pagesA/punchclock/card/detail?id='+id
})
}
}else if(item.relation_type == 'consume'){
//
let id = item.relation_id
uni.navigateTo({
url: '/pages/index/groupCompany/cost/costDetail?id='+id
})
}else if(item.relation_type == 'record'){
//
let id = item.relation_id
uni.navigateTo({
url:'/pagesA/crm/cluesManagement/followUpDetail/followUpDetail?id='+id,
})
}else if(item.relation_type == 'contract'){
//
let id = item.relation_id
uni.navigateTo({
url: '/pagesB/contract/contractDetail?id=' + id
})
}else if(item.relation_type == 'plan') {
//
let id = item.relation_id
uni.navigateTo({
url: '/pagesB/contract/contractDetail?id=' + id
})
}else if(item.relation_type == 'receivables') {
//
let id = item.relation_id
uni.navigateTo({
url: '/pagesB/contract/paymentDetail?id='+id
})
}else if(item.relation_type == 'event') {
//
let id = item.relation_id
uni.navigateTo({
url:'/pages/index/dataList?type=2'
})
}else if(item.relation_type == 'customer') {
//
let id = item.relation_id
uni.navigateTo({
url: '/pages/index/groupCompany/groupCompany?id='+id
})
}else if(item.relation_type == 'sign') {
//
let id = item.relation_id
uni.navigateTo({
url: '/pages/signin/signin'
})
}else if(item.relation_type == 'achievement'){
//
let id = item.relation_id
uni.navigateTo({
url: '/pagesA/crm/salesTarget/history_detail?id='+id
})
}else if(item.relation_type == 'daily'){
//
let id = item.relation_id
uni.navigateTo({
url:'/pageB/workreport/workDetail?id='+id
})
}else if(item.relation_type == 'notice'){
//
let id = item.relation_id
uni.navigateTo({
url:'/pages/news/noticeDetail?id='+id
})
}else if(item.relation_type == 'approval'){
//
let id = item.relation_id
uni.navigateTo({
url:'/pagesA/work/approve/approveDetail?id='+id
})
}else if(item.relation_type == 'leave'){
//
let id = item.relation_id
uni.navigateTo({
url:'/pagesA/punchclock/leave/detail?id='+id
})
}else if(item.relation_type == 'card'){
//
let id = item.relation_id
uni.navigateTo({
url:'/pagesA/punchclock/card/detail?id='+id
})
}
}
}
}
</script>
<style lang="scss" scoped>
.the_reminder {
padding: 40rpx 20rpx 100rpx;
.reminder_item {
background-color: #fff;
border-radius: 10rpx;
padding: 0 30rpx;
margin-bottom: 20rpx;
.item_con {
display: flex;
padding: 20rpx 0;
justify-content: space-between;
.item_left{
display: flex;
justify-content: flex-start;
}
.icon-task {
padding-right: 20rpx;
}
.circle_dot {
width: 12rpx;
height: 12rpx;
background-color: #fb6260;
margin: 11rpx 0 0 80rpx;
border-radius: 10rpx;
}
}
.item_time {
display: flex;
align-items: center;
padding-bottom: 20rpx;
color: #999;
:last-child {
margin-top: 5rpx;
}
}
}
}
.lxs_time{
padding-left: 5px;
padding-top: 1px;
}
</style>

572
pages/profile/profile.vue Normal file
View File

@ -0,0 +1,572 @@
<template>
<view class="profile">
<!-- 个人信息 -->
<view class="profile_info" >
<view class="infoleft">
<view class="info_img">
<image :src="userInfo.img ? userInfo.img :BASE_IMG_URL+'headImg.png'" mode="scaleToFill"></image>
</view>
<view class="info_con">
<view>{{userInfo.name}}<text>{{userInfo.post?userInfo.post:''}}</text></view>
<view>{{userInfo.mobile}}</view>
</view>
</view>
<image :src="BASE_IMG_URL+'lxr_set.svg'" @click="toSet" class="rightimg" ></image>
</view>
<view class="warpbox">
<view class="fun_box_fir">
<view class="fun_fir_1" @click="remind">
<view class="fun_tip" v-if="info && info.leads && info.leads.count != 0">{{info && info.leads.count}}</view>
<image :src="BASE_IMG_URL+'index_new_22.svg'" mode="scaleToFill"></image>
<view>通知</view>
</view>
<view class="fun_fir_1" @click="jumpDeal">
<view class="fun_tip" v-if="info && info.agent && info.agent.count != 0">{{info && info.agent.count}}</view>
<image :src="BASE_IMG_URL+'index_new_23.svg'" mode="scaleToFill"></image>
<view>待办</view>
</view>
<view class="fun_fir_1" @click="toApproveManage">
<view class="fun_tip" v-if="info && info.examine && info.examine.count != 0">{{info && info.examine.count}}</view>
<image :src="BASE_IMG_URL+'index_new_7.png'" mode="scaleToFill"></image>
<view>审批</view>
</view>
</view>
</view>
<!-- 在线联系 -->
<view class="link_box" v-if="false">
<view class="link_left">
<image src="/static/kefu.jpg" class="logoimg" mode="scaleToFill"></image>
<view class="link_cen">
<view class="label">在线咨询</view>
<view class="text">添加客服进行咨询</view>
</view>
</view>
<view class="link_btn" @click="toCopy">复制微信号</view>
</view>
<view class="warpbox">
<view class="warptitle">客户管理</view>
<view class="fun_box">
<view class="fun_fir" @click="toWaterCustomer">
<image :src="BASE_IMG_URL+'index_new_24.svg'" mode="scaleToFill"></image>
<view>公海客户</view>
</view>
<view class="fun_fir" @click="toIndexClue">
<image :src="BASE_IMG_URL+'index_new_26.svg'" mode="scaleToFill"></image>
<view>线索</view>
</view>
<view class="fun_fir" @click="toIndexCustomer">
<image :src="BASE_IMG_URL+'index_new_25.svg'" mode="scaleToFill"></image>
<view>客户</view>
</view>
<view class="fun_fir" @click="toIndexContract">
<image :src="BASE_IMG_URL+'index_new_5.png'" mode="scaleToFill"></image>
<view>合同</view>
</view>
<view class="fun_fir" @click="toNears">
<image :src="BASE_IMG_URL+'index_new_9.png'" mode="scaleToFill"></image>
<view>附近客户</view>
</view>
<view class="fun_fir" @click="toProductList">
<image :src="BASE_IMG_URL+'index_new_11.png'" mode="scaleToFill"></image>
<view>产品</view>
</view>
</view>
</view>
<view class="warpbox">
<view class="warptitle">办公</view>
<view class="fun_box">
<view class="fun_fir" @click="workreport">
<image :src="BASE_IMG_URL+'index_new_12.png'" mode="scaleToFill"></image>
<view>工作报告</view>
</view>
<view class="fun_fir" @click="affiche">
<image :src="BASE_IMG_URL+'index_new_19.png'" mode="scaleToFill"></image>
<view>公告</view>
</view>
<view class="fun_fir" @click="toIndexRecord">
<image :src="BASE_IMG_URL+'index_new_7.png'" mode="scaleToFill"></image>
<view>跟进记录</view>
</view>
<view class="fun_fir" @click="jumpSign">
<image :src="BASE_IMG_URL+'index_new_12.png'" mode="scaleToFill"></image>
<view>签到记录</view>
</view>
<view class="fun_fir" @click="toClientele">
<image :src="BASE_IMG_URL+'index_new_21.svg'" mode="scaleToFill"></image>
<view>重点关注</view>
</view>
<view class="fun_fir" @click="agendar">
<image :src="BASE_IMG_URL+'index_new_17.png'" mode="scaleToFill"></image>
<view>日程</view>
</view>
<view class="fun_fir" @click="approve">
<image :src="BASE_IMG_URL+'index_new_20.png'" mode="scaleToFill"></image>
<view>办公</view>
</view>
</view>
</view>
<view class="warpbox">
<view class="warptitle">财务</view>
<view class="fun_box">
<view class="fun_fir" @click="toPayPlan">
<image :src="BASE_IMG_URL+'index_new_18.png'" mode="scaleToFill"></image>
<view>回款计划</view>
</view>
<view class="fun_fir" @click="toPayment">
<image :src="BASE_IMG_URL+'index_new_23.svg'" mode="scaleToFill"></image>
<view>回款单</view>
</view>
<view class="fun_fir" @click="toCostList">
<image :src="BASE_IMG_URL+'feiyong1.png'" mode="scaleToFill"></image>
<view>费用管理</view>
</view>
</view>
</view>
<view class="warpbox">
<view class="warptitle">统计</view>
<view class="fun_box">
<!-- <view class="fun_fir" @click="toReturnedMoney">
<image :src="BASE_IMG_URL+'index_new_6.png'" mode="scaleToFill"></image>
<view>回款统计</view>
</view> -->
<view class="fun_fir" @click="achievementObjectClick">
<image :src="BASE_IMG_URL+'index_new_8.png'" mode="scaleToFill"></image>
<view>业绩完成度</view>
</view>
<view class="fun_fir" @click="collectClick">
<image :src="BASE_IMG_URL+'index_new_11.png'" mode="scaleToFill"></image>
<view>销售简报</view>
</view>
<view class="fun_fir" @click="achieveRank">
<image :src="BASE_IMG_URL+'index_new_10.png'" mode="scaleToFill"></image>
<view>排行榜</view>
</view>
</view>
</view>
<view class="warpbox" v-if="roleType == 1 || roleType == 2">
<view class="warptitle">管理</view>
<view class="fun_box">
<view class="fun_fir" @click="jumpStaffList" v-if="roleType == 1 || roleType == 2">
<image :src="BASE_IMG_URL+'index_new_23.svg'" mode="scaleToFill"></image>
<view>员工列表</view>
</view>
<view class="fun_fir" @click="toTarget">
<image :src="BASE_IMG_URL+'index_new_7.png'" mode="scaleToFill"></image>
<view>业绩目标</view>
</view>
</view>
</view>
<view class="warpbox">
<view class="warptitle">帮助中心</view>
<view class="fun_box">
<view class="fun_fir" @click="toPushNews">
<image :src="BASE_IMG_URL+'tixing.png'" mode="scaleToFill"></image>
<view class="tabtext">消息推送</view>
</view>
</view>
</view>
<!-- 底部导航 -->
<uniTabbar v-if="tipNumber || tipNumber==0" :tipNumber="tipNumber"></uniTabbar>
<!-- 消息推送 -->
<uni-popup ref="smsPop" type="center">
<view class="ewmbox">
<!-- <view class="close" @click="toCloseSms" ></view> -->
<image src="@/static/gongzhonghao.jpg" show-menu-by-longpress class="ewmSelf" mode=""></image>
<view class="ewmtext">长按识别二维码关注公众号</view>
</view>
</uni-popup>
</view>
</template>
<script>
import uniTabbar from '@/components/tabbar/tabbar.vue'
import {pageJumps} from "./profile_page_iumps.js";
import { netGetUserInfo } from '@/api/index.js'
import { netAgentList } from '@/api/clues.js'
import { BASE_IMG_URL } from '@/util/api.js'
import * as crmjs from "@/pagesA/crm/crm_page_jumps.js";
import * as newsjs from "@/pages/news/news_page_jumps.js";
export default {
mixins:[pageJumps,crmjs.pageJumps,crmjs.statisticalPageJumps,newsjs.pageJumps],
components:{
uniTabbar
},
data() {
return {
userInfo:{},
roleType:1,
rules:[],
tipNumber:null,
BASE_IMG_URL:BASE_IMG_URL,
info:{},
configInfo:{}
}
},
onShow() {
this.roleType = uni.getStorageSync('roleType')
this.rules = uni.getStorageSync('rules')
this.getTip()
},
methods: {
getTip(){
netAgentList().then(res=>{
uni.setStorageSync('token',res.data.userinfo.token)
uni.setStorageSync('roleType',res.data.userinfo.role_type)
uni.setStorageSync('rules',res.data.userinfo.rules)
this.info = res.data
this.tipNumber = res.data.total
this.getInfo()
})
},
getInfo() {
netGetUserInfo().then(res=>{
this.userInfo = res.data
})
},
//
toProductList() {
uni.navigateTo({
url:'/pagesA/product/index'
})
},
//
jumpStaffList() {
uni.navigateTo({
url:'/pagesA/profile/staff/stafflist/index'
})
},
//
jumpExamineStaff() {
uni.navigateTo({
url:'/pagesA/profile/staff/examinestaff/index'
})
},
//
toEnterprise(id) {
console.log(id,'id')
uni.navigateTo({
url: '/pagesA/profile/enterpriseInfo/enterpriseInfo?id?' +id
})
},
//
toSet(){
uni.navigateTo({
url:'/pagesA/profile/set'
})
},
//
toPayment() {
uni.navigateTo({
url:'/pagesA/payment/index'
})
},
toPayPlan() {
uni.navigateTo({
url:'/pagesA/payplan/index'
})
},
//
toCostList() {
uni.navigateTo({
url:'/pagesA/cost/index'
})
},
//
toApproveManage() {
uni.navigateTo({
url:'/pagesA/work/approvelManage/index'
})
},
//
toTarget() {
if (this.roleType == 2 && (this.rules.indexOf('all') != -1 || this.rules.indexOf('2') != -1)) {
uni.navigateTo({
url: '/pagesA/crm/salesTarget/salesTarget',
})
} else {
uni.navigateTo({
url: '/pagesA/crm/salesTarget/myTarget',
})
}
},
//
achieveRank() {
uni.navigateTo({
url:'/pagesA/crm/statisticalFrom/achieveRank'
})
},
//
toCopy() {
uni.setClipboardData({
data:'lcq406337111',
success:(res)=>{
uni.showToast({
title:'微信号已复制',
icon:'none'
})
},
fail:(err)=>{
}
})
},
//
toPushNews() {
this.$refs.smsPop.open()
},
toCloseSms() {
this.$refs.smsPop.close()
},
}
}
</script>
<style lang="scss" scoped>
.buttonBtn{
display: inline-block;
border:none;
margin:0;
padding:0;
line-height: 50rpx;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
&::after{
border:none;
}
}
.ewmbox{
width:620rpx;
background:#fff;
border-radius: 10rpx;
padding:30rpx;
position: relative;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
.icon-cuo{
font-size: 40rpx;
position: absolute;
right:30rpx;
top:30rpx;
color:#666;
}
.ewmSelf{
width:500rpx;
}
.ewmtext{
font-size:24rpx;
color:#666;
margin-top:30rpx;
}
}
// 线
.link_box{
width:702rpx;
box-sizing: border-box;
background:#fff;
border-radius: 20rpx;
margin:0 auto 30rpx;
padding:30rpx;
box-shadow: 1rpx 1rpx 10rpx rgba(0,0,0,0.1);
display: flex;
justify-content: space-between;
align-items: center;
.link_left{
display: flex;
justify-content: flex-start;
align-items: center;
.logoimg{
width:140rpx;
height:140rpx;
margin-right:24rpx;
}
.link_cen{
.label{
font-size:28rpx;
color:#333;
}
.text{
font-size:26rpx;
color:#999;
margin-top:10rpx;
}
}
}
.link_btn{
width:160rpx;
height:60rpx;
border-radius: 30rpx;
background:$uni-text-color;
color:#fff;
text-align: center;
line-height: 60rpx;
font-size:24rpx;
}
}
.fun_box_fir{
display: flex;
justify-content: space-around;
align-items: center;
.fun_fir_1{
flex-shrink: 0;
background:#fff;
border-radius: 10rpx;
text-align: center;
width:142rpx;
height:115rpx;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
font-size:24rpx;
color:#000;
position: relative;
.fun_tip{
position: absolute;
right:15rpx;
top:-10rpx;
background:#F13E27;
color:#fff;
font-size:26rpx;
width:40rpx;
height:40rpx;
border-radius: 50%;
text-align: center;
line-height: 40rpx;
z-index:2;
}
image{
width:50rpx;
height:50rpx;
margin-bottom:15rpx;
}
}
}
.message_num {
width: 20rpx;
height: 20rpx;
border-radius: 20rpx;
color: #fff;
position: relative;
top: 0;
right: 0;
}
.color{
background: #fff;
}
.colore{
background: #f00;
}
.warpbox{
width:702rpx;
box-sizing: border-box;
background:#fff;
border-radius: 20rpx;
margin:0 auto 30rpx;
padding:30rpx;
box-shadow: 1rpx 1rpx 10rpx rgba(0,0,0,0.1);
.warptitle{
font-size:26rpx;
color:#333;
margin-bottom:30rpx;
}
.fun_box{
display: flex;
justify-content: flex-start;
align-items: center;
flex-wrap:wrap;
.fun_fir{
flex-shrink: 0;
background:#fff;
border-radius: 10rpx;
text-align: center;
width:142rpx;
height:115rpx;
margin-right:24rpx;
margin-bottom:24rpx;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
font-size:24rpx;
color:#000;
&:nth-child(4n){
margin-right:0;
}
image{
width:50rpx;
height:50rpx;
margin-bottom:15rpx;
}
}
}
}
.profile {
//
.profile_info {
background-color: #fff;
display: flex;
padding: 50rpx;
border-bottom: 1rpx solid #EAEAEA;
margin-bottom: 30rpx;
display: flex;
justify-content: space-between;
align-items: center;
.infoleft{
display: flex;
justify-content: flex-start;
align-items: center;
.info_img {
width: 150rpx;
image {
width: 120rpx;
height: 120rpx;
border-radius: 50%;
}
}
}
.info_con {
flex: 1;
margin-top: 20rpx;
:first-child {
font-size: 28rpx;
margin-bottom: 15rpx;
}
text {
font-size: 24rpx;
margin-left: 10rpx;
color: #999;
}
:last-child {
color: #999;
}
}
.rightimg{
width:40rpx;
height:40rpx;
}
}
}
.iconfont{
padding-top: 4px;
}
.lxs_font{
font-size: 14px;
}
</style>

View File

@ -0,0 +1,64 @@
export const pageJumps = {
methods: {
//待办
jumpDeal() {
uni.navigateTo({
url:'/pagesA/profile/needDeal'
})
},
// 重点关注
toClientele() {
uni.navigateTo({
url: '/pagesA/profile/mySet/keyFocus/keyFocus'
})
},
//公告
affiche(){
uni.navigateTo({
url: '/pages/news/notice',
})
},
//签到 记录
jumpSign() {
uni.navigateTo({
url:'/pages/signin/signin'
})
},
//审批
remind(){
uni.navigateTo({
url: '/pages/news/theReminder/theReminder',
})
},
//出差 签到
addChuchai() {
uni.navigateTo({
url:'/pagesA/signin/busSign'
})
},
//工作 报告
workreport() {
uni.navigateTo({
url:'/pages/workreport/list'
})
},
// 意见反馈
toIdea() {
uni.navigateTo({
url: '/pagesA/profile/feedback/feedback'
})
},
// 关于
toAboutApp() {
uni.navigateTo({
url: '/pagesA/profile/about/about'
})
},
//办公
approve() {
uni.navigateTo({
url:'/pagesA/work/approve/index'
})
}
}
}

309
pages/public/login.vue Normal file
View File

@ -0,0 +1,309 @@
<template>
<view class="container">
<view class="wrapper">
<!-- logo -->
<view class="titbox">
<view class="firtit">{{info.mobile_name}}</view>
<view class="sectit">实现线索到回款全流程管理</view>
</view>
<!-- 表单 -->
<view class="login-box">
<view class="input-item">
<view class="itemtit">手机号</view>
<view class="itembot">
<image class="phoneimg" :src="BASE_IMG_URL+'phone1.png'" mode=""></image>
<input
type="text"
placeholder="请输入账号"
placeholderStyle="color:#999;font-size:30rpx"
class="inp"
v-model="account"
>
</view>
</view>
<view class="input-item">
<view class="itemtit">密码</view>
<view class="itembot">
<image class="suoimg" :src="BASE_IMG_URL+'suo1.png'" mode=""></image>
<input class="inp" v-model="password" v-if="!showPassword" type="text" password placeholder="请输入密码" placeholder-class="pl" />
<input class="inp" v-model="password" v-if="showPassword" type="text" placeholder="请输入密码" placeholder-class="pl" />
<image :src="BASE_IMG_URL+'nosee1.png'" v-if="!showPassword" @click="showPassword = true" class="eayimg" mode=""></image>
<image :src="BASE_IMG_URL+'see1.png'" v-if="showPassword" @click="showPassword = false" class="eayimg" mode=""></image>
</view>
</view>
</view>
<!-- 登录按钮 -->
<view class="btn_g" @tap="toLogin">登录</view>
<!-- <view class="freelogin" @click="freeLogin">暂不登录进行演示</view> -->
</view>
<!-- <view class="priva_w">
<radio value="" color="#008EFF" @click.stop="selectAgree" :checked="readAndagree"/>请阅读并同意 <text @click.stop="showPrivacy = true">隐私政策</text>
</view>
<web-view src="https://testcrm.qingdong.vip/privacy.html" v-if="showPrivacy"></web-view> -->
<!-- 需要用户阅读 并同意隐私协议 -->
<uni-popup ref="privacyPopup" type="bottom" :safe-area="false" @touchmove.stop.prevent>
<view class="privacy_mask">
<view class="privacy_box">
<view class="priva_tit">隐私政策提示</view>
<view class="priva_tip">欢迎使用CRM客户管理软件</view>
<view class="priva_con">
我们将通过 <text @click="toOpenPrivacy">隐私政策</text> 帮助您了解我们收集使用存储和共享个人信息的情况
未经您的单独同意我们不会主动向任何第三方共享您的个人信息
当您使用一些功能服务时我们可能会在获得您的明示同意后
从授权第三方处获取世章或向其提供信息
</view>
<button open-type="agreePrivacyAuthorization" @agreeprivacyauthorization="handleAgreePrivacyAuthorization" class="agreebtn">同意并继续</button>
<view class="noagree">
<text @click="closePop">不同意</text>
</view>
</view>
</view>
</uni-popup>
</view>
</template>
<script>
import {
BASE_IMG_URL,
SIGN_NO
} from '@/util/api.js'
import { netNewLogin, defaultInfo, netlogin_text } from '@/api/login'
export default {
data() {
return {
BASE_IMG_URL:BASE_IMG_URL,
account:'',
showPassword:false,
password:'',
info:{},
showPrivacy:false,
readAndagree:false,
isAgreePrivacy:false, //
};
},
onShow() {
//
this.getDefInfo()
// #ifdef MP-WEIXIN
this.handlePrivacyStatus()
// #endif
},
methods: {
///////////////////////
//
handlePrivacyStatus() {
wx.getPrivacySetting({
success:(res)=>{
console.log(res,'000000')
if (res.needAuthorization){
//
this.$refs.privacyPopup.open()
this.isAgreePrivacy = true
}else{
//
this.isAgreePrivacy = false
}
}
})
},
toOpenPrivacy() {
wx.openPrivacyContract({})
},
handleAgreePrivacyAuthorization() {
this.isAgreePrivacy = false
this.$refs.privacyPopup.close()
},
showPrivacyPop() {
this.$refs.privacyPopup.open()
},
closePop() {
this.$refs.privacyPopup.close()
},
////////////////////////////
selectAgree() {
this.readAndagree = !this.readAndagree
},
getDefInfo() {
defaultInfo().then(res=>{
this.info = res.data
uni.setStorageSync('mapKey',res.data.map_key)
uni.setStorageSync('appid',res.data.appid)
uni.setStorageSync('NAME',res.data.mobile_name)
})
},
jump(path, query) {
this.$Router.push({
path: path,
query: query
});
},
toLogin() {
if(this.isAgreePrivacy){
this.$refs.privacyPopup.open()
return
}
if(!this.account){
uni.showToast({
title:'请填写账号',
icon:'none'
})
return
}
if(!this.password){
uni.showToast({
title:'请填写密码',
icon:'none'
})
return
}
// if(!this.readAndagree){
// uni.showToast({
// title:'',
// icon:'none'
// })
// return
// }
let params = {
account:this.account,
password:this.password
}
netNewLogin(params).then(res=>{
this.jumpPage(res)
})
},
//
freeLogin() {
if(this.isAgreePrivacy){
this.$refs.privacyPopup.open()
return
}
// if(!this.readAndagree){
// uni.showToast({
// title:'',
// icon:'none'
// })
// return
// }
netlogin_text().then(res=>{
this.jumpPage(res)
})
},
jumpPage(res){
uni.setStorageSync('userinfo',res.data.userinfo)
uni.setStorageSync('token',res.data.userinfo.token)
uni.redirectTo({
url:'/pages/index/index'
})
}
}
};
</script>
<style lang="scss">
.priva_w{
display: flex;
justify-content: center;
align-items: center;
font-size:24rpx;
margin-top:80rpx;
color:#999;
radio{
transform: scale(0.7);
}
text{
color:$uni-text-color;
}
}
.freelogin{
text-align: center;
font-size:24rpx;
color:red;
margin-top:60rpx;
}
.wrapper {
padding-bottom: 40upx;
width: 100%;
margin-top:100rpx;
.titbox{
padding:40rpx 0 50rpx;
.firtit{
font-size:48rpx;
color:$uni-text-color;
font-weight: bold;
text-align: center;
}
.sectit{
font-size:32rpx;
color:#999999;
margin-top:30rpx;
text-align: center;
}
}
//
.login-box {
margin:0 auto 100rpx;
.input-item {
padding:26rpx 30rpx;
border-bottom: 1rpx solid #c7c7c7;
width: 630rpx;
margin:0 auto 50rpx;
.itemtit{
font-size:30rpx;
color:#666666;
margin-bottom:50rpx;
}
.itembot{
display: flex;
justify-content: flex-start;
align-items: center;
}
.phoneimg{
width:41rpx;
height:40rpx;
}
.suoimg{
width:40rpx;
height:44rpx;
}
.inp {
width:460rpx;
margin-left:30rpx;
font-size: 28rpx;
}
.pl {
font-size:30rpx;
color: #999999;
}
.eayimg{
margin-left:30rpx;
width:33rpx;
height:33rpx;
}
}
}
.li_box{
margin:40rpx auto 0;
width:690rpx;
display: flex;
justify-content: space-between;
align-items: center;
padding:0 30rpx;
font-weight: 700;
.register{
font-size:26rpx;
color:#333333;
}
.forgot{
font-size:26rpx;
color:#333333;
}
}
//
}
</style>

197
pages/signin/signin.vue Normal file
View File

@ -0,0 +1,197 @@
<template>
<view>
<view class="tab_list">
<view class="tabli" :class="type == 0 ? 'tabliactive' : ''" @click="changeFirTab(0)">全部</view>
<view class="tabli" :class="type == 1 ? 'tabliactive' : ''" @click="changeFirTab(1)">我创建的</view>
<view class="tabli" :class="type == 2 ? 'tabliactive' : ''" @click="changeFirTab(2)">下属创建的</view>
</view>
<view class="signli" v-for="item in list" :key="item.id" @click="toSigndetail(item)">
<view class="signtop">
<image :src=" item.staff.img ? item.staff.img : BASE_IMG_URL+'headImg.png'" class="headimg" mode="scaleToFill"></image>
<view class="info">
<view class="infotop">
<view class="name">{{item.staff?item.staff.name:''}}</view>
<view class="time">{{item.createtime}}</view>
</view>
<view class="address">{{item.location}}</view>
</view>
</view>
<view class="kehu">
<view>拜访客户</view>
<view class="kehuinfo" @click="toMore(item.customer)">
{{item.customer?item.customer.name:''}}
</view>
</view>
</view>
<view style="height: 50rpx;"></view>
<view class="noData" v-if="list.length == 0">暂无更多</view>
<!-- 新增 -->
<view class="icon_creat" @click="addChuchai">
<image :src="BASE_IMG_URL+'1.png'" mode="scaleToFill"></image>
</view>
</view>
</template>
<script>
import { netGetSignList } from '@/api/index.js'
import { BASE_IMG_URL } from '@/util/api.js'
export default{
data() {
return {
list:[],
page:1,
totalPage:1,
BASE_IMG_URL:BASE_IMG_URL,
type:0, //0 1 2
}
},
onShow() {
this.init()
},
onReachBottom() {
if(this.page < this.totalPage){
this.page ++
this.getList()
}
},
methods:{
changeFirTab(type) {
this.type = type
this.init()
},
init() {
this.page = 1
this.list = []
this.getList()
},
getList() {
let params = {
type:this.type,
page:this.page
}
netGetSignList(params).then(res=>{
this.list = this.list.concat(res.data.data)
this.totalPage = res.data.last_page
})
},
toPrevieimg(files) {
uni.previewImage({
urls: files
})
},
toMore(obj) {
uni.navigateTo({
url: '/pages/index/groupCompany/groupCompany?id='+obj.id
})
},
//
addChuchai() {
uni.navigateTo({
url:'/pagesA/signin/busSign'
})
},
//
toSigndetail(item) {
uni.navigateTo({
url:'/pagesA/signin/signDetail?id='+item.id
})
}
}
}
</script>
<style lang="scss" scoped>
.tab_list{
width:750rpx;
height:80rpx;
display: flex;
justify-content: space-around;
align-items: center;
background:#fff;
margin-bottom:24rpx;
.tabli{
font-size:24rpx;
color:#333;
line-height: 75rpx;
text-align: center;
border-bottom:4rpx solid #fff;
}
.tabliactive{
border-bottom:4rpx solid $uni-text-color;
}
}
.signli{
padding:30rpx;
background:#fff;
border-radius: 10rpx;
margin-bottom:20rpx;
.signtop{
display: flex;
justify-content: flex-start;
align-items: center;
margin-bottom:24rpx;
.headimg{
width:80rpx;
height:80rpx;
border-radius: 50%;
}
.info{
margin-left:15rpx;
.infotop{
display: flex;
justify-content: flex-start;
align-items: center;
.name{
font-size:26rpx;
color:#333;
}
.time{
font-size:24rpx;
color:#999;
margin-left:10rpx;
}
}
.address{
font-size:24rpx;
color:#666;
margin-top:15rpx;
}
}
}
.remark{
padding:20rpx;
font-size:24rpx;
line-height: 32rpx;
}
.kehu{
display: flex;
justify-content: flex-start;
align-items: center;
font-size:24rpx;
padding:0 20rpx;
color:#666;
.kehuinfo{
font-size:24rpx;
color:$uni-text-color;
}
}
}
.fujian{
font-size:24rpx;
color:#333;
padding:0 20rpx;
margin-top:20rpx;
.imgbox{
display: flex;
justify-content: flex-start;
align-items: center;
margin-top:15rpx;
}
.fujianimg{
width:120rpx;
height:120rpx;
margin-right:15rpx;
}
}
</style>

66
pages/tovoid/tovoid.vue Normal file
View File

@ -0,0 +1,66 @@
<template>
<view>
<view class="textbox">
<textarea name="" v-model="content" placeholder="请输入审核意见" id="" class="textcontent"></textarea>
</view>
<view class="btn" @click="saveExamine">保存</view>
</view>
</template>
<script>
import { netExamine } from '@/api/kehu.js'
export default{
data() {
return{
status:'', //1 2
id:'',
type:'', //receivables contract consume
content:''
}
},
onLoad(options) {
this.status = options.status
this.id = options.id
this.type = options.type
},
onShow() {
},
methods:{
saveExamine() {
let params = {
relation_type: this.type,
relation_id:this.id,
content:this.content,
status: this.status
}
}
}
}
</script>
<style lang="scss" scoped>
.textbox{
background:#fff;
padding:20rpx 24rpx;
.textcontent{
width:100%;
height:300rpx;
border-radius: 8rpx;
border:1rpx solid #CCCCCC;
padding:20rpx;
}
}
.btn{
width:680rpx;
height:80rpx;
border-radius: 40rpx;
background:$uni-text-color;
margin:100rpx auto;
font-size:24rpx;
color:#fff;
text-align: center;
line-height: 80rpx;
}
</style>

445
pages/workreport/list.vue Normal file
View File

@ -0,0 +1,445 @@
<template>
<view>
<view class="select_warp">
<view class="topbox">
<view class="tab_list">
<view
class="tab_li"
v-for="(item,index) in readList"
:key="index"
:class="{'tab_li_active': item.id == readIndex}"
@click="changeTab(item)"
>{{item.name}}</view>
</view>
</view>
<view class="searchbox">
<view class="searchtext" @click="toQuery">筛选<view class="iconfont icon-shaixuan"></view></view>
</view>
<uni-popup ref="screenpopup" type="top" background-color="#fff">
<view class="warpbox">
<scroll-view scroll-y class="scrollbox" style="height:600rpx;background:#fff;" >
<!--筛选模块 -->
<view class="screen_content" @tap.stop.prevent>
<view class="fir_li">
<view class="li_label">提交人</view>
<view class="li_box">
<view class="form_right" @click="toSelectStaff">
<view :class="staffObj ? 'valueActive' : '' ">{{staffObj ? staffObj.name : '点击选择'}}</view>
<view class="iconfont icon-arrows_right"></view>
</view>
</view>
</view>
<view class="fir_li">
<view class="li_label">报告类型</view>
<picker @change="changeWorkType" :value="workIndex" :range="workList">
<view class="li_box">
<view class="form_right">
<view :class="workList[workIndex] ? 'valueActive' : '' ">{{workList[workIndex] ? workList[workIndex] : '点击选择'}}</view>
<view class="iconfont icon-arrows_right"></view>
</view>
</view>
</picker>
</view>
<view class="fir_li">
<view class="li_label">时间筛选</view>
<view class="li_box" style="display: flex;">
<picker @change="changeStartTime" mode="date" :end="end_time"
style="width:50%;border-right:1rpx solid #CCCCCC">
<view class="form_right">
<view style="flex:1;text-align: center;"
:class="start_time ? 'valueactive' : '' ">
{{start_time ? start_time : '开始时间'}}</view>
</view>
</picker>
<picker @change="changeEndTime" mode="date" :start="start_time" style="width:50%">
<view class="form_right">
<view style="flex:1;text-align: center;"
:class="end_time ? 'valueactive' : '' ">{{end_time ? end_time : '结束时间'}}
</view>
</view>
</picker>
</view>
</view>
</view>
</scroll-view>
<view class="button_bottom">
<view @tap.stop="reset">重置</view>
<view @tap.stop="sureQuery">确定</view>
</view>
</view>
</uni-popup>
</view>
<view>
<view class="work_li" v-for="(item,index) in list" :key="index" @click="jumpDetail(item)">
<view class="li_key" v-if="item.is_read != 1"></view>
<view class="li_left">
<image :src="item.staff.img ? item.staff.img : BASE_IMG_URL+'img/headImg.png'" class="li_img" mode=""></image>
<view class="">
<view class="li_name">{{item.staff.name}} <text style="font-size:24rpx;color:#999;margin-left:15rpx">{{item.staff.post?item.staff.post:''}}</text> </view>
<view class="li_post">{{item.createtime}}</view>
</view>
</view>
<view class="li_right">
<view class="tatus firbg" v-if="item.type == '日报'">日报</view>
<view class="tatus secbg" v-if="item.type == '周报'">周报</view>
<view class="tatus thrbg" v-if="item.type == '月报'">月报</view>
<view class="tatus forbg" v-if="item.type == '季报'">季报</view>
<view class="tatus fivbg" v-if="item.type == '年报'">年报</view>
</view>
</view>
<u-loadmore v-if="list.length == 0" status="nomore"></u-loadmore>
</view>
<!-- 创建用户图标 -->
<view class="icon_creat" @click="createWork">
<image :src="BASE_IMG_URL+'1.png'"></image>
</view>
<select-staff ref="staffChild" @sureStaff="sureStaff"></select-staff>
</view>
</template>
<script>
import { netWorkreportList } from '@/api/index.js'
import { netSelect, netSearchStaffList } from '@/api/kehu.js'
import { BASE_IMG_URL } from '@/util/api.js'
import selectStaff from '@/components/selectStaff.vue'
export default{
components:{
selectStaff
},
data(){
return{
BASE_IMG_URL:BASE_IMG_URL,
list:[],
page:1,
totalPage:1,
workList:[],
workIndex:null,
readList:[{id:0,name:'全部'},{id:1,name:'已读'},{id:2,name:'未读'}],
readIndex:0,
staffObj:null, //
permission:{}, //
start_time:'',
end_time:'',
}
},
onShow() {
this.list = []
this.page = 1
this.getList()
//
this.getSelect()
//
this.getPeopel()
this.permission = getApp().globalData.permission
},
onReachBottom() {
if(this.page >= this.totalPage){
return
}
this.page ++
this.getList()
},
methods:{
toSelectStaff() {
this.$refs.staffChild.init()
},
sureStaff(obj) {
this.staffObj = obj
},
toQuery() {
this.$refs.screenpopup.open()
},
changeStartTime(e) {
this.start_time = e.detail.value
if(!this.end_time){
this.end_time = e.detail.value
}
},
changeEndTime(e) {
this.end_time = e.detail.value
if(!this.start_time){
this.start_time = e.detail.value
}
},
init(){
this.page = 1
this.list = []
setTimeout(()=>{
this.getList()
},200)
},
changeTab(item) {
this.readIndex = item.id
this.init()
},
//
getPeopel() {
netSearchStaffList().then(res=>{
this.typeList = res.data
})
},
//
getSelect() {
netSelect().then(res=>{
this.workList = res.data['报告类型']
})
},
getList() {
let params = {
page:this.page,
is_read:this.readIndex,
staff_id:this.staffObj?this.staffObj.id:'',
type:(this.workList && this.workList[this.workIndex])?this.workList[this.workIndex]:'',
times:(this.start_time && this.end_time) ? (this.start_time + ',' + this.end_time) : '',
}
netWorkreportList(params).then(res=>{
this.list = this.list.concat(res.data.data)
this.totalPage = res.data.last_page
})
},
jumpDetail(item) {
uni.navigateTo({
url:'/pagesB/workreport/workDetail?id='+item.id
})
},
//
changeRead(e) {
this.readIndex = e.detail.value
},
changeWorkType(e) {
this.workIndex = e.detail.value
},
//
reset() {
this.readIndex = null
this.workIndex = null
this.staffObj = null
this.start_time = ''
this.end_time = ''
},
sureQuery() {
this.$refs.screenpopup.close()
this.init()
},
//
createWork() {
uni.navigateTo({
url:'/pagesB/workreport/addReports'
})
}
}
}
</script>
<style lang="scss" scoped>
.topbox{
width:750rpx;
height:80rpx;
background:#fff;
.tab_list{
padding:0 24rpx;
display: flex;
justify-content: space-around;
align-items: center;
.tab_li{
width:120rpx;
font-size:30rpx;
color:#666;
height:80rpx;
margin-right:40rpx;
line-height: 80rpx;
flex-shrink: 0;
text-align: center;
}
.tab_li_active{
color:#000;
position: relative;
&::after{
content:'';
width:60rpx;
height:6rpx;
background:$uni-text-color;
position: absolute;
bottom:0;
left:50%;
transform: translateX(-50%);
}
}
}
}
.icon_creat {
position: fixed;
z-index: 1;
bottom: 100rpx;
right: 100rpx;
image {
width: 80rpx;
height: 80rpx;
border-radius: 50%;
}
}
.firbg{
background:#AF99FE;
}
.secbg{
background:#FBB545;
}
.thrbg{
background:#4AD49D;
}
.forbg{
background:#FF6E7F;
}
.fivbg{
background:#54B1F7;
}
.valueactive{
color:#333;
}
.rediowarp{
display: flex;
justify-content: flex-start;
flex-wrap: wrap;
label{
display: flex;
justify-content: flex-start;
margin-right:24rpx;
align-items: center;
}
radio{
transform: scale(0.7);
}
}
.work_li{
width:702rpx;
background:#fff;
border-radius: 10rpx;
padding:30rpx;
box-sizing: border-box;
display: flex;
justify-content: space-between;
align-items: center;
margin:0 auto 24rpx;
position: relative;
.li_key{
position: absolute;
right:5rpx;
top:5rpx;
width:20rpx;
height:20rpx;
border-radius: 50%;
background:red;
}
.li_left{
display: flex;
justify-content: flex-start;
align-items: center;
font-size:26rpx;
color:#333;
.li_img{
width:80rpx;
height:80rpx;
border-radius: 50%;
margin-right:15rpx;
}
.li_name{
font-size:26rpx;
color:#333;
margin-bottom:15rpx;
}
}
.li_right{
.tatus{
font-size:24rpx;
color:#fff;
width:110rpx;
height:55rpx;
border-radius: 10rpx;
text-align: center;
line-height: 55rpx;
}
}
}
.select_warp{
z-index: 9;
}
.searchbox{
display: flex;
justify-content: flex-end;
margin:24rpx;
.searchtext{
display: flex;
justify-content: center;
align-items: center;
font-size:24rpx;
color:$uni-text-color;
padding:5rpx 23rpx;
background:#fff;
border-radius: 5rpx;
box-shadow: 2rpx 2rpx 50rpx rgba(0,0,0,0.1);
}
}
.warpbox{
width:750rpx;
z-index: 2;
background:rgba(0,0,0,0.7);
.screen_content {
width:702rpx;
z-index: 2;
border-top:1rpx solid #CCCCCC;
background-color: #fff;
padding:24rpx;
.fir_li{
margin-bottom:20rpx;
.li_label{
font-size:28rpx;
color:#333333;
margin-bottom:15rpx;
}
.li_box{
border-radius: 15rpx;
border:1rpx solid #CCCCCC;
height:60rpx;
padding:0 35rpx;
line-height: 60rpx;
}
.form_right {
display: flex;
color: #999;
justify-content: space-between;
image {
width: 40rpx;
height: 40rpx;
margin: 28rpx 5rpx 0 0;
}
}
}
}
.button_bottom {
display: flex;
width: 100%;
height: 90rpx;
background-color: #fff;
line-height: 90rpx;
text-align: center;
font-size: 32rpx;
:first-child {
flex: 1;
color: $uni-text-color;
border-top:1rpx solid #CCCCCC;
}
:last-child {
flex: 1;
background-color: $uni-text-color;
color: #fff;
}
}
}
</style>

View File

@ -0,0 +1,398 @@
<template>
<view class="">
<view class="top_required">
只展示<span style="color:#f00">必填</span>字段<switch :checked="isRequired" color="#008EFF" @change="changeRequired" />
</view>
<view class="fllow_form">
<view><text>*</text>客户名称</view>
<view class="form_right" @click="changeCus">
<view :class="customerObj.id ? 'valueActive' : '' ">{{customerObj.id ? customerObj.name : '点击选择'}}</view>
<view class="iconfont icon-arrows_right"></view>
</view>
</view>
<form-item v-for="(item,index) in listForm" :isNotRequired="isRequired" :key="index" :objInfo="item" @changeData="changeOtherData">
</form-item>
<!-- 添加产品 -->
<view class="fllow_form" v-if="!isRequired">
<view style="padding-left:15rpx;">购买产品</view>
<view class="add_in" @click="addPart">
+添加产品
</view>
</view>
<view class="pro_warp" v-if="productList.length != 0">
<view class="li_warp" v-for="(item,index) in productList" :key="index">
<view class="cell_con">
<view class="cell_con_top">
<view class="contitle">{{item.name}}</view>
<image :src="BASE_IMG_URL+'delete1.png'" @click="delProduct(index)" class="deleimg" mode=""></image>
</view>
<view class="pro_con_box">
<view class="boxleft">
<view class="context">编号{{item.num}}</view>
<view class="context">单位{{item.unit}}</view>
<view class="context">
零售价<input type="digit" v-model="item.price" class="productPrice" placeholder="产品价格">
</view>
<view class="context">
批发价<input type="digit" v-model="item.wholesale" class="productPrice" placeholder="批发价">
</view>
</view>
<view class="conbot">
<view class="conright">
<uni-number-box :min="1" v-model="item.number" @change="(e)=>{changeNumber(e,index)}"></uni-number-box>
</view>
</view>
</view>
</view>
</view>
</view>
<view id="btn" class="btn_g bg-blue button-hover round" @click="$noMultipleClicks(toSave)">
保存
</view>
<!-- 添加产品 -->
<popup-list ref="productChild" @selectList="selectList"></popup-list>
<!-- 添加产品配置 -->
<popup-product-config ref="productConfig" @selectList="configList"></popup-product-config>
<!-- 选择客户 -->
<select-customer ref="customerChild" @getCustomerinfo="sureSelect"></select-customer>
</view>
</template>
<script>
import selectCustomer from '@/components/selectCustomer.vue'
import popupList from '@/components/selectProduct/index'
import popupProductConfig from '@/components/selectProductConfig/index'
import formItem from '@/components/form/formitem.vue'
import { BASE_IMG_URL } from '@/util/api.js'
import { netSetForm, netAddBusiness } from '@/api/index'
import { netKehuDetail } from '@/api/kehu.js'
export default{
components:{
selectCustomer,
popupList,
popupProductConfig,
formItem
},
data() {
return{
BASE_IMG_URL:BASE_IMG_URL,
noClick: true, //
customerObj:{},
listForm:[],
productList:[],
isRequired:false, //
}
},
onLoad(options) {
if(options.id){
//id
this.getCustomerInfo(options.id)
}
this.getForm()
},
methods:{
//
changeRequired(e) {
this.isRequired = e.detail.value
},
//
getCustomerInfo(id) {
netKehuDetail({id}).then(res=>{
res = res.data
this.customerObj = {
id:res.id,
name:res.name,
}
})
},
getForm() {
netSetForm({type:'business'}).then(res=>{
let arr = res.data.data
arr.forEach(ele=>{
ele.value = ele.value?ele.value:''
})
this.listForm = arr
})
},
//
changeCus(e) {
this.$refs.customerChild.init()
},
sureSelect(obj) {
this.customerObj = obj
},
changeOtherData(name, value, obj) {
let arr = this.listForm
arr.forEach((ele, index) => {
if (ele.id == obj.id) {
ele.value = value
this.$set(this.listForm, index, ele)
}
})
},
//
addPart() {
this.$refs.productChild.init()
},
selectList(arr) {
arr.forEach(ele=>{
ele.minprice = ele.price
ele.parts = []
})
this.productList = this.deWeight(arr.concat(this.productList))
},
deWeight(arr) {
for (var i = 0; i < arr.length - 1; i++) {
for (var j = i + 1; j < arr.length; j++) {
if (arr[i].id == arr[j].id) {
arr.splice(j, 1);
j--;
}
}
}
return arr;
},
//
changeNumber(e,index){
let obj = this.productList[index]
obj.number = e
this.$set(this.productList,index,obj)
},
delProduct(index) {
this.productList.splice(index,1)
},
//
toSelectConfig(item,index) {
this.configIndex = index
this.$refs.productConfig.init(item.id)
},
configList(arr) {
let obj = this.productList[this.configIndex]
obj.parts = this.deWeight(obj.parts.concat(arr))
this.$set(this.productList,this.configIndex,obj)
},
//
changeConfigNumber(e,conindex,index) {
let obj = this.productList[index]
obj.parts[conindex].number = e
this.$set(this.productList,index,obj)
},
//
delPeizhi(index,conindex) {
let obj = this.productList[index]
obj.parts.splice(conindex,1)
this.$set(this.productList,index,obj)
},
toSave() {
if(!this.customerObj.id){
uni.showToast({
title:'请选择客户名称',
icon:'none'
})
return
}
let params = this.checkCommonForm(this.listForm)
if(!params){
return
}
//
let product = []
if(this.productList.length > 0){
this.productList.forEach(ele=>{
product.push({
product_id:ele.id,
price: ele.price,
number: ele.number,
wholesale: ele.wholesale
})
})
}
params = Object.assign({},params,{customer_id:this.customerObj.id,product})
netAddBusiness(params).then(res=>{
uni.showToast({
title:res.msg,
icon:'none'
})
setTimeout(()=>{
uni.navigateBack({
delta:1
})
},2000)
})
},
}
}
</script>
<style lang="scss" scoped>
.add_in{
background-color: $uni-text-color;
color:#fff;
height:60rpx;
line-height: 60rpx;
padding:0 15rpx;
font-size: 24rpx;
border-radius: 10rpx;
}
.fllow_form {
display: flex;
justify-content: space-between;
align-items: center;
background-color: #fff;
border-bottom: 1rpx solid #EAEAEA;
padding: 30rpx 20rpx;
color: #999;
font-size: 32rpx;
.form_right {
display: flex;
align-items: center;
color: #999;
:first-child {
width: 450rpx;
text-align: right;
}
image {
width: 40rpx;
height: 40rpx;
margin: 28rpx 5rpx 0 0;
}
}
.theme {
color: #5ca9fe;
}
text {
color: #f00;
margin-left: 10rpx;
}
.form_input {
input {
text-align: right;
margin-right: 10rpx;
}
}
}
.pro_warp{
padding:30rpx 24rpx 0 24rpx;
background:#fff;
border-bottom:1rpx solid #f5f5f5;
.li_warp{
padding-bottom:24rpx;
margin-bottom:24rpx;
border-bottom:2rpx solid #f5f5f5;
&:last-child{
border-bottom:0;
}
.cell_con{
padding:0 40rpx;
.cell_con_top{
display: flex;
justify-content: space-between;
align-items: center;
.contitle{
font-size:28rpx;
color:#333;
}
.deleimg{
width:44rpx;
height:44rpx;
}
}
.pro_con_box{
display: flex;
justify-content: space-between;
align-items: center;
.context{
font-size:26rpx;
color:#666;
margin-top:10rpx;
display: flex;
justify-content: flex-start;
align-items: center;
.productPrice{
width:150rpx;
background:#f5f5f5;
text-align: center;
}
}
.conbot{
margin-top:10rpx;
display: flex;
justify-content: space-between;
align-items: center;
.conmoney{
font-size:26rpx;
color:#333;
}
}
}
.config_set{
margin-top:24rpx;
.config_title{
font-size:24rpx;
color:#333;
display: flex;
justify-content: flex-start;
align-items: center;
.addConimg{
width:100rpx;
height:40rpx;
margin-left:10rpx;
}
}
.config_list{
margin-top:24rpx;
.config_li{
display: flex;
justify-content: flex-start;
align-items: center;
margin-top:24rpx;
border-bottom:1rpx solid #f5f5f5;
padding-bottom:24rpx;
.conimg{
width:100rpx;
height:100rpx;
border-radius: 10rpx;
margin-right:20rpx;
}
.config_name{
width:290rpx;
font-size:24rpx;
color:#333;
overflow: hidden;
text-overflow:ellipsis;
white-space: nowrap;
}
.config_step{
margin-left:24rpx;
}
}
}
}
}
.right_del_btn{
width:90rpx;
height:240rpx;
background:#F00;
color:#fff;
text-align: center;
line-height: 224rpx;
}
}
}
.del{
width:40rpx;
height:40rpx;
border-radius: 50%;
border:1rpx solid #ff7800;
font-size:28rpx;
color:#ff7800;
flex-shrink: 0;
margin-right:24rpx;
text-align: center;
line-height: 38rpx;
}
</style>

171
pagesA/business/advance.vue Normal file
View File

@ -0,0 +1,171 @@
<template>
<view class="">
<view class="fllow_form">
<view><text>*</text>商机阶段</view>
<picker :range="arr" :value="arrIndex" @change="changeArr">
<view class="form_right" >
<view :class="arr[arrIndex] ? 'valueActive' : '' ">{{arr[arrIndex] ? arr[arrIndex] : '商机阶段'}}</view>
<view class="iconfont icon-arrows_right"></view>
</view>
</picker>
</view>
<view class="fllow_area">
<view class="area_head">备注</view>
<textarea
maxlength="-1"
:class="remark ? 'valueActive' : '' "
placeholder="备注"
v-model="remark"
placeholder-style="color:#999;font-size:32rpx;" />
</view>
<!-- 上传图片 -->
<upload-image
:imgList="imgList"
:flag="false"
@uploadImg="uploadImg"
@delImg="delImg"
></upload-image>
<!-- 上传文件 -->
<upload-file
title="文件"
v-if="false"
:fileList="fileList"
@uploadFile="uploadFile"
@delFile="delFile"
>
</upload-file>
<view id="btn" class="btn_g bg-blue button-hover round" @click="$noMultipleClicks(toSave)">
保存
</view>
</view>
</template>
<script>
import uploadImage from "@/components/uploadImg/index.vue"
import uploadFile from '@/components/uploadFile/index.vue'
import { netAdvanceBusiness } from '@/api/index.js'
export default{
components:{
uploadImage,
uploadFile
},
data() {
return{
noClick: true, //
arr:['初期沟通','立项跟踪','方案/报价','谈判审核','赢单','输单','无效'],
arrIndex:0,
remark:'',
imgList:[],
fileList:[],
id:'',
}
},
onLoad(options) {
this.id = options.id
this.arrIndex = options.status
},
methods:{
changeArr(e) {
console.log(e,'===')
this.arrIndex = e.detail.value
},
uploadImg(obj) {
this.imgList.push(obj)
},
delImg(index) {
this.imgList.splice(index,1)
},
uploadFile(obj) {
this.fileList.push(obj)
},
delFile(index) {
this.fileList.splice(index,1)
},
toSave(){
let arr = []
let b = this.imgList.concat(this.fileList)
b.forEach(ele=>{
arr.push(ele.id)
})
let params = {
id:this.id,
type:this.arrIndex,
remark:this.remark,
file:arr.join(',')
}
netAdvanceBusiness(params).then(res=>{
uni.showToast({
title:res.msg,
icon:'none'
})
setTimeout(()=>{
uni.navigateBack({
delta:1
})
},2000)
})
}
}
}
</script>
<style lang="scss" scoped>
.fllow_form {
display: flex;
justify-content: space-between;
align-items: center;
background-color: #fff;
border-bottom: 1rpx solid #EAEAEA;
padding: 30rpx 20rpx;
color: #999;
font-size: 32rpx;
.form_right {
display: flex;
align-items: center;
color: #999;
:first-child {
width: 450rpx;
text-align: right;
}
image {
width: 40rpx;
height: 40rpx;
margin: 28rpx 5rpx 0 0;
}
}
.theme {
color: #5ca9fe;
}
text {
color: #f00;
margin-left: 10rpx;
}
.form_input {
input {
text-align: right;
margin-right: 10rpx;
}
}
}
.fllow_area {
background-color: #fff;
padding: 30rpx 20rpx;
padding-bottom: 30rpx;
color: #999;
font-size: 32rpx;
.area_head {
margin-bottom:24rpx;
margin-left:15rpx;
}
textarea {
width: 80%;
height: 300rpx;
padding: 30rpx;
background: #f8f8f8;
margin: 0 auto;
}
}
</style>

View File

@ -0,0 +1,169 @@
<template>
<view class="">
<scroll-view scroll-y="true" class="scrollbox">
<view class="listbox">
<view class="li" v-for="(item,index) in list" :key="index">
<view class="time">推进时间{{item.createtime}}</view>
<view class="content">
<span>推进阶段</span>
<text v-if="item.type == 0">初期沟通</text>
<text v-if="item.type == 1">立项跟踪</text>
<text v-if="item.type == 2">方案/报价</text>
<text v-if="item.type == 3">谈判审核</text>
<text v-if="item.type == 4">赢单</text>
<text v-if="item.type == 5">输单</text>
<text v-if="item.type == 6">无效</text>
</view>
<view class="content">
<span>备注</span>{{item.remark}}
</view>
<view class="main_img" @click.stop.prevent v-if="item.imgList != item">
<image v-for="(ele,index) in item.imgList" :key="index" :src="ele.file_path" @click.stop="toPrevieImg(item.imgList,index)" class="imgbox" ></image>
</view>
<view class="fllow_file_li" @click.stop.prevent v-if="item.fileList.length != 0">
<view class="fil_li" v-for="(fileitem,fileindex) in item.fileList" :key="fileindex">
<image :src="BASE_IMG_URL+'fujian.png'" class="fileimg" mode="scaleToFill"></image>
<view class="filename" @click="openCommonFile(fileitem)">{{fileitem.name}}</view>
</view>
</view>
</view>
</view>
</scroll-view>
</view>
</template>
<script>
import { netBusinessHistory } from '@/api/index.js'
import { BASE_IMG_URL } from '@/util/api.js'
export default{
props:{
info:{
type:Object,
default:{}
}
},
data() {
return{
BASE_IMG_URL:BASE_IMG_URL,
list:[]
}
},
created() {
this.getList()
},
methods:{
getList() {
netBusinessHistory({id:this.info.id}).then(res=>{
res = res.data
res.forEach(ele=>{
ele.imgList = []
ele.fileList = []
if(ele.file){
ele.file.forEach(item=>{
if(item.types.indexOf('image') != -1){
ele.imgList.push({
id:item.id,
file_path:item.file_path,
name:item.name
})
}else{
ele.fileList.push({
id:item.id,
file_path:item.file_path,
name:item.name
})
}
})
}
})
this.list = res
})
},
//
toPrevieImg(arr,index) {
let data = []
arr.forEach(ele=>{
data.push(ele.file_path)
})
uni.previewImage({
urls: data,
current:index
})
}
}
}
</script>
<style lang="scss" scoped>
.scrollbox{
width:100%;
height:900rpx;
.listbox{
.li{
padding:24rpx;
background:#fff;
border-radius: 20rpx;
width:690rpx;
margin:24rpx auto 0;
.time{
font-size:30rpx;
color:#000;
padding-bottom:24rpx;
border-bottom:1rpx solid #f5f5f5;
margin-bottom:15rpx;
}
.content{
display: flex;
justify-content: flex-start;
font-size: 28rpx;
color:#333;
margin-bottom:15rpx;
}
.main_img {
display: flex;
justify-content: flex-start;
align-items: center;
flex-wrap: wrap;
margin-top: 20rpx;
.imgbox {
padding: 10rpx;
border-radius: 10rpx;
width: 160rpx;
height: 160rpx;
margin-right: 14rpx;
margin-bottom: 14rpx;
}
}
.fllow_file_li {
padding: 24rpx 34rpx;
background: #fff;
.fil_li {
display: flex;
justify-content: flex-start;
align-items: center;
padding-bottom: 14rpx;
padding-top:15rpx;
.fileimg {
width: 20rpx;
height: 20rpx;
margin-right:25rpx;
}
.filename {
width:450rpx;
font-size: 24rpx;
color: #999999;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.closeimg {
width: 32rpx;
height: 32rpx;
}
}
}
}
}
}
</style>

View File

@ -0,0 +1,212 @@
<template>
<view class="">
<view class="basic_main">
<view>客户名称</view>
<view style="color:#008EFF" @click="toKehuInfo">{{info.customer.name}}</view>
</view>
<form-item v-for="(item,index) in listForm" :key="index" :objInfo="item" :isEdit="false"></form-item>
<view class="basic_main">
<view>购买产品</view>
<view></view>
</view>
<view class="pro_warp" v-if="info.product && info.product.length != 0">
<view class="li_warp" v-for="(item,index) in info.product" :key="index">
<image class="pro_img" :src="item.img" mode=""></image>
<view class="cell_con">
<view class="cell_con_top">
<view class="contitle">{{item.name}}</view>
</view>
<view class="context">编号{{item.num}}</view>
<view class="info_l">
<view class="context">单位{{item.unit}}</view>
<view class="context">数量{{item.number}}</view>
</view>
<view class="context">零售价{{item.price}}</view>
<view class="context">批发价{{item.wholesale}}</view>
</view>
</view>
</view>
</view>
</template>
<script>
import { netSetForm } from '@/api/index.js'
import formItem from '@/components/form/formitem.vue'
import { BASE_IMG_URL } from '@/util/api.js'
export default{
components:{
formItem
},
props:{
info:{
type:Object,
default:{}
},
},
data() {
return{
BASE_IMG_URL:BASE_IMG_URL,
listForm:[]
}
},
created() {
// form
this.getForm()
},
methods:{
getForm() {
netSetForm({type:'business'}).then(res=>{
res = res.data.data
res.forEach(ele=>{
ele.value = this.info[ele.id]?this.info[ele.id]:''
})
this.listForm = res
})
},
//
toKehuInfo() {
uni.navigateTo({
url: '/pages/index/groupCompany/groupCompany?id=' + this.info.customer.id
})
},
}
}
</script>
<style lang="scss" scoped>
.basic_main {
display: flex;
justify-content: space-between;
padding: 0 32rpx;
background-color: #fff;
height: 90rpx;
line-height: 90rpx;
border-bottom: 1rpx solid #EAEAEA;
:first-child {
color: #999;
}
>view{
font-size: 32rpx;
}
}
.pro_warp{
padding:30rpx 24rpx;
background:#fff;
margin-bottom:24rpx;
.li_warp{
padding-bottom:24rpx;
margin-bottom:24rpx;
border-bottom:1rpx solid #f5f5f5;
display: flex;
justify-content: flex-start;
align-items: center;
position: relative;
.pro_status{
font-size:26rpx;
color:#007AFF;
position: absolute;
right:35rpx;
top:10rpx;
}
.pro_img{
width:160rpx;
height:160rpx;
flex-shrink: 0;
margin-right:24rpx;
}
.cell_con{
padding:0 40rpx 0 0;
flex:1;
.cell_con_top{
display: flex;
justify-content: space-between;
align-items: center;
.contitle{
font-size:28rpx;
color:#333;
}
}
.context{
font-size:26rpx;
color:#999;
margin-top:10rpx;
}
.info_l{
display: flex;
justify-content: space-between;
align-items: center;
.context{
font-size:26rpx;
color:#999;
margin-right:24rpx;
&:last-child{
margin-right:0;
}
}
}
.con_info{
margin-top:15rpx;
.contitle{
font-size:26rpx;
color:#333;
}
.config_li{
display: flex;
justify-content: flex-start;
align-items: center;
margin-top:24rpx;
border-bottom:1rpx solid #f5f5f5;
&:last-child{
border-bottom:0;
}
.conimg{
width:80rpx;
height:80rpx;
border-radius: 10rpx;
margin-right:20rpx;
}
.config_name{
width:100rpx;
font-size:24rpx;
color:#333;
overflow: hidden;
text-overflow:ellipsis;
white-space: nowrap;
}
.config_step{
margin-left:24rpx;
}
}
}
.conbot{
margin-top:10rpx;
display: flex;
justify-content: space-between;
align-items: center;
.conmoney{
font-size:26rpx;
color:#333;
}
}
}
.right_del_btn{
width:90rpx;
height:240rpx;
background:#F00;
color:#fff;
text-align: center;
line-height: 224rpx;
}
}
.total_money{
text-align: right;
font-size:26rpx;
span{
font-size:26rpx;
color:#F00;
}
}
}
</style>

View File

@ -0,0 +1,209 @@
<template>
<view class="">
<view class="manage_con">
<view class="clineInfo" v-for="(item,index) in list" :key="index" @click.stop="toDetail(item)">
<view class="info_head">
<view>{{item.name}}</view>
</view>
<view class="info_main">
<view >
<view class="main_left">
<view class="left_top" v-if="item.customer" style="margin-top: 20rpx;color: #666;font-size: 30rpx;">
{{item.customer ? item.customer.name : '--'}}
</view>
<view class="left_followUp" style="margin-top: 20rpx;color: #666;font-size: 30rpx;">
<view>下次跟进时间</view>
<view>{{item.next_time ? item.next_time : '--'}}</view>
</view>
<view class="left_foot">
<view class="l_box">
<span v-if="item.type == 0">初期沟通</span>
<span v-if="item.type == 1">立项跟踪</span>
<span v-if="item.type == 2">方案/报价</span>
<span v-if="item.type == 3">谈判审核</span>
<span v-if="item.type == 4">赢单</span>
<span v-if="item.type == 5">输单</span>
<span v-if="item.type == 6">无效</span>
</view>
</view>
</view>
</view>
<view class="main_right" v-if="item.owner_staff">
<image :src="item.owner_staff ? item.owner_staff.img : BASE_IMG_URL+'headImg.png'" mode="scaleToFill">
</image>
<view>{{item.owner_staff?item.owner_staff.name:''}}</view>
</view>
</view>
<view class="info_footer" @click.stop.prevent>
<view class="footer_content" @click="toAddfollow(item)">
<image :src="BASE_IMG_URL+'tj.png'" mode="scaleToFill"></image>
<view>跟进</view>
</view>
<view class="footer_content" @click="toTrans(item)">
<image :src="BASE_IMG_URL+'rq.png'" mode="scaleToFill"></image>
<view>转移</view>
</view>
</view>
</view>
<view style="height: 200rpx;"></view>
<u-empty v-if="list.length == 0" text="暂无更多"></u-empty>
</view>
<view class="icon_creat" @click="addBusiness">
<image :src="BASE_IMG_URL+'1.png'" mode="scaleToFill"></image>
</view>
</view>
</template>
<script>
import { BASE_IMG_URL } from '@/util/api.js'
import { netBusinessList } from '@/api/index.js'
export default{
data() {
return{
BASE_IMG_URL:BASE_IMG_URL,
list:[],
page:1,
totalPage:1,
id:'', //id
}
},
onLoad(options) {
this.id = options.id
},
onShow() {
this.getList()
},
onReachBottom() {
if(this.page < this.totalPage){
this.page ++
this.getList()
}
},
methods:{
getList() {
let params = {
page:this.page,
customer_id:this.id
}
netBusinessList(params).then(res=>{
this.list = res.data.data
this.totalPage = res.data.last_page
})
},
//
toAddfollow(item) {
uni.navigateTo({
url: '/pagesA/crm/customerManagement/newFllow/newFllow?id='+item.id+'&type=5'
})
},
//
toTrans(item) {
uni.navigateTo({
url:'/pagesA/business/trans?id='+item.id
})
},
addBusiness(){
uni.navigateTo({
url:'/pagesA/business/addBusiness?id='+this.id
})
}
}
}
</script>
<style lang="scss" scoped>
.clineInfo {
background-color: #fff;
padding: 30rpx 45rpx;
margin-bottom: 20rpx;
border-radius: 10rpx;
box-shadow: 2rpx 2rpx 50rpx rgba(0, 0, 0, 0.1);
.info_head {
display: flex;
justify-content: space-between;
:first-child {
font-size: 34rpx;
font-weight: 700;
color: #333;
}
}
.info_main {
display: flex;
justify-content: space-between;
.main_left {
.left_followUp {
display: flex;
padding-bottom: 30rpx;
font-size: 30rpx;
color: #666;
}
.left_star {
font-size: 30rpx;
color: #666;
display: flex;
padding-bottom: 30rpx;
}
.left_foot {
padding-bottom: 20rpx;
.l_box {
margin-right: 35rpx;
float: left;
span {
background: $uni-text-color-opcity;
padding: 5rpx 12rpx;
font-size: 26rpx;
color: $uni-text-color;
border-radius: 5rpx;
}
}
}
}
.main_right {
text-align: center;
padding: 20rpx 15rpx 0 0;
image {
border-radius: 50%;
width: 129rpx;
height: 129rpx;
margin-bottom: 5rpx;
}
}
}
.info_footer {
display: flex;
justify-content: space-around;
padding-top: 30rpx;
height: 80rpx;
border-top: 1px solid #ededed;
margin-top: 20rpx;
.footer_content {
// width: 25%;
line-height: 28rpx;
display: flex;
justify-content: center;
align-items: center;
image{
width: 48rpx;
height: 48rpx;
margin-right: 15rpx;
}
}
}
}
</style>

423
pagesA/business/detail.vue Normal file
View File

@ -0,0 +1,423 @@
<template>
<view class="group_company">
<view class="contractinfo" v-if="info">
<view class="nameli">
<view class="name">{{info.name}}</view>
</view>
<view class="content" >
下次跟进时间{{info.next_time ? info.next_time : ''}}
</view>
<view class="content">
商机金额{{info.money ? info.money : ''}}
</view>
<view class="content" >
创建人{{info.owner_staff ? info.owner_staff.name : ''}}
</view>
<view class="bus_box">
<view class="bustit">商机推进阶段:</view>
<!-- <view class="busright">推进商机</view> -->
</view>
<view class="stepbox">
<view class="stepli " :class="{'stepli_a':index <= options_active}" v-for="(item,index) in options" :key="index">
<view class="num">{{index+1}}</view>
<view class="step_text">{{item.title}} <text v-if="index != options.length-1"> > </text> </view>
</view>
</view>
</view>
<!-- 标签栏 -->
<view class="group_tab">
<u-tabs name="cate_name" :list="lists" :is-scroll="false" active-color="#008EFF" :current="current"
@change="change"></u-tabs>
<view class="processing_title" v-if="current == 0">
<customer-dynamic v-if="info.id" :kehuid="info.id" :type="5"></customer-dynamic>
</view>
<view class="processing_title" v-if="current == 1">
<base-info v-if="info.id" :info="info" ></base-info>
</view>
<view class="processing_title" v-if="current == 2">
<related-contract v-if="info.id" :info="info" ></related-contract>
</view>
<view class="processing_title" v-if="current == 3">
<advance-history v-if="info.id" :info="info"></advance-history>
</view>
</view>
<view style="height:100rpx;"></view>
<!-- 底部导航栏 -->
<view class="bottom_nav">
<view class="bottom_item" @click="followClick(info.id,5)">
<image :src="BASE_IMG_URL+'tj.png'" class="botimg"></image>
<view>跟进</view>
</view>
<view class="bottom_item" @click="moreClick">
<image :src="BASE_IMG_URL+'morebtn.png'" class="botimg"></image>
<view>更多操作</view>
</view>
</view>
<uni-popup ref="popup" type="bottom" background-color="#fff">
<view class="pull_head">更多操作</view>
<view class="pull_con">
<view class="bottom_item" @click="toTrans(info.id)">
<view style="padding: 5rpx 12rpx;border: 1px solid #ededed;">转移商机</view>
</view>
<view class="bottom_item" @click="toEditcontract(info.id)">
<view style="padding: 5rpx 12rpx;border: 1px solid #ededed;">修改商机</view>
</view>
<view class="bottom_item" @click="toDelBusiness(info.id)">
<view style="padding: 5rpx 12rpx;border: 1px solid #ededed;">删除商机</view>
</view>
<view class="bottom_item" @click="toAddContract">
<view style="padding: 5rpx 12rpx;border: 1px solid #ededed;">添加合同</view>
</view>
<view class="bottom_item" @click="advanceBusiness">
<view style="padding: 5rpx 12rpx;border: 1px solid #ededed;">推进商机</view>
</view>
</view>
</uni-popup>
</view>
</template>
<script>
import { BASE_IMG_URL } from '@/util/api.js'
import customerDynamic from 'components/content/customerDynamic/customerDynamic.vue';
import baseInfo from './baseInfo.vue'
import relatedContract from './relatedContract.vue'
import advanceHistory from './advanceHistory.vue'
import { netBusinessDetail, netDelBusiness } from '@/api/index.js'
export default {
created() {
},
data() {
return {
id: '', //id
info: {},
BASE_IMG_URL:BASE_IMG_URL,
current: 0,
lists: [
{
name: '跟进记录',
status: 0
},
{
name: '基本信息',
status: 1
},
{
name:'合同',
status:2
},
{
name:'推进历史',
status:3
}
],
options:[
{title: '初期沟通'},
{title: '立项跟踪'},
{title: '方案/报价'},
{title: '谈判审核'},
{title: '赢单'},
],
options_active:0
}
},
onLoad(options) {
this.id = options.id
},
onHide() {
this.$refs.popup.close()
},
onShow() {
this.info = {}
this.getInfo()
},
components: {
customerDynamic,
baseInfo,
relatedContract,
advanceHistory
},
methods: {
change(index) {
this.current = index;
},
tabs_change(e) {
this.current = e;
this.mescroll.resetUpScroll();
},
moreClick() {
this.$refs.popup.open()
},
//
getInfo() {
netBusinessDetail({
id: this.id
}).then(res => {
this.info = res.data
let type = res.data.type
if(type == 5){
this.options = [
{title: '初期沟通'},
{title: '立项跟踪'},
{title: '方案/报价'},
{title: '谈判审核'},
{title: '输单'},
]
this.options_active = 4
}else if(type == 6){
this.options = [
{title: '初期沟通'},
{title: '立项跟踪'},
{title: '方案/报价'},
{title: '谈判审核'},
{title: '无效'},
]
this.options_active = 4
}else{
this.options_active = type
}
})
},
//
followClick(id,type) {
uni.navigateTo({
url: '/pagesA/crm/customerManagement/newFllow/newFllow?id='+id+'&type='+type
})
},
//
toTrans(id) {
uni.navigateTo({
url:'/pagesA/business/trans?id='+id
})
},
//
toEditcontract(id) {
uni.navigateTo({
url: '/pagesA/business/editBusiness?id='+this.id
})
},
//
toDelBusiness(id) {
uni.showModal({
title:'提示',
content:'请确认是否删除?',
success:(res)=>{
if(res.confirm){
netDelBusiness({id:id}).then(res=>{
uni.showToast({
title:res.msg,
icon:'none'
})
setTimeout(()=>{
uni.navigateBack({
delta:1
})
},2000)
})
}
}
})
},
//
toAddContract() {
uni.navigateTo({
url:'/pagesA/crm/contract/contract?id='+this.info.customer.id+'&businessid='+this.id
})
},
//
advanceBusiness() {
uni.navigateTo({
url:'/pagesA/business/advance?id='+this.id+'&status='+this.info.type
})
}
}
}
</script>
<style lang="scss">
.bus_box{
display: flex;
justify-content: space-between;
align-items: center;
font-size:30rpx;
color:#fff;
margin-bottom:24rpx;
.busright{
font-size:24rpx;
width:120rpx;
text-align: center;
border:1rpx solid #fff;
padding:5rpx 0;
border-radius: 10rpx;
}
}
.stepbox{
display: flex;
justify-content: space-between;
align-items: center;
.xian{
width:35rpx;
height:2rpx;
background:#c7c5c5;
margin-bottom:35rpx;
}
.xian_a{
background:#fff;
}
.stepli{
display: flex;
flex-direction: column;
align-items: center;
text-align: center;
flex-shrink: 0;
.num{
width:40rpx;
height:40rpx;
border-radius: 50%;
border:1rpx solid #c7c5c5;
font-size:24rpx;
text-align: center;
line-height: 38rpx;
color:#c7c5c5;
margin-bottom:15rpx;
margin-right:10rpx;
}
.step_text{
font-size:26rpx;
color:#c7c5c5;
text{
font-size:26rpx;
color:#c7c5c5;
margin-left:10rpx;
}
}
}
.stepli_a{
.num{
color:#fff;
border:2rpx solid #fff;
}
.step_text{
color:#fff;
text{
font-size:26rpx;
color:#fff;
}
}
}
}
.pull_head {
font-size: 34rpx;
color: #999;
padding: 30rpx 0;
text-align: center;
}
.contractinfo {
background: $uni-text-color;
padding: 20rpx 40rpx;
position: relative;
.nameli {
display: flex;
justify-content: flex-start;
align-items: center;
margin-bottom: 24rpx;
.zhangimg {
width: 40rpx;
height: 40rpx;
margin-right: 15rpx;
}
.name {
font-size: 32rpx;
color: #fff;
font-size: 36rpx;
font-weight: 600;
}
}
.content {
font-size: 30rpx;
color: #fff;
margin: 15rpx 0;
}
}
.tabinfo {
display: flex;
justify-content: space-between;
align-items: center;
padding: 20rpx;
background: #fff;
border-top: 1rpx solid #C0C0C0;
.tableft {
display: flex;
justify-content: flex-start;
align-items: center;
.headerimg {
width: 45rpx;
height: 45rpx;
border-radius: 50%;
}
.name {
font-size: 26rpx;
color: $uni-text-color;
margin-left: 24rpx;
}
}
.rightimg {
width: 32rpx;
height: 32rpx;
}
}
.group_tab {
margin: 20rpx 0;
}
.bottom_nav {
position: fixed;
bottom: 0;
left: 0;
right: 0;
padding: 20rpx 0;
background-color: #fff;
text-align: center;
color: #999;
z-index: 2;
display: flex;
justify-content: space-around;
align-items: center;
border-top:1rpx solid #f5f5f5;
.bottom_item{
font-size:24rpx;
.botimg{
width:40rpx;
height:40rpx;
}
}
}
.pull_head{
font-size: 34rpx;
color: #999;
padding: 30rpx 0;
}
.pull_con {
display: flex;
justify-content: space-between;
flex-wrap: wrap;
padding: 20rpx 30rpx 100rpx;
.bottom_item{
margin-right:40rpx;
margin-bottom:35rpx;
&:nth-child(4n){
margin-right:0;
}
}
}
</style>

View File

@ -0,0 +1,390 @@
<template>
<view class="">
<view class="fllow_form">
<view><text>*</text>客户名称</view>
<view class="form_right" @click="changeCus">
<view :class="customerObj.id ? 'valueActive' : '' ">{{customerObj.id ? customerObj.name : '点击选择'}}</view>
<view class="iconfont icon-arrows_right"></view>
</view>
</view>
<form-item v-for="(item,index) in listForm" :key="index" :objInfo="item" @changeData="changeOtherData">
</form-item>
<!-- 添加产品 -->
<view class="fllow_form">
<view style="padding-left:15rpx;">购买产品</view>
<view class="add_in" @click="addPart">
+添加产品
</view>
</view>
<view class="pro_warp" v-if="productList.length != 0">
<view class="li_warp" v-for="(item,index) in productList" :key="index">
<view class="cell_con">
<view class="cell_con_top">
<view class="contitle">{{item.name}}</view>
<image :src="BASE_IMG_URL+'delete1.png'" @click="delProduct(index)" class="deleimg" mode=""></image>
</view>
<view class="pro_con_box">
<view class="boxleft">
<view class="context">编号{{item.num}}</view>
<view class="context">单位{{item.unit}}</view>
<view class="context">
零售价<input type="digit" v-model="item.price" class="productPrice" placeholder="产品价格">
</view>
<view class="context">
批发价<input type="digit" v-model="item.wholesale" class="productPrice" placeholder="批发价">
</view>
</view>
<view class="conbot">
<view class="conright">
<uni-number-box :min="1" v-model="item.number" @change="(e)=>{changeNumber(e,index)}"></uni-number-box>
</view>
</view>
</view>
</view>
</view>
</view>
<view id="btn" class="btn_g bg-blue button-hover round" @click="$noMultipleClicks(toSave)">
保存
</view>
<!-- 添加产品 -->
<popup-list ref="productChild" @selectList="selectList"></popup-list>
<!-- 添加产品配置 -->
<popup-product-config ref="productConfig" @selectList="configList"></popup-product-config>
<!-- 选择客户 -->
<select-customer ref="customerChild" @getCustomerinfo="sureSelect"></select-customer>
</view>
</template>
<script>
import selectCustomer from '@/components/selectCustomer.vue'
import popupList from '@/components/selectProduct/index'
import popupProductConfig from '@/components/selectProductConfig/index'
import formItem from '@/components/form/formitem.vue'
import { BASE_IMG_URL } from '@/util/api.js'
import { netSetForm, netBusinessDetail, netEditBusiness } from '@/api/index'
export default{
components:{
selectCustomer,
popupList,
popupProductConfig,
formItem
},
data() {
return{
BASE_IMG_URL:BASE_IMG_URL,
noClick: true, //
customerObj:{},
listForm:[],
productList:[],
id:'', //id
info:{}, //
}
},
onLoad(options) {
this.id = options.id
this.getDetail()
},
methods:{
getDetail(){
netBusinessDetail({id:this.id}).then(res=>{
this.info = res.data
this.productList = res.data.product
this.customerObj = res.data.customer
this.getForm()
})
},
getForm() {
netSetForm({type:'business'}).then(res=>{
res = res.data.data
res.forEach(ele=>{
ele.value = this.info[ele.id]?this.info[ele.id]:''
})
this.listForm = res
})
},
//
changeCus(e) {
this.$refs.customerChild.init()
},
sureSelect(obj) {
this.customerObj = obj
},
changeOtherData(name, value, obj) {
let arr = this.listForm
arr.forEach((ele, index) => {
if (ele.id == obj.id) {
ele.value = value
this.$set(this.listForm, index, ele)
}
})
},
//
addPart() {
this.$refs.productChild.init()
},
selectList(arr) {
arr.forEach(ele=>{
ele.minprice = ele.price
ele.parts = []
ele.product_id = ele.id
})
this.productList = this.deWeight(arr.concat(this.productList))
},
deWeight(arr) {
for (var i = 0; i < arr.length - 1; i++) {
for (var j = i + 1; j < arr.length; j++) {
if (arr[i].id == arr[j].id) {
arr.splice(j, 1);
j--;
}
}
}
return arr;
},
//
changeNumber(e,index){
let obj = this.productList[index]
obj.number = e
this.$set(this.productList,index,obj)
},
delProduct(index) {
this.productList.splice(index,1)
},
//
toSelectConfig(item,index) {
this.configIndex = index
this.$refs.productConfig.init(item.product_id)
},
configList(arr) {
let obj = this.productList[this.configIndex]
obj.parts = obj.parts?obj.parts:[]
obj.parts = this.deWeight(obj.parts.concat(arr))
this.$set(this.productList,this.configIndex,obj)
},
//
changeConfigNumber(e,conindex,index) {
let obj = this.productList[index]
obj.parts[conindex].number = e
this.$set(this.productList,index,obj)
},
//
delPeizhi(index,conindex) {
let obj = this.productList[index]
obj.parts.splice(conindex,1)
this.$set(this.productList,index,obj)
},
toSave() {
if(!this.customerObj.id){
uni.showToast({
title:'请选择客户名称',
icon:'none'
})
return
}
let params = this.checkCommonForm(this.listForm)
if(!params){
return
}
//
let product = []
if(this.productList.length > 0){
this.productList.forEach(ele=>{
product.push({
product_id:ele.product_id,
price: ele.price,
number: ele.number,
parts: ele.parts,
cost_price: ele.cost_price,
wholesale: ele.wholesale
})
})
}
params = Object.assign({},params,{customer_id:this.customerObj.id,product,id:this.id})
netEditBusiness(params).then(res=>{
uni.showToast({
title:res.msg,
icon:'none'
})
setTimeout(()=>{
uni.navigateBack({
delta:1
})
},2000)
})
},
}
}
</script>
<style lang="scss" scoped>
.add_in{
background-color: $uni-text-color;
color:#fff;
height:60rpx;
line-height: 60rpx;
padding:0 15rpx;
font-size: 24rpx;
border-radius: 10rpx;
}
.fllow_form {
display: flex;
justify-content: space-between;
align-items: center;
background-color: #fff;
border-bottom: 1rpx solid #EAEAEA;
padding: 30rpx 20rpx;
color: #999;
font-size: 32rpx;
.form_right {
display: flex;
align-items: center;
color: #999;
:first-child {
width: 450rpx;
text-align: right;
}
image {
width: 40rpx;
height: 40rpx;
margin: 28rpx 5rpx 0 0;
}
}
.theme {
color: #5ca9fe;
}
text {
color: #f00;
margin-left: 10rpx;
}
.form_input {
input {
text-align: right;
margin-right: 10rpx;
}
}
}
.pro_warp{
padding:30rpx 24rpx 0 24rpx;
background:#fff;
border-bottom:1rpx solid #f5f5f5;
.li_warp{
padding-bottom:24rpx;
margin-bottom:24rpx;
border-bottom:2rpx solid #f5f5f5;
&:last-child{
border-bottom:0;
}
.cell_con{
padding:0 40rpx;
.cell_con_top{
display: flex;
justify-content: space-between;
align-items: center;
.contitle{
font-size:28rpx;
color:#333;
}
.deleimg{
width:44rpx;
height:44rpx;
}
}
.pro_con_box{
display: flex;
justify-content: space-between;
align-items: center;
.context{
font-size:26rpx;
color:#666;
margin-top:10rpx;
display: flex;
justify-content: flex-start;
align-items: center;
.productPrice{
width:150rpx;
background:#f5f5f5;
text-align: center;
}
}
.conbot{
margin-top:10rpx;
display: flex;
justify-content: space-between;
align-items: center;
.conmoney{
font-size:26rpx;
color:#333;
}
}
}
.config_set{
margin-top:24rpx;
.config_title{
font-size:24rpx;
color:#333;
display: flex;
justify-content: flex-start;
align-items: center;
.addConimg{
width:100rpx;
height:40rpx;
margin-left:10rpx;
}
}
.config_list{
margin-top:24rpx;
.config_li{
display: flex;
justify-content: flex-start;
align-items: center;
margin-top:24rpx;
border-bottom:1rpx solid #f5f5f5;
padding-bottom:24rpx;
.conimg{
width:100rpx;
height:100rpx;
border-radius: 10rpx;
margin-right:20rpx;
}
.config_name{
width:290rpx;
font-size:24rpx;
color:#333;
overflow: hidden;
text-overflow:ellipsis;
white-space: nowrap;
}
.config_step{
margin-left:24rpx;
}
}
}
}
}
.right_del_btn{
width:90rpx;
height:240rpx;
background:#F00;
color:#fff;
text-align: center;
line-height: 224rpx;
}
}
}
.del{
width:40rpx;
height:40rpx;
border-radius: 50%;
border:1rpx solid #ff7800;
font-size:28rpx;
color:#ff7800;
flex-shrink: 0;
margin-right:24rpx;
text-align: center;
line-height: 38rpx;
}
</style>

399
pagesA/business/index.vue Normal file
View File

@ -0,0 +1,399 @@
<template>
<view class="">
<view class="tab_list" style="margin-top:0;">
<view class="tabli" :class="type == 0 ? 'tabliactive' : ''" @click="changeFirTab(0)">全部</view>
<view class="tabli" :class="type == 1 ? 'tabliactive' : ''" @click="changeFirTab(1)">我负责的</view>
<view class="tabli" :class="type == 2 ? 'tabliactive' : ''" @click="changeFirTab(2)">下属负责的</view>
</view>
<!-- 筛选 -->
<view class="searchbox">
<view class="searchtext" @click="toQuery">筛选<view class="iconfont icon-shaixuan"></view></view>
</view>
<view class="manage_con">
<view class="clineInfo" v-for="(item,index) in list" :key="index" @click.stop="toDetail(item)">
<view class="info_head">
<view>{{item.name}}</view>
</view>
<view class="info_main">
<view >
<view class="main_left">
<view class="left_top" v-if="item.customer" style="margin-top: 20rpx;color: #666;font-size: 30rpx;">
{{item.customer ? item.customer.name : '--'}}
</view>
<view class="left_followUp" style="margin-top: 20rpx;color: #666;font-size: 30rpx;">
<view>下次跟进时间</view>
<view>{{item.next_time ? item.next_time : '--'}}</view>
</view>
<view class="left_followUp" style="margin-top: 20rpx;color: #666;font-size: 30rpx;">
<view>商机金额</view>
<view>{{item.money ? item.money : '--'}}</view>
</view>
<view class="left_foot">
<view class="l_box">
<span v-if="item.type == 0">初期沟通</span>
<span v-if="item.type == 1">立项跟踪</span>
<span v-if="item.type == 2">方案/报价</span>
<span v-if="item.type == 3">谈判审核</span>
<span v-if="item.type == 4">赢单</span>
<span v-if="item.type == 5">输单</span>
<span v-if="item.type == 6">无效</span>
</view>
</view>
</view>
</view>
<view class="main_right" v-if="item.owner_staff">
<image :src="item.owner_staff ? item.owner_staff.img : BASE_IMG_URL+'headImg.png'" mode="scaleToFill">
</image>
<view>{{item.owner_staff?item.owner_staff.name:''}}</view>
</view>
</view>
<view class="info_footer" @click.stop.prevent>
<view class="footer_content" @click="toAddfollow(item)">
<image :src="BASE_IMG_URL+'tj.png'" mode="scaleToFill"></image>
<view>跟进</view>
</view>
<view class="footer_content" @click="toTrans(item)">
<image :src="BASE_IMG_URL+'rq.png'" mode="scaleToFill"></image>
<view>转移</view>
</view>
</view>
</view>
<view style="height: 200rpx;"></view>
<u-empty v-if="list.length == 0" text="暂无更多"></u-empty>
</view>
<view class="icon_creat" @click="addBusiness">
<image :src="BASE_IMG_URL+'1.png'" mode="scaleToFill"></image>
</view>
<view class="bot_total" @click="lookTotal">总金额合计> </view>
<uni-popup ref="popup" type="bottom" background-color="#fff" @touchmove.stop.prevent>
<view class="botwarp">
<view class="wa_li">
<view class="wa_label">商机总金额</view>
<view class="wa_money"> <text>{{moneyInfo.allmoney?moneyInfo.allmoney:'0'}}</text> </view>
</view>
<view class="wa_li">
<view class="wa_label">已成交金额</view>
<view class="wa_money"> <text>{{moneyInfo.repayment_money?moneyInfo.repayment_money:'0'}}</text> </view>
</view>
<view class="wa_li">
<view class="wa_label">未成交金额</view>
<view class="wa_money"> <text>{{moneyInfo.no_money?moneyInfo.no_money:'0'}}</text> </view>
</view>
<view class="wa_btn" @click="removeTotal">取消</view>
</view>
</uni-popup>
<!-- 筛选 -->
<screen-pop
ref="screenChild"
@sureParams="sureParams"
:searchForm="searchForm"
@changeSearchData="changeSearchData"
@resetForm="resetForm"
></screen-pop>
</view>
</template>
<script>
import { BASE_IMG_URL } from '@/util/api.js'
import { netBusinessList } from '@/api/index.js'
import screenPop from './screen.vue'
export default{
components:{
screenPop
},
data() {
return{
BASE_IMG_URL:BASE_IMG_URL,
list:[],
type:0,
page:1,
totalPage:1,
queryParams:{},
timeArr:[],
busStatus:null,
moneyInfo:{},
searchForm:[]
}
},
onLoad(options) {
if(options.type){
this.type = options.type
this.timeArr = [options.stime,options.etime]
}
if(options.busStatus){
this.busStatus = options.busStatus
this.timeArr = [options.stime,options.etime]
}
this.handleSearchForm('business',(data)=>{
this.searchForm = data
})
},
onShow() {
this.init()
},
onReachBottom() {
if(this.page < this.totalPage){
this.page ++
this.getList()
}
},
methods:{
changeSearchData(type,key,value){
let arr = this.searchForm
arr.forEach((ele,index)=>{
if(ele.field == type){
ele[key] = value
this.$set(this.searchForm, index, ele)
}
})
},
resetForm() {
this.searchForm = this.handleResetSearch(this.searchForm)
},
//
lookTotal() {
this.$refs.popup.open()
},
removeTotal() {
this.$refs.popup.close()
},
init() {
this.page = 1
this.list = []
this.getList()
},
changeFirTab(type) {
this.type = type
this.init()
},
toQuery() {
let params = {
timeArr:this.timeArr,
busStatus:this.busStatus
}
this.$refs.screenChild.init(params)
},
sureParams(params) {
this.queryParams = params
this.init()
},
getList() {
let params = {
page:this.page,
type:this.type,
contract_status:this.busStatus,
createtime:this.timeArr.length > 0 ? (this.timeArr[0] + ',' + this.timeArr[1]) : '',
...this.queryParams,
...this.handleSureSearch(this.searchForm)
}
netBusinessList(params).then(res=>{
this.list = this.list.concat(res.data.data)
this.totalPage = res.data.last_page
this.moneyInfo = res.data.moneyinfo
})
},
addBusiness(){
uni.navigateTo({
url:'/pagesA/business/addBusiness'
})
},
//
toDetail(item){
uni.navigateTo({
url:'/pagesA/business/detail?id='+item.id
})
},
//
toAddfollow(item) {
uni.navigateTo({
url: '/pagesA/crm/customerManagement/newFllow/newFllow?id='+item.id+'&type=5'
})
},
//
toTrans(item) {
uni.navigateTo({
url:'/pagesA/business/trans?id='+item.id
})
}
}
}
</script>
<style lang="scss" scoped>
.clineInfo {
background-color: #fff;
padding: 30rpx 45rpx;
margin-bottom: 20rpx;
border-radius: 10rpx;
box-shadow: 2rpx 2rpx 50rpx rgba(0, 0, 0, 0.1);
.info_head {
display: flex;
justify-content: space-between;
:first-child {
font-size: 34rpx;
font-weight: 700;
color: #333;
}
}
.info_main {
display: flex;
justify-content: space-between;
.main_left {
.left_followUp {
display: flex;
font-size: 30rpx;
color: #666;
}
.left_star {
font-size: 30rpx;
color: #666;
display: flex;
padding-bottom: 30rpx;
}
.left_foot {
padding-bottom: 20rpx;
margin-top:25rpx;
.l_box {
margin-right: 35rpx;
float: left;
span {
background: $uni-text-color-opcity;
padding: 5rpx 12rpx;
font-size: 26rpx;
color: $uni-text-color;
border-radius: 5rpx;
}
}
}
}
.main_right {
text-align: center;
padding: 20rpx 15rpx 0 0;
image {
border-radius: 50%;
width: 129rpx;
height: 129rpx;
margin-bottom: 5rpx;
}
}
}
.info_footer {
display: flex;
justify-content: space-around;
padding-top: 30rpx;
height: 80rpx;
border-top: 1px solid #ededed;
margin-top: 20rpx;
.footer_content {
// width: 25%;
line-height: 28rpx;
display: flex;
justify-content: center;
align-items: center;
image{
width: 48rpx;
height: 48rpx;
margin-right: 15rpx;
}
}
}
}
.searchbox{
display: flex;
justify-content: flex-end;
margin:24rpx;
.searchtext{
display: flex;
justify-content: center;
align-items: center;
font-size:24rpx;
color:$uni-text-color;
padding:8rpx 28rpx;
background:#fff;
border-radius: 5rpx;
box-shadow: 2rpx 2rpx 50rpx rgba(0,0,0,0.1);
.icon-shaixuan{
color:$uni-text-color;
}
}
}
.tab_list{
width:750rpx;
height:80rpx;
display: flex;
justify-content: space-around;
align-items: center;
background:#fff;
.tabli{
font-size:24rpx;
color:#333;
line-height: 75rpx;
text-align: center;
border-bottom:4rpx solid #fff;
}
.tabliactive{
border-bottom:4rpx solid $uni-text-color;
}
}
.bot_total{
position: fixed;
left:0;
bottom:0;
width:750rpx;
height:calc(80rpx + env(safe-area-inset-bottom) / 2);
background:#fff;
font-size:24rpx;
color:#333;
text-align: center;
line-height: 80rpx;
color:$uni-text-color;
border-top:1rpx solid #f5f5f5;
padding-bottom:calc(env(safe-area-inset-bottom) / 2);
}
.botwarp{
background:#fff;
padding:0 24rpx;
.wa_li{
padding:24rpx 35rpx;
border-bottom:1rpx solid #f5f5f5;
display: flex;
justify-content: space-between;
align-items: center;
.wa_label{
font-size:24rpx;
color:#333;
}
.wa_money{
font-size:24rpx;
color:#666;
text{
color:$uni-text-color;
}
}
}
.wa_btn{
width:100%;
height:100rpx;
font-size:24rpx;
color:$uni-text-color;
text-align: center;
line-height: 100rpx;
}
}
</style>

View File

@ -0,0 +1,128 @@
<template>
<view class="">
<scroll-view scroll-y="true" class="scrollbox">
<view class="lxr_con_list" v-for="(item,index) in contract_list" :key="index"
@click="toContractDetail(item.id)">
<view class="name">{{item.name?item.name:'--'}}</view>
<view class="info_box">
<view class="info_left">
<view class="info">关联客户{{item.customer?item.customer.name:'--'}}</view>
<view class="info">合同编号{{item.num}}</view>
<view class="info">已回款&yen;{{item.receivables.repayment_money}}</view>
<view class="info">待回款&yen;{{item.receivables.be_money}}</view>
<view class="info">签约时间{{item.order_date}}</view>
<view class="con_status" v-if="item.check_status == 0">
<span>待审核</span>
</view>
<view class="con_status" v-if="item.check_status == 1">
<span>审核中</span>
</view>
<view class="con_status pass" v-if="item.check_status == 2">
<span>审核通过</span>
</view>
<view class="con_status nopass" v-if="item.check_status == 3">
<span>审核未通过</span>
</view>
<view class="con_status nopass" v-if="item.check_status == 4">
<span>已撤回</span>
</view>
</view>
<view class="pro_li_right">&yen;{{item.money}}</view>
</view>
</view>
<u-empty v-if="contract_list.length == 0" text="暂无更多"></u-empty>
</scroll-view>
</view>
</template>
<script>
import { netRelationContract } from '@/api/index.js'
export default{
props:{
info:{
type:Object,
default:{}
}
},
data() {
return{
contract_list:[]
}
},
created() {
this.getList()
},
methods:{
getList(){
netRelationContract({id:this.info.id}).then(res=>{
this.contract_list = res.data.data
console.log(this.contract_list,'====')
})
},
//
toContractDetail(id) {
uni.navigateTo({
url: '/pagesB/contract/contractDetail?id=' + id
})
},
}
}
</script>
<style lang="scss" scoped>
.scrollbox{
height:900rpx;
}
.lxr_con_list {
width:690rpx;
margin:24rpx auto 0;
padding: 20rpx 0;
background: #fff;
box-sizing: border-box;
border-radius: 20rpx;
&:last-child {
border-bottom: none;
}
.name {
font-size: 34rpx;
color: #333333;
font-weight: 500;
border-bottom: 1rpx solid #ededed;
padding:0 24rpx 24rpx;
}
.info_box{
display: flex;
justify-content: space-between;
align-items: center;
padding:24rpx;
.info {
font-size: 32rpx;
color: #999999;
margin: 10rpx 0;
}
.pro_li_right {
color: $uni-text-color;
font-size: 33rpx;
font-weight: 500;
}
}
.con_status {
width: 130rpx;
height: 36rpx;
text-align: center;
line-height: 36rpx;
background: $uni-text-color-opcity;
margin-top: 30rpx;
span {
font-size: 26rpx;
color: $uni-text-color;
}
}
.nopass {
color: #ec7f51;
}
.pass {
color: #22A7F6;
}
}
</style>

233
pagesA/business/screen.vue Normal file
View File

@ -0,0 +1,233 @@
<template>
<view class="">
<uni-popup ref="popup" type="top" background-color="#fff">
<scroll-view scroll-y class="scrollbox" style="height:600rpx;background:#fff;" >
<!--筛选模块 -->
<view class="screen_content" @tap.stop.prevent>
<view class="fir_li">
<view class="li_label">关联客户</view>
<view class="li_box" @click="toSelectCustomer">
<view class="form_right" style="text-align: center;">
<view :class="customerObj.id ? 'valueActive' : ''">
{{customerObj.id ? customerObj.name : '点击选择'}}
</view>
<view class="iconfont icon-arrows_right"></view>
</view>
</view>
</view>
<view class="fir_li">
<view class="li_label">归属人</view>
<view class="li_box" @click="toSelectStaff">
<view class="form_right">
<view :class="staffObj.id ? 'valueactive' : '' ">
{{staffObj.id ? staffObj.name : '点击选择'}}</view>
<view class="iconfont icon-arrows_right"></view>
</view>
</view>
</view>
<view class="fir_li">
<view class="li_label">成交状态</view>
<view class="li_box">
<picker @change="changeStatus" :range="statusArr" :value="statusIndex" :range-key="'name'">
<view class="form_right">
<view style="flex:1;text-align: center;"
:class="statusArr[statusIndex] ? 'valueactive' : '' ">{{statusArr[statusIndex] ? statusArr[statusIndex].name : '成交状态'}}
</view>
</view>
</picker>
</view>
</view>
<view class="fir_li">
<view class="li_label">时间筛选</view>
<view class="li_box" style="display: flex;">
<picker @change="changeStartTime" mode="date" :end="end_time"
style="width:50%;border-right:1rpx solid #CCCCCC">
<view class="form_right">
<view style="flex:1;text-align: center;"
:class="start_time ? 'valueactive' : '' ">
{{start_time ? start_time : '开始时间'}}</view>
</view>
</picker>
<picker @change="changeEndTime" mode="date" :start="start_time" style="width:50%">
<view class="form_right">
<view style="flex:1;text-align: center;"
:class="end_time ? 'valueactive' : '' ">{{end_time ? end_time : '结束时间'}}
</view>
</view>
</picker>
</view>
</view>
<search-item v-for="(item,index) in searchForm" :key="index" :objInfo="item" @changeSearchData="changeSearchData"></search-item>
</view>
</scroll-view>
<view class="button_bottom">
<view @tap.stop="reset">重置</view>
<view @tap.stop="sureQuery">确定</view>
</view>
</uni-popup>
<select-customer ref="customerChild" @getCustomerinfo="getCustomerinfo"></select-customer>
<select-staff ref="staffChild" @sureStaff="sureStaff"></select-staff>
</view>
</template>
<script>
import selectCustomer from '@/components/selectCustomer.vue'
import selectStaff from '@/components/selectStaff.vue'
import searchItem from '@/components/search/searchitem.vue'
export default{
components:{
selectCustomer,
selectStaff,
searchItem
},
props:{
searchForm:{
type:Array,
default:[]
}
},
data() {
return{
times:'',
staffObj:{},
customerObj:{},
start_time:'',
end_time:'',
showIndex:1,
contract_status:null, //1 2
statusArr:[
{id:1,name:'未成交'},
{id:2,name:'已成交'}
],
statusIndex:null,
}
},
methods:{
init(obj) {
this.$refs.popup.open()
if(obj.timeArr && obj.timeArr.length!=0 && this.showIndex == 1){
this.start_time = obj.timeArr[0]
this.end_time = obj.timeArr[1]
}
this.statusIndex = obj.statusIndex
},
close() {
this.$refs.popup.close()
},
changeStatus(e) {
this.statusIndex = e.detail.value
},
toSelectCustomer() {
this.$refs.customerChild.init()
},
getCustomerinfo(obj) {
this.customerObj = obj
},
//
toSelectStaff() {
this.$refs.staffChild.init()
},
sureStaff(obj) {
this.staffObj = obj
},
changeStartTime(e) {
this.showIndex = 2
this.start_time = e.detail.value
if(!this.end_time){
this.end_time = e.detail.value
}
},
changeEndTime(e) {
this.showIndex = 2
this.end_time = e.detail.value
if(!this.start_time){
this.start_time = e.detail.value
}
},
changeSearchData(type,key,value){
this.$emit('changeSearchData',type,key,value)
},
reset() {
this.customerObj = {}
this.staffObj = {}
this.start_time = ''
this.end_time = ''
this.statusIndex = null
this.$emit('resetForm')
},
sureQuery() {
let params = {
createtime:(this.start_time && this.end_time) ? (this.start_time + ',' + this.end_time) : '',
customer_id:this.customerObj.id?this.customerObj.id:'',
staff_id:this.staffObj.id?this.staffObj.id:'',
contract_status:this.statusArr[this.statusIndex]?this.statusArr[this.statusIndex].id:'',
}
this.close()
this.$emit('sureParams',params)
}
}
}
</script>
<style lang="scss" scoped>
.screen_content {
width:702rpx;
z-index: 2;
border-top:1rpx solid #CCCCCC;
background-color: #fff;
padding:24rpx;
.fir_li{
margin-bottom:20rpx;
.li_label{
font-size:28rpx;
color:#333333;
margin-bottom:15rpx;
}
.li_box{
border-radius: 15rpx;
border:1rpx solid #CCCCCC;
height:60rpx;
padding:0 35rpx;
line-height: 60rpx;
}
.form_right {
display: flex;
justify-content: space-between;
color:#999;
image {
width: 40rpx;
height: 40rpx;
margin: 28rpx 5rpx 0 0;
}
.rightinput{
height:60rpx;
line-height: 60rpx;
width:100%;
}
}
}
}
.button_bottom {
display: flex;
width: 100%;
height: 90rpx;
background-color: #fff;
line-height: 90rpx;
text-align: center;
font-size: 32rpx;
:first-child {
flex: 1;
color: $uni-text-color;
border-top:1rpx solid #CCCCCC;
}
:last-child {
flex: 1;
background-color: $uni-text-color;
color: #fff;
}
}
</style>

129
pagesA/business/trans.vue Normal file
View File

@ -0,0 +1,129 @@
<template>
<view class="tranfer_clue">
<view class="fllow_form">
<view style="color: #333;font-size: 32rpx;"><text>*</text>接收对象</view>
<view class="form_right" @click="changeStaff">
<view>{{staffObj.id ? staffObj.name : '点击选择'}}</view>
<view class="iconfont icon-arrows_right"></view>
</view>
</view>
<view id="btn" class="btn_g bg-blue button-hover round" @click="Totrans">
保存
</view>
<!-- 选择员工 -->
<select-staff ref="staffChild" @sureStaff="sureSelect" :type="2"></select-staff>
</view>
</template>
<script>
import { netTransBusiness } from '@/api/index.js'
import { BASE_IMG_URL } from '@/util/api.js'
import selectStaff from '@/components/selectStaff.vue'
export default {
components:{
selectStaff
},
data() {
return {
id:'',
staffObj:{},
}
},
onLoad(options) {
this.id = options.id
},
onShow() {
},
methods: {
changeStaff(e) {
this.$refs.staffChild.init()
},
sureSelect(obj) {
this.staffObj = obj
},
Totrans() {
if(!this.staffObj.id){
uni.showToast({
title:'请选择接受对象',
icon:'none'
})
return
}
let params = {
id:this.id,
owner_staff_id: this.staffObj.id
}
netTransBusiness(params).then(res=>{
uni.showToast({
title:res.msg,
icon:'none'
})
setTimeout(()=>{
uni.redirectTo({
url:"/pagesA/business/index"
})
},1000)
})
}
}
}
</script>
<style lang="scss" scoped>
.fllow_form {
display: flex;
justify-content: space-between;
height: 100rpx;
line-height: 100rpx;
background-color: #fff;
border-bottom: 1rpx solid #EAEAEA;
padding: 0 30rpx 0 47rpx;
margin: 0 0 30rpx;
.form_right {
display: flex;
color: #999;
image {
width: 40rpx;
height: 40rpx;
margin: 28rpx 5rpx 0 0;
}
}
text {
color: #f00;
margin-left: 10rpx;
}
}
.fllow_area {
background-color: #fff;
margin-bottom: 30rpx;
padding-bottom: 30rpx;
color: #999;
.area_head {
height: 100rpx;
line-height: 100rpx;
font-size: 32rpx;
padding: 0 70rpx;
text {
color: #f00;
}
}
textarea {
width: 80%;
height: 300rpx;
padding: 30rpx;
background: #f8f8f8;
margin: 0 auto;
}
}
#btn {
font-size: 26rpx;
color: #fff;
text-align: center;
line-height: 88rpx;
width: 500rpx;
height: 88rpx;
background: $uni-text-color;
border-radius: 29rpx;
}
</style>

88
pagesA/circulate/add.vue Normal file
View File

@ -0,0 +1,88 @@
<template>
<view>
<!-- 添加成员 -->
<examine-people title="添加成员" :list="remindPeople" @delItem="delItem"></examine-people>
<view class="staffli">
<view class="statext">权限</view>
<picker @change="changePre" :range="preArr" :value="preIndex">
<view class="liright">
{{preArr[preIndex]?preArr[preIndex]:'请选择'}}
<view class="iconfont icon-you"></view>
</view>
</picker>
</view>
<view class="button" @click="$noMultipleClicks(sureSub)">确定</view>
</view>
</template>
<script>
export default{
data() {
return{
noClick:true, //
id:'',
type:'',
preArr:['只读','读写'],
preIndex:0
}
},
onLoad(options) {
this.id = options.id
},
onShow() {
},
methods:{
changePre(e) {
this.preIndex = e.detail.value
},
sureSub() {
if(this.remindPeople.length == 0) {
uni.showToast({
title:'请选择成员',
icon:'none'
})
return
}
let arr = []
this.remindPeople.forEach(ele=>{
arr.push(ele.id)
})
let params = {
id:this.id,
staff_id:arr.join(','),
is_edit:this.preIndex
}
},
}
}
</script>
<style lang="scss" scoped>
.staffli{
display: flex;
justify-content: space-between;
align-items: center;
padding:24rpx 35rpx;
border-top:1rpx solid #f5f5f5;
border-bottom:1rpx solid #f5f5f5;
.statext{
font-size:26rpx;
color:#666;
}
.liright{
display: flex;
justify-content: flex-end;
align-items: center;
font-size:26rpx;
color:#666;
.icon-you{
font-size:28rpx;
}
}
}
</style>

231
pagesA/circulate/edit.vue Normal file
View File

@ -0,0 +1,231 @@
<template>
<view>
<view class="tit_warp">
<view class="cirtit">负责人</view>
</view>
<view class="cirinfo" v-for="(item,index) in arr" :key="index" v-if="item.roles == 1">
<image :src="item.img?item.img:BASE_IMG_URL+'headImg.png'" class="staffimg" mode=""></image>
<view class="staffinfo">
<view class="staffright" @click="toSelectStaff">
<view class="ri_left">
<view class="name">{{item.name}}</view>
<!-- <view class="post">{{item.post}}</view> -->
</view>
<view class="iconfont icon-you"></view>
</view>
<view class="staffli" @click="noChange">
<view class="statext">权限</view>
<view class="liright">
负责人
<view class="iconfont icon-arrows_right"></view>
</view>
</view>
</view>
</view>
<view class="tit_warp">
<view class="cirtit">团队成员</view>
<view class="titright" @click="toSelect">添加团队成员</view>
</view>
<view class="cirinfo" v-for="(item,index) in arr" :key="index" v-if="item.roles == 2">
<image :src="item.img?item.img:BASE_IMG_URL+'headImg.png'" class="staffimg" mode=""></image>
<view class="staffinfo">
<view class="staffright">
<view class="ri_left">
<view class="name">{{item.name}}</view>
<!-- <view class="post">{{item.post}}</view> -->
</view>
<image :src="BASE_IMG_URL+'delete1.png'" @click="delFollow(index)" class="deleimg" mode=""></image>
</view>
<view class="staffli">
<view class="statext">权限</view>
<picker @change="(e)=>{changePre(e,index)}" :range="preArr" :value="preIndex">
<view class="liright">
{{preArr[item.is_edit]?preArr[item.is_edit]:'请选择'}}
<view class="iconfont icon-arrows_right"></view>
</view>
</picker>
</view>
</view>
</view>
<view id="btn" class="btn_g bg-blue button-hover round" @click="$noMultipleClicks(sureSub)">
确定
</view>
<!-- 选择成员 -->
<select-staff ref="staffChild" @sureStaff="sureStaff" :type="2"></select-staff>
</view>
</template>
<script>
import { BASE_IMG_URL} from '@/util/api.js'
import { netTeamList, netTeamEdit } from '@/api/index.js'
import selectStaff from '@/components/selectStaff.vue'
export default{
components:{
selectStaff
},
data() {
return{
noClick:true, //
BASE_IMG_URL:BASE_IMG_URL,
id:'',
type:'',
arr:[],
preArr:['只读','读写'],
preIndex:0
}
},
onLoad(options) {
this.id = options.id
this.getList()
},
methods:{
changePre(e,index) {
let obj = this.arr[index]
obj.is_edit = e.detail.value
this.$set(this.arr,index,obj)
},
toSelect() {
this.$refs.staffChild.init()
},
sureStaff(obj) {
if(obj.id){
let flag = false
this.arr.forEach(ele=>{
if(ele.id == obj.id){
flag = true
}
})
if(!flag){
let item = {
id:obj.id,
img:obj.img,
name:obj.name,
post:obj.post,
roles:2,
is_edit:0
}
this.arr.push(item)
}
}
},
delFollow(index) {
this.arr.splice(index,1)
},
getList() {
netTeamList({id:this.id}).then(res=>{
this.arr = res.data
})
},
sureSub() {
let a = []
this.arr.forEach(ele=>{
if(ele.roles == 2){
a.push({
id:ele.id,
is_edit:ele.is_edit
})
}
})
let params = {
id:this.id,
staff:a
}
netTeamEdit(params).then(res=>{
uni.showToast({
title:res.msg,
icon:'none'
})
setTimeout(()=>{
uni.navigateBack({
delta:1
})
},2000)
})
},
noChange() {
uni.showToast({
title:'不允许修改负责人',
icon:'none'
})
}
}
}
</script>
<style lang="scss" scoped>
.tit_warp{
display: flex;
justify-content: space-between;
align-items: center;
padding:24rpx 30rpx;
border-bottom:1rpx solid #d2d0d0;
.cirtit{
font-size:28rpx;
}
.titright{
font-size:24rpx;
color:$uni-text-color;
}
}
.cirinfo{
padding:24rpx;
border-bottom:1rpx solid #d2d0d0;
display: flex;
justify-content: flex-start;
&:last-child{
border-bottom:0;
}
.staffimg{
width:80rpx;
height:80rpx;
border-radius: 50%;
margin-right:24rpx;
}
.staffinfo{
flex:1;
.staffright{
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom:24rpx;
.ri_left{
.name{
font-size:26rpx;
color:#333;
}
.post{
font-size:24rpx;
color:#666;
margin-top:15rpx;
}
}
.deleimg{
width:44rpx;
height:44rpx;
}
}
.staffli{
display: flex;
justify-content: space-between;
align-items: center;
padding:24rpx 0;
border-top:1rpx solid #d2d0d0;
.statext{
font-size:26rpx;
color:#666;
}
.liright{
display: flex;
justify-content: flex-end;
align-items: center;
color:#666;
font-size:28rpx;
}
}
}
}
</style>

141
pagesA/circulate/index.vue Normal file
View File

@ -0,0 +1,141 @@
<template>
<view>
<view class="opewrap">
<view class="operation" @click="toEdit">修改</view>
</view>
<view class="cirtit">负责人</view>
<view class="peobox">
<view class="peoinfo" v-for="(item,index) in list" :key="index" v-if="item.roles == 1">
<image :src="item.img?item.img:BASE_IMG_URL+'headImg.png'" class="peoimg" mode=""></image>
<view class="peoright">
<view class="pr_left">
<view class="name">{{item.name}}</view>
<!-- <view class="pr_post">{{item.post}} - {{item.name}}</view> -->
<view class="pr_text">团队角色 负责人</view>
<view class="pr_text">权限 负责人</view>
</view>
<image :src="BASE_IMG_URL+'call.png'" @click="toCall(item)" class="pr_phone" mode="">
</view>
</view>
</view>
<view class="cirtit">团队成员</view>
<view class="peobox">
<view class="peoinfo" v-for="(item,index) in list" :key="index" v-if="item.roles == 2">
<image :src="item.img?item.img:BASE_IMG_URL+'headImg.png'" class="peoimg" mode=""></image>
<view class="peoright">
<view class="pr_left">
<view class="name">{{item.name}}</view>
<!-- <view class="pr_post">{{item.post}} - {{item.name}}</view> -->
<view class="pr_text">团队角色 普通员工</view>
<view class="pr_text" v-if="item.is_edit == 0">权限 只读</view>
<view class="pr_text" v-if="item.is_edit == 1">权限 读写</view>
</view>
<image :src="BASE_IMG_URL+'call.png'" @click="toCall(item)" class="pr_phone" mode="">
</view>
</view>
</view>
<view style="height:30rpx;"></view>
</view>
</template>
<script>
import { BASE_IMG_URL } from '@/util/api.js'
import { netTeamList } from '@/api/index.js'
export default{
data() {
return{
BASE_IMG_URL:BASE_IMG_URL,
id:'',
list:[]
}
},
onLoad(options) {
this.id = options.id
},
onShow() {
this.getList()
},
methods:{
getList() {
netTeamList({id:this.id}).then(res=>{
this.list = res.data
})
},
toCall(item) {
uni.makePhoneCall({
phoneNumber:item.mobile
})
},
toEdit() {
uni.navigateTo({
url:'/pagesA/circulate/edit?id='+this.id
})
},
}
}
</script>
<style lang="scss" scoped>
.opewrap{
padding:35rpx 35rpx 0;
display: flex;
justify-content: flex-end;
align-items: center;
.operation{
font-size:28rpx;
color:$uni-text-color;
font-weight: bold;
margin-left:30rpx;
}
}
.cirtit{
padding:24rpx 30rpx;
font-size:28rpx;
border-bottom:1rpx solid #d2d0d0;
}
.peobox{
.peoinfo{
padding:24rpx 30rpx;
display: flex;
justify-content: flex-start;
border-bottom:1rpx solid #d2d0d0;
&:last-child{
border-bottom:0;
}
.peoimg{
width:100rpx;
height:100rpx;
border-radius: 50%;
flex-shrink: 0;
margin-right:24rpx;
}
.peoright{
display: flex;
justify-content: space-between;
align-items: center;
flex:1;
.pr_left{
.name{
font-size:28rpx;
color:#333;
margin-bottom:15rpx;
}
.pr_post{
font-size:26rpx;
color:#666;
}
.pr_text{
font-size:26rpx;
color:#999;
}
}
.pr_phone{
width:42rpx;
height:40rpx;
}
}
}
}
</style>

220
pagesA/cost/index.vue Normal file
View File

@ -0,0 +1,220 @@
<template>
<view class="">
<view class="tab_list">
<view class="tabli" :class="type == 0 ? 'tabliactive' : ''" @click="changeFirTab(0)">全部</view>
<view class="tabli" :class="type == 1 ? 'tabliactive' : ''" @click="changeFirTab(1)">我负责的</view>
<view class="tabli" :class="type == 2 ? 'tabliactive' : ''" @click="changeFirTab(2)">下属负责的</view>
</view>
<!-- 筛选 -->
<view class="searchbox">
<view class="searchtext" @click="toQuery">筛选<view class="iconfont icon-shaixuan"></view></view>
</view>
<scroll-view scroll-y class="scrollbox" @scrolltolower="loodMore">
<view class="payList">
<cost-item :list="list"></cost-item>
</view>
</scroll-view>
<view style="height: 200rpx;"></view>
<view class="bot_total" @click="lookTotal">总金额合计> </view>
<uni-popup ref="popup" type="bottom" background-color="#fff" @touchmove.stop.prevent>
<view class="botwarp">
<view class="wa_li">
<view class="wa_label">总金额</view>
<view class="wa_money"> <text>{{moneyInfo.allmoney?moneyInfo.allmoney:'0'}}</text> </view>
</view>
<view class="wa_li">
<view class="wa_label">费用待审核总金额</view>
<view class="wa_money"> <text>{{moneyInfo.inmoney?moneyInfo.inmoney:'0'}}</text> </view>
</view>
<view class="wa_li">
<view class="wa_label">费用审核通过总金额</view>
<view class="wa_money"> <text>{{moneyInfo.remoney?moneyInfo.remoney:'0'}}</text> </view>
</view>
<view class="wa_li">
<view class="wa_label">费用审核未通过金额</view>
<view class="wa_money"> <text>{{moneyInfo.nomoney?moneyInfo.nomoney:'0'}}</text> </view>
</view>
<view class="wa_btn" @click="removeTotal">取消</view>
</view>
</uni-popup>
<view class="icon_creat" @click="addCost">
<image :src="BASE_IMG_URL+'1.png'" mode="scaleToFill"></image>
</view>
<screen-pop ref="screenChild" @sureParams="surePa"></screen-pop>
</view>
</template>
<script>
import screenPop from './screen.vue'
import { netCostList } from '@/api/kehu.js'
import costItem from './item.vue'
import { BASE_IMG_URL } from '@/util/api.js'
export default{
components:{
screenPop,
costItem
},
data() {
return{
BASE_IMG_URL:BASE_IMG_URL,
type:0,
page:1,
totalPage:1,
list:[],
queryParams:{},
moneyInfo:{}
}
},
onLoad() {
},
onShow() {
this.init()
},
methods:{
//
lookTotal() {
this.$refs.popup.open()
},
removeTotal() {
this.$refs.popup.close()
},
changeFirTab(type) {
this.type = type
this.init()
},
surePa(params){
this.queryParams = params
this.init()
},
toQuery() {
this.$refs.screenChild.init()
},
loodMore() {
if(this.page < this.totalPage){
this.page ++
this.getList()
}
},
init() {
this.page = 1
this.list = []
setTimeout(()=>{
this.getList()
},200)
},
getList() {
let params = {
type:this.type,
page:this.page,
...this.queryParams
}
netCostList(params).then(res=>{
this.list = this.list.concat(res.data.data)
this.totalPage = res.data.last_page
this.moneyInfo = res.data.moneyinfo
})
},
//
addCost() {
uni.navigateTo({
url: '/pages/index/groupCompany/cost/addCost'
})
},
}
}
</script>
<style lang="scss" scoped>
.bot_total{
position: fixed;
left:0;
bottom:0;
width:750rpx;
height:calc(80rpx + env(safe-area-inset-bottom) / 2);
background:#fff;
font-size:24rpx;
color:#333;
text-align: center;
line-height: 80rpx;
color:$uni-text-color;
border-top:1rpx solid #f5f5f5;
padding-bottom:calc(env(safe-area-inset-bottom) / 2);
}
.botwarp{
background:#fff;
padding:0 24rpx;
.wa_li{
padding:24rpx 35rpx;
border-bottom:1rpx solid #f5f5f5;
display: flex;
justify-content: space-between;
align-items: center;
.wa_label{
font-size:24rpx;
color:#333;
}
.wa_money{
font-size:24rpx;
color:#666;
text{
color:$uni-text-color;
}
}
}
.wa_btn{
width:100%;
height:100rpx;
font-size:24rpx;
color:$uni-text-color;
text-align: center;
line-height: 100rpx;
}
}
.tab_list{
width:750rpx;
height:80rpx;
display: flex;
justify-content: space-around;
align-items: center;
background:#fff;
.tabli{
font-size:24rpx;
color:#333;
line-height: 75rpx;
text-align: center;
border-bottom:4rpx solid #fff;
}
.tabliactive{
border-bottom:4rpx solid $uni-text-color;
}
}
.searchbox{
display: flex;
justify-content: flex-end;
margin:24rpx;
.searchtext{
display: flex;
justify-content: center;
align-items: center;
font-size:24rpx;
color:$uni-text-color;
padding:8rpx 28rpx;
background:#fff;
border-radius: 5rpx;
box-shadow: 2rpx 2rpx 50rpx rgba(0,0,0,0.1);
.icon-shaixuan{
color:$uni-text-color;
}
}
}
.scrollbox{
width:750rpx;
height:calc(100vh - 180rpx);
}
</style>

103
pagesA/cost/item.vue Normal file
View File

@ -0,0 +1,103 @@
<template>
<view class="">
<view class="cost" v-for="(item,index) in list" :key="index" @click="toDetail(item)">
<view class="cost_status" v-if="item.check_status == 0"><span>待审核</span></view>
<view class="cost_status" v-if="item.check_status == 1"><span>审核中</span></view>
<view class="cost_status" v-if="item.check_status == 2"><span>审核通过</span></view>
<view class="cost_status" v-if="item.check_status == 3"><span>审核未通过</span></view>
<view class="cost_status" v-if="item.check_status == 4"><span>撤销</span></view>
<view class="cost_type">{{item.consume_type}}</view>
<view class="cost_info">
<view class="cost_left">
<view class="cost_text">关联客户{{item.customer.name}}</view>
<view class="cost_text">费用金额{{item.money}}</view>
<view class="cost_text">消费日期{{item.consume_time}}</view>
</view>
<view class="cost_right">
<image :src="item.staff.img" class="staffimg" mode=""></image>
<view class="staffname">{{item.staff.name}}</view>
</view>
</view>
</view>
<u-empty v-if="list.length == 0" text="暂无更多"></u-empty>
</view>
</template>
<script>
export default{
props:{
list:{
type:Array,
default:[]
}
},
data() {
return{
}
},
methods:{
toDetail(item) {
uni.navigateTo({
url:'/pages/index/groupCompany/cost/costDetail?id='+item.id
})
}
}
}
</script>
<style lang="scss" scoped>
.cost{
width:690rpx;
margin:0 auto 24rpx;
background:#fff;
border-radius: 20rpx;
padding:30rpx;
position: relative;
.cost_type{
font-size:28rpx;
color:#333;
padding-bottom:15rpx;
border-bottom:1rpx solid #f5f5f5;
}
.cost_status{
position: absolute;
right:24rpx;
top:24rpx;
background:$uni-text-color-opcity;
border-radius: 5rpx;
font-size: 26rpx;
color: $uni-text-color;
padding: 5rpx 12rpx;
}
.cost_info{
display: flex;
justify-content: space-between;
align-items: center;
padding:10rpx;
.cost_left{
.cost_text{
font-size:24rpx;
color:#999;
margin-bottom:10rpx;
}
}
.cost_right{
display: flex;
flex-direction: column;
align-items: center;
.staffimg{
width:80rpx;
height:80rpx;
border-radius: 50%;
margin-bottom:8rpx;
}
.staffname{
font-size:24rpx;
color:#999;
}
}
}
}
</style>

188
pagesA/cost/screen.vue Normal file
View File

@ -0,0 +1,188 @@
<template>
<view class="">
<uni-popup ref="popup" type="top" background-color="#fff">
<scroll-view scroll-y class="scrollbox" style="height:600rpx;background:#fff;" >
<!--筛选模块 -->
<view class="screen_content" @tap.stop.prevent>
<view class="fir_li">
<view class="li_label">关联客户</view>
<view class="li_box" @click="toSelectCustomer">
<view class="form_right" style="text-align: center;">
<view :class="customerObj ? 'valueActive' : ''">
{{customerObj ? customerObj.name : '点击选择'}}
</view>
<view class="iconfont icon-arrows_right"></view>
</view>
</view>
</view>
<view class="fir_li">
<view class="li_label">费用状态</view>
<picker @change="changeTab" :value="check_status" :range="statusList" :range-key="'name'">
<view class="li_box" >
<view class="form_right" style="text-align: center;">
<view :class="statusList[check_status] ? 'valueActive' : ''">
{{statusList[check_status] ? statusList[check_status].name : '点击选择'}}
</view>
<view class="iconfont icon-arrows_right"></view>
</view>
</view>
</picker>
</view>
<view class="fir_li">
<view class="li_label">时间筛选</view>
<view class="li_box" style="display: flex;">
<picker @change="changeStartTime" mode="date" :end="end_time"
style="width:50%;border-right:1rpx solid #CCCCCC">
<view class="form_right">
<view style="flex:1;text-align: center;"
:class="start_time ? 'valueactive' : '' ">
{{start_time ? start_time : '开始时间'}}</view>
</view>
</picker>
<picker @change="changeEndTime" mode="date" :start="start_time" style="width:50%">
<view class="form_right">
<view style="flex:1;text-align: center;"
:class="end_time ? 'valueactive' : '' ">{{end_time ? end_time : '结束时间'}}
</view>
</view>
</picker>
</view>
</view>
</view>
</scroll-view>
<view class="button_bottom">
<view @tap.stop="reset">重置</view>
<view @tap.stop="sureQuery">确定</view>
</view>
</uni-popup>
<select-customer ref="customerChild" @getCustomerinfo="getCustomerinfo"></select-customer>
</view>
</template>
<script>
import selectCustomer from '@/components/selectCustomer.vue'
export default{
components:{
selectCustomer
},
data() {
return{
times:'',
statusList:[
{id:1,name:'待审核'},
{id:2,name:'审核通过'},
{id:3,name:'审核拒绝'}
],
check_status:null,
customerObj:null,
start_time:'',
end_time:''
}
},
methods:{
init() {
this.$refs.popup.open()
},
close() {
this.$refs.popup.close()
},
toSelectCustomer() {
this.$refs.customerChild.init()
},
getCustomerinfo(obj) {
this.customerObj = obj
},
changeTab(e) {
this.check_status = e.detail.value
},
changeStartTime(e) {
this.start_time = e.detail.value
if(!this.end_time){
this.end_time = e.detail.value
}
},
changeEndTime(e) {
this.end_time = e.detail.value
if(!this.start_time){
this.start_time = e.detail.value
}
},
reset() {
this.check_status = null
this.customerObj = null
this.start_time = ''
this.end_time = ''
},
sureQuery() {
let params = {
times:(this.start_time && this.end_time) ? (this.start_time + ',' + this.end_time) : '',
check_status:this.statusList[this.check_status]?this.statusList[this.check_status].id:'',
customer_id:this.customerObj?this.customerObj.id:''
}
this.close()
this.$emit('sureParams',params)
}
}
}
</script>
<style lang="scss" scoped>
.screen_content {
width:702rpx;
z-index: 2;
border-top:1rpx solid #CCCCCC;
background-color: #fff;
padding:24rpx;
.fir_li{
margin-bottom:20rpx;
.li_label{
font-size:28rpx;
color:#333333;
margin-bottom:15rpx;
}
.li_box{
border-radius: 15rpx;
border:1rpx solid #CCCCCC;
height:60rpx;
padding:0 35rpx;
line-height: 60rpx;
}
.form_right {
display: flex;
justify-content: space-between;
color:#999;
image {
width: 40rpx;
height: 40rpx;
margin: 28rpx 5rpx 0 0;
}
.rightinput{
height:60rpx;
line-height: 60rpx;
width:100%;
}
}
}
}
.button_bottom {
display: flex;
width: 100%;
height: 90rpx;
background-color: #fff;
line-height: 90rpx;
text-align: center;
font-size: 32rpx;
:first-child {
flex: 1;
color: $uni-text-color;
border-top:1rpx solid #CCCCCC;
}
:last-child {
flex: 1;
background-color: $uni-text-color;
color: #fff;
}
}
</style>

View File

@ -0,0 +1,513 @@
<template>
<view>
<!-- 顶部导航栏 -->
<view class="select_warp">
<view class="manage_tab">
<view class="tab_array">
<image :src="BASE_IMG_URL+'ss.png'" mode="scaleToFill"></image>
<input type="text" :class="name ? 'valueactive' : '' " @input="searchName" v-model="name"
placeholder="线索名称" class="li_box" />
</view>
<view class="tab_screen" @click="toSearch">
<image :src="BASE_IMG_URL+'shaixuan.png'" mode="scaleToFill"></image>
</view>
</view>
</view>
<scroll-view scroll-x="true" style="width:750rpx;padding:0 24rpx;box-sizing: border-box;background:#fff">
<view class="tabbox">
<view class="tabli" v-for="(item,index) in tabList" :key="index" :class="{'tabactive': status == index}"
@click="changeTab(index)">
<view class="tabname">{{item}}</view>
<view class="tabot"></view>
</view>
</view>
</scroll-view>
<!-- 内容模块 -->
<view class="clues_content">
<view class="clues_item" v-for="(item,index) in list" :key="index">
<view class="info_head">
<view style="width: #333333; font-size: 34rpx;">{{item.name ? item.name : '--'}}</view>
</view>
<view class="info_main" @click="moreClick(item)">
<view class="main_left">
<view class="left_followUp">
<view>下次跟进时间{{item.next_time ? item.next_time : '--'}}</view>
</view>
<view class="left_star">
<view>客户星级</view>
<view>
<u-rate :count="5" v-model="item.level" disabled active-color="#FFD049"
inactive-color="#b2b2b2" :size="30" :gutter="10"></u-rate>
</view>
</view>
<view class="left_foot">
<view class="l_box">
<span>{{item.source ? item.source : '--'}}</span>
</view>
</view>
</view>
<view class="main_right">
<image :src="item.owner_staff.img ? item.owner_staff.img : BASE_IMG_URL+'headImg.png'"
mode="scaleToFill"></image>
<view>{{item.owner_staff ? item.owner_staff.name : '--'}}</view>
</view>
</view>
<view class="info_footer">
<view class="footer_content" @click="newFollowClick(item.id,4)">
<image :src="BASE_IMG_URL+'morebtn.png'" mode="scaleToFill"></image>
<view>跟进</view>
</view>
<view class="footer_content" @click="getaddCustomer(item.id)">
<image :src="BASE_IMG_URL+'tj.png'" mode="scaleToFill"></image>
<view>转客</view>
</view>
<view class="footer_content" @click="toCall(item.mobile)">
<image :src="BASE_IMG_URL+'dh.png'" mode="scaleToFill"></image>
<view>电话</view>
</view>
</view>
</view>
<view style="height: 200rpx;"></view>
<u-empty margin-top="500rpx" v-if="list.length == 0" text="暂无更多"></u-empty>
</view>
<view class="btn_fix" @click="newCluesClick">
<image :src="BASE_IMG_URL+'1.png'" mode="scaleToFill"></image>
</view>
<screen-pop ref="screenChild"
@sureParams="sureParams"
:searchForm="searchForm"
@changeSearchData="changeSearchData"
@resetForm="resetForm"
></screen-pop>
</view>
</template>
<script>
import screenPop from './screen.vue'
import {
netCluesList
} from '@/api/clues.js'
import {
netSearchStaffList,
netAddkehu
} from '@/api/kehu.js'
import {
BASE_IMG_URL
} from '@/util/api.js'
export default {
components:{
screenPop
},
data() {
return {
page: 1,
limit: 10,
totalPage: 1,
list: [],
BASE_IMG_URL: BASE_IMG_URL,
name: '',
tabList: ['全部', '我负责的', '下属负责的', '今日待跟进', '今日已联系', '从未跟进的'],
status: 0,
queryParams:{},
searchForm:[]
}
},
onLoad(options) {
if (options.startTime) {
this.start_time = options.startTime
this.end_time = options.endTime
}
if(options.stime){
this.status = options.status
this.start_time = options.stime
this.end_time = options.etime
}
//
this.getSearchForm()
},
onShow() {
this.init()
},
onReachBottom() {
if (this.page >= this.totalPage) {
return
}
this.page++
this.getList()
},
methods: {
getSearchForm() {
this.handleSearchForm('leads',(data)=>{
this.searchForm = data
})
},
changeSearchData(type,key,value){
let arr = this.searchForm
arr.forEach((ele,index)=>{
if(ele.field == type){
ele[key] = value
this.$set(this.searchForm, index, ele)
}
})
},
resetForm() {
this.searchForm = this.handleResetSearch(this.searchForm)
},
toSearch() {
let obj = {
type:'DatePicker',
start_time:this.start_time,
end_time:this.end_time
}
this.$refs.screenChild.init(obj)
},
sureParams(params){
this.queryParams = params
this.init()
},
changeTab(status) {
this.status = status
this.init()
},
init() {
this.page = 1
this.totalPage = 1
this.list = []
setTimeout(()=>{
this.getList()
},200)
},
//
searchName(e) {
this.name = e.detail.value
this.init()
},
//线
getList() {
let params = {
page: this.page,
limit: this.limit,
name: this.name,
createtime: (this.start_time && this.end_time) ? (this.start_time + ',' + this.end_time) : '',
staff_id: this.staffObj?this.staffObj.id:'',
team: this.status,
...this.queryParams,
...this.handleSureSearch(this.searchForm)
}
netCluesList(params).then(res => {
this.list = this.list.concat(res.data.data)
this.totalPage = res.data.last_page
})
},
//
newFollowClick(id, type) {
uni.navigateTo({
url: '/pagesA/crm/customerManagement/newFllow/newFllow?id=' + id + '&type=' + type
})
},
//
getaddCustomer(id) {
uni.navigateTo({
url: '/pagesA/crm/createCustomer/createCustomer?leads_id=' + id
})
},
//
moreClick(item) {
uni.navigateTo({
url: '/pagesA/crm/cluesManagement/cluesMore/cluesMore?id=' + item.id
})
},
// 线
newCluesClick() {
uni.navigateTo({
url: '/pagesA/crm/cluesManagement/newClues/newClues'
})
},
//
toCall(phone) {
// #ifdef MP-ALIPAY
dd.showCallMenu({
phoneNumber: phone, //
code: '+86', // +86
})
// #endif
// #ifndef MP-ALIPAY || APP-PLUS
uni.makePhoneCall({
phoneNumber: phone
})
// #endif
// #ifdef APP-PLUS
plus.device.dial(phone, true);
// #endif
},
}
}
</script>
<style lang="scss">
.tabbox {
height: 80rpx;
display: flex;
justify-content: flex-start;
background: #fff;
.tabli {
padding-top: 20rpx;
flex-shrink: 0;
margin-right: 35rpx;
position: relative;
.tabname {
font-size: 26rpx;
color: #666;
text-align: center;
margin-bottom: 15rpx;
}
.tabot {
width: 80rpx;
height: 8rpx;
border-radius: 4rpx;
background: #fff;
position: absolute;
left: 50%;
transform: translateX(-50%);
bottom: 0;
}
}
.tabactive {
.tabot {
background: $uni-text-color;
}
}
}
.left_foot {
padding-bottom: 20rpx;
margin: 20rpx 0;
.l_box {
margin-right: 35rpx;
float: left;
span {
background: $uni-text-color-opcity;
padding: 5rpx 12rpx;
font-size: 26rpx;
color: $uni-text-color;
border-radius: 5rpx;
}
}
}
.valueactive {
color: #333;
}
.select_warp {
z-index: 9;
position: relative;
}
.searchbox {
width: 100%;
height: 80rpx;
line-height: 80rpx;
background-color: $uni-text-color;
display: flex;
justify-content: space-around;
margin-bottom: 40rpx;
position: fixed;
left: 0;
top: 0;
z-index: 1;
.tab_array {
display: flex;
background: #fff;
border-radius: 34rpx;
height: 68rpx;
width: 467rpx;
image {
width: 50rpx;
height: 50rpx;
margin: 8rpx 15rpx 0 28rpx;
}
input {
line-height: 68rpx;
height: 68rpx;
}
}
.searchtext {
display: flex;
justify-content: center;
align-items: center;
font-size: 30rpx;
color: #999;
margin-right: 55rpx;
}
}
.manage_tab {
width: 100%;
height: 80rpx;
line-height: 80rpx;
background-color: $uni-text-color;
display: flex;
justify-content: space-around;
z-index: 1;
.tab_array {
display: flex;
background: #fff;
border-radius: 34rpx;
height: 68rpx;
width: 467rpx;
overflow: hidden;
image {
width: 50rpx;
height: 50rpx;
margin: 8rpx 15rpx 0 28rpx;
}
input {
line-height: 68rpx;
height: 68rpx;
}
}
.tab_screen {
display: flex;
image {
width: 43rpx;
height: 44rpx;
margin-top: 10rpx;
}
}
}
.clues_content {
// margin: 0 24rpx;
// margin-top: 100rpx;
.clues_item {
background-color: #fff;
border-radius: 10rpx;
margin-top: 20rpx;
padding: 20rpx 24rpx;
box-shadow: 2rpx 2rpx 50rpx rgba(0, 0, 0, 0.1);
.info_head {
display: flex;
justify-content: space-between;
:first-child {
font-size: 28rpx;
font-weight: 700;
color: #333;
}
}
.info_main {
display: flex;
justify-content: space-between;
padding-bottom: 20rpx;
border-bottom: 1px solid #ededed;
.main_left {
.left_followUp {
display: flex;
padding: 20rpx 0;
font-size: 30rpx;
color: #666;
margin: 20rpx 0;
}
.left_star {
display: flex;
padding-bottom: 20rpx;
font-size: 30rpx;
color: #666;
}
}
.main_right {
text-align: center;
padding: 20rpx 20rpx 0 0;
image {
width: 129rpx;
height: 129rpx;
margin-bottom: 5rpx;
border-radius: 50%;
}
}
}
.info_footer {
display: flex;
justify-content: space-around;
padding-top: 30rpx;
height: 80rpx;
.footer_content {
line-height: 80rpx;
display: flex;
justify-content: center;
align-items: center;
image {
width: 48rpx;
height: 48rpx;
margin-right: 15rpx;
}
.icon-iconmore-copy,
.icon-follow {
font-size: 22rpx;
}
.icon-follow,
.icon-task,
.icon-tel {
margin-right: 5rpx;
}
.icon-iconmore-copy {
margin-left: 5rpx;
margin-top: 2rpx;
}
}
}
}
}
.btn_fix {
position: fixed;
bottom: 100rpx;
right: 80rpx;
image {
width: 80rpx;
height: 80rpx;
background-color: #fff;
border-radius: 40rpx;
}
}
</style>

Some files were not shown because too many files have changed in this diff Show More