update

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