huangxiao 2 týždňov pred
rodič
commit
cae18d8877
50 zmenil súbory, kde vykonal 10559 pridanie a 5 odobranie
  1. 5 5
      pom.xml
  2. 57 0
      src/main/java/net/mingsoft/people/action/BaseAction.java
  3. 71 0
      src/main/java/net/mingsoft/people/action/PeopleAction.java
  4. 147 0
      src/main/java/net/mingsoft/people/action/PeopleLogAction.java
  5. 371 0
      src/main/java/net/mingsoft/people/action/PeopleUserAction.java
  6. 80 0
      src/main/java/net/mingsoft/people/action/people/FileAction.java
  7. 276 0
      src/main/java/net/mingsoft/people/action/people/PeopleAction.java
  8. 289 0
      src/main/java/net/mingsoft/people/action/people/PeopleUserAction.java
  9. 48 0
      src/main/java/net/mingsoft/people/annotation/PeopleLogAnn.java
  10. 189 0
      src/main/java/net/mingsoft/people/aop/FileVerifyAop.java
  11. 183 0
      src/main/java/net/mingsoft/people/aop/PeopleLogAop.java
  12. 342 0
      src/main/java/net/mingsoft/people/bean/PeopleBean.java
  13. 36 0
      src/main/java/net/mingsoft/people/bean/PeopleLogBean.java
  14. 37 0
      src/main/java/net/mingsoft/people/bean/PeopleLoginBean.java
  15. 113 0
      src/main/java/net/mingsoft/people/biz/IPeopleBiz.java
  16. 21 0
      src/main/java/net/mingsoft/people/biz/IPeopleLogBiz.java
  17. 48 0
      src/main/java/net/mingsoft/people/biz/IPeopleUserBiz.java
  18. 268 0
      src/main/java/net/mingsoft/people/biz/impl/PeopleBizImpl.java
  19. 38 0
      src/main/java/net/mingsoft/people/biz/impl/PeopleLogBizImpl.java
  20. 67 0
      src/main/java/net/mingsoft/people/biz/impl/PeopleUserBizImpl.java
  21. 28 0
      src/main/java/net/mingsoft/people/constant/Const.java
  22. 47 0
      src/main/java/net/mingsoft/people/constant/e/CookieConstEnum.java
  23. 47 0
      src/main/java/net/mingsoft/people/constant/e/LoginTypeEnum.java
  24. 48 0
      src/main/java/net/mingsoft/people/constant/e/PeopleAddressEnum.java
  25. 68 0
      src/main/java/net/mingsoft/people/constant/e/PeopleEnum.java
  26. 59 0
      src/main/java/net/mingsoft/people/constant/e/PeopleLogTypeEnum.java
  27. 78 0
      src/main/java/net/mingsoft/people/constant/e/SessionConstEnum.java
  28. 79 0
      src/main/java/net/mingsoft/people/dao/IPeopleDao.java
  29. 292 0
      src/main/java/net/mingsoft/people/dao/IPeopleDao.xml
  30. 19 0
      src/main/java/net/mingsoft/people/dao/IPeopleLogDao.java
  31. 58 0
      src/main/java/net/mingsoft/people/dao/IPeopleLogDao.xml
  32. 51 0
      src/main/java/net/mingsoft/people/dao/IPeopleUserDao.java
  33. 199 0
      src/main/java/net/mingsoft/people/dao/IPeopleUserDao.xml
  34. 357 0
      src/main/java/net/mingsoft/people/entity/PeopleEntity.java
  35. 232 0
      src/main/java/net/mingsoft/people/entity/PeopleLogEntity.java
  36. 320 0
      src/main/java/net/mingsoft/people/entity/PeopleUserEntity.java
  37. 83 0
      src/main/java/net/mingsoft/people/filter/PeopleLoginFilter.java
  38. 66 0
      src/main/java/net/mingsoft/people/realm/PeopleAuthRealm.java
  39. 36 0
      src/main/java/net/mingsoft/people/realm/PeopleLoginMD5CredentialsMatcher.java
  40. 55 0
      src/main/java/net/mingsoft/people/resources/resources_en_US.properties
  41. 55 0
      src/main/java/net/mingsoft/people/resources/resources_zh_CN.properties
  42. 30 0
      src/main/java/net/mingsoft/people/util/PeopleUtil.java
  43. 874 0
      src/main/webapp/WEB-INF/manager/index.ftl
  44. 642 0
      src/main/webapp/WEB-INF/manager/login.ftl
  45. 2031 0
      src/main/webapp/WEB-INF/manager/main.ftl
  46. 268 0
      src/main/webapp/WEB-INF/manager/people/people-log/form.ftl
  47. 284 0
      src/main/webapp/WEB-INF/manager/people/people-log/index.ftl
  48. 369 0
      src/main/webapp/WEB-INF/manager/people/people-user/audit.ftl
  49. 686 0
      src/main/webapp/WEB-INF/manager/people/people-user/form.ftl
  50. 412 0
      src/main/webapp/WEB-INF/manager/people/people-user/index.ftl

+ 5 - 5
pom.xml

@@ -49,11 +49,11 @@
             <artifactId>ms-msend</artifactId>
             <version>3.0.0</version>
         </dependency>
-        <dependency>
-            <groupId>net.mingsoft</groupId>
-            <artifactId>ms-mpeople</artifactId>
-            <version>${ms.version}</version>
-        </dependency>
+        <!--<dependency>-->
+        <!--    <groupId>net.mingsoft</groupId>-->
+        <!--    <artifactId>ms-mpeople</artifactId>-->
+        <!--    <version>${ms.version}</version>-->
+        <!--</dependency>-->
         <dependency>
             <groupId>com.github.oshi</groupId>
             <artifactId>oshi-core</artifactId>

+ 57 - 0
src/main/java/net/mingsoft/people/action/BaseAction.java

@@ -0,0 +1,57 @@
+/**
+ * Copyright (c) 2012-present 铭软科技(mingsoft.net)
+ * 本软件及相关文档文件(以下简称“软件”)的版权归 铭软科技 所有
+ * 遵循 铭软科技《服务协议》中的《保密条款》
+ */
+
+
+
+
+package net.mingsoft.people.action;
+
+import jakarta.servlet.http.HttpServletRequest;
+import net.mingsoft.base.util.BundleUtil;
+import net.mingsoft.basic.util.BasicUtil;
+import net.mingsoft.people.constant.Const;
+import net.mingsoft.people.constant.e.SessionConstEnum;
+import net.mingsoft.people.entity.PeopleEntity;
+import net.mingsoft.people.util.PeopleUtil;
+
+import java.util.MissingResourceException;
+
+/**
+ *
+ * 基础类
+ * @author 铭飞开发团队
+ * @version
+ * 版本号:0.0<br/>
+ * 创建日期:2017-8-23 10:10:22<br/>
+ * 历史修订:<br/>
+ */
+public class BaseAction extends net.mingsoft.mdiy.action.BaseAction {
+
+	@Override
+	protected String getResString(String key) {
+		// TODO Auto-generated method stub
+		String str = "";
+		try {
+			str = super.getResString(key);
+		} catch (MissingResourceException e) {
+//			str = getLocaleString(key, Const.RESOURCES);
+			str = BundleUtil.getString(Const.RESOURCES,key);
+		}
+
+		return str;
+	}
+	
+	/**
+	 * 从shiro中获取会员信息.没有返回shiro未登录异常<br/>
+	 * 建议Action层使用,如果其他层如biz层建议直接调用PeopleUtil.getPeopleBean()
+	 */
+	protected PeopleEntity getPeopleBySession() {
+		// 由于SecurityUtils.getSubject()压入的是完整peopleBean数据,peopleBean又是peopleEntity子类
+		// 所以这里直接采用peopleBean返回
+		return PeopleUtil.getPeopleBean();
+	}
+
+}

+ 71 - 0
src/main/java/net/mingsoft/people/action/PeopleAction.java

@@ -0,0 +1,71 @@
+/**
+ * Copyright (c) 2012-present 铭软科技(mingsoft.net)
+ * 本软件及相关文档文件(以下简称“软件”)的版权归 铭软科技 所有
+ * 遵循 铭软科技《服务协议》中的《保密条款》
+ */
+
+
+
+
+package net.mingsoft.people.action;
+
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.enums.ParameterIn;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import net.mingsoft.base.entity.ResultData;
+import net.mingsoft.basic.annotation.LogAnn;
+import net.mingsoft.basic.constant.e.BusinessTypeEnum;
+import net.mingsoft.people.biz.IPeopleBiz;
+import net.mingsoft.people.constant.e.PeopleEnum;
+import net.mingsoft.people.entity.PeopleEntity;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+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.ResponseBody;
+
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import java.util.List;
+
+/**
+ * 用户基础信息表管理控制层
+ * @author 铭飞开发团队
+ * @version 
+ * 版本号:0.0<br/>
+ * 创建日期:2017-8-23 10:10:22<br/>
+ * 历史修订:<br/>
+ */
+@Tag(name = "后端-会员模块接口")
+@Controller
+@RequestMapping("/${ms.manager.path}/people")
+public class PeopleAction extends BaseAction{
+	
+	/**
+	 * 注入用户控制层
+	 */
+	@Autowired
+	private IPeopleBiz peopleBiz;
+
+	@Operation(summary = "更新用户状态接口")
+    @Parameter(name = "peoples", description = "所选用户", required =  true, in = ParameterIn.QUERY)
+	@LogAnn(title = "更新用户状态接口",businessType= BusinessTypeEnum.UPDATE)
+	@PostMapping("/updateState")
+    @ResponseBody
+	public ResultData updateState(@RequestBody List<PeopleEntity> peoples, HttpServletRequest request, HttpServletResponse response){
+		if(peoples.size() <= 0){
+			return ResultData.build().error();
+		}
+		for(int i = 0;i < peoples.size(); i++){
+			if(peoples.get(i).getPeopleState() == PeopleEnum.STATE_CHECK.toInt()){
+				peoples.get(i).setPeopleStateEnum(PeopleEnum.STATE_NOT_CHECK);
+			}else{
+				peoples.get(i).setPeopleStateEnum(PeopleEnum.STATE_CHECK);
+			}
+			this.peopleBiz.updateById(peoples.get(i));
+		}
+		return ResultData.build().success();
+	}
+}

+ 147 - 0
src/main/java/net/mingsoft/people/action/PeopleLogAction.java

@@ -0,0 +1,147 @@
+/**
+ * Copyright (c) 2012-present 铭软科技(mingsoft.net)
+ * 本软件及相关文档文件(以下简称“软件”)的版权归 铭软科技 所有
+ * 遵循 铭软科技《服务协议》中的《保密条款》
+ */
+
+package net.mingsoft.people.action;
+
+import io.swagger.v3.oas.annotations.Hidden;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.Parameters;
+import io.swagger.v3.oas.annotations.enums.ParameterIn;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import net.mingsoft.base.entity.ResultData;
+import net.mingsoft.basic.bean.EUListBean;
+import net.mingsoft.basic.util.BasicUtil;
+import net.mingsoft.people.bean.PeopleLogBean;
+import net.mingsoft.people.biz.IPeopleLogBiz;
+import net.mingsoft.people.constant.e.PeopleLogTypeEnum;
+import net.mingsoft.people.entity.PeopleLogEntity;
+import org.apache.shiro.authz.annotation.RequiresPermissions;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.ModelMap;
+import org.springframework.validation.BindingResult;
+import org.springframework.web.bind.annotation.*;
+
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+
+/**
+ * 会员日志管理控制层
+ *
+ * @author 铭软科技
+ * 创建日期:2023-6-5 17:34:20<br/>
+ * 历史修订:<br/>
+ */
+@Tag(name = "后台-会员日志接口")
+@Controller("mpeoplePeopleLogAction")
+@RequestMapping("/${ms.manager.path}/people/peopleLog")
+public class PeopleLogAction extends net.mingsoft.people.action.BaseAction {
+
+
+    /**
+     * 注入会员日志业务层
+     */
+    @Autowired
+    private IPeopleLogBiz peopleLogBiz;
+
+    /**
+     * 返回主界面index
+     */
+    @Hidden
+    @GetMapping("/index")
+    @RequiresPermissions("people:peopleLog:view")
+    public String index(HttpServletResponse response, HttpServletRequest request) {
+        return "/people/people-log/index";
+    }
+
+    /**
+     * 查询会员日志列表
+     *
+     * @param peopleLog 会员日志实体
+     */
+    @Operation(summary = "查询会员日志列表接口")
+    @Parameters({
+            @Parameter(name = "peopleId", description = "会员编号", in = ParameterIn.QUERY),
+            @Parameter(name = "logIp", description = "IP", in = ParameterIn.QUERY),
+            @Parameter(name = "logAddr", description = "所在地区", in = ParameterIn.QUERY),
+            @Parameter(name = "logType", description = "日志类型", in = ParameterIn.QUERY),
+            @Parameter(name = "logInfo", description = "日志信息", in = ParameterIn.QUERY)
+    })
+    @RequestMapping(value = "/list", method = {RequestMethod.GET, RequestMethod.POST})
+    @ResponseBody
+    public ResultData list(@ModelAttribute @Parameter(hidden = true) PeopleLogBean peopleLog, HttpServletResponse response, HttpServletRequest request, @Parameter(hidden = true) ModelMap model, BindingResult result) {
+        BasicUtil.startPage();
+        List<PeopleLogEntity> logList = peopleLogBiz.query(peopleLog);
+        return ResultData.build().success(new EUListBean(logList,(int)BasicUtil.endPage(logList).getTotal()));
+    }
+
+    /**
+     * 返回编辑界面peopleLog的form
+     */
+    @Hidden
+    @GetMapping("/form")
+    public String form(@ModelAttribute PeopleLogEntity peopleLog, HttpServletResponse response, HttpServletRequest request, ModelMap model) {
+        return "/people/people-log/form";
+    }
+
+
+    /**
+     * 获取会员日志
+     *
+     * @param peopleLog 会员日志实体
+     */
+    @Operation(summary = "获取会员日志列表接口")
+    @Parameter(name = "id", description = "主键ID", required =  true, in = ParameterIn.QUERY)
+    @GetMapping("/get")
+    @ResponseBody
+    public ResultData get(@ModelAttribute @Parameter(hidden = true) PeopleLogEntity peopleLog, HttpServletResponse response, HttpServletRequest request, @Parameter(hidden = true) ModelMap model) {
+        if (peopleLog.getId() == null) {
+            return ResultData.build().error();
+        }
+        PeopleLogEntity _peopleLog = (PeopleLogEntity) peopleLogBiz.getById(peopleLog.getId());
+        return ResultData.build().success(_peopleLog);
+    }
+
+    /**
+     * 获取日志类型枚举类
+     */
+    @Operation(summary = "获取日志类型枚举类")
+    @PostMapping("/queryLogType")
+    @ResponseBody
+    public ResultData queryLogType(HttpServletResponse response, HttpServletRequest request) {
+        List<HashMap<String, String>> list = new ArrayList<>();
+        try {
+            Class _class = Class.forName(PeopleLogTypeEnum.class.getName());
+            Object[] enumConstants = _class.getEnumConstants();
+            Arrays.stream(enumConstants).forEach(e-> {
+                HashMap<String, String> map = new HashMap<>();
+                map.put("value", e.toString().toLowerCase());
+                try {
+                    Method label = e.getClass().getMethod("getLabel");
+                    map.put("label", label.invoke(e).toString());
+                } catch (NoSuchMethodException ex) {
+                    ex.printStackTrace();
+                } catch (IllegalAccessException ex) {
+                    ex.printStackTrace();
+                } catch (InvocationTargetException ex) {
+                    ex.printStackTrace();
+                }
+                list.add(map);
+            });
+        } catch (ClassNotFoundException e) {
+            e.printStackTrace();
+        }
+        return ResultData.build().success(list);
+    }
+
+}

+ 371 - 0
src/main/java/net/mingsoft/people/action/PeopleUserAction.java

@@ -0,0 +1,371 @@
+/**
+ * Copyright (c) 2012-present 铭软科技(mingsoft.net)
+ * 本软件及相关文档文件(以下简称“软件”)的版权归 铭软科技 所有
+ * 遵循 铭软科技《服务协议》中的《保密条款》
+ */
+
+
+
+
+package net.mingsoft.people.action;
+
+import cn.hutool.core.collection.CollectionUtil;
+import cn.hutool.crypto.SecureUtil;
+import io.swagger.v3.oas.annotations.Hidden;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.Parameters;
+import io.swagger.v3.oas.annotations.enums.ParameterIn;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import net.mingsoft.base.entity.ResultData;
+import net.mingsoft.basic.annotation.LogAnn;
+import net.mingsoft.basic.bean.EUListBean;
+import net.mingsoft.basic.constant.e.BusinessTypeEnum;
+import net.mingsoft.basic.util.BasicUtil;
+import net.mingsoft.basic.util.FileUtil;
+import net.mingsoft.basic.util.StringUtil;
+import net.mingsoft.mdiy.util.ConfigUtil;
+import net.mingsoft.people.bean.PeopleBean;
+import net.mingsoft.people.biz.IPeopleBiz;
+import net.mingsoft.people.biz.IPeopleUserBiz;
+import net.mingsoft.people.constant.e.PeopleEnum;
+import net.mingsoft.people.entity.PeopleEntity;
+import net.mingsoft.people.entity.PeopleUserEntity;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.shiro.authz.annotation.Logical;
+import org.apache.shiro.authz.annotation.RequiresPermissions;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.ModelMap;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.Date;
+import java.util.List;
+
+/**
+ * 用户基础信息表管理控制层
+ * @author 伍晶晶
+ * @version
+ * 版本号:0.0<br/>
+ * 创建日期:2017-8-23 10:10:22<br/>
+ * 历史修订:修改list接口,过滤掉未审核的用户数据<br/>
+ */
+@Tag(name = "后端-会员模块接口")
+@Controller
+@RequestMapping("/${ms.manager.path}/people/peopleUser")
+public class PeopleUserAction extends BaseAction{
+
+	/**
+	 * 注入用户基础信息表业务层
+	 */
+	@Autowired
+	private IPeopleUserBiz peopleUserBiz;
+
+	@Autowired
+	private IPeopleBiz peopleBiz;
+
+	/**
+	 * 返回主界面index
+	 */
+	@Hidden
+	@GetMapping("/index")
+	@RequiresPermissions("people:user:view")
+	public String index(HttpServletResponse response,HttpServletRequest request){
+		return "/people/people-user/index";
+	}
+
+
+
+    @Operation(summary = "获取用户基础详情接口")
+    @Parameters({
+        @Parameter(name = "peopleId", description = "用户ID关联people表的(people_id)", required =  true, in = ParameterIn.QUERY),
+    })
+    @GetMapping("/get")
+    @ResponseBody
+	@RequiresPermissions("people:user:view")
+    public ResultData get(@ModelAttribute @Parameter(hidden = true) PeopleBean PeopleBean, HttpServletResponse response, HttpServletRequest request, @Parameter(hidden = true) ModelMap model){
+        if(StringUtils.isBlank(PeopleBean.getPeopleId())) {
+            return ResultData.build().error(getResString("err.error", this.getResString("pu.people.id")));
+        }
+		PeopleBean _peopleUser = peopleBiz.getPeopleById(PeopleBean.getPeopleId());
+        return ResultData.build().success( _peopleUser);
+    }
+
+	@Operation(summary = "用户基础信息列表接口")
+	@Parameters({
+    	@Parameter(name = "peopleName", description = "用户账号", required = false, in = ParameterIn.QUERY),
+    	@Parameter(name = "puNickname", description = "用户昵称", required =  false, in = ParameterIn.QUERY),
+    	@Parameter(name = "peopleState", description = "审核状态", required =  false, in = ParameterIn.QUERY),
+    	@Parameter(name = "puRealName", description = "真实姓名", required =  false, in = ParameterIn.QUERY),
+    	@Parameter(name = "peopleDateTimes", description = "注册时间范围,如2019-01-23至2019-01-24", required =  false, in = ParameterIn.QUERY),
+    	@Parameter(name = "peopleId", description = "用户ID关联people表的(people_id)", required =  false, in = ParameterIn.QUERY),
+    	@Parameter(name = "puAddress", description = "用户地址", required =  false, in = ParameterIn.QUERY),
+    	@Parameter(name = "puIcon", description = "用户头像图标地址", required =  false, in = ParameterIn.QUERY),
+    	@Parameter(name = "puSex", description = "用户性别(0.未知、1.男、2.女)", required =  false, in = ParameterIn.QUERY),
+    	@Parameter(name = "puBirthday", description = "用户出生年月日", required =  false, in = ParameterIn.QUERY),
+    	@Parameter(name = "puCard", description = "身份证", required =  false, in = ParameterIn.QUERY),
+    	@Parameter(name = "puAppId", description = "用户所属应用ID", required =  false, in = ParameterIn.QUERY),
+    	@Parameter(name = "puProvince", description = "省", required =  false, in = ParameterIn.QUERY),
+    	@Parameter(name = "puCity", description = "城市", required =  false, in = ParameterIn.QUERY),
+    	@Parameter(name = "puDistrict", description = "区", required =  false, in = ParameterIn.QUERY),
+    	@Parameter(name = "puStreet", description = "街道", required =  false, in = ParameterIn.QUERY)
+
+    })
+	@GetMapping("/auditList")
+	@ResponseBody
+	@RequiresPermissions("people:user:view")
+	public ResultData auditList(@ModelAttribute @Parameter(hidden = true) PeopleBean peoplebean, HttpServletResponse response, HttpServletRequest request, @Parameter(hidden = true) ModelMap model) {
+		if(peoplebean == null){
+			peoplebean = new PeopleBean();
+		}
+		peoplebean.setPeopleStateEnum(PeopleEnum.STATE_CHECK);
+		BasicUtil.startPage();
+		// 注册时间处理
+		List<PeopleBean> peopleUserList = peopleBiz.query(peoplebean);
+		EUListBean list = new EUListBean(peopleUserList,(int) BasicUtil.endPage(peopleUserList).getTotal());
+		return ResultData.build().success( list);
+	}
+
+	@Operation(summary = "查询未审核的用户列表接口")
+	@GetMapping("/unAuditList")
+	@Parameters({
+			@Parameter(name = "peopleName", description = "用户账号", required = false, in = ParameterIn.QUERY),
+			@Parameter(name = "puNickname", description = "用户昵称", required =  false, in = ParameterIn.QUERY),
+			@Parameter(name = "peopleState", description = "审核状态", required =  false, in = ParameterIn.QUERY),
+			@Parameter(name = "puRealName", description = "真实姓名", required =  false, in = ParameterIn.QUERY),
+			@Parameter(name = "peopleDateTimes", description = "注册时间范围,如2019-01-23至2019-01-24", required =  false, in = ParameterIn.QUERY),
+			@Parameter(name = "peopleId", description = "用户ID关联people表的(people_id)", required =  false, in = ParameterIn.QUERY),
+			@Parameter(name = "puAddress", description = "用户地址", required =  false, in = ParameterIn.QUERY),
+			@Parameter(name = "puIcon", description = "用户头像图标地址", required =  false, in = ParameterIn.QUERY),
+			@Parameter(name = "puSex", description = "用户性别(0.未知、1.男、2.女)", required =  false, in = ParameterIn.QUERY),
+			@Parameter(name = "puBirthday", description = "用户出生年月日", required =  false, in = ParameterIn.QUERY),
+			@Parameter(name = "puCard", description = "身份证", required =  false, in = ParameterIn.QUERY),
+			@Parameter(name = "puAppId", description = "用户所属应用ID", required =  false, in = ParameterIn.QUERY),
+			@Parameter(name = "puProvince", description = "省", required =  false, in = ParameterIn.QUERY),
+			@Parameter(name = "puCity", description = "城市", required =  false, in = ParameterIn.QUERY),
+			@Parameter(name = "puDistrict", description = "区", required =  false, in = ParameterIn.QUERY),
+			@Parameter(name = "puStreet", description = "街道", required =  false, in = ParameterIn.QUERY)
+	})
+	@ResponseBody
+	@RequiresPermissions("people:view")
+	public ResultData unAuditList(@ModelAttribute @Parameter(hidden = true) PeopleBean peopleBean, HttpServletResponse response, HttpServletRequest request, @Parameter(hidden = true) ModelMap model) {
+		if(peopleBean == null){
+			peopleBean = new PeopleBean();
+		}
+
+		peopleBean.setPeopleStateEnum(PeopleEnum.STATE_NOT_CHECK);
+		BasicUtil.startPage();
+		List<PeopleBean> peopleUserList = peopleBiz.query(peopleBean);
+		EUListBean list = new EUListBean(peopleUserList,(int) BasicUtil.endPage(peopleUserList).getTotal());
+		return ResultData.build().success(list);
+	}
+
+	/**
+	 * 返回编辑界面peopleUser_form
+	 */
+	@Hidden
+	@GetMapping("/form")
+	@RequiresPermissions(value = {"people:user:save", "people:user:update"}, logical = Logical.OR)
+	public String form(@ModelAttribute PeopleUserEntity peopleUser, HttpServletResponse response, HttpServletRequest request, ModelMap model){
+		return "/people/people-user/form";
+	}
+
+	@Operation(summary = "保存用户基础信息接口")
+	@Parameters({
+		@Parameter(name = "peopleName", description = "登录账号", required =  true, in = ParameterIn.QUERY),
+		@Parameter(name = "peoplePassword", description = "用户密码", required =  true, in = ParameterIn.QUERY),
+        @Parameter(name = "peopleId", description = "用户ID关联people表的(people_id)", required =  false, in = ParameterIn.QUERY),
+        @Parameter(name = "puRealName", description = "用户真实名称", required =  false, in = ParameterIn.QUERY),
+        @Parameter(name = "puAddress", description = "用户地址", required =  false, in = ParameterIn.QUERY),
+        @Parameter(name = "puIcon", description = "用户头像图标地址", required =  false, in = ParameterIn.QUERY),
+        @Parameter(name = "puNickname", description = "用户昵称", required =  false, in = ParameterIn.QUERY),
+        @Parameter(name = "puSex", description = "用户性别(0.未知、1.男、2.女)", required =  false, in = ParameterIn.QUERY),
+        @Parameter(name = "puBirthday", description = "用户出生年月日", required =  false, in = ParameterIn.QUERY),
+        @Parameter(name = "puCard", description = "身份证", required =  false, in = ParameterIn.QUERY),
+        @Parameter(name = "puAppId", description = "用户所属应用ID", required =  false, in = ParameterIn.QUERY),
+        @Parameter(name = "puProvince", description = "省", required =  false, in = ParameterIn.QUERY),
+        @Parameter(name = "puCity", description = "城市", required =  false, in = ParameterIn.QUERY),
+        @Parameter(name = "puDistrict", description = "区", required =  false, in = ParameterIn.QUERY),
+        @Parameter(name = "puStreet", description = "街道", required =  false, in = ParameterIn.QUERY)
+    })
+	@LogAnn(title = "保存用户基础信息接口",businessType= BusinessTypeEnum.INSERT)
+	@PostMapping("/save")
+	@ResponseBody
+	@RequiresPermissions("people:user:save")
+	public ResultData save(@ModelAttribute @Parameter(hidden = true) PeopleBean peopleUser, HttpServletResponse response, HttpServletRequest request) {
+		if(peopleUser.getPeoplePhoneCheck()== PeopleEnum.PHONE_NO_CHECK.toInt() && peopleUser.getPeopleMailCheck()==PeopleEnum.MAIL_NO_CHECK.toInt()  && !StringUtil.checkLength(peopleUser.getPeopleName()+"", 6, 30)){
+			return ResultData.build().error(getResString("err.length", this.getResString("people.name"), "6", "30"));
+		}
+		if(!StringUtil.checkLength(peopleUser.getPeoplePassword()+"", 6, 30)){
+			return ResultData.build().error(getResString("err.length", this.getResString("people.password"), "6", "30"));
+		}
+		//验证用户真实名称的值是否合法
+		if(!StringUtil.checkLength(peopleUser.getPuRealName()+"", 0, 50)){
+			return ResultData.build().error(getResString("err.length", this.getResString("pu.real.name"), "0", "50"));
+		}
+		if(!StringUtil.checkLength(peopleUser.getPuAddress()+"", 0, 200)){
+			return ResultData.build().error(getResString("err.length", this.getResString("pu.address"), "0", "200"));
+		}
+		if(!StringUtil.checkLength(peopleUser.getPuIcon()+"", 0, 200)){
+			return ResultData.build().error(getResString("err.length", this.getResString("pu.icon"), "0", "200"));
+		}
+		if(!StringUtil.checkLength(peopleUser.getPuNickname()+"", 0, 50)){
+			return ResultData.build().error(getResString("err.length", this.getResString("pu.nickname"), "0", "50"));
+		}
+		//验证用户性别(0.未知、1.男、2.女)的值是否合法
+		if(!StringUtil.checkLength(peopleUser.getPuSex()+"", 0, 10)){
+			return ResultData.build().error(getResString("err.length", this.getResString("pu.sex"), "0", "10"));
+		}
+		//验证身份证的值是否合法
+		if(!StringUtil.checkLength(peopleUser.getPuCard()+"", 0, 255)){
+			return ResultData.build().error(getResString("err.length", this.getResString("pu.card"), "0", "255"));
+		}
+		if(StringUtils.isNotBlank(peopleUser.getPeoplePassword()) && StringUtils.isNotBlank(peopleUser.getPeopleName())){
+			//设置用户密码
+			peopleUser.setPeoplePassword(SecureUtil.md5(peopleUser.getPeoplePassword()));
+		}
+		// 手机号不为空则标记为通过
+		if (StringUtils.isNotBlank(peopleUser.getPeoplePhone())){
+			peopleUser.setPeoplePhoneCheck(PeopleEnum.PHONE_CHECK);
+		}
+		if(StringUtils.isBlank(peopleUser.getPeoplePhone())){
+			peopleUser.setPeoplePhoneCheck(PeopleEnum.PHONE_NO_CHECK);
+		}
+		// 邮箱不为空则标记为通过
+		if (StringUtils.isNotBlank(peopleUser.getPeopleMail())){
+			peopleUser.setPeopleMailCheck(PeopleEnum.MAIL_CHECK);
+		}
+		if(StringUtils.isBlank(peopleUser.getPeopleMail())){
+			peopleUser.setPeopleMailCheck(PeopleEnum.MAIL_NO_CHECK);
+		}
+		// 验证用户输入的信息是否合法
+		if(!peopleBiz.isExists(peopleUser)){
+			return ResultData.build().error("用户输入信息不合法");
+		}
+		// 验证是否开启了 审核功能
+		String peopleState = ConfigUtil.getString("会员配置", "peopleState");
+		if ("true".equalsIgnoreCase(peopleState)){
+			peopleUser.setPeopleState(0); // 开启
+		}
+		else {
+			peopleUser.setPeopleState(1); // 关闭
+		}
+
+		peopleUser.setPeopleDateTime(new Date());
+		peopleBiz.savePeople(peopleUser);
+		return ResultData.build().success("保存成功,记得审核!",peopleUser);
+	}
+
+	@Operation(summary = "批量删除用户接口")
+    @Parameters({
+        @Parameter(name = "peopleId", description = "多个puPeopleId直接用逗号隔开,例如puPeopleId=1,2,3,4", required =  true, in = ParameterIn.QUERY)
+    })
+	@LogAnn(title = "批量删除用户接口",businessType= BusinessTypeEnum.DELETE)
+	@PostMapping("/delete")
+	@ResponseBody
+	@RequiresPermissions("people:user:del")
+	public ResultData delete(@RequestBody List<PeopleBean> peopleBeans, HttpServletResponse response, HttpServletRequest request) {
+		if (CollectionUtil.isEmpty(peopleBeans)) {
+			return ResultData.build().error(this.getResString("err.empty", this.getResString("people.id")));
+		}
+		String[] ids = peopleBeans.stream().map(PeopleBean::getId).toArray(String[]::new);
+
+		FileUtil.del(peopleBeans);
+		peopleBiz.deletePeople(ids);
+		return ResultData.build().success();
+
+	}
+
+	@Operation(summary = "修改用户基础信息接口")
+	@Parameters({
+		@Parameter(name = "peoplePassword", description = "用户密码", required =  false, in = ParameterIn.QUERY),
+        @Parameter(name = "puRealName", description = "用户真实名称", required =  false, in = ParameterIn.QUERY),
+        @Parameter(name = "puAddress", description = "用户地址", required =  false, in = ParameterIn.QUERY),
+        @Parameter(name = "puIcon", description = "用户头像图标地址", required =  false, in = ParameterIn.QUERY),
+        @Parameter(name = "puNickname", description = "用户昵称", required =  false, in = ParameterIn.QUERY),
+        @Parameter(name = "puSex", description = "用户性别(0.未知、1.男、2.女)", required =  false, in = ParameterIn.QUERY),
+        @Parameter(name = "puBirthday", description = "用户出生年月日", required =  false, in = ParameterIn.QUERY),
+        @Parameter(name = "puCard", description = "身份证", required =  false, in = ParameterIn.QUERY),
+        @Parameter(name = "puAppId", description = "用户所属应用ID", required =  false, in = ParameterIn.QUERY),
+        @Parameter(name = "puProvince", description = "省", required =  false, in = ParameterIn.QUERY),
+        @Parameter(name = "puCity", description = "城市", required =  false, in = ParameterIn.QUERY),
+        @Parameter(name = "puDistrict", description = "区", required =  false, in = ParameterIn.QUERY),
+        @Parameter(name = "puStreet", description = "街道", required =  false, in = ParameterIn.QUERY)
+    })
+	@LogAnn(title = "修改用户基础信息接口",businessType= BusinessTypeEnum.UPDATE)
+	@PostMapping("/update")
+	@ResponseBody
+	@RequiresPermissions("people:user:update")
+	public ResultData update(@ModelAttribute @Parameter(hidden = true) PeopleBean peopleUser, HttpServletResponse response,
+                             HttpServletRequest request) {
+		if(peopleUser.getPeoplePhoneCheck()==PeopleEnum.PHONE_NO_CHECK.toInt() && peopleUser.getPeopleMailCheck()==PeopleEnum.MAIL_NO_CHECK.toInt() && !StringUtil.checkLength(peopleUser.getPeopleName()+"", 6, 30)){
+			return ResultData.build().error(getResString("err.length", this.getResString("people.name"), "6", "30"));
+		}
+		if(!StringUtil.checkLength(peopleUser.getPuRealName()+"", 0, 50)){
+			return ResultData.build().error(getResString("err.length", this.getResString("pu.real.name"), "0", "50"));
+		}
+		if(!StringUtil.checkLength(peopleUser.getPuAddress()+"", 0, 200)){
+			return ResultData.build().error(getResString("err.length", this.getResString("pu.address"), "0", "200"));
+		}
+		if(!StringUtil.checkLength(peopleUser.getPuIcon()+"", 0, 200)){
+			return ResultData.build().error(getResString("err.length", this.getResString("pu.icon"), "0", "200"));
+		}
+		if(!StringUtil.checkLength(peopleUser.getPuNickname()+"", 0, 50)){
+			return ResultData.build().error(getResString("err.length", this.getResString("pu.nickname"), "0", "50"));
+		}
+		//验证用户性别(0.未知、1.男、2.女)的值是否合法
+		if(!StringUtil.checkLength(peopleUser.getPuSex()+"", 0, 10)){
+			return ResultData.build().error(getResString("err.length", this.getResString("pu.sex"), "0", "10"));
+		}
+		//验证身份证的值是否合法
+		if(!StringUtil.checkLength(peopleUser.getPuCard()+"", 0, 255)){
+			return ResultData.build().error(getResString("err.length", this.getResString("pu.card"), "0", "255"));
+		}
+		// 不允许用户通过该接口修改审核状态
+		PeopleEntity _people = peopleBiz.getById(peopleUser.getPeopleId());
+		peopleUser.setPeopleState(_people.getPeopleState());
+		// 手机号不为空则标记为通过
+		if (StringUtils.isNotBlank(peopleUser.getPeoplePhone())){
+			peopleUser.setPeoplePhoneCheck(PeopleEnum.PHONE_CHECK);
+		}
+		if(StringUtils.isBlank(peopleUser.getPeoplePhone())){
+			peopleUser.setPeoplePhoneCheck(PeopleEnum.PHONE_NO_CHECK);
+		}
+
+		// 邮箱不为空则标记为通过
+		if (StringUtils.isNotBlank(peopleUser.getPeopleMail())){
+			peopleUser.setPeopleMailCheck(PeopleEnum.MAIL_CHECK);
+		}
+		if(StringUtils.isBlank(peopleUser.getPeopleMail())){
+			peopleUser.setPeopleMailCheck(PeopleEnum.MAIL_NO_CHECK);
+		}
+		// 验证用户输入的信息是否合法
+		if(!peopleBiz.isExists(peopleUser)){
+			return ResultData.build().error("用户输入信息不合法");
+		}
+		//判断用户密码是否为空,如果不为空则进行密码的更新
+		if(!StringUtils.isBlank(peopleUser.getPeoplePassword())){
+			//设置用户密码
+			if(!StringUtil.checkLength(peopleUser.getPeoplePassword()+"", 6, 30)){
+				return ResultData.build().error(getResString("err.length", this.getResString("people.password"), "6", "30"));
+			}else {
+				peopleUser.setPeoplePassword(SecureUtil.md5(peopleUser.getPeoplePassword()));
+			}
+		}
+		peopleUser.setId(peopleUser.getPeopleId() + "");
+		peopleBiz.updatePeople(peopleUser);
+		return ResultData.build().success(peopleUser);
+	}
+
+	/**
+	 * 返回主界面index
+	 */
+	@Hidden
+	@GetMapping("/audit")
+	@RequiresPermissions("people:view")
+	public String indexAudit(HttpServletResponse response,HttpServletRequest request){
+		return "/people/people-user/audit";
+	}
+}

+ 80 - 0
src/main/java/net/mingsoft/people/action/people/FileAction.java

@@ -0,0 +1,80 @@
+/**
+ * Copyright (c) 2012-present 铭软科技(mingsoft.net)
+ * 本软件及相关文档文件(以下简称“软件”)的版权归 铭软科技 所有
+ * 遵循 铭软科技《服务协议》中的《保密条款》
+ */
+
+package net.mingsoft.people.action.people;
+
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.Parameters;
+import io.swagger.v3.oas.annotations.enums.ParameterIn;
+import io.swagger.v3.oas.annotations.enums.ParameterStyle;
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import net.mingsoft.base.entity.ResultData;
+import net.mingsoft.basic.action.BaseFileAction;
+import net.mingsoft.basic.bean.UploadConfigBean;
+import net.mingsoft.basic.constant.e.BusinessTypeEnum;
+import net.mingsoft.basic.util.BasicUtil;
+import net.mingsoft.config.MSProperties;
+import net.mingsoft.mdiy.util.ConfigUtil;
+import net.mingsoft.people.annotation.PeopleLogAnn;
+import net.mingsoft.people.constant.e.PeopleLogTypeEnum;
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * 会员上传文件
+ */
+@Tag(name = "前端-用户-会员模块接口")
+@Controller("peopleFile")
+@RequestMapping("/people/file")
+public class FileAction extends BaseFileAction {
+
+
+    protected final static Logger LOG = LoggerFactory.getLogger(FileAction.class);
+
+
+    @Operation(summary = "处理post请求上传文件")
+    @PeopleLogAnn(title = "处理post请求上传文件",businessType= PeopleLogTypeEnum.DELETE)
+    @Parameters({
+            @Parameter(name = "uploadPath", description = "上传文件夹地址", required = true, in = ParameterIn.QUERY, style = ParameterStyle.FORM),
+            @Parameter(name = "file", description = "文件流", required = false, style = ParameterStyle.FORM),
+            @Parameter(name = "rename", description = "是否重命名", required =false, style = ParameterStyle.FORM, schema = @Schema(defaultValue = "true")),
+            @Parameter(name = "appId", description = "上传路径是否需要拼接appId", required =false, style = ParameterStyle.FORM, schema = @Schema(defaultValue = "false")),
+            @Parameter(name = "uploadFolderPath", description = "是否修改上传目录", required =false, style = ParameterStyle.FORM, schema = @Schema(defaultValue = "false")),
+    })
+    @PostMapping("/upload")
+    @ResponseBody
+    public ResultData upload(@Parameter(hidden = true) UploadConfigBean bean, HttpServletRequest req, HttpServletResponse res) throws IOException {
+        boolean uploadEnable = ConfigUtil.getEntity("文件上传配置")==null? MSProperties.upload.enableWeb :ConfigUtil.getBoolean("文件上传配置", "uploadEnable");
+        if(uploadEnable){
+            //非法路径过滤
+            if(StringUtils.isBlank(bean.getUploadPath()) || bean.getUploadPath().contains("../")||bean.getUploadPath().contains("..\\")){
+                return ResultData.build().error(getResString("err.error", getResString("file.path")));
+            }
+            // 是否需要拼接appId
+            if(bean.isAppId()){
+                bean.setUploadPath(BasicUtil.getApp().getAppId()+ File.separator+ bean.getUploadPath()) ;
+            }
+            UploadConfigBean config = new UploadConfigBean(bean.getUploadPath(),bean.getFile(),null, bean.isRename());
+            return this.upload(config);
+        }else {
+            return ResultData.build().error(getResString("insufficient.permissions"));
+        }
+
+    }
+
+}

+ 276 - 0
src/main/java/net/mingsoft/people/action/people/PeopleAction.java

@@ -0,0 +1,276 @@
+/**
+ * Copyright (c) 2012-present 铭软科技(mingsoft.net)
+ * 本软件及相关文档文件(以下简称“软件”)的版权归 铭软科技 所有
+ * 遵循 铭软科技《服务协议》中的《保密条款》
+ */
+
+
+
+
+package net.mingsoft.people.action.people;
+
+import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.crypto.SecureUtil;
+import freemarker.core.ParseException;
+import freemarker.template.MalformedTemplateNameException;
+import freemarker.template.TemplateNotFoundException;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.Parameters;
+import io.swagger.v3.oas.annotations.enums.ParameterIn;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import net.mingsoft.base.entity.ResultData;
+import net.mingsoft.base.exception.BusinessException;
+import net.mingsoft.basic.util.BasicUtil;
+import net.mingsoft.basic.util.StringUtil;
+import net.mingsoft.mdiy.biz.IPageBiz;
+import net.mingsoft.mdiy.entity.PageEntity;
+import net.mingsoft.mdiy.util.ParserUtil;
+import net.mingsoft.people.action.BaseAction;
+import net.mingsoft.people.annotation.PeopleLogAnn;
+import net.mingsoft.people.biz.IPeopleBiz;
+import net.mingsoft.people.constant.e.PeopleEnum;
+import net.mingsoft.people.constant.e.PeopleLogTypeEnum;
+import net.mingsoft.people.constant.e.SessionConstEnum;
+import net.mingsoft.people.entity.PeopleEntity;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.shiro.SecurityUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.*;
+
+import java.io.IOException;
+import java.util.Map;
+
+/**
+ *
+ * 用户基础信息表管理控制层
+ * @author 铭飞开发团队
+ * @version
+ * 版本号:0.0<br/>
+ * 创建日期:2017-8-23 10:10:22<br/>
+ * 历史修订:<br/>
+ */
+@Tag(name = "前端-用户-会员模块接口")
+@Controller("peopleMain")
+@RequestMapping("/people")
+public class PeopleAction extends BaseAction {
+	/**
+	 * 注入用户基础业务层
+	 */
+	@Autowired
+	private IPeopleBiz peopleBiz;
+
+	@Value("${ms.diy.html-dir:html}")
+	private String htmlDir;
+
+	/**
+	 * 自定义页面业务层
+	 */
+	@Autowired
+	private IPageBiz pageBiz;
+
+	@Operation(summary = "修改密码接口")
+	@PostMapping(value = "/changePassword")
+	@Parameters({
+		@Parameter(name = "peoplePassword", description = "用户密码", required =  true, in = ParameterIn.QUERY),
+		@Parameter(name = "peopleOldPassword", description = "用户旧密码", required =  true, in = ParameterIn.QUERY)
+	})
+	@ResponseBody
+	@PeopleLogAnn(title = "修改密码", businessType = PeopleLogTypeEnum.UPDATE)
+	public ResultData changePassword(@ModelAttribute @Parameter(hidden = true) PeopleEntity people, HttpServletRequest request,
+			HttpServletResponse response) {
+		// 验证码验证 验证码不为null 或 验证码不相等
+		if (!checkRandCode()) {
+			return ResultData.build().error(
+					this.getResString("err.error", this.getResString("rand.code")));
+		}
+		if (StringUtils.isBlank(people.getPeoplePassword())) {
+			// 用户或密码不能为空
+			return ResultData.build().error(
+					this.getResString("err.empty", this.getResString("people.password")));
+		}
+
+
+		// 验证新密码的长度
+		if (!StringUtil.checkLength(people.getPeoplePassword(), 6, 30)) {
+			return ResultData.build().error(
+					this.getResString("err.length", this.getResString("people.password"), "6", "30"));
+		}
+
+		// 验证新密码的合法:空格字符
+		if (people.getPeoplePassword().contains(" ")) {
+			return ResultData.build().error(
+					 this.getResString("people.password") + this.getResString("people.space"));
+		}
+
+		// 获取用户session
+		PeopleEntity curPeople = peopleBiz.getById(getPeopleBySession().getId());
+		if (StringUtils.isBlank(people.getPeopleOldPassword())) {
+			// 用户或密码不能为空
+			return ResultData.build().error(
+					this.getResString("err.empty", this.getResString("people.old.password")));
+		}
+		// 将用户输入的原始密码用MD5加密再和数据库中的进行比对
+		if (!curPeople.getPeoplePassword().equals(SecureUtil.md5(people.getPeopleOldPassword()))) {
+			// 用户或密码不能为空
+			return ResultData.build().error(
+					this.getResString("err.error", this.getResString("people.password")));
+		}
+		// 执行修改
+		curPeople.setPeoplePassword(SecureUtil.md5(people.getPeoplePassword()));
+		peopleBiz.updateById(curPeople);
+		return ResultData.build().success();
+	}
+
+	@Operation(summary = "修改手机号接口")
+	@PostMapping(value = "/changePhone")
+	@Parameters({
+		@Parameter(name = "peoplePassword", description = "用户密码", required =  true, in = ParameterIn.QUERY),
+		@Parameter(name = "peopleCode", description = "手机验证码", required =  true, in = ParameterIn.QUERY)
+	})
+	@ResponseBody
+	@PeopleLogAnn(title = "修改手机号", businessType = PeopleLogTypeEnum.UPDATE)
+	public ResultData changePhone(@ModelAttribute @Parameter(hidden = true) PeopleEntity people, HttpServletRequest request,
+			HttpServletResponse response) {
+		// 获取用户发送验证码session
+		PeopleEntity _people = (PeopleEntity) BasicUtil.getSession( SessionConstEnum.SEND_CODE_SESSION);
+		PeopleEntity peopleSession = this.getPeopleBySession();
+		// 判断手机是否已经存在
+		if (StringUtils.isBlank(people.getPeoplePhone())) {
+			return ResultData.build().error(
+					this.getResString("err.empty", this.getResString("people.phone")));
+		}
+		// 如果手机号码已经绑定过就需要验证手机短信吗
+		if (_people.getPeoplePhoneCheck() == PeopleEnum.PHONE_CHECK.toInt()) {
+			// 判断用户输入的验证是否正确
+			if (!people.getPeopleCode().equals(_people.getPeopleCode())) {
+				// 返回错误信息
+				return ResultData.build().error(
+						this.getResString("err.error", this.getResString("people.phone.code")));
+			}
+		}
+		people.setId(peopleSession.getId());
+		people.setPeoplePhone(people.getPeoplePhone());
+		peopleBiz.updateEntity(people);
+		return ResultData.build().success();
+	}
+
+	@Operation(summary = "验证用户短信、邮箱验证码是否正确接口")
+	@Parameter(name = "peopleCode", description = "手机验证码", required =  true, in = ParameterIn.QUERY)
+	@PostMapping(value = "/checkPeopleCode")
+	@ResponseBody
+	public ResultData checkPeopleCode(@ModelAttribute @Parameter(hidden = true) PeopleEntity people, HttpServletRequest request,
+			HttpServletResponse response) {
+		// 获取session中的用户实体
+		PeopleEntity _people = this.getPeopleBySession();
+		PeopleEntity _temp = peopleBiz.getByPeople(_people);
+		if (people.getPeopleCode().equals(_temp.getPeopleCode())) {
+			return ResultData.build().success();
+		} else {
+			return ResultData.build().error();
+		}
+	}
+
+	@Operation(summary = "读取当前登录用户的基本信息 用户信息接口")
+	@GetMapping("/info")
+	@ResponseBody
+	public ResultData info(HttpServletRequest request, HttpServletResponse response) {
+		// 得到登录后session中的用户实体值
+		PeopleEntity people = this.getPeopleBySession();
+		// 返回用户信息
+		return ResultData.build().success(people);
+	}
+
+	@Operation(summary = "退出登录接口")
+	@GetMapping(value = "/quit")
+	@ResponseBody
+	public ResultData quit(HttpServletRequest request, HttpServletResponse response) {
+		// 移除当前用户
+		SecurityUtils.getSubject().logout();
+		return ResultData.build().success();
+	}
+
+	@Operation(summary = "更新用户邮箱或手机号接口")
+	@Parameters({
+		@Parameter(name = "peopleMail", description = "用户邮箱", required =  false, in = ParameterIn.QUERY),
+		@Parameter(name = "peoplePhone", description = "手机号", required =  false, in = ParameterIn.QUERY)
+	})
+	@PostMapping(value = "/update")
+	@ResponseBody
+	@PeopleLogAnn(title = "更新用户邮箱或手机号接口", businessType = PeopleLogTypeEnum.UPDATE)
+	public ResultData update(@ModelAttribute @Parameter(hidden = true) PeopleEntity people, HttpServletRequest request, HttpServletResponse response) {
+		if (people == null) {
+			// 未填写信息返回错误信息
+			return ResultData.build().error(
+					this.getResString("err.empty", this.getResString("people")));
+		}
+		String peopleId = this.getPeopleBySession().getId();
+		PeopleEntity _people = peopleBiz.getById(peopleId);
+
+		if (_people.getPeopleMailCheck() == PeopleEnum.MAIL_CHECK.toInt()) {
+			people.setPeopleMail(null);
+		}
+		if (_people.getPeoplePhoneCheck() == PeopleEnum.PHONE_CHECK.toInt()) {
+			people.setPeoplePhone(null);
+		}
+		_people.setPeoplePhone(people.getPeoplePhone());
+		_people.setPeopleMail(people.getPeopleMail());
+		peopleBiz.updateById(_people);
+		// 返回更新成功
+		return ResultData.build().success();
+	}
+
+	@Operation(summary = "前端会员中心所有页面都可以使用该方法 支持参数传递与解析,例如页面中有参数id=10 传递过来,跳转页面可以使用{id/}获取该参数")
+	@Parameter(name = "diy", description = "id", required =  true, in = ParameterIn.PATH)
+	@ResponseBody
+	@GetMapping(value = "/{diy}")
+	public String diy(@PathVariable(value = "diy") String diy, HttpServletRequest req, HttpServletResponse resp) {
+		Map<String, Object> map = BasicUtil.assemblyRequestMap();
+
+		//站点编号
+		if (BasicUtil.getWebsiteApp() != null) {
+			map.put(ParserUtil.APP_DIR, BasicUtil.getWebsiteApp().getAppDir());
+			map.put(ParserUtil.URL, BasicUtil.getWebsiteApp().getAppHostUrl());
+			map.put(ParserUtil.APP_ID, BasicUtil.getWebsiteApp().getAppId());
+		} else {
+			map.put(ParserUtil.URL, BasicUtil.getUrl());
+			map.put(ParserUtil.APP_DIR, BasicUtil.getApp().getAppDir());
+		}
+		String contextPath = BasicUtil.getContextPath();
+		if (StringUtils.isNotBlank(contextPath) && "/".equalsIgnoreCase(contextPath)) {
+			contextPath = "";
+		}
+
+		map.putIfAbsent("contextPath", contextPath);
+		map.put(ParserUtil.IS_DO,false);
+		map.put(ParserUtil.HTML,htmlDir);
+
+		//解析后的内容
+		String content = "";
+		PageEntity page = new PageEntity();
+		page.setPageKey("people/"+diy);
+		//根据请求路径查询模版文件
+		PageEntity _page = (PageEntity) pageBiz.getEntity(page);
+		if(ObjectUtil.isNull(_page)){
+			// 通过抛异常方式构建页面提示用户错误
+			throw new BusinessException(getResString("templet.file"));
+		}
+		try {
+			content = ParserUtil.rendering(_page.getPagePath(), map);
+		} catch (TemplateNotFoundException e) {
+			e.printStackTrace();
+		} catch (MalformedTemplateNameException e) {
+			e.printStackTrace();
+		} catch (ParseException e) {
+			e.printStackTrace();
+		} catch (IOException e) {
+			e.printStackTrace();
+		}
+		return content;
+	}
+
+}

+ 289 - 0
src/main/java/net/mingsoft/people/action/people/PeopleUserAction.java

@@ -0,0 +1,289 @@
+/**
+ * Copyright (c) 2012-present 铭软科技(mingsoft.net)
+ * 本软件及相关文档文件(以下简称“软件”)的版权归 铭软科技 所有
+ * 遵循 铭软科技《服务协议》中的《保密条款》
+ */
+
+
+
+
+package net.mingsoft.people.action.people;
+
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.collection.CollectionUtil;
+import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.Parameters;
+import io.swagger.v3.oas.annotations.enums.ParameterIn;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import net.mingsoft.base.entity.ResultData;
+import net.mingsoft.mdiy.biz.IModelBiz;
+import net.mingsoft.mdiy.constant.e.ModelCustomTypeEnum;
+import net.mingsoft.mdiy.entity.ModelEntity;
+import net.mingsoft.people.action.BaseAction;
+import net.mingsoft.people.annotation.PeopleLogAnn;
+import net.mingsoft.people.bean.PeopleBean;
+import net.mingsoft.people.biz.IPeopleBiz;
+import net.mingsoft.people.biz.IPeopleUserBiz;
+import net.mingsoft.people.constant.e.PeopleEnum;
+import net.mingsoft.people.constant.e.PeopleLogTypeEnum;
+import net.mingsoft.people.entity.PeopleEntity;
+import net.mingsoft.people.entity.PeopleUserEntity;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ *
+ * 铭飞会员系统 详细的用户信息
+ * @author 铭飞开发团队
+ * @version
+ * 版本号:0.0<br/>
+ * 创建日期:2017-8-23 10:10:22<br/>
+ * 历史修订:<br/>
+ */
+@Tag(name = "前端-用户-会员模块接口")
+@Controller("webPeopleUser")
+@RequestMapping("/people/user")
+public class PeopleUserAction extends BaseAction {
+
+	/**
+	 * 注入用户详细信息业务层
+	 */
+	@Autowired
+	private IPeopleUserBiz peopleUserBiz;
+
+	/**
+	 * 注入用户业务层
+	 */
+	@Autowired
+	private IPeopleBiz peopleBiz;
+
+	@Autowired
+	private IModelBiz modelBiz;
+
+	@Operation(summary = "读取当前登录用户的基本信息接口")
+	@GetMapping("/info")
+	@ResponseBody
+	public ResultData info(HttpServletRequest request, HttpServletResponse response) {
+		// 获取用户session
+		PeopleEntity people = this.getPeopleBySession();
+		PeopleBean peopleUser = peopleBiz.getPeopleById(people.getId());
+		if (peopleUser == null) {
+			// 没用用户详细信息
+			return ResultData.build().error();
+		}
+
+		Map<String, Object> peopleMap = BeanUtil.beanToMap(peopleUser);
+
+		// 移除掉会员密码
+		peopleMap.remove("peoplePassword");
+
+		LambdaQueryWrapper<ModelEntity> wrapper = new LambdaQueryWrapper<>();
+		wrapper.eq(ModelEntity::getModelCustomType, ModelCustomTypeEnum.MODEL.getLabel());
+		wrapper.eq(ModelEntity::getModelType,"people");
+		ModelEntity peopleModel = modelBiz.getOne(wrapper);
+
+
+		if (peopleModel == null){
+			return ResultData.build().success(peopleMap);
+		}
+		List<Map<String, Object>> peopleModelDataList = this.modelBiz.queryForList(StrUtil.format("select * from {} where link_id = ?", peopleModel.getModelTableName()), people.getId());
+		if (CollectionUtil.isEmpty(peopleModelDataList)){
+			return ResultData.build().success(peopleMap);
+		}
+
+		Map<String, Object> peopleModelData = peopleModelDataList.get(0);
+
+		// TODO: 2025/8/11 防止peopleId会被模型ID覆盖
+		peopleModelData.putAll(peopleMap);
+
+		// 返回用户详细信息
+		return ResultData.build().success(peopleModelData);
+	}
+
+	@Operation(summary = "更新用户信息接口")
+	@Parameters({
+		@Parameter(name = "puRealName", description = "用户真实名称", required = false, in = ParameterIn.QUERY),
+		@Parameter(name = "puAddress", description = "用户地址", required = false, in = ParameterIn.QUERY),
+		@Parameter(name = "puIcon", description = "用户头像图标地址", required = false, in = ParameterIn.QUERY),
+		@Parameter(name = "puNickname", description = "用户昵称", required = false, in = ParameterIn.QUERY),
+		@Parameter(name = "puSex", description = "用户性别(0.未知、1.男、2.女)", required = false, in = ParameterIn.QUERY),
+		@Parameter(name = "puBirthday", description = "用户出生年月日", required = false, in = ParameterIn.QUERY),
+		@Parameter(name = "puCard", description = "身份证", required = false, in = ParameterIn.QUERY),
+		@Parameter(name = "puProvince", description = "省", required = false, in = ParameterIn.QUERY),
+		@Parameter(name = "puCity", description = "城市", required = false, in = ParameterIn.QUERY),
+		@Parameter(name = "puDistrict", description = "区", required = false, in = ParameterIn.QUERY),
+		@Parameter(name = "puStreet", description = "街道", required = false, in = ParameterIn.QUERY),
+	})
+	@PostMapping("/update")
+	@ResponseBody
+	public ResultData update(@ModelAttribute @Parameter(hidden = true) PeopleBean peopleUser, HttpServletRequest request,
+							 HttpServletResponse response) {
+		if (peopleUser == null) {
+			// 未填写信息返回错误信息
+			return ResultData.build().error(
+					this.getResString("err.empty", this.getResString("people")));
+		}
+		String peopleId = this.getPeopleBySession().getId();
+		peopleUser.setId(peopleId);
+		peopleUser.setPeopleId(peopleId);
+		//以免用户修改登录账号信息,邮箱、手机
+		peopleUser.setPeoplePhone(null);
+		peopleUser.setPeoplePhoneCheck(-1);
+		peopleUser.setPeopleName(null);
+		peopleUser.setPeopleMail(null);
+		peopleUser.setPeopleMailCheck(-1);
+		PeopleBean pue = peopleBiz.getPeopleById(peopleId);
+		if (pue == null) {
+			this.peopleBiz.savePeople(peopleUser);
+		} else {
+			peopleBiz.updatePeople(peopleUser);
+		}
+		// 返回更新成功
+		return ResultData.build().success( this.getResString("success"));
+	}
+	@Operation(summary = "更新邮箱")
+	@Parameters({
+		@Parameter(name = "peopleMail", description = "邮箱", required = false, in = ParameterIn.QUERY),
+	})
+	@PostMapping("/updateMail")
+	@ResponseBody
+	@PeopleLogAnn(title = "更新邮箱", businessType = PeopleLogTypeEnum.UPDATE)
+	public ResultData updateMail(String peopleMail, HttpServletRequest request,
+			HttpServletResponse response) {
+		if (StrUtil.isBlank(peopleMail)) {
+			// 未填写信息返回错误信息
+			return ResultData.build().error(
+					this.getResString("err.empty", this.getResString("people.mail")));
+		}
+		if(StringUtils.isNotEmpty(peopleMail)){
+			PeopleEntity peopleByMail = peopleBiz.getEntityByMailOrPhone(peopleMail);
+			if(ObjectUtil.isNotNull(peopleByMail)){
+				return ResultData.build().error( this.getResString("err.exist", this.getResString("people.mail")));
+			}
+		}
+		String peopleId = this.getPeopleBySession().getId();
+		PeopleBean peopleUser =new PeopleBean();
+		peopleUser.setId(peopleId);
+		peopleUser.setPeopleId(peopleId);
+		//以免用户修改登录账号信息,邮箱、手机
+		peopleUser.setPeopleMail(peopleMail);
+		peopleUser.setPeopleMailCheck(PeopleEnum.MAIL_CHECK);
+		peopleBiz.updatePeople(peopleUser);
+		// 返回更新成功
+		return ResultData.build().success( this.getResString("success"));
+	}
+
+	@Operation(summary = "更新手机号")
+	@Parameters({
+			@Parameter(name = "peoplePhone", description = "手机号码", required = false, in = ParameterIn.QUERY),
+	})
+	@PostMapping("/updatePhone")
+	@ResponseBody
+	@PeopleLogAnn(title = "更新手机号", businessType = PeopleLogTypeEnum.UPDATE)
+	public ResultData updatePhone(String peoplePhone, HttpServletRequest request,
+								 HttpServletResponse response) {
+		if (StrUtil.isBlank(peoplePhone)) {
+			// 未填写信息返回错误信息
+			return ResultData.build().error(
+					this.getResString("err.empty", this.getResString("people.phone")));
+		}
+		if(StringUtils.isNotEmpty(peoplePhone)){
+			PeopleEntity peopleByMail = peopleBiz.getEntityByMailOrPhone(peoplePhone);
+			if(ObjectUtil.isNotNull(peopleByMail)){
+				return ResultData.build().error( this.getResString("err.exist", this.getResString("people.phone")));
+			}
+		}
+		String peopleId = this.getPeopleBySession().getId();
+		PeopleBean peopleUser =new PeopleBean();
+		peopleUser.setId(peopleId);
+		peopleUser.setPeopleId(peopleId);
+		//以免用户修改登录账号信息,邮箱、手机
+		peopleUser.setPeoplePhone(peoplePhone);
+		peopleUser.setPeoplePhoneCheck(PeopleEnum.PHONE_CHECK);
+		peopleBiz.updatePeople(peopleUser);
+		// 返回更新成功
+		return ResultData.build().success( this.getResString("success"));
+	}
+
+	/**
+	 * 推荐使用update
+	 */
+	@Deprecated
+	@Operation(summary = "保存用户头像(包含头像)接口")
+	@Parameters({
+		@Parameter(name = "puIcon", description = "用户头像", required = true, in = ParameterIn.QUERY),
+		@Parameter(name = "peopleMail", description = "用户手机", required = false, in = ParameterIn.QUERY),
+		@Parameter(name = "peoplePhone", description = "用户邮箱", required = false, in = ParameterIn.QUERY)
+	})
+	@PostMapping("/saveUserIcon")
+	@ResponseBody
+	public ResultData saveUserIcon(@ModelAttribute @Parameter(hidden = true) PeopleBean peopleUser, HttpServletRequest request,
+			HttpServletResponse response) {
+		if (peopleUser == null) {
+			// 未填写信息返回错误信息
+			return ResultData.build().error(this.getResString("people.user.msg.null.error"));
+		}
+		// 获取用户session
+		PeopleEntity people = this.getPeopleBySession();
+		peopleUser.setId(people.getId());
+		PeopleUserEntity oldPeopleUser = peopleUserBiz.lambdaQuery().eq(PeopleUserEntity::getPeopleId,people.getId()).one();
+		String imgPath = peopleUser.getPuIcon().trim(); // 新图片路径
+		if (!StringUtils.isBlank(imgPath)) {
+			oldPeopleUser.setPuIcon(imgPath);
+		}
+		peopleUserBiz.updateById(oldPeopleUser);
+		// 更新手机和电子邮件
+		if (!StringUtils.isBlank(peopleUser.getPeopleMail())) {
+			people.setPeopleMail(peopleUser.getPeopleMail());
+		}
+		if (!StringUtils.isBlank(peopleUser.getPeoplePhone())) {
+			people.setPeoplePhone(peopleUser.getPeoplePhone());
+		}
+
+		this.peopleBiz.save(people);
+		// 返回用户添加成功
+		return ResultData.build().success(
+				this.getResString("people.user.save.msg.success"));
+	}
+
+	/**
+	 * 推荐使用update
+	 */
+	@Deprecated
+	@Operation(summary = "更新用户信息(包含头像)接口")
+	@Parameters({
+		@Parameter(name = "puIcon", description = "用户头像", required = false, in = ParameterIn.QUERY)
+	})
+	@PostMapping("/updateUserIcon")
+	@ResponseBody
+	public ResultData updateUserIcon(@ModelAttribute @Parameter(hidden = true) PeopleUserEntity peopleUser, HttpServletRequest request,
+			HttpServletResponse response) {
+		if (peopleUser == null) {
+			// 未填写信息返回错误信息
+			return ResultData.build().error(this.getResString("people.user.msg.null.error"));
+		}
+		// 获取用户session
+		PeopleEntity people = this.getPeopleBySession();
+		PeopleUserEntity oldPeopleUser = peopleUserBiz.lambdaQuery().eq(PeopleUserEntity::getPeopleId,people.getId()).one();
+		String imgPath = peopleUser.getPuIcon().trim();
+		if (!StringUtils.isBlank(imgPath)) {
+			oldPeopleUser.setPuIcon(imgPath);
+		}
+		this.peopleUserBiz.updateById(oldPeopleUser);
+		// 返回更新成功
+		return ResultData.build().success(this.getResString("people.user.update.msg.success"));
+	}
+
+
+}

+ 48 - 0
src/main/java/net/mingsoft/people/annotation/PeopleLogAnn.java

@@ -0,0 +1,48 @@
+/**
+ * Copyright (c) 2012-present 铭软科技(mingsoft.net)
+ * 本软件及相关文档文件(以下简称“软件”)的版权归 铭软科技 所有
+ * 遵循 铭软科技《服务协议》中的《保密条款》
+ */
+
+
+
+
+
+
+package net.mingsoft.people.annotation;
+
+import net.mingsoft.people.constant.e.PeopleLogTypeEnum;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * @author 铭软科技
+ * 创建日期:2023-6-5 11:48:14<br/>
+ * 历史修订:<br/>
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.METHOD)
+public @interface PeopleLogAnn {
+
+    /**
+     * 会员日志标题
+     * @return
+     */
+    String title() default "";
+
+    /**
+     * 业务类型
+     * @return
+     */
+    PeopleLogTypeEnum businessType() default PeopleLogTypeEnum.OTHER;
+
+    /**
+     * 是否保存请求的参数,如果data不需要可以设置false减少日志表的内容
+     * @return
+     */
+    boolean saveRequestData() default true;
+
+}

+ 189 - 0
src/main/java/net/mingsoft/people/aop/FileVerifyAop.java

@@ -0,0 +1,189 @@
+/**
+ * Copyright (c) 2012-present 铭软科技(mingsoft.net)
+ * 本软件及相关文档文件(以下简称“软件”)的版权归 铭软科技 所有
+ * 遵循 铭软科技《服务协议》中的《保密条款》
+ */
+
+
+
+
+
+
+package net.mingsoft.people.aop;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.exceptions.UtilException;
+import cn.hutool.core.io.FileTypeUtil;
+import cn.hutool.core.io.FileUtil;
+import cn.hutool.core.io.file.FileNameUtil;
+import cn.hutool.core.util.IdUtil;
+import cn.hutool.core.util.StrUtil;
+import cn.hutool.core.util.ZipUtil;
+import net.mingsoft.base.entity.ResultData;
+import net.mingsoft.base.exception.BusinessException;
+import net.mingsoft.basic.aop.BaseAop;
+import net.mingsoft.basic.bean.UploadConfigBean;
+import net.mingsoft.config.MSProperties;
+import net.mingsoft.mdiy.util.ConfigUtil;
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.aspectj.lang.JoinPoint;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Before;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/**
+ * 会员层验证上传文件是否合法的aop
+ */
+@Component("peopleFileVerify")
+@Aspect
+public class FileVerifyAop extends BaseAop {
+
+    private static final Logger LOG = LoggerFactory.getLogger(FileVerifyAop.class);
+
+    /**
+     * 会员层 web端上传文件的时候,将验证文件后缀是否合法。适配开源与高级版本
+     * @param joinPoint
+     * @return
+     * @throws Throwable
+     */
+    @Before("execution(* net.mingsoft.people.action.people.FileAction.upload(..))")
+    public void peopleWebUploadAop(JoinPoint joinPoint) throws Throwable {
+        UploadConfigBean bean = super.getType(joinPoint, UploadConfigBean.class);
+        if (bean.getFile() == null) {
+            throw new BusinessException("文件不能为空!");
+        }
+        //检查文件名是否为空
+        String uploadFileName = FileNameUtil.cleanInvalid(bean.getFile().getOriginalFilename());
+        if (StringUtils.isBlank(uploadFileName) || StringUtils.isBlank(FileNameUtil.mainName(uploadFileName))) {
+            throw new BusinessException("文件名不能为空!");
+        }
+        if (uploadFileName.lastIndexOf(".") < 0) {
+            LOG.info("文件格式错误:{}", uploadFileName);
+            throw new BusinessException("文件名错误");
+        }
+        String mimeType = FileUtil.getSuffix(uploadFileName);
+        if ("zip".equalsIgnoreCase(mimeType) || "zip".equalsIgnoreCase(FileNameUtil.extName(uploadFileName))){
+            checkZip(bean.getFile());
+        }else{
+            checkFile(bean.getFile());
+        }
+    }
+
+
+    /**
+     * 检查普通文件后缀(配合文件上传配置使用,开源版本在upload方法中以做了处理) 会员层默认web层的上传
+     */
+    private void checkFile(MultipartFile file) throws IOException {
+        InputStream inputStream = file.getInputStream();
+        try {
+            Map<String,String> fileConfigMap = ConfigUtil.getMap("文件上传配置");
+            if(CollUtil.isNotEmpty(fileConfigMap)){
+                //允许上传的格式
+                List<String> types = new ArrayList<>();
+                String[] fileTypes = ConfigUtil.getString("文件上传配置","webFileType","").split(",");
+                // 自定义配置中禁止的文件类型
+                String[] errorType = ConfigUtil.getString("文件上传配置", "uploadDenied", "exe,jsp").split(",");
+                List<String> errorTypeList = Arrays.asList(errorType);
+                CollUtil.addAll(types,fileTypes);
+                //统一转换成小写
+                types = types.stream().map(String::toLowerCase).collect(Collectors.toList());
+                //文件的真实类型
+                String fileType = FileTypeUtil.getType(inputStream);
+                if (!types.contains(fileType)||errorTypeList.contains(fileType)){
+                    throw new BusinessException(StrUtil.format("名称为:{},类型为:{}的文件禁止上传",file.getName(),fileType));
+                }
+                long fileSize = ConfigUtil.getInt("文件上传配置", "webFileSize", 20);
+                // 检测文件是否过大
+                if (file.getSize() > (fileSize * 1024)) {
+                    throw new BusinessException("上传文件大于"+fileSize+"KB");
+                }
+            }
+        }catch (UtilException e) {
+            LOG.error(e.getMessage(), e);
+            e.printStackTrace();
+        } finally {
+            IOUtils.closeQuietly(inputStream);
+        }
+    }
+
+    /**
+     * 检查压缩包
+     */
+    private void checkZip(MultipartFile multipartFile) throws Exception{
+        //创建临时解压文件夹
+        File tempFilePath = FileUtil.mkdir(FileUtil.getTmpDirPath()+"/Zip"+ IdUtil.simpleUUID());
+        File zipFile = FileUtil.file(tempFilePath.getAbsolutePath() + "/" + IdUtil.simpleUUID() +".zip");
+        InputStream inputStream = multipartFile.getInputStream();
+        FileUtils.copyInputStreamToFile(inputStream, zipFile);
+
+        try {
+            ZipUtil.unzip(zipFile,tempFilePath);
+            //获取文件夹下所有文件
+            List<File> files = FileUtil.loopFiles(tempFilePath);
+            //移除压缩包自身
+            files.remove(zipFile);
+
+            Map<String,String> fileConfigMap = ConfigUtil.getMap("文件上传配置");
+
+            if(CollUtil.isEmpty(fileConfigMap)){
+                // 开源版本
+                List<String> deniedList = StringUtils.isBlank(MSProperties.upload.denied)? new ArrayList<>() : Arrays.stream(MSProperties.upload.denied.split(",")).map(String::toLowerCase).collect(Collectors.toList());
+                for (File file : files) {
+                    //文件的真实类型
+                    String fileType = FileTypeUtil.getType(file);
+                    //通过yml的配置检查文件格式是否合法
+                    if (deniedList.contains(fileType)){
+                        throw new BusinessException(StrUtil.format("压缩包内文件{}的类型{}禁止上传",file.getName(),fileType));
+                    }
+                }
+            }else{
+                //高级版本
+                List<String> types = new ArrayList<>();
+                //会员层默认web层的上传
+                String[] fileTypes = ConfigUtil.getString("文件上传配置","webFileType","").split(",");
+                // 自定义配置中禁止的文件类型
+                String[] errorType = ConfigUtil.getString("文件上传配置", "uploadDenied", "exe,jsp").split(",");
+                List<String> errorTypeList = Arrays.asList(errorType);
+                CollUtil.addAll(types,fileTypes);
+                //统一转换成小写
+                types = types.stream().map(String::toLowerCase).collect(Collectors.toList());
+                // 自定义配置中大小校验
+                long fileSize = ConfigUtil.getInt("文件上传配置", "webFileSize", 20);
+                // 检测文件是否过大
+                if (multipartFile.getSize() > (fileSize * 1024)) {
+                    throw new BusinessException("上传文件大于" + fileSize + "KB");
+                }
+                for (File file : files) {
+                    //文件的真实类型
+                    String fileType = FileTypeUtil.getType(file);
+                    if (!types.contains(fileType) || errorTypeList.contains(fileType)){
+                        throw new BusinessException(StrUtil.format("压缩包内名称为:{},类型为:{}的文件禁止上传",file.getName(),fileType));
+                    }
+                }
+            }
+
+
+        } catch (UtilException e) {
+            LOG.error(e.getMessage(), e);
+            e.printStackTrace();
+        } finally {
+            IOUtils.closeQuietly(inputStream);
+        }
+    }
+
+
+}

+ 183 - 0
src/main/java/net/mingsoft/people/aop/PeopleLogAop.java

@@ -0,0 +1,183 @@
+/**
+ * Copyright (c) 2012-present 铭软科技(mingsoft.net)
+ * 本软件及相关文档文件(以下简称“软件”)的版权归 铭软科技 所有
+ * 遵循 铭软科技《服务协议》中的《保密条款》
+ */
+
+
+
+
+package net.mingsoft.people.aop;
+
+import cn.hutool.core.lang.Filter;
+import cn.hutool.core.lang.mutable.MutablePair;
+import cn.hutool.core.util.BooleanUtil;
+import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.json.JSONUtil;
+import jakarta.servlet.http.HttpServletRequest;
+import net.mingsoft.base.entity.ResultData;
+import net.mingsoft.basic.aop.BaseAop;
+import net.mingsoft.basic.util.BasicUtil;
+import net.mingsoft.basic.util.IpUtils;
+import net.mingsoft.basic.util.SpringUtil;
+import net.mingsoft.people.annotation.PeopleLogAnn;
+import net.mingsoft.people.biz.IPeopleLogBiz;
+import net.mingsoft.people.constant.e.PeopleLogTypeEnum;
+import net.mingsoft.people.entity.PeopleLogEntity;
+import net.mingsoft.people.util.PeopleUtil;
+import org.apache.commons.lang3.StringUtils;
+import org.aspectj.lang.JoinPoint;
+import org.aspectj.lang.annotation.AfterReturning;
+import org.aspectj.lang.annotation.AfterThrowing;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Pointcut;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.MediaType;
+import org.springframework.stereotype.Component;
+import org.springframework.web.context.request.RequestAttributes;
+import org.springframework.web.context.request.RequestContextHolder;
+
+import java.util.Date;
+import java.util.Map;
+
+/**
+ * @author by 铭飞开源团队
+ * @Description TODO
+ * @date 2019/11/20 10:28
+ */
+@Aspect
+@Component
+public class PeopleLogAop extends BaseAop {
+
+    @Autowired
+    private IPeopleLogBiz peopleLogBiz;
+
+
+    public String getPeopleId() {
+        try {
+            return PeopleUtil.getPeopleBean().getId();
+        } catch (Exception e) {
+            return "未知";
+        }
+    }
+
+
+
+    //保存和更新
+    @Pointcut("@annotation(net.mingsoft.people.annotation.PeopleLogAnn)")
+    public void peopleLogCut() {
+    }
+
+    @AfterReturning(pointcut = "peopleLogCut()", returning = "result")
+    public void peopleLogCut(JoinPoint joinPoint, ResultData result) {
+        handleLog(joinPoint, null, result);
+    }
+
+    /**
+     * 拦截异常操作
+     *
+     * @param joinPoint 切点
+     * @param e 异常
+     */
+    @AfterThrowing(value = "peopleLogCut()", throwing = "e")
+    public void doAfterThrowing(JoinPoint joinPoint, Exception e)
+    {
+        handleLog(joinPoint, e, null);
+    }
+
+    /**
+     * 成功状态
+     */
+    private static final String SUCCESS="success";
+    /**
+     * 失败状态
+     */
+    private static final String ERROR="error";
+
+    protected void handleLog(final JoinPoint joinPoint, final Exception exception, Object result) {
+        try {
+            // 获得注解
+            PeopleLogAnn controllerLog = getAnnotation(joinPoint, PeopleLogAnn.class);
+            if (controllerLog == null) {
+                return;
+            }
+            PeopleLogEntity peopleLogEntity = new PeopleLogEntity();
+            // 默认成功
+            peopleLogEntity.setLogStatus(SUCCESS);
+
+            // 请求IP
+            String ip = BasicUtil.getIp();
+            peopleLogEntity.setLogIp(ip);
+            // 获取地区
+            String address = IpUtils.getRealAddressByIp(ip);
+            peopleLogEntity.setLogAddr(address);
+
+            //设置返回参数
+            peopleLogEntity.setLogResult(JSONUtil.parseObj(result).toJSONString(0, new Filter<MutablePair<Object, Object>>() {
+                @Override
+                public boolean accept(MutablePair<Object, Object> objectObjectMutablePair) {
+                    return !objectObjectMutablePair.getKey().toString().equalsIgnoreCase("id");
+                }
+            }));
+
+            // 获取会员信息
+            peopleLogEntity.setPeopleId(getPeopleId());
+
+            if (exception != null) {
+                // 保存异常信息
+                peopleLogEntity.setLogStatus(ERROR);
+                peopleLogEntity.setlogErrorMsg(StringUtils.substring(exception.getMessage(), 0, 4000));
+            }
+
+            // 登录失败特殊处理
+            if (PeopleLogTypeEnum.LOGIN.getLabel().equalsIgnoreCase(controllerLog.businessType().label)){
+                ResultData resultData = (ResultData) result;
+                if (resultData != null && !BooleanUtil.toBoolean(resultData.get("result").toString())) {
+                    peopleLogEntity.setLogStatus(ERROR);
+                    peopleLogEntity.setlogErrorMsg(String.valueOf(resultData.get("msg")));
+                }
+            }
+
+            // 设置类型
+            peopleLogEntity.setLogType(controllerLog.businessType().name().toLowerCase());
+            // 设置日志标题
+            peopleLogEntity.setLogTitle(controllerLog.title());
+
+            RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
+            HttpServletRequest request = (HttpServletRequest) requestAttributes
+                    .resolveReference(RequestAttributes.REFERENCE_REQUEST);
+            String header = request.getHeader("User-Agent");
+            if (StringUtils.isNotEmpty(header)) {
+                peopleLogEntity.setLogInfo(header);
+            } else {
+                peopleLogEntity.setLogInfo("未知详情");
+            }
+
+            // 是否需要保存request,参数和值
+            if (controllerLog.saveRequestData()){
+                // 获取参数的信息,传入到数据库中。
+                boolean isJson =StringUtils.isNotBlank(SpringUtil.getRequest().getContentType())&& MediaType.valueOf(SpringUtil.getRequest().getContentType()).includes(MediaType.APPLICATION_JSON);
+                //如果是json请求参数需要获取方法体上的参数
+                if(isJson){
+                    Object jsonParam = getJsonParam(joinPoint);
+                    if(ObjectUtil.isNotNull(jsonParam)){
+                        String jsonString = JSONUtil.toJsonPrettyStr(jsonParam);
+                        peopleLogEntity.setLogParam(jsonString);
+                    }
+                }else {
+                    Map<String, String[]> map = SpringUtil.getRequest().getParameterMap();
+                    String params = JSONUtil.toJsonPrettyStr(map);
+                    peopleLogEntity.setLogParam(params);
+                }
+            }
+            peopleLogEntity.setCreateDate(new Date());
+
+            peopleLogBiz.save(peopleLogEntity);
+        } catch (Exception exp) {
+            LOG.error("日志记录错误:{}", exp.getMessage());
+            exp.printStackTrace();
+        }
+    }
+
+
+}

+ 342 - 0
src/main/java/net/mingsoft/people/bean/PeopleBean.java

@@ -0,0 +1,342 @@
+/**
+ * Copyright (c) 2012-present 铭软科技(mingsoft.net)
+ * 本软件及相关文档文件(以下简称“软件”)的版权归 铭软科技 所有
+ * 遵循 铭软科技《服务协议》中的《保密条款》
+ */
+
+
+
+
+package net.mingsoft.people.bean;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import net.mingsoft.people.entity.PeopleEntity;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.util.Date;
+
+/**
+ * 
+ * 会员扩展数据,用于后台数据查询
+ * @author 铭飞开发团队
+ * @version 
+ * 版本号:0.0<br/>
+ * 创建日期:2017-8-23 10:10:22<br/>
+ * 历史修订:<br/>
+ */
+public class PeopleBean extends PeopleEntity {
+
+
+	/**
+	 * 用户ID关联people表的(people_id)
+	 */
+	private String peopleId;
+	/**
+	 * 用户真实名称
+	 */
+	private String puRealName;
+	/**
+	 * 用户地址
+	 */
+	private String puAddress;
+
+	/**
+	 * 用户等级
+	 */
+	private String puLevel;
+
+	/**
+	 * 等级名称
+	 */
+	private String puLevelName;
+	/**
+	 * 用户头像图标地址
+	 */
+	private String puIcon;
+	/**
+	 * 用户昵称
+	 */
+	private String puNickname;
+	/**
+	 * 用户性别(0.未知、1.男、2.女)
+	 */
+	private Integer puSex;
+	/**
+	 * 用户出生年月日
+	 */
+	@DateTimeFormat(pattern = "yyyy-MM-dd")
+	@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd")
+	private Date puBirthday;
+	/**
+	 * 身份证
+	 */
+	private String puCard;
+
+	/**
+	 * 城市选择
+	 */
+	private Long provinceId;
+	/**
+	 * 省
+	 */
+	private String provinceName;
+	/**
+	 * 城市id
+	 */
+	private Long cityId;
+	/**
+	 * 城市
+	 */
+	private String cityName;
+	/**
+	 * 区id
+	 */
+	private Long countyId;
+	/**
+	 * 区
+	 */
+	private String countyName;
+
+
+
+	public String getPeopleId() {
+		return peopleId;
+	}
+
+	public void setPeopleId(String peopleId) {
+		this.peopleId = peopleId;
+	}
+
+	/**
+	 * 设置用户真实名称
+	 */
+	public void setPuRealName(String puRealName) {
+		this.puRealName = puRealName;
+	}
+
+	/**
+	 * 获取用户真实名称
+	 */
+	public String getPuRealName() {
+		return this.puRealName;
+	}
+
+	/**
+	 * 设置用户地址
+	 */
+	public void setPuAddress(String puAddress) {
+		this.puAddress = puAddress;
+	}
+
+	/**
+	 * 获取用户地址
+	 */
+	public String getPuAddress() {
+		return this.puAddress;
+	}
+
+	public String getPuLevel() {
+		return puLevel;
+	}
+
+	public void setPuLevel(String puLevel) {
+		this.puLevel = puLevel;
+	}
+
+	public String getPuLevelName() {
+		return puLevelName;
+	}
+
+	public void setPuLevelName(String puLevelName) {
+		this.puLevelName = puLevelName;
+	}
+
+	/**
+	 * 设置用户头像图标地址
+	 */
+	public void setPuIcon(String puIcon) {
+		this.puIcon = puIcon;
+	}
+
+	/**
+	 * 获取用户头像图标地址
+	 */
+	public String getPuIcon() {
+		return this.puIcon;
+	}
+
+	/**
+	 * 设置用户昵称
+	 */
+	public void setPuNickname(String puNickname) {
+		this.puNickname = puNickname;
+	}
+
+	/**
+	 * 获取用户昵称
+	 */
+	public String getPuNickname() {
+		return this.puNickname;
+	}
+
+	/**
+	 * 设置用户性别(0.未知、1.男、2.女)
+	 */
+	public void setPuSex(Integer puSex) {
+		this.puSex = puSex;
+	}
+
+	/**
+	 * 获取用户性别(0.未知、1.男、2.女)
+	 */
+	public Integer getPuSex() {
+		return this.puSex;
+	}
+
+	/**
+	 * 设置用户出生年月日
+	 */
+	public void setPuBirthday(Date puBirthday) {
+		this.puBirthday = puBirthday;
+	}
+
+	/**
+	 * 获取用户出生年月日
+	 */
+	public Date getPuBirthday() {
+		return this.puBirthday;
+	}
+
+	/**
+	 * 设置身份证
+	 */
+	public void setPuCard(String puCard) {
+		this.puCard = puCard;
+	}
+
+	/**
+	 * 获取身份证
+	 */
+	public String getPuCard() {
+		return this.puCard;
+	}
+	/**
+	 * 设置城市选择
+	 */
+	public void setProvinceId(Long provinceId) {
+		this.provinceId = provinceId;
+	}
+
+	/**
+	 * 获取城市选择
+	 */
+	public Long getProvinceId() {
+		return this.provinceId;
+	}
+	/**
+	 * 设置省
+	 */
+	public void setProvinceName(String provinceName) {
+		this.provinceName = provinceName;
+	}
+
+	/**
+	 * 获取省
+	 */
+	public String getProvinceName() {
+		return this.provinceName;
+	}
+	/**
+	 * 设置城市
+	 */
+	public void setCityName(String cityName) {
+		this.cityName = cityName;
+	}
+
+	/**
+	 * 获取城市
+	 */
+	public String getCityName() {
+		return this.cityName;
+	}
+	/**
+	 * 设置区
+	 */
+	public void setCountyName(String countyName) {
+		this.countyName = countyName;
+	}
+
+	/**
+	 * 获取区
+	 */
+	public String getCountyName() {
+		return this.countyName;
+	}
+	/**
+	 * 设置城市id
+	 */
+	public void setCityId(Long cityId) {
+		this.cityId = cityId;
+	}
+
+	/**
+	 * 获取城市id
+	 */
+	public Long getCityId() {
+		return this.cityId;
+	}
+	/**
+	 * 设置区id
+	 */
+	public void setCountyId(Long countyId) {
+		this.countyId = countyId;
+	}
+
+	/**
+	 * 获取区id
+	 */
+	public Long getCountyId() {
+		return this.countyId;
+	}
+
+
+
+
+	private String  peopleDateTimes;
+	
+	private String peopleDateStartTime;
+	
+	private String peopleDateEndTime;
+
+	public String getPeopleDateTimes() {
+		return peopleDateTimes;
+	}
+
+	public void setPeopleDateTimes(String peopleDateTimes) {
+		this.peopleDateTimes = peopleDateTimes;
+	}
+
+	public String getPeopleDateStartTime() {
+		if(peopleDateTimes != null && peopleDateTimes != "" ){
+			return peopleDateTimes.split("至")[0];
+		}
+		return peopleDateStartTime;
+	}
+
+	public void setPeopleDateStartTime(String startTime) {
+		this.peopleDateStartTime = startTime;
+	}
+
+	public String getPeopleDateEndTime() {
+		if(peopleDateTimes != null && peopleDateTimes != "" ){
+			return peopleDateTimes.split("至")[1];
+		}
+		return peopleDateEndTime;
+	}
+
+	public void setPeopleDateEndTime(String endTime) {
+		this.peopleDateEndTime = endTime;
+	}
+	
+	
+}

+ 36 - 0
src/main/java/net/mingsoft/people/bean/PeopleLogBean.java

@@ -0,0 +1,36 @@
+/**
+ * Copyright (c) 2012-present 铭软科技(mingsoft.net)
+ * 本软件及相关文档文件(以下简称“软件”)的版权归 铭软科技 所有
+ * 遵循 铭软科技《服务协议》中的《保密条款》
+ */
+
+package net.mingsoft.people.bean;
+
+import net.mingsoft.people.entity.PeopleLogEntity;
+
+/**
+ * 会员日志实体bean,用来时间搜索
+ */
+public class PeopleLogBean extends PeopleLogEntity {
+
+    private String startTime;
+
+    private String endTime;
+
+    public String getStartTime() {
+        return startTime;
+    }
+
+    public void setStartTime(String startTime) {
+        this.startTime = startTime;
+    }
+
+    public String getEndTime() {
+        return endTime;
+    }
+
+    public void setEndTime(String endTime) {
+        this.endTime = endTime;
+    }
+
+}

+ 37 - 0
src/main/java/net/mingsoft/people/bean/PeopleLoginBean.java

@@ -0,0 +1,37 @@
+/**
+ * Copyright (c) 2012-present 铭软科技(mingsoft.net)
+ * 本软件及相关文档文件(以下简称“软件”)的版权归 铭软科技 所有
+ * 遵循 铭软科技《服务协议》中的《保密条款》
+ */
+
+
+
+
+package net.mingsoft.people.bean;
+
+import net.mingsoft.people.entity.PeopleEntity;
+
+/**
+ * 
+ * 会员扩展数据,用于登录返回cookie
+ * @author 铭飞开发团队
+ * @version 
+ * 版本号:0.0<br/>
+ * 创建日期:2017-8-23 10:10:22<br/>
+ * 历史修订:<br/>
+ */
+public class PeopleLoginBean extends PeopleEntity{
+
+	private String  cookie;
+
+	public String getCookie() {
+		return cookie;
+	}
+
+	public void setCookie(String cookie) {
+		this.cookie = cookie;
+	}
+	
+	
+	
+}

+ 113 - 0
src/main/java/net/mingsoft/people/biz/IPeopleBiz.java

@@ -0,0 +1,113 @@
+/**
+ * Copyright (c) 2012-present 铭软科技(mingsoft.net)
+ * 本软件及相关文档文件(以下简称“软件”)的版权归 铭软科技 所有
+ * 遵循 铭软科技《服务协议》中的《保密条款》
+ */
+
+
+
+
+package net.mingsoft.people.biz;
+
+import net.mingsoft.base.biz.IBaseBiz;
+import net.mingsoft.people.bean.PeopleBean;
+import net.mingsoft.people.constant.e.LoginTypeEnum;
+import net.mingsoft.people.entity.PeopleEntity;
+import net.mingsoft.people.entity.PeopleUserEntity;
+
+import java.util.List;
+
+
+/**
+ * 
+ * 用户业务层,继承IBaseBiz
+ * @author 铭飞开发团队
+ * @version 
+ * 版本号:0.0<br/>
+ * 创建日期:2017-8-23 10:10:22<br/>
+ * 历史修订:<br/>
+ */
+public interface IPeopleBiz  extends IBaseBiz<PeopleEntity>{
+
+	/**
+	 * 后台管理页面查询用户基本信息与详细详细
+	 * @param peopleBean
+	 * @return
+	 */
+	List<PeopleBean> query(PeopleBean peopleBean);
+
+	/**
+	 * 根据会员ID获取用户基本、详细信息
+	 * @param id 用户ID
+	 * @return 用户实体
+	 */
+	PeopleBean getPeopleById(String id);
+
+
+	/**
+	 * 批量删除用户
+	 * @param peopleIds 用户id集合
+	 */
+	public void deletePeople(String[] peopleIds);
+	
+	/**
+	 * 更具用户实体获取用户信息,
+	 * @param people 用户实体,可以设置用户名、用户邮箱、用户手机号
+	 * @return 用户实体
+	 */
+	PeopleEntity getByPeople(PeopleEntity people);
+	
+
+	/**
+	 * 根据用户名(帐号,手机,邮箱)和验证码查询用户信息开始
+	 * @param userName 用户名
+	 * @param peopleCode 验证码
+	 * @return 用户实体
+	 */
+	PeopleEntity getEntityByCode(String userName, String peopleCode);
+	
+	/**
+	 * 根据用户用户名查询用户实体</br>
+	 * @param userName 用户名(注:手机号,邮箱)
+	 * @return 查询到的用户实体
+	 */
+	PeopleEntity getEntityByMailOrPhone(String userName);
+	
+	/**
+	 * 根据用户用户名查询用户实体</br>
+	 * @param userName 用户名(注:手机号,邮箱,用户名称都可作为用户名登录)
+	 * @return 查询到的用户实体
+	 */
+	public PeopleEntity getEntityByUserName(String userName);
+	
+
+	/**
+	 * 用户有子类添加
+	 * @param people 用户实体
+	 * @return 用户ID
+	 */
+	public int savePeople(PeopleBean people);
+	
+	/**
+	 * 根据用户ID进行用户实体的更新,用于有子类的更新操作
+	 * @param people 用户实体
+	 */
+	public void updatePeople(PeopleBean people);
+
+	/**
+	 * 判断账号是否存在,会依次判断类型 PeopleEntity、登陆账号、邮箱,只验证已经绑定的账号信息
+	 * @param people 这里的 loginName 可能是账号peopleName、手机号peoplePhone、邮箱peopleMail
+	 * @return   true:存在,false:不存在
+	 */
+	boolean isExists(PeopleBean people);
+
+
+	/**
+	 * 判断账号是否存在,方法里面通过组织 PeopleEntity 再调用 isExists(people) 方法进行验证
+	 * @param loginName 这里的 loginName 可能是账号、手机号、邮箱
+	 * @param loginType 登陆类型
+	 * @return   true:存在,false:不存在
+	 */
+	boolean isExists(String loginName, LoginTypeEnum loginType);
+
+}

+ 21 - 0
src/main/java/net/mingsoft/people/biz/IPeopleLogBiz.java

@@ -0,0 +1,21 @@
+/**
+ * Copyright (c) 2012-present 铭软科技(mingsoft.net)
+ * 本软件及相关文档文件(以下简称“软件”)的版权归 铭软科技 所有
+ * 遵循 铭软科技《服务协议》中的《保密条款》
+ */
+
+package net.mingsoft.people.biz;
+
+import net.mingsoft.base.biz.IBaseBiz;
+import net.mingsoft.people.entity.PeopleLogEntity;
+
+/**
+ * 会员日志业务
+ * @author 铭软科技
+ * 创建日期:2023-6-5 17:34:20<br/>
+ * 历史修订:<br/>
+ */
+public interface IPeopleLogBiz extends IBaseBiz<PeopleLogEntity> {
+
+
+}

+ 48 - 0
src/main/java/net/mingsoft/people/biz/IPeopleUserBiz.java

@@ -0,0 +1,48 @@
+/**
+ * Copyright (c) 2012-present 铭软科技(mingsoft.net)
+ * 本软件及相关文档文件(以下简称“软件”)的版权归 铭软科技 所有
+ * 遵循 铭软科技《服务协议》中的《保密条款》
+ */
+
+
+
+
+package net.mingsoft.people.biz;
+
+import net.mingsoft.base.biz.IBaseBiz;
+import net.mingsoft.people.bean.PeopleBean;
+import net.mingsoft.people.entity.PeopleUserEntity;
+
+import java.util.List;
+
+/**
+ * 
+ * 用户信息业务层接口
+ * @author 铭飞开发团队
+ * @version 
+ * 版本号:0.0<br/>
+ * 创建日期:2017-8-23 10:10:22<br/>
+ * 历史修订:<br/>
+ */
+public interface IPeopleUserBiz extends IBaseBiz<PeopleUserEntity> {
+
+	/**
+	 * 批量查询用户
+	 * @param peopleIds 用户id集合
+	 */
+	List<PeopleBean> queryBatchIds(List<String> peopleIds);
+
+	/**
+	 * 通过会员信息获取会员详情
+	 * @param peopleBean 用户bean
+	 * @return 用户bean
+	 */
+	PeopleBean getByEntity(PeopleBean peopleBean);
+
+	/**
+	 * 批量查询用户
+	 * @param peopleBean 用户bean
+	 * @return 集合
+	 */
+	List<PeopleBean> query(PeopleBean peopleBean);
+}

+ 268 - 0
src/main/java/net/mingsoft/people/biz/impl/PeopleBizImpl.java

@@ -0,0 +1,268 @@
+/**
+ * Copyright (c) 2012-present 铭软科技(mingsoft.net)
+ * 本软件及相关文档文件(以下简称“软件”)的版权归 铭软科技 所有
+ * 遵循 铭软科技《服务协议》中的《保密条款》
+ */
+
+
+
+
+package net.mingsoft.people.biz.impl;
+
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+import net.mingsoft.base.biz.impl.BaseBizImpl;
+import net.mingsoft.base.dao.IBaseDao;
+import net.mingsoft.base.exception.BusinessException;
+import net.mingsoft.base.util.SqlInjectionUtil;
+import net.mingsoft.basic.util.StringUtil;
+import net.mingsoft.mdiy.biz.IModelBiz;
+import net.mingsoft.mdiy.entity.ModelEntity;
+import net.mingsoft.people.bean.PeopleBean;
+import net.mingsoft.people.biz.IPeopleBiz;
+import net.mingsoft.people.constant.e.LoginTypeEnum;
+import net.mingsoft.people.constant.e.PeopleEnum;
+import net.mingsoft.people.dao.IPeopleDao;
+import net.mingsoft.people.dao.IPeopleUserDao;
+import net.mingsoft.people.entity.PeopleEntity;
+import net.mingsoft.people.entity.PeopleUserEntity;
+import org.apache.commons.lang3.ArrayUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.List;
+
+/**
+ * 
+ * 用户业务层实现类
+ * @author 铭飞开发团队
+ * @version 
+ * 版本号:0.0<br/>
+ * 创建日期:2017-8-23 10:10:22<br/>
+ * 历史修订:<br/>
+ */
+@Service("peopleBiz")
+@Transactional
+public class PeopleBizImpl  extends BaseBizImpl<IPeopleDao,PeopleEntity> implements IPeopleBiz{
+
+	/**
+	 * 用户持久化层
+	 */
+	@Autowired
+	private IPeopleDao peopleDao;
+
+	/**
+	 * 注入配置模型业务层
+	 */
+	@Autowired
+	private IModelBiz modelBiz;
+
+	@Autowired
+	private IPeopleUserDao peopleUserDao;
+
+	/**
+	 * 获取peopleDao
+	 */
+	@Override
+	protected IBaseDao getDao() {
+		return peopleDao;
+	}
+
+	/**
+	 * 用户有子类增加
+	 */
+	@Override
+	public int savePeople(PeopleBean people) {
+		PeopleEntity peopleEntity = BeanUtil.copyProperties(people, PeopleEntity.class);
+		save(peopleEntity);
+		PeopleUserEntity peopleUserEntity = BeanUtil.copyProperties(people, PeopleUserEntity.class);
+		peopleUserEntity.setPeopleId(peopleEntity.getId());
+		// 设置peopleId值,防止peopleBean中没有id值
+		people.setPeopleId(peopleEntity.getId());
+		people.setId(peopleEntity.getId());
+		return peopleUserDao.insert(peopleUserEntity);
+	}
+	
+	/**
+	 * 根据用户ID进行用户实体的更新,用于有子类的更新操作
+	 * @param people
+	 */	
+	@Override
+	public void updatePeople(PeopleBean people) {
+		//修改子类子类时,people中没有参数,保证执行updateSQL语句是一定正确
+		PeopleEntity peopleEntity = BeanUtil.copyProperties(people, PeopleEntity.class);
+		peopleEntity.setId(people.getPeopleId());
+		updateEntity(peopleEntity);
+		PeopleUserEntity peopleUserEntity = BeanUtil.copyProperties(people, PeopleUserEntity.class);
+		// 防止修改
+		peopleUserEntity.setId(null);
+		LambdaUpdateWrapper<PeopleUserEntity> wrapper = new LambdaUpdateWrapper<>();
+		wrapper.eq(PeopleUserEntity::getPeopleId, people.getPeopleId());
+		peopleUserDao.update(peopleUserEntity, wrapper);
+	}
+
+
+	
+	/**
+	 * 根据用户用户名查询用户实体</br>
+	 * @param userName 用户名(注:手机号,邮箱,用户名称都可作为用户名登录)
+	 * @return 查询到的用户实体
+	 */
+	public PeopleEntity getEntityByUserName(String userName){
+		return this.peopleDao.getEntityByUserName(userName);
+	}	
+	
+
+	@Override
+	public PeopleEntity getEntityByCode(String userName, String peopleCode) {
+		// TODO Auto-generated method stub
+		return this.peopleDao.getEntityByCode(userName, peopleCode);
+	}
+
+
+	@Override
+	public List<PeopleBean> query(PeopleBean peopleBean) {
+		return peopleDao.query(peopleBean);
+	}
+
+	@Override
+	public PeopleBean getPeopleById(String id) {
+		return  peopleDao.getPeopleById(id);
+	}
+
+	@Override
+	public void deletePeople(String[] peopleIds) {
+		if(ArrayUtils.isEmpty(peopleIds)){
+			return;
+		}
+		LambdaQueryWrapper<ModelEntity> queryWrapper = new LambdaQueryWrapper<>();
+		queryWrapper.eq(ModelEntity::getModelType, "people");
+		queryWrapper.eq(ModelEntity::getModelName, "扩展会员信息");
+		ModelEntity model = modelBiz.getOne(queryWrapper);
+		if (model != null) {
+			for (String peopleId : peopleIds) {
+				// 过滤表名
+				SqlInjectionUtil.filterContent(model.getModelTableName());
+				//删除模型表的数据
+				modelBiz.update(StrUtil.format("DELETE FROM {} WHERE LINK_ID = ?", model.getModelTableName()), peopleId);
+			}
+		}
+		peopleDao.delete(peopleIds);
+		peopleUserDao.delete(peopleIds);
+	}
+
+	@Override
+	public PeopleEntity getByPeople(PeopleEntity people) {
+		// TODO Auto-generated method stub
+		return peopleDao.getByPeople(people);
+	}
+
+
+
+	@Override
+	public PeopleEntity getEntityByMailOrPhone(String userName) {
+		// TODO Auto-generated method stub
+		return peopleDao.getEntityByMailOrPhone(userName);
+	}
+
+	@Override
+	public boolean isExists(PeopleBean peopleUser) {
+		if (peopleUser==null){
+			throw new BusinessException("检测对象不可以为空");
+		}
+		// 是否为更新
+		boolean isUpdate = StringUtils.isNotBlank(peopleUser.getPeopleId());
+		//获取更改前的用户
+		PeopleBean oldPeopleUser = new PeopleBean();
+		if (isUpdate){
+			oldPeopleUser =  peopleDao.getPeopleById(peopleUser.getPeopleId());
+		}
+		//如果填写了邮箱,则验证邮箱格式是否正确
+		if (!StringUtils.isBlank(peopleUser.getPeopleMail()) && !StringUtil.isEmail(peopleUser.getPeopleMail())) {
+			return false;
+		}
+
+		// 邮箱或手机号绑定   验证用户名可以为空
+		if(peopleUser.getPeoplePhoneCheck()== PeopleEnum.PHONE_NO_CHECK.toInt() && peopleUser.getPeopleMailCheck()==PeopleEnum.MAIL_NO_CHECK.toInt() && StringUtils.isBlank(peopleUser.getPeopleName())){
+			return false;
+		}
+
+		//如果填写了手机号码,则验证手机号码填写是否正确
+		if (!StringUtils.isBlank(peopleUser.getPeoplePhone()) && !StringUtil.isMobile(peopleUser.getPeoplePhone())) {
+			return false;
+		}
+
+		//当用户名进行修改时验证用户名是否是唯一的
+		if (!StringUtils.isBlank(peopleUser.getPeopleName())) {
+			// 验证用户名是否唯一
+			PeopleEntity peopleName = peopleDao.getEntityByUserName(peopleUser.getPeopleName());
+			//判断之前是否已经存在用户名,如果不存在,则判断是否存在重名,如果存在,判断用户是否更改用户名如果更改则判断新更改的用户名是否已经存在
+			//判断填写的用户名和之前用户名是否相同,如果不相同
+			if(StringUtils.isBlank(oldPeopleUser.getPeopleName())){
+				if (peopleName != null) {
+					return false;
+				}
+			}else{
+				if(!oldPeopleUser.getPeopleName().equals(peopleUser.getPeopleName())){
+					if (peopleName != null) {
+						return false;
+					}
+				}
+			}
+
+		}
+		if(!StringUtils.isBlank(peopleUser.getPeoplePhone())){
+			PeopleEntity peoplePhone = peopleDao.getEntityByMailOrPhone(peopleUser.getPeoplePhone());
+			//判断之前是否已经存在手机号,如果不存在,则判断是否存在重名,如果存在,判断用户是否更改手机号如果更改则判断新更改的手机号是否已经存在
+			//判断填写的手机号和之前手机号是否相同,如果不相同
+			if(StringUtils.isBlank(oldPeopleUser.getPeoplePhone())){
+				if (peoplePhone != null) {
+					return false;
+				}
+			}else{
+				if(!oldPeopleUser.getPeoplePhone().equals(peopleUser.getPeoplePhone())){
+					if (peoplePhone != null) {
+						return false;
+					}
+				}
+			}
+		}
+		//验证邮箱的唯一性
+		if(!StringUtils.isBlank(peopleUser.getPeopleMail())){
+			PeopleEntity peopleMail = peopleDao.getEntityByMailOrPhone(peopleUser.getPeopleMail());
+			//判断之前是否已经存在邮箱(且绑定),如果不存在,则判断是否存在重名,如果存在,判断用户是否更改邮箱如果更改则判断新更改的邮箱是否已经存在
+			//判断填写的邮箱和之前邮箱是否相同,如果不相同
+			if(StringUtils.isBlank(oldPeopleUser.getPeopleMail())){
+				if (peopleMail != null) {
+					return false;
+				}
+			}else{
+				if(!oldPeopleUser.getPeopleMail().equals(peopleUser.getPeopleMail())){
+					if (peopleMail != null) {
+						return false;
+					}
+				}
+			}
+		}
+		//验证用户身份证号码
+		return true;
+	}
+
+	@Override
+	public boolean isExists(String loginName, LoginTypeEnum loginType) {
+		PeopleBean peopleUser = new PeopleBean();
+		if (LoginTypeEnum.NAME.toString().equals(loginType.toString())){
+			peopleUser.setPeopleName(loginName);
+		}else if (LoginTypeEnum.MAIL.toString().equals(loginType.toString())){
+			peopleUser.setPeopleMail(loginName);
+		}else {
+			peopleUser.setPeoplePhone(loginName);
+		}
+
+		return isExists(peopleUser);
+	}
+}

+ 38 - 0
src/main/java/net/mingsoft/people/biz/impl/PeopleLogBizImpl.java

@@ -0,0 +1,38 @@
+/**
+ * Copyright (c) 2012-present 铭软科技(mingsoft.net)
+ * 本软件及相关文档文件(以下简称“软件”)的版权归 铭软科技 所有
+ * 遵循 铭软科技《服务协议》中的《保密条款》
+ */
+
+package net.mingsoft.people.biz.impl;
+
+import net.mingsoft.base.biz.impl.BaseBizImpl;
+import net.mingsoft.people.biz.IPeopleLogBiz;
+import net.mingsoft.people.dao.IPeopleLogDao;
+import net.mingsoft.people.entity.PeopleLogEntity;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import net.mingsoft.base.dao.IBaseDao;
+
+/**
+ * 会员日志管理持久化层
+ * @author 铭软科技
+ * 创建日期:2023-6-5 17:34:20<br/>
+ * 历史修订:<br/>
+ */
+@Service("mpeoplepeopleLogBizImpl")
+public class PeopleLogBizImpl extends BaseBizImpl<IPeopleLogDao, PeopleLogEntity> implements IPeopleLogBiz {
+
+
+    @Autowired
+    private IPeopleLogDao peopleLogDao;
+
+
+    @Override
+    protected IBaseDao getDao() {
+        // TODO Auto-generated method stub
+        return peopleLogDao;
+    }
+
+
+}

+ 67 - 0
src/main/java/net/mingsoft/people/biz/impl/PeopleUserBizImpl.java

@@ -0,0 +1,67 @@
+/**
+ * Copyright (c) 2012-present 铭软科技(mingsoft.net)
+ * 本软件及相关文档文件(以下简称“软件”)的版权归 铭软科技 所有
+ * 遵循 铭软科技《服务协议》中的《保密条款》
+ */
+
+
+
+
+package net.mingsoft.people.biz.impl;
+
+
+import net.mingsoft.base.biz.IBaseBiz;
+import net.mingsoft.base.biz.impl.BaseBizImpl;
+import net.mingsoft.base.dao.IBaseDao;
+import net.mingsoft.people.bean.PeopleBean;
+import net.mingsoft.people.biz.IPeopleUserBiz;
+import net.mingsoft.people.dao.IPeopleDao;
+import net.mingsoft.people.dao.IPeopleUserDao;
+import net.mingsoft.people.entity.PeopleUserEntity;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.List;
+
+/**
+ * 
+ * 用户信息业务层层实现类
+ * @author 铭飞开发团队
+ * @version 
+ * 版本号:0.0<br/>
+ * 创建日期:2017-8-23 10:10:22<br/>
+ * 历史修订:<br/>
+ */
+@Service("peopleUserBiz")
+@Transactional
+public class PeopleUserBizImpl extends BaseBizImpl<IPeopleUserDao,PeopleUserEntity> implements IPeopleUserBiz {
+
+	/**
+	 * 用户信息持久化层注入
+	 */
+	@Autowired
+	private IPeopleUserDao peopleUserDao;
+
+	@Override
+	protected IBaseDao getDao() {
+		return peopleUserDao;
+	}
+
+
+
+	@Override
+	public List<PeopleBean> queryBatchIds(List<String> peopleIds) {
+		return peopleUserDao.queryBatchIds(peopleIds);
+	}
+
+	@Override
+	public PeopleBean getByEntity(PeopleBean peopleBean) {
+		return peopleUserDao.getByEntity(peopleBean);
+	}
+
+	@Override
+	public List<PeopleBean> query(PeopleBean peopleBean) {
+		return peopleUserDao.query(peopleBean);
+	}
+}

+ 28 - 0
src/main/java/net/mingsoft/people/constant/Const.java

@@ -0,0 +1,28 @@
+/**
+ * Copyright (c) 2012-present 铭软科技(mingsoft.net)
+ * 本软件及相关文档文件(以下简称“软件”)的版权归 铭软科技 所有
+ * 遵循 铭软科技《服务协议》中的《保密条款》
+ */
+
+
+
+
+package net.mingsoft.people.constant;
+
+
+/**
+ * 用户模块常量
+ * @author wjj
+ * @version
+ * 版本号:0.0<br/>
+ * 创建日期:2017-8-23 10:10:22<br/>
+ * 历史修订:<br/>
+ */
+public class Const {
+	public final static String RESOURCES = "net.mingsoft.people.resources.resources";
+	
+	/**
+	 * 自定义页面时默认路径
+	 */
+	public final static String DIY_PATH = "people";
+}

+ 47 - 0
src/main/java/net/mingsoft/people/constant/e/CookieConstEnum.java

@@ -0,0 +1,47 @@
+/**
+ * Copyright (c) 2012-present 铭软科技(mingsoft.net)
+ * 本软件及相关文档文件(以下简称“软件”)的版权归 铭软科技 所有
+ * 遵循 铭软科技《服务协议》中的《保密条款》
+ */
+
+
+
+
+package net.mingsoft.people.constant.e;
+
+import net.mingsoft.base.constant.e.BaseCookieEnum;
+
+public enum CookieConstEnum implements BaseCookieEnum  {
+	/**
+	 * 用户的cookie
+	 */
+	PEOPLE_COOKIE("people_cookie"),
+	/**
+	 * 用户登录地址
+	 */
+	PEOPLE_LOGIN_URL("people_login_url");
+
+	/**
+	 * 设置session常量
+	 *
+	 * @param attr
+	 *            常量
+	 */
+	CookieConstEnum(String attr) {
+		this.attr = attr;
+	}
+
+	private String attr;
+
+	/**
+	 * 返回SessionConst常量的字符串表示
+	 *
+	 * @return 字符串
+	 */
+	@Override
+	public String toString() {
+		// TODO Auto-generated method stub
+		return attr;
+	}
+
+}

+ 47 - 0
src/main/java/net/mingsoft/people/constant/e/LoginTypeEnum.java

@@ -0,0 +1,47 @@
+/**
+ * Copyright (c) 2012-present 铭软科技(mingsoft.net)
+ * 本软件及相关文档文件(以下简称“软件”)的版权归 铭软科技 所有
+ * 遵循 铭软科技《服务协议》中的《保密条款》
+ */
+
+package net.mingsoft.people.constant.e;
+
+import net.mingsoft.base.constant.e.BaseEnum;
+
+/**
+ * 登陆类型
+ */
+public enum LoginTypeEnum implements BaseEnum {
+    /**
+     * 账号登陆
+     */
+    NAME(" 账号"),
+
+    /**
+     * 邮箱登陆
+     */
+    MAIL(" 邮箱"),
+
+    /**
+     * 手机号登陆
+     */
+    PHONE("手机号");
+
+    /**
+     * 枚举类型
+     */
+    public String label;
+
+    LoginTypeEnum(String label) {
+        this.label = label;
+    }
+
+    public String getLabel() {
+        return this.label;
+    }
+
+    @Override
+    public int toInt() {
+        return 0;
+    }
+}

+ 48 - 0
src/main/java/net/mingsoft/people/constant/e/PeopleAddressEnum.java

@@ -0,0 +1,48 @@
+/**
+ * Copyright (c) 2012-present 铭软科技(mingsoft.net)
+ * 本软件及相关文档文件(以下简称“软件”)的版权归 铭软科技 所有
+ * 遵循 铭软科技《服务协议》中的《保密条款》
+ */
+
+
+
+
+package net.mingsoft.people.constant.e;
+
+import net.mingsoft.base.constant.e.BaseEnum;
+
+/**
+ * 
+ * 用户收货地址状态枚举类
+ * @author 铭飞开发团队
+ * @version 
+ * 版本号:0.0<br/>
+ * 创建日期:2017-8-23 10:10:22<br/>
+ * 历史修订:<br/>
+ */
+public enum PeopleAddressEnum implements BaseEnum{
+	/**
+	 * 默认收货地址
+	 */
+	ADDRESS_DEFAULT(0),
+	
+	/**
+	 * 非默认收货地址
+	 */
+	ADDRESS_NOT_DEFAULT(1);
+	
+	PeopleAddressEnum(Object code) {
+		this.code = code;
+	}  
+
+	private Object code;
+
+	@Override
+	public String toString() {
+		return code.toString();
+	}
+
+	public int toInt() {
+		return Integer.parseInt(code.toString());
+	}
+}

+ 68 - 0
src/main/java/net/mingsoft/people/constant/e/PeopleEnum.java

@@ -0,0 +1,68 @@
+/**
+ * Copyright (c) 2012-present 铭软科技(mingsoft.net)
+ * 本软件及相关文档文件(以下简称“软件”)的版权归 铭软科技 所有
+ * 遵循 铭软科技《服务协议》中的《保密条款》
+ */
+
+
+
+
+package net.mingsoft.people.constant.e;
+
+import net.mingsoft.base.constant.e.BaseEnum;
+
+public enum PeopleEnum implements BaseEnum {
+	/**
+	 * 用户为已审核状态
+	 */
+	STATE_CHECK(1),
+	/**
+	 * 用户为未审核状态
+	 */
+	STATE_NOT_CHECK(0),
+	
+	/**
+	 * 手机验证通过
+	 */
+	PHONE_CHECK(1),
+	
+	/**
+	 * 手机验证不通过
+	 */
+	PHONE_NO_CHECK(0),
+	/**
+	 * 邮箱验证通过
+	 */
+	MAIL_CHECK(1),
+	/**
+	 * 邮箱验证不通过
+	 */
+	MAIL_NO_CHECK(0),
+	/**
+	 *根据用户名注册
+	 */
+	REGISTER_NAME(1),
+	/**
+	 *根据手机号注册
+	 */
+	REGISTER_PHONE(2),
+	/**
+	 *根据邮箱注册
+	 */
+	REGISTER_EMAIL(3);
+	
+	PeopleEnum(Object code) {
+		this.code = code;
+	}
+
+	private Object code;
+
+	@Override
+	public String toString() {
+		return code.toString();
+	}
+
+	public int toInt() {
+		return Integer.parseInt(code.toString());
+	}
+}

+ 59 - 0
src/main/java/net/mingsoft/people/constant/e/PeopleLogTypeEnum.java

@@ -0,0 +1,59 @@
+/**
+ * Copyright (c) 2012-present 铭软科技(mingsoft.net)
+ * 本软件及相关文档文件(以下简称“软件”)的版权归 铭软科技 所有
+ * 遵循 铭软科技《服务协议》中的《保密条款》
+ */
+
+package net.mingsoft.people.constant.e;
+
+import net.mingsoft.base.constant.e.BaseEnum;
+
+public enum PeopleLogTypeEnum implements BaseEnum {
+    /**
+     * 其它
+     */
+    OTHER("其他"),
+
+    /**
+     * 异常
+     */
+    ERROR("异常"),
+
+    /**
+     * 登录
+     */
+    LOGIN("登录"),
+
+    /**
+     * 新增
+     */
+    INSERT("新增"),
+
+    /**
+     * 修改
+     */
+    UPDATE("修改"),
+
+    /**
+     * 删除
+     */
+    DELETE("删除");
+
+    /**
+     * 枚举类型
+     */
+    public String label;
+
+    PeopleLogTypeEnum(String label) {
+        this.label = label;
+    }
+
+    public String getLabel() {
+        return this.label;
+    }
+
+    @Override
+    public int toInt() {
+        return 0;
+    }
+}

+ 78 - 0
src/main/java/net/mingsoft/people/constant/e/SessionConstEnum.java

@@ -0,0 +1,78 @@
+/**
+ * Copyright (c) 2012-present 铭软科技(mingsoft.net)
+ * 本软件及相关文档文件(以下简称“软件”)的版权归 铭软科技 所有
+ * 遵循 铭软科技《服务协议》中的《保密条款》
+ */
+
+
+
+
+package net.mingsoft.people.constant.e;
+
+import net.mingsoft.base.constant.e.BaseSessionEnum;
+
+/**
+ * 
+ * 会员系统
+ * @author 铭飞开发团队
+ * @version 
+ * 版本号:0.0<br/>
+ * 创建日期:2017-8-23 10:10:22<br/>
+ * 历史修订:<br/>
+ */
+public enum SessionConstEnum implements BaseSessionEnum {
+	/**
+	 * 用户的session
+	 */
+	PEOPLE_SESSION("people_session"),
+
+	/**
+	 * 用户取回密码的session
+	 */
+	PEOPLE_GET_PASSWORD_SESSION("people_get_password_session"),
+	
+	/**
+	 * 用户验证手机号、用名称、邮箱的session
+	 */
+	PEOPLE_EXISTS_SESSION("people_exists_session"),
+
+
+	/**
+	 * 重置密码session
+	 */
+	PEOPLE_RESET_PASSWORD_SESSION("people_reset_password_session"),
+	
+	/**
+	 * 用户更改手机号码的session
+	 */
+	PEOPEL_SET_PHONE_SESSION("people_set_phone_seesion"),
+	
+	/**
+	 * 用户发送验证码
+	 */
+	SEND_CODE_SESSION("send_code_seesion");
+
+	/**
+	 * 设置session常量
+	 * 
+	 * @param attr
+	 *            常量
+	 */
+	SessionConstEnum(String attr) {
+		this.attr = attr;
+	}
+
+	private String attr;
+
+	/**
+	 * 返回SessionConst常量的字符串表示
+	 * 
+	 * @return 字符串
+	 */
+	@Override
+	public String toString() {
+		// TODO Auto-generated method stub
+		return attr;
+	}
+
+}

+ 79 - 0
src/main/java/net/mingsoft/people/dao/IPeopleDao.java

@@ -0,0 +1,79 @@
+/**
+ * Copyright (c) 2012-present 铭软科技(mingsoft.net)
+ * 本软件及相关文档文件(以下简称“软件”)的版权归 铭软科技 所有
+ * 遵循 铭软科技《服务协议》中的《保密条款》
+ */
+
+
+
+
+package net.mingsoft.people.dao;
+
+
+import net.mingsoft.base.dao.IBaseDao;
+import net.mingsoft.people.bean.PeopleBean;
+import net.mingsoft.people.entity.PeopleEntity;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+
+/**
+ * 
+ * 用户持久化层
+ * @author 铭飞开发团队
+ * @version 
+ * 版本号:0.0<br/>
+ * 创建日期:2017-8-23 10:10:22<br/>
+ * 历史修订:<br/>
+ */
+public interface IPeopleDao extends IBaseDao<PeopleEntity>{
+	
+	/**
+	 * 根据用户用户名查询用户实体</br>
+	 * @param userName 用户名(注:手机号,邮箱,用户名称都可作为用户名登录)
+	 * @return 查询到的用户实体
+	 */
+	PeopleEntity getEntityByUserName(@Param("userName")String userName);
+	
+	
+	/**
+	 * 根据用户用户名查询用户实体</br>
+	 * @param userName 用户名(注:手机号,邮箱)
+	 * @return 查询到的用户实体
+	 */
+	PeopleEntity getEntityByMailOrPhone(@Param("userName")String userName);
+	
+	/**
+	 * 根据用户信息查询对应用户
+	 * @param people 用户信息
+	 * @return  返回用户
+	 */
+	PeopleEntity getByPeople(@Param("people")PeopleEntity people);
+	
+
+	
+	/**
+	 * 根据用户的验证码和用户名(:手机号,邮箱,用户名称都可作为用户名登录)
+	 * @param userName 用户名
+	 * @param peopleCode 用户验证码
+	 * @return 会员基础信息
+	 */
+	PeopleEntity getEntityByCode(@Param("userName")String userName,@Param("peopleCode")String peopleCode);
+
+	/**
+	 * 根据用户信息批量查询用户
+	 * @param peopleBean 用户信息
+	 * @return 集合
+	 */
+	List<PeopleBean> query(@Param("where")PeopleBean peopleBean);
+
+	/**
+	 * 根据会员id 查询用户的基础、详细信息
+	 * @param id 会员id
+	 * @return 会员信息
+	 */
+	PeopleBean getPeopleById(String id);
+
+
+}

+ 292 - 0
src/main/java/net/mingsoft/people/dao/IPeopleDao.xml

@@ -0,0 +1,292 @@
+<?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" >
+<!-- 管理员持久化层XML配置继承IRoleDao -->
+<mapper namespace="net.mingsoft.people.dao.IPeopleDao">
+	<!-- 表字段开始 -->
+	<sql id="column_list">
+		PEOPLE_PHONE,PEOPLE_NAME,PEOPLE_PASSWORD,PEOPLE_CODE,
+		PEOPLE_DATETIME,PEOPLE_MAIL,PEOPLE_STATE,PEOPLE_CODESENDDATE,
+		PEOPLE_PHONECHECK,PEOPLE_MAILLCHECK
+	</sql>
+
+	<sql id="user_column_list">
+		people_id,PU_REAL_NAME,PU_ADDRESS,PU_LEVEL,PU_LEVEL_NAME,PU_ICON,PU_NICKNAME,PU_SEX,PU_BIRTHDAY,PU_CARD,
+ PROVINCE_ID,PROVINCE_NAME,CITY_ID,CITY_NAME,COUNTY_ID,COUNTY_NAME
+	</sql>
+
+
+
+	<!-- 将实体属性与表字段对接开始 -->
+	<resultMap id="resultMap" type="net.mingsoft.people.bean.PeopleBean">
+		<id column="id" property="id"/><!-- 将实体的ID属性与表的ID字段对接 -->
+		<result column="PEOPLE_PHONE" property="peoplePhone"/><!-- 将实体的peoplePhone属性与表的peoplePhone字段对接 -->
+		<result column="PEOPLE_NAME" property="peopleName"/><!-- 将实体的peopleName属性与表的peopleName字段对接 -->
+		<result column="PEOPLE_PASSWORD" property="peoplePassword"/><!--
+			将实体的PEOPLE_PASSWORD属性与表的peoplePwd字段对接 -->
+		<result column="PEOPLE_DATETIME" property="peopleDateTime"/><!--
+			将实体的peopleDateTime属性与表的peopleDateTime字段对接 -->
+		<result column="PEOPLE_MAIL" property="peopleMail"/><!-- 用户邮箱 -->
+		<result column="PEOPLE_IP" property="peopleIp"/><!-- 用户ip -->
+		<result column="PEOPLE_STATE" property="peopleState"/><!-- 用户状态 -->
+		<result column="PEOPLE_CODE" property="peopleCode"/><!-- 用户随机码 -->
+		<result column="PEOPLE_CODESENDDATE" property="peopleCodeSendDate"/><!--
+			用户随机码发送时间 -->
+		<result column="PEOPLE_MAILLCHECK" property="peopleMailCheck"/><!--
+			用户是否通过邮箱验证 -->
+		<result column="PEOPLE_PHONECHECK" property="peoplePhoneCheck"/><!--
+			用户是否通过电话验证 -->
+		<result column="PU_REAL_NAME" property="puRealName"/><!--用户的真实名称 -->
+		<result column="PU_ADDRESS" property="puAddress"/><!--用户地址 -->
+		<result column="PU_ICON" property="puIcon"/><!-- 用户头像 -->
+		<result column="PU_LEVEL" property="puLevel"/><!-- 用户等级 -->
+		<result column="PU_LEVEL_NAME" property="puLevelName"/><!-- 等级名称 -->
+		<result column="PU_ICON" property="puIcon"/><!-- 用户头像 -->
+		<result column="PU_NICKNAME" property="puNickname"/><!--用户昵称 -->
+		<result column="PU_SEX" property="puSex"/><!-- 用户性别0.未知;1.男;2.女 -->
+		<result column="PU_BIRTHDAY" property="puBirthday"/><!--用户生日 -->
+		<result column="PU_CARD" property="puCard"/><!-- 用户身份证号码 -->
+	</resultMap>
+
+	<!-- 将实体属性与表字段对接结束 -->
+	<sql id="insertColumns">
+		<if test="peoplePhone != null">PEOPLE_PHONE,</if>
+			<if test="peopleName != null">PEOPLE_NAME,</if>
+			<if test="peoplePassword != null">PEOPLE_PASSWORD,</if>
+			<if test="peopleDateTime != null">PEOPLE_DATETIME,</if>
+			<if test="peopleMail != null">PEOPLE_MAIL,</if>
+			<if test="peopleIp != null">PEOPLE_IP,</if>
+			<if test="peopleState != null">PEOPLE_STATE,</if>
+			<if test="peopleCode != null">PEOPLE_CODE,</if>
+			<if test="peopleCodeSendDate != null">PEOPLE_CODESENDDATE,</if>
+			<if test="peopleMailCheck != null and peopleMailCheck &gt; -1">PEOPLE_MAILLCHECK,</if>
+			<if test="peoplePhoneCheck != null and  peoplePhoneCheck &gt; -1">PEOPLE_PHONECHECK,</if>
+	</sql>
+	<sql id="insertValues">
+		<if test="peoplePhone != null">#{peoplePhone},</if>
+			<if test="peopleName != null">#{peopleName},</if>
+			<if test="peoplePassword != null">#{peoplePassword},</if>
+			<if test="peopleDateTime != null">#{peopleDateTime},</if>
+			<if test="peopleMail != null">#{peopleMail},</if>
+			<if test="peopleIp != null">#{peopleIp},</if>
+			<if test="peopleState != null">#{peopleState},</if>
+			<if test="peopleCode != null">#{peopleCode},</if>
+			<if test="peopleCodeSendDate != null">#{peopleCodeSendDate},</if>
+			<if test="peopleMailCheck != null and peopleMailCheck &gt; -1">#{peopleMailCheck},</if>
+			<if test="peoplePhoneCheck != null and  peoplePhoneCheck &gt; -1">#{peoplePhoneCheck},</if>
+	</sql>
+	<insert id="saveEntity"
+		parameterType="net.mingsoft.base.entity.BaseEntity">
+		insert into people
+		<trim prefix="(" suffix=")" suffixOverrides=",">
+			<include refid="insertColumns"></include>
+		</trim>
+		<trim prefix="values (" suffix=")" suffixOverrides=",">
+			<include refid="insertValues"></include>
+		</trim>
+	</insert>
+	<!-- 查询用户开始 -->
+	<select id="getEntity" resultMap="resultMap" parameterType="String">
+		select
+		<include refid="column_list" />
+		,p.id,PU_NICKNAME,PU_REAL_NAME
+		from people p LEFT JOIN people_user ON
+		(p.id = people_user.PEOPLE_ID)
+ 		where
+		p.id =
+		#{id}
+	</select>
+	<!-- 查询用户结束 -->
+
+	<!-- 查询用户开始 -->
+	<select id="getByEntity" resultMap="resultMap" parameterType="net.mingsoft.people.entity.PeopleEntity">
+		select
+		<include refid="column_list" />
+		,PU_NICKNAME,PU_REAL_NAME,p.id
+		from people p LEFT JOIN people_user ON
+		(p.id = people_user.PEOPLE_ID)
+ 		<where>
+ 			<if test="id != null and id  &gt; 0">and p.id=#{id}</if>
+ 			<if test="peopleName != null and peopleName != ''">and PEOPLE_NAME=#{peopleName}</if>
+ 			<if test="peopleMail != null and peopleMail != ''">and PEOPLE_MAIL=#{peopleMail}</if>
+ 			<if test="peoplePhone != null and peoplePhone != ''">and PEOPLE_PHONE=#{peoplePhone}</if>
+ 			<if test="peopleMailCheck != null and peopleMailCheck &gt; -1">and PEOPLE_MAILLCHECK=#{peopleMailCheck}</if>
+ 		</where>
+	</select>
+	<!-- 查询用户结束 -->
+
+	<sql id="updateEntitySet">
+	       <if test="peoplePhone != null">PEOPLE_PHONE=#{peoplePhone},</if>
+		   <if test="peopleName != null and peopleName != ''">PEOPLE_NAME=#{peopleName},</if>
+		   <if test="peoplePassword != null  and peoplePassword != ''">PEOPLE_PASSWORD=#{peoplePassword},</if>
+		   <if test="peopleDateTime != null ">PEOPLE_DATETIME=#{peopleDateTime},</if>
+		   <if test="peopleMail != null">PEOPLE_MAIL=#{peopleMail},</if>
+		   <if test="peopleIp != null  and peopleIp != ''">PEOPLE_IP=#{peopleIp},</if>
+		   <if test="peopleState != null">PEOPLE_STATE=#{peopleState},</if>
+		   <if test="peopleCode != null  and peopleCode != ''">PEOPLE_CODE=#{peopleCode},</if>
+		   <if test="peopleCodeSendDate != null">PEOPLE_CODESENDDATE=#{peopleCodeSendDate},</if>
+		   <if test="peopleMailCheck != null and peopleMailCheck &gt; -1">PEOPLE_MAILLCHECK=#{peopleMailCheck},</if>
+		   <if test="peoplePhoneCheck != null and peoplePhoneCheck &gt; -1">PEOPLE_PHONECHECK=#{peoplePhoneCheck},</if>
+	</sql>
+	<!-- mysql和oracle更新用户开始 -->
+	<update id="updateEntity" parameterType="net.mingsoft.base.entity.BaseEntity">
+		update people
+		<set>
+			<include refid="updateEntitySet" />
+		</set>
+		where id = #{id}
+	</update>
+	<!-- 更新用户结束 -->
+
+
+	<!-- 删除用户开始 -->
+	<delete id="deleteEntity" parameterType="int">
+		delete from people where
+		id = #{id}
+	</delete>
+	<!-- 删除用户结束 -->
+
+	<!-- 根据用户名(帐号,手机,邮箱)查询用户信息开始 -->
+	<select id="getEntityByUserName" resultMap="resultMap">
+		select
+		<include refid="column_list" />
+		,people.id,<include refid="user_column_list" />
+		from people LEFT JOIN people_user ON
+		(people.id = people_user.PEOPLE_ID)
+		 where (people_name=#{userName} or
+		(people_phone=#{userName} and PEOPLE_PHONECHECK=1) or
+		people_mail=#{userName} and PEOPLE_MAILLCHECK=1)
+	</select>
+	<!-- 根据用户名(帐号,手机,邮箱)查询用户信息结束 -->
+	<select id="getEntityByMailOrPhone" resultMap="resultMap">
+		select
+		<include refid="column_list" />
+		,people.id,<include refid="user_column_list" />
+		from people LEFT JOIN people_user ON
+		(people.id = people_user.PEOPLE_ID)
+		where people_phone=#{userName} or
+		people_mail=#{userName}  and PEOPLE_MAILLCHECK=1
+	</select>
+
+	<select id="getByPeople" parameterType="net.mingsoft.people.entity.PeopleEntity"
+		resultMap="resultMap">
+		<if test="people != null">
+			select
+			<include refid="column_list" />
+			,people.id,<include refid="user_column_list" />
+			from people LEFT JOIN people_user ON
+			(people.id = people_user.PEOPLE_ID)
+			<trim prefix="WHERE" prefixOverrides="AND|OR">
+
+				<trim prefix="and (" prefixOverrides="AND|OR" suffix=")" >
+					<if test="people.peopleName != null">
+						or people_name = #{people.peopleName}
+					</if>
+					<if test="people.peopleMail != null and people.peopleMail != '' ">
+						or (people_mail = #{people.peopleMail} and
+						PEOPLE_MAILLCHECK=1
+						)
+					</if>
+					<if test="people.peoplePhone !=null  and people.peoplePhone  != '' ">
+						or (people_phone = #{people.peoplePhone} and
+						PEOPLE_PHONECHECK=1)
+					</if>
+				</trim>
+			</trim>
+
+		</if>
+
+	</select>
+
+	<!-- 查询用户列表开始 -->
+	<select id="query" resultMap="resultMap">
+		select
+		<include refid="column_list" />
+		,p.id,<include refid="user_column_list" />
+		from people p left join people_user on
+		p.id=PEOPLE_ID
+		<where>
+			<if test="where!=null">
+				<if test="where.peopleName != null and where.peopleName!=''">
+					and PEOPLE_NAME=#{where.peopleName}
+				</if>
+				<!-- 用户审核状态 -->
+				<if test="where.peopleState!=null and where.peopleState &gt; -1">
+					and PEOPLE_STATE=#{where.peopleState}
+				</if>
+				<!-- 根据用户注册时间 <if test="people.peopleDateStartTime !=null "> </if> -->
+
+
+				<!-- 根据用户昵称 -->
+				<if test="where.puNickname !=null and where.puNickname!=''">
+					and PU_NICKNAME=#{where.puNickname}
+				</if>
+				<!-- 根据用户性别 -->
+				<if
+					test="where.puSex != null and  where.puSex &gt; -1 ">
+					and PU_SEX=#{where.puSex}
+				</if>
+				<!-- 根据用户真实姓名 -->
+				<if
+					test="where.puRealName != null and where.puRealName !=''">
+					and PU_REAL_NAME=#{where.puRealName}
+				</if>
+				<if test="where.peopleDateStartTime != null and where.peopleDateEndTime !=null ">
+					<if test="_databaseId == 'mysql'">
+						and (PEOPLE_DATETIME between
+						#{where.peopleDateStartTime} and #{where.peopleDateEndTime})
+					</if>
+					<if test="_databaseId == 'oracle'">
+						and PEOPLE_DATETIME &gt; to_date(#{where.peopleDateStartTime}, 'yyyy-mm-dd hh24:mi:ss')
+						and PEOPLE_DATETIME &lt; to_date(#{where.peopleDateEndTime}, 'yyyy-mm-dd hh24:mi:ss')
+					</if>
+				</if>
+				<if test="where.peopleId != null and where.peopleId !=''">
+					and p.id=#{where.peopleId}
+				</if>
+				<if test="where.peopleMail != null and where.peopleMail !=''">
+					and p.PEOPLE_MAIL=#{where.peopleMail}
+				</if>
+				<if test="where.peoplePhone != null and where.peoplePhone !=''">
+					and p.PEOPLE_PHONE=#{where.peoplePhone}
+				</if>
+
+			</if>
+		</where>
+		order by p.PEOPLE_DATETIME desc
+	</select>
+	<!-- 查询用户列表结束 -->
+
+	<!-- 根据应用ID查询用户总数结束 -->
+
+	<!-- 根据用户名(帐号,手机,邮箱)和验证码查询用户信息开始 -->
+	<select id="getEntityByCode" resultMap="resultMap">
+		select
+		<include refid="column_list" />,p.id
+		from people p
+		where (people_name=#{userName} or
+		people_phone=#{userName} or
+		people_mail=#{userName}) and
+		people_code=#{peopleCode}
+	</select>
+	<select id="getPeopleById" resultMap="resultMap">
+		select
+		<include refid="column_list" />
+		,p.id,<include refid="user_column_list" />
+		from people p left join people_user on
+		p.id=PEOPLE_ID where p.id = #{id}
+
+	</select>
+	<!-- 根据用户名(帐号,手机,邮箱)和验证码用户信息结束 -->
+
+	<!-- 批量删除用户开始 -->
+	<delete id="delete" parameterType="java.lang.String">
+		delete from people
+		<where>
+			id in
+			<foreach collection="ids" item="item" index="index"
+				open="(" separator="," close=")">#{item}</foreach>
+		</where>
+	</delete>
+	<!-- 批量删除用户结束 -->
+
+</mapper>

+ 19 - 0
src/main/java/net/mingsoft/people/dao/IPeopleLogDao.java

@@ -0,0 +1,19 @@
+/**
+ * Copyright (c) 2012-present 铭软科技(mingsoft.net)
+ * 本软件及相关文档文件(以下简称“软件”)的版权归 铭软科技 所有
+ * 遵循 铭软科技《服务协议》中的《保密条款》
+ */
+
+package net.mingsoft.people.dao;
+
+import net.mingsoft.base.dao.IBaseDao;
+import net.mingsoft.people.entity.PeopleLogEntity;
+
+/**
+ * 会员日志持久层
+ * @author 铭软科技
+ * 创建日期:2023-6-5 17:34:20<br/>
+ * 历史修订:<br/>
+ */
+public interface IPeopleLogDao extends IBaseDao<PeopleLogEntity> {
+}

+ 58 - 0
src/main/java/net/mingsoft/people/dao/IPeopleLogDao.xml

@@ -0,0 +1,58 @@
+<?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="net.mingsoft.people.dao.IPeopleLogDao">
+
+    <resultMap id="resultMap" type="net.mingsoft.people.entity.PeopleLogEntity">
+        <result column="LOG_TITLE" property="logTitle" /><!--标题 -->
+        <result column="PEOPLE_ID" property="peopleId" /><!--会员编号 -->
+        <result column="LOG_IP" property="logIp" /><!--IP -->
+        <result column="LOG_ADDR" property="logAddr" /><!--所在地区 -->
+        <result column="LOG_TYPE" property="logType" /><!--日志类型 -->
+        <result column="LOG_STATUS" property="logStatus" /><!--日志状态 -->
+        <result column="LOG_PARAM" property="logParam" /><!--请求参数 -->
+        <result column="LOG_RESULT" property="logResult" /><!--返回参数 -->
+        <result column="LOG_INFO" property="logInfo" /><!--日志信息 -->
+        <result column="LOG_ERROR_MSG" property="logErrorMsg" /><!--错误消息 -->
+    </resultMap>
+
+    <select id="query" resultMap="resultMap">
+        SELECT * FROM PEOPLE_LOG
+        <where>
+            <if test="peopleId != null and peopleId != ''"> and people_id=#{peopleId}</if>
+            <if test="logTitle != null and logTitle != ''"> and log_title=#{logTitle}</if>
+            <if test="logType != null and logType != ''"> and log_type=#{logType}</if>
+            <if test="logIp != null and logIp != ''"> and log_addr=#{logIp}</if>
+            <if test="logAddr != null and logAddr != ''"> and log_ip=#{logAddr}</if>
+            <if test="logStatus != null and logStatus != ''"> and log_status=#{logStatus}</if>
+            <if test="logParam != null and logParam != ''"> and log_param=#{logParam}</if>
+            <if test="logResult != null and logResult != ''"> and log_result=#{logResult}</if>
+            <if test="logErrorMsg != null and logErrorMsg != ''"> and log_error_msg=#{logErrorMsg}</if>
+            <if test="createBy &gt; 0"> and create_by=#{createBy} </if>
+            <if test="createDate != null">
+                <if test="_databaseId == 'mysql'">
+                    and TO_DAYS(create_date) = TO_DAYS(#{createDate})
+                </if>
+                <if test="_databaseId == 'oracle'">
+                    and TO_CHAR(create_date,'yyyy-mm-dd') = TO_CHAR(#{createDate},'yyyy-mm-dd')
+                </if>
+            </if>
+            <if test="updateBy &gt; 0"> and update_by=#{updateBy} </if>
+            <if test="updateDate != null"> and update_date=#{updateDate} </if>
+            <if test="del != null"> and del=#{del} </if>
+            <if test="_databaseId == 'mysql'">
+                <if test="startTime != null and endTime != null">
+                    and date_format(create_date,'%Y-%m-%d %H:%i:%s') BETWEEN date_format(#{startTime},'%Y-%m-%d %H:%i:%s') AND date_format(#{endTime},'%Y-%m-%d %H:%i:%s')
+                </if>
+            </if>
+            <if test="_databaseId == 'oracle'">
+                <if test="startTime != null and endTime != null">
+                    and create_date BETWEEN to_date(#{startTime},'yyyy-mm-dd hh24:mi:ss') AND to_date(#{endTime},'yyyy-mm-dd hh24:mi:ss')
+                </if>
+            </if>
+            AND DEL=0
+            <include refid="net.mingsoft.base.dao.IBaseDao.sqlWhere"></include>
+        </where>
+        ORDER BY ID DESC
+    </select>
+
+</mapper>

+ 51 - 0
src/main/java/net/mingsoft/people/dao/IPeopleUserDao.java

@@ -0,0 +1,51 @@
+/**
+ * Copyright (c) 2012-present 铭软科技(mingsoft.net)
+ * 本软件及相关文档文件(以下简称“软件”)的版权归 铭软科技 所有
+ * 遵循 铭软科技《服务协议》中的《保密条款》
+ */
+
+
+
+
+package net.mingsoft.people.dao;
+
+
+import net.mingsoft.people.bean.PeopleBean;
+import net.mingsoft.people.entity.PeopleUserEntity;
+import org.apache.ibatis.annotations.Param;
+
+import net.mingsoft.base.dao.IBaseDao;
+
+import java.util.List;
+
+/**
+ * 
+ * 用户信息持久化层
+ * @author 铭飞开发团队
+ * @version 
+ * 版本号:0.0<br/>
+ * 创建日期:2017-8-23 10:10:22<br/>
+ * 历史修订:<br/>
+ */
+public interface IPeopleUserDao extends IBaseDao<PeopleUserEntity> {
+
+	/**
+	 * 根据用户id集合批量查询用户
+	 * @param peopleIds 用户id集合
+	 */
+	List<PeopleBean> queryBatchIds(@Param("peopleIds") List peopleIds);
+
+	/**
+	 * 根据用户信息查询用户
+	 * @param peopleBean 用户信息
+	 * @return 用户信息
+	 */
+	PeopleBean getByEntity(PeopleBean peopleBean);
+
+	/**
+	 * 根据用户信息批量查询用户信息
+	 * @param peopleBean 用户信息
+	 * @return 集合
+	 */
+	List<PeopleBean> query(PeopleBean peopleBean);
+}

+ 199 - 0
src/main/java/net/mingsoft/people/dao/IPeopleUserDao.xml

@@ -0,0 +1,199 @@
+<?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="net.mingsoft.people.dao.IPeopleUserDao">
+
+	<resultMap id="resultMap" type="net.mingsoft.people.bean.PeopleBean">
+		<id column="id" property="id"/><!-- 将实体的id属性与表的id字段对接 -->
+		<result column="PEOPLE_ID" property="peopleId" /><!--用户ID关联people表的(id) -->
+		<result column="PU_REAL_NAME" property="puRealName" /><!--用户真实名称 -->
+		<result column="PU_ADDRESS" property="puAddress" /><!--用户地址 -->
+		<result column="PU_ICON" property="puIcon" /><!--用户头像图标地址 -->
+		<result column="pu_level" property="puLevel" /><!--用户等级 -->
+		<result column="pu_level_name" property="puLevelName" /><!--用户等级名称 -->
+		<result column="PU_NICKNAME" property="puNickname" /><!--用户昵称 -->
+		<result column="PU_SEX" property="puSex" /><!--用户性别(0.未知、1.男、2.女) -->
+		<result column="PU_BIRTHDAY" property="puBirthday" /><!--用户出生年月日 -->
+		<result column="PU_CARD" property="puCard" /><!--身份证 -->
+		<result column="province_id" property="provinceId" /><!--城市选择 -->
+		<result column="province_name" property="provinceName" /><!--省 -->
+		<result column="city_name" property="cityName" /><!--城市 -->
+		<result column="county_name" property="countyName" /><!--区 -->
+		<result column="city_id" property="cityId" /><!--城市id -->
+		<result column="county_id" property="countyId" /><!--区id -->
+		<result column="PEOPLE_PHONE" property="peoplePhone"/><!-- 将实体的peoplePhone属性与表的peoplePhone字段对接 -->
+		<result column="PEOPLE_NAME" property="peopleName"/><!-- 将实体的peopleName属性与表的peopleName字段对接 -->
+		<result column="PEOPLE_PASSWORD" property="peoplePassword"/><!-- 将实体的peoplePwd属性与表的peoplePwd字段对接 -->
+		<result column="PEOPLE_DATETIME" property="peopleDateTime"/><!-- 将实体的peopleDateTime属性与表的peopleDateTime字段对接 -->
+		<result column="PEOPLE_STATE" property="peopleState"/><!-- 用户邮箱 -->
+		<result column="PEOPLE_MAIL" property="peopleMail"/><!-- 用户邮箱 -->
+		<result column="PEOPLE_MAILLCHECK" property="peopleMailCheck"/>
+		<result column="PEOPLE_PHONECHECK" property="peoplePhoneCheck"/>
+	</resultMap>
+
+
+	<!--保存-->
+	<insert id="saveEntity"
+		parameterType="net.mingsoft.people.entity.PeopleUserEntity" >
+		insert into people_user
+		<trim prefix="(" suffix=")" suffixOverrides=",">
+			<if test="id &gt; 0">PEOPLE_ID,</if>
+			<if test="puRealName != null and puRealName != ''">PU_REAL_NAME,</if>
+			<if test="puAddress != null and puAddress != ''">PU_ADDRESS,</if>
+			<if test="puLevel != null and puLevel != ''">pu_level,</if>
+			<if test="puLevelName != null and puLevelName != ''">pu_level_name,</if>
+			<if test="puIcon != null and puIcon != ''">PU_ICON,</if>
+			<if test="puNickname != null and puNickname != ''">PU_NICKNAME,</if>
+			<if test="puSex != null">PU_SEX,</if>
+			<if test="puBirthday != null">PU_BIRTHDAY,</if>
+			<if test="puCard != null and puCard != ''">PU_CARD,</if>
+			<if test="provinceId != null">province_id,</if>
+			<if test="provinceName != null and provinceName != ''">province_name,</if>
+			<if test="cityName != null and cityName != ''">city_name,</if>
+			<if test="countyName != null and countyName != ''">county_name,</if>
+			<if test="cityId != null">city_id,</if>
+			<if test="countyId != null">county_id,</if>
+		</trim>
+		<trim prefix="values (" suffix=")" suffixOverrides=",">
+			<if test="id">#{id},</if>
+			<if test="puRealName != null and puRealName != ''">#{puRealName},</if>
+			<if test="puAddress != null and puAddress != ''">#{puAddress},</if>
+			<if test="puLevel != null and puLevel != ''">#{puLevel},</if>
+			<if test="puLevelName != null and puLevelName != ''">#{puLevelName},</if>
+			<if test="puIcon != null and puIcon != ''">#{puIcon},</if>
+			<if test="puNickname != null and puNickname != ''">#{puNickname},</if>
+			<if test="puSex != null">#{puSex},</if>
+			<if test="puBirthday != null">#{puBirthday},</if>
+			<if test="puCard != null and puCard != ''">#{puCard},</if>
+			<if test="provinceId != null">#{provinceId},</if>
+			<if test="provinceName != null and provinceName != ''">#{provinceName},</if>
+			<if test="cityName != null and cityName != ''">#{cityName},</if>
+			<if test="countyName != null and countyName != ''">#{countyName},</if>
+			<if test="cityId != null">#{cityId},</if>
+			<if test="countyId != null">#{countyId},</if>
+		</trim>
+	</insert>
+
+	<!--更新-->
+	<update id="updateEntity" parameterType="net.mingsoft.people.entity.PeopleUserEntity">
+		update people_user
+		<set>
+			<if test="puRealName != null and puRealName != ''">PU_REAL_NAME=#{puRealName},</if>
+			<if test="puAddress != null and puAddress != ''">PU_ADDRESS=#{puAddress},</if>
+			<if test="puLevel != null and puLevel != ''">pu_level=#{puLevel},</if>
+			<if test="puLevelName != null and puLevelName != ''">pu_level_name=#{puLevelName},</if>
+			PU_ICON=#{puIcon},
+			<if test="puNickname != null and puNickname != ''">PU_NICKNAME=#{puNickname},</if>
+			<if test="puSex != null">PU_SEX=#{puSex},</if>
+			<if test="puBirthday != null">PU_BIRTHDAY=#{puBirthday},</if>
+			<if test="puCard != null and puCard != ''">PU_CARD=#{puCard},</if>
+			<if test="provinceId != null">province_id=#{provinceId},</if>
+			<if test="provinceName != null and provinceName != ''">province_name=#{provinceName},</if>
+			<if test="cityName != null and cityName != ''">city_name=#{cityName},</if>
+			<if test="countyName != null and countyName != ''">county_name=#{countyName},</if>
+			<if test="cityId != null">city_id=#{cityId},</if>
+			<if test="countyId != null">county_id=#{countyId},</if>
+		</set>
+		where PEOPLE_ID = #{peopleId}
+	</update>
+
+	<!--根据id获取-->
+	<select id="getEntity" resultMap="resultMap" parameterType="String">
+		select p.*, pu.* from people p left join people_user pu on
+		p.id = pu.PEOPLE_ID where pu.PEOPLE_ID=#{peopleId}
+	</select>
+
+	<!--根据实体获取-->
+	<select id="getByEntity" resultMap="resultMap" parameterType="net.mingsoft.people.bean.PeopleBean">
+		select p.*, pu.* from people p left join people_user pu on
+		p.id = PEOPLE_ID
+		<where>
+			<if test="peopleMailCheck &gt; 0">and PEOPLE_MAILLCHECK=#{peopleMailCheck}</if>
+		    <if test="peoplePhoneCheck &gt; 0">and PEOPLE_PHONECHECK=#{peoplePhoneCheck}</if>
+			<if test="puRealName != null and puRealName != ''"> and PU_REAL_NAME=#{puRealName} </if>
+			<if test="puAddress != null and puAddress != ''"> and PU_ADDRESS=#{puAddress} </if>
+			<if test="puLevel != null and puLevel != ''"> and pu_level=#{puLevel} </if>
+			<if test="puLevelName != null and puLevelName != ''"> and pu_level_name=#{puLevelName} </if>
+			<if test="puIcon != null and puIcon != ''"> and PU_ICON=#{puIcon} </if>
+			<if test="puNickname != null and puNickname != ''"> and PU_NICKNAME=#{puNickname} </if>
+			<if test="puSex != null"> and PU_SEX=#{puSex} </if>
+			<if test="puBirthday != null"> and PU_BIRTHDAY=#{puBirthday} </if>
+			<if test="puCard != null and puCard != ''"> and PU_CARD=#{puCard} </if>
+			<if test="provinceId != null"> and province_id=#{provinceId} </if>
+			<if test="provinceName != null and provinceName != ''">and province_name=#{provinceName}</if>
+			<if test="cityName != null and cityName != ''">and city_name=#{cityName}</if>
+			<if test="countyName != null and countyName != ''">and county_name=#{countyName}</if>
+			<if test="cityId != null"> and city_id=#{cityId} </if>
+			<if test="countyId != null"> and county_id=#{countyId} </if>
+			<if test="peopleMail != null and peopleMail !=''"> and PEOPLE_MAIL=#{peopleMail} </if>
+			<if test="peoplePhone != null and peoplePhone !=''"> and PEOPLE_PHONE=#{peoplePhone} </if>
+		</where>
+	</select>
+
+
+	<!--删除-->
+	<delete id="deleteEntity" parameterType="String">
+		delete from people_user  where PEOPLE_ID=#{id}
+	</delete>
+
+	<!--批量删除-->
+	<delete id="delete" >
+		delete from people_user
+		<where>
+			 PEOPLE_ID  in <foreach collection="ids" item="item" index="index"
+			open="(" separator="," close=")">#{item}</foreach>
+		</where>
+	</delete>
+	<!--查询全部-->
+	<select id="queryAll" resultMap="resultMap">
+		select * from people_user order by PEOPLE_ID desc
+	</select>
+	<!--条件查询-->
+	<select id="query" resultMap="resultMap">
+		select  p.*, pu.* from people p left join people_user pu on
+		p.id=PEOPLE_ID
+		<where>
+			<if test="peopleId != '' and peopleId != null">and PEOPLE_ID=#{peopleId}</if>
+			<if test="peopleState &gt; -1 and peopleState != null">and PEOPLE_STATE=#{peopleState}</if>
+			<if test="peopleName != null and peopleName != ''">and PEOPLE_NAME like CONCAT(CONCAT('%',#{peopleName}),'%')</if>
+			<if test="puRealName != null and puRealName != ''">and PU_REAL_NAME like CONCAT(CONCAT('%',#{puRealName}),'%')</if>
+			<if test="puAddress != null and puAddress != ''">and PU_ADDRESS=#{puAddress}</if>
+			<if test="puLevel != null and puLevel != ''">and pu_level=#{puLevel}</if>
+			<if test="puLevelName != null and puLevelName != ''">and pu_level_name=#{puLevelName}</if>
+			<if test="puIcon != null and puIcon != ''">and PU_ICON=#{puIcon}</if>
+			<if test="peopleMail != null and peopleMail != ''">and PEOPLE_MAIL like CONCAT(CONCAT('%',#{peopleMail}),'%')</if>
+			<if test="peoplePhone != null and peoplePhone != ''">and PEOPLE_PHONE like CONCAT(CONCAT('%',#{peoplePhone}),'%')</if>
+			<if test="puNickname != null and puNickname != ''">and PU_NICKNAME like CONCAT(CONCAT('%',#{puNickname}),'%')</if>
+			<if test="puSex &gt; 0">and PU_SEX=#{puSex}</if>
+			<if test="puBirthday != null">and PU_BIRTHDAY=#{puBirthday}</if>
+			<if test="puCard != null and puCard != ''">and PU_CARD=#{puCard}</if>
+			<if test="provinceId != null">and province_id=#{provinceId}</if>
+			<if test="provinceName != null and provinceName != ''">and province_name=#{provinceName}</if>
+			<if test="cityName != null and cityName != ''">and city_name=#{cityName}</if>
+			<if test="countyName != null and countyName != ''">and county_name=#{countyName}</if>
+			<if test="cityId != null">and city_id=#{cityId}</if>
+			<if test="countyId != null">and county_id=#{countyId}</if>
+			<if test="startTime != null and endTime != null">
+				<if test="_databaseId == 'mysql'">
+					and date_format(PEOPLE_DATETIME,'%Y-%m-%d') between #{startTime} and #{endTime}
+				</if>
+				<if test="_databaseId == 'oracle'">
+					and to_char(PEOPLE_DATETIME,'yyyy-mm-dd') > #{startTime}
+					and #{endTime} > to_char(PEOPLE_DATETIME,'yyyy-mm-dd')
+				</if>
+			</if>
+		</where>
+		order by p.PEOPLE_DATETIME desc
+	</select>
+
+
+	<!--批量查询-->
+	<select id="queryBatchIds" parameterType="java.util.List" resultMap="resultMap">
+		select  p.*, pu.* from people p left join people_user pu on
+		p.id=pu.PEOPLE_ID
+		<where>
+			pu.PEOPLE_ID  in <foreach collection="peopleIds" item="item" index="index"
+								   open="(" separator="," close=")">#{item}</foreach>
+		</where>
+	</select>
+
+</mapper>

+ 357 - 0
src/main/java/net/mingsoft/people/entity/PeopleEntity.java

@@ -0,0 +1,357 @@
+/**
+ * Copyright (c) 2012-present 铭软科技(mingsoft.net)
+ * 本软件及相关文档文件(以下简称“软件”)的版权归 铭软科技 所有
+ * 遵循 铭软科技《服务协议》中的《保密条款》
+ */
+
+
+
+
+package net.mingsoft.people.entity;
+
+import com.baomidou.mybatisplus.annotation.*;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import net.mingsoft.base.constant.e.BaseEnum;
+import net.mingsoft.base.entity.BaseEntity;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.util.Date;
+
+/**
+ *
+ * 用户基础表
+ * @author 铭飞开发团队
+ * @version
+ * 版本号:0.0<br/>
+ * 创建日期:2017-8-23 10:10:22<br/>
+ * 历史修订:<br/>
+ */
+@TableName("people")
+public class PeopleEntity extends BaseEntity {
+
+	/**
+	 * 雪花ID规则
+	 */
+	@TableId(type = IdType.ASSIGN_ID)
+	private String id;
+
+	@Override
+	public String getId() {
+		return id;
+	}
+
+	@Override
+	public void setId(String id) {
+		this.id = id;
+	}
+
+	/**
+	 * 不参表结构 大于0表示自动登录
+	 */
+	@TableField(exist = false)
+	private int peopleAutoLogin;
+
+	/**
+	 * 用户随机验证码
+	 */
+	private String peopleCode;
+
+	/**
+	 * 用户登录ip
+	 */
+	private String peopleIp;
+
+	/**
+	 * 发送验证码的时间
+	 */
+	@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
+	@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+	@TableField(value = "PEOPLE_CODESENDDATE")
+	private Date peopleCodeSendDate;
+
+	/**
+	 * 注册时间
+	 */
+	@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
+	@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+	@TableField(value = "PEOPLE_DATETIME")
+	private Date peopleDateTime;
+
+	/**
+	 * 用户邮箱</br>
+	 * 可用作登录</br>
+	 */
+	@TableField(updateStrategy = FieldStrategy.NOT_EMPTY)
+	private String peopleMail;
+
+	/**
+	 * 是否通过邮箱验证
+	 */
+	@TableField(value = "PEOPLE_MAILLCHECK")
+	private int peopleMailCheck = -1;
+
+	/**
+	 * 登录帐号
+	 */
+	private String peopleName;
+
+
+	/**
+	 * 旧密码,不参与表结构
+	 */
+	@TableField(exist = false)
+	@JsonIgnore
+	private String peopleOldPassword;
+
+	/**
+	 * 登录密码
+	 */
+	@JsonIgnore
+	@TableField(updateStrategy = FieldStrategy.NOT_EMPTY)
+	private String peoplePassword;
+
+	/**
+	 * 用户电话</br>
+	 * 可用作登录</br>
+	 */
+	@TableField(updateStrategy = FieldStrategy.NOT_EMPTY)
+	private String peoplePhone;
+
+	/**
+	 * 是否通过手机验证
+	 */
+	@TableField(value = "PEOPLE_PHONECHECK")
+	private int peoplePhoneCheck = -1;
+
+	/**
+	 * 用户状态 1.已审核 0.未审核
+	 */
+	private Integer peopleState;
+
+	/**
+	 * 用户真信息
+	 */
+	@TableField(exist = false)
+	private PeopleUserEntity peopleUser;
+
+	public int getPeopleAutoLogin() {
+		return peopleAutoLogin;
+	}
+
+	/**
+	 * 获取用户随机码
+	 *
+	 * @return
+	 */
+	public String getPeopleCode() {
+		return peopleCode;
+	}
+
+	public Date getPeopleCodeSendDate() {
+		return peopleCodeSendDate;
+	}
+
+	/**
+	 * 获取peopleDateTime
+	 *
+	 * @return peopleDateTime
+	 */
+	public Date getPeopleDateTime() {
+		return peopleDateTime;
+	}
+
+	/**
+	 * 获取peopleMail
+	 *
+	 * @return peopleMail
+	 */
+	public String getPeopleMail() {
+		return peopleMail;
+	}
+
+	public int getPeopleMailCheck() {
+		return peopleMailCheck;
+	}
+
+	/**
+	 * 获取peopleName
+	 *
+	 * @return peopleName
+	 */
+	public String getPeopleName() {
+		return peopleName;
+	}
+
+	public String getPeopleOldPassword() {
+		return peopleOldPassword;
+	}
+
+	/**
+	 * 获取peoplePassword
+	 *
+	 * @return peoplePassword
+	 */
+	public String getPeoplePassword() {
+		return peoplePassword;
+	}
+
+	/**
+	 * 获取peoplePhone
+	 *
+	 * @return peoplePhone
+	 */
+	public String getPeoplePhone() {
+		return peoplePhone;
+	}
+
+	public int getPeoplePhoneCheck() {
+		return peoplePhoneCheck;
+	}
+
+	/**
+	 * 获取peopleState
+	 *
+	 * @return peopleState
+	 */
+	public Integer getPeopleState() {
+		return peopleState;
+	}
+
+	public PeopleUserEntity getPeopleUser() {
+		return peopleUser;
+	}
+
+	public void setPeopleAutoLogin(int peopleAutoLogin) {
+		this.peopleAutoLogin = peopleAutoLogin;
+	}
+
+	/**
+	 * 设置用户随机码
+	 *
+	 * @param peopleCode
+	 */
+	public void setPeopleCode(String peopleCode) {
+		this.peopleCode = peopleCode;
+	}
+
+	public void setPeopleCodeSendDate(Date peopleCodeSendDate) {
+		this.peopleCodeSendDate = peopleCodeSendDate;
+	}
+
+	/**
+	 * 设置peopleDateTime
+	 *
+	 * @param peopleDateTime
+	 */
+	public void setPeopleDateTime(Date peopleDateTime) {
+		this.peopleDateTime = peopleDateTime;
+	}
+
+	/**
+	 * 设置peopleMail
+	 *
+	 * @param peopleMail
+	 */
+	public void setPeopleMail(String peopleMail) {
+		this.peopleMail = peopleMail;
+	}
+
+	public void setPeopleMailCheck(BaseEnum check) {
+		this.peopleMailCheck = check.toInt();
+	}
+
+	/**
+	 * 推荐使用枚举类形参方法
+	 *
+	 * @param peopleMailCheck
+	 */
+	@Deprecated
+	public void setPeopleMailCheck(int peopleMailCheck) {
+		this.peopleMailCheck = peopleMailCheck;
+	}
+
+	/**
+	 * 设置peopleName
+	 *
+	 * @param peopleName
+	 */
+	public void setPeopleName(String peopleName) {
+		this.peopleName = peopleName;
+	}
+
+	public void setPeopleOldPassword(String peopleOldPassword) {
+		this.peopleOldPassword = peopleOldPassword;
+	}
+
+	/**
+	 * 设置peoplePwd
+	 *
+	 * @param peoplePassword
+	 */
+	public void setPeoplePassword(String peoplePassword) {
+		this.peoplePassword = peoplePassword;
+	}
+
+	/**
+	 * 设置peoplePhone
+	 *
+	 * @param peoplePhone
+	 */
+	public void setPeoplePhone(String peoplePhone) {
+		this.peoplePhone = peoplePhone;
+	}
+
+
+	public void setPeoplePhoneCheck(BaseEnum check) {
+		this.peoplePhoneCheck = check.toInt();
+	}
+
+	/**
+	 * 推荐使用枚举类形参方法
+	 *
+	 * @param peoplePhoneCheck
+	 */
+	@Deprecated
+	public void setPeoplePhoneCheck(int peoplePhoneCheck) {
+		this.peoplePhoneCheck = peoplePhoneCheck;
+	}
+
+	/**
+	 * 设置peopleState
+	 */
+	@JsonIgnore
+	public void setPeopleStateEnum(BaseEnum e) {
+		this.peopleState = e.toInt();
+	}
+
+	/**
+	 * 设置peopleState,控制层推荐使用setPeopleState(BaseEnum e) 方法
+	 *
+	 * @param peopleState
+	 */
+	public void setPeopleState(Integer peopleState) {
+		this.peopleState = peopleState;
+	}
+
+	public void setPeopleUser(PeopleUserEntity peopleUser) {
+		this.peopleUser = peopleUser;
+	}
+
+	/**
+	 * 获取用户ip
+	 */
+	public String getPeopleIp() {
+		return peopleIp;
+	}
+	/**
+	 *设置用户ip
+	 */
+	public void setPeopleIp(String peopleIp) {
+		this.peopleIp = peopleIp;
+	}
+
+
+
+}

+ 232 - 0
src/main/java/net/mingsoft/people/entity/PeopleLogEntity.java

@@ -0,0 +1,232 @@
+/**
+ * Copyright (c) 2012-present 铭软科技(mingsoft.net)
+ * 本软件及相关文档文件(以下简称“软件”)的版权归 铭软科技 所有
+ * 遵循 铭软科技《服务协议》中的《保密条款》
+ */
+
+package net.mingsoft.people.entity;
+
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import net.mingsoft.base.entity.BaseEntity;
+
+/**
+ * 会员日志实体
+ *
+ * @author 铭软科技
+ * 创建日期:2023-6-6 11:51:32<br/>
+ * 历史修订:<br/>
+ */
+@TableName("PEOPLE_LOG")
+public class PeopleLogEntity extends BaseEntity {
+
+    private static final long serialVersionUID = 1686023492415L;
+
+
+    /**
+     * 雪花ID规则
+     */
+    @TableId(type = IdType.ASSIGN_ID)
+    private String id;
+
+
+    /**
+     * 会员编号
+     */
+    private String peopleId;
+
+    /**
+     * 标题
+     */
+    private String logTitle;
+
+    /**
+     * IP
+     */
+    private String logIp;
+
+    /**
+     * 所在地区
+     */
+    private String logAddr;
+
+    /**
+     * 日志类型
+     */
+
+    private String logType;
+
+    /**
+     * 日志状态
+     */
+
+    private String logStatus;
+
+    /**
+     * 请求参数
+     */
+
+    private String logParam;
+
+    /**
+     * 返回参数
+     */
+
+    private String logResult;
+
+    /**
+     * 日志信息
+     */
+
+    private String logInfo;
+
+    /**
+     * 错误消息
+     */
+
+    private String logErrorMsg;
+
+    /**
+     * 设置标题
+     */
+    public void setLogTitle(String logTitle) {
+        this.logTitle = logTitle;
+    }
+
+    /**
+     * 获取标题
+     */
+    public String getLogTitle() {
+        return this.logTitle;
+    }
+
+    /**
+     * 设置会员编号
+     */
+    public void setPeopleId(String peopleId) {
+        this.peopleId = peopleId;
+    }
+
+    /**
+     * 获取会员编号
+     */
+    public String getPeopleId() {
+        return this.peopleId;
+    }
+
+    /**
+     * 设置IP
+     */
+    public void setLogIp(String logIp) {
+        this.logIp = logIp;
+    }
+
+    /**
+     * 获取IP
+     */
+    public String getLogIp() {
+        return this.logIp;
+    }
+
+    /**
+     * 设置所在地区
+     */
+    public void setLogAddr(String logAddr) {
+        this.logAddr = logAddr;
+    }
+
+    /**
+     * 获取所在地区
+     */
+    public String getLogAddr() {
+        return this.logAddr;
+    }
+
+    /**
+     * 设置日志类型
+     */
+    public void setLogType(String logType) {
+        this.logType = logType;
+    }
+
+    /**
+     * 获取日志类型
+     */
+    public String getLogType() {
+        return this.logType;
+    }
+
+    /**
+     * 设置日志状态
+     */
+    public void setLogStatus(String logStatus) {
+        this.logStatus = logStatus;
+    }
+
+    /**
+     * 获取日志状态
+     */
+    public String getLogStatus() {
+        return this.logStatus;
+    }
+
+    /**
+     * 设置请求参数
+     */
+    public void setLogParam(String logParam) {
+        this.logParam = logParam;
+    }
+
+    /**
+     * 获取请求参数
+     */
+    public String getLogParam() {
+        return this.logParam;
+    }
+
+    /**
+     * 设置返回参数
+     */
+    public void setLogResult(String logResult) {
+        this.logResult = logResult;
+    }
+
+    /**
+     * 获取返回参数
+     */
+    public String getLogResult() {
+        return this.logResult;
+    }
+
+    /**
+     * 设置日志信息
+     */
+    public void setLogInfo(String logInfo) {
+        this.logInfo = logInfo;
+    }
+
+    /**
+     * 获取日志信息
+     */
+    public String getLogInfo() {
+        return this.logInfo;
+    }
+
+    /**
+     * 设置错误消息
+     */
+    public void setlogErrorMsg(String logErrorMsg) {
+        this.logErrorMsg = logErrorMsg;
+    }
+
+    /**
+     * 获取错误消息
+     */
+    public String getlogErrorMsg() {
+        return this.logErrorMsg;
+    }
+
+
+}

+ 320 - 0
src/main/java/net/mingsoft/people/entity/PeopleUserEntity.java

@@ -0,0 +1,320 @@
+/**
+ * Copyright (c) 2012-present 铭软科技(mingsoft.net)
+ * 本软件及相关文档文件(以下简称“软件”)的版权归 铭软科技 所有
+ * 遵循 铭软科技《服务协议》中的《保密条款》
+ */
+
+
+
+
+package net.mingsoft.people.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import net.mingsoft.base.entity.BaseEntity;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.util.Date;
+
+ /**
+ * 用户基础信息表实体
+ * @author 伍晶晶
+ * @version 
+ * 版本号:0.0<br/>
+ * 创建日期:2017-8-23 10:10:22<br/>
+ * 历史修订:<br/>
+ */
+ @TableName("people_user")
+public class PeopleUserEntity extends BaseEntity {
+
+	private static final long serialVersionUID = 1503454222227L;
+
+	 /**
+	  * 雪花ID规则
+	  */
+	 @TableId(type = IdType.ASSIGN_ID)
+	 private String id;
+
+	 @Override
+	 public String getId() {
+		 return id;
+	 }
+
+	 @Override
+	 public void setId(String id) {
+		 this.id = id;
+	 }
+
+	/**
+	 * 用户ID关联people表的(people_id)
+	 */
+	private String peopleId;
+	/**
+	 * 用户真实名称
+	 */
+	private String puRealName; 
+	/**
+	 * 用户地址
+	 */
+	private String puAddress;
+
+	 /**
+	  * 用户等级
+	  */
+	private String puLevel;
+
+	 /**
+	  * 等级名称
+	  */
+	private String puLevelName;
+	/**
+	 * 用户头像图标地址
+	 */
+	private String puIcon; 
+	/**
+	 * 用户昵称
+	 */
+	private String puNickname; 
+	/**
+	 * 用户性别(0.未知、1.男、2.女)
+	 */
+	private Integer puSex;
+	/**
+	 * 用户出生年月日
+	 */
+	@DateTimeFormat(pattern = "yyyy-MM-dd")
+	@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd")
+	private Date puBirthday;
+	/**
+	 * 身份证
+	 */
+	private String puCard;
+
+     /**
+      * 城市选择
+      */
+     private Long provinceId;
+     /**
+      * 省
+      */
+     private String provinceName;
+	 /**
+	  * 城市id
+	  */
+	 private Long cityId;
+     /**
+      * 城市
+      */
+     private String cityName;
+	 /**
+	  * 区id
+	  */
+	 private Long countyId;
+     /**
+      * 区
+      */
+     private String countyName;
+
+	 public String getPeopleId() {
+		 return peopleId;
+	 }
+
+	 public void setPeopleId(String peopleId) {
+		 this.peopleId = peopleId;
+	 }
+
+	 /**
+	 * 设置用户真实名称
+	 */
+	public void setPuRealName(String puRealName) {
+		this.puRealName = puRealName;
+	}
+
+	/**
+	 * 获取用户真实名称
+	 */
+	public String getPuRealName() {
+		return this.puRealName;
+	}
+	
+	/**
+	 * 设置用户地址
+	 */
+	public void setPuAddress(String puAddress) {
+		this.puAddress = puAddress;
+	}
+
+	/**
+	 * 获取用户地址
+	 */
+	public String getPuAddress() {
+		return this.puAddress;
+	}
+
+	 public String getPuLevel() {
+		 return puLevel;
+	 }
+
+	 public void setPuLevel(String puLevel) {
+		 this.puLevel = puLevel;
+	 }
+
+	 public String getPuLevelName() {
+		 return puLevelName;
+	 }
+
+	 public void setPuLevelName(String puLevelName) {
+		 this.puLevelName = puLevelName;
+	 }
+
+	 /**
+	 * 设置用户头像图标地址
+	 */
+	public void setPuIcon(String puIcon) {
+		this.puIcon = puIcon;
+	}
+
+	/**
+	 * 获取用户头像图标地址
+	 */
+	public String getPuIcon() {
+		return this.puIcon;
+	}
+	
+	/**
+	 * 设置用户昵称
+	 */
+	public void setPuNickname(String puNickname) {
+		this.puNickname = puNickname;
+	}
+
+	/**
+	 * 获取用户昵称
+	 */
+	public String getPuNickname() {
+		return this.puNickname;
+	}
+	
+	/**
+	 * 设置用户性别(0.未知、1.男、2.女)
+	 */
+	public void setPuSex(Integer puSex) {
+		this.puSex = puSex;
+	}
+
+	/**
+	 * 获取用户性别(0.未知、1.男、2.女)
+	 */
+	public Integer getPuSex() {
+		return this.puSex;
+	}
+	
+	/**
+	 * 设置用户出生年月日
+	 */
+	public void setPuBirthday(Date puBirthday) {
+		this.puBirthday = puBirthday;
+	}
+
+	/**
+	 * 获取用户出生年月日
+	 */
+	public Date getPuBirthday() {
+		return this.puBirthday;
+	}
+	
+	/**
+	 * 设置身份证
+	 */
+	public void setPuCard(String puCard) {
+		this.puCard = puCard;
+	}
+
+	/**
+	 * 获取身份证
+	 */
+	public String getPuCard() {
+		return this.puCard;
+	}
+     /**
+      * 设置城市选择
+      */
+     public void setProvinceId(Long provinceId) {
+         this.provinceId = provinceId;
+     }
+
+     /**
+      * 获取城市选择
+      */
+     public Long getProvinceId() {
+         return this.provinceId;
+     }
+     /**
+      * 设置省
+      */
+     public void setProvinceName(String provinceName) {
+         this.provinceName = provinceName;
+     }
+
+     /**
+      * 获取省
+      */
+     public String getProvinceName() {
+         return this.provinceName;
+     }
+     /**
+      * 设置城市
+      */
+     public void setCityName(String cityName) {
+         this.cityName = cityName;
+     }
+
+     /**
+      * 获取城市
+      */
+     public String getCityName() {
+         return this.cityName;
+     }
+     /**
+      * 设置区
+      */
+     public void setCountyName(String countyName) {
+         this.countyName = countyName;
+     }
+
+     /**
+      * 获取区
+      */
+     public String getCountyName() {
+         return this.countyName;
+     }
+     /**
+      * 设置城市id
+      */
+     public void setCityId(Long cityId) {
+         this.cityId = cityId;
+     }
+
+     /**
+      * 获取城市id
+      */
+     public Long getCityId() {
+         return this.cityId;
+     }
+     /**
+      * 设置区id
+      */
+     public void setCountyId(Long countyId) {
+         this.countyId = countyId;
+     }
+
+     /**
+      * 获取区id
+      */
+     public Long getCountyId() {
+         return this.countyId;
+     }
+ }

+ 83 - 0
src/main/java/net/mingsoft/people/filter/PeopleLoginFilter.java

@@ -0,0 +1,83 @@
+/**
+ * Copyright (c) 2012-present 铭软科技(mingsoft.net)
+ * 本软件及相关文档文件(以下简称“软件”)的版权归 铭软科技 所有
+ * 遵循 铭软科技《服务协议》中的《保密条款》
+ */
+
+package net.mingsoft.people.filter;
+
+import cn.hutool.json.JSONUtil;
+import jakarta.servlet.ServletRequest;
+import jakarta.servlet.ServletResponse;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import net.mingsoft.base.entity.ResultData;
+import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
+import org.springframework.http.HttpStatus;
+
+import java.io.PrintWriter;
+
+/**
+ * 会员身份校验过滤器 在shiroConfig中进行注册 拦截/people/**接口
+ */
+public class PeopleLoginFilter extends FormAuthenticationFilter {
+
+    /**
+     * 构造会员身份过滤器并设置登录地址
+     * @param loginUrl 会员登录地址
+     */
+    public PeopleLoginFilter(String loginUrl) {
+        super();
+        setLoginUrl(loginUrl);
+    }
+
+    /**
+     * 前端options请求放行
+     */
+    @Override
+    protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
+        HttpServletRequest request1 = (HttpServletRequest) request;
+        //获取请求方式
+        String method = request1.getMethod();
+        //如果是options请求方式,则放行
+        if("OPTIONS".equalsIgnoreCase(method)){
+            return true;
+        }
+
+        return super.isAccessAllowed(request, response, mappedValue);
+    }
+
+    /**
+     * 身份认证没有通过是的执行方法
+     */
+    @Override
+    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
+        HttpServletRequest req = (HttpServletRequest)request;
+        HttpServletResponse resp = (HttpServletResponse) response;
+        if (this.isLoginRequest(request, response)) {
+            if (this.isLoginSubmission(request, response)) {
+                return this.executeLogin(request, response);
+            } else {
+                return true;
+            }
+        } else {
+            String ajaxHeader = req.getHeader("X-Requested-With");
+            if (ajaxHeader != null || req.getHeader("X-TOKEN") != null) {
+                //前端Ajax请求,则不会重定向
+                resp.setHeader("Access-Control-Allow-Origin",  req.getHeader("Origin"));
+                resp.setHeader("Access-Control-Allow-Credentials", "true");
+                resp.setContentType("application/json; charset=utf-8");
+                resp.setCharacterEncoding("UTF-8");
+                resp.setStatus(HttpStatus.UNAUTHORIZED.value());
+                PrintWriter out = resp.getWriter();
+                ResultData data = ResultData.build().code(HttpStatus.UNAUTHORIZED).msg("未检测到登录信息,请重新登录");
+                out.println(JSONUtil.toJsonStr(data));
+                out.flush();
+                out.close();
+            }else {
+                this.saveRequestAndRedirectToLogin(request, response);
+            }
+            return false;
+        }
+    }
+}

+ 66 - 0
src/main/java/net/mingsoft/people/realm/PeopleAuthRealm.java

@@ -0,0 +1,66 @@
+/**
+ * Copyright (c) 2012-present 铭软科技(mingsoft.net)
+ * 本软件及相关文档文件(以下简称“软件”)的版权归 铭软科技 所有
+ * 遵循 铭软科技《服务协议》中的《保密条款》
+ */
+
+package net.mingsoft.people.realm;
+
+import jakarta.annotation.Resource;
+import net.mingsoft.basic.realm.BaseAuthRealm;
+import net.mingsoft.basic.realm.CustomUserNamePasswordToken;
+import net.mingsoft.people.biz.IPeopleBiz;
+import net.mingsoft.people.entity.PeopleEntity;
+import org.apache.shiro.authc.*;
+import org.apache.shiro.authz.AuthorizationException;
+import org.apache.shiro.authz.AuthorizationInfo;
+import org.apache.shiro.authz.SimpleAuthorizationInfo;
+import org.apache.shiro.subject.PrincipalCollection;
+
+public class PeopleAuthRealm extends BaseAuthRealm {
+
+    @Resource
+    private IPeopleBiz peopleBiz;
+
+    public PeopleAuthRealm() {
+        super();
+        super.setName(this.getClass().getName());
+        setCredentialsMatcher(new PeopleLoginMD5CredentialsMatcher());
+
+    }
+
+    @Override
+    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
+        UsernamePasswordToken upToken = (UsernamePasswordToken) token;
+        PeopleEntity people =  peopleBiz.getEntityByUserName(upToken.getUsername());
+        if (people != null) {
+            return new SimpleAuthenticationInfo(people, people.getPeoplePassword(), getName());
+        }
+        return null;
+    }
+
+    @Override
+    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
+        // 授权当前会员角色信息,防止会员请求
+        SimpleAuthorizationInfo info= new SimpleAuthorizationInfo();
+        info.addRole(CustomUserNamePasswordToken.AuthType.PEOPLE.toString());
+        return info;
+    }
+
+    @Override
+    public boolean supports(AuthenticationToken token) {
+        if (token instanceof CustomUserNamePasswordToken customUserNamePasswordToken) {
+            return customUserNamePasswordToken.getAuthType() == CustomUserNamePasswordToken.AuthType.PEOPLE;
+        }
+        return false;
+    }
+
+    @Override
+    public boolean hasRole(PrincipalCollection principal, String roleIdentifier) {
+        // 校验当前登录人是否是会员类型登录,防止请求错乱
+        if (principal.getPrimaryPrincipal() instanceof PeopleEntity && CustomUserNamePasswordToken.AuthType.PEOPLE.toString().equals(roleIdentifier)) {
+            return super.hasRole(principal, roleIdentifier);
+        }
+        return false;
+    }
+}

+ 36 - 0
src/main/java/net/mingsoft/people/realm/PeopleLoginMD5CredentialsMatcher.java

@@ -0,0 +1,36 @@
+/**
+ * Copyright (c) 2012-present 铭软科技(mingsoft.net)
+ * 本软件及相关文档文件(以下简称“软件”)的版权归 铭软科技 所有
+ * 遵循 铭软科技《服务协议》中的《保密条款》
+ */
+
+package net.mingsoft.people.realm;
+
+import org.apache.shiro.authc.AuthenticationInfo;
+import org.apache.shiro.authc.AuthenticationToken;
+import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+public class PeopleLoginMD5CredentialsMatcher extends HashedCredentialsMatcher {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(PeopleLoginMD5CredentialsMatcher.class);
+
+    public PeopleLoginMD5CredentialsMatcher() {
+        super();
+        // 设置加密算法为MD5
+        setHashAlgorithmName("MD5");
+        // 设置加密次数为1次
+        setHashIterations(1);
+        // 设置是否存储为十六进制字符串
+        setStoredCredentialsHexEncoded(true);
+    }
+
+    @Override
+    public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {
+        boolean matches = super.doCredentialsMatch(token, info);
+        LOGGER.debug("People MD5密码校验结果: {}", matches);
+        return matches;
+    }
+}

+ 55 - 0
src/main/java/net/mingsoft/people/resources/resources_en_US.properties

@@ -0,0 +1,55 @@
+#\u4F1A\u5458\u7248\u672C
+version=1e9885a45cc02276c79f6215ff2211a0
+
+#----------\u7528\u6237\u6A21\u5757-------
+people = user
+people.username = user name
+people.name = user name
+people.password = password
+people.old.password = old password
+people.phone = phone number
+people.mail = mailbox
+people.login = login
+people.register = register
+people.get.password=Retrieve password
+people.set.phone=Change mobile phone number
+people.address=Incomplete address information
+people.code=Verification code
+people.phone.code=Mobile verification code
+people.mail.code=Mail verification code
+people.code.time.error=verification codes are sent frequently
+people.card=ID number
+people.space=cannot contain spaces
+people.no.exist=user name or password
+#---------------\u6CE8\u518C\u7528\u6237\u65F6\u90AE\u7BB1\u53D1\u9001\u5185\u5BB9-----
+people.register.title=Registration verification
+people.register.content=Registration verification code
+peopleImageCode=Verification code
+peopleCode=random code
+people.state.error=people not reviewed
+pu.icon=User avatar icon address
+pu.address=User address
+pu.district=District
+pu.app.id= User ID
+pu.real.name=User\u2019s real name
+pu.birthday=User\u2019s birth date
+pu.people.id=User ID
+pu.street=Street
+pu.sex=User gender
+pu.card=ID card
+pu.province =province
+pu.nickname=user nickname
+pu.city=city
+receive=receive user
+type=type
+templet.file=template file does not exist
+
+people.user.msg.null.error=Please fill in the information\!
+people.user.save.msg.success=Successfully added user details\!
+people.user.update.msg.success=Update user details successfully\!
+people.session.name.mismatch.error=Please enter the currently logged in user name!
+
+log.ip=log ip
+log.info=log info
+log.type=log type
+log.addr=log addr

+ 55 - 0
src/main/java/net/mingsoft/people/resources/resources_zh_CN.properties

@@ -0,0 +1,55 @@
+#\u4F1A\u5458\u7248\u672C
+version=1e9885a45cc02276c79f6215ff2211a0
+
+#----------\u7528\u6237\u6A21\u5757-------
+people = \u7528\u6237
+people.username = \u7528\u6237\u540D
+people.name = \u7528\u6237\u540D
+people.password = \u5BC6\u7801
+people.old.password = \u65E7\u5BC6\u7801
+people.phone = \u624B\u673A\u53F7
+people.mail = \u90AE\u7BB1
+people.login = \u767B\u9646
+people.register= \u6CE8\u518C
+people.get.password=\u53D6\u56DE\u5BC6\u7801
+people.set.phone=\u66F4\u6539\u624B\u673A\u53F7\u7801
+people.address=\u5730\u5740\u4FE1\u606F\u4E0D\u5168
+people.code=\u9A8C\u8BC1\u7801
+people.phone.code=\u624B\u673A\u9A8C\u8BC1\u7801
+people.mail.code=\u90AE\u7BB1\u9A8C\u8BC1\u7801
+people.code.time.error=\u9A8C\u8BC1\u7801\u53D1\u9001\u9891\u7E41
+people.card=\u8EAB\u4EFD\u8BC1\u53F7\u7801
+people.space=\u4E0D\u80FD\u542B\u6709\u7A7A\u683C
+people.no.exist=\u7528\u6237\u540D\u6216\u5BC6\u7801
+#---------------\u6CE8\u518C\u7528\u6237\u65F6\u90AE\u7BB1\u53D1\u9001\u5185\u5BB9-----
+people.register.title=\u6CE8\u518C\u9A8C\u8BC1
+people.register.content=\u6CE8\u518C\u9A8C\u8BC1\u7801
+peopleImageCode=\u9A8C\u8BC1\u7801
+peopleCode=\u968F\u673A\u7801
+
+pu.icon=\u7528\u6237\u5934\u50CF\u56FE\u6807\u5730\u5740
+pu.address=\u7528\u6237\u5730\u5740
+pu.district=\u533A
+pu.app.id=\u7528\u6237\u6240\u5C5E\u5E94\u7528ID
+pu.real.name=\u7528\u6237\u771F\u5B9E\u540D\u79F0
+pu.birthday=\u7528\u6237\u51FA\u751F\u5E74\u6708\u65E5
+pu.people.id=\u7528\u6237ID
+pu.street=\u8857\u9053
+pu.sex=\u7528\u6237\u6027\u522B
+pu.card=\u8EAB\u4EFD\u8BC1
+pu.province=\u7701
+pu.nickname=\u7528\u6237\u6635\u79F0
+pu.city=\u57CE\u5E02
+receive=\u63A5\u6536\u7528\u6237
+type=\u7C7B\u578B
+templet.file=\u6A21\u677F\u6587\u4EF6\u4E0D\u5B58\u5728
+people.state.error=\u7528\u6237\u672A\u5BA1\u6838
+people.user.msg.null.error=\u8BF7\u586B\u5199\u4FE1\u606F\!
+people.user.save.msg.success=\u65B0\u589E\u7528\u6237\u8BE6\u7EC6\u4FE1\u606F\u6210\u529F\!
+people.user.update.msg.success=\u66F4\u65B0\u7528\u6237\u8BE6\u7EC6\u4FE1\u606F\u6210\u529F\!
+people.session.name.mismatch.error=\u8BF7\u8F93\u5165\u5F53\u524D\u767B\u5F55\u7684\u7528\u6237\u540D\uFF01
+
+log.ip=IP
+log.info=\u65E5\u5FD7\u4FE1\u606F
+log.type=\u65E5\u5FD7\u7C7B\u578B
+log.addr=\u6240\u5728\u5730\u533A

+ 30 - 0
src/main/java/net/mingsoft/people/util/PeopleUtil.java

@@ -0,0 +1,30 @@
+/**
+ * Copyright (c) 2012-present 铭软科技(mingsoft.net)
+ * 本软件及相关文档文件(以下简称“软件”)的版权归 铭软科技 所有
+ * 遵循 铭软科技《服务协议》中的《保密条款》
+ */
+
+package net.mingsoft.people.util;
+
+import net.mingsoft.people.bean.PeopleBean;
+import org.apache.shiro.SecurityUtils;
+import org.apache.shiro.authz.UnauthorizedException;
+import org.apache.shiro.subject.Subject;
+
+/**
+ * 会员工具类
+ */
+public class PeopleUtil {
+
+    /**
+     * 从shiro中获取会员信息.没有直接抛出shiro未登录异常
+     */
+    public static PeopleBean getPeopleBean() {
+        Subject subject = SecurityUtils.getSubject();
+        if(subject.getPrincipal() instanceof PeopleBean) {
+            return  (PeopleBean) subject.getPrincipal();
+        }
+        throw new UnauthorizedException();
+    }
+
+}

+ 874 - 0
src/main/webapp/WEB-INF/manager/index.ftl

@@ -0,0 +1,874 @@
+<!-- 主页 -->
+<!DOCTYPE html>
+<html>
+<head>
+    <title>MCms</title>
+    <#include '/include/head-file.ftl'/>
+
+    <script src="${base}/static/plugins/sockjs/1.4.0/sockjs.min.js"></script>
+    <script src="${base}/static/plugins/stomp/2.3.3/stomp.min.js"></script>
+
+    <style>
+        .to-ele {
+            font-size: 18px;
+            margin: -2px 9px 0px 3px
+        }
+    </style>
+</head>
+<body>
+<#include 'basic/components/reset-password.ftl'/>
+<#include 'basic/components/switch-theme.ftl'/>
+<#include 'basic/components/manager-icon.ftl'/>
+<div id="index" class="index">
+    <el-container  :class="theme">
+        <!--左侧菜单-->
+        <el-aside class="ms-admin-menu-aside" v-cloak>
+            <el-scrollbar style="height:100%">
+                <el-menu :default-active="asideMenuActive" class="el-menu-vertical-demo"
+                         text-color="rgba(255,255,255,1)" active-text-color="rgba(255,255,255,1)"
+                         :collapse="collapseMenu" :unique-opened='true' ref='menu'>
+                    <div class="ms-admin-logo" :style="{display: 'flex','padding-left': (collapseMenu?'5px':'22px')}">
+                        <img :src="ms.base+'/static/images/ms.png'"/>
+                        <div class="class-1" v-show="!collapseMenu">
+                            <div class="class-2">v</div>
+                            6.0.3
+                        </div>
+                    </div>
+                    <template v-for="(menu,i) in asideMenuList" :key='i'>
+
+                        <el-sub-menu  v-if="!menu.isSingle" :popper-class="'ms-admin-menu-aside-submenu '+theme" :index="menu.id+''">
+                            <template #title>
+                                <!-- 修改图标样式使其与文字对齐 -->
+                                <i :class="['ms-admin-icon','iconfont',menu.modelIcon?menu.modelIcon:'icon-zidingyimoxing']"
+                                   style="margin-right: 4px;"></i>
+                                <span>{{ menu.modelTitle }}</span>
+                            </template>
+                            <!-- 子菜单 -->
+                            <el-menu-item :index="sub.id+''"
+                                          v-for="(sub,index) in getSubMenu(menu.id)"
+                                          :key='sub.modelId' v-text="sub.modelTitle"
+                                          @click.self='open(sub)'></el-menu-item>
+                        </el-sub-menu>
+                        <!-- 子菜单 -->
+                        <el-menu-item v-else :index="menu.id+''" style="margin-left: 2px"
+                                      :key='menu.modelId'
+                                      @click.self='open(menu)'>
+                            <i :class="['ms-admin-icon','iconfont',menu.modelIcon?menu.modelIcon:'icon-zidingyimoxing']" style="margin-right: 4px;"></i>
+                            <span>{{menu.modelTitle}}</span>
+                        </el-menu-item>
+                    </template>
+                    <!--  当没有菜单显示时显示提示图片  -->
+                    <img v-if="asideMenuList.length == 0 " :src="ms.base+'/static/images/tip.png'" />
+                    <!-- 收缩按钮 -->
+                </el-menu>
+            </el-scrollbar>
+        </el-aside>
+        <!--右侧内容-->
+        <el-container class="ms-admin-container" v-cloak>
+            <!--头部-->
+            <el-header class="ms-admin-header" v-cloak>
+                <!--展示合并菜单-->
+                <div class="ms-admin-header-menu-shrink" @click="collapseMenu = !collapseMenu">
+                    <i class="iconfont"
+                       :class="collapseMenu?'icon-liebiaoxiangyou':'icon-shousuo'"></i>
+                </div>
+                <!--头部menu-->
+                <el-menu menu-trigger="hover" class="ms-admin-header-menu"
+                         mode="horizontal" :ellipsis="false" >
+                    <el-sub-menu index="1" style="height: 100%">
+                        <template #title>
+                            <i class="iconfont icon-gezi" style="font-size: 17px;margin-right:8PX"></i>
+                            <span>功能大全</span>
+                        </template>
+                        <div class="ms-admin-header-menu-all" v-if="parentMenuList.length > 0">
+                            <li class="ms-admin-header-menu-all-item" v-for="(item,index) of parentMenuList"
+                                :key='index'>
+                                <div  style="display:flex;" @click='openMenu(item,index)'>
+                                    <i :class="['iconfont',item.modelIcon?item.modelIcon:'icon-zidingyimoxing']" style="padding-right: 4px"></i>
+                                    <div style="width:80px">{{item.modelTitle}}</div>
+                                </div>
+                                <div style="float: right;width: 18px;">
+                                    <i  @click="item.isMark=!item.isMark"
+                                        :class="item.isMark?'el-icon-star-on ':'el-icon-star-off'"></i>
+                                </div>
+
+                            </li>
+                        </div>
+                        <div style="display: flex; justify-content: center; width: 100%;"  v-else>
+                            <el-empty :image-size="50" description="无菜单,请检查站点信息" />
+                        </div>
+                    </el-sub-menu>
+                </el-menu>
+                <!--头部右侧-->
+                <div class="ms-admin-header-right">
+                    <!-- 主题切换 -->
+                    <ms-switch-theme :theme="theme" @update-theme="updateTheme"></ms-switch-theme>
+                    <!-- 设置 -->
+                    <ms-manager-icon :manager="managerInfo">
+                        <template #default>
+                            <el-menu-item
+                                    style="display: flex;align-items: center" @click='$refs.resetPasswordForm.open()' index="reset-password">
+                                <i class="el-icon-key"></i>
+                                <span slot="title">修改密码</span>
+                            </el-menu-item>
+                        </template>
+                    </ms-manager-icon>
+                    <!--mstore按钮-->
+                    <#--<ms-store ref="storec" client="${client}"></ms-store>-->
+                </div>
+
+            </el-header>
+            <!--内容-->
+            <el-main class="ms-admin-main">
+                <!--选项卡-->
+                <el-tabs class="ms-admin-tabs" v-model="currentTab" type="card" closable @tab-remove="closeTab"
+                         @tab-click='tabClick' tab-position="top">
+                    <el-tab-pane v-for="(item, index) in editableTabs"
+                                 :key="index"
+                                 :label="item.modelTitle"
+                                 :name="item.id">
+                        <keep-alive>
+                            <iframe :src='item.modelUrl.startsWith("http")||item.modelUrl.startsWith("https")||item.isStore?item.modelUrl:ms.manager+"/"+encodeURI(item.modelUrl)+(item.modelUrl.indexOf("?")==-1?"?":"&")'
+                                    :ref="item.id" :style="{background:'url('+ms.base+'/static/images/loading.gif) no-repeat center'}"></iframe>
+                        </keep-alive>
+                    </el-tab-pane>
+                </el-tabs>
+            </el-main>
+        </el-container>
+    </el-container>
+    <reset-password ref="resetPasswordForm" :manager="managerInfo"  ></reset-password>
+</div>
+</body>
+
+</html>
+<script>
+
+    const indexVue = new _Vue({
+        el: "#index",
+        components:{
+            MsManagerIcon,
+            MsSwitchTheme,
+            ResetPassword
+        },
+        data: function () {
+            return {
+                menuList: [], //菜单接口数据
+                asideMenuList: [], //侧边菜单
+                parentMenuList: [], //一级菜单
+                subMenuList: [], //二级菜单 所有
+                asideMenuActive: "", //左侧选中菜单
+                headMenuActive: '', //头部菜单激活
+                editableTabs: [{"modelTitle": "工作台", "id": "0", "modelUrl": "main.do"}], //当前打开的tab页面
+                collapseMenu: false, //菜单折叠,false不折叠
+                currentTab: '0', //当前激活tab的name,初始值为工作台id
+                //登录用户信息
+                managerInfo: {
+                    managerName: '', //账号
+                    managerNickName: '',
+                },
+                mstore: {},
+                //主题
+                theme: localStorage.getItem("theme") || 'ms-theme-light',
+                appId:'',
+                managerPermissions: [], // 管理员拥有的权限
+            }
+        },
+        computed: {
+        },
+        watch: {
+            parentMenuList: {
+                handler: function (n, o) {
+                    localStorage.setItem(this.managerInfo.managerName + "-parent-menu-list-" + this.appId, JSON.stringify(n))
+                },
+                deep: true
+            },
+            editableTabs: {
+                handler: function (n, o) {
+                    if (n.length) {
+                        var that = this;
+                        if (!document.querySelector('.el-icon-refresh')) {
+                            var i = document.createElement('i');
+                            i.className = "el-icon-refresh ms-admin-refresh"
+                            i.title = "点击刷新当前页"
+                            i.addEventListener('click', function () {
+                                var index = null
+                                Object.keys(that.$refs).forEach(function (item, i) {
+                                    item.indexOf(that.currentTab) > -1 ? index = i : ''
+                                }, that)
+                                if(that.$refs[Object.keys(that.$refs)[index]][0].contentDocument!=null) {
+                                    that.$refs[Object.keys(that.$refs)[index]][0].contentDocument.location.reload(true)
+                                }
+
+                            })
+                            document.querySelector('.el-tabs__header').appendChild(i, document.querySelector('.el-tabs__nav-wrap'))
+                        }
+                    } else {
+                        if (document.querySelector('.ms-admin-refresh')) {
+                            document.querySelector('.el-tabs__header').removeChild(document.querySelector('.ms-admin-refresh'))
+                        }
+                    }
+                },
+                deep: true
+            }
+        },
+        methods: {
+			/**
+			 * 获取当前应用
+			 */
+			getApp: function (){
+				var that = this;
+				ms.http.get(ms.manager + "/basic/app/get.do").then(function (res){
+					if (res.result){
+						that.appId = res.data.id;
+                        // 修改标题
+                        document.title = res.data.appName;
+						that.list();
+					}
+				})
+			},
+            /**
+             * 获取菜单列表
+             */
+            list: function () {
+                var that = this;
+                ms.http.get(ms.manager + "/basic/model/list.do")
+                    .then(function (res) {
+                        that.menuList = res.data.rows;
+                        //获取收藏
+                        var markList = localStorage.getItem(that.managerInfo.managerName + "-parent-menu-list-" + that.appId);
+
+                        //组织顶部功能大全显示菜单
+                        that.menuList.forEach(function (item, index) {
+                            //如果没有收藏,默认全部显示
+                            if(markList == null) {
+                                item.isMark = true;
+                            } else {
+                                item.isMark = false;
+                            }
+                            //判断是否是一级菜单,简单判断通过url,如果菜单有地址就表示为一级菜单
+                            if(item.modelUrl) {
+                                item.isSingle = true;
+                            }
+
+                            //如果是顶级菜单增加
+                            item.modelId ? that.subMenuList.push(item) : that.parentMenuList.push(item);
+                            // 添加管理员具有的权限
+                            if(item.modelIsMenu===0){
+                                that.managerPermissions.push(item.modelUrl);
+                            }
+                        })
+                        // 每次进主页都更新管理员拥有的菜单权限
+                        sessionStorage.setItem("manager-permission-list", JSON.stringify(that.managerPermissions))
+                        //如果收藏就优先显示收藏
+                        if(markList) {
+                            var markMenuList = JSON.parse(markList);
+                            // 遍历最新的菜单覆盖缓存的菜单,避免菜单变化导致缓存菜单没更新
+                            that.parentMenuList.forEach(function (item){
+                                markMenuList.forEach(function (markItem){
+                                    if (item.id === markItem.id){
+                                        item.isMark = markItem.isMark;
+                                        //更新缓存中的菜单数据
+                                        markItem = item;
+                                    }
+                                })
+                            })
+                            //更新缓存
+                            localStorage.setItem(that.managerInfo.managerName + "-parent-menu-list-" + that.appId, JSON.stringify(markMenuList))
+                        }
+
+                        //简单深度复制一下,否则数据无法双向绑定
+                        that.parentMenuList = JSON.parse(JSON.stringify(that.parentMenuList));
+
+                        //左侧菜单也显示收藏的菜单
+                        that.parentMenuList.forEach(function (item) {
+                            if(item.isMark) {
+                                that.asideMenuList.push(item);
+                            }
+                        })
+
+                    }, function (err) {
+                        that.$notify({
+                            title: '错误',
+                            message: err,
+                            type: 'error'
+                        });
+                })
+            },
+            /**
+             * 左侧菜单打开页面
+             * @param sub
+             */
+            open: function (sub) {
+                var that = this
+                var result = '';
+                result = this.editableTabs.some(function (item, index) {
+                    return item.id == sub.id
+                })
+
+                if (sub.syncStoreUrl) {
+                    sub.modelUrl = sub.syncStoreUrl;
+                    sub.modelTitle = 'MStore';
+                    sub.id = 'MStore';
+                    sub.isStore = true;
+                    !result ? this.editableTabs.push(sub) : ""
+                } else {
+                    !result ? this.editableTabs.push(sub) : ""
+                }
+                this.currentTab = sub.id;
+                this.headMenuActive = sub.modelId
+                this.$nextTick(function () {
+                    that.asideMenuActive = sub.id;
+                })
+                // 处理其他逻辑
+                setTimeout(function () {
+                    if (document.querySelector('.el-tabs__nav-prev')) {
+                        document.querySelector('.el-tabs__nav-wrap').style.padding = '0 40px'
+                    } else {
+                        document.querySelector('.el-tabs__nav-wrap').style.padding = '0'
+                    }
+                }, 16)
+            },
+            /**
+             * 点击选项卡切换左侧菜单
+             * @param tab tab页
+             */
+            tabClick: function (tab,e) {
+                var _menu = this.menuList.filter(m=>{
+                    return m.id == tab.props.name;
+                })
+                if(_menu.length > 0) {
+                    this.asideMenuActive = _menu[0].id;
+                    this.headMenuActive = _menu[0].modelId;
+                }
+
+            },
+            /**
+             * 获取当前菜单的子菜单
+             * @param id 父菜单
+             * @returns {*[]}
+             */
+            getSubMenu: function (id) {
+                var result = [];
+                var that = this;
+                that.subMenuList && that.subMenuList.forEach(function (item) {
+                    item.modelId == id ? result.push(item) : ''
+                })
+                return result;
+            },
+            /**
+             * 关闭tab
+             * @param targetName 菜单
+             */
+            closeTab: function (targetName) {
+                var that = this;
+                // 关闭的面板是当前激活面板
+                if (that.currentTab == targetName) {
+                    var modelId = null
+                    that.editableTabs.forEach(function (tab, index, arr) {
+                        if (tab.id == targetName) {
+                            modelId = arr[index].modelId
+                            var nextTab = arr[index + 1] || arr[index - 1];
+                            if (nextTab) {
+                                that.currentTab = nextTab.id
+                                that.asideMenuActive = nextTab.id
+                                that.headMenuActive = nextTab.modelId
+                            }
+                        }
+                    })
+                }
+                // 去掉关闭的tab
+                that.editableTabs = that.editableTabs.filter(function (tab) {
+                    return tab.id !== targetName
+                })
+
+                // 关闭左侧父菜单
+                if (that.editableTabs.length) {
+                    var result = that.editableTabs.every(function (item) {
+                        return item.modelId !== modelId
+                    })
+                    if (result) {
+                        that.asideMenuList.forEach(function (menu, index, arr) {
+                            if (menu.id == modelId) {
+                                var flag = false;
+                                that.markList && that.markList.forEach(function (item, index, array) {
+                                    if (item.title == menu.modelTitle) {
+                                        flag = true;
+                                    }
+                                })
+                                if (!flag && that.markList) {
+                                    arr.splice(index, 1);
+                                }
+                            }
+                        })
+                    }
+                } else {
+                    that.asideMenuList = []
+                }
+
+                // 判断是否出现左右箭头
+                setTimeout(function () {
+                    if (document.querySelector('.el-tabs__nav-prev')) {
+                        document.querySelector('.el-tabs__nav-wrap').style.padding = '0 40px'
+                    } else {
+                        document.querySelector('.el-tabs__nav-wrap').style.padding = '0'
+                    }
+                }, 16)
+            },
+
+            /**
+             * 功能大全打开菜单
+             * @param menu 菜单
+             */
+            openMenu: function (menu) {
+                var that = this;
+                this.asideMenuList.some(function (item, index) {
+                    return item.id == menu.id
+                }) || this.asideMenuList.push(menu)
+                var children = [];
+                this.menuList.forEach(function (tab) {
+                    if (tab.modelId == menu.id) {
+                        children.push(tab)
+                    }
+                })
+                // 若子菜单不是功能导航
+                if(children.length>0 && children[0].modelIsMenu) {
+                    //默认打开第一个子菜单
+                    this.currentTab = children[0] && children[0].id;
+                    this.open(children[0]);
+                    menu.isSingle = false;
+
+                    that.$nextTick(function () {
+                        that.$refs.menu.open(String(menu.id))
+                    })
+                } else if(menu.modelUrl) {
+                    this.open(menu);
+                    menu.isSingle = true;
+
+                    that.$nextTick(function () {
+                        that.$refs.menu.open(String(menu.id))
+                    })
+
+                }
+
+            },
+            /**
+             * 获取管理员信息
+             */
+            getManagerInfo: function () {
+                var that = this;
+                ms.http.get(ms.manager + "/basic/manager/info.do")
+                    .then(function (res) {
+                        that.managerInfo = res.data;
+                        // 请求菜单数据
+                        that.getApp();
+                    }, function (err) {
+                        that.$notify({
+                            title: '错误',
+                            message: err,
+                            type: 'error'
+                        });
+                    }).catch( function(err){
+                    that.$notify({
+                        title: '错误',
+                        message: err,
+                        type: 'error'
+                    });
+                });
+            },
+            /**
+             * 主界面常用菜单,点击打开左侧菜单
+             * main.ftl 里面使用
+             * @param id 菜单编号
+             */
+            openParentMenuInId: function (id) {
+                var data = this.parentMenuList.find(function (menu) {
+                    return menu.id == id
+                })
+                data && this.openMenu(data)
+            },
+            /**
+             * 更新主题
+             */
+            updateTheme:function(){
+                this.theme = localStorage.getItem("theme") || 'ms-theme-light';
+            }
+
+        },
+        created: function () {
+        },
+        mounted: function () {
+            //获取登录用户信息,成功后获取菜单信息
+            this.getManagerInfo();
+
+        },
+    })
+    //标准版需要
+    window.indexVue = indexVue;
+</script>
+<style>
+    .ms-admin-logo {
+        display: flex;
+        align-items: center;
+        overflow: hidden;
+    }
+
+    .ms-admin-logo img {
+        padding: 14px 0;
+        width: 50px;
+    }
+
+    .ms-admin-logo>div {
+        display: flex;
+        align-items: center;
+    }
+
+    .ms-admin-logo>div span {
+        margin-top: -6px;
+        position: absolute;
+        margin-left: 10px;
+        font-size: 12px;
+    }
+
+    .ms-admin-logo .iconfont {
+        color: #fff;
+        margin-left: auto;
+        margin-right: 20px;
+        cursor: pointer;
+    }
+
+    .ms-admin-header-right {
+        margin-left: auto;
+        min-width: 200px;
+        display: flex;
+        align-items: center;
+        justify-content: flex-end;
+        padding: 0;
+        line-height: 1;
+    }
+
+    .ms-admin-header-menu-shrink {
+        width: 64px;
+        display: flex;
+        justify-content: center;
+        align-items: center;
+        line-height: 50px;
+        border-right: 1px solid rgba(238, 238, 238, 1);
+        cursor: pointer;
+    }
+
+    .ms-admin-header-menu-shrink:hover {
+        background: rgba(250, 250, 250, 0.2);
+    }
+
+    .el-menu-vertical-demo:not(.el-menu--collapse) {
+        width: 180px;
+        min-height: 100vh;
+    }
+
+    .el-menu--collapse {
+        height: 100vh;
+    }
+
+    .ms-admin-menu-aside {
+        width: auto !important;
+        height: 100vh;
+        position: relative;
+        overflow: visible;
+    }
+
+    .ms-admin-menu-aside .ms-admin-menu .el-menu--inline .is-active {
+        border-left: 2px solid #0099ff;
+    }
+
+    .ms-admin-menu-aside .ms-menu-expand i {
+        font-weight: bolder;
+        font-size: 14px;
+        color: #333;
+        position: absolute;
+        transform: rotate(90deg);
+        right: 40%;
+    }
+
+    .ms-admin-menu-aside .ms-menu-expand::before {
+        border-color: transparent transparent #eee;
+        border-style: none solid solid;
+        border-width: 0 30px 22px;
+        content: "";
+        display: block;
+        height: 0;
+        left: -10px;
+        width: 30px;
+    }
+
+    .ms-admin-menu-aside .el-sub-menu__title,
+    .ms-admin-menu-aside .el-menu-item {
+        color: rgba(255, 255, 255, 1);
+        height: 40px;
+        line-height: 40px;
+    }
+
+    .ms-admin-menu-aside .el-sub-menu__title i {
+        color: inherit;
+    }
+
+    .ms-admin-menu-aside .el-sub-menu__title .iconfont {
+        font-size: 19px !important;
+    }
+
+    .ms-admin-menu-aside .el-sub-menu.is-active .el-sub-menu__title {
+        color: rgba(255, 255, 255, 1) !important;
+    }
+
+    .ms-admin-menu-aside .el-sub-menu__title:hover {
+        background-color: rgba(255,255,255,0.3) !important;
+    }
+
+    .ms-admin-header {
+        display: flex;
+        padding: 0;
+        background-color: rgba(255, 255, 255, 1);
+        height: 50px !important;
+        box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
+        z-index: 0;
+        overflow: hidden;
+    }
+
+    .ms-admin-header .ms-admin-header-menu {
+        border-bottom: none;
+        position: relative;
+    }
+
+    .ms-admin-header .ms-admin-header-menu>.ms-admin-menu-item>* {
+        height: 50px !important;
+        line-height: 50px !important;
+        border-bottom: none !important;
+        font-size: 1em;
+    }
+
+    .ms-admin-header .ms-admin-header-menu .ms-admin-shortcut-menu>li {
+        margin: 0;
+        padding: 0 20px;
+        text-align: left;
+        display: -webkit-inline-box;
+        display: inline-block;
+        height: 50px;
+        line-height: 50px;
+        font-weight: normal;
+        font-size: 14px;
+        color: #333;
+    }
+
+    .ms-admin-header .ms-admin-header-menu .ms-admin-shortcut-menu>li:hover {
+        cursor: pointer;
+        color: #0099ff;
+    }
+
+    .ms-admin-header-menu .el-sub-menu__title {
+        height: 50px !important;
+        line-height: 50px !important;
+        display: flex;
+        align-items: center;
+    }
+
+    .ms-admin-header-menu .el-sub-menu__title:hover {
+        background-color: #f2f6fc !important;
+        color: #409eff !important;
+    }
+
+    .ms-admin-header-menu .el-sub-menu__title:hover i {
+        color: #409eff !important;
+    }
+
+    .ms-admin-header-menu .el-sub-menu__icon-arrow {
+        margin-top: -4px !important;
+    }
+
+    .ms-admin-header-menu-item .el-menu-item:hover {
+        background-color: #f2f6fc !important;
+        color: #409eff !important;
+    }
+
+    .ms-admin-header-menu-item .el-menu-item:hover i {
+        color: #409eff !important;
+    }
+
+    .ms-admin-header-menu-all {
+        width: 560px;
+        height: auto;
+        background: rgba(255, 255, 255, 1);
+        border-radius: 2px;
+        display: flex;
+        flex-direction: row;
+        flex-wrap: wrap;
+        line-height: 40px;
+    }
+
+    .ms-admin-header-menu-all .iconfont {
+        font-size: 17px;
+    }
+
+    .ms-admin-header-menu-all .ms-admin-header-menu-all-item {
+        display: flex;
+        width: 25%;
+        justify-content: center;
+        align-items: center;
+        cursor: pointer;
+    }
+
+    .ms-admin-header-menu-all .ms-admin-header-menu-all-item .el-icon-star-on {
+        color: #ccc;
+        font-size: 17px;
+        margin-left: -1px;
+        margin-top: 1px;
+    }
+
+    .ms-admin-header-menu-all .ms-admin-header-menu-all-item .el-icon-star-on:hover {
+        color: rgba(64, 158, 255, 1);
+    }
+
+    .ms-admin-header-menu-all .ms-admin-header-menu-all-item .el-icon-star-off {
+        color: #ccc;
+    }
+
+    .ms-admin-header-menu-all .ms-admin-header-menu-all-item .el-icon-star-off:hover {
+        color: rgba(64, 158, 255, 1);
+    }
+
+    .ms-admin-header-menu-all .ms-admin-header-menu-all-item:hover {
+        color: rgba(64, 158, 255, 1);
+    }
+
+    .ms-admin-menu-aside-submenu .el-menu-item {
+
+        line-height: 40px;
+        height: 40px;
+    }
+
+    .el-sub-menu__title * {
+        vertical-align: top;
+    }
+
+    .ms-admin-login-theme .el-dropdown-menu__item {
+        display: flex;
+        flex-direction: row;
+        justify-content: center;
+        align-items: center;
+    }
+
+    .el-tabs__nav .el-tabs__item:nth-child(1) i {
+        display: none;
+    }
+
+    .el-tabs__item.is-active {
+        background-color: rgba(255, 255, 255, 1);
+    }
+
+    .el-menu {
+        border-right: 0px;
+    }
+
+    .ms-admin-logo .class-1 {
+        color: white;
+        padding-top: 8px;
+        color: #ffffff;
+        word-wrap: break-word;
+        font-family: MicrosoftYaHei-Bold;
+        font-weight: bold;
+        font-style: italic;
+    }
+
+    .ms-admin-logo .class-2 {
+        font-size: 12px;
+        font-weight: normal;
+    }
+
+    .top-operate-select .el-menu--popup {
+        width: 162px;
+        min-width: 162px;
+    }
+
+    .ms-admin-container {
+        height: auto;
+    }
+
+    .ms-admin-container>.ms-admin-main {
+        padding: 0;
+        background-color: #fff;
+        z-index: 0;
+        overflow: hidden;
+    }
+
+    .ms-admin-container>.ms-admin-main .ms-admin-tabs {
+        height: calc(100vh - 50px);
+        display: flex;
+        flex-direction: column;
+    }
+
+    .ms-admin-container>.ms-admin-main .ms-admin-tabs .el-tabs__content {
+        height: 100%;
+    }
+
+    .ms-admin-container>.ms-admin-main .ms-admin-tabs .el-tabs__content .el-tab-pane {
+        height: 100%;
+    }
+
+    .ms-admin-container>.ms-admin-main .ms-admin-tabs .el-tabs__header {
+        background: #fafafa;
+        margin-bottom: 0;
+    }
+
+    .ms-admin-container>.ms-admin-main .ms-admin-tabs .el-tabs__header .el-tabs__nav-scroll .el-tabs__nav {
+        border-left: none;
+        border-radius: 0;
+    }
+
+    .ms-admin-container>.ms-admin-main .ms-admin-tabs .ms-admin-refresh {
+        float: right;
+        width: 40px;
+        height: 40px;
+        text-align: center;
+        border-left: 1px solid #e6e6e6;
+        cursor: pointer;
+        position: relative;
+    }
+
+    .ms-admin-container>.ms-admin-main .ms-admin-tabs .ms-admin-refresh::before {
+        position: absolute;
+        left: 34%;
+        top: 50%;
+        transform: translateY(-50%);
+        color: #999;
+    }
+
+    .ms-admin-container>.ms-admin-main .ms-admin-tabs .el-tabs__nav-next,
+    .ms-admin-container>.ms-admin-main .ms-admin-tabs .el-tabs__nav-prev {
+        width: 40px;
+        height: 40px;
+        display: flex;
+        justify-content: center;
+        align-items: center;
+    }
+
+    .ms-admin-container>.ms-admin-main .ms-admin-tabs .el-tabs__nav-next {
+        border-left: 1px solid #e6e6e6;
+    }
+
+    .ms-admin-container>.ms-admin-main .ms-admin-tabs .el-tabs__nav-prev {
+        border-right: 1px solid #e6e6e6;
+    }
+
+    .ms-admin-container>.ms-admin-main iframe {
+        width: 100%;
+        height: 100%;
+        border: none !important;
+    }
+
+
+
+    /**tab页标题白色 **/
+
+    /** 表单提示 **/
+    .el-form-item__content {
+        display: unset !important;
+    }
+</style>

+ 642 - 0
src/main/webapp/WEB-INF/manager/login.ftl

@@ -0,0 +1,642 @@
+<html>
+<head>
+    <meta charset="utf-8" />
+    <title>MCms</title>
+    <#include "/include/head-file.ftl"/>
+    <link rel="stylesheet" type="text/css" href="${base}/static/plugins/TextInputEffects/css/normalize.css" />
+    <link rel="stylesheet" type="text/css" href="${base}/static/plugins/TextInputEffects/css/set1.css" />
+    <style>
+        [v-cloak]{
+            display: none;
+        }
+    </style>
+</head>
+<body class="custom-body">
+<div id="app" v-cloak>
+    <!--大容器开始-->
+    <div  class="class-1" @keydown.13='login'>
+<#--        <img src="${base}/static/images/yanhua.png" style="position: absolute;"/>-->
+
+        <!--大容器开始-->
+        <div  class="class-2" style="position: absolute">
+            <!--大容器开始-->
+            <div  class="class-3" style="position: relative">
+                <!--图片开始-->
+                <img src="${base}/static/images/login-banner.png" class="class-4" />
+                <!--图片结束-->
+            </div>
+            <!--大容器结束-->
+            <!--大容器开始-->
+            <div  class="class-5">
+                <!--小容器开始-->
+                <div  class="class-6" >
+                    <!--文本开始-->
+                    <div class="class-7" style="position: relative">
+                        <div>登录</div>
+                    </div>
+                    <!--文本结束-->
+                    <!--小容器开始-->
+                    <el-form :model="form" ref="form" :rules="rules" @submit.native.prevent>
+                        <div  class="class-8" >
+                            <el-form-item prop="managerName">
+                                <span class="input input--hoshi">
+                                    <input v-model="form.managerName" class="input__field input__field--hoshi" type="text"  id="input-name" />
+                                    <label class="input__label input__label--hoshi input__label--hoshi-color-1" for="input-name">
+                                        <span class="input__label-content input__label-content--hoshi">账号</span>
+                                    </label>
+                                </span>
+                            </el-form-item>
+                        </div>
+                        <!--小容器结束-->
+                        <!--小容器开始-->
+                        <div  class="class-13" >
+                            <!--文本开始-->
+                            <el-form-item prop="managerPassword">
+                                <span class="input input--hoshi">
+                                    <input v-model="form.managerPassword" class="input__field input__field--hoshi" type="password" id="input-password" autocomplete="off" />
+                                    <label class="input__label input__label--hoshi input__label--hoshi-color-1" for="input-password">
+                                        <span class="input__label-content input__label-content--hoshi">密码</span>
+                                    </label>
+                                </span>
+                            </el-form-item>
+                        </div>
+                        <!--小容器结束-->
+                        <!--小容器开始-->
+                        <div  class="class-16" >
+                            <!--小容器开始-->
+                            <div  class="class-17" >
+                                <!--文本开始-->
+                                <el-form-item prop="rand_code">
+                                    <span class="input input--hoshi">
+                                        <input v-model="form.rand_code" class="input__field input__field--hoshi" type="text" link id="input-rand-code" />
+                                        <label class="input__label input__label--hoshi input__label--hoshi-color-1" for="input-rand-code">
+                                            <span class="input__label-content input__label-content--hoshi">验证码</span>
+                                        </label>
+                                    </span>
+                                </el-form-item>
+                            </div>
+                            <!--小容器结束-->
+                            <!--大容器开始-->
+                            <div class="class-20" >
+                                <img :src="ms.base+verifCode" class="code-img" @click="code" />
+                            </div>
+                            <!--大容器结束-->
+                            <!--小容器开始-->
+                            <div  class="class-21" >
+                                <!--小容器开始-->
+                                <div @click="code"
+                                     class="class-22" >
+                                    <!--文本开始-->
+                                    <div class="class-23">
+
+                                        看不清?
+
+                                    </div>
+                                    <!--文本结束-->
+                                    <!--文本开始-->
+                                    <div class="class-24">
+
+                                        换一张
+
+                                    </div>
+                                    <!--文本结束-->
+                                </div>
+                                <!--小容器结束-->
+                            </div>
+                            <!--小容器结束-->
+                        </div>
+                        <!--小容器结束-->
+
+                        <!--小容器开始-->
+                        <div  class="class-25" >
+                        </div>
+                        <!--小容器结束-->
+                        <!--按钮开始-->
+                        <el-button @click="login" type="primary" :loading="loading" native-type="submit"
+                                   class="class-26">
+                            {{loading?'登录中':'登录'}}
+                        </el-button>
+                        <!--按钮结束-->
+                        <!--小容器开始-->
+                        <div  class="class-27" >
+                            <el-checkbox v-model="form.rememberMe">记住我</el-checkbox>
+                            <!--文本结束-->
+                        </div>
+                    </el-form>
+                    <!--小容器结束-->
+                </div>
+                <!--小容器结束-->
+            </div>
+            <!--大容器结束-->
+        </div>
+        <!--大容器结束-->
+    </div>
+    <!--大容器结束-->
+</div>
+</body>
+</html>
+<script src="${base}/static/plugins/TextInputEffects/js/classie.js"></script>
+<script>
+    var app = new _Vue({
+        el: '#app',
+        watch:{
+
+        },
+        data: function () {
+            return {
+                base: ms.base,
+                loading: false,
+                app: {
+                    appTitle: '6.0.0  铭飞MCms',
+                    appLogo: '',
+                    appCopyright: '',
+                    appUrl: '',
+                },
+                form: {
+                    managerName: '',
+                    managerPassword: '',
+                    rand_code: '',
+                    rememberMe: true,
+                },
+                rules: {
+                    managerName: [
+                        {required: true, message: '请输入账号', trigger: 'blur'},
+                        {min: 1, max: 30, message: '长度不能超过30个字符', trigger: 'change'}
+                    ],
+                    managerPassword: [
+                        {required: true, message: '请输入密码', trigger: 'blur'},
+                        {min: 1, max: 30, message: '长度不能超过30个字符', trigger: 'change'}
+                    ],
+                    rand_code: [
+                        {required: true, message: '请输入验证码', trigger: 'blur'},
+                        {min: 1, max: 4, message: '长度不能超过4个字符', trigger: 'change'}
+                    ],
+                },
+
+                verifCode:  "/code.do?t=" + new Date().getTime()
+            }
+        },
+        methods: {
+            //登录输入框下边框动画
+            loginIptAnimation:function() {
+                this.$nextTick(function () {
+                    const label = document.querySelectorAll('.input__label-content--hoshi')
+                    const ipt = document.querySelectorAll('.input__field--hoshi')
+                    ipt.forEach((item, index) => {
+                        if (!!item.value) {
+                            label[index].style.transform = 'translate3d(0, -40%, 0)'
+                        } else {
+                            label[index].style.transform = 'translate3d(0, 0, 0)'
+                        }
+                    })
+                })
+            },
+            //登录
+            login:function () {
+                var that = this;
+                that.$refs.form.validate(function(valid){
+                    if (valid) {
+                        that.loading = true;
+                        ms.http.post(ms.manager + "/login.do", {
+                            managerName:that.form.managerName,
+                            managerPassword:that.form.managerPassword,
+                            rand_code:that.form.rand_code,
+                            rememberMe:that.form.rememberMe
+                        }).then(function (res) {
+                            if(res.result){
+                                if(that.form.rememberMe) {
+                                    localStorage.setItem('managerName',that.form.managerName);
+                                    localStorage.setItem('managerPassword',that.form.managerPassword);
+                                } else {
+                                    localStorage.setItem('managerName','');
+                                    localStorage.setItem('managerPassword','');
+                                }
+                                localStorage.setItem('rememberMe',that.form.rememberMe);
+                                ms.util.openSystemUrl("/index.do");
+                                that.loading = false;
+                            }else {
+                                that.$notify({
+                                    title: '失败',
+                                    message: res.msg,
+                                    type: 'error'
+                                });
+                                that.code();
+                                that.loading = false;
+                            }
+                        }).catch(function () {
+                            that.code();
+                            that.loading = false;
+                        });
+                    }
+                });
+            },
+            //获取验证码
+            code:function(){
+                this.verifCode = "/code.do?t=" + new Date().getTime();
+            },
+            //初始
+            initial:function(){
+                this.form.managerName = localStorage.getItem('managerName');
+                this.form.managerPassword =  localStorage.getItem('managerPassword');
+                if(localStorage.getItem('rememberMe')==='true') {
+                    this.form.rememberMe = true  ;
+                } else {
+                    this.form.rememberMe = false ;
+                }
+
+                top.location != self.location?(top.location = self.location):'';
+            },
+            get: function (){
+                var that = this;
+                ms.http.get(ms.base + "/basic/app/get.do").then(function (res) {
+                    if (res.result) {
+                        that.app = res.data;
+                        document.title = that.app.appName;
+                    }
+                })
+            }
+        },
+        created:function(){
+            this.get();
+            this.code();
+            this.initial();
+        }
+    })
+</script>
+
+
+<style>
+    .el-form-item{
+        margin-bottom: 0px;
+    }
+    .el-form-item__content{
+        line-height: initial;
+    }
+    .custom-body {
+    }
+    .class-1
+    {
+        color:#333333;
+        background-image:url(${base}/static/images/login-bg.jpg);
+        outline:none;
+        outline-offset:-1px;
+        background-size:cover;
+        background-position:center;
+        height:100%;
+        max-width:100%;
+        align-items:center;
+        flex-direction:row;
+        display:flex;
+        justify-content:center;
+        animation-duration:1s;
+        width:100%;
+        background-repeat:no-repeat;
+    }
+    .class-2
+    {
+        box-shadow:0 2px 12px 0 rgba(0, 0, 0, 0.1);
+        color:#333333;
+        outline:none;
+        outline-offset:-1px;
+        height:540px;
+        max-width:100%;
+        background-color:rgba(255, 255, 255, 1);
+        flex-direction:row;
+        display:flex;
+        animation-duration:1s;
+        border-radius:12px;
+        width:1000px;
+        background-repeat:no-repeat;
+    }
+    .class-3
+    {
+        color:#333333;
+        outline:none;
+        outline-offset:-1px;
+        height:100%;
+        max-width:100%;
+        align-items:flex-start;
+        flex-direction:row;
+        display:flex;
+        justify-content:flex-start;
+        animation-duration:1s;
+        width:460px;
+        background-repeat:no-repeat;
+    }
+    .class-4
+    {
+        height:100%;
+        animation-duration:1s;
+        width:100%;
+    }
+    .class-5
+    {
+        color:#333333;
+        outline:none;
+        padding-bottom:20px;
+        outline-offset:-1px;
+        flex:1;
+        padding-top:20px;
+        height:100%;
+        max-width:100%;
+        align-items:center;
+        flex-direction:column;
+        display:flex;
+        justify-content:flex-start;
+        animation-duration:1s;
+        width:200px;
+        background-repeat:no-repeat;
+    }
+    .class-6
+    {
+        color:#333333;
+        outline:none;
+        outline-offset:-1px;
+        max-width:100%;
+        flex-direction:column;
+        display:flex;
+        animation-duration:1s;
+        width:330px;
+        background-repeat:no-repeat;
+        margin-top:20px;
+    }
+    .class-7
+    {
+        color:#333333;
+        word-wrap:break-word;
+        display:inline-block;
+        animation-duration:1s;
+        font-size:36px;
+        line-height:1.4;
+        margin-bottom:20px;
+    }
+    .class-8
+    {
+        color:#333333;
+        outline:none;
+        outline-offset:-1px;
+        height:80px;
+        max-width:100%;
+        flex-direction:column;
+        display:flex;
+        justify-content:flex-end;
+        animation-duration:1s;
+        width:100%;
+        background-repeat:no-repeat;
+    }
+    .class-9
+    {
+        color:#BBBBBB;
+        word-wrap:break-word;
+        display:inline-block;
+        animation-duration:1s;
+        font-size:12px;
+        line-height:1.4;
+    }
+    .class-10
+    {
+        color:#333333;
+        outline:none;
+        outline-offset:-1px;
+        height:40px;
+        max-width:100%;
+        align-items:center;
+        flex-direction:row;
+        display:flex;
+        animation-duration:1s;
+        width:100%;
+        background-repeat:no-repeat;
+    }
+    .class-11
+    {
+        color:#333333;
+        word-wrap:break-word;
+        display:inline-block;
+        animation-duration:1s;
+        font-size:14px;
+        line-height:1.4;
+    }
+    .class-12
+    {
+        margin-right:auto;
+        animation-duration:1s;
+        background-color:#eee;
+        border-radius:1px;
+        width:100%;
+        height:1px;
+        margin-left:auto;
+    }
+    .class-13
+    {
+        color:#333333;
+        outline:none;
+        outline-offset:-1px;
+        height:80px;
+        max-width:100%;
+        flex-direction:column;
+        display:flex;
+        justify-content:flex-end;
+        animation-duration:1s;
+        width:100%;
+        background-repeat:no-repeat;
+    }
+    .class-14
+    {
+        color:#BBBBBB;
+        word-wrap:break-word;
+        padding-bottom:10px;
+        display:inline-block;
+        animation-duration:1s;
+        font-size:14px;
+        line-height:1.4;
+    }
+    .class-15
+    {
+        margin-right:auto;
+        animation-duration:1s;
+        background-color:#eee;
+        border-radius:1px;
+        width:100%;
+        height:1px;
+        margin-left:auto;
+    }
+    .class-16
+    {
+        color:#333333;
+        outline:none;
+        outline-offset:-1px;
+        height:80px;
+        max-width:100%;
+        align-items:flex-end;
+        flex-direction:row;
+        display:flex;
+        justify-content:flex-start;
+        animation-duration:1s;
+        background-repeat:no-repeat;
+    }
+    .class-17
+    {
+        color:#333333;
+        outline:none;
+        outline-offset:-1px;
+        flex:1;
+        height:80px;
+        max-width:100%;
+        flex-direction:column;
+        display:flex;
+        justify-content:flex-end;
+        animation-duration:1s;
+        width:200px;
+        background-repeat:no-repeat;
+    }
+    .class-18
+    {
+        color:#BBBBBB;
+        word-wrap:break-word;
+        display:inline-block;
+        animation-duration:1s;
+        font-size:14px;
+        line-height:1.4;
+        margin-bottom:10px;
+    }
+    .class-19
+    {
+        margin-right:auto;
+        animation-duration:1s;
+        background-color:#eee;
+        border-radius:1px;
+        width:100%;
+        height:1px;
+        margin-left:auto;
+    }
+    .class-20
+    {
+        cursor:pointer;
+        color:#333333;
+        margin-right:10px;
+        outline-offset:-1px;
+        height:40px;
+        max-width:100%;
+        align-items:center;
+        flex-direction:row;
+        display:flex;
+        justify-content:center;
+        margin-left:10px;
+        animation-duration:1s;
+        width:88px;
+        background-repeat:no-repeat;
+        margin-bottom: 0.85em;
+    }
+    .class-21
+    {
+        color:#333333;
+        outline:none;
+        outline-offset:-1px;
+        max-width:100%;
+        align-items:flex-end;
+        flex-direction:column;
+        display:flex;
+        justify-content:flex-end;
+        animation-duration:1s;
+        background-repeat:no-repeat;
+        margin-bottom: 0.85em;
+    }
+    .class-22
+    {
+        color:#333333;
+        outline:none;
+        outline-offset:-1px;
+        max-width:100%;
+        flex-direction:column;
+        display:flex;
+        animation-duration:1s;
+        background-repeat:no-repeat;
+    }
+    .class-23
+    {
+        color:#BBBBBB;
+        word-wrap:break-word;
+        display:inline-block;
+        animation-duration:1s;
+        font-size:12px;
+        line-height:1.4;
+    }
+    .class-24
+    {
+        cursor:pointer;
+        color:#0099FF;
+        word-wrap:break-word;
+        display:inline-block;
+        animation-duration:1s;
+        font-size:12px;
+        line-height:1.4;
+    }
+    .class-25
+    {
+        color:#333333;
+        outline:none;
+        outline-offset:-1px;
+        height:40px;
+        max-width:100%;
+        flex-direction:row;
+        display:flex;
+        animation-duration:1s;
+        width:100px;
+        background-repeat:no-repeat;
+    }
+    .class-26
+    {
+        background-color:#0099ff;
+        width: 100%;
+        height: 40px;
+        line-height: 40px;
+    }
+    .class-27
+    {
+        color:#333333;
+        outline:none;
+        outline-offset:-1px;
+        max-width:100%;
+        align-items:center;
+        flex-direction:row;
+        display:flex;
+        animation-duration:1s;
+        width:100px;
+        background-repeat:no-repeat;
+        margin-top:20px;
+    }
+    .class-28
+    {
+        color:#333333;
+        outline:1px dashed hsla(0, 0%, 66.7%, 0.7);
+        outline-offset:-1px;
+        height:14px;
+        max-width:100%;
+        flex-direction:row;
+        display:flex;
+        animation-duration:1s;
+        width:14px;
+        background-repeat:no-repeat;
+    }
+    .class-29
+    {
+        color:#999999;
+        word-wrap:break-word;
+        display:inline-block;
+        margin-left:10px;
+        animation-duration:1s;
+        font-size:14px;
+        line-height:1.4;
+    }
+    @media (max-width: 768px){
+    }
+    .input__label--hoshi::before{
+        content: '';
+        position: absolute;
+        top: 1px;
+        left: 0;
+        width: 100%;
+        height: calc(100% - 10px);
+        border-bottom: 1px solid #B9C1CA;
+    }
+</style>

+ 2031 - 0
src/main/webapp/WEB-INF/manager/main.ftl

@@ -0,0 +1,2031 @@
+<html>
+
+<head>
+    <meta charset="utf-8"/>
+    <title>控制台</title>
+    <#include "../../include/head-file.ftl">
+    <link rel="stylesheet" href="${base}/static/plugins/jquery.liMarquee/liMarquee.css">
+</head>
+<body>
+<div id="app" v-cloak>
+    <div class="ms-console">
+        <div class="ms-console-left">
+            <div class="ms-panel">
+                <div class="ms-panel-title">
+                    <i class="iconfont icon-zidingyimoxing"></i>
+                    <span class="ms-panel-txt">
+                            常用功能
+                    </span>
+                </div>
+                <div class="ms-panel-body">
+                    <div v-if="markList.length==0" class="menu-item-empty">
+                        <el-empty>
+                            <div slot="description">
+                                展开顶部<b style="color: #E6A23C">功能大全</b>,点击菜单右侧<b style="color: #E6A23C">五角星</b>设置为常用功能
+                            </div>
+                        </el-empty>
+                    </div>
+                    <template v-else v-for="item in markList" >
+                        <div  class="menu-item" v-if="item.isMark" >
+                            <div class="menu-link" @click="openParentMenuInId(item.id)">
+                                <i :class="['menu-icon','iconfont',item.modelIcon?item.modelIcon:'icon-zidingyimoxing']"></i>
+                                <span class="menu-text">
+                                    {{item.modelTitle}}
+                            </span>
+                            </div>
+                        </div>
+                    </template>
+
+
+                </div>
+            </div>
+            <div class="ms-panel">
+                <div class="ms-panel-title">
+                    <i class="iconfont icon-logo"></i>
+                    <span class="ms-panel-txt">
+                            帮助手册
+                        </span>
+                </div>
+                <div class="ms-panel-body">
+                    <div class="text-link" v-for="item in mainJson.helps">
+
+                        <a :href="item.link" target="_blank" class="text-links-text">
+                            <i class="iconfont icon-wenjian text-links-icon"></i> {{item.text}}
+                        </a>
+                    </div>
+                </div>
+
+
+            </div>
+            <div class="ms-panel">
+                <div class="ms-panel-title">
+                    <i class="iconfont icon-daima"></i>
+                    <span class="ms-panel-txt">
+                            MS平台
+                        </span>
+                </div>
+                <div class="ms-panel-body space-around">
+                    <a :href="item.link" target="_blank" class="img-link" v-for="item in mainJson.ms">
+                        <img :title="item.text" :alt="item.text" :src="item.pic"/>
+                        <span class="img-links-text">
+                                {{item.text}}
+                            </span>
+                        <span class="img-links-text-sm">
+                                {{item.desc}}
+                            </span>
+                    </a>
+                </div>
+            </div>
+            <div class="ms-panel">
+                <div class="ms-panel-title">
+                    <i class="iconfont icon-chajian"></i>
+                    <span class="ms-panel-txt">
+                            热门插件
+                        </span>
+                </div>
+                <div class="ms-panel-body space-around">
+                    <a :href="item.link" target="_blank" class="img-link" v-for="item in mainJson.plugs">
+                        <img :title="item.text" :alt="item.text" :src="item.pic"/>
+                    </a>
+                </div>
+            </div>
+        </div>
+        <div class="ms-console-right">
+            <div class="news-list">
+                <div class="news-list-title">
+                    <img title="" alt="" :src="ms.base+'/static/images/icon-voice.png'"/>
+                    <span>
+                            公告
+                        </span>
+                </div>
+                <div class="news-list-body">
+                    <ul style="margin: 0">
+                        <li  v-for="(item,index) in contentList" :key="index">
+                            <a v-if="item.contentOutLink==''" target="_blank" :href="'https://www.mingsoft.net/'+item.id+'.html'" class="news-list-a" >{{item.contentTitle}}</a>
+                            <a v-else target="_blank" :href="item.contentOutLink" class="news-list-a" >{{item.contentTitle}}</a>
+                        </li>
+                    </ul>
+                </div>
+            </div>
+            <div class="ms-service">
+                <div class="ms-panel">
+                    <div class="ms-panel-title">
+                        <i class="iconfont icon-QQ4"></i>
+                        <span class="ms-panel-txt">
+                                QQ群
+                            </span>
+                    </div>
+                    <div class="ms-panel-body">
+                        <div class="qq-item" v-for="item in mainJson.QQGroups">
+                            <img :title="item.text" :alt="item.text" :src="ms.base+'/static/images/icon-qq.png'"
+                                 class="qq-icon"/>
+                            <div class="qq-text">
+                                <span class="qq-text-name">
+                                    {{item.text}}
+                                </span>
+                                <a :href="item.link" target="_blank" class="qq-text-no">
+                                    {{item.number}}
+                                </a>
+                            </div>
+                        </div>
+
+                    </div>
+                </div>
+            </div>
+            <div class="ms-other">
+                <div class="ms-panel">
+                    <div class="ms-panel-title">
+                        <i class="iconfont icon-beizi"></i>
+                        <span class="ms-panel-txt">
+                                商务技术支持
+                            </span>
+                    </div>
+                    <div class="ms-panel-body">
+                        <div class="qq-item">
+                            <img title="" alt=""  :src="ms.base+'/static/images/icon-telephone.png'" class="qq-icon"/>
+                            <div class="qq-text">
+                                    <span class="qq-text-name">
+                                        商务电话
+                                    </span>
+                                <span class="qq-text-no">
+                                        19970180163
+                                    </span>
+                            </div>
+                        </div>
+                        <div class="qq-item">
+                            <img title="" alt=""  :src="ms.base+'/static/images/icon-qq.png'" class="qq-icon"/>
+                            <div class="qq-text">
+                                    <span class="qq-text-name">
+                                        商务QQ
+                                    </span>
+                                <span class="qq-text-no">
+                                        3336073455
+                                    </span>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+                <a :href="item.link" class="version-link" target="_blank" v-for="item in mainJson.versions">
+                    <img :title="item.text" :alt="item.text" :src="item.pic"/>
+                </a>
+            </div>
+        </div>
+    </div>
+</div>
+</body>
+
+</html>
+<script src="${base}/static/plugins/jquery/3.6.3/jquery-3.6.3.min.js"></script>
+<script src="${base}/static/plugins/jquery.liMarquee/jquery.liMarquee.js"></script>
+
+<script>
+    const app = new _Vue({
+        el: '#app',
+        component() {
+        },
+        data: function () {
+            return {
+                markList: [], //常用功能列表
+                contentList: [],
+                msNewsPath: 'https://www.mingsoft.net/',
+                liMarquee: false,
+                base: ms.base,
+                mainJson:[],
+                appId: ""
+            }
+
+        },
+        watch: {},
+        methods: {
+            openParentMenuInId:function (id){
+                window.parent.indexVue.openParentMenuInId(id)
+            },
+            getApp: function (){
+				var that = this;
+				ms.http.get(ms.manager + "/basic/app/get.do").then(function (res){
+					if (res.result){
+						that.appId = res.data.id;
+						that.queryMarkList();
+                    }
+                })
+            },
+            queryMarkList: function () {
+                var that = this;
+                ms.http.get(ms.manager + "/basic/manager/info.do").then((res) => {
+                    if(res.result) {
+                        var _markList = localStorage.getItem(res.data.managerName + "-parent-menu-list-" + that.appId);
+                        if (_markList) {
+                            that.markList = JSON.parse(_markList);
+                        }
+                        var hasMark = false;
+                        that.markList.forEach(function (item) {
+                            if(item.isMark) {
+                                hasMark = true;
+                            }
+                        });
+                        if(!hasMark) {
+                            that.markList = [];
+                        }
+                    }
+                });
+
+            },
+            getMainJson: function () {
+                var that = this;
+                axios.create({
+                    withCredentials: true
+                }).get("//cdn.mingsoft.net/open/main.json").then(function (res) {
+                    that.mainJson = JSON.parse(JSON.stringify(res.data));
+                });
+            },
+            queryContentList: function () {
+                var that = this;
+                axios.create({
+                    withCredentials: true
+                }).post("https://www.mingsoft.net/cms/content/list.do?categoryId=160&pageSize=50&flag=open").then(function (res) {
+                    if (res.data.result && res.data.data.total > 0) {
+                        that.contentList = res.data.data.rows;
+                        that.$nextTick(() =>{
+                            $('.news-list-body').liMarquee({
+                                direction: 'up',
+                                drag:false,
+                                scrollamount:20
+
+                            })
+                        })
+                    }
+                });
+            }
+        },
+        computed() {
+        },
+        created() {
+			this.getApp();
+            this.queryContentList();
+            this.getMainJson();
+        },
+        mounted:function () {
+            this.liMarquee = true;
+
+
+        }
+    });
+</script>
+<style scoped>
+    [v-cloak] {
+        display: none;
+    }
+    .str_wrap,.str_wrap.str_active  {
+        background-color: #fdf6ec;
+    }
+
+    html,body {
+    }
+    .menu-link {
+        font-size: 16px;
+    }
+    #app {
+        height: 100%;
+        overflow-y: scroll;
+        overflow-x: -moz-scrollbars-none;
+    }
+
+    .news-list-body {
+        height: 200px;
+        overflow: hidden;
+    }
+    .news-list-body ul li {
+        height: 30px;
+        color: #409EFF;
+        white-space:nowrap;
+        ext-overflow: ellipsis;
+        overflow: hidden;
+        width: 280px;
+
+    }
+    a:link, a:visited, a:active {
+        text-decoration: none;
+        color: #303133;
+        font-size: 16px;
+    }
+    a:hover {
+        color: #409EFF !important;
+    }
+
+    .ms-console {
+        width: 100%;
+        display: flex;
+        flex-direction: row;
+        flex: 1;
+        flex-shrink: 0;
+        flex-wrap: nowrap;
+        background-color: rgba(238, 238, 238, 1);
+        box-sizing: border-box;
+        margin-left: 0px;
+        padding: 10px;
+
+    }
+
+
+    .ms-console .ms-console-left {
+        width: 75%;
+        min-height: 50px;
+        display: flex;
+        flex-direction: column;
+        flex-shrink: 0;
+        flex-wrap: nowrap;
+        margin-left: 0px;
+        padding-top: 20px;
+        padding-right: 20px;
+        padding-bottom: 20px;
+        padding-left: 20px;
+        background-color: rgba(255, 255, 255, 1);
+        box-sizing: border-box;
+        margin-top: 0px;
+        margin-bottom: 0px;
+    }
+
+
+    .ms-console .ms-console-left .ms-panel {
+        width: 100%;
+        min-height: 50px;
+        display: flex;
+        flex-direction: column;
+        flex-shrink: 0;
+        flex-wrap: nowrap;
+        margin-left: 0px;
+        padding-top: 0px;
+        padding-right: 0px;
+        padding-bottom: 0px;
+        padding-left: 0px;
+        box-sizing: border-box;
+    }
+
+
+    .ms-console .ms-console-left .ms-panel .ms-panel-title {
+        width: 100%;
+        height: unset;
+        min-height: 50px;
+        display: flex;
+        flex-direction: row;
+        flex-shrink: 0;
+        flex-wrap: nowrap;
+        align-items: center;
+        margin-left: 0px;
+        padding-top: 0px;
+        padding-right: 0px;
+        padding-bottom: 0px;
+        padding-left: 0px;
+        box-sizing: border-box;
+    }
+
+
+    .ms-console .ms-console-left .ms-panel .ms-panel-title i {
+        font-size: 20PX;
+        margin-left: 0px;
+        padding-top: 0px;
+        padding-right: 0px;
+        padding-bottom: 0px;
+        padding-left: 0px;
+    }
+
+
+    .ms-console .ms-console-left .ms-panel .ms-panel-title .ms-panel-txt {
+        flex-direction: row;
+        display: inline-block;
+        word-wrap: break-word;
+        font-weight: 500;
+        font-size: 18PX;
+        margin-top: 0px;
+        margin-bottom: 0px;
+        margin-left: 8px;
+        padding-top: 0px;
+        padding-right: 0px;
+        padding-bottom: 0px;
+        padding-left: 0px;
+    }
+
+
+    .ms-console .ms-console-left .ms-panel .ms-panel-body {
+        width: 100%;
+        min-height: 50px;
+        display: flex;
+        flex-direction: row;
+        flex-shrink: 1;
+        flex-wrap: wrap;
+        padding-top: 0px;
+        padding-right: 0px;
+        padding-bottom: 0px;
+        padding-left: 0px;
+        box-sizing: border-box;
+        margin-top: 0px;
+        margin-bottom: 0px;
+    }
+
+    .space-around {
+        justify-content: space-between;
+    }
+
+    .space-around {
+        justify-content: space-between;
+    }
+    .ms-console .ms-console-left .ms-panel .ms-panel-body .menu-item-empty {
+        display: flex;
+        justify-content: center;
+        align-items: center;
+        flex: 1;
+    }
+
+    .ms-console .ms-console-left .ms-panel .ms-panel-body .menu-item {
+        width: 20%;
+        height: unset;
+        min-height: 50px;
+        display: flex;
+        flex-direction: column;
+        flex-shrink: 0;
+        flex-wrap: nowrap;
+        justify-content: center;
+        align-items: center;
+        padding-top: 0px;
+        padding-right: 0px;
+        padding-bottom: 0px;
+        padding-left: 0px;
+        box-sizing: border-box;
+        margin-top: 16px;
+        margin-bottom: 16px;
+        margin-left: 0px;
+    }
+
+
+    .ms-console .ms-console-left .ms-panel .ms-panel-body .menu-item .menu-link {
+        width: unset;
+        height: 100%;
+        min-height: 50px;
+        display: flex;
+        flex-direction: column;
+        flex-shrink: 0;
+        flex-wrap: nowrap;
+        align-items: center;
+        margin-top: 0px;
+        margin-bottom: 0px;
+        box-sizing: border-box;
+    }
+
+    .menu-link:hover {
+        color: #409EFF;
+        cursor: pointer;
+    }
+
+
+    .ms-console .ms-console-left .ms-panel .ms-panel-body .menu-item .menu-link .menu-icon {
+        font-size: 42PX;
+        margin-top: 0px;
+    }
+
+
+    .ms-console .ms-console-left .ms-panel .ms-panel-body .menu-item .menu-link .menu-text {
+        flex-direction: row;
+        display: inline-block;
+        word-wrap: break-word;
+        margin-top: 5px;
+        padding-top: 0px;
+        padding-right: 0px;
+        padding-bottom: 0px;
+        padding-left: 0px;
+        margin-left: 0px;
+    }
+
+
+    .ms-console .ms-console-left .ms-panel .ms-panel-body .text-link {
+        width: 20%;
+        height: unset;
+        min-height: 50px;
+        display: flex;
+        flex-direction: row;
+        flex-shrink: 0;
+        flex-wrap: nowrap;
+        justify-content: flex-start;
+        align-items: center;
+        padding-top: 0px;
+        padding-right: 0px;
+        padding-bottom: 0px;
+        padding-left: 0px;
+        box-sizing: border-box;
+        margin-top: 0px;
+        margin-bottom: 0px;
+        margin-left: 0px;
+    }
+
+
+    .ms-console .ms-console-left .ms-panel .ms-panel-body .text-link .text-links-icon {
+        margin-top: 0px;
+        margin-bottom: 0px;
+        margin-left: 0px;
+        padding-top: 0px;
+        padding-right: 0px;
+        padding-bottom: 0px;
+        padding-left: 0px;
+    }
+
+
+    .ms-console .ms-console-left .ms-panel .ms-panel-body .text-link .text-links-text {
+        flex-direction: row;
+        display: inline-block;
+        word-wrap: break-word;
+        margin-top: 0px;
+        padding-top: 0px;
+        padding-right: 0px;
+        padding-bottom: 0px;
+        padding-left: 0px;
+        margin-left: 8px;
+    }
+
+
+    .ms-console .ms-console-left .ms-panel .ms-panel-body .img-link {
+        width: 24%;
+        height: 200px;
+        min-height: 50px;
+        display: flex;
+        flex-direction: column;
+        flex-shrink: 0;
+        flex-wrap: nowrap;
+        justify-content: center;
+        align-items: center;
+        padding-top: 0px;
+        padding-right: 0px;
+        padding-bottom: 0px;
+        padding-left: 0px;
+        box-sizing: border-box;
+        margin-top: 16px;
+        margin-bottom: 16px;
+        margin-left: 0px;
+        position: relative;
+        border-radius: 20px;
+        overflow: hidden;
+    }
+
+
+    .ms-console .ms-console-left .ms-panel .ms-panel-body .img-link img {
+        width: 100%;
+        height: 100%;
+        margin-top: 0px;
+        margin-bottom: 0px;
+        margin-left: 0px;
+        padding-top: 0px;
+        padding-right: 0px;
+        padding-bottom: 0px;
+        padding-left: 0px;
+        position: absolute;
+        z-index: 0;
+        vertical-align: top;
+    }
+
+
+    .ms-console .ms-console-left .ms-panel .ms-panel-body .img-link .img-links-text {
+        flex-direction: row;
+        display: inline-block;
+        word-wrap: break-word;
+        margin-top: 0px;
+        padding-top: 0px;
+        padding-right: 0px;
+        padding-bottom: 0px;
+        padding-left: 0px;
+        font-size: 32PX;
+        color: #FFFFFF;
+        margin-bottom: 0px;
+        margin-left: 8px;
+        z-index: 1;
+        text-shadow: #666 3px 4px 5px;
+    }
+
+
+    .ms-console .ms-console-left .ms-panel .ms-panel-body .img-link .img-links-text-sm {
+        flex-direction: row;
+        display: inline-block;
+        word-wrap: break-word;
+        margin-top: 0px;
+        padding-top: 0px;
+        padding-right: 0px;
+        padding-bottom: 0px;
+        padding-left: 0px;
+        font-size: 24PX;
+        color: #FFFFFF;
+        margin-bottom: 0px;
+        margin-left: 8px;
+        z-index: 1;
+        text-shadow: #666 3px 4px 5px;
+    }
+
+
+    .ms-console .ms-console-right {
+        width: unset;
+        min-height: 50px;
+        display: flex;
+        flex-direction: column;
+        flex: 1;
+        flex-shrink: 0;
+        flex-wrap: nowrap;
+        margin-left: 10px;
+        box-sizing: border-box;
+        margin-bottom: 0px;
+        padding-top: 0px;
+        padding-right: 0px;
+        padding-bottom: 0px;
+        padding-left: 0px;
+        margin-top: 0px;
+        margin-right: 0px;
+    }
+
+
+    .ms-console .ms-console-right .news-list {
+        width: 100%;
+        height: unset;
+        min-height: 50px;
+        display: flex;
+        flex-direction: column;
+        flex-shrink: 0;
+        flex-wrap: nowrap;
+        margin-bottom: 8px;
+        margin-left: 0px;
+        background-color: rgba(253, 246, 236, 1);
+        box-sizing: border-box;
+        margin-right: 0px;
+        padding-top: 0px;
+        padding-right: 0px;
+        padding-bottom: 8px;
+        padding-left: 0px;
+    }
+
+
+    .ms-console .ms-console-right .news-list .news-list-title {
+        width: 100%;
+        height: unset;
+        display: flex;
+        flex-direction: row;
+        flex-shrink: 0;
+        flex-wrap: nowrap;
+        justify-content: flex-start;
+        align-items: center;
+        margin-right: 0px;
+        margin-bottom: 0px;
+        padding-top: 10px;
+        padding-right: 10px;
+        padding-bottom: 10px;
+        padding-left: 10px;
+        box-sizing: border-box;
+    }
+
+
+    .ms-console .ms-console-right .news-list .news-list-title > img {
+        width: 20px;
+        height: 20px;
+        margin-right: 10px;
+        margin-bottom: 0px;
+        padding-top: 0px;
+        padding-right: 0px;
+        padding-bottom: 0px;
+        padding-left: 0px;
+        vertical-align: top;
+    }
+
+
+    .ms-console .ms-console-right .news-list .news-list-title > span {
+        flex-direction: row;
+        display: inline-block;
+        word-wrap: break-word;
+        color: #E6A23C;
+        margin-right: 0px;
+        margin-bottom: 0px;
+        padding-top: 0px;
+        padding-right: 0px;
+        padding-bottom: 0px;
+        padding-left: 0px;
+    }
+
+
+    .ms-console .ms-console-right .news-list .news-list-body {
+        width: 100%;
+        min-height: 50px;
+        line-height: 48px;
+        display: flex;
+        flex-direction: column;
+        flex-shrink: 0;
+        flex-wrap: nowrap;
+        padding-top: 10px;
+        padding-right: 10px;
+        padding-bottom: 10px;
+        padding-left: 40px;
+        box-sizing: border-box;
+    }
+
+
+    .ms-console .ms-console-right .news-list .news-list-body .news-list-a {
+        flex-direction: row;
+        line-height: 24px;
+        color: #409EFF;
+        text-decoration: none;
+        display: flex;
+        cursor: pointer;
+        padding-top: 0px;
+        padding-left: 0px;
+        padding-right: 0px;
+        padding-bottom: 0px;
+        margin-bottom: 0px;
+        height: 28px;
+        justify-content: flex-start;
+        align-items: center;
+    }
+
+    .news-list-a:hover {
+        text-decoration: underline !important;
+    }
+
+
+    .ms-console .ms-console-right .ms-service {
+        width: 100%;
+        height: unset;
+        min-height: 50px;
+        display: flex;
+        flex-direction: column;
+        flex-shrink: 0;
+        flex-wrap: nowrap;
+        align-items: center;
+        margin-bottom: 8px;
+        margin-left: 0px;
+        padding-right: 10px;
+        padding-bottom: 10px;
+        padding-left: 10px;
+        background-color: rgba(255, 255, 255, 1);
+        box-sizing: border-box;
+    }
+
+
+    .ms-console .ms-console-right .ms-service .ms-panel {
+        width: 100%;
+        min-height: 50px;
+        display: flex;
+        flex-direction: column;
+        flex-shrink: 0;
+        flex-wrap: nowrap;
+        margin-left: 0px;
+        padding-top: 0px;
+        padding-right: 0px;
+        padding-bottom: 0px;
+        padding-left: 0px;
+        box-sizing: border-box;
+        margin-bottom: 0px;
+    }
+
+
+    .ms-console .ms-console-right .ms-service .ms-panel .ms-panel-title {
+        width: 100%;
+        height: unset;
+        min-height: 50px;
+        display: flex;
+        flex-direction: row;
+        flex-shrink: 0;
+        flex-wrap: nowrap;
+        align-items: center;
+        margin-left: 0px;
+        padding-top: 0px;
+        padding-right: 0px;
+        padding-bottom: 0px;
+        padding-left: 0px;
+        box-sizing: border-box;
+        margin-bottom: 0px;
+    }
+
+
+    .ms-console .ms-console-right .ms-service .ms-panel .ms-panel-title i {
+        font-size: 20PX;
+        margin-left: 0px;
+        padding-top: 0px;
+        padding-right: 0px;
+        padding-bottom: 0px;
+        padding-left: 0px;
+    }
+
+
+    .ms-console .ms-console-right .ms-service .ms-panel .ms-panel-title .ms-panel-txt {
+        flex-direction: row;
+        display: inline-block;
+        word-wrap: break-word;
+        font-weight: 500;
+        font-size: 18PX;
+        margin-top: 0px;
+        margin-bottom: 0px;
+        margin-left: 8px;
+        padding-top: 0px;
+        padding-right: 0px;
+        padding-bottom: 0px;
+        padding-left: 0px;
+    }
+
+
+    .ms-console .ms-console-right .ms-service .ms-panel .ms-panel-body {
+        width: 100%;
+        min-height: 50px;
+        display: flex;
+        flex-direction: row;
+        flex-shrink: 1;
+        flex-wrap: wrap;
+        padding-top: 0px;
+        padding-right: 0px;
+        padding-bottom: 0px;
+        padding-left: 0px;
+        box-sizing: border-box;
+        margin-top: 0px;
+        margin-bottom: 0px;
+        margin-left: 0px;
+    }
+
+
+    .ms-console .ms-console-right .ms-service .ms-panel .ms-panel-body .server-item {
+        width: 50%;
+        height: 120px;
+        min-height: 50px;
+        display: flex;
+        flex-direction: column;
+        flex-shrink: 0;
+        flex-wrap: nowrap;
+        justify-content: center;
+        align-items: center;
+        margin-bottom: 0px;
+        box-sizing: border-box;
+        margin-left: 0px;
+        padding-right: 0px;
+        padding-left: 0px;
+        margin-right: 0px;
+        margin-top: 0px;
+    }
+
+
+    .ms-console .ms-console-right .ms-service .ms-panel .ms-panel-body .server-item > i {
+        font-size: 42PX;
+        margin-right: 10px;
+        margin-left: 0px;
+    }
+
+
+    .ms-console .ms-console-right .ms-service .ms-panel .ms-panel-body .server-item .server-text {
+        width: 100%;
+        height: unset;
+        min-height: 50px;
+        display: flex;
+        flex-direction: column;
+        flex-shrink: 0;
+        flex-wrap: nowrap;
+        box-sizing: border-box;
+        justify-content: center;
+        align-items: center;
+        margin-right: 0px;
+        margin-left: 0px;
+    }
+
+
+    .ms-console .ms-console-right .ms-service .ms-panel .ms-panel-body .server-item .server-text .server-desc {
+        flex-direction: row;
+        display: inline-block;
+        word-wrap: break-word;
+        font-size: 12PX;
+        color: #999999;
+        margin-left: 0px;
+        margin-right: 0px;
+    }
+
+
+    .ms-console .ms-console-right .ms-service .ms-panel .ms-panel-body .server-item .server-text .server-date {
+        width: 100%;
+        height: unset;
+        display: flex;
+        flex-direction: row;
+        flex-shrink: 0;
+        flex-wrap: nowrap;
+        justify-content: center;
+        align-items: center;
+        box-sizing: border-box;
+        margin-top: 10px;
+    }
+
+
+    .ms-console .ms-console-right .ms-service .ms-panel .ms-panel-body .server-item .server-text .server-date .server-data {
+        flex-direction: row;
+        display: inline-block;
+        word-wrap: break-word;
+        line-height: 1.4;
+        font-size: 20PX;
+        font-weight: 600;
+        color: #333333;
+        margin-left: 0px;
+        margin-top: 0px;
+    }
+
+
+    .ms-console .ms-console-right .ms-service .ms-panel .ms-panel-body .server-item .server-text .server-date .s {
+        flex-direction: row;
+        display: inline-block;
+        word-wrap: break-word;
+        line-height: 1.4;
+        font-size: 20PX;
+        font-weight: 600;
+        color: #333333;
+        margin-left: 0px;
+    }
+
+
+    .ms-console .ms-console-right .ms-service .ms-panel .ms-panel-body .server-item .server-text .server-date .date-green {
+        flex-direction: row;
+        display: inline-block;
+        word-wrap: break-word;
+        line-height: 1.4;
+        font-size: 20PX;
+        font-weight: 600;
+        color: #67C23A;
+        margin-left: 0px;
+    }
+
+
+    .ms-console .ms-console-right .ms-service .ms-panel .ms-panel-body .qq-item {
+        width: 50%;
+        min-height: 50px;
+        display: flex;
+        flex-direction: row;
+        flex-shrink: 0;
+        flex-wrap: nowrap;
+        justify-content: flex-start;
+        align-items: center;
+        margin-bottom: 10px;
+        box-sizing: border-box;
+        margin-left: 0px;
+        padding-right: 0px;
+        padding-left: 0px;
+    }
+
+
+    .ms-console .ms-console-right .ms-service .ms-panel .ms-panel-body .qq-item .qq-icon {
+        width: 35px;
+        height: 39px;
+        margin-left: 10px;
+        vertical-align: top;
+        margin-right: 10px;
+        padding-right: 0px;
+        padding-left: 0px;
+    }
+
+
+    .ms-console .ms-console-right .ms-service .ms-panel .ms-panel-body .qq-item .qq-text {
+        width: unset;
+        height: unset;
+        min-height: 50px;
+        display: flex;
+        flex-direction: column;
+        flex-shrink: 0;
+        flex-wrap: nowrap;
+        box-sizing: border-box;
+        justify-content: center;
+        align-items: flex-start;
+        margin-right: 0px;
+        margin-left: 0px;
+    }
+
+
+    .ms-console .ms-console-right .ms-service .ms-panel .ms-panel-body .qq-item .qq-text .qq-text-name {
+        flex-direction: row;
+        display: inline-block;
+        word-wrap: break-word;
+        font-size: 12PX;
+        color: #999999;
+        margin-left: 0px;
+    }
+
+
+    .ms-console .ms-console-right .ms-service .ms-panel .ms-panel-body .qq-item .qq-text .qq-text-no {
+        flex-direction: row;
+        display: inline-block;
+        word-wrap: break-word;
+        line-height: 1.4;
+        font-size: 16PX;
+        font-weight: 600;
+        color: #333333;
+        margin-left: 0px;
+    }
+
+
+    .ms-console .ms-console-right .ms-other {
+        width: 100%;
+        height: unset;
+        min-height: 50px;
+        display: flex;
+        flex-direction: column;
+        flex: 1;
+        flex-shrink: 0;
+        flex-wrap: nowrap;
+        align-items: center;
+        margin-bottom: 0px;
+        margin-left: 0px;
+        padding-right: 10px;
+        padding-bottom: 10px;
+        padding-left: 10px;
+        background-color: rgba(255, 255, 255, 1);
+        box-sizing: border-box;
+    }
+
+
+    .ms-console .ms-console-right .ms-other .ms-panel {
+        width: 100%;
+        min-height: 50px;
+        display: flex;
+        flex-direction: column;
+        flex-shrink: 0;
+        flex-wrap: nowrap;
+        margin-left: 0px;
+        padding-top: 0px;
+        padding-right: 0px;
+        padding-bottom: 0px;
+        padding-left: 0px;
+        box-sizing: border-box;
+    }
+
+
+    .ms-console .ms-console-right .ms-other .ms-panel .ms-panel-title {
+        width: 100%;
+        height: unset;
+        min-height: 50px;
+        display: flex;
+        flex-direction: row;
+        flex-shrink: 0;
+        flex-wrap: nowrap;
+        align-items: center;
+        margin-left: 0px;
+        padding-top: 0px;
+        padding-right: 0px;
+        padding-bottom: 0px;
+        padding-left: 0px;
+        box-sizing: border-box;
+        margin-bottom: 0px;
+    }
+
+
+    .ms-console .ms-console-right .ms-other .ms-panel .ms-panel-title i {
+        font-size: 20PX;
+        margin-left: 0px;
+        padding-top: 0px;
+        padding-right: 0px;
+        padding-bottom: 0px;
+        padding-left: 0px;
+    }
+
+
+    .ms-console .ms-console-right .ms-other .ms-panel .ms-panel-title .ms-panel-txt {
+        flex-direction: row;
+        display: inline-block;
+        word-wrap: break-word;
+        font-weight: 500;
+        font-size: 18PX;
+        margin-top: 0px;
+        margin-bottom: 0px;
+        margin-left: 8px;
+        padding-top: 0px;
+        padding-right: 0px;
+        padding-bottom: 0px;
+        padding-left: 0px;
+    }
+
+
+    .ms-console .ms-console-right .ms-other .ms-panel .ms-panel-body {
+        width: 100%;
+        min-height: 50px;
+        display: flex;
+        flex-direction: row;
+        flex-shrink: 1;
+        flex-wrap: wrap;
+        padding-top: 0px;
+        padding-right: 0px;
+        padding-bottom: 0px;
+        padding-left: 0px;
+        box-sizing: border-box;
+        margin-top: 0px;
+        margin-bottom: 0px;
+        margin-left: 0px;
+    }
+
+
+    .ms-console .ms-console-right .ms-other .ms-panel .ms-panel-body .qq-item {
+        width: 50%;
+        height: 100px;
+        min-height: 50px;
+        display: flex;
+        flex-direction: row;
+        flex-shrink: 0;
+        flex-wrap: nowrap;
+        justify-content: flex-start;
+        align-items: center;
+        margin-bottom: 0px;
+        box-sizing: border-box;
+        margin-left: 0px;
+        padding-right: 0px;
+        padding-left: 0px;
+        margin-right: 0px;
+    }
+
+
+    .ms-console .ms-console-right .ms-other .ms-panel .ms-panel-body .qq-item .qq-icon {
+        width: 35px;
+        height: 39px;
+        margin-left: 10px;
+        vertical-align: top;
+        margin-right: 10px;
+        padding-right: 0px;
+        padding-left: 0px;
+    }
+
+
+    .ms-console .ms-console-right .ms-other .ms-panel .ms-panel-body .qq-item .qq-text {
+        width: unset;
+        height: unset;
+        min-height: 50px;
+        display: flex;
+        flex-direction: column;
+        flex-shrink: 0;
+        flex-wrap: nowrap;
+        box-sizing: border-box;
+        justify-content: center;
+        align-items: flex-start;
+        margin-right: 0px;
+        margin-left: 0px;
+    }
+
+
+    .ms-console .ms-console-right .ms-other .ms-panel .ms-panel-body .qq-item .qq-text .qq-text-name {
+        flex-direction: row;
+        display: inline-block;
+        word-wrap: break-word;
+        font-size: 12PX;
+        color: #999999;
+        margin-left: 0px;
+    }
+
+
+    .ms-console .ms-console-right .ms-other .ms-panel .ms-panel-body .qq-item .qq-text .qq-text-no {
+        flex-direction: row;
+        display: inline-block;
+        word-wrap: break-word;
+        line-height: 1.4;
+        font-size: 16PX;
+        font-weight: 600;
+        color: #333333;
+        margin-left: 0px;
+    }
+
+
+    .ms-console .ms-console-right .ms-other .version-link {
+        width: 98%;
+        height: unset;
+        margin-left: 0px;
+        padding-right: 0px;
+        padding-left: 0px;
+        vertical-align: top;
+        margin-top: 0px;
+        margin-bottom: 8px;
+    }
+
+
+    .ms-console .ms-console-right .ms-other .version-link img {
+        width: 100%;
+        height: unset;
+        margin-left: 0px;
+        padding-right: 0px;
+        padding-left: 0px;
+        vertical-align: top;
+        margin-top: 0px;
+        margin-bottom: 0px;
+    }
+
+
+    @media (max-width: 768px) {
+        .ms-console {
+            width: 100%;
+            height: unset;
+            min-height: 50px;
+            display: flex;
+            flex-direction: column;
+            flex: 1;
+            flex-shrink: 0;
+            flex-wrap: nowrap;
+            background-color: rgba(238, 238, 238, 1);
+            box-sizing: border-box;
+            margin-left: 0px;
+            padding-top: 10px;
+            padding-right: 10px;
+            padding-bottom: 10px;
+            padding-left: 10px;
+            margin-top: 0px;
+            margin-bottom: 0px;
+        }
+
+        .ms-console .ms-console-left {
+            width: 100%;
+            min-height: 50px;
+            display: flex;
+            flex-direction: column;
+            flex-shrink: 0;
+            flex-wrap: nowrap;
+            margin-left: 0px;
+            padding-top: 20px;
+            padding-right: 20px;
+            padding-bottom: 20px;
+            padding-left: 20px;
+            background-color: rgba(255, 255, 255, 1);
+            box-sizing: border-box;
+            margin-top: 0px;
+            margin-bottom: 0px;
+        }
+
+        .ms-console .ms-console-left .ms-panel {
+            width: 100%;
+            min-height: 50px;
+            display: flex;
+            flex-direction: column;
+            flex-shrink: 0;
+            flex-wrap: nowrap;
+            margin-left: 0px;
+            padding-top: 0px;
+            padding-right: 0px;
+            padding-bottom: 0px;
+            padding-left: 0px;
+            box-sizing: border-box;
+        }
+
+        .ms-console .ms-console-left .ms-panel .ms-panel-title {
+            width: 100%;
+            height: unset;
+            min-height: 50px;
+            display: flex;
+            flex-direction: row;
+            flex-shrink: 0;
+            flex-wrap: nowrap;
+            align-items: center;
+            margin-left: 0px;
+            padding-top: 0px;
+            padding-right: 0px;
+            padding-bottom: 0px;
+            padding-left: 0px;
+            box-sizing: border-box;
+        }
+
+        .ms-console .ms-console-left .ms-panel .ms-panel-title i {
+            font-size: 20PX;
+            margin-left: 0px;
+            padding-top: 0px;
+            padding-right: 0px;
+            padding-bottom: 0px;
+            padding-left: 0px;
+        }
+
+        .ms-console .ms-console-left .ms-panel .ms-panel-title .ms-panel-txt {
+            flex-direction: row;
+            display: inline-block;
+            word-wrap: break-word;
+            font-weight: 500;
+            font-size: 18PX;
+            margin-top: 0px;
+            margin-bottom: 0px;
+            margin-left: 8px;
+            padding-top: 0px;
+            padding-right: 0px;
+            padding-bottom: 0px;
+            padding-left: 0px;
+        }
+
+        .ms-console .ms-console-left .ms-panel .ms-panel-body {
+            width: 100%;
+            min-height: 50px;
+            display: flex;
+            flex-direction: row;
+            flex-shrink: 1;
+            flex-wrap: wrap;
+            padding-top: 0px;
+            padding-right: 0px;
+            padding-bottom: 0px;
+            padding-left: 0px;
+            box-sizing: border-box;
+            margin-top: 0px;
+            margin-bottom: 0px;
+        }
+
+        .ms-console .ms-console-left .ms-panel .ms-panel-body .menu-item {
+            width: 50%;
+            height: unset;
+            min-height: 50px;
+            display: flex;
+            flex-direction: column;
+            flex-shrink: 0;
+            flex-wrap: nowrap;
+            justify-content: center;
+            align-items: center;
+            padding-top: 0px;
+            padding-right: 0px;
+            padding-bottom: 0px;
+            padding-left: 0px;
+            box-sizing: border-box;
+            margin-top: 16px;
+            margin-bottom: 16px;
+            margin-left: 0px;
+        }
+
+        .ms-console .ms-console-left .ms-panel .ms-panel-body .menu-item .menu-link {
+            width: unset;
+            height: 100%;
+            min-height: 50px;
+            display: flex;
+            flex-direction: column;
+            flex-shrink: 0;
+            flex-wrap: nowrap;
+            align-items: center;
+            margin-top: 0px;
+            margin-bottom: 0px;
+            box-sizing: border-box;
+        }
+
+        .ms-console .ms-console-left .ms-panel .ms-panel-body .menu-item .menu-link .menu-icon {
+            font-size: 42PX;
+            margin-top: 0px;
+        }
+
+        .ms-console .ms-console-left .ms-panel .ms-panel-body .menu-item .menu-link .menu-text {
+            flex-direction: row;
+            display: inline-block;
+            word-wrap: break-word;
+            margin-top: 5px;
+            padding-top: 0px;
+            padding-right: 0px;
+            padding-bottom: 0px;
+            padding-left: 0px;
+            margin-left: 0px;
+        }
+
+        .ms-console .ms-console-left .ms-panel .ms-panel-body .text-link {
+            width: 50%;
+            height: unset;
+            min-height: 50px;
+            display: flex;
+            flex-direction: row;
+            flex-shrink: 0;
+            flex-wrap: nowrap;
+            justify-content: flex-start;
+            align-items: center;
+            padding-top: 0px;
+            padding-right: 0px;
+            padding-bottom: 0px;
+            padding-left: 0px;
+            box-sizing: border-box;
+            margin-top: 0px;
+            margin-bottom: 0px;
+            margin-left: 0px;
+        }
+
+        .ms-console .ms-console-left .ms-panel .ms-panel-body .text-link .text-links-icon {
+            margin-top: 0px;
+            margin-bottom: 0px;
+            margin-left: 0px;
+            padding-top: 0px;
+            padding-right: 0px;
+            padding-bottom: 0px;
+            padding-left: 0px;
+        }
+
+        .ms-console .ms-console-left .ms-panel .ms-panel-body .text-link .text-links-text {
+            flex-direction: row;
+            display: inline-block;
+            word-wrap: break-word;
+            margin-top: 0px;
+            padding-top: 0px;
+            padding-right: 0px;
+            padding-bottom: 0px;
+            padding-left: 0px;
+            margin-left: 8px;
+            margin-bottom: 0px;
+        }
+
+        .ms-console .ms-console-left .ms-panel .ms-panel-body .img-link {
+            width: 100%;
+            height: 200px;
+            min-height: 50px;
+            display: flex;
+            flex-direction: column;
+            flex-shrink: 0;
+            flex-wrap: nowrap;
+            justify-content: center;
+            align-items: center;
+            padding-top: 0px;
+            padding-right: 0px;
+            padding-bottom: 0px;
+            padding-left: 0px;
+            box-sizing: border-box;
+            margin-top: 16px;
+            margin-bottom: 16px;
+            margin-left: 0px;
+            position: relative;
+            border-radius: 20px;
+            overflow: hidden;
+        }
+
+        .ms-console .ms-console-left .ms-panel .ms-panel-body .img-link img {
+            width: 100%;
+            height: 100%;
+            margin-top: 0px;
+            margin-bottom: 0px;
+            margin-left: 0px;
+            padding-top: 0px;
+            padding-right: 0px;
+            padding-bottom: 0px;
+            padding-left: 0px;
+            position: absolute;
+            z-index: 0;
+            vertical-align: top;
+        }
+
+        .ms-console .ms-console-left .ms-panel .ms-panel-body .img-link .img-links-text {
+            flex-direction: row;
+            display: inline-block;
+            word-wrap: break-word;
+            margin-top: 0px;
+            padding-top: 0px;
+            padding-right: 0px;
+            padding-bottom: 0px;
+            padding-left: 0px;
+            font-size: 32PX;
+            color: #FFFFFF;
+            margin-bottom: 0px;
+            margin-left: 8px;
+            z-index: 1;
+            text-shadow: #666 3px 4px 5px;
+        }
+
+        .ms-console .ms-console-left .ms-panel .ms-panel-body .img-link .img-links-text-sm {
+            flex-direction: row;
+            display: inline-block;
+            word-wrap: break-word;
+            margin-top: 0px;
+            padding-top: 0px;
+            padding-right: 0px;
+            padding-bottom: 0px;
+            padding-left: 0px;
+            font-size: 24PX;
+            color: #FFFFFF;
+            margin-bottom: 0px;
+            margin-left: 8px;
+            z-index: 1;
+            text-shadow: #666 3px 4px 5px;
+        }
+
+        .ms-console .ms-console-right {
+            width: unset;
+            height: 100%;
+            min-height: 50px;
+            display: flex;
+            flex-direction: column;
+            flex: 1;
+            flex-shrink: 0;
+            flex-wrap: nowrap;
+            margin-left: 0px;
+            box-sizing: border-box;
+            margin-bottom: 0px;
+            padding-top: 0px;
+            padding-right: 0px;
+            padding-bottom: 0px;
+            padding-left: 0px;
+            margin-top: 10px;
+            margin-right: 0px;
+        }
+
+        .ms-console .ms-console-right .news-list {
+            width: 100%;
+            height: unset;
+            min-height: 50px;
+            display: flex;
+            flex-direction: column;
+            flex-shrink: 0;
+            flex-wrap: nowrap;
+            margin-bottom: 8px;
+            margin-left: 0px;
+            background-color: rgba(253, 246, 236, 1);
+            box-sizing: border-box;
+            margin-right: 0px;
+            padding-top: 0px;
+            padding-right: 0px;
+            padding-bottom: 8px;
+            padding-left: 0px;
+        }
+
+        .ms-console .ms-console-right .news-list .news-list-title {
+            width: 100%;
+            height: unset;
+            display: flex;
+            flex-direction: row;
+            flex-shrink: 0;
+            flex-wrap: nowrap;
+            justify-content: flex-start;
+            align-items: center;
+            margin-right: 0px;
+            margin-bottom: 0px;
+            padding-top: 10px;
+            padding-right: 10px;
+            padding-bottom: 10px;
+            padding-left: 10px;
+            box-sizing: border-box;
+        }
+
+        .ms-console .ms-console-right .news-list .news-list-title > img {
+            width: 20px;
+            height: 20px;
+            margin-right: 10px;
+            margin-bottom: 0px;
+            padding-top: 0px;
+            padding-right: 0px;
+            padding-bottom: 0px;
+            padding-left: 0px;
+            vertical-align: top;
+        }
+
+        .ms-console .ms-console-right .news-list .news-list-title > span {
+            flex-direction: row;
+            display: inline-block;
+            word-wrap: break-word;
+            color: #E6A23C;
+            margin-right: 0px;
+            margin-bottom: 0px;
+            padding-top: 0px;
+            padding-right: 0px;
+            padding-bottom: 0px;
+            padding-left: 0px;
+        }
+
+        .ms-console .ms-console-right .news-list .news-list-body {
+            width: 100%;
+            height: unset;
+            min-height: 50px;
+            line-height: 48px;
+            display: flex;
+            flex-direction: column;
+            flex-shrink: 0;
+            flex-wrap: nowrap;
+            padding-top: 10px;
+            padding-right: 10px;
+            padding-bottom: 10px;
+            padding-left: 40px;
+            box-sizing: border-box;
+        }
+
+        .ms-console .ms-console-right .news-list .news-list-body .news-list-a {
+            flex-direction: row;
+            line-height: 24px;
+            color: #409EFF;
+            text-decoration: none;
+            display: flex;
+            cursor: pointer;
+            padding-top: 0px;
+            padding-left: 0px;
+            padding-right: 0px;
+            padding-bottom: 0px;
+            margin-bottom: 0px;
+            height: 28px;
+            justify-content: flex-start;
+            align-items: center;
+        }
+
+        .ms-console .ms-console-right .ms-service {
+            width: 100%;
+            height: unset;
+            min-height: 50px;
+            display: flex;
+            flex-direction: column;
+            flex-shrink: 0;
+            flex-wrap: nowrap;
+            align-items: center;
+            margin-bottom: 8px;
+            margin-left: 0px;
+            padding-right: 10px;
+            padding-bottom: 10px;
+            padding-left: 10px;
+            background-color: rgba(255, 255, 255, 1);
+            box-sizing: border-box;
+        }
+
+        .ms-console .ms-console-right .ms-service .ms-panel {
+            width: 100%;
+            min-height: 50px;
+            display: flex;
+            flex-direction: column;
+            flex-shrink: 0;
+            flex-wrap: nowrap;
+            margin-left: 0px;
+            padding-top: 0px;
+            padding-right: 0px;
+            padding-bottom: 0px;
+            padding-left: 0px;
+            box-sizing: border-box;
+            margin-bottom: 0px;
+        }
+
+        .ms-console .ms-console-right .ms-service .ms-panel .ms-panel-title {
+            width: 100%;
+            height: unset;
+            min-height: 50px;
+            display: flex;
+            flex-direction: row;
+            flex-shrink: 0;
+            flex-wrap: nowrap;
+            align-items: center;
+            margin-left: 0px;
+            padding-top: 0px;
+            padding-right: 0px;
+            padding-bottom: 0px;
+            padding-left: 0px;
+            box-sizing: border-box;
+            margin-bottom: 0px;
+        }
+
+        .ms-console .ms-console-right .ms-service .ms-panel .ms-panel-title i {
+            font-size: 20PX;
+            margin-left: 0px;
+            padding-top: 0px;
+            padding-right: 0px;
+            padding-bottom: 0px;
+            padding-left: 0px;
+        }
+
+        .ms-console .ms-console-right .ms-service .ms-panel .ms-panel-title .ms-panel-txt {
+            flex-direction: row;
+            display: inline-block;
+            word-wrap: break-word;
+            font-weight: 500;
+            font-size: 18PX;
+            margin-top: 0px;
+            margin-bottom: 0px;
+            margin-left: 8px;
+            padding-top: 0px;
+            padding-right: 0px;
+            padding-bottom: 0px;
+            padding-left: 0px;
+        }
+
+        .ms-console .ms-console-right .ms-service .ms-panel .ms-panel-body {
+            width: 100%;
+            min-height: 50px;
+            display: flex;
+            flex-direction: row;
+            flex-shrink: 1;
+            flex-wrap: wrap;
+            padding-top: 0px;
+            padding-right: 0px;
+            padding-bottom: 0px;
+            padding-left: 0px;
+            box-sizing: border-box;
+            margin-top: 0px;
+            margin-bottom: 0px;
+            margin-left: 0px;
+        }
+
+        .ms-console .ms-console-right .ms-service .ms-panel .ms-panel-body .server-item {
+            width: 50%;
+            height: 120px;
+            min-height: 50px;
+            display: flex;
+            flex-direction: column;
+            flex-shrink: 0;
+            flex-wrap: nowrap;
+            justify-content: center;
+            align-items: center;
+            margin-bottom: 0px;
+            box-sizing: border-box;
+            margin-left: 0px;
+            padding-right: 0px;
+            padding-left: 0px;
+            margin-right: 0px;
+            margin-top: 0px;
+        }
+
+        .ms-console .ms-console-right .ms-service .ms-panel .ms-panel-body .server-item > i {
+            font-size: 42PX;
+            margin-right: 10px;
+            margin-left: 0px;
+        }
+
+        .ms-console .ms-console-right .ms-service .ms-panel .ms-panel-body .server-item .server-text {
+            width: 100%;
+            height: unset;
+            min-height: 50px;
+            display: flex;
+            flex-direction: column;
+            flex-shrink: 0;
+            flex-wrap: nowrap;
+            box-sizing: border-box;
+            justify-content: center;
+            align-items: center;
+            margin-right: 0px;
+            margin-left: 0px;
+        }
+
+        .ms-console .ms-console-right .ms-service .ms-panel .ms-panel-body .server-item .server-text .server-desc {
+            flex-direction: row;
+            display: inline-block;
+            word-wrap: break-word;
+            font-size: 12PX;
+            color: #999999;
+            margin-left: 0px;
+            margin-right: 0px;
+        }
+
+        .ms-console .ms-console-right .ms-service .ms-panel .ms-panel-body .server-item .server-text .server-date {
+            width: 100%;
+            height: unset;
+            display: flex;
+            flex-direction: row;
+            flex-shrink: 0;
+            flex-wrap: nowrap;
+            justify-content: center;
+            align-items: center;
+            box-sizing: border-box;
+            margin-top: 10px;
+        }
+
+        .ms-console .ms-console-right .ms-service .ms-panel .ms-panel-body .server-item .server-text .server-date .server-data {
+            flex-direction: row;
+            display: inline-block;
+            word-wrap: break-word;
+            line-height: 1.4;
+            font-size: 20PX;
+            font-weight: 600;
+            color: #333333;
+            margin-left: 0px;
+            margin-top: 0px;
+        }
+
+        .ms-console .ms-console-right .ms-service .ms-panel .ms-panel-body .server-item .server-text .server-date .s {
+            flex-direction: row;
+            display: inline-block;
+            word-wrap: break-word;
+            line-height: 1.4;
+            font-size: 20PX;
+            font-weight: 600;
+            color: #333333;
+            margin-left: 0px;
+        }
+
+        .ms-console .ms-console-right .ms-service .ms-panel .ms-panel-body .server-item .server-text .server-date .date-green {
+            flex-direction: row;
+            display: inline-block;
+            word-wrap: break-word;
+            line-height: 1.4;
+            font-size: 20PX;
+            font-weight: 600;
+            color: #67C23A;
+            margin-left: 0px;
+        }
+
+        .ms-console .ms-console-right .ms-service .ms-panel .ms-panel-body .qq-item {
+            width: 50%;
+            height: 100px;
+            min-height: 50px;
+            display: flex;
+            flex-direction: row;
+            flex-shrink: 0;
+            flex-wrap: nowrap;
+            justify-content: flex-start;
+            align-items: center;
+            margin-bottom: 0px;
+            box-sizing: border-box;
+            margin-left: 0px;
+            padding-right: 0px;
+            padding-left: 0px;
+            margin-top: 0px;
+        }
+
+        .ms-console .ms-console-right .ms-service .ms-panel .ms-panel-body .qq-item .qq-icon {
+            width: 35px;
+            height: 39px;
+            margin-left: 4px;
+            vertical-align: top;
+            margin-right: 4px;
+            padding-right: 0px;
+            padding-left: 0px;
+        }
+
+        .ms-console .ms-console-right .ms-service .ms-panel .ms-panel-body .qq-item .qq-text {
+            width: unset;
+            height: unset;
+            min-height: 50px;
+            display: flex;
+            flex-direction: column;
+            flex-shrink: 0;
+            flex-wrap: nowrap;
+            box-sizing: border-box;
+            justify-content: center;
+            align-items: flex-start;
+            margin-right: 0px;
+            margin-left: 0px;
+        }
+
+        .ms-console .ms-console-right .ms-service .ms-panel .ms-panel-body .qq-item .qq-text .qq-text-name {
+            flex-direction: row;
+            display: inline-block;
+            word-wrap: break-word;
+            font-size: 12PX;
+            color: #999999;
+            margin-left: 0px;
+        }
+
+        .ms-console .ms-console-right .ms-service .ms-panel .ms-panel-body .qq-item .qq-text .qq-text-no {
+            flex-direction: row;
+            display: inline-block;
+            word-wrap: break-word;
+            line-height: 1.4;
+            font-size: 16PX;
+            font-weight: 600;
+            color: #333333;
+            margin-left: 0px;
+        }
+
+        .ms-console .ms-console-right .ms-other {
+            width: 100%;
+            height: unset;
+            min-height: 50px;
+            display: flex;
+            flex-direction: column;
+            flex: 1;
+            flex-shrink: 0;
+            flex-wrap: nowrap;
+            align-items: center;
+            margin-bottom: 0px;
+            margin-left: 0px;
+            padding-right: 10px;
+            padding-bottom: 10px;
+            padding-left: 10px;
+            background-color: rgba(255, 255, 255, 1);
+            box-sizing: border-box;
+        }
+
+        .ms-console .ms-console-right .ms-other .ms-panel {
+            width: 100%;
+            min-height: 50px;
+            display: flex;
+            flex-direction: column;
+            flex-shrink: 0;
+            flex-wrap: nowrap;
+            margin-left: 0px;
+            padding-top: 0px;
+            padding-right: 0px;
+            padding-bottom: 0px;
+            padding-left: 0px;
+            box-sizing: border-box;
+        }
+
+        .ms-console .ms-console-right .ms-other .ms-panel .ms-panel-title {
+            width: 100%;
+            height: unset;
+            min-height: 50px;
+            display: flex;
+            flex-direction: row;
+            flex-shrink: 0;
+            flex-wrap: nowrap;
+            align-items: center;
+            margin-left: 0px;
+            padding-top: 0px;
+            padding-right: 0px;
+            padding-bottom: 0px;
+            padding-left: 0px;
+            box-sizing: border-box;
+            margin-bottom: 0px;
+        }
+
+        .ms-console .ms-console-right .ms-other .ms-panel .ms-panel-title i {
+            font-size: 20PX;
+            margin-left: 0px;
+            padding-top: 0px;
+            padding-right: 0px;
+            padding-bottom: 0px;
+            padding-left: 0px;
+        }
+
+        .ms-console .ms-console-right .ms-other .ms-panel .ms-panel-title .ms-panel-txt {
+            flex-direction: row;
+            display: inline-block;
+            word-wrap: break-word;
+            font-weight: 500;
+            font-size: 18PX;
+            margin-top: 0px;
+            margin-bottom: 0px;
+            margin-left: 8px;
+            padding-top: 0px;
+            padding-right: 0px;
+            padding-bottom: 0px;
+            padding-left: 0px;
+        }
+
+        .ms-console .ms-console-right .ms-other .ms-panel .ms-panel-body {
+            width: 100%;
+            min-height: 50px;
+            display: flex;
+            flex-direction: row;
+            flex-shrink: 1;
+            flex-wrap: wrap;
+            padding-top: 0px;
+            padding-right: 0px;
+            padding-bottom: 0px;
+            padding-left: 0px;
+            box-sizing: border-box;
+            margin-top: 0px;
+            margin-bottom: 0px;
+            margin-left: 0px;
+        }
+
+        .ms-console .ms-console-right .ms-other .ms-panel .ms-panel-body .qq-item {
+            width: 50%;
+            height: 100px;
+            min-height: 50px;
+            display: flex;
+            flex-direction: row;
+            flex-shrink: 0;
+            flex-wrap: nowrap;
+            justify-content: flex-start;
+            align-items: center;
+            margin-bottom: 0px;
+            box-sizing: border-box;
+            margin-left: 0px;
+            padding-right: 0px;
+            padding-left: 0px;
+            margin-right: 0px;
+        }
+
+        .ms-console .ms-console-right .ms-other .ms-panel .ms-panel-body .qq-item .qq-icon {
+            width: 35px;
+            height: 39px;
+            margin-left: 4px;
+            vertical-align: top;
+            margin-right: 4px;
+            padding-right: 0px;
+            padding-left: 0px;
+        }
+
+        .ms-console .ms-console-right .ms-other .ms-panel .ms-panel-body .qq-item .qq-text {
+            width: unset;
+            height: unset;
+            min-height: 50px;
+            display: flex;
+            flex-direction: column;
+            flex-shrink: 0;
+            flex-wrap: nowrap;
+            box-sizing: border-box;
+            justify-content: center;
+            align-items: flex-start;
+            margin-right: 0px;
+            margin-left: 0px;
+        }
+
+        .ms-console .ms-console-right .ms-other .ms-panel .ms-panel-body .qq-item .qq-text .qq-text-name {
+            flex-direction: row;
+            display: inline-block;
+            word-wrap: break-word;
+            font-size: 12PX;
+            color: #999999;
+            margin-left: 0px;
+        }
+
+        .ms-console .ms-console-right .ms-other .ms-panel .ms-panel-body .qq-item .qq-text .qq-text-no {
+            flex-direction: row;
+            display: inline-block;
+            word-wrap: break-word;
+            line-height: 1.4;
+            font-size: 20PX;
+            font-weight: 600;
+            color: #333333;
+            margin-left: 0px;
+        }
+
+        .ms-console .ms-console-right .ms-other .version-link {
+            width: 98%;
+            height: unset;
+            margin-left: 0px;
+            padding-right: 0px;
+            padding-left: 0px;
+            vertical-align: top;
+            margin-top: 0px;
+            margin-bottom: 0px;
+        }
+
+        .ms-console .ms-console-right .ms-other .version-link img {
+            width: 100%;
+            height: unset;
+            margin-left: 0px;
+            padding-right: 0px;
+            padding-left: 0px;
+            vertical-align: top;
+            margin-top: 0px;
+            margin-bottom: 0px;
+            padding-bottom: 0px;
+        }
+
+
+    }
+</style>

+ 268 - 0
src/main/webapp/WEB-INF/manager/people/people-log/form.ftl

@@ -0,0 +1,268 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+    <title>会员日志</title>
+    <#include "../../include/head-file.ftl">
+
+</head>
+
+<body>
+<div id="form" v-loading="loading" v-cloak>
+    <el-header class="ms-header ms-tr" height="50px">
+        <el-button size="default" class="iconfont icon-fanhui" plain @click="back()">返回</el-button>
+    </el-header>
+    <el-main class="ms-container">
+        <el-form ref="form" :model="form" label-width="120px" label-position="right" size="small">
+
+            <el-row
+                    :gutter=0
+                    justify="start" align="top">
+                <el-col :span=12>
+                    <!--标题-->
+                    <el-form-item label="标题" prop="logTitle">
+                        <el-input
+                                v-model="form.logTitle"
+                                :disabled="true"
+                                :style="{width:  '100%'}"
+                                :clearable="true"
+                                placeholder="请输入标题">
+                        </el-input>
+                    </el-form-item>
+                </el-col>
+                <el-col :span=12>
+                    <!--会员编号-->
+                    <el-form-item label="会员编号" prop="peopleId">
+                        <el-input
+                                v-model="form.peopleId"
+                                :disabled="true"
+                                :readonly="true"
+                                :style="{width:  '100%'}"
+                                :clearable="true"
+                                placeholder="请输入会员编号">
+                        </el-input>
+                    </el-form-item>
+                </el-col>
+            </el-row>
+            <el-row
+                    :gutter=0
+                    justify="start" align="top">
+                <el-col :span=12>
+                    <!--IP-->
+                    <el-form-item label="IP" prop="logIp">
+                        <el-input
+                                v-model="form.logIp"
+                                :disabled="true"
+                                :style="{width:  '100%'}"
+                                :clearable="false"
+                                placeholder="请输入IP">
+                        </el-input>
+                    </el-form-item>
+                </el-col>
+                <el-col :span=12>
+                    <!--所在地区-->
+                    <el-form-item label="所在地区" prop="logAddr">
+                        <el-input
+                                v-model="form.logAddr"
+                                :disabled="true"
+                                :style="{width:  '100%'}"
+                                :clearable="false"
+                                placeholder="请输入所在地区">
+                        </el-input>
+                    </el-form-item>
+                </el-col>
+            </el-row>
+            <el-row
+                    :gutter=0
+                    justify="start" align="top">
+                <el-col :span=12>
+                    <!--日志类型-->
+                    <el-form-item label="日志类型" prop="logType">
+                        <el-select v-model="form.logType"
+                                   :style="{width: '100%'}"
+                                   :filterable="true"
+                                   :disabled="true"
+                                   :multiple="false" :clearable="false"
+                                   placeholder="请选择日志类型">
+                            <el-option v-for='item in logTypeOptions' :key="item.value" :value="item.value"
+                                       :label="item.label"></el-option>
+                        </el-select>
+                    </el-form-item>
+
+                </el-col>
+                <el-col :span=12>
+                    <!--日志状态-->
+                    <el-form-item label="日志状态" prop="logStatus">
+                        <el-select v-model="form.logStatus"
+                                   :style="{width: '100%'}"
+                                   :filterable="false"
+                                   :disabled="true"
+                                   :multiple="false" :clearable="true"
+                                   placeholder="请选择日志状态">
+                            <el-option v-for='item in logStatusOptions' :key="item.value" :value="item.value"
+                                       :label="item.label"></el-option>
+                        </el-select>
+                    </el-form-item>
+
+                </el-col>
+            </el-row>
+            <el-row
+                    :gutter=0
+                    justify="start" align="top">
+                <el-col :span=12>
+                    <el-form-item label="创建时间" prop="createDate">
+                        <el-input
+                                v-model="form.createDate"
+                                :disabled="true"
+                                :style="{width:  '100%'}"
+                                :clearable="false"
+                                placeholder="请输入创建时间">
+                        </el-input>
+                    </el-form-item>
+                </el-col>
+                <el-col :span=12>
+                </el-col>
+            </el-row>
+            <el-row
+                    :gutter=0
+                    justify="start" align="top">
+                <el-col :span=12>
+                    <!--请求参数-->
+                    <el-form-item label="请求参数" prop="logParam">
+                        <el-input
+                                type="textarea" :rows="5"
+                                :disabled="true"
+                                v-model="form.logParam"
+                                :style="{width: '100%'}"
+                                placeholder="请输入请求参数">
+                        </el-input>
+                    </el-form-item>
+
+                </el-col>
+                <el-col :span=12>
+                    <!--返回参数-->
+                    <el-form-item label="返回参数" prop="logResult">
+                        <el-input
+                                type="textarea" :rows="5"
+                                :disabled="true"
+                                v-model="form.logResult"
+                                :style="{width: '100%'}"
+                                placeholder="请输入返回参数">
+                        </el-input>
+                    </el-form-item>
+
+                </el-col>
+            </el-row>
+            <!--日志信息-->
+            <el-form-item label="日志信息" prop="logInfo">
+                <el-input
+                        type="textarea" :rows="5"
+                        :disabled="true"
+                        :readonly="true"
+                        v-model="form.logInfo"
+                        :style="{width: '100%'}"
+                        placeholder="请输入日志信息">
+                </el-input>
+                <div class="ms-form-tip">
+                    日志信息,存储登录的浏览器信息或者换绑邮箱的信息等
+                </div>
+            </el-form-item>
+
+            <!--错误消息-->
+            <el-form-item label="错误消息" prop="logErrorMsg">
+                <el-input
+                        type="textarea" :rows="5"
+                        :disabled="true"
+                        v-model="form.logErrorMsg"
+                        :style="{width: '100%'}"
+                        placeholder="请输入错误消息">
+                </el-input>
+            </el-form-item>
+
+        </el-form>
+    </el-main>
+</div>
+</body>
+
+</html>
+
+<script>
+    var formVue = new _Vue({
+        el: '#form',
+        data: function () {
+            return {
+                loading: false,
+                saveDisabled: false,
+                // 日志类型
+                logTypeOptions: [],
+                logStatusOptions:[{"value":"success","label":"成功"},{"value":"error","label":"失败"}],
+                //表单数据
+                form: {
+                    // 标题
+                    logTitle: '',
+                    // 会员编号
+                    peopleId:'',
+                    // IP
+                    logIp:'',
+                    // 所在地区
+                    logAddr:'',
+                    // 日志类型
+                    logType:"",
+                    // 日志状态
+                    logStatus:"",
+                    // 请求参数
+                    logParam:'',
+                    // 返回参数
+                    logResult:'',
+                    // 日志信息
+                    logInfo:'',
+                    // 错误消息
+                    logErrorMsg:'',
+                },
+            }
+        },
+        watch: {},
+        components: {},
+        computed: {},
+        methods: {
+            back: function (){
+                ms.util.openSystemUrl("/people/peopleLog/index.do",true);
+            },
+            //获取当前会员日志
+            get: function (id) {
+                var that = this;
+                this.loading = true
+                ms.http.get(ms.manager + "/people/peopleLog/get.do", {"id": id}).then(function (res) {
+                    that.loading = false
+                    if (res.result && res.data) {
+                        that.form = res.data;
+                    }
+                });
+            },
+
+            //获取logType数据源
+            logTypeOptionsGet: function () {
+                var that = this;
+                ms.http.post(ms.manager + '/people/peopleLog/queryLogType.do').then(function (res) {
+                    that.logTypeOptions = res.data;
+                }).catch(function (err) {
+                    console.log(err);
+                });
+            },
+
+
+        },
+        created: function () {
+            //加载日志类型 数据
+            this.logTypeOptionsGet();
+
+            this.form.id = ms.util.getParameter("id");
+            if (this.form.id) {
+                this.get(this.form.id);
+            }
+        }
+    });
+
+</script>
+<style>
+</style>

+ 284 - 0
src/main/webapp/WEB-INF/manager/people/people-log/index.ftl

@@ -0,0 +1,284 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <title>会员日志</title>
+    <#include "../../include/head-file.ftl">
+</head>
+<body>
+<div id="index" class="ms-index" v-cloak>
+    <div class="ms-search">
+        <el-row>
+            <el-form :model="form" ref="searchForm" label-width="120px" size="default">
+                <el-row>
+                    <el-col :span=8>
+                        <!--会员编号-->
+                        <el-form-item label="会员编号" prop="peopleId">
+                            <el-input
+                                    v-model="form.peopleId"
+                                    :style="{width:  '100%'}"
+                                    :clearable="true"
+                                    placeholder="请输入会员编号">
+                            </el-input>
+                        </el-form-item>
+                    </el-col>
+                    <el-col :span=8>
+                        <!--会员编号-->
+                        <el-form-item label="标题" prop="logTitle">
+                            <el-input
+                                    v-model="form.logTitle"
+                                    :style="{width:  '100%'}"
+                                    :clearable="true"
+                                    placeholder="请输入标题">
+                            </el-input>
+                        </el-form-item>
+                    </el-col>
+                    <el-col :span=8>
+                        <!--日志类型-->
+                        <el-form-item label="日志类型" prop="logType">
+                            <el-select v-model="form.logType"
+                                       :style="{width: '100%'}"
+                                       :filterable="true"
+                                       :disabled="false"
+                                       :multiple="false" :clearable="true"
+                                       placeholder="请选择日志类型">
+                                <el-option v-for='item in logTypeOptions' :key="item" :value="item.value"
+                                           :label="item.label"></el-option>
+                            </el-select>
+                        </el-form-item>
+                    </el-col>
+                </el-row>
+                <el-row>
+                    <el-col :span=8>
+                        <!--日志类型-->
+                        <el-form-item label="请求状态" prop="logStatus">
+                            <el-select v-model="form.logStatus"
+                                       :style="{width: '100%'}"
+                                       :filterable="false"
+                                       :multiple="false" :clearable="true"
+                                       placeholder="请选择请求状态">
+                                <el-option v-for='item in logStatusOptions' :key="item.value" :value="item.value"
+                                           :label="item.label"></el-option>
+                            </el-select>
+                        </el-form-item>
+                    </el-col>
+                    <el-col :span=8>
+                        <el-form-item label="创建时间" prop="createDateScope">
+                            <el-date-picker
+                                    v-model="form.createDateScope"
+                                    value-format="YYYY-MM-DD HH:mm:ss"
+                                    format="YYYY-MM-DD HH:mm:ss"
+                                    type="datetimerange"
+                                    :style="{width:  '100%'}"
+                                    start-placeholder="开始时间"
+                                    end-placeholder="结束时间">
+                            </el-date-picker>
+                        </el-form-item>
+                    </el-col>
+                    <el-col :span=8 style="text-align: right;">
+                        <el-button type="primary" class="el-icon-search" size="default" @click="currentPage=1;list(true)">
+                            搜索
+                        </el-button>
+                        <el-button @click="rest" class="el-icon-refresh" size="default">重置</el-button>
+                    </el-col>
+                </el-row>
+            </el-form>
+        </el-row>
+    </div>
+    <el-main class="ms-container">
+        <el-table height="calc(100vh - 68px)" v-loading="loading" ref="multipleTable" border :data="dataList"
+                  tooltip-effect="dark" @selection-change="handleSelectionChange">
+            <template #empty>
+                {{emptyText}}
+            </template>
+            <el-table-column type="selection" width="40" :selectable="isChecked"></el-table-column>
+            <el-table-column label="标题" align="left" prop="logTitle">
+            </el-table-column>
+            <el-table-column label="会员编号" align="left" prop="peopleId">
+            </el-table-column>
+            <el-table-column label="IP" align="left" prop="logIp">
+            </el-table-column>
+            <el-table-column label="所在地区" align="left" prop="logAddr">
+            </el-table-column>
+            <el-table-column label="请求状态" width="80" align="center" prop="logStatus" :formatter="logStatusFormat">
+            </el-table-column>
+            <el-table-column label="创建时间" align="center" prop="createDate">
+            </el-table-column>
+            <el-table-column label="操作" width="180" align="center">
+                <template #default="scope">
+                        <el-link type="primary" :underline="false" @click="save(scope.row.id)">详情</el-link>
+                </template>
+            </el-table-column>
+        </el-table>
+        <el-pagination
+                background
+                :page-sizes="[50,100,200,500]"
+                layout="total, sizes, prev, pager, next, jumper"
+                :current-page="currentPage"
+                :page-size="pageSize"
+                :total="total"
+                class="ms-pagination"
+                @current-change='currentChange'
+                @size-change="sizeChange">
+        </el-pagination>
+    </el-main>
+</div>
+</body>
+
+</html>
+<script>
+    var indexVue = new _Vue({
+        el: '#index',
+        data: function (){
+            return{
+                logStatusOptions: [{"value": "success", "label": "成功"}, {"value": "error", "label": "失败"}],
+                dataList: [], //会员日志列表
+                selectionList: [],//会员日志列表选中
+                total: 0, //总记录数量
+                pageSize: 50, //页面数量
+                currentPage: 1, //初始页
+                manager: ms.manager,
+                loading: true,//加载状态
+                emptyText: '',//提示文字
+                // 日志类型
+                logTypeOptions: [],
+                //搜索表单
+                form: {
+                    sqlWhere: null,
+                    logStatus: null,
+                    createDateScope: null,
+                },
+            }
+        },
+        watch: {},
+        methods: {
+            isChecked: function (row) {
+                if (row.del == 3) {
+                    return false;
+                }
+                return true;
+            },
+            //查询列表
+            list: function (isSearch) {
+                var that = this;
+                var data = {}; //搜索参数
+                that.loading = true;
+                var page = {
+                    pageNo: that.currentPage,
+                    pageSize: that.pageSize
+                }
+                var form = JSON.parse(JSON.stringify(that.form))
+
+                //处理时间范围
+                if (form.createDateScope) {
+                    form.startTime = form.createDateScope[0];
+                    form.endTime = form.createDateScope[1];
+                }
+
+                if (isSearch) {
+                    //删除空字符串
+                    for (var key in form) {
+                        if (form[key] === undefined || form[key] === null) {
+                            delete form[key]
+                        }
+                    }
+                    form.sqlWhere ? data = Object.assign({}, {sqlWhere: form.sqlWhere}, page) : data = Object.assign({}, form, page)
+                } else {
+                    data = page;
+                }
+
+                sessionStorage.setItem(this.historyKey,JSON.stringify({form: form, page: page}));
+                ms.http.post(ms.manager + "/people/peopleLog/list.do", data).then(
+                    function (res) {
+                        if (!res.result || res.data.total <= 0) {
+                            that.emptyText = "暂无数据"
+                            that.dataList = [];
+                            that.total = 0;
+                        } else {
+                            that.emptyText = '';
+                            that.total = res.data.total;
+                            that.dataList = res.data.rows;
+                        }
+                        that.loading = false;
+                    }).catch(function (err) {
+                    that.loading = false;
+                    console.log(err);
+                });
+
+            },
+            //会员日志列表选中
+            handleSelectionChange: function (val) {
+                this.selectionList = val;
+            },
+            //新增
+            save: function (id) {
+                if (id) {
+                    ms.util.openSystemUrl("/people/peopleLog/form.do?id=" + id);
+                }
+            },
+
+            //pageSize改变时会触发
+            sizeChange: function (pagesize) {
+                this.loading = true;
+                this.pageSize = pagesize;
+                this.list(true);
+            },
+            //currentPage改变时会触发
+            currentChange: function (currentPage) {
+                this.loading = true;
+                this.currentPage = currentPage;
+                this.list(true);
+            },
+            //重置表单
+            rest: function () {
+                this.currentPage = 1;
+                this.form = {
+                    sqlWhere: null
+                };
+                this.list();
+            },
+            //表格数据转换
+            logStatusFormat: function (row, column, cellValue, index) {
+                var value = "";
+                if (cellValue) {
+                    var data = this.logStatusOptions.find(function (value) {
+                        return value.value == cellValue;
+                    })
+                    if (data && data.label) {
+                        value = data.label;
+                    }
+                }
+                return value;
+            },
+            //获取logType数据源
+            logTypeOptionsGet: function () {
+                var that = this;
+                ms.http.post(ms.manager + '/people/peopleLog/queryLogType.do').then(function (res) {
+                    that.logTypeOptions = res.data;
+                }).catch(function (err) {
+                    console.log(err);
+                });
+            },
+
+        },
+        mounted: function () {
+            //加载日志类型 数据
+            this.logTypeOptionsGet();
+
+            //如果存在历史参数,恢复页面结果
+            if(sessionStorage.getItem(this.historyKey) && ms.util.getParameter("isBack") == 'true') {
+                var _history = JSON.parse(sessionStorage.getItem(this.historyKey))
+                this.form = _history.form;
+                this.total = _history.total;
+                this.currentPage = _history.page.pageNo;
+                this.pageSize = _history.page.pageSize;
+            }
+
+            this.list();
+        },
+    })
+</script>
+<style>
+    #index .ms-container {
+        height: calc(100vh - 141px);
+    }
+</style>

+ 369 - 0
src/main/webapp/WEB-INF/manager/people/people-user/audit.ftl

@@ -0,0 +1,369 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <title>用户</title>
+    <#include "../../include/head-file.ftl">
+</head>
+<body>
+<div id="index" v-cloak class="ms-index">
+    <div class="ms-search" style="padding: 20px 10px 20px 10px;">
+        <el-row>
+            <el-form :model="form" ref="searchForm" :rules="rules" label-width="80px" size="default">
+                <el-row>
+                    <el-col :span=8>
+                        <el-form-item label="账号" prop="peopleName">
+                            <el-input v-model="form.peopleName"
+                                      :disabled="false"
+                                      :style="{width:  '100%'}"
+                                      :clearable="true"
+                                      placeholder="请输入账号">
+                            </el-input>
+                        </el-form-item>
+                    </el-col>
+                    <el-col :span=8>
+                        <el-form-item label="昵称" prop="puNickname">
+                            <el-input v-model="form.puNickname"
+                                      :disabled="false"
+                                      :style="{width:  '100%'}"
+                                      :clearable="true"
+                                      placeholder="请输入昵称">
+                            </el-input>
+                        </el-form-item>
+                    </el-col>
+                    <el-col :span=8>
+                        <el-form-item label="真实姓名" prop="puRealName">
+                            <el-input v-model="form.puRealName"
+                                      :disabled="false"
+                                      :style="{width:  '100%'}"
+                                      :clearable="true"
+                                      placeholder="请输入真实姓名">
+                            </el-input>
+                        </el-form-item>
+                    </el-col>
+                </el-row>
+                <el-row>
+                    <el-col :span=8>
+                        <el-form-item label="手机号码" prop="peoplePhone">
+                            <el-input v-model="form.peoplePhone"
+                                      :disabled="false"
+                                      :style="{width:  '100%'}"
+                                      :clearable="true"
+                                      placeholder="请输入手机号码">
+                            </el-input>
+                        </el-form-item>
+                    </el-col>
+                    <el-col :span=8>
+                        <el-form-item label="邮箱" prop="peopleMail">
+                            <el-input v-model="form.peopleMail"
+                                      :disabled="false"
+                                      :style="{width:  '100%'}"
+                                      :clearable="true"
+                                      placeholder="请输入邮箱">
+                            </el-input>
+                        </el-form-item>
+                    </el-col>
+                    <el-col :span=8>
+                        <el-form-item label="注册时间" prop="peopleDateTimes">
+                            <el-date-picker
+                                    v-model="peopleDateTimes"
+                                    value-format="YYYY-MM-DD HH:mm:ss"
+                                    format="YYYY-MM-DD"
+                                    type="daterange"
+                                    :style="{width:  '100%'}"
+                                    start-placeholder="开始日期"
+                                    end-placeholder="结束日期">
+                            </el-date-picker>
+                        </el-form-item>
+                    </el-col>
+                </el-row>
+                <el-row>
+                    <el-col :span=8>
+                        <el-form-item label="用户ID" prop="peopleId">
+                            <el-input v-model="form.peopleId"
+                                      :disabled="false"
+                                      :style="{width:  '100%'}"
+                                      :clearable="true"
+                                      placeholder="请输入用户ID">
+                            </el-input>
+                        </el-form-item>
+                    </el-col>
+                    <el-col :span=16  style="text-align:right;">
+                        <el-button type="primary" class="el-icon-search" size="default" @click="loading=true;currentPage=1;list()">查询
+                        </el-button>
+                        <el-button @click="rest" class="el-icon-refresh" size="default">重置</el-button>
+                    </el-col>
+                </el-row>
+            </el-form>
+        </el-row>
+    </div>
+    <el-main class="ms-container">
+        <el-table v-loading="loading" ref="multipleTable" height="calc(100vh-68px)" class="ms-table-pagination" border :data="treeList"
+                  tooltip-effect="dark" @selection-change="handleSelectionChange">
+            <template #empty>
+                {{emptyText}}
+            </template>
+            <el-table-column type="selection" width="40"></el-table-column>
+            <el-table-column label="ID" align="center" prop="id">
+            </el-table-column>
+            <el-table-column width="80" label="头像" align="center">
+                <template #default="scope">
+                    <el-image v-if="scope.row.puIcon !=null" :src="scope.row.puIcon" style="width: 50px;height: 50px;line-height: 50px;font-size: 50px">
+                        <template #error>
+                            <div class="image-slot">
+                                <i class="el-icon-picture-outline"></i>
+                            </div>
+                        </template>
+                    </el-image>
+                </template>
+            </el-table-column>
+            <el-table-column label="账号" align="left" prop="peopleName">
+            </el-table-column>
+            <el-table-column label="真实姓名" align="left" prop="puRealName">
+            </el-table-column>
+            <el-table-column label="昵称" align="left" prop="puNickname">
+            </el-table-column>
+            <el-table-column label="手机号码" width="130" align="center" prop="peoplePhone">
+            </el-table-column>
+            <el-table-column label="邮箱"  width="200" align="center" prop="peopleMail">
+            </el-table-column>
+            <el-table-column label="注册时间" width="180" align="center" prop="peopleDateTime">
+            </el-table-column>
+            <el-table-column label="用户状态" width="100" align="center" prop="peopleState">
+                <template #default="scope">
+                    {{scope.row.peopleState==0?'未审':'已审'}}
+                </template>
+            </el-table-column>
+            <@shiro.hasPermission name="people:user:update">
+                <el-table-column label="操作" width="180px" align="center">
+                    <template #default="scope">
+                        <@shiro.hasPermission name="people:user:update">
+                            <el-link :underline="false" type="primary" @click="save(scope.row.id)">编辑</el-link>
+                        </@shiro.hasPermission>
+                        <@shiro.hasPermission name="people:user:check">
+                        <el-link :underline="false" type="primary" @click="updateUserState(scope.row)">审核
+                        </el-link>
+                        </@shiro.hasPermission>
+                    </template>
+                </el-table-column>
+            </@shiro.hasPermission>
+        </el-table>
+        <el-pagination
+                background
+                :page-sizes="[10, 50, 100]"
+                layout="total, sizes, prev, pager, next, jumper"
+                :current-page="currentPage"
+                :page-size="pageSize"
+                :total="total"
+                class="ms-pagination"
+                @current-change='currentChange'
+                @size-change="sizeChange">
+        </el-pagination>
+    </el-main>
+</div>
+</body>
+
+</html>
+<script>
+    var indexVue = new _Vue({
+        el: '#index',
+        data: function (){
+            return {
+                treeList: [],
+                //用户列表
+                selectionList: [],
+                //用户列表选中
+                loading: true,
+                emptyText: '',
+                total: 0,
+                //总记录数量
+                pageSize: 10,
+                //页面数量
+                currentPage: 1,
+                //初始页
+                mananger: ms.manager,
+                //搜索表单
+                form: {
+                    // id
+                    id: '',
+                    // 用户名
+                    peopleName: '',
+                    // 密码
+                    peoplePassword: '',
+                    // 昵称
+                    puNickname: '',
+                    // 性别
+                    puSex: '',
+                    // 真实姓名
+                    puRealName: '',
+                    // 身份证
+                    puCard: '',
+                    // 手机号码
+                    peoplePhone: '',
+                    // 邮箱
+                    peopleMail: '',
+                    // 头像
+                    // 地址
+                    puAddress: ''
+                },
+                peopleDateTimes: null,
+                puSexOptions: [{
+                    "value": 1,
+                    "label": "男"
+                }, {
+                    "value": 2,
+                    "label": "女"
+                }],
+                peopleStateOptions: [{
+                    "value": 0,
+                    "label": "未审"
+                }, {
+                    "value": 1,
+                    "label": "已审"
+                }],
+                rules: {peopleId: [{max: 20, message: '长度不能超过20位', trigger: 'blur'}]},
+                historyKey: "people_people_user_audit_history"
+            }
+        },
+        methods: {
+            //查询列表
+            list: function () {
+                var that = this;
+                var page = {
+                    pageNo: that.currentPage,
+                    pageSize: that.pageSize
+                };
+                var form = JSON.parse(JSON.stringify(that.form));
+
+                if (that.peopleDateTimes) {
+                    form.peopleDateTimes = that.peopleDateTimes[0] + '至' + that.peopleDateTimes[1];
+                } else {
+                    form.peopleDateTimes = null;
+                }
+
+                for (var key in form) {
+                    if (!form[key]) {
+                        delete form[key];
+                    }
+                }
+
+                sessionStorage.setItem(this.historyKey, JSON.stringify({form: form, page: page}));
+
+                that.$refs.searchForm.validate(function (valid) {
+                    if (valid) {
+                        setTimeout(function () {
+                            ms.http.get(ms.manager + "/people/peopleUser/unAuditList.do", Object.assign({}, form, page))
+                                .then(function (data) {
+                                    if (data.result) {
+                                        if (data.data.total <= 0) {
+                                            that.loading = false;
+                                            that.emptyText = '暂无数据';
+                                            that.treeList = [];
+                                        } else {
+                                            that.emptyText = '';
+                                            that.loading = false;
+                                            that.total = data.data.total;
+                                            that.treeList = data.data.rows;
+                                            that.treeList.forEach(function (item) {
+                                                if (item.puIcon == null && item.puIcon == "") {
+                                                    item.puIcon = null;
+                                                }
+                                                if(!item.puIcon.startsWith("http://") && !item.puIcon.startsWith("https://")) {
+                                                    item.puIcon = ms.contextpath + item.puIcon;
+                                                }
+                                            });
+                                        }
+                                    }
+                                }).catch(function (err) {
+                                that.$notify({
+                                    type: 'warning',
+                                    msg: err.msg,
+                                    title: '失败'
+                                })
+                                that.loading = false;
+
+                                // console.log(err);
+                            });
+                        }, 500);
+                    } else {
+                        that.loading = false;
+                    }
+                })
+
+            },
+            //用户列表选中
+            handleSelectionChange: function (val) {
+                this.selectionList = val;
+            },
+
+            //更新用户审核状态
+            updateUserState: function (row) {
+                var that = this;
+                that.$confirm('此操作将审核用户, 是否继续?', '提示', {
+                    confirmButtonText: '确定',
+                    cancelButtonText: '取消',
+                    type: 'warning'
+                }).then(function () {
+                    ms.http.post(ms.manager + "/people/updateState.do", row.length ? row : [row], {
+                        headers: {
+                            'Content-Type': 'application/json'
+                        }
+                    }).then(function (data) {
+                        if (data.result) {
+                            that.$notify({
+                                title:'成功',
+                                type: 'success',
+                                message: '审核成功!'
+                            }); //审核成功,刷新列表
+
+                            that.list();
+                        }
+                    });
+                });
+            },
+            //新增
+            save: function (id) {
+                if (id) {
+                    ms.util.openSystemUrl("/people/peopleUser/form.do?peopleId=" + id+"&backUrl="+encodeURIComponent("/people/peopleUser/audit.do"));
+                } else {
+                    ms.util.openSystemUrl("/people/peopleUser/form.do");
+                }
+            },
+            //pageSize改变时会触发
+            sizeChange: function (pagesize) {
+                this.loading = true;
+                this.pageSize = pagesize;
+                this.list();
+            },
+            //currentPage改变时会触发
+            currentChange: function (currentPage) {
+                this.loading = true;
+                this.currentPage = currentPage;
+                this.list();
+            },
+            //重置表单
+            rest: function () {
+                this.currentPage = 1;
+                this.loading = true;
+                this.$refs.searchForm.resetFields();
+                this.peopleDateTimes = null;
+                this.list();
+            }
+        },
+        mounted: function () {
+            //如果存在历史参数,恢复页面结果
+            if(sessionStorage.getItem(this.historyKey) && ms.util.getParameter("isBack") == 'true') {
+                var _history = JSON.parse(sessionStorage.getItem(this.historyKey))
+                this.form = _history.form;
+                this.total = parseInt(_history.total);
+                this.currentPage = parseInt(_history.page.pageNo);
+                this.pageSize = parseInt(_history.page.pageSize);
+            }
+            this.list();
+        }
+    });
+</script>
+<style>
+    #index .ms-search {
+        padding: 20px 0;
+    }
+</style>

+ 686 - 0
src/main/webapp/WEB-INF/manager/people/people-user/form.ftl

@@ -0,0 +1,686 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <title>用户</title>
+    <#include "../../include/head-file.ftl">
+</head>
+<body>
+<div id="form" v-cloak>
+    <el-header class="ms-header ms-tr" height="50px">
+        <el-button type="primary" class="iconfont icon-baocun" size="default" @click="save()" :loading="saveDisabled">保存
+        </el-button>
+        <el-button size="default" plain @click="back()"><i class="iconfont icon-fanhui"></i>返回
+        </el-button>
+    </el-header>
+    <el-main class="ms-container" style="position:relative;">
+        <el-scrollbar style="height: calc(100vh - 50px)">
+            <el-tabs v-model="activeName" style="height: calc(100% - 10px);">
+
+                <el-tab-pane label="基本信息" name="基本信息">
+                    <el-form  ref="form" :model="form" :rules="rules" label-width="100px" size="default">
+                        <el-main class="ms-container ms-margin-bottom-zero">
+                            <el-row
+                                    :gutter=0
+                                    justify="start" align="top">
+                                <el-col :span=12>
+                                    <el-form-item label="账号" prop="peopleName">
+                                        <el-input v-model="form.peopleName"
+                                                  :disabled="false"
+                                                  :style="{width:  '100%'}"
+                                                  :clearable="true"
+                                                  placeholder="请输入账号">
+                                        </el-input>
+                                    </el-form-item>
+                                </el-col>
+                                <el-col :span=12>
+                                    <el-form-item label="密码" prop="peoplePassword">
+                                        <el-input v-model="form.peoplePassword"
+                                                  type="password"
+                                                  autocomplete='new-password'
+                                                  :disabled="false"
+                                                  :style="{width:  '100%'}"
+                                                  :clearable="true"
+                                                  placeholder="请输入密码">
+                                        </el-input>
+                                    </el-form-item>
+                                </el-col>
+                            </el-row>
+                            <el-row
+                                    :gutter=0
+                                    justify="start" align="top">
+                                <el-col :span=12>
+                                    <el-form-item label="手机号码" prop="peoplePhone">
+                                        <el-input v-model="form.peoplePhone"
+                                                  :disabled="false"
+                                                  :style="{width:  '100%'}"
+                                                  :clearable="true"
+                                                  placeholder="请输入手机号码">
+                                        </el-input>
+                                    </el-form-item>
+                                </el-col>
+                                <el-col :span=12>
+                                    <el-form-item label="手机绑定" prop="peoplePhoneCheck">
+                                        <el-switch v-model="form.peoplePhoneCheck"
+                                                   :active-value="1"
+                                                   :inactive-value="0"
+                                                   :disabled="false">
+                                        </el-switch>
+                                        <div class="ms-form-tip">手机号绑定可以用来登录</div>
+                                    </el-form-item>
+                                </el-col>
+                            </el-row>
+                            <el-row
+                                    :gutter=0
+                                    justify="start" align="top">
+                                <el-col :span=12>
+                                    <el-form-item label="邮箱" prop="peopleMail">
+                                        <el-input v-model="form.peopleMail"
+                                                  :disabled="false"
+                                                  :style="{width:  '100%'}"
+                                                  :clearable="true"
+                                                  placeholder="请输入邮箱">
+                                        </el-input>
+                                    </el-form-item>
+                                </el-col>
+                                <el-col :span=12>
+                                    <el-form-item label="邮箱绑定" prop="peopleMailCheck">
+                                        <el-switch v-model="form.peopleMailCheck"
+                                                   :active-value="1"
+                                                   :inactive-value="0"
+                                                   :disabled="false">
+                                        </el-switch><div class="ms-form-tip">邮箱绑定可以用来登录,未绑定则不能通过邮箱登录</div>
+                                    </el-form-item>
+                                </el-col>
+                            </el-row>
+                            <el-row
+                                    :gutter=0
+                                    justify="start" align="top">
+                                <el-col :span=12>
+                                    <el-form-item label="昵称" prop="puNickname">
+                                        <el-input v-model="form.puNickname"
+                                                  :disabled="false"
+                                                  :style="{width:  '100%'}"
+                                                  :clearable="true"
+                                                  placeholder="请输入昵称">
+                                        </el-input>
+                                    </el-form-item>
+                                </el-col>
+                                <el-col :span=12>
+                                    <el-form-item label="性别" prop="puSex">
+                                        <el-select v-model="form.puSex"
+                                                   :style="{width: '100%'}"
+                                                   :disabled="false"
+                                                   :multiple="false" :clearable="true"
+                                                   placeholder="请选择性别">
+                                            <el-option v-for='item in puSexOptions' :key="item.value"
+                                                       :value="item.value"
+                                                       :label="item.label"
+                                                       ></el-option>
+                                        </el-select>
+                                    </el-form-item>
+                                </el-col>
+                            </el-row>
+                        </el-main>
+                    </el-form>
+                </el-tab-pane>
+
+                <el-tab-pane label="详细信息" name="详细信息">
+                    <el-form  ref="form-more" :model="form"  label-width="100px" size="default">
+                        <el-main class="ms-container ms-margin-bottom-zero">
+
+                            <el-row
+                                    :gutter=0
+                                    justify="start" align="top">
+                                <el-col :span=12>
+                                    <el-form-item label="真实姓名" prop="puRealName">
+                                        <el-input v-model="form.puRealName"
+                                                  :disabled="false"
+                                                  :style="{width:  '100%'}"
+                                                  :clearable="true"
+                                                  placeholder="请输入真实姓名">
+                                        </el-input>
+                                    </el-form-item>
+                                </el-col>
+                                <el-col :span=12>
+                                    <el-form-item label="身份证" prop="puCard">
+                                        <el-input v-model="form.puCard"
+                                                  :disabled="false"
+                                                  :style="{width:  '100%'}"
+                                                  :clearable="true"
+                                                  placeholder="请输入身份证">
+                                        </el-input>
+                                    </el-form-item>
+                                </el-col>
+                            </el-row>
+                            <el-row
+                                    :gutter=0
+                                    justify="start" align="top">
+                                <el-col :span=12>
+                                    <el-form-item label="生日" prop="puBirthday">
+                                        <el-date-picker
+                                                v-model="form.puBirthday"
+                                                placeholder="请选择用户生日"
+                                                :readonly="false"
+                                                :disabled="false"
+                                                :editable="true"
+                                                :clearable="true"
+                                                format="YYYY-MM-DD"
+                                                value-format="YYYY-MM-DD"
+                                                :style="{width:'100%'}"
+                                                type="date">
+                                        </el-date-picker>
+                                    </el-form-item>
+                                </el-col>
+
+                                <el-col :span=12>
+                                    <el-form-item label="用户等级" prop="puLevel">
+                                        <template #label>用户等级
+                                        </template>
+                                        <el-select v-model="form.puLevel"
+                                                   @change="puLevelSelectChange"
+                                                   :style="{width: '100%'}"
+                                                   :filterable="false"
+                                                   :disabled="false"
+                                                   :multiple="false" :clearable="true"
+                                                   placeholder="请选择用户等级">
+                                            <el-option v-for='item in puLevelOptions' :key="item.dictValue"
+                                                       :value="item.dictValue"
+                                                       :label="item.dictLabel"></el-option>
+                                        </el-select>
+
+                                        <div class="ms-form-tip">通过 自定义字典 配置,类型为“用户等级类型”</div>
+
+                                    </el-form-item>
+
+                                </el-col>
+                            </el-row>
+
+
+                            <el-form-item label="城市选择" prop="cityValue">
+                                <el-row :gutter=10 justify="start" align="top">
+                                    <el-cascader :key="cityValue"
+                                            ref="cityRef"
+                                            v-model="cityValue"
+                                            :props="cityProps"
+                                            @change="cityHandleChange">
+                                    </el-cascader>
+                                </el-row>
+                            </el-form-item>
+                            <el-form-item label="地址" prop="puAddress">
+                                <el-input
+                                        type="textarea" :rows="5"
+                                        :disabled="false"
+                                        v-model="form.puAddress"
+                                        :style="{width: '100%'}"
+                                        placeholder="请输入地址">
+                                </el-input>
+                            </el-form-item>
+
+                            <el-form-item label="头像" prop="puIcon">
+                                <el-upload
+                                        :file-list="puIcon"
+                                        :action="ms.manager+'/file/upload.do'"
+                                        :on-remove="puIconhandleRemove"
+                                        :style="{width:''}"
+                                        :limit="1"
+                                        :disabled="false"
+                                        :data="{uploadPath:'/people','isRename':true,'appId':true}"
+                                        :on-success="puIconBasicPicSuccess"
+                                        :on-exceed="puIconhandleExceed"
+                                        accept="image/*"
+                                        list-type="picture-card">
+                                    <i class="el-icon-plus"></i>
+                                    <template #tip>
+                                        <div class="el-upload__tip">最多上传1张头像</div>
+                                    </template>
+                                </el-upload>
+                            </el-form-item>
+                        </el-main>
+                    </el-form>
+                </el-tab-pane>
+                <el-tab-pane label="扩展会员信息" name="扩展会员信息">
+                    <div id="peopleUserModel"></div>
+                    <#--id参数必须要字符串-->
+                    <ms-mdiy-form v-if="modelId!=null" ref="modelForm" type="model" :model-id="modelId" :id="form.peopleId+''"></ms-mdiy-form>
+                </el-tab-pane>
+            </el-tabs>
+        </el-scrollbar>
+    </el-main>
+</div>
+</body>
+</html>
+<script>
+    var form = new _Vue({
+        el: '#form',
+        data: function () {
+            return {
+                saveDisabled: false,
+                provinces: [],
+                activeName: '基本信息',
+                // 城市级联数据
+                cityValue:[],
+                cityProps: {
+                    value: "id",
+                    label: "name",
+                    lazy: true,
+                    lazyLoad: this.lazyLoad,
+                },
+                modelName:null,
+                modelId:null,
+                categoryIdOptions: [],
+                //表单数据
+                form: {
+                    // 用户名
+                    peopleName: '',
+                    // 密码
+                    peoplePassword: '',
+                    // 昵称
+                    puNickname: '',
+                    // 性别
+                    puSex: '',
+                    //用户生日
+                    puBirthday: '',
+                    // 真实姓名
+                    puRealName: '',
+                    // 身份证
+                    puCard: '',
+                    // 手机号码
+                    peoplePhone: '',
+                    // 邮箱
+                    peopleMail: '',
+                    // 手机验证
+                    peoplePhoneCheck: '',
+                    // 邮箱验证
+                    peopleMailCheck: '',
+                    // 用户状态
+                    peopleState: '',
+                    // 头像
+                    puIcon: '',
+                    // 城市选择
+                    provinceId: '',
+                    // 省
+                    provinceName: '',
+                    // 城市
+                    cityName: '',
+                    // 区
+                    countyName: '',
+                    // 城市id
+                    cityId: '',
+                    // 区id
+                    countyId: '',
+                    // 地址
+                    puAddress: '',
+                    //用户等级
+                    puLevel: null,
+                    //用户等级名称
+                    puLevelName: null
+                },
+                puIcon: [],
+                puLevelOptions: [],
+                puSexOptions: [{
+                    "value": 1,
+                    "label": "男"
+                }, {
+                    "value": 2,
+                    "label": "女"
+                }],
+                rules: {
+                    // 登录名
+                    peopleName: [{
+                        "required": true,
+                        "message": "登录名不能为空"
+                    }, {"pattern": "^[^[!@#$%^&*()_+-/~?!@#¥%…&*()——+—?》《:“‘’]+$", "message": "登录名格式不匹配"}, {
+                        "min": 6,
+                        "max": 30,
+                        "message": "登录名长度必须为6-30"
+                    }],
+                    // 登录密码
+                    peoplePassword: [{
+                        "pattern": "^[^[!@#$%^&*()_+-/~?!@#¥%…&*()——+—?》《:“‘’]+$", "message": "登录密码格式不匹配"}, {
+                        "min": 6,
+                        "max": 30,
+                        "message": "登录密码长度必须为6-30"
+                    }],
+                    // 昵称
+                    puNickname: [{
+                        "min": 1,
+                        "max": 50,
+                        "message": "昵称长度必须为1-50"
+                    }],
+                    // 真实姓名
+                    puRealName: [{
+                        "min": 1,
+                        "max": 50,
+                        "message": "真实姓名长度必须为1-50"
+                    }],
+                    // 身份证
+                    puCard: [{
+                        "pattern": "^[X0-9]+$",
+                        "message": "身份证格式不匹配"
+                    }, {
+                        "min": 1,
+                        "max": 50,
+                        "message": "身份证长度必须为1-50"
+                    }],
+                    // 手机号码
+                    peoplePhone: [{
+                        "pattern": /^[1][0-9]{10}$/,
+                        "message": "手机号码格式不匹配"
+                    }],
+                    // 邮箱
+                    peopleMail: [{
+                        "pattern": "^([a-z0-9A-Z]+[-|\\.]?)+[a-z0-9A-Z]@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\\.)+[a-zA-Z]{2,}$",
+                        "message": "邮箱格式不匹配"
+                    }, {
+                        "min": 1,
+                        "max": 50,
+                        "message": "邮箱长度必须为1-50"
+                    }]
+                },
+                backUrl: ''
+            };
+        },
+        watch: {
+            // 已经绑定邮箱或手机更新时不必填选用户名
+            "form.peopleMailCheck": function(v) {
+                if (v === 1) {
+                    this.rules.peopleName[0].required = false;
+                    this.rules.peopleMail[0].required = true;
+                }
+            },
+            "form.peoplePhoneCheck": function(v) {
+                if (v === 1) {
+                    this.rules.peopleName[0].required = false;
+                    this.rules.peoplePhone[0].required = true;
+                }
+            },
+        },
+        computed: {
+        },
+        methods: {
+			back: function (){
+			    if (this.backUrl){
+					ms.util.openSystemUrl(decodeURIComponent(this.backUrl));
+                }else {
+					ms.util.openSystemUrl("/people/peopleUser/index.do")
+                }
+            },
+            // 城市数据懒加载方法
+            lazyLoad(node,resolve){
+                var level = node.level;
+                var formData = {};
+                if (node.pathNodes){
+                    var id = node.pathNodes[node.pathNodes.length-1].data.id;
+                    if (level === 1){
+                        formData.provinceId  = id;
+                    }
+                    else  if (level === 2){
+                        formData.cityId  = id;
+                    }
+                }
+                ms.http.get(ms.manager+'/basic/city/list.do',formData).then(function (res){
+                    if (res.result){
+                        if (level === 0){
+                            res.data.forEach(function (item){
+                                item.name = item.provinceName;
+                                item.id = item.provinceId;
+                                // 判断是否是叶子节点
+                                item.leaf = level >= 2
+                            })
+                        }
+                        else if (level === 1){
+                            res.data.forEach(function (item){
+                                item.name = item.cityName;
+                                item.id = item.cityId;
+                                // 判断是否是叶子节点
+                                item.leaf = level >= 2
+                            })
+                        }
+                        else if (level === 2){
+                            res.data.forEach(function (item){
+                                item.name = item.countyName;
+                                item.id = item.countyId;
+                                // 判断是否是叶子节点
+                                item.leaf = level >= 2
+                            })
+                        }
+                        resolve(res.data)
+                    }
+                })
+            },
+            // 处理城市各级别数据保存
+            cityHandleChange:function(value){
+                var labels = this.$refs.cityRef.getCheckedNodes()[0].pathLabels;
+                this.form.provinceId = value[0]
+                this.form.provinceName = labels[0]
+                this.form.cityId = value[1]
+                this.form.cityName = labels[1]
+                this.form.countyId = value[2]
+                this.form.countyName = labels[2]
+            },
+
+            //对象拷贝 用来去除多余额数据
+            objectCopy: function (src, o) {
+                for (var key in src) {
+                    if (o[key] != undefined) {
+                        src[key] = o[key];
+                    }
+                }
+            },
+            async save() {
+                var that = this;
+                var url = ms.manager + "/people/peopleUser/save.do";
+                if (that.form.peopleId > 0) {
+                    url = ms.manager + "/people/peopleUser/update.do";
+                    // 更新的时候不用判断是否填写密码
+                    that.rules.peoplePassword[0].required = false;
+                }
+                var formValid = false;
+
+                if(that.$refs.modelForm) {
+                    await that.$refs.modelForm.$refs.form.$refs.form.validate((valid,fields) => {
+                        formValid = valid;
+                    })
+
+                    if(!formValid) {
+                    that.activeName = '扩展信息';
+                    return;
+                }
+                }
+
+                this.$refs.form.validate(function (valid) {
+                    if (valid) {
+                        that.saveDisabled = true;
+                        if (that.puIcon && that.puIcon.length > 0) {
+                            that.form.puIcon = that.puIcon[0].url.replace(new RegExp('^'+ms.contextpath), "");
+                        }
+                        var data = JSON.parse(JSON.stringify(that.form));
+
+                        //保存用户信息
+                        ms.http.post(url, data).then(function (res) {
+                            if (res.result) {
+                                // 自定义模型保存,
+                                if(that.$refs.modelForm) {
+                                    that.$refs.modelForm.$refs.form.form.linkId = res.data.id;
+                                    that.$refs.modelForm.getForm().save(function (resModel) {
+                                        if(resModel.result){
+                                            //模型保存成功
+                                        }else {
+                                            //模型保存失败
+                                        }
+                                    });
+                                }
+                                that.$notify({
+                                    title: '成功',
+                                    message: res.data.peopleState == 0 ? '保存成功,已将数据纳入待审核中!' : '保存成功!',
+                                    type: 'success',
+                                    duration: 1500,
+                                    onClose: function () {
+                                        window.history.go(-1);
+                                    }
+                                });
+                                that.saveDisabled = false;
+
+                            } else {
+                                that.$notify({
+                                    title: '失败',
+                                    message: res.msg,
+                                    type: 'warning'
+                                });
+                                that.saveDisabled = false;
+                            }
+                        }).catch(function (error) {
+                            that.saveDisabled = false;
+                        });
+                    } else {
+                        // 自定义模型
+                        that.activeName = '基本信息';
+                        return false;
+                    }
+                });
+            },
+            //获取当前用户
+            get: function (id) {
+                var that = this;
+                ms.http.get(ms.manager + "/people/peopleUser/get.do", {
+                    "peopleId": id
+                }).then(function (res) {
+                    if (res.result) {
+                        // 设置城市的回显值
+                        that.cityValue = [res.data.provinceId,res.data.cityId,res.data.countyId];
+                        that.objectCopy(that.form, res.data);
+                        that.form.peopleDateTime = '';
+                        // that.puIcon = that.form.puIcon;
+                        if (that.form.puIcon) {
+                            if(!that.form.puIcon.startsWith("http://") && !that.form.puIcon.startsWith("https://")) {
+                                that.puIcon = [{url: ms.contextpath + that.form.puIcon, uid: ""}];
+                            }else{
+                                that.puIcon = [{url: that.form.puIcon, uid: ""}];
+                            }
+                        }
+                    }
+                }).catch(function (err) {
+                    console.log(err);
+                });
+            },
+            puLevelSelectChange: function (level) {
+                var dict = this.puLevelOptions.find(function (item) {
+                    return item.dictValue == level;
+                });
+                this.form.puLevelName = dict.dictLabel;
+            },
+            //获取puLevel数据源
+            puLevelOptionsGet: function () {
+                var that = this;
+                ms.http.get(ms.manager + '/mdiy/dict/list.do', {
+                    dictType: '用户等级类型',
+                    pageSize: 99999
+                }).then(function (res) {
+                    if (res.result) {
+                        res = res.data;
+                        that.puLevelOptions = res.rows;
+                    }
+                }).catch(function (err) {
+                    console.log(err);
+                });
+            },
+            //上传超过限制
+            puIconhandleExceed: function (files, fileList) {
+                this.$notify({
+                    title: '失败',
+                    message: '当前最多上传1张头像',
+                    type: 'warning'
+                });
+            },
+            //puIcon文件上传完成回调
+            puIconBasicPicSuccess: function (response, file, fileList) {
+                var that = this;
+                if (response.result) {
+                    if(!response.data.startsWith("http://") && !response.data.startsWith("https://")) {
+                        file.url = ms.contextpath + response.data;
+                    }else{
+                        file.url = response.data;
+                    }
+                    that.puIcon = response.data;
+                    that.puIcon = [];
+                    that.puIcon.push({url: file.url, uid: file.uid});
+                } else {
+                    this.$notify({
+                        title: '失败',
+                        message: response.msg,
+                        type: 'warning'
+                    });
+                }
+            },
+            puIconhandleRemove: function (file, files) {
+                // var index = -1;
+                this.form.puIcon = '';
+                this.puIcon = [];
+                // index = this.form.puIcon.findIndex(function (text) {
+                //     return text == file;
+                // });
+                //
+                // if (index != -1) {
+                //     this.form.puIcon.splice(0, 1);
+                // }
+            },
+
+        },
+        created: function () {
+            var that = this;
+			that.backUrl = ms.util.getParameter("backUrl");
+            this.puLevelOptionsGet();
+            this.form.peopleId = ms.util.getParameter("peopleId");
+            if (this.form.peopleId) {
+                this.get(this.form.peopleId);
+            } else {
+                this.rules.peoplePassword.push({
+                    "required": true,
+                    "message": "密码必须填写"
+                });
+            }
+            this.$nextTick(function (){
+                //加载自定义模型,modelName:模型名称,linkId:主表ID
+                ms.http.get(ms.manager + "/mdiy/model/get.do", {"modelName":"扩展会员信息"}).then(function (res) {
+                    if (res.result && res.data) {
+                        that.modelId = res.data.id;
+                        that.modelName = res.data.modelName;
+                    }
+                });
+            })
+
+
+        }
+    });
+</script>
+<style>
+    #form .ms-container {
+        margin: 12px;
+        height: calc(100% - 24px);
+        padding: 14px;
+        background: #fff;
+    }
+
+    #form .ms-footer {
+        margin: 0px 12px 12px 12px;
+        height: 100% !important;
+        padding: 14px;
+        background: #fff;
+    }
+
+    .el-select {
+        width: 100%;
+    }
+
+    body {
+        overflow: hidden;
+    }
+
+    #form {
+        overflow: hidden;
+    }
+
+    .el-scrollbar__bar.is-vertical {
+        width: 6px !important;
+    }
+</style>

+ 412 - 0
src/main/webapp/WEB-INF/manager/people/people-user/index.ftl

@@ -0,0 +1,412 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <title>用户</title>
+    <#include "../../include/head-file.ftl">
+</head>
+<body>
+<div id="index" v-cloak class="ms-index">
+    <el-header class="ms-header" height="50px">
+        <el-col :span=12>
+            <@shiro.hasPermission name="people:user:save">
+                <el-button type="primary" class="el-icon-plus" size="default" @click="save()">新增</el-button>
+            </@shiro.hasPermission>
+            <@shiro.hasPermission name="people:user:del">
+                <el-button type="danger" class="el-icon-delete" size="default" @click="del(selectionList)"
+                           :disabled="!selectionList.length">删除
+                </el-button>
+            </@shiro.hasPermission>
+        </el-col>
+    </el-header>
+    <div class="ms-search" style="padding: 20px 10px 20px 10px;">
+        <el-row>
+            <el-form :model="form" ref="searchForm" :rules="rules" label-width="80px" size="default">
+                <el-row>
+                    <el-col :span=8>
+                        <el-form-item label="账号" prop="peopleName">
+                            <el-input v-model="form.peopleName"
+                                      :disabled="false"
+                                      :style="{width:  '100%'}"
+                                      :clearable="true"
+                                      placeholder="请输入账号">
+                            </el-input>
+                        </el-form-item>
+                    </el-col>
+                    <el-col :span=8>
+                        <el-form-item label="昵称" prop="puNickname">
+                            <el-input v-model="form.puNickname"
+                                      :disabled="false"
+                                      :style="{width:  '100%'}"
+                                      :clearable="true"
+                                      placeholder="请输入昵称">
+                            </el-input>
+                        </el-form-item>
+                    </el-col>
+                    <el-col :span=8>
+                        <el-form-item label="真实姓名" prop="puRealName">
+                            <el-input v-model="form.puRealName"
+                                      :disabled="false"
+                                      :style="{width:  '100%'}"
+                                      :clearable="true"
+                                      placeholder="请输入真实姓名">
+                            </el-input>
+                        </el-form-item>
+                    </el-col>
+                </el-row>
+                <el-row>
+                    <el-col :span=8>
+                        <el-form-item label="手机号码" prop="peoplePhone">
+                            <el-input v-model="form.peoplePhone"
+                                      :disabled="false"
+                                      :style="{width:  '100%'}"
+                                      :clearable="true"
+                                      placeholder="请输入手机号码">
+                            </el-input>
+                        </el-form-item>
+                    </el-col>
+                    <el-col :span=8>
+                        <el-form-item label="邮箱" prop="peopleMail">
+                            <el-input v-model="form.peopleMail"
+                                      :disabled="false"
+                                      :style="{width:  '100%'}"
+                                      :clearable="true"
+                                      placeholder="请输入邮箱">
+                            </el-input>
+                        </el-form-item>
+                    </el-col>
+                    <el-col :span=8>
+                        <el-form-item label="注册时间" prop="peopleDateTimes">
+                            <el-date-picker
+                                    v-model="peopleDateTimes"
+                                    value-format="YYYY-MM-DD HH:mm:ss"
+                                    format="YYYY-MM-DD"
+                                    type="daterange"
+                                    :style="{width:  '100%'}"
+                                    start-placeholder="开始日期"
+                                    end-placeholder="结束日期">
+                            </el-date-picker>
+                        </el-form-item>
+                    </el-col>
+                </el-row>
+                <el-row>
+                    <el-col :span=8>
+                        <el-form-item label="用户ID" prop="peopleId">
+                            <el-input v-model="form.peopleId"
+                                      :disabled="false"
+                                      :style="{width:  '100%'}"
+                                      :clearable="true"
+                                      placeholder="请输入用户ID">
+                            </el-input>
+                        </el-form-item>
+                    </el-col>
+                    <el-col :span=16  style="text-align:right;">
+                        <el-button type="primary" class="el-icon-search" size="default" @click="loading=true;currentPage=1;list()">查询
+                        </el-button>
+                        <el-button @click="rest" class="el-icon-refresh" size="default">重置</el-button>
+                    </el-col>
+                </el-row>
+            </el-form>
+        </el-row>
+    </div>
+    <el-main class="ms-container">
+        <el-table v-loading="loading" ref="multipleTable" height="calc(100vh-68px)" class="ms-table-pagination" border :data="treeList"
+                  tooltip-effect="dark" @selection-change="handleSelectionChange">
+            <template #empty>
+                {{emptyText}}
+            </template>
+            <el-table-column type="selection" width="40"></el-table-column>
+            <el-table-column label="ID" align="center" prop="id">
+            </el-table-column>
+            <el-table-column width="80" label="头像" align="center">
+                <template #default="scope">
+                    <el-image v-if="scope.row.puIcon !=null" :src="scope.row.puIcon" style="width: 50px;height: 50px;line-height: 50px;font-size: 50px">
+                        <template #error>
+                            <div class="image-slot">
+                                <i class="el-icon-picture-outline"></i>
+                            </div>
+                        </template>
+                    </el-image>
+                </template>
+            </el-table-column>
+            <el-table-column label="账号" align="left" prop="peopleName">
+            </el-table-column>
+            <el-table-column label="真实姓名" align="left" prop="puRealName">
+            </el-table-column>
+            <el-table-column label="昵称" align="left" prop="puNickname">
+            </el-table-column>
+            <el-table-column label="手机号码" width="130" align="center" prop="peoplePhone">
+            </el-table-column>
+            <el-table-column label="邮箱"  width="200" align="center" prop="peopleMail">
+            </el-table-column>
+            <el-table-column label="注册时间" width="180" align="center" prop="peopleDateTime">
+            </el-table-column>
+            <el-table-column label="用户状态" width="100" align="center" prop="peopleState">
+                <template #default="scope">
+                    {{scope.row.peopleState==0?'未审':'已审'}}
+                </template>
+            </el-table-column>
+            <@shiro.hasPermission name="people:user:update">
+                <el-table-column label="操作" width="180px" align="center">
+                    <template #default="scope">
+                        <@shiro.hasPermission name="people:user:update">
+                            <el-link :underline="false" type="primary" @click="save(scope.row.id)">编辑</el-link>
+                        </@shiro.hasPermission>
+                        <@shiro.hasPermission name="people:user:del">
+                        <el-link :underline="false" type="primary" @click="del([scope.row])">删除</el-link>
+                        </@shiro.hasPermission>
+                    </template>
+                </el-table-column>
+            </@shiro.hasPermission>
+        </el-table>
+        <el-pagination
+                background
+                :page-sizes="[10, 50, 100]"
+                layout="total, sizes, prev, pager, next, jumper"
+                :current-page="currentPage"
+                :page-size="pageSize"
+                :total="total"
+                class="ms-pagination"
+                @current-change='currentChange'
+                @size-change="sizeChange">
+        </el-pagination>
+    </el-main>
+</div>
+</body>
+
+</html>
+<script>
+    var indexVue = new _Vue({
+        el: '#index',
+        data: function (){
+            return {
+                treeList: [],
+                //用户列表
+                selectionList: [],
+                //用户列表选中
+                loading: true,
+                emptyText: '',
+                total: 0,
+                //总记录数量
+                pageSize: 50,
+                //页面数量
+                currentPage: 1,
+                //初始页
+                mananger: ms.manager,
+                //搜索表单
+                form: {
+                    // id
+                    id: '',
+                    // 用户名
+                    peopleName: '',
+                    // 密码
+                    peoplePassword: '',
+                    // 昵称
+                    puNickname: '',
+                    // 性别
+                    puSex: '',
+                    // 真实姓名
+                    puRealName: '',
+                    // 身份证
+                    puCard: '',
+                    // 手机号码
+                    peoplePhone: '',
+                    // 邮箱
+                    peopleMail: '',
+                    // 头像
+                    // 地址
+                    puAddress: ''
+                },
+                peopleDateTimes: null,
+                puSexOptions: [{
+                    "value": 1,
+                    "label": "男"
+                }, {
+                    "value": 2,
+                    "label": "女"
+                }],
+                peopleStateOptions: [{
+                    "value": 0,
+                    "label": "未审"
+                }, {
+                    "value": 1,
+                    "label": "已审"
+                }],
+                rules: {peopleId: [{max: 20, message: '长度不能超过20位', trigger: 'blur'}]},
+                historyKey: "people_people_user_history"
+            }
+        },
+        methods: {
+            //查询列表
+            list: function () {
+                var that = this;
+                var page = {
+                    pageNo: that.currentPage,
+                    pageSize: that.pageSize
+                };
+                var form = JSON.parse(JSON.stringify(that.form));
+
+                if (that.peopleDateTimes) {
+                    form.peopleDateTimes = that.peopleDateTimes[0] + '至' + that.peopleDateTimes[1];
+                } else {
+                    form.peopleDateTimes = null;
+                }
+
+                for (var key in form) {
+                    if (!form[key]) {
+                        delete form[key];
+                    }
+                }
+
+                sessionStorage.setItem(this.historyKey,JSON.stringify({form: form, page: page}));
+
+                that.$refs.searchForm.validate(function (valid) {
+                    if (valid){
+                        setTimeout(function () {
+                            ms.http.get(ms.manager + "/people/peopleUser/auditList.do", Object.assign({}, form, page))
+                                .then(function (data) {
+                                    if(data.result){
+                                        if (data.data.total <= 0) {
+                                            that.loading = false;
+                                            that.emptyText = '暂无数据';
+                                            that.treeList = [];
+                                        } else {
+                                            that.emptyText = '';
+                                            that.loading = false;
+                                            that.total = data.data.total;
+                                            that.treeList = data.data.rows;
+                                            that.treeList.forEach(function (item) {
+                                                // 如果puIcon为空,则设置为null并返回
+                                                if (!item.puIcon) {
+                                                    item.puIcon = null;
+                                                    return;
+                                                }
+                                                if(!item.puIcon.startsWith("http://") && !item.puIcon.startsWith("https://")) {
+                                                    item.puIcon = ms.contextpath + item.puIcon;
+                                                }
+                                            });
+                                        }
+                                    }
+                                }).catch(function (err) {
+                                that.$notify({
+                                    type: 'warning',
+                                    msg: err.msg,
+                                    title: '失败'
+                                })
+                                that.loading = false;
+
+                                // console.log(err);
+                            });
+                        }, 500);
+                    }else {
+                        that.loading = false;
+                    }
+                })
+
+            },
+            //用户列表选中
+            handleSelectionChange: function (val) {
+                this.selectionList = val;
+            },
+            //删除
+            del: function (row) {
+                var that = this;
+                that.$confirm('此操作将永久删除所选内容, 是否继续?', '提示', {
+                    confirmButtonText: '确定',
+                    cancelButtonText: '取消',
+                    type: 'warning'
+                }).then(function () {
+                    ms.http.post(ms.manager + "/people/peopleUser/delete.do", row.length ? row : [row], {
+                        headers: {
+                            'Content-Type': 'application/json'
+                        }
+                    }).then(function (data) {
+                        if (data.result) {
+                            that.$notify({
+                                title:'成功',
+                                type: 'success',
+                                message: '删除成功!'
+                            }); //删除成功,刷新列表
+
+                            that.list();
+                        } else {
+                            that.$notify({
+                                title: '失败',
+                                message: data.msg,
+                                type: 'warning'
+                            });
+                        }
+                    });
+                });
+            },
+            //更新用户审核状态
+            updateUserState: function (row) {
+                var that = this;
+                that.$confirm('此操作将审核用户, 是否继续?', '提示', {
+                    confirmButtonText: '确定',
+                    cancelButtonText: '取消',
+                    type: 'warning'
+                }).then(function () {
+                    ms.http.post(ms.manager + "/people/updateState.do", row.length ? row : [row], {
+                        headers: {
+                            'Content-Type': 'application/json'
+                        }
+                    }).then(function (data) {
+                        if (data.result) {
+                            that.$notify({
+                                title:'成功',
+                                type: 'success',
+                                message: '审核成功!'
+                            }); //审核成功,刷新列表
+
+                            that.list();
+                        }
+                    });
+                });
+            },
+            //新增
+            save: function (id) {
+                if (id) {
+                    ms.util.openSystemUrl("/people/peopleUser/form.do?peopleId=" + id);
+                } else {
+                    ms.util.openSystemUrl("/people/peopleUser/form.do");
+                }
+            },
+            //pageSize改变时会触发
+            sizeChange: function (pagesize) {
+                this.loading = true;
+                this.pageSize = pagesize;
+                this.list();
+            },
+            //currentPage改变时会触发
+            currentChange: function (currentPage) {
+                this.loading = true;
+                this.currentPage = currentPage;
+                this.list();
+            },
+            //重置表单
+            rest: function () {
+                this.currentPage = 1;
+                this.loading = true;
+                this.$refs.searchForm.resetFields();
+                this.peopleDateTimes = null;
+                this.list();
+            }
+        },
+        mounted: function () {
+            //如果存在历史参数,恢复页面结果
+            if(sessionStorage.getItem(this.historyKey) && ms.util.getParameter("isBack") == 'true') {
+                var _history = JSON.parse(sessionStorage.getItem(this.historyKey))
+                this.form = _history.form;
+                this.total = parseInt(_history.total);
+                this.currentPage = parseInt(_history.page.pageNo);
+                this.pageSize = parseInt(_history.page.pageSize);
+            }
+            this.list();
+        }
+    });
+</script>
+<style>
+    #index .ms-search {
+        padding: 20px 0;
+    }
+</style>