fix: 功能界面统一优化完善。

This commit is contained in:
tianyongbao
2026-02-07 23:53:44 +08:00
parent 72aad5cf31
commit f8df4a41dd
10 changed files with 229 additions and 155 deletions

View File

@@ -3,7 +3,7 @@
<view class="section">
<view class="section-title">{{ title }}</view>
<view class="form-view">
<u--form labelPosition="left" :model="form" :rules="rules" ref="uForm" labelWidth="120rpx"
<u--form labelPosition="left" :model="form" :rules="rules" ref="uForm" labelWidth="140rpx"
:labelStyle="{ color: '#333333', fontSize: '30rpx' }">
<u-form-item label="参数名称" prop="configName" required>
<u--input v-model="form.configName" placeholder="请输入参数名称"
@@ -180,11 +180,7 @@ function submit() {
if (errors && Array.isArray(errors)) {
errorFields.value = errors.map(err => err.field || err.prop)
}
console.log('验证失败')
proxy.$refs['uToast'].show({
type: 'error',
message: '请填写完整信息'
})
proxy.$modal.msgError('请填写完整信息')
})
}
</script>

View File

@@ -3,7 +3,7 @@
<view class="section">
<view class="section-title">{{ title }}</view>
<view class="form-view">
<u--form labelPosition="left" :model="form" :rules="rules" ref="uForm" labelWidth="120rpx"
<u--form labelPosition="left" :model="form" :rules="rules" ref="uForm" labelWidth="140rpx"
:labelStyle="{ color: '#333333', fontSize: '30rpx' }">
<u-form-item label="上级部门" prop="parentName" @click="showDeptPicker = true">
<view class="input-with-arrow">
@@ -274,10 +274,7 @@ function submit() {
if (errors && Array.isArray(errors)) {
errorFields.value = errors.map(err => err.field || err.prop)
}
proxy.$refs['uToast'].show({
type: 'error',
message: '请填写完整信息'
})
proxy.$modal.msgError('请填写完整信息')
})
}
</script>

View File

@@ -3,7 +3,7 @@
<view class="section">
<view class="section-title">{{ title }}</view>
<view class="form-view">
<u--form labelPosition="left" :model="form" :rules="rules" ref="uForm" labelWidth="120rpx"
<u--form labelPosition="left" :model="form" :rules="rules" ref="uForm" labelWidth="140rpx"
:labelStyle="{ color: '#333333', fontSize: '30rpx' }">
<u-form-item label="字典名称" prop="dictName" required>
<u--input v-model="form.dictName" placeholder="请输入字典名称"
@@ -132,11 +132,7 @@ function submit() {
if (errors && Array.isArray(errors)) {
errorFields.value = errors.map(err => err.field || err.prop)
}
console.log('验证失败')
proxy.$refs['uToast'].show({
type: 'error',
message: '请填写完整信息'
})
proxy.$modal.msgError('请填写完整信息')
})
}
</script>

View File

@@ -3,7 +3,7 @@
<view class="section">
<view class="section-title">{{ title }}</view>
<view class="form-view">
<u--form labelPosition="left" :model="form" :rules="rules" ref="uForm" labelWidth="120rpx"
<u--form labelPosition="left" :model="form" :rules="rules" ref="uForm" labelWidth="140rpx"
:labelStyle="{ color: '#333333', fontSize: '30rpx' }">
<u-form-item label="字典类型">
<u--input v-model="form.dictType" disabled disabledColor="#ffffff" placeholder="字典类型"

View File

@@ -3,7 +3,7 @@
<view class="section">
<view class="section-title">{{ title }}</view>
<view class="form-view">
<u--form labelPosition="left" :model="form" :rules="rules" ref="uForm" labelWidth="120rpx"
<u--form labelPosition="left" :model="form" :rules="rules" ref="uForm" labelWidth="140rpx"
:labelStyle="{ color: '#333333', fontSize: '30rpx' }">
<u-form-item label="上级菜单" prop="parentName" @click="showParentPicker = true">

View File

@@ -3,23 +3,26 @@
<view class="section">
<view class="section-title">公告信息</view>
<view class="form-view">
<u--form labelPosition="left" :model="form" ref="uForm" labelWidth="120rpx"
:labelStyle="{ color: '#333333', fontSize: '30rpx' }">
<u--form labelPosition="left" :model="form" :rules="rules" ref="uForm" labelWidth="140rpx"
:labelStyle="{ color: '#333333', fontSize: '30rpx', marginRight: '24rpx' }">
<u-form-item label="公告标题" prop="noticeTitle" required>
<u--input v-model="form.noticeTitle" placeholder="请输入公告标题"
inputAlign="left" :customStyle="getInputStyle('noticeTitle')"></u--input>
</u-form-item>
<u-form-item label="公告类型" prop="noticeType" required>
<u-radio-group v-model="form.noticeType" placement="row">
<u-radio v-for="item in noticeTypeList" :key="item.dictValue" :name="item.dictValue" :label="item.dictLabel">
</u-radio>
</u-radio-group>
<u-form-item label="公告类型" prop="noticeTypeName" required @click="showNoticeTypePicker = true">
<view class="input-with-arrow">
<u--input v-model="noticeTypeName" disabled disabledColor="#ffffff" placeholder="请选择公告类型"
inputAlign="left" :customStyle="getInputStyle('noticeType')"></u--input>
<text class="arrow-icon"></text>
</view>
</u-form-item>
<u-form-item label="状态" prop="status">
<u-radio-group v-model="form.status" placement="row">
<u-radio v-for="item in statusList" :key="item.dictValue" :name="item.dictValue" :label="item.dictLabel">
</u-radio>
</u-radio-group>
<u-form-item label="状态" prop="statusName" @click="showStatusPicker = true">
<view class="input-with-arrow">
<u--input v-model="statusName" disabled disabledColor="#ffffff" placeholder="请选择状态"
inputAlign="left" :customStyle="inputBaseStyle"></u--input>
<text class="arrow-icon"></text>
</view>
</u-form-item>
</u--form>
@@ -79,11 +82,19 @@
</view>
</view>
<u-toast ref="uToast"></u-toast>
<!-- 公告类型选择器 -->
<u-picker itemHeight="88" :show="showNoticeTypePicker" :columns="noticeTypeColumns" keyName="dictLabel"
@cancel="showNoticeTypePicker = false" @confirm="handleNoticeTypeConfirm"></u-picker>
<!-- 状态选择器 -->
<u-picker itemHeight="88" :show="showStatusPicker" :columns="statusColumns" keyName="dictLabel"
@cancel="showStatusPicker = false" @confirm="handleStatusConfirm"></u-picker>
</view>
</template>
<script setup>
import { ref, reactive, onMounted, nextTick } from 'vue'
import { ref, reactive, getCurrentInstance } from 'vue'
import { getNotice, addNotice, updateNotice } from '@/api/system/notice'
import { getDicts } from "@/api/system/dict/data"
import { onLoad, onReady } from "@dcloudio/uni-app"
@@ -95,6 +106,14 @@ const noticeTypeList = ref([])
const statusList = ref([])
const editorCtx = ref(null)
const contentLength = ref(0)
const showNoticeTypePicker = ref(false)
const showStatusPicker = ref(false)
const noticeTypeName = ref('')
const statusName = ref('')
// picker 列数据
const noticeTypeColumns = ref([])
const statusColumns = ref([])
const form = reactive({
noticeId: undefined,
@@ -136,42 +155,44 @@ const getInputStyle = (field) => {
return errorFields.value.includes(field) ? inputErrorStyle : inputBaseStyle
}
const rules = {
noticeTitle: [
{ required: true, message: '公告标题不能为空', trigger: ['blur', 'change'] }
],
noticeType: [
{ required: true, message: '公告类型不能为空', trigger: ['blur', 'change'] }
],
noticeContent: [
{ required: true, message: '公告内容不能为空', trigger: ['blur', 'change'] }
]
}
onLoad((options) => {
console.log('页面加载参数:', options)
if (options.id) {
noticeId.value = options.id
title.value = '修改公告'
console.log('加载公告详情ID:', noticeId.value)
getNotice(noticeId.value).then(response => {
console.log('获取到的公告数据:', response.data)
Object.assign(form, response.data)
console.log('表单数据初始化完成:', form)
// 如果编辑器已经初始化,设置内容
if (editorCtx.value && form.noticeContent) {
console.log('设置编辑器初始内容:', form.noticeContent)
editorCtx.value.setContents({
html: form.noticeContent
})
}
}).catch(error => {
console.error('获取公告详情失败:', error)
})
}
// 获取字典数据
console.log('开始获取字典数据')
getDicts('sys_notice_type').then(res => {
noticeTypeList.value = res.data
console.log('公告类型字典:', res.data)
}).catch(error => {
console.error('获取公告类型字典失败:', error)
noticeTypeColumns.value = [res.data]
updateNoticeTypeName()
})
getDicts('sys_notice_status').then(res => {
statusList.value = res.data
console.log('公告状态字典:', res.data)
}).catch(error => {
console.error('获取公告状态字典失败:', error)
statusColumns.value = [res.data]
updateStatusName()
})
})
@@ -179,26 +200,45 @@ onReady(() => {
// 页面准备完成后的一些初始化操作
})
// 更新公告类型显示名称
function updateNoticeTypeName() {
if (form.noticeType && noticeTypeList.value.length > 0) {
const item = noticeTypeList.value.find(v => v.dictValue === form.noticeType)
noticeTypeName.value = item ? item.dictLabel : ''
}
}
// 更新状态显示名称
function updateStatusName() {
if (form.status && statusList.value.length > 0) {
const item = statusList.value.find(v => v.dictValue === form.status)
statusName.value = item ? item.dictLabel : ''
}
}
// 公告类型选择确认
function handleNoticeTypeConfirm(e) {
form.noticeType = e.value[0].dictValue
noticeTypeName.value = e.value[0].dictLabel
showNoticeTypePicker.value = false
}
// 状态选择确认
function handleStatusConfirm(e) {
form.status = e.value[0].dictValue
statusName.value = e.value[0].dictLabel
showStatusPicker.value = false
}
// 编辑器初始化完成
function onEditorReady() {
console.log('编辑器初始化完成')
uni.createSelectorQuery().select('#editor').context((res) => {
editorCtx.value = res.context
console.log('编辑器上下文获取成功:', editorCtx.value)
// 如果是编辑模式,设置初始内容
if (form.noticeContent) {
console.log('设置初始内容到编辑器:', form.noticeContent)
editorCtx.value.setContents({
html: form.noticeContent,
success: () => {
console.log('编辑器内容设置成功')
},
fail: (error) => {
console.error('编辑器内容设置失败:', error)
}
html: form.noticeContent
})
} else {
console.log('没有初始内容需要设置')
}
}).exec()
}
@@ -213,7 +253,6 @@ function onEditorInput(e) {
// 计算内容长度去除HTML标签
const text = res.text || ''
contentLength.value = text.length
console.log('编辑器内容已更新:', res.html)
}
})
}
@@ -230,10 +269,6 @@ function editorBlur() {
editorCtx.value.getContents({
success: (res) => {
form.noticeContent = res.html
console.log('失去焦点时保存的内容:', res.html)
},
fail: (error) => {
console.error('失去焦点时获取内容失败:', error)
}
})
}
@@ -298,8 +333,7 @@ function insertImage() {
icon: 'success'
})
},
fail: (err) => {
console.error('插入图片失败', err)
fail: () => {
uni.showToast({
title: '插入失败',
icon: 'none'
@@ -314,119 +348,76 @@ function insertImage() {
})
}
} catch (e) {
console.error('解析上传结果失败', e)
uni.showToast({
title: '上传失败',
icon: 'none'
})
}
},
fail: (err) => {
fail: () => {
uni.hideLoading()
console.error('上传失败', err)
uni.showToast({
title: '上传失败',
icon: 'none'
})
}
})
},
fail: (err) => {
console.error('选择图片失败', err)
}
})
}
// 提交表单
async function submitForm() {
errorFields.value = [] // 清空错误字段
try {
// 提交前确保获取最新的编辑器内容
if (editorCtx.value) {
const content = await new Promise((resolve, reject) => {
await new Promise((resolve, reject) => {
editorCtx.value.getContents({
success: (res) => {
form.noticeContent = res.html
console.log('提交前获取到的内容:', res.html)
resolve(res.html)
},
fail: reject
})
})
// 确保内容已更新到表单
await nextTick()
}
// 使用 UView 表单验证
const { proxy } = getCurrentInstance()
await proxy.$refs['uForm'].validate()
// 验证通过,提交数据
doSubmit()
} catch (error) {
console.error('获取编辑器内容失败:', error)
modal.msgError('获取内容失败,请重试')
} catch (errors) {
// 记录验证失败的字段
if (errors && Array.isArray(errors)) {
errorFields.value = errors.map(err => err.field || err.prop)
}
modal.msgError('请填写完整信息')
}
}
function doSubmit() {
errorFields.value = [] // 清空错误字段
console.log('准备提交的表单数据:', form)
if (!form.noticeTitle) {
errorFields.value.push('noticeTitle')
modal.msgError('请输入公告标题')
return
}
if (!form.noticeType) {
errorFields.value.push('noticeType')
modal.msgError('请选择公告类型')
return
}
if (!form.noticeContent || form.noticeContent.trim() === '') {
errorFields.value.push('noticeContent')
modal.msgError('请输入公告内容')
return
}
const submitForm = { ...form }
console.log('最终提交的数据:', submitForm)
// 检查必要字段
console.log('检查字段:')
console.log('- 标题:', submitForm.noticeTitle)
console.log('- 类型:', submitForm.noticeType)
console.log('- 内容长度:', submitForm.noticeContent.length)
console.log('- 状态:', submitForm.status)
console.log('- ID:', submitForm.noticeId)
if (noticeId.value) {
console.log('执行修改操作')
updateNotice(submitForm).then(response => {
console.log('修改成功响应:', response)
modal.msgSuccess('修改成功')
setTimeout(() => {
uni.navigateBack()
}, 1000)
}).catch(error => {
console.error('修改失败:', error)
console.log('错误详情:', {
message: error.message,
response: error.response,
data: error.response?.data
})
modal.msgError('修改失败: ' + (error.message || '未知错误'))
})
} else {
console.log('执行新增操作')
addNotice(submitForm).then(response => {
console.log('新增成功响应:', response)
modal.msgSuccess('新增成功')
setTimeout(() => {
uni.navigateBack()
}, 1000)
}).catch(error => {
console.error('新增失败:', error)
console.log('错误详情:', {
message: error.message,
response: error.response,
data: error.response?.data
})
modal.msgError('新增失败: ' + (error.message || '未知错误'))
})
}
@@ -473,6 +464,23 @@ function doSubmit() {
padding-top: 16rpx;
}
// 带箭头的输入框容器
.input-with-arrow {
position: relative;
width: 100%;
.arrow-icon {
position: absolute;
right: 20rpx;
top: 50%;
transform: translateY(-50%);
color: #c0c4cc;
font-size: 20rpx;
pointer-events: none;
z-index: 10;
}
}
/* 确保表单项正常布局 */
.u-form-item {
display: flex;

View File

@@ -3,7 +3,7 @@
<view class="section">
<view class="section-title">{{ title }}</view>
<view class="form-view">
<u--form labelPosition="left" :model="form" :rules="rules" ref="uForm" labelWidth="120rpx"
<u--form labelPosition="left" :model="form" :rules="rules" ref="uForm" labelWidth="140rpx"
:labelStyle="{ color: '#333333', fontSize: '30rpx' }">
<u-form-item label="岗位名称" prop="postName" required>
<u--input v-model="form.postName" placeholder="请输入岗位名称" maxlength="30"
@@ -170,10 +170,7 @@ function submit() {
if (errors && Array.isArray(errors)) {
errorFields.value = errors.map(err => err.field || err.prop)
}
proxy.$refs['uToast'].show({
type: 'error',
message: '请填写完整信息'
})
proxy.$modal.msgError('请填写完整信息')
})
}
</script>

View File

@@ -3,7 +3,7 @@
<view class="section">
<view class="section-title">{{ title }}</view>
<view class="form-view">
<u--form labelPosition="left" :model="form" :rules="rules" ref="uForm" labelWidth="120rpx"
<u--form labelPosition="left" :model="form" :rules="rules" ref="uForm" labelWidth="140rpx"
:labelStyle="{ color: '#333333', fontSize: '30rpx' }">
<u-form-item label="角色名称" prop="roleName" required>

View File

@@ -3,8 +3,8 @@
<view class="section">
<view class="section-title">{{ title }}</view>
<view class="form-view">
<u--form labelPosition="left" :model="form" :rules="rules" ref="uForm" labelWidth="120rpx"
:labelStyle="{ color: '#333333', fontSize: '30rpx' }">
<u--form labelPosition="left" :model="form" :rules="rules" ref="uForm" labelWidth="140rpx"
:labelStyle="{ color: '#333333', fontSize: '30rpx', marginRight: '24rpx' }">
<u-form-item label="用户昵称" prop="nickName" required>
<u--input v-model="form.nickName" placeholder="请输入用户昵称" maxlength="30"
inputAlign="left" :customStyle="getInputStyle('nickName')"></u--input>
@@ -460,29 +460,64 @@ function confirmRoleSelect() {
// 提交
function submit() {
errorFields.value = [] // 清空错误字段
proxy.$refs['uForm'].validate().then(() => {
if (form.userId) {
updateUser(form).then(() => {
proxy.$modal.msgSuccess('修改成功')
setTimeout(() => {
uni.navigateTo({ url: `/pages_mine/pages/system/user/list` })
}, 1500)
})
} else {
addUser(form).then(() => {
proxy.$modal.msgSuccess('新增成功')
setTimeout(() => {
uni.navigateTo({ url: `/pages_mine/pages/system/user/list` })
}, 1500)
})
// 手动验证必填项
if (!form.nickName) {
errorFields.value.push('nickName')
proxy.$modal.msgError('请输入用户昵称')
return
}
// 新增时验证用户名和密码
if (!form.userId) {
if (!form.userName) {
errorFields.value.push('userName')
proxy.$modal.msgError('请输入用户名称')
return
}
}).catch((errors) => {
// 记录验证失败的字段
if (errors && Array.isArray(errors)) {
errorFields.value = errors.map(err => err.field || err.prop)
if (!form.password) {
errorFields.value.push('password')
proxy.$modal.msgError('请输入用户密码')
return
}
proxy.$modal.msgError('请填写完整信息')
})
}
if (!form.phonenumber) {
errorFields.value.push('phonenumber')
proxy.$modal.msgError('请输入手机号码')
return
}
// 验证手机号格式
if (!/^1[3-9]\d{9}$/.test(form.phonenumber)) {
errorFields.value.push('phonenumber')
proxy.$modal.msgError('请输入正确的手机号码')
return
}
// 验证邮箱格式(如果填写了邮箱)
if (form.email && !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(form.email)) {
errorFields.value.push('email')
proxy.$modal.msgError('请输入正确的邮箱地址')
return
}
// 提交数据
if (form.userId) {
updateUser(form).then(() => {
proxy.$modal.msgSuccess('修改成功')
setTimeout(() => {
uni.navigateTo({ url: `/pages_mine/pages/system/user/list` })
}, 1500)
})
} else {
addUser(form).then(() => {
proxy.$modal.msgSuccess('新增成功')
setTimeout(() => {
uni.navigateTo({ url: `/pages_mine/pages/system/user/list` })
}, 1500)
})
}
}
</script>

View File

@@ -95,7 +95,7 @@
.form-view {
// 表单项间距
:deep(.u-form-item) {
margin-bottom: 5rpx;
margin-bottom: -10rpx;
position: relative;
}
@@ -179,8 +179,8 @@
border-color: #f56c6c !important;
}
// 下拉箭头放到输入框内部右侧
:deep(.u-form-item__body__right) {
// 下拉箭头放到输入框内部右侧(仅在有图标时生效)
:deep(.u-form-item__body__right:has(.u-icon)) {
position: absolute !important;
right: 24rpx !important;
top: 50% !important;
@@ -195,6 +195,51 @@
font-size: 28rpx !important;
}
// 带箭头的下拉选择框(使用 class="with-arrow"
:deep(.with-arrow) {
position: relative;
cursor: pointer;
// 增加点击区域提示
.u-form-item__body {
cursor: pointer;
}
// disabled 输入框允许点击穿透
.u--input {
pointer-events: none !important;
}
.u-input {
pointer-events: none !important;
}
.u-input__content {
pointer-events: none !important;
}
.u-input__content__field-wrapper {
pointer-events: none !important;
}
.u-input__content__field-wrapper__field {
pointer-events: none !important;
}
// 用伪元素添加箭头,不影响布局宽度
&::after {
content: '';
position: absolute;
right: 20rpx;
top: 50%;
transform: translateY(-50%);
color: #c0c4cc;
font-size: 20rpx;
pointer-events: none;
z-index: 10;
}
}
// 统一图标颜色
:deep(.u-icon) {
color: #909399 !important;