From 065f7052c66c5382b6d756c7dd1c2b3401fa75a8 Mon Sep 17 00:00:00 2001 From: wzk <2438381872@qq.com> Date: Thu, 27 Nov 2025 09:24:26 +0800 Subject: [PATCH] =?UTF-8?q?=E6=A3=80=E6=9F=A5=E9=A1=B9=E7=9B=AE=E8=AE=BE?= =?UTF-8?q?=E7=BD=AE->=E5=A5=97=E9=A4=90=E8=AE=BE=E7=BD=AE->=E5=A5=97?= =?UTF-8?q?=E9=A4=90=E7=AE=A1=E7=90=86=E8=A1=A5=E5=85=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../check/controller/CheckTypeController.java | 2 +- .../components/PackageManagement.vue | 133 +++---- .../components/PackageSettings.vue | 357 ++++++++++-------- .../checkprojectSettings/index.vue | 30 +- 4 files changed, 270 insertions(+), 252 deletions(-) diff --git a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/check/controller/CheckTypeController.java b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/check/controller/CheckTypeController.java index 0a8006f8..24f17067 100644 --- a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/check/controller/CheckTypeController.java +++ b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/check/controller/CheckTypeController.java @@ -124,7 +124,7 @@ public class CheckTypeController extends BaseController { return AjaxResult.success(result); } else { List list = checkPackageService.list(wrapper); - return AjaxResult.success(list); + return AjaxResult.success(list); } } diff --git a/openhis-ui-vue3/src/views/maintainSystem/checkprojectSettings/components/PackageManagement.vue b/openhis-ui-vue3/src/views/maintainSystem/checkprojectSettings/components/PackageManagement.vue index c7012137..dc3a2b62 100644 --- a/openhis-ui-vue3/src/views/maintainSystem/checkprojectSettings/components/PackageManagement.vue +++ b/openhis-ui-vue3/src/views/maintainSystem/checkprojectSettings/components/PackageManagement.vue @@ -95,9 +95,11 @@ {{ getLevelLabel(row.packageLevel) }} - + @@ -232,60 +234,65 @@ onMounted(async () => { console.error('获取套餐级别字典失败:', error) } - // 获取科室列表 - 优先使用Organization API(包含编码和名称) + // 获取科室列表 - 使用Organization完整API(包含编码和名称) try { - // 尝试使用Organization API获取科室列表(包含编码) + // 使用Organization完整API获取科室列表(包含busNo编码) const orgResponse = await request({ - url: '/app-common/department-list', - method: 'get' + url: '/base-data-manage/organization/organization', + method: 'get', + params: { + pageNo: 1, + pageSize: 1000 // 获取足够多的数据 + } }) - console.log('科室Organization API响应:', orgResponse) - let orgList = [] if (orgResponse) { - if (Array.isArray(orgResponse)) { - orgList = orgResponse - } else if (orgResponse.data) { - if (Array.isArray(orgResponse.data)) { + if (orgResponse.data) { + if (orgResponse.data.records && Array.isArray(orgResponse.data.records)) { + orgList = orgResponse.data.records + } else if (Array.isArray(orgResponse.data)) { orgList = orgResponse.data - } else if (orgResponse.data.data && Array.isArray(orgResponse.data.data)) { - orgList = orgResponse.data.data } - } else if (orgResponse.code === 200 && orgResponse.data) { - orgList = Array.isArray(orgResponse.data) ? orgResponse.data : [] + } else if (Array.isArray(orgResponse)) { + orgList = orgResponse } } + // 展开树结构,过滤出科室类型(typeEnum=2) + if (orgList && orgList.length > 0) { + const flattenList = [] + function flatten(nodes) { + nodes.forEach(node => { + if (node.typeEnum === 2 && node.busNo && node.name) { + flattenList.push(node) + } + if (node.children && node.children.length > 0) { + flatten(node.children) + } + }) + } + flatten(orgList) + orgList = flattenList + } + if (orgList && orgList.length > 0) { - // 使用Organization数据(包含编码和名称) departments.value = orgList.map(org => { const busNo = (org.busNo || org.code || '').trim() const name = (org.name || org.deptName || '').trim() - // 如果busNo是层级编码(如 "A01.001"),同时存储前缀("A01")用于匹配 const busNoPrefix = busNo ? busNo.split('.')[0] : '' return { dictValue: name, dictLabel: name, deptId: org.id || org.deptId, - deptCode: busNo || name, // 优先使用busNo,如果没有则使用名称 - busNoPrefix: busNoPrefix, // 存储前缀用于匹配 - rawOrg: org // 保存原始数据用于调试 + deptCode: busNo || name, + busNoPrefix: busNoPrefix, + rawOrg: org } }) - console.log('科室数据加载成功(Organization):', departments.value.length) - console.log('科室映射关系(前5个):', departments.value.slice(0, 5).map(d => ({ - deptCode: `"${d.deptCode}"`, - busNoPrefix: `"${d.busNoPrefix}"`, - codeLength: d.deptCode ? d.deptCode.length : 0, - name: d.dictLabel, - rawBusNo: d.rawOrg?.busNo - }))) } else { // 如果Organization API没有数据,使用系统部门API const deptResponse = await listDept() - console.log('科室API响应:', deptResponse) - // 处理不同的响应格式 let deptList = [] if (deptResponse) { if (Array.isArray(deptResponse)) { @@ -302,26 +309,21 @@ onMounted(async () => { } if (deptList && deptList.length > 0) { - // 将部门列表转换为字典格式 departments.value = deptList.map(dept => ({ dictValue: dept.deptName || dept.name, dictLabel: dept.deptName || dept.name, deptId: dept.deptId || dept.id, - deptCode: dept.deptName || dept.name // 如果没有编码,使用名称 + deptCode: dept.deptName || dept.name })) - console.log('科室数据加载成功(Dept):', departments.value.length, departments.value) } else { - console.warn('科室列表为空,尝试使用字典方式') // 如果获取失败,尝试使用字典方式 try { const dictResponse = await getDicts('dept') - console.log('科室字典响应:', dictResponse) if (dictResponse && dictResponse.data) { departments.value = dictResponse.data - console.log('使用字典方式加载科室数据成功:', departments.value.length) } } catch (dictError) { - console.error('获取科室字典也失败:', dictError) + console.error('获取科室字典失败:', dictError) } } } @@ -432,34 +434,11 @@ function getDeptName(deptValue) { return dept.dictLabel } - // 如果找不到,输出详细信息用于调试 - const deptCodes = departments.value.map(d => ({ - deptCode: String(d.deptCode || '').trim(), - deptCodeUpper: String(d.deptCode || '').trim().toUpperCase(), - busNoPrefix: String(d.busNoPrefix || '').trim().toUpperCase(), - name: d.dictLabel, - rawBusNo: d.rawOrg?.busNo, - rawBusNoUpper: d.rawOrg?.busNo ? String(d.rawOrg.busNo).trim().toUpperCase() : '', - rawBusNoPrefix: d.rawOrg?.busNo ? String(d.rawOrg.busNo).trim().toUpperCase().split('.')[0] : '' - })) - - // 输出详细的调试信息,包括所有科室的完整信息 - console.group('🔍 科室匹配失败 - 详细信息') - console.log('搜索值:', trimmedValue) - console.log('搜索值(大写):', trimmedValue.toUpperCase()) - console.log('搜索值长度:', trimmedValue.length) - console.log('可用科室总数:', deptCodes.length) - console.log('前5个科室详情:', deptCodes.slice(0, 5)) - console.log('所有科室编码列表:', deptCodes.map(d => ({ - deptCode: d.deptCode, - deptCodeUpper: d.deptCodeUpper, - busNoPrefix: d.busNoPrefix, - rawBusNo: d.rawBusNo, - rawBusNoUpper: d.rawBusNoUpper, - rawBusNoPrefix: d.rawBusNoPrefix, - name: d.name - }))) - console.groupEnd() + // 无法匹配时,返回原始编码值 + const isOldFormat = /^[A-Z]\d{2}$/.test(trimmedValue) + if (isOldFormat) { + return trimmedValue + ' (旧格式)' + } return trimmedValue } @@ -494,8 +473,6 @@ async function handleQuery() { tableData.value = [] total.value = 0 } - - console.log('查询成功,共', total.value, '条数据') } } catch (error) { console.error('查询失败:', error) @@ -520,28 +497,17 @@ function handleReset() { handleQuery() } -// 返回套餐设置界面 -function handleBackToSettings() { - emit('back-to-settings') -} - // 新增 function handleAdd() { - console.log('新增套餐') - // 通知父组件切换到套餐设置界面,模式为新增 emit('switch-to-settings', { mode: 'add', data: null }) } // 编辑 async function handleEdit(row) { try { - console.log('编辑套餐:', row.id) - - // 获取完整的套餐数据(包含明细) const response = await getCheckPackage(row.id) if (response && (response.code === 200 || response.code === 0) && response.data) { - // 通知父组件切换到套餐设置界面,模式为编辑 emit('switch-to-settings', { mode: 'edit', data: response.data }) } else { ElMessage.error('加载套餐数据失败') @@ -555,13 +521,9 @@ async function handleEdit(row) { // 查看 async function handleView(row) { try { - console.log('查看套餐:', row.id) - - // 获取完整的套餐数据(包含明细) const response = await getCheckPackage(row.id) if (response && (response.code === 200 || response.code === 0) && response.data) { - // 通知父组件切换到套餐设置界面,模式为查看 emit('switch-to-settings', { mode: 'view', data: response.data }) } else { ElMessage.error('加载套餐数据失败') @@ -589,7 +551,6 @@ function handleDelete(row) { if (response && (response.code === 200 || response.code === 0)) { ElMessage.success('删除成功') - // 刷新列表 handleQuery() } else { ElMessage.error(response?.msg || response?.message || '删除失败') @@ -598,9 +559,7 @@ function handleDelete(row) { console.error('删除失败:', error) ElMessage.error('删除失败: ' + (error.message || '未知错误')) } - }).catch(() => { - console.log('用户取消删除') - }) + }).catch(() => {}) } diff --git a/openhis-ui-vue3/src/views/maintainSystem/checkprojectSettings/components/PackageSettings.vue b/openhis-ui-vue3/src/views/maintainSystem/checkprojectSettings/components/PackageSettings.vue index 2bb6190b..8514ce5a 100644 --- a/openhis-ui-vue3/src/views/maintainSystem/checkprojectSettings/components/PackageSettings.vue +++ b/openhis-ui-vue3/src/views/maintainSystem/checkprojectSettings/components/PackageSettings.vue @@ -10,7 +10,7 @@ -
+

基本信息

- + @@ -95,7 +95,7 @@ @@ -386,6 +386,7 @@ import { addCheckPackage, updateCheckPackage } from '@/api/system/checkType' import { getDiagnosisTreatmentList } from '@/views/catalog/diagnosistreatment/components/diagnosistreatment' import useUserStore from '@/store/modules/user' import request from '@/utils/request' // 导入request工具用于调用Organization API +import cache from '@/plugins/cache' // 导入缓存工具 // 接收props const props = defineProps({ @@ -477,7 +478,6 @@ const detailData = ref([]) // 监听packageData变化,加载数据 watch(() => props.packageData, (newData) => { if (newData) { - console.log('加载套餐数据:', newData) loadPackageData(newData) } }, { immediate: true }) @@ -486,12 +486,33 @@ watch(() => props.packageData, (newData) => { function loadPackageData(data) { if (!data) return - console.log('开始加载套餐数据到表单...') - // 填充基本信息 Object.keys(formData).forEach(key => { if (data[key] !== undefined) { - formData[key] = data[key] + // 特殊处理科室字段:检查编码格式并匹配 + if (key === 'department' && data[key]) { + const deptValue = String(data[key]).trim() + const isOldFormat = /^[A-Z]\d{2}$/.test(deptValue) + + if (isOldFormat && departments.value.length > 0) { + // 旧编码格式:在下拉框中添加临时选项 + const tempDept = { + deptCode: deptValue, + dictLabel: `旧编码: ${deptValue} (请重新选择)`, + dictValue: deptValue, + isOldFormat: true + } + const exists = departments.value.find(d => d.deptCode === deptValue) + if (!exists) { + departments.value.unshift(tempDept) + } + formData[key] = deptValue + } else { + formData[key] = data[key] + } + } else { + formData[key] = data[key] + } } }) @@ -515,8 +536,6 @@ function loadPackageData(data) { filteredList: diagnosisTreatmentList.value })) } - - console.log('套餐数据加载完成') } onMounted(async () => { @@ -534,30 +553,53 @@ onMounted(async () => { console.error('✗ 获取套餐级别字典失败:', error) } - // 获取科室列表 - 优先使用Organization API(包含编码和名称) + // 获取科室列表 - 使用Organization完整API(包含编码和名称) try { - // 尝试使用Organization API获取科室列表(包含编码) + // 使用Organization完整API获取科室列表(包含busNo编码) const orgResponse = await request({ - url: '/app-common/department-list', - method: 'get' + url: '/base-data-manage/organization/organization', + method: 'get', + params: { + pageNo: 1, + pageSize: 1000 // 获取足够多的数据 + } }) - console.log('科室Organization API响应:', orgResponse) + console.log('科室Organization完整API响应:', orgResponse) let orgList = [] if (orgResponse) { - if (Array.isArray(orgResponse)) { - orgList = orgResponse - } else if (orgResponse.data) { - if (Array.isArray(orgResponse.data)) { + // 处理分页响应格式:{ code: 200, data: { records: [...], total: ... } } + if (orgResponse.data) { + if (orgResponse.data.records && Array.isArray(orgResponse.data.records)) { + // 分页格式,提取records + orgList = orgResponse.data.records + } else if (Array.isArray(orgResponse.data)) { orgList = orgResponse.data - } else if (orgResponse.data.data && Array.isArray(orgResponse.data.data)) { - orgList = orgResponse.data.data } - } else if (orgResponse.code === 200 && orgResponse.data) { - orgList = Array.isArray(orgResponse.data) ? orgResponse.data : [] + } else if (Array.isArray(orgResponse)) { + orgList = orgResponse } } + // 如果是树结构,需要展开所有节点(包括children),并过滤出科室类型(typeEnum=2) + if (orgList && orgList.length > 0) { + const flattenList = [] + function flatten(nodes) { + nodes.forEach(node => { + // 只包含科室类型(typeEnum=2)且有busNo的节点 + if (node.typeEnum === 2 && node.busNo && node.name) { + flattenList.push(node) + } + if (node.children && node.children.length > 0) { + flatten(node.children) + } + }) + } + flatten(orgList) + orgList = flattenList + console.log('展开后的科室列表(包含busNo):', orgList.length, orgList.slice(0, 3).map(o => ({ busNo: o.busNo, name: o.name }))) + } + if (orgList && orgList.length > 0) { // 使用Organization数据(包含编码和名称) departments.value = orgList.map(org => { @@ -637,91 +679,127 @@ onMounted(async () => { } } - // 获取诊疗项目列表 - 使用分批加载策略 - loading.value = true + // 加载诊疗项目列表(优先使用缓存) + await loadDiagnosisTreatmentList(false) + + // 初始化一行空数据 + handleAddRow() + } catch (error) { + console.error('✗ 初始化数据失败:', error) + } +}) + +// 诊疗项目列表缓存key和过期时间(30分钟) +const DIAGNOSIS_TREATMENT_CACHE_KEY = 'check_package_diagnosis_treatment_list' +const CACHE_EXPIRE_TIME = 30 * 60 * 1000 // 30分钟 + +// 加载诊疗项目列表(支持缓存) +async function loadDiagnosisTreatmentList(forceRefresh = false) { + // 如果不是强制刷新,先尝试从缓存加载 + if (!forceRefresh) { try { - console.log('开始获取诊疗项目列表...') - - // 分批加载数据,避免一次性加载过多导致超时 - let allItems = [] - const maxBatches = 3 // 最多加载3批 - const batchSize = 50 // 每批50条 - - for (let page = 1; page <= maxBatches; page++) { - try { - const treatmentResponse = await getDiagnosisTreatmentList({ - pageNo: page, - pageSize: batchSize - }) - - console.log(`第${page}批API响应:`, treatmentResponse) - - // 处理不同的响应格式 - let batchData = [] - if (treatmentResponse) { - if (treatmentResponse.data && treatmentResponse.data.records) { - batchData = treatmentResponse.data.records - } else if (treatmentResponse.data && Array.isArray(treatmentResponse.data)) { - batchData = treatmentResponse.data - } else if (treatmentResponse.records && Array.isArray(treatmentResponse.records)) { - batchData = treatmentResponse.records - } - } - - if (batchData.length > 0) { - allItems = allItems.concat(batchData) - console.log(`✓ 第${page}批加载成功: ${batchData.length}条,累计: ${allItems.length}条`) - - // 如果这批数据少于pageSize,说明已经是最后一批了 - if (batchData.length < batchSize) { - break - } - } else { - break // 没有更多数据了 - } - } catch (batchError) { - console.error(`第${page}批加载失败:`, batchError) - break // 出错就停止继续加载 + const cachedData = cache.session.getJSON(DIAGNOSIS_TREATMENT_CACHE_KEY) + if (cachedData && cachedData.data && cachedData.timestamp) { + const now = Date.now() + const cacheAge = now - cachedData.timestamp + + // 检查缓存是否过期 + if (cacheAge < CACHE_EXPIRE_TIME) { + diagnosisTreatmentList.value = cachedData.data + // 静默加载,不显示消息 + return } } + } catch (error) { + // 缓存读取失败,继续从API加载 + console.error('读取缓存失败:', error) + } + } + + // 从API加载数据 + loading.value = true + try { + let allItems = [] + const maxBatches = 3 + const batchSize = 50 + + for (let page = 1; page <= maxBatches; page++) { + try { + const treatmentResponse = await getDiagnosisTreatmentList({ + pageNo: page, + pageSize: batchSize + }) + + let batchData = [] + if (treatmentResponse) { + if (treatmentResponse.data && treatmentResponse.data.records) { + batchData = treatmentResponse.data.records + } else if (treatmentResponse.data && Array.isArray(treatmentResponse.data)) { + batchData = treatmentResponse.data + } else if (treatmentResponse.records && Array.isArray(treatmentResponse.records)) { + batchData = treatmentResponse.records + } + } + + if (batchData.length > 0) { + allItems = allItems.concat(batchData) + if (batchData.length < batchSize) { + break + } + } else { + break + } + } catch (batchError) { + console.error(`第${page}批加载失败:`, batchError) + if (page === 1) { + throw batchError + } + break + } + } + + if (allItems.length > 0) { + diagnosisTreatmentList.value = allItems - if (allItems.length > 0) { - diagnosisTreatmentList.value = allItems - console.log(`✓ 诊疗项目加载完成,共${allItems.length}条`) + // 保存到缓存 + try { + cache.session.setJSON(DIAGNOSIS_TREATMENT_CACHE_KEY, { + data: allItems, + timestamp: Date.now() + }) + } catch (cacheError) { + console.error('保存缓存失败:', cacheError) + } + + // 只在强制刷新时显示成功消息 + if (forceRefresh) { ElMessage.success(`成功加载${allItems.length}个诊疗项目`) - } else { - console.warn('未获取到任何诊疗项目数据') + } + } else { + if (forceRefresh) { ElMessage.warning({ message: '未获取到诊疗项目数据。请先在【系统管理-目录管理-诊疗项目】中添加数据', duration: 6000, showClose: true }) } - - } catch (error) { - console.error('获取诊疗项目列表失败:', error) + } + } catch (error) { + console.error('获取诊疗项目列表失败:', error) + if (forceRefresh) { ElMessage.error({ message: '获取诊疗项目列表失败,请检查网络连接或联系管理员', duration: 6000, showClose: true }) - } finally { - loading.value = false } - - // 初始化一行空数据 - handleAddRow() - - console.log('=== PackageSettings 组件初始化完成 ===') - console.log('最终诊疗项目列表:', diagnosisTreatmentList.value) - } catch (error) { - console.error('✗ 初始化数据失败:', error) + } finally { + loading.value = false } -}) +} // 套餐级别变更处理 function handlePackageLevelChange(value) { - console.log('套餐级别变更:', value) // 重置关联字段 if (value !== '2') { formData.department = '' @@ -915,10 +993,45 @@ function calculateTotal(row) { calculatePackagePrice() } -// 计算套餐金额 +// 计算套餐金额(应用折扣) function calculatePackagePrice() { + // 计算所有明细项目的总金额 const total = detailData.value.reduce((sum, item) => sum + (item.total || 0), 0) - formData.packagePrice = total.toFixed(2) + + // 如果有折扣,应用折扣计算 + let finalPrice = total + if (formData.discount && parseFloat(formData.discount) > 0 && parseFloat(formData.discount) <= 100) { + const discountRate = parseFloat(formData.discount) / 100 // 将百分比转换为小数(如10% -> 0.1) + const discountAmount = total * discountRate // 折扣金额 + finalPrice = total - discountAmount // 折扣后金额 + } + + formData.packagePrice = finalPrice.toFixed(2) +} + +// 折扣变更处理 +function handleDiscountChange(value) { + // 验证并清理输入 + const regex = /^\d*\.?\d*$/ + if (!regex.test(value)) { + formData.discount = value.replace(/[^\d.]/g, '') + return + } + + // 验证折扣范围 + const discountValue = parseFloat(formData.discount) + if (discountValue && (discountValue < 0 || discountValue > 100)) { + ElMessage.warning('折扣必须在0-100之间') + // 重置为有效值 + if (discountValue < 0) { + formData.discount = '0' + } else if (discountValue > 100) { + formData.discount = '100' + } + } + + // 重新计算套餐金额 + calculatePackagePrice() } // 套餐管理 @@ -927,66 +1040,12 @@ function handlePackageManagement() { emit('switch-to-management') } -// 刷新 - 重新加载诊疗项目数据 +// 刷新 - 清除缓存并重新加载诊疗项目数据 async function handleRefresh() { - try { - loading.value = true - console.log('开始刷新诊疗项目数据...') - - // 分批加载数据,避免一次性加载过多导致超时 - let allItems = [] - const maxBatches = 3 // 最多加载3批 - const batchSize = 50 // 每批50条 - - for (let page = 1; page <= maxBatches; page++) { - try { - const treatmentResponse = await getDiagnosisTreatmentList({ - pageNo: page, - pageSize: batchSize - }) - - console.log(`第${page}批API响应:`, treatmentResponse) - - let batchData = [] - if (treatmentResponse) { - if (treatmentResponse.data && treatmentResponse.data.records) { - batchData = treatmentResponse.data.records - } else if (treatmentResponse.data && Array.isArray(treatmentResponse.data)) { - batchData = treatmentResponse.data - } else if (treatmentResponse.records && Array.isArray(treatmentResponse.records)) { - batchData = treatmentResponse.records - } - } - - if (batchData.length > 0) { - allItems = allItems.concat(batchData) - console.log(`✓ 第${page}批加载成功: ${batchData.length}条,累计: ${allItems.length}条`) - - // 如果这批数据少于pageSize,说明已经是最后一批了 - if (batchData.length < batchSize) { - break - } - } else { - break // 没有更多数据了 - } - } catch (batchError) { - console.error(`第${page}批加载失败:`, batchError) - break // 出错就停止继续加载 - } - } - - if (allItems.length > 0) { - diagnosisTreatmentList.value = allItems - ElMessage.success('刷新成功,共加载 ' + allItems.length + ' 个项目') - } else { - ElMessage.warning('未获取到项目数据,请先在【系统管理-目录管理-诊疗项目】中添加数据') - } - } catch (error) { - console.error('刷新失败:', error) - ElMessage.error('刷新失败,请检查网络连接或联系管理员') - } finally { - loading.value = false - } + // 清除缓存 + cache.session.remove(DIAGNOSIS_TREATMENT_CACHE_KEY) + // 强制刷新加载 + await loadDiagnosisTreatmentList(true) } // 数字输入验证 - 用于表单字段 diff --git a/openhis-ui-vue3/src/views/maintainSystem/checkprojectSettings/index.vue b/openhis-ui-vue3/src/views/maintainSystem/checkprojectSettings/index.vue index f707822b..89294775 100644 --- a/openhis-ui-vue3/src/views/maintainSystem/checkprojectSettings/index.vue +++ b/openhis-ui-vue3/src/views/maintainSystem/checkprojectSettings/index.vue @@ -55,17 +55,17 @@
@@ -322,7 +322,7 @@ function handleMenuClick(menu) { currentPackageData.value = null console.log('显示套餐设置界面') } else { - loadMenuData(menu); + loadMenuData(menu); } }