ow
This commit is contained in:
1 parent
b5d2a2ede0
commit
aff58692bb
17 files changed
+1851
-240
No files matched your search
@@ -5,7 +5,8 @@
|
||||
* 对齐旧逻辑:
|
||||
* - FindByKey(PersonId) 取 FamilyPersonData,主对象 FamilyPerson;
|
||||
* - 头像上传 file-path=FamilyPersonAvatar(旧 FileUpload 的移动端等价:chooseImage 单图 +
|
||||
* uploadFile 直传 DmsFile/UploadDmsFile,FilePath 走请求头、form 字段名=原始文件名);
|
||||
* uploadFile 直传 DmsFile/UploadFile,FilePath 走请求头、form 字段名=原始文件名、
|
||||
* filename=分片三段式物理名并同存 AvatarFilename);
|
||||
* - 性别是 GenderPolicy 枚举,admin-form 无 select,用 #extra 行点开 option-picker 回写;
|
||||
* - 只读门控:!IsCanAmend 且 Privacy!=='Y' 时只显「基本资料」卡、隐藏其余卡与修改/删除;
|
||||
* - 保存按 CreatedBy 有无决定 Update / Insert。
|
||||
@@ -15,7 +16,7 @@ import type { AdminFormAction, AdminFormField, AdminFormSection } from "@/admin/
|
||||
import { onLoad } from "@dcloudio/uni-app";
|
||||
import { useLocale } from "uview-pro";
|
||||
import { computed, ref } from "vue";
|
||||
import { uploadFile } from "@/common/http.interceptor";
|
||||
import { buildChunkFileName, uploadFile } from "@/common/http.interceptor";
|
||||
import { useAuthGuard } from "@/composables";
|
||||
import { usePolicyOptions } from "@/composables/usePolicyOptions";
|
||||
import { FamilyPersonData } from "@/data/auto/familyPersonData";
|
||||
@@ -166,7 +167,9 @@ function onGenderConfirm(key: string): void {
|
||||
genderPickerVisible.value = false;
|
||||
}
|
||||
|
||||
/** 头像上传:单图 -> DmsFile/UploadDmsFile(FilePath=FamilyPersonAvatar),成功后本地预览 */
|
||||
/** 头像上传:单图 -> DmsFile/UploadFile(旧 FileUpload 默认通道,FilePath 头指定 FamilyPersonAvatar)。
|
||||
* 后端按 {Backup}/{FilePath}/{ext}/{分片名} 落盘,FindByKey 的 AvatarUrl 也按此拼 URL,
|
||||
* 故 AvatarFilename 必须存分片物理名(buildChunkFileName),不能存原始文件名 */
|
||||
async function onUploadAvatar(): Promise<void> {
|
||||
if (uploading.value) {
|
||||
return;
|
||||
@@ -181,13 +184,15 @@ async function onUploadAvatar(): Promise<void> {
|
||||
}
|
||||
try {
|
||||
uploading.value = true;
|
||||
const physicalName = buildChunkFileName(fileName);
|
||||
await uploadFile({
|
||||
url: "/DmsFile/UploadDmsFile",
|
||||
url: "/DmsFile/UploadFile",
|
||||
filePath,
|
||||
name: fileName,
|
||||
fileName: physicalName,
|
||||
header: { FilePath: "FamilyPersonAvatar" },
|
||||
});
|
||||
person.value.AvatarFilename = fileName;
|
||||
person.value.AvatarFilename = physicalName;
|
||||
person.value.AvatarUrl = filePath;
|
||||
uni.showToast({ title: t("FamilyPersonPage.avatarUploadedTip"), icon: "none" });
|
||||
}
|
||||
@@ -288,6 +293,26 @@ useAuthGuard(() => {
|
||||
<admin-form :nav-title="t('FamilyPersonPage.detailTitle')" :show-nav-back="true" :hero-title="heroTitle"
|
||||
:hero-chips="heroChips" :sections="sections" :model="person" :readonly="readonly" :actions="actions"
|
||||
@back="onBack" @action="onAction" @field-change="onFieldChange">
|
||||
<!-- 旧系统同款:头像就在 hero 卡左侧,显示与上传同一处;编辑态右侧出「清除头像」 -->
|
||||
<template #hero-side="{ readonly: ro }">
|
||||
<view class="hero-avatar" @tap="!ro && onUploadAvatar()">
|
||||
<image v-if="person.AvatarUrl" class="hero-avatar__img" :src="person.AvatarUrl" mode="aspectFill" />
|
||||
<u-icon v-else name="account" size="56" color="#ffffff" />
|
||||
<view v-if="!ro" class="hero-avatar__mask">
|
||||
<text v-if="uploading" class="hero-avatar__mask-text">
|
||||
{{ t("FamilyPersonPage.uploadingTip") }}
|
||||
</text>
|
||||
<u-icon v-else name="camera" size="28" color="#ffffff" />
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
<template #hero-end="{ readonly: ro }">
|
||||
<view v-if="!ro && (person.AvatarUrl || person.AvatarFilename)" class="hero-clear" @tap="onClearAvatar">
|
||||
<text class="hero-clear-text">
|
||||
{{ t("FamilyPersonPage.clearAvatar") }}
|
||||
</text>
|
||||
</view>
|
||||
</template>
|
||||
<template #extra="{ readonly: ro }">
|
||||
<!-- 只读门控提示:无修改权限且对方未公开详细资料 -->
|
||||
<view v-if="readonlyBasicOnly" class="ro-tip">
|
||||
@@ -297,38 +322,7 @@ useAuthGuard(() => {
|
||||
</view>
|
||||
|
||||
<template v-else>
|
||||
<!-- 头像 + 性别(admin-form 无 select,枚举行在这里点开的 option-picker 里回写) -->
|
||||
<view class="group">
|
||||
<view class="group-head">
|
||||
<text class="group-title">
|
||||
{{ t("FamilyPersonPage.avatarTitle") }}
|
||||
</text>
|
||||
</view>
|
||||
<view class="group-card avatar-card">
|
||||
<view class="avatar-box" :class="{ 'avatar-box--tap': !ro }" @tap="!ro && onUploadAvatar()">
|
||||
<image v-if="person.AvatarUrl" class="avatar-img" :src="person.AvatarUrl"
|
||||
mode="aspectFill" />
|
||||
<u-icon v-else name="account-fill" size="72" color="#c4c8cf" />
|
||||
</view>
|
||||
<view v-if="!ro" class="avatar-ops">
|
||||
<view class="avatar-op" @tap="onUploadAvatar">
|
||||
<u-icon name="camera" size="30" color="#059669" />
|
||||
<text class="avatar-op-text">
|
||||
{{ uploading ? t("FamilyPersonPage.uploadingTip") :
|
||||
t("FamilyPersonPage.uploadAvatar") }}
|
||||
</text>
|
||||
</view>
|
||||
<view v-if="person.AvatarUrl || person.AvatarFilename" class="avatar-op"
|
||||
@tap="onClearAvatar">
|
||||
<u-icon name="close-circle" size="30" color="#c4c8cf" />
|
||||
<text class="avatar-op-text">
|
||||
{{ t("FamilyPersonPage.clearAvatar") }}
|
||||
</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 性别(admin-form 无 select,枚举行在这里点开的 option-picker 里回写) -->
|
||||
<view class="group">
|
||||
<view class="group-card">
|
||||
<view class="enum-row" :class="{ 'enum-row--tap': !ro }"
|
||||
@@ -388,51 +382,54 @@ useAuthGuard(() => {
|
||||
border-radius: 20rpx;
|
||||
}
|
||||
|
||||
.avatar-card {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 28rpx;
|
||||
}
|
||||
|
||||
.avatar-box {
|
||||
/* hero 左侧头像(旧系统 ft-hero-avatar 同款):显示与上传同一处,编辑态覆相机遮罩 */
|
||||
.hero-avatar {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex: none;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 160rpx;
|
||||
height: 160rpx;
|
||||
width: 120rpx;
|
||||
height: 120rpx;
|
||||
overflow: hidden;
|
||||
background-color: $u-bg-color;
|
||||
border: 2rpx solid $u-border-color;
|
||||
background-color: rgba(255, 255, 255, 0.18);
|
||||
border: 4rpx solid rgba(255, 255, 255, 0.55);
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.avatar-box--tap {
|
||||
border-style: dashed;
|
||||
}
|
||||
|
||||
.avatar-img {
|
||||
.hero-avatar__img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.avatar-ops {
|
||||
.hero-avatar__mask {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 20rpx;
|
||||
}
|
||||
|
||||
.avatar-op {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background-color: rgba(0, 0, 0, 0.35);
|
||||
}
|
||||
|
||||
.avatar-op-text {
|
||||
margin-left: 8rpx;
|
||||
font-size: 26rpx;
|
||||
color: $u-content-color;
|
||||
.hero-avatar__mask-text {
|
||||
font-size: 20rpx;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
/* hero 右侧「清除头像」白胶囊(旧系统同款位) */
|
||||
.hero-clear {
|
||||
flex: none;
|
||||
padding: 10rpx 24rpx;
|
||||
background-color: rgba(255, 255, 255, 0.22);
|
||||
border-radius: 999rpx;
|
||||
}
|
||||
|
||||
.hero-clear-text {
|
||||
font-size: 24rpx;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.enum-row {
|
||||
|
||||
Reference in new issue
Block a user