main
parent
c03f5b6f45
commit
1abc380d5e
@ -0,0 +1,261 @@
|
||||
<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>
|
||||
|
||||
<!-- 提交按钮 -->
|
||||
<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: ''
|
||||
})
|
||||
|
||||
// 错误信息
|
||||
const errors = ref({
|
||||
name: '',
|
||||
description: ''
|
||||
})
|
||||
|
||||
// 提交状态
|
||||
const submitLoading = ref(false)
|
||||
|
||||
// 表单验证
|
||||
const isFormValid = computed(() => {
|
||||
return formData.value.name.trim() && formData.value.description.trim()
|
||||
})
|
||||
|
||||
// 输入事件处理
|
||||
const onNameInput = () => {
|
||||
if (errors.value.name) {
|
||||
errors.value.name = ''
|
||||
}
|
||||
}
|
||||
|
||||
const onDescriptionInput = () => {
|
||||
if (errors.value.description) {
|
||||
errors.value.description = ''
|
||||
}
|
||||
}
|
||||
|
||||
// 表单验证函数
|
||||
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
|
||||
}
|
||||
|
||||
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()
|
||||
})
|
||||
|
||||
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 = () => {
|
||||
if (formData.value.name.trim() || formData.value.description.trim()) {
|
||||
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>
|
||||
Loading…
Reference in new issue