FRONT правки
Правки фронта
This commit is contained in:
@@ -1,5 +1,14 @@
|
||||
// Базовый URL API (берётся из внешнего config.js)
|
||||
const API_BASE = window.APP_CONFIG?.API_BASE || 'http://localhost'
|
||||
const API_BASE = window.APP_CONFIG?.API_BASE || ''
|
||||
|
||||
// Формирование полного URL (добавляет домен к относительным путям)
|
||||
export const getFullUrl = (url) => {
|
||||
if (!url) return ''
|
||||
if (url.startsWith('http://') || url.startsWith('https://') || url.startsWith('data:')) {
|
||||
return url
|
||||
}
|
||||
return API_BASE + url
|
||||
}
|
||||
|
||||
// Базовая функция запроса
|
||||
const request = async (endpoint, options = {}) => {
|
||||
|
||||
@@ -110,12 +110,12 @@ const filteredTotalTasks = computed(() => {
|
||||
})
|
||||
|
||||
const inProgressTasks = computed(() => {
|
||||
const col = filteredColumns.value.find(c => c.id === 3) // В работе
|
||||
const col = filteredColumns.value.find(c => c.id === 2) // В работе
|
||||
return col ? col.cards.length : 0
|
||||
})
|
||||
|
||||
const completedTasks = computed(() => {
|
||||
const col = filteredColumns.value.find(c => c.id === 5) // Готово
|
||||
const col = filteredColumns.value.find(c => c.id === 4) // Готово
|
||||
return col ? col.cards.length : 0
|
||||
})
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
<div v-if="card.assignee" class="assignee">
|
||||
<img
|
||||
v-if="isAvatarUrl(card.assignee)"
|
||||
:src="card.assignee"
|
||||
:src="getFullUrl(card.assignee)"
|
||||
alt="avatar"
|
||||
class="assignee-img"
|
||||
/>
|
||||
@@ -53,6 +53,7 @@
|
||||
|
||||
<script setup>
|
||||
import { ref, computed, onMounted, onUpdated } from 'vue'
|
||||
import { getFullUrl } from '../api'
|
||||
|
||||
const props = defineProps({
|
||||
card: Object,
|
||||
@@ -143,7 +144,7 @@ const daysLeftText = computed(() => {
|
||||
})
|
||||
|
||||
const isAvatarUrl = (value) => {
|
||||
return value && (value.startsWith('http://') || value.startsWith('https://'))
|
||||
return value && (value.startsWith('http://') || value.startsWith('https://') || value.startsWith('/'))
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
@@ -91,7 +91,7 @@
|
||||
<div class="user-dropdown" v-if="!usersLoading" ref="dropdownRef">
|
||||
<!-- Выбранный пользователь / триггер -->
|
||||
<button class="dropdown-trigger" @click="toggleDropdown">
|
||||
<img v-if="selectedUser" :src="selectedUser.avatar_url" :alt="selectedUser.name" class="user-avatar">
|
||||
<img v-if="selectedUser" :src="getFullUrl(selectedUser.avatar_url)" :alt="selectedUser.name" class="user-avatar">
|
||||
<span v-else class="no-user-icon">—</span>
|
||||
<span class="user-name">{{ selectedUser ? selectedUser.name : 'Без исполнителя' }}</span>
|
||||
<i data-lucide="chevron-down" class="dropdown-arrow"></i>
|
||||
@@ -123,7 +123,7 @@
|
||||
:class="{ active: form.userId === user.id }"
|
||||
@click="selectUser(user.id)"
|
||||
>
|
||||
<img :src="user.avatar_url" :alt="user.name" class="user-avatar">
|
||||
<img :src="getFullUrl(user.avatar_url)" :alt="user.name" class="user-avatar">
|
||||
<div class="user-info">
|
||||
<span class="user-name">{{ user.name }}</span>
|
||||
<span class="user-telegram">{{ user.telegram }}</span>
|
||||
@@ -290,7 +290,7 @@
|
||||
import { ref, reactive, computed, watch, onMounted, onUpdated, onUnmounted, nextTick } from 'vue'
|
||||
import DatePicker from './DatePicker.vue'
|
||||
import ConfirmDialog from './ConfirmDialog.vue'
|
||||
import { usersApi, taskImageApi } from '../api'
|
||||
import { usersApi, taskImageApi, getFullUrl } from '../api'
|
||||
|
||||
const props = defineProps({
|
||||
show: Boolean,
|
||||
@@ -337,16 +337,6 @@ const isDragging = ref(false)
|
||||
const fileError = ref('')
|
||||
const allowedTypes = ['image/png', 'image/jpeg', 'image/jpg']
|
||||
const maxFileSize = 10 * 1024 * 1024 // 10 MB
|
||||
const API_BASE = window.APP_CONFIG?.API_BASE || ''
|
||||
|
||||
// Формирование полного URL (добавляет домен к относительным путям)
|
||||
const getFullUrl = (url) => {
|
||||
if (!url) return ''
|
||||
if (url.startsWith('http://') || url.startsWith('https://') || url.startsWith('data:')) {
|
||||
return url
|
||||
}
|
||||
return API_BASE + url
|
||||
}
|
||||
|
||||
// Видимые файлы (без помеченных на удаление)
|
||||
const visibleFiles = computed(() => attachedFiles.value.filter(f => !f.toDelete))
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
class="team-card"
|
||||
>
|
||||
<div class="card-avatar">
|
||||
<img :src="user.avatar_url" :alt="user.name">
|
||||
<img :src="getFullUrl(user.avatar_url)" :alt="user.name">
|
||||
</div>
|
||||
<div class="card-info">
|
||||
<h3 class="card-name">{{ user.name }}</h3>
|
||||
@@ -46,7 +46,7 @@
|
||||
import { ref, onMounted, onUpdated } from 'vue'
|
||||
import Sidebar from '../components/Sidebar.vue'
|
||||
import Header from '../components/Header.vue'
|
||||
import { usersApi } from '../api'
|
||||
import { usersApi, getFullUrl } from '../api'
|
||||
|
||||
const users = ref([])
|
||||
const loading = ref(true)
|
||||
|
||||
Reference in New Issue
Block a user