Add custom request management
This commit is contained in:
24
ruoyi-ui/src/api/app/customRequest.js
Normal file
24
ruoyi-ui/src/api/app/customRequest.js
Normal file
@@ -0,0 +1,24 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
export function listCustomRequest(query) {
|
||||
return request({
|
||||
url: '/app/customRequest/list',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
export function getCustomRequest(id) {
|
||||
return request({
|
||||
url: '/app/customRequest/' + id,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
export function updateCustomRequestStatus(data) {
|
||||
return request({
|
||||
url: '/app/customRequest/status',
|
||||
method: 'put',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
262
ruoyi-ui/src/views/app/customRequest/index.vue
Normal file
262
ruoyi-ui/src/views/app/customRequest/index.vue
Normal file
@@ -0,0 +1,262 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<el-form v-show="showSearch" ref="queryForm" :model="queryParams" size="small" :inline="true" label-width="82px">
|
||||
<el-form-item label="需求单号" prop="requestNo">
|
||||
<el-input v-model="queryParams.requestNo" placeholder="请输入需求单号" clearable @keyup.enter.native="handleQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item label="项目名称" prop="projectName">
|
||||
<el-input v-model="queryParams.projectName" placeholder="请输入项目名称" clearable @keyup.enter.native="handleQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item label="技术栈" prop="techStackName">
|
||||
<el-input v-model="queryParams.techStackName" placeholder="请输入技术栈" clearable @keyup.enter.native="handleQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item label="用户" prop="userName">
|
||||
<el-input v-model="queryParams.userName" placeholder="账号或昵称" clearable @keyup.enter.native="handleQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item label="需求状态" prop="status">
|
||||
<el-select v-model="queryParams.status" placeholder="全部状态" clearable>
|
||||
<el-option v-for="item in statusOptions" :key="item.value" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="积分状态" prop="pointStatus">
|
||||
<el-select v-model="queryParams.pointStatus" placeholder="全部状态" clearable>
|
||||
<el-option label="已扣除" :value="0" />
|
||||
<el-option label="已退回" :value="1" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="提交时间">
|
||||
<el-date-picker
|
||||
v-model="dateRange"
|
||||
style="width: 240px"
|
||||
value-format="yyyy-MM-dd"
|
||||
type="daterange"
|
||||
range-separator="-"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<right-toolbar :show-search.sync="showSearch" @queryTable="getList" />
|
||||
</el-row>
|
||||
|
||||
<el-table v-loading="loading" :data="requestList">
|
||||
<el-table-column label="需求单号" prop="requestNo" min-width="205" show-overflow-tooltip />
|
||||
<el-table-column label="用户" min-width="150">
|
||||
<template slot-scope="scope">
|
||||
<div>{{ scope.row.nickName || scope.row.userName || '-' }}</div>
|
||||
<div class="secondary-text">{{ scope.row.userName || '-' }} / ID: {{ scope.row.userId }}</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="项目名称" prop="projectName" min-width="180" show-overflow-tooltip />
|
||||
<el-table-column label="技术栈" prop="techStackName" min-width="185" show-overflow-tooltip>
|
||||
<template slot-scope="scope">{{ scope.row.techStackName || '-' }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="项目需求" prop="requirementContent" min-width="250" show-overflow-tooltip />
|
||||
<el-table-column label="状态" align="center" width="120">
|
||||
<template slot-scope="scope">
|
||||
<el-tag :type="statusType(scope.row.status)" size="small">{{ statusLabel(scope.row.status) }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="积分" align="center" width="105">
|
||||
<template slot-scope="scope">
|
||||
<span :class="scope.row.pointStatus === 1 ? 'point-refunded' : ''">
|
||||
{{ scope.row.pointAmount }} / {{ scope.row.pointStatus === 1 ? '已退' : '已扣' }}
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="当前进度" prop="progressNote" min-width="210" show-overflow-tooltip />
|
||||
<el-table-column label="更新时间" prop="updateTime" width="165" />
|
||||
<el-table-column label="操作" align="center" width="145" fixed="right">
|
||||
<template slot-scope="scope">
|
||||
<el-button v-hasPermi="['app:customRequest:query']" type="text" icon="el-icon-view" size="mini" @click="handleView(scope.row)">详情</el-button>
|
||||
<el-button v-if="scope.row.status !== 5" v-hasPermi="['app:customRequest:edit']" type="text" icon="el-icon-edit" size="mini" @click="handleUpdate(scope.row)">更新</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<pagination
|
||||
v-show="total > 0"
|
||||
:total="total"
|
||||
:page.sync="queryParams.pageNum"
|
||||
:limit.sync="queryParams.pageSize"
|
||||
@pagination="getList"
|
||||
/>
|
||||
|
||||
<el-dialog title="定制需求详情" :visible.sync="detailOpen" width="760px" append-to-body>
|
||||
<el-descriptions v-if="detail.id" :column="2" border>
|
||||
<el-descriptions-item label="需求单号" :span="2">{{ detail.requestNo }}</el-descriptions-item>
|
||||
<el-descriptions-item label="用户昵称">{{ detail.nickName || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="用户账号">{{ detail.userName || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="项目名称" :span="2">{{ detail.projectName }}</el-descriptions-item>
|
||||
<el-descriptions-item label="技术栈" :span="2">{{ detail.techStackName || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="项目需求" :span="2">
|
||||
<div class="requirement-detail">{{ detail.requirementContent }}</div>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="当前状态">
|
||||
<el-tag :type="statusType(detail.status)" size="small">{{ statusLabel(detail.status) }}</el-tag>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="积分状态">{{ detail.pointAmount }}积分 / {{ detail.pointStatus === 1 ? '已退回' : '已扣除' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="当前进度" :span="2">{{ detail.progressNote || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item v-if="detail.rejectReason" label="未通过原因" :span="2">{{ detail.rejectReason }}</el-descriptions-item>
|
||||
<el-descriptions-item label="提交时间">{{ detail.createTime || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="更新时间">{{ detail.updateTime || '-' }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
<div slot="footer" class="dialog-footer"><el-button @click="detailOpen = false">关闭</el-button></div>
|
||||
</el-dialog>
|
||||
|
||||
<el-dialog title="更新需求状态" :visible.sync="updateOpen" width="560px" append-to-body>
|
||||
<el-form ref="updateForm" :model="form" :rules="rules" label-width="100px">
|
||||
<el-form-item label="项目名称"><span>{{ form.projectName }}</span></el-form-item>
|
||||
<el-form-item label="技术栈"><span>{{ form.techStackName || '-' }}</span></el-form-item>
|
||||
<el-form-item label="新状态" prop="status">
|
||||
<el-select v-model="form.status" placeholder="请选择状态" style="width: 100%" @change="handleStatusChange">
|
||||
<el-option v-for="item in statusOptions" :key="item.value" :label="item.label" :value="item.value" :disabled="form.pointStatus === 1 && item.value !== 5" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="form.status !== 5" label="进度说明" prop="progressNote">
|
||||
<el-input v-model="form.progressNote" type="textarea" :rows="4" maxlength="300" show-word-limit placeholder="这段内容会展示给用户" />
|
||||
</el-form-item>
|
||||
<el-form-item v-if="form.status === 5" label="未通过原因" prop="rejectReason">
|
||||
<el-input v-model="form.rejectReason" type="textarea" :rows="3" maxlength="300" show-word-limit placeholder="必填,保存后自动退回99积分" />
|
||||
</el-form-item>
|
||||
<el-alert v-if="form.status === 5 && form.pointStatus === 0" title="保存后将自动退回99积分,此操作不能撤销。" type="warning" :closable="false" show-icon />
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button @click="updateOpen = false">取消</el-button>
|
||||
<el-button type="primary" :loading="submitting" @click="submitUpdate">确定</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getCustomRequest, listCustomRequest, updateCustomRequestStatus } from '@/api/app/customRequest'
|
||||
|
||||
export default {
|
||||
name: 'CustomRequest',
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
submitting: false,
|
||||
showSearch: true,
|
||||
total: 0,
|
||||
requestList: [],
|
||||
dateRange: [],
|
||||
detailOpen: false,
|
||||
updateOpen: false,
|
||||
detail: {},
|
||||
form: {},
|
||||
statusOptions: [
|
||||
{ value: 0, label: '待审核' },
|
||||
{ value: 1, label: '审核中' },
|
||||
{ value: 2, label: '已接单' },
|
||||
{ value: 3, label: '开发中' },
|
||||
{ value: 4, label: '已完成' },
|
||||
{ value: 5, label: '审核未通过' }
|
||||
],
|
||||
statusProgressDefaults: {
|
||||
0: '需求已提交,等待平台审核',
|
||||
1: '平台正在审核您的项目需求',
|
||||
2: '项目需求已通过审核,平台已接单',
|
||||
3: '项目正在开发中,请耐心等待',
|
||||
4: '项目已开发完成,请联系南音查看演示成果',
|
||||
5: '需求审核未通过,99积分已退回'
|
||||
},
|
||||
queryParams: {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
requestNo: undefined,
|
||||
projectName: undefined,
|
||||
techStackName: undefined,
|
||||
userName: undefined,
|
||||
status: undefined,
|
||||
pointStatus: undefined
|
||||
},
|
||||
rules: {
|
||||
status: [{ required: true, message: '请选择状态', trigger: 'change' }],
|
||||
progressNote: [{ required: true, message: '请填写进度说明', trigger: 'blur' }],
|
||||
rejectReason: [{ required: true, message: '请填写审核未通过原因', trigger: 'blur' }]
|
||||
}
|
||||
}
|
||||
},
|
||||
created() { this.getList() },
|
||||
methods: {
|
||||
getList() {
|
||||
this.loading = true
|
||||
listCustomRequest(this.addDateRange(this.queryParams, this.dateRange)).then(response => {
|
||||
this.requestList = response.rows || []
|
||||
this.total = response.total || 0
|
||||
}).finally(() => { this.loading = false })
|
||||
},
|
||||
handleQuery() { this.queryParams.pageNum = 1; this.getList() },
|
||||
resetQuery() { this.dateRange = []; this.resetForm('queryForm'); this.handleQuery() },
|
||||
handleView(row) {
|
||||
getCustomRequest(row.id).then(response => { this.detail = response.data; this.detailOpen = true })
|
||||
},
|
||||
handleUpdate(row) {
|
||||
getCustomRequest(row.id).then(response => {
|
||||
const data = response.data
|
||||
this.form = {
|
||||
id: data.id,
|
||||
projectName: data.projectName,
|
||||
techStackName: data.techStackName,
|
||||
status: data.status,
|
||||
pointStatus: data.pointStatus,
|
||||
progressNote: data.progressNote || '',
|
||||
rejectReason: data.rejectReason || ''
|
||||
}
|
||||
this.updateOpen = true
|
||||
this.$nextTick(() => { if (this.$refs.updateForm) this.$refs.updateForm.clearValidate() })
|
||||
})
|
||||
},
|
||||
handleStatusChange(status) {
|
||||
this.form.progressNote = this.statusProgressDefaults[status] || ''
|
||||
if (status !== 5) this.form.rejectReason = ''
|
||||
this.$nextTick(() => {
|
||||
if (this.$refs.updateForm) this.$refs.updateForm.clearValidate(['progressNote', 'rejectReason'])
|
||||
})
|
||||
},
|
||||
submitUpdate() {
|
||||
this.$refs.updateForm.validate(valid => {
|
||||
if (!valid) return
|
||||
const doUpdate = () => {
|
||||
this.submitting = true
|
||||
const updateData = Object.assign({}, this.form, {
|
||||
progressNote: String(this.form.progressNote || '').trim(),
|
||||
rejectReason: this.form.status === 5 ? String(this.form.rejectReason || '').trim() : ''
|
||||
})
|
||||
updateCustomRequestStatus(updateData).then(() => {
|
||||
this.$modal.msgSuccess(this.form.status === 5 && this.form.pointStatus === 0 ? '已拒绝并退回99积分' : '状态更新成功')
|
||||
this.updateOpen = false
|
||||
this.getList()
|
||||
}).finally(() => { this.submitting = false })
|
||||
}
|
||||
if (this.form.status === 5 && this.form.pointStatus === 0) {
|
||||
this.$modal.confirm('确认审核不通过并退回99积分吗?退款后不能恢复为其他状态。').then(doUpdate).catch(() => {})
|
||||
} else {
|
||||
doUpdate()
|
||||
}
|
||||
})
|
||||
},
|
||||
statusLabel(status) {
|
||||
const item = this.statusOptions.find(option => option.value === status)
|
||||
return item ? item.label : '未知状态'
|
||||
},
|
||||
statusType(status) {
|
||||
return { 0: 'info', 1: 'warning', 2: 'success', 3: 'primary', 4: 'success', 5: 'danger' }[status] || 'info'
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.secondary-text { margin-top: 2px; color: #909399; font-size: 12px; }
|
||||
.point-refunded { color: #2b9660; }
|
||||
.requirement-detail { white-space: pre-wrap; line-height: 1.7; }
|
||||
</style>
|
||||
Reference in New Issue
Block a user