fix
This commit is contained in:
@@ -20,7 +20,7 @@ type CurrentEmployee = {
|
|||||||
avatar?: string | null;
|
avatar?: string | null;
|
||||||
};
|
};
|
||||||
|
|
||||||
type MainTabKey = "incoming" | "transfer" | "review" | "outgoing" | "archive";
|
type MainTabKey = "incoming" | "transfer" | "review" | "outgoing";
|
||||||
type DocTabKey =
|
type DocTabKey =
|
||||||
| "all"
|
| "all"
|
||||||
| "simple"
|
| "simple"
|
||||||
@@ -40,6 +40,22 @@ const employeeLoading = ref(false);
|
|||||||
const refreshing = ref(false);
|
const refreshing = ref(false);
|
||||||
const switchingList = ref(false);
|
const switchingList = ref(false);
|
||||||
let suppressDocTabReload = false;
|
let suppressDocTabReload = false;
|
||||||
|
const mainTabCounts = ref<Record<MainTabKey, number>>({
|
||||||
|
incoming: 0,
|
||||||
|
transfer: 0,
|
||||||
|
review: 0,
|
||||||
|
outgoing: 0,
|
||||||
|
});
|
||||||
|
const docTabCounts = ref<Record<DocTabKey, number>>({
|
||||||
|
all: 0,
|
||||||
|
simple: 0,
|
||||||
|
memo: 0,
|
||||||
|
bill: 0,
|
||||||
|
contract: 0,
|
||||||
|
contract_application: 0,
|
||||||
|
entry_letter: 0,
|
||||||
|
outgoing_letter: 0,
|
||||||
|
});
|
||||||
|
|
||||||
const {
|
const {
|
||||||
items: tasks,
|
items: tasks,
|
||||||
@@ -48,6 +64,7 @@ const {
|
|||||||
load: loadTasks,
|
load: loadTasks,
|
||||||
} = useModelApi<Task, TaskCreate, TaskUpdate, TaskListParams>(taskApi, {
|
} = useModelApi<Task, TaskCreate, TaskUpdate, TaskListParams>(taskApi, {
|
||||||
defaultListParams: { ordering: "-id" },
|
defaultListParams: { ordering: "-id" },
|
||||||
|
autoLoad: false,
|
||||||
loadErrorMessage: "Не удалось загрузить задачи",
|
loadErrorMessage: "Не удалось загрузить задачи",
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -63,6 +80,7 @@ const {
|
|||||||
TaskTransferListParams
|
TaskTransferListParams
|
||||||
>(taskTransferApi, {
|
>(taskTransferApi, {
|
||||||
defaultListParams: { ordering: "-id" },
|
defaultListParams: { ordering: "-id" },
|
||||||
|
autoLoad: false,
|
||||||
loadErrorMessage: "Не удалось загрузить переносы срока",
|
loadErrorMessage: "Не удалось загрузить переносы срока",
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -71,7 +89,6 @@ const mainTabs = [
|
|||||||
{ key: "transfer", label: "Перенос срока", icon: "underway-o" },
|
{ key: "transfer", label: "Перенос срока", icon: "underway-o" },
|
||||||
{ key: "review", label: "Для проверки", icon: "eye-o" },
|
{ key: "review", label: "Для проверки", icon: "eye-o" },
|
||||||
{ key: "outgoing", label: "Исходящие", icon: "send-gift-o" },
|
{ key: "outgoing", label: "Исходящие", icon: "send-gift-o" },
|
||||||
{ key: "archive", label: "Архив", icon: "folder-o" },
|
|
||||||
] as const;
|
] as const;
|
||||||
|
|
||||||
const docTabs = [
|
const docTabs = [
|
||||||
@@ -91,6 +108,7 @@ const visibleItems = computed(() =>
|
|||||||
const activeLoading = computed(() =>
|
const activeLoading = computed(() =>
|
||||||
mainTab.value === "transfer" ? taskTransferLoading.value : taskLoading.value,
|
mainTab.value === "transfer" ? taskTransferLoading.value : taskLoading.value,
|
||||||
);
|
);
|
||||||
|
const showLoading = computed(() => activeLoading.value || refreshing.value);
|
||||||
const showEmployeeLoading = computed(
|
const showEmployeeLoading = computed(
|
||||||
() =>
|
() =>
|
||||||
employeeLoading.value &&
|
employeeLoading.value &&
|
||||||
@@ -101,6 +119,11 @@ const activeError = computed(() =>
|
|||||||
mainTab.value === "transfer" ? taskTransferError.value : taskError.value,
|
mainTab.value === "transfer" ? taskTransferError.value : taskError.value,
|
||||||
);
|
);
|
||||||
const showDocTabs = computed(() => mainTab.value !== "transfer");
|
const showDocTabs = computed(() => mainTab.value !== "transfer");
|
||||||
|
const visibleDocTabs = computed(() =>
|
||||||
|
showDocTabs.value
|
||||||
|
? docTabs.filter((tab) => (docTabCounts.value[tab.key] ?? 0) > 0)
|
||||||
|
: [],
|
||||||
|
);
|
||||||
|
|
||||||
function personName(
|
function personName(
|
||||||
person: { short_name?: string | null; name?: string | null } | null,
|
person: { short_name?: string | null; name?: string | null } | null,
|
||||||
@@ -120,6 +143,10 @@ function taskTitle(task: {
|
|||||||
return task.text?.trim() || task.result?.trim() || `Задача #${task.id}`;
|
return task.text?.trim() || task.result?.trim() || `Задача #${task.id}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function badgeValue(count: number) {
|
||||||
|
return count > 0 ? count : undefined;
|
||||||
|
}
|
||||||
|
|
||||||
function isTaskTransfer(item: Task | TaskTransfer): item is TaskTransfer {
|
function isTaskTransfer(item: Task | TaskTransfer): item is TaskTransfer {
|
||||||
return "employee_from" in item;
|
return "employee_from" in item;
|
||||||
}
|
}
|
||||||
@@ -144,19 +171,17 @@ function itemPath(item: Task | TaskTransfer) {
|
|||||||
return isTaskTransfer(item) ? `/tasks/${item.task.id}` : `/tasks/${item.id}`;
|
return isTaskTransfer(item) ? `/tasks/${item.task.id}` : `/tasks/${item.id}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function taskParams(): TaskListParams | TaskTransferListParams | null {
|
function buildTaskParams(
|
||||||
if (!employee.value) {
|
tab: MainTabKey,
|
||||||
return null;
|
doc: DocTabKey,
|
||||||
}
|
employeeId: number,
|
||||||
|
): TaskListParams | TaskTransferListParams | null {
|
||||||
const employeeId = employee.value.id;
|
switch (tab) {
|
||||||
|
|
||||||
switch (mainTab.value) {
|
|
||||||
case "incoming":
|
case "incoming":
|
||||||
return {
|
return {
|
||||||
doer: employeeId,
|
doer: employeeId,
|
||||||
archive: false,
|
archive: false,
|
||||||
typ: docTab.value === "all" ? undefined : docTab.value,
|
typ: doc === "all" ? undefined : doc,
|
||||||
q: "entry",
|
q: "entry",
|
||||||
incomplete: true,
|
incomplete: true,
|
||||||
};
|
};
|
||||||
@@ -164,24 +189,50 @@ function taskParams(): TaskListParams | TaskTransferListParams | null {
|
|||||||
return {
|
return {
|
||||||
q: "to_approve",
|
q: "to_approve",
|
||||||
incomplete: true,
|
incomplete: true,
|
||||||
typ: docTab.value === "all" ? undefined : docTab.value,
|
archive: false,
|
||||||
|
typ: doc === "all" ? undefined : doc,
|
||||||
};
|
};
|
||||||
case "outgoing":
|
case "outgoing":
|
||||||
return {
|
return {
|
||||||
q: "outgoing",
|
q: "outgoing",
|
||||||
archive: false,
|
archive: false,
|
||||||
incomplete: true,
|
incomplete: true,
|
||||||
typ: docTab.value === "all" ? undefined : docTab.value,
|
typ: doc === "all" ? undefined : doc,
|
||||||
};
|
};
|
||||||
case "archive":
|
case "transfer":
|
||||||
return {
|
return {
|
||||||
typ: docTab.value === "all" ? undefined : docTab.value,
|
employee_to: employeeId,
|
||||||
|
status: "A",
|
||||||
};
|
};
|
||||||
default:
|
default:
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function taskParams(): TaskListParams | TaskTransferListParams | null {
|
||||||
|
if (!employee.value) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return buildTaskParams(mainTab.value, docTab.value, employee.value.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
function taskCountParams(tab: MainTabKey): TaskListParams | TaskTransferListParams | null {
|
||||||
|
if (!employee.value) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return buildTaskParams(tab, "all", employee.value.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
function docCountParams(doc: DocTabKey): TaskListParams | null {
|
||||||
|
if (!employee.value || mainTab.value === "transfer") {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return buildTaskParams(mainTab.value, doc, employee.value.id) as TaskListParams;
|
||||||
|
}
|
||||||
|
|
||||||
async function loadCurrentEmployee() {
|
async function loadCurrentEmployee() {
|
||||||
employeeLoading.value = true;
|
employeeLoading.value = true;
|
||||||
employeeError.value = "";
|
employeeError.value = "";
|
||||||
@@ -217,10 +268,80 @@ async function reloadList() {
|
|||||||
await loadTasks(params as TaskListParams);
|
await loadTasks(params as TaskListParams);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function reloadForTabChange() {
|
async function countTaskItems(params: TaskListParams | TaskTransferListParams | null) {
|
||||||
|
if (!params) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ("employee_to" in params) {
|
||||||
|
const response = await taskTransferApi.list({ ...params, limit: 1 });
|
||||||
|
return response.count;
|
||||||
|
}
|
||||||
|
|
||||||
|
const response = await taskApi.list({ ...params, limit: 1 });
|
||||||
|
return response.count;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function reloadCounts() {
|
||||||
|
if (!employee.value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const mainCounts = await Promise.allSettled(
|
||||||
|
mainTabs.map(async (tab) => [tab.key, await countTaskItems(taskCountParams(tab.key))] as const),
|
||||||
|
);
|
||||||
|
mainTabCounts.value = {
|
||||||
|
...mainTabCounts.value,
|
||||||
|
...Object.fromEntries(
|
||||||
|
mainCounts.flatMap((result) =>
|
||||||
|
result.status === "fulfilled" ? [result.value] : [],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
} as Record<MainTabKey, number>;
|
||||||
|
|
||||||
|
if (mainTab.value === "transfer") {
|
||||||
|
docTabCounts.value = {
|
||||||
|
all: 0,
|
||||||
|
simple: 0,
|
||||||
|
memo: 0,
|
||||||
|
bill: 0,
|
||||||
|
contract: 0,
|
||||||
|
contract_application: 0,
|
||||||
|
entry_letter: 0,
|
||||||
|
outgoing_letter: 0,
|
||||||
|
};
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const docCounts = await Promise.allSettled(
|
||||||
|
docTabs.map(async (tab) => [tab.key, await countTaskItems(docCountParams(tab.key))] as const),
|
||||||
|
);
|
||||||
|
docTabCounts.value = {
|
||||||
|
...docTabCounts.value,
|
||||||
|
...Object.fromEntries(
|
||||||
|
docCounts.flatMap((result) =>
|
||||||
|
result.status === "fulfilled" ? [result.value] : [],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
} as Record<DocTabKey, number>;
|
||||||
|
|
||||||
|
const nextDocTab = visibleDocTabs.value[0]?.key ?? "all";
|
||||||
|
if (docTab.value !== nextDocTab) {
|
||||||
|
suppressDocTabReload = true;
|
||||||
|
docTab.value = nextDocTab;
|
||||||
|
await nextTick();
|
||||||
|
suppressDocTabReload = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function reloadForTabChange(options: { reloadCounts: boolean }) {
|
||||||
switchingList.value = true;
|
switchingList.value = true;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
if (options.reloadCounts) {
|
||||||
|
await reloadCounts();
|
||||||
|
}
|
||||||
|
|
||||||
await reloadList();
|
await reloadList();
|
||||||
} finally {
|
} finally {
|
||||||
switchingList.value = false;
|
switchingList.value = false;
|
||||||
@@ -231,6 +352,7 @@ async function onRefresh() {
|
|||||||
refreshing.value = true;
|
refreshing.value = true;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
await reloadCounts();
|
||||||
await reloadList();
|
await reloadList();
|
||||||
} finally {
|
} finally {
|
||||||
refreshing.value = false;
|
refreshing.value = false;
|
||||||
@@ -246,18 +368,18 @@ watch(mainTab, () => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void reloadForTabChange();
|
void reloadForTabChange({ reloadCounts: true });
|
||||||
});
|
});
|
||||||
|
|
||||||
watch(docTab, () => {
|
watch(docTab, () => {
|
||||||
if (showDocTabs.value && !suppressDocTabReload) {
|
if (showDocTabs.value && !suppressDocTabReload) {
|
||||||
void reloadForTabChange();
|
void reloadForTabChange({ reloadCounts: false });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
await loadCurrentEmployee();
|
await loadCurrentEmployee();
|
||||||
await reloadList();
|
await reloadForTabChange({ reloadCounts: true });
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -285,22 +407,24 @@ onMounted(async () => {
|
|||||||
:key="tab.key"
|
:key="tab.key"
|
||||||
:name="tab.key"
|
:name="tab.key"
|
||||||
:icon="tab.icon"
|
:icon="tab.icon"
|
||||||
|
:badge="badgeValue(mainTabCounts[tab.key])"
|
||||||
>
|
>
|
||||||
{{ tab.label }}
|
{{ tab.label }}
|
||||||
</van-tabbar-item>
|
</van-tabbar-item>
|
||||||
</van-tabbar>
|
</van-tabbar>
|
||||||
|
|
||||||
<van-tabs
|
<van-tabs
|
||||||
v-if="showDocTabs"
|
v-if="showDocTabs && visibleDocTabs.length > 0"
|
||||||
v-model:active="docTab"
|
v-model:active="docTab"
|
||||||
shrink
|
shrink
|
||||||
class="tabs tabs-secondary"
|
class="tabs tabs-secondary"
|
||||||
>
|
>
|
||||||
<van-tab
|
<van-tab
|
||||||
v-for="tab in docTabs"
|
v-for="tab in visibleDocTabs"
|
||||||
:key="tab.key"
|
:key="tab.key"
|
||||||
:name="tab.key"
|
:name="tab.key"
|
||||||
:title="tab.label"
|
:title="tab.label"
|
||||||
|
:badge="badgeValue(docTabCounts[tab.key])"
|
||||||
/>
|
/>
|
||||||
</van-tabs>
|
</van-tabs>
|
||||||
|
|
||||||
@@ -311,8 +435,8 @@ onMounted(async () => {
|
|||||||
@refresh="onRefresh"
|
@refresh="onRefresh"
|
||||||
>
|
>
|
||||||
<van-list
|
<van-list
|
||||||
:loading="activeLoading || refreshing"
|
:loading="showLoading"
|
||||||
:finished="true"
|
:finished="false"
|
||||||
loading-text="Загрузка..."
|
loading-text="Загрузка..."
|
||||||
:immediate-check="false"
|
:immediate-check="false"
|
||||||
>
|
>
|
||||||
|
|||||||
Reference in New Issue
Block a user