This commit is contained in:
zhx 2026-06-25 19:29:26 +08:00
parent 25ccb09f31
commit 9678f262a9
2 changed files with 121 additions and 11 deletions

View File

@ -53,6 +53,46 @@ const form = reactive({
const isUpdate = computed(() => Boolean(props.row?.id));
const title = computed(() => (isUpdate.value ? '修改经理' : '添加经理'));
function normalizeFeatureEnabled(value: unknown) {
if (value === undefined || value === null || value === '') {
return true;
}
if (typeof value === 'boolean') {
return value;
}
if (typeof value === 'number') {
return value !== 0;
}
const normalized = String(value).trim().toLowerCase();
return !['0', 'false', 'n', 'no', 'off', '关', '关闭'].includes(normalized);
}
function camelToSnake(key: string) {
return key.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`);
}
function featurePayloadKey(key: FeatureSwitchKey) {
const bodyKey = key.replace(/^can/, '');
return bodyKey ? `${bodyKey[0]?.toLowerCase()}${bodyKey.slice(1)}` : key;
}
function rowFeatureValue(row: null | Record<string, any>, key: FeatureSwitchKey) {
const snakeKey = camelToSnake(key);
const value = Object.prototype.hasOwnProperty.call(row || {}, key)
? row?.[key]
: undefined;
if (value !== undefined) {
return value;
}
if (Object.prototype.hasOwnProperty.call(row || {}, snakeKey)) {
return row?.[snakeKey];
}
const payloadKey = featurePayloadKey(key);
return Object.prototype.hasOwnProperty.call(row?.features || {}, payloadKey)
? row?.features?.[payloadKey]
: row?.features?.[key];
}
watch(
() => props.open,
(open) => {
@ -64,15 +104,19 @@ watch(
form.sysOrigin = props.row?.sysOrigin || props.sysOrigin || 'LIKEI';
form.contact = props.row?.contact || '';
form.regionId = String(props.row?.regionId || '');
form.canAddBdLeader = props.row?.canAddBdLeader !== false;
form.canGiftProps = props.row?.canGiftProps !== false;
form.canBanUser = props.row?.canBanUser !== false;
form.canUnbanUser = props.row?.canUnbanUser !== false;
form.canChangeCountry = props.row?.canChangeCountry !== false;
form.canAddBdLeader = normalizeFeatureEnabled(rowFeatureValue(props.row, 'canAddBdLeader'));
form.canGiftProps = normalizeFeatureEnabled(rowFeatureValue(props.row, 'canGiftProps'));
form.canBanUser = normalizeFeatureEnabled(rowFeatureValue(props.row, 'canBanUser'));
form.canUnbanUser = normalizeFeatureEnabled(rowFeatureValue(props.row, 'canUnbanUser'));
form.canChangeCountry = normalizeFeatureEnabled(rowFeatureValue(props.row, 'canChangeCountry'));
},
{ immediate: true },
);
function setFeature(key: FeatureSwitchKey, checked: unknown) {
form[key] = normalizeFeatureEnabled(checked);
}
function toggleFeature(key: FeatureSwitchKey) {
form[key] = !form[key];
}
@ -153,7 +197,12 @@ async function handleSubmit() {
@keydown.space.prevent="toggleFeature('canAddBdLeader')"
>
<span>加BD Leader</span>
<Switch v-model:checked="form.canAddBdLeader" @click.stop />
<span class="feature-switch-control" @click.stop>
<Switch
:checked="form.canAddBdLeader"
@change="(checked) => setFeature('canAddBdLeader', checked)"
/>
</span>
</div>
<div
class="feature-switch-row"
@ -165,7 +214,12 @@ async function handleSubmit() {
@keydown.space.prevent="toggleFeature('canGiftProps')"
>
<span>赠送道具</span>
<Switch v-model:checked="form.canGiftProps" @click.stop />
<span class="feature-switch-control" @click.stop>
<Switch
:checked="form.canGiftProps"
@change="(checked) => setFeature('canGiftProps', checked)"
/>
</span>
</div>
<div
class="feature-switch-row"
@ -177,7 +231,12 @@ async function handleSubmit() {
@keydown.space.prevent="toggleFeature('canBanUser')"
>
<span>封禁用户</span>
<Switch v-model:checked="form.canBanUser" @click.stop />
<span class="feature-switch-control" @click.stop>
<Switch
:checked="form.canBanUser"
@change="(checked) => setFeature('canBanUser', checked)"
/>
</span>
</div>
<div
class="feature-switch-row"
@ -189,7 +248,12 @@ async function handleSubmit() {
@keydown.space.prevent="toggleFeature('canUnbanUser')"
>
<span>解封用户</span>
<Switch v-model:checked="form.canUnbanUser" @click.stop />
<span class="feature-switch-control" @click.stop>
<Switch
:checked="form.canUnbanUser"
@change="(checked) => setFeature('canUnbanUser', checked)"
/>
</span>
</div>
<div
class="feature-switch-row"
@ -201,7 +265,12 @@ async function handleSubmit() {
@keydown.space.prevent="toggleFeature('canChangeCountry')"
>
<span>改国家</span>
<Switch v-model:checked="form.canChangeCountry" @click.stop />
<span class="feature-switch-control" @click.stop>
<Switch
:checked="form.canChangeCountry"
@change="(checked) => setFeature('canChangeCountry', checked)"
/>
</span>
</div>
</div>
</FormItem>
@ -230,4 +299,9 @@ async function handleSubmit() {
outline: 2px solid rgb(22 119 255 / 20%);
outline-offset: 2px;
}
.feature-switch-control {
align-items: center;
display: inline-flex;
}
</style>

View File

@ -85,8 +85,44 @@ function getUserShortId(profile?: Record<string, any> | null) {
return profile?.actualAccount || profile?.account || profile?.id || '-';
}
function normalizeFeatureEnabled(value: unknown) {
if (value === undefined || value === null || value === '') {
return true;
}
if (typeof value === 'boolean') {
return value;
}
if (typeof value === 'number') {
return value !== 0;
}
const normalized = String(value).trim().toLowerCase();
return !['0', 'false', 'n', 'no', 'off', '关', '关闭'].includes(normalized);
}
function camelToSnake(key: string) {
return key.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`);
}
function featurePayloadKey(key: string) {
const bodyKey = key.replace(/^can/, '');
return bodyKey ? `${bodyKey[0]?.toLowerCase()}${bodyKey.slice(1)}` : key;
}
function isFeatureEnabled(record: Record<string, any>, key: string) {
return record?.[key] !== false;
const snakeKey = camelToSnake(key);
let value = Object.prototype.hasOwnProperty.call(record || {}, key)
? record?.[key]
: undefined;
if (value === undefined && Object.prototype.hasOwnProperty.call(record || {}, snakeKey)) {
value = record?.[snakeKey];
}
if (value === undefined && record?.features) {
const payloadKey = featurePayloadKey(key);
value = Object.prototype.hasOwnProperty.call(record.features, payloadKey)
? record.features[payloadKey]
: record.features[key];
}
return normalizeFeatureEnabled(value);
}
async function loadData(reset = false) {