生日祝福修改

This commit is contained in:
2026-09-10 14:33:15 +08:00
parent 5ea061ee8e
commit 3fc338af1e
10 changed files with 271 additions and 37 deletions
@@ -101,6 +101,11 @@ public class SysMsgServiceImpl extends BaseServiceImpl<Sys_msg> implements SysMs
}
});
// false 仅保存并通知站内消息,供业务自行按渠道发送,避免再次触发学校平台组合推送。
if (!isExternal) {
return sysMsg;
}
//发送学校平台消息
ThreadUtil.execute(() -> {
// 46表示短信和钉钉组合发送;按照消息中心要求,组合中包含短信时手机号必填。
@@ -141,6 +141,10 @@ public class View_user {
@Column
private String unionCode;
/** 用户视图中的所属校区值,供变更表单回显及原值比较使用。 */
@Column
private String campus;
@Column
private String campusId;
@@ -2,6 +2,13 @@ package com.budwk.app.zhgh.staffmanage.birthday.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import com.budwk.app.base.result.Result;
import com.budwk.app.base.annotation.RepeatSubmit;
import com.budwk.app.base.annotation.SLog;
import cn.hutool.core.util.StrUtil;
import org.nutz.aop.interceptor.ioc.TransAop;
import org.nutz.ioc.aop.Aop;
import org.nutz.mvc.annotation.POST;
import org.nutz.mvc.annotation.Param;
import com.budwk.app.zhgh.staffmanage.birthday.param.UserBirthdayPageForm;
import com.budwk.app.zhgh.staffmanage.birthday.service.UserBirthdayService;
import io.swagger.annotations.Api;
@@ -23,6 +30,27 @@ import javax.servlet.http.HttpServletResponse;
@Api(tags = "生日祝福数据导出")
public class UserBirthdayExportController {
/**
* 修改生日列表中指定人员的所属校区,复用生日导出权限。
*
* @param userId 列表行的人员 ID;工号、姓名由服务端查询,不接收前端覆盖
* @param campusId 校区编码,仅允许 hz(杭州校区)或 cx(长兴校区)
* @return Resultcode=0 表示保存成功,msg 为操作提示,无额外业务数据
*/
@At
@POST
@RepeatSubmit
@Aop(TransAop.READ_COMMITTED)
@SaCheckPermission("staff.birthday.export")
@SLog(tag = "生日校区维护", msg = "修改人员生日校区")
public Result saveCampus(@Param("userId") String userId, @Param("campusId") String campusId) {
if (StrUtil.isBlank(userId) || !StrUtil.equalsAny(campusId, "hz", "cx")) {
return Result.error("请选择人员和有效的所属校区");
}
userBirthdayService.saveCampus(userId, campusId);
return Result.success("所属校区修改成功");
}
@Inject
private UserBirthdayService userBirthdayService;
@@ -22,6 +22,15 @@ public interface UserBirthdayService extends BaseService<Sys_user> {
*/
Pagination pageData(UserBirthdayPageForm pageForm);
/**
* 按人员工号新增或更新生日校区标记,保留现有备注及创建信息。
*
* @param userId 当前操作者可管理的生日会员 ID
* @param campusId hz 表示杭州校区,cx 表示长兴校区
* @throws com.budwk.app.base.exception.BaseException 参数无效或人员不在可管理范围时抛出
*/
void saveCampus(String userId, String campusId);
/**
* 导出符合查询条件的生日会员。
*
@@ -4,13 +4,19 @@ 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.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.StrUtil;
import com.budwk.app.base.page.Pagination;
import com.budwk.app.base.exception.BaseException;
import com.budwk.app.sys.views.View_user;
import com.budwk.app.zhgh.staffmanage.birthday.models.UserBirthdayCampus;
import com.budwk.app.base.service.impl.BaseServiceImpl;
import com.budwk.app.base.sms.SmsService;
import com.budwk.app.base.utils.CommonDownloadUtil;
import com.budwk.app.sys.models.Sys_msg;
import com.budwk.app.sys.models.Sys_user;
import com.budwk.app.sys.services.SysMsgService;
import com.budwk.app.web.commons.base.Globals;
import com.budwk.app.zhgh.staffmanage.birthday.models.UserBirthdayConfig;
import com.budwk.app.zhgh.staffmanage.birthday.param.UserBirthdayPageForm;
import com.budwk.app.zhgh.staffmanage.birthday.param.UserBirthdaySendMsgForm;
@@ -63,6 +69,9 @@ public class UserBirthdayServiceImpl extends BaseServiceImpl<Sys_user> implement
@Inject
private SysMsgService sysMsgService;
@Inject
private SmsService smsService;
@Inject
private UserBirthdayMsgLogService userBirthdayMsgLogService;
@@ -75,6 +84,60 @@ public class UserBirthdayServiceImpl extends BaseServiceImpl<Sys_user> implement
return listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), buildBirthdaySql(pageForm));
}
/**
* 校验人员范围并保存生日校区;锁定人员行,使同一人员的并发保存串行执行。
*
* @param userId 列表人员 ID,须属于当前操作者可查询的会员且已维护生日
* @param campusId hz(杭州校区)或 cx(长兴校区),名称由后端确定
* @throws BaseException 人员无效、超出管理范围或校区编码无效
*/
@Override
@Aop(TransAop.READ_COMMITTED)
public void saveCampus(String userId, String campusId) {
if (StrUtil.isBlank(userId) || !StrUtil.equalsAny(campusId, "hz", "cx")) {
throw new BaseException("请选择人员和有效的所属校区");
}
// 即使尚未创建校区标记,也通过已存在的人员行互斥,避免并发插入重复工号标记。
Sql lockSql = Sqls.create("SELECT id FROM sys_user WHERE id = @userId FOR UPDATE");
lockSql.params().set("userId", userId);
lockSql.setCallback(Sqls.callback.str());
dao().execute(lockSql);
if (lockSql.getObject(String.class) == null) {
throw new BaseException("人员不存在");
}
// 复用生日列表的组织权限条件,范围由登录身份确定,不信任客户端传入的组织信息。
Cnd scope = Cnd.where("id", "=", userId).and("member", "=", 1).and("birthday", "is not", null);
new UserBirthdayPageForm().buildSearch(scope, "");
View_user user = dao().fetch(View_user.class, scope);
if (user == null || StrUtil.isBlank(user.getLoginname())) {
throw new BaseException("人员不在可管理的生日会员范围内");
}
List<UserBirthdayCampus> records = dao().query(UserBirthdayCampus.class,
Cnd.where("loginname", "=", user.getLoginname()).desc("updatedAt").asc("id"));
UserBirthdayCampus campus = records.stream()
.filter(item -> !Boolean.TRUE.equals(item.getDelFlag()))
.findFirst().orElse(records.isEmpty() ? new UserBirthdayCampus() : records.get(0));
boolean insert = StrUtil.isBlank(campus.getId());
campus.setLoginname(user.getLoginname());
campus.setUsername(user.getUsername());
campus.setCampusId(campusId);
campus.setCampusName("cx".equals(campusId) ? "长兴校区" : "杭州校区");
campus.setDelFlag(false);
if (insert) {
dao().insert(campus);
} else {
dao().update(campus);
}
// 当前工号若已有重复有效记录,仅保留本次更新的记录,其余逻辑删除,避免列表联表重复。
for (UserBirthdayCampus duplicate : records) {
if (!duplicate.getId().equals(campus.getId()) && !Boolean.TRUE.equals(duplicate.getDelFlag())) {
duplicate.setDelFlag(true);
dao().update(duplicate);
}
}
}
@Override
public void exportXlsx(UserBirthdayPageForm pageForm, HttpServletResponse response) {
try {
@@ -95,7 +158,19 @@ public class UserBirthdayServiceImpl extends BaseServiceImpl<Sys_user> implement
ExportParams exportParams = new ExportParams();
exportParams.setType(ExcelType.XSSF);
// 当前列表按查询校区生成顶部标题,未指定校区时使用全校标题。
exportParams.setTitle(buildSignatureTitle(getCampusDisplayName(pageForm.getCampusName())));
try (Workbook workbook = ExcelExportUtil.exportExcel(exportParams, columns, list)) {
// 调整当前工作簿的全部字体,保留各字体原有的加粗、颜色和字体名称。
for (int fontIndex = 0; fontIndex < workbook.getNumberOfFontsAsInt(); fontIndex++) {
workbook.getFontAt(fontIndex).setFontHeightInPoints((short) 16);
}
// 字号增大后为每行保留至少 28 磅高度,已有更高的标题或数据行不缩小。
for (Sheet sheet : workbook) {
for (Row row : sheet) {
row.setHeightInPoints(Math.max(row.getHeightInPoints(), 28));
}
}
CommonDownloadUtil.download("生日祝福人员名单.xlsx", workbook, response);
}
} catch (Exception e) {
@@ -433,9 +508,9 @@ public class UserBirthdayServiceImpl extends BaseServiceImpl<Sys_user> implement
sheet.setColumnWidth(7, 16 * 256);
CellStyle titleStyle = createCellStyle(workbook, true, (short) 16, false);
CellStyle subtitleStyle = createCellStyle(workbook, false, (short) 12, false);
CellStyle headerStyle = createCellStyle(workbook, true, (short) 11, true);
CellStyle contentStyle = createCellStyle(workbook, false, (short) 11, true);
CellStyle subtitleStyle = createCellStyle(workbook, false, (short) 16, false);
CellStyle headerStyle = createCellStyle(workbook, true, (short) 16, true);
CellStyle contentStyle = createCellStyle(workbook, false, (short) 16, true);
Row titleRow = sheet.createRow(0);
titleRow.setHeightInPoints(28);
@@ -443,13 +518,13 @@ public class UserBirthdayServiceImpl extends BaseServiceImpl<Sys_user> implement
sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, 7));
Row subtitleRow = sheet.createRow(1);
subtitleRow.setHeightInPoints(22);
subtitleRow.setHeightInPoints(28);
createCell(subtitleRow, 0, buildSignatureSubtitle(displayPeriod), subtitleStyle);
sheet.addMergedRegion(new CellRangeAddress(1, 1, 0, 7));
String[] headers = {"序号", "部门", "姓名", "签名", "序号", "部门", "姓名", "签名"};
Row headerRow = sheet.createRow(2);
headerRow.setHeightInPoints(22);
headerRow.setHeightInPoints(28);
for (int i = 0; i < headers.length; i++) {
createCell(headerRow, i, headers[i], headerStyle);
}
@@ -457,7 +532,7 @@ public class UserBirthdayServiceImpl extends BaseServiceImpl<Sys_user> implement
int leftSize = (list.size() + 1) / 2;
for (int i = 0; i < leftSize; i++) {
Row row = sheet.createRow(i + 3);
row.setHeightInPoints(22);
row.setHeightInPoints(28);
fillSignatureRow(row, 0, i, getListItem(list, i), contentStyle);
fillSignatureRow(row, 4, i + leftSize, getListItem(list, i + leftSize), contentStyle);
}
@@ -551,10 +626,10 @@ public class UserBirthdayServiceImpl extends BaseServiceImpl<Sys_user> implement
}
if (start.getYear() == end.getYear()) {
return start.format(DateTimeFormatter.ofPattern("yyyy年M月")) + "-" +
end.format(DateTimeFormatter.ofPattern("M月"));
end.format(DateTimeFormatter.ofPattern("M月"));
}
return start.format(DateTimeFormatter.ofPattern("yyyy年M月")) + "-" +
end.format(DateTimeFormatter.ofPattern("yyyy年M月"));
end.format(DateTimeFormatter.ofPattern("yyyy年M月"));
}
private String buildSignatureDisplayPeriod(LocalDate start, LocalDate end) {
@@ -563,10 +638,10 @@ public class UserBirthdayServiceImpl extends BaseServiceImpl<Sys_user> implement
}
if (start.getYear() == end.getYear()) {
return start.format(DateTimeFormatter.ofPattern("yyyy年M")) + "-" +
end.format(DateTimeFormatter.ofPattern("M月"));
end.format(DateTimeFormatter.ofPattern("M月"));
}
return start.format(DateTimeFormatter.ofPattern("yyyy年M月")) + "-" +
end.format(DateTimeFormatter.ofPattern("yyyy年M月"));
end.format(DateTimeFormatter.ofPattern("yyyy年M月"));
}
private String buildSignatureDateDisplayPeriod(LocalDate start, LocalDate end) {
@@ -575,21 +650,22 @@ public class UserBirthdayServiceImpl extends BaseServiceImpl<Sys_user> implement
}
if (isSameMonth(start, end)) {
return start.format(DateTimeFormatter.ofPattern("yyyy年M月d日")) + "-" +
end.format(DateTimeFormatter.ofPattern("d日"));
end.format(DateTimeFormatter.ofPattern("d日"));
}
if (start.getYear() == end.getYear()) {
return start.format(DateTimeFormatter.ofPattern("yyyy年M月d日")) + "-" +
end.format(DateTimeFormatter.ofPattern("M月d日"));
end.format(DateTimeFormatter.ofPattern("M月d日"));
}
return start.format(DateTimeFormatter.ofPattern("yyyy年M月d日")) + "-" +
end.format(DateTimeFormatter.ofPattern("yyyy年M月d日"));
end.format(DateTimeFormatter.ofPattern("yyyy年M月d日"));
}
/** 统一列表和签名表的顶部标题,校区取按钮参数或列表筛选条件。 */
private String buildSignatureTitle(String campusDisplayName) {
if (StrUtil.isBlank(campusDisplayName)) {
return "浙江交通职业技术学院职工生日蛋糕券发放名单";
return "浙江交通职业技术学院职工座谈会及生日蛋糕券发放名单";
}
return "浙江交通职业技术学院" + campusDisplayName + "职工生日蛋糕券发放名单";
return "浙江交通职业技术学院" + campusDisplayName + "职工座谈会及生日蛋糕券发放名单";
}
private String buildSignatureSubtitle(String displayPeriod) {
@@ -643,8 +719,9 @@ public class UserBirthdayServiceImpl extends BaseServiceImpl<Sys_user> implement
/**
* 将生日消息写入当前项目消息中心并生成发送记录。
* 发送内容只包含标题和正文,不向站内、短信或钉钉渠道传递生日页面链接。
* 单人、批量和自动发送共用此入口:站内保留跳转地址,短信仅发祝福正文,钉钉正文附带生日链接。
*/
@Aop(TransAop.READ_COMMITTED)
private int sendMessages(List<String> loginNames, String title, String content,
String pushBy, String pushByName, String pushType) {
List<String> recipients = loginNames == null ? List.of() : loginNames.stream()
@@ -655,17 +732,50 @@ public class UserBirthdayServiceImpl extends BaseServiceImpl<Sys_user> implement
return 0;
}
// 链接携带发送时的福利贺卡文件 ID;未配置时仍进入生日页面,由页面展示未配置提示。
String fileId = StrUtil.blankToDefault(getConfig().getBirthdayUrl(), "");
String link = StrUtil.removeSuffix(Globals.AppDomain, "/")
+ "/platform/staffManage/birthday/manage/h5";
Sys_msg message = new Sys_msg();
message.setTitle(title);
message.setNote(content);
message.setUrl(link);
message.setType("user");
message.setSendType("show");
message.setSendAt(Times.getTS());
message.setCreatedBy(pushBy);
sysMsgService.saveMsg(message, recipients.toArray(String[]::new), true);
userBirthdayMsgLogService.insertLogs(recipients, title, content, "",
pushBy, pushByName, pushType);
// 短信接收人需携带工号和手机号,沿用消息中心按工号分组的查询范围。
Sql receiverSql = Sqls.create("SELECT loginname, mobile FROM vw_user $condition");
receiverSql.setCondition(Cnd.where("loginname", "in", recipients).groupBy("loginname"));
List<NutMap> receivers = listMap(receiverSql).stream()
.map(user -> NutMap.NEW()
.addv("userId", user.getString("loginname"))
.addv("mobile", user.getString("mobile"))
.addv("email", "")
.addv("flag", 0))
.toList();
if (!receivers.isEmpty()) {
// 分别提交渠道任务,任一渠道失败不会阻断另一渠道;实际结果由学校消息服务分别留存。
ThreadUtil.execute(() -> {
boolean success = smsService.sendMsg("4", null, receivers, title, content, null, null);
if (!success) {
log.warn("生日短信发送未成功,消息ID:{},请查看学校平台发送记录", message.getId());
}
});
ThreadUtil.execute(() -> {
// 当前钉钉使用文本消息,链接明确写入正文,跳转参数留空以避免平台重复追加。
boolean success = smsService.sendMsg("6", null, receivers, title, content, null, link);
if (!success) {
log.warn("生日钉钉发送未成功,消息ID:{},请查看学校平台发送记录", message.getId());
} else {
userBirthdayMsgLogService.insertLogs(recipients, title, content, link,
pushBy, pushByName, pushType);
}
});
}
return recipients.size();
}
}
@@ -87,6 +87,7 @@ public class MemberManageServiceImpl extends BaseServiceImpl<Sys_user> implement
u.unitName,
u.unionId,
u.unionName,
u.campus,
u.birthday,
u.manyUnit,
u.member,
@@ -267,6 +268,7 @@ public class MemberManageServiceImpl extends BaseServiceImpl<Sys_user> implement
NutMap newMap = Lang.obj2nutmap(record);
// 原数据
NutMap sourceMap = Lang.obj2nutmap(info);
// 原数据已映射 campus,直接与表单同名字段比较,避免被 campusId 覆盖而误报异动。
List<NutMap> changeList = new ArrayList<>();
for (String fieldName : allowChangeFieldNames) {
@@ -55,10 +55,36 @@ layout("/layouts/platform.html"){
:label="column.label" :width="column.width" :fixed="column.fixed"
:sortable="column.sortable"
header-align="center" show-overflow-tooltip></el-table-column>
<el-table-column label="操作" fixed="right" width="150" align="center">
<template slot-scope="{row}">
<el-button type="text" size="small" @click="openCampusForm(row)">修改所属校区</el-button>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
</template>
<el-dialog title="修改所属校区" :visible.sync="campusDialogVisible" width="480px"
:close-on-click-modal="false" :close-on-press-escape="!formLoading" :show-close="!formLoading">
<el-form ref="campusFormRef" :model="campusForm" :rules="campusRules" label-width="100px">
<el-form-item label="工号">
<el-input :value="campusForm.loginname" readonly></el-input>
</el-form-item>
<el-form-item label="姓名">
<el-input :value="campusForm.username" readonly></el-input>
</el-form-item>
<el-form-item label="所属校区" prop="campusId">
<el-select v-model="campusForm.campusId" :disabled="formLoading" placeholder="请选择所属校区" style="width:100%">
<el-option v-for="item in campuses" :key="item.id" :label="item.name" :value="item.id"></el-option>
</el-select>
</el-form-item>
<div class="text-muted">此设置用于生日名单及签名表。</div>
</el-form>
<template slot="footer">
<el-button :disabled="formLoading" @click="closeCampusForm">取消</el-button>
<el-button type="primary" :loading="formLoading" @click="saveCampus">保存</el-button>
</template>
</el-dialog>
</guava>
</div>
@@ -86,6 +112,11 @@ layout("/layouts/platform.html"){
},
queryForm: {userStates:[],personTypes:[]},
birthdayRange: [],
campusDialogVisible: false,
campusForm: {userId:"",loginname:"",username:"",campusId:""},
campusRules: {
campusId: [{required:true,message:"请选择所属校区",trigger:"change"}]
},
campuses: [
{id:"hz",name:"杭州校区"},
{id:"cx",name:"长兴校区"}
@@ -109,6 +140,48 @@ layout("/layouts/platform.html"){
}
},
methods: {
// 回显列表中实际生效的生日校区,包括未设置标记时按单位推导出的校区。
openCampusForm(row) {
const campus = this.campuses.find(item => item.name === row.campusName || item.id === row.campusName)
this.$set(this, "campusForm", {
userId: row.id,
loginname: row.loginname,
username: row.username,
campusId: campus ? campus.id : ""
})
this.$set(this, "campusDialogVisible", true)
this.$nextTick(() => {
if (this.$refs.campusFormRef) this.$refs.campusFormRef.clearValidate()
})
},
// 保存中禁止关闭,避免请求未完成时切换到其他人员。
closeCampusForm() {
if (!this.formLoading) this.$set(this, "campusDialogVisible", false)
},
// 仅提交人员 ID 和校区编码,工号、姓名及校区名称由后端读取并校验。
saveCampus() {
if (this.formLoading) return
this.$refs.campusFormRef.validate((valid) => {
if (!valid) return
this.$set(this, "formLoading", true)
this.$axios.post("/platform/staffManage/birthday/export/saveCampus", {
userId: this.campusForm.userId,
campusId: this.campusForm.campusId
}).then((res) => {
if (res.code === 0) {
this.$message.success("所属校区修改成功")
this.$set(this, "campusDialogVisible", false)
this.doSearch()
} else {
this.$message.error(res.msg || "所属校区修改失败")
}
}).catch(() => {
this.$message.error("所属校区修改失败,请稍后重试")
}).finally(() => {
this.$set(this, "formLoading", false)
})
})
},
initOrganizationOptions() {
if (this.$auth.hasRoleOr("SYSADMIN, SCHOOL_UNION_ADMIN, SCHOOL_UNION_MEMBER_ADMIN")) {
this.$businessTool.listUnion().then((data) => {
@@ -110,7 +110,7 @@ const MEMBER_CHANGE = {
</el-select>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item v-else label="所属校区">
<el-descriptions-item v-else-if="!replaceWelfareWithCampus" label="所属校区">
<el-form-item prop="campus">
<dict-select style="width: 100%" placeholder="请选择所属校区" v-model="formData.campus"
:disabled="allowFields('campus')" code="USER_CAMPUS"></dict-select>
@@ -196,7 +196,14 @@ const MEMBER_CHANGE = {
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="福利会员状态">
<!-- 管理页在福利会员位置展示校区,保留三级单位;其他调用方沿用原字段布局。 -->
<el-descriptions-item v-if="replaceWelfareWithCampus" label="所属校区">
<el-form-item prop="campus">
<dict-select style="width: 100%" placeholder="请选择所属校区" v-model="formData.campus"
:disabled="allowFields('campus')" code="USER_CAMPUS"></dict-select>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item v-else label="福利会员状态">
<el-form-item prop="welfareMember">
<el-radio-group v-model="formData.welfareMember" size="small" class="welfare-member-radio-group"
style="display: flex; align-items: center; flex-wrap: nowrap; white-space: nowrap;">
@@ -288,6 +295,8 @@ const MEMBER_CHANGE = {
props: {
id: { type: String, default: '' },
showThreeUnit: { type: Boolean, default: false },
// 仅管理页启用福利会员与校区的展示替换,默认保持共用页面行为。
replaceWelfareWithCampus: { type: Boolean, default: false },
},
mixins: [initTableMixins],
store,
@@ -406,9 +415,7 @@ const MEMBER_CHANGE = {
.then((resp) => {
if (resp.code === 0) {
this.threeUnits = resp.data || []
if (this.threeUnits.length === 0) {
this.$message.warning("当前所属单位未配置三级单位")
}
// 未配置三级单位时保持空选项,允许继续编辑其他人员信息。
} else {
this.$message.error(resp.msg || "三级单位查询失败")
}
@@ -525,6 +532,7 @@ const MEMBER_CHANGE = {
this.$set(this.formData, "position", position)
this.$set(this.formData, "education", education)
this.$set(this.formData, "academicDegree", academicDegree)
// 与编辑接口及变更记录统一使用 campus,正确回显当前人员所属校区。
this.$set(this.formData, "campus", campus)
this.$set(this.formData, "threeUnitId", threeUnitId)
this.$set(this.formData, "userState", userState)
@@ -185,16 +185,9 @@ layout("/layouts/platform.html"){
</template>
</el-table-column>
<el-table-column align="center" header-align="center" label="福利会员" prop="member"
<!-- 所属校区展示列表接口返回的 campus 字段。 -->
<el-table-column align="center" header-align="center" label="所属校区" prop="campus"
show-overflow-tooltip sortable>
<template scope="{row}">
<span class="text-success " v-if="row.welfareMember==1">
<i class="fa fa-circle ml5"></i>
</span>
<span class="text-danger" v-else>
<i class="fa fa-circle ml5"></i>
</span>
</template>
</el-table-column>
<el-table-column align="center" header-align="center" label="操作"
@@ -227,7 +220,7 @@ layout("/layouts/platform.html"){
</template>
<template #public>
<member-change ref="memberChangeRef" :show-three-unit="true" @do-back="$refs.guava.index()" @do-submit="doSubmit"></member-change>
<member-change ref="memberChangeRef" :show-three-unit="true" :replace-welfare-with-campus="true" @do-back="$refs.guava.index()" @do-submit="doSubmit"></member-change>
</template>
<template #edit>
@@ -22,7 +22,7 @@ layout("/layouts/platform_h5.html"){
@keyframes confetti-fall { 0% { transform: translate3d(0,-20px,0) rotate(0); opacity: 0; }
12% { opacity: 1; } 100% { transform: translate3d(35px,62vh,0) rotate(540deg); opacity: 0; } }
.greeting-zone { position: relative; z-index: 4; height: 48%; display: flex; flex-direction: column; align-items: center;
justify-content: flex-start; padding: 0 24px calc(20px + env(safe-area-inset-bottom)); box-sizing: border-box; }
justify-content: flex-start; padding: 24px 24px calc(20px + env(safe-area-inset-bottom)); box-sizing: border-box; /* 下移祝福卡片,为蛋糕底部留出间距。 */ }
.greeting-card { width: 100%; box-sizing: border-box; padding: 20px 20px 16px; border: 1px solid rgba(164,60,26,.3);
border-radius: 18px; background: rgba(255,249,228,.92); box-shadow: 0 12px 30px rgba(109,29,10,.22);
text-align: center; animation: card-enter .7s ease-out both; }
@@ -115,7 +115,7 @@ layout("/layouts/platform_h5.html"){
生日快乐,幸福安康!
</div>
</div>
<button class="receive-button" @click="openCoupon">领取生日福利</button>
<button v-if="hasCouponId" class="receive-button" @click="openCoupon">领取生日福利</button>
</div>
<button type="button" class="music-button" :class="{playing:musicPlaying}"
@@ -165,6 +165,8 @@ layout("/layouts/platform_h5.html"){
return {
appName: "${AppName!}",
userName: "${userName!}",
// 仅地址参数 id 非空时提供福利入口,后台配置的贺卡不作为按钮显示依据。
hasCouponId: "${fileId!}".trim().length > 0,
pageLoading: false,
showMusicPrompt: false,
musicPromptResolved: false,
@@ -230,7 +232,7 @@ layout("/layouts/platform_h5.html"){
}
},
openCoupon() {
if (this.showCoupon) return
if (!this.hasCouponId || this.showCoupon) return
this.$set(this, "showCoupon", true)
window.h5PopupHistory.open(this.popupHistoryToken, "birthdayCoupon")
},