Browse Source

feat:新增小程序回访记录

lsw 10 months ago
parent
commit
e3555b6d51
34 changed files with 846 additions and 261 deletions
  1. 2 2
      admin-ui/package.json
  2. 7 6
      admin-ui/src/plugins/vue-layer/lib/vue-layer.umd.min.js
  3. 87 0
      admin-ui/src/views/work/follow/record/edit.vue
  4. 110 0
      admin-ui/src/views/work/follow/record/index.vue
  5. 3 8
      admin-ui/src/views/work/follow/template/edit.vue
  6. 4 8
      admin-ui/src/views/work/follow/template/index.vue
  7. 1 1
      app/App.vue
  8. 1 2
      app/common/common.scss
  9. 0 120
      app/components/images/images.vue
  10. 32 10
      app/pages.json
  11. 41 49
      app/pages/follow/detail.vue
  12. 112 0
      app/pages/follow/index.vue
  13. 1 1
      app/pages/other/agreement.vue
  14. 26 17
      app/pages/user/index.vue
  15. 19 0
      app/pages/user/info.vue
  16. 4 11
      app/pages/user/login.vue
  17. BIN
      app/static/favicon.png
  18. 17 11
      ruoyi-admin/src/main/java/com/ruoyi/web/work/api/Api_FollowController.java
  19. 17 4
      ruoyi-admin/src/main/java/com/ruoyi/web/work/api/Api_UserController.java
  20. 9 0
      ruoyi-admin/src/main/java/com/ruoyi/web/work/api/config/BaseController.java
  21. 0 1
      ruoyi-admin/src/main/java/com/ruoyi/web/work/api/config/InterceptorConfig.java
  22. 15 0
      ruoyi-admin/src/main/java/com/ruoyi/web/work/api/util/AppUtil.java
  23. 62 0
      ruoyi-admin/src/main/java/com/ruoyi/web/work/controller/FollowRecordController.java
  24. 59 0
      ruoyi-admin/src/main/java/com/ruoyi/web/work/domain/FollowRecord.java
  25. 8 4
      ruoyi-admin/src/main/java/com/ruoyi/web/work/domain/FollowTemplate.java
  26. 22 0
      ruoyi-admin/src/main/java/com/ruoyi/web/work/domain/dto/FollowRecordDto.java
  27. 5 0
      ruoyi-admin/src/main/java/com/ruoyi/web/work/domain/dto/UserEditDto.java
  28. 13 0
      ruoyi-admin/src/main/java/com/ruoyi/web/work/mapper/FollowRecordMapper.java
  29. 32 0
      ruoyi-admin/src/main/java/com/ruoyi/web/work/service/IFollowRecordService.java
  30. 23 0
      ruoyi-admin/src/main/java/com/ruoyi/web/work/service/IUserService.java
  31. 56 0
      ruoyi-admin/src/main/java/com/ruoyi/web/work/service/impl/FollowRecordServiceImpl.java
  32. 30 0
      ruoyi-admin/src/main/java/com/ruoyi/web/work/service/impl/UserServiceImpl.java
  33. 17 0
      ruoyi-admin/src/main/resources/mapper/work/FollowRecordMapper.xml
  34. 11 6
      ruoyi-admin/src/main/resources/mapper/work/FollowTemplateMapper.xml

+ 2 - 2
admin-ui/package.json

@@ -5,8 +5,8 @@
   "author": "若依",
   "license": "MIT",
   "scripts": {
-    "dev": "vue-cli-service serve",
-    "build:prod": "vue-cli-service build",
+    "dev": "SET NODE_OPTIONS=--openssl-legacy-provider && vue-cli-service serve",
+    "build:prod": "SET NODE_OPTIONS=--openssl-legacy-provider && vue-cli-service build",
     "build:stage": "vue-cli-service build --mode staging",
     "preview": "node build/index.js --preview",
     "lint": "eslint --ext .js,.vue src"

+ 7 - 6
admin-ui/src/plugins/vue-layer/lib/vue-layer.umd.min.js

@@ -5767,12 +5767,13 @@ var iframevue_type_template_id_1c9ad754_staticRenderFns = []
                 instance.vm = instance.$mount();
                 document.getElementById(_this2.id).appendChild(instance.vm.$el);
                 _this2.options.layer.instancesVue[_this2.options.id].iframe = instance.vm;
-                var element = document.querySelector('.vl-notify.vl-notify-main');
-                var width = element.offsetWidth;
-                var height = element.offsetHeight;
-                element.style.left = 'calc(50% - ('+width+'px/ 2))';
-                element.style.top = 'calc(50% - ('+height+'px/ 2))';
-                element.classList.add('animated', 'fadeInLeft');
+               var elements = document.querySelectorAll('.vl-notify.vl-notify-main');
+               elements.forEach(function(element) {
+                   var width = element.offsetWidth;
+                   var height = element.offsetHeight;
+                   element.style.left = 'calc(50% - (' + width + 'px / 2))';
+                   element.style.top = 'calc(50% - (' + height + 'px / 2))';
+               });
               case 10:
               case "end":
                 return _context2.stop();

+ 87 - 0
admin-ui/src/views/work/follow/record/edit.vue

@@ -0,0 +1,87 @@
+<template>
+  <div class="cmain">
+      <el-form ref="form" :model="form" :rules="rules" label-width="100px">
+        <el-form-item label="问题模板id" prop="templateId">
+          <el-input v-model="form.templateId" placeholder="请输入问题模板id" clearable/>
+        </el-form-item>
+        <el-form-item label="患者id" prop="userId">
+          <el-input v-model="form.userId" placeholder="请输入患者id" clearable/>
+        </el-form-item>
+        <el-form-item label="状态" prop="state">
+          <el-input v-model="form.state" placeholder="请输入状态" clearable/>
+        </el-form-item>
+        <el-form-item label="医生id" prop="doctorId">
+          <el-input v-model="form.doctorId" placeholder="请输入医生id" clearable/>
+        </el-form-item>
+        <el-form-item label="创建人" prop="createBy">
+          <el-input v-model="form.createBy" placeholder="请输入创建人" clearable/>
+        </el-form-item>
+        <el-form-item label="创建时间" prop="createTime">
+          <el-date-picker clearable
+            v-model="form.createTime"
+            type="date"
+            value-format="yyyy-MM-dd"
+            placeholder="请选择创建时间">
+          </el-date-picker>
+        </el-form-item>
+        <el-form-item label="更新人" prop="updateBy">
+          <el-input v-model="form.updateBy" placeholder="请输入更新人" clearable/>
+        </el-form-item>
+        <el-form-item label="更新时间" prop="updateTime">
+          <el-date-picker clearable
+            v-model="form.updateTime"
+            type="date"
+            value-format="yyyy-MM-dd"
+            placeholder="请选择更新时间">
+          </el-date-picker>
+        </el-form-item>
+        <el-form-item label="部门ID" prop="deptId">
+          <el-input v-model="form.deptId" placeholder="请输入部门ID" clearable/>
+        </el-form-item>
+      </el-form>
+    <div class="mfooter">
+      <el-button type="primary" @click="submitForm">确 定</el-button>
+      <el-button @click="$layer.close(layerid)">取 消</el-button>
+    </div>
+  </div>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      form: {},
+      rules: {
+      }
+    };
+  },
+  mounted() {
+    if (this.param.id) {
+      this.ajax({ url: '/work/record/detail/' + this.param.id }).then(response => {
+        this.form = response.data;
+      });
+    }
+  },
+  methods: {
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.id) {
+              this.ajax({method: 'post',url: '/work/record/edit', data: this.form }).then(response => {
+                  this.$modal.msgSuccess("修改成功");
+                  this.$layer.close(this.layerid);
+                  this.$parent.getList();
+              });
+          } else {
+              this.ajax({method: 'post',url: '/work/record/add', data: this.form }).then(response => {
+                  this.$modal.msgSuccess("新增成功");
+                  this.$layer.close(this.layerid);
+                  this.$parent.getList();
+               });
+          }
+        }
+      });
+    }
+  }
+};
+</script>

+ 110 - 0
admin-ui/src/views/work/follow/record/index.vue

@@ -0,0 +1,110 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryForm" :inline="true" @submit.native.prevent>
+      <el-form-item label="问题模板id" prop="templateId">
+        <el-input v-model="queryParams.templateId" placeholder="请输入问题模板id"  @keyup.enter.native="handleQuery" clearable class="inp"/>
+      </el-form-item>
+      <el-form-item label="患者id" prop="userId">
+        <el-input v-model="queryParams.userId" placeholder="请输入患者id"  @keyup.enter.native="handleQuery" clearable class="inp"/>
+      </el-form-item>
+      <el-form-item label="状态" prop="state">
+        <el-input v-model="queryParams.state" placeholder="请输入状态"  @keyup.enter.native="handleQuery" clearable class="inp"/>
+      </el-form-item>
+      <el-form-item label="医生id" prop="doctorId">
+        <el-input v-model="queryParams.doctorId" placeholder="请输入医生id"  @keyup.enter.native="handleQuery" clearable class="inp"/>
+      </el-form-item>
+      <el-form-item label="部门ID" prop="deptId">
+        <el-input v-model="queryParams.deptId" placeholder="请输入部门ID"  @keyup.enter.native="handleQuery" clearable class="inp"/>
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>
+        <el-button icon="el-icon-refresh" @click="resetQuery">重置</el-button>
+      </el-form-item>
+    </el-form>
+    <el-row :gutter="10" class="mb8">
+        <el-button type="primary" icon="el-icon-plus" :disabled="ids.length > 0" @click="op('add')" v-hasPermi="['work:record:add']">新增</el-button>
+        <el-button type="success" icon="el-icon-edit" :disabled="ids.length != 1" @click="op('edit',ids)" v-hasPermi="['work:record:edit']">修改</el-button>
+        <el-button type="danger" icon="el-icon-delete" :disabled="ids.length == 0" @click="del" v-hasPermi="['work:record:remove']">删除{{ids.length>0?'('+ids.length+')':''}}</el-button>
+    </el-row>
+
+    <el-table :data="response.rows" border @selection-change="selects" height="calc(100vh - 270px)">
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="寻访记录id" align="center" prop="id" />
+      <el-table-column label="问题模板id" align="center" prop="templateId" />
+      <el-table-column label="患者id" align="center" prop="userId" />
+      <el-table-column label="状态" align="center" prop="state" />
+      <el-table-column label="医生id" align="center" prop="doctorId" />
+      <el-table-column label="部门ID" align="center" prop="deptId" />
+      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+        <template slot-scope="scope">
+          <el-button size="mini" type="text" icon="el-icon-edit" @click="op('edit',scope.row)" v-hasPermi="['work:record:edit']">修改</el-button>
+          <el-button size="mini" type="text" icon="el-icon-delete" @click="del(scope.row)" v-hasPermi="['work:record:remove']">删除</el-button>
+        </template>
+      </el-table-column>
+      <template slot="empty">
+          <el-empty></el-empty>
+      </template>
+    </el-table>
+    <pagination v-if="response.total>0" :total="response.total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList"/>
+  </div>
+</template>
+
+<script>
+import edit from './edit'
+export default {
+  name: "Record",
+  data() {
+    return {
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+                      templateId: null,
+                      userId: null,
+                      state: null,
+                      doctorId: null,
+                      deptId: null,
+                orderByColumn:'id', //排序字段
+                isAsc: 'desc' //排序方式
+      }
+    };
+  },
+  created() {
+    this.getList();
+  },
+  methods: {
+    getList() {
+      this.ajax({ url: '/work/record/list', data: this.queryParams }).then(response => {
+            this.response = response;
+      });
+    },
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    selects(rows) {
+      this.ids = rows.map(item => item.id)
+    },
+    op(tag, row) {
+          if (tag == 'add') {
+            this.iframe({ obj: edit, param: {}, title:'新增',width: '45%', height: '55%'});
+          }
+          if (tag == 'edit') {
+              const id = row.id || this.ids[0];
+              this.iframe({ obj: edit, param: {id: id}, title:'编辑',width: '50%', height: '50%'});
+          }
+    },
+    del(row) {
+        this.$confirm('是否确认删除选中数据?', '警告', { type: 'warning' }).then(() => {
+        this.get({ url: '/work/record/remove/' + (row.id || this.ids) }).then(response => {
+                this.$modal.msgSuccess('删除成功');
+                this.getList();
+            });
+        });
+    }
+  }
+};
+</script>

+ 3 - 8
admin-ui/src/views/work/follow/template/edit.vue

@@ -62,17 +62,12 @@
                 <div class="mts">
                   <input v-if="item.input == '填空'" placeholder="请输入" :disabled="true" />
                   <textarea v-if="item.input == '多行文本'" :disabled="true" placeholder="请输入"></textarea>
-                  <input type="number" v-if="item.input == '电话'" placeholder="请输入" :disabled="true" />
-                  <div v-if="item.input == '附件'"><el-button class="fjian" icon="el-icon-upload">选择文件</el-button></div>
-                  <div class="ops" v-if="item.selects.length <= 4">
+                  <input type="number" v-if="item.input == '数字'" placeholder="请输入" :disabled="true" />
+                  <div class="ops">
                     <div v-for="(op, i) in item.selects" :key="op.name">
                       <div class="op">{{ op.name }}</div>
                     </div>
                   </div>
-                  <div v-else class="mchoice">
-                    <span>点击选择</span>
-                    <i class="el-icon-caret-bottom icon"></i>
-                  </div>
                 </div>
               </div>
               <el-divider>结束</el-divider>
@@ -96,7 +91,7 @@ export default {
     return {
       form: { state: 0, op: [] },
       nulls: ['必填', '非必填'],
-      selects: ['填空', '单选', '多选', '判断', '附件', '多行文本', '电话'],
+      selects: ['填空', '单选', '多选', '判断', '数字', '多行文本'],
       rules: {
         title: [{ required: true, message: '标题不能为空', trigger: 'blur' }],
         op: [{ required: true, message: '内容不能为空', trigger: 'blur' }],

+ 4 - 8
admin-ui/src/views/work/follow/template/index.vue

@@ -1,18 +1,12 @@
 <template>
   <div class="app-container">
     <el-form :model="queryParams" ref="queryForm" :inline="true" @submit.native.prevent>
-      <el-form-item label="关联账号" prop="userId">
-        <el-input v-model="queryParams.userId" placeholder="请输入关联账号" @keyup.enter.native="handleQuery" clearable class="inp" />
-      </el-form-item>
       <el-form-item label="标题" prop="title">
         <el-input v-model="queryParams.title" placeholder="请输入标题" @keyup.enter.native="handleQuery" clearable class="inp" />
       </el-form-item>
       <el-form-item label="状态" prop="state">
         <el-input v-model="queryParams.state" placeholder="请输入状态" @keyup.enter.native="handleQuery" clearable class="inp" />
       </el-form-item>
-      <el-form-item label="部门ID" prop="deptId">
-        <el-input v-model="queryParams.deptId" placeholder="请输入部门ID" @keyup.enter.native="handleQuery" clearable class="inp" />
-      </el-form-item>
       <el-form-item>
         <el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>
         <el-button icon="el-icon-refresh" @click="resetQuery">重置</el-button>
@@ -27,14 +21,16 @@
 
     <el-table :data="response.rows" border @selection-change="selects" height="calc(100vh - 270px)">
       <el-table-column type="selection" width="55" align="center" />
-      <el-table-column label="标题" align="left" prop="title" />
+      <el-table-column label="模板标题" align="left" prop="title" />
       <el-table-column label="状态" align="center" prop="state" width="140">
         <template slot-scope="scope">
           <el-tag type="success" v-if="scope.row.state == 0">启用</el-tag>
           <el-tag type="danger" v-if="scope.row.state == 1">停用</el-tag>
         </template>
       </el-table-column>
-      <el-table-column label="创建时间" align="center" prop="createTime" width="200" />
+      <el-table-column label="创建人" align="center" prop="createBy" width="130" />
+      <el-table-column label="创建时间" align="center" prop="createTime" width="160" />
+      <el-table-column label="所属科室" align="center" prop="deptName" width="130" />
       <el-table-column label="操作" align="center" width="200">
         <template slot-scope="scope">
           <el-button size="mini" type="text" icon="el-icon-edit" @click="op('edit', scope.row)" v-hasPermi="['work:template:edit']">修改</el-button>

+ 1 - 1
app/App.vue

@@ -30,7 +30,7 @@ button::after {
 /**挂载iconfont字体图标*/
 @font-face {
 	font-family: 'iconfont';
-	src: url('https://at.alicdn.com/t/c/font_4620946_fqi31jzmzp7.ttf?t=1721209495536') format('truetype');
+	src: url('https://at.alicdn.com/t/c/font_4620946_zi17cneza5h.ttf?t=1721295443583') format('truetype');
 	/* src: url('~@/static/font/iconfont.ttf') format('truetype'); */
 }
 .icon {

+ 1 - 2
app/common/common.scss

@@ -134,11 +134,10 @@
 			width: 27px;
 			height: 27px;
 			font-size: 25px;
-			box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
 			text-align: center;
 			padding: 7px;
 			border-radius: 50%;
-			margin-right: 13px;
+			margin-right: 5px;
 			line-height: 29px;
 		}
 		.title {

+ 0 - 120
app/components/images/images.vue

@@ -1,120 +0,0 @@
-<template>
-	<view class="imgs">
-		<button class="btn" @click="choose()" v-if="!read">
-			<text class="icon">&#xe658;</text>
-			<text class="text">选择上传</text>
-		</button>
-		<view class="files omit" v-for="(item, index) in value" :key="index" @click="preview(item)">
-			<view class="file omit">{{ index + 1 }}, {{ item.url }}</view>
-			<view class="type">{{ item.type.toLowerCase() }}</view>
-			<view class="look" v-if="read">查看</view>
-			<view class="del" v-else @click.stop="del(item)">删除</view>
-		</view>
-	</view>
-</template>
-
-<script>
-export default {
-	name: 'images',
-	props: {
-		value: {
-			type: Array
-		},
-		read: {
-			type: Boolean,
-			default: false
-		}
-	},
-	data() {
-		return {
-			show: false,
-			ip: this.http.ip,
-			list: this.value,
-			item: {},
-			actions: [{ name: '图片' }, { name: '视频' }]
-		};
-	},
-	methods: {
-		getType(name) {
-			return name.substring(name.lastIndexOf('.') + 1);
-		},
-		choose() {
-			if (this.value.length >= 5) {
-				uni.showModal({ content: '最多只能上传5个附件', showCancel: false });
-				return;
-			}
-			uni.chooseFile({
-				count: 5,
-				success: e => {
-					console.log('asd:' + JSON.stringify(e));
-					e.tempFilePaths.forEach((item, index) => {
-						uni.showLoading({ title: '正在上传...', mask: true });
-						uni.uploadFile({
-							url: this.http.urls.upload,
-							filePath: item,
-							name: 'file',
-							header: { Authorization: this.getUser().token },
-							success: res => {
-								uni.hideLoading();
-								let data = JSON.parse(res.data);
-								if (data.code == 200) {
-									if (this.value.length < 5) {
-										this.value.push({ url: data.fileName, type: data.fileName.substring(data.fileName.lastIndexOf('.') + 1) });
-										this.$forceUpdate();
-										this.$emit('input', this.value);
-									} else {
-										uni.showModal({ content: '最多只能上传5个附件', showCancel: false });
-									}
-								} else {
-									uni.showModal({ content: data.msg, showCancel: false });
-								}
-							},
-							fail: res => {
-								uni.hideLoading();
-								uni.showModal({ content: '图片上传失败', showCancel: false });
-							}
-						});
-					});
-				}
-			});
-		},
-		//预览资源
-		preview(item) {
-			if (item.type.toLowerCase() == 'jpg' || item.type.toLowerCase() == 'png') {
-				uni.previewImage({
-					urls: [this.ip + item.url]
-				});
-			}
-			if (item.type.toLowerCase() == 'mp4') {
-				this.item = item;
-				this.show = true;
-			}
-		},
-		del(item) {
-			this.value.splice(this.value.indexOf(item), 1);
-		}
-	}
-};
-</script>
-
-<style lang="scss" scoped>
-.imgs {
-	margin-top: -15px;
-	.btn {
-		background-color: white;
-		box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0);
-		border-radius: 5px;
-		color: #656363;
-		.icon {
-			padding-right: 5px;
-		}
-		margin-bottom: 10px;
-	}
-}
-.popup_xz {
-	overflow: hidden;
-	._video {
-		width: 100%;
-	}
-}
-</style>

+ 32 - 10
app/pages.json

@@ -36,24 +36,46 @@
 			}
 		},
 		{
-			"path" : "pages/doctor/index",
-			"style" : 
-			{
-				"navigationBarTitleText" : "医生介绍"
+			"path": "pages/doctor/index",
+			"style": {
+				"navigationBarTitleText": "医生介绍"
 			}
 		},
 		{
-			"path" : "pages/follow/detail",
-			"style" : 
-			{
-				"navigationBarTitleText" : "随访详情"
+			"path": "pages/follow/detail",
+			"style": {
+				"navigationBarTitleText": "随访详情"
+			}
+		},
+		{
+			"path": "pages/user/login",
+			"style": {
+				"navigationBarTitleText": "用户登录"
+			}
+		},
+		{
+			"path": "pages/other/agreement",
+			"style": {
+				"navigationBarTitleText": "协议"
+			}
+		},
+		{
+			"path": "pages/user/info",
+			"style": {
+				"navigationBarTitleText": "我的信息"
+			}
+		},
+		{
+			"path": "pages/other/setting",
+			"style": {
+				"navigationBarTitleText": "设置"
 			}
 		},
 		{
-			"path" : "pages/user/login",
+			"path" : "pages/follow/index",
 			"style" : 
 			{
-				"navigationBarTitleText" : "用户登录"
+				"navigationBarTitleText" : "我的回访"
 			}
 		}
 	],

+ 41 - 49
app/pages/follow/detail.vue

@@ -11,12 +11,8 @@
 			</view>
 			<view class="mts">
 				<input v-if="item.input == '填空'" v-model="item.s_value" placeholder="请输入" />
-				<input v-if="item.input == '数字' || item.input == '电话'" type="number" v-model="item.s_value" placeholder="请输入" :disabled="look ? true : false" />
+				<input v-if="item.input == '数字'" type="number" v-model="item.s_value" placeholder="请输入" :disabled="look ? true : false" />
 				<textarea v-if="item.input == '多行文本'" v-model="item.s_value" placeholder="请输入" />
-				<view v-if="item.input == '附件'">
-					<images v-model="item.s_value" :read="look ? true : false"></images>
-					<view class="fjsc" v-if="!look">最多添加5个附件,单个文件不超过20M。</view>
-				</view>
 				<view class="ops" v-if="item.input == '单选' || item.input == '多选' || item.input == '判断'">
 					<view v-for="(op, i) in item.selects" :key="op.name">
 						<view class="op" :class="{ active: op.check }" @click="check(item, op)">{{ op.name }}</view>
@@ -39,18 +35,49 @@ export default {
 	},
 	onLoad(e) {
 		this.http.request({
-			url: '/app/follow/detail/115',
+			url: '/app/follow/detail/' + e.id,
 			success: (res) => {
 				this.item = res.data.data;
 				this.item.op = JSON.parse(this.item.op);
 			}
 		});
 	},
-	methods: {}
+	methods: {
+		//单选或多选
+		check(item, op) {
+			if (this.look) {
+				return;
+			}
+			if (item.input == '单选' || item.input == '判断') {
+				item.selects.forEach((i) => (i.check = false));
+				op.check = true;
+			} else {
+				op.check = !op.check;
+			}
+			this.$forceUpdate();
+		},
+		add() {
+			let rule = [];
+			let obj = {};
+			this.item.op
+				.filter((item) => item.ifnull == '必填')
+				.forEach((item) => {
+					rule.push({ name: item.name, checkType: 'notnull', errorMsg: '第' + (this.item.op.indexOf(item) + 1) + '项,' + item.name + '不能为空' });
+					obj[item.name] = item.s_value;
+				});
+			if (!this.verify.check(obj, rule)) {
+				uni.showModal({ content: this.verify.error, showCancel: false });
+				return;
+			}
+		}
+	}
 };
 </script>
 
 <style lang="scss">
+page {
+	background-color: white;
+}
 .title {
 	text-align: center;
 }
@@ -58,7 +85,7 @@ export default {
 	.mtt {
 		text-align: left;
 		font-size: 16px;
-		padding: 12px 0px 12px 0px;
+		padding: 15px 0px 12px 0px;
 		position: relative;
 		color: $font-c;
 		.ifnull {
@@ -70,17 +97,17 @@ export default {
 		}
 		.dx {
 			font-size: 12px;
-			color: #989898;
+			color: #646464;
 		}
 	}
 	input {
-		background-color: white;
+		background-color: $inp;
 		border-radius: 5px;
 		padding: 12px;
 		font-size: 14px;
 	}
 	textarea {
-		background-color: white;
+		background-color: $inp;
 		border-radius: 5px;
 		width: 93%;
 		padding: 12px;
@@ -91,54 +118,19 @@ export default {
 		margin-top: -5px;
 		overflow: hidden;
 		.op {
-			padding: 8px;
-			background-color: white;
+			padding: 9px;
+			background-color: $inp;
 			margin-top: 10px;
 			font-size: 14px;
 			border-radius: 3px;
 			color: #656363;
 			float: left;
-			margin-right: 7px;
+			margin-right: 10px;
 			&.active {
 				background-color: $main-color;
 				color: white;
 			}
 		}
 	}
-	.choice {
-		background-color: white;
-		margin-top: 5px;
-		padding: 12px;
-		border-radius: 3px;
-		font-size: 14px;
-		color: #656363;
-		overflow: hidden;
-		.omit {
-			width: 80%;
-			float: left;
-		}
-		.gx {
-			font-weight: bold;
-			color: #4581fb;
-			padding-left: 5px;
-		}
-		.icon {
-			float: right;
-			margin-top: 3px;
-		}
-	}
-	.up {
-		font-size: 14px;
-		color: #989898;
-		position: relative;
-		.icon {
-			padding-right: 3px;
-		}
-	}
-	.fjsc {
-		color: #989898;
-		font-size: 14px;
-		margin-top: 5px;
-	}
 }
 </style>

+ 112 - 0
app/pages/follow/index.vue

@@ -0,0 +1,112 @@
+<template>
+	<view>
+		<view class="tab">
+			<u-tabs :list="tab" @click="click"></u-tabs>
+		</view>
+		<view class="list">
+			<view class="item" v-for="(item, index) in list" :key="index" @click="go('/pages/follow/detail?id=' + item.id)">
+				<view class="title omit">
+					<text class="icon" v-if="item.top === 1">&#xe61f;</text>
+					<text>{{ item.templateName }}</text>
+				</view>
+				<view class="desc">
+					<text>{{ item.state == 0 ? '待回访' : '已回访' }}</text>
+					<text>{{ item.createTime }}</text>
+				</view>
+			</view>
+			<view class="loading" v-if="loadMore"><u-loadmore :status="loadMore ? 'loading' : 'nomore'" /></view>
+			<u-empty v-if="!loadMore && list.length == 0"></u-empty>
+		</view>
+	</view>
+</template>
+
+<script>
+export default {
+	data() {
+		return {
+			tab: [
+				{ name: '全部', state: '' },
+				{ name: '待回访', state: 0 },
+				{ name: '已回访', state: 1 }
+			],
+			list: [],
+			param: { pageNum: 1, pageSize: 10 },
+			loadMore: true
+		};
+	},
+	onLoad(e) {
+		this.getData();
+	},
+	methods: {
+		click(e) {
+			this.current = e.index;
+			this.param.type = e.dictValue;
+			this.refresh();
+		},
+		getData() {
+			this.http.request({
+				url: '/app/follow/list',
+				data: this.param,
+				loading: 'false',
+				success: (res) => {
+					this.loadMore = res.data.pages > this.param.pageNum ? true : false;
+					this.list.push(...res.data.rows);
+				}
+			});
+		},
+		go(url) {
+			uni.navigateTo({ url: url });
+		},
+		//刷新数据
+		refresh() {
+			this.loadMore = true;
+			this.param.pageNum = 1;
+			this.list = [];
+			this.getData();
+		}
+	},
+	//下拉刷新
+	onPullDownRefresh() {
+		setTimeout(() => {
+			this.refresh();
+			uni.stopPullDownRefresh();
+		}, 1000);
+	},
+	//上拉加载
+	onReachBottom() {
+		if (this.loadMore) {
+			this.param.pageNum++;
+			this.getData();
+		}
+	}
+};
+</script>
+
+<style lang="scss">
+.list {
+	padding: 10px 12px;
+	.item {
+		border-radius: 5px;
+		padding: 13px 12px 13px 12px;
+		margin-bottom: 10px;
+		overflow: hidden;
+		box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
+		background-color: white;
+		.title {
+			font-size: 15px;
+			font-weight: bold;
+			.icon {
+				color: orangered;
+				padding-right: 3px;
+			}
+		}
+		.desc {
+			font-size: 14px;
+			padding-top: 10px;
+			text {
+				padding-right: 30px;
+			}
+		}
+	}
+}
+</style>

+ 1 - 1
app/pages/other/agreement.vue

@@ -13,7 +13,7 @@ export default {
 	},
 	onLoad(e) {
 		this.http.request({
-			url: '/app/common/agreement/' + e.title,
+			url: '/app/common/introduction/' + e.title,
 			success: (res) => {
 				this.content = res.data.msg.replace(new RegExp('/profile/upload/', 'g'), this.http.ip + '/profile/upload/');
 				uni.setNavigationBarTitle({ title: e.title });

+ 26 - 17
app/pages/user/index.vue

@@ -1,9 +1,9 @@
 <template>
 	<view class="main">
-		<view class="user" @click="go('/pages/user/auth')">
+		<view class="user" @click="go('/pages/user/info')">
 			<image :src="user.avatar ? ip + user.avatar : '../../static/favicon.png'" class="head"></image>
 			<view class="con" v-if="user.id">
-				<view class="nickName">{{ user.type == 0 ? '个人用户' : '企业用户' }}</view>
+				<view class="nickName">{{ user.nickName ? user.nickName : '个人用户' }}</view>
 				<view class="welcome">欢迎使用岑溪人民医院小程序</view>
 			</view>
 			<view class="con" v-else>
@@ -14,10 +14,30 @@
 		</view>
 		<view class="cmd">
 			<view class="s_item" @click="go('/pages/help/my')">
-				<text class="icon ic" style="color: #f44336">&#xe60b;</text>
+				<text class="icon ic" style="color: #03a9f4">&#xe685;</text>
+				<text class="title">我的体检</text>
+				<text class="icon arrow">&#xe62b;</text>
+			</view>
+			<view class="s_item" @click="go('/pages/follow/index')">
+				<text class="icon ic" style="color: #607d8b">&#xe60b;</text>
 				<text class="title">我的回访</text>
 				<text class="icon arrow">&#xe62b;</text>
 			</view>
+			<view class="s_item" @click="go('/pages/help/my')">
+				<text class="icon ic" style="color: #f44336">&#xe7c4;</text>
+				<text class="title">分享应用</text>
+				<text class="icon arrow">&#xe62b;</text>
+			</view>
+			<view class="s_item" @click="go('/pages/help/my')">
+				<text class="icon ic" style="color: #4caf50">&#xe62c;</text>
+				<text class="title">建议反馈</text>
+				<text class="icon arrow">&#xe62b;</text>
+			</view>
+			<view class="s_item" @click="go('/pages/other/setting')">
+				<text class="icon ic" style="color: #9e9e9e">&#xe60f;</text>
+				<text class="title">设置</text>
+				<text class="icon arrow">&#xe62b;</text>
+			</view>
 		</view>
 	</view>
 </template>
@@ -27,19 +47,14 @@ export default {
 		return {
 			ip: this.http.ip,
 			user: {},
-			type: [
-				{ name: '找工作(个人)', value: 0 },
-				{ name: '我要招聘(企业)', value: 1 }
-			],
 			show: false
 		};
 	},
 	onShow() {
-		/* 		this.user = {
-			token: 'eyJhbGciOiJIUzUxMiJ9.eyJsb2dpbl91c2VyX2tleSI6IjdhZGY4MzFmLWE0NjQtNGY5YS04YTY5LWMzM2QyNDU2MzI2ZSJ9.EPHElRmlVoFTfT4OxHNpvIC7bDKc1gKpNiO1u_dBOerYh5JFIuSrSkgp0PtQ0kOhO9iuvU0dttEGbsgofdrcpQ'
+/* 		 		this.user = {
+			token: 'eyJhbGciOiJIUzUxMiJ9.eyJsb2dpbl91c2VyX2tleSI6ImQ3YmZjZjVkLTgxZTgtNGJjMi04MjA1LTE5ZTY3NzdhNzEyMSJ9._pm56LMt6uOsjee2AlZOKdESEEj9axkz62-T74YsHeifH78cn2BouBDSCl-lDPpvOWmJOs1-CZS44oCUeBGlhw'
 		};
 		uni.setStorageSync('user', this.user); */
-
 		if (this.hasLogin()) {
 			this.getUserInfo();
 		} else {
@@ -52,12 +67,6 @@ export default {
 				url: '/app/user/info',
 				success: (res) => {
 					this.user = res.data.data;
-					uni.setStorageSync('money', res.data.data.money || 0);
-					uni.setStorageSync('bankName', res.data.data.bankName);
-					if (res.data.data.type == null) {
-						uni.navigateTo({ url: '/pages/user/switch' });
-						return;
-					}
 				}
 			});
 		},
@@ -71,7 +80,7 @@ export default {
 	},
 	onShareAppMessage: function (res) {
 		return {
-			title: '爱就业咨询服务平台',
+			title: '岑溪人民医院小程序',
 			path: '/pages/index/index',
 			imageUrl: 'https://chenglantimes.com/prod-api/profile/upload/2024/06/16/blob_20240616055022A009.jpeg',
 			success: (res) => {},

+ 19 - 0
app/pages/user/info.vue

@@ -0,0 +1,19 @@
+<template>
+	<view>
+		
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				
+			};
+		}
+	}
+</script>
+
+<style lang="scss">
+
+</style>

+ 4 - 11
app/pages/user/login.vue

@@ -1,8 +1,6 @@
 <template>
 	<view class="bg">
-		<view class="p">
-			<image src="https://chenglantimes.com/prod-api/profile/upload/2024/06/04/1717472782145.jpg" class="pic" mode="widthFix"></image>
-		</view>
+		<image src="https://axure-file.lanhuapp.com/md5__f93627286149f825890eb821ab5d5abb.png" class="pic" mode="widthFix"></image>
 		<view class="xy">
 			<u-checkbox-group class="checkbox" v-model="item.checked">
 				<u-checkbox size="15" shape="circle" label="我已阅读并同意" labelSize="14" name="true"></u-checkbox>
@@ -74,14 +72,9 @@ export default {
 <style lang="scss">
 .bg {
 	padding: 30px;
-	.p {
-		text-align: center;
-		padding: 45px 15px 15px 15px;
-		.pic {
-			width: 150px;
-			height: 150px;
-			border-radius: 50%;
-		}
+	.pic {
+		width: 100%;
+		border-radius: 5px;
 	}
 }
 </style>

BIN
app/static/favicon.png


+ 17 - 11
ruoyi-admin/src/main/java/com/ruoyi/web/work/api/Api_FollowController.java

@@ -1,15 +1,14 @@
 package com.ruoyi.web.work.api;
 
-import com.ruoyi.common.core.controller.BaseController;
 import com.ruoyi.common.core.domain.AjaxResult;
 import com.ruoyi.common.core.page.TableDataInfo;
-import com.ruoyi.web.work.domain.FollowTemplate;
-import com.ruoyi.web.work.service.IFollowTemplateService;
+import com.ruoyi.web.work.api.config.BaseController;
+import com.ruoyi.web.work.domain.FollowRecord;
+import com.ruoyi.web.work.domain.dto.FollowRecordDto;
+import com.ruoyi.web.work.service.IFollowRecordService;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
 
 import java.util.List;
 
@@ -22,18 +21,25 @@ import java.util.List;
 @RestController
 @RequestMapping("/app/follow")
 public class Api_FollowController extends BaseController {
+
     @Autowired
-    private IFollowTemplateService followTemplateService;
+    private IFollowRecordService followRecordService;
 
     @GetMapping("/list")
-    public TableDataInfo list(FollowTemplate followTemplate) {
+    public TableDataInfo list(FollowRecord followRecord) {
+        followRecord.setPatientId(getUser().getId());
         startPage();
-        List<FollowTemplate> list = followTemplateService.selectList(followTemplate);
+        List<FollowRecord> list = followRecordService.selectList(followRecord);
         return getDataTable(list);
     }
 
+    @PostMapping("/push")
+    public AjaxResult push(@Validated @RequestBody FollowRecordDto dto) {
+        return followRecordService.push(dto);
+    }
+
     @GetMapping(value = "/detail/{id}")
     public AjaxResult detail(@PathVariable("id") Long id) {
-        return AjaxResult.success(followTemplateService.getById(id));
+        return followRecordService.detail(id);
     }
 }

+ 17 - 4
ruoyi-admin/src/main/java/com/ruoyi/web/work/api/Api_UserController.java

@@ -3,13 +3,11 @@ package com.ruoyi.web.work.api;
 import com.ruoyi.common.core.domain.AjaxResult;
 import com.ruoyi.web.work.api.config.BaseController;
 import com.ruoyi.web.work.domain.dto.LoginDto;
+import com.ruoyi.web.work.domain.dto.UserEditDto;
 import com.ruoyi.web.work.service.IUserService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.validation.annotation.Validated;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.bind.annotation.*;
 
 import java.rmi.ServerException;
 
@@ -25,5 +23,20 @@ public class Api_UserController extends BaseController {
         return userService.login(dto);
     }
 
+    @GetMapping("/info")
+    public AjaxResult info() {
+        return userService.info();
+    }
+
+    @PostMapping("/edit")
+    public AjaxResult edit(@Validated @RequestBody UserEditDto dto) {
+        return userService.edit(dto);
+    }
+
+    @GetMapping("/exit")
+    public AjaxResult exit() {
+        return userService.exit();
+    }
+
 }
 

+ 9 - 0
ruoyi-admin/src/main/java/com/ruoyi/web/work/api/config/BaseController.java

@@ -11,9 +11,13 @@ import com.ruoyi.common.utils.DateUtils;
 import com.ruoyi.common.utils.PageUtils;
 import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.common.utils.sql.SqlUtil;
+import com.ruoyi.web.work.domain.User;
 import org.springframework.web.bind.WebDataBinder;
 import org.springframework.web.bind.annotation.InitBinder;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
 
+import javax.servlet.http.HttpServletRequest;
 import java.beans.PropertyEditorSupport;
 import java.util.Date;
 import java.util.List;
@@ -132,4 +136,9 @@ public class BaseController {
     }
 
 
+    public User getUser() {
+        ServletRequestAttributes sra = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
+        HttpServletRequest request = sra.getRequest();
+        return (User) request.getAttribute("user");
+    }
 }

+ 0 - 1
ruoyi-admin/src/main/java/com/ruoyi/web/work/api/config/InterceptorConfig.java

@@ -23,7 +23,6 @@ public class InterceptorConfig implements WebMvcConfigurer {
         registration.excludePathPatterns("/app/user/login"); //排除
         registration.excludePathPatterns("/app/home/**"); //排除
         registration.excludePathPatterns("/app/knowledge/**"); //排除
-        registration.excludePathPatterns("/app/follow/**"); //排除
         registration.excludePathPatterns("/app/common/type/*"); //排除
         registration.excludePathPatterns("/app/common/introduction/*"); //排除
     }

+ 15 - 0
ruoyi-admin/src/main/java/com/ruoyi/web/work/api/util/AppUtil.java

@@ -0,0 +1,15 @@
+package com.ruoyi.web.work.api.util;
+
+import com.ruoyi.web.work.domain.User;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+
+import javax.servlet.http.HttpServletRequest;
+
+public class AppUtil {
+    public static User getUser() {
+        ServletRequestAttributes sra = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
+        HttpServletRequest request = sra.getRequest();
+        return (User) request.getAttribute("user");
+    }
+}

+ 62 - 0
ruoyi-admin/src/main/java/com/ruoyi/web/work/controller/FollowRecordController.java

@@ -0,0 +1,62 @@
+package com.ruoyi.web.work.controller;
+
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.page.TableDataInfo;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.web.work.domain.FollowRecord;
+import com.ruoyi.web.work.service.IFollowRecordService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * 回访记录
+ * @author lsw
+ * @date 2024-07-18
+ */
+@RestController
+@RequestMapping("/work/record")
+public class FollowRecordController extends BaseController {
+    @Autowired
+    private IFollowRecordService followRecordService;
+
+    @PreAuthorize("@ss.hasPermi('work:record:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(FollowRecord followRecord){
+        startPage();
+        List<FollowRecord> list = followRecordService.selectList(followRecord);
+        return getDataTable(list);
+    }
+
+    @PreAuthorize("@ss.hasPermi('work:record:query')")
+    @GetMapping(value = "/detail/{id}")
+    public AjaxResult detail(@PathVariable("id") Long id){
+        return AjaxResult.success(followRecordService.getById(id));
+    }
+
+    @PreAuthorize("@ss.hasPermi('work:record:add')")
+    @Log(title = "回访记录", businessType = BusinessType.INSERT)
+    @PostMapping("/add")
+    public AjaxResult add(@RequestBody FollowRecord followRecord){
+        return toAjax(followRecordService.save(followRecord));
+    }
+
+    @PreAuthorize("@ss.hasPermi('work:record:edit')")
+    @Log(title = "回访记录", businessType = BusinessType.UPDATE)
+    @PostMapping("/edit")
+    public AjaxResult edit(@RequestBody FollowRecord followRecord){
+        return toAjax(followRecordService.updateById(followRecord));
+    }
+
+    @PreAuthorize("@ss.hasPermi('work:record:remove')")
+    @Log(title = "回访记录", businessType = BusinessType.DELETE)
+    @GetMapping("/remove/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids){
+        return toAjax(followRecordService.removeByIds(Arrays.asList(ids)));
+    }
+}

+ 59 - 0
ruoyi-admin/src/main/java/com/ruoyi/web/work/domain/FollowRecord.java

@@ -0,0 +1,59 @@
+package com.ruoyi.web.work.domain;
+
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+import java.util.Date;
+/**
+ * @author lsw
+ * @date 2024-07-18
+ */
+@Data
+@TableName(value = "tb_follow_record")
+@Accessors(chain = true)
+public class FollowRecord{
+    private static final long serialVersionUID = 1L;
+
+    private Long id;
+
+    @ApiModelProperty(value = "模板名称")
+    private String templateName;
+
+    @ApiModelProperty(value = "回访内容")
+    private String op;
+
+    @ApiModelProperty(value = "状态:0=未回访,1=已回访")
+    private Integer state;
+
+    @TableField(fill = FieldFill.INSERT)
+    private String createBy;
+
+    @TableField(fill = FieldFill.INSERT)
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date createTime;
+
+    @TableField(fill = FieldFill.UPDATE)
+    private String updateBy;
+
+    @TableField(fill = FieldFill.UPDATE)
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date updateTime;
+
+    @ApiModelProperty(value = "患者id")
+    private Long patientId;
+
+    @ApiModelProperty(value = "患者id")
+    @TableField(fill = FieldFill.INSERT)
+    private Long userId;
+
+    @ApiModelProperty(value = "部门ID")
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
+
+
+}

+ 8 - 4
ruoyi-admin/src/main/java/com/ruoyi/web/work/domain/FollowTemplate.java

@@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.annotation.FieldFill;
 import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableName;
 import com.fasterxml.jackson.annotation.JsonFormat;
+import com.ruoyi.web.work.domain.base.BaseData;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 import lombok.experimental.Accessors;
@@ -16,14 +17,11 @@ import java.util.Date;
 @Data
 @TableName(value = "tb_follow_template")
 @Accessors(chain = true)
-public class FollowTemplate{
+public class FollowTemplate extends BaseData {
     private static final long serialVersionUID = 1L;
 
     private Long id;
 
-    @ApiModelProperty(value = "关联账号")
-    private Long userId;
-
     @ApiModelProperty(value = "标题")
     private String title;
 
@@ -47,7 +45,13 @@ public class FollowTemplate{
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private Date updateTime;
 
+
+    @ApiModelProperty(value = "关联账号")
+    @TableField(fill = FieldFill.INSERT)
+    private Long userId;
+
     @ApiModelProperty(value = "部门ID")
+    @TableField(fill = FieldFill.INSERT)
     private Long deptId;
 
 

+ 22 - 0
ruoyi-admin/src/main/java/com/ruoyi/web/work/domain/dto/FollowRecordDto.java

@@ -0,0 +1,22 @@
+package com.ruoyi.web.work.domain.dto;
+
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+
+/**
+ * @author lsw
+ * @date 2024-07-18
+ */
+@Data
+@Accessors(chain = true)
+public class FollowRecordDto {
+
+    @NotNull(message = "参数错误")
+    private Long id;
+
+    @NotBlank(message = "回访内容不能为空")
+    private String op;
+}

+ 5 - 0
ruoyi-admin/src/main/java/com/ruoyi/web/work/domain/dto/UserEditDto.java

@@ -0,0 +1,5 @@
+package com.ruoyi.web.work.domain.dto;
+
+public class UserEditDto {
+
+}

+ 13 - 0
ruoyi-admin/src/main/java/com/ruoyi/web/work/mapper/FollowRecordMapper.java

@@ -0,0 +1,13 @@
+package com.ruoyi.web.work.mapper;
+
+import java.util.List;
+import com.ruoyi.web.work.domain.FollowRecord;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+ * @author lsw
+ * @date 2024-07-18
+ */
+public interface FollowRecordMapper extends BaseMapper<FollowRecord> {
+    List<FollowRecord> selectList(FollowRecord followRecord);
+}

+ 32 - 0
ruoyi-admin/src/main/java/com/ruoyi/web/work/service/IFollowRecordService.java

@@ -0,0 +1,32 @@
+package com.ruoyi.web.work.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.web.work.domain.FollowRecord;
+import com.ruoyi.web.work.domain.dto.FollowRecordDto;
+
+import java.util.List;
+
+/**
+ * @author lsw
+ * @date 2024-07-18
+ */
+public interface IFollowRecordService extends IService<FollowRecord> {
+    List<FollowRecord> selectList(FollowRecord followRecord);
+
+    /**
+     * 查看详情
+     *
+     * @param id
+     * @return
+     */
+    AjaxResult detail(Long id);
+
+    /**
+     * 提交回访记录
+     *
+     * @param dto
+     * @return
+     */
+    AjaxResult push(FollowRecordDto dto);
+}

+ 23 - 0
ruoyi-admin/src/main/java/com/ruoyi/web/work/service/IUserService.java

@@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.extension.service.IService;
 import com.ruoyi.common.core.domain.AjaxResult;
 import com.ruoyi.web.work.domain.User;
 import com.ruoyi.web.work.domain.dto.LoginDto;
+import com.ruoyi.web.work.domain.dto.UserEditDto;
 
 import java.rmi.ServerException;
 import java.util.List;
@@ -22,4 +23,26 @@ public interface IUserService extends IService<User>{
      * @return
      */
     AjaxResult login(LoginDto dto) throws ServerException;
+
+
+    /**
+     * 编辑用户信息
+     *
+     * @param dto
+     * @return
+     */
+    AjaxResult edit(UserEditDto dto);
+
+    /**
+     * 退出登陆
+     *
+     * @return
+     */
+    AjaxResult exit();
+
+    /**
+     * 用户详情
+     * @return
+     */
+    AjaxResult info();
 }

+ 56 - 0
ruoyi-admin/src/main/java/com/ruoyi/web/work/service/impl/FollowRecordServiceImpl.java

@@ -0,0 +1,56 @@
+package com.ruoyi.web.work.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.exception.ServiceException;
+import com.ruoyi.web.work.api.util.AppUtil;
+import com.ruoyi.web.work.domain.FollowRecord;
+import com.ruoyi.web.work.domain.dto.FollowRecordDto;
+import com.ruoyi.web.work.mapper.FollowRecordMapper;
+import com.ruoyi.web.work.mapper.FollowTemplateMapper;
+import com.ruoyi.web.work.service.IFollowRecordService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+/**
+ * @author lsw
+ * @date 2024-07-18
+ */
+@Service
+public class FollowRecordServiceImpl extends ServiceImpl<FollowRecordMapper, FollowRecord> implements IFollowRecordService {
+    @Autowired
+    private FollowRecordMapper followRecordMapper;
+
+    @Autowired
+    private FollowTemplateMapper followTemplateMapper;
+
+    @Override
+    public List<FollowRecord> selectList(FollowRecord followRecord) {
+        return followRecordMapper.selectList(followRecord);
+    }
+
+    @Override
+    public AjaxResult detail(Long id) {
+        FollowRecord followRecord = getById(id);
+        if (followRecord == null || !followRecord.getPatientId().equals(AppUtil.getUser().getId())) {
+            return AjaxResult.error("回访不存在或非法操作");
+        }
+        return AjaxResult.success(followRecord);
+    }
+
+    @Override
+    public AjaxResult push(FollowRecordDto dto) {
+        FollowRecord followRecord = getById(dto.getId());
+        if (followRecord == null || !followRecord.getPatientId().equals(AppUtil.getUser().getId())) {
+            return AjaxResult.error("回访不存在或非法操作");
+        }
+        followRecord.setOp(dto.getOp());
+        followRecord.setState(1);
+        if (!updateById(followRecord)) {
+            throw new ServiceException("提交回访记录失败");
+        }
+        return AjaxResult.success();
+    }
+}

+ 30 - 0
ruoyi-admin/src/main/java/com/ruoyi/web/work/service/impl/UserServiceImpl.java

@@ -4,13 +4,17 @@ import com.alibaba.fastjson2.JSON;
 import com.alibaba.fastjson2.JSONObject;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.exception.ServiceException;
 import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.common.utils.http.HttpUtils;
 import com.ruoyi.web.work.api.config.TokenServices;
+import com.ruoyi.web.work.api.util.AppUtil;
 import com.ruoyi.web.work.domain.User;
 import com.ruoyi.web.work.domain.dto.LoginDto;
+import com.ruoyi.web.work.domain.dto.UserEditDto;
 import com.ruoyi.web.work.mapper.UserMapper;
 import com.ruoyi.web.work.service.IUserService;
+import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.core.env.Environment;
 import org.springframework.stereotype.Service;
@@ -62,4 +66,30 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IU
         }
         return AjaxResult.success(new AjaxResult().put("token", tokenService.createToken(user)));
     }
+
+    @Override
+    public AjaxResult edit(UserEditDto dto) {
+        User user = new User();
+        BeanUtils.copyProperties(dto, user);
+        user.setId(AppUtil.getUser().getId());
+        if (!updateById(user)) {
+            throw new ServiceException("编辑用户信息失败");
+        }
+        return AjaxResult.success();
+    }
+
+    @Override
+    public AjaxResult exit() {
+        try {
+            tokenService.delLoginUser(AppUtil.getUser().getToken());
+            return AjaxResult.success();
+        } catch (Exception e) {
+            return AjaxResult.error("退出登录失败");
+        }
+    }
+
+    @Override
+    public AjaxResult info() {
+        return AjaxResult.success(getById(AppUtil.getUser().getId()));
+    }
 }

+ 17 - 0
ruoyi-admin/src/main/resources/mapper/work/FollowRecordMapper.xml

@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.web.work.mapper.FollowRecordMapper">
+    
+    <select id="selectList" resultType="com.ruoyi.web.work.domain.FollowRecord">
+        select id,template_name,state,create_time from tb_follow_record
+        <where>
+            <if test="patientId != null "> and patient_id = #{patientId}</if>
+            <if test="userId != null "> and user_id = #{userId}</if>
+            <if test="state != null "> and state = #{state}</if>
+            <if test="deptId != null "> and dept_id = #{deptId}</if>
+        </where>
+    </select>
+
+</mapper>

+ 11 - 6
ruoyi-admin/src/main/resources/mapper/work/FollowTemplateMapper.xml

@@ -5,12 +5,17 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 <mapper namespace="com.ruoyi.web.work.mapper.FollowTemplateMapper">
     
     <select id="selectList" resultType="com.ruoyi.web.work.domain.FollowTemplate">
-        select * from tb_follow_template
-        <where>  
-            <if test="userId != null "> and user_id = #{userId}</if>
-            <if test="title != null  and title != ''"> and title = #{title}</if>
-            <if test="state != null "> and state = #{state}</if>
-            <if test="deptId != null "> and dept_id = #{deptId}</if>
+        SELECT
+        k.*,
+        d.dept_name AS deptName
+        FROM
+        tb_follow_template k
+        LEFT JOIN sys_dept d ON d.dept_id = k.dept_id
+        <where>
+            <if test="userId != null "> and k.user_id = #{userId}</if>
+            <if test="title != null  and title != ''"> and k.title = #{title}</if>
+            <if test="state != null "> and k.state = #{state}</if>
+            <if test="deptId != null "> and k.dept_id = #{deptId}</if>
         </where>
     </select>