Operators can edit landing copy as plain fields instead of JSON/HTML; default CMS seed and UI chrome are now Farsi/RTL. Co-authored-by: Cursor <cursoragent@cursor.com>
101 lines
3.3 KiB
Vue
101 lines
3.3 KiB
Vue
<template>
|
||
<div>
|
||
<div class="row" style="justify-content: space-between; margin-bottom: 1rem">
|
||
<h1>{{ isNew ? "پست جدید" : "ویرایش پست" }}</h1>
|
||
<RouterLink class="btn ghost" to="/blog">بازگشت</RouterLink>
|
||
</div>
|
||
<form class="card" @submit.prevent="save">
|
||
<div class="grid-2">
|
||
<div class="field">
|
||
<label class="label">عنوان</label>
|
||
<input v-model="form.title" class="input" required />
|
||
</div>
|
||
<div class="field">
|
||
<label class="label">اسلاگ</label>
|
||
<input v-model="form.slug" class="input" dir="ltr" required />
|
||
</div>
|
||
</div>
|
||
<div class="field">
|
||
<label class="label">خلاصه</label>
|
||
<textarea v-model="form.excerpt" class="textarea" />
|
||
</div>
|
||
<div class="field">
|
||
<label class="label">متن پست</label>
|
||
<textarea v-model="form.content" class="textarea" style="min-height: 240px" placeholder="متن را عادی بنویسید. برای پاراگراف جدید Enter بزنید." />
|
||
</div>
|
||
<div class="grid-2">
|
||
<div class="field">
|
||
<label class="label">آدرس تصویر کاور</label>
|
||
<input v-model="form.coverUrl" class="input" dir="ltr" placeholder="از بخش رسانه آپلود کنید و آدرس را اینجا بگذارید" />
|
||
</div>
|
||
<div class="field">
|
||
<label class="label">عنوان سئو</label>
|
||
<input v-model="form.seoTitle" class="input" />
|
||
</div>
|
||
<div class="field">
|
||
<label class="label">توضیح سئو</label>
|
||
<input v-model="form.seoDesc" class="input" />
|
||
</div>
|
||
<div class="field">
|
||
<label class="label">آدرس Canonical</label>
|
||
<input v-model="form.canonical" class="input" dir="ltr" />
|
||
</div>
|
||
<div class="field">
|
||
<label class="label">تصویر اشتراکگذاری</label>
|
||
<input v-model="form.ogImage" class="input" dir="ltr" />
|
||
</div>
|
||
<div class="field">
|
||
<label class="label"><input v-model="form.published" type="checkbox" /> منتشر شود</label>
|
||
</div>
|
||
</div>
|
||
<p v-if="msg" class="muted">{{ msg }}</p>
|
||
<button class="btn">ذخیره</button>
|
||
</form>
|
||
</div>
|
||
</template>
|
||
|
||
<script setup lang="ts">
|
||
import { computed, onMounted, reactive, ref } from "vue";
|
||
import { useRoute, useRouter } from "vue-router";
|
||
import { api } from "../lib/api";
|
||
|
||
const route = useRoute();
|
||
const router = useRouter();
|
||
const isNew = computed(() => route.name === "blog-new");
|
||
const msg = ref("");
|
||
const form = reactive({
|
||
title: "",
|
||
slug: "",
|
||
excerpt: "",
|
||
content: "",
|
||
coverUrl: "",
|
||
seoTitle: "",
|
||
seoDesc: "",
|
||
ogImage: "",
|
||
canonical: "",
|
||
published: false,
|
||
});
|
||
|
||
onMounted(async () => {
|
||
if (isNew.value) return;
|
||
const { data } = await api.get(`/admin/blog/${route.params.id}`);
|
||
Object.assign(form, data);
|
||
});
|
||
|
||
async function save() {
|
||
msg.value = "";
|
||
try {
|
||
if (isNew.value) {
|
||
const { data } = await api.post("/admin/blog", form);
|
||
msg.value = "ایجاد شد.";
|
||
router.replace(`/blog/${data.id}`);
|
||
} else {
|
||
await api.put(`/admin/blog/${route.params.id}`, form);
|
||
msg.value = "ذخیره شد.";
|
||
}
|
||
} catch {
|
||
msg.value = "خطا در ذخیره.";
|
||
}
|
||
}
|
||
</script>
|