Lufaneng 9 months ago
parent c03f5b6f45
commit 1abc380d5e

@ -115,6 +115,14 @@
{
"navigationBarTitleText" : "支付结果"
}
},
{
"path" : "add-requirement/add-requirement",
"style" :
{
"navigationBarTitleText" : "新增需求",
"navigationStyle": "custom"
}
}
]
}

@ -134,6 +134,12 @@
<uv-icon name="arrow-right" size="16" color="#ccc"></uv-icon>
</view>
</view>
<view class="profile-item" @click="addRequirement">
<view class="item-label">新增需求</view>
<view class="item-content">
<uv-icon name="arrow-right" size="16" color="#ccc"></uv-icon>
</view>
</view>
<view class="profile-item" @click="logout">
<view class="item-label">退出登录</view>
<view class="item-content">
@ -186,12 +192,19 @@ const getMemberInfo = () => {
.finally(() => {
uni.hideLoading();
});
};
};
const viewUserAgreement = () => {
uni.navigateTo({
url: "/pagesA/user-agreement/user-agreement",
});
uni.navigateTo({
url: "/pagesA/user-agreement/user-agreement",
});
};
//
const addRequirement = () => {
uni.navigateTo({
url: "/pagesA/add-requirement/add-requirement",
});
};
//
@ -279,7 +292,7 @@ onPullDownRefresh(() => {
uni.stopPullDownRefresh();
});
const logoutLoading = ref(false)
const logoutLoading = ref(false);
const logout = () => {
uni.showModal({
@ -318,10 +331,10 @@ const logout = () => {
font-size: 14px;
background: linear-gradient(180deg, #7b9cdb 0%, #f8f8f8 40%);
min-height: 100vh;
// padding-bottom: 120px;
// padding-bottom: 120px;
/* #ifdef H5 */
// padding-bottom: 170px;
// padding-bottom: 170px;
/* H5环境下需要更多空间 (底部按钮高度 + tabBar高度 + 间距) */
/* #endif */
}

@ -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>

@ -8,7 +8,7 @@
<view class="record-item">
<!-- 记录信息 -->
<view class="record-info">
<view class="record-title">{{ record.file_name || record.order_no + record.order_no || record.plannedNo }}</view>
<view class="record-title">{{ record.file_name || record.order_no || record.plannedNo }}</view>
<view class="record-time">
生成时间:
{{

Loading…
Cancel
Save