create upload image

parent 32dc7933
......@@ -11,6 +11,7 @@
"axios": "^0.21.1",
"core-js": "^3.6.5",
"http-status-codes": "^2.1.4",
"moment": "^2.29.1",
"quasar": "^2.0.0-beta.1",
"secure-ls": "^1.2.6",
"vue": "^3.0.11",
......@@ -11148,7 +11149,6 @@
"version": "2.29.1",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz",
"integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==",
"dev": true,
"engines": {
"node": "*"
}
......@@ -31957,8 +31957,7 @@
"moment": {
"version": "2.29.1",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz",
"integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==",
"dev": true
"integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ=="
},
"move-concurrently": {
"version": "1.0.1",
......@@ -94,7 +94,9 @@ export type BannerType = {
bannerUrl: string;
id: number;
numIndex: number;
status: 1;
status: number;
url?: string;
file?: File;
};
export type SchedulesType = {
......
import { defineComponent, PropType, ref } from 'vue';
import { defineComponent, PropType, ref, watch } from 'vue';
import { i18n } from 'src/boot/i18n';
import { BannerType, StoriesType } from 'src/assets/type';
import UploadImage from 'components/upload-image/index.vue';
import { Dialog } from 'quasar';
export default defineComponent({
components: { UploadImage },
props: {
account: { type: String, required: true },
banners: { type: Array as PropType<BannerType[]>, required: true },
shortDescription: { type: Array, required: true },
socialEmbedded: { type: Array, required: true },
stories: { type: Array as PropType<StoriesType[]>, required: true },
formatSchedules: { type: Array as PropType<string[]>, required: true },
},
setup() {
setup(props, context) {
watch(
() => props.banners.length,
(value) => {
slide.value = value - 1;
}
);
const slide = ref(1);
const slideStory = ref(0);
const editor = ref('Customize it.');
const accountRules = [
(val?: string) =>
......@@ -20,7 +32,43 @@ export default defineComponent({
'artist.artistInformation.validateMessages.requireFullName'
),
];
return { slide, editor, accountRules };
const uploadBanner = (value: FileList) => {
context.emit('selectedFile', encodeImageFileAsURL(value[0]));
};
const encodeImageFileAsURL = (file: File) => {
return { url: URL.createObjectURL(file), file: file };
};
const deleteImage = (index: number) => {
Dialog.create({
title: i18n.global.t(
'managingUnit.confirmActionsTitle.confirmDeleteManagingUnitsTitle'
),
message: i18n.global.t(
'managingUnit.confirmActionsTitle.confirmDeleteManagingUnitsContent'
),
cancel: i18n.global.t(
'managingUnit.confirmActionsTitle.confirmDeleteManagingUnitsCancelBtnLabel'
),
color: 'negative',
}).onOk(() => {
context.emit('deleteBanner', index);
});
};
return {
slide,
slideStory,
editor,
accountRules,
uploadBanner,
deleteImage,
};
},
emits: ['update:account', 'update:shortDescription'],
emits: [
'update:account',
'update:shortDescription',
'update:content',
'update:formatSchedules',
'selectedFile',
'deleteBanner',
],
});
......@@ -2,7 +2,7 @@
<div class="row q-col-gutter-sm">
<div class="col-12 text-uppercase text-weight-medium">Tài khoản VAB</div>
<br />
<div class="col-2 flex flex-center justify-start">
<div class="col-auto flex flex-center justify-start">
<div>Tên đăng nhập</div>
</div>
<div class="col-2 flex flex-center">
......@@ -11,6 +11,7 @@
@update:model-value="$emit('update:account', $event)"
:rules="accountRules"
dense
readonly
hide-bottom-space
outlined
></q-input>
......@@ -26,6 +27,8 @@
<div class="col-4">
<q-carousel
v-model="slide"
:key="banners.length"
v-if="banners.length"
animated
arrows
navigation
......@@ -35,11 +38,30 @@
<q-carousel-slide
v-for="(bannerInfo, bannerIdx) in banners"
:key="bannerIdx"
:name="bannerInfo.id"
img-src="https://kenh14cdn.com/203336854389633024/2020/12/31/photo-1-16094117624341764656274.jpg"
/>
:name="bannerIdx"
:img-src="bannerInfo.bannerUrl || bannerInfo.url"
>
<template v-slot:default>
<div align="right">
<q-icon
color="red"
name="mdi-close-circle"
size="24px"
@click="deleteImage(bannerIdx)"
></q-icon>
</div>
</template>
</q-carousel-slide>
</q-carousel>
<UploadImage v-else @selectedFile="uploadBanner"></UploadImage>
<UploadImage
class="q-mt-xs"
v-if="banners.length"
:isBtn="true"
@selectedFile="uploadBanner"
></UploadImage>
</div>
<div class="col-8">
<q-editor
:model-value="shortDescription"
......@@ -48,7 +70,7 @@
toolbar-text-color="white"
toolbar-toggle-color="yellow-8"
toolbar-bg="primary"
height="266px"
style="height: 100%"
:toolbar="[
['token'],
['bold', 'italic', 'underline'],
......@@ -66,30 +88,50 @@
</div>
</div>
<div class="col-12 q-mt-md">
<div class="row" align="center" justify="center">
<div class="col-3">
<div class="row q-col-gutter-lg" align="center" justify="center">
<div class="col-4">
<div class="text-h6 text-weight-regular">Nổi bật(Embed)</div>
<q-card class="my-card q-mt-sm" style="height: 300px">
<img style="height: 100%" :src="socialEmbedded" />
<!-- <img style="height: 100%" :src="socialEmbedded" /> -->
<iframe
style="height: 100%; width: 100%"
:src="socialEmbedded"
frameborder="0"
></iframe>
</q-card>
</div>
<q-space></q-space>
<div class="col-3">
<div class="col-4">
<div class="text-h6 text-weight-regular">Story</div>
<q-card class="my-card q-mt-sm" style="height: 300px">
<img
v-if="stories[0].imageUrl !== null"
style="height: 70%"
:src="stories[0].imageUrl"
/>
<div class="text-subtitle2">{{ stories[0].content }}</div>
</q-card>
<q-carousel v-model="slideStory" animated arrows navigation infinite>
<q-carousel-slide
v-for="(story, storyIdx) in stories"
:key="storyIdx"
:name="storyIdx"
class="q-pt-sm"
>
<q-card class="my-card">
<q-img fit="contain" :src="story.imageUrl" />
<q-input
type="textarea"
:model-value="story.content"
@update:model-value="$emit('update:content', $event)"
></q-input>
</q-card>
</q-carousel-slide>
</q-carousel>
</div>
<q-space></q-space>
<div class="col-3 q-mr-md">
<div class="col-4">
<div class="text-h6 text-weight-regular">Lịch</div>
<q-date class="q-mt-sm" event-color="orange" />
<q-date
style="width: 100%"
:model-value="formatSchedules"
@update:model-value="$emit('update:formatSchedules', $event)"
multiple
readonly
class="q-mt-sm"
event-color="orange"
/>
</div>
</div>
</div>
......
......@@ -13,6 +13,7 @@ export default defineComponent({
setup() {
const userTableColumnsBankAccount = [
{
name: 'STT',
required: true,
label: 'STT',
align: 'center',
......@@ -111,5 +112,5 @@ export default defineComponent({
changePageSize,
};
},
emits: ['click:addBankBtn'],
emits: ['click:addBankBtn', 'confirmDeleteAccBank'],
});
......@@ -68,6 +68,8 @@
<!-- :label="$t('artist.dialogLabel.fieldLabels.isDefault')" -->
<q-checkbox
:model-value="isDefault"
:true-value="1"
:false-value="2"
@update:model-value="$emit('update:isDefault', $event)"
/>
</div>
......
......@@ -23,17 +23,35 @@
<template v-slot:body-cell-isDefault="rowData">
<q-td>
<div align="center">
<q-checkbox v-model="rowData.value" />
<q-checkbox
:true-value="1"
:false-value="2"
v-model="rowData.value"
/>
</div>
</q-td>
</template>
<template v-slot:body-cell-action>
<q-td style="padding: 0" class="flex flex-center">
<q-btn flat round color="primary" icon="mdi-information-outline">
</q-btn>
<q-btn flat round color="primary" icon="mdi-minus-circle-outline">
</q-btn>
<q-btn flat round color="primary" icon="mdi-lock-outline"> </q-btn>
<template v-slot:body-cell-action="item">
<q-td style="padding: 0; height: 100%">
<div align="center">
<q-btn
flat
round
color="primary"
icon="mdi-delete-outline"
@click="$emit('confirmDeleteAccBank', item)"
>
</q-btn>
<q-btn flat round color="primary" icon="mdi-circle-edit-outline">
</q-btn>
</div>
</q-td>
</template>
<template v-slot:body-cell-STT="item">
<q-td style="padding: 0; height: 100%">
<div align="center">
{{ item.rowIndex + 1 }}
</div>
</q-td>
</template>
</q-table>
......
import { defineComponent, ref } from 'vue';
export default defineComponent({
// name: 'ComponentName'
props: {
isBtn: {
type: Boolean,
default: false,
},
},
setup() {
const upload = ref(null);
const uploadBanner = () => {
// eslint-disable-next-line
// @ts-ignore
// eslint-disable-next-line
upload.value?.click();
};
return { uploadBanner, upload };
},
});
<template>
<q-card
@click="uploadBanner"
:class="{
'full-height full-width flex flex-center': !isBtn,
}"
bordered
>
<div
align="center"
:class="{
'flex flex-center q-py-xs': isBtn,
}"
>
<q-icon
name="mdi-plus-circle-outline"
:size="isBtn ? 'sm' : 'xl'"
></q-icon>
<div class="q-mt-xs">{{ $t('uploadImage.uploadBanner') }}</div>
</div>
<input
ref="upload"
hidden
type="file"
accept="image/png, image/jpeg"
@change="$emit('selectedFile', $event.target.files)"
/>
</q-card>
</template>
<script lang="ts" src="./UploadImage.ts"></script>
......@@ -450,4 +450,7 @@ export default {
},
},
recordPerPage: 'Số bản ghi',
uploadImage: {
uploadBanner: 'Tải lên Banner',
},
};
......@@ -65,6 +65,10 @@
<VabAccount
v-model:account="account"
v-model:short-description="shortDescription"
v-model:content="stories[0].content"
v-model:format-schedules="formatSchedules"
@selectedFile="selectedFile"
@deleteBanner="banners.splice($event, 1)"
:social-embedded="socialEmbedded"
:banners="banners"
:stories="stories"
......@@ -73,6 +77,7 @@
<q-tab-panel name="bankAccount">
<BankAccount
:bank-accounts="bankAccounts"
@confirmDeleteAccBank="confirmDeleteAccBank"
@click:addBankBtn="isOpenAddAccountBankDialog = true"
></BankAccount>
</q-tab-panel>
......
......@@ -8,6 +8,7 @@ import { api, BaseResponseBody } from 'src/boot/axios';
import { API_PATHS, config } from 'src/assets/configurations';
import { useRoute } from 'vue-router';
import { AxiosResponse } from 'axios';
import moment from 'moment';
import {
ArtistInfoType,
FieldType,
......@@ -19,6 +20,7 @@ import {
ProductType,
BannerType,
StoriesType,
SchedulesType,
} from 'src/assets/type';
export default defineComponent({
......@@ -99,6 +101,8 @@ export default defineComponent({
const shortDescription: Ref<string | null> = ref('');
const socialEmbedded: Ref<string | null> = ref('');
const stories: Ref<StoriesType[]> = ref([]);
const schedules: Ref<SchedulesType[]> = ref([]);
const formatSchedules: Ref<string[]> = ref([]);
const route = useRoute();
//state accountBank
......@@ -107,7 +111,7 @@ export default defineComponent({
const cardNumber: Ref<string | null | undefined> = ref();
const bankName: Ref<string | null | undefined> = ref();
const cardType: Ref<number | undefined> = ref();
const isDefault: Ref<number | undefined> = ref();
const isDefault: Ref<number | undefined> = ref(1);
const getInformationArtist = async () => {
const response = (await api({
......@@ -122,7 +126,10 @@ export default defineComponent({
artistCode.value = ArtistInformation.artistCode;
fullName.value = ArtistInformation.fullName;
artistName.value = ArtistInformation.artistName;
birthday.value = ArtistInformation.birthday;
birthday.value = moment(
ArtistInformation.birthday,
'DD/MM/YYYY HH:mm:ss'
).format('YYYY-MM-DD');
address.value = ArtistInformation.address;
status.value = ArtistInformation.status;
phoneNumber.value = ArtistInformation.phoneNumber;
......@@ -139,11 +146,20 @@ export default defineComponent({
fields.value = ArtistInformation.fields;
bankAccounts.value = ArtistInformation.bankAccounts;
products.value = ArtistInformation.products;
banners.value = ArtistInformation.banners;
banners.value = ArtistInformation.banners || [];
socialEmbedded.value = ArtistInformation.socialEmbedded;
stories.value = ArtistInformation.stories;
};
schedules.value = ArtistInformation.schedules;
for (let index = 0; index < schedules.value.length; index++) {
const element = schedules.value[index];
formatSchedules.value.push(
moment(element.scheduleTime, 'DD/MM/YYYY HH:mm:ss').format(
'YYYY/MM/DD'
)
);
}
};
const getFieldOptions = async () => {
const response = (await api({
url: API_PATHS.getFieldOptions,
......@@ -196,7 +212,6 @@ export default defineComponent({
workOptions.value = response.data.data;
}
};
const addAccBank = () => {
const newAccount = {
accountNumber: accountNumber.value,
......@@ -208,6 +223,15 @@ export default defineComponent({
bankAccounts.value.push(newAccount as BankAccountType);
isOpenAddAccountBankDialog.value = false;
};
const confirmDeleteAccBank = (value: number) => {
console.log(value, 'valueeee');
};
const selectedFile = (value: BannerType) => {
banners.value.push(value);
console.log(banners.value);
};
onMounted(() => {
void getInformationArtist();
void getFieldOptions();
......@@ -265,6 +289,10 @@ export default defineComponent({
cardType,
isDefault,
addAccBank,
schedules,
formatSchedules,
confirmDeleteAccBank,
selectedFile,
};
},
});
......@@ -70,7 +70,7 @@
hide-pagination
>
<template v-slot:body-cell-avatar="avatar">
<q-td style="padding: 0" class="flex flex-center">
<q-td style="padding: 0; height: 100%" class="flex flex-center">
<q-img
style="width: 7rem"
fit="contain"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment