xiaohaizhao 1 месяц назад
Родитель
Сommit
3f8b6b5f6b

+ 125 - 0
CRM/contract/create.js

@@ -0,0 +1,125 @@
+Page({
+  data: {
+    year: '',
+    taskname: '',
+    templateName: '',
+    remarks: '',
+    selectedTemplateId: '',
+    showYearPicker: false,
+    showTemplatePicker: false,
+    yearColumns: [],
+    templateList: [],
+    loading: false
+  },
+
+  onLoad() {
+    const currentYear = new Date().getFullYear();
+    this.setData({ year: currentYear.toString() });
+    this.generateYearColumns();
+    this.loadTemplates();
+  },
+
+  generateYearColumns() {
+    const currentYear = new Date().getFullYear();
+    const years = [];
+    for (let i = currentYear - 5; i <= currentYear + 5; i++) {
+      years.push(i.toString());
+    }
+    this.setData({ yearColumns: years });
+  },
+
+  loadTemplates() {
+    getApp().globalData.http.basic({
+      id: '2026041309474202',
+      content: {
+        pageNumber: 1,
+        pageSize: 100
+      }
+    }).then(res => {
+      if (res.msg === '成功') {
+        this.setData({ templateList: res.data || [] });
+      } else {
+        wx.showToast({ title: res.msg || '加载合同模版失败', icon: 'none' });
+      }
+    }).catch(() => {
+      wx.showToast({ title: '加载合同模版失败', icon: 'none' });
+    });
+  },
+
+  selectYear() {
+    this.setData({ showYearPicker: true });
+  },
+
+  closeYearPicker() {
+    this.setData({ showYearPicker: false });
+  },
+
+  onYearConfirm(e) {
+    this.setData({ year: e.detail.value[0] });
+    this.closeYearPicker();
+  },
+
+  selectTemplate() {
+    this.setData({ showTemplatePicker: true });
+  },
+
+  closeTemplatePicker() {
+    this.setData({ showTemplatePicker: false });
+  },
+
+  selectTemplateItem(e) {
+    const { id, name } = e.currentTarget.dataset;
+    this.setData({ selectedTemplateId: id, templateName: name });
+  },
+
+  onTemplateConfirm() {
+    this.closeTemplatePicker();
+  },
+
+  onTasknameChange(e) {
+    this.setData({ taskname: e.detail });
+  },
+
+  onRemarksChange(e) {
+    this.setData({ remarks: e.detail });
+  },
+
+  submitForm() {
+    if (!this.data.year) {
+      wx.showToast({ title: '请选择年度', icon: 'none' });
+      return;
+    }
+    if (!this.data.taskname) {
+      wx.showToast({ title: '请输入任务名称', icon: 'none' });
+      return;
+    }
+    if (!this.data.selectedTemplateId) {
+      wx.showToast({ title: '请选择合同模版', icon: 'none' });
+      return;
+    }
+
+    this.setData({ loading: true });
+    getApp().globalData.http.basic({
+      id: '2026041309401702',
+      content: {
+        taskname: this.data.taskname,
+        year: this.data.year,
+        remarks: this.data.remarks,
+        sa_esign_contract_templateid: this.data.selectedTemplateId
+      }
+    }).then(res => {
+      if (res.msg === '成功') {
+        wx.showToast({ title: '创建成功', icon: 'success' });
+        setTimeout(() => {
+          wx.navigateBack();
+        }, 1500);
+      } else {
+        wx.showToast({ title: res.msg || '创建失败', icon: 'none' });
+      }
+    }).catch(() => {
+      wx.showToast({ title: '创建失败', icon: 'none' });
+    }).finally(() => {
+      this.setData({ loading: false });
+    });
+  }
+});

+ 10 - 0
CRM/contract/create.json

@@ -0,0 +1,10 @@
+{
+  "usingComponents": {
+    "Yl_HeadNav": "/components/Yl_HeadNav/index",
+    "van-field": "@vant/weapp/field/index",
+    "van-button": "@vant/weapp/button/index",
+    "van-popup": "@vant/weapp/popup/index",
+    "van-picker": "@vant/weapp/picker/index",
+    "van-icon": "@vant/weapp/icon/index"
+  }
+}

+ 51 - 0
CRM/contract/create.scss

@@ -0,0 +1,51 @@
+.container {
+  min-height: 100vh;
+  background-color: #f5f5f5;
+}
+
+.content {
+  padding: 20rpx;
+}
+
+.submit-button {
+  margin-top: 30rpx;
+  border-radius: 8rpx;
+  font-size: 32rpx;
+}
+
+.picker-header {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  padding: 20rpx;
+  border-bottom: 1rpx solid #eee;
+  .cancel,
+  .confirm {
+    font-size: 28rpx;
+    color: #666;
+  }
+  .title {
+    font-size: 32rpx;
+    font-weight: bold;
+    color: #333;
+  }
+  .confirm {
+    color: #085CDF;
+  }
+}
+
+.template-list {
+  max-height: 600rpx;
+  overflow-y: auto;
+  .template-item {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    padding: 20rpx;
+    border-bottom: 1rpx solid #eee;
+    .template-name {
+      font-size: 28rpx;
+      color: #333;
+    }
+  }
+}

+ 73 - 0
CRM/contract/create.wxml

@@ -0,0 +1,73 @@
+<view class="container">
+  <Yl_HeadNav title="新建合同任务" showBack="true" />
+  <view class="content">
+    <view class="form">
+      <van-field
+        label="年度"
+        value="{{ year }}"
+        placeholder="请选择年份"
+        bind:tap="selectYear"
+        readonly
+        required
+      />
+      <van-field
+        label="任务名称"
+        value="{{ taskname }}"
+        placeholder="请输入任务名称"
+        bind:change="onTasknameChange"
+        required
+      />
+      <van-field
+        label="合同模版"
+        value="{{ templateName }}"
+        placeholder="请选择合同模版"
+        bind:tap="selectTemplate"
+        readonly
+        required
+      />
+      <van-field
+        label="备注"
+        value="{{ remarks }}"
+        placeholder="请输入备注"
+        bind:change="onRemarksChange"
+        type="textarea"
+      />
+    </view>
+    <van-button
+      type="primary"
+      class="submit-button"
+      bindtap="submitForm"
+      loading="{{ loading }}"
+    >提交</van-button>
+  </view>
+  <van-popup
+    show="{{ showYearPicker }}"
+    position="bottom"
+    bind:close="closeYearPicker"
+  >
+    <van-picker
+      columns="{{ yearColumns }}"
+      bind:confirm="onYearConfirm"
+      bind:cancel="closeYearPicker"
+    />
+  </van-popup>
+  <van-popup
+    show="{{ showTemplatePicker }}"
+    position="bottom"
+    bind:close="closeTemplatePicker"
+  >
+    <view class="picker-header">
+      <text class="cancel" bindtap="closeTemplatePicker">取消</text>
+      <text class="title">选择合同模版</text>
+      <text class="confirm" bindtap="onTemplateConfirm">确定</text>
+    </view>
+    <view class="template-list">
+      <block wx:for="{{ templateList }}" wx:key="id">
+        <view class="template-item" bindtap="selectTemplateItem" data-id="{{ item.id }}" data-name="{{ item.name }}">
+          <view class="template-name">{{ item.name }}</view>
+          <van-icon wx:if="{{ selectedTemplateId === item.id }}" name="success" color="#67C23A" />
+        </view>
+      </block>
+    </view>
+  </van-popup>
+</view>

+ 238 - 0
CRM/contract/detail.js

@@ -0,0 +1,238 @@
+Page({
+  data: {
+    taskId: '',
+    detail: {},
+    list: [],
+    showAddDistributor: false,
+    showEditTerm: false,
+    distributorList: [],
+    selectedDistributors: [],
+    beginDate: '',
+    endDate: '',
+    currentDetailId: ''
+  },
+
+  onLoad(options) {
+    this.setData({ taskId: options.id });
+    this.loadTaskDetail();
+    this.loadDetailList();
+  },
+
+  loadTaskDetail() {
+    getApp().globalData.http.basic({
+      id: '2026041309443002',
+      content: {
+        sa_esign_contract_taskid: this.data.taskId
+      }
+    }).then(res => {
+      if (res.msg === '成功') {
+        this.setData({ detail: res.data || {} });
+      } else {
+        wx.showToast({ title: res.msg || '加载详情失败', icon: 'none' });
+      }
+    }).catch(() => {
+      wx.showToast({ title: '加载详情失败', icon: 'none' });
+    });
+  },
+
+  loadDetailList() {
+    getApp().globalData.http.basic({
+      id: '2026041315403802',
+      content: {
+        sa_esign_contract_taskid: this.data.taskId,
+        pageNumber: 1,
+        pageSize: 100
+      }
+    }).then(res => {
+      if (res.msg === '成功') {
+        this.setData({ list: res.data || [] });
+      } else {
+        wx.showToast({ title: res.msg || '加载明细失败', icon: 'none' });
+      }
+    }).catch(() => {
+      wx.showToast({ title: '加载明细失败', icon: 'none' });
+    });
+  },
+
+  addDistributor() {
+    this.loadDistributorList();
+    this.setData({ showAddDistributor: true, selectedDistributors: [] });
+  },
+
+  closeAddDistributor() {
+    this.setData({ showAddDistributor: false });
+  },
+
+  loadDistributorList() {
+    getApp().globalData.http.basic({
+      id: '2026041315545602',
+      content: {
+        sa_esign_contract_taskid: this.data.taskId,
+        pageNumber: 1,
+        pageSize: 100
+      }
+    }).then(res => {
+      if (res.msg === '成功') {
+        this.setData({ distributorList: res.data || [] });
+      } else {
+        wx.showToast({ title: res.msg || '加载经销商列表失败', icon: 'none' });
+      }
+    }).catch(() => {
+      wx.showToast({ title: '加载经销商列表失败', icon: 'none' });
+    });
+  },
+
+  selectDistributor(e) {
+    const distributorId = e.currentTarget.dataset.id;
+    let selectedDistributors = this.data.selectedDistributors;
+    if (selectedDistributors.includes(distributorId)) {
+      selectedDistributors = selectedDistributors.filter(id => id !== distributorId);
+    } else {
+      selectedDistributors.push(distributorId);
+    }
+    this.setData({ selectedDistributors });
+  },
+
+  confirmAddDistributor() {
+    if (this.data.selectedDistributors.length === 0) {
+      wx.showToast({ title: '请选择经销商', icon: 'none' });
+      return;
+    }
+
+    getApp().globalData.http.basic({
+      id: '2026041315394702',
+      content: {
+        sa_esign_contract_taskid: this.data.taskId,
+        sa_agentsids: this.data.selectedDistributors
+      }
+    }).then(res => {
+      if (res.msg === '成功') {
+        wx.showToast({ title: '添加成功', icon: 'success' });
+        this.closeAddDistributor();
+        this.loadDetailList();
+      } else {
+        wx.showToast({ title: res.msg || '添加失败', icon: 'none' });
+      }
+    }).catch(() => {
+      wx.showToast({ title: '添加失败', icon: 'none' });
+    });
+  },
+
+  publishTask() {
+    getApp().globalData.http.basic({
+      id: '2026041309482202',
+      content: {
+        sa_esign_contract_taskid: this.data.taskId
+      }
+    }).then(res => {
+      if (res.msg === '成功') {
+        wx.showToast({ title: '发布成功', icon: 'success' });
+        this.loadTaskDetail();
+      } else {
+        wx.showToast({ title: res.msg || '发布失败', icon: 'none' });
+      }
+    }).catch(() => {
+      wx.showToast({ title: '发布失败', icon: 'none' });
+    });
+  },
+
+  withdrawTask() {
+    getApp().globalData.http.basic({
+      id: '2026041309485902',
+      content: {
+        sa_esign_contract_taskid: this.data.taskId
+      }
+    }).then(res => {
+      if (res.msg === '成功') {
+        wx.showToast({ title: '撤回成功', icon: 'success' });
+        this.loadTaskDetail();
+      } else {
+        wx.showToast({ title: res.msg || '撤回失败', icon: 'none' });
+      }
+    }).catch(() => {
+      wx.showToast({ title: '撤回失败', icon: 'none' });
+    });
+  },
+
+  editTerm(e) {
+    const detailId = e.currentTarget.dataset.id;
+    this.setData({ showEditTerm: true, currentDetailId: detailId, beginDate: '', endDate: '' });
+  },
+
+  closeEditTerm() {
+    this.setData({ showEditTerm: false });
+  },
+
+  selectBeginDate() {
+    wx.datePicker({
+      start: '2020-01-01',
+      end: '2030-12-31',
+      success: (res) => {
+        this.setData({ beginDate: res.value });
+      }
+    });
+  },
+
+  selectEndDate() {
+    wx.datePicker({
+      start: '2020-01-01',
+      end: '2030-12-31',
+      success: (res) => {
+        this.setData({ endDate: res.value });
+      }
+    });
+  },
+
+  confirmEditTerm() {
+    if (!this.data.beginDate || !this.data.endDate) {
+      wx.showToast({ title: '请选择日期', icon: 'none' });
+      return;
+    }
+
+    getApp().globalData.http.basic({
+      id: '2026041415245302',
+      content: {
+        sa_esign_contract_taskmxids: [this.data.currentDetailId],
+        begindate: this.data.beginDate,
+        enddate: this.data.endDate
+      }
+    }).then(res => {
+      if (res.msg === '成功') {
+        wx.showToast({ title: '修改成功', icon: 'success' });
+        this.closeEditTerm();
+        this.loadDetailList();
+      } else {
+        wx.showToast({ title: res.msg || '修改失败', icon: 'none' });
+      }
+    }).catch(() => {
+      wx.showToast({ title: '修改失败', icon: 'none' });
+    });
+  },
+
+  deleteDetail(e) {
+    const detailId = e.currentTarget.dataset.id;
+    wx.showModal({
+      title: '确认删除',
+      content: '确定要删除这个经销商吗?',
+      success: (res) => {
+        if (res.confirm) {
+          getApp().globalData.http.basic({
+            id: '2026041315414702',
+            content: {
+              sa_esign_contract_taskmxids: [detailId]
+            }
+          }).then(res => {
+            if (res.msg === '成功') {
+              wx.showToast({ title: '删除成功', icon: 'success' });
+              this.loadDetailList();
+            } else {
+              wx.showToast({ title: res.msg || '删除失败', icon: 'none' });
+            }
+          }).catch(() => {
+            wx.showToast({ title: '删除失败', icon: 'none' });
+          });
+        }
+      }
+    });
+  }
+});

+ 11 - 0
CRM/contract/detail.json

@@ -0,0 +1,11 @@
+{
+  "usingComponents": {
+    "Yl_HeadNav": "/components/Yl_HeadNav/index",
+    "van-tag": "@vant/weapp/tag/index",
+    "van-button": "@vant/weapp/button/index",
+    "Yl_Empty": "/components/Yl_Empty/index",
+    "van-popup": "@vant/weapp/popup/index",
+    "van-checkbox": "@vant/weapp/checkbox/index",
+    "van-field": "@vant/weapp/field/index"
+  }
+}

+ 133 - 0
CRM/contract/detail.scss

@@ -0,0 +1,133 @@
+.contract-detail {
+  min-height: 100vh;
+  background-color: #f5f5f5;
+  padding: 20rpx;
+
+  .content {
+    padding-bottom: 20rpx;
+  }
+
+  .card-item {
+    background-color: #fff;
+    border-radius: 12rpx;
+    padding: 24rpx;
+    margin-bottom: 20rpx;
+
+    .card-header {
+      font-size: 32rpx;
+      font-weight: bold;
+      color: #333;
+      margin-bottom: 15rpx;
+      border-bottom: 1rpx solid #eee;
+      padding-bottom: 10rpx;
+    }
+
+    .exp {
+      font-size: 26rpx;
+      color: #666;
+      line-height: 1.5;
+      margin-top: 8rpx;
+    }
+
+    .exp.full-width {
+      width: 100%;
+    }
+  }
+
+  .action-buttons {
+    display: flex;
+    gap: 10rpx;
+    margin-bottom: 20rpx;
+    van-button {
+      flex: 1;
+      font-size: 28rpx;
+    }
+  }
+
+  .detail-item {
+    border-bottom: 1rpx solid #eee;
+    padding: 15rpx 0;
+
+    &:last-child {
+      border-bottom: none;
+    }
+
+    .detail-header {
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+      margin-bottom: 10rpx;
+      .distributor-name {
+        font-size: 28rpx;
+        font-weight: bold;
+        color: #333;
+      }
+    }
+
+    .detail-info {
+      margin-left: 10rpx;
+      .exp {
+        font-size: 24rpx;
+        color: #666;
+        line-height: 1.4;
+        margin-top: 6rpx;
+      }
+    }
+
+    .detail-action {
+      margin-top: 15rpx;
+      display: flex;
+      gap: 10rpx;
+      justify-content: flex-end;
+    }
+  }
+
+  .popup-header {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    padding: 20rpx;
+    border-bottom: 1rpx solid #eee;
+    .cancel,
+    .confirm {
+      font-size: 28rpx;
+      color: #666;
+    }
+    .title {
+      font-size: 32rpx;
+      font-weight: bold;
+      color: #333;
+    }
+    .confirm {
+      color: #085CDF;
+    }
+  }
+
+  .distributor-list {
+    max-height: 600rpx;
+    overflow-y: auto;
+    .distributor-item {
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+      padding: 20rpx;
+      border-bottom: 1rpx solid #eee;
+      .distributor-info {
+        .name {
+          font-size: 28rpx;
+          color: #333;
+          margin-bottom: 5rpx;
+          display: block;
+        }
+        .code {
+          font-size: 24rpx;
+          color: #666;
+        }
+      }
+    }
+  }
+
+  .form {
+    padding: 20rpx;
+  }
+}

+ 132 - 0
CRM/contract/detail.wxml

@@ -0,0 +1,132 @@
+<view class="contract-detail">
+  <Yl_HeadNav title="合同任务详情" showBack="true" />
+  <view class="content">
+    <!-- 表头信息 -->
+    <view class="card-item">
+      <view class="card-header">
+        合同任务信息
+      </view>
+      <view class="exp">任务名称:{{ detail.taskname || '--' }}</view>
+      <view class="exp">合同模版名称:{{ detail.template_name || '--' }}</view>
+      <view class="exp">年度:{{ detail.year || '--' }}</view>
+      <view class="exp">合同类型:{{ detail.contract_type || '--' }}</view>
+      <view class="exp">电子合同模版id:{{ detail.sa_esign_contract_templateid || '--' }}</view>
+      <view class="exp">创建人:{{ detail.create_user || '--' }}</view>
+      <view class="exp">创建时间:{{ detail.create_time || '--' }}</view>
+      <view class="exp" wx:if="{{ detail.publish_time }}">发布时间:{{ detail.publish_time || '--' }}</view>
+      <view class="exp">
+        状态:
+        <van-tag wx:if="{{ detail.status === '新建' }}" color="#909399">新建</van-tag>
+        <van-tag wx:elif="{{ detail.status === '发布' }}" color="#67C23A">发布</van-tag>
+        <van-tag wx:elif="{{ detail.status === '撤回' }}" color="#F56C6C">撤回</van-tag>
+        <text wx:else>--</text>
+      </view>
+      <view class="exp full-width">备注:{{ detail.remarks || '--' }}</view>
+    </view>
+
+    <!-- 操作按钮 -->
+    <view class="action-buttons">
+      <van-button type="primary" bindtap="addDistributor">添加经销商</van-button>
+      <van-button 
+        type="success" 
+        wx:if="{{ detail.status === '新建' || detail.status === '撤回' }}" 
+        bindtap="publishTask"
+      >发布</van-button>
+      <van-button 
+        type="warning" 
+        wx:if="{{ detail.status === '发布' }}" 
+        bindtap="withdrawTask"
+      >撤回</van-button>
+    </view>
+
+    <!-- 明细列表 -->
+    <view class="card-item">
+      <view class="card-header">
+        经销商明细
+      </view>
+      <block wx:for="{{ list }}" wx:key="id">
+        <view class="detail-item">
+          <view class="detail-header">
+            <view class="distributor-name">{{ item.distributor_name || '--' }}</view>
+            <van-tag wx:if="{{ item.status === '待开始' }}" color="#909399">待开始</van-tag>
+            <van-tag wx:elif="{{ item.status === '待签署' }}" color="#E6A23C">待签署</van-tag>
+            <van-tag wx:elif="{{ item.status === '部分签署' }}" color="#409EFF">部分签署</van-tag>
+            <van-tag wx:elif="{{ item.status === '已签署' }}" color="#67C23A">已签署</van-tag>
+            <van-tag wx:elif="{{ item.status === '已拒签' }}" color="#F56C6C">已拒签</van-tag>
+            <text wx:else>--</text>
+          </view>
+          <view class="detail-info">
+            <view class="exp">编号:{{ item.distributor_code || '--' }}</view>
+            <view class="exp">区域:{{ item.area || '--' }}</view>
+            <view class="exp">联系人:{{ item.contact || '--' }}</view>
+            <view class="exp">联系方式:{{ item.contact_phone || '--' }}</view>
+            <view class="exp">合同期限:{{ item.begindate || '--' }} 至 {{ item.enddate || '--' }}</view>
+            <view class="exp">年度任务(万元):{{ item.year_task || '--' }}</view>
+            <view class="exp">一季度任务(万元):{{ item.quarter1_task || '--' }}</view>
+            <view class="exp">二季度任务(万元):{{ item.quarter2_task || '--' }}</view>
+            <view class="exp">三季度任务(万元):{{ item.quarter3_task || '--' }}</view>
+            <view class="exp">四季度任务(万元):{{ item.quarter4_task || '--' }}</view>
+          </view>
+          <view class="detail-action">
+            <van-button size="small" bindtap="editTerm" data-id="{{ item.id }}">编辑期限</van-button>
+            <van-button size="small" type="danger" bindtap="deleteDetail" data-id="{{ item.id }}">删除</van-button>
+          </view>
+        </view>
+      </block>
+      <Yl_Empty wx:if="{{ list.length === 0 }}" text="暂无经销商" />
+    </view>
+  </view>
+
+  <!-- 添加经销商弹窗 -->
+  <van-popup
+    show="{{ showAddDistributor }}"
+    position="bottom"
+    bind:close="closeAddDistributor"
+  >
+    <view class="popup-header">
+      <text class="cancel" bindtap="closeAddDistributor">取消</text>
+      <text class="title">选择经销商</text>
+      <text class="confirm" bindtap="confirmAddDistributor">确定</text>
+    </view>
+    <view class="distributor-list">
+      <block wx:for="{{ distributorList }}" wx:key="id">
+        <view class="distributor-item" bindtap="selectDistributor" data-id="{{ item.id }}" data-name="{{ item.name }}">
+          <view class="distributor-info">
+            <text class="name">{{ item.name }}</text>
+            <text class="code">{{ item.code }}</text>
+          </view>
+          <van-checkbox value="{{ selectedDistributors.includes(item.id) }}" />
+        </view>
+      </block>
+    </view>
+  </van-popup>
+
+  <!-- 编辑期限弹窗 -->
+  <van-popup
+    show="{{ showEditTerm }}"
+    position="bottom"
+    bind:close="closeEditTerm"
+  >
+    <view class="popup-header">
+      <text class="cancel" bindtap="closeEditTerm">取消</text>
+      <text class="title">编辑合同期限</text>
+      <text class="confirm" bindtap="confirmEditTerm">确定</text>
+    </view>
+    <view class="form">
+      <van-field
+        label="开始日期"
+        value="{{ beginDate }}"
+        placeholder="请选择开始日期"
+        bind:tap="selectBeginDate"
+        readonly
+      />
+      <van-field
+        label="结束日期"
+        value="{{ endDate }}"
+        placeholder="请选择结束日期"
+        bind:tap="selectEndDate"
+        readonly
+      />
+    </view>
+  </van-popup>
+</view>

+ 67 - 0
CRM/contract/index.js

@@ -0,0 +1,67 @@
+Page({
+  data: {
+    list: [],
+    searchValue: '',
+    pageNumber: 1,
+    pageSize: 20,
+    loading: false,
+    hasMore: true
+  },
+
+  onLoad() {
+    this.getList();
+  },
+
+  onReachBottom() {
+    if (!this.data.loading && this.data.hasMore) {
+      this.setData({
+        pageNumber: this.data.pageNumber + 1
+      });
+      this.getList();
+    }
+  },
+
+  getList() {
+    this.setData({ loading: true });
+    getApp().globalData.http.basic({
+      id: '2026041309474202',
+      content: {
+        pageNumber: this.data.pageNumber,
+        pageSize: this.data.pageSize
+      }
+    }).then(res => {
+      if (res.msg === '成功') {
+        const newList = res.data || [];
+        const list = this.data.pageNumber === 1 ? newList : [...this.data.list, ...newList];
+        this.setData({
+          list,
+          hasMore: newList.length === this.data.pageSize,
+          loading: false
+        });
+      } else {
+        wx.showToast({ title: res.msg || '加载失败', icon: 'none' });
+        this.setData({ loading: false });
+      }
+    }).catch(() => {
+      wx.showToast({ title: '加载失败', icon: 'none' });
+      this.setData({ loading: false });
+    });
+  },
+
+  onSearch(e) {
+    this.setData({ 
+      pageNumber: 1,
+      searchValue: e.detail 
+    });
+    this.getList();
+  },
+
+  goToCreate() {
+    wx.navigateTo({ url: '/CRM/contract/create' });
+  },
+
+  goToDetail(e) {
+    const taskId = e.currentTarget.dataset.id;
+    wx.navigateTo({ url: `/CRM/contract/detail?id=${taskId}` });
+  }
+});

+ 11 - 0
CRM/contract/index.json

@@ -0,0 +1,11 @@
+{
+  "usingComponents": {
+    "Yl_HeadNav": "/components/Yl_HeadNav/index",
+    "van-search": "@vant/weapp/search/index",
+    "van-tabs": "@vant/weapp/tabs/index",
+    "van-tab": "@vant/weapp/tab/index",
+    "van-tag": "@vant/weapp/tag/index",
+    "Yl_Empty": "/components/Yl_Empty/index",
+    "van-button": "@vant/weapp/button/index"
+  }
+}

+ 81 - 0
CRM/contract/index.scss

@@ -0,0 +1,81 @@
+.container {
+  min-height: 100vh;
+  background-color: #f5f5f5;
+
+  .header {
+    width: 100%;
+  }
+
+  .item {
+    background-color: #fff;
+    border-radius: 12rpx;
+    padding: 24rpx;
+    margin-bottom: 20rpx;
+
+    .top {
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+      margin-bottom: 15rpx;
+
+      .name {
+        font-size: 32rpx;
+        font-weight: bold;
+        color: #333;
+        flex: 1;
+      }
+
+      .statu {
+        font-size: 24rpx;
+        padding: 4rpx 12rpx;
+        border-radius: 4rpx;
+      }
+    }
+
+    .content {
+      .row {
+        display: flex;
+        margin-bottom: 10rpx;
+
+        .exp {
+          font-size: 26rpx;
+          color: #666;
+          flex: 1;
+
+          &.full-width {
+            width: 100%;
+            flex: none;
+          }
+
+          .link {
+            color: #3874F6;
+            text-decoration: underline;
+          }
+
+          .text-green {
+            color: #52C41A;
+          }
+
+          .text-red {
+            color: #FF4D4F;
+          }
+        }
+      }
+    }
+  }
+
+  .create-order-button {
+    position: fixed;
+    bottom: 30rpx;
+    left: 50%;
+    transform: translateX(-50%);
+    width: 90%;
+    
+    .create-btn {
+      width: 100%;
+      height: 80rpx;
+      font-size: 32rpx;
+      border-radius: 8rpx;
+    }
+  }
+}

+ 70 - 0
CRM/contract/index.wxml

@@ -0,0 +1,70 @@
+<view class="container">
+  <van-search use-action-slot placeholder='请输入搜索关键词' shape='round' bind:search="onSearch" bind:clear="onSearch" />
+  <view class="header" style="height: 20rpx;"></view>
+  <Yl_ListBox id='ListBox' bind:getlist='getList'>
+    <navigator url="/CRM/contract/detail?id={{item.sa_esign_contract_taskid}}" class="item" wx:for="{{ list }}" wx:key="sa_esign_contract_taskid">
+      <view class="top">
+        <view class="name">{{item.taskname || '--'}}</view>
+        <view class="statu" style="background-color: {{set.color(item.status)}}; color: #fff;">
+          {{item.status || '--'}}
+        </view>
+      </view>
+      <view class="content">
+        <view class="row">
+          <view class="exp">
+            合同模版:{{item.template_name || '--'}}
+          </view>
+          <view class="exp">
+            年度:{{item.year || '--'}}
+          </view>
+        </view>
+        <view class="row">
+          <view class="exp">
+            合同类型:{{item.contract_type || '--'}}
+          </view>
+          <view class="exp">
+            创建人:{{item.create_user || '--'}}
+          </view>
+        </view>
+        <view class="row">
+          <view class="exp">
+            创建时间:{{item.create_time || '--'}}
+          </view>
+          <view class="exp" wx:if="{{ item.publish_time }}">
+            发布时间:{{item.publish_time || '--'}}
+          </view>
+        </view>
+        <view class="row">
+          <view class="exp full-width">
+            备注:{{item.remarks || '--'}}
+          </view>
+        </view>
+      </view>
+    </navigator>
+    <Yl_Empty wx:if="{{list.length==0}}" text="暂无合同任务" />
+    <view style="height:150rpx;" />
+  </Yl_ListBox>
+  <!-- 新建按钮 -->
+  <view class="create-order-button">
+    <van-button custom-class="create-btn" color="#3874F6" bind:tap="goToCreate">新建合同任务</van-button>
+  </view>
+</view>
+<wxs module="set">
+  module.exports = {
+    color: function (statu) {
+      var color = '#999999';
+      switch (statu) {
+        case "新建":
+          color = '#909399';
+          break;
+        case "发布":
+          color = '#67C23A';
+          break;
+        case "撤回":
+          color = '#F56C6C';
+          break;
+      };
+      return color;
+    }
+  }
+</wxs>

+ 10 - 1
CRM/customer/create.js

@@ -334,7 +334,16 @@ Page({
             }
           });
         } else if (content.sa_customersid == 0) {
-          getCurrentPages().find(v => v.__route__ == 'CRM/lead/detail').selectComponent("#FollowRecord").getList("", true)
+          // 刷新线索相关页面
+          const pages = getCurrentPages();
+          const detailPage = pages.find(v => v.__route__ == 'CRM/lead/detail');
+          const listPage = pages.find(v => v.__route__ == 'CRM/lead/index');
+          if (detailPage) {
+            detailPage.selectComponent("#FollowRecord").getList("", true);
+          }
+          if (listPage) {
+            listPage.getList(true);
+          }
           // 非选择模式,跳转到客户详情
           wx.redirectTo({
             url: '/CRM/customer/detail?id=' + res.data,

+ 3 - 1
CRM/customer/detail.scss

@@ -29,8 +29,10 @@
     .statu {
       font-size: 24rpx;
       padding: 6rpx 18rpx;
-      border-radius: 16rpx;
+      border-radius: 8rpx;
       font-weight: 500;
+      background-color: #fff;
+      border: 2rpx solid;
     }
   }
 

+ 1 - 1
CRM/customer/detail.wxml

@@ -1,7 +1,7 @@
 <view class="intr">
   <view class="top">
     <view class="name">{{detail.name || '--'}}</view>
-    <view class="statu" style="background-color: {{set.color(detail.status)}}; color: #fff;">
+    <view class="statu" style="border-color: {{set.color(detail.status)}}; color: {{set.color(detail.status)}};">
       {{detail.status || '--'}}
     </view>
   </view>

+ 3 - 1
CRM/customer/index.scss

@@ -64,9 +64,11 @@
     .statu {
       font-size: 22rpx;
       padding: 6rpx 16rpx;
-      border-radius: 6rpx;
+      border-radius: 8rpx;
       font-weight: 500;
       flex-shrink: 0;
+      background-color: #fff;
+      border: 2rpx solid;
     }
   }
 

+ 1 - 1
CRM/customer/index.wxml

@@ -7,7 +7,7 @@
         <navigator url="/CRM/customer/detail?id={{item.sa_customersid}}" class="item">
           <view class="top">
             <view class="name">{{item.name || '--'}}</view>
-            <view class="statu" style="background-color: {{set.color(item.status)}}; color: #fff;">
+            <view class="statu" style="border-color: {{set.color(item.status)}}; color: {{set.color(item.status)}};">
               {{item.status || '--'}}
             </view>
           </view>

+ 3 - 1
CRM/lead/detail.scss

@@ -31,8 +31,10 @@
     .statu {
       font-size: 24rpx;
       padding: 6rpx 18rpx;
-      border-radius: 16rpx;
+      border-radius: 8rpx;
       font-weight: 500;
+      background-color: #fff;
+      border: 2rpx solid;
     }
   }
 

+ 1 - 1
CRM/lead/detail.wxml

@@ -1,7 +1,7 @@
 <view class="intr">
   <view class="top">
     <view class="name">{{detail.name || '--'}}</view>
-    <view class="statu" style="background-color: {{set.color(detail.status)}}; color: #fff;">
+    <view class="statu" style="border-color: {{set.color(detail.status)}}; color: {{set.color(detail.status)}};">
       {{detail.status || '--'}}
     </view>
   </view>

+ 210 - 0
CRM/lead/index.js

@@ -4,6 +4,16 @@ Page({
   data: {
     "id": 20221101094502,
     list: [],
+    teamList: [],
+    authoptions: [],
+    hasAllotPermission: false,
+    leader: null,
+    showActionSheet: false,
+    teamActions: [],
+    showAssignConfirm: false,
+    showWithdrawConfirm: false,
+    selectedTeam: null,
+    currentClueId: null,
     content: {
       isAll: false,
       nocache: true,
@@ -18,8 +28,21 @@ Page({
     }
   },
   onLoad() {
+    this.getAuth();
+    this.getTeamList();
     this.getList();
   },
+  // 获取权限信息
+  getAuth() {
+    let auth = wx.getStorageSync("auth").wcrmlead;
+    if (auth) {
+      const hasAllotPermission = auth.options.some(v => v == 'allot');
+      this.setData({
+        authoptions: auth.options,
+        hasAllotPermission: hasAllotPermission
+      });
+    }
+  },
   /* 获取线索列表 */
   getList(init = false) {
     if (init.detail != undefined) init = init.detail;
@@ -71,5 +94,192 @@ Page({
     wx.navigateTo({
       url: `./detail?id=${id}`
     });
+  },
+  // 获取经销商团队列表
+  getTeamList() {
+    _Http.basic({
+      classname: "sale.team.team",
+      method: "query_teamList",
+      content: {
+        pageNumber: 1,
+        pageSize: 99999,
+        where: {
+          condition: ""
+        }
+      },
+    }).then(res => {
+      if (res.code === 1) {
+        const teamList = res.data || [];
+        const leader = teamList.find(team => team.isleader === 1);
+        // 生成团队成员操作选项(排除负责人自己)
+        const teamActions = teamList.map(team => ({
+          name: team.name + ' ' + team.phonenumber,
+          subname: '在手 待跟进、跟进中 线索数量:' + team.ordercluecount,
+          data: team
+        }));
+        this.setData({
+          teamList,
+          leader,
+          teamActions
+        });
+      }
+    }).catch(err => {
+      console.error('获取经销商团队列表失败', err);
+    });
+  },
+  // 转客户
+  convertToCustomer(e) {
+    const item = e.currentTarget.dataset.item;
+    wx.navigateTo({
+      url: `/CRM/customer/create?clueId=${item.sat_orderclueid}&clueInfo=${encodeURIComponent(JSON.stringify(item))}`
+    });
+  },
+  // 点击分配按钮 - 弹出选人面板
+  onAssignTap(e) {
+    const item = e.currentTarget.dataset.item;
+    // 禁用当前负责人选项
+    const teamActions = this.data.teamList.map(team => ({
+      name: team.name + ' ' + team.phonenumber,
+      subname: '在手 待跟进、跟进中 线索数量:' + team.ordercluecount,
+      disabled: item.leadername === team.name,
+      data: team
+    }));
+    this.setData({
+      currentClueId: item.sat_orderclueid,
+      teamActions,
+      showActionSheet: true
+    });
+  },
+  // 选择团队成员
+  onActionSheetSelect(event) {
+    const selectedTeam = event.detail.data;
+    this.setData({
+      selectedTeam,
+      showActionSheet: false,
+      showAssignConfirm: true
+    });
+  },
+  // 关闭动作面板
+  onActionSheetClose() {
+    this.setData({
+      showActionSheet: false
+    });
+  },
+  // 确认分配
+  confirmAssign() {
+    const { selectedTeam, currentClueId } = this.data;
+    if (selectedTeam && currentClueId) {
+      this.doAssignClue(currentClueId, selectedTeam);
+    }
+    this.setData({
+      showAssignConfirm: false,
+      selectedTeam: null
+    });
+  },
+  // 取消分配
+  cancelAssign() {
+    this.setData({
+      showAssignConfirm: false,
+      selectedTeam: null
+    });
+  },
+  // 点击撤回按钮 - 弹出确认框
+  onWithdrawTap(e) {
+    const item = e.currentTarget.dataset.item;
+    const { leader } = this.data;
+    if (!leader) {
+      wx.showToast({ title: '未找到团队负责人', icon: 'none' });
+      return;
+    }
+    this.setData({
+      currentClueId: item.sat_orderclueid,
+      selectedTeam: leader,
+      showWithdrawConfirm: true
+    });
+  },
+  // 确认撤回
+  confirmWithdraw() {
+    const { selectedTeam, currentClueId } = this.data;
+    if (selectedTeam && currentClueId) {
+      this.doAssignClue(currentClueId, selectedTeam);
+    }
+    this.setData({
+      showWithdrawConfirm: false,
+      selectedTeam: null
+    });
+  },
+  // 取消撤回
+  cancelWithdraw() {
+    this.setData({
+      showWithdrawConfirm: false,
+      selectedTeam: null
+    });
+  },
+  // 执行分配/撤回接口
+  doAssignClue(clueId, team) {
+    _Http.basic({
+      classname: "crm.agent.orderclue.orderclue",
+      method: "changeClue",
+      content: {
+        sat_orderclueid: [clueId],
+        sys_enterprise_hrid: team.sys_enterprise_hrid,
+        ordercluecount: "待跟进"
+      }
+    }).then(res => {
+      console.log("线索分配结果", res);
+      if (res.code === 1) {
+        wx.showToast({ title: '操作成功', icon: 'none' });
+        this.getList(true);
+      } else {
+        wx.showToast({ title: res.msg || '操作失败', icon: 'none' });
+      }
+    }).catch(err => {
+      console.error('线索分配失败', err);
+      wx.showToast({ title: '网络错误', icon: 'none' });
+    });
+  },
+  // 打电话
+  makeCall(e) {
+    const item = e.currentTarget.dataset.item;
+    const phoneNumber = item.phonenumber;
+    if (!phoneNumber) {
+      wx.showToast({
+        title: '未找到电话号码',
+        icon: 'none'
+      });
+      return;
+    }
+    wx.makePhoneCall({
+      phoneNumber: phoneNumber,
+      success: (res) => {
+        // 调用跟进接口
+        this.addFollowRecord(item.sat_orderclueid);
+      },
+      fail: (err) => {
+        console.error('拨打电话失败', err);
+      }
+    });
+  },
+  // 添加跟进记录
+  addFollowRecord(clueId) {
+    const content = {
+      sat_orderclueid: clueId,
+      content: '',
+      logtype: "电话沟通",
+      followTime: new Date().toISOString().slice(0, 19).replace('T', ' '),
+      result: "继续跟进"
+    };
+    _Http.basic({
+      id: "20221208100602",
+      content
+    }).then(res => {
+      console.log('添加跟进记录结果:', res);
+      if (res.code === 1) {
+        // 刷新列表
+        this.getList(true);
+      }
+    }).catch(err => {
+      console.error('添加跟进记录失败:', err);
+    });
   }
 });

+ 5 - 1
CRM/lead/index.json

@@ -1,4 +1,8 @@
 {
-  "usingComponents": {},
+  "usingComponents": {
+    "van-icon": "@vant/weapp/icon/index",
+    "van-action-sheet": "@vant/weapp/action-sheet/index",
+    "van-dialog": "@vant/weapp/dialog/index"
+  },
   "navigationBarTitleText": "线索列表"
 }

+ 121 - 18
CRM/lead/index.scss

@@ -7,50 +7,77 @@
   width: 100%;
 }
 
+.list-item {
+  margin-bottom: 24rpx;
+  border-radius: 16rpx;
+  overflow: hidden;
+  box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.06);
+  background-color: #fff;
+}
+
 .item {
-  display: flex;
-  flex-direction: column;
   padding: 24rpx;
-  background-color: #fff;
-  margin-bottom: 20rpx;
-  border-radius: 12rpx;
-  box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.05);
+  transition: all 0.3s ease;
+
+  &:active {
+    background-color: #f9f9f9;
+  }
 
   .top {
     display: flex;
     justify-content: space-between;
     align-items: center;
-    margin-bottom: 16rpx;
+    margin-bottom: 20rpx;
+
+    .name-row {
+      display: flex;
+      align-items: center;
+      flex: 1;
+      overflow: hidden;
+      margin-right: 16rpx;
+    }
 
     .name {
       font-size: 34rpx;
       font-weight: 600;
       color: #1a1a1a;
-      flex: 1;
+      line-height: 48rpx;
+      flex-shrink: 0;
+      margin-right: 16rpx;
+    }
+
+    .phone-tag {
+      font-size: 26rpx;
+      color: #666;
+      line-height: 40rpx;
       overflow: hidden;
       text-overflow: ellipsis;
       white-space: nowrap;
-      margin-right: 16rpx;
     }
 
     .statu {
-      font-size: 22rpx;
-      padding: 6rpx 16rpx;
-      border-radius: 6rpx;
+      font-size: 24rpx;
+      padding: 6rpx 20rpx;
+      border-radius: 8rpx;
       font-weight: 500;
       flex-shrink: 0;
+      background-color: #fff;
+      border: 2rpx solid;
     }
   }
 
   .content {
     width: 100%;
+    margin-bottom: 8rpx;
 
     .row {
       display: flex;
-      margin-top: 12rpx;
-      
-      &:first-child {
-        margin-top: 0;
+      margin-bottom: 14rpx;
+      flex-wrap: wrap;
+      align-items: center;
+
+      &:last-child {
+        margin-bottom: 0;
       }
     }
 
@@ -58,12 +85,88 @@
       flex: 1;
       font-size: 26rpx;
       color: #666;
-      line-height: 1.5;
+      line-height: 40rpx;
+      margin-right: 24rpx;
 
       &.full-width {
         flex: none;
         width: 100%;
+        margin-right: 0;
       }
     }
   }
-}
+}
+
+/* 操作按钮区域 */
+.actions {
+  display: flex;
+  padding: 20rpx 24rpx;
+  gap: 16rpx;
+  background: linear-gradient(180deg, #fafbfc 0%, #f5f6f8 100%);
+  border-top: 1rpx solid #eef0f3;
+}
+
+/* 操作按钮基础样式 */
+.action-btn {
+  flex: 1;
+  height: 76rpx;
+  border-radius: 38rpx;
+  font-size: 26rpx;
+  font-weight: 500;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  color: #fff;
+  position: relative;
+  overflow: hidden;
+  text-decoration: none;
+  letter-spacing: 1rpx;
+  box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.12);
+  transition: transform 0.15s ease, box-shadow 0.15s ease;
+
+  /* 转客户 */
+  &.convert {
+    background: linear-gradient(135deg, #3b82f6 0%, #2563eb 100%);
+    box-shadow: 0 4rpx 14rpx rgba(37, 99, 235, 0.3);
+
+    &:active {
+      box-shadow: 0 2rpx 6rpx rgba(37, 99, 235, 0.25);
+    }
+  }
+
+  /* 分配 */
+  &.assign {
+    background: linear-gradient(135deg, #10b981 0%, #059669 100%);
+    box-shadow: 0 4rpx 14rpx rgba(5, 150, 105, 0.3);
+
+    &:active {
+      box-shadow: 0 2rpx 6rpx rgba(5, 150, 105, 0.25);
+    }
+  }
+
+  /* 撤回 */
+  &.withdraw {
+    background: linear-gradient(135deg, #f59e0b 0%, #d97706 100%);
+    box-shadow: 0 4rpx 14rpx rgba(217, 119, 6, 0.3);
+
+    &:active {
+      box-shadow: 0 2rpx 6rpx rgba(217, 119, 6, 0.25);
+    }
+  }
+
+  /* 打电话 */
+  &.call {
+    background: linear-gradient(135deg, #8b5cf6 0%, #7c3aed 100%);
+    box-shadow: 0 4rpx 14rpx rgba(124, 58, 237, 0.3);
+
+    &:active {
+      box-shadow: 0 2rpx 6rpx rgba(124, 58, 237, 0.25);
+    }
+  }
+
+  /* 按压效果 */
+  &:active {
+    transform: scale(0.95);
+    opacity: 0.9;
+  }
+}

+ 36 - 10
CRM/lead/index.wxml

@@ -2,17 +2,19 @@
   <van-search use-action-slot placeholder='请输入搜索关键词' shape='round' bind:search="onSearch" bind:clear="onSearch" />
   <view class="header" style="height: 20rpx;"></view>
   <Yl_ListBox id='ListBox' bind:getlist='getList'>
-    <view wx:for="{{list}}" wx:key="sat_orderclueid" bind:tap="goToDetail" data-id="{{item.sat_orderclueid}}">
-      <view class="item">
+    <view wx:for="{{list}}" wx:key="sat_orderclueid" class="list-item">
+      <view class="item" bind:tap="goToDetail" data-id="{{item.sat_orderclueid}}">
         <view class="top">
-          <view class="name">{{item.name || '--'}}</view>
-          <view class="statu" style="background-color: {{set.color(item.status)}}; color: #fff;">
+          <view class="name-row">
+            <view class="name">{{item.name || '--'}}</view>
+            <view class="phone-tag">{{item.phonenumber || '--'}}</view>
+          </view>
+          <view class="statu" style="border-color: {{set.color(item.status)}}; color: {{set.color(item.status)}};">
             {{item.status || '--'}}
           </view>
         </view>
         <view class="content">
           <view class="row">
-            <view class="exp">手机号:{{item.phonenumber || '--'}}</view>
             <view class="exp">来源:{{item.cluesource || '--'}}</view>
           </view>
           <view class="row">
@@ -23,19 +25,43 @@
             <view class="exp full-width">地址:{{item.address || '--'}}</view>
           </view>
           <view class="row">
-            <view class="exp full-width">备注:{{item.notes || '--'}}</view>
-          </view>
-          <view class="row">
-            <view class="exp">创建人:{{item.followBy || '--'}}</view>
-            <view class="exp">最后跟进时间:{{item.followDate || '--'}}</view>
+            <view class="exp full-width">最后跟进时间:{{item.followDate || '--'}}</view>
           </view>
         </view>
       </view>
+      <view class="actions">
+        <view wx:if="{{item.status !== '已无效' && item.status !== '已转化'}}" bind:tap="convertToCustomer" data-item="{{item}}" class="action-btn convert">
+          <van-icon name="friends" size="28rpx" color="#fff" custom-style="margin-right: 8rpx;" />
+          <text>转客户</text>
+        </view>
+        <view wx:if="{{item.status !== '已无效' && hasAllotPermission && leader && item.leadername === leader.name}}" catchtap="onAssignTap" data-item="{{item}}" class="action-btn assign">
+          <van-icon name="share" size="28rpx" color="#fff" custom-style="margin-right: 8rpx;" />
+          <text>分配</text>
+        </view>
+        <view wx:if="{{item.status !== '已无效' && hasAllotPermission && leader && item.leadername !== leader.name}}" catchtap="onWithdrawTap" data-item="{{item}}" class="action-btn withdraw">
+          <van-icon name="revoke" size="28rpx" color="#fff" custom-style="margin-right: 8rpx;" />
+          <text>撤回</text>
+        </view>
+        <view bind:tap="makeCall" data-item="{{item}}" class="action-btn call">
+          <van-icon name="phone" size="28rpx" color="#fff" custom-style="margin-right: 8rpx;" />
+          <text>打电话</text>
+        </view>
+      </view>
     </view>
     <Yl_Empty wx:if="{{list.length==0}}" />
     <view style="height:150rpx;" />
   </Yl_ListBox>
 </view>
+
+<!-- 线索分配动作面板 -->
+<van-action-sheet show="{{ showActionSheet }}" title="选择负责人" actions="{{ teamActions }}" cancel-text="取消" zIndex='99999999' bind:cancel='onActionSheetClose' bind:close="onActionSheetClose" bind:select="onActionSheetSelect" />
+
+<!-- 分配确认弹窗 -->
+<van-dialog show="{{ showAssignConfirm }}" title="确认分配" message="确定要将此线索分配给所选负责人吗?" show-cancel-button bind:confirm="confirmAssign" bind:cancel="cancelAssign" confirm-button-color="#3874F6" />
+
+<!-- 撤回确认弹窗 -->
+<van-dialog show="{{ showWithdrawConfirm }}" title="确认撤回" message="确定要将此线索撤回给团队负责人吗?" show-cancel-button bind:confirm="confirmWithdraw" bind:cancel="cancelWithdraw" confirm-button-color="#3874F6" />
+
 <wxs module="set">
    module.exports = {
     color: function (statu) {

+ 162 - 0
CRM/lead/index.wxss

@@ -0,0 +1,162 @@
+.container {
+  padding: 20rpx;
+  background-color: #f5f5f5;
+}
+
+.list-item {
+  margin-bottom: 24rpx;
+  border-radius: 16rpx;
+  overflow: hidden;
+  box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.06);
+  background-color: #fff;
+}
+
+.item {
+  padding: 24rpx;
+  transition: all 0.3s ease;
+}
+
+.item:active {
+  background-color: #f9f9f9;
+}
+
+.top {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  margin-bottom: 20rpx;
+}
+
+.name-row {
+  display: flex;
+  align-items: center;
+  flex: 1;
+  overflow: hidden;
+  margin-right: 16rpx;
+}
+
+.name {
+  font-size: 34rpx;
+  font-weight: 600;
+  color: #1a1a1a;
+  line-height: 48rpx;
+  flex-shrink: 0;
+  margin-right: 16rpx;
+}
+
+.phone-tag {
+  font-size: 26rpx;
+  color: #666;
+  line-height: 40rpx;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+}
+
+.statu {
+  padding: 6rpx 20rpx;
+  border-radius: 8rpx;
+  font-size: 24rpx;
+  font-weight: 500;
+  flex-shrink: 0;
+  background-color: #fff;
+  border: 2rpx solid;
+}
+
+.content {
+  margin-bottom: 8rpx;
+}
+
+.row {
+  display: flex;
+  margin-bottom: 14rpx;
+  flex-wrap: wrap;
+  align-items: center;
+}
+
+.exp {
+  flex: 1;
+  font-size: 26rpx;
+  color: #666;
+  margin-right: 24rpx;
+  line-height: 40rpx;
+}
+
+.exp.full-width {
+  flex: 100%;
+  margin-right: 0;
+}
+
+/* 操作按钮区域 */
+.actions {
+  display: flex;
+  padding: 20rpx 24rpx;
+  gap: 16rpx;
+  background: linear-gradient(180deg, #fafbfc 0%, #f5f6f8 100%);
+  border-top: 1rpx solid #eef0f3;
+}
+
+/* 操作按钮基础样式 */
+.action-btn {
+  flex: 1;
+  height: 76rpx;
+  border-radius: 38rpx;
+  font-size: 26rpx;
+  font-weight: 500;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  color: #fff;
+  position: relative;
+  overflow: hidden;
+  text-decoration: none;
+  letter-spacing: 1rpx;
+  box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.12);
+  transition: transform 0.15s ease, box-shadow 0.15s ease;
+}
+
+/* 转客户按钮 */
+.action-btn.convert {
+  background: linear-gradient(135deg, #3b82f6 0%, #2563eb 100%);
+  box-shadow: 0 4rpx 14rpx rgba(37, 99, 235, 0.3);
+}
+
+/* 分配按钮 */
+.action-btn.assign {
+  background: linear-gradient(135deg, #10b981 0%, #059669 100%);
+  box-shadow: 0 4rpx 14rpx rgba(5, 150, 105, 0.3);
+}
+
+/* 撤回按钮 */
+.action-btn.withdraw {
+  background: linear-gradient(135deg, #f59e0b 0%, #d97706 100%);
+  box-shadow: 0 4rpx 14rpx rgba(217, 119, 6, 0.3);
+}
+
+/* 打电话按钮 */
+.action-btn.call {
+  background: linear-gradient(135deg, #8b5cf6 0%, #7c3aed 100%);
+  box-shadow: 0 4rpx 14rpx rgba(124, 58, 237, 0.3);
+}
+
+/* 按钮按压效果 */
+.action-btn:active {
+  transform: scale(0.95);
+  opacity: 0.9;
+}
+
+.action-btn.convert:active {
+  box-shadow: 0 2rpx 6rpx rgba(37, 99, 235, 0.25);
+}
+
+.action-btn.assign:active {
+  box-shadow: 0 2rpx 6rpx rgba(5, 150, 105, 0.25);
+}
+
+.action-btn.withdraw:active {
+  box-shadow: 0 2rpx 6rpx rgba(217, 119, 6, 0.25);
+}
+
+.action-btn.call:active {
+  box-shadow: 0 2rpx 6rpx rgba(124, 58, 237, 0.25);
+}

+ 2 - 4
CRM/lead/modules/followRecord/index.wxml

@@ -12,12 +12,10 @@
     <view wx:for="{{list}}" wx:key="index" class="follow-item">
       <view class="follow-header">
         <view class="follow-title">
-          {{item.rowindex || index + 1}}. {{item.createdate || '--'}}, 由经销商端 <text class="bold-text">{{item.createby || '--'}}</text> {{item.logtype || '转化'}}, <block wx:if="{{item.followupmode}}">
-            跟进方式: <text class="bold-text">{{item.followupmode || '--'}}</text>,
-          </block>跟进内容:
+          {{item.rowindex || index + 1}}. {{item.createdate || '--'}}, 由经销商端 <text class="bold-text">{{item.createby || '--'}}</text> {{item.logtype || '转化'}}<block wx:if="{{item.followupmode}}">, 跟进方式: <text class="bold-text">{{item.followupmode || '--'}}</text></block><block wx:if="{{item.content}}">, 跟进内容:</block>
         </view>
       </view>
-      <view class="follow-content">{{item.content || '--'}}</view>
+      <view wx:if="{{item.content}}" class="follow-content">{{item.content}}</view>
     </view>
   </view>
 </view>

+ 2 - 0
CRM/order/detail.scss

@@ -26,6 +26,8 @@
       font-size: 24rpx;
       padding: 4rpx 12rpx;
       border-radius: 8rpx;
+      background-color: #fff;
+      border: 2rpx solid;
     }
   }
 

+ 1 - 1
CRM/order/detail.wxml

@@ -1,7 +1,7 @@
 <view class="intr">
   <view class="top">
     <view class="name">{{detail.sonum || '--'}}</view>
-    <view class="statu" style="background-color: {{set.color(detail.status)}}; color: #fff;">
+    <view class="statu" style="border-color: {{set.color(detail.status)}}; color: {{set.color(detail.status)}};">
       {{detail.status || '--'}}
     </view>
   </view>

+ 2 - 0
CRM/order/index.scss

@@ -32,6 +32,8 @@
         font-size: 24rpx;
         padding: 4rpx 12rpx;
         border-radius: 8rpx;
+        background-color: #fff;
+        border: 2rpx solid;
       }
     }
 

+ 1 - 1
CRM/order/index.wxml

@@ -5,7 +5,7 @@
     <navigator url="/CRM/order/detail?id={{item.sa_custorderid}}" class="item" wx:for="{{list}}" wx:key="sa_custorderid">
       <view class="top">
         <view class="name">{{item.sonum || '--'}}</view>
-        <view class="statu" style="background-color: {{set.color(item.status)}}; color: #fff;">
+        <view class="statu" style="border-color: {{set.color(item.status)}}; color: {{set.color(item.status)}};">
           {{item.status || '--'}}
         </view>
       </view>

+ 3 - 0
app.json

@@ -123,6 +123,9 @@
         "warehouse/index",
         "lead/index",
         "lead/detail",
+        "contract/index",
+        "contract/create",
+        "contract/detail",
         "customer/modules/order/details",
         "customer/modules/followRecord/create",
         "lead/modules/followRecord/create",

+ 6 - 0
pages/index/index.js

@@ -236,7 +236,13 @@ Page({
 					key: "wcrmlead",
 					path: "/CRM/lead/index",
 					icon: "work-xiaoshouxiansuo"
+				}, {
+					name: "合同",
+					key: "wcrmsign",
+					path: "/CRM/contract/index",
+					icon: "work-hehuoren"
 				}];
+
 				let crm = getApp().globalData.queryPer.query(wx.getStorageSync('userauth'), ["CRM"], ["crm"]),
 					list = [];
 				crm.forEach(v => {

+ 9 - 2
project.private.config.json

@@ -24,12 +24,19 @@
   "condition": {
     "miniprogram": {
       "list": [
+        {
+          "name": "CRM/contract/index",
+          "pathName": "CRM/contract/index",
+          "query": "",
+          "scene": null,
+          "launchMode": "default"
+        },
         {
           "name": "CRM/lead/detail",
           "pathName": "CRM/lead/detail",
           "query": "id=422",
-          "scene": null,
-          "launchMode": "default"
+          "launchMode": "default",
+          "scene": null
         },
         {
           "name": "CRM/order/detail",