You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

377 lines
8.2 KiB

<template>
<view class="container">
<!-- 自定义导航栏 -->
<view class="custom-navbar">
<view class="navbar-content">
<view class="back-btn" @click="goBack">
<uv-icon name="arrow-left" size="20" color="#333"></uv-icon>
</view>
<view class="navbar-title">新增需求</view>
<view class="placeholder"></view>
</view>
</view>
<!-- 表单内容 -->
<view class="form-container">
<view class="form-item">
<view class="form-label">
需求名称
<text class="required">*</text>
</view>
<uv-input
v-model="formData.name"
placeholder="请输入需求名称"
:clearable="true"
:maxlength="50"
@input="onNameInput"
></uv-input>
<view class="error-text" v-if="errors.name">{{ errors.name }}</view>
</view>
<view class="form-item">
<view class="form-label">
需求描述
<text class="required">*</text>
</view>
<uv-textarea
v-model="formData.description"
placeholder="请详细描述您的需求..."
:maxlength="500"
:autoHeight="true"
:minHeight="120"
@input="onDescriptionInput"
></uv-textarea>
<view class="char-count">{{ formData.description.length }}/500</view>
<view class="error-text" v-if="errors.description">
{{ errors.description }}
</view>
</view>
<view class="form-item">
<view class="form-label">
邮箱
<text class="required">*</text>
</view>
<uv-input
v-model="formData.email"
placeholder="请输入邮箱地址"
:clearable="true"
type="email"
@input="onEmailInput"
></uv-input>
<view class="error-text" v-if="errors.email">{{ errors.email }}</view>
</view>
<view class="form-item">
<view class="form-label">
手机
<text class="required">*</text>
</view>
<uv-input
v-model="formData.phone"
placeholder="请输入手机号"
:clearable="true"
type="number"
:maxlength="11"
@input="onPhoneInput"
></uv-input>
<view class="error-text" v-if="errors.phone">{{ errors.phone }}</view>
</view>
<view class="form-item">
<view class="form-label">联系厂家</view>
<uv-input
v-model="formData.vendor_contact"
placeholder="请输入联系厂家(选填)"
:clearable="true"
:maxlength="100"
@input="onVendorContactInput"
></uv-input>
<view class="error-text" v-if="errors.vendor_contact">
{{ errors.vendor_contact }}
</view>
</view>
</view>
<!-- 提交按钮 -->
<view class="submit-section">
<uv-button
type="primary"
:loading="submitLoading"
@click="submitRequirement"
:disabled="!isFormValid"
>
提交需求
</uv-button>
</view>
</view>
</template>
<script setup>
import { ref, computed } from "vue";
import { useUserStore } from "@/store";
import RPC from "@/utils/request";
const userStore = useUserStore();
// 表单数据
const formData = ref({
name: "",
description: "",
email: "",
phone: "",
vendor_contact: "",
});
// 错误信息
const errors = ref({
name: "",
description: "",
email: "",
phone: "",
vendor_contact: "",
});
// 提交状态
const submitLoading = ref(false);
// 邮箱验证
const validateEmail = (email) => {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return emailRegex.test(email);
};
// 手机号验证
const validatePhone = (phone) => {
const phoneRegex = /^1[3-9]\d{9}$/;
return phoneRegex.test(phone);
};
// 表单验证
const isFormValid = computed(() => {
return (
formData.value.name.trim() &&
formData.value.description.trim() &&
formData.value.email.trim() &&
formData.value.phone.trim()
);
});
// 输入事件处理
const onNameInput = () => {
if (errors.value.name) {
errors.value.name = "";
}
};
const onDescriptionInput = () => {
if (errors.value.description) {
errors.value.description = "";
}
};
const onEmailInput = () => {
if (errors.value.email) {
errors.value.email = "";
}
};
const onPhoneInput = () => {
if (errors.value.phone) {
errors.value.phone = "";
}
};
const onVendorContactInput = () => {
if (errors.value.vendor_contact) {
errors.value.vendor_contact = "";
}
};
// 表单验证函数
const validateForm = () => {
let isValid = true;
// 验证需求名称
if (!formData.value.name.trim()) {
errors.value.name = "请输入需求名称";
isValid = false;
}
// 验证需求描述
if (!formData.value.description.trim()) {
errors.value.description = "请输入需求描述";
isValid = false;
}
// 验证邮箱
if (!formData.value.email.trim()) {
errors.value.email = "请输入邮箱地址";
isValid = false;
} else if (!validateEmail(formData.value.email.trim())) {
errors.value.email = "请输入正确的邮箱格式";
isValid = false;
}
// 验证手机号
if (!formData.value.phone.trim()) {
errors.value.phone = "请输入手机号";
isValid = false;
} else if (!validatePhone(formData.value.phone.trim())) {
errors.value.phone = "请输入正确的手机号格式";
isValid = false;
}
return isValid;
};
// 提交需求
const submitRequirement = async () => {
if (!validateForm()) {
return;
}
submitLoading.value = true;
try {
const response = await RPC.post("/requirement/create", {
proposer_id: userStore.userInfo.id,
proposer: userStore.userInfo.username,
name: formData.value.name.trim(),
description: formData.value.description.trim(),
email: formData.value.email.trim(),
phone: formData.value.phone.trim(),
vendor_contact: formData.value.vendor_contact.trim(),
category:'需求新增'
});
uni.showToast({
title: "需求提交成功",
icon: "success",
});
// 延迟返回上一页
setTimeout(() => {
uni.navigateBack();
}, 1500);
} catch (error) {
console.error("提交需求失败:", error);
uni.showToast({
title: error.message || "提交失败,请重试",
icon: "none",
});
} finally {
submitLoading.value = false;
}
};
// 返回上一页
const goBack = () => {
const hasContent =
formData.value.name.trim() ||
formData.value.description.trim() ||
formData.value.email.trim() ||
formData.value.phone.trim() ||
formData.value.vendor_contact.trim();
if (hasContent) {
uni.showModal({
title: "提示",
content: "您有未保存的内容,确定要离开吗?",
success: (res) => {
if (res.confirm) {
uni.navigateBack();
}
},
});
} else {
uni.navigateBack();
}
};
</script>
<style lang="scss" scoped>
.container {
min-height: 100vh;
background-color: #f8f8f8;
}
.custom-navbar {
background: white;
padding-top: var(--status-bar-height);
border-bottom: 1px solid #e5e5e5;
.navbar-content {
display: flex;
align-items: center;
justify-content: space-between;
height: 44px;
padding: 0 16px;
.back-btn {
width: 40px;
height: 40px;
display: flex;
align-items: center;
justify-content: center;
}
.navbar-title {
font-size: 18px;
font-weight: 600;
color: #333;
}
.placeholder {
width: 40px;
}
}
}
.form-container {
padding: 20px 16px;
.form-item {
margin-bottom: 24px;
.form-label {
font-size: 16px;
color: #333;
margin-bottom: 8px;
font-weight: 500;
.required {
color: #ff3333;
margin-left: 2px;
}
}
.char-count {
text-align: right;
font-size: 12px;
color: #999;
margin-top: 4px;
}
.error-text {
color: #ff3333;
font-size: 12px;
margin-top: 4px;
}
}
}
.submit-section {
position: fixed;
bottom: 0;
left: 0;
right: 0;
background: white;
padding: 16px;
border-top: 1px solid #e5e5e5;
/* #ifdef H5 */
bottom: 50px;
/* #endif */
}
</style>