641 lines
20 KiB
Vue
641 lines
20 KiB
Vue
<template>
|
||
<view class="container">
|
||
<view class="form-container">
|
||
<uni-section title="基础卡片" type="line">
|
||
<!-- 基础表单校验:缩小字体+一行两列布局 -->
|
||
<uni-forms
|
||
ref="valiForm"
|
||
label-position="left"
|
||
:modelValue="form"
|
||
style="font-size: 10px;"
|
||
>
|
||
<!-- 一行两列布局容器 -->
|
||
<view class="form-row">
|
||
<uni-forms-item label="标题:" name="title" class="form-item">
|
||
<uni-easyinput
|
||
v-model="form.title"
|
||
placeholder="请输入标题搜索"
|
||
/>
|
||
</uni-forms-item>
|
||
<uni-forms-item label="详情:" name="detail" class="form-item">
|
||
<uni-easyinput
|
||
v-model="form.detail"
|
||
placeholder="请输入详情搜索"
|
||
/>
|
||
</uni-forms-item>
|
||
</view>
|
||
|
||
<!-- 第二行两列 -->
|
||
<view class="form-row">
|
||
<uni-forms-item label="优先级:" name="priority" class="form-item">
|
||
<uni-data-select
|
||
v-model="form.priority"
|
||
:localdata="priorityList"
|
||
/>
|
||
</uni-forms-item>
|
||
<uni-forms-item label="进度:" name="progress" class="form-item">
|
||
<uni-data-select
|
||
v-model="form.progress"
|
||
:localdata="progressList"
|
||
/>
|
||
</uni-forms-item>
|
||
</view>
|
||
</uni-forms>
|
||
|
||
<view class="btn-group">
|
||
<view class="btn-left">
|
||
<!-- 新增按钮:点击打开弹窗 -->
|
||
<button
|
||
class="iconfont icon-add mini-btn add-btn"
|
||
@click="openDialog('add')"
|
||
hover-class="is-hover"
|
||
type="default"
|
||
size="mini"
|
||
> 新增</button>
|
||
|
||
<!-- 删除按钮:未选中数据时禁用 -->
|
||
<button
|
||
class="iconfont icon-ashbin mini-btn del-btn"
|
||
hover-class="is-hover"
|
||
type="default"
|
||
size="mini"
|
||
:disabled="selectedIndexs.length === 0"
|
||
@click="batchDel"
|
||
> 删除</button>
|
||
<!-- 编辑按钮:未选中数据时禁用 -->
|
||
<button
|
||
class="iconfont icon-edit mini-btn edit-btn"
|
||
hover-class="is-hover"
|
||
type="default"
|
||
size="mini"
|
||
:disabled="selectedIndexs.length === 0"
|
||
@click="openDialog('edit')"
|
||
> 编辑</button>
|
||
</view>
|
||
|
||
<view class="btn-right">
|
||
<button
|
||
class="iconfont icon-search mini-btn"
|
||
hover-class="is-hover"
|
||
type="default"
|
||
size="mini"
|
||
@click="search"
|
||
> 查询</button>
|
||
</view>
|
||
</view>
|
||
</uni-section>
|
||
</view>
|
||
|
||
<view class="uni-container">
|
||
<!-- 表格区域:保持原有紧凑样式并优化 -->
|
||
<uni-table
|
||
ref="table"
|
||
:loading="loading"
|
||
border
|
||
stripe
|
||
type="selection"
|
||
emptyText="暂无更多数据"
|
||
@selection-change="selectionChange"
|
||
style="width: 100%;"
|
||
:border-width="1"
|
||
>
|
||
<uni-tr>
|
||
<uni-th align="center" class="ui-th" sortable width="200rpx" @sort-change="idSort">需求单号</uni-th>
|
||
<uni-th align="center" width="300rpx" class="ui-th">需求标题</uni-th>
|
||
<uni-th align="center" width="240rpx" class="ui-th">需求详情</uni-th>
|
||
<uni-th align="center" width="140rpx" @sort-change="prioritySort" sortable class="ui-th">优先级</uni-th>
|
||
<uni-th align="center" width="140rpx" class="ui-th">进度</uni-th>
|
||
<uni-th align="center" width="200rpx" class="ui-th">需求类型</uni-th>
|
||
<uni-th align="center" width="200rpx" class="ui-th">经办人名称</uni-th>
|
||
<uni-th align="center" width="300rpx" class="ui-th">操作</uni-th>
|
||
</uni-tr>
|
||
<uni-tr v-for="(item, index) in tableData" :key="index" style="height: 30px; line-height: 30px;">
|
||
|
||
<uni-td style="padding: 1px 0; font-size: 13px;">{{ item.id }}</uni-td>
|
||
<uni-td style="padding: 1px 0; font-size: 13px;">{{ item.title }}</uni-td>
|
||
<uni-td style="padding: 1px 0; font-size: 13px;">
|
||
<view class="name">{{ item.detail }}</view>
|
||
</uni-td>
|
||
<uni-td align="center" style=" padding: 1px 0; font-size: 13px;">{{ item.priority }}</uni-td>
|
||
<uni-td align="center" style=" padding: 1px 0; font-size: 13px;">{{ item.progress }}</uni-td>
|
||
<uni-td align="center" style=" padding: 1px 0; font-size: 13px;">{{ item.reqType }}</uni-td>
|
||
<uni-td align="center" style=" padding: 1px 0; font-size: 13px;">{{ item.assigneeName }}</uni-td>
|
||
<uni-td style="width: auto; padding: 1px 0; font-size: 13px;">
|
||
<view class="uni-group">
|
||
<!-- 行内修改按钮:点击打开编辑弹窗 -->
|
||
<button size="mini" type="primary" style="padding: 1px 6px; font-size: 10px;" @click="openDialog('edit', item)">修改</button>
|
||
<!-- 行内删除按钮:点击单行删除 -->
|
||
<button size="mini" type="warn" style="padding: 1px 6px; font-size: 10px;" @click="delSingle(item)">删除</button>
|
||
</view>
|
||
</uni-td>
|
||
</uni-tr>
|
||
</uni-table>
|
||
<view class="uni-pagination-box" style="margin-top: 8px;">
|
||
<uni-pagination
|
||
show-icon
|
||
:page-size="form.pageSize"
|
||
:current="form.pageNum"
|
||
:total="total"
|
||
@change="change"
|
||
style="font-size: 11px;"
|
||
/>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 新增/修改弹窗 -->
|
||
<uni-popup ref="formDialog" type="center" :mask-click="false">
|
||
<view class="dialog-container">
|
||
<view class="dialog-title">{{ dialogType === 'add' ? '新增需求' : '编辑需求' }}</view>
|
||
<!-- 弹窗表单 -->
|
||
<uni-forms
|
||
ref="dialogForm"
|
||
label-width="65px"
|
||
label-position="left"
|
||
:modelValue="dialogFormData"
|
||
:rules="formRules"
|
||
style="padding: 10rpx;"
|
||
>
|
||
<!-- 需求标题(必填) -->
|
||
<uni-forms-item label="需求标题:" name="title" required>
|
||
<uni-easyinput
|
||
v-model="dialogFormData.title"
|
||
placeholder="请输入需求标题"
|
||
style="font-size: 12px;"
|
||
/>
|
||
</uni-forms-item>
|
||
<!-- 详情(必填) -->
|
||
<uni-forms-item label="详情:" name="detail" required>
|
||
<uni-easyinput
|
||
v-model="dialogFormData.detail"
|
||
type="textarea"
|
||
placeholder="请输入需求详情"
|
||
style="font-size: 12px; height: 100px;"
|
||
/>
|
||
</uni-forms-item>
|
||
<!-- 优先级(下拉框,默认高) -->
|
||
<uni-forms-item label="优先级:" name="priority">
|
||
<uni-data-select
|
||
v-model="dialogFormData.priority"
|
||
:localdata="priorityList"
|
||
style="font-size: 12px;"
|
||
/>
|
||
</uni-forms-item>
|
||
<!-- 进度(下拉框) -->
|
||
<uni-forms-item label="进度:" name="progress">
|
||
<uni-data-select
|
||
v-model="dialogFormData.progress"
|
||
:localdata="progressList"
|
||
style="font-size: 12px;"
|
||
/>
|
||
</uni-forms-item>
|
||
<!-- 需求类型(下拉框) -->
|
||
<uni-forms-item label="需求类型:" name="reqType">
|
||
<uni-data-select
|
||
v-model="dialogFormData.reqType"
|
||
:localdata="reqTypeList"
|
||
style="font-size: 12px;"
|
||
/>
|
||
</uni-forms-item>
|
||
<!-- 经办人(可选输入框) -->
|
||
<uni-forms-item label="经办人:" name="assigneeName">
|
||
<uni-easyinput
|
||
v-model="dialogFormData.assigneeName"
|
||
placeholder="请输入经办人名称"
|
||
style="font-size: 12px;"
|
||
/>
|
||
</uni-forms-item>
|
||
</uni-forms>
|
||
<!-- 弹窗按钮 -->
|
||
<view class="dialog-btn-group">
|
||
<button class="cancel-btn" @click="closeDialog">取消</button>
|
||
<button class="confirm-btn" @click="submitDialog">确定</button>
|
||
</view>
|
||
</view>
|
||
</uni-popup>
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
import UniTh from "../../../uni_modules/uni-table/components/uni-th/uni-th.vue";
|
||
import UniTr from "../../../uni_modules/uni-table/components/uni-tr/uni-tr.vue";
|
||
import UniTd from "../../../uni_modules/uni-table/components/uni-td/uni-td.vue";
|
||
import {addRequire, delRequire, delRequires, listRequire, updateRequire} from "../../../api/system/require";
|
||
import UniTable from "../../../uni_modules/uni-table/components/uni-table/uni-table.vue";
|
||
import UniPopup from "../../../uni_modules/uni-popup/components/uni-popup/uni-popup.vue";
|
||
import UniForms from "../../../uni_modules/uni-forms/components/uni-forms/uni-forms.vue";
|
||
import UniFormsItem from "../../../uni_modules/uni-forms/components/uni-forms-item/uni-forms-item.vue";
|
||
import UniEasyinput from "../../../uni_modules/uni-easyinput/components/uni-easyinput/uni-easyinput.vue";
|
||
import UniDataSelect from "../../../uni_modules/uni-data-select/components/uni-data-select/uni-data-select.vue";
|
||
|
||
export default {
|
||
components: {
|
||
UniTable, UniTd, UniTr, UniTh,
|
||
UniPopup, UniForms, UniFormsItem, UniEasyinput, UniDataSelect
|
||
},
|
||
data() {
|
||
return {
|
||
searchVal: '',
|
||
tableData: [],
|
||
total: 0,
|
||
// 优先级下拉选项
|
||
priorityList: [
|
||
{ value: 0, text: '高' },
|
||
{ value: 1, text: '中' },
|
||
{ value: 2, text: '低' }
|
||
],
|
||
// 进度下拉选项
|
||
progressList: [
|
||
{ value: 0, text: '未完成' },
|
||
{ value: 1, text: '进行中' },
|
||
{ value: 2, text: '已完成' }
|
||
],
|
||
// 需求类型下拉选项(可根据实际需求补充)
|
||
reqTypeList: [
|
||
{ value: 0, text: '功能需求' },
|
||
{ value: 1, text: '优化需求' },
|
||
{ value: 2, text: 'BUG修复' }
|
||
],
|
||
form: {
|
||
title: null,
|
||
detail: null,
|
||
priority: null,
|
||
progress: null,
|
||
pageNum: 1,
|
||
pageSize: 10
|
||
},
|
||
loading: false,
|
||
selectIds:[],
|
||
selectedIndexs: [], // 已选择的行索引
|
||
// 弹窗相关
|
||
dialogType: 'add', // add-新增 edit-编辑
|
||
dialogFormData: {
|
||
title: '',
|
||
detail: '',
|
||
priority: 0, // 默认高
|
||
progress: 0,
|
||
reqType: '',
|
||
assigneeName: ''
|
||
},
|
||
// 表单校验规则
|
||
formRules: {
|
||
title: {
|
||
rules: [{ required: true, errorMessage: '请输入需求标题' }]
|
||
},
|
||
detail: {
|
||
rules: [{ required: true, errorMessage: '请输入需求详情' }]
|
||
}
|
||
},
|
||
currentEditItem: null // 当前编辑的行数据
|
||
}
|
||
},
|
||
onLoad() {
|
||
this.getData()
|
||
},
|
||
methods: {
|
||
// 多选处理
|
||
selectedItems() {
|
||
this.selectIds = this.selectedIndexs.map(i => this.tableData[i].id);
|
||
return this.selectedIndexs.map(i => this.tableData[i])
|
||
},
|
||
// 补充selection-change事件
|
||
selectionChange(e) {
|
||
this.selectedIndexs = e.detail.index
|
||
console.info(e)
|
||
},
|
||
idSort(e) {
|
||
if (e["order"] === 'descending') {
|
||
this.tableData.sort((a, b) => b.id - a.id);
|
||
return;
|
||
}
|
||
this.tableData.sort((a, b) => a.id - b.id);
|
||
},
|
||
prioritySort(e) {
|
||
if (e.order === 'descending') {
|
||
this.tableData.sort((a, b) => b.priority - a.priority);
|
||
return;
|
||
}
|
||
this.tableData.sort((a, b) => a.priority - b.priority);
|
||
},
|
||
// ========== 删除相关方法 ==========
|
||
// 批量删除
|
||
batchDel() {
|
||
const data = this.tableData.filter(item => !this.selectIds.includes(item.id));
|
||
console.info(`${this.selectIds}选中的数据:${JSON.stringify(data)} `)
|
||
// todo 多选删除 有bug 第二次删除之前第一次删除还在的索引还在
|
||
const selectedItems = this.selectedItems()
|
||
if (selectedItems.length === 0) {
|
||
uni.showToast({ title: '请选择要删除的数据', icon: 'none' })
|
||
return
|
||
}
|
||
const selectedIds = selectedItems.map(item => Number(item.id))
|
||
.filter(id => id !== undefined && id !== null && id !== '');
|
||
|
||
uni.showModal({
|
||
title: '提示',
|
||
content: `确定要删除选中的${selectedItems.length}条数据吗?`,
|
||
success: (res) => {
|
||
if (res.confirm) {
|
||
delRequires(selectedIds).then((response) => {
|
||
if (response.code === 200) {
|
||
uni.showToast({ title: '批量删除成功', icon: 'success' })
|
||
} else {
|
||
uni.showToast({ title: '批量删除失败', icon: 'error' })
|
||
}
|
||
this.getData()
|
||
this.selectedIndexs=[]
|
||
})
|
||
}
|
||
}
|
||
})
|
||
},
|
||
// 分页触发
|
||
change(e) {
|
||
this.selectedIndexs = []
|
||
this.getData(e.current)
|
||
},
|
||
// 搜索
|
||
search() {
|
||
this.getData()
|
||
},
|
||
// 获取数据
|
||
getData(pageNum) {
|
||
this.loading = true
|
||
this.form.pageNum = pageNum || this.form.pageNum
|
||
listRequire(this.form).then(response => {
|
||
if (response.code === 200 && response.rows) {
|
||
this.tableData = response.rows
|
||
this.total = response.total
|
||
}
|
||
this.loading = false
|
||
}).catch(error => {
|
||
console.error('获取数据失败:', error)
|
||
this.loading = false
|
||
})
|
||
},
|
||
|
||
|
||
// ========== 弹窗相关方法 ==========
|
||
// 打开弹窗
|
||
openDialog(type, item = null) {
|
||
this.dialogType = type
|
||
// 重置表单
|
||
this.dialogFormData = {
|
||
title: '',
|
||
detail: '',
|
||
priority: 0,
|
||
progress: 0,
|
||
reqType: '',
|
||
assigneeName: ''
|
||
}
|
||
// 编辑模式:回显数据
|
||
if (type === 'edit') {
|
||
// 批量编辑取第一个选中项,行内编辑取传入的item
|
||
const editItem = item || this.selectedItems()[0]
|
||
if (editItem) {
|
||
this.currentEditItem = editItem
|
||
this.dialogFormData = { ...editItem }
|
||
} else {
|
||
uni.showToast({ title: '请选择要编辑的数据', icon: 'none' })
|
||
return
|
||
}
|
||
}
|
||
// 打开弹窗
|
||
this.$refs.formDialog.open()
|
||
},
|
||
// 关闭弹窗
|
||
closeDialog() {
|
||
this.$refs.formDialog.close()
|
||
// 重置表单校验
|
||
this.$refs.dialogForm.clearValidate()
|
||
},
|
||
// 提交弹窗表单
|
||
submitDialog() {
|
||
// 表单校验
|
||
this.$refs.dialogForm.validate().then(() => {
|
||
if (this.dialogType === 'add') {
|
||
addRequire(this.dialogFormData).then(response => {
|
||
if (response.code===200) {
|
||
this.$modal.msgSuccess("新增成功")
|
||
} else {
|
||
this.$modal.msgError("新增失败")
|
||
}
|
||
this.getData()
|
||
})
|
||
} else {
|
||
updateRequire(this.dialogFormData).then(response => {
|
||
if (response.code===200) {
|
||
this.$modal.msgSuccess("修改成功")
|
||
} else {
|
||
this.$modal.msgError("修改失败")
|
||
}
|
||
this.getData()
|
||
})
|
||
}
|
||
// 关闭弹窗并刷新数据
|
||
this.closeDialog()
|
||
|
||
}).catch(err => {
|
||
console.error('表单校验失败:', err)
|
||
})
|
||
},
|
||
|
||
|
||
// 单行删除
|
||
delSingle(item) {
|
||
uni.showModal({
|
||
title: '提示',
|
||
content: '确定要删除这条数据吗?',
|
||
success: (res) => {
|
||
if (res.confirm) {
|
||
delRequire(item.id).then(response => {
|
||
if (response.code === 200) {
|
||
uni.showToast({title: '删除成功', icon: 'success'})
|
||
} else {
|
||
uni.showToast({title: '删除失败', icon: 'success'})
|
||
}
|
||
})
|
||
this.getData()
|
||
this.selectedIndexs=[]
|
||
}
|
||
}
|
||
})
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style scoped>
|
||
/* 页面基础样式重置 */
|
||
page {
|
||
padding-top: 0 !important;
|
||
font-size: 12px;
|
||
}
|
||
|
||
/* 整体容器样式 */
|
||
.container {
|
||
margin: 20rpx;
|
||
border-radius: 20rpx;
|
||
background: #fff;
|
||
font-size: 12px;
|
||
}
|
||
|
||
.form-container {
|
||
margin: 20rpx 0 0 0;
|
||
padding: 15rpx;
|
||
border-radius: 20rpx;
|
||
background: #fff;
|
||
}
|
||
|
||
/* 表单一行两列布局核心样式 - 优化版 */
|
||
.form-row {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
justify-content: space-between;
|
||
margin: 0 10rpx 10rpx 10rpx;
|
||
width: 100%;
|
||
/* 新增:清除flex布局默认的基线对齐,避免垂直错位 */
|
||
align-items: flex-start;
|
||
/* 新增:计算宽度时包含内边距/边框,避免溢出 */
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
.form-item {
|
||
display: flex;
|
||
align-items: center;
|
||
width: 48%; /* 保留你的48%宽度,留2%间距 */
|
||
box-sizing: border-box;
|
||
margin: 0 !important; /* 保留清除默认间距 */
|
||
/* 新增适配uni-forms-item的关键样式 */
|
||
padding: 0; /* 清除组件默认内边距 */
|
||
min-height: auto; /* 取消组件默认最小高度,避免高度不一致 */
|
||
}
|
||
|
||
/* 新增:适配uni-data-select组件,防止下拉框溢出 */
|
||
.form-item .uni-data-select {
|
||
width: 100%; /* 下拉选择器占满form-item宽度 */
|
||
flex: 1; /* 让选择器自适应剩余空间 */
|
||
}
|
||
|
||
/* 新增:统一label标签样式,避免文字错位 */
|
||
.form-item .uni-forms-item__label {
|
||
/* 根据你的需求调整label宽度,比如固定120rpx */
|
||
flex: 0 0 120rpx;
|
||
padding: 0; /* 清除默认内边距 */
|
||
margin-right: 10rpx; /* label和选择器之间留间距 */
|
||
}
|
||
|
||
/* 新增:统一表单项内容区域样式 */
|
||
.form-item .uni-forms-item__content {
|
||
flex: 1; /* 内容区域占满剩余宽度 */
|
||
padding: 0; /* 清除默认内边距 */
|
||
}
|
||
/* 核心:父容器flex布局,通过justify-content: space-between实现左右分布 */
|
||
.btn-group {
|
||
display: flex;
|
||
justify-content: space-between; /* 关键:左右元素分别靠两端 */
|
||
align-items: center; /* 垂直居中,保证按钮对齐 */
|
||
width: 100%; /* 占满父容器宽度,确保分布效果 */
|
||
padding: 20rpx 10rpx 0; /* 左右留间距,避免贴边 */
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
/* 左侧按钮容器:横向排列,靠左 */
|
||
.btn-left {
|
||
display: flex;
|
||
align-items: center;
|
||
}
|
||
|
||
/* 右侧按钮容器:横向排列,靠右 */
|
||
.btn-right {
|
||
display: flex;
|
||
align-items: center;
|
||
}
|
||
|
||
/* 表格容器样式 */
|
||
.uni-container {
|
||
padding: 10px;
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
.uni-group {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
}
|
||
|
||
/* 需求详情文字样式 */
|
||
.name {
|
||
line-height: 18px;
|
||
font-size: 11px;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
white-space: nowrap;
|
||
}
|
||
|
||
/* 分页区域样式 */
|
||
.uni-pagination-box {
|
||
text-align: center;
|
||
}
|
||
|
||
/deep/ .uni-forms-item__label {
|
||
font-size: 12px !important;
|
||
padding: 0 !important;
|
||
}
|
||
/deep/ .uni-select, /deep/.uni-easyinput__content-input {
|
||
font-size: 12px !important;
|
||
height: 30px;
|
||
}
|
||
|
||
/* 弹窗样式 */
|
||
.dialog-container {
|
||
background: #fff;
|
||
border-radius: 10rpx;
|
||
padding: 20rpx;
|
||
width: 600rpx;
|
||
}
|
||
|
||
.dialog-title {
|
||
font-size: 16px;
|
||
font-weight: bold;
|
||
text-align: center;
|
||
padding: 10rpx 0;
|
||
border-bottom: 1px solid #eee;
|
||
margin-bottom: 10rpx;
|
||
}
|
||
|
||
.dialog-btn-group {
|
||
display: flex;
|
||
justify-content: flex-end;
|
||
margin-top: 20rpx;
|
||
gap: 10rpx;
|
||
}
|
||
|
||
/* 禁用按钮样式 */
|
||
/deep/ button[disabled] {
|
||
background-color: #e5e5e5 !important;
|
||
color: #999 !important;
|
||
border-color: #ddd !important;
|
||
}
|
||
/deep/ .uni-forms-item {
|
||
margin-bottom: 12rpx;
|
||
}
|
||
|
||
/deep/ .uni-table-td {
|
||
text-align: center !important;
|
||
}
|
||
.ui-th {
|
||
width: auto;
|
||
height: 18px;
|
||
line-height: 18px;
|
||
font-size: 13px;
|
||
}
|
||
.ui-th:last-child {
|
||
width: 160rpx;
|
||
}
|
||
/deep/ .uni-table-th {
|
||
padding: 16rpx 5rpx;
|
||
}
|
||
.uni-group button:last-child {
|
||
margin-left: 0;
|
||
}
|
||
</style> |