Explorar o código

新建行事历模块

qymljy hai 4 meses
pai
achega
cbf4b3b676

+ 3 - 1
app.json

@@ -91,7 +91,9 @@
                 "tryOut/insert",
                 "dealer/Salesperson/insert",
                 "hospital/Surgery/update",
-                "select/area/index"
+                "select/area/index",
+                "select/task/index",
+                "calendar/index"
             ]
         },
         {

+ 1 - 1
project.private.config.json

@@ -1,7 +1,7 @@
 {
     "description": "项目私有配置文件。此文件中的内容将覆盖 project.config.json 中的相同字段。项目的改动优先同步到此文件中。详见文档:https://developers.weixin.qq.com/miniprogram/dev/devtools/projectconfig.html",
     "setting": {
-        "urlCheck": true,
+        "urlCheck": false,
         "autoAudits": false,
         "compileHotReLoad": true,
         "bigPackageSizeSupport": false

+ 202 - 0
prsx/calendar/index.js

@@ -0,0 +1,202 @@
+Page({
+  data: {
+    currentMonth: '2025-12',
+    selectedDate: '2025-12-15',
+    viewMode: 'month', // month / week
+    
+    tasks: [
+      { id: 1, title: '参加扬州大学附属医院产品推介会', date: '2025-12-15' },
+      { id: 2, title: '跟台上海天伦医院手术3场', date: '2025-12-15' }
+    ],
+    records: [
+      { id: 1, title: '参加扬州大学附属医院产品推介会', date: '2025-12-15' },
+      { id: 2, title: '跟台上海天伦医院手术3场', date: '2025-12-15' }
+    ],
+    currentDate: '', // 当前选择的日期
+    currentYear: '', // 当前显示的年份
+    currentMonth: '', // 当前显示的月份
+    weekdays: ['日', '一', '二', '三', '四', '五', '六'],
+    days: [], // 当前月份的日期数组
+    selectedDate: '', // 格式:'2025-04-05'
+  },
+
+  onLoad() {
+    // this.generateCalendar();
+    // this.updateCalendar(new Date());
+    const now = new Date();
+    const year = now.getFullYear();
+    const month = now.getMonth() + 1; // 月份从 0 开始
+    const today = this.formatDate(now);
+
+    this.setData({
+      selectedDate: today
+    });
+
+    this.renderCalendar(year, month);
+  },
+   // 格式化日期为 YYYY-MM-DD
+   formatDate(date) {
+    const y = date.getFullYear();
+    const m = String(date.getMonth() + 1).padStart(2, '0');
+    const d = String(date.getDate()).padStart(2, '0');
+    return `${y}-${m}-${d}`;
+  },
+  // 渲染日历
+  renderCalendar(year, month) {
+    const today = this.formatDate(new Date());
+    const selected = this.data.selectedDate;
+
+    const firstDay = new Date(year, month - 1, 1).getDay(); // 本月1号是星期几(0=周日)
+    const daysInMonth = new Date(year, month, 0).getDate(); // 本月总天数
+
+    let days = [];
+
+    // 上月填充
+    const prevMonthDays = new Date(year, month - 1, 0).getDate();
+    for (let i = firstDay - 1; i >= 0; i--) {
+      const day = prevMonthDays - i;
+      const fullDate = this.formatDate(new Date(year, month - 2, day));
+      days.push({
+        day,
+        type: 'other',
+        fullDate,
+        isToday: false,
+        isSelected: false
+      });
+    }
+
+    // 本月
+    for (let i = 1; i <= daysInMonth; i++) {
+      const fullDate = this.formatDate(new Date(year, month - 1, i));
+      days.push({
+        day: i,
+        type: 'current',
+        fullDate,
+        isToday: fullDate === today,
+        isSelected: fullDate === selected
+      });
+    }
+
+    // 下月填充(补足到 6 行 42 格)
+    const totalCells = 42;
+    const remaining = totalCells - days.length;
+    for (let i = 1; i <= remaining; i++) {
+      const fullDate = this.formatDate(new Date(year, month, i));
+      days.push({
+        day: i,
+        type: 'other',
+        fullDate,
+        isToday: false,
+        isSelected: false
+      });
+    }
+
+    this.setData({
+      currentYear: year,
+      currentMonth: month,
+      days
+    });
+  },
+  // 切换月份
+  onMonthChange(e) {
+    const [year, month] = e.detail.value.split('-').map(Number);
+    this.renderCalendar(year, month);
+  },
+
+  // 点击日期
+  onDayTap(e) {
+    const fullDate = e.currentTarget.dataset.date;
+    this.setData({ selectedDate: fullDate });
+    // 重新渲染以更新 isSelected
+    this.renderCalendar(this.data.currentYear, this.data.currentMonth);
+  },
+  
+  updateCalendar(date) {
+    const year = date.getFullYear();
+    const month = date.getMonth() + 1; // 获取月份(从0开始)
+    const firstDayOfMonth = new Date(year, month - 1, 1).getDay(); // 当月第一天是星期几
+    const totalDaysInMonth = new Date(year, month, 0).getDate(); // 当月总天数
+
+    let days = [];
+    // 添加上个月末尾的空白天数
+    for (let i = 0; i < firstDayOfMonth; i++) {
+      days.push({ day: '', type: 'empty' });
+    }
+    // 添加当月的天数
+    for (let i = 1; i <= totalDaysInMonth; i++) {
+      days.push({ day: i, type: 'day' });
+    }
+
+    this.setData({
+      currentDate: `${year}-${String(month).padStart(2, '0')}`,
+      currentYear: year,
+      currentMonth: month,
+      days: days
+    });
+  },
+
+  generateCalendar() {
+    const { currentMonth } = this.data;
+    const year = parseInt(currentMonth.split('-')[0]);
+    const month = parseInt(currentMonth.split('-')[1]) - 1;
+
+    const date = new Date(year, month, 1);
+    const firstDay = date.getDay(); // 0=Sun, 1=Mon...
+    const daysInMonth = new Date(year, month + 1, 0).getDate();
+
+    let days = [];
+    // 填充前面空格
+    for (let i = 0; i < firstDay; i++) {
+      days.push({ day: '', date: '', isCurrent: false, hasTask: false });
+    }
+
+    // 填充当月日期
+    for (let i = 1; i <= daysInMonth; i++) {
+      const currentDate = `${year}-${String(month + 1).padStart(2, '0')}-${String(i).padStart(2, '0')}`;
+      const hasTask = this.data.tasks.some(t => t.date === currentDate);
+      const isCurrent = currentDate === this.data.selectedDate;
+
+      days.push({
+        day: i,
+        date: currentDate,
+        isCurrent,
+        hasTask,
+        taskCount: this.data.tasks.filter(t => t.date === currentDate).length
+      });
+    }
+
+    this.setData({ days });
+  },
+
+  bindDateChange(e) {
+    // const value = e.detail.value;
+    // this.setData({ currentMonth: value });
+    // this.generateCalendar();
+    const selectedDate = e.detail.value.split('-');
+    const year = parseInt(selectedDate[0], 10);
+    const month = parseInt(selectedDate[1], 10);
+    this.updateCalendar(new Date(year, month - 1));
+  },
+
+  goToday() {
+    const today = new Date().toISOString().split('T')[0];
+    this.setData({ currentMonth: today.substring(0, 7), selectedDate: today });
+    this.generateCalendar();
+  },
+
+  switchView(e) {
+    const mode = e.currentTarget.dataset.view;
+    this.setData({ viewMode: mode });
+  },
+
+  onDayClick(e) {
+    const date = e.currentTarget.dataset.date;
+    this.setData({ selectedDate: date });
+  },
+
+  addNew() {
+    wx.navigateTo({
+      url: '../add/add'
+    });
+  }
+});

+ 4 - 0
prsx/calendar/index.json

@@ -0,0 +1,4 @@
+{
+    "usingComponents": {},
+    "navigationBarTitleText": "行事历"
+}

+ 267 - 0
prsx/calendar/index.scss

@@ -0,0 +1,267 @@
+.container {
+  background-color: #f8f9fa;
+  min-height: 100vh;
+}
+
+.navbar {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  height: 60rpx;
+  background-color: #007AFF;
+  color: white;
+  padding: 0 20rpx;
+  font-size: 32rpx;
+}
+
+.back-btn {
+  font-size: 32rpx;
+  color: white;
+}
+
+.right-actions {
+  display: flex;
+  gap: 20rpx;
+  align-items: center;
+}
+
+.dots, .profile {
+  width: 40rpx;
+  height: 40rpx;
+  border-radius: 50%;
+  background-color: rgba(255,255,255,0.3);
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  font-size: 24rpx;
+}
+
+.calendar-header {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  padding: 20rpx;
+  background-color: white;
+  border-bottom: 1rpx solid #e5e5e5;
+  margin: 0 20rpx 0 20rpx;
+}
+
+.select-date {
+  font-size: 32rpx;
+  color: #333;
+}
+
+.calendar-controls {
+  display: flex;
+  gap: 20rpx;
+}
+
+.btn-today, .btn-month, .btn-week {
+  padding: 10rpx 20rpx;
+  border-radius: 20rpx;
+  font-size: 28rpx;
+  background-color: #007AFF;
+  color: white;
+}
+
+.btn-month.active {
+  background-color: #007AFF;
+}
+
+.calendar-grid {
+  margin: 10rpx;
+  background-color: white;
+  border-radius: 10rpx;
+  overflow: hidden;
+  box-shadow: 0 5rpx 5rpx rgba(0,0,0,0.1);
+}
+
+.weekdays {
+  display: grid;
+  grid-template-columns: repeat(7, 1fr);
+  text-align: center;
+  padding: 10rpx;
+  font-size: 28rpx;
+  color: #999;
+}
+
+.day-item {
+  position: relative;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  height: 80rpx;
+  font-size: 28rpx;
+  color: #333;
+  cursor: pointer;
+}
+
+.day-item.current {
+  color: #007AFF;
+  font-weight: bold;
+}
+
+.day-item.has-task::after {
+  content: '';
+  position: absolute;
+  bottom: 10rpx;
+  right: 10rpx;
+  width: 8rpx;
+  height: 8rpx;
+  background-color: #ff3b30;
+  border-radius: 50%;
+}
+
+.task-dot {
+  width: 8rpx;
+  height: 8rpx;
+  background-color: #ff3b30;
+  border-radius: 50%;
+  margin-top: 4rpx;
+}
+
+.section {
+  margin: 20rpx;
+  background-color: white;
+  border-radius: 10rpx;
+  padding: 20rpx;
+  box-shadow: 0 2rpx 10rpx rgba(0,0,0,0.1);
+}
+
+.section-title {
+  font-size: 32rpx;
+  color: #333;
+  margin-bottom: 10rpx;
+}
+
+.section-date {
+  font-size: 28rpx;
+  color: #999;
+  margin-bottom: 10rpx;
+}
+
+.task-item, .record-item {
+  margin-bottom: 15rpx;
+  padding: 15rpx;
+  border-left: 5rpx solid #ff3b30;
+  background-color: #fff8f8;
+  border-radius: 6rpx;
+}
+
+.record-item {
+  border-left-color: #007AFF;
+  background-color: #f0f8ff;
+}
+
+.task-text, .record-text {
+  font-size: 28rpx;
+  color: #333;
+}
+
+.add-btn {
+  position: fixed;
+  bottom: 60rpx;
+  right: 60rpx;
+  width: 80rpx;
+  height: 80rpx;
+  background-color: #007AFF;
+  border-radius: 50%;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  color: white;
+  font-size: 48rpx;
+  z-index: 10;
+}
+
+.calendar-container {
+  padding: 20rpx;
+  background-color: #f5f5f5;
+}
+
+.calendar-header {
+  text-align: center;
+  font-size: 36rpx;
+  margin-bottom: 20rpx;
+  color: #333;
+}
+
+.weekdays {
+  display: grid;
+  grid-template-columns: repeat(7, 1fr);
+  text-align: center;
+  font-size: 28rpx;
+  color: #666;
+  margin-bottom: 10rpx;
+}
+
+.calendar-grid {
+  display: grid;
+  grid-template-columns: repeat(7, 1fr);
+  gap: 10rpx;
+}
+
+.calendar-grid view {
+  text-align: center;
+  padding: 8px;
+}
+
+.calendar-grid .empty {
+  color: #ccc;
+}
+
+.day {
+  display: flex;
+  flex-direction: column;
+  justify-content: center;
+  align-items: center;
+  height: 60rpx; /* 稍微增加高度,避免拥挤 */
+  font-size: 28rpx;
+  border-radius: 10rpx;
+}
+.dots-container {
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  margin-top: 4rpx;
+  height: 5rpx;
+}
+
+.dot {
+  font-size: 20rpx;
+  line-height: 1;
+  margin: 0 2rpx;
+}
+
+
+.task-dot {
+  color: #ff3b30; /* 红色 - 任务 */
+}
+
+.followup-dot {
+  color: #007AFF; /* 蓝色 - 跟进 */
+}
+
+/* 当前月日期 */
+.day.current {
+  color: #333;
+  background-color: #fff;
+}
+
+/* 非当前月(灰色) */
+.day.other {
+  color: #ccc;
+}
+
+/* 今日样式(边框 or 背景) */
+.day.today {
+  color: #85b8ee;
+  font-weight: bold;
+}
+
+/* 选中日期高亮 */
+.day.selected {
+  background-color: #85b8ee !important;
+  color: white !important;
+  font-weight: bold;
+}

+ 59 - 0
prsx/calendar/index.wxml

@@ -0,0 +1,59 @@
+<view class="container">
+  <!-- 日历头部 -->
+  <view class="calendar-header">
+    <picker mode="date" fields="month" value="{{currentDate}}" bindchange="onMonthChange">
+      <view>{{currentYear}}年{{currentMonth}}月</view>
+    </picker>
+    <!-- <view class="calendar-controls">
+      <button class="btn-today" bindtap="goToday">今</button>
+      <button class="btn-month" bindtap="switchView" data-view="month">月</button>
+      <button class="btn-week" bindtap="switchView" data-view="week">周</button>
+    </view> -->
+  </view>
+
+  <view class="calendar-container">
+    <!-- 星期栏 -->
+    <view class="weekdays">
+      <block wx:for="{{weekdays}}" wx:key="index">
+        <view>{{item}}</view>
+      </block>
+    </view>
+
+    <!-- 日历网格 -->
+    <view class="calendar-grid">
+      <block wx:for="{{days}}" wx:key="index">
+        <view class="day {{item.type}} {{item.isSelected ? 'selected' : ''}} {{item.isToday ? 'today' : ''}}" data-date="{{item.fullDate}}" bindtap="{{item.type === 'current' ? 'onDayTap' : ''}}">
+          <text>{{ item.day }}</text>
+          <!-- 任务和跟进标记容器 -->
+          <view class="dots-container" >
+            <text  class="dot task-dot">•</text>
+            <text  class="dot followup-dot" style="line-height: 1;margin-top: 1rpx;">•</text>
+          </view>
+        </view>
+      </block>
+    </view>
+  </view>
+
+  <!-- 任务列表 -->
+  <view class="section">
+    <view class="section-title">任务</view>
+    <view class="section-date">{{ selectedDate }}</view>
+    <view wx:for="{{ tasks }}" wx:key="id" class="task-item">
+      <text class="task-text">{{ item.title }}</text>
+    </view>
+  </view>
+
+  <!-- 跟进记录 -->
+  <view class="section">
+    <view class="section-title">跟进记录</view>
+    <view class="section-date">{{ selectedDate }}</view>
+    <view wx:for="{{ records }}" wx:key="id" class="record-item">
+      <text class="record-text">{{ item.title }}</text>
+    </view>
+  </view>
+
+  <!-- 添加按钮 -->
+  <view class="add-btn" bindtap="addNew">
+    <text>+</text>
+  </view>
+</view>

+ 1 - 0
prsx/select/department/index.js

@@ -57,6 +57,7 @@ Page({
     },
     /* 选中 */
     changeResult(e) {
+      console.log(e,'e的数据选择')
         let {
             id
         } = e.currentTarget.dataset, result = this.data.result;

+ 127 - 0
prsx/select/task/index.js

@@ -0,0 +1,127 @@
+const _Http = getApp().globalData.http;
+
+Page({
+    data: {
+        params: {}, //请求体
+        result: [], //返回结果
+        radio: false, //是否为单选
+        idname: "sys_taskid", //idkey
+        showName: "title", //表单用 显示名称
+        sColors: getApp().globalData.sColors,
+    },
+    onLoad(options) {
+        console.log("options", options)
+        if (options.params) {
+            let params = JSON.parse(options.params);
+            if (!params.content.pageNumber || !params.content.pageTotal) {
+                params.content.pageNumber = 1;
+                params.content.pageTotal = 1;
+            }
+            this.setData({
+                params
+            });
+        }
+        this.setData({
+            radio: options.radio ? true : false,
+            idname: options.idname || this.data.idname,
+            showName: options.showName || this.data.showName
+        });
+        this.getList()
+    },
+    getList(init = false) {
+        //init 用于初始化分页
+        if (init.detail != undefined) init = init.detail;
+        let params = this.data.params;
+        if (init) params.content.pageNumber = 1;
+        if (params.content.pageNumber > params.content.pageTotal) return;
+        //init 用于初始化分页
+        _Http.basic(params).then(res => {
+            console.log("选择任务列表", res)
+            this.selectComponent('#ListBox').RefreshToComplete();
+            if (res.code != '1') return wx.showToast({
+                title: res.data,
+                icon: "none"
+            })
+            this.setData({
+                'params.content.pageNumber': res.pageNumber + 1,
+                'params.content.pageTotal': res.pageTotal,
+                'params.content.total': res.total,
+                list: res.pageNumber == 1 ? res.data : this.data.list.concat(res.data)
+            })
+        })
+    },
+    uploadList() {
+        let params = JSON.parse(JSON.stringify(this.data.params));
+        params.content.pageSize = (params.content.pageNumber - 1) * params.content.pageSize;
+        params.content.pageNumber = 1;
+        _Http.basic(params).then(res => {
+            console.log("更新列表", res);
+            if (res.code != '1') return wx.showToast({
+                title: res.data,
+                icon: "none"
+            })
+            this.setData({
+                'params.content.total': res.total,
+                list: res.data
+            })
+        })
+    },
+    /* 选中 */
+    changeResult(e) {
+      console.log(e,'eeee')
+        let {
+            id
+        } = e.currentTarget.dataset, result = this.data.result;
+        if (this.data.radio) {
+            result = [id];
+        } else {
+            result.some(v => v == id) ? result = result.filter(v => v != id) : result.push(id)
+        }
+        this.setData({
+            result
+        });
+        if (this.data.radio) this.submit();
+    },
+    /* 提交 */
+    submit() {
+      console.log(this.data,'输出提交数据')
+        let result = this.data.result,
+            obj = this.data.radio ? {
+                id: result,
+                item: this.data.list.find(value => value[this.data.idname] == result),
+                value: [this.data.list.find(value => value[this.data.idname] == result)[this.data.showName], result]
+            } : {
+                result,
+                list: result.map(v => this.data.list.find(value => value[this.data.idname] == v)),
+                value: [result.map(v => {
+                    let data = this.data.list.find(value => value[this.data.idname] == v);
+                    return data ? data[this.data.showName] : ""
+                }), result]
+            }
+        getApp().globalData.handleSelect && getApp().globalData.handleSelect(obj)
+    },
+    /* 开始搜索 */
+    startSearch({
+        detail
+    }) {
+        let condition = this.data.content ? this.data.content.where.condition : this.data.params.content.where.condition;
+        if (detail == condition) return;
+        this.setData({
+            'content.where.condition': detail,
+            'params.content.where.condition': detail
+        });
+        this.getList(true);
+    },
+    /* 取消搜索 */
+    onClear() {
+        this.setData({
+            'content.where.condition': "",
+            'params.content.where.condition': ""
+        });
+        this.getList(true);
+    },
+    onUnload() {
+        //回收数据
+        getApp().globalData.handleSelect = null;
+    },
+})

+ 4 - 0
prsx/select/task/index.json

@@ -0,0 +1,4 @@
+{
+  "usingComponents": {},
+  "navigationBarTitleText": "选择任务"
+}

+ 115 - 0
prsx/select/task/index.scss

@@ -0,0 +1,115 @@
+.project-item {
+	display: flex;
+	align-items: center;
+	background-color: #fff;
+	width: 690rpx;
+	border-radius: 8rpx;
+	margin: 0 auto 20rpx;
+	padding: 20rpx 30rpx;
+	box-sizing: border-box;
+
+	.main {
+		position: relative;
+		overflow: hidden;
+
+		.label {
+			font-size: 30rpx;
+      font-family: PingFang SC-Regular, PingFang SC;
+      font-weight: bold;
+			color: #333333;
+		}
+
+		.tag-box {
+			display: flex;
+			align-items: center;
+			width: 100%;
+
+			.datatag,
+			.systemtag {
+				flex-shrink: 0;
+				margin-top: 6rpx;
+				background: #3874f6;
+				color: #ffffff;
+				margin-right: 10rpx;
+				display: flex;
+				align-items: center;
+				height: 40rpx;
+				font-size: 20rpx;
+				padding: 0 10rpx;
+				border-radius: 20rpx;
+				font-family: PingFang SC-Regular, PingFang SC;
+			}
+
+			.datatag {
+				background: #FA8C16;
+			}
+		}
+
+		.replenish {
+			display: flex;
+			min-height: 34rpx;
+			font-size: 24rpx;
+			font-family: PingFang SC-Regular, PingFang SC;
+			color: #333333;
+			margin-top: 8rpx;
+			word-break: break-all;
+			white-space: pre-wrap;
+    }
+    .replenish1 {
+			display: flex;
+			min-height: 34rpx;
+			font-size: 20rpx;
+			font-family: PingFang SC-Regular, PingFang SC;
+			color: #c9c9c9;
+			margin-top: 8rpx;
+			word-break: break-all;
+			white-space: pre-wrap;
+		}
+  }
+  
+}
+
+.line-1 {
+	overflow: hidden;
+	white-space: nowrap;
+	text-overflow: ellipsis;
+}
+
+
+.footer {
+	display: flex;
+	justify-content: space-between;
+	align-items: center;
+	padding: 0 30rpx;
+	position: fixed;
+	width: 100vw;
+	height: 130rpx;
+	background: #FFFFFF;
+	box-shadow: 0px -4rpx 16rpx 2rpx rgba(150, 157, 165, 0.16);
+	bottom: 0;
+	box-sizing: border-box;
+
+	.count {
+		font-size: 28rpx;
+		font-family: PingFang SC-Regular, PingFang SC;
+		color: #333333;
+	}
+
+	.but {
+		width: 156rpx;
+		height: 90rpx;
+		background: #3874F6;
+		border-radius: 8rpx;
+		font-size: 28rpx;
+		font-family: PingFang SC-Bold, PingFang SC;
+		font-weight: bold;
+		color: #FFFFFF;
+	}
+}
+
+.iconfont {
+	font-size: 28rpx;
+	font-family: PingFang SC-Regular, PingFang SC;
+	color: #666666;
+	padding: 0 10rpx;
+}

+ 37 - 0
prsx/select/task/index.wxml

@@ -0,0 +1,37 @@
+<van-search value="{{ params.content.where.condition }}" shape='round' placeholder="请输入搜索关键词" use-action-slot bind:clear='onClear' bind:search="startSearch">
+</van-search>
+<view class="global-total">总共{{params.content.total}}个</view>
+<Yl_ListBox id='ListBox' bind:getlist='getList'>
+	<navigator url="#" class="project-item" wx:for="{{list}}" wx:key="sys_taskid" data-id="{{item.sys_taskid}}" bind:tap="changeResult">
+		<view class="main">
+			<view class="label">
+				{{item.title}}
+			</view>
+			<view class="replenish">
+				<text>{{item.contenttext}}</text>
+			</view>
+			<view class="replenish1">
+				<text>{{item.begindate + '至' + item.enddate}}</text>
+			</view>
+		</view>
+	</navigator>
+	<view wx:if="{{!radio}}" style="height: 70rpx;" />
+	<My_empty wx:if="{{!list.length}}" />
+</Yl_ListBox>
+<block wx:if="{{!radio}}">
+	<view class="footer">
+		<view class="count">
+			已选:{{result.length}}
+		</view>
+		<van-button custom-class='but' disabled='{{result.length==0}}' bind:click="submit">确定</van-button>
+	</view>
+	<wxs module="handle">
+		module.exports = {
+			isCheck: function (id, list) {
+				return list.some(function (v) {
+					return v == id
+				});
+			},
+		}
+	</wxs>
+</block>

+ 350 - 165
prsx/trace/add/index.js

@@ -1,177 +1,362 @@
 const _Http = getApp().globalData.http;
 Page({
-    data: {
-        loading: false,
-        list: [{
-            label: "跟进内容",
-            key: "content",
-            value: "",
-        }],
-        content: {
+  data: {
+    loading: false,
+    showAll: false,
+    special: false,
+    disabled: true,
+    list: [{
+      label: "跟进内容",
+      key: "content",
+      value: "",
+    }],
+    content: {
 
-        }
     },
-    onLoad(options) {
-        getApp().globalData.Language.getLanguagePackage(this, '跟进');
-        if (options.ownertable) {
-            this.setData({
-                ...options
-            })
-        };
-        //编辑获取原信息,新建初始化模板
-        if (options.sys_datafollowupid) {
-            _Http.basic({
-                "id": 20221026085601,
-                "content": {
-                    "sys_datafollowupid": options.sys_datafollowupid
-                },
-            }).then(res => {
-                console.log("跟进详情", res)
-                if (res.code != '1') {
-                    wx.showToast({
-                        title: res.msg,
-                        icon: "none"
-                    })
-                    setTimeout(() => {
-                        wx.navigateBack()
-                    }, 300)
-                };
-                this.setData({
-                    [`list[0].value`]: res.data.content,
-                    resource: res.data.resource
-                })
-                if (res.data.attinfos.length) this.selectComponent("#Yl_files").handleFiles(res.data.attinfos);
-                this.data.content = Object.assign(res.data, options);
+  },
+  onLoad(options) {
+    getApp().globalData.Language.getLanguagePackage(this, '跟进');
+    console.log(options, 'options********')
+    if (options.ownertable) {
+      this.setData({
+        ...options
+      })
+    };
+    console.log(options.resource, 'resource')
+    // this.formSet(options.resource)
+    if (options.resource == '医院管理' || options.resource == '科室管理' || options.resource == '医生管理' || options.resource == '经销商管理' || options.resource == '行事历') {
+      this.setData({
+        special: true
+      })
+    }
 
-            })
-        } else {
-            options.sys_datafollowupid = 0;
-            this.data.content = options;
-        }
-    },
-    changeState({
-        detail
-    }) {
-        this.setData({
-            loading: detail
-        })
-    },
-    onInput(e) {
-        const {
-            index
-        } = e.target.dataset;
-        this.data.list[index].value = e.detail.value;
-        this.setData({
-            list: this.data.list
-        })
-    },
-    onVoiceInput(e) {
-        let {
-            index
-        } = e.target.dataset;
-        this.setData({
-            [`list[${index}].value`]: e.detail
-        })
-    },
-    /* 绑定媒体 */
-    insertImgEdit({
-        detail
-    }) {
-        this.handleFileLink(detail)
-    },
-    handleFileLink(attachmentids, ownertable = "temporary", ownerid = 1, data) {
-        _Http.basic({
-            "classname": "system.attachment.Attachment",
-            "method": "createFileLink",
-            "content": {
-                ownertable,
-                ownerid,
-                usetype: 'default',
-                attachmentids
-            }
-        }).then(res => {
-            console.log('跟进记录绑定附件', res)
-            if (res.code != '1') return wx.showToast({
-                title: res.msg,
-                icon: "none"
-            })
-            if (ownertable == 'temporary') {
-                this.selectComponent("#Yl_files").handleFiles(res.data)
-            } else {
-                if (res.data.length) data.attinfos = res.data;
-                _Http.basic({
-                    "classname": "system.attachment.Attachment",
-                    "method": "createFileLink",
-                    "content": {
-                        ownertable: this.data.ownertable,
-                        ownerid: this.data.ownerid,
-                        usetype: 'default',
-                        attachmentids
-                    }
-                })
-                this.changeItem(data)
-                setTimeout(() => {
-                    wx.navigateBack()
-                }, 500)
-            }
-        })
-    },
-    changeItem(data) {
+    //编辑获取原信息,新建初始化模板
+    if (options.sys_datafollowupid) {
+      _Http.basic({
+        "id": 20221026085601,
+        "content": {
+          "sys_datafollowupid": options.sys_datafollowupid
+        },
+      }).then(res => {
+        console.log("跟进详情", res)
+        if (res.code != '1') {
+          wx.showToast({
+            title: res.msg,
+            icon: "none"
+          })
+          setTimeout(() => {
+            wx.navigateBack()
+          }, 300)
+        };
+        // this.formSet(res.data.resource, res.data.type, '编辑', res.data)
+        // if (res.data.resource == '医院管理' || res.data.resource == '科室管理' || res.data.resource == '医生管理' || res.data.resource == '经销商管理' || res.data.resource == '行事历') {
+        //   this.setData({
+        //     special: true
+        //   })
+        // } else {
+          
+        // }
         this.setData({
-            loading: false
+          [`list[0].value`]: res.data.content,
+          resource: res.data.resource
         })
-        let page = getCurrentPages()[getCurrentPages().length - 2],
-            isDetail = page.__route__ == 'prsx/trace/detail/index';
-        if (isDetail) {
-            page.getDetail();
-            page = getCurrentPages()[getCurrentPages().length - 3];
-        }
-        let model = page.selectComponent("#Trace");
-        if (this.data.content.sys_datafollowupid == 0) {
-            if (page) {
-                if (model) model.getList(0, true)
-            }
-        } else {
-            let list = model.data.list,
-                index = list.findIndex(v => v.sys_datafollowupid == data.sys_datafollowupid);
-            if (index != -1) list[index] = data;
-            model.setData({
-                list
-            })
+        if (res.data.attinfos.length) this.selectComponent("#Yl_files").handleFiles(res.data.attinfos);
+        this.data.content = Object.assign(res.data, options);
 
-        }
-    },
-    submit() {
-        this.setData({
-            loading: true
-        })
-        let content = Object.assign(this.data.content, this.selectComponent("#Form").submit())
-        content.content = this.data.list[0].value;
-        content.resource = this.data.resource || ''
+      })
+    } else {
+      options.sys_datafollowupid = 0;
+      this.data.content = options;
+    }
+  },
+  formSet(val, type_select, btn_type, datas) {
+    let form = [{
+      label: "跟进类型",
+      error: false,
+      errMsg: "",
+      type: "option",
+      optionNmae: "hosfollowtype",
+      optionType: "radio", //复选   radio 单选
+      value: "",
+      placeholder: "跟进类型",
+      valueName: "type",
+      checking: "base",
+      required: true
+    }, {
+      label: "关联任务",
+      error: false,
+      errMsg: "",
+      type: "route",
+      url: "/prsx/select/task/index",
+      value: "",
+      placeholder: "任务",
+      valueName: "sys_taskid",
+      checking: "base",
+      required: false,
+      params: {
+        "content": {
+          "pageNumber": 1,
+          "pageSize": 20,
+          "where": {
+            "condition": ""
+          }
+        },
+        "id": 2025122309161202,
+      },
+      query: "&radio=true",
+    }, {
+      label: "推荐产品",
+      key: "products",
+      value: "",
+    }]
+    if (val == '医院管理' || val == '科室管理' || val == '医生管理') form.unshift({
+      label: "跟进对象",
+      error: false,
+      errMsg: "",
+      hint: "",
+      type: "radio",
+      value: '',
+      radioList: [{
+        id: '临床',
+        name: '临床'
+      }, {
+        id: '经销商',
+        name: '经销商'
+      }],
+      valueName: "followobj", //绑定的字段名称
+      required: true, //必填
+      direction: "horizontal",
+      interrupt: true,
+      disabled: false
+    })
+
+    if(val == '经销商管理') form.unshift({
+      label: "跟进对象",
+      error: false,
+      errMsg: "",
+      hint: "",
+      type: "radio",
+      value: '',
+      radioList: [{
+        id: '临床',
+        name: '临床'
+      }, {
+        id: '经销商',
+        name: '经销商'
+      }],
+      valueName: "followobj", //绑定的字段名称
+      required: true, //必填
+      direction: "horizontal",
+      interrupt: true,
+      disabled: false
+    },{
+      label: "经销商",
+      error: false,
+      errMsg: "",
+      type: "route",
+      url: "/prsx/select/dealer/index",
+      value: "",
+      placeholder: "经销商",
+      valueName: "sys_taskid",
+      checking: "base",
+      required: false,
+      params: {
+        "content": {
+          "pageNumber": 1,
+          "pageSize": 20,
+          "where": {
+            "condition": ""
+          }
+        },
+        "id": 2025122309161202,
+      },
+      query: "&radio=true",
+    })
+
+    let list = [{
+      label: "目的",
+      key: "target",
+      value: "",
+    }, {
+      label: "过程",
+      key: "content",
+      value: "",
+    }, {
+      label: "结果",
+      key: "results",
+      value: "",
+    }, {
+      label: "下次跟进计划",
+      key: "nextplan",
+      value: "",
+    }]
+    if (btn_type == '编辑') {
+      let data = datas;
+      form = form.map(v => {
+        v.value = data[v.valueName] || "";
+        return v
+      })
+      list = list.map(k => {
+        k.value = data[k.valueName] || "";
+        return k
+      })
+      form.find(v => v.label == '跟进对象').value = type_select
+    } else {
+      if (val == '医院管理' || val == '科室管理' || val == '医生管理') {
+        form.find(v => v.label == '跟进对象').value = '临床'
+        form.find(v => v.label == '跟进对象').disabled = true
+      }else if(val == '经销商'){
+        form.find(v => v.label == '跟进对象').value = '经销商'
+        form.find(v => v.label == '跟进对象').disabled = true
+      }
+    }
+
+
+    this.setData({
+      form,
+      list
+    })
+  },
+  /* 表单必填项是否完成 */
+  onConfirm({
+    detail
+  }) {
+    this.setData({
+      disabled: detail
+    })
+  },
+  // 是否显示全部
+  onChange({
+    detail
+  }) {
+    this.setData({
+      showAll: detail
+    })
+  },
+
+  changeState({
+    detail
+  }) {
+    this.setData({
+      loading: detail
+    })
+  },
+  onInput(e) {
+    const {
+      index
+    } = e.target.dataset;
+    this.data.list[index].value = e.detail.value;
+    this.setData({
+      list: this.data.list
+    })
+  },
+  onVoiceInput(e) {
+    let {
+      index
+    } = e.target.dataset;
+    this.setData({
+      [`list[${index}].value`]: e.detail
+    })
+  },
+  /* 绑定媒体 */
+  insertImgEdit({
+    detail
+  }) {
+    this.handleFileLink(detail)
+  },
+  handleFileLink(attachmentids, ownertable = "temporary", ownerid = 1, data) {
+    _Http.basic({
+      "classname": "system.attachment.Attachment",
+      "method": "createFileLink",
+      "content": {
+        ownertable,
+        ownerid,
+        usetype: 'default',
+        attachmentids
+      }
+    }).then(res => {
+      console.log('跟进记录绑定附件', res)
+      if (res.code != '1') return wx.showToast({
+        title: res.msg,
+        icon: "none"
+      })
+      if (ownertable == 'temporary') {
+        this.selectComponent("#Yl_files").handleFiles(res.data)
+      } else {
+        if (res.data.length) data.attinfos = res.data;
         _Http.basic({
-            "id": 20220930121601,
-            content
-        }).then(res => {
-            console.log("保存跟进内容", res)
-            this.setData({
-                loading: false
-            })
-            wx.showToast({
-                title: getApp().globalData.Language.getMapText(res.code != 1 ? res.msg : content.sys_datafollowupid == 0 ? '保存成功' : '修改成功'),
-                icon: "none",
-                mask: res.code != 1
-            });
-            if (res.msg != '成功') return;
-            let attachmentids = this.selectComponent("#Yl_files").getFiles().attachmentids;
-            if (attachmentids.length) return this.handleFileLink(attachmentids, 'sys_datafollowup', res.data.sys_datafollowupid, res.data);
-            this.changeItem(res.data)
-            setTimeout(() => {
-                wx.navigateBack()
-            }, 500)
-            getCurrentPages().find(v => v.route == 'prsx/hospital/detail').getDetail();
+          "classname": "system.attachment.Attachment",
+          "method": "createFileLink",
+          "content": {
+            ownertable: this.data.ownertable,
+            ownerid: this.data.ownerid,
+            usetype: 'default',
+            attachmentids
+          }
         })
-    },
-    onUnload() {
-        if (this.data.content.sys_datafollowupid == 0) this.selectComponent("#Yl_files").deleteAll()
+        this.changeItem(data)
+        setTimeout(() => {
+          wx.navigateBack()
+        }, 500)
+      }
+    })
+  },
+  changeItem(data) {
+    this.setData({
+      loading: false
+    })
+    let page = getCurrentPages()[getCurrentPages().length - 2],
+      isDetail = page.__route__ == 'prsx/trace/detail/index';
+    if (isDetail) {
+      page.getDetail();
+      page = getCurrentPages()[getCurrentPages().length - 3];
+    }
+    let model = page.selectComponent("#Trace");
+    if (this.data.content.sys_datafollowupid == 0) {
+      if (page) {
+        if (model) model.getList(0, true)
+      }
+    } else {
+      let list = model.data.list,
+        index = list.findIndex(v => v.sys_datafollowupid == data.sys_datafollowupid);
+      if (index != -1) list[index] = data;
+      model.setData({
+        list
+      })
+
     }
+  },
+  submit() {
+    this.setData({
+      loading: true
+    })
+    let content = Object.assign(this.data.content, this.selectComponent("#Form").submit())
+    content.content = this.data.list[0].value;
+    content.resource = this.data.resource || ''
+    _Http.basic({
+      "id": 20220930121601,
+      content
+    }).then(res => {
+      console.log("保存跟进内容", res)
+      this.setData({
+        loading: false
+      })
+      wx.showToast({
+        title: getApp().globalData.Language.getMapText(res.code != 1 ? res.msg : content.sys_datafollowupid == 0 ? '保存成功' : '修改成功'),
+        icon: "none",
+        mask: res.code != 1
+      });
+      if (res.msg != '成功') return;
+      let attachmentids = this.selectComponent("#Yl_files").getFiles().attachmentids;
+      if (attachmentids.length) return this.handleFileLink(attachmentids, 'sys_datafollowup', res.data.sys_datafollowupid, res.data);
+      this.changeItem(res.data)
+      setTimeout(() => {
+        wx.navigateBack()
+      }, 500)
+      getCurrentPages().find(v => v.route == 'prsx/hospital/detail').getDetail();
+    })
+  },
+  onUnload() {
+    if (this.data.content.sys_datafollowupid == 0) this.selectComponent("#Yl_files").deleteAll()
+  }
 })

+ 11 - 4
prsx/trace/add/index.wxml

@@ -1,11 +1,17 @@
-<Yl_field id='Form' form='{{form}}' bind:onConfirm='onConfirm' />
-<view class="inputs" wx:for="{{list}}" wx:key="key">
+<!-- <Yl_Headline title='跟进记录' type='switch' switchLabel='仅显示必填信息' switch='{{showAll}}' bind:callBack='onChange' />
+<Yl_field wx:if="{{special}}" id='Form' form='{{form}}' showAll='{{!showAll}}' bind:onConfirm='onConfirm' />
+
+<view style="height: 20rpx;" /> -->
+<view>
+  <view class="inputs" wx:for="{{list}}" wx:key="key" >
     <view class="label">
         {{language[item.label]||item.label}}
         <Yl_VoiceInput class="Yl_VoiceInput" data-index="{{index}}" bindcallback="onVoiceInput" />
     </view>
-    <textarea value="{{item.value}}" placeholder="{{language['请输入']||'请输入'}}..." auto-height maxlength='-1' data-index="{{index}}" bindinput='onInput' />
+    <textarea  value="{{item.value}}" placeholder="{{language['请输入']||'请输入'}}..." auto-height maxlength='-1' data-index="{{index}}" bindinput='onInput' />
+  </view>
 </view>
+
 <view class="box">
     <view class="content">
         <view class="upload">
@@ -26,5 +32,6 @@
 </view>
 <view style="height: 130rpx;" />
 <view class="footer">
-    <van-button custom-class='but' disabled='{{list[0].value.length==0}}' loading='{{loading}}' bindclick="submit">{{language['确定']||'确定'}}</van-button>
+    <van-button wx:if="{{special}}" custom-class='but' disabled='{{disabled || loading}}' loading='{{loading}}' bindclick="submit">{{language['确定']||'确定'}}</van-button>
+    <van-button wx:else="" custom-class='but' disabled='{{list[0].value.length==0 || loading}}' loading='{{loading}}' bindclick="submit">{{language['确定']||'确定'}}</van-button>
 </view>

+ 4 - 4
utils/Http.js

@@ -3,16 +3,16 @@ class HTTP {
         this.ENV = wx.getAccountInfoSync().miniProgram.envVersion;
         this.urls = [{
             name: "生产环境",
-            url: "http://111.198.58.134:9000"
+            url: "https://www.3hmeditech.com:9000"
         }, {
             name: "开发环境",
             url: "http://61.164.207.46:8100"
         }]
         if (this.ENV === 'release') { // 正式版
-            this.baseUrl = "http://111.198.58.134:9000";
+            this.baseUrl = "https://www.3hmeditech.com:9000";
         } else {
-            // this.baseUrl = "http://61.164.207.46:8100";
-            this.baseUrl = "http://111.198.58.134:9000";
+            this.baseUrl = "http://61.164.207.46:8100";
+            // this.baseUrl = "https://www.3hmeditech.com:9000";
         }
 
         this.init = (content, init = false) => {

+ 40 - 1
utils/work/apps.js

@@ -23,7 +23,8 @@ function getapps() {
     icon: "work-shujutongji"
   }];
   let app = [...getApp().globalData.queryPer.query(wx.getStorageSync('userauth'), ['通用'], ['通用', '工作汇报']),
-      ...getApp().globalData.queryPer.query(wx.getStorageSync('userauth'), ['CRM'], ['业务管理', '数据统计'])
+      ...getApp().globalData.queryPer.query(wx.getStorageSync('userauth'), ['CRM'], ['业务管理', '数据统计']),
+      ...getApp().globalData.queryPer.query(wx.getStorageSync('userauth'), ['行事历'], ['行事历'])
     ],
     list = [];
   app.forEach((v, i) => {
@@ -51,6 +52,11 @@ function getapps() {
 //CRM
 function getcrm() {
   const paths = [{
+    name: "行事历",
+    path: "/prsx/calendar/index",
+    icon: "work-shichanghuodong",
+    objectname: ""
+  },{
     name: "市场活动",
     path: "/prsx/activity/index",
     icon: "work-shichanghuodong",
@@ -125,6 +131,38 @@ function getcrm() {
   });
   return dye(list.sort((a, b) => a.index - b.index))
 };
+//行事历
+function getxsl() {
+  const paths = [{
+    name: "行事历",
+    path: "/prsx/calendar/index",
+    icon: "work-shichanghuodong",
+    objectname: ""
+  }];
+  let xsl = getApp().globalData.queryPer.query(wx.getStorageSync('userauth'), ['行事历'], ['行事历']),
+    list = [];
+  xsl.forEach(v => {
+    v.apps.forEach(s => {
+      authList[s.name] = {
+        options: s.meta.auth.map(a => a.option),
+        optionnames: s.meta.auth.map(a => a.optionname),
+        istask: s.istask == 1,
+        isdatafollowup: s.isdatafollowup == 1,
+        isdatatag: s.isdatatag == 1,
+        isdatateam: s.isdatateam == 1,
+      }
+      if (authList[s.name].options.some(s => s == "read")) {
+        let i = paths.findIndex(k => k.name == s.meta.title);
+        if (i != -1) {
+          paths[i].index = i;
+          paths[i].appName = s.name;
+          list.push(paths[i])
+        }
+      }
+    })
+  });
+  return dye(list.sort((a, b) => a.index - b.index))
+};
 //染色
 function dye(list) {
   let colorList = [{
@@ -189,5 +227,6 @@ function dye(list) {
 module.exports = {
   getapps,
   getcrm,
+  getxsl,
   authList
 };

+ 5 - 0
utils/work/work.js

@@ -7,6 +7,11 @@ async function initWorkbench(that) {
         appid: "wx197f219a82a89d7b",
         list: apps.getapps()
     }, {
+      label: "行事历",
+      appid: "wx197f219a82a89d7b",
+      icon: "work-CRM",
+      list: apps.getxsl()
+  },{
         label: "CRM",
         appid: "wx197f219a82a89d7b",
         icon: "work-CRM",