add user invite

This commit is contained in:
Timi
2026-08-15 01:33:52 +08:00
parent e4d02a714f
commit c810162926
8 changed files with 764 additions and 13 deletions
+189
View File
@@ -0,0 +1,189 @@
<template>
<t-dialog
v-model:visible="popupVisible"
:cancel-btn="null"
confirm-btn="生成邀请海报"
:close-on-overlay-click="!pickerVisible"
:z-index="10000"
destroy-on-close
@confirm="generateInvite"
>
<section class="invite-popup">
<header class="header">
<h2>配置邀请信息</h2>
<button class="close" type="button" @click="popupVisible = false">×</button>
</header>
<t-form class="form" label-align="left">
<t-form-item
v-if="isGlobalManager"
label="目标门店"
arrow
@click="openPicker('store')"
>
<span v-text="selectedStoreName" />
</t-form-item>
<t-form-item
label="目标角色"
arrow
@click="openPicker('role')"
>
<span v-text="selectedRoleName" />
</t-form-item>
</t-form>
</section>
</t-dialog>
<t-popup v-model="pickerVisible" placement="bottom" :z-index="11000">
<t-picker
v-model="pickerValue"
:columns="pickerColumns"
:title="pickerType === 'role' ? '选择角色' : '选择门店'"
@cancel="pickerVisible = false"
@confirm="confirmPicker"
/>
</t-popup>
</template>
<script setup lang="ts">
import { Toast } from "tdesign-mobile-vue";
import ManagedUserAPI from "@/api/ManagedUserAPI";
import { useCurrentStoreStore } from "@/store/currentStoreStore";
import { gaoRoleCodes } from "@/utils/permission";
import { RoleAPI, useUserStore } from "timi-web";
defineOptions({ name: "UserInvite" });
const props = defineProps<{
visible: boolean;
storeId?: string;
}>();
const emit = defineEmits<{
"update:visible": [value: boolean];
}>();
const router = useRouter();
const userStore = useUserStore();
const currentStoreStore = useCurrentStoreStore();
const isGlobalManager = computed(() => userStore.hasRoles(gaoRoleCodes.globalManager));
const popupVisible = computed({
get: () => props.visible,
set: value => emit("update:visible", value)
});
const formModel = reactive({ roleId: "", storeId: "" });
const roleList = ref<Array<{ id?: string; name?: string; code?: string }>>([]);
const isGenerating = ref(false);
const isLoaded = ref(false);
const roleOptions = computed(() => roleList.value.filter(item => item.id).map(item => ({ label: item.name || item.code || "未命名角色", value: item.id as string })));
const storeOptions = computed(() => currentStoreStore.storeList.filter(item => item.id).map(item => ({ label: item.name || item.code || "未命名门店", value: item.id as string })));
const selectedRoleName = computed(() => roleOptions.value.find(item => item.value === formModel.roleId)?.label || "请选择角色");
const selectedStoreName = computed(() => storeOptions.value.find(item => item.value === formModel.storeId)?.label || "请选择门店");
const pickerVisible = ref(false);
const pickerType = ref<"role" | "store">("role");
const pickerValue = ref<Array<string | number>>([]);
const pickerColumns = computed(() => [pickerType.value === "role" ? roleOptions.value : storeOptions.value]);
async function loadData(): Promise<void> {
if (isLoaded.value) {
return;
}
const roleRequest = RoleAPI.manageableList("GAO");
if (isGlobalManager.value) {
await currentStoreStore.loadStoreList();
formModel.storeId = currentStoreStore.storeList.some(item => item.id === props.storeId)
? props.storeId || ""
: currentStoreStore.currentStoreId;
}
roleList.value = await roleRequest;
if (!isGlobalManager.value) {
const store = await currentStoreStore.loadLoginStore();
formModel.storeId = store?.id || "";
}
isLoaded.value = true;
}
function openPicker(type: "role" | "store"): void {
pickerType.value = type;
pickerValue.value = [type === "role" ? formModel.roleId : formModel.storeId];
pickerVisible.value = true;
}
function confirmPicker(): void {
const value = String(pickerValue.value[0] || "");
if (pickerType.value === "role") {
formModel.roleId = value;
} else {
formModel.storeId = value;
}
pickerVisible.value = false;
}
async function generateInvite(): Promise<void> {
if (!formModel.roleId || (isGlobalManager.value && !formModel.storeId)) {
Toast.warning(isGlobalManager.value ? "请选择角色和门店" : "请选择角色");
return;
}
isGenerating.value = true;
try {
const result = await ManagedUserAPI.invite(isGlobalManager.value ? { roleId: formModel.roleId, storeId: formModel.storeId } : { roleId: formModel.roleId });
popupVisible.value = false;
await router.push({
name: "UserInvitePoster",
query: {
code: result.code,
expireAt: String(result.expireAt),
storeName: isGlobalManager.value ? selectedStoreName.value : currentStoreStore.currentStoreName,
roleName: selectedRoleName.value
}
});
} finally {
isGenerating.value = false;
}
}
watch(() => props.visible, async visible => {
if (!visible) {
return;
}
try {
await loadData();
} catch {
Toast.error("邀请配置加载失败");
}
});
</script>
<style scoped lang="less">
.invite-popup {
.header {
display: flex;
align-items: center;
justify-content: space-between;
h2 {
margin: 0;
color: #0f172a;
font-size: 1.125rem;
}
.close {
border: 0;
padding: 0 .25rem;
color: #64748b;
background: transparent;
font-size: 1.75rem;
line-height: 1;
}
}
.form {
margin: 1rem 0 0 0;
}
}
:global(html.theme-dark) .invite-popup {
background: #0f172a;
.header h2 {
color: #e2e8f0;
}
}
</style>