update

parent 559338d5
......@@ -18,6 +18,7 @@
"quasar": "^2.7.1",
"secure-ls": "^1.2.6",
"vue": "^3.0.11",
"vue-advanced-cropper": "^2.8.8",
"vue-i18n": "^9.0.0-beta.0",
"vuex": "^4.0.2",
"vuex-persistedstate": "^4.0.0-beta.3"
......@@ -4068,6 +4069,11 @@
"integrity": "sha512-riT/3vI5YpVH6/qomlDnJow6TBee2PBKSEpx3O32EGPYbWGIRsIlGRms3Sm74wYE1JMo8RnO04Hb12+v1J5ICw==",
"dev": true
},
"node_modules/classnames": {
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.2.tgz",
"integrity": "sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw=="
},
"node_modules/clean-css": {
"version": "4.2.4",
"resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.4.tgz",
......@@ -5105,6 +5111,11 @@
"resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.20.tgz",
"integrity": "sha512-/WwNkdXfckNgw6S5R125rrW8ez139lBHWouiBvX8dfMFtcn6V81REDqnH7+CRpRipfYlyU1CmOnOxrmGcFOjeA=="
},
"node_modules/debounce": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.1.tgz",
"integrity": "sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug=="
},
"node_modules/debug": {
"version": "4.3.4",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
......@@ -5683,6 +5694,11 @@
"integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=",
"dev": true
},
"node_modules/easy-bem": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/easy-bem/-/easy-bem-1.1.1.tgz",
"integrity": "sha512-GJRqdiy2h+EXy6a8E6R+ubmqUM08BK0FWNq41k24fup6045biQ8NXxoXimiwegMQvFFV3t1emADdGNL1TlS61A=="
},
"node_modules/ee-first": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
......@@ -12346,6 +12362,23 @@
"@vue/shared": "3.2.33"
}
},
"node_modules/vue-advanced-cropper": {
"version": "2.8.8",
"resolved": "https://registry.npmjs.org/vue-advanced-cropper/-/vue-advanced-cropper-2.8.8.tgz",
"integrity": "sha512-yDM7Jb/gnxcs//JdbOogBUoHr1bhCQSto7/ohgETKAe4wvRpmqIkKSppMm1huVQr+GP1YoVlX/fkjKxvYzwwDQ==",
"dependencies": {
"classnames": "^2.2.6",
"debounce": "^1.2.0",
"easy-bem": "^1.0.2"
},
"engines": {
"node": ">=8",
"npm": ">=5"
},
"peerDependencies": {
"vue": "^3.0.0"
}
},
"node_modules/vue-eslint-parser": {
"version": "7.11.0",
"resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-7.11.0.tgz",
......@@ -16183,6 +16216,11 @@
"integrity": "sha512-riT/3vI5YpVH6/qomlDnJow6TBee2PBKSEpx3O32EGPYbWGIRsIlGRms3Sm74wYE1JMo8RnO04Hb12+v1J5ICw==",
"dev": true
},
"classnames": {
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.2.tgz",
"integrity": "sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw=="
},
"clean-css": {
"version": "4.2.4",
"resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.4.tgz",
......@@ -16957,6 +16995,11 @@
"resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.20.tgz",
"integrity": "sha512-/WwNkdXfckNgw6S5R125rrW8ez139lBHWouiBvX8dfMFtcn6V81REDqnH7+CRpRipfYlyU1CmOnOxrmGcFOjeA=="
},
"debounce": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.1.tgz",
"integrity": "sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug=="
},
"debug": {
"version": "4.3.4",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
......@@ -17428,6 +17471,11 @@
"integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=",
"dev": true
},
"easy-bem": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/easy-bem/-/easy-bem-1.1.1.tgz",
"integrity": "sha512-GJRqdiy2h+EXy6a8E6R+ubmqUM08BK0FWNq41k24fup6045biQ8NXxoXimiwegMQvFFV3t1emADdGNL1TlS61A=="
},
"ee-first": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
......@@ -22416,6 +22464,16 @@
"@vue/shared": "3.2.33"
}
},
"vue-advanced-cropper": {
"version": "2.8.8",
"resolved": "https://registry.npmjs.org/vue-advanced-cropper/-/vue-advanced-cropper-2.8.8.tgz",
"integrity": "sha512-yDM7Jb/gnxcs//JdbOogBUoHr1bhCQSto7/ohgETKAe4wvRpmqIkKSppMm1huVQr+GP1YoVlX/fkjKxvYzwwDQ==",
"requires": {
"classnames": "^2.2.6",
"debounce": "^1.2.0",
"easy-bem": "^1.0.2"
}
},
"vue-eslint-parser": {
"version": "7.11.0",
"resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-7.11.0.tgz",
......
......@@ -154,6 +154,15 @@ export type ProvinceType = {
level: string;
};
export type Coordinates = {
image: {
src:string
}
canvas: any
}
export type MusicType = {
id: number;
name: string;
......@@ -472,6 +481,7 @@ export type PostDetailType = {
createTime?: string;
updateBy?: string;
updateTime?: string;
filePost:string
};
export type PostCategoryDetailType = {
......
......@@ -183,14 +183,34 @@
</q-card-actions>
</q-form>
</q-card>
<div>
<q-dialog ref="" v-model="dialogCrop">
<q-card class="q-dialog-plugin">
<cropper
ref="cropper"
:src="imageCrop"
@change="changeCrop"
class="cropper"
/>
<q-card-actions align="right">
<q-btn color="primary" label="Cancel" @click="handeDialogCrop" />
<q-btn color="primary" label="OK" @click="onOKCrop" />
</q-card-actions>
</q-card>
</q-dialog>
</div>
</q-dialog>
</template>
<script lang="ts">
import { defineComponent, ref } from 'vue';
import { defineComponent, ref, Ref } from 'vue';
import { i18n } from 'src/boot/i18n';
import { Coordinates } from 'src/assets/type';
import { Cropper } from 'vue-advanced-cropper';
import 'vue-advanced-cropper/dist/style.css';
export default defineComponent({
components: { Cropper },
props: {
isOpened: {
type: Boolean,
......@@ -206,10 +226,56 @@ export default defineComponent({
numIndex: { type: Number, required: true },
},
setup(_, context) {
const dialogCrop = ref(false);
const imageCrop = ref();
const fileCrop = ref();
const urlCrop: Ref<string> = ref('');
const selectedFile = (value: FileList) => {
dialogCrop.value = true;
imageCrop.value = URL.createObjectURL(value[0]);
};
const handeDialogCrop = () => {
imageCrop.value = null;
dialogCrop.value = false;
};
const changeCrop = (coordinates: Coordinates) => {
// eslint-disable-next-line
// @ts-ignore
// eslint-disable-next-line
// fileCrop.value = coordinates;
// eslint-disable-next-line
// @ts-ignore
// eslint-disable-next-line
urlCrop.value = coordinates.canvas.toDataURL();
// eslint-disable-next-line
// @ts-ignore
// eslint-disable-next-line
fetch(urlCrop.value)
.then((res) => res.blob())
.then((blob) => {
const file = new File([blob], 'file-1678935701090.jpg', {
type: blob.type,
});
fileCrop.value = file;
});
};
const onOKCrop = () => {
dialogCrop.value = false;
context.emit('SetAvatar', {
file: value[0],
url: URL.createObjectURL(value[0]),
// eslint-disable-next-line
// @ts-ignore
// eslint-disable-next-line
file: fileCrop.value,
// eslint-disable-next-line
// @ts-ignore
// eslint-disable-next-line
url: urlCrop.value,
});
};
const deleteAvatar = () => {
......@@ -251,6 +317,13 @@ export default defineComponent({
deleteAvatar,
uploadAvatar,
upload,
imageCrop,
fileCrop,
dialogCrop,
onOKCrop,
handeDialogCrop,
changeCrop,
};
},
emits: [
......
......@@ -187,14 +187,33 @@
</q-card-actions>
</q-form>
</q-card>
<div>
<q-dialog ref="" v-model="dialogCrop">
<q-card class="q-dialog-plugin">
<cropper
ref="cropper"
:src="imageCrop"
@change="changeCrop"
class="cropper"
/>
<q-card-actions align="right">
<q-btn color="primary" label="Cancel" @click="handeDialogCrop" />
<q-btn color="primary" label="OK" @click="onOKCrop" />
</q-card-actions>
</q-card>
</q-dialog>
</div>
</q-dialog>
</template>
<script lang="ts">
import { defineComponent, ref } from 'vue';
import { defineComponent, ref, Ref } from 'vue';
import { i18n } from 'src/boot/i18n';
import { Coordinates } from 'src/assets/type';
import { Cropper } from 'vue-advanced-cropper';
import 'vue-advanced-cropper/dist/style.css';
export default defineComponent({
components: { Cropper },
props: {
isOpened: {
type: Boolean,
......@@ -210,12 +229,58 @@ export default defineComponent({
numIndex: { type: Number, required: true },
},
setup(_, context) {
const dialogCrop = ref(false);
const imageCrop = ref();
const fileCrop = ref();
const urlCrop: Ref<string> = ref('');
const selectedFile = (value: FileList) => {
dialogCrop.value = true;
imageCrop.value = URL.createObjectURL(value[0]);
};
const handeDialogCrop = () => {
imageCrop.value = null;
dialogCrop.value = false;
};
const changeCrop = (coordinates: Coordinates) => {
// eslint-disable-next-line
// @ts-ignore
// eslint-disable-next-line
// fileCrop.value = coordinates;
// eslint-disable-next-line
// @ts-ignore
// eslint-disable-next-line
urlCrop.value = coordinates.canvas.toDataURL();
// eslint-disable-next-line
// @ts-ignore
// eslint-disable-next-line
fetch(urlCrop.value)
.then((res) => res.blob())
.then((blob) => {
const file = new File([blob], 'file-1678935701090.jpg', {
type: blob.type,
});
fileCrop.value = file;
});
};
const onOKCrop = () => {
dialogCrop.value = false;
context.emit('SetAvatar', {
file: value[0],
url: URL.createObjectURL(value[0]),
// eslint-disable-next-line
// @ts-ignore
// eslint-disable-next-line
file: fileCrop.value,
// eslint-disable-next-line
// @ts-ignore
// eslint-disable-next-line
url: urlCrop.value,
});
};
const deleteAvatar = () => {
context.emit('deleteAvatar');
};
......@@ -255,6 +320,13 @@ export default defineComponent({
deleteAvatar,
uploadAvatar,
upload,
imageCrop,
fileCrop,
dialogCrop,
onOKCrop,
handeDialogCrop,
changeCrop,
};
},
emits: [
......
......@@ -157,7 +157,13 @@
</div>
</div>
<div class="col-12 q-mt-md">
<div class="col-12">
<div class="q-gutter-sm">
<q-radio v-model="shape" val="0" label="Nhập nội dung" />
<q-radio v-model="shape" val="1" label="Upload File" />
</div>
</div>
<div v-if="shape === '0'">
<q-tabs
v-model="tabContent"
dense
......@@ -303,6 +309,27 @@
</q-tab-panel>
</q-tab-panels>
</div>
<div v-if="shape === '1'" class="q-ml-lg">
{{ urlPDF }}
<div>
<q-btn
color="primary"
no-caps
style="width: 90px"
label="Chọn file"
@click="uploadFilePDF"
/>
</div>
<input
ref="uploadPDF"
hidden
class="q-ml-md"
@change="selectedFilePDF($event.target.files)"
type="file"
accept=".pdf"
/>
</div>
</div>
</q-card-section>
<q-card-actions align="right">
......@@ -326,11 +353,27 @@
</q-card-actions>
</q-form>
</q-card>
<div>
<q-dialog ref="" v-model="dialogCrop">
<q-card class="q-dialog-plugin">
<cropper
ref="cropper"
:src="imageCrop"
@change="changeCrop"
class="cropper"
/>
<q-card-actions align="right">
<q-btn color="primary" label="Cancel" @click="handeDialogCrop" />
<q-btn color="primary" label="OK" @click="onOKCrop" />
</q-card-actions>
</q-card>
</q-dialog>
</div>
</q-dialog>
</template>
<script lang="ts">
import { defineComponent, PropType, ref, Ref } from 'vue';
import { defineComponent, PropType, ref, Ref, watch } from 'vue';
import { i18n } from 'src/boot/i18n';
import { config } from 'src/assets/configurations.example';
import { API_PATHS } from 'src/assets/configurations.example';
......@@ -338,13 +381,17 @@ import { AxiosResponse } from 'axios';
import { api, BaseResponseBody } from 'src/boot/axios';
import { FileUploadType } from 'src/assets/type';
import { Coordinates } from 'src/assets/type';
import { Cropper } from 'vue-advanced-cropper';
import 'vue-advanced-cropper/dist/style.css';
import { type } from 'os';
export type AvatarType = {
file?: File;
url?: string | null;
};
export default defineComponent({
components: { Cropper },
props: {
isOpened: {
type: Boolean,
......@@ -355,8 +402,9 @@ export default defineComponent({
name: { type: String, required: true },
category: { type: Number, required: true },
categoryOptions: { type: Array, required: true },
urlPDF: { type: String, required: true },
status: { type: Number, required: true },
languageOptions: {
type: Array as PropType<
{
......@@ -378,8 +426,14 @@ export default defineComponent({
methods: {},
setup(_, context) {
const dialogCrop = ref(false);
const imageCrop = ref();
const shape = ref('0');
const fileCrop = ref();
const urlCrop: Ref<string> = ref('');
const avatarUploaded: Ref<string> = ref('');
const uploadImage = ref(null);
const file = ref();
const uploadFile = () => {
// eslint-disable-next-line
// @ts-ignore
......@@ -387,13 +441,76 @@ export default defineComponent({
uploadImage.value?.click();
};
const selectedFile = (value: FileList) => {
context.emit('SetAvatar', {
watch(
() => _.urlPDF,
(value) => {
if (value) {
if (value !== '') {
shape.value = '1';
}
} else {
shape.value = '0';
}
}
);
const filePDF = ref();
const selectedFilePDF = (value: FileList) => {
context.emit('SetFilePDF', {
file: value[0],
url: URL.createObjectURL(value[0]),
});
};
const selectedFile = (value: FileList) => {
dialogCrop.value = true;
imageCrop.value = URL.createObjectURL(value[0]);
};
const handeDialogCrop = () => {
imageCrop.value = null;
dialogCrop.value = false;
};
const changeCrop = (coordinates: Coordinates) => {
// eslint-disable-next-line
// @ts-ignore
// eslint-disable-next-line
// fileCrop.value = coordinates;
// eslint-disable-next-line
// @ts-ignore
// eslint-disable-next-line
urlCrop.value = coordinates.canvas.toDataURL();
// eslint-disable-next-line
// @ts-ignore
// eslint-disable-next-line
fetch(urlCrop.value)
.then((res) => res.blob())
.then((blob) => {
const file = new File([blob], 'file-1678935701090.jpg', {
type: blob.type,
});
fileCrop.value = file;
});
};
const onOKCrop = () => {
dialogCrop.value = false;
context.emit('SetAvatar', {
// eslint-disable-next-line
// @ts-ignore
// eslint-disable-next-line
file: fileCrop.value,
// eslint-disable-next-line
// @ts-ignore
// eslint-disable-next-line
url: urlCrop.value,
});
};
const callApiUploadAvatar = async (file: File) => {
try {
const bodyFormData = new FormData();
......@@ -429,26 +546,21 @@ export default defineComponent({
// eslint-disable-next-line
// @ts-ignore
// eslint-disable-next-line
const file = files[0]
const file = files[0];
// eslint-disable-next-line
// @ts-ignore
// eslint-disable-next-line
avatarUploaded.value = callApiUploadAvatar(
file
).then(res => {
console.log(res,'res')
document.execCommand(
'insertHTML',
true,
'<div><img src="' + config.API_IMAGE_ENDPOINT + res + '" /></div>'
);
})
avatarUploaded.value = callApiUploadAvatar(file).then((res) => {
document.execCommand(
'insertHTML',
true,
'<div><img src="' + config.API_IMAGE_ENDPOINT + res + '" /></div>'
);
});
// eslint-disable-next-line
// @ts-ignore
// eslint-disable-next-line
};
input.click();
};
......@@ -456,6 +568,8 @@ export default defineComponent({
const deleteAvatar = () => {
context.emit('deleteAvatar');
};
const uploadPDF = ref(null);
const upload = ref(null);
const uploadAvatar = () => {
// eslint-disable-next-line
......@@ -463,6 +577,13 @@ export default defineComponent({
// eslint-disable-next-line
upload.value?.click();
};
const uploadFilePDF = () => {
// eslint-disable-next-line
// @ts-ignore
// eslint-disable-next-line
uploadPDF.value?.click();
};
const categoryRules = [
(val?: number) =>
val !== undefined ||
......@@ -490,14 +611,27 @@ export default defineComponent({
categoryRules,
uploadImage,
upload,
uploadPDF,
uploadAvatar,
deleteAvatar,
tab,
tabContent,
uploadFile,
uploadFilePDF,
selectedFilePDF,
file,
insertImg,
// uploadStory
imageCrop,
fileCrop,
dialogCrop,
shape,
onOKCrop,
handeDialogCrop,
changeCrop,
};
},
emits: [
......@@ -507,9 +641,11 @@ export default defineComponent({
'update:category',
'update:content',
'update:status',
'savePostInfo',
'SetAvatar',
'deleteAvatar',
'SetFilePDF',
],
});
</script>
......@@ -2,10 +2,14 @@ import { defineComponent, Ref, ref, watch } from 'vue';
import { i18n } from 'src/boot/i18n';
import { Notify } from 'quasar';
import UploadImage from '../../upload-image/index.vue';
import { Cropper } from 'vue-advanced-cropper';
import { Coordinates } from 'src/assets/type';
// import { Preview } from 'vue-advanced-cropper';
import 'vue-advanced-cropper/dist/style.css';
export default defineComponent({
components: {
UploadImage,
Cropper,
},
props: {
......@@ -16,6 +20,10 @@ export default defineComponent({
},
setup(props, context) {
const imageCrop = ref();
const fileCrop = ref();
const urlCrop: Ref<string> = ref('');
const dialogCrop = ref(false);
const file: Ref<File | string> = ref('');
const name: Ref<string> = ref('');
const code: Ref<string> = ref('');
......@@ -29,9 +37,58 @@ export default defineComponent({
{ id: 2, name: 'Sản phẩm nổi bật' },
]);
const uploadAvatar = (value: FileList) => {
urlFileLocal.value = URL.createObjectURL(value[0]);
file.value = value[0];
console.log(value, 'value');
dialogCrop.value = true;
imageCrop.value = URL.createObjectURL(value[0]);
// urlFileLocal.value = URL.createObjectURL(value[0]);
// file.value = value[0];
};
const handeDialogCrop = () => {
imageCrop.value = null;
dialogCrop.value = false;
};
const changeCrop = (coordinates: Coordinates) => {
// eslint-disable-next-line
// @ts-ignore
// eslint-disable-next-line
urlCrop.value = coordinates.canvas.toDataURL();
// eslint-disable-next-line
// @ts-ignore
// eslint-disable-next-line
fetch(urlCrop.value)
.then((res) => res.blob())
.then((blob) => {
const file = new File([blob], 'file-1678935701090.jpg', {
type: blob.type,
});
fileCrop.value = file;
});
};
const onOKCrop = () => {
// context.emit('SetAvatar', {
// file: fileCrop.value as File,
// url: urlCrop.value,
// });
// eslint-disable-next-line
// @ts-ignore
// eslint-disable-next-line
urlFileLocal.value = urlCrop.value;
// eslint-disable-next-line
// @ts-ignore
// eslint-disable-next-line
file.value = fileCrop.value;
dialogCrop.value = false;
};
watch(
() => props.openAddHotProduct,
(value) => {
......@@ -102,6 +159,13 @@ export default defineComponent({
return {
uploadAvatar,
SubmitData,
changeCrop,
handeDialogCrop,
onOKCrop,
imageCrop,
fileCrop,
urlCrop,
dialogCrop,
urlFileLocal,
file,
name,
......
......@@ -105,6 +105,22 @@
/>
</q-card-actions>
</q-form>
<q-dialog ref="" v-model="dialogCrop">
<q-card class="q-dialog-plugin">
<cropper
ref="cropper"
:src="imageCrop"
@change="changeCrop"
class="cropper"
/>
<q-card-actions align="right">
<q-btn color="primary" label="Cancel" @click="handeDialogCrop" />
<q-btn color="primary" label="OK" @click="onOKCrop" />
</q-card-actions>
</q-card>
</q-dialog>
</q-card>
</q-dialog>
</template>
......
......@@ -12,8 +12,10 @@
<q-img
@click="uploadBanner"
:src="avatar"
style="height: 263px; width: 195px; cursor: pointer"
:style="`cursor: pointer; height: 263px;
width: 195px;`"
></q-img>
<q-icon
name="mdi-close-circle"
color="red"
......@@ -684,10 +686,29 @@
></q-input>
</div>
</div>
<div>
<q-dialog ref="" v-model="dialogCrop">
<q-card class="q-dialog-plugin">
<cropper
ref="cropper"
:src="imageCrop"
@change="changeCrop"
class="cropper"
/>
<q-card-actions align="right">
<q-btn color="primary" label="Cancel" @click="handeDialogCrop" />
<q-btn color="primary" label="OK" @click="onOKCrop" />
</q-card-actions>
</q-card>
</q-dialog>
</div>
</div>
</div>
</template>
<script lang="ts">
import { Cropper } from 'vue-advanced-cropper';
// import { Preview } from 'vue-advanced-cropper';
import 'vue-advanced-cropper/dist/style.css';
import { defineComponent, onMounted, PropType, ref, Ref } from 'vue';
import { i18n } from 'src/boot/i18n';
// import UploadImage from '../../upload-image/index.vue';
......@@ -696,7 +717,7 @@ import { FieldType, NationalityType } from 'src/assets/type';
import { API_PATHS, config } from 'src/assets/configurations.example';
import { api, BaseResponseBody } from 'src/boot/axios';
import { AxiosResponse } from 'axios';
import { ProvinceType } from 'src/assets/type';
import { ProvinceType, Coordinates } from 'src/assets/type';
export default defineComponent({
props: {
mnBookingPhone: { type: String, required: true },
......@@ -769,22 +790,61 @@ export default defineComponent({
// options: { type: String, required: true },
provinceOptions: { type: Array, required: true },
},
// components: {
// UploadImage,
// },
components: {
Cropper,
// Preview,
},
setup(_, context) {
const dialogCrop = ref(false);
const imageCrop = ref();
const fileCrop = ref();
const urlCrop: Ref<string> = ref('');
const BirthdayDatePicker = ref(moment().format('YYYY/MM/DD'));
const selectedFile = (value: FileList) => {
if (value.length !== 0) {
context.emit('SetAvatar', {
file: value[0],
url: URL.createObjectURL(value[0]),
});
context.emit('update:hidden_img', false);
imageCrop.value = URL.createObjectURL(value[0]);
dialogCrop.value = true;
// context.emit('update:hidden_img', false);
}
};
const handeDialogCrop = () => {
imageCrop.value = null;
dialogCrop.value = false;
};
const changeCrop = (coordinates: Coordinates) => {
// eslint-disable-next-line
// @ts-ignore
// eslint-disable-next-line
// fileCrop.value = coordinates;
// eslint-disable-next-line
// @ts-ignore
// eslint-disable-next-line
urlCrop.value = coordinates.canvas.toDataURL();
// eslint-disable-next-line
// @ts-ignore
// eslint-disable-next-line
fetch(urlCrop.value)
.then((res) => res.blob())
.then((blob) => {
const file = new File([blob], 'file-1678935701090.jpg', { type: blob.type });
fileCrop.value = file;
});
};
const onOKCrop = () => {
context.emit('SetAvatar', {
file: fileCrop.value as File,
url: urlCrop.value,
});
dialogCrop.value = false;
};
const provinceOptions1: Ref<ProvinceType[]> = ref([]);
const getProvinceOptions = async () => {
......@@ -885,6 +945,13 @@ export default defineComponent({
return {
check_infoBooking: ref(false),
upload,
imageCrop,
fileCrop,
dialogCrop,
onOKCrop,
handeDialogCrop,
changeCrop,
uploadBanner,
filterFn,
selectedFile,
......
......@@ -170,6 +170,23 @@
</q-card-actions>
</q-form>
</q-card>
<div>
<q-dialog ref="" v-model="dialogCrop">
<q-card class="q-dialog-plugin">
<cropper
ref="cropper"
:src="imageCrop"
@change="changeCrop"
class="cropper"
/>
<q-card-actions align="right">
<q-btn color="primary" label="Cancel" @click="handeDialogCrop" />
<q-btn color="primary" label="OK" @click="onOKCrop" />
</q-card-actions>
</q-card>
</q-dialog>
</div>
</q-dialog>
</template>
......@@ -182,7 +199,11 @@ import { api, BaseResponseBody } from 'src/boot/axios';
import { Dialog, Notify } from 'quasar';
import { ListArrayArtist } from 'src/assets/type';
import { config, API_PATHS } from 'src/assets/configurations.example';
import { Coordinates } from 'src/assets/type';
import { Cropper } from 'vue-advanced-cropper';
import 'vue-advanced-cropper/dist/style.css';
export default defineComponent({
components: { Cropper },
props: {
isOpened: {
type: Boolean,
......@@ -225,13 +246,57 @@ export default defineComponent({
}
}
);
const dialogCrop = ref(false);
const imageCrop = ref();
const fileCrop = ref();
const urlCrop: Ref<string> = ref('');
const artistOptions: Ref<ListArrayArtist[]> = ref([]);
const selectedFile = (value: FileList) => {
dialogCrop.value = true;
imageCrop.value = URL.createObjectURL(value[0]);
};
const handeDialogCrop = () => {
imageCrop.value = null;
dialogCrop.value = false;
};
const changeCrop = (coordinates: Coordinates) => {
// eslint-disable-next-line
// @ts-ignore
// eslint-disable-next-line
// fileCrop.value = coordinates;
// eslint-disable-next-line
// @ts-ignore
// eslint-disable-next-line
urlCrop.value = coordinates.canvas.toDataURL();
// eslint-disable-next-line
// @ts-ignore
// eslint-disable-next-line
fetch(urlCrop.value)
.then((res) => res.blob())
.then((blob) => {
const file = new File([blob], 'file-1678935701090.jpg', {
type: blob.type,
});
fileCrop.value = file;
});
};
const onOKCrop = () => {
dialogCrop.value = false;
context.emit('SetAvatar', {
file: value[0],
url: URL.createObjectURL(value[0]),
// eslint-disable-next-line
// @ts-ignore
// eslint-disable-next-line
file: fileCrop.value,
// eslint-disable-next-line
// @ts-ignore
// eslint-disable-next-line
url: urlCrop.value,
});
};
......@@ -322,7 +387,14 @@ export default defineComponent({
deleteAvatar,
uploadAvatar,
upload,
upload,
imageCrop,
fileCrop,
dialogCrop,
onOKCrop,
handeDialogCrop,
changeCrop,
};
},
emits: [
......
......@@ -6,10 +6,12 @@ import ListPostDialog from 'components/post-category/list-post-dialog/index.vue'
import { api, BaseResponseBody } from 'src/boot/axios';
import { AxiosResponse } from 'axios';
import { config } from 'src/assets/configurations.example';
import { Coordinates } from 'src/assets/type';
import { Cropper } from 'vue-advanced-cropper';
import 'vue-advanced-cropper/dist/style.css';
export default defineComponent({
// name: 'ComponentName'
components: { UploadImage, ListPostDialog },
components: { UploadImage, ListPostDialog, Cropper },
props: {
isOpenAddDialog: { type: Boolean, required: true },
languages: { type: Array as PropType<LanguageType[]>, required: true },
......@@ -42,6 +44,11 @@ export default defineComponent({
}
}
);
const dialogCrop = ref(false);
const imageCrop = ref();
const fileCrop = ref();
const urlCrop: Ref<string> = ref('');
const name: Ref<string | null> = ref(null);
const title: Ref<string | null> = ref(null);
const image: Ref<string | null> = ref(null);
......@@ -113,14 +120,54 @@ export default defineComponent({
const tabName: Ref<string> = ref('vi');
const tabTitle: Ref<string> = ref('vi');
const uploadImage = (value: FileList) => {
urlFileLocal.value = URL.createObjectURL(value[0]);
file.value = value[0];
image.value = urlFileLocal.value;
dialogCrop.value = true;
imageCrop.value = URL.createObjectURL(value[0]);
// file.value = value[0];
// image.value = urlFileLocal.value;
};
const imageUploaded: Ref<string | null> = ref(null);
const deletePostSelected = (postIdx: number) => {
userTableRowsPost.value.splice(postIdx, 1);
};
const handeDialogCrop = () => {
imageCrop.value = null;
dialogCrop.value = false;
};
const changeCrop = (coordinates: Coordinates) => {
// eslint-disable-next-line
// @ts-ignore
// eslint-disable-next-line
// fileCrop.value = coordinates;
// eslint-disable-next-line
// @ts-ignore
// eslint-disable-next-line
urlCrop.value = coordinates.canvas.toDataURL();
// eslint-disable-next-line
// @ts-ignore
// eslint-disable-next-line
fetch(urlCrop.value)
.then((res) => res.blob())
.then((blob) => {
const file = new File([blob], 'file-1678935701090.jpg', {
type: blob.type,
});
fileCrop.value = file;
});
};
const onOKCrop = () => {
dialogCrop.value = false;
urlFileLocal.value = urlCrop.value;
// eslint-disable-next-line
// @ts-ignore
// eslint-disable-next-line
file.value = fileCrop.value;
image.value = urlCrop.value;
};
const callApiUploadAvatar = async (file: File) => {
try {
const bodyFormData = new FormData();
......@@ -164,6 +211,13 @@ export default defineComponent({
tabName,
tabTitle,
confirmAddPostCategory,
imageCrop,
fileCrop,
dialogCrop,
onOKCrop,
handeDialogCrop,
changeCrop,
};
},
emits: [
......
......@@ -234,6 +234,26 @@
</q-card-actions>
</q-form>
</q-card>
<div>
<q-dialog ref="" v-model="dialogCrop">
<q-card class="q-dialog-plugin">
<cropper
ref="cropper"
:src="imageCrop"
@change="changeCrop"
class="cropper"
/>
<q-card-actions align="right">
<q-btn color="primary" label="Cancel" @click="handeDialogCrop" />
<q-btn color="primary" label="OK" @click="onOKCrop" />
</q-card-actions>
</q-card>
</q-dialog>
</div>
</q-dialog>
<ListPostDialog
v-model:is-open-list-post="isOpenListPost"
......
......@@ -11,10 +11,12 @@ import ListPostDialog from 'components/post-category/list-post-dialog/index.vue'
import { api, BaseResponseBody } from 'src/boot/axios';
import { AxiosResponse } from 'axios';
import { config } from 'src/assets/configurations.example';
import { Coordinates } from 'src/assets/type';
import { Cropper } from 'vue-advanced-cropper';
import 'vue-advanced-cropper/dist/style.css';
export default defineComponent({
// name: 'ComponentName'
components: { UploadImage, ListPostDialog },
components: { UploadImage, ListPostDialog,Cropper },
props: {
isOpenUpdateDialog: { type: Boolean, required: true },
languages: { type: Array as PropType<LanguageType[]>, required: true },
......@@ -43,6 +45,11 @@ export default defineComponent({
}
}
);
const dialogCrop = ref(false);
const imageCrop = ref();
const fileCrop = ref();
const urlCrop: Ref<string> = ref('');
const id: Ref<number | null> = ref(null);
const name: Ref<string | null> = ref(null);
const title: Ref<string | null> = ref(null);
......@@ -117,14 +124,69 @@ export default defineComponent({
const tabName: Ref<string> = ref('vi');
const tabTitle: Ref<string> = ref('vi');
const uploadImage = (value: FileList) => {
urlFileLocal.value = URL.createObjectURL(value[0]);
file.value = value[0];
image.value = urlFileLocal.value;
dialogCrop.value = true;
imageCrop.value = URL.createObjectURL(value[0]);
};
const imageUploaded: Ref<string | null> = ref(null);
const deletePostSelected = (postIdx: number) => {
userTableRowsPost.value.splice(postIdx, 1);
};
const handeDialogCrop = () => {
imageCrop.value = null;
dialogCrop.value = false;
};
const changeCrop = (coordinates: Coordinates) => {
// eslint-disable-next-line
// @ts-ignore
// eslint-disable-next-line
// fileCrop.value = coordinates;
// eslint-disable-next-line
// @ts-ignore
// eslint-disable-next-line
urlCrop.value = coordinates.canvas.toDataURL();
// eslint-disable-next-line
// @ts-ignore
// eslint-disable-next-line
fetch(urlCrop.value)
.then((res) => res.blob())
.then((blob) => {
const file = new File([blob], 'file-1678935701090.jpg', {
type: blob.type,
});
fileCrop.value = file;
});
};
const onOKCrop = () => {
dialogCrop.value = false;
urlFileLocal.value = urlCrop.value;
// eslint-disable-next-line
// @ts-ignore
// eslint-disable-next-line
file.value = fileCrop.value;
image.value = urlCrop.value;
};
const callApiUploadAvatar = async (file: File) => {
try {
const bodyFormData = new FormData();
......@@ -170,6 +232,13 @@ export default defineComponent({
tabTitle,
confirmUpdatePostCategory,
imageAPI,
imageCrop,
fileCrop,
dialogCrop,
onOKCrop,
handeDialogCrop,
changeCrop,
};
},
emits: [
......
......@@ -233,6 +233,23 @@
</q-card-actions>
</q-form>
</q-card>
<div>
<q-dialog ref="" v-model="dialogCrop">
<q-card class="q-dialog-plugin">
<cropper
ref="cropper"
:src="imageCrop"
@change="changeCrop"
class="cropper"
/>
<q-card-actions align="right">
<q-btn color="primary" label="Cancel" @click="handeDialogCrop" />
<q-btn color="primary" label="OK" @click="onOKCrop" />
</q-card-actions>
</q-card>
</q-dialog>
</div>
</q-dialog>
<ListPostDialog
v-model:is-open-list-post="isOpenListPost"
......
......@@ -273,6 +273,23 @@
</div>
</q-card-actions>
</q-form>
<div>
<q-dialog ref="" v-model="dialogCrop">
<q-card class="q-dialog-plugin">
<cropper
ref="cropper"
:src="imageCrop"
@change="changeCrop"
class="cropper"
/>
<q-card-actions align="right">
<q-btn color="primary" label="Cancel" @click="handeDialogCrop" />
<q-btn color="primary" label="OK" @click="onOKCrop" />
</q-card-actions>
</q-card>
</q-dialog>
</div>
</q-card>
</q-dialog>
......@@ -309,6 +326,9 @@
import { defineComponent, ref, Ref, PropType } from 'vue';
import InfoVABAddUpdateBankAccountDialog from 'components/update-info-vab/info-vab-add-update-bank-account/index.vue';
import { i18n } from 'src/boot/i18n';
import { Coordinates } from 'src/assets/type';
import { Cropper } from 'vue-advanced-cropper';
import 'vue-advanced-cropper/dist/style.css';
//bankAccount
const bankAccountTableColumnsInfoVAB = [
{
......@@ -377,7 +397,7 @@ const bankAccountTableColumnsInfoVAB = [
];
export default defineComponent({
components: { InfoVABAddUpdateBankAccountDialog },
components: { InfoVABAddUpdateBankAccountDialog, Cropper },
props: {
isOpened: {
type: Boolean,
......@@ -398,12 +418,21 @@ export default defineComponent({
bankAccountList: { type: Array as PropType<unknown[]>, required: true },
},
setup(_, context) {
const dialogCrop = ref(false);
const imageCrop = ref();
const fileCrop = ref();
const urlCrop: Ref<string> = ref('');
const selectedFile = (value: FileList) => {
context.emit('SetAvatar', {
file: value[0],
url: URL.createObjectURL(value[0]),
});
dialogCrop.value = true;
imageCrop.value = URL.createObjectURL(value[0]);
};
const deleteAvatar = () => {
context.emit('deleteAvatar');
};
......@@ -416,6 +445,50 @@ export default defineComponent({
upload.value?.click();
};
const handeDialogCrop = () => {
imageCrop.value = null;
dialogCrop.value = false;
};
const changeCrop = (coordinates: Coordinates) => {
// eslint-disable-next-line
// @ts-ignore
// eslint-disable-next-line
// fileCrop.value = coordinates;
// eslint-disable-next-line
// @ts-ignore
// eslint-disable-next-line
urlCrop.value = coordinates.canvas.toDataURL();
// eslint-disable-next-line
// @ts-ignore
// eslint-disable-next-line
fetch(urlCrop.value)
.then((res) => res.blob())
.then((blob) => {
const file = new File([blob], 'file-1678935701090.jpg', {
type: blob.type,
});
fileCrop.value = file;
});
};
const onOKCrop = () => {
dialogCrop.value = false;
context.emit('SetAvatar', {
// eslint-disable-next-line
// @ts-ignore
// eslint-disable-next-line
file: fileCrop.value,
// eslint-disable-next-line
// @ts-ignore
// eslint-disable-next-line
url: urlCrop.value,
});
};
const bankAccountListInfoVAB: Ref<unknown[]> = ref([]);
const addBankAccountDialogIsOpened = ref(false);
const updateBankAccountDialogIsOpened = ref(false);
......@@ -495,6 +568,13 @@ export default defineComponent({
updateBankAccountDialogIsOpened,
updateNewBankAccount,
bankAccountListInfoVAB,
imageCrop,
fileCrop,
dialogCrop,
onOKCrop,
handeDialogCrop,
changeCrop,
};
},
emits: [
......
......@@ -131,10 +131,12 @@
v-model:image="image"
v-model:content="content"
v-model:status="status"
v-model:urlPDF="urlPDF"
:languageOptions="languageOptions"
:categoryOptions="categoryOptions"
isUpdate
@SetAvatar="setAvatar($event)"
@SetFilePDF="SetFilePDF($event)"
@deleteAvatar="deleteAvatar"
@savePostInfo="addNewPost"
/>
......@@ -146,9 +148,11 @@
v-model:image="image"
v-model:content="content"
v-model:status="status"
v-model:urlPDF="urlPDF"
:languageOptions="languageOptions"
:categoryOptions="categoryOptions"
@SetAvatar="setAvatar($event)"
@SetFilePDF="SetFilePDF($event)"
@deleteAvatar="deleteAvatar"
@savePostInfo="confirmUpdatePost"
/>
......@@ -277,7 +281,7 @@ export default defineComponent({
sortable: false,
},
];
const shape = ref('0');
const pageIndex = ref(1);
const pageSize = ref(20);
const totalPage = ref(1);
......@@ -293,8 +297,12 @@ export default defineComponent({
const postId: Ref<number | undefined> = ref(undefined);
const namePost = ref('');
const avatarFile: Ref<File | null> = ref(null);
const filePDF: Ref<File | null> = ref(null);
const urlPDF: Ref<string | null> = ref(null);
const avatarUploaded: Ref<string> = ref('');
const filePDFUploaded: Ref<string> = ref('');
const imageChange: Ref<string> = ref('');
const urlPDFChange: Ref<string> = ref('');
const languageOptions: Ref<FromType> = ref([]);
const changePageSize = () => {
......@@ -368,11 +376,14 @@ export default defineComponent({
avatarUploaded.value = await callApiUploadAvatar(
avatarFile.value as File
);
filePDFUploaded.value = await callApiUploadAvatar(filePDF.value as File);
const data = {
image: avatarUploaded.value,
status: status.value,
category: { id: category.value?.id },
langs: languageOptions.value,
filePost: filePDFUploaded.value,
};
const response = (await api({
url: API_PATHS.addPost,
......@@ -412,27 +423,54 @@ export default defineComponent({
languageOptions.value = response.data.data.langs;
status.value = response.data.data.status;
category.value = response.data.data.category;
urlPDF.value = response.data.data.filePost;
urlPDFChange.value = response.data.data.filePost;
}
} catch (error) {}
};
//gọi api update
const confirmUpdatePost = async () => {
// if (avatarFile.value) {
// avatarUploaded.value = await callApiUploadAvatar(avatarFile.value);
// void updatePost(avatarUploaded.value);
// } else {
// void updatePost(imageChange.value);
// }
if (avatarFile.value) {
avatarUploaded.value = await callApiUploadAvatar(avatarFile.value);
void updatePost(avatarUploaded.value);
filePDFUploaded.value = urlPDF.value as string;
} else if (urlPDF.value) {
filePDFUploaded.value = await callApiUploadAvatar(
filePDF.value as File
);
avatarUploaded.value = imageChange.value;
} else if (avatarFile.value && urlPDF.value) {
// eslint-disable-next-line
// @ts-ignore
// eslint-disable-next-line
avatarUploaded.value = await callApiUploadAvatar(avatarFile.value);
filePDFUploaded.value = await callApiUploadAvatar(
filePDF.value as File
);
} else {
void updatePost(imageChange.value);
avatarUploaded.value = imageChange.value;
filePDFUploaded.value = urlPDF.value as string;
}
void updatePost(avatarUploaded.value, filePDFUploaded.value)
};
const updatePost = async (image: string) => {
const updatePost = async (image: string,filePost: string ) => {
const data = {
id: postId.value,
image,
status: status.value,
category: { id: category.value?.id },
langs: languageOptions.value,
filePost,
};
const response = (await api({
url: API_PATHS.updatePost,
......@@ -454,6 +492,10 @@ export default defineComponent({
avatarFile.value = value.file as File;
image.value = value.url as string;
};
const SetFilePDF = (value: { file?: File; url?: string }) => {
filePDF.value = value.file as File;
urlPDF.value = value.url as string;
};
const callApiUploadAvatar = async (file: File) => {
try {
......@@ -559,12 +601,15 @@ export default defineComponent({
openUpdatePostDialog,
getDetailPost,
updatePost,
urlPDF,
namePost,
content,
languageOptions,
image,
postId,
shape,
setAvatar,
SetFilePDF,
callApiUploadAvatar,
deleteAvatar,
getpostCategory,
......
<template>
<div class="row q-col-gutter-sm flex-center q-mt-sm">
<div class="col-auto text-h6 text-weight-regular flex flex-center q-mr-md">
{{ $t('banner.title') }}
{{ $t('banner.title') }}
<q-separator vertical spaced />
</div>
<q-space></q-space>
......
<template>
<div class="row q-col-gutter-sm flex-center q-mt-sm">
<div class="col-auto text-h6 text-weight-regular flex flex-center q-mr-md">
{{ $t('configPartner.title') }}
{{ $t('configPartner.title') }} 123
<q-separator vertical spaced />
</div>
<q-space></q-space>
......@@ -326,9 +326,7 @@ export default defineComponent({
addConfigPartnerDialogIsOpened.value = false;
Notify.create({
type: 'positive',
message: i18n.global.t(
'configPartner.actionMessages.addNewBannerAccess'
),
message: 'Thêm Đối tác thành công',
actions: [{ icon: 'close', color: 'white' }],
});
void getListConfigPartner();
......
<template>
<div class="row q-col-gutter-sm flex-center q-mt-sm">
<div class="col-auto text-h6 text-weight-regular flex flex-center q-mr-md">
{{ $t('postCategory.title.postCategory') }}
{{ $t('postCategory.title.postCategory') }}
<q-separator vertical spaced />
</div>
<q-space></q-space>
......
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