fix:修复了一点点问题,目前点击用户详情的话已有的角色会显示了,然后修复了角色启用和禁用的状态表示做反了,合同中新增了合同类别

This commit is contained in:
Maple 2025-08-15 10:07:36 +08:00
parent 66d4a1bbfe
commit c5c7aeaa61
8 changed files with 172 additions and 26 deletions

View File

@ -18,6 +18,10 @@
<a-descriptions-item label="合同金额">
<span class="font-medium text-green-600">{{ (contractDetail.amount || 0).toLocaleString() }}</span>
</a-descriptions-item>
<a-descriptions-item label="合同类别">
{{ contractDetail.category || '-' }}
</a-descriptions-item>
<a-descriptions-item label="已收款金额">
<span class="font-medium text-blue-600">{{ (contractDetail.receivedAmount || 0).toLocaleString() }}</span>
</a-descriptions-item>
@ -74,6 +78,7 @@ interface ContractDetail {
code: string
projectId: string
type: string
category?: string
productService: string
paymentDate: string | null
performanceDeadline: string | null

View File

@ -46,6 +46,21 @@
</a-col>
</a-row>
<a-row :gutter="16">
<a-col :span="12">
<a-form-item field="category" label="合同类别">
<a-select v-model="contractData.category" placeholder="请选择合同类别" allow-clear>
<a-option value="框架协议">框架协议</a-option>
<a-option value="单次合同">单次合同</a-option>
<a-option value="三年长协">三年长协</a-option>
<a-option value="两年长协">两年长协</a-option>
<a-option value="派工单">派工单</a-option>
</a-select>
</a-form-item>
</a-col>
</a-row>
<a-row :gutter="16">
<a-col :span="12">
<a-form-item field="signDate" label="签订日期">

View File

@ -135,6 +135,7 @@ interface ContractItem {
code: string
projectId: string
type: string
category?: string
productService: string
paymentDate: string | null
performanceDeadline: string | null
@ -165,6 +166,7 @@ const searchForm = reactive({
contractCode: '',
client: '',
status: '',
category: '',
signDateRange: [] as [string, string] | [],
page: 1,
size: 10,
@ -196,6 +198,21 @@ const queryFormColumns = [
],
},
},
{
field: 'category',
label: '合同类别',
type: 'select' as const,
props: {
placeholder: '请选择合同类别',
options: [
{ label: '框架协议', value: '框架协议' },
{ label: '单次合同', value: '单次合同' },
{ label: '三年长协', value: '三年长协' },
{ label: '两年长协', value: '两年长协' },
{ label: '派工单', value: '派工单' }
]
}
},
{
field: 'signDateRange',
label: '签署时间',
@ -218,6 +235,7 @@ const tableColumns: TableColumnData[] = [
{ title: '签署日期', dataIndex: 'signDate', slotName: 'signDate', width: 120 },
{ title: '履约期限', dataIndex: 'performanceDeadline', slotName: 'performanceDeadline', width: 120 },
{ title: '付款日期', dataIndex: 'paymentDate', slotName: 'paymentDate', width: 120 },
{ title: '合同类别', dataIndex: 'category', width: 120 },
{ title: '合同状态', dataIndex: 'contractStatus', slotName: 'status', width: 100 },
{ title: '销售人员', dataIndex: 'salespersonName', width: 100 },
{ title: '销售部门', dataIndex: 'salespersonDeptName', width: 100 },
@ -239,6 +257,7 @@ const fetchContractList = async () => {
code: searchForm.contractCode,
customer: searchForm.client,
contractStatus: searchForm.status,
category: (searchForm as any).category || undefined,
signDateStart: Array.isArray(searchForm.signDateRange) && searchForm.signDateRange.length === 2 ? searchForm.signDateRange[0] : undefined,
signDateEnd: Array.isArray(searchForm.signDateRange) && searchForm.signDateRange.length === 2 ? searchForm.signDateRange[1] : undefined,
}
@ -325,6 +344,8 @@ const reset = () => {
status: '',
signDateRange: [],
page: 1,
category: '',
size: 10,
})
pagination.current = 1
@ -354,6 +375,7 @@ const newContractData = ref<ContractItem>({
code: '',
projectId: '',
type: '支出合同',
category: '',
productService: '',
paymentDate: null,
performanceDeadline: null,
@ -387,6 +409,7 @@ const openAddModal = () => {
code: '',
projectId: '',
type: '支出合同',
category: '',
productService: '',
paymentDate: null,
performanceDeadline: null,
@ -444,6 +467,7 @@ const handleAddSubmit = async () => {
salespersonId: (newContractData.value as any).salespersonId || '',
signDate: newContractData.value.signDate || null,
type: newContractData.value.type || '支出合同',
category: newContractData.value.category || '',
}
// ID
@ -535,6 +559,7 @@ const handleEditSubmit = async () => {
productService: editedContractData.value.productService || '',
projectId: editedContractData.value.projectId || '',
salespersonId: editedContractData.value.salespersonId || '',
category: editedContractData.value.category || '',
signDate: editedContractData.value.signDate || null,
type: editedContractData.value.type || '',
};

View File

@ -18,6 +18,10 @@
<a-descriptions-item label="合同金额">
<span class="font-medium text-green-600">{{ (contractDetail.amount || 0).toLocaleString() }}</span>
</a-descriptions-item>
<a-descriptions-item label="合同类别">
{{ contractDetail.category || '-' }}
</a-descriptions-item>
<a-descriptions-item label="已收款金额">
<span class="font-medium text-blue-600">{{ (contractDetail.receivedAmount || 0).toLocaleString() }}</span>
</a-descriptions-item>
@ -74,6 +78,7 @@ interface ContractDetail {
code: string
projectId: string
type: string
category?: string
productService: string
paymentDate: string | null
performanceDeadline: string | null

View File

@ -46,6 +46,20 @@
</a-col>
</a-row>
<a-row :gutter="16">
<a-col :span="12">
<a-form-item field="category" label="合同类别">
<a-select v-model="contractData.category" placeholder="请选择合同类别" allow-clear>
<a-option value="框架协议">框架协议</a-option>
<a-option value="单次合同">单次合同</a-option>
<a-option value="三年长协">三年长协</a-option>
<a-option value="两年长协">两年长协</a-option>
<a-option value="派工单">派工单</a-option>
</a-select>
</a-form-item>
</a-col>
</a-row>
<a-row :gutter="16">
<a-col :span="12">
<a-form-item field="signDate" label="签订日期">

View File

@ -136,6 +136,7 @@ interface ContractItem {
code: string
projectId: string
type: string
category?: string
productService: string
paymentDate: string | null
performanceDeadline: string | null
@ -166,6 +167,7 @@ const searchForm = reactive({
contractCode: '',
client: '',
status: '',
category: '',
signDateRange: [] as [string, string] | [],
page: 1,
size: 10,
@ -186,6 +188,17 @@ const queryFormColumns = [
],
},
},
{ field: 'category', label: '合同类别', type: 'select' as const, props: {
placeholder: '请选择合同类别',
options: [
{ label: '框架协议', value: '框架协议' },
{ label: '单次合同', value: '单次合同' },
{ label: '三年长协', value: '三年长协' },
{ label: '两年长协', value: '两年长协' },
{ label: '派工单', value: '派工单' },
],
}
},
{ field: 'signDateRange', label: '签署时间', type: 'range-picker' as const, props: {
placeholder: ['开始日期', '结束日期'], format: 'YYYY-MM-DD',
}
@ -198,6 +211,7 @@ const tableColumns: TableColumnData[] = [
{ title: '项目名称', dataIndex: 'projectName', width: 250, ellipsis: true, tooltip: true },
{ title: '客户名称', dataIndex: 'customer', width: 200, ellipsis: true, tooltip: true },
{ title: '合同金额', dataIndex: 'amount', slotName: 'contractAmount', width: 120 },
{ title: '合同类别', dataIndex: 'category', width: 120 },
{ title: '已收款金额', dataIndex: 'receivedAmount', slotName: 'receivedAmount', width: 120 },
{ title: '未收款金额', dataIndex: 'pendingAmount', width: 120 },
{ title: '签署日期', dataIndex: 'signDate', slotName: 'signDate', width: 120 },
@ -312,6 +326,9 @@ const fetchContractList = async () => {
pageSize: searchForm.size,
code: searchForm.contractCode,
customer: searchForm.client,
category: (searchForm as any).category || undefined,
contractStatus: searchForm.status,
signDateStart: Array.isArray(searchForm.signDateRange) && searchForm.signDateRange.length === 2 ? searchForm.signDateRange[0] : undefined,
signDateEnd: Array.isArray(searchForm.signDateRange) && searchForm.signDateRange.length === 2 ? searchForm.signDateRange[1] : undefined,
@ -393,6 +410,7 @@ const reset = () => {
contractCode: '',
client: '',
status: '',
category: '',
signDateRange: [],
page: 1,
size: 10,
@ -421,6 +439,7 @@ const showAddModal = ref(false)
const newContractData = ref<ContractItem>({
contractId: '', customer: '', code: '', projectId: '', type: '收入合同',
productService: '', paymentDate: null, performanceDeadline: null,
category: '',
paymentAddress: '', amount: 0, accountNumber: '', notes: '',
contractStatus: '未执行', contractText: '', projectName: '',
salespersonName: null, salespersonDeptName: '', settlementAmount: null,
@ -432,6 +451,7 @@ const openAddModal = () => {
Object.assign(newContractData.value, {
contractId: '', customer: '', code: '', projectId: '', type: '收入合同',
productService: '', paymentDate: null, performanceDeadline: null,
category: '',
paymentAddress: '', amount: 0, accountNumber: '', notes: '',
contractStatus: '未执行', contractText: '', projectName: '',
salespersonName: null, salespersonDeptName: '', settlementAmount: null,
@ -464,6 +484,7 @@ const handleAddSubmit = async () => {
// projectId
projectName: newContractData.value.projectName || '',
salespersonId: (newContractData.value as any).salespersonId || '',
category: newContractData.value.category || '',
signDate: newContractData.value.signDate || null,
type: newContractData.value.type || '收入合同',
}
@ -534,6 +555,7 @@ const handleEditSubmit = async () => {
productService: editedContractData.value.productService || '',
projectId: editedContractData.value.projectId || '',
salespersonId: editedContractData.value.salespersonId || '',
category: editedContractData.value.category || '',
signDate: editedContractData.value.signDate || null,
type: editedContractData.value.type || '',
};

View File

@ -22,8 +22,8 @@
</a-form-item>
<a-form-item label="状态" field="status">
<a-select v-model="form.status" placeholder="请选择状态">
<a-option :value="0" label="正常" />
<a-option :value="1" label="停用" />
<a-option :value="1" label="正常" />
<a-option :value="0" label="停用" />
</a-select>
</a-form-item>
<a-form-item label="描述" field="remark">

View File

@ -15,6 +15,7 @@
<script setup lang="ts">
import { Message, type TreeNodeData } from '@arco-design/web-vue'
import { useWindowSize } from '@vueuse/core'
import { nextTick } from 'vue'
import { addUserNew, getUserDetailNew, updateUserNew } from '@/apis/system/user-new'
import { type ColumnItem, GiForm } from '@/components/GiForm'
import type { Status } from '@/types/global'
@ -186,7 +187,7 @@ const columns: ColumnItem[] = reactive([
field: 'roleIds',
type: 'select',
span: 12,
required: true,
//required: true,
props: {
options: roleList,
multiple: true,
@ -347,15 +348,12 @@ const save = async () => {
//
const onAdd = async () => {
reset()
if (!deptList.value.length) {
await getDeptList()
}
if (!roleList.value.length) {
await getRoleList()
}
if (!postList.value.length) {
await getPostList()
}
// v-model
await Promise.all([
deptList.value.length ? Promise.resolve() : getDeptList(),
roleList.value.length ? Promise.resolve() : getRoleList(),
postList.value.length ? Promise.resolve() : getPostList(),
])
dataId.value = ''
visible.value = true
}
@ -365,15 +363,12 @@ const onUpdate = async (id: string) => {
try {
reset()
dataId.value = id
if (!deptList.value.length) {
await getDeptList()
}
if (!roleList.value.length) {
await getRoleList()
}
if (!postList.value.length) {
await getPostList()
}
// //
await Promise.all([
deptList.value.length ? Promise.resolve() : getDeptList(),
roleList.value.length ? Promise.resolve() : getRoleList(),
postList.value.length ? Promise.resolve() : getPostList(),
])
// 使API
const { data } = await getUserDetailNew(id)
@ -381,13 +376,78 @@ const onUpdate = async (id: string) => {
return Message.error('获取用户详情失败')
}
// API
// API
Object.keys(form).forEach(key => {
if (data[key] !== undefined) {
form[key] = data[key]
if ((data as any)[key] !== undefined) {
;(form as any)[key] = (data as any)[key]
}
})
// / ID
const normalizeIdArray = (val: any): string[] => {
if (Array.isArray(val)) return val.map(v => String(v))
if (typeof val === 'string') return val.split(',').map(s => s.trim()).filter(Boolean)
return []
}
//
form.deptId = data.deptId ? String(data.deptId) : ''
//
if ((data as any).postIds !== undefined) {
form.postIds = normalizeIdArray((data as any).postIds)
}
// roleIds / roles / roleIdList
const roleIdsFromArray = normalizeIdArray((data as any).roleIds)
const roleIdsFromRoles = Array.isArray((data as any).roles)
? (data as any).roles.map((r: any) => String(r.roleId ?? r.id ?? r.role_id)).filter(Boolean)
: []
const roleIdsFromList = normalizeIdArray((data as any).roleIdList)
let mergedRoleIds = roleIdsFromArray.length
? roleIdsFromArray
: (roleIdsFromRoles.length ? roleIdsFromRoles : roleIdsFromList)
// IDID
if (!mergedRoleIds.length) {
const namesStr = (data as any).roleName || (data as any).roleNames
const roleNames: string[] = Array.isArray(namesStr)
? (namesStr as any[]).map(n => String(n))
: (typeof namesStr === 'string' ? namesStr.split(/,|/).map(s => s.trim()).filter(Boolean) : [])
if (roleNames.length && Array.isArray(roleList.value)) {
const labelToId = new Map<string, string>((roleList.value || []).map(opt => [String(opt.label), String(opt.value)]))
const ids = roleNames.map(n => labelToId.get(n)).filter((v): v is string => !!v)
if (ids.length) mergedRoleIds = ids
}
}
form.roleIds = mergedRoleIds
//
try {
const optionValSet = new Set((roleList.value || []).map(o => String(o.value)))
const fromRolesMap = new Map<string, string>()
if (Array.isArray((data as any).roles)) {
;(data as any).roles.forEach((r: any) => {
const id = String(r.roleId ?? r.id ?? r.role_id)
const name = r.roleName ?? r.name ?? r.role_key ?? id
if (id) fromRolesMap.set(id, String(name))
})
}
const toAppend: any[] = []
mergedRoleIds.forEach(id => {
const sId = String(id)
if (!optionValSet.has(sId)) {
toAppend.push({ label: fromRolesMap.get(sId) || sId, value: sId, disabled: false })
}
})
if (toAppend.length) {
//
roleList.value = [...(roleList.value || []), ...toAppend]
}
} catch (_) {}
visible.value = true
} catch (error) {
console.error('获取用户详情失败', error)