Initial commit

This commit is contained in:
Developer
2025-04-21 16:03:20 +02:00
commit 2832896157
22874 changed files with 3092801 additions and 0 deletions

View File

@@ -0,0 +1,41 @@
<template>
<div class="mt-3 md:mt-6 feed-footer">
<div class="flex justify-between">
<div class="misc-info flex space-x-4">
<like-count @likeFeed="likeFeed" :likes="likes" :liked="liked" />
<comment-count :comments="comments" />
<share-count />
</div>
<view-count />
</div>
</div>
</template>
<script>
import LikeCount from "@/Shared/Misc/LikeCount";
import ViewCount from "@/Shared/Misc/ViewCount";
import CommentCount from "@/Shared/Misc/CommentCount";
import ShareCount from "@/Shared/Misc/ShareCount";
export default {
components: {
LikeCount,
CommentCount,
ShareCount,
ViewCount,
},
emits:['likeFeed'],
props: {
comments: Number,
likes: Number,
liked: Boolean,
},
methods:{
likeFeed(){
this.$emit('likeFeed');
},
}
};
</script>

View File

@@ -0,0 +1,62 @@
<template>
<div @click.stop="" class="feed-header flex items-center justify-between">
<div class="flex items-center">
<inertia-link :href="route('profile.user', user.username)" class="flex-shrink-0 block mr-2 md:mr-4">
<user-avatar :user='user' size='small' class="w-10 h-10 md:w-14 md:h-14 text-lg" />
</inertia-link>
<inertia-link :href="route('profile.user', user.username)" class="flex flex-col">
<span class="hover:underline text-sm md:text-base block font-medium text-white">{{ user.name }}</span>
<span class="hover:underline text-xs text-gray-light">{{created_at}}</span>
</inertia-link>
</div>
<div class="flex-shrink-0 text-white">
<dropdown-menu-point>
<MenuItems class="origin-top-right absolute right-0 mt-2 w-64 bg-indigo-300 shadow-lg max-h-60 rounded-md text-base ring-1 ring-indigo-200 overflow-auto focus:outline-none">
<MenuItem v-if="user.id === $page.props.auth.user.id">
<button @click="onRemoveFeed()" class="w-full group flex items-center px-4 py-2 text-base hover:bg-indigo-100 text-gray-light">
<MinusCircleIcon class="mr-3 h-5 w-5 text-gray-400 group-hover:text-orange" aria-hidden="true" />
Удалить
</button>
</MenuItem>
<MenuItem v-if="user.id !== $page.props.auth.user.id">
<inertia-link :href="route('video.create')" class="group flex items-center px-4 py-2 text-base hover:bg-indigo-100 text-gray-light">
<ExclamationIcon class="mr-3 h-5 w-5 text-gray-400 group-hover:text-orange" aria-hidden="true" />
Пожаловаться
</inertia-link>
</MenuItem>
</MenuItems>
</dropdown-menu-point>
</div>
</div>
</template>
<script>
import UserAvatar from '@/Shared/Misc/UserAvatar'
import DropdownMenuPoint from '@/Shared/Form/DropdownMenuPoint'
import { MenuItem, MenuItems } from '@headlessui/vue'
import {
MinusCircleIcon,
ExclamationIcon,
} from '@heroicons/vue/solid'
export default {
components: {
UserAvatar,
DropdownMenuPoint,
MinusCircleIcon,
ExclamationIcon,
MenuItem,
MenuItems,
},
emits: ['onRemoveFeed'],
props: {
user: Object,
created_at: String,
},
methods:{
onRemoveFeed(){
this.$emit('onRemoveFeed');
},
}
};
</script>

View File

@@ -0,0 +1,72 @@
<template>
<modal-feed
@close-modal="closeModal"
:modalFeed='modalFeed'
:open="show"
@destroyFeed="destroyFeed"
/>
<div v-for="feed in feedLists" :key="feed.id">
<feed-list-node @onRemoveFeed="onRemoveFeed" @open-modal="openModal" :feed="feed" />
</div>
</template>
<script>
import FeedListNode from "@/Shared/FeedList/FeedListNode";
import ModalFeed from "@/Shared/Overlay/ModalFeed";
import { Inertia } from "@inertiajs/inertia";
import filter from 'lodash/filter';
export default {
components: {
FeedListNode,
ModalFeed,
},
props: {
feeds: Array,
selfFeed: Boolean,
selfUser: {
type: Number,
default: 0,
},
},
data() {
return {
showLoadButton: true,
show: false,
entity: {},
feedLists: [],
complaints: [],
modalFeed: {},
};
},
mounted() {
this.feedLists = this.feeds;
},
methods: {
onRemoveFeed(id){
Inertia.delete(route('feed.destroy', id), { preserveScroll: true, preserveState: true })
this.destroyFeed(id);
},
destroyFeed(id = null){
const that = this;
this.feedLists = filter(this.feedLists, function (x) {
if(id){
return x.id !== id;
}
return x.id !== that.modalFeed.id;
});
},
openModal(feed) {
this.show = true;
this.modalFeed = feed;
},
closeModal() {
this.show = false;
}
},
};
</script>

View File

@@ -0,0 +1,68 @@
<template>
<component
@click.prevent="openModal(feed)"
@onRemoveFeed='onRemoveFeed'
@like-feed="likeFeed"
:is="currentTypeNode"
:feed_id="feed.id"
:user="feed.user"
:entity="feed.entity"
></component>
</template>
<script>
import { Inertia } from "@inertiajs/inertia";
import FeedImages from "@/Shared/FeedList/Images";
import FeedVideos from "@/Shared/FeedList/Videos";
import FeedMusics from "@/Shared/FeedList/Musics";
import { usePage } from "@inertiajs/inertia-vue3";
export default {
components: {
FeedImages,
FeedVideos,
FeedMusics,
},
props: {
feed: Object,
},
emits: ["openModal", "onRemoveFeed"],
computed: {
authUser() {
return usePage().props.value.auth.user;
},
currentTypeNode() {
if (this.feed.entity.is_paid && this.authUser.id !== this.feed.user.id) {
//return "feed-paid-" + this.feed.type.toLowerCase();
}
return "feed-" + this.feed.type.toLowerCase();
},
},
methods: {
onRemoveFeed(id) {
this.$emit("onRemoveFeed", id);
},
openModal(feed) {
this.$emit("openModal", feed);
},
likeFeed() {
Inertia.post(
route("feed.like", this.feed.id),
{},
{
preserveScroll: true,
preserveState: true,
}
);
if (this.feed.entity.liked) {
this.feed.entity.liked = false;
this.feed.entity.likes--;
} else {
this.feed.entity.liked = true;
this.feed.entity.likes++;
}
},
},
};
</script>

View File

@@ -0,0 +1,75 @@
<template>
<div class="">
<div class="flex items-center border-b border-indigo-100">
<div class="flex-shrink-0 mr-5 w-28 md:w-56">
<feed-preview class="h-28 w-28 md:w-56 md:h-56 object-cover" type="music" :source='preview' />
</div>
<div class="flex flex-col">
<span class="text-base md:text-xl font-semibold text-gray">{{title}}</span>
</div>
</div>
<div data-simplebar class="max-h-72 overflow-auto">
<div class="divide-y divide-indigo-100">
<div
@click.prevent="startPlay(media)"
v-for="media in medias" :key="media.id"
:class="[currentSong?.id === media.id ? 'bg-indigo-300 bg-opacity-25' : 'hover:bg-indigo-300 hover:bg-opacity-25', 'p-4 flex items-center space-x-4']">
<div class="flex">
<toggle-play-button :media_id="media.id" />
</div>
<div class="flex-1 text-sm text-gray-light">
{{media.name}}
</div>
<div class="text-sm text-gray-light">
<div v-if="currentSong?.id === media.id">{{seek}}</div>
<span v-else>{{media.time}}</span>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import { mapActions, mapState, mapGetters } from "vuex";
import FeedPreview from "@/Shared/Feed/FeedPreview";
import TogglePlayButton from "@/Shared/Misc/TogglePlayButton";
export default {
components: {
FeedPreview,
TogglePlayButton,
},
props: {
medias: Array,
feed_id: Number,
title: String,
preview: String,
},
methods: {
...mapActions(["toggleAudio", "newCurrentPlaylist", "skipToIndexByMusic"]),
startPlay(music) {
if (this.currentSong?.id === music.id) {
this.toggleAudio();
return;
}
// if (this.playlist_id === this.feed_id) {
// this.skipToIndexByMusic(music);
// return;
// }
this.newCurrentPlaylist([music, this.medias, this.feed_id]);
},
},
computed: {
...mapGetters(["playing"]),
...mapState({
playlist_id: (state) => state.player.playlist_id,
seek: (state) => state.player.seek,
currentSong: (state) => state.player.currentSong,
}),
},
};
</script>

View File

@@ -0,0 +1,95 @@
<template>
<div @click.stop="" class="mt-3 rounded-md bg-indigo-300 p-4"
v-if="disabled === 0 && is_paid && $page.props.auth.user.id !== user_id">
<div v-if="bought == 0" class="flex items-center justify-center">
<div class="mr-5 mb-2 md:mb-0 font-bold text-center md:text-left w-full md:w-auto">
Цена: {{price}}
</div>
<div>
<button @click="purchaseFeed" type="button" class="my-1 transition shadow-none hover:shadow-classic2 inline-flex items-center px-8 py-1 md:py-3 justify-center text-sm md:text-base rounded-md text-white bg-pink focus:outline-none">
Купить
</button>
</div>
</div>
<div v-else class="flex flex-wrap items-center justify-center">
<div class="mr-5 mb-2 md:mb-0 font-bold text-center md:text-left w-full md:w-auto">
Данный товар вами куплен
</div>
<button v-if="disable_btn == 0 && paid_open == 0" @click="replaceFeed" type="button" class="my-1 mx-1 transition shadow-none hover:shadow-classic2 inline-flex items-center px-8 py-1 md:py-3 justify-center text-sm md:text-base rounded-md text-white bg-orange focus:outline-none">
Показать
</button>
<inertia-link :href="route('setting.show.purchases', feed_id)" class="my-1 mx-1 transition shadow-none hover:shadow-classic2 inline-flex items-center px-8 py-1 md:py-3 justify-center text-sm md:text-base rounded-md text-white bg-pink focus:outline-none">
Скачать
</inertia-link>
</div>
</div>
<div @click.stop="" v-else-if="is_paid && $page.props.auth.user.id === user_id" class="p-4 text-center">
<button v-if="paid_open === 0" @click="replaceFeed" type="button" class="my-1 mx-1 transition shadow-none hover:shadow-classic2 inline-flex items-center px-8 py-1 md:py-2 justify-center text-sm rounded-md text-white bg-orange focus:outline-none">
Показать платный контент
</button>
</div>
</template>
<script>
import axios from "axios";
export default {
components: {},
emits: ["onReplaceFeed"],
props: {
user_id: Number,
is_paid: Boolean,
feed_id: Number,
price: String,
paid_open: {
type: Number,
default: 0,
},
},
data() {
return {
bought: 0,
disable_btn: 0,
disabled: 1,
};
},
mounted() {
if (this.is_paid) {
axios
.post(route("feeds.purchase_check", this.feed_id))
.then(({ data }) => {
if (data === 1) {
this.bought = 1;
}
this.disabled = 0;
});
}
},
methods: {
purchaseFeed() {
axios.post(route("feed.purchase", this.feed_id)).then(({ data }) => {
if (data.error == 1) {
alert(data.msg);
} else {
this.$emit("onReplaceFeed", data);
this.disable_btn = 1;
this.bought = 1;
}
});
},
replaceFeed() {
axios.post(route("feeds.replace", this.feed_id)).then(({ data }) => {
if (data.collection) {
this.$emit("onReplaceFeed", data);
this.disable_btn = 1;
}
});
},
},
};
</script>

View File

@@ -0,0 +1,68 @@
<template>
<div class="shadow-classic rounded-md bg-indigo-200 p-3 md:px-5 md:py-7">
<feed-header @onRemoveFeed='onRemoveFeed' :created_at='entity.created_at_humans' :user='user' />
<div class="mt-3 md:mt-6 feed-body">
<div class="mb-3 md:mb-6 text-gray text-sm md:text-base">
<div @click.stop="">
{{entity.body}}
</div>
<feed-paid-block
@onReplaceFeed='onReplaceFeed'
:is_paid='entity.is_paid'
:user_id='user.id'
:price='entity.price'
:feed_id='feed_id'
:paid_open='entity.paid_open'
/>
</div>
<div class="grid gap-1 md:gap-3 grid-cols-2 md:grid-cols-[repeat(auto-fit,minmax(280px,1fr))]">
<div v-for="media in entity.collection_medias" :key="media.id">
<img class="w-full h-full object-cover" :src="media.url" alt="">
</div>
</div>
</div>
<feed-footer
@likeFeed='likeFeed'
:likes='entity.likes'
:liked='entity.liked'
:comments='entity.comments'
/>
</div>
</template>
<script>
import FeedHeader from "@/Shared/FeedList/FeedHeader";
import FeedFooter from "@/Shared/FeedList/FeedFooter";
import FeedPaidBlock from "@/Shared/FeedList/FeedPaidBlock";
export default {
components: {
FeedHeader,
FeedFooter,
FeedPaidBlock,
},
emits: ["likeFeed", "onRemoveFeed"],
props: {
entity: Object,
user: Object,
feed_id: Number,
},
methods: {
onReplaceFeed(data) {
this.entity.collection_medias = data.collection;
this.entity.preview = data.preview;
this.entity.paid_open = 1;
},
onRemoveFeed() {
this.$emit("onRemoveFeed", this.feed_id);
},
likeFeed() {
this.$emit("likeFeed");
},
},
};
</script>

View File

@@ -0,0 +1,66 @@
<template>
<div class="shadow-classic rounded-md bg-indigo-200 p-3 md:px-5 md:py-7">
<feed-header :created_at='entity.created_at_humans' :user='user' />
<div @click.stop="" class="mt-3 md:mt-6 feed-body">
<div class="mb-3 md:mb-6 text-gray text-sm md:text-base">
<div @click.stop="">
{{entity.body}}
</div>
<feed-paid-block
@onReplaceFeed='onReplaceFeed'
:is_paid='entity.is_paid'
:user_id='user.id'
:price='entity.price'
:feed_id='feed_id'
:paid_open='entity.paid_open'
/>
</div>
<feed-music-body
:feed_id='feed_id'
:title='entity.title'
:preview='entity.preview'
:medias='entity.collection_medias'
/>
</div>
<feed-footer
@likeFeed='likeFeed'
:likes='entity.likes'
:liked='entity.liked'
:comments='entity.comments'
/>
</div>
</template>
<script>
import FeedHeader from "@/Shared/FeedList/FeedHeader";
import FeedFooter from "@/Shared/FeedList/FeedFooter";
import FeedMusicBody from "@/Shared/FeedList/FeedMusicBody";
import FeedPaidBlock from "@/Shared/FeedList/FeedPaidBlock";
export default {
components: {
FeedHeader,
FeedFooter,
FeedMusicBody,
FeedPaidBlock,
},
emits: ["likeFeed"],
props: {
entity: Object,
user: Object,
feed_id: Number,
},
methods: {
onReplaceFeed(data) {
this.entity.collection_medias = data.collection;
this.entity.preview = data.preview;
this.entity.paid_open = 1;
},
likeFeed() {
this.$emit("likeFeed");
},
},
};
</script>

View File

@@ -0,0 +1,48 @@
<template>
<div class="shadow-classic rounded-md bg-indigo-200 p-3 md:px-5 md:py-7">
<feed-header :created_at='entity.created_at_humans' :user='user' />
<div @click.stop="" class="mt-3 md:mt-6 feed-body">
<div class="mb-3 md:mb-6 text-gray text-sm md:text-base">
{{entity.body}}
</div>
<div class="grid gap-1 md:gap-3 grid-cols-2 md:grid-cols-[repeat(auto-fit,minmax(280px,1fr))]">
<div v-for="media in entity.collection_medias" :key="media.id">
<video :src="media.url" controls></video>
</div>
</div>
</div>
<feed-footer
@likeFeed='likeFeed'
:likes='entity.likes'
:liked='entity.liked'
:comments='entity.comments'
/>
</div>
</template>
<script>
import FeedHeader from '@/Shared/FeedList/FeedHeader'
import FeedFooter from '@/Shared/FeedList/FeedFooter'
export default {
components: {
FeedHeader,
FeedFooter,
},
emits: ["likeFeed"],
props: {
entity: Object,
user: Object,
feed_id: Number,
},
methods: {
likeFeed() {
this.$emit("likeFeed");
},
},
};
</script>