GoToPage

本文介绍了一个简单的分页查询实现方法,通过更改页面索引来触发数据更新,并使用SQL语句来实现特定的分页效果。同时展示了如何通过事件传递新旧页面索引。

private void GoToPage(int pageIndex)
{
   // 准备事件数据
   PageChangedEventArgs e = new PageChangedEventArgs();
   e.OldPageIndex = CurrentPageIndex;
   e.NewPageIndex = pageIndex;

   // 更新当前的索引
   CurrentPageIndex = pageIndex;

   // 启动页面更改事件
   OnPageIndexChanged(e);

   // 绑定新数据
   DataBind();
}


SELECT * FROM
(SELECT TOP ItemsPerPage * FROM
(SELECT TOP ItemsPerPage*CurrentPageIndex * FROM
(SelectCommand) AS t0
ORDER BY SortField ASC) AS t1
ORDER BY SortField DESC) AS t2
ORDER BY SortField
       
 

比較mrviewer0.vue與mrviewer.vue,找出mrviewer.vue的錯誤之處: mrviewer0.vue: <template> <div class="container"> <!-- 控制面板 --> <div class="control-panel"> <button @click="fetchData" class="refresh-btn">刷新數據</button> <button @click="toggleRelative" class="relative-btn"> {{ showRelative ? '病態關聯' : '病態關聯' }} </button> <!-- 本草关联器按钮 --> <button @click="toggleMNRelative" class="relative-btn"> {{ showMNRelative ? '本草關聯' : '本草關聯' }} </button> <!-- 方剂关联器按钮 --> <button @click="togglePNRelative" class="relative-btn"> {{ showPNRelative ? '方劑關聯' : '方劑關聯' }} </button> <!-- 出处关联器按钮 --> <button @click="toggleSNRelative" class="relative-btn"> {{ showSNRelative ? '典籍關聯' : '典籍關聯' }} </button> <!-- 新增人物关联器按钮 --> <button @click="toggleFNRelative" class="relative-btn"> {{ showFNRelative ? '人物關聯' : '人物關聯' }} </button> <input v-model="searchQuery" placeholder="搜索..." class="search-input" /> <div class="pagination-controls"> <span>每頁顯示:</span> <select v-model.number="pageSize" class="page-size-select"> <option value="1">1筆</option> <option value="4">4筆</option> <option value="10">10筆</option> </select> <button @click="prevPage" :disabled="currentPage === 1">上一页</button> <span>第</span> <input type="number" v-model.number="inputPage" min="1" :max="totalPages" class="page-input" @input="handlePageInput"> <span>頁 / 共 {{ totalPages }} 頁</span> <button @click="nextPage" :disabled="currentPage === totalPages">下一頁</button> <span>醫案閱讀器</span> </div> </div> <!-- 主内容区域 --> <div class="content-area"> <div class="horizontal-records" v-if="filteredData.length > 0"> <div v-for="(item, index) in paginatedData" :key="item.id" class="record-card"> <div class="record-header"> <h3>醫案 #{{ (currentPage - 1) * pageSize + index + 1 }}</h3> </div> <div class="record-body"> <div v-for="(value, key) in processFieldNames(item)" :key="key" class="record-field"> <div class="field-name">{{ key }}:</div> <div class="field-value"> <!-- 病态名称 --> <div v-if="key === '相關病態' && Array.isArray(value)" class="dntag-value" v-html="formatDntagValueHTML(value)"></div> <!-- 本草名称 --> <div v-else-if="key === '相關本草' && Array.isArray(value)" class="mntag-value" v-html="formatMntagValueHTML(value)"></div> <!-- 方剂名称 --> <div v-else-if="key === '相關方劑' && Array.isArray(value)" class="pntag-value" v-html="formatPntagValueHTML(value)"></div> <!-- 出处名称 --> <div v-else-if="key === '相關典籍' && Array.isArray(value)" class="sntag-value" v-html="formatSntagValueHTML(value)"></div> <!-- 新增人物名称 --> <div v-else-if="key === '相關人物' && Array.isArray(value)" class="fntag-value" v-html="formatFntagValueHTML(value)"></div> <div v-else-if="Array.isArray(value)" class="array-value"> <span v-for="(subItem, subIndex) in value" :key="subIndex"> <span v-html="formatValue(subItem, key)"></span><span v-if="subIndex < value.length - 1">;</span> </span> </div> <div v-else v-html="formatValue(value, key)"></div> </div> </div> </div> </div> </div> <div v-else class="no-data"> 沒有找到匹配的數據 </div> </div> <!-- 相关区域 --> <div class="relative-area"> <mrdnrelate v-if="showRelative" :currentCase="currentCase" :allTags="api2Data" @data-updated="handleDataUpdated"></mrdnrelate> <!-- 本草关联器 --> <mrmnrelate v-else-if="showMNRelative" :currentCase="currentCase" :allTags="api3Data" @data-updated="handleDataUpdated"></mrmnrelate> <!-- 方剂关联器 --> <mrpnrelate v-else-if="showPNRelative" :currentCase="currentCase" :allTags="api5Data" @data-updated="handleDataUpdated"></mrpnrelate> <!-- 出处关联器 --> <mrsnrelate v-else-if="showSNRelative" :currentCase="currentCase" :allTags="api4Data" @data-updated="handleDataUpdated"></mrsnrelate> <!-- 新增人物关联器 --> <mrfnrelate v-else-if="showFNRelative" :currentCase="currentCase" :allTags="api6Data" @data-updated="handleDataUpdated"></mrfnrelate> <span v-else>點按下方關聯器,顯示醫案相關專有名詞</span> </div> </div> </template> <script> import mrdnrelate from './mrdnrelate.vue'; import mrmnrelate from './mrmnrelate.vue'; import mrpnrelate from './mrpnrelate.vue'; // 导入方剂关联器组件 import mrsnrelate from './mrsnrelate.vue'; import mrfnrelate from './mrfnrelate.vue'; // 导入新增的人物关联器组件 export default { name: 'mrviewer', components: { mrdnrelate, mrmnrelate, mrpnrelate, mrsnrelate, mrfnrelate }, data() { return { api1Data: [], api2Data: [], api3Data: [], // 本草标签数据 api4Data: [], // 出处标签数据 api5Data: [], // 方剂标签数据 api6Data: [], // 新增人物标签数据 mergedData: [], currentPage: 1, pageSize: 1, searchQuery: '', sortKey: '', sortOrders: {}, inputPage: 1, fieldNames: { 'mrcase': '醫案全文', 'mrorigin': '醫案出處', 'mrdoctor': '醫案醫者', 'mrname': '醫案命名', 'mrposter': '醫案提交者', 'mrlasttime': '最後編輯時間', 'mreditnumber': '編輯次數', 'mrreadnumber': '閱讀次數', 'mrpriority': '重要性', 'dntag': '相關病態', 'mntag': '相關本草', 'pntag': '相關方劑', 'sntag': '相關典籍', 'fntag': '相關人物' // 新增人物字段 }, inputTimeout: null, dnNames: [], mnNames: [], // 本草名称列表 pnNames: [], // 方剂名称列表 snNames: [], // 出处名称列表 fnNames: [], // 新增人物名称列表 stateVersion: '1.0', showRelative: false, showMNRelative: false, // 控制本草关联器显示 showPNRelative: false, // 控制方剂关联器显示 showSNRelative: false, // 控制出处关联器显示 showFNRelative: false, // 新增控制人物关联器显示 currentCase: null }; }, computed: { filteredData() { const query = this.searchQuery.trim(); if (query && /^\d+$/.test(query)) { const idToSearch = parseInt(query, 10); return this.mergedData.filter(item => item.id === idToSearch); } if (!query) return this.mergedData; const lowerQuery = query.toLowerCase(); return this.mergedData.filter(item => { return Object.values(item).some(value => { if (value === null || value === undefined) return false; if (Array.isArray(value)) { return value.some(subValue => { if (typeof subValue === 'object' && subValue !== null) { return JSON.stringify(subValue).toLowerCase().includes(lowerQuery); } return String(subValue).toLowerCase().includes(lowerQuery); }); } if (typeof value === 'object' && value !== null) { return JSON.stringify(value).toLowerCase().includes(lowerQuery); } return String(value).toLowerCase().includes(lowerQuery); }); }); }, sortedData() { if (!this.sortKey) return this.filteredData; const order = this.sortOrders[this.sortKey] || 1; return [...this.filteredData].sort((a, b) => { const getValue = (obj) => { const val = obj[this.sortKey]; if (Array.isArray(val)) return JSON.stringify(val); return val; }; const aValue = getValue(a); const bValue = getValue(b); if (aValue === bValue) return 0; return aValue > bValue ? order : -order; }); }, paginatedData() { const start = (this.currentPage - 1) * Number(this.pageSize); const end = start + Number(this.pageSize); const data = this.sortedData.slice(start, end); // 更新当前医案完整数据 if (data.length > 0) { this.currentCase = data[0]; } else { this.currentCase = null; } return data; }, totalPages() { return Math.ceil(this.filteredData.length / this.pageSize) || 1; } }, watch: { pageSize() { this.currentPage = 1; this.inputPage = 1; this.saveState(); }, currentPage(newVal) { this.inputPage = newVal; this.saveState(); }, filteredData() { if (this.currentPage > this.totalPages) { this.currentPage = Math.max(1, this.totalPages); } this.inputPage = this.currentPage; }, searchQuery() { this.saveState(); } }, methods: { // 处理数据更新事件 handleDataUpdated() { // 显示操作成功的提示 alert('數據已更新,正在刷新醫案數據...'); // 刷新数据 this.fetchData(); }, // 本草关联器切换方法 toggleMNRelative() { if (!this.showMNRelative) { this.showRelative = false; this.showPNRelative = false; this.showSNRelative = false; this.showFNRelative = false; } this.showMNRelative = !this.showMNRelative; }, // 方剂关联器切换方法 togglePNRelative() { if (!this.showPNRelative) { this.showRelative = false; this.showMNRelative = false; this.showSNRelative = false; this.showFNRelative = false; } this.showPNRelative = !this.showPNRelative; }, // 出处关联器切换方法 toggleSNRelative() { if (!this.showSNRelative) { this.showRelative = false; this.showMNRelative = false; this.showPNRelative = false; this.showFNRelative = false; } this.showSNRelative = !this.showSNRelative; }, // 病态关联器切换方法 toggleRelative() { if (this.showRelative) { this.showRelative = false; } else { this.showMNRelative = false; this.showPNRelative = false; this.showSNRelative = false; this.showFNRelative = false; this.showRelative = true; } }, // 新增人物关联器切换方法 toggleFNRelative() { if (!this.showFNRelative) { this.showRelative = false; this.showMNRelative = false; this.showPNRelative = false; this.showSNRelative = false; } this.showFNRelative = !this.showFNRelative; }, // 病态名称HTML格式化方法 (使用橙色) formatDntagValueHTML(dntagArray) { return dntagArray.map(tagObj => { const name = tagObj.dnname || tagObj.name || '未命名標籤'; return `<span style="color: rgb(212, 107, 8); font-weight: bold;">${this.escapeHtml(name)}</span>`; }).join(';'); }, // 本草名称HTML格式化方法 (使用绿色) formatMntagValueHTML(mntagArray) { return mntagArray.map(tagObj => { const name = tagObj.mnname || tagObj.name || '未命名標籤'; return `<span style="color: rgb(0, 128, 0); font-weight: bold;">${this.escapeHtml(name)}</span>`; }).join(';'); }, // 方剂名称HTML格式化方法 (使用紫色) formatPntagValueHTML(pntagArray) { return pntagArray.map(tagObj => { const name = tagObj.pnname || tagObj.name || '未命名標籤'; return `<span style="color: rgb(128, 0, 128); font-weight: bold;">${this.escapeHtml(name)}</span>`; }).join(';'); }, // 出处名称HTML格式化方法 (使用蓝色) formatSntagValueHTML(sntagArray) { return sntagArray.map(tagObj => { const name = tagObj.snname || tagObj.name || '未命名標籤'; return `<span style="color: rgb(51, 102, 255); font-weight: bold;">${this.escapeHtml(name)}</span>`; }).join(';'); }, // 新增人物名称HTML格式化方法 (使用棕色) formatFntagValueHTML(fntagArray) { return fntagArray.map(tagObj => { const name = tagObj.fnname || tagObj.name || '未命名標籤'; return `<span style="color: #8B4513; font-weight: bold;">${this.escapeHtml(name)}</span>`; }).join(';'); }, // HTML转义方法防止XSS攻击 escapeHtml(text) { const map = { '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }; return text.replace(/[&<>"']/g, m => map[m]); }, saveState() { const state = { version: this.stateVersion, currentPage: this.currentPage, pageSize: this.pageSize, searchQuery: this.searchQuery, timestamp: new Date().getTime() }; sessionStorage.setItem('mrviewerState', JSON.stringify(state)); }, restoreState() { const savedState = sessionStorage.getItem('mrviewerState'); if (!savedState) return; try { const state = JSON.parse(savedState); if (state.version !== this.stateVersion) return; this.currentPage = state.currentPage || 1; this.pageSize = state.pageSize || 1; this.searchQuery = state.searchQuery || ''; this.inputPage = this.currentPage; } catch (e) { sessionStorage.removeItem('mrviewerState'); } }, clearState() { sessionStorage.removeItem('mrviewerState'); }, async fetchData() { try { // 获取原有数据 const api1Response = await fetch("MRInfo/?format=json"); this.api1Data = await api1Response.json(); const api2Response = await fetch("DNTag/?format=json"); this.api2Data = await api2Response.json(); // 本草数据获取 const api3Response = await fetch("MNTag/?format=json"); this.api3Data = await api3Response.json(); // 方剂数据获取 const api5Response = await fetch("PNTag/?format=json"); this.api5Data = await api5Response.json(); // 出处数据获取 const api4Response = await fetch("SNTag/?format=json"); this.api4Data = await api4Response.json(); // 新增人物数据获取 const api6Response = await fetch("FNTag/?format=json"); this.api6Data = await api6Response.json(); // 本草名称列表 this.mnNames = this.api3Data.map(item => item.mnname).filter(name => name && name.trim()); this.mnNames.sort((a, b) => b.length - a.length); // 方剂名称列表 this.pnNames = this.api5Data.map(item => item.pnname).filter(name => name && name.trim()); this.pnNames.sort((a, b) => b.length - a.length); // 病态名称列表 this.dnNames = this.api2Data.map(item => item.dnname).filter(name => name && name.trim()); this.dnNames.sort((a, b) => b.length - a.length); // 出处名称列表 this.snNames = this.api4Data.map(item => item.snname).filter(name => name && name.trim()); this.snNames.sort((a, b) => b.length - a.length); // 新增人物名称列表 this.fnNames = this.api6Data.map(item => item.fnname).filter(name => name && name.trim()); this.fnNames.sort((a, b) => b.length - a.length); this.mergeData(); this.currentPage = 1; this.inputPage = 1; this.saveState(); } catch (error) { console.error("獲取數據失敗:", error); alert("數據加載失敗,請稍後重試"); } }, mergeData() { this.mergedData = this.api1Data.map((item) => { const newItem = { ...item }; // 处理病态标签 if (newItem.dntag && Array.isArray(newItem.dntag)) { newItem.dntag = newItem.dntag.map((tagId) => { const matchedItem = this.api2Data.find(api2Item => api2Item.id === tagId); return matchedItem || { id: tagId, dnname: "未找到匹配的數據" }; }); } // 处理本草标签 if (newItem.mntag && Array.isArray(newItem.mntag)) { newItem.mntag = newItem.mntag.map((tagId) => { const matchedItem = this.api3Data.find(api3Item => api3Item.id === tagId); return matchedItem || { id: tagId, mnname: "未找到匹配的數據" }; }); } // 处理方剂标签 if (newItem.pntag && Array.isArray(newItem.pntag)) { newItem.pntag = newItem.pntag.map((tagId) => { const matchedItem = this.api5Data.find(api5Item => api5Item.id === tagId); return matchedItem || { id: tagId, pnname: "未找到匹配的數據" }; }); } // 处理出处标签 if (newItem.sntag && Array.isArray(newItem.sntag)) { newItem.sntag = newItem.sntag.map((tagId) => { const matchedItem = this.api4Data.find(api4Item => api4Item.id === tagId); return matchedItem || { id: tagId, snname: "未找到匹配的數據" }; }); } // 新增处理人物标签 if (newItem.fntag && Array.isArray(newItem.fntag)) { newItem.fntag = newItem.fntag.map((tagId) => { const matchedItem = this.api6Data.find(api6Item => api6Item.id === tagId); return matchedItem || { id: tagId, fnname: "未找到匹配的數據" }; }); } return newItem; }); // 初始化排序顺序 this.sortOrders = {}; if (this.mergedData.length > 0) { Object.keys(this.mergedData[0]).forEach(key => { this.sortOrders[key] = 1; }); } }, processFieldNames(item) { const result = {}; for (const key in item) { const newKey = this.fieldNames[key] || key; result[newKey] = item[key]; } return result; }, formatValue(value, fieldName) { if (value === null || value === undefined) return ''; // 醫案全文的高亮(保持不变) if (fieldName === '醫案全文' && typeof value === 'string') { let highlighted = this.highlightMatches(value, this.dnNames, 'rgb(212, 107, 8)'); highlighted = this.highlightMatches(highlighted, this.mnNames, 'rgb(0, 128, 0)'); highlighted = this.highlightMatches(highlighted, this.pnNames, 'rgb(128, 0, 128)'); highlighted = this.highlightMatches(highlighted, this.snNames, 'rgb(51, 102, 255)'); highlighted = this.highlightMatches(highlighted, this.fnNames, '#8B4513'); return highlighted; } // 醫案出處字段:高亮相关典籍(蓝色) else if (fieldName === '醫案出處' && typeof value === 'string') { return this.highlightMatches(value, this.snNames, 'rgb(51, 102, 255)'); } // 醫案醫者字段:高亮相关人物(棕色) else if (fieldName === '醫案醫者' && typeof value === 'string') { return this.highlightMatches(value, this.fnNames, '#8B4513'); } // 其他字段处理(保持不变) if (typeof value === 'string' && value.startsWith('http')) { return `<a href="${value}" target="_blank">${value}</a>`; } return value; }, // 改进的高亮方法,支持不同颜色 highlightMatches(text, words, color) { if (!text || typeof text !== 'string' || words.length === 0) { return text; } const pattern = new RegExp( words .map(name => name.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')) .join('|'), 'gi' ); return text.replace(pattern, match => `<span style="color: ${color}; font-weight: bold;">${this.escapeHtml(match)}</span>` ); }, sortBy(key) { const originalKey = Object.keys(this.fieldNames).find( origKey => this.fieldNames[origKey] === key ) || key; this.sortKey = originalKey; this.sortOrders[originalKey] = this.sortOrders[originalKey] * -1; this.saveState(); }, prevPage() { if (this.currentPage > 1) { this.currentPage--; this.saveState(); } }, nextPage() { if (this.currentPage < this.totalPages) { this.currentPage++; this.saveState(); } }, handlePageInput() { clearTimeout(this.inputTimeout); this.inputTimeout = setTimeout(() => { this.goToPage(); this.saveState(); }, 300); }, goToPage() { if (this.inputPage === null || this.inputPage === undefined || this.inputPage === '') { this.inputPage = this.currentPage; return; } const page = parseInt(this.inputPage); if (isNaN(page)) { this.inputPage = this.currentPage; return; } if (page < 1) { this.currentPage = 1; } else if (page > this.totalPages) { this.currentPage = this.totalPages; } else { this.currentPage = page; } this.inputPage = this.currentPage; } }, mounted() { this.restoreState(); this.fetchData(); }, activated() { this.restoreState(); }, deactivated() { this.saveState(); } }; </script> <style scoped> .container { max-width: 1200px; margin: 0px; padding: 0px; } .control-panel { margin-bottom: 0px; display: flex; flex-wrap: wrap; gap: 10px; justify-content: flex-end; align-items: center; position: fixed; bottom: 0; left: 0; width: 100%; background-color: #ffd800ff; z-index: 999; padding: 10px 20px; box-sizing: border-box; } .content-area { position: fixed; top: 56px; bottom: 45px; left: 0; width: 70%; background: white; padding: 1px; z-index: 100; overflow-y: auto; } .relative-area { position: fixed; top: 56px; bottom: 45px; right: 0; width: 30%; background: lightblue; padding: 1px; z-index: 100; overflow-y: auto; } .refresh-btn, .relative-btn { padding: 4px; background-color: #4CAF50; color: white; border: none; border-radius: 4px; cursor: pointer; } .refresh-btn:hover, .relative-btn:hover { background-color: #45a049; } .search-input { padding: 8px; border: 1px solid #ddd; border-radius: 4px; flex-grow: 1; max-width: 300px; } .pagination-controls { display: flex; align-items: center; gap: 5px; } .page-size-select { padding: 4px; border-radius: 4px; width: 70px; } .page-input { width: 50px; padding: 4px; border: 1px solid #ddd; border-radius: 4px; text-align: center; } .horizontal-records { display: flex; flex-direction: column; gap: 20px; } .record-card { border: 1px solid #ddd; border-radius: 4px; overflow: hidden; box-shadow: 0 2px 4px rgba(0,0,0,0.1); } .record-header { padding: 12px 16px; background-color: #f5f5f5; border-bottom: 1px solid #ddd; } .record-header h3 { margin: 0; font-size: 1.1em; } .record-body { padding: 16px; } .record-field { display: flex; margin-bottom: 12px; line-height: 1.5; } .record-field:last-child { margin-bottom: 0; } .field-name { font-weight: bold; min-width: 120px; color: #555; } .field-value { flex-grow: 1; display: flex; flex-wrap: wrap; gap: 8px; } .dntag-value { display: flex; flex-wrap: wrap; gap: 8px; } /* 本草名称样式 */ .mntag-value { display: flex; flex-wrap: wrap; gap: 8px; color: #006400; /* 深绿色 */ font-weight: 500; } /* 方剂名称样式 */ .pntag-value { display: flex; flex-wrap: wrap; gap: 8px; color: #800080; /* 紫色 */ font-weight: 500; } /* 出处名称样式 */ .sntag-value { display: flex; flex-wrap: wrap; gap: 8px; color: #0094ff; /* 靛蓝->蓝色 */ font-weight: 500; } /* 新增人物名称样式 */ .fntag-value { display: flex; flex-wrap: wrap; gap: 8px; color: #8B4513; /* 棕色 */ font-weight: 500; } .array-value { display: flex; flex-wrap: wrap; gap: 8px; } .no-data { padding: 20px; text-align: center; color: #666; font-style: italic; } button:disabled { opacity: 0.5; cursor: not-allowed; } </style> mrviewer.vue: <!-- mrviewer.vue --> <template> <div class="container"> <!-- 控制面板 --> <div class="control-panel"> <button @click="fetchData" class="refresh-btn">刷新數據</button> <button @click="toggleRelative" class="relative-btn"> {{ showRelative ? '病態關聯' : '病態關聯' }} </button> <!-- 本草关联器按钮 --> <button @click="toggleMNRelative" class="relative-btn"> {{ showMNRelative ? '本草關聯' : '本草關聯' }} </button> <!-- 方剂关联器按钮 --> <button @click="togglePNRelative" class="relative-btn"> {{ showPNRelative ? '方劑關聯' : '方劑關聯' }} </button> <!-- 出处关联器按钮 --> <button @click="toggleSNRelative" class="relative-btn"> {{ showSNRelative ? '典籍關聯' : '典籍關聯' }} </button> <!-- 人物关联器按钮 --> <button @click="toggleFNRelative" class="relative-btn"> {{ showFNRelative ? '人物關聯' : '人物關聯' }} </button> <!-- 新增辨證关联器按钮 --> <button @click="toggleDianNRelative" class="relative-btn"> {{ showDianNRelative ? '辨證關聯' : '辨證關聯' }} </button> <input v-model="searchQuery" placeholder="搜索..." class="search-input" /> <div class="pagination-controls"> <span>每頁顯示:</span> <select v-model.number="pageSize" class="page-size-select"> <option value="1">1筆</option> <option value="4">4筆</option> <option value="10">10筆</option> </select> <button @click="prevPage" :disabled="currentPage === 1">上一页</button> <span>第</span> <input type="number" v-model.number="inputPage" min="1" :max="totalPages" class="page-input" @input="handlePageInput"> <span>頁 / 共 {{ totalPages }} 頁</span> <button @click ="nextPage" :disabled="currentPage === totalPages"> 下一頁</button> <span>醫案閱讀器</span> </div> </div> <!-- 主内容区域 --> <div class="content-area"> <div class="horizontal-records" v-if="filteredData.length > 0"> <div v-for="(item, index) in paginatedData" :key="item.id" class="record-card"> <div class="record-header"> <h3>醫案 #{{ (currentPage - 1) * pageSize + index + 1 }}</h3> </div> <div class="record-body"> <div v-for="(value, key) in processFieldNames(item)" :key="key" class="record-field"> <div class="field-name">{{ key }}:</div> <div class="field-value"> <!-- 病态名称 --> <div v-if="key === '相關病態' && Array.isArray(value)" class="dntag-value" v-html="formatDntagValueHTML(value)"></div> <!-- 本草名称 --> <div v-else-if="key === '相關本草' && Array.isArray(value)" class="mntag-value" v-html="formatMntagValueHTML(value)"></div> <!-- 方剂名称 --> <div v-else-if="key === '相關方劑' && Array.isArray(value)" class="pntag-value" v-html="formatPntagValueHTML(value)"></div> <!-- 出处名称 --> <div v-else-if="key === '相關典籍' && Array.isArray(value)" class="sntag-value" v-html="formatSntagValueHTML(value)"></div> <!-- 人物名称 --> <div v-else-if="key === '相關人物' && Array.isArray(value)" class="fntag-value" v-html="formatFntagValueHTML(value)"></div> <!-- 辨證名称 --> <div v-else-if="key === '相關辨證' && Array.isArray(value)" class="diantag-value" v-html="formatDiantagValueHTML(value)"></div> <div v-else-if="Array.isArray(value)" class="array-value"> <span v-for="(subItem, subIndex) in value" :key="subIndex"> <span v-html="formatValue(subItem, key)"></span><span v-if="subIndex < value.length - 1">;</span> </span> </div> <div v-else v-html="formatValue(value, key)"></div> </div> </div> </div> </div> </div> <div v-else class="no-data"> 沒有找到匹配的數據 </div> </div> <!-- 相关区域 --> <div class="relative-area"> <mrdnrelate v-if="showRelative" :currentCase="currentCase" :allTags="api2Data" @data-updated="handleDataUpdated"></mrdnrelate> <!-- 本草关联器 --> <mrmnrelate v-else-if="showMNRelative" :currentCase="currentCase" :allTags="api3Data" @data-updated="handleDataUpdated"></mrmnrelate> <!-- 方剂关联器 --> <mrpnrelate v-else-if="showPNRelative" :currentCase="currentCase" :allTags="api5Data" @data-updated="handleDataUpdated"></mrpnrelate> <!-- 出处关联器 --> <mrsnrelate v-else-if="showSNRelative" :currentCase="currentCase" :allTags="api4Data" @data-updated="handleDataUpdated"></mrsnrelate> <!-- 人物关联器 --> <mrfnrelate v-else-if="showFNRelative" :currentCase="currentCase" :allTags="api6Data" @data-updated="handleDataUpdated"></mrfnrelate> <!-- 新增辨證关联器 --> <mrdianrelate v-else-if="showDianNRelative" :currentCase="currentCase" :allTags="api7Data" @data-updated="handleDataUpdated"></mrdianrelate> <span v-else>點按下方關聯器,顯示醫案相關專有名詞</span> </div> </div> </template> <script> import mrdnrelate from './mrdnrelate.vue'; import mrmnrelate from './mrmnrelate.vue'; import mrpnrelate from './mrpnrelate.vue'; import mrsnrelate from './mrsnrelate.vue'; import mrfnrelate from './mrfnrelate.vue'; import mrdianrelate from './mrdianrelate.vue'; // 导入辨證关联器组件 export default { name: 'mrviewer', components: { mrdnrelate, mrmnrelate, mrpnrelate, mrsnrelate, mrfnrelate, mrdianrelate }, data() { return { api1Data: [], api2Data: [], api3Data: [], api4Data: [], api5Data: [], api6Data: [], api7Data: [], // 辨證标签数据 mergedData: [], currentPage: 1, pageSize: 1, searchQuery: '', sortKey: '', sortOrders: {}, inputPage: 1, fieldNames: { 'mrcase': '醫案全文', 'mrorigin': '醫案出處', 'mrdoctor': '醫案醫者', 'mrname': '醫案命名', 'mrposter': '醫案提交者', 'mrlasttime': '最後編輯時間', 'mreditnumber': '編輯次數', 'mrreadnumber': '閱讀次數', 'mrpriority': '重要性', 'dntag': '相關病態', 'mntag': '相關本草', 'pntag': '相關方劑', 'sntag': '相關典籍', 'fntag': '相關人物', 'diantag': '相關辨證' // 新增辨證字段 }, inputTimeout: null, dnNames: [], mnNames: [], pnNames: [], snNames: [], fnNames: [], dianNames: [], // 辨證名称列表 stateVersion: '1.0', showRelative: false, showMNRelative: false, showPNRelative: false, showSNRelative: false, showFNRelative: false, showDianNRelative: false, // 控制辨證关联器显示 currentCase: null }; }, computed: { filteredData() { const query = this.searchQuery.trim(); if (query && /^\d+$/.test(query)) { const idToSearch = parseInt(query, 10); return this.mergedData.filter(item => item.id === idToSearch); } if (!query) return this.mergedData; const lowerQuery = query.toLowerCase(); return this.mergedData.filter(item => { return Object.values(item).some(value => { if (value === null || value === undefined) return false; if (Array.isArray(value)) { return value.some(subValue => { if (typeof subValue === 'object' && subValue !== null) { return JSON.stringify(subValue).toLowerCase().includes(lowerQuery); } return String(subValue).toLowerCase().includes(lowerQuery); }); } if (typeof value === 'object' && value !== null) { return JSON.stringify(value).toLowerCase().includes(lowerQuery); } return String(value).toLowerCase().includes(lowerQuery); }); }); }, sortedData() { if (!this.sortKey) return this.filteredData; const order = this.sortOrders[this.sortKey] || 1; return [...this.filteredData].sort((a, b) => { const getValue = (obj) => { const val = obj[this.sortKey]; if (Array.isArray(val)) return JSON.stringify(val); return val; }; const aValue = getValue(a); const bValue = getValue(b); if (aValue === bValue) return 0; return aValue > bValue ? order : -order; }); }, paginatedData() { const start = (this.currentPage - 1) * Number(this.pageSize); const end = start + Number(this.pageSize); const data = this.sortedData.slice(start, end); if (data.length > 0) { this.currentCase = data[0]; } else { this.currentCase = null; } return data; }, totalPages() { return Math.ceil(this.filteredData.length / this.pageSize) || 1; } }, watch: { pageSize() { this.currentPage = 1; this.inputPage = 1; this.saveState(); }, currentPage(newVal) { this.inputPage = newVal; this.saveState(); }, filteredData() { if (this.currentPage > this.totalPages) { this.currentPage = Math.max(1, this.totalPages); } this.inputPage = this.currentPage; }, searchQuery() { this.saveState(); } }, methods: { handleDataUpdated() { alert('數據已更新,正在刷新醫案數據...'); this.fetchData(); }, toggleMNRelative() { if (!this.showMNRelative) { this.showRelative = false; this.showPNRelative = false; this.showSNRelative = false; this.showFNRelative = false; this.showDianNRelative = false; } this.showMNRelative = !this.showMNRelative; }, togglePNRelative() { if (!this.showPNRelative) { this.showRelative = false; this.showMNRelative = false; this.showSNRelative = false; this.showFNRelative = false; this.showDianNRelative = false; } this.showPNRelative = !this.showPNRelative; }, toggleSNRelative() { if (!this.showSNRelative) { this.showRelative = false; this.showMNRelative = false; this.showPNRelative = false; this.showFNRelative = false; this.showDianNRelative = false; } this.showSNRelative = !this.showSNRelative; }, toggleRelative() { if (this.showRelative) { this.showRelative = false; } else { this.showMNRelative = false; this.showPNRelative = false; this.showSNRelative = false; this.showFNRelative = false; this.showDianNRelative = false; this.showRelative = true; } }, toggleFNRelative() { if (!this.showFNRelative) { this.showRelative = false; this.showMNRelative = false; this.showPNRelative = false; this.showSNRelative = false; this.showDianNRelative = false; } this.showFNRelative = !this.showFNRelative; }, // 辨證关联器切换方法 toggleDianNRelative() { if (!this.showDianNRelative) { this.showRelative = false; this.showMNRelative = false; this.showPNRelative = false; this.showSNRelative = false; this.showFNRelative = false; } this.showDianNRelative = !this.showDianNRelative; }, // 辨證名称HTML格式化方法 (使用红色) formatDiantagValueHTML(diantagArray) { return diantagArray.map(tagObj => { const name = tagObj.dianname || tagObj.name || '未命名標籤'; return `<span style="color: rgb(255, 0, 0); font-weight: bold;">${this.escapeHtml(name)}</span>`; }).join(';'); }, escapeHtml(text) { const map = { '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }; return text.replace(/[&<>"']/g, m => map[m]); }, saveState() { const state = { version: this.stateVersion, currentPage: this.currentPage, pageSize: this.pageSize, searchQuery: this.searchQuery, timestamp: new Date().getTime() }; sessionStorage.setItem('mrviewerState', JSON.stringify(state)); }, restoreState() { const savedState = sessionStorage.getItem('mrviewerState'); if (!savedState) return; try { const state = JSON.parse(savedState); if (state.version !== this.stateVersion) return; this.currentPage = state.currentPage || 1; this.pageSize = state.pageSize || 1; this.searchQuery = state.searchQuery || ''; this.inputPage = this.currentPage; } catch (e) { sessionStorage.removeItem('mrviewerState'); } }, async fetchData() { try { // 获取原有数据 const api1Response = await fetch("MRInfo/?format=json"); this.api1Data = await api1Response.json(); const api2Response = await fetch("DNTag/?format=json"); this.api2Data = await api2Response.json(); const api3Response = await fetch("MNTag/?format=json"); this.api3Data = await api3Response.json(); const api4Response = await fetch("SNTag/?format=json"); this.api4Data = await api4Response.json(); const api5Response = await fetch("PNTag/?format=json"); this.api5Data = await api5Response.json(); const api6Response = await fetch("FNTag/?format=json"); this.api6Data = await api6Response.json(); // 辨證数据获取 const api7Response = await fetch("DiaNTag/?format=json"); this.api7Data = await api7Response.json(); // 本草名称列表 this.mnNames = this.api3Data.map(item => item.mnname).filter(name => name && name.trim()); this.mnNames.sort((a, b) => b.length - a.length); // 方剂名称列表 this.pnNames = this.api5Data.map(item => item.pnname).filter(name => name && name.trim()); this.pnNames.sort((a, b) => b.length - a.length); // 病态名称列表 this.dnNames = this.api2Data.map(item => item.dnname).filter(name => name && name.trim()); this.dnNames.sort((a, b) => b.length - a.length); // 出处名称列表 this.snNames = this.api4Data.map(item => item.snname).filter(name => name && name.trim()); this.snNames.sort((a, b) => b.length - a.length); // 人物名称列表 this.fnNames = this.api6Data.map(item => item.fnname).filter(name => name && name.trim()); this.fnNames.sort((a, b) => b.length - a.length); // 辨證名称列表 this.dianNames = this.api7Data.map(item => item.dianname).filter(name => name && name.trim()); this.dianNames.sort((a, b) => b.length - a.length); this.mergeData(); this.currentPage = 1; this.inputPage = 1; this.saveState(); } catch (error) { console.error("獲取數據失敗:", error); alert("數據加載失敗,請稍後重試"); } }, mergeData() { this.mergedData = this.api1Data.map((item) => { const newItem = { ...item }; // 处理病态标签 if (newItem.dntag && Array.isArray(newItem.dntag)) { newItem.dntag = newItem.dntag.map((tagId) => { const matchedItem = this.api2Data.find(api2Item => api2Item.id === tagId); return matchedItem || { id: tagId, dnname: "未找到匹配的數據" }; }); } // 处理本草标签 if (newItem.mntag && Array.isArray(newItem.mntag)) { newItem.mntag = newItem.mntag.map((tagId) => { const matchedItem = this.api3Data.find(api3Item => api3Item.id === tagId); return matchedItem || { id: tagId, mnname: "未找到匹配的數據" }; }); } // 处理方剂标签 if (newItem.pntag && Array.isArray(newItem.pntag)) { newItem.pntag = newItem.pntag.map((tagId) => { const matchedItem = this.api5Data.find(api5Item => api5Item.id === tagId); return matchedItem || { id: tagId, pnname: "未找到匹配的數據" }; }); } // 处理出处标签 if (newItem.sntag && Array.isArray(newItem.sntag)) { newItem.sntag = newItem.sntag.map((tagId) => { const matchedItem = this.api4Data.find(api4Item => api4Item.id === tagId); return matchedItem || { id: tagId, snname: "未找到匹配的數據" }; }); } // 处理人物标签 if (newItem.fntag && Array.isArray(newItem.fntag)) { newItem.fntag = newItem.fntag.map((tagId) => { const matchedItem = this.api6Data.find(api6Item => api6Item.id === tagId); return matchedItem || { id: tagId, fnname: "未找到匹配的數據" }; }); } // 处理辨證标签 if (newItem.diantag && Array.isArray(newItem.diantag)) { newItem.diantag = newItem.diantag.map((tagId) => { const matchedItem = this.api7Data.find(api7Item => api7Item.id === tagId); return matchedItem || { id: tagId, dianname: "未找到匹配的數據" }; }); } return newItem; }); // 初始化排序顺序 this.sortOrders = {}; if (this.mergedData.length > 0) { Object.keys(this.mergedData[0]).forEach(key => { this.sortOrders[key] = 1; }); } }, processFieldNames(item) { const result = {}; for (const key in item) { const newKey = this.fieldNames[key] || key; result[newKey] = item[key]; } return result; }, formatValue(value, fieldName) { if (value === null || value === undefined) return ''; // 醫案全文的高亮 if (fieldName === '醫案全文' && typeof value === 'string') { let highlighted = this.highlightMatches(value, this.dnNames, 'rgb(212, 107, 8)'); highlighted = this.highlightMatches(highlighted, this.mnNames, 'rgb(0, 128, 0)'); highlighted = this.highlightMatches(highlighted, this.pnNames, 'rgb(128, 0, 128)'); highlighted = this.highlightMatches(highlighted, this.snNames, 'rgb(51, 102, 255)'); highlighted = this.highlightMatches(highlighted, this.fnNames, '#8B4513'); highlighted = this.highlightMatches(highlighted, this.dianNames, 'rgb(255, 0, 0)'); // 辨證高亮 return highlighted; } // 醫案出處字段 else if (fieldName === '醫案出處' && typeof value === 'string') { return this.highlightMatches(value, this.snNames, 'rgb(51, 102, 255)'); } // 醫案醫者字段 else if (fieldName === '醫案醫者' && typeof value === 'string') { return this.highlightMatches(value, this.fnNames, '#8B4513'); } if (typeof value === 'string' && value.startsWith('http')) { return `<a href="${value}" target="_blank">${value}</a>`; } return value; }, highlightMatches(text, words, color) { if (!text || typeof text !== 'string' || words.length === 0) { return text; } const pattern = new RegExp( words .map(name => name.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')) .join('|'), 'gi' ); return text.replace(pattern, match => `<span style="color: ${color}; font-weight: bold;">${this.escapeHtml(match)}</span>` ); }, prevPage() { if (this.currentPage > 1) { this.currentPage--; this.saveState(); } }, nextPage() { if (this.currentPage < this.totalPages) { this.currentPage++; this.saveState(); } }, handlePageInput() { clearTimeout(this.inputTimeout); this.inputTimeout = setTimeout(() => { this.goToPage(); this.saveState(); }, 300); }, goToPage() { if (this.inputPage === null || this.inputPage === undefined || this.inputPage === '') { this.inputPage = this.currentPage; return; } const page = parseInt(this.inputPage); if (isNaN(page)) { this.inputPage = this.currentPage; return; } if (page < 1) { this.currentPage = 1; } else if (page > this.totalPages) { this.currentPage = this.totalPages; } else { this.currentPage = page; } this.inputPage = this.currentPage; } }, mounted() { this.restoreState(); this.fetchData(); }, activated() { this.restoreState(); }, deactivated() { this.saveState(); } }; </script> <style scoped> .container { max-width: 1200px; margin: 0px; padding: 0px; } .control-panel { margin-bottom: 0px; display: flex; flex-wrap: wrap; gap: 10px; justify-content: flex-end; align-items: center; position: fixed; bottom: 0; left: 0; width: 100%; background-color: #ffd800ff; z-index: 999; padding: 10px 20px; box-sizing: border-box; } .content-area { position: fixed; top: 56px; bottom: 45px; left: 0; width: 70%; background: white; padding: 1px; z-index: 100; overflow-y: auto; } .relative-area { position: fixed; top: 56px; bottom: 45px; right: 0; width: 30%; background: lightblue; padding: 1px; z-index: 100; overflow-y: auto; } .refresh-btn, .relative-btn { padding: 4px; background-color: #4CAF50; color: white; border: none; border-radius: 4px; cursor: pointer; } .refresh-btn:hover, .relative-btn:hover { background-color: #45a049; } .search-input { padding: 8px; border: 1px solid #ddd; border-radius: 4px; flex-grow: 1; max-width: 300px; } .pagination-controls { display: flex; align-items: center; gap: 5px; } .page-size-select { padding: 4px; border-radius: 4px; width: 70px; } .page-input { width: 50px; padding: 4px; border: 1px solid #ddd; border-radius: 4px; text-align: center; } .horizontal-records { display: flex; flex-direction: column; gap: 20px; } .record-card { border: 1px solid #ddd; border-radius: 4px; overflow: hidden; box-shadow: 0 2px 4px rgba(0,0,0,0.1); } .record-header { padding: 12px 16px; background-color: #f5f5f5; border-bottom: 1px solid #ddd; } .record-header h3 { margin: 0; font-size: 1.1em; } .record-body { padding: 16px; } .record-field { display: flex; margin-bottom: 12px; line-height: 1.5; } .record-field:last-child { margin-bottom: 0; } .field-name { font-weight: bold; min-width: 120px; color: #555; } .field-value { flex-grow: 1; display: flex; flex-wrap: wrap; gap: 8px; } .dntag-value { display: flex; flex-wrap: wrap; gap: 8px; } .mntag-value { display: flex; flex-wrap: wrap; gap: 8px; color: #006400; font-weight: 500; } .pntag-value { display: flex; flex-wrap: wrap; gap: 8px; color: #800080; font-weight: 500; } .sntag-value { display: flex; flex-wrap: wrap; gap: 8px; color: #0094ff; font-weight: 500; } .fntag-value { display: flex; flex-wrap: wrap; gap: 8px; color: #8B4513; font-weight: 500; } /* 辨證名称样式 */ .diantag-value { display: flex; flex-wrap: wrap; gap: 8px; color: rgb(255, 0, 0); font-weight: 500; } .array-value { display: flex; flex-wrap: wrap; gap: 8px; } .no-data { padding: 20px; text-align: center; color: #666; font-style: italic; } button:disabled { opacity: 0.5; cursor: not-allowed; } </style>
08-02
<template> <view class="container"> <!-- 顶部固定区域 --> <view class="header-section"> <view class="banner-section"> <!-- 修复:使用英文双引号 --> <image class="banner-image" :src="bannerData.imageUrl" /> </view> <view class="title">{{ bannerData.title }}</view> </view> <!-- 分隔线 --> <view class="section-divider"></view> <!-- 内容包装器 --> <view class="content-wrapper"> <!-- 可滚动区域 --> <view class="scroll-container"> <scroll-view scroll-y="true" :enhanced="true" :show-scrollbar="false" class="scroll-view" > <view v-for="item in newsList" :key="item.id" class="news-item" @click="navigateToDetail(item)" > <view class="news-content"> <text class="news-title">{{ item.title }}</text> <text class="news-summary">{{ item.summary }}</text> <text class="news-date">{{ item.publishDate }}</text> </view> <view class="status-box" :class="item.read ? 'read' : 'unread'" > {{ item.read ? '已阅' : '未阅' }} </view> </view> <!-- 加载状态提示 --> <!-- 修复:使用统一的 loading 变量 --> <view v-if="listLoading" class="loading-text">加载中...</view> <view v-if="!listLoading && newsList.length === 0" class="no-data">暂无数据</view> </scroll-view> </view> </view> <!-- 分页组件 --> <view class="pagination"> <!-- 每页条数选择器 --> <view class="page-size-selector"> <picker :value="pageSizeIndex" :range="pageSizeOptions" range-key="label" @change="changePageSize" > <view class="selector-box"> <text class="selector-text">{{ pageSize }}条/页</text> <text class="selector-icon">▼</text> </view> </picker> </view> <!-- 分页控制 --> <view class="page-controls"> <button class="page-btn prev-btn" :disabled="currentPage === 1" @click="goToPage(currentPage - 1)" > < </button> <view class="page-info"> <input type="number" v-model="currentPage" class="page-input" :min="1" :max="totalPages" @blur="validatePage" /> <text class="page-total">/ {{ totalPages }}</text> </view> <button class="page-btn next-btn" :disabled="currentPage >= totalPages" @click="goToPage(currentPage + 1)" > > </button> </view> <!-- 跳转按钮 --> <button class="go-btn" @click="validatePage">跳转</button> </view> </view> </template> <script setup> import { ref, onMounted, computed, watch } from 'vue'; // 顶部横幅数据 const bannerData = ref({ title: '', imageUrl: '' }); // 新闻列表数据 const newsList = ref([]); // 修复:使用统一的加载状态变量 const listLoading = ref(false); // 分页相关数据 const currentPage = ref(1); const pageSize = ref(10); const total = ref(0); // 分页选项配置 const pageSizeOptions = ref([ { value: 5, label: '5条/页' }, { value: 10, label: '10条/页' }, { value: 15, label: '15条/页' }, { value: 20, label: '20条/页' } ]); // 计算属性 const pageSizeIndex = computed(() => pageSizeOptions.value.findIndex(opt => opt.value === pageSize.value) ); const totalPages = computed(() => { return Math.ceil(total.value / pageSize.value) || 1; }); // 监听页码变化 watch([currentPage, pageSize], () => { fetchData(); }); // 获取顶部横幅数据 const fetchBanners = () => { listLoading.value = true; uni.request({ url: '/api/incorruptFront/culture/index', method: 'POST', success: (res) => { if (res.statusCode === 200 && res.data.code === 200) { bannerData.value = { title: res.data.data.title, imageUrl: res.data.data.imageUrl }; } else { uni.showToast({ title: res.data?.msg || '请求失败', icon: 'none' }); } }, fail: (err) => { uni.showToast({ title: '网络错误', icon: 'error' }); console.error('请求失败:', err); }, complete: () => { listLoading.value = false; } }); }; // 获取廉洁文化资讯列表 const fetchData = () => { listLoading.value = true; uni.request({ url: '/api/incorruptFront/frontArticle/list', method: 'GET', data: { pageNum: currentPage.value, pageSize: pageSize.value }, success: (res) => { if (res.statusCode === 200 && res.data.code === 200) { newsList.value = res.data.rows.map(item => ({ id: item.articleId, title: item.title, summary: item.articleDescribe, publishDate: item.publishDate, read: Math.random() > 0.5 // 模拟阅读状态 })); total.value = res.data.total; } else { uni.showToast({ title: res.data?.msg || '获取数据失败', icon: 'none' }); } }, fail: (err) => { uni.showToast({ title: '网络错误', icon: 'error' }); console.error('请求失败:', err); }, complete: () => { listLoading.value = false; } }); }; // 改变每页条数 const changePageSize = (e) => { const index = e.detail.value; pageSize.value = pageSizeOptions.value[index].value; currentPage.value = 1; }; // 跳转到指定页码 const goToPage = (page) => { if (page < 1 || page > totalPages.value) return; currentPage.value = page; }; // 验证页码 const validatePage = () => { if (currentPage.value < 1) currentPage.value = 1; if (currentPage.value > totalPages.value) currentPage.value = totalPages.value; }; // 跳转详情页 const navigateToDetail = (item) => { uni.navigateTo({ url: `/pages/IntegrityCulture/IntegrityCultureDetail/IntegrityCultureDetail?articleId=${item.id}` }); }; onMounted(() => { fetchBanners(); fetchData(); }); </script> <style scoped> /* 整体容器 - 禁止滚动 */ .container { padding: 30rpx; background-color: #f9f9f9; height: 100vh; overflow: hidden; box-sizing: border-box; display: flex; flex-direction: column; } /* 顶部固定区域 */ .header-section { flex-shrink: 0; margin-bottom: 20rpx; } .banner-section { border-radius: 16rpx; overflow: hidden; box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.1); } .banner-image { width: 100%; height: 320rpx; display: block; object-fit: cover; } .title { font-size: 36rpx; font-weight: bold; text-align: center; margin: 20rpx 0; color: #2c3e50; position: relative; padding-top: 20rpx; } .title::before { content: ''; position: absolute; top: 0; left: 50%; transform: translateX(-50%); width: 60rpx; height: 6rpx; background: linear-gradient(to right, #4caf50, #2196f3, #4caf50); border-radius: 3rpx; } /* 分隔线 */ .section-divider { height: 1rpx; background: linear-gradient(to right, #4caf50, #2196f3, #4caf50); margin: 10rpx 0 20rpx; opacity: 0.2; } /* 内容包装器 */ .content-wrapper { flex: 1; display: flex; flex-direction: column; min-height: 0; } /* 滚动区域容器 */ .scroll-container { flex: 1; min-height: 0; display: flex; flex-direction: column; background-color: #fff; border-radius: 16rpx; overflow: hidden; box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05); } /* 滚动视图 */ .scroll-view { flex: 1; height: 100%; } /* 隐藏滚动条 */ .scroll-view ::-webkit-scrollbar { display: none; width: 0; height: 0; color: transparent; } /* 新闻项样式 */ .news-item { padding: 30rpx; display: flex; justify-content: space-between; align-items: flex-start; border-bottom: 1rpx solid #eee; transition: background-color 0.2s; position: relative; } .news-item:active { background-color: #f5f7fa; } .news-content { flex: 1; padding-right: 20rpx; } .news-title { font-size: 32rpx; font-weight: bold; color: #333; display: block; margin-bottom: 10rpx; } .news-summary { font-size: 28rpx; color: #666; display: block; margin-bottom: 10rpx; line-height: 1.5; } .news-date { font-size: 24rpx; color: #999; display: block; } .status-box { padding: 8rpx 16rpx; font-size: 24rpx; border-radius: 8rpx; min-width: 80rpx; text-align: center; flex-shrink: 0; align-self: flex-start; } .status-box.read { background-color: rgba(76, 175, 80, 0.1); color: #4caf50; } .status-box.unread { background-color: rgba(244, 67, 54, 0.1); color: #f44336; } /* 加载状态 */ .loading-text, .no-data { text-align: center; padding: 30rpx; font-size: 28rpx; color: #999; } /* 分页样式 */ .pagination { display: flex; align-items: center; justify-content: space-between; padding: 12rpx 20rpx; background-color: #fff; border-radius: 16rpx; height: 80rpx; box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05); margin-top: 20rpx; flex-shrink: 0; } /* 每页选择器样式 */ .page-size-selector { flex: 0 0 auto; } .selector-box { display: flex; align-items: center; padding: 0 20rpx; height: 56rpx; background-color: #f5f7fa; border-radius: 40rpx; font-size: 24rpx; } .selector-text { color: #333; margin-right: 8rpx; } .selector-icon { font-size: 20rpx; color: #666; } /* 分页控制区域 */ .page-controls { display: flex; align-items: center; margin: 0 15rpx; flex: 1; justify-content: center; } /* 页码按钮样式 */ .page-btn { display: flex; align-items: center; justify-content: center; width: 60rpx; height: 60rpx; padding: 0; margin: 0 5rpx; background-color: #f5f7fa; border-radius: 50%; font-size: 32rpx; line-height: 1; } .prev-btn, .next-btn { background-color: #4caf50; color: white; } .page-btn:disabled { background-color: #f0f0f0; color: #cccccc; } /* 页码信息样式 */ .page-info { display: flex; align-items: center; margin: 0 15rpx; } .page-input { width: 80rpx; height: 50rpx; border: 1rpx solid #ddd; border-radius: 8rpx; padding: 0 10rpx; text-align: center; font-size: 28rpx; background-color: #fff; } .page-total { font-size: 24rpx; color: #666; margin-left: 5rpx; } /* 跳转按钮 */ .go-btn { padding: 0 20rpx; height: 56rpx; background-color: #2196f3; color: white; border-radius: 40rpx; font-size: 24rpx; line-height: 56rpx; } /* 响应式调整 */ @media (max-height: 700px) { .banner-image { height: 240rpx; } .title { font-size: 32rpx; margin: 15rpx 0; } .news-item { padding: 20rpx; } .pagination { height: 70rpx; } } @media (max-width: 480px) { .container { padding: 20rpx; } .pagination { padding: 10rpx; } .selector-text { font-size: 22rpx; } .page-input { width: 70rpx; font-size: 24rpx; } .go-btn { padding: 0 15rpx; font-size: 22rpx; } .news-title { font-size: 30rpx; } .news-summary { font-size: 26rpx; } } </style> 帮我去掉列表板块里的已阅,未阅
最新发布
08-23
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值