Правки
This commit is contained in:
@@ -434,8 +434,6 @@ defineExpose({ saveTask, deleteTask, archiveTask })
|
||||
-ms-overflow-style: none;
|
||||
/* Предотвращаем системные жесты (pull-to-refresh) */
|
||||
overscroll-behavior: contain;
|
||||
/* Разрешаем и горизонтальный и вертикальный pan - колонки внутри скроллятся вертикально */
|
||||
touch-action: pan-x pan-y;
|
||||
}
|
||||
|
||||
.board.mobile .columns::-webkit-scrollbar {
|
||||
|
||||
@@ -142,17 +142,33 @@ const handleDrop = (e) => {
|
||||
.column.mobile {
|
||||
width: 100vw;
|
||||
min-width: 100vw;
|
||||
height: 100%;
|
||||
max-height: none;
|
||||
/* Высота по контенту, но ограничена доступным пространством */
|
||||
height: fit-content;
|
||||
max-height: calc(100% - 20px);
|
||||
padding: 0 16px;
|
||||
scroll-snap-align: start;
|
||||
scroll-snap-stop: always;
|
||||
flex-shrink: 0;
|
||||
/* Вертикальный скролл на уровне колонки - убирает вложенные скроллы */
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
/* Скрываем скроллбар в мобильной версии - пользователи свайпают пальцем */
|
||||
.column.mobile {
|
||||
scrollbar-width: none;
|
||||
-ms-overflow-style: none;
|
||||
}
|
||||
|
||||
.column.mobile::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.column.mobile .cards {
|
||||
max-height: calc(100vh - 320px);
|
||||
overflow-y: auto;
|
||||
/* Без overflow - скролл на уровне .column */
|
||||
max-height: none;
|
||||
overflow: visible;
|
||||
min-height: auto;
|
||||
}
|
||||
|
||||
.column.drag-over .cards {
|
||||
|
||||
@@ -772,6 +772,13 @@ const handleSave = async () => {
|
||||
|
||||
try {
|
||||
if (isNew.value) {
|
||||
// Проверяем что у всех колонок есть имена
|
||||
const emptyColumnNew = form.value.columns.find(c => !c.name_columns?.trim())
|
||||
if (emptyColumnNew) {
|
||||
toast.error('Укажите название для всех колонок')
|
||||
return
|
||||
}
|
||||
|
||||
// Проверяем что у всех отделов есть имена (для нового проекта тоже)
|
||||
const emptyDeptNew = form.value.departments.find(d => !d.name_departments?.trim())
|
||||
if (emptyDeptNew) {
|
||||
@@ -826,6 +833,13 @@ const handleSave = async () => {
|
||||
}
|
||||
} else {
|
||||
// Редактирование проекта
|
||||
// Проверяем что у всех колонок есть имена
|
||||
const emptyColumn = form.value.columns.find(c => !c.name_columns?.trim())
|
||||
if (emptyColumn) {
|
||||
toast.error('Укажите название для всех колонок')
|
||||
return
|
||||
}
|
||||
|
||||
// Обновляем название если изменилось
|
||||
if (form.value.name !== initialForm.value.name) {
|
||||
await store.updateProject(props.project.id, form.value.name)
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
:alt="selectedOption.label"
|
||||
class="option-avatar"
|
||||
>
|
||||
<span v-else-if="selectedOption?.label" class="avatar-placeholder">{{ selectedOption.label[0] }}</span>
|
||||
<span v-else-if="!selectedOption" class="no-selection-icon">—</span>
|
||||
<span class="selected-label">{{ selectedOption?.label || placeholder }}</span>
|
||||
</slot>
|
||||
@@ -54,6 +55,7 @@
|
||||
:alt="option.label"
|
||||
class="option-avatar"
|
||||
>
|
||||
<span v-else class="avatar-placeholder">{{ (option.label || '?')[0] }}</span>
|
||||
<div class="option-content">
|
||||
<span class="option-label">{{ option.label }}</span>
|
||||
<a
|
||||
@@ -127,13 +129,14 @@
|
||||
:class="{ active: isActive(option.value) }"
|
||||
@click="selectOption(option.value)"
|
||||
>
|
||||
<img
|
||||
v-if="option.avatar"
|
||||
:src="option.avatar"
|
||||
:alt="option.label"
|
||||
class="option-avatar"
|
||||
>
|
||||
<div class="option-content">
|
||||
<img
|
||||
v-if="option.avatar"
|
||||
:src="option.avatar"
|
||||
:alt="option.label"
|
||||
class="option-avatar"
|
||||
>
|
||||
<span v-else class="avatar-placeholder">{{ (option.label || '?')[0] }}</span>
|
||||
<div class="option-content">
|
||||
<span class="option-label">{{ option.label }}</span>
|
||||
<a
|
||||
v-if="option.subtitle"
|
||||
@@ -498,11 +501,31 @@ onUpdated(refreshIcons)
|
||||
.option-avatar {
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
border-radius: 6px;
|
||||
border-radius: 50%;
|
||||
object-fit: cover;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.avatar-placeholder {
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
color: var(--text-secondary);
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
text-transform: uppercase;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.dropdown-item.active .avatar-placeholder {
|
||||
background: rgba(0, 0, 0, 0.15);
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.option-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@@ -703,7 +726,14 @@ onUpdated(refreshIcons)
|
||||
.mobile-select-item .option-avatar {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border-radius: 10px;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.mobile-select-item .avatar-placeholder {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border-radius: 50%;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.mobile-select-item .option-content {
|
||||
|
||||
@@ -316,15 +316,15 @@ onUnmounted(() => {
|
||||
border-top: 1px solid rgba(255, 255, 255, 0.06);
|
||||
}
|
||||
|
||||
/* Transition — плавное появление */
|
||||
/* Transition — выезд справа для десктопа */
|
||||
.panel-enter-active,
|
||||
.panel-leave-active {
|
||||
transition: opacity 0.2s ease;
|
||||
transition: opacity 0.25s ease;
|
||||
}
|
||||
|
||||
.panel-enter-active .panel,
|
||||
.panel-leave-active .panel {
|
||||
transition: opacity 0.2s ease, transform 0.2s ease;
|
||||
transition: transform 0.25s ease;
|
||||
}
|
||||
|
||||
.panel-enter-from,
|
||||
@@ -334,8 +334,7 @@ onUnmounted(() => {
|
||||
|
||||
.panel-enter-from .panel,
|
||||
.panel-leave-to .panel {
|
||||
opacity: 0;
|
||||
transform: scale(0.98);
|
||||
transform: translateX(100%);
|
||||
}
|
||||
|
||||
/* На мобильных убираем transform из анимации - он ломает layout в iOS PWA */
|
||||
|
||||
Reference in New Issue
Block a user