feat: 邀请函邮件发送 + 首次设密/密码为空 + 姓名单一可信源

邀请发送 (菜单暂隐藏, 待确认参数见 发送邀请-待确认参数.md):
- 后端: BizInvite / BizInviteRecipient + Controller/Service/Mapper/XML
- 邮件: InviteMailSender (spring-boot-starter-mail SMTP) + application*.yml 邮件配置
- 上传进度: UploadProgressRegistry + UploadProgressController
- 前端: InviteList / InviteNew / InviteDetail / InviteView + api/business/invite.js
- 原型: proto/html/components/invite-detail / new-invitation / send-invitation

登录/账号:
- 首次设密: /getInfo 返回 isPasswordEmpty, SysProfileController 密码为空时跳过旧密码校验, ForcePasswordDialog 强制弹窗
- 姓名单一可信源 resolveDisplayName: doctor→biz_expert.name, sponsor/executor→biz_person.name, 其余回退 nick_name
- OA compliance 门禁改为按手机号查 ecology 视图 (不再限定 manager/leader)

其它:
- OSS zip 在线查看 (列清单+取单文件, 公开只读) + SecurityConfig permitAll
- doctor 项目详情 ProjectDetail.vue
- 数据库/测试/设计文档 (md) 入库
This commit is contained in:
郭庆泰
2026-09-10 20:40:49 +08:00
parent 56615f9806
commit 5a0a892574
171 changed files with 11032 additions and 876 deletions
+98 -3
View File
@@ -29,6 +29,24 @@
</view>
</view>
<!-- 连拍已选照片条 -->
<view v-if="shots.length" class="shot-strip">
<view class="shot-scroll">
<view v-for="(s, i) in shots" :key="i" class="shot-thumb">
<image class="shot-img" :src="s" mode="aspectFill" />
<view class="shot-del" @click="removeShot(i)">
<text>×</text>
</view>
</view>
</view>
<view class="shot-bar">
<text class="shot-count">已拍 {{ shots.length }} 张</text>
<button class="submit-btn" @click="submitAll">
<text>提交全部</text>
</button>
</view>
</view>
<!-- 底部控制条 -->
<view class="controls">
<button class="ctrl-btn" @click="flipCamera">
@@ -54,8 +72,8 @@
<button class="preview-btn preview-btn-cancel" @click="retake">
<text>重拍</text>
</button>
<button class="preview-btn preview-btn-confirm" @click="confirm">
<text>使用</text>
<button class="preview-btn preview-btn-confirm" @click="addShot">
<text>加入</text>
</button>
</view>
</view>
@@ -67,7 +85,8 @@ import { useCamera } from '@/composables/useCamera'
const videoId = 'signin-video'
// A4 纸: 从顶边到底边的一竖条, 水平位置在 60%~70% 宽度 (签到人手机号/身份证号所在列) 做高斯模糊脱敏
const { captured, errorMsg, startCamera, flipCamera, takePhoto, retake, confirm } =
// 签到表支持连拍多张: shots 攒批 + 提交全部
const { captured, errorMsg, startCamera, flipCamera, takePhoto, retake, shots, addShot, removeShot, submitAll } =
useCamera(videoId, { start: 0.6, end: 0.7, radius: 20 })
function goBack() {
@@ -315,4 +334,80 @@ function goBack() {
background: #FFD600;
color: #000;
}
/* ========== 连拍已选照片条 ========== */
.shot-strip {
background: rgba(0, 0, 0, 0.7);
padding: 20rpx 30rpx;
}
.shot-scroll {
display: flex;
flex-direction: row;
overflow-x: auto;
}
.shot-thumb {
position: relative;
width: 120rpx;
height: 160rpx;
margin-right: 16rpx;
flex-shrink: 0;
border: 2rpx solid #fff;
border-radius: 8rpx;
overflow: hidden;
}
.shot-img {
width: 100%;
height: 100%;
}
.shot-del {
position: absolute;
top: 0;
right: 0;
width: 40rpx;
height: 40rpx;
background: rgba(0, 0, 0, 0.6);
border-radius: 0 0 0 12rpx;
display: flex;
justify-content: center;
align-items: center;
}
.shot-del text {
color: #fff;
font-size: 30rpx;
line-height: 1;
}
.shot-bar {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
margin-top: 16rpx;
}
.shot-count {
color: #ccc;
font-size: 26rpx;
}
.submit-btn {
margin: 0;
padding: 0 40rpx;
min-height: 68rpx;
border: none;
outline: none;
appearance: none;
-webkit-appearance: none;
border-radius: 34rpx;
background: #FFD600;
color: #000;
font-size: 28rpx;
font-weight: bold;
line-height: 68rpx;
}
</style>