This commit is contained in:
@jyuhsin
2025-10-30 17:38:59 +08:00
parent a5bdf21346
commit ef9b9bc03d
35 changed files with 707 additions and 103 deletions
@@ -0,0 +1,41 @@
package com.budwk.app.base.utils;
/**
* @ClassName DistanceUtils
* @Author JyuHsin
* @Date 2025/10/30 16:22
* @Version 1.0
* @Description TODO
*/
public class DistanceUtils {
private static final double EARTH_RADIUS = 6371000; // 地球半径,单位:米
/**
* 计算两个经纬度之间的距离(单位:米)
* @param lat1 纬度1(单位:度)
* @param lng1 经度1(单位:度)
* @param lat2 纬度2(单位:度)
* @param lng2 经度2(单位:度)
* @return 距离(米)
*/
public static double getDistance(double lat1, double lng1, double lat2, double lng2) {
// 将角度转为弧度
double lat1Rad = Math.toRadians(lat1);
double lng1Rad = Math.toRadians(lng1);
double lat2Rad = Math.toRadians(lat2);
double lng2Rad = Math.toRadians(lng2);
// 纬度和经度的差值(弧度)
double deltaLat = lat2Rad - lat1Rad;
double deltaLng = lng2Rad - lng1Rad;
// Haversine 公式
double a = Math.sin(deltaLat / 2) * Math.sin(deltaLat / 2)
+ Math.cos(lat1Rad) * Math.cos(lat2Rad)
* Math.sin(deltaLng / 2) * Math.sin(deltaLng / 2);
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
return EARTH_RADIUS * c; // 返回米
}
}
@@ -139,6 +139,7 @@ public class ActivityBasicScopeController {
FROM
`vw_user` u
LEFT JOIN sys_user_role sur ON sur.userid = u.id
LEFT JOIN club_user clubuser ON clubuser.userid=u.id
$condition
""");
Cnd cnd = getCnd(activityUserScopePageParam);
@@ -86,7 +86,7 @@ public class ActivityBasicUnitController {
for (int i = 0; i < list.size(); i++) {
nodeList.add(new TreeNode<>(list.get(i).getId(), list.get(i).getParentId(), list.get(i).getName(), i));
}
List<Tree<String>> treeList = TreeUtil.build(nodeList, "1");
List<Tree<String>> treeList = TreeUtil.build(nodeList, "0000");
return Result.success(treeList);
}
@@ -6,9 +6,13 @@ import cn.hutool.core.util.StrUtil;
import com.budwk.app.base.annotation.SLog;
import com.budwk.app.base.param.PageForm;
import com.budwk.app.base.result.Result;
import com.budwk.app.flow.entity.ProcessInstance;
import com.budwk.app.flow.enums.ProcessInstanceStateEnum;
import com.budwk.app.sys.models.Sys_home_activity;
import com.budwk.app.sys.models.Sys_union;
import com.budwk.app.zhgh.activity.trainSignUp.models.*;
import com.budwk.app.zhgh.activity.trainSignUp.service.TrainSignUpActivityService;
import com.budwk.app.zhgh.club.model.SysClub;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
@@ -197,4 +201,38 @@ public class TrainSignUpManageController {
List<TrainSignUpActivity> query = dao.query(TrainSignUpActivity.class, Cnd.NEW().desc("activityStartTime"));
return Result.success().addData(query);
}
@At
@Ok("json:full")
@ApiOperation("查询分工会和协会")
@SaCheckPermission("trainSignUp.manage")
public Result selectUnionAndClub() {
List<NutMap> result = new ArrayList<>();
List<Sys_union> unionList = dao.query(Sys_union.class, Cnd.NEW().asc(Sys_union::getUnionCode));
for (Sys_union union : unionList) {
NutMap map = new NutMap();
map.put("id", union.getId());
map.put("name", union.getName());
map.put("type", "union");
result.add(map);
}
List<SysClub> clubList = dao.query(SysClub.class, Cnd.NEW().asc(SysClub::getClubCode));
List<ProcessInstance> instanceList = dao.query(
ProcessInstance.class,
Cnd.where(ProcessInstance::getBusinessNo, "in", clubList.stream().map(SysClub::getId).toList())
.and(ProcessInstance::getState, "=", ProcessInstanceStateEnum.FINISHED.getCode())
);
List<String> passList = instanceList.stream().map(ProcessInstance::getBusinessNo).toList();
List<SysClub> passClubList = clubList.stream().filter(o -> passList.contains(o.getId())).toList();
for (SysClub sysClub : passClubList) {
NutMap map = new NutMap();
map.put("id", sysClub.getId());
map.put("name", sysClub.getClubName());
map.put("type", "club");
result.add(map);
}
return Result.success(result);
}
}
@@ -2,12 +2,15 @@ package com.budwk.app.zhgh.activity.trainSignUp.controller.manage;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.dev33.satoken.annotation.SaMode;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import com.budwk.app.base.annotation.SLog;
import com.budwk.app.base.param.PageForm;
import com.budwk.app.base.result.Result;
import com.budwk.app.base.utils.DistanceUtils;
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
import com.budwk.app.zhgh.activity.trainSignUp.models.TrainSignUpCourse;
import com.budwk.app.zhgh.activity.trainSignUp.models.TrainSignUpUserCourse;
import com.budwk.app.zhgh.activity.trainSignUp.service.TrainSignUpActivityService;
import io.swagger.annotations.Api;
@@ -26,6 +29,8 @@ import org.nutz.mvc.annotation.At;
import org.nutz.mvc.annotation.Ok;
import org.nutz.mvc.annotation.Param;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Date;
import java.util.List;
@@ -73,22 +78,25 @@ public class TrainsignUpMineController {
return Result.error(99, "未查询到您的报名记录");
}
// 获取现在的日期,并往后推1个小时
String oneHourLater = DateUtil.offsetHour(new Date(), 1).toString("yyyy-MM-dd HH:mm:ss");
TrainSignUpUserCourse userCourse = dao.fetch(
TrainSignUpUserCourse.class,
Cnd.where("courseId", "=", courseId)
.and("userId", "=", SecurityUtil.getUserId())
.and("courseStartTime", "<=", oneHourLater)
.and("courseEndTime", ">=", oneHourLater)
);
if (userCourse == null) {
TrainSignUpCourse course = dao.fetch(TrainSignUpCourse.class, courseId);
int minute = course.getSignUnit() != null ? course.getSignUnit() : 0;
boolean flag = true;
// 获取现在的日期,并根据设置的数据
List<TrainSignUpUserCourse> timeList = dao.query(TrainSignUpUserCourse.class, Cnd.where("courseId", "=", courseId));
for (TrainSignUpUserCourse userCourse : timeList) {
DateTime startTime = DateUtil.offsetMinute(userCourse.getCourseStartTime(), -minute);
DateTime endTime = DateUtil.offsetMinute(userCourse.getCourseEndTime(), minute);
if(DateUtil.isIn(DateUtil.date(), startTime, endTime)) {
userCourse.setAttend(true);
userCourse.setAttendTime(DateUtil.date());
flag = false;
}
}
if(flag) {
return Result.error(99, "未到签到时间");
}
userCourse.setAttend(true);
userCourse.setAttendTime(DateUtil.date());
dao.update(userCourse);
dao.update(timeList);
return Result.success();
}
@@ -122,6 +130,29 @@ public class TrainsignUpMineController {
return Result.success();
}
@At
@ApiOperation("定位签到")
@Aop(TransAop.READ_COMMITTED)
@SaCheckPermission(value = {"trainSignUp.mine", "h5.trainSignUp.mine"}, mode = SaMode.OR)
@SLog(tag = "品牌活动-定位签到", msg = "定位签到")
public Result positionSign(String courseId, String timeId, Double lat, Double lng) {
TrainSignUpCourse course = dao.fetch(TrainSignUpCourse.class, courseId);
List<Double> coordinates = course.getCourseLocationCoordinates();
double distance = DistanceUtils.getDistance(coordinates.get(0), coordinates.get(1), lat, lng);
int radius = course.getRadius() != null ? course.getRadius() : 100;
if(distance > radius) {
int result = BigDecimal.valueOf(distance).setScale(0, RoundingMode.HALF_UP).intValue();
return Result.error(99, "签到失败,您距离签到点还有%s米".formatted(result));
}
TrainSignUpUserCourse userCourse = dao.fetch(TrainSignUpUserCourse.class, timeId);
userCourse.setAttend(true);
userCourse.setAttendTime(DateUtil.date());
dao.update(userCourse);
return Result.success();
}
@At
@ApiOperation("分活动查询")
@SaCheckPermission(value = {"trainSignUp.mine", "h5.trainSignUp.mine"}, mode = SaMode.OR)
@@ -7,12 +7,15 @@ import cn.afterturn.easypoi.excel.export.ExcelExportService;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import com.budwk.app.base.constant.RoleConstant;
import com.budwk.app.base.page.Pagination;
import com.budwk.app.base.param.PageForm;
import com.budwk.app.base.result.Result;
import com.budwk.app.base.utils.CommonDownloadUtil;
import com.budwk.app.sys.models.Sys_file;
import com.budwk.app.sys.utils.SysFileMinIoUtil;
import com.budwk.app.web.commons.auth.utils.AuthUtil;
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
import com.budwk.app.zhgh.activity.trainSignUp.models.TrainMobileSignColumn;
import com.budwk.app.zhgh.activity.trainSignUp.models.TrainSignUpActivity;
import com.budwk.app.zhgh.activity.trainSignUp.models.TrainSignUpCourse;
@@ -96,7 +99,28 @@ public class TrainSignUpActivityStatisticsController {
@SaCheckPermission("trainSignUp.statistics")
public Result activityList(@Param(value = "year") Integer year) {
List<TrainSignUpActivity> list = dao.query(TrainSignUpActivity.class, Cnd.NEW().andEX("year", "=", year).desc("activityStartTime"));
return Result.success(list);
if(!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_CHAIRMAN.name())) {
// 获取当前登录用户的工会
String unionId = SecurityUtil.getUnionId();
// 获取当前登录用户的协会
List<String> clubIds = SecurityUtil.getClubIds();
List<TrainSignUpActivity> result = new ArrayList<>();
for (TrainSignUpActivity activity : list) {
if(AuthUtil.hasRole(RoleConstant.BRANCH_UNION_CHAIRMAN.name())) {
if(activity.getHostUnits().contains(unionId) || activity.getHelpUnits().contains(unionId)) {
result.add(activity);
}
}
if(AuthUtil.hasRoleOr(RoleConstant.CLUB_PRESIDENT.name(), RoleConstant.CLUB_OPERATOR.name())) {
if(clubIds.stream().anyMatch(activity.getHostUnits()::contains) || clubIds.stream().anyMatch(activity.getHelpUnits()::contains)) {
result.add(activity);
}
}
}
return Result.success(result);
}
return Result.success(list);
}
/**
@@ -114,6 +114,16 @@ public class TrainSignUpActivity extends BaseModel implements Serializable, SysH
@ColDefine(type = ColType.VARCHAR, width = 20)
private String trainType;
@Column
@Comment("主办单位")
@ColDefine(type = ColType.MYSQL_JSON)
private List<String> hostUnits;
@Column
@Comment("协办单位")
@ColDefine(type = ColType.MYSQL_JSON)
private List<String> helpUnits;
@Override
public Sys_home_activity covertToSysHomeActivity() {
Sys_home_activity sysHomeActivity = new Sys_home_activity();
@@ -114,6 +114,16 @@ public class TrainSignUpCourse extends BaseModel implements Serializable {
@Comment("签到方式 1.扫描二维码签到 2.被扫 3.gps签到")
private Integer signType;
@Column
@ColDefine(type = ColType.INT)
@Comment("签到时间误差")
private Integer signUnit;
@Column
@ColDefine(type = ColType.INT)
@Comment("签到半径")
private Integer radius;
@Column
@ColDefine(type = ColType.BOOLEAN)
@Comment("移动端是否签收礼品")
@@ -18,10 +18,13 @@ import com.budwk.app.sys.services.SysUserService;
import com.budwk.app.sys.views.View_user;
import com.budwk.app.web.commons.auth.utils.AuthUtil;
import com.budwk.app.web.controllers.open.commons.service.CommonService;
import com.budwk.app.zhgh.activity.basic.models.ActivityUserScope;
import com.budwk.app.zhgh.activity.trainSignUp.models.TrainSignUpActivity;
import com.budwk.app.zhgh.club.model.ClubUser;
import com.budwk.app.zhgh.club.model.SysClub;
import com.budwk.app.zhgh.club.param.ClubUserPageForm;
import com.budwk.app.zhgh.club.service.SysClubInfoManageService;
import com.budwk.app.zhgh.club.service.SysClubUserService;
import com.budwk.app.zhgh.club.vo.ClubCommonPageVo;
import com.budwk.app.zhgh.club.vo.ClubUserImportVo;
import io.swagger.annotations.ApiOperation;
@@ -67,6 +70,8 @@ public class ClubInfoManageController {
private SysRoleService sysRoleService;
@Inject
private SysUserService sysUserService;
@Inject
private SysClubUserService clubUserService;
@At("")
@Ok("beetl:/platform/zhgh/club/infoManage/manage/index.html")
@@ -159,6 +164,22 @@ public class ClubInfoManageController {
.and("clubId", "=", clubUser.getClubId()));
}
}
/* 根据品牌活动,操作user_scope表 start */
List<TrainSignUpActivity> list = dao.query(TrainSignUpActivity.class, Cnd.NEW());
List<TrainSignUpActivity> activityList = new ArrayList<>();
for (TrainSignUpActivity activity : list) {
boolean host = Lang.isNotEmpty(activity.getHostUnits()) && activity.getHostUnits().contains(clubUser.getClubId());
if(host) {
activityList.add(activity);
}
}
if(Lang.isNotEmpty(activityList)) {
List<Integer> groupList = activityList.stream().map(TrainSignUpActivity::getActivityGroupId).distinct().toList();
dao.clear(ActivityUserScope.class, Cnd.where("userId", "=", clubUser.getUserId()).and("groupId", "in", groupList));
}
/* 根据品牌活动,操作user_scope表 end */
sysUserService.clearCache();
sysRoleService.clearCache();
return Result.success();
@@ -282,7 +303,9 @@ public class ClubInfoManageController {
}
dao.insertOrUpdate(clubUser);
}
return Result.success();
clubUserService.clubUser2Scope(clubId, Arrays.asList(users));
return Result.success();
}
@At
@@ -353,6 +376,10 @@ public class ClubInfoManageController {
});
dao.insert(sysUserRoleList);
if(Lang.isNotEmpty(clubUserList)) {
clubUserService.clubUser2Scope(businessId, clubUserList.stream().map(ClubUser::getUserId).toList());
}
//如果有错误数据就返回给前端
if (Lang.isNotEmpty(errorInfos)) {
NutMap nutMap = NutMap.NEW();
@@ -7,9 +7,14 @@ import com.budwk.app.flow.engine.core.Execution;
import com.budwk.app.flow.engine.core.ServiceContext;
import com.budwk.app.zhgh.club.model.ClubUser;
import com.budwk.app.zhgh.club.model.ClubUserApply;
import com.budwk.app.zhgh.club.service.SysClubUserService;
import org.nutz.aop.interceptor.ioc.TransAop;
import org.nutz.dao.Dao;
import org.nutz.ioc.aop.Aop;
import org.nutz.json.Json;
import java.util.List;
/**
* @ClassName ClubUserJoinInterceptor
* @Author JyuHsin
@@ -20,14 +25,18 @@ import org.nutz.json.Json;
public class ClubUserJoinInterceptor implements FlowInterceptor {
@Override
@Aop(TransAop.READ_COMMITTED)
public void intercept(Execution execution) {
String formDataStr = execution.getArgs().getStr(FlowConst.FORM_DATA);
ClubUserApply clubUserApply = Json.fromJson(ClubUserApply.class, formDataStr);
Dao dao = ServiceContext.find(Dao.class);
SysClubUserService userService = ServiceContext.find(SysClubUserService.class);
ClubUser clubUser = BeanUtil.copyProperties(clubUserApply, ClubUser.class);
dao.insert(clubUser);
userService.clubUser2Scope(clubUser.getClubId(), List.of(clubUser.getUserId()));
}
}
@@ -22,4 +22,6 @@ public interface SysClubUserService extends BaseService<ClubUser> {
Pagination pageDataByApplyJoinClubAudit(@Valid ClubUserPageForm pageForm);
String getClubLeader(@Valid String clubId);
void clubUser2Scope(String clubId, List<String> users);
}
@@ -129,16 +129,7 @@ public class SysClubInfoManageServiceImpl extends BaseServiceImpl<ClubCommonPage
LEFT JOIN sys_club club ON scu.clubId = club.id
RIGHT JOIN `vw_user` u ON scu.userId = u.id
$condition
ORDER BY
CASE
WHEN JSON_CONTAINS(scu.roleCode, '"CLUB_PRESIDENT"') THEN 1
WHEN JSON_CONTAINS(scu.roleCode, '"CLUB_VICE_PRESIDENT"') THEN 2
WHEN JSON_CONTAINS(scu.roleCode, '"CLUB_SECRETARY"') THEN 3
WHEN JSON_CONTAINS(scu.roleCode, '"CLUB_VICE_SECRETARY"') THEN 4
WHEN JSON_CONTAINS(scu.roleCode, '"CLUB_OPERATOR"') THEN 5
WHEN JSON_CONTAINS(scu.roleCode, '"CLUB_MEMBER"') THEN 6
ELSE 99
END
$order
""");
Cnd cnd = Cnd.NEW();
@@ -155,7 +146,20 @@ public class SysClubInfoManageServiceImpl extends BaseServiceImpl<ClubCommonPage
if (StrUtil.isAllNotBlank(pageForm.getPageOrderName(), pageForm.getPageOrderBy())) {
cnd.orderBy(pageForm.getPageOrderName(), "descending".equals(pageForm.getPageOrderBy()) ? "desc" : "asc");
}
} else {
sql.setVar("order", """
ORDER BY
CASE
WHEN JSON_CONTAINS(scu.roleCode, '"CLUB_PRESIDENT"') THEN 1
WHEN JSON_CONTAINS(scu.roleCode, '"CLUB_VICE_PRESIDENT"') THEN 2
WHEN JSON_CONTAINS(scu.roleCode, '"CLUB_SECRETARY"') THEN 3
WHEN JSON_CONTAINS(scu.roleCode, '"CLUB_VICE_SECRETARY"') THEN 4
WHEN JSON_CONTAINS(scu.roleCode, '"CLUB_OPERATOR"') THEN 5
WHEN JSON_CONTAINS(scu.roleCode, '"CLUB_MEMBER"') THEN 6
ELSE 99
END
""");
}
//查询理事机构
if (pageForm.getRadioType() != null && 1 == pageForm.getRadioType()) {
@@ -8,6 +8,8 @@ import com.budwk.app.sys.models.Sys_user;
import com.budwk.app.sys.services.SysRoleService;
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
import com.budwk.app.web.controllers.open.commons.service.CommonService;
import com.budwk.app.zhgh.activity.basic.models.ActivityUserScope;
import com.budwk.app.zhgh.activity.trainSignUp.models.TrainSignUpActivity;
import com.budwk.app.zhgh.club.model.ClubUser;
import com.budwk.app.zhgh.club.param.ClubUserPageForm;
import com.budwk.app.zhgh.club.service.SysClubService;
@@ -23,6 +25,7 @@ import org.nutz.ioc.aop.Aop;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.json.Json;
import org.nutz.lang.Lang;
import org.nutz.lang.util.NutMap;
import javax.validation.Valid;
@@ -142,4 +145,39 @@ public class SysClubUserServiceImpl extends BaseServiceImpl<ClubUser> implements
.filter(Objects::nonNull)
.collect(Collectors.joining(""));
}
@Override
public void clubUser2Scope(String clubId, List<String> users) {
// 添加协会成员需要增加到品牌活动的组别去wcnm
List<TrainSignUpActivity> list = dao().query(TrainSignUpActivity.class, Cnd.NEW());
List<TrainSignUpActivity> activityList = new ArrayList<>();
for (TrainSignUpActivity activity : list) {
boolean host = Lang.isNotEmpty(activity.getHostUnits()) && activity.getHostUnits().contains(clubId);
if(host) {
activityList.add(activity);
}
}
if(Lang.isNotEmpty(activityList)) {
// 查询所有的组别
List<ActivityUserScope> groupAllList = dao().query(ActivityUserScope.class, Cnd.NEW().groupBy("groupId"));
Map<Integer, String> groupMap = groupAllList.stream().collect(Collectors.toMap(ActivityUserScope::getGroupId, ActivityUserScope::getGroupName));
List<Integer> groupList = activityList.stream().map(TrainSignUpActivity::getActivityGroupId).distinct().toList();
List<ActivityUserScope> addScopes = new ArrayList<>();
for (Integer groupId : groupList) {
for (String user : users) {
int count = dao().count(ActivityUserScope.class, Cnd.where(ActivityUserScope::getGroupId, "=", groupId).and(ActivityUserScope::getUserId, "=", user));
if(count > 0) {
continue;
}
ActivityUserScope scope = new ActivityUserScope();
scope.setGroupId(groupId);
scope.setGroupName(groupMap.get(groupId));
scope.setUserId(user);
addScopes.add(scope);
}
}
dao().insert(addScopes);
}
}
}
@@ -0,0 +1,52 @@
package com.budwk.app.zhgh.map;
import cn.dev33.satoken.annotation.SaCheckLogin;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
import com.budwk.app.base.page.Pagination;
import com.budwk.app.base.result.Result;
import com.budwk.app.sys.models.Sys_config;
import com.budwk.app.sys.services.SysConfigService;
import com.budwk.app.zhgh.club.param.ClubUserPageForm;
import com.budwk.app.zhgh.club.vo.ClubCommonPageVo;
import io.swagger.annotations.ApiOperation;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.mvc.annotation.At;
import org.nutz.mvc.annotation.Ok;
import javax.validation.Valid;
/**
* @ClassName TMapController
* @Author JyuHsin
* @Date 2025/10/30 11:22
* @Version 1.0
* @Description TODO
*/
@IocBean
@Ok("json")
@At("/platform/TMap")
public class TMapController {
private static String KEY = "MLLBZ-GQECI-ASXG7-5GNOZ-XW2OF-H5BVH";
@Inject
private SysConfigService configService;
@At
@SaCheckLogin
@ApiOperation("关键词输入提示")
public Result suggestion(String keyword) {
if(StrUtil.isBlank(keyword)) {
return Result.error("关键词不能为空");
}
Sys_config city = configService.getValueByKey("CityName");
String cityName = city != null ? city.getConfigValue() : "";
String url = "https://apis.map.qq.com/ws/place/v1/suggestion?key=%s&keyword=%s&region=%s"
.formatted(KEY, keyword, cityName);
String response = HttpUtil.get(url);
return Result.success(JSONUtil.parse(response));
}
}
@@ -0,0 +1,155 @@
<template>
<div style="position: relative !important">
<div style="margin-bottom: 10px">
<el-autocomplete
v-model="addressValue"
style="width: 100%"
:fetch-suggestions="querySearchAsync"
placeholder="请输入关键词查询地址"
@select="handleSelect"
:trigger-on-focus="false"
/>
</div>
<div id="mapContainer"></div>
</div>
</template>
<script>
module.exports = {
name: "TMap",
props: {
radius: {
type: Number,
default: 50
},
position: {
type: Array,
default: () => {
return []
}
},
view: { type: Boolean, default: false }
},
data() {
return {
map: null,
poi: this.position,
appMapCenterPointX: 0,
appMapCenterPointY: 0,
markerLayer: null,
addressValue: '',
circle: null,
}
},
methods: {
handleSelect(item) {
if (item.location) {
//
const center = new TMap.LatLng(item.location.lat, item.location.lng)
this.map.setCenter(center)
this.clearMarker()
this.createMarker(center)
this.poi = [item.location.lat, item.location.lng]
}
},
async querySearchAsync(queryString, cb) {
if (!queryString) {
return
}
const res = await this.$axios.post("/platform/TMap/suggestion", {
keyword: queryString,
})
if (res.code === 0 && res.data.status === 0) {
res.data.data.forEach((item) => {
item.value = item.title + "【详细地址:" + item.address + "】"
})
cb(res.data.data)
} else {
this.$message.error(res.msg)
cb([])
}
},
initMap() {
const center = new TMap.LatLng(this.appMapCenterPointY, this.appMapCenterPointX)
this.map = new TMap.Map('mapContainer', {
resizeEnable: true,
zoom: 16,
center: center
})
//
this.markerLayer = new TMap.MultiMarker({
map: this.map,
geometries: []
});
if (this.poi && this.poi.length > 0) {
const posi = new TMap.LatLng(this.poi[0], this.poi[1])
this.createMarker(posi)
this.map.setCenter(posi)
} else {
this.createMarker(center)
}
this.map.on("click", (event) => {
if (!this.view) {
this.clearMarker()
this.createMarker(event.latLng)
this.poi = [event.latLng.getLat(), event.latLng.getLng()]
}
})
},
//
clearMarker() {
if (this.markerLayer) {
this.markerLayer.setGeometries([])
}
if(this.circle) {
this.circle.setGeometries([])
}
},
//
createMarker(position) {
this.markerLayer.add([
{
id: 'marker_' + Date.now(),
position: position
}
]);
this.circle = new TMap.MultiCircle({
map: this.map,
geometries: [{
center: position,
radius: this.radius,
}],
});
},
async getConfigKey(key) {
const resp = await this.$axios.post("/open/common/getConfigKey", { key })
return resp.data
}
},
watch: {
position(newVal) {
this.poi = newVal
},
poi(newVal) {
this.$emit("update:position", newVal)
}
},
async mounted() {
// DOM
this.$nextTick(async () => {
this.appMapCenterPointX = await this.getConfigKey("AppMapCenterPointX")
this.appMapCenterPointY = await this.getConfigKey("AppMapCenterPointY")
this.initMap()
})
}
}
</script>
<style scoped>
#mapContainer {
padding: 0;
margin: 0;
width: 100%;
height: 500px;
}
</style>
@@ -63,7 +63,7 @@ module.exports = {
}
})
.catch((err) => {
console.log(err)
this.$toast('未获取到摄像头信息')
})
},
start() {
@@ -88,7 +88,7 @@ module.exports = {
});
},
closeScan() {
this.html5QrCode.stop()
this.html5QrCode?.stop()
.then((ignore) => {
console.log("QR Code scanning stopped.");
})
@@ -80,6 +80,7 @@
src="https://webapi.amap.com/maps?v=2.0&key=57f0d098ba1b881ecc436c4cfd23bbbf&plugin=AMap.PolyEditor,AMap.Geolocation"
></script>
<script src="https://map.qq.com/api/gljs?v=2.exp&key=MLLBZ-GQECI-ASXG7-5GNOZ-XW2OF-H5BVH"></script>
<script>
Vue.config.devtools = true
@@ -31,9 +31,9 @@
<link rel="stylesheet" href="${base!}/assets/platform/css/common.css" />
<!-- import Jquery -->
<script src="${base!}/assets/platform/plugins/jquery/jquery-high.min.js"></script>
<script src="${base!}/assets/platform/plugins/jquery/jquery.js"></script>
<!-- pjax是异步加载html片段的工具,模拟前端路由机制 -->
<script src="${base!}/assets/platform/plugins/pjax/jquery.pjax-high.min.js"></script>
<script src="${base!}/assets/platform/plugins/pjax/jquery.pjax.js"></script>
<!-- nprogress 配合pjax使用 -->
<link rel="stylesheet" href="${base!}/assets/platform/plugins/nprogress/nprogress.css" />
<script src="${base!}/assets/platform/plugins/nprogress/nprogress.js"></script>
@@ -92,28 +92,13 @@ l
<script src="${base!}/assets/platform/js/util/autoShowError.js"></script>
<script src="${base!}/assets/platform/plugins/fullcalendar/fullcalendar.min.js"></script>
<script>
// 安全地冻结 Object.prototype(跳过不可配置属性)
(function () {
const badKeys = ['constructor', 'prototype'];
for (const key of badKeys) {
if (key in Object.prototype) {
try {
delete Object.prototype[key];
} catch (e) {
// 忽略无法删除的属性(如 __proto__ 在现代浏览器中不可删除)
}
}
}
<!--<script
type="text/javascript"
src="https://webapi.amap.com/maps?v=2.0&key=b4fa2e2bc10a725ab007b98a3aa447cc&plugin=AMap.PolyEditor,AMap.Geolocation"
></script>-->
<script src="https://map.qq.com/api/gljs?v=2.exp&key=MLLBZ-GQECI-ASXG7-5GNOZ-XW2OF-H5BVH"></script>
// 冻结 Object.prototype(如果可能)
try {
Object.freeze(Object.prototype);
} catch (e) {
// 忽略错误(某些环境可能不允许)
}
})();
</script>
<script type="text/javascript">
window._AMapSecurityConfig = {
securityJsCode: "4fa1e1aeabba7eb9518129cf57ab17c1"
@@ -71,22 +71,21 @@ layout("/layouts/platform.html"){
<el-table-column prop="loginname" label="工号" width="100" fixed="left"></el-table-column>
<el-table-column prop="username" label="姓名" fixed="left" width="120" show-overflow-tooltip></el-table-column>
<el-table-column prop="sex" label="性别" sortable></el-table-column>
<!-- <el-table-column prop="mobile" label="手机号" width="120"></el-table-column>-->
<el-table-column prop="mobile" label="手机号" width="120"></el-table-column>
<el-table-column prop="birthday" label="生日" sortable width="120">
<template slot-scope="{row}">{{$moment(row.birthday).format('YYYY-MM-DD')}}</template>
</el-table-column>
<el-table-column prop="userState" label="在职状态" sortable width="120"></el-table-column>
<el-table-column prop="arrivalAtSchoolDate" label="来校时间" sortable width="120"></el-table-column>
<el-table-column prop="preparedBy" label="编制类别" sortable width="120"></el-table-column>
<el-table-column prop="postDoctoralJoinDate" label="进站时间" sortable width="120"></el-table-column>
<el-table-column prop="personType" label="教职工类别" sortable width="120"></el-table-column>
<el-table-column prop="comeSchoolDate" label="来校年月" sortable width="120"></el-table-column>
<el-table-column prop="technicalTitle" label="技术职称" sortable width="120"></el-table-column>
<el-table-column prop="position" label="干部职务" sortable width="120" show-overflow-tooltip></el-table-column>
<el-table-column prop="education" label="学历" show-overflow-tooltip sortable width="120"></el-table-column>
<el-table-column prop="academicDegree" label="学位" show-overflow-tooltip sortable width="120"></el-table-column>
<el-table-column prop="unitName" label="单位" show-overflow-tooltip sortable width="120"></el-table-column>
<el-table-column prop="unitId" label="单位编码" sortable width="120"></el-table-column>
<el-table-column prop="nationality" label="国籍" sortable></el-table-column>
<el-table-column prop="political" label="政治面貌" sortable></el-table-column>
<el-table-column prop="nation" label="民族" sortable></el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
@@ -92,7 +92,7 @@
<!-- import axios -->
<script src="${base!}/assets/platform/plugins/axios/axios.js"></script>
<!-- import Jquery -->
<script src="${base!}/assets/platform/plugins/jquery/jquery-high.min.js"></script>
<script src="${base!}/assets/platform/plugins/jquery/jquery.js"></script>
<!-- import SM2 -->
<script src="${base!}/assets/platform/plugins/sm-crypto/sm2.js"></script>
<!-- import commonUtil -->
@@ -31,11 +31,11 @@ const courseList = {
<el-col class="query-content">
<el-tag
:effect="pageForm.assortTypes.includes(item) ? 'dark' : 'plain'"
:key="item"
:key="index"
:type="item"
@click="tagClick('assortTypes', item)"
style="margin-right: 10px; cursor: pointer"
v-for="item in assortList"
v-for="item,index in assortList"
>
{{ item }}
</el-tag>
@@ -31,11 +31,11 @@ const courseList = {
<el-col class="query-content">
<el-tag
:effect="pageForm.assortTypes.includes(item) ? 'dark' : 'plain'"
:key="item"
:key="index"
:type="item"
@click="tagClick('assortTypes', item)"
style="margin-right: 10px; cursor: pointer"
v-for="item in assortList"
v-for="item,index in assortList"
>
{{ item }}
</el-tag>
@@ -102,6 +102,22 @@ const basicForm = {
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20" type="flex">
<el-col :span="12">
<el-form-item label="主办单位" prop="hostUnits">
<el-select multiple filterable placeholder="请选择主办单位" style="width: 100%" v-model="formData.hostUnits">
<el-option :label="item.name" :value="item.id" :key="item.id" v-for="item in undertakeOptions"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="协办单位" prop="helpUnits">
<el-select multiple filterable placeholder="请选择协办单位" style="width: 100%" v-model="formData.helpUnits">
<el-option :label="item.name" :value="item.id" :key="item.id" v-for="item in undertakeOptions"></el-option>
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-form-item :rules="{required:true,message: '请输入活动介绍', trigger: 'blur'}" label="活动介绍" prop="introduce">
<text-editor v-model="formData.introduce"></text-editor>
</el-form-item>
@@ -318,7 +334,9 @@ const basicForm = {
},
restrictLimit: 1,
limitNum: 1,
typeLimits: []
typeLimits: [],
hostUnits: [],
helpUnits: [],
},
historicalActList: [],
trainTypeList: [],
@@ -331,6 +349,7 @@ const basicForm = {
},
campusList: [],
courseTypeList: [],
undertakeOptions: [],
}
},
components: {
@@ -537,6 +556,8 @@ const basicForm = {
}
cloneData.typeLimits = JSON.stringify(this.formData.typeLimits)
cloneData.courseList = JSON.stringify(cloneData.courseList)
cloneData.hostUnits = JSON.stringify(cloneData.hostUnits)
cloneData.helpUnits = JSON.stringify(cloneData.helpUnits)
const confirm = await this.$confirm("您确定要" + type + "吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
@@ -570,8 +591,13 @@ const basicForm = {
this.activityGroupList = await this.getActivityGroup()
this.historicalActList = await this.getHistoricalActList()
this.courseTypeList = await this.getAllType()
await this.selectUnionAndClub()
await this.init(row)
},
async selectUnionAndClub() {
const resp = await this.$axios.post("/platform/trainSignUp/manage/selectUnionAndClub")
this.undertakeOptions = resp.data
},
},
watch: {
'formData.restrictLimit'(val) {
@@ -75,11 +75,32 @@ const customForm = {
</el-col>
</el-row>
<el-row v-if="formData.courseList[moreInfoIndex].isMobileSign === true" :gutter="50" type="flex">
<el-col :span="4">
<span>签到时间误差</span>
</el-col>
<el-col :span="20">
<el-input placeholder="请输入签到时间误差" v-model="formData.courseList[moreInfoIndex].signUnit" type="number">
<template slot="append">分钟</template>
</el-input>
</el-col>
</el-row>
<el-row v-if="formData.courseList[moreInfoIndex].isMobileSign === true" :gutter="50" type="flex">
<el-col :span="4">
<span>签到半径</span>
</el-col>
<el-col :span="20">
<el-input placeholder="请输入签到半径" v-model="formData.courseList[moreInfoIndex].radius" type="number">
<template slot="append"></template>
</el-input>
</el-col>
</el-row>
<el-row
v-if="formData.courseList[moreInfoIndex].isMobileSign === true
&& formData.courseList[moreInfoIndex].signType == 3"
:gutter="50"
type="flex"
v-if="formData.courseList[moreInfoIndex].isMobileSign === true"
:gutter="50"
type="flex"
>
<el-col :span="4">
<span>地点坐标</span>
@@ -157,7 +178,9 @@ const customForm = {
</el-drawer>
<el-dialog :close-on-click-modal="false" :visible.sync="mapDialog" title="位置信息" :append-to-body="true">
<map-container v-if="mapDialog" :position.sync="formData.courseList[mapIndex].courseLocationCoordinates"></map-container>
<map-container v-if="mapDialog"
:radius="formData.courseList[moreInfoIndex].radius"
:position.sync="formData.courseList[mapIndex].courseLocationCoordinates"></map-container>
<span slot="footer" class="dialog-footer">
<el-button type="primary" @click="mapDialog = false"> </el-button>
</span>
@@ -181,7 +204,7 @@ const customForm = {
},
components: {
"union-form": unionForm,
"map-container": httpVueLoader("/components/plugins/mapContainer/MapContainer.vue?v=1.0.1")
"map-container": httpVueLoader("/components/plugins/mapContainer/TMap.vue?v=1.0.6")
},
methods: {
openMap(index) {
@@ -66,14 +66,14 @@ const makeQrcode = {
this.courseDialog = true
},
makeCourseCode(row) {
const url = '/platform/trainSignUp/mine/drivingScan'
const url = '${AppDomain!}/platform/trainSignUp/mine/drivingScan'
const data = url + '?courseId=' + row.id
console.log(data)
const content = jrQrcode.getQrBase64(data)
let image = new Image()
image.src = content
let viewer = new Viewer(image, {
zIndex: 99999999,
zIndex: 999999,
})
viewer.show()
},
@@ -115,9 +115,11 @@ layout("/layouts/platform.html"){
}
},
activityChange(val) {
const activity = this.activityList.find((o) => o.id === val)
const type = this.dict.type.TRAIN_SIGNUP_TYPE.find(o => o.code === activity.trainType)
this.trainType = type?.name || "培训班"
this.$nextTick(() => {
const activity = this.activityList.find((o) => o.id === val)
const type = this.dict.type.TRAIN_SIGNUP_TYPE?.find(o => o.code === activity.trainType)
this.trainType = type?.name || "培训班"
})
},
exportSignUser() {
this.$downLoad(loc() + "/exportSignUser", { activityId: this.pageForm.activityId })
@@ -105,9 +105,11 @@ layout("/layouts/platform.html"){
},
methods: {
activityChange(val) {
const activity = this.activityList.find((o) => o.id === val)
const type = this.dict.type.TRAIN_SIGNUP_TYPE.find(o => o.code === activity.trainType)
this.trainType = type?.name || "培训班"
this.$nextTick(() => {
const activity = this.activityList.find((o) => o.id === val)
const type = this.dict.type.TRAIN_SIGNUP_TYPE?.find(o => o.code === activity.trainType)
this.trainType = type?.name || "培训班"
})
},
async yearChange() {
this.pageForm.activityId = null
@@ -108,8 +108,8 @@ layout("/layouts/platform.html"){
{ label: "姓名", prop: "username" },
{ label: "工号", prop: "loginname" },
{ label: "联系方式", prop: "mobile" },
{ label: "单位", prop: "unitname", sortable: true },
{ label: "分工会", prop: "unionname", sortable: true },
{ label: "单位", prop: "unitName", sortable: true },
{ label: "分工会", prop: "unionName", sortable: true },
{ label: "课程", prop: "courseNames", sortable: true },
{ label: "缺席次数", prop: "absentCount" },
{ label: "是否黑名单", prop: "isDisabled", sortable: true }
@@ -192,12 +192,14 @@ layout("/layouts/platform.html"){
this.$downLoad(url, param)
},
async activityChange(val) {
const activity = this.activityList.find((o) => o.id === val)
const type = this.dict.type.TRAIN_SIGNUP_TYPE.find(o => o.code === activity.trainType)
this.trainType = type?.name || "培训班"
const resp = await this.$axios.post(loc() + "/getCourseByActivityId", { activityId: val })
this.courseList = resp.data
this.pageForm.courseId = ""
this.$nextTick(async () => {
const activity = this.activityList.find((o) => o.id === val)
const type = this.dict.type.TRAIN_SIGNUP_TYPE?.find(o => o.code === activity.trainType)
this.trainType = type?.name || "培训班"
const resp = await this.$axios.post(loc() + "/getCourseByActivityId", { activityId: val })
this.courseList = resp.data
this.pageForm.courseId = ""
})
},
async handleUser(userId) {
const resp = await $.post(loc() + "/doHandleUser", { userId })
@@ -57,8 +57,7 @@ const CLUB_MANAGER_TEMPLATE = {
<el-button type="primary" @click="managePerson.push({})" size="mini">增加</el-button>
</template>
<template slot-scope="scope">
<el-button :disabled="scope.row.roleCode === 'CLUB_PRESIDENT'
|| scope.row.roleCode === 'CLUB_SECRETARY'"
<el-button
@click="deleteRow(scope.row, scope.$index)"
size="mini" type="danger">删除
</el-button>
@@ -101,7 +101,7 @@ layout("/layouts/platform.html"){
async doHandle(type) {
let formData = {}
try {
let hz = this.$refs.clubManagerRef.managePerson.filter((o) => o.roleCode === CLUB_ROLE_CONSTANT.CLUB_PRESIDENT)
/*let hz = this.$refs.clubManagerRef.managePerson.filter((o) => o.roleCode === CLUB_ROLE_CONSTANT.CLUB_PRESIDENT)
if (hz.length !== 1) {
this.$message.warning({ title: "警告", message: "会长需要1人" })
return
@@ -110,14 +110,14 @@ layout("/layouts/platform.html"){
if (msz.length !== 1) {
this.$message.warning({ title: "警告", message: "秘书长需要1人" })
return
}
}*/
formData.sponsor = this.$refs.clubSponsorRef.sponsorData
.filter((o) => o.userId !== "" && o.userId !== undefined)
.map((o) => o.userId)
if (['onFinishTask', 'onSubmit'].includes(type) && formData.sponsor && formData.sponsor.length < 3) {
/*if (['onFinishTask', 'onSubmit'].includes(type) && formData.sponsor && formData.sponsor.length < 3) {
this.$message.warning({ title: "警告", message: "发起人要求不少于3人" })
return
}
}*/
let manageValid = false
for (const item of this.$refs.clubManagerRef.managePerson) {
if (!item.userId) {
@@ -125,10 +125,10 @@ layout("/layouts/platform.html"){
break
}
}
if (['onFinishTask', 'onSubmit'].includes(type) && (this.$refs.clubManagerRef.managePerson.length === 0 || manageValid)) {
/*if (['onFinishTask', 'onSubmit'].includes(type) && (this.$refs.clubManagerRef.managePerson.length === 0 || manageValid)) {
this.$message.warning({ title: "警告", message: "请填写理事机构信息" })
return
}
}*/
const cloneData = clone(this.$refs.clubFormRef.formData)
let array = []
if (formData.sponsor) {
@@ -31,11 +31,11 @@ const courseList = {
<el-col class="query-content">
<el-tag
:effect="pageForm.assortTypes.includes(item) ? 'dark' : 'plain'"
:key="item"
:key="index"
:type="item"
@click="tagClick('assortTypes', item)"
style="margin-right: 10px; cursor: pointer"
v-for="item in assortList"
v-for="item,index in assortList"
>
{{ item }}
</el-tag>
@@ -32,7 +32,7 @@ layout("/layouts/platform_h5.html"){
<van-tabs v-if="assortList.length > 0" type="card" color="#1867B0"
style="margin-top: 10px" @click="tabClick">
<van-tab v-for="item in assortList" :name="item" :title="item">
<van-tab v-for="item,index in assortList" :name="item" :title="item" :key="index">
</van-tab>
</van-tabs>
@@ -4,6 +4,7 @@ const times = {
`
<div>
<van-action-sheet v-model="visible" title="时间段" cancel-text="取消">
<div id="mapContainer" v-if="row?.isMobileSign === true && row?.signType === 3" style="width: 100%; height: 250px"></div>
<button v-for="(item,index) in row?.courseTimes" type="button" class="van-action-sheet__item">
<div style="display: flex; justify-content: space-between; align-items: center">
<div>
@@ -44,6 +45,10 @@ const times = {
selectCourseTime: {},
signVisible: false,
markerLayer: null,
map: null,
circle: null,
}
},
components: {
@@ -56,22 +61,140 @@ const times = {
onOpen(row) {
this.row = row
this.visible = true
this.$nextTick(() => {
if(this.row.signType === 3) {
if(this.map) this.map.destroy()
this.initMap()
this.getLocation((coords) => {
if (coords) {
const center = new TMap.LatLng(coords.lat, coords.lng)
this.markerLayer.remove(["current"])
this.createMarker(center, 'current', 'current')
}
})
}
})
},
onSign(courseTime) {
async onSign(courseTime) {
this.selectCourseTime = courseTime
if(this.row.signType === 1) {
if (this.row.signType === 1) {
this.signVisible = true
this.$nextTick(() => {
this.$refs.scanCodeRef.init()
})
}
if(this.row.signType === 2) {
if (this.row.signType === 2) {
this.makeCode()
}
if(this.row.signType === 3) {
this.$toast('此签到模式正在升级中')
if (this.row.signType === 3) {
this.getLocation((coords) => {
if (coords) {
this.$axios.post('/platform/trainSignUp/mine/positionSign', {
timeId: courseTime.id,
courseId: this.row.id,
lat: coords.lat,
lng: coords.lng
}).then(res => {
if (res.code === 0) {
this.$toast('签到成功')
this.visible = false
} else {
this.$toast(res.msg)
this.markerLayer.remove(["current"])
this.getLocation((coords) => {
if (coords) {
const center = new TMap.LatLng(coords.lat, coords.lng)
this.createMarker(center, 'current', 'current')
}
})
}
})
}
})
}
},
getLocation(callback) {
if (typeof callback !== 'function') {
callback = () => {};
}
if (!navigator.geolocation) {
this.$toast('当前浏览器不支持定位功能');
callback(null);
return;
}
navigator.geolocation.getCurrentPosition(
(position) => {
callback({
lat: position.coords.latitude,
lng: position.coords.longitude
});
},
(error) => {
let msg = '定位失败,请稍后重试';
switch (error.code) {
case error.PERMISSION_DENIED:
msg = '请允许浏览器获取位置信息';
break;
case error.POSITION_UNAVAILABLE:
msg = '无法获取当前位置';
break;
case error.TIMEOUT:
msg = '定位超时,请重试';
break;
}
this.$toast(msg);
callback(null);
},
{
enableHighAccuracy: true,
timeout: 10000,
maximumAge: 60000
}
);
},
initMap() {
if(!this.row.courseLocationCoordinates) {
this.$toast('未设置签到点')
return
}
const posi = JSON.parse(this.row.courseLocationCoordinates)
const center = new TMap.LatLng(posi[0], posi[1])
this.map = new TMap.Map('mapContainer', {
resizeEnable: true,
zoom: 16,
center: center
})
this.markerLayer = new TMap.MultiMarker({
map: this.map,
styles: {
"current": new TMap.MarkerStyle({
"src": "https://mapapi.qq.com/web/bundles/lbs-home/prod/assets/markerActive-NhH9NoBV.png",
"width": 40, // 点标记样式宽度(像素)
})
},
geometries: []
})
this.createMarker(center)
this.createCircle(center)
},
createMarker(position, styleId = 'marker', id = 'marker_' + Date.now()) {
this.markerLayer.add([
{
id: id,
position: position,
styleId: styleId
}
]);
},
createCircle(position) {
this.circle = new TMap.MultiCircle({
map: this.map,
geometries: [{
center: position,
radius: this.row.radius || 100,
}],
});
},
makeCode() {
const url = '/platform/trainSignUp/mine/passiveScan'
const data = url + '?id=' + this.selectCourseTime.id
@@ -26,7 +26,7 @@ layout("/layouts/platform_h5.html"){
<van-tabs v-if="assortList.length > 0" type="card" color="#1867B0"
style="margin-top: 10px" @click="tabClick">
<van-tab v-for="item in assortList" :name="item" :title="item">
<van-tab v-for="item,index in assortList" :name="item" :title="item" :key="index">
</van-tab>
</van-tabs>
@@ -26,7 +26,7 @@ layout("/layouts/platform_h5.html"){
<van-tabs v-if="assortList.length > 0" type="card" color="#1867B0"
style="margin-top: 10px" @click="tabClick">
<van-tab v-for="item in assortList" :name="item" :title="item">
<van-tab v-for="item,index in assortList" :name="item" :title="item" :key="index">
</van-tab>
</van-tabs>