feat: inline edit resource store status
This commit is contained in:
parent
1b835ba52d
commit
fa5663bdbf
@ -1,6 +1,7 @@
|
||||
<script lang="ts" setup>
|
||||
import {
|
||||
computed,
|
||||
nextTick,
|
||||
reactive,
|
||||
ref,
|
||||
} from 'vue';
|
||||
@ -13,6 +14,7 @@ import {
|
||||
Card,
|
||||
Empty,
|
||||
Input,
|
||||
InputNumber,
|
||||
message,
|
||||
Pagination,
|
||||
Select,
|
||||
@ -20,11 +22,14 @@ import {
|
||||
Switch,
|
||||
Table,
|
||||
Tag,
|
||||
Tooltip,
|
||||
} from 'antdv-next';
|
||||
|
||||
import {
|
||||
addOrUpdatePropsStore,
|
||||
offShelfPropsSource,
|
||||
pagePropsSource,
|
||||
updatePropsSource,
|
||||
} from '#/api/legacy/props';
|
||||
import InlineFilterField from '#/views/_shared/inline-filter-field.vue';
|
||||
import InlineFilterToolbar from '#/views/_shared/inline-filter-toolbar.vue';
|
||||
@ -64,6 +69,9 @@ const formOpen = ref(false);
|
||||
const salesOpen = ref(false);
|
||||
const overviewOpen = ref(false);
|
||||
const activeRow = ref<null | Record<string, any>>(null);
|
||||
const amountEditingId = ref<null | string>(null);
|
||||
const amountSavingId = ref<null | string>(null);
|
||||
const amountDraft = ref<null | number>(null);
|
||||
|
||||
const query = reactive({
|
||||
cursor: 1,
|
||||
@ -83,6 +91,7 @@ const columns = [
|
||||
{ dataIndex: 'cover', key: 'cover', title: '资源', width: 120 },
|
||||
{ dataIndex: 'del', key: 'del', title: '上/下架', width: 120 },
|
||||
{ dataIndex: 'amount', key: 'amount', title: '底价', width: 100 },
|
||||
{ dataIndex: 'storeShelfStatus', key: 'storeShelfStatus', title: '是否上架道具商店', width: 160 },
|
||||
{ dataIndex: 'adminFree', key: 'adminFree', title: 'Admin Free', width: 120 },
|
||||
{ dataIndex: 'actions', key: 'actions', title: '操作', width: 180 },
|
||||
];
|
||||
@ -122,6 +131,108 @@ async function handleStatusChange(record: Record<string, any>, checked: boolean)
|
||||
}
|
||||
}
|
||||
|
||||
function getRecordId(record: Record<string, any>) {
|
||||
return String(record.id || '');
|
||||
}
|
||||
|
||||
function isAmountEditing(record: Record<string, any>) {
|
||||
return amountEditingId.value === getRecordId(record);
|
||||
}
|
||||
|
||||
function isAmountSaving(record: Record<string, any>) {
|
||||
return amountSavingId.value === getRecordId(record);
|
||||
}
|
||||
|
||||
function startAmountEdit(record: Record<string, any>) {
|
||||
if (!canEdit.value) {
|
||||
return;
|
||||
}
|
||||
amountEditingId.value = getRecordId(record);
|
||||
amountDraft.value = Number(record.amount ?? 0);
|
||||
void nextTick();
|
||||
}
|
||||
|
||||
function cancelAmountEdit() {
|
||||
amountEditingId.value = null;
|
||||
amountDraft.value = null;
|
||||
}
|
||||
|
||||
function buildPropsSourceUpdatePayload(record: Record<string, any>, amount: number) {
|
||||
return {
|
||||
adminFree: Boolean(record.adminFree),
|
||||
amount,
|
||||
code: record.code,
|
||||
cover: record.cover,
|
||||
expand: record.expand,
|
||||
id: record.id,
|
||||
name: record.name,
|
||||
sourceUrl: record.sourceUrl,
|
||||
sysOrigin: record.sysOrigin,
|
||||
type: record.type,
|
||||
};
|
||||
}
|
||||
|
||||
async function handleAmountConfirm(record: Record<string, any>) {
|
||||
if (!isAmountEditing(record) || isAmountSaving(record)) {
|
||||
return;
|
||||
}
|
||||
const amount = Number(amountDraft.value);
|
||||
if (!Number.isFinite(amount) || amount < 0) {
|
||||
message.warning('请输入正确的底价');
|
||||
return;
|
||||
}
|
||||
const previous = record.amount;
|
||||
if (Number(previous ?? 0) === amount) {
|
||||
cancelAmountEdit();
|
||||
return;
|
||||
}
|
||||
amountSavingId.value = getRecordId(record);
|
||||
record.amount = amount;
|
||||
try {
|
||||
await updatePropsSource(buildPropsSourceUpdatePayload(record, amount));
|
||||
message.success('底价已更新');
|
||||
cancelAmountEdit();
|
||||
} catch (error) {
|
||||
record.amount = previous;
|
||||
throw error;
|
||||
} finally {
|
||||
amountSavingId.value = null;
|
||||
}
|
||||
}
|
||||
|
||||
function getStoreCommodity(record: Record<string, any>) {
|
||||
return record.storeCommodity || null;
|
||||
}
|
||||
|
||||
function buildStoreShelfPayload(record: Record<string, any>, checked: boolean) {
|
||||
const commodity = getStoreCommodity(record);
|
||||
return {
|
||||
...commodity,
|
||||
label: commodity.label || '',
|
||||
propsType: commodity.propsType || record.type,
|
||||
shelfStatus: checked,
|
||||
sourceId: commodity.sourceId || record.id,
|
||||
sysOrigin: commodity.sysOrigin || record.sysOrigin,
|
||||
};
|
||||
}
|
||||
|
||||
async function handleStoreShelfStatusChange(record: Record<string, any>, checked: boolean) {
|
||||
const commodity = getStoreCommodity(record);
|
||||
if (!commodity) {
|
||||
message.warning('请先在道具商店配置该资源');
|
||||
return;
|
||||
}
|
||||
const previous = commodity.shelfStatus;
|
||||
commodity.shelfStatus = checked;
|
||||
try {
|
||||
await addOrUpdatePropsStore(buildStoreShelfPayload(record, checked));
|
||||
message.success('道具商店状态已更新');
|
||||
} catch (error) {
|
||||
commodity.shelfStatus = previous;
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
function openCreate() {
|
||||
activeRow.value = null;
|
||||
formOpen.value = true;
|
||||
@ -203,7 +314,7 @@ loadData(true);
|
||||
:loading="loading"
|
||||
:pagination="false"
|
||||
row-key="id"
|
||||
:scroll="{ x: 1160 }"
|
||||
:scroll="{ x: 1320 }"
|
||||
>
|
||||
<template #bodyCell="{ column, record }">
|
||||
<template v-if="column.key === 'cover'">
|
||||
@ -217,6 +328,42 @@ loadData(true);
|
||||
@change="(checked: boolean) => handleStatusChange(record, checked)"
|
||||
/>
|
||||
</template>
|
||||
<template v-else-if="column.key === 'amount'">
|
||||
<InputNumber
|
||||
v-if="isAmountEditing(record)"
|
||||
v-model:value="amountDraft"
|
||||
autofocus
|
||||
:disabled="isAmountSaving(record)"
|
||||
:min="0"
|
||||
size="small"
|
||||
style="width: 92px"
|
||||
@blur="() => handleAmountConfirm(record)"
|
||||
@keydown.enter.prevent="() => handleAmountConfirm(record)"
|
||||
@keydown.esc="cancelAmountEdit"
|
||||
/>
|
||||
<span
|
||||
v-else
|
||||
:class="['amount-value', { 'amount-value--editable': canEdit }]"
|
||||
@click="startAmountEdit(record)"
|
||||
>
|
||||
{{ record.amount ?? 0 }}
|
||||
</span>
|
||||
</template>
|
||||
<template v-else-if="column.key === 'storeShelfStatus'">
|
||||
<Tooltip
|
||||
:title="getStoreCommodity(record) ? '' : '请先在道具商店配置该资源'"
|
||||
>
|
||||
<Switch
|
||||
:checked="Boolean(getStoreCommodity(record)?.shelfStatus)"
|
||||
:disabled="!getStoreCommodity(record)"
|
||||
checked-children="上架"
|
||||
un-checked-children="下架"
|
||||
@change="
|
||||
(checked: boolean) => handleStoreShelfStatusChange(record, checked)
|
||||
"
|
||||
/>
|
||||
</Tooltip>
|
||||
</template>
|
||||
<template v-else-if="column.key === 'adminFree'">
|
||||
<Tag :color="record.adminFree ? 'green' : 'default'">
|
||||
{{ record.adminFree ? '是' : '否' }}
|
||||
@ -286,4 +433,14 @@ loadData(true);
|
||||
.toolbar {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.amount-value {
|
||||
display: inline-block;
|
||||
min-width: 48px;
|
||||
}
|
||||
|
||||
.amount-value--editable {
|
||||
color: #1677ff;
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user