332 lines
8.3 KiB
Vue
332 lines
8.3 KiB
Vue
<script setup>
|
|
import { ref, computed } from "vue";
|
|
import { onLoad } from "@dcloudio/uni-app";
|
|
import { createShooting, updateShooting, getShootingDetail } from "@/api/shooting";
|
|
|
|
const isEdit = ref(false);
|
|
const editId = ref(0);
|
|
const submitting = ref(false);
|
|
|
|
const form = ref({
|
|
title: "",
|
|
city: "",
|
|
description: "",
|
|
style: "",
|
|
shoot_date: "",
|
|
is_free: false,
|
|
budget_min: "",
|
|
budget_max: "",
|
|
role_needed: "photographer",
|
|
max_applicants: 1,
|
|
contact_info: "",
|
|
});
|
|
|
|
const roleOptions = [
|
|
{ label: "摄影师", value: "photographer" },
|
|
{ label: "Coser", value: "cosplayer" },
|
|
{ label: "不限", value: "both" },
|
|
];
|
|
|
|
const roleIndex = computed({
|
|
get() {
|
|
return roleOptions.findIndex((o) => o.value === form.value.role_needed);
|
|
},
|
|
set(idx) {
|
|
form.value.role_needed = roleOptions[idx].value;
|
|
},
|
|
});
|
|
|
|
function onDateChange(e) {
|
|
form.value.shoot_date = e.detail.value;
|
|
}
|
|
|
|
function validate() {
|
|
if (!form.value.title.trim()) {
|
|
uni.showToast({ title: "请输入标题", icon: "none" });
|
|
return false;
|
|
}
|
|
if (!form.value.city.trim()) {
|
|
uni.showToast({ title: "请输入城市", icon: "none" });
|
|
return false;
|
|
}
|
|
if (!form.value.is_free) {
|
|
const min = Number(form.value.budget_min);
|
|
const max = Number(form.value.budget_max);
|
|
if (min && max && min > max) {
|
|
uni.showToast({ title: "最低预算不能高于最高预算", icon: "none" });
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
async function handleSubmit() {
|
|
if (!validate()) return;
|
|
submitting.value = true;
|
|
|
|
const data = {
|
|
title: form.value.title.trim(),
|
|
city: form.value.city.trim(),
|
|
description: form.value.description.trim() || null,
|
|
style: form.value.style.trim() || null,
|
|
is_free: form.value.is_free,
|
|
role_needed: form.value.role_needed,
|
|
max_applicants: Number(form.value.max_applicants) || 1,
|
|
contact_info: form.value.contact_info.trim() || null,
|
|
};
|
|
|
|
if (form.value.shoot_date) {
|
|
data.shoot_date = new Date(form.value.shoot_date).toISOString();
|
|
}
|
|
if (!form.value.is_free) {
|
|
data.budget_min = form.value.budget_min ? Number(form.value.budget_min) : null;
|
|
data.budget_max = form.value.budget_max ? Number(form.value.budget_max) : null;
|
|
}
|
|
|
|
try {
|
|
if (isEdit.value) {
|
|
await updateShooting(editId.value, data);
|
|
uni.showToast({ title: "更新成功", icon: "success" });
|
|
} else {
|
|
await createShooting(data);
|
|
uni.showToast({ title: "发布成功,等待审核", icon: "success" });
|
|
}
|
|
setTimeout(() => uni.navigateBack(), 1200);
|
|
} catch (e) {
|
|
uni.showToast({ title: e.message || "提交失败", icon: "none" });
|
|
} finally {
|
|
submitting.value = false;
|
|
}
|
|
}
|
|
|
|
async function loadForEdit(id) {
|
|
try {
|
|
const d = await getShootingDetail(id);
|
|
form.value.title = d.title || "";
|
|
form.value.city = d.city || "";
|
|
form.value.description = d.description || "";
|
|
form.value.style = d.style || "";
|
|
form.value.is_free = d.is_free || false;
|
|
form.value.budget_min = d.budget_min ? String(d.budget_min) : "";
|
|
form.value.budget_max = d.budget_max ? String(d.budget_max) : "";
|
|
form.value.role_needed = d.role_needed || "photographer";
|
|
form.value.max_applicants = d.max_applicants || 1;
|
|
form.value.contact_info = d.contact_info || "";
|
|
if (d.shoot_date) {
|
|
form.value.shoot_date = d.shoot_date.substring(0, 10);
|
|
}
|
|
} catch (e) {
|
|
uni.showToast({ title: "加载失败", icon: "none" });
|
|
}
|
|
}
|
|
|
|
onLoad((query) => {
|
|
if (query.id) {
|
|
isEdit.value = true;
|
|
editId.value = Number(query.id);
|
|
uni.setNavigationBarTitle({ title: "编辑约拍" });
|
|
loadForEdit(editId.value);
|
|
}
|
|
});
|
|
</script>
|
|
|
|
<template>
|
|
<view class="create-page">
|
|
<view class="form-card">
|
|
<view class="form-row">
|
|
<text class="form-label required">标题</text>
|
|
<input
|
|
v-model="form.title"
|
|
class="form-input"
|
|
placeholder="如:上海外滩约拍"
|
|
:maxlength="100"
|
|
/>
|
|
</view>
|
|
|
|
<view class="form-row">
|
|
<text class="form-label required">城市</text>
|
|
<input
|
|
v-model="form.city"
|
|
class="form-input"
|
|
placeholder="如:上海"
|
|
:maxlength="50"
|
|
/>
|
|
</view>
|
|
|
|
<view class="form-row">
|
|
<text class="form-label">风格</text>
|
|
<input
|
|
v-model="form.style"
|
|
class="form-input"
|
|
placeholder="如:古风、JK、日系清新"
|
|
:maxlength="50"
|
|
/>
|
|
</view>
|
|
|
|
<view class="form-row">
|
|
<text class="form-label">拍摄日期</text>
|
|
<picker mode="date" :value="form.shoot_date" @change="onDateChange">
|
|
<view class="form-input picker-display">
|
|
{{ form.shoot_date || "选择日期(可选)" }}
|
|
</view>
|
|
</picker>
|
|
</view>
|
|
|
|
<view class="form-row">
|
|
<text class="form-label">需要角色</text>
|
|
<picker
|
|
:range="roleOptions"
|
|
range-key="label"
|
|
:value="roleIndex"
|
|
@change="roleIndex = $event.detail.value"
|
|
>
|
|
<view class="form-input picker-display">
|
|
{{ roleOptions[roleIndex]?.label || "选择" }}
|
|
</view>
|
|
</picker>
|
|
</view>
|
|
|
|
<view class="form-row">
|
|
<text class="form-label">招募人数</text>
|
|
<input
|
|
v-model="form.max_applicants"
|
|
class="form-input"
|
|
type="number"
|
|
placeholder="默认1人"
|
|
/>
|
|
</view>
|
|
|
|
<view class="form-row switch-row">
|
|
<text class="form-label">互免约拍</text>
|
|
<switch :checked="form.is_free" @change="form.is_free = $event.detail.value" color="#6366f1" />
|
|
</view>
|
|
|
|
<template v-if="!form.is_free">
|
|
<view class="form-row">
|
|
<text class="form-label">预算下限</text>
|
|
<input
|
|
v-model="form.budget_min"
|
|
class="form-input"
|
|
type="digit"
|
|
placeholder="最低价格(选填)"
|
|
/>
|
|
</view>
|
|
<view class="form-row">
|
|
<text class="form-label">预算上限</text>
|
|
<input
|
|
v-model="form.budget_max"
|
|
class="form-input"
|
|
type="digit"
|
|
placeholder="最高价格(选填)"
|
|
/>
|
|
</view>
|
|
</template>
|
|
|
|
<view class="form-row">
|
|
<text class="form-label">联系方式</text>
|
|
<input
|
|
v-model="form.contact_info"
|
|
class="form-input"
|
|
placeholder="微信/QQ/手机号(仅对方可见)"
|
|
:maxlength="100"
|
|
/>
|
|
</view>
|
|
|
|
<view class="form-row">
|
|
<text class="form-label">详细描述</text>
|
|
<textarea
|
|
v-model="form.description"
|
|
class="form-textarea"
|
|
placeholder="描述拍摄需求、时间安排等"
|
|
:maxlength="2000"
|
|
/>
|
|
</view>
|
|
</view>
|
|
|
|
<view class="submit-row">
|
|
<view
|
|
class="submit-btn"
|
|
:class="{ disabled: submitting }"
|
|
@tap="handleSubmit"
|
|
>
|
|
{{ submitting ? "提交中..." : isEdit ? "保存修改" : "发布约拍" }}
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</template>
|
|
|
|
<style scoped>
|
|
.create-page {
|
|
min-height: 100vh;
|
|
background: #f5f6fa;
|
|
padding-bottom: 40rpx;
|
|
}
|
|
.form-card {
|
|
background: #fff;
|
|
margin: 16rpx 20rpx;
|
|
border-radius: 20rpx;
|
|
padding: 12rpx 28rpx;
|
|
}
|
|
.form-row {
|
|
padding: 20rpx 0;
|
|
border-bottom: 1rpx solid #f3f4f6;
|
|
}
|
|
.form-row:last-child {
|
|
border-bottom: none;
|
|
}
|
|
.switch-row {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
}
|
|
.form-label {
|
|
font-size: 26rpx;
|
|
color: #374151;
|
|
margin-bottom: 10rpx;
|
|
display: block;
|
|
}
|
|
.form-label.required::before {
|
|
content: "* ";
|
|
color: #ef4444;
|
|
}
|
|
.form-input {
|
|
width: 100%;
|
|
height: 72rpx;
|
|
border: 1rpx solid #e5e7eb;
|
|
border-radius: 12rpx;
|
|
padding: 0 20rpx;
|
|
font-size: 28rpx;
|
|
box-sizing: border-box;
|
|
line-height: 72rpx;
|
|
}
|
|
.picker-display {
|
|
display: flex;
|
|
align-items: center;
|
|
color: #374151;
|
|
}
|
|
.form-textarea {
|
|
width: 100%;
|
|
min-height: 200rpx;
|
|
border: 1rpx solid #e5e7eb;
|
|
border-radius: 12rpx;
|
|
padding: 16rpx 20rpx;
|
|
font-size: 28rpx;
|
|
box-sizing: border-box;
|
|
}
|
|
.submit-row {
|
|
padding: 20rpx 28rpx;
|
|
}
|
|
.submit-btn {
|
|
text-align: center;
|
|
padding: 24rpx 0;
|
|
background: #6366f1;
|
|
color: #fff;
|
|
font-size: 30rpx;
|
|
font-weight: 700;
|
|
border-radius: 16rpx;
|
|
}
|
|
.submit-btn.disabled {
|
|
opacity: 0.6;
|
|
}
|
|
</style>
|