commit
This commit is contained in:
+9
-2
@@ -37,7 +37,7 @@ public class GuildHallController {
|
||||
|
||||
@At("")
|
||||
@SaCheckPermission("guildHall.management")
|
||||
@Ok("beetl:/platform/zhgh/democratic/teachercongress/guildhall/index.html")
|
||||
@Ok("beetl:/platform/zhgh/democratic/teachercongress/guildhall/manage/index.html")
|
||||
public void index() {
|
||||
}
|
||||
|
||||
@@ -90,10 +90,17 @@ public class GuildHallController {
|
||||
return Result.success(dao.fetch(GuildHall.class, id));
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission("guildHall.management")
|
||||
@ApiOperation("查询会议厅多个")
|
||||
public Result selectList() {
|
||||
return Result.success(dao.query(GuildHall.class, Cnd.NEW()));
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission("guildHall.management")
|
||||
@ApiOperation("查询座位")
|
||||
public Result selectSeat(String hallId) {
|
||||
public Result selectSeatList(String hallId) {
|
||||
List<GuildHallSeat> list = dao.query(GuildHallSeat.class, Cnd.where(GuildHallSeat::getHallId, "=", hallId)
|
||||
.asc(GuildHallSeat::getRowNumber).asc(GuildHallSeat::getColNumber));
|
||||
|
||||
|
||||
+45
-1
@@ -1,21 +1,33 @@
|
||||
package com.budwk.app.zhgh.democratic.teachercongress.guildhall.controller;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import com.budwk.app.base.annotation.SLog;
|
||||
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.zhgh.democratic.teachercongress.guildhall.models.GuildHall;
|
||||
import com.budwk.app.zhgh.democratic.teachercongress.guildhall.models.GuildHallMeeting;
|
||||
import com.budwk.app.zhgh.democratic.teachercongress.guildhall.models.GuildHallSeat;
|
||||
import com.budwk.app.zhgh.democratic.teachercongress.guildhall.models.GuildHallSeatSelect;
|
||||
import com.budwk.app.zhgh.democratic.teachercongress.guildhall.service.GuildHallMeetingService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.nutz.aop.interceptor.ioc.TransAop;
|
||||
import org.nutz.dao.Cnd;
|
||||
import org.nutz.dao.Dao;
|
||||
import org.nutz.ioc.aop.Aop;
|
||||
import org.nutz.ioc.loader.annotation.Inject;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
import org.nutz.lang.Lang;
|
||||
import org.nutz.lang.util.NutMap;
|
||||
import org.nutz.mvc.annotation.At;
|
||||
import org.nutz.mvc.annotation.Ok;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Api("会议厅会议")
|
||||
@IocBean
|
||||
@At("/platform/guildHall/meeting")
|
||||
@@ -50,17 +62,32 @@ public class GuildHallMeetingController {
|
||||
@SaCheckPermission("guildHall.meeting")
|
||||
@SLog(tag = "会议厅会议", msg = "保存会议厅会议")
|
||||
@ApiOperation("保存会议厅会议")
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
public Result save(GuildHallMeeting meeting) {
|
||||
dao.insert(meeting);
|
||||
return Result.success();
|
||||
List<GuildHallSeat> seats = dao.query(GuildHallSeat.class, Cnd.where("hallId", "=", meeting.getHallId()));
|
||||
List<GuildHallSeatSelect> selects = BeanUtil.copyToList(seats, GuildHallSeatSelect.class);
|
||||
for (GuildHallSeatSelect select : selects) {
|
||||
select.setMeetingId(meeting.getId());
|
||||
}
|
||||
dao.insert(selects);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission("guildHall.meeting")
|
||||
@SLog(tag = "会议厅会议", msg = "修改会议厅会议")
|
||||
@ApiOperation("修改会议厅会议")
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
public Result update(GuildHallMeeting meeting) {
|
||||
dao.update(meeting);
|
||||
dao.clear(GuildHallSeatSelect.class, Cnd.where("hallId", "=", meeting.getHallId()));
|
||||
List<GuildHallSeat> seats = dao.query(GuildHallSeat.class, Cnd.where("hallId", "=", meeting.getHallId()));
|
||||
List<GuildHallSeatSelect> selects = BeanUtil.copyToList(seats, GuildHallSeatSelect.class);
|
||||
for (GuildHallSeatSelect select : selects) {
|
||||
select.setMeetingId(meeting.getId());
|
||||
}
|
||||
dao.insert(selects);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
@@ -73,4 +100,21 @@ public class GuildHallMeetingController {
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission("guildHall")
|
||||
@ApiOperation("查询会议")
|
||||
public Result selectList() {
|
||||
List<NutMap> results = new ArrayList<>();
|
||||
List<GuildHallMeeting> meetings = dao.query(GuildHallMeeting.class, Cnd.NEW().desc("startTime"));
|
||||
for (GuildHallMeeting meeting : meetings) {
|
||||
if(DateUtil.compare(DateUtil.date(), meeting.getEndTime()) > 0) {
|
||||
continue;
|
||||
}
|
||||
NutMap nutMap = Lang.obj2nutmap(meeting);
|
||||
GuildHall hall = dao.fetch(GuildHall.class, meeting.getHallId());
|
||||
nutMap.put("address", hall.getAddress());
|
||||
results.add(nutMap);
|
||||
}
|
||||
return Result.success(results);
|
||||
}
|
||||
}
|
||||
|
||||
+140
@@ -0,0 +1,140 @@
|
||||
package com.budwk.app.zhgh.democratic.teachercongress.guildhall.controller;
|
||||
|
||||
import cn.afterturn.easypoi.excel.ExcelExportUtil;
|
||||
import cn.afterturn.easypoi.excel.entity.ExportParams;
|
||||
import cn.afterturn.easypoi.excel.entity.enmus.ExcelType;
|
||||
import cn.afterturn.easypoi.excel.entity.params.ExcelExportEntity;
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
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.zhgh.democratic.teachercongress.guildhall.models.GuildHall;
|
||||
import com.budwk.app.zhgh.democratic.teachercongress.guildhall.models.GuildHallMeeting;
|
||||
import com.budwk.app.zhgh.democratic.teachercongress.guildhall.service.GuildHallService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.nutz.dao.Cnd;
|
||||
import org.nutz.dao.Dao;
|
||||
import org.nutz.dao.Sqls;
|
||||
import org.nutz.dao.sql.Sql;
|
||||
import org.nutz.ioc.loader.annotation.Inject;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
import org.nutz.lang.Lang;
|
||||
import org.nutz.lang.util.NutMap;
|
||||
import org.nutz.mvc.annotation.At;
|
||||
import org.nutz.mvc.annotation.Ok;
|
||||
import org.nutz.mvc.annotation.Param;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @ClassName GuildHallSeatSummaryController
|
||||
* @Author JyuHsin
|
||||
* @Date 2025/10/24 16:25
|
||||
* @Version 1.0
|
||||
* @Description TODO
|
||||
*/
|
||||
@Api("会议选座统计")
|
||||
@IocBean
|
||||
@At("/platform/guildHall/seatSummary")
|
||||
@Ok("json:full")
|
||||
public class GuildHallSeatSummaryController {
|
||||
|
||||
@Inject
|
||||
private Dao dao;
|
||||
@Inject
|
||||
private GuildHallService guildHallService;
|
||||
|
||||
@At("")
|
||||
@SaCheckPermission("guildHall.seatSummary")
|
||||
@Ok("beetl:/platform/zhgh/democratic/teachercongress/guildhall/seatSummary/index.html")
|
||||
public void index() {
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission("guildHall.seatSummary")
|
||||
@ApiOperation("分页查询")
|
||||
public Result pageData(PageForm pageForm,
|
||||
@Param(value = "meetingId") String meetingId) {
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT
|
||||
u.userName,
|
||||
u.loginName,
|
||||
u.unitName as unitName,
|
||||
u.unionName as unionName,
|
||||
u.mobile,
|
||||
u.sex,
|
||||
t1.rowNumber,
|
||||
t1.colNumber
|
||||
FROM
|
||||
`guild_hall_seat_select` t1
|
||||
LEFT JOIN `vw_user` u ON u.id = t1.userId
|
||||
WHERE
|
||||
t1.userId IS NOT NULL AND t1.meetingId = @meetingId
|
||||
order by t1.rowNumber ASC,t1.colNumber ASC
|
||||
""");
|
||||
sql.setParam("meetingId", meetingId);
|
||||
Pagination pagination = guildHallService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql);
|
||||
return Result.success(pagination);
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission("guildHall.seatSummary")
|
||||
@ApiOperation("查询会议")
|
||||
public Result listMeeting() {
|
||||
List<GuildHallMeeting> meetings = dao.query(GuildHallMeeting.class, Cnd.NEW().desc("startTime"));
|
||||
return Result.success(meetings);
|
||||
}
|
||||
|
||||
@At
|
||||
@Ok("void")
|
||||
@SaCheckPermission("guildHall.seatSummary")
|
||||
public void exportExcel(String meetingId, HttpServletResponse response) {
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT
|
||||
u.userName,
|
||||
u.loginName,
|
||||
u.unitName as unitName,
|
||||
u.unionName as unionName,
|
||||
u.mobile,
|
||||
u.sex,
|
||||
t1.rowNumber,
|
||||
t1.colNumber,
|
||||
CONCAT(t1.rowNumber,'排',t1.colNumber,'列') seat
|
||||
FROM
|
||||
`guild_hall_seat_select` t1
|
||||
LEFT JOIN `vw_user` u ON u.id = t1.userId
|
||||
WHERE
|
||||
t1.userId IS NOT NULL AND t1.meetingId = @meetingId
|
||||
order by t1.rowNumber ASC,t1.colNumber ASC
|
||||
""");
|
||||
sql.setParam("meetingId",meetingId);
|
||||
|
||||
List<NutMap> list = guildHallService.listMap(sql);
|
||||
|
||||
List<ExcelExportEntity> exportEntities = new ArrayList<>();
|
||||
exportEntities.add(new ExcelExportEntity("姓名", "userName", 20));
|
||||
exportEntities.add(new ExcelExportEntity("工号", "loginName", 20));
|
||||
exportEntities.add(new ExcelExportEntity("性别", "sex", 20));
|
||||
exportEntities.add(new ExcelExportEntity("单位", "unitName", 20));
|
||||
exportEntities.add(new ExcelExportEntity("分工会", "unionName", 20));
|
||||
exportEntities.add(new ExcelExportEntity("手机号", "mobile", 20));
|
||||
exportEntities.add(new ExcelExportEntity("座位", "seat", 20));
|
||||
|
||||
try {
|
||||
ExportParams exportParams = new ExportParams();
|
||||
exportParams.setSheetName("选座人员");
|
||||
exportParams.setType(ExcelType.XSSF);
|
||||
Workbook workbook = ExcelExportUtil.exportExcel(exportParams, exportEntities, list);
|
||||
CommonDownloadUtil.download("选座人员.xlsx", workbook, response);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
+97
@@ -0,0 +1,97 @@
|
||||
package com.budwk.app.zhgh.democratic.teachercongress.guildhall.controller;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import com.budwk.app.base.result.Result;
|
||||
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
|
||||
import com.budwk.app.zhgh.democratic.teachercongress.guildhall.models.GuildHallMeeting;
|
||||
import com.budwk.app.zhgh.democratic.teachercongress.guildhall.models.GuildHallSeat;
|
||||
import com.budwk.app.zhgh.democratic.teachercongress.guildhall.models.GuildHallSeatSelect;
|
||||
import com.budwk.app.zhgh.democratic.teachercongress.guildhall.service.GuildHallService;
|
||||
import io.swagger.annotations.Api;
|
||||
import org.nutz.dao.Cnd;
|
||||
import org.nutz.dao.Dao;
|
||||
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 org.nutz.mvc.annotation.Param;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @ClassName GuildHallSelectSeatController
|
||||
* @Author JyuHsin
|
||||
* @Date 2025/10/24 15:22
|
||||
* @Version 1.0
|
||||
* @Description TODO
|
||||
*/
|
||||
@Api("会议选座")
|
||||
@IocBean
|
||||
@At("/platform/guildHall/selectSeat")
|
||||
@Ok("json:full")
|
||||
public class GuildHallSelectSeatController {
|
||||
|
||||
@Inject
|
||||
private Dao dao;
|
||||
@Inject
|
||||
private GuildHallService guildHallService;
|
||||
|
||||
@At("")
|
||||
@SaCheckPermission("guildHall.selectSeat")
|
||||
@Ok("beetl:/platform/zhgh/democratic/teachercongress/guildhall/selectSeat/index.html")
|
||||
public void index() {
|
||||
}
|
||||
|
||||
@At("/h5")
|
||||
@SaCheckPermission("h5.guildHall.selectSeat")
|
||||
@Ok("beetl:/platform/zhghh5/democratic/teachercongress/guildhall/selectSeat/index.html")
|
||||
public void h5Index() {
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission("guildHall.selectSeat")
|
||||
public Result loadSeats(@Param("meetingId") String meetingId) {
|
||||
// 已选择情况
|
||||
List<GuildHallSeatSelect> selectedSeats = dao.query(GuildHallSeatSelect.class, Cnd.where("meetingId", "=", meetingId));
|
||||
|
||||
for (GuildHallSeatSelect selectedSeat : selectedSeats) {
|
||||
if (selectedSeat.getUserId() != null) {
|
||||
selectedSeat.setIsOccupied(true);
|
||||
selectedSeat.setOccupiedBy(selectedSeat.getUserId());
|
||||
selectedSeat.setIsMine(selectedSeat.getUserId().equals(SecurityUtil.getUserId()));
|
||||
} else {
|
||||
selectedSeat.setIsOccupied(false);
|
||||
selectedSeat.setIsMine(false);
|
||||
}
|
||||
}
|
||||
|
||||
// 座位排序 首先按seatRowNum 再按seatColNum
|
||||
selectedSeats.sort((o1, o2) -> {
|
||||
int compare = o1.getRowNumber().compareTo(o2.getRowNumber());
|
||||
if (compare == 0) {
|
||||
return o1.getColNumber().compareTo(o2.getColNumber());
|
||||
}
|
||||
return compare;
|
||||
});
|
||||
return Result.success(selectedSeats);
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission("guildHall.selectSeat")
|
||||
public Result doSelect(@Param("meetingId") String meetingId, Integer rowNumber, Integer colNumber) {
|
||||
GuildHallSeatSelect oldSeat = dao.fetch(GuildHallSeatSelect.class, Cnd.where("meetingId", "=", meetingId).and("userId", "=", SecurityUtil.getUserId()));
|
||||
if(oldSeat != null){
|
||||
oldSeat.setUserId(null);
|
||||
oldSeat.setSelectTime(null);
|
||||
dao.update(oldSeat);
|
||||
}
|
||||
|
||||
GuildHallSeatSelect seat = dao.fetch(GuildHallSeatSelect.class, Cnd.where("meetingId", "=", meetingId).and("rowNumber", "=", rowNumber).and("colNumber", "=", colNumber));
|
||||
seat.setUserId(SecurityUtil.getUserId());
|
||||
seat.setSelectTime(new Date());
|
||||
dao.update(seat);
|
||||
|
||||
return Result.success();
|
||||
}
|
||||
}
|
||||
+5
@@ -58,4 +58,9 @@ public class GuildHallMeeting extends BaseModel {
|
||||
@ColDefine(type = ColType.INT)
|
||||
private Integer groupId;
|
||||
|
||||
@Column
|
||||
@Comment("会厅Id")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 100)
|
||||
private String hallId;
|
||||
|
||||
}
|
||||
|
||||
+8
@@ -7,6 +7,8 @@ import lombok.experimental.Accessors;
|
||||
import org.nutz.dao.entity.annotation.*;
|
||||
import org.nutz.dao.interceptor.annotation.PrevInsert;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Table("guild_hall_seat")
|
||||
@@ -39,9 +41,15 @@ public class GuildHallSeat extends BaseModel {
|
||||
@ColDefine(type = ColType.INT)
|
||||
private Integer colNumber;
|
||||
|
||||
@Column
|
||||
@Comment("座位编号")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||
private String seatNumber;
|
||||
|
||||
@Column
|
||||
@Comment("是否启用")
|
||||
@ColDefine(type = ColType.BOOLEAN)
|
||||
@Default("1")
|
||||
private Boolean enable;
|
||||
|
||||
}
|
||||
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
package com.budwk.app.zhgh.democratic.teachercongress.guildhall.models;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.nutz.dao.entity.annotation.*;
|
||||
import org.nutz.dao.interceptor.annotation.PrevInsert;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* @ClassName GuildHallSeatSelect
|
||||
* @Author JyuHsin
|
||||
* @Date 2025/10/24 15:55
|
||||
* @Version 1.0
|
||||
* @Description TODO
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Table("guild_hall_seat_select")
|
||||
@TableMeta("{'mysql-charset':'utf8mb4'}")
|
||||
@Comment("会议厅座位")
|
||||
@Accessors(chain = true)
|
||||
@TableIndexes(value = {
|
||||
@Index(name = "INDEX_GUILD_HALL_SEAT_HALL_ID", fields = "hallId",unique = false)
|
||||
})
|
||||
public class GuildHallSeatSelect extends GuildHallSeat{
|
||||
|
||||
@Name
|
||||
@PrevInsert(uu32 = true)
|
||||
@Comment("ID")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||
private String id;
|
||||
|
||||
@Column
|
||||
@Comment("会议id")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||
private String meetingId;
|
||||
|
||||
@Column
|
||||
@Comment("用户id")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||
private String userId;
|
||||
|
||||
@Column
|
||||
@Comment("选座时间")
|
||||
@ColDefine(type = ColType.DATETIME)
|
||||
private Date selectTime;
|
||||
|
||||
private Boolean isOccupied;
|
||||
private String occupiedBy;
|
||||
private Boolean isMine;
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 10 KiB |
@@ -48,6 +48,7 @@ module.exports = {
|
||||
<el-select placeholder="参加人员范围"
|
||||
v-model="internalGroupId"
|
||||
clearable
|
||||
style="width: 100%"
|
||||
filterable>
|
||||
<el-option v-for="item in groupOptions"
|
||||
:label="item.groupName"
|
||||
@@ -55,7 +56,7 @@ module.exports = {
|
||||
:key="item.groupId"
|
||||
></el-option>
|
||||
</el-select>
|
||||
<el-button @click="$refs.drawerUserScope.userScopeDialog = true" type="primary" icon="el-icon-setting">设置
|
||||
<el-button @click="$refs.drawerUserScope.userScopeDialog = true" type="primary" icon="el-icon-setting" class="ml10">设置
|
||||
</el-button>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -8,10 +8,11 @@ const jcdt = {
|
||||
<div class="jcdt-content">
|
||||
<div class="jcdt-list">
|
||||
<div class="jcdt-item" v-for="item in list" :key="item.title" @click="onLink(item)">
|
||||
<div class="date">{{item.date}}</div>
|
||||
<div class="date" v-if="item.date">{{item.date}}</div>
|
||||
<div class="title">{{item.title}}</div>
|
||||
<div class="image">
|
||||
<img :src="item.image" alt="">
|
||||
<img v-if="item.image" :src="item.image" alt="">
|
||||
<img v-else src="/assets/platform/img/v4/not-image.png" alt="">
|
||||
</div>
|
||||
<div class="summary">{{item.summary}}</div>
|
||||
</div>
|
||||
@@ -38,7 +39,7 @@ const jcdt = {
|
||||
style: /*language=CSS*/ `
|
||||
.jcdt-wrapper {
|
||||
width: 100%;
|
||||
background-image: url(https://cdgh.ncu.edu.cn/images/index_bg2.png);
|
||||
background-image: url(/assets/platform/img/v4/home-bg.png);
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
|
||||
@@ -32,7 +32,7 @@ layout("/layouts/platform.html"){
|
||||
</search-item>
|
||||
<search-item label="场地类型">
|
||||
<el-select v-model="pageForm.siteType" @change="doSearch" style="width: 100%"
|
||||
placeholder="请选择慰问类型" filterable clearable>
|
||||
placeholder="请选择场地类型" filterable clearable>
|
||||
<el-option v-for="item in typeOptions"
|
||||
:value="item.id"
|
||||
:key="item.id"
|
||||
|
||||
@@ -33,7 +33,7 @@ layout("/layouts/platform.html"){
|
||||
</search-item>
|
||||
<search-item label="场地类型">
|
||||
<el-select v-model="pageForm.siteType" @change="doSearch" style="width: 100%"
|
||||
placeholder="请选择慰问类型" filterable clearable>
|
||||
placeholder="请选择场地类型" filterable clearable>
|
||||
<el-option v-for="item in typeOptions"
|
||||
:value="item.id"
|
||||
:key="item.id"
|
||||
|
||||
+1
-1
@@ -34,7 +34,7 @@ layout("/layouts/platform.html"){
|
||||
</search-item>
|
||||
<search-item label="场地类型">
|
||||
<el-select v-model="pageForm.siteType" @change="doSearch" style="width: 100%"
|
||||
placeholder="请选择慰问类型" filterable clearable>
|
||||
placeholder="请选择场地类型" filterable clearable>
|
||||
<el-option v-for="item in typeOptions"
|
||||
:value="item.id"
|
||||
:key="item.id"
|
||||
|
||||
+1
-1
@@ -123,7 +123,7 @@ const seat = {
|
||||
|
||||
loadSeats() {
|
||||
// 加载现有座位数据
|
||||
this.$axios.post('/platform/guildHall/selectSeat', {hallId: this.row.id}).then(res => {
|
||||
this.$axios.post('/platform/guildHall/selectSeatList', {hallId: this.row.id}).then(res => {
|
||||
if (res.code === 0 && res.data && res.data.length > 0) {
|
||||
this.seats = res.data
|
||||
// 根据现有数据计算行列数
|
||||
+24
-12
@@ -9,7 +9,7 @@ layout("/layouts/platform.html"){
|
||||
<el-input placeholder="请输入名称" clearable v-model="pageForm.searchKeyword"></el-input>
|
||||
</search-item>
|
||||
<search-item label="年度">
|
||||
<el-date-picker v-model="pageForm.year" type="year" placeholder="请选择年度"></el-date-picker>
|
||||
<el-date-picker v-model="pageForm.year" type="year" placeholder="请选择年度" style="width: 100%;"></el-date-picker>
|
||||
</search-item>
|
||||
</search>
|
||||
</el-card>
|
||||
@@ -31,6 +31,7 @@ layout("/layouts/platform.html"){
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!--#include("/layouts/pagination.html"){}#-->
|
||||
</el-card>
|
||||
|
||||
<el-dialog :title="formData.id ? '编辑' : '新增'" :visible.sync="dialogVisible" width="70%">
|
||||
@@ -40,7 +41,7 @@ layout("/layouts/platform.html"){
|
||||
</el-form-item>
|
||||
<el-form-item label="年度" prop="year">
|
||||
<el-date-picker v-model="formData.year" type="year" value-format="yyyy"
|
||||
placeholder="选择年度"></el-date-picker>
|
||||
placeholder="选择年度" style="width: 100%;"></el-date-picker>
|
||||
</el-form-item>
|
||||
<el-form-item label="开始时间" prop="startTime">
|
||||
<el-date-picker
|
||||
@@ -60,6 +61,11 @@ layout("/layouts/platform.html"){
|
||||
style="width: 100%;">
|
||||
</el-date-picker>
|
||||
</el-form-item>
|
||||
<el-form-item label="会厅选择" prop="hallId">
|
||||
<el-select v-model="formData.hallId" placeholder="请选择会厅" style="width: 100%">
|
||||
<el-option v-for="item in hallList" :key="item.id" :label="item.name" :value="item.id"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="内容" prop="content">
|
||||
<text-editor v-model="formData.content"></text-editor>
|
||||
</el-form-item>
|
||||
@@ -83,12 +89,14 @@ layout("/layouts/platform.html"){
|
||||
return {
|
||||
dialogVisible: false,
|
||||
formRules: {
|
||||
name: [{required: true, message: '请输入名称', trigger: 'blur'}],
|
||||
year: [{required: true, message: '请选择年度', trigger: 'change'}],
|
||||
startTime: [{required: true, message: '请选择开始时间', trigger: 'change'}],
|
||||
endTime: [{required: true, message: '请选择结束时间', trigger: 'change'}],
|
||||
content: [{required: true, message: '请输入内容', trigger: 'blur'}]
|
||||
}
|
||||
name: [{required: true, message: '必填', trigger: 'blur'}],
|
||||
year: [{required: true, message: '必填', trigger: 'change'}],
|
||||
startTime: [{required: true, message: '必填', trigger: 'change'}],
|
||||
endTime: [{required: true, message: '必填', trigger: 'change'}],
|
||||
hallId: [{required: true, message: '必填', trigger: 'blur'}],
|
||||
content: [{required: true, message: '必填', trigger: 'blur'}],
|
||||
},
|
||||
hallList: [],
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
@@ -106,6 +114,7 @@ layout("/layouts/platform.html"){
|
||||
},
|
||||
onEdit(row) {
|
||||
this.dialogVisible = true;
|
||||
row.year = row.year.toString()
|
||||
this.formData = {...row}
|
||||
},
|
||||
onSave() {
|
||||
@@ -139,13 +148,16 @@ layout("/layouts/platform.html"){
|
||||
this.$message.success(res.msg)
|
||||
})
|
||||
})
|
||||
}
|
||||
},
|
||||
selectList() {
|
||||
this.$axios.post('/platform/guildHall/selectList').then(res => {
|
||||
this.hallList = res.data
|
||||
})
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.selectList();
|
||||
this.doSearch();
|
||||
setTimeout(() => {
|
||||
console.log(this.$refs.tableRef.columns)
|
||||
},2000)
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
+81
@@ -0,0 +1,81 @@
|
||||
<!--#
|
||||
layout("/layouts/platform.html"){
|
||||
#-->
|
||||
<style>
|
||||
|
||||
</style>
|
||||
|
||||
<div id="app" v-cloak>
|
||||
<guava>
|
||||
<el-card shadow="never">
|
||||
<search @search="doSearch">
|
||||
<search-item label="会议">
|
||||
<el-select clearable v-model="pageForm.meetingId" filterable placeholder="请选择会议">
|
||||
<el-option
|
||||
v-for="item in meetings"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="item.id">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</search-item>
|
||||
</search>
|
||||
</el-card>
|
||||
<el-card shadow="never" class="mt20">
|
||||
<table-tool label="选座人员">
|
||||
<el-button size="small" type="primary" @click="exportExcel">导出选座人员</el-button>
|
||||
</table-tool>
|
||||
<el-table :data="tableData" @sort-change='pageOrder'>
|
||||
<el-table-column type="index" width="50px" label="序号" :index="indexMethod"></el-table-column>
|
||||
<el-table-column align="center" header-align="center" label="姓名" prop="userName"></el-table-column>
|
||||
<el-table-column align="center" header-align="center" label="工号" prop="loginName"></el-table-column>
|
||||
<el-table-column align="center" header-align="center" label="性别" prop="sex"></el-table-column>
|
||||
<el-table-column align="center" header-align="center" label="所属单位" prop="unitName"></el-table-column>
|
||||
<el-table-column align="center" header-align="center" label="所属工会" prop="unionName"></el-table-column>
|
||||
<el-table-column align="center" header-align="center" label="联系方式" prop="mobile"></el-table-column>
|
||||
<el-table-column align="center" header-align="center" label="座位" prop="seat">
|
||||
<template scope="{row}">
|
||||
{{row.rowNumber + '排' + row.colNumber + '列'}}
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!--#include("/layouts/pagination.html"){}#-->
|
||||
</el-card>
|
||||
</guava>
|
||||
</div>
|
||||
<script>
|
||||
let vue = new Vue({
|
||||
el: '#app',
|
||||
mixins: [initTableMixins],
|
||||
data() {
|
||||
return {
|
||||
meetings: []
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 加载会议列表
|
||||
loadMeetings() {
|
||||
$.post('/platform/guildHall/seatSummary/listMeeting').then(res => {
|
||||
if (res.code === 0) {
|
||||
this.meetings = res.data
|
||||
if (this.meetings.length > 0) {
|
||||
this.pageForm.meetingId = this.meetings[0].id
|
||||
}
|
||||
this.pageData()
|
||||
}
|
||||
})
|
||||
},
|
||||
exportExcel() {
|
||||
this.$downLoad(loc() + "/exportExcel", {
|
||||
meetingId: this.pageForm.meetingId
|
||||
})
|
||||
}
|
||||
},
|
||||
async created() {
|
||||
this.loadMeetings()
|
||||
}
|
||||
})
|
||||
</script>
|
||||
<!--#
|
||||
}
|
||||
#-->
|
||||
+837
@@ -0,0 +1,837 @@
|
||||
<!--#
|
||||
layout("/layouts/platform.html"){
|
||||
#-->
|
||||
|
||||
<style>
|
||||
.container-seat {
|
||||
margin: 0 auto;
|
||||
background: white;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.header-seat {
|
||||
background-color: #ffffff;
|
||||
color: #000000;
|
||||
padding: 10px 20px;
|
||||
border-bottom: 1px solid #ddd;
|
||||
}
|
||||
|
||||
.header-seat h1 {
|
||||
font-size: 24px;
|
||||
margin-bottom: 5px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.header-seat p {
|
||||
opacity: 0.9;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.main-content-seat {
|
||||
display: flex;
|
||||
min-height: calc(100vh - 80px);
|
||||
}
|
||||
|
||||
.seat-area {
|
||||
flex: 1;
|
||||
padding: 30px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.stage {
|
||||
text-align: center;
|
||||
padding: 15px;
|
||||
background-color: #1867b0;
|
||||
color: white;
|
||||
margin-bottom: 30px;
|
||||
border-radius: 4px;
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.legend {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 20px;
|
||||
margin-bottom: 30px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.legend-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.legend-seat-svg {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
.seat-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(10, 1fr);
|
||||
gap: 8px;
|
||||
margin: 0 auto;
|
||||
padding: 20px;
|
||||
background-color: #fafafa;
|
||||
border-radius: 8px;
|
||||
border: 1px solid #e0e0e0;
|
||||
width: fit-content;
|
||||
justify-self: center;
|
||||
}
|
||||
|
||||
.seat {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
border-radius: 4px;
|
||||
border: 1px solid transparent;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 10px;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.seat-icon {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
|
||||
.seat-number {
|
||||
font-size: 10px;
|
||||
font-weight: 600;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.seat-back, .seat-cushion, .seat-armrest {
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.seat.available .seat-back {
|
||||
fill: #f8f9fa;
|
||||
stroke: #dee2e6;
|
||||
stroke-width: 1;
|
||||
}
|
||||
.seat.available .seat-cushion {
|
||||
fill: #ffffff;
|
||||
stroke: #dee2e6;
|
||||
stroke-width: 1;
|
||||
}
|
||||
.seat.available .seat-armrest {
|
||||
fill: #e9ecef;
|
||||
stroke: #dee2e6;
|
||||
stroke-width: 1;
|
||||
}
|
||||
.seat.available .seat-number {
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.seat.available:hover .seat-back {
|
||||
fill: #e3f2fd;
|
||||
stroke: #1867b0;
|
||||
}
|
||||
.seat.available:hover .seat-cushion {
|
||||
fill: #f0f8ff;
|
||||
stroke: #1867b0;
|
||||
}
|
||||
.seat.available:hover .seat-armrest {
|
||||
fill: #e3f2fd;
|
||||
stroke: #1867b0;
|
||||
}
|
||||
.seat.available:hover .seat-number {
|
||||
color: #1867b0;
|
||||
}
|
||||
|
||||
.seat.occupied .seat-back {
|
||||
fill: #adb5bd;
|
||||
stroke: #6c757d;
|
||||
stroke-width: 1;
|
||||
}
|
||||
.seat.occupied .seat-cushion {
|
||||
fill: #d0d0d0;
|
||||
stroke: #6c757d;
|
||||
stroke-width: 1;
|
||||
}
|
||||
.seat.occupied .seat-armrest {
|
||||
fill: #adb5bd;
|
||||
stroke: #6c757d;
|
||||
stroke-width: 1;
|
||||
}
|
||||
.seat.occupied .seat-number {
|
||||
color: #666;
|
||||
}
|
||||
.seat.occupied {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.seat.selected .seat-back {
|
||||
fill: #0d47a1;
|
||||
stroke: #1867b0;
|
||||
stroke-width: 2;
|
||||
}
|
||||
.seat.selected .seat-cushion {
|
||||
fill: #1867b0;
|
||||
stroke: #0d47a1;
|
||||
stroke-width: 2;
|
||||
}
|
||||
.seat.selected .seat-armrest {
|
||||
fill: #0d47a1;
|
||||
stroke: #1867b0;
|
||||
stroke-width: 2;
|
||||
}
|
||||
.seat.selected .seat-number {
|
||||
/*color: white;*/
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.seat.my-seat .seat-back {
|
||||
fill: #c62828;
|
||||
stroke: #ff3742;
|
||||
stroke-width: 2;
|
||||
}
|
||||
.seat.my-seat .seat-cushion {
|
||||
fill: #ff4757;
|
||||
stroke: #c62828;
|
||||
stroke-width: 2;
|
||||
}
|
||||
.seat.my-seat .seat-armrest {
|
||||
fill: #c62828;
|
||||
stroke: #ff3742;
|
||||
stroke-width: 2;
|
||||
}
|
||||
.seat.my-seat .seat-number {
|
||||
/*color: white;*/
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.seat.disabled .seat-back {
|
||||
fill: #f5f5f5;
|
||||
stroke: #cccccc;
|
||||
stroke-width: 1;
|
||||
}
|
||||
.seat.disabled .seat-cushion {
|
||||
fill: #f0f0f0;
|
||||
stroke: #cccccc;
|
||||
stroke-width: 1;
|
||||
}
|
||||
.seat.disabled .seat-armrest {
|
||||
fill: #f5f5f5;
|
||||
stroke: #cccccc;
|
||||
stroke-width: 1;
|
||||
}
|
||||
.seat.disabled .seat-number {
|
||||
color: #999;
|
||||
}
|
||||
.seat.disabled {
|
||||
cursor: not-allowed;
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.sidebar-seat {
|
||||
width: 300px;
|
||||
background-color: #fafafa;
|
||||
border-left: 1px solid #e0e0e0;
|
||||
}
|
||||
|
||||
.section {
|
||||
background: white;
|
||||
padding: 20px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.section h3 {
|
||||
color: #333;
|
||||
margin-bottom: 15px;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.form-group {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.form-group label {
|
||||
display: block;
|
||||
margin-bottom: 5px;
|
||||
color: #555;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.form-group input {
|
||||
width: 100%;
|
||||
padding: 8px 12px;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 4px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.form-group input:focus {
|
||||
outline: none;
|
||||
border-color: #1867b0;
|
||||
}
|
||||
|
||||
.btn {
|
||||
width: 100%;
|
||||
padding: 10px;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
font-size: 14px;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.2s ease;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
background-color: #1867b0;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.btn-primary:hover:not(:disabled) {
|
||||
background-color: #155a8a;
|
||||
}
|
||||
|
||||
.btn-secondary {
|
||||
background-color: #6c757d;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.btn-secondary:hover:not(:disabled) {
|
||||
background-color: #5a6268;
|
||||
}
|
||||
|
||||
.btn:disabled {
|
||||
opacity: 0.6;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.my-booking {
|
||||
padding: 15px;
|
||||
background-color: #f8f9fa;
|
||||
border-radius: 4px;
|
||||
border-left: 3px solid #1867b0;
|
||||
}
|
||||
|
||||
.my-booking p {
|
||||
margin-bottom: 8px;
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.my-booking strong {
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.alert {
|
||||
padding: 12px;
|
||||
border-radius: 4px;
|
||||
margin-bottom: 15px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.alert-success {
|
||||
background-color: #d4edda;
|
||||
color: #155724;
|
||||
border: 1px solid #c3e6cb;
|
||||
}
|
||||
|
||||
.alert-error {
|
||||
background-color: #f8d7da;
|
||||
color: #721c24;
|
||||
border: 1px solid #f5c6cb;
|
||||
}
|
||||
|
||||
.loading {
|
||||
text-align: center;
|
||||
padding: 50px;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.main-content-seat {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.sidebar-seat {
|
||||
width: 100%;
|
||||
border-left: none;
|
||||
border-top: 1px solid #e0e0e0;
|
||||
}
|
||||
|
||||
.seat-grid {
|
||||
gap: 6px;
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
.seat {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
.header-seat {
|
||||
padding: 15px 20px;
|
||||
}
|
||||
|
||||
.seat-area, .sidebar-seat {
|
||||
padding: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
/* 会议选择弹窗样式 */
|
||||
.meeting-modal {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
.meeting-modal-content {
|
||||
background: white;
|
||||
border-radius: 8px;
|
||||
padding: 30px;
|
||||
max-width: 600px;
|
||||
width: 90%;
|
||||
max-height: 80vh;
|
||||
overflow-y: auto;
|
||||
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
.meeting-modal h2 {
|
||||
color: #333;
|
||||
margin-bottom: 20px;
|
||||
font-size: 20px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.meeting-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 15px;
|
||||
}
|
||||
|
||||
.meeting-item {
|
||||
border: 2px solid #e0e0e0;
|
||||
border-radius: 8px;
|
||||
padding: 20px;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
background: #fafafa;
|
||||
}
|
||||
|
||||
.meeting-item:hover {
|
||||
border-color: #1867b0;
|
||||
background: #f0f8ff;
|
||||
}
|
||||
|
||||
.meeting-item.selected {
|
||||
border-color: #1867b0;
|
||||
background: #e8f4fd;
|
||||
}
|
||||
|
||||
.meeting-name {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.meeting-info {
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.meeting-time {
|
||||
font-size: 13px;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.modal-buttons {
|
||||
display: flex;
|
||||
gap: 15px;
|
||||
margin-top: 25px;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.modal-btn {
|
||||
padding: 10px 25px;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
font-size: 14px;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.2s ease;
|
||||
}
|
||||
|
||||
.modal-btn-primary {
|
||||
background-color: #1867b0;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.modal-btn-primary:hover:not(:disabled) {
|
||||
background-color: #155a8a;
|
||||
}
|
||||
|
||||
.modal-btn-secondary {
|
||||
background-color: #6c757d;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.modal-btn-secondary:hover:not(:disabled) {
|
||||
background-color: #5a6268;
|
||||
}
|
||||
|
||||
.modal-btn:disabled {
|
||||
opacity: 0.6;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div id="app" v-cloak>
|
||||
<guava>
|
||||
<!-- 会议选择弹窗 -->
|
||||
<div v-if="showMeetingModal" class="meeting-modal">
|
||||
<div class="meeting-modal-content">
|
||||
<h2>请选择会议</h2>
|
||||
<div class="meeting-list">
|
||||
<div
|
||||
v-for="meeting in meetings"
|
||||
:key="meeting.id"
|
||||
:class="['meeting-item', { selected: selectedMeetingId === meeting.id }]"
|
||||
@click="selectMeeting(meeting)"
|
||||
>
|
||||
<div class="meeting-name">{{ meeting.name }}</div>
|
||||
<div class="meeting-info">地点:{{ meeting.address }}</div>
|
||||
<div class="meeting-time">时间:{{ meeting.startTime }} 至 {{ meeting.endTime }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-buttons">
|
||||
<button
|
||||
class="modal-btn"
|
||||
@click="showMeetingModal = false"
|
||||
>
|
||||
取消选择
|
||||
</button>
|
||||
<button
|
||||
class="modal-btn modal-btn-primary"
|
||||
@click="confirmMeetingSelection"
|
||||
:disabled="!selectedMeetingId"
|
||||
>
|
||||
确认选择
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container-seat">
|
||||
<div class="header-seat" v-if="meeting">
|
||||
<h1>{{ meeting.name }}</h1>
|
||||
<p>{{ meeting.startTime + ' 至 ' + meeting.endTime}}</p>
|
||||
</div>
|
||||
|
||||
<div class="main-content-seat">
|
||||
<div class="seat-area">
|
||||
<!-- <div class="stage">主席台</div>-->
|
||||
|
||||
<div class="legend">
|
||||
<div class="legend-item">
|
||||
<svg class="legend-seat-svg" viewBox="0 0 50 50" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect x="8" y="5" width="34" height="20" rx="3" ry="3" fill="#f8f9fa" stroke="#dee2e6" stroke-width="1"/>
|
||||
<rect x="5" y="22" width="40" height="18" rx="4" ry="4" fill="#ffffff" stroke="#dee2e6" stroke-width="1"/>
|
||||
<rect x="2" y="20" width="6" height="15" rx="2" ry="2" fill="#e9ecef" stroke="#dee2e6" stroke-width="1"/>
|
||||
<rect x="42" y="20" width="6" height="15" rx="2" ry="2" fill="#e9ecef" stroke="#dee2e6" stroke-width="1"/>
|
||||
</svg>
|
||||
<span>可选座位</span>
|
||||
</div>
|
||||
<div class="legend-item">
|
||||
<svg class="legend-seat-svg" viewBox="0 0 50 50" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect x="8" y="5" width="34" height="20" rx="3" ry="3" fill="#adb5bd" stroke="#6c757d" stroke-width="1"/>
|
||||
<rect x="5" y="22" width="40" height="18" rx="4" ry="4" fill="#d0d0d0" stroke="#6c757d" stroke-width="1"/>
|
||||
<rect x="2" y="20" width="6" height="15" rx="2" ry="2" fill="#adb5bd" stroke="#6c757d" stroke-width="1"/>
|
||||
<rect x="42" y="20" width="6" height="15" rx="2" ry="2" fill="#adb5bd" stroke="#6c757d" stroke-width="1"/>
|
||||
</svg>
|
||||
<span>已被占用</span>
|
||||
</div>
|
||||
<div class="legend-item">
|
||||
<svg class="legend-seat-svg" viewBox="0 0 50 50" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect x="8" y="5" width="34" height="20" rx="3" ry="3" fill="#0d47a1" stroke="#1867b0" stroke-width="2"/>
|
||||
<rect x="5" y="22" width="40" height="18" rx="4" ry="4" fill="#1867b0" stroke="#0d47a1" stroke-width="2"/>
|
||||
<rect x="2" y="20" width="6" height="15" rx="2" ry="2" fill="#0d47a1" stroke="#1867b0" stroke-width="2"/>
|
||||
<rect x="42" y="20" width="6" height="15" rx="2" ry="2" fill="#0d47a1" stroke="#1867b0" stroke-width="2"/>
|
||||
</svg>
|
||||
<span>当前选择</span>
|
||||
</div>
|
||||
<div class="legend-item">
|
||||
<svg class="legend-seat-svg" viewBox="0 0 50 50" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect x="8" y="5" width="34" height="20" rx="3" ry="3" fill="#c62828" stroke="#ff3742" stroke-width="2"/>
|
||||
<rect x="5" y="22" width="40" height="18" rx="4" ry="4" fill="#ff4757" stroke="#c62828" stroke-width="2"/>
|
||||
<rect x="2" y="20" width="6" height="15" rx="2" ry="2" fill="#c62828" stroke="#ff3742" stroke-width="2"/>
|
||||
<rect x="42" y="20" width="6" height="15" rx="2" ry="2" fill="#c62828" stroke="#ff3742" stroke-width="2"/>
|
||||
</svg>
|
||||
<span>我的座位</span>
|
||||
</div>
|
||||
<div class="legend-item">
|
||||
<svg class="legend-seat-svg" viewBox="0 0 50 50" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect x="8" y="5" width="34" height="20" rx="3" ry="3" fill="#f5f5f5" stroke="#cccccc" stroke-width="1"/>
|
||||
<rect x="5" y="22" width="40" height="18" rx="4" ry="4" fill="#f0f0f0" stroke="#cccccc" stroke-width="1"/>
|
||||
<rect x="2" y="20" width="6" height="15" rx="2" ry="2" fill="#f5f5f5" stroke="#cccccc" stroke-width="1"/>
|
||||
<rect x="42" y="20" width="6" height="15" rx="2" ry="2" fill="#f5f5f5" stroke="#cccccc" stroke-width="1"/>
|
||||
</svg>
|
||||
<span>禁用座位</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="loading" class="loading">
|
||||
<p>正在加载座位信息...</p>
|
||||
</div>
|
||||
|
||||
<div v-else class="seat-grid" :style="gridStyle">
|
||||
<div
|
||||
v-for="seat in seats"
|
||||
:key="seat.id"
|
||||
:class="getSeatClass(seat)"
|
||||
class="seat"
|
||||
@click="selectSeat(seat)"
|
||||
:title="getSeatTitle(seat)"
|
||||
>
|
||||
<svg class="seat-icon" viewBox="0 0 50 50" xmlns="http://www.w3.org/2000/svg">
|
||||
<!-- 座位靠背 -->
|
||||
<rect x="8" y="5" width="34" height="20" rx="3" ry="3" class="seat-back"/>
|
||||
<!-- 座位坐垫 -->
|
||||
<rect x="5" y="22" width="40" height="18" rx="4" ry="4" class="seat-cushion"/>
|
||||
<!-- 扶手 -->
|
||||
<rect x="2" y="20" width="6" height="15" rx="2" ry="2" class="seat-armrest"/>
|
||||
<rect x="42" y="20" width="6" height="15" rx="2" ry="2" class="seat-armrest"/>
|
||||
</svg>
|
||||
<span class="seat-number">{{ seat.rowNumber }}-{{ seat.colNumber }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="sidebar-seat">
|
||||
<div class="section">
|
||||
<h3>操作列</h3>
|
||||
<button
|
||||
class="btn btn-primary mt10"
|
||||
@click="showMeetingModal = true"
|
||||
>
|
||||
切换会议
|
||||
</button>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h3>座位选择</h3>
|
||||
|
||||
<div v-if="selectedSeat" class="my-booking" style="border-left-color: #28a745;">
|
||||
<p><strong>选中座位:</strong> {{ selectedSeat.seatNumber }}</p>
|
||||
<p><strong>位置:</strong> 第{{ selectedSeat.rowNumber }}排第{{ selectedSeat.colNumber }}列</p>
|
||||
</div>
|
||||
<div v-else class="my-booking">
|
||||
<p style="color: #999;">请点击座位进行选择</p>
|
||||
</div>
|
||||
|
||||
<div v-if="alertMessage" :class="'alert alert-' + alertType">
|
||||
{{ alertMessage }}
|
||||
</div>
|
||||
|
||||
<button
|
||||
class="btn btn-primary mt10"
|
||||
@click="confirmSelection"
|
||||
:disabled="!selectedSeat || submitting"
|
||||
>
|
||||
{{ submitting ? '提交中...' : '提交选座' }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="section">
|
||||
<h3>我的座位</h3>
|
||||
<div v-if="myCurrentSeat" class="my-booking">
|
||||
<p><strong>座位号:</strong> {{ myCurrentSeat.rowNumber }}-{{ myCurrentSeat.colNumber }} </p>
|
||||
<p><strong>位置:</strong> 第{{ myCurrentSeat.rowNumber }}排第{{ myCurrentSeat.colNumber }}列</p>
|
||||
<p><strong>选择时间:</strong> {{ formatTime(myCurrentSeat.selectTime) }}</p>
|
||||
</div>
|
||||
<div v-else class="my-booking">
|
||||
<p style="color: #999;">暂未选择座位</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</guava>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
new Vue({
|
||||
el: '#app',
|
||||
data() {
|
||||
return {
|
||||
meetings: [], // 会议列表
|
||||
selectedMeetingId: null, // 选中的会议ID
|
||||
showMeetingModal: true, // 显示会议选择弹窗
|
||||
meeting: null,
|
||||
seats: [],
|
||||
selectedSeat: null,
|
||||
myCurrentSeat: null,
|
||||
loading: false,
|
||||
submitting: false,
|
||||
alertMessage: '',
|
||||
alertType: 'success',
|
||||
seatConfig: {
|
||||
rows: 8,
|
||||
cols: 12
|
||||
},
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.loadMeetings();
|
||||
},
|
||||
computed: {
|
||||
gridStyle() {
|
||||
return {
|
||||
'grid-template-columns': 'repeat(' + this.seatConfig.cols + ', 1fr)'
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 加载会议列表
|
||||
loadMeetings() {
|
||||
$.post('/platform/guildHall/meeting/selectList').then(res => {
|
||||
if (res.code === 0) {
|
||||
this.meetings = res.data
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
// 选择会议
|
||||
selectMeeting(meeting) {
|
||||
this.selectedMeetingId = meeting.id;
|
||||
},
|
||||
|
||||
// 确认会议选择
|
||||
confirmMeetingSelection() {
|
||||
if (!this.selectedMeetingId) {
|
||||
this.$message.error('请选择一个会议');
|
||||
return;
|
||||
}
|
||||
|
||||
const selectedMeeting = this.meetings.find(m => m.id === this.selectedMeetingId);
|
||||
if (selectedMeeting) {
|
||||
this.meeting = selectedMeeting
|
||||
this.loadSeats();
|
||||
}
|
||||
},
|
||||
|
||||
// 查询选座情况
|
||||
async loadSeats() {
|
||||
if (!this.meeting.id) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.loading = true;
|
||||
|
||||
const {code,data,msg} = await $.post('/platform/guildHall/selectSeat/loadSeats', {meetingId: this.meeting.id})
|
||||
if (code === 0) {
|
||||
if(data.length === 0) {
|
||||
this.$message.warning('该会议暂未设置座位')
|
||||
return
|
||||
}
|
||||
this.seats = data;
|
||||
this.myCurrentSeat = this.seats.find(seat => seat.isMine);
|
||||
// 根据现有数据计算行列数
|
||||
const maxRow = Math.max(...this.seats.map(s => parseInt(s.rowNumber)))
|
||||
const maxCol = Math.max(...this.seats.map(s => parseInt(s.colNumber)))
|
||||
this.seatConfig.rows = maxRow
|
||||
this.seatConfig.cols = maxCol
|
||||
}
|
||||
|
||||
this.loading = false
|
||||
this.showMeetingModal = false;
|
||||
},
|
||||
|
||||
selectSeat(seat) {
|
||||
if (!seat.enable) {
|
||||
this.$message.error('该座位已被禁用');
|
||||
return;
|
||||
}
|
||||
|
||||
if (seat.isOccupied && !seat.isMine) {
|
||||
this.$message.error('该座位已被占用');
|
||||
return;
|
||||
}
|
||||
|
||||
if (seat.isMine) {
|
||||
this.$message.success('这是您当前的座位');
|
||||
return;
|
||||
}
|
||||
|
||||
this.selectedSeat = seat;
|
||||
this.$set(this.selectedSeat, 'seatNumber', seat.rowNumber + '-' + seat.colNumber)
|
||||
},
|
||||
|
||||
async confirmSelection() {
|
||||
if (!this.selectedSeat) {
|
||||
this.$message.error('请先选择座位');
|
||||
return;
|
||||
}
|
||||
this.submitting = true;
|
||||
const {code,data,msg} = await $.post('/platform/guildHall/selectSeat/doSelect', {
|
||||
meetingId: this.meeting.id,
|
||||
seatNumber: this.selectedSeat.seatNumber,
|
||||
rowNumber: this.selectedSeat.rowNumber,
|
||||
colNumber: this.selectedSeat.colNumber
|
||||
})
|
||||
this.submitting = false
|
||||
|
||||
if (code === 0) {
|
||||
this.$message.success("选座成功")
|
||||
this.loadSeats();
|
||||
}
|
||||
},
|
||||
|
||||
getSeatClass(seat) {
|
||||
if (!seat.enable) return 'disabled';
|
||||
if (seat.isMine) return 'my-seat';
|
||||
if (seat === this.selectedSeat) return 'selected';
|
||||
if (seat.isOccupied) return 'occupied';
|
||||
return 'available';
|
||||
},
|
||||
|
||||
getSeatTitle(seat) {
|
||||
if (seat.isMine) return '我的座位';
|
||||
if (seat === this.selectedSeat) return '当前选择';
|
||||
if (seat.status === 1) return '已被占用';
|
||||
return '点击选择此座位';
|
||||
},
|
||||
|
||||
formatTime(time) {
|
||||
if (!time) return '';
|
||||
return new Date(time).toLocaleString('zh-CN');
|
||||
},
|
||||
|
||||
showAlert(message, type) {
|
||||
this.alertMessage = message;
|
||||
this.alertType = type;
|
||||
setTimeout(() => {
|
||||
this.alertMessage = '';
|
||||
}, 3000);
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
<!--#
|
||||
}
|
||||
#-->
|
||||
@@ -234,6 +234,7 @@ const apply = {
|
||||
selectTime(item) {
|
||||
if((item.dateStr + ' ' + item.startTime + '-' + item.endTime) !== (this.selected.dateStr + ' ' + this.selected.startTime + '-' + this.selected.endTime)) {
|
||||
this.$set(this.selected, 'day', item.dateStr)
|
||||
this.$set(this.selected, "dateStr", item.dateStr)
|
||||
this.$set(this.selected, 'startTime', item.startTime)
|
||||
this.$set(this.selected, 'endTime', item.endTime)
|
||||
} else {
|
||||
|
||||
+908
@@ -0,0 +1,908 @@
|
||||
<!--#
|
||||
layout("/layouts/platform_h5.html"){
|
||||
#-->
|
||||
|
||||
<style>
|
||||
*{
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.mobile-seat-container {
|
||||
background: #f7f8fa;
|
||||
min-height: 100vh;
|
||||
padding-bottom: 160px;
|
||||
}
|
||||
|
||||
.mobile-header {
|
||||
background: white;
|
||||
padding: 16px;
|
||||
border-bottom: 1px solid #ebedf0;
|
||||
/*position: sticky;*/
|
||||
/*top: 0;*/
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.mobile-header .meeting-title {
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
color: #323233;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.mobile-header .meeting-time {
|
||||
font-size: 14px;
|
||||
color: #969799;
|
||||
}
|
||||
|
||||
.mobile-stage {
|
||||
text-align: center;
|
||||
padding: 8px;
|
||||
background: transparent;
|
||||
margin: 16px;
|
||||
border-radius: 16px;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.stage-svg {
|
||||
width: 100%;
|
||||
height: 80px;
|
||||
margin-bottom: 8px;
|
||||
filter: drop-shadow(0 4px 8px rgba(0, 0, 0, 0.15));
|
||||
}
|
||||
|
||||
.stage-text {
|
||||
font-size: 18px;
|
||||
font-weight: 700;
|
||||
color: #1565c0;
|
||||
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
|
||||
background: linear-gradient(45deg, #1976d2, #42a5f5);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
margin-top: -4px;
|
||||
}
|
||||
|
||||
.mobile-legend {
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
padding: 12px 16px;
|
||||
background: white;
|
||||
margin: 0 16px 16px;
|
||||
border-radius: 8px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.mobile-legend-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.mobile-legend-seat {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
.mobile-seat-area {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.zoom-controls {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
gap: 6px;
|
||||
padding: 8px 16px;
|
||||
margin-bottom: 8px;
|
||||
/*background: rgba(128, 128, 128, 0.1);*/
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.zoom-controls .van-button {
|
||||
background: rgba(128, 128, 128, 0.2) !important;
|
||||
border: 1px solid rgba(128, 128, 128, 0.3) !important;
|
||||
color: #666 !important;
|
||||
font-size: 11px;
|
||||
padding: 2px 6px !important;
|
||||
height: 24px !important;
|
||||
min-width: auto !important;
|
||||
}
|
||||
|
||||
.zoom-controls .van-button:disabled {
|
||||
background: rgba(128, 128, 128, 0.1) !important;
|
||||
color: #ccc !important;
|
||||
}
|
||||
|
||||
.zoom-level {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 3px;
|
||||
font-size: 10px;
|
||||
font-weight: 500;
|
||||
color: #666;
|
||||
padding: 3px 6px;
|
||||
background: rgba(128, 128, 128, 0.15);
|
||||
border-radius: 6px;
|
||||
min-width: 45px;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.seat-grid-container {
|
||||
width: 100%;
|
||||
min-height: 300px;
|
||||
position: relative;
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.mobile-seat-grid {
|
||||
display: grid;
|
||||
/*grid-template-columns: repeat(10, 1fr);*/
|
||||
gap: 4px;
|
||||
background: white;
|
||||
padding: 12px;
|
||||
border-radius: 12px;
|
||||
width: 100%;
|
||||
user-select: none;
|
||||
-webkit-user-select: none;
|
||||
overflow: auto;
|
||||
max-height: 60vh;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
/* 隐藏滚动条 */
|
||||
scrollbar-width: none; /* Firefox */
|
||||
-ms-overflow-style: none; /* IE 和 Edge */
|
||||
}
|
||||
|
||||
/* 隐藏 Webkit 浏览器的滚动条 */
|
||||
.mobile-seat-grid::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.mobile-seat {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
position: relative;
|
||||
touch-action: manipulation;
|
||||
transform-origin: center;
|
||||
}
|
||||
|
||||
.mobile-seat-icon {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
margin-bottom: 1px;
|
||||
}
|
||||
|
||||
.mobile-seat-number {
|
||||
font-size: 8px;
|
||||
font-weight: 600;
|
||||
text-align: center;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
/* 座位状态样式 */
|
||||
.mobile-seat.available .seat-back {
|
||||
fill: #f8f9fa;
|
||||
stroke: #dee2e6;
|
||||
stroke-width: 1;
|
||||
}
|
||||
|
||||
.mobile-seat.available .seat-cushion {
|
||||
fill: #ffffff;
|
||||
stroke: #dee2e6;
|
||||
stroke-width: 1;
|
||||
}
|
||||
|
||||
.mobile-seat.available .seat-armrest {
|
||||
fill: #e9ecef;
|
||||
stroke: #dee2e6;
|
||||
stroke-width: 1;
|
||||
}
|
||||
|
||||
.mobile-seat.available .mobile-seat-number {
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.mobile-seat.available:active .seat-back {
|
||||
fill: #e3f2fd;
|
||||
stroke: #1867b0;
|
||||
}
|
||||
|
||||
.mobile-seat.available:active .seat-cushion {
|
||||
fill: #f0f8ff;
|
||||
stroke: #1867b0;
|
||||
}
|
||||
|
||||
.mobile-seat.available:active .seat-armrest {
|
||||
fill: #e3f2fd;
|
||||
stroke: #1867b0;
|
||||
}
|
||||
|
||||
.mobile-seat.occupied .seat-back {
|
||||
fill: #adb5bd;
|
||||
stroke: #6c757d;
|
||||
stroke-width: 1;
|
||||
}
|
||||
|
||||
.mobile-seat.occupied .seat-cushion {
|
||||
fill: #d0d0d0;
|
||||
stroke: #6c757d;
|
||||
stroke-width: 1;
|
||||
}
|
||||
|
||||
.mobile-seat.occupied .seat-armrest {
|
||||
fill: #adb5bd;
|
||||
stroke: #6c757d;
|
||||
stroke-width: 1;
|
||||
}
|
||||
|
||||
.mobile-seat.occupied .mobile-seat-number {
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.mobile-seat.occupied {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.mobile-seat.selected .seat-back {
|
||||
fill: #0d47a1;
|
||||
stroke: #1867b0;
|
||||
stroke-width: 2;
|
||||
}
|
||||
|
||||
.mobile-seat.selected .seat-cushion {
|
||||
fill: #1867b0;
|
||||
stroke: #0d47a1;
|
||||
stroke-width: 2;
|
||||
}
|
||||
|
||||
.mobile-seat.selected .seat-armrest {
|
||||
fill: #0d47a1;
|
||||
stroke: #1867b0;
|
||||
stroke-width: 2;
|
||||
}
|
||||
|
||||
.mobile-seat.selected .mobile-seat-number {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.mobile-seat.my-seat .seat-back {
|
||||
fill: #c62828;
|
||||
stroke: #ff3742;
|
||||
stroke-width: 2;
|
||||
}
|
||||
|
||||
.mobile-seat.my-seat .seat-cushion {
|
||||
fill: #ff4757;
|
||||
stroke: #c62828;
|
||||
stroke-width: 2;
|
||||
}
|
||||
|
||||
.mobile-seat.my-seat .seat-armrest {
|
||||
fill: #c62828;
|
||||
stroke: #ff3742;
|
||||
stroke-width: 2;
|
||||
}
|
||||
|
||||
.mobile-seat.my-seat .mobile-seat-number {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.mobile-seat.disabled .seat-back {
|
||||
fill: #f5f5f5;
|
||||
stroke: #cccccc;
|
||||
stroke-width: 1;
|
||||
}
|
||||
|
||||
.mobile-seat.disabled .seat-cushion {
|
||||
fill: #f0f0f0;
|
||||
stroke: #cccccc;
|
||||
stroke-width: 1;
|
||||
}
|
||||
|
||||
.mobile-seat.disabled .seat-armrest {
|
||||
fill: #f5f5f5;
|
||||
stroke: #cccccc;
|
||||
stroke-width: 1;
|
||||
}
|
||||
|
||||
.mobile-seat.disabled .mobile-seat-number {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.mobile-seat.disabled {
|
||||
cursor: not-allowed;
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.mobile-bottom-panel {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background: white;
|
||||
border-top: 1px solid #ebedf0;
|
||||
padding: 16px;
|
||||
z-index: 200;
|
||||
}
|
||||
|
||||
.mobile-selected-info {
|
||||
background: #f0f8ff;
|
||||
border: 1px solid #1989fa;
|
||||
border-radius: 8px;
|
||||
padding: 12px;
|
||||
margin-bottom: 12px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.mobile-selected-info .seat-info {
|
||||
color: #1989fa;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.mobile-my-seat-info {
|
||||
background: #fff2f0;
|
||||
border: 1px solid #ff4757;
|
||||
border-radius: 8px;
|
||||
padding: 12px;
|
||||
margin-top: 16px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.mobile-my-seat-info .seat-info {
|
||||
color: #ff4757;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.mobile-loading {
|
||||
text-align: center;
|
||||
padding: 60px 20px;
|
||||
color: #969799;
|
||||
}
|
||||
|
||||
/* 会议选择弹窗样式 */
|
||||
.meeting-modal-content {
|
||||
max-height: 70vh;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.meeting-modal-content .van-nav-bar__text {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.meeting-item {
|
||||
border: 1px solid #ebedf0;
|
||||
border-radius: 8px;
|
||||
padding: 16px;
|
||||
margin-bottom: 12px;
|
||||
background: white;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.meeting-item:active {
|
||||
background: #f0f8ff;
|
||||
border-color: #1989fa;
|
||||
}
|
||||
|
||||
.meeting-item.selected {
|
||||
background: #f0f8ff;
|
||||
border-color: #1989fa;
|
||||
}
|
||||
|
||||
.meeting-name {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: #323233;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.meeting-info {
|
||||
font-size: 14px;
|
||||
color: #646566;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.meeting-time {
|
||||
font-size: 12px;
|
||||
color: #969799;
|
||||
}
|
||||
|
||||
@media (max-width: 375px) {
|
||||
.mobile-seat-grid {
|
||||
grid-template-columns: repeat(8, 28px);
|
||||
gap: 3px;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.mobile-seat {
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
}
|
||||
|
||||
.mobile-seat-icon {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
.mobile-seat-number {
|
||||
font-size: 8px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<div id="app" v-cloak>
|
||||
<van-nav-bar title="会议选座" left-text="返回" left-arrow @click-left="historyBack" placeholder fixed></van-nav-bar>
|
||||
|
||||
<!-- 会议选择弹窗 -->
|
||||
<van-popup v-model="showMeetingModal" position="bottom" :close-on-click-overlay="false">
|
||||
<div class="meeting-modal-content">
|
||||
<van-nav-bar title="选择会议"></van-nav-bar>
|
||||
<div style="padding: 16px;">
|
||||
<div v-for="meeting in meetings" :key="meeting.id"
|
||||
:class="['meeting-item', { selected: selectedMeetingId === meeting.id }]"
|
||||
@click="selectMeeting(meeting)">
|
||||
<div class="meeting-name">{{ meeting.name }}</div>
|
||||
<div class="meeting-info">地点:{{ meeting.address }}</div>
|
||||
<div class="meeting-time">时间:{{ meeting.startTime }} 至 {{ meeting.endTime }}</div>
|
||||
</div>
|
||||
|
||||
<div style="display: flex; gap: 22px">
|
||||
<van-button block @click="showMeetingModal = false" style="margin-top: 16px;">
|
||||
取消选择
|
||||
</van-button>
|
||||
|
||||
<van-button block type="info" :disabled="!selectedMeetingId"
|
||||
@click="confirmMeetingSelection" style="margin-top: 16px;">
|
||||
确认选择
|
||||
</van-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</van-popup>
|
||||
|
||||
<div class="mobile-seat-container">
|
||||
<!-- 头部信息 -->
|
||||
<div class="mobile-header" v-if="meeting">
|
||||
<div class="meeting-title">{{ meeting.name }}</div>
|
||||
<div class="meeting-time">{{ meeting.startTime }} 至 {{ meeting.endTime }}</div>
|
||||
</div>
|
||||
|
||||
<!-- 主席台 -->
|
||||
<div class="mobile-stage">
|
||||
<svg class="stage-svg" viewBox="0 0 320 100" xmlns="http://www.w3.org/2000/svg">
|
||||
<!-- 背景装饰 -->
|
||||
<rect x="0" y="0" width="320" height="100" fill="url(#bgGradient)" rx="12" ry="12"/>
|
||||
|
||||
<!-- 主舞台基座 -->
|
||||
<ellipse cx="160" cy="75" rx="140" ry="15" fill="url(#baseGradient)" opacity="0.8"/>
|
||||
|
||||
<!-- 主舞台平台 -->
|
||||
<path d="M 30 45 Q 30 35 40 35 L 280 35 Q 290 35 290 45 L 285 65 Q 285 70 280 70 L 40 70 Q 35 70 35 65 Z"
|
||||
fill="url(#stageGradient)" stroke="url(#stageStroke)" stroke-width="2"/>
|
||||
|
||||
<!-- 台阶层次 -->
|
||||
<path d="M 45 50 Q 45 45 50 45 L 270 45 Q 275 45 275 50 L 272 62 Q 272 65 270 65 L 50 65 Q 47 65 47 62 Z"
|
||||
fill="url(#stepGradient)" stroke="#1976d2" stroke-width="1"/>
|
||||
|
||||
<!-- 装饰花纹 -->
|
||||
<path d="M 60 52 Q 65 50 70 52 Q 75 54 80 52" stroke="#ffffff" stroke-width="1.5" fill="none" opacity="0.7"/>
|
||||
<path d="M 240 52 Q 245 50 250 52 Q 255 54 260 52" stroke="#ffffff" stroke-width="1.5" fill="none" opacity="0.7"/>
|
||||
|
||||
<!-- 中央装饰 -->
|
||||
<circle cx="160" cy="52" r="8" fill="url(#centerGradient)" stroke="#ffffff" stroke-width="1" opacity="0.9"/>
|
||||
<circle cx="160" cy="52" r="4" fill="#ffd700" opacity="0.8"/>
|
||||
|
||||
<!-- 聚光灯光束 -->
|
||||
<path d="M 80 20 L 85 35 L 75 35 Z" fill="url(#lightGradient)" opacity="0.6"/>
|
||||
<path d="M 160 15 L 167 35 L 153 35 Z" fill="url(#lightGradient)" opacity="0.8"/>
|
||||
<path d="M 240 20 L 245 35 L 235 35 Z" fill="url(#lightGradient)" opacity="0.6"/>
|
||||
|
||||
<!-- 聚光灯 -->
|
||||
<circle cx="80" cy="18" r="4" fill="#ffd700" stroke="#ffb300" stroke-width="1"/>
|
||||
<circle cx="160" cy="13" r="5" fill="#ffd700" stroke="#ffb300" stroke-width="1"/>
|
||||
<circle cx="240" cy="18" r="4" fill="#ffd700" stroke="#ffb300" stroke-width="1"/>
|
||||
|
||||
<!-- 星光效果 -->
|
||||
<g opacity="0.8">
|
||||
<path d="M 100 25 L 102 30 L 107 30 L 103 33 L 105 38 L 100 35 L 95 38 L 97 33 L 93 30 L 98 30 Z" fill="#ffd700"/>
|
||||
<path d="M 220 28 L 222 32 L 226 32 L 223 35 L 225 39 L 220 36 L 215 39 L 217 35 L 214 32 L 218 32 Z" fill="#ffd700"/>
|
||||
</g>
|
||||
|
||||
<!-- 渐变定义 -->
|
||||
<defs>
|
||||
<linearGradient id="bgGradient" x1="0%" y1="0%" x2="0%" y2="100%">
|
||||
<stop offset="0%" style="stop-color:#e3f2fd;stop-opacity:1" />
|
||||
<stop offset="100%" style="stop-color:#bbdefb;stop-opacity:1" />
|
||||
</linearGradient>
|
||||
<linearGradient id="stageGradient" x1="0%" y1="0%" x2="0%" y2="100%">
|
||||
<stop offset="0%" style="stop-color:#1e88e5;stop-opacity:1" />
|
||||
<stop offset="30%" style="stop-color:#1976d2;stop-opacity:1" />
|
||||
<stop offset="70%" style="stop-color:#1565c0;stop-opacity:1" />
|
||||
<stop offset="100%" style="stop-color:#0d47a1;stop-opacity:1" />
|
||||
</linearGradient>
|
||||
<linearGradient id="stageStroke" x1="0%" y1="0%" x2="0%" y2="100%">
|
||||
<stop offset="0%" style="stop-color:#42a5f5;stop-opacity:1" />
|
||||
<stop offset="100%" style="stop-color:#1565c0;stop-opacity:1" />
|
||||
</linearGradient>
|
||||
<linearGradient id="stepGradient" x1="0%" y1="0%" x2="0%" y2="100%">
|
||||
<stop offset="0%" style="stop-color:#42a5f5;stop-opacity:1" />
|
||||
<stop offset="100%" style="stop-color:#1976d2;stop-opacity:1" />
|
||||
</linearGradient>
|
||||
<linearGradient id="baseGradient" x1="0%" y1="0%" x2="0%" y2="100%">
|
||||
<stop offset="0%" style="stop-color:#90caf9;stop-opacity:0.6" />
|
||||
<stop offset="100%" style="stop-color:#1976d2;stop-opacity:0.8" />
|
||||
</linearGradient>
|
||||
<radialGradient id="centerGradient" cx="50%" cy="50%" r="50%">
|
||||
<stop offset="0%" style="stop-color:#ffffff;stop-opacity:1" />
|
||||
<stop offset="100%" style="stop-color:#1976d2;stop-opacity:1" />
|
||||
</radialGradient>
|
||||
<linearGradient id="lightGradient" x1="0%" y1="0%" x2="0%" y2="100%">
|
||||
<stop offset="0%" style="stop-color:#fff9c4;stop-opacity:0.9" />
|
||||
<stop offset="100%" style="stop-color:#fff59d;stop-opacity:0.3" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
<div class="stage-text">主席台</div>
|
||||
</div>
|
||||
|
||||
<!-- 图例 -->
|
||||
<div class="mobile-legend">
|
||||
<div class="mobile-legend-item">
|
||||
<svg class="mobile-legend-seat" viewBox="0 0 50 50" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect x="8" y="5" width="34" height="20" rx="3" ry="3" fill="#f8f9fa" stroke="#dee2e6"
|
||||
stroke-width="1"/>
|
||||
<rect x="5" y="22" width="40" height="18" rx="4" ry="4" fill="#ffffff" stroke="#dee2e6"
|
||||
stroke-width="1"/>
|
||||
<rect x="2" y="20" width="6" height="15" rx="2" ry="2" fill="#e9ecef" stroke="#dee2e6"
|
||||
stroke-width="1"/>
|
||||
<rect x="42" y="20" width="6" height="15" rx="2" ry="2" fill="#e9ecef" stroke="#dee2e6"
|
||||
stroke-width="1"/>
|
||||
</svg>
|
||||
<span>可选</span>
|
||||
</div>
|
||||
<div class="mobile-legend-item">
|
||||
<svg class="mobile-legend-seat" viewBox="0 0 50 50" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect x="8" y="5" width="34" height="20" rx="3" ry="3" fill="#adb5bd" stroke="#6c757d"
|
||||
stroke-width="1"/>
|
||||
<rect x="5" y="22" width="40" height="18" rx="4" ry="4" fill="#d0d0d0" stroke="#6c757d"
|
||||
stroke-width="1"/>
|
||||
<rect x="2" y="20" width="6" height="15" rx="2" ry="2" fill="#adb5bd" stroke="#6c757d"
|
||||
stroke-width="1"/>
|
||||
<rect x="42" y="20" width="6" height="15" rx="2" ry="2" fill="#adb5bd" stroke="#6c757d"
|
||||
stroke-width="1"/>
|
||||
</svg>
|
||||
<span>占用</span>
|
||||
</div>
|
||||
<div class="mobile-legend-item">
|
||||
<svg class="mobile-legend-seat" viewBox="0 0 50 50" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect x="8" y="5" width="34" height="20" rx="3" ry="3" fill="#0d47a1" stroke="#1867b0"
|
||||
stroke-width="2"/>
|
||||
<rect x="5" y="22" width="40" height="18" rx="4" ry="4" fill="#1867b0" stroke="#0d47a1"
|
||||
stroke-width="2"/>
|
||||
<rect x="2" y="20" width="6" height="15" rx="2" ry="2" fill="#0d47a1" stroke="#1867b0"
|
||||
stroke-width="2"/>
|
||||
<rect x="42" y="20" width="6" height="15" rx="2" ry="2" fill="#0d47a1" stroke="#1867b0"
|
||||
stroke-width="2"/>
|
||||
</svg>
|
||||
<span>选中</span>
|
||||
</div>
|
||||
<div class="mobile-legend-item">
|
||||
<svg class="mobile-legend-seat" viewBox="0 0 50 50" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect x="8" y="5" width="34" height="20" rx="3" ry="3" fill="#c62828" stroke="#ff3742"
|
||||
stroke-width="2"/>
|
||||
<rect x="5" y="22" width="40" height="18" rx="4" ry="4" fill="#ff4757" stroke="#c62828"
|
||||
stroke-width="2"/>
|
||||
<rect x="2" y="20" width="6" height="15" rx="2" ry="2" fill="#c62828" stroke="#ff3742"
|
||||
stroke-width="2"/>
|
||||
<rect x="42" y="20" width="6" height="15" rx="2" ry="2" fill="#c62828" stroke="#ff3742"
|
||||
stroke-width="2"/>
|
||||
</svg>
|
||||
<span>我的</span>
|
||||
</div>
|
||||
<div class="mobile-legend-item">
|
||||
<svg class="mobile-legend-seat" viewBox="0 0 50 50" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect x="8" y="5" width="34" height="20" rx="3" ry="3" fill="#f5f5f5" stroke="#cccccc"
|
||||
stroke-width="1"/>
|
||||
<rect x="5" y="22" width="40" height="18" rx="4" ry="4" fill="#f0f0f0" stroke="#cccccc"
|
||||
stroke-width="1"/>
|
||||
<rect x="2" y="20" width="6" height="15" rx="2" ry="2" fill="#f5f5f5" stroke="#cccccc"
|
||||
stroke-width="1"/>
|
||||
<rect x="42" y="20" width="6" height="15" rx="2" ry="2" fill="#f5f5f5" stroke="#cccccc"
|
||||
stroke-width="1"/>
|
||||
</svg>
|
||||
<span>禁用</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 座位区域 -->
|
||||
<div class="mobile-seat-area">
|
||||
<van-loading v-if="loading" type="spinner" color="#1989fa" class="mobile-loading">
|
||||
正在加载座位信息...
|
||||
</van-loading>
|
||||
|
||||
<div v-else class="seat-grid-container">
|
||||
<div class="mobile-seat-grid" id="seatGrid" :style="gridStyle">
|
||||
<div v-for="seat in seats" :key="seat.id"
|
||||
:class="getSeatClass(seat)"
|
||||
class="mobile-seat"
|
||||
@click="selectSeat(seat)">
|
||||
<svg class="mobile-seat-icon" viewBox="0 0 50 50" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect x="8" y="5" width="34" height="20" rx="3" ry="3" class="seat-back"/>
|
||||
<rect x="5" y="22" width="40" height="18" rx="4" ry="4" class="seat-cushion"/>
|
||||
<rect x="2" y="20" width="6" height="15" rx="2" ry="2" class="seat-armrest"/>
|
||||
<rect x="42" y="20" width="6" height="15" rx="2" ry="2" class="seat-armrest"/>
|
||||
</svg>
|
||||
<span class="mobile-seat-number">{{ seat.rowNumber }}-{{ seat.colNumber }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 缩放控制按钮 -->
|
||||
<div class="zoom-controls">
|
||||
<van-button type="default" size="mini" @click="zoomOut" :disabled="currentScale <= 0.5">
|
||||
<van-icon name="minus" size="12" />
|
||||
缩小
|
||||
</van-button>
|
||||
<div class="zoom-level">
|
||||
<van-icon name="search" size="12" />
|
||||
{{ Math.round(currentScale * 100) }}%
|
||||
</div>
|
||||
<van-button type="default" size="mini" @click="resetZoom">
|
||||
<van-icon name="replay" size="12" />
|
||||
重置
|
||||
</van-button>
|
||||
<van-button type="default" size="mini" @click="zoomIn" :disabled="currentScale >= 3">
|
||||
<van-icon name="plus" size="12" />
|
||||
放大
|
||||
</van-button>
|
||||
</div>
|
||||
|
||||
<!-- 我的座位信息 -->
|
||||
<div v-if="myCurrentSeat" class="mobile-my-seat-info" style="margin: 16px;">
|
||||
<div style="margin-bottom: 4px;">我的座位</div>
|
||||
<div class="seat-info">{{ myCurrentSeat.rowNumber }}-{{ myCurrentSeat.colNumber }} (第{{ myCurrentSeat.rowNumber }}排第{{
|
||||
myCurrentSeat.colNumber }}列)
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 底部操作面板 -->
|
||||
<div class="mobile-bottom-panel">
|
||||
<div v-if="selectedSeat" class="mobile-selected-info">
|
||||
<div style="margin-bottom: 4px;">已选择座位</div>
|
||||
<div class="seat-info">{{ selectedSeat.rowNumber }}-{{ selectedSeat.colNumber }} (第{{ selectedSeat.rowNumber }}排第{{
|
||||
selectedSeat.colNumber }}列)
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="display: flex; gap: 22px">
|
||||
<van-button type="info" block @click="showMeetingModal = true">
|
||||
切换会议
|
||||
</van-button>
|
||||
|
||||
<van-button type="info" block :disabled="!selectedSeat || submitting"
|
||||
:loading="submitting" @click="confirmSelection">
|
||||
{{ submitting ? '提交中...' : '确认选座' }}
|
||||
</van-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const vue = new Vue({
|
||||
el: '#app',
|
||||
data() {
|
||||
return {
|
||||
meetings: [], // 会议列表
|
||||
selectedMeetingId: null, // 选中的会议ID
|
||||
showMeetingModal: true, // 显示会议选择弹窗
|
||||
meeting: null,
|
||||
seats: [],
|
||||
selectedSeat: null,
|
||||
myCurrentSeat: null,
|
||||
loading: false,
|
||||
submitting: false,
|
||||
currentScale: 1, // 当前缩放比例
|
||||
seatConfig: {
|
||||
rows: 8,
|
||||
cols: 12
|
||||
},
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.loadMeetings();
|
||||
this.$nextTick(() => {
|
||||
this.initPinchZoom();
|
||||
});
|
||||
},
|
||||
computed: {
|
||||
gridStyle() {
|
||||
return {
|
||||
'grid-template-columns': 'repeat(' + this.seatConfig.cols + ', 1fr)'
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 加载会议列表
|
||||
loadMeetings() {
|
||||
$.post('/platform/guildHall/meeting/selectList').then(res => {
|
||||
if (res.code === 0) {
|
||||
this.meetings = res.data
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
// 选择会议
|
||||
selectMeeting(meeting) {
|
||||
this.selectedMeetingId = meeting.id;
|
||||
},
|
||||
|
||||
// 确认会议选择
|
||||
confirmMeetingSelection() {
|
||||
if (!this.selectedMeetingId) {
|
||||
this.$toast('请选择一个会议');
|
||||
return;
|
||||
}
|
||||
|
||||
const selectedMeeting = this.meetings.find(m => m.id === this.selectedMeetingId);
|
||||
if (selectedMeeting) {
|
||||
this.meeting = selectedMeeting
|
||||
this.loadSeats();
|
||||
}
|
||||
},
|
||||
|
||||
// 查询选座情况
|
||||
async loadSeats() {
|
||||
if (!this.meeting.id) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.loading = true;
|
||||
|
||||
const {
|
||||
code,
|
||||
data,
|
||||
msg
|
||||
} = await $.post('/platform/guildHall/selectSeat/loadSeats', {meetingId: this.meeting.id})
|
||||
if (code === 0) {
|
||||
this.seats = data;
|
||||
this.myCurrentSeat = this.seats.find(seat => seat.isMine);
|
||||
// 根据现有数据计算行列数
|
||||
const maxRow = Math.max(...this.seats.map(s => parseInt(s.rowNumber)))
|
||||
const maxCol = Math.max(...this.seats.map(s => parseInt(s.colNumber)))
|
||||
this.seatConfig.rows = maxRow
|
||||
this.seatConfig.cols = maxCol
|
||||
}
|
||||
|
||||
this.loading = false
|
||||
this.showMeetingModal = false;
|
||||
},
|
||||
|
||||
selectSeat(seat) {
|
||||
if (!seat.enable) {
|
||||
this.$toast('该座位已被禁用');
|
||||
return;
|
||||
}
|
||||
|
||||
if (seat.isOccupied && !seat.isMine) {
|
||||
this.$toast('该座位已被占用');
|
||||
return;
|
||||
}
|
||||
|
||||
if (seat.isMine) {
|
||||
this.$toast('这是您当前的座位');
|
||||
return;
|
||||
}
|
||||
|
||||
this.selectedSeat = seat;
|
||||
// 添加触觉反馈
|
||||
if (navigator.vibrate) {
|
||||
navigator.vibrate(50);
|
||||
}
|
||||
},
|
||||
|
||||
async confirmSelection() {
|
||||
if (!this.selectedSeat) {
|
||||
this.$toast('请先选择座位');
|
||||
return;
|
||||
}
|
||||
|
||||
this.submitting = true;
|
||||
const {code, data, msg} = await $.post('/platform/guildHall/selectSeat/doSelect', {
|
||||
meetingId: this.meeting.id,
|
||||
rowNumber: this.selectedSeat.rowNumber,
|
||||
colNumber: this.selectedSeat.colNumber
|
||||
})
|
||||
this.submitting = false
|
||||
|
||||
if (code === 0) {
|
||||
this.$toast.success("选座成功")
|
||||
this.selectedSeat = null;
|
||||
this.loadSeats();
|
||||
} else {
|
||||
this.$toast.fail(msg || '选座失败');
|
||||
}
|
||||
},
|
||||
|
||||
getSeatClass(seat) {
|
||||
if (!seat.enable) {
|
||||
return 'disabled';
|
||||
}
|
||||
if (seat.isMine) return 'my-seat';
|
||||
if (seat === this.selectedSeat) return 'selected';
|
||||
if (seat.isOccupied) return 'occupied';
|
||||
return 'available';
|
||||
},
|
||||
|
||||
getSeatTitle(seat) {
|
||||
if (seat.isMine) return '我的座位';
|
||||
if (seat === this.selectedSeat) return '当前选择';
|
||||
if (seat.status === 1) return '已被占用';
|
||||
return '点击选择此座位';
|
||||
},
|
||||
|
||||
formatTime(time) {
|
||||
if (!time) return '';
|
||||
return new Date(time).toLocaleString('zh-CN');
|
||||
},
|
||||
|
||||
// 放大
|
||||
zoomIn() {
|
||||
if (this.currentScale < 3) {
|
||||
this.currentScale = Math.min(3, this.currentScale + 0.2);
|
||||
this.applyZoom();
|
||||
}
|
||||
},
|
||||
|
||||
// 缩小
|
||||
zoomOut() {
|
||||
if (this.currentScale > 0.5) {
|
||||
this.currentScale = Math.max(0.5, this.currentScale - 0.2);
|
||||
this.applyZoom();
|
||||
}
|
||||
},
|
||||
|
||||
// 重置缩放
|
||||
resetZoom() {
|
||||
this.currentScale = 1;
|
||||
this.applyZoom();
|
||||
},
|
||||
|
||||
// 应用缩放
|
||||
applyZoom() {
|
||||
const seats = document.querySelectorAll('.mobile-seat');
|
||||
const seatGrid = document.querySelector('.mobile-seat-grid');
|
||||
|
||||
seats.forEach(seat => {
|
||||
seat.style.transform = 'scale(' + this.currentScale + ')';
|
||||
seat.style.transformOrigin = 'center center';
|
||||
seat.style.transition = 'transform 0.2s ease';
|
||||
});
|
||||
|
||||
// 动态调整网格间距
|
||||
if (seatGrid) {
|
||||
const baseGap = 4;
|
||||
const adjustedGap = baseGap * this.currentScale * 5;
|
||||
seatGrid.style.gap = adjustedGap + 'px';
|
||||
}
|
||||
},
|
||||
|
||||
// 初始化双指缩放功能(已替换为按钮控制)
|
||||
initPinchZoom() {
|
||||
// 双指缩放功能已被按钮控制替代,保留此方法以避免错误
|
||||
console.log('双指缩放功能已替换为按钮控制');
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<!--#
|
||||
}
|
||||
#-->
|
||||
Reference in New Issue
Block a user