Initial project commit
This commit is contained in:
@@ -0,0 +1,331 @@
|
||||
<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>
|
||||
Reference in New Issue
Block a user