changes
This commit is contained in:
@@ -1,66 +1,97 @@
|
||||
<template>
|
||||
<div
|
||||
class="tile is-ancestor py-5 px-3 mx-0"
|
||||
v-if="image"
|
||||
class="fixed-grid has-12-cols"
|
||||
>
|
||||
<div class="tile is-1" />
|
||||
<div class="tile is-7">
|
||||
<Cropper
|
||||
ref="cropper"
|
||||
:src="image"
|
||||
@change="onChange"
|
||||
:stencil-props="getRatio"
|
||||
/>
|
||||
</div>
|
||||
<div class="tile is-1"></div>
|
||||
<div class="tile">
|
||||
<div v-if="avatar !== true">
|
||||
<p class="mt-2 fs-16">Chọn tỷ lệ hoặc nhập chiều rộng và cao</p>
|
||||
<div class="tags are-medium mt-2">
|
||||
<a
|
||||
:class="curRatio.k === v.k ? 'tag is-primary' : 'tag'"
|
||||
v-for="(v, i) in ratios"
|
||||
:key="i"
|
||||
@click="curRatio = v"
|
||||
>{{ v.k }}</a
|
||||
>
|
||||
</div>
|
||||
<div class="block mt-5">
|
||||
<b-radio
|
||||
v-model="radio"
|
||||
native-value="replace"
|
||||
>
|
||||
Ghi đè
|
||||
</b-radio>
|
||||
<b-radio
|
||||
v-model="radio"
|
||||
class="ml-3"
|
||||
native-value="new"
|
||||
>
|
||||
Tạo file mới
|
||||
</b-radio>
|
||||
</div>
|
||||
<p class="mt-4">
|
||||
<a
|
||||
class="button is-primary mr-4 mb-2"
|
||||
:class="loading ? 'is-loading' : ''"
|
||||
@click="updateImage()"
|
||||
>Lưu lại</a
|
||||
>
|
||||
</p>
|
||||
<p
|
||||
class="mt-2"
|
||||
v-if="coordinates"
|
||||
>
|
||||
Hình ảnh cắt,
|
||||
{{ "W: " + coordinates.width + ", H: " + coordinates.height + ", W/H: " + coordinates.ratio }}
|
||||
</p>
|
||||
<div class="grid is-gap-2">
|
||||
<div class="cell is-col-span-8">
|
||||
<Cropper
|
||||
ref="cropper"
|
||||
:src="image"
|
||||
:canvas="false"
|
||||
@change="onChange"
|
||||
:stencil-props="getRatio"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="is-italic has-text-grey"
|
||||
v-else
|
||||
>
|
||||
* Di chuyển khung để chọn hình ảnh phù hợp
|
||||
<div class="cell is-col-span-4">
|
||||
<div
|
||||
v-if="avatar"
|
||||
class="is-italic has-text-grey"
|
||||
>
|
||||
* Di chuyển khung để chọn hình ảnh phù hợp
|
||||
</div>
|
||||
<div v-else>
|
||||
<p class="label">Chọn tỷ lệ:</p>
|
||||
<div class="fixed-grid has-12-cols">
|
||||
<div class="grid is-gap-0.5">
|
||||
<div
|
||||
class="cell is-col-span-3"
|
||||
v-for="ratio in ratios"
|
||||
:key="ratio"
|
||||
>
|
||||
<button
|
||||
:class="['button is-fullwidth is-small', curRatio === ratio ? 'is-primary' : 'is-light']"
|
||||
@click="curRatio = ratio"
|
||||
>
|
||||
{{ ratio }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<hr />
|
||||
<div
|
||||
v-if="coordinates"
|
||||
class="fixed-grid has-3-cols is-family-monospace"
|
||||
>
|
||||
<div class="grid">
|
||||
<div class="cell p-2 rounded has-background-white-ter has-text-centered">
|
||||
<p class="fs-11 is-uppercase has-text-grey">width</p>
|
||||
<p class="font-semibold">{{ coordinates.width }}</p>
|
||||
</div>
|
||||
<div class="cell p-2 rounded has-background-white-ter has-text-centered">
|
||||
<p class="fs-11 is-uppercase has-text-grey">height</p>
|
||||
<p class="font-semibold">{{ coordinates.height }}</p>
|
||||
</div>
|
||||
<div class="cell p-2 rounded has-background-white-ter has-text-centered">
|
||||
<p class="fs-11 is-uppercase has-text-grey">ratio</p>
|
||||
<p class="font-semibold">{{ coordinates.ratio }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<hr />
|
||||
<div class="block is-flex is-gap-1 is-flex-wrap-wrap">
|
||||
<button
|
||||
v-for="v in [
|
||||
{ name: 'Ghi đè', value: 'replace' },
|
||||
{ name: 'Tạo file mới', value: 'new' },
|
||||
]"
|
||||
:key="v.value"
|
||||
@click="radio = v.value"
|
||||
:class="['button fs-14', radio === v.value ? 'is-primary is-light' : 'is-white']"
|
||||
>
|
||||
<span class="icon">
|
||||
<Icon
|
||||
:name="
|
||||
radio === v.value
|
||||
? 'material-symbols:radio-button-checked-outline'
|
||||
: 'material-symbols:radio-button-unchecked'
|
||||
"
|
||||
:size="18"
|
||||
/>
|
||||
</span>
|
||||
<span>{{ v.name }}</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="block">
|
||||
<button
|
||||
class="button is-primary"
|
||||
:class="loading && 'is-loading'"
|
||||
@click="updateImage"
|
||||
>
|
||||
Lưu lại
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -68,6 +99,7 @@
|
||||
<script>
|
||||
import { CircleStencil, Cropper } from "vue-advanced-cropper";
|
||||
import "vue-advanced-cropper/dist/style.css";
|
||||
|
||||
export default {
|
||||
components: {
|
||||
Cropper,
|
||||
@@ -78,61 +110,67 @@ export default {
|
||||
return {
|
||||
coordinates: undefined,
|
||||
ratios: [
|
||||
{ k: "1/1" },
|
||||
{ k: "5/4" },
|
||||
{ k: "4/3" },
|
||||
{ k: "3/2" },
|
||||
{ k: "5/3" },
|
||||
{ k: "16/9" },
|
||||
{ k: "2/1" },
|
||||
{ k: "3/1" },
|
||||
{ k: "4/5" },
|
||||
{ k: "3/4" },
|
||||
{ k: "2/3" },
|
||||
{ k: "3/5" },
|
||||
{ k: "9/16" },
|
||||
{ k: "1/2" },
|
||||
{ k: "1/3" },
|
||||
"1/1",
|
||||
"5/4",
|
||||
"4/3",
|
||||
"3/2",
|
||||
"5/3",
|
||||
"16/9",
|
||||
"2/1",
|
||||
"3/1",
|
||||
"4/5",
|
||||
"3/4",
|
||||
"2/3",
|
||||
"3/5",
|
||||
"9/16",
|
||||
"1/2",
|
||||
"1/3",
|
||||
],
|
||||
curRatio: { k: "1/1" },
|
||||
curRatio: "1/1",
|
||||
radio: this.avatar ? "new" : "replace",
|
||||
rectangle: true,
|
||||
loading: false,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
getRatio() {
|
||||
return { aspectRatio: this.$calc(this.curRatio.k) };
|
||||
return { aspectRatio: this.$calc(this.curRatio) };
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
onChange({ coordinates, canvas }) {
|
||||
onChange({ coordinates }) {
|
||||
this.coordinates = coordinates;
|
||||
this.coordinates.ratio = ((this.coordinates.width * 1.0) / this.coordinates.height).toFixed(2);
|
||||
this.coordinates.ratio = (this.coordinates.width / this.coordinates.height).toFixed(2);
|
||||
},
|
||||
updateImage() {
|
||||
const { canvas } = this.$refs.cropper.getResult();
|
||||
if (canvas) canvas.toBlob((blod) => this.saveAs(blod));
|
||||
if (canvas) canvas.toBlob((blob) => this.saveAs(blob));
|
||||
},
|
||||
async saveAs(blod) {
|
||||
this.loading = true;
|
||||
var form = new FormData();
|
||||
let name =
|
||||
this.selected.file.indexOf("-") > 0
|
||||
? this.selected.file.substring(15, this.selected.file.length)
|
||||
: this.selected.file;
|
||||
this.fileName = this.$dayjs(new Date()).format("YYYYMMDDhhmmss") + "-" + name;
|
||||
if (this.radio === "replace") this.fileName = this.selected.file;
|
||||
form.append("filename", this.fileName);
|
||||
form.append("name", name);
|
||||
form.append("file", blod);
|
||||
form.append("type", "file");
|
||||
form.append("size", this.selected.size);
|
||||
form.append("user", this.$store.state.login.id);
|
||||
let result = await this.$insertapi("upload", { data: form });
|
||||
this.loading = false;
|
||||
if (result === "error") return;
|
||||
this.$emit("modalevent", { name: "image", data: result.rows[0] });
|
||||
async saveAs(blob) {
|
||||
try {
|
||||
this.loading = true;
|
||||
const form = new FormData();
|
||||
const name =
|
||||
this.selected.file.indexOf("-") > 0
|
||||
? this.selected.file.substring(15, this.selected.file.length)
|
||||
: this.selected.file;
|
||||
this.fileName = this.$dayjs(new Date()).format("YYYYMMDDhhmmss") + "-" + name;
|
||||
if (this.radio === "replace") this.fileName = this.selected.file;
|
||||
|
||||
form.append("filename", this.fileName);
|
||||
form.append("name", name);
|
||||
form.append("file", blob);
|
||||
form.append("type", "file");
|
||||
form.append("size", this.selected.size);
|
||||
form.append("user", this.$store.login.id);
|
||||
|
||||
const result = await this.$insertapi("upload", { data: form });
|
||||
if (result === "error") return;
|
||||
this.$emit("modalevent", { name: "image", data: result.rows[0] });
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user